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