int setup_log() { if ((rploglen =str_len(rplog)) < 7) { warn3x("log must have at least seven characters.", 0, 0); return(0); } if (pipe(logpipe) == -1) { warn3x("unable to create pipe for log.", 0, 0); return(-1); } coe(logpipe[1]); coe(logpipe[0]); ndelay_on(logpipe[0]); ndelay_on(logpipe[1]); if (fd_copy(2, logpipe[1]) == -1) { warn3x("unable to set filedescriptor for log.", 0, 0); return(-1); } io[0].fd =logpipe[0]; io[0].events =IOPAUSE_READ; taia_now(&stamplog); return(1); }
static void warnx(const char *m1) { warn3x(m1, "", ""); }
static void warn2_cannot(const char *m1, const char *m2) { warn3x("cannot ", m1, m2); }
static void runsvdir(void) { DIR *dir; direntry *d; int i; struct stat s; dir = opendir("."); if (!dir) { warn2_cannot("open directory ", svdir); return; } for (i = 0; i < svnum; i++) sv[i].isgone = 1; errno = 0; while ((d = readdir(dir))) { if (d->d_name[0] == '.') continue; if (stat(d->d_name, &s) == -1) { warn2_cannot("stat ", d->d_name); errno = 0; continue; } if (!S_ISDIR(s.st_mode)) continue; for (i = 0; i < svnum; i++) { if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { sv[i].isgone = 0; if (!sv[i].pid) runsv(i, d->d_name); break; } } if (i == svnum) { /* new service */ struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); if (!svnew) { warn3x("cannot start runsv ", d->d_name, " too many services"); continue; } sv = svnew; svnum++; memset(&sv[i], 0, sizeof(sv[i])); sv[i].ino = s.st_ino; sv[i].dev = s.st_dev; /*sv[i].pid = 0;*/ /*sv[i].isgone = 0;*/ runsv(i, d->d_name); check = 1; } } if (errno) { warn2_cannot("read directory ", svdir); closedir(dir); check = 1; return; } closedir(dir); /* SIGTERM removed runsv's */ for (i = 0; i < svnum; i++) { if (!sv[i].isgone) continue; if (sv[i].pid) kill(sv[i].pid, SIGTERM); sv[i] = sv[--svnum]; check = 1; } }
void runsvdir() { DIR *dir; direntry *d; int i; struct stat s; if (! (dir =opendir("."))) { warn("unable to open directory ", svdir); return; } for (i =0; i < svnum; i++) sv[i].isgone =1; errno =0; while ((d =readdir(dir))) { if (d->d_name[0] == '.') continue; if (stat(d->d_name, &s) == -1) { warn("unable to stat ", d->d_name); errno =0; continue; } if (! S_ISDIR(s.st_mode)) continue; for (i =0; i < svnum; i++) { if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { sv[i].isgone =0; if (! sv[i].pid) runsv(i, d->d_name); break; } } if (i == svnum) { /* new service */ if (svnum >= MAXSERVICES) { warn3x("unable to start runsv ", d->d_name, ": too many services."); continue; } sv[i].ino =s.st_ino; sv[i].dev =s.st_dev; sv[i].pid =0; sv[i].isgone =0; svnum++; runsv(i, d->d_name); check =1; } } if (errno) { warn("unable to read directory ", svdir); closedir(dir); check =1; return; } closedir(dir); /* SIGTERM removed runsv's */ for (i =0; i < svnum; i++) { if (! sv[i].isgone) continue; if (sv[i].pid) kill(sv[i].pid, SIGTERM); sv[i] =sv[--svnum]; check =1; } }
int main(int argc, char **argv) { struct stat s; time_t mtime =0; int wstat; int curdir; int pid; struct taia deadline; struct taia now; struct taia stampcheck; char ch; int i; progname =*argv++; if (! argv || ! *argv) usage(); if (**argv == '-') { switch (*(*argv +1)) { case 'P': pgrp =1; case '-': ++argv; } if (! argv || ! *argv) usage(); } sig_catch(sig_term, s_term); sig_catch(sig_hangup, s_hangup); svdir =*argv++; if (argv && *argv) { rplog =*argv; if (setup_log() != 1) { rplog =0; warn3x("log service disabled.", 0, 0); } } if ((curdir =open_read(".")) == -1) fatal("unable to open current directory", 0); coe(curdir); taia_now(&stampcheck); for (;;) { /* collect children */ for (;;) { if ((pid =wait_nohang(&wstat)) <= 0) break; for (i =0; i < svnum; i++) { if (pid == sv[i].pid) { /* runsv has gone */ sv[i].pid =0; check =1; break; } } } taia_now(&now); if (now.sec.x < (stampcheck.sec.x -3)) { /* time warp */ warn3x("time warp: resetting time stamp.", 0, 0); taia_now(&stampcheck); taia_now(&now); if (rplog) taia_now(&stamplog); } if (taia_less(&now, &stampcheck) == 0) { /* wait at least a second */ taia_uint(&deadline, 1); taia_add(&stampcheck, &now, &deadline); if (stat(svdir, &s) != -1) { if (check || \ s.st_mtime != mtime || s.st_ino != ino || s.st_dev != dev) { /* svdir modified */ if (chdir(svdir) != -1) { mtime =s.st_mtime; dev =s.st_dev; ino =s.st_ino; check =0; if (now.sec.x <= (4611686018427387914ULL +(uint64)mtime)) sleep(1); runsvdir(); while (fchdir(curdir) == -1) { warn("unable to change directory, pausing", 0); sleep(5); } } else warn("unable to change directory to ", svdir); } } else warn("unable to stat ", svdir); } if (rplog) if (taia_less(&now, &stamplog) == 0) { write(logpipe[1], ".", 1); taia_uint(&deadline, 900); taia_add(&stamplog, &now, &deadline); } /* half a second */ deadline.sec.x =0; deadline.nano =500000000UL; deadline.atto =0; taia_add(&deadline, &now, &deadline); sig_block(sig_child); if (rplog) iopause(io, 1, &deadline, &now); else iopause(0, 0, &deadline, &now); sig_unblock(sig_child); if (rplog && (io[0].revents | IOPAUSE_READ)) while (read(logpipe[0], &ch, 1) > 0) if (ch) { for (i =6; i < rploglen; i++) rplog[i -1] =rplog[i]; rplog[rploglen -1] =ch; } switch(exitsoon) { case 1: _exit(0); case 2: for (i =0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); _exit(111); } } /* for (;;) */ /* not reached */ _exit(0); }