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; } }
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; } }
/* gcc 4.3.0 does better with NOINLINE */ static NOINLINE int do_rescan(void) { DIR *dir; struct dirent *d; int i; struct stat s; int need_rescan = 0; dir = opendir("."); if (!dir) { warn2_cannot("open directory ", svdir); return 1; /* need to rescan again soon */ } for (i = 0; i < svnum; i++) sv[i].isgone = 1; while (1) { errno = 0; d = readdir(dir); if (!d) break; if (d->d_name[0] == '.') continue; if (stat(d->d_name, &s) == -1) { warn2_cannot("stat ", d->d_name); continue; } if (!S_ISDIR(s.st_mode)) continue; /* Do we have this service listed already? */ for (i = 0; i < svnum; i++) { if ((sv[i].ino == s.st_ino) #if CHECK_DEVNO_TOO && (sv[i].dev == s.st_dev) #endif ) { if (sv[i].pid == 0) /* restart if it has died */ goto run_ith_sv; sv[i].isgone = 0; /* "we still see you" */ goto next_dentry; } } { /* Not found, make new service */ struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); if (!svnew) { warn2_cannot("start runsv ", d->d_name); need_rescan = 1; continue; } sv = svnew; svnum++; #if CHECK_DEVNO_TOO sv[i].dev = s.st_dev; #endif sv[i].ino = s.st_ino; run_ith_sv: sv[i].pid = runsv(d->d_name); sv[i].isgone = 0; } next_dentry: ; } i = errno; closedir(dir); if (i) { /* readdir failed */ warn2_cannot("read directory ", svdir); return 1; /* need to rescan again soon */ } /* Send SIGTERM to runsv whose directories * were no longer found (-> must have been removed) */ for (i = 0; i < svnum; i++) { if (!sv[i].isgone) continue; if (sv[i].pid) kill(sv[i].pid, SIGTERM); svnum--; sv[i] = sv[svnum]; i--; /* so that we don't skip new sv[i] (bug was here!) */ } return need_rescan; }