+ }
+
+ /* Running in new daemon process. */
+ free((char *) program_name);
+ program_name = saved_program_name;
+}
+
+/* Close stdin, stdout, stderr. If we're started from e.g. an SSH session,
+ * then this keeps us from holding that session open artificially. */
+static void
+close_standard_fds(void)
+{
+ int null_fd = get_null_fd();
+ if (null_fd >= 0) {
+ dup2(null_fd, STDIN_FILENO);
+ dup2(null_fd, STDOUT_FILENO);
+ dup2(null_fd, STDERR_FILENO);
+ }
+}
+
+/* If daemonization is configured, then starts daemonization, by forking and
+ * returning in the child process. The parent process hangs around until the
+ * child lets it know either that it completed startup successfully (by calling
+ * daemon_complete()) or that it failed to start up (by exiting with a nonzero
+ * exit code). */
+void
+daemonize_start(void)
+{
+ daemonize_fd = -1;
+
+ if (detach) {
+ if (fork_and_wait_for_startup(&daemonize_fd) > 0) {
+ /* Running in parent process. */
+ exit(0);
+ }
+ /* Running in daemon or monitor process. */
+ }
+
+ if (monitor) {
+ int saved_daemonize_fd = daemonize_fd;
+ pid_t daemon_pid;
+
+ daemon_pid = fork_and_wait_for_startup(&daemonize_fd);
+ if (daemon_pid > 0) {
+ /* Running in monitor process. */
+ fork_notify_startup(saved_daemonize_fd);
+ close_standard_fds();
+ monitor_daemon(daemon_pid);
+ }
+ /* Running in daemon process. */
+ }
+
+ make_pidfile();
+}
+
+/* If daemonization is configured, then this function notifies the parent
+ * process that the child process has completed startup successfully. */
+void
+daemonize_complete(void)
+{
+ fork_notify_startup(daemonize_fd);
+
+ if (detach) {
+ setsid();
+ if (chdir_) {
+ ignore(chdir("/"));
+ }
+ close_standard_fds();