1*36e94dc5SPeter Avalos /* $OpenBSD: log.c,v 1.45 2013/05/16 09:08:41 dtucker Exp $ */ 218de8d7fSPeter Avalos /* 318de8d7fSPeter Avalos * Author: Tatu Ylonen <ylo@cs.hut.fi> 418de8d7fSPeter Avalos * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 518de8d7fSPeter Avalos * All rights reserved 618de8d7fSPeter Avalos * 718de8d7fSPeter Avalos * As far as I am concerned, the code I have written for this software 818de8d7fSPeter Avalos * can be used freely for any purpose. Any derived versions of this 918de8d7fSPeter Avalos * software must be clearly marked as such, and if the derived work is 1018de8d7fSPeter Avalos * incompatible with the protocol description in the RFC file, it must be 1118de8d7fSPeter Avalos * called by a name other than "ssh" or "Secure Shell". 1218de8d7fSPeter Avalos */ 1318de8d7fSPeter Avalos /* 1418de8d7fSPeter Avalos * Copyright (c) 2000 Markus Friedl. All rights reserved. 1518de8d7fSPeter Avalos * 1618de8d7fSPeter Avalos * Redistribution and use in source and binary forms, with or without 1718de8d7fSPeter Avalos * modification, are permitted provided that the following conditions 1818de8d7fSPeter Avalos * are met: 1918de8d7fSPeter Avalos * 1. Redistributions of source code must retain the above copyright 2018de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer. 2118de8d7fSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright 2218de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer in the 2318de8d7fSPeter Avalos * documentation and/or other materials provided with the distribution. 2418de8d7fSPeter Avalos * 2518de8d7fSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2618de8d7fSPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2718de8d7fSPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2818de8d7fSPeter Avalos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2918de8d7fSPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3018de8d7fSPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3118de8d7fSPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3218de8d7fSPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3318de8d7fSPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3418de8d7fSPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3518de8d7fSPeter Avalos */ 3618de8d7fSPeter Avalos 3718de8d7fSPeter Avalos #include "includes.h" 3818de8d7fSPeter Avalos 3918de8d7fSPeter Avalos #include <sys/types.h> 4018de8d7fSPeter Avalos 41*36e94dc5SPeter Avalos #include <fcntl.h> 4218de8d7fSPeter Avalos #include <stdarg.h> 4318de8d7fSPeter Avalos #include <stdio.h> 4418de8d7fSPeter Avalos #include <stdlib.h> 4518de8d7fSPeter Avalos #include <string.h> 4618de8d7fSPeter Avalos #include <syslog.h> 4718de8d7fSPeter Avalos #include <unistd.h> 4818de8d7fSPeter Avalos #include <errno.h> 49*36e94dc5SPeter Avalos #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 5018de8d7fSPeter Avalos # include <vis.h> 5118de8d7fSPeter Avalos #endif 5218de8d7fSPeter Avalos 5318de8d7fSPeter Avalos #include "xmalloc.h" 5418de8d7fSPeter Avalos #include "log.h" 5518de8d7fSPeter Avalos 5618de8d7fSPeter Avalos static LogLevel log_level = SYSLOG_LEVEL_INFO; 5718de8d7fSPeter Avalos static int log_on_stderr = 1; 58*36e94dc5SPeter Avalos static int log_stderr_fd = STDERR_FILENO; 5918de8d7fSPeter Avalos static int log_facility = LOG_AUTH; 6018de8d7fSPeter Avalos static char *argv0; 611c188a7fSPeter Avalos static log_handler_fn *log_handler; 621c188a7fSPeter Avalos static void *log_handler_ctx; 6318de8d7fSPeter Avalos 6418de8d7fSPeter Avalos extern char *__progname; 6518de8d7fSPeter Avalos 6618de8d7fSPeter Avalos #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) 6718de8d7fSPeter Avalos #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) 6818de8d7fSPeter Avalos 6918de8d7fSPeter Avalos /* textual representation of log-facilities/levels */ 7018de8d7fSPeter Avalos 7118de8d7fSPeter Avalos static struct { 7218de8d7fSPeter Avalos const char *name; 7318de8d7fSPeter Avalos SyslogFacility val; 7418de8d7fSPeter Avalos } log_facilities[] = { 7518de8d7fSPeter Avalos { "DAEMON", SYSLOG_FACILITY_DAEMON }, 7618de8d7fSPeter Avalos { "USER", SYSLOG_FACILITY_USER }, 7718de8d7fSPeter Avalos { "AUTH", SYSLOG_FACILITY_AUTH }, 7818de8d7fSPeter Avalos #ifdef LOG_AUTHPRIV 7918de8d7fSPeter Avalos { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, 8018de8d7fSPeter Avalos #endif 8118de8d7fSPeter Avalos { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, 8218de8d7fSPeter Avalos { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, 8318de8d7fSPeter Avalos { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, 8418de8d7fSPeter Avalos { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, 8518de8d7fSPeter Avalos { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, 8618de8d7fSPeter Avalos { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, 8718de8d7fSPeter Avalos { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, 8818de8d7fSPeter Avalos { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, 8918de8d7fSPeter Avalos { NULL, SYSLOG_FACILITY_NOT_SET } 9018de8d7fSPeter Avalos }; 9118de8d7fSPeter Avalos 9218de8d7fSPeter Avalos static struct { 9318de8d7fSPeter Avalos const char *name; 9418de8d7fSPeter Avalos LogLevel val; 9518de8d7fSPeter Avalos } log_levels[] = 9618de8d7fSPeter Avalos { 9718de8d7fSPeter Avalos { "QUIET", SYSLOG_LEVEL_QUIET }, 9818de8d7fSPeter Avalos { "FATAL", SYSLOG_LEVEL_FATAL }, 9918de8d7fSPeter Avalos { "ERROR", SYSLOG_LEVEL_ERROR }, 10018de8d7fSPeter Avalos { "INFO", SYSLOG_LEVEL_INFO }, 10118de8d7fSPeter Avalos { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 10218de8d7fSPeter Avalos { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, 10318de8d7fSPeter Avalos { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 10418de8d7fSPeter Avalos { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 10518de8d7fSPeter Avalos { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 10618de8d7fSPeter Avalos { NULL, SYSLOG_LEVEL_NOT_SET } 10718de8d7fSPeter Avalos }; 10818de8d7fSPeter Avalos 10918de8d7fSPeter Avalos SyslogFacility 11018de8d7fSPeter Avalos log_facility_number(char *name) 11118de8d7fSPeter Avalos { 11218de8d7fSPeter Avalos int i; 11318de8d7fSPeter Avalos 11418de8d7fSPeter Avalos if (name != NULL) 11518de8d7fSPeter Avalos for (i = 0; log_facilities[i].name; i++) 11618de8d7fSPeter Avalos if (strcasecmp(log_facilities[i].name, name) == 0) 11718de8d7fSPeter Avalos return log_facilities[i].val; 11818de8d7fSPeter Avalos return SYSLOG_FACILITY_NOT_SET; 11918de8d7fSPeter Avalos } 12018de8d7fSPeter Avalos 12118de8d7fSPeter Avalos const char * 12218de8d7fSPeter Avalos log_facility_name(SyslogFacility facility) 12318de8d7fSPeter Avalos { 12418de8d7fSPeter Avalos u_int i; 12518de8d7fSPeter Avalos 12618de8d7fSPeter Avalos for (i = 0; log_facilities[i].name; i++) 12718de8d7fSPeter Avalos if (log_facilities[i].val == facility) 12818de8d7fSPeter Avalos return log_facilities[i].name; 12918de8d7fSPeter Avalos return NULL; 13018de8d7fSPeter Avalos } 13118de8d7fSPeter Avalos 13218de8d7fSPeter Avalos LogLevel 13318de8d7fSPeter Avalos log_level_number(char *name) 13418de8d7fSPeter Avalos { 13518de8d7fSPeter Avalos int i; 13618de8d7fSPeter Avalos 13718de8d7fSPeter Avalos if (name != NULL) 13818de8d7fSPeter Avalos for (i = 0; log_levels[i].name; i++) 13918de8d7fSPeter Avalos if (strcasecmp(log_levels[i].name, name) == 0) 14018de8d7fSPeter Avalos return log_levels[i].val; 14118de8d7fSPeter Avalos return SYSLOG_LEVEL_NOT_SET; 14218de8d7fSPeter Avalos } 14318de8d7fSPeter Avalos 14418de8d7fSPeter Avalos const char * 14518de8d7fSPeter Avalos log_level_name(LogLevel level) 14618de8d7fSPeter Avalos { 14718de8d7fSPeter Avalos u_int i; 14818de8d7fSPeter Avalos 14918de8d7fSPeter Avalos for (i = 0; log_levels[i].name != NULL; i++) 15018de8d7fSPeter Avalos if (log_levels[i].val == level) 15118de8d7fSPeter Avalos return log_levels[i].name; 15218de8d7fSPeter Avalos return NULL; 15318de8d7fSPeter Avalos } 15418de8d7fSPeter Avalos 15518de8d7fSPeter Avalos /* Error messages that should be logged. */ 15618de8d7fSPeter Avalos 15718de8d7fSPeter Avalos void 15818de8d7fSPeter Avalos error(const char *fmt,...) 15918de8d7fSPeter Avalos { 16018de8d7fSPeter Avalos va_list args; 16118de8d7fSPeter Avalos 16218de8d7fSPeter Avalos va_start(args, fmt); 16318de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_ERROR, fmt, args); 16418de8d7fSPeter Avalos va_end(args); 16518de8d7fSPeter Avalos } 16618de8d7fSPeter Avalos 16718de8d7fSPeter Avalos void 16818de8d7fSPeter Avalos sigdie(const char *fmt,...) 16918de8d7fSPeter Avalos { 17018de8d7fSPeter Avalos #ifdef DO_LOG_SAFE_IN_SIGHAND 17118de8d7fSPeter Avalos va_list args; 17218de8d7fSPeter Avalos 17318de8d7fSPeter Avalos va_start(args, fmt); 17418de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_FATAL, fmt, args); 17518de8d7fSPeter Avalos va_end(args); 17618de8d7fSPeter Avalos #endif 17718de8d7fSPeter Avalos _exit(1); 17818de8d7fSPeter Avalos } 17918de8d7fSPeter Avalos 18018de8d7fSPeter Avalos 18118de8d7fSPeter Avalos /* Log this message (information that usually should go to the log). */ 18218de8d7fSPeter Avalos 18318de8d7fSPeter Avalos void 18418de8d7fSPeter Avalos logit(const char *fmt,...) 18518de8d7fSPeter Avalos { 18618de8d7fSPeter Avalos va_list args; 18718de8d7fSPeter Avalos 18818de8d7fSPeter Avalos va_start(args, fmt); 18918de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_INFO, fmt, args); 19018de8d7fSPeter Avalos va_end(args); 19118de8d7fSPeter Avalos } 19218de8d7fSPeter Avalos 19318de8d7fSPeter Avalos /* More detailed messages (information that does not need to go to the log). */ 19418de8d7fSPeter Avalos 19518de8d7fSPeter Avalos void 19618de8d7fSPeter Avalos verbose(const char *fmt,...) 19718de8d7fSPeter Avalos { 19818de8d7fSPeter Avalos va_list args; 19918de8d7fSPeter Avalos 20018de8d7fSPeter Avalos va_start(args, fmt); 20118de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); 20218de8d7fSPeter Avalos va_end(args); 20318de8d7fSPeter Avalos } 20418de8d7fSPeter Avalos 20518de8d7fSPeter Avalos /* Debugging messages that should not be logged during normal operation. */ 20618de8d7fSPeter Avalos 20718de8d7fSPeter Avalos void 20818de8d7fSPeter Avalos debug(const char *fmt,...) 20918de8d7fSPeter Avalos { 21018de8d7fSPeter Avalos va_list args; 21118de8d7fSPeter Avalos 21218de8d7fSPeter Avalos va_start(args, fmt); 21318de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); 21418de8d7fSPeter Avalos va_end(args); 21518de8d7fSPeter Avalos } 21618de8d7fSPeter Avalos 21718de8d7fSPeter Avalos void 21818de8d7fSPeter Avalos debug2(const char *fmt,...) 21918de8d7fSPeter Avalos { 22018de8d7fSPeter Avalos va_list args; 22118de8d7fSPeter Avalos 22218de8d7fSPeter Avalos va_start(args, fmt); 22318de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); 22418de8d7fSPeter Avalos va_end(args); 22518de8d7fSPeter Avalos } 22618de8d7fSPeter Avalos 22718de8d7fSPeter Avalos void 22818de8d7fSPeter Avalos debug3(const char *fmt,...) 22918de8d7fSPeter Avalos { 23018de8d7fSPeter Avalos va_list args; 23118de8d7fSPeter Avalos 23218de8d7fSPeter Avalos va_start(args, fmt); 23318de8d7fSPeter Avalos do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); 23418de8d7fSPeter Avalos va_end(args); 23518de8d7fSPeter Avalos } 23618de8d7fSPeter Avalos 23718de8d7fSPeter Avalos /* 23818de8d7fSPeter Avalos * Initialize the log. 23918de8d7fSPeter Avalos */ 24018de8d7fSPeter Avalos 24118de8d7fSPeter Avalos void 24218de8d7fSPeter Avalos log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) 24318de8d7fSPeter Avalos { 24418de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 24518de8d7fSPeter Avalos struct syslog_data sdata = SYSLOG_DATA_INIT; 24618de8d7fSPeter Avalos #endif 24718de8d7fSPeter Avalos 24818de8d7fSPeter Avalos argv0 = av0; 24918de8d7fSPeter Avalos 25018de8d7fSPeter Avalos switch (level) { 25118de8d7fSPeter Avalos case SYSLOG_LEVEL_QUIET: 25218de8d7fSPeter Avalos case SYSLOG_LEVEL_FATAL: 25318de8d7fSPeter Avalos case SYSLOG_LEVEL_ERROR: 25418de8d7fSPeter Avalos case SYSLOG_LEVEL_INFO: 25518de8d7fSPeter Avalos case SYSLOG_LEVEL_VERBOSE: 25618de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG1: 25718de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG2: 25818de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG3: 25918de8d7fSPeter Avalos log_level = level; 26018de8d7fSPeter Avalos break; 26118de8d7fSPeter Avalos default: 26218de8d7fSPeter Avalos fprintf(stderr, "Unrecognized internal syslog level code %d\n", 26318de8d7fSPeter Avalos (int) level); 26418de8d7fSPeter Avalos exit(1); 26518de8d7fSPeter Avalos } 26618de8d7fSPeter Avalos 2671c188a7fSPeter Avalos log_handler = NULL; 2681c188a7fSPeter Avalos log_handler_ctx = NULL; 2691c188a7fSPeter Avalos 27018de8d7fSPeter Avalos log_on_stderr = on_stderr; 27118de8d7fSPeter Avalos if (on_stderr) 27218de8d7fSPeter Avalos return; 27318de8d7fSPeter Avalos 27418de8d7fSPeter Avalos switch (facility) { 27518de8d7fSPeter Avalos case SYSLOG_FACILITY_DAEMON: 27618de8d7fSPeter Avalos log_facility = LOG_DAEMON; 27718de8d7fSPeter Avalos break; 27818de8d7fSPeter Avalos case SYSLOG_FACILITY_USER: 27918de8d7fSPeter Avalos log_facility = LOG_USER; 28018de8d7fSPeter Avalos break; 28118de8d7fSPeter Avalos case SYSLOG_FACILITY_AUTH: 28218de8d7fSPeter Avalos log_facility = LOG_AUTH; 28318de8d7fSPeter Avalos break; 28418de8d7fSPeter Avalos #ifdef LOG_AUTHPRIV 28518de8d7fSPeter Avalos case SYSLOG_FACILITY_AUTHPRIV: 28618de8d7fSPeter Avalos log_facility = LOG_AUTHPRIV; 28718de8d7fSPeter Avalos break; 28818de8d7fSPeter Avalos #endif 28918de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL0: 29018de8d7fSPeter Avalos log_facility = LOG_LOCAL0; 29118de8d7fSPeter Avalos break; 29218de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL1: 29318de8d7fSPeter Avalos log_facility = LOG_LOCAL1; 29418de8d7fSPeter Avalos break; 29518de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL2: 29618de8d7fSPeter Avalos log_facility = LOG_LOCAL2; 29718de8d7fSPeter Avalos break; 29818de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL3: 29918de8d7fSPeter Avalos log_facility = LOG_LOCAL3; 30018de8d7fSPeter Avalos break; 30118de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL4: 30218de8d7fSPeter Avalos log_facility = LOG_LOCAL4; 30318de8d7fSPeter Avalos break; 30418de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL5: 30518de8d7fSPeter Avalos log_facility = LOG_LOCAL5; 30618de8d7fSPeter Avalos break; 30718de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL6: 30818de8d7fSPeter Avalos log_facility = LOG_LOCAL6; 30918de8d7fSPeter Avalos break; 31018de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL7: 31118de8d7fSPeter Avalos log_facility = LOG_LOCAL7; 31218de8d7fSPeter Avalos break; 31318de8d7fSPeter Avalos default: 31418de8d7fSPeter Avalos fprintf(stderr, 31518de8d7fSPeter Avalos "Unrecognized internal syslog facility code %d\n", 31618de8d7fSPeter Avalos (int) facility); 31718de8d7fSPeter Avalos exit(1); 31818de8d7fSPeter Avalos } 31918de8d7fSPeter Avalos 32018de8d7fSPeter Avalos /* 32118de8d7fSPeter Avalos * If an external library (eg libwrap) attempts to use syslog 32218de8d7fSPeter Avalos * immediately after reexec, syslog may be pointing to the wrong 32318de8d7fSPeter Avalos * facility, so we force an open/close of syslog here. 32418de8d7fSPeter Avalos */ 32518de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 32618de8d7fSPeter Avalos openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 32718de8d7fSPeter Avalos closelog_r(&sdata); 32818de8d7fSPeter Avalos #else 32918de8d7fSPeter Avalos openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 33018de8d7fSPeter Avalos closelog(); 33118de8d7fSPeter Avalos #endif 33218de8d7fSPeter Avalos } 33318de8d7fSPeter Avalos 334*36e94dc5SPeter Avalos void 335*36e94dc5SPeter Avalos log_change_level(LogLevel new_log_level) 336*36e94dc5SPeter Avalos { 337*36e94dc5SPeter Avalos /* no-op if log_init has not been called */ 338*36e94dc5SPeter Avalos if (argv0 == NULL) 339*36e94dc5SPeter Avalos return; 340*36e94dc5SPeter Avalos log_init(argv0, new_log_level, log_facility, log_on_stderr); 341*36e94dc5SPeter Avalos } 342*36e94dc5SPeter Avalos 343*36e94dc5SPeter Avalos int 344*36e94dc5SPeter Avalos log_is_on_stderr(void) 345*36e94dc5SPeter Avalos { 346*36e94dc5SPeter Avalos return log_on_stderr; 347*36e94dc5SPeter Avalos } 348*36e94dc5SPeter Avalos 349*36e94dc5SPeter Avalos /* redirect what would usually get written to stderr to specified file */ 350*36e94dc5SPeter Avalos void 351*36e94dc5SPeter Avalos log_redirect_stderr_to(const char *logfile) 352*36e94dc5SPeter Avalos { 353*36e94dc5SPeter Avalos int fd; 354*36e94dc5SPeter Avalos 355*36e94dc5SPeter Avalos if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) { 356*36e94dc5SPeter Avalos fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile, 357*36e94dc5SPeter Avalos strerror(errno)); 358*36e94dc5SPeter Avalos exit(1); 359*36e94dc5SPeter Avalos } 360*36e94dc5SPeter Avalos log_stderr_fd = fd; 361*36e94dc5SPeter Avalos } 362*36e94dc5SPeter Avalos 36318de8d7fSPeter Avalos #define MSGBUFSIZ 1024 36418de8d7fSPeter Avalos 36518de8d7fSPeter Avalos void 3661c188a7fSPeter Avalos set_log_handler(log_handler_fn *handler, void *ctx) 3671c188a7fSPeter Avalos { 3681c188a7fSPeter Avalos log_handler = handler; 3691c188a7fSPeter Avalos log_handler_ctx = ctx; 3701c188a7fSPeter Avalos } 3711c188a7fSPeter Avalos 3721c188a7fSPeter Avalos void 3731c188a7fSPeter Avalos do_log2(LogLevel level, const char *fmt,...) 3741c188a7fSPeter Avalos { 3751c188a7fSPeter Avalos va_list args; 3761c188a7fSPeter Avalos 3771c188a7fSPeter Avalos va_start(args, fmt); 3781c188a7fSPeter Avalos do_log(level, fmt, args); 3791c188a7fSPeter Avalos va_end(args); 3801c188a7fSPeter Avalos } 3811c188a7fSPeter Avalos 3821c188a7fSPeter Avalos void 38318de8d7fSPeter Avalos do_log(LogLevel level, const char *fmt, va_list args) 38418de8d7fSPeter Avalos { 38518de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 38618de8d7fSPeter Avalos struct syslog_data sdata = SYSLOG_DATA_INIT; 38718de8d7fSPeter Avalos #endif 38818de8d7fSPeter Avalos char msgbuf[MSGBUFSIZ]; 38918de8d7fSPeter Avalos char fmtbuf[MSGBUFSIZ]; 39018de8d7fSPeter Avalos char *txt = NULL; 39118de8d7fSPeter Avalos int pri = LOG_INFO; 39218de8d7fSPeter Avalos int saved_errno = errno; 3931c188a7fSPeter Avalos log_handler_fn *tmp_handler; 39418de8d7fSPeter Avalos 39518de8d7fSPeter Avalos if (level > log_level) 39618de8d7fSPeter Avalos return; 39718de8d7fSPeter Avalos 39818de8d7fSPeter Avalos switch (level) { 39918de8d7fSPeter Avalos case SYSLOG_LEVEL_FATAL: 40018de8d7fSPeter Avalos if (!log_on_stderr) 40118de8d7fSPeter Avalos txt = "fatal"; 40218de8d7fSPeter Avalos pri = LOG_CRIT; 40318de8d7fSPeter Avalos break; 40418de8d7fSPeter Avalos case SYSLOG_LEVEL_ERROR: 40518de8d7fSPeter Avalos if (!log_on_stderr) 40618de8d7fSPeter Avalos txt = "error"; 40718de8d7fSPeter Avalos pri = LOG_ERR; 40818de8d7fSPeter Avalos break; 40918de8d7fSPeter Avalos case SYSLOG_LEVEL_INFO: 41018de8d7fSPeter Avalos pri = LOG_INFO; 41118de8d7fSPeter Avalos break; 41218de8d7fSPeter Avalos case SYSLOG_LEVEL_VERBOSE: 41318de8d7fSPeter Avalos pri = LOG_INFO; 41418de8d7fSPeter Avalos break; 41518de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG1: 41618de8d7fSPeter Avalos txt = "debug1"; 41718de8d7fSPeter Avalos pri = LOG_DEBUG; 41818de8d7fSPeter Avalos break; 41918de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG2: 42018de8d7fSPeter Avalos txt = "debug2"; 42118de8d7fSPeter Avalos pri = LOG_DEBUG; 42218de8d7fSPeter Avalos break; 42318de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG3: 42418de8d7fSPeter Avalos txt = "debug3"; 42518de8d7fSPeter Avalos pri = LOG_DEBUG; 42618de8d7fSPeter Avalos break; 42718de8d7fSPeter Avalos default: 42818de8d7fSPeter Avalos txt = "internal error"; 42918de8d7fSPeter Avalos pri = LOG_ERR; 43018de8d7fSPeter Avalos break; 43118de8d7fSPeter Avalos } 4321c188a7fSPeter Avalos if (txt != NULL && log_handler == NULL) { 43318de8d7fSPeter Avalos snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); 43418de8d7fSPeter Avalos vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); 43518de8d7fSPeter Avalos } else { 43618de8d7fSPeter Avalos vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); 43718de8d7fSPeter Avalos } 43818de8d7fSPeter Avalos strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), 43918de8d7fSPeter Avalos log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); 4401c188a7fSPeter Avalos if (log_handler != NULL) { 4411c188a7fSPeter Avalos /* Avoid recursion */ 4421c188a7fSPeter Avalos tmp_handler = log_handler; 4431c188a7fSPeter Avalos log_handler = NULL; 4441c188a7fSPeter Avalos tmp_handler(level, fmtbuf, log_handler_ctx); 4451c188a7fSPeter Avalos log_handler = tmp_handler; 4461c188a7fSPeter Avalos } else if (log_on_stderr) { 44718de8d7fSPeter Avalos snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); 448*36e94dc5SPeter Avalos (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); 44918de8d7fSPeter Avalos } else { 45018de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 45118de8d7fSPeter Avalos openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 45218de8d7fSPeter Avalos syslog_r(pri, &sdata, "%.500s", fmtbuf); 45318de8d7fSPeter Avalos closelog_r(&sdata); 45418de8d7fSPeter Avalos #else 45518de8d7fSPeter Avalos openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 45618de8d7fSPeter Avalos syslog(pri, "%.500s", fmtbuf); 45718de8d7fSPeter Avalos closelog(); 45818de8d7fSPeter Avalos #endif 45918de8d7fSPeter Avalos } 46018de8d7fSPeter Avalos errno = saved_errno; 46118de8d7fSPeter Avalos } 462