respawn.c - 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)))… | |
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_NO… | |
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 } |