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)
74 fprintf( stderr, "usage: %s -H <uri> | ([-h <host>] -p <port>) -D <manager> -w <passwd> -d <datadir> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
79 main( int argc, char **argv )
83 char *host = "localhost";
90 char *retries = RETRIES;
100 char *afiles[MAXREQS];
103 char *mreqs[MAXREQS];
105 char *sargs[MAXARGS];
107 char scmd[MAXPATHLEN];
108 char *rargs[MAXARGS];
110 char rcmd[MAXPATHLEN];
111 char *aargs[MAXARGS];
113 char acmd[MAXPATHLEN];
114 char *margs[MAXARGS];
116 char mcmd[MAXPATHLEN];
117 char *modargs[MAXARGS];
119 char modcmd[MAXPATHLEN];
120 char *modfile = NULL;
121 char *modreqs[MAXREQS];
122 char *moddn[MAXREQS];
125 while ( (i = getopt( argc, argv, "D:d:H:h:j:l:P:p:r:w:" )) != EOF ) {
127 case 'D': /* slapd manager */
128 manager = ArgDup( optarg );
131 case 'd': /* data directory */
132 dirname = strdup( optarg );
135 case 'H': /* slapd uri */
136 uri = strdup( optarg );
139 case 'h': /* slapd host */
140 host = strdup( optarg );
143 case 'j': /* the number of parallel clients */
144 maxkids = atoi( optarg );
147 case 'l': /* the number of loops per client */
148 loops = strdup( optarg );
151 case 'P': /* prog directory */
152 progdir = strdup( optarg );
155 case 'p': /* the servers port number */
156 port = strdup( optarg );
160 retries = strdup( optarg );
163 case 'w': /* the managers passwd */
164 passwd = ArgDup( optarg );
173 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
174 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
178 children = malloc( maxkids * sizeof(HANDLE) );
180 /* get the file list */
181 if ( ( datadir = opendir( dirname )) == NULL ) {
183 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
185 exit( EXIT_FAILURE );
189 /* look for search, read, modrdn, and add/delete files */
190 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
192 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
193 sfile = get_file_name( dirname, file->d_name );
195 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
196 rfile = get_file_name( dirname, file->d_name );
198 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
199 mfile = get_file_name( dirname, file->d_name );
201 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
202 modfile = get_file_name( dirname, file->d_name );
204 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
205 && ( anum < MAXREQS )) {
206 afiles[anum++] = get_file_name( dirname, file->d_name );
213 /* look for search requests */
215 snum = get_search_filters( sfile, sreqs, sbase );
218 /* look for read requests */
220 rnum = get_read_entries( rfile, rreqs );
223 /* look for modrdn requests */
225 mnum = get_read_entries( mfile, mreqs );
227 /* look for modify requests */
229 modnum = get_search_filters( modfile, modreqs, moddn );
233 * generate the search clients
237 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
239 sargs[sanum++] = scmd;
241 sargs[sanum++] = "-H";
242 sargs[sanum++] = uri;
244 sargs[sanum++] = "-h";
245 sargs[sanum++] = host;
246 sargs[sanum++] = "-p";
247 sargs[sanum++] = port;
249 sargs[sanum++] = "-D";
250 sargs[sanum++] = manager;
251 sargs[sanum++] = "-w";
252 sargs[sanum++] = passwd;
253 sargs[sanum++] = "-l";
254 sargs[sanum++] = loops;
255 sargs[sanum++] = "-r";
256 sargs[sanum++] = retries;
257 sargs[sanum++] = "-b";
258 sargs[sanum++] = NULL; /* will hold the search base */
259 sargs[sanum++] = "-f";
260 sargs[sanum++] = NULL; /* will hold the search request */
261 sargs[sanum++] = NULL;
264 * generate the read clients
268 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
270 rargs[ranum++] = rcmd;
272 rargs[ranum++] = "-H";
273 rargs[ranum++] = uri;
275 rargs[ranum++] = "-h";
276 rargs[ranum++] = host;
277 rargs[ranum++] = "-p";
278 rargs[ranum++] = port;
280 rargs[ranum++] = "-l";
281 rargs[ranum++] = loops;
282 rargs[ranum++] = "-r";
283 rargs[ranum++] = retries;
284 rargs[ranum++] = "-e";
285 rargs[ranum++] = NULL; /* will hold the read entry */
286 rargs[ranum++] = NULL;
289 * generate the modrdn clients
293 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
295 margs[manum++] = mcmd;
297 margs[manum++] = "-H";
298 margs[manum++] = uri;
300 margs[manum++] = "-h";
301 margs[manum++] = host;
302 margs[manum++] = "-p";
303 margs[manum++] = port;
305 margs[manum++] = "-D";
306 margs[manum++] = manager;
307 margs[manum++] = "-w";
308 margs[manum++] = passwd;
309 margs[manum++] = "-l";
310 margs[manum++] = loops;
311 margs[manum++] = "-r";
312 margs[manum++] = retries;
313 margs[manum++] = "-e";
314 margs[manum++] = NULL; /* will hold the modrdn entry */
315 margs[manum++] = NULL;
318 * generate the modify clients
322 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
324 modargs[modanum++] = modcmd;
326 modargs[modanum++] = "-H";
327 modargs[modanum++] = uri;
329 modargs[modanum++] = "-h";
330 modargs[modanum++] = host;
331 modargs[modanum++] = "-p";
332 modargs[modanum++] = port;
334 modargs[modanum++] = "-D";
335 modargs[modanum++] = manager;
336 modargs[modanum++] = "-w";
337 modargs[modanum++] = passwd;
338 modargs[modanum++] = "-l";
339 modargs[modanum++] = loops;
340 modargs[modanum++] = "-r";
341 modargs[modanum++] = retries;
342 modargs[modanum++] = "-e";
343 modargs[modanum++] = NULL; /* will hold the modify entry */
344 modargs[modanum++] = "-a";;
345 modargs[modanum++] = NULL; /* will hold the ava */
346 modargs[modanum++] = NULL;
349 * generate the add/delete clients
353 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
355 aargs[aanum++] = acmd;
357 aargs[aanum++] = "-H";
358 aargs[aanum++] = uri;
360 aargs[aanum++] = "-h";
361 aargs[aanum++] = host;
362 aargs[aanum++] = "-p";
363 aargs[aanum++] = port;
365 aargs[aanum++] = "-D";
366 aargs[aanum++] = manager;
367 aargs[aanum++] = "-w";
368 aargs[aanum++] = passwd;
369 aargs[aanum++] = "-l";
370 aargs[aanum++] = loops;
371 aargs[aanum++] = "-r";
372 aargs[aanum++] = retries;
373 aargs[aanum++] = "-f";
374 aargs[aanum++] = NULL; /* will hold the add data file */
375 aargs[aanum++] = NULL;
377 for ( j = 0; j < MAXREQS; j++ ) {
381 sargs[sanum - 2] = sreqs[j];
382 sargs[sanum - 4] = sbase[j];
383 fork_child( scmd, sargs );
389 rargs[ranum - 2] = rreqs[j];
390 fork_child( rcmd, rargs );
396 margs[manum - 2] = mreqs[j];
397 fork_child( mcmd, margs );
402 modargs[modanum - 4] = moddn[j];
403 modargs[modanum - 2] = modreqs[j];
404 fork_child( modcmd, modargs );
410 aargs[aanum - 2] = afiles[j];
411 fork_child( acmd, aargs );
419 exit( EXIT_SUCCESS );
423 get_file_name( char *dirname, char *filename )
425 char buf[MAXPATHLEN];
427 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
429 return( strdup( buf ));
434 get_search_filters( char *filename, char *filters[], char *bases[] )
439 if ( (fp = fopen( filename, "r" )) != NULL ) {
442 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
445 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
447 bases[filter] = ArgDup( line );
448 fgets( line, BUFSIZ, fp );
449 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
452 filters[filter++] = ArgDup( line );
463 get_read_entries( char *filename, char *entries[] )
468 if ( (fp = fopen( filename, "r" )) != NULL ) {
471 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
474 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
476 entries[entry++] = ArgDup( line );
487 fork_child( char *prog, char **args )
491 wait4kids( maxkids );
493 switch ( pid = fork() ) {
496 /* The __LIBASCII execvp only handles ASCII "prog",
497 * we still need to translate the arg vec ourselves.
499 { char *arg2[MAXREQS];
502 for (i=0; args[i]; i++) {
503 arg2[i] = ArgDup(args[i]);
509 execvp( prog, args );
510 fprintf( stderr, "%s: ", prog );
512 exit( EXIT_FAILURE );
515 case -1: /* trouble */
516 fprintf( stderr, "Could not fork to run %s\n", prog );
520 default: /* parent */
527 wait4kids( int nkidval )
531 while ( nkids >= nkidval ) {
534 if ( WIFSTOPPED(status) ) {
536 "stopping: child stopped with signal %d\n",
537 (int) WSTOPSIG(status) );
539 } else if ( WIFSIGNALED(status) ) {
541 "stopping: child terminated with signal %d%s\n",
542 (int) WTERMSIG(status),
544 WCOREDUMP(status) ? ", core dumped" : ""
549 exit( WEXITSTATUS(status) );
551 } else if ( WEXITSTATUS(status) != 0 ) {
553 "stopping: child exited with status %d\n",
554 (int) WEXITSTATUS(status) );
555 exit( WEXITSTATUS(status) );
565 wait4kids( int nkidval )
569 while ( nkids >= nkidval ) {
570 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
571 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
572 children[i] = children[i+1];
578 fork_child( char *prog, char **args )
582 wait4kids( maxkids );
584 rc = _spawnvp( _P_NOWAIT, prog, args );
587 fprintf( stderr, "%s: ", prog );
590 children[nkids++] = (HANDLE)rc;