DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦353213165⟧ TextFile

    Length: 13851 (0x361b)
    Types: TextFile
    Names: »dbmbuild.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Tools/dbmbuild/dbmbuild.c« 

TextFile

/* dbmbuild: build the database of information */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Tools/dbmbuild/RCS/dbmbuild.c,v 5.0 90/09/20 16:26:01 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Tools/dbmbuild/RCS/dbmbuild.c,v 5.0 90/09/20 16:26:01 pp Exp Locker: pp $
 *
 * $Log:	dbmbuild.c,v $
 * Revision 5.0  90/09/20  16:26:01  pp
 * rcsforce : 5.0 public release
 * 
 */



/* ---------------------------------------------------------------------------


	Database builder for PP address database

	Command line:
		dbmbuild [-flags] [outfile]

		where flags are:
		d   -   debugging output
		v   -   verbose output
		k   -   keep going if a table is missing
		n   -   don't make a new database file

	output-file is name of EXISTING dbm file to insert entires.
	Note it is two files, an output-file.dir and an output-file.pag.

--------------------------------------------------------------------------- */


#include        "head.h"
#include        "util.h"
#include        "chan.h"
#include        "dbase.h"
#include        <sys/file.h>
#include        <varargs.h>

extern Table    *tb_all[];  /* -- order tables searched -- */
extern CHAN     *ch_all[];  /* -- order chans searched -- */
extern int      errno;
extern char     *tbldfldir,
		*ppdbm;

#ifdef GDBM
GDBM_FILE	*thedb;
#define store(x,y)	gdbm_store (thedb, x, y, GDBM_REPLACE)
#define fetch(x)	gdbm_fetch (thedb, x)
#else
#if sparc && defined(__GNUC__)	/* work around bug in gcc 1.37 sparc version */
 #error GCC and dbm do not get along on a sparc - compile with cc.
#endif
#endif

#ifdef NDBM
DBM             *thedb;
#define         store(x,y)      dbm_store (thedb, (x), (y), DBM_REPLACE)
#define         fetch(x)        dbm_fetch (thedb, (x))
#endif


int             error,
		Debug,
		Verbose,
		newflag = 1,
		keepgoing;

char            dbfile [128],
		*dblock;

static char *myname;
static short    tb_nopen;   /* -- no of opened file descriptors -- */
void    adios (), advise ();

static int theinit (), theend ();
static int dbfinit (), dbfclose ();
static int process ();
static int install ();
static int prdatum ();
static int check ();
static int tb_open (), tb_close (), tb_free ();
static void cleanup ();

/* ---------------------  Begin  Routines  -------------------------------- */


/*
Process arguments, set flags and invoke file processing.
then clean up and exit properly.
*/


