ash: some beautification work, no code changes
[oweals/busybox.git] / runit / runsvdir.c
index 94397bc368c444c2a6358941362ac441c0f17ef7..8099ebf5c9090c5492aa287161f4528ca173a2e5 100644 (file)
@@ -25,7 +25,7 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
+/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
 /* TODO: depends on runit_lib.c - review and reduce/eliminate */
 
 #include <sys/poll.h>
@@ -35,24 +35,46 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #define MAXSERVICES 1000
 
+/* Should be not needed - all dirs are on same FS, right? */
+#define CHECK_DEVNO_TOO 0
+
 struct service {
+#if CHECK_DEVNO_TOO
        dev_t dev;
+#endif
        ino_t ino;
        pid_t pid;
        smallint isgone;
 };
 
-struct service *sv;
-static char *svdir;
-static int svnum;
-static char *rplog;
-static int rploglen;
-static int logpipe[2];
-static struct pollfd pfd[1];
-static unsigned stamplog;
-static smallint check = 1;
-static smallint exitsoon;
-static smallint set_pgrp;
+struct globals {
+       struct service *sv;
+       char *svdir;
+       int svnum;
+#if ENABLE_FEATURE_RUNSVDIR_LOG
+       char *rplog;
+       int rploglen;
+       struct fd_pair logpipe;
+       struct pollfd pfd[1];
+       unsigned stamplog;
+#endif
+       smallint need_rescan; /* = 1; */
+       smallint set_pgrp;
+};
+#define G (*(struct globals*)&bb_common_bufsiz1)
+#define sv          (G.sv          )
+#define svdir       (G.svdir       )
+#define svnum       (G.svnum       )
+#define rplog       (G.rplog       )
+#define rploglen    (G.rploglen    )
+#define logpipe     (G.logpipe     )
+#define pfd         (G.pfd         )
+#define stamplog    (G.stamplog    )
+#define need_rescan (G.need_rescan )
+#define set_pgrp    (G.set_pgrp    )
+#define INIT_G() do { \
+       need_rescan = 1; \
+} while (0)
 
 static void fatal2_cannot(const char *m1, const char *m2)
 {
@@ -67,19 +89,12 @@ static void warn2_cannot(const char *m1, const char *m2)
 {
        warn3x("cannot ", m1, m2);
 }
+#if ENABLE_FEATURE_RUNSVDIR_LOG
 static void warnx(const char *m1)
 {
        warn3x(m1, "", "");
 }
-
-static void s_term(int sig_no)
-{
-       exitsoon = 1;
-}
-static void s_hangup(int sig_no)
-{
-       exitsoon = 2;
-}
+#endif
 
 static void runsv(int no, const char *name)
 {
@@ -100,15 +115,17 @@ static void runsv(int no, const char *name)
                /* child */
                if (set_pgrp)
                        setsid();
-               signal(SIGHUP, SIG_DFL);
-               signal(SIGTERM, SIG_DFL);
+               bb_signals(0
+                       + (1 << SIGHUP)
+                       + (1 << SIGTERM)
+                       , SIG_DFL);
                execvp(prog[0], prog);
                fatal2_cannot("start runsv ", name);
        }
        sv[no].pid = pid;
 }
 
-static void runsvdir(void)
+static void do_rescan(void)
 {
        DIR *dir;
        direntry *d;
@@ -122,19 +139,26 @@ static void runsvdir(void)
        }
        for (i = 0; i < svnum; i++)
                sv[i].isgone = 1;
