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 }