If a debug class was explicitly set to zero the debug system would not
[kai/samba.git] / source3 / lib / debug.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /* -------------------------------------------------------------------------- **
25  * Defines...
26  *
27  *  FORMAT_BUFR_MAX - Index of the last byte of the format buffer;
28  *                    format_bufr[FORMAT_BUFR_MAX] should always be reserved
29  *                    for a terminating nul byte.
30  */
31
32 #define FORMAT_BUFR_MAX ( sizeof( format_bufr ) - 1 )
33
34 /* -------------------------------------------------------------------------- **
35  * This module implements Samba's debugging utility.
36  *
37  * The syntax of a debugging log file is represented as:
38  *
39  *  <debugfile> :== { <debugmsg> }
40  *
41  *  <debugmsg>  :== <debughdr> '\n' <debugtext>
42  *
43  *  <debughdr>  :== '[' TIME ',' LEVEL ']' [ [FILENAME ':'] [FUNCTION '()'] ]
44  *
45  *  <debugtext> :== { <debugline> }
46  *
47  *  <debugline> :== TEXT '\n'
48  *
49  * TEXT     is a string of characters excluding the newline character.
50  * LEVEL    is the DEBUG level of the message (an integer in the range 0..10).
51  * TIME     is a timestamp.
52  * FILENAME is the name of the file from which the debug message was generated.
53  * FUNCTION is the function from which the debug message was generated.
54  *
55  * Basically, what that all means is:
56  *
57  * - A debugging log file is made up of debug messages.
58  *
59  * - Each debug message is made up of a header and text.  The header is
60  *   separated from the text by a newline.
61  *
62  * - The header begins with the timestamp and debug level of the message
63  *   enclosed in brackets.  The filename and function from which the
64  *   message was generated may follow.  The filename is terminated by a
65  *   colon, and the function name is terminated by parenthesis.
66  *
67  * - The message text is made up of zero or more lines, each terminated by
68  *   a newline.
69  */
70
71 /* -------------------------------------------------------------------------- **
72  * External variables.
73  *
74  *  dbf           - Global debug file handle.
75  *  debugf        - Debug file name.
76  *  append_log    - If True, then the output file will be opened in append
77  *                  mode.
78  *  DEBUGLEVEL    - System-wide debug message limit.  Messages with message-
79  *                  levels higher than DEBUGLEVEL will not be processed.
80  */
81
82 FILE   *dbf        = NULL;
83 pstring debugf     = "";
84 BOOL    append_log = False;
85
86 int     DEBUGLEVEL_CLASS[DBGC_LAST];
87 BOOL    DEBUGLEVEL_CLASS_ISSET[DBGC_LAST];
88 int     DEBUGLEVEL = DEBUGLEVEL_CLASS;
89
90
91 /* -------------------------------------------------------------------------- **
92  * Internal variables.
93  *
94  *  stdout_logging  - Default False, if set to True then dbf will be set to
95  *                    stdout and debug output will go to dbf only, and not
96  *                    to syslog.  Set in setup_logging() and read in Debug1().
97  *
98  *  debug_count     - Number of debug messages that have been output.
99  *                    Used to check log size.
100  *
101  *  syslog_level    - Internal copy of the message debug level.  Written by
102  *                    dbghdr() and read by Debug1().
103  *
104  *  format_bufr     - Used to format debug messages.  The dbgtext() function
105  *                    prints debug messages to a string, and then passes the
106  *                    string to format_debug_text(), which uses format_bufr
107  *                    to build the formatted output.
108  *
109  *  format_pos      - Marks the first free byte of the format_bufr.
110  * 
111  *
112  *  log_overflow    - When this variable is True, never attempt to check the
113  *                    size of the log. This is a hack, so that we can write
114  *                    a message using DEBUG, from open_logs() when we
115  *                    are unable to open a new log file for some reason.
116  */
117
118 static BOOL    stdout_logging = False;
119 static int     debug_count    = 0;
120 #ifdef WITH_SYSLOG
121 static int     syslog_level   = 0;
122 #endif
123 static pstring format_bufr    = { '\0' };
124 static size_t     format_pos     = 0;
125 static BOOL    log_overflow   = False;
126
127 /*
128 * Define all the debug class selection names here. Names *MUST NOT* contain 
129 * white space. There must be one name for each DBGC_<class name>, and they 
130 * must be in the table in the order of DBGC_<class name>.. 
131 */
132 char *classname_table[] = {
133         "all",               /* DBGC_ALL; index refs traditional DEBUGLEVEL */
134         "tdb",               /* DBGC_TDB          */
135         "printdrivers",      /* DBGC_PRINTDRIVERS */
136         "lanman",            /* DBGC_LANMAN       */
137         "smb",               /* DBGC_SMB          */
138         "rpc",               /* DBGC_RPC          */
139         "rpc_hdr",           /* DBGC_RPC_HDR      */
140         "bdc",               /* DBGC_BDC          */
141 };
142
143
144 /* -------------------------------------------------------------------------- **
145  * Functions...
146  */
147
148 /****************************************************************************
149 utility access to debug class names's
150 ****************************************************************************/
151 char* debug_classname_from_index(int ndx)
152 {
153         return classname_table[ndx];
154 }
155
156 /****************************************************************************
157 utility to translate names to debug class index's
158 ****************************************************************************/
159 int debug_lookup_classname(char* classname)
160 {
161         int i;
162
163         if (!classname) return -1;
164
165         for (i=0; i<DBGC_LAST; i++) {
166                 if (strcmp(classname, classname_table[i])==0)
167                         return i;
168         }
169         return -1;
170 }
171
172 /****************************************************************************
173 parse the debug levels from smbcontrol. Example debug level parameter:
174   printdrivers:7
175 ****************************************************************************/
176 BOOL debug_parse_params(char **params, int *debuglevel_class,
177                         BOOL *debuglevel_class_isset)
178 {
179         int   i, ndx;
180         char *class_name;
181         char *class_level;
182         
183         /* Set the new debug level array to the current DEBUGLEVEL array */
184         memcpy(debuglevel_class, DEBUGLEVEL_CLASS, sizeof(DEBUGLEVEL_CLASS));
185
186         /* Allow DBGC_ALL to be specifies w/o requiring its class name e.g."10"  
187          * v.s. "all:10", this is the traditional way to set DEBUGLEVEL 
188          */
189         if (isdigit((int)params[0][0])) {
190                 debuglevel_class[DBGC_ALL] = atoi(params[0]);
191                 debuglevel_class_isset[DBGC_ALL] = True;
192                 i = 1; /* start processing at the next params */
193         }
194         else
195                 i = 0; /* DBGC_ALL not specified  OR class name was included */
196
197         /* Fill in new debug class levels */
198         for (; i < DBGC_LAST && params[i]; i++) {
199                 if ((class_name=strtok(params[i],":")) &&
200                         (class_level=strtok(NULL, "\0")) &&
201             ((ndx = debug_lookup_classname(class_name)) != -1)) {
202                                 debuglevel_class[ndx] = atoi(class_level);
203                                 debuglevel_class_isset[ndx] = True;
204                 } else {
205                         DEBUG(0,("debug_parse_params: unrecognized debug class name or format [%s]\n", params[i]));
206                         return False;
207                 }
208         }
209
210         return True;
211 }
212
213 /****************************************************************************
214 parse the debug levels from smb.conf. Example debug level string:
215   3 tdb:5 printdrivers:7
216 Note: the 1st param has no "name:" preceeding it.
217 ****************************************************************************/
218 BOOL debug_parse_levels(char *params_str)
219 {
220         int  i;
221         char *params[DBGC_LAST];
222         int  debuglevel_class[DBGC_LAST];       
223         BOOL debuglevel_class_isset[DBGC_LAST];
224
225         ZERO_ARRAY(params);
226         ZERO_ARRAY(debuglevel_class);
227         ZERO_ARRAY(debuglevel_class_isset);
228
229         if ((params[0]=strtok(params_str," ,"))) {
230                 for (i=1; i<DBGC_LAST;i++) {
231                         if ((params[i]=strtok(NULL," ,"))==NULL)
232                                 break;
233                 }
234         }
235         else
236                 return False;
237
238         if (debug_parse_params(params, debuglevel_class, 
239                                debuglevel_class_isset)) {
240                 debug_message(0, getpid(), (void*)debuglevel_class, sizeof(debuglevel_class));
241
242                 memcpy(DEBUGLEVEL_CLASS, debuglevel_class, 
243                        sizeof(debuglevel_class));
244
245                 memcpy(DEBUGLEVEL_CLASS_ISSET, debuglevel_class_isset,
246                        sizeof(debuglevel_class_isset));
247
248                 {
249                         int q;
250
251                         for (q = 0; q < DBGC_LAST; q++)
252                                 DEBUG(0, ("%s: %d/%d\n",
253                                           classname_table[q],
254                                           DEBUGLEVEL_CLASS[q],
255                                           DEBUGLEVEL_CLASS_ISSET[q]));
256                 }
257
258                 return True;
259         } else
260                 return False;
261 }
262
263 /****************************************************************************
264 receive a "set debug level" message
265 ****************************************************************************/
266 void debug_message(int msg_type, pid_t src, void *buf, size_t len)
267 {
268         struct debuglevel_message *dm = (struct debuglevel_message *)buf;
269         int i;
270
271         /* Set the new DEBUGLEVEL_CLASS array from the passed message */
272         memcpy(DEBUGLEVEL_CLASS, dm->debuglevel_class, sizeof(dm->debuglevel_class));
273         memcpy(DEBUGLEVEL_CLASS_ISSET, dm->debuglevel_class_isset, sizeof(dm->debuglevel_class_isset));
274
275         DEBUG(1,("INFO: Debug class %s level = %d   (pid %u from pid %u)\n",
276                         classname_table[DBGC_ALL],
277                         DEBUGLEVEL_CLASS[DBGC_ALL], (unsigned int)getpid(), (unsigned int)src));
278
279         for (i=1; i<DBGC_LAST; i++) {
280                 if (DEBUGLEVEL_CLASS[i])
281                          DEBUGADD(1,("INFO: Debug class %s level = %d\n", 
282                                                 classname_table[i], DEBUGLEVEL_CLASS[i]));
283         }
284 }
285
286
287 /****************************************************************************
288 send a "set debug level" message
289 ****************************************************************************/
290 void debug_message_send(pid_t pid, int level)
291 {
292         message_send_pid(pid, MSG_DEBUG, &level, sizeof(int), False);
293 }
294
295
296 /* ************************************************************************** **
297  * get ready for syslog stuff
298  * ************************************************************************** **
299  */
300 void setup_logging(char *pname, BOOL interactive)
301 {
302         message_register(MSG_DEBUG, debug_message);
303
304         /* reset to allow multiple setup calls, going from interactive to
305            non-interactive */
306         stdout_logging = False;
307         dbf = NULL;
308
309         if (interactive) {
310                 stdout_logging = True;
311                 dbf = stdout;
312         }
313 #ifdef WITH_SYSLOG
314         else {
315                 char *p = strrchr( pname,'/' );
316                 if (p)
317                         pname = p + 1;
318 #ifdef LOG_DAEMON
319                 openlog( pname, LOG_PID, SYSLOG_FACILITY );
320 #else /* for old systems that have no facility codes. */
321                 openlog( pname, LOG_PID );
322 #endif
323         }
324 #endif
325 } /* setup_logging */
326
327 /* ************************************************************************** **
328  * reopen the log files
329  * note that we now do this unconditionally
330  * We attempt to open the new debug fp before closing the old. This means
331  * if we run out of fd's we just keep using the old fd rather than aborting.
332  * Fix from dgibson@linuxcare.com.
333  * ************************************************************************** **
334  */
335
336 BOOL reopen_logs( void )
337 {
338         pstring fname;
339         mode_t oldumask;
340         FILE *new_dbf = NULL;
341         BOOL ret = True;
342
343         if (stdout_logging)
344                 return True;
345
346         if (DEBUGLEVEL_CLASS[ DBGC_ALL ] <= 0) {
347                 if (dbf) {
348                         (void)fclose(dbf);
349                         dbf = NULL;
350                 }
351                 return True;
352         }
353
354         oldumask = umask( 022 );
355   
356         pstrcpy(fname, debugf );
357         if (lp_loaded() && (*lp_logfile()))
358                 pstrcpy(fname, lp_logfile());
359
360         pstrcpy( debugf, fname );
361         if (append_log)
362                 new_dbf = sys_fopen( debugf, "a" );
363         else
364                 new_dbf = sys_fopen( debugf, "w" );
365
366         if (!new_dbf) {
367                 log_overflow = True;
368                 DEBUG(0, ("Unable to open new log file %s: %s\n", debugf, strerror(errno)));
369                 log_overflow = False;
370                 fflush(dbf);
371                 ret = False;
372         } else {
373                 setbuf(new_dbf, NULL);
374                 if (dbf)
375                         (void) fclose(dbf);
376                 dbf = new_dbf;
377         }
378
379         /* Fix from klausr@ITAP.Physik.Uni-Stuttgart.De
380          * to fix problem where smbd's that generate less
381          * than 100 messages keep growing the log.
382          */
383         force_check_log_size();
384         (void)umask(oldumask);
385
386         return ret;
387 }
388
389 /* ************************************************************************** **
390  * Force a check of the log size.
391  * ************************************************************************** **
392  */
393 void force_check_log_size( void )
394 {
395   debug_count = 100;
396 }
397
398 /***************************************************************************
399  Check to see if there is any need to check if the logfile has grown too big.
400 **************************************************************************/
401
402 BOOL need_to_check_log_size( void )
403 {
404         int maxlog;
405
406         if( debug_count++ < 100 )
407                 return( False );
408
409         maxlog = lp_max_log_size() * 1024;
410         if( !dbf || maxlog <= 0 ) {
411                 debug_count = 0;
412                 return(False);
413         }
414         return( True );
415 }
416
417 /* ************************************************************************** **
418  * Check to see if the log has grown to be too big.
419  * ************************************************************************** **
420  */
421
422 void check_log_size( void )
423 {
424         int         maxlog;
425         SMB_STRUCT_STAT st;
426
427         /*
428          *  We need to be root to check/change log-file, skip this and let the main
429          *  loop check do a new check as root.
430          */
431
432         if( geteuid() != 0 )
433                 return;
434
435         if(log_overflow || !need_to_check_log_size() )
436                 return;
437
438         maxlog = lp_max_log_size() * 1024;
439
440         if( sys_fstat( fileno( dbf ), &st ) == 0 && st.st_size > maxlog ) {
441                 (void)reopen_logs();
442                 if( dbf && get_file_size( debugf ) > maxlog ) {
443                         pstring name;
444
445                         slprintf( name, sizeof(name)-1, "%s.old", debugf );
446                         (void)rename( debugf, name );
447       
448                         if (!reopen_logs()) {
449                                 /* We failed to reopen a log - continue using the old name. */
450                                 (void)rename(name, debugf);
451                         }
452                 }
453         }
454
455         /*
456          * Here's where we need to panic if dbf == NULL..
457          */
458
459         if(dbf == NULL) {
460                 /* This code should only be reached in very strange
461                         circumstances. If we merely fail to open the new log we
462                         should stick with the old one. ergo this should only be
463                         reached when opening the logs for the first time: at
464                         startup or when the log level is increased from zero.
465                         -dwg 6 June 2000
466                 */
467                 dbf = sys_fopen( "/dev/console", "w" );
468                 if(dbf) {
469                         DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n",
470                                         debugf ));
471                 } else {
472                         /*
473                          * We cannot continue without a debug file handle.
474                          */
475                         abort();
476                 }
477         }
478         debug_count = 0;
479 } /* check_log_size */
480
481 /* ************************************************************************** **
482  * Write an debug message on the debugfile.
483  * This is called by dbghdr() and format_debug_text().
484  * ************************************************************************** **
485  */
486  int Debug1( char *format_str, ... )
487 {
488   va_list ap;  
489   int old_errno = errno;
490
491   if( stdout_logging )
492     {
493     va_start( ap, format_str );
494     if(dbf)
495       (void)vfprintf( dbf, format_str, ap );
496     va_end( ap );
497     errno = old_errno;
498     return( 0 );
499     }
500   
501 #ifdef WITH_SYSLOG
502   if( !lp_syslog_only() )
503 #endif
504     {
505     if( !dbf )
506       {
507       mode_t oldumask = umask( 022 );
508
509       if( append_log )
510         dbf = sys_fopen( debugf, "a" );
511       else
512         dbf = sys_fopen( debugf, "w" );
513       (void)umask( oldumask );
514       if( dbf )
515         {
516         setbuf( dbf, NULL );
517         }
518       else
519         {
520         errno = old_errno;
521         return(0);
522         }
523       }
524     }
525
526 #ifdef WITH_SYSLOG
527   if( syslog_level < lp_syslog() )
528     {
529     /* map debug levels to syslog() priorities
530      * note that not all DEBUG(0, ...) calls are
531      * necessarily errors
532      */
533     static int priority_map[] = { 
534       LOG_ERR,     /* 0 */
535       LOG_WARNING, /* 1 */
536       LOG_NOTICE,  /* 2 */
537       LOG_INFO,    /* 3 */
538       };
539     int     priority;
540     pstring msgbuf;
541
542     if( syslog_level >= ( sizeof(priority_map) / sizeof(priority_map[0]) )
543      || syslog_level < 0)
544       priority = LOG_DEBUG;
545     else
546       priority = priority_map[syslog_level];
547       
548     va_start( ap, format_str );
549     vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap );
550     va_end( ap );
551       
552     msgbuf[255] = '\0';
553     syslog( priority, "%s", msgbuf );
554     }
555 #endif
556   
557   check_log_size();
558
559 #ifdef WITH_SYSLOG
560   if( !lp_syslog_only() )
561 #endif
562     {
563     va_start( ap, format_str );
564     if(dbf)
565       (void)vfprintf( dbf, format_str, ap );
566     va_end( ap );
567     if(dbf)
568       (void)fflush( dbf );
569     }
570
571   errno = old_errno;
572
573   return( 0 );
574   } /* Debug1 */
575
576
577 /* ************************************************************************** **
578  * Print the buffer content via Debug1(), then reset the buffer.
579  *
580  *  Input:  none
581  *  Output: none
582  *
583  * ************************************************************************** **
584  */
585 static void bufr_print( void )
586   {
587   format_bufr[format_pos] = '\0';
588   (void)Debug1( "%s", format_bufr );
589   format_pos = 0;
590   } /* bufr_print */
591
592 /* ************************************************************************** **
593  * Format the debug message text.
594  *
595  *  Input:  msg - Text to be added to the "current" debug message text.
596  *
597  *  Output: none.
598  *
599  *  Notes:  The purpose of this is two-fold.  First, each call to syslog()
600  *          (used by Debug1(), see above) generates a new line of syslog
601  *          output.  This is fixed by storing the partial lines until the
602  *          newline character is encountered.  Second, printing the debug
603  *          message lines when a newline is encountered allows us to add
604  *          spaces, thus indenting the body of the message and making it
605  *          more readable.
606  *
607  * ************************************************************************** **
608  */
609 static void format_debug_text( char *msg )
610   {
611   size_t i;
612   BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || 
613                                         !(lp_loaded())));
614
615   for( i = 0; msg[i]; i++ )
616     {
617     /* Indent two spaces at each new line. */
618     if(timestamp && 0 == format_pos)
619       {
620       format_bufr[0] = format_bufr[1] = ' ';
621       format_pos = 2;
622       }
623
624     /* If there's room, copy the character to the format buffer. */
625     if( format_pos < FORMAT_BUFR_MAX )
626       format_bufr[format_pos++] = msg[i];
627
628     /* If a newline is encountered, print & restart. */
629     if( '\n' == msg[i] )
630       bufr_print();
631
632     /* If the buffer is full dump it out, reset it, and put out a line
633      * continuation indicator.
634      */
635     if( format_pos >= FORMAT_BUFR_MAX )
636       {
637       bufr_print();
638       (void)Debug1( " +>\n" );
639       }
640     }
641
642   /* Just to be safe... */
643   format_bufr[format_pos] = '\0';
644   } /* format_debug_text */
645
646 /* ************************************************************************** **
647  * Flush debug output, including the format buffer content.
648  *
649  *  Input:  none
650  *  Output: none
651  *
652  * ************************************************************************** **
653  */
654 void dbgflush( void )
655   {
656   bufr_print();
657   if(dbf)
658     (void)fflush( dbf );
659   } /* dbgflush */
660
661 /* ************************************************************************** **
662  * Print a Debug Header.
663  *
664  *  Input:  level - Debug level of the message (not the system-wide debug
665  *                  level.
666  *          file  - Pointer to a string containing the name of the file
667  *                  from which this function was called, or an empty string
668  *                  if the __FILE__ macro is not implemented.
669  *          func  - Pointer to a string containing the name of the function
670  *                  from which this function was called, or an empty string
671  *                  if the __FUNCTION__ macro is not implemented.
672  *          line  - line number of the call to dbghdr, assuming __LINE__
673  *                  works.
674  *
675  *  Output: Always True.  This makes it easy to fudge a call to dbghdr()
676  *          in a macro, since the function can be called as part of a test.
677  *          Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) )
678  *
679  *  Notes:  This function takes care of setting syslog_level.
680  *
681  * ************************************************************************** **
682  */
683
684 BOOL dbghdr( int level, char *file, char *func, int line )
685 {
686   /* Ensure we don't lose any real errno value. */
687   int old_errno = errno;
688
689   if( format_pos ) {
690     /* This is a fudge.  If there is stuff sitting in the format_bufr, then
691      * the *right* thing to do is to call
692      *   format_debug_text( "\n" );
693      * to write the remainder, and then proceed with the new header.
694      * Unfortunately, there are several places in the code at which
695      * the DEBUG() macro is used to build partial lines.  That in mind,
696      * we'll work under the assumption that an incomplete line indicates
697      * that a new header is *not* desired.
698      */
699     return( True );
700   }
701
702 #ifdef WITH_SYSLOG
703   /* Set syslog_level. */
704   syslog_level = level;
705 #endif
706
707   /* Don't print a header if we're logging to stdout. */
708   if( stdout_logging )
709     return( True );
710
711   /* Print the header if timestamps are turned on.  If parameters are
712    * not yet loaded, then default to timestamps on.
713    */
714   if( lp_timestamp_logs() || !(lp_loaded()) ) {
715     char header_str[200];
716
717         header_str[0] = '\0';
718
719         if( lp_debug_pid())
720           slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)sys_getpid());
721
722         if( lp_debug_uid()) {
723       size_t hs_len = strlen(header_str);
724           slprintf(header_str + hs_len,
725                sizeof(header_str) - 1 - hs_len,
726                            ", effective(%u, %u), real(%u, %u)",
727                (unsigned int)geteuid(), (unsigned int)getegid(),
728                            (unsigned int)getuid(), (unsigned int)getgid()); 
729         }
730   
731     /* Print it all out at once to prevent split syslog output. */
732     (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
733                   timestring(lp_debug_hires_timestamp()), level,
734                                   header_str, file, func, line );
735   }
736
737   errno = old_errno;
738   return( True );
739 }
740
741 /* ************************************************************************** **
742  * Add text to the body of the "current" debug message via the format buffer.
743  *
744  *  Input:  format_str  - Format string, as used in printf(), et. al.
745  *          ...         - Variable argument list.
746  *
747  *  ..or..  va_alist    - Old style variable parameter list starting point.
748  *
749  *  Output: Always True.  See dbghdr() for more info, though this is not
750  *          likely to be used in the same way.
751  *
752  * ************************************************************************** **
753  */
754  BOOL dbgtext( char *format_str, ... )
755   {
756   va_list ap;
757   pstring msgbuf;
758
759   va_start( ap, format_str ); 
760   vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap );
761   va_end( ap );
762
763   format_debug_text( msgbuf );
764
765   return( True );
766   } /* dbgtext */
767
768
769 /* ************************************************************************** */