respawn.c - ubase - suckless linux base utils
HTML git clone git://git.suckless.org/ubase
DIR Log
DIR Files
DIR Refs
DIR README
DIR 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 }