home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD2.img / d4xx / d473 / cnewssrc / cnews_src.lzh / dbz / dbzmain.c < prev    next >
C/C++ Source or Header  |  1990-12-15  |  11KB  |  512 lines

  1. /*
  2.  * dbz - use and test dbz in various ways
  3.  *
  4.  * -Log-
  5.  */
  6.  
  7. #include <stdio.h>
  8. #ifdef AMIGA
  9.   typedef long off_t;
  10. #else
  11. # include <sys/types.h>
  12. # include <sys/stat.h>        /* Why??? */
  13. #endif /* !AMIGA */
  14. #include <string.h>
  15. #include <dbz.h>
  16.  
  17. #ifdef FUNNYSEEKS
  18. #include <unistd.h>
  19. #else
  20. #define    SEEK_SET    0
  21. #endif
  22.  
  23. #define    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
  24.  
  25. #ifndef lint
  26. static char RCSid[] = "$Header$";
  27. #endif
  28.  
  29. char *progname;
  30.  
  31. char *inname = "(no file)";        /* filename for messages etc. */
  32. long lineno;                /* line number for messages etc. */
  33.  
  34. char *basename;
  35. char *pagname;
  36. char *dirname;
  37. char *str2dup();
  38. FILE *base;
  39.  
  40. int op = 'b';            /* what to do, default build a new table */
  41. int baseinput = 1;        /* is the base file also the input? */
  42.  
  43. char *from = NULL;        /* old table to use for dbzagain() */
  44. int omitzero = 0;        /* omit lines tagged with 0 */
  45. long every = 0;            /* report every n lines */
  46. int syncs = 0;            /* dbzsync() on each report */
  47. int quick = 0;            /* quick checking, not too thorough */
  48. int sweep = 0;            /* sweep file checking all offsets */
  49. int useincore = 1;        /* should we use incore facility? */
  50. long xxx = 0;            /* debugging variable */
  51. int printx = 0;            /* print xxx after all is done */
  52. int unique = 1;            /* before store(), check with fetch() */
  53. int usefresh = 0;        /* use dbzfresh? */
  54. long siz = 0;            /* -p size */
  55. char map = 'C';            /* -p map */
  56. long tag = 0;            /* -p tag mask */
  57. int exact = 0;            /* do not run dbzsize(siz) */
  58. int dbzint = 1;            /* use new interface? */
  59. char fs = '\t';            /* field separator, default tab */
  60. int unopen = 0;            /* make base unopenable during dbminit? */
  61. char *change = NULL;        /* chdir here before dbmclose */
  62.  
  63. #define    DEFBUF    1024        /* default line-buffer size */
  64. int buflen = DEFBUF;        /* line length limit */
  65. char lbuf[DEFBUF];
  66. char *line = lbuf;
  67. char cbuf[DEFBUF];
  68. char *cmp = cbuf;
  69.  
  70. void fail();
  71. void dofile();
  72. void runs();
  73. void dosweep();
  74. void mkfiles();
  75. void crfile();
  76. void doline();
  77.  
  78. #ifdef HAVERFCIZE
  79. extern char *rfc822ize();
  80. #else
  81. #define    rfc822ize(n)    (n)
  82. #endif
  83.  
  84. /*
  85.  - main - parse arguments and handle options
  86.  */
  87. main(argc, argv)
  88. int argc;
  89. char *argv[];
  90. {
  91.     int c;
  92.     int errflg = 0;
  93.     extern int optind;
  94.     extern char *optarg;
  95.     void process();
  96.     int doruns = 0;
  97.     extern long atol();
  98.     extern char *malloc();
  99.  
  100. #ifdef FJE
  101.     if ((progname=strrchr(*argv, '/')) || (progname=strrchr(*argv, ':')))
  102.         progname++;
  103.     else
  104. #endif /* FJE */
  105.         progname = argv[0];
  106.  
  107.     while ((c = getopt(argc, argv, "axct:l:R0E:SqOiX:Yuf:p:eMUC:d")) != EOF)
  108.         switch (c) {
  109.         case 'a':    /* append to existing table */
  110.             if (op != 'b')
  111.                 fail("only one of -a -x -c can be given", "");
  112.             op = 'a';
  113.             baseinput = 0;
  114.             break;
  115.         case 'x':    /* extract from existing table */
  116.             if (op != 'b')
  117.                 fail("only one of -a -x -c can be given", "");
  118.             op = 'x';
  119.             baseinput = 0;
  120.             break;
  121.         case 'c':    /* check existing table */
  122.             if (op != 'b')
  123.                 fail("only one of -a -x -c can be given", "");
  124.             op = 'c';
  125.             break;
  126.         case 't':    /* set field separator */
  127.             if (strlen(optarg) > 1)
  128.                 fail("only one field separator allowed", "");
  129.             fs = *optarg;
  130.             break;
  131.         case 'l':    /* override line-length limit */
  132.             buflen = atoi(optarg) + 1;
  133.             if (buflen <= 2)
  134.                 fail("bad -l value `%s'", optarg);
  135.             line = malloc(buflen);
  136.             cmp = malloc(buflen);
  137.             if (line == NULL || cmp == NULL)
  138.                 fail("cannot allocate %s-byte buffers", optarg);
  139.             break;
  140.         case 'R':    /* print run statistics */
  141.             doruns = 1;
  142.             break;
  143.         case '0':    /* omit lines tagged (by fake -t) with 0 */
  144.             omitzero = 1;
  145.             break;
  146.         case 'E':    /* report every n items */
  147.             every = atol(optarg);
  148.             break;
  149.         case 'S':    /* dbzsync() on each -E report */
  150.             syncs = 1;
  151.             break;
  152.         case 'q':    /* quick check, not too thorough */
  153.             quick = 1;
  154.             break;
  155.         case 'O':    /* sweep file checking all offsets */
  156.             sweep = 1;
  157.             break;
  158.         case 'i':    /* don't use incore */
  159.             useincore = 0;
  160.             break;
  161.         case 'X':    /* set xxx */
  162.             xxx = atoi(optarg);
  163.             break;
  164.         case 'Y':    /* print xxx afterward */
  165.             printx = 1;
  166.             break;
  167.         case 'u':    /* don't check uniqueness */
  168.             unique = 0;
  169.             break;
  170.         case 'f':    /* init from existing table's parameters */
  171.             from = optarg;
  172.             break;
  173.         case 'p':    /* parameters for dbzfresh */
  174.             if (sscanf(optarg, "%ld %1s %lx", &siz, &map, &tag) != 3) {
  175.                 map = '?';
  176.                 tag = 0;
  177.                 if (sscanf(optarg, "%ld", &siz) != 1)
  178.                     fail("bad -n value `%s'", optarg);
  179.             }
  180.             usefresh = 1;
  181.             break;
  182.         case 'e':    /* -p size is exact, don't dbzsize() it */
  183.             exact = 1;
  184.             break;
  185.         case 'M':    /* use old dbm interface + rfc822ize */
  186.             dbzint = 0;
  187.             break;
  188.         case 'U':    /* make base unopenable during init */
  189.             unopen = 1;
  190.             break;
  191.         case 'C':    /* change directories before dbmclose */
  192.             change = optarg;
  193.             break;
  194.         case 'd':    /* Debugging. */
  195.             if (dbzdebug(1) < 0)
  196.                 fail("dbz debugging not available", "");
  197.             break;
  198.         case '?':
  199.         default:
  200.             errflg++;
  201.             break;
  202.         }
  203.     if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
  204.         fprintf(stderr, "usage: %s ", progname);
  205.         fprintf(stderr, "[-a] [-x] [-c] database [file] ...\n");
  206.         return(2);
  207.     }
  208.  
  209.     (void) dbzincore(useincore);
  210.     basename = argv[optind];
  211.     pagname = str2dup(basename, ".pag");
  212.     dirname = str2dup(basename, ".dir");
  213.     mkfiles();
  214.     optind++;
  215.  
  216.     if (baseinput)        /* implies no further arguments */
  217.         process(base, basename);
  218.     else if (optind >= argc)
  219.         process(stdin, "stdin");
  220.     else
  221.         for (; optind < argc; optind++)
  222.             dofile(argv[optind]);
  223.  
  224.     if (change != NULL)
  225.         (void) chdir(change);
  226.     if (dbmclose() < 0)
  227.         fail("dbmclose failed", "");
  228.     if (doruns)
  229.         runs(pagname);
  230.     if (sweep)
  231.         dosweep(basename, pagname);
  232.     if (printx)
  233.         printf("%ld\n", xxx);
  234.     return(0);
  235. }
  236.  
  237. /*
  238.  - dofile - open a file and invoke process()
  239.  */
  240. void
  241. dofile(name)
  242. char *name;
  243. {
  244.     register FILE *in;
  245.  
  246.     if (STREQ(name, "-"))
  247.         process(stdin, "-");
  248.     else {
  249.         in = fopen(name, "r");
  250.         if (in == NULL)
  251.             fail("cannot open `%s'", name);
  252.         process(in, name);
  253.         (void) fclose(in);
  254.     }
  255. }
  256.  
  257. /*
  258.  - mkfiles - create empty files and open them up
  259.  */
  260. void
  261. mkfiles()
  262. {
  263.     if (op == 'b' && !dbzint) {
  264.         crfile(dirname);
  265.         crfile(pagname);
  266.     }
  267.  
  268.     base = fopen(basename, (op == 'a') ? "a" : "r");
  269.     if (base == NULL)
  270.         fail("cannot open `%s'", basename);
  271. #ifndef AMIGA
  272.     if (unopen)
  273.         (void) chmod(basename, 0);
  274. #endif /* !AMIGA */
  275.     if (from != NULL) {
  276.         if (dbzagain(basename, from) < 0)
  277.             fail("dbzagain(`%s'...) failed", basename);
  278.     } else if (op == 'b' && dbzint) {
  279.         if (!exact)
  280.             siz = dbzsize(siz);
  281.         if (dbzfresh(basename, siz, (int)fs, map, tag) < 0)
  282.             fail("dbzfresh(`%s'...) failed", basename);
  283.     } else if (dbminit(basename) < 0)
  284.         fail("dbminit(`%s') failed", basename);
  285. #ifndef AMIGA
  286.     if (unopen)
  287.         (void) chmod(basename, 0600);    /* hard to restore original */
  288. #endif /* !AMIGA */
  289. }
  290.  
  291. /*
  292.  - crfile - create a file
  293.  */
  294. void
  295. crfile(name)
  296. char *name;
  297. {
  298.     register int f;
  299.  
  300.     f = creat(name, 0666);
  301.     if (f < 0)
  302.         fail("cannot create `%s'", name);
  303.     (void) close(f);
  304. }
  305.  
  306. /*
  307.  - process - process input file
  308.  */
  309. void
  310. process(in, name)
  311. FILE *in;
  312. char *name;
  313. {
  314.     register off_t place;
  315.  
  316.     inname = name;
  317.     lineno = 0;
  318.  
  319.     for (;;) {
  320.         place = ftell(in);
  321.         if (fgets(line, buflen, in) == NULL)
  322.             return;
  323.         lineno++;
  324.         if (every > 0 && lineno%every == 0) {
  325.             fprintf(stderr, "%ld\n", lineno);
  326.             if (dbzsync() < 0)
  327.                 fail("dbzsync failed", "");
  328.         }
  329.         doline(line, place);
  330.     }
  331.     /* NOTREACHED */
  332. }
  333.  
  334. /*
  335.  - doline - process input line
  336.  */
  337. void
  338. doline(lp, inoffset)
  339. char *lp;
  340. off_t inoffset;
  341. {
  342.     register char *p;
  343.     register char pc;
  344.     datum key, value;
  345.     off_t place = inoffset;
  346.     register int shouldfind;
  347.     register int llen;
  348.     char keytext[DBZMAXKEY+1];
  349.  
  350.     p = NULL;
  351.     if (fs != '\0')
  352.         p = strchr(lp, (int) fs);
  353.     if (p == NULL)
  354.         p = lp + strlen(lp);
  355.     if (p > lp && *(p-1) == '\n')
  356.         p--;
  357.     if (p - lp > DBZMAXKEY)
  358.         fail("key of `%.40s...' too long", lp);
  359.     pc = *p;
  360.     *p = '\0';
  361.     (void) strcpy(keytext, lp);
  362.     *p = pc;
  363.     key.dptr = (dbzint) ? keytext : rfc822ize(keytext);
  364.     key.dsize = strlen(keytext)+1;
  365.  
  366.     switch (op) {
  367.     case 'a':
  368.         place = ftell(base);
  369.         llen = strlen(lp);
  370.         if (fwrite(lp, 1, llen, base) != llen)
  371.             fail("write error in `%s'", basename);
  372.         /* FALLTHROUGH */
  373.     case 'b':
  374.         if (omitzero && p != NULL && *(p+1) == '0')
  375.             return;
  376.         if (unique) {
  377.             value = (dbzint) ? dbzfetch(key) : fetch(key);
  378.             if (value.dptr != NULL)
  379.                 fail("`%.40s...' already present", lp);
  380.         }
  381.         value.dptr = (char *)&place;
  382.         value.dsize = (int)sizeof(off_t);
  383.         if (((dbzint) ? dbzstore(key, value) : store(key, value)) < 0)
  384.             fail("store failed on `%.40s...'", lp);
  385.         break;
  386.     case 'c':
  387.         value = (dbzint) ? dbzfetch(key) : fetch(key);
  388.         shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
  389.         if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
  390.             fail("`%.40s...' found, shouldn't be", lp);
  391.         if (shouldfind && (value.dptr == NULL ||
  392.                     value.dsize != sizeof(off_t)))
  393.             fail("can't find `%.40s...'", lp);
  394.         if (shouldfind && !quick) {
  395.             (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
  396.             if (place != inoffset)
  397.                 fail("offset mismatch on `%.40s...'", lp);
  398.             if (fseek(base, place, SEEK_SET) == -1)
  399.                 fail("fseek failed on `%.40s...'", lp);
  400.             if (fgets(cmp, buflen, base) == NULL)
  401.                 fail("can't read line for `%.40s...'", lp);
  402.             if (!STREQ(lp, cmp))
  403.                 fail("compare failed on `%.40s...'", lp);
  404.         }
  405.         break;
  406.     case 'x':
  407.         value = (dbzint) ? dbzfetch(key) : fetch(key);
  408.         if (value.dptr != NULL) {
  409.             (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
  410.             if (fseek(base, place, SEEK_SET) == -1)
  411.                 fail("fseek failed on `%.40s...'", lp);
  412.             if (fgets(cmp, buflen, base) == NULL)
  413.                 fail("can't read line for `%.40s...'", lp);
  414.             fputs(cmp, stdout);
  415.         }
  416.         break;
  417.     default:
  418.         fail("unknown operator -- can't happen", "");
  419.         break;
  420.     }
  421. }
  422.  
  423. /*
  424.  - runs - print run statistics
  425.  */
  426. void
  427. runs(file)
  428. char *file;
  429. {
  430.     register FILE *fd;
  431.     off_t it;
  432.     register long run;
  433.  
  434.     fd = fopen(file, "r");
  435.     if (fd == NULL)
  436.         fail("cannot reopen `%s'", file);
  437.     run = 0;
  438.     while (fread((char *)&it, sizeof(off_t), 1, fd) == 1) {
  439.         if (it != 0)
  440.             run++;
  441.         else if (run > 0) {
  442.             printf("%ld\n", run);
  443.             run = 0;
  444.         }
  445.     }
  446.     (void) fclose(fd);
  447. }
  448.  
  449. /*
  450.  - dosweep - sweep pag file checking for valid offsets
  451.  */
  452. void
  453. dosweep(fn, pn)
  454. char *fn;
  455. char *pn;
  456. {
  457.     register FILE *pf;
  458.     off_t it;
  459.     char nl;
  460.     register FILE *hf;
  461.  
  462.     hf = fopen(fn, "r");
  463.     if (hf == NULL)
  464.         fail("cannot reopen `%s'", fn);
  465.     pf = fopen(pn, "r");
  466.     if (pf == NULL)
  467.         fail("cannot reopen `%s'", pn);
  468.     while (fread((char *)&it, sizeof(off_t), 1, pf) == 1) {
  469.         it = (it & (0x80<<24)) ? (it&~(0xff<<24)) : it;
  470.         if (it != 0 && it != 1) {    /* 0 empty, 1 known okay */
  471.             it--;        /* get rid of bias */
  472.             (void) fseek(hf, it-1, SEEK_SET);
  473.             nl = getc(hf);
  474.             if (nl != '\n')
  475.                 fprintf(stderr, "offset 0%lo does not point to line\n",
  476.                                 (long)it);
  477.         }
  478.     }
  479.     (void) fclose(hf);
  480.     (void) fclose(pf);
  481. }
  482.  
  483. /*
  484.  - fail - complain and die
  485.  */
  486. void fail(s1, s2)
  487. char *s1;
  488. char *s2;
  489. {
  490.     fprintf(stderr, "%s: (file `%s', line %ld) ", progname, inname, lineno);
  491.     fprintf(stderr, s1, s2);
  492.     fputc('\n', stderr);
  493.     exit( 1 );
  494. }
  495.  
  496. /*
  497.  - str2dup - concatenate strings and malloc result
  498.  */
  499. char *str2dup(s1, s2)
  500. char *s1;
  501. char *s2;
  502. {
  503.     register char *p;
  504.  
  505.     p = malloc((size_t)strlen(s1) + strlen(s2) + 1);
  506.     if (p == NULL)
  507.         fail("can't allocate space for strings", "");
  508.     (void) strcpy(p, s1);
  509.     (void) strcat(p, s2);
  510.     return(p);
  511. }
  512.