diff -urNp -x '*.orig' Pound-2.8.org/config.c Pound-2.8/config.c --- Pound-2.8.org/config.c 2021-10-04 21:55:51.849501382 +0200 +++ Pound-2.8/config.c 2021-10-04 21:55:51.876168039 +0200 @@ -73,7 +73,7 @@ static CODE facilitynames[] = { }; #endif -static regex_t Empty, Comment, User, Group, RootJail, Daemon, LogFacility, LogLevel, Alive, SSLEngine, Control; +static regex_t Empty, Comment, User, Group, RootJail, Daemon, LogFacility, LogFile, LogLevel, ErrorLog, Alive, SSLEngine, Control; static regex_t ListenHTTP, ListenHTTPS, End, Address, Port, Cert, xHTTP, Client, CheckURL; static regex_t Err414, Err500, Err501, Err503, MaxRequest, HeadRemove, RewriteLocation, RewriteDestination; static regex_t Service, ServiceName, URL, HeadRequire, HeadDeny, BackEnd, Emergency, Priority, HAport, HAportAddr; @@ -1330,6 +1330,18 @@ parse_file(void) def_facility = facilitynames[i].c_val; break; } + } else if(!regexec(&LogFile, lin, 4, matches, 0)) { + lin[matches[1].rm_eo] = '\0'; + if((log_file = strdup(lin + matches[1].rm_so)) == NULL) { + logmsg(LOG_ERR, "line %d: LogFile config: out of memory - aborted", n_lin); + exit(1); + } + } else if(!regexec(&ErrorLog, lin, 4, matches, 0)) { + lin[matches[1].rm_eo] = '\0'; + if((error_log = strdup(lin + matches[1].rm_so)) == NULL) { + logmsg(LOG_ERR, "line %d: ErrorLog config: out of memory - aborted", n_lin); + exit(1); + } } else if(!regexec(&Grace, lin, 4, matches, 0)) { grace = atoi(lin + matches[1].rm_so); } else if(!regexec(&LogLevel, lin, 4, matches, 0)) { @@ -1436,7 +1448,9 @@ config_parse(const int argc, char **cons || regcomp(&Daemon, "^[ \t]*Daemon[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Threads, "^[ \t]*Threads[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&LogFacility, "^[ \t]*LogFacility[ \t]+([a-z0-9-]+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&LogFile, "^[ \t]*LogFile[ \t]+(.+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&LogLevel, "^[ \t]*LogLevel[ \t]+([0-5])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&ErrorLog, "^[ \t]*ErrorLog[ \t]+(.+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Grace, "^[ \t]*Grace[ \t]+([0-9]+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Alive, "^[ \t]*Alive[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&SSLEngine, "^[ \t]*SSLEngine[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) @@ -1572,6 +1586,8 @@ config_parse(const int argc, char **cons group = NULL; root_jail = NULL; ctrl_name = NULL; + log_file = NULL; + error_log = NULL; numthreads = 128; alive_to = 30; @@ -1601,7 +1617,9 @@ config_parse(const int argc, char **cons regfree(&Daemon); regfree(&Threads); regfree(&LogFacility); + regfree(&LogFile); regfree(&LogLevel); + regfree(&ErrorLog); regfree(&Grace); regfree(&Alive); regfree(&SSLEngine); diff -urNp -x '*.orig' Pound-2.8.org/pound.c Pound-2.8/pound.c --- Pound-2.8.org/pound.c 2018-05-11 12:16:05.000000000 +0200 +++ Pound-2.8/pound.c 2021-10-04 21:55:51.876168039 +0200 @@ -32,6 +32,8 @@ char *user, /* user *group, /* group to run as */ *root_jail, /* directory to chroot to */ *pid_name, /* file to record pid in */ + *log_file, /* print log messages to this file, instead of syslog */ + *error_log, /* print error messages to this file, instead of syslog */ *ctrl_name; /* control socket name */ int alive_to, /* check interval for resurrection */ @@ -54,6 +56,7 @@ regex_t HEADER, /* Allowed h AUTHORIZATION; /* the Authorisation header */ static int shut_down = 0; +static int flush_logs = 0; #ifndef SOL_TCP /* for systems without the definition */ @@ -183,6 +186,33 @@ get_thr_qlen(void) return res; } +static void +reopen_logs() +{ + + logmsg(LOG_NOTICE, "reopening logs..."); + // reopen logs, but check access first, as it might fail in chroot + if (log_file) { + if (access(log_file, F_OK) == 0 && access(log_file, W_OK) == -1) { + logmsg(LOG_ERR, "%s: %s", log_file, strerror(errno)); + } else { + stdout = freopen(log_file, "a", stdout); + logmsg(LOG_ERR, "reopen stdout: %p", stdout); + setlinebuf(stdout); + } + } + if (error_log) { + if (access(error_log, F_OK) == 0 && access(error_log, W_OK) == -1) { + logmsg(LOG_ERR, "%s: %s", error_log, strerror(errno)); + } else { + stderr = freopen(error_log, "a", stderr); + logmsg(LOG_ERR, "reopen stderr: %p", stderr); + setlinebuf(stderr); + } + } + flush_logs = 0; +} + /* * handle SIGTERM/SIGQUIT - exit */ @@ -220,6 +250,21 @@ h_shut(const int sig) } /* + * handle SIGUSR1 - reopen logs + */ +static RETSIGTYPE +h_reopen(const int sig) +{ + logmsg(LOG_NOTICE, "%d received signal %d - reopening logs...", getpid(), sig); + if (son > 0) { + reopen_logs(); + kill(son, sig); + } else { + flush_logs = 1; + } +} + +/* * Pound: the reverse-proxy/load-balancer * * Arguments: @@ -254,6 +299,7 @@ main(const int argc, char **argv) signal(SIGINT, h_shut); signal(SIGTERM, h_term); signal(SIGQUIT, h_term); + signal(SIGUSR1, h_reopen); signal(SIGPIPE, SIG_IGN); srandom(getpid()); @@ -386,11 +432,23 @@ main(const int argc, char **argv) /* daemonize - make ourselves a subprocess. */ switch (fork()) { case 0: - if(log_facility != -1) { - close(0); - close(1); - close(2); + if (error_log) { + stderr = freopen(error_log, "a", stderr); + setlinebuf(stderr); + } else { + if (log_facility != -1) { + close(2); + } } + if (log_file) { + stdout = freopen(log_file, "a", stdout); + setlinebuf(stdout); + } else { + if (log_facility != -1) { + close(1); + } + } + close(0); break; case -1: logmsg(LOG_ERR, "fork: %s - aborted", strerror(errno)); @@ -448,7 +506,6 @@ main(const int argc, char **argv) logmsg(LOG_ERR, "MONITOR: worker exited (stopped?) %d, restarting...", status); } else if (son == 0) { #endif - /* thread stuff */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); @@ -499,6 +556,11 @@ main(const int argc, char **argv) (void)unlink(ctrl_name); exit(0); } + + if (flush_logs) { + reopen_logs(); + } + for(lstn = listeners, i = 0; i < n_listeners; lstn = lstn->next, i++) { polls[i].events = POLLIN | POLLPRI; polls[i].revents = 0; diff -urNp -x '*.orig' Pound-2.8.org/pound.h Pound-2.8/pound.h --- Pound-2.8.org/pound.h 2018-05-11 12:16:05.000000000 +0200 +++ Pound-2.8/pound.h 2021-10-04 21:55:51.876168039 +0200 @@ -264,6 +264,8 @@ extern char *user, /* user *group, /* group to run as */ *root_jail, /* directory to chroot to */ *pid_name, /* file to record pid in */ + *log_file, /* print log messages to this file, instead of syslog */ + *error_log, /* print error messages to this file, instead of syslog */ *ctrl_name; /* control socket name */ extern int numthreads, /* number of worker threads */ diff -urNp -x '*.orig' Pound-2.8.org/svc.c Pound-2.8/svc.c --- Pound-2.8.org/svc.c 2021-10-04 21:55:51.849501382 +0200 +++ Pound-2.8/svc.c 2021-10-04 21:55:51.876168039 +0200 @@ -220,49 +220,47 @@ t_clean(LHASH_OF(TABNODE) *const tab, vo #ifdef HAVE_STDARG_H void logmsg(const int priority, const char *fmt, ...) -{ - char buf[MAXBUF + 1]; - va_list ap; - struct tm *t_now, t_res; - - buf[MAXBUF] = '\0'; - va_start(ap, fmt); - vsnprintf(buf, MAXBUF, fmt, ap); - va_end(ap); - if(log_facility == -1) { - fprintf((priority == LOG_INFO || priority == LOG_DEBUG)? stdout: stderr, "%s\n", buf); - } else { - if(print_log) - printf("%s\n", buf); - else - syslog(log_facility | priority, "%s", buf); - } - return; -} #else void logmsg(const int priority, const char *fmt, va_alist) va_dcl +#endif { char buf[MAXBUF + 1]; va_list ap; struct tm *t_now, t_res; + int log = (priority == LOG_INFO || priority == LOG_DEBUG); buf[MAXBUF] = '\0'; +#ifdef HAVE_STDARG_H + va_start(ap, fmt); +#else va_start(ap); +#endif vsnprintf(buf, MAXBUF, fmt, ap); va_end(ap); - if(log_facility == -1) { - fprintf((priority == LOG_INFO || priority == LOG_DEBUG)? stdout: stderr, "%s\n", buf); + + // if access log or error log are set, use them. + if (log && log_file) { + fprintf(stdout, "%s\n", buf); + return; + } + if (!log && error_log) { + fprintf(stderr, "%s\n", buf); + return; + } + + if (log_facility == -1) { + fprintf(log ? stdout : stderr, "%s\n", buf); } else { - if(print_log) + if (print_log) { printf("%s\n", buf); - else + } else { syslog(log_facility | priority, "%s", buf); + } } return; } -#endif /* * Translate inet/inet6 address/port into a string