Use sec_initial_uid() in the places where being root doesn't matter,
[samba.git] / source3 / lib / debug.c
index 43d1f64eb17ceb3a88091ecba5ec932287c4f64e..83211dd5e6e2e7ef46f9f6a55198c9f35907ab4c 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -30,7 +29,8 @@
  *                    for a terminating null byte.
  */
 
-#define FORMAT_BUFR_MAX ( sizeof( format_bufr ) - 1 )
+#define FORMAT_BUFR_SIZE 1024
+#define FORMAT_BUFR_MAX (FORMAT_BUFR_SIZE - 1)
 
 /* -------------------------------------------------------------------------- **
  * This module implements Samba's debugging utility.
  */
 
 XFILE   *dbf        = NULL;
-pstring debugf     = "";
-BOOL    debug_warn_unknown_class = True;
-BOOL    debug_auto_add_unknown_class = True;
-BOOL    AllowDebugChange = True;
-
-/* 
-   used to check if the user specified a 
-   logfile on the command line 
-*/
-BOOL    override_logfile;              
+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
+   logfile on the command line
+*/
+bool    override_logfile;
 
 /*
  * 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;
+static bool debug_all_class_isset_hack = True;
 
 static int debug_num_classes = 0;
 int     *DEBUGLEVEL_CLASS = &debug_all_class_hack;
-BOOL    *DEBUGLEVEL_CLASS_ISSET = &debug_all_class_isset_hack;
+bool    *DEBUGLEVEL_CLASS_ISSET = &debug_all_class_isset_hack;
 
 /* DEBUGLEVEL is #defined to *debug_level */
 int     DEBUGLEVEL = &debug_all_class_hack;
@@ -133,14 +132,14 @@ int     DEBUGLEVEL = &debug_all_class_hack;
  *                    are unable to open a new log file for some reason.
  */
 
-static BOOL    stdout_logging = False;
+static bool    stdout_logging = False;
 static int     debug_count    = 0;
 #ifdef WITH_SYSLOG
 static int     syslog_level   = 0;
 #endif
-static pstring format_bufr    = { '\0' };
+static char *format_bufr = NULL;
 static size_t     format_pos     = 0;
-static BOOL    log_overflow   = False;
+static bool    log_overflow   = False;
 
 /*
  * Define all the debug class selection names here. Names *MUST NOT* contain 
@@ -164,8 +163,10 @@ static const char *default_classname_table[] = {
        "idmap",             /* DBGC_IDMAP        */
        "quota",             /* DBGC_QUOTA        */
        "acls",              /* DBGC_ACLS         */
-       "printerdb",         /* DBGC_PRINTERDB    */
        "locking",           /* DBGC_LOCKING      */
+       "msdfs",             /* DBGC_MSDFS        */
+       "dmapi",             /* DBGC_DMAPI        */
+       "registry",          /* DBGC_REGISTRY     */
        NULL
 };
 
@@ -176,6 +177,41 @@ static char **classname_table = NULL;
  * Functions...
  */
 
+/***************************************************************************
+ Free memory pointed to by global pointers.
+****************************************************************************/
+
+static bool initialized;
+
+void gfree_debugsyms(void)
+{
+       int i;
+
+       if ( classname_table ) {
+               for ( i = 0; i < debug_num_classes; i++ ) {
+                       SAFE_FREE( classname_table[i] );
+               }
+               SAFE_FREE( classname_table );
+       }
+
+       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 ) {
+               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;
+}
 
 /****************************************************************************
 utility lists registered debug class names's
@@ -189,14 +225,16 @@ static char *debug_list_class_names_and_levels(void)
        char **list;
        char *buf = NULL;
        char *b;
-       BOOL err = False;
+       bool err = False;
 
-       if (DEBUGLEVEL_CLASS == &debug_all_class_hack)
+       if (DEBUGLEVEL_CLASS == &debug_all_class_hack) {
                return NULL;
+       }
 
        list = SMB_CALLOC_ARRAY(char *, debug_num_classes + 1);
-       if (!list)
+       if (!list) {
                return NULL;
+       }
 
        /* prepare strings */
        for (i = 0, dim = 0; i < debug_num_classes; i++) {
@@ -212,7 +250,7 @@ static char *debug_list_class_names_and_levels(void)
        }
 
        /* create single string list - add space for newline */
