]> git.sur5r.net Git - openldap/blob - libraries/liblutil/debug.c
More contrib cleanout
[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 #include "portable.h"
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #include <ac/stdarg.h>
13 #include <ac/string.h>
14 #include <ac/time.h>
15
16 #include "ldap_log.h"
17 #include "ldap_defaults.h"
18 #include "lber.h"
19
20 struct DEBUGLEVEL
21 {
22         char *subsystem;
23         int  level;
24 };
25
26 static struct DEBUGLEVEL **levelArray;
27 static long   numLevels = 0;
28
29 static FILE *log_file = NULL;
30 static int global_level = 0;
31
32 #if 0
33 #ifdef LDAP_SYSLOG
34 static int use_syslog = 0;
35
36 static int debug2syslog(int l) {
37         switch (l) {
38         /* insert mapping cases here */
39         default:
40         }
41         return LOG_DEBUG
42 }
43 #endif
44 #endif
45
46 static char *lutil_levels[] = {"emergency", "alert", "critical",
47                            "error", "warning", "notice",
48                            "information", "entry", "args",
49                            "results", "detail1", "detail2",
50                            NULL};
51
52 int lutil_mnem2level( char *level )
53 {
54     int i;
55     for( i = 0; lutil_levels[i] != NULL; i++ )
56     {
57         if ( !strcasecmp( level, lutil_levels[i] ) )
58         {
59             return i;
60         }
61     }
62     return 0;
63 }
64
65 static void addSubsys( const char *subsys, int level )
66 {
67         int i, j;
68
69         if ( !strcasecmp( subsys, "global") ) global_level = level;
70
71         for( i = 0; i < numLevels; i++ )
72         {
73                 if ( levelArray[i] == NULL )
74                 {
75                         levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
76                         levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
77                         strcpy ( levelArray[i]->subsystem, subsys );
78                         levelArray[i]->level = level;
79                         return;
80                 }
81                 if( !strcasecmp( subsys, levelArray[i]->subsystem ) )
82                 {
83                         levelArray[i]->level = level;
84                         return;
85                 }
86         }
87         levelArray = (struct DEBUGLEVEL**)ber_memrealloc( levelArray, sizeof( struct DEBUGLEVEL* ) * (numLevels + 10) );
88         for( j = numLevels; j < (numLevels + 10); j++ )
89         {
90                 levelArray[j] = NULL;
91         }
92         numLevels += 10;
93         levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
94         levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
95         strcpy( levelArray[i]->subsystem, subsys );
96         levelArray[i]->level = level;
97         return;
98 }
99
100 void lutil_set_debug_level( char* subsys, int level )
101 {
102     addSubsys( subsys, level );
103 }
104
105 int lutil_debug_file( FILE *file )
106 {
107         log_file = file;
108         ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
109
110         return 0;
111 }
112
113 void lutil_log_int(
114         FILE* file,
115         char *subsys, int level,
116         const char *fmt, va_list vl )
117 {
118         time_t now;
119         struct tm *today;
120         int i;
121
122         if ( levelArray == NULL ) return; /* logging isn't set up */
123
124         /*
125          * Look for the subsystem in the level array.  When we find it,
126          * break out of the loop.
127          */
128         for( i = 0; i < numLevels; i++ ) {
129                 if ( levelArray[i] == NULL ) break; 
130                 if ( ! strcasecmp( levelArray[i]->subsystem, subsys ) ) break;
131         }
132
133         /*
134          * If we didn't find the subsystem, or the set level is less than
135          * the requested output level, don't output it.
136          */
137         if ( (level > global_level) &&
138                 ((i > numLevels ) || (levelArray[i] == NULL) || ( level > levelArray[i]->level )) )
139         {
140                 return;
141         }
142
143 #if 0
144 #ifdef LDAP_SYSLOG
145         /* we're configured to use syslog */
146         if( use_syslog ) {
147                 vsyslog( debug2syslog(level), fmt, vl );
148                 return;
149         }
150 #endif
151 #endif
152
153 #if 0
154 #ifdef HAVE_WINSOCK
155         if( log_file == NULL ) {
156                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
157
158                 if ( log_file == NULL )
159                         log_file = fopen( "openldap.log", "w" );
160
161                 if ( log_file == NULL )
162                         return;
163
164                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
165         }
166 #endif
167 #endif
168
169         if( file == NULL ) {
170                 /*
171                  * Use stderr unless file was specified via:
172                  *   ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
173                  */
174                 file = stderr;
175         }
176
177 #ifdef HAVE_WINSOCK
178         /*
179          * Stick the time in the buffer to output when using Winsock
180          * as NT can't pipe to a timestamp program like Unix can.
181          * This, of course, makes some logs hard to read.
182      */
183         time( &now );
184         today = localtime( &now );
185         fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
186                 today->tm_year + 1900, today->tm_mon + 1,
187                 today->tm_mday, today->tm_hour,
188                 today->tm_min, today->tm_sec );
189 #endif
190
191         /*
192          * format the output data.
193          */
194         vfprintf( file, fmt, vl );
195 }
196
197 /*
198  * The primary logging routine.  Takes the subsystem being logged from, the
199  * level of the log output and the format and data.  Send this on to the
200  * internal routine with the print file, if any.
201  */
202 void lutil_log( char *subsys, int level, const char *fmt, ... )
203 {
204         FILE* outfile = NULL;
205         va_list vl;
206         va_start( vl, fmt );
207         ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
208         lutil_log_int( outfile, subsys, level, fmt, vl );
209         va_end( vl );
210 }
211
212 void lutil_log_initialize(int argc, char **argv)
213 {
214     int i;
215     /*
216      * Start by setting the hook for the libraries to use this logging
217      * routine.
218      */
219     ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
220
221     if ( argc == 0 ) return;
222     /*
223      * Now go through the command line options to set the debugging
224      * levels
225      */
226     for( i = 0; i < argc; i++ )
227     {
228         char *next = argv[i];
229         if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
230         {
231             char subsys[64];
232             int level;
233             char *optarg = argv[i+1];
234             char *index = strchr( optarg, '=' );
235             if ( index != NULL )
236             {
237                 *index = 0;
238                 strcpy ( subsys, optarg );
239                 level = atoi( index+1 );
240                 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
241                 lutil_set_debug_level( subsys, level );
242                 *index = '=';
243             }
244             else
245             {
246                 global_level = atoi( optarg );
247                 /* 
248                  * if a negative number was used, make the global level the
249                  * maximum sane level.
250                  */
251                 if ( global_level < 0 ) global_level = 65535;
252             }
253         }
254     }
255 }
256
257 void (lutil_debug)( int debug, int level, const char *fmt, ... )
258 {
259         char buffer[4096];
260         va_list vl;
261
262         if ( !(level & debug ) )
263                 return;
264
265 #ifdef HAVE_WINSOCK
266         if( log_file == NULL ) {
267                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
268
269                 if ( log_file == NULL )
270                         log_file = fopen( "openldap.log", "w" );
271
272                 if ( log_file == NULL )
273                         return;
274
275                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
276         }
277 #endif
278         va_start( vl, fmt );
279
280 #ifdef HAVE_VSNPRINTF
281         vsnprintf( buffer, sizeof(buffer), fmt, vl );
282 #else
283         vsprintf( buffer, fmt, vl );
284 #endif
285         buffer[sizeof(buffer)-1] = '\0';
286
287         if( log_file != NULL ) {
288                 fputs( buffer, log_file );
289                 fflush( log_file );
290         }
291
292     fputs( buffer, stderr );
293         va_end( vl );
294 }