diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2025-11-04 21:55:42 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2025-11-04 21:55:42 +0000 |
| commit | 1667855c0c05f26b378ed8a011336770485321e5 (patch) | |
| tree | e2b040143458aef7d3c4b4e64f9cda98ff543e64 | |
| parent | 2b61e7fa65bdae911e33fa415c4925fb2aabfeb1 (diff) | |
| download | s6-1667855c0c05f26b378ed8a011336770485321e5.tar.gz | |
Move daemontools/runit wrapper support here
| -rw-r--r-- | .gitignore | 3 | ||||
| -rwxr-xr-x | configure | 39 | ||||
| -rw-r--r-- | package/configure-snippets/configure_case_lines | 6 | ||||
| -rw-r--r-- | package/configure-snippets/configure_generate_configh | 11 | ||||
| -rw-r--r-- | package/configure-snippets/configure_generate_make | 16 | ||||
| -rw-r--r-- | package/configure-snippets/configure_help_options | 3 | ||||
| -rw-r--r-- | package/configure-snippets/configure_init_vars | 3 | ||||
| -rw-r--r-- | package/deps.mak | 9 | ||||
| -rw-r--r-- | package/modes | 3 | ||||
| -rw-r--r-- | package/targets.mak | 88 | ||||
| -rw-r--r-- | src/alias/deps-exe/s6-alias | 1 | ||||
| -rw-r--r-- | src/alias/deps-exe/s6-alias-chpst | 3 | ||||
| -rw-r--r-- | src/alias/deps-exe/s6-alias-sv | 3 | ||||
| -rw-r--r-- | src/alias/s6-alias-chpst.c | 357 | ||||
| -rw-r--r-- | src/alias/s6-alias-sv.c | 448 | ||||
| -rw-r--r-- | src/alias/s6-alias.c | 227 |
16 files changed, 1220 insertions, 0 deletions
@@ -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 @@ -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.") ; +} |
