Annotation of embedaddon/lighttpd/src/log.c, revision 1.1.1.1

1.1       misho       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:  */
                     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: 
                     52: int open_logfile_or_pipe(server *srv, const char* logfile) {
                     53:        int fd;
                     54: 
                     55:        if (logfile[0] == '|') {
                     56: #ifdef HAVE_FORK
                     57:                /* create write pipe and spawn process */
                     58: 
                     59:                int to_log_fds[2];
                     60: 
                     61:                if (pipe(to_log_fds)) {
                     62:                        log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
                     63:                        return -1;
                     64:                }
                     65: 
                     66:                /* fork, execve */
                     67:                switch (fork()) {
                     68:                case 0:
                     69:                        /* child */
                     70:                        close(STDIN_FILENO);
                     71: 
                     72:                        /* dup the filehandle to STDIN */
                     73:                        if (to_log_fds[0] != STDIN_FILENO) {
                     74:                                if (STDIN_FILENO != dup2(to_log_fds[0], STDIN_FILENO)) {
                     75:                                        log_error_write(srv, __FILE__, __LINE__, "ss",
                     76:                                                "dup2 failed: ", strerror(errno));
                     77:                                        exit(-1);
                     78:                                }
                     79:                                close(to_log_fds[0]);
                     80:                        }
                     81:                        close(to_log_fds[1]);
                     82: 
                     83: #ifndef FD_CLOEXEC
                     84:                        {
                     85:                                int i;
                     86:                                /* we don't need the client socket */
                     87:                                for (i = 3; i < 256; i++) {
                     88:                                        close(i);
                     89:                                }
                     90:                        }
                     91: #endif
                     92: 
                     93:                        /* close old stderr */
                     94:                        openDevNull(STDERR_FILENO);
                     95: 
                     96:                        /* exec the log-process (skip the | ) */
                     97:                        execl("/bin/sh", "sh", "-c", logfile + 1, NULL);
                     98:                        log_error_write(srv, __FILE__, __LINE__, "sss",
                     99:                                        "spawning log process failed: ", strerror(errno),
                    100:                                        logfile + 1);
                    101: 
                    102:                        exit(-1);
                    103:                        break;
                    104:                case -1:
                    105:                        /* error */
                    106:                        log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed: ", strerror(errno));
                    107:                        return -1;
                    108:                default:
                    109:                        close(to_log_fds[0]);
                    110:                        fd = to_log_fds[1];
                    111:                        break;
                    112:                }
                    113: 
                    114: #else
                    115:                return -1;
                    116: #endif
                    117:        } else if (-1 == (fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
                    118:                log_error_write(srv, __FILE__, __LINE__, "SSSS",
                    119:                                "opening errorlog '", logfile,
                    120:                                "' failed: ", strerror(errno));
                    121: 
                    122:                return -1;
                    123:        }
                    124: 
                    125: #ifdef FD_CLOEXEC
                    126:        fcntl(fd, F_SETFD, FD_CLOEXEC);
                    127: #endif
                    128: 
                    129:        return fd;
                    130: }
                    131: 
                    132: 
                    133: /**
                    134:  * open the errorlog
                    135:  *
                    136:  * we have 4 possibilities:
                    137:  * - stderr (default)
                    138:  * - syslog
                    139:  * - logfile
                    140:  * - pipe
                    141:  *
                    142:  * if the open failed, report to the user and die
                    143:  *
                    144:  */
                    145: 
                    146: int log_error_open(server *srv) {
                    147: #ifdef HAVE_SYSLOG_H
                    148:        /* perhaps someone wants to use syslog() */
                    149:        openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
                    150: #endif
                    151: 
                    152:        srv->errorlog_mode = ERRORLOG_FD;
                    153:        srv->errorlog_fd = STDERR_FILENO;
                    154: 
                    155:        if (srv->srvconf.errorlog_use_syslog) {
                    156:                srv->errorlog_mode = ERRORLOG_SYSLOG;
                    157:        } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
                    158:                const char *logfile = srv->srvconf.errorlog_file->ptr;
                    159: 
                    160:                if (-1 == (srv->errorlog_fd = open_logfile_or_pipe(srv, logfile))) {
                    161:                        return -1;
                    162:                }
                    163:                srv->errorlog_mode = (logfile[0] == '|') ? ERRORLOG_PIPE : ERRORLOG_FILE;
                    164:        }
                    165: 
                    166:        log_error_write(srv, __FILE__, __LINE__, "s", "server started");
                    167: 
                    168:        if (srv->errorlog_mode == ERRORLOG_FD && !srv->srvconf.dont_daemonize) {
                    169:                /* We can only log to stderr in dont-daemonize mode;
                    170:                 * if we do daemonize and no errorlog file is specified, we log into /dev/null
                    171:                 */
                    172:                srv->errorlog_fd = -1;
                    173:        }
                    174: 
                    175:        if (!buffer_is_empty(srv->srvconf.breakagelog_file)) {
                    176:                int breakage_fd;
                    177:                const char *logfile = srv->srvconf.breakagelog_file->ptr;
                    178: 
                    179:                if (srv->errorlog_mode == ERRORLOG_FD) {
                    180:                        srv->errorlog_fd = dup(STDERR_FILENO);
                    181: #ifdef FD_CLOEXEC
                    182:                        fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
                    183: #endif
                    184:                }
                    185: 
                    186:                if (-1 == (breakage_fd = open_logfile_or_pipe(srv, logfile))) {
                    187:                        return -1;
                    188:                }
                    189: 
                    190:                if (STDERR_FILENO != breakage_fd) {
                    191:                        dup2(breakage_fd, STDERR_FILENO);
                    192:                        close(breakage_fd);
                    193:                }
                    194:        } else if (!srv->srvconf.dont_daemonize) {
                    195:                /* move stderr to /dev/null */
                    196:                openDevNull(STDERR_FILENO);
                    197:        }
                    198:        return 0;
                    199: }
                    200: 
                    201: /**
                    202:  * open the errorlog
                    203:  *
                    204:  * if the open failed, report to the user and die
                    205:  * if no filename is given, use syslog instead
                    206:  *
                    207:  */
                    208: 
                    209: int log_error_cycle(server *srv) {
                    210:        /* only cycle if the error log is a file */
                    211: 
                    212:        if (srv->errorlog_mode == ERRORLOG_FILE) {
                    213:                const char *logfile = srv->srvconf.errorlog_file->ptr;
                    214:                /* already check of opening time */
                    215: 
                    216:                int new_fd;
                    217: 
                    218:                if (-1 == (new_fd = open_logfile_or_pipe(srv, logfile))) {
                    219:                        /* write to old log */
                    220:                        log_error_write(srv, __FILE__, __LINE__, "SSSSS",
                    221:                                        "cycling errorlog '", logfile,
                    222:                                        "' failed: ", strerror(errno),
                    223:                                        ", falling back to syslog()");
                    224: 
                    225:                        close(srv->errorlog_fd);
                    226:                        srv->errorlog_fd = -1;
                    227: #ifdef HAVE_SYSLOG_H
                    228:                        srv->errorlog_mode = ERRORLOG_SYSLOG;
                    229: #endif
                    230:                } else {
                    231:                        /* ok, new log is open, close the old one */
                    232:                        close(srv->errorlog_fd);
                    233:                        srv->errorlog_fd = new_fd;
                    234: #ifdef FD_CLOEXEC
                    235:                        /* close fd on exec (cgi) */
                    236:                        fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
                    237: #endif
                    238:                }
                    239:        }
                    240: 
                    241:        return 0;
                    242: }
                    243: 
                    244: int log_error_close(server *srv) {
                    245:        switch(srv->errorlog_mode) {
                    246:        case ERRORLOG_PIPE:
                    247:        case ERRORLOG_FILE:
                    248:        case ERRORLOG_FD:
                    249:                if (-1 != srv->errorlog_fd) {
                    250:                        /* don't close STDERR */
                    251:                        if (STDERR_FILENO != srv->errorlog_fd)
                    252:                                close(srv->errorlog_fd);
                    253:                        srv->errorlog_fd = -1;
                    254:                }
                    255:                break;
                    256:        case ERRORLOG_SYSLOG:
                    257: #ifdef HAVE_SYSLOG_H
                    258:                closelog();
                    259: #endif
                    260:                break;
                    261:        }
                    262: 
                    263:        return 0;
                    264: }
                    265: 
                    266: /* lowercase: append space, uppercase: don't */
                    267: static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) {
                    268:        for(; *fmt; fmt++) {
                    269:                int d;
                    270:                char *s;
                    271:                buffer *b;
                    272:                off_t o;
                    273: 
                    274:                switch(*fmt) {
                    275:                case 's':           /* string */
                    276:                        s = va_arg(ap, char *);
                    277:                        buffer_append_string(out, s);
                    278:                        buffer_append_string_len(out, CONST_STR_LEN(" "));
                    279:                        break;
                    280:                case 'b':           /* buffer */
                    281:                        b = va_arg(ap, buffer *);
                    282:                        buffer_append_string_buffer(out, b);
                    283:                        buffer_append_string_len(out, CONST_STR_LEN(" "));
                    284:                        break;
                    285:                case 'd':           /* int */
                    286:                        d = va_arg(ap, int);
                    287:                        buffer_append_long(out, d);
                    288:                        buffer_append_string_len(out, CONST_STR_LEN(" "));
                    289:                        break;
                    290:                case 'o':           /* off_t */
                    291:                        o = va_arg(ap, off_t);
                    292:                        buffer_append_off_t(out, o);
                    293:                        buffer_append_string_len(out, CONST_STR_LEN(" "));
                    294:                        break;
                    295:                case 'x':           /* int (hex) */
                    296:                        d = va_arg(ap, int);
                    297:                        buffer_append_string_len(out, CONST_STR_LEN("0x"));
                    298:                        buffer_append_long_hex(out, d);
                    299:                        buffer_append_string_len(out, CONST_STR_LEN(" "));
                    300:                        break;
                    301:                case 'S':           /* string */
                    302:                        s = va_arg(ap, char *);
                    303:                        buffer_append_string(out, s);
                    304:                        break;
                    305:                case 'B':           /* buffer */
                    306:                        b = va_arg(ap, buffer *);
                    307:                        buffer_append_string_buffer(out, b);
                    308:                        break;
                    309:                case 'D':           /* int */
                    310:                        d = va_arg(ap, int);
                    311:                        buffer_append_long(out, d);
                    312:                        break;
                    313:                case 'O':           /* off_t */
                    314:                        o = va_arg(ap, off_t);
                    315:                        buffer_append_off_t(out, o);
                    316:                        break;
                    317:                case 'X':           /* int (hex) */
                    318:                        d = va_arg(ap, int);
                    319:                        buffer_append_string_len(out, CONST_STR_LEN("0x"));
                    320:                        buffer_append_long_hex(out, d);
                    321:                        break;
                    322:                case '(':
                    323:                case ')':
                    324:                case '<':
                    325:                case '>':
                    326:                case ',':
                    327:                case ' ':
                    328:                        buffer_append_string_len(out, fmt, 1);
                    329:                        break;
                    330:                }
                    331:        }
                    332: }
                    333: 
                    334: static int log_buffer_prepare(buffer *b, server *srv, const char *filename, unsigned int line) {
                    335:        switch(srv->errorlog_mode) {
                    336:        case ERRORLOG_PIPE:
                    337:        case ERRORLOG_FILE:
                    338:        case ERRORLOG_FD:
                    339:                if (-1 == srv->errorlog_fd) return -1;
                    340:                /* cache the generated timestamp */
                    341:                if (srv->cur_ts != srv->last_generated_debug_ts) {
                    342:                        buffer_prepare_copy(srv->ts_debug_str, 255);
                    343:                        strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
                    344:                        srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
                    345: 
                    346:                        srv->last_generated_debug_ts = srv->cur_ts;
                    347:                }
                    348: 
                    349:                buffer_copy_string_buffer(b, srv->ts_debug_str);
                    350:                buffer_append_string_len(b, CONST_STR_LEN(": ("));
                    351:                break;
                    352:        case ERRORLOG_SYSLOG:
                    353:                /* syslog is generating its own timestamps */
                    354:                buffer_copy_string_len(b, CONST_STR_LEN("("));
                    355:                break;
                    356:        }
                    357: 
                    358:        buffer_append_string(b, filename);
                    359:        buffer_append_string_len(b, CONST_STR_LEN("."));
                    360:        buffer_append_long(b, line);
                    361:        buffer_append_string_len(b, CONST_STR_LEN(") "));
                    362: 
                    363:        return 0;
                    364: }
                    365: 
                    366: static void log_write(server *srv, buffer *b) {
                    367:        switch(srv->errorlog_mode) {
                    368:        case ERRORLOG_PIPE:
                    369:        case ERRORLOG_FILE:
                    370:        case ERRORLOG_FD:
                    371:                buffer_append_string_len(b, CONST_STR_LEN("\n"));
                    372:                write(srv->errorlog_fd, b->ptr, b->used - 1);
                    373:                break;
                    374:        case ERRORLOG_SYSLOG:
                    375:                syslog(LOG_ERR, "%s", b->ptr);
                    376:                break;
                    377:        }
                    378: }
                    379: 
                    380: int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
                    381:        va_list ap;
                    382: 
                    383:        if (-1 == log_buffer_prepare(srv->errorlog_buf, srv, filename, line)) return 0;
                    384: 
                    385:        va_start(ap, fmt);
                    386:        log_buffer_append_printf(srv->errorlog_buf, fmt, ap);
                    387:        va_end(ap);
                    388: 
                    389:        log_write(srv, srv->errorlog_buf);
                    390: 
                    391:        return 0;
                    392: }
                    393: 
                    394: int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...) {
                    395:        va_list ap;
                    396:        size_t prefix_used;
                    397:        buffer *b = srv->errorlog_buf;
                    398:        char *pos, *end, *current_line;
                    399: 
                    400:        if (multiline->used < 2) return 0;
                    401: 
                    402:        if (-1 == log_buffer_prepare(b, srv, filename, line)) return 0;
                    403: 
                    404:        va_start(ap, fmt);
                    405:        log_buffer_append_printf(b, fmt, ap);
                    406:        va_end(ap);
                    407: 
                    408:        prefix_used = b->used;
                    409: 
                    410:        current_line = pos = multiline->ptr;
                    411:        end = multiline->ptr + multiline->used;
                    412: 
                    413:        for ( ; pos < end ; ++pos) {
                    414:                switch (*pos) {
                    415:                case '\n':
                    416:                case '\r':
                    417:                case '\0': /* handles end of string */
                    418:                        if (current_line < pos) {
                    419:                                /* truncate to prefix */
                    420:                                b->used = prefix_used;
                    421:                                b->ptr[b->used - 1] = '\0';
                    422: 
                    423:                                buffer_append_string_len(b, current_line, pos - current_line);
                    424:                                log_write(srv, b);
                    425:                        }
                    426:                        current_line = pos + 1;
                    427:                        break;
                    428:                default:
                    429:                        break;
                    430:                }
                    431:        }
                    432: 
                    433:        return 0;
                    434: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>