diff options
Diffstat (limited to 'runit')
-rw-r--r-- | runit/chpst.c | 13 | ||||
-rw-r--r-- | runit/runsv.c | 95 | ||||
-rw-r--r-- | runit/sv.c | 170 | ||||
-rw-r--r-- | runit/svlogd.c | 13 |
4 files changed, 171 insertions, 120 deletions
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) | |||
463 | xchroot(root); | 463 | xchroot(root); |
464 | } | 464 | } |
465 | 465 | ||
466 | /* nice should be done before xsetuid */ | ||
467 | if (opt & OPT_n) { | ||
468 | errno = 0; | ||
469 | if (nice(xatoi(nicestr)) == -1) | ||
470 | bb_perror_msg_and_die("nice"); | ||
471 | } | ||
472 | |||
466 | if (opt & OPT_u) { | 473 | if (opt & OPT_u) { |
467 | if (setgroups(1, &ugid.gid) == -1) | 474 | if (setgroups(1, &ugid.gid) == -1) |
468 | bb_perror_msg_and_die("setgroups"); | 475 | bb_perror_msg_and_die("setgroups"); |
@@ -470,12 +477,6 @@ int chpst_main(int argc UNUSED_PARAM, char **argv) | |||
470 | xsetuid(ugid.uid); | 477 | xsetuid(ugid.uid); |
471 | } | 478 | } |
472 | 479 | ||
473 | if (opt & OPT_n) { | ||
474 | errno = 0; | ||
475 | if (nice(xatoi(nicestr)) == -1) | ||
476 | bb_perror_msg_and_die("nice"); | ||
477 | } | ||
478 | |||
479 | if (opt & OPT_0) | 480 | if (opt & OPT_0) |
480 | close(STDIN_FILENO); | 481 | close(STDIN_FILENO); |
481 | if (opt & OPT_1) | 482 | if (opt & OPT_1) |
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) | |||
134 | bb_error_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2); | 134 | bb_error_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2); |
135 | /* was exiting 111 */ | 135 | /* was exiting 111 */ |
136 | } | 136 | } |
137 | static void warn2_cannot(const char *m1, const char *m2) | ||
138 | { | ||
139 | bb_perror_msg("%s: warning: can't %s%s", dir, m1, m2); | ||
140 | } | ||
137 | static void warn_cannot(const char *m) | 141 | static void warn_cannot(const char *m) |
138 | { | 142 | { |
139 | bb_perror_msg("%s: warning: cannot %s", dir, m); | 143 | warn2_cannot(m, ""); |
140 | } | 144 | } |
141 | 145 | ||
142 | static void s_child(int sig_no UNUSED_PARAM) | 146 | static void s_child(int sig_no UNUSED_PARAM) |
@@ -165,10 +169,25 @@ static void update_status(struct svdir *s) | |||
165 | ssize_t sz; | 169 | ssize_t sz; |
166 | int fd; | 170 | int fd; |
167 | svstatus_t status; | 171 | svstatus_t status; |
172 | const char *fstatus ="log/supervise/status"; | ||
173 | const char *fstatusnew ="log/supervise/status.new"; | ||
174 | const char *f_stat ="log/supervise/stat"; | ||
175 | const char *fstatnew ="log/supervise/stat.new"; | ||
176 | const char *fpid ="log/supervise/pid"; | ||
177 | const char *fpidnew ="log/supervise/pid.new"; | ||
178 | |||
179 | if (!s->islog) { | ||
180 | fstatus += 4; | ||
181 | fstatusnew += 4; | ||
182 | f_stat += 4; | ||
183 | fstatnew += 4; | ||
184 | fpid += 4; | ||
185 | fpidnew += 4; | ||
186 | } | ||
168 | 187 | ||
169 | /* pid */ | 188 | /* pid */ |
170 | if (pidchanged) { | 189 | if (pidchanged) { |
171 | fd = open_trunc_or_warn("supervise/pid.new"); | 190 | fd = open_trunc_or_warn(fpidnew); |
172 | if (fd < 0) | 191 | if (fd < 0) |
173 | return; | 192 | return; |
174 | if (s->pid) { | 193 | if (s->pid) { |
@@ -177,14 +196,13 @@ static void update_status(struct svdir *s) | |||
177 | write(fd, spid, size); | 196 | write(fd, spid, size); |
178 | } | 197 | } |
179 | close(fd); | 198 | close(fd); |
180 | if (rename_or_warn("supervise/pid.new", | 199 | if (rename_or_warn(fpidnew, fpid)) |
181 | s->islog ? "log/supervise/pid" : "log/supervise/pid"+4)) | ||
182 | return; | 200 | return; |
183 | pidchanged = 0; | 201 | pidchanged = 0; |
184 | } | 202 | } |
185 | 203 | ||
186 | /* stat */ | 204 | /* stat */ |
187 | fd = open_trunc_or_warn("supervise/stat.new"); | 205 | fd = open_trunc_or_warn(fstatnew); |
188 | if (fd < -1) | 206 | if (fd < -1) |
189 | return; | 207 | return; |
190 | 208 | ||
@@ -220,8 +238,7 @@ static void update_status(struct svdir *s) | |||
220 | close(fd); | 238 | close(fd); |
221 | } | 239 | } |
222 | 240 | ||
223 | rename_or_warn("supervise/stat.new", | 241 | rename_or_warn(fstatnew, f_stat); |
224 | s->islog ? "log/supervise/stat" : "log/supervise/stat"+4); | ||
225 | 242 | ||
226 | /* supervise compatibility */ | 243 | /* supervise compatibility */ |
227 | memset(&status, 0, sizeof(status)); | 244 | memset(&status, 0, sizeof(status)); |
@@ -237,18 +254,17 @@ static void update_status(struct svdir *s) | |||
237 | if (s->ctrl & C_TERM) | 254 | if (s->ctrl & C_TERM) |
238 | status.got_term = 1; | 255 | status.got_term = 1; |
239 | status.run_or_finish = s->state; | 256 | status.run_or_finish = s->state; |
240 | fd = open_trunc_or_warn("supervise/status.new"); | 257 | fd = open_trunc_or_warn(fstatusnew); |
241 | if (fd < 0) | 258 | if (fd < 0) |
242 | return; | 259 | return; |
243 | sz = write(fd, &status, sizeof(status)); | 260 | sz = write(fd, &status, sizeof(status)); |
244 | close(fd); | 261 | close(fd); |
245 | if (sz != sizeof(status)) { | 262 | if (sz != sizeof(status)) { |
246 | warn_cannot("write supervise/status.new"); | 263 | warn2_cannot("write ", fstatusnew); |
247 | unlink("supervise/status.new"); | 264 | unlink(fstatusnew); |
248 | return; | 265 | return; |
249 | } | 266 | } |
250 | rename_or_warn("supervise/status.new", | 267 | rename_or_warn(fstatusnew, fstatus); |
251 | s->islog ? "log/supervise/status" : "log/supervise/status"+4); | ||
252 | } | 268 | } |
253 | 269 | ||
254 | static unsigned custom(struct svdir *s, char c) | 270 | static unsigned custom(struct svdir *s, char c) |
@@ -266,26 +282,26 @@ static unsigned custom(struct svdir *s, char c) | |||
266 | if (st.st_mode & S_IXUSR) { | 282 | if (st.st_mode & S_IXUSR) { |
267 | pid = vfork(); | 283 | pid = vfork(); |
268 | if (pid == -1) { | 284 | if (pid == -1) { |
269 | warn_cannot("vfork for control/?"); | 285 | warn2_cannot("vfork for ", a); |
270 | return 0; | 286 | return 0; |
271 | } | 287 | } |
272 | if (pid == 0) { | 288 | if (pid == 0) { |
273 | /* child */ | 289 | /* child */ |
274 | if (haslog && dup2(logpipe.wr, 1) == -1) | 290 | if (haslog && dup2(logpipe.wr, 1) == -1) |
275 | warn_cannot("setup stdout for control/?"); | 291 | warn2_cannot("setup stdout for ", a); |
276 | execl(a, a, (char *) NULL); | 292 | execl(a, a, (char *) NULL); |
277 | fatal_cannot("run control/?"); | 293 | fatal2_cannot("run ", a); |
278 | } | 294 | } |
279 | /* parent */ | 295 | /* parent */ |
280 | if (safe_waitpid(pid, &w, 0) == -1) { | 296 | if (safe_waitpid(pid, &w, 0) == -1) { |
281 | warn_cannot("wait for child control/?"); | 297 | warn2_cannot("wait for child ", a); |
282 | return 0; | 298 | return 0; |
283 | } | 299 | } |
284 | return WEXITSTATUS(w) == 0; | 300 | return WEXITSTATUS(w) == 0; |
285 | } | 301 | } |
286 | } else { | 302 | } else { |
287 | if (errno != ENOENT) | 303 | if (errno != ENOENT) |
288 | warn_cannot("stat control/?"); | 304 | warn2_cannot("stat ", a); |
289 | } | 305 | } |
290 | return 0; | 306 | return 0; |
291 | } | 307 | } |
@@ -387,13 +403,13 @@ static int ctrl(struct svdir *s, char c) | |||
387 | case 'd': /* down */ | 403 | case 'd': /* down */ |
388 | s->sd_want = W_DOWN; | 404 | s->sd_want = W_DOWN; |
389 | update_status(s); | 405 | update_status(s); |
390 | if (s->pid && s->state != S_FINISH) | 406 | if (s->state == S_RUN) |
391 | stopservice(s); | 407 | stopservice(s); |
392 | break; | 408 | break; |
393 | case 'u': /* up */ | 409 | case 'u': /* up */ |
394 | s->sd_want = W_UP; | 410 | s->sd_want = W_UP; |
395 | update_status(s); | 411 | update_status(s); |
396 | if (s->pid == 0) | 412 | if (s->state == S_DOWN) |
397 | startservice(s); | 413 | startservice(s); |
398 | break; | 414 | break; |
399 | case 'x': /* exit */ | 415 | case 'x': /* exit */ |
@@ -403,22 +419,22 @@ static int ctrl(struct svdir *s, char c) | |||
403 | update_status(s); | 419 | update_status(s); |
404 | /* FALLTHROUGH */ | 420 | /* FALLTHROUGH */ |
405 | case 't': /* sig term */ | 421 | case 't': /* sig term */ |
406 | if (s->pid && s->state != S_FINISH) | 422 | if (s->state == S_RUN) |
407 | stopservice(s); | 423 | stopservice(s); |
408 | break; | 424 | break; |
409 | case 'k': /* sig kill */ | 425 | case 'k': /* sig kill */ |
410 | if (s->pid && !custom(s, c)) | 426 | if ((s->state == S_RUN) && !custom(s, c)) |
411 | kill(s->pid, SIGKILL); | 427 | kill(s->pid, SIGKILL); |
412 | s->state = S_DOWN; | 428 | s->state = S_DOWN; |
413 | break; | 429 | break; |
414 | case 'p': /* sig pause */ | 430 | case 'p': /* sig pause */ |
415 | if (s->pid && !custom(s, c)) | 431 | if ((s->state == S_RUN) && !custom(s, c)) |
416 | kill(s->pid, SIGSTOP); | 432 | kill(s->pid, SIGSTOP); |
417 | s->ctrl |= C_PAUSE; | 433 | s->ctrl |= C_PAUSE; |
418 | update_status(s); | 434 | update_status(s); |
419 | break; | 435 | break; |
420 | case 'c': /* sig cont */ | 436 | case 'c': /* sig cont */ |
421 | if (s->pid && !custom(s, c)) | 437 | if ((s->state == S_RUN) && !custom(s, c)) |
422 | kill(s->pid, SIGCONT); | 438 | kill(s->pid, SIGCONT); |
423 | s->ctrl &= ~C_PAUSE; | 439 | s->ctrl &= ~C_PAUSE; |
424 | update_status(s); | 440 | update_status(s); |
@@ -426,7 +442,7 @@ static int ctrl(struct svdir *s, char c) | |||
426 | case 'o': /* once */ | 442 | case 'o': /* once */ |
427 | s->sd_want = W_DOWN; | 443 | s->sd_want = W_DOWN; |
428 | update_status(s); | 444 | update_status(s); |
429 | if (!s->pid) | 445 | if (s->state == S_DOWN) |
430 | startservice(s); | 446 | startservice(s); |
431 | break; | 447 | break; |
432 | case 'a': /* sig alarm */ | 448 | case 'a': /* sig alarm */ |
@@ -450,11 +466,26 @@ static int ctrl(struct svdir *s, char c) | |||
450 | } | 466 | } |
451 | return 1; | 467 | return 1; |
452 | sendsig: | 468 | sendsig: |
453 | if (s->pid && !custom(s, c)) | 469 | if ((s->state == S_RUN) && !custom(s, c)) |
454 | kill(s->pid, sig); | 470 | kill(s->pid, sig); |
455 | return 1; | 471 | return 1; |
456 | } | 472 | } |
457 | 473 | ||
474 | static void open_control(const char *f, struct svdir *s) | ||
475 | { | ||
476 | struct stat st; | ||
477 | mkfifo(f, 0600); | ||
478 | if (stat(f, &st) == -1) | ||
479 | fatal2_cannot("stat ", f); | ||
480 | if (!S_ISFIFO(st.st_mode)) | ||
481 | bb_error_msg_and_die("%s: fatal: %s exists but is not a fifo", dir, f); | ||
482 | s->fdcontrol = xopen(f, O_RDONLY|O_NDELAY); | ||
483 | close_on_exec_on(s->fdcontrol); | ||
484 | s->fdcontrolwrite = xopen(f, O_WRONLY|O_NDELAY); | ||
485 | close_on_exec_on(s->fdcontrolwrite); | ||
486 | update_status(s); | ||
487 | } | ||
488 | |||
458 | int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 489 | int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
459 | int runsv_main(int argc UNUSED_PARAM, char **argv) | 490 | int runsv_main(int argc UNUSED_PARAM, char **argv) |
460 | { | 491 | { |
@@ -554,19 +585,9 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) | |||
554 | close_on_exec_on(svd[1].fdlock); | 585 | close_on_exec_on(svd[1].fdlock); |
555 | } | 586 | } |
556 | 587 | ||
557 | mkfifo("log/supervise/control"+4, 0600); | 588 | open_control("log/supervise/control"+4, &svd[0]); |
558 | svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY); | ||
559 | close_on_exec_on(svd[0].fdcontrol); | ||
560 | svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY); | ||
561 | close_on_exec_on(svd[0].fdcontrolwrite); | ||
562 | update_status(&svd[0]); | ||
563 | if (haslog) { | 589 | if (haslog) { |
564 | mkfifo("log/supervise/control", 0600); | 590 | open_control("log/supervise/control", &svd[1]); |
565 | svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY); | ||
566 | close_on_exec_on(svd[1].fdcontrol); | ||
567 | svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY); | ||
568 | close_on_exec_on(svd[1].fdcontrolwrite); | ||
569 | update_status(&svd[1]); | ||
570 | } | 591 | } |
571 | mkfifo("log/supervise/ok"+4, 0600); | 592 | mkfifo("log/supervise/ok"+4, 0600); |
572 | fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY); | 593 | fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY); |
diff --git a/runit/sv.c b/runit/sv.c index 9e2132259..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 | |||
25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* Taken from http://smarden.sunsite.dk/runit/sv.8.html: | 28 | /* Taken from http://smarden.org/runit/sv.8.html: |
29 | 29 | ||
30 | sv - control and manage services monitored by runsv | 30 | sv - control and manage services monitored by runsv |
31 | 31 | ||
@@ -36,17 +36,13 @@ The sv program reports the current status and controls the state of services | |||
36 | monitored by the runsv(8) supervisor. | 36 | monitored by the runsv(8) supervisor. |
37 | 37 | ||
38 | services consists of one or more arguments, each argument naming a directory | 38 | services consists of one or more arguments, each argument naming a directory |
39 | service used by runsv(8). If service doesn't start with a dot or slash, | 39 | service used by runsv(8). If service doesn't start with a dot or slash and |
40 | it is searched in the default services directory /var/service/, otherwise | 40 | doesn't end with a slash, it is searched in the default services directory |
41 | relative to the current directory. | 41 | /var/service/, otherwise relative to the current directory. |
42 | 42 | ||
43 | command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, | 43 | command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, |
44 | 1, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, | 44 | 1, 2, term, kill, or exit, or start, stop, reload, restart, shutdown, |
45 | force-reload, force-restart, force-shutdown. | 45 | force-stop, force-reload, force-restart, force-shutdown, try-restart. |
46 | |||
47 | The sv program can be sym-linked to /etc/init.d/ to provide an LSB init | ||
48 | script interface. The service to be controlled then is specified by the | ||
49 | base name of the "init script". | ||
50 | 46 | ||
51 | status | 47 | status |
52 | Report the current status of the service, and the appendant log service | 48 | Report the current status of the service, and the appendant log service |
@@ -66,9 +62,9 @@ exit | |||
66 | If the service is running, send it the TERM signal, and the CONT signal. | 62 | If the service is running, send it the TERM signal, and the CONT signal. |
67 | Do not restart the service. If the service is down, and no log service | 63 | Do not restart the service. If the service is down, and no log service |
68 | exists, runsv(8) exits. If the service is down and a log service exists, | 64 | exists, runsv(8) exits. If the service is down and a log service exists, |
69 | send the TERM signal to the log service. If the log service is down, | 65 | runsv(8) closes the standard input of the log service and waits for it to |
70 | runsv(8) exits. This command is ignored if it is given to an appendant | 66 | terminate. If the log service is down, runsv(8) exits. This command is |
71 | log service. | 67 | ignored if it is given to an appendant log service. |
72 | 68 | ||
73 | sv actually looks only at the first character of above commands. | 69 | sv actually looks only at the first character of above commands. |
74 | 70 | ||
@@ -85,6 +81,8 @@ start | |||
85 | stop | 81 | stop |
86 | Same as down, but wait up to 7 seconds for the service to become down. | 82 | Same as down, but wait up to 7 seconds for the service to become down. |
87 | Then report the status or timeout. | 83 | Then report the status or timeout. |
84 | reload | ||
85 | Same as hup, and additionally report the status afterwards. | ||
88 | restart | 86 | restart |
89 | Send the commands term, cont, and up to the service, and wait up to | 87 | Send the commands term, cont, and up to the service, and wait up to |
90 | 7 seconds for the service to restart. Then report the status or timeout. | 88 | 7 seconds for the service to restart. Then report the status or timeout. |
@@ -112,6 +110,9 @@ force-shutdown | |||
112 | Same as exit, but wait up to 7 seconds for the runsv(8) process to | 110 | Same as exit, but wait up to 7 seconds for the runsv(8) process to |
113 | terminate. Then report the status, and on timeout send the service | 111 | terminate. Then report the status, and on timeout send the service |
114 | the kill command. | 112 | the kill command. |
113 | try-restart | ||
114 | if the service is running, send it the term and cont commands, and wait up to | ||
115 | 7 seconds for the service to restart. Then report the status or timeout. | ||
115 | 116 | ||
116 | Additional Commands | 117 | Additional Commands |
117 | 118 | ||
@@ -126,8 +127,8 @@ check | |||
126 | Options | 127 | Options |
127 | 128 | ||
128 | -v | 129 | -v |
129 | wait up to 7 seconds for the command to take effect. | 130 | If the command is up, down, term, once, cont, or exit, then wait up to 7 |
130 | Then report the status or timeout. | 131 | seconds for the command to take effect. Then report the status or timeout. |
131 | -w sec | 132 | -w sec |
132 | Override the default timeout of 7 seconds with sec seconds. Implies -v. | 133 | Override the default timeout of 7 seconds with sec seconds. Implies -v. |
133 | 134 | ||
@@ -192,6 +193,7 @@ struct globals { | |||
192 | /* "Bernstein" time format: unix + 0x400000000000000aULL */ | 193 | /* "Bernstein" time format: unix + 0x400000000000000aULL */ |
193 | uint64_t tstart, tnow; | 194 | uint64_t tstart, tnow; |
194 | svstatus_t svstatus; | 195 | svstatus_t svstatus; |
196 | unsigned islog; | ||
195 | } FIX_ALIASING; | 197 | } FIX_ALIASING; |
196 | #define G (*(struct globals*)bb_common_bufsiz1) | 198 | #define G (*(struct globals*)bb_common_bufsiz1) |
197 | #define acts (G.acts ) | 199 | #define acts (G.acts ) |
@@ -200,6 +202,7 @@ struct globals { | |||
200 | #define tstart (G.tstart ) | 202 | #define tstart (G.tstart ) |
201 | #define tnow (G.tnow ) | 203 | #define tnow (G.tnow ) |
202 | #define svstatus (G.svstatus ) | 204 | #define svstatus (G.svstatus ) |
205 | #define islog (G.islog ) | ||
203 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 206 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
204 | 207 | ||
205 | 208 | ||
@@ -215,7 +218,7 @@ static void fatal_cannot(const char *m1) | |||
215 | 218 | ||
216 | static void out(const char *p, const char *m1) | 219 | static void out(const char *p, const char *m1) |
217 | { | 220 | { |
218 | printf("%s%s: %s", p, *service, m1); | 221 | printf("%s%s%s: %s", p, *service, islog ? "/log" : "", m1); |
219 | if (errno) { | 222 | if (errno) { |
220 | printf(": %s", strerror(errno)); | 223 | printf(": %s", strerror(errno)); |
221 | } | 224 | } |
@@ -300,15 +303,14 @@ static unsigned svstatus_print(const char *m) | |||
300 | } | 303 | } |
301 | pid = SWAP_LE32(svstatus.pid_le32); | 304 | pid = SWAP_LE32(svstatus.pid_le32); |
302 | timestamp = SWAP_BE64(svstatus.time_be64); | 305 | timestamp = SWAP_BE64(svstatus.time_be64); |
303 | if (pid) { | 306 | switch (svstatus.run_or_finish) { |
304 | switch (svstatus.run_or_finish) { | 307 | case 0: printf("down: "); break; |
305 | case 1: printf("run: "); break; | 308 | case 1: printf("run: "); break; |
306 | case 2: printf("finish: "); break; | 309 | case 2: printf("finish: "); break; |
307 | } | ||
308 | printf("%s: (pid %d) ", m, pid); | ||
309 | } else { | ||
310 | printf("down: %s: ", m); | ||
311 | } | 310 | } |
311 | printf("%s: ", m); | ||
312 | if (svstatus.run_or_finish) | ||
313 | printf("(pid %d) ", pid); | ||
312 | diff = tnow - timestamp; | 314 | diff = tnow - timestamp; |
313 | printf("%us", (diff < 0 ? 0 : diff)); | 315 | printf("%us", (diff < 0 ? 0 : diff)); |
314 | if (pid) { | 316 | if (pid) { |
@@ -331,16 +333,21 @@ static int status(const char *unused UNUSED_PARAM) | |||
331 | return 0; | 333 | return 0; |
332 | 334 | ||
333 | r = svstatus_print(*service); | 335 | r = svstatus_print(*service); |
336 | islog = 1; | ||
334 | if (chdir("log") == -1) { | 337 | if (chdir("log") == -1) { |
335 | if (errno != ENOENT) { | 338 | if (errno != ENOENT) { |
336 | printf("; log: "WARN"can't change to log service directory: %s", | 339 | printf("; "); |
337 | strerror(errno)); | 340 | warn("can't change directory"); |
338 | } | 341 | } else |
339 | } else if (svstatus_get()) { | 342 | bb_putchar('\n'); |
343 | } else { | ||
340 | printf("; "); | 344 | printf("; "); |
341 | svstatus_print("log"); | 345 | if (svstatus_get()) { |
346 | r = svstatus_print("log"); | ||
347 | bb_putchar('\n'); | ||
348 | } | ||
342 | } | 349 | } |
343 | bb_putchar('\n'); /* will also flush the output */ | 350 | islog = 0; |
344 | return r; | 351 | return r; |
345 | } | 352 | } |
346 | 353 | ||
@@ -379,35 +386,53 @@ static int check(const char *a) | |||
379 | r = svstatus_get(); | 386 | r = svstatus_get(); |
380 | if (r == -1) | 387 | if (r == -1) |
381 | return -1; | 388 | return -1; |
382 | if (r == 0) { | 389 | while (*a) { |
383 | if (*a == 'x') | 390 | if (r == 0) { |
384 | return 1; | 391 | if (*a == 'x') |
385 | return -1; | 392 | return 1; |
386 | } | 393 | return -1; |
387 | pid_le32 = svstatus.pid_le32; | 394 | } |
388 | switch (*a) { | 395 | pid_le32 = svstatus.pid_le32; |
389 | case 'x': | 396 | switch (*a) { |
390 | return 0; | 397 | case 'x': |
391 | case 'u': | ||
392 | if (!pid_le32 || svstatus.run_or_finish != 1) return 0; | ||
393 | if (!checkscript()) return 0; | ||
394 | break; | ||
395 | case 'd': | ||
396 | if (pid_le32) return 0; | ||
397 | break; | ||
398 | case 'c': | ||
399 | if (pid_le32 && !checkscript()) return 0; | ||
400 | break; | ||
401 | case 't': | ||
402 | if (!pid_le32 && svstatus.want == 'd') break; | ||
403 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
404 | if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) | ||
405 | return 0; | ||
406 | break; | ||
407 | case 'o': | ||
408 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
409 | if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) | ||
410 | return 0; | 398 | return 0; |
399 | case 'u': | ||
400 | if (!pid_le32 || svstatus.run_or_finish != 1) | ||
401 | return 0; | ||
402 | if (!checkscript()) | ||
403 | return 0; | ||
404 | break; | ||
405 | case 'd': | ||
406 | if (pid_le32 || svstatus.run_or_finish != 0) | ||
407 | return 0; | ||
408 | break; | ||
409 | case 'C': | ||
410 | if (pid_le32 && !checkscript()) | ||
411 | return 0; | ||
412 | break; | ||
413 | case 't': | ||
414 | case 'k': | ||
415 | if (!pid_le32 && svstatus.want == 'd') | ||
416 | break; | ||
417 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
418 | if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) | ||
419 | return 0; | ||
420 | break; | ||
421 | case 'o': | ||
422 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
423 | if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) | ||
424 | return 0; | ||
425 | break; | ||
426 | case 'p': | ||
427 | if (pid_le32 && !svstatus.paused) | ||
428 | return 0; | ||
429 | break; | ||
430 | case 'c': | ||
431 | if (pid_le32 && svstatus.paused) | ||
432 | return 0; | ||
433 | break; | ||
434 | } | ||
435 | ++a; | ||
411 | } | 436 | } |
412 | printf(OK); | 437 | printf(OK); |
413 | svstatus_print(*service); | 438 | svstatus_print(*service); |
@@ -419,14 +444,10 @@ static int control(const char *a) | |||
419 | { | 444 | { |
420 | int fd, r, l; | 445 | int fd, r, l; |
421 | 446 | ||
422 | /* Is it an optimization? | ||
423 | It causes problems with "sv o SRV; ...; sv d SRV" | ||
424 | ('d' is not passed to SRV because its .want == 'd'): | ||
425 | if (svstatus_get() <= 0) | 447 | if (svstatus_get() <= 0) |
426 | return -1; | 448 | return -1; |
427 | if (svstatus.want == *a) | 449 | if (svstatus.want == *a && (*a != 'd' || svstatus.got_term == 1)) |
428 | return 0; | 450 | return 0; |
429 | */ | ||
430 | fd = open("supervise/control", O_WRONLY|O_NDELAY); | 451 | fd = open("supervise/control", O_WRONLY|O_NDELAY); |
431 | if (fd == -1) { | 452 | if (fd == -1) { |
432 | if (errno != ENODEV) | 453 | if (errno != ENODEV) |
@@ -516,17 +537,23 @@ static int sv(char **argv) | |||
516 | acts = "tc"; | 537 | acts = "tc"; |
517 | kll = 1; | 538 | kll = 1; |
518 | break; | 539 | break; |
540 | case 't': | ||
541 | if (str_equal(action, "try-restart")) { | ||
542 | acts = "tc"; | ||
543 | break; | ||
544 | } | ||
519 | case 'c': | 545 | case 'c': |
520 | if (str_equal(action, "check")) { | 546 | if (str_equal(action, "check")) { |
521 | act = NULL; | 547 | act = NULL; |
522 | acts = "c"; | 548 | acts = "C"; |
523 | break; | 549 | break; |
524 | } | 550 | } |
525 | case 'u': case 'd': case 'o': case 't': case 'p': case 'h': | 551 | case 'u': case 'd': case 'o': case 'p': case 'h': |
526 | case 'a': case 'i': case 'k': case 'q': case '1': case '2': | 552 | case 'a': case 'i': case 'k': case 'q': case '1': case '2': |
527 | action[1] = '\0'; | 553 | action[1] = '\0'; |
528 | acts = action; | 554 | acts = action; |
529 | if (!verbose) cbk = NULL; | 555 | if (!verbose) |
556 | cbk = NULL; | ||
530 | break; | 557 | break; |
531 | case 's': | 558 | case 's': |
532 | if (str_equal(action, "shutdown")) { | 559 | if (str_equal(action, "shutdown")) { |
@@ -550,6 +577,10 @@ static int sv(char **argv) | |||
550 | acts = "tcu"; | 577 | acts = "tcu"; |
551 | break; | 578 | break; |
552 | } | 579 | } |
580 | if (str_equal(action, "reload")) { | ||
581 | acts = "h"; | ||
582 | break; | ||
583 | } | ||
553 | bb_show_usage(); | 584 | bb_show_usage(); |
554 | case 'f': | 585 | case 'f': |
555 | if (str_equal(action, "force-reload")) { | 586 | if (str_equal(action, "force-reload")) { |
@@ -578,7 +609,9 @@ static int sv(char **argv) | |||
578 | 609 | ||
579 | service = argv; | 610 | service = argv; |
580 | while ((x = *service) != NULL) { | 611 | while ((x = *service) != NULL) { |
581 | if (x[0] != '/' && x[0] != '.') { | 612 | if (x[0] != '/' && x[0] != '.' |
613 | && x[0] != '\0' && x[strlen(x) - 1] != '/' | ||
614 | ) { | ||
582 | if (chdir(varservice) == -1) | 615 | if (chdir(varservice) == -1) |
583 | goto chdir_failed_0; | 616 | goto chdir_failed_0; |
584 | } | 617 | } |
@@ -688,12 +721,7 @@ int svc_main(int argc UNUSED_PARAM, char **argv) | |||
688 | /* getopt32() was already called: | 721 | /* getopt32() was already called: |
689 | * reset the libc getopt() function, which keeps internal state. | 722 | * reset the libc getopt() function, which keeps internal state. |
690 | */ | 723 | */ |
691 | #ifdef __GLIBC__ | 724 | GETOPT_RESET(); |
692 | optind = 0; | ||
693 | #else /* BSD style */ | ||
694 | optind = 1; | ||
695 | /* optreset = 1; */ | ||
696 | #endif | ||
697 | 725 | ||
698 | do { | 726 | do { |
699 | if (opts & 1) { | 727 | if (opts & 1) { |
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 | |||
137 | //kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o | 137 | //kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o |
138 | 138 | ||
139 | //usage:#define svlogd_trivial_usage | 139 | //usage:#define svlogd_trivial_usage |
140 | //usage: "[-ttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..." | 140 | //usage: "[-tttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..." |
141 | //usage:#define svlogd_full_usage "\n\n" | 141 | //usage:#define svlogd_full_usage "\n\n" |
142 | //usage: "Continuously read log data from stdin and write to rotated log files in DIRs" | 142 | //usage: "Read log data from stdin and write to rotated log files in DIRs" |
143 | //usage: "\n" | 143 | //usage: "\n" |
144 | //usage: "\n""DIR/config file modifies behavior:" | 144 | //usage: "\n""DIR/config file modifies behavior:" |
145 | //usage: "\n""sSIZE - when to rotate logs" | 145 | //usage: "\n""sSIZE - when to rotate logs" |
@@ -339,17 +339,18 @@ static unsigned pmatch(const char *p, const char *s, unsigned len) | |||
339 | /*** ex fmt_ptime.[ch] ***/ | 339 | /*** ex fmt_ptime.[ch] ***/ |
340 | 340 | ||
341 | /* NUL terminated */ | 341 | /* NUL terminated */ |
342 | static void fmt_time_human_30nul(char *s) | 342 | static void fmt_time_human_30nul(char *s, char dt_delim) |
343 | { | 343 | { |
344 | struct tm *ptm; | 344 | struct tm *ptm; |
345 | struct timeval tv; | 345 | struct timeval tv; |
346 | 346 | ||
347 | gettimeofday(&tv, NULL); | 347 | gettimeofday(&tv, NULL); |
348 | ptm = gmtime(&tv.tv_sec); | 348 | ptm = gmtime(&tv.tv_sec); |
349 | sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000", | 349 | sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", |
350 | (unsigned)(1900 + ptm->tm_year), | 350 | (unsigned)(1900 + ptm->tm_year), |
351 | (unsigned)(ptm->tm_mon + 1), | 351 | (unsigned)(ptm->tm_mon + 1), |
352 | (unsigned)(ptm->tm_mday), | 352 | (unsigned)(ptm->tm_mday), |
353 | dt_delim, | ||
353 | (unsigned)(ptm->tm_hour), | 354 | (unsigned)(ptm->tm_hour), |
354 | (unsigned)(ptm->tm_min), | 355 | (unsigned)(ptm->tm_min), |
355 | (unsigned)(ptm->tm_sec), | 356 | (unsigned)(ptm->tm_sec), |
@@ -1160,8 +1161,8 @@ int svlogd_main(int argc, char **argv) | |||
1160 | if (timestamp) { | 1161 | if (timestamp) { |
1161 | if (timestamp == 1) | 1162 | if (timestamp == 1) |
1162 | fmt_time_bernstein_25(stamp); | 1163 | fmt_time_bernstein_25(stamp); |
1163 | else /* 2: */ | 1164 | else /* 2+: */ |
1164 | fmt_time_human_30nul(stamp); | 1165 | fmt_time_human_30nul(stamp, timestamp == 2 ? '_' : 'T'); |
1165 | printlen += 26; | 1166 | printlen += 26; |
1166 | printptr -= 26; | 1167 | printptr -= 26; |
1167 | memcpy(printptr, stamp, 25); | 1168 | memcpy(printptr, stamp, 25); |