From af9550cfe7ea35590d9c8e246ebeaa32f6469966 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 4 Jun 2026 09:47:23 +0000 Subject: Prepare for 2.15.1.0; add s6-svscanboot Also fix links on why.html. s6-svscanboot doc coming soon. --- .gitignore | 1 + INSTALL | 4 +- NEWS | 4 +- doc/index.html | 7 +- doc/overview.html | 12 +- doc/s6-svscan-not-1.html | 18 +-- doc/s6-svscan.html | 2 +- doc/upgrade.html | 5 +- doc/why.html | 6 +- package/deps-build | 2 +- package/deps.mak | 3 + package/info | 2 +- package/modes | 1 + package/targets.mak | 2 +- src/alias/s6-alias.c | 10 +- src/supervision/deps-exe/s6-svscanboot | 1 + src/supervision/s6-svscanboot.c | 270 +++++++++++++++++++++++++++++++++ 17 files changed, 323 insertions(+), 27 deletions(-) create mode 100644 src/supervision/deps-exe/s6-svscanboot create mode 100644 src/supervision/s6-svscanboot.c diff --git a/.gitignore b/.gitignore index 3063492..545156b 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ /s6-cleanfifodir /s6-mkfifodir /s6-svscan +/s6-svscanboot /s6-supervise /s6-svc /s6-svscanctl diff --git a/INSTALL b/INSTALL index 340d2d2..2dd3f1f 100644 --- a/INSTALL +++ b/INSTALL @@ -6,8 +6,8 @@ Build Instructions - A POSIX-compliant C development environment - GNU make version 3.81 or later - - skalibs version 2.15.0.0 or later: https://skarnet.org/software/skalibs/ - - Recommended: execline version 2.9.9.0 or later: https://skarnet.org/software/execline/ + - skalibs version 2.15.0.1 or later: https://skarnet.org/software/skalibs/ + - Recommended: execline version 2.9.9.2 or later: https://skarnet.org/software/execline/ (You can disable this requirement at configure time, but will lose some functionality.) - Optional: nsss version 0.2.1.2 or later: https://skarnet.org/software/nsss/ diff --git a/NEWS b/NEWS index 2c61928..89b9bd0 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,11 @@ Changelog for s6. -In 2.15.0.1 +In 2.15.1.0 ----------- - Bugfixes. + - New command: s6-svscanboot, for a self-logging s6-svscan +that is not pid 1. In 2.15.0.0 diff --git a/doc/index.html b/doc/index.html index 53d0b49..d9b8918 100644 --- a/doc/index.html +++ b/doc/index.html @@ -89,7 +89,7 @@ requirement if you link against the shared version of the skalibs library.
  • (Optional, but really recommended for full functionality): execline version -2.9.9.1 or later. When s6 is built with execline support (which is the default), +2.9.9.2 or later. When s6 is built with execline support (which is the default), execline is a build-time requirement, and also a run-time requirement for certain binaries that spawn scripts interpreted with execlineb.
  • @@ -116,8 +116,8 @@ want nsswitch-like functionality:

    Download

    In some of the following examples, we'll assume that /command/s6-svscanboot -is the name of the script you are using to start s6-svscan. We will also assume +is the name of the program you are using to start s6-svscan. We will also assume that all of the s6 executables are available through the /command path. Adjust this accordingly.

    @@ -76,7 +74,7 @@ config file with telinit q.

    Example

    -
     SV:123456:respawn:/command/s6-svscanboot 
    +
    SV:123456:respawn:/command/s6-svscanboot -c /dev/console /run/service
    @@ -97,7 +95,7 @@ stop on runlevel [!2345] oom never respawn -exec /command/s6-svscanboot +exec /command/s6-svscanboot -c /dev/console /run/service @@ -149,7 +147,7 @@ file with kill -s HUP 1.

    Example

    -
     sv /command/s6-svscanboot "" on 
    +
     sv "/command/s6-svscanboot -c /dev/console /run/service" "" on 

    MacOS launchd

    diff --git a/doc/s6-svscan.html b/doc/s6-svscan.html index 5a09527..fc50f60 100644 --- a/doc/s6-svscan.html +++ b/doc/s6-svscan.html @@ -28,7 +28,7 @@ the root or a branch of a supervision tree.

    Interface

    -     s6-svscan [ -d notif ] [ -X consoleholder ] [ -C services_max ] [ -L name_max ] [ -t rescan ] scandir
    +     s6-svscan [ -d notif ] [ -X consoleholder ] [ -C services_max ] [ -L name_max ] [ -t rescan ] scandir
     

    diff --git a/package/deps-build b/package/deps-build index 071d42c..8678590 100644 --- a/package/deps-build +++ b/package/deps-build @@ -1,3 +1,3 @@ true true /package/prog/skalibs 2.15.0.1 libskarnet $usensss false /package/admin/nsss 0.2.1.2 libnsss -$useexecline $useexecline /package/admin/execline 2.9.9.1 libexecline +$useexecline $useexecline /package/admin/execline 2.9.9.2 libexecline diff --git a/package/deps.mak b/package/deps.mak index 4f58086..0771491 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -135,6 +135,7 @@ src/supervision/s6-svlisten1.o src/supervision/s6-svlisten1.lo: src/supervision/ src/supervision/s6-svok.o src/supervision/s6-svok.lo: src/supervision/s6-svok.c src/include/s6/supervise.h src/supervision/s6-svperms.o src/supervision/s6-svperms.lo: src/supervision/s6-svperms.c src/include/s6/supervise.h src/supervision/s6-svscan.o src/supervision/s6-svscan.lo: src/supervision/s6-svscan.c src/include/s6/config.h src/include/s6/supervise.h +src/supervision/s6-svscanboot.o src/supervision/s6-svscanboot.lo: src/supervision/s6-svscanboot.c src/include/s6/config.h src/supervision/s6-svscanctl.o src/supervision/s6-svscanctl.lo: src/supervision/s6-svscanctl.c src/include/s6/supervise.h src/supervision/s6-svstat.o src/supervision/s6-svstat.lo: src/supervision/s6-svstat.c src/include/s6/supervise.h src/supervision/s6-svunlink.o src/supervision/s6-svunlink.lo: src/supervision/s6-svunlink.c src/include/s6/supervise.h @@ -293,6 +294,8 @@ s6-svperms: EXTRA_LIBS := s6-svperms: src/supervision/s6-svperms.o ${LIBNSSS} -lskarnet s6-svscan: EXTRA_LIBS := ${SYSCLOCK_LIB} ${SPAWN_LIB} s6-svscan: src/supervision/s6-svscan.o -lskarnet +s6-svscanboot: EXTRA_LIBS := +s6-svscanboot: src/supervision/s6-svscanboot.o -lskarnet s6-svscanctl: EXTRA_LIBS := s6-svscanctl: src/supervision/s6-svscanctl.o ${LIBS6} -lskarnet s6-svstat: EXTRA_LIBS := ${SYSCLOCK_LIB} diff --git a/package/info b/package/info index 6eff7fb..d7c4218 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=s6 -version=2.15.0.1 +version=2.15.1.0 category=admin package_macro_name=S6 diff --git a/package/modes b/package/modes index d7b6953..e8a1fae 100644 --- a/package/modes +++ b/package/modes @@ -10,6 +10,7 @@ s6-ftrig-wait 0755 s6-cleanfifodir 0755 s6-mkfifodir 0755 s6-svscan 0755 +s6-svscanboot 0755 s6-supervise 0755 s6-svc 0755 s6-svlink 0755 diff --git a/package/targets.mak b/package/targets.mak index a607f2b..409f511 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -80,7 +80,7 @@ endif ifneq ($(EXECLINE_LIB),) LIB_DEFS += S6AUTO=s6auto S6AUTO_DESCRIPTION := The s6auto library (C helpers to create service directories) -BIN_TARGETS += s6-usertree-maker s6-instance-maker +BIN_TARGETS += s6-usertree-maker s6-instance-maker s6-svscanboot endif WRAP_ANY := diff --git a/src/alias/s6-alias.c b/src/alias/s6-alias.c index 568d29d..f530fe9 100644 --- a/src/alias/s6-alias.c +++ b/src/alias/s6-alias.c @@ -56,9 +56,17 @@ static void readproctitle (int argc, char const *const *argv) static void svscanboot (int argc, char const *const *argv) { + char const *newargv[6] ; + unsigned int m = 0 ; + newargv[m++] = S6_BINPREFIX "s6-svscanboot" ; + newargv[m++] = "-c" ; + newargv[m++] = "/dev/console" ; + newargv[m++] = "--" ; + newargv[m++] = "/service" ; + newargv[m++] = 0 ; (void)argc ; (void)argv ; - noboot("svscanboot") ; + xexec(newargv) ; } #endif diff --git a/src/supervision/deps-exe/s6-svscanboot b/src/supervision/deps-exe/s6-svscanboot new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/supervision/deps-exe/s6-svscanboot @@ -0,0 +1 @@ +-lskarnet diff --git a/src/supervision/s6-svscanboot.c b/src/supervision/s6-svscanboot.c new file mode 100644 index 0000000..8de924b --- /dev/null +++ b/src/supervision/s6-svscanboot.c @@ -0,0 +1,270 @@ +/* ISC license. */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define USAGE "s6-svscanboot [ -c devconsole ] [ -D catchalldir ] [ -m catchallmode ] [ -l catchalluser ] [ -o catchalloptions ] [ -d notif ] [ -C services_max ] [ -L name_max ] [ -t rescan ] scandir" +#define dieusage() strerr_dieusage(100, USAGE) + +enum golb_e +{ + GOLB_USER = 0x01, +} ; + +enum gola_e +{ + GOLA_CONSOLE, + GOLA_DIR, + GOLA_MODE, + GOLA_USER, + GOLA_OPTIONS, + GOLA_NOTIF, + GOLA_MAXSERVICES, + GOLA_MAXLEN, + GOLA_TIMEOUT, + GOLA_N +} ; + +int main (int argc, char const *const *argv) +{ + static gol_bool const rgolb[] = + { + { .so = 'u', .lo = "user", .clear = 0, .set = GOLB_USER }, + } ; + static gol_arg const rgola[] = + { + { .so = 'c', .lo = "console", .i = GOLA_CONSOLE }, + { .so = 'D', .lo = "catchall-directory", .i = GOLA_DIR }, + { .so = 'm', .lo = "catchall-mode", .i = GOLA_MODE }, + { .so = 'l', .lo = "catchall-user", .i = GOLA_USER }, + { .so = 'o', .lo = "catchall-options", .i = GOLA_OPTIONS }, + { .so = 'd', .lo = "notification-fd", .i = GOLA_NOTIF }, + { .so = 'C', .lo = "services-max", .i = GOLA_MAXSERVICES }, + { .so = 'L', .lo = "name-max", .i = GOLA_MAXLEN }, + { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT }, + } ; + unsigned int catchall_mode = 02700 ; + unsigned int fdconsole = 3 ; + unsigned int fdnotif = 0 ; + unsigned int servicesmax = 0 ; + unsigned int namemax = 0 ; + unsigned int timeout = 0 ; + uid_t uid = -1 ; + gid_t gid = -1 ; + stralloc sa = STRALLOC_ZERO ; + buffer b ; + int fd ; + unsigned int m = 0 ; + char const *newargv[14] ; + uint64_t wgolb = 0 ; + char const *wgola[GOLA_N] = { 0 } ; + unsigned int golc ; + char buf[4096] ; + char fmtc[UINT_FMT] ; + char fmtd[UINT_FMT] ; + char fmtC[UINT_FMT] ; + char fmtL[UINT_FMT] ; + char fmtt[UINT_FMT] ; + + PROG = "s6-svscanboot" ; + wgola[GOLA_OPTIONS] = "t" ; + + golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + if (!argc) dieusage() ; + + if (wgola[GOLA_MODE] && !uint0_oscan(wgola[GOLA_MODE], &catchall_mode)) + strerr_dief(100, "catchall-mode must be an (octal) unsigned integer") ; + if (wgola[GOLA_NOTIF]) + { + if (!uint0_scan(wgola[GOLA_NOTIF], &fdnotif)) + strerr_dief(100, "notification-fd", " must be an unsigned integer") ; + if (fdnotif < 3) + strerr_dief(100, "notification-fd", " must be 3 or greater") ; + if (fcntl(fdnotif, F_GETFD) == -1) + strerr_diefsys(111, "notification-fd", " sanity check failed") ; + if (fdnotif == 3) fdconsole = 4 ; + } + if (wgola[GOLA_MAXSERVICES]) + { + if (!uint0_scan(wgola[GOLA_MAXSERVICES], &servicesmax)) + strerr_dief(100, "services-max", " must be an unsigned integer") ; + if (servicesmax < 4) servicesmax = 4 ; + if (servicesmax > 160000) servicesmax = 160000 ; + } + if (wgola[GOLA_MAXLEN]) + { + if (!uint0_scan(wgola[GOLA_MAXLEN], &namemax)) + strerr_dief(100, "name-max", " must be an unsigned integer") ; + if (namemax < 11) namemax = 11 ; + if (namemax > 1019) namemax = 1019 ; + } + if (wgola[GOLA_TIMEOUT] && !uint0_scan(wgola[GOLA_TIMEOUT], &timeout)) + strerr_dief(100, "timeout", " must be an unsigned integer") ; + if (wgola[GOLA_USER] && geteuid()) + { + wgola[GOLA_USER] = 0 ; + strerr_warnw("ignoring catchall-user option when not root") ; + } + if (wgolb & GOLB_USER && (!wgola[GOLA_DIR] || wgola[GOLA_DIR][0] != '/')) + { + size_t namelen ; + size_t dirlen ; + char *logdir ; + char *x = getenv("XDG_RUNTIME_DIR") ; + if (!x) strerr_dienotset(100, "XDG_RUNTIME_DIR") ; + if (!wgola[GOLA_DIR]) wgola[GOLA_DIR] = "uncaught-logs" ; + dirlen = strlen(x) ; + namelen = strlen(wgola[GOLA_DIR]) ; + logdir = alloc(dirlen + namelen + 2) ; + if (!logdir) strerr_diefusys(111, "alloc") ; + memcpy(logdir, x, dirlen) ; + logdir[dirlen] = '/' ; + memcpy(logdir + dirlen + 1, wgola[GOLA_DIR], namelen + 1) ; + wgola[GOLA_DIR] = logdir ; + } + if (!wgola[GOLA_DIR]) wgola[GOLA_DIR] = "/run/uncaught-logs" ; + if (wgola[GOLA_USER]) + { + struct passwd *pw = getpwnam(wgola[GOLA_USER]) ; + if (!pw) strerr_diefsys(111, "getpwnam ", wgola[GOLA_USER]) ; + uid = pw->pw_uid ; + gid = pw->pw_gid ; + } + + if (mkdirp(wgola[GOLA_DIR], catchall_mode) == -1) + strerr_diefusys(111, "mkdir ", wgola[GOLA_DIR]) ; + if (chown(wgola[GOLA_DIR], uid, gid) == -1) + strerr_diefusys(111, "chown ", wgola[GOLA_DIR]) ; + if (chmod(wgola[GOLA_DIR], catchall_mode) == -1) + strerr_diefusys(111, "chmod ", wgola[GOLA_DIR]) ; + if (wgola[GOLA_DIR][0] != '/') + { + char *x = realpath(wgola[GOLA_DIR], 0) ; + if (!x) strerr_diefusys(111, "realpath ", wgola[GOLA_DIR]) ; + wgola[GOLA_DIR] = x ; + } + + size_t slen = strlen(argv[0]) ; + char fn[slen + 31] ; + memcpy(fn, argv[0], slen) ; + memcpy(fn + slen, "/s6-svscan-log", 15) ; + rm_rf(fn) ; + if (mkdirp2(fn, 02755) == -1) + strerr_diefusys(111, "mkdir ", fn) ; + + memcpy(fn + slen + 14, "/notification-fd", 17) ; + if (!openwritenclose_unsafe(fn, "3\n", 2)) + strerr_diefusys(111, "write to ", fn) ; + + memcpy(fn + slen + 14, "/run", 5) ; + fd = openc_create(fn) ; + buffer_init(&b, &buffer_write, fd, buf, 4096) ; + +#define diew() strerr_diefusys(111, "write to ", fn) ; + + if (buffer_puts(&b, + "#!" EXECLINE_SHEBANGPREFIX "execlineb -s1\n" + EXECLINE_EXTBINPREFIX "fdmove -c 1 2\n" + EXECLINE_EXTBINPREFIX "redirfd -rnb 0 fifo\n") == -1) diew() ; + if (wgola[GOLA_USER]) + { + if (!string_quotes(&sa, wgola[GOLA_USER])) + strerr_diefusys(111, "quote ", "catchall-user") ; + if (buffer_puts(&b, S6_EXTBINPREFIX "s6-setuidgid ") == -1 + || buffer_put(&b, sa.s, sa.len) == -1 + || buffer_put(&b, "\n", 1) == -1) diew() ; + sa.len = 0 ; + } + if (!string_quotes(&sa, wgola[GOLA_DIR])) + strerr_diefusys(111, "quote ", "catchall-directory") ; + if (buffer_puts(&b, + EXECLINE_EXTBINPREFIX "exec -c\n" + S6_EXTBINPREFIX "s6-log -bpd3 -- ") == -1 + || buffer_puts(&b, wgola[GOLA_OPTIONS]) == -1 + || buffer_put(&b, " ", 1) == -1 + || buffer_put(&b, sa.s, sa.len) == -1 + || buffer_putflush(&b, "\n", 1) == -1) diew() ; + sa.len = 0 ; + if (fchmod(fd, 0755) == -1) + strerr_diefusys(111, "chmod ", fn) ; + fd_close(fd) ; + + memcpy(fn + slen + 14, "/fifo", 6) ; + if (mkfifo(fn, 0600) == -1) + strerr_diefusys(111, "mkfifo ", fn) ; + + fd = open2("/dev/null", O_RDONLY) ; + if (fd == -1) strerr_diefusys(111, "open ", "/dev/null") ; + if (fd_move(0, fd) == -1) strerr_diefusys(111, "fd_move ", "/dev/null", " to ", "stdin") ; + if (wgola[GOLA_CONSOLE]) + { + fd = open2("/dev/console", O_WRONLY) ; + if (fd == -1) strerr_diefusys(111, "open ", "/dev/console") ; + if (fd_move(fdconsole, fd) == -1) strerr_diefusys(111, "fd_move ", "/dev/console") ; + } + else if (fd_copy(fdconsole, 2) == -1) strerr_diefusys(111, "fd_copy ", "stderr") ; + b.fd = open2(fn, O_RDONLY | O_NONBLOCK) ; + if (b.fd == -1) strerr_diefusys(111, "open ", fn, " for reading") ; + fd = open2(fn, O_WRONLY | O_NONBLOCK) ; + if (fd == -1) strerr_diefusys(111, "open ", fn, " for writing") ; + fd_close(b.fd) ; + if (ndelay_off(fd) == -1) strerr_diefusys(111, "ndelay_off ", fn) ; + if (fd_move(1, fd) == -1) strerr_diefusys(111, "fd_move ", fn, " to ", "stdout") ; + if (fd_copy(2, 1) == -1) strerr_diefusys(111, "copy ", "stdout", " to ", "stderr") ; + + fmtc[uint_fmt(fmtc, fdconsole)] = 0 ; + + newargv[m++] = S6_BINPREFIX "s6-svscan" ; + newargv[m++] = "-X" ; + newargv[m++] = fmtc ; + if (fdnotif) + { + fmtd[uint_fmt(fmtd, fdnotif)] = 0 ; + newargv[m++] = "-d" ; + newargv[m++] = fmtd ; + } + if (servicesmax) + { + fmtC[uint_fmt(fmtC, servicesmax)] = 0 ; + newargv[m++] = "-C" ; + newargv[m++] = fmtC ; + } + if (namemax) + { + fmtL[uint_fmt(fmtL, namemax)] = 0 ; + newargv[m++] = "-L" ; + newargv[m++] = fmtL ; + } + if (timeout) + { + fmtt[uint_fmt(fmtt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtt ; + } + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = 0 ; + + exec(newargv) ; + _exit(111) ; +} -- cgit v1.3.1