runit

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 32705d016c867bedd5604e9acbed060b022ddf0d
parent 13805d8b0cda80e4b33faa4a90b0f89194789e97
Author: Gerrit Pape <pape@smarden.org>
Date:   Sun, 12 Dec 2004 18:17:14 +0000

  * doc/upgrade.html: typo.
  * runsv.c: support custom control commands through control/ directory,
    optionally switch off sending signal.
  * man/runsv.8: document custom control commands.

Diffstat:
Mdoc/upgrade.html | 9++++++++-
Mman/runsv.8 | 24++++++++++++++++++++++++
Mpackage/CHANGES | 7+++++++
Msrc/runsv.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++----------------
4 files changed, 90 insertions(+), 17 deletions(-)

diff --git a/doc/upgrade.html b/doc/upgrade.html @@ -9,6 +9,13 @@ <hr> <h1>runit - upgrading from previous versions</h1> <hr> +<h3>1.1.0 to 1.2.0</h3> +With this version the <a href="runsv.8.html">runsv</a> program makes +controlling the service through commands normally sent by +<a href="runsvctrl.8.html">runsvctrl</a> configurable; +arbitrary actions through external programs can optionally be specified, and +signalling of the service disabled if desired. +See the <a href="runsv.8.html">man page</a> for details. <h3>1.0.x to 1.1.0</h3> The <a href="svlogd.8.html">svlogd</a> program now interprets the ``e'' and ``E'' configuration options so that they can be combined to select or @@ -19,7 +26,7 @@ It also provides the new ``t'' and ``N'' configuration options, see the The <a href="chpst.8.html">chpst</a> program supports adjusting the nice level through the new -n command line option. <p> -Staring with this version, <tt>/etc/runit/2</tt> by default runs the +Starting with this version, <tt>/etc/runit/2</tt> by default runs the <a href="runsvdir.8.html">runsvdir</a> program with the -P option. To adapt edit <tt>/etc/runit/2</tt> and change the invocation of <a href="runsvdir.8.html">runsvdir</a> accordingly, see diff --git a/man/runsv.8 b/man/runsv.8 @@ -157,6 +157,30 @@ ignores unknown characters written to the control pipe. usually blocks if no .B runsv process is running in the service directory. +.SH CUSTOMIZE CONTROL +For each control character +.I c +sent to the control pipe, +.B runsv +first checks if +.I service\fR/control/\fIc +exists and is executable. +If so, it starts +.I service\fR/control/\fIc +and waits for it to terminate, before interpreting the command. +If the program exits with return code 0, +.B runsv +refrains from sending the service the corresponding signal. +The command +.I o +is always considered as command +.IR u . +The +.IR u , +.IR e , +and +.I x +commands of an optional log service cannot be customized. .SH SIGNALS If .B runsv diff --git a/package/CHANGES b/package/CHANGES @@ -1,3 +1,10 @@ +runit 1.2.0 + + * doc/upgrade.html: typo. + * runsv.c: support custom control commands through control/ directory, + optionally switch off sending signal. + * man/runsv.8: document custom control commands. + runit 1.1.0 Sat, 06 Nov 2004 17:21:11 +0000 * svlogd.c: new config option t timeout (thx Enrico Scholz); config diff --git a/src/runsv.c b/src/runsv.c @@ -18,6 +18,7 @@ #include "fd.h" #include "buffer.h" #include "fmt.h" +#include "byte.h" #define USAGE " dir" @@ -200,7 +201,39 @@ void update_status(struct svdir *s) { warn("unable to rename supervise/status.new to supervise/status"); } } +unsigned int custom(char c) { + int pid; + int w; + char a[7]; + struct stat st; + char *prog[2]; + byte_copy(a, 7, "ctrl/?"); + a[5] =c; + if (stat(a, &st) == 0) { + if (st.st_mode & S_IXUSR) { + if ((pid =fork()) == -1) { + warn("unable to fork for ctrl/?"); + return(0); + } + if (! pid) { + if (haslog && fd_copy(1, logpipe[1]) == -1) + warn("unable to setup stdout for ctrl/?"); + prog[0] =a; + prog[1] =0; + execve(a, prog, environ); + } + if (wait_pid(&w, pid) == -1) { + warn("unable to wait for child ctrl/?"); + return(0); + } + return(! wait_exitcode(w)); + } + } + else + if (errno != error_noent) warn("unable to stat ctrl/?"); + return(0); +} void stopservice(struct svdir *s) { if (s->pid) kill(s->pid, SIGTERM); s->ctrl |=C_TERM; @@ -214,8 +247,10 @@ void startservice(struct svdir *s) { if (s->state == S_FINISH) run[0] ="./finish"; - else + else { run[0] ="./run"; + if (! s->islog) custom('u'); + } run[1] =0; if (s->pid != 0) stopservice(s); /* should never happen */ @@ -259,64 +294,64 @@ void startservice(struct svdir *s) { update_status(s); sleep(1); } - int ctrl(struct svdir *s, char c) { switch(c) { case 'd': /* down */ s->want =W_DOWN; - if (s->pid && s->state != S_FINISH) stopservice(s); - else update_status(s); + update_status(s); + if (s->pid && s->state != S_FINISH && ! custom(c)) stopservice(s); break; case 'u': /* up */ s->want =W_UP; + update_status(s); if (s->pid == 0) startservice(s); - else update_status(s); break; case 'e': case 'x': /* exit */ if (s->islog) break; s->want =W_EXIT; - if (s->pid && s->state != S_FINISH) stopservice(s); + update_status(s); + if (s->pid && s->state != S_FINISH && ! custom(c)) stopservice(s); break; case 't': /* sig term */ - if (s->pid && s->state != S_FINISH) stopservice(s); + if (s->pid && s->state != S_FINISH && ! custom(c)) stopservice(s); break; case 'k': /* sig kill */ if (s->pid) kill(s->pid, SIGKILL); s->state =S_DOWN; break; case 'p': /* sig pause */ - kill(s->pid, SIGSTOP); + if (s->pid && ! custom(c)) kill(s->pid, SIGSTOP); s->ctrl |=C_PAUSE; update_status(s); break; case 'c': /* sig cont */ - kill(s->pid, SIGCONT); + if (s->pid && ! custom(c)) kill(s->pid, SIGCONT); if (s->ctrl & C_PAUSE) s->ctrl &=~C_PAUSE; update_status(s); break; case 'o': /* once */ s->want =W_DOWN; + update_status(s); if (! s->pid) startservice(s); - else update_status(s); break; case 'a': /* sig alarm */ - if (s->pid) kill(s->pid, SIGALRM); + if (s->pid && ! custom(c)) kill(s->pid, SIGALRM); break; case 'h': /* sig hup */ - if (s->pid) kill(s->pid, SIGHUP); + if (s->pid && ! custom(c)) kill(s->pid, SIGHUP); break; case 'i': /* sig int */ - if (s->pid) kill(s->pid, SIGINT); + if (s->pid && ! custom(c)) kill(s->pid, SIGINT); break; case 'q': /* sig quit */ - if (s->pid) kill(s->pid, SIGQUIT); + if (s->pid && ! custom(c)) kill(s->pid, SIGQUIT); break; case '1': /* sig usr1 */ - if (s->pid) kill(s->pid, SIGUSR1); + if (s->pid && ! custom(c)) kill(s->pid, SIGUSR1); break; case '2': /* sig usr2 */ - if (s->pid) kill(s->pid, SIGUSR2); + if (s->pid && ! custom(c)) kill(s->pid, SIGUSR2); break; } return(1);