2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2006 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
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>.
16 * This work was initially developed by Kurt Spanier for inclusion
17 * in OpenLDAP Software.
24 #include <ac/stdlib.h>
27 #include <ac/dirent.h>
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/unistd.h>
35 #include "ldap_defaults.h"
39 #include "slapd-common.h"
41 #define SEARCHCMD "slapd-search"
42 #define READCMD "slapd-read"
43 #define ADDCMD "slapd-addel"
44 #define MODRDNCMD "slapd-modrdn"
45 #define MODIFYCMD "slapd-modify"
46 #define BINDCMD "slapd-bind"
52 #define TSEARCHFILE "do_search.0"
53 #define TREADFILE "do_read.0"
54 #define TADDFILE "do_add."
55 #define TMODRDNFILE "do_modrdn.0"
56 #define TMODIFYFILE "do_modify.0"
57 #define TBINDFILE "do_bind.0"
59 static char *get_file_name( char *dirname, char *filename );
60 static int get_search_filters( char *filename, char *filters[], char *bases[] );
61 static int get_read_entries( char *filename, char *entries[] );
62 static void fork_child( char *prog, char **args );
63 static void wait4kids( int nkidval );
65 static int maxkids = 20;
69 static HANDLE *children;
70 static char argbuf[BUFSIZ];
71 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
73 #define ArgDup(x) strdup(x)
81 "-H <uri> | ([-h <host>] -p <port>) "
96 main( int argc, char **argv )
100 char *host = "localhost";
102 char *manager = NULL;
104 char *dirname = NULL;
105 char *progdir = NULL;
107 char *retries = RETRIES;
114 char *sreqs[MAXREQS];
115 char *sbase[MAXREQS];
117 char *sargs[MAXARGS];
119 char scmd[MAXPATHLEN];
122 char *rreqs[MAXREQS];
124 char *rargs[MAXARGS];
126 char rcmd[MAXPATHLEN];
128 char *afiles[MAXREQS];
130 char *aargs[MAXARGS];
132 char acmd[MAXPATHLEN];
135 char *mreqs[MAXREQS];
137 char *margs[MAXARGS];
139 char mcmd[MAXPATHLEN];
141 char *modfile = NULL;
142 char *modreqs[MAXREQS];
143 char *moddn[MAXREQS];
145 char *modargs[MAXARGS];
147 char modcmd[MAXPATHLEN];
150 char *breqs[MAXREQS];
151 char *bcreds[MAXREQS];
153 char *bargs[MAXARGS];
155 char bcmd[MAXPATHLEN];
157 tester_init( "slapd-tester" );
159 while ( (i = getopt( argc, argv, "D:d:FH:h:j:l:P:p:r:t:w:" )) != EOF ) {
161 case 'D': /* slapd manager */
162 manager = ArgDup( optarg );
165 case 'd': /* data directory */
166 dirname = strdup( optarg );
173 case 'H': /* slapd uri */
174 uri = strdup( optarg );
177 case 'h': /* slapd host */
178 host = strdup( optarg );
181 case 'j': /* the number of parallel clients */
182 if ( lutil_atoi( &maxkids, optarg ) != 0 ) {
187 case 'l': /* the number of loops per client */
188 loops = strdup( optarg );
191 case 'P': /* prog directory */
192 progdir = strdup( optarg );
195 case 'p': /* the servers port number */
196 port = strdup( optarg );
199 case 'r': /* the number of retries in case of error */
200 retries = strdup( optarg );
203 case 't': /* the delay in seconds between each retry */
204 delay = strdup( optarg );
207 case 'w': /* the managers passwd */
208 passwd = ArgDup( optarg );
217 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
218 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
222 children = malloc( maxkids * sizeof(HANDLE) );
224 /* get the file list */
225 if ( ( datadir = opendir( dirname )) == NULL ) {
227 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
229 exit( EXIT_FAILURE );
233 /* look for search, read, modrdn, and add/delete files */
234 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
236 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
237 sfile = get_file_name( dirname, file->d_name );
239 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
240 rfile = get_file_name( dirname, file->d_name );
242 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
243 mfile = get_file_name( dirname, file->d_name );
245 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
246 modfile = get_file_name( dirname, file->d_name );
248 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
249 && ( anum < MAXREQS )) {
250 afiles[anum++] = get_file_name( dirname, file->d_name );
252 } else if ( !strcasecmp( file->d_name, TBINDFILE )) {
253 bfile = get_file_name( dirname, file->d_name );
260 /* look for search requests */
262 snum = get_search_filters( sfile, sreqs, sbase );
265 /* look for read requests */
267 rnum = get_read_entries( rfile, rreqs );
270 /* look for modrdn requests */
272 mnum = get_read_entries( mfile, mreqs );
275 /* look for modify requests */
277 modnum = get_search_filters( modfile, modreqs, moddn );
280 /* look for bind requests */
282 bnum = get_search_filters( bfile, bcreds, breqs );
286 * generate the search clients
290 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
292 sargs[sanum++] = scmd;
294 sargs[sanum++] = "-H";
295 sargs[sanum++] = uri;
297 sargs[sanum++] = "-h";
298 sargs[sanum++] = host;
299 sargs[sanum++] = "-p";
300 sargs[sanum++] = port;
302 sargs[sanum++] = "-D";
303 sargs[sanum++] = manager;
304 sargs[sanum++] = "-w";
305 sargs[sanum++] = passwd;
306 sargs[sanum++] = "-l";
307 sargs[sanum++] = loops;
308 sargs[sanum++] = "-r";
309 sargs[sanum++] = retries;
310 sargs[sanum++] = "-t";
311 sargs[sanum++] = delay;
312 sargs[sanum++] = "-b";
313 sargs[sanum++] = NULL; /* will hold the search base */
314 sargs[sanum++] = "-f";
315 sargs[sanum++] = NULL; /* will hold the search request */
316 sargs[sanum++] = NULL;
319 * generate the read clients
323 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
325 rargs[ranum++] = rcmd;
327 rargs[ranum++] = "-H";
328 rargs[ranum++] = uri;
330 rargs[ranum++] = "-h";
331 rargs[ranum++] = host;
332 rargs[ranum++] = "-p";
333 rargs[ranum++] = port;
335 rargs[ranum++] = "-l";
336 rargs[ranum++] = loops;
337 rargs[ranum++] = "-r";
338 rargs[ranum++] = retries;
339 rargs[ranum++] = "-t";
340 rargs[ranum++] = delay;
341 rargs[ranum++] = "-e";
342 rargs[ranum++] = NULL; /* will hold the read entry */
343 rargs[ranum++] = NULL;
346 * generate the modrdn clients
350 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
352 margs[manum++] = mcmd;
354 margs[manum++] = "-H";
355 margs[manum++] = uri;
357 margs[manum++] = "-h";
358 margs[manum++] = host;
359 margs[manum++] = "-p";
360 margs[manum++] = port;
362 margs[manum++] = "-D";
363 margs[manum++] = manager;
364 margs[manum++] = "-w";
365 margs[manum++] = passwd;
366 margs[manum++] = "-l";
367 margs[manum++] = loops;
368 margs[manum++] = "-r";
369 margs[manum++] = retries;
370 margs[manum++] = "-t";
371 margs[manum++] = delay;
373 margs[manum++] = "-F";
375 margs[manum++] = "-e";
376 margs[manum++] = NULL; /* will hold the modrdn entry */
377 margs[manum++] = NULL;
380 * generate the modify clients
384 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
386 modargs[modanum++] = modcmd;
388 modargs[modanum++] = "-H";
389 modargs[modanum++] = uri;
391 modargs[modanum++] = "-h";
392 modargs[modanum++] = host;
393 modargs[modanum++] = "-p";
394 modargs[modanum++] = port;
396 modargs[modanum++] = "-D";
397 modargs[modanum++] = manager;
398 modargs[modanum++] = "-w";
399 modargs[modanum++] = passwd;
400 modargs[modanum++] = "-l";
401 modargs[modanum++] = loops;
402 modargs[modanum++] = "-r";
403 modargs[modanum++] = retries;
404 modargs[modanum++] = "-t";
405 modargs[modanum++] = delay;
407 modargs[modanum++] = "-F";
409 modargs[modanum++] = "-e";
410 modargs[modanum++] = NULL; /* will hold the modify entry */
411 modargs[modanum++] = "-a";;
412 modargs[modanum++] = NULL; /* will hold the ava */
413 modargs[modanum++] = NULL;
416 * generate the add/delete clients
420 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
422 aargs[aanum++] = acmd;
424 aargs[aanum++] = "-H";
425 aargs[aanum++] = uri;
427 aargs[aanum++] = "-h";
428 aargs[aanum++] = host;
429 aargs[aanum++] = "-p";
430 aargs[aanum++] = port;
432 aargs[aanum++] = "-D";
433 aargs[aanum++] = manager;
434 aargs[aanum++] = "-w";
435 aargs[aanum++] = passwd;
436 aargs[aanum++] = "-l";
437 aargs[aanum++] = loops;
438 aargs[aanum++] = "-r";
439 aargs[aanum++] = retries;
440 aargs[aanum++] = "-t";
441 aargs[aanum++] = delay;
443 aargs[aanum++] = "-F";
445 aargs[aanum++] = "-f";
446 aargs[aanum++] = NULL; /* will hold the add data file */
447 aargs[aanum++] = NULL;
450 * generate the bind clients
454 snprintf( bcmd, sizeof bcmd, "%s" LDAP_DIRSEP BINDCMD,
456 bargs[banum++] = bcmd;
458 bargs[banum++] = "-H";
459 bargs[banum++] = uri;
461 bargs[banum++] = "-h";
462 bargs[banum++] = host;
463 bargs[banum++] = "-p";
464 bargs[banum++] = port;
466 bargs[banum++] = "-l";
467 bargs[banum++] = loops;
469 bargs[banum++] = "-r";
470 bargs[banum++] = retries;
471 bargs[banum++] = "-t";
472 bargs[banum++] = delay;
475 bargs[banum++] = "-F";
477 bargs[banum++] = "-D";
478 bargs[banum++] = NULL;
479 bargs[banum++] = "-w";
480 bargs[banum++] = NULL;
481 bargs[banum++] = NULL;
483 for ( j = 0; j < MAXREQS; j++ ) {
486 sargs[sanum - 2] = sreqs[j];
487 sargs[sanum - 4] = sbase[j];
488 fork_child( scmd, sargs );
494 rargs[ranum - 2] = rreqs[j];
495 fork_child( rcmd, rargs );
501 margs[manum - 2] = mreqs[j];
502 fork_child( mcmd, margs );
507 modargs[modanum - 4] = moddn[j];
508 modargs[modanum - 2] = modreqs[j];
509 fork_child( modcmd, modargs );
515 aargs[aanum - 2] = afiles[j];
516 fork_child( acmd, aargs );
522 bargs[banum - 4] = breqs[j];
523 bargs[banum - 2] = bcreds[j];
524 fork_child( bcmd, bargs );
532 exit( EXIT_SUCCESS );
536 get_file_name( char *dirname, char *filename )
538 char buf[MAXPATHLEN];
540 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
542 return( strdup( buf ));
547 get_search_filters( char *filename, char *filters[], char *bases[] )
552 if ( (fp = fopen( filename, "r" )) != NULL ) {
555 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
558 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
560 bases[filter] = ArgDup( line );
561 fgets( line, BUFSIZ, fp );
562 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
565 filters[filter++] = ArgDup( line );
576 get_read_entries( char *filename, char *entries[] )
581 if ( (fp = fopen( filename, "r" )) != NULL ) {
584 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
587 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
589 entries[entry++] = ArgDup( line );
600 fork_child( char *prog, char **args )
604 wait4kids( maxkids );
606 switch ( pid = fork() ) {
609 /* The __LIBASCII execvp only handles ASCII "prog",
610 * we still need to translate the arg vec ourselves.
612 { char *arg2[MAXREQS];
615 for (i=0; args[i]; i++) {
616 arg2[i] = ArgDup(args[i]);
622 execvp( prog, args );
623 tester_perror( "execvp" );
624 exit( EXIT_FAILURE );
627 case -1: /* trouble */
628 tester_perror( "fork" );
631 default: /* parent */
638 wait4kids( int nkidval )
642 while ( nkids >= nkidval ) {
645 if ( WIFSTOPPED(status) ) {
647 "stopping: child stopped with signal %d\n",
648 (int) WSTOPSIG(status) );
650 } else if ( WIFSIGNALED(status) ) {
652 "stopping: child terminated with signal %d%s\n",
653 (int) WTERMSIG(status),
655 WCOREDUMP(status) ? ", core dumped" : ""
660 exit( WEXITSTATUS(status) );
662 } else if ( WEXITSTATUS(status) != 0 ) {
664 "stopping: child exited with status %d\n",
665 (int) WEXITSTATUS(status) );
666 exit( WEXITSTATUS(status) );
676 wait4kids( int nkidval )
680 while ( nkids >= nkidval ) {
681 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
682 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
683 children[i] = children[i+1];
689 fork_child( char *prog, char **args )
693 wait4kids( maxkids );
695 rc = _spawnvp( _P_NOWAIT, prog, args );
698 tester_perror( "_spawnvp" );
700 children[nkids++] = (HANDLE)rc;