summaryrefslogtreecommitdiff
path: root/data/lighttpd/lighttpd-1.4.53/src/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'data/lighttpd/lighttpd-1.4.53/src/log.c')
-rw-r--r--data/lighttpd/lighttpd-1.4.53/src/log.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/data/lighttpd/lighttpd-1.4.53/src/log.c b/data/lighttpd/lighttpd-1.4.53/src/log.c
new file mode 100644
index 000000000..866ade394
--- /dev/null
+++ b/data/lighttpd/lighttpd-1.4.53/src/log.c
@@ -0,0 +1,216 @@
+#include "first.h"
+
+#include "base.h"
+#include "log.h"
+
+#include <sys/types.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYSLOG_H
+# include <syslog.h>
+#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;
+}
+
+/* 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 */
+ case 's': /* string */
+ s = va_arg(ap, char *);
+ buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0);
+ break;
+ case 'B': /* buffer */
+ case 'b': /* buffer */
+ b = va_arg(ap, buffer *);
+ buffer_append_string_c_escaped(out, CONST_BUF_LEN(b));
+ break;
+ case 'D': /* int */
+ case 'd': /* int */
+ d = va_arg(ap, int);
+ buffer_append_int(out, d);
+ break;
+ case 'O': /* off_t */
+ case 'o': /* off_t */
+ o = va_arg(ap, off_t);
+ buffer_append_int(out, o);
+ break;
+ case 'X': /* int (hex) */
+ case 'x': /* int (hex) */
+ d = va_arg(ap, int);
+ buffer_append_string_len(out, CONST_STR_LEN("0x"));
+ buffer_append_uint_hex(out, d);
+ break;
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case ',':
+ case ' ':
+ buffer_append_string_len(out, fmt, 1);
+ break;
+ }
+
+ if (*fmt >= 'a') { /* 's' 'b' 'd' 'o' 'x' */
+ buffer_append_string_len(out, CONST_STR_LEN(" "));
+ }
+ }
+}
+
+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 -1;
+ /* cache the generated timestamp */
+ if (srv->cur_ts != srv->last_generated_debug_ts) {
+ buffer_clear(srv->ts_debug_str);
+ buffer_append_strftime(srv->ts_debug_str, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
+
+ srv->last_generated_debug_ts = srv->cur_ts;
+ }
+
+ buffer_copy_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(b, CONST_STR_LEN("("));
+ break;
+ }
+
+ buffer_append_string(b, filename);
+ buffer_append_string_len(b, CONST_STR_LEN("."));
+ buffer_append_int(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_all(srv->errorlog_fd, CONST_BUF_LEN(b));
+ 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_len;
+ buffer *b = srv->errorlog_buf;
+ char *pos, *end, *current_line;
+
+ if (buffer_string_is_empty(multiline)) 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_len = buffer_string_length(b);
+
+ current_line = pos = multiline->ptr;
+ end = multiline->ptr + buffer_string_length(multiline);
+
+ for ( ; pos <= end ; ++pos) {
+ switch (*pos) {
+ case '\n':
+ case '\r':
+ case '\0': /* handles end of string */
+ if (current_line < pos) {
+ /* truncate to prefix */
+ buffer_string_set_length(b, prefix_len);
+
+ buffer_append_string_len(b, current_line, pos - current_line);
+ log_write(srv, b);
+ }
+ current_line = pos + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}