#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <dbz.h>
#ifdef FUNNYSEEKS
#include <unistd.h>
#else
#define SEEK_SET 0
#endif
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
#ifndef lint
static char RCSid[] = "$Header: /egcs/carton/cvsfiles/egcs/./libio/dbz/dbzmain.c,v 1.1.1.1 1997/08/21 22:58:23 jason Exp $";
#endif
char *progname;
char *inname = "(no file)";
long lineno;
char *my_basename;
char *pagname;
char *dir_name;
char *str2dup();
FILE *base;
int op = 'b';
int baseinput = 1;
char *from = NULL;
int omitzero = 0;
long every = 0;
int syncs = 0;
int quick = 0;
int sweep = 0;
int useincore = 1;
long xxx = 0;
int printx = 0;
int unique = 1;
int usefresh = 0;
long siz = 0;
char map = 'C';
long tag = 0;
int exact = 0;
int dbzint = 1;
char fs = '\t';
int unopen = 0;
char *change = NULL;
#define DEFBUF 1024
int buflen = DEFBUF;
char lbuf[DEFBUF];
char *line = lbuf;
char cbuf[DEFBUF];
char *cmp = cbuf;
void fail();
void dofile();
void runs();
void dosweep();
void mkfiles();
void crfile();
void doline();
void process();
#ifdef HAVERFCIZE
extern char *rfc822ize();
#else
#define rfc822ize(n) (n)
#endif
extern char *malloc();
int
main(argc, argv)
int argc;
char *argv[];
{
int c;
int errflg = 0;
extern int optind;
extern char *optarg;
int doruns = 0;
extern long atol();
progname = argv[0];
while ((c = getopt(argc, argv, "axcmt:l:R0E:SqOiX:Yuf:p:eMUC:d")) != EOF)
switch (c) {
case 'a':
if (op != 'b')
fail("only one of -a -x -c -m can be given", "");
op = 'a';
baseinput = 0;
break;
case 'x':
if (op != 'b')
fail("only one of -a -x -c -m can be given", "");
op = 'x';
baseinput = 0;
break;
case 'c':
if (op != 'b')
fail("only one of -a -x -c -m can be given", "");
op = 'c';
break;
case 'm':
if (op != 'b')
fail("only one of -a -x -c -m can be given", "");
op = 'm';
baseinput = 0;
break;
case 't':
if (strlen(optarg) > 1)
fail("only one field separator allowed", "");
fs = *optarg;
break;
case 'l':
buflen = atoi(optarg) + 1;
if (buflen <= 2)
fail("bad -l value `%s'", optarg);
line = malloc(buflen);
cmp = malloc(buflen);
if (line == NULL || cmp == NULL)
fail("cannot allocate %s-byte buffers", optarg);
break;
case 'R':
doruns = 1;
break;
case '0':
omitzero = 1;
break;
case 'E':
every = atol(optarg);
break;
case 'S':
syncs = 1;
break;
case 'q':
quick = 1;
break;
case 'O':
sweep = 1;
break;
case 'i':
useincore = 0;
break;
case 'X':
xxx = atoi(optarg);
break;
case 'Y':
printx = 1;
break;
case 'u':
unique = 0;
break;
case 'f':
from = optarg;
break;
case 'p':
if (sscanf(optarg, "%ld %1s %lx", &siz, &map, &tag) != 3) {
map = '?';
tag = 0;
if (sscanf(optarg, "%ld", &siz) != 1)
fail("bad -n value `%s'", optarg);
}
usefresh = 1;
break;
case 'e':
exact = 1;
break;
case 'M':
dbzint = 0;
break;
case 'U':
unopen = 1;
break;
case 'C':
change = optarg;
break;
case 'd':
if (dbzdebug(1) < 0)
fail("dbz debugging not available", "");
break;
case '?':
default:
errflg++;
break;
}
if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
fprintf(stderr, "usage: %s ", progname);
fprintf(stderr, "[-a] [-x] [-c] database [file] ...\n");
exit(2);
}
(void) dbzincore(useincore);
my_basename = argv[optind];
pagname = str2dup(my_basename, ".pag");
dir_name = str2dup(my_basename, ".dir");
mkfiles();
optind++;
if (baseinput)
process(base, my_basename);
else if (optind >= argc)
process(stdin, "stdin");
else
for (; optind < argc; optind++)
dofile(argv[optind]);
if (change != NULL)
(void) chdir(change);
if (dbmclose() < 0)
fail("dbmclose failed", "");
if (doruns)
runs(pagname);
if (sweep)
dosweep(my_basename, pagname);
if (printx)
printf("%ld\n", xxx);
#ifdef DBZ_FINISH
DBZ_FINISH;
#endif
exit(0);
}
void
dofile(name)
char *name;
{
register FILE *in;
if (STREQ(name, "-"))
process(stdin, "-");
else {
in = fopen(name, "r");
if (in == NULL)
fail("cannot open `%s'", name);
process(in, name);
(void) fclose(in);
}
}
void
mkfiles()
{
if (op == 'b' && !dbzint) {
crfile(dir_name);
crfile(pagname);
}
base = fopen(my_basename, (op == 'a') ? "a" : "r");
if (base == NULL)
fail("cannot open `%s'", my_basename);
if (unopen)
(void) chmod(my_basename, 0);
if (from != NULL) {
if (dbzagain(my_basename, from) < 0)
fail("dbzagain(`%s'...) failed", my_basename);
} else if (op == 'b' && dbzint) {
if (!exact)
siz = dbzsize(siz);
if (dbzfresh(my_basename, siz, (int)fs, map, (off_t)tag) < 0)
fail("dbzfresh(`%s'...) failed", my_basename);
} else if (dbminit(my_basename) < 0)
fail("dbminit(`%s') failed", my_basename);
if (unopen)
(void) chmod(my_basename, 0600);
}
void
crfile(name)
char *name;
{
register int f;
f = creat(name, 0666);
if (f < 0)
fail("cannot create `%s'", name);
(void) close(f);
}
void
process(in, name)
FILE *in;
char *name;
{
register off_t place;
inname = name;
lineno = 0;
for (;;) {
place = ftell(in);
if (fgets(line, buflen, in) == NULL)
return;
lineno++;
if (every > 0 && lineno%every == 0) {
fprintf(stderr, "%ld\n", lineno);
if (dbzsync() < 0)
fail("dbzsync failed", "");
}
doline(line, place);
}
}
void
doline(lp, inoffset)
char *lp;
off_t inoffset;
{
register char *p;
register char pc;
datum key, value;
off_t place = inoffset;
register int shouldfind;
register int llen;
char keytext[DBZMAXKEY+1];
p = NULL;
if (fs != '\0')
p = strchr(lp, fs);
if (p == NULL)
p = lp + strlen(lp);
if (p > lp && *(p-1) == '\n')
p--;
if (p - lp > DBZMAXKEY)
fail("key of `%.40s...' too long", lp);
pc = *p;
*p = '\0';
(void) strcpy(keytext, lp);
*p = pc;
key.dptr = (dbzint) ? keytext : rfc822ize(keytext);
key.dsize = strlen(keytext)+1;
switch (op) {
case 'a':
place = ftell(base);
llen = strlen(lp);
if (fwrite(lp, 1, llen, base) != llen)
fail("write error in `%s'", my_basename);
case 'b':
if (omitzero && p != NULL && *(p+1) == '0')
return;
if (unique) {
value = (dbzint) ? dbzfetch(key) : fetch(key);
if (value.dptr != NULL)
fail("`%.40s...' already present", lp);
}
value.dptr = (char *)&place;
value.dsize = (int)sizeof(off_t);
if (((dbzint) ? dbzstore(key, value) : store(key, value)) < 0)
fail("store failed on `%.40s...'", lp);
break;
case 'c':
value = (dbzint) ? dbzfetch(key) : fetch(key);
shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
fail("`%.40s...' found, shouldn't be", lp);
if (shouldfind && (value.dptr == NULL ||
value.dsize != sizeof(off_t)))
fail("can't find `%.40s...'", lp);
if (shouldfind && !quick) {
(void) memcpy((char *)&place, value.dptr, sizeof(off_t));
if (place != inoffset)
fail("offset mismatch on `%.40s...'", lp);
if (fseek(base, place, SEEK_SET) == -1)
fail("fseek failed on `%.40s...'", lp);
if (fgets(cmp, buflen, base) == NULL)
fail("can't read line for `%.40s...'", lp);
if (!STREQ(lp, cmp))
fail("compare failed on `%.40s...'", lp);
}
break;
case 'x':
value = (dbzint) ? dbzfetch(key) : fetch(key);
if (value.dptr != NULL && !quick) {
(void) memcpy((char *)&place, value.dptr, sizeof(off_t));
if (fseek(base, place, SEEK_SET) == -1)
fail("fseek failed on `%.40s...'", lp);
if (fgets(cmp, buflen, base) == NULL)
fail("can't read line for `%.40s...'", lp);
fputs(cmp, stdout);
} else if (value.dptr != NULL)
fputs(lp, stdout);
break;
case 'm':
value = (dbzint) ? dbzfetch(key) : fetch(key);
if (value.dptr == NULL) {
fputs(keytext, stdout);
putchar('\n');
}
break;
default:
fail("unknown operator -- can't happen", "");
break;
}
}
void
runs(file)
char *file;
{
register FILE *fd;
off_t it;
register long run;
fd = fopen(file, "r");
if (fd == NULL)
fail("cannot reopen `%s'", file);
run = 0;
while (fread((char *)&it, sizeof(off_t), 1, fd) == 1) {
if (it != 0)
run++;
else if (run > 0) {
printf("%ld\n", run);
run = 0;
}
}
(void) fclose(fd);
}
void
dosweep(fn, pn)
char *fn;
char *pn;
{
register FILE *pf;
off_t it;
char nl;
register FILE *hf;
hf = fopen(fn, "r");
if (hf == NULL)
fail("cannot reopen `%s'", fn);
pf = fopen(pn, "r");
if (pf == NULL)
fail("cannot reopen `%s'", pn);
while (fread((char *)&it, sizeof(off_t), 1, pf) == 1) {
it = (it & ((off_t)0x80000000)) ? (it&~((off_t)0xff000000)) : it;
if (it != 0 && it != 1) {
it--;
(void) fseek(hf, it-1, SEEK_SET);
nl = getc(hf);
if (nl != '\n')
fprintf(stderr, "offset 0%lo does not point to line\n",
(long)it);
}
}
(void) fclose(hf);
(void) fclose(pf);
}
void
fail(s1, s2)
char *s1;
char *s2;
{
fprintf(stderr, "%s: (file `%s', line %ld) ", progname, inname, lineno);
fprintf(stderr, s1, s2);
fprintf(stderr, "\n");
exit(1);
}
char *
str2dup(s1, s2)
char *s1;
char *s2;
{
register char *p;
p = malloc((size_t)strlen(s1) + strlen(s2) + 1);
if (p == NULL)
fail("can't allocate space for strings", "");
(void) strcpy(p, s1);
(void) strcat(p, s2);
return(p);
}