main (argc, argv)
char                    **argv;
{
	register Table      *tp;
	char                *p,
	*outfile = NULLCP;
	int                 ind;
	int		opt;
	extern char *optarg;
	extern int optind;

	myname = argv[0];
	sys_init (myname);

	while ((opt = getopt (argc, argv, "dknv")) != EOF) {
		switch (opt) {
		    case 'd':
			Debug++;
			break;
		    case 'k':
			keepgoing++;
			break;
		    case 'n':
			newflag = 0;
			break;
		    case 'v':
			Verbose++;
			break;
		    default:
			adios (NULLCP, "Usage: %s [-vnkd] [database]", myname);
		}
	}

	if (optind < argc)
		optarg = argv[optind++];

	/* -- use default database -- */

	if (outfile == NULLCP) {
		if (!isstr (ppdbm)) {
			adios (NULLCP,
			       "no default data base, in 'ppdbm' variable");
		}
		outfile = ppdbm;
	}


	/* -- check for existence first -- */

	error = 0;

	if (optind >= argc) {

		for (ind = 0; ch_all[ind] != NULLCHAN; ind++) {
			if (ch_all[ind] -> ch_table != NULLTBL)
				error += check (ch_all[ind] -> ch_table);

			if (Debug)
				fprintf (stderr, "ch_show = '%s' - %d\n",
					 ch_all[ind] -> ch_show, error);
		}


		for (ind = 0; (tp = tb_all[ind]) != NULLTBL; ind++) {
			error += check (tp);
			if (Debug)
				fprintf (stderr, "tb_show = '%s' - %d\n",
					 tp -> tb_show, error);
		}
	}
	else {
		int	ac = optind;
		while (ac < argc) {
			if ((tp = tb_nm2struct (argv[ac++])) == NULLTBL) {
				advise (NULLCP, "Table '%s' is unknown",
					argv[ac - 1]);
				error++;
			}
			error += check (tp);
		}
	}

	if (error)
		adios (NULLCP, "Some tables are missing.  dbmbuild aborted.");

	getfpath (tbldfldir, outfile, dbfile);

	if (Verbose || Debug) 
		fprintf (stderr, 
"database info:\n\ttables from %s\n\tdatabase = %s{.dir,.pag}\n\tpath = %s\n",
			 tbldfldir, outfile, dbfile);

	dblock = multcat (dbfile, ".lck", NULLCP);

	(void) close (creat (dblock, 0444 ));

	if (!theinit (newflag))
		cleanup (NOTOK);

	if (optind >= argc) {

		/* -- process for real! -- */

		for (ind = 0; ch_all[ind] != NULLCHAN; ind++)
			process (ch_all[ind] -> ch_table);


		for (ind = 0; (tp = tb_all[ind]) != NULLTBL; ind++) {

			/* -- in case table used by chan -- */

			if (tp -> tb_fp != (FILE *)EOF) {
				if (Debug)
					fprintf (stderr, "Table '%s'\n", tp -> tb_name);
				process (tp);
			}
		}

	}
	else
		while (optind < argc) {

			if ((tp = tb_nm2struct (argv[optind++])) == NULLTBL) {
				(void) fflush (stdout);
				adios (NULLCP, "Table '%s' is unknown",
				       argv[optind-1]);
			}
			process (tp);
		}

	cleanup (theend (newflag));
}


/* ---------------------  Static  Routines  ------------------------------- */




static int theinit (new)   /* -- initialize the dbm files -- */
int             new;
{
    char        tmpfile [100];


    /* -- start with fresh files -- */

    if (new) {
	if (Verbose || Debug)
	    fprintf (stderr, "Temporary database:  %s$\n", dbfile);

	(void) sprintf (tmpfile, "%s$.pag", dbfile);

	if (Debug)
	    fprintf (stderr, "creating '%s'\n", tmpfile);


	if (close (creat (tmpfile, 0644)) < 0)
	    adios (tmpfile, "could not creat");

	(void) chmod (tmpfile, 0644);   /* -- in case umask screwed us -- */

	(void) sprintf (tmpfile, "%s$.dir", dbfile);

	if (Debug)
	    fprintf (stderr, "creating '%s'\n", tmpfile);


	/* -- create and/or zero the file -- */

	if (close (creat (tmpfile, 0644)) < 0)
	    adios (tmpfile, "could not creat");

	(void) chmod (tmpfile, 0644);   /* -- in case umask screwed us -- */

	(void) sprintf (tmpfile, "%s$", dbfile);

	return (dbfinit (tmpfile));
    }

    return (dbfinit (dbfile));
}




static theend (new)               /* cleanup the dbm files */
int             new;
{
    char        fromfile [100],
		tofile [100];


    dbfclose();

    /* -- started with fresh files -- */

    if (new) {
	if (Verbose || Debug)
	    fprintf (stderr, "Moving to database:  %s\n", dbfile);

	(void) sprintf (fromfile, "%s$.pag", dbfile);

	(void) sprintf (tofile, "%s.pag", dbfile);

	if (Debug)
	    fprintf (stderr, "moving '%s'\n", fromfile);

	(void) unlink (tofile);

	/* -- create and/or zero the file -- */

	if (link (fromfile, tofile ) < 0 ||
		unlink (fromfile) < 0) {
			adios (tofile, "could not link to");
	}

	(void) sprintf (fromfile, "%s$.dir", dbfile);

	(void) sprintf (tofile, "%s.dir", dbfile);

	if (Debug)
	    fprintf (stderr, "moving '%s'\n", fromfile);

	(void) unlink (tofile);

	/* -- create and/or zero the file -- */

	if (link (fromfile, tofile ) < 0 ||
		unlink (fromfile) < 0) {
			adios (tofile, "could not link to ");
	}

	return (TRUE);
    }

    return (TRUE);
}




