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:
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);