-       errno = 0;
-       while ((d = readdir(dir))) {
+
+       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);
-                       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)) {
+                       if ((sv[i].ino == s.st_ino)
+#if CHECK_DEVNO_TOO
+                        && (sv[i].dev == s.st_dev)
+#endif
+                       ) {
                                sv[i].isgone = 0;
                                if (!sv[i].pid)
                                        runsv(i, d->d_name);
@@ -145,67 +169,45 @@ static void runsvdir(void)
                        /* new service */
                        struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
                        if (!svnew) {
-                               warn3x("cannot start runsv ", d->d_name,
-                                               " too many services");
+                               warn2_cannot("start runsv ", d->d_name);
                                continue;
                        }
                        sv = svnew;
                        svnum++;
                        memset(&sv[i], 0, sizeof(sv[i]));
                        sv[i].ino = s.st_ino;
+#if CHECK_DEVNO_TOO
                        sv[i].dev = s.st_dev;
+#endif
                        /*sv[i].pid = 0;*/
                        /*sv[i].isgone = 0;*/
                        runsv(i, d->d_name);
-                       check = 1;
+                       need_rescan = 1;
                }
        }
-       if (errno) {
+       i = errno;
+       closedir(dir);
+       if (i) {
                warn2_cannot("read directory ", svdir);
-               closedir(dir);
-               check = 1;
+               need_rescan = 1;
                return;
        }
-       closedir(dir);
 
-       /* SIGTERM removed runsv's */
+       /* Send SIGTERM to runsv whose directories were not found (removed) */
        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;
+               svnum--;
+               sv[i] = sv[svnum];
+               i--; /* so that we don't skip new sv[i] (bug was here!) */
+               need_rescan = 1;
        }
 }
 
