]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-tester.c
added new test slapd-modify (based on slapd-modrdn). Adds a single attribute to an...
[openldap] / tests / progs / slapd-tester.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2004 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
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>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This work was initially developed by Kurt Spanier for inclusion
17  * in OpenLDAP Software.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdlib.h>
25
26 #include <ac/ctype.h>
27 #include <ac/dirent.h>
28 #include <ac/param.h>
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/unistd.h>
32 #include <ac/wait.h>
33
34
35 #include "ldap_defaults.h"
36
37
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"
43 #define MAXARGS         100
44 #define MAXREQS                 20
45 #define LOOPS                   "100"
46
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"
52
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 );
58
59 static int      maxkids = 20;
60 static int      nkids;
61
62 #ifdef HAVE_WINSOCK
63 static HANDLE   *children;
64 static char argbuf[BUFSIZ];
65 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
66 #else
67 #define ArgDup(x) strdup(x)
68 #endif
69
70 static void
71 usage( char *name )
72 {
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 );
74         exit( EXIT_FAILURE );
75 }
76
77 int
78 main( int argc, char **argv )
79 {
80         int             i, j;
81         char            *uri = NULL;
82         char            *host = "localhost";
83         char            *port = NULL;
84         char            *manager = NULL;
85         char            *passwd = NULL;
86         char            *dirname = NULL;
87         char            *progdir = NULL;
88         char            *loops = LOOPS;
89         DIR                     *datadir;
90         struct dirent   *file;
91         char            *sfile = NULL;
92         char            *sreqs[MAXREQS];
93         char            *sbase[MAXREQS];
94         int         snum = 0;
95         char            *rfile = NULL;
96         char            *rreqs[MAXREQS];
97         int         rnum = 0;
98         char            *afiles[MAXREQS];
99         int         anum = 0;
100         char            *mfile = NULL;
101         char            *mreqs[MAXREQS];
102         int             mnum = 0;
103         char            *sargs[MAXARGS];
104         int                     sanum;
105         char            scmd[MAXPATHLEN];
106         char            *rargs[MAXARGS];
107         int                     ranum;
108         char            rcmd[MAXPATHLEN];
109         char            *aargs[MAXARGS];
110         int                     aanum;
111         char            acmd[MAXPATHLEN];
112         char            *margs[MAXARGS];
113         int             manum;
114         char            mcmd[MAXPATHLEN];
115         char            *modargs[MAXARGS];
116         int             modanum;
117         char            modcmd[MAXPATHLEN];
118         char            *modfile = NULL;
119         char            *modreqs[MAXREQS];
120         char            *moddn[MAXREQS];
121         int             modnum = 0;
122
123         while ( (i = getopt( argc, argv, "H:h:p:D:w:b:d:j:l:P:" )) != EOF ) {
124                 switch( i ) {
125                         case 'H':               /* slapd uri */
126                                 uri = strdup( optarg );
127                         break;
128                                 
129                         case 'h':               /* slapd host */
130                                 host = strdup( optarg );
131                         break;
132
133                         case 'p':               /* the servers port number */
134                                 port = strdup( optarg );
135                                 break;
136
137                         case 'D':               /* slapd manager */
138                                 manager = ArgDup( optarg );
139                         break;
140
141                         case 'w':               /* the managers passwd */
142                                 passwd = ArgDup( optarg );
143                                 break;
144
145                         case 'd':               /* data directory */
146                                 dirname = strdup( optarg );
147                         break;
148
149                         case 'P':               /* prog directory */
150                                 progdir = strdup( optarg );
151                         break;
152
153                         case 'j':               /* the number of parallel clients */
154                                 maxkids = atoi( optarg );
155                                 break;
156
157                         case 'l':               /* the number of loops per client */
158                                 loops = strdup( optarg );
159                                 break;
160
161                         default:
162                                 usage( argv[0] );
163                                 break;
164                 }
165         }
166
167         if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
168                         ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
169                 usage( argv[0] );
170
171 #ifdef HAVE_WINSOCK
172         children = malloc( maxkids * sizeof(HANDLE) );
173 #endif
174         /* get the file list */
175         if ( ( datadir = opendir( dirname )) == NULL ) {
176
177                 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
178                                         argv[0], dirname );
179                 exit( EXIT_FAILURE );
180
181         }
182
183         /*  look for search, read, modrdn, and add/delete files */
184         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
185
186                 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
187                         sfile = get_file_name( dirname, file->d_name );
188                         continue;
189                 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
190                         rfile = get_file_name( dirname, file->d_name );
191                         continue;
192                 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
193                         mfile = get_file_name( dirname, file->d_name );
194                         continue;
195                 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
196                         modfile = get_file_name( dirname, file->d_name );
197                         continue;
198                 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
199                         && ( anum < MAXREQS )) {
200                         afiles[anum++] = get_file_name( dirname, file->d_name );
201                         continue;
202                 }
203         }
204
205         closedir( datadir );
206
207         /* look for search requests */
208         if ( sfile ) {
209                 snum = get_search_filters( sfile, sreqs, sbase );
210         }
211
212         /* look for read requests */
213         if ( rfile ) {
214                 rnum = get_read_entries( rfile, rreqs );
215         }
216
217         /* look for modrdn requests */
218         if ( mfile ) {
219                 mnum = get_read_entries( mfile, mreqs );
220         }
221         /* look for modify requests */
222         if ( modfile ) {
223                 modnum = get_search_filters( modfile, modreqs, moddn );
224         }
225
226         /*
227          * generate the search clients
228          */
229
230         sanum = 0;
231         snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
232                 progdir );
233         sargs[sanum++] = scmd;
234         if ( uri ) {
235                 sargs[sanum++] = "-H";
236                 sargs[sanum++] = uri;
237         } else {
238                 sargs[sanum++] = "-h";
239                 sargs[sanum++] = host;
240                 sargs[sanum++] = "-p";
241                 sargs[sanum++] = port;
242         }
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;
250
251         /*
252          * generate the read clients
253          */
254
255         ranum = 0;
256         snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
257                 progdir );
258         rargs[ranum++] = rcmd;
259         if ( uri ) {
260                 rargs[ranum++] = "-H";
261                 rargs[ranum++] = uri;
262         } else {
263                 rargs[ranum++] = "-h";
264                 rargs[ranum++] = host;
265                 rargs[ranum++] = "-p";
266                 rargs[ranum++] = port;
267         }
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;
273
274         /*
275          * generate the modrdn clients
276          */
277
278         manum = 0;
279         snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
280                 progdir );
281         margs[manum++] = mcmd;
282         if ( uri ) {
283                 margs[manum++] = "-H";
284                 margs[manum++] = uri;
285         } else {
286                 margs[manum++] = "-h";
287                 margs[manum++] = host;
288                 margs[manum++] = "-p";
289                 margs[manum++] = port;
290         }
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;
300         
301         /*
302          * generate the modify clients
303          */
304
305         modanum = 0;
306         snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
307                 progdir );
308         modargs[modanum++] = modcmd;
309         if ( uri ) {
310                 modargs[modanum++] = "-H";
311                 modargs[modanum++] = uri;
312         } else {
313                 modargs[modanum++] = "-h";
314                 modargs[modanum++] = host;
315                 modargs[modanum++] = "-p";
316                 modargs[modanum++] = port;
317         }
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;
329
330         /*
331          * generate the add/delete clients
332          */
333
334         aanum = 0;
335         snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
336                 progdir );
337         aargs[aanum++] = acmd;
338         if ( uri ) {
339                 aargs[aanum++] = "-H";
340                 aargs[aanum++] = uri;
341         } else {
342                 aargs[aanum++] = "-h";
343                 aargs[aanum++] = host;
344                 aargs[aanum++] = "-p";
345                 aargs[aanum++] = port;
346         }
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;
356
357         for ( j = 0; j < MAXREQS; j++ ) {
358
359                 if ( j < snum ) {
360
361                         sargs[sanum - 2] = sreqs[j];
362                         sargs[sanum - 4] = sbase[j];
363                         fork_child( scmd, sargs );
364
365                 }
366
367                 if ( j < rnum ) {
368
369                         rargs[ranum - 2] = rreqs[j];
370                         fork_child( rcmd, rargs );
371
372                 }
373
374                 if ( j < mnum ) {
375
376                         margs[manum - 2] = mreqs[j];
377                         fork_child( mcmd, margs );
378
379                 }
380                 if ( j < modnum ) {
381
382                         modargs[modanum - 4] = moddn[j];
383                         modargs[modanum - 2] = modreqs[j];
384                         fork_child( modcmd, modargs );
385
386                 }
387
388                 if ( j < anum ) {
389
390                         aargs[aanum - 2] = afiles[j];
391                         fork_child( acmd, aargs );
392
393                 }
394
395         }
396
397         wait4kids( -1 );
398
399         exit( EXIT_SUCCESS );
400 }
401
402 static char *
403 get_file_name( char *dirname, char *filename )
404 {
405         char buf[MAXPATHLEN];
406
407         snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
408                 dirname, filename );
409         return( strdup( buf ));
410 }
411
412
413 static int
414 get_search_filters( char *filename, char *filters[], char *bases[] )
415 {
416         FILE    *fp;
417         int     filter = 0;
418
419         if ( (fp = fopen( filename, "r" )) != NULL ) {
420                 char  line[BUFSIZ];
421
422                 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
423                         char *nl;
424
425                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
426                                 *nl = '\0';
427                         bases[filter] = ArgDup( line );
428                         fgets( line, BUFSIZ, fp );
429                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
430                                 *nl = '\0';
431
432                         filters[filter++] = ArgDup( line );
433
434                 }
435                 fclose( fp );
436         }
437
438         return( filter );
439 }
440
441
442 static int
443 get_read_entries( char *filename, char *entries[] )
444 {
445         FILE    *fp;
446         int     entry = 0;
447
448         if ( (fp = fopen( filename, "r" )) != NULL ) {
449                 char  line[BUFSIZ];
450
451                 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
452                         char *nl;
453
454                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
455                                 *nl = '\0';
456                         entries[entry++] = ArgDup( line );
457
458                 }
459                 fclose( fp );
460         }
461
462         return( entry );
463 }
464
465 #ifndef HAVE_WINSOCK
466 static void
467 fork_child( char *prog, char **args )
468 {
469         pid_t   pid;
470
471         wait4kids( maxkids );
472
473         switch ( pid = fork() ) {
474         case 0:         /* child */
475 #ifdef HAVE_EBCDIC
476                 /* The __LIBASCII execvp only handles ASCII "prog",
477                  * we still need to translate the arg vec ourselves.
478                  */
479                 { char *arg2[MAXREQS];
480                 int i;
481
482                 for (i=0; args[i]; i++) {
483                         arg2[i] = ArgDup(args[i]);
484                         __atoe(arg2[i]);
485                 }
486                 arg2[i] = NULL;
487                 args = arg2; }
488 #endif
489                 execvp( prog, args );
490                 fprintf( stderr, "%s: ", prog );
491                 perror( "execv" );
492                 exit( EXIT_FAILURE );
493                 break;
494
495         case -1:        /* trouble */
496                 fprintf( stderr, "Could not fork to run %s\n", prog );
497                 perror( "fork" );
498                 break;
499
500         default:        /* parent */
501                 nkids++;
502                 break;
503         }
504 }
505
506 static void
507 wait4kids( int nkidval )
508 {
509         int             status;
510
511         while ( nkids >= nkidval ) {
512                 wait( &status );
513
514                 if ( WIFSTOPPED(status) ) {
515                         fprintf( stderr,
516                             "stopping: child stopped with signal %d\n",
517                             (int) WSTOPSIG(status) );
518
519                 } else if ( WIFSIGNALED(status) ) {
520                         fprintf( stderr, 
521                             "stopping: child terminated with signal %d%s\n",
522                             (int) WTERMSIG(status),
523 #ifdef WCOREDUMP
524                                 WCOREDUMP(status) ? ", core dumped" : ""
525 #else
526                                 ""
527 #endif
528                                 );
529                         exit( WEXITSTATUS(status)  );
530
531                 } else if ( WEXITSTATUS(status) != 0 ) {
532                         fprintf( stderr, 
533                             "stopping: child exited with status %d\n",
534                             (int) WEXITSTATUS(status) );
535                         exit( WEXITSTATUS(status) );
536
537                 } else {
538                         nkids--;
539                 }
540         }
541 }
542 #else
543
544 static void
545 wait4kids( int nkidval )
546 {
547         int rc, i;
548
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];
553                 nkids--;
554         }
555 }
556
557 static void
558 fork_child( char *prog, char **args )
559 {
560         int rc;
561
562         wait4kids( maxkids );
563
564         rc = _spawnvp( _P_NOWAIT, prog, args );
565
566         if ( rc == -1 ) {
567                 fprintf( stderr, "%s: ", prog );
568                 perror("spawnvp");
569         } else {
570                 children[nkids++] = (HANDLE)rc;
571         }
572 }
573 #endif