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