]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-tester.c
Added support for "-H" arg with LDAP uri / ldap_initialize
[openldap] / tests / progs / slapd-tester.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 #include "portable.h"
7
8 #include <stdio.h>
9
10 #include <ac/stdlib.h>
11
12 #include <ac/ctype.h>
13 #include <ac/dirent.h>
14 #include <ac/param.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
17 #include <ac/unistd.h>
18 #include <ac/wait.h>
19
20
21 #include "ldap_defaults.h"
22
23
24 #define SEARCHCMD               "slapd-search"
25 #define READCMD                 "slapd-read"
26 #define ADDCMD                  "slapd-addel"
27 #define MAXARGS         100
28 #define MAXREQS                 20
29 #define LOOPS                   "100"
30
31 #define TSEARCHFILE             "do_search.0"
32 #define TREADFILE               "do_read.0"
33 #define TADDFILE                "do_add."
34
35 static char *get_file_name( char *dirname, char *filename );
36 static int  get_search_filters( char *filename, char *filters[] );
37 static int  get_read_entries( char *filename, char *entries[] );
38 static void fork_child( char *prog, char **args );
39 static void     wait4kids( int nkidval );
40
41 static int      maxkids = 20;
42 static int      nkids;
43
44 #ifdef HAVE_WINSOCK
45 static HANDLE   *children;
46 static char argbuf[BUFSIZ];
47 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
48 #else
49 #define ArgDup(x) strdup(x)
50 #endif
51
52 static void
53 usage( char *name )
54 {
55         fprintf( stderr, "usage: %s [-h <host>] -p <port> -D <manager> -w <passwd> -d <datadir> -b <baseDN> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
56         exit( EXIT_FAILURE );
57 }
58
59 int
60 main( int argc, char **argv )
61 {
62         int             i, j;
63         char            *uri = NULL;
64         char            *host = "localhost";
65         char            *port = NULL;
66         char            *manager = NULL;
67         char            *passwd = NULL;
68         char            *dirname = NULL;
69         char        *sbase = NULL;
70         char            *progdir = NULL;
71         char            *loops = LOOPS;
72         DIR                     *datadir;
73         struct dirent   *file;
74         char            *sfile = NULL;
75         char            *sreqs[MAXREQS];
76         int         snum = 0;
77         char            *rfile = NULL;
78         char            *rreqs[MAXREQS];
79         int         rnum = 0;
80         char            *afiles[MAXREQS];
81         int         anum = 0;
82         char            *sargs[MAXARGS];
83         int                     sanum;
84         char            scmd[MAXPATHLEN];
85         char            *rargs[MAXARGS];
86         int                     ranum;
87         char            rcmd[MAXPATHLEN];
88         char            *aargs[MAXARGS];
89         int                     aanum;
90         char            acmd[MAXPATHLEN];
91
92         while ( (i = getopt( argc, argv, "H:h:p:D:w:b:d:j:l:P:" )) != EOF ) {
93                 switch( i ) {
94                         case 'H':               /* slapd uri */
95                                 uri = strdup( optarg );
96                         break;
97                                 
98                         case 'h':               /* slapd host */
99                                 host = strdup( optarg );
100                         break;
101
102                         case 'p':               /* the servers port number */
103                                 port = strdup( optarg );
104                                 break;
105
106                         case 'D':               /* slapd manager */
107                                 manager = ArgDup( optarg );
108                         break;
109
110                         case 'w':               /* the managers passwd */
111                                 passwd = ArgDup( optarg );
112                                 break;
113
114                         case 'b':               /* the base DN */
115                                 sbase = ArgDup( optarg );
116                                 break;
117
118                         case 'd':               /* data directory */
119                                 dirname = strdup( optarg );
120                         break;
121
122                         case 'P':               /* prog directory */
123                                 progdir = strdup( optarg );
124                         break;
125
126                         case 'j':               /* the number of parallel clients */
127                                 maxkids = atoi( optarg );
128                                 break;
129
130                         case 'l':               /* the number of loops per client */
131                                 loops = strdup( optarg );
132                                 break;
133
134                         default:
135                                 usage( argv[0] );
136                                 break;
137                 }
138         }
139
140         if (( dirname == NULL ) || ( sbase == NULL ) || ( port == NULL && uri == NULL ) ||
141                         ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
142                 usage( argv[0] );
143
144 #ifdef HAVE_WINSOCK
145         children = malloc( maxkids * sizeof(HANDLE) );
146 #endif
147         /* get the file list */
148         if ( ( datadir = opendir( dirname )) == NULL ) {
149
150                 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
151                                         argv[0], dirname );
152                 exit( EXIT_FAILURE );
153
154         }
155
156         /*  look for search, read, and add/delete files */
157         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
158
159                 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
160                         sfile = get_file_name( dirname, file->d_name );
161                         continue;
162                 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
163                         rfile = get_file_name( dirname, file->d_name );
164                         continue;
165                 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
166                         && ( anum < MAXREQS )) {
167                         afiles[anum++] = get_file_name( dirname, file->d_name );
168                         continue;
169                 }
170         }
171
172         closedir( datadir );
173
174         /* look for search requests */
175         if ( sfile ) {
176                 snum = get_search_filters( sfile, sreqs );
177         }
178
179         /* look for read requests */
180         if ( rfile ) {
181                 rnum = get_read_entries( rfile, rreqs );
182         }
183
184         /*
185          * generate the search clients
186          */
187
188         sanum = 0;
189         snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
190                 progdir );
191         sargs[sanum++] = scmd;
192         if ( uri ) {
193                 sargs[sanum++] = "-H";
194                 sargs[sanum++] = uri;
195         } else {
196                 sargs[sanum++] = "-h";
197                 sargs[sanum++] = host;
198                 sargs[sanum++] = "-p";
199                 sargs[sanum++] = port;
200         }
201         sargs[sanum++] = "-b";
202         sargs[sanum++] = sbase;
203         sargs[sanum++] = "-l";
204         sargs[sanum++] = loops;
205         sargs[sanum++] = "-f";
206         sargs[sanum++] = NULL;          /* will hold the search request */
207         sargs[sanum++] = NULL;
208
209         /*
210          * generate the read clients
211          */
212
213         ranum = 0;
214         snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
215                 progdir );
216         rargs[ranum++] = rcmd;
217         if ( uri ) {
218                 rargs[ranum++] = "-H";
219                 rargs[ranum++] = uri;
220         } else {
221                 rargs[ranum++] = "-h";
222                 rargs[ranum++] = host;
223                 rargs[ranum++] = "-p";
224                 rargs[ranum++] = port;
225         }
226         rargs[ranum++] = "-l";
227         rargs[ranum++] = loops;
228         rargs[ranum++] = "-e";
229         rargs[ranum++] = NULL;          /* will hold the read entry */
230         rargs[ranum++] = NULL;
231
232         /*
233          * generate the add/delete clients
234          */
235
236         aanum = 0;
237         snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
238                 progdir );
239         aargs[aanum++] = acmd;
240         if ( uri ) {
241                 aargs[aanum++] = "-H";
242                 aargs[aanum++] = uri;
243         } else {
244                 aargs[aanum++] = "-h";
245                 aargs[aanum++] = host;
246                 aargs[aanum++] = "-p";
247                 aargs[aanum++] = port;
248         }
249         aargs[aanum++] = "-D";
250         aargs[aanum++] = manager;
251         aargs[aanum++] = "-w";
252         aargs[aanum++] = passwd;
253         aargs[aanum++] = "-l";
254         aargs[aanum++] = loops;
255         aargs[aanum++] = "-f";
256         aargs[aanum++] = NULL;          /* will hold the add data file */
257         aargs[aanum++] = NULL;
258
259         for ( j = 0; j < MAXREQS; j++ ) {
260
261                 if ( j < snum ) {
262
263                         sargs[sanum - 2] = sreqs[j];
264                         fork_child( scmd, sargs );
265
266                 }
267
268                 if ( j < rnum ) {
269
270                         rargs[ranum - 2] = rreqs[j];
271                         fork_child( rcmd, rargs );
272
273                 }
274
275                 if ( j < anum ) {
276
277                         aargs[aanum - 2] = afiles[j];
278                         fork_child( acmd, aargs );
279
280                 }
281
282         }
283
284         wait4kids( -1 );
285
286         exit( EXIT_SUCCESS );
287 }
288
289 static char *
290 get_file_name( char *dirname, char *filename )
291 {
292         char buf[MAXPATHLEN];
293
294         snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
295                 dirname, filename );
296         return( strdup( buf ));
297 }
298
299
300 static int
301 get_search_filters( char *filename, char *filters[] )
302 {
303         FILE    *fp;
304         int     filter = 0;
305
306         if ( (fp = fopen( filename, "r" )) != NULL ) {
307                 char  line[BUFSIZ];
308
309                 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
310                         char *nl;
311
312                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
313                                 *nl = '\0';
314                         filters[filter++] = ArgDup( line );
315
316                 }
317                 fclose( fp );
318         }
319
320         return( filter );
321 }
322
323
324 static int
325 get_read_entries( char *filename, char *entries[] )
326 {
327         FILE    *fp;
328         int     entry = 0;
329
330         if ( (fp = fopen( filename, "r" )) != NULL ) {
331                 char  line[BUFSIZ];
332
333                 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
334                         char *nl;
335
336                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
337                                 *nl = '\0';
338                         entries[entry++] = ArgDup( line );
339
340                 }
341                 fclose( fp );
342         }
343
344         return( entry );
345 }
346
347 #ifndef HAVE_WINSOCK
348 static void
349 fork_child( char *prog, char **args )
350 {
351         pid_t   pid;
352
353         wait4kids( maxkids );
354
355         switch ( pid = fork() ) {
356         case 0:         /* child */
357 #ifdef HAVE_EBCDIC
358                 /* The __LIBASCII execvp only handles ASCII "prog",
359                  * we still need to translate the arg vec ourselves.
360                  */
361                 { char *arg2[MAXREQS];
362                 int i;
363
364                 for (i=0; args[i]; i++) {
365                         arg2[i] = ArgDup(args[i]);
366                         __atoe(arg2[i]);
367                 }
368                 arg2[i] = NULL;
369                 args = arg2; }
370 #endif
371                 execvp( prog, args );
372                 fprintf( stderr, "%s: ", prog );
373                 perror( "execv" );
374                 exit( EXIT_FAILURE );
375                 break;
376
377         case -1:        /* trouble */
378                 fprintf( stderr, "Could not fork to run %s\n", prog );
379                 perror( "fork" );
380                 break;
381
382         default:        /* parent */
383                 nkids++;
384                 break;
385         }
386 }
387
388 static void
389 wait4kids( int nkidval )
390 {
391         int             status;
392
393         while ( nkids >= nkidval ) {
394                 wait( &status );
395
396                 if ( WIFSTOPPED(status) ) {
397                         fprintf( stderr,
398                             "stopping: child stopped with signal %d\n",
399                             (int) WSTOPSIG(status) );
400
401                 } else if ( WIFSIGNALED(status) ) {
402                         fprintf( stderr, 
403                             "stopping: child terminated with signal %d%s\n",
404                             (int) WTERMSIG(status),
405 #ifdef WCOREDUMP
406                                 WCOREDUMP(status) ? ", core dumped" : ""
407 #else
408                                 ""
409 #endif
410                                 );
411                         exit( WEXITSTATUS(status)  );
412
413                 } else if ( WEXITSTATUS(status) != 0 ) {
414                         fprintf( stderr, 
415                             "stopping: child exited with status %d\n",
416                             (int) WEXITSTATUS(status) );
417                         exit( WEXITSTATUS(status) );
418
419                 } else {
420                         nkids--;
421                 }
422         }
423 }
424 #else
425
426 static void
427 wait4kids( int nkidval )
428 {
429         int rc, i;
430
431         while ( nkids >= nkidval ) {
432                 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
433                 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
434                         children[i] = children[i+1];
435                 nkids--;
436         }
437 }
438
439 static void
440 fork_child( char *prog, char **args )
441 {
442         int rc;
443
444         wait4kids( maxkids );
445
446         rc = _spawnvp( _P_NOWAIT, prog, args );
447
448         if ( rc == -1 ) {
449                 fprintf( stderr, "%s: ", prog );
450                 perror("spawnvp");
451         } else {
452                 children[nkids++] = (HANDLE)rc;
453         }
454 }
455 #endif