|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 13851 (0x361b)
Types: TextFile
Names: »dbmbuild.c«
└─⟦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«
/* 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