summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/index.html24
-rw-r--r--doc/quickstart.html142
-rw-r--r--doc/s6-linux-init-maker.html63
-rw-r--r--src/init/s6-linux-init-maker.c95
4 files changed, 252 insertions, 72 deletions
diff --git a/doc/index.html b/doc/index.html
index ad0d3b0..c3426e0 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -20,9 +20,9 @@
<h2> What is it&nbsp;? </h2>
<p>
- s6-linux-init is a set of minimalistic tools to create and manage
-the init process on a Linux system - i.e. the first process created
-by the kernel at boot time.
+ s6-linux-init is a set of minimalistic tools to create a
+<a href="http://skarnet.org/software/s6/">s6</a>-based init
+system, including a <tt>/sbin/init</tt> binary, on a Linux kernel.
</p>
<p>
@@ -61,11 +61,12 @@ and then you can <em>boot</em> your system on that init script.
</p>
<p>
- The listed dependencies are all <em>build-time</em> dependencies and also
-<em>boot-time</em> dependencies, i.e. you need the tools installed to build
-s6-linux-init and to boot your system. There are no <em>run-time</em>
-dependencies, except skalibs if you linked against the shared version of
-the library.
+ skalibs and execline are <em>build-time</em> dependencies.
+ There are no <em>run-time</em> dependencies.
+ And every listed package, save skalibs, is a <em>boot-time</em> dependency.
+ If you are using the shared version of the skalibs library,
+then skalibs also becomes a <em>run-time</em> and a
+<em>boot-time</em> dependency.
</p>
<h3> Licensing </h3>
@@ -101,6 +102,13 @@ the previous versions of s6-linux-init and the current one. </li>
<h2> Reference </h2>
+<h3> Quickstart guide and FAQ </h3>
+
+<p>
+ There is one,
+ <a href="quickstart.html">here</a>&nbsp;!
+</p>
+
<h3> Commands </h3>
<p>
diff --git a/doc/quickstart.html b/doc/quickstart.html
new file mode 100644
index 0000000..da47334
--- /dev/null
+++ b/doc/quickstart.html
@@ -0,0 +1,142 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-linux-init: quickstart and FAQ</title>
+ <meta name="Description" content="s6-linux-init: quickstart and FAQ" />
+ <meta name="Keywords" content="s6-linux-init installation quickstart faq" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> Quickstart and FAQ for s6-linux-init </h1>
+
+<h2> Quickstart </h2>
+
+<ul>
+ <li> Install all the s6-linux-init dependencies:
+ <ul>
+ <li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> </li>
+ <li> <a href="http://skarnet.org/software/execline/">execline</a> </li>
+ <li> <a href="http://skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> </li>
+ <li> <a href="http://skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> </li>
+ <li> <a href="http://skarnet.org/software/s6/">s6</a> </li>
+ </ul> </li>
+ <li> Install <a href="index.html">s6-linux-init</a> itself </li>
+ <li> Save your old <tt>/sbin/init</tt> binary </li>
+ <li> Save and remove your old <tt>/etc/s6-linux-init</tt> directory, if you have one </li>
+ <li> Make sure you have a <tt>/run</tt> directory </li>
+ <li> Write a machine initialization script in <tt>/etc/rc.init</tt> and
+ a machine shutdown script in <tt>/etc/rc.shutdown</tt>. Make them executable. </li>
+ <li> Check that your devtmpfs is automounted by your kernel at boot time. If it is not,
+add the <tt>-d 1</tt> option to the <tt>s6-linux-init-maker</tt> command line below. </li>
+ <li> As root, run: <pre>
+ rm -rf /tmp/s6-linux-init /tmp/init
+ s6-linux-init-maker /tmp/s6-linux-init &gt; /tmp/init
+ chmod 0700 /tmp/init
+ mv /tmp/s6-linux-init /etc/
+ mv /tmp/init /sbin/ </pre> </li>
+ <li> Reboot. </li>
+ <li> Congratulations! your machine is now running a s6-based init system. </li>
+</ul>
+
+<h2> FAQ </h2>
+
+<h4> Why is it so complicated to use s6 as an init process? It's much
+simpler with runit. </h4>
+
+<p>
+ Yes, runit is simpler, because it provides a simple
+<a href="http://smarden.org/runit/runit.8.html">runit</a> binary
+suitable as a <tt>/sbin/init</tt> program and calls scripts to
+handle the three stages of init. However, the runit design has a
+few perfectible points:
+</p>
+
+<ul>
+ <li> The one-time initialization is performed in <tt>/etc/runit/1</tt>, but
+the supervision tree is not run until <tt>/etc/runit/2</tt>, which means
+means that it is impossible to start supervised services during the
+one-time initialization. Early daemons such as <tt>udevd</tt>, for
+instance, have to remain unsupervised. </li>
+ <li> runit runs with its descriptors pointing to <tt>/dev/console</tt>,
+which means that error messages from the supervision tree, and uncaught
+logs, will be displayed on the system console; they are not saved beyond
+the console buffer capabilities. </li>
+ <li> The runit supervision tree is of height 3
+(runit, runsvdir, runsv), when height 2 is enough - some init
+systems, like sysvinit, systemd or launchd, even provide a
+supervision tree of height 1! (At the expense of complexity in the init
+process, of course.) Height 3 is a bit redundant, because the supervision
+capabilities of the root will be redundant with either those of the trunk
+or those of the branches. Its display is also aesthetically less pleasing than
+height 2: try out <tt>ps afuxww</tt> on a runit-based system.
+Yes, this point is extremely minor, but still deserves a mention. :-) </li>
+</ul>
+
+<p>
+ Running a s6-based init addresses those issues:
+</p>
+
+<ul>
+ <li> Save for the initial tmpfs mount, <em>all</em> of the machine
+initialization runs in the stage 2 script, i.e. <tt>/etc/rc.init</tt>,
+and the supervision tree is already available at that point. This
+makes it possible to start one-shot services as well as long-run
+services in the desired order while ensuring that every long-run service
+is properly supervised, i.e. it lays the ground for a proper dependency
+management system. </li>
+ <li> s6-linux-init solves the problem of uncaught logs in a clean
+way, and any error message from any process in the system is
+guaranteed to end up in a logging directory. The <em>only</em>
+exception is error messages from the catch-all logger process itself:
+those naturally go to <tt>/dev/console</tt>. </li>
+ <li> When s6-svscan runs as process 1, the supervision tree is of
+height 2, and <tt>ps afuxww</tt> looks clean. </li>
+</ul>
+
+<p>
+ To sum up, a s6-based init is cleaner than a runit-based
+init; it's a bit more complex to set up, but it organizes the system
+in a better way, without using more resources. And the goal of
+s6-linux-init is to make the setup more accessible.
+</p>
+
+<h4> My <tt>/etc/rc.init</tt> script is not printing anything! </h4>
+
+<p>
+ You probably gave the <tt>-r</tt> option to
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>, and
+your <tt>/etc/rc.init</tt>'s output is being logged into the
+<tt>/run/uncaught-logs</tt> directory instead of printed to
+<tt>/dev/console</tt>.
+</p>
+
+<h4> I want to run s6 in a container, and I just want to log
+to stdout/stderr, without this tmpfs and <tt>/dev/console</tt>
+stuff and
+without having a catch-all logger inside the container. Is it
+possible&nbsp;? </h4>
+
+<p>
+ Yes, it is possible, but then s6-linux-init may not be what you
+are looking for. For your case, it will be simpler to run s6-svscan
+directly!
+</p>
+
+<p>
+ If you are using
+<a href="https://www.docker.com/">Docker</a>, there is a
+<a href="https://github.com/just-containers/s6-overlay">s6-overlay</a>
+project specifically made for integrating s6 into Docker images.
+</p>
+
+</body>
+</html>
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html
index cdf617e..530cd41 100644
--- a/doc/s6-linux-init-maker.html
+++ b/doc/s6-linux-init-maker.html
@@ -49,6 +49,7 @@ machine</em> - else the scripts will crash.
[ -u <em>log_user</em> ] \
[ -g <em>early_getty</em> ] \
[ -2 <em>stage2</em> ] \
+ [ -r ] \
[ -3 <em>stage3</em> ] \
[ -p <em>initial_path</em> ] \
[ -m <em>initial_umask</em> ] \
@@ -74,7 +75,7 @@ declared as <em>basedir</em>. Be careful: it contains fifos, files with
precise uid/gid permissions, and files with non-standard access rights,
so be sure to copy it verbatim. The
<a href="http://skarnet.org/software/s6-portable-utils/s6-hiercopy.html">s6-hiercopy</a>
-tool can do it, as well as the GNU or busybox <tt>cp -a</tt> command.
+tool can do it, as well as the GNU or busybox <tt>cp -a</tt> or <tt>mv</tt> commands.
</p>
<p>
@@ -133,11 +134,10 @@ system. When <em>stage2</em> is executed, the machine state is as follows:
<ul>
<li> <em>stage2</em>'s working directory is <tt>/</tt> and its stdin
-is <tt>/dev/null</tt>. <em>stage2</em>'s
-stdout and stderr both point to the pipe to the catch-all logger, so
-unless redirected, <em>stage2</em>'s output will be logged into the
-<tt><em>tmpfsdir/uncaught-logs</em></tt> directory. </li>
- <li> The system has a valid device directory mounted on <tt>/dev</tt>.
+is <tt>/dev/null</tt>. Its
+stdout and stderr both point either to <tt>/dev/console</tt> or to the pipe
+to the catch-all logger, depending on the <tt>-r</tt> option. </li>
+ <li> The system has a valid device directory mounted on <tt>/dev</tt>. </li>
<li> Depending on the kernel boot command line, the root filesystem
may be in read-only mode. </li>
<li> There is a tmpfs available for root only in <em>tmpfsdir</em>. </li>
@@ -227,6 +227,14 @@ 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>&nbsp;: 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>-3</tt>&nbsp;<em>stage3</em>&nbsp;: <em>stage3</em> is
the location of the stage 3 script that will be run at the end of
the machine lifetime, when s6-svscan is told to terminate.
@@ -235,8 +243,14 @@ It must be absolute. Default is
<li> <tt>-p</tt>&nbsp;<em>initial_path</em>&nbsp;: the value to
set the PATH environment variable to, for all the starting processes.
-This will be done as early as possible in <em>stage1</em>. Default is
-the value that has been compiled in
+This will be done as early as possible in <em>stage1</em>. It is
+absolutely necessary for
+<a href="http://skarnet.org/software/execline/">execline</a>,
+<a href="http://skarnet.org/software/s6/">s6</a>,
+<a href="http://skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> and
+<a href="http://skarnet.org/software/s6-linux-utils/">s6-linux-utils</a>
+binaries to be accessible via <em>initial_path</em>, else the machine
+will not boot. Default is the value that has been compiled in
<a href="http://skarnet.org/software/skalibs/">skalibs</a> via the
<tt>--with-default-path</tt> configure option, i.e. by default
<strong><tt>/usr/bin:/bin</tt></strong>. </li> <p />
@@ -272,5 +286,38 @@ The TZ variable, for instance, is a good candidate to be set in
the global environment. </li> <p />
</ul>
+<h2> Notes </h2>
+
+<p>
+ The difficult parts of
+<a href="http://skarnet.org/software/s6/s6-svscan-1.html">running
+s6-svscan as process 1</a> are:
+</p>
+
+<ul>
+ <li> The fact that the supervision tree requires writable directories,
+so in order to accommodate read-only root filesystems, there needs to
+be a tmpfs mounted before s6-svscan is run. </li>
+ <li> The catch-22 coming for the need to redirect the supervision
+tree's output away from <tt>/dev/console</tt> (which is fine for a
+first process invocation but impractical for log management of a
+whole process tree) and into a logger that is itself managed by the
+supervision tree it's reading data from. </li>
+</ul>
+
+<p>
+ The main benefit of s6-linux-init-maker is that it automates those
+parts. This means that it has been designed for <em>real hardware</em>
+where the above issues apply.
+ If you are building an init system for a
+virtual machine, a container, or anything similar that does not
+have the <tt>/dev/console</tt> issue or the read-only rootfs issue,
+you will probably not reap much benefit from using s6-linux-init-maker:
+you could probably invoke
+<a href="http://skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+directly as your process 1, or build a script by hand, which
+would result in a simpler init with less dependencies.
+</p>
+
</body>
</html>
diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c
index b897115..007bd94 100644
--- a/src/init/s6-linux-init-maker.c
+++ b/src/init/s6-linux-init-maker.c
@@ -18,27 +18,23 @@
#include <skalibs/sgetopt.h>
#include <skalibs/skamisc.h>
#include <execline/config.h>
-#include <s6-portable-utils/config.h>
-#include <s6-linux-utils/config.h>
#include <s6/config.h>
-#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -g early_getty_cmd ] [ -2 stage2_script ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -e initial_envvar ... ] dir"
+#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -g early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -e initial_envvar ... ] dir"
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "stralloc_catb") ;
+#define BANNER "*\n* init created by s6-linux-init-maker\n* see http://skarnet.org/software/s6-linux-init/\n*\n"
+
#define CRASH_SCRIPT \
"#!" EXECLINE_EXTBINPREFIX "execlineb -P\n\n" \
-EXECLINE_EXTBINPREFIX "redirfd -r 0 /dev/console\n" \
-EXECLINE_EXTBINPREFIX "redirfd -w 1 /dev/console\n" \
-EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" \
-EXECLINE_EXTBINPREFIX "foreground { " \
-S6_PORTABLE_UTILS_EXTBINPREFIX "s6-echo -- " \
+"redirfd -r 0 /dev/console\n" \
+"redirfd -w 1 /dev/console\n" \
+"fdmove -c 2 1\n" \
+"foreground { s6-echo -- " \
"\"s6-svscan crashed. Dropping to an interactive shell.\" }\n" \
"/bin/sh -i\n"
-#define BANNER1 "s6-init: stage 1"
-#define BANNER2 "s6-init: stage 2"
-
static char const *slashrun = "/run" ;
static char const *robase = "/etc/s6-linux-init" ;
static char const *init_script = "/etc/rc.init" ;
@@ -51,6 +47,7 @@ static gid_t uncaught_logs_gid = 65534 ;
static unsigned int initial_umask = 022 ;
static unsigned int timestamp_style = 1 ;
static unsigned int slashdev_style = 2 ;
+static int redirect_stage2 = 0 ;
typedef int writetobuf_func_t (buffer *) ;
typedef writetobuf_func_t *writetobuf_func_t_ref ;
@@ -70,12 +67,12 @@ static int s6_svscan_log_script (buffer *b)
char fmt[UINT64_FMT] ;
if (buffer_puts(b,
"#!" EXECLINE_EXTBINPREFIX "execlineb -P\n\n"
- EXECLINE_EXTBINPREFIX "redirfd -rnb 0 fifo\n"
- S6_EXTBINPREFIX "s6-applyuidgid -u ") < 0
+ "redirfd -rnb 0 fifo\n"
+ "s6-applyuidgid -u ") < 0
|| buffer_put(b, fmt, uint64_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, " --\n" S6_EXTBINPREFIX "s6-log -bp -- ") < 0
+ || buffer_puts(b, " --\ns6-log -bp -- ") < 0
|| buffer_puts(b, timestamp_style & 1 ? "t " : "") < 0
|| buffer_puts(b, timestamp_style & 2 ? "T " : "") < 0) return 0 ;
if (!string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ;
@@ -240,20 +237,17 @@ static int make_init_script (buffer *b)
satmp.len = sabase ;
if (buffer_put(b, "\n", 1) < 0
|| buffer_puts(b, bindir) < 0
- || buffer_puts(b, "/cd /\n"
- EXECLINE_EXTBINPREFIX "umask 0") < 0
+ || buffer_puts(b, "/cd /\numask 0") < 0
|| buffer_put(b, fmt, uint_ofmt(fmt, initial_umask)) < 0
- || buffer_puts(b, "\n"
- EXECLINE_EXTBINPREFIX "if { "
- S6_PORTABLE_UTILS_EXTBINPREFIX "s6-echo -- \"" BANNER1 "\" }\n"
- EXECLINE_EXTBINPREFIX "if { "
- S6_LINUX_UTILS_EXTBINPREFIX "s6-mount -nwt tmpfs -o mode=0755 tmpfs ") < 0
+ || buffer_puts(b, "\nif { s6-echo -- ") < 0)
+ || !string_quote(&satmp, BANNER, sizeof(BANNER) - 1) < 0) return 0 ;
+ if (buffer_puts(b, satmp.s, satmp.len) < 0) goto err ;
+ satmp.len = sabase ;
+ if (buffer_puts(b, " }\nif { s6-mount -nwt tmpfs -o mode=0755 tmpfs ") < 0
|| !string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ;
pos = satmp.len ;
if (buffer_put(b, satmp.s + sabase, pos - sabase) < 0
- || buffer_puts(b, " }\n"
- EXECLINE_EXTBINPREFIX "if { "
- S6_PORTABLE_UTILS_EXTBINPREFIX "s6-hiercopy ") < 0
+ || buffer_puts(b, " }\nif { s6-hiercopy ") < 0
|| !string_quote(&satmp, robase, str_len(robase))) return 0 ;
pos2 = satmp.len ;
if (buffer_put(b, satmp.s + pos, pos2 - pos) < 0
@@ -262,42 +256,30 @@ static int make_init_script (buffer *b)
|| buffer_puts(b, " }\n") < 0) goto err ;
if (slashdev_style == 1)
{
- if (buffer_puts(b,
- EXECLINE_EXTBINPREFIX "if { "
- S6_LINUX_UTILS_EXTBINPREFIX "s6-mount -nt devtmpfs dev /dev }\n") < 0)
- goto err ;
+ if (buffer_puts(b, "if { s6-mount -nt devtmpfs dev /dev }\n") < 0) goto err ;
}
- if (buffer_puts(b,
- EXECLINE_EXTBINPREFIX "redirfd -r 0 /dev/null\n"
- S6_EXTBINPREFIX "s6-envdir -I -- ") < 0
+ if (buffer_puts(b, "redirfd -r 0 /dev/null\ns6-envdir -I -- ") < 0
|| buffer_put(b, satmp.s + pos, pos2 - pos) < 0
- || buffer_puts(b, "/env\n"
- EXECLINE_EXTBINPREFIX "background\n{\n "
- S6_EXTBINPREFIX "s6-setsid --\n "
- EXECLINE_EXTBINPREFIX "redirfd -w 2 ") < 0
- || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
- || buffer_puts(b, "/service/s6-svscan-log/fifo\n "
- EXECLINE_EXTBINPREFIX "if { "
- S6_PORTABLE_UTILS_EXTBINPREFIX "s6-echo -- \"" BANNER2 "\" }\n "
- EXECLINE_EXTBINPREFIX "fdmove -c 1 2\n ") < 0
- || !string_quote(&satmp, init_script, str_len(init_script))
+ || buffer_puts(b, "/env\nbackground\n{\n s6-setsid --\n ") < 0) goto err ;
+ if (redirect_stage2)
+ {
+ if (buffer_puts(b, "redirfd -w 2 ") < 0
+ || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b, "/service/s6-svscan-log/fifo\n fdmove -c 1 2\n ") < 0) goto err ;
+ }
+ else
+ {
+ if (buffer_puts(b, "redirfd -w 3 ") < 0
+ || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b, "/service/s6-svscan-log/fifo\n fdclose 3\n ") < 0) goto err ;
+ }
+ if (!string_quote(&satmp, init_script, str_len(init_script))
|| buffer_put(b, satmp.s + pos2, satmp.len - pos2) < 0
- || buffer_puts(b, "\n}\n"
- EXECLINE_EXTBINPREFIX "unexport !\n"
- EXECLINE_EXTBINPREFIX "redirfd -wnb 1 ") < 0
+ || buffer_puts(b, "\n}\nunexport !\nredirfd -wnb 1 ") < 0
|| buffer_put(b, satmp.s + sabase, pos - sabase) < 0
- || buffer_puts(b,
- "/service/s6-svscan-log/fifo\n"
- EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n"
- EXECLINE_EXTBINPREFIX "cd ") < 0
+ || buffer_puts(b, "/service/s6-svscan-log/fifo\nfdmove -c 2 1\ncd ") < 0
|| buffer_put(b, satmp.s + sabase, pos - sabase) < 0
- || buffer_puts(b, "/service\n") < 0) goto err ;
- if (sizeof(S6_EXTBINPREFIX) > 1)
- {
- if (buffer_puts(b, EXECLINE_EXTBINPREFIX "exec -a s6-svscan --\n") < 0)
- goto err ;
- }
- if (buffer_puts(b, S6_EXTBINPREFIX "s6-svscan -t0\n") < 0) goto err ;
+ || buffer_puts(b, "/service\ns6-svscan -t0\n") < 0) goto err ;
return 1 ;
err:
satmp.len = sabase ;
@@ -313,7 +295,7 @@ int main (int argc, char const *const *argv)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:3:p:m:t:d:e:", &l) ;
+ register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:r3:p:m:t:d:e:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -323,6 +305,7 @@ int main (int argc, char const *const *argv)
case 'u' : catchall_user = l.arg ; break ;
case 'g' : early_getty = l.arg ; break ;
case '2' : init_script = l.arg ; break ;
+ case 'r' : redirect_stage2 = 1 ; break ;
case '3' : shutdown_script = l.arg ; break ;
case 'p' : initial_path = l.arg ; break ;
case 'm' : if (!uint0_oscan(l.arg, &initial_umask)) dieusage() ; break ;