ubase

suckless linux base utils
git clone git://git.2f30.org/ubase
Log | Files | Refs | README | LICENSE

commit 0e6d7ca2864634a9aecf7c03e40e1fcd046f826b
parent 053e63968df9add6f632da58be1d10084c6798af
Author: sin <sin@2f30.org>
Date:   Mon, 21 Apr 2014 11:48:09 +0100

Implement fifo listener mode for respawn

Diffstat:
Mrespawn.1 | 8+++++++-
Mrespawn.c | 43++++++++++++++++++++++++++++++++++++++++---
2 files changed, 47 insertions(+), 4 deletions(-)

diff --git 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 @@ -1,6 +1,11 @@ /* See LICENSE file for copyright and license details. */ +#include <fcntl.h> #include <errno.h> +#include <stdio.h> #include <stdlib.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> @@ -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[]) { + char *fifo = NULL; + unsigned int delay = 0; pid_t pid; + char buf[BUFSIZ]; int savederrno; - unsigned int delay = 0; + 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;