diff options
-rw-r--r-- | doc/s6-linux-init-maker.html | 81 | ||||
-rw-r--r-- | src/init/s6-linux-init-maker.c | 50 | ||||
-rw-r--r-- | src/init/s6-linux-init.c | 16 | ||||
-rw-r--r-- | src/state/s6-linux-init-shutdown.c | 1 | ||||
-rw-r--r-- | src/state/s6-linux-init-shutdownd.c | 43 |
5 files changed, 75 insertions, 116 deletions
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html index 4c0b51d..6f3d204 100644 --- a/doc/s6-linux-init-maker.html +++ b/doc/s6-linux-init-maker.html @@ -49,20 +49,18 @@ machine</em> - else the scripts will crash. <pre> s6-linux-init-maker \ [ -c <em>basedir</em> ] \ - [ -l <em>tmpfsdir</em> ] \ [ -b <em>execline_bindir</em> ] \ [ -u <em>log_uid</em> -g <em>log_gid</em> | -U ] \ [ -G <em>early_getty</em> ] \ - [ -2 <em>initscript</em> ] \ - [ -r ] \ - [ -Z ] <em>shutdownscript</em> \ + [ -1 ] \ + [ -L ] \ [ -p <em>initial_path</em> ] \ [ -m <em>initial_umask</em> ] \ [ -t <em>timestamp_style</em> ] \ [ -d <em>dev_style</em> ] \ [ -s <em>env_store</em> ] \ [ -e <em>initial_envvar</em> ] ... \ - [ -n ] \ + [ -E <em>stage2_envvar</em> ] ... \ [ -q ] <em>finalsleeptime</em> <em>dir</em> </pre> @@ -87,18 +85,28 @@ tool can do it, as well as the GNU or busybox <tt>cp -a</tt> or <tt>mv</tt> comm </p> <p> - The <tt><em>basedir</em>/init</tt> script -is then suitable as a "stage 1" init program, i.e. the first program -run by the kernel. The administrator should make a symbolic link -from <tt>/sbin/init</tt> to <tt><em>basedir</em>/init</tt>; the -machine will then be ready to boot + The <tt><em>basedir</em>/bin</tt> directory contains scripts, or +links to programs, that are suitable as System V-compatible programs +of the same name; the administrator should copy them to (or symlink +them from) a place where those programs are usually found, typically +<tt>/sbin</tt>. +</p> + +<p> + In particular, the <tt><em>basedir</em>/bin/init</tt> script +suitable as a "stage 1" init program, i.e. the first program +run by the kernel (possibly after an initramfs execution). +Once this script is copied to, or symlinked from, +<tt>/sbin/init</tt>, the machine will be ready to boot on the +new s6-based system. </p> <h2> Boot sequence </h2> <p> - When the kernel boots, it runs the <tt><em>basedir</em>/init</tt> script, -also known as <em>stage 1</em>. and this is what happens: + When the kernel boots, it may run an initramfs first, but in any +case it then runs the <tt><em>basedir</em>/init</tt> script, +also known as <em>stage 1</em>. This is what happens during stage 1: </p> <ul> @@ -246,11 +254,6 @@ created directory <em>dir</em> to <em>basedir</em>. <em>basedir</em> must be absolute. Default is <strong><tt>/etc/s6-linux-init</tt></strong>. </li> <p /> - <li> <tt>-l</tt> <em>tmpfsdir</em> : at boot time, a tmpfs will -be mounted on <em>tmpfsdir</em>. The directory should already exist in -the root filesystem, and be empty. <em>tmpfsdir</em> must be absolute. Default is -<strong><tt>/run</tt></strong>. </li> <p /> - <li> <tt>-b</tt> <em>execline_bindir</em> : init is run by the kernel without a PATH, and since it is a script, it is necessary to tell it where to find the @@ -285,27 +288,13 @@ should be a getty, to allow logins even if <em>stage2</em> fails. <tt>"/sbin/getty 38400 tty1"</tt>. By default, no early service is defined. </li> <p /> - <li> <tt>-2</tt> <em>initscript</em> : <em>initscript</em> is -the location of the stage 2 script that will be run when the -system has an operational supervision tree. It must be absolute. Default is -<strong><tt>/etc/rc.init</tt></strong>. </li> <p /> - - <li> <tt>-r</tt> : redirect. By default, <em>stage2</em> is -run with stdout and stderr pointing to <tt>/dev/console</tt>, so that -users can see what init scripts print. However, it may conflict -with an early getty, or be undesirable for other reasons. The -<tt>-r</tt> option redirects <em>stage2</em>'s stdout and stderr -to the catch-all logger, so the output will be made available -in the <tt><em>tmpfsdir</em>/uncaught-logs</tt> directory. </li> <p /> - - <li> <tt>-Z</tt> <em>shutdownscript</em> : -<em>shutdownscript</em> is the location of the script that will be -run when s6-svscan receives a signal that tells it to stop the -machine, before it executes into the final shutdown sequence. It must be -absolute. Default is <strong><tt>/etc/rc.shutdown</tt></strong>. -Note that this script is run with its stdout and stderr -redirected to the <tt><em>tmpfsdir</em>/uncaught-logs</tt> logging -directory, so its output will not appear on the system's console. </li> <p /> + <li> <tt>-1</tt> : make it so that all the messages that are +sent to the catch-all logger (i.e. all the error messages that are not +caught by a dedicated logger, as well as the output from <em>stage2</em>) +are also copied to <tt>/dev/console</tt>. This is generally useful to +debug a system at a glance, but if a failing program keeps sending +error messages, it may interfere with comfortable usage of an early +getty. </li> <li> <tt>-p</tt> <em>initial_path</em> : the value to set the PATH environment variable to, for all the starting processes. @@ -360,16 +349,18 @@ will adjust the global environment directory in <em>dir</em>/env. to make sure that <em>VAR</em> does not appear in the global environment, or of the form <em>VAR=VALUE</em>, to add an environment variable <em>VAR</em> with the value <em>VALUE</em>. +The global environment is the environment that every supervised +process (as well as the <em>stage2</em> script) will run with, +so it will be inherited by default by every process running on +the system. The TZ variable, for instance, is a good candidate to be set in the global environment. </li> <p /> - <li> <tt>-n</tt> : tells s6-linux-init-maker that the init script -is going to run in a container, as pid 1 in a non-root namespace. -This modifies the <tt>.s6-svscan/finish</tt>, <tt>.s6-svscan/SIGHUP</tt> -and <tt>.s6-svscan/SIGINT</tt> scripts slightly, in order to provide -adequate functionality when the containerized system is asked to -shutdown. Do not add this option if the init script is going to run -in the root pid namespace. </li> <p /> + <li> <tt>-E</tt> <em>stage2_envvar</em> : same behaviour +as the <tt>-e</tt> option, except that every declared +<em>stage2_envvar</em> will be put in the environment run by the +<em>stage2</em> script. They will not be put in the global +environment. </li> <li> <tt>-q</tt> <em>finalsleeptime</em> : when the machine shuts down, all processes that have not already been killed during diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c index 48c95c6..ede9a52 100644 --- a/src/init/s6-linux-init-maker.c +++ b/src/init/s6-linux-init-maker.c @@ -22,7 +22,7 @@ #include "defaults.h" #include "initctl.h" -#define USAGE "s6-linux-init-maker [ -c basedir ] [ -b execline_bindir ] [ -u log_uid -g log_gid | -U ] [ -G early_getty_cmd ] [ -r ] [ -L ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d slashdev ] [ -s env_store ] [ -e initial_envvar ... ] [ -q default_grace_time ] dir" +#define USAGE "s6-linux-init-maker [ -c basedir ] [ -b execline_bindir ] [ -u log_uid -g log_gid | -U ] [ -G early_getty_cmd ] [ -1 ] [ -L ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d slashdev ] [ -s env_store ] [ -e initial_envvar ... ] [ -q default_grace_time ] dir" #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") ; @@ -48,7 +48,7 @@ static gid_t uncaught_logs_gid = 0 ; static unsigned int initial_umask = 0022 ; static unsigned int timestamp_style = 1 ; static unsigned int finalsleep = 3000 ; -static int redirect_stage2 = 0 ; +static int console = 0 ; static int logouthookd = 0 ; typedef int writetobuf_func_t (buffer *, void *) ; @@ -102,19 +102,31 @@ static int s6_svscan_log_script (buffer *b, void *data) { char fmt[UINT64_FMT] ; (void)data ; - return put_shebang(b) - && buffer_puts(b, - "redirfd -w 2 /dev/console\n" - "redirfd -w 1 /dev/null\n" - "redirfd -rnb 0 " LOGGER_FIFO "\n" - "s6-applyuidgid -u ") >= 0 - && buffer_put(b, fmt, uid_fmt(fmt, uncaught_logs_uid)) >= 0 - && buffer_puts(b, " -g ") >= 0 - && buffer_put(b, fmt, gid_fmt(fmt, uncaught_logs_gid)) >= 0 - && buffer_puts(b, " --\ns6-log -bpd3 -- ") >= 0 - && buffer_puts(b, timestamp_style & 1 ? "t " : "") >= 0 - && buffer_puts(b, timestamp_style & 2 ? "T " : "") >= 0 - && buffer_puts(b, S6_LINUX_INIT_TMPFS "/" UNCAUGHT_DIR "\n") >= 0 ; + if (!put_shebang(b) + || buffer_puts(b, + "redirfd -w 2 /dev/console\n" + "redirfd -w 1 /dev/") < 0 + || buffer_puts(b, console ? "console" : "null") < 0 + || buffer_puts(b, "\n" + "redirfd -rnb 0 " LOGGER_FIFO "\n" + "s6-applyuidgid -u ") < 0 + || buffer_put(b, fmt, uid_fmt(fmt, uncaught_logs_uid)) < 0 + || buffer_puts(b, " -g ") < 0 + || buffer_put(b, fmt, gid_fmt(fmt, uncaught_logs_gid)) < 0 + || buffer_puts(b, " --\ns6-log -bpd3 -- ") < 0) + return 0 ; + if (console) + { + if (timestamp_style & 1 && buffer_puts(b, "t ") < 0 + || timestamp_style & 2 && buffer_puts(b, "T ") < 0 + || buffer_puts(b, "1 ") < 0) + return 0 ; + } + if (timestamp_style & 1 && buffer_puts(b, "t ") < 0 + || timestamp_style & 2 && buffer_puts(b, "T ") < 0 + || buffer_puts(b, S6_LINUX_INIT_TMPFS "/" UNCAUGHT_DIR "\n") < 0) + return 0 ; + return 1 ; } static int logouthookd_script (buffer *b, void *data) @@ -177,10 +189,6 @@ static inline int stage1_script (buffer *b) if (buffer_puts(b, " -m 00") < 0 || buffer_put(b, fmt, uint_ofmt(fmt, initial_umask)) < 0) return 0 ; } - if (redirect_stage2) - { - if (buffer_puts(b, " -r") < 0) return 0 ; - } if (initial_path) { if (buffer_puts(b, " -p ") < 0 @@ -399,7 +407,7 @@ int main (int argc, char const *const *argv, char const *const *envp) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "c:b:u:g:UG:rLp:m:t:d:s:e:E:q:", &l) ; + int opt = subgetopt_r(argc, argv, "c:b:u:g:UG:1Lp:m:t:d:s:e:E:q:", &l) ; if (opt == -1) break ; switch (opt) { @@ -417,7 +425,7 @@ int main (int argc, char const *const *argv, char const *const *envp) if (!uint0_scan(x, &uncaught_logs_gid)) strerr_dieinvalid(100, "GID") ; } case 'G' : early_getty = l.arg ; break ; - case 'r' : redirect_stage2 = 1 ; break ; + case '1' : console = 1 ; break ; case 'L' : logouthookd = 1 ; break ; case 'p' : initial_path = l.arg ; break ; case 'm' : if (!uint0_oscan(l.arg, &initial_umask)) dieusage() ; break ; diff --git a/src/init/s6-linux-init.c b/src/init/s6-linux-init.c index 6758682..aeddbac 100644 --- a/src/init/s6-linux-init.c +++ b/src/init/s6-linux-init.c @@ -23,12 +23,12 @@ #include "defaults.h" #include "initctl.h" -#define USAGE "s6-linux-init [ -r ] [ -c basedir ] [ -p initpath ] [ -s envdumpdir ] [ -m umask ] [ -d devtmpfs ]" +#define USAGE "s6-linux-init [ -c basedir ] [ -p initpath ] [ -s envdumpdir ] [ -m umask ] [ -d devtmpfs ]" #define dieusage() strerr_dieusage(100, USAGE) #define BANNER "\n s6-linux-init version " S6_LINUX_INIT_VERSION "\n\n" -static inline void run_stage2 (char const *basedir, char const **argv, unsigned int argc, char const *const *envp, size_t envlen, stralloc *envmodifs, int redirect) +static inline void run_stage2 (char const *basedir, char const **argv, unsigned int argc, char const *const *envp, size_t envlen, stralloc *envmodifs) { size_t dirlen = strlen(basedir) ; char const *childargv[argc + 2] ; @@ -47,10 +47,10 @@ static inline void run_stage2 (char const *basedir, char const **argv, unsigned childargv[argc + 1] = 0 ; setsid() ; fd_close(1) ; - if (open(LOGFIFO, O_WRONLY) != 1) /* blocks */ + if (open(LOGFIFO, O_WRONLY) != 1) /* blocks until catch-all logger is up */ strerr_diefu1sys(111, "open " LOGFIFO " for writing") ; - if (fd_copy(1 + redirect, 2 - redirect) == -1) - strerr_diefu1sys(111, "redirect output file descriptor") ; + if (fd_copy(2, 1) == -1) + strerr_diefu1sys(111, "fd_copy stdout to stderr") ; xpathexec_r(childargv, envp, envlen, envmodifs->s, envmodifs->len) ; } @@ -62,7 +62,6 @@ int main (int argc, char const **argv, char const *const *envp) char const *slashdev = 0 ; char const *envdumpdir = 0 ; stralloc envmodifs = STRALLOC_ZERO ; - int redirect = 0 ; PROG = "s6-linux-init" ; if (getpid() != 1) @@ -76,11 +75,10 @@ int main (int argc, char const **argv, char const *const *envp) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "rc:p:s:m:d:", &l) ; + int opt = subgetopt_r(argc, argv, "c:p:s:m:d:", &l) ; if (opt == -1) break ; switch (opt) { - case 'r' : redirect = 1 ; break ; case 'c' : basedir = l.arg ; break ; case 'p' : path = l.arg ; break ; case 's' : envdumpdir = l.arg ; break ; @@ -160,7 +158,7 @@ int main (int argc, char const **argv, char const *const *envp) } pid = fork() ; if (pid == -1) strerr_diefu1sys(111, "fork") ; - if (!pid) run_stage2(basedir, argv, argc, newenvp, !!path, &envmodifs, redirect) ; + if (!pid) run_stage2(basedir, argv, argc, newenvp, !!path, &envmodifs) ; if (fd_copy(2, 1) == -1) strerr_diefu1sys(111, "redirect output file descriptor") ; xpathexec_r(newargv, newenvp, !!path, envmodifs.s, envmodifs.len) ; diff --git a/src/state/s6-linux-init-shutdown.c b/src/state/s6-linux-init-shutdown.c index eb65d1d..bb0391d 100644 --- a/src/state/s6-linux-init-shutdown.c +++ b/src/state/s6-linux-init-shutdown.c @@ -8,7 +8,6 @@ #include <errno.h> #include <time.h> #include <utmpx.h> -#include <sys/reboot.h> #include <skalibs/uint32.h> #include <skalibs/types.h> diff --git a/src/state/s6-linux-init-shutdownd.c b/src/state/s6-linux-init-shutdownd.c index d4ecd4b..e330ac6 100644 --- a/src/state/s6-linux-init-shutdownd.c +++ b/src/state/s6-linux-init-shutdownd.c @@ -45,30 +45,11 @@ static inline void prepare_shutdown (char c, unsigned int *what, tain_t *deadlin tain_unpack(pack, deadline) ; uint32_unpack_big(pack + TAIN_PACK, &u) ; if (u && u <= 300000) *grace_time = u ; - *what = byte_chr(" hpr", c, 4) ; -} - -static inline void change_runlevels (char c) -{ - pid_t pid = doublefork() ; - if (pid == -1) - strerr_warnwu1sys("doublefork for runlevel change") ; - if (pid) - { - size_t basedirlen = strlen(basedir) ; - char fn[basedirlen + sizeof("/scripts/runlevel")] ; - char s[2] = { c, 0 } ; - char const *cargv[3] = { fn, s, 0 } ; - PROG = "s6-linux-init-shutdownd (grandchild)" ; - memcpy(fn, basedir, basedirlen) ; - memcpy(fn + basedirlen, "/scripts/runlevel", sizeof("/scripts/runlevel")) ; - xpathexec_run(cargv[0], cargv, (char const *const *)environ) ; - } + *what = 1 + byte_chr("hpr", c, 3) ; } static inline void handle_stdin (unsigned int *what, tain_t *deadline, unsigned int *grace_time) { - char rl = 0 ; for (;;) { char c ; @@ -84,23 +65,7 @@ static inline void handle_stdin (unsigned int *what, tain_t *deadline, unsigned break ; case 'c' : *what = 0 ; - rl = 0 ; - tain_add_g(deadline, &tain_infinite_relative) ; - break ; - case 'S' : - *what = 4 ; - tain_copynow(deadline) ; - break ; - case '0' : - case '1' : - case '2' : - case '3' : - case '4' : - case '5' : - case '6' : - *what = 0 ; tain_add_g(deadline, &tain_infinite_relative) ; - rl = c ; break ; default : { @@ -110,12 +75,11 @@ static inline void handle_stdin (unsigned int *what, tain_t *deadline, unsigned break ; } } - if (rl) change_runlevels(rl) ; } static inline void prepare_stage4 (char const *bindir, char const *basedir, unsigned int what) { - static char const *table[4] = { "single", "halt", "poweroff", "reboot" } ; + static char const *table[3] = { "halt", "poweroff", "reboot" } ; stralloc sa = STRALLOC_ZERO ; buffer b ; char buf[512] ; @@ -133,7 +97,7 @@ static inline void prepare_stage4 (char const *bindir, char const *basedir, unsi strerr_diefu1sys(111, "string_quote") ; if (buffer_put(&b, sa.s, sa.len) == -1 || buffer_puts(&b, "/bin/" STAGE4 " ") == -1 - || buffer_puts(&b, table[what]) == -1 + || buffer_puts(&b, table[what-1]) == -1 || buffer_putsflush(&b, "\n") == -1) strerr_diefu2sys(111, "write to ", STAGE4_FILE ".new") ; stralloc_free(&sa) ; @@ -213,7 +177,6 @@ int main (int argc, char const *const *argv) handle_stdin(&what, &deadline, &grace_time) ; } - if (what == 4) what = 0 ; /* Stage 3 */ |