#!/bin/execlineb # # This is the turnstile s6-rc backend. It accepts the action as its first # argument, which is either "ready", "run", or "stop". The backend can be # written in any language, in this case the shebang is used to run it. # # It also serves as an example of how to implement such backend in a non # shell language. # # Arguments for "ready": # # live: the path to s6-rc's live dir; it is the string that is # written by dinit into ready_fd for the "run" part of the process # # Arguments for "run": # # ready_p: path to named pipe (fifo) that should be poked with a string; this # will be passed to the "ready" script of the sequence as its sole # argument (here this is the path to s6-rc's live state directory) # srvdir: an internal directory that can be used by the service manager # for any purpose (usually to keep track of its state) # confdir: the path where turnstile's configuration data reside, used # to source the configuration file # # Arguments for "stop": # # pid: the PID of the service manager to stop (gracefully); it should # terminate the services it's running and then stop itself # # How the script manages its configuration and so on is up to the script. # # Note that the script *must* exec the service manager directly, i.e. the # service manager must fully replace the shell process for this to work. # # Copyright 2024 Carlos Eduardo # License: BSD-2-Clause # importas -i directive 1 shift -n 1 case $directive { run { # source additional arguments. # two subsitution steps are needed because https://skarnet.org/lists/skaware/2049.html multisubstitute { importas -i __confdir 3 importas -i __home HOME } envfile -I -- ${__confdir}/s6-rc.conf # despite the above warning, we do want serial substitution on these, so we import it here, before the bigger multisubstitute. multisubstitute { importas -uD "${HOME}/.local/share/s6/compiled" compiled compileddir importas -uD "${statedir}/s6-rc" live livestatedir importas -uD "${statedir}/env" env envdir } multisubstitute { importas -i readyfifo 1 importas -i statedir 2 importas -i confdir 3 # not used directly, but might be useful for the config file importas -Si HOME importas -Si USER importas -Si XDG_RUNTIME_DIR importas -Si SHELL importas -Si LOGNAME } # Initialize state directory. # confdir/s6 should have the definition for a s6-svscan-log # service that acts as the catch-all loger. See: # /run/service/s6-svscan-log # on a s6-linux-init powered machine for an example. # It should also contain a .s6-svscan/SIGINT file with # foreground { s6-rc -bDa } s6-svscanctl -t . if { cp -a -- ${confdir}/s6 ${statedir}/service } pipeline -dw -- { if { forstdin -x0 _ exit 0 } if -nt { # Create envdir. if { mkdir -p -- ${env} } # Init service management layer. if { s6-rc-init -c $compiled -l $live -- ${statedir}/service } # Wait for logger to come up. redirfd -w 2 ${statedir}/service/s6-svscan-log/fifo # Print string for the ready step. redirfd -w 1 ${readyfifo} printf %s $live } # tell s6-svscan to give up if anything goes awry. s6-svscanctl -t -- ${statedir}/service } # turn pipeline output into notification-fd. fdmove -c 3 1 # backup stderr for catch-all logger fdmove -c 4 2 # fifo trick redirfd -wnb 2 ${statedir}/service/s6-svscan-log/fifo fdmove -c 1 2 # avoid leaking script arguments emptyenv -P # export extra info for helper scripts export SVDIR ${statedir}/service export TURNSTILE_S6RC_LIVESTATE_DIR ${live} s6-svscan -d 3 -X 4 -- ${statedir}/service } ready { importas -i string 1 s6-rc -l $string -up change default } stop { importas -i ! 1 # Using INT instead of TERM so the s6-rc -bDa change hook runs kill -s INT $! } } exit 32