]> git.sur5r.net Git - openldap/blob - libraries/liblber/debug.c
Add BER_BVNULL
[openldap] / libraries / liblber / debug.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdarg.h>
12 #include <ac/stdlib.h>
13 #include <ac/string.h>
14 #include <ac/time.h>
15 #include <ac/ctype.h>
16
17 #ifdef LDAP_SYSLOG
18 #include <ac/syslog.h>
19 #endif
20
21 #include "ldap_log.h"
22 #include "ldap_defaults.h"
23 #include "lber.h"
24 #include "ldap_pvt.h"
25
26 struct DEBUGLEVEL
27 {
28         char *subsystem;
29         int  level;
30 };
31
32 int ldap_loglevels[LDAP_SUBSYS_NUM];
33 static long   numLevels = 0;
34
35 static FILE *log_file = NULL;
36 static int global_level = 0;
37
38 #ifdef LDAP_SYSLOG
39 static int use_syslog = 0;
40
41 static int debug2syslog(int l) {
42         switch (l) {
43         case LDAP_LEVEL_EMERG:  return LOG_EMERG;
44         case LDAP_LEVEL_ALERT:  return LOG_ALERT;
45         case LDAP_LEVEL_CRIT:   return LOG_CRIT;
46         case LDAP_LEVEL_ERR:    return LOG_ERR;
47         case LDAP_LEVEL_WARNING:        return LOG_WARNING;
48         case LDAP_LEVEL_NOTICE: return LOG_NOTICE;
49         case LDAP_LEVEL_INFO:   return LOG_INFO;
50         }
51         return LOG_DEBUG;
52 }
53 #endif
54
55 static char *lutil_levels[] = {"emergency", "alert", "critical",
56                            "error", "warning", "notice",
57                            "information", "entry", "args",
58                            "results", "detail1", "detail2",
59                            NULL};
60
61 static char *lutil_subsys[LDAP_SUBSYS_NUM] = {"global","operation", "transport",
62                                 "connection", "filter", "ber", 
63                                 "config", "acl", "cache", "index", 
64                                 "ldif", "tools", "slapd", "slurpd",
65                                 "backend", "back_bdb", "back_ldbm", 
66                                 "back_ldap", "back_meta", "back_mon" };
67
68 int lutil_mnem2subsys( const char *subsys )
69 {
70     int i;
71     for( i = 0; i < LDAP_SUBSYS_NUM; i++ )
72     {
73                 if ( !strcasecmp( subsys, lutil_subsys[i] ) )
74                 {
75                 return i;
76                 }
77     }
78     return -1;
79 }
80
81 void lutil_set_all_backends( level )
82 {
83     int i;
84
85     for( i = 0; i < LDAP_SUBSYS_NUM; i++ )
86     {
87                 if ( !strncasecmp( "back_", lutil_subsys[i], strlen("back_") ) )
88                 {
89                         ldap_loglevels[i] = level;
90                 }
91     }
92 }
93
94 int lutil_mnem2level( const char *level )
95 {
96     int i;
97     for( i = 0; lutil_levels[i] != NULL; i++ )
98     {
99         if ( !strcasecmp( level, lutil_levels[i] ) )
100         {
101             return i;
102         }
103     }
104     return -1;
105 }
106
107 static int addSubsys( const char *subsys, int level )
108 {
109         int subsys_num;
110
111         if ( !strcasecmp( subsys, "backend" ) )
112         {
113                 lutil_set_all_backends( level );
114                 return level;
115         }
116         else
117         {
118                 subsys_num = lutil_mnem2subsys(subsys);
119                 if(subsys_num < 0)
120                 {
121                         fprintf(stderr, "Unknown Subsystem name [ %s ] - Discarded\n", 
122                                 subsys);
123                         fflush(stderr);
124                         return -1;
125                 }
126
127                 ldap_loglevels[subsys_num] = level;
128                 return level;
129         }
130         return -1;
131 }
132
133 int lutil_set_debug_level( const char* subsys, int level )
134 {
135     return( addSubsys( subsys, level ) );
136 }
137
138 int lutil_debug_file( FILE *file )
139 {
140         log_file = file;
141         ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
142
143         return 0;
144 }
145
146 void lutil_log_int(
147         FILE* file,
148         const char *subsys, int level,
149         const char *fmt, va_list vl )
150 {
151 #ifdef HAVE_WINSOCK
152         time_t now;
153         struct tm *today;
154 #endif
155         size_t i;
156         char * t_subsys;
157         char * tmp;
158
159         t_subsys = strdup(subsys);
160         
161         for(tmp = t_subsys, i = 0; i < strlen(t_subsys); i++, tmp++)
162                 *tmp = TOUPPER( (unsigned char) *tmp );
163
164 #ifdef LDAP_SYSLOG
165         /* we're configured to use syslog */
166         if( use_syslog ) {
167 #ifdef HAVE_VSYSLOG
168                 vsyslog( debug2syslog(level), fmt, vl );
169 #else
170                 char data[4096];
171                 vsnprintf( data, sizeof(data), fmt, vl );
172                 syslog( debug2syslog(level), data );
173 #endif
174                 return;
175         }
176 #endif
177
178 #if 0
179 #ifdef HAVE_WINSOCK
180         if( log_file == NULL ) {
181                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
182
183                 if ( log_file == NULL )
184                         log_file = fopen( "openldap.log", "w" );
185
186                 if ( log_file == NULL )
187                         return;
188
189                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
190         }
191 #endif
192 #endif
193
194         if( file == NULL ) {
195                 /*
196                  * Use stderr unless file was specified via:
197                  *   ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
198                  */
199                 file = stderr;
200         }
201
202 #ifdef HAVE_WINSOCK
203         /*
204          * Stick the time in the buffer to output when using Winsock
205          * as NT can't pipe to a timestamp program like Unix can.
206          * This, of course, makes some logs hard to read.
207      */
208         time( &now );
209         today = localtime( &now );
210         fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
211                 today->tm_year + 1900, today->tm_mon + 1,
212                 today->tm_mday, today->tm_hour,
213                 today->tm_min, today->tm_sec );
214 #endif
215
216         /*
217          * format the output data.
218          */
219
220         fprintf(file, "\n%s:: ", t_subsys ); 
221         vfprintf( file, fmt, vl );
222         fflush( file );
223 }
224
225 /*
226  * The primary logging routine.  Takes the subsystem being logged from, the
227  * level of the log output and the format and data.  Send this on to the
228  * internal routine with the print file, if any.
229  */
230 void lutil_log( const int subsys, int level, const char *fmt, ... )
231 {
232         FILE* outfile = NULL;
233         va_list vl;
234         va_start( vl, fmt );
235         ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
236         lutil_log_int( outfile, lutil_subsys[subsys], level, fmt, vl );
237         va_end( vl );
238 }
239
240 void lutil_log_initialize(int argc, char **argv)
241 {
242     int i;
243     /*
244      * Start by setting the hook for the libraries to use this logging
245      * routine.
246      */
247     ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
248
249     if ( argc == 0 ) return;
250     /*
251      * Now go through the command line options to set the debugging
252      * levels
253      */
254     for( i = 0; i < argc; i++ )
255     {
256                 char *next = argv[i];
257         
258                 if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
259                 {
260                         char subsys[64];
261                         int level;
262                 char *optarg = argv[i+1];
263                 char *index = strchr( optarg, '=' );
264                 if ( index != NULL )
265                 {
266                                 *index = 0;
267                                 strcpy ( subsys, optarg );
268                                 level = atoi( index+1 );
269                                 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
270                                 lutil_set_debug_level( subsys, level );
271                                 *index = '=';
272                 }
273                 else
274                 {
275                                 global_level = atoi( optarg );
276                                 ldap_loglevels[0] = global_level;
277                                 /* 
278                                 * if a negative number was used, make the global level the
279                                 * maximum sane level.
280                                 */
281                                 if ( global_level < 0 ) 
282                                 {
283                                         global_level = 65535;
284                                         ldap_loglevels[0] = 65535;
285                         }
286                 }
287                 }
288     }
289 }
290
291 void (lutil_debug)( int debug, int level, const char *fmt, ... )
292 {
293         char buffer[4096];
294         va_list vl;
295
296         if ( !(level & debug ) )
297                 return;
298
299 #ifdef HAVE_WINSOCK
300         if( log_file == NULL ) {
301                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
302
303                 if ( log_file == NULL )
304                         log_file = fopen( "openldap.log", "w" );
305
306                 if ( log_file == NULL )
307                         return;
308
309                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
310         }
311 #endif
312         va_start( vl, fmt );
313
314 #ifdef HAVE_VSNPRINTF
315         vsnprintf( buffer, sizeof(buffer), fmt, vl );
316 #else
317         vsprintf( buffer, fmt, vl );
318 #endif
319         buffer[sizeof(buffer)-1] = '\0';
320
321         if( log_file != NULL ) {
322                 fputs( buffer, log_file );
323                 fflush( log_file );
324         }
325
326         fputs( buffer, stderr );
327         va_end( vl );
328 }