1 # Apply timing control to this host
2 # This is run as a cron job to either "close" or "open" the blocking of
3 # the host via a configured control implementation.
5 # File control.dat defines the limits, and control mechanism.
6 # File activity-$date.dat is the local activity.
9 (write-line 2 (join (map string args)))
14 'ACTDIR SITE:listener.activity.dir
15 'CONTROL.DAT SITE:control.dat
16 'EXTRA.DAT SITE:control.extra.dat
17 'USAGE.DAT SITE:control.usage.dat
18 'USAGE.TMP SITE:control.usage.tmp
19 'ACTION SITE:control.action
22 # Set current time variables in local timezone
23 (map set '(YEAR MONTH DATE HOUR MINUTE SECOND DOY DOW)
24 (date-list (+ NOW (* 60 (now 0 -2)))))
25 ;(println (list YEAR MONTH DATE HOUR MINUTE SECOND DOY DOW))
28 DAY (list YEAR MONTH DATE)
31 GAP SITE:control.activity.gap
32 CLIP SITE:control.activity.clip
36 # (( weekday start limit stop ) ... )
37 (setf CONTROL (read-expr (or (read-file CONTROL.DAT)
38 (die "** Missing " CONTROL.DAT " ** Exiting."))
41 (write-line 2 (string (list CONTROL DOW)))
43 (map set '(dow MODE START LIMIT END)
44 (or (assoc DOW CONTROL)
45 (assoc 'policy CONTROL)
46 (list DOW (6 30) 120 (20 0)))
49 # Load the configured control mechanism
50 (if (file? ACTION) (load ACTION)
51 (die "** Unknown control mechanism. Exiting!!"))
53 (die "** Control function (control cmd reason) not defined. Exiting!!"))
55 ;; Apply control command with reason, then exit
56 (define (do-control x r) (control x r) (exit 0))
58 ;; Utility: Combine an (hour minutes) pair into total minutes
59 (define (minutes x) (+ (* (x 0) 60) (x 1)))
61 ;; Utility: Combine hours and minutes into total seconds
62 (define (seconds H M) (+ (* 3600 H) (* 60 M)))
64 # Apply EXTRA.DAT. This is a pair of hours and minutes to force open,
65 # relative to the modification time of the file.
67 (when (regex "([0-9]+) ([0-9]+)" (or (read-file EXTRA.DAT) "") 0)
68 (<= NOW (+ (file-info EXTRA.DAT 6) (seconds (int $1) (int $2))))))
70 ;;==== Utilities for activity data
71 # Activity is lines of timestamps. Collect TOTAL as list of unique
72 # time values (H M) within the start-end time span.
74 (define (log-name-fmt t)
75 (format "%d%02d%02d-.*\\.dat" (0 3 (date-list t))))
78 (find-all "([0-9]+( \\S+)?).*" (read-file (format "%s/%s" ACTDIR f)) $1 0))
80 # Collect all timestamps of the UTC date of the given time stamp
82 (flat (map log-lines (directory ACTDIR (log-name-fmt t)))))
84 # Translate timestamp into its local time (hour minute), if it's
85 # within the applicable day, null otherwise.
86 (define (period-minute x)
88 (letn ((d (date-list (+ (int x 0 10) (* 60 (now 0 -2)))))
90 (on (if (regex "^[0-9]+ ([0-9]+)$" x 0) (> (int $1 0 10) CLIP) 1))
92 (and on (= (0 3 d) DAY) tm)))) ; (>= tm START) (< tm END) tm))))
95 # Collect all mentioned minutes from the activity logs
100 (sort (extend (logs (- NOW 86400)) (logs NOW)))))))
102 # Add all mentioned minutes, and fill in any time periods of less than
103 # the configured GAP minutes between them.
106 (setf LAST (minutes (pop TOTAL) SUM 1))
108 (letn ((M (minutes x)) (V (- M LAST)))
109 (inc SUM (if (< V GAP) V 1))
113 # Rework SUM into (h m) format
114 (setf SUM (letn ((h (/ SUM 60)) (m (- SUM (* 60 h)))) (list h m)))
116 # Write out current usage with atomic update (jic)
117 (write-file USAGE.TMP (string SUM))
118 (rename-file USAGE.TMP USAGE.DAT)
120 # Apply current policy setting
121 ; ** Note that do-control exits
122 (when OVERRIDE (do-control "open" "override"))
124 (closed (do-control "close" "closed"))
125 (opened (do-control "open" "open"))
126 (timed ;; Close host outside start-end times
127 (when (< HM START) (do-control "close" "early"))
128 (when (>= HM END) (do-control "close" "late"))
129 (when (> SUM LIMIT) (do-control "close" "usage"))
130 (do-control "open" "usage")
132 (true (die "Unknown control mode " MODE))