Index: src/mod_proxy_backend_fastcgi.c =================================================================== --- src/mod_proxy_backend_fastcgi.c (revision 2371) +++ src/mod_proxy_backend_fastcgi.c (working copy) @@ -640,10 +640,11 @@ ==18752== by 0x804F5D8: lighty_mainloop (server.c:1001) mod_proxy_backend_fastcgi.c.597: (trace) (stderr from 127.0.0.1:9090 for /trac/) SERVER_ADDR */ - TRACE("(stderr from %s for %s) %s", +/* TRACE("(stderr from %s for %s) %s", SAFE_BUF_STR(proxy_con->address->name), SAFE_BUF_STR(sess->remote_con->uri.path), - SAFE_BUF_STR(b)); + SAFE_BUF_STR(b)); */ + log_error_write_plain(srv, SAFE_BUF_STR(b)); buffer_free(b); } rc = HANDLER_GO_ON; Index: src/log.c =================================================================== --- src/log.c (revision 2371) +++ src/log.c (working copy) @@ -41,6 +41,76 @@ # define O_LARGEFILE 0 #endif +static int open_logfile_or_pipe(void *srv, const char* logfile) { + int fd; + + if (logfile[0] == '|') { +#ifdef HAVE_FORK + /* create write pipe and spawn process */ + + int to_log_fds[2]; + pid_t pid; + int i; + + if (pipe(to_log_fds)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno)); + return HANDLER_ERROR; + } + + /* fork, execve */ + switch (pid = fork()) { + case 0: + /* child */ + + close(STDIN_FILENO); + + /* dup the filehandle to STDIN */ + + if (dup2(to_log_fds[0], STDIN_FILENO) == STDIN_FILENO) { + + close(to_log_fds[0]); + /* not needed */ + close(to_log_fds[1]); + + /* we don't need the client socket */ + for (i = 3; i < 256; i++) { + close(i); + } + + /* exec the log-process (skip the | ) */ + execl("/bin/sh", "sh", "-c", logfile + 1, NULL); + } + + log_error_write(srv, __FILE__, __LINE__, "sss", + "spawning error-log process failed: ", strerror(errno), + logfile + 1); + + exit(-1); + break; + case -1: + /* error */ + log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed: ", strerror(errno)); + return -1; + default: + close(to_log_fds[0]); + + fd = to_log_fds[1]; + } + +#else + return -1; +#endif + } else if (-1 == (fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { + log_error_write(srv, __FILE__, __LINE__, "SSSS", + "opening errorlog '", logfile, + "' failed: ", strerror(errno)); + + return -1; + } + return fd; +} + + /** * open the errorlog * @@ -124,11 +194,7 @@ if (use_syslog) { err->mode = ERRORLOG_SYSLOG; } else if (!buffer_is_empty(file)) { - if (-1 == (err->fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { - log_error_write(NULL, __FILE__, __LINE__, "SBSS", - "opening errorlog '", file, - "' failed: ", strerror(errno)); - + if (-1 == (err->fd = open_logfile_or_pipe(NULL, file->ptr))) { return -1; } #ifdef FD_CLOEXEC @@ -174,7 +240,7 @@ int new_fd; - if (-1 == (new_fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { + if (-1 == (new_fd = open_logfile_or_pipe(NULL, file->ptr))) { /* write to old log */ log_error_write(NULL, __FILE__, __LINE__, "SBSSS", "cycling errorlog '", file, @@ -196,6 +262,36 @@ return 0; } +int log_error_write_plain(void *srv, const char* str) { + UNUSED(srv); + buffer *b; + errorlog *err = myconfig; + + b = buffer_init(); + buffer_prepare_copy(b, 4096); + buffer_append_string(b, str); + + switch(err->mode) { + case ERRORLOG_FILE: + buffer_append_string_len(b, CONST_STR_LEN("\n")); + write(err->fd, b->ptr, b->used - 1); + break; + case ERRORLOG_STDERR: + buffer_append_string_len(b, CONST_STR_LEN("\n")); + write(STDERR_FILENO, b->ptr, b->used - 1); + break; +#ifdef HAVE_SYSLOG_H + case ERRORLOG_SYSLOG: + syslog(LOG_ERR, "%s", b->ptr); + break; +#endif + } + + buffer_free(b); + + return 0; +} + int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...) { va_list ap; time_t t; Index: src/log.h =================================================================== --- src/log.h (revision 2371) +++ src/log.h (working copy) @@ -10,6 +10,7 @@ LI_API int log_error_open(buffer *file, int use_syslog); LI_API int log_error_close(); LI_API int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...); +LI_API int log_error_write_plain(void *srv, const char* str); LI_API int log_error_cycle(); #define REMOVE_PATH_FROM_FILE 1 #if REMOVE_PATH_FROM_FILE