From bc66af50ffdffe39ba6c6e3d4dc03e095a89134c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 8 Mar 2012 12:21:26 +1100 Subject: lib/util: Add a callback facility for debug messages This will allow dlz_bind9 to put log messages somewhere useful, which may make it easier to debug. Andrew Bartlett --- lib/util/debug.c | 57 +++++++++++++++++++++++++++++++++++++++++++------------- lib/util/debug.h | 9 ++++++++- 2 files changed, 52 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/util/debug.c b/lib/util/debug.c index a7e2a0f78e..52abd799f7 100644 --- a/lib/util/debug.c +++ b/lib/util/debug.c @@ -88,6 +88,8 @@ static struct { struct debug_settings settings; char *debugf; + debug_callback_fn callback; + void *callback_private; } state = { .settings = { .timestamp_logs = true @@ -125,7 +127,7 @@ int *DEBUGLEVEL_CLASS = discard_const_p(int, debug_class_list_initial); * debug_count - Number of debug messages that have been output. * Used to check log size. * - * syslog_level - Internal copy of the message debug level. Written by + * current_msg_level - Internal copy of the message debug level. Written by * dbghdr() and read by Debug1(). * * format_bufr - Used to format debug messages. The dbgtext() function @@ -143,9 +145,7 @@ int *DEBUGLEVEL_CLASS = discard_const_p(int, debug_class_list_initial); */ static int debug_count = 0; -#ifdef WITH_SYSLOG -static int syslog_level = 0; -#endif +static int current_msg_level = 0; static char *format_bufr = NULL; static size_t format_pos = 0; static bool log_overflow = false; @@ -519,6 +519,20 @@ bool debug_get_output_is_stdout(void) return (state.logtype == DEBUG_DEFAULT_STDOUT) || (state.logtype == DEBUG_STDOUT); } +void debug_set_callback(void *private_ptr, debug_callback_fn fn) +{ + debug_init(); + if (fn) { + state.logtype = DEBUG_CALLBACK; + state.callback_private = private_ptr; + state.callback = fn; + } else { + state.logtype = DEBUG_DEFAULT_STDERR; + state.callback_private = NULL; + state.callback = NULL; + } +} + /************************************************************************** reopen the log files note that we now do this unconditionally @@ -546,6 +560,8 @@ bool reopen_logs_internal(void) state.schedule_reopen_logs = false; switch (state.logtype) { + case DEBUG_CALLBACK: + return true; case DEBUG_STDOUT: case DEBUG_DEFAULT_STDOUT: debug_close_fd(state.fd); @@ -735,7 +751,23 @@ void check_log_size( void ) debug_count++; - if ( state.logtype != DEBUG_FILE ) { + if (state.logtype == DEBUG_CALLBACK) { + char *msg; + int ret; + va_start( ap, format_str ); + ret = vasprintf( &msg, format_str, ap ); + if (ret != -1) { + if (msg[ret - 1] == '\n') { + msg[ret - 1] = '\0'; + } + state.callback(state.callback_private, current_msg_level, msg); + free(msg); + } + va_end( ap ); + + goto done; + + } else if ( state.logtype != DEBUG_FILE ) { va_start( ap, format_str ); if (state.fd > 0) (void)vdprintf( state.fd, format_str, ap ); @@ -760,8 +792,9 @@ void check_log_size( void ) } } + #ifdef WITH_SYSLOG - if( syslog_level < state.settings.syslog ) { + if( current_msg_level < state.settings.syslog ) { /* map debug levels to syslog() priorities * note that not all DEBUG(0, ...) calls are * necessarily errors */ @@ -775,10 +808,10 @@ void check_log_size( void ) char *msgbuf = NULL; int ret; - if( syslog_level >= ARRAY_SIZE(priority_map) || syslog_level < 0) + if( current_msg_level >= ARRAY_SIZE(priority_map) || current_msg_level < 0) priority = LOG_DEBUG; else - priority = priority_map[syslog_level]; + priority = priority_map[current_msg_level]; /* * Specify the facility to interoperate with other syslog @@ -913,7 +946,7 @@ void dbgflush( void ) in a macro, since the function can be called as part of a test. Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) ) - Notes: This function takes care of setting syslog_level. + Notes: This function takes care of setting current_msg_level. ****************************************************************************/ @@ -935,10 +968,8 @@ bool dbghdrclass(int level, int cls, const char *location, const char *func) return( true ); } -#ifdef WITH_SYSLOG - /* Set syslog_level. */ - syslog_level = level; -#endif + /* Set current_msg_level. */ + current_msg_level = level; /* Don't print a header if we're logging to stdout. */ if ( state.logtype != DEBUG_FILE ) { diff --git a/lib/util/debug.h b/lib/util/debug.h index c61a2c55be..b3647a3345 100644 --- a/lib/util/debug.h +++ b/lib/util/debug.h @@ -197,7 +197,7 @@ extern int *DEBUGLEVEL_CLASS; * for example. This makes it easy to override for debug to stderr on * the command line, as the smb.conf cannot reset it back to * file-based logging */ -enum debug_logtype {DEBUG_DEFAULT_STDERR = 0, DEBUG_DEFAULT_STDOUT = 1, DEBUG_FILE = 2, DEBUG_STDOUT = 3, DEBUG_STDERR = 4}; +enum debug_logtype {DEBUG_DEFAULT_STDERR = 0, DEBUG_DEFAULT_STDOUT = 1, DEBUG_FILE = 2, DEBUG_STDOUT = 3, DEBUG_STDERR = 4, DEBUG_CALLBACK = 5}; struct debug_settings { size_t max_log_size; @@ -233,6 +233,13 @@ bool debug_get_output_is_stdout(void); void debug_schedule_reopen_logs(void); char *debug_list_class_names_and_levels(void); +typedef void (*debug_callback_fn)(void *private_ptr, int level, const char *msg); + +/** + Set a callback for all debug messages. Use in dlz_bind9 to push output to the bind logs + */ +void debug_set_callback(void *private_ptr, debug_callback_fn fn); + /** log suspicious usage - print comments and backtrace */ -- cgit