3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
10 #include <ac/stdlib.h>
13 #include <ac/dirent.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
17 #include <ac/unistd.h>
21 #include "ldap_defaults.h"
24 #define SEARCHCMD "slapd-search"
25 #define READCMD "slapd-read"
26 #define ADDCMD "slapd-addel"
27 #define MODRDNCMD "slapd-modrdn"
32 #define TSEARCHFILE "do_search.0"
33 #define TREADFILE "do_read.0"
34 #define TADDFILE "do_add."
35 #define TMODRDNFILE "do_modrdn.0"
37 static char *get_file_name( char *dirname, char *filename );
38 static int get_search_filters( char *filename, char *filters[] );
39 static int get_read_entries( char *filename, char *entries[] );
40 static void fork_child( char *prog, char **args );
41 static void wait4kids( int nkidval );
43 static int maxkids = 20;
47 static HANDLE *children;
48 static char argbuf[BUFSIZ];
49 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
51 #define ArgDup(x) strdup(x)
57 fprintf( stderr, "usage: %s [-h <host>] -p <port> -D <manager> -w <passwd> -d <datadir> -b <baseDN> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
62 main( int argc, char **argv )
66 char *host = "localhost";
82 char *afiles[MAXREQS];
89 char scmd[MAXPATHLEN];
92 char rcmd[MAXPATHLEN];
95 char acmd[MAXPATHLEN];
98 char mcmd[MAXPATHLEN];
100 while ( (i = getopt( argc, argv, "H:h:p:D:w:b:d:j:l:P:" )) != EOF ) {
102 case 'H': /* slapd uri */
103 uri = strdup( optarg );
106 case 'h': /* slapd host */
107 host = strdup( optarg );
110 case 'p': /* the servers port number */
111 port = strdup( optarg );
114 case 'D': /* slapd manager */
115 manager = ArgDup( optarg );
118 case 'w': /* the managers passwd */
119 passwd = ArgDup( optarg );
122 case 'b': /* the base DN */
123 sbase = ArgDup( optarg );
126 case 'd': /* data directory */
127 dirname = strdup( optarg );
130 case 'P': /* prog directory */
131 progdir = strdup( optarg );
134 case 'j': /* the number of parallel clients */
135 maxkids = atoi( optarg );
138 case 'l': /* the number of loops per client */
139 loops = strdup( optarg );
148 if (( dirname == NULL ) || ( sbase == NULL ) || ( port == NULL && uri == NULL ) ||
149 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
153 children = malloc( maxkids * sizeof(HANDLE) );
155 /* get the file list */
156 if ( ( datadir = opendir( dirname )) == NULL ) {
158 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
160 exit( EXIT_FAILURE );
164 /* look for search, read, modrdn, and add/delete files */
165 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
167 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
168 sfile = get_file_name( dirname, file->d_name );
170 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
171 rfile = get_file_name( dirname, file->d_name );
173 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
174 mfile = get_file_name( dirname, file->d_name );
176 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
177 && ( anum < MAXREQS )) {
178 afiles[anum++] = get_file_name( dirname, file->d_name );
185 /* look for search requests */
187 snum = get_search_filters( sfile, sreqs );
190 /* look for read requests */
192 rnum = get_read_entries( rfile, rreqs );
195 /* look for modrdn requests */
197 mnum = get_read_entries( mfile, mreqs );
201 * generate the search clients
205 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
207 sargs[sanum++] = scmd;
209 sargs[sanum++] = "-H";
210 sargs[sanum++] = uri;
212 sargs[sanum++] = "-h";
213 sargs[sanum++] = host;
214 sargs[sanum++] = "-p";
215 sargs[sanum++] = port;
217 sargs[sanum++] = "-b";
218 sargs[sanum++] = sbase;
219 sargs[sanum++] = "-l";
220 sargs[sanum++] = loops;
221 sargs[sanum++] = "-f";
222 sargs[sanum++] = NULL; /* will hold the search request */
223 sargs[sanum++] = NULL;
226 * generate the read clients
230 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
232 rargs[ranum++] = rcmd;
234 rargs[ranum++] = "-H";
235 rargs[ranum++] = uri;
237 rargs[ranum++] = "-h";
238 rargs[ranum++] = host;
239 rargs[ranum++] = "-p";
240 rargs[ranum++] = port;
242 rargs[ranum++] = "-l";
243 rargs[ranum++] = loops;
244 rargs[ranum++] = "-e";
245 rargs[ranum++] = NULL; /* will hold the read entry */
246 rargs[ranum++] = NULL;
249 * generate the modrdn clients
253 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
255 margs[manum++] = mcmd;
257 margs[manum++] = "-H";
258 margs[manum++] = uri;
260 margs[manum++] = "-h";
261 margs[manum++] = host;
262 margs[manum++] = "-p";
263 margs[manum++] = port;
265 margs[manum++] = "-D";
266 margs[manum++] = manager;
267 margs[manum++] = "-w";
268 margs[manum++] = passwd;
269 margs[manum++] = "-l";
270 margs[manum++] = loops;
271 margs[manum++] = "-e";
272 margs[manum++] = NULL; /* will hold the modrdn entry */
273 margs[manum++] = NULL;
276 * generate the add/delete clients
280 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
282 aargs[aanum++] = acmd;
284 aargs[aanum++] = "-H";
285 aargs[aanum++] = uri;
287 aargs[aanum++] = "-h";
288 aargs[aanum++] = host;
289 aargs[aanum++] = "-p";
290 aargs[aanum++] = port;
292 aargs[aanum++] = "-D";
293 aargs[aanum++] = manager;
294 aargs[aanum++] = "-w";
295 aargs[aanum++] = passwd;
296 aargs[aanum++] = "-l";
297 aargs[aanum++] = loops;
298 aargs[aanum++] = "-f";
299 aargs[aanum++] = NULL; /* will hold the add data file */
300 aargs[aanum++] = NULL;
302 for ( j = 0; j < MAXREQS; j++ ) {
306 sargs[sanum - 2] = sreqs[j];
307 fork_child( scmd, sargs );
313 rargs[ranum - 2] = rreqs[j];
314 fork_child( rcmd, rargs );
320 margs[manum - 2] = mreqs[j];
321 fork_child( mcmd, margs );
327 aargs[aanum - 2] = afiles[j];
328 fork_child( acmd, aargs );
336 exit( EXIT_SUCCESS );
340 get_file_name( char *dirname, char *filename )
342 char buf[MAXPATHLEN];
344 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
346 return( strdup( buf ));
351 get_search_filters( char *filename, char *filters[] )
356 if ( (fp = fopen( filename, "r" )) != NULL ) {
359 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
362 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
364 filters[filter++] = ArgDup( line );
375 get_read_entries( char *filename, char *entries[] )
380 if ( (fp = fopen( filename, "r" )) != NULL ) {
383 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
386 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
388 entries[entry++] = ArgDup( line );
399 fork_child( char *prog, char **args )
403 wait4kids( maxkids );
405 switch ( pid = fork() ) {
408 /* The __LIBASCII execvp only handles ASCII "prog",
409 * we still need to translate the arg vec ourselves.
411 { char *arg2[MAXREQS];
414 for (i=0; args[i]; i++) {
415 arg2[i] = ArgDup(args[i]);
421 execvp( prog, args );
422 fprintf( stderr, "%s: ", prog );
424 exit( EXIT_FAILURE );
427 case -1: /* trouble */
428 fprintf( stderr, "Could not fork to run %s\n", prog );
432 default: /* parent */
439 wait4kids( int nkidval )
443 while ( nkids >= nkidval ) {
446 if ( WIFSTOPPED(status) ) {
448 "stopping: child stopped with signal %d\n",
449 (int) WSTOPSIG(status) );
451 } else if ( WIFSIGNALED(status) ) {
453 "stopping: child terminated with signal %d%s\n",
454 (int) WTERMSIG(status),
456 WCOREDUMP(status) ? ", core dumped" : ""
461 exit( WEXITSTATUS(status) );
463 } else if ( WEXITSTATUS(status) != 0 ) {
465 "stopping: child exited with status %d\n",
466 (int) WEXITSTATUS(status) );
467 exit( WEXITSTATUS(status) );
477 wait4kids( int nkidval )
481 while ( nkids >= nkidval ) {
482 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
483 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
484 children[i] = children[i+1];
490 fork_child( char *prog, char **args )
494 wait4kids( maxkids );
496 rc = _spawnvp( _P_NOWAIT, prog, args );
499 fprintf( stderr, "%s: ", prog );
502 children[nkids++] = (HANDLE)rc;