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[], char *bases[] );
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 <uri> | ([-h <host>] -p <port>) -D <manager> -w <passwd> -d <datadir> [-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 'd': /* data directory */
123 dirname = strdup( optarg );
126 case 'P': /* prog directory */
127 progdir = strdup( optarg );
130 case 'j': /* the number of parallel clients */
131 maxkids = atoi( optarg );
134 case 'l': /* the number of loops per client */
135 loops = strdup( optarg );
144 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
145 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
149 children = malloc( maxkids * sizeof(HANDLE) );
151 /* get the file list */
152 if ( ( datadir = opendir( dirname )) == NULL ) {
154 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
156 exit( EXIT_FAILURE );
160 /* look for search, read, modrdn, and add/delete files */
161 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
163 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
164 sfile = get_file_name( dirname, file->d_name );
166 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
167 rfile = get_file_name( dirname, file->d_name );
169 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
170 mfile = get_file_name( dirname, file->d_name );
172 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
173 && ( anum < MAXREQS )) {
174 afiles[anum++] = get_file_name( dirname, file->d_name );
181 /* look for search requests */
183 snum = get_search_filters( sfile, sreqs, sbase );
186 /* look for read requests */
188 rnum = get_read_entries( rfile, rreqs );
191 /* look for modrdn requests */
193 mnum = get_read_entries( mfile, mreqs );
197 * generate the search clients
201 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
203 sargs[sanum++] = scmd;
205 sargs[sanum++] = "-H";
206 sargs[sanum++] = uri;
208 sargs[sanum++] = "-h";
209 sargs[sanum++] = host;
210 sargs[sanum++] = "-p";
211 sargs[sanum++] = port;
213 sargs[sanum++] = "-l";
214 sargs[sanum++] = loops;
215 sargs[sanum++] = "-b";
216 sargs[sanum++] = NULL; /* will hold the search base */
217 sargs[sanum++] = "-f";
218 sargs[sanum++] = NULL; /* will hold the search request */
219 sargs[sanum++] = NULL;
222 * generate the read clients
226 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
228 rargs[ranum++] = rcmd;
230 rargs[ranum++] = "-H";
231 rargs[ranum++] = uri;
233 rargs[ranum++] = "-h";
234 rargs[ranum++] = host;
235 rargs[ranum++] = "-p";
236 rargs[ranum++] = port;
238 rargs[ranum++] = "-l";
239 rargs[ranum++] = loops;
240 rargs[ranum++] = "-e";
241 rargs[ranum++] = NULL; /* will hold the read entry */
242 rargs[ranum++] = NULL;
245 * generate the modrdn clients
249 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
251 margs[manum++] = mcmd;
253 margs[manum++] = "-H";
254 margs[manum++] = uri;
256 margs[manum++] = "-h";
257 margs[manum++] = host;
258 margs[manum++] = "-p";
259 margs[manum++] = port;
261 margs[manum++] = "-D";
262 margs[manum++] = manager;
263 margs[manum++] = "-w";
264 margs[manum++] = passwd;
265 margs[manum++] = "-l";
266 margs[manum++] = loops;
267 margs[manum++] = "-e";
268 margs[manum++] = NULL; /* will hold the modrdn entry */
269 margs[manum++] = NULL;
272 * generate the add/delete clients
276 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
278 aargs[aanum++] = acmd;
280 aargs[aanum++] = "-H";
281 aargs[aanum++] = uri;
283 aargs[aanum++] = "-h";
284 aargs[aanum++] = host;
285 aargs[aanum++] = "-p";
286 aargs[aanum++] = port;
288 aargs[aanum++] = "-D";
289 aargs[aanum++] = manager;
290 aargs[aanum++] = "-w";
291 aargs[aanum++] = passwd;
292 aargs[aanum++] = "-l";
293 aargs[aanum++] = loops;
294 aargs[aanum++] = "-f";
295 aargs[aanum++] = NULL; /* will hold the add data file */
296 aargs[aanum++] = NULL;
298 for ( j = 0; j < MAXREQS; j++ ) {
302 sargs[sanum - 2] = sreqs[j];
303 sargs[sanum - 4] = sbase[j];
304 fork_child( scmd, sargs );
310 rargs[ranum - 2] = rreqs[j];
311 fork_child( rcmd, rargs );
317 margs[manum - 2] = mreqs[j];
318 fork_child( mcmd, margs );
324 aargs[aanum - 2] = afiles[j];
325 fork_child( acmd, aargs );
333 exit( EXIT_SUCCESS );
337 get_file_name( char *dirname, char *filename )
339 char buf[MAXPATHLEN];
341 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
343 return( strdup( buf ));
348 get_search_filters( char *filename, char *filters[], char *bases[] )
353 if ( (fp = fopen( filename, "r" )) != NULL ) {
356 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
359 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
361 bases[filter] = ArgDup( line );
362 fgets( line, BUFSIZ, fp );
363 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
366 filters[filter++] = ArgDup( line );
377 get_read_entries( char *filename, char *entries[] )
382 if ( (fp = fopen( filename, "r" )) != NULL ) {
385 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
388 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
390 entries[entry++] = ArgDup( line );
401 fork_child( char *prog, char **args )
405 wait4kids( maxkids );
407 switch ( pid = fork() ) {
410 /* The __LIBASCII execvp only handles ASCII "prog",
411 * we still need to translate the arg vec ourselves.
413 { char *arg2[MAXREQS];
416 for (i=0; args[i]; i++) {
417 arg2[i] = ArgDup(args[i]);
423 execvp( prog, args );
424 fprintf( stderr, "%s: ", prog );
426 exit( EXIT_FAILURE );
429 case -1: /* trouble */
430 fprintf( stderr, "Could not fork to run %s\n", prog );
434 default: /* parent */
441 wait4kids( int nkidval )
445 while ( nkids >= nkidval ) {
448 if ( WIFSTOPPED(status) ) {
450 "stopping: child stopped with signal %d\n",
451 (int) WSTOPSIG(status) );
453 } else if ( WIFSIGNALED(status) ) {
455 "stopping: child terminated with signal %d%s\n",
456 (int) WTERMSIG(status),
458 WCOREDUMP(status) ? ", core dumped" : ""
463 exit( WEXITSTATUS(status) );
465 } else if ( WEXITSTATUS(status) != 0 ) {
467 "stopping: child exited with status %d\n",
468 (int) WEXITSTATUS(status) );
469 exit( WEXITSTATUS(status) );
479 wait4kids( int nkidval )
483 while ( nkids >= nkidval ) {
484 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
485 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
486 children[i] = children[i+1];
492 fork_child( char *prog, char **args )
496 wait4kids( maxkids );
498 rc = _spawnvp( _P_NOWAIT, prog, args );
501 fprintf( stderr, "%s: ", prog );
504 children[nkids++] = (HANDLE)rc;