Exemplo n.º 1
0
/*==================================================
 * open_database -- open database
 *  forceopen:    [in] flag to override reader/writer protection
 *  dbpath:       [in] database path to open
 *================================================*/
BOOLEAN
open_database (INT alteration, STRING dbpath, INT *lldberr)
{
	LLDATABASE lldb = lldb_alloc();
	BOOLEAN rtn = FALSE;
	char fpath[MAXPATHLEN];

	/* tentatively copy paths into gedlib module versions */
	strupdate(&readpath_file, lastpathname(dbpath));
	llstrncpy(fpath, dbpath, sizeof(fpath), 0);
	expand_special_fname_chars(fpath, sizeof(fpath), uu8);
	strupdate(&readpath, fpath);

	if (f_dbnotify)
		(*f_dbnotify)(readpath, TRUE);

	rtn = open_database_impl(lldb, alteration, lldberr);
	if (!rtn) {
		/* open failed so clean up, preserve lldberr */
		int myerr = *lldberr;
		lldb_close(&lldb);
		*lldberr = myerr;
	}
	def_lldb = lldb;
	return rtn;
}
Exemplo n.º 2
0
/*======================================+
 * llrpt_newfile -- Switch output to new file
 * usage: newfile(STRING, BOOL) -> VOID
 *=====================================*/
PVALUE
llrpt_newfile (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	PNODE argvar = builtin_args(node);
	BOOLEAN aflag=FALSE;
	STRING name=0;
	PVALUE val = eval_and_coerce(PSTRING, argvar, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonstrx, "newfile", "1");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	name = pvalue_to_string(val);
	if (!name || !name[0]) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, val, "1st arg to newfile must be a nonempty string.");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	strupdate(&outfilename, name);
	delete_pvalue_ptr(&val);
	val = eval_and_coerce(PBOOL, argvar=inext(argvar), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonboox, "newfile", "2");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	aflag = pvalue_to_bool(val);
	delete_pvalue_ptr(&val);
	if (!set_output_file(outfilename, aflag)) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, NULL, "Failed to open output file: %s", outfilename);
	}
	return NULL;
}
Exemplo n.º 3
0
/*======================================+
 * start_output_file -- Start outputing to specified file
 *  (Closes any previously open output file)
 * Calls msg_error & returns FALSE, if problem
 *=====================================*/
BOOLEAN
start_output_file (STRING outfname)
{
	BOOLEAN append=FALSE;
	if (set_output_file(outfname, append)) {
		strupdate(&outfilename, outfname);
		return TRUE;
	} else {
		return FALSE;
	}
}
Exemplo n.º 4
0
/*==================================================
 * update_db_options --
 *  check database-specific options for updates
 *================================================*/
static void
update_db_options (void)
{
    TABLE opttab = create_table_str();
    CNSTRING str=0;
    get_db_options(opttab);

    str = valueof_str(opttab, "codeset");
    if (!str || !str[0]) {
        /*
        no specified database/internal codeset
        so default to user's default codeset, which
        should be from locale
        */
        str = get_defcodeset();
    }
    if (!int_codeset)
        strupdate(&int_codeset, "");
    if (!eqstr_ex(int_codeset, str)) {
        /* database encoding changed */
        strupdate(&int_codeset, str);

        /* Here is where the global uu8 variable is set
        This is a flag if the internal (database) encoding is UTF-8 */
        uu8 = is_codeset_utf8(int_codeset);

        /* always translate to internal codeset */
        set_gettext_codeset(PACKAGE, int_codeset);
        /* need to reload all predefined codeset conversions */
        transl_load_xlats();
        if (uu8) {
            charprops_load_utf8();
        } else {
            charprops_load(int_codeset);
        }
    }

    destroy_table(opttab);
}
Exemplo n.º 5
0
/*===================================================
 * update_useropts -- Set any global variables
 * dependent on user options
 *=================================================*/
