version 1.7.2.3, 2001/03/21 18:52:49 |
version 1.8, 2000/09/07 20:27:52 |
|
|
/* |
/* |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Shared versions of debug(), log(), etc. |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
|
* All rights reserved |
|
* |
* |
* As far as I am concerned, the code I have written for this software |
|
* can be used freely for any purpose. Any derived versions of this |
|
* software must be clearly marked as such, and if the derived work is |
|
* incompatible with the protocol description in the RFC file, it must be |
|
* called by a name other than "ssh" or "Secure Shell". |
|
*/ |
|
/* |
|
* Copyright (c) 2000 Markus Friedl. All rights reserved. |
* Copyright (c) 2000 Markus Friedl. All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
|
|
#include "includes.h" |
#include "includes.h" |
RCSID("$OpenBSD$"); |
RCSID("$OpenBSD$"); |
|
|
#include "log.h" |
#include "ssh.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
|
|
#include <syslog.h> |
|
|
|
static LogLevel log_level = SYSLOG_LEVEL_INFO; |
|
static int log_on_stderr = 1; |
|
static int log_facility = LOG_AUTH; |
|
static char *argv0; |
|
|
|
extern char *__progname; |
|
|
|
/* textual representation of log-facilities/levels */ |
|
|
|
static struct { |
|
const char *name; |
|
SyslogFacility val; |
|
} log_facilities[] = { |
|
{ "DAEMON", SYSLOG_FACILITY_DAEMON }, |
|
{ "USER", SYSLOG_FACILITY_USER }, |
|
{ "AUTH", SYSLOG_FACILITY_AUTH }, |
|
{ "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, |
|
{ "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, |
|
{ "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, |
|
{ "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, |
|
{ "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, |
|
{ "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, |
|
{ "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, |
|
{ "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, |
|
{ NULL, 0 } |
|
}; |
|
|
|
static struct { |
|
const char *name; |
|
LogLevel val; |
|
} log_levels[] = |
|
{ |
|
{ "QUIET", SYSLOG_LEVEL_QUIET }, |
|
{ "FATAL", SYSLOG_LEVEL_FATAL }, |
|
{ "ERROR", SYSLOG_LEVEL_ERROR }, |
|
{ "INFO", SYSLOG_LEVEL_INFO }, |
|
{ "VERBOSE", SYSLOG_LEVEL_VERBOSE }, |
|
{ "DEBUG", SYSLOG_LEVEL_DEBUG1 }, |
|
{ "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, |
|
{ "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, |
|
{ "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, |
|
{ NULL, 0 } |
|
}; |
|
|
|
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; |
|
} |
|
|
|
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; |
|
} |
|
/* Fatal messages. This function never returns. */ |
/* Fatal messages. This function never returns. */ |
|
|
void |
void |
|
|
{ |
{ |
va_list args; |
va_list args; |
va_start(args, fmt); |
va_start(args, fmt); |
do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); |
do_log(SYSLOG_LEVEL_DEBUG, fmt, args); |
va_end(args); |
va_end(args); |
} |
} |
|
|
void |
|
debug2(const char *fmt,...) |
|
{ |
|
va_list args; |
|
va_start(args, fmt); |
|
do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); |
|
va_end(args); |
|
} |
|
|
|
void |
|
debug3(const char *fmt,...) |
|
{ |
|
va_list args; |
|
va_start(args, fmt); |
|
do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); |
|
va_end(args); |
|
} |
|
|
|
/* Fatal cleanup */ |
/* Fatal cleanup */ |
|
|
struct fatal_cleanup { |
struct fatal_cleanup { |
|
|
return; |
return; |
} |
} |
} |
} |
fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx", |
fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n", |
(u_long) proc, (u_long) context); |
(unsigned long) proc, (unsigned long) context); |
} |
} |
|
|
/* Cleanup and exit */ |
/* Cleanup and exit */ |
|
|
for (cu = fatal_cleanups; cu; cu = next_cu) { |
for (cu = fatal_cleanups; cu; cu = next_cu) { |
next_cu = cu->next; |
next_cu = cu->next; |
debug("Calling cleanup 0x%lx(0x%lx)", |
debug("Calling cleanup 0x%lx(0x%lx)", |
(u_long) cu->proc, (u_long) cu->context); |
(unsigned long) cu->proc, (unsigned long) cu->context); |
(*cu->proc) (cu->context); |
(*cu->proc) (cu->context); |
} |
} |
exit(255); |
exit(255); |
} |
} |
|
|
|
/* textual representation of log-facilities/levels */ |
|
|
/* |
static struct { |
* Initialize the log. |
const char *name; |
*/ |
SyslogFacility val; |
|
} log_facilities[] = { |
|
{ "DAEMON", SYSLOG_FACILITY_DAEMON }, |
|
{ "USER", SYSLOG_FACILITY_USER }, |
|
{ "AUTH", SYSLOG_FACILITY_AUTH }, |
|
{ "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, |
|
{ "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, |
|
{ "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, |
|
{ "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, |
|
{ "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, |
|
{ "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, |
|
{ "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, |
|
{ "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, |
|
{ NULL, 0 } |
|
}; |
|
|
void |
static struct { |
log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) |
const char *name; |
|
LogLevel val; |
|
} log_levels[] = |
{ |
{ |
argv0 = av0; |
{ "QUIET", SYSLOG_LEVEL_QUIET }, |
|
{ "FATAL", SYSLOG_LEVEL_FATAL }, |
|
{ "ERROR", SYSLOG_LEVEL_ERROR }, |
|
{ "INFO", SYSLOG_LEVEL_INFO }, |
|
{ "VERBOSE", SYSLOG_LEVEL_VERBOSE }, |
|
{ "DEBUG", SYSLOG_LEVEL_DEBUG }, |
|
{ NULL, 0 } |
|
}; |
|
|
switch (level) { |
SyslogFacility |
case SYSLOG_LEVEL_QUIET: |
log_facility_number(char *name) |
case SYSLOG_LEVEL_FATAL: |
{ |
case SYSLOG_LEVEL_ERROR: |
int i; |
case SYSLOG_LEVEL_INFO: |
if (name != NULL) |
case SYSLOG_LEVEL_VERBOSE: |
for (i = 0; log_facilities[i].name; i++) |
case SYSLOG_LEVEL_DEBUG1: |
if (strcasecmp(log_facilities[i].name, name) == 0) |
case SYSLOG_LEVEL_DEBUG2: |
return log_facilities[i].val; |
case SYSLOG_LEVEL_DEBUG3: |
return (SyslogFacility) - 1; |
log_level = level; |
|
break; |
|
default: |
|
fprintf(stderr, "Unrecognized internal syslog level code %d\n", |
|
(int) level); |
|
exit(1); |
|
} |
|
|
|
log_on_stderr = on_stderr; |
|
if (on_stderr) |
|
return; |
|
|
|
switch (facility) { |
|
case SYSLOG_FACILITY_DAEMON: |
|
log_facility = LOG_DAEMON; |
|
break; |
|
case SYSLOG_FACILITY_USER: |
|
log_facility = LOG_USER; |
|
break; |
|
case SYSLOG_FACILITY_AUTH: |
|
log_facility = LOG_AUTH; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL0: |
|
log_facility = LOG_LOCAL0; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL1: |
|
log_facility = LOG_LOCAL1; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL2: |
|
log_facility = LOG_LOCAL2; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL3: |
|
log_facility = LOG_LOCAL3; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL4: |
|
log_facility = LOG_LOCAL4; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL5: |
|
log_facility = LOG_LOCAL5; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL6: |
|
log_facility = LOG_LOCAL6; |
|
break; |
|
case SYSLOG_FACILITY_LOCAL7: |
|
log_facility = LOG_LOCAL7; |
|
break; |
|
default: |
|
fprintf(stderr, |
|
"Unrecognized internal syslog facility code %d\n", |
|
(int) facility); |
|
exit(1); |
|
} |
|
} |
} |
|
|
#define MSGBUFSIZ 1024 |
LogLevel |
|
log_level_number(char *name) |
void |
|
do_log(LogLevel level, const char *fmt, va_list args) |
|
{ |
{ |
char msgbuf[MSGBUFSIZ]; |
int i; |
char fmtbuf[MSGBUFSIZ]; |
if (name != NULL) |
char *txt = NULL; |
for (i = 0; log_levels[i].name; i++) |
int pri = LOG_INFO; |
if (strcasecmp(log_levels[i].name, name) == 0) |
|
return log_levels[i].val; |
if (level > log_level) |
return (LogLevel) - 1; |
return; |
|
|
|
switch (level) { |
|
case SYSLOG_LEVEL_FATAL: |
|
if (!log_on_stderr) |
|
txt = "fatal"; |
|
pri = LOG_CRIT; |
|
break; |
|
case SYSLOG_LEVEL_ERROR: |
|
if (!log_on_stderr) |
|
txt = "error"; |
|
pri = LOG_ERR; |
|
break; |
|
case SYSLOG_LEVEL_INFO: |
|
pri = LOG_INFO; |
|
break; |
|
case SYSLOG_LEVEL_VERBOSE: |
|
pri = LOG_INFO; |
|
break; |
|
case SYSLOG_LEVEL_DEBUG1: |
|
txt = "debug1"; |
|
pri = LOG_DEBUG; |
|
break; |
|
case SYSLOG_LEVEL_DEBUG2: |
|
txt = "debug2"; |
|
pri = LOG_DEBUG; |
|
break; |
|
case SYSLOG_LEVEL_DEBUG3: |
|
txt = "debug3"; |
|
pri = LOG_DEBUG; |
|
break; |
|
default: |
|
txt = "internal error"; |
|
pri = LOG_ERR; |
|
break; |
|
} |
|
if (txt != NULL) { |
|
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); |
|
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); |
|
} else { |
|
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); |
|
} |
|
if (log_on_stderr) { |
|
fprintf(stderr, "%s\r\n", msgbuf); |
|
} else { |
|
openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); |
|
syslog(pri, "%.500s", msgbuf); |
|
closelog(); |
|
} |
|
} |
} |