version 1.1, 2013/10/14 10:32:47
|
version 1.1.1.3, 2016/11/02 10:35:00
|
Line 1
|
Line 1
|
|
#include "first.h" |
|
|
#include "base.h" |
#include "base.h" |
#include "log.h" |
#include "log.h" |
#include "array.h" |
#include "array.h" |
Line 26
|
Line 28
|
# define O_LARGEFILE 0 |
# define O_LARGEFILE 0 |
#endif |
#endif |
|
|
|
#ifndef HAVE_CLOCK_GETTIME |
|
#ifdef HAVE_SYS_TIME_H |
|
# include <sys/time.h> /* gettimeofday() */ |
|
#endif |
|
#endif |
|
|
|
int log_clock_gettime_realtime (struct timespec *ts) { |
|
#ifdef HAVE_CLOCK_GETTIME |
|
return clock_gettime(CLOCK_REALTIME, ts); |
|
#else |
|
/* Mac OSX does not provide clock_gettime() |
|
* e.g. defined(__APPLE__) && defined(__MACH__) */ |
|
struct timeval tv; |
|
gettimeofday(&tv, NULL); |
|
ts->tv_sec = tv.tv_sec; |
|
ts->tv_nsec = tv.tv_usec * 1000; |
|
return 0; |
|
#endif |
|
} |
|
|
|
/* retry write on EINTR or when not all data was written */ |
|
ssize_t write_all(int fd, const void* buf, size_t count) { |
|
ssize_t written = 0; |
|
|
|
while (count > 0) { |
|
ssize_t r = write(fd, buf, count); |
|
if (r < 0) { |
|
switch (errno) { |
|
case EINTR: |
|
/* try again */ |
|
break; |
|
default: |
|
/* fail - repeating probably won't help */ |
|
return -1; |
|
} |
|
} else if (0 == r) { |
|
/* really shouldn't happen... */ |
|
errno = EIO; |
|
return -1; |
|
} else { |
|
force_assert(r <= (ssize_t) count); |
|
written += r; |
|
buf = r + (char const*) buf; |
|
count -= r; |
|
} |
|
} |
|
|
|
return written; |
|
} |
|
|
/* Close fd and _try_ to get a /dev/null for it instead. |
/* Close fd and _try_ to get a /dev/null for it instead. |
* close() alone may trigger some bugs when a |
* close() alone may trigger some bugs when a |
* process opens another file and gets fd = STDOUT_FILENO or STDERR_FILENO |
* process opens another file and gets fd = STDOUT_FILENO or STDERR_FILENO |
Line 122 int open_logfile_or_pipe(server *srv, const char* logf
|
Line 174 int open_logfile_or_pipe(server *srv, const char* logf
|
return -1; |
return -1; |
} |
} |
|
|
#ifdef FD_CLOEXEC | fd_close_on_exec(fd); |
fcntl(fd, F_SETFD, FD_CLOEXEC); | |
#endif | |
|
|
return fd; |
return fd; |
} |
} |
Line 154 int log_error_open(server *srv) {
|
Line 204 int log_error_open(server *srv) {
|
|
|
if (srv->srvconf.errorlog_use_syslog) { |
if (srv->srvconf.errorlog_use_syslog) { |
srv->errorlog_mode = ERRORLOG_SYSLOG; |
srv->errorlog_mode = ERRORLOG_SYSLOG; |
} else if (!buffer_is_empty(srv->srvconf.errorlog_file)) { | } else if (!buffer_string_is_empty(srv->srvconf.errorlog_file)) { |
const char *logfile = srv->srvconf.errorlog_file->ptr; |
const char *logfile = srv->srvconf.errorlog_file->ptr; |
|
|
if (-1 == (srv->errorlog_fd = open_logfile_or_pipe(srv, logfile))) { |
if (-1 == (srv->errorlog_fd = open_logfile_or_pipe(srv, logfile))) { |
Line 172 int log_error_open(server *srv) {
|
Line 222 int log_error_open(server *srv) {
|
srv->errorlog_fd = -1; |
srv->errorlog_fd = -1; |
} |
} |
|
|
if (!buffer_is_empty(srv->srvconf.breakagelog_file)) { | if (!buffer_string_is_empty(srv->srvconf.breakagelog_file)) { |
int breakage_fd; |
int breakage_fd; |
const char *logfile = srv->srvconf.breakagelog_file->ptr; |
const char *logfile = srv->srvconf.breakagelog_file->ptr; |
|
|
if (srv->errorlog_mode == ERRORLOG_FD) { |
if (srv->errorlog_mode == ERRORLOG_FD) { |
srv->errorlog_fd = dup(STDERR_FILENO); |
srv->errorlog_fd = dup(STDERR_FILENO); |
#ifdef FD_CLOEXEC | fd_close_on_exec(srv->errorlog_fd); |
fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC); | |
#endif | |
} |
} |
|
|
if (-1 == (breakage_fd = open_logfile_or_pipe(srv, logfile))) { |
if (-1 == (breakage_fd = open_logfile_or_pipe(srv, logfile))) { |
Line 231 int log_error_cycle(server *srv) {
|
Line 279 int log_error_cycle(server *srv) {
|
/* ok, new log is open, close the old one */ |
/* ok, new log is open, close the old one */ |
close(srv->errorlog_fd); |
close(srv->errorlog_fd); |
srv->errorlog_fd = new_fd; |
srv->errorlog_fd = new_fd; |
#ifdef FD_CLOEXEC | fd_close_on_exec(srv->errorlog_fd); |
/* close fd on exec (cgi) */ | |
fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC); | |
#endif | |
} |
} |
} |
} |
|
|
Line 274 static void log_buffer_append_printf(buffer *out, cons
|
Line 319 static void log_buffer_append_printf(buffer *out, cons
|
switch(*fmt) { |
switch(*fmt) { |
case 's': /* string */ |
case 's': /* string */ |
s = va_arg(ap, char *); |
s = va_arg(ap, char *); |
buffer_append_string(out, s); | buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
break; |
break; |
case 'b': /* buffer */ |
case 'b': /* buffer */ |
b = va_arg(ap, buffer *); |
b = va_arg(ap, buffer *); |
buffer_append_string_buffer(out, b); | buffer_append_string_c_escaped(out, CONST_BUF_LEN(b)); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
break; |
break; |
case 'd': /* int */ |
case 'd': /* int */ |
d = va_arg(ap, int); |
d = va_arg(ap, int); |
buffer_append_long(out, d); | buffer_append_int(out, d); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
break; |
break; |
case 'o': /* off_t */ |
case 'o': /* off_t */ |
o = va_arg(ap, off_t); |
o = va_arg(ap, off_t); |
buffer_append_off_t(out, o); | buffer_append_int(out, o); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
break; |
break; |
case 'x': /* int (hex) */ |
case 'x': /* int (hex) */ |
d = va_arg(ap, int); |
d = va_arg(ap, int); |
buffer_append_string_len(out, CONST_STR_LEN("0x")); |
buffer_append_string_len(out, CONST_STR_LEN("0x")); |
buffer_append_long_hex(out, d); | buffer_append_uint_hex(out, d); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
buffer_append_string_len(out, CONST_STR_LEN(" ")); |
break; |
break; |
case 'S': /* string */ |
case 'S': /* string */ |
s = va_arg(ap, char *); |
s = va_arg(ap, char *); |
buffer_append_string(out, s); | buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0); |
break; |
break; |
case 'B': /* buffer */ |
case 'B': /* buffer */ |
b = va_arg(ap, buffer *); |
b = va_arg(ap, buffer *); |
buffer_append_string_buffer(out, b); | buffer_append_string_c_escaped(out, CONST_BUF_LEN(b)); |
break; |
break; |
case 'D': /* int */ |
case 'D': /* int */ |
d = va_arg(ap, int); |
d = va_arg(ap, int); |
buffer_append_long(out, d); | buffer_append_int(out, d); |
break; |
break; |
case 'O': /* off_t */ |
case 'O': /* off_t */ |
o = va_arg(ap, off_t); |
o = va_arg(ap, off_t); |
buffer_append_off_t(out, o); | buffer_append_int(out, o); |
break; |
break; |
case 'X': /* int (hex) */ |
case 'X': /* int (hex) */ |
d = va_arg(ap, int); |
d = va_arg(ap, int); |
buffer_append_string_len(out, CONST_STR_LEN("0x")); |
buffer_append_string_len(out, CONST_STR_LEN("0x")); |
buffer_append_long_hex(out, d); | buffer_append_uint_hex(out, d); |
break; |
break; |
case '(': |
case '(': |
case ')': |
case ')': |
Line 339 static int log_buffer_prepare(buffer *b, server *srv,
|
Line 384 static int log_buffer_prepare(buffer *b, server *srv,
|
if (-1 == srv->errorlog_fd) return -1; |
if (-1 == srv->errorlog_fd) return -1; |
/* cache the generated timestamp */ |
/* cache the generated timestamp */ |
if (srv->cur_ts != srv->last_generated_debug_ts) { |
if (srv->cur_ts != srv->last_generated_debug_ts) { |
buffer_prepare_copy(srv->ts_debug_str, 255); | buffer_string_prepare_copy(srv->ts_debug_str, 255); |
strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); | buffer_append_strftime(srv->ts_debug_str, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); |
srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1; | |
|
|
srv->last_generated_debug_ts = srv->cur_ts; |
srv->last_generated_debug_ts = srv->cur_ts; |
} |
} |
|
|
buffer_copy_string_buffer(b, srv->ts_debug_str); | buffer_copy_buffer(b, srv->ts_debug_str); |
buffer_append_string_len(b, CONST_STR_LEN(": (")); |
buffer_append_string_len(b, CONST_STR_LEN(": (")); |
break; |
break; |
case ERRORLOG_SYSLOG: |
case ERRORLOG_SYSLOG: |
Line 357 static int log_buffer_prepare(buffer *b, server *srv,
|
Line 401 static int log_buffer_prepare(buffer *b, server *srv,
|
|
|
buffer_append_string(b, filename); |
buffer_append_string(b, filename); |
buffer_append_string_len(b, CONST_STR_LEN(".")); |
buffer_append_string_len(b, CONST_STR_LEN(".")); |
buffer_append_long(b, line); | buffer_append_int(b, line); |
buffer_append_string_len(b, CONST_STR_LEN(") ")); |
buffer_append_string_len(b, CONST_STR_LEN(") ")); |
|
|
return 0; |
return 0; |
Line 369 static void log_write(server *srv, buffer *b) {
|
Line 413 static void log_write(server *srv, buffer *b) {
|
case ERRORLOG_FILE: |
case ERRORLOG_FILE: |
case ERRORLOG_FD: |
case ERRORLOG_FD: |
buffer_append_string_len(b, CONST_STR_LEN("\n")); |
buffer_append_string_len(b, CONST_STR_LEN("\n")); |
write(srv->errorlog_fd, b->ptr, b->used - 1); | write_all(srv->errorlog_fd, CONST_BUF_LEN(b)); |
break; |
break; |
case ERRORLOG_SYSLOG: |
case ERRORLOG_SYSLOG: |
syslog(LOG_ERR, "%s", b->ptr); |
syslog(LOG_ERR, "%s", b->ptr); |
Line 393 int log_error_write(server *srv, const char *filename,
|
Line 437 int log_error_write(server *srv, const char *filename,
|
|
|
int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...) { |
int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...) { |
va_list ap; |
va_list ap; |
size_t prefix_used; | size_t prefix_len; |
buffer *b = srv->errorlog_buf; |
buffer *b = srv->errorlog_buf; |
char *pos, *end, *current_line; |
char *pos, *end, *current_line; |
|
|
if (multiline->used < 2) return 0; | if (buffer_string_is_empty(multiline)) return 0; |
|
|
if (-1 == log_buffer_prepare(b, srv, filename, line)) return 0; |
if (-1 == log_buffer_prepare(b, srv, filename, line)) return 0; |
|
|
Line 405 int log_error_write_multiline_buffer(server *srv, cons
|
Line 449 int log_error_write_multiline_buffer(server *srv, cons
|
log_buffer_append_printf(b, fmt, ap); |
log_buffer_append_printf(b, fmt, ap); |
va_end(ap); |
va_end(ap); |
|
|
prefix_used = b->used; | prefix_len = buffer_string_length(b); |
|
|
current_line = pos = multiline->ptr; |
current_line = pos = multiline->ptr; |
end = multiline->ptr + multiline->used; | end = multiline->ptr + buffer_string_length(multiline); |
|
|
for ( ; pos < end ; ++pos) { | for ( ; pos <= end ; ++pos) { |
switch (*pos) { |
switch (*pos) { |
case '\n': |
case '\n': |
case '\r': |
case '\r': |
case '\0': /* handles end of string */ |
case '\0': /* handles end of string */ |
if (current_line < pos) { |
if (current_line < pos) { |
/* truncate to prefix */ |
/* truncate to prefix */ |
b->used = prefix_used; | buffer_string_set_length(b, prefix_len); |
b->ptr[b->used - 1] = '\0'; | |
|
|
buffer_append_string_len(b, current_line, pos - current_line); |
buffer_append_string_len(b, current_line, pos - current_line); |
log_write(srv, b); |
log_write(srv, b); |