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)
76 "-H <uri> | ([-h <host>] -p <port>) "
83 "[-r <maxretries>]\n",
89 main( int argc, char **argv )
93 char *host = "localhost";
100 char *retries = RETRIES;
104 char *sreqs[MAXREQS];
105 char *sbase[MAXREQS];
108 char *rreqs[MAXREQS];
110 char *afiles[MAXREQS];
113 char *mreqs[MAXREQS];
115 char *sargs[MAXARGS];
117 char scmd[MAXPATHLEN];
118 char *rargs[MAXARGS];
120 char rcmd[MAXPATHLEN];
121 char *aargs[MAXARGS];
123 char acmd[MAXPATHLEN];
124 char *margs[MAXARGS];
126 char mcmd[MAXPATHLEN];
127 char *modargs[MAXARGS];
129 char modcmd[MAXPATHLEN];
130 char *modfile = NULL;
131 char *modreqs[MAXREQS];
132 char *moddn[MAXREQS];
135 while ( (i = getopt( argc, argv, "D:d:H:h:j:l:P:p:r:w:" )) != EOF ) {
137 case 'D': /* slapd manager */
138 manager = ArgDup( optarg );
141 case 'd': /* data directory */
142 dirname = strdup( optarg );
145 case 'H': /* slapd uri */
146 uri = strdup( optarg );
149 case 'h': /* slapd host */
150 host = 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 );
161 case 'P': /* prog directory */
162 progdir = strdup( optarg );
165 case 'p': /* the servers port number */
166 port = strdup( optarg );
170 retries = strdup( optarg );
173 case 'w': /* the managers passwd */
174 passwd = ArgDup( optarg );
183 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
184 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
188 children = malloc( maxkids * sizeof(HANDLE) );
190 /* get the file list */
191 if ( ( datadir = opendir( dirname )) == NULL ) {
193 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
195 exit( EXIT_FAILURE );
199 /* look for search, read, modrdn, and add/delete files */
200 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
202 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
203 sfile = get_file_name( dirname, file->d_name );
205 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
206 rfile = get_file_name( dirname, file->d_name );
208 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
209 mfile = get_file_name( dirname, file->d_name );
211 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
212 modfile = get_file_name( dirname, file->d_name );
214 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
215 && ( anum < MAXREQS )) {
216 afiles[anum++] = get_file_name( dirname, file->d_name );
223 /* look for search requests */
225 snum = get_search_filters( sfile, sreqs, sbase );
228 /* look for read requests */
230 rnum = get_read_entries( rfile, rreqs );
233 /* look for modrdn requests */
235 mnum = get_read_entries( mfile, mreqs );
237 /* look for modify requests */
239 modnum = get_search_filters( modfile, modreqs, moddn );
243 * generate the search clients
247 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
249 sargs[sanum++] = scmd;
251 sargs[sanum++] = "-H";
252 sargs[sanum++] = uri;
254 sargs[sanum++] = "-h";
255 sargs[sanum++] = host;
256 sargs[sanum++] = "-p";
257 sargs[sanum++] = port;
259 sargs[sanum++] = "-D";
260 sargs[sanum++] = manager;
261 sargs[sanum++] = "-w";
262 sargs[sanum++] = passwd;
263 sargs[sanum++] = "-l";
264 sargs[sanum++] = loops;
265 sargs[sanum++] = "-r";
266 sargs[sanum++] = retries;
267 sargs[sanum++] = "-b";
268 sargs[sanum++] = NULL; /* will hold the search base */
269 sargs[sanum++] = "-f";
270 sargs[sanum++] = NULL; /* will hold the search request */
271 sargs[sanum++] = NULL;
274 * generate the read clients
278 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
280 rargs[ranum++] = rcmd;
282 rargs[ranum++] = "-H";
283 rargs[ranum++] = uri;
285 rargs[ranum++] = "-h";
286 rargs[ranum++] = host;
287 rargs[ranum++] = "-p";
288 rargs[ranum++] = port;
290 rargs[ranum++] = "-l";
291 rargs[ranum++] = loops;
292 rargs[ranum++] = "-r";
293 rargs[ranum++] = retries;
294 rargs[ranum++] = "-e";
295 rargs[ranum++] = NULL; /* will hold the read entry */
296 rargs[ranum++] = NULL;
299 * generate the modrdn clients
303 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
305 margs[manum++] = mcmd;
307 margs[manum++] = "-H";
308 margs[manum++] = uri;
310 margs[manum++] = "-h";
311 margs[manum++] = host;
312 margs[manum++] = "-p";
313 margs[manum++] = port;
315 margs[manum++] = "-D";
316 margs[manum++] = manager;
317 margs[manum++] = "-w";
318 margs[manum++] = passwd;
319 margs[manum++] = "-l";
320 margs[manum++] = loops;
321 margs[manum++] = "-r";
322 margs[manum++] = retries;
323 margs[manum++] = "-e";
324 margs[manum++] = NULL; /* will hold the modrdn entry */
325 margs[manum++] = NULL;
328 * generate the modify clients
332 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
334 modargs[modanum++] = modcmd;
336 modargs[modanum++] = "-H";
337 modargs[modanum++] = uri;
339 modargs[modanum++] = "-h";
340 modargs[modanum++] = host;
341 modargs[modanum++] = "-p";
342 modargs[modanum++] = port;
344 modargs[modanum++] = "-D";
345 modargs[modanum++] = manager;
346 modargs[modanum++] = "-w";
347 modargs[modanum++] = passwd;
348 modargs[modanum++] = "-l";
349 modargs[modanum++] = loops;
350 modargs[modanum++] = "-r";
351 modargs[modanum++] = retries;
352 modargs[modanum++] = "-e";
353 modargs[modanum++] = NULL; /* will hold the modify entry */
354 modargs[modanum++] = "-a";;
355 modargs[modanum++] = NULL; /* will hold the ava */
356 modargs[modanum++] = NULL;
359 * generate the add/delete clients
363 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
365 aargs[aanum++] = acmd;
367 aargs[aanum++] = "-H";
368 aargs[aanum++] = uri;
370 aargs[aanum++] = "-h";
371 aargs[aanum++] = host;
372 aargs[aanum++] = "-p";
373 aargs[aanum++] = port;
375 aargs[aanum++] = "-D";
376 aargs[aanum++] = manager;
377 aargs[aanum++] = "-w";
378 aargs[aanum++] = passwd;
379 aargs[aanum++] = "-l";
380 aargs[aanum++] = loops;
381 aargs[aanum++] = "-r";
382 aargs[aanum++] = retries;
383 aargs[aanum++] = "-f";
384 aargs[aanum++] = NULL; /* will hold the add data file */
385 aargs[aanum++] = NULL;
387 for ( j = 0; j < MAXREQS; j++ ) {
391 sargs[sanum - 2] = sreqs[j];
392 sargs[sanum - 4] = sbase[j];
393 fork_child( scmd, sargs );
399 rargs[ranum - 2] = rreqs[j];
400 fork_child( rcmd, rargs );
406 margs[manum - 2] = mreqs[j];
407 fork_child( mcmd, margs );
412 modargs[modanum - 4] = moddn[j];
413 modargs[modanum - 2] = modreqs[j];
414 fork_child( modcmd, modargs );
420 aargs[aanum - 2] = afiles[j];
421 fork_child( acmd, aargs );
429 exit( EXIT_SUCCESS );
433 get_file_name( char *dirname, char *filename )
435 char buf[MAXPATHLEN];
437 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
439 return( strdup( buf ));
444 get_search_filters( char *filename, char *filters[], char *bases[] )
449 if ( (fp = fopen( filename, "r" )) != NULL ) {
452 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
455 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
457 bases[filter] = ArgDup( line );
458 fgets( line, BUFSIZ, fp );
459 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
462 filters[filter++] = ArgDup( line );
473 get_read_entries( char *filename, char *entries[] )
478 if ( (fp = fopen( filename, "r" )) != NULL ) {
481 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
484 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
486 entries[entry++] = ArgDup( line );
497 fork_child( char *prog, char **args )
501 wait4kids( maxkids );
503 switch ( pid = fork() ) {
506 /* The __LIBASCII execvp only handles ASCII "prog",
507 * we still need to translate the arg vec ourselves.
509 { char *arg2[MAXREQS];
512 for (i=0; args[i]; i++) {
513 arg2[i] = ArgDup(args[i]);
519 execvp( prog, args );
520 fprintf( stderr, "%s: ", prog );
522 exit( EXIT_FAILURE );
525 case -1: /* trouble */
526 fprintf( stderr, "Could not fork to run %s\n", prog );
530 default: /* parent */
537 wait4kids( int nkidval )
541 while ( nkids >= nkidval ) {
544 if ( WIFSTOPPED(status) ) {
546 "stopping: child stopped with signal %d\n",
547 (int) WSTOPSIG(status) );
549 } else if ( WIFSIGNALED(status) ) {
551 "stopping: child terminated with signal %d%s\n",
552 (int) WTERMSIG(status),
554 WCOREDUMP(status) ? ", core dumped" : ""
559 exit( WEXITSTATUS(status) );
561 } else if ( WEXITSTATUS(status) != 0 ) {
563 "stopping: child exited with status %d\n",
564 (int) WEXITSTATUS(status) );
565 exit( WEXITSTATUS(status) );
575 wait4kids( int nkidval )
579 while ( nkids >= nkidval ) {
580 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
581 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
582 children[i] = children[i+1];
588 fork_child( char *prog, char **args )
592 wait4kids( maxkids );
594 rc = _spawnvp( _P_NOWAIT, prog, args );
597 fprintf( stderr, "%s: ", prog );
600 children[nkids++] = (HANDLE)rc;