]> git.sur5r.net Git - openldap/blob - servers/slapd/config.c
0fdb6229c2ff0cec8c42e60176b5152a82de0dad
[openldap] / servers / slapd / config.c
1 /* config.c - configuration file handling routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/ctype.h>
14 #include <ac/signal.h>
15 #include <ac/socket.h>
16 #include <ac/errno.h>
17
18 #include "lutil.h"
19 #include "ldap_pvt.h"
20 #include "slap.h"
21
22 #define ARGS_STEP       512
23
24 /*
25  * defaults for various global variables
26  */
27 struct slap_limits_set deflimit = {
28         SLAPD_DEFAULT_TIMELIMIT,        /* backward compatible limits */
29         0,
30
31         SLAPD_DEFAULT_SIZELIMIT,        /* backward compatible limits */
32         0,
33         -1                              /* no limit on unchecked size */
34 };
35
36 AccessControl   *global_acl = NULL;
37 slap_access_t           global_default_access = ACL_READ;
38 slap_mask_t             global_restrictops = 0;
39 slap_mask_t             global_allows = 0;
40 slap_mask_t             global_disallows = 0;
41 slap_mask_t             global_requires = 0;
42 slap_ssf_set_t  global_ssf_set;
43 char            *replogfile;
44 int             global_gentlehup = 0;
45 int             global_idletimeout = 0;
46 char    *global_host = NULL;
47 char    *global_realm = NULL;
48 char            *ldap_srvtab = "";
49 char            *default_passwd_hash = NULL;
50 int             cargc = 0, cargv_size = 0;
51 char    **cargv;
52 struct berval default_search_base = { 0, NULL };
53 struct berval default_search_nbase = { 0, NULL };
54 unsigned                num_subordinates = 0;
55
56 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
57 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
58
59 char   *slapd_pid_file  = NULL;
60 char   *slapd_args_file = NULL;
61
62 char   *strtok_quote_ptr;
63
64 #ifdef SLAPD_RLOOKUPS
65 int use_reverse_lookup = 1;
66 #else /* !SLAPD_RLOOKUPS */
67 int use_reverse_lookup = 0;
68 #endif /* !SLAPD_RLOOKUPS */
69
70 static char     *fp_getline(FILE *fp, int *lineno);
71 static void     fp_getline_init(int *lineno);
72 static int      fp_parse_line(int lineno, char *line);
73
74 static char     *strtok_quote(char *line, char *sep);
75 static int      load_ucdata(char *path);
76
77 int
78 read_config( const char *fname )
79 {
80         FILE    *fp;
81         char    *line, *savefname, *saveline;
82         int savelineno;
83         int     lineno, i;
84         int rc;
85         struct berval vals[2];
86
87         static int lastmod = 1;
88         static BackendInfo *bi = NULL;
89         static BackendDB        *be = NULL;
90
91         vals[1].bv_val = NULL;
92
93         cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
94         cargv_size = ARGS_STEP + 1;
95
96         if ( (fp = fopen( fname, "r" )) == NULL ) {
97                 ldap_syslog = 1;
98 #ifdef NEW_LOGGING
99                 LDAP_LOG(( "config", LDAP_LEVEL_ENTRY, "read_config: "
100                         "could not open config file \"%s\": %s (%d)\n",
101                     fname, strerror(errno), errno ));
102 #else
103                 Debug( LDAP_DEBUG_ANY,
104                     "could not open config file \"%s\": %s (%d)\n",
105                     fname, strerror(errno), errno );
106 #endif
107                 return 1;
108         }
109
110 #ifdef NEW_LOGGING
111         LDAP_LOG(( "config", LDAP_LEVEL_ENTRY,
112                 "read_config: reading config file %s\n", fname ));
113 #else
114         Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
115 #endif
116
117
118         fp_getline_init( &lineno );
119
120         while ( (line = fp_getline( fp, &lineno )) != NULL ) {
121                 /* skip comments and blank lines */
122                 if ( line[0] == '#' || line[0] == '\0' ) {
123                         continue;
124                 }
125
126                 /* fp_parse_line is destructive, we save a copy */
127                 saveline = ch_strdup( line );
128
129                 if ( fp_parse_line( lineno, line ) != 0 ) {
130                         return( 1 );
131                 }
132
133                 if ( cargc < 1 ) {
134 #ifdef NEW_LOGGING
135                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
136                                    "%s: line %d: bad config line (ignored)\n",
137                                    fname, lineno ));
138 #else
139                         Debug( LDAP_DEBUG_ANY,
140                             "%s: line %d: bad config line (ignored)\n",
141                             fname, lineno, 0 );
142 #endif
143
144                         continue;
145                 }
146
147                 if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
148                         if ( cargc < 2 ) {
149 #ifdef NEW_LOGGING
150                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
151                                            "%s : line %d: missing type in \"backend\" line.\n",
152                                            fname, lineno ));
153 #else
154                                 Debug( LDAP_DEBUG_ANY,
155                 "%s: line %d: missing type in \"backend <type>\" line\n",
156                                     fname, lineno, 0 );
157 #endif
158
159                                 return( 1 );
160                         }
161
162                         if( be != NULL ) {
163 #ifdef NEW_LOGGING
164                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
165                                            "%s: line %d: backend line must appear before any "
166                                            "database definition.\n", fname, lineno ));
167 #else
168                                 Debug( LDAP_DEBUG_ANY,
169 "%s: line %d: backend line must appear before any database definition\n",
170                                     fname, lineno, 0 );
171 #endif
172
173                                 return( 1 );
174                         }
175
176                         bi = backend_info( cargv[1] );
177
178                         if( bi == NULL ) {
179 #ifdef NEW_LOGGING
180                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
181                                            "read_config: backend %s initialization failed.\n",
182                                            cargv[1] ));
183 #else
184                                 Debug( LDAP_DEBUG_ANY,
185                                         "backend %s initialization failed.\n",
186                                     cargv[1], 0, 0 );
187 #endif
188
189                                 return( 1 );
190                         }
191                 } else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
192                         if ( cargc < 2 ) {
193 #ifdef NEW_LOGGING
194                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
195                                            "%s: line %d: missing type in \"database <type>\" line\n",
196                                            fname, lineno ));
197 #else
198                                 Debug( LDAP_DEBUG_ANY,
199                 "%s: line %d: missing type in \"database <type>\" line\n",
200                                     fname, lineno, 0 );
201 #endif
202
203                                 return( 1 );
204                         }
205
206                         bi = NULL;
207                         be = backend_db_init( cargv[1] );
208
209                         if( be == NULL ) {
210 #ifdef NEW_LOGGING
211                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
212                                            "database %s initialization failed.\n",
213                                            cargv[1] ));
214 #else
215                                 Debug( LDAP_DEBUG_ANY,
216                                         "database %s initialization failed.\n",
217                                     cargv[1], 0, 0 );
218 #endif
219
220                                 return( 1 );
221                         }
222
223                 /* set thread concurrency */
224                 } else if ( strcasecmp( cargv[0], "concurrency" ) == 0 ) {
225                         int c;
226                         if ( cargc < 2 ) {
227 #ifdef NEW_LOGGING
228                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
229                                            "%s: line %d: missing level in \"concurrency <level\" line\n",
230                                            fname, lineno ));
231 #else
232                                 Debug( LDAP_DEBUG_ANY,
233             "%s: line %d: missing level in \"concurrency <level>\" line\n",
234                                     fname, lineno, 0 );
235 #endif
236
237                                 return( 1 );
238                         }
239
240                         c = atoi( cargv[1] );
241
242                         if( c < 1 ) {
243 #ifdef NEW_LOGGING
244                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
245                                            "%s: line %d: invalid level (%d) in "
246                                            "\"concurrency <level>\" line.\n",
247                                            fname, lineno, c ));
248 #else
249                                 Debug( LDAP_DEBUG_ANY,
250             "%s: line %d: invalid level (%d) in \"concurrency <level>\" line\n",
251                                     fname, lineno, c );
252 #endif
253
254                                 return( 1 );
255                         }
256
257                         ldap_pvt_thread_set_concurrency( c );
258
259                 /* set sockbuf max */
260                 } else if ( strcasecmp( cargv[0], "sockbuf_max_incoming" ) == 0 ) {
261                         long max;
262                         if ( cargc < 2 ) {
263 #ifdef NEW_LOGGING
264                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
265                                            "%s: line %d: missing max in \"sockbuf_max_incoming <bytes>\" line\n",
266                                            fname, lineno ));
267 #else
268                                 Debug( LDAP_DEBUG_ANY,
269                                            "%s: line %d: missing max in \"sockbuf_max_incoming <bytes>\" line\n",
270                                     fname, lineno, 0 );
271 #endif
272
273                                 return( 1 );
274                         }
275
276                         max = atol( cargv[1] );
277
278                         if( max < 0 ) {
279 #ifdef NEW_LOGGING
280                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
281                                            "%s: line %d: invalid max value (%ld) in "
282                                            "\"sockbuf_max_incoming <bytes>\" line.\n",
283                                            fname, lineno, max ));
284 #else
285                                 Debug( LDAP_DEBUG_ANY,
286                                         "%s: line %d: invalid max value (%ld) in "
287                                         "\"sockbuf_max_incoming <bytes>\" line.\n",
288                                     fname, lineno, max );
289 #endif
290
291                                 return( 1 );
292                         }
293
294                         sockbuf_max_incoming = max;
295
296                 /* set sockbuf max authenticated */
297                 } else if ( strcasecmp( cargv[0], "sockbuf_max_incoming_auth" ) == 0 ) {
298                         long max;
299                         if ( cargc < 2 ) {
300 #ifdef NEW_LOGGING
301                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
302                                            "%s: line %d: missing max in \"sockbuf_max_incoming_auth <bytes>\" line\n",
303                                            fname, lineno ));
304 #else
305                                 Debug( LDAP_DEBUG_ANY,
306                                            "%s: line %d: missing max in \"sockbuf_max_incoming_auth <bytes>\" line\n",
307                                     fname, lineno, 0 );
308 #endif
309
310                                 return( 1 );
311                         }
312
313                         max = atol( cargv[1] );
314
315                         if( max < 0 ) {
316 #ifdef NEW_LOGGING
317                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
318                                            "%s: line %d: invalid max value (%ld) in "
319                                            "\"sockbuf_max_incoming_auth <bytes>\" line.\n",
320                                            fname, lineno, max ));
321 #else
322                                 Debug( LDAP_DEBUG_ANY,
323                                         "%s: line %d: invalid max value (%ld) in "
324                                         "\"sockbuf_max_incoming_auth <bytes>\" line.\n",
325                                     fname, lineno, max );
326 #endif
327
328                                 return( 1 );
329                         }
330
331                         sockbuf_max_incoming_auth = max;
332
333                 /* default search base */
334                 } else if ( strcasecmp( cargv[0], "defaultSearchBase" ) == 0 ) {
335                         if ( cargc < 2 ) {
336 #ifdef NEW_LOGGING
337                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
338                                         "%s: line %d: missing dn in \"defaultSearchBase <dn\" "
339                                         "line\n", fname, lineno ));
340 #else
341                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
342                                         "missing dn in \"defaultSearchBase <dn>\" line\n",
343                                         fname, lineno, 0 );
344 #endif
345
346                                 return 1;
347
348                         } else if ( cargc > 2 ) {
349 #ifdef NEW_LOGGING
350                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
351                                         "%s: line %d: extra cruft after <dn> in "
352                                         "\"defaultSearchBase %s\" line (ignored)\n",
353                                         fname, lineno, cargv[1] ));
354 #else
355                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
356                                         "extra cruft after <dn> in \"defaultSearchBase %s\", "
357                                         "line (ignored)\n",
358                                         fname, lineno, cargv[1] );
359 #endif
360                         }
361
362                         if ( bi != NULL || be != NULL ) {
363 #ifdef NEW_LOGGING
364                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
365                                         "%s: line %d: defaultSearchBase line must appear "
366                                         "prior to any backend or database definitions\n",
367                                         fname, lineno ));
368 #else
369                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
370                                         "defaultSearchBaase line must appear prior to "
371                                         "any backend or database definition\n",
372                                     fname, lineno, 0 );
373 #endif
374
375                                 return 1;
376                         }
377
378                         if ( default_search_nbase.bv_len ) {
379 #ifdef NEW_LOGGING
380                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
381                                         "default search base \"%s\" already defined "
382                                         "(discarding old)\n", fname, lineno,
383                                         default_search_base.bv_val ));
384 #else
385                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
386                                         "default search base \"%s\" already defined "
387                                         "(discarding old)\n",
388                                         fname, lineno, default_search_base.bv_val );
389 #endif
390
391                                 free( default_search_base.bv_val );
392                                 free( default_search_nbase.bv_val );
393                         }
394
395                         if ( load_ucdata( NULL ) < 0 ) return 1;
396
397                         {
398                                 struct berval dn;
399
400                                 dn.bv_val = cargv[1];
401                                 dn.bv_len = strlen( dn.bv_val );
402
403                                 rc = dnPrettyNormal( NULL, &dn,
404                                         &default_search_base,
405                                         &default_search_nbase );
406
407                                 if( rc != LDAP_SUCCESS ) {
408 #ifdef NEW_LOGGING
409                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
410                                                 "%s: line %d: defaultSearchBase DN is invalid.\n",
411                                                 fname, lineno ));
412 #else
413                                         Debug( LDAP_DEBUG_ANY,
414                                                 "%s: line %d: defaultSearchBase DN is invalid\n",
415                                            fname, lineno, 0 );
416 #endif
417                                         return( 1 );
418                                 }
419                         }
420
421                 /* set maximum threads in thread pool */
422                 } else if ( strcasecmp( cargv[0], "threads" ) == 0 ) {
423                         int c;
424                         if ( cargc < 2 ) {
425 #ifdef NEW_LOGGING
426                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
427                                            "%s: line %d: missing count in \"threads <count>\" line\n",
428                                            fname, lineno ));
429 #else
430                                 Debug( LDAP_DEBUG_ANY,
431             "%s: line %d: missing count in \"threads <count>\" line\n",
432                                     fname, lineno, 0 );
433 #endif
434
435                                 return( 1 );
436                         }
437
438                         c = atoi( cargv[1] );
439
440                         if( c < 0 ) {
441 #ifdef NEW_LOGGING
442                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
443                                            "%s: line %d: invalid level (%d) in \"threads <count>\""
444                                            "line\n",fname, lineno, c ));
445 #else
446                                 Debug( LDAP_DEBUG_ANY,
447             "%s: line %d: invalid level (%d) in \"threads <count>\" line\n",
448                                     fname, lineno, c );
449 #endif
450
451                                 return( 1 );
452                         }
453
454                         ldap_pvt_thread_pool_maxthreads( &connection_pool, c );
455
456                         /* save for later use */
457                         connection_pool_max = c;
458
459                 /* get pid file name */
460                 } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
461                         if ( cargc < 2 ) {
462 #ifdef NEW_LOGGING
463                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
464                                            "%s: line %d missing file name in \"pidfile <file>\" line.\n",
465                                            fname, lineno ));
466 #else
467                                 Debug( LDAP_DEBUG_ANY,
468             "%s: line %d: missing file name in \"pidfile <file>\" line\n",
469                                     fname, lineno, 0 );
470 #endif
471
472                                 return( 1 );
473                         }
474
475                         slapd_pid_file = ch_strdup( cargv[1] );
476
477                 /* get args file name */
478                 } else if ( strcasecmp( cargv[0], "argsfile" ) == 0 ) {
479                         if ( cargc < 2 ) {
480 #ifdef NEW_LOGGING
481                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
482                                            "%s: %d: missing file name in "
483                                            "\"argsfile <file>\" line.\n",
484                                            fname, lineno ));
485 #else
486                                 Debug( LDAP_DEBUG_ANY,
487             "%s: line %d: missing file name in \"argsfile <file>\" line\n",
488                                     fname, lineno, 0 );
489 #endif
490
491                                 return( 1 );
492                         }
493
494                         slapd_args_file = ch_strdup( cargv[1] );
495
496                 /* default password hash */
497                 } else if ( strcasecmp( cargv[0], "password-hash" ) == 0 ) {
498                         if ( cargc < 2 ) {
499 #ifdef NEW_LOGGING
500                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
501                                            "%s: line %d: missing hash in "
502                                            "\"password-hash <hash>\" line.\n",
503                                            fname, lineno ));
504 #else
505                                 Debug( LDAP_DEBUG_ANY,
506             "%s: line %d: missing hash in \"password-hash <hash>\" line\n",
507                                     fname, lineno, 0 );
508 #endif
509
510                                 return( 1 );
511                         }
512                         if ( default_passwd_hash != NULL ) {
513 #ifdef NEW_LOGGING
514                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
515                                            "%s: line %d: already set default password_hash!\n",
516                                            fname, lineno ));
517 #else
518                                 Debug( LDAP_DEBUG_ANY,
519                                         "%s: line %d: already set default password_hash!\n",
520                                         fname, lineno, 0 );
521 #endif
522
523                                 return 1;
524
525                         }
526
527                         if ( lutil_passwd_scheme( cargv[1] ) == 0 ) {
528 #ifdef NEW_LOGGING
529                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
530                                            "%s: line %d: password scheme \"%s\" not available\n",
531                                            fname, lineno, cargv[1] ));
532 #else
533                                 Debug( LDAP_DEBUG_ANY,
534                                         "%s: line %d: password scheme \"%s\" not available\n",
535                                         fname, lineno, cargv[1] );
536 #endif
537                                 return 1;
538                         }
539
540                         default_passwd_hash = ch_strdup( cargv[1] );
541
542                 } else if ( strcasecmp( cargv[0], "password-crypt-salt-format" ) == 0 ) 
543                 {
544                         if ( cargc < 2 ) {
545 #ifdef NEW_LOGGING
546                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
547                                         "%s: line %d: missing format in "
548                                         "\"password-crypt-salt-format <format>\" line\n",
549                                         fname, lineno ));
550 #else
551                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: missing format in "
552                                         "\"password-crypt-salt-format <format>\" line\n",
553                                     fname, lineno, 0 );
554 #endif
555
556                                 return 1;
557                         }
558
559                         lutil_salt_format( cargv[1] );
560
561                 /* SASL config options */
562                 } else if ( strncasecmp( cargv[0], "sasl", 4 ) == 0 ) {
563                         if ( slap_sasl_config( cargc, cargv, line, fname, lineno ) )
564                                 return 1;
565
566                 /* set UCDATA path */
567                 } else if ( strcasecmp( cargv[0], "ucdata-path" ) == 0 ) {
568                         int err;
569                         if ( cargc < 2 ) {
570 #ifdef NEW_LOGGING
571                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
572                                            "%s: line %d: missing path in "
573                                            "\"ucdata-path <path>\" line.\n",
574                                            fname, lineno ));
575 #else
576                                 Debug( LDAP_DEBUG_ANY,
577             "%s: line %d: missing path in \"ucdata-path <path>\" line\n",
578                                     fname, lineno, 0 );
579 #endif
580
581                                 return( 1 );
582                         }
583
584                         err = load_ucdata( cargv[1] );
585                         if ( err <= 0 ) {
586                                 if ( err == 0 ) {
587 #ifdef NEW_LOGGING
588                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
589                                                    "%s: line %d: ucdata already loaded, ucdata-path "
590                                                    "must be set earlier in the file and/or be "
591                                                    "specified only once!\n",
592                                                    fname, lineno ));
593 #else
594                                         Debug( LDAP_DEBUG_ANY,
595                                                "%s: line %d: ucdata already loaded, ucdata-path must be set earlier in the file and/or be specified only once!\n",
596                                                fname, lineno, 0 );
597 #endif
598
599                                 }
600                                 return( 1 );
601                         }
602
603                 /* set size limit */
604                 } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
605                         int rc = 0, i;
606                         struct slap_limits_set *lim;
607                         
608                         if ( cargc < 2 ) {
609 #ifdef NEW_LOGGING
610                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
611                                            "%s: line %d: missing limit in \"sizelimit <limit>\" line.\n",
612                                            fname, lineno ));
613 #else
614                                 Debug( LDAP_DEBUG_ANY,
615             "%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
616                                     fname, lineno, 0 );
617 #endif
618
619                                 return( 1 );
620                         }
621
622                         if ( be == NULL ) {
623                                 lim = &deflimit;
624                         } else {
625                                 lim = &be->be_def_limit;
626                         }
627
628                         for ( i = 1; i < cargc; i++ ) {
629                                 if ( strncasecmp( cargv[i], "size", 4 ) == 0 ) {
630                                         rc = parse_limit( cargv[i], lim );
631                                 } else {
632                                         lim->lms_s_soft = atoi( cargv[i] );
633                                         lim->lms_s_hard = 0;
634                                 }
635
636                                 if ( rc ) {
637 #ifdef NEW_LOGGING
638                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
639                                                    "%s: line %d: unable "
640                                                    "to parse value \"%s\" "
641                                                    "in \"sizelimit "
642                                                    "<limit>\" line.\n",
643                                                    fname, lineno, cargv[i] ));
644 #else
645                                         Debug( LDAP_DEBUG_ANY,
646                                                 "%s: line %d: unable "
647                                                 "to parse value \"%s\" "
648                                                 "in \"sizelimit "
649                                                 "<limit>\" line\n",
650                                                 fname, lineno, cargv[i] );
651 #endif
652                                 }
653                         }
654
655                 /* set time limit */
656                 } else if ( strcasecmp( cargv[0], "timelimit" ) == 0 ) {
657                         int rc = 0, i;
658                         struct slap_limits_set *lim;
659                         
660                         if ( cargc < 2 ) {
661 #ifdef NEW_LOGGING
662                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
663                                            "%s: line %d missing limit in \"timelimit <limit>\" line.\n",
664                                            fname, lineno ));
665 #else
666                                 Debug( LDAP_DEBUG_ANY,
667             "%s: line %d: missing limit in \"timelimit <limit>\" line\n",
668                                     fname, lineno, 0 );
669 #endif
670
671                                 return( 1 );
672                         }
673                         
674                         if ( be == NULL ) {
675                                 lim = &deflimit;
676                         } else {
677                                 lim = &be->be_def_limit;
678                         }
679
680                         for ( i = 1; i < cargc; i++ ) {
681                                 if ( strncasecmp( cargv[i], "time", 4 ) == 0 ) {
682                                         rc = parse_limit( cargv[i], lim );
683                                 } else {
684                                         lim->lms_t_soft = atoi( cargv[i] );
685                                         lim->lms_t_hard = 0;
686                                 }
687
688                                 if ( rc ) {
689 #ifdef NEW_LOGGING
690                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
691                                                    "%s: line %d: unable "
692                                                    "to parse value \"%s\" "
693                                                    "in \"timelimit "
694                                                    "<limit>\" line.\n",
695                                                    fname, lineno, cargv[i] ));
696 #else
697                                         Debug( LDAP_DEBUG_ANY,
698                                                 "%s: line %d: unable "
699                                                 "to parse value \"%s\" "
700                                                 "in \"timelimit "
701                                                 "<limit>\" line\n",
702                                                 fname, lineno, cargv[i] );
703 #endif
704                                 }
705                         }
706
707                 /* set regex-based limits */
708                 } else if ( strcasecmp( cargv[0], "limits" ) == 0 ) {
709                         if ( be == NULL ) {
710 #ifdef NEW_LOGGING
711                                 LDAP_LOG(( "config", LDAP_LEVEL_WARNING,
712                                            "%s: line %d \"limits\" allowed only in database environment.\n",
713                                            fname, lineno ));
714 #else
715                                 Debug( LDAP_DEBUG_ANY,
716         "%s: line %d \"limits\" allowed only in database environment.\n%s",
717                                         fname, lineno, "" );
718 #endif
719                                 return( 1 );
720                         }
721
722                         if ( parse_limits( be, fname, lineno, cargc, cargv ) ) {
723                                 return( 1 );
724                         }
725
726                 /* mark this as a subordinate database */
727                 } else if ( strcasecmp( cargv[0], "subordinate" ) == 0 ) {
728                         if ( be == NULL ) {
729 #ifdef NEW_LOGGING
730                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
731                                         "subordinate keyword must appear inside a database "
732                                         "definition.\n", fname, lineno ));
733 #else
734                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix line "
735                                         "must appear inside a database definition.\n",
736                                     fname, lineno, 0 );
737 #endif
738                                 return 1;
739
740                         } else {
741                                 be->be_flags |= SLAP_BFLAG_GLUE_SUBORDINATE;
742                                 num_subordinates++;
743                         }
744
745                 /* set database suffix */
746                 } else if ( strcasecmp( cargv[0], "suffix" ) == 0 ) {
747                         Backend *tmp_be;
748                         struct berval dn, pdn, ndn;
749
750                         if ( cargc < 2 ) {
751 #ifdef NEW_LOGGING
752                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
753                                         "%s: line %d: missing dn in \"suffix <dn>\" line.\n",
754                                         fname, lineno ));
755 #else
756                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
757                                         "missing dn in \"suffix <dn>\" line\n",
758                                     fname, lineno, 0 );
759 #endif
760
761                                 return( 1 );
762
763                         } else if ( cargc > 2 ) {
764 #ifdef NEW_LOGGING
765                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
766                                         "%s: line %d: extra cruft after <dn> in \"suffix %s\""
767                                         " line (ignored).\n", fname, lineno, cargv[1] ));
768 #else
769                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: extra cruft "
770                                         "after <dn> in \"suffix %s\" line (ignored)\n",
771                                     fname, lineno, cargv[1] );
772 #endif
773                         }
774
775                         if ( be == NULL ) {
776 #ifdef NEW_LOGGING
777                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
778                                         "%s: line %d: suffix line must appear inside a database "
779                                         "definition.\n", fname, lineno ));
780 #else
781                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix line "
782                                         "must appear inside a database definition\n",
783                                     fname, lineno, 0 );
784 #endif
785                                 return( 1 );
786
787 #if defined(SLAPD_MONITOR_DN)
788                         /* "cn=Monitor" is reserved for monitoring slap */
789                         } else if ( strcasecmp( cargv[1], SLAPD_MONITOR_DN ) == 0 ) {
790 #ifdef NEW_LOGGING
791                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: \""
792                                         SLAPD_MONITOR_DN "\" is reserved for monitoring slapd\n", 
793                                         fname, lineno ));
794 #else
795                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: \""
796                                         SLAPD_MONITOR_DN "\" is reserved for monitoring slapd\n", 
797                                         fname, lineno, 0 );
798 #endif
799                                 return( 1 );
800 #endif /* SLAPD_MONITOR_DN */
801                         }
802
803                         if ( load_ucdata( NULL ) < 0 ) return 1;
804
805                         dn.bv_val = cargv[1];
806                         dn.bv_len = strlen( cargv[1] );
807
808                         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
809                         if( rc != LDAP_SUCCESS ) {
810 #ifdef NEW_LOGGING
811                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
812                                         "%s: line %d: suffix DN is invalid.\n",
813                                         fname, lineno ));
814 #else
815                                 Debug( LDAP_DEBUG_ANY,
816                                         "%s: line %d: suffix DN is invalid\n",
817                                    fname, lineno, 0 );
818 #endif
819                                 return( 1 );
820                         }
821
822                         tmp_be = select_backend( &ndn, 0, 0 );
823                         if ( tmp_be == be ) {
824 #ifdef NEW_LOGGING
825                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
826                                         "%s: line %d: suffix already served by this backend "
827                                         "(ignored)\n", fname, lineno ));
828 #else
829                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix "
830                                         "already served by this backend (ignored)\n",
831                                     fname, lineno, 0 );
832 #endif
833                                 free( pdn.bv_val );
834                                 free( ndn.bv_val );
835
836                         } else if ( tmp_be  != NULL ) {
837 #ifdef NEW_LOGGING
838                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
839                                         "%s: line %d: suffix already served by a preceding "
840                                         "backend \"%s\"\n", fname, lineno,
841                                         tmp_be->be_suffix[0].bv_val ));
842 #else
843                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix "
844                                         "already served by a preceeding backend \"%s\"\n",
845                                     fname, lineno, tmp_be->be_suffix[0].bv_val );
846 #endif
847                                 free( pdn.bv_val );
848                                 free( ndn.bv_val );
849                                 return( 1 );
850
851                         } else if( pdn.bv_len == 0 && default_search_nbase.bv_len ) {
852 #ifdef NEW_LOGGING
853                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
854                                                 "%s: line %d: suffix DN empty and default search "
855                                                 "base provided \"%s\" (assuming okay).\n",
856                                                 fname, lineno, default_search_base.bv_val ));
857 #else
858                                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
859                                                 "suffix DN empty and default "
860                                                 "search base provided \"%s\" (assuming okay)\n",
861                                         fname, lineno, default_search_base.bv_val );
862 #endif
863                         }
864
865                         ber_bvarray_add( &be->be_suffix, &pdn );
866                         ber_bvarray_add( &be->be_nsuffix, &ndn );
867
868                 /* set database suffixAlias */
869                 } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
870                         Backend *tmp_be;
871                         struct berval alias, palias, nalias;
872                         struct berval aliased, paliased, naliased;
873
874                         if ( cargc < 2 ) {
875 #ifdef NEW_LOGGING
876                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
877                                         "%s: line %d: missing alias and aliased_dn in "
878                                         "\"suffixAlias <alias> <aliased_dn>\" line.\n",
879                                         fname, lineno ));
880 #else
881                                 Debug( LDAP_DEBUG_ANY,
882                                         "%s: line %d: missing alias and aliased_dn in "
883                                         "\"suffixAlias <alias> <aliased_dn>\" line.\n",
884                                         fname, lineno, 0 );
885 #endif
886
887                                 return( 1 );
888                         } else if ( cargc < 3 ) {
889 #ifdef NEW_LOGGING
890                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
891                                         "%s: line %d: missing aliased_dn in "
892                                         "\"suffixAlias <alias> <aliased_dn>\" line\n",
893                                         fname, lineno ));
894 #else
895                                 Debug( LDAP_DEBUG_ANY,
896                                         "%s: line %d: missing aliased_dn in "
897                                         "\"suffixAlias <alias> <aliased_dn>\" line\n",
898                                         fname, lineno, 0 );
899 #endif
900                                 return( 1 );
901
902                         } else if ( cargc > 3 ) {
903 #ifdef NEW_LOGGING
904                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
905                                         "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
906                                         fname, lineno ));
907 #else
908                                 Debug( LDAP_DEBUG_ANY,
909                                         "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
910                                         fname, lineno, 0 );
911 #endif
912                         }
913
914                         if ( be == NULL ) {
915 #ifdef NEW_LOGGING
916                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
917                                         "%s: line %d: suffixAlias line must appear inside a "
918                                         "database definition.\n", fname, lineno ));
919 #else
920                                 Debug( LDAP_DEBUG_ANY,
921                                         "%s: line %d: suffixAlias line"
922                                         " must appear inside a database definition.\n",
923                                         fname, lineno, 0 );
924 #endif
925                                 return 1;
926                         }
927
928                         if ( load_ucdata( NULL ) < 0 ) return 1;
929                         
930                         alias.bv_val = cargv[1];
931                         alias.bv_len = strlen( cargv[1] );
932
933                         rc = dnPrettyNormal( NULL, &alias, &palias, &nalias );
934                         if( rc != LDAP_SUCCESS ) {
935 #ifdef NEW_LOGGING
936                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
937                                         "%s: line %d: alias DN is invalid.\n",
938                                         fname, lineno ));
939 #else
940                                 Debug( LDAP_DEBUG_ANY,
941                                         "%s: line %d: alias DN is invalid\n",
942                                    fname, lineno, 0 );
943 #endif
944                                 return( 1 );
945                         }
946
947                         tmp_be = select_backend( &nalias, 0, 0 );
948                         free( nalias.bv_val );
949                         if ( tmp_be && tmp_be != be ) {
950 #ifdef NEW_LOGGING
951                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
952                                         "%s: line %d: suffixAlias served by a preceeding "
953                                         "backend \"%s\"\n",
954                                         fname, lineno, tmp_be->be_suffix[0].bv_val ));
955 #else
956                                 Debug( LDAP_DEBUG_ANY,
957                                         "%s: line %d: suffixAlias served by"
958                                         "  a preceeding backend \"%s\"\n",
959                                         fname, lineno, tmp_be->be_suffix[0].bv_val );
960 #endif
961                                 free( palias.bv_val );
962                                 return -1;
963                         }
964
965                         aliased.bv_val = cargv[2];
966                         aliased.bv_len = strlen( cargv[2] );
967
968                         rc = dnPrettyNormal( NULL, &aliased, &paliased, &naliased );
969                         if( rc != LDAP_SUCCESS ) {
970 #ifdef NEW_LOGGING
971                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
972                                         "%s: line %d: aliased DN is invalid.\n",
973                                         fname, lineno ));
974 #else
975                                 Debug( LDAP_DEBUG_ANY,
976                                         "%s: line %d: aliased DN is invalid\n",
977                                    fname, lineno, 0 );
978 #endif
979                                 free( palias.bv_val );
980                                 return( 1 );
981                         }
982
983                         tmp_be = select_backend( &naliased, 0, 0 );
984                         free( naliased.bv_val );
985                         if ( tmp_be && tmp_be != be ) {
986 #ifdef NEW_LOGGING
987                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
988                                         "%s: line %d: suffixAlias derefs to a different backend "
989                                         "a preceeding backend \"%s\"\n",
990                                         fname, lineno, tmp_be->be_suffix[0].bv_val ));
991 #else
992                                 Debug( LDAP_DEBUG_ANY,
993                                         "%s: line %d: suffixAlias derefs to differnet backend"
994                                         "  a preceeding backend \"%s\"\n",
995                                         fname, lineno, tmp_be->be_suffix[0].bv_val );
996 #endif
997                                 free( palias.bv_val );
998                                 free( paliased.bv_val );
999                                 return -1;
1000                         }
1001
1002                         ber_bvarray_add( &be->be_suffixAlias, &palias ); 
1003                         ber_bvarray_add( &be->be_suffixAlias, &paliased );
1004
1005                /* set max deref depth */
1006                } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
1007                                         int i;
1008                        if ( cargc < 2 ) {
1009 #ifdef NEW_LOGGING
1010                                LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1011                                           "%s: line %d: missing depth in \"maxDerefDepth <depth>\""
1012                                           " line\n", fname, lineno ));
1013 #else
1014                                Debug( LDAP_DEBUG_ANY,
1015                    "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
1016                                    fname, lineno, 0 );
1017 #endif
1018
1019                                return( 1 );
1020                        }
1021                        if ( be == NULL ) {
1022 #ifdef NEW_LOGGING
1023                                LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1024                                           "%s: line %d: depth line must appear inside a database "
1025                                           "definition.\n", fname, lineno ));
1026 #else
1027                                Debug( LDAP_DEBUG_ANY,
1028 "%s: line %d: depth line must appear inside a database definition.\n",
1029                                    fname, lineno, 0 );
1030 #endif
1031                                                         return 1;
1032
1033                        } else if ((i = atoi(cargv[1])) < 0) {
1034 #ifdef NEW_LOGGING
1035                                LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1036                                           "%s: line %d: depth must be positive.\n",
1037                                           fname, lineno ));
1038 #else
1039                                Debug( LDAP_DEBUG_ANY,
1040 "%s: line %d: depth must be positive.\n",
1041                                    fname, lineno, 0 );
1042 #endif
1043                                                         return 1;
1044
1045
1046                        } else {
1047                            be->be_max_deref_depth = i;
1048                                            }
1049
1050
1051                 /* set magic "root" dn for this database */
1052                 } else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
1053                         if ( cargc < 2 ) {
1054 #ifdef NEW_LOGGING
1055                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1056                                            "%s: line %d: missing dn in \"rootdn <dn>\" line.\n",
1057                                            fname, lineno ));
1058 #else
1059                                 Debug( LDAP_DEBUG_ANY,
1060                     "%s: line %d: missing dn in \"rootdn <dn>\" line\n",
1061                                     fname, lineno, 0 );
1062 #endif
1063
1064                                 return( 1 );
1065                         }
1066
1067                         if ( be == NULL ) {
1068 #ifdef NEW_LOGGING
1069                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1070                                            "%s: line %d: rootdn line must appear inside a database "
1071                                            "definition.\n", fname, lineno ));
1072 #else
1073                                 Debug( LDAP_DEBUG_ANY,
1074 "%s: line %d: rootdn line must appear inside a database definition.\n",
1075                                     fname, lineno, 0 );
1076 #endif
1077                                 return 1;
1078
1079                         } else {
1080                                 struct berval dn;
1081                                 
1082                                 if ( load_ucdata( NULL ) < 0 ) return 1;
1083
1084                                 dn.bv_val = cargv[1];
1085                                 dn.bv_len = strlen( cargv[1] );
1086
1087                                 rc = dnPrettyNormal( NULL, &dn,
1088                                         &be->be_rootdn,
1089                                         &be->be_rootndn );
1090
1091                                 if( rc != LDAP_SUCCESS ) {
1092 #ifdef NEW_LOGGING
1093                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1094                                                 "%s: line %d: rootdn DN is invalid.\n",
1095                                                 fname, lineno ));
1096 #else
1097                                         Debug( LDAP_DEBUG_ANY,
1098                                                 "%s: line %d: rootdn DN is invalid\n",
1099                                            fname, lineno, 0 );
1100 #endif
1101                                         return( 1 );
1102                                 }
1103                         }
1104
1105                 /* set super-secret magic database password */
1106                 } else if ( strcasecmp( cargv[0], "rootpw" ) == 0 ) {
1107                         if ( cargc < 2 ) {
1108 #ifdef NEW_LOGGING
1109                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1110                                         "%s: line %d: missing passwd in \"rootpw <passwd>\""
1111                                         " line\n", fname, lineno ));
1112 #else
1113                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1114                                         "missing passwd in \"rootpw <passwd>\" line\n",
1115                                     fname, lineno, 0 );
1116 #endif
1117
1118                                 return( 1 );
1119                         }
1120
1121                         if ( be == NULL ) {
1122 #ifdef NEW_LOGGING
1123                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
1124                                         "rootpw line must appear inside a database "
1125                                         "definition.\n", fname, lineno ));
1126 #else
1127                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1128                                         "rootpw line must appear inside a database "
1129                                         "definition.\n",
1130                                     fname, lineno, 0 );
1131 #endif
1132                                 return 1;
1133
1134                         } else {
1135                                 Backend *tmp_be = select_backend( &be->be_rootndn, 0, 0 );
1136
1137                                 if( tmp_be != be ) {
1138 #ifdef NEW_LOGGING
1139                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1140                                                 "%s: line %d: "
1141                                                 "rootpw can only be set when rootdn is under suffix\n"
1142                                                 fname, lineno ));
1143 #else
1144                                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1145                                                 "rootpw can only be set when rootdn is under suffix\n",
1146                                         fname, lineno, 0 );
1147 #endif
1148                                         return 1;
1149                                 }
1150
1151                                 be->be_rootpw.bv_val = ch_strdup( cargv[1] );
1152                                 be->be_rootpw.bv_len = strlen( be->be_rootpw.bv_val );
1153                         }
1154
1155                 /* make this database read-only */
1156                 } else if ( strcasecmp( cargv[0], "readonly" ) == 0 ) {
1157                         if ( cargc < 2 ) {
1158 #ifdef NEW_LOGGING
1159                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1160                                            "%s: line %d: missing on|off in \"readonly <on|off>\" line.\n",
1161                                            fname, lineno ));
1162 #else
1163                                 Debug( LDAP_DEBUG_ANY,
1164             "%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
1165                                     fname, lineno, 0 );
1166 #endif
1167
1168                                 return( 1 );
1169                         }
1170                         if ( be == NULL ) {
1171                                 if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1172                                         global_restrictops |= SLAP_RESTRICT_OP_WRITES;
1173                                 } else {
1174                                         global_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1175                                 }
1176                         } else {
1177                                 if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1178                                         be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
1179                                 } else {
1180                                         be->be_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1181                                 }
1182                         }
1183
1184
1185                 /* allow these features */
1186                 } else if ( strcasecmp( cargv[0], "allows" ) == 0 ||
1187                         strcasecmp( cargv[0], "allow" ) == 0 )
1188                 {
1189                         slap_mask_t     allows;
1190
1191                         if ( be != NULL ) {
1192 #ifdef NEW_LOGGING
1193                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1194                                            "%s: line %d: allow line must appear prior to "
1195                                            "database definitions.\n", fname, lineno ));
1196 #else
1197                                 Debug( LDAP_DEBUG_ANY,
1198 "%s: line %d: allow line must appear prior to database definitions\n",
1199                                     fname, lineno, 0 );
1200 #endif
1201
1202                         }
1203
1204                         if ( cargc < 2 ) {
1205 #ifdef NEW_LOGGING
1206                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1207                                            "%s: line %d: missing feature(s) in \"allow <features>\""
1208                                            " line\n", fname, lineno ));
1209 #else
1210                                 Debug( LDAP_DEBUG_ANY,
1211             "%s: line %d: missing feature(s) in \"allow <features>\" line\n",
1212                                     fname, lineno, 0 );
1213 #endif
1214
1215                                 return( 1 );
1216                         }
1217
1218                         allows = 0;
1219
1220                         for( i=1; i < cargc; i++ ) {
1221                                 if( strcasecmp( cargv[i], "bind_v2" ) == 0 ) {
1222                                         allows |= SLAP_ALLOW_BIND_V2;
1223
1224                                 } else if( strcasecmp( cargv[i], "bind_anon_cred" ) == 0 ) {
1225                                         allows |= SLAP_ALLOW_BIND_ANON_CRED;
1226
1227                                 } else if( strcasecmp( cargv[i], "bind_anon_dn" ) == 0 ) {
1228                                         allows |= SLAP_ALLOW_BIND_ANON_DN;
1229
1230                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1231 #ifdef NEW_LOGGING
1232                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1233                                                    "%s: line %d: unknown feature %s in "
1234                                                    "\"allow <features>\" line.\n",
1235                                                    fname, lineno, cargv[1] ));
1236 #else
1237                                         Debug( LDAP_DEBUG_ANY,
1238                     "%s: line %d: unknown feature %s in \"allow <features>\" line\n",
1239                                             fname, lineno, cargv[i] );
1240 #endif
1241
1242                                         return( 1 );
1243                                 }
1244                         }
1245
1246                         global_allows = allows;
1247
1248                 /* disallow these features */
1249                 } else if ( strcasecmp( cargv[0], "disallows" ) == 0 ||
1250                         strcasecmp( cargv[0], "disallow" ) == 0 )
1251                 {
1252                         slap_mask_t     disallows;
1253
1254                         if ( be != NULL ) {
1255 #ifdef NEW_LOGGING
1256                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1257                                            "%s: line %d: disallow line must appear prior to "
1258                                            "database definitions.\n", fname, lineno ));
1259 #else
1260                                 Debug( LDAP_DEBUG_ANY,
1261 "%s: line %d: disallow line must appear prior to database definitions\n",
1262                                     fname, lineno, 0 );
1263 #endif
1264
1265                         }
1266
1267                         if ( cargc < 2 ) {
1268 #ifdef NEW_LOGGING
1269                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1270                                            "%s: line %d: missing feature(s) in \"disallow <features>\""
1271                                            " line.\n", fname, lineno ));
1272 #else
1273                                 Debug( LDAP_DEBUG_ANY,
1274             "%s: line %d: missing feature(s) in \"disallow <features>\" line\n",
1275                                     fname, lineno, 0 );
1276 #endif
1277
1278                                 return( 1 );
1279                         }
1280
1281                         disallows = 0;
1282
1283                         for( i=1; i < cargc; i++ ) {
1284                                 if( strcasecmp( cargv[i], "bind_anon" ) == 0 ) {
1285                                         disallows |= SLAP_DISALLOW_BIND_ANON;
1286
1287                                 } else if( strcasecmp( cargv[i], "bind_simple" ) == 0 ) {
1288                                         disallows |= SLAP_DISALLOW_BIND_SIMPLE;
1289
1290                                 } else if( strcasecmp( cargv[i], "bind_krbv4" ) == 0 ) {
1291                                         disallows |= SLAP_DISALLOW_BIND_KRBV4;
1292
1293                                 } else if( strcasecmp( cargv[i], "tls_2_anon" ) == 0 ) {
1294                                         disallows |= SLAP_DISALLOW_TLS_2_ANON;
1295
1296                                 } else if( strcasecmp( cargv[i], "tls_authc" ) == 0 ) {
1297                                         disallows |= SLAP_DISALLOW_TLS_AUTHC;
1298
1299                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1300 #ifdef NEW_LOGGING
1301                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1302                                                 "%s: line %d: unknown feature %s in "
1303                                                 "\"disallow <features>\" line.\n",
1304                                                 fname, lineno, cargv[i] ));
1305 #else
1306                                         Debug( LDAP_DEBUG_ANY,
1307                     "%s: line %d: unknown feature %s in \"disallow <features>\" line\n",
1308                                             fname, lineno, cargv[i] );
1309 #endif
1310
1311                                         return( 1 );
1312                                 }
1313                         }
1314
1315                         global_disallows = disallows;
1316
1317                 /* require these features */
1318                 } else if ( strcasecmp( cargv[0], "requires" ) == 0 ||
1319                         strcasecmp( cargv[0], "require" ) == 0 )
1320                 {
1321                         slap_mask_t     requires;
1322
1323                         if ( cargc < 2 ) {
1324 #ifdef NEW_LOGGING
1325                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1326                                            "%s: line %d: missing feature(s) in "
1327                                            "\"require <features>\" line.\n", fname, lineno ));
1328 #else
1329                                 Debug( LDAP_DEBUG_ANY,
1330             "%s: line %d: missing feature(s) in \"require <features>\" line\n",
1331                                     fname, lineno, 0 );
1332 #endif
1333
1334                                 return( 1 );
1335                         }
1336
1337                         requires = 0;
1338
1339                         for( i=1; i < cargc; i++ ) {
1340                                 if( strcasecmp( cargv[i], "bind" ) == 0 ) {
1341                                         requires |= SLAP_REQUIRE_BIND;
1342
1343                                 } else if( strcasecmp( cargv[i], "LDAPv3" ) == 0 ) {
1344                                         requires |= SLAP_REQUIRE_LDAP_V3;
1345
1346                                 } else if( strcasecmp( cargv[i], "authc" ) == 0 ) {
1347                                         requires |= SLAP_REQUIRE_AUTHC;
1348
1349                                 } else if( strcasecmp( cargv[i], "SASL" ) == 0 ) {
1350                                         requires |= SLAP_REQUIRE_SASL;
1351
1352                                 } else if( strcasecmp( cargv[i], "strong" ) == 0 ) {
1353                                         requires |= SLAP_REQUIRE_STRONG;
1354
1355                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1356 #ifdef NEW_LOGGING
1357                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1358                                                    "%s: line %d: unknown feature %s in "
1359                                                    "\"require <features>\" line.\n",
1360                                                    fname, lineno ));
1361 #else
1362                                         Debug( LDAP_DEBUG_ANY,
1363                     "%s: line %d: unknown feature %s in \"require <features>\" line\n",
1364                                             fname, lineno, cargv[i] );
1365 #endif
1366
1367                                         return( 1 );
1368                                 }
1369                         }
1370
1371                         if ( be == NULL ) {
1372                                 global_requires = requires;
1373                         } else {
1374                                 be->be_requires = requires;
1375                         }
1376
1377                 /* required security factors */
1378                 } else if ( strcasecmp( cargv[0], "security" ) == 0 ) {
1379                         slap_ssf_set_t *set;
1380
1381                         if ( cargc < 2 ) {
1382 #ifdef NEW_LOGGING
1383                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1384                                            "%s: line %d: missing factor(s) in \"security <factors>\""
1385                                            " line.\n", fname, lineno ));
1386 #else
1387                                 Debug( LDAP_DEBUG_ANY,
1388             "%s: line %d: missing factor(s) in \"security <factors>\" line\n",
1389                                     fname, lineno, 0 );
1390 #endif
1391
1392                                 return( 1 );
1393                         }
1394
1395                         if ( be == NULL ) {
1396                                 set = &global_ssf_set;
1397                         } else {
1398                                 set = &be->be_ssf_set;
1399                         }
1400
1401                         for( i=1; i < cargc; i++ ) {
1402                                 if( strncasecmp( cargv[i], "ssf=",
1403                                         sizeof("ssf") ) == 0 )
1404                                 {
1405                                         set->sss_ssf =
1406                                                 atoi( &cargv[i][sizeof("ssf")] );
1407
1408                                 } else if( strncasecmp( cargv[i], "transport=",
1409                                         sizeof("transport") ) == 0 )
1410                                 {
1411                                         set->sss_transport =
1412                                                 atoi( &cargv[i][sizeof("transport")] );
1413
1414                                 } else if( strncasecmp( cargv[i], "tls=",
1415                                         sizeof("tls") ) == 0 )
1416                                 {
1417                                         set->sss_tls =
1418                                                 atoi( &cargv[i][sizeof("tls")] );
1419
1420                                 } else if( strncasecmp( cargv[i], "sasl=",
1421                                         sizeof("sasl") ) == 0 )
1422                                 {
1423                                         set->sss_sasl =
1424                                                 atoi( &cargv[i][sizeof("sasl")] );
1425
1426                                 } else if( strncasecmp( cargv[i], "update_ssf=",
1427                                         sizeof("update_ssf") ) == 0 )
1428                                 {
1429                                         set->sss_update_ssf =
1430                                                 atoi( &cargv[i][sizeof("update_ssf")] );
1431
1432                                 } else if( strncasecmp( cargv[i], "update_transport=",
1433                                         sizeof("update_transport") ) == 0 )
1434                                 {
1435                                         set->sss_update_transport =
1436                                                 atoi( &cargv[i][sizeof("update_transport")] );
1437
1438                                 } else if( strncasecmp( cargv[i], "update_tls=",
1439                                         sizeof("update_tls") ) == 0 )
1440                                 {
1441                                         set->sss_update_tls =
1442                                                 atoi( &cargv[i][sizeof("update_tls")] );
1443
1444                                 } else if( strncasecmp( cargv[i], "update_sasl=",
1445                                         sizeof("update_sasl") ) == 0 )
1446                                 {
1447                                         set->sss_update_sasl =
1448                                                 atoi( &cargv[i][sizeof("update_sasl")] );
1449
1450                                 } else {
1451 #ifdef NEW_LOGGING
1452                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1453                                                    "%s: line %d: unknown factor %S in "
1454                                                    "\"security <factors>\" line.\n",
1455                                                    fname, lineno, cargv[1] ));
1456 #else
1457                                         Debug( LDAP_DEBUG_ANY,
1458                     "%s: line %d: unknown factor %s in \"security <factors>\" line\n",
1459                                             fname, lineno, cargv[i] );
1460 #endif
1461
1462                                         return( 1 );
1463                                 }
1464                         }
1465                 /* where to send clients when we don't hold it */
1466                 } else if ( strcasecmp( cargv[0], "referral" ) == 0 ) {
1467                         if ( cargc < 2 ) {
1468 #ifdef NEW_LOGGING
1469                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1470                                            "%s: line %d: missing URL in \"referral <URL>\""
1471                                            " line.\n", fname, lineno ));
1472 #else
1473                                 Debug( LDAP_DEBUG_ANY,
1474                     "%s: line %d: missing URL in \"referral <URL>\" line\n",
1475                                     fname, lineno, 0 );
1476 #endif
1477
1478                                 return( 1 );
1479                         }
1480
1481                         if( validate_global_referral( cargv[1] ) ) {
1482 #ifdef NEW_LOGGING
1483                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1484                                         "invalid URL (%s) in \"referral\" line.\n",
1485                                         fname, lineno, cargv[1] ));
1486 #else
1487                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1488                                         "invalid URL (%s) in \"referral\" line.\n",
1489                                     fname, lineno, cargv[1] );
1490 #endif
1491                                 return 1;
1492                         }
1493
1494                         vals[0].bv_val = cargv[1];
1495                         vals[0].bv_len = strlen( vals[0].bv_val );
1496                         value_add( &default_referral, vals );
1497
1498 #ifdef NEW_LOGGING
1499                 } else if ( strcasecmp( cargv[0], "logfile" ) == 0 ) {
1500                         FILE *logfile;
1501                         if ( cargc < 2 ) {
1502 #ifdef NEW_LOGGING
1503                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1504                                            "%s: line %d: Error in logfile directive, "
1505                                            "\"logfile <filename>\"\n", fname, lineno ));
1506 #else
1507                                 Debug( LDAP_DEBUG_ANY,
1508                                        "%s: line %d: Error in logfile directive, \"logfile filename\"\n",
1509                                        fname, lineno, 0 );
1510 #endif
1511
1512                                 return( 1 );
1513                         }
1514                         logfile = fopen( cargv[1], "w" );
1515                         if ( logfile != NULL ) lutil_debug_file( logfile );
1516
1517 #endif
1518                 /* start of a new database definition */
1519                 } else if ( strcasecmp( cargv[0], "debug" ) == 0 ) {
1520                         int level;
1521                         if ( cargc < 3 ) {
1522 #ifdef NEW_LOGGING
1523                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1524                                            "%s: line %d: Error in debug directive, "
1525                                            "\"debug <subsys> <level>\"\n", fname, lineno ));
1526 #else
1527                                 Debug( LDAP_DEBUG_ANY,
1528                                         "%s: line %d: Error in debug directive, \"debug subsys level\"\n",
1529                                         fname, lineno, 0 );
1530 #endif
1531
1532                                 return( 1 );
1533                         }
1534                         level = atoi( cargv[2] );
1535                         if ( level <= 0 ) level = lutil_mnem2level( cargv[2] );
1536                         lutil_set_debug_level( cargv[1], level );
1537                 /* specify an Object Identifier macro */
1538                 } else if ( strcasecmp( cargv[0], "objectidentifier" ) == 0 ) {
1539                         rc = parse_oidm( fname, lineno, cargc, cargv );
1540                         if( rc ) return rc;
1541
1542                 /* specify an objectclass */
1543                 } else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
1544                         if ( *cargv[1] == '(' ) {
1545                                 char * p;
1546                                 p = strchr(saveline,'(');
1547                                 rc = parse_oc( fname, lineno, p, cargv );
1548                                 if( rc ) return rc;
1549
1550                         } else {
1551 #ifdef NEW_LOGGING
1552                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1553                                            "%s: line %d: old objectclass format not supported\n",
1554                                            fname, lineno ));
1555 #else
1556                                 Debug( LDAP_DEBUG_ANY,
1557                                        "%s: line %d: old objectclass format not supported.\n",
1558                                        fname, lineno, 0 );
1559 #endif
1560                         }
1561
1562                 /* specify an attribute type */
1563                 } else if (( strcasecmp( cargv[0], "attributetype" ) == 0 )
1564                         || ( strcasecmp( cargv[0], "attribute" ) == 0 ))
1565                 {
1566                         if ( *cargv[1] == '(' ) {
1567                                 char * p;
1568                                 p = strchr(saveline,'(');
1569                                 rc = parse_at( fname, lineno, p, cargv );
1570                                 if( rc ) return rc;
1571
1572                         } else {
1573 #ifdef NEW_LOGGING
1574                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1575                                            "%s: line %d: old attribute type format not supported.\n",
1576                                            fname, lineno ));
1577 #else
1578                                 Debug( LDAP_DEBUG_ANY,
1579     "%s: line %d: old attribute type format not supported.\n",
1580                                     fname, lineno, 0 );
1581 #endif
1582
1583                         }
1584
1585                 /* turn on/off schema checking */
1586                 } else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {
1587                         if ( cargc < 2 ) {
1588 #ifdef NEW_LOGGING
1589                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1590                                            "%s: line %d: missing on|off in "
1591                                            "\"schemacheck <on|off>\" line.\n",
1592                                            fname, lineno ));
1593 #else
1594                                 Debug( LDAP_DEBUG_ANY,
1595     "%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
1596                                     fname, lineno, 0 );
1597 #endif
1598
1599                                 return( 1 );
1600                         }
1601                         if ( strcasecmp( cargv[1], "off" ) == 0 ) {
1602 #ifdef NEW_LOGGING
1603                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1604                                         "%s: line %d: schema checking disabled! your mileage may vary!\n",
1605                                         fname, lineno ));
1606 #else
1607                                 Debug( LDAP_DEBUG_ANY,
1608                                         "%s: line %d: schema checking disabled! your mileage may vary!\n",
1609                                     fname, lineno, 0 );
1610 #endif
1611                                 global_schemacheck = 0;
1612                         } else {
1613                                 global_schemacheck = 1;
1614                         }
1615
1616                 /* specify access control info */
1617                 } else if ( strcasecmp( cargv[0], "access" ) == 0 ) {
1618                         parse_acl( be, fname, lineno, cargc, cargv );
1619
1620                 /* debug level to log things to syslog */
1621                 } else if ( strcasecmp( cargv[0], "loglevel" ) == 0 ) {
1622                         if ( cargc < 2 ) {
1623 #ifdef NEW_LOGGING
1624                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1625                                            "%s: line %d: missing level in \"loglevel <level>\""
1626                                            " line.\n", fname, lineno ));
1627 #else
1628                                 Debug( LDAP_DEBUG_ANY,
1629                     "%s: line %d: missing level in \"loglevel <level>\" line\n",
1630                                     fname, lineno, 0 );
1631 #endif
1632
1633                                 return( 1 );
1634                         }
1635
1636                         ldap_syslog = 0;
1637
1638                         for( i=1; i < cargc; i++ ) {
1639                                 ldap_syslog += atoi( cargv[1] );
1640                         }
1641
1642                 /* list of replicas of the data in this backend (master only) */
1643                 } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
1644                         if ( cargc < 2 ) {
1645 #ifdef NEW_LOGGING
1646                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1647                                            "%s: line %d: missing host in \"replica "
1648                                            " <host[:port]\" line\n", fname, lineno ));
1649 #else
1650                                 Debug( LDAP_DEBUG_ANY,
1651             "%s: line %d: missing host in \"replica <host[:port]>\" line\n",
1652                                     fname, lineno, 0 );
1653 #endif
1654
1655                                 return( 1 );
1656                         }
1657                         if ( be == NULL ) {
1658 #ifdef NEW_LOGGING
1659                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1660                                            "%s: line %d: replica line must appear inside "
1661                                            "a database definition.\n", fname, lineno ));
1662 #else
1663                                 Debug( LDAP_DEBUG_ANY,
1664 "%s: line %d: replica line must appear inside a database definition\n",
1665                                     fname, lineno, 0 );
1666 #endif
1667                                 return 1;
1668
1669                         } else {
1670                                 int nr = -1;
1671
1672                                 for ( i = 1; i < cargc; i++ ) {
1673                                         if ( strncasecmp( cargv[i], "host=", 5 )
1674                                             == 0 ) {
1675                                                 nr = add_replica_info( be, 
1676                                                         cargv[i] + 5 );
1677                                                 break;
1678                                         }
1679                                 }
1680                                 if ( i == cargc ) {
1681 #ifdef NEW_LOGGING
1682                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1683                                                 "%s: line %d: missing host in \"replica\" line\n",
1684                                                 fname, lineno ));
1685 #else
1686                                         Debug( LDAP_DEBUG_ANY,
1687                     "%s: line %d: missing host in \"replica\" line\n",
1688                                             fname, lineno, 0 );
1689 #endif
1690                                         return 1;
1691
1692                                 } else if ( nr == -1 ) {
1693 #ifdef NEW_LOGGING
1694                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1695                                                    "%s: line %d: unable to add"
1696                                                    " replica \"%s\"\n",
1697                                                    fname, lineno, 
1698                                                    cargv[i] + 5 ));
1699 #else
1700                                         Debug( LDAP_DEBUG_ANY,
1701                 "%s: line %d: unable to add replica \"%s\"\n",
1702                                                 fname, lineno, cargv[i] + 5 );
1703 #endif
1704                                         return 1;
1705                                 } else {
1706                                         for ( i = 1; i < cargc; i++ ) {
1707                                                 if ( strncasecmp( cargv[i], "suffix=", 7 ) == 0 ) {
1708
1709                                                         switch ( add_replica_suffix( be, nr, cargv[i] + 7 ) ) {
1710                                                         case 1:
1711 #ifdef NEW_LOGGING
1712                                                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1713                                                                                 "%s: line %d: suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
1714                                                                                 fname, lineno, cargv[i] + 7 ));
1715 #else
1716                                                                 Debug( LDAP_DEBUG_ANY,
1717                                                                                 "%s: line %d: suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
1718                                                                                 fname, lineno, cargv[i] + 7 );
1719 #endif
1720                                                                 break;
1721
1722                                                         case 2:
1723 #ifdef NEW_LOGGING
1724                                                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1725                                                                                         "%s: line %d: unable to normalize suffix in \"replica\" line (ignored)\n",
1726                                                                                         fname, lineno ));
1727 #else
1728                                                                 Debug( LDAP_DEBUG_ANY,
1729                                                                                  "%s: line %d: unable to normalize suffix in \"replica\" line (ignored)\n",
1730                                                                                  fname, lineno, 0 );
1731 #endif
1732                                                                 break;
1733                                                         }
1734
1735                                                 } else if ( strncasecmp( cargv[i], "attr", 4 ) == 0 ) {
1736                                                         int exclude = 0;
1737                                                         char *arg = cargv[i] + 4;
1738
1739                                                         if ( arg[0] == '!' ) {
1740                                                                 arg++;
1741                                                                 exclude = 1;
1742                                                         }
1743
1744                                                         if ( arg[0] != '=' ) {
1745                                                                 continue;
1746                                                         }
1747
1748                                                         if ( add_replica_attrs( be, nr, arg + 1, exclude ) ) {
1749 #ifdef NEW_LOGGING
1750                                                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1751                                                                                 "%s: line %d: attribute \"%s\" in \"replica\" line is unknown\n",
1752                                                                                 fname, lineno, arg + 1 ));
1753 #else
1754                                                                 Debug( LDAP_DEBUG_ANY,
1755                                                                                 "%s: line %d: attribute \"%s\" in \"replica\" line is unknown\n",
1756                                                                                 fname, lineno, arg + 1 );
1757 #endif
1758                                                                 return( 1 );
1759                                                         }
1760                                                 }
1761                                         }
1762                                 }
1763                         }
1764
1765                 /* dn of master entity allowed to write to replica */
1766                 } else if ( strcasecmp( cargv[0], "updatedn" ) == 0 ) {
1767                         if ( cargc < 2 ) {
1768 #ifdef NEW_LOGGING
1769                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1770                                            "%s: line %d: missing dn in \"updatedn <dn>\""
1771                                            " line.\n", fname, lineno ));
1772 #else
1773                                 Debug( LDAP_DEBUG_ANY,
1774                     "%s: line %d: missing dn in \"updatedn <dn>\" line\n",
1775                                     fname, lineno, 0 );
1776 #endif
1777
1778                                 return( 1 );
1779                         }
1780                         if ( be == NULL ) {
1781 #ifdef NEW_LOGGING
1782                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1783                                            "%s: line %d: updatedn line must appear inside "
1784                                            "a database definition\n",
1785                                            fname, lineno ));
1786 #else
1787                                 Debug( LDAP_DEBUG_ANY,
1788 "%s: line %d: updatedn line must appear inside a database definition\n",
1789                                     fname, lineno, 0 );
1790 #endif
1791                                 return 1;
1792
1793                         } else {
1794                                 struct berval dn;
1795
1796                                 if ( load_ucdata( NULL ) < 0 ) return 1;
1797
1798                                 dn.bv_val = cargv[1];
1799                                 dn.bv_len = strlen( cargv[1] );
1800
1801                                 rc = dnNormalize2( NULL, &dn, &be->be_update_ndn );
1802                                 if( rc != LDAP_SUCCESS ) {
1803 #ifdef NEW_LOGGING
1804                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1805                                                 "%s: line %d: updatedn DN is invalid.\n",
1806                                                 fname, lineno ));
1807 #else
1808                                         Debug( LDAP_DEBUG_ANY,
1809                                                 "%s: line %d: updatedn DN is invalid\n",
1810                                             fname, lineno, 0 );
1811 #endif
1812                                         return 1;
1813                                 }
1814                         }
1815
1816                 } else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
1817                         if ( cargc < 2 ) {
1818 #ifdef NEW_LOGGING
1819                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1820                                         "missing url in \"updateref <ldapurl>\" line.\n",
1821                                         fname, lineno ));
1822 #else
1823                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1824                                         "missing url in \"updateref <ldapurl>\" line\n",
1825                                     fname, lineno, 0 );
1826 #endif
1827
1828                                 return( 1 );
1829                         }
1830                         if ( be == NULL ) {
1831 #ifdef NEW_LOGGING
1832                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: updateref"
1833                                         " line must appear inside a database definition\n",
1834                                         fname, lineno ));
1835 #else
1836                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: updateref"
1837                                         " line must appear inside a database definition\n",
1838                                         fname, lineno, 0 );
1839 #endif
1840                                 return 1;
1841
1842                         } else if ( !be->be_update_ndn.bv_len ) {
1843 #ifdef NEW_LOGGING
1844                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
1845                                         "updateref line must come after updatedn.\n",
1846                                         fname, lineno ));
1847 #else
1848                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1849                                         "updateref line must after updatedn.\n",
1850                                     fname, lineno, 0 );
1851 #endif
1852                                 return 1;
1853                         }
1854
1855                         if( validate_global_referral( cargv[1] ) ) {
1856 #ifdef NEW_LOGGING
1857                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1858                                         "invalid URL (%s) in \"updateref\" line.\n",
1859                                         fname, lineno, cargv[1] ));
1860 #else
1861                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1862                                         "invalid URL (%s) in \"updateref\" line.\n",
1863                                     fname, lineno, cargv[1] );
1864 #endif
1865                                 return 1;
1866                         }
1867
1868                         vals[0].bv_val = cargv[1];
1869                         vals[0].bv_len = strlen( vals[0].bv_val );
1870                         value_add( &be->be_update_refs, vals );
1871
1872                 /* replication log file to which changes are appended */
1873                 } else if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
1874                         if ( cargc < 2 ) {
1875 #ifdef NEW_LOGGING
1876                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1877                                            "%s: line %d: missing filename in \"replogfile <filename>\""
1878                                            " line.\n", fname, lineno ));
1879 #else
1880                                 Debug( LDAP_DEBUG_ANY,
1881             "%s: line %d: missing filename in \"replogfile <filename>\" line\n",
1882                                     fname, lineno, 0 );
1883 #endif
1884
1885                                 return( 1 );
1886                         }
1887                         if ( be ) {
1888                                 be->be_replogfile = ch_strdup( cargv[1] );
1889                         } else {
1890                                 replogfile = ch_strdup( cargv[1] );
1891                         }
1892
1893                 /* file from which to read additional rootdse attrs */
1894                 } else if ( strcasecmp( cargv[0], "rootDSE" ) == 0) {
1895                         if ( cargc < 2 ) {
1896 #ifdef NEW_LOGGING
1897                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1898                                         "missing filename in \"rootDSE <filename>\" line.\n",
1899                                         fname, lineno ));
1900 #else
1901                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1902                                         "missing filename in \"rootDSE <filename>\" line.\n",
1903                                     fname, lineno, 0 );
1904 #endif
1905                                 return 1;
1906                         }
1907
1908                         if( read_root_dse_file( cargv[1] ) ) {
1909 #ifdef NEW_LOGGING
1910                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1911                                         "could not read \"rootDSE <filename>\" line.\n",
1912                                         fname, lineno ));
1913 #else
1914                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1915                                         "could not read \"rootDSE <filename>\" line\n",
1916                                     fname, lineno, 0 );
1917 #endif
1918                                 return 1;
1919                         }
1920
1921                 /* maintain lastmodified{by,time} attributes */
1922                 } else if ( strcasecmp( cargv[0], "lastmod" ) == 0 ) {
1923                         if ( cargc < 2 ) {
1924 #ifdef NEW_LOGGING
1925                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1926                                            "%s: line %d: missing on|off in \"lastmod <on|off>\""
1927                                            " line.\n", fname, lineno ));
1928 #else
1929                                 Debug( LDAP_DEBUG_ANY,
1930             "%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
1931                                     fname, lineno, 0 );
1932 #endif
1933
1934                                 return( 1 );
1935                         }
1936                         if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1937                                 if ( be ) {
1938                                         be->be_flags &= ~SLAP_BFLAG_NOLASTMOD;
1939                                 } else {
1940                                         lastmod = 1;
1941                                 }
1942                         } else {
1943                                 if ( be ) {
1944                                         be->be_flags |= SLAP_BFLAG_NOLASTMOD;
1945                                 } else {
1946                                         lastmod = 0;
1947                                 }
1948                         }
1949
1950 #ifdef SIGHUP
1951                 /* turn on/off gentle SIGHUP handling */
1952                 } else if ( strcasecmp( cargv[0], "gentlehup" ) == 0 ) {
1953                         if ( cargc < 2 ) {
1954                                 Debug( LDAP_DEBUG_ANY,
1955     "%s: line %d: missing on|off in \"gentlehup <on|off>\" line\n",
1956                                     fname, lineno, 0 );
1957                                 return( 1 );
1958                         }
1959                         if ( strcasecmp( cargv[1], "off" ) == 0 ) {
1960                                 global_gentlehup = 0;
1961                         } else {
1962                                 global_gentlehup = 1;
1963                         }
1964 #endif
1965
1966                 /* set idle timeout value */
1967                 } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
1968                         int i;
1969                         if ( cargc < 2 ) {
1970 #ifdef NEW_LOGGING
1971                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1972                                            "%s: line %d: missing timeout value in "
1973                                            "\"idletimeout <seconds>\" line.\n", fname, lineno ));
1974 #else
1975                                 Debug( LDAP_DEBUG_ANY,
1976             "%s: line %d: missing timeout value in \"idletimeout <seconds>\" line\n",
1977                                     fname, lineno, 0 );
1978 #endif
1979
1980                                 return( 1 );
1981                         }
1982
1983                         i = atoi( cargv[1] );
1984
1985                         if( i < 0 ) {
1986 #ifdef NEW_LOGGING
1987                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1988                                            "%s: line %d: timeout value (%d) invalid "
1989                                            "\"idletimeout <seconds>\" line.\n",
1990                                            fname, lineno, i ));
1991 #else
1992                                 Debug( LDAP_DEBUG_ANY,
1993             "%s: line %d: timeout value (%d) invalid \"idletimeout <seconds>\" line\n",
1994                                     fname, lineno, i );
1995 #endif
1996
1997                                 return( 1 );
1998                         }
1999
2000                         global_idletimeout = i;
2001
2002                 /* include another config file */
2003                 } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
2004                         if ( cargc < 2 ) {
2005 #ifdef NEW_LOGGING
2006                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2007                                            "%s: line %d: missing filename in \"include "
2008                                            "<filename>\" line.\n", fname, lineno ));
2009 #else
2010                                 Debug( LDAP_DEBUG_ANY,
2011     "%s: line %d: missing filename in \"include <filename>\" line\n",
2012                                     fname, lineno, 0 );
2013 #endif
2014
2015                                 return( 1 );
2016                         }
2017                         savefname = ch_strdup( cargv[1] );
2018                         savelineno = lineno;
2019
2020                         if ( read_config( savefname ) != 0 ) {
2021                                 return( 1 );
2022                         }
2023
2024                         free( savefname );
2025                         lineno = savelineno - 1;
2026
2027                 /* location of kerberos srvtab file */
2028                 } else if ( strcasecmp( cargv[0], "srvtab" ) == 0 ) {
2029                         if ( cargc < 2 ) {
2030 #ifdef NEW_LOGGING
2031                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2032                                            "%s: line %d: missing filename in \"srvtab "
2033                                            "<filename>\" line.\n", fname, lineno ));
2034 #else
2035                                 Debug( LDAP_DEBUG_ANY,
2036             "%s: line %d: missing filename in \"srvtab <filename>\" line\n",
2037                                     fname, lineno, 0 );
2038 #endif
2039
2040                                 return( 1 );
2041                         }
2042                         ldap_srvtab = ch_strdup( cargv[1] );
2043
2044 #ifdef SLAPD_MODULES
2045                 } else if (strcasecmp( cargv[0], "moduleload") == 0 ) {
2046                    if ( cargc < 2 ) {
2047 #ifdef NEW_LOGGING
2048                            LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2049                                       "%s: line %d: missing filename in \"moduleload "
2050                                       "<filename>\" line.\n", fname, lineno ));
2051 #else
2052                       Debug( LDAP_DEBUG_ANY,
2053                              "%s: line %d: missing filename in \"moduleload <filename>\" line\n",
2054                              fname, lineno, 0 );
2055 #endif
2056
2057                       exit( EXIT_FAILURE );
2058                    }
2059                    if (module_load(cargv[1], cargc - 2, (cargc > 2) ? cargv + 2 : NULL)) {
2060 #ifdef NEW_LOGGING
2061                            LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2062                                       "%s: line %d: failed to load or initialize module %s\n",
2063                                       fname, lineno, cargv[1] ));
2064 #else
2065                       Debug( LDAP_DEBUG_ANY,
2066                              "%s: line %d: failed to load or initialize module %s\n",
2067                              fname, lineno, cargv[1]);
2068 #endif
2069
2070                       exit( EXIT_FAILURE );
2071                    }
2072                 } else if (strcasecmp( cargv[0], "modulepath") == 0 ) {
2073                    if ( cargc != 2 ) {
2074 #ifdef NEW_LOGGING
2075                            LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2076                                       "%s: line %d: missing path in \"modulepath <path>\""
2077                                       " line\n", fname, lineno ));
2078 #else
2079                       Debug( LDAP_DEBUG_ANY,
2080                              "%s: line %d: missing path in \"modulepath <path>\" line\n",
2081                              fname, lineno, 0 );
2082 #endif
2083
2084                       exit( EXIT_FAILURE );
2085                    }
2086                    if (module_path( cargv[1] )) {
2087 #ifdef NEW_LOGGING
2088                            LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2089                                       "%s: line %d: failed to set module search path to %s.\n",
2090                                       fname, lineno, cargv[1] ));
2091 #else
2092                            Debug( LDAP_DEBUG_ANY,
2093                                   "%s: line %d: failed to set module search path to %s\n",
2094                                   fname, lineno, cargv[1]);
2095 #endif
2096
2097                       exit( EXIT_FAILURE );
2098                    }
2099                    
2100 #endif /*SLAPD_MODULES*/
2101
2102 #ifdef HAVE_TLS
2103                 } else if ( !strcasecmp( cargv[0], "TLSRandFile" ) ) {
2104                         rc = ldap_pvt_tls_set_option( NULL,
2105                                                       LDAP_OPT_X_TLS_RANDOM_FILE,
2106                                                       cargv[1] );
2107                         if ( rc )
2108                                 return rc;
2109
2110                 } else if ( !strcasecmp( cargv[0], "TLSCipherSuite" ) ) {
2111                         rc = ldap_pvt_tls_set_option( NULL,
2112                                                       LDAP_OPT_X_TLS_CIPHER_SUITE,
2113                                                       cargv[1] );
2114                         if ( rc )
2115                                 return rc;
2116
2117                 } else if ( !strcasecmp( cargv[0], "TLSCertificateFile" ) ) {
2118                         rc = ldap_pvt_tls_set_option( NULL,
2119                                                       LDAP_OPT_X_TLS_CERTFILE,
2120                                                       cargv[1] );
2121                         if ( rc )
2122                                 return rc;
2123
2124                 } else if ( !strcasecmp( cargv[0], "TLSCertificateKeyFile" ) ) {
2125                         rc = ldap_pvt_tls_set_option( NULL,
2126                                                       LDAP_OPT_X_TLS_KEYFILE,
2127                                                       cargv[1] );
2128                         if ( rc )
2129                                 return rc;
2130
2131                 } else if ( !strcasecmp( cargv[0], "TLSCACertificatePath" ) ) {
2132                         rc = ldap_pvt_tls_set_option( NULL,
2133                                                       LDAP_OPT_X_TLS_CACERTDIR,
2134                                                       cargv[1] );
2135                         if ( rc )
2136                                 return rc;
2137
2138                 } else if ( !strcasecmp( cargv[0], "TLSCACertificateFile" ) ) {
2139                         rc = ldap_pvt_tls_set_option( NULL,
2140                                                       LDAP_OPT_X_TLS_CACERTFILE,
2141                                                       cargv[1] );
2142                         if ( rc )
2143                                 return rc;
2144                 } else if ( !strcasecmp( cargv[0], "TLSVerifyClient" ) ) {
2145                         if ( isdigit( (unsigned char) cargv[1][0] ) ) {
2146                                 i = atoi(cargv[1]);
2147                                 rc = ldap_pvt_tls_set_option( NULL,
2148                                                       LDAP_OPT_X_TLS_REQUIRE_CERT,
2149                                                       &i );
2150                         } else {
2151                                 rc = ldap_int_tls_config( NULL,
2152                                                       LDAP_OPT_X_TLS_REQUIRE_CERT,
2153                                                       cargv[1] );
2154                         }
2155
2156                         if ( rc )
2157                                 return rc;
2158
2159 #endif
2160
2161                 } else if ( !strcasecmp( cargv[0], "reverse-lookup" ) ) {
2162 #ifdef SLAPD_RLOOKUPS
2163                         if ( cargc < 2 ) {
2164 #ifdef NEW_LOGGING
2165                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2166                                            "%s: line %d: reverse-lookup: "
2167                                            "missing \"on\" or \"off\"\n",
2168                                            fname, lineno ));
2169 #else
2170                                 Debug( LDAP_DEBUG_ANY,
2171 "%s: line %d: reverse-lookup: missing \"on\" or \"off\"\n",
2172                                         fname, lineno, 0 );
2173 #endif
2174                                 return( 1 );
2175                         }
2176
2177                         if ( !strcasecmp( cargv[1], "on" ) ) {
2178                                 use_reverse_lookup = 1;
2179                         } else if ( !strcasecmp( cargv[1], "off" ) ) {
2180                                 use_reverse_lookup = 0;
2181                         } else {
2182 #ifdef NEW_LOGGING
2183                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2184                                            "%s: line %d: reverse-lookup: "
2185                                            "must be \"on\" (default) "
2186                                            "or \"off\"\n",
2187                                            fname, lineno ));
2188 #else
2189                                 Debug( LDAP_DEBUG_ANY,
2190 "%s: line %d: reverse-lookup: must be \"on\" (default) or \"off\"\n",
2191                                         fname, lineno, 0 );
2192 #endif
2193                                 return( 1 );
2194                         }
2195
2196 #else /* !SLAPD_RLOOKUPS */
2197 #ifdef NEW_LOGGING
2198                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2199                                    "%s: line %d: reverse lookups "
2200                                    "are not configured (ignored).\n",
2201                                    fname, lineno ));
2202 #else
2203                         Debug( LDAP_DEBUG_ANY,
2204 "%s: line %d: reverse lookups are not configured (ignored).\n",
2205                                 fname, lineno, 0 );
2206 #endif
2207 #endif /* !SLAPD_RLOOKUPS */
2208
2209                 /* pass anything else to the current backend info/db config routine */
2210                 } else {
2211                         if ( bi != NULL ) {
2212                                 if ( bi->bi_config == 0 ) {
2213 #ifdef NEW_LOGGING
2214                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2215                                                    "%s: line %d: unknown directive \"%s\" inside "
2216                                                    "backend info definition (ignored).\n",
2217                                                    fname, lineno, cargv[0] ));
2218 #else
2219                                         Debug( LDAP_DEBUG_ANY,
2220 "%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
2221                                                 fname, lineno, cargv[0] );
2222 #endif
2223
2224                                 } else {
2225                                         if ( (*bi->bi_config)( bi, fname, lineno, cargc, cargv )
2226                                                 != 0 )
2227                                         {
2228                                                 return( 1 );
2229                                         }
2230                                 }
2231                         } else if ( be != NULL ) {
2232                                 if ( be->be_config == 0 ) {
2233 #ifdef NEW_LOGGING
2234                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2235                                                    "%s: line %d: uknown directive \"%s\" inside "
2236                                                    "backend database definition (ignored).\n",
2237                                                    fname, lineno, cargv[0] ));
2238 #else
2239                                         Debug( LDAP_DEBUG_ANY,
2240 "%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
2241                                         fname, lineno, cargv[0] );
2242 #endif
2243
2244                                 } else {
2245                                         if ( (*be->be_config)( be, fname, lineno, cargc, cargv )
2246                                                 != 0 )
2247                                         {
2248                                                 return( 1 );
2249                                         }
2250                                 }
2251                         } else {
2252 #ifdef NEW_LOGGING
2253                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2254                                            "%s: line %d: unknown directive \"%s\" outside backend "
2255                                            "info and database definitions (ignored).\n",
2256                                            fname, lineno, cargv[0] ));
2257 #else
2258                                 Debug( LDAP_DEBUG_ANY,
2259 "%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
2260                                     fname, lineno, cargv[0] );
2261 #endif
2262
2263                         }
2264                 }
2265                 free( saveline );
2266         }
2267         fclose( fp );
2268
2269         if ( load_ucdata( NULL ) < 0 ) return 1;
2270         return( 0 );
2271 }
2272
2273 static int
2274 fp_parse_line(
2275     int         lineno,
2276     char        *line
2277 )
2278 {
2279         char *  token;
2280         char *  logline;
2281         char    logbuf[sizeof("pseudorootpw ***")];
2282
2283         cargc = 0;
2284         token = strtok_quote( line, " \t" );
2285
2286         logline = line;
2287         if ( token &&
2288              (strcasecmp( token, "rootpw" ) == 0 ||
2289               strcasecmp( token, "replica" ) == 0 || /* contains "credentials" */
2290               strcasecmp( token, "bindpw" ) == 0 ||       /* used in back-ldap */
2291               strcasecmp( token, "pseudorootpw" ) == 0 || /* used in back-meta */
2292                   strcasecmp( token, "dbpasswd" ) == 0 ) )    /* used in back-sql */
2293                 sprintf( logline = logbuf, "%s ***", token );
2294         if ( strtok_quote_ptr )
2295                 *strtok_quote_ptr = ' ';
2296 #ifdef NEW_LOGGING
2297         LDAP_LOG(( "config", LDAP_LEVEL_DETAIL1,
2298                    "line %d (%s)\n", lineno, logline ));
2299 #else
2300         Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, logline, 0 );
2301 #endif
2302         if ( strtok_quote_ptr )
2303                 *strtok_quote_ptr = '\0';
2304
2305         for ( ; token != NULL; token = strtok_quote( NULL, " \t" ) ) {
2306                 if ( cargc == cargv_size - 1 ) {
2307                         char **tmp;
2308                         tmp = ch_realloc( cargv, (cargv_size + ARGS_STEP) *
2309                                             sizeof(*cargv) );
2310                         if ( tmp == NULL ) {
2311 #ifdef NEW_LOGGING
2312                                 LDAP_LOG(( "config", LDAP_LEVEL_ERR,
2313                                            "line %d: out of memory\n", 
2314                                            lineno ));
2315 #else
2316                                 Debug( LDAP_DEBUG_ANY, 
2317                                                 "line %d: out of memory\n", 
2318                                                 lineno, 0, 0 );
2319 #endif
2320                                 return -1;
2321                         }
2322                         cargv = tmp;
2323                         cargv_size += ARGS_STEP;
2324                 }
2325                 cargv[cargc++] = token;
2326         }
2327         cargv[cargc] = NULL;
2328         return 0;
2329 }
2330
2331 static char *
2332 strtok_quote( char *line, char *sep )
2333 {
2334         int             inquote;
2335         char            *tmp;
2336         static char     *next;
2337
2338         strtok_quote_ptr = NULL;
2339         if ( line != NULL ) {
2340                 next = line;
2341         }
2342         while ( *next && strchr( sep, *next ) ) {
2343                 next++;
2344         }
2345
2346         if ( *next == '\0' ) {
2347                 next = NULL;
2348                 return( NULL );
2349         }
2350         tmp = next;
2351
2352         for ( inquote = 0; *next; ) {
2353                 switch ( *next ) {
2354                 case '"':
2355                         if ( inquote ) {
2356                                 inquote = 0;
2357                         } else {
2358                                 inquote = 1;
2359                         }
2360                         AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
2361                         break;
2362
2363                 case '\\':
2364                         if ( next[1] )
2365                                 AC_MEMCPY( next,
2366                                             next + 1, strlen( next + 1 ) + 1 );
2367                         next++;         /* dont parse the escaped character */
2368                         break;
2369
2370                 default:
2371                         if ( ! inquote ) {
2372                                 if ( strchr( sep, *next ) != NULL ) {
2373                                         strtok_quote_ptr = next;
2374                                         *next++ = '\0';
2375                                         return( tmp );
2376                                 }
2377                         }
2378                         next++;
2379                         break;
2380                 }
2381         }
2382
2383         return( tmp );
2384 }
2385
2386 static char     buf[BUFSIZ];
2387 static char     *line;
2388 static int      lmax, lcur;
2389
2390 #define CATLINE( buf )  { \
2391         int     len; \
2392         len = strlen( buf ); \
2393         while ( lcur + len + 1 > lmax ) { \
2394                 lmax += BUFSIZ; \
2395                 line = (char *) ch_realloc( line, lmax ); \
2396         } \
2397         strcpy( line + lcur, buf ); \
2398         lcur += len; \
2399 }
2400
2401 static char *
2402 fp_getline( FILE *fp, int *lineno )
2403 {
2404         char            *p;
2405
2406         lcur = 0;
2407         CATLINE( buf );
2408         (*lineno)++;
2409
2410         /* hack attack - keeps us from having to keep a stack of bufs... */
2411         if ( strncasecmp( line, "include", 7 ) == 0 ) {
2412                 buf[0] = '\0';
2413                 return( line );
2414         }
2415
2416         while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
2417                 /* trim off \r\n or \n */
2418                 if ( (p = strchr( buf, '\n' )) != NULL ) {
2419                         if( p > buf && p[-1] == '\r' ) --p;
2420                         *p = '\0';
2421                 }
2422                 
2423                 /* trim off trailing \ and append the next line */
2424                 if ( line[ 0 ] != '\0' 
2425                                 && (p = line + strlen( line ) - 1)[ 0 ] == '\\'
2426                                 && p[ -1 ] != '\\' ) {
2427                         p[ 0 ] = '\0';
2428                         lcur--;
2429
2430                 } else {
2431                         if ( ! isspace( (unsigned char) buf[0] ) ) {
2432                                 return( line );
2433                         }
2434
2435                         /* change leading whitespace to a space */
2436                         buf[0] = ' ';
2437                 }
2438
2439                 CATLINE( buf );
2440                 (*lineno)++;
2441         }
2442         buf[0] = '\0';
2443
2444         return( line[0] ? line : NULL );
2445 }
2446
2447 static void
2448 fp_getline_init( int *lineno )
2449 {
2450         *lineno = -1;
2451         buf[0] = '\0';
2452 }
2453
2454 /* Loads ucdata, returns 1 if loading, 0 if already loaded, -1 on error */
2455 static int
2456 load_ucdata( char *path )
2457 {
2458         static int loaded = 0;
2459         int err;
2460         
2461         if ( loaded ) {
2462                 return( 0 );
2463         }
2464         err = ucdata_load( path ? path : SLAPD_DEFAULT_UCDATA, UCDATA_ALL );
2465         if ( err ) {
2466 #ifdef NEW_LOGGING
2467                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2468                            "load_ucdata: Error %d loading ucdata.\n", err ));
2469 #else
2470                 Debug( LDAP_DEBUG_ANY, "error loading ucdata (error %d)\n",
2471                        err, 0, 0 );
2472 #endif
2473
2474                 return( -1 );
2475         }
2476         loaded = 1;
2477         return( 1 );
2478 }
2479
2480 void
2481 config_destroy( )
2482 {
2483         ucdata_unload( UCDATA_ALL );
2484         free( line );
2485         if ( slapd_args_file )
2486                 free ( slapd_args_file );
2487         if ( slapd_pid_file )
2488                 free ( slapd_pid_file );
2489         acl_destroy( global_acl, NULL );
2490 }