diff options
Diffstat (limited to 'servers/slapd/logging.c')
-rw-r--r-- | servers/slapd/logging.c | 836 |
1 files changed, 836 insertions, 0 deletions
diff --git a/servers/slapd/logging.c b/servers/slapd/logging.c new file mode 100644 index 0000000..95f7ff2 --- /dev/null +++ b/servers/slapd/logging.c @@ -0,0 +1,836 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 2021-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/errno.h> +#include <ac/param.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/unistd.h> +#include <ac/ctype.h> + +#include <sys/stat.h> +#ifndef _WIN32 +#include <sys/uio.h> +#endif +#include <fcntl.h> + +#include "slap.h" +#include "ldif.h" + +#include "slap-config.h" +#include "slap-cfglog.h" + +static int config_syslog, active_syslog; + +static char logfile_suffix[sizeof(".xx.gz")]; +static char logfile_path[MAXPATHLEN - sizeof(logfile_suffix) -1]; +static long logfile_fslimit; +static int logfile_age, logfile_only, logfile_max; +static char *syslog_prefix; +static int splen; + +typedef enum { LFMT_DEFAULT, LFMT_DEBUG, LFMT_SYSLOG_UTC, LFMT_SYSLOG_LOCAL } LogFormat; +static LogFormat logfile_format; + +static slap_verbmasks logformat_key[] = { + { BER_BVC("default"), LFMT_DEFAULT }, + { BER_BVC("debug"), LFMT_DEBUG }, + { BER_BVC("syslog-utc"), LFMT_SYSLOG_UTC }, + { BER_BVC("syslog-localtime"), LFMT_SYSLOG_LOCAL }, + { BER_BVNULL, 0 } +}; + +char *serverName; +int slap_debug_orig; + +ldap_pvt_thread_mutex_t logfile_mutex; + +static off_t logfile_fsize; +static time_t logfile_fcreated; +static int logfile_fd = -1; +static char logpaths[2][MAXPATHLEN]; +static int logpathlen; + +#define SYSLOG_STAMP "Mmm dd hh:mm:ss" + +void +slap_debug_print( const char *data ) +{ +#ifdef _WIN32 + char msgbuf[4096]; + int prefixlen, poffset = 0, datalen; +#else + char prefix[sizeof("ssssssssssssssss.ffffffff 0xtttttttttttttttt ")]; + struct iovec iov[2]; +#endif + int rotate = 0; +#ifdef HAVE_CLOCK_GETTIME + struct timespec tv; +#define TS "%08x" +#define Tfrac tv.tv_nsec +#define gettime(tv) clock_gettime( CLOCK_REALTIME, tv ) +#else + struct timeval tv; +#define TS "%05x" +#define Tfrac tv.tv_usec +#define gettime(tv) gettimeofday( tv, NULL ) +#endif + char *ptr; + int len; + + + gettime( &tv ); +#ifdef _WIN32 + ptr = msgbuf; + prefixlen = sprintf( ptr, "%lx." TS " %p ", + (long)tv.tv_sec, (unsigned int)Tfrac, (void *)ldap_pvt_thread_self() ); + if ( prefixlen < splen ) { + poffset = splen - prefixlen; + AC_MEMCPY( ptr+poffset, ptr, prefixlen ); + } + + ptr = lutil_strncopy( ptr+poffset+prefixlen, data, sizeof(msgbuf) - prefixlen); + len = ptr - msgbuf - poffset; + datalen = len - prefixlen; + if ( !logfile_only ) + (void)!write( 2, msgbuf+poffset, len ); + ptr = msgbuf; +#else + iov[0].iov_base = prefix; + iov[0].iov_len = sprintf( prefix, "%lx." TS " %p ", + (long)tv.tv_sec, (unsigned int)Tfrac, (void *)ldap_pvt_thread_self() ); + iov[1].iov_base = (void *)data; + iov[1].iov_len = strlen( data ); + len = iov[0].iov_len + iov[1].iov_len; + if ( !logfile_only ) + (void)!writev( 2, iov, 2 ); +#endif + if ( logfile_fd >= 0 ) { + if ( logfile_fslimit || logfile_age ) { + ldap_pvt_thread_mutex_lock( &logfile_mutex ); + if ( logfile_fslimit && logfile_fsize + len > logfile_fslimit ) + rotate = 1; + if ( logfile_age && tv.tv_sec - logfile_fcreated >= logfile_age ) + rotate |= 2; + if ( rotate ) { + close( logfile_fd ); + logfile_fd = -1; + strcpy( logpaths[0]+logpathlen, ".tmp" ); + rename( logfile_path, logpaths[0] ); + logfile_open( logfile_path ); + } + } + + if ( logfile_format > LFMT_DEBUG ) { + struct tm tm; + if ( logfile_format == LFMT_SYSLOG_UTC ) + ldap_pvt_gmtime( &tv.tv_sec, &tm ); + else + ldap_pvt_localtime( &tv.tv_sec, &tm ); +#ifdef _WIN32 + if ( splen < prefixlen ) + ptr += prefixlen - splen; + memcpy( ptr, syslog_prefix, splen ); +#else + ptr = syslog_prefix; +#endif + strftime( ptr, sizeof( SYSLOG_STAMP ), + "%b %d %H:%M:%S", &tm ); + ptr[ sizeof( SYSLOG_STAMP )-1 ] = ' '; +#ifdef _WIN32 + len = datalen + splen; +#else + iov[0].iov_base = syslog_prefix; + iov[0].iov_len = splen; +#endif + } + +#ifdef _WIN32 + if ( logfile_format <= LFMT_DEBUG ) + ptr += poffset; /* only nonzero if logfile-format was explicitly set */ + len = write( logfile_fd, ptr, len ); +#else + len = writev( logfile_fd, iov, 2 ); +#endif + if ( len > 0 ) + logfile_fsize += len; + if ( logfile_fslimit || logfile_age ) + ldap_pvt_thread_mutex_unlock( &logfile_mutex ); + } + if ( rotate ) { + int i; + for (i=logfile_max; i > 1; i--) { + sprintf( logpaths[0]+logpathlen, ".%02d", i ); + sprintf( logpaths[1]+logpathlen, ".%02d", i-1 ); + rename( logpaths[1], logpaths[0] ); + } + sprintf( logpaths[0]+logpathlen, ".tmp" ); + rename( logpaths[0], logpaths[1] ); + } +} + +void +logfile_close() +{ + if ( logfile_fd >= 0 ) { + close( logfile_fd ); + logfile_fd = -1; + } + logfile_path[0] = '\0'; +} + +int +logfile_open( const char *path ) +{ + struct stat st; + int fd, saved_errno; + + /* the logfile is for slapd only, not tools */ + if ( !( slapMode & SLAP_SERVER_MODE )) + return 0; + + fd = open( path, O_CREAT|O_WRONLY, 0640 ); + if ( fd < 0 ) { + saved_errno = errno; +fail: + logfile_only = 0; /* make sure something gets output */ + return saved_errno; + } + + if ( fstat( fd, &st ) ) { + saved_errno = errno; + close( fd ); + goto fail; + } + + if ( !logfile_path[0] ) { + logpathlen = strlen( path ); + if ( logpathlen >= sizeof(logfile_path) ) { + saved_errno = ENAMETOOLONG; + goto fail; + } + strcpy( logfile_path, path ); + strcpy( logpaths[0], path ); + strcpy( logpaths[1], path ); + } + + logfile_fsize = st.st_size; + logfile_fcreated = st.st_ctime; /* not strictly true but close enough */ + logfile_fd = fd; + lseek( fd, 0, SEEK_END ); + + return 0; +} + +const char * +logfile_name() +{ + return logfile_path[0] ? logfile_path : NULL; +} + +#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) +#ifdef LOG_LOCAL4 +int +slap_parse_syslog_user( const char *arg, int *syslogUser ) +{ + static slap_verbmasks syslogUsers[] = { + { BER_BVC( "LOCAL0" ), LOG_LOCAL0 }, + { BER_BVC( "LOCAL1" ), LOG_LOCAL1 }, + { BER_BVC( "LOCAL2" ), LOG_LOCAL2 }, + { BER_BVC( "LOCAL3" ), LOG_LOCAL3 }, + { BER_BVC( "LOCAL4" ), LOG_LOCAL4 }, + { BER_BVC( "LOCAL5" ), LOG_LOCAL5 }, + { BER_BVC( "LOCAL6" ), LOG_LOCAL6 }, + { BER_BVC( "LOCAL7" ), LOG_LOCAL7 }, +#ifdef LOG_USER + { BER_BVC( "USER" ), LOG_USER }, +#endif /* LOG_USER */ +#ifdef LOG_DAEMON + { BER_BVC( "DAEMON" ), LOG_DAEMON }, +#endif /* LOG_DAEMON */ + { BER_BVNULL, 0 } + }; + int i = verb_to_mask( arg, syslogUsers ); + + if ( BER_BVISNULL( &syslogUsers[ i ].word ) ) { + Debug( LDAP_DEBUG_ANY, + "unrecognized syslog user \"%s\".\n", + arg ); + return 1; + } + + *syslogUser = syslogUsers[ i ].mask; + + return 0; +} +#endif /* LOG_LOCAL4 */ + +int +slap_parse_syslog_level( const char *arg, int *levelp ) +{ + static slap_verbmasks str2syslog_level[] = { + { BER_BVC( "EMERG" ), LOG_EMERG }, + { BER_BVC( "ALERT" ), LOG_ALERT }, + { BER_BVC( "CRIT" ), LOG_CRIT }, + { BER_BVC( "ERR" ), LOG_ERR }, + { BER_BVC( "WARNING" ), LOG_WARNING }, + { BER_BVC( "NOTICE" ), LOG_NOTICE }, + { BER_BVC( "INFO" ), LOG_INFO }, + { BER_BVC( "DEBUG" ), LOG_DEBUG }, + { BER_BVNULL, 0 } + }; + int i = verb_to_mask( arg, str2syslog_level ); + if ( BER_BVISNULL( &str2syslog_level[ i ].word ) ) { + Debug( LDAP_DEBUG_ANY, + "unknown syslog level \"%s\".\n", + arg ); + return 1; + } + + *levelp = str2syslog_level[ i ].mask; + + return 0; +} +#endif /* LDAP_DEBUG && LDAP_SYSLOG */ + +static char **debug_unknowns; +static char **syslog_unknowns; + +static int +parse_debug_unknowns( char **unknowns, int *levelp ) +{ + int i, level, rc = 0; + + for ( i = 0; unknowns[ i ] != NULL; i++ ) { + level = 0; + if ( str2loglevel( unknowns[ i ], &level )) { + fprintf( stderr, + "unrecognized log level \"%s\"\n", unknowns[ i ] ); + rc = 1; + } else { + *levelp |= level; + } + } + return rc; +} + +int +slap_parse_debug_level( const char *arg, int *levelp, int which ) +{ + int level; + + if ( arg && arg[ 0 ] != '-' && !isdigit( (unsigned char) arg[ 0 ] ) ) + { + int i; + char **levels; + char ***unknowns = which ? &syslog_unknowns : &debug_unknowns; + + levels = ldap_str2charray( arg, "," ); + + for ( i = 0; levels[ i ] != NULL; i++ ) { + level = 0; + + if ( str2loglevel( levels[ i ], &level ) ) { + /* remember this for later */ + ldap_charray_add( unknowns, levels[ i ] ); + fprintf( stderr, + "unrecognized log level \"%s\" (deferred)\n", + levels[ i ] ); + } else { + *levelp |= level; + } + } + + ldap_charray_free( levels ); + + } else { + int rc; + + if ( arg[0] == '-' ) { + rc = lutil_atoix( &level, arg, 0 ); + } else { + unsigned ulevel; + + rc = lutil_atoux( &ulevel, arg, 0 ); + level = (int)ulevel; + } + + if ( rc ) { + fprintf( stderr, + "unrecognized log level " + "\"%s\"\n", arg ); + return 1; + } + + if ( level == 0 ) { + *levelp = 0; + + } else { + *levelp |= level; + } + } + + return 0; +} + +int +slap_parse_debug_unknowns() { + int rc = 0; + if ( debug_unknowns ) { + rc = parse_debug_unknowns( debug_unknowns, &slap_debug ); + ldap_charray_free( debug_unknowns ); + debug_unknowns = NULL; + if ( rc ) + goto leave; + ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug ); + ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug ); + } + if ( syslog_unknowns ) { + rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog ); + ldap_charray_free( syslog_unknowns ); + syslog_unknowns = NULL; + } +leave: + return rc; +} + +void slap_check_unknown_level( char *levelstr, int level ) +{ + int i; + + if ( debug_unknowns ) { + for ( i = 0; debug_unknowns[ i ]; i++ ) { + if ( !strcasecmp( debug_unknowns[ i ], levelstr )) { + slap_debug |= level; + break; + } + } + } + + if ( syslog_unknowns ) { + for ( i = 0; syslog_unknowns[ i ]; i++ ) { + if ( !strcasecmp( syslog_unknowns[ i ], levelstr )) { + ldap_syslog |= level; + break; + } + } + } +} + +static slap_verbmasks *loglevel_ops; + +static int +loglevel_init( void ) +{ + slap_verbmasks lo[] = { + { BER_BVC("Any"), (slap_mask_t) LDAP_DEBUG_ANY }, + { BER_BVC("Trace"), LDAP_DEBUG_TRACE }, + { BER_BVC("Packets"), LDAP_DEBUG_PACKETS }, + { BER_BVC("Args"), LDAP_DEBUG_ARGS }, + { BER_BVC("Conns"), LDAP_DEBUG_CONNS }, + { BER_BVC("BER"), LDAP_DEBUG_BER }, + { BER_BVC("Filter"), LDAP_DEBUG_FILTER }, + { BER_BVC("Config"), LDAP_DEBUG_CONFIG }, + { BER_BVC("ACL"), LDAP_DEBUG_ACL }, + { BER_BVC("Stats"), LDAP_DEBUG_STATS }, + { BER_BVC("Stats2"), LDAP_DEBUG_STATS2 }, + { BER_BVC("Shell"), LDAP_DEBUG_SHELL }, + { BER_BVC("Parse"), LDAP_DEBUG_PARSE }, +#if 0 /* no longer used (nor supported) */ + { BER_BVC("Cache"), LDAP_DEBUG_CACHE }, + { BER_BVC("Index"), LDAP_DEBUG_INDEX }, +#endif + { BER_BVC("Sync"), LDAP_DEBUG_SYNC }, + { BER_BVC("None"), LDAP_DEBUG_NONE }, + { BER_BVNULL, 0 } + }; + + return slap_verbmasks_init( &loglevel_ops, lo ); +} + +void +slap_loglevel_destroy( void ) +{ + if ( loglevel_ops ) { + (void)slap_verbmasks_destroy( loglevel_ops ); + } + loglevel_ops = NULL; +} + +static slap_mask_t loglevel_ignore[] = { -1, 0 }; + +int +slap_loglevel_get( struct berval *s, int *l ) +{ + int rc; + slap_mask_t m, i; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + for ( m = 0, i = 1; !BER_BVISNULL( &loglevel_ops[ i ].word ); i++ ) { + m |= loglevel_ops[ i ].mask; + } + + for ( i = 1; m & i; i <<= 1 ) + ; + + if ( i == 0 ) { + return -1; + } + + rc = slap_verbmasks_append( &loglevel_ops, i, s, loglevel_ignore ); + + if ( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, "slap_loglevel_get(%lu, \"%s\") failed\n", + i, s->bv_val ); + + } else { + *l = i; + slap_check_unknown_level( s->bv_val, i ); + } + + return rc; +} + +int +slap_syslog_get() +{ + return active_syslog; +} + +void +slap_syslog_set( int l ) +{ + active_syslog = l; + if ( logfile_only ) { + slap_debug |= active_syslog; + ldap_syslog = 0; + } else { + ldap_syslog = active_syslog; + } +} + +int +slap_debug_get() +{ + return slap_debug_orig; +} + +void +slap_debug_set( int l ) +{ + slap_debug_orig = l; + if ( logfile_only ) + slap_debug = slap_debug_orig | active_syslog; + else + slap_debug = slap_debug_orig; + ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug); + ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug); + ldif_debug = slap_debug; +} + +int +str2loglevel( const char *s, int *l ) +{ + int i; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + i = verb_to_mask( s, loglevel_ops ); + + if ( BER_BVISNULL( &loglevel_ops[ i ].word ) ) { + return -1; + } + + *l = loglevel_ops[ i ].mask; + + return 0; +} + +const char * +loglevel2str( int l ) +{ + struct berval bv = BER_BVNULL; + + loglevel2bv( l, &bv ); + + return bv.bv_val; +} + +int +loglevel2bv( int l, struct berval *bv ) +{ + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + BER_BVZERO( bv ); + + return enum_to_verb( loglevel_ops, l, bv ) == -1; +} + +int +loglevel2bvarray( int l, BerVarray *bva ) +{ + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + if ( l == 0 ) { + struct berval bv = BER_BVC("0"); + return value_add_one( bva, &bv ); + } + + return mask_to_verbs( loglevel_ops, l, bva ); +} + +int +loglevel_print( FILE *out ) +{ + int i; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + fprintf( out, "Installed log subsystems:\n\n" ); + for ( i = 0; !BER_BVISNULL( &loglevel_ops[ i ].word ); i++ ) { + unsigned mask = loglevel_ops[ i ].mask & 0xffffffffUL; + fprintf( out, + (mask == ((slap_mask_t) -1 & 0xffffffffUL) + ? "\t%-30s (-1, 0xffffffff)\n" : "\t%-30s (%u, 0x%x)\n"), + loglevel_ops[ i ].word.bv_val, mask, mask ); + } + + fprintf( out, "\nNOTE: custom log subsystems may be later installed " + "by specific code\n\n" ); + + return 0; +} + +int +config_logging(ConfigArgs *c) { + int i, rc = 0; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + if (c->op == SLAP_CONFIG_EMIT) { + switch(c->type) { + case CFG_LOGLEVEL: + /* Get default or commandline slapd setting */ + if ( ldap_syslog && !config_syslog ) + config_syslog = ldap_syslog; + rc = loglevel2bvarray( config_syslog, &c->rvalue_vals ); + break; + + case CFG_LOGFILE: { + const char *logfileName = logfile_name(); + if ( logfileName && *logfileName ) + c->value_string = ch_strdup( logfileName ); + else + rc = 1; + } + break; + case CFG_LOGFILE_FORMAT: + if ( logfile_format ) { + value_add_one( &c->rvalue_vals, &logformat_key[logfile_format].word ); + } else { + rc = 1; + } + break; + case CFG_LOGFILE_ONLY: + c->value_int = logfile_only; + break; + case CFG_LOGFILE_ROTATE: + rc = 1; + if ( logfile_max ) { + char buf[64]; + struct berval bv; + bv.bv_len = snprintf( buf, sizeof(buf), "%d %ld %ld", logfile_max, + (long) logfile_fslimit / 1048576, (long) logfile_age / 3600 ); + if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) { + bv.bv_val = buf; + value_add_one( &c->rvalue_vals, &bv ); + rc = 0; + } + } + break; + default: + rc = 1; + } + return rc; + } else if ( c->op == LDAP_MOD_DELETE ) { + switch(c->type) { + case CFG_LOGLEVEL: + if ( !c->line ) { + config_syslog = 0; + } else { + i = verb_to_mask( c->line, loglevel_ops ); + config_syslog &= ~loglevel_ops[i].mask; + } + goto reset; + + case CFG_LOGFILE: + logfile_close(); + break; + + case CFG_LOGFILE_FORMAT: + logfile_format = 0; + ch_free( syslog_prefix ); + syslog_prefix = NULL; + break; + + case CFG_LOGFILE_ONLY: + /* remove loglevel from debuglevel */ + slap_debug = slap_debug_orig; + ldap_syslog = config_syslog; + break; + + case CFG_LOGFILE_ROTATE: + logfile_max = logfile_fslimit = logfile_age = 0; + break; + default: + rc = 1; + } + return rc; + } + + switch(c->type) { + case CFG_LOGLEVEL: + for( i=1; i < c->argc; i++ ) { + int level; + + if ( isdigit((unsigned char)c->argv[i][0]) || c->argv[i][0] == '-' ) { + if( lutil_atoix( &level, c->argv[i], 0 ) != 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse level", c->argv[0] ); + Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", + c->log, c->cr_msg, c->argv[i]); + return( 1 ); + } + } else { + if ( str2loglevel( c->argv[i], &level ) ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown level", c->argv[0] ); + Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", + c->log, c->cr_msg, c->argv[i]); + return( 1 ); + } + } + /* Explicitly setting a zero clears all the levels */ + if ( level ) + config_syslog |= level; + else + config_syslog = 0; + } + +reset: + slap_debug = slap_debug_orig; + active_syslog = config_syslog; + if ( slapMode & SLAP_SERVER_MODE ) { + if ( logfile_only ) { + slap_debug |= config_syslog; + ldap_syslog = 0; + } else { + ldap_syslog = config_syslog; + } + } + rc = 0; + break; + + case CFG_LOGFILE: + rc = logfile_open( c->value_string ); + ch_free( c->value_string ); + break; + + case CFG_LOGFILE_FORMAT: { + int len; + i = verb_to_mask( c->argv[1], logformat_key ); + + if ( BER_BVISNULL( &logformat_key[ i ].word ) ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown format", c->argv[0] ); + Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", + c->log, c->cr_msg, c->argv[1]); + return( 1 ); + } + if ( syslog_prefix ) + ch_free( syslog_prefix ); + len = strlen( global_host ) + 1 + strlen( serverName ) + 1 + sizeof("[123456789]:") + + sizeof( SYSLOG_STAMP ); + syslog_prefix = ch_malloc( len ); + splen = sprintf( syslog_prefix, SYSLOG_STAMP " %s %s[%d]: ", global_host, serverName, getpid() ); + logfile_format = logformat_key[i].mask; + } + break; + + case CFG_LOGFILE_ONLY: + logfile_only = c->value_int; + goto reset; + + case CFG_LOGFILE_ROTATE: { + unsigned lf_max, lf_mbyte, lf_hour; + if ( lutil_atoux( &lf_max, c->argv[1], 0 ) != 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> " + "invalid max value \"%s\"", c->argv[0], c->argv[1] ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", + c->log, c->cr_msg ); + return 1; + } + if ( !lf_max || lf_max > 99 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> " + "invalid max value \"%s\" must be 1-99", c->argv[0], c->argv[1] ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", + c->log, c->cr_msg ); + return 1; + } + if ( lutil_atoux( &lf_mbyte, c->argv[2], 0 ) != 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> " + "invalid Mbyte value \"%s\"", c->argv[0], c->argv[2] ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", + c->log, c->cr_msg ); + return 1; + } + if ( lutil_atoux( &lf_hour, c->argv[3], 0 ) != 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> " + "invalid hours value \"%s\"", c->argv[0], c->argv[3] ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", + c->log, c->cr_msg ); + return 1; + } + if ( !lf_mbyte && !lf_hour ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> " + "Mbyte and hours cannot both be zero", c->argv[0] ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", + c->log, c->cr_msg ); + return 1; + } + logfile_max = lf_max; + logfile_fslimit = lf_mbyte * 1048576; /* Megabytes to bytes */ + logfile_age = lf_hour * 3600; /* hours to seconds */ + } + break; + default: + rc = 1; + } + return rc; +} |