blob: 9495a2a4fb52388610d30585c7d197ba69503f80 [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 )
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000078#define INIT_G() do { \
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000079} while (0)
Denis Vlasenko04c63862006-11-17 18:58:49 +000080
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000081static void fatal2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000082{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010083 bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000084 /* was exiting 100 */
85}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000086static void warn3x(const char *m1, const char *m2, const char *m3)
Denis Vlasenko04c63862006-11-17 18:58:49 +000087{
88 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
Denis Vlasenkof7996f32007-01-11 17:20:00 +000089}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000090static void warn2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000091{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010092 warn3x("can't ", m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000093}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000094#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000095static void warnx(const char *m1)
Denis Vlasenko04c63862006-11-17 18:58:49 +000096{
97 warn3x(m1, "", "");
Denis Vlasenkof7996f32007-01-11 17:20:00 +000098}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000099#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +0000100
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000101/* inlining + vfork -> bigger code */
102static NOINLINE pid_t runsv(const char *name)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000103{
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000104 pid_t pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000105
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000106 /* If we got signaled, stop spawning children at once! */
107 if (bb_got_signal)
108 return 0;
109
110 pid = vfork();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000111 if (pid == -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000112 warn2_cannot("vfork", "");
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000113 return 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000114 }
115 if (pid == 0) {
116 /* child */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000117 if (option_mask32 & 1) /* -P option? */
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000118 setsid();
Denis Vlasenko96575962008-10-29 03:42:44 +0000119/* man execv:
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000120 * "Signals set to be caught by the calling process image
121 * shall be set to the default action in the new process image."
Denis Vlasenko96575962008-10-29 03:42:44 +0000122 * Therefore, we do not need this: */
123#if 0
Denis Vlasenko25591c32008-02-16 22:58:56 +0000124 bb_signals(0
Denis Vlasenko96575962008-10-29 03:42:44 +0000125 | (1 << SIGHUP)
126 | (1 << SIGTERM)
Denis Vlasenko25591c32008-02-16 22:58:56 +0000127 , SIG_DFL);
Denis Vlasenko96575962008-10-29 03:42:44 +0000128#endif
Denis Vlasenkof09f4e02009-02-26 12:29:59 +0000129 execlp("runsv", "runsv", name, (char *) NULL);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000130 fatal2_cannot("start runsv ", name);
131 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000132 return pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000133}
134
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000135/* gcc 4.3.0 does better with NOINLINE */
136static NOINLINE int do_rescan(void)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000137{
138 DIR *dir;
Denys Vlasenkoaebb7422009-08-02 00:55:49 +0200139 struct dirent *d;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000140 int i;
141 struct stat s;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000142 int need_rescan = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000143
144 dir = opendir(".");
145 if (!dir) {
146 warn2_cannot("open directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000147 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000148 }
149 for (i = 0; i < svnum; i++)
150 sv[i].isgone = 1;
Denis Vlasenko8f740942008-05-31 07:00:33 +0000151
152 while (1) {
153 errno = 0;
154 d = readdir(dir);
155 if (!d)
156 break;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000157 if (d->d_name[0] == '.')
158 continue;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000159 if (stat(d->d_name, &s) == -1) {
160 warn2_cannot("stat ", d->d_name);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000161 continue;
162 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000163 if (!S_ISDIR(s.st_mode))
164 continue;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000165 /* Do we have this service listed already? */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000166 for (i = 0; i < svnum; i++) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000167 if ((sv[i].ino == s.st_ino)
168#if CHECK_DEVNO_TOO
169 && (sv[i].dev == s.st_dev)
170#endif
171 ) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000172 if (sv[i].pid == 0) /* restart if it has died */
173 goto run_ith_sv;
174 sv[i].isgone = 0; /* "we still see you" */
175 goto next_dentry;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000176 }
177 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000178 { /* Not found, make new service */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000179 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
180 if (!svnew) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000181 warn2_cannot("start runsv ", d->d_name);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000182 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000183 continue;
184 }
185 sv = svnew;
186 svnum++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000187#if CHECK_DEVNO_TOO
Denis Vlasenko04c63862006-11-17 18:58:49 +0000188 sv[i].dev = s.st_dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000189#endif
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000190 sv[i].ino = s.st_ino;
191 run_ith_sv:
192 sv[i].pid = runsv(d->d_name);
193 sv[i].isgone = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000194 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000195 next_dentry: ;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000196 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000197 i = errno;
198 closedir(dir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000199 if (i) { /* readdir failed */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000200 warn2_cannot("read directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000201 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000202 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000203
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000204 /* Send SIGTERM to runsv whose directories
205 * were no longer found (-> must have been removed) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000206 for (i = 0; i < svnum; i++) {
207 if (!sv[i].isgone)
208 continue;
209 if (sv[i].pid)
210 kill(sv[i].pid, SIGTERM);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000211 svnum--;
212 sv[i] = sv[svnum];
213 i--; /* so that we don't skip new sv[i] (bug was here!) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000214 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000215 return need_rescan;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000216}
217
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000218int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000219int runsvdir_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000220{
221 struct stat s;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000222 dev_t last_dev = last_dev; /* for gcc */
223 ino_t last_ino = last_ino; /* for gcc */
224 time_t last_mtime = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000225 int wstat;
226 int curdir;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000227 pid_t pid;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000228 unsigned deadline;
229 unsigned now;
230 unsigned stampcheck;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000231 int i;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000232 int need_rescan = 1;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000233 char *opt_s_argv[3];
Denis Vlasenko04c63862006-11-17 18:58:49 +0000234
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000235 INIT_G();
236
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000237 opt_complementary = "-1";
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000238 opt_s_argv[0] = NULL;
239 opt_s_argv[2] = NULL;
240 getopt32(argv, "Ps:", &opt_s_argv[0]);
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000241 argv += optind;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000242
Denis Vlasenko96575962008-10-29 03:42:44 +0000243 bb_signals(0
244 | (1 << SIGTERM)
245 | (1 << SIGHUP)
246 /* For busybox's init, SIGTERM == reboot,
247 * SIGUSR1 == halt
248 * SIGUSR2 == poweroff
249 * so we need to intercept SIGUSRn too.
250 * Note that we do not implement actual reboot
251 * (killall(TERM) + umount, etc), we just pause
252 * respawing and avoid exiting (-> making kernel oops).
253 * The user is responsible for the rest. */
254 | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0)
255 , record_signo);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000256 svdir = *argv++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000257
258#if ENABLE_FEATURE_RUNSVDIR_LOG
259 /* setup log */
260 if (*argv) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000261 rplog = *argv;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000262 rploglen = strlen(rplog);
263 if (rploglen < 7) {
264 warnx("log must have at least seven characters");
265 } else if (piped_pair(logpipe)) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100266 warnx("can't create pipe for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000267 } else {
268 close_on_exec_on(logpipe.rd);
269 close_on_exec_on(logpipe.wr);
270 ndelay_on(logpipe.rd);
271 ndelay_on(logpipe.wr);
272 if (dup2(logpipe.wr, 2) == -1) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100273 warnx("can't set filedescriptor for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000274 } else {
275 pfd[0].fd = logpipe.rd;
276 pfd[0].events = POLLIN;
277 stamplog = monotonic_sec();
278 goto run;
279 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000280 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000281 rplog = NULL;
282 warnx("log service disabled");
Denis Vlasenko04c63862006-11-17 18:58:49 +0000283 }
Denis Vlasenko96575962008-10-29 03:42:44 +0000284 run:
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000285#endif
Denys Vlasenko05e86052010-10-13 12:53:27 +0200286 curdir = open(".", O_RDONLY|O_NDELAY);
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000287 if (curdir == -1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000288 fatal2_cannot("open current directory", "");
Denis Vlasenko96e1b382007-09-30 23:50:48 +0000289 close_on_exec_on(curdir);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000290
Denis Vlasenko45946f82007-08-20 17:27:40 +0000291 stampcheck = monotonic_sec();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000292
293 for (;;) {
294 /* collect children */
295 for (;;) {
Denis Vlasenkofb0eba72008-01-02 19:55:04 +0000296 pid = wait_any_nohang(&wstat);
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
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000350 deadline = (need_rescan ? 1 : 5);
Denis Vlasenko96575962008-10-29 03:42:44 +0000351 sig_block(SIGCHLD);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000352#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000353 if (rplog)
Denis Vlasenko45946f82007-08-20 17:27:40 +0000354 poll(pfd, 1, deadline*1000);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000355 else
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000356#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +0000357 sleep(deadline);
Denis Vlasenko8c783952007-01-27 22:21:52 +0000358 sig_unblock(SIGCHLD);
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 = ' ';
366 for (i = 6; i < rploglen; i++)
367 rplog[i-1] = rplog[i];
368 rplog[rploglen-1] = ch;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000369 }
370 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000371#endif
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000372 if (!bb_got_signal)
373 continue;
374
375 /* -s SCRIPT: useful if we are init.
376 * In this case typically script never returns,
377 * it halts/powers off/reboots the system. */
378 if (opt_s_argv[0]) {
379 /* Single parameter: signal# */
380 opt_s_argv[1] = utoa(bb_got_signal);
381 pid = spawn(opt_s_argv);
382 if (pid > 0) {
Denis Vlasenko93b38202009-02-14 20:58:13 +0000383 /* Remembering to wait for _any_ children,
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000384 * not just pid */
385 while (wait(NULL) != pid)
386 continue;
387 }
388 }
389
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000390 if (bb_got_signal == SIGHUP) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000391 for (i = 0; i < svnum; i++)
392 if (sv[i].pid)
393 kill(sv[i].pid, SIGTERM);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000394 }
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000395 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
396 /* Exit unless we are init */
397 if (getpid() != 1)
398 return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000399
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000400 /* init continues to monitor services forever */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000401 bb_got_signal = 0;
402 } /* for (;;) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000403}