Author: mturk Date: Thu Aug 5 11:43:42 2010 New Revision: 982549 URL: http://svn.apache.org/viewvc?rev=982549&view=rev Log: DAEMON-80: Apply patch from Damien Raude-Morvan enabling syslog support
Modified: commons/proper/daemon/trunk/src/native/unix/man/jsvc.1.xml commons/proper/daemon/trunk/src/native/unix/native/debug.c commons/proper/daemon/trunk/src/native/unix/native/debug.h commons/proper/daemon/trunk/src/native/unix/native/jsvc-unix.c Modified: commons/proper/daemon/trunk/src/native/unix/man/jsvc.1.xml URL: http://svn.apache.org/viewvc/commons/proper/daemon/trunk/src/native/unix/man/jsvc.1.xml?rev=982549&r1=982548&r2=982549&view=diff ============================================================================== --- commons/proper/daemon/trunk/src/native/unix/man/jsvc.1.xml (original) +++ commons/proper/daemon/trunk/src/native/unix/man/jsvc.1.xml Thu Aug 5 11:43:42 2010 @@ -146,15 +146,19 @@ <varlistentry> <term><option>-outfile</option> /full/path/to/file</term> <listitem> - <para>Location for output from stdout (defaults to /dev/null). Use - the value '&2' to simulate '1>&2'</para> + <para>Location for output from stdout (defaults to + /dev/null). Use the value '&2' to simulate + '1>&2', or 'SYSLOG' to send output to the system + log.</para> </listitem> </varlistentry> <varlistentry> <term><option>-errfile</option> /full/path/to/file</term> <listitem> - <para>Location for output from stderr (defaults to /dev/null). Use - the value '&1' to simulate '2>&1'</para> + <para>Location for output from stderr (defaults to + /dev/null). Use the value '&1' to simulate + '2>&1', or 'SYSLOG' to send output to the system + log.</para> </listitem> </varlistentry> <varlistentry> Modified: commons/proper/daemon/trunk/src/native/unix/native/debug.c URL: http://svn.apache.org/viewvc/commons/proper/daemon/trunk/src/native/unix/native/debug.c?rev=982549&r1=982548&r2=982549&view=diff ============================================================================== --- commons/proper/daemon/trunk/src/native/unix/native/debug.c (original) +++ commons/proper/daemon/trunk/src/native/unix/native/debug.c Thu Aug 5 11:43:42 2010 @@ -23,6 +23,12 @@ /* Wether debug is enabled or not */ bool log_debug_flag = false; +/* Wether SYSLOG logging (for stderr) is enable or not. */ +bool log_stderr_syslog_flag = false; + +/* Wether SYSLOG logging (for stdout) is enable or not. */ +bool log_stdout_syslog_flag = false; + /* The name of the jsvc binary. */ char *log_prog = "jsvc"; @@ -39,12 +45,13 @@ void log_debug(const char *fmt, ...) if (fmt == NULL) return; - now = time(NULL); - nowtm = localtime(&now); - strftime(buff, sizeof(buff), "%d/%m/%Y %T", nowtm); - va_start(ap, fmt); - fprintf(stderr, "%s %d %s debug: ", buff, getpid(), log_prog); + if (log_stderr_syslog_flag) { + now = time(NULL); + nowtm = localtime(&now); + strftime(buff, sizeof(buff), "%d/%m/%Y %T", nowtm); + fprintf(stderr, "%s %d %s debug: ", buff, getpid(), log_prog); + } vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); fflush(stderr); @@ -62,12 +69,13 @@ void log_error(const char *fmt, ...) if (fmt == NULL) return; - now = time(NULL); - nowtm = localtime(&now); - strftime(buff, sizeof(buff), "%d/%m/%Y %T", nowtm); - va_start(ap, fmt); - fprintf(stderr, "%s %d %s error: ", buff, getpid(), log_prog); + if (log_stderr_syslog_flag) { + now = time(NULL); + nowtm = localtime(&now); + strftime(buff, sizeof(buff), "%d/%m/%Y %T", nowtm); + fprintf(stderr, "%s %d %s error: ", buff, getpid(), log_prog); + } vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); fflush(stderr); Modified: commons/proper/daemon/trunk/src/native/unix/native/debug.h URL: http://svn.apache.org/viewvc/commons/proper/daemon/trunk/src/native/unix/native/debug.h?rev=982549&r1=982548&r2=982549&view=diff ============================================================================== --- commons/proper/daemon/trunk/src/native/unix/native/debug.h (original) +++ commons/proper/daemon/trunk/src/native/unix/native/debug.h Thu Aug 5 11:43:42 2010 @@ -26,6 +26,12 @@ extern "C" { */ extern bool log_debug_flag; +/* Wether SYSLOG logging (for stderr) is enable or not. */ +extern bool log_stderr_syslog_flag; + +/* Wether SYSLOG logging (for stdout) is enable or not. */ +extern bool log_stdout_syslog_flag; + /** * The name of the jsvc binary. */ Modified: commons/proper/daemon/trunk/src/native/unix/native/jsvc-unix.c URL: http://svn.apache.org/viewvc/commons/proper/daemon/trunk/src/native/unix/native/jsvc-unix.c?rev=982549&r1=982548&r2=982549&view=diff ============================================================================== --- commons/proper/daemon/trunk/src/native/unix/native/jsvc-unix.c (original) +++ commons/proper/daemon/trunk/src/native/unix/native/jsvc-unix.c Thu Aug 5 11:43:42 2010 @@ -24,8 +24,11 @@ #include <sys/wait.h> #include <fcntl.h> #include <stdio.h> +#include <string.h> #include <pwd.h> #include <grp.h> +#include <syslog.h> +#include <errno.h> #ifdef OS_LINUX #include <sys/prctl.h> #include <sys/syscall.h> @@ -48,12 +51,16 @@ extern char **environ; static mode_t envmask; /* mask to create the files */ pid_t controlled = 0; /* the child process pid */ +pid_t logger_pid = 0; /* the logger process pid */ static bool stopping = false; static bool doreload = false; static void (*handler_int) (int) = NULL; static void (*handler_hup) (int) = NULL; static void (*handler_trm) (int) = NULL; +static int run_controller(arg_data *args, home_data *data, uid_t uid, + gid_t gid); + #ifdef OS_CYGWIN /* * File locking routine @@ -741,11 +748,63 @@ static FILE *loc_freopen(char *outfile, return freopen(outfile, mode, stream); } +#define LOGBUF_SIZE 1024 + +/* Read from file descriptors. Log to syslog. */ +static int logger_child(int out_fd, int err_fd, char *procname) +{ + fd_set rfds; + struct timeval tv; + int retval, n; + char buf[LOGBUF_SIZE]; + + if (out_fd > err_fd) { + n = out_fd + 1; + } else { + n = err_fd + 1; + } + + openlog(procname, LOG_PID, LOG_DAEMON); + + while (1) { + FD_ZERO(&rfds); + FD_SET(out_fd, &rfds); + FD_SET(err_fd, &rfds); + tv.tv_sec = 60; + tv.tv_usec = 0; + retval = select(n, &rfds, NULL, NULL, &tv); + if (retval == -1) + syslog(LOG_ERR, "select: %s", strerror(errno)); + else if (retval) { + if (FD_ISSET(out_fd, &rfds)) { + ssize_t n = read(out_fd, buf, LOGBUF_SIZE-1); + if (n < 0) { + syslog(LOG_ERR, "read: %s", strerror(errno)); + } else if (n > 0 && buf[0] != '\n') { + buf[n] = 0; + syslog(LOG_INFO, "%s", buf); + } + } + if (FD_ISSET(err_fd, &rfds)) { + ssize_t n = read(err_fd, buf, LOGBUF_SIZE-1); + if (n < 0) { + syslog(LOG_ERR, "read: %s", strerror(errno)); + } else if (n > 0 && buf[0] != '\n') { + buf[n] = 0; + syslog(LOG_ERR, "%s", buf); + } + } + } + } +} + /** * Redirect stdin, stdout, stderr. */ -static void set_output(char *outfile, char *errfile, bool redirectstdin) +static void set_output(char *outfile, char *errfile, bool redirectstdin, char *procname) { + int out_pipe[2] = {0, 0}, err_pipe[2] = {0, 0}, fork_needed = 0; + if (redirectstdin == true) { freopen("/dev/null", "r", stdin); } @@ -760,11 +819,31 @@ static void set_output(char *outfile, ch if (strcmp(outfile, "&2") == 0 && strcmp(errfile, "&1") == 0) { outfile = "/dev/null"; } - if (strcmp(outfile, "&2") != 0) { + if (strcmp(outfile, "SYSLOG") == 0) { + freopen("/dev/null", "a", stdout); + /* Send stdout to syslog through a logger process */ + if (pipe(out_pipe) == -1) { + log_error("cannot create stdout pipe: %s", + strerror(errno)); + } else { + fork_needed = 1; + log_stdout_syslog_flag = true; + } + } else if (strcmp(outfile, "&2") != 0) { loc_freopen(outfile, "a", stdout); } - if (strcmp(errfile, "&1") != 0) { + if (strcmp(errfile, "SYSLOG") == 0) { + freopen("/dev/null", "a", stderr); + /* Send stderr to syslog through a logger process */ + if (pipe(err_pipe) == -1) { + log_error("cannot create stderr pipe: %s", + strerror(errno)); + } else { + fork_needed = 1; + log_stderr_syslog_flag = true; + } + } else if (strcmp(errfile, "&1") != 0) { loc_freopen(errfile, "a", stderr); } else { @@ -775,17 +854,43 @@ static void set_output(char *outfile, ch close(1); dup(2); } + + if (fork_needed) { + pid_t pid = fork(); + if (pid == -1) { + log_error("cannot create logger process: %s", strerror(errno)); + } else { + if (pid) { + logger_pid = pid; + if (out_pipe[0] != 0) { + close(out_pipe[0]); + if (dup2(out_pipe[1], 1) == -1) { + log_error("cannot redirect stdout to pipe for syslog: %s", + strerror(errno)); + } + } + if (err_pipe[0] != 0) { + close(err_pipe[0]); + if (dup2(err_pipe[1], 2) == -1) { + log_error("cannot redirect stderr to pipe for syslog: %s", + strerror(errno)); + } + } + } else { + exit(logger_child(out_pipe[0], err_pipe[0], procname)); + } + } + } } int main(int argc, char *argv[]) { arg_data *args = NULL; home_data *data = NULL; - int status = 0; pid_t pid = 0; uid_t uid = 0; gid_t gid = 0; - time_t laststart; + int res; /* Parse command line arguments */ args = arguments(argc, argv); @@ -890,11 +995,27 @@ int main(int argc, char *argv[]) } envmask = umask(0077); - set_output(args->outfile, args->errfile, args->redirectstdin); + set_output(args->outfile, args->errfile, args->redirectstdin, args->procname); + + res = run_controller(args, data, uid, gid); + if (logger_pid != 0) { + kill(logger_pid, SIGTERM); + } + + return res; +} + +static int run_controller(arg_data *args, home_data *data, uid_t uid, + gid_t gid) +{ + pid_t pid = 0; + /* We have to fork: this process will become the controller and the other will be the child */ while ((pid = fork()) != -1) { + time_t laststart; + int status = 0; /* We forked (again), if this is the child, we go on normally */ if (pid == 0) exit(child(args, data, uid, gid)); @@ -975,4 +1096,3 @@ void main_shutdown(void) log_debug("Killing self with TERM signal"); kill(controlled, SIGTERM); } -