1/* See LICENSE file for copyright and license details. */
2
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 <poll.h>
11#include <signal.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15
16#include "util.h"
17#include "wexec.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 {
51 // ?man -d:num: specify directory
52 case 'd':
53 delay = estrtol(EARGF(usage()), 0);
54 break;
55 // ?man -l:str: list in long format
56 case 'l':
57 fifo = EARGF(usage());
58 break;
59 default:
60 usage();
61 }
62 ARGEND;
63
64 if (argc < 1)
65 usage();
66
67 if (fifo && delay > 0)
68 usage();
69
70 setsid();
71
72 signal(SIGTERM, sigterm);
73
74 if (fifo) {
75 pollset->fd = open(fifo, O_RDONLY | O_NONBLOCK);
76 if (pollset->fd < 0)
77 eprintf("open %s:", fifo);
78 pollset->events = POLLIN;
79 }
80
81 while (1) {
82 if (fifo) {
83 pollset->revents = 0;
84 polln = poll(pollset, 1, -1);
85 if (polln <= 0) {
86 if (polln == 0 || errno == EAGAIN)
87 continue;
88 eprintf("poll:");
89 }
90 while ((n = read(pollset->fd, buf, sizeof(buf))) > 0)
91 ;
92 if (n < 0)
93 if (errno != EAGAIN)
94 eprintf("read %s:", fifo);
95 if (n == 0) {
96 close(pollset->fd);
97 pollset->fd = open(fifo, O_RDONLY | O_NONBLOCK);
98 if (pollset->fd < 0)
99 eprintf("open %s:", fifo);
100 pollset->events = POLLIN;
101 }
102 }
103 pid = fork();
104 if (pid < 0)
105 eprintf("fork:");
106 switch (pid) {
107 case 0:
108 wexecvp_self(argv[0], argv);
109 savederrno = errno;
110 weprintf("wexecvp %s:", argv[0]);
111 _exit(savederrno == ENOENT ? 127 : 126);
112 break;
113 default:
114 waitpid(pid, NULL, 0);
115 break;
116 }
117 if (!fifo)
118 sleep(delay);
119 }
120 /* not reachable */
121 return 0;
122}