1/* See LICENSE file for copyright and license details. */
2
3
4#include <sys/stat.h>
5#include <sys/time.h>
6#include <sys/types.h>
7#include <sys/wait.h>
8
9#include <errno.h>
10#include <fcntl.h>
11#include <poll.h>
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16
17#include "util.h"
18
19static void
20sigterm(int sig)
21{
22 if (sig == SIGTERM) {
23 kill(0, SIGTERM);
24 _exit(0);
25 }
26}
27
28static void
29usage(void)
30{
31 eprintf("usage: %s [-l fifo] [-d N] cmd [args...]\n", argv0);
32}
33
34// ?man respawn: restart command on exit
35// ?man arguments: cmd [args...
36// ?man run a command and restart it automatically when it exits
37int
38main(int argc, char *argv[])
39{
40 char *fifo = NULL;
41 unsigned int delay = 0;
42 pid_t pid;
43 char buf[BUFSIZ];
44 int savederrno;
45 ssize_t n;
46 struct pollfd pollset[1];
47 int polln;
48
49 ARGBEGIN {
50 // ?man -d:num: specify directory
51 case 'd':
52 delay = estrtol(EARGF(usage()), 0);
53 break;
54 // ?man -l:str: list in long format
55 case 'l':
56 fifo = EARGF(usage());
57 break;
58 default:
59 usage();
60 } ARGEND;
61
62 if (argc < 1)
63 usage();
64
65 if (fifo && delay > 0)
66 usage();
67
68 setsid();
69
70 signal(SIGTERM, sigterm);
71
72 if (fifo) {
73 pollset->fd = open(fifo, O_RDONLY | O_NONBLOCK);
74 if (pollset->fd < 0)
75 eprintf("open %s:", fifo);
76 pollset->events = POLLIN;
77 }
78
79 while (1) {
80 if (fifo) {
81 pollset->revents = 0;
82 polln = poll(pollset, 1, -1);
83 if (polln <= 0) {
84 if (polln == 0 || errno == EAGAIN)
85 continue;
86 eprintf("poll:");
87 }
88 while ((n = read(pollset->fd, buf, sizeof(buf))) > 0)
89 ;
90 if (n < 0)
91 if (errno != EAGAIN)
92 eprintf("read %s:", fifo);
93 if (n == 0) {
94 close(pollset->fd);
95 pollset->fd = open(fifo, O_RDONLY | O_NONBLOCK);
96 if (pollset->fd < 0)
97 eprintf("open %s:", fifo);
98 pollset->events = POLLIN;
99 }
100 }
101 pid = fork();
102 if (pid < 0)
103 eprintf("fork:");
104 switch (pid) {
105 case 0:
106 execvp(argv[0], argv);
107 savederrno = errno;
108 weprintf("execvp %s:", argv[0]);
109 _exit(savederrno == ENOENT ? 127 : 126);
110 break;
111 default:
112 waitpid(pid, NULL, 0);
113 break;
114 }
115 if (!fifo)
116 sleep(delay);
117 }
118 /* not reachable */
119 return 0;
120}