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 }