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>) "
90 main( int argc, char **argv )
94 char *host = "localhost";
101 char *retries = RETRIES;
106 char *sreqs[MAXREQS];
107 char *sbase[MAXREQS];
110 char *rreqs[MAXREQS];
112 char *afiles[MAXREQS];
115 char *mreqs[MAXREQS];
117 char *sargs[MAXARGS];
119 char scmd[MAXPATHLEN];
120 char *rargs[MAXARGS];
122 char rcmd[MAXPATHLEN];
123 char *aargs[MAXARGS];
125 char acmd[MAXPATHLEN];
126 char *margs[MAXARGS];
128 char mcmd[MAXPATHLEN];
129 char *modargs[MAXARGS];
131 char modcmd[MAXPATHLEN];
132 char *modfile = NULL;
133 char *modreqs[MAXREQS];
134 char *moddn[MAXREQS];
137 while ( (i = getopt( argc, argv, "D:d:H:h:j:l:P:p:r:t:w:" )) != EOF ) {
139 case 'D': /* slapd manager */
140 manager = ArgDup( optarg );
143 case 'd': /* data directory */
144 dirname = strdup( optarg );
147 case 'H': /* slapd uri */
148 uri = strdup( optarg );
151 case 'h': /* slapd host */
152 host = strdup( optarg );
155 case 'j': /* the number of parallel clients */
156 maxkids = atoi( optarg );
159 case 'l': /* the number of loops per client */
160 loops = strdup( optarg );
163 case 'P': /* prog directory */
164 progdir = strdup( optarg );
167 case 'p': /* the servers port number */
168 port = strdup( optarg );
171 case 'r': /* the number of retries in case of error */
172 retries = strdup( optarg );
175 case 't': /* the delay in seconds between each retry */
176 delay = strdup( optarg );
179 case 'w': /* the managers passwd */
180 passwd = ArgDup( optarg );
189 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
190 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
194 children = malloc( maxkids * sizeof(HANDLE) );
196 /* get the file list */
197 if ( ( datadir = opendir( dirname )) == NULL ) {
199 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
201 exit( EXIT_FAILURE );
205 /* look for search, read, modrdn, and add/delete files */
206 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
208 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
209 sfile = get_file_name( dirname, file->d_name );
211 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
212 rfile = get_file_name( dirname, file->d_name );
214 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
215 mfile = get_file_name( dirname, file->d_name );
217 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
218 modfile = get_file_name( dirname, file->d_name );
220 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
221 && ( anum < MAXREQS )) {
222 afiles[anum++] = get_file_name( dirname, file->d_name );
229 /* look for search requests */
231 snum = get_search_filters( sfile, sreqs, sbase );
234 /* look for read requests */
236 rnum = get_read_entries( rfile, rreqs );
239 /* look for modrdn requests */
241 mnum = get_read_entries( mfile, mreqs );
243 /* look for modify requests */
245 modnum = get_search_filters( modfile, modreqs, moddn );
249 * generate the search clients
253 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
255 sargs[sanum++] = scmd;
257 sargs[sanum++] = "-H";
258 sargs[sanum++] = uri;
260 sargs[sanum++] = "-h";
261 sargs[sanum++] = host;
262 sargs[sanum++] = "-p";
263 sargs[sanum++] = port;
265 sargs[sanum++] = "-D";
266 sargs[sanum++] = manager;
267 sargs[sanum++] = "-w";
268 sargs[sanum++] = passwd;
269 sargs[sanum++] = "-l";
270 sargs[sanum++] = loops;
271 sargs[sanum++] = "-r";
272 sargs[sanum++] = retries;
273 sargs[sanum++] = "-t";
274 sargs[sanum++] = delay;
275 sargs[sanum++] = "-b";
276 sargs[sanum++] = NULL; /* will hold the search base */
277 sargs[sanum++] = "-f";
278 sargs[sanum++] = NULL; /* will hold the search request */
279 sargs[sanum++] = NULL;
282 * generate the read clients
286 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
288 rargs[ranum++] = rcmd;
290 rargs[ranum++] = "-H";
291 rargs[ranum++] = uri;
293 rargs[ranum++] = "-h";
294 rargs[ranum++] = host;
295 rargs[ranum++] = "-p";
296 rargs[ranum++] = port;
298 rargs[ranum++] = "-l";
299 rargs[ranum++] = loops;
300 rargs[ranum++] = "-r";
301 rargs[ranum++] = retries;
302 rargs[ranum++] = "-t";
303 rargs[ranum++] = delay;
304 rargs[ranum++] = "-e";
305 rargs[ranum++] = NULL; /* will hold the read entry */
306 rargs[ranum++] = NULL;
309 * generate the modrdn clients
313 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
315 margs[manum++] = mcmd;
317 margs[manum++] = "-H";
318 margs[manum++] = uri;
320 margs[manum++] = "-h";
321 margs[manum++] = host;
322 margs[manum++] = "-p";
323 margs[manum++] = port;
325 margs[manum++] = "-D";
326 margs[manum++] = manager;
327 margs[manum++] = "-w";
328 margs[manum++] = passwd;
329 margs[manum++] = "-l";
330 margs[manum++] = loops;
331 margs[manum++] = "-r";
332 margs[manum++] = retries;
333 margs[manum++] = "-t";
334 margs[manum++] = delay;
335 margs[manum++] = "-e";
336 margs[manum++] = NULL; /* will hold the modrdn entry */
337 margs[manum++] = NULL;
340 * generate the modify clients
344 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
346 modargs[modanum++] = modcmd;
348 modargs[modanum++] = "-H";
349 modargs[modanum++] = uri;
351 modargs[modanum++] = "-h";
352 modargs[modanum++] = host;
353 modargs[modanum++] = "-p";
354 modargs[modanum++] = port;
356 modargs[modanum++] = "-D";
357 modargs[modanum++] = manager;
358 modargs[modanum++] = "-w";
359 modargs[modanum++] = passwd;
360 modargs[modanum++] = "-l";
361 modargs[modanum++] = loops;
362 modargs[modanum++] = "-r";
363 modargs[modanum++] = retries;
364 modargs[modanum++] = "-t";
365 modargs[modanum++] = delay;
366 modargs[modanum++] = "-e";
367 modargs[modanum++] = NULL; /* will hold the modify entry */
368 modargs[modanum++] = "-a";;
369 modargs[modanum++] = NULL; /* will hold the ava */
370 modargs[modanum++] = NULL;
373 * generate the add/delete clients
377 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
379 aargs[aanum++] = acmd;
381 aargs[aanum++] = "-H";
382 aargs[aanum++] = uri;
384 aargs[aanum++] = "-h";
385 aargs[aanum++] = host;
386 aargs[aanum++] = "-p";
387 aargs[aanum++] = port;
389 aargs[aanum++] = "-D";
390 aargs[aanum++] = manager;
391 aargs[aanum++] = "-w";
392 aargs[aanum++] = passwd;
393 aargs[aanum++] = "-l";
394 aargs[aanum++] = loops;
395 aargs[aanum++] = "-r";
396 aargs[aanum++] = retries;
397 aargs[aanum++] = "-t";
398 aargs[aanum++] = delay;
399 aargs[aanum++] = "-f";
400 aargs[aanum++] = NULL; /* will hold the add data file */
401 aargs[aanum++] = NULL;
403 for ( j = 0; j < MAXREQS; j++ ) {
407 sargs[sanum - 2] = sreqs[j];
408 sargs[sanum - 4] = sbase[j];
409 fork_child( scmd, sargs );
415 rargs[ranum - 2] = rreqs[j];
416 fork_child( rcmd, rargs );
422 margs[manum - 2] = mreqs[j];
423 fork_child( mcmd, margs );
428 modargs[modanum - 4] = moddn[j];
429 modargs[modanum - 2] = modreqs[j];
430 fork_child( modcmd, modargs );
436 aargs[aanum - 2] = afiles[j];
437 fork_child( acmd, aargs );
445 exit( EXIT_SUCCESS );
449 get_file_name( char *dirname, char *filename )
451 char buf[MAXPATHLEN];
453 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
455 return( strdup( buf ));
460 get_search_filters( char *filename, char *filters[], char *bases[] )
465 if ( (fp = fopen( filename, "r" )) != NULL ) {
468 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
471 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
473 bases[filter] = ArgDup( line );
474 fgets( line, BUFSIZ, fp );
475 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
478 filters[filter++] = ArgDup( line );
489 get_read_entries( char *filename, char *entries[] )
494 if ( (fp = fopen( filename, "r" )) != NULL ) {
497 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
500 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
502 entries[entry++] = ArgDup( line );
513 fork_child( char *prog, char **args )
517 wait4kids( maxkids );
519 switch ( pid = fork() ) {
522 /* The __LIBASCII execvp only handles ASCII "prog",
523 * we still need to translate the arg vec ourselves.
525 { char *arg2[MAXREQS];
528 for (i=0; args[i]; i++) {
529 arg2[i] = ArgDup(args[i]);
535 execvp( prog, args );
536 fprintf( stderr, "%s: ", prog );
538 exit( EXIT_FAILURE );
541 case -1: /* trouble */
542 fprintf( stderr, "Could not fork to run %s\n", prog );
546 default: /* parent */
553 wait4kids( int nkidval )
557 while ( nkids >= nkidval ) {
560 if ( WIFSTOPPED(status) ) {
562 "stopping: child stopped with signal %d\n",
563 (int) WSTOPSIG(status) );
565 } else if ( WIFSIGNALED(status) ) {
567 "stopping: child terminated with signal %d%s\n",
568 (int) WTERMSIG(status),
570 WCOREDUMP(status) ? ", core dumped" : ""
575 exit( WEXITSTATUS(status) );
577 } else if ( WEXITSTATUS(status) != 0 ) {
579 "stopping: child exited with status %d\n",
580 (int) WEXITSTATUS(status) );
581 exit( WEXITSTATUS(status) );
591 wait4kids( int nkidval )
595 while ( nkids >= nkidval ) {
596 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
597 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
598 children[i] = children[i+1];
604 fork_child( char *prog, char **args )
608 wait4kids( maxkids );
610 rc = _spawnvp( _P_NOWAIT, prog, args );
613 fprintf( stderr, "%s: ", prog );
616 children[nkids++] = (HANDLE)rc;