1 #include "base.h"
2 #include "log.h"
3 #include "array.h"
4
5 #include <sys/types.h>
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <stdlib.h>
13
14 #include <stdarg.h>
15 #include <stdio.h>
16
17 #ifdef HAVE_SYSLOG_H
18 # include <syslog.h>
19 #endif
20
21 #ifdef HAVE_VALGRIND_VALGRIND_H
22 # include <valgrind/valgrind.h>
23 #endif
24
25 #ifndef O_LARGEFILE
26 # define O_LARGEFILE 0
27 #endif
28
29 /* Close fd and _try_ to get a /dev/null for it instead.
30 * close() alone may trigger some bugs when a
31 * process opens another file and gets fd = STDOUT_FILENO or STDERR_FILENO
32 * and later tries to just print on stdout/stderr
33 *
34 * Returns 0 on success and -1 on failure (fd gets closed in all cases)
35 */
openDevNull(int fd)36 int openDevNull(int fd) {
37 int tmpfd;
38 close(fd);
39 #if defined(__WIN32)
40 /* Cygwin should work with /dev/null */
41 tmpfd = open("nul", O_RDWR);
42 #else
43 tmpfd = open("/dev/null", O_RDWR);
44 #endif
45 if (tmpfd != -1 && tmpfd != fd) {
46 dup2(tmpfd, fd);
47 close(tmpfd);
48 }
49 return (tmpfd != -1) ? 0 : -1;
50 }
51
open_logfile_or_pipe(server * srv,const char * logfile)52 int open_logfile_or_pipe(server *srv, const char* logfile) {
53 int fd;
54
55 if (logfile[0] == '|') {
56 fprintf(stderr, "I am creating a pipe here!\n");
57 #ifdef HAVE_FORK
58 /* create write pipe and spawn process */
59
60 int to_log_fds[2];
61
62 if (pipe(to_log_fds)) {
63 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
64 return -1;
65 }
66
67 /* fork, execve */
68 switch (fork()) {
69 case 0:
70 /* child */
71 close(STDIN_FILENO);
72
73 /* dup the filehandle to STDIN */
74 if (to_log_fds[0] != STDIN_FILENO) {
75 if (STDIN_FILENO != dup2(to_log_fds[0], STDIN_FILENO)) {
76 log_error_write(srv, __FILE__, __LINE__, "ss",
77 "dup2 failed: ", strerror(errno));
78 exit(-1);
79 }
80 close(to_log_fds[0]);
81 }
82 close(to_log_fds[1]);
83
84 #ifndef FD_CLOEXEC
85 {
86 int i;
87 /* we don't need the client socket */
88 for (i = 3; i < 256; i++) {
89 close(i);
90 }
91 }
92 #endif
93
94 /* close old stderr */
95 openDevNull(STDERR_FILENO);
96
97 /* exec the log-process (skip the | ) */
98 execl("/bin/sh", "sh", "-c", logfile + 1, NULL);
99 log_error_write(srv, __FILE__, __LINE__, "sss",
100 "spawning log process failed: ", strerror(errno),
101 logfile + 1);
102
103 exit(-1);
104 break;
105 case -1:
106 /* error */
107 log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed: ", strerror(errno));
108 return -1;
109 default:
110 close(to_log_fds[0]);
111 fd = to_log_fds[1];
112 break;
113 }
114
115 #else
116 return -1;
117 #endif
118 } else if (-1 == (fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
119 log_error_write(srv, __FILE__, __LINE__, "SSSS",
120 "opening errorlog '", logfile,
121 "' failed: ", strerror(errno));
122
123 return -1;
124 }
125
126 #ifdef FD_CLOEXEC
127 fcntl(fd, F_SETFD, FD_CLOEXEC);
128 #endif
129
130 return fd;
131 }
132
133
134 /**
135 * open the errorlog
136 *
137 * we have 4 possibilities:
138 * - stderr (default)
139 * - syslog
140 * - logfile
141 * - pipe
142 *
143 * if the open failed, report to the user and die
144 *
145 */
146
log_error_open(server * srv)147 int log_error_open(server *srv) {
148 #ifdef HAVE_SYSLOG_H
149 /* perhaps someone wants to use syslog() */
150 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
151 #endif
152
153 srv->errorlog_mode = ERRORLOG_FD;
154 srv->errorlog_fd = STDERR_FILENO;
155
156 if (srv->srvconf.errorlog_use_syslog) {
157 srv->errorlog_mode = ERRORLOG_SYSLOG;
158 } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
159 const char *logfile = srv->srvconf.errorlog_file->ptr;
160
161 if (-1 == (srv->errorlog_fd = open_logfile_or_pipe(srv, logfile))) {
162 return -1;
163 }
164 srv->errorlog_mode = (logfile[0] == '|') ? ERRORLOG_PIPE : ERRORLOG_FILE;
165 }
166
167 log_error_write(srv, __FILE__, __LINE__, "s", "server started");
168
169 if (srv->errorlog_mode == ERRORLOG_FD && !srv->srvconf.dont_daemonize) {
170 /* We can only log to stderr in dont-daemonize mode;
171 * if we do daemonize and no errorlog file is specified, we log into /dev/null
172 */
173 srv->errorlog_fd = -1;
174 }
175
176 if (!buffer_is_empty(srv->srvconf.breakagelog_file)) {
177 int breakage_fd;
178 const char *logfile = srv->srvconf.breakagelog_file->ptr;
179
180 if (srv->errorlog_mode == ERRORLOG_FD) {
181 srv->errorlog_fd = dup(STDERR_FILENO);
182 #ifdef FD_CLOEXEC
183 fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
184 #endif
185 }
186
187 if (-1 == (breakage_fd = open_logfile_or_pipe(srv, logfile))) {
188 return -1;
189 }
190
191 if (STDERR_FILENO != breakage_fd) {
192 dup2(breakage_fd, STDERR_FILENO);
193 close(breakage_fd);
194 }
195 } else if (!srv->srvconf.dont_daemonize) {
196 /* move stderr to /dev/null */
197 openDevNull(STDERR_FILENO);
198 }
199 return 0;
200 }
201
202 /**
203 * open the errorlog
204 *
205 * if the open failed, report to the user and die
206 * if no filename is given, use syslog instead
207 *
208 */
209
log_error_cycle(server * srv)210 int log_error_cycle(server *srv) {
211 /* only cycle if the error log is a file */
212
213 if (srv->errorlog_mode == ERRORLOG_FILE) {
214 const char *logfile = srv->srvconf.errorlog_file->ptr;
215 /* already check of opening time */
216
217 int new_fd;
218
219 if (-1 == (new_fd = open_logfile_or_pipe(srv, logfile))) {
220 /* write to old log */
221 log_error_write(srv, __FILE__, __LINE__, "SSSSS",
222 "cycling errorlog '", logfile,
223 "' failed: ", strerror(errno),
224 ", falling back to syslog()");
225
226 close(srv->errorlog_fd);
227 srv->errorlog_fd = -1;
228 #ifdef HAVE_SYSLOG_H
229 srv->errorlog_mode = ERRORLOG_SYSLOG;
230 #endif
231 } else {
232 /* ok, new log is open, close the old one */
233 close(srv->errorlog_fd);
234 srv->errorlog_fd = new_fd;
235 #ifdef FD_CLOEXEC
236 /* close fd on exec (cgi) */
237 fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
238 #endif
239 }
240 }
241
242 return 0;
243 }
244
log_error_close(server * srv)245 int log_error_close(server *srv) {
246 switch(srv->errorlog_mode) {
247 case ERRORLOG_PIPE:
248 case ERRORLOG_FILE:
249 case ERRORLOG_FD:
250 if (-1 != srv->errorlog_fd) {
251 /* don't close STDERR */
252 if (STDERR_FILENO != srv->errorlog_fd)
253 close(srv->errorlog_fd);
254 srv->errorlog_fd = -1;
255 }
256 break;
257 case ERRORLOG_SYSLOG:
258 #ifdef HAVE_SYSLOG_H
259 closelog();
260 #endif
261 break;
262 }
263
264 return 0;
265 }
266
log_error_write(server * srv,const char * filename,unsigned int line,const char * fmt,...)267 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
268 va_list ap;
269
270 switch(srv->errorlog_mode) {
271 case ERRORLOG_PIPE:
272 case ERRORLOG_FILE:
273 case ERRORLOG_FD:
274 if (-1 == srv->errorlog_fd) return 0;
275 /* cache the generated timestamp */
276 if (srv->cur_ts != srv->last_generated_debug_ts) {
277 buffer_prepare_copy(srv->ts_debug_str, 255);
278 strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
279 srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
280
281 srv->last_generated_debug_ts = srv->cur_ts;
282 }
283
284 buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str);
285 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(": ("));
286 break;
287 case ERRORLOG_SYSLOG:
288 /* syslog is generating its own timestamps */
289 buffer_copy_string_len(srv->errorlog_buf, CONST_STR_LEN("("));
290 break;
291 }
292
293 buffer_append_string(srv->errorlog_buf, filename);
294 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("."));
295 buffer_append_long(srv->errorlog_buf, line);
296 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(") "));
297
298
299 for(va_start(ap, fmt); *fmt; fmt++) {
300 int d;
301 char *s;
302 buffer *b;
303 off_t o;
304
305 switch(*fmt) {
306 case 's': /* string */
307 s = va_arg(ap, char *);
308 buffer_append_string(srv->errorlog_buf, s);
309 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
310 break;
311 case 'b': /* buffer */
312 b = va_arg(ap, buffer *);
313 buffer_append_string_buffer(srv->errorlog_buf, b);
314 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
315 break;
316 case 'd': /* int */
317 d = va_arg(ap, int);
318 buffer_append_long(srv->errorlog_buf, d);
319 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
320 break;
321 case 'o': /* off_t */
322 o = va_arg(ap, off_t);
323 buffer_append_off_t(srv->errorlog_buf, o);
324 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
325 break;
326 case 'x': /* int (hex) */
327 d = va_arg(ap, int);
328 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
329 buffer_append_long_hex(srv->errorlog_buf, d);
330 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
331 break;
332 case 'S': /* string */
333 s = va_arg(ap, char *);
334 buffer_append_string(srv->errorlog_buf, s);
335 break;
336 case 'B': /* buffer */
337 b = va_arg(ap, buffer *);
338 buffer_append_string_buffer(srv->errorlog_buf, b);
339 break;
340 case 'D': /* int */
341 d = va_arg(ap, int);
342 buffer_append_long(srv->errorlog_buf, d);
343 break;
344 case 'O': /* off_t */
345 o = va_arg(ap, off_t);
346 buffer_append_off_t(srv->errorlog_buf, o);
347 break;
348 case 'X': /* int (hex) */
349 d = va_arg(ap, int);
350 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
351 buffer_append_long_hex(srv->errorlog_buf, d);
352 break;
353 case '(':
354 case ')':
355 case '<':
356 case '>':
357 case ',':
358 case ' ':
359 buffer_append_string_len(srv->errorlog_buf, fmt, 1);
360 break;
361 }
362 }
363 va_end(ap);
364
365 switch(srv->errorlog_mode) {
366 case ERRORLOG_PIPE:
367 case ERRORLOG_FILE:
368 case ERRORLOG_FD:
369 buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
370 write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
371 break;
372 case ERRORLOG_SYSLOG:
373 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
374 break;
375 }
376
377 return 0;
378 }
379
380