]> git.sur5r.net Git - openldap/blob - libraries/liblutil/debug.c
convert string levels to ints
[openldap] / libraries / liblutil / debug.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * Copyright (c) 1996, 1998 by Internet Software Consortium.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20  * SOFTWARE.
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26
27 #include <ac/stdarg.h>
28 #include <ac/string.h>
29 #include <ac/time.h>
30
31 #include "ldap_log.h"
32 #include "ldap_defaults.h"
33 #include "lber.h"
34
35 static FILE *log_file;
36
37 struct M2S
38 {
39         char *mnemonic;
40         int  subsys;
41 };
42
43 struct DEBUGLEVEL
44 {
45         char *subsystem;
46         int  level;
47 };
48
49 static struct DEBUGLEVEL **levelArray;
50 static long   numLevels = 0;
51
52 int global_level = 0;
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 int lutil_mnem2level( char *level )
61 {
62     int i;
63     for( i = 0; lutil_levels[i] != NULL; i++ )
64     {
65         if ( !strcasecmp( level, lutil_levels[i] ) )
66         {
67             return i;
68         }
69     }
70     return 0;
71 }
72
73 static void addSubsys( const char *subsys, int level )
74 {
75         int i, j;
76         for( i = 0; i < numLevels; i++ )
77         {
78                 if ( levelArray[i] == NULL )
79                 {
80                         levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
81                         levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
82                         strcpy ( levelArray[i]->subsystem, subsys );
83                         levelArray[i]->level = level;
84                         return;
85                 }
86                 if( !strcasecmp( subsys, levelArray[i]->subsystem ) )
87                 {
88                         levelArray[i]->level = level;
89                         return;
90                 }
91         }
92         levelArray = (struct DEBUGLEVEL**)ber_memrealloc( levelArray, sizeof( struct DEBUGLEVEL* ) * (numLevels + 10) );
93         for( j = numLevels; j < (numLevels + 10); j++ )
94         {
95                 levelArray[j] = NULL;
96         }
97         numLevels += 10;
98         levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
99         levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
100         strcpy( levelArray[i]->subsystem, subsys );
101         levelArray[i]->level = level;
102         return;
103 }
104
105 void lutil_set_debug_level( char* subsys, int level )
106 {
107         addSubsys( subsys, level );
108 }
109
110 int lutil_debug_file( FILE *file )
111 {
112         log_file = file;
113         ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
114
115         return 0;
116 }
117
118 void lutil_log_int(FILE* file, char *subsys, int level, const char *fmt, va_list vl )
119 {
120         char buffer[4096];
121         time_t now;
122         struct tm *today;
123         int i;
124
125         if ( levelArray == NULL ) return; /* logging isn't set up */
126         /*
127          * Look for the subsystem in the level array.  When we find it, break out of the
128          * loop.
129          */
130         for( i = 0; i < numLevels; i++ )
131         {
132                 if ( levelArray[i] == NULL ) return; 
133                 if ( ! strcasecmp( levelArray[i]->subsystem, subsys ) ) break;
134         }
135
136         /*
137          * If we didn't find the subsystem, or the set level is less than
138          * the requested output level, don't output it.
139          */
140         if ( (level > global_level) && 
141              ((i > numLevels ) || ( level > levelArray[i]->level )) )
142                 return;
143
144 #if 0
145 #ifdef HAVE_WINSOCK
146         if( log_file == NULL ) {
147                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
148
149                 if ( log_file == NULL )
150                         log_file = fopen( "openldap.log", "w" );
151
152                 if ( log_file == NULL )
153                         return;
154
155                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
156         }
157 #endif
158 #endif
159
160         /*
161          * Stick the time in the buffer to output.  Kurt doesn't like
162          * doing this here, but NT can't pipe to a timestamp program
163          * like Unix can, and I don't think it costs much.
164          */
165         time( &now );
166         today = localtime( &now );
167         sprintf( buffer, "%4d%02d%02d:%02d:%02d:%02d ",
168                 today->tm_year + 1900, today->tm_mon + 1,
169                 today->tm_mday, today->tm_hour,
170                 today->tm_min, today->tm_sec );
171
172         /*
173          * format the output data.
174          */
175 #ifdef HAVE_VSNPRINTF
176         vsnprintf( &buffer[18], sizeof(buffer)-18, fmt, vl );
177 #else
178         vsprintf( &buffer[18], fmt, vl );
179 #endif
180         buffer[sizeof(buffer)-1] = '\0';
181
182         /*
183          * If the user set up a file using 
184          * ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file), use
185          * it.  Otherwise, just output to stderr.
186          */
187         if( file != NULL ) {
188                 fputs( buffer, file );
189                 fflush( file );
190         }
191         else
192         {
193             fputs( buffer, stderr );
194         }
195
196 /*
197  * Kurt or someone needs to decide what to do about this.  This
198  * code will log to syslog if the level is less than a normal
199  * debug level (meaning a warning or error of some kind).  However,
200  * having the code here means that ldap_syslog has to be defined.
201  */
202 #if 0
203 #ifdef LDAP_SYSLOG
204         if ( level < LDAP_LEVEL_ENTRY && level >= ldap_syslog )
205         {
206                 syslog( level, buffer );
207         }
208 #endif
209 #endif
210 }
211
212 /*
213  * The primary logging routine.  Takes the subsystem being logged from, the
214  * level of the log output and the format and data.  Send this on to the
215  * internal routine with the print file, if any.
216  */
217 void lutil_log( char *subsys, int level, const char *fmt, ... )
218 {
219         FILE* outfile = NULL;
220         va_list vl;
221         va_start( vl, fmt );
222         ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
223         lutil_log_int( outfile, subsys, level, fmt, vl );
224         va_end( vl );
225 }
226
227 void lutil_log_initialize(int argc, char **argv)
228 {
229     int i;
230     /*
231      * Start by setting the hook for the libraries to use this logging
232      * routine.
233      */
234     ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
235
236     if ( argc == 0 ) return;
237     /*
238      * Now go through the command line options to set the debugging
239      * levels
240      */
241     for( i = 0; i < argc; i++ )
242     {
243         char *next = argv[i];
244         if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
245         {
246             char subsys[64];
247             int level;
248             char *optarg = argv[i+1];
249             char *index = strchr( optarg, '=' );
250             if ( index != NULL )
251             {
252                 *index = 0;
253                 strcpy ( subsys, optarg );
254                 level = atoi( index+1 );
255                 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
256                 lutil_set_debug_level( subsys, level );
257                 *index = '=';
258             }
259             else
260             {
261                 global_level = atoi( optarg );
262             }
263         }
264     }
265 }
266
267 void (lutil_debug)( int debug, int level, const char *fmt, ... )
268 {
269         char buffer[4096];
270         va_list vl;
271
272         if ( !(level & debug ) )
273                 return;
274
275 #ifdef HAVE_WINSOCK
276         if( log_file == NULL ) {
277                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
278
279                 if ( log_file == NULL )
280                         log_file = fopen( "openldap.log", "w" );
281
282                 if ( log_file == NULL )
283                         return;
284
285                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
286         }
287 #endif
288         va_start( vl, fmt );
289
290 #ifdef HAVE_VSNPRINTF
291         vsnprintf( buffer, sizeof(buffer), fmt, vl );
292 #else
293         vsprintf( buffer, fmt, vl );
294 #endif
295         buffer[sizeof(buffer)-1] = '\0';
296
297         if( log_file != NULL ) {
298                 fputs( buffer, log_file );
299                 fflush( log_file );
300         }
301
302     fputs( buffer, stderr );
303         va_end( vl );
304 }