aboutsummaryrefslogtreecommitdiff
path: root/libio/dbz/dbzmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'libio/dbz/dbzmain.c')
-rw-r--r--libio/dbz/dbzmain.c519
1 files changed, 519 insertions, 0 deletions
diff --git a/libio/dbz/dbzmain.c b/libio/dbz/dbzmain.c
new file mode 100644
index 00000000000..4317a0d0831
--- /dev/null
+++ b/libio/dbz/dbzmain.c
@@ -0,0 +1,519 @@
+/*
+ * dbz - use and test dbz in various ways
+ *
+ * -Log-
+ */
+
+#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 1997/08/21 22:58:23 jason Exp $";
+#endif
+
+char *progname;
+
+char *inname = "(no file)"; /* filename for messages etc. */
+long lineno; /* line number for messages etc. */
+
+char *my_basename;
+char *pagname;
+char *dir_name;
+char *str2dup();
+FILE *base;
+
+int op = 'b'; /* what to do, default build a new table */
+int baseinput = 1; /* is the base file also the input? */
+
+char *from = NULL; /* old table to use for dbzagain() */
+int omitzero = 0; /* omit lines tagged with 0 */
+long every = 0; /* report every n lines */
+int syncs = 0; /* dbzsync() on each report */
+int quick = 0; /* quick checking, not too thorough */
+int sweep = 0; /* sweep file checking all offsets */
+int useincore = 1; /* should we use incore facility? */
+long xxx = 0; /* debugging variable */
+int printx = 0; /* print xxx after all is done */
+int unique = 1; /* before store(), check with fetch() */
+int usefresh = 0; /* use dbzfresh? */
+long siz = 0; /* -p size */
+char map = 'C'; /* -p map */
+long tag = 0; /* -p tag mask */
+int exact = 0; /* do not run dbzsize(siz) */
+int dbzint = 1; /* use new interface? */
+char fs = '\t'; /* field separator, default tab */
+int unopen = 0; /* make base unopenable during dbminit? */
+char *change = NULL; /* chdir here before dbmclose */
+
+#define DEFBUF 1024 /* default line-buffer size */
+int buflen = DEFBUF; /* line length limit */
+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();
+
+/*
+ - main - parse arguments and handle options
+ */
+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': /* append to existing table */
+ if (op != 'b')
+ fail("only one of -a -x -c -m can be given", "");
+ op = 'a';
+ baseinput = 0;
+ break;
+ case 'x': /* extract from existing table */
+ if (op != 'b')
+ fail("only one of -a -x -c -m can be given", "");
+ op = 'x';
+ baseinput = 0;
+ break;
+ case 'c': /* check existing table */
+ if (op != 'b')
+ fail("only one of -a -x -c -m can be given", "");
+ op = 'c';
+ break;
+ case 'm': /* extract missing (complement of -x) */
+ if (op != 'b')
+ fail("only one of -a -x -c -m can be given", "");
+ op = 'm';
+ baseinput = 0;
+ break;
+ case 't': /* set field separator */
+ if (strlen(optarg) > 1)
+ fail("only one field separator allowed", "");
+ fs = *optarg;
+ break;
+ case 'l': /* override line-length limit */
+ 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': /* print run statistics */
+ doruns = 1;
+ break;
+ case '0': /* omit lines tagged (by fake -t) with 0 */
+ omitzero = 1;
+ break;
+ case 'E': /* report every n items */
+ every = atol(optarg);
+ break;
+ case 'S': /* dbzsync() on each -E report */
+ syncs = 1;
+ break;
+ case 'q': /* quick check or extract */
+ quick = 1;
+ break;
+ case 'O': /* sweep file checking all offsets */
+ sweep = 1;
+ break;
+ case 'i': /* don't use incore */
+ useincore = 0;
+ break;
+ case 'X': /* set xxx */
+ xxx = atoi(optarg);
+ break;
+ case 'Y': /* print xxx afterward */
+ printx = 1;
+ break;
+ case 'u': /* don't check uniqueness */
+ unique = 0;
+ break;
+ case 'f': /* init from existing table's parameters */
+ from = optarg;
+ break;
+ case 'p': /* parameters for dbzfresh */
+ 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': /* -p size is exact, don't dbzsize() it */
+ exact = 1;
+ break;
+ case 'M': /* use old dbm interface + rfc822ize */
+ dbzint = 0;
+ break;
+ case 'U': /* make base unopenable during init */
+ unopen = 1;
+ break;
+ case 'C': /* change directories before dbmclose */
+ change = optarg;
+ break;
+ case 'd': /* Debugging. */
+ 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) /* implies no further arguments */
+ 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);
+}
+
+/*
+ - dofile - open a file and invoke process()
+ */
+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);
+ }
+}
+
+/*
+ - mkfiles - create empty files and open them up
+ */
+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, 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); /* hard to restore original */
+}
+
+/*
+ - crfile - create a file
+ */
+void
+crfile(name)
+char *name;
+{
+ register int f;
+
+ f = creat(name, 0666);
+ if (f < 0)
+ fail("cannot create `%s'", name);
+ (void) close(f);
+}
+
+/*
+ - process - process input file
+ */
+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);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ - doline - process input line
+ */
+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);
+ /* FALLTHROUGH */
+ 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;
+ }
+}
+
+/*
+ - runs - print run statistics
+ */
+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);
+}
+
+/*
+ - dosweep - sweep pag file checking for valid offsets
+ */
+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) { /* 0 empty, 1 known okay */
+ it--; /* get rid of bias */
+ (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);
+}
+
+/*
+ - fail - complain and die
+ */
+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);
+}
+
+/*
+ - str2dup - concatenate strings and malloc result
+ */
+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);
+}