/*
Initialize the dbm file. Fetch the local name datum
Init to 1 and store it if there is no datum by that name.
*/

static dbfinit (filename)
char    *filename;
{
#ifdef GDBM
	if ((thedb = gdbm_open (filename, 0, GDBM_NEWDB, 0666, NULL)) == NULL)
#else
#ifdef NDBM
	if ((thedb = dbm_open (filename, O_CREAT|O_RDWR, 0666)) == NULL)
#else
	if (dbminit (filename) < 0)
#endif
#endif
	    adios (filename, "could not initialize data base");
	return (1);
}




/*
Close the dbm datafile.
Can't close the file because the library does not provide the call...
*/

static dbfclose()
{
#ifdef NDBM
	dbm_close (thedb);
#endif
#ifdef GDBM
	gdbm_close (thedb);
#endif
}




/*
Process a sequential file and insert items into the database
Opens argument assumes database is initialized.
*/

static process (tp)
Table           *tp;
{
    datum       key,
		value;
    char        tbkey [LINESIZE],
		tbvalue [LINESIZE],
		*cp;
    int status;

    if (tp == NULLTBL)
	return;

    if (Verbose || Debug)
	fprintf (stderr, tp -> tb_fp == (FILE *)EOF ?
			"%s (%s) already done\n" : "%s (%s)\n",
			tp -> tb_show, tp -> tb_name);

    if (tp -> tb_fp == (FILE *)EOF)
	return;


    /* -- gain access to a channel table -- */

    if (!tb_open (tp)) {
	fprintf (stderr, "could not open table \"%s\" (%s, file = '%s'):\n\t",
			tp -> tb_show, tp -> tb_name,
			tp -> tb_file);
	perror ("");

	/* -- don't try again -- */
	tp -> tb_fp = (FILE *)EOF;

	if (keepgoing)
	    return;
	cleanup (NOTOK);
    }


    tbkey[0] = tbvalue[0] = '\0';
    while ((status = tab_fetch (tp -> tb_fp, tbkey, tbvalue)) != DONE) {

	if (status == NOTOK) {
		if (!keepgoing)
			adios (NULLCP, "Bad record in file %s (last was %s:%s)",
				 tp -> tb_name, tbkey, tbvalue);
		advise (NULLCP, "Bad record in file %s (last was %s:%s)", 
				tp -> tb_name, tbkey, tbvalue);
		continue;
	}

	value.dptr = tbvalue;
	value.dsize = strlen (tbvalue) + 1;

	/* -- all keys are lower case -- */
	for (cp = tbkey; *cp != 0; cp++)
	    *cp = uptolow (*cp);

	key.dptr = tbkey;
	key.dsize = strlen (tbkey) + 1;

	if (Debug)
	    fprintf (stderr, " (%d)'%s': (%d)'%s'\n",
		     key.dsize, key.dptr, value.dsize, value.dptr);

	install (key, value, tp -> tb_name);
    }

    if (ferror (tp -> tb_fp))
	advise ("", "i/o error with table %s (%s, file = %s)",
			    tp -> tb_show, tp -> tb_name,
			    tp -> tb_file);

    (void) tb_close (tp);

    /* -- don't try again -- */
    tp -> tb_fp = (FILE *)EOF;
}




/*
Install a datum into the database.
Fetch entry first to see if we have to append name for building entry.
*/

static install (key, value, tbname)
datum           key,
		value;
char            tbname[];
{
    datum       old;
    char        newentry [ENTRYSIZE],
		*p,
		*q;

    p = newentry;

    old = fetch (key);

    if (old.dptr != NULLCP) {
	if (Debug) {
	    fprintf (stderr, "\tFound old entry\n\t");
	    prdatum (old);
	}
	for (p = newentry, q = old.dptr ; *p++ = *q++;);
	*(p-1) = FS;
    }
    else
	*p = '\0';

    (void) sprintf (p, "%s %s", tbname, value.dptr);

    old.dptr = newentry;
    old.dsize = strlen (newentry)+1;

    if (Debug) {
	fprintf (stderr, "\tNew datum\n\t");
	prdatum (old);
    }


    /* -- put the datum back -- */

    if (store (key, old) < 0) {
	advise ("",
		"store failed; key='%s'", key.dptr);
	prdatum (old);
	cleanup (NOTOK);
    }

}




