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