summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL2
-rw-r--r--doc/index.html2
-rw-r--r--doc/s6-linux-init-maker.html38
-rw-r--r--doc/upgrade.html3
-rwxr-xr-xexamples/rc.init4
-rwxr-xr-xexamples/rc.shutdown19
-rwxr-xr-xexamples/rc.tini3
-rw-r--r--src/init/s6-linux-init-maker.c67
8 files changed, 132 insertions, 6 deletions
diff --git a/INSTALL b/INSTALL
index c93d004..90f83e3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -10,7 +10,7 @@ Build Instructions
- execline version 2.1.4.1 or later: http://skarnet.org/software/execline/
- s6-portable-utils version 2.0.5.3 or later: http://skarnet.org/software/s6-portable-utils/
- s6-linux-utils version 2.0.2.3 or later: http://skarnet.org/software/s6-linux-utils/
- - s6 version 2.2.1.1 or later: http://skarnet.org/software/s6/
+ - s6 version 2.2.2.0 or later: http://skarnet.org/software/s6/
Note that all those are build-time dependencies, and they are
*also* run-time dependencies when you use the init binary created
diff --git a/doc/index.html b/doc/index.html
index 260b286..f328f44 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -58,7 +58,7 @@ a small FAQ.
<li> <a href="http://skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> version
2.0.2.3 or later </li>
<li> <a href="http://skarnet.org/software/s6/">s6</a> version
-2.2.1.1 or later </li>
+2.2.2.0 or later </li>
</ul>
<p>
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html
index 530cd41..95c0101 100644
--- a/doc/s6-linux-init-maker.html
+++ b/doc/s6-linux-init-maker.html
@@ -50,6 +50,7 @@ machine</em> - else the scripts will crash.
[ -g <em>early_getty</em> ] \
[ -2 <em>stage2</em> ] \
[ -r ] \
+ [ -Z ] <em>stage2_finish</em> \
[ -3 <em>stage3</em> ] \
[ -p <em>initial_path</em> ] \
[ -m <em>initial_umask</em> ] \
@@ -186,6 +187,37 @@ do not hold any file descriptor to a filesystem that would need to be
unmounted. </li>
</ul>
+<p>
+ When s6-svscan receives a signal such as SIGINT, typically sent by the
+Ctrl-Alt-Del key combination or a <tt>reboot</tt> or <tt>poweroff</tt>
+command, it will run the corresponding script in
+<tt><em>tmpfsdir</em>/service/.s6-svscan</tt>, which will first run
+<em>stage2_finish</em>, then send an exit command to s6-svscan as
+described above. This is useful if some commands need to be run before
+s6-svscan executes into <em>stage3</em>: for instance, if the machine
+state is maintained by a service manager such as
+<a href="http://skarnet.org/software/s6-rc/">s6-rc</a>, all the
+services can be turned off in <em>stage2_finish</em> while s6-svscan
+is still alive, and then the last steps of the shutdown procedure can
+be performed in <em>stage3</em>.
+</p>
+
+<p>
+ Generally speaking, <em>stage2_finish</em> should undo what
+<em>stage2</em> has done at boot time, so <em>stage3</em> has very
+little work to do.
+</p>
+
+<p>
+ The <tt>examples/</tt> subdirectory of the s6-linux-init package
+contains an example of <tt>/etc/rc.init</tt>, <tt>/etc/rc.tini</tt>
+and <tt>/etc/rc.shutdown</tt> scripts, suitable for
+<em>stage2</em>, <em>stage2_finish</em> and <em>stage3</em>
+respectively. Those scripts can practically be used as is if the machine
+is managed by the <a href="http://skarnet.org/software/s6-rc/">s6-rc</a>
+service manager.
+</p>
+
<h2> s6-linux-init-maker options </h2>
<ul>
@@ -235,6 +267,12 @@ with an early getty, or be undesirable for other reasons. The
to the catch-all logger, so the output will be made available
in the <tt><em>tmpfsdir</em>/uncaught-logs</tt> directory. </li> <p />
+ <li> <tt>-Z</tt>&nbsp;<em>stage2_finish</em>&nbsp;:
+<em>stage2_finish</em> is the location of the script that will be
+run when s6-svscan receives a signal that tells it to stop the
+machine, before it executes into <em>stage3</em>. It must be
+absolute. Default is <strong><tt>/etc/rc.tini</tt></strong>. </li> <p />
+
<li> <tt>-3</tt>&nbsp;<em>stage3</em>&nbsp;: <em>stage3</em> is
the location of the stage 3 script that will be run at the end of
the machine lifetime, when s6-svscan is told to terminate.
diff --git a/doc/upgrade.html b/doc/upgrade.html
index a5787ed..3118cbf 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -30,7 +30,8 @@ dependency bumped to 2.0.5.3. </li>
<li> <a href="http://skarnet.org/software/s6-linux-utils/">s6-linux-utils</a>
dependency bumped to 2.0.2.3. </li>
<li> <a href="http://skarnet.org/software/s6/">s6</a>
-dependency bumped to 2.2.1.1. </li>
+dependency bumped to 2.2.2.0. </li>
+ <li> <em>stage2_finish</em> support added. </li>
</ul>
<h2> in 0.0.1.3 </h2>
diff --git a/examples/rc.init b/examples/rc.init
new file mode 100755
index 0000000..e0b2b72
--- /dev/null
+++ b/examples/rc.init
@@ -0,0 +1,4 @@
+#!/bin/execlineb -P
+
+if { s6-rc-init /run/service }
+s6-rc -u change ok-all
diff --git a/examples/rc.shutdown b/examples/rc.shutdown
new file mode 100755
index 0000000..5589903
--- /dev/null
+++ b/examples/rc.shutdown
@@ -0,0 +1,19 @@
+#!/bin/execlineb -S0
+
+foreground { s6-echo "Syncing disks." }
+foreground { s6-sync }
+foreground { s6-echo "Sending all processes the TERM signal." }
+foreground { s6-nuke -th }
+s6-sleep 2
+foreground { s6-echo "Sending all processes the KILL signal." }
+foreground { s6-nuke -k }
+wait { }
+
+foreground { s6-echo "Syncing disks." }
+foreground { s6-sync }
+foreground { s6-echo "Unmounting disks." }
+foreground { s6-umount -a }
+foreground { s6-mount -o ro,remount /dev/root / }
+
+foreground { s6-echo "\nPerforming "${1}"." }
+s6-${1}
diff --git a/examples/rc.tini b/examples/rc.tini
new file mode 100755
index 0000000..abefb22
--- /dev/null
+++ b/examples/rc.tini
@@ -0,0 +1,3 @@
+#!/bin/execlineb -P
+
+s6-rc -da change
diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c
index b0663e2..87d3787 100644
--- a/src/init/s6-linux-init-maker.c
+++ b/src/init/s6-linux-init-maker.c
@@ -18,7 +18,7 @@
#include <skalibs/sgetopt.h>
#include <skalibs/skamisc.h>
-#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -g early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -e initial_envvar ... ] dir"
+#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -g early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -Z finish_script ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -e initial_envvar ... ] dir"
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "stralloc_catb") ;
@@ -35,6 +35,7 @@
static char const *slashrun = "/run" ;
static char const *robase = "/etc/s6-linux-init" ;
static char const *init_script = "/etc/rc.init" ;
+static char const *tini_script = "/etc/rc.tini" ;
static char const *shutdown_script = "/etc/rc.shutdown" ;
static char const *bindir = "/bin" ;
static char const *initial_path = SKALIBS_DEFAULTPATH ;
@@ -117,6 +118,57 @@ static int finish_script (buffer *b)
return 0 ;
}
+static int sig_script (buffer *b, char c)
+{
+ unsigned int sabase = satmp.len ;
+ if (!put_shebang(b)
+ || buffer_puts(b, "foreground { ") < 0
+ || !string_quote(&satmp, tini_script, str_len(tini_script))) return 0 ;
+ if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
+ satmp.len = sabase ;
+ if (buffer_puts(b, " }\ns6-svscanctl -") < 0
+ || buffer_put(b, &c, 1) < 0
+ || buffer_puts(b, " -- ") < 0
+ || !string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ;
+ if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
+ satmp.len = sabase ;
+ if (buffer_puts(b, "/service\n") < 0) return 0 ;
+ return 1 ;
+ err:
+ satmp.len = sabase ;
+ return 0 ;
+}
+
+static int sigterm_script (buffer *b)
+{
+ return sig_script(b, 't') ;
+}
+
+static int sighup_script (buffer *b)
+{
+ return sig_script(b, 'h') ;
+}
+
+static int sigquit_script (buffer *b)
+{
+ return sig_script(b, 'q') ;
+}
+
+static int sigint_script (buffer *b)
+{
+ return sig_script(b, '6') ;
+}
+
+static int sigusr1_script (buffer *b)
+{
+ return sig_script(b, '7') ;
+}
+
+static int sigusr2_script (buffer *b)
+{
+ return sig_script(b, '0') ;
+}
+
static void cleanup (char const *base)
{
int e = errno ;
@@ -205,6 +257,12 @@ static inline void make_image (char const *base)
auto_dir(base, "run-image/service/.s6-svscan", 0, 0, 0755) ;
auto_script(base, "run-image/service/.s6-svscan/crash", &crash_script) ;
auto_script(base, "run-image/service/.s6-svscan/finish", &finish_script) ;
+ auto_script(base, "run-image/service/.s6-svscan/SIGTERM", &sigterm_script) ;
+ auto_script(base, "run-image/service/.s6-svscan/SIGHUP", &sighup_script) ;
+ auto_script(base, "run-image/service/.s6-svscan/SIGQUIT", &sigquit_script) ;
+ auto_script(base, "run-image/service/.s6-svscan/SIGINT", &sigint_script) ;
+ auto_script(base, "run-image/service/.s6-svscan/SIGUSR1", &sigusr1_script) ;
+ auto_script(base, "run-image/service/.s6-svscan/SIGUSR2", &sigusr2_script) ;
auto_dir(base, "run-image/service/s6-svscan-log", 0, 0, 0755) ;
auto_fifo(base, "run-image/service/s6-svscan-log/fifo") ;
auto_script(base, "run-image/service/s6-svscan-log/run", &s6_svscan_log_script) ;
@@ -280,7 +338,7 @@ static inline int make_init_script (buffer *b)
|| buffer_put(b, satmp.s + pos2, satmp.len - pos2) < 0
|| buffer_puts(b, "\n}\nunexport !\ncd ") < 0
|| buffer_put(b, satmp.s + sabase, pos - sabase) < 0
- || buffer_puts(b, "/service\nfdmove -c 2 1\ns6-svscan -t0\n") < 0) goto err ;
+ || buffer_puts(b, "/service\nfdmove -c 2 1\ns6-svscan -st0\n") < 0) goto err ;
return 1 ;
err:
satmp.len = sabase ;
@@ -295,7 +353,7 @@ int main (int argc, char const *const *argv)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:r3:p:m:t:d:e:", &l) ;
+ register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:rZ:3:p:m:t:d:e:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -306,6 +364,7 @@ int main (int argc, char const *const *argv)
case 'g' : early_getty = l.arg ; break ;
case '2' : init_script = l.arg ; break ;
case 'r' : redirect_stage2 = 1 ; break ;
+ case 'Z' : tini_script = l.arg ; break ;
case '3' : shutdown_script = l.arg ; break ;
case 'p' : initial_path = l.arg ; break ;
case 'm' : if (!uint0_oscan(l.arg, &initial_umask)) dieusage() ; break ;
@@ -327,6 +386,8 @@ int main (int argc, char const *const *argv)
strerr_dief3x(100, "initial location for binaries ", bindir, " is not absolute") ;
if (init_script[0] != '/')
strerr_dief3x(100, "stage 2 script location ", init_script, " is not absolute") ;
+ if (tini_script[0] != '/')
+ strerr_dief3x(100, "stage 2 finish script location ", tini_script, " is not absolute") ;
if (shutdown_script[0] != '/')
strerr_dief3x(100, "stage 3 script location ", shutdown_script, " is not absolute") ;
if (timestamp_style > 3)