-       b = buf = SMB_MALLOC(dim+1);
+       b = buf = (char *)SMB_MALLOC(dim+1);
        if (!buf) {
                err = True;
                goto done;
@@ -227,13 +265,12 @@ static char *debug_list_class_names_and_levels(void)
 
 done:
        /* free strings list */
-       for (i = 0; i < debug_num_classes; i++)
-               if (list[i]) free(list[i]);
-       free(list);
+       for (i = 0; i < debug_num_classes; i++) {
+               SAFE_FREE(list[i]);
+       }
+       SAFE_FREE(list);
 
        if (err) {
-               if (buf)
-                       free(buf);
                return NULL;
        } else {
                return buf;
@@ -297,7 +334,7 @@ int debug_add_class(const char *classname)
        new_ptr = SMB_REALLOC_ARRAY(new_ptr, int, debug_num_classes + 1);
        if (!new_ptr)
                return -1;
-       DEBUGLEVEL_CLASS = new_ptr;
+       DEBUGLEVEL_CLASS = (int *)new_ptr;
        DEBUGLEVEL_CLASS[ndx] = 0;
 
        /* debug_level is the pointer used for the DEBUGLEVEL-thingy */
@@ -311,16 +348,16 @@ int debug_add_class(const char *classname)
        if (new_ptr == &debug_all_class_isset_hack) {
                new_ptr = NULL;
        }
-       new_ptr = SMB_REALLOC_ARRAY(new_ptr, BOOL, debug_num_classes + 1);
+       new_ptr = SMB_REALLOC_ARRAY(new_ptr, bool, debug_num_classes + 1);
        if (!new_ptr)
                return -1;
-       DEBUGLEVEL_CLASS_ISSET = new_ptr;
+       DEBUGLEVEL_CLASS_ISSET = (bool *)new_ptr;
        DEBUGLEVEL_CLASS_ISSET[ndx] = False;
 
        new_ptr = SMB_REALLOC_ARRAY(classname_table, char *, debug_num_classes + 1);
        if (!new_ptr)
                return -1;
-       classname_table = new_ptr;
+       classname_table = (char **)new_ptr;
 
        classname_table[ndx] = SMB_STRDUP(classname);
        if (! classname_table[ndx])
@@ -380,7 +417,7 @@ static void debug_dump_status(int level)
  printdrivers:7
 ****************************************************************************/
 
-static BOOL debug_parse_params(char **params)
+static bool debug_parse_params(char **params)
 {
        int   i, ndx;
        char *class_name;
@@ -402,8 +439,9 @@ static BOOL debug_parse_params(char **params)
 
        /* Fill in new debug class levels */
        for (; i < debug_num_classes && params[i]; i++) {
-               if ((class_name=strtok(params[i],":")) &&
-                       (class_level=strtok(NULL, "\0")) &&
+               char *saveptr;
+               if ((class_name = strtok_r(params[i],":", &saveptr)) &&
+                       (class_level = strtok_r(NULL, "\0", &saveptr)) &&
             ((ndx = debug_lookup_classname(class_name)) != -1)) {
                                DEBUGLEVEL_CLASS[ndx] = atoi(class_level);
                                DEBUGLEVEL_CLASS_ISSET[ndx] = True;
@@ -422,7 +460,7 @@ static BOOL debug_parse_params(char **params)
  Note: the 1st param has no "name:" preceeding it.
 ****************************************************************************/
 
-BOOL debug_parse_levels(const char *params_str)
+bool debug_parse_levels(const char *params_str)
 {
        char **params;
 
@@ -432,14 +470,14 @@ BOOL debug_parse_levels(const char *params_str)
        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(&params);
+               TALLOC_FREE(params);
                return True;
        } else {
-               str_list_free(&params);
+               TALLOC_FREE(params);
                return False;
        }
 }
@@ -448,45 +486,50 @@ BOOL debug_parse_levels(const char *params_str)
  Receive a "set debug level" message.
 ****************************************************************************/
 
-static void debug_message(int msg_type, pid_t src, void *buf, size_t len)
+void debug_message(struct messaging_context *msg_ctx,
+                         void *private_data, 
+                         uint32_t msg_type, 
+                         struct server_id src,
+                         DATA_BLOB *data)
 {
-       const char *params_str = buf;
+       const char *params_str = (const char *)data->data;
 
        /* Check, it's a proper string! */
-       if (params_str[len-1] != '\0') {
+       if (params_str[(data->length)-1] != '\0') {
                DEBUG(1, ("Invalid debug message from pid %u to pid %u\n",
-                         (unsigned int)src, (unsigned int)getpid()));
+                         (unsigned int)procid_to_pid(&src),
+                         (unsigned int)getpid()));
                return;
        }
 
        DEBUG(3, ("INFO: Remote set of debug to `%s'  (pid %u from pid %u)\n",
-                 params_str, (unsigned int)getpid(), (unsigned int)src));
+                 params_str, (unsigned int)getpid(),
+                 (unsigned int)procid_to_pid(&src)));
 
        debug_parse_levels(params_str);
 }
 
-/****************************************************************************
- Send a "set debug level" message.
-****************************************************************************/
-
-void debug_message_send(pid_t pid, const char *params_str)
-{
-       if (!params_str)
-               return;
-       message_send_pid(pid, MSG_DEBUG, params_str, strlen(params_str) + 1,
-                        False);
-}
-
 /****************************************************************************
  Return current debug level.
 ****************************************************************************/
 
-static void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len)
+static void debuglevel_message(struct messaging_context *msg_ctx,
+                              void *private_data, 
+                              uint32_t msg_type, 
+                              struct server_id src,
+                              DATA_BLOB *data)
 {
        char *message = debug_list_class_names_and_levels();
 
-       DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n",(unsigned int)src));
-       message_send_pid(src, MSG_DEBUGLEVEL, message, strlen(message) + 1, True);
+       if (!message) {
+               DEBUG(0,("debuglevel_message - debug_list_class_names_and_levels returned NULL\n"));
+               return;
+       }
+
+       DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %s\n",
+                procid_str_static(&src)));
+       messaging_send_buf(msg_ctx, src, MSG_DEBUGLEVEL,
+                          (uint8 *)message, strlen(message) + 1);
 
        SAFE_FREE(message);
 }
