2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2004 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/stdarg.h>
21 #include <ac/stdlib.h>
22 #include <ac/string.h>
27 #include <ac/syslog.h>
31 #include "ldap_defaults.h"
35 int ldap_loglevels[LDAP_SUBSYS_NUM];
37 static FILE *log_file = NULL;
38 static int global_level = 0;
41 static int use_syslog = 0;
43 static int debug2syslog(int l) {
45 case LDAP_LEVEL_EMERG: return LOG_EMERG;
46 case LDAP_LEVEL_ALERT: return LOG_ALERT;
47 case LDAP_LEVEL_CRIT: return LOG_CRIT;
48 case LDAP_LEVEL_ERR: return LOG_ERR;
49 case LDAP_LEVEL_WARNING: return LOG_WARNING;
50 case LDAP_LEVEL_NOTICE: return LOG_NOTICE;
51 case LDAP_LEVEL_INFO: return LOG_INFO;
57 static char *debug_levels[] = {
58 "emergency", "alert", "critical",
59 "error", "warning", "notice",
60 "information", "entry", "args",
61 "results", "detail1", "detail2",
64 static char *debug_subsys[LDAP_SUBSYS_NUM] = {
65 "GLOBAL", "OPERATION", "TRANSPORT",
66 "CONNECTION", "FILTER", "BER",
67 "CONFIG", "ACL", "CACHE", "INDEX",
68 "LDIF", "TOOLS", "SLAPD", "SLURPD",
69 "BACKEND", "BACK_BDB", "BACK_LDBM",
70 "BACK_LDAP", "BACK_META", "BACK_MON" };
72 int lutil_mnem2subsys( const char *subsys )
75 for( i = 0; i < LDAP_SUBSYS_NUM; i++ ) {
76 if ( !strcasecmp( subsys, debug_subsys[i] ) ) {
83 void lutil_set_all_backends( int level )
86 for( i = 0; i < LDAP_SUBSYS_NUM; i++ ) {
87 if ( !strncasecmp( "BACK_", debug_subsys[i], sizeof("BACK_")-1 ) ) {
88 ldap_loglevels[i] = level;
93 int lutil_mnem2level( const char *level )
96 for( i = 0; debug_levels[i] != NULL; i++ ) {
97 if ( !strcasecmp( level, debug_levels[i] ) ) {
104 static int addSubsys( const char *subsys, int level )
108 if ( !strcasecmp( subsys, "BACKEND" ) ) {
109 lutil_set_all_backends( level );
113 subsys_num = lutil_mnem2subsys(subsys);
115 fprintf(stderr, _("Unknown Subsystem name [ %s ] - Discarded\n"),
121 ldap_loglevels[subsys_num] = level;
127 int lutil_set_debug_level( const char* subsys, int level )
129 return( addSubsys( subsys, level ) );
132 int lutil_debug_file( FILE *file )
135 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
142 const char *subsys, int level,
143 const char *fmt, va_list vl )
151 /* we're configured to use syslog */
154 vsyslog( debug2syslog(level), fmt, vl );
157 vsnprintf( data, sizeof(data), fmt, vl );
158 syslog( debug2syslog(level), data );
166 if( log_file == NULL ) {
167 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
169 if ( log_file == NULL ) {
170 log_file = fopen( "openldap.log", "w" );
171 if ( log_file == NULL ) return;
174 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
181 * Use stderr unless file was specified via:
182 * ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
189 * Stick the time in the buffer to output when using Winsock
190 * as NT can't pipe to a timestamp program like Unix can.
191 * This, of course, makes some logs hard to read.
194 today = localtime( &now );
195 fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
196 today->tm_year + 1900, today->tm_mon + 1,
197 today->tm_mday, today->tm_hour,
198 today->tm_min, today->tm_sec );
202 * format the output data.
205 fprintf(file, "\n%s:: ", subsys );
206 vfprintf( file, fmt, vl );
211 * The primary logging routine. Takes the subsystem being logged from, the
212 * level of the log output and the format and data. Send this on to the
213 * internal routine with the print file, if any.
215 void lutil_log( const int subsys, int level, const char *fmt, ... )
217 FILE* outfile = NULL;
220 ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
221 lutil_log_int( outfile, debug_subsys[subsys], level, fmt, vl );
225 void lutil_log_initialize(int argc, char **argv)
229 * Start by setting the hook for the libraries to use this logging
232 ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
234 if ( argc == 0 ) return;
237 * Now go through the command line options to set the debugging
240 for( i = 0; i < argc; i++ ) {
241 char *next = argv[i];
243 if ( i < argc-1 && next[0] == '-' && next[1] == 'd' ) {
246 char *optarg = argv[i+1];
247 char *index = strchr( optarg, '=' );
249 if ( index != NULL ) {
251 strcpy ( subsys, optarg );
252 level = atoi( index+1 );
253 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
254 lutil_set_debug_level( subsys, level );
258 global_level = atoi( optarg );
259 ldap_loglevels[0] = global_level;
261 * if a negative number was used, make the global level the
262 * maximum sane level.
264 if ( global_level < 0 ) {
265 global_level = 65535;
266 ldap_loglevels[0] = 65535;
273 void (lutil_debug)( int debug, int level, const char *fmt, ... )
278 if ( !(level & debug ) ) return;
281 if( log_file == NULL ) {
282 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
284 if ( log_file == NULL ) {
285 log_file = fopen( "openldap.log", "w" );
286 if ( log_file == NULL ) return;
289 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
294 vsnprintf( buffer, sizeof(buffer), fmt, vl );
295 buffer[sizeof(buffer)-1] = '\0';
296 if( log_file != NULL ) {
297 fputs( buffer, log_file );
300 fputs( buffer, stderr );
304 #if defined(HAVE_EBCDIC) && defined(LDAP_SYSLOG)
306 void eb_syslog( int pri, const char *fmt, ... )
312 vsnprintf( buffer, sizeof(buffer), fmt, vl );
313 buffer[sizeof(buffer)-1] = '\0';
315 /* The syslog function appears to only work with pure EBCDIC */
317 #pragma convlit(suspend)
318 syslog( pri, "%s", buffer );
319 #pragma convlit(resume)