blob: 9d560e0974caaecc45ec19b868c29dd0ac3e77e6 [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
31#include <sys/poll.h>
32#include <sys/file.h>
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000033#include "libbb.h"
Denis Vlasenko04c63862006-11-17 18:58:49 +000034#include "runit_lib.h"
35
36#define MAXSERVICES 1000
37
Denis Vlasenko923a79a2008-09-22 21:34:24 +000038/* Should be not needed - all dirs are on same FS, right? */
39#define CHECK_DEVNO_TOO 0
40
Denis Vlasenko45946f82007-08-20 17:27:40 +000041struct service {
Denis Vlasenko923a79a2008-09-22 21:34:24 +000042#if CHECK_DEVNO_TOO
Denis Vlasenko45946f82007-08-20 17:27:40 +000043 dev_t dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000044#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +000045 ino_t ino;
46 pid_t pid;
47 smallint isgone;
48};
49
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000050struct globals {
51 struct service *sv;
52 char *svdir;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000053 int svnum;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000054#if ENABLE_FEATURE_RUNSVDIR_LOG
55 char *rplog;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000056 int rploglen;
57 struct fd_pair logpipe;
58 struct pollfd pfd[1];
59 unsigned stamplog;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000060#endif
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000061};
62#define G (*(struct globals*)&bb_common_bufsiz1)
Denis Vlasenko923a79a2008-09-22 21:34:24 +000063#define sv (G.sv )
64#define svdir (G.svdir )
65#define svnum (G.svnum )
66#define rplog (G.rplog )
67#define rploglen (G.rploglen )
68#define logpipe (G.logpipe )
69#define pfd (G.pfd )
70#define stamplog (G.stamplog )
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000071#define INIT_G() do { \
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000072} while (0)
Denis Vlasenko04c63862006-11-17 18:58:49 +000073
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000074static void fatal2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000075{
76 bb_perror_msg_and_die("%s: fatal: cannot %s%s", svdir, m1, m2);
77 /* was exiting 100 */
78}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000079static void warn3x(const char *m1, const char *m2, const char *m3)
Denis Vlasenko04c63862006-11-17 18:58:49 +000080{
81 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
Denis Vlasenkof7996f32007-01-11 17:20:00 +000082}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000083static void warn2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000084{
85 warn3x("cannot ", m1, m2);
86}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000087#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000088static void warnx(const char *m1)
Denis Vlasenko04c63862006-11-17 18:58:49 +000089{
90 warn3x(m1, "", "");
Denis Vlasenkof7996f32007-01-11 17:20:00 +000091}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000092#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +000093
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +000094/* inlining + vfork -> bigger code */
95static NOINLINE pid_t runsv(const char *name)
Denis Vlasenko04c63862006-11-17 18:58:49 +000096{
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +000097 pid_t pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +000098
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +000099 /* If we got signaled, stop spawning children at once! */
100 if (bb_got_signal)
101 return 0;
102
103 pid = vfork();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000104 if (pid == -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000105 warn2_cannot("vfork", "");
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000106 return 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000107 }
108 if (pid == 0) {
109 /* child */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000110 if (option_mask32 & 1) /* -P option? */
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000111 setsid();
Denis Vlasenko96575962008-10-29 03:42:44 +0000112/* man execv:
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000113 * "Signals set to be caught by the calling process image
114 * shall be set to the default action in the new process image."
Denis Vlasenko96575962008-10-29 03:42:44 +0000115 * Therefore, we do not need this: */
116#if 0
Denis Vlasenko25591c32008-02-16 22:58:56 +0000117 bb_signals(0
Denis Vlasenko96575962008-10-29 03:42:44 +0000118 | (1 << SIGHUP)
119 | (1 << SIGTERM)
Denis Vlasenko25591c32008-02-16 22:58:56 +0000120 , SIG_DFL);
Denis Vlasenko96575962008-10-29 03:42:44 +0000121#endif
Denis Vlasenko58f3c2e2008-10-29 03:45:33 +0000122 execlp("runsv", "runsv", name, NULL);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000123 fatal2_cannot("start runsv ", name);
124 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000125 return pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000126}
127
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000128/* gcc 4.3.0 does better with NOINLINE */
129static NOINLINE int do_rescan(void)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000130{
131 DIR *dir;
132 direntry *d;
133 int i;
134 struct stat s;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000135 int need_rescan = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000136
137 dir = opendir(".");
138 if (!dir) {
139 warn2_cannot("open directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000140 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000141 }
142 for (i = 0; i < svnum; i++)
143 sv[i].isgone = 1;
Denis Vlasenko8f740942008-05-31 07:00:33 +0000144
145 while (1) {
146 errno = 0;
147 d = readdir(dir);
148 if (!d)
149 break;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000150 if (d->d_name[0] == '.')
151 continue;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000152 if (stat(d->d_name, &s) == -1) {
153 warn2_cannot("stat ", d->d_name);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000154 continue;
155 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000156 if (!S_ISDIR(s.st_mode))
157 continue;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000158 /* Do we have this service listed already? */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000159 for (i = 0; i < svnum; i++) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000160 if ((sv[i].ino == s.st_ino)
161#if CHECK_DEVNO_TOO
162 && (sv[i].dev == s.st_dev)
163#endif
164 ) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000165 if (sv[i].pid == 0) /* restart if it has died */
166 goto run_ith_sv;
167 sv[i].isgone = 0; /* "we still see you" */
168 goto next_dentry;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000169 }
170 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000171 { /* Not found, make new service */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000172 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
173 if (!svnew) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000174 warn2_cannot("start runsv ", d->d_name);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000175 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000176 continue;
177 }
178 sv = svnew;
179 svnum++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000180#if CHECK_DEVNO_TOO
Denis Vlasenko04c63862006-11-17 18:58:49 +0000181 sv[i].dev = s.st_dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000182#endif
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000183 sv[i].ino = s.st_ino;
184 run_ith_sv:
185 sv[i].pid = runsv(d->d_name);
186 sv[i].isgone = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000187 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000188 next_dentry: ;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000189 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000190 i = errno;
191 closedir(dir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000192 if (i) { /* readdir failed */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000193 warn2_cannot("read directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000194 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000195 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000196
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000197 /* Send SIGTERM to runsv whose directories
198 * were no longer found (-> must have been removed) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000199 for (i = 0; i < svnum; i++) {
200 if (!sv[i].isgone)
201 continue;
202 if (sv[i].pid)
203 kill(sv[i].pid, SIGTERM);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000204 svnum--;
205 sv[i] = sv[svnum];
206 i--; /* so that we don't skip new sv[i] (bug was here!) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000207 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000208 return need_rescan;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000209}
210
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000211int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000212int runsvdir_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000213{
214 struct stat s;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000215 dev_t last_dev = last_dev; /* for gcc */
216 ino_t last_ino = last_ino; /* for gcc */
217 time_t last_mtime = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000218 int wstat;
219 int curdir;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000220 pid_t pid;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000221 unsigned deadline;
222 unsigned now;
223 unsigned stampcheck;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000224 int i;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000225 int need_rescan = 1;
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
Denis Vlasenko96575962008-10-29 03:42:44 +0000236 bb_signals(0
237 | (1 << SIGTERM)
238 | (1 << SIGHUP)
239 /* For busybox's init, SIGTERM == reboot,
240 * SIGUSR1 == halt
241 * SIGUSR2 == poweroff
242 * so we need to intercept SIGUSRn too.
243 * Note that we do not implement actual reboot
244 * (killall(TERM) + umount, etc), we just pause
245 * respawing and avoid exiting (-> making kernel oops).
246 * The user is responsible for the rest. */
247 | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0)
248 , record_signo);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000249 svdir = *argv++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000250
251#if ENABLE_FEATURE_RUNSVDIR_LOG
252 /* setup log */
253 if (*argv) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000254 rplog = *argv;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000255 rploglen = strlen(rplog);
256 if (rploglen < 7) {
257 warnx("log must have at least seven characters");
258 } else if (piped_pair(logpipe)) {
259 warnx("cannot create pipe for log");
260 } else {
261 close_on_exec_on(logpipe.rd);
262 close_on_exec_on(logpipe.wr);
263 ndelay_on(logpipe.rd);
264 ndelay_on(logpipe.wr);
265 if (dup2(logpipe.wr, 2) == -1) {
266 warnx("cannot set filedescriptor for log");
267 } else {
268 pfd[0].fd = logpipe.rd;
269 pfd[0].events = POLLIN;
270 stamplog = monotonic_sec();
271 goto run;
272 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000273 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000274 rplog = NULL;
275 warnx("log service disabled");
Denis Vlasenko04c63862006-11-17 18:58:49 +0000276 }
Denis Vlasenko96575962008-10-29 03:42:44 +0000277 run:
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000278#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +0000279 curdir = open_read(".");
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000280 if (curdir == -1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000281 fatal2_cannot("open current directory", "");
Denis Vlasenko96e1b382007-09-30 23:50:48 +0000282 close_on_exec_on(curdir);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000283
Denis Vlasenko45946f82007-08-20 17:27:40 +0000284 stampcheck = monotonic_sec();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000285
286 for (;;) {
287 /* collect children */
288 for (;;) {
Denis Vlasenkofb0eba72008-01-02 19:55:04 +0000289 pid = wait_any_nohang(&wstat);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000290 if (pid <= 0)
291 break;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000292 for (i = 0; i < svnum; i++) {
293 if (pid == sv[i].pid) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000294 /* runsv has died */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000295 sv[i].pid = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000296 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000297 }
298 }
299 }
300
Denis Vlasenko45946f82007-08-20 17:27:40 +0000301 now = monotonic_sec();
302 if ((int)(now - stampcheck) >= 0) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000303 /* wait at least a second */
Denis Vlasenko45946f82007-08-20 17:27:40 +0000304 stampcheck = now + 1;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000305
Denis Vlasenko04c63862006-11-17 18:58:49 +0000306 if (stat(svdir, &s) != -1) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000307 if (need_rescan || s.st_mtime != last_mtime
Denis Vlasenko45946f82007-08-20 17:27:40 +0000308 || s.st_ino != last_ino || s.st_dev != last_dev
Denis Vlasenko04c63862006-11-17 18:58:49 +0000309 ) {
310 /* svdir modified */
311 if (chdir(svdir) != -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000312 last_mtime = s.st_mtime;
313 last_dev = s.st_dev;
314 last_ino = s.st_ino;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000315 //if (now <= mtime)
316 // sleep(1);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000317 need_rescan = do_rescan();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000318 while (fchdir(curdir) == -1) {
319 warn2_cannot("change directory, pausing", "");
320 sleep(5);
321 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000322 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000323 warn2_cannot("change directory to ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000324 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000325 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000326 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000327 warn2_cannot("stat ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000328 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000329 }
330
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000331#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000332 if (rplog) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000333 if ((int)(now - stamplog) >= 0) {
Denis Vlasenko37188322008-02-16 13:20:56 +0000334 write(logpipe.wr, ".", 1);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000335 stamplog = now + 900;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000336 }
337 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000338 pfd[0].revents = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000339#endif
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000340 deadline = (need_rescan ? 1 : 5);
Denis Vlasenko96575962008-10-29 03:42:44 +0000341 sig_block(SIGCHLD);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000342#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000343 if (rplog)
Denis Vlasenko45946f82007-08-20 17:27:40 +0000344 poll(pfd, 1, deadline*1000);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000345 else
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000346#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +0000347 sleep(deadline);
Denis Vlasenko8c783952007-01-27 22:21:52 +0000348 sig_unblock(SIGCHLD);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000349
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000350#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko45946f82007-08-20 17:27:40 +0000351 if (pfd[0].revents & POLLIN) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000352 char ch;
Denis Vlasenko37188322008-02-16 13:20:56 +0000353 while (read(logpipe.rd, &ch, 1) > 0) {
Denis Vlasenko96575962008-10-29 03:42:44 +0000354 if (ch < ' ')
355 ch = ' ';
356 for (i = 6; i < rploglen; i++)
357 rplog[i-1] = rplog[i];
358 rplog[rploglen-1] = ch;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000359 }
360 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000361#endif
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000362 if (!bb_got_signal)
363 continue;
364
365 /* -s SCRIPT: useful if we are init.
366 * In this case typically script never returns,
367 * it halts/powers off/reboots the system. */
368 if (opt_s_argv[0]) {
369 /* Single parameter: signal# */
370 opt_s_argv[1] = utoa(bb_got_signal);
371 pid = spawn(opt_s_argv);
372 if (pid > 0) {
373 /* Remebering to wait for _any_ children,
374 * not just pid */
375 while (wait(NULL) != pid)
376 continue;
377 }
378 }
379
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000380 switch (bb_got_signal) {
381 case SIGHUP:
Denis Vlasenko04c63862006-11-17 18:58:49 +0000382 for (i = 0; i < svnum; i++)
383 if (sv[i].pid)
384 kill(sv[i].pid, SIGTERM);
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000385 /* Fall through */
386 default: /* SIGTERM (or SIGUSRn if we are init) */
387 /* Exit unless we are init */
388 if (getpid() == 1)
389 break;
390 return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000391 }
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000392
393 bb_got_signal = 0;
394 } /* for (;;) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000395}