]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-tester.c
Don't shutdown when select() returns EBADF.
[openldap] / tests / progs / slapd-tester.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/stdlib.h>
6
7 #include <ac/ctype.h>
8 #include <ac/dirent.h>
9 #include <ac/socket.h>
10 #include <ac/string.h>
11 #include <ac/unistd.h>
12 #include <ac/wait.h>
13
14 #ifdef HAVE_SYS_PARAM_H
15 #include <sys/param.h>
16 #endif
17
18 #include "ldapconfig.h"
19
20
21 #define SEARCHCMD               "slapd-search"
22 #define READCMD                 "slapd-read"
23 #define ADDCMD                  "slapd-addel"
24 #define MAXARGS         100
25 #define MAXREQS                 20
26 #define LOOPS                   "100"
27
28 #define TSEARCHFILE             "do_search.0"
29 #define TREADFILE               "do_read.0"
30 #define TADDFILE                "do_add."
31
32 static char *get_file_name( char *dirname, char *filename );
33 static int  get_search_filters( char *filename, char *filters[] );
34 static int  get_read_entries( char *filename, char *entries[] );
35 static void fork_child( char *prog, char *args[] );
36 static void     wait4kids( int nkidval );
37
38 static int      maxkids = 20;
39 static int      nkids;
40
41 static void
42 usage( char *name )
43 {
44         fprintf( stderr, "usage: %s [-h <host>] -p <port> -D <manager> -w <passwd> -d <datadir> -b <baseDN> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
45         exit( 1 );
46 }
47
48 int
49 main( int argc, char **argv )
50 {
51         int             i, j;
52         char            *host = "localhost";
53         char            *port = NULL;
54         char            *manager = NULL;
55         char            *passwd = NULL;
56         char            *dirname = NULL;
57         char        *sbase = NULL;
58         char            *progdir = NULL;
59         char            *loops = LOOPS;
60         DIR                     *datadir;
61         struct dirent   *file;
62         char            *sfile = NULL;
63         char            *sreqs[MAXREQS];
64         int         snum = 0;
65         char            *rfile = NULL;
66         char            *rreqs[MAXREQS];
67         int         rnum = 0;
68         char            *afiles[MAXREQS];
69         int         anum = 0;
70         char            *sargs[MAXARGS];
71         int                     sanum;
72         char            scmd[MAXPATHLEN];
73         char            *rargs[MAXARGS];
74         int                     ranum;
75         char            rcmd[MAXPATHLEN];
76         char            *aargs[MAXARGS];
77         int                     aanum;
78         char            acmd[MAXPATHLEN];
79
80         while ( (i = getopt( argc, argv, "h:p:D:w:b:d:j:l:P:" )) != EOF ) {
81                 switch( i ) {
82                         case 'h':               /* slapd host */
83                                 host = strdup( optarg );
84                         break;
85
86                         case 'p':               /* the servers port number */
87                                 port = strdup( optarg );
88                                 break;
89
90                         case 'D':               /* slapd manager */
91                                 manager = strdup( optarg );
92                         break;
93
94                         case 'w':               /* the managers passwd */
95                                 passwd = strdup( optarg );
96                                 break;
97
98                         case 'b':               /* the base DN */
99                                 sbase = strdup( optarg );
100                                 break;
101
102                         case 'd':               /* data directory */
103                                 dirname = strdup( optarg );
104                         break;
105
106                         case 'P':               /* prog directory */
107                                 progdir = strdup( optarg );
108                         break;
109
110                         case 'j':               /* the number of parallel clients */
111                                 maxkids = atoi( optarg );
112                                 break;
113
114                         case 'l':               /* the number of loops per client */
115                                 loops = strdup( optarg );
116                                 break;
117
118                         default:
119                                 usage( argv[0] );
120                                 break;
121                 }
122         }
123
124         if (( dirname == NULL ) || ( sbase == NULL ) || ( port == NULL ) ||
125                         ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
126                 usage( argv[0] );
127
128         /* get the file list */
129         if ( ( datadir = opendir( dirname )) == NULL ) {
130
131                 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
132                                         argv[0], dirname );
133                 exit( 1 );
134
135         }
136
137         /*  look for search, read, and add/delete files */
138         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
139
140                 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
141                         sfile = get_file_name( dirname, file->d_name );
142                         continue;
143                 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
144                         rfile = get_file_name( dirname, file->d_name );
145                         continue;
146                 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
147                         && ( anum < MAXREQS )) {
148                         afiles[anum++] = get_file_name( dirname, file->d_name );
149                         continue;
150                 }
151         }
152
153         closedir( datadir );
154
155         /* look for search requests */
156         if ( sfile ) {
157                 snum = get_search_filters( sfile, sreqs );
158         }
159
160         /* look for read requests */
161         if ( rfile ) {
162                 rnum = get_read_entries( rfile, rreqs );
163         }
164
165         /*
166          * generate the search clients
167          */
168
169         sanum = 0;
170         sprintf( scmd, "%s%s%s", progdir, DIRSEP, SEARCHCMD );
171         sargs[sanum++] = scmd;
172         sargs[sanum++] = "-h";
173         sargs[sanum++] = host;
174         sargs[sanum++] = "-p";
175         sargs[sanum++] = port;
176         sargs[sanum++] = "-b";
177         sargs[sanum++] = sbase;
178         sargs[sanum++] = "-l";
179         sargs[sanum++] = loops;
180         sargs[sanum++] = "-f";
181         sargs[sanum++] = NULL;          /* will hold the search request */
182         sargs[sanum++] = NULL;
183
184         /*
185          * generate the read clients
186          */
187
188         ranum = 0;
189         sprintf( rcmd, "%s%s%s", progdir, DIRSEP, READCMD );
190         rargs[ranum++] = rcmd;
191         rargs[ranum++] = "-h";
192         rargs[ranum++] = host;
193         rargs[ranum++] = "-p";
194         rargs[ranum++] = port;
195         rargs[ranum++] = "-l";
196         rargs[ranum++] = loops;
197         rargs[ranum++] = "-e";
198         rargs[ranum++] = NULL;          /* will hold the read entry */
199         rargs[ranum++] = NULL;
200
201         /*
202          * generate the add/delete clients
203          */
204
205         aanum = 0;
206         sprintf( acmd, "%s%s%s", progdir, DIRSEP, ADDCMD );
207         aargs[aanum++] = acmd;
208         aargs[aanum++] = "-h";
209         aargs[aanum++] = host;
210         aargs[aanum++] = "-p";
211         aargs[aanum++] = port;
212         aargs[aanum++] = "-D";
213         aargs[aanum++] = manager;
214         aargs[aanum++] = "-w";
215         aargs[aanum++] = passwd;
216         aargs[aanum++] = "-l";
217         aargs[aanum++] = loops;
218         aargs[aanum++] = "-f";
219         aargs[aanum++] = NULL;          /* will hold the add data file */
220         aargs[aanum++] = NULL;
221
222         for ( j = 0; j < MAXREQS; j++ ) {
223
224                 if ( j < snum ) {
225
226                         sargs[sanum - 2] = sreqs[j];
227                         fork_child( scmd, sargs );
228
229                 }
230
231                 if ( j < rnum ) {
232
233                         rargs[ranum - 2] = rreqs[j];
234                         fork_child( rcmd, rargs );
235
236                 }
237
238                 if ( j < anum ) {
239
240                         aargs[aanum - 2] = afiles[j];
241                         fork_child( acmd, aargs );
242
243                 }
244
245         }
246
247         wait4kids( -1 );
248
249         exit( 0 );
250 }
251
252 static char *
253 get_file_name( char *dirname, char *filename )
254 {
255         char buf[MAXPATHLEN];
256
257         sprintf( buf, "%s%s%s", dirname, DIRSEP, filename );
258         return( strdup( buf ));
259 }
260
261
262 static int
263 get_search_filters( char *filename, char *filters[] )
264 {
265         FILE    *fp;
266         int     filter = 0;
267
268         if ( (fp = fopen( filename, "r" )) != NULL ) {
269                 char  line[BUFSIZ];
270
271                 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
272                         char *nl;
273
274                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
275                                 *nl = '\0';
276                         filters[filter++] = strdup( line );
277
278                 }
279                 fclose( fp );
280         }
281
282         return( filter );
283 }
284
285
286 static int
287 get_read_entries( char *filename, char *entries[] )
288 {
289         FILE    *fp;
290         int     entry = 0;
291
292         if ( (fp = fopen( filename, "r" )) != NULL ) {
293                 char  line[BUFSIZ];
294
295                 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
296                         char *nl;
297
298                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
299                                 *nl = '\0';
300                         entries[entry++] = strdup( line );
301
302                 }
303                 fclose( fp );
304         }
305
306         return( entry );
307 }
308
309
310 static void
311 fork_child( char *prog, char *args[] )
312 {
313         pid_t   pid;
314
315         wait4kids( maxkids );
316
317         switch ( pid = fork() ) {
318         case 0:         /* child */
319                 execvp( prog, args );
320                 fprintf( stderr, "%s: ", prog );
321                 perror( "execv" );
322                 exit( -1 );
323                 break;
324
325         case -1:        /* trouble */
326                 fprintf( stderr, "Could not fork to run %s\n", prog );
327                 perror( "fork" );
328                 break;
329
330         default:        /* parent */
331                 nkids++;
332                 break;
333         }
334 }
335
336 static void
337 wait4kids( int nkidval )
338 {
339         int             status;
340
341         while ( nkids >= nkidval ) {
342                 wait( &status );
343
344                 if ( WIFSTOPPED(status) ) {
345                         fprintf( stderr,
346                             "stopping: child stopped with signal %d\n",
347                             (int) WSTOPSIG(status) );
348
349                 } else if ( WIFSIGNALED(status) ) {
350                         fprintf( stderr, 
351                             "stopping: child terminated with signal %d%s\n",
352                             (int) WTERMSIG(status),
353 #ifdef WCOREDUMP
354                                 WCOREDUMP(status) ? ", core dumped" : ""
355 #else
356                                 ""
357 #endif
358                                 );
359                         exit( WEXITSTATUS(status)  );
360
361                 } else if ( WEXITSTATUS(status) != 0 ) {
362                         fprintf( stderr, 
363                             "stopping: child exited with status %d\n",
364                             (int) WEXITSTATUS(status) );
365                         exit( WEXITSTATUS(status) );
366
367                 } else {
368                         nkids--;
369                 }
370         }
371 }