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"
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++] = "-l";
244 sargs[sanum++] = loops;
245 sargs[sanum++] = "-b";
246 sargs[sanum++] = NULL; /* will hold the search base */
247 sargs[sanum++] = "-f";
248 sargs[sanum++] = NULL; /* will hold the search request */
249 sargs[sanum++] = NULL;
252 * generate the read clients
256 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
258 rargs[ranum++] = rcmd;
260 rargs[ranum++] = "-H";
261 rargs[ranum++] = uri;
263 rargs[ranum++] = "-h";
264 rargs[ranum++] = host;
265 rargs[ranum++] = "-p";
266 rargs[ranum++] = port;
268 rargs[ranum++] = "-l";
269 rargs[ranum++] = loops;
270 rargs[ranum++] = "-e";
271 rargs[ranum++] = NULL; /* will hold the read entry */
272 rargs[ranum++] = NULL;
275 * generate the modrdn clients
279 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
281 margs[manum++] = mcmd;
283 margs[manum++] = "-H";
284 margs[manum++] = uri;
286 margs[manum++] = "-h";
287 margs[manum++] = host;
288 margs[manum++] = "-p";
289 margs[manum++] = port;
291 margs[manum++] = "-D";
292 margs[manum++] = manager;
293 margs[manum++] = "-w";
294 margs[manum++] = passwd;
295 margs[manum++] = "-l";
296 margs[manum++] = loops;
297 margs[manum++] = "-e";
298 margs[manum++] = NULL; /* will hold the modrdn entry */
299 margs[manum++] = NULL;
302 * generate the modify clients
306 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
308 modargs[modanum++] = modcmd;
310 modargs[modanum++] = "-H";
311 modargs[modanum++] = uri;
313 modargs[modanum++] = "-h";
314 modargs[modanum++] = host;
315 modargs[modanum++] = "-p";
316 modargs[modanum++] = port;
318 modargs[modanum++] = "-D";
319 modargs[modanum++] = manager;
320 modargs[modanum++] = "-w";
321 modargs[modanum++] = passwd;
322 modargs[modanum++] = "-l";
323 modargs[modanum++] = loops;
324 modargs[modanum++] = "-e";
325 modargs[modanum++] = NULL; /* will hold the modify entry */
326 modargs[modanum++] = "-a";;
327 modargs[modanum++] = NULL; /* will hold the ava */
328 modargs[modanum++] = NULL;
331 * generate the add/delete clients
335 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
337 aargs[aanum++] = acmd;
339 aargs[aanum++] = "-H";
340 aargs[aanum++] = uri;
342 aargs[aanum++] = "-h";
343 aargs[aanum++] = host;
344 aargs[aanum++] = "-p";
345 aargs[aanum++] = port;
347 aargs[aanum++] = "-D";
348 aargs[aanum++] = manager;
349 aargs[aanum++] = "-w";
350 aargs[aanum++] = passwd;
351 aargs[aanum++] = "-l";
352 aargs[aanum++] = loops;
353 aargs[aanum++] = "-f";
354 aargs[aanum++] = NULL; /* will hold the add data file */
355 aargs[aanum++] = NULL;
357 for ( j = 0; j < MAXREQS; j++ ) {
361 sargs[sanum - 2] = sreqs[j];
362 sargs[sanum - 4] = sbase[j];
363 fork_child( scmd, sargs );
369 rargs[ranum - 2] = rreqs[j];
370 fork_child( rcmd, rargs );
376 margs[manum - 2] = mreqs[j];
377 fork_child( mcmd, margs );
382 modargs[modanum - 4] = moddn[j];
383 modargs[modanum - 2] = modreqs[j];
384 fork_child( modcmd, modargs );
390 aargs[aanum - 2] = afiles[j];
391 fork_child( acmd, aargs );
399 exit( EXIT_SUCCESS );
403 get_file_name( char *dirname, char *filename )
405 char buf[MAXPATHLEN];
407 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
409 return( strdup( buf ));
414 get_search_filters( char *filename, char *filters[], char *bases[] )
419 if ( (fp = fopen( filename, "r" )) != NULL ) {
422 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
425 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
427 bases[filter] = ArgDup( line );
428 fgets( line, BUFSIZ, fp );
429 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
432 filters[filter++] = ArgDup( line );
443 get_read_entries( char *filename, char *entries[] )
448 if ( (fp = fopen( filename, "r" )) != NULL ) {
451 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
454 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
456 entries[entry++] = ArgDup( line );
467 fork_child( char *prog, char **args )
471 wait4kids( maxkids );
473 switch ( pid = fork() ) {
476 /* The __LIBASCII execvp only handles ASCII "prog",
477 * we still need to translate the arg vec ourselves.
479 { char *arg2[MAXREQS];
482 for (i=0; args[i]; i++) {
483 arg2[i] = ArgDup(args[i]);
489 execvp( prog, args );
490 fprintf( stderr, "%s: ", prog );
492 exit( EXIT_FAILURE );
495 case -1: /* trouble */
496 fprintf( stderr, "Could not fork to run %s\n", prog );
500 default: /* parent */
507 wait4kids( int nkidval )
511 while ( nkids >= nkidval ) {
514 if ( WIFSTOPPED(status) ) {
516 "stopping: child stopped with signal %d\n",
517 (int) WSTOPSIG(status) );
519 } else if ( WIFSIGNALED(status) ) {
521 "stopping: child terminated with signal %d%s\n",
522 (int) WTERMSIG(status),
524 WCOREDUMP(status) ? ", core dumped" : ""
529 exit( WEXITSTATUS(status) );
531 } else if ( WEXITSTATUS(status) != 0 ) {
533 "stopping: child exited with status %d\n",
534 (int) WEXITSTATUS(status) );
535 exit( WEXITSTATUS(status) );
545 wait4kids( int nkidval )
549 while ( nkids >= nkidval ) {
550 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
551 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
552 children[i] = children[i+1];
558 fork_child( char *prog, char **args )
562 wait4kids( maxkids );
564 rc = _spawnvp( _P_NOWAIT, prog, args );
567 fprintf( stderr, "%s: ", prog );
570 children[nkids++] = (HANDLE)rc;