*/
#include "includes.h"
+#include "librpc/gen_ndr/messaging.h"
/* -------------------------------------------------------------------------- **
* Defines...
* a newline.
*/
+/* state variables for the debug system */
+static struct {
+ int fd; /* The log file handle */
+ enum debug_logtype logtype; /* The type of logging we are doing: eg stdout, file, stderr */
+ const char *prog_name;
+ bool reopening_logs;
+} state;
+
/* -------------------------------------------------------------------------- **
* External variables.
*
- * dbf - Global debug file handle.
* debugf - Debug file name.
* DEBUGLEVEL - System-wide debug message limit. Messages with message-
* levels higher than DEBUGLEVEL will not be processed.
*/
-XFILE *dbf = NULL;
static char *debugf = NULL;
bool debug_warn_unknown_class = True;
bool debug_auto_add_unknown_class = True;
-bool AllowDebugChange = True;
/*
used to check if the user specified a
*/
bool override_logfile;
-static TALLOC_CTX *tmp_debug_ctx;
-
/*
* This is to allow assignment to DEBUGLEVEL before the debug
- * system has been initialised.
+ * system has been initialized.
*/
static int debug_all_class_hack = 1;
static bool debug_all_class_isset_hack = True;
/* -------------------------------------------------------------------------- **
* Internal variables.
*
- * stdout_logging - Default False, if set to True then dbf will be set to
- * stdout and debug output will go to dbf only, and not
- * to syslog. Set in setup_logging() and read in Debug1().
- *
* debug_count - Number of debug messages that have been output.
* Used to check log size.
*
* are unable to open a new log file for some reason.
*/
-static bool stdout_logging = False;
static int debug_count = 0;
#ifdef WITH_SYSLOG
static int syslog_level = 0;
Free memory pointed to by global pointers.
****************************************************************************/
+static bool initialized;
+
void gfree_debugsyms(void)
{
int i;
SAFE_FREE( classname_table );
}
- if ( DEBUGLEVEL_CLASS != &debug_all_class_hack )
+ if ( DEBUGLEVEL_CLASS != &debug_all_class_hack ) {
SAFE_FREE( DEBUGLEVEL_CLASS );
+ DEBUGLEVEL_CLASS = &debug_all_class_hack;
+ }
- if ( DEBUGLEVEL_CLASS_ISSET != &debug_all_class_isset_hack )
+ if ( DEBUGLEVEL_CLASS_ISSET != &debug_all_class_isset_hack ) {
SAFE_FREE( DEBUGLEVEL_CLASS_ISSET );
+ DEBUGLEVEL_CLASS_ISSET = &debug_all_class_isset_hack;
+ }
SAFE_FREE(format_bufr);
+
+ debug_num_classes = 0;
+
+ debug_level = DEBUGLEVEL_CLASS;
+
+ initialized = false;
}
/****************************************************************************
/* Just in case */
debug_init();
- if (AllowDebugChange == False)
- return True;
-
- params = str_list_make(params_str, NULL);
+ params = str_list_make_v3(talloc_tos(), params_str, NULL);
if (debug_parse_params(params)) {
debug_dump_status(5);
- str_list_free(¶ms);
+ TALLOC_FREE(params);
return True;
} else {
- str_list_free(¶ms);
+ TALLOC_FREE(params);
return False;
}
}
Receive a "set debug level" message.
****************************************************************************/
-static void debug_message(struct messaging_context *msg_ctx,
+void debug_message(struct messaging_context *msg_ctx,
void *private_data,
uint32_t msg_type,
struct server_id src,
void debug_init(void)
{
- static bool initialised = False;
const char **p;
- if (initialised)
+ if (initialized)
return;
- initialised = True;
+ initialized = true;
for(p = default_classname_table; *p; p++) {
debug_add_class(*p);
debuglevel_message);
}
-/***************************************************************************
- Get ready for syslog stuff
-**************************************************************************/
+/**
+ control the name of the logfile and whether logging will be to stdout, stderr
+ or a file, and set up syslog
-void setup_logging(const char *pname, bool interactive)
+ new_log indicates the destination for the debug log (an enum in
+ order of precedence - once set to DEBUG_FILE, it is not possible to
+ reset to DEBUG_STDOUT 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
+*/
+void setup_logging(const char *prog_name, enum debug_logtype new_logtype)
{
debug_init();
-
- /* reset to allow multiple setup calls, going from interactive to
- non-interactive */
- stdout_logging = False;
- if (dbf) {
- x_fflush(dbf);
- (void) x_fclose(dbf);
+ if (state.logtype < new_logtype) {
+ state.logtype = new_logtype;
}
-
- dbf = NULL;
-
- if (interactive) {
- stdout_logging = True;
- dbf = x_stdout;
- x_setbuf( x_stdout, NULL );
+ if (prog_name) {
+ state.prog_name = prog_name;
}
+ reopen_logs();
+
+ if (state.logtype == DEBUG_FILE) {
#ifdef WITH_SYSLOG
- else {
- const char *p = strrchr_m( pname,'/' );
+ const char *p = strrchr_m( prog_name,'/' );
if (p)
- pname = p + 1;
+ prog_name = p + 1;
#ifdef LOG_DAEMON
- openlog( pname, LOG_PID, SYSLOG_FACILITY );
+ openlog( prog_name, LOG_PID, SYSLOG_FACILITY );
#else
/* for old systems that have no facility codes. */
- openlog( pname, LOG_PID );
+ openlog( prog_name, LOG_PID );
#endif
- }
#endif
+ }
}
/***************************************************************************
debugf = SMB_STRDUP(name);
}
+static void debug_close_fd(int fd)
+{
+ if (fd > 2) {
+ close(fd);
+ }
+}
+
/**************************************************************************
reopen the log files
note that we now do this unconditionally
Fix from dgibson@linuxcare.com.
**************************************************************************/
-bool reopen_logs( void )
+/**
+ reopen the log file (usually called because the log file name might have changed)
+*/
+bool reopen_logs(void)
{
- char *fname = NULL;
mode_t oldumask;
- XFILE *new_dbf = NULL;
- XFILE *old_dbf = NULL;
+ int new_fd = 0;
+ int old_fd = 0;
bool ret = True;
- if (stdout_logging)
- return True;
+ char *fname = NULL;
+ if (state.reopening_logs) {
+ return true;
+ }
+
+ switch (state.logtype) {
+ case DEBUG_STDOUT:
+ debug_close_fd(state.fd);
+ state.fd = 1;
+ return true;
+
+ case DEBUG_DEFAULT_STDERR:
+ case DEBUG_STDERR:
+ debug_close_fd(state.fd);
+ state.fd = 2;
+ return true;
+
+ case DEBUG_FILE:
+ break;
+ }
oldumask = umask( 022 );
}
debugf = fname;
- new_dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644);
+ new_fd = open( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644);
- if (!new_dbf) {
+ if (new_fd == -1) {
log_overflow = True;
DEBUG(0, ("Unable to open new log file %s: %s\n", debugf, strerror(errno)));
log_overflow = False;
- if (dbf)
- x_fflush(dbf);
ret = False;
} else {
- x_setbuf(new_dbf, NULL);
- old_dbf = dbf;
- dbf = new_dbf;
- if (old_dbf)
- (void) x_fclose(old_dbf);
+ old_fd = state.fd;
+ state.fd = new_fd;
+ debug_close_fd(old_fd);
}
/* Fix from klausr@ITAP.Physik.Uni-Stuttgart.De
force_check_log_size();
(void)umask(oldumask);
- /* Take over stderr to catch ouput into logs */
- if (dbf && sys_dup2(x_fileno(dbf), 2) == -1) {
+ /* Take over stderr to catch output into logs */
+ if (state.fd > 0 && dup2(state.fd, 2) == -1) {
close_low_fds(True); /* Close stderr too, if dup2 can't point it
at the logfile */
}
return( False );
maxlog = lp_max_log_size() * 1024;
- if( !dbf || maxlog <= 0 ) {
+ if ( state.fd > 0 || maxlog <= 0 ) {
debug_count = 0;
return(False);
}
* loop check do a new check as root.
*/
- if( geteuid() != 0 )
+ if( geteuid() != sec_initial_uid() )
return;
if(log_overflow || !need_to_check_log_size() )
maxlog = lp_max_log_size() * 1024;
- if( sys_fstat( x_fileno( dbf ), &st ) == 0 && st.st_size > maxlog ) {
+ if(sys_fstat(state.fd, &st, false) == 0
+ && st.st_ex_size > maxlog ) {
(void)reopen_logs();
- if( dbf && get_file_size( debugf ) > maxlog ) {
+ if( state.fd > 0 && get_file_size( debugf ) > maxlog ) {
char *name = NULL;
if (asprintf(&name, "%s.old", debugf ) < 0) {
}
/*
- * Here's where we need to panic if dbf == NULL..
+ * Here's where we need to panic if state.fd == 0 or -1 (invalid values)
*/
- if(dbf == NULL) {
+ if (state.fd <= 0) {
/* This code should only be reached in very strange
* circumstances. If we merely fail to open the new log we
* should stick with the old one. ergo this should only be
* startup or when the log level is increased from zero.
* -dwg 6 June 2000
*/
- dbf = x_fopen( "/dev/console", O_WRONLY, 0);
- if(dbf) {
+ int fd = open( "/dev/console", O_WRONLY, 0);
+ if (fd != -1) {
+ state.fd = fd;
DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n",
debugf ));
} else {
debug_count++;
- if( stdout_logging ) {
+ if ( state.logtype != DEBUG_FILE ) {
va_start( ap, format_str );
- if(dbf)
- (void)x_vfprintf( dbf, format_str, ap );
+ if (state.fd > 0)
+ (void)vdprintf( state.fd, format_str, ap );
va_end( ap );
errno = old_errno;
goto done;
if( !lp_syslog_only() )
#endif
{
- if( !dbf ) {
+ if( state.fd <= 0 ) {
mode_t oldumask = umask( 022 );
-
- dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644 );
+ int fd = open( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644 );
(void)umask( oldumask );
- if( dbf ) {
- x_setbuf( dbf, NULL );
- } else {
+ if(fd == -1) {
errno = old_errno;
goto done;
}
+ state.fd = fd;
}
}
/* map debug levels to syslog() priorities
* note that not all DEBUG(0, ...) calls are
* necessarily errors */
- static int priority_map[] = {
+ static const int priority_map[4] = {
LOG_ERR, /* 0 */
LOG_WARNING, /* 1 */
LOG_NOTICE, /* 2 */
};
int priority;
char *msgbuf = NULL;
+ int ret;
- if( syslog_level >= ( sizeof(priority_map) / sizeof(priority_map[0]) ) || syslog_level < 0)
+ if( syslog_level >= ARRAY_SIZE(priority_map) || syslog_level < 0)
priority = LOG_DEBUG;
else
priority = priority_map[syslog_level];
+ /*
+ * Specify the facility to interoperate with other syslog
+ * callers (vfs_full_audit for example).
+ */
+ priority |= SYSLOG_FACILITY;
+
va_start(ap, format_str);
- vasprintf(&msgbuf, format_str, ap);
+ ret = vasprintf(&msgbuf, format_str, ap);
va_end(ap);
- if (msgbuf) {
+ if (ret != -1) {
syslog(priority, "%s", msgbuf);
}
SAFE_FREE(msgbuf);
#endif
{
va_start( ap, format_str );
- if(dbf)
- (void)x_vfprintf( dbf, format_str, ap );
+ if (state.fd > 0)
+ (void)vdprintf( state.fd, format_str, ap );
va_end( ap );
- if(dbf)
- (void)x_fflush( dbf );
}
done:
- TALLOC_FREE(tmp_debug_ctx);
-
errno = old_errno;
return( 0 );
static void format_debug_text( const char *msg )
{
size_t i;
- bool timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded())));
+ bool timestamp = (state.logtype == DEBUG_FILE && (lp_timestamp_logs() || !(lp_loaded())));
if (!format_bufr) {
debug_init();
void dbgflush( void )
{
bufr_print();
- if(dbf)
- (void)x_fflush( dbf );
}
/***************************************************************************
****************************************************************************/
-bool dbghdr(int level, int cls, const char *file, const char *func, int line)
+bool dbghdrclass(int level, int cls, const char *location, const char *func)
{
/* Ensure we don't lose any real errno value. */
int old_errno = errno;
#endif
/* Don't print a header if we're logging to stdout. */
- if( stdout_logging )
+ if ( state.logtype != DEBUG_FILE ) {
return( True );
+ }
/* Print the header if timestamps are turned on. If parameters are
* not yet loaded, then default to timestamps on.
/* Print it all out at once to prevent split syslog output. */
if( lp_debug_prefix_timestamp() ) {
(void)Debug1( "[%s, %2d%s] ",
- current_timestring(lp_debug_hires_timestamp()), level,
- header_str);
+ current_timestring(talloc_tos(),
+ lp_debug_hires_timestamp()),
+ level, header_str);
} else {
- (void)Debug1( "[%s, %2d%s] %s:%s(%d)\n",
- current_timestring(lp_debug_hires_timestamp()), level,
- header_str, file, func, line );
+ (void)Debug1( "[%s, %2d%s] %s(%s)\n",
+ current_timestring(talloc_tos(),
+ lp_debug_hires_timestamp()),
+ level, header_str, location, func );
}
}
return( True );
}
+bool dbghdr(int level, const char *location, const char *func)
+{
+ /* For compatibility with Samba 4, which doesn't have debug classes */
+ return dbghdrclass(level, 0, location, func);
+}
+
/***************************************************************************
Add text to the body of the "current" debug message via the format buffer.
va_list ap;
char *msgbuf = NULL;
bool ret = true;
+ int res;
va_start(ap, format_str);
- vasprintf(&msgbuf, format_str, ap);
+ res = vasprintf(&msgbuf, format_str, ap);
va_end(ap);
- if (msgbuf) {
+ if (res != -1) {
format_debug_text(msgbuf);
} else {
ret = false;
SAFE_FREE(msgbuf);
return ret;
}
-
-/*
- * Get us a temporary talloc context usable just for DEBUG arguments
- */
-TALLOC_CTX *debug_ctx(void)
-{
- if (tmp_debug_ctx == NULL) {
- tmp_debug_ctx = talloc_named_const(NULL, 0, "debug_ctx");
- }
- return tmp_debug_ctx;
-}