1 /* $OpenLDAP: pkg/ldap/tests/progs/slapd-tester.c,v 1.46.2.8 2008/02/11 23:26:50 kurt Exp $ */ 2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1999-2008 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15 /* ACKNOWLEDGEMENTS: 16 * This work was initially developed by Kurt Spanier for inclusion 17 * in OpenLDAP Software. 18 */ 19 20 #include "portable.h" 21 22 #include <stdio.h> 23 24 #include "ac/stdlib.h" 25 26 #include "ac/ctype.h" 27 #include "ac/dirent.h" 28 #include "ac/param.h" 29 #include "ac/socket.h" 30 #include "ac/string.h" 31 #include "ac/unistd.h" 32 #include "ac/wait.h" 33 34 35 #include "ldap_defaults.h" 36 #include "lutil.h" 37 38 #include "ldap.h" 39 #include "ldap_pvt.h" 40 #include "lber_pvt.h" 41 #include "slapd-common.h" 42 43 #define SEARCHCMD "slapd-search" 44 #define READCMD "slapd-read" 45 #define ADDCMD "slapd-addel" 46 #define MODRDNCMD "slapd-modrdn" 47 #define MODIFYCMD "slapd-modify" 48 #define BINDCMD "slapd-bind" 49 #define MAXARGS 100 50 #define MAXREQS 5000 51 #define LOOPS 100 52 #define OUTERLOOPS "1" 53 #define RETRIES "0" 54 55 #define TSEARCHFILE "do_search.0" 56 #define TREADFILE "do_read.0" 57 #define TADDFILE "do_add." 58 #define TMODRDNFILE "do_modrdn.0" 59 #define TMODIFYFILE "do_modify.0" 60 #define TBINDFILE "do_bind.0" 61 62 static char *get_file_name( char *dirname, char *filename ); 63 static int get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] ); 64 static int get_read_entries( char *filename, char *entries[], char *filters[] ); 65 static void fork_child( char *prog, char **args ); 66 static void wait4kids( int nkidval ); 67 68 static int maxkids = 20; 69 static int nkids; 70 71 #ifdef HAVE_WINSOCK 72 static HANDLE *children; 73 static char argbuf[BUFSIZ]; 74 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\"")) 75 #else 76 #define ArgDup(x) strdup(x) 77 #endif 78 79 static void 80 usage( char *name, char opt ) 81 { 82 if ( opt ) { 83 fprintf( stderr, "%s: unable to handle option \'%c\'\n\n", 84 name, opt ); 85 } 86 87 fprintf( stderr, 88 "usage: %s " 89 "-H <uri> | ([-h <host>] -p <port>) " 90 "-D <manager> " 91 "-w <passwd> " 92 "-d <datadir> " 93 "[-i <ignore>] " 94 "[-j <maxchild>] " 95 "[-l {<loops>|<type>=<loops>[,...]}] " 96 "[-L <outerloops>] " 97 "-P <progdir> " 98 "[-r <maxretries>] " 99 "[-t <delay>] " 100 "[-C] " 101 "[-F] " 102 "[-I] " 103 "[-N]\n", 104 name ); 105 exit( EXIT_FAILURE ); 106 } 107 108 int 109 main( int argc, char **argv ) 110 { 111 int i, j; 112 char *uri = NULL; 113 char *host = "localhost"; 114 char *port = NULL; 115 char *manager = NULL; 116 char *passwd = NULL; 117 char *dirname = NULL; 118 char *progdir = NULL; 119 int loops = LOOPS; 120 char *outerloops = OUTERLOOPS; 121 char *retries = RETRIES; 122 char *delay = "0"; 123 DIR *datadir; 124 struct dirent *file; 125 int friendly = 0; 126 int chaserefs = 0; 127 int noattrs = 0; 128 int nobind = 0; 129 int noinit = 1; 130 char *ignore = NULL; 131 /* search */ 132 char *sfile = NULL; 133 char *sreqs[MAXREQS]; 134 char *sattrs[MAXREQS]; 135 char *sbase[MAXREQS]; 136 LDAPURLDesc *slud[MAXREQS]; 137 int snum = 0; 138 char *sargs[MAXARGS]; 139 int sanum; 140 int sextra_args = 0; 141 char scmd[MAXPATHLEN]; 142 /* static so that its address can be used in initializer below. */ 143 static char sloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 144 /* read */ 145 char *rfile = NULL; 146 char *rreqs[MAXREQS]; 147 int rnum = 0; 148 char *rargs[MAXARGS]; 149 char *rflts[MAXREQS]; 150 int ranum; 151 int rextra_args = 0; 152 char rcmd[MAXPATHLEN]; 153 static char rloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 154 /* addel */ 155 char *afiles[MAXREQS]; 156 int anum = 0; 157 char *aargs[MAXARGS]; 158 int aanum; 159 char acmd[MAXPATHLEN]; 160 static char aloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 161 /* modrdn */ 162 char *nfile = NULL; 163 char *nreqs[MAXREQS]; 164 int nnum = 0; 165 char *nargs[MAXARGS]; 166 int nanum; 167 char ncmd[MAXPATHLEN]; 168 static char nloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 169 /* modify */ 170 char *mfile = NULL; 171 char *mreqs[MAXREQS]; 172 char *mdn[MAXREQS]; 173 int mnum = 0; 174 char *margs[MAXARGS]; 175 int manum; 176 char mcmd[MAXPATHLEN]; 177 static char mloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 178 /* bind */ 179 char *bfile = NULL; 180 char *breqs[MAXREQS]; 181 char *bcreds[MAXREQS]; 182 char *battrs[MAXREQS]; 183 int bnum = 0; 184 char *bargs[MAXARGS]; 185 int banum; 186 char bcmd[MAXPATHLEN]; 187 static char bloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 188 char **bargs_extra = NULL; 189 190 char *friendlyOpt = NULL; 191 int pw_ask = 0; 192 char *pw_file = NULL; 193 194 /* extra action to do after bind... */ 195 typedef struct extra_t { 196 char *action; 197 struct extra_t *next; 198 } extra_t; 199 200 extra_t *extra = NULL; 201 int nextra = 0; 202 203 tester_init( "slapd-tester", TESTER_TESTER ); 204 205 sloops[0] = '\0'; 206 rloops[0] = '\0'; 207 aloops[0] = '\0'; 208 nloops[0] = '\0'; 209 mloops[0] = '\0'; 210 bloops[0] = '\0'; 211 212 while ( ( i = getopt( argc, argv, "AB:CD:d:FH:h:Ii:j:L:l:NP:p:r:t:Ww:y:" ) ) != EOF ) 213 { 214 switch ( i ) { 215 case 'A': 216 noattrs++; 217 break; 218 219 case 'B': { 220 char **p, 221 **b = ldap_str2charray( optarg, "," ); 222 extra_t **epp; 223 224 for ( epp = &extra; *epp; epp = &(*epp)->next ) 225 ; 226 227 for ( p = b; p[0]; p++ ) { 228 *epp = calloc( 1, sizeof( extra_t ) ); 229 (*epp)->action = p[0]; 230 epp = &(*epp)->next; 231 nextra++; 232 } 233 234 ldap_memfree( b ); 235 } break; 236 237 case 'C': 238 chaserefs++; 239 break; 240 241 case 'D': /* slapd manager */ 242 manager = ArgDup( optarg ); 243 break; 244 245 case 'd': /* data directory */ 246 dirname = strdup( optarg ); 247 break; 248 249 case 'F': 250 friendly++; 251 break; 252 253 case 'H': /* slapd uri */ 254 uri = strdup( optarg ); 255 break; 256 257 case 'h': /* slapd host */ 258 host = strdup( optarg ); 259 break; 260 261 case 'I': 262 noinit = 0; 263 break; 264 265 case 'i': 266 ignore = optarg; 267 break; 268 269 case 'j': /* the number of parallel clients */ 270 if ( lutil_atoi( &maxkids, optarg ) != 0 ) { 271 usage( argv[0], 'j' ); 272 } 273 break; 274 275 case 'l': /* the number of loops per client */ 276 if ( !isdigit( (unsigned char) optarg[0] ) ) { 277 char **p, 278 **l = ldap_str2charray( optarg, "," ); 279 280 for ( p = l; p[0]; p++) { 281 struct { 282 struct berval type; 283 char *buf; 284 } types[] = { 285 { BER_BVC( "add=" ), aloops }, 286 { BER_BVC( "bind=" ), bloops }, 287 { BER_BVC( "modify=" ), mloops }, 288 { BER_BVC( "modrdn=" ), nloops }, 289 { BER_BVC( "read=" ), rloops }, 290 { BER_BVC( "search=" ), sloops }, 291 { BER_BVNULL, NULL } 292 }; 293 int c, n; 294 295 for ( c = 0; types[c].type.bv_val; c++ ) { 296 if ( strncasecmp( p[0], types[c].type.bv_val, types[c].type.bv_len ) == 0 ) { 297 break; 298 } 299 } 300 301 if ( types[c].type.bv_val == NULL ) { 302 usage( argv[0], 'l' ); 303 } 304 305 if ( lutil_atoi( &n, &p[0][types[c].type.bv_len] ) != 0 ) { 306 usage( argv[0], 'l' ); 307 } 308 309 snprintf( types[c].buf, sizeof( aloops ), "%d", n ); 310 } 311 312 ldap_charray_free( l ); 313 314 } else if ( lutil_atoi( &loops, optarg ) != 0 ) { 315 usage( argv[0], 'l' ); 316 } 317 break; 318 319 case 'L': /* the number of outerloops per client */ 320 outerloops = strdup( optarg ); 321 break; 322 323 case 'N': 324 nobind++; 325 break; 326 327 case 'P': /* prog directory */ 328 progdir = strdup( optarg ); 329 break; 330 331 case 'p': /* the servers port number */ 332 port = strdup( optarg ); 333 break; 334 335 case 'r': /* the number of retries in case of error */ 336 retries = strdup( optarg ); 337 break; 338 339 case 't': /* the delay in seconds between each retry */ 340 delay = strdup( optarg ); 341 break; 342 343 case 'w': /* the managers passwd */ 344 passwd = ArgDup( optarg ); 345 memset( optarg, '*', strlen( optarg ) ); 346 break; 347 348 case 'W': 349 pw_ask++; 350 break; 351 352 case 'y': 353 pw_file = optarg; 354 break; 355 356 default: 357 usage( argv[0], '\0' ); 358 break; 359 } 360 } 361 362 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) || 363 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL )) 364 { 365 usage( argv[0], '\0' ); 366 } 367 368 #ifdef HAVE_WINSOCK 369 children = malloc( maxkids * sizeof(HANDLE) ); 370 #endif 371 /* get the file list */ 372 if ( ( datadir = opendir( dirname )) == NULL ) { 373 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n", 374 argv[0], dirname ); 375 exit( EXIT_FAILURE ); 376 } 377 378 /* look for search, read, modrdn, and add/delete files */ 379 for ( file = readdir( datadir ); file; file = readdir( datadir )) { 380 381 if ( !strcasecmp( file->d_name, TSEARCHFILE )) { 382 sfile = get_file_name( dirname, file->d_name ); 383 continue; 384 } else if ( !strcasecmp( file->d_name, TREADFILE )) { 385 rfile = get_file_name( dirname, file->d_name ); 386 continue; 387 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) { 388 nfile = get_file_name( dirname, file->d_name ); 389 continue; 390 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) { 391 mfile = get_file_name( dirname, file->d_name ); 392 continue; 393 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE )) 394 && ( anum < MAXREQS )) { 395 afiles[anum++] = get_file_name( dirname, file->d_name ); 396 continue; 397 } else if ( !strcasecmp( file->d_name, TBINDFILE )) { 398 bfile = get_file_name( dirname, file->d_name ); 399 continue; 400 } 401 } 402 403 closedir( datadir ); 404 405 if ( pw_ask ) { 406 passwd = getpassphrase( _("Enter LDAP Password: ") ); 407 408 } else if ( pw_file ) { 409 struct berval pw; 410 411 if ( lutil_get_filed_password( pw_file, &pw ) ) { 412 exit( EXIT_FAILURE ); 413 } 414 415 passwd = pw.bv_val; 416 } 417 418 if ( !sfile && !rfile && !nfile && !mfile && !bfile && !anum ) { 419 fprintf( stderr, "no data files found.\n" ); 420 exit( EXIT_FAILURE ); 421 } 422 423 /* look for search requests */ 424 if ( sfile ) { 425 snum = get_search_filters( sfile, sreqs, sattrs, sbase, slud ); 426 if ( snum < 0 ) { 427 fprintf( stderr, 428 "unable to parse file \"%s\" line %d\n", 429 sfile, -2*(snum + 1)); 430 exit( EXIT_FAILURE ); 431 } 432 } 433 434 /* look for read requests */ 435 if ( rfile ) { 436 rnum = get_read_entries( rfile, rreqs, rflts ); 437 if ( rnum < 0 ) { 438 fprintf( stderr, 439 "unable to parse file \"%s\" line %d\n", 440 rfile, -2*(rnum + 1) ); 441 exit( EXIT_FAILURE ); 442 } 443 } 444 445 /* look for modrdn requests */ 446 if ( nfile ) { 447 nnum = get_read_entries( nfile, nreqs, NULL ); 448 if ( nnum < 0 ) { 449 fprintf( stderr, 450 "unable to parse file \"%s\" line %d\n", 451 nfile, -2*(nnum + 1) ); 452 exit( EXIT_FAILURE ); 453 } 454 } 455 456 /* look for modify requests */ 457 if ( mfile ) { 458 mnum = get_search_filters( mfile, mreqs, NULL, mdn, NULL ); 459 if ( mnum < 0 ) { 460 fprintf( stderr, 461 "unable to parse file \"%s\" line %d\n", 462 mfile, -2*(mnum + 1) ); 463 exit( EXIT_FAILURE ); 464 } 465 } 466 467 /* look for bind requests */ 468 if ( bfile ) { 469 bnum = get_search_filters( bfile, bcreds, battrs, breqs, NULL ); 470 if ( bnum < 0 ) { 471 fprintf( stderr, 472 "unable to parse file \"%s\" line %d\n", 473 bfile, -2*(bnum + 1) ); 474 exit( EXIT_FAILURE ); 475 } 476 } 477 478 /* setup friendly option */ 479 480 switch ( friendly ) { 481 case 0: 482 break; 483 484 case 1: 485 friendlyOpt = "-F"; 486 break; 487 488 default: 489 /* NOTE: right now we don't need it more than twice */ 490 case 2: 491 friendlyOpt = "-FF"; 492 break; 493 } 494 495 if ( sloops[0] == '\0' ) snprintf( sloops, sizeof( sloops ), "%d", 10 * loops ); 496 if ( rloops[0] == '\0' ) snprintf( rloops, sizeof( rloops ), "%d", 20 * loops ); 497 if ( aloops[0] == '\0' ) snprintf( aloops, sizeof( aloops ), "%d", loops ); 498 if ( nloops[0] == '\0' ) snprintf( nloops, sizeof( nloops ), "%d", loops ); 499 if ( mloops[0] == '\0' ) snprintf( mloops, sizeof( mloops ), "%d", loops ); 500 if ( bloops[0] == '\0' ) snprintf( bloops, sizeof( bloops ), "%d", 20 * loops ); 501 502 /* 503 * generate the search clients 504 */ 505 506 sanum = 0; 507 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD, 508 progdir ); 509 sargs[sanum++] = scmd; 510 if ( uri ) { 511 sargs[sanum++] = "-H"; 512 sargs[sanum++] = uri; 513 } else { 514 sargs[sanum++] = "-h"; 515 sargs[sanum++] = host; 516 sargs[sanum++] = "-p"; 517 sargs[sanum++] = port; 518 } 519 sargs[sanum++] = "-D"; 520 sargs[sanum++] = manager; 521 sargs[sanum++] = "-w"; 522 sargs[sanum++] = passwd; 523 sargs[sanum++] = "-l"; 524 sargs[sanum++] = sloops; 525 sargs[sanum++] = "-L"; 526 sargs[sanum++] = outerloops; 527 sargs[sanum++] = "-r"; 528 sargs[sanum++] = retries; 529 sargs[sanum++] = "-t"; 530 sargs[sanum++] = delay; 531 if ( friendly ) { 532 sargs[sanum++] = friendlyOpt; 533 } 534 if ( chaserefs ) { 535 sargs[sanum++] = "-C"; 536 } 537 if ( noattrs ) { 538 sargs[sanum++] = "-A"; 539 } 540 if ( nobind ) { 541 sargs[sanum++] = "-N"; 542 } 543 if ( ignore ) { 544 sargs[sanum++] = "-i"; 545 sargs[sanum++] = ignore; 546 } 547 sargs[sanum++] = "-b"; 548 sargs[sanum++] = NULL; /* will hold the search base */ 549 sargs[sanum++] = "-s"; 550 sargs[sanum++] = NULL; /* will hold the search scope */ 551 sargs[sanum++] = "-f"; 552 sargs[sanum++] = NULL; /* will hold the search request */ 553 554 sargs[sanum++] = NULL; 555 sargs[sanum++] = NULL; /* might hold the "attr" request */ 556 sextra_args += 2; 557 558 sargs[sanum] = NULL; 559 560 /* 561 * generate the read clients 562 */ 563 564 ranum = 0; 565 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD, 566 progdir ); 567 rargs[ranum++] = rcmd; 568 if ( uri ) { 569 rargs[ranum++] = "-H"; 570 rargs[ranum++] = uri; 571 } else { 572 rargs[ranum++] = "-h"; 573 rargs[ranum++] = host; 574 rargs[ranum++] = "-p"; 575 rargs[ranum++] = port; 576 } 577 rargs[ranum++] = "-D"; 578 rargs[ranum++] = manager; 579 rargs[ranum++] = "-w"; 580 rargs[ranum++] = passwd; 581 rargs[ranum++] = "-l"; 582 rargs[ranum++] = rloops; 583 rargs[ranum++] = "-L"; 584 rargs[ranum++] = outerloops; 585 rargs[ranum++] = "-r"; 586 rargs[ranum++] = retries; 587 rargs[ranum++] = "-t"; 588 rargs[ranum++] = delay; 589 if ( friendly ) { 590 rargs[ranum++] = friendlyOpt; 591 } 592 if ( chaserefs ) { 593 rargs[ranum++] = "-C"; 594 } 595 if ( noattrs ) { 596 rargs[ranum++] = "-A"; 597 } 598 if ( ignore ) { 599 rargs[ranum++] = "-i"; 600 rargs[ranum++] = ignore; 601 } 602 rargs[ranum++] = "-e"; 603 rargs[ranum++] = NULL; /* will hold the read entry */ 604 605 rargs[ranum++] = NULL; 606 rargs[ranum++] = NULL; /* might hold the filter arg */ 607 rextra_args += 2; 608 609 rargs[ranum] = NULL; 610 611 /* 612 * generate the modrdn clients 613 */ 614 615 nanum = 0; 616 snprintf( ncmd, sizeof ncmd, "%s" LDAP_DIRSEP MODRDNCMD, 617 progdir ); 618 nargs[nanum++] = ncmd; 619 if ( uri ) { 620 nargs[nanum++] = "-H"; 621 nargs[nanum++] = uri; 622 } else { 623 nargs[nanum++] = "-h"; 624 nargs[nanum++] = host; 625 nargs[nanum++] = "-p"; 626 nargs[nanum++] = port; 627 } 628 nargs[nanum++] = "-D"; 629 nargs[nanum++] = manager; 630 nargs[nanum++] = "-w"; 631 nargs[nanum++] = passwd; 632 nargs[nanum++] = "-l"; 633 nargs[nanum++] = nloops; 634 nargs[nanum++] = "-L"; 635 nargs[nanum++] = outerloops; 636 nargs[nanum++] = "-r"; 637 nargs[nanum++] = retries; 638 nargs[nanum++] = "-t"; 639 nargs[nanum++] = delay; 640 if ( friendly ) { 641 nargs[nanum++] = friendlyOpt; 642 } 643 if ( chaserefs ) { 644 nargs[nanum++] = "-C"; 645 } 646 if ( ignore ) { 647 nargs[nanum++] = "-i"; 648 nargs[nanum++] = ignore; 649 } 650 nargs[nanum++] = "-e"; 651 nargs[nanum++] = NULL; /* will hold the modrdn entry */ 652 nargs[nanum] = NULL; 653 654 /* 655 * generate the modify clients 656 */ 657 658 manum = 0; 659 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODIFYCMD, 660 progdir ); 661 margs[manum++] = mcmd; 662 if ( uri ) { 663 margs[manum++] = "-H"; 664 margs[manum++] = uri; 665 } else { 666 margs[manum++] = "-h"; 667 margs[manum++] = host; 668 margs[manum++] = "-p"; 669 margs[manum++] = port; 670 } 671 margs[manum++] = "-D"; 672 margs[manum++] = manager; 673 margs[manum++] = "-w"; 674 margs[manum++] = passwd; 675 margs[manum++] = "-l"; 676 margs[manum++] = mloops; 677 margs[manum++] = "-L"; 678 margs[manum++] = outerloops; 679 margs[manum++] = "-r"; 680 margs[manum++] = retries; 681 margs[manum++] = "-t"; 682 margs[manum++] = delay; 683 if ( friendly ) { 684 margs[manum++] = friendlyOpt; 685 } 686 if ( chaserefs ) { 687 margs[manum++] = "-C"; 688 } 689 if ( ignore ) { 690 margs[manum++] = "-i"; 691 margs[manum++] = ignore; 692 } 693 margs[manum++] = "-e"; 694 margs[manum++] = NULL; /* will hold the modify entry */ 695 margs[manum++] = "-a";; 696 margs[manum++] = NULL; /* will hold the ava */ 697 margs[manum] = NULL; 698 699 /* 700 * generate the add/delete clients 701 */ 702 703 aanum = 0; 704 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD, 705 progdir ); 706 aargs[aanum++] = acmd; 707 if ( uri ) { 708 aargs[aanum++] = "-H"; 709 aargs[aanum++] = uri; 710 } else { 711 aargs[aanum++] = "-h"; 712 aargs[aanum++] = host; 713 aargs[aanum++] = "-p"; 714 aargs[aanum++] = port; 715 } 716 aargs[aanum++] = "-D"; 717 aargs[aanum++] = manager; 718 aargs[aanum++] = "-w"; 719 aargs[aanum++] = passwd; 720 aargs[aanum++] = "-l"; 721 aargs[aanum++] = aloops; 722 aargs[aanum++] = "-L"; 723 aargs[aanum++] = outerloops; 724 aargs[aanum++] = "-r"; 725 aargs[aanum++] = retries; 726 aargs[aanum++] = "-t"; 727 aargs[aanum++] = delay; 728 if ( friendly ) { 729 aargs[aanum++] = friendlyOpt; 730 } 731 if ( chaserefs ) { 732 aargs[aanum++] = "-C"; 733 } 734 if ( ignore ) { 735 aargs[aanum++] = "-i"; 736 aargs[aanum++] = ignore; 737 } 738 aargs[aanum++] = "-f"; 739 aargs[aanum++] = NULL; /* will hold the add data file */ 740 aargs[aanum] = NULL; 741 742 /* 743 * generate the bind clients 744 */ 745 746 banum = 0; 747 snprintf( bcmd, sizeof bcmd, "%s" LDAP_DIRSEP BINDCMD, 748 progdir ); 749 bargs[banum++] = bcmd; 750 if ( !noinit ) { 751 bargs[banum++] = "-I"; /* init on each bind */ 752 } 753 if ( uri ) { 754 bargs[banum++] = "-H"; 755 bargs[banum++] = uri; 756 } else { 757 bargs[banum++] = "-h"; 758 bargs[banum++] = host; 759 bargs[banum++] = "-p"; 760 bargs[banum++] = port; 761 } 762 bargs[banum++] = "-l"; 763 bargs[banum++] = bloops; 764 bargs[banum++] = "-L"; 765 bargs[banum++] = outerloops; 766 #if 0 767 bargs[banum++] = "-r"; 768 bargs[banum++] = retries; 769 bargs[banum++] = "-t"; 770 bargs[banum++] = delay; 771 #endif 772 if ( friendly ) { 773 bargs[banum++] = friendlyOpt; 774 } 775 if ( chaserefs ) { 776 bargs[banum++] = "-C"; 777 } 778 if ( ignore ) { 779 bargs[banum++] = "-i"; 780 bargs[banum++] = ignore; 781 } 782 if ( nextra ) { 783 bargs[banum++] = "-B"; 784 bargs_extra = &bargs[banum++]; 785 } 786 bargs[banum++] = "-D"; 787 bargs[banum++] = NULL; 788 bargs[banum++] = "-w"; 789 bargs[banum++] = NULL; 790 bargs[banum] = NULL; 791 792 #define DOREQ(n,j) ((n) && ((maxkids > (n)) ? ((j) < maxkids ) : ((j) < (n)))) 793 794 for ( j = 0; j < MAXREQS; j++ ) { 795 /* search */ 796 if ( DOREQ( snum, j ) ) { 797 int jj = j % snum; 798 int x = sanum - sextra_args; 799 800 /* base */ 801 if ( sbase[jj] != NULL ) { 802 sargs[sanum - 7] = sbase[jj]; 803 804 } else { 805 sargs[sanum - 7] = slud[jj]->lud_dn; 806 } 807 808 /* scope */ 809 if ( slud[jj] != NULL ) { 810 sargs[sanum - 5] = (char *)ldap_pvt_scope2str( slud[jj]->lud_scope ); 811 812 } else { 813 sargs[sanum - 5] = "sub"; 814 } 815 816 /* filter */ 817 if ( sreqs[jj] != NULL ) { 818 sargs[sanum - 3] = sreqs[jj]; 819 820 } else if ( slud[jj]->lud_filter != NULL ) { 821 sargs[sanum - 3] = slud[jj]->lud_filter; 822 823 } else { 824 sargs[sanum - 3] = "(objectClass=*)"; 825 } 826 827 /* extras */ 828 sargs[x] = NULL; 829 830 /* attr */ 831 if ( sattrs[jj] != NULL ) { 832 sargs[x++] = "-a"; 833 sargs[x++] = sattrs[jj]; 834 } 835 836 /* attrs */ 837 if ( slud[jj] != NULL && slud[jj]->lud_attrs != NULL ) { 838 int i; 839 840 for ( i = 0; slud[jj]->lud_attrs[ i ] != NULL && x + i < MAXARGS - 1; i++ ) { 841 sargs[x + i] = slud[jj]->lud_attrs[ i ]; 842 } 843 sargs[x + i] = NULL; 844 } 845 846 fork_child( scmd, sargs ); 847 } 848 849 /* read */ 850 if ( DOREQ( rnum, j ) ) { 851 int jj = j % rnum; 852 int x = ranum - rextra_args; 853 854 rargs[ranum - 3] = rreqs[jj]; 855 if ( rflts[jj] != NULL ) { 856 rargs[x++] = "-f"; 857 rargs[x++] = rflts[jj]; 858 } 859 rargs[x] = NULL; 860 fork_child( rcmd, rargs ); 861 } 862 863 /* rename */ 864 if ( j < nnum ) { 865 nargs[nanum - 1] = nreqs[j]; 866 fork_child( ncmd, nargs ); 867 } 868 869 /* modify */ 870 if ( j < mnum ) { 871 margs[manum - 3] = mdn[j]; 872 margs[manum - 1] = mreqs[j]; 873 fork_child( mcmd, margs ); 874 } 875 876 /* add/delete */ 877 if ( j < anum ) { 878 aargs[aanum - 1] = afiles[j]; 879 fork_child( acmd, aargs ); 880 } 881 882 /* bind */ 883 if ( DOREQ( bnum, j ) ) { 884 int jj = j % bnum; 885 886 if ( nextra ) { 887 int n = ((double)nextra)*rand()/(RAND_MAX + 1.0); 888 extra_t *e; 889 890 for ( e = extra; n-- > 0; e = e->next ) 891 ; 892 *bargs_extra = e->action; 893 } 894 895 if ( battrs[jj] != NULL ) { 896 bargs[banum - 3] = manager ? manager : ""; 897 bargs[banum - 1] = passwd ? passwd : ""; 898 899 bargs[banum + 0] = "-b"; 900 bargs[banum + 1] = breqs[jj]; 901 bargs[banum + 2] = "-f"; 902 bargs[banum + 3] = bcreds[jj]; 903 bargs[banum + 4] = "-a"; 904 bargs[banum + 5] = battrs[jj]; 905 bargs[banum + 6] = NULL; 906 907 } else { 908 bargs[banum - 3] = breqs[jj]; 909 bargs[banum - 1] = bcreds[jj]; 910 bargs[banum] = NULL; 911 } 912 913 fork_child( bcmd, bargs ); 914 bargs[banum] = NULL; 915 } 916 } 917 918 wait4kids( -1 ); 919 920 exit( EXIT_SUCCESS ); 921 } 922 923 static char * 924 get_file_name( char *dirname, char *filename ) 925 { 926 char buf[MAXPATHLEN]; 927 928 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s", 929 dirname, filename ); 930 return( strdup( buf )); 931 } 932 933 934 static int 935 get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] ) 936 { 937 FILE *fp; 938 int filter = 0; 939 940 if ( (fp = fopen( filename, "r" )) != NULL ) { 941 char line[BUFSIZ]; 942 943 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) { 944 char *nl; 945 int got_URL = 0; 946 947 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) 948 *nl = '\0'; 949 950 if ( luds ) luds[filter] = NULL; 951 952 if ( luds && strncmp( line, "ldap:///", STRLENOF( "ldap:///" ) ) == 0 ) { 953 LDAPURLDesc *lud; 954 955 got_URL = 1; 956 bases[filter] = NULL; 957 if ( ldap_url_parse( line, &lud ) != LDAP_URL_SUCCESS ) { 958 filter = -filter - 1; 959 break; 960 } 961 962 if ( lud->lud_dn == NULL || lud->lud_exts != NULL ) { 963 filter = -filter - 1; 964 ldap_free_urldesc( lud ); 965 break; 966 } 967 968 luds[filter] = lud; 969 970 } else { 971 bases[filter] = ArgDup( line ); 972 } 973 fgets( line, BUFSIZ, fp ); 974 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) 975 *nl = '\0'; 976 977 filters[filter] = ArgDup( line ); 978 if ( attrs ) { 979 if ( filters[filter][0] == '+') { 980 char *sep = strchr( filters[filter], ':' ); 981 982 attrs[ filter ] = &filters[ filter ][ 1 ]; 983 if ( sep != NULL ) { 984 sep[ 0 ] = '\0'; 985 /* NOTE: don't free this! */ 986 filters[ filter ] = &sep[ 1 ]; 987 } 988 989 } else { 990 attrs[ filter ] = NULL; 991 } 992 } 993 filter++; 994 995 } 996 fclose( fp ); 997 } 998 999 return filter; 1000 } 1001 1002 1003 static int 1004 get_read_entries( char *filename, char *entries[], char *filters[] ) 1005 { 1006 FILE *fp; 1007 int entry = 0; 1008 1009 if ( (fp = fopen( filename, "r" )) != NULL ) { 1010 char line[BUFSIZ]; 1011 1012 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) { 1013 char *nl; 1014 1015 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) 1016 *nl = '\0'; 1017 if ( filters != NULL && line[0] == '+' ) { 1018 LDAPURLDesc *lud; 1019 1020 if ( ldap_url_parse( &line[1], &lud ) != LDAP_URL_SUCCESS ) { 1021 entry = -entry - 1; 1022 break; 1023 } 1024 1025 if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) { 1026 ldap_free_urldesc( lud ); 1027 entry = -entry - 1; 1028 break; 1029 } 1030 1031 entries[entry] = ArgDup( lud->lud_dn ); 1032 1033 if ( lud->lud_filter ) { 1034 filters[entry] = ArgDup( lud->lud_filter ); 1035 1036 } else { 1037 filters[entry] = ArgDup( "(objectClass=*)" ); 1038 } 1039 ldap_free_urldesc( lud ); 1040 1041 } else { 1042 entries[entry] = ArgDup( line ); 1043 } 1044 1045 entry++; 1046 1047 } 1048 fclose( fp ); 1049 } 1050 1051 return( entry ); 1052 } 1053 1054 #ifndef HAVE_WINSOCK 1055 static void 1056 fork_child( char *prog, char **args ) 1057 { 1058 /* note: obscures global pid var; intended */ 1059 pid_t pid; 1060 1061 wait4kids( maxkids ); 1062 1063 switch ( pid = fork() ) { 1064 case 0: /* child */ 1065 #ifdef HAVE_EBCDIC 1066 /* The __LIBASCII execvp only handles ASCII "prog", 1067 * we still need to translate the arg vec ourselves. 1068 */ 1069 { char *arg2[MAXREQS]; 1070 int i; 1071 1072 for (i=0; args[i]; i++) { 1073 arg2[i] = ArgDup(args[i]); 1074 __atoe(arg2[i]); 1075 } 1076 arg2[i] = NULL; 1077 args = arg2; } 1078 #endif 1079 execvp( prog, args ); 1080 tester_perror( "execvp", NULL ); 1081 { int i; 1082 for (i=0; args[i]; i++); 1083 fprintf(stderr,"%d args\n", i); 1084 for (i=0; args[i]; i++) 1085 fprintf(stderr,"%d %s\n", i, args[i]); 1086 } 1087 1088 exit( EXIT_FAILURE ); 1089 break; 1090 1091 case -1: /* trouble */ 1092 tester_perror( "fork", NULL ); 1093 break; 1094 1095 default: /* parent */ 1096 nkids++; 1097 break; 1098 } 1099 } 1100 1101 static void 1102 wait4kids( int nkidval ) 1103 { 1104 int status; 1105 1106 while ( nkids >= nkidval ) { 1107 wait( &status ); 1108 1109 if ( WIFSTOPPED(status) ) { 1110 fprintf( stderr, 1111 "stopping: child stopped with signal %d\n", 1112 (int) WSTOPSIG(status) ); 1113 1114 } else if ( WIFSIGNALED(status) ) { 1115 fprintf( stderr, 1116 "stopping: child terminated with signal %d%s\n", 1117 (int) WTERMSIG(status), 1118 #ifdef WCOREDUMP 1119 WCOREDUMP(status) ? ", core dumped" : "" 1120 #else 1121 "" 1122 #endif 1123 ); 1124 exit( WEXITSTATUS(status) ); 1125 1126 } else if ( WEXITSTATUS(status) != 0 ) { 1127 fprintf( stderr, 1128 "stopping: child exited with status %d\n", 1129 (int) WEXITSTATUS(status) ); 1130 exit( WEXITSTATUS(status) ); 1131 1132 } else { 1133 nkids--; 1134 } 1135 } 1136 } 1137 #else 1138 1139 static void 1140 wait4kids( int nkidval ) 1141 { 1142 int rc, i; 1143 1144 while ( nkids >= nkidval ) { 1145 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE ); 1146 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++) 1147 children[i] = children[i+1]; 1148 nkids--; 1149 } 1150 } 1151 1152 static void 1153 fork_child( char *prog, char **args ) 1154 { 1155 int rc; 1156 1157 wait4kids( maxkids ); 1158 1159 rc = _spawnvp( _P_NOWAIT, prog, args ); 1160 1161 if ( rc == -1 ) { 1162 tester_perror( "_spawnvp", NULL ); 1163 } else { 1164 children[nkids++] = (HANDLE)rc; 1165 } 1166 } 1167 #endif 1168