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 return (tmpfd
!= -1) ? 0 : -1;
104 int open_logfile_or_pipe(server
*srv
, const char* logfile
) {
107 if (logfile
[0] == '|') {
109 /* create write pipe and spawn process */
113 if (pipe(to_log_fds
)) {
114 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "pipe failed: ", strerror(errno
));
124 /* dup the filehandle to STDIN */
125 if (to_log_fds
[0] != STDIN_FILENO
) {
126 if (STDIN_FILENO
!= dup2(to_log_fds
[0], STDIN_FILENO
)) {
127 log_error_write(srv
, __FILE__
, __LINE__
, "ss",
128 "dup2 failed: ", strerror(errno
));
131 close(to_log_fds
[0]);
133 close(to_log_fds
[1]);
138 /* we don't need the client socket */
139 for (i
= 3; i
< 256; i
++) {
145 /* close old stderr */
146 openDevNull(STDERR_FILENO
);
148 /* exec the log-process (skip the | ) */
149 execl("/bin/sh", "sh", "-c", logfile
+ 1, NULL
);
150 log_error_write(srv
, __FILE__
, __LINE__
, "sss",
151 "spawning log process failed: ", strerror(errno
),
158 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "fork failed: ", strerror(errno
));
161 close(to_log_fds
[0]);
169 } else if (-1 == (fd
= open(logfile
, O_APPEND
| O_WRONLY
| O_CREAT
| O_LARGEFILE
, 0644))) {
170 log_error_write(srv
, __FILE__
, __LINE__
, "SSSS",
171 "opening errorlog '", logfile
,
172 "' failed: ", strerror(errno
));
177 fd_close_on_exec(fd
);
186 * we have 4 possibilities:
192 * if the open failed, report to the user and die
196 int log_error_open(server
*srv
) {
198 /* perhaps someone wants to use syslog() */
199 openlog("lighttpd", LOG_CONS
| LOG_PID
, LOG_DAEMON
);
202 srv
->errorlog_mode
= ERRORLOG_FD
;
203 srv
->errorlog_fd
= STDERR_FILENO
;
205 if (srv
->srvconf
.errorlog_use_syslog
) {
206 srv
->errorlog_mode
= ERRORLOG_SYSLOG
;
207 } else if (!buffer_string_is_empty(srv
->srvconf
.errorlog_file
)) {
208 const char *logfile
= srv
->srvconf
.errorlog_file
->ptr
;
210 if (-1 == (srv
->errorlog_fd
= open_logfile_or_pipe(srv
, logfile
))) {
213 srv
->errorlog_mode
= (logfile
[0] == '|') ? ERRORLOG_PIPE
: ERRORLOG_FILE
;
216 log_error_write(srv
, __FILE__
, __LINE__
, "s", "server started");
218 if (srv
->errorlog_mode
== ERRORLOG_FD
&& !srv
->srvconf
.dont_daemonize
) {
219 /* We can only log to stderr in dont-daemonize mode;
220 * if we do daemonize and no errorlog file is specified, we log into /dev/null
222 srv
->errorlog_fd
= -1;
225 if (!buffer_string_is_empty(srv
->srvconf
.breakagelog_file
)) {
227 const char *logfile
= srv
->srvconf
.breakagelog_file
->ptr
;
229 if (srv
->errorlog_mode
== ERRORLOG_FD
) {
230 srv
->errorlog_fd
= dup(STDERR_FILENO
);
231 fd_close_on_exec(srv
->errorlog_fd
);
234 if (-1 == (breakage_fd
= open_logfile_or_pipe(srv
, logfile
))) {
238 if (STDERR_FILENO
!= breakage_fd
) {
239 dup2(breakage_fd
, STDERR_FILENO
);
242 } else if (!srv
->srvconf
.dont_daemonize
) {
243 /* move stderr to /dev/null */
244 openDevNull(STDERR_FILENO
);
252 * if the open failed, report to the user and die
253 * if no filename is given, use syslog instead
257 int log_error_cycle(server
*srv
) {
258 /* only cycle if the error log is a file */
260 if (srv
->errorlog_mode
== ERRORLOG_FILE
) {
261 const char *logfile
= srv
->srvconf
.errorlog_file
->ptr
;
262 /* already check of opening time */
266 if (-1 == (new_fd
= open_logfile_or_pipe(srv
, logfile
))) {
267 /* write to old log */
268 log_error_write(srv
, __FILE__
, __LINE__
, "SSSSS",
269 "cycling errorlog '", logfile
,
270 "' failed: ", strerror(errno
),
271 ", falling back to syslog()");
273 close(srv
->errorlog_fd
);
274 srv
->errorlog_fd
= -1;
276 srv
->errorlog_mode
= ERRORLOG_SYSLOG
;
279 /* ok, new log is open, close the old one */
280 close(srv
->errorlog_fd
);
281 srv
->errorlog_fd
= new_fd
;
282 fd_close_on_exec(srv
->errorlog_fd
);
289 int log_error_close(server
*srv
) {
290 switch(srv
->errorlog_mode
) {
294 if (-1 != srv
->errorlog_fd
) {
295 /* don't close STDERR */
296 if (STDERR_FILENO
!= srv
->errorlog_fd
)
297 close(srv
->errorlog_fd
);
298 srv
->errorlog_fd
= -1;
301 case ERRORLOG_SYSLOG
:
311 /* lowercase: append space, uppercase: don't */
312 static void log_buffer_append_printf(buffer
*out
, const char *fmt
, va_list ap
) {
320 case 's': /* string */
321 s
= va_arg(ap
, char *);
322 buffer_append_string_c_escaped(out
, s
, (NULL
!= s
) ? strlen(s
) : 0);
323 buffer_append_string_len(out
, CONST_STR_LEN(" "));
325 case 'b': /* buffer */
326 b
= va_arg(ap
, buffer
*);
327 buffer_append_string_c_escaped(out
, CONST_BUF_LEN(b
));
328 buffer_append_string_len(out
, CONST_STR_LEN(" "));
332 buffer_append_int(out
, d
);
333 buffer_append_string_len(out
, CONST_STR_LEN(" "));
335 case 'o': /* off_t */
336 o
= va_arg(ap
, off_t
);
337 buffer_append_int(out
, o
);
338 buffer_append_string_len(out
, CONST_STR_LEN(" "));
340 case 'x': /* int (hex) */
342 buffer_append_string_len(out
, CONST_STR_LEN("0x"));
343 buffer_append_uint_hex(out
, d
);
344 buffer_append_string_len(out
, CONST_STR_LEN(" "));
346 case 'S': /* string */
347 s
= va_arg(ap
, char *);
348 buffer_append_string_c_escaped(out
, s
, (NULL
!= s
) ? strlen(s
) : 0);
350 case 'B': /* buffer */
351 b
= va_arg(ap
, buffer
*);
352 buffer_append_string_c_escaped(out
, CONST_BUF_LEN(b
));
356 buffer_append_int(out
, d
);
358 case 'O': /* off_t */
359 o
= va_arg(ap
, off_t
);
360 buffer_append_int(out
, o
);
362 case 'X': /* int (hex) */
364 buffer_append_string_len(out
, CONST_STR_LEN("0x"));
365 buffer_append_uint_hex(out
, d
);
373 buffer_append_string_len(out
, fmt
, 1);
379 static int log_buffer_prepare(buffer
*b
, server
*srv
, const char *filename
, unsigned int line
) {
380 switch(srv
->errorlog_mode
) {
384 if (-1 == srv
->errorlog_fd
) return -1;
385 /* cache the generated timestamp */
386 if (srv
->cur_ts
!= srv
->last_generated_debug_ts
) {
387 buffer_string_prepare_copy(srv
->ts_debug_str
, 255);
388 buffer_append_strftime(srv
->ts_debug_str
, "%Y-%m-%d %H:%M:%S", localtime(&(srv
->cur_ts
)));
390 srv
->last_generated_debug_ts
= srv
->cur_ts
;
393 buffer_copy_buffer(b
, srv
->ts_debug_str
);
394 buffer_append_string_len(b
, CONST_STR_LEN(": ("));
396 case ERRORLOG_SYSLOG
:
397 /* syslog is generating its own timestamps */
398 buffer_copy_string_len(b
, CONST_STR_LEN("("));
402 buffer_append_string(b
, filename
);
403 buffer_append_string_len(b
, CONST_STR_LEN("."));
404 buffer_append_int(b
, line
);
405 buffer_append_string_len(b
, CONST_STR_LEN(") "));
410 static void log_write(server
*srv
, buffer
*b
) {
411 switch(srv
->errorlog_mode
) {
415 buffer_append_string_len(b
, CONST_STR_LEN("\n"));
416 write_all(srv
->errorlog_fd
, CONST_BUF_LEN(b
));
418 case ERRORLOG_SYSLOG
:
419 syslog(LOG_ERR
, "%s", b
->ptr
);
424 int log_error_write(server
*srv
, const char *filename
, unsigned int line
, const char *fmt
, ...) {
427 if (-1 == log_buffer_prepare(srv
->errorlog_buf
, srv
, filename
, line
)) return 0;
430 log_buffer_append_printf(srv
->errorlog_buf
, fmt
, ap
);
433 log_write(srv
, srv
->errorlog_buf
);
438 int log_error_write_multiline_buffer(server
*srv
, const char *filename
, unsigned int line
, buffer
*multiline
, const char *fmt
, ...) {
441 buffer
*b
= srv
->errorlog_buf
;
442 char *pos
, *end
, *current_line
;
444 if (buffer_string_is_empty(multiline
)) return 0;
446 if (-1 == log_buffer_prepare(b
, srv
, filename
, line
)) return 0;
449 log_buffer_append_printf(b
, fmt
, ap
);
452 prefix_len
= buffer_string_length(b
);
454 current_line
= pos
= multiline
->ptr
;
455 end
= multiline
->ptr
+ buffer_string_length(multiline
);
457 for ( ; pos
<= end
; ++pos
) {
461 case '\0': /* handles end of string */
462 if (current_line
< pos
) {
463 /* truncate to prefix */
464 buffer_string_set_length(b
, prefix_len
);
466 buffer_append_string_len(b
, current_line
, pos
- current_line
);
469 current_line
= pos
+ 1;