|
Lines 69-74
static void restrict_process(const char *);
Link Here
|
| 69 |
static void handle_term(int); |
69 |
static void handle_term(int); |
| 70 |
static void handle_chld(int); |
70 |
static void handle_chld(int); |
| 71 |
static void handle_hup(int); |
71 |
static void handle_hup(int); |
|
|
72 |
static void handle_alarm(int); |
| 72 |
static int open_log(const char *); |
73 |
static int open_log(const char *); |
| 73 |
static void reopen_log(struct log_params *); |
74 |
static void reopen_log(struct log_params *); |
| 74 |
static int listen_child(int, struct log_params *); |
75 |
static int listen_child(int, struct log_params *); |
|
Lines 86-92
int
Link Here
|
| 86 |
main(int argc, char *argv[]) |
87 |
main(int argc, char *argv[]) |
| 87 |
{ |
88 |
{ |
| 88 |
const char *pidfile, *ppidfile, *title, *user, *outfn, *logtag; |
89 |
const char *pidfile, *ppidfile, *title, *user, *outfn, *logtag; |
| 89 |
int ch, nochdir, noclose, restart, dosyslog, child_eof; |
90 |
int ch, nochdir, noclose, restart, dosyslog, child_eof, delay; |
| 90 |
sigset_t mask_susp, mask_orig, mask_read, mask_term; |
91 |
sigset_t mask_susp, mask_orig, mask_read, mask_term; |
| 91 |
struct log_params logpar; |
92 |
struct log_params logpar; |
| 92 |
int pfd[2] = { -1, -1 }, outfd = -1; |
93 |
int pfd[2] = { -1, -1 }, outfd = -1; |
|
Lines 104-112
main(int argc, char *argv[])
Link Here
|
| 104 |
restart = 0; |
105 |
restart = 0; |
| 105 |
dosyslog = 0; |
106 |
dosyslog = 0; |
| 106 |
log_reopen = 0; |
107 |
log_reopen = 0; |
|
|
108 |
delay = 0; |
| 107 |
outfn = NULL; |
109 |
outfn = NULL; |
| 108 |
title = NULL; |
110 |
title = NULL; |
| 109 |
while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) { |
111 |
while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:d:")) != -1) { |
| 110 |
switch (ch) { |
112 |
switch (ch) { |
| 111 |
case 'c': |
113 |
case 'c': |
| 112 |
nochdir = 0; |
114 |
nochdir = 0; |
|
Lines 164-169
main(int argc, char *argv[])
Link Here
|
| 164 |
case 'u': |
166 |
case 'u': |
| 165 |
user = optarg; |
167 |
user = optarg; |
| 166 |
break; |
168 |
break; |
|
|
169 |
case 'd': |
| 170 |
delay = strtol(optarg, &p, 0); |
| 171 |
if (p == optarg || delay < 0) |
| 172 |
errx(6, "invalid shutdown delay"); |
| 173 |
break; |
| 167 |
default: |
174 |
default: |
| 168 |
usage(); |
175 |
usage(); |
| 169 |
} |
176 |
} |
|
Lines 210-216
main(int argc, char *argv[])
Link Here
|
| 210 |
* and syslog. |
217 |
* and syslog. |
| 211 |
*/ |
218 |
*/ |
| 212 |
pid = -1; |
219 |
pid = -1; |
| 213 |
if (pidfile || ppidfile || restart || outfd != -1 || dosyslog) { |
220 |
if (pidfile || ppidfile || restart || outfd != -1 || dosyslog || delay) { |
| 214 |
struct sigaction act_term, act_chld, act_hup; |
221 |
struct sigaction act_term, act_chld, act_hup; |
| 215 |
|
222 |
|
| 216 |
/* Avoid PID racing with SIGCHLD and SIGTERM. */ |
223 |
/* Avoid PID racing with SIGCHLD and SIGTERM. */ |
|
Lines 355-361
main(int argc, char *argv[])
Link Here
|
| 355 |
if (child_gone && child_eof) { |
362 |
if (child_gone && child_eof) { |
| 356 |
break; |
363 |
break; |
| 357 |
} else if (terminate) { |
364 |
} else if (terminate) { |
| 358 |
goto exit; |
365 |
goto cleanup; |
| 359 |
} else if (!child_eof) { |
366 |
} else if (!child_eof) { |
| 360 |
if (sigprocmask(SIG_BLOCK, &mask_read, NULL)) { |
367 |
if (sigprocmask(SIG_BLOCK, &mask_read, NULL)) { |
| 361 |
warn("sigprocmask"); |
368 |
warn("sigprocmask"); |
|
Lines 390-395
main(int argc, char *argv[])
Link Here
|
| 390 |
pfd[0] = -1; |
397 |
pfd[0] = -1; |
| 391 |
goto restart; |
398 |
goto restart; |
| 392 |
} |
399 |
} |
|
|
400 |
|
| 401 |
cleanup: |
| 402 |
/* |
| 403 |
* If shutdown delay is set and the child process is still running |
| 404 |
* wait for up to delay seconds for it to exit. While we wait try and |
| 405 |
* output any last messages from the process. If we get to the |
| 406 |
* elapsed time send sigkill to the child process. At that point we |
| 407 |
* should get a SIGCHLD signal to set child_gone and we break out of |
| 408 |
* our read loop. |
| 409 |
*/ |
| 410 |
if (!child_gone && delay) { |
| 411 |
struct sigaction act_alarm; |
| 412 |
memset(&act_alarm, 0, sizeof(act_alarm)); |
| 413 |
act_alarm.sa_handler = handle_alarm; |
| 414 |
sigemptyset(&act_alarm.sa_mask); |
| 415 |
/* Don't want to race with SIGCHLD handler setting child_gone */ |
| 416 |
sigaddset(&act_alarm.sa_mask, SIGCHLD); |
| 417 |
|
| 418 |
if (sigaction(SIGALRM, &act_alarm, NULL) == -1) { |
| 419 |
warn("sigaction"); |
| 420 |
goto exit; |
| 421 |
} |
| 422 |
alarm(delay); |
| 423 |
while (!child_eof) { |
| 424 |
child_eof = !listen_child(pfd[0], &logpar); |
| 425 |
} |
| 426 |
/* Block SIGCHLD while we test if child is gone */ |
| 427 |
if (sigprocmask(SIG_BLOCK, &mask_susp, &mask_orig)) { |
| 428 |
warn("sigprocmask"); |
| 429 |
goto exit; |
| 430 |
} |
| 431 |
while(!child_gone) { |
| 432 |
sigsuspend(&mask_orig); |
| 433 |
} |
| 434 |
alarm(0); |
| 435 |
} |
| 393 |
exit: |
436 |
exit: |
| 394 |
close(outfd); |
437 |
close(outfd); |
| 395 |
close(pfd[0]); |
438 |
close(pfd[0]); |
|
Lines 556-561
do_output(const unsigned char *buf, size_t len, struct log_params *logpar)
Link Here
|
| 556 |
printf("%.*s", (int)len, buf); |
599 |
printf("%.*s", (int)len, buf); |
| 557 |
} |
600 |
} |
| 558 |
|
601 |
|
|
|
602 |
static void |
| 603 |
handle_alarm(int signo __unused) |
| 604 |
{ |
| 605 |
if (pid > 0 && !child_gone) { |
| 606 |
kill(pid, SIGKILL); |
| 607 |
} |
| 608 |
} |
| 609 |
|
| 559 |
/* |
610 |
/* |
| 560 |
* We use the global PID acquired directly from fork. If there is no valid |
611 |
* We use the global PID acquired directly from fork. If there is no valid |
| 561 |
* child pid, the handler should be blocked and/or child_gone == 1. |
612 |
* child pid, the handler should be blocked and/or child_gone == 1. |
|
Lines 615-621
usage(void)
Link Here
|
| 615 |
{ |
666 |
{ |
| 616 |
(void)fprintf(stderr, |
667 |
(void)fprintf(stderr, |
| 617 |
"usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n" |
668 |
"usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n" |
| 618 |
" [-u user] [-o output_file] [-t title]\n" |
669 |
" [-u user] [-o output_file] [-t title] [-d shutdown_delay]\n" |
| 619 |
" [-l syslog_facility] [-s syslog_priority]\n" |
670 |
" [-l syslog_facility] [-s syslog_priority]\n" |
| 620 |
" [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n" |
671 |
" [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n" |
| 621 |
"command arguments ...\n"); |
672 |
"command arguments ...\n"); |