@@ -497,27 +540,34 @@ Init debugging (one time stuff)
 
 void debug_init(void)
 {
-       static BOOL initialised = False;
        const char **p;
 
-       if (initialised)
+       if (initialized)
                return;
-       
-       initialised = True;
 
-       message_register(MSG_DEBUG, debug_message);
-       message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message);
+       initialized = true;
 
        for(p = default_classname_table; *p; p++) {
                debug_add_class(*p);
        }
+       format_bufr = (char *)SMB_MALLOC(FORMAT_BUFR_SIZE);
+       if (!format_bufr) {
+               smb_panic("debug_init: unable to create buffer");
+       }
+}
+
+void debug_register_msgs(struct messaging_context *msg_ctx)
+{
+       messaging_register(msg_ctx, NULL, MSG_DEBUG, debug_message);
+       messaging_register(msg_ctx, NULL, MSG_REQ_DEBUGLEVEL,
+                          debuglevel_message);
 }
 
 /***************************************************************************
  Get ready for syslog stuff
 **************************************************************************/
 
-void setup_logging(const char *pname, BOOL interactive)
+void setup_logging(const char *pname, bool interactive)
 {
        debug_init();
 
@@ -526,7 +576,9 @@ void setup_logging(const char *pname, BOOL interactive)
        stdout_logging = False;
        if (dbf) {
                x_fflush(dbf);
-               (void) x_fclose(dbf);
+                if (dbf != x_stdout) {
+                        (void) x_fclose(dbf);
+                }
        }
 
        dbf = NULL;
@@ -551,6 +603,25 @@ void setup_logging(const char *pname, BOOL interactive)
 #endif
 }
 
