Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
radsecproxy/debug.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
284 lines (262 sloc)
7 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright (c) 2007-2009, UNINETT AS | |
* Copyright (c) 2010-2011, NORDUnet A/S */ | |
/* See LICENSE for licensing information. */ | |
#ifndef SYS_SOLARIS9 | |
#include <stdint.h> | |
#endif | |
#ifdef __linux__ | |
#include <sys/syscall.h> | |
#include <unistd.h> | |
#endif | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdarg.h> | |
#include <string.h> | |
#include <strings.h> | |
#include <time.h> | |
#include <sys/time.h> | |
#include <syslog.h> | |
#include <errno.h> | |
#include <assert.h> | |
#include <pthread.h> | |
#include "debug.h" | |
#include "util.h" | |
static char *debug_ident = NULL; | |
static uint8_t debug_level = DBG_INFO; | |
static char *debug_filepath = NULL; | |
static FILE *debug_file = NULL; | |
static int debug_syslogfacility = 0; | |
static int fticks_syslogfacility = 0; | |
static uint8_t debug_timestamp = 0; | |
static uint8_t debug_tid = 0; | |
void debug_init(char *ident) { | |
debug_file = stderr; | |
setvbuf(debug_file, NULL, _IONBF, 0); | |
debug_ident = ident; | |
} | |
void debug_set_level(uint8_t level) { | |
switch (level) { | |
case 1: | |
debug_level = DBG_ERR; | |
return; | |
case 2: | |
debug_level = DBG_WARN; | |
return; | |
case 3: | |
debug_level = DBG_NOTICE; | |
return; | |
case 4: | |
debug_level = DBG_INFO; | |
return; | |
case 5: | |
debug_level = DBG_DBG; | |
return; | |
} | |
} | |
void debug_timestamp_on() { | |
debug_timestamp = 1; | |
} | |
void debug_tid_on() { | |
debug_tid = 1; | |
} | |
uint8_t debug_get_level() { | |
return debug_level; | |
} | |
int debug_set_destination(char *dest, int log_type) { | |
static const char *facstrings[] = { | |
"LOG_DAEMON", "LOG_MAIL", "LOG_USER", "LOG_LOCAL0", | |
"LOG_LOCAL1", "LOG_LOCAL2", "LOG_LOCAL3", "LOG_LOCAL4", | |
"LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7", NULL }; | |
static const int facvals[] = { | |
LOG_DAEMON, LOG_MAIL, LOG_USER, LOG_LOCAL0, | |
LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, | |
LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7 }; | |
extern int errno; | |
int i; | |
if (!strncasecmp(dest, "file:///", 8)) { | |
if (log_type != LOG_TYPE_FTICKS) { | |
debug_filepath = stringcopy(dest + 7, 0); | |
debug_file = fopen(debug_filepath, "a"); | |
if (!debug_file) { | |
debug_file = stderr; | |
debugx(1, DBG_ERR, "Failed to open logfile %s\n%s", | |
debug_filepath, strerror(errno)); | |
} | |
setvbuf(debug_file, NULL, _IONBF, 0); | |
} else { | |
debug(DBG_WARN, "FTicksSyslogFacility starting with file:/// not " | |
"permitted, assuming default F-Ticks destination"); | |
} | |
return 1; | |
} | |
if (!strncasecmp(dest, "x-syslog://", 11) || log_type == LOG_TYPE_FTICKS) { | |
if (!strncasecmp(dest, "x-syslog://", 11)) { | |
dest += 11; | |
if (*dest == '/') | |
dest++; | |
} | |
if (*dest) { | |
for (i = 0; facstrings[i]; i++) | |
if (!strcasecmp(dest, facstrings[i])) | |
break; | |
if (!facstrings[i]) | |
debugx(1, DBG_ERR, "Unknown syslog facility %s", dest); | |
if (log_type != LOG_TYPE_FTICKS) | |
debug_syslogfacility = facvals[i]; | |
else if (log_type == LOG_TYPE_FTICKS) | |
fticks_syslogfacility = facvals[i]; | |
} else { | |
if (log_type != LOG_TYPE_FTICKS) | |
debug_syslogfacility = LOG_DAEMON; | |
else if (log_type == LOG_TYPE_FTICKS) | |
fticks_syslogfacility = 0; | |
} | |
openlog(debug_ident, LOG_PID, debug_syslogfacility); | |
return 1; | |
} | |
debug(DBG_ERR, "Unknown log destination, exiting %s", dest); | |
exit(1); | |
} | |
void debug_reopen_log() { | |
extern int errno; | |
/* not a file, noop, return success */ | |
if (!debug_filepath) { | |
debug(DBG_ERR, "skipping reopen"); | |
return; | |
} | |
if (debug_file != stderr) | |
fclose(debug_file); | |
debug_file = fopen(debug_filepath, "a"); | |
if (debug_file) | |
debug(DBG_ERR, "Reopened logfile %s", debug_filepath); | |
else { | |
debug_file = stderr; | |
debug(DBG_ERR, "Failed to open logfile %s, using stderr\n%s", | |
debug_filepath, strerror(errno)); | |
} | |
setvbuf(debug_file, NULL, _IONBF, 0); | |
} | |
void debug_logit(uint8_t level, const char *format, va_list ap) { | |
struct timeval now; | |
char *timebuf = NULL, *tidbuf, *tmp = NULL, *tmp2 = NULL; | |
int priority; | |
size_t malloc_size; | |
if (debug_tid) { | |
#ifdef __linux__ | |
pid_t tid = syscall(SYS_gettid); | |
tidbuf = malloc(3*sizeof(tid)+1); | |
sprintf(tidbuf, "%u", tid); | |
#else | |
pthread_t tid = pthread_self(); | |
uint8_t *ptid = (uint8_t *)&tid; | |
int i; | |
tidbuf = malloc((2*sizeof(tid)+1)); | |
tmp = tidbuf; | |
for (i = sizeof(tid)-1; i >= 0; i--) { | |
tmp += sprintf(tmp, "%02x", ptid[i]); | |
} | |
#endif | |
tmp = malloc(strlen(tidbuf) + strlen(format) + 4); | |
sprintf(tmp, "(%s) %s", tidbuf, format); | |
format = tmp; | |
free(tidbuf); | |
} | |
if (debug_syslogfacility) { | |
switch (level) { | |
case DBG_DBG: | |
priority = LOG_DEBUG; | |
break; | |
case DBG_INFO: | |
priority = LOG_INFO; | |
break; | |
case DBG_NOTICE: | |
priority = LOG_NOTICE; | |
break; | |
case DBG_WARN: | |
priority = LOG_WARNING; | |
break; | |
case DBG_ERR: | |
priority = LOG_ERR; | |
break; | |
default: | |
priority = LOG_DEBUG; | |
} | |
vsyslog(priority, format, ap); | |
} else { | |
if (debug_timestamp && (timebuf = malloc(26 + 1))) { | |
gettimeofday(&now, NULL); | |
ctime_r(&now.tv_sec, timebuf); | |
/*ctime_r writes exactly 24 bytes + "\n\0" */ | |
strncpy(timebuf+24,": ", 3); | |
} | |
malloc_size = strlen(format) + (timebuf ? strlen(timebuf) : 0) + 2*sizeof(char); | |
tmp2 = malloc(malloc_size); | |
if (tmp2) { | |
snprintf(tmp2, malloc_size, "%s%s\n", timebuf ? timebuf : "", format); | |
format = tmp2; | |
} | |
vfprintf(debug_file, format, ap); | |
} | |
free(tmp); | |
free(tmp2); | |
free(timebuf); | |
} | |
void debug(uint8_t level, char *format, ...) { | |
va_list ap; | |
if (level < debug_level) | |
return; | |
va_start(ap, format); | |
debug_logit(level, format, ap); | |
va_end(ap); | |
} | |
void debugx(int status, uint8_t level, char *format, ...) { | |
if (level >= debug_level) { | |
va_list ap; | |
va_start(ap, format); | |
debug_logit(level, format, ap); | |
va_end(ap); | |
} | |
exit(status); | |
} | |
void debugerrno(int err, uint8_t level, char *format, ...) { | |
if (level >= debug_level) { | |
va_list ap; | |
size_t len = strlen(format); | |
char *tmp = malloc(len + 1024 + 2); | |
assert(tmp); | |
strcpy(tmp, format); | |
tmp[len++] = ':'; | |
tmp[len++] = ' '; | |
va_start(ap, format); | |
if (strerror_r(err, tmp + len, 1024)) | |
debug_logit(level, format, ap); | |
else | |
debug_logit(level, tmp, ap); | |
va_end(ap); | |
free(tmp); | |
} | |
} | |
void debugerrnox(int err, uint8_t level, char *format, ...) { | |
if (level >= debug_level) { | |
va_list ap; | |
va_start(ap, format); | |
debugerrno(err, level, format, ap); | |
va_end(ap); | |
} | |
exit(err); | |
} | |
void fticks_debug(const char *format, ...) { | |
int priority; | |
va_list ap; | |
va_start(ap, format); | |
if (!debug_syslogfacility && !fticks_syslogfacility) | |
debug_logit(0xff, format, ap); | |
else { | |
priority = LOG_DEBUG | fticks_syslogfacility; | |
vsyslog(priority, format, ap); | |
} | |
va_end(ap); | |
} | |
/* Local Variables: */ | |
/* c-file-style: "stroustrup" */ | |
/* End: */ |