blob: b4c0b2ef00bf712f58d948daae1e6665e70c4604 [file] [log] [blame]
Denis Vlasenko8a164052007-03-12 23:34:52 +00001/*
2Copyright (c) 2001-2006, Gerrit Pape
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
Denis Vlasenkod18f52b2008-03-02 12:53:15 +000028/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
Denis Vlasenko04c63862006-11-17 18:58:49 +000029/* TODO: depends on runit_lib.c - review and reduce/eliminate */
30
Pere Orga5bc8c002011-04-11 03:29:49 +020031//usage:#define runsvdir_trivial_usage
32//usage: "[-P] [-s SCRIPT] DIR"
33//usage:#define runsvdir_full_usage "\n\n"
34//usage: "Start a runsv process for each subdirectory. If it exits, restart it.\n"
35//usage: "\n -P Put each runsv in a new session"
36//usage: "\n -s SCRIPT Run SCRIPT <signo> after signal is processed"
37
Denis Vlasenko04c63862006-11-17 18:58:49 +000038#include <sys/file.h>
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000039#include "libbb.h"
Denis Vlasenko04c63862006-11-17 18:58:49 +000040#include "runit_lib.h"
41
42#define MAXSERVICES 1000
43
Denis Vlasenko923a79a2008-09-22 21:34:24 +000044/* Should be not needed - all dirs are on same FS, right? */
45#define CHECK_DEVNO_TOO 0
46
Denis Vlasenko45946f82007-08-20 17:27:40 +000047struct service {
Denis Vlasenko923a79a2008-09-22 21:34:24 +000048#if CHECK_DEVNO_TOO
Denis Vlasenko45946f82007-08-20 17:27:40 +000049 dev_t dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000050#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +000051 ino_t ino;
52 pid_t pid;
53 smallint isgone;
54};
55
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000056struct globals {
57 struct service *sv;
58 char *svdir;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000059 int svnum;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000060#if ENABLE_FEATURE_RUNSVDIR_LOG
61 char *rplog;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000062 struct fd_pair logpipe;
63 struct pollfd pfd[1];
64 unsigned stamplog;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000065#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +010066} FIX_ALIASING;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000067#define G (*(struct globals*)&bb_common_bufsiz1)
Denis Vlasenko923a79a2008-09-22 21:34:24 +000068#define sv (G.sv )
69#define svdir (G.svdir )
70#define svnum (G.svnum )
71#define rplog (G.rplog )
Denis Vlasenko923a79a2008-09-22 21:34:24 +000072#define logpipe (G.logpipe )
73#define pfd (G.pfd )
74#define stamplog (G.stamplog )
Denys Vlasenko16714242011-09-21 01:59:15 +020075#define INIT_G() do { } while (0)
Denis Vlasenko04c63862006-11-17 18:58:49 +000076
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000077static void fatal2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000078{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010079 bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000080 /* was exiting 100 */
81}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000082static void warn3x(const char *m1, const char *m2, const char *m3)
Denis Vlasenko04c63862006-11-17 18:58:49 +000083{
84 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
Denis Vlasenkof7996f32007-01-11 17:20:00 +000085}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000086static void warn2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000087{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010088 warn3x("can't ", m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000089}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000090#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000091static void warnx(const char *m1)
Denis Vlasenko04c63862006-11-17 18:58:49 +000092{
93 warn3x(m1, "", "");
Denis Vlasenkof7996f32007-01-11 17:20:00 +000094}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000095#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +000096
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +000097/* inlining + vfork -> bigger code */
98static NOINLINE pid_t runsv(const char *name)
Denis Vlasenko04c63862006-11-17 18:58:49 +000099{
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000100 pid_t pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000101
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000102 /* If we got signaled, stop spawning children at once! */
103 if (bb_got_signal)
104 return 0;
105
106 pid = vfork();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000107 if (pid == -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000108 warn2_cannot("vfork", "");
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000109 return 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000110 }
111 if (pid == 0) {
112 /* child */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000113 if (option_mask32 & 1) /* -P option? */
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000114 setsid();
Denis Vlasenko96575962008-10-29 03:42:44 +0000115/* man execv:
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000116 * "Signals set to be caught by the calling process image
117 * shall be set to the default action in the new process image."
Denis Vlasenko96575962008-10-29 03:42:44 +0000118 * Therefore, we do not need this: */
119#if 0
Denis Vlasenko25591c32008-02-16 22:58:56 +0000120 bb_signals(0
Denis Vlasenko96575962008-10-29 03:42:44 +0000121 | (1 << SIGHUP)
122 | (1 << SIGTERM)
Denis Vlasenko25591c32008-02-16 22:58:56 +0000123 , SIG_DFL);
Denis Vlasenko96575962008-10-29 03:42:44 +0000124#endif
Denis Vlasenkof09f4e02009-02-26 12:29:59 +0000125 execlp("runsv", "runsv", name, (char *) NULL);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000126 fatal2_cannot("start runsv ", name);
127 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000128 return pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000129}
130
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000131/* gcc 4.3.0 does better with NOINLINE */
132static NOINLINE int do_rescan(void)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000133{
134 DIR *dir;
Denys Vlasenkoaebb7422009-08-02 00:55:49 +0200135 struct dirent *d;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000136 int i;
137 struct stat s;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000138 int need_rescan = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000139
140 dir = opendir(".");
141 if (!dir) {
142 warn2_cannot("open directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000143 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000144 }
145 for (i = 0; i < svnum; i++)
146 sv[i].isgone = 1;
Denis Vlasenko8f740942008-05-31 07:00:33 +0000147
148 while (1) {
149 errno = 0;
150 d = readdir(dir);
151 if (!d)
152 break;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000153 if (d->d_name[0] == '.')
154 continue;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000155 if (stat(d->d_name, &s) == -1) {
156 warn2_cannot("stat ", d->d_name);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000157 continue;
158 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000159 if (!S_ISDIR(s.st_mode))
160 continue;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000161 /* Do we have this service listed already? */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000162 for (i = 0; i < svnum; i++) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000163 if ((sv[i].ino == s.st_ino)
164#if CHECK_DEVNO_TOO
165 && (sv[i].dev == s.st_dev)
166#endif
167 ) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000168 if (sv[i].pid == 0) /* restart if it has died */
169 goto run_ith_sv;
170 sv[i].isgone = 0; /* "we still see you" */
171 goto next_dentry;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000172 }
173 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000174 { /* Not found, make new service */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000175 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
176 if (!svnew) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000177 warn2_cannot("start runsv ", d->d_name);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000178 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000179 continue;
180 }
181 sv = svnew;
182 svnum++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000183#if CHECK_DEVNO_TOO
Denis Vlasenko04c63862006-11-17 18:58:49 +0000184 sv[i].dev = s.st_dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000185#endif
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000186 sv[i].ino = s.st_ino;
187 run_ith_sv:
188 sv[i].pid = runsv(d->d_name);
189 sv[i].isgone = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000190 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000191 next_dentry: ;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000192 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000193 i = errno;
194 closedir(dir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000195 if (i) { /* readdir failed */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000196 warn2_cannot("read directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000197 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000198 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000199
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000200 /* Send SIGTERM to runsv whose directories
201 * were no longer found (-> must have been removed) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000202 for (i = 0; i < svnum; i++) {
203 if (!sv[i].isgone)
204 continue;
205 if (sv[i].pid)
206 kill(sv[i].pid, SIGTERM);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000207 svnum--;
208 sv[i] = sv[svnum];
209 i--; /* so that we don't skip new sv[i] (bug was here!) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000210 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000211 return need_rescan;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000212}
213
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000214int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000215int runsvdir_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000216{
217 struct stat s;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000218 dev_t last_dev = last_dev; /* for gcc */
219 ino_t last_ino = last_ino; /* for gcc */
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100220 time_t last_mtime;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000221 int curdir;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000222 unsigned stampcheck;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000223 int i;
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100224 int need_rescan;
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100225 bool i_am_init;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000226 char *opt_s_argv[3];
Denis Vlasenko04c63862006-11-17 18:58:49 +0000227
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000228 INIT_G();
229
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000230 opt_complementary = "-1";
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000231 opt_s_argv[0] = NULL;
232 opt_s_argv[2] = NULL;
233 getopt32(argv, "Ps:", &opt_s_argv[0]);
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000234 argv += optind;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000235
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100236 i_am_init = (getpid() == 1);
Denis Vlasenko96575962008-10-29 03:42:44 +0000237 bb_signals(0
238 | (1 << SIGTERM)
239 | (1 << SIGHUP)
240 /* For busybox's init, SIGTERM == reboot,
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100241 * SIGUSR1 == halt,
242 * SIGUSR2 == poweroff,
243 * Ctlr-ALt-Del sends SIGINT to init,
244 * so we need to intercept SIGUSRn and SIGINT too.
Denis Vlasenko96575962008-10-29 03:42:44 +0000245 * Note that we do not implement actual reboot
246 * (killall(TERM) + umount, etc), we just pause
247 * respawing and avoid exiting (-> making kernel oops).
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100248 * The user is responsible for the rest.
249 */
250 | (i_am_init ? ((1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGINT)) : 0)
Denis Vlasenko96575962008-10-29 03:42:44 +0000251 , record_signo);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000252 svdir = *argv++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000253
254#if ENABLE_FEATURE_RUNSVDIR_LOG
255 /* setup log */
256 if (*argv) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000257 rplog = *argv;
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100258 if (strlen(rplog) < 7) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000259 warnx("log must have at least seven characters");
260 } else if (piped_pair(logpipe)) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100261 warnx("can't create pipe for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000262 } else {
263 close_on_exec_on(logpipe.rd);
264 close_on_exec_on(logpipe.wr);
265 ndelay_on(logpipe.rd);
266 ndelay_on(logpipe.wr);
267 if (dup2(logpipe.wr, 2) == -1) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100268 warnx("can't set filedescriptor for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000269 } else {
270 pfd[0].fd = logpipe.rd;
271 pfd[0].events = POLLIN;
272 stamplog = monotonic_sec();
273 goto run;
274 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000275 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000276 rplog = NULL;
277 warnx("log service disabled");
Denis Vlasenko04c63862006-11-17 18:58:49 +0000278 }
Denis Vlasenko96575962008-10-29 03:42:44 +0000279 run:
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000280#endif
Denys Vlasenko05e86052010-10-13 12:53:27 +0200281 curdir = open(".", O_RDONLY|O_NDELAY);
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000282 if (curdir == -1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000283 fatal2_cannot("open current directory", "");
Denis Vlasenko96e1b382007-09-30 23:50:48 +0000284 close_on_exec_on(curdir);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000285
Denis Vlasenko45946f82007-08-20 17:27:40 +0000286 stampcheck = monotonic_sec();
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100287 need_rescan = 1;
288 last_mtime = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000289
290 for (;;) {
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100291 unsigned now;
292 unsigned sig;
293
Denis Vlasenko04c63862006-11-17 18:58:49 +0000294 /* collect children */
295 for (;;) {
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100296 pid_t pid = wait_any_nohang(NULL);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000297 if (pid <= 0)
298 break;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000299 for (i = 0; i < svnum; i++) {
300 if (pid == sv[i].pid) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000301 /* runsv has died */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000302 sv[i].pid = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000303 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000304 }
305 }
306 }
307
Denis Vlasenko45946f82007-08-20 17:27:40 +0000308 now = monotonic_sec();
309 if ((int)(now - stampcheck) >= 0) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000310 /* wait at least a second */
Denis Vlasenko45946f82007-08-20 17:27:40 +0000311 stampcheck = now + 1;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000312
Denis Vlasenko04c63862006-11-17 18:58:49 +0000313 if (stat(svdir, &s) != -1) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000314 if (need_rescan || s.st_mtime != last_mtime
Denis Vlasenko45946f82007-08-20 17:27:40 +0000315 || s.st_ino != last_ino || s.st_dev != last_dev
Denis Vlasenko04c63862006-11-17 18:58:49 +0000316 ) {
317 /* svdir modified */
318 if (chdir(svdir) != -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000319 last_mtime = s.st_mtime;
320 last_dev = s.st_dev;
321 last_ino = s.st_ino;
Eric Lammerts31905f92010-12-06 01:26:26 +0100322 /* if the svdir changed this very second, wait until the
323 * next second, because we won't be able to detect more
324 * changes within this second */
325 while (time(NULL) == last_mtime)
326 usleep(100000);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000327 need_rescan = do_rescan();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000328 while (fchdir(curdir) == -1) {
329 warn2_cannot("change directory, pausing", "");
330 sleep(5);
331 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000332 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000333 warn2_cannot("change directory to ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000334 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000335 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000336 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000337 warn2_cannot("stat ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000338 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000339 }
340
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000341#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000342 if (rplog) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000343 if ((int)(now - stamplog) >= 0) {
Denis Vlasenko37188322008-02-16 13:20:56 +0000344 write(logpipe.wr, ".", 1);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000345 stamplog = now + 900;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000346 }
347 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000348 pfd[0].revents = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000349#endif
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100350 {
351 unsigned deadline = (need_rescan ? 1 : 5);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000352#if ENABLE_FEATURE_RUNSVDIR_LOG
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100353 if (rplog)
354 poll(pfd, 1, deadline*1000);
355 else
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000356#endif
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100357 sleep(deadline);
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100358 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000359
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000360#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko45946f82007-08-20 17:27:40 +0000361 if (pfd[0].revents & POLLIN) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000362 char ch;
Denis Vlasenko37188322008-02-16 13:20:56 +0000363 while (read(logpipe.rd, &ch, 1) > 0) {
Denis Vlasenko96575962008-10-29 03:42:44 +0000364 if (ch < ' ')
365 ch = ' ';
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100366 for (i = 6; rplog[i] != '\0'; i++)
Denis Vlasenko96575962008-10-29 03:42:44 +0000367 rplog[i-1] = rplog[i];
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100368 rplog[i-1] = ch;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000369 }
370 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000371#endif
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100372 sig = bb_got_signal;
373 if (!sig)
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000374 continue;
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100375 bb_got_signal = 0;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000376
377 /* -s SCRIPT: useful if we are init.
378 * In this case typically script never returns,
379 * it halts/powers off/reboots the system. */
380 if (opt_s_argv[0]) {
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100381 pid_t pid;
382
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000383 /* Single parameter: signal# */
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100384 opt_s_argv[1] = utoa(sig);
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000385 pid = spawn(opt_s_argv);
386 if (pid > 0) {
Denis Vlasenko93b38202009-02-14 20:58:13 +0000387 /* Remembering to wait for _any_ children,
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000388 * not just pid */
389 while (wait(NULL) != pid)
390 continue;
391 }
392 }
393
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100394 if (sig == SIGHUP) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000395 for (i = 0; i < svnum; i++)
396 if (sv[i].pid)
397 kill(sv[i].pid, SIGTERM);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000398 }
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000399 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
400 /* Exit unless we are init */
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100401 if (!i_am_init)
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100402 return (SIGHUP == sig) ? 111 : EXIT_SUCCESS;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000403
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000404 /* init continues to monitor services forever */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000405 } /* for (;;) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000406}