+/**
+   Just run logging to stdout for this program 
+*/
+_PUBLIC_ void setup_logging_stdout(void)
+{
+       setup_logging(NULL, True);
+}
+
+
+/***************************************************************************
+ Set the logfile name.
+**************************************************************************/
+
+void debug_set_logfile(const char *name)
+{
+       SAFE_FREE(debugf);
+       debugf = SMB_STRDUP(name);
+}
+
 /**************************************************************************
  reopen the log files
  note that we now do this unconditionally
@@ -559,31 +630,39 @@ void setup_logging(const char *pname, BOOL interactive)
  Fix from dgibson@linuxcare.com.
 **************************************************************************/
 
-BOOL reopen_logs( void )
+bool reopen_logs( void )
 {
-       pstring fname;
+       char *fname = NULL;
        mode_t oldumask;
        XFILE *new_dbf = NULL;
        XFILE *old_dbf = NULL;
-       BOOL ret = True;
+       bool ret = True;
 
        if (stdout_logging)
                return True;
 
        oldumask = umask( 022 );
-  
-       pstrcpy(fname, debugf );
-       debugf[0] = '\0';
+
+       fname = debugf;
+       if (!fname) {
+               return false;
+       }
+       debugf = NULL;
 
        if (lp_loaded()) {
                char *logfname;
 
                logfname = lp_logfile();
-               if (*logfname)
-                       pstrcpy(fname, logfname);
+               if (*logfname) {
+                       SAFE_FREE(fname);
+                       fname = SMB_STRDUP(logfname);
+                       if (!fname) {
+                               return false;
+                       }
+               }
        }
 
-       pstrcpy( debugf, fname );
+       debugf = fname;
        new_dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644);
 
        if (!new_dbf) {
@@ -608,8 +687,8 @@ BOOL reopen_logs( void )
        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 (dbf && dup2(x_fileno(dbf), 2) == -1) {
                close_low_fds(True); /* Close stderr too, if dup2 can't point it
                                        at the logfile */
        }
@@ -630,7 +709,7 @@ void force_check_log_size( void )
  Check to see if there is any need to check if the logfile has grown too big.
 **************************************************************************/
 
-BOOL need_to_check_log_size( void )
+bool need_to_check_log_size( void )
 {
        int maxlog;
 
@@ -659,7 +738,7 @@ void check_log_size( void )
         *  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() )
@@ -667,18 +746,22 @@ void check_log_size( void )
 
        maxlog = lp_max_log_size() * 1024;
 
-       if( sys_fstat( x_fileno( dbf ), &st ) == 0 && st.st_size > maxlog ) {
+       if(sys_fstat(x_fileno(dbf), &st, false) == 0
+          && st.st_ex_size > maxlog ) {
                (void)reopen_logs();
                if( dbf && get_file_size( debugf ) > maxlog ) {
-                       pstring name;
+                       char *name = NULL;
+
+                       if (asprintf(&name, "%s.old", debugf ) < 0) {
+                               return;
+                       }
+                       (void)rename(debugf, name);
 
-                       slprintf( name, sizeof(name)-1, "%s.old", debugf );
-                       (void)rename( debugf, name );
-      
                        if (!reopen_logs()) {
                                /* We failed to reopen a log - continue using the old name. */
                                (void)rename(name, debugf);
                        }
+                       SAFE_FREE(name);
                }
        }
 
@@ -715,7 +798,7 @@ void check_log_size( void )
 
  int Debug1( const char *format_str, ... )
 {
-       va_list ap;  
+       va_list ap;
        int old_errno = errno;
 
        debug_count++;
@@ -726,13 +809,13 @@ void check_log_size( void )
                        (void)x_vfprintf( dbf, format_str, ap );
                va_end( ap );
                errno = old_errno;
-               return( 0 );
+               goto done;
        }
 
        /* prevent recursion by checking if reopen_logs() has temporaily
-          set the debugf string to "" */
-       if( debugf[0] == '\0')
-               return( 0 );
+          set the debugf string to NULL */
+       if( debugf == NULL)
+               goto done;
 
 #ifdef WITH_SYSLOG
        if( !lp_syslog_only() )
@@ -747,7 +830,7 @@ void check_log_size( void )
                                x_setbuf( dbf, NULL );
                        } else {
                                errno = old_errno;
-                               return(0);
+                               goto done;
                        }
                }
        }
@@ -757,29 +840,38 @@ void check_log_size( void )
                /* 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 */
                        LOG_INFO,    /* 3 */
                };
                int     priority;
