]> git.sur5r.net Git - openldap/blob - libraries/liblber/debug.c
92b52d67b75c3c950079ff850cc476f2a0f80641
[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                 vsyslog( debug2syslog(level), fmt, vl );
168                 return;
169         }
170 #endif
171
172 #if 0
173 #ifdef HAVE_WINSOCK
174         if( log_file == NULL ) {
175                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
176
177                 if ( log_file == NULL )
178                         log_file = fopen( "openldap.log", "w" );
179
180                 if ( log_file == NULL )
181                         return;
182
183                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
184         }
185 #endif
186 #endif
187
188         if( file == NULL ) {
189                 /*
190                  * Use stderr unless file was specified via:
191                  *   ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
192                  */
193                 file = stderr;
194         }
195
196 #ifdef HAVE_WINSOCK
197         /*
198          * Stick the time in the buffer to output when using Winsock
199          * as NT can't pipe to a timestamp program like Unix can.
200          * This, of course, makes some logs hard to read.
201      */
202         time( &now );
203         today = localtime( &now );
204         fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
205                 today->tm_year + 1900, today->tm_mon + 1,
206                 today->tm_mday, today->tm_hour,
207                 today->tm_min, today->tm_sec );
208 #endif
209
210         /*
211          * format the output data.
212          */
213
214         fprintf(file, "\n%s:: ", t_subsys ); 
215         vfprintf( file, fmt, vl );
216         fflush( file );
217 }
218
219 /*
220  * The primary logging routine.  Takes the subsystem being logged from, the
221  * level of the log output and the format and data.  Send this on to the
222  * internal routine with the print file, if any.
223  */
224 void lutil_log( const int subsys, int level, const char *fmt, ... )
225 {
226         FILE* outfile = NULL;
227         va_list vl;
228         va_start( vl, fmt );
229         ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
230         lutil_log_int( outfile, lutil_subsys[subsys], level, fmt, vl );
231         va_end( vl );
232 }
233
234 void lutil_log_initialize(int argc, char **argv)
235 {
236     int i;
237     /*
238      * Start by setting the hook for the libraries to use this logging
239      * routine.
240      */
241     ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
242
243     if ( argc == 0 ) return;
244     /*
245      * Now go through the command line options to set the debugging
246      * levels
247      */
248     for( i = 0; i < argc; i++ )
249     {
250                 char *next = argv[i];
251         
252                 if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
253                 {
254                         char subsys[64];
255                         int level;
256                 char *optarg = argv[i+1];
257                 char *index = strchr( optarg, '=' );
258                 if ( index != NULL )
259                 {
260                                 *index = 0;
261                                 strcpy ( subsys, optarg );
262                                 level = atoi( index+1 );
263                                 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
264                                 lutil_set_debug_level( subsys, level );
265                                 *index = '=';
266                 }
267                 else
268                 {
269                                 global_level = atoi( optarg );
270                                 ldap_loglevels[0] = global_level;
271                                 /* 
272                                 * if a negative number was used, make the global level the
273                                 * maximum sane level.
274                                 */
275                                 if ( global_level < 0 ) 
276                                 {
277                                         global_level = 65535;
278                                         ldap_loglevels[0] = 65535;
279                         }
280                 }
281                 }
282     }
283 }
284
285 void (lutil_debug)( int debug, int level, const char *fmt, ... )
286 {
287         char buffer[4096];
288         va_list vl;
289
290         if ( !(level & debug ) )
291                 return;
292
293 #ifdef HAVE_WINSOCK
294         if( log_file == NULL ) {
295                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
296
297                 if ( log_file == NULL )
298                         log_file = fopen( "openldap.log", "w" );
299
300                 if ( log_file == NULL )
301                         return;
302
303                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
304         }
305 #endif
306         va_start( vl, fmt );
307
308 #ifdef HAVE_VSNPRINTF
309         vsnprintf( buffer, sizeof(buffer), fmt, vl );
310 #else
311         vsprintf( buffer, fmt, vl );
312 #endif
313         buffer[sizeof(buffer)-1] = '\0';
314
315         if( log_file != NULL ) {
316                 fputs( buffer, log_file );
317                 fflush( log_file );
318         }
319
320     fputs( buffer, stderr );
321         va_end( vl );
322 }