openldap/servers/slapd/tools/edb2ldif.c
Kurt Zeilenga b5494457d8 Remove extern declarations of library functions from source.c.
This could cause problems on odd systems.  The generic
  headers should be extended as needed to include necessary
  system headers or, if necessary, make explicit declarations.
Extended ac/string.h header to look for string.h/strings.h if
  STDC_HEADERS is not defined.  Also provide basic declarations for
  str*() functions.  This could cause problems on odd systems.
Extended ac/unistd.h header to define basic declaration for misc
  functions that might be missing from headers.   This includes
  externs for getenv(), getopt(), mktemp(), tempname().
Protect fax500.h from multiple inclusion.  Moved includes of
  system/generic headers back to source files.
Made mail500 helper functions static.
Fixed includes of ctype.h, signal.h, etc. to use generics.
lutil/tempname.c: was including stdlib.h twice, one should stdio.h.
Wrapped <sys/resource.h> with HAVE_SYS_RESOURCE_H.
lber/io.c/ber_get_next(): Changed noctets back to signed.
  Used with BerRead which expects signed int as second arg and
  returns signed int.
1998-11-16 05:07:27 +00:00

906 lines
20 KiB
C

/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
#include "portable.h"
#include <stdio.h>
#include <stdlib.h>
#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/dirent.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <quipu/config.h>
#include <quipu/entry.h>
#include <quipu/commonarg.h>
#include <quipu/attrvalue.h>
#if ICRELEASE > 1
#define HAVE_FILE_ATTR_DIR
#endif
#ifdef TURBO_DISK
#define HAVE_PARSE_ENTRY
#endif
#define DEF_EDBFILENAME "EDB"
#define EDB_ROOT_FILENAME "EDB.root"
#define DEF_BASEDN ""
#define EDBMAP_FILENAME "EDB.map"
#define ADDVALS_FILENAME ".add"
#define MAX_LINE_SIZE 2048
#define VERBOSE_ENTRY_REPORT_THRESHOLD 250
/* data structures */
struct edbmap {
char *edbm_filename;
char *edbm_rdn;
struct edbmap *edbm_next;
};
/* prototypes */
static int edb2ldif( FILE *outfp, char *edbfile, char *basedn, int recurse );
static int convert_entry( FILE *fp, char *edbname, FILE *outfp,
char *basedn, char *loc_addvals, int loc_addlen, char *linebuf );
static int add_rdn_values (Attr_Sequence entryas, RDN rdn);
static int read_edbmap( char *mapfile, struct edbmap **edbmapp );
static char *file2rdn( struct edbmap *edbmap, char *filename );
static void free_edbmap( struct edbmap *edbmap );
static char *read_file( char *filename, int *lenp );
static void print_err( char *msg );
/* globals */
#ifdef LDAP_DEBUG
static int debugflg;
#endif
static int verboseflg;
static int override_add = 0;
static int entrycount;
static char **ignore_attr = NULL;
static char *always_addvals = NULL;
static int always_addlen;
static char *last_dn;
static char *edb_home = ".";
char *progname;
int ldap_syslog = 0;
int ldap_syslog_level = 0;
int
main( int argc, char **argv )
{
char *usage = "usage: %s [-d] [-o] [-r] [-v] [-b basedn] [-a addvalsfile] [-f fileattrdir] [-i ignoreattr...] [edbfile...]\n";
char edbfile[ MAXNAMLEN ], *basedn;
int c, rc, errflg, ignore_count, recurse;
extern char dsa_mode;
#ifdef HAVE_FILE_ATTR_DIR
extern char *file_attr_directory;
#endif
if (( progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
progname = argv[ 0 ];
} else {
++progname;
}
errflg = recurse = 0;
#ifdef LDAP_DEBUG
debugflg = 0;
#endif
ignore_count = 0;
always_addvals = NULL;
basedn = NULL;
while (( c = getopt( argc, argv, "dorva:b:f:h:i:" )) != -1 ) {
switch( c ) {
case 'd':
#ifdef LDAP_DEBUG
++debugflg;
#else
fprintf( stderr, "Ignoring -d: compile with -DLDAP_DEBUG to enable this option.\n" );
#endif
break;
case 'o':
++override_add;
break;
case 'r':
++recurse;
break;
case 'v':
++verboseflg;
break;
case 'a':
if ( always_addvals != NULL ) {
++errflg;
} else if (( always_addvals = read_file( optarg, &always_addlen ))
== NULL ) {
print_err( optarg );
exit( 1 );
}
break;
case 'b':
if ( basedn != NULL ) {
++errflg;
} else {
basedn = optarg;
}
break;
case 'f':
#ifdef HAVE_FILE_ATTR_DIR
/* add trailing slash to directory name if missing */
if ( *( optarg + strlen( optarg ) - 1 ) == '/' ) {
file_attr_directory = strdup( optarg );
} else if (( file_attr_directory = (char *)malloc( strlen( optarg )
+ 2 )) != NULL ) {
sprintf( file_attr_directory, "%s/", optarg );
}
if ( file_attr_directory == NULL ) {
print_err( "malloc" );
exit( 1 );
}
#else /* HAVE_FILE_ATTR_DIR */
fprintf( stderr, "Ignoring -f: this option requires a newer version of ISODE.\n" );
#endif /* HAVE_FILE_ATTR_DIR */
break;
case 'h':
edb_home = optarg;
break;
case 'i':
if ( ignore_count == 0 ) {
ignore_attr = (char **)malloc( 2 * sizeof( char * ));
} else {
ignore_attr = (char **)realloc( ignore_attr,
( ignore_count + 2 ) * sizeof( char * ));
}
if ( ignore_attr == NULL ) {
print_err( "malloc/realloc" );
exit( 1 );
}
ignore_attr[ ignore_count ] = optarg;
ignore_attr[ ++ignore_count ] = NULL;
break;
default:
++errflg;
}
}
if ( errflg ) {
fprintf( stderr, usage, progname );
exit( 1 );
}
if ( basedn == NULL ) {
basedn = DEF_BASEDN;
}
/* load & initialize quipu syntax handlers */
quipu_syntaxes();
#ifdef LDAP_USE_PP
pp_quipu_init( progname );
#endif
dsap_init( NULL, NULL );
dsa_mode = 1; /* so {CRYPT} is accepted by EDB parse routines */
if ( init_syntaxes() < 0 ) {
fprintf( stderr, "%s: init_syntaxes failed -- check your oid tables \n",
progname );
exit( 1 );
}
entrycount = 0;
/* process EDB file(s) */
if ( optind >= argc ) {
*edbfile = '\0';
rc = edb2ldif( stdout, edbfile, basedn, recurse );
} else {
for ( rc = 0; rc >= 0 && optind < argc; ++optind ) {
if ( argv[ optind ][ 0 ] == '/' ) {
strcpy( edbfile, argv[ optind ] );
} else {
sprintf( edbfile, "%s/%s", edb_home, argv[ optind ] );
}
rc = edb2ldif( stdout, edbfile, basedn, recurse );
}
}
if ( last_dn != NULL ) {
free( last_dn );
}
#ifdef LDAP_DEBUG
fprintf( stderr, "edb2ldif: exit( %d )\n", ( rc < 0 ) ? 1 : 0 );
#endif
exit( ( rc < 0 ) ? 1 : 0 );
}
static int
edb2ldif( FILE *outfp, char *edbfile, char *basedn, int recurse )
{
FILE *fp;
char *addvals, *p, *rdn, line[ MAX_LINE_SIZE + 1 ];
char dirname[ MAXNAMLEN ], filename[ MAXNAMLEN ];
int err, startcount, addvals_len;
struct stat st;
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif( 0x%X, \"%s\", \"%s\", %d)\n",
outfp, edbfile, basedn, recurse );
}
#endif
if ( *edbfile == '\0' ) {
sprintf( filename, "%s/%s", edb_home, EDB_ROOT_FILENAME );
if ( stat( filename, &st ) == 0 ) {
if (( err = edb2ldif( outfp, filename, basedn, 0 )) < 0 ) {
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 0 return( %d )\n", err );
}
#endif
return( err );
}
if (( basedn = strdup( last_dn )) == NULL ) {
print_err( "strdup" );
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 1 return( -1 )\n" );
}
#endif
return( -1 );
}
}
sprintf( edbfile, "%s/%s", edb_home, DEF_EDBFILENAME );
}
if ( verboseflg ) {
fprintf( stderr, "%s: converting EDB file: \"%s\"\n\tbasedn: \"%s\"\n",
progname, edbfile, basedn );
}
startcount = entrycount;
err = 0;
/* construct name of directory we are working in */
if (( p = strrchr( edbfile, '/' )) == NULL ) {
dirname[ 0 ] = '.';
dirname[ 1 ] = '\0';
} else {
strncpy( dirname, edbfile, p - edbfile );
dirname[ p - edbfile ] = '\0';
}
/* load local ".add" file (if any) */
sprintf( filename, "%s/%s", dirname, ADDVALS_FILENAME );
addvals_len = 0;
addvals = read_file( filename, &addvals_len );
/* read and convert this EDB file */
if (( fp = fopen( edbfile, "r" )) == NULL ) {
print_err( edbfile );
if ( addvals != NULL ) {
free( addvals );
}
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 2 return( -1 )\n" );
}
#endif
return( -1 );
}
/* skip first two lines (type and timestamp) if they are present */
if ( fgets( line, MAX_LINE_SIZE, fp ) == NULL ) {
err = -1;
} else {
line[ strlen( line ) - 1 ] = '\0';
if ( strcmp( line, "MASTER" ) == 0 || strcmp( line, "SLAVE" ) == 0 ||
strcmp( line, "CACHE" ) == 0 ) {
if ( fgets( line, MAX_LINE_SIZE, fp ) == NULL ) {
err = -1;
}
} else {
rewind( fp );
}
}
if ( err != 0 ) {
fprintf( stderr, "%s: skipping empty EDB file %s\n", progname,
edbfile );
err = 0; /* treat as a non-fatal error */
} else {
while ( !feof( fp ) && ( err = convert_entry( fp, edbfile, outfp,
basedn, addvals, addvals_len, line )) > 0 ) {
if ( verboseflg && (( entrycount - startcount ) %
VERBOSE_ENTRY_REPORT_THRESHOLD ) == 0 ) {
fprintf( stderr, "\tworking... %d entries done...\n",
entrycount - startcount );
}
}
}
fclose( fp );
if ( addvals != NULL ) {
free( addvals );
}
if ( err < 0 ) {
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 3 return( %d )\n", err );
}
#endif
return( err );
}
if ( verboseflg ) {
fprintf( stderr, "\t%d entries converted\n\n",
entrycount - startcount );
}
/* optionally convert EDB file within sub-directories */
if ( recurse ) {
char *newbase;
DIR *dp;
struct dirent *dep;
struct edbmap *edbmap;
/* open this directory */
if (( dp = opendir( dirname )) == NULL ) {
print_err( dirname );
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 4 return( -1 )\n" );
}
#endif
return( -1 );
}
/* check for EDB.map file and record contents for future reference */
sprintf( filename, "%s/%s", dirname, EDBMAP_FILENAME );
if ( read_edbmap( filename, &edbmap ) < 0 ) {
print_err( "read_edbmap" );
closedir( dp );
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 5 return( -1 )\n" );
}
#endif
return( -1 );
}
p = dirname + strlen( dirname );
*p++ = '/';
*p = '\0';
/* scan looking for sub-directories w/EDB files in them */
err = 0;
while ( err >= 0 && ( dep = readdir( dp )) != NULL ) {
if ( dep->d_name[ 0 ] == '.' && ( dep->d_name[ 1 ] == '\0' ||
( dep->d_name[ 1 ] == '.' && dep->d_name[ 2 ] == '\0' ))) {
continue; /* skip "." and ".." */
}
strcpy( p, dep->d_name );
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: checking directory \"%s\"\n",
dirname );
}
#endif
if ( stat( dirname, &st ) != 0 ) {
print_err( dirname );
} else if ( S_ISDIR( st.st_mode )) {
sprintf( filename, "%s/%s", dirname, DEF_EDBFILENAME );
if ( stat( filename, &st ) == 0 && S_ISREG( st.st_mode )) {
if (( newbase = malloc( strlen( basedn ) +
strlen( dep->d_name ) + 3 )) == NULL ) {
print_err( "malloc" );
err = -1;
continue;
}
sprintf( newbase, "%s@%s", basedn,
file2rdn( edbmap, dep->d_name ));
/* recurse */
err = edb2ldif( outfp, filename, newbase, recurse );
free( newbase );
}
}
}
free_edbmap( edbmap );
closedir( dp );
if ( verboseflg ) {
fprintf( stderr, "%s: %d total entries converted under \"%s\"\n\n",
progname, entrycount - startcount, basedn );
}
}
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "edb2ldif: 6 return( %d )\n", err );
}
#endif
return( err );
}
/*
* read one entry from fp and write to outfp.
* return > 0 if entry converted, 0 if end of file, < 0 if error occurs
*/
static int
convert_entry(
FILE *fp,
char *edbname,
FILE *outfp,
char *basedn,
char *loc_addvals,
int loc_addlen,
char *linebuf
)
{
Attr_Sequence as, tmpas;
AV_Sequence av;
PS attrtype_ps, val_ps;
char *dnstr;
DN dn;
RDN rdn;
int valcnt;
extern int parse_status;
extern char *parse_file;
extern RDN parse_rdn;
#ifdef HAVE_PARSE_ENTRY
extern char *parse_entry;
extern Attr_Sequence fget_attributes();
#else /* HAVE_PARSE_ENTRY */
extern Attr_Sequence get_attributes();
#endif /* HAVE_PARSE_ENTRY */
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "convert_entry( 0x%X, \"%s\", 0x%X, \"%s\", ...)\n",
fp, edbname, outfp, basedn );
}
#endif
while (( dnstr = fgets( linebuf, MAX_LINE_SIZE, fp )) != NULL &&
*linebuf == '\n' ) {
;
}
if ( dnstr == NULL ) {
return( feof( fp ) ? 0 : -1 ); /* end of file or error */
}
linebuf[ strlen( linebuf ) - 1 ] = '\0';
if (( dnstr = malloc( strlen( basedn ) + strlen( linebuf ) + 2 ))
== NULL ) {
print_err( "convert_entry" );
return( -1 );
}
sprintf( dnstr, "%s@%s", basedn, linebuf );
if ( last_dn != NULL ) {
free( last_dn );
}
last_dn = dnstr;
if ( entrycount > 0 ) {
fputc( '\n', outfp );
}
/*
* parse_entry, parse_file and parse_rdn are needed inside the
* libisode decoding routines, so we set it here.
*/
parse_file = edbname;
#ifdef HAVE_PARSE_ENTRY
parse_entry = dnstr;
#endif
parse_rdn = rdn = str2rdn( linebuf );
if (( val_ps = ps_alloc( str_open )) == NULLPS ||
str_setup( val_ps, NULLCP, 0, 0 ) == NOTOK ) {
fprintf( stderr, "%s: ps_alloc/setup failed (EDB file %s)\n", progname,
edbname );
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
if (( dn = str2dn( dnstr )) == NULLDN || av2ldif( outfp, NULL, dn,
0, "dn", val_ps ) < 0 ) {
sprintf( linebuf,
"str2dn or av2ldif of DN failed (EDB file %s, entry %s)\n",
edbname, dnstr );
print_err( linebuf );
if ( dn != NULLDN ) {
dn_free( dn );
}
ps_free( val_ps );
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
dn_free( dn );
++entrycount;
if ( always_addvals != NULL && ( loc_addvals == NULL || !override_add )
&& fwrite( always_addvals, always_addlen, 1, outfp ) != 1 ) {
sprintf( linebuf,
"write of additional values failed (EDB file %s, entry %s)\n",
edbname, dnstr );
print_err( linebuf );
ps_free( val_ps );
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
if ( loc_addvals != NULL && fwrite( loc_addvals, loc_addlen, 1,
outfp ) != 1 ) {
sprintf( linebuf,
"write of additional values failed (EDB file %s, entry %s)\n",
edbname, dnstr );
print_err( linebuf );
ps_free( val_ps );
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
#ifdef HAVE_PARSE_ENTRY
as = fget_attributes( fp );
#else /* HAVE_PARSE_ENTRY */
as = get_attributes( fp );
#endif /* HAVE_PARSE_ENTRY */
if ( parse_status != 0 ) {
fprintf( stderr, "%s: problem parsing entry (EDB file %s)\n", progname,
edbname );
ps_free( val_ps );
if ( as != NULLATTR ) {
as_free( as );
}
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
if ( add_rdn_values( as, rdn ) != 0 ) {
sprintf( linebuf,
"adding RDN values(s) failed (EDB file %s, entry %s)\n",
edbname, dnstr );
print_err( linebuf );
if ( as != NULLATTR ) {
as_free( as );
}
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
if (( attrtype_ps = ps_alloc( str_open )) == NULLPS ||
str_setup( attrtype_ps, NULLCP, 0, 0 ) == NOTOK ) {
fprintf( stderr, "%s: ps_alloc/setup failed (EDB file %s)\n", progname,
edbname );
if ( as != NULLATTR ) {
as_free( as );
}
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
for ( tmpas = as; tmpas != NULLATTR; tmpas = tmpas->attr_link ) {
attrtype_ps->ps_ptr = attrtype_ps->ps_base;
AttrT_print( attrtype_ps, tmpas->attr_type, EDBOUT );
*attrtype_ps->ps_ptr = '\0';
if ( ignore_attr != NULL ) {
int i;
for ( i = 0; ignore_attr[ i ] != NULL; ++i ) {
if ( strcasecmp( attrtype_ps->ps_base, ignore_attr[ i ] )
== 0 ) {
break;
}
}
if ( ignore_attr[ i ] != NULL ) {
continue; /* skip this attribute */
}
}
valcnt = 0;
for ( av = tmpas->attr_value; av != NULLAV; av = av->avseq_next ) {
++valcnt;
if ( av2ldif( outfp, av, NULL, tmpas->attr_type->oa_syntax,
attrtype_ps->ps_base, val_ps ) < 0 ) {
sprintf( linebuf,
"av2ldif failed (EDB file %s, entry %s, attribute %s, value no. %d)\n",
edbname, dnstr, attrtype_ps->ps_base, valcnt );
print_err( linebuf );
ps_free( attrtype_ps );
ps_free( val_ps );
as_free( as );
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( -1 );
}
}
}
ps_free( attrtype_ps );
ps_free( val_ps );
as_free( as );
if ( rdn != NULLRDN ) {
rdn_free( rdn );
}
return( 1 );
}
static int
add_rdn_values( Attr_Sequence entryas, RDN rdn )
{
/*
* this routine is based on code from the real_unravel_attribute() routine
* found in isode-8.0/.dsap/common/attribute.c
*/
AttributeType at;
AV_Sequence avs;
Attr_Sequence as;
for (; rdn != NULLRDN; rdn = rdn->rdn_next ) {
if (( as = as_find_type( entryas, rdn->rdn_at )) == NULLATTR ) {
at = AttrT_cpy( rdn->rdn_at );
avs = avs_comp_new( AttrV_cpy(&rdn->rdn_av ));
as = as_comp_new( at, avs, NULLACL_INFO );
entryas = as_merge( entryas, as );
} else {
for ( avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next ) {
if ( AttrV_cmp( &rdn->rdn_av, &avs->avseq_av ) == 0 ) {
break;
}
}
if ( avs == NULLAV ) {
avs = avs_comp_new( AttrV_cpy( &rdn->rdn_av ));
as->attr_value = avs_merge( as->attr_value, avs );
}
}
}
return( 0 );
}
/* read the EDB.map file and return a linked list of translations */
static int
read_edbmap( char *mapfile, struct edbmap **edbmapp )
{
FILE *fp;
char *p, *filename, *rdn, line[ MAX_LINE_SIZE + 1 ];
int err;
struct edbmap *emp, *tmpemp;
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "read_edbmap( \"%s\", ...)\n", mapfile );
}
#endif
if (( fp = fopen( mapfile, "r" )) == NULL ) {
*edbmapp = NULL;
return( 0 ); /* soft error -- no EDB.map file */
}
emp = NULL;
/*
* read all the lines in the file, looking for lines of the form:
* RDN # filename
*/
err = 0;
while ( err == 0 && fgets( line, MAX_LINE_SIZE, fp ) != NULL ) {
line[ strlen( line ) - 1 ] = '\0'; /* remove trailing newline */
if (( filename = strchr( line, '#' )) == NULL ) {
continue;
}
*filename++ = '\0';
while ( isspace( *filename )) { /* strip leading whitespace */
++filename;
}
if ( *filename == '\0' ) {
continue;
}
p = filename + strlen( filename ) - 1;
while ( isspace( *p )) { /* strip trailing whitespace */
*p-- = '\0';
}
rdn = line;
while ( isspace( *rdn )) { /* strip leading whitespace */
++rdn;
}
if ( *rdn == '\0' ) {
continue;
}
p = rdn + strlen( rdn ) - 1;
while ( isspace( *p )) { /* strip trailing whitespace */
*p-- = '\0';
}
if (( tmpemp = (struct edbmap *)calloc( 1, sizeof( struct edbmap )))
== NULL ||
( tmpemp->edbm_filename = strdup( filename )) == NULL ||
( tmpemp->edbm_rdn = strdup( rdn )) == NULL ) {
err = -1;
} else {
tmpemp->edbm_next = emp;
emp = tmpemp;
}
}
fclose( fp );
if ( err == 0 ) {
*edbmapp = emp;
} else {
free_edbmap( emp );
}
return( err );
}
static char *
file2rdn( struct edbmap *edbmap, char *filename )
{
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "file2rdn( 0x%X, \"%s\" )\n", edbmap, filename );
}
#endif
while ( edbmap != NULL ) {
if ( strcmp( filename, edbmap->edbm_filename ) == 0 ) {
break;
}
edbmap = edbmap->edbm_next;
}
return(( edbmap == NULL ) ? filename : edbmap->edbm_rdn );
}
/* free the edbmap list */
static void
free_edbmap( struct edbmap *edbmap )
{
struct edbmap *tmp;
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "free_edbmap( 0x%X )\n", edbmap );
}
#endif
while ( edbmap != NULL ) {
if ( edbmap->edbm_filename != NULL ) free( edbmap->edbm_filename );
if ( edbmap->edbm_rdn != NULL ) free( edbmap->edbm_rdn );
tmp = edbmap;
edbmap = edbmap->edbm_next;
free( tmp );
}
}
static void
print_err( char *msg )
{
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "print_err( \"%s\" )\n", msg );
}
#endif
if ( errno > sys_nerr ) {
fprintf( stderr, "%s: %s: error %d\n", progname, msg, errno );
} else {
fprintf( stderr, "%s: %s: %s\n", progname, msg, sys_errlist[ errno ] );
}
}
static char *
read_file( char *filename, int *lenp )
{
FILE *fp;
struct stat st;
char *buf;
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "read_file( \"%s\", 0x%X )\n", filename, lenp );
}
#endif
if ( stat( filename, &st ) != 0 || !S_ISREG( st.st_mode ) ||
( fp = fopen( filename, "r" )) == NULL ) {
return( NULL );
}
if (( buf = (char *)malloc( st.st_size )) == NULL ) {
fclose( fp );
return( NULL );
}
if ( fread( buf, st.st_size, 1, fp ) != 1 ) {
fclose( fp );
free( buf );
return( NULL );
}
fclose( fp );
*lenp = st.st_size;
return( buf );
}