-               pstring msgbuf;
+               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];
 
-               va_start( ap, format_str );
-               vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap );
-               va_end( ap );
+               /*
+                * Specify the facility to interoperate with other syslog
+                * callers (vfs_full_audit for example).
+                */
+               priority |= SYSLOG_FACILITY;
+
+               va_start(ap, format_str);
+               ret = vasprintf(&msgbuf, format_str, ap);
+               va_end(ap);
 
-               msgbuf[255] = '\0';
-               syslog( priority, "%s", msgbuf );
+               if (ret != -1) {
+                       syslog(priority, "%s", msgbuf);
+               }
+               SAFE_FREE(msgbuf);
        }
 #endif
-  
+
        check_log_size();
 
 #ifdef WITH_SYSLOG
@@ -794,6 +886,7 @@ void check_log_size( void )
                        (void)x_fflush( dbf );
        }
 
+ done:
        errno = old_errno;
 
        return( 0 );
@@ -832,7 +925,11 @@ static void bufr_print( void )
 static void format_debug_text( const char *msg )
 {
        size_t i;
-       BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded())));
+       bool timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded())));
+
+       if (!format_bufr) {
+               debug_init();
+       }
 
        for( i = 0; msg[i]; i++ ) {
                /* Indent two spaces at each new line. */
@@ -881,6 +978,7 @@ void dbgflush( void )
 
  Input:  level - Debug level of the message (not the system-wide debug
                   level. )
+         cls   - Debuglevel class of the calling module.
           file  - Pointer to a string containing the name of the file
                   from which this function was called, or an empty string
                   if the __FILE__ macro is not implemented.
@@ -898,7 +996,7 @@ void dbgflush( void )
 
 ****************************************************************************/
 
-BOOL dbghdr( int level, 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;
@@ -928,7 +1026,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
        /* Print the header if timestamps are turned on.  If parameters are
         * not yet loaded, then default to timestamps on.
         */
-       if( lp_timestamp_logs() || !(lp_loaded()) ) {
+       if( lp_timestamp_logs() || lp_debug_prefix_timestamp() || !(lp_loaded()) ) {
                char header_str[200];
 
                header_str[0] = '\0';
@@ -944,17 +1042,39 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
                                (unsigned int)geteuid(), (unsigned int)getegid(),
                                (unsigned int)getuid(), (unsigned int)getgid()); 
                }
+
+               if (lp_debug_class() && (cls != DBGC_ALL)) {
+                       size_t hs_len = strlen(header_str);
+                       slprintf(header_str + hs_len,
+                                sizeof(header_str) -1 - hs_len,
+                                ", class=%s",
+                                default_classname_table[cls]);
+               }
   
                /* Print it all out at once to prevent split syslog output. */
-               (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
-                       timestring(lp_debug_hires_timestamp()), level,
-                       header_str, file, func, line );
+               if( lp_debug_prefix_timestamp() ) {
+                   (void)Debug1( "[%s, %2d%s] ",
+                       current_timestring(talloc_tos(),
+                                          lp_debug_hires_timestamp()),
+                       level, header_str);
+               } else {
+                   (void)Debug1( "[%s, %2d%s] %s(%s)\n",
+                       current_timestring(talloc_tos(),
+                                          lp_debug_hires_timestamp()),
+                       level, header_str, location, func );
+               }
        }
 
        errno = old_errno;
        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.
 
@@ -968,16 +1088,22 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
 
 ***************************************************************************/
 
BOOL dbgtext( const char *format_str, ... )
bool dbgtext( const char *format_str, ... )
 {
        va_list ap;
-       pstring msgbuf;
-
-       va_start( ap, format_str ); 
-       vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap );
-       va_end( ap );
+       char *msgbuf = NULL;
+       bool ret = true;
+       int res;
 
-       format_debug_text( msgbuf );
+       va_start(ap, format_str);
+       res = vasprintf(&msgbuf, format_str, ap);
+       va_end(ap);
 
-  return( True );
+       if (res != -1) {
+               format_debug_text(msgbuf);
+       } else {
+               ret = false;
+       }
+       SAFE_FREE(msgbuf);
+       return ret;
 }