Feature #296 » lighttpd-piperrorlog.patch
trunk/src/log.c (working copy) | ||
---|---|---|
/**
|
||
* open the errorlog
|
||
*
|
||
* we have 3 possibilities:
|
||
* we have 4 possibilities:
|
||
* - stderr (default)
|
||
* - syslog
|
||
* - logfile
|
||
* - pipe
|
||
*
|
||
* if the open failed, report to the user and die
|
||
*
|
||
... | ... | |
/* the errorlog */
|
||
int fd;
|
||
enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } mode;
|
||
enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG, ERRORLOG_PIPE } mode;
|
||
buffer *buf;
|
||
time_t cached_ts;
|
||
... | ... | |
TRACE("%s", "server stopped");
|
||
switch(err->mode) {
|
||
case ERRORLOG_PIPE: /* fall through */
|
||
case ERRORLOG_FILE:
|
||
close(err->fd);
|
||
break;
|
||
... | ... | |
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 (*(char *)file->ptr == '|') {
|
||
#ifdef HAVE_FORK
|
||
/* create write pipe and spawn process */
|
||
int to_log_fds[2];
|
||
pid_t pid;
|
||
if (pipe(to_log_fds)) {
|
||
log_error_write(NULL, __FILE__, __LINE__, "ss",
|
||
"pipe failed: ", strerror(errno));
|
||
return -1;
|
||
}
|
||
/* fork, execve */
|
||
switch (pid = fork()) {
|
||
case 0:
|
||
/* child */
|
||
close(STDIN_FILENO);
|
||
dup2(to_log_fds[0], STDIN_FILENO);
|
||
close(to_log_fds[0]);
|
||
/* not needed */
|
||
close(to_log_fds[1]);
|
||
/* we don't need the client socket */
|
||
for (fd = 3; fd < 256; fd++) {
|
||
close(fd);
|
||
}
|
||
/* exec the log-process (skip the | )
|
||
*
|
||
*/
|
||
execl("/bin/sh", "sh", "-c", file->ptr + 1, NULL);
|
||
|
||
log_error_write(NULL, __FILE__, __LINE__, "ssb",
|
||
"spawning log-process failed: ",
|
||
strerror(errno), file->ptr + 1);
|
||
exit(-1);
|
||
break;
|
||
case -1:
|
||
/* error */
|
||
log_error_write(NULL, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
|
||
break;
|
||
default:
|
||
close(to_log_fds[0]);
|
||
err->fd = to_log_fds[1];
|
||
break;
|
||
}
|
||
err->mode = ERRORLOG_PIPE;
|
||
#else
|
||
log_error_write(NULL, __FILE__, __LINE__, "SBS",
|
||
"opening errorlog '", file,"' impossible");
|
||
return -1;
|
||
#endif
|
||
} else {
|
||
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));
|
||
return -1;
|
||
}
|
||
err->mode = ERRORLOG_FILE;
|
||
}
|
||
#ifdef FD_CLOEXEC
|
||
/* close fd on exec (cgi) */
|
||
fcntl(err->fd, F_SETFD, FD_CLOEXEC);
|
||
#endif
|
||
err->mode = ERRORLOG_FILE;
|
||
}
|
||
TRACE("%s", "server started");
|
||
... | ... | |
*/
|
||
int log_error_cycle(void) {
|
||
/* only cycle if we are not in syslog-mode */
|
||
/* only cycle if the error log is a file */
|
||
errorlog *err = myconfig;
|
||
... | ... | |
UNUSED(srv);
|
||
switch(err->mode) {
|
||
case ERRORLOG_PIPE: /* fall through */
|
||
case ERRORLOG_FILE:
|
||
case ERRORLOG_STDERR:
|
||
/* cache the generated timestamp */
|
||
... | ... | |
va_end(ap);
|
||
switch(err->mode) {
|
||
case ERRORLOG_PIPE: /* fall through */
|
||
case ERRORLOG_FILE:
|
||
BUFFER_APPEND_STRING_CONST(err->buf, "\n");
|
||
write(err->fd, err->buf->ptr, err->buf->used - 1);
|
||
... | ... | |
/* write b */
|
||
switch(err->mode) {
|
||
case ERRORLOG_PIPE: /* fall through */
|
||
case ERRORLOG_FILE:
|
||
buffer_append_string(b, "\r\n");
|
||
write(err->fd, b->ptr, b->used - 1);
|