void
update_useropts (VPTR uparm)
{
    uparm = uparm; /* unused */
    if (suppress_reload)
        return;
    /* deal with db-specific options */
    /* includes setting int_codeset */
    if (def_lldb)
        update_db_options();
    /* in case user changed any codesets */
    init_codesets();
    /* in case user changed locale (need int_codeset already set) */
    uilocale();
    /* in case user changed codesets */
    /* TODO: Isn't this superfluous, as it was called in update_db_options above ? */
    transl_load_xlats();

    strupdate(&illegal_char, getlloptstr("IllegalChar", 0));

    nodechk_enable(!!getlloptint("nodecheck", 0));
}
Exemplo n.º 6
0
static FILE *
ask_for_file_worker (STRING mode,
                     STRING ttl,
                     STRING *pfname,
                     STRING *pfullpath,
                     STRING path,
                     STRING ext,
                     DIRECTION direction)
{
	FILE *fp;
	char prompt[MAXPATHLEN];
	char fname[MAXPATHLEN];
	int elen, flen;
	BOOLEAN rtn;

	make_fname_prompt(prompt, sizeof(prompt), ext);

	if (direction==INPUT)
		rtn = ask_for_input_filename(ttl, path, prompt, fname, sizeof(fname));
	else
		rtn = ask_for_output_filename(ttl, path, prompt, fname, sizeof(fname));
	
	if (pfname) {
		if (fname && fname[0])
			*pfname = strdup(fname);
		else
			*pfname = 0;
	}
	if (pfullpath) *pfullpath = 0; /* 0 indicates we didn't try to open */

	if (!rtn || !fname[0]) return NULL;

	if (!expand_special_fname_chars(fname, sizeof(fname), uu8)) {
		msg_error(_(qSfn2long));
		return NULL;
	}

ask_for_file_try:

	/* try name as given */
	if (ISNULL(path)) {
		/* bare filename was given */
		if ((fp = fopen(fname, mode)) != NULL) {
			if (pfname)
				strupdate(pfname, fname);
			return fp;
		}
	} else {
		/* fully qualified path was given */
		if ((fp = fopenpath(fname, mode, path, ext, uu8, pfullpath)) != NULL) {
			return fp;
		}
	}

	/* try default extension */
	if (ext) {
		elen = strlen(ext);
		flen = strlen(fname);
		if (elen<flen && path_match(fname+flen-elen, ext)) {
			ext = NULL;	/* the file name has the extension already */
		} else {
			/* add extension and go back and retry */
			llstrapps(fname, sizeof(fname), uu8, ext);
			ext = NULL; /* only append extension once! */
			goto ask_for_file_try;
		}
	}

	/* failed to open it, give up */
	msg_error(_(qSnofopn), fname);
	return NULL;
}
Exemplo n.º 7
0
/*==================================
 * main -- Main routine of LifeLines
 *================================*/
