]> git.sur5r.net Git - openldap/blob - clients/tools/ldapmodify.c
Rework client control parsing... need to implement
[openldap] / clients / tools / ldapmodify.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* ldapmodify.c - generic program to modify or add entries using LDAP */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/stdlib.h>
13
14 #include <ac/ctype.h>
15 #include <ac/signal.h>
16 #include <ac/string.h>
17 #include <ac/unistd.h>
18
19 #ifdef HAVE_SYS_STAT_H
20 #include <sys/stat.h>
21 #endif
22
23 #ifdef HAVE_SYS_FILE_H
24 #include <sys/file.h>
25 #endif
26 #ifdef HAVE_FCNTL_H
27 #include <fcntl.h>
28 #endif
29
30 #include <ldap.h>
31
32 #include "lutil.h"
33 #include "lutil_ldap.h"
34 #include "ldif.h"
35 #include "ldap_defaults.h"
36 #include "ldap_log.h"
37
38 static char     *prog;
39 static char     *binddn = NULL;
40 static struct berval passwd = { 0, NULL };
41 static char *ldapuri = NULL;
42 static char     *ldaphost = NULL;
43 static int      ldapport = 0;
44 #ifdef HAVE_CYRUS_SASL
45 static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
46 static char *sasl_realm = NULL;
47 static char     *sasl_authc_id = NULL;
48 static char     *sasl_authz_id = NULL;
49 static char     *sasl_mech = NULL;
50 static char     *sasl_secprops = NULL;
51 #endif
52 static int      use_tls = 0;
53 static int      ldapadd, not, verbose, contoper, force;
54 static LDAP     *ld = NULL;
55
56 #define LDAPMOD_MAXLINE         4096
57
58 /* strings found in replog/LDIF entries (mostly lifted from slurpd/slurp.h) */
59 #define T_VERSION_STR           "version"
60 #define T_REPLICA_STR           "replica"
61 #define T_DN_STR                "dn"
62 #define T_CHANGETYPESTR         "changetype"
63 #define T_ADDCTSTR              "add"
64 #define T_MODIFYCTSTR           "modify"
65 #define T_DELETECTSTR           "delete"
66 #define T_MODRDNCTSTR           "modrdn"
67 #define T_MODDNCTSTR            "moddn"
68 #define T_RENAMECTSTR           "rename"
69 #define T_MODOPADDSTR           "add"
70 #define T_MODOPREPLACESTR       "replace"
71 #define T_MODOPDELETESTR        "delete"
72 #define T_MODSEPSTR             "-"
73 #define T_NEWRDNSTR             "newrdn"
74 #define T_DELETEOLDRDNSTR       "deleteoldrdn"
75 #define T_NEWSUPSTR             "newsuperior"
76
77
78 static void usage LDAP_P(( const char *prog )) LDAP_GCCATTR((noreturn));
79 static int process_ldif_rec LDAP_P(( char *rbuf, int count ));
80 static void addmodifyop LDAP_P((
81         LDAPMod ***pmodsp, int modop,
82         const char *attr,
83         struct berval *value ));
84 static int domodify LDAP_P((
85         const char *dn,
86         LDAPMod **pmods,
87         int newentry ));
88 static int dodelete LDAP_P((
89         const char *dn ));
90 static int dorename LDAP_P((
91         const char *dn,
92         const char *newrdn,
93         const char *newsup,
94         int deleteoldrdn ));
95 static char *read_one_record LDAP_P(( FILE *fp ));
96
97 static void
98 usage( const char *prog )
99 {
100     fprintf( stderr,
101 "Add or modify entries from an LDAP server\n\n"
102 "usage: %s [options]\n"
103 "       The list of desired operations are read from stdin or from the file\n"
104 "       specified by \"-f file\".\n"
105 "Add or modify options:\n"
106 "  -a         add values (default%s)\n"
107 "  -c         continuous operation mode (do not stop on errors)\n"
108 "  -F         force all changes records to be used\n"
109 "  -S file    write skipped modifications to `file'\n"
110
111 "Common options:\n"
112 "  -d level   set LDAP debugging level to `level'\n"
113 "  -D binddn  bind DN\n"
114 "  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
115 "             [!]manageDSAit   (alternate form, see -M)\n"
116 "             [!]noop\n"
117 "  -f file    read operations from `file'\n"
118 "  -h host    LDAP server\n"
119 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
120 "  -I         use SASL Interactive mode\n"
121 "  -k         use Kerberos authentication\n"
122 "  -K         like -k, but do only step 1 of the Kerberos bind\n"
123 "  -M         enable Manage DSA IT control (-MM to make critical)\n"
124 "  -n         show what would be done but don't actually update\n"
125 "  -O props   SASL security properties\n"
126 "  -p port    port on LDAP server\n"
127 "  -P version procotol version (default: 3)\n"
128 "  -Q         use SASL Quiet mode\n"
129 "  -R realm   SASL realm\n"
130 "  -U authcid SASL authentication identity\n"
131 "  -v         run in verbose mode (diagnostics to standard output)\n"
132 "  -w passwd  bind passwd (for simple authentication)\n"
133 "  -W         prompt for bind passwd\n"
134 "  -x         Simple authentication\n"
135 "  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
136 "  -y file    Read passwd from file\n"
137 "  -Y mech    SASL mechanism\n"
138 "  -Z         Start TLS request (-ZZ to require successful response)\n"
139              , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") );
140
141     exit( EXIT_FAILURE );
142 }
143
144
145 int
146 main( int argc, char **argv )
147 {
148     char                *infile, *rejfile, *rbuf, *start, *rejbuf = NULL;
149     FILE                *fp, *rejfp;
150         char            *matched_msg = NULL, *error_msg = NULL;
151         int             rc, i, authmethod, version, want_bindpw, debug, manageDSAit, noop, referrals;
152         int count, len;
153         char    *pw_file = NULL;
154         char    *control, *cvalue;
155         int             crit;
156
157     prog = lutil_progname( "ldapmodify", argc, argv );
158
159     /* Print usage when no parameters */
160     if( argc < 2 ) usage( prog );
161
162         /* strncmp instead of strcmp since NT binaries carry .exe extension */
163     ldapadd = ( strncmp( prog, "ldapadd", sizeof("ldapadd")-1 ) == 0 );
164
165     infile = NULL;
166     rejfile = NULL;
167     not = verbose = want_bindpw = debug = manageDSAit = noop = referrals = 0;
168     authmethod = -1;
169         version = -1;
170
171     while (( i = getopt( argc, argv, "acrf:E:F"
172                 "Cd:D:e:h:H:IkKMnO:p:P:QR:S:U:vw:WxX:y:Y:Z" )) != EOF )
173         {
174         switch( i ) {
175         /* Modify Options */
176         case 'a':       /* add */
177             ldapadd = 1;
178             break;
179         case 'c':       /* continuous operation */
180             contoper = 1;
181             break;
182         case 'E': /* modify controls */
183                 if( version == LDAP_VERSION2 ) {
184                         fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
185                                 prog, version );
186                         return EXIT_FAILURE;
187                 }
188
189                 /* should be extended to support comma separated list of
190                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
191                  */
192
193                 crit = 0;
194                 cvalue = NULL;
195                 if( optarg[0] == '!' ) {
196                         crit = 1;
197                         optarg++;
198                 }
199
200                 control = strdup( optarg );
201                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
202                         *cvalue++ = '\0';
203                 }
204                 fprintf( stderr, "Invalid modify control name: %s\n", control );
205                 usage(prog);
206                 return EXIT_FAILURE;
207         case 'f':       /* read from file */
208                 if( infile != NULL ) {
209                         fprintf( stderr, "%s: -f previously specified\n", prog );
210                         return EXIT_FAILURE;
211                 }
212             infile = strdup( optarg );
213             break;
214         case 'F':       /* force all changes records to be used */
215             force = 1;
216             break;
217
218         /* Common Options */
219         case 'C':
220                 referrals++;
221                 break;
222         case 'd':
223             debug |= atoi( optarg );
224             break;
225         case 'D':       /* bind DN */
226                 if( binddn != NULL ) {
227                         fprintf( stderr, "%s: -D previously specified\n", prog );
228                         return EXIT_FAILURE;
229                 }
230             binddn = strdup( optarg );
231             break;
232         case 'e': /* general controls */
233                 if( version == LDAP_VERSION2 ) {
234                         fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
235                                 prog, version );
236                         return EXIT_FAILURE;
237                 }
238
239                 /* should be extended to support comma separated list of
240                  *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
241                  */
242
243                 crit = 0;
244                 cvalue = NULL;
245                 if( optarg[0] == '!' ) {
246                         crit = 1;
247                         optarg++;
248                 }
249
250                 control = strdup( optarg );
251                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
252                         *cvalue++ = '\0';
253                 }
254
255                 if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
256                         if( cvalue != NULL ) {
257                                 fprintf( stderr, "manageDSAit: no control value expected" );
258                                 usage(prog);
259                                 return EXIT_FAILURE;
260                         }
261
262                         manageDSAit = 1 + crit;
263                         free( control );
264                         break;
265                         
266                 } else if ( strcasecmp( control, "noop" ) == 0 ) {
267                         if( cvalue != NULL ) {
268                                 fprintf( stderr, "noop: no control value expected" );
269                                 usage(prog);
270                                 return EXIT_FAILURE;
271                         }
272
273                         noop = 1 + crit;
274                         free( control );
275                         break;
276
277                 } else {
278                         fprintf( stderr, "Invalid general control name: %s\n", control );
279                         usage(prog);
280                         return EXIT_FAILURE;
281                 }
282         case 'h':       /* ldap host */
283                 if( ldapuri != NULL ) {
284                         fprintf( stderr, "%s: -h incompatible with -H\n", prog );
285                         return EXIT_FAILURE;
286                 }
287                 if( ldaphost != NULL ) {
288                         fprintf( stderr, "%s: -h previously specified\n", prog );
289                         return EXIT_FAILURE;
290                 }
291             ldaphost = strdup( optarg );
292             break;
293         case 'H':       /* ldap URI */
294                 if( ldaphost != NULL ) {
295                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
296                         return EXIT_FAILURE;
297                 }
298                 if( ldapport ) {
299                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
300                         return EXIT_FAILURE;
301                 }
302                 if( ldapuri != NULL ) {
303                         fprintf( stderr, "%s: -H previously specified\n", prog );
304                         return EXIT_FAILURE;
305                 }
306             ldapuri = strdup( optarg );
307             break;
308         case 'I':
309 #ifdef HAVE_CYRUS_SASL
310                 if( version == LDAP_VERSION2 ) {
311                         fprintf( stderr, "%s: -I incompatible with version %d\n",
312                                 prog, version );
313                         return EXIT_FAILURE;
314                 }
315                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
316                         fprintf( stderr, "%s: incompatible previous "
317                                 "authentication choice\n",
318                                 prog );
319                         return EXIT_FAILURE;
320                 }
321                 authmethod = LDAP_AUTH_SASL;
322                 version = LDAP_VERSION3;
323                 sasl_flags = LDAP_SASL_INTERACTIVE;
324                 break;
325 #else
326                 fprintf( stderr, "%s: was not compiled with SASL support\n",
327                         prog );
328                 return( EXIT_FAILURE );
329 #endif
330         case 'k':       /* kerberos bind */
331 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
332                 if( version > LDAP_VERSION2 ) {
333                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
334                                 prog, version );
335                         return EXIT_FAILURE;
336                 }
337
338                 if( authmethod != -1 ) {
339                         fprintf( stderr, "%s: -k incompatible with previous "
340                                 "authentication choice\n", prog );
341                         return EXIT_FAILURE;
342                 }
343                         
344                 authmethod = LDAP_AUTH_KRBV4;
345 #else
346                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
347                 return EXIT_FAILURE;
348 #endif
349             break;
350         case 'K':       /* kerberos bind, part one only */
351 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
352                 if( version > LDAP_VERSION2 ) {
353                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
354                                 prog, version );
355                         return EXIT_FAILURE;
356                 }
357                 if( authmethod != -1 ) {
358                         fprintf( stderr, "%s: incompatible with previous "
359                                 "authentication choice\n", prog );
360                         return EXIT_FAILURE;
361                 }
362
363                 authmethod = LDAP_AUTH_KRBV41;
364 #else
365                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
366                 return( EXIT_FAILURE );
367 #endif
368             break;
369         case 'M':
370                 /* enable Manage DSA IT */
371                 if( version == LDAP_VERSION2 ) {
372                         fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
373                                 prog, version );
374                         return EXIT_FAILURE;
375                 }
376                 manageDSAit++;
377                 version = LDAP_VERSION3;
378                 break;
379         case 'n':       /* print deletes, don't actually do them */
380             ++not;
381             break;
382         case 'O':
383 #ifdef HAVE_CYRUS_SASL
384                 if( sasl_secprops != NULL ) {
385                         fprintf( stderr, "%s: -O previously specified\n", prog );
386                         return EXIT_FAILURE;
387                 }
388                 if( version == LDAP_VERSION2 ) {
389                         fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
390                                 prog, version );
391                         return EXIT_FAILURE;
392                 }
393                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
394                         fprintf( stderr, "%s: incompatible previous "
395                                 "authentication choice\n", prog );
396                         return EXIT_FAILURE;
397                 }
398                 authmethod = LDAP_AUTH_SASL;
399                 version = LDAP_VERSION3;
400                 sasl_secprops = strdup( optarg );
401 #else
402                 fprintf( stderr, "%s: not compiled with SASL support\n",
403                         prog );
404                 return( EXIT_FAILURE );
405 #endif
406                 break;
407         case 'p':
408                 if( ldapport ) {
409                         fprintf( stderr, "%s: -p previously specified\n", prog );
410                         return EXIT_FAILURE;
411                 }
412             ldapport = atoi( optarg );
413             break;
414         case 'P':
415                 switch( atoi(optarg) ) {
416                 case 2:
417                         if( version == LDAP_VERSION3 ) {
418                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
419                                         prog, version );
420                                 return EXIT_FAILURE;
421                         }
422                         version = LDAP_VERSION2;
423                         break;
424                 case 3:
425                         if( version == LDAP_VERSION2 ) {
426                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
427                                         prog, version );
428                                 return EXIT_FAILURE;
429                         }
430                         version = LDAP_VERSION3;
431                         break;
432                 default:
433                         fprintf( stderr, "%s: protocol version should be 2 or 3\n",
434                                 prog );
435                         usage( prog );
436                         return( EXIT_FAILURE );
437                 } break;
438         case 'Q':
439 #ifdef HAVE_CYRUS_SASL
440                 if( version == LDAP_VERSION2 ) {
441                         fprintf( stderr, "%s: -Q incompatible with version %d\n",
442                                 prog, version );
443                         return EXIT_FAILURE;
444                 }
445                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
446                         fprintf( stderr, "%s: incompatible previous "
447                                 "authentication choice\n",
448                                 prog );
449                         return EXIT_FAILURE;
450                 }
451                 authmethod = LDAP_AUTH_SASL;
452                 version = LDAP_VERSION3;
453                 sasl_flags = LDAP_SASL_QUIET;
454                 break;
455 #else
456                 fprintf( stderr, "%s: not compiled with SASL support\n",
457                         prog );
458                 return( EXIT_FAILURE );
459 #endif
460         case 'r':       /* replace (obsolete) */
461                 break;
462
463         case 'R':
464 #ifdef HAVE_CYRUS_SASL
465                 if( sasl_realm != NULL ) {
466                         fprintf( stderr, "%s: -R previously specified\n", prog );
467                         return EXIT_FAILURE;
468                 }
469                 if( version == LDAP_VERSION2 ) {
470                         fprintf( stderr, "%s: -R incompatible with version %d\n",
471                                 prog, version );
472                         return EXIT_FAILURE;
473                 }
474                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
475                         fprintf( stderr, "%s: incompatible previous "
476                                 "authentication choice\n",
477                                 prog );
478                         return EXIT_FAILURE;
479                 }
480                 authmethod = LDAP_AUTH_SASL;
481                 version = LDAP_VERSION3;
482                 sasl_realm = strdup( optarg );
483 #else
484                 fprintf( stderr, "%s: not compiled with SASL support\n",
485                         prog );
486                 return( EXIT_FAILURE );
487 #endif
488                 break;
489         case 'S':       /* skipped modifications to file */
490                 if( rejfile != NULL ) {
491                         fprintf( stderr, "%s: -S previously specified\n", prog );
492                         return EXIT_FAILURE;
493                 }
494                 rejfile = strdup( optarg );
495                 break;
496         case 'U':
497 #ifdef HAVE_CYRUS_SASL
498                 if( sasl_authc_id != NULL ) {
499                         fprintf( stderr, "%s: -U previously specified\n", prog );
500                         return EXIT_FAILURE;
501                 }
502                 if( version == LDAP_VERSION2 ) {
503                         fprintf( stderr, "%s: -U incompatible with version %d\n",
504                                 prog, version );
505                         return EXIT_FAILURE;
506                 }
507                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
508                         fprintf( stderr, "%s: incompatible previous "
509                                 "authentication choice\n",
510                                 prog );
511                         return EXIT_FAILURE;
512                 }
513                 authmethod = LDAP_AUTH_SASL;
514                 version = LDAP_VERSION3;
515                 sasl_authc_id = strdup( optarg );
516 #else
517                 fprintf( stderr, "%s: not compiled with SASL support\n",
518                         prog );
519                 return( EXIT_FAILURE );
520 #endif
521                 break;
522         case 'v':       /* verbose mode */
523             verbose++;
524             break;
525         case 'w':       /* password */
526             passwd.bv_val = strdup( optarg );
527                 {
528                         char* p;
529
530                         for( p = optarg; *p != '\0'; p++ ) {
531                                 *p = '\0';
532                         }
533                 }
534                 passwd.bv_len = strlen( passwd.bv_val );
535             break;
536         case 'W':
537                 want_bindpw++;
538                 break;
539         case 'y':
540                 pw_file = optarg;
541                 break;
542         case 'Y':
543 #ifdef HAVE_CYRUS_SASL
544                 if( sasl_mech != NULL ) {
545                         fprintf( stderr, "%s: -Y previously specified\n", prog );
546                         return EXIT_FAILURE;
547                 }
548                 if( version == LDAP_VERSION2 ) {
549                         fprintf( stderr, "%s: -Y incompatible with version %d\n",
550                                 prog, version );
551                         return EXIT_FAILURE;
552                 }
553                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
554                         fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
555                         return EXIT_FAILURE;
556                 }
557                 authmethod = LDAP_AUTH_SASL;
558                 version = LDAP_VERSION3;
559                 sasl_mech = strdup( optarg );
560 #else
561                 fprintf( stderr, "%s: not compiled with SASL support\n",
562                         prog );
563                 return( EXIT_FAILURE );
564 #endif
565                 break;
566         case 'x':
567                 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
568                         fprintf( stderr, "%s: incompatible with previous "
569                                 "authentication choice\n", prog );
570                         return EXIT_FAILURE;
571                 }
572                 authmethod = LDAP_AUTH_SIMPLE;
573                 break;
574         case 'X':
575 #ifdef HAVE_CYRUS_SASL
576                 if( sasl_authz_id != NULL ) {
577                         fprintf( stderr, "%s: -X previously specified\n", prog );
578                         return EXIT_FAILURE;
579                 }
580                 if( version == LDAP_VERSION2 ) {
581                         fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
582                                 prog, version );
583                         return EXIT_FAILURE;
584                 }
585                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
586                         fprintf( stderr, "%s: -X incompatible with "
587                                 "authentication choice\n", prog );
588                         return EXIT_FAILURE;
589                 }
590                 authmethod = LDAP_AUTH_SASL;
591                 version = LDAP_VERSION3;
592                 sasl_authz_id = strdup( optarg );
593 #else
594                 fprintf( stderr, "%s: not compiled with SASL support\n",
595                         prog );
596                 return( EXIT_FAILURE );
597 #endif
598                 break;
599         case 'Z':
600 #ifdef HAVE_TLS
601                 if( version == LDAP_VERSION2 ) {
602                         fprintf( stderr, "%s: -Z incompatible with version %d\n",
603                                 prog, version );
604                         return EXIT_FAILURE;
605                 }
606                 version = LDAP_VERSION3;
607                 use_tls++;
608 #else
609                 fprintf( stderr, "%s: not compiled with TLS support\n",
610                         prog );
611                 return( EXIT_FAILURE );
612 #endif
613                 break;
614         default:
615                 fprintf( stderr, "%s: unrecognized option -%c\n",
616                         prog, optopt );
617             usage( prog );
618         }
619     }
620
621         if (version == -1) {
622                 version = LDAP_VERSION3;
623         }
624         if (authmethod == -1 && version > LDAP_VERSION2) {
625 #ifdef HAVE_CYRUS_SASL
626                 authmethod = LDAP_AUTH_SASL;
627 #else
628                 authmethod = LDAP_AUTH_SIMPLE;
629 #endif
630         }
631
632         if ( argc != optind )
633         usage( prog );
634
635     if ( rejfile != NULL ) {
636         if (( rejfp = fopen( rejfile, "w" )) == NULL ) {
637             perror( rejfile );
638             return( EXIT_FAILURE );
639         }
640     } else {
641         rejfp = NULL;
642     }
643
644     if ( infile != NULL ) {
645         if (( fp = fopen( infile, "r" )) == NULL ) {
646             perror( infile );
647             return( EXIT_FAILURE );
648         }
649     } else {
650         fp = stdin;
651     }
652
653         if ( debug ) {
654                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
655                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
656                 }
657                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
658                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
659                 }
660                 ldif_debug = debug;
661         }
662
663 #ifdef SIGPIPE
664         (void) SIGNAL( SIGPIPE, SIG_IGN );
665 #endif
666
667     if ( !not ) {
668         if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
669                 if ( verbose ) {
670                         fprintf( stderr, "ldap_init( %s, %d )\n",
671                                 ldaphost != NULL ? ldaphost : "<DEFAULT>",
672                                 ldapport );
673                 }
674
675                 ld = ldap_init( ldaphost, ldapport );
676                 if( ld == NULL ) {
677                         perror("ldapmodify: ldap_init");
678                         return EXIT_FAILURE;
679                 }
680
681         } else {
682                 if ( verbose ) {
683                         fprintf( stderr, "ldap_initialize( %s )\n",
684                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
685                 }
686
687                 rc = ldap_initialize( &ld, ldapuri );
688                 if( rc != LDAP_SUCCESS ) {
689                         fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
690                                 rc, ldap_err2string(rc) );
691                         return EXIT_FAILURE;
692                 }
693         }
694
695         /* referrals */
696         if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
697                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
698         {
699                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
700                         referrals ? "on" : "off" );
701                 return EXIT_FAILURE;
702         }
703
704
705         if (version == -1 ) {
706                 version = LDAP_VERSION3;
707         }
708
709         if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
710                 != LDAP_OPT_SUCCESS )
711         {
712                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
713                         version );
714                 return EXIT_FAILURE;
715         }
716
717         if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
718                 ldap_perror( ld, "ldap_start_tls" );
719                 if ( use_tls > 1 ) {
720                         return( EXIT_FAILURE );
721                 }
722         }
723
724         if ( pw_file || want_bindpw ) {
725                 if ( pw_file ) {
726                         rc = lutil_get_filed_password( pw_file, &passwd );
727                         if( rc ) return EXIT_FAILURE;
728                 } else {
729                         passwd.bv_val = getpassphrase( "Enter LDAP Password: " );
730                         passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
731                 }
732         }
733
734         if ( authmethod == LDAP_AUTH_SASL ) {
735 #ifdef HAVE_CYRUS_SASL
736                 void *defaults;
737
738                 if( sasl_secprops != NULL ) {
739                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
740                                 (void *) sasl_secprops );
741                         
742                         if( rc != LDAP_OPT_SUCCESS ) {
743                                 fprintf( stderr,
744                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
745                                         sasl_secprops );
746                                 return( EXIT_FAILURE );
747                         }
748                 }
749                 
750                 defaults = lutil_sasl_defaults( ld,
751                         sasl_mech,
752                         sasl_realm,
753                         sasl_authc_id,
754                         passwd.bv_val,
755                         sasl_authz_id );
756
757                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
758                         sasl_mech, NULL, NULL,
759                         sasl_flags, lutil_sasl_interact, defaults );
760
761                 if( rc != LDAP_SUCCESS ) {
762                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
763                         return( EXIT_FAILURE );
764                 }
765 #else
766                 fprintf( stderr, "%s: not compiled with SASL support\n",
767                         prog );
768                 return( EXIT_FAILURE );
769 #endif
770         }
771         else {
772                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
773                                 != LDAP_SUCCESS ) {
774                         ldap_perror( ld, "ldap_bind" );
775                         return( EXIT_FAILURE );
776                 }
777
778         }
779
780     }
781
782     rc = 0;
783
784         if ( manageDSAit || noop ) {
785                 int err, i = 0;
786                 LDAPControl c1, c2;
787                 LDAPControl *ctrls[3];
788
789                 if ( manageDSAit ) {
790                         ctrls[i++] = &c1;
791                         ctrls[i] = NULL;
792                         c1.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
793                         c1.ldctl_value.bv_val = NULL;
794                         c1.ldctl_value.bv_len = 0;
795                         c1.ldctl_iscritical = manageDSAit > 1;
796                 }
797
798                 if ( noop ) {
799                         ctrls[i++] = &c2;
800                         ctrls[i] = NULL;
801
802                         c2.ldctl_oid = LDAP_CONTROL_NOOP;
803                         c2.ldctl_value.bv_val = NULL;
804                         c2.ldctl_value.bv_len = 0;
805                         c2.ldctl_iscritical = noop > 1;
806                 }
807         
808                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
809
810                 if( err != LDAP_OPT_SUCCESS ) {
811                         fprintf( stderr, "Could not set %scontrols\n",
812                                 (c1.ldctl_iscritical || c2.ldctl_iscritical)
813                                 ? "critical " : "" );
814                         if ( c1.ldctl_iscritical && c2.ldctl_iscritical ) {
815                                 return EXIT_FAILURE;
816                         }
817                 }
818         }
819
820         count = 0;
821     while (( rc == 0 || contoper ) &&
822                 ( rbuf = read_one_record( fp )) != NULL ) {
823         count++;
824
825         start = rbuf;
826
827         if ( rejfp ) {
828                 len = strlen( rbuf );
829                 if (( rejbuf = (char *)malloc( len+1 )) == NULL ) {
830                         perror( "realloc" );
831                         exit( EXIT_FAILURE );
832                 }
833                 memcpy( rejbuf, rbuf, len+1 );
834         }
835
836     rc = process_ldif_rec( start, count );
837
838         if ( rc && rejfp ) {
839                 fprintf(rejfp, "# Error: %s (%d)", ldap_err2string(rc), rc);
840
841                 ldap_get_option(ld, LDAP_OPT_MATCHED_DN, &matched_msg);
842                 if ( matched_msg != NULL && *matched_msg != '\0' ) {
843                         fprintf( rejfp, ", matched DN: %s", matched_msg );
844                 }
845
846                 ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &error_msg);
847                 if ( error_msg != NULL && *error_msg != '\0' ) {
848                         fprintf( rejfp, ", additional info: %s", error_msg );
849                 }
850                 fprintf( rejfp, "\n%s\n", rejbuf );
851         }
852                 if (rejfp) 
853                         free( rejbuf );
854                 free( rbuf );
855     }
856
857     if ( !not ) {
858                 ldap_unbind( ld );
859     }
860
861     if ( rejfp != NULL ) {
862             fclose( rejfp );
863     }
864
865         return( rc );
866 }
867
868
869 static int
870 process_ldif_rec( char *rbuf, int count )
871 {
872     char        *line, *dn, *type, *newrdn, *newsup, *p;
873     int         rc, linenum, modop, replicaport;
874     int         expect_modop, expect_sep, expect_ct, expect_newrdn, expect_newsup;
875     int         expect_deleteoldrdn, deleteoldrdn;
876     int         saw_replica, use_record, new_entry, delete_entry, got_all;
877     LDAPMod     **pmods;
878         int version;
879         struct berval val;
880
881     new_entry = ldapadd;
882
883     rc = got_all = saw_replica = delete_entry = modop = expect_modop = 0;
884     expect_deleteoldrdn = expect_newrdn = expect_newsup = 0;
885         expect_sep = expect_ct = 0;
886     linenum = 0;
887         version = 0;
888     deleteoldrdn = 1;
889     use_record = force;
890     pmods = NULL;
891     dn = newrdn = newsup = NULL;
892
893     while ( rc == 0 && ( line = ldif_getline( &rbuf )) != NULL ) {
894         ++linenum;
895
896         if ( expect_sep && strcasecmp( line, T_MODSEPSTR ) == 0 ) {
897             expect_sep = 0;
898             expect_ct = 1;
899             continue;
900         }
901         
902         if ( ldif_parse_line( line, &type, &val.bv_val, &val.bv_len ) < 0 ) {
903             fprintf( stderr, "%s: invalid format (line %d) entry: \"%s\"\n",
904                     prog, linenum, dn == NULL ? "" : dn );
905             rc = LDAP_PARAM_ERROR;
906             break;
907         }
908
909         if ( dn == NULL ) {
910             if ( !use_record && strcasecmp( type, T_REPLICA_STR ) == 0 ) {
911                 ++saw_replica;
912                 if (( p = strchr( val.bv_val, ':' )) == NULL ) {
913                     replicaport = 0;
914                 } else {
915                     *p++ = '\0';
916                     replicaport = atoi( p );
917                 }
918                 if ( ldaphost != NULL && strcasecmp( val.bv_val, ldaphost ) == 0 &&
919                         replicaport == ldapport ) {
920                     use_record = 1;
921                 }
922             } else if ( count == 1 && linenum == 1 && 
923                         strcasecmp( type, T_VERSION_STR ) == 0 )
924                 {
925                         if( val.bv_len == 0 || atoi(val.bv_val) != 1 ) {
926                         fprintf( stderr, "%s: invalid version %s, line %d (ignored)\n",
927                                 prog, val.bv_val == NULL ? "(null)" : val.bv_val, linenum );
928                         }
929                         version++;
930
931             } else if ( strcasecmp( type, T_DN_STR ) == 0 ) {
932                 if (( dn = strdup( val.bv_val ? val.bv_val : "" )) == NULL ) {
933                     perror( "strdup" );
934                     exit( EXIT_FAILURE );
935                 }
936                 expect_ct = 1;
937             }
938             goto end_line;      /* skip all lines until we see "dn:" */
939         }
940
941         if ( expect_ct ) {
942             expect_ct = 0;
943             if ( !use_record && saw_replica ) {
944                 printf( "%s: skipping change record for entry: %s\n"
945                         "\t(LDAP host/port does not match replica: lines)\n",
946                         prog, dn );
947                 free( dn );
948                 ber_memfree( type );
949                 ber_memfree( val.bv_val );
950                 return( 0 );
951             }
952
953             if ( strcasecmp( type, T_CHANGETYPESTR ) == 0 ) {
954 #ifdef LIBERAL_CHANGETYPE_MODOP
955                 /* trim trailing spaces (and log warning ...) */
956
957                 int icnt;
958                 for ( icnt = val.bv_len; --icnt > 0; ) {
959                     if ( !isspace( (unsigned char) val.bv_val[icnt] ) ) {
960                         break;
961                     }
962                 }
963
964                 if ( ++icnt != val.bv_len ) {
965                     fprintf( stderr, "%s: illegal trailing space after \"%s: %s\" trimmed (line %d of entry \"%s\")\n",
966                             prog, T_CHANGETYPESTR, val.bv_val, linenum, dn );
967                     val.bv_val[icnt] = '\0';
968                 }
969 #endif /* LIBERAL_CHANGETYPE_MODOP */
970
971                 if ( strcasecmp( val.bv_val, T_MODIFYCTSTR ) == 0 ) {
972                         new_entry = 0;
973                         expect_modop = 1;
974                 } else if ( strcasecmp( val.bv_val, T_ADDCTSTR ) == 0 ) {
975                         new_entry = 1;
976                 } else if ( strcasecmp( val.bv_val, T_MODRDNCTSTR ) == 0
977                         || strcasecmp( val.bv_val, T_MODDNCTSTR ) == 0
978                         || strcasecmp( val.bv_val, T_RENAMECTSTR ) == 0)
979                 {
980                     expect_newrdn = 1;
981                 } else if ( strcasecmp( val.bv_val, T_DELETECTSTR ) == 0 ) {
982                     got_all = delete_entry = 1;
983                 } else {
984                     fprintf( stderr,
985                             "%s:  unknown %s \"%s\" (line %d of entry \"%s\")\n",
986                             prog, T_CHANGETYPESTR, val.bv_val, linenum, dn );
987                     rc = LDAP_PARAM_ERROR;
988                 }
989                 goto end_line;
990             } else if ( ldapadd ) {             /*  missing changetype => add */
991                 new_entry = 1;
992                 modop = LDAP_MOD_ADD;
993             } else {
994                 expect_modop = 1;       /* missing changetype => modify */
995             }
996         }
997
998         if ( expect_modop ) {
999 #ifdef LIBERAL_CHANGETYPE_MODOP
1000             /* trim trailing spaces (and log warning ...) */
1001             
1002             int icnt;
1003             for ( icnt = val.bv_len; --icnt > 0; ) {
1004                 if ( !isspace( (unsigned char) val.bv_val[icnt] ) ) {
1005                     break;
1006                 }
1007             }
1008             
1009             if ( ++icnt != val.bv_len ) {
1010                 fprintf( stderr, "%s: illegal trailing space after \"%s: %s\" trimmed (line %d of entry \"%s\")\n",
1011                         prog, type, val.bv_val, linenum, dn );
1012                 val.bv_val[icnt] = '\0';
1013             }
1014 #endif /* LIBERAL_CHANGETYPE_MODOP */
1015
1016             expect_modop = 0;
1017             expect_sep = 1;
1018             if ( strcasecmp( type, T_MODOPADDSTR ) == 0 ) {
1019                 modop = LDAP_MOD_ADD;
1020                 goto end_line;
1021             } else if ( strcasecmp( type, T_MODOPREPLACESTR ) == 0 ) {
1022                 modop = LDAP_MOD_REPLACE;
1023                 addmodifyop( &pmods, modop, val.bv_val, NULL );
1024                 goto end_line;
1025             } else if ( strcasecmp( type, T_MODOPDELETESTR ) == 0 ) {
1026                 modop = LDAP_MOD_DELETE;
1027                 addmodifyop( &pmods, modop, val.bv_val, NULL );
1028                 goto end_line;
1029             } else {    /* no modify op:  use default */
1030                 modop = ldapadd ? LDAP_MOD_ADD : LDAP_MOD_REPLACE;
1031             }
1032         }
1033
1034         if ( expect_newrdn ) {
1035             if ( strcasecmp( type, T_NEWRDNSTR ) == 0 ) {
1036                         if (( newrdn = strdup( val.bv_val ? val.bv_val : "" )) == NULL ) {
1037                     perror( "strdup" );
1038                     exit( EXIT_FAILURE );
1039                 }
1040                 expect_deleteoldrdn = 1;
1041                 expect_newrdn = 0;
1042             } else {
1043                 fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n",
1044                         prog, T_NEWRDNSTR, type, linenum, dn );
1045                 rc = LDAP_PARAM_ERROR;
1046             }
1047         } else if ( expect_deleteoldrdn ) {
1048             if ( strcasecmp( type, T_DELETEOLDRDNSTR ) == 0 ) {
1049                 deleteoldrdn = ( *val.bv_val == '0' ) ? 0 : 1;
1050                 expect_deleteoldrdn = 0;
1051                 expect_newsup = 1;
1052                 got_all = 1;
1053             } else {
1054                 fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n",
1055                         prog, T_DELETEOLDRDNSTR, type, linenum, dn );
1056                 rc = LDAP_PARAM_ERROR;
1057             }
1058         } else if ( expect_newsup ) {
1059             if ( strcasecmp( type, T_NEWSUPSTR ) == 0 ) {
1060                 if (( newsup = strdup( val.bv_val ? val.bv_val : "" )) == NULL ) {
1061                     perror( "strdup" );
1062                     exit( EXIT_FAILURE );
1063                 }
1064                 expect_newsup = 0;
1065             } else {
1066                 fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n",
1067                         prog, T_NEWSUPSTR, type, linenum, dn );
1068                 rc = LDAP_PARAM_ERROR;
1069             }
1070         } else if ( got_all ) {
1071             fprintf( stderr,
1072                     "%s: extra lines at end (line %d of entry \"%s\")\n",
1073                     prog, linenum, dn );
1074             rc = LDAP_PARAM_ERROR;
1075         } else {
1076                 addmodifyop( &pmods, modop, type, val.bv_val == NULL ? NULL : &val );
1077         }
1078
1079 end_line:
1080         ber_memfree( type );
1081         ber_memfree( val.bv_val );
1082     }
1083
1084         if( linenum == 0 ) {
1085                 return 0;
1086         }
1087
1088         if( version && linenum == 1 ) {
1089                 return 0;
1090         }
1091
1092     if ( rc == 0 ) {
1093         if ( delete_entry ) {
1094             rc = dodelete( dn );
1095         } else if ( newrdn != NULL ) {
1096             rc = dorename( dn, newrdn, newsup, deleteoldrdn );
1097         } else {
1098             rc = domodify( dn, pmods, new_entry );
1099         }
1100
1101         if ( rc == LDAP_SUCCESS ) {
1102             rc = 0;
1103         }
1104     }
1105
1106     if ( dn != NULL ) {
1107         free( dn );
1108     }
1109     if ( newrdn != NULL ) {
1110         free( newrdn );
1111     }
1112     if ( pmods != NULL ) {
1113         ldap_mods_free( pmods, 1 );
1114     }
1115
1116     return( rc );
1117 }
1118
1119
1120 static void
1121 addmodifyop(
1122         LDAPMod ***pmodsp,
1123         int modop,
1124         const char *attr,
1125         struct berval *val )
1126 {
1127         LDAPMod         **pmods;
1128         int                     i, j;
1129
1130         pmods = *pmodsp;
1131         modop |= LDAP_MOD_BVALUES;
1132
1133         i = 0;
1134         if ( pmods != NULL ) {
1135                 for ( ; pmods[ i ] != NULL; ++i ) {
1136                         if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
1137                                 pmods[ i ]->mod_op == modop )
1138                         {
1139                                 break;
1140                         }
1141                 }
1142         }
1143
1144         if ( pmods == NULL || pmods[ i ] == NULL ) {
1145                 if (( pmods = (LDAPMod **)ber_memrealloc( pmods, (i + 2) *
1146                         sizeof( LDAPMod * ))) == NULL )
1147                 {
1148                         perror( "realloc" );
1149                         exit( EXIT_FAILURE );
1150                 }
1151
1152                 *pmodsp = pmods;
1153                 pmods[ i + 1 ] = NULL;
1154
1155                 pmods[ i ] = (LDAPMod *)ber_memcalloc( 1, sizeof( LDAPMod ));
1156                 if ( pmods[ i ] == NULL ) {
1157                         perror( "calloc" );
1158                         exit( EXIT_FAILURE );
1159                 }
1160
1161                 pmods[ i ]->mod_op = modop;
1162                 pmods[ i ]->mod_type = ber_strdup( attr );
1163                 if ( pmods[ i ]->mod_type == NULL ) {
1164                         perror( "strdup" );
1165                         exit( EXIT_FAILURE );
1166                 }
1167         }
1168
1169         if ( val != NULL ) {
1170                 j = 0;
1171                 if ( pmods[ i ]->mod_bvalues != NULL ) {
1172                         for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
1173                                 /* Empty */;
1174                         }
1175                 }
1176
1177                 pmods[ i ]->mod_bvalues = (struct berval **) ber_memrealloc(
1178                         pmods[ i ]->mod_bvalues, (j + 2) * sizeof( struct berval * ));
1179                 if ( pmods[ i ]->mod_bvalues == NULL ) {
1180                         perror( "ber_realloc" );
1181                         exit( EXIT_FAILURE );
1182                 }
1183
1184                 pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
1185                 pmods[ i ]->mod_bvalues[ j ] = ber_bvdup( val );
1186                 if ( pmods[ i ]->mod_bvalues[ j ] == NULL ) {
1187                         perror( "ber_bvdup" );
1188                         exit( EXIT_FAILURE );
1189                 }
1190         }
1191 }
1192
1193
1194 static int
1195 domodify(
1196         const char *dn,
1197         LDAPMod **pmods,
1198         int newentry )
1199 {
1200     int                 i, j, k, notascii, op;
1201     struct berval       *bvp;
1202
1203     if ( pmods == NULL ) {
1204         fprintf( stderr, "%s: no attributes to change or add (entry=\"%s\")\n",
1205                 prog, dn );
1206         return( LDAP_PARAM_ERROR );
1207     } 
1208
1209     for ( i = 0; pmods[ i ] != NULL; ++i ) {
1210         op = pmods[ i ]->mod_op & ~LDAP_MOD_BVALUES;
1211         if( op == LDAP_MOD_ADD && ( pmods[i]->mod_bvalues == NULL )) {
1212                 fprintf( stderr,
1213                         "%s: attribute \"%s\" has no values (entry=\"%s\")\n",
1214                         prog, pmods[i]->mod_type, dn );
1215                 return LDAP_PARAM_ERROR;
1216         }
1217     }
1218
1219     if ( verbose ) {
1220         for ( i = 0; pmods[ i ] != NULL; ++i ) {
1221             op = pmods[ i ]->mod_op & ~LDAP_MOD_BVALUES;
1222             printf( "%s %s:\n", op == LDAP_MOD_REPLACE ?
1223                     "replace" : op == LDAP_MOD_ADD ?
1224                     "add" : "delete", pmods[ i ]->mod_type );
1225             if ( pmods[ i ]->mod_bvalues != NULL ) {
1226                 for ( j = 0; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
1227                     bvp = pmods[ i ]->mod_bvalues[ j ];
1228                     notascii = 0;
1229                     for ( k = 0; (unsigned long) k < bvp->bv_len; ++k ) {
1230                         if ( !isascii( bvp->bv_val[ k ] )) {
1231                             notascii = 1;
1232                             break;
1233                         }
1234                     }
1235                     if ( notascii ) {
1236                         printf( "\tNOT ASCII (%ld bytes)\n", bvp->bv_len );
1237                     } else {
1238                         printf( "\t%s\n", bvp->bv_val );
1239                     }
1240                 }
1241             }
1242         }
1243     }
1244
1245     if ( newentry ) {
1246         printf( "%sadding new entry \"%s\"\n", not ? "!" : "", dn );
1247     } else {
1248         printf( "%smodifying entry \"%s\"\n", not ? "!" : "", dn );
1249     }
1250
1251     if ( !not ) {
1252         if ( newentry ) {
1253             i = ldap_add_s( ld, dn, pmods );
1254         } else {
1255             i = ldap_modify_s( ld, dn, pmods );
1256         }
1257         if ( i != LDAP_SUCCESS ) {
1258                 /* print error message about failed update including DN */
1259                 fprintf( stderr, "%s: update failed: %s\n", prog, dn );
1260                 ldap_perror( ld, newentry ? "ldap_add" : "ldap_modify" );
1261         } else if ( verbose ) {
1262             printf( "modify complete\n" );
1263         }
1264     } else {
1265         i = LDAP_SUCCESS;
1266     }
1267
1268     putchar( '\n' );
1269
1270     return( i );
1271 }
1272
1273
1274 static int
1275 dodelete(
1276         const char *dn )
1277 {
1278     int rc;
1279
1280     printf( "%sdeleting entry \"%s\"\n", not ? "!" : "", dn );
1281     if ( !not ) {
1282         if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) {
1283                 fprintf( stderr, "%s: delete failed: %s\n", prog, dn );
1284                 ldap_perror( ld, "ldap_delete" );
1285         } else if ( verbose ) {
1286             printf( "delete complete" );
1287         }
1288     } else {
1289         rc = LDAP_SUCCESS;
1290     }
1291
1292     putchar( '\n' );
1293
1294     return( rc );
1295 }
1296
1297
1298 static int
1299 dorename(
1300         const char *dn,
1301         const char *newrdn,
1302         const char* newsup,
1303         int deleteoldrdn )
1304 {
1305     int rc;
1306
1307
1308     printf( "%smodifying rdn of entry \"%s\"\n", not ? "!" : "", dn );
1309     if ( verbose ) {
1310         printf( "\tnew RDN: \"%s\" (%skeep existing values)\n",
1311                 newrdn, deleteoldrdn ? "do not " : "" );
1312     }
1313     if ( !not ) {
1314         if (( rc = ldap_rename2_s( ld, dn, newrdn, newsup, deleteoldrdn ))
1315                 != LDAP_SUCCESS )
1316         {
1317                 fprintf( stderr, "%s: rename failed: %s\n", prog, dn );
1318                 ldap_perror( ld, "ldap_modrdn" );
1319         } else {
1320             printf( "modrdn completed\n" );
1321         }
1322     } else {
1323         rc = LDAP_SUCCESS;
1324     }
1325
1326     putchar( '\n' );
1327
1328     return( rc );
1329 }
1330
1331
1332 static char *
1333 read_one_record( FILE *fp )
1334 {
1335     char        *buf, line[ LDAPMOD_MAXLINE ];
1336     int         lcur, lmax;
1337
1338     lcur = lmax = 0;
1339     buf = NULL;
1340
1341     while ( fgets( line, sizeof(line), fp ) != NULL ) {
1342         int len = strlen( line );
1343
1344                 if( len < 2 || ( len == 2 && *line == '\r' )) {
1345                         if( buf == NULL ) {
1346                                 continue;
1347                         } else {
1348                                 break;
1349                         }
1350                 }
1351
1352                 if ( lcur + len + 1 > lmax ) {
1353                         lmax = LDAPMOD_MAXLINE
1354                                 * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
1355
1356                         if (( buf = (char *)realloc( buf, lmax )) == NULL ) {
1357                                 perror( "realloc" );
1358                                 exit( EXIT_FAILURE );
1359                         }
1360                 }
1361
1362                 strcpy( buf + lcur, line );
1363                 lcur += len;
1364     }
1365
1366     return( buf );
1367 }