struct debug_settings settings;
char *debugf;
+ debug_callback_fn callback;
+ void *callback_private;
} state = {
.settings = {
.timestamp_logs = true
* 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
*/
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;
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
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);
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 );
}
}
+
#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 */
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
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.
****************************************************************************/
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 ) {
* 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;
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
*/