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