morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

respawn.c (1746B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <sys/select.h>
      3 #include <sys/stat.h>
      4 #include <sys/time.h>
      5 #include <sys/types.h>
      6 #include <sys/wait.h>
      7 
      8 #include <errno.h>
      9 #include <fcntl.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: respawn [-l fifo] [-d N] cmd [args...]\n");
     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 	int fd;
     41 	ssize_t n;
     42 	fd_set rdfd;
     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 		/* TODO: we should use O_RDONLY and re-open the fd on EOF */
     67 		fd = open(fifo, O_RDWR | O_NONBLOCK);
     68 		if (fd < 0)
     69 			eprintf("open %s:", fifo);
     70 	}
     71 
     72 	while (1) {
     73 		if (fifo) {
     74 			FD_ZERO(&rdfd);
     75 			FD_SET(fd, &rdfd);
     76 			n = select(fd + 1, &rdfd, NULL, NULL, NULL);
     77 			if (n < 0)
     78 				eprintf("select:");
     79 			if (n == 0 || FD_ISSET(fd, &rdfd) == 0)
     80 				continue;
     81 			while ((n = read(fd, buf, sizeof(buf))) > 0)
     82 				;
     83 			if (n < 0)
     84 				if (errno != EAGAIN)
     85 					eprintf("read %s:", fifo);
     86 		}
     87 		pid = fork();
     88 		if (pid < 0)
     89 			eprintf("fork:");
     90 		switch (pid) {
     91 		case 0:
     92 			execvp(argv[0], argv);
     93 			savederrno = errno;
     94 			weprintf("execvp %s:", argv[0]);
     95 			_exit(savederrno == ENOENT ? 127 : 126);
     96 			break;
     97 		default:
     98 			waitpid(pid, NULL, 0);
     99 			break;
    100 		}
    101 		if (!fifo)
    102 			sleep(delay);
    103 	}
    104 	/* not reachable */
    105 	return 0;
    106 }