Lines Matching +full:supervisor +full:- +full:mode

1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
84 enum daemon_mode mode;
124 { "change-dir", no_argument, NULL, 'c' },
125 { "close-fds", no_argument, NULL, 'f' },
128 { "output-file", required_argument, NULL, 'o' },
129 { "output-mask", required_argument, NULL, 'm' },
130 { "child-pidfile", required_argument, NULL, 'p' },
131 { "supervisor-pidfile", required_argument, NULL, 'P' },
133 { "restart-count", required_argument, NULL, 'C' },
134 { "restart-delay", required_argument, NULL, 'R' },
137 { "syslog-priority", required_argument, NULL, 's' },
138 { "syslog-facility", required_argument, NULL, 'l' },
139 { "syslog-tag", required_argument, NULL, 'T' },
148 "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n"
149 " [-u user] [-o output_file] [-t title]\n"
150 " [-l syslog_facility] [-s syslog_priority]\n"
151 " [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"
152 " [-C restart_count]\n"
156 " --change-dir -c Change the current working directory to root\n"
157 " --close-fds -f Set stdin, stdout, stderr to /dev/null\n"
158 " --sighup -H Close and re-open output file on SIGHUP\n"
159 " --syslog -S Send output to syslog\n"
160 " --output-file -o <file> Append output of the child process to file\n"
161 " --output-mask -m <mask> What to send to syslog/file\n"
163 " --child-pidfile -p <file> Write PID of the child process to file\n"
164 " --supervisor-pidfile -P <file> Write PID of the supervisor process to file\n"
165 " --restart -r Restart child if it terminates (1 sec delay)\n"
166 " --restart-count -C <N> Restart child at most N times, then exit\n"
167 " --restart-delay -R <N> Restart child if it terminates after N sec\n"
168 " --title -t <title> Set the title of the supervisor process\n"
169 " --user -u <user> Drop privileges, run as given user\n"
170 " --syslog-priority -s <prio> Set syslog priority\n"
171 " --syslog-facility -l <flty> Set syslog facility\n"
172 " --syslog-tag -T <tag> Set syslog tag\n"
173 " --help -h Show this help\n");
192 * Supervision mode is enabled if one of the following options are used:
193 * --child-pidfile -p
194 * --supervisor-pidfile -P
195 * --restart -r / --restart-delay -R
196 * --syslog -S
197 * --syslog-facility -l
198 * --syslog-priority -s
199 * --syslog-tag -T
201 * In supervision mode daemon executes the command in a forked process
202 * and observes the child by waiting for SIGCHILD. In supervision mode
208 while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
229 if (state.syslog_facility == -1) {
233 state.mode = MODE_SUPERVISE;
245 * the supervision mode on. For non-supervised mode
249 state.mode = MODE_SUPERVISE;
253 state.mode = MODE_SUPERVISE;
257 state.mode = MODE_SUPERVISE;
261 state.mode = MODE_SUPERVISE;
270 state.mode = MODE_SUPERVISE;
275 if (state.syslog_priority == -1) {
279 state.mode = MODE_SUPERVISE;
283 state.mode = MODE_SUPERVISE;
291 state.mode = MODE_SUPERVISE;
303 argc -= optind;
317 if (state.output_fd == -1) {
335 * i.e. --foreground, -f
337 if (daemon(state.keep_cur_workdir, state.keep_fds_open) == -1) {
342 if (state.mode == MODE_DAEMON) {
352 state.mode = MODE_SUPERVISE;
355 if (state.restart_enabled && state.restart_count > -1) {
369 pidfile_write(state->child_pidfh);
371 if (state->user != NULL) {
372 restrict_process(state->user);
378 execvp(state->argv[0], state->argv);
379 /* execvp() failed - report error and exit this process */
380 err(1, "%s", state->argv[0]);
386 * - read until EOF
387 * - read until EOF but only for a while
388 * - bail immediately
412 state->pipe_rd = pipe_fd[0];
413 state->pipe_wr = pipe_fd[1];
415 kq = state->kqueue_fd;
416 EV_SET(&event, state->pipe_rd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0,
418 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
425 state->pid = fork();
428 switch (state->pid) {
429 case -1:
431 state->mode = MODE_NOCHILD;
442 close(state->pipe_wr);
443 state->pipe_wr = -1;
444 setproctitle("%s[%d]", state->title, (int)state->pid);
447 while (state->mode != MODE_NOCHILD) {
450 case -1:
470 state->pid = -1;
471 state->mode = MODE_NOCHILD;
478 if (state->mode != MODE_SUPERVISE) {
484 state->mode = MODE_TERMINATING;
485 state->restart_enabled = false;
486 if (state->pid > 0) {
487 kill(state->pid, SIGTERM);
495 if (state->log_reopen && state->output_fd >= 0) {
520 close(state->pipe_rd);
521 state->pipe_rd = -1;
528 if (state->child_pidfh != NULL && state->restart_enabled) {
529 pidfile_truncate(state->child_pidfh);
543 assert(state->pipe_rd == -1);
544 assert(state->pipe_wr == -1);
546 if (!state->restart_enabled) {
551 state->restart_delay, NULL);
552 if (kevent(state->kqueue_fd, &event, 1, NULL, 0, NULL) == -1) {
557 ret = kevent(state->kqueue_fd, NULL, 0, &event, 1, NULL);
558 if (ret == -1) {
586 state->restart_enabled = false;
589 if (state->log_reopen && state->output_fd >= 0) {
602 assert(state->restart_enabled);
611 if (state->child_pidfile) {
612 state->child_pidfh = pidfile_open(state->child_pidfile, 0600, &fpid);
613 if (state->child_pidfh == NULL) {
618 err(2, "pidfile ``%s''", state->child_pidfile);
622 if (state->parent_pidfile) {
623 state->parent_pidfh= pidfile_open(state->parent_pidfile, 0600, &fpid);
624 if (state->parent_pidfh == NULL) {
626 pidfile_remove(state->child_pidfh);
632 err(2, "ppidfile ``%s''", state->parent_pidfile);
641 for (cp = c; cp->c_name; cp++)
642 if (strcmp(cp->c_name, str) == 0) {
643 return cp->c_val;
645 return -1;
658 if (setusercontext(NULL, pw, pw->pw_uid, LOGIN_SETALL) != 0) {
662 setenv("USER", pw->pw_name, 1);
663 setenv("HOME", pw->pw_dir, 1);
664 setenv("SHELL", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL, 1);
681 assert(state->pos < LBUF_SIZE - 1);
683 rv = read(state->pipe_rd, state->buf + state->pos,
684 LBUF_SIZE - state->pos - 1);
686 state->pos += rv;
687 assert(state->pos <= LBUF_SIZE - 1);
688 /* Always NUL-terminate just in case. */
689 state->buf[LBUF_SIZE - 1] = '\0';
698 cp = memrchr(state->buf, '\n', state->pos);
700 size_t bytes_line = cp - state->buf + 1;
701 assert(bytes_line <= state->pos);
702 do_output(state->buf, bytes_line, state);
703 state->pos -= bytes_line;
704 memmove(state->buf, cp + 1, state->pos);
707 if (state->pos < LBUF_SIZE - 1) {
710 do_output(state->buf, state->pos, state);
711 state->pos = 0;
713 } else if (rv == -1) {
723 if (state->pos > 0) {
724 do_output(state->buf, state->pos, state);
725 state->pos = 0;
744 if (state->syslog_enabled) {
745 syslog(state->syslog_priority, "%.*s", (int)len, buf);
747 if (state->output_fd != -1) {
748 if (write(state->output_fd, buf, len) == -1)
751 if (state->keep_fds_open &&
752 !state->syslog_enabled &&
753 state->output_fd == -1) {
770 outfd = open_log(state->output_filename);
771 if (state->output_fd >= 0) {
772 close(state->output_fd);
774 state->output_fd = outfd;
790 .mode = MODE_DAEMON,
793 .pipe_rd = -1,
794 .pipe_wr = -1,
796 .kqueue_fd = -1,
805 .output_fd = -1,
807 .restart_count = -1,
817 if (state->kqueue_fd >= 0) {
818 close(state->kqueue_fd);
820 if (state->output_fd >= 0) {
821 close(state->output_fd);
823 if (state->pipe_rd >= 0) {
824 close(state->pipe_rd);
827 if (state->pipe_wr >= 0) {
828 close(state->pipe_wr);
830 if (state->syslog_enabled) {
833 pidfile_remove(state->child_pidfh);
834 pidfile_remove(state->parent_pidfh);
845 * Returns true if SIGCHILD came from state->pid due to its exit.
853 int who = waitpid(-1, &status, WNOHANG);
854 if (state->pid == who && (WIFEXITED(status) ||
861 if (who == -1 && errno != EINTR) {
871 if (state->stdmask & STDERR_FILENO) {
872 if (dup2(state->pipe_wr, STDERR_FILENO) == -1) {
876 if (state->stdmask & STDOUT_FILENO) {
877 if (dup2(state->pipe_wr, STDOUT_FILENO) == -1) {
881 if (state->pipe_wr != STDERR_FILENO &&
882 state->pipe_wr != STDOUT_FILENO) {
883 close(state->pipe_wr);
887 close(state->pipe_rd);
897 if (kq == -1) {
902 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
907 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
912 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
926 if (ftruncate(pfd, 0) == -1)
927 return (-1);
931 * it may not always and do a best-effort reset of the position just to