3 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/stdarg.h>
12 #include <ac/stdlib.h>
13 #include <ac/string.h>
17 #include <ac/syslog.h>
21 #include "ldap_defaults.h"
30 static struct DEBUGLEVEL **levelArray;
31 static long numLevels = 0;
33 static FILE *log_file = NULL;
34 static int global_level = 0;
37 static int use_syslog = 0;
39 static int debug2syslog(int l) {
41 case LDAP_LEVEL_EMERG: return LOG_EMERG;
42 case LDAP_LEVEL_ALERT: return LOG_ALERT;
43 case LDAP_LEVEL_CRIT: return LOG_CRIT;
44 case LDAP_LEVEL_ERR: return LOG_ERR;
45 case LDAP_LEVEL_WARNING: return LOG_WARNING;
46 case LDAP_LEVEL_NOTICE: return LOG_NOTICE;
47 case LDAP_LEVEL_INFO: return LOG_INFO;
53 static char *lutil_levels[] = {"emergency", "alert", "critical",
54 "error", "warning", "notice",
55 "information", "entry", "args",
56 "results", "detail1", "detail2",
59 int lutil_mnem2level( const char *level )
62 for( i = 0; lutil_levels[i] != NULL; i++ )
64 if ( !strcasecmp( level, lutil_levels[i] ) )
72 static void addSubsys( const char *subsys, int level )
76 if ( !strcasecmp( subsys, "global") ) global_level = level;
78 for( i = 0; i < numLevels; i++ )
80 if ( levelArray[i] == NULL )
82 levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
83 levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
84 strcpy ( levelArray[i]->subsystem, subsys );
85 levelArray[i]->level = level;
88 if( !strcasecmp( subsys, levelArray[i]->subsystem ) )
90 levelArray[i]->level = level;
94 levelArray = (struct DEBUGLEVEL**)ber_memrealloc( levelArray, sizeof( struct DEBUGLEVEL* ) * (numLevels + 10) );
95 for( j = numLevels; j < (numLevels + 10); j++ )
100 levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
101 levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
102 strcpy( levelArray[i]->subsystem, subsys );
103 levelArray[i]->level = level;
107 void lutil_set_debug_level( const char* subsys, int level )
109 addSubsys( subsys, level );
112 int lutil_debug_file( FILE *file )
115 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
122 const char *subsys, int level,
123 const char *fmt, va_list vl )
131 if ( levelArray == NULL ) return; /* logging isn't set up */
134 * Look for the subsystem in the level array. When we find it,
135 * break out of the loop.
137 for( i = 0; i < numLevels; i++ ) {
138 if ( levelArray[i] == NULL ) break;
139 if ( ! strcasecmp( levelArray[i]->subsystem, subsys ) ) break;
143 * If we didn't find the subsystem, or the set level is less than
144 * the requested output level, don't output it.
146 if ( (level > global_level) &&
147 ((i > numLevels ) || (levelArray[i] == NULL) || ( level > levelArray[i]->level )) )
153 /* we're configured to use syslog */
155 vsyslog( debug2syslog(level), fmt, vl );
162 if( log_file == NULL ) {
163 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
165 if ( log_file == NULL )
166 log_file = fopen( "openldap.log", "w" );
168 if ( log_file == NULL )
171 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
178 * Use stderr unless file was specified via:
179 * ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
186 * Stick the time in the buffer to output when using Winsock
187 * as NT can't pipe to a timestamp program like Unix can.
188 * This, of course, makes some logs hard to read.
191 today = localtime( &now );
192 fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
193 today->tm_year + 1900, today->tm_mon + 1,
194 today->tm_mday, today->tm_hour,
195 today->tm_min, today->tm_sec );
199 * format the output data.
201 vfprintf( file, fmt, vl );
205 * The primary logging routine. Takes the subsystem being logged from, the
206 * level of the log output and the format and data. Send this on to the
207 * internal routine with the print file, if any.
209 void lutil_log( const char *subsys, int level, const char *fmt, ... )
211 FILE* outfile = NULL;
214 ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
215 lutil_log_int( outfile, subsys, level, fmt, vl );
219 void lutil_log_initialize(int argc, char **argv)
223 * Start by setting the hook for the libraries to use this logging
226 ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
228 if ( argc == 0 ) return;
230 * Now go through the command line options to set the debugging
233 for( i = 0; i < argc; i++ )
235 char *next = argv[i];
236 if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
240 char *optarg = argv[i+1];
241 char *index = strchr( optarg, '=' );
245 strcpy ( subsys, optarg );
246 level = atoi( index+1 );
247 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
248 lutil_set_debug_level( subsys, level );
253 global_level = atoi( optarg );
255 * if a negative number was used, make the global level the
256 * maximum sane level.
258 if ( global_level < 0 ) global_level = 65535;
264 void (lutil_debug)( int debug, int level, const char *fmt, ... )
269 if ( !(level & debug ) )
273 if( log_file == NULL ) {
274 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
276 if ( log_file == NULL )
277 log_file = fopen( "openldap.log", "w" );
279 if ( log_file == NULL )
282 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
287 #ifdef HAVE_VSNPRINTF
288 vsnprintf( buffer, sizeof(buffer), fmt, vl );
290 vsprintf( buffer, fmt, vl );
292 buffer[sizeof(buffer)-1] = '\0';
294 if( log_file != NULL ) {
295 fputs( buffer, log_file );
299 fputs( buffer, stderr );