X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/20244695afc42ee15576f0232a90879d53953f3a..HEAD:/log.c diff --git a/log.c b/log.c index c9c1631c..4a8239b9 100644 --- a/log.c +++ b/log.c @@ -1,3 +1,4 @@ +/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,12 +35,22 @@ */ #include "includes.h" -RCSID("$OpenBSD: log.c,v 1.17 2001/03/04 17:42:28 millert Exp $"); -#include "log.h" -#include "xmalloc.h" +#include +#include +#include +#include +#include #include +#include +#include +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) +# include +#endif + +#include "xmalloc.h" +#include "log.h" static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; @@ -48,6 +59,9 @@ static char *argv0; extern char *__progname; +#define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) +#define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) + /* textual representation of log-facilities/levels */ static struct { @@ -57,6 +71,9 @@ static struct { { "DAEMON", SYSLOG_FACILITY_DAEMON }, { "USER", SYSLOG_FACILITY_USER }, { "AUTH", SYSLOG_FACILITY_AUTH }, +#ifdef LOG_AUTHPRIV + { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, +#endif { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, @@ -65,7 +82,7 @@ static struct { { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, - { NULL, 0 } + { NULL, SYSLOG_FACILITY_NOT_SET } }; static struct { @@ -82,40 +99,53 @@ static struct { { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, - { NULL, 0 } + { NULL, SYSLOG_LEVEL_NOT_SET } }; SyslogFacility log_facility_number(char *name) { int i; + if (name != NULL) for (i = 0; log_facilities[i].name; i++) if (strcasecmp(log_facilities[i].name, name) == 0) return log_facilities[i].val; - return (SyslogFacility) - 1; + return SYSLOG_FACILITY_NOT_SET; +} + +const char * +log_facility_name(SyslogFacility facility) +{ + u_int i; + + for (i = 0; log_facilities[i].name; i++) + if (log_facilities[i].val == facility) + return log_facilities[i].name; + return NULL; } LogLevel log_level_number(char *name) { int i; + if (name != NULL) for (i = 0; log_levels[i].name; i++) if (strcasecmp(log_levels[i].name, name) == 0) return log_levels[i].val; - return (LogLevel) - 1; + return SYSLOG_LEVEL_NOT_SET; } -/* Fatal messages. This function never returns. */ -void -fatal(const char *fmt,...) +const char * +log_level_name(LogLevel level) { - va_list args; - va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); - va_end(args); - fatal_cleanup(); + u_int i; + + for (i = 0; log_levels[i].name != NULL; i++) + if (log_levels[i].val == level) + return log_levels[i].name; + return NULL; } /* Error messages that should be logged. */ @@ -124,17 +154,33 @@ void error(const char *fmt,...) { va_list args; + va_start(args, fmt); do_log(SYSLOG_LEVEL_ERROR, fmt, args); va_end(args); } +void +sigdie(const char *fmt,...) +{ +#ifdef DO_LOG_SAFE_IN_SIGHAND + va_list args; + + va_start(args, fmt); + do_log(SYSLOG_LEVEL_FATAL, fmt, args); + va_end(args); +#endif + _exit(1); +} + + /* Log this message (information that usually should go to the log). */ void -log(const char *fmt,...) +logit(const char *fmt,...) { va_list args; + va_start(args, fmt); do_log(SYSLOG_LEVEL_INFO, fmt, args); va_end(args); @@ -146,6 +192,7 @@ void verbose(const char *fmt,...) { va_list args; + va_start(args, fmt); do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); va_end(args); @@ -157,6 +204,7 @@ void debug(const char *fmt,...) { va_list args; + va_start(args, fmt); do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); va_end(args); @@ -166,6 +214,7 @@ void debug2(const char *fmt,...) { va_list args; + va_start(args, fmt); do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); va_end(args); @@ -175,75 +224,12 @@ void debug3(const char *fmt,...) { va_list args; + va_start(args, fmt); do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); va_end(args); } -/* Fatal cleanup */ - -struct fatal_cleanup { - struct fatal_cleanup *next; - void (*proc) (void *); - void *context; -}; - -static struct fatal_cleanup *fatal_cleanups = NULL; - -/* Registers a cleanup function to be called by fatal() before exiting. */ - -void -fatal_add_cleanup(void (*proc) (void *), void *context) -{ - struct fatal_cleanup *cu; - - cu = xmalloc(sizeof(*cu)); - cu->proc = proc; - cu->context = context; - cu->next = fatal_cleanups; - fatal_cleanups = cu; -} - -/* Removes a cleanup frunction to be called at fatal(). */ - -void -fatal_remove_cleanup(void (*proc) (void *context), void *context) -{ - struct fatal_cleanup **cup, *cu; - - for (cup = &fatal_cleanups; *cup; cup = &cu->next) { - cu = *cup; - if (cu->proc == proc && cu->context == context) { - *cup = cu->next; - xfree(cu); - return; - } - } - fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx", - (u_long) proc, (u_long) context); -} - -/* Cleanup and exit */ -void -fatal_cleanup(void) -{ - struct fatal_cleanup *cu, *next_cu; - static int called = 0; - - if (called) - exit(255); - called = 1; - /* Call cleanup functions. */ - for (cu = fatal_cleanups; cu; cu = next_cu) { - next_cu = cu->next; - debug("Calling cleanup 0x%lx(0x%lx)", - (u_long) cu->proc, (u_long) cu->context); - (*cu->proc) (cu->context); - } - exit(255); -} - - /* * Initialize the log. */ @@ -251,6 +237,10 @@ fatal_cleanup(void) void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) { +#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) + struct syslog_data sdata = SYSLOG_DATA_INIT; +#endif + argv0 = av0; switch (level) { @@ -284,10 +274,10 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) case SYSLOG_FACILITY_AUTH: log_facility = LOG_AUTH; break; -#ifdef LOG_AUTHPRIV /** BAL: Verify */ - case SYSLOG_FACILITY_AUTHPRIV - log_facility = AUTHPRIV; - break +#ifdef LOG_AUTHPRIV + case SYSLOG_FACILITY_AUTHPRIV: + log_facility = LOG_AUTHPRIV; + break; #endif case SYSLOG_FACILITY_LOCAL0: log_facility = LOG_LOCAL0; @@ -319,6 +309,19 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) (int) facility); exit(1); } + + /* + * If an external library (eg libwrap) attempts to use syslog + * immediately after reexec, syslog may be pointing to the wrong + * facility, so we force an open/close of syslog here. + */ +#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) + openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); + closelog_r(&sdata); +#else + openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); + closelog(); +#endif } #define MSGBUFSIZ 1024 @@ -326,10 +329,14 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) void do_log(LogLevel level, const char *fmt, va_list args) { +#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) + struct syslog_data sdata = SYSLOG_DATA_INIT; +#endif char msgbuf[MSGBUFSIZ]; char fmtbuf[MSGBUFSIZ]; char *txt = NULL; int pri = LOG_INFO; + int saved_errno = errno; if (level > log_level) return; @@ -374,11 +381,21 @@ do_log(LogLevel level, const char *fmt, va_list args) } else { vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); } + strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), + log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); if (log_on_stderr) { - fprintf(stderr, "%s\r\n", msgbuf); + snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); + write(STDERR_FILENO, msgbuf, strlen(msgbuf)); } else { +#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) + openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); + syslog_r(pri, &sdata, "%.500s", fmtbuf); + closelog_r(&sdata); +#else openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); - syslog(pri, "%.500s", msgbuf); + syslog(pri, "%.500s", fmtbuf); closelog(); +#endif } + errno = saved_errno; }