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#define FOR_watch
27#include "toys.h"
28
29GLOBALS(
30 int n;
31
32 pid_t pid, oldpid;
33)
34
35
36static void watch_child(int sig)
37{
38 int status;
39 pid_t pid = wait(&status);
40
41 status = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127;
42 if (status) {
43
44 if (FLAG(b)) putchar('\b');
45 if (FLAG(e)) {
46 printf("Exit status %d\r\n", status);
47 tty_reset();
48 _exit(status);
49 }
50 }
51
52 if (pid == TT.oldpid) TT.oldpid = 0;
53 else if (pid == TT.pid) TT.pid = 0;
54}
55
56
57
58static int watch_escape(FILE *out, int cols, int wc)
59{
60 if (wc==27 || (wc>=7 && wc<=13)) return -1;
61 if (wc < 32) return 0;
62
63 return crunch_escape(out, cols, wc);
64}
65
66void watch_main(void)
67{
68 char *cmdv[] = {"/bin/sh", "-c", 0, 0}, *cmd, *ss;
69 long long now, then = millitime();
70 unsigned width, height, i, cmdlen, len, xx QUIET, yy QUIET, active QUIET;
71 struct pollfd pfd[2];
72 pid_t pid = 0;
73 int fds[2], cc;
74
75
76 for (i = TT.n%1000, len = i ? 3 : 1; i && !(i%10); i /= 10) len--;
77 len = sprintf(toybuf, "Every %u.%0*us:", TT.n/1000, len, i)+1;
78 cmdlen = len;
79 for (i = 0; toys.optargs[i]; i++) len += strlen(toys.optargs[i])+1;
80 ss = stpcpy(cmd = xmalloc(len), toybuf);
81 cmdv[2] = cmd+cmdlen;
82 for (i = 0; toys.optargs[i]; i++) ss += sprintf(ss, " %s",toys.optargs[i]);
83 cmdlen = ss-cmd;
84
85
86 memset(pfd, 0, sizeof(pfd));
87 pfd[0].events = pfd[1].events = POLLIN;
88
89 xsignal_flags(SIGCHLD, watch_child, SA_RESTART|SA_NOCLDSTOP);
90
91 for (;;) {
92
93
94 if ((now = millitime())>=then) {
95
96
97
98 while ((then += TT.n)<=now);
99 start_redraw(&width, &height);
100
101
102 if (!FLAG(t)) {
103 time_t t = time(0);
104 int pad, ctimelen;
105
106
107 ctimelen = strlen(ss = ctime(&t));
108 if (ss[ctimelen-1]=='\n') ss[--ctimelen] = 0;
109
110
111 pad = width-++ctimelen;
112 if (pad>0) draw_trim(cmd, -pad, pad);
113 printf("%c", pad<cmdlen ? '*' : ' ');
114 if (width) xputs(ss+(width>ctimelen ? 0 : width-1));
115 if (yy>=3) xprintf("\r\n");
116 xx = 0;
117 yy = 2;
118 }
119
120
121 if (TT.oldpid>0) kill(TT.oldpid, SIGKILL);
122 if (TT.pid>0) kill(TT.pid, SIGTERM);
123 TT.oldpid = pid;
124 if (fds[0]>0) close(fds[0]);
125 if (fds[1]>0) close(fds[1]);
126
127
128 fds[0] = fds[1] = -1;
129 TT.pid = xpopen_both(FLAG(x) ? toys.optargs : cmdv, fds);
130 pfd[1].fd = fds[1];
131 active = 1;
132 }
133
134
135 len = 0;
136 xpoll(pfd, 1+(active && yy<height), then-now);
137 if (pfd[0].revents&POLLIN) {
138 memset(toybuf, 0, 16);
139 cc = scan_key_getsize(toybuf, 0, &width, &height);
140
141
142 if (cc == 3 || tolower(cc) == 'q') xexit();
143 }
144 if (pfd[0].revents&POLLHUP) xexit();
145 if (active) {
146 if (pfd[1].revents&POLLIN) len = read(fds[1], toybuf, sizeof(toybuf)-1);
147 if (pfd[1].revents&POLLHUP) active = 0;
148 }
149
150
151
152 if (len<1) continue;
153 ss = toybuf;
154 toybuf[len] = 0;
155 while (yy<height) {
156 if (xx==width) {
157 xx = 0;
158 if (++yy>=height) break;
159 }
160 xx += crunch_str(&ss, width-xx, stdout, 0, watch_escape);
161 if (xx==width) {
162 xx = 0;
163 if (++yy>=height) break;
164 continue;
165 }
166
167 if (ss-toybuf==len || *ss>27) break;
168 cc = *ss++;
169 if (cc==27) continue;
170
171
172 if (cc>=10 && cc<=12) {
173 if (++yy>=height) break;
174 if (cc=='\n') putchar('\r'), xx = 0;
175 }
176 putchar(cc);
177 if (cc=='\b' && xx) xx--;
178 else if (cc=='\t') {
179 xx = (xx|7)+1;
180 if (xx>width-1) xx = width-1;
181 }
182 }
183 }
184
185 if (CFG_TOYBOX_FREE) free(cmd);
186}
187