78 lines
2.4 KiB
Fennel
78 lines
2.4 KiB
Fennel
(local { : assoc : system : dirname } (require :anoia))
|
|
(local { : mktree : rmtree : symlink } (require :anoia.fs))
|
|
(local { : AF_LOCAL : SOCK_STREAM } (require :anoia.net.constants))
|
|
(local ll (require :lualinux))
|
|
|
|
(local { : view } (require :fennel))
|
|
|
|
(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 (table.concat matches " ") }
|
|
_ nil))
|
|
|
|
(fn %% [fmt ...] (string.format fmt ...))
|
|
|
|
(var up :unknown)
|
|
|
|
(fn start-service [devname linkname service]
|
|
(match (if linkname (symlink (.. "/dev/" devname) linkname) true)
|
|
ok (pcall system (%% "s6-rc-up-tree %q" service))
|
|
(nil err) false))
|
|
|
|
(fn stop-service [linkname service]
|
|
(match (pcall system (%% "s6-rc -b -d change %q" service))
|
|
ok (if linkname (os.remove linkname) true)
|
|
(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 " ")))]
|
|
(when parameters.linkname (mktree (dirname parameters.linkname)))
|
|
(var finished? false)
|
|
|
|
(print "registering for events" (fh:write parameters.matches))
|
|
|
|
(while (not finished?)
|
|
(let [e (parse-uevent (fh:read))]
|
|
(when e
|
|
(let [wanted? (. {:add true :change true} e.action)]
|
|
(toggle-service e.devname parameters.linkname parameters.service wanted?)))
|
|
(set finished? (= e nil))
|
|
))))
|
|
|
|
(fn unix-connect [pathname]
|
|
(let [addr (string.pack "=Hz" AF_LOCAL pathname)]
|
|
(match (ll.socket AF_LOCAL SOCK_STREAM 0)
|
|
sock (doto sock (ll.connect addr))
|
|
(nil err) (error err))))
|
|
|
|
|
|
(fn run [args]
|
|
(let [fd (assert (unix-connect "/run/devout.sock"))
|
|
devout {
|
|
:read #(ll.read fd)
|
|
:write #(ll.write fd $2)
|
|
:close #(ll.close fd)
|
|
}]
|
|
(run-with-fh devout arg)))
|
|
|
|
{ : run : run-with-fh }
|