root/src/vfs/smbfs/helpers/lib/debug.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. setup_logging
  2. Debug1
  3. Debug1
  4. bufr_print
  5. format_debug_text
  6. dbgflush
  7. dbghdr
  8. dbgtext
  9. dbgtext

   1 /*
   2    Unix SMB/Netbios implementation.
   3    Version 1.9.
   4    Samba utility functions
   5 
   6    Copyright (C) Andrew Tridgell 1992-1998
   7 
   8    Copyright (C) 2011-2019
   9    Free Software Foundation, Inc.
  10 
  11    This file is part of the Midnight Commander.
  12 
  13    The Midnight Commander is free software: you can redistribute it
  14    and/or modify it under the terms of the GNU General Public License as
  15    published by the Free Software Foundation, either version 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include "includes.h"
  28 
  29 /* -------------------------------------------------------------------------- **
  30  * Defines...
  31  *
  32  *  FORMAT_BUFR_MAX - Index of the last byte of the format buffer;
  33  *                    format_bufr[FORMAT_BUFR_MAX] should always be reserved
  34  *                    for a terminating nul byte.
  35  */
  36 
  37 #define FORMAT_BUFR_MAX ( sizeof( format_bufr ) - 1 )
  38 
  39 /* -------------------------------------------------------------------------- **
  40  * This module implements Samba's debugging utility.
  41  *
  42  * The syntax of a debugging log file is represented as:
  43  *
  44  *  <debugfile> :== { <debugmsg> }
  45  *
  46  *  <debugmsg>  :== <debughdr> '\n' <debugtext>
  47  *
  48  *  <debughdr>  :== '[' TIME ',' LEVEL ']' [ [FILENAME ':'] [FUNCTION '()'] ]
  49  *
  50  *  <debugtext> :== { <debugline> }
  51  *
  52  *  <debugline> :== TEXT '\n'
  53  *
  54  * TEXT     is a string of characters excluding the newline character.
  55  * LEVEL    is the DEBUG level of the message (an integer in the range 0..10).
  56  * TIME     is a timestamp.
  57  * FILENAME is the name of the file from which the debug message was generated.
  58  * FUNCTION is the function from which the debug message was generated.
  59  *
  60  * Basically, what that all means is:
  61  *
  62  * - A debugging log file is made up of debug messages.
  63  *
  64  * - Each debug message is made up of a header and text.  The header is
  65  *   separated from the text by a newline.
  66  *
  67  * - The header begins with the timestamp and debug level of the message
  68  *   enclosed in brackets.  The filename and function from which the
  69  *   message was generated may follow.  The filename is terminated by a
  70  *   colon, and the function name is terminated by parenthesis.
  71  *
  72  * - The message text is made up of zero or more lines, each terminated by
  73  *   a newline.
  74  */
  75 
  76 /* -------------------------------------------------------------------------- **
  77  * External variables.
  78  *
  79  *  dbf           - Global debug file handle.
  80  *  debugf        - Debug file name.
  81  *  append_log    - If True, then the output file will be opened in append
  82  *                  mode.
  83  *  DEBUGLEVEL    - System-wide debug message limit.  Messages with message-
  84  *                  levels higher than DEBUGLEVEL will not be processed.
  85  */
  86 
  87 FILE *dbf = NULL;
  88 pstring debugf = "";
  89 BOOL append_log = False;
  90 int DEBUGLEVEL = 1;
  91 
  92 
  93 /* -------------------------------------------------------------------------- **
  94  * Internal variables.
  95  *
  96  *  stdout_logging  - Default False, if set to True then dbf will be set to
  97  *                    stdout and debug output will go to dbf only, and not
  98  *                    to syslog.  Set in setup_logging() and read in Debug1().
  99  *
 100  *  syslog_level    - Internal copy of the message debug level.  Written by
 101  *                    dbghdr() and read by Debug1().
 102  *
 103  *  format_bufr     - Used to format debug messages.  The dbgtext() function
 104  *                    prints debug messages to a string, and then passes the
 105  *                    string to format_debug_text(), which uses format_bufr
 106  *                    to build the formatted output.
 107  *
 108  *  format_pos      - Marks the first free byte of the format_bufr.
 109  */
 110 
 111 static BOOL stdout_logging = False;
 112 static pstring format_bufr = { '\0' };
 113 
 114 static size_t format_pos = 0;
 115 
 116 
 117 /* -------------------------------------------------------------------------- **
 118  * Functions...
 119  */
 120 
 121 /* ************************************************************************** **
 122  * get ready for syslog stuff
 123  * ************************************************************************** **
 124  */
 125 void
 126 setup_logging (const char *pname, BOOL interactive)
     /* [previous][next][first][last][top][bottom][index][help]  */
 127 {
 128     (void) pname;
 129     if (interactive)
 130     {
 131         stdout_logging = True;
 132         dbf = stderr;
 133     }
 134 }                               /* setup_logging */
 135 
 136 /* ************************************************************************** **
 137  * Write an debug message on the debugfile.
 138  * This is called by dbghdr() and format_debug_text().
 139  * ************************************************************************** **
 140  */
 141 #ifdef HAVE_STDARG_H
 142 int
 143 Debug1 (const char *format_str, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 144 {
 145 #else
 146 int
 147 Debug1 (va_alist)
     /* [previous][next][first][last][top][bottom][index][help]  */
 148      va_dcl
 149 {
 150     const char *format_str;
 151 #endif
 152     va_list ap;
 153     int old_errno = errno;
 154 
 155     if (stdout_logging)
 156     {
 157 #ifdef HAVE_STDARG_H
 158         va_start (ap, format_str);
 159 #else
 160         va_start (ap);
 161         format_str = va_arg (ap, const char *);
 162 #endif
 163         (void) vfprintf (dbf, format_str, ap);
 164         va_end (ap);
 165         errno = old_errno;
 166         return (0);
 167     }
 168 
 169     if (!dbf && *debugf)
 170     {
 171         mode_t oldumask = umask (022);
 172 
 173         if (append_log)
 174             dbf = sys_fopen (debugf, "a");
 175         else
 176             dbf = sys_fopen (debugf, "w");
 177         (void) umask (oldumask);
 178         if (dbf)
 179         {
 180             setbuf (dbf, NULL);
 181         }
 182         else
 183         {
 184             errno = old_errno;
 185             return (0);
 186         }
 187     }
 188 
 189     if (dbf)
 190     {
 191 #ifdef HAVE_STDARG_H
 192         va_start (ap, format_str);
 193 #else
 194         va_start (ap);
 195         format_str = va_arg (ap, const char *);
 196 #endif
 197         (void) vfprintf (dbf, format_str, ap);
 198         va_end (ap);
 199         (void) fflush (dbf);
 200     }
 201 
 202     errno = old_errno;
 203 
 204     return (0);
 205 }                               /* Debug1 */
 206 
 207 
 208 /* ************************************************************************** **
 209  * Print the buffer content via Debug1(), then reset the buffer.
 210  *
 211  *  Input:  none
 212  *  Output: none
 213  *
 214  * ************************************************************************** **
 215  */
 216 static void
 217 bufr_print (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 218 {
 219     format_bufr[format_pos] = '\0';
 220     (void) Debug1 ("%s", format_bufr);
 221     format_pos = 0;
 222 }                               /* bufr_print */
 223 
 224 /* ************************************************************************** **
 225  * Format the debug message text.
 226  *
 227  *  Input:  msg - Text to be added to the "current" debug message text.
 228  *
 229  *  Output: none.
 230  *
 231  *  Notes:  The purpose of this is two-fold.  First, each call to syslog()
 232  *          (used by Debug1(), see above) generates a new line of syslog
 233  *          output.  This is fixed by storing the partial lines until the
 234  *          newline character is encountered.  Second, printing the debug
 235  *          message lines when a newline is encountered allows us to add
 236  *          spaces, thus indenting the body of the message and making it
 237  *          more readable.
 238  *
 239  * ************************************************************************** **
 240  */
 241 static void
 242 format_debug_text (char *msg)
     /* [previous][next][first][last][top][bottom][index][help]  */
 243 {
 244     size_t i;
 245     BOOL timestamp = (!stdout_logging && (lp_timestamp_logs () || !(lp_loaded ())));
 246 
 247     for (i = 0; msg[i]; i++)
 248     {
 249         /* Indent two spaces at each new line. */
 250         if (timestamp && 0 == format_pos)
 251         {
 252             format_bufr[0] = format_bufr[1] = ' ';
 253             format_pos = 2;
 254         }
 255 
 256         /* If there's room, copy the character to the format buffer. */
 257         if (format_pos < FORMAT_BUFR_MAX)
 258             format_bufr[format_pos++] = msg[i];
 259 
 260         /* If a newline is encountered, print & restart. */
 261         if ('\n' == msg[i])
 262             bufr_print ();
 263 
 264         /* If the buffer is full dump it out, reset it, and put out a line
 265          * continuation indicator.
 266          */
 267         if (format_pos >= FORMAT_BUFR_MAX)
 268         {
 269             bufr_print ();
 270             (void) Debug1 (" +>\n");
 271         }
 272     }
 273 
 274     /* Just to be safe... */
 275     format_bufr[format_pos] = '\0';
 276 }                               /* format_debug_text */
 277 
 278 /* ************************************************************************** **
 279  * Flush debug output, including the format buffer content.
 280  *
 281  *  Input:  none
 282  *  Output: none
 283  *
 284  * ************************************************************************** **
 285  */
 286 void
 287 dbgflush (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 288 {
 289     bufr_print ();
 290     (void) fflush (dbf);
 291 }                               /* dbgflush */
 292 
 293 /* ************************************************************************** **
 294  * Print a Debug Header.
 295  *
 296  *  Input:  level - Debug level of the message (not the system-wide debug
 297  *                  level.
 298  *          file  - Pointer to a string containing the name of the file
 299  *                  from which this function was called, or an empty string
 300  *                  if the __FILE__ macro is not implemented.
 301  *          func  - Pointer to a string containing the name of the function
 302  *                  from which this function was called, or an empty string
 303  *                  if the __FUNCTION__ macro is not implemented.
 304  *          line  - line number of the call to dbghdr, assuming __LINE__
 305  *                  works.
 306  *
 307  *  Output: Always True.  This makes it easy to fudge a call to dbghdr()
 308  *          in a macro, since the function can be called as part of a test.
 309  *          Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) )
 310  *
 311  *  Notes:  This function takes care of setting syslog_level.
 312  *
 313  * ************************************************************************** **
 314  */
 315 BOOL
 316 dbghdr (int level, const char *file, const char *func, int line)
     /* [previous][next][first][last][top][bottom][index][help]  */
 317 {
 318     if (format_pos)
 319     {
 320         /* This is a fudge.  If there is stuff sitting in the format_bufr, then
 321          * the *right* thing to do is to call
 322          *   format_debug_text( "\n" );
 323          * to write the remainder, and then proceed with the new header.
 324          * Unfortunately, there are several places in the code at which
 325          * the DEBUG() macro is used to build partial lines.  That in mind,
 326          * we'll work under the assumption that an incomplete line indicates
 327          * that a new header is *not* desired.
 328          */
 329         return (True);
 330     }
 331 
 332     /* Don't print a header if we're logging to stdout. */
 333     if (stdout_logging)
 334         return (True);
 335 
 336     /* Print the header if timestamps are turned on.  If parameters are
 337      * not yet loaded, then default to timestamps on.
 338      */
 339     if (lp_timestamp_logs () || !(lp_loaded ()))
 340     {
 341         /* Print it all out at once to prevent split syslog output. */
 342         (void) Debug1 ("[%s, %d] %s:%s(%d)\n", timestring (), level, file, func, line);
 343     }
 344 
 345     return (True);
 346 }                               /* dbghdr */
 347 
 348 /* ************************************************************************** **
 349  * Add text to the body of the "current" debug message via the format buffer.
 350  *
 351  *  Input:  format_str  - Format string, as used in printf(), et. al.
 352  *          ...         - Variable argument list.
 353  *
 354  *  ..or..  va_alist    - Old style variable parameter list starting point.
 355  *
 356  *  Output: Always True.  See dbghdr() for more info, though this is not
 357  *          likely to be used in the same way.
 358  *
 359  * ************************************************************************** **
 360  */
 361 #ifdef HAVE_STDARG_H
 362 BOOL
 363 dbgtext (const char *format_str, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 364 {
 365     va_list ap;
 366     pstring msgbuf;
 367 
 368     va_start (ap, format_str);
 369     vslprintf (msgbuf, sizeof (msgbuf) - 1, format_str, ap);
 370     va_end (ap);
 371 
 372     format_debug_text (msgbuf);
 373 
 374     return (True);
 375 }                               /* dbgtext */
 376 
 377 #else
 378 BOOL
 379 dbgtext (va_alist)
     /* [previous][next][first][last][top][bottom][index][help]  */
 380      va_dcl
 381 {
 382     char *format_str;
 383     va_list ap;
 384     pstring msgbuf;
 385 
 386     va_start (ap);
 387     format_str = va_arg (ap, char *);
 388     vslprintf (msgbuf, sizeof (msgbuf) - 1, format_str, ap);
 389     va_end (ap);
 390 
 391     format_debug_text (msgbuf);
 392 
 393     return (True);
 394 }                               /* dbgtext */
 395 
 396 #endif
 397 
 398 /* ************************************************************************** */

/* [previous][next][first][last][top][bottom][index][help]  */