Back to index

openldap  2.4.31
slapd-tester.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1999-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* ACKNOWLEDGEMENTS:
00016  * This work was initially developed by Kurt Spanier for inclusion
00017  * in OpenLDAP Software.
00018  */
00019 
00020 #include "portable.h"
00021 
00022 #include <stdio.h>
00023 
00024 #include "ac/stdlib.h"
00025 
00026 #include "ac/ctype.h"
00027 #include "ac/dirent.h"
00028 #include "ac/param.h"
00029 #include "ac/socket.h"
00030 #include "ac/string.h"
00031 #include "ac/unistd.h"
00032 #include "ac/wait.h"
00033 
00034 
00035 #include "ldap_defaults.h"
00036 #include "lutil.h"
00037 
00038 #include "ldap.h"
00039 #include "ldap_pvt.h"
00040 #include "lber_pvt.h"
00041 #include "slapd-common.h"
00042 
00043 #define SEARCHCMD           "slapd-search"
00044 #define READCMD                    "slapd-read"
00045 #define ADDCMD                     "slapd-addel"
00046 #define MODRDNCMD           "slapd-modrdn"
00047 #define MODIFYCMD           "slapd-modify"
00048 #define BINDCMD                    "slapd-bind"
00049 #define MAXARGS                    100
00050 #define MAXREQS                    5000
00051 #define LOOPS               100
00052 #define OUTERLOOPS          "1"
00053 #define RETRIES                    "0"
00054 
00055 #define TSEARCHFILE         "do_search.0"
00056 #define TREADFILE           "do_read.0"
00057 #define TADDFILE            "do_add."
00058 #define TMODRDNFILE         "do_modrdn.0"
00059 #define TMODIFYFILE         "do_modify.0"
00060 #define TBINDFILE           "do_bind.0"
00061 
00062 static char *get_file_name( char *dirname, char *filename );
00063 static int  get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] );
00064 static int  get_read_entries( char *filename, char *entries[], char *filters[] );
00065 static void fork_child( char *prog, char **args );
00066 static void   wait4kids( int nkidval );
00067 
00068 static int      maxkids = 20;
00069 static int      nkids;
00070 
00071 #ifdef HAVE_WINSOCK
00072 static HANDLE *children;
00073 static char argbuf[BUFSIZ];
00074 #define       ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
00075 #else
00076 #define       ArgDup(x) strdup(x)
00077 #endif
00078 
00079 static void
00080 usage( char *name, char opt )
00081 {
00082        if ( opt ) {
00083               fprintf( stderr, "%s: unable to handle option \'%c\'\n\n",
00084                      name, opt );
00085        }
00086 
00087        fprintf( stderr,
00088               "usage: %s "
00089               "-H <uri> | ([-h <host>] -p <port>) "
00090               "-D <manager> "
00091               "-w <passwd> "
00092               "-d <datadir> "
00093               "[-i <ignore>] "
00094               "[-j <maxchild>] "
00095               "[-l {<loops>|<type>=<loops>[,...]}] "
00096               "[-L <outerloops>] "
00097               "-P <progdir> "
00098               "[-r <maxretries>] "
00099               "[-t <delay>] "
00100               "[-C] "
00101               "[-F] "
00102               "[-I] "
00103               "[-N]\n",
00104               name );
00105        exit( EXIT_FAILURE );
00106 }
00107 
00108 int
00109 main( int argc, char **argv )
00110 {
00111        int           i, j;
00112        char          *uri = NULL;
00113        char          *host = "localhost";
00114        char          *port = NULL;
00115        char          *manager = NULL;
00116        char          *passwd = NULL;
00117        char          *dirname = NULL;
00118        char          *progdir = NULL;
00119        int           loops = LOOPS;
00120        char          *outerloops = OUTERLOOPS;
00121        char          *retries = RETRIES;
00122        char          *delay = "0";
00123        DIR           *datadir;
00124        struct dirent *file;
00125        int           friendly = 0;
00126        int           chaserefs = 0;
00127        int           noattrs = 0;
00128        int           nobind = 0;
00129        int           noinit = 1;
00130        char          *ignore = NULL;
00131        /* search */
00132        char          *sfile = NULL;
00133        char          *sreqs[MAXREQS];
00134        char          *sattrs[MAXREQS];
00135        char          *sbase[MAXREQS];
00136        LDAPURLDesc   *slud[MAXREQS];
00137        int           snum = 0;
00138        char          *sargs[MAXARGS];
00139        int           sanum;
00140        int           sextra_args = 0;
00141        char          scmd[MAXPATHLEN];
00142        int           swamp = 0;
00143        char          swampopt[sizeof("-SSS")];
00144        /* static so that its address can be used in initializer below. */
00145        static char   sloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)];
00146        /* read */
00147        char          *rfile = NULL;
00148        char          *rreqs[MAXREQS];
00149        int           rnum = 0;
00150        char          *rargs[MAXARGS];
00151        char          *rflts[MAXREQS];
00152        int           ranum;
00153        int           rextra_args = 0;
00154        char          rcmd[MAXPATHLEN];
00155        static char   rloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)];
00156        /* addel */
00157        char          *afiles[MAXREQS];
00158        int           anum = 0;
00159        char          *aargs[MAXARGS];
00160        int           aanum;
00161        char          acmd[MAXPATHLEN];
00162        static char   aloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)];
00163        /* modrdn */
00164        char          *nfile = NULL;
00165        char          *nreqs[MAXREQS];
00166        int           nnum = 0;
00167        char          *nargs[MAXARGS];
00168        int           nanum;
00169        char          ncmd[MAXPATHLEN];
00170        static char   nloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)];
00171        /* modify */
00172        char          *mfile = NULL;
00173        char          *mreqs[MAXREQS];
00174        char          *mdn[MAXREQS];
00175        int           mnum = 0;
00176        char          *margs[MAXARGS];
00177        int           manum;
00178        char          mcmd[MAXPATHLEN];
00179        static char   mloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)];
00180        /* bind */
00181        char          *bfile = NULL;
00182        char          *breqs[MAXREQS];
00183        char          *bcreds[MAXREQS];
00184        char          *battrs[MAXREQS];
00185        int           bnum = 0;
00186        char          *bargs[MAXARGS];
00187        int           banum;
00188        char          bcmd[MAXPATHLEN];
00189        static char   bloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)];
00190        char          **bargs_extra = NULL;
00191 
00192        char          *friendlyOpt = NULL;
00193        int           pw_ask = 0;
00194        char          *pw_file = NULL;
00195 
00196        /* extra action to do after bind... */
00197        typedef struct extra_t {
00198               char          *action;
00199               struct extra_t       *next;
00200        }             extra_t;
00201 
00202        extra_t              *extra = NULL;
00203        int           nextra = 0;
00204 
00205        tester_init( "slapd-tester", TESTER_TESTER );
00206 
00207        sloops[0] = '\0';
00208        rloops[0] = '\0';
00209        aloops[0] = '\0';
00210        nloops[0] = '\0';
00211        mloops[0] = '\0';
00212        bloops[0] = '\0';
00213 
00214        while ( ( i = getopt( argc, argv, "AB:CD:d:FH:h:Ii:j:L:l:NP:p:r:St:Ww:y:" ) ) != EOF )
00215        {
00216               switch ( i ) {
00217               case 'A':
00218                      noattrs++;
00219                      break;
00220 
00221               case 'B': {
00222                      char   **p,
00223                             **b = ldap_str2charray( optarg, "," );
00224                      extra_t       **epp;
00225 
00226                      for ( epp = &extra; *epp; epp = &(*epp)->next )
00227                             ;
00228 
00229                      for ( p = b; p[0]; p++ ) {
00230                             *epp = calloc( 1, sizeof( extra_t ) );
00231                             (*epp)->action = p[0];
00232                             epp = &(*epp)->next;
00233                             nextra++;
00234                      }
00235 
00236                      ldap_memfree( b );
00237                      } break;
00238 
00239               case 'C':
00240                      chaserefs++;
00241                      break;
00242 
00243               case 'D':            /* slapd manager */
00244                      manager = ArgDup( optarg );
00245                      break;
00246 
00247               case 'd':            /* data directory */
00248                      dirname = strdup( optarg );
00249                      break;
00250 
00251               case 'F':
00252                      friendly++;
00253                      break;
00254 
00255               case 'H':            /* slapd uri */
00256                      uri = strdup( optarg );
00257                      break;
00258 
00259               case 'h':            /* slapd host */
00260                      host = strdup( optarg );
00261                      break;
00262 
00263               case 'I':
00264                      noinit = 0;
00265                      break;
00266 
00267               case 'i':
00268                      ignore = optarg;
00269                      break;
00270 
00271               case 'j':            /* the number of parallel clients */
00272                      if ( lutil_atoi( &maxkids, optarg ) != 0 ) {
00273                             usage( argv[0], 'j' );
00274                      }
00275                      break;
00276 
00277               case 'l':            /* the number of loops per client */
00278                      if ( !isdigit( (unsigned char) optarg[0] ) ) {
00279                             char   **p,
00280                                    **l = ldap_str2charray( optarg, "," );
00281 
00282                             for ( p = l; p[0]; p++) {
00283                                    struct {
00284                                           struct berval type;
00285                                           char          *buf;
00286                                    } types[] = {
00287                                           { BER_BVC( "add=" ), aloops },
00288                                           { BER_BVC( "bind=" ),       bloops },
00289                                           { BER_BVC( "modify=" ),     mloops },
00290                                           { BER_BVC( "modrdn=" ),     nloops },
00291                                           { BER_BVC( "read=" ),       rloops },
00292                                           { BER_BVC( "search=" ),     sloops },
00293                                           { BER_BVNULL,        NULL }
00294                                    };
00295                                    int    c, n;
00296 
00297                                    for ( c = 0; types[c].type.bv_val; c++ ) {
00298                                           if ( strncasecmp( p[0], types[c].type.bv_val, types[c].type.bv_len ) == 0 ) {
00299                                                  break;
00300                                           }
00301                                    }
00302 
00303                                    if ( types[c].type.bv_val == NULL ) {
00304                                           usage( argv[0], 'l' );
00305                                    }
00306 
00307                                    if ( lutil_atoi( &n, &p[0][types[c].type.bv_len] ) != 0 ) {
00308                                           usage( argv[0], 'l' );
00309                                    }
00310 
00311                                    snprintf( types[c].buf, sizeof( aloops ), "%d", n );
00312                             }
00313 
00314                             ldap_charray_free( l );
00315 
00316                      } else if ( lutil_atoi( &loops, optarg ) != 0 ) {
00317                             usage( argv[0], 'l' );
00318                      }
00319                      break;
00320 
00321               case 'L':            /* the number of outerloops per client */
00322                      outerloops = strdup( optarg );
00323                      break;
00324 
00325               case 'N':
00326                      nobind++;
00327                      break;
00328 
00329               case 'P':            /* prog directory */
00330                      progdir = strdup( optarg );
00331                      break;
00332 
00333               case 'p':            /* the servers port number */
00334                      port = strdup( optarg );
00335                      break;
00336 
00337               case 'r':            /* the number of retries in case of error */
00338                      retries = strdup( optarg );
00339                      break;
00340 
00341               case 'S':
00342                      swamp++;
00343                      break;
00344 
00345               case 't':            /* the delay in seconds between each retry */
00346                      delay = strdup( optarg );
00347                      break;
00348 
00349               case 'w':            /* the managers passwd */
00350                      passwd = ArgDup( optarg );
00351                      memset( optarg, '*', strlen( optarg ) );
00352                      break;
00353 
00354               case 'W':
00355                      pw_ask++;
00356                      break;
00357 
00358               case 'y':
00359                      pw_file = optarg;
00360                      break;
00361 
00362               default:
00363                      usage( argv[0], '\0' );
00364                      break;
00365               }
00366        }
00367 
00368        if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
00369                      ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
00370        {
00371               usage( argv[0], '\0' );
00372        }
00373 
00374 #ifdef HAVE_WINSOCK
00375        children = malloc( maxkids * sizeof(HANDLE) );
00376 #endif
00377        /* get the file list */
00378        if ( ( datadir = opendir( dirname )) == NULL ) {
00379               fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
00380                                    argv[0], dirname );
00381               exit( EXIT_FAILURE );
00382        }
00383 
00384        /*  look for search, read, modrdn, and add/delete files */
00385        for ( file = readdir( datadir ); file; file = readdir( datadir )) {
00386 
00387               if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
00388                      sfile = get_file_name( dirname, file->d_name );
00389                      continue;
00390               } else if ( !strcasecmp( file->d_name, TREADFILE )) {
00391                      rfile = get_file_name( dirname, file->d_name );
00392                      continue;
00393               } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
00394                      nfile = get_file_name( dirname, file->d_name );
00395                      continue;
00396               } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
00397                      mfile = get_file_name( dirname, file->d_name );
00398                      continue;
00399               } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
00400                      && ( anum < MAXREQS )) {
00401                      afiles[anum++] = get_file_name( dirname, file->d_name );
00402                      continue;
00403               } else if ( !strcasecmp( file->d_name, TBINDFILE )) {
00404                      bfile = get_file_name( dirname, file->d_name );
00405                      continue;
00406               }
00407        }
00408 
00409        closedir( datadir );
00410 
00411        if ( pw_ask ) {
00412               passwd = getpassphrase( _("Enter LDAP Password: ") );
00413 
00414        } else if ( pw_file ) {
00415               struct berval pw;
00416 
00417               if ( lutil_get_filed_password( pw_file, &pw ) ) {
00418                      exit( EXIT_FAILURE );
00419               }
00420 
00421               passwd = pw.bv_val;
00422        }
00423 
00424        if ( !sfile && !rfile && !nfile && !mfile && !bfile && !anum ) {
00425               fprintf( stderr, "no data files found.\n" );
00426               exit( EXIT_FAILURE );
00427        }
00428 
00429        /* look for search requests */
00430        if ( sfile ) {
00431               snum = get_search_filters( sfile, sreqs, sattrs, sbase, slud );
00432               if ( snum < 0 ) {
00433                      fprintf( stderr,
00434                             "unable to parse file \"%s\" line %d\n",
00435                             sfile, -2*(snum + 1));
00436                      exit( EXIT_FAILURE );
00437               }
00438        }
00439 
00440        /* look for read requests */
00441        if ( rfile ) {
00442               rnum = get_read_entries( rfile, rreqs, rflts );
00443               if ( rnum < 0 ) {
00444                      fprintf( stderr,
00445                             "unable to parse file \"%s\" line %d\n",
00446                             rfile, -2*(rnum + 1) );
00447                      exit( EXIT_FAILURE );
00448               }
00449        }
00450 
00451        /* look for modrdn requests */
00452        if ( nfile ) {
00453               nnum = get_read_entries( nfile, nreqs, NULL );
00454               if ( nnum < 0 ) {
00455                      fprintf( stderr,
00456                             "unable to parse file \"%s\" line %d\n",
00457                             nfile, -2*(nnum + 1) );
00458                      exit( EXIT_FAILURE );
00459               }
00460        }
00461 
00462        /* look for modify requests */
00463        if ( mfile ) {
00464               mnum = get_search_filters( mfile, mreqs, NULL, mdn, NULL );
00465               if ( mnum < 0 ) {
00466                      fprintf( stderr,
00467                             "unable to parse file \"%s\" line %d\n",
00468                             mfile, -2*(mnum + 1) );
00469                      exit( EXIT_FAILURE );
00470               }
00471        }
00472 
00473        /* look for bind requests */
00474        if ( bfile ) {
00475               bnum = get_search_filters( bfile, bcreds, battrs, breqs, NULL );
00476               if ( bnum < 0 ) {
00477                      fprintf( stderr,
00478                             "unable to parse file \"%s\" line %d\n",
00479                             bfile, -2*(bnum + 1) );
00480                      exit( EXIT_FAILURE );
00481               }
00482        }
00483 
00484        /* setup friendly option */
00485        switch ( friendly ) {
00486        case 0:
00487               break;
00488 
00489        case 1:
00490               friendlyOpt = "-F";
00491               break;
00492 
00493        default:
00494               /* NOTE: right now we don't need it more than twice */
00495        case 2:
00496               friendlyOpt = "-FF";
00497               break;
00498        }
00499 
00500        /* setup swamp option */
00501        if ( swamp ) {
00502               swampopt[0] = '-';
00503               if ( swamp > 3 ) swamp = 3;
00504               swampopt[swamp + 1] = '\0';
00505               for ( ; swamp-- > 0; ) swampopt[swamp + 1] = 'S';
00506        }
00507 
00508        /* setup loop options */
00509        if ( sloops[0] == '\0' ) snprintf( sloops, sizeof( sloops ), "%d", 10 * loops );
00510        if ( rloops[0] == '\0' ) snprintf( rloops, sizeof( rloops ), "%d", 20 * loops );
00511        if ( aloops[0] == '\0' ) snprintf( aloops, sizeof( aloops ), "%d", loops );
00512        if ( nloops[0] == '\0' ) snprintf( nloops, sizeof( nloops ), "%d", loops );
00513        if ( mloops[0] == '\0' ) snprintf( mloops, sizeof( mloops ), "%d", loops );
00514        if ( bloops[0] == '\0' ) snprintf( bloops, sizeof( bloops ), "%d", 20 * loops );
00515 
00516        /*
00517         * generate the search clients
00518         */
00519 
00520        sanum = 0;
00521        snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
00522               progdir );
00523        sargs[sanum++] = scmd;
00524        if ( uri ) {
00525               sargs[sanum++] = "-H";
00526               sargs[sanum++] = uri;
00527        } else {
00528               sargs[sanum++] = "-h";
00529               sargs[sanum++] = host;
00530               sargs[sanum++] = "-p";
00531               sargs[sanum++] = port;
00532        }
00533        sargs[sanum++] = "-D";
00534        sargs[sanum++] = manager;
00535        sargs[sanum++] = "-w";
00536        sargs[sanum++] = passwd;
00537        sargs[sanum++] = "-l";
00538        sargs[sanum++] = sloops;
00539        sargs[sanum++] = "-L";
00540        sargs[sanum++] = outerloops;
00541        sargs[sanum++] = "-r";
00542        sargs[sanum++] = retries;
00543        sargs[sanum++] = "-t";
00544        sargs[sanum++] = delay;
00545        if ( friendly ) {
00546               sargs[sanum++] = friendlyOpt;
00547        }
00548        if ( chaserefs ) {
00549               sargs[sanum++] = "-C";
00550        }
00551        if ( noattrs ) {
00552               sargs[sanum++] = "-A";
00553        }
00554        if ( nobind ) {
00555               sargs[sanum++] = "-N";
00556        }
00557        if ( ignore ) {
00558               sargs[sanum++] = "-i";
00559               sargs[sanum++] = ignore;
00560        }
00561        if ( swamp ) {
00562               sargs[sanum++] = swampopt;
00563        }
00564        sargs[sanum++] = "-b";
00565        sargs[sanum++] = NULL;             /* will hold the search base */
00566        sargs[sanum++] = "-s";
00567        sargs[sanum++] = NULL;             /* will hold the search scope */
00568        sargs[sanum++] = "-f";
00569        sargs[sanum++] = NULL;             /* will hold the search request */
00570 
00571        sargs[sanum++] = NULL;
00572        sargs[sanum++] = NULL;             /* might hold the "attr" request */
00573        sextra_args += 2;
00574 
00575        sargs[sanum] = NULL;
00576 
00577        /*
00578         * generate the read clients
00579         */
00580 
00581        ranum = 0;
00582        snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
00583               progdir );
00584        rargs[ranum++] = rcmd;
00585        if ( uri ) {
00586               rargs[ranum++] = "-H";
00587               rargs[ranum++] = uri;
00588        } else {
00589               rargs[ranum++] = "-h";
00590               rargs[ranum++] = host;
00591               rargs[ranum++] = "-p";
00592               rargs[ranum++] = port;
00593        }
00594        rargs[ranum++] = "-D";
00595        rargs[ranum++] = manager;
00596        rargs[ranum++] = "-w";
00597        rargs[ranum++] = passwd;
00598        rargs[ranum++] = "-l";
00599        rargs[ranum++] = rloops;
00600        rargs[ranum++] = "-L";
00601        rargs[ranum++] = outerloops;
00602        rargs[ranum++] = "-r";
00603        rargs[ranum++] = retries;
00604        rargs[ranum++] = "-t";
00605        rargs[ranum++] = delay;
00606        if ( friendly ) {
00607               rargs[ranum++] = friendlyOpt;
00608        }
00609        if ( chaserefs ) {
00610               rargs[ranum++] = "-C";
00611        }
00612        if ( noattrs ) {
00613               rargs[ranum++] = "-A";
00614        }
00615        if ( ignore ) {
00616               rargs[ranum++] = "-i";
00617               rargs[ranum++] = ignore;
00618        }
00619        if ( swamp ) {
00620               rargs[ranum++] = swampopt;
00621        }
00622        rargs[ranum++] = "-e";
00623        rargs[ranum++] = NULL;             /* will hold the read entry */
00624 
00625        rargs[ranum++] = NULL;
00626        rargs[ranum++] = NULL;             /* might hold the filter arg */
00627        rextra_args += 2;
00628 
00629        rargs[ranum] = NULL;
00630 
00631        /*
00632         * generate the modrdn clients
00633         */
00634 
00635        nanum = 0;
00636        snprintf( ncmd, sizeof ncmd, "%s" LDAP_DIRSEP MODRDNCMD,
00637               progdir );
00638        nargs[nanum++] = ncmd;
00639        if ( uri ) {
00640               nargs[nanum++] = "-H";
00641               nargs[nanum++] = uri;
00642        } else {
00643               nargs[nanum++] = "-h";
00644               nargs[nanum++] = host;
00645               nargs[nanum++] = "-p";
00646               nargs[nanum++] = port;
00647        }
00648        nargs[nanum++] = "-D";
00649        nargs[nanum++] = manager;
00650        nargs[nanum++] = "-w";
00651        nargs[nanum++] = passwd;
00652        nargs[nanum++] = "-l";
00653        nargs[nanum++] = nloops;
00654        nargs[nanum++] = "-L";
00655        nargs[nanum++] = outerloops;
00656        nargs[nanum++] = "-r";
00657        nargs[nanum++] = retries;
00658        nargs[nanum++] = "-t";
00659        nargs[nanum++] = delay;
00660        if ( friendly ) {
00661               nargs[nanum++] = friendlyOpt;
00662        }
00663        if ( chaserefs ) {
00664               nargs[nanum++] = "-C";
00665        }
00666        if ( ignore ) {
00667               nargs[nanum++] = "-i";
00668               nargs[nanum++] = ignore;
00669        }
00670        nargs[nanum++] = "-e";
00671        nargs[nanum++] = NULL;             /* will hold the modrdn entry */
00672        nargs[nanum] = NULL;
00673        
00674        /*
00675         * generate the modify clients
00676         */
00677 
00678        manum = 0;
00679        snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODIFYCMD,
00680               progdir );
00681        margs[manum++] = mcmd;
00682        if ( uri ) {
00683               margs[manum++] = "-H";
00684               margs[manum++] = uri;
00685        } else {
00686               margs[manum++] = "-h";
00687               margs[manum++] = host;
00688               margs[manum++] = "-p";
00689               margs[manum++] = port;
00690        }
00691        margs[manum++] = "-D";
00692        margs[manum++] = manager;
00693        margs[manum++] = "-w";
00694        margs[manum++] = passwd;
00695        margs[manum++] = "-l";
00696        margs[manum++] = mloops;
00697        margs[manum++] = "-L";
00698        margs[manum++] = outerloops;
00699        margs[manum++] = "-r";
00700        margs[manum++] = retries;
00701        margs[manum++] = "-t";
00702        margs[manum++] = delay;
00703        if ( friendly ) {
00704               margs[manum++] = friendlyOpt;
00705        }
00706        if ( chaserefs ) {
00707               margs[manum++] = "-C";
00708        }
00709        if ( ignore ) {
00710               margs[manum++] = "-i";
00711               margs[manum++] = ignore;
00712        }
00713        margs[manum++] = "-e";
00714        margs[manum++] = NULL;             /* will hold the modify entry */
00715        margs[manum++] = "-a";;
00716        margs[manum++] = NULL;             /* will hold the ava */
00717        margs[manum] = NULL;
00718 
00719        /*
00720         * generate the add/delete clients
00721         */
00722 
00723        aanum = 0;
00724        snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
00725               progdir );
00726        aargs[aanum++] = acmd;
00727        if ( uri ) {
00728               aargs[aanum++] = "-H";
00729               aargs[aanum++] = uri;
00730        } else {
00731               aargs[aanum++] = "-h";
00732               aargs[aanum++] = host;
00733               aargs[aanum++] = "-p";
00734               aargs[aanum++] = port;
00735        }
00736        aargs[aanum++] = "-D";
00737        aargs[aanum++] = manager;
00738        aargs[aanum++] = "-w";
00739        aargs[aanum++] = passwd;
00740        aargs[aanum++] = "-l";
00741        aargs[aanum++] = aloops;
00742        aargs[aanum++] = "-L";
00743        aargs[aanum++] = outerloops;
00744        aargs[aanum++] = "-r";
00745        aargs[aanum++] = retries;
00746        aargs[aanum++] = "-t";
00747        aargs[aanum++] = delay;
00748        if ( friendly ) {
00749               aargs[aanum++] = friendlyOpt;
00750        }
00751        if ( chaserefs ) {
00752               aargs[aanum++] = "-C";
00753        }
00754        if ( ignore ) {
00755               aargs[aanum++] = "-i";
00756               aargs[aanum++] = ignore;
00757        }
00758        aargs[aanum++] = "-f";
00759        aargs[aanum++] = NULL;             /* will hold the add data file */
00760        aargs[aanum] = NULL;
00761 
00762        /*
00763         * generate the bind clients
00764         */
00765 
00766        banum = 0;
00767        snprintf( bcmd, sizeof bcmd, "%s" LDAP_DIRSEP BINDCMD,
00768               progdir );
00769        bargs[banum++] = bcmd;
00770        if ( !noinit ) {
00771               bargs[banum++] = "-I";      /* init on each bind */
00772        }
00773        if ( uri ) {
00774               bargs[banum++] = "-H";
00775               bargs[banum++] = uri;
00776        } else {
00777               bargs[banum++] = "-h";
00778               bargs[banum++] = host;
00779               bargs[banum++] = "-p";
00780               bargs[banum++] = port;
00781        }
00782        bargs[banum++] = "-l";
00783        bargs[banum++] = bloops;
00784        bargs[banum++] = "-L";
00785        bargs[banum++] = outerloops;
00786 #if 0
00787        bargs[banum++] = "-r";
00788        bargs[banum++] = retries;
00789        bargs[banum++] = "-t";
00790        bargs[banum++] = delay;
00791 #endif
00792        if ( friendly ) {
00793               bargs[banum++] = friendlyOpt;
00794        }
00795        if ( chaserefs ) {
00796               bargs[banum++] = "-C";
00797        }
00798        if ( ignore ) {
00799               bargs[banum++] = "-i";
00800               bargs[banum++] = ignore;
00801        }
00802        if ( nextra ) {
00803               bargs[banum++] = "-B";
00804               bargs_extra = &bargs[banum++];
00805        }
00806        bargs[banum++] = "-D";
00807        bargs[banum++] = NULL;
00808        bargs[banum++] = "-w";
00809        bargs[banum++] = NULL;
00810        bargs[banum] = NULL;
00811 
00812 #define       DOREQ(n,j) ((n) && ((maxkids > (n)) ? ((j) < maxkids ) : ((j) < (n))))
00813 
00814        for ( j = 0; j < MAXREQS; j++ ) {
00815               /* search */
00816               if ( DOREQ( snum, j ) ) {
00817                      int    jj = j % snum;
00818                      int    x = sanum - sextra_args;
00819 
00820                      /* base */
00821                      if ( sbase[jj] != NULL ) {
00822                             sargs[sanum - 7] = sbase[jj];
00823 
00824                      } else {
00825                             sargs[sanum - 7] = slud[jj]->lud_dn;
00826                      }
00827 
00828                      /* scope */
00829                      if ( slud[jj] != NULL ) {
00830                             sargs[sanum - 5] = (char *)ldap_pvt_scope2str( slud[jj]->lud_scope );
00831 
00832                      } else {
00833                             sargs[sanum - 5] = "sub";
00834                      }
00835 
00836                      /* filter */
00837                      if ( sreqs[jj] != NULL ) {
00838                             sargs[sanum - 3] = sreqs[jj];
00839 
00840                      } else if ( slud[jj]->lud_filter != NULL ) {
00841                             sargs[sanum - 3] = slud[jj]->lud_filter;
00842 
00843                      } else {
00844                             sargs[sanum - 3] = "(objectClass=*)";
00845                      }
00846 
00847                      /* extras */
00848                      sargs[x] = NULL;
00849 
00850                      /* attr */
00851                      if ( sattrs[jj] != NULL ) {
00852                             sargs[x++] = "-a";
00853                             sargs[x++] = sattrs[jj];
00854                      }
00855 
00856                      /* attrs */
00857                      if ( slud[jj] != NULL && slud[jj]->lud_attrs != NULL ) {
00858                             int    i;
00859 
00860                             for ( i = 0; slud[jj]->lud_attrs[ i ] != NULL && x + i < MAXARGS - 1; i++ ) {
00861                                    sargs[x + i] = slud[jj]->lud_attrs[ i ];
00862                             }
00863                             sargs[x + i] = NULL;
00864                      }
00865 
00866                      fork_child( scmd, sargs );
00867               }
00868 
00869               /* read */
00870               if ( DOREQ( rnum, j ) ) {
00871                      int    jj = j % rnum;
00872                      int    x = ranum - rextra_args;
00873 
00874                      rargs[ranum - 3] = rreqs[jj];
00875                      if ( rflts[jj] != NULL ) {
00876                             rargs[x++] = "-f";
00877                             rargs[x++] = rflts[jj];
00878                      }
00879                      rargs[x] = NULL;
00880                      fork_child( rcmd, rargs );
00881               }
00882 
00883               /* rename */
00884               if ( j < nnum ) {
00885                      nargs[nanum - 1] = nreqs[j];
00886                      fork_child( ncmd, nargs );
00887               }
00888 
00889               /* modify */
00890               if ( j < mnum ) {
00891                      margs[manum - 3] = mdn[j];
00892                      margs[manum - 1] = mreqs[j];
00893                      fork_child( mcmd, margs );
00894               }
00895 
00896               /* add/delete */
00897               if ( j < anum ) {
00898                      aargs[aanum - 1] = afiles[j];
00899                      fork_child( acmd, aargs );
00900               }
00901 
00902               /* bind */
00903               if ( DOREQ( bnum, j ) ) {
00904                      int    jj = j % bnum;
00905 
00906                      if ( nextra ) {
00907                             int    n = ((double)nextra)*rand()/(RAND_MAX + 1.0);
00908                             extra_t       *e;
00909 
00910                             for ( e = extra; n-- > 0; e = e->next )
00911                                    ;
00912                             *bargs_extra = e->action;
00913                      }
00914 
00915                      if ( battrs[jj] != NULL ) {
00916                             bargs[banum - 3] = manager ? manager : "";
00917                             bargs[banum - 1] = passwd ? passwd : "";
00918 
00919                             bargs[banum + 0] = "-b";
00920                             bargs[banum + 1] = breqs[jj];
00921                             bargs[banum + 2] = "-f";
00922                             bargs[banum + 3] = bcreds[jj];
00923                             bargs[banum + 4] = "-a";
00924                             bargs[banum + 5] = battrs[jj];
00925                             bargs[banum + 6] = NULL;
00926 
00927                      } else {
00928                             bargs[banum - 3] = breqs[jj];
00929                             bargs[banum - 1] = bcreds[jj];
00930                             bargs[banum] = NULL;
00931                      }
00932 
00933                      fork_child( bcmd, bargs );
00934                      bargs[banum] = NULL;
00935               }
00936        }
00937 
00938        wait4kids( -1 );
00939 
00940        exit( EXIT_SUCCESS );
00941 }
00942 
00943 static char *
00944 get_file_name( char *dirname, char *filename )
00945 {
00946        char buf[MAXPATHLEN];
00947 
00948        snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
00949               dirname, filename );
00950        return( strdup( buf ));
00951 }
00952 
00953 
00954 static int
00955 get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] )
00956 {
00957        FILE    *fp;
00958        int     filter = 0;
00959 
00960        if ( (fp = fopen( filename, "r" )) != NULL ) {
00961               char  line[BUFSIZ];
00962 
00963               while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
00964                      char   *nl;
00965                      int    got_URL = 0;
00966 
00967                      if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
00968                             *nl = '\0';
00969 
00970                      if ( luds ) luds[filter] = NULL;
00971 
00972                      if ( luds && strncmp( line, "ldap:///", STRLENOF( "ldap:///" ) ) == 0 ) {
00973                             LDAPURLDesc   *lud;
00974 
00975                             got_URL = 1;
00976                             bases[filter] = NULL;
00977                             if ( ldap_url_parse( line, &lud ) != LDAP_URL_SUCCESS ) {
00978                                    filter = -filter - 1;
00979                                    break;
00980                             }
00981 
00982                             if ( lud->lud_dn == NULL || lud->lud_exts != NULL ) {
00983                                    filter = -filter - 1;
00984                                    ldap_free_urldesc( lud );
00985                                    break;
00986                             }
00987 
00988                             luds[filter] = lud;
00989 
00990                      } else {
00991                             bases[filter] = ArgDup( line );
00992                      }
00993                      if ( fgets( line, BUFSIZ, fp ) == NULL )
00994                             *line = '\0';
00995                      if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
00996                             *nl = '\0';
00997 
00998                      filters[filter] = ArgDup( line );
00999                      if ( attrs ) {
01000                             if ( filters[filter][0] == '+') {
01001                                    char   *sep = strchr( filters[filter], ':' );
01002 
01003                                    attrs[ filter ] = &filters[ filter ][ 1 ];
01004                                    if ( sep != NULL ) {
01005                                           sep[ 0 ] = '\0';
01006                                           /* NOTE: don't free this! */
01007                                           filters[ filter ] = &sep[ 1 ];
01008                                    }
01009 
01010                             } else {
01011                                    attrs[ filter ] = NULL;
01012                             }
01013                      }
01014                      filter++;
01015 
01016               }
01017               fclose( fp );
01018        }
01019 
01020        return filter;
01021 }
01022 
01023 
01024 static int
01025 get_read_entries( char *filename, char *entries[], char *filters[] )
01026 {
01027        FILE    *fp;
01028        int     entry = 0;
01029 
01030        if ( (fp = fopen( filename, "r" )) != NULL ) {
01031               char  line[BUFSIZ];
01032 
01033               while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
01034                      char *nl;
01035 
01036                      if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
01037                             *nl = '\0';
01038                      if ( filters != NULL && line[0] == '+' ) {
01039                             LDAPURLDesc   *lud;
01040 
01041                             if ( ldap_url_parse( &line[1], &lud ) != LDAP_URL_SUCCESS ) {
01042                                    entry = -entry - 1;
01043                                    break;
01044                             }
01045 
01046                             if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
01047                                    ldap_free_urldesc( lud );
01048                                    entry = -entry - 1;
01049                                    break;
01050                             }
01051 
01052                             entries[entry] = ArgDup( lud->lud_dn );
01053 
01054                             if ( lud->lud_filter ) {
01055                                    filters[entry] = ArgDup( lud->lud_filter );
01056 
01057                             } else {
01058                                    filters[entry] = ArgDup( "(objectClass=*)" );
01059                             }
01060                             ldap_free_urldesc( lud );
01061 
01062                      } else {
01063                             if ( filters != NULL )
01064                                    filters[entry] = NULL;
01065 
01066                             entries[entry] = ArgDup( line );
01067                      }
01068 
01069                      entry++;
01070 
01071               }
01072               fclose( fp );
01073        }
01074 
01075        return( entry );
01076 }
01077 
01078 #ifndef HAVE_WINSOCK
01079 static void
01080 fork_child( char *prog, char **args )
01081 {
01082        /* note: obscures global pid var; intended */
01083        pid_t  pid;
01084 
01085        wait4kids( maxkids );
01086 
01087        switch ( pid = fork() ) {
01088        case 0:              /* child */
01089 #ifdef HAVE_EBCDIC
01090               /* The __LIBASCII execvp only handles ASCII "prog",
01091                * we still need to translate the arg vec ourselves.
01092                */
01093               { char *arg2[MAXREQS];
01094               int i;
01095 
01096               for (i=0; args[i]; i++) {
01097                      arg2[i] = ArgDup(args[i]);
01098                      __atoe(arg2[i]);
01099               }
01100               arg2[i] = NULL;
01101               args = arg2; }
01102 #endif
01103               execvp( prog, args );
01104               tester_perror( "execvp", NULL );
01105               { int i;
01106                      for (i=0; args[i]; i++);
01107                      fprintf(stderr,"%d args\n", i);
01108                      for (i=0; args[i]; i++)
01109                             fprintf(stderr,"%d %s\n", i, args[i]);
01110               }
01111 
01112               exit( EXIT_FAILURE );
01113               break;
01114 
01115        case -1:      /* trouble */
01116               tester_perror( "fork", NULL );
01117               break;
01118 
01119        default:      /* parent */
01120               nkids++;
01121               break;
01122        }
01123 }
01124 
01125 static void
01126 wait4kids( int nkidval )
01127 {
01128        int           status;
01129 
01130        while ( nkids >= nkidval ) {
01131               pid_t pid = wait( &status );
01132 
01133               if ( WIFSTOPPED(status) ) {
01134                      fprintf( stderr,
01135                          "stopping: child PID=%ld stopped with signal %d\n",
01136                          (long) pid, (int) WSTOPSIG(status) );
01137 
01138               } else if ( WIFSIGNALED(status) ) {
01139                      fprintf( stderr, 
01140                          "stopping: child PID=%ld terminated with signal %d%s\n",
01141                          (long) pid, (int) WTERMSIG(status),
01142 #ifdef WCOREDUMP
01143                             WCOREDUMP(status) ? ", core dumped" : ""
01144 #else
01145                             ""
01146 #endif
01147                             );
01148                      exit( WEXITSTATUS(status)  );
01149 
01150               } else if ( WEXITSTATUS(status) != 0 ) {
01151                      fprintf( stderr, 
01152                          "stopping: child PID=%ld exited with status %d\n",
01153                          (long) pid, (int) WEXITSTATUS(status) );
01154                      exit( WEXITSTATUS(status) );
01155 
01156               } else {
01157                      nkids--;
01158               }
01159        }
01160 }
01161 #else
01162 
01163 static void
01164 wait4kids( int nkidval )
01165 {
01166        int rc, i;
01167 
01168        while ( nkids >= nkidval ) {
01169               rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
01170               for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
01171                      children[i] = children[i+1];
01172               nkids--;
01173        }
01174 }
01175 
01176 static void
01177 fork_child( char *prog, char **args )
01178 {
01179        int rc;
01180 
01181        wait4kids( maxkids );
01182 
01183        rc = _spawnvp( _P_NOWAIT, prog, args );
01184 
01185        if ( rc == -1 ) {
01186               tester_perror( "_spawnvp", NULL );
01187        } else {
01188               children[nkids++] = (HANDLE)rc;
01189        }
01190 }
01191 #endif