int
main (int argc, char **argv)
{
	extern char *optarg;
	extern int optind;
	char * msg;
	int c;
	BOOLEAN ok=FALSE;
	STRING dbrequested=NULL; /* database (path) requested */
	STRING dbused=NULL; /* database (path) found */
	BOOLEAN forceopen=FALSE, lockchange=FALSE;
	char lockarg = 0; /* option passed for database lock */
	INT alteration=0;
	LIST exprogs=NULL;
	TABLE exargs=NULL;
	STRING progout=NULL;
	BOOLEAN graphical=TRUE;
	STRING configfile=0;
	STRING crashlog=0;
	int i=0;

	/* initialize all the low-level library code */
	init_stdlib();

#if HAVE_SETLOCALE
	/* initialize locales */
	setlocale(LC_ALL, "");
#endif /* HAVE_SETLOCALE */
	
	/* capture user's default codeset */
	ext_codeset = strsave(ll_langinfo());
	/* TODO: We can use this info for default conversions */

#if ENABLE_NLS
	/* setup gettext translation */
	ll_bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
#endif

	save_original_locales();
	load_usage();

	/* handle conventional arguments --version and --help */
	/* needed for help2man to synthesize manual pages */
	for (i=1; i<argc; ++i) {
		if (!strcmp(argv[i], "--version")
			|| !strcmp(argv[i], "-v")) {
			print_version("llexec");
			return 0;
		}
		if (!strcmp(argv[i], "--help")
			|| !strcmp(argv[i], "-h")
			|| !strcmp(argv[i], "-?")) {
			print_usage();
			return 0;
		}
	}

	/* Parse Command-Line Arguments */
	opterr = 0;	/* turn off getopt's error message */
	while ((c = getopt(argc, argv, "adkrwil:fntc:Fu:x:o:zC:I:vh?")) != -1) {
		switch (c) {
		case 'c':	/* adjust cache sizes */
			while(optarg && *optarg) {
				if(isasciiletter((uchar)*optarg) && isupper((uchar)*optarg))
					*optarg = tolower((uchar)*optarg);
				if(*optarg == 'i') {
					INT icsz_indi=0;
					sscanf(optarg+1, "%ld,%ld", &csz_indi, &icsz_indi);
				}
				else if(*optarg == 'f') {
					INT icsz_fam=0;
					sscanf(optarg+1, "%ld,%ld", &csz_fam, &icsz_fam);
				}
				else if(*optarg == 's') {
					INT icsz_sour=0;
					sscanf(optarg+1, "%ld,%ld", &csz_sour, &icsz_sour);
				}
				else if(*optarg == 'e') {
					INT icsz_even=0;
					sscanf(optarg+1, "%ld,%ld", &csz_even, &icsz_even);
				}
				else if((*optarg == 'o') || (*optarg == 'x')) {
					INT icsz_othr=0;
					sscanf(optarg+1, "%ld,%ld", &csz_othr, &icsz_othr);
				}
				optarg++;
				while(*optarg && isdigit((uchar)*optarg)) optarg++;
				if(*optarg == ',') optarg++;
				while(*optarg && isdigit((uchar)*optarg)) optarg++;
			}
			break;
#ifdef FINNISH
# ifdef FINNISHOPTION
		case 'F':	/* Finnish sorting order [toggle] */
			opt_finnish = !opt_finnish;
			/*
			TO DO - need to mark Finnish databases, as 
			name records are not interoperable, because of
			different soundex encoding
			2001/02/17, Perry Rapp
			*/
			break;
# endif
#endif
		case 'a':	/* debug allocation */
			alloclog = TRUE;
			break;
		case 'd':	/* debug = no signal catchers */
			debugmode = TRUE;
			break;
		case 'k':	/* don't show key values */
			keyflag = FALSE;
			break;
		case 'r':	/* request for read only access */
			readonly = TRUE;
			break;
		case 'w':	/* request for write access */
			writeable = TRUE;
			break;
		case 'i': /* immutable access */
			immutable = TRUE;
			readonly = TRUE;
			break;
		case 'l': /* locking switch */
			lockchange = TRUE;
			lockarg = *optarg;
			break;
		case 'f':	/* force database open in all cases */
			forceopen = TRUE;
			break;
		case 'n':	/* use non-traditional family rules */
			traditional = FALSE;
			break;
		case 't': /* show lots of trace statements for debugging */
			prog_trace = TRUE;
			break;
		case 'x': /* execute program */
			if (!exprogs) {
				exprogs = create_list2(LISTDOFREE);
			}
			push_list(exprogs, strdup(optarg ? optarg : ""));
			break;
		case 'I': /* program arguments */
			{
				STRING optname=0, optval=0;
				parse_arg(optarg, &optname, &optval);
				if (optname && optval) {
					if (!exargs) {
						exargs = create_table_str();
					}
					insert_table_str(exargs, optname, optval);
				}
				strfree(&optname);
				strfree(&optval);
			}
			break;
		case 'o': /* output directory */
			progout = optarg;
			break;
		case 'z': /* nongraphical box */
			graphical = FALSE;
			break;
		case 'C': /* specify config file */
			configfile = optarg;
			break;
		case 'v': /* show version */
			showversion = TRUE;
			goto usage;
			break;
		case 'h': /* show usage */
		case '?': /* show usage */
			showversion = TRUE;
			showusage = TRUE;
			goto usage;
			break;
		}
	}

prompt_for_db:

	/* catch any fault, so we can close database */
	if (debugmode)
		stdstring_hardfail();
	else
		set_signals();

	platform_init();
	set_displaykeys(keyflag);
	/* initialize options & misc. stuff */
	llgettext_set_default_localedir(LOCALEDIR);
	if (!init_lifelines_global(configfile, &msg, &main_db_notify)) {
		llwprintf("%s", msg);
		goto finish;
	}
	/* setup crashlog in case init_screen fails (eg, bad menu shortcuts) */
	crashlog = getlloptstr("CrashLog_llexec", NULL);
	if (!crashlog) { crashlog = "Crashlog_llexec.log"; }
	crash_setcrashlog(crashlog);
	init_interpreter(); /* give interpreter its turn at initialization */

	/* Validate Command-Line Arguments */
	if ((readonly || immutable) && writeable) {
		llwprintf(_(qSnorwandro));
		goto finish;
	}
	if (forceopen && lockchange) {
		llwprintf(_(qSnofandl));
		goto finish;
	}
	if (lockchange && lockarg != 'y' && lockarg != 'n') {
		llwprintf(_(qSbdlkar));
		goto finish;
	}
	if (forceopen)
		alteration = 3;
	else if (lockchange) {
		if (lockarg == 'y')
			alteration = 2;
		else
			alteration = 1;
	}
	c = argc - optind;
	if (c > 1) {
		showusage = TRUE;
		goto usage;
	}

	/* Open database, prompting user if necessary */
	if (1) {
		STRING errmsg=0;
		if (!alldone && c>0) {
			dbrequested = strsave(argv[optind]);
		} else {
			strupdate(&dbrequested, "");
		}
		if (!select_database(dbrequested, alteration, &errmsg)) {
			if (errmsg) {
				llwprintf(errmsg);
			}
			alldone = 0;
			goto finish;
		}
	}

	/* Start Program */
	if (!init_lifelines_postdb()) {
		llwprintf(_(qSbaddb));
		goto finish;
	}
	/* does not use show module */
	/* does not use browse module */
	if (exargs) {
		set_cmd_options(exargs);
		release_table(exargs);
		exargs = 0;
	}
	if (exprogs) {
		BOOLEAN picklist = FALSE;
		BOOLEAN timing = FALSE;
		interp_main(exprogs, progout, picklist, timing);
		destroy_list(exprogs);
	} else {
		/* TODO: prompt for report filename */
	}
	/* does not use show module */
	/* does not use browse module */
	ok=TRUE;

finish:
	/* we free this not because we care so much about these tiny amounts
	of memory, but to ensure we have the memory management right */
	/* strfree frees memory & nulls pointer */
	if (dbused) strfree(&dbused);
	strfree(&dbrequested);
	strfree(&readpath_file);
	shutdown_interpreter();
	close_lifelines();
	shutdown_ui(!ok);
	if (alldone == 2)
		goto prompt_for_db; /* changing databases */
	termlocale();
	strfree(&ext_codeset);

usage:
	/* Display Version and/or Command-Line Usage Help */
	if (showversion) { print_version("llexec"); }
	if (showusage) puts(usage_summary);

	/* Exit */
	return !ok;
}
Exemplo n.º 8
0
Arquivo: dnpsp.c Projeto: hoytech/npsp
/**==========================================================================**\
 **	M A IN
\**==========================================================================**/
int	main
	(
	int argc,
	char *argv[]
	)
	{
	param_t	param	;
	npc_t	*npc	= NULL ;

	ProgramName	= *argv++ ; --argc ;
	param_default( &param );

	while( argv[0] && argv[1] && argv[0][0]=='-' )
		{
		switch( argv[0][1] )
			{
		case 'n': param.seedNumber= argv[1];  break;
		case 'm': param.maxDigits = atoi( argv[1] ); break;
		case 'b': param.baseNumber= atoi( argv[1] ); break;
		case 'a': param.savePeriod= atoi( argv[1] ); break;
		case 'i': strupdate(&(param.loadFile), argv[1] ); break;
		case 'o': strupdate(&(param.saveFile), argv[1] ); break;

		case 'v': param.help |= PARAM_VERSION ;
			  param_usage( &param ) ;

		default	: fprintf( stderr, "unknown option: '%c'\n" );
			  param_usage( &param );
			}
		param.numParams ++ ;
		argc -= 2 ;
		argv += 2 ;
		}

	param_verify( &param );

	if( (npc = npc_new( param.maxDigits )) == NULL )
		{
		fprintf( stderr, "err npc_new\n" );
		return( 0 );
		}
	npc->base = param.baseNumber ;

	if( param.loadFile )
		{
		if( !npc_loadFile( npc, param.loadFile ) )
			return( 0 );
		}
	else
		{
        	if( !npc_string_ingest( npc, param.seedNumber ) )
			{
			fprintf( stderr, "err loading seedNumber\n" );
			return( 0 );
			}
		else
			npc->origSeed =	atoi( param.seedNumber ) ;
		}

	copywrite() ;

	npc_loop( npc ) ;

	printf(	"\n"
		"Progress: %%%6.2f Digits: %7d Its: %8d Secs: %6u\n"
		, 100. * npc->numDigits / npc->maxDigits
		, npc->numDigits
		, npc->iterates
		, npc->timeMark - npc->timeInit
		) ;

	if( param.saveFile )
		npc_saveFile( npc, param.saveFile ) ;

	return 0;
	}
