]> git.sur5r.net Git - openldap/blob - clients/tools/ldapmodify.c
Everything compiles.... but tests fail...
[openldap] / clients / tools / ldapmodify.c
1 /* ldapmodify.c - generic program to modify or add entries using LDAP */
2
3 #define DISABLE_BRIDGE
4 #include "portable.h"
5
6 #include <stdio.h>
7 #include <ac/string.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/file.h>
13 #include <fcntl.h>
14 #ifndef VMS
15 #include <unistd.h>
16 #endif /* VMS */
17
18 #include <lber.h>
19 #include <ldap.h>
20 #include <ldif.h>
21
22 #include "ldapconfig.h"
23
24 static char     *prog;
25 static char     *binddn = LDAPMODIFY_BINDDN;
26 static char     *passwd = LDAPMODIFY_BIND_CRED;
27 static char     *ldaphost = LDAPHOST;
28 static int      ldapport = LDAP_PORT;
29 static int      new, replace, not, verbose, contoper, force, valsfromfiles;
30 static LDAP     *ld;
31
32 #ifdef LDAP_DEBUG
33 extern int ldap_debug, lber_debug;
34 #endif /* LDAP_DEBUG */
35
36 #define safe_realloc( ptr, size )       ( ptr == NULL ? malloc( size ) : \
37                                          realloc( ptr, size ))
38
39 #define LDAPMOD_MAXLINE         4096
40
41 /* strings found in replog/LDIF entries (mostly lifted from slurpd/slurp.h) */
42 #define T_REPLICA_STR           "replica"
43 #define T_DN_STR                "dn"
44 #define T_CHANGETYPESTR         "changetype"
45 #define T_ADDCTSTR              "add"
46 #define T_MODIFYCTSTR           "modify"
47 #define T_DELETECTSTR           "delete"
48 #define T_MODRDNCTSTR           "modrdn"
49 #define T_MODOPADDSTR           "add"
50 #define T_MODOPREPLACESTR       "replace"
51 #define T_MODOPDELETESTR        "delete"
52 #define T_MODSEPSTR             "-"
53 #define T_NEWRDNSTR             "newrdn"
54 #define T_DELETEOLDRDNSTR       "deleteoldrdn"
55
56
57 #ifdef NEEDPROTOS
58 static int process_ldapmod_rec( char *rbuf );
59 static int process_ldif_rec( char *rbuf );
60 static void addmodifyop( LDAPMod ***pmodsp, int modop, char *attr,
61         char *value, int vlen );
62 static int domodify( char *dn, LDAPMod **pmods, int newentry );
63 static int dodelete( char *dn );
64 static int domodrdn( char *dn, char *newrdn, int deleteoldrdn );
65 static void freepmods( LDAPMod **pmods );
66 static int fromfile( char *path, struct berval *bv );
67 static char *read_one_record( FILE *fp );
68 #else /* NEEDPROTOS */
69 static int process_ldapmod_rec();
70 static int process_ldif_rec();
71 static void addmodifyop();
72 static int domodify();
73 static int dodelete();
74 static int domodrdn();
75 static void freepmods();
76 static int fromfile();
77 static char *read_one_record();
78 #endif /* NEEDPROTOS */
79
80
81 main( argc, argv )
82     int         argc;
83     char        **argv;
84 {
85     char                *infile, *rbuf, *start, *p, *q;
86     FILE                *fp;
87     int                 rc, i, kerberos, use_ldif, authmethod;
88     char                *usage = "usage: %s [-abcknrvF] [-d debug-level] [-h ldaphost] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n";
89
90     extern char *optarg;
91     extern int  optind;
92
93     if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
94         prog = argv[ 0 ];
95     } else {
96         ++prog;
97     }
98     new = ( strcmp( prog, "ldapadd" ) == 0 );
99
100     infile = NULL;
101     kerberos = not = verbose = valsfromfiles = 0;
102
103     while (( i = getopt( argc, argv, "FabckKnrtvh:p:D:w:d:f:" )) != EOF ) {
104         switch( i ) {
105         case 'a':       /* add */
106             new = 1;
107             break;
108         case 'b':       /* read values from files (for binary attributes) */
109             valsfromfiles = 1;
110             break;
111         case 'c':       /* continuous operation */
112             contoper = 1;
113             break;
114         case 'r':       /* default is to replace rather than add values */
115             replace = 1;
116             break;
117         case 'k':       /* kerberos bind */
118             kerberos = 2;
119             break;
120         case 'K':       /* kerberos bind, part 1 only */
121             kerberos = 1;
122             break;
123         case 'F':       /* force all changes records to be used */
124             force = 1;
125             break;
126         case 'h':       /* ldap host */
127             ldaphost = strdup( optarg );
128             break;
129         case 'D':       /* bind DN */
130             binddn = strdup( optarg );
131             break;
132         case 'w':       /* password */
133             passwd = strdup( optarg );
134             break;
135         case 'd':
136 #ifdef LDAP_DEBUG
137             ldap_debug = lber_debug = atoi( optarg );   /* */
138 #else /* LDAP_DEBUG */
139             fprintf( stderr, "%s: compile with -DLDAP_DEBUG for debugging\n",
140                     prog );
141 #endif /* LDAP_DEBUG */
142             break;
143         case 'f':       /* read from file */
144             infile = strdup( optarg );
145             break;
146         case 'p':
147             ldapport = atoi( optarg );
148             break;
149         case 'n':       /* print adds, don't actually do them */
150             ++not;
151             break;
152         case 'v':       /* verbose mode */
153             verbose++;
154             break;
155         default:
156             fprintf( stderr, usage, prog );
157             exit( 1 );
158         }
159     }
160
161     if ( argc - optind != 0 ) {
162         fprintf( stderr, usage, prog );
163         exit( 1 );
164     }
165
166     if ( infile != NULL ) {
167         if (( fp = fopen( infile, "r" )) == NULL ) {
168             perror( infile );
169             exit( 1 );
170         }
171     } else {
172         fp = stdin;
173     }
174
175
176     if ( !not ) {
177         if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) {
178             perror( "ldap_open" );
179             exit( 1 );
180         }
181
182         ld->ld_deref = LDAP_DEREF_NEVER;        /* this seems prudent */
183
184         if ( !kerberos ) {
185             authmethod = LDAP_AUTH_SIMPLE;
186         } else if ( kerberos == 1 ) {
187             authmethod = LDAP_AUTH_KRBV41;
188         } else {
189             authmethod = LDAP_AUTH_KRBV4;
190         }
191         if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
192             ldap_perror( ld, "ldap_bind" );
193             exit( 1 );
194         }
195     }
196
197     rc = 0;
198
199     while (( rc == 0 || contoper ) &&
200                 ( rbuf = read_one_record( fp )) != NULL ) {
201         /*
202          * we assume record is ldif/slapd.replog if the first line
203          * has a colon that appears to the left of any equal signs, OR
204          * if the first line consists entirely of digits (an entry id)
205          */
206         use_ldif = ( p = strchr( rbuf, ':' )) != NULL &&
207                 ( q = strchr( rbuf, '\n' )) != NULL && p < q &&
208                 (( q = strchr( rbuf, '=' )) == NULL || p < q );
209
210         start = rbuf;
211
212         if ( !use_ldif && ( q = strchr( rbuf, '\n' )) != NULL ) {
213             for ( p = rbuf; p < q; ++p ) {
214                 if ( !isdigit( *p )) {
215                     break;
216                 }
217             }
218             if ( p >= q ) {
219                 use_ldif = 1;
220                 start = q + 1;
221             }
222         }
223
224         if ( use_ldif ) {
225             rc = process_ldif_rec( start );
226         } else {
227             rc = process_ldapmod_rec( start );
228         }
229
230         free( rbuf );
231     }
232
233     if ( !not ) {
234         ldap_unbind( ld );
235     }
236
237     exit( rc );
238 }
239
240
241 static int
242 process_ldif_rec( char *rbuf )
243 {
244     char        *line, *dn, *type, *value, *newrdn, *p;
245     int         rc, linenum, vlen, modop, replicaport;
246     int         expect_modop, expect_sep, expect_ct, expect_newrdn;
247     int         expect_deleteoldrdn, deleteoldrdn;
248     int         saw_replica, use_record, new_entry, delete_entry, got_all;
249     LDAPMod     **pmods;
250
251     new_entry = new;
252
253     rc = got_all = saw_replica = delete_entry = expect_modop = 0;
254     expect_deleteoldrdn = expect_newrdn = expect_sep = expect_ct = 0;
255     linenum = 0;
256     deleteoldrdn = 1;
257     use_record = force;
258     pmods = NULL;
259     dn = newrdn = NULL;
260
261     while ( rc == 0 && ( line = str_getline( &rbuf )) != NULL ) {
262         ++linenum;
263         if ( expect_sep && strcasecmp( line, T_MODSEPSTR ) == 0 ) {
264             expect_sep = 0;
265             expect_ct = 1;
266             continue;
267         }
268         
269         if ( str_parse_line( line, &type, &value, &vlen ) < 0 ) {
270             fprintf( stderr, "%s: invalid format (line %d of entry: %s\n",
271                     prog, linenum, dn == NULL ? "" : dn );
272             rc = LDAP_PARAM_ERROR;
273             break;
274         }
275
276         if ( dn == NULL ) {
277             if ( !use_record && strcasecmp( type, T_REPLICA_STR ) == 0 ) {
278                 ++saw_replica;
279                 if (( p = strchr( value, ':' )) == NULL ) {
280                     replicaport = LDAP_PORT;
281                 } else {
282                     *p++ = '\0';
283                     replicaport = atoi( p );
284                 }
285                 if ( strcasecmp( value, ldaphost ) == 0 &&
286                         replicaport == ldapport ) {
287                     use_record = 1;
288                 }
289             } else if ( strcasecmp( type, T_DN_STR ) == 0 ) {
290                 if (( dn = strdup( value )) == NULL ) {
291                     perror( "strdup" );
292                     exit( 1 );
293                 }
294                 expect_ct = 1;
295             }
296             continue;   /* skip all lines until we see "dn:" */
297         }
298
299         if ( expect_ct ) {
300             expect_ct = 0;
301             if ( !use_record && saw_replica ) {
302                 printf( "%s: skipping change record for entry: %s\n\t(LDAP host/port does not match replica: lines)\n",
303                         prog, dn );
304                 free( dn );
305                 return( 0 );
306             }
307
308             if ( strcasecmp( type, T_CHANGETYPESTR ) == 0 ) {
309                 if ( strcasecmp( value, T_MODIFYCTSTR ) == 0 ) {
310                         new_entry = 0;
311                         expect_modop = 1;
312                 } else if ( strcasecmp( value, T_ADDCTSTR ) == 0 ) {
313                         new_entry = 1;
314                 } else if ( strcasecmp( value, T_MODRDNCTSTR ) == 0 ) {
315                     expect_newrdn = 1;
316                 } else if ( strcasecmp( value, T_DELETECTSTR ) == 0 ) {
317                     got_all = delete_entry = 1;
318                 } else {
319                     fprintf( stderr,
320                             "%s:  unknown %s \"%s\" (line %d of entry: %s)\n",
321                             prog, T_CHANGETYPESTR, value, linenum, dn );
322                     rc = LDAP_PARAM_ERROR;
323                 }
324                 continue;
325             } else if ( new ) {         /*  missing changetype => add */
326                 new_entry = 1;
327                 modop = LDAP_MOD_ADD;
328             } else {
329                 expect_modop = 1;       /* missing changetype => modify */
330             }
331         }
332
333         if ( expect_modop ) {
334             expect_modop = 0;
335             expect_sep = 1;
336             if ( strcasecmp( type, T_MODOPADDSTR ) == 0 ) {
337                 modop = LDAP_MOD_ADD;
338                 continue;
339             } else if ( strcasecmp( type, T_MODOPREPLACESTR ) == 0 ) {
340                 modop = LDAP_MOD_REPLACE;
341                 continue;
342             } else if ( strcasecmp( type, T_MODOPDELETESTR ) == 0 ) {
343                 modop = LDAP_MOD_DELETE;
344                 addmodifyop( &pmods, modop, value, NULL, 0 );
345                 continue;
346             } else {    /* no modify op:  use default */
347                 modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
348             }
349         }
350
351         if ( expect_newrdn ) {
352             if ( strcasecmp( type, T_NEWRDNSTR ) == 0 ) {
353                 if (( newrdn = strdup( value )) == NULL ) {
354                     perror( "strdup" );
355                     exit( 1 );
356                 }
357                 expect_deleteoldrdn = 1;
358                 expect_newrdn = 0;
359             } else {
360                 fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n",
361                         prog, T_NEWRDNSTR, type, linenum, dn );
362                 rc = LDAP_PARAM_ERROR;
363             }
364         } else if ( expect_deleteoldrdn ) {
365             if ( strcasecmp( type, T_DELETEOLDRDNSTR ) == 0 ) {
366                 deleteoldrdn = ( *value == '0' ) ? 0 : 1;
367                 got_all = 1;
368             } else {
369                 fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n",
370                         prog, T_DELETEOLDRDNSTR, type, linenum, dn );
371                 rc = LDAP_PARAM_ERROR;
372             }
373         } else if ( got_all ) {
374             fprintf( stderr,
375                     "%s: extra lines at end (line %d of entry %s)\n",
376                     prog, linenum, dn );
377             rc = LDAP_PARAM_ERROR;
378         } else {
379             addmodifyop( &pmods, modop, type, value, vlen );
380         }
381     }
382
383     if ( rc == 0 ) {
384         if ( delete_entry ) {
385             rc = dodelete( dn );
386         } else if ( newrdn != NULL ) {
387             rc = domodrdn( dn, newrdn, deleteoldrdn );
388         } else {
389             rc = domodify( dn, pmods, new_entry );
390         }
391
392         if ( rc == LDAP_SUCCESS ) {
393             rc = 0;
394         }
395     }
396
397     if ( dn != NULL ) {
398         free( dn );
399     }
400     if ( newrdn != NULL ) {
401         free( newrdn );
402     }
403     if ( pmods != NULL ) {
404         freepmods( pmods );
405     }
406
407     return( rc );
408 }
409
410
411 static int
412 process_ldapmod_rec( char *rbuf )
413 {
414     char        *line, *dn, *p, *q, *attr, *value;
415     int         rc, linenum, modop;
416     LDAPMod     **pmods;
417
418     pmods = NULL;
419     dn = NULL;
420     linenum = 0;
421     line = rbuf;
422     rc = 0;
423
424     while ( rc == 0 && rbuf != NULL && *rbuf != '\0' ) {
425         ++linenum;
426         if (( p = strchr( rbuf, '\n' )) == NULL ) {
427             rbuf = NULL;
428         } else {
429             if ( *(p-1) == '\\' ) {     /* lines ending in '\' are continued */
430                 strcpy( p - 1, p );
431                 rbuf = p;
432                 continue;
433             }
434             *p++ = '\0';
435             rbuf = p;
436         }
437
438         if ( dn == NULL ) {     /* first line contains DN */
439             if (( dn = strdup( line )) == NULL ) {
440                 perror( "strdup" );
441                 exit( 1 );
442             }
443         } else {
444             if (( p = strchr( line, '=' )) == NULL ) {
445                 value = NULL;
446                 p = line + strlen( line );
447             } else {
448                 *p++ = '\0';
449                 value = p;
450             }
451
452             for ( attr = line; *attr != '\0' && isspace( *attr ); ++attr ) {
453                 ;       /* skip attribute leading white space */
454             }
455
456             for ( q = p - 1; q > attr && isspace( *q ); --q ) {
457                 *q = '\0';      /* remove attribute trailing white space */
458             }
459
460             if ( value != NULL ) {
461                 while ( isspace( *value )) {
462                     ++value;            /* skip value leading white space */
463                 }
464                 for ( q = value + strlen( value ) - 1; q > value &&
465                         isspace( *q ); --q ) {
466                     *q = '\0';  /* remove value trailing white space */
467                 }
468                 if ( *value == '\0' ) {
469                     value = NULL;
470                 }
471
472             }
473
474             if ( value == NULL && new ) {
475                 fprintf( stderr, "%s: missing value on line %d (attr is %s)\n",
476                         prog, linenum, attr );
477                 rc = LDAP_PARAM_ERROR;
478             } else {
479                  switch ( *attr ) {
480                 case '-':
481                     modop = LDAP_MOD_DELETE;
482                     ++attr;
483                     break;
484                 case '+':
485                     modop = LDAP_MOD_ADD;
486                     ++attr;
487                     break;
488                 default:
489                     modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
490                 }
491
492                 addmodifyop( &pmods, modop, attr, value,
493                         ( value == NULL ) ? 0 : strlen( value ));
494             }
495         }
496
497         line = rbuf;
498     }
499
500     if ( rc == 0 ) {
501         if ( dn == NULL ) {
502             rc = LDAP_PARAM_ERROR;
503         } else if (( rc = domodify( dn, pmods, new )) == LDAP_SUCCESS ) {
504             rc = 0;
505         }
506     }
507
508     if ( pmods != NULL ) {
509         freepmods( pmods );
510     }
511     if ( dn != NULL ) {
512         free( dn );
513     }
514
515     return( rc );
516 }
517
518
519 static void
520 addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
521 {
522     LDAPMod             **pmods;
523     int                 i, j;
524     struct berval       *bvp;
525
526     pmods = *pmodsp;
527     modop |= LDAP_MOD_BVALUES;
528
529     i = 0;
530     if ( pmods != NULL ) {
531         for ( ; pmods[ i ] != NULL; ++i ) {
532             if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
533                     pmods[ i ]->mod_op == modop ) {
534                 break;
535             }
536         }
537     }
538
539     if ( pmods == NULL || pmods[ i ] == NULL ) {
540         if (( pmods = (LDAPMod **)safe_realloc( pmods, (i + 2) *
541                 sizeof( LDAPMod * ))) == NULL ) {
542             perror( "safe_realloc" );
543             exit( 1 );
544         }
545         *pmodsp = pmods;
546         pmods[ i + 1 ] = NULL;
547         if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
548                 == NULL ) {
549             perror( "calloc" );
550             exit( 1 );
551         }
552         pmods[ i ]->mod_op = modop;
553         if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
554             perror( "strdup" );
555             exit( 1 );
556         }
557     }
558
559     if ( value != NULL ) {
560         j = 0;
561         if ( pmods[ i ]->mod_bvalues != NULL ) {
562             for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
563                 ;
564             }
565         }
566         if (( pmods[ i ]->mod_bvalues =
567                 (struct berval **)safe_realloc( pmods[ i ]->mod_bvalues,
568                 (j + 2) * sizeof( struct berval * ))) == NULL ) {
569             perror( "safe_realloc" );
570             exit( 1 );
571         }
572         pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
573         if (( bvp = (struct berval *)malloc( sizeof( struct berval )))
574                 == NULL ) {
575             perror( "malloc" );
576             exit( 1 );
577         }
578         pmods[ i ]->mod_bvalues[ j ] = bvp;
579
580         if ( valsfromfiles && *value == '/' ) { /* get value from file */
581             if ( fromfile( value, bvp ) < 0 ) {
582                 exit( 1 );
583             }
584         } else {
585             bvp->bv_len = vlen;
586             if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
587                 perror( "malloc" );
588                 exit( 1 );
589             }
590             SAFEMEMCPY( bvp->bv_val, value, vlen );
591             bvp->bv_val[ vlen ] = '\0';
592         }
593     }
594 }
595
596
597 static int
598 domodify( char *dn, LDAPMod **pmods, int newentry )
599 {
600     int                 i, j, k, notascii, op;
601     struct berval       *bvp;
602
603     if ( pmods == NULL ) {
604         fprintf( stderr, "%s: no attributes to change or add (entry %s)\n",
605                 prog, dn );
606         return( LDAP_PARAM_ERROR );
607     }
608
609     if ( verbose ) {
610         for ( i = 0; pmods[ i ] != NULL; ++i ) {
611             op = pmods[ i ]->mod_op & ~LDAP_MOD_BVALUES;
612             printf( "%s %s:\n", op == LDAP_MOD_REPLACE ?
613                     "replace" : op == LDAP_MOD_ADD ?
614                     "add" : "delete", pmods[ i ]->mod_type );
615             if ( pmods[ i ]->mod_bvalues != NULL ) {
616                 for ( j = 0; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
617                     bvp = pmods[ i ]->mod_bvalues[ j ];
618                     notascii = 0;
619                     for ( k = 0; k < bvp->bv_len; ++k ) {
620                         if ( !isascii( bvp->bv_val[ k ] )) {
621                             notascii = 1;
622                             break;
623                         }
624                     }
625                     if ( notascii ) {
626                         printf( "\tNOT ASCII (%ld bytes)\n", bvp->bv_len );
627                     } else {
628                         printf( "\t%s\n", bvp->bv_val );
629                     }
630                 }
631             }
632         }
633     }
634
635     if ( newentry ) {
636         printf( "%sadding new entry %s\n", not ? "!" : "", dn );
637     } else {
638         printf( "%smodifying entry %s\n", not ? "!" : "", dn );
639     }
640
641     if ( !not ) {
642         if ( newentry ) {
643             i = ldap_add_s( ld, dn, pmods );
644         } else {
645             i = ldap_modify_s( ld, dn, pmods );
646         }
647         if ( i != LDAP_SUCCESS ) {
648             ldap_perror( ld, newentry ? "ldap_add" : "ldap_modify" );
649         } else if ( verbose ) {
650             printf( "modify complete\n" );
651         }
652     } else {
653         i = LDAP_SUCCESS;
654     }
655
656     putchar( '\n' );
657
658     return( i );
659 }
660
661
662 static int
663 dodelete( char *dn )
664 {
665     int rc;
666
667     printf( "%sdeleting entry %s\n", not ? "!" : "", dn );
668     if ( !not ) {
669         if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) {
670             ldap_perror( ld, "ldap_delete" );
671         } else if ( verbose ) {
672             printf( "delete complete" );
673         }
674     } else {
675         rc = LDAP_SUCCESS;
676     }
677
678     putchar( '\n' );
679
680     return( rc );
681 }
682
683
684 static int
685 domodrdn( char *dn, char *newrdn, int deleteoldrdn )
686 {
687     int rc;
688
689     if ( verbose ) {
690         printf( "new RDN: %s (%skeep existing values)\n",
691                 newrdn, deleteoldrdn ? "do not " : "" );
692     }
693
694     printf( "%smodifying rdn of entry %s\n", not ? "!" : "", dn );
695     if ( !not ) {
696         if (( rc = ldap_modrdn2_s( ld, dn, newrdn, deleteoldrdn ))
697                 != LDAP_SUCCESS ) {
698             ldap_perror( ld, "ldap_modrdn" );
699         } else {
700             printf( "modrdn completed\n" );
701         }
702     } else {
703         rc = LDAP_SUCCESS;
704     }
705
706     putchar( '\n' );
707
708     return( rc );
709 }
710
711
712
713 static void
714 freepmods( LDAPMod **pmods )
715 {
716     int i;
717
718     for ( i = 0; pmods[ i ] != NULL; ++i ) {
719         if ( pmods[ i ]->mod_bvalues != NULL ) {
720             ber_bvecfree( pmods[ i ]->mod_bvalues );
721         }
722         if ( pmods[ i ]->mod_type != NULL ) {
723             free( pmods[ i ]->mod_type );
724         }
725         free( pmods[ i ] );
726     }
727     free( pmods );
728 }
729
730
731 static int
732 fromfile( char *path, struct berval *bv )
733 {
734         FILE            *fp;
735         long            rlen;
736         int             eof;
737
738         if (( fp = fopen( path, "r" )) == NULL ) {
739                 perror( path );
740                 return( -1 );
741         }
742
743         if ( fseek( fp, 0L, SEEK_END ) != 0 ) {
744                 perror( path );
745                 fclose( fp );
746                 return( -1 );
747         }
748
749         bv->bv_len = ftell( fp );
750
751         if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) {
752                 perror( "malloc" );
753                 fclose( fp );
754                 return( -1 );
755         }
756
757         if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
758                 perror( path );
759                 fclose( fp );
760                 return( -1 );
761         }
762
763         rlen = fread( bv->bv_val, 1, bv->bv_len, fp );
764         eof = feof( fp );
765         fclose( fp );
766
767         if ( rlen != bv->bv_len ) {
768                 perror( path );
769                 free( bv->bv_val );
770                 return( -1 );
771         }
772
773         return( bv->bv_len );
774 }
775
776
777 static char *
778 read_one_record( FILE *fp )
779 {
780     int         len;
781     char        *buf, line[ LDAPMOD_MAXLINE ];
782     int         lcur, lmax;
783
784     lcur = lmax = 0;
785     buf = NULL;
786
787     while (( fgets( line, sizeof(line), fp ) != NULL ) &&
788             (( len = strlen( line )) > 1 )) {
789         if ( lcur + len + 1 > lmax ) {
790             lmax = LDAPMOD_MAXLINE
791                     * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
792             if (( buf = (char *)safe_realloc( buf, lmax )) == NULL ) {
793                 perror( "safe_realloc" );
794                 exit( 1 );
795             }
796         }
797         strcpy( buf + lcur, line );
798         lcur += len;
799     }
800
801     return( buf );
802 }