commit 4da6b9c320e6b49d38af5cb6b5861480141f24cd parent 478dd24279f833042a94590df0726d163b576af5 Author: Laurent Bercot <ska-skaware@skarnet.org> Date: Tue, 6 Oct 2015 16:23:19 +0000 - add -s support to s6-svscan - change examples to support -s - change examples to invoke s6-rc, remove servicedirs Diffstat:
57 files changed, 159 insertions(+), 178 deletions(-)
diff --git a/doc/index.html b/doc/index.html @@ -101,7 +101,7 @@ library. </li> <h3> Download </h3> <ul> - <li> The current released version of s6 is <a href="s6-2.2.1.1.tar.gz">2.2.1.1</a>. </li> + <li> The current released version of s6 is <a href="s6-2.2.2.0.tar.gz">2.2.2.0</a>. </li> <li> Alternatively, you can checkout a copy of the s6 git repository: <pre> git clone git://git.skarnet.org/s6 </pre> </li> <li> There's also a diff --git a/doc/libs6/index.html b/doc/libs6/index.html @@ -54,7 +54,7 @@ stands for your skalibs sysdeps directory. </li> <p> The <tt>s6/s6.h</tt> header is actually a concatenation of other headers: -the libs6net is separated into several modules, each of them with its +the libs6 is separated into several modules, each of them with its own header. </p> diff --git a/doc/s6-svscan.html b/doc/s6-svscan.html @@ -27,7 +27,7 @@ the root or a branch of a <em>supervision tree</em>. <h2> Interface </h2> <pre> - s6-svscan [ -c max ] [ -t <em>rescan</em> ] [ <em>scandir</em> ] + s6-svscan [ -S | -s ] [ -c max ] [ -t <em>rescan</em> ] [ <em>scandir</em> ] </pre> <ul> @@ -59,6 +59,9 @@ execution. </li> <h2> Options </h2> <ul> + <li> <tt>-S </tt> : do not divert signals. This is the default for now; +it may change in a future version of s6. </li> + <li> <tt>-s </tt> : divert signals - see below. </li> <li> <tt>-c <em>max</em></tt> : maintain services for up to <em>max</em> service directories. Default is 500. Lower limit is 2. There is no upper limit, but: <ul> @@ -82,20 +85,67 @@ scan (and a reap) every 5 seconds. It is <em>strongly</em> discouraged to set <h2> Signals </h2> <p> - s6-svscan reacts to the following signals: + s6-svscan always reacts to the following signals: </p> <ul> <li> SIGCHLD : triggers the reaper. </li> <li> SIGALRM : triggers the scanner. </li> + <li> SIGABRT : acts as if a <tt>s6-svscanctl -b</tt> command had been received. </li> +</ul> + +<p> + By default, it also reacts to the following signals: +</p> + +<ul> <li> SIGTERM : acts as if a <tt>s6-svscanctl -t</tt> command had been received. </li> <li> SIGHUP : acts as if a <tt>s6-svscanctl -h</tt> command had been received. </li> <li> SIGQUIT : acts as if a <tt>s6-svscanctl -q</tt> command had been received. </li> - <li> SIGABRT : acts as if a <tt>s6-svscanctl -b</tt> command had been received. </li> <li> SIGINT : acts as if a <tt>s6-svscanctl -6</tt> command had been received. </li> - <li> SIGUSR1 : acts as if a <tt>s6-svscanctl -7</tt> command had been received. </li> </ul> +<p> + But if the <tt>-s</tt> option was given, then instead of those default actions, +s6-svscan uses configurable handlers: it forks and executes a program every time +it receives one of the following signals. +</p> + +<ul> + <li> SIGTERM : fork and execute <tt>.s6-svscan/SIGTERM</tt> </li> + <li> SIGHUP : fork and execute <tt>.s6-svscan/SIGHUP</tt> </li> + <li> SIGQUIT : fork and execute <tt>.s6-svscan/SIGQUIT</tt> </li> + <li> SIGINT : fork and execute <tt>.s6-svscan/SIGINT</tt> </li> + <li> SIGUSR1 : fork and execute <tt>.s6-svscan/SIGUSR1</tt> </li> + <li> SIGUSR2 : fork and execute <tt>.s6-svscan/SIGUSR2</tt> </li> +</ul> + +<p> + If an action cannot be taken (the relevant file doesn't exist, or isn't +executable, or any kind of error happens), s6-svscan prints a warning +message to its standard error but does nothing else with the signal. +</p> + +<p> + The <tt>-s</tt> mechanism is useful, for instance, when s6-svscan is running as +process 1 and needs to trap signals such as SIGINT (sent on some systems by +a Ctrl-Alt-Del press) in order to perform some specific work instead of +executing into <tt>.s6-svscan/finish</tt> on the spot. +</p> + +<p> + s6-svscan will not exit its loop on its own when it receives a signal such as +SIGINT and the <tt>-s</tt> option has been given. To make it exit its loop, +invoke a <a href="s6-svscanctl.html">s6-svscanctl</a> command from the signal +handling script. For instance, a <tt>.s6-svscan/SIGINT</tt> script could look +like this: +</p> + +<pre> #!/command/execlineb -P + foreground { shutdown-the-services } + s6-svscanctl -i . +</pre> + <h2> The reaper </h2> <p> diff --git a/doc/ucspilogd.html b/doc/ucspilogd.html @@ -79,7 +79,7 @@ than a standard <em>syslogd</em>. </p> <p> - In the <tt>examples/ROOT/img/services-local/syslogd-linux</tt> subdirectory of the s6 package, you will + In the <tt>examples/syslogd-linux</tt> subdirectory of the s6 package, you will find a suitable ucspilogd <a href="servicedir.html">service directory</a>. The run scripts are written in the <a href="http://skarnet.org/software/execline/">execline</a> @@ -97,7 +97,7 @@ You can use <tt>ucspilogd</tt> to process data from those interfaces. </p> <p> - The <tt>examples/ROOT/img/services-local/klogd-linux</tt> subdirectory of the s6 package + The <tt>examples/klogd-linux</tt> subdirectory of the s6 package is a <a href="servicedir.html">service directory</a> providing such a <em>klogd</em> service for Linux, using the <tt>/proc/kmsg</tt> interface. </p> diff --git a/doc/upgrade.html b/doc/upgrade.html @@ -18,6 +18,13 @@ <h1> What has changed in s6 </h1> +<h2> in 2.2.2.0 </h2> + +<ul> + <li> <a href="s6-svscan.html">s6-svscan</a> now supports the <tt>-s</tt> +option for configurable signal management. </li> +</ul> + <h2> in 2.2.1.1 </h2> <ul> diff --git a/examples/ROOT/etc/s6-init/init-stage1 b/examples/ROOT/etc/s6-init/init-stage1 @@ -56,4 +56,4 @@ background unexport ! # Start stage 2. -s6-svscan -t0 /service +s6-svscan -st0 /service diff --git a/examples/ROOT/etc/s6-init/init-stage2 b/examples/ROOT/etc/s6-init/init-stage2 @@ -4,7 +4,6 @@ # starts. It should perform all the remaining one-time initialization # tasks. - if -nt { @@ -12,22 +11,9 @@ if -nt # NOT on /dev/console ! if { s6-echo "* init-stage2 starting." } -# Call your one-time early initialization scripts (before bringing -# the network up) here: -# set the hostname, mount filesystems, adjust sysctls, etc. -# if { s6-mount -wt devpts -o noexec,nosuid,gid=0,mode=0600 devpts /dev/pts } -# if { s6-mount -wt ext4 /dev/sda3 /mnt/rwfs } - -# Start the local services - if { s6-hiercopy /img/services-local /service } - if { s6-svscanctl -a /service } - -# Bring up the network - if { /etc/s6-init/network-config } - -# Start the late services - if { s6-hiercopy /img/services-network /service } - if { s6-svscanctl -a /service } +# Call your service manager commands here to run the boot scripts. + if { s6-rc-init /service } + if { s6-rc -u change normal-state } # We're done and the machine is fully operational. s6-echo "* init-stage2 completed." diff --git a/examples/ROOT/etc/s6-init/init-stage3 b/examples/ROOT/etc/s6-init/init-stage3 @@ -13,7 +13,7 @@ foreground { s6-echo "Syncing disks." } foreground { s6-sync } -# Even if s6-svscan properly brought all the services down +# Even if s6-rc and s6-svscan properly brought all the services down # before exec'ing into this script, users might have launched # background nohup processes, so we have to kill everything. diff --git a/examples/ROOT/etc/s6-init/network-config b/examples/ROOT/etc/s6-init/network-config @@ -1,5 +0,0 @@ -#!/command/execlineb -P - -# if { ifconfig lo 127.0.0.1 netmask 255.0.0.0 } - -# Configure your network interfaces and routing here. diff --git a/examples/ROOT/etc/s6-rc/README b/examples/ROOT/etc/s6-rc/README @@ -0,0 +1,9 @@ + If you are using s6-rc as your service manager, this directory should +be the place where you store your compiled service databases. + + The /etc/s6-init/init-stage2 script invokes s6-rc which expects to +find its data here by default. + + The /run/service/.s6-svscan/SIG{INT,USR1,USR2} scripts invoke +s6-rc to bring down all the managed services before shutting down +s6-svscan. diff --git a/examples/ROOT/img/README b/examples/ROOT/img/README @@ -1,9 +1,4 @@ -This directory is read-only. It contains the service -repository (actually one list of services that do not -need the network and one list of services that can only -be started after the network is up), and an image of the +This directory is read-only. It contains an image of the tmpfs that it copied as-is at boot-time (during stage 1 -init). -This directory is only used at boot-time, it is never -written to (the service directories are copied as-is -to /service during stage 2 init). +init). It is only used at boot-time, it is never +written to. diff --git a/examples/ROOT/img/services-local/README b/examples/ROOT/img/services-local/README @@ -1,5 +0,0 @@ -This is the service repository for services that should be started -early, typically before the network goes up. -"klogd" and "syslogd" services should be present as soon as possible, -because other services might need them. However, since they need -a writable disk filesystem, they can't be run as early as a getty. diff --git a/examples/ROOT/img/services-local/klogd-linux/README b/examples/ROOT/img/services-local/klogd-linux/README @@ -1,3 +0,0 @@ -This klogd emulation is only valid under Linux. -The service only processes logs from /proc/kmsg and -sends them to stdout, i.e. its own logger. diff --git a/examples/ROOT/img/services-local/syslogd-linux/README b/examples/ROOT/img/services-local/syslogd-linux/README @@ -1,7 +0,0 @@ -This syslogd emulation works on any Unix where syslog() is -implemented via a connection on the /dev/log Unix-domain socket. -It needs a Unix superserver (see s6-networking, ucspi-unix or -ucspi-ipc) and ucspilogd. -A ucspilogd process is spawned for every syslog() client. It -processes logs and sends them to stderr, i.e. the service's -logger. diff --git a/examples/ROOT/img/services-network/README b/examples/ROOT/img/services-network/README @@ -1,5 +0,0 @@ -This is the service repository for all the late services, -i.e. those that do not need to be started before the network -is up. -Only a few examples are provided here; you can make your own -service directories depending on your needs. diff --git a/examples/ROOT/img/services-network/dns-cache/README b/examples/ROOT/img/services-network/dns-cache/README @@ -1,2 +0,0 @@ -Service directory for a DNS caching resolver service, -implemented via djbdns's dnscache running on 127.0.0.1 diff --git a/examples/ROOT/img/services-network/dns-cache/env/CACHESIZE b/examples/ROOT/img/services-network/dns-cache/env/CACHESIZE @@ -1 +0,0 @@ -1048576 diff --git a/examples/ROOT/img/services-network/dns-cache/env/IP b/examples/ROOT/img/services-network/dns-cache/env/IP @@ -1 +0,0 @@ -127.0.0.1 diff --git a/examples/ROOT/img/services-network/dns-cache/env/IPSEND b/examples/ROOT/img/services-network/dns-cache/env/IPSEND @@ -1 +0,0 @@ -0.0.0.0 diff --git a/examples/ROOT/img/services-network/dns-cache/env/ROOT b/examples/ROOT/img/services-network/dns-cache/env/ROOT @@ -1 +0,0 @@ -/service/dns-cache/root diff --git a/examples/ROOT/img/services-network/dns-cache/log/README b/examples/ROOT/img/services-network/dns-cache/log/README @@ -1,3 +0,0 @@ -Logger service for the dns-cache service. -djbdns's dnscache produces a lot of output, so -you may want to add log filters. diff --git a/examples/ROOT/img/services-network/dns-cache/log/run b/examples/ROOT/img/services-network/dns-cache/log/run @@ -1,4 +0,0 @@ -#!/command/execlineb -P -s6-setuidgid dnslog -exec -c -s6-log t s1000000 n20 /var/log/dns-cache diff --git a/examples/ROOT/img/services-network/dns-cache/root/ip/127.0.0.1 b/examples/ROOT/img/services-network/dns-cache/root/ip/127.0.0.1 diff --git a/examples/ROOT/img/services-network/dns-cache/root/servers/@ b/examples/ROOT/img/services-network/dns-cache/root/servers/@ @@ -1,13 +0,0 @@ -198.41.0.4 -192.228.79.201 -192.33.4.12 -128.8.10.90 -192.203.230.10 -192.5.5.241 -192.112.36.4 -128.63.2.53 -192.36.148.17 -192.58.128.30 -193.0.14.129 -199.7.83.42 -202.12.27.33 diff --git a/examples/ROOT/img/services-network/dns-cache/run b/examples/ROOT/img/services-network/dns-cache/run @@ -1,12 +0,0 @@ -#!/command/execlineb -P -fdmove -c 2 1 -s6-envuidgid dnscache -s6-envdir env -s6-softlimit -m 2000000 -pipeline -d -{ - redirfd -r 0 /dev/urandom - s6-head -c 128 -} -unexport ! -dnscache diff --git a/examples/ROOT/img/services-network/fifodir-cleanup/README b/examples/ROOT/img/services-network/fifodir-cleanup/README @@ -1,2 +0,0 @@ -This service cleans up the fifodirs for all the services in -/service once a day. diff --git a/examples/ROOT/img/services-network/fifodir-cleanup/run b/examples/ROOT/img/services-network/fifodir-cleanup/run @@ -1,14 +0,0 @@ -#!/command/execlineb -P -fdmove -c 2 1 -if -{ - forbacktickx -p -0 i { s6-ls -0 /service } - import i unexport i - foreground - { - if { s6-test -d /service/${i}/log } - s6-cleanfifodir /service/${i}/log/event - } - s6-cleanfifodir /service/${i}/event -} -s6-sleep 86400 diff --git a/examples/ROOT/img/services-network/ntpclient/README b/examples/ROOT/img/services-network/ntpclient/README @@ -1,9 +0,0 @@ -This service updates the system clock via NTP every 4 hours. -If you're not in France, change 0.fr.pool.ntp.org to a NTP -server pool more fitting your location. -See www.ntp.pool.org for details. - -Do yourself a favor and don't rely on NTP internally. -Just synchronize your main time server via this NTP client -to the outside world, and use a saner and simpler protocol -like TAICLOCK in your internal, fast-speed network. diff --git a/examples/ROOT/img/services-network/ntpclient/log/README b/examples/ROOT/img/services-network/ntpclient/log/README @@ -1,3 +0,0 @@ -Yes, the output of the ntpclient service is logged to -the /var/log/ntpclient logdir. -Make sure it has the correct Unix credentials and permissions! diff --git a/examples/ROOT/img/services-network/ntpclient/log/run b/examples/ROOT/img/services-network/ntpclient/log/run @@ -1,4 +0,0 @@ -#!/command/execlineb -P -s6-setuidgid ntplog -exec -c -s6-log t /var/log/ntpclient diff --git a/examples/ROOT/img/services-network/ntpclient/run b/examples/ROOT/img/services-network/ntpclient/run @@ -1,19 +0,0 @@ -#!/command/execlineb -P - -fdmove -c 2 1 -if -{ - pipeline - { - s6-setuidgid ntp - backtick -n NTPSERVERIP - { - pipeline { s6-dnsip4 -t 16000 0.fr.pool.ntp.org. } - s6-head -n 1 - } - s6-sntpclock -v $NTPSERVERIP - } - s6-clockadd -} -s6-setuidgid nobody -s6-sleep 14400 diff --git a/examples/ROOT/img/services-network/sshd/README b/examples/ROOT/img/services-network/sshd/README @@ -1,5 +0,0 @@ -Service directory for a sshd server over IPv4, -implemented via s6-networking and dropbear. -The rules subdirectory implements access control; in -this example, only 127.0.0.1 is allowed to connect -(which isn't exactly useful for a SSH server). diff --git a/examples/ROOT/img/services-network/sshd/log/README b/examples/ROOT/img/services-network/sshd/log/README @@ -1 +0,0 @@ -Logging service for sshd. diff --git a/examples/ROOT/img/services-network/sshd/log/run b/examples/ROOT/img/services-network/sshd/log/run @@ -1,4 +0,0 @@ -#!/command/execlineb -P -s6-setuidgid log -exec -c -s6-log t s1000000 n20 /var/log/sshd diff --git a/examples/ROOT/img/services-network/sshd/notification-fd b/examples/ROOT/img/services-network/sshd/notification-fd @@ -1 +0,0 @@ -3 diff --git a/examples/ROOT/img/services-network/sshd/rules/ip4/0.0.0.0_0/deny b/examples/ROOT/img/services-network/sshd/rules/ip4/0.0.0.0_0/deny diff --git a/examples/ROOT/img/services-network/sshd/rules/ip4/127.0.0.1_32/allow b/examples/ROOT/img/services-network/sshd/rules/ip4/127.0.0.1_32/allow diff --git a/examples/ROOT/img/services-network/sshd/run b/examples/ROOT/img/services-network/sshd/run @@ -1,6 +0,0 @@ -#!/command/execlineb -P -fdmove -c 2 1 -fdmove 1 3 -s6-tcpserver4 -1 -- 0.0.0.0 22 -s6-tcpserver-access -vvDRl0 -t 5000 -i rules -dropbear -iEg diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/README b/examples/ROOT/img/tmpfs/service/.s6-svscan/README @@ -1,2 +1,9 @@ -This is the image of the control directory of the s6-svscan process. -Notice how the symlinks point to ever-existing scripts. +This is the image of the control directory of the s6-svscan process +running as pid 1. +"crash" is run if s6-svscan fails. +"finish" is run when s6-svscan exits its loop. + + The "SIG*" files are run as children of s6-svscan when it receives +the corresponding signal. SIGINT, SIGUSR1 and SIGUSR2 will all +trigger "s6-rc -da change" (the service manager will shut down all +the services), then s6-svscan will be told to exit its loop. diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/SIGINT b/examples/ROOT/img/tmpfs/service/.s6-svscan/SIGINT @@ -0,0 +1,3 @@ +#!/command/execlineb -P +foreground { s6-rc -da change } +s6-svscanctl -6 . diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/SIGUSR1 b/examples/ROOT/img/tmpfs/service/.s6-svscan/SIGUSR1 @@ -0,0 +1,3 @@ +#!/command/execlineb -P +foreground { s6-rc -da change } +s6-svscanctl -0 . diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/SIGUSR2 b/examples/ROOT/img/tmpfs/service/.s6-svscan/SIGUSR2 @@ -0,0 +1,3 @@ +#!/command/execlineb -P +foreground { s6-rc -da change } +s6-svscanctl -7 . diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/crash b/examples/ROOT/img/tmpfs/service/.s6-svscan/crash @@ -1 +0,0 @@ -/etc/s6-init/crash- \ No newline at end of file diff --git a/examples/ROOT/etc/s6-init/crash b/examples/ROOT/img/tmpfs/service/.s6-svscan/crash diff --git a/examples/ROOT/run b/examples/ROOT/run @@ -0,0 +1 @@ +mnt/tmpfs+ \ No newline at end of file diff --git a/examples/klogd-linux/README b/examples/klogd-linux/README @@ -0,0 +1,5 @@ +This is an example of a service directory for process supervision by s6. + +This klogd emulation is only valid under Linux. +The service only processes logs from /proc/kmsg and +sends them to stdout, i.e. its own logger. diff --git a/examples/ROOT/img/services-local/klogd-linux/log/README b/examples/klogd-linux/log/README diff --git a/examples/ROOT/img/services-local/klogd-linux/log/run b/examples/klogd-linux/log/run diff --git a/examples/ROOT/img/services-local/klogd-linux/run b/examples/klogd-linux/run diff --git a/examples/syslogd-linux/README b/examples/syslogd-linux/README @@ -0,0 +1,9 @@ +This is an example of a service directory for process supervision by s6. + +This syslogd emulation works on any Unix where syslog() is +implemented via a connection on the /dev/log Unix-domain socket. +It needs a Unix superserver (see s6-networking, ucspi-unix or +ucspi-ipc) and ucspilogd. +A ucspilogd process is spawned for every syslog() client. It +processes logs and sends them to stderr, i.e. the service's +logger. diff --git a/examples/ROOT/img/services-local/syslogd-linux/log/README b/examples/syslogd-linux/log/README diff --git a/examples/ROOT/img/services-local/syslogd-linux/log/env/LOGSCRIPT b/examples/syslogd-linux/log/env/LOGSCRIPT diff --git a/examples/ROOT/img/services-local/syslogd-linux/log/run b/examples/syslogd-linux/log/run diff --git a/examples/ROOT/img/services-local/syslogd-linux/notification-fd b/examples/syslogd-linux/notification-fd diff --git a/examples/ROOT/img/services-local/syslogd-linux/run b/examples/syslogd-linux/run diff --git a/package/info b/package/info @@ -1,4 +1,4 @@ package=s6 -version=2.2.1.1 +version=2.2.2.0 category=admin package_macro_name=S6 diff --git a/src/supervision/s6-svscan.c b/src/supervision/s6-svscan.c @@ -21,11 +21,12 @@ #include <s6/config.h> #include <s6/s6-supervise.h> -#define USAGE "s6-svscan [ -c maxservices ] [ -t timeout ] [ dir ]" +#define USAGE "s6-svscan [ -S | -s ] [ -c maxservices ] [ -t timeout ] [ dir ]" -#define SHUTDOWN_PROG S6_SVSCAN_CTLDIR "/shutdown" #define FINISH_PROG S6_SVSCAN_CTLDIR "/finish" #define CRASH_PROG S6_SVSCAN_CTLDIR "/crash" +#define SIGNAL_PROG S6_SVSCAN_CTLDIR "/SIG" +#define SIGNAL_PROG_LEN (sizeof(SIGNAL_PROG) - 1) #define DIR_RETRY_TIMEOUT 3 #define CHECK_RETRY_TIMEOUT 4 @@ -126,12 +127,38 @@ static void handle_signals (void) case 0 : return ; case SIGCHLD : wantreap = 1 ; break ; case SIGALRM : wantscan = 1 ; break ; + case SIGABRT : cont = 0 ; break ; case SIGTERM : term() ; break ; case SIGHUP : hup() ; break ; case SIGQUIT : quit() ; break ; - case SIGABRT : cont = 0 ; break ; case SIGINT : intr() ; break ; - case SIGUSR1 : usr1() ; break ; + } + } +} + +static void handle_diverted_signals (void) +{ + for (;;) + { + register int sig = selfpipe_read() ; + switch (sig) + { + case -1 : panic("selfpipe_read") ; + case 0 : return ; + case SIGCHLD : wantreap = 1 ; break ; + case SIGALRM : wantscan = 1 ; break ; + case SIGABRT : cont = 0 ; break ; + default : + { + char const *name = sig_name(sig) ; + unsigned int len = str_len(name) ; + char fn[SIGNAL_PROG_LEN + len + 1] ; + char const *const newargv[2] = { fn, 0 } ; + byte_copy(fn, SIGNAL_PROG_LEN, SIGNAL_PROG) ; + byte_copy(fn + SIGNAL_PROG_LEN, len + 1, name) ; + if (!child_spawn0(newargv[0], newargv, (char const **)environ)) + strerr_warnwu2sys("spawn ", newargv[0]) ; + } } } } @@ -422,16 +449,19 @@ static void scan (void) int main (int argc, char const *const *argv) { iopause_fd x[2] = { { -1, IOPAUSE_READ, 0 }, { -1, IOPAUSE_READ, 0 } } ; + int divertsignals = 0 ; PROG = "s6-svscan" ; { subgetopt_t l = SUBGETOPT_ZERO ; unsigned int t = 5000 ; for (;;) { - register int opt = subgetopt_r(argc, argv, "t:c:", &l) ; + register int opt = subgetopt_r(argc, argv, "Sst:c:", &l) ; if (opt == -1) break ; switch (opt) { + case 'S' : divertsignals = 0 ; break ; + case 's' : divertsignals = 1 ; break ; case 't' : if (uint0_scan(l.arg, &t)) break ; case 'c' : if (uint0_scan(l.arg, &max)) break ; default : strerr_dieusage(100, USAGE) ; @@ -465,7 +495,11 @@ int main (int argc, char const *const *argv) sigaddset(&set, SIGQUIT) ; sigaddset(&set, SIGABRT) ; sigaddset(&set, SIGINT) ; - sigaddset(&set, SIGUSR1) ; + if (divertsignals) + { + sigaddset(&set, SIGUSR1) ; + sigaddset(&set, SIGUSR2) ; + } if (selfpipe_trapset(&set) < 0) strerr_diefu1sys(111, "trap signals") ; } @@ -497,7 +531,8 @@ int main (int argc, char const *const *argv) errno = EIO ; panic("check internal pipes") ; } - if (x[0].revents & IOPAUSE_READ) handle_signals() ; + if (x[0].revents & IOPAUSE_READ) + divertsignals ? handle_diverted_signals() : handle_signals() ; if (x[1].revents & IOPAUSE_READ) handle_control(x[1].fd) ; } }