]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/edb2ldif.c
Update for Alpha3 from -devel as of OPENLDAP_DEVEL_981116.
[openldap] / servers / slapd / tools / edb2ldif.c
1 /*
2  * Copyright (c) 1995 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include <ac/ctype.h>
19 #include <ac/errno.h>
20 #include <ac/dirent.h>
21 #include <ac/string.h>
22 #include <ac/unistd.h>
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include <quipu/config.h>
28 #include <quipu/entry.h>
29 #include <quipu/commonarg.h>
30 #include <quipu/attrvalue.h>
31
32 #if ICRELEASE > 1
33 #define HAVE_FILE_ATTR_DIR
34 #endif
35
36 #ifdef TURBO_DISK
37 #define HAVE_PARSE_ENTRY
38 #endif
39
40 #define DEF_EDBFILENAME         "EDB"
41 #define EDB_ROOT_FILENAME       "EDB.root"
42 #define DEF_BASEDN              ""
43 #define EDBMAP_FILENAME         "EDB.map"
44 #define ADDVALS_FILENAME        ".add"
45
46 #define MAX_LINE_SIZE   2048
47
48 #define VERBOSE_ENTRY_REPORT_THRESHOLD  250
49
50
51 /* data structures */
52 struct edbmap {
53     char                *edbm_filename;
54     char                *edbm_rdn;
55     struct edbmap       *edbm_next;
56 };
57
58 /* prototypes */
59 static int edb2ldif( FILE *outfp, char *edbfile, char *basedn, int recurse );
60 static int convert_entry( FILE *fp, char *edbname, FILE *outfp,
61         char *basedn, char *loc_addvals, int loc_addlen, char *linebuf );
62 static int add_rdn_values (Attr_Sequence entryas, RDN rdn);
63 static int read_edbmap( char *mapfile, struct edbmap **edbmapp );
64 static char *file2rdn( struct edbmap *edbmap, char *filename );
65 static void free_edbmap( struct edbmap *edbmap );
66 static char *read_file( char *filename, int *lenp );
67 static void print_err( char *msg );
68
69
70 /* globals */
71 #ifdef LDAP_DEBUG
72 static int      debugflg;
73 #endif
74 static int      verboseflg;
75 static int      override_add = 0;
76 static int      entrycount;
77 static char     **ignore_attr = NULL;
78 static char     *always_addvals = NULL;
79 static int      always_addlen;
80 static char     *last_dn;
81 static char     *edb_home = ".";
82 char            *progname;
83 int             ldap_syslog = 0;
84 int             ldap_syslog_level = 0;
85
86
87 int
88 main( int argc, char **argv )
89 {
90     char        *usage = "usage: %s [-d] [-o] [-r] [-v] [-b basedn] [-a addvalsfile] [-f fileattrdir] [-i ignoreattr...] [edbfile...]\n";
91     char        edbfile[ MAXNAMLEN ], *basedn;
92     int         c, rc, errflg, ignore_count, recurse;
93     extern char dsa_mode;
94 #ifdef HAVE_FILE_ATTR_DIR
95     extern char *file_attr_directory;
96 #endif
97
98     if (( progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
99         progname = argv[ 0 ];
100     } else {
101         ++progname;
102     }
103
104     errflg = recurse = 0;
105 #ifdef LDAP_DEBUG
106     debugflg = 0;
107 #endif
108     ignore_count = 0;
109     always_addvals = NULL;
110     basedn = NULL;
111
112     while (( c = getopt( argc, argv, "dorva:b:f:h:i:" )) != -1 ) {
113         switch( c ) {
114         case 'd':
115 #ifdef LDAP_DEBUG
116             ++debugflg;
117 #else
118             fprintf( stderr, "Ignoring -d:  compile with -DLDAP_DEBUG to enable this option.\n" );
119 #endif
120             break;
121
122         case 'o':
123             ++override_add;     
124             break;
125
126         case 'r':
127             ++recurse;  
128             break;
129
130         case 'v':
131             ++verboseflg;
132             break;
133
134         case 'a':
135             if ( always_addvals != NULL ) {
136                 ++errflg;
137             } else if (( always_addvals = read_file( optarg, &always_addlen ))
138                     == NULL ) {
139                 print_err( optarg );
140                 exit( 1 );
141             }
142             break;
143
144         case 'b':
145             if ( basedn != NULL ) {
146                 ++errflg;
147             } else {
148                 basedn = optarg;
149             }
150             break;
151
152         case 'f':
153 #ifdef HAVE_FILE_ATTR_DIR
154             /* add trailing slash to directory name if missing */
155             if ( *( optarg + strlen( optarg ) - 1 ) == '/' ) {
156                 file_attr_directory = strdup( optarg );
157             } else if (( file_attr_directory = (char *)malloc( strlen( optarg )
158                     + 2 )) != NULL ) {
159                 sprintf( file_attr_directory, "%s/", optarg );
160         
161             }
162             if ( file_attr_directory == NULL ) {
163                 print_err( "malloc" );
164                 exit( 1 );
165             }
166 #else /* HAVE_FILE_ATTR_DIR */
167             fprintf( stderr, "Ignoring -f:  this option requires a newer version of ISODE.\n" );
168 #endif /* HAVE_FILE_ATTR_DIR */
169             break;
170
171         case 'h':
172             edb_home = optarg;
173             break;
174
175         case 'i':
176             if ( ignore_count == 0 ) {
177                 ignore_attr = (char **)malloc( 2 * sizeof( char * ));
178             } else {
179                 ignore_attr = (char **)realloc( ignore_attr,
180                     ( ignore_count + 2 ) * sizeof( char * ));
181             }
182             if ( ignore_attr == NULL ) {
183                 print_err( "malloc/realloc" );
184                 exit( 1 );
185             }
186             ignore_attr[ ignore_count ] = optarg;
187             ignore_attr[ ++ignore_count ] = NULL;
188             break;
189
190         default:
191             ++errflg;
192         }
193     }
194
195     if ( errflg ) {
196         fprintf( stderr, usage, progname );
197         exit( 1 );
198     }
199
200     if ( basedn == NULL ) {
201         basedn = DEF_BASEDN;
202     }
203
204     /* load & initialize quipu syntax handlers */
205     quipu_syntaxes();
206 #ifdef LDAP_USE_PP
207     pp_quipu_init( progname );
208 #endif
209     dsap_init( NULL, NULL );
210
211     dsa_mode = 1;       /* so {CRYPT} is accepted by EDB parse routines */
212
213     if ( init_syntaxes() < 0 ) {
214         fprintf( stderr, "%s: init_syntaxes failed -- check your oid tables \n",
215             progname );
216         exit( 1 );
217     }
218
219
220     entrycount = 0;
221
222     /* process EDB file(s) */
223     if ( optind >= argc ) {
224         *edbfile = '\0';
225         rc = edb2ldif( stdout, edbfile, basedn, recurse );
226     } else {
227         for ( rc = 0; rc >= 0 && optind < argc; ++optind ) {
228             if ( argv[ optind ][ 0 ] == '/' ) {
229                 strcpy( edbfile, argv[ optind ] );
230             } else {
231                 sprintf( edbfile, "%s/%s", edb_home, argv[ optind ] );
232             }
233             rc = edb2ldif( stdout, edbfile, basedn, recurse );
234         }
235     }
236
237     if ( last_dn != NULL ) {
238         free( last_dn );
239     }
240
241 #ifdef LDAP_DEBUG
242     fprintf( stderr, "edb2ldif: exit( %d )\n", ( rc < 0 ) ? 1 : 0 );
243 #endif
244
245     exit( ( rc < 0 ) ? 1 : 0 );
246 }
247
248
249 static int
250 edb2ldif( FILE *outfp, char *edbfile, char *basedn, int recurse )
251 {
252     FILE        *fp;
253     char        *addvals, *p, *rdn, line[ MAX_LINE_SIZE + 1 ];
254     char        dirname[ MAXNAMLEN ], filename[ MAXNAMLEN ];
255     int         err, startcount, addvals_len;
256     struct stat st;
257
258 #ifdef LDAP_DEBUG
259     if ( debugflg ) {
260         fprintf( stderr, "edb2ldif( 0x%X, \"%s\", \"%s\", %d)\n",
261                 outfp, edbfile, basedn, recurse );
262     }
263 #endif
264
265     if ( *edbfile == '\0' ) {
266         sprintf( filename, "%s/%s", edb_home, EDB_ROOT_FILENAME );
267         if ( stat( filename, &st ) == 0 ) {
268             if (( err = edb2ldif( outfp, filename, basedn, 0 )) < 0 ) {
269 #ifdef LDAP_DEBUG
270                 if ( debugflg ) {
271                     fprintf( stderr, "edb2ldif: 0 return( %d )\n", err );
272                 }
273 #endif
274                 return( err );
275             }
276             if (( basedn = strdup( last_dn )) == NULL ) {
277                 print_err( "strdup" );
278 #ifdef LDAP_DEBUG
279                 if ( debugflg ) {
280                     fprintf( stderr, "edb2ldif: 1 return( -1 )\n" );
281                 }
282 #endif
283                 return( -1 );
284             }
285         }
286         sprintf( edbfile, "%s/%s", edb_home, DEF_EDBFILENAME );
287     }
288
289     if ( verboseflg ) {
290         fprintf( stderr, "%s: converting EDB file: \"%s\"\n\tbasedn: \"%s\"\n",
291                 progname, edbfile, basedn );
292     }
293
294     startcount = entrycount;
295     err = 0;
296
297
298     /* construct name of directory we are working in */
299     if (( p = strrchr( edbfile, '/' )) == NULL ) {
300         dirname[ 0 ] = '.';
301         dirname[ 1 ] = '\0';
302     } else {
303         strncpy( dirname, edbfile, p - edbfile );
304         dirname[ p - edbfile ] = '\0';
305     }
306
307     /* load local ".add" file (if any) */
308     sprintf( filename, "%s/%s", dirname, ADDVALS_FILENAME );
309     addvals_len = 0;
310     addvals = read_file( filename, &addvals_len );
311
312     /* read and convert this EDB file */
313     if (( fp = fopen( edbfile, "r" )) == NULL ) {
314         print_err( edbfile );
315         if ( addvals != NULL ) {
316             free( addvals );
317         }
318 #ifdef LDAP_DEBUG
319         if ( debugflg ) {
320             fprintf( stderr, "edb2ldif: 2 return( -1 )\n" );
321         }
322 #endif
323         return( -1 );
324     }
325
326     /* skip first two lines (type and timestamp) if they are present */
327     if ( fgets( line, MAX_LINE_SIZE, fp ) == NULL ) {
328         err = -1;
329     } else {
330         line[ strlen( line ) - 1 ] = '\0';
331         if ( strcmp( line, "MASTER" ) == 0 || strcmp( line, "SLAVE" ) == 0 ||
332                 strcmp( line, "CACHE" ) == 0 ) {
333             if ( fgets( line, MAX_LINE_SIZE, fp ) == NULL ) {
334                 err = -1;
335             }
336         } else {
337             rewind( fp );
338         }
339     }
340
341     if ( err != 0 ) {
342         fprintf( stderr, "%s: skipping empty EDB file %s\n", progname,
343                 edbfile );
344         err = 0;        /* treat as a non-fatal error */
345     } else {
346         while ( !feof( fp ) && ( err = convert_entry( fp, edbfile, outfp,
347                 basedn, addvals, addvals_len, line )) > 0 ) {
348             if ( verboseflg && (( entrycount - startcount ) %
349                     VERBOSE_ENTRY_REPORT_THRESHOLD ) == 0 ) {
350                 fprintf( stderr, "\tworking... %d entries done...\n", 
351                         entrycount - startcount );
352             }
353         }
354     }
355
356     fclose( fp );
357     if ( addvals != NULL ) {
358         free( addvals );
359     }
360
361     if ( err < 0 ) {
362 #ifdef LDAP_DEBUG
363         if ( debugflg ) {
364             fprintf( stderr, "edb2ldif: 3 return( %d )\n", err );
365         }
366 #endif
367         return( err );
368     }
369
370     if ( verboseflg ) {
371         fprintf( stderr, "\t%d entries converted\n\n", 
372                 entrycount - startcount );
373     }
374
375     /* optionally convert EDB file within sub-directories */
376     if ( recurse ) {
377         char            *newbase;
378         DIR             *dp;
379         struct dirent   *dep;
380         struct edbmap   *edbmap;
381
382         /* open this directory */
383         if (( dp = opendir( dirname )) == NULL ) {
384             print_err( dirname );
385 #ifdef LDAP_DEBUG
386             if ( debugflg ) {
387                 fprintf( stderr, "edb2ldif: 4 return( -1 )\n" );
388             }
389 #endif
390             return( -1 );
391         }
392
393         /* check for EDB.map file and record contents for future reference */
394         sprintf( filename, "%s/%s", dirname, EDBMAP_FILENAME );
395         if ( read_edbmap( filename, &edbmap ) < 0 ) {
396             print_err( "read_edbmap" );
397             closedir( dp );
398 #ifdef LDAP_DEBUG
399             if ( debugflg ) {
400                 fprintf( stderr, "edb2ldif: 5 return( -1 )\n" );
401             }
402 #endif
403             return( -1 );
404         }
405
406         p = dirname + strlen( dirname );
407         *p++ = '/';
408         *p = '\0';
409
410         /* scan looking for sub-directories w/EDB files in them */
411         err = 0;
412         while ( err >= 0 && ( dep = readdir( dp )) != NULL ) {
413             if ( dep->d_name[ 0 ] == '.' && ( dep->d_name[ 1 ] == '\0' ||
414                     ( dep->d_name[ 1 ] == '.' && dep->d_name[ 2 ] == '\0' ))) {
415                 continue;       /* skip "." and ".." */
416             }
417
418             strcpy( p, dep->d_name );
419 #ifdef LDAP_DEBUG
420             if ( debugflg ) {
421                 fprintf( stderr, "edb2ldif: checking directory \"%s\"\n",
422                         dirname );
423             }
424 #endif
425
426             if ( stat( dirname, &st ) != 0 ) {
427                 print_err( dirname );
428             } else if ( S_ISDIR( st.st_mode )) {
429                 sprintf( filename, "%s/%s", dirname, DEF_EDBFILENAME );
430
431                 if ( stat( filename, &st ) == 0 && S_ISREG( st.st_mode )) {
432                     if (( newbase = malloc( strlen( basedn ) +
433                             strlen( dep->d_name ) + 3 )) == NULL ) {
434                         print_err( "malloc" );
435                         err = -1;
436                         continue;
437                     }
438
439                     sprintf( newbase, "%s@%s", basedn,
440                             file2rdn( edbmap, dep->d_name ));
441
442                     /* recurse */
443                     err = edb2ldif( outfp, filename, newbase, recurse );
444
445                     free( newbase );
446                 }
447             }
448         }
449
450         free_edbmap( edbmap );
451         closedir( dp );
452
453         if ( verboseflg ) {
454             fprintf( stderr, "%s: %d total entries converted under \"%s\"\n\n",
455                     progname, entrycount - startcount, basedn );
456         }
457     }
458
459 #ifdef LDAP_DEBUG
460     if ( debugflg ) {
461         fprintf( stderr, "edb2ldif: 6 return( %d )\n", err );
462     }
463 #endif
464     return( err );
465 }
466
467
468 /*
469  * read one entry from fp and write to outfp.
470  * return > 0 if entry converted, 0 if end of file, < 0 if error occurs
471  */
472 static int
473 convert_entry(
474     FILE        *fp,
475     char        *edbname,
476     FILE        *outfp,
477     char        *basedn,
478     char        *loc_addvals,
479     int         loc_addlen,
480     char        *linebuf
481 )
482 {
483     Attr_Sequence       as, tmpas;
484     AV_Sequence         av;
485     PS                  attrtype_ps, val_ps;
486     char                *dnstr;
487     DN                  dn;
488     RDN                 rdn;
489     int                 valcnt;
490     extern int          parse_status;
491     extern char         *parse_file;
492     extern RDN          parse_rdn;
493 #ifdef HAVE_PARSE_ENTRY
494     extern char         *parse_entry;
495     extern Attr_Sequence        fget_attributes();
496 #else /* HAVE_PARSE_ENTRY */
497     extern Attr_Sequence        get_attributes();
498 #endif /* HAVE_PARSE_ENTRY */
499
500 #ifdef LDAP_DEBUG
501     if ( debugflg ) {
502         fprintf( stderr, "convert_entry( 0x%X, \"%s\", 0x%X, \"%s\", ...)\n",
503                 fp, edbname, outfp, basedn );
504     }
505 #endif
506
507     while (( dnstr = fgets( linebuf, MAX_LINE_SIZE, fp )) != NULL &&
508             *linebuf == '\n' ) {
509         ;
510     }
511
512     if ( dnstr == NULL ) {
513         return( feof( fp ) ? 0 : -1 );  /* end of file or error */
514     }
515
516     linebuf[ strlen( linebuf ) - 1 ] = '\0';
517
518     if (( dnstr = malloc( strlen( basedn ) + strlen( linebuf ) + 2 ))
519             == NULL ) {
520         print_err( "convert_entry" );
521         return( -1 );
522     }
523     sprintf( dnstr, "%s@%s", basedn, linebuf );
524     if ( last_dn != NULL ) {
525         free( last_dn );
526     }
527     last_dn = dnstr;
528
529     if ( entrycount > 0 ) {
530         fputc( '\n', outfp );
531     }
532
533     /*
534      * parse_entry, parse_file and parse_rdn are needed inside the
535      * libisode decoding routines, so we set it here.
536      */
537     parse_file = edbname;
538 #ifdef HAVE_PARSE_ENTRY
539     parse_entry = dnstr;
540 #endif
541     parse_rdn = rdn = str2rdn( linebuf );
542
543     if (( val_ps = ps_alloc( str_open )) == NULLPS ||
544             str_setup( val_ps, NULLCP, 0, 0 ) == NOTOK ) {
545         fprintf( stderr, "%s: ps_alloc/setup failed (EDB file %s)\n", progname,
546                 edbname );
547         if ( rdn != NULLRDN ) {
548             rdn_free( rdn );
549         }
550         return( -1 );
551     }
552
553     if (( dn = str2dn( dnstr )) == NULLDN || av2ldif( outfp, NULL, dn,
554             0, "dn", val_ps ) < 0 ) {
555         sprintf( linebuf,
556                 "str2dn or av2ldif of DN failed (EDB file %s, entry %s)\n", 
557                 edbname, dnstr );
558         print_err( linebuf );
559         if ( dn != NULLDN ) {
560             dn_free( dn );
561         }
562         ps_free( val_ps );
563         if ( rdn != NULLRDN ) {
564             rdn_free( rdn );
565         }
566         return( -1 );
567     }
568     dn_free( dn );
569
570     ++entrycount;
571
572     if ( always_addvals != NULL && ( loc_addvals == NULL || !override_add )
573             && fwrite( always_addvals, always_addlen, 1, outfp ) != 1 ) {
574         sprintf( linebuf,
575                 "write of additional values failed (EDB file %s, entry %s)\n", 
576                 edbname, dnstr );
577         print_err( linebuf );
578         ps_free( val_ps );
579         if ( rdn != NULLRDN ) {
580             rdn_free( rdn );
581         }
582         return( -1 );
583     }
584
585     if ( loc_addvals != NULL && fwrite( loc_addvals, loc_addlen, 1,
586             outfp ) != 1 ) {
587         sprintf( linebuf,
588                 "write of additional values failed (EDB file %s, entry %s)\n", 
589                 edbname, dnstr );
590         print_err( linebuf );
591         ps_free( val_ps );
592         if ( rdn != NULLRDN ) {
593             rdn_free( rdn );
594         }
595         return( -1 );
596     }
597
598
599 #ifdef HAVE_PARSE_ENTRY
600     as = fget_attributes( fp );
601 #else /* HAVE_PARSE_ENTRY */
602     as = get_attributes( fp );
603 #endif /* HAVE_PARSE_ENTRY */
604
605     if ( parse_status != 0 ) {
606         fprintf( stderr, "%s: problem parsing entry (EDB file %s)\n", progname,
607                 edbname );
608         ps_free( val_ps );
609         if ( as != NULLATTR ) {
610             as_free( as );
611         }
612         if ( rdn != NULLRDN ) {
613             rdn_free( rdn );
614         }
615         return( -1 );
616     }
617
618     if ( add_rdn_values( as, rdn ) != 0 ) {
619         sprintf( linebuf,
620             "adding RDN values(s) failed (EDB file %s, entry %s)\n", 
621             edbname, dnstr );
622         print_err( linebuf );
623         if ( as != NULLATTR ) {
624             as_free( as );
625         }
626         if ( rdn != NULLRDN ) {
627             rdn_free( rdn );
628         }
629         return( -1 );
630     }
631
632     if (( attrtype_ps = ps_alloc( str_open )) == NULLPS ||
633             str_setup( attrtype_ps, NULLCP, 0, 0 ) == NOTOK ) {
634         fprintf( stderr, "%s: ps_alloc/setup failed (EDB file %s)\n", progname,
635                 edbname );
636         if ( as != NULLATTR ) {
637             as_free( as );
638         }
639         if ( rdn != NULLRDN ) {
640             rdn_free( rdn );
641         }
642         return( -1 );
643     }
644
645     for ( tmpas = as; tmpas != NULLATTR; tmpas = tmpas->attr_link ) {
646         attrtype_ps->ps_ptr = attrtype_ps->ps_base;
647         AttrT_print( attrtype_ps, tmpas->attr_type, EDBOUT );
648         *attrtype_ps->ps_ptr = '\0';
649
650         if ( ignore_attr != NULL ) {
651             int i;
652
653             for ( i = 0; ignore_attr[ i ] != NULL; ++i ) {
654                 if ( strcasecmp( attrtype_ps->ps_base, ignore_attr[ i ] )
655                         == 0 ) {
656                     break;
657                 }
658             }
659             if ( ignore_attr[ i ] != NULL ) {
660                 continue;       /* skip this attribute */
661             }
662         }
663
664         valcnt = 0;
665         for ( av = tmpas->attr_value; av != NULLAV; av = av->avseq_next ) {
666             ++valcnt;
667             if ( av2ldif( outfp, av, NULL, tmpas->attr_type->oa_syntax,
668                     attrtype_ps->ps_base, val_ps ) < 0 ) {
669                 sprintf( linebuf,
670                         "av2ldif failed (EDB file %s, entry %s, attribute %s, value no. %d)\n", 
671                         edbname, dnstr, attrtype_ps->ps_base, valcnt );
672                 print_err( linebuf );
673                 ps_free( attrtype_ps );
674                 ps_free( val_ps );
675                 as_free( as );
676                 if ( rdn != NULLRDN ) {
677                     rdn_free( rdn );
678                 }
679                 return( -1 );
680             }
681         }
682     }
683
684     ps_free( attrtype_ps );
685     ps_free( val_ps );
686     as_free( as );
687     if ( rdn != NULLRDN ) {
688         rdn_free( rdn );
689     }
690
691     return( 1 );
692 }
693
694
695 static int
696 add_rdn_values( Attr_Sequence entryas, RDN rdn )
697 {
698 /*
699  * this routine is based on code from the real_unravel_attribute() routine
700  * found in isode-8.0/.dsap/common/attribute.c
701  */
702     AttributeType       at;
703     AV_Sequence         avs;
704     Attr_Sequence       as;
705
706     for (; rdn != NULLRDN; rdn = rdn->rdn_next ) {
707         if (( as = as_find_type( entryas, rdn->rdn_at )) == NULLATTR ) {
708             at = AttrT_cpy( rdn->rdn_at );
709             avs = avs_comp_new( AttrV_cpy(&rdn->rdn_av ));
710             as  = as_comp_new( at, avs, NULLACL_INFO );
711             entryas = as_merge( entryas, as );
712         } else {
713             for ( avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next ) {
714                 if ( AttrV_cmp( &rdn->rdn_av, &avs->avseq_av ) == 0 ) {
715                     break;
716                 }
717             }
718
719             if ( avs == NULLAV ) {
720                 avs = avs_comp_new( AttrV_cpy( &rdn->rdn_av ));
721                 as->attr_value = avs_merge( as->attr_value, avs );
722             }
723         }
724     }
725
726     return( 0 );
727 }
728
729
730 /* read the EDB.map file and return a linked list of translations */
731 static int
732 read_edbmap( char *mapfile, struct edbmap **edbmapp )
733 {
734     FILE                *fp;
735     char                *p, *filename, *rdn, line[ MAX_LINE_SIZE + 1 ];
736     int                 err;
737     struct edbmap       *emp, *tmpemp;
738
739 #ifdef LDAP_DEBUG
740     if ( debugflg ) {
741         fprintf( stderr, "read_edbmap( \"%s\", ...)\n", mapfile );
742     }
743 #endif
744
745     if (( fp = fopen( mapfile, "r" )) == NULL ) {
746         *edbmapp = NULL;
747         return( 0 );    /* soft error -- no EDB.map file */
748     }
749
750     emp = NULL;
751
752     /*
753      * read all the lines in the file, looking for lines of the form:
754      *  RDN # filename
755      */
756     err = 0;
757     while ( err == 0 && fgets( line, MAX_LINE_SIZE, fp ) != NULL ) {
758         line[ strlen( line ) - 1 ] = '\0';      /* remove trailing newline */
759         if (( filename = strchr( line, '#' )) == NULL ) {
760             continue;
761         }
762
763         *filename++ = '\0';
764         while ( isspace( *filename )) { /* strip leading whitespace */
765             ++filename;
766         }
767
768         if ( *filename == '\0' ) {
769             continue;
770         }
771
772         p = filename + strlen( filename ) - 1;
773         while ( isspace( *p )) {        /* strip trailing whitespace */
774             *p-- = '\0';
775         }
776
777         rdn = line;
778         while ( isspace( *rdn )) {      /* strip leading whitespace */
779             ++rdn;
780         }
781
782         if ( *rdn == '\0' ) {
783             continue;
784         }
785
786         p = rdn + strlen( rdn ) - 1;
787         while ( isspace( *p )) {        /* strip trailing whitespace */
788             *p-- = '\0';
789         }
790
791         if (( tmpemp = (struct edbmap *)calloc( 1, sizeof( struct edbmap )))
792                 == NULL ||
793                 ( tmpemp->edbm_filename = strdup( filename )) == NULL ||
794                 ( tmpemp->edbm_rdn = strdup( rdn )) == NULL ) {
795             err = -1;
796         } else {
797             tmpemp->edbm_next = emp;
798             emp = tmpemp;
799         }
800     }
801
802     fclose( fp );
803
804     if ( err == 0 ) {
805         *edbmapp = emp;
806     } else {
807         free_edbmap( emp );
808     }
809
810     return( err );
811 }
812
813
814 static char *
815 file2rdn( struct edbmap *edbmap, char *filename )
816 {
817 #ifdef LDAP_DEBUG
818     if ( debugflg ) {
819         fprintf( stderr, "file2rdn( 0x%X, \"%s\" )\n", edbmap, filename );
820     }
821 #endif
822
823     while ( edbmap != NULL ) {
824         if ( strcmp( filename, edbmap->edbm_filename ) == 0 ) {
825             break;
826         }
827         edbmap = edbmap->edbm_next;
828     }
829
830     return(( edbmap == NULL ) ? filename : edbmap->edbm_rdn );
831 }
832
833
834 /* free the edbmap list */
835 static void
836 free_edbmap( struct edbmap *edbmap )
837 {
838     struct edbmap       *tmp;
839
840 #ifdef LDAP_DEBUG
841     if ( debugflg ) {
842         fprintf( stderr, "free_edbmap( 0x%X )\n", edbmap );
843     }
844 #endif
845
846     while ( edbmap != NULL ) {
847         if ( edbmap->edbm_filename != NULL ) free( edbmap->edbm_filename );
848         if ( edbmap->edbm_rdn != NULL ) free( edbmap->edbm_rdn );
849         tmp = edbmap;
850         edbmap = edbmap->edbm_next;
851         free( tmp );
852     }
853 }
854
855
856 static void
857 print_err( char *msg )
858 {
859 #ifdef LDAP_DEBUG
860     if ( debugflg ) {
861         fprintf( stderr, "print_err( \"%s\" )\n", msg );
862     }
863 #endif
864
865     if ( errno > sys_nerr ) {
866         fprintf( stderr, "%s: %s: error %d\n", progname, msg, errno );
867     } else {
868         fprintf( stderr, "%s: %s: %s\n", progname, msg, sys_errlist[ errno ] );
869     }
870 }
871
872
873 static char *
874 read_file( char *filename, int *lenp )
875 {
876     FILE        *fp;
877     struct stat st;
878     char        *buf;
879
880 #ifdef LDAP_DEBUG
881     if ( debugflg ) {
882         fprintf( stderr, "read_file( \"%s\", 0x%X )\n", filename, lenp );
883     }
884 #endif
885
886     if ( stat( filename, &st ) != 0 || !S_ISREG( st.st_mode ) ||
887             ( fp = fopen( filename, "r" )) == NULL ) {
888         return( NULL );
889     }
890
891     if (( buf = (char *)malloc( st.st_size )) == NULL ) {
892         fclose( fp );
893         return( NULL );
894     }
895
896     if ( fread( buf, st.st_size, 1, fp ) != 1 ) {
897         fclose( fp );
898         free( buf );
899         return( NULL );
900     }
901
902     fclose( fp );
903     *lenp = st.st_size;
904     return( buf );
905 }