summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2019-04-26 15:52:54 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2019-04-26 15:52:54 +0000
commit1bfba3b0be32306b078f5ee527b864e758b2c77b (patch)
tree155db6f3c01becd24d422a2e55582e222ad6a89e
parent9e6d0f168bf59df9cd829d6ebe63fb08ea9ae01e (diff)
downloads6-linux-init-1bfba3b0be32306b078f5ee527b864e758b2c77b.tar.xz
Make a single hpr. Full doc, first draft.
-rw-r--r--INSTALL11
-rw-r--r--doc/index.html96
-rw-r--r--doc/overview.html149
-rw-r--r--doc/quickstart.html178
-rw-r--r--doc/s6-linux-init-echo.html69
-rw-r--r--doc/s6-linux-init-halt.html102
-rw-r--r--doc/s6-linux-init-hpr.html87
-rw-r--r--doc/s6-linux-init-logouthookd.html84
-rw-r--r--doc/s6-linux-init-maker.html451
-rw-r--r--doc/s6-linux-init-poweroff.html102
-rw-r--r--doc/s6-linux-init-reboot.html102
-rw-r--r--doc/s6-linux-init-shutdown.html36
-rw-r--r--doc/s6-linux-init-shutdownd.html16
-rw-r--r--doc/s6-linux-init-telinit.html72
-rw-r--r--doc/s6-linux-init-umountall.html61
-rw-r--r--doc/s6-linux-init.html154
-rw-r--r--doc/upgrade.html9
-rw-r--r--doc/why.html139
-rw-r--r--package/deps.mak19
-rw-r--r--package/modes4
-rw-r--r--package/targets.mak10
-rwxr-xr-xskel/rc.shutdown4
-rw-r--r--src/init/s6-linux-init-maker.c36
-rw-r--r--src/init/s6-linux-init-telinit.c12
-rw-r--r--src/lib/s6_linux_init_logouthook.c1
-rw-r--r--src/shutdown/deps-exe/s6-linux-init-hpr (renamed from src/shutdown/deps-exe/s6-linux-init-halt)0
-rw-r--r--src/shutdown/deps-exe/s6-linux-init-poweroff5
-rw-r--r--src/shutdown/deps-exe/s6-linux-init-reboot5
-rw-r--r--src/shutdown/hpr_shutdown.c2
-rw-r--r--src/shutdown/s6-linux-init-halt.c7
-rw-r--r--src/shutdown/s6-linux-init-hpr.c (renamed from src/shutdown/hpr.c)9
-rw-r--r--src/shutdown/s6-linux-init-poweroff.c7
-rw-r--r--src/shutdown/s6-linux-init-reboot.c7
-rw-r--r--src/shutdown/s6-linux-init-shutdownd.c113
34 files changed, 1268 insertions, 891 deletions
diff --git a/INSTALL b/INSTALL
index c9d11fb..a64f220 100644
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,8 @@ Build Instructions
- skalibs version 2.8.0.0 or later: https://skarnet.org/software/skalibs/
- execline version 2.5.1.0 or later: https://skarnet.org/software/execline/
- s6 version 2.8.0.0 or later: https://skarnet.org/software/s6/
- - Recommended: utmps version 0.0.2.0 or later: https://skarnet.org/software/utmps/
+ - Optional: nsss version 0.0.1.1 or later: https://skarnet.org/software/nsss/
+ - Optional: utmps version 0.0.2.0 or later: https://skarnet.org/software/utmps/
This software is Linux-specific. It will run on a Linux kernel,
version 2.6.32 or later. However, it should not be too hard to port to
@@ -22,12 +23,18 @@ other Unix-like operating systems.
./configure && make && sudo make install
will work for most users.
- It will install the binaries in /bin.
+ It will install the exported binaries in /bin, the unexported
+binaries in /libexec, and the skeleton scripts in /etc/s6-linux-init/skel.
You can strip the binaries and libraries of their extra symbols via
"make strip" before the "make install" phase. It will shave a few bytes
off them.
+ Your default init binaries will not be overwritten. They will only be
+overwritten by a manual action after you invoke s6-linux-init-maker,
+check that you are happy with its output, and decide to use it as
+your default init.
+
* Customization
-------------
diff --git a/doc/index.html b/doc/index.html
index c8d7e7e..1b4dda6 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -26,22 +26,52 @@ system, including a <tt>/sbin/init</tt> binary, on a Linux kernel.
</p>
<p>
- s6-linux-init is meant to automate creation of scripts revolving
-around the use of other skarnet.org tools, especially s6, in order
-to provide a complete booting environment with integrated supervision
-and logging without having to hand-craft all the details.
+ The resulting architecture follows the Unix philosophy (one job &rarr;
+one tool) as closely as possible, and is fully dedicated to the s6 way of
+managing a system:
</p>
+<ul>
+ <li> <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+runs as process 1 for the whole machine lifetime. </li>
+ <li> Every daemon is supervised. </li>
+ <li> No logs are ever lost. </li>
+ <li> Policy is entirely left to the user. Typically, <em>any</em> service manager
+can be run on top of s6-linux-init. </li>
+</ul>
+
+<p>
+ Nevertheless, the architecture is fully compliant with various
+empirical and historical specifications. For instance, it provides:
+</p>
+
+<ul>
+ <li> utmp management compatible with sysvinit </li>
+ <li> runlevel management, with a configurable default, overridable from the
+kernel command line </li>
+ <li> sysvinit-like commands to shut the system down, including a
+<tt>shutdown</tt> command that follows the
+<a href="http://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/shutdown.html">LSB specification</a> </li>
+</ul>
+
+<h2> Getting started </h2>
+
<p>
Please read the documentation for the
<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> program
carefully, but if you're impatient, you can also read this
-<a href="quickstart.html">quickstart guide</a>, which includes
-a small FAQ.
+<a href="quickstart.html">quickstart guide</a>.
</p>
<hr />
+<ul>
+ <li> <a href="why.html">Why</a> s6-linux-init&nbsp;? </li>
+ <li> <a href="overview.html">An overview</a> of s6-linux-init </li>
+</ul>
+
+<hr />
+
<h2> Installation </h2>
<h3> Requirements </h3>
@@ -50,30 +80,31 @@ a small FAQ.
<li> A Linux-based system with a standard C development environment </li>
<li> GNU make, version 3.81 or later </li>
<li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version
-2.6.4.0 or later </li>
+2.8.0.1 or later </li>
<li> <a href="//skarnet.org/software/execline/">execline</a> version
-2.3.0.4 or later </li>
- <li> <a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> version
-2.2.1.1 or later </li>
- <li> <a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> version
-2.4.0.2 or later </li>
+2.5.1.0 or later </li>
<li> <a href="//skarnet.org/software/s6/">s6</a> version
-2.7.1.0 or later </li>
+2.8.0.0 or later </li>
</ul>
<p>
-When you <em>build</em> s6-linux-init, the
- <a href="s6-linux-init-maker.html">s6-linux-init-maker</a> tool
-is created (as well as the shutdown commands);
- then you <em>run</em> that tool to create an init script,
-and then you can <em>boot</em> your system on that init script.
+ The following optional dependencies are also supported:
</p>
+<ul>
+ <li> If you're using <a href="https://www.musl-libc.org/">musl</a> and
+want nsswitch-like functionality:
+<a href="//skarnet.org/software/nsss/">nsss</a> version
+0.0.1.1 or later </li>
+ <li> If you want secure utmp functionality:
+<a href="//skarnet.org/software/utmps/">utmps</a> version
+0.0.2.1 or later </li>
+</ul>
+
<p>
- skalibs is a <em>build-time</em> dependency. If you are linking binaries
-against the shared version of the skalibs library, it also becomes a
-<em>run-time</em> and <em>boot-time</em> dependency. <br />
- All the other listed packages are <em>boot-time</em> dependencies only.
+ All those dependencies are <em>build-time</em> and <em>run-time</em>,
+except possibly skalibs, which is not needed at run time if you are linking
+all the other packages against the <em>static</em> version of libskarnet.
</p>
<h3> Licensing </h3>
@@ -87,7 +118,7 @@ against the shared version of the skalibs library, it also becomes a
<ul>
<li> The current released version of s6-linux-init is
-<a href="s6-linux-init-0.4.0.0.tar.gz">0.4.0.0</a>. </li>
+<a href="s6-linux-init-1.0.0.0.tar.gz">1.0.0.0</a>. </li>
<li> Alternatively, you can checkout a copy of the
<a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-linux-init/">s6-linux-init
git repository</a>:
@@ -114,6 +145,14 @@ the previous versions of s6-linux-init and the current one. </li>
<h2> Reference </h2>
+<h3> General </h3>
+
+<ul>
+ <li> A <a href="why.html">rationale</a> for this package </li>
+ <li> An <a href="overview.html">overview</a> of s6-linux-init </li>
+ <li> A <a href="quickstart.html">quickstart page</a> </li>
+</ul>
+
<h3> Commands </h3>
<p>
@@ -123,9 +162,14 @@ the previous versions of s6-linux-init and the current one. </li>
<ul>
<li><a href="s6-linux-init-maker.html">The <tt>s6-linux-init-maker</tt> program</a></li>
-<li><a href="s6-halt.html">The <tt>s6-halt</tt> program</a></li>
-<li><a href="s6-poweroff.html">The <tt>s6-poweroff</tt> program</a></li>
-<li><a href="s6-reboot.html">The <tt>s6-reboot</tt> program</a></li>
+<li><a href="s6-linux-init.html">The <tt>s6-linux-init</tt> program</a></li>
+<li><a href="s6-linux-init-hpr.html">The <tt>s6-linux-init-hpr</tt> program</a></li>
+<li><a href="s6-linux-init-shutdown.html">The <tt>s6-linux-init-shutdown</tt> program</a></li>
+<li><a href="s6-linux-init-shutdownd.html">The <tt>s6-linux-init-shutdownd</tt> program</a></li>
+<li><a href="s6-linux-init-telinit.html">The <tt>s6-linux-init-telinit</tt> program</a></li>
+<li><a href="s6-linux-init-logouthookd.html">The <tt>s6-linux-init-logouthookd</tt> program</a></li>
+<li><a href="s6-linux-init-echo.html">The <tt>s6-linux-init-umountall</tt> program</a></li>
+<li><a href="s6-linux-init-umountall.html">The <tt>s6-linux-init-umountall</tt> program</a></li>
</ul>
<h2> Related resources </h2>
diff --git a/doc/overview.html b/doc/overview.html
new file mode 100644
index 0000000..e1f3b31
--- /dev/null
+++ b/doc/overview.html
@@ -0,0 +1,149 @@
+<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: overview</title>
+ <meta name="Description" content="s6-linux-init: overview" />
+ <meta name="Keywords" content="s6-linux-init overview architecture design" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> An overview of s6-linux-init </h1>
+
+<h2> Organisation of the package </h2>
+
+<p>
+ When installed, the <tt>s6-linux-init</tt> package provides the
+following:
+</p>
+
+<ul>
+ <li> <em>Binaries</em>, that are typically installed in <tt>/bin</tt>
+ <ul>
+ <li> <a href="s6-linux-init-maker.html">s6-linux-init-maker</a> is the main
+program of the package and is used to create <tt>/sbin/init</tt> scripts
+and their supporting environment depending on configuration parameters
+given on its command line. </li>
+ <li> <a href="s6-linux-init-hpr.html">s6-linux-init-hpr</a> is an
+implementation of the sysv <tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt>
+commands; <a href="s6-linux-init-telinit.html">s6-linux-init-telinit</a>
+is an implementation of the sysv <tt>telinit</tt> command; and
+ <a href="s6-linux-init-shutdown.html">s6-linux-init-shutdown</a>
+is an implementation of the
+<a href="http://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/shutdown.html">shutdown</a>
+command. <a href="s6-linux-init.html">s6-linux-init</a> is an
+implementation of stage 1 <tt>/sbin/init</tt>, but it needs to be
+given command-line options in order to do what the user has chosen.
+An invocation of <a href="s6-linux-init-maker.html">s6-linux-init-maker</a>
+will create proper wrappers for all those commands, named after their
+short sysv names; the wrappers are directly usable as turnkey replacements
+for sysv commands. </li>
+ <li> Other binaries are support binaries, not meant to be called
+directly by the user. They are called internally, in scripts
+created by a
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation -
+typically in run scripts for early services. </li>
+ </ul> </li> <p />
+
+ <li> A <em>small library</em>, that for now contains a single symbol,
+<tt>s6_linux_init_logouthook()</tt>, intended for distributions using
+<tt>login</tt> programs that add utmp entries for users logging in and
+expect <tt>init</tt> to clean up after them when users log out. See
+the <a href="s6-linux-init-logouthookd.html">s6-linux-init-logouthookd</a>
+page for details. </li> <p />
+
+ <li> <em>Skeleton scripts</em>, installed by default in
+<tt>/etc/s6-linux-init/skel</tt>; that location can be changed at build
+time via the <tt>--skeldir</tt> configure option. At
+<tt>s6-linux-init-maker</tt>, the scripts are copied from the skeleton
+directory to the <tt>scripts</tt> subdirectory of the directory created
+by <tt>s6-linux-init-maker</tt>, and the copy is meant to be edited
+by the user. The skeleton scripts are commented and examples of
+interaction with various service manager are given; it is recommended
+to review them, and possibly edit them too.
+These scripts are the following:
+ <ul>
+ <li> <em>rc.init</em>: the script launching the system initialization
+procedure once stage 1 init is done and
+<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a> is
+safely running as pid 1. </li>
+ <li> <em>rc.shutdown</em>: the script launching the system shutdown
+procedure when the admin runs a <tt>halt</tt>, <tt>poweroff</tt>,
+<tt>reboot</tt> or <tt>shutdown</tt> command. </li>
+ <li> <em>runlevel</em>: the script executing a machine state change
+at boot time (normally invoked by <em>rc.init</em>, towards the default
+runlevel) or when the administrator runs a <tt>telinit</tt> command. </li>
+ </ul> </li>
+</ul>
+
+<h2> Organisation of the booted system </h2>
+
+<p>
+ When a system has booted on an <tt>/sbin/init</tt> program created by
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>, the following
+invariants are met:
+</p>
+
+<ul>
+ <li> A tmpfs is mounted on <tt>/run</tt> - that location can be changed
+at build-time via the <tt>--tmpfsdir</tt> option to configure. The rest
+of this document assumes it is <tt>/run</tt>. </li>
+ <li> <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a> is
+running as pid 1 on the <tt>/run/service</tt> scandir. </li>
+ <li> Every process on the system is running with at least the environment
+defined in the <tt>/etc/s6-linux-init/current/env</tt> envdir. The
+<tt>/etc/s6-linux-init/current</tt> location can be changed at
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation time
+via the <tt>-c</tt> option. </li>
+ <li> Some early services are defined in <tt>/run/service</tt>, and running.
+They are not seen by the service manager and should remain up all the time,
+until the machine shuts down: they are considered a part of the init system,
+even if they're not process 1. Each of these services uses very few resources.
+The services are:
+ <ul>
+ <li> <tt>s6-svscan-log</tt>: the catch-all logger </li>
+ <li> <tt>s6-linux-init-shutdownd</tt>: the shutdown manager, running
+the shutdown sequence in a reproducible environment when a shutdown command
+is executed, then performing the last shutdown steps. </li>
+ <li> <tt>s6-linux-init-runleveld</tt>: the runlevel manager, running
+the <em>runlevel</em> script in a reproducible environment when a <tt>telinit</tt>
+command is executed. </li>
+ <li> (optionally) <tt>s6-linux-init-logouthookd</tt>: a local service performing
+utmp record cleanup duty for patched <tt>login</tt> programs. </li>
+ <li> (optionally) <tt>s6-linux-init-early-getty</tt>: the early getty,
+allowing the user to login even if <em>rc.init</em> fails early. </li>
+ <li> (optionally) <tt>utmpd</tt> and <tt>wtmpd</tt>: the services performing
+utmp and wtmp access when <a href="//skarnet.org/software/utmps/">utmps</a> is
+used. </li>
+ </ul> </li>
+</ul>
+
+ <h2> Integration with the service manager </h2>
+
+<p>
+ The s6-linux-init package's duties stop where the service manager's start.
+s6-linux-init simply brings the system up to the point where it is stable and
+operational enough for the service manager to take over; and at shutdown
+time, s6-linux-init just tells the service manager to bring down the services,
+and then performs the last steps of the shutdown: killing all the remaining
+processes, unmounting the file systems and halting/powering off/rebooting
+the machine.
+</p>
+
+<p>
+ All the interactions between s6-linux-init and the service manager are
+configurable: they happen in the <em>rc.init</em>, <em>rc.shutdown</em>
+and <em>runlevel</em> scripts. Examples are provided in the skeleton
+scripts, that you should review and edit.
+</p>
+
+</body>
+</html>
diff --git a/doc/quickstart.html b/doc/quickstart.html
index 6a0069b..b214443 100644
--- a/doc/quickstart.html
+++ b/doc/quickstart.html
@@ -3,9 +3,9 @@
<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" />
+ <title>s6-linux-init: quickstart</title>
+ <meta name="Description" content="s6-linux-init: quickstart" />
+ <meta name="Keywords" content="s6-linux-init installation quickstart quick start" />
<!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
</head>
<body>
@@ -16,7 +16,7 @@
<a href="//skarnet.org/">skarnet.org</a>
</p>
-<h1> Quickstart and FAQ for s6-linux-init </h1>
+<h1> Quickstart for s6-linux-init </h1>
<h2> Quickstart </h2>
@@ -25,175 +25,27 @@
<ul>
<li> <a href="//skarnet.org/software/skalibs/">skalibs</a> </li>
<li> <a href="//skarnet.org/software/execline/">execline</a> </li>
- <li> <a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> </li>
- <li> <a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> </li>
<li> <a href="//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> Install <a href="index.html">s6-linux-init</a> itself. </li>
+ <li> Save your old <tt>/sbin/init</tt>, <tt>/sbin/telinit</tt>, <tt>/sbin/shutdown</tt>,
+<tt>/sbin/halt</tt>, <tt>/sbin/poweroff</tt> and <tt>/sbin/reboot</tt> binaries. </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 sure they are
-executable. See below for more information on how to write these scripts. </li>
+ <li> Edit the scripts in <tt>/etc/s6-linux-init/skel</tt>. </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
- mv /tmp/s6-linux-init /etc/
- ln -sf /etc/s6-linux-init/init /sbin/init </pre> </li>
+ rm -rf /tmp/blah
+ s6-linux-init-maker -1 -G "/sbin/getty 38400 tty1" /tmp/blah
+ rm -rf /etc/s6-linux-init/current
+ mv /tmp/blah /etc/s6-linux-init/current
+ cp -a /etc/s6-linux-init/current/bin/* /sbin/ </pre> </li>
<li> Reboot. </li>
<li> Congratulations! your machine is now running a s6-based init system. </li>
- <li> To shut the machine down, use the
-<a href="s6-halt.html">s6-halt</a>,
-<a href="s6-poweroff.html">s6-poweroff</a> or
-<a href="s6-reboot.html">s6-reboot</a> command as appropriate. </li>
+ <li> To shut the machine down, use <tt>/sbin/shutdown</tt>, <tt>/sbin/halt</tt>,
+<tt>/sbin/poweroff</tt> or <tt>/sbin/reboot</tt> as usual. </li>
</ol>
-<h3> What should go into <tt>/etc/rc.init</tt> and <tt>/etc/rc.shutdown</tt>&nbsp;? </h3>
-
-<h4> <tt>/etc/rc.init</tt> </h4>
-
-<p>
- This script will be run after s6-linux-init has done is job, i.e.
-<a href="//skarnet.org/software/s6/">s6-svscan</a> is running as process 1, and it
-is now up to <tt>/etc/rc.init</tt> to get the machine to its usable state.
-It normally contains a call to the service manager to bring up all the services;
-for instance, if you're using
-<a href="//skarnet.org/software/s6-rc/">s6-rc</a> as your service manager, and
-your top bundle (containing all the services you want to bring up) is named
-<tt>ok-all</tt>, a proper <tt>/etc/rc.init</tt> could look like this:
-</p>
-
-<pre>#!/bin/sh
-s6-rc-init /run/service &amp;&amp; exec s6-rc -u change ok-all
-</pre>
-
-<p>
- The script can assume that:
-</p>
-
-<ul>
- <li> There is a tmpfs partition, only writable by root, mounted on <tt>/run</tt> </li>
- <li> There is a <a href="//skarnet.org/software/s6/">s6</a> supervision tree
-running on <tt>/run/service</tt> </li>
- <li> <tt>/dev</tt> is mounted, but <tt>/proc</tt> and <tt>/sys</tt> are not </li>
-</ul>
-
-<h4> <tt>/etc/rc.shutdown</tt> </h4>
-
-<p>
- This script is spawned by <a href="//skarnet.org/software/s6/">s6-svscan</a>
-when the administrator calls <a href="s6-halt.html">s6-halt</a>,
-<a href="s6-poweroff.html">s6-poweroff</a> or
-<a href="s6-reboot.html">s6-reboot</a>. When this script exits, the final
-shutdown sequence is run, which means that the supervision tree is dismantled,
-all processes are killed, the file systems are umounted and the system
-undergoes a hardware shutdown or reboot. So the goal of this script is to
-bring services down in an orderly fashion and perform all the necessary
-cleanups before all remaining processes are summarily killed.
-</p>
-
-<p>
- If you're using <a href="//skarnet.org/software/s6-rc/">s6-rc</a> as your
-service manager, a proper <tt>/etc/rc.shutdown</tt> could look like this:
-</p>
-
-<pre>#!/bin/sh
-exec s6-rc -da change
-</pre>
-
-<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-echo.html b/doc/s6-linux-init-echo.html
new file mode 100644
index 0000000..837eab0
--- /dev/null
+++ b/doc/s6-linux-init-echo.html
@@ -0,0 +1,69 @@
+<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: the s6-linux-init-echo program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init-echo program" />
+ <meta name="Keywords" content="s6-linux-init command s6-linux-init-echo echo" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-linux-init-echo</tt> program </h1>
+
+<p>
+ s6-linux-init-echo writes its arguments to stdout.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-linux-init-echo [ -n ] [ -s sep ] <em>args...</em>
+</pre>
+
+<p>
+ s6-linux-init-echo writes its arguments <em>args</em> to stdout, separated with spaces.
+</p>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-n</tt>&nbsp;: do not output a trailing newline. </li>
+ <li> <tt>-s</tt>&nbsp;<em>sep</em>&nbsp;: separate arguments with the <em>sep</em>
+character instead of a space. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> Strange, and appalling, as it may seem for such a simple task, there is
+no way to ensure that the <tt>echo</tt> program will behave consistently from
+Unix system to Unix system - and even from Linux distribution to Linux
+distribution. Despite there being a
+<a href="//pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html">standard</a>
+for it, the <tt>echo</tt> commands in GNU coreutils, busybox, toybox, sbase, and
+other implementations basically all exhibit different behaviours. Every shell has
+a built-in <tt>echo</tt> command, that fails to follow the POSIX standard. <tt>echo</tt>
+is the prime example of the consequences of the blatant disregard of early Unices
+for cross-system compatibility, and its followup as a turf war between GNU and the
+rest of the Linux world. As a distribution-agnostic software developer, it is ironically
+impossible to rely on a definite behaviour of the <tt>echo</tt> command on every
+supported system, and that is why s6-linux-init provides its own implementation.
+Fortunately, it is very easy to do so, with minimal overhead. </li>
+ <li> This command is an exact duplicate of the
+<a href="//skarnet.org/software/s6-portable-utils/s6-echo.html">s6-echo</a> command
+provided in the <a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a>
+package. It was decided <em>not</em> to have a dependency from s6-linux-init to
+s6-portable-utils: that dependency would arguably be a higher cost than the small
+amount of code duplication. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-linux-init-halt.html b/doc/s6-linux-init-halt.html
deleted file mode 100644
index 0f68995..0000000
--- a/doc/s6-linux-init-halt.html
+++ /dev/null
@@ -1,102 +0,0 @@
-<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: the s6-linux-init-halt program</title>
- <meta name="Description" content="s6-linux-init: the s6-linux-init-halt program" />
- <meta name="Keywords" content="s6 linux init administration root utilities shutdown halt poweroff reboot" />
- <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
- </head>
-<body>
-
-<p>
-<a href="index.html">s6-linux-init</a><br />
-<a href="//skarnet.org/software/">Software</a><br />
-<a href="//skarnet.org/">skarnet.org</a>
-</p>
-
-<h1> The <tt>s6-linux-init-halt</tt> program </h1>
-
-<p>
-<tt>s6-linux-init-halt</tt> triggers the shutdown procedure in order to
-halt the system; or, with the <tt>-f</tt> option, it performs an immediate
-hard shutdown.
-</p>
-
-<h2> Interface </h2>
-
-<pre>
- s6-linux-init-halt [ -h | -p | -r ] [ -d | -w ] [ -W ] [ -f ] [ -R <em>tmpfsdir</em> ]
-</pre>
-
-<ul>
- <li> If the <tt>-f</tt> option is present, s6-linux-init-halt halts the system immediately. </li>
- <li> Else, it triggers the machine's shutdown procedure.
- <li> It exits 0. The shutdown procedure happens asynchronously. </li>
-</ul>
-
-<p>
- This interface follows the traditional <em>sysvinit</em> interface for the
-<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> programs as close as possible.
-</p>
-
-<h2> Exit codes </h2>
-
-<ul>
- <li> 0: shutdown procedure triggered. </li>
- <li> 100: wrong usage, or user does not have root privileges. </li>
- <li> 111: system call failed. </li>
-</ul>
-
-<h2> Options </h2>
-
-<ul>
- <li> <tt>-h</tt>&nbsp;: halt. No matter the name of the command, it will order
-a halt (i.e. the system will be shut down, but the power will remain up).
-This is the default for <tt>s6-linux-init-halt</tt>. </li>
- <li> <tt>-p</tt>&nbsp;: poweroff. No matter the name of the command, it will order
-a power off. This is the default for <tt>s6-linux-init-poweroff</tt>. </li>
- <li> <tt>-r</tt>&nbsp;: reboot. No matter the name of the command, it will order
-a reboot. This is the default for <tt>s6-linux-init-reboot</tt>. </li>
- <li> <tt>-d</tt>&nbsp;: Do not write a wtmp shutdown entry. </li>
- <li> <tt>-w</tt>&nbsp;: Only write a wtmp shutdown entry; do not actually shut down
-the system. </li>
- <li> <tt>-W</tt>&nbsp;: Do not send a <tt>wall</tt> message to users before shutting
-down the system. Some other implementations of the <tt>halt</tt>, <tt>poweroff</tt>
-and <tt>reboot</tt> commands use the <tt>--no-wall</tt> long option to achieve this. </li>
- <li> <tt>-f</tt>&nbsp;: force. The command will not trigger a clean shutdown
-procedure; it will just sync the filesystems then tell the kernel to immediately
-halt, poweroff or reboot. This should be the last step in the lifetime of the
-machine. </li>
- <li> <tt>-R&nbsp;<em>tmpfsdir</em></tt>&nbsp;: assume that the root-only
-boot-time tmpfs has been mounted on <em>tmpfsdir</em>. Default is <tt>/run</tt>.
-It is important to get this right, because the contact point with the
-<a href="s6-linux-init-shutdownd.html">s6-linux-init-shutdownd</a> daemon,
-which manages the shutdown procedure, is located under this directory. The
-<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> scripts created by a
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation
-automatically use the correct <tt>-R</tt> option. </li>
-</ul>
-
-<h2> Notes </h2>
-
-<ul>
- <li> The
-<a href="s6-linux-init-halt.html">s6-linux-init-halt</a>,
-<a href="s6-linux-init-poweroff.html">s6-linux-init-poweroff</a>,
-<a href="s6-linux-init-reboot.html">s6-linux-init-reboot</a> and
-<a href="s6-linux-init-shutdown.html">s6-linux-init-shutdown</a>
-binaries are not meant to be called directly by administrators.
-Instead, their purpose is to be used in <tt>halt</tt>, <tt>poweroff</tt>,
-<tt>reboot</tt> and <tt>shutdown</tt> scripts created by
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>; those scripts
-will call them with the correct <tt>-R&nbsp;<em>tmpfsdir</em></tt> option.
-The scripts should typically be linked to <tt>/sbin</tt> after
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> execution, to
-provide drop-in replacements for the <em>sysvinit</em> programs with the
-same names. </li>
-</ul>
-
-</body>
-</html>
diff --git a/doc/s6-linux-init-hpr.html b/doc/s6-linux-init-hpr.html
new file mode 100644
index 0000000..304ed35
--- /dev/null
+++ b/doc/s6-linux-init-hpr.html
@@ -0,0 +1,87 @@
+<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: the s6-linux-init-hpr program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init-hpr program" />
+ <meta name="Keywords" content="s6 linux init administration root utilities shutdown halt poweroff reboot s6-linux-init-hpr" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-linux-init-hpr</tt> program </h1>
+</h1>
+
+<p>
+ <tt>s6-linux-init-hpr</tt> triggers the software shutdown procedure,
+or, with the <tt>-f</tt> option, it perform an immediate hardware shutdown.
+It is normally invoked as <tt>/sbin/halt</tt>, <tt>/sbin/poweroff</tt> or
+<tt>/sbin/reboot</tt>.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-linux-init-hpr [ -f ] [ -h | -p | -r ] [ -d | -w ] [ -W ]
+</pre>
+
+<ul>
+ <li> If the <tt>-f</tt> option is present, the hardware command is executed immediately. </li>
+ <li> Else, the machine's shutdown procedure is started.
+ <li> The command exits 0; the shutdown procedure happens asynchronously. </li>
+</ul>
+
+<p>
+ This interface is the traditional <em>sysvinit</em> interface for the
+<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> programs.
+<tt>s6-linux-init-hpr</tt> must always be called with one of the
+<tt>-h</tt>, <tt>-p</tt> or <tt>-r</tt> options.
+</p>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: shutdown procedure triggered. </li>
+ <li> 100: wrong usage, or user does not have root privileges. </li>
+ <li> 111: system call failed. </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-f</tt>&nbsp;: force. The command will not trigger a clean shutdown
+procedure; it will just sync the filesystems then tell the kernel to immediately
+halt, poweroff or reboot. This should be the last step in the lifetime of the
+machine. </li>
+ <li> <tt>-h</tt>&nbsp;: halt. The system will be shut down, but the power will remain up. </li>
+ <li> <tt>-p</tt>&nbsp;: poweroff. The system will be shut down and the power turned off. </li>
+ <li> <tt>-r</tt>&nbsp;: reboot. The system will reboot. </li>
+ <li> <tt>-d</tt>&nbsp;: Do not write a wtmp shutdown entry. </li>
+ <li> <tt>-w</tt>&nbsp;: Only write a wtmp shutdown entry; do not actually shut down
+the system. </li>
+ <li> <tt>-W</tt>&nbsp;: Do not send a <tt>wall</tt> message to users before shutting
+down the system. Some other implementations of the <tt>halt</tt>, <tt>poweroff</tt>
+and <tt>reboot</tt> commands use the <tt>--no-wall</tt> long option to achieve this. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> When an administrator runs
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>, the resulting
+directory has a <tt>bin/</tt> subdirectory that contains <tt>halt</tt>,
+<tt>poweroff</tt> and <tt>reboot</tt> scripts that call <tt>s6-linux-init-hpr</tt>
+with the relevant option. The
+contents of this <tt>bin/</tt> subdirectory should then be copied by the
+administrator into <tt>/sbin</tt> for full interface compatibility with sysvinit. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-linux-init-logouthookd.html b/doc/s6-linux-init-logouthookd.html
new file mode 100644
index 0000000..34f5bd8
--- /dev/null
+++ b/doc/s6-linux-init-logouthookd.html
@@ -0,0 +1,84 @@
+<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: the s6-linux-init-logouthookd program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init-logouthookd program" />
+ <meta name="Keywords" content="s6-linux-init command s6-linux-init-logouthookd login logout utmp hook sysvinit" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-linux-init-logouthookd</tt> program </h1>
+
+<p>
+ s6-linux-init-logouthookd cleans up its client's utmp record when it dies.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-ipcserver <em>socket</em> s6-linux-init-logouthookd
+</pre>
+
+<p>
+ s6-linux-init-logouthookd implements a
+<a href="//skarnet.org/software/s6/localservice.html">local service</a>
+for getty programs that add an utmp record when a user logs in.
+</p>
+
+<p>
+ In the sysvinit model, <tt>getty</tt>/<tt>login</tt> and similar programs add an utmp
+record for every user that logs in, then exec into the user's shell.
+At logout time, the shell dies; sysvinit is supervising the <tt>getty</tt>
+program, so it's watching the pid, and respawns the <tt>getty</tt> when the
+shell dies. But before respawning the <tt>getty</tt>, it cleans up the
+utmp record, to correctly report that the user isn't logged in on this
+terminal anymore.
+</p>
+
+<p>
+ utmp is an old, clunky, insecure system (unless you're using
+<a href="//skarnet.org/software/utmps/">utmps</a>) and it is definitely
+not pid 1's job to have any knowledge of utmp and play janitor after
+<tt>getty</tt>. <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+definitely will not do it.
+</p>
+
+<p>
+ Some distributions use versions of <tt>login</tt> that fork the user's
+shell instead of execing it. When the user logs out, the <tt>login</tt>
+program cleans up after itself. This is a better model, but it's not
+always easy to patch <tt>login</tt> to go from a "exec the shell" model to a
+"fork the shell as a child" model.
+</p>
+
+<p>
+ <tt>s6-linux-init</tt> comes with a small library which makes it easy
+for a distribution to fully support utmp cleanup with an s6 init system
+if they so choose. Before execing into the user's shell, the <tt>login</tt>
+program should just make a call to <tt>s6_linux_init_logouthook()</tt>,
+and that's it. That function will call the <tt>s6-linux-init-logouthookd</tt>
+local service, which will do nothing but wait until the user's shell dies;
+and when it happens, the user's utmp record will automatically be cleaned up.
+</p>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> The <a href="//skarnet.org/software/s6/localservice.html">local service</a>
+implementing logouthook support is automatically created at boot time when the
+<tt>-L</tt> option has been given to
+<a href="s6-linux-init-maker">s6-linux-init-maker</a>. Client-side, though,
+the various login programs must be patched at the source level. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html
index a512501..45284ab 100644
--- a/doc/s6-linux-init-maker.html
+++ b/doc/s6-linux-init-maker.html
@@ -21,27 +21,25 @@
<p>
<tt>s6-linux-init-maker</tt> reads configuration options on
the command line, and outputs a directory to place in the
-root filesystem. That directory contains a script suitable
-as an init program, as well as support file hierarchies to
-get a complete
+root filesystem. That directory contains
+a script that is suitable as an <tt>/sbin/init</tt> program
+as well as all the necessary files that this script needs
+to properly boot and bring up a full
<a href="//skarnet.org/software/s6/">s6</a>
-infrastructure running when the system is booted on that
-script.
+infrastructure.
</p>
<p>
s6-linux-init-maker only writes scripts. At boot time, these
scripts will call commands provided by other skarnet.org packages
such as
-<a href="//skarnet.org/software/execline/">execline</a> or
+<a href="//skarnet.org/software/execline/">execline</a> and
<a href="//skarnet.org/software/s6/">s6</a>. It is the
responsibility of the administrator to make sure that all the
dependencies are properly installed at boot time, and that the
-correct options have been given to s6-linux-init-maker so that
-the programs are found <em>on the root filesystem of the
-machine</em> - else the scripts will crash.
-</p>
-
+correct options have been given to <tt>s6-linux-init-maker</tt>
+so that the programs are found <em>on the root filesystem of the
+machine</em>. If it is not the case, the system will fail to boot.
</p>
<h2> Interface and usage </h2>
@@ -49,7 +47,7 @@ machine</em> - else the scripts will crash.
<pre>
s6-linux-init-maker \
[ -c <em>basedir</em> ] \
- [ -u <em>log_uid</em> -g <em>log_gid</em> | -U ] \
+ [ -u <em>log_user</em> ] \
[ -G <em>early_getty</em> ] \
[ -1 ] \
[ -L ] \
@@ -59,13 +57,15 @@ machine</em> - else the scripts will crash.
[ -d <em>dev_style</em> ] \
[ -s <em>env_store</em> ] \
[ -e <em>initial_envvar</em> ] ... \
- [ -E <em>stage2_envvar</em> ] ... \
[ -q ] <em>finalsleeptime</em>
+ [ -D <em>initdefault</em> ] \
+ [ -U <em>utmp_user</em> ] \
<em>dir</em>
</pre>
<ul>
- <li> s6-linux-init-maker should be run as root. </li>
+ <li> s6-linux-init-maker must be run as root, on the machine
+that will boot an s6-based system. </li>
<li> s6-linux-init-maker parses options on its command line. </li>
<li> It writes data into a directory <em>dir</em>, which must not
exist beforehand. </li>
@@ -75,171 +75,72 @@ or its contents. </li>
</ul>
<p>
- <em>dir</em> should then be copied by the administrator to the place
-declared as <em>basedir</em>. Be careful: it contains fifos, files with
+ Once the command has been run and <em>dir</em> has been created, there
+are a few manual steps to take:
+</p>
+
+<ol>
+ <li> <tt>s6-linux-init-maker</tt> has copied some scripts from the
+<tt>/etc/s6-linux-init/skel</tt> directory (or the directory you
+gave as an argument to the <tt>--skeldir</tt> configure option at
+build time) to the <em>dir</em><tt>/scripts</tt> directory. You
+should <strong>edit these scripts</strong> and adapt them to your use case.
+(Or you could edit the skeleton scripts before running
+<tt>s6-linux-init-maker</tt>.) The scripts are:
+ <ul>
+ <li> <tt>rc.init</tt>: this script will be run as <em>stage 2
+initialization</em>, i.e. the initialization that happens once
+<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+is running as process 1, and should contain all your normal
+system bootup tasks. Typically, it should initialize the service
+manager and then order it to bring the machine state to its
+fully operational state. <em>rc.init</em> is given the default
+<em>runlevel</em> as a first argument (i.e. the name of the state
+the machine should be brought to, traditionally <tt>default</tt>
+for OpenRC and <tt>2</tt> or <tt>5</tt> for sysv-rc), and the
+rest of the command line is made of the kernel's command line
+except for the kernel arguments of the <em>key=value</em> form,
+which have been stored into <em>env_store</em>. </li>
+ <li> <tt>rc.shutdown</tt>: this script will be run as the
+<em>shutdown sequence</em>, when the administrator runs the
+<tt>shutdown</tt>, <tt>halt</tt>, <tt>poweroff</tt> or <tt>reboot</tt>
+command. (As well as <tt>init 0</tt>, <tt>init 6</tt>.
+<tt>telinit 0</tt> and <tt>telinit 6</tt> for compatibility
+reasons.) It should ask the service manager to bring all the
+services down, and exit when it's done (in other words: it should
+not try to perform a hard halt/poweroff/reboot itself.)
+No arguments are given to this script. </li>
+ <li> <tt>runlevel</tt>: this script will be invoked for every
+<em>runlevel change</em>, i.e. change of machine states. It is
+given one argument: the name of the runlevel to change to.
+Typically, the <em>runlevel</em> script should just invoke the
+service manager, asking it to bring the machine state to the
+wanted runlevel. </li>
+ </ul> </li>
+ <li> Copy the <em>dir</em> directory to the place declared as
+<em>basedir</em> (<tt>/etc/s6-linux-init/current</tt> by default).
+ 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="//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> or <tt>mv</tt> commands.
-</p>
-
-<p>
- 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>
+tool can do it, as well as the GNU or busybox <tt>cp -a</tt> or <tt>mv</tt> commands. </li>
+ <li> Back up your <tt>/sbin</tt>. Then copy, link or symlink all the scripts
+and symlinks in the <em>basedir</em><tt>/bin</tt> directory into <tt>/sbin</tt>.
+ In particular, the <tt><em>basedir</em>/bin/init</tt> script should
+be accessible as <tt>/sbin/init</tt>. </li>
+</ol>
<h2> Boot sequence </h2>
<p>
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>
- <li> <em>stage 1</em> is an
-<a href="//skarnet.org/software/execline/">execline</a> script, so
-the first process run by the kernel is the
-<a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>
-program launcher. </li>
- <li> <em>stage 1</em> mounts a
-<a href="https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt">tmpfs</a>
-filesystem on <em>tmpfsdir</em>. </li>
- <li> <em>stage 1</em> copies <tt><em>basedir</em>/run-image</tt> verbatim to
-<em>tmpfsdir</em>. </li>
- <li> <em>stage 1</em> empties its environment, then reads a global set of environment variables from the
-<tt><em>basedir</em>/env</tt>
-<a href="//skarnet.org/software/s6/s6-envdir.html">environment directory</a>. </li>
- <li> <em>stage 1</em> forks a child that will block until
-<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a> is running. </li>
- <li> <em>stage 1</em> executes, as process 1, into
-<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>,
-with <tt><em>tmpfsdir</em>/service</tt> as a
-<a href="//skarnet.org/software/s6/scandir.html">scan directory</a>. </li>
- <li> This scan directory already contains at least one service, which is the
-<em>catch-all logger</em>: error messages from the supervision tree, and
-from services that do not have a dedicated logger, are handled by a
-special <a href="//skarnet.org/software/s6/s6-log.html">s6-log</a>
-instance and made available in <tt><em>tmpfsdir</em>/uncaught-logs</tt>
-instead of clogging the system console. </li>
- <li> If the <tt>-G</tt> option has been given to s6-linux-init-maker, the
-scan directory will also contain a service for an early getty. </li>
- <li> s6-svscan starts all the services defined in the scan directory,
-and unblocks the child forked by <em>stage 1</em>. </li>
- <li> This child executes into <em>initscript</em>. </li>
-</ul>
-
-<p>
- <em>initscript</em> is the responsibility of the administrator - it will
-not be written automatically!
-It should
-contain all the necessary initialization sequence to bring up a proper
-system. When <em>initscript</em> is executed, the machine state is as follows:
-</p>
-
-<ul>
- <li> <em>initscript</em>'s working directory is <tt>/</tt> and its stdin
-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>
- <li> <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
-is running as process 1. At any time, it is possible to make it supervise a long-lived
-process by linking the appropriate
-<a href="//skarnet.org/software/s6/servicedir.html">service directory</a>
-into <tt><em>tmpfsdir</em>/service</tt>, then running the command
-<tt>s6-svscanctl -a <em>tmpfsdir</em>/service</tt>. Services without a
-dedicated logger will send their output to the catch-all logger. </li>
- <li> A getty service may already be available. The point of this early
-getty is essentially to make it easier to debug if <em>initscript</em> fails. </li>
-</ul>
-
-<p>
- There is <em>nothing else</em>. In particular, no filesystem has been
-mounted yet, including <tt>/proc</tt> and <tt>/sys</tt>; and no one-time
-initialization
-has been performed. The point of <em>stage 1</em> is only to make it
-possible to run <em>initscript</em> with a logging infrastructure and a
-supervision infrastructure already available, and all the
-real machine and service initialization should happen in <em>initscript</em>,
-also known as <em>stage 2</em>.
-</p>
-
-<h2> Shutdown sequence </h2>
-
-<ul>
-
- <li> A shutdown is performed when the administrator runs one of the
-<a href="s6-halt.html">s6-halt</a>,
-<a href="s6-poweroff.html">s6-poweroff</a> or
-<a href="s6-reboot.html">s6-reboot</a> commands. </li>
-
- <li> Those commands send a signal to the
-<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
-process running as pid 1; this signal is caught and s6-svscan runs the
-corresponding "signal handler" script that has been placed by
-s6-linux-init-maker into the
-<tt><em>basedir</em>/run-image/service/.s6-svscan</tt> directory (and that
-has been copied at boot time to <tt><em>tmpfsdir</em>/service/.s6-svscan</tt>). </li>
-
- <li> That script first spawns the <em>shutdownscript</em> script, who
-must have been written by the administrator. The purpose of
-<em>shutdownscript</em> is to perform the high-level shutdown sequence
-while the supervision tree is still alive. Typically, when using a
-service manager, <em>shutdownscript</em> would tell the service manager
-to bring all services down. When using
-<a href="//skarnet.org/software/s6-rc/">s6-rc</a>, a typical
-<em>stage2_finish</em> script just contains <tt>s6-rc -da change</tt>.
- More generally speaking, <em>shutdownscript</em> should undo what
-<em>stage2</em> has done at boot time. </li>
-
- <li> The "signal handler" script then tells s6-svscan to exit via an
-appropriate <a href="//skarnet.org/software/s6/s6-svscanctl.html">s6-svscanctl</a>
-command: s6-svscan then executes into the final shutdown sequence. This
-sequence is made of the following actions:
-
-<ul>
- <li> The supervision tree gets torn down. </li>
- <li> All data is flushed to disk. </li>
- <li> All processes get a SIGTERM, a SIGHUP, and a SIGCONT. This should
-allow all processes to die gracefully. Note that most processes should
-already have been killed during the <tt>/etc/rc.shutdown</tt> execution;
-this phase only catches stragglers, background processs, etc. </li>
- <li> The sequence sleeps for <em>finalsleeptime</em> milliseconds, to
-allow all processes to finish their clean exit routine. </li>
- <li> All processes get a SIGKILL. </li>
- <li> All zombies are reaped. </li>
- <li> All filesystems get unmounted, and the root filesystem is remounted
-read-only. </li>
- <li> The machine performs a hardware reboot, halt or poweroff, depending
-on the command that has been used. </li>
-</ul> </li>
-
-</ul>
-
-<p>
- The <tt>examples/</tt> subdirectory of the s6-linux-init package
-contains an example of <tt>/etc/rc.init</tt>
-and <tt>/etc/rc.shutdown</tt> scripts, suitable for
-<em>initscript</em> and <em>shutdownscript</em>
-respectively. Those scripts can practically be used as is if the machine
-is managed by the <a href="//skarnet.org/software/s6-rc/">s6-rc</a>
-service manager.
+also known as <em>stage 1</em>. This script is just an execution
+of the <a href="s6-linux-init.html">s6-linux-init</a> program with
+some command-line options that are directly transferred from the
+<tt>s6-linux-init-maker</tt> invocation. Refer to the
+<a href="s6-linux-init.html">s6-linux-init</a> man page to know
+exactly what it does.
</p>
<h2> s6-linux-init-maker options </h2>
@@ -248,60 +149,50 @@ service manager.
<li> <tt>-c</tt>&nbsp;<em>basedir</em>&nbsp;: at boot time, <em>stage 1</em>,
which should be accessible as <tt><em>basedir</em>/init</tt>,
will read its read-only data from <em>basedir</em>. After running
-s6-linux-init-maker, the administrator should make sure to copy the
+<tt>s6-linux-init-maker</tt>, you should make sure to copy the
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>-u</tt>&nbsp;<em>log_uid</em>&nbsp;: the catch-all
-logger will run with the uid <em>log_uid</em>. Default is 0. </li> <p />
-
- <li> <tt>-g</tt>&nbsp;<em>log_gid</em>&nbsp;: the catch-all
-logger will run with the gid <em>log_gid</em>. Default is 0. </li> <p />
+<strong><tt>/etc/s6-linux-init/current</tt></strong>. </li> <p />
- <li> <tt>-U</tt>&nbsp;: the correct <em>log_uid</em> and
-<em>log_gid</em> values for the catch-all logger will be read from the
-UID and GID environment variables that have been passed to
-s6-linux-init-maker. This allows for invocations such as
-<tt>s6-envuidgid nobody s6-linux-init-maker -U ...</tt> so that
-the catch-all logger runs as the <tt>nobody</tt> user. Be aware that
-this option is only safe when the user database on the
-<em>boot-time</em> machine is the same as on the <em>run-time</em>
-machine, else the catch-all logger may run with an unexpected uid
-and gid. </li> <p />
+ <li> <tt>-u</tt>&nbsp;<em>log_user</em>&nbsp;: the catch-all
+logger will run as the <em>log_user</em> user. Default is <tt>root</tt>. </li> <p />
<li> <tt>-G</tt>&nbsp;<em>early_getty</em>&nbsp;: if this option
-is set, s6-linux-init-maker will define a service that will run
-very early, before <em>stage2</em> is executed. This early service
-should be a getty, to allow logins even if <em>stage2</em> fails.
+is set, <tt>s6-linux-init-maker</tt> will define an additional s6 service
+that will be named <tt>s6-linux-init-early-getty</tt> and started
+at the same time <em>rc.init</em> is executed. This early service
+should be a getty, or equivalent, to allow logins even if <em>stage2</em> fails.
<em>early_getty</em> should be a simple command line: for instance,
<tt>"/sbin/getty 38400 tty1"</tt>. By default, no early service
is defined. </li> <p />
<li> <tt>-1</tt>&nbsp;: 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>)
+caught by a dedicated logger, as well as the output from <em>rc.init</em>,
+<em>runlevel</em> and <em>rc.shutdown</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>
+getty. A common workaround is to make the early getty start on
+<tt>tty2</tt> and leave tty1 for <tt>/dev/console</tt> to print on. </li> <p />
+
+ <li> <tt>-L</tt>&nbsp;: add an early <tt>s6-linux-init-logouthookd</tt>
+service to clean up utmp records at user logout time. Check the
+<a href="s6-linux-init-logouthookd">s6-linux-init-logouthookd</a> page
+for details. </li> <p />
<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>stage 1</em>. It is
-absolutely necessary for
-<a href="//skarnet.org/software/execline/">execline</a>,
-<a href="//skarnet.org/software/s6/">s6</a>,
-<a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> and
-<a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a>
+It is absolutely necessary for
+<a href="//skarnet.org/software/execline/">execline</a> and
+<a href="//skarnet.org/software/s6/">s6</a>
binaries to be accessible via <em>initial_path</em>, else the machine
will not boot. Default is
<strong><tt>/usr/bin:/bin</tt></strong>. </li> <p />
<li> <tt>-m</tt>&nbsp;<em>initial_umask</em>&nbsp;: the value of
the initial file umask for all the starting processes, in octal.
-Default is
-<strong><tt>022</tt></strong>. </li> <p />
+Default is <strong><tt>022</tt></strong>. </li> <p />
<li> <tt>-t</tt>&nbsp;<em>timestamp_style</em>&nbsp;: how
logs are timestamped by the catch-all logger. 0 means no
@@ -319,39 +210,37 @@ devtmpfs automounted by the kernel at boot time. Default is
<strong><tt>2</tt></strong>. </li> <p />
<li> <tt>-s</tt>&nbsp;<em>env_store</em>&nbsp;: stage 1 init sometimes
-inherits a few environment variables from the kernel. It empties its
-environment before spawning stage2 and executing into s6-svscan, in
+inherits a few environment variables from the kernel. (These variables
+correspond to the arguments on the kernel command line that are of the
+form <em>key=value</em>.) It empties its
+environment before spawning <em>rc.init</em> and executing into s6-svscan, in
order to prevent those "kernel" environment variables from leaking
into the whole process tree. However, sometimes those variables are
needed at a later time; in that case, giving the <tt>-s</tt> option
-to s6-linux-init-maker makes stage 1 init dump the "kernel" environment
-variables into the <em>env_store</em> directory, via the
-<a href="//skarnet.org/software/s6-portable-utils/s6-dumpenv.html">s6-dumpenv</a>
-program, before erasing them. <em>env_store</em> should obviously be
-a writable directory, so it should be located under <em>tmpfsdir</em>!
-If this option is not given (which is the default), the environment
-inherited from the kernel isn't saved anywhere. </li> <p />
+to <tt>s6-linux-init-maker</tt> makes stage 1 init dump the "kernel" environment
+variables into the <em>env_store</em> directory (under a format that is
+later readable with
+<a href="//skarnet.org/software/s6/s6-envdir.html">s6-envdir -fn</a>)
+before erasing them. <em>env_store</em> should obviously be
+a writable directory, so it should be located under <tt>/run</tt>
+(or your chosen tmpfsdir)!
+If this option is not given, the environment inherited from the kernel
+isn't saved anywhere - which is the default. </li> <p />
<li> <tt>-e</tt>&nbsp;<em>initial_envvar</em>&nbsp;: this option
-can be repeated. For every <em>initial_envvar</em>, s6-linux-init-maker
+can be repeated. For every <em>initial_envvar</em>, <tt>s6-linux-init-maker</tt>
will adjust the global environment directory in <em>dir</em>/env.
<em>initial_envvar</em> must either be of the form <em>VAR</em>,
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,
+process (as well as the <em>rc.init</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>-E</tt>&nbsp;<em>stage2_envvar</em>&nbsp;: 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>&nbsp;<em>finalsleeptime</em>&nbsp;: when the machine
shuts down, all processes that have not already been killed during
<tt>shutdownscript</tt> will receive a SIGTERM or a SIGHUP to allow
@@ -361,11 +250,114 @@ will go on. This option configures the amount of time that will
elapse between the SIGTERM/SIGHUP and the SIGKILL.
Default is <strong>2000</strong>, meaning a grace period of 2 seconds. </li> <p />
+ <li> <tt>-D</tt>&nbsp;<em>initdefault</em>&nbsp;: boot the system with
+a runlevel set to <em>initdefault</em>, which can be an arbitrary
+string, but is usually <tt>2</tt>, <tt>3</tt>, <tt>5</tt> (traditional
+sysvinit behaviour) or <tt>default</tt> (OpenRC behaviour). Default is
+<tt>default</tt>. Note that if a <tt>2</tt>, <tt>3</tt>, <tt>4</tt>,
+<tt>5</tt>, or <tt>default</tt> argument is encountered in the kernel
+command line, it will be interpreted as the runlevel to boot the system
+on, and will override the default given here. </li> <p />
+
+ <li> <tt>-U</tt>&nbsp;<em>utmp_user</em>&nbsp;: this option is only
+available when the s6-linux-init package has been built with the
+<tt>--enable-utmps</tt> configure option, that enables support for the
+<a href="//skarnet.org/software/utmps/">utmps</a> package. The option
+defines the user that the <tt>utmpd</tt> and <tt>wtmpd</tt> services
+will run as. Default is <tt>utmp</tt>. </li> <p />
+</ul>
+
+<h2> Organization of the created directory </h2>
+
+<p>
+ If <tt>s6-linux-init-maker</tt> returns successfully, <em>dir</em>
+contains data that will be used at boot time. (Actually,
+<em>basedir</em> will be used at boot time, not <em>dir</em>. Do not
+forget to copy <em>dir</em> to <em>basedir</em> once you have checked
+you are happy with what <tt>s6-linux-init-maker</tt> has created.)
+</p>
+
+<p>
+ This boot-time data is made of several subdirectories:
+</p>
+
+<ul>
+ <li> <tt>bin</tt>: this subdirectory contains scripts and symlinks
+that should be copied to <tt>/sbin</tt> or <tt>/bin</tt>. There is
+an <tt>init</tt> program performing stage 1 init, a <tt>telinit</tt>
+program to change runlevels, and utilities to order a machine shutdown. </li>
+ <li> <tt>env</tt>: this subdirectory is the envdir that is
+used to store the global environment. It will be read at boot time
+by stage 1 init, and transmitted to all spawned processes. </li>
+ <li> <tt>scripts</tt>: this subdirectory contains a copy of the
+skeleton scripts that have been installed in <tt>/etc/s6-linux-init/skel</tt>
+(or the argument to the <tt>--skeldir</tt> configure option at
+build time). These scripts should be edited before booting. They are
+described above. </li>
+ <li> <tt>run-image</tt>: this is a file hierarchy that will be
+copied verbatim at boot time to the newly made and mounted
+<tt>/run</tt> tmpfs (or whatever your <em>tmpfsdir</em> is). The
+subdirectories it contains are the following:
+ <ul>
+ <li> <tt>uncaught-logs</tt>: this is the directory where the
+catch-all logger will store and rotate the error messages produced
+by the s6 supervision tree and the services that do not redirect
+their own logs. </li>
+ <li> <tt>service</tt>: <tt>/run/service</tt> will be the scandir.
+It initially contains a <tt>.s6-svscan</tt> subdirectory that
+tells <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+what to do if it receives a signal (typically via the ctrlaltdel
+combination) and ensures a hard reboot if <tt>s6-svscan</tt> ever fails. It
+also contains a list of early services, i.e. s6 services that will
+be run at boot time as soon as <tt>s6-svscan</tt> is executed. These
+services are:
+ <ul>
+ <li> <tt>s6-svscan-log</tt>: the catch-all logger. </li>
+ <li> <tt>s6-linux-init-shutdownd</tt>: a service that listens
+to shutdown commands such as <tt>reboot</tt> and triggers the software
+shutdown procedure. The service is asleep for the whole lifetime of
+the machine and uses very few resources. </li>
+ <li> <tt>s6-linux-init-runleveld</tt>: a service that listens
+to runlevel change commands such as <tt>telinit</tt> and calls the
+<em>runlevel</em> script in a reproducible environment to bring the
+machine to the wanted state. </li>
+ <li> (If the <tt>-L</tt> option has been given to
+<tt>s6-linux-init-maker</tt>) <tt>s6-linux-init-logouthookd</tt>:
+the "clean up user utmp records at logout time" service. See the
+<a href="s6-linux-init-logouthookd.html">s6-linux-init-logouthookd</a>
+page for details. </li>
+ <li> (If the <tt>-G</tt> option has been given to
+<tt>s6-linux-init-maker</tt>) <tt>s6-linux-init-early-getty</tt>:
+the early getty service, that will allow a user to log in even if
+<em>rc.init</em> fails to bring the machine to a state where logins
+are possible. </li>
+ </ul> </li>
+ </ul> </li>
+</ul>
+
+<p>
+ If s6-linux-init has been built with
+<a href="//skarnet.org/software/utmps/">utmps</a> support, some more
+directories may exist:
+</p>
+
+<ul>
+ <li> A directory somewhere under <tt>run-image</tt>, by default <tt>utmp</tt>,
+that is the location where the utmp and wtmp files will be created. </li>
+ <li> Two additional early services named <tt>utmpd</tt> and <tt>wtmpd</tt>,
+that are the <a href="//skarnet.org/software/utmps/">utmps</a> way of
+providing secure utmp functionality. </li>
</ul>
<h2> Notes </h2>
<p>
+ A directory created by <tt>s6-linux-init-maker</tt> is only valid on
+the machine it has been created on. Pre-creating init directories for
+other machines is not supported.
+</p>
+
+<p>
The difficult parts of
<a href="//skarnet.org/software/s6/s6-svscan-1.html">running
s6-svscan as process 1</a> are:
@@ -380,22 +372,27 @@ 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>
+ <li> Keeping appearances of compatibility with another init system
+is difficult: in particular, the mechanisms around the shutdown
+procedure are fundamentally different from about any other init
+system, so even a simple command such as <tt>reboot</tt> needs an
+ad-hoc implementation. </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:
+ The main benefit of <tt>s6-linux-init-maker</tt> is that it offers
+transparent compatibility while automating the tricky technical part.
+That means that <tt>s6-linux-init-maker</tt> has been designed for
+<em>real hardware</em>, or at least full-fledged Linux systems,
+where the above issues apply. If you are building an init system for a
+container, or anything similar that does not
+have the <tt>/dev/console</tt> issue, the read-only rootfs issue,
+or the need for sysvinit compatibility,
+you will probably not reap much benefit from using <tt>s6-linux-init-maker</tt>:
you could probably invoke
<a href="//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.
-Nevertheless, if you prefer using s6-linux-init-maker, it
-supports this case via the <tt>-n</tt> option.
</p>
</body>
diff --git a/doc/s6-linux-init-poweroff.html b/doc/s6-linux-init-poweroff.html
deleted file mode 100644
index 2126b23..0000000
--- a/doc/s6-linux-init-poweroff.html
+++ /dev/null
@@ -1,102 +0,0 @@
-<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: the s6-linux-init-poweroff program</title>
- <meta name="Description" content="s6-linux-init: the s6-linux-init-poweroff program" />
- <meta name="Keywords" content="s6 linux init administration root utilities shutdown halt poweroff reboot" />
- <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
- </head>
-<body>
-
-<p>
-<a href="index.html">s6-linux-init</a><br />
-<a href="//skarnet.org/software/">Software</a><br />
-<a href="//skarnet.org/">skarnet.org</a>
-</p>
-
-<h1> The <tt>s6-linux-init-poweroff</tt> program </h1>
-
-<p>
-<tt>s6-linux-init-poweroff</tt> triggers the shutdown procedure in order to
-halt the system; or, with the <tt>-f</tt> option, it performs an immediate
-hard shutdown.
-</p>
-
-<h2> Interface </h2>
-
-<pre>
- s6-linux-init-poweroff [ -h | -p | -r ] [ -d | -w ] [ -W ] [ -f ] [ -R <em>tmpfsdir</em> ]
-</pre>
-
-<ul>
- <li> If the <tt>-f</tt> option is present, s6-linux-init-poweroff halts the system immediately. </li>
- <li> Else, it triggers the machine's shutdown procedure.
- <li> It exits 0. The shutdown procedure happens asynchronously. </li>
-</ul>
-
-<p>
- This interface follows the traditional <em>sysvinit</em> interface for the
-<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> programs as close as possible.
-</p>
-
-<h2> Exit codes </h2>
-
-<ul>
- <li> 0: shutdown procedure triggered. </li>
- <li> 100: wrong usage, or user does not have root privileges. </li>
- <li> 111: system call failed. </li>
-</ul>
-
-<h2> Options </h2>
-
-<ul>
- <li> <tt>-h</tt>&nbsp;: halt. No matter the name of the command, it will order
-a halt (i.e. the system will be shut down, but the power will remain up).
-This is the default for <tt>s6-linux-init-halt</tt>. </li>
- <li> <tt>-p</tt>&nbsp;: poweroff. No matter the name of the command, it will order
-a power off. This is the default for <tt>s6-linux-init-poweroff</tt>. </li>
- <li> <tt>-r</tt>&nbsp;: reboot. No matter the name of the command, it will order
-a reboot. This is the default for <tt>s6-linux-init-reboot</tt>. </li>
- <li> <tt>-d</tt>&nbsp;: Do not write a wtmp shutdown entry. </li>
- <li> <tt>-w</tt>&nbsp;: Only write a wtmp shutdown entry; do not actually shut down
-the system. </li>
- <li> <tt>-W</tt>&nbsp;: Do not send a <tt>wall</tt> message to users before shutting
-down the system. Some other implementations of the <tt>halt</tt>, <tt>poweroff</tt>
-and <tt>reboot</tt> commands use the <tt>--no-wall</tt> long option to achieve this. </li>
- <li> <tt>-f</tt>&nbsp;: force. The command will not trigger a clean shutdown
-procedure; it will just sync the filesystems then tell the kernel to immediately
-halt, poweroff or reboot. This should be the last step in the lifetime of the
-machine. </li>
- <li> <tt>-R&nbsp;<em>tmpfsdir</em></tt>&nbsp;: assume that the root-only
-boot-time tmpfs has been mounted on <em>tmpfsdir</em>. Default is <tt>/run</tt>.
-It is important to get this right, because the contact point with the
-<a href="s6-linux-init-shutdownd.html">s6-linux-init-shutdownd</a> daemon,
-which manages the shutdown procedure, is located under this directory. The
-<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> scripts created by a
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation
-automatically use the correct <tt>-R</tt> option. </li>
-</ul>
-
-<h2> Notes </h2>
-
-<ul>
- <li> The
-<a href="s6-linux-init-halt.html">s6-linux-init-halt</a>,
-<a href="s6-linux-init-poweroff.html">s6-linux-init-poweroff</a>,
-<a href="s6-linux-init-reboot.html">s6-linux-init-reboot</a> and
-<a href="s6-linux-init-shutdown.html">s6-linux-init-shutdown</a>
-binaries are not meant to be called directly by administrators.
-Instead, their purpose is to be used in <tt>halt</tt>, <tt>poweroff</tt>,
-<tt>reboot</tt> and <tt>shutdown</tt> scripts created by
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>; those scripts
-will call them with the correct <tt>-R&nbsp;<em>tmpfsdir</em></tt> option.
-The scripts should typically be linked to <tt>/sbin</tt> after
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> execution, to
-provide drop-in replacements for the <em>sysvinit</em> programs with the
-same names. </li>
-</ul>
-
-</body>
-</html>
diff --git a/doc/s6-linux-init-reboot.html b/doc/s6-linux-init-reboot.html
deleted file mode 100644
index 422eeed..0000000
--- a/doc/s6-linux-init-reboot.html
+++ /dev/null
@@ -1,102 +0,0 @@
-<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: the s6-linux-init-reboot program</title>
- <meta name="Description" content="s6-linux-init: the s6-linux-init-reboot program" />
- <meta name="Keywords" content="s6 linux init administration root utilities shutdown halt poweroff reboot" />
- <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
- </head>
-<body>
-
-<p>
-<a href="index.html">s6-linux-init</a><br />
-<a href="//skarnet.org/software/">Software</a><br />
-<a href="//skarnet.org/">skarnet.org</a>
-</p>
-
-<h1> The <tt>s6-linux-init-reboot</tt> program </h1>
-
-<p>
-<tt>s6-linux-init-reboot</tt> triggers the shutdown procedure in order to
-reboot the system; or, with the <tt>-f</tt> option, it performs an immediate
-hard reboot.
-</p>
-
-<h2> Interface </h2>
-
-<pre>
- s6-linux-init-reboot [ -h | -p | -r ] [ -d | -w ] [ -W ] [ -f ] [ -R <em>tmpfsdir</em> ]
-</pre>
-
-<ul>
- <li> If the <tt>-f</tt> option is present, s6-linux-init-reboot reboots the system immediately. </li>
- <li> Else, it triggers the machine's shutdown procedure, which will end in a reboot.
- <li> It exits 0. The shutdown procedure happens asynchronously. </li>
-</ul>
-
-<p>
- This interface follows the traditional <em>sysvinit</em> interface for the
-<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> programs as close as possible.
-</p>
-
-<h2> Exit codes </h2>
-
-<ul>
- <li> 0: shutdown procedure triggered. </li>
- <li> 100: wrong usage, or user does not have root privileges. </li>
- <li> 111: system call failed. </li>
-</ul>
-
-<h2> Options </h2>
-
-<ul>
- <li> <tt>-h</tt>&nbsp;: halt. No matter the name of the command, it will order
-a halt (i.e. the system will be shut down, but the power will remain up).
-This is the default for <tt>s6-linux-init-halt</tt>. </li>
- <li> <tt>-p</tt>&nbsp;: poweroff. No matter the name of the command, it will order
-a power off. This is the default for <tt>s6-linux-init-poweroff</tt>. </li>
- <li> <tt>-r</tt>&nbsp;: reboot. No matter the name of the command, it will order
-a reboot. This is the default for <tt>s6-linux-init-reboot</tt>. </li>
- <li> <tt>-d</tt>&nbsp;: Do not write a wtmp shutdown entry. </li>
- <li> <tt>-w</tt>&nbsp;: Only write a wtmp shutdown entry; do not actually shut down
-the system. </li>
- <li> <tt>-W</tt>&nbsp;: Do not send a <tt>wall</tt> message to users before shutting
-down the system. Some other implementations of the <tt>halt</tt>, <tt>poweroff</tt>
-and <tt>reboot</tt> commands use the <tt>--no-wall</tt> long option to achieve this. </li>
- <li> <tt>-f</tt>&nbsp;: force. The command will not trigger a clean shutdown
-procedure; it will just sync the filesystems then tell the kernel to immediately
-halt, poweroff or reboot. This should be the last step in the lifetime of the
-machine. </li>
- <li> <tt>-R&nbsp;<em>tmpfsdir</em></tt>&nbsp;: assume that the root-only
-boot-time tmpfs has been mounted on <em>tmpfsdir</em>. Default is <tt>/run</tt>.
-It is important to get this right, because the contact point with the
-<a href="s6-linux-init-shutdownd.html">s6-linux-init-shutdownd</a> daemon,
-which manages the shutdown procedure, is located under this directory. The
-<tt>halt</tt>, <tt>poweroff</tt> and <tt>reboot</tt> scripts created by a
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation
-automatically use the correct <tt>-R</tt> option. </li>
-</ul>
-
-<h2> Notes </h2>
-
-<ul>
- <li> The
-<a href="s6-linux-init-halt.html">s6-linux-init-halt</a>,
-<a href="s6-linux-init-poweroff.html">s6-linux-init-poweroff</a>,
-<a href="s6-linux-init-reboot.html">s6-linux-init-reboot</a> and
-<a href="s6-linux-init-shutdown.html">s6-linux-init-shutdown</a>
-binaries are not meant to be called directly by administrators.
-Instead, their purpose is to be used in <tt>halt</tt>, <tt>poweroff</tt>,
-<tt>reboot</tt> and <tt>shutdown</tt> scripts created by
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>; those scripts
-will call them with the correct <tt>-R&nbsp;<em>tmpfsdir</em></tt> option.
-The scripts should typically be linked to <tt>/sbin</tt> after
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> execution, to
-provide drop-in replacements for the <em>sysvinit</em> programs with the
-same names. </li>
-</ul>
-
-</body>
-</html>
diff --git a/doc/s6-linux-init-shutdown.html b/doc/s6-linux-init-shutdown.html
index 72bbfcf..b48ea61 100644
--- a/doc/s6-linux-init-shutdown.html
+++ b/doc/s6-linux-init-shutdown.html
@@ -20,24 +20,25 @@
<p>
<tt>s6-linux-init-shutdown</tt> triggers the system shutdown procedure.
+It is normally invoked as <tt>/sbin/shutdown</tt>.
</p>
<h2> Interface </h2>
<pre>
- s6-linux-init-shutdown [ -h | -p | -r | -k ] [ -a ] [ -t <em>sec</em> ] [ -f | -F ] [ -R <em>tmpfsdir</em> ] <em>time</em> [ <em>message</em> ]
- s6-linux-init-shutdown -c [ -R <em>tmpfsdir</em> ] [ <em>message</em> ]
+ s6-linux-init-shutdown [ -h | -p | -r | -k ] [ -a ] [ -t <em>sec</em> ] [ -f | -F ] <em>time</em> [ <em>message</em> ]
+ s6-linux-init-shutdown -c [ <em>message</em> ]
</pre>
<ul>
<li> If the <tt>-c</tt> option is present, a pending shutdown is cancelled. </li>
- <li> Else, it triggers the shutdown procedure.
+ <li> Else, it triggers the shutdown procedure. </li>
<li> It exits 0. The shutdown procedure happens asynchronously. </li>
</ul>
<p>
The <tt>s6-linux-init-shutdown</tt> program conforms to the LSB-3.0.0
-<a href="https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA.junk/shutdown.html">shutdown</a>
+<a href="http://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/shutdown.html">shutdown</a>
interface.
</p>
@@ -49,29 +50,16 @@ interface.
<li> 111: system call failed. </li>
</ul>
-<h2> Supplementary options </h2>
-
-<p>
- These options are supported by <tt>s6-linux-init-shutdown</tt> but are not
-part of the LSB-3.0.0 <tt>shutdown</tt> specification.
-</p>
-
-<ul>
- <li> <tt>-R&nbsp;<em>tmpfsdir</em></tt>&nbsp;: assume that the root-only
-boot-time tmpfs has been mounted on <em>tmpfsdir</em>. Default is <tt>/run</tt>.
-The <tt>shutdown</tt> script created by a
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation
-automatically execs into <tt>s6-linux-init-shutdown</tt> with the correct
-<tt>-R</tt> option. </li>
-</ul>
-
<h2> Notes </h2>
<ul>
- <li> The <a href="s6-linux-init-shutdown.html">s6-linux-init-shutdown</a>
-binary is not meant to be called directly by administrators.
-Instead, its purpose is to be used in a <tt>shutdown</tt> script created by
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a>. </li>
+ <li> The <tt>s6-linux-init-shutdown</tt>
+binary is not meant to be called directly by administrators. Instead, after a
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation,
+the <tt>bin/</tt> subdirectory of the target will contain a <tt>shutdown</tt>
+symlink to <tt>s6-linux-init-shutdown</tt>. The <tt>bin/</tt> subdirectory
+should be copied by the administrator into <tt>/sbin</tt> for full
+interface compatibility with sysvinit. </li>
</ul>
</body>
diff --git a/doc/s6-linux-init-shutdownd.html b/doc/s6-linux-init-shutdownd.html
index b6ea412..f4cf8a0 100644
--- a/doc/s6-linux-init-shutdownd.html
+++ b/doc/s6-linux-init-shutdownd.html
@@ -3,8 +3,8 @@
<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: the s6-linux-init-shutdownd internal program</title>
- <meta name="Description" content="s6-linux-init: the s6-linux-init-shutdownd internal program" />
+ <title>s6-linux-init: the s6-linux-init-shutdownd program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init-shutdownd program" />
<meta name="Keywords" content="s6 linux init administration root utilities shutdown halt poweroff reboot daemon shutdownd" />
<!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
</head>
@@ -16,7 +16,7 @@
<a href="//skarnet.org/">skarnet.org</a>
</p>
-<h1> The <tt>s6-linux-init-shutdownd</tt> internal program </h1>
+<h1> The <tt>s6-linux-init-shutdownd</tt> program </h1>
<p>
<tt>s6-linux-init-shutdownd</tt> is the daemon that manages the shutdown
@@ -27,7 +27,7 @@ directly by the user.
<h2> Interface </h2>
<pre>
- s6-linux-init-shutdownd [ -b <em>bindir</em> ] [ -c <em>basedir</em> ] [ -g <em>gracetime</em> ] <em>fifo</em>
+ s6-linux-init-shutdownd [ -c <em>basedir</em> ] [ -g <em>gracetime</em> ] <em>fifo</em>
</pre>
<ul>
@@ -36,8 +36,9 @@ and listens to it. This is where programs such as
<a href="s6-linux-init-shutdown.html">s6-linux-init-shutdown</a> send their
commands when they are told to trigger the shutdown procedure.</li>
<li> When it receives a command to shut down, <tt>s6-linux-init-shutdownd</tt>
-first spawns the <em>stage3</em> script defined by the last
-<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation. </li>
+first spawns the <em>rc.shutdown</em> script defined by the
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation that
+created the shutdownd service. </li>
<li> When this script exits, <tt>s6-linux-init-shutdownd</tt> kills all
processes, first with a SIGTERM, then (after the grace time specified by
the shutdown command) with a SIGKILL. </li>
@@ -56,9 +57,6 @@ machine. </li>
<h2> Options </h2>
<ul>
- <li> <tt>-b&nbsp;<em>bindir</em></tt>&nbsp;: look for the
-<a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>
-script interpreter in the <em>bindir</em> directory. Default is <tt>/bin</tt>. </li>
<li> <tt>-c&nbsp;<em>basedir</em></tt>&nbsp;: look for the
<em>stage3</em> and <em>stage4</em> scripts in the <em>basedir</em>
directory. Default is <tt>/etc/s6-linux-init</tt>. </li>
diff --git a/doc/s6-linux-init-telinit.html b/doc/s6-linux-init-telinit.html
new file mode 100644
index 0000000..bc7f12d
--- /dev/null
+++ b/doc/s6-linux-init-telinit.html
@@ -0,0 +1,72 @@
+<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: the s6-linux-init-telinit program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init-telinit program" />
+ <meta name="Keywords" content="s6 linux init administration root utilities telinit" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-linux-init-telinit</tt> program </h1>
+
+<p>
+<tt>s6-linux-init-telinit</tt> changes runlevels, i.e. changes the
+system state. It is normally invoked as <tt>/sbin/telinit</tt> or
+just <tt>init</tt> with an argument.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-linux-init-telinit <tt>rl</tt>
+</pre>
+
+<ul>
+ <li> <tt>s6-linux-init-telinit</tt> may be called with the same options as
+<tt>s6-linux-init</tt>, but it ignores them all. </li>
+ <li> It calls the runleveld
+<a href="//skarnet.org/software/s6/localservice.html">local service</a> with
+the <em>rl</em> argument. This local service executes the user-provided
+<tt>runlevel</tt> script, which changes the system state to the state
+described by <em>rl</em>. </li>
+ <li> As a special case, if <em>rl</em> is <tt>0</tt> or <tt>6</tt>,
+<tt>s6-linux-init-telinit</tt> then executes into
+<a href="s6-linux-init-hpr.html">s6-linux-init-hpr</a> with the <tt>-p</tt>
+or <tt>-r</tt> option respectively,
+for compatibility with sysvinit's <em>0</em> and <em>6</em> runlevels
+that respectively halt and reboot the machine. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> Traditional sysvinit only allows integer runlevels, from 0 to 6.
+More advanced service managers, like OpenRC or s6-rc, allow the admin to
+define alphanumerical runlevels, or <em>states</em>. <tt>s6-linux-init-telinit</tt>
+does not implement policy; it only makes sure the user-provided <tt>runlevel</tt>
+script is called with the <em>rl</em> argument, under a safe and reproducible
+environment. The <tt>runlevel</tt> script can then change the machine state
+as chosen by the user - typically by invoking the service manager. </li>
+ <li> The <tt>0</tt> and <tt>6</tt> special case has been added because
+some legacy programs may assume that calling <tt>init 0</tt> and <tt>init 6</tt>
+respectively halt and reboot the system. </li>
+ <li> The <tt>s6-linux-init-telinit</tt>
+binary is not meant to be called directly by administrators. Instead, after a
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation,
+the <tt>bin/</tt> subdirectory of the target will contain a <tt>telinit</tt>
+symlink to <tt>s6-linux-init-telinit</tt>. The <tt>bin/</tt> subdirectory
+should be copied by the administrator into <tt>/sbin</tt> for full
+interface compatibility with sysvinit. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-linux-init-umountall.html b/doc/s6-linux-init-umountall.html
new file mode 100644
index 0000000..c2402fd
--- /dev/null
+++ b/doc/s6-linux-init-umountall.html
@@ -0,0 +1,61 @@
+<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: the s6-linux-init-umountall program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init-umountall program" />
+ <meta name="Keywords" content="s6 linux administration root linux utilities umount unmount filesystem" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-linux-init-umountall</tt> program </h1>
+
+<p>
+ <tt>s6-linux-init-umountall</tt> unmounts all the filesystems.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-linux-init-umountall
+</pre>
+
+<ul>
+ <li> <tt>s6-linux-init-umountall</tt> unmounts all partitions according to <tt>/proc/mounts</tt>.
+It processes <tt>/proc/mounts</tt> in the reverse order, starting with the most recently mounted
+partition and ending with the root filesystem ("unmounting" the root filesystem means remounting
+it read-only). </li>
+ <li> <tt>s6-linux-init-umountall</tt> does not touch <tt>/etc/mtab</tt>. </li>
+ <li> If a filesystem fails to unmount, a warning is printed to stderr, but
+<tt>s6-linux-init-umountall</tt> still attempts to unmount all the other ones. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> <tt>s6-linux-init-umountall</tt> is automatically called at the very end of the shutdown procedure,
+in "stage 4", i.e. after a SIGKILL has been sent to all the processes on the system, and
+right before the system reboots (or halts, or is powered off). By that point, there is
+no possible process that could prevent real file systems from being unmounted. </li>
+ <li> It is likely that some filesystems will still fail to unmount, typically
+<tt>/proc</tt> and <tt>/dev</tt>. That's okay: those are pseudo-filesystems, and
+will not cause data loss or a fsck if the system shuts down while they are still mounted. </li>
+ <li> Distributions usually provide a <tt>umount</tt> command with a <tt>-a</tt> option
+to unmount all filesystems. That command is usually bloated with historical artifacts
+and relies on unsafe interfaces, so it was decided not to use it. The
+<a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> package also
+provides a <a href="//skarnet.org/software/s6-linux-utils/s6-umount.html">s6-umount</a>
+command with a <tt>-a</tt> option, but adding a dependency to that package would be a
+higher cost than simply reimplementing the specific functionality here. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-linux-init.html b/doc/s6-linux-init.html
new file mode 100644
index 0000000..a4bb636
--- /dev/null
+++ b/doc/s6-linux-init.html
@@ -0,0 +1,154 @@
+<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: the s6-linux-init program</title>
+ <meta name="Description" content="s6-linux-init: the s6-linux-init program" />
+ <meta name="Keywords" content="s6 linux init administration root init boot pid1 pid 1 /sbin/init" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-linux-init</tt> program </h1>
+
+<p>
+<tt>s6-linux-init</tt> is a program that is meant to run as pid 1,
+as a <em>stage 1 init</em>: it performs the necessary early system preparation
+and execs into <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-linux-init [ -c <em>basedir</em> ] [ -p <em>initial_path</em> ] [ -s <em>env_store</em> ] [ -m <em>umask</em> ] [ -d <em>dev_style</em> ] [ -D <em>initdefault</em> ] [ <em>args...</em> ]
+</pre>
+
+<ul>
+ <li> If <tt>s6-linux-init</tt> isn't pid 1, it execs into
+<a href="s6-linux-init-telinit.html">s6-linux-init-telinit</a> with the
+same arguments. </li>
+ </li>
+ <li> Else, it performs some early preparation, spawns a process that
+will run the <em>rc.init</em> script, then execs into
+<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>.
+</ul>
+
+<h2> Options </h2>
+
+<p>
+ These options should exactly mirror the options with the same name that
+have been given to <a href="s6-linux-init-maker.html">s6-linux-init-maker</a>.
+If there is a discrepancy, the system might not boot.
+</p>
+
+<ul>
+ <li> <tt>-c</tt>&nbsp;<em>basedir</em>&nbsp;: read all its initialization
+data from <em>basedir</em>. If the data has not indeed been copied to
+<em>basedir</em>, <strong>the system will not boot</strong>. </li>
+ <li> <tt>-p</tt>&nbsp;<em>initial_path</em>&nbsp;: the value to
+set the initial PATH environment variable to.
+ <li> <tt>-s</tt>&nbsp;<em>env_store</em>&nbsp;: the place where to dump
+kernel environment variables. </li>
+ <li> <tt>-m</tt>&nbsp;<em>initial_umask</em>&nbsp;: the value of
+the initial file umask. </li>
+ <li> <tt>-d</tt>&nbsp;<em>dev_style</em>&nbsp;: how <tt>/dev</tt> is
+handled on this system. 0 means a static <tt>/dev</tt>, 1 means
+devtmpfs but not automounted by the kernel at boot time, and 2 means
+devtmpfs automounted by the kernel at boot time. </li>
+ <li> <tt>-D</tt>&nbsp;<em>initdefault</em>&nbsp;: the initial runlevel
+to boot to, if it isn't overridden by the kernel command line.
+This is only given as a first argument to <em>rc.init</em>.
+Default is <tt>default</tt>. </li>
+</ul>
+
+<h2> Early preparation </h2>
+
+<p>
+ When booting a system, <tt>s6-linux-init</tt> performs the following
+operations:
+</p>
+
+<ul>
+ <li> It prints a banner to <tt>/dev/console</tt>. </li>
+ <li> It chdirs to <tt>/</tt>. </li>
+ <li> It sets the umask to <em>initial_umask</em>. </li>
+ <li> It becomes a session leader. </li>
+ <li> It mounts a devtmpfs on <tt>/dev</tt>, if necessary. </li>
+ <li> It uses <tt>/dev/null</tt> as its stdin (instead of <tt>/dev/console</tt>).
+<tt>/dev/console</tt> is still used, for now, as stdout and stderr. </li>
+ <li> It unmounts <tt>/run</tt> (or the directory you have given to the
+<tt>--tmpfsdir</tt> configure option at package build time), just in case. </li>
+ <li> It creates a tmpfs on <tt>/run</tt> (or your chosen <em>tmpfsdir</em>). </li>
+ <li> It copies the whole <tt><em>basedir</em>/run-image</tt> hierarchy to
+<tt>/run</tt> (or your chosen tmpfsdir). </li>
+ <li> It reads the initial environment from <tt><em>basedir</em>/env</tt>. </li>
+ <li> If required, it stores the kernel environment into <em>env_store</em>. </li>
+ <li> It performs "the fifo trick", i.e. it redirects its stdout to the
+catch-all logger's fifo, without blocking, before the catch-all
+logger is even up (because it's a service that will be spawned a bit
+later, when <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+is executed). </li>
+ <li> It forks a child.
+ <ul>
+ <li> The child scans the kernel command line to find a suitable runlevel
+(<tt>default</tt>, <tt>2</tt>, <tt>3</tt>, <tt>4</tt>, or <tt>5</tt>). If
+it doesn't find any kernel command line argument that defines a runlevel,
+it uses <em>initdefault</em>. </li>
+ <li> The child becomes a session leader. </li>
+ <li> The child blocks until the catch-all logger runs. </li>
+ </ul> </li>
+ <li> It also makes the catch-all logger's fifo its stderr. </li>
+ <li> It execs into <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+with <tt>/run/service</tt> as its scandir (or <em>tmpfsdir</em>/service) </li>.
+ <ul>
+ <li> <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+spawns the early services that are defined in
+<tt><em>basedir</em>/run-image/service</tt>, and have been copied into
+<tt>/run/service</tt> (or <em>tmpfsdir</em>/service). </li>
+ <li> One of those early services is <tt>s6-svscan-log</tt>, which is
+the catch-all logger. When this service is up, <tt>s6-linux-init<tt>'s
+child unblocks. </li>
+ <li> The child execs into <tt><em>basedir</em>/scripts/rc.init</tt>.
+The first argument to <em>rc.init</em> is the chosen runlevel. The kernel
+command line, as given by the kernel to <tt>s6-linux-init</tt> (i.e. without
+the <tt>key=value</tt> arguments, which were passed into <tt>s6-linux-init</tt>'s
+environment and were stored into <em>env_store</em>), makes for the rest of
+the arguments given to <em>rc.init</em>. </li>
+ </ul> </li>
+</ul>
+
+<p>
+ By the time <em>rc.init</em> runs,
+<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a> is running
+as pid 1 and has spawned its early services - at least the catch-all logger,
+and the other services, including the early getty if it has been defined, are
+started in parallel and will be ready instantly. <em>rc.init</em> can then
+perform <em>stage 2</em> of the initialization process, i.e. the initialization
+sequence per se.
+</p>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> The <tt>s6-linux-init</tt>
+binary is not meant to be called directly, or be linked to <tt>/sbin/init</tt>
+directly, because it takes command-line options.
+ Instead, after a
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> invocation,
+the <tt>bin/</tt> subdirectory of the target will contain a script called
+<tt>init</tt>, which execs into <tt>s6-linux-init</tt> with the appropriate
+command-line options, and <em>is</em> suitable as a <tt>/sbin/init</tt> program.
+The <tt>bin/</tt> subdirectory
+should be copied by the administrator into <tt>/sbin</tt> for full
+interface compatibility with sysvinit. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index 1acbba5..02aaeea 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,6 +18,15 @@
<h1> What has changed in s6-linux-init </h1>
+
+<h2> in 1.0.0.0 </h2>
+
+<ul>
+ <li> This is a complete rewrite and redesign of s6-linux-init: the
+<em>lifetime</em> version number has increased. No compatibility
+whatsoever is retained with previous versions. </li>
+</ul>
+
<h2> in 0.4.0.1 </h2>
<ul>
diff --git a/doc/why.html b/doc/why.html
new file mode 100644
index 0000000..2c200c5
--- /dev/null
+++ b/doc/why.html
@@ -0,0 +1,139 @@
+<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: why?</title>
+ <meta name="Description" content="s6-linux-init: why?" />
+ <meta name="Keywords" content="s6-linux-init why rationale s6 software stack init pid 1" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-linux-init</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> Why s6-linux-init&nbsp;? </h1>
+
+<h2> The s6 software stack </h2>
+
+<p>
+ The s6 ecosystem is made of several parts, which are mainly the following:
+</p>
+
+<ul>
+ <li> <a href="//skarnet.org/software/skalibs/">skalibs</a>: a C system
+programming library that is used in all skarnet.org software. </li>
+ <li> <a href="//skarnet.org/software/execline/">execline</a>: a small
+scripting language that is mainly used in various parts of the s6
+ecosystem because:
+ <ul>
+ <li> It is very quick to launch, and efficient with small scripts, so it
+is a good choice for s6 run scripts. </li>
+ <li> It is much easier to programmatically generate execline scripts than
+shell scripts. execline allows programs such as
+<a href="s6-linux-init-maker.html">s6-linux-init-maker</a> to generate scripts
+quite easily, whereas using the shell syntax would require them to understand
+the full subleties of shell quoting. </li>
+ </ul>
+ <li> <a href="//skarnet.org/software/s6/">s6</a>, the main dish: a process
+supervision suite. </li>
+ <li> <a href="//skarnet.org/software/s6-rc/">s6-rc</a>: a service manager
+for s6. </li>
+ <li> and <a href="//skarnet.org/software/s6-linux-init/">s6-linux-init</a>: this
+package. </li>
+</ul>
+
+<h2> Providing a complete init system </h2>
+
+<p>
+ As explained in
+<a href="https://archive.fosdem.org/2017/schedule/event/s6_supervision/">this
+presentation"></a>, an init system is made of four parts:
+</p>
+
+<ol>
+ <li> <tt>/sbin/init</tt>: the first userspace program that is run by the
+kernel at boot time (not counting an initramfs). </li>
+ <li> <em>pid 1</em>: the program that will run as process 1 for most of
+the lifetime of the machine. This is not necessarily the same executable
+as <tt>/sbin/init</tt>, because <tt>/sbin/init</tt> can exec into something
+else. </li>
+ <li> a <em>process supervisor</em>. </li>
+ <li> a <em>service manager</em>. </li>
+</ol>
+
+<p>
+ The <a href="//skarnet.org/software/s6/">s6</a> package obviously provides
+part 3. It also provides part 2, because
+<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a> is suitable
+as being pid 1 after some small setup is performed.
+</p>
+
+<p>
+ Part 4, service management, can be provided in a variety of ways. The
+<a href="//skarnet.org/software/s6-rc/">s6-rc</a> service manager is the
+natural complement to the s6 process supervisor, but it is not the only
+possibility. The
+<a href="https://jjacky.com/anopa/">anopa</a> package also provides a
+service manager designed to work with s6. And, at the expense of
+tight integration with the supervisor, it is possible to run a "traditional"
+service manager, such as sysv-rc or OpenRC, with an s6-based init system.
+This flexibility is possible because service management is one layer above
+the mechanisms of init and process supervision.
+</p>
+
+<p>
+ Remains part 1. And that's where s6-linux-init enters the picture.
+</p>
+
+<h3> Portability </h3>
+
+<p>
+ Part 1 of an init system, the <tt>/sbin/init</tt> program, has been purposefully
+omitted from the main s6 package, for a simple reason: s6 aims to be portable
+to any flavor of Unix, and <em>it is impossible to implement <tt>/sbin/init</tt>
+in a portable way</em>.
+</p>
+
+<p>
+ For instance, to do its job,
+<a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a> needs
+a writable directory. Such a directory may not be available at boot time,
+before mounting filesystems, because the root filesystem may be read-only.
+So, at least one writable filesystem (typically a RAM-backed one) must be
+mounted before s6-svscan can be executed and be pid 1. And mounting a
+filesystem is a non-portable operation.
+</p>
+
+<h3> Complexity </h3>
+
+<p>
+ Moreover, the sequence of operations that a <tt>/sbin/init</tt> program
+needs to perform before executing into <tt>s6-svscan</tt> is a bit
+tricky. It can be scripted, but it's not easy, and since it's so early
+in the lifetime of the machine, there's no safety net at all (the
+supervision tree itself, and the early getty, are supposed to be the
+safety net! and they're not there yet). So it's better to automate
+these operations.
+</p>
+
+<h2> Conclusion </h2>
+
+<p>
+ <tt>s6-linux-init</tt> aims to provide a fully functional <tt>/sbin/init</tt>
+program that executes into an s6 supervision tree with all the necessary
+support services already in place, as well as the corresponding shutdown
+commands. It also aims to be flexible enough to accommodate various needs
+and be compatible with any user-chosen service manager.
+</p>
+
+<p>
+As usual, it is about <em>mechanism</em>, not <em>policy</em>.
+</p>
+
+</body>
+</html>
diff --git a/package/deps.mak b/package/deps.mak
index 3a5c457..565df1a 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -7,23 +7,20 @@ src/shutdown/hpr.h: src/include-local/initctl.h
src/init/s6-linux-init-maker.o src/init/s6-linux-init-maker.lo: src/init/s6-linux-init-maker.c src/include-local/defaults.h src/include-local/initctl.h src/include/s6-linux-init/config.h
src/init/s6-linux-init-telinit.o src/init/s6-linux-init-telinit.lo: src/init/s6-linux-init-telinit.c src/include-local/initctl.h src/include/s6-linux-init/config.h
src/init/s6-linux-init.o src/init/s6-linux-init.lo: src/init/s6-linux-init.c src/include-local/defaults.h src/include-local/initctl.h src/include/s6-linux-init/config.h
-src/lib/s6_linux_init_logouthook.o src/lib/s6_linux_init_logouthook.lo: src/lib/s6_linux_init_logouthook.c src/include-local/initctl.h
+src/lib/s6_linux_init_logouthook.o src/lib/s6_linux_init_logouthook.lo: src/lib/s6_linux_init_logouthook.c src/include-local/initctl.h src/include/s6-linux-init/s6-linux-init.h
src/misc/s6-linux-init-echo.o src/misc/s6-linux-init-echo.lo: src/misc/s6-linux-init-echo.c
src/misc/s6-linux-init-logouthookd.o src/misc/s6-linux-init-logouthookd.lo: src/misc/s6-linux-init-logouthookd.c
src/misc/s6-linux-init-umountall.o src/misc/s6-linux-init-umountall.lo: src/misc/s6-linux-init-umountall.c
-src/shutdown/hpr.o src/shutdown/hpr.lo: src/shutdown/hpr.c src/include-local/defaults.h src/shutdown/hpr.h
src/shutdown/hpr_shutdown.o src/shutdown/hpr_shutdown.lo: src/shutdown/hpr_shutdown.c src/shutdown/hpr.h
src/shutdown/hpr_wall.o src/shutdown/hpr_wall.lo: src/shutdown/hpr_wall.c src/shutdown/hpr.h
-src/shutdown/s6-linux-init-halt.o src/shutdown/s6-linux-init-halt.lo: src/shutdown/s6-linux-init-halt.c
-src/shutdown/s6-linux-init-poweroff.o src/shutdown/s6-linux-init-poweroff.lo: src/shutdown/s6-linux-init-poweroff.c
-src/shutdown/s6-linux-init-reboot.o src/shutdown/s6-linux-init-reboot.lo: src/shutdown/s6-linux-init-reboot.c
+src/shutdown/s6-linux-init-hpr.o src/shutdown/s6-linux-init-hpr.lo: src/shutdown/s6-linux-init-hpr.c src/include-local/defaults.h src/shutdown/hpr.h
src/shutdown/s6-linux-init-shutdown.o src/shutdown/s6-linux-init-shutdown.lo: src/shutdown/s6-linux-init-shutdown.c src/include-local/defaults.h src/shutdown/hpr.h src/include-local/initctl.h
src/shutdown/s6-linux-init-shutdownd.o src/shutdown/s6-linux-init-shutdownd.lo: src/shutdown/s6-linux-init-shutdownd.c src/include-local/defaults.h src/shutdown/hpr.h src/include-local/initctl.h
s6-linux-init: EXTRA_LIBS :=
s6-linux-init: src/init/s6-linux-init.o -lskarnet
-s6-linux-init-maker: EXTRA_LIBS :=
-s6-linux-init-maker: src/init/s6-linux-init-maker.o -lskarnet
+s6-linux-init-maker: EXTRA_LIBS := ${MAYBEPTHREAD_LIB}
+s6-linux-init-maker: src/init/s6-linux-init-maker.o ${LIBNSSS} -lskarnet
s6-linux-init-telinit: EXTRA_LIBS :=
s6-linux-init-telinit: src/init/s6-linux-init-telinit.o -lskarnet
ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
@@ -44,12 +41,8 @@ libhpr.a.xyzzy: src/shutdown/hpr_shutdown.o src/shutdown/hpr_wall.o
else
libhpr.a.xyzzy: src/shutdown/hpr_shutdown.lo src/shutdown/hpr_wall.lo
endif
-s6-linux-init-halt: EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB}
-s6-linux-init-halt: src/shutdown/s6-linux-init-halt.o libhpr.a.xyzzy ${LIBUTMPS} -lskarnet
-s6-linux-init-poweroff: EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB}
-s6-linux-init-poweroff: src/shutdown/s6-linux-init-poweroff.o libhpr.a.xyzzy ${LIBUTMPS} -lskarnet
-s6-linux-init-reboot: EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB}
-s6-linux-init-reboot: src/shutdown/s6-linux-init-reboot.o libhpr.a.xyzzy ${LIBUTMPS} -lskarnet
+s6-linux-init-hpr: EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB}
+s6-linux-init-hpr: src/shutdown/s6-linux-init-hpr.o libhpr.a.xyzzy ${LIBUTMPS} -lskarnet
s6-linux-init-shutdown: EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB}
s6-linux-init-shutdown: src/shutdown/s6-linux-init-shutdown.o libhpr.a.xyzzy ${LIBUTMPS} -lskarnet
s6-linux-init-shutdownd: EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB}
diff --git a/package/modes b/package/modes
index a2cac61..ab52a84 100644
--- a/package/modes
+++ b/package/modes
@@ -1,7 +1,5 @@
s6-linux-init 0700
-s6-linux-init-halt 0750
-s6-linux-init-poweroff 0750
-s6-linux-init-reboot 0750
+s6-linux-init-hpr 0750
s6-linux-init-shutdown 0755
s6-linux-init-shutdownd 0700
s6-linux-init-telinit 0750
diff --git a/package/targets.mak b/package/targets.mak
index ebe7d3c..412e9e3 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -1,16 +1,12 @@
-LIBEXEC_TARGETS := \
+BIN_TARGETS := \
s6-linux-init \
-s6-linux-init-halt \
-s6-linux-init-poweroff \
-s6-linux-init-reboot \
+s6-linux-init-hpr \
s6-linux-init-shutdown \
s6-linux-init-shutdownd \
s6-linux-init-telinit \
s6-linux-init-logouthookd \
s6-linux-init-echo \
-s6-linux-init-umountall
-
-BIN_TARGETS := \
+s6-linux-init-umountall \
s6-linux-init-maker
LIB_DEFS := S6_LINUX_INIT=s6_linux_init
diff --git a/skel/rc.shutdown b/skel/rc.shutdown
index 6acd0f0..d72916e 100755
--- a/skel/rc.shutdown
+++ b/skel/rc.shutdown
@@ -5,7 +5,7 @@
### telling it to bring all the services down.
### If your services are managed by sysv-rc:
-### remove the K11reboot link from /etc/rc6.d to prevent
+### also remove the K11reboot link from /etc/rc6.d to prevent
### sysv-rc from rebooting prematurely - because sysvinit does
### not properly separate state changes from system init/shutdown.
# exec /etc/init.d/rc 6
@@ -14,4 +14,4 @@
# exec /sbin/openrc shutdown
### If your services are managed by s6-rc:
-# exec s6-rc -da change
+# exec s6-rc -bda change
diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c
index 82ab14f..f75371f 100644
--- a/src/init/s6-linux-init-maker.c
+++ b/src/init/s6-linux-init-maker.c
@@ -85,6 +85,14 @@ static int linewithargs_script (buffer *b, char const *line)
&& buffer_puts(b, " $@\n") >= 0 ;
}
+static int hpr_script (buffer *b, char const *what)
+{
+ return put_shebang_options(b, "-S0")
+ && buffer_puts(b, S6_LINUX_INIT_BINPREFIX "s6-linux-init-hpr -") >= 0
+ && buffer_puts(b, what) >= 0
+ && buffer_put(b, " $@\n", 1) >= 0 ;
+}
+
static int death_script (buffer *b, char const *s)
{
return put_shebang(b)
@@ -92,11 +100,11 @@ static int death_script (buffer *b, char const *s)
EXECLINE_EXTBINPREFIX "redirfd -w 1 /dev/console\n"
EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n"
EXECLINE_EXTBINPREFIX "foreground { "
- S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-echo -- \"s6-svscan ") >= 0
+ S6_LINUX_INIT_BINPREFIX "s6-linux-init-echo -- \"s6-svscan ") >= 0
&& buffer_puts(b, s) >= 0
&& buffer_puts(b,
". Rebooting.\" }\n"
- S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-reboot\n") >= 0 ;
+ S6_LINUX_INIT_BINPREFIX "s6-linux-init-hpr -r -f\n") >= 0 ;
}
static int s6_svscan_log_script (buffer *b, char const *data)
@@ -139,7 +147,7 @@ static int logouthookd_script (buffer *b, char const *data)
return put_shebang(b)
&& buffer_puts(b,
S6_EXTBINPREFIX "s6-ipcserver -1 -l0 -- " LOGOUTHOOKD_SOCKET "\n"
- S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-logouthookd\n") >= 0 ;
+ S6_LINUX_INIT_BINPREFIX "s6-linux-init-logouthookd\n") >= 0 ;
}
static int shutdownd_script (buffer *b, char const *data)
@@ -147,7 +155,7 @@ static int shutdownd_script (buffer *b, char const *data)
size_t sabase = satmp.len ;
char fmt[UINT_FMT] ;
if (!put_shebang(b)
- || buffer_puts(b, S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-shutdownd -c ") < 0
+ || buffer_puts(b, S6_LINUX_INIT_BINPREFIX "s6-linux-init-shutdownd -c ") < 0
|| !string_quote(&satmp, robase, strlen(robase))) return 0 ;
if (buffer_puts(b, satmp.s + sabase) < 0) goto err ;
satmp.len = sabase ;
@@ -188,7 +196,7 @@ static int runleveld_script (buffer *b, char const *data)
static int sig_script (buffer *b, char const *option)
{
return put_shebang(b)
- && buffer_puts(b, S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-shutdown -a ") >= 0
+ && buffer_puts(b, S6_LINUX_INIT_BINPREFIX "s6-linux-init-shutdown -a ") >= 0
&& buffer_puts(b, option) >= 0
&& buffer_puts(b, " -- now\n") >= 0 ;
}
@@ -197,7 +205,7 @@ static inline int stage1_script (buffer *b, char const *data)
{
size_t sabase = satmp.len ;
if (!put_shebang_options(b, "-S0")
- || buffer_puts(b, S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init -c ") < 0
+ || buffer_puts(b, S6_LINUX_INIT_BINPREFIX "s6-linux-init -c ") < 0
|| !string_quote(&satmp, robase, strlen(robase))) return 0 ;
if (buffer_puts(b, satmp.s + sabase) < 0) goto err ;
satmp.len = sabase ;
@@ -360,12 +368,12 @@ static void copy_script (char const *base, char const *src, char const *dst)
static void auto_exec (char const *base, char const *name, char const *target)
{
- if (S6_LINUX_INIT_LIBEXECPREFIX[0] == '/')
+ if (S6_LINUX_INIT_BINPREFIX[0] == '/')
{
size_t len = strlen(target) ;
- char fn[sizeof(S6_LINUX_INIT_LIBEXECPREFIX) + len] ;
- memcpy(fn, S6_LINUX_INIT_LIBEXECPREFIX, sizeof(S6_LINUX_INIT_LIBEXECPREFIX) - 1) ;
- memcpy(fn + sizeof(S6_LINUX_INIT_LIBEXECPREFIX) - 1, target, len + 1) ;
+ char fn[sizeof(S6_LINUX_INIT_BINPREFIX) + len] ;
+ memcpy(fn, S6_LINUX_INIT_BINPREFIX, sizeof(S6_LINUX_INIT_BINPREFIX) - 1) ;
+ memcpy(fn + sizeof(S6_LINUX_INIT_BINPREFIX) - 1, target, len + 1) ;
auto_symlink(base, name, fn) ;
}
else
@@ -540,12 +548,12 @@ static inline void make_scripts (char const *base)
static inline void make_bins (char const *base)
{
auto_dir(base, "bin", 0, 0, 0755) ;
- auto_exec(base, "bin/halt", "s6-linux-init-halt") ;
- auto_exec(base, "bin/reboot", "s6-linux-init-reboot") ;
- auto_exec(base, "bin/poweroff", "s6-linux-init-poweroff") ;
+ auto_script(base, "bin/init", &stage1_script, 0) ;
+ auto_script(base, "bin/halt", &hpr_script, "h") ;
+ auto_script(base, "bin/poweroff", &hpr_script, "p") ;
+ auto_script(base, "bin/reboot", &hpr_script, "r") ;
auto_exec(base, "bin/shutdown", "s6-linux-init-shutdown") ;
auto_exec(base, "bin/telinit", "s6-linux-init-telinit") ;
- auto_script(base, "bin/init", &stage1_script, 0) ;
}
int main (int argc, char const *const *argv, char const *const *envp)
diff --git a/src/init/s6-linux-init-telinit.c b/src/init/s6-linux-init-telinit.c
index 8678709..42441d6 100644
--- a/src/init/s6-linux-init-telinit.c
+++ b/src/init/s6-linux-init-telinit.c
@@ -24,7 +24,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:p:s:m:d:", &l) ;
+ int opt = subgetopt_r(argc, argv, "c:p:s:m:d:D:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -32,7 +32,8 @@ int main (int argc, char const *const *argv, char const *const *envp)
case 'p' :
case 's' :
case 'm' :
- case 'd' : break ;
+ case 'd' :
+ case 'D' : break ;
default : dieusage() ;
}
}
@@ -63,9 +64,10 @@ int main (int argc, char const *const *argv, char const *const *envp)
fmt[uint_fmt(fmt, WEXITSTATUS(wstat))] = 0 ;
strerr_dief3x(wait_estatus(wstat), newargv[0], " died with exitcode ", fmt) ;
}
-
- newargv[0] = argv[0][0] == '6' ? S6_LINUX_INIT_BINPREFIX "reboot" : S6_LINUX_INIT_BINPREFIX "poweroff" ;
- newargv[1] = 0 ;
+
+ newargv[0] = S6_LINUX_INIT_BINPREFIX "s6-linux-init-hpr" ;
+ newargv[1] = argv[0][0] == '6' ? "-r" : "-p" ;
+ newargv[2] = 0 ;
}
xpathexec_run(newargv[0], newargv, envp) ;
diff --git a/src/lib/s6_linux_init_logouthook.c b/src/lib/s6_linux_init_logouthook.c
index 215365d..810f29b 100644
--- a/src/lib/s6_linux_init_logouthook.c
+++ b/src/lib/s6_linux_init_logouthook.c
@@ -3,6 +3,7 @@
#include <skalibs/djbunix.h>
#include <skalibs/webipc.h>
+#include <s6-linux-init/s6-linux-init.h>
#include "initctl.h"
int s6_linux_init_logouthook (void)
diff --git a/src/shutdown/deps-exe/s6-linux-init-halt b/src/shutdown/deps-exe/s6-linux-init-hpr
index 0c4376c..0c4376c 100644
--- a/src/shutdown/deps-exe/s6-linux-init-halt
+++ b/src/shutdown/deps-exe/s6-linux-init-hpr
diff --git a/src/shutdown/deps-exe/s6-linux-init-poweroff b/src/shutdown/deps-exe/s6-linux-init-poweroff
deleted file mode 100644
index 0c4376c..0000000
--- a/src/shutdown/deps-exe/s6-linux-init-poweroff
+++ /dev/null
@@ -1,5 +0,0 @@
-libhpr.a.xyzzy
-${LIBUTMPS}
--lskarnet
-${TAINNOW_LIB}
-${SOCKET_LIB}
diff --git a/src/shutdown/deps-exe/s6-linux-init-reboot b/src/shutdown/deps-exe/s6-linux-init-reboot
deleted file mode 100644
index 0c4376c..0000000
--- a/src/shutdown/deps-exe/s6-linux-init-reboot
+++ /dev/null
@@ -1,5 +0,0 @@
-libhpr.a.xyzzy
-${LIBUTMPS}
--lskarnet
-${TAINNOW_LIB}
-${SOCKET_LIB}
diff --git a/src/shutdown/hpr_shutdown.c b/src/shutdown/hpr_shutdown.c
index 9c9ff51..3ede92d 100644
--- a/src/shutdown/hpr_shutdown.c
+++ b/src/shutdown/hpr_shutdown.c
@@ -9,7 +9,7 @@
int hpr_shutdown (unsigned int what, tain_t const *when, unsigned int grace)
{
- char pack[5 + TAIN_PACK] = { " hpr"[what] } ;
+ char pack[5 + TAIN_PACK] = { "Shpr"[what] } ;
tain_pack(pack+1, when) ;
uint32_pack_big(pack + 1 + TAIN_PACK, (uint32_t)grace) ;
return hpr_send(pack, 5 + TAIN_PACK) ;
diff --git a/src/shutdown/s6-linux-init-halt.c b/src/shutdown/s6-linux-init-halt.c
deleted file mode 100644
index 4ccca1d..0000000
--- a/src/shutdown/s6-linux-init-halt.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* ISC license. */
-
-#undef PROGNAME
-#define PROGNAME "s6-linux-init-halt"
-#undef WHATDEFAULT
-#define WHATDEFAULT 1
-#include "hpr.c"
diff --git a/src/shutdown/hpr.c b/src/shutdown/s6-linux-init-hpr.c
index a769c8c..c5f7afb 100644
--- a/src/shutdown/hpr.c
+++ b/src/shutdown/s6-linux-init-hpr.c
@@ -29,15 +29,15 @@
#define _PATH_WTMP "/dev/null/wtmp"
#endif
-#define USAGE PROGNAME " [ -h | -p | -r ] [ -d | -w ] [ -W ] [ -f ]"
+#define USAGE "s6-linux-init-hpr [ -h | -p | -r ] [ -d | -w ] [ -W ] [ -f ]"
int main (int argc, char const *const *argv)
{
- int what = WHATDEFAULT ;
+ int what = 0 ;
int force = 0 ;
int dowtmp = 1 ;
int dowall = 1 ;
- PROG = PROGNAME ;
+ PROG = "s6-linux-init-hpr" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
@@ -60,6 +60,9 @@ int main (int argc, char const *const *argv)
argc -= l.ind ; argv += l.ind ;
}
+ if (!what)
+ strerr_dief1x(100, "one of the -h, -p or -r options must be given") ;
+
if (geteuid())
{
errno = EPERM ;
diff --git a/src/shutdown/s6-linux-init-poweroff.c b/src/shutdown/s6-linux-init-poweroff.c
deleted file mode 100644
index d25dbb6..0000000
--- a/src/shutdown/s6-linux-init-poweroff.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* ISC license. */
-
-#undef PROGNAME
-#define PROGNAME "s6-linux-init-poweroff"
-#undef WHATDEFAULT
-#define WHATDEFAULT 2
-#include "hpr.c"
diff --git a/src/shutdown/s6-linux-init-reboot.c b/src/shutdown/s6-linux-init-reboot.c
deleted file mode 100644
index 3612684..0000000
--- a/src/shutdown/s6-linux-init-reboot.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* ISC license. */
-
-#undef PROGNAME
-#define PROGNAME "s6-linux-init-reboot"
-#undef WHATDEFAULT
-#define WHATDEFAULT 3
-#include "hpr.c"
diff --git a/src/shutdown/s6-linux-init-shutdownd.c b/src/shutdown/s6-linux-init-shutdownd.c
index c6d6316..90d43e8 100644
--- a/src/shutdown/s6-linux-init-shutdownd.c
+++ b/src/shutdown/s6-linux-init-shutdownd.c
@@ -36,6 +36,41 @@
static char const *basedir = BASEDIR ;
+static inline void run_stage3 (char const *basedir, char const *const *envp)
+{
+ pid_t pid ;
+ size_t basedirlen = strlen(basedir) ;
+ char stage3[basedirlen + sizeof("/" STAGE3)] ;
+ char const *stage3_argv[2] = { stage3, 0 } ;
+ memcpy(stage3, basedir, basedirlen) ;
+ memcpy(stage3 + basedirlen, "/" STAGE3, sizeof("/" STAGE3)) ;
+ pid = child_spawn0(stage3_argv[0], stage3_argv, envp) ;
+ if (pid)
+ {
+ int wstat ;
+ if (wait_pid(pid, &wstat) == -1) strerr_diefu1sys(111, "waitpid") ;
+ if (WIFSIGNALED(wstat))
+ {
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ;
+ strerr_warnw3x(stage3, " was killed by signal ", fmt) ;
+ }
+ else if (WEXITSTATUS(wstat))
+ {
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ;
+ strerr_warnw3x(stage3, " was killed by signal ", fmt) ;
+ }
+ else if (WEXITSTATUS(wstat))
+ {
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, WEXITSTATUS(wstat))] = 0 ;
+ strerr_warnw3x(stage3, " exited ", fmt) ;
+ }
+ }
+ else strerr_warnwu2sys("spawn ", stage3) ;
+}
+
static inline void prepare_shutdown (char c, unsigned int *what, tain_t *deadline, unsigned int *grace_time)
{
uint32_t u ;
@@ -43,22 +78,23 @@ static inline void prepare_shutdown (char c, unsigned int *what, tain_t *deadlin
ssize_t r = sanitize_read(buffer_get(buffer_0small, pack, TAIN_PACK)) ;
if (r == -1) strerr_diefu1sys(111, "read from pipe") ;
if (r < TAIN_PACK + 4) strerr_dief1x(101, "bad shutdown protocol") ;
+ *what = byte_chr("Shpr", c, 4) ;
tain_unpack(pack, deadline) ;
uint32_unpack_big(pack + TAIN_PACK, &u) ;
if (u && u <= 300000) *grace_time = u ;
- *what = 1 + byte_chr("hpr", c, 3) ;
}
-static inline void handle_stdin (unsigned int *what, tain_t *deadline, unsigned int *grace_time)
+static inline void handle_fifo (buffer *b, unsigned int *what, tain_t *deadline, unsigned int *grace_time)
{
for (;;)
{
char c ;
- ssize_t r = sanitize_read(buffer_get(buffer_0small, &c, 1)) ;
+ ssize_t r = sanitize_read(buffer_get(b, &c, 1)) ;
if (r == -1) strerr_diefu1sys(111, "read from pipe") ;
else if (!r) break ;
switch (c)
{
+ case 'S' :
case 'h' :
case 'p' :
case 'r' :
@@ -80,7 +116,6 @@ static inline void handle_stdin (unsigned int *what, tain_t *deadline, unsigned
static inline void prepare_stage4 (char const *basedir, unsigned int what)
{
- static char const *table[3] = { "halt", "poweroff", "reboot" } ;
buffer b ;
int fd ;
char buf[512] ;
@@ -92,9 +127,9 @@ static inline void prepare_stage4 (char const *basedir, unsigned int what)
if (buffer_puts(&b,
"#!" EXECLINE_SHEBANGPREFIX "/execlineb -P\n\n"
EXECLINE_EXTBINPREFIX "foreground { "
- S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-umountall }\n"
- S6_LINUX_INIT_LIBEXECPREFIX "s6-linux-init-") < 0
- || buffer_puts(&b, table[what-1]) < 0
+ S6_LINUX_INIT_BINPREFIX "s6-linux-init-umountall }\n"
+ S6_LINUX_INIT_BINPREFIX "s6-linux-init-hpr -") < 0
+ || buffer_put(&b, "hpr" + what - 1, 1) < 0
|| buffer_putsflush(&b, " -f\n") < 0)
strerr_diefu2sys(111, "write to ", STAGE4_FILE ".new") ;
if (fchmod(fd, S_IRWXU) == -1)
@@ -106,10 +141,12 @@ static inline void prepare_stage4 (char const *basedir, unsigned int what)
int main (int argc, char const *const *argv, char const *const *envp)
{
- pid_t pid ;
- tain_t deadline ;
unsigned int what = 0 ;
unsigned int grace_time = 3000 ;
+ tain_t deadline ;
+ int fdr, fdw ;
+ buffer b ;
+ char buf[64] ;
PROG = "s6-linux-init-shutdownd" ;
{
@@ -139,80 +176,46 @@ int main (int argc, char const *const *argv, char const *const *envp)
strerr_warnwu2sys("exec ", stage4_argv[0]) ;
}
- fd_close(1) ;
- fd_close(0) ;
-
- if (open_read(SHUTDOWND_FIFO))
+ fdr = open_read(SHUTDOWND_FIFO) ;
+ if (fdr == -1 || coe(fdr) == -1)
strerr_diefu3sys(111, "open ", SHUTDOWND_FIFO, " for reading") ;
- if (open_write(SHUTDOWND_FIFO) != 1)
+ fdw = open_write(SHUTDOWND_FIFO) ;
+ if (fdw == -1 || coe(fdw) == -1)
strerr_diefu3sys(111, "open ", SHUTDOWND_FIFO, " for writing") ;
if (sig_ignore(SIGPIPE) == -1)
strerr_diefu1sys(111, "sig_ignore SIGPIPE") ;
+ buffer_init(&b, &buffer_read, fdr, buf, 64) ;
tain_now_g() ;
tain_add_g(&deadline, &tain_infinite_relative) ;
for (;;)
{
- iopause_fd x = { .fd = 0, .events = IOPAUSE_READ } ;
+ iopause_fd x = { .fd = fdr, .events = IOPAUSE_READ } ;
int r = iopause_g(&x, 1, &deadline) ;
if (r == -1) strerr_diefu1sys(111, "iopause") ;
if (!r)
{
+ run_stage3(basedir, envp) ;
+ tain_now_g() ;
if (what) break ;
tain_add_g(&deadline, &tain_infinite_relative) ;
continue ;
}
if (x.revents & IOPAUSE_READ)
- handle_stdin(&what, &deadline, &grace_time) ;
+ handle_fifo(&b, &what, &deadline, &grace_time) ;
}
-
- /* Stage 3 */
-
+ fd_close(fdw) ;
+ fd_close(fdr) ;
fd_close(1) ;
- fd_close(0) ;
- if (open_readb("/dev/null"))
- strerr_diefu1sys(111, "open /dev/null for reading") ;
if (open_write("/dev/console") != 1 || ndelay_off(1) == -1)
strerr_diefu1sys(111, "open /dev/console for writing") ;
- {
- size_t basedirlen = strlen(basedir) ;
- char stage3[basedirlen + sizeof("/" STAGE3)] ;
- char const *stage3_argv[2] = { stage3, 0 } ;
- memcpy(stage3, basedir, basedirlen) ;
- memcpy(stage3 + basedirlen, "/" STAGE3, sizeof("/" STAGE3)) ;
- pid = child_spawn0(stage3_argv[0], stage3_argv, envp) ;
- if (pid)
- {
- int wstat ;
- if (wait_pid(pid, &wstat) == -1) strerr_diefu1sys(111, "waitpid") ;
- if (WIFSIGNALED(wstat))
- {
- char fmt[UINT_FMT] ;
- fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ;
- strerr_warnw3x(stage3, " was killed by signal ", fmt) ;
- }
- else if (WEXITSTATUS(wstat))
- {
- char fmt[UINT_FMT] ;
- fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ;
- strerr_warnw3x(stage3, " was killed by signal ", fmt) ;
- }
- else if (WEXITSTATUS(wstat))
- {
- char fmt[UINT_FMT] ;
- fmt[uint_fmt(fmt, WEXITSTATUS(wstat))] = 0 ;
- strerr_warnw3x(stage3, " exited ", fmt) ;
- }
- }
- else strerr_warnwu2sys("spawn ", stage3) ;
- }
+ if (fd_copy(2, 1) == -1) strerr_warnwu1sys("fd_copy") ;
/* The end is coming! */
prepare_stage4(basedir, what) ;
- if (fd_move(2, 1) == -1) strerr_warnwu1sys("fd_move") ;
sync() ;
if (sig_ignore(SIGTERM) == -1) strerr_warnwu1sys("sig_ignore SIGTERM") ;
strerr_warni1x("sending all processes the TERM signal...") ;