1 /* $NetBSD: slapcommon.c,v 1.1.1.3 2010/12/12 15:22:48 adam Exp $ */ 2 3 /* slapcommon.c - common routine for the slap tools */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/slapcommon.c,v 1.73.2.20 2010/04/14 22:59:10 quanah Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2010 The OpenLDAP Foundation. 8 * Portions Copyright 1998-2003 Kurt D. Zeilenga. 9 * Portions Copyright 2003 IBM Corporation. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted only as authorized by the OpenLDAP 14 * Public License. 15 * 16 * A copy of this license is available in file LICENSE in the 17 * top-level directory of the distribution or, alternatively, at 18 * <http://www.OpenLDAP.org/license.html>. 19 */ 20 /* ACKNOWLEDGEMENTS: 21 * This work was initially developed by Kurt Zeilenga for inclusion 22 * in OpenLDAP Software. Additional signficant contributors include 23 * Jong Hyuk Choi 24 * Hallvard B. Furuseth 25 * Howard Chu 26 * Pierangelo Masarati 27 */ 28 29 #include "portable.h" 30 31 #include <stdio.h> 32 33 #include <ac/stdlib.h> 34 #include <ac/ctype.h> 35 #include <ac/string.h> 36 #include <ac/socket.h> 37 #include <ac/unistd.h> 38 39 #include "slapcommon.h" 40 #include "lutil.h" 41 #include "ldif.h" 42 43 tool_vars tool_globals; 44 45 #ifdef CSRIMALLOC 46 static char *leakfilename; 47 static FILE *leakfile; 48 #endif 49 50 static LDIFFP dummy; 51 52 #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) 53 int start_syslog; 54 static char **syslog_unknowns; 55 #ifdef LOG_LOCAL4 56 static int syslogUser = SLAP_DEFAULT_SYSLOG_USER; 57 #endif /* LOG_LOCAL4 */ 58 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 59 60 static void 61 usage( int tool, const char *progname ) 62 { 63 char *options = NULL; 64 fprintf( stderr, 65 "usage: %s [-v] [-d debuglevel] [-f configfile] [-F configdir] [-o <name>[=<value>]]", 66 progname ); 67 68 switch( tool ) { 69 case SLAPACL: 70 options = "\n\t[-U authcID | -D authcDN] [-X authzID | -o authzDN=<DN>]" 71 "\n\t-b DN [-u] [attr[/access][:value]] [...]\n"; 72 break; 73 74 case SLAPADD: 75 options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]\n" 76 "\t[-l ldiffile] [-j linenumber] [-q] [-u] [-s] [-w]\n"; 77 break; 78 79 case SLAPAUTH: 80 options = "\n\t[-U authcID] [-X authzID] [-R realm] [-M mech] ID [...]\n"; 81 break; 82 83 case SLAPCAT: 84 options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" 85 " [-l ldiffile] [-a filter] [-s subtree] [-H url]\n"; 86 break; 87 88 case SLAPDN: 89 options = "\n\t[-N | -P] DN [...]\n"; 90 break; 91 92 case SLAPINDEX: 93 options = " [-c]\n\t[-g] [-n databasenumber | -b suffix] [attr ...] [-q] [-t]\n"; 94 break; 95 96 case SLAPTEST: 97 options = " [-n databasenumber] [-u]\n"; 98 break; 99 100 case SLAPSCHEMA: 101 options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" 102 " [-l errorfile] [-a filter] [-s subtree] [-H url]\n"; 103 break; 104 } 105 106 if ( options != NULL ) { 107 fputs( options, stderr ); 108 } 109 exit( EXIT_FAILURE ); 110 } 111 112 static int 113 parse_slapopt( void ) 114 { 115 size_t len = 0; 116 char *p; 117 118 p = strchr( optarg, '=' ); 119 if ( p != NULL ) { 120 len = p - optarg; 121 p++; 122 } 123 124 if ( strncasecmp( optarg, "sockurl", len ) == 0 ) { 125 if ( !BER_BVISNULL( &listener_url ) ) { 126 ber_memfree( listener_url.bv_val ); 127 } 128 ber_str2bv( p, 0, 1, &listener_url ); 129 130 } else if ( strncasecmp( optarg, "domain", len ) == 0 ) { 131 if ( !BER_BVISNULL( &peer_domain ) ) { 132 ber_memfree( peer_domain.bv_val ); 133 } 134 ber_str2bv( p, 0, 1, &peer_domain ); 135 136 } else if ( strncasecmp( optarg, "peername", len ) == 0 ) { 137 if ( !BER_BVISNULL( &peer_name ) ) { 138 ber_memfree( peer_name.bv_val ); 139 } 140 ber_str2bv( p, 0, 1, &peer_name ); 141 142 } else if ( strncasecmp( optarg, "sockname", len ) == 0 ) { 143 if ( !BER_BVISNULL( &sock_name ) ) { 144 ber_memfree( sock_name.bv_val ); 145 } 146 ber_str2bv( p, 0, 1, &sock_name ); 147 148 } else if ( strncasecmp( optarg, "ssf", len ) == 0 ) { 149 if ( lutil_atou( &ssf, p ) ) { 150 Debug( LDAP_DEBUG_ANY, "unable to parse ssf=\"%s\".\n", p, 0, 0 ); 151 return -1; 152 } 153 154 } else if ( strncasecmp( optarg, "transport_ssf", len ) == 0 ) { 155 if ( lutil_atou( &transport_ssf, p ) ) { 156 Debug( LDAP_DEBUG_ANY, "unable to parse transport_ssf=\"%s\".\n", p, 0, 0 ); 157 return -1; 158 } 159 160 } else if ( strncasecmp( optarg, "tls_ssf", len ) == 0 ) { 161 if ( lutil_atou( &tls_ssf, p ) ) { 162 Debug( LDAP_DEBUG_ANY, "unable to parse tls_ssf=\"%s\".\n", p, 0, 0 ); 163 return -1; 164 } 165 166 } else if ( strncasecmp( optarg, "sasl_ssf", len ) == 0 ) { 167 if ( lutil_atou( &sasl_ssf, p ) ) { 168 Debug( LDAP_DEBUG_ANY, "unable to parse sasl_ssf=\"%s\".\n", p, 0, 0 ); 169 return -1; 170 } 171 172 } else if ( strncasecmp( optarg, "authzDN", len ) == 0 ) { 173 ber_str2bv( p, 0, 1, &authzDN ); 174 175 #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) 176 } else if ( strncasecmp( optarg, "syslog", len ) == 0 ) { 177 if ( parse_debug_level( p, &ldap_syslog, &syslog_unknowns ) ) { 178 return -1; 179 } 180 start_syslog = 1; 181 182 } else if ( strncasecmp( optarg, "syslog-level", len ) == 0 ) { 183 if ( parse_syslog_level( p, &ldap_syslog_level ) ) { 184 return -1; 185 } 186 start_syslog = 1; 187 188 #ifdef LOG_LOCAL4 189 } else if ( strncasecmp( optarg, "syslog-user", len ) == 0 ) { 190 if ( parse_syslog_user( p, &syslogUser ) ) { 191 return -1; 192 } 193 start_syslog = 1; 194 #endif /* LOG_LOCAL4 */ 195 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 196 197 } else { 198 return -1; 199 } 200 201 return 0; 202 } 203 204 /* 205 * slap_tool_init - initialize slap utility, handle program options. 206 * arguments: 207 * name program name 208 * tool tool code 209 * argc, argv command line arguments 210 */ 211 212 static int need_shutdown; 213 214 void 215 slap_tool_init( 216 const char* progname, 217 int tool, 218 int argc, char **argv ) 219 { 220 char *options; 221 char *conffile = NULL; 222 char *confdir = NULL; 223 struct berval base = BER_BVNULL; 224 char *filterstr = NULL; 225 char *subtree = NULL; 226 char *ldiffile = NULL; 227 char **debug_unknowns = NULL; 228 int rc, i; 229 int mode = SLAP_TOOL_MODE; 230 int truncatemode = 0; 231 int use_glue = 1; 232 int writer; 233 234 #ifdef LDAP_DEBUG 235 /* tools default to "none", so that at least LDAP_DEBUG_ANY 236 * messages show up; use -d 0 to reset */ 237 slap_debug = LDAP_DEBUG_NONE; 238 ldif_debug = slap_debug; 239 #endif 240 ldap_syslog = 0; 241 242 #ifdef CSRIMALLOC 243 leakfilename = malloc( strlen( progname ) + STRLENOF( ".leak" ) + 1 ); 244 sprintf( leakfilename, "%s.leak", progname ); 245 if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) { 246 leakfile = stderr; 247 } 248 free( leakfilename ); 249 leakfilename = NULL; 250 #endif 251 252 scope = LDAP_SCOPE_DEFAULT; 253 254 switch( tool ) { 255 case SLAPADD: 256 options = "b:cd:f:F:gj:l:n:o:qsS:uvw"; 257 break; 258 259 case SLAPCAT: 260 options = "a:b:cd:f:F:gH:l:n:o:s:v"; 261 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; 262 break; 263 264 case SLAPDN: 265 options = "d:f:F:No:Pv"; 266 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; 267 break; 268 269 case SLAPSCHEMA: 270 options = "a:b:cd:f:F:gH:l:n:o:s:v"; 271 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; 272 break; 273 274 case SLAPTEST: 275 options = "d:f:F:n:o:Quv"; 276 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; 277 break; 278 279 case SLAPAUTH: 280 options = "d:f:F:M:o:R:U:vX:"; 281 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; 282 break; 283 284 case SLAPINDEX: 285 options = "b:cd:f:F:gn:o:qtv"; 286 mode |= SLAP_TOOL_READMAIN; 287 break; 288 289 case SLAPACL: 290 options = "b:D:d:f:F:o:uU:vX:"; 291 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; 292 break; 293 294 default: 295 fprintf( stderr, "%s: unknown tool mode (%d)\n", progname, tool ); 296 exit( EXIT_FAILURE ); 297 } 298 299 dbnum = -1; 300 while ( (i = getopt( argc, argv, options )) != EOF ) { 301 switch ( i ) { 302 case 'a': 303 filterstr = ch_strdup( optarg ); 304 break; 305 306 case 'b': 307 ber_str2bv( optarg, 0, 1, &base ); 308 break; 309 310 case 'c': /* enable continue mode */ 311 continuemode++; 312 break; 313 314 case 'd': { /* turn on debugging */ 315 int level = 0; 316 317 if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) { 318 usage( tool, progname ); 319 } 320 #ifdef LDAP_DEBUG 321 if ( level == 0 ) { 322 /* allow to reset log level */ 323 slap_debug = 0; 324 325 } else { 326 slap_debug |= level; 327 } 328 #else 329 if ( level != 0 ) 330 fputs( "must compile with LDAP_DEBUG for debugging\n", 331 stderr ); 332 #endif 333 } break; 334 335 case 'D': 336 ber_str2bv( optarg, 0, 1, &authcDN ); 337 break; 338 339 case 'f': /* specify a conf file */ 340 conffile = ch_strdup( optarg ); 341 break; 342 343 case 'F': /* specify a conf dir */ 344 confdir = ch_strdup( optarg ); 345 break; 346 347 case 'g': /* disable subordinate glue */ 348 use_glue = 0; 349 break; 350 351 case 'H': { 352 LDAPURLDesc *ludp; 353 int rc; 354 355 rc = ldap_url_parse_ext( optarg, &ludp, 356 LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_NOEMPTY_DN ); 357 if ( rc != LDAP_URL_SUCCESS ) { 358 usage( tool, progname ); 359 } 360 361 /* don't accept host, port, attrs, extensions */ 362 if ( ldap_pvt_url_scheme2proto( ludp->lud_scheme ) != LDAP_PROTO_TCP ) { 363 usage( tool, progname ); 364 } 365 366 if ( ludp->lud_host != NULL ) { 367 usage( tool, progname ); 368 } 369 370 if ( ludp->lud_port != 0 ) { 371 usage( tool, progname ); 372 } 373 374 if ( ludp->lud_attrs != NULL ) { 375 usage( tool, progname ); 376 } 377 378 if ( ludp->lud_exts != NULL ) { 379 usage( tool, progname ); 380 } 381 382 if ( ludp->lud_dn != NULL && ludp->lud_dn[0] != '\0' ) { 383 subtree = ludp->lud_dn; 384 ludp->lud_dn = NULL; 385 } 386 387 if ( ludp->lud_filter != NULL && ludp->lud_filter[0] != '\0' ) { 388 filterstr = ludp->lud_filter; 389 ludp->lud_filter = NULL; 390 } 391 392 scope = ludp->lud_scope; 393 394 ldap_free_urldesc( ludp ); 395 } break; 396 397 case 'j': /* jump to linenumber */ 398 if ( lutil_atoi( &jumpline, optarg ) ) { 399 usage( tool, progname ); 400 } 401 break; 402 403 case 'l': /* LDIF file */ 404 ldiffile = ch_strdup( optarg ); 405 break; 406 407 case 'M': 408 ber_str2bv( optarg, 0, 0, &mech ); 409 break; 410 411 case 'N': 412 if ( dn_mode && dn_mode != SLAP_TOOL_LDAPDN_NORMAL ) { 413 usage( tool, progname ); 414 } 415 dn_mode = SLAP_TOOL_LDAPDN_NORMAL; 416 break; 417 418 case 'n': /* which config file db to index */ 419 if ( lutil_atoi( &dbnum, optarg ) || dbnum < 0 ) { 420 usage( tool, progname ); 421 } 422 break; 423 424 case 'o': 425 if ( parse_slapopt() ) { 426 usage( tool, progname ); 427 } 428 break; 429 430 case 'P': 431 if ( dn_mode && dn_mode != SLAP_TOOL_LDAPDN_PRETTY ) { 432 usage( tool, progname ); 433 } 434 dn_mode = SLAP_TOOL_LDAPDN_PRETTY; 435 break; 436 437 case 'Q': 438 quiet++; 439 slap_debug = 0; 440 break; 441 442 case 'q': /* turn on quick */ 443 mode |= SLAP_TOOL_QUICK; 444 break; 445 446 case 'R': 447 realm = optarg; 448 break; 449 450 case 'S': 451 if ( lutil_atou( &csnsid, optarg ) 452 || csnsid > SLAP_SYNC_SID_MAX ) 453 { 454 usage( tool, progname ); 455 } 456 break; 457 458 case 's': /* dump subtree */ 459 if ( tool == SLAPADD ) 460 mode |= SLAP_TOOL_NO_SCHEMA_CHECK; 461 else if ( tool == SLAPCAT || tool == SLAPSCHEMA ) 462 subtree = ch_strdup( optarg ); 463 break; 464 465 case 't': /* turn on truncate */ 466 truncatemode++; 467 mode |= SLAP_TRUNCATE_MODE; 468 break; 469 470 case 'U': 471 ber_str2bv( optarg, 0, 0, &authcID ); 472 break; 473 474 case 'u': /* dry run */ 475 dryrun++; 476 break; 477 478 case 'v': /* turn on verbose */ 479 verbose++; 480 break; 481 482 case 'w': /* write context csn at the end */ 483 update_ctxcsn++; 484 break; 485 486 case 'X': 487 ber_str2bv( optarg, 0, 0, &authzID ); 488 break; 489 490 default: 491 usage( tool, progname ); 492 break; 493 } 494 } 495 496 #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) 497 if ( start_syslog ) { 498 char *logName; 499 #ifdef HAVE_EBCDIC 500 logName = ch_strdup( progname ); 501 __atoe( logName ); 502 #else 503 logName = (char *)progname; 504 #endif 505 506 #ifdef LOG_LOCAL4 507 openlog( logName, OPENLOG_OPTIONS, syslogUser ); 508 #elif defined LOG_DEBUG 509 openlog( logName, OPENLOG_OPTIONS ); 510 #endif 511 #ifdef HAVE_EBCDIC 512 free( logName ); 513 logName = NULL; 514 #endif 515 } 516 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 517 518 switch ( tool ) { 519 case SLAPCAT: 520 case SLAPSCHEMA: 521 writer = 1; 522 break; 523 524 default: 525 writer = 0; 526 break; 527 } 528 529 switch ( tool ) { 530 case SLAPADD: 531 case SLAPCAT: 532 case SLAPSCHEMA: 533 if ( ( argc != optind ) || (dbnum >= 0 && base.bv_val != NULL ) ) { 534 usage( tool, progname ); 535 } 536 537 break; 538 539 case SLAPINDEX: 540 if ( dbnum >= 0 && base.bv_val != NULL ) { 541 usage( tool, progname ); 542 } 543 544 break; 545 546 case SLAPDN: 547 if ( argc == optind ) { 548 usage( tool, progname ); 549 } 550 break; 551 552 case SLAPAUTH: 553 if ( argc == optind && BER_BVISNULL( &authcID ) ) { 554 usage( tool, progname ); 555 } 556 break; 557 558 case SLAPTEST: 559 if ( argc != optind ) { 560 usage( tool, progname ); 561 } 562 break; 563 564 case SLAPACL: 565 if ( !BER_BVISNULL( &authcDN ) && !BER_BVISNULL( &authcID ) ) { 566 usage( tool, progname ); 567 } 568 if ( BER_BVISNULL( &base ) ) { 569 usage( tool, progname ); 570 } 571 ber_dupbv( &baseDN, &base ); 572 break; 573 574 default: 575 break; 576 } 577 578 if ( ldiffile == NULL ) { 579 dummy.fp = writer ? stdout : stdin; 580 ldiffp = &dummy; 581 582 } else if ((ldiffp = ldif_open( ldiffile, writer ? "w" : "r" )) 583 == NULL ) 584 { 585 perror( ldiffile ); 586 exit( EXIT_FAILURE ); 587 } 588 589 /* 590 * initialize stuff and figure out which backend we're dealing with 591 */ 592 593 rc = slap_init( mode, progname ); 594 if ( rc != 0 ) { 595 fprintf( stderr, "%s: slap_init failed!\n", progname ); 596 exit( EXIT_FAILURE ); 597 } 598 599 rc = read_config( conffile, confdir ); 600 601 if ( rc != 0 ) { 602 fprintf( stderr, "%s: bad configuration %s!\n", 603 progname, confdir ? "directory" : "file" ); 604 exit( EXIT_FAILURE ); 605 } 606 607 if ( debug_unknowns ) { 608 rc = parse_debug_unknowns( debug_unknowns, &slap_debug ); 609 ldap_charray_free( debug_unknowns ); 610 debug_unknowns = NULL; 611 if ( rc ) 612 exit( EXIT_FAILURE ); 613 } 614 615 #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) 616 if ( syslog_unknowns ) { 617 rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog ); 618 ldap_charray_free( syslog_unknowns ); 619 syslog_unknowns = NULL; 620 if ( rc ) 621 exit( EXIT_FAILURE ); 622 } 623 #endif 624 625 at_oc_cache = 1; 626 627 switch ( tool ) { 628 case SLAPADD: 629 case SLAPCAT: 630 case SLAPINDEX: 631 case SLAPSCHEMA: 632 if ( !nbackends ) { 633 fprintf( stderr, "No databases found " 634 "in config file\n" ); 635 exit( EXIT_FAILURE ); 636 } 637 break; 638 639 default: 640 break; 641 } 642 643 if ( use_glue ) { 644 rc = glue_sub_attach( 0 ); 645 646 if ( rc != 0 ) { 647 fprintf( stderr, 648 "%s: subordinate configuration error\n", progname ); 649 exit( EXIT_FAILURE ); 650 } 651 } 652 653 rc = slap_schema_check(); 654 655 if ( rc != 0 ) { 656 fprintf( stderr, "%s: slap_schema_prep failed!\n", progname ); 657 exit( EXIT_FAILURE ); 658 } 659 660 switch ( tool ) { 661 case SLAPTEST: 662 if ( dbnum >= 0 ) 663 goto get_db; 664 /* FALLTHRU */ 665 case SLAPDN: 666 case SLAPAUTH: 667 be = NULL; 668 goto startup; 669 670 default: 671 break; 672 } 673 674 if( filterstr ) { 675 filter = str2filter( filterstr ); 676 677 if( filter == NULL ) { 678 fprintf( stderr, "Invalid filter '%s'\n", filterstr ); 679 exit( EXIT_FAILURE ); 680 } 681 682 ch_free( filterstr ); 683 filterstr = NULL; 684 } 685 686 if( subtree ) { 687 struct berval val; 688 ber_str2bv( subtree, 0, 0, &val ); 689 rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL ); 690 if( rc != LDAP_SUCCESS ) { 691 fprintf( stderr, "Invalid subtree DN '%s'\n", subtree ); 692 exit( EXIT_FAILURE ); 693 } 694 695 if ( BER_BVISNULL( &base ) && dbnum == -1 ) { 696 base = val; 697 } else { 698 free( subtree ); 699 subtree = NULL; 700 } 701 } 702 703 if( base.bv_val != NULL ) { 704 struct berval nbase; 705 706 rc = dnNormalize( 0, NULL, NULL, &base, &nbase, NULL ); 707 if( rc != LDAP_SUCCESS ) { 708 fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n", 709 progname, base.bv_val ); 710 exit( EXIT_FAILURE ); 711 } 712 713 be = select_backend( &nbase, 0 ); 714 ber_memfree( nbase.bv_val ); 715 BER_BVZERO( &nbase ); 716 717 switch ( tool ) { 718 case SLAPACL: 719 goto startup; 720 721 default: 722 break; 723 } 724 725 if( be == NULL ) { 726 fprintf( stderr, "%s: slap_init no backend for \"%s\"\n", 727 progname, base.bv_val ); 728 exit( EXIT_FAILURE ); 729 } 730 /* If the named base is a glue master, operate on the 731 * entire context 732 */ 733 if ( SLAP_GLUE_INSTANCE( be ) ) { 734 nosubordinates = 1; 735 } 736 737 ch_free( base.bv_val ); 738 BER_BVZERO( &base ); 739 740 } else if ( dbnum == -1 ) { 741 /* no suffix and no dbnum specified, just default to 742 * the first available database 743 */ 744 if ( nbackends <= 0 ) { 745 fprintf( stderr, "No available databases\n" ); 746 exit( EXIT_FAILURE ); 747 } 748 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 749 dbnum++; 750 751 /* db #0 is cn=config, don't select it as a default */ 752 if ( dbnum < 1 ) continue; 753 754 if ( SLAP_MONITOR(be)) 755 continue; 756 757 /* If just doing the first by default and it is a 758 * glue subordinate, find the master. 759 */ 760 if ( SLAP_GLUE_SUBORDINATE(be) ) { 761 nosubordinates = 1; 762 continue; 763 } 764 break; 765 } 766 767 if ( !be ) { 768 fprintf( stderr, "Available database(s) " 769 "do not allow %s\n", progname ); 770 exit( EXIT_FAILURE ); 771 } 772 773 if ( nosubordinates == 0 && dbnum > 1 ) { 774 Debug( LDAP_DEBUG_ANY, 775 "The first database does not allow %s;" 776 " using the first available one (%d)\n", 777 progname, dbnum, 0 ); 778 } 779 780 } else if ( dbnum >= nbackends ) { 781 fprintf( stderr, 782 "Database number selected via -n is out of range\n" 783 "Must be in the range 0 to %d" 784 " (the number of configured databases)\n", 785 nbackends - 1 ); 786 exit( EXIT_FAILURE ); 787 788 } else { 789 get_db: 790 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 791 if ( dbnum == 0 ) break; 792 dbnum--; 793 } 794 } 795 796 if ( scope != LDAP_SCOPE_DEFAULT && BER_BVISNULL( &sub_ndn ) ) { 797 if ( be && be->be_nsuffix ) { 798 ber_dupbv( &sub_ndn, be->be_nsuffix ); 799 800 } else { 801 fprintf( stderr, 802 "<scope> needs a DN or a valid database\n" ); 803 exit( EXIT_FAILURE ); 804 } 805 } 806 807 startup:; 808 if ( be ) { 809 BackendDB *bdtmp; 810 811 dbnum = 0; 812 LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) { 813 if ( bdtmp == be ) break; 814 dbnum++; 815 } 816 } 817 818 #ifdef CSRIMALLOC 819 mal_leaktrace(1); 820 #endif 821 822 if ( conffile != NULL ) { 823 ch_free( conffile ); 824 conffile = NULL; 825 } 826 827 if ( confdir != NULL ) { 828 ch_free( confdir ); 829 confdir = NULL; 830 } 831 832 if ( ldiffile != NULL ) { 833 ch_free( ldiffile ); 834 ldiffile = NULL; 835 } 836 837 /* slapdn doesn't specify a backend to startup */ 838 if ( !dryrun && tool != SLAPDN ) { 839 need_shutdown = 1; 840 841 if ( slap_startup( be ) ) { 842 switch ( tool ) { 843 case SLAPTEST: 844 fprintf( stderr, "slap_startup failed " 845 "(test would succeed using " 846 "the -u switch)\n" ); 847 break; 848 849 default: 850 fprintf( stderr, "slap_startup failed\n" ); 851 break; 852 } 853 854 exit( EXIT_FAILURE ); 855 } 856 } 857 } 858 859 int slap_tool_destroy( void ) 860 { 861 int rc = 0; 862 if ( !dryrun ) { 863 if ( need_shutdown ) { 864 if ( slap_shutdown( be )) 865 rc = EXIT_FAILURE; 866 } 867 if ( slap_destroy()) 868 rc = EXIT_FAILURE; 869 } 870 #ifdef SLAPD_MODULES 871 if ( slapMode == SLAP_SERVER_MODE ) { 872 /* always false. just pulls in necessary symbol references. */ 873 lutil_uuidstr(NULL, 0); 874 } 875 module_kill(); 876 #endif 877 schema_destroy(); 878 #ifdef HAVE_TLS 879 ldap_pvt_tls_destroy(); 880 #endif 881 config_destroy(); 882 883 #ifdef CSRIMALLOC 884 mal_dumpleaktrace( leakfile ); 885 #endif 886 887 if ( !BER_BVISNULL( &authcDN ) ) { 888 ch_free( authcDN.bv_val ); 889 BER_BVZERO( &authcDN ); 890 } 891 892 if ( ldiffp && ldiffp != &dummy ) { 893 ldif_close( ldiffp ); 894 } 895 return rc; 896 } 897 898 899