liminix/pkgs/uevent-watch/watch.fnl

71 lines
2.1 KiB
Fennel

(local { : assoc : system : dirname } (require :anoia))
(local { : mktree : rmtree : symlink } (require :anoia.fs))
(fn parse-match [s] (string.match s "(.-)=(.+)"))
(fn parse-args [args]
(match args
["-s" service & rest] (assoc (parse-args rest) :service service)
["-n" path & rest] (assoc (parse-args rest) :linkname path)
matches { :matches (collect [_ m (ipairs matches)] (parse-match m)) }
_ nil))
(fn %% [fmt ...] (string.format fmt ...))
(fn event-matches? [params e]
(and
e
(accumulate [match? true
name value (pairs params.matches)]
(and match? (= value (. e name))))))
(var up :unknown)
(fn start-service [devname linkname service]
(match (symlink (.. "/dev/" devname ) linkname)
ok (pcall system (%% "s6-rc -b -u change %q" service))
(nil err) false))
(fn stop-service [linkname service]
(match (pcall system (%% "s6-rc -b -d change %q" linkname service))
ok (os.remove linkname)
(nil err) false))
(fn toggle-service [devname linkname service wanted?]
(when (not (= up wanted?))
(set up
(if wanted?
(start-service devname linkname service)
(not (stop-service linkname service))))))
(fn parse-uevent [s]
(when s
(let [(nl nxt) (string.find s "\0" 1 true)]
(collect [k v (string.gmatch
(string.sub s (+ 1 nxt))
"(%g-)=(%g+)")]
(k:lower) v))))
(fn run-with-fh [fh args]
(set up :unknown)
(let [parameters
(assert (parse-args args) (.. "can't parse args: " (table.concat args " ")))]
(mktree (dirname parameters.linkname))
(var finished? false)
(while (not finished?)
(let [e (parse-uevent (fh:read 5000))]
(when (event-matches? parameters e)
(let [wanted? (. {:add true :change true} e.action)]
(toggle-service e.devname parameters.linkname parameters.service wanted?)))
(set finished? (= e nil))
))))
(fn run [args]
(let [nellie (require :nellie)
netlink (nellie.open 4)]
(run-with-fh netlink arg)))
{ : run : run-with-fh : event-matches? }