2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2003 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"
41 int ldap_loglevels[LDAP_SUBSYS_NUM];
43 static FILE *log_file = NULL;
44 static int global_level = 0;
47 static int use_syslog = 0;
49 static int debug2syslog(int l) {
51 case LDAP_LEVEL_EMERG: return LOG_EMERG;
52 case LDAP_LEVEL_ALERT: return LOG_ALERT;
53 case LDAP_LEVEL_CRIT: return LOG_CRIT;
54 case LDAP_LEVEL_ERR: return LOG_ERR;
55 case LDAP_LEVEL_WARNING: return LOG_WARNING;
56 case LDAP_LEVEL_NOTICE: return LOG_NOTICE;
57 case LDAP_LEVEL_INFO: return LOG_INFO;
63 static char *lutil_levels[] = {
64 "emergency", "alert", "critical",
65 "error", "warning", "notice",
66 "information", "entry", "args",
67 "results", "detail1", "detail2",
70 static char *lutil_subsys[LDAP_SUBSYS_NUM] = {
71 "GLOBAL","OPERATION", "TRANSPORT",
72 "CONNECTION", "FILTER", "BER",
73 "CONFIG", "ACL", "CACHE", "INDEX",
74 "LDIF", "TOOLS", "SLAPD", "SLURPD",
75 "BACKEND", "BACK_BDB", "BACK_LDBM",
76 "BACK_LDAP", "BACK_META", "BACK_MON" };
78 int lutil_mnem2subsys( const char *subsys )
81 for( i = 0; i < LDAP_SUBSYS_NUM; i++ ) {
82 if ( !strcasecmp( subsys, lutil_subsys[i] ) ) {
89 void lutil_set_all_backends( int level )
93 for( i = 0; i < LDAP_SUBSYS_NUM; i++ ) {
94 if ( !strncasecmp( "BACK_", lutil_subsys[i], sizeof("BACK_")-1 ) ) {
95 ldap_loglevels[i] = level;
100 int lutil_mnem2level( const char *level )
103 for( i = 0; lutil_levels[i] != NULL; i++ ) {
104 if ( !strcasecmp( level, lutil_levels[i] ) ) {
111 static int addSubsys( const char *subsys, int level )
115 if ( !strcasecmp( subsys, "BACKEND" ) ) {
116 lutil_set_all_backends( level );
120 subsys_num = lutil_mnem2subsys(subsys);
122 fprintf(stderr, _("Unknown Subsystem name [ %s ] - Discarded\n"),
128 ldap_loglevels[subsys_num] = level;
134 int lutil_set_debug_level( const char* subsys, int level )
136 return( addSubsys( subsys, level ) );
139 int lutil_debug_file( FILE *file )
142 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
149 const char *subsys, int level,
150 const char *fmt, va_list vl )
160 /* we're configured to use syslog */
163 vsyslog( debug2syslog(level), fmt, vl );
166 vsnprintf( data, sizeof(data), fmt, vl );
167 syslog( debug2syslog(level), data );
175 if( log_file == NULL ) {
176 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
178 if ( log_file == NULL ) {
179 log_file = fopen( "openldap.log", "w" );
180 if ( log_file == NULL ) return;
183 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
190 * Use stderr unless file was specified via:
191 * ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
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.
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 );
211 * format the output data.
214 fprintf(file, "\n%s:: ", subsys );
215 vfprintf( file, fmt, vl );
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.
224 void lutil_log( const int subsys, int level, const char *fmt, ... )
226 FILE* outfile = NULL;
229 ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
230 lutil_log_int( outfile, lutil_subsys[subsys], level, fmt, vl );
234 void lutil_log_initialize(int argc, char **argv)
238 * Start by setting the hook for the libraries to use this logging
241 ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
243 if ( argc == 0 ) return;
246 * Now go through the command line options to set the debugging
249 for( i = 0; i < argc; i++ ) {
250 char *next = argv[i];
252 if ( i < argc-1 && next[0] == '-' && next[1] == 'd' ) {
255 char *optarg = argv[i+1];
256 char *index = strchr( optarg, '=' );
258 if ( index != NULL ) {
260 strcpy ( subsys, optarg );
261 level = atoi( index+1 );
262 if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
263 lutil_set_debug_level( subsys, level );
267 global_level = atoi( optarg );
268 ldap_loglevels[0] = global_level;
270 * if a negative number was used, make the global level the
271 * maximum sane level.
273 if ( global_level < 0 ) {
274 global_level = 65535;
275 ldap_loglevels[0] = 65535;
282 void (lutil_debug)( int debug, int level, const char *fmt, ... )
287 if ( !(level & debug ) ) return;
290 if( log_file == NULL ) {
291 log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
293 if ( log_file == NULL ) {
294 log_file = fopen( "openldap.log", "w" );
295 if ( log_file == NULL ) return;
298 ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
303 vsnprintf( buffer, sizeof(buffer), fmt, vl );
304 buffer[sizeof(buffer)-1] = '\0';
306 if( log_file != NULL ) {
307 fputs( buffer, log_file );
311 fputs( buffer, stderr );