1 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
2 /* TODO: depends on runit_lib.c - review and reduce/eliminate */
9 #define MAXSERVICES 1000
12 static unsigned long dev;
13 static unsigned long ino;
14 static struct service {
24 static int logpipe[2];
25 static iopause_fd io[1];
26 static struct taia stamplog;
30 #define usage() bb_show_usage()
31 static void fatal2_cannot(char *m1, char *m2)
33 bb_perror_msg_and_die("%s: fatal: cannot %s%s", svdir, m1, m2);
36 static void warn3x(char *m1, char *m2, char *m3)
38 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
40 static void warn2_cannot(char *m1, char *m2)
42 warn3x("cannot ", m1, m2);
44 static void warnx(char *m1)
49 static void s_term(int sig_no)
53 static void s_hangup(int sig_no)
58 static void runsv(int no, char *name)
63 warn2_cannot("fork for ", name);
73 sig_uncatch(sig_hangup);
74 sig_uncatch(sig_term);
76 execvp(prog[0], prog);
77 //pathexec_run(*prog, prog, (char* const*)environ);
78 fatal2_cannot("start runsv ", name);
83 static void runsvdir(void)
92 warn2_cannot("open directory ", svdir);
95 for (i = 0; i < svnum; i++)
98 while ((d = readdir(dir))) {
99 if (d->d_name[0] == '.') continue;
100 if (stat(d->d_name, &s) == -1) {
101 warn2_cannot("stat ", d->d_name);
105 if (!S_ISDIR(s.st_mode)) continue;
106 for (i = 0; i < svnum; i++) {
107 if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) {
116 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
118 warn3x("cannot start runsv ", d->d_name,
119 " too many services");
124 memset(&sv[i], 0, sizeof(sv[i]));
125 sv[i].ino = s.st_ino;
126 sv[i].dev = s.st_dev;
134 warn2_cannot("read directory ", svdir);
141 /* SIGTERM removed runsv's */
142 for (i = 0; i < svnum; i++) {
146 kill(sv[i].pid, SIGTERM);
152 static int setup_log(void)
154 rploglen = strlen(rplog);
156 warnx("log must have at least seven characters");
159 if (pipe(logpipe) == -1) {
160 warnx("cannot create pipe for log");
165 ndelay_on(logpipe[0]);
166 ndelay_on(logpipe[1]);
167 if (fd_copy(2, logpipe[1]) == -1) {
168 warnx("cannot set filedescriptor for log");
171 io[0].fd = logpipe[0];
172 io[0].events = IOPAUSE_READ;
177 int runsvdir_main(int argc, char **argv)
184 struct taia deadline;
186 struct taia stampcheck;
191 if (!argv || !*argv) usage();
193 switch (*(*argv + 1)) {
197 if (!argv || !*argv) usage();
200 sig_catch(sig_term, s_term);
201 sig_catch(sig_hangup, s_hangup);
205 if (setup_log() != 1) {
207 warnx("log service disabled");
210 curdir = open_read(".");
212 fatal2_cannot("open current directory", "");
215 taia_now(&stampcheck);
218 /* collect children */
220 pid = wait_nohang(&wstat);
222 for (i = 0; i < svnum; i++) {
223 if (pid == sv[i].pid) {
233 if (now.sec.x < (stampcheck.sec.x - 3)) {
235 warnx("time warp: resetting time stamp");
236 taia_now(&stampcheck);
238 if (rplog) taia_now(&stamplog);
240 if (taia_less(&now, &stampcheck) == 0) {
241 /* wait at least a second */
242 taia_uint(&deadline, 1);
243 taia_add(&stampcheck, &now, &deadline);
245 if (stat(svdir, &s) != -1) {
246 if (check || s.st_mtime != mtime
247 || s.st_ino != ino || s.st_dev != dev
250 if (chdir(svdir) != -1) {
255 if (now.sec.x <= (4611686018427387914ULL + (uint64_t)mtime))
258 while (fchdir(curdir) == -1) {
259 warn2_cannot("change directory, pausing", "");
263 warn2_cannot("change directory to ", svdir);
266 warn2_cannot("stat ", svdir);
270 if (taia_less(&now, &stamplog) == 0) {
271 write(logpipe[1], ".", 1);
272 taia_uint(&deadline, 900);
273 taia_add(&stamplog, &now, &deadline);
276 taia_uint(&deadline, check ? 1 : 5);
277 taia_add(&deadline, &now, &deadline);
279 sig_block(sig_child);
281 iopause(io, 1, &deadline, &now);
283 iopause(0, 0, &deadline, &now);
284 sig_unblock(sig_child);
286 if (rplog && (io[0].revents | IOPAUSE_READ))
287 while (read(logpipe[0], &ch, 1) > 0)
289 for (i = 6; i < rploglen; i++)
290 rplog[i-1] = rplog[i];
291 rplog[rploglen-1] = ch;
298 for (i = 0; i < svnum; i++)
300 kill(sv[i].pid, SIGTERM);