]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-addel.c
Note ITS#5177 was fixed in 2.3.39
[openldap] / tests / progs / slapd-addel.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2007 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/param.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/unistd.h>
31 #include <ac/wait.h>
32
33 #define LDAP_DEPRECATED 1
34 #include <ldap.h>
35 #include <lutil.h>
36
37 #define LOOPS   100
38 #define RETRIES 0
39
40 static char *
41 get_add_entry( char *filename, LDAPMod ***mods );
42
43 static void
44 do_addel( char *uri, char *host, int port, char *manager, char *passwd,
45         char *dn, LDAPMod **attrs, int maxloop, int maxretries, int delay,
46         int friendly );
47
48 static void
49 usage( char *name )
50 {
51         fprintf( stderr,
52                 "usage: %s "
53                 "-H <uri> | ([-h <host>] -p <port>) "
54                 "-D <manager> "
55                 "-w <passwd> "
56                 "-f <addfile> "
57                 "[-l <loops>] "
58                 "[-r <maxretries>] "
59                 "[-t <delay>] "
60                 "[-F]\n",
61                         name );
62         exit( EXIT_FAILURE );
63 }
64
65 int
66 main( int argc, char **argv )
67 {
68         int             i;
69         char            *host = "localhost";
70         char            *uri = NULL;
71         int             port = -1;
72         char            *manager = NULL;
73         char            *passwd = NULL;
74         char            *filename = NULL;
75         char            *entry = NULL;
76         int             loops = LOOPS;
77         int             retries = RETRIES;
78         int             delay = 0;
79         int             friendly = 0;
80         LDAPMod         **attrs = NULL;
81
82         while ( (i = getopt( argc, argv, "FH:h:p:D:w:f:l:r:t:" )) != EOF ) {
83                 switch( i ) {
84                 case 'F':
85                         friendly++;
86                         break;
87                         
88                 case 'H':               /* the server's URI */
89                         uri = strdup( optarg );
90                         break;
91
92                 case 'h':               /* the servers host */
93                         host = strdup( optarg );
94                         break;
95
96                 case 'p':               /* the servers port */
97                         if ( lutil_atoi( &port, optarg ) != 0 ) {
98                                 usage( argv[0] );
99                         }
100                         break;
101
102                 case 'D':               /* the servers manager */
103                         manager = strdup( optarg );
104                         break;
105
106                 case 'w':               /* the server managers password */
107                         passwd = strdup( optarg );
108                         break;
109
110                 case 'f':               /* file with entry search request */
111                         filename = strdup( optarg );
112                         break;
113
114                 case 'l':               /* the number of loops */
115                         if ( lutil_atoi( &loops, optarg ) != 0 ) {
116                                 usage( argv[0] );
117                         }
118                         break;
119
120                 case 'r':               /* number of retries */
121                         if ( lutil_atoi( &retries, optarg ) != 0 ) {
122                                 usage( argv[0] );
123                         }
124                         break;
125
126                 case 't':               /* delay in seconds */
127                         if ( lutil_atoi( &delay, optarg ) != 0 ) {
128                                 usage( argv[0] );
129                         }
130                         break;
131
132                 default:
133                         usage( argv[0] );
134                         break;
135                 }
136         }
137
138         if (( filename == NULL ) || ( port == -1 && uri == NULL ) ||
139                                 ( manager == NULL ) || ( passwd == NULL ))
140                 usage( argv[0] );
141
142         entry = get_add_entry( filename, &attrs );
143         if (( entry == NULL ) || ( *entry == '\0' )) {
144
145                 fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
146                                 argv[0], filename );
147                 exit( EXIT_FAILURE );
148
149         }
150
151         if (( attrs == NULL ) || ( *attrs == '\0' )) {
152
153                 fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
154                                 argv[0], filename );
155                 exit( EXIT_FAILURE );
156
157         }
158
159         do_addel( uri, host, port, manager, passwd, entry, attrs,
160                         loops, retries, delay, friendly );
161
162         exit( EXIT_SUCCESS );
163 }
164
165
166 static void
167 addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
168 {
169     LDAPMod             **pmods;
170     int                 i, j;
171     struct berval       *bvp;
172
173     pmods = *pmodsp;
174     modop |= LDAP_MOD_BVALUES;
175
176     i = 0;
177     if ( pmods != NULL ) {
178                 for ( ; pmods[ i ] != NULL; ++i ) {
179                 if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
180                         pmods[ i ]->mod_op == modop ) {
181                                 break;
182                 }
183                 }
184     }
185
186     if ( pmods == NULL || pmods[ i ] == NULL ) {
187                 if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
188                         sizeof( LDAPMod * ))) == NULL ) {
189                         perror( "realloc" );
190                         exit( EXIT_FAILURE );
191                 }
192                 *pmodsp = pmods;
193                 pmods[ i + 1 ] = NULL;
194                 if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
195                         == NULL ) {
196                         perror( "calloc" );
197                         exit( EXIT_FAILURE );
198                 }
199                 pmods[ i ]->mod_op = modop;
200                 if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
201                 perror( "strdup" );
202                 exit( EXIT_FAILURE );
203                 }
204     }
205
206     if ( value != NULL ) {
207                 j = 0;
208                 if ( pmods[ i ]->mod_bvalues != NULL ) {
209                 for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
210                                 ;
211                 }
212                 }
213                 if (( pmods[ i ]->mod_bvalues =
214                         (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
215                         (j + 2) * sizeof( struct berval * ))) == NULL ) {
216                         perror( "ber_realloc" );
217                         exit( EXIT_FAILURE );
218                 }
219                 pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
220                 if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
221                         == NULL ) {
222                         perror( "malloc" );
223                         exit( EXIT_FAILURE );
224                 }
225                 pmods[ i ]->mod_bvalues[ j ] = bvp;
226
227             bvp->bv_len = vlen;
228             if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
229                         perror( "malloc" );
230                         exit( EXIT_FAILURE );
231             }
232             AC_MEMCPY( bvp->bv_val, value, vlen );
233             bvp->bv_val[ vlen ] = '\0';
234     }
235 }
236
237
238 static char *
239 get_add_entry( char *filename, LDAPMod ***mods )
240 {
241         FILE    *fp;
242         char    *entry = NULL;
243
244         if ( (fp = fopen( filename, "r" )) != NULL ) {
245                 char  line[BUFSIZ];
246
247                 if ( fgets( line, BUFSIZ, fp )) {
248                         char *nl;
249
250                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
251                                 *nl = '\0';
252                         entry = strdup( line );
253
254                 }
255
256                 while ( fgets( line, BUFSIZ, fp )) {
257                         char    *nl;
258                         char    *value;
259
260                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
261                                 *nl = '\0';
262
263                         if ( *line == '\0' ) break;
264                         if ( !( value = strchr( line, ':' ))) break;
265
266                         *value++ = '\0'; 
267                         while ( *value && isspace( (unsigned char) *value ))
268                                 value++;
269
270                         addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
271
272                 }
273                 fclose( fp );
274         }
275
276         return( entry );
277 }
278
279
280 static void
281 do_addel(
282         char *uri,
283         char *host,
284         int port,
285         char *manager,
286         char *passwd,
287         char *entry,
288         LDAPMod **attrs,
289         int maxloop,
290         int maxretries,
291         int delay,
292         int friendly
293 )
294 {
295         LDAP    *ld = NULL;
296         int     i = 0, do_retry = maxretries;
297         pid_t   pid = getpid();
298         int     rc = LDAP_SUCCESS;
299
300 retry:;
301         if ( uri ) {
302                 ldap_initialize( &ld, uri );
303         } else {
304                 ld = ldap_init( host, port );
305         }
306         if ( ld == NULL ) {
307                 perror( "ldap_init" );
308                 exit( EXIT_FAILURE );
309         }
310
311         {
312                 int version = LDAP_VERSION3;
313                 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
314                         &version ); 
315         }
316
317         if ( do_retry == maxretries ) {
318                 fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
319                         (long) pid, maxloop, entry );
320         }
321
322         rc = ldap_bind_s( ld, manager, passwd, LDAP_AUTH_SIMPLE );
323         if ( rc != LDAP_SUCCESS ) {
324                 ldap_perror( ld, "ldap_bind" );
325                 switch ( rc ) {
326                 case LDAP_BUSY:
327                 case LDAP_UNAVAILABLE:
328                         if ( do_retry > 0 ) {
329                                 do_retry--;
330                                 if ( delay != 0 ) {
331                                     sleep( delay );
332                                 }
333                                 goto retry;
334                         }
335                 /* fallthru */
336                 default:
337                         break;
338                 }
339                 exit( EXIT_FAILURE );
340         }
341
342         for ( ; i < maxloop; i++ ) {
343
344                 /* add the entry */
345                 rc = ldap_add_s( ld, entry, attrs );
346                 if ( rc != LDAP_SUCCESS ) {
347                         ldap_perror( ld, "ldap_add" );
348                         switch ( rc ) {
349                         case LDAP_ALREADY_EXISTS:
350                                 /* NOTE: this likely means
351                                  * the delete failed
352                                  * during the previous round... */
353                                 if ( !friendly ) {
354                                         goto done;
355                                 }
356                                 break;
357
358                         case LDAP_BUSY:
359                         case LDAP_UNAVAILABLE:
360                                 if ( do_retry > 0 ) {
361                                         do_retry--;
362                                         goto retry;
363                                 }
364                                 /* fall thru */
365
366                         default:
367                                 goto done;
368                         }
369                 }
370
371 #if 0
372                 /* wait a second for the add to really complete */
373                 /* This masks some race conditions though. */
374                 sleep( 1 );
375 #endif
376
377                 /* now delete the entry again */
378                 rc = ldap_delete_s( ld, entry );
379                 if ( rc != LDAP_SUCCESS ) {
380                         ldap_perror( ld, "ldap_delete" );
381                         switch ( rc ) {
382                         case LDAP_NO_SUCH_OBJECT:
383                                 /* NOTE: this likely means
384                                  * the add failed
385                                  * during the previous round... */
386                                 if ( !friendly ) {
387                                         goto done;
388                                 }
389                                 break;
390
391                         case LDAP_BUSY:
392                         case LDAP_UNAVAILABLE:
393                                 if ( do_retry > 0 ) {
394                                         do_retry--;
395                                         goto retry;
396                                 }
397                                 /* fall thru */
398
399                         default:
400                                 goto done;
401                         }
402                 }
403         }
404
405 done:;
406         fprintf( stderr, " PID=%ld - Add/Delete done (%d).\n", (long) pid, rc );
407
408         ldap_unbind( ld );
409 }
410
411