1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1999 Berkeley Software Design, Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Berkeley Software Design Inc's name may not be used to endorse or 15 * promote products derived from this software without specific prior 16 * written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * From BSDI: daemon.c,v 1.2 1996/08/15 01:11:09 jch Exp 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/mman.h> 38 #include <sys/wait.h> 39 40 #include <fcntl.h> 41 #include <err.h> 42 #include <errno.h> 43 #include <getopt.h> 44 #include <libutil.h> 45 #include <login_cap.h> 46 #include <paths.h> 47 #include <pwd.h> 48 #include <signal.h> 49 #include <stdio.h> 50 #include <stdbool.h> 51 #include <stdlib.h> 52 #include <unistd.h> 53 #include <string.h> 54 #include <strings.h> 55 #define SYSLOG_NAMES 56 #include <syslog.h> 57 #include <time.h> 58 #include <assert.h> 59 60 #define LBUF_SIZE 4096 61 62 struct daemon_state { 63 int pipe_fd[2]; 64 const char *child_pidfile; 65 const char *parent_pidfile; 66 const char *output_filename; 67 const char *syslog_tag; 68 const char *title; 69 const char *user; 70 struct pidfh *parent_pidfh; 71 struct pidfh *child_pidfh; 72 int keep_cur_workdir; 73 int restart_delay; 74 int stdmask; 75 int syslog_priority; 76 int syslog_facility; 77 int keep_fds_open; 78 int output_fd; 79 bool supervision_enabled; 80 bool child_eof; 81 bool restart_enabled; 82 bool syslog_enabled; 83 bool log_reopen; 84 }; 85 86 static void setup_signals(struct daemon_state *); 87 static void restrict_process(const char *); 88 static void handle_term(int); 89 static void handle_chld(int); 90 static void handle_hup(int); 91 static int open_log(const char *); 92 static void reopen_log(struct daemon_state *); 93 static bool listen_child(int, struct daemon_state *); 94 static int get_log_mapping(const char *, const CODE *); 95 static void open_pid_files(struct daemon_state *); 96 static void do_output(const unsigned char *, size_t, struct daemon_state *); 97 static void daemon_sleep(time_t, long); 98 static void daemon_state_init(struct daemon_state *); 99 static void daemon_terminate(struct daemon_state *); 100 101 static volatile sig_atomic_t terminate = 0; 102 static volatile sig_atomic_t child_gone = 0; 103 static volatile sig_atomic_t pid = 0; 104 static volatile sig_atomic_t do_log_reopen = 0; 105 106 static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:h"; 107 108 static const struct option longopts[] = { 109 { "change-dir", no_argument, NULL, 'c' }, 110 { "close-fds", no_argument, NULL, 'f' }, 111 { "sighup", no_argument, NULL, 'H' }, 112 { "syslog", no_argument, NULL, 'S' }, 113 { "output-file", required_argument, NULL, 'o' }, 114 { "output-mask", required_argument, NULL, 'm' }, 115 { "child-pidfile", required_argument, NULL, 'p' }, 116 { "supervisor-pidfile", required_argument, NULL, 'P' }, 117 { "restart", no_argument, NULL, 'r' }, 118 { "restart-delay", required_argument, NULL, 'R' }, 119 { "title", required_argument, NULL, 't' }, 120 { "user", required_argument, NULL, 'u' }, 121 { "syslog-priority", required_argument, NULL, 's' }, 122 { "syslog-facility", required_argument, NULL, 'l' }, 123 { "syslog-tag", required_argument, NULL, 'T' }, 124 { "help", no_argument, NULL, 'h' }, 125 { NULL, 0, NULL, 0 } 126 }; 127 128 static _Noreturn void 129 usage(int exitcode) 130 { 131 (void)fprintf(stderr, 132 "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n" 133 " [-u user] [-o output_file] [-t title]\n" 134 " [-l syslog_facility] [-s syslog_priority]\n" 135 " [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n" 136 "command arguments ...\n"); 137 138 (void)fprintf(stderr, 139 " --change-dir -c Change the current working directory to root\n" 140 " --close-fds -f Set stdin, stdout, stderr to /dev/null\n" 141 " --sighup -H Close and re-open output file on SIGHUP\n" 142 " --syslog -S Send output to syslog\n" 143 " --output-file -o <file> Append output of the child process to file\n" 144 " --output-mask -m <mask> What to send to syslog/file\n" 145 " 1=stdout, 2=stderr, 3=both\n" 146 " --child-pidfile -p <file> Write PID of the child process to file\n" 147 " --supervisor-pidfile -P <file> Write PID of the supervisor process to file\n" 148 " --restart -r Restart child if it terminates (1 sec delay)\n" 149 " --restart-delay -R <N> Restart child if it terminates after N sec\n" 150 " --title -t <title> Set the title of the supervisor process\n" 151 " --user -u <user> Drop privileges, run as given user\n" 152 " --syslog-priority -s <prio> Set syslog priority\n" 153 " --syslog-facility -l <flty> Set syslog facility\n" 154 " --syslog-tag -T <tag> Set syslog tag\n" 155 " --help -h Show this help\n"); 156 157 exit(exitcode); 158 } 159 160 int 161 main(int argc, char *argv[]) 162 { 163 char *p = NULL; 164 int ch = 0; 165 struct daemon_state state; 166 sigset_t mask_orig; 167 sigset_t mask_read; 168 sigset_t mask_term; 169 sigset_t mask_susp; 170 171 daemon_state_init(&state); 172 173 /* 174 * Signal handling logic: 175 * 176 * - SIGTERM is masked while there is no child. 177 * 178 * - SIGCHLD is masked while reading from the pipe. SIGTERM has to be 179 * caught, to avoid indefinite blocking on read(). 180 * 181 * - Both SIGCHLD and SIGTERM are masked before calling sigsuspend() 182 * to avoid racing. 183 * 184 * - After SIGTERM is recieved and propagated to the child there are 185 * several options on what to do next: 186 * - read until EOF 187 * - read until EOF but only for a while 188 * - bail immediately 189 * Currently the third option is used, because otherwise there is no 190 * guarantee that read() won't block indefinitely if the child refuses 191 * to depart. To handle the second option, a different approach 192 * would be needed (procctl()?). 193 * 194 * - Child's exit might be detected by receiveing EOF from the pipe. 195 * But the child might have closed its stdout and stderr, so deamon 196 * must wait for the SIGCHLD to ensure that the child is actually gone. 197 */ 198 sigemptyset(&mask_susp); 199 sigemptyset(&mask_read); 200 sigemptyset(&mask_term); 201 sigemptyset(&mask_orig); 202 sigaddset(&mask_susp, SIGTERM); 203 sigaddset(&mask_susp, SIGCHLD); 204 sigaddset(&mask_term, SIGTERM); 205 sigaddset(&mask_read, SIGCHLD); 206 207 /* 208 * Supervision mode is enabled if one of the following options are used: 209 * --child-pidfile -p 210 * --supervisor-pidfile -P 211 * --restart -r / --restart-delay -R 212 * --syslog -S 213 * --syslog-facility -l 214 * --syslog-priority -s 215 * --syslog-tag -T 216 * 217 * In supervision mode daemon executes the command in a forked process 218 * and observes the child by waiting for SIGCHILD. In supervision mode 219 * daemon must never exit before the child, this is necessary to prevent 220 * orphaning the child and leaving a stale pid file. 221 * To achieve this daemon catches SIGTERM and 222 * forwards it to the child, expecting to get SIGCHLD eventually. 223 */ 224 while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { 225 switch (ch) { 226 case 'c': 227 state.keep_cur_workdir = 0; 228 break; 229 case 'f': 230 state.keep_fds_open = 0; 231 break; 232 case 'H': 233 state.log_reopen = true; 234 break; 235 case 'l': 236 state.syslog_facility = get_log_mapping(optarg, 237 facilitynames); 238 if (state.syslog_facility == -1) { 239 errx(5, "unrecognized syslog facility"); 240 } 241 state.syslog_enabled = true; 242 state.supervision_enabled = true; 243 break; 244 case 'm': 245 state.stdmask = strtol(optarg, &p, 10); 246 if (p == optarg || state.stdmask < 0 || state.stdmask > 3) { 247 errx(6, "unrecognized listening mask"); 248 } 249 break; 250 case 'o': 251 state.output_filename = optarg; 252 /* 253 * TODO: setting output filename doesn't have to turn 254 * the supervision mode on. For non-supervised mode 255 * daemon could open the specified file and set it's 256 * descriptor as both stderr and stout before execve() 257 */ 258 state.supervision_enabled = true; 259 break; 260 case 'p': 261 state.child_pidfile = optarg; 262 state.supervision_enabled = true; 263 break; 264 case 'P': 265 state.parent_pidfile = optarg; 266 state.supervision_enabled = true; 267 break; 268 case 'r': 269 state.restart_enabled = true; 270 state.supervision_enabled = true; 271 break; 272 case 'R': 273 state.restart_enabled = true; 274 state.restart_delay = strtol(optarg, &p, 0); 275 if (p == optarg || state.restart_delay < 1) { 276 errx(6, "invalid restart delay"); 277 } 278 break; 279 case 's': 280 state.syslog_priority = get_log_mapping(optarg, 281 prioritynames); 282 if (state.syslog_priority == -1) { 283 errx(4, "unrecognized syslog priority"); 284 } 285 state.syslog_enabled = true; 286 state.supervision_enabled = true; 287 break; 288 case 'S': 289 state.syslog_enabled = true; 290 state.supervision_enabled = true; 291 break; 292 case 't': 293 state.title = optarg; 294 break; 295 case 'T': 296 state.syslog_tag = optarg; 297 state.syslog_enabled = true; 298 state.supervision_enabled = true; 299 break; 300 case 'u': 301 state.user = optarg; 302 break; 303 case 'h': 304 usage(0); 305 __builtin_unreachable(); 306 default: 307 usage(1); 308 } 309 } 310 argc -= optind; 311 argv += optind; 312 313 if (argc == 0) { 314 usage(1); 315 } 316 317 if (!state.title) { 318 state.title = argv[0]; 319 } 320 321 if (state.output_filename) { 322 state.output_fd = open_log(state.output_filename); 323 if (state.output_fd == -1) { 324 err(7, "open"); 325 } 326 } 327 328 if (state.syslog_enabled) { 329 openlog(state.syslog_tag, LOG_PID | LOG_NDELAY, 330 state.syslog_facility); 331 } 332 333 /* 334 * Try to open the pidfile before calling daemon(3), 335 * to be able to report the error intelligently 336 */ 337 open_pid_files(&state); 338 if (daemon(state.keep_cur_workdir, state.keep_fds_open) == -1) { 339 warn("daemon"); 340 daemon_terminate(&state); 341 } 342 /* Write out parent pidfile if needed. */ 343 pidfile_write(state.parent_pidfh); 344 345 if (state.supervision_enabled) { 346 /* Block SIGTERM to avoid racing until we have forked. */ 347 if (sigprocmask(SIG_BLOCK, &mask_term, &mask_orig)) { 348 warn("sigprocmask"); 349 daemon_terminate(&state); 350 } 351 352 setup_signals(&state); 353 354 /* 355 * Try to protect against pageout kill. Ignore the 356 * error, madvise(2) will fail only if a process does 357 * not have superuser privileges. 358 */ 359 (void)madvise(NULL, 0, MADV_PROTECT); 360 restart: 361 if (pipe(state.pipe_fd)) { 362 err(1, "pipe"); 363 } 364 /* 365 * Spawn a child to exec the command. 366 */ 367 child_gone = 0; 368 pid = fork(); 369 } 370 371 /* fork failed, this can only happen when supervision is enabled */ 372 if (pid == -1) { 373 warn("fork"); 374 daemon_terminate(&state); 375 } 376 377 /* fork succeeded, this is child's branch or supervision is disabled */ 378 if (pid == 0) { 379 pidfile_write(state.child_pidfh); 380 381 if (state.user != NULL) { 382 restrict_process(state.user); 383 } 384 /* 385 * In supervision mode, the child gets the original sigmask, 386 * and dup'd pipes. 387 */ 388 if (state.supervision_enabled) { 389 close(state.pipe_fd[0]); 390 if (sigprocmask(SIG_SETMASK, &mask_orig, NULL)) { 391 err(1, "sigprogmask"); 392 } 393 if (state.stdmask & STDERR_FILENO) { 394 if (dup2(state.pipe_fd[1], STDERR_FILENO) == -1) { 395 err(1, "dup2"); 396 } 397 } 398 if (state.stdmask & STDOUT_FILENO) { 399 if (dup2(state.pipe_fd[1], STDOUT_FILENO) == -1) { 400 err(1, "dup2"); 401 } 402 } 403 if (state.pipe_fd[1] != STDERR_FILENO && 404 state.pipe_fd[1] != STDOUT_FILENO) { 405 close(state.pipe_fd[1]); 406 } 407 } 408 execvp(argv[0], argv); 409 /* execvp() failed - report error and exit this process */ 410 err(1, "%s", argv[0]); 411 } 412 413 /* 414 * else: pid > 0 415 * fork succeeded, this is the parent branch, this can only happen when 416 * supervision is enabled. 417 * 418 * Unblock SIGTERM - now there is a valid child PID to signal to. 419 */ 420 if (sigprocmask(SIG_UNBLOCK, &mask_term, NULL)) { 421 warn("sigprocmask"); 422 daemon_terminate(&state); 423 } 424 close(state.pipe_fd[1]); 425 state.pipe_fd[1] = -1; 426 427 setproctitle("%s[%d]", state.title, (int)pid); 428 for (;;) { 429 if (child_gone && state.child_eof) { 430 break; 431 } 432 433 if (terminate) { 434 daemon_terminate(&state); 435 } 436 437 if (state.child_eof) { 438 if (sigprocmask(SIG_BLOCK, &mask_susp, NULL)) { 439 warn("sigprocmask"); 440 daemon_terminate(&state); 441 } 442 while (!terminate && !child_gone) { 443 sigsuspend(&mask_orig); 444 } 445 if (sigprocmask(SIG_UNBLOCK, &mask_susp, NULL)) { 446 warn("sigprocmask"); 447 daemon_terminate(&state); 448 } 449 continue; 450 } 451 452 if (sigprocmask(SIG_BLOCK, &mask_read, NULL)) { 453 warn("sigprocmask"); 454 daemon_terminate(&state); 455 } 456 457 state.child_eof = !listen_child(state.pipe_fd[0], &state); 458 459 if (sigprocmask(SIG_UNBLOCK, &mask_read, NULL)) { 460 warn("sigprocmask"); 461 daemon_terminate(&state); 462 } 463 464 } 465 if (state.restart_enabled && !terminate) { 466 daemon_sleep(state.restart_delay, 0); 467 } 468 if (sigprocmask(SIG_BLOCK, &mask_term, NULL)) { 469 warn("sigprocmask"); 470 daemon_terminate(&state); 471 } 472 if (state.restart_enabled && !terminate) { 473 close(state.pipe_fd[0]); 474 state.pipe_fd[0] = -1; 475 goto restart; 476 } 477 daemon_terminate(&state); 478 } 479 480 static void 481 daemon_sleep(time_t secs, long nsecs) 482 { 483 struct timespec ts = { secs, nsecs }; 484 485 while (!terminate && nanosleep(&ts, &ts) == -1) { 486 if (errno != EINTR) { 487 err(1, "nanosleep"); 488 } 489 } 490 } 491 492 /* 493 * Setup SIGTERM, SIGCHLD and SIGHUP handlers. 494 * To avoid racing SIGCHLD with SIGTERM corresponding 495 * signal handlers mask the other signal. 496 */ 497 static void 498 setup_signals(struct daemon_state *state) 499 { 500 struct sigaction act_term = { 0 }; 501 struct sigaction act_chld = { 0 }; 502 struct sigaction act_hup = { 0 }; 503 504 /* Setup SIGTERM */ 505 act_term.sa_handler = handle_term; 506 sigemptyset(&act_term.sa_mask); 507 sigaddset(&act_term.sa_mask, SIGCHLD); 508 if (sigaction(SIGTERM, &act_term, NULL) == -1) { 509 warn("sigaction"); 510 daemon_terminate(state); 511 } 512 513 /* Setup SIGCHLD */ 514 act_chld.sa_handler = handle_chld; 515 sigemptyset(&act_chld.sa_mask); 516 sigaddset(&act_chld.sa_mask, SIGTERM); 517 if (sigaction(SIGCHLD, &act_chld, NULL) == -1) { 518 warn("sigaction"); 519 daemon_terminate(state); 520 } 521 522 /* Setup SIGHUP if configured */ 523 if (!state->log_reopen || state->output_fd < 0) { 524 return; 525 } 526 527 act_hup.sa_handler = handle_hup; 528 sigemptyset(&act_hup.sa_mask); 529 if (sigaction(SIGHUP, &act_hup, NULL) == -1) { 530 warn("sigaction"); 531 daemon_terminate(state); 532 } 533 } 534 535 static void 536 open_pid_files(struct daemon_state *state) 537 { 538 pid_t fpid; 539 int serrno; 540 541 if (state->child_pidfile) { 542 state->child_pidfh = pidfile_open(state->child_pidfile, 0600, &fpid); 543 if (state->child_pidfh == NULL) { 544 if (errno == EEXIST) { 545 errx(3, "process already running, pid: %d", 546 fpid); 547 } 548 err(2, "pidfile ``%s''", state->child_pidfile); 549 } 550 } 551 /* Do the same for the actual daemon process. */ 552 if (state->parent_pidfile) { 553 state->parent_pidfh= pidfile_open(state->parent_pidfile, 0600, &fpid); 554 if (state->parent_pidfh == NULL) { 555 serrno = errno; 556 pidfile_remove(state->child_pidfh); 557 errno = serrno; 558 if (errno == EEXIST) { 559 errx(3, "process already running, pid: %d", 560 fpid); 561 } 562 err(2, "ppidfile ``%s''", state->parent_pidfile); 563 } 564 } 565 } 566 567 static int 568 get_log_mapping(const char *str, const CODE *c) 569 { 570 const CODE *cp; 571 for (cp = c; cp->c_name; cp++) 572 if (strcmp(cp->c_name, str) == 0) { 573 return cp->c_val; 574 } 575 return -1; 576 } 577 578 static void 579 restrict_process(const char *user) 580 { 581 struct passwd *pw = NULL; 582 583 pw = getpwnam(user); 584 if (pw == NULL) { 585 errx(1, "unknown user: %s", user); 586 } 587 588 if (setusercontext(NULL, pw, pw->pw_uid, LOGIN_SETALL) != 0) { 589 errx(1, "failed to set user environment"); 590 } 591 592 setenv("USER", pw->pw_name, 1); 593 setenv("HOME", pw->pw_dir, 1); 594 setenv("SHELL", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL, 1); 595 } 596 597 /* 598 * We try to collect whole lines terminated by '\n'. Otherwise we collect a 599 * full buffer, and then output it. 600 * 601 * Return value of false is assumed to mean EOF or error, and true indicates to 602 * continue reading. 603 */ 604 static bool 605 listen_child(int fd, struct daemon_state *state) 606 { 607 static unsigned char buf[LBUF_SIZE]; 608 static size_t bytes_read = 0; 609 int rv; 610 611 assert(state != NULL); 612 assert(bytes_read < LBUF_SIZE - 1); 613 614 if (do_log_reopen) { 615 reopen_log(state); 616 } 617 rv = read(fd, buf + bytes_read, LBUF_SIZE - bytes_read - 1); 618 if (rv > 0) { 619 unsigned char *cp; 620 621 bytes_read += rv; 622 assert(bytes_read <= LBUF_SIZE - 1); 623 /* Always NUL-terminate just in case. */ 624 buf[LBUF_SIZE - 1] = '\0'; 625 /* 626 * Chomp line by line until we run out of buffer. 627 * This does not take NUL characters into account. 628 */ 629 while ((cp = memchr(buf, '\n', bytes_read)) != NULL) { 630 size_t bytes_line = cp - buf + 1; 631 assert(bytes_line <= bytes_read); 632 do_output(buf, bytes_line, state); 633 bytes_read -= bytes_line; 634 memmove(buf, cp + 1, bytes_read); 635 } 636 /* Wait until the buffer is full. */ 637 if (bytes_read < LBUF_SIZE - 1) { 638 return true; 639 } 640 do_output(buf, bytes_read, state); 641 bytes_read = 0; 642 return true; 643 } else if (rv == -1) { 644 /* EINTR should trigger another read. */ 645 if (errno == EINTR) { 646 return true; 647 } else { 648 warn("read"); 649 return false; 650 } 651 } 652 /* Upon EOF, we have to flush what's left of the buffer. */ 653 if (bytes_read > 0) { 654 do_output(buf, bytes_read, state); 655 bytes_read = 0; 656 } 657 return false; 658 } 659 660 /* 661 * The default behavior is to stay silent if the user wants to redirect 662 * output to a file and/or syslog. If neither are provided, then we bounce 663 * everything back to parent's stdout. 664 */ 665 static void 666 do_output(const unsigned char *buf, size_t len, struct daemon_state *state) 667 { 668 assert(len <= LBUF_SIZE); 669 assert(state != NULL); 670 671 if (len < 1) { 672 return; 673 } 674 if (state->syslog_enabled) { 675 syslog(state->syslog_priority, "%.*s", (int)len, buf); 676 } 677 if (state->output_fd != -1) { 678 if (write(state->output_fd, buf, len) == -1) 679 warn("write"); 680 } 681 if (state->keep_fds_open && 682 !state->syslog_enabled && 683 state->output_fd == -1) { 684 printf("%.*s", (int)len, buf); 685 } 686 } 687 688 /* 689 * We use the global PID acquired directly from fork. If there is no valid 690 * child pid, the handler should be blocked and/or child_gone == 1. 691 */ 692 static void 693 handle_term(int signo) 694 { 695 if (pid > 0 && !child_gone) { 696 kill(pid, signo); 697 } 698 terminate = 1; 699 } 700 701 static void 702 handle_chld(int signo __unused) 703 { 704 705 for (;;) { 706 int rv = waitpid(-1, NULL, WNOHANG); 707 if (pid == rv) { 708 child_gone = 1; 709 break; 710 } else if (rv == -1 && errno != EINTR) { 711 warn("waitpid"); 712 return; 713 } 714 } 715 } 716 717 static void 718 handle_hup(int signo __unused) 719 { 720 721 do_log_reopen = 1; 722 } 723 724 static int 725 open_log(const char *outfn) 726 { 727 728 return open(outfn, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0600); 729 } 730 731 static void 732 reopen_log(struct daemon_state *state) 733 { 734 int outfd; 735 736 do_log_reopen = 0; 737 outfd = open_log(state->output_filename); 738 if (state->output_fd >= 0) { 739 close(state->output_fd); 740 } 741 state->output_fd = outfd; 742 } 743 744 static void 745 daemon_state_init(struct daemon_state *state) 746 { 747 *state = (struct daemon_state) { 748 .pipe_fd = { -1, -1 }, 749 .parent_pidfh = NULL, 750 .child_pidfh = NULL, 751 .child_pidfile = NULL, 752 .parent_pidfile = NULL, 753 .title = NULL, 754 .user = NULL, 755 .supervision_enabled = false, 756 .child_eof = false, 757 .restart_enabled = false, 758 .keep_cur_workdir = 1, 759 .restart_delay = 1, 760 .stdmask = STDOUT_FILENO | STDERR_FILENO, 761 .syslog_enabled = false, 762 .log_reopen = false, 763 .syslog_priority = LOG_NOTICE, 764 .syslog_tag = "daemon", 765 .syslog_facility = LOG_DAEMON, 766 .keep_fds_open = 1, 767 .output_fd = -1, 768 .output_filename = NULL, 769 }; 770 } 771 772 static _Noreturn void 773 daemon_terminate(struct daemon_state *state) 774 { 775 assert(state != NULL); 776 close(state->output_fd); 777 close(state->pipe_fd[0]); 778 close(state->pipe_fd[1]); 779 if (state->syslog_enabled) { 780 closelog(); 781 } 782 pidfile_remove(state->child_pidfh); 783 pidfile_remove(state->parent_pidfh); 784 785 /* 786 * Note that the exit value here doesn't matter in the case of a clean 787 * exit; daemon(3) already detached us from the caller, nothing is left 788 * to care about this one. 789 */ 790 exit(1); 791 } 792