blob: 11ab40abf32d0f4755c0f5fca98be5a6f6554714 [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
Denys Vlasenko95f79532017-08-02 14:26:33 +020016THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
Denis Vlasenko8a164052007-03-12 23:34:52 +000017WARRANTIES, 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> */
Denys Vlasenko0863e1a2015-10-19 00:41:28 +020029
30//config:config RUNSVDIR
Denys Vlasenko4eed2c62017-07-18 22:01:24 +020031//config: bool "runsvdir (6 kb)"
Denys Vlasenko0863e1a2015-10-19 00:41:28 +020032//config: default y
33//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020034//config: runsvdir starts a runsv process for each subdirectory, or symlink to
35//config: a directory, in the services directory dir, up to a limit of 1000
36//config: subdirectories, and restarts a runsv process if it terminates.
Denys Vlasenko0863e1a2015-10-19 00:41:28 +020037//config:
38//config:config FEATURE_RUNSVDIR_LOG
39//config: bool "Enable scrolling argument log"
40//config: depends on RUNSVDIR
41//config: default n
42//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020043//config: Enable feature where second parameter of runsvdir holds last error
44//config: message (viewable via top/ps). Otherwise (feature is off
45//config: or no parameter), error messages go to stderr only.
Denys Vlasenko0863e1a2015-10-19 00:41:28 +020046
47//applet:IF_RUNSVDIR(APPLET(runsvdir, BB_DIR_USR_BIN, BB_SUID_DROP))
48
49//kbuild:lib-$(CONFIG_RUNSVDIR) += runsvdir.o
Denis Vlasenko04c63862006-11-17 18:58:49 +000050
Pere Orga5bc8c002011-04-11 03:29:49 +020051//usage:#define runsvdir_trivial_usage
52//usage: "[-P] [-s SCRIPT] DIR"
53//usage:#define runsvdir_full_usage "\n\n"
54//usage: "Start a runsv process for each subdirectory. If it exits, restart it.\n"
55//usage: "\n -P Put each runsv in a new session"
56//usage: "\n -s SCRIPT Run SCRIPT <signo> after signal is processed"
57
Denis Vlasenko04c63862006-11-17 18:58:49 +000058#include <sys/file.h>
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000059#include "libbb.h"
Denys Vlasenkoe6a2f4c2016-04-21 16:26:30 +020060#include "common_bufsiz.h"
Denis Vlasenko04c63862006-11-17 18:58:49 +000061#include "runit_lib.h"
62
63#define MAXSERVICES 1000
64
Denis Vlasenko923a79a2008-09-22 21:34:24 +000065/* Should be not needed - all dirs are on same FS, right? */
66#define CHECK_DEVNO_TOO 0
67
Denis Vlasenko45946f82007-08-20 17:27:40 +000068struct service {
Denis Vlasenko923a79a2008-09-22 21:34:24 +000069#if CHECK_DEVNO_TOO
Denis Vlasenko45946f82007-08-20 17:27:40 +000070 dev_t dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000071#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +000072 ino_t ino;
73 pid_t pid;
74 smallint isgone;
75};
76
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000077struct globals {
78 struct service *sv;
79 char *svdir;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000080 int svnum;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000081#if ENABLE_FEATURE_RUNSVDIR_LOG
82 char *rplog;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000083 struct fd_pair logpipe;
84 struct pollfd pfd[1];
85 unsigned stamplog;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000086#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +010087} FIX_ALIASING;
Denys Vlasenkoe6a2f4c2016-04-21 16:26:30 +020088#define G (*(struct globals*)bb_common_bufsiz1)
Denis Vlasenko923a79a2008-09-22 21:34:24 +000089#define sv (G.sv )
90#define svdir (G.svdir )
91#define svnum (G.svnum )
92#define rplog (G.rplog )
Denis Vlasenko923a79a2008-09-22 21:34:24 +000093#define logpipe (G.logpipe )
94#define pfd (G.pfd )
95#define stamplog (G.stamplog )
Denys Vlasenko47cfbf32016-04-21 18:18:48 +020096#define INIT_G() do { setup_common_bufsiz(); } while (0)
Denis Vlasenko04c63862006-11-17 18:58:49 +000097
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000098static void fatal2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000099{
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100100 bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000101 /* was exiting 100 */
102}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000103static void warn3x(const char *m1, const char *m2, const char *m3)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000104{
105 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000106}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000107static void warn2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000108{
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100109 warn3x("can't ", m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000110}
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000111#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenkoab2aea42007-01-29 22:51:58 +0000112static void warnx(const char *m1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000113{
114 warn3x(m1, "", "");
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000115}
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000116#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +0000117
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000118/* inlining + vfork -> bigger code */
119static NOINLINE pid_t runsv(const char *name)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000120{
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000121 pid_t pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000122
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000123 /* If we got signaled, stop spawning children at once! */
124 if (bb_got_signal)
125 return 0;
126
127 pid = vfork();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000128 if (pid == -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000129 warn2_cannot("vfork", "");
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000130 return 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000131 }
132 if (pid == 0) {
133 /* child */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000134 if (option_mask32 & 1) /* -P option? */
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000135 setsid();
Denis Vlasenko96575962008-10-29 03:42:44 +0000136/* man execv:
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000137 * "Signals set to be caught by the calling process image
138 * shall be set to the default action in the new process image."
Denis Vlasenko96575962008-10-29 03:42:44 +0000139 * Therefore, we do not need this: */
140#if 0
Denis Vlasenko25591c32008-02-16 22:58:56 +0000141 bb_signals(0
Denis Vlasenko96575962008-10-29 03:42:44 +0000142 | (1 << SIGHUP)
143 | (1 << SIGTERM)
Denis Vlasenko25591c32008-02-16 22:58:56 +0000144 , SIG_DFL);
Denis Vlasenko96575962008-10-29 03:42:44 +0000145#endif
Denis Vlasenkof09f4e02009-02-26 12:29:59 +0000146 execlp("runsv", "runsv", name, (char *) NULL);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000147 fatal2_cannot("start runsv ", name);
148 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000149 return pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000150}
151
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000152/* gcc 4.3.0 does better with NOINLINE */
153static NOINLINE int do_rescan(void)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000154{
155 DIR *dir;
Denys Vlasenkoaebb7422009-08-02 00:55:49 +0200156 struct dirent *d;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000157 int i;
158 struct stat s;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000159 int need_rescan = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000160
161 dir = opendir(".");
162 if (!dir) {
163 warn2_cannot("open directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000164 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000165 }
166 for (i = 0; i < svnum; i++)
167 sv[i].isgone = 1;
Denis Vlasenko8f740942008-05-31 07:00:33 +0000168
169 while (1) {
170 errno = 0;
171 d = readdir(dir);
172 if (!d)
173 break;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000174 if (d->d_name[0] == '.')
175 continue;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000176 if (stat(d->d_name, &s) == -1) {
177 warn2_cannot("stat ", d->d_name);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000178 continue;
179 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000180 if (!S_ISDIR(s.st_mode))
181 continue;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000182 /* Do we have this service listed already? */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000183 for (i = 0; i < svnum; i++) {
Denys Vlasenkoef159702016-09-01 11:16:22 +0200184 if (sv[i].ino == s.st_ino
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000185#if CHECK_DEVNO_TOO
Denys Vlasenkoef159702016-09-01 11:16:22 +0200186 && sv[i].dev == s.st_dev
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000187#endif
188 ) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000189 if (sv[i].pid == 0) /* restart if it has died */
190 goto run_ith_sv;
191 sv[i].isgone = 0; /* "we still see you" */
192 goto next_dentry;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000193 }
194 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000195 { /* Not found, make new service */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000196 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
197 if (!svnew) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000198 warn2_cannot("start runsv ", d->d_name);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000199 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000200 continue;
201 }
202 sv = svnew;
203 svnum++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000204#if CHECK_DEVNO_TOO
Denis Vlasenko04c63862006-11-17 18:58:49 +0000205 sv[i].dev = s.st_dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000206#endif
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000207 sv[i].ino = s.st_ino;
208 run_ith_sv:
209 sv[i].pid = runsv(d->d_name);
210 sv[i].isgone = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000211 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000212 next_dentry: ;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000213 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000214 i = errno;
215 closedir(dir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000216 if (i) { /* readdir failed */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000217 warn2_cannot("read directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000218 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000219 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000220
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000221 /* Send SIGTERM to runsv whose directories
222 * were no longer found (-> must have been removed) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000223 for (i = 0; i < svnum; i++) {
224 if (!sv[i].isgone)
225 continue;
226 if (sv[i].pid)
227 kill(sv[i].pid, SIGTERM);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000228 svnum--;
229 sv[i] = sv[svnum];
230 i--; /* so that we don't skip new sv[i] (bug was here!) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000231 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000232 return need_rescan;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000233}
234
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000235int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000236int runsvdir_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000237{
238 struct stat s;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000239 dev_t last_dev = last_dev; /* for gcc */
240 ino_t last_ino = last_ino; /* for gcc */
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100241 time_t last_mtime;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000242 int curdir;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000243 unsigned stampcheck;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000244 int i;
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100245 int need_rescan;
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100246 bool i_am_init;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000247 char *opt_s_argv[3];
Denis Vlasenko04c63862006-11-17 18:58:49 +0000248
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000249 INIT_G();
250
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000251 opt_s_argv[0] = NULL;
252 opt_s_argv[2] = NULL;
Denys Vlasenko22542ec2017-08-08 21:55:02 +0200253 getopt32(argv, "^" "Ps:" "\0" "-1", &opt_s_argv[0]);
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000254 argv += optind;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000255
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100256 i_am_init = (getpid() == 1);
Denis Vlasenko96575962008-10-29 03:42:44 +0000257 bb_signals(0
258 | (1 << SIGTERM)
259 | (1 << SIGHUP)
260 /* For busybox's init, SIGTERM == reboot,
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100261 * SIGUSR1 == halt,
262 * SIGUSR2 == poweroff,
263 * Ctlr-ALt-Del sends SIGINT to init,
264 * so we need to intercept SIGUSRn and SIGINT too.
Denis Vlasenko96575962008-10-29 03:42:44 +0000265 * Note that we do not implement actual reboot
266 * (killall(TERM) + umount, etc), we just pause
267 * respawing and avoid exiting (-> making kernel oops).
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100268 * The user is responsible for the rest.
269 */
270 | (i_am_init ? ((1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGINT)) : 0)
Denis Vlasenko96575962008-10-29 03:42:44 +0000271 , record_signo);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000272 svdir = *argv++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000273
274#if ENABLE_FEATURE_RUNSVDIR_LOG
275 /* setup log */
276 if (*argv) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000277 rplog = *argv;
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100278 if (strlen(rplog) < 7) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000279 warnx("log must have at least seven characters");
280 } else if (piped_pair(logpipe)) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100281 warnx("can't create pipe for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000282 } else {
283 close_on_exec_on(logpipe.rd);
284 close_on_exec_on(logpipe.wr);
285 ndelay_on(logpipe.rd);
286 ndelay_on(logpipe.wr);
287 if (dup2(logpipe.wr, 2) == -1) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100288 warnx("can't set filedescriptor for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000289 } else {
290 pfd[0].fd = logpipe.rd;
291 pfd[0].events = POLLIN;
292 stamplog = monotonic_sec();
293 goto run;
294 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000295 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000296 rplog = NULL;
297 warnx("log service disabled");
Denis Vlasenko04c63862006-11-17 18:58:49 +0000298 }
Denis Vlasenko96575962008-10-29 03:42:44 +0000299 run:
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000300#endif
Denys Vlasenko05e86052010-10-13 12:53:27 +0200301 curdir = open(".", O_RDONLY|O_NDELAY);
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000302 if (curdir == -1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000303 fatal2_cannot("open current directory", "");
Denis Vlasenko96e1b382007-09-30 23:50:48 +0000304 close_on_exec_on(curdir);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000305
Denis Vlasenko45946f82007-08-20 17:27:40 +0000306 stampcheck = monotonic_sec();
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100307 need_rescan = 1;
308 last_mtime = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000309
310 for (;;) {
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100311 unsigned now;
312 unsigned sig;
313
Denis Vlasenko04c63862006-11-17 18:58:49 +0000314 /* collect children */
315 for (;;) {
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100316 pid_t pid = wait_any_nohang(NULL);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000317 if (pid <= 0)
318 break;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000319 for (i = 0; i < svnum; i++) {
320 if (pid == sv[i].pid) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000321 /* runsv has died */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000322 sv[i].pid = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000323 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000324 }
325 }
326 }
327
Denis Vlasenko45946f82007-08-20 17:27:40 +0000328 now = monotonic_sec();
329 if ((int)(now - stampcheck) >= 0) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000330 /* wait at least a second */
Denis Vlasenko45946f82007-08-20 17:27:40 +0000331 stampcheck = now + 1;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000332
Denis Vlasenko04c63862006-11-17 18:58:49 +0000333 if (stat(svdir, &s) != -1) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000334 if (need_rescan || s.st_mtime != last_mtime
Denis Vlasenko45946f82007-08-20 17:27:40 +0000335 || s.st_ino != last_ino || s.st_dev != last_dev
Denis Vlasenko04c63862006-11-17 18:58:49 +0000336 ) {
337 /* svdir modified */
338 if (chdir(svdir) != -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000339 last_mtime = s.st_mtime;
340 last_dev = s.st_dev;
341 last_ino = s.st_ino;
Eric Lammerts31905f92010-12-06 01:26:26 +0100342 /* if the svdir changed this very second, wait until the
343 * next second, because we won't be able to detect more
344 * changes within this second */
345 while (time(NULL) == last_mtime)
346 usleep(100000);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000347 need_rescan = do_rescan();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000348 while (fchdir(curdir) == -1) {
349 warn2_cannot("change directory, pausing", "");
350 sleep(5);
351 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000352 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000353 warn2_cannot("change directory to ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000354 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000355 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000356 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000357 warn2_cannot("stat ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000358 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000359 }
360
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000361#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000362 if (rplog) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000363 if ((int)(now - stamplog) >= 0) {
Denis Vlasenko37188322008-02-16 13:20:56 +0000364 write(logpipe.wr, ".", 1);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000365 stamplog = now + 900;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000366 }
367 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000368 pfd[0].revents = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000369#endif
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100370 {
371 unsigned deadline = (need_rescan ? 1 : 5);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000372#if ENABLE_FEATURE_RUNSVDIR_LOG
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100373 if (rplog)
374 poll(pfd, 1, deadline*1000);
375 else
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000376#endif
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100377 sleep(deadline);
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100378 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000379
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000380#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko45946f82007-08-20 17:27:40 +0000381 if (pfd[0].revents & POLLIN) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000382 char ch;
Denis Vlasenko37188322008-02-16 13:20:56 +0000383 while (read(logpipe.rd, &ch, 1) > 0) {
Denis Vlasenko96575962008-10-29 03:42:44 +0000384 if (ch < ' ')
385 ch = ' ';
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100386 for (i = 6; rplog[i] != '\0'; i++)
Denis Vlasenko96575962008-10-29 03:42:44 +0000387 rplog[i-1] = rplog[i];
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100388 rplog[i-1] = ch;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000389 }
390 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000391#endif
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100392 sig = bb_got_signal;
393 if (!sig)
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000394 continue;
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100395 bb_got_signal = 0;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000396
397 /* -s SCRIPT: useful if we are init.
398 * In this case typically script never returns,
399 * it halts/powers off/reboots the system. */
400 if (opt_s_argv[0]) {
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100401 pid_t pid;
402
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000403 /* Single parameter: signal# */
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100404 opt_s_argv[1] = utoa(sig);
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000405 pid = spawn(opt_s_argv);
406 if (pid > 0) {
Denis Vlasenko93b38202009-02-14 20:58:13 +0000407 /* Remembering to wait for _any_ children,
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000408 * not just pid */
409 while (wait(NULL) != pid)
410 continue;
411 }
412 }
413
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100414 if (sig == SIGHUP) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000415 for (i = 0; i < svnum; i++)
416 if (sv[i].pid)
417 kill(sv[i].pid, SIGTERM);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000418 }
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000419 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
420 /* Exit unless we are init */
Denys Vlasenko7db2a7c2015-03-02 17:39:13 +0100421 if (!i_am_init)
Denys Vlasenkofa535f32015-03-02 17:37:31 +0100422 return (SIGHUP == sig) ? 111 : EXIT_SUCCESS;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000423
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000424 /* init continues to monitor services forever */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000425 } /* for (;;) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000426}