2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2005 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"
38 #define SEARCHCMD "slapd-search"
39 #define READCMD "slapd-read"
40 #define ADDCMD "slapd-addel"
41 #define MODRDNCMD "slapd-modrdn"
42 #define MODIFYCMD "slapd-modify"
48 #define TSEARCHFILE "do_search.0"
49 #define TREADFILE "do_read.0"
50 #define TADDFILE "do_add."
51 #define TMODRDNFILE "do_modrdn.0"
52 #define TMODIFYFILE "do_modify.0"
54 static char *get_file_name( char *dirname, char *filename );
55 static int get_search_filters( char *filename, char *filters[], char *bases[] );
56 static int get_read_entries( char *filename, char *entries[] );
57 static void fork_child( char *prog, char **args );
58 static void wait4kids( int nkidval );
60 static int maxkids = 20;
64 static HANDLE *children;
65 static char argbuf[BUFSIZ];
66 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
68 #define ArgDup(x) strdup(x)
76 "-H <uri> | ([-h <host>] -p <port>) "
91 main( int argc, char **argv )
95 char *host = "localhost";
100 char *progdir = NULL;
102 char *retries = RETRIES;
107 char *sreqs[MAXREQS];
108 char *sbase[MAXREQS];
111 char *rreqs[MAXREQS];
113 char *afiles[MAXREQS];
116 char *mreqs[MAXREQS];
118 char *sargs[MAXARGS];
120 char scmd[MAXPATHLEN];
121 char *rargs[MAXARGS];
123 char rcmd[MAXPATHLEN];
124 char *aargs[MAXARGS];
126 char acmd[MAXPATHLEN];
127 char *margs[MAXARGS];
129 char mcmd[MAXPATHLEN];
130 char *modargs[MAXARGS];
132 char modcmd[MAXPATHLEN];
133 char *modfile = NULL;
134 char *modreqs[MAXREQS];
135 char *moddn[MAXREQS];
139 while ( (i = getopt( argc, argv, "D:d:FH:h:j:l:P:p:r:t:w:" )) != EOF ) {
141 case 'D': /* slapd manager */
142 manager = ArgDup( optarg );
145 case 'd': /* data directory */
146 dirname = strdup( optarg );
153 case 'H': /* slapd uri */
154 uri = strdup( optarg );
157 case 'h': /* slapd host */
158 host = strdup( optarg );
161 case 'j': /* the number of parallel clients */
162 maxkids = atoi( optarg );
165 case 'l': /* the number of loops per client */
166 loops = strdup( optarg );
169 case 'P': /* prog directory */
170 progdir = strdup( optarg );
173 case 'p': /* the servers port number */
174 port = strdup( optarg );
177 case 'r': /* the number of retries in case of error */
178 retries = strdup( optarg );
181 case 't': /* the delay in seconds between each retry */
182 delay = strdup( optarg );
185 case 'w': /* the managers passwd */
186 passwd = ArgDup( optarg );
195 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
196 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
200 children = malloc( maxkids * sizeof(HANDLE) );
202 /* get the file list */
203 if ( ( datadir = opendir( dirname )) == NULL ) {
205 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
207 exit( EXIT_FAILURE );
211 /* look for search, read, modrdn, and add/delete files */
212 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
214 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
215 sfile = get_file_name( dirname, file->d_name );
217 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
218 rfile = get_file_name( dirname, file->d_name );
220 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
221 mfile = get_file_name( dirname, file->d_name );
223 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
224 modfile = get_file_name( dirname, file->d_name );
226 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
227 && ( anum < MAXREQS )) {
228 afiles[anum++] = get_file_name( dirname, file->d_name );
235 /* look for search requests */
237 snum = get_search_filters( sfile, sreqs, sbase );
240 /* look for read requests */
242 rnum = get_read_entries( rfile, rreqs );
245 /* look for modrdn requests */
247 mnum = get_read_entries( mfile, mreqs );
249 /* look for modify requests */
251 modnum = get_search_filters( modfile, modreqs, moddn );
255 * generate the search clients
259 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
261 sargs[sanum++] = scmd;
263 sargs[sanum++] = "-H";
264 sargs[sanum++] = uri;
266 sargs[sanum++] = "-h";
267 sargs[sanum++] = host;
268 sargs[sanum++] = "-p";
269 sargs[sanum++] = port;
271 sargs[sanum++] = "-D";
272 sargs[sanum++] = manager;
273 sargs[sanum++] = "-w";
274 sargs[sanum++] = passwd;
275 sargs[sanum++] = "-l";
276 sargs[sanum++] = loops;
277 sargs[sanum++] = "-r";
278 sargs[sanum++] = retries;
279 sargs[sanum++] = "-t";
280 sargs[sanum++] = delay;
281 sargs[sanum++] = "-b";
282 sargs[sanum++] = NULL; /* will hold the search base */
283 sargs[sanum++] = "-f";
284 sargs[sanum++] = NULL; /* will hold the search request */
285 sargs[sanum++] = NULL;
288 * generate the read clients
292 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
294 rargs[ranum++] = rcmd;
296 rargs[ranum++] = "-H";
297 rargs[ranum++] = uri;
299 rargs[ranum++] = "-h";
300 rargs[ranum++] = host;
301 rargs[ranum++] = "-p";
302 rargs[ranum++] = port;
304 rargs[ranum++] = "-l";
305 rargs[ranum++] = loops;
306 rargs[ranum++] = "-r";
307 rargs[ranum++] = retries;
308 rargs[ranum++] = "-t";
309 rargs[ranum++] = delay;
310 rargs[ranum++] = "-e";
311 rargs[ranum++] = NULL; /* will hold the read entry */
312 rargs[ranum++] = NULL;
315 * generate the modrdn clients
319 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
321 margs[manum++] = mcmd;
323 margs[manum++] = "-H";
324 margs[manum++] = uri;
326 margs[manum++] = "-h";
327 margs[manum++] = host;
328 margs[manum++] = "-p";
329 margs[manum++] = port;
331 margs[manum++] = "-D";
332 margs[manum++] = manager;
333 margs[manum++] = "-w";
334 margs[manum++] = passwd;
335 margs[manum++] = "-l";
336 margs[manum++] = loops;
337 margs[manum++] = "-r";
338 margs[manum++] = retries;
339 margs[manum++] = "-t";
340 margs[manum++] = delay;
342 margs[manum++] = "-F";
344 margs[manum++] = "-e";
345 margs[manum++] = NULL; /* will hold the modrdn entry */
346 margs[manum++] = NULL;
349 * generate the modify clients
353 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
355 modargs[modanum++] = modcmd;
357 modargs[modanum++] = "-H";
358 modargs[modanum++] = uri;
360 modargs[modanum++] = "-h";
361 modargs[modanum++] = host;
362 modargs[modanum++] = "-p";
363 modargs[modanum++] = port;
365 modargs[modanum++] = "-D";
366 modargs[modanum++] = manager;
367 modargs[modanum++] = "-w";
368 modargs[modanum++] = passwd;
369 modargs[modanum++] = "-l";
370 modargs[modanum++] = loops;
371 modargs[modanum++] = "-r";
372 modargs[modanum++] = retries;
373 modargs[modanum++] = "-t";
374 modargs[modanum++] = delay;
376 modargs[modanum++] = "-F";
378 modargs[modanum++] = "-e";
379 modargs[modanum++] = NULL; /* will hold the modify entry */
380 modargs[modanum++] = "-a";;
381 modargs[modanum++] = NULL; /* will hold the ava */
382 modargs[modanum++] = NULL;
385 * generate the add/delete clients
389 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
391 aargs[aanum++] = acmd;
393 aargs[aanum++] = "-H";
394 aargs[aanum++] = uri;
396 aargs[aanum++] = "-h";
397 aargs[aanum++] = host;
398 aargs[aanum++] = "-p";
399 aargs[aanum++] = port;
401 aargs[aanum++] = "-D";
402 aargs[aanum++] = manager;
403 aargs[aanum++] = "-w";
404 aargs[aanum++] = passwd;
405 aargs[aanum++] = "-l";
406 aargs[aanum++] = loops;
407 aargs[aanum++] = "-r";
408 aargs[aanum++] = retries;
409 aargs[aanum++] = "-t";
410 aargs[aanum++] = delay;
412 aargs[aanum++] = "-F";
414 aargs[aanum++] = "-f";
415 aargs[aanum++] = NULL; /* will hold the add data file */
416 aargs[aanum++] = NULL;
418 for ( j = 0; j < MAXREQS; j++ ) {
422 sargs[sanum - 2] = sreqs[j];
423 sargs[sanum - 4] = sbase[j];
424 fork_child( scmd, sargs );
430 rargs[ranum - 2] = rreqs[j];
431 fork_child( rcmd, rargs );
437 margs[manum - 2] = mreqs[j];
438 fork_child( mcmd, margs );
443 modargs[modanum - 4] = moddn[j];
444 modargs[modanum - 2] = modreqs[j];
445 fork_child( modcmd, modargs );
451 aargs[aanum - 2] = afiles[j];
452 fork_child( acmd, aargs );
460 exit( EXIT_SUCCESS );
464 get_file_name( char *dirname, char *filename )
466 char buf[MAXPATHLEN];
468 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
470 return( strdup( buf ));
475 get_search_filters( char *filename, char *filters[], char *bases[] )
480 if ( (fp = fopen( filename, "r" )) != NULL ) {
483 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
486 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
488 bases[filter] = ArgDup( line );
489 fgets( line, BUFSIZ, fp );
490 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
493 filters[filter++] = ArgDup( line );
504 get_read_entries( char *filename, char *entries[] )
509 if ( (fp = fopen( filename, "r" )) != NULL ) {
512 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
515 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
517 entries[entry++] = ArgDup( line );
528 fork_child( char *prog, char **args )
532 wait4kids( maxkids );
534 switch ( pid = fork() ) {
537 /* The __LIBASCII execvp only handles ASCII "prog",
538 * we still need to translate the arg vec ourselves.
540 { char *arg2[MAXREQS];
543 for (i=0; args[i]; i++) {
544 arg2[i] = ArgDup(args[i]);
550 execvp( prog, args );
551 fprintf( stderr, "%s: ", prog );
553 exit( EXIT_FAILURE );
556 case -1: /* trouble */
557 fprintf( stderr, "Could not fork to run %s\n", prog );
561 default: /* parent */
568 wait4kids( int nkidval )
572 while ( nkids >= nkidval ) {
575 if ( WIFSTOPPED(status) ) {
577 "stopping: child stopped with signal %d\n",
578 (int) WSTOPSIG(status) );
580 } else if ( WIFSIGNALED(status) ) {
582 "stopping: child terminated with signal %d%s\n",
583 (int) WTERMSIG(status),
585 WCOREDUMP(status) ? ", core dumped" : ""
590 exit( WEXITSTATUS(status) );
592 } else if ( WEXITSTATUS(status) != 0 ) {
594 "stopping: child exited with status %d\n",
595 (int) WEXITSTATUS(status) );
596 exit( WEXITSTATUS(status) );
606 wait4kids( int nkidval )
610 while ( nkids >= nkidval ) {
611 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
612 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
613 children[i] = children[i+1];
619 fork_child( char *prog, char **args )
623 wait4kids( maxkids );
625 rc = _spawnvp( _P_NOWAIT, prog, args );
628 fprintf( stderr, "%s: ", prog );
631 children[nkids++] = (HANDLE)rc;