From 018804204f41e6e60cec536843275f8fdd4d3620 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Mar 2017 22:32:05 +0100 Subject: runit: fix chpst -n -N -u USER busybox's chpst first switches user/group and then tries to call nice(). Once the root priviledges are dropped, process priority can only be lowered. So negative nice values don't work anymore. Upstream version of chpst correctly calls nice() before switching user. Signed-off-by: Denys Vlasenko --- runit/chpst.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'runit') diff --git a/runit/chpst.c b/runit/chpst.c index 846c846d3..ee3a33153 100644 --- a/runit/chpst.c +++ b/runit/chpst.c @@ -463,6 +463,13 @@ int chpst_main(int argc UNUSED_PARAM, char **argv) xchroot(root); } + /* nice should be done before xsetuid */ + if (opt & OPT_n) { + errno = 0; + if (nice(xatoi(nicestr)) == -1) + bb_perror_msg_and_die("nice"); + } + if (opt & OPT_u) { if (setgroups(1, &ugid.gid) == -1) bb_perror_msg_and_die("setgroups"); @@ -470,12 +477,6 @@ int chpst_main(int argc UNUSED_PARAM, char **argv) xsetuid(ugid.uid); } - if (opt & OPT_n) { - errno = 0; - if (nice(xatoi(nicestr)) == -1) - bb_perror_msg_and_die("nice"); - } - if (opt & OPT_0) close(STDIN_FILENO); if (opt & OPT_1) -- cgit v1.2.3-55-g6feb From 835ad3a984c5590ae4f6c94f2f0781ea049d1ae8 Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Wed, 12 Apr 2017 00:58:46 +0300 Subject: libbb: GETOPT_RESET macro Signed-off-by: Kaarle Ritvanen Signed-off-by: Denys Vlasenko --- include/libbb.h | 22 ++++++++++++++++++++++ libbb/getopt32.c | 8 +------- libbb/vfork_daemon_rexec.c | 28 ++-------------------------- runit/sv.c | 7 +------ shell/shell_common.c | 8 +------- util-linux/getopt.c | 7 +------ 6 files changed, 28 insertions(+), 52 deletions(-) (limited to 'runit') diff --git a/include/libbb.h b/include/libbb.h index 2c30bde6f..11d022fb5 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1178,6 +1178,28 @@ extern uint32_t option_mask32; extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; +/* BSD-derived getopt() functions require that optind be set to 1 in + * order to reset getopt() state. This used to be generally accepted + * way of resetting getopt(). However, glibc's getopt() + * has additional getopt() state beyond optind (specifically, glibc + * extensions ('+' and '-' at the start of the string), and requires + * that optind be set to zero to reset its state. BSD-derived versions + * of getopt() misbehaved if optind is set to 0 in order to reset getopt(), + * and glibc's getopt() used to coredump if optind is set 1 in order + * to reset getopt(). + * Then BSD introduced additional variable "optreset" which + * be set to 1 in order to reset getopt(). Sigh. Standards, anyone? + * + * By ~2008, OpenBSD 3.4 was changed to survive glibc-like optind = 0 + * (to interpret it as if optreset was set). + */ +#ifdef __GLIBC__ +#define GETOPT_RESET() (optind = 0) +#else /* BSD style */ +#define GETOPT_RESET() (optind = 1) +#endif + + /* Having next pointer as a first member allows easy creation * of "llist-compatible" structs, and using llist_FOO functions * on them. diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 497fc016f..3104826ef 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -576,13 +576,7 @@ getopt32(char **argv, const char *applet_opts, ...) * run_nofork_applet() does this, but we might end up here * also via gunzip_main() -> gzip_main(). Play safe. */ -#ifdef __GLIBC__ - optind = 0; -#else /* BSD style */ - optind = 1; - /* optreset = 1; */ -#endif - /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ + GETOPT_RESET(); /* Note: just "getopt() <= 0" will not work well for * "fake" short options, like this one: diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 2e7dc2d9b..fd481bf6e 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -121,28 +121,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) /* In case getopt() or getopt32() was already called: * reset the libc getopt() function, which keeps internal state. - * - * BSD-derived getopt() functions require that optind be set to 1 in - * order to reset getopt() state. This used to be generally accepted - * way of resetting getopt(). However, glibc's getopt() - * has additional getopt() state beyond optind, and requires that - * optind be set to zero to reset its state. So the unfortunate state of - * affairs is that BSD-derived versions of getopt() misbehave if - * optind is set to 0 in order to reset getopt(), and glibc's getopt() - * will core dump if optind is set 1 in order to reset getopt(). - * - * More modern versions of BSD require that optreset be set to 1 in - * order to reset getopt(). Sigh. Standards, anyone? */ -#ifdef __GLIBC__ - optind = 0; -#else /* BSD style */ - optind = 1; - /* optreset = 1; */ -#endif - /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */ - /* (values above are what they initialized to in glibc and uclibc) */ - /* option_mask32 = 0; - not needed, no applet depends on it being 0 */ + GETOPT_RESET(); argc = 1; while (argv[argc]) @@ -167,11 +147,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) restore_nofork_data(&old); /* Other globals can be simply reset to defaults */ -#ifdef __GLIBC__ - optind = 0; -#else /* BSD style */ - optind = 1; -#endif + GETOPT_RESET(); return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ } diff --git a/runit/sv.c b/runit/sv.c index 9e2132259..64f1ae395 100644 --- a/runit/sv.c +++ b/runit/sv.c @@ -688,12 +688,7 @@ int svc_main(int argc UNUSED_PARAM, char **argv) /* getopt32() was already called: * reset the libc getopt() function, which keeps internal state. */ -#ifdef __GLIBC__ - optind = 0; -#else /* BSD style */ - optind = 1; - /* optreset = 1; */ -#endif + GETOPT_RESET(); do { if (opts & 1) { diff --git a/shell/shell_common.c b/shell/shell_common.c index 549b17ca1..fb86e680f 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -401,13 +401,7 @@ shell_builtin_ulimit(char **argv) /* In case getopt was already called: * reset the libc getopt() function, which keeps internal state. */ -#ifdef __GLIBC__ - optind = 0; -#else /* BSD style */ - optind = 1; - /* optreset = 1; */ -#endif - /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ + GETOPT_RESET(); argc = 1; while (argv[argc]) diff --git a/util-linux/getopt.c b/util-linux/getopt.c index 63294c520..79d54854b 100644 --- a/util-linux/getopt.c +++ b/util-linux/getopt.c @@ -246,12 +246,7 @@ static int generate_output(char **argv, int argc, const char *optstr, const stru /* We used it already in main() in getopt32(), * we *must* reset getopt(3): */ -#ifdef __GLIBC__ - optind = 0; -#else /* BSD style */ - optind = 1; - /* optreset = 1; */ -#endif + GETOPT_RESET(); while (1) { #if ENABLE_FEATURE_GETOPT_LONG -- cgit v1.2.3-55-g6feb From 79c0d7332ab9707bcbdaaa71b034d939ad36c8d7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 May 2017 19:12:09 +0200 Subject: svlogd.c: support -ttt (dateTtime instead of date_time) Backport from upstream version: 1.7.0 Sat, 07 Oct 2006 18:24:17 +0000 * svlogd.c: new option -ttt: prefix log messages with sortable UTC timestamp YYYY-MM-DDTHH:MM:SS.xxxxx. function old new delta svlogd_main 1429 1454 +25 packed_usage 31575 31580 +5 Signed-off-by: Denys Vlasenko --- runit/svlogd.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'runit') diff --git a/runit/svlogd.c b/runit/svlogd.c index 3ed13b67b..795bf48bb 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -137,9 +137,9 @@ log message, you can use a pattern like this instead //kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o //usage:#define svlogd_trivial_usage -//usage: "[-ttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..." +//usage: "[-tttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..." //usage:#define svlogd_full_usage "\n\n" -//usage: "Continuously read log data from stdin and write to rotated log files in DIRs" +//usage: "Read log data from stdin and write to rotated log files in DIRs" //usage: "\n" //usage: "\n""DIR/config file modifies behavior:" //usage: "\n""sSIZE - when to rotate logs" @@ -339,17 +339,18 @@ static unsigned pmatch(const char *p, const char *s, unsigned len) /*** ex fmt_ptime.[ch] ***/ /* NUL terminated */ -static void fmt_time_human_30nul(char *s) +static void fmt_time_human_30nul(char *s, char dt_delim) { struct tm *ptm; struct timeval tv; gettimeofday(&tv, NULL); ptm = gmtime(&tv.tv_sec); - sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000", + sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", (unsigned)(1900 + ptm->tm_year), (unsigned)(ptm->tm_mon + 1), (unsigned)(ptm->tm_mday), + dt_delim, (unsigned)(ptm->tm_hour), (unsigned)(ptm->tm_min), (unsigned)(ptm->tm_sec), @@ -1160,8 +1161,8 @@ int svlogd_main(int argc, char **argv) if (timestamp) { if (timestamp == 1) fmt_time_bernstein_25(stamp); - else /* 2: */ - fmt_time_human_30nul(stamp); + else /* 2+: */ + fmt_time_human_30nul(stamp, timestamp == 2 ? '_' : 'T'); printlen += 26; printptr -= 26; memcpy(printptr, stamp, 25); -- cgit v1.2.3-55-g6feb From bcb5764822b07f2f1f6a5db355566ac1da70ac5b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 May 2017 19:44:48 +0200 Subject: runsv: update to match version 2.1.2 of runit Backport from upstream versions: 2.1.0 Thu, 24 Sep 2009 22:49:33 +0000 * runsv.c: exit with error if [log/]supervise/control exists, but is not a fifo. [Code abstracted into a separate function to make it more compact for BusyBox.] 1.9.0 Mon, 05 May 2008 22:00:13 +0000 * runsv.c: create temporary new status files for log/supervise/ actually in log/supervise/. 1.7.2 Tue, 21 Nov 2006 15:13:47 +0000 * runsv.c: really don't act on commands in state finish; minor. function old new delta open_control - 135 +135 update_status 553 612 +59 custom 223 242 +19 ctrl 426 422 -4 warn_cannot 21 10 -11 runsv_main 1786 1662 -124 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/3 up/down: 213/-139) Total: 74 bytes Signed-off-by: Denys Vlasenko --- runit/runsv.c | 95 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 37 deletions(-) (limited to 'runit') diff --git a/runit/runsv.c b/runit/runsv.c index e0e31508a..939653d12 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -134,9 +134,13 @@ static void fatal2x_cannot(const char *m1, const char *m2) bb_error_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2); /* was exiting 111 */ } +static void warn2_cannot(const char *m1, const char *m2) +{ + bb_perror_msg("%s: warning: can't %s%s", dir, m1, m2); +} static void warn_cannot(const char *m) { - bb_perror_msg("%s: warning: cannot %s", dir, m); + warn2_cannot(m, ""); } static void s_child(int sig_no UNUSED_PARAM) @@ -165,10 +169,25 @@ static void update_status(struct svdir *s) ssize_t sz; int fd; svstatus_t status; + const char *fstatus ="log/supervise/status"; + const char *fstatusnew ="log/supervise/status.new"; + const char *f_stat ="log/supervise/stat"; + const char *fstatnew ="log/supervise/stat.new"; + const char *fpid ="log/supervise/pid"; + const char *fpidnew ="log/supervise/pid.new"; + + if (!s->islog) { + fstatus += 4; + fstatusnew += 4; + f_stat += 4; + fstatnew += 4; + fpid += 4; + fpidnew += 4; + } /* pid */ if (pidchanged) { - fd = open_trunc_or_warn("supervise/pid.new"); + fd = open_trunc_or_warn(fpidnew); if (fd < 0) return; if (s->pid) { @@ -177,14 +196,13 @@ static void update_status(struct svdir *s) write(fd, spid, size); } close(fd); - if (rename_or_warn("supervise/pid.new", - s->islog ? "log/supervise/pid" : "log/supervise/pid"+4)) + if (rename_or_warn(fpidnew, fpid)) return; pidchanged = 0; } /* stat */ - fd = open_trunc_or_warn("supervise/stat.new"); + fd = open_trunc_or_warn(fstatnew); if (fd < -1) return; @@ -220,8 +238,7 @@ static void update_status(struct svdir *s) close(fd); } - rename_or_warn("supervise/stat.new", - s->islog ? "log/supervise/stat" : "log/supervise/stat"+4); + rename_or_warn(fstatnew, f_stat); /* supervise compatibility */ memset(&status, 0, sizeof(status)); @@ -237,18 +254,17 @@ static void update_status(struct svdir *s) if (s->ctrl & C_TERM) status.got_term = 1; status.run_or_finish = s->state; - fd = open_trunc_or_warn("supervise/status.new"); + fd = open_trunc_or_warn(fstatusnew); if (fd < 0) return; sz = write(fd, &status, sizeof(status)); close(fd); if (sz != sizeof(status)) { - warn_cannot("write supervise/status.new"); - unlink("supervise/status.new"); + warn2_cannot("write ", fstatusnew); + unlink(fstatusnew); return; } - rename_or_warn("supervise/status.new", - s->islog ? "log/supervise/status" : "log/supervise/status"+4); + rename_or_warn(fstatusnew, fstatus); } static unsigned custom(struct svdir *s, char c) @@ -266,26 +282,26 @@ static unsigned custom(struct svdir *s, char c) if (st.st_mode & S_IXUSR) { pid = vfork(); if (pid == -1) { - warn_cannot("vfork for control/?"); + warn2_cannot("vfork for ", a); return 0; } if (pid == 0) { /* child */ if (haslog && dup2(logpipe.wr, 1) == -1) - warn_cannot("setup stdout for control/?"); + warn2_cannot("setup stdout for ", a); execl(a, a, (char *) NULL); - fatal_cannot("run control/?"); + fatal2_cannot("run ", a); } /* parent */ if (safe_waitpid(pid, &w, 0) == -1) { - warn_cannot("wait for child control/?"); + warn2_cannot("wait for child ", a); return 0; } return WEXITSTATUS(w) == 0; } } else { if (errno != ENOENT) - warn_cannot("stat control/?"); + warn2_cannot("stat ", a); } return 0; } @@ -387,13 +403,13 @@ static int ctrl(struct svdir *s, char c) case 'd': /* down */ s->sd_want = W_DOWN; update_status(s); - if (s->pid && s->state != S_FINISH) + if (s->state == S_RUN) stopservice(s); break; case 'u': /* up */ s->sd_want = W_UP; update_status(s); - if (s->pid == 0) + if (s->state == S_DOWN) startservice(s); break; case 'x': /* exit */ @@ -403,22 +419,22 @@ static int ctrl(struct svdir *s, char c) update_status(s); /* FALLTHROUGH */ case 't': /* sig term */ - if (s->pid && s->state != S_FINISH) + if (s->state == S_RUN) stopservice(s); break; case 'k': /* sig kill */ - if (s->pid && !custom(s, c)) + if ((s->state == S_RUN) && !custom(s, c)) kill(s->pid, SIGKILL); s->state = S_DOWN; break; case 'p': /* sig pause */ - if (s->pid && !custom(s, c)) + if ((s->state == S_RUN) && !custom(s, c)) kill(s->pid, SIGSTOP); s->ctrl |= C_PAUSE; update_status(s); break; case 'c': /* sig cont */ - if (s->pid && !custom(s, c)) + if ((s->state == S_RUN) && !custom(s, c)) kill(s->pid, SIGCONT); s->ctrl &= ~C_PAUSE; update_status(s); @@ -426,7 +442,7 @@ static int ctrl(struct svdir *s, char c) case 'o': /* once */ s->sd_want = W_DOWN; update_status(s); - if (!s->pid) + if (s->state == S_DOWN) startservice(s); break; case 'a': /* sig alarm */ @@ -450,11 +466,26 @@ static int ctrl(struct svdir *s, char c) } return 1; sendsig: - if (s->pid && !custom(s, c)) + if ((s->state == S_RUN) && !custom(s, c)) kill(s->pid, sig); return 1; } +static void open_control(const char *f, struct svdir *s) +{ + struct stat st; + mkfifo(f, 0600); + if (stat(f, &st) == -1) + fatal2_cannot("stat ", f); + if (!S_ISFIFO(st.st_mode)) + bb_error_msg_and_die("%s: fatal: %s exists but is not a fifo", dir, f); + s->fdcontrol = xopen(f, O_RDONLY|O_NDELAY); + close_on_exec_on(s->fdcontrol); + s->fdcontrolwrite = xopen(f, O_WRONLY|O_NDELAY); + close_on_exec_on(s->fdcontrolwrite); + update_status(s); +} + int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int runsv_main(int argc UNUSED_PARAM, char **argv) { @@ -554,19 +585,9 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) close_on_exec_on(svd[1].fdlock); } - mkfifo("log/supervise/control"+4, 0600); - svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY); - close_on_exec_on(svd[0].fdcontrol); - svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY); - close_on_exec_on(svd[0].fdcontrolwrite); - update_status(&svd[0]); + open_control("log/supervise/control"+4, &svd[0]); if (haslog) { - mkfifo("log/supervise/control", 0600); - svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY); - close_on_exec_on(svd[1].fdcontrol); - svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY); - close_on_exec_on(svd[1].fdcontrolwrite); - update_status(&svd[1]); + open_control("log/supervise/control", &svd[1]); } mkfifo("log/supervise/ok"+4, 0600); fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY); -- cgit v1.2.3-55-g6feb From 0c63299b84513ff995413f820cb5f3d546c0c5d7 Mon Sep 17 00:00:00 2001 From: James Byrne Date: Mon, 15 May 2017 21:39:51 +0200 Subject: sv: update to match version 2.1.2 of runit Backport from upstream versions: 2.1.2 Sun, 10 Aug 2014 18:01:54 +0000 * sv.c: properly format status command's output on failure cases. * sv.c: support optional LSB init script actions reload and try-restart. * sv.c: fix typo that may lead to wrong output from sv when reporting status of multiple service directories. 2.1.1 Sun, 04 Oct 2009 20:28:38 +0000 * sv.c: on 'down', send runsv the 'down' command properly if not yet done (e.g. when taken up with 'once'). [Remove previous workaround added to BusyBox version]. 1.9.0 Mon, 05 May 2008 22:00:13 +0000 * sv.c: service name is also relative to the current directory if it ends with a slash. 1.8.0 Fri, 21 Sep 2007 00:33:56 +0000 * sv.c: fix race on check for down if pid is 0 and state is run or finish. 1.7.1 Sat, 04 Nov 2006 19:23:29 +0000 * sv.c: properly wait for a service to be restarted on 'restart'; support checks through -v for pause, cont, kill. function old new delta sv 1184 1280 +96 control 132 180 +48 status 118 139 +21 out 64 85 +21 svstatus_print 334 344 +10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/0 up/down: 196/0) Total: 196 bytes Signed-off-by: James Byrne Signed-off-by: Denys Vlasenko --- runit/sv.c | 163 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 65 deletions(-) (limited to 'runit') diff --git a/runit/sv.c b/runit/sv.c index 64f1ae395..faa31d4fa 100644 --- a/runit/sv.c +++ b/runit/sv.c @@ -25,7 +25,7 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Taken from http://smarden.sunsite.dk/runit/sv.8.html: +/* Taken from http://smarden.org/runit/sv.8.html: sv - control and manage services monitored by runsv @@ -36,17 +36,13 @@ The sv program reports the current status and controls the state of services monitored by the runsv(8) supervisor. services consists of one or more arguments, each argument naming a directory -service used by runsv(8). If service doesn't start with a dot or slash, -it is searched in the default services directory /var/service/, otherwise -relative to the current directory. +service used by runsv(8). If service doesn't start with a dot or slash and +doesn't end with a slash, it is searched in the default services directory +/var/service/, otherwise relative to the current directory. command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, -1, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, -force-reload, force-restart, force-shutdown. - -The sv program can be sym-linked to /etc/init.d/ to provide an LSB init -script interface. The service to be controlled then is specified by the -base name of the "init script". +1, 2, term, kill, or exit, or start, stop, reload, restart, shutdown, +force-stop, force-reload, force-restart, force-shutdown, try-restart. status Report the current status of the service, and the appendant log service @@ -66,9 +62,9 @@ exit If the service is running, send it the TERM signal, and the CONT signal. Do not restart the service. If the service is down, and no log service exists, runsv(8) exits. If the service is down and a log service exists, - send the TERM signal to the log service. If the log service is down, - runsv(8) exits. This command is ignored if it is given to an appendant - log service. + runsv(8) closes the standard input of the log service and waits for it to + terminate. If the log service is down, runsv(8) exits. This command is + ignored if it is given to an appendant log service. sv actually looks only at the first character of above commands. @@ -85,6 +81,8 @@ start stop Same as down, but wait up to 7 seconds for the service to become down. Then report the status or timeout. +reload + Same as hup, and additionally report the status afterwards. restart Send the commands term, cont, and up to the service, and wait up to 7 seconds for the service to restart. Then report the status or timeout. @@ -112,6 +110,9 @@ force-shutdown Same as exit, but wait up to 7 seconds for the runsv(8) process to terminate. Then report the status, and on timeout send the service the kill command. +try-restart + if the service is running, send it the term and cont commands, and wait up to + 7 seconds for the service to restart. Then report the status or timeout. Additional Commands @@ -126,8 +127,8 @@ check Options -v - wait up to 7 seconds for the command to take effect. - Then report the status or timeout. + If the command is up, down, term, once, cont, or exit, then wait up to 7 + seconds for the command to take effect. Then report the status or timeout. -w sec Override the default timeout of 7 seconds with sec seconds. Implies -v. @@ -192,6 +193,7 @@ struct globals { /* "Bernstein" time format: unix + 0x400000000000000aULL */ uint64_t tstart, tnow; svstatus_t svstatus; + unsigned islog; } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) #define acts (G.acts ) @@ -200,6 +202,7 @@ struct globals { #define tstart (G.tstart ) #define tnow (G.tnow ) #define svstatus (G.svstatus ) +#define islog (G.islog ) #define INIT_G() do { setup_common_bufsiz(); } while (0) @@ -215,7 +218,7 @@ static void fatal_cannot(const char *m1) static void out(const char *p, const char *m1) { - printf("%s%s: %s", p, *service, m1); + printf("%s%s%s: %s", p, *service, islog ? "/log" : "", m1); if (errno) { printf(": %s", strerror(errno)); } @@ -300,15 +303,14 @@ static unsigned svstatus_print(const char *m) } pid = SWAP_LE32(svstatus.pid_le32); timestamp = SWAP_BE64(svstatus.time_be64); - if (pid) { - switch (svstatus.run_or_finish) { + switch (svstatus.run_or_finish) { + case 0: printf("down: "); break; case 1: printf("run: "); break; case 2: printf("finish: "); break; - } - printf("%s: (pid %d) ", m, pid); - } else { - printf("down: %s: ", m); } + printf("%s: ", m); + if (svstatus.run_or_finish) + printf("(pid %d) ", pid); diff = tnow - timestamp; printf("%us", (diff < 0 ? 0 : diff)); if (pid) { @@ -331,16 +333,21 @@ static int status(const char *unused UNUSED_PARAM) return 0; r = svstatus_print(*service); + islog = 1; if (chdir("log") == -1) { if (errno != ENOENT) { - printf("; log: "WARN"can't change to log service directory: %s", - strerror(errno)); - } - } else if (svstatus_get()) { + printf("; "); + warn("can't change directory"); + } else + bb_putchar('\n'); + } else { printf("; "); - svstatus_print("log"); + if (svstatus_get()) { + r = svstatus_print("log"); + bb_putchar('\n'); + } } - bb_putchar('\n'); /* will also flush the output */ + islog = 0; return r; } @@ -379,35 +386,53 @@ static int check(const char *a) r = svstatus_get(); if (r == -1) return -1; - if (r == 0) { - if (*a == 'x') - return 1; - return -1; - } - pid_le32 = svstatus.pid_le32; - switch (*a) { - case 'x': - return 0; - case 'u': - if (!pid_le32 || svstatus.run_or_finish != 1) return 0; - if (!checkscript()) return 0; - break; - case 'd': - if (pid_le32) return 0; - break; - case 'c': - if (pid_le32 && !checkscript()) return 0; - break; - case 't': - if (!pid_le32 && svstatus.want == 'd') break; - timestamp = SWAP_BE64(svstatus.time_be64); - if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) - return 0; - break; - case 'o': - timestamp = SWAP_BE64(svstatus.time_be64); - if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) + while (*a) { + if (r == 0) { + if (*a == 'x') + return 1; + return -1; + } + pid_le32 = svstatus.pid_le32; + switch (*a) { + case 'x': return 0; + case 'u': + if (!pid_le32 || svstatus.run_or_finish != 1) + return 0; + if (!checkscript()) + return 0; + break; + case 'd': + if (pid_le32 || svstatus.run_or_finish != 0) + return 0; + break; + case 'C': + if (pid_le32 && !checkscript()) + return 0; + break; + case 't': + case 'k': + if (!pid_le32 && svstatus.want == 'd') + break; + timestamp = SWAP_BE64(svstatus.time_be64); + if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) + return 0; + break; + case 'o': + timestamp = SWAP_BE64(svstatus.time_be64); + if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) + return 0; + break; + case 'p': + if (pid_le32 && !svstatus.paused) + return 0; + break; + case 'c': + if (pid_le32 && svstatus.paused) + return 0; + break; + } + ++a; } printf(OK); svstatus_print(*service); @@ -419,14 +444,10 @@ static int control(const char *a) { int fd, r, l; -/* Is it an optimization? - It causes problems with "sv o SRV; ...; sv d SRV" - ('d' is not passed to SRV because its .want == 'd'): if (svstatus_get() <= 0) return -1; - if (svstatus.want == *a) + if (svstatus.want == *a && (*a != 'd' || svstatus.got_term == 1)) return 0; -*/ fd = open("supervise/control", O_WRONLY|O_NDELAY); if (fd == -1) { if (errno != ENODEV) @@ -516,17 +537,23 @@ static int sv(char **argv) acts = "tc"; kll = 1; break; + case 't': + if (str_equal(action, "try-restart")) { + acts = "tc"; + break; + } case 'c': if (str_equal(action, "check")) { act = NULL; - acts = "c"; + acts = "C"; break; } - case 'u': case 'd': case 'o': case 't': case 'p': case 'h': + case 'u': case 'd': case 'o': case 'p': case 'h': case 'a': case 'i': case 'k': case 'q': case '1': case '2': action[1] = '\0'; acts = action; - if (!verbose) cbk = NULL; + if (!verbose) + cbk = NULL; break; case 's': if (str_equal(action, "shutdown")) { @@ -550,6 +577,10 @@ static int sv(char **argv) acts = "tcu"; break; } + if (str_equal(action, "reload")) { + acts = "h"; + break; + } bb_show_usage(); case 'f': if (str_equal(action, "force-reload")) { @@ -578,7 +609,9 @@ static int sv(char **argv) service = argv; while ((x = *service) != NULL) { - if (x[0] != '/' && x[0] != '.') { + if (x[0] != '/' && x[0] != '.' + && x[0] != '\0' && x[strlen(x) - 1] != '/' + ) { if (chdir(varservice) == -1) goto chdir_failed_0; } -- cgit v1.2.3-55-g6feb