diff --git a/respawn.1 b/respawn.1 index f9d68a1..05ad86b 100644 --- a/respawn.1 +++ b/respawn.1 @@ -2,7 +2,7 @@ .SH NAME \fBrespawn\fR - Spawn the given command repeatedly .SH SYNOPSIS -\fBrespawn\fR [\fB-d\fI N\fR] \fIcmd\fR [\fIargs...\fR] +\fBrespawn\fR [\fB-l\fI fifo\fR] [\fB-d\fI N\fR] \fIcmd\fR [\fIargs...\fR] .SH DESCRIPTION \fBrespawn\fR spawns the given \fIcmd\fR in a new session repeatedly. @@ -10,3 +10,9 @@ repeatedly. .TP \fB-d\fR Set the delay between invocations of \fIcmd\fR. It defaults to 0. +.TP +\fB-l\fR +Listen on the specified \fIfifo\fR for writes. For each write +spawn a new instance of \fIcmd\fR. This can be used in conjunction +with a process supervisor to restart a particular program. The \fB-l\fR +and \fB-d\fR options are incompatible. All writes are discarded. diff --git a/respawn.c b/respawn.c index 453c534..4f65e04 100644 --- a/respawn.c +++ b/respawn.c @@ -1,6 +1,11 @@ /* See LICENSE file for copyright and license details. */ +#include #include +#include #include +#include +#include +#include #include #include #include @@ -9,20 +14,28 @@ static void usage(void) { - eprintf("usage: respawn [-d N] cmd [args...]\n"); + eprintf("usage: respawn [-l fifo] [-d N] cmd [args...]\n"); } int main(int argc, char *argv[]) { - pid_t pid; - int savederrno; + char *fifo = NULL; unsigned int delay = 0; + pid_t pid; + char buf[BUFSIZ]; + int savederrno; + int fd; + ssize_t n; + fd_set rdfd; ARGBEGIN { case 'd': delay = estrtol(EARGF(usage()), 0); break; + case 'l': + fifo = EARGF(usage()); + break; default: usage(); } ARGEND; @@ -30,7 +43,30 @@ main(int argc, char *argv[]) if(argc < 1) usage(); + if (fifo && delay > 0) + usage(); + + if (fifo) { + fd = open(fifo, O_RDWR | O_NONBLOCK); + if (fd < 0) + eprintf("open %s:", fifo); + } + while (1) { + if (fifo) { + FD_ZERO(&rdfd); + FD_SET(fd, &rdfd); + n = select(fd + 1, &rdfd, NULL, NULL, NULL); + if (n < 0) + eprintf("select:"); + if (n == 0 || FD_ISSET(fd, &rdfd) == 0) + continue; + while ((n = read(fd, buf, sizeof(buf))) > 0) + ; + if (n < 0) + if (errno != EAGAIN) + eprintf("read %s:", fifo); + } pid = fork(); if (pid < 0) eprintf("fork:"); @@ -47,7 +83,8 @@ main(int argc, char *argv[]) waitpid(pid, NULL, 0); break; } - sleep(delay); + if (!fifo) + sleep(delay); } /* not reachable */ return EXIT_SUCCESS;