/*
Print a datum.
Takes the datum arg & prints it so it can be read as either a key or entry.
*/

static prdatum (value)
datum           value;
{
	int     cnt;
	char    data [512];

	(void) strcpy (data, value.dptr);

	for (cnt = 0; cnt < value.dsize; cnt++) {
		if (value.dptr [cnt] >= ' ' && value.dptr [cnt] <= '~')
			putc (value.dptr [cnt], stderr);
		else
			fprintf (stderr, "<\\%03o>", value.dptr [cnt]);
	}

	putc ('\n', stderr);
}




static check (tp)
Table   *tp;
{

    /* -- its bad -- */
    if (tp == NULLTBL) {
	if (Debug)
		fprintf (stderr, "check's tp is NULL\n");
	return (1);
    }

    if (tp->tb_fp == (FILE *)EOF) {
	if (Debug)
		fprintf (stderr, "check's tp has a EOF FILE \n");
	return (1);
    }

    /* -- gain access to a channel table -- */
    if (!tb_open (tp)) {
	advise ("", "could not open table \"%s\" (%s, file = '%s')",
		tp -> tb_show, tp -> tb_name, tp -> tb_file);
	tp -> tb_fp = (FILE *)EOF;
	return (1);
    }

    (void) tb_close (tp);
    tp -> tb_fp = NULLFILE;
    return (0);
}




static void 	cleanup (exitval)
int     exitval;
{
	exit (exitval == TRUE? 0 : 1);  /* TRUE is non-zero */
}

/* -------------  Basic  File  Action  ------------------------------------ */

static tb_open (tp)
register Table  *tp;   /* -- table's state information -- */
{
    char        temppath [128];


    /*
    currently, there is one file (descriptor) per table.  for a large
    configuration, you will run out of fd's.  until/unless you run
    a single-file dbm-based version, there is a hack, below, which
    limits the number of open file-descriptors to 6.  Trying to open
    a 7th will cause a currently-opened one to be closed.
    */

    if (tp == NULLTBL) {
	if (Debug)
		fprintf (stderr, "tb_open's table is NULL\n");
	return (FALSE);
    }

    if (tb_nopen < 6 || tb_free()) {

	getfpath (tbldfldir, tp -> tb_file, temppath);

	/* -- add on directory portion -- */
	if ((tp -> tb_fp = fopen (temppath, "r")) != NULLFILE) {
		tb_nopen++;
		return (TRUE);
	}
    }

    printf ("cannot open %s\n", temppath);

    return (FALSE);
}




static tb_close (tp)
register Table  *tp;
{
	if (tp -> tb_fp == (FILE *)NOTOK || tp -> tb_fp == NULLFILE)
		return (FALSE);

	(void) fclose (tp -> tb_fp);

	/* -- mark as free -- */
	tp -> tb_fp = 0;

	tb_nopen--;

	return (TRUE);
}




static tb_free()   /* -- create a free file descriptor -- */
{
    register Table      **tpp;

    /*
    step from the lowest search priority to the highest, looking for a
    channel to close.  return success as soon as one is done.
    */

    for (tpp = tb_all; *tpp != 0; tpp++) {
	if (tb_close (*tpp))
		return (TRUE);   /* -- got a channel closed -- */
    }
    return (FALSE);   /* -- couldn't get any closed -- */
}


#ifndef lint
static void    _advise ();


void    adios (va_alist)
va_dcl
{
	va_list ap;

	va_start (ap);

	_advise (ap);

	va_end (ap);

	_exit (1);
}
#else
/* VARARGS */

void    adios (what, fmt)
char   *what,
       *fmt;
{
	adios (what, fmt);
}
#endif


#ifndef lint

void    advise (va_alist)
va_dcl
{
	va_list ap;

	va_start (ap);

	_advise (ap);

	va_end (ap);
}

static void  _advise (ap)
va_list ap;
{
	char    buffer[BUFSIZ];

	asprintf (buffer, ap);

	(void) fflush (stdout);

	fprintf (stderr, "%s: ", myname);
	(void) fputs (buffer, stderr);
	(void) fputc ('\n', stderr);

	(void) fflush (stderr);
}
#else
/* VARARGS */

void    advise (what, fmt)
char   *what,
       *fmt;
{
	advise (what, fmt);
}
#endif