X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslurpd%2Fconfig.c;h=4ab518f5e6e8d1e7ea00794efec7a90ffa1dedbf;hb=8687dace5b3a5a8d2b44c087c8f0091ad0cbc298;hp=43a4bcd90b8796ac465a22086461a29d18a5bd0b;hpb=c0366d3c3b1bedb626431dd8d39322d1e1b00dc2;p=openldap diff --git a/servers/slurpd/config.c b/servers/slurpd/config.c index 43a4bcd90b..4ab518f5e6 100644 --- a/servers/slurpd/config.c +++ b/servers/slurpd/config.c @@ -1,5 +1,20 @@ -/* - * Copyright (c) 1996 Regents of the University of Michigan. +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2005 The OpenLDAP Foundation. + * Portions Copyright 2003 Mark Benson. + * Portions Copyright 2002 John Morrissey. + * 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 file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* Portions Copyright (c) 1996 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted @@ -9,6 +24,13 @@ * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). Additional signficant contributors + * include: + * John Morrissey + * Mark Benson + */ /* @@ -18,31 +40,34 @@ #include "portable.h" #include -#include +#include #include #include #include -#include #include +#include #include "slurp.h" #include "globals.h" -#define MAXARGS 100 +#define ARGS_STEP 512 /* Forward declarations */ static void add_replica LDAP_P(( char **, int )); static int parse_replica_line LDAP_P(( char **, int, Ri *)); -static void parse_line LDAP_P(( char *, int *, char ** )); -static char *getline LDAP_P(( FILE * )); +static void parse_line LDAP_P(( char * )); +static char *slurpd_getline LDAP_P(( FILE * )); static char *strtok_quote LDAP_P(( char *, char * )); +int cargc = 0, cargv_size = 0; +char **cargv; /* current config file line # */ static int lineno; - +char *slurpd_pid_file = NULL; +char *slurpd_args_file = NULL; /* * Read the slapd config file, looking only for config options we're @@ -54,66 +79,224 @@ slurpd_read_config( char *fname ) { - FILE *fp; - char *line; - int cargc; - char *cargv[MAXARGS]; - - Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n", - fname, 0, 0 ); + FILE *fp; + char *line; + +#define GOT_REPLOG_NO (0) +#define GOT_REPLOG_ONE (1) +#define GOT_REPLOG_YES (2) +#define GOT_REPLOG_DONE (3) +#define GOT_REPLOG_MASK (0xF) +#define GOT_REPLOG(i) ((i) & GOT_REPLOG_MASK) +#define GOT_REPLOG_SET(i,v) ((i) = ((i) & ~GOT_REPLOG_MASK) | ((v) & GOT_REPLOG_MASK)) + +#define GOT_REPLOG_PID (0x10) +#define GOT_REPLOG_ARGS (0x20) +#define GOT_REPLOG_INTERVAL (0x40) + int got_replog = GOT_REPLOG_NO; + + /* + * replica-pidfile and replica-argsfile can appear before any replog; + * in this case they're global (legacy behavior); otherwise, since + * each replog needs a slurpd, they can appear after a replogfile line; + * in that case, the replog specific values are used. + */ + + if ( cargv == NULL ) { + cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) ); + cargv_size = ARGS_STEP + 1; + } - if ( (fp = fopen( fname, "r" )) == NULL ) { - perror( fname ); - exit( 1 ); - } + Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n", + fname, 0, 0 ); - lineno = 0; - while ( (line = getline( fp )) != NULL ) { - /* skip comments and blank lines */ - if ( line[0] == '#' || line[0] == '\0' ) { - continue; + if ( (fp = fopen( fname, "r" )) == NULL ) { + perror( fname ); + exit( EXIT_FAILURE ); } - Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 ); + lineno = 0; + while ( (line = slurpd_getline( fp )) != NULL ) { + /* skip comments and blank lines */ + if ( line[0] == '#' || line[0] == '\0' ) { + continue; + } - parse_line( line, &cargc, cargv ); + Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 ); - if ( cargc < 1 ) { - fprintf( stderr, "line %d: bad config line (ignored)\n", lineno ); - continue; - } + parse_line( line ); - /* replication log file to which changes are appended */ - if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) { - /* - * if slapd_replogfile has a value, the -r option was given, - * so use that value. If slapd_replogfile has length == 0, - * then we should use the value in the config file we're reading. - */ - if ( sglob->slapd_replogfile[ 0 ] == '\0' ) { - if ( cargc < 2 ) { - fprintf( stderr, - "line %d: missing filename in \"replogfile ", - lineno ); - fprintf( stderr, "\" line\n" ); - exit( 1 ); - } else if ( cargc > 2 && *cargv[2] != '#' ) { - fprintf( stderr, - "line %d: extra cruft at the end of \"replogfile %s\"", - lineno, cargv[1] ); - fprintf( stderr, "line (ignored)\n" ); + if ( cargc < 1 ) { + fprintf( stderr, "line %d: bad config line (ignored)\n", lineno ); + continue; + } + + /* replication log file to which changes are appended */ + if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) { + /* + * if slapd_replogfile has a value, the -r option was given, + * so use that value. If slapd_replogfile has length == 0, + * then we should use the value in the config file we're reading. + */ + if ( cargc < 2 ) { + fprintf( stderr, + "line %d: missing filename in \"replogfile ", + lineno ); + fprintf( stderr, "\" line\n" ); + exit( EXIT_FAILURE ); + + } else if ( cargc > 2 && *cargv[2] != '#' ) { + fprintf( stderr, + "line %d: extra cruft at the end of \"replogfile %s\"", + lineno, cargv[1] ); + fprintf( stderr, "line (ignored)\n" ); + } + + LUTIL_SLASHPATH( cargv[1] ); + if ( sglob->slapd_replogfile[0] == '\0' ) { + strcpy( sglob->slapd_replogfile, cargv[1] ); + GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES); + + } else { + if ( strcmp( sglob->slapd_replogfile, cargv[1] ) == 0 ) { + GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES); + + } else if ( GOT_REPLOG(got_replog) == GOT_REPLOG_YES ) { + GOT_REPLOG_SET(got_replog, GOT_REPLOG_DONE); + + } else { + GOT_REPLOG_SET(got_replog, GOT_REPLOG_ONE); + } + } + + } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) { + add_replica( cargv, cargc ); + + /* include another config file */ + } else if ( strcasecmp( cargv[0], "include" ) == 0 ) { + char *savefname; + int savelineno; + + if ( cargc < 2 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing filename in \"include \" line\n", + fname, lineno, 0 ); + + return( 1 ); + } + LUTIL_SLASHPATH( cargv[1] ); + savefname = strdup( cargv[1] ); + savelineno = lineno; + + if ( slurpd_read_config( savefname ) != 0 ) { + return( 1 ); + } + + free( savefname ); + lineno = savelineno - 1; + + } else if ( strcasecmp( cargv[0], "replica-pidfile" ) == 0 ) { + if ( cargc < 2 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing file name in \"replica-pidfile \" line\n", + fname, lineno, 0 ); + + return( 1 ); + } + + switch ( GOT_REPLOG(got_replog) ) { + case GOT_REPLOG_YES: + Debug( LDAP_DEBUG_CONFIG, "%s: line %d: " + "got replog specific replica-pidfile \"%s\".\n", + fname, lineno, cargv[1] ); + case GOT_REPLOG_NO: + LUTIL_SLASHPATH( cargv[1] ); + if ( slurpd_pid_file != NULL ) { + ch_free( slurpd_pid_file ); + } + slurpd_pid_file = ch_strdup( cargv[1] ); + got_replog |= GOT_REPLOG_PID; + break; + + default: + Debug( LDAP_DEBUG_CONFIG, "%s: line %d: " + "replica-pidfile \"%s\" not mine.\n", + fname, lineno, cargv[1] ); + break; + } + + } else if ( strcasecmp( cargv[0], "replica-argsfile" ) == 0 ) { + if ( cargc < 2 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing file name in \"argsfile \" line\n", + fname, lineno, 0 ); + + return( 1 ); + } + + switch ( GOT_REPLOG(got_replog) ) { + case GOT_REPLOG_YES: + Debug( LDAP_DEBUG_CONFIG, "%s: line %d: " + "got replog specific replica-argsfile \"%s\".\n", + fname, lineno, cargv[1] ); + case GOT_REPLOG_NO: + LUTIL_SLASHPATH( cargv[1] ); + if ( slurpd_args_file != NULL ) { + ch_free( slurpd_args_file ); + } + slurpd_args_file = ch_strdup( cargv[1] ); + got_replog |= GOT_REPLOG_ARGS; + break; + + default: + Debug( LDAP_DEBUG_CONFIG, "%s: line %d: " + "replica-argsfile \"%s\" not mine.\n", + fname, lineno, cargv[1] ); + break; + } + + } else if ( strcasecmp( cargv[0], "replicationinterval" ) == 0 ) { + int c; + + if ( cargc < 2 ) { + Debug( LDAP_DEBUG_ANY, "%s: line %d: missing interval in " + "\"replicationinterval \" line\n", + fname, lineno, 0 ); + return( 1 ); + } + + if ( lutil_atoi( &c, cargv[1] ) != 0 || c < 1 ) { + Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid interval " + "(%d) in \"replicationinterval \" line\n", + fname, lineno, c ); + + return( 1 ); + } + + switch ( GOT_REPLOG(got_replog) ) { + case GOT_REPLOG_YES: + Debug( LDAP_DEBUG_CONFIG, "%s: line %d: " + "got replog specific replicationinterval \"%s\".\n", + fname, lineno, cargv[1] ); + case GOT_REPLOG_NO: + sglob->no_work_interval = c; + got_replog |= GOT_REPLOG_INTERVAL; + break; + + default: + Debug( LDAP_DEBUG_CONFIG, "%s: line %d: " + "replicationinterval \"%s\" not mine.\n", + fname, lineno, cargv[1] ); + break; + } } - sprintf( sglob->slapd_replogfile, cargv[1] ); - } - } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) { - add_replica( cargv, cargc ); } - } - fclose( fp ); - Debug( LDAP_DEBUG_CONFIG, - "Config: ** configuration file successfully read and parsed\n", - 0, 0, 0 ); - return 0; + + fclose( fp ); + Debug( LDAP_DEBUG_CONFIG, + "Config: ** configuration file successfully read and parsed\n", + 0, 0, 0 ); + return 0; } @@ -124,19 +307,30 @@ slurpd_read_config( */ static void parse_line( - char *line, - int *argcp, - char **argv + char *line ) { char * token; - *argcp = 0; + cargc = 0; for ( token = strtok_quote( line, " \t" ); token != NULL; - token = strtok_quote( NULL, " \t" ) ) { - argv[(*argcp)++] = token; + token = strtok_quote( NULL, " \t" ) ) + { + if ( cargc == cargv_size - 1 ) { + char **tmp; + tmp = ch_realloc( cargv, (cargv_size + ARGS_STEP) * + sizeof(*cargv) ); + if (tmp == NULL) { + cargc = 0; + return; + } + cargv = tmp; + cargv_size += ARGS_STEP; + } + + cargv[cargc++] = token; } - argv[*argcp] = NULL; + cargv[cargc] = NULL; } @@ -173,11 +367,13 @@ strtok_quote( } else { inquote = 1; } - strcpy( next, next + 1 ); + AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 ); break; case '\\': - strcpy( next, next + 1 ); + if ( next[1] ) + AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 ); + next++; /* dont parse the escaped character */ break; default: @@ -212,7 +408,7 @@ strtok_quote( * Get a line of input. */ static char * -getline( +slurpd_getline( FILE *fp ) { @@ -225,13 +421,17 @@ getline( CATLINE( buf ); while ( fgets( buf, sizeof(buf), fp ) != NULL ) { if ( (p = strchr( buf, '\n' )) != NULL ) { - *p = '\0'; + if( p > buf && p[-1] == '\r' ) --p; + *p = '\0'; } lineno++; if ( ! isspace( (unsigned char) buf[0] ) ) { return( line ); } + /* change leading whitespace to space */ + buf[0] = ' '; + CATLINE( buf ); } buf[0] = '\0'; @@ -256,13 +456,13 @@ add_replica( ( nr + 1 ) * sizeof( Re * )); if ( sglob->replicas == NULL ) { fprintf( stderr, "out of memory, add_replica\n" ); - exit( 1 ); + exit( EXIT_FAILURE ); } sglob->replicas[ nr ] = NULL; if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) { fprintf( stderr, "out of memory, Ri_init\n" ); - exit( 1 ); + exit( EXIT_FAILURE ); } if ( parse_replica_line( cargv, cargc, sglob->replicas[ nr - 1] ) < 0 ) { @@ -285,7 +485,7 @@ add_replica( sglob->replicas[ nr - 1 ] ); if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) { fprintf( stderr, "Failed to add status element structure\n" ); - exit( 1 ); + exit( EXIT_FAILURE ); } } } @@ -296,7 +496,7 @@ add_replica( * Parse a "replica" line from the config file. replica lines should be * in the following format: * replica host= binddn= - * bindmethod="simple|kerberos" credentials= + * bindmethod="simple" credentials= * * where: * describes the host name and port number where the @@ -304,12 +504,10 @@ add_replica( * * is the DN to bind to the replica slapd as, * - * bindmethod is either "simple" or "kerberos", and + * bindmethod is "simple", and * * are the credentials (e.g. password) for binddn. are - * only used for bindmethod=simple. For bindmethod=kerberos, the - * credentials= option should be omitted. Credentials for kerberos - * authentication are in the system srvtab file. + * only used for bindmethod=simple. * * The "replica" config file line may be split across multiple lines. If * a line begins with whitespace, it is considered a continuation of the @@ -319,6 +517,8 @@ add_replica( #define GOT_DN 2 #define GOT_METHOD 4 #define GOT_ALL ( GOT_HOST | GOT_DN | GOT_METHOD ) +#define GOT_MECH 8 + static int parse_replica_line( char **cargv, @@ -329,58 +529,130 @@ parse_replica_line( int gots = 0; int i; char *hp, *val; + LDAPURLDesc *ludp; for ( i = 1; i < cargc; i++ ) { - if ( !strncasecmp( cargv[ i ], HOSTSTR, strlen( HOSTSTR ))) { - val = cargv[ i ] + strlen( HOSTSTR ) + 1; + if ( !strncasecmp( cargv[ i ], HOSTSTR, sizeof( HOSTSTR ) - 1 ) ) { + if ( gots & GOT_HOST ) { + fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " ); + fprintf( stderr, "file, too many host or uri names specified, line %d\n", + lineno ); + return -1; + } + val = cargv[ i ] + sizeof( HOSTSTR ); /* '\0' string terminator accounts for '=' */ if (( hp = strchr( val, ':' )) != NULL ) { *hp = '\0'; hp++; - ri->ri_port = atoi( hp ); + if ( lutil_atoi( &ri->ri_port, hp ) != 0 ) { + fprintf( stderr, "unable to parse port \"%s\", line %d\n", + hp, lineno ); + return -1; + } } if ( ri->ri_port <= 0 ) { - ri->ri_port = 0; + ri->ri_port = LDAP_PORT; } ri->ri_hostname = strdup( val ); gots |= GOT_HOST; + } else if ( !strncasecmp( cargv[ i ], URISTR, sizeof( URISTR ) - 1 ) ) { + if ( gots & GOT_HOST ) { + fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " ); + fprintf( stderr, "file, too many host or uri names specified, line %d\n", + lineno ); + return -1; + } + if ( ldap_url_parse( cargv[ i ] + sizeof( URISTR ), &ludp ) != LDAP_SUCCESS ) { + fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " ); + fprintf( stderr, "file, bad uri format specified, line %d\n", + lineno ); + return -1; + } + if (ludp->lud_host == NULL) { + fprintf( stderr, "Error: Malformed \"replica\" line in slapd config " ); + fprintf( stderr, "file, missing uri hostname, line %d\n", + lineno ); + return -1; + } + ri->ri_hostname = strdup ( ludp->lud_host ); + ri->ri_port = ludp->lud_port; + ri->ri_uri = strdup ( cargv[ i ] + sizeof( URISTR ) ); + ldap_free_urldesc( ludp ); + gots |= GOT_HOST; + } else if ( !strncasecmp( cargv[ i ], + ATTRSTR, sizeof( ATTRSTR ) - 1 ) ) { + /* ignore it */ ; + } else if ( !strncasecmp( cargv[ i ], + SUFFIXSTR, sizeof( SUFFIXSTR ) - 1 ) ) { + /* ignore it */ ; + } else if ( !strncasecmp( cargv[i], STARTTLSSTR, sizeof(STARTTLSSTR)-1 )) { + val = cargv[ i ] + sizeof( STARTTLSSTR ); + if( !strcasecmp( val, CRITICALSTR ) ) { + ri->ri_tls = TLS_CRITICAL; + } else { + ri->ri_tls = TLS_ON; + } + } else if ( !strncasecmp( cargv[ i ], TLSSTR, sizeof( TLSSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( TLSSTR ); + if( !strcasecmp( val, CRITICALSTR ) ) { + ri->ri_tls = TLS_CRITICAL; + } else { + ri->ri_tls = TLS_ON; + } } else if ( !strncasecmp( cargv[ i ], - BINDDNSTR, strlen( BINDDNSTR ))) { - val = cargv[ i ] + strlen( BINDDNSTR ) + 1; + BINDDNSTR, sizeof( BINDDNSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( BINDDNSTR ); ri->ri_bind_dn = strdup( val ); gots |= GOT_DN; } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR, - strlen( BINDMETHSTR ))) { - val = cargv[ i ] + strlen( BINDMETHSTR ) + 1; + sizeof( BINDMETHSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( BINDMETHSTR ); if ( !strcasecmp( val, KERBEROSSTR )) { -#ifdef HAVE_KERBEROS - ri->ri_bind_method = AUTH_KERBEROS; - if ( ri->ri_srvtab == NULL ) { - ri->ri_srvtab = strdup( sglob->default_srvtab ); - } - gots |= GOT_METHOD; -#else /* HAVE_KERBEROS */ fprintf( stderr, "Error: a bind method of \"kerberos\" was\n" ); - fprintf( stderr, "specified in the slapd configuration file,\n" ); - fprintf( stderr, "but slurpd was not built with kerberos.\n" ); - fprintf( stderr, "You must rebuild the LDAP release with\n" ); - fprintf( stderr, "kerberos support if you wish to use\n" ); - fprintf( stderr, "bindmethod=kerberos\n" ); - exit( 1 ); -#endif /* HAVE_KERBEROS */ + fprintf( stderr, "specified in the slapd configuration file.\n" ); + fprintf( stderr, "slurpd no longer supports Kerberos.\n" ); + exit( EXIT_FAILURE ); } else if ( !strcasecmp( val, SIMPLESTR )) { - ri->ri_bind_method = AUTH_SIMPLE; + ri->ri_bind_method = LDAP_AUTH_SIMPLE; + gots |= GOT_METHOD; + } else if ( !strcasecmp( val, SASLSTR )) { + ri->ri_bind_method = LDAP_AUTH_SASL; gots |= GOT_METHOD; } else { ri->ri_bind_method = -1; } - } else if ( !strncasecmp( cargv[ i ], CREDSTR, strlen( CREDSTR ))) { - val = cargv[ i ] + strlen( CREDSTR ) + 1; + } else if ( !strncasecmp( cargv[ i ], + SASLMECHSTR, sizeof( SASLMECHSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( SASLMECHSTR ); + gots |= GOT_MECH; + ri->ri_saslmech = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], + CREDSTR, sizeof( CREDSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( CREDSTR ); ri->ri_password = strdup( val ); - } else if ( !strncasecmp( cargv[ i ], BINDPSTR, strlen( BINDPSTR ))) { - val = cargv[ i ] + strlen( BINDPSTR ) + 1; - ri->ri_principal = strdup( val ); - } else if ( !strncasecmp( cargv[ i ], SRVTABSTR, strlen( SRVTABSTR ))) { - val = cargv[ i ] + strlen( SRVTABSTR ) + 1; + } else if ( !strncasecmp( cargv[ i ], + SECPROPSSTR, sizeof( SECPROPSSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( SECPROPSSTR ); + ri->ri_secprops = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], + REALMSTR, sizeof( REALMSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( REALMSTR ); + ri->ri_realm = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], + AUTHCSTR, sizeof( AUTHCSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( AUTHCSTR ); + ri->ri_authcId = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], + OLDAUTHCSTR, sizeof( OLDAUTHCSTR ) - 1 ) ) { + /* Old authcID is provided for some backwards compatibility */ + val = cargv[ i ] + sizeof( OLDAUTHCSTR ); + ri->ri_authcId = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], + AUTHZSTR, sizeof( AUTHZSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( AUTHZSTR ); + ri->ri_authzId = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], + SRVTABSTR, sizeof( SRVTABSTR ) - 1 ) ) { + val = cargv[ i ] + sizeof( SRVTABSTR ); if ( ri->ri_srvtab != NULL ) { free( ri->ri_srvtab ); } @@ -391,11 +663,18 @@ parse_replica_line( cargv[ i ] ); } } - if ( gots != GOT_ALL ) { - fprintf( stderr, "Error: Malformed \"replica\" line in slapd " ); - fprintf( stderr, "config file, line %d\n", lineno ); - return -1; - } + + if ( ri->ri_bind_method == LDAP_AUTH_SASL) { + if ((gots & GOT_MECH) == 0) { + fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " ); + fprintf( stderr, "slapd config file, line %d\n", lineno ); + return -1; + } + } else if ( gots != GOT_ALL ) { + fprintf( stderr, "Error: Malformed \"replica\" line in slapd " ); + fprintf( stderr, "config file, line %d\n", lineno ); + return -1; + } return 0; }