]> git.sur5r.net Git - openldap/blob - libraries/liblutil/debug.c
baf49c867f3b6da11f1a654016d4dce3ef04a1e7
[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         for( i = 0; i < numLevels; i++ )
69         {
70                 if ( levelArray[i] == NULL )
71                 {
72                         levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
73                         levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
74                         strcpy ( levelArray[i]->subsystem, subsys );
75                         levelArray[i]->level = level;
76                         return;
77                 }
78                 if( !strcasecmp( subsys, levelArray[i]->subsystem ) )
79                 {
80                         levelArray[i]->level = level;
81                         return;
82                 }
83         }
84         levelArray = (struct DEBUGLEVEL**)ber_memrealloc( levelArray, sizeof( struct DEBUGLEVEL* ) * (numLevels + 10) );
85         for( j = numLevels; j < (numLevels + 10); j++ )
86         {
87                 levelArray[j] = NULL;
88         }
89         numLevels += 10;
90         levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
91         levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
92         strcpy( levelArray[i]->subsystem, subsys );
93         levelArray[i]->level = level;
94         return;
95 }
96
97 void lutil_set_debug_level( char* subsys, int level )
98 {
99     addSubsys( subsys, level );
100 }
101
102 int lutil_debug_file( FILE *file )
103 {
104         log_file = file;
105         ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
106
107         return 0;
108 }
109
110 void lutil_log_int(
111         FILE* file,
112         char *subsys, int level,
113         const char *fmt, va_list vl )
114 {
115         time_t now;
116         struct tm *today;
117         int i;
118
119         if ( levelArray == NULL ) return; /* logging isn't set up */
120
121         /*
122          * Look for the subsystem in the level array.  When we find it,
123          * break out of the loop.
124          */
125         for( i = 0; i < numLevels; i++ ) {
126                 if ( levelArray[i] == NULL ) return; 
127                 if ( ! strcasecmp( levelArray[i]->subsystem, subsys ) ) break;
128         }
129
130         /*
131          * If we didn't find the subsystem, or the set level is less than
132          * the requested output level, don't output it.
133          */
134         if ( (level > global_level) &&
135                 ((i > numLevels ) || ( level > levelArray[i]->level )) )
136         {
137                 return;
138         }
139
140 #if 0
141 #ifdef LDAP_SYSLOG
142         /* we're configured to use syslog */
143         if( use_syslog ) {
144                 vsyslog( debug2syslog(level), fmt, vl );
145                 return;
146         }
147 #endif
148 #endif
149
150 #if 0
151 #ifdef HAVE_WINSOCK
152         if( log_file == NULL ) {
153                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
154
155                 if ( log_file == NULL )
156                         log_file = fopen( "openldap.log", "w" );
157
158                 if ( log_file == NULL )
159                         return;
160
161                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
162         }
163 #endif
164 #endif
165
166         if( file == NULL ) {
167                 /*
168                  * Use stderr unless file was specified via:
169                  *   ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
170                  */
171                 file = stderr;
172         }
173
174 #ifdef HAVE_WINSOCK
175         /*
176          * Stick the time in the buffer to output when using Winsock
177          * as NT can't pipe to a timestamp program like Unix can.
178          * This, of course, makes some logs hard to read.
179      */
180         time( &now );
181         today = localtime( &now );
182         fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
183                 today->tm_year + 1900, today->tm_mon + 1,
184                 today->tm_mday, today->tm_hour,
185                 today->tm_min, today->tm_sec );
186 #endif
187
188         /*
189          * format the output data.
190          */
191         vfprintf( file, fmt, vl );
192 }
193
194 /*
195  * The primary logging routine.  Takes the subsystem being logged from, the
196  * level of the log output and the format and data.  Send this on to the
197  * internal routine with the print file, if any.
198  */
199 void lutil_log( char *subsys, int level, const char *fmt, ... )
200 {
201         FILE* outfile = NULL;
202         va_list vl;
203         va_start( vl, fmt );
204         ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
205         lutil_log_int( outfile, subsys, level, fmt, vl );
206         va_end( vl );
207 }
208
209 void lutil_log_initialize(int argc, char **argv)
210 {
211     int i;
212     /*
213      * Start by setting the hook for the libraries to use this logging
214      * routine.
215      */
216     ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
217
218     if ( argc == 0 ) return;
219     /*
220      * Now go through the command line options to set the debugging
221      * levels
222      */
223     for( i = 0; i < argc; i++ )
224     {
225         char *next = argv[i];
226         if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
227         {
228             char subsys[64];
229             int level;
230             char *optarg = argv[i+1];
231             char *index = strchr( optarg, '=' );
232             if ( index != NULL )
233             {
234                 *index = 0;
235                 strcpy ( subsys, optarg );
236                 level = atoi( index+1 );
237                 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
238                 lutil_set_debug_level( subsys, level );
239                 *index = '=';
240             }
241             else
242             {
243                 global_level = atoi( optarg );
244             }
245         }
246     }
247 }
248
249 void (lutil_debug)( int debug, int level, const char *fmt, ... )
250 {
251         char buffer[4096];
252         va_list vl;
253
254         if ( !(level & debug ) )
255                 return;
256
257 #ifdef HAVE_WINSOCK
258         if( log_file == NULL ) {
259                 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
260
261                 if ( log_file == NULL )
262                         log_file = fopen( "openldap.log", "w" );
263
264                 if ( log_file == NULL )
265                         return;
266
267                 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
268         }
269 #endif
270         va_start( vl, fmt );
271
272 #ifdef HAVE_VSNPRINTF
273         vsnprintf( buffer, sizeof(buffer), fmt, vl );
274 #else
275         vsprintf( buffer, fmt, vl );
276 #endif
277         buffer[sizeof(buffer)-1] = '\0';
278
279         if( log_file != NULL ) {
280                 fputs( buffer, log_file );
281                 fflush( log_file );
282         }
283
284     fputs( buffer, stderr );
285         va_end( vl );
286 }