2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2004 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"
46 #define TSEARCHFILE "do_search.0"
47 #define TREADFILE "do_read.0"
48 #define TADDFILE "do_add."
49 #define TMODRDNFILE "do_modrdn.0"
51 static char *get_file_name( char *dirname, char *filename );
52 static int get_search_filters( char *filename, char *filters[], char *bases[] );
53 static int get_read_entries( char *filename, char *entries[] );
54 static void fork_child( char *prog, char **args );
55 static void wait4kids( int nkidval );
57 static int maxkids = 20;
61 static HANDLE *children;
62 static char argbuf[BUFSIZ];
63 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
65 #define ArgDup(x) strdup(x)
71 fprintf( stderr, "usage: %s -H <uri> | ([-h <host>] -p <port>) -D <manager> -w <passwd> -d <datadir> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
76 main( int argc, char **argv )
80 char *host = "localhost";
96 char *afiles[MAXREQS];
101 char *sargs[MAXARGS];
103 char scmd[MAXPATHLEN];
104 char *rargs[MAXARGS];
106 char rcmd[MAXPATHLEN];
107 char *aargs[MAXARGS];
109 char acmd[MAXPATHLEN];
110 char *margs[MAXARGS];
112 char mcmd[MAXPATHLEN];
114 while ( (i = getopt( argc, argv, "H:h:p:D:w:b:d:j:l:P:" )) != EOF ) {
116 case 'H': /* slapd uri */
117 uri = strdup( optarg );
120 case 'h': /* slapd host */
121 host = strdup( optarg );
124 case 'p': /* the servers port number */
125 port = strdup( optarg );
128 case 'D': /* slapd manager */
129 manager = ArgDup( optarg );
132 case 'w': /* the managers passwd */
133 passwd = ArgDup( optarg );
136 case 'd': /* data directory */
137 dirname = strdup( optarg );
140 case 'P': /* prog directory */
141 progdir = strdup( optarg );
144 case 'j': /* the number of parallel clients */
145 maxkids = atoi( optarg );
148 case 'l': /* the number of loops per client */
149 loops = strdup( optarg );
158 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
159 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
163 children = malloc( maxkids * sizeof(HANDLE) );
165 /* get the file list */
166 if ( ( datadir = opendir( dirname )) == NULL ) {
168 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
170 exit( EXIT_FAILURE );
174 /* look for search, read, modrdn, and add/delete files */
175 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
177 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
178 sfile = get_file_name( dirname, file->d_name );
180 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
181 rfile = get_file_name( dirname, file->d_name );
183 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
184 mfile = get_file_name( dirname, file->d_name );
186 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
187 && ( anum < MAXREQS )) {
188 afiles[anum++] = get_file_name( dirname, file->d_name );
195 /* look for search requests */
197 snum = get_search_filters( sfile, sreqs, sbase );
200 /* look for read requests */
202 rnum = get_read_entries( rfile, rreqs );
205 /* look for modrdn requests */
207 mnum = get_read_entries( mfile, mreqs );
211 * generate the search clients
215 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
217 sargs[sanum++] = scmd;
219 sargs[sanum++] = "-H";
220 sargs[sanum++] = uri;
222 sargs[sanum++] = "-h";
223 sargs[sanum++] = host;
224 sargs[sanum++] = "-p";
225 sargs[sanum++] = port;
227 sargs[sanum++] = "-l";
228 sargs[sanum++] = loops;
229 sargs[sanum++] = "-b";
230 sargs[sanum++] = NULL; /* will hold the search base */
231 sargs[sanum++] = "-f";
232 sargs[sanum++] = NULL; /* will hold the search request */
233 sargs[sanum++] = NULL;
236 * generate the read clients
240 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
242 rargs[ranum++] = rcmd;
244 rargs[ranum++] = "-H";
245 rargs[ranum++] = uri;
247 rargs[ranum++] = "-h";
248 rargs[ranum++] = host;
249 rargs[ranum++] = "-p";
250 rargs[ranum++] = port;
252 rargs[ranum++] = "-l";
253 rargs[ranum++] = loops;
254 rargs[ranum++] = "-e";
255 rargs[ranum++] = NULL; /* will hold the read entry */
256 rargs[ranum++] = NULL;
259 * generate the modrdn clients
263 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
265 margs[manum++] = mcmd;
267 margs[manum++] = "-H";
268 margs[manum++] = uri;
270 margs[manum++] = "-h";
271 margs[manum++] = host;
272 margs[manum++] = "-p";
273 margs[manum++] = port;
275 margs[manum++] = "-D";
276 margs[manum++] = manager;
277 margs[manum++] = "-w";
278 margs[manum++] = passwd;
279 margs[manum++] = "-l";
280 margs[manum++] = loops;
281 margs[manum++] = "-e";
282 margs[manum++] = NULL; /* will hold the modrdn entry */
283 margs[manum++] = NULL;
286 * generate the add/delete clients
290 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
292 aargs[aanum++] = acmd;
294 aargs[aanum++] = "-H";
295 aargs[aanum++] = uri;
297 aargs[aanum++] = "-h";
298 aargs[aanum++] = host;
299 aargs[aanum++] = "-p";
300 aargs[aanum++] = port;
302 aargs[aanum++] = "-D";
303 aargs[aanum++] = manager;
304 aargs[aanum++] = "-w";
305 aargs[aanum++] = passwd;
306 aargs[aanum++] = "-l";
307 aargs[aanum++] = loops;
308 aargs[aanum++] = "-f";
309 aargs[aanum++] = NULL; /* will hold the add data file */
310 aargs[aanum++] = NULL;
312 for ( j = 0; j < MAXREQS; j++ ) {
316 sargs[sanum - 2] = sreqs[j];
317 sargs[sanum - 4] = sbase[j];
318 fork_child( scmd, sargs );
324 rargs[ranum - 2] = rreqs[j];
325 fork_child( rcmd, rargs );
331 margs[manum - 2] = mreqs[j];
332 fork_child( mcmd, margs );
338 aargs[aanum - 2] = afiles[j];
339 fork_child( acmd, aargs );
347 exit( EXIT_SUCCESS );
351 get_file_name( char *dirname, char *filename )
353 char buf[MAXPATHLEN];
355 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
357 return( strdup( buf ));
362 get_search_filters( char *filename, char *filters[], char *bases[] )
367 if ( (fp = fopen( filename, "r" )) != NULL ) {
370 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
373 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
375 bases[filter] = ArgDup( line );
376 fgets( line, BUFSIZ, fp );
377 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
380 filters[filter++] = ArgDup( line );
391 get_read_entries( char *filename, char *entries[] )
396 if ( (fp = fopen( filename, "r" )) != NULL ) {
399 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
402 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
404 entries[entry++] = ArgDup( line );
415 fork_child( char *prog, char **args )
419 wait4kids( maxkids );
421 switch ( pid = fork() ) {
424 /* The __LIBASCII execvp only handles ASCII "prog",
425 * we still need to translate the arg vec ourselves.
427 { char *arg2[MAXREQS];
430 for (i=0; args[i]; i++) {
431 arg2[i] = ArgDup(args[i]);
437 execvp( prog, args );
438 fprintf( stderr, "%s: ", prog );
440 exit( EXIT_FAILURE );
443 case -1: /* trouble */
444 fprintf( stderr, "Could not fork to run %s\n", prog );
448 default: /* parent */
455 wait4kids( int nkidval )
459 while ( nkids >= nkidval ) {
462 if ( WIFSTOPPED(status) ) {
464 "stopping: child stopped with signal %d\n",
465 (int) WSTOPSIG(status) );
467 } else if ( WIFSIGNALED(status) ) {
469 "stopping: child terminated with signal %d%s\n",
470 (int) WTERMSIG(status),
472 WCOREDUMP(status) ? ", core dumped" : ""
477 exit( WEXITSTATUS(status) );
479 } else if ( WEXITSTATUS(status) != 0 ) {
481 "stopping: child exited with status %d\n",
482 (int) WEXITSTATUS(status) );
483 exit( WEXITSTATUS(status) );
493 wait4kids( int nkidval )
497 while ( nkids >= nkidval ) {
498 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
499 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
500 children[i] = children[i+1];
506 fork_child( char *prog, char **args )
510 wait4kids( maxkids );
512 rc = _spawnvp( _P_NOWAIT, prog, args );
515 fprintf( stderr, "%s: ", prog );
518 children[nkids++] = (HANDLE)rc;