blob: 32526cf4caecb8558fc1186d3638cbda42ada5f5 [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/poll.h>
39#include <sys/file.h>
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000040#include "libbb.h"
Denis Vlasenko04c63862006-11-17 18:58:49 +000041#include "runit_lib.h"
42
43#define MAXSERVICES 1000
44
Denis Vlasenko923a79a2008-09-22 21:34:24 +000045/* Should be not needed - all dirs are on same FS, right? */
46#define CHECK_DEVNO_TOO 0
47
Denis Vlasenko45946f82007-08-20 17:27:40 +000048struct service {
Denis Vlasenko923a79a2008-09-22 21:34:24 +000049#if CHECK_DEVNO_TOO
Denis Vlasenko45946f82007-08-20 17:27:40 +000050 dev_t dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000051#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +000052 ino_t ino;
53 pid_t pid;
54 smallint isgone;
55};
56
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000057struct globals {
58 struct service *sv;
59 char *svdir;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000060 int svnum;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000061#if ENABLE_FEATURE_RUNSVDIR_LOG
62 char *rplog;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000063 int rploglen;
64 struct fd_pair logpipe;
65 struct pollfd pfd[1];
66 unsigned stamplog;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000067#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +010068} FIX_ALIASING;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000069#define G (*(struct globals*)&bb_common_bufsiz1)
Denis Vlasenko923a79a2008-09-22 21:34:24 +000070#define sv (G.sv )
71#define svdir (G.svdir )
72#define svnum (G.svnum )
73#define rplog (G.rplog )
74#define rploglen (G.rploglen )
75#define logpipe (G.logpipe )
76#define pfd (G.pfd )
77#define stamplog (G.stamplog )
Denys Vlasenko16714242011-09-21 01:59:15 +020078#define INIT_G() do { } while (0)
Denis Vlasenko04c63862006-11-17 18:58:49 +000079
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000080static void fatal2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000081{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010082 bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000083 /* was exiting 100 */
84}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000085static void warn3x(const char *m1, const char *m2, const char *m3)
Denis Vlasenko04c63862006-11-17 18:58:49 +000086{
87 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
Denis Vlasenkof7996f32007-01-11 17:20:00 +000088}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000089static void warn2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000090{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010091 warn3x("can't ", m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000092}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000093#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000094static void warnx(const char *m1)
Denis Vlasenko04c63862006-11-17 18:58:49 +000095{
96 warn3x(m1, "", "");
Denis Vlasenkof7996f32007-01-11 17:20:00 +000097}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000098#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +000099
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000100/* inlining + vfork -> bigger code */
101static NOINLINE pid_t runsv(const char *name)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000102{
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000103 pid_t pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000104
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000105 /* If we got signaled, stop spawning children at once! */
106 if (bb_got_signal)
107 return 0;
108
109 pid = vfork();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000110 if (pid == -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000111 warn2_cannot("vfork", "");
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000112 return 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000113 }
114 if (pid == 0) {
115 /* child */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000116 if (option_mask32 & 1) /* -P option? */
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000117 setsid();
Denis Vlasenko96575962008-10-29 03:42:44 +0000118/* man execv:
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000119 * "Signals set to be caught by the calling process image
120 * shall be set to the default action in the new process image."
Denis Vlasenko96575962008-10-29 03:42:44 +0000121 * Therefore, we do not need this: */
122#if 0
Denis Vlasenko25591c32008-02-16 22:58:56 +0000123 bb_signals(0
Denis Vlasenko96575962008-10-29 03:42:44 +0000124 | (1 << SIGHUP)
125 | (1 << SIGTERM)
Denis Vlasenko25591c32008-02-16 22:58:56 +0000126 , SIG_DFL);
Denis Vlasenko96575962008-10-29 03:42:44 +0000127#endif
Denis Vlasenkof09f4e02009-02-26 12:29:59 +0000128 execlp("runsv", "runsv", name, (char *) NULL);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000129 fatal2_cannot("start runsv ", name);
130 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000131 return pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000132}
133
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000134/* gcc 4.3.0 does better with NOINLINE */
135static NOINLINE int do_rescan(void)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000136{
137 DIR *dir;
Denys Vlasenkoaebb7422009-08-02 00:55:49 +0200138 struct dirent *d;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000139 int i;
140 struct stat s;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000141 int need_rescan = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000142
143 dir = opendir(".");
144 if (!dir) {
145 warn2_cannot("open directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000146 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000147 }
148 for (i = 0; i < svnum; i++)
149 sv[i].isgone = 1;
Denis Vlasenko8f740942008-05-31 07:00:33 +0000150
151 while (1) {
152 errno = 0;
153 d = readdir(dir);
154 if (!d)
155 break;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000156 if (d->d_name[0] == '.')
157 continue;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000158 if (stat(d->d_name, &s) == -1) {
159 warn2_cannot("stat ", d->d_name);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000160 continue;
161 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000162 if (!S_ISDIR(s.st_mode))
163 continue;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000164 /* Do we have this service listed already? */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000165 for (i = 0; i < svnum; i++) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000166 if ((sv[i].ino == s.st_ino)
167#if CHECK_DEVNO_TOO
168 && (sv[i].dev == s.st_dev)
169#endif
170 ) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000171 if (sv[i].pid == 0) /* restart if it has died */
172 goto run_ith_sv;
173 sv[i].isgone = 0; /* "we still see you" */
174 goto next_dentry;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000175 }
176 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000177 { /* Not found, make new service */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000178 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
179 if (!svnew) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000180 warn2_cannot("start runsv ", d->d_name);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000181 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000182 continue;
183 }
184 sv = svnew;
185 svnum++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000186#if CHECK_DEVNO_TOO
Denis Vlasenko04c63862006-11-17 18:58:49 +0000187 sv[i].dev = s.st_dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000188#endif
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000189 sv[i].ino = s.st_ino;
190 run_ith_sv:
191 sv[i].pid = runsv(d->d_name);
192 sv[i].isgone = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000193 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000194 next_dentry: ;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000195 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000196 i = errno;
197 closedir(dir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000198 if (i) { /* readdir failed */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000199 warn2_cannot("read directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000200 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000201 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000202
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000203 /* Send SIGTERM to runsv whose directories
204 * were no longer found (-> must have been removed) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000205 for (i = 0; i < svnum; i++) {
206 if (!sv[i].isgone)
207 continue;
208 if (sv[i].pid)
209 kill(sv[i].pid, SIGTERM);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000210 svnum--;
211 sv[i] = sv[svnum];
212 i--; /* so that we don't skip new sv[i] (bug was here!) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000213 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000214 return need_rescan;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000215}
216
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000217int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000218int runsvdir_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000219{
220 struct stat s;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000221 dev_t last_dev = last_dev; /* for gcc */
222 ino_t last_ino = last_ino; /* for gcc */
223 time_t last_mtime = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000224 int wstat;
225 int curdir;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000226 pid_t pid;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000227 unsigned deadline;
228 unsigned now;
229 unsigned stampcheck;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000230 int i;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000231 int need_rescan = 1;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000232 char *opt_s_argv[3];
Denis Vlasenko04c63862006-11-17 18:58:49 +0000233
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000234 INIT_G();
235
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000236 opt_complementary = "-1";
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000237 opt_s_argv[0] = NULL;
238 opt_s_argv[2] = NULL;
239 getopt32(argv, "Ps:", &opt_s_argv[0]);
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000240 argv += optind;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000241
Denis Vlasenko96575962008-10-29 03:42:44 +0000242 bb_signals(0
243 | (1 << SIGTERM)
244 | (1 << SIGHUP)
245 /* For busybox's init, SIGTERM == reboot,
246 * SIGUSR1 == halt
247 * SIGUSR2 == poweroff
248 * so we need to intercept SIGUSRn too.
249 * Note that we do not implement actual reboot
250 * (killall(TERM) + umount, etc), we just pause
251 * respawing and avoid exiting (-> making kernel oops).
252 * The user is responsible for the rest. */
253 | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0)
254 , record_signo);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000255 svdir = *argv++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000256
257#if ENABLE_FEATURE_RUNSVDIR_LOG
258 /* setup log */
259 if (*argv) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000260 rplog = *argv;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000261 rploglen = strlen(rplog);
262 if (rploglen < 7) {
263 warnx("log must have at least seven characters");
264 } else if (piped_pair(logpipe)) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100265 warnx("can't create pipe for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000266 } else {
267 close_on_exec_on(logpipe.rd);
268 close_on_exec_on(logpipe.wr);
269 ndelay_on(logpipe.rd);
270 ndelay_on(logpipe.wr);
271 if (dup2(logpipe.wr, 2) == -1) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100272 warnx("can't set filedescriptor for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000273 } else {
274 pfd[0].fd = logpipe.rd;
275 pfd[0].events = POLLIN;
276 stamplog = monotonic_sec();
277 goto run;
278 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000279 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000280 rplog = NULL;
281 warnx("log service disabled");
Denis Vlasenko04c63862006-11-17 18:58:49 +0000282 }
Denis Vlasenko96575962008-10-29 03:42:44 +0000283 run:
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000284#endif
Denys Vlasenko05e86052010-10-13 12:53:27 +0200285 curdir = open(".", O_RDONLY|O_NDELAY);
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000286 if (curdir == -1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000287 fatal2_cannot("open current directory", "");
Denis Vlasenko96e1b382007-09-30 23:50:48 +0000288 close_on_exec_on(curdir);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000289
Denis Vlasenko45946f82007-08-20 17:27:40 +0000290 stampcheck = monotonic_sec();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000291
292 for (;;) {
293 /* collect children */
294 for (;;) {
Denis Vlasenkofb0eba72008-01-02 19:55:04 +0000295 pid = wait_any_nohang(&wstat);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000296 if (pid <= 0)
297 break;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000298 for (i = 0; i < svnum; i++) {
299 if (pid == sv[i].pid) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000300 /* runsv has died */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000301 sv[i].pid = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000302 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000303 }
304 }
305 }
306
Denis Vlasenko45946f82007-08-20 17:27:40 +0000307 now = monotonic_sec();
308 if ((int)(now - stampcheck) >= 0) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000309 /* wait at least a second */
Denis Vlasenko45946f82007-08-20 17:27:40 +0000310 stampcheck = now + 1;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000311
Denis Vlasenko04c63862006-11-17 18:58:49 +0000312 if (stat(svdir, &s) != -1) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000313 if (need_rescan || s.st_mtime != last_mtime
Denis Vlasenko45946f82007-08-20 17:27:40 +0000314 || s.st_ino != last_ino || s.st_dev != last_dev
Denis Vlasenko04c63862006-11-17 18:58:49 +0000315 ) {
316 /* svdir modified */
317 if (chdir(svdir) != -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000318 last_mtime = s.st_mtime;
319 last_dev = s.st_dev;
320 last_ino = s.st_ino;
Eric Lammerts31905f92010-12-06 01:26:26 +0100321 /* if the svdir changed this very second, wait until the
322 * next second, because we won't be able to detect more
323 * changes within this second */
324 while (time(NULL) == last_mtime)
325 usleep(100000);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000326 need_rescan = do_rescan();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000327 while (fchdir(curdir) == -1) {
328 warn2_cannot("change directory, pausing", "");
329 sleep(5);
330 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000331 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000332 warn2_cannot("change directory to ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000333 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000334 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000335 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000336 warn2_cannot("stat ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000337 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000338 }
339
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000340#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000341 if (rplog) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000342 if ((int)(now - stamplog) >= 0) {
Denis Vlasenko37188322008-02-16 13:20:56 +0000343 write(logpipe.wr, ".", 1);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000344 stamplog = now + 900;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000345 }
346 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000347 pfd[0].revents = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000348#endif
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000349 deadline = (need_rescan ? 1 : 5);
Denis Vlasenko96575962008-10-29 03:42:44 +0000350 sig_block(SIGCHLD);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000351#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000352 if (rplog)
Denis Vlasenko45946f82007-08-20 17:27:40 +0000353 poll(pfd, 1, deadline*1000);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000354 else
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000355#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +0000356 sleep(deadline);
Denis Vlasenko8c783952007-01-27 22:21:52 +0000357 sig_unblock(SIGCHLD);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000358
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000359#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko45946f82007-08-20 17:27:40 +0000360 if (pfd[0].revents & POLLIN) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000361 char ch;
Denis Vlasenko37188322008-02-16 13:20:56 +0000362 while (read(logpipe.rd, &ch, 1) > 0) {
Denis Vlasenko96575962008-10-29 03:42:44 +0000363 if (ch < ' ')
364 ch = ' ';
365 for (i = 6; i < rploglen; i++)
366 rplog[i-1] = rplog[i];
367 rplog[rploglen-1] = ch;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000368 }
369 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000370#endif
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000371 if (!bb_got_signal)
372 continue;
373
374 /* -s SCRIPT: useful if we are init.
375 * In this case typically script never returns,
376 * it halts/powers off/reboots the system. */
377 if (opt_s_argv[0]) {
378 /* Single parameter: signal# */
379 opt_s_argv[1] = utoa(bb_got_signal);
380 pid = spawn(opt_s_argv);
381 if (pid > 0) {
Denis Vlasenko93b38202009-02-14 20:58:13 +0000382 /* Remembering to wait for _any_ children,
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000383 * not just pid */
384 while (wait(NULL) != pid)
385 continue;
386 }
387 }
388
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000389 if (bb_got_signal == SIGHUP) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000390 for (i = 0; i < svnum; i++)
391 if (sv[i].pid)
392 kill(sv[i].pid, SIGTERM);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000393 }
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000394 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
395 /* Exit unless we are init */
396 if (getpid() != 1)
397 return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000398
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000399 /* init continues to monitor services forever */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000400 bb_got_signal = 0;
401 } /* for (;;) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000402}