[mod_fastcgi,log] support multi line logging (fixes #2252)

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2866 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
Stefan Bühler 2013-03-25 17:22:32 +00:00
parent 543bd249fb
commit 0e48ef6acb
4 changed files with 149 additions and 91 deletions

1
NEWS
View File

@ -7,6 +7,7 @@ NEWS
* mod_fastcgi: fix mix up of "mode" => "authorizer" in other fastcgi configs (fixes #2465, thx peex)
* fix handling of If-Modified-Since if If-None-Match is present (don't return 412 for date parsing errors);
follow current draft for HTTP/1.1, which tells us to ignore If-Modified-Since if we have matching etags.
* [mod_fastcgi,log] support multi line logging (fixes #2252)
- 1.4.32 - 2012-11-21
* Code cleanup with clang/sparse (fixes #2437, thx kibi)

234
src/log.c
View File

@ -263,14 +263,80 @@ int log_error_close(server *srv) {
return 0;
}
int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
va_list ap;
/* lowercase: append space, uppercase: don't */
static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) {
for(; *fmt; fmt++) {
int d;
char *s;
buffer *b;
off_t o;
switch(*fmt) {
case 's': /* string */
s = va_arg(ap, char *);
buffer_append_string(out, s);
buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'b': /* buffer */
b = va_arg(ap, buffer *);
buffer_append_string_buffer(out, b);
buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'd': /* int */
d = va_arg(ap, int);
buffer_append_long(out, d);
buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'o': /* off_t */
o = va_arg(ap, off_t);
buffer_append_off_t(out, o);
buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'x': /* int (hex) */
d = va_arg(ap, int);
buffer_append_string_len(out, CONST_STR_LEN("0x"));
buffer_append_long_hex(out, d);
buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'S': /* string */
s = va_arg(ap, char *);
buffer_append_string(out, s);
break;
case 'B': /* buffer */
b = va_arg(ap, buffer *);
buffer_append_string_buffer(out, b);
break;
case 'D': /* int */
d = va_arg(ap, int);
buffer_append_long(out, d);
break;
case 'O': /* off_t */
o = va_arg(ap, off_t);
buffer_append_off_t(out, o);
break;
case 'X': /* int (hex) */
d = va_arg(ap, int);
buffer_append_string_len(out, CONST_STR_LEN("0x"));
buffer_append_long_hex(out, d);
break;
case '(':
case ')':
case '<':
case '>':
case ',':
case ' ':
buffer_append_string_len(out, fmt, 1);
break;
}
}
}
static int log_buffer_prepare(buffer *b, server *srv, const char *filename, unsigned int line) {
switch(srv->errorlog_mode) {
case ERRORLOG_PIPE:
case ERRORLOG_FILE:
case ERRORLOG_FD:
if (-1 == srv->errorlog_fd) return 0;
if (-1 == srv->errorlog_fd) return -1;
/* cache the generated timestamp */
if (srv->cur_ts != srv->last_generated_debug_ts) {
buffer_prepare_copy(srv->ts_debug_str, 255);
@ -280,99 +346,89 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const
srv->last_generated_debug_ts = srv->cur_ts;
}
buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(": ("));
buffer_copy_string_buffer(b, srv->ts_debug_str);
buffer_append_string_len(b, CONST_STR_LEN(": ("));
break;
case ERRORLOG_SYSLOG:
/* syslog is generating its own timestamps */
buffer_copy_string_len(srv->errorlog_buf, CONST_STR_LEN("("));
buffer_copy_string_len(b, CONST_STR_LEN("("));
break;
}
buffer_append_string(srv->errorlog_buf, filename);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("."));
buffer_append_long(srv->errorlog_buf, line);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(") "));
for(va_start(ap, fmt); *fmt; fmt++) {
int d;
char *s;
buffer *b;
off_t o;
switch(*fmt) {
case 's': /* string */
s = va_arg(ap, char *);
buffer_append_string(srv->errorlog_buf, s);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
break;
case 'b': /* buffer */
b = va_arg(ap, buffer *);
buffer_append_string_buffer(srv->errorlog_buf, b);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
break;
case 'd': /* int */
d = va_arg(ap, int);
buffer_append_long(srv->errorlog_buf, d);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
break;
case 'o': /* off_t */
o = va_arg(ap, off_t);
buffer_append_off_t(srv->errorlog_buf, o);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
break;
case 'x': /* int (hex) */
d = va_arg(ap, int);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
buffer_append_long_hex(srv->errorlog_buf, d);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
break;
case 'S': /* string */
s = va_arg(ap, char *);
buffer_append_string(srv->errorlog_buf, s);
break;
case 'B': /* buffer */
b = va_arg(ap, buffer *);
buffer_append_string_buffer(srv->errorlog_buf, b);
break;
case 'D': /* int */
d = va_arg(ap, int);
buffer_append_long(srv->errorlog_buf, d);
break;
case 'O': /* off_t */
o = va_arg(ap, off_t);
buffer_append_off_t(srv->errorlog_buf, o);
break;
case 'X': /* int (hex) */
d = va_arg(ap, int);
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
buffer_append_long_hex(srv->errorlog_buf, d);
break;
case '(':
case ')':
case '<':
case '>':
case ',':
case ' ':
buffer_append_string_len(srv->errorlog_buf, fmt, 1);
break;
}
}
va_end(ap);
switch(srv->errorlog_mode) {
case ERRORLOG_PIPE:
case ERRORLOG_FILE:
case ERRORLOG_FD:
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
break;
case ERRORLOG_SYSLOG:
syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
break;
}
buffer_append_string(b, filename);
buffer_append_string_len(b, CONST_STR_LEN("."));
buffer_append_long(b, line);
buffer_append_string_len(b, CONST_STR_LEN(") "));
return 0;
}
static void log_write(server *srv, buffer *b) {
switch(srv->errorlog_mode) {
case ERRORLOG_PIPE:
case ERRORLOG_FILE:
case ERRORLOG_FD:
buffer_append_string_len(b, CONST_STR_LEN("\n"));
write(srv->errorlog_fd, b->ptr, b->used - 1);
break;
case ERRORLOG_SYSLOG:
syslog(LOG_ERR, "%s", b->ptr);
break;
}
}
int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
va_list ap;
if (-1 == log_buffer_prepare(srv->errorlog_buf, srv, filename, line)) return 0;
va_start(ap, fmt);
log_buffer_append_printf(srv->errorlog_buf, fmt, ap);
va_end(ap);
log_write(srv, srv->errorlog_buf);
return 0;
}
int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...) {
va_list ap;
size_t prefix_used;
buffer *b = srv->errorlog_buf;
char *pos, *end, *current_line;
if (multiline->used < 2) return 0;
if (-1 == log_buffer_prepare(b, srv, filename, line)) return 0;
va_start(ap, fmt);
log_buffer_append_printf(b, fmt, ap);
va_end(ap);
prefix_used = b->used;
current_line = pos = multiline->ptr;
end = multiline->ptr + multiline->used;
for ( ; pos < end ; ++pos) {
switch (*pos) {
case '\n':
case '\r':
case '\0': /* handles end of string */
if (current_line < pos) {
/* truncate to prefix */
b->used = prefix_used;
b->ptr[b->used - 1] = '\0';
buffer_append_string_len(b, current_line, pos - current_line);
log_write(srv, b);
}
current_line = pos + 1;
break;
default:
break;
}
}
return 0;
}

View File

@ -15,6 +15,7 @@ int open_logfile_or_pipe(server *srv, const char* logfile);
int log_error_open(server *srv);
int log_error_close(server *srv);
int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...);
int log_error_cycle(server *srv);
#endif

View File

@ -2674,8 +2674,8 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
case FCGI_STDERR:
if (packet.len == 0) break;
log_error_write(srv, __FILE__, __LINE__, "sb",
"FastCGI-stderr:", packet.b);
log_error_write_multiline_buffer(srv, __FILE__, __LINE__, packet.b, "s",
"FastCGI-stderr:");
break;
case FCGI_END_REQUEST: