root/lib/util/debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_reopen_logs
  2. debug_schedule_reopen_logs
  3. log_timestring
  4. dbghdr
  5. dbghdrclass
  6. dbgtext
  7. reopen_logs
  8. setup_logging
  9. do_debug_tab
  10. log_suspicious_usage
  11. print_suspicious_usage
  12. get_task_id
  13. log_task_id
  14. register_debug_handlers

   1 /*
   2    Unix SMB/CIFS implementation.
   3    Samba debug functions
   4    Copyright (C) Andrew Tridgell 2003
   5    Copyright (C) James J Myers   2003
   6 
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11 
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16 
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "system/filesys.h"
  23 #include "system/time.h"
  24 #include "dynconfig/dynconfig.h"
  25 
  26 /**
  27  * @file
  28  * @brief Debug logging
  29  **/
  30 
  31 /** 
  32  * this global variable determines what messages are printed 
  33  */
  34 int _debug_level = 0;
  35 _PUBLIC_ int *debug_level = &_debug_level;
  36 static int debug_all_class_hack = 1;
  37 int *DEBUGLEVEL_CLASS = &debug_all_class_hack; /* For samba 3 */
  38 static bool debug_all_class_isset_hack = true;
  39 bool    *DEBUGLEVEL_CLASS_ISSET = &debug_all_class_isset_hack; /* For samba 3 */
  40 XFILE *dbf = NULL; /* For Samba 3*/
  41 
  42 /* the registered mutex handlers */
  43 static struct {
  44         const char *name;
  45         struct debug_ops ops;
  46 } debug_handlers;
  47 
  48 /* state variables for the debug system */
  49 static struct {
  50         int fd;
  51         enum debug_logtype logtype;
  52         const char *prog_name;
  53 } state;
  54 
  55 static bool reopen_logs_scheduled;
  56 static bool check_reopen_logs(void)
     /* [<][>][^][v][top][bottom][index][help] */
  57 {
  58         if (state.fd == 0 || reopen_logs_scheduled) {
  59                 reopen_logs_scheduled = false;
  60                 reopen_logs();
  61         }
  62 
  63         if (state.fd <= 0) 
  64                 return false;
  65 
  66         return true;
  67 }
  68 
  69 _PUBLIC_ void debug_schedule_reopen_logs(void)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71         reopen_logs_scheduled = true;
  72 }
  73 
  74 static void log_timestring(int level, const char *location, const char *func)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76         char *t = NULL;
  77         char *s = NULL;
  78 
  79         if (!check_reopen_logs()) return;
  80 
  81         if (state.logtype != DEBUG_FILE) return;
  82 
  83         t = timestring(NULL, time(NULL));
  84         if (!t) return;
  85 
  86         asprintf(&s, "[%s, %d %s:%s()]\n", t, level, location, func);
  87         talloc_free(t);
  88         if (!s) return;
  89 
  90         write(state.fd, s, strlen(s));
  91         free(s);
  92 }
  93 
  94 /**
  95   the backend for debug messages. Note that the DEBUG() macro has already
  96   ensured that the log level has been met before this is called
  97 */
  98 _PUBLIC_ void dbghdr(int level, const char *location, const char *func)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         log_timestring(level, location, func);
 101         log_task_id();
 102 }
 103 
 104 
 105 _PUBLIC_ void dbghdrclass(int level, int dclass, const char *location, const char *func)
     /* [<][>][^][v][top][bottom][index][help] */
 106 {
 107         /* Simple wrapper, Samba 4 doesn't do debug classes */
 108         dbghdr(level, location, func);
 109 }
 110 
 111 /**
 112   the backend for debug messages. Note that the DEBUG() macro has already
 113   ensured that the log level has been met before this is called
 114 
 115   @note You should never have to call this function directly. Call the DEBUG()
 116   macro instead.
 117 */
 118 _PUBLIC_ void dbgtext(const char *format, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 119 {
 120         va_list ap;
 121         char *s = NULL;
 122 
 123         if (!check_reopen_logs()) return;
 124 
 125         va_start(ap, format);
 126         vasprintf(&s, format, ap);
 127         va_end(ap);
 128 
 129         write(state.fd, s, strlen(s));
 130         free(s);
 131 }
 132 
 133 _PUBLIC_ const char *logfile = NULL;
 134 
 135 /**
 136   reopen the log file (usually called because the log file name might have changed)
 137 */
 138 _PUBLIC_ void reopen_logs(void)
     /* [<][>][^][v][top][bottom][index][help] */
 139 {
 140         char *fname = NULL;
 141         int old_fd = state.fd;
 142 
 143         switch (state.logtype) {
 144         case DEBUG_STDOUT:
 145                 state.fd = 1;
 146                 break;
 147 
 148         case DEBUG_STDERR:
 149                 state.fd = 2;
 150                 break;
 151 
 152         case DEBUG_FILE:
 153                 if (logfile && (*logfile) == '/') {
 154                         fname = strdup(logfile);
 155                 } else {
 156                         asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, state.prog_name);
 157                 }
 158                 if (fname) {
 159                         int newfd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0600);
 160                         if (newfd == -1) {
 161                                 DEBUG(1, ("Failed to open new logfile: %s\n", fname));
 162                                 old_fd = -1;
 163                         } else {
 164                                 state.fd = newfd;
 165                         }
 166                         free(fname);
 167                 } else {
 168                         DEBUG(1, ("Failed to find name for file-based logfile!\n"));
 169                 }
 170 
 171                 break;
 172         }
 173 
 174         if (old_fd > 2) {
 175                 close(old_fd);
 176         }
 177 }
 178 
 179 /**
 180   control the name of the logfile and whether logging will be to stdout, stderr
 181   or a file
 182 */
 183 _PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype)
     /* [<][>][^][v][top][bottom][index][help] */
 184 {
 185         if (state.logtype < new_logtype) {
 186                 state.logtype = new_logtype;
 187         }
 188         if (prog_name) {
 189                 state.prog_name = prog_name;
 190         }
 191         reopen_logs();
 192 }
 193 
 194 /**
 195   return a string constant containing n tabs
 196   no more than 10 tabs are returned
 197 */
 198 _PUBLIC_ const char *do_debug_tab(int n)
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200         const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", 
 201                               "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", 
 202                               "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"};
 203         return tabs[MIN(n, 10)];
 204 }
 205 
 206 
 207 /**
 208   log suspicious usage - print comments and backtrace
 209 */      
 210 _PUBLIC_ void log_suspicious_usage(const char *from, const char *info)
     /* [<][>][^][v][top][bottom][index][help] */
 211 {
 212         if (!debug_handlers.ops.log_suspicious_usage) return;
 213 
 214         debug_handlers.ops.log_suspicious_usage(from, info);
 215 }
 216 
 217 
 218 /**
 219   print suspicious usage - print comments and backtrace
 220 */      
 221 _PUBLIC_ void print_suspicious_usage(const char* from, const char* info)
     /* [<][>][^][v][top][bottom][index][help] */
 222 {
 223         if (!debug_handlers.ops.print_suspicious_usage) return;
 224 
 225         debug_handlers.ops.print_suspicious_usage(from, info);
 226 }
 227 
 228 _PUBLIC_ uint32_t get_task_id(void)
     /* [<][>][^][v][top][bottom][index][help] */
 229 {
 230         if (debug_handlers.ops.get_task_id) {
 231                 return debug_handlers.ops.get_task_id();
 232         }
 233         return getpid();
 234 }
 235 
 236 _PUBLIC_ void log_task_id(void)
     /* [<][>][^][v][top][bottom][index][help] */
 237 {
 238         if (!debug_handlers.ops.log_task_id) return;
 239 
 240         if (!check_reopen_logs()) return;
 241 
 242         debug_handlers.ops.log_task_id(state.fd);
 243 }
 244 
 245 /**
 246   register a set of debug handlers. 
 247 */
 248 _PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops)
     /* [<][>][^][v][top][bottom][index][help] */
 249 {
 250         debug_handlers.name = name;
 251         debug_handlers.ops = *ops;
 252 }

/* [<][>][^][v][top][bottom][index][help] */