Index: usr.sbin/daemon/daemon.8 =================================================================== --- usr.sbin/daemon/daemon.8 +++ usr.sbin/daemon/daemon.8 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 2, 2019 +.Dd September 22, 2020 .Dt DAEMON 8 .Os .Sh NAME @@ -34,7 +34,7 @@ .Nd run detached from the controlling terminal .Sh SYNOPSIS .Nm -.Op Fl cfrS +.Op Fl cfHrS .Op Fl p Ar child_pidfile .Op Fl P Ar supervisor_pidfile .Op Fl t Ar title @@ -68,6 +68,10 @@ .Pa /dev/null , then stdout and/or stderr is redirected to a file or to syslog as specified by the other options. +.It Fl H +Close +.Pa output_file +and re-open it when signal SIGHUP is received. .It Fl S Enable syslog output. This is implicitly applied if other syslog parameters are provided. @@ -77,6 +81,12 @@ Append output from the daemonized process to .Pa output_file . If the file does not exist, it is created with permissions 0600. +When this option is used together with options +.Fl c and +.Fl H +the absolute path needs to be provided to ensure +.Nm +can re-open the file later on. .It Fl m Ar output_mask Redirect output from the child process stdout (1), stderr (2), or both (3). This value specifies what is sent to syslog and the log file. Index: usr.sbin/daemon/daemon.c =================================================================== --- usr.sbin/daemon/daemon.c +++ usr.sbin/daemon/daemon.c @@ -61,11 +61,13 @@ int logpri; int noclose; int outfd; + const char *outfn; }; static void restrict_process(const char *); static void handle_term(int); static void handle_chld(int); +static void reopen_logs(int); static int listen_child(int, struct log_params *); static int get_log_mapping(const char *, const CODE *); static void open_pid_files(const char *, const char *, struct pidfh **, @@ -76,6 +78,8 @@ static volatile sig_atomic_t terminate = 0, child_gone = 0, pid = 0; +static const struct log_params *lpp; + int main(int argc, char *argv[]) { @@ -84,7 +88,7 @@ sigset_t mask_susp, mask_orig, mask_read, mask_term; struct log_params logpar; int pfd[2] = { -1, -1 }, outfd = -1; - int stdmask, logpri, logfac; + int stdmask, logpri, logfac, log_reopen; struct pidfh *ppfh, *pfh; char *p; @@ -97,9 +101,10 @@ logtag = "daemon"; restart = 0; dosyslog = 0; + log_reopen = 0; outfn = NULL; title = NULL; - while ((ch = getopt(argc, argv, "cfSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) { + while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) { switch (ch) { case 'c': nochdir = 0; @@ -107,6 +112,9 @@ case 'f': noclose = 0; break; + case 'H': + log_reopen = 1; + break; case 'l': logfac = get_log_mapping(optarg, facilitynames); if (logfac == -1) @@ -201,7 +209,7 @@ */ pid = -1; if (pidfile || ppidfile || restart || outfd != -1 || dosyslog) { - struct sigaction act_term, act_chld; + struct sigaction act_term, act_chld, act_hup; /* Avoid PID racing with SIGCHLD and SIGTERM. */ memset(&act_term, 0, sizeof(act_term)); @@ -214,6 +222,10 @@ sigemptyset(&act_chld.sa_mask); sigaddset(&act_chld.sa_mask, SIGTERM); + memset(&act_hup, 0, sizeof(act_hup)); + act_hup.sa_handler = reopen_logs; + sigemptyset(&act_hup.sa_mask); + /* Block these when avoiding racing before sigsuspend(). */ sigemptyset(&mask_susp); sigaddset(&mask_susp, SIGTERM); @@ -251,6 +263,13 @@ logpar.dosyslog = dosyslog; logpar.logpri = logpri; logpar.noclose = noclose; + logpar.outfn = outfn; + lpp = &logpar; + if (log_reopen && outfd >= 0 && + sigaction(SIGHUP, &act_hup, NULL) == -1) { + warn("sigaction"); + goto exit; + } restart: if (pipe(pfd)) err(1, "pipe"); @@ -558,11 +577,24 @@ } } +static void +reopen_logs(int signo) +{ + (void)signo; + int outfd; + + outfd = open(lpp->outfn, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0600); + if (outfd < 0) + return; + (void)dup2(outfd, lpp->outfd); + (void)close(outfd); +} + static void usage(void) { (void)fprintf(stderr, - "usage: daemon [-cfrS] [-p child_pidfile] [-P supervisor_pidfile]\n" + "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n" " [-u user] [-o output_file] [-t title]\n" " [-l syslog_facility] [-s syslog_priority]\n" " [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"