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