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 #define SEARCHCMD "slapd-search"
40 #define READCMD "slapd-read"
41 #define ADDCMD "slapd-addel"
42 #define MODRDNCMD "slapd-modrdn"
43 #define MODIFYCMD "slapd-modify"
44 #define BINDCMD "slapd-bind"
50 #define TSEARCHFILE "do_search.0"
51 #define TREADFILE "do_read.0"
52 #define TADDFILE "do_add."
53 #define TMODRDNFILE "do_modrdn.0"
54 #define TMODIFYFILE "do_modify.0"
55 #define TBINDFILE "do_bind.0"
57 static char *get_file_name( char *dirname, char *filename );
58 static int get_search_filters( char *filename, char *filters[], char *bases[] );
59 static int get_read_entries( char *filename, char *entries[] );
60 static void fork_child( char *prog, char **args );
61 static void wait4kids( int nkidval );
63 static int maxkids = 20;
67 static HANDLE *children;
68 static char argbuf[BUFSIZ];
69 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
71 #define ArgDup(x) strdup(x)
79 "-H <uri> | ([-h <host>] -p <port>) "
94 main( int argc, char **argv )
98 char *host = "localhost";
100 char *manager = NULL;
102 char *dirname = NULL;
103 char *progdir = NULL;
105 char *retries = RETRIES;
112 char *sreqs[MAXREQS];
113 char *sbase[MAXREQS];
115 char *sargs[MAXARGS];
117 char scmd[MAXPATHLEN];
120 char *rreqs[MAXREQS];
122 char *rargs[MAXARGS];
124 char rcmd[MAXPATHLEN];
126 char *afiles[MAXREQS];
128 char *aargs[MAXARGS];
130 char acmd[MAXPATHLEN];
133 char *mreqs[MAXREQS];
135 char *margs[MAXARGS];
137 char mcmd[MAXPATHLEN];
139 char *modfile = NULL;
140 char *modreqs[MAXREQS];
141 char *moddn[MAXREQS];
143 char *modargs[MAXARGS];
145 char modcmd[MAXPATHLEN];
148 char *breqs[MAXREQS];
149 char *bcreds[MAXREQS];
151 char *bargs[MAXARGS];
153 char bcmd[MAXPATHLEN];
155 while ( (i = getopt( argc, argv, "D:d:FH:h:j:l:P:p:r:t:w:" )) != EOF ) {
157 case 'D': /* slapd manager */
158 manager = ArgDup( optarg );
161 case 'd': /* data directory */
162 dirname = strdup( optarg );
169 case 'H': /* slapd uri */
170 uri = strdup( optarg );
173 case 'h': /* slapd host */
174 host = strdup( optarg );
177 case 'j': /* the number of parallel clients */
178 if ( lutil_atoi( &maxkids, optarg ) != 0 ) {
183 case 'l': /* the number of loops per client */
184 loops = strdup( optarg );
187 case 'P': /* prog directory */
188 progdir = strdup( optarg );
191 case 'p': /* the servers port number */
192 port = strdup( optarg );
195 case 'r': /* the number of retries in case of error */
196 retries = strdup( optarg );
199 case 't': /* the delay in seconds between each retry */
200 delay = strdup( optarg );
203 case 'w': /* the managers passwd */
204 passwd = ArgDup( optarg );
213 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
214 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
218 children = malloc( maxkids * sizeof(HANDLE) );
220 /* get the file list */
221 if ( ( datadir = opendir( dirname )) == NULL ) {
223 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
225 exit( EXIT_FAILURE );
229 /* look for search, read, modrdn, and add/delete files */
230 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
232 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
233 sfile = get_file_name( dirname, file->d_name );
235 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
236 rfile = get_file_name( dirname, file->d_name );
238 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
239 mfile = get_file_name( dirname, file->d_name );
241 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
242 modfile = get_file_name( dirname, file->d_name );
244 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
245 && ( anum < MAXREQS )) {
246 afiles[anum++] = get_file_name( dirname, file->d_name );
248 } else if ( !strcasecmp( file->d_name, TBINDFILE )) {
249 bfile = get_file_name( dirname, file->d_name );
256 /* look for search requests */
258 snum = get_search_filters( sfile, sreqs, sbase );
261 /* look for read requests */
263 rnum = get_read_entries( rfile, rreqs );
266 /* look for modrdn requests */
268 mnum = get_read_entries( mfile, mreqs );
271 /* look for modify requests */
273 modnum = get_search_filters( modfile, modreqs, moddn );
276 /* look for bind requests */
278 bnum = get_search_filters( bfile, bcreds, breqs );
282 * generate the search clients
286 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
288 sargs[sanum++] = scmd;
290 sargs[sanum++] = "-H";
291 sargs[sanum++] = uri;
293 sargs[sanum++] = "-h";
294 sargs[sanum++] = host;
295 sargs[sanum++] = "-p";
296 sargs[sanum++] = port;
298 sargs[sanum++] = "-D";
299 sargs[sanum++] = manager;
300 sargs[sanum++] = "-w";
301 sargs[sanum++] = passwd;
302 sargs[sanum++] = "-l";
303 sargs[sanum++] = loops;
304 sargs[sanum++] = "-r";
305 sargs[sanum++] = retries;
306 sargs[sanum++] = "-t";
307 sargs[sanum++] = delay;
308 sargs[sanum++] = "-b";
309 sargs[sanum++] = NULL; /* will hold the search base */
310 sargs[sanum++] = "-f";
311 sargs[sanum++] = NULL; /* will hold the search request */
312 sargs[sanum++] = NULL;
315 * generate the read clients
319 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
321 rargs[ranum++] = rcmd;
323 rargs[ranum++] = "-H";
324 rargs[ranum++] = uri;
326 rargs[ranum++] = "-h";
327 rargs[ranum++] = host;
328 rargs[ranum++] = "-p";
329 rargs[ranum++] = port;
331 rargs[ranum++] = "-l";
332 rargs[ranum++] = loops;
333 rargs[ranum++] = "-r";
334 rargs[ranum++] = retries;
335 rargs[ranum++] = "-t";
336 rargs[ranum++] = delay;
337 rargs[ranum++] = "-e";
338 rargs[ranum++] = NULL; /* will hold the read entry */
339 rargs[ranum++] = NULL;
342 * generate the modrdn clients
346 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
348 margs[manum++] = mcmd;
350 margs[manum++] = "-H";
351 margs[manum++] = uri;
353 margs[manum++] = "-h";
354 margs[manum++] = host;
355 margs[manum++] = "-p";
356 margs[manum++] = port;
358 margs[manum++] = "-D";
359 margs[manum++] = manager;
360 margs[manum++] = "-w";
361 margs[manum++] = passwd;
362 margs[manum++] = "-l";
363 margs[manum++] = loops;
364 margs[manum++] = "-r";
365 margs[manum++] = retries;
366 margs[manum++] = "-t";
367 margs[manum++] = delay;
369 margs[manum++] = "-F";
371 margs[manum++] = "-e";
372 margs[manum++] = NULL; /* will hold the modrdn entry */
373 margs[manum++] = NULL;
376 * generate the modify clients
380 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
382 modargs[modanum++] = modcmd;
384 modargs[modanum++] = "-H";
385 modargs[modanum++] = uri;
387 modargs[modanum++] = "-h";
388 modargs[modanum++] = host;
389 modargs[modanum++] = "-p";
390 modargs[modanum++] = port;
392 modargs[modanum++] = "-D";
393 modargs[modanum++] = manager;
394 modargs[modanum++] = "-w";
395 modargs[modanum++] = passwd;
396 modargs[modanum++] = "-l";
397 modargs[modanum++] = loops;
398 modargs[modanum++] = "-r";
399 modargs[modanum++] = retries;
400 modargs[modanum++] = "-t";
401 modargs[modanum++] = delay;
403 modargs[modanum++] = "-F";
405 modargs[modanum++] = "-e";
406 modargs[modanum++] = NULL; /* will hold the modify entry */
407 modargs[modanum++] = "-a";;
408 modargs[modanum++] = NULL; /* will hold the ava */
409 modargs[modanum++] = NULL;
412 * generate the add/delete clients
416 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
418 aargs[aanum++] = acmd;
420 aargs[aanum++] = "-H";
421 aargs[aanum++] = uri;
423 aargs[aanum++] = "-h";
424 aargs[aanum++] = host;
425 aargs[aanum++] = "-p";
426 aargs[aanum++] = port;
428 aargs[aanum++] = "-D";
429 aargs[aanum++] = manager;
430 aargs[aanum++] = "-w";
431 aargs[aanum++] = passwd;
432 aargs[aanum++] = "-l";
433 aargs[aanum++] = loops;
434 aargs[aanum++] = "-r";
435 aargs[aanum++] = retries;
436 aargs[aanum++] = "-t";
437 aargs[aanum++] = delay;
439 aargs[aanum++] = "-F";
441 aargs[aanum++] = "-f";
442 aargs[aanum++] = NULL; /* will hold the add data file */
443 aargs[aanum++] = NULL;
446 * generate the bind clients
450 snprintf( bcmd, sizeof bcmd, "%s" LDAP_DIRSEP BINDCMD,
452 bargs[banum++] = bcmd;
454 bargs[banum++] = "-H";
455 bargs[banum++] = uri;
457 bargs[banum++] = "-h";
458 bargs[banum++] = host;
459 bargs[banum++] = "-p";
460 bargs[banum++] = port;
462 bargs[banum++] = "-l";
463 bargs[banum++] = loops;
465 bargs[banum++] = "-r";
466 bargs[banum++] = retries;
467 bargs[banum++] = "-t";
468 bargs[banum++] = delay;
471 bargs[banum++] = "-F";
473 bargs[banum++] = "-D";
474 bargs[banum++] = NULL;
475 bargs[banum++] = "-w";
476 bargs[banum++] = NULL;
477 bargs[banum++] = NULL;
479 for ( j = 0; j < MAXREQS; j++ ) {
482 sargs[sanum - 2] = sreqs[j];
483 sargs[sanum - 4] = sbase[j];
484 fork_child( scmd, sargs );
490 rargs[ranum - 2] = rreqs[j];
491 fork_child( rcmd, rargs );
497 margs[manum - 2] = mreqs[j];
498 fork_child( mcmd, margs );
503 modargs[modanum - 4] = moddn[j];
504 modargs[modanum - 2] = modreqs[j];
505 fork_child( modcmd, modargs );
511 aargs[aanum - 2] = afiles[j];
512 fork_child( acmd, aargs );
518 bargs[banum - 4] = breqs[j];
519 bargs[banum - 2] = bcreds[j];
520 fork_child( bcmd, bargs );
528 exit( EXIT_SUCCESS );
532 get_file_name( char *dirname, char *filename )
534 char buf[MAXPATHLEN];
536 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
538 return( strdup( buf ));
543 get_search_filters( char *filename, char *filters[], char *bases[] )
548 if ( (fp = fopen( filename, "r" )) != NULL ) {
551 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
554 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
556 bases[filter] = ArgDup( line );
557 fgets( line, BUFSIZ, fp );
558 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
561 filters[filter++] = ArgDup( line );
572 get_read_entries( char *filename, char *entries[] )
577 if ( (fp = fopen( filename, "r" )) != NULL ) {
580 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
583 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
585 entries[entry++] = ArgDup( line );
596 fork_child( char *prog, char **args )
600 wait4kids( maxkids );
602 switch ( pid = fork() ) {
605 /* The __LIBASCII execvp only handles ASCII "prog",
606 * we still need to translate the arg vec ourselves.
608 { char *arg2[MAXREQS];
611 for (i=0; args[i]; i++) {
612 arg2[i] = ArgDup(args[i]);
618 execvp( prog, args );
619 fprintf( stderr, "%s: ", prog );
621 exit( EXIT_FAILURE );
624 case -1: /* trouble */
625 fprintf( stderr, "Could not fork to run %s\n", prog );
629 default: /* parent */
636 wait4kids( int nkidval )
640 while ( nkids >= nkidval ) {
643 if ( WIFSTOPPED(status) ) {
645 "stopping: child stopped with signal %d\n",
646 (int) WSTOPSIG(status) );
648 } else if ( WIFSIGNALED(status) ) {
650 "stopping: child terminated with signal %d%s\n",
651 (int) WTERMSIG(status),
653 WCOREDUMP(status) ? ", core dumped" : ""
658 exit( WEXITSTATUS(status) );
660 } else if ( WEXITSTATUS(status) != 0 ) {
662 "stopping: child exited with status %d\n",
663 (int) WEXITSTATUS(status) );
664 exit( WEXITSTATUS(status) );
674 wait4kids( int nkidval )
678 while ( nkids >= nkidval ) {
679 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
680 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
681 children[i] = children[i+1];
687 fork_child( char *prog, char **args )
691 wait4kids( maxkids );
693 rc = _spawnvp( _P_NOWAIT, prog, args );
696 fprintf( stderr, "%s: ", prog );
699 children[nkids++] = (HANDLE)rc;