version 1.6, 1999/11/10 22:24:01 |
version 1.7, 1999/11/10 23:36:44 |
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "ssh.h" |
#include "ssh.h" |
|
|
static int log_debug = 0; |
static LogLevel log_level = SYSLOG_LEVEL_INFO; |
static int log_quiet = 0; |
|
static int log_on_stderr = 0; |
static int log_on_stderr = 0; |
|
|
/* Initialize the log. |
/* Initialize the log. |
av0 program name (should be argv[0]) |
av0 program name (should be argv[0]) |
on_stderr print also on stderr |
on_stderr print also on stderr |
debug send debugging messages to system log |
level logging level |
quiet don\'t log anything |
|
*/ |
*/ |
|
|
void log_init(char *av0, int on_stderr, int debug, int quiet, |
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) |
SyslogFacility facility) |
|
{ |
{ |
int log_facility; |
int log_facility; |
|
|
|
switch (level) |
|
{ |
|
case SYSLOG_LEVEL_QUIET: |
|
case SYSLOG_LEVEL_ERROR: |
|
case SYSLOG_LEVEL_FATAL: |
|
case SYSLOG_LEVEL_INFO: |
|
case SYSLOG_LEVEL_CHAT: |
|
case SYSLOG_LEVEL_DEBUG: |
|
log_level = level; |
|
break; |
|
default: |
|
fprintf(stderr, "Unrecognized internal syslog level code %d\n", |
|
(int)level); |
|
exit(1); |
|
} |
|
|
switch (facility) |
switch (facility) |
{ |
{ |
case SYSLOG_FACILITY_DAEMON: |
case SYSLOG_FACILITY_DAEMON: |
|
|
exit(1); |
exit(1); |
} |
} |
|
|
log_debug = debug; |
|
log_quiet = quiet; |
|
log_on_stderr = on_stderr; |
log_on_stderr = on_stderr; |
closelog(); /* Close any previous log. */ |
closelog(); /* Close any previous log. */ |
openlog(av0, LOG_PID, log_facility); |
openlog(av0, LOG_PID, log_facility); |
|
|
|
|
#define MSGBUFSIZE 1024 |
#define MSGBUFSIZE 1024 |
|
|
#define DECL_MSGBUF char msgbuf[MSGBUFSIZE] |
void |
|
do_log(LogLevel level, const char *fmt, va_list args) |
/* Log this message (information that usually should go to the log). */ |
|
|
|
void log(const char *fmt, ...) |
|
{ |
{ |
va_list args; |
char msgbuf[MSGBUFSIZE]; |
DECL_MSGBUF; |
char fmtbuf[MSGBUFSIZE]; |
if (log_quiet) |
char *txt = NULL; |
return; |
int pri = LOG_INFO; |
va_start(args, fmt); |
|
vsnprintf(msgbuf, MSGBUFSIZE, fmt, args); |
|
va_end(args); |
|
if (log_on_stderr) |
|
fprintf(stderr, "log: %s\n", msgbuf); |
|
syslog(LOG_INFO, "log: %.500s", msgbuf); |
|
} |
|
|
|
/* Debugging messages that should not be logged during normal operation. */ |
if (level > log_level) |
|
|
void debug(const char *fmt, ...) |
|
{ |
|
va_list args; |
|
DECL_MSGBUF; |
|
if (!log_debug || log_quiet) |
|
return; |
return; |
va_start(args, fmt); |
switch (level) |
vsnprintf(msgbuf, MSGBUFSIZE, fmt, args); |
|
va_end(args); |
|
if (log_on_stderr) |
|
fprintf(stderr, "debug: %s\n", msgbuf); |
|
syslog(LOG_DEBUG, "debug: %.500s", msgbuf); |
|
} |
|
|
|
/* Error messages that should be logged. */ |
|
|
|
void error(const char *fmt, ...) |
|
{ |
|
va_list args; |
|
DECL_MSGBUF; |
|
if (log_quiet) |
|
return; |
|
va_start(args, fmt); |
|
vsnprintf(msgbuf, MSGBUFSIZE, fmt, args); |
|
va_end(args); |
|
if (log_on_stderr) |
|
fprintf(stderr, "error: %s\n", msgbuf); |
|
syslog(LOG_ERR, "error: %.500s", msgbuf); |
|
} |
|
|
|
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; |
case SYSLOG_LEVEL_ERROR: |
if (cu->proc == proc && cu->context == context) |
txt = "error"; |
{ |
pri = LOG_ERR; |
*cup = cu->next; |
break; |
xfree(cu); |
case SYSLOG_LEVEL_FATAL: |
return; |
txt = "fatal"; |
} |
pri = LOG_ERR; |
|
break; |
|
case SYSLOG_LEVEL_INFO: |
|
pri = LOG_INFO; |
|
break; |
|
case SYSLOG_LEVEL_CHAT: |
|
pri = LOG_INFO; |
|
break; |
|
case SYSLOG_LEVEL_DEBUG: |
|
txt = "debug"; |
|
pri = LOG_DEBUG; |
|
break; |
|
default: |
|
txt = "internal error"; |
|
pri = LOG_ERR; |
|
break; |
} |
} |
fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n", |
|
(unsigned long)proc, (unsigned long)context); |
|
} |
|
|
|
/* Fatal messages. This function never returns. */ |
if (txt != NULL) { |
|
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); |
void fatal(const char *fmt, ...) |
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); |
{ |
}else{ |
va_list args; |
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); |
struct fatal_cleanup *cu, *next_cu; |
|
static int fatal_called = 0; |
|
DECL_MSGBUF; |
|
|
|
if (!log_quiet) { |
|
va_start(args, fmt); |
|
vsnprintf(msgbuf, MSGBUFSIZE, fmt, args); |
|
va_end(args); |
|
if (log_on_stderr) |
|
fprintf(stderr, "fatal: %s\n", msgbuf); |
|
syslog(LOG_ERR, "fatal: %.500s", msgbuf); |
|
} |
} |
|
if (log_on_stderr) |
if (fatal_called) |
fprintf(stderr, "%s\n", msgbuf); |
exit(1); |
syslog(pri, "%.500s", msgbuf); |
fatal_called = 1; |
|
|
|
/* Call cleanup functions. */ |
|
for (cu = fatal_cleanups; cu; cu = next_cu) |
|
{ |
|
next_cu = cu->next; |
|
debug("Calling cleanup 0x%lx(0x%lx)", |
|
(unsigned long)cu->proc, (unsigned long)cu->context); |
|
(*cu->proc)(cu->context); |
|
} |
|
|
|
exit(1); |
|
} |
} |