1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#define FOR_timeout
30#include "toys.h"
31
32GLOBALS(
33 char *s, *k;
34
35 struct pollfd pfd;
36 sigjmp_buf sj;
37)
38
39static void handler(int sig)
40{
41 siglongjmp(TT.sj, 1);
42}
43
44static long nantomil(struct timespec *ts)
45{
46 return ts->tv_sec*1000+ts->tv_nsec/1000000;
47}
48
49void timeout_main(void)
50{
51 int fds[] = {0, -1}, ii, ms, nextsig, pid;
52 struct timespec tts, kts;
53
54
55 toys.exitval = 125;
56 xparsetimespec(*toys.optargs, &tts);
57 if (TT.k) xparsetimespec(TT.k, &kts);
58
59 nextsig = SIGTERM;
60 if (TT.s && -1 == (nextsig = sig_to_num(TT.s)))
61 error_exit("bad -s: '%s'", TT.s);
62
63 if (!FLAG(foreground)) setpgid(0, 0);
64
65 toys.exitval = 0;
66 TT.pfd.events = POLLIN;
67 if (sigsetjmp(TT.sj, 1)) goto done;
68 xsignal_flags(SIGCHLD, handler, SA_NOCLDSTOP);
69 pid = xpopen_both(toys.optargs+1, FLAG(i) ? fds : 0);
70 if (!FLAG(i)) xpipe(fds);
71 TT.pfd.fd = fds[1];
72 ms = nantomil(&tts);
73 for (;;) {
74 if (1 != xpoll(&TT.pfd, 1, ms)) {
75 if (FLAG(v))
76 perror_msg("sending signal %s to command %s", num_to_sig(nextsig),
77 toys.optargs[1]);
78 toys.exitval = (nextsig==9) ? 137 : 124;
79 kill(pid, nextsig);
80 if (!TT.k || nextsig==SIGKILL) break;
81 nextsig = SIGKILL;
82 ms = nantomil(&kts);
83
84 continue;
85 }
86 if (TT.pfd.revents&POLLIN) {
87 errno = 0;
88 if (1>(ii = read(fds[1], toybuf, sizeof(toybuf)))) {
89 if (errno==EINTR) continue;
90 break;
91 }
92 writeall(1, toybuf, ii);
93 }
94 if (TT.pfd.revents&POLLHUP) break;
95 }
96done:
97 xsignal(SIGCHLD, SIG_DFL);
98 ii = xpclose_both(pid, fds);
99
100 if (FLAG(preserve_status) || !toys.exitval) toys.exitval = ii;
101}
102