23 #ifdef HAVE_VALGRIND_VALGRIND_H
24 # include <valgrind/valgrind.h>
28 # define O_LARGEFILE 0
31 #ifndef HAVE_CLOCK_GETTIME
32 #ifdef HAVE_SYS_TIME_H
33 # include <sys/time.h> /* gettimeofday() */
37 int log_clock_gettime_realtime (struct timespec
*ts
) {
38 #ifdef HAVE_CLOCK_GETTIME
39 return clock_gettime(CLOCK_REALTIME
, ts
);
41 /* Mac OSX does not provide clock_gettime()
42 * e.g. defined(__APPLE__) && defined(__MACH__) */
44 gettimeofday(&tv
, NULL
);
45 ts
->tv_sec
= tv
.tv_sec
;
46 ts
->tv_nsec
= tv
.tv_usec
* 1000;
51 /* retry write on EINTR or when not all data was written */
52 ssize_t
write_all(int fd
, const void* buf
, size_t count
) {
56 ssize_t r
= write(fd
, buf
, count
);
63 /* fail - repeating probably won't help */
67 /* really shouldn't happen... */
71 force_assert(r
<= (ssize_t
) count
);
73 buf
= r
+ (char const*) buf
;
81 /* Close fd and _try_ to get a /dev/null for it instead.
82 * close() alone may trigger some bugs when a
83 * process opens another file and gets fd = STDOUT_FILENO or STDERR_FILENO
84 * and later tries to just print on stdout/stderr
86 * Returns 0 on success and -1 on failure (fd gets closed in all cases)
88 int openDevNull(int fd
) {
92 /* Cygwin should work with /dev/null */
93 tmpfd
= open("nul", O_RDWR
);
95 tmpfd
= open("/dev/null", O_RDWR
);
97 if (tmpfd
!= -1 && tmpfd
!= fd
) {
101 /* coverity[leaked_handle : FALSE] */
102 return (tmpfd
!= -1) ? 0 : -1;
105 int open_logfile_or_pipe(server
*srv
, const char* logfile
) {
108 if (logfile
[0] == '|') {
110 /* create write pipe and spawn process */
114 if (pipe(to_log_fds
)) {
115 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "pipe failed: ", strerror(errno
));
125 /* dup the filehandle to STDIN */
126 if (to_log_fds
[0] != STDIN_FILENO
) {
127 if (STDIN_FILENO
!= dup2(to_log_fds
[0], STDIN_FILENO
)) {
128 log_error_write(srv
, __FILE__
, __LINE__
, "ss",
129 "dup2 failed: ", strerror(errno
));
132 close(to_log_fds
[0]);
134 close(to_log_fds
[1]);
139 /* we don't need the client socket */
140 for (i
= 3; i
< 256; i
++) {
146 /* close old stderr */
147 openDevNull(STDERR_FILENO
);
149 /* exec the log-process (skip the | ) */
150 execl("/bin/sh", "sh", "-c", logfile
+ 1, NULL
);
151 log_error_write(srv
, __FILE__
, __LINE__
, "sss",
152 "spawning log process failed: ", strerror(errno
),
159 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "fork failed: ", strerror(errno
));
162 close(to_log_fds
[0]);
170 } else if (-1 == (fd
= open(logfile
, O_APPEND
| O_WRONLY
| O_CREAT
| O_LARGEFILE
, 0644))) {
171 log_error_write(srv
, __FILE__
, __LINE__
, "SSSS",
172 "opening errorlog '", logfile
,
173 "' failed: ", strerror(errno
));
178 fd_close_on_exec(fd
);
187 * we have 4 possibilities:
193 * if the open failed, report to the user and die
197 int log_error_open(server
*srv
) {
199 /* perhaps someone wants to use syslog() */
200 openlog("lighttpd", LOG_CONS
| LOG_PID
, LOG_DAEMON
);
203 srv
->errorlog_mode
= ERRORLOG_FD
;
204 srv
->errorlog_fd
= STDERR_FILENO
;
206 if (srv
->srvconf
.errorlog_use_syslog
) {
207 srv
->errorlog_mode
= ERRORLOG_SYSLOG
;
208 } else if (!buffer_string_is_empty(srv
->srvconf
.errorlog_file
)) {
209 const char *logfile
= srv
->srvconf
.errorlog_file
->ptr
;
211 if (-1 == (srv
->errorlog_fd
= open_logfile_or_pipe(srv
, logfile
))) {
214 srv
->errorlog_mode
= (logfile
[0] == '|') ? ERRORLOG_PIPE
: ERRORLOG_FILE
;
217 log_error_write(srv
, __FILE__
, __LINE__
, "s", "server started");
219 if (srv
->errorlog_mode
== ERRORLOG_FD
&& !srv
->srvconf
.dont_daemonize
) {
220 /* We can only log to stderr in dont-daemonize mode;
221 * if we do daemonize and no errorlog file is specified, we log into /dev/null
223 srv
->errorlog_fd
= -1;
226 if (!buffer_string_is_empty(srv
->srvconf
.breakagelog_file
)) {
228 const char *logfile
= srv
->srvconf
.breakagelog_file
->ptr
;
230 if (srv
->errorlog_mode
== ERRORLOG_FD
) {
231 srv
->errorlog_fd
= dup(STDERR_FILENO
);
232 fd_close_on_exec(srv
->errorlog_fd
);
235 if (-1 == (breakage_fd
= open_logfile_or_pipe(srv
, logfile
))) {
239 if (STDERR_FILENO
!= breakage_fd
) {
240 dup2(breakage_fd
, STDERR_FILENO
);
243 } else if (!srv
->srvconf
.dont_daemonize
) {
244 /* move stderr to /dev/null */
245 openDevNull(STDERR_FILENO
);
253 * if the open failed, report to the user and die
254 * if no filename is given, use syslog instead
258 int log_error_cycle(server
*srv
) {
259 /* only cycle if the error log is a file */
261 if (srv
->errorlog_mode
== ERRORLOG_FILE
) {
262 const char *logfile
= srv
->srvconf
.errorlog_file
->ptr
;
263 /* already check of opening time */
267 if (-1 == (new_fd
= open_logfile_or_pipe(srv
, logfile
))) {
268 /* write to old log */
269 log_error_write(srv
, __FILE__
, __LINE__
, "SSSSS",
270 "cycling errorlog '", logfile
,
271 "' failed: ", strerror(errno
),
272 ", falling back to syslog()");
274 close(srv
->errorlog_fd
);
275 srv
->errorlog_fd
= -1;
277 srv
->errorlog_mode
= ERRORLOG_SYSLOG
;
280 /* ok, new log is open, close the old one */
281 close(srv
->errorlog_fd
);
282 srv
->errorlog_fd
= new_fd
;
283 fd_close_on_exec(srv
->errorlog_fd
);
290 int log_error_close(server
*srv
) {
291 switch(srv
->errorlog_mode
) {
295 if (-1 != srv
->errorlog_fd
) {
296 /* don't close STDERR */
297 if (STDERR_FILENO
!= srv
->errorlog_fd
)
298 close(srv
->errorlog_fd
);
299 srv
->errorlog_fd
= -1;
302 case ERRORLOG_SYSLOG
:
312 /* lowercase: append space, uppercase: don't */
313 static void log_buffer_append_printf(buffer
*out
, const char *fmt
, va_list ap
) {
321 case 's': /* string */
322 s
= va_arg(ap
, char *);
323 buffer_append_string_c_escaped(out
, s
, (NULL
!= s
) ? strlen(s
) : 0);
324 buffer_append_string_len(out
, CONST_STR_LEN(" "));
326 case 'b': /* buffer */
327 b
= va_arg(ap
, buffer
*);
328 buffer_append_string_c_escaped(out
, CONST_BUF_LEN(b
));
329 buffer_append_string_len(out
, CONST_STR_LEN(" "));
333 buffer_append_int(out
, d
);
334 buffer_append_string_len(out
, CONST_STR_LEN(" "));
336 case 'o': /* off_t */
337 o
= va_arg(ap
, off_t
);
338 buffer_append_int(out
, o
);
339 buffer_append_string_len(out
, CONST_STR_LEN(" "));
341 case 'x': /* int (hex) */
343 buffer_append_string_len(out
, CONST_STR_LEN("0x"));
344 buffer_append_uint_hex(out
, d
);
345 buffer_append_string_len(out
, CONST_STR_LEN(" "));
347 case 'S': /* string */
348 s
= va_arg(ap
, char *);
349 buffer_append_string_c_escaped(out
, s
, (NULL
!= s
) ? strlen(s
) : 0);
351 case 'B': /* buffer */
352 b
= va_arg(ap
, buffer
*);
353 buffer_append_string_c_escaped(out
, CONST_BUF_LEN(b
));
357 buffer_append_int(out
, d
);
359 case 'O': /* off_t */
360 o
= va_arg(ap
, off_t
);
361 buffer_append_int(out
, o
);
363 case 'X': /* int (hex) */
365 buffer_append_string_len(out
, CONST_STR_LEN("0x"));
366 buffer_append_uint_hex(out
, d
);
374 buffer_append_string_len(out
, fmt
, 1);
380 static int log_buffer_prepare(buffer
*b
, server
*srv
, const char *filename
, unsigned int line
) {
381 switch(srv
->errorlog_mode
) {
385 if (-1 == srv
->errorlog_fd
) return -1;
386 /* cache the generated timestamp */
387 if (srv
->cur_ts
!= srv
->last_generated_debug_ts
) {
388 buffer_string_prepare_copy(srv
->ts_debug_str
, 255);
389 buffer_append_strftime(srv
->ts_debug_str
, "%Y-%m-%d %H:%M:%S", localtime(&(srv
->cur_ts
)));
391 srv
->last_generated_debug_ts
= srv
->cur_ts
;
394 buffer_copy_buffer(b
, srv
->ts_debug_str
);
395 buffer_append_string_len(b
, CONST_STR_LEN(": ("));
397 case ERRORLOG_SYSLOG
:
398 /* syslog is generating its own timestamps */
399 buffer_copy_string_len(b
, CONST_STR_LEN("("));
403 buffer_append_string(b
, filename
);
404 buffer_append_string_len(b
, CONST_STR_LEN("."));
405 buffer_append_int(b
, line
);
406 buffer_append_string_len(b
, CONST_STR_LEN(") "));
411 static void log_write(server
*srv
, buffer
*b
) {
412 switch(srv
->errorlog_mode
) {
416 buffer_append_string_len(b
, CONST_STR_LEN("\n"));
417 write_all(srv
->errorlog_fd
, CONST_BUF_LEN(b
));
419 case ERRORLOG_SYSLOG
:
420 syslog(LOG_ERR
, "%s", b
->ptr
);
425 int log_error_write(server
*srv
, const char *filename
, unsigned int line
, const char *fmt
, ...) {
428 if (-1 == log_buffer_prepare(srv
->errorlog_buf
, srv
, filename
, line
)) return 0;
431 log_buffer_append_printf(srv
->errorlog_buf
, fmt
, ap
);
434 log_write(srv
, srv
->errorlog_buf
);
439 int log_error_write_multiline_buffer(server
*srv
, const char *filename
, unsigned int line
, buffer
*multiline
, const char *fmt
, ...) {
442 buffer
*b
= srv
->errorlog_buf
;
443 char *pos
, *end
, *current_line
;
445 if (buffer_string_is_empty(multiline
)) return 0;
447 if (-1 == log_buffer_prepare(b
, srv
, filename
, line
)) return 0;
450 log_buffer_append_printf(b
, fmt
, ap
);
453 prefix_len
= buffer_string_length(b
);
455 current_line
= pos
= multiline
->ptr
;
456 end
= multiline
->ptr
+ buffer_string_length(multiline
);
458 for ( ; pos
<= end
; ++pos
) {
462 case '\0': /* handles end of string */
463 if (current_line
< pos
) {
464 /* truncate to prefix */
465 buffer_string_set_length(b
, prefix_len
);
467 buffer_append_string_len(b
, current_line
, pos
- current_line
);
470 current_line
= pos
+ 1;