#!/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.
#
# 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