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"
47 #define TSEARCHFILE "do_search.0"
48 #define TREADFILE "do_read.0"
49 #define TADDFILE "do_add."
50 #define TMODRDNFILE "do_modrdn.0"
51 #define TMODIFYFILE "do_modify.0"
53 static char *get_file_name( char *dirname, char *filename );
54 static int get_search_filters( char *filename, char *filters[], char *bases[] );
55 static int get_read_entries( char *filename, char *entries[] );
56 static void fork_child( char *prog, char **args );
57 static void wait4kids( int nkidval );
59 static int maxkids = 20;
63 static HANDLE *children;
64 static char argbuf[BUFSIZ];
65 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
67 #define ArgDup(x) strdup(x)
73 fprintf( stderr, "usage: %s -H <uri> | ([-h <host>] -p <port>) -D <manager> -w <passwd> -d <datadir> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
78 main( int argc, char **argv )
82 char *host = "localhost";
98 char *afiles[MAXREQS];
101 char *mreqs[MAXREQS];
103 char *sargs[MAXARGS];
105 char scmd[MAXPATHLEN];
106 char *rargs[MAXARGS];
108 char rcmd[MAXPATHLEN];
109 char *aargs[MAXARGS];
111 char acmd[MAXPATHLEN];
112 char *margs[MAXARGS];
114 char mcmd[MAXPATHLEN];
115 char *modargs[MAXARGS];
117 char modcmd[MAXPATHLEN];
118 char *modfile = NULL;
119 char *modreqs[MAXREQS];
120 char *moddn[MAXREQS];
123 while ( (i = getopt( argc, argv, "H:h:p:D:w:b:d:j:l:P:" )) != EOF ) {
125 case 'H': /* slapd uri */
126 uri = strdup( optarg );
129 case 'h': /* slapd host */
130 host = strdup( optarg );
133 case 'p': /* the servers port number */
134 port = strdup( optarg );
137 case 'D': /* slapd manager */
138 manager = ArgDup( optarg );
141 case 'w': /* the managers passwd */
142 passwd = ArgDup( optarg );
145 case 'd': /* data directory */
146 dirname = strdup( optarg );
149 case 'P': /* prog directory */
150 progdir = strdup( optarg );
153 case 'j': /* the number of parallel clients */
154 maxkids = atoi( optarg );
157 case 'l': /* the number of loops per client */
158 loops = strdup( optarg );
167 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
168 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
172 children = malloc( maxkids * sizeof(HANDLE) );
174 /* get the file list */
175 if ( ( datadir = opendir( dirname )) == NULL ) {
177 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
179 exit( EXIT_FAILURE );
183 /* look for search, read, modrdn, and add/delete files */
184 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
186 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
187 sfile = get_file_name( dirname, file->d_name );
189 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
190 rfile = get_file_name( dirname, file->d_name );
192 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
193 mfile = get_file_name( dirname, file->d_name );
195 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
196 modfile = get_file_name( dirname, file->d_name );
198 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
199 && ( anum < MAXREQS )) {
200 afiles[anum++] = get_file_name( dirname, file->d_name );
207 /* look for search requests */
209 snum = get_search_filters( sfile, sreqs, sbase );
212 /* look for read requests */
214 rnum = get_read_entries( rfile, rreqs );
217 /* look for modrdn requests */
219 mnum = get_read_entries( mfile, mreqs );
221 /* look for modify requests */
223 modnum = get_search_filters( modfile, modreqs, moddn );
227 * generate the search clients
231 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
233 sargs[sanum++] = scmd;
235 sargs[sanum++] = "-H";
236 sargs[sanum++] = uri;
238 sargs[sanum++] = "-h";
239 sargs[sanum++] = host;
240 sargs[sanum++] = "-p";
241 sargs[sanum++] = port;
243 sargs[sanum++] = "-D";
244 sargs[sanum++] = manager;
245 sargs[sanum++] = "-w";
246 sargs[sanum++] = passwd;
247 sargs[sanum++] = "-l";
248 sargs[sanum++] = loops;
249 sargs[sanum++] = "-b";
250 sargs[sanum++] = NULL; /* will hold the search base */
251 sargs[sanum++] = "-f";
252 sargs[sanum++] = NULL; /* will hold the search request */
253 sargs[sanum++] = NULL;
256 * generate the read clients
260 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
262 rargs[ranum++] = rcmd;
264 rargs[ranum++] = "-H";
265 rargs[ranum++] = uri;
267 rargs[ranum++] = "-h";
268 rargs[ranum++] = host;
269 rargs[ranum++] = "-p";
270 rargs[ranum++] = port;
272 rargs[ranum++] = "-l";
273 rargs[ranum++] = loops;
274 rargs[ranum++] = "-e";
275 rargs[ranum++] = NULL; /* will hold the read entry */
276 rargs[ranum++] = NULL;
279 * generate the modrdn clients
283 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
285 margs[manum++] = mcmd;
287 margs[manum++] = "-H";
288 margs[manum++] = uri;
290 margs[manum++] = "-h";
291 margs[manum++] = host;
292 margs[manum++] = "-p";
293 margs[manum++] = port;
295 margs[manum++] = "-D";
296 margs[manum++] = manager;
297 margs[manum++] = "-w";
298 margs[manum++] = passwd;
299 margs[manum++] = "-l";
300 margs[manum++] = loops;
301 margs[manum++] = "-e";
302 margs[manum++] = NULL; /* will hold the modrdn entry */
303 margs[manum++] = NULL;
306 * generate the modify clients
310 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
312 modargs[modanum++] = modcmd;
314 modargs[modanum++] = "-H";
315 modargs[modanum++] = uri;
317 modargs[modanum++] = "-h";
318 modargs[modanum++] = host;
319 modargs[modanum++] = "-p";
320 modargs[modanum++] = port;
322 modargs[modanum++] = "-D";
323 modargs[modanum++] = manager;
324 modargs[modanum++] = "-w";
325 modargs[modanum++] = passwd;
326 modargs[modanum++] = "-l";
327 modargs[modanum++] = loops;
328 modargs[modanum++] = "-e";
329 modargs[modanum++] = NULL; /* will hold the modify entry */
330 modargs[modanum++] = "-a";;
331 modargs[modanum++] = NULL; /* will hold the ava */
332 modargs[modanum++] = NULL;
335 * generate the add/delete clients
339 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
341 aargs[aanum++] = acmd;
343 aargs[aanum++] = "-H";
344 aargs[aanum++] = uri;
346 aargs[aanum++] = "-h";
347 aargs[aanum++] = host;
348 aargs[aanum++] = "-p";
349 aargs[aanum++] = port;
351 aargs[aanum++] = "-D";
352 aargs[aanum++] = manager;
353 aargs[aanum++] = "-w";
354 aargs[aanum++] = passwd;
355 aargs[aanum++] = "-l";
356 aargs[aanum++] = loops;
357 aargs[aanum++] = "-f";
358 aargs[aanum++] = NULL; /* will hold the add data file */
359 aargs[aanum++] = NULL;
361 for ( j = 0; j < MAXREQS; j++ ) {
365 sargs[sanum - 2] = sreqs[j];
366 sargs[sanum - 4] = sbase[j];
367 fork_child( scmd, sargs );
373 rargs[ranum - 2] = rreqs[j];
374 fork_child( rcmd, rargs );
380 margs[manum - 2] = mreqs[j];
381 fork_child( mcmd, margs );
386 modargs[modanum - 4] = moddn[j];
387 modargs[modanum - 2] = modreqs[j];
388 fork_child( modcmd, modargs );
394 aargs[aanum - 2] = afiles[j];
395 fork_child( acmd, aargs );
403 exit( EXIT_SUCCESS );
407 get_file_name( char *dirname, char *filename )
409 char buf[MAXPATHLEN];
411 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
413 return( strdup( buf ));
418 get_search_filters( char *filename, char *filters[], char *bases[] )
423 if ( (fp = fopen( filename, "r" )) != NULL ) {
426 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
429 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
431 bases[filter] = ArgDup( line );
432 fgets( line, BUFSIZ, fp );
433 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
436 filters[filter++] = ArgDup( line );
447 get_read_entries( char *filename, char *entries[] )
452 if ( (fp = fopen( filename, "r" )) != NULL ) {
455 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
458 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
460 entries[entry++] = ArgDup( line );
471 fork_child( char *prog, char **args )
475 wait4kids( maxkids );
477 switch ( pid = fork() ) {
480 /* The __LIBASCII execvp only handles ASCII "prog",
481 * we still need to translate the arg vec ourselves.
483 { char *arg2[MAXREQS];
486 for (i=0; args[i]; i++) {
487 arg2[i] = ArgDup(args[i]);
493 execvp( prog, args );
494 fprintf( stderr, "%s: ", prog );
496 exit( EXIT_FAILURE );
499 case -1: /* trouble */
500 fprintf( stderr, "Could not fork to run %s\n", prog );
504 default: /* parent */
511 wait4kids( int nkidval )
515 while ( nkids >= nkidval ) {
518 if ( WIFSTOPPED(status) ) {
520 "stopping: child stopped with signal %d\n",
521 (int) WSTOPSIG(status) );
523 } else if ( WIFSIGNALED(status) ) {
525 "stopping: child terminated with signal %d%s\n",
526 (int) WTERMSIG(status),
528 WCOREDUMP(status) ? ", core dumped" : ""
533 exit( WEXITSTATUS(status) );
535 } else if ( WEXITSTATUS(status) != 0 ) {
537 "stopping: child exited with status %d\n",
538 (int) WEXITSTATUS(status) );
539 exit( WEXITSTATUS(status) );
549 wait4kids( int nkidval )
553 while ( nkids >= nkidval ) {
554 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
555 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
556 children[i] = children[i+1];
562 fork_child( char *prog, char **args )
566 wait4kids( maxkids );
568 rc = _spawnvp( _P_NOWAIT, prog, args );
571 fprintf( stderr, "%s: ", prog );
574 children[nkids++] = (HANDLE)rc;