aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-11-04 21:55:42 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2025-11-04 21:55:42 +0000
commit1667855c0c05f26b378ed8a011336770485321e5 (patch)
treee2b040143458aef7d3c4b4e64f9cda98ff543e64
parent2b61e7fa65bdae911e33fa415c4925fb2aabfeb1 (diff)
downloads6-1667855c0c05f26b378ed8a011336770485321e5.tar.gz
Move daemontools/runit wrapper support here
-rw-r--r--.gitignore3
-rwxr-xr-xconfigure39
-rw-r--r--package/configure-snippets/configure_case_lines6
-rw-r--r--package/configure-snippets/configure_generate_configh11
-rw-r--r--package/configure-snippets/configure_generate_make16
-rw-r--r--package/configure-snippets/configure_help_options3
-rw-r--r--package/configure-snippets/configure_init_vars3
-rw-r--r--package/deps.mak9
-rw-r--r--package/modes3
-rw-r--r--package/targets.mak88
-rw-r--r--src/alias/deps-exe/s6-alias1
-rw-r--r--src/alias/deps-exe/s6-alias-chpst3
-rw-r--r--src/alias/deps-exe/s6-alias-sv3
-rw-r--r--src/alias/s6-alias-chpst.c357
-rw-r--r--src/alias/s6-alias-sv.c448
-rw-r--r--src/alias/s6-alias.c227
16 files changed, 1220 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 4a9ae96..0a6a9c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,9 @@
/config.mak
/src/include/s6/config.h
/ucspilogd
+/s6-alias
+/s6-alias-chpst
+/s6-alias-sv
/s6-ftrigrd
/s6-ftrig-listen1
/s6-ftrig-listen
diff --git a/configure b/configure
index 31f1a55..db892dd 100755
--- a/configure
+++ b/configure
@@ -50,6 +50,9 @@ Optional features:
--enable-absolute-paths hardcode absolute BINDIR/foobar paths in binaries [disabled]
--enable-nsss use the nsss library for user information [disabled]
--disable-execline don't use the execline library [enabled]
+ --enable-aliases-daemontools build emulation of daemontools programs [disabled]
+ --enable-aliases-runit build emulation of runit programs [disabled]
+ --disable-aliases-symlinks do not create daemontools/runit multicall symlinks [enabled]
EOF
exit 0
@@ -172,6 +175,9 @@ vpathd=''
build=
usensss=false
useexecline=true
+adaemontools=false
+arunit=false
+asymlinks=true
for arg ; do
case "$arg" in
@@ -213,6 +219,12 @@ for arg ; do
--disable-nsss|--enable-nsss=no) usensss=false ;;
--enable-execline|--enable-execline=yes) useexecline=true ;;
--disable-execline|--enable-execline=no) useexecline=false ;;
+ --enable-aliases-daemontools|--enable-aliases-daemontools=yes) adaemontools=true ;;
+ --disable-aliases-daemontools|--enable-aliases-daemontools=no) adaemontools=false ;;
+ --enable-aliases-runit|--enable-aliases-runit=yes) arunit=true ;;
+ --disable-aliases-runit|--enable-aliases-runit=no) arunit=false ;;
+ --enable-aliases-symlinks|--enable-aliases-symlinks=yes) asymlinks=true ;;
+ --disable-aliases-symlinks|--enable-aliases-symlinks=no) asymlinks=false ;;
--enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
--enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
--host=*|--target=*) target=${arg#*=} ;;
@@ -530,6 +542,22 @@ if $useexecline ; then
else
echo "EXECLINE_LIB :="
fi
+
+if $adaemontools ; then
+ echo "WRAP_DAEMONTOOLS := 1"
+else
+ echo "WRAP_DAEMONTOOLS :="
+fi
+if $arunit ; then
+ echo "WRAP_RUNIT := 1"
+else
+ echo "WRAP_RUNIT :="
+fi
+if $asymlinks ; then
+ echo "WRAP_SYMLINKS := 1"
+else
+ echo "WRAP_SYMLINKS :="
+fi
exec 1>&3 3>&-
echo " ... done."
@@ -565,6 +593,17 @@ echo "#undef ${package_macro_name}_USE_EXECLINE"
if $useexecline ; then
echo "#define ${package_macro_name}_USE_EXECLINE"
fi
+
+echo "#undef ${package_macro_name}_WRAP_DAEMONTOOLS"
+if $adaemontools ; then
+ echo "#define ${package_macro_name}_WRAP_DAEMONTOOLS"
+fi
+
+echo "#undef ${package_macro_name}_WRAP_RUNIT"
+if $arunit ; then
+ echo "#define ${package_macro_name}_WRAP_RUNIT"
+fi
+
echo
echo "#endif"
exec 1>&3 3>&-
diff --git a/package/configure-snippets/configure_case_lines b/package/configure-snippets/configure_case_lines
index edd57ae..237460b 100644
--- a/package/configure-snippets/configure_case_lines
+++ b/package/configure-snippets/configure_case_lines
@@ -2,3 +2,9 @@
--disable-nsss|--enable-nsss=no) usensss=false ;;
--enable-execline|--enable-execline=yes) useexecline=true ;;
--disable-execline|--enable-execline=no) useexecline=false ;;
+ --enable-aliases-daemontools|--enable-aliases-daemontools=yes) adaemontools=true ;;
+ --disable-aliases-daemontools|--enable-aliases-daemontools=no) adaemontools=false ;;
+ --enable-aliases-runit|--enable-aliases-runit=yes) arunit=true ;;
+ --disable-aliases-runit|--enable-aliases-runit=no) arunit=false ;;
+ --enable-aliases-symlinks|--enable-aliases-symlinks=yes) asymlinks=true ;;
+ --disable-aliases-symlinks|--enable-aliases-symlinks=no) asymlinks=false ;;
diff --git a/package/configure-snippets/configure_generate_configh b/package/configure-snippets/configure_generate_configh
index 3c4a1e8..51b89a4 100644
--- a/package/configure-snippets/configure_generate_configh
+++ b/package/configure-snippets/configure_generate_configh
@@ -2,3 +2,14 @@ echo "#undef ${package_macro_name}_USE_EXECLINE"
if $useexecline ; then
echo "#define ${package_macro_name}_USE_EXECLINE"
fi
+
+echo "#undef ${package_macro_name}_WRAP_DAEMONTOOLS"
+if $adaemontools ; then
+ echo "#define ${package_macro_name}_WRAP_DAEMONTOOLS"
+fi
+
+echo "#undef ${package_macro_name}_WRAP_RUNIT"
+if $arunit ; then
+ echo "#define ${package_macro_name}_WRAP_RUNIT"
+fi
+
diff --git a/package/configure-snippets/configure_generate_make b/package/configure-snippets/configure_generate_make
index b0d2474..3dc8e91 100644
--- a/package/configure-snippets/configure_generate_make
+++ b/package/configure-snippets/configure_generate_make
@@ -10,3 +10,19 @@ if $useexecline ; then
else
echo "EXECLINE_LIB :="
fi
+
+if $adaemontools ; then
+ echo "WRAP_DAEMONTOOLS := 1"
+else
+ echo "WRAP_DAEMONTOOLS :="
+fi
+if $arunit ; then
+ echo "WRAP_RUNIT := 1"
+else
+ echo "WRAP_RUNIT :="
+fi
+if $asymlinks ; then
+ echo "WRAP_SYMLINKS := 1"
+else
+ echo "WRAP_SYMLINKS :="
+fi
diff --git a/package/configure-snippets/configure_help_options b/package/configure-snippets/configure_help_options
index 96e9e51..09360fe 100644
--- a/package/configure-snippets/configure_help_options
+++ b/package/configure-snippets/configure_help_options
@@ -1,3 +1,6 @@
--enable-nsss use the nsss library for user information [disabled]
--disable-execline don't use the execline library [enabled]
+ --enable-aliases-daemontools build emulation of daemontools programs [disabled]
+ --enable-aliases-runit build emulation of runit programs [disabled]
+ --disable-aliases-symlinks do not create daemontools/runit multicall symlinks [enabled]
diff --git a/package/configure-snippets/configure_init_vars b/package/configure-snippets/configure_init_vars
index 68c268b..64ff7fe 100644
--- a/package/configure-snippets/configure_init_vars
+++ b/package/configure-snippets/configure_init_vars
@@ -1,2 +1,5 @@
usensss=false
useexecline=true
+adaemontools=false
+arunit=false
+asymlinks=true
diff --git a/package/deps.mak b/package/deps.mak
index bad353e..9a44562 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -7,6 +7,9 @@ src/include/s6/ftrigr.h: src/include/s6/config.h
src/include/s6/lock.h: src/include/s6/config.h
src/include/s6/s6.h: src/include/s6/accessrules.h src/include/s6/auto.h src/include/s6/compat.h src/include/s6/ftrigr.h src/include/s6/ftrigw.h src/include/s6/lock.h src/include/s6/supervise.h
src/supervision/s6-svlisten.h: src/include/s6/ftrigr.h
+src/alias/s6-alias-chpst.o src/alias/s6-alias-chpst.lo: src/alias/s6-alias-chpst.c src/include/s6/config.h
+src/alias/s6-alias-sv.o src/alias/s6-alias-sv.lo: src/alias/s6-alias-sv.c src/include/s6/config.h src/include/s6/supervise.h
+src/alias/s6-alias.o src/alias/s6-alias.lo: src/alias/s6-alias.c src/include/s6/config.h
src/conn-tools/s6-accessrules-cdb-from-fs.o src/conn-tools/s6-accessrules-cdb-from-fs.lo: src/conn-tools/s6-accessrules-cdb-from-fs.c
src/conn-tools/s6-accessrules-fs-from-cdb.o src/conn-tools/s6-accessrules-fs-from-cdb.lo: src/conn-tools/s6-accessrules-fs-from-cdb.c
src/conn-tools/s6-connlimit.o src/conn-tools/s6-connlimit.lo: src/conn-tools/s6-connlimit.c
@@ -145,6 +148,12 @@ src/supervision/s6_svlisten_loop.o src/supervision/s6_svlisten_loop.lo: src/supe
src/supervision/s6_svlisten_signal_handler.o src/supervision/s6_svlisten_signal_handler.lo: src/supervision/s6_svlisten_signal_handler.c src/supervision/s6-svlisten.h
src/usertree/s6-usertree-maker.o src/usertree/s6-usertree-maker.lo: src/usertree/s6-usertree-maker.c src/include/s6/auto.h src/include/s6/config.h
+s6-alias: EXTRA_LIBS :=
+s6-alias: src/alias/s6-alias.o -lskarnet
+s6-alias-chpst: EXTRA_LIBS := ${MAYBEPTHREAD_LIB}
+s6-alias-chpst: src/alias/s6-alias-chpst.o ${LIBNSSS} -lskarnet
+s6-alias-sv: EXTRA_LIBS := ${SPAWN_LIB}
+s6-alias-sv: src/alias/s6-alias-sv.o ${LIBS6} -lskarnet
s6-accessrules-cdb-from-fs: EXTRA_LIBS := ${SOCKET_LIB} ${SYSCLOCK_LIB}
s6-accessrules-cdb-from-fs: src/conn-tools/s6-accessrules-cdb-from-fs.o -lskarnet
s6-accessrules-fs-from-cdb: EXTRA_LIBS :=
diff --git a/package/modes b/package/modes
index dc5b2c3..007d9dd 100644
--- a/package/modes
+++ b/package/modes
@@ -1,4 +1,7 @@
ucspilogd 0755
+s6-alias 0755
+s6-alias-chpst 0755
+s6-alias-sv 0755
s6-ftrigrd 0755
s6-ftrig-listen1 0755
s6-ftrig-listen 0755
diff --git a/package/targets.mak b/package/targets.mak
index b784325..d281923 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -78,3 +78,91 @@ LIB_DEFS += S6AUTO=s6auto
S6AUTO_DESCRIPTION := The s6auto library (C helpers to create service directories)
BIN_TARGETS += s6-usertree-maker s6-instance-maker
endif
+
+WRAP_ANY :=
+
+ifdef WRAP_DAEMONTOOLS
+
+WRAP_ANY := 1
+
+ifdef WRAP_SYMLINKS
+
+DAEMONTOOLS_TARGETS := \
+envdir \
+envuidgid \
+fghack \
+multilog \
+pgrphack \
+readproctitle \
+setlock \
+setuidgid \
+softlimit \
+supervise \
+svc \
+svok \
+svscan \
+svscanboot \
+svstat \
+tai64n \
+tai64nlocal \
+
+else
+
+DAEMONTOOLS_TARGETS :=
+
+endif
+
+install-bin: $(DAEMONTOOLS_TARGETS:%=$(DESTDIR)$(bindir)/%)
+
+ifneq ($(exthome),)
+global-links: $(DAEMONTOOLS_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
+endif
+
+endif
+
+ifdef WRAP_RUNIT
+
+WRAP_ANY := 1
+
+ifdef WRAP_SYMLINKS
+
+RUNIT_TARGETS := \
+runit \
+runit-init \
+runsv \
+runsvchdir \
+runsvdir \
+svlogd \
+utmpset
+RUNIT_SPECIAL_TARGETS := chpst sv
+
+else
+
+RUNIT_TARGETS :=
+RUNIT_SPECIAL_TARGETS :=
+
+endif
+
+BIN_TARGETS += s6-alias-sv s6-alias-chpst
+
+install-bin: $(RUNIT_TARGETS:%=$(DESTDIR)$(bindir)/%) $(RUNIT_SPECIAL_TARGETS:%=$(DESTDIR)$(bindir)/%)
+
+ifneq ($(exthome),)
+global-links: $(RUNIT_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(RUNIT_SPECIAL_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
+endif
+
+$(DESTDIR)$(bindir)/chpst: $(DESTDIR)$(bindir)/s6-alias-chpst
+ exec $(INSTALL) -D -l s6-alias-chpst $@
+$(DESTDIR)$(bindir)/sv: $(DESTDIR)$(bindir)/s6-alias-sv
+ exec $(INSTALL) -D -l s6-alias-sv $@
+
+endif
+
+ifdef WRAP_ANY
+
+BIN_TARGETS += s6-alias
+
+$(DAEMONTOOLS_TARGETS:%=$(DESTDIR)$(bindir)/%) $(RUNIT_TARGETS:%=$(DESTDIR)$(bindir)/%): $(DESTDIR)$(bindir)/s6-alias
+ exec $(INSTALL) -D -l s6-alias $@
+
+endif
diff --git a/src/alias/deps-exe/s6-alias b/src/alias/deps-exe/s6-alias
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/alias/deps-exe/s6-alias
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/alias/deps-exe/s6-alias-chpst b/src/alias/deps-exe/s6-alias-chpst
new file mode 100644
index 0000000..ee4ed0b
--- /dev/null
+++ b/src/alias/deps-exe/s6-alias-chpst
@@ -0,0 +1,3 @@
+${LIBNSSS}
+-lskarnet
+${MAYBEPTHREAD_LIB}
diff --git a/src/alias/deps-exe/s6-alias-sv b/src/alias/deps-exe/s6-alias-sv
new file mode 100644
index 0000000..e575f02
--- /dev/null
+++ b/src/alias/deps-exe/s6-alias-sv
@@ -0,0 +1,3 @@
+${LIBS6}
+-lskarnet
+${SPAWN_LIB}
diff --git a/src/alias/s6-alias-chpst.c b/src/alias/s6-alias-chpst.c
new file mode 100644
index 0000000..f38e29e
--- /dev/null
+++ b/src/alias/s6-alias-chpst.c
@@ -0,0 +1,357 @@
+ /* ISC license. */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <skalibs/uint64.h>
+#include <skalibs/types.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr.h>
+#include <skalibs/exec.h>
+
+#include <s6/config.h>
+
+#ifdef S6_USE_EXECLINE
+# include <execline/config.h>
+# define USAGE "s6-alias-chpst [ -v ] [ -P ] [ -0 ] [ -1 ] [ -2 ] [ -u user ] [ -U user ] [ -b argv0 ] [ -e dir ] [ -n niceness ] [ -l lock | -L lock ] [ -m bytes ] [ -d bytes ] [ -o n ] [ -p n ] [ -f bytes ] [ -c bytes ] prog..."
+#else
+# define USAGE "s6-alias-chpst [ -v ] [ -P ] [ -u user ] [ -U user ] [ -e dir ] [ -n niceness ] [ -l lock | -L lock ] [ -m bytes ] [ -d bytes ] [ -o n ] [ -p n ] [ -f bytes ] [ -c bytes ] prog..."
+#endif
+
+#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static unsigned int verbosity = 0 ;
+
+static void printit (char const *const *argv)
+{
+ buffer_puts(buffer_2, PROG) ;
+ buffer_puts(buffer_2, ": info: executing the following command line:") ;
+ for (; *argv ; argv++)
+ {
+ buffer_puts(buffer_2, " ") ;
+ buffer_puts(buffer_2, *argv) ;
+ }
+ buffer_putsflush(buffer_2, "\n") ;
+}
+
+static inline size_t parseuggnum (char const *s, uint32_t *flags, uid_t *uid, gid_t *gid, gid_t *tab)
+{
+ size_t n = 0 ;
+ size_t pos = uid_scan(s, uid) ;
+ if (!pos) dieusage() ;
+ if (!s[pos]) return 0 ;
+ if (s[pos] != ':') dieusage() ;
+ s += pos+1 ;
+ pos = gid_scan(s, gid) ;
+ if (!pos) dieusage() ;
+ *flags |= 32768 ;
+ if (!s[pos]) return 0 ;
+ if (s[pos] != ':') dieusage() ;
+ s += pos+1 ;
+ if (!gid_scanlist(tab, NGROUPS_MAX, s, &n)) dieusage() ;
+ return n ;
+}
+
+static struct passwd *do_getpwnam (char const *s)
+{
+ struct passwd *pw = getpwnam(s) ;
+ if (!pw)
+ {
+ if (errno) strerr_diefu1sys(111, "read user database") ;
+ else strerr_dief2x(100, "user not found in user database: ", s) ;
+ }
+ return pw ;
+}
+
+static struct group *do_getgrnam (char const *s)
+{
+ struct group *gr = getgrnam(s) ;
+ if (!gr)
+ {
+ if (errno) strerr_diefu1sys(111, "read group database") ;
+ else strerr_dief2x(100, "group not found in group database: ", s) ;
+ }
+ return gr ;
+}
+
+static inline size_t parseuggsym (char const *s, uint32_t *flags, uid_t *uid, gid_t *gid, gid_t *tab)
+{
+ size_t n = 0 ;
+ struct passwd *pw ;
+ struct group *gr ;
+ size_t pos = str_chr(s, ':') ;
+ *flags |= 32768 ;
+ errno = 0 ;
+ if (!s[pos]) pw = do_getpwnam(s) ;
+ else
+ {
+ char tmp[pos+1] ;
+ memcpy(tmp, s, pos) ;
+ tmp[pos] = 0 ;
+ pw = do_getpwnam(tmp) ;
+ }
+ *uid = pw->pw_uid ;
+ if (!s[pos])
+ {
+ *gid = pw->pw_gid ;
+ return 0 ;
+ }
+ s += pos+1 ;
+ pos = str_chr(s, ':') ;
+ errno = 0 ;
+ if (!s[pos]) gr = do_getgrnam(s) ;
+ else
+ {
+ char tmp[pos+1] ;
+ memcpy(tmp, s, pos) ;
+ tmp[pos] = 0 ;
+ gr = do_getgrnam(tmp) ;
+ }
+ *gid = gr->gr_gid ;
+ if (!s[pos]) return 0 ;
+ s += pos+1 ;
+ while (*s)
+ {
+ if (n >= NGROUPS_MAX)
+ strerr_dief1x(100, "too many supplementary groups listed for the -u option") ;
+ pos = str_chr(s, ':') ;
+ errno = 0 ;
+ if (!s[pos]) gr = do_getgrnam(s) ;
+ else
+ {
+ char tmp[pos+1] ;
+ memcpy(tmp, s, pos) ;
+ tmp[pos] = 0 ;
+ gr = do_getgrnam(tmp) ;
+ }
+ tab[n++] = gr->gr_gid ;
+ s += s[pos] ? pos+1 : pos ;
+ }
+ return n ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ static char const *valopt[6] = { "-m", "-d", "-o", "-p", "-f", "-c" } ;
+ unsigned int newargc = 0 ;
+ char const *newroot = 0 ;
+ char const *edir = 0 ;
+ char const *lockfile = 0 ;
+ char const *envug = 0 ;
+#ifdef S6_USE_EXECLINE
+ char const *argv0 = 0 ;
+#endif
+ uint32_t flags = 0 ;
+ int niceval = 0 ;
+ char valfmt[6][UINT64_FMT] ;
+ char nicefmt[INT_FMT] ;
+ char uidfmt[UID_FMT] ;
+ char gidfmt[GID_FMT] ;
+ char gidlistfmt[GID_FMT * NGROUPS_MAX] ;
+ PROG = "s6-alias-chpst" ;
+
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+#ifdef S6_USE_EXECLINE
+ int opt = subgetopt_r(argc, argv, "vP012u:U:b:e:/:n:l:L:m:d:o:p:f:c:", &l) ;
+#else
+ int opt = subgetopt_r(argc, argv, "vPu:U:e:/:n:l:L:m:d:o:p:f:c:", &l) ;
+#endif
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'v' : verbosity++ ; break ;
+ case 'P' : flags |= 8 ; newargc += 2 ; break ;
+#ifdef S6_USE_EXECLINE
+ case '0' : flags |= 1 ; newargc += 2 ; break ;
+ case '1' : flags |= 2 ; newargc += 2 ; break ;
+ case '2' : flags |= 4 ; newargc += 2 ; break ;
+ case 'b' : argv0 = l.arg ; newargc += 4 ; break ;
+#endif
+ case 'u' :
+ {
+ size_t n ;
+ uid_t uid ;
+ gid_t gid ;
+ gid_t tab[NGROUPS_MAX] ;
+ newargc += 6 ;
+ flags |= 16384 ; flags &= ~32768 ;
+ n = l.arg[0] == ':' ?
+ parseuggnum(l.arg + 1, &flags, &uid, &gid, tab) :
+ parseuggsym(l.arg, &flags, &uid, &gid, tab) ;
+ uidfmt[uid_fmt(uidfmt, uid)] = 0 ;
+ if (flags & 32768)
+ {
+ newargc += 2 ;
+ gidfmt[gid_fmt(gidfmt, gid)] = 0 ;
+ }
+ gidlistfmt[gid_fmtlist(gidlistfmt, tab, n)] = 0 ;
+ break ;
+ }
+ case 'U' :
+ envug = l.arg ;
+ newargc += 3 ;
+ if (envug[0] == ':') { flags |= 4096 ; envug++ ; newargc++ ; } else flags &= ~4096 ;
+ if (strchr(envug, ':')) { flags |= 8192 ; newargc++ ; } else flags &= ~8192 ;
+ break ;
+ case 'e' : edir = l.arg ; newargc += 3 ; break ;
+ case '/' : newroot = l.arg ; newargc += 2 ; break ;
+ case 'n' :
+ if (!int0_scan(l.arg, &niceval)) dieusage() ;
+ newargc += 3 ;
+ break ;
+ case 'l' : lockfile = l.arg ; flags &= ~16 ; newargc += 4 ; break ;
+ case 'L' : lockfile = l.arg ; flags |= 16 ; newargc += 4 ; break ;
+ case 'm' :
+ case 'd' :
+ case 'o' :
+ case 'p' :
+ case 'f' :
+ case 'c' :
+ {
+ uint64_t val ;
+ size_t pos = byte_chr("mdopfc", 6, opt) ;
+ if (!uint640_scan(l.arg, &val)) dieusage() ;
+ valfmt[pos][uint64_fmt(valfmt[pos], val)] = 0 ;
+ flags |= 32 | (1 << (6 + pos)) ;
+ newargc += 2 ;
+ break ;
+ }
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (newroot)
+ {
+ newroot = realpath(newroot, 0) ;
+ if (!newroot) dienomem() ;
+ }
+ if (flags & 32) newargc += 2 ;
+ newargc += argc ;
+
+ {
+ unsigned int m = 0 ;
+ char const *newargv[newargc + 1] ;
+
+ if (niceval)
+ {
+ nicefmt[int_fmt(nicefmt, niceval)] = 0 ;
+ newargv[m++] = "nice" ;
+ newargv[m++] = "-n" ;
+ newargv[m++] = nicefmt ;
+ newargv[m++] = "--" ;
+ }
+
+ if (flags & 8)
+ {
+ newargv[m++] = S6_BINPREFIX "s6-setsid" ;
+ newargv[m++] = "--" ;
+ }
+
+ if (edir)
+ {
+ newargv[m++] = S6_BINPREFIX "s6-envdir" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = edir ;
+ }
+
+ if (lockfile)
+ {
+ newargv[m++] = S6_BINPREFIX "s6-setlock" ;
+ newargv[m++] = flags & 16 ? "-n" : "-N" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = lockfile ;
+ }
+
+ if (flags & 16384)
+ {
+ newargv[m++] = S6_BINPREFIX "s6-applyuidgid" ;
+ newargv[m++] = "-u" ;
+ newargv[m++] = uidfmt ;
+ if (flags & 32768)
+ {
+ newargv[m++] = "-g" ;
+ newargv[m++] = gidfmt ;
+ }
+ newargv[m++] = "-G" ;
+ newargv[m++] = gidlistfmt ;
+ newargv[m++] = "--" ;
+ }
+
+ if (envug)
+ {
+ newargv[m++] = S6_BINPREFIX "s6-envuidgid" ;
+ if (flags & 4096) newargv[m++] = "-n" ;
+ if (flags & 8192) newargv[m++] = "-B" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = envug ;
+ }
+
+ if (flags & 32)
+ {
+ newargv[m++] = S6_BINPREFIX "s6-softlimit" ;
+ for (unsigned int i = 0 ; i < 6 ; i++) if (flags & (1 << (i + 6)))
+ {
+ newargv[m++] = valopt[i] ;
+ newargv[m++] = valfmt[i] ;
+ }
+ newargv[m++] = "--" ;
+ }
+
+#ifdef S6_USE_EXECLINE
+ if (flags & 1)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ;
+ newargv[m++] = "0" ;
+ }
+
+ if (flags & 2)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ;
+ newargv[m++] = "1" ;
+ }
+
+ if (flags & 4)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ;
+ newargv[m++] = "2" ;
+ }
+
+ if (argv0 && newroot)
+ {
+ argv0 = 0 ;
+ strerr_warnw1x("the -b option is ineffective when the -/ option is also given") ;
+ }
+
+ if (argv0)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "exec" ;
+ newargv[m++] = "-a" ;
+ newargv[m++] = argv0 ;
+ newargv[m++] = "--" ;
+ }
+#endif
+
+ if (newroot)
+ {
+ newargv[m++] = "chroot" ;
+ newargv[m++] = newroot ;
+ }
+
+ for (int i = 0 ; i < argc+1 ; i++) newargv[m++] = argv[i] ;
+ if (verbosity) printit(newargv) ;
+ xexec0(newargv) ;
+ }
+}
diff --git a/src/alias/s6-alias-sv.c b/src/alias/s6-alias-sv.c
new file mode 100644
index 0000000..ad348ca
--- /dev/null
+++ b/src/alias/s6-alias-sv.c
@@ -0,0 +1,448 @@
+ /* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr.h>
+#include <skalibs/cspawn.h>
+#include <skalibs/djbunix.h>
+
+#include <s6/config.h>
+#include <s6/supervise.h>
+
+#define USAGE "s6-alias-sv [ -v ] [ -w sec ] command services..."
+#define dieusage() strerr_dieusage(100, USAGE)
+#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
+
+typedef int exec_func (char const *, char const *const *) ;
+typedef exec_func *exec_func_ref ;
+
+typedef struct info_s info_t, *info_t_ref ;
+struct info_s
+{
+ char const *name ;
+ exec_func_ref f ;
+} ;
+
+static int dowait = 0 ;
+static uint32_t secs = 7 ;
+
+static void warnnolog (void)
+{
+ strerr_warnw1x("s6-svc only sends commands to a single service, even if it has a dedicated logger") ;
+}
+
+static void warnnokill (void)
+{
+ strerr_warnw1x("s6-supervise pilots a kill signal via the timeout-kill file in the service directory") ;
+}
+
+static int info_cmp (void const *a, void const *b)
+{
+ char const *name = a ;
+ info_t const *info = b ;
+ return strcmp(name, info->name) ;
+}
+
+static int spawnit (char const *const *argv, char const *const *envp)
+{
+ int wstat ;
+ pid_t r ;
+ pid_t pid = cspawn(argv[0], argv, envp, 0, 0, 0) ;
+ if (!pid)
+ {
+ strerr_warnwu2sys("spawn ", argv[0]) ;
+ return 1 ;
+ }
+ r = wait_pid(pid, &wstat) ;
+ if (r != pid)
+ {
+ strerr_warnwu2sys("wait for ", argv[0]) ;
+ return 1 ;
+ }
+ return !!WIFSIGNALED(wstat) || !!WEXITSTATUS(wstat) ;
+}
+
+static int simple_svc (char const *dir, char const *options, char const *const *envp)
+{
+ char const *argv[5] = { S6_BINPREFIX "s6-svc", options, "--", dir, 0 } ;
+ return spawnit(argv, envp) ;
+}
+
+static int complex_svc (char const *dir, char const *order, char waitfor, char const *const *envp)
+{
+ char warg[4] = "-w?" ;
+ char fmt[2 + UINT32_FMT] = "-T" ;
+ char const *argv[7] = { S6_BINPREFIX "s6-svc", warg, fmt, order, "--", dir, 0 } ;
+ fmt[2 + uint32_fmt(fmt + 2, 1000 * secs)] = 0 ;
+ warg[2] = waitfor ;
+ return spawnit(argv, envp) ;
+}
+
+static int status (char const *dir, char const *const *envp)
+{
+ int e ;
+ char const *argv[4] = { S6_BINPREFIX "s6-svstat", "--", dir, 0 } ;
+ size_t dirlen = strlen(dir) ;
+ buffer_puts(buffer_1, dir) ;
+ buffer_putsflush(buffer_1, ": ") ;
+ e = spawnit(argv, envp) ;
+ if (dirlen < 5 || strcmp(dir + dirlen - 4, "/log"))
+ {
+ struct stat st ;
+ char log[dirlen + 5] ;
+ memcpy(log, dir, dirlen) ;
+ memcpy(log + dirlen, "/log", 5) ;
+ if (stat(log, &st) < 0)
+ {
+ if (errno != ENOENT)
+ {
+ strerr_warnwu2sys("stat", log) ;
+ e = 1 ;
+ }
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
+ argv[2] = log ;
+ buffer_puts(buffer_1, log) ;
+ buffer_putsflush(buffer_1, ": ") ;
+ e |= spawnit(argv, envp) ;
+ }
+ }
+ return e ;
+}
+
+static int action (char const *dir, char const *simple, char const *cplx, char waitchar, char const *const *envp)
+{
+ if (dowait)
+ {
+ int e = complex_svc(dir, cplx, waitchar, envp) ;
+ return e | status(dir, envp) ;
+ }
+ else return simple_svc(dir, simple, envp) ;
+}
+
+static int usr1_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-1", envp) ;
+}
+
+static int usr2_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-2", envp) ;
+}
+
+static int alarm_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-a", envp) ;
+}
+
+static int cont_h (char const *dir, char const *const *envp)
+{
+ return action(dir, "-c", "-o", 'U', envp) ;
+}
+
+static int down (char const *dir, char const *const *envp)
+{
+ return action(dir, "-d", "-d", 'D', envp) ;
+}
+
+static int forcedown (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return down(dir, envp) ;
+}
+
+static int bail (char const *dir, char const *const *envp)
+{
+ int e ;
+ warnnolog() ;
+ e = action(dir, "-xd", "-d", 'D', envp) ;
+ if (dowait) e |= simple_svc(dir, "-x", envp) ;
+ return e ;
+}
+
+static int forcebail (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return bail(dir, envp) ;
+}
+
+static int hup_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-h", envp) ;
+}
+
+static int int_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-i", envp) ;
+}
+
+static int kill_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-k", envp) ;
+}
+
+static int once (char const *dir, char const *const *envp)
+{
+ return action(dir, "-o", "-o", 'U', envp) ;
+}
+
+static int pause_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-p", envp) ;
+}
+
+static int quit_h (char const *dir, char const *const *envp)
+{
+ return simple_svc(dir, "-q", envp) ;
+}
+
+static int term_h (char const *dir, char const *const *envp)
+{
+ return action(dir, "-t", "-r", 'R', envp) ;
+}
+
+static int up (char const *dir, char const *const *envp)
+{
+ return action(dir, "-u", "-u", 'U', envp) ;
+}
+
+static int check (char const *dir, char const *const *envp)
+{
+ int e ;
+ s6_svstatus_t svst ;
+ char warg[3] = "-?" ;
+ char fmt[2 + UINT32_FMT] = "-t" ;
+ char const *argv[6] = { S6_BINPREFIX "s6-svwait", warg, fmt, "--", dir, 0 } ;
+ fmt[2 + uint32_fmt(fmt + 2, 1000 * secs)] = 0 ;
+ if (!s6_svstatus_read(dir, &svst)) return 1 ;
+ warg[1] = svst.flagwantup ? 'U' : 'D' ;
+ e = spawnit(argv, envp) ;
+ return e | status(dir, envp) ;
+}
+
+static int lsb_reload (char const *dir, char const *const *envp)
+{
+ hup_h(dir, envp) ;
+ return status(dir, envp) ;
+}
+
+static int lsb_restart (char const *dir, char const *const *envp)
+{
+ int e = complex_svc(dir, "-ru", 'U', envp) ;
+ return e | status(dir, envp) ;
+}
+
+static int lsb_start (char const *dir, char const *const *envp)
+{
+ int e = complex_svc(dir, "-u", 'U', envp) ;
+ return e | status(dir, envp) ;
+}
+
+static int lsb_stop (char const *dir, char const *const *envp)
+{
+ int e = complex_svc(dir, "-d", 'D', envp) ;
+ return e | status(dir, envp) ;
+}
+
+static int lsb_shutdown (char const *dir, char const *const *envp)
+{
+ int e ;
+ warnnolog() ;
+ e = complex_svc(dir, "-d", 'D', envp) ;
+ e |= status(dir, envp) ;
+ return e | simple_svc(dir, "-x", envp) ;
+}
+
+static int lsb_forcereload (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return lsb_reload(dir, envp) ;
+}
+
+static int lsb_forcerestart (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return lsb_restart(dir, envp) ;
+}
+
+static int lsb_forcestop (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return lsb_stop(dir, envp) ;
+}
+
+static int lsb_forceshutdown (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return lsb_shutdown(dir, envp) ;
+}
+
+static int lsb_tryrestart (char const *dir, char const *const *envp)
+{
+ int e = 0 ;
+ s6_svstatus_t svst ;
+ if (s6_svstatus_read(dir, &svst) && svst.flagwantup && svst.pid && !svst.flagfinishing)
+ e = complex_svc(dir, "-r", 'U', envp) ;
+ return e | status(dir, envp) ;
+}
+
+static int lsb_forcetryrestart (char const *dir, char const *const *envp)
+{
+ warnnokill() ;
+ return lsb_tryrestart(dir, envp) ;
+}
+
+static info_t const commands[] =
+{
+ { .name = "1", .f = &usr1_h },
+ { .name = "2", .f = &usr2_h },
+ { .name = "D", .f = &forcedown },
+ { .name = "E", .f = &forcebail },
+ { .name = "T", .f = &lsb_forcetryrestart },
+ { .name = "X", .f = &forcebail },
+ { .name = "a", .f = &alarm_h },
+ { .name = "al", .f = &alarm_h },
+ { .name = "ala", .f = &alarm_h },
+ { .name = "alar", .f = &alarm_h },
+ { .name = "alarm", .f = &alarm_h },
+ { .name = "c", .f = &cont_h },
+ { .name = "check", .f = &check },
+ { .name = "co", .f = &cont_h },
+ { .name = "con", .f = &cont_h },
+ { .name = "cont", .f = &cont_h },
+ { .name = "d", .f = &down },
+ { .name = "do", .f = &down },
+ { .name = "dow", .f = &down },
+ { .name = "down", .f = &down },
+ { .name = "e", .f = &bail },
+ { .name = "ex", .f = &bail },
+ { .name = "exi", .f = &bail },
+ { .name = "exit", .f = &bail },
+ { .name = "force-reload", .f = &lsb_forcereload },
+ { .name = "force-restart", .f = &lsb_forcerestart },
+ { .name = "force-shutdown", .f = &lsb_forceshutdown },
+ { .name = "force-stop", .f = &lsb_forcestop },
+ { .name = "h", .f = &hup_h },
+ { .name = "hu", .f = &hup_h },
+ { .name = "hup", .f = &hup_h },
+ { .name = "i", .f = &int_h },
+ { .name = "in", .f = &int_h },
+ { .name = "int", .f = &int_h },
+ { .name = "inte", .f = &int_h },
+ { .name = "inter", .f = &int_h },
+ { .name = "interr", .f = &int_h },
+ { .name = "interru", .f = &int_h },
+ { .name = "interrup", .f = &int_h },
+ { .name = "interrupt", .f = &int_h },
+ { .name = "k", .f = &kill_h },
+ { .name = "ki", .f = &kill_h },
+ { .name = "kil", .f = &kill_h },
+ { .name = "kill", .f = &kill_h },
+ { .name = "o", .f = &once },
+ { .name = "on", .f = &once },
+ { .name = "onc", .f = &once },
+ { .name = "once", .f = &once },
+ { .name = "p", .f = &pause_h },
+ { .name = "pa", .f = &pause_h },
+ { .name = "pau", .f = &pause_h },
+ { .name = "paus", .f = &pause_h },
+ { .name = "pause", .f = &pause_h },
+ { .name = "q", .f = &quit_h },
+ { .name = "qu", .f = &quit_h },
+ { .name = "qui", .f = &quit_h },
+ { .name = "quit", .f = &quit_h },
+ { .name = "reload", .f = &lsb_reload },
+ { .name = "restart", .f = &lsb_restart },
+ { .name = "s", .f = &status },
+ { .name = "shutdown", .f = &lsb_shutdown },
+ { .name = "st", .f = &status },
+ { .name = "sta", .f = &status },
+ { .name = "start", .f = &lsb_start },
+ { .name = "stat", .f = &status },
+ { .name = "statu", .f = &status },
+ { .name = "status", .f = &status },
+ { .name = "stop", .f = &lsb_stop },
+ { .name = "t", .f = &term_h },
+ { .name = "te", .f = &term_h },
+ { .name = "ter", .f = &term_h },
+ { .name = "term", .f = &term_h },
+ { .name = "try-restart", .f = &lsb_tryrestart },
+ { .name = "u", .f = &up },
+ { .name = "up", .f = &up },
+ { .name = "x", .f = &bail }
+} ;
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ int e = 0 ;
+ info_t *p ;
+ char const *x = getenv("SVWAIT") ;
+ char const *scandir = getenv("SVDIR") ;
+ size_t scandirlen ;
+ PROG = "s6-alias-sv" ;
+ if (!scandir) scandir = "/run/service" ; /* TODO: read from s6li config if any? */
+ scandirlen = strlen(scandir) ;
+ if (x)
+ {
+ if (!uint320_scan(x, &secs))
+ strerr_warnw1x("invalid SVWAIT value") ;
+ }
+
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "vw:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'v' : dowait = 1 ; break ;
+ case 'w' : if (!uint320_scan(l.arg, &secs)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (argc < 2) dieusage() ;
+ p = bsearch(argv[0], commands, sizeof(commands) / sizeof(info_t), sizeof(info_t), &info_cmp) ;
+ if (!p) strerr_dief2x(100, "unknown command: ", argv[0]) ;
+
+ for (argv++ ; *argv ; argv++)
+ {
+ if (!argv[0][0]) continue ;
+ if (argv[0][0] == '/' || argv[0][strlen(argv[0]) - 1] == '/' || (argv[0][0] == '.' && (!argv[0][1] || argv[0][1] == '/' || (argv[0][1] == '.' && (!argv[0][2] || argv[0][2] == '/')))))
+ e += (*p->f)(*argv, envp) ;
+ else
+ {
+ int what = 1 ;
+ struct stat st ;
+ size_t len = strlen(*argv) ;
+ char fn[scandirlen + len + 2] ;
+ memcpy(fn, scandir, scandirlen) ;
+ fn[scandirlen] = '/' ;
+ memcpy(fn + scandirlen + 1, *argv, len + 1) ;
+ if (stat(fn, &st) < 0) /* XXX: TOCTOU but we don't care */
+ {
+ if (errno != ENOENT)
+ {
+ e++ ;
+ what = 0 ;
+ strerr_warnwu2sys("stat ", fn) ;
+ }
+ }
+ else if (S_ISDIR(st.st_mode)) what = 2 ;
+ if (what) e += (*p->f)(what > 1 ? fn : *argv, envp) ;
+ }
+ }
+ return e ;
+}
diff --git a/src/alias/s6-alias.c b/src/alias/s6-alias.c
new file mode 100644
index 0000000..568d29d
--- /dev/null
+++ b/src/alias/s6-alias.c
@@ -0,0 +1,227 @@
+ /* ISC license. */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/skamisc.h>
+#include <skalibs/exec.h>
+
+#include <s6/config.h>
+
+#define USAGE "s6-alias [ -v ] cmdname options..."
+#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static unsigned int verbosity = 0 ;
+
+typedef void exec_func (int, char const *const *) ;
+typedef exec_func *exec_func_ref ;
+
+typedef struct info_s info_t, *info_t_ref ;
+struct info_s
+{
+ char const *name ;
+ char const *cmd ;
+ exec_func_ref f ;
+} ;
+
+static int info_cmp (void const *a, void const *b)
+{
+ char const *name = a ;
+ info_t const *info = b ;
+ return strcmp(name, info->name) ;
+}
+
+#if defined(S6_WRAP_DAEMONTOOLS) || defined (S6_WRAP_RUNIT)
+static void noboot (char const *name)
+{
+ strerr_dief3x(100, "s6 does not provide a ", name, " emulation. To boot on a s6 supervision tree, please consider the s6-linux-init package.") ;
+}
+#endif
+
+#ifdef S6_WRAP_DAEMONTOOLS
+
+static void readproctitle (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ noboot("readproctitle") ;
+}
+
+static void svscanboot (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ noboot("svscanboot") ;
+}
+
+#endif
+
+#ifdef S6_WRAP_RUNIT
+
+static void runit (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ noboot("runit") ;
+}
+
+static void runit_init (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ noboot("runit-init") ;
+}
+
+static void runsvchdir (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ strerr_dief1x(100, "s6 does not provide a runsvchdir emulation. To handle several different sets of services, please consider the s6-rc package.") ;
+}
+
+static void runsvdir (int argc, char const *const *argv)
+{
+ char const *newargv[4] = { S6_BINPREFIX "s6-svscan", "-t0", 0, 0 } ;
+ int dosetsid = 0 ;
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "P", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'P' : dosetsid = 1 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ if (dosetsid)
+ strerr_warnw1x("-P option ignored: s6-svscan does not run its supervisor processes (s6-supervise) in a new session. However, by default, it runs every service in a new session.") ;
+ if (argc >= 2)
+ strerr_warnw1x("s6-svscan does not support logging to a readproctitle process. To log the output of your supervision tree, please consider using the s6-linux-init package.") ;
+ newargv[2] = argv[0] ;
+ if (verbosity)
+ {
+ buffer_puts(buffer_2, PROG) ;
+ buffer_puts(buffer_2, ": info: executing command line:") ;
+ for (char const *const *p = argv ; *p ; p++)
+ {
+ buffer_puts(buffer_2, " ") ;
+ buffer_puts(buffer_2, *p) ;
+ }
+ buffer_putsflush(buffer_2, "\n") ;
+ }
+ xexec(newargv) ;
+}
+
+static void svlogd (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ strerr_dief1x(100, "the s6-log program is similar to svlogd, but uses a different filtering syntax and does not use a config file in the logdir. Please see https://skarnet.org/software/s6/s6-log.html") ;
+}
+
+static void utmpset (int argc, char const *const *argv)
+{
+ (void)argc ;
+ (void)argv ;
+ strerr_dief1x(100, "s6 does not provide a utmpset emulation. To handle utmp records, please consider the s6-linux-init package, along with the utmps package if necessary.") ;
+}
+
+#endif
+
+static info_t const aliases[] =
+{
+#ifdef S6_WRAP_RUNIT
+ { .name = "chpst", .cmd = S6_BINPREFIX "s6-alias-chpst", .f = 0 },
+#endif
+#ifdef S6_WRAP_DAEMONTOOLS
+ { .name = "envdir", .cmd = S6_BINPREFIX "s6-envdir", .f = 0 },
+ { .name = "envuidgid", .cmd = S6_BINPREFIX "s6-envuidgid", .f = 0 },
+ { .name = "fghack", .cmd = S6_BINPREFIX "s6-fghack", .f = 0 },
+ { .name = "multilog", .cmd = S6_BINPREFIX "s6-log", .f = 0 },
+ { .name = "pgrphack", .cmd = S6_BINPREFIX "s6-setsid", .f = 0 },
+ { .name = "readproctitle", .cmd = 0, .f = &readproctitle },
+#endif
+#ifdef S6_WRAP_RUNIT
+ { .name = "runit", .cmd = 0, .f = &runit },
+ { .name = "runit-init", .cmd = 0, .f = &runit_init },
+ { .name = "runsv", .cmd = S6_BINPREFIX "s6-supervise", .f = 0 },
+ { .name = "runsvchdir", .cmd = 0, .f = &runsvchdir },
+ { .name = "runsvdir", .cmd = 0, .f = &runsvdir },
+#endif
+#ifdef S6_WRAP_DAEMONTOOLS
+ { .name = "setlock", .cmd = S6_BINPREFIX "s6-setlock", .f = 0 },
+ { .name = "setuidgid", .cmd = S6_BINPREFIX "s6-setuidgid", .f = 0 },
+ { .name = "softlimit", .cmd = S6_BINPREFIX "s6-softlimit", .f = 0 },
+ { .name = "supervise", .cmd = S6_BINPREFIX "s6-supervise", .f = 0 },
+#endif
+#ifdef S6_WRAP_RUNIT
+ { .name = "sv", .cmd = S6_BINPREFIX "s6-alias-sv", .f = 0 },
+#endif
+#ifdef S6_WRAP_DAEMONTOOLS
+ { .name = "svc", .cmd = S6_BINPREFIX "s6-svc", .f = 0 },
+#endif
+#ifdef S6_WRAP_RUNIT
+ { .name = "svlogd", .cmd = 0, .f = &svlogd },
+#endif
+#ifdef S6_WRAP_DAEMONTOOLS
+ { .name = "svok", .cmd = S6_BINPREFIX "s6-svok", .f = 0 },
+ { .name = "svscan", .cmd = S6_BINPREFIX "s6-svscan", .f = 0 },
+ { .name = "svscanboot", .cmd = 0, .f = &svscanboot },
+ { .name = "svstat", .cmd = S6_BINPREFIX "s6-svstat", .f = 0 },
+ { .name = "tai64n", .cmd = S6_BINPREFIX "s6-tai64n", .f = 0 },
+ { .name = "tai64nlocal", .cmd = S6_BINPREFIX "s6-tai64nlocal", .f = 0 },
+#endif
+#ifdef S6_WRAP_RUNIT
+ { .name = "utmpset", .cmd = 0, .f = &utmpset },
+#endif
+} ;
+
+int main (int argc, char const **argv)
+{
+ char const *name = argv[0] ;
+ stralloc sa = STRALLOC_ZERO ;
+ info_t *p ;
+ PROG = "s6-alias" ;
+
+ if (!sabasename(&sa, name, strlen(name)) || !stralloc_0(&sa)) dienomem() ;
+ if (!strcmp(sa.s, PROG))
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "v", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'v' : verbosity++ ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ if (!argc) dieusage() ;
+ name = *argv ;
+ stralloc_free(&sa) ;
+ }
+ else name = sa.s ;
+
+ p = bsearch(name, aliases, sizeof(aliases) / sizeof(info_t), sizeof(info_t), &info_cmp) ;
+ if (!p) strerr_dief2x(100, "unknown alias: ", name) ;
+ if (p->cmd)
+ {
+ argv[0] = p->cmd ;
+ if (verbosity)
+ strerr_warni4x("the s6 version of ", name, " is ", p->cmd) ;
+ xexec(argv) ;
+ }
+ else (*p->f)(argc, argv) ;
+ strerr_dief1x(101, "can't happen: incorrect alias handler. Please submit a bug-report.") ;
+}