Exemplo n.º 9
0
/*=================================================
 * do_import -- Read GEDCOM file to database
 *  ifeed: [IN]  output methods
 *  fp:    [I/O] GEDCOM file whence to load data
 *===============================================*/
static BOOLEAN
do_import (IMPORT_FEEDBACK ifeed, FILE *fp)
{
	NODE node, conv;
	XLAT ttm = 0;
	STRING msg;
	BOOLEAN emp;
	INT nindi = 0, nfam = 0, neven = 0;
	INT nsour = 0, nothr = 0, type, num = 0;
	INT totkeys = 0, totused = 0;
	char msgbuf[80];
	BOOLEAN succeeded=FALSE;
	STRING str,unistr=0;
	ZSTR zerr=0;
	TABLE metadatatab = create_table_str();
	STRING gdcodeset=0;
	INT warnings=0;

	/* start by assuming default */
	strupdate(&gdcodeset, gedcom_codeset_in);

/*	rptui_init(); *//* clear ui time counter */

/* Open and validate GEDCOM file */
	if ((unistr=check_file_for_unicode(fp)) && !eqstr(unistr, "UTF-8")) {
		msg_error(_(qSunsupuniv), unistr);
		goto end_import;
	}
	if (eqstr_ex(unistr, "UTF-8")) {
		strupdate(&gdcodeset, "UTF-8");
	}

	if (!scan_header(fp, metadatatab, &zerr)) {
		msg_error(zs_str(zerr));
		goto end_import;
	}

	if ((str = valueof_str(metadatatab, "GEDC.FORM"))!= NULL) {
		if (!eqstr(str, "LINEAGE-LINKED")) {
			if (!ask_yes_or_no_msg(
				_("This is not a lineage linked GEDCOM file.")
				, _("Proceed anyway?")
				))
				goto end_import;
		}
	}
	if (!unistr && (str = valueof_str(metadatatab, "CHAR"))!= NULL) {
		/* if no BOM, use file's declared encoding if present */
		strupdate(&gdcodeset, str);
	}

	/* TODO: Push this codeset question down to after the validation, where we can know if
	the incoming file happened to really be all ASCII */

	if (!int_codeset[0]) {
		/* TODO: ask if user would like to adopt codeset of incoming file, if we found it */
		if (!ask_yes_or_no_msg(
			_("No current internal codeset, so no codeset conversion can be done")
			, _("Proceed without codeset conversion?")
			))
			goto end_import;
	}

	/* Warn if lossy code conversion likely */
	if (gdcodeset[0] && int_codeset[0]) {
		if (is_lossy_conversion(gdcodeset, int_codeset)) {
			ZSTR zstr=zs_new();
			zs_setf(zstr, _("Lossy codeset conversion (from <%s> to <%s>) likely")
				, gdcodeset, int_codeset);
			if (!ask_yes_or_no_msg(
				zs_str(zstr)
				, _("Proceed anyway?")
				))
				goto end_import;
		}
	}

	/* validate */
	if (ifeed && ifeed->validating_fnc)
		(*ifeed->validating_fnc)();

	if (!validate_gedcom(ifeed, fp)) {
		if (ifeed && ifeed->error_invalid_fnc)
			(*ifeed->error_invalid_fnc)(_(qSgdnadd));
		goto end_import;
	}
	warnings = validate_get_warning_count();
	if (warnings) {
		ZSTR zstr=zs_new();
		zs_setf(zstr, _pl("%d warning during import",
			"%d warnings during import", warnings), warnings);
		if (!ask_yes_or_no_msg(zs_str(zstr), _(qSproceed))) {
			goto end_import;
		}
	}

	if (gdcodeset[0] && int_codeset[0]) {
retry_input_codeset:
		ttm = transl_get_xlat(gdcodeset, int_codeset);
		if (!transl_is_xlat_valid(ttm)) {
			ZSTR zstr=zs_new();
			char csname[64];
			BOOLEAN b;
			transl_release_xlat(ttm);
			ttm = 0;
			zs_setf(zstr, _("Cannot convert codeset (from <%s> to <%s>)")
				, gdcodeset, int_codeset);
			b = ask_for_string(zs_str(zstr)
				, _("Enter codeset to assume (* for none)")
				, csname, sizeof(csname)) && csname[0];
			zs_free(&zstr);
			if (!b)
				goto end_import;
			if (!eqstr(csname, "*")) {
				strupdate(&gdcodeset, csname);
				goto retry_input_codeset;
			}
		}
	}
	
	if((num_indis() > 0)
		|| (num_fams() > 0)
		|| (num_sours() > 0)
		|| (num_evens() > 0)
		|| (num_othrs() > 0)) gd_reuse = FALSE;
	else if((gd_reuse = check_stdkeys())) {
		totused = gd_itot + gd_ftot + gd_stot + gd_etot + gd_xtot;
		totkeys = gd_imax + gd_fmax + gd_smax + gd_emax + gd_xmax;
		if((totkeys-totused) > 0) {
			INT delkeys = totkeys-totused;
			snprintf(msgbuf, sizeof(msgbuf)
				, _pl("Using original keys, %d deleted record will be in the database."
					, "Using original keys, %d deleted records will be in the database."
					, delkeys)
				, delkeys
				);
		}
		else strcpy(msgbuf, " ");
		gd_reuse = ask_yes_or_no_msg(msgbuf, _(qScfoldk));
/*
TODO: why were these here ?
		touchwin(uiw_win(stdout_win));
		wrefresh(uiw_win(stdout_win));
*/
	}

	/* start loading the file */
	rewind(fp);

	/* test for read-only database here */

	if(readonly) {
		if (ifeed && ifeed->error_readonly_fnc)
			(*ifeed->error_readonly_fnc)();
		goto end_import;
	}

	/* tell user we are beginning real part of import */
	if (ifeed && ifeed->beginning_import_fnc) {
		if(gd_reuse)
			(*ifeed->beginning_import_fnc)(_(qSdboldk));
		else
			(*ifeed->beginning_import_fnc)(_(qSdbnewk));
	}


/* Add records to database */
	node = convert_first_fp_to_node(fp, FALSE, ttm, &msg, &emp);
	while (node) {
		if (!(conv = node_to_node(node, &type))) {
			free_nodes(node);
			node = next_fp_to_node(fp, FALSE, ttm, &msg, &emp);
			continue;
		}
		switch (type) {
		case INDI_REC: num = ++nindi; break;
		case FAM_REC:  num = ++nfam;  break;
		case EVEN_REC: num = ++neven; break;
		case SOUR_REC: num = ++nsour; break;
		case OTHR_REC: num = ++nothr; break;
		default: FATAL();
		}
		restore_record(conv, type, num);
		if (ifeed && ifeed->added_rec_fnc)
			ifeed->added_rec_fnc(nxref(conv)[1], ntag(conv), num);
		free_nodes(node);
		node = next_fp_to_node(fp, FALSE, ttm, &msg, &emp);
	}
	if (msg) {
		msg_error(msg);
	}
	if(gd_reuse && ((totkeys - totused) > 0)) {
		if (ifeed && ifeed->adding_unused_keys_fnc)
			(*ifeed->adding_unused_keys_fnc)();
		addmissingkeys(INDI_REC);
		addmissingkeys(FAM_REC);
		addmissingkeys(EVEN_REC);
		addmissingkeys(SOUR_REC);
		addmissingkeys(OTHR_REC);
	}
	succeeded = TRUE;

end_import:
	validate_end_import();
	zs_free(&zerr);
	destroy_table(metadatatab);
	strfree(&gdcodeset);
	return succeeded;
}