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-2020 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) /**/ 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, ...) /*
*/ 144 { 145 #else 146 int 147 Debug1 (va_alist) /*
*/ 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) /*
*/ 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) /*
*/ 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) /*
*/ 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) /*
*/ 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, ...) /*
*/ 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) /*
*/ 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 /* ************************************************************************** */