ubase

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

respawn.c (1914B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <sys/stat.h>
      3 #include <sys/time.h>
      4 #include <sys/types.h>
      5 #include <sys/wait.h>
      6 
      7 #include <errno.h>
      8 #include <fcntl.h>
      9 #include <poll.h>
     10 #include <signal.h>
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #include <unistd.h>
     14 
     15 #include "util.h"
     16 
     17 static void
     18 sigterm(int sig)
     19 {
     20 	if (sig == SIGTERM) {
     21 		kill(0, SIGTERM);
     22 		_exit(0);
     23 	}
     24 }
     25 
     26 static void
     27 usage(void)
     28 {
     29 	eprintf("usage: %s [-l fifo] [-d N] cmd [args...]\n", argv0);
     30 }
     31 
     32 int
     33 main(int argc, char *argv[])
     34 {
     35 	char *fifo = NULL;
     36 	unsigned int delay = 0;
     37 	pid_t pid;
     38 	char buf[BUFSIZ];
     39 	int savederrno;
     40 	ssize_t n;
     41 	struct pollfd pollset[1];
     42 	int polln;
     43 
     44 	ARGBEGIN {
     45 	case 'd':
     46 		delay = estrtol(EARGF(usage()), 0);
     47 		break;
     48 	case 'l':
     49 		fifo = EARGF(usage());
     50 		break;
     51 	default:
     52 		usage();
     53 	} ARGEND;
     54 
     55 	if (argc < 1)
     56 		usage();
     57 
     58 	if (fifo && delay > 0)
     59 		usage();
     60 
     61 	setsid();
     62 
     63 	signal(SIGTERM, sigterm);
     64 
     65 	if (fifo) {
     66 		pollset->fd = open(fifo, O_RDONLY | O_NONBLOCK);
     67 		if (pollset->fd < 0)
     68 			eprintf("open %s:", fifo);
     69 		pollset->events = POLLIN;
     70 	}
     71 
     72 	while (1) {
     73 		if (fifo) {
     74 			pollset->revents = 0;
     75 			polln = poll(pollset, 1, -1);
     76 			if (polln <= 0) {
     77 				if (polln == 0 || errno == EAGAIN)
     78 					continue;
     79 				eprintf("poll:");
     80 			}
     81 			while ((n = read(pollset->fd, buf, sizeof(buf))) > 0)
     82 				;
     83 			if (n < 0)
     84 				if (errno != EAGAIN)
     85 					eprintf("read %s:", fifo);
     86 			if (n == 0) {
     87 				close(pollset->fd);
     88 				pollset->fd = open(fifo, O_RDONLY | O_NONBLOCK);
     89 				if (pollset->fd < 0)
     90 					eprintf("open %s:", fifo);
     91 				pollset->events = POLLIN;
     92 			}
     93 		}
     94 		pid = fork();
     95 		if (pid < 0)
     96 			eprintf("fork:");
     97 		switch (pid) {
     98 		case 0:
     99 			execvp(argv[0], argv);
    100 			savederrno = errno;
    101 			weprintf("execvp %s:", argv[0]);
    102 			_exit(savederrno == ENOENT ? 127 : 126);
    103 			break;
    104 		default:
    105 			waitpid(pid, NULL, 0);
    106 			break;
    107 		}
    108 		if (!fifo)
    109 			sleep(delay);
    110 	}
    111 	/* not reachable */
    112 	return 0;
    113 }