-static int setup_log(void)
-{
-       rploglen = strlen(rplog);
-       if (rploglen < 7) {
-               warnx("log must have at least seven characters");
-               return 0;
-       }
-       if (pipe(logpipe)) {
-               warnx("cannot create pipe for log");
-               return -1;
-       }
-       coe(logpipe[1]);
-       coe(logpipe[0]);
-       ndelay_on(logpipe[0]);
-       ndelay_on(logpipe[1]);
-       if (dup2(logpipe[1], 2) == -1) {
-               warnx("cannot set filedescriptor for log");
-               return -1;
-       }
-       pfd[0].fd = logpipe[0];
-       pfd[0].events = POLLIN;
-       stamplog = monotonic_sec();
-       return 1;
-}
-
-int runsvdir_main(int argc, char **argv);
-int runsvdir_main(int argc, char **argv)
+int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int runsvdir_main(int argc UNUSED_PARAM, char **argv)
 {
        struct stat s;
        dev_t last_dev = last_dev; /* for gcc */
@@ -217,49 +219,63 @@ int runsvdir_main(int argc, char **argv)
        unsigned deadline;
        unsigned now;
        unsigned stampcheck;
-       char ch;
        int i;
 
-       argv++;
-       if (!*argv)
-               bb_show_usage();
-       if (argv[0][0] == '-') {
-               switch (argv[0][1]) {
-               case 'P': set_pgrp = 1;
-               case '-': ++argv;
-               }
-               if (!*argv)
-                       bb_show_usage();
-       }
+       INIT_G();
 
-       sig_catch(SIGTERM, s_term);
-       sig_catch(SIGHUP, s_hangup);
+       opt_complementary = "-1";
+       set_pgrp = getopt32(argv, "P");
+       argv += optind;
+
+       bb_signals_recursive((1 << SIGTERM) | (1 << SIGHUP), record_signo);
        svdir = *argv++;
-       if (argv && *argv) {
+
+#if ENABLE_FEATURE_RUNSVDIR_LOG
+       /* setup log */
+       if (*argv) {
                rplog = *argv;
-               if (setup_log() != 1) {
-                       rplog = 0;
-                       warnx("log service disabled");
+               rploglen = strlen(rplog);
+               if (rploglen < 7) {
+                       warnx("log must have at least seven characters");
+               } else if (piped_pair(logpipe)) {
+                       warnx("cannot create pipe for log");
+               } else {
+                       close_on_exec_on(logpipe.rd);
+                       close_on_exec_on(logpipe.wr);
+                       ndelay_on(logpipe.rd);
+                       ndelay_on(logpipe.wr);
+                       if (dup2(logpipe.wr, 2) == -1) {
+                               warnx("cannot set filedescriptor for log");
+                       } else {
+                               pfd[0].fd = logpipe.rd;
+                               pfd[0].events = POLLIN;
+                               stamplog = monotonic_sec();
+                               goto run;
+                       }
                }
+               rplog = NULL;
+               warnx("log service disabled");
        }
+run:
+#endif
        curdir = open_read(".");
        if (curdir == -1)
                fatal2_cannot("open current directory", "");
-       coe(curdir);
+       close_on_exec_on(curdir);
 
        stampcheck = monotonic_sec();
 
        for (;;) {
                /* collect children */
                for (;;) {
-                       pid = wait_nohang(&wstat);
+                       pid = wait_any_nohang(&wstat);
                        if (pid <= 0)
                                break;
                        for (i = 0; i < svnum; i++) {
                                if (pid == sv[i].pid) {
                                        /* runsv has gone */
                                        sv[i].pid = 0;
-                                       check = 1;
+                                       need_rescan = 1;
                                        break;
                                }
                        }
@@ -271,7 +287,7 @@ int runsvdir_main(int argc, char **argv)
                        stampcheck = now + 1;
 
                        if (stat(svdir, &s) != -1) {
-                               if (check || s.st_mtime != last_mtime
+                               if (need_rescan || s.st_mtime != last_mtime
                                 || s.st_ino != last_ino || s.st_dev != last_dev
                                ) {
                                        /* svdir modified */
@@ -279,10 +295,10 @@ int runsvdir_main(int argc, char **argv)
                                                last_mtime = s.st_mtime;
                                                last_dev = s.st_dev;
                                                last_ino = s.st_ino;
-                                               check = 0;
+                                               need_rescan = 0;
                                                //if (now <= mtime)
                                                //      sleep(1);
-                                               runsvdir();
+                                               do_rescan();
                                                while (fchdir(curdir) == -1) {
                                                        warn2_cannot("change directory, pausing", "");
                                                        sleep(5);
@@ -294,24 +310,29 @@ int runsvdir_main(int argc, char **argv)
                                warn2_cannot("stat ", svdir);
                }
 
+#if ENABLE_FEATURE_RUNSVDIR_LOG
                if (rplog) {
                        if ((int)(now - stamplog) >= 0) {
-                               write(logpipe[1], ".", 1);
+                               write(logpipe.wr, ".", 1);
                                stamplog = now + 900;
                        }
                }
-
                pfd[0].revents = 0;
+#endif
                sig_block(SIGCHLD);
-               deadline = (check ? 1 : 5);
+               deadline = (need_rescan ? 1 : 5);
+#if ENABLE_FEATURE_RUNSVDIR_LOG
                if (rplog)
                        poll(pfd, 1, deadline*1000);
                else
+#endif
                        sleep(deadline);
                sig_unblock(SIGCHLD);
 
+#if ENABLE_FEATURE_RUNSVDIR_LOG
                if (pfd[0].revents & POLLIN) {
-                       while (read(logpipe[0], &ch, 1) > 0) {
+                       char ch;
+                       while (read(logpipe.rd, &ch, 1) > 0) {
                                if (ch) {
                                        for (i = 6; i < rploglen; i++)
                                                rplog[i-1] = rplog[i];
@@ -319,15 +340,15 @@ int runsvdir_main(int argc, char **argv)
                                }
                        }
                }
-
-               switch (exitsoon) {
-               case 1:
-                       _exit(0);
-               case 2:
+#endif
+               switch (bb_got_signal) {
+               case SIGHUP:
                        for (i = 0; i < svnum; i++)
                                if (sv[i].pid)
                                        kill(sv[i].pid, SIGTERM);
-                       _exit(111);
+                       // N.B. fall through
+               case SIGTERM:
+                       _exit((SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS);
                }
        }
        /* not reached */