int main (int argc, char *argv[]) { conf_t conf; /* FIXME: Revamp signal handlers. */ if (posignal (SIGHUP, SIG_IGN) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to ignore signal=%d", SIGHUP); } if (posignal (SIGPIPE, SIG_IGN) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to ignore signal=%d", SIGPIPE); } /* Close stdin since it is not used. */ if (close (STDIN_FILENO) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to close standard input"); } /* Set stdout to be line buffered. */ if (setvbuf (stdout, NULL, _IOLBF, 0) < 0) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to line-buffer standard output"); } log_open_file (stderr, argv[0], LOG_INFO, LOG_OPT_PRIORITY); conf = create_conf (); parse_cmdline (conf, argc, argv); start_threads (conf); process_creds (conf); stop_threads (conf); destroy_conf (conf); log_close_file (); exit (EMUNGE_SUCCESS); }
static void handle_signals (void) { if (posignal (SIGHUP, hup_handler) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to handle signal=%d", SIGHUP); } if (posignal (SIGINT, exit_handler) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to handle signal=%d", SIGINT); } if (posignal (SIGTERM, exit_handler) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to handle signal=%d", SIGTERM); } if (posignal (SIGPIPE, SIG_IGN) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to ignore signal=%d", SIGPIPE); } return; }
static int daemonize_init (char *progname) { /* Begins the daemonization of the process. * Despite the fact that this routine backgrounds the process, control * will not be returned to the shell until daemonize_fini() is called. * Returns an 'fd' to pass to daemonize_fini() to complete the daemonization. */ int fds [2]; pid_t pid; int n; signed char priority; char ebuf [1024]; /* Clear file mode creation mask. */ umask (0); /* Create pipe for IPC so parent process will wait to terminate until * signaled by grandchild process. This allows messages written to * stdout/stderr by the grandchild to be properly displayed before * the parent process returns control to the shell. */ if (pipe (fds) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to create daemon pipe"); } /* Set the fd used by log_err() to return status back to the parent. */ log_set_err_pipe (fds[1]); /* Automatically background the process and * ensure child is not a process group leader. */ if ((pid = fork ()) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to create child process"); } else if (pid > 0) { log_set_err_pipe (-1); if (close (fds[1]) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to close write-pipe in parent process"); } if ((n = read (fds[0], &priority, sizeof (priority))) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to read status from grandchild process"); } if ((n > 0) && (priority >= 0)) { if ((n = read (fds[0], ebuf, sizeof (ebuf))) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to read err msg from grandchild process"); } if ((n > 0) && (ebuf[0] != '\0')) { log_open_file (stderr, progname, priority, LOG_OPT_PRIORITY); log_msg (priority, "%s", ebuf); } exit (EXIT_FAILURE); } exit (EXIT_SUCCESS); } if (close (fds[0]) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to close read-pipe in child process"); } /* Become a session leader and process group leader * with no controlling tty. */ if (setsid () < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to disassociate controlling tty"); } /* Ignore SIGHUP to keep child from terminating when * the session leader (ie, the parent) terminates. */ if (posignal (SIGHUP, SIG_IGN) == SIG_ERR) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to ignore signal=%d", SIGHUP); } /* Abdicate session leader position in order to guarantee * daemon cannot automatically re-acquire a controlling tty. */ if ((pid = fork ()) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to create grandchild process"); } else if (pid > 0) { exit (EXIT_SUCCESS); } return (fds[1]); }