home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / tools / dbmbuild.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  12.4 KB  |  570 lines

  1. /*
  2.  *      Database builder for MMDF address database
  3.  *
  4.  *      Command line:
  5.  *              dbmbuild [-flags] [-t tailorfile] [outfile]
  6.  *
  7.  *              where flags are:
  8.  *              d   -   debugging output
  9.  *              v   -   verbose output
  10.  *        k   -   keep going if a table is missing
  11.  *              n   -   make a new dbm file from scratch
  12.  *              t   -   alternate tailorfile
  13.  *
  14.  *      output-file is name of EXISTING dbm file to insert entires.
  15.  *      Note it is two files, an output-file.dir and an output-file.pag.
  16.  *
  17.  *      No arguments defaults to  -n.
  18.  */
  19.  
  20. #include "util.h"
  21. #include "mmdf.h"
  22. #include "ch.h"
  23. #include "dm.h"
  24. #include "chdbm.h"
  25.  
  26. extern Table **tb_list;  /* order tables searched         */
  27. extern Domain **dm_list; /* ordr domain tables searched  */
  28. extern Chan  **ch_tbsrch;  /* order chans searched         */
  29.  
  30. extern char *blt();
  31. extern char *multcat();
  32. extern char *tbldfldir;
  33. extern char *tbldbm;
  34. extern char *lckdfldir;
  35. extern char *mmtailor;
  36.  
  37. typedef struct
  38. {
  39.     char *dptr;
  40.     int dsize;
  41. } datum;
  42.  
  43. extern datum fetch ();
  44.  
  45. typedef struct dbmentry
  46. {
  47.     char dbmvalue[1];
  48. } Entry;
  49.  
  50. int error;
  51. int Debug;
  52. int Verbose;
  53. int newflag;
  54. int keepgoing;
  55. char dbfile[128];
  56. char *dblock;
  57. int lckfd;
  58.  
  59. char dbmstr[] = "DBM$$";
  60.             /* string for locking the database */
  61.  
  62. /*
  63.  * Main procedure.
  64.  * process arguments, set flags and invoke file processing.
  65.  * clean up and exit properly.
  66.  */
  67.  
  68. main(argc, argv)
  69. char **argv;
  70. {
  71.     int ind;
  72.     char *p;
  73.     char *outfile;
  74.     register Table  *tblptr;
  75.     char *prog;
  76.  
  77.     prog = argv[0];
  78.  
  79.     argv++; argc--;
  80.     outfile = (char *)0;
  81.  
  82.     if (argc == 0)
  83.     newflag++;
  84.  
  85.     while(argc-- > 0)
  86.     {
  87.     if (Debug)
  88.         fprintf (stderr, "arg='%s'\n", *argv);
  89.     p = *argv++;
  90.     if(*p == '-')
  91.     {
  92.         while(*++p)
  93.         switch(*p)
  94.         {
  95.             case 'O':    /* Obsolete, ignored */
  96.                 break;
  97.  
  98.             case 'd':
  99.                 Debug++;
  100.                 break;
  101.  
  102.             case 'k':
  103.                 keepgoing++;
  104.                 break;
  105.  
  106.             case 'n':
  107.                 newflag++;
  108.                 break;
  109.  
  110.             case 'v':
  111.                 Verbose++;
  112.                 break;
  113.  
  114.             case 't':
  115.                 if (argc--==2) newflag++;
  116.                 mmtailor = *argv++;
  117.                 break;
  118.  
  119.             default:
  120.                 fprintf (stderr,"Unknown flag %c\n",*p);
  121.                 break;
  122.         }
  123.     }
  124.     else
  125.     {
  126.          outfile = p;
  127.          break;
  128.     }
  129.     }
  130.  
  131.     mmdf_init(prog);
  132.  
  133.     if (outfile == 0)           /* use default database */
  134.     {
  135.     if (tbldbm == 0 || tbldbm[0] == '\0')
  136.     {
  137.         fprintf (stderr, "no default data base, in 'tbldbm' variable\n");
  138.         exit (NOTOK);
  139.     }
  140.     outfile = tbldbm;
  141.     }
  142.  
  143.     /*
  144.      *  Check for existence first
  145.      */
  146.     error = 0;
  147.     if (argc <= 0) {
  148.     for (ind = 0; dm_list[ind] != (Domain *)0; ind++)
  149.         error += check(dm_list[ind] -> dm_table);
  150.  
  151.     for (ind = 0; ch_tbsrch[ind] != (Chan *) 0; ind++)
  152.     {
  153.         error += check(ch_tbsrch[ind] -> ch_table);
  154.  
  155.         if ((tblptr = ch_tbsrch[ind] -> ch_insource) != (Table *) 0)
  156.         error += check(tblptr);
  157.         if ((tblptr = ch_tbsrch[ind] -> ch_outsource) != (Table *) 0)
  158.         error += check(tblptr);
  159.         if ((tblptr = ch_tbsrch[ind] -> ch_indest) != (Table *) 0)
  160.         error += check(tblptr);
  161.         if ((tblptr = ch_tbsrch[ind] -> ch_outdest) != (Table *) 0)
  162.         error += check(tblptr);
  163.     }
  164.  
  165.     for (ind = 0; (tblptr = tb_list[ind]) != (Table *) 0; ind++)
  166.         error += check (tblptr);
  167.     } else {
  168.     while (argc-- > 0)
  169.     {
  170.         if ((tblptr = tb_nm2struct (*argv++)) == (Table *) NOTOK)
  171.         {
  172.         fprintf (stderr, "Table '%s' is unknown\n", *--argv);
  173.         error++;
  174.         };
  175.         error += check(tblptr);
  176.     }
  177.     }
  178.  
  179.     if (error) {
  180.     fprintf (stderr, "Some tables are missing.  dbmbuild aborted.\n");
  181.         exit(9);
  182.     }
  183.  
  184.     getfpath (outfile, tbldfldir, dbfile);
  185.     dblock = multcat (dbfile, ".lck", (char *)0);
  186.     (void) close( creat( dblock, 0444 ));
  187.  
  188.     if ((lckfd = lk_open(dblock, 0, (char *)0, (char *)0, 10)) < 0) {
  189.     perror (dblock);
  190.     fprintf (stderr, "Data base %s is locked.  Try again later.\n",
  191.          dbfile);
  192.     exit (NOTOK);
  193.     }
  194.  
  195.     if (!theinit (newflag))
  196.     cleanup (-1);
  197.  
  198.     if (argc <= 0)
  199.     {
  200.     /*
  201.      *  Now process for real!
  202.      */
  203.     for (ind = 0; dm_list[ind] != (Domain *)0; ind++)
  204.     {
  205.         if (Debug)
  206.         fprintf (stderr, "Domain '%s'\n", dm_list[ind] -> dm_show);
  207.         process (dm_list[ind] -> dm_table);
  208.     }
  209.  
  210.     for (ind = 0; ch_tbsrch[ind] != (Chan *) 0; ind++)
  211.     {
  212.         if (Debug)
  213.         fprintf (stderr, "Chan '%s'\n", ch_tbsrch[ind] -> ch_show);
  214.         process (ch_tbsrch[ind] -> ch_table);
  215.  
  216.         if ((tblptr = ch_tbsrch[ind] -> ch_insource) != (Table *) 0)
  217.         {
  218.         if (Debug)
  219.             fprintf (stderr, "Source inbound filter\n");
  220.         if (Verbose || Debug)
  221.             putc ('\t', stderr);
  222.         process (tblptr);
  223.         }
  224.         if ((tblptr = ch_tbsrch[ind] -> ch_outsource) != (Table *) 0)
  225.         {
  226.         if (Debug)
  227.             fprintf (stderr, "Source outbound filter\n");
  228.         if (Verbose || Debug)
  229.             putc ('\t', stderr);
  230.         process (tblptr);
  231.         }
  232.         if ((tblptr = ch_tbsrch[ind] -> ch_indest) != (Table *) 0)
  233.         {
  234.         if (Debug)
  235.             fprintf (stderr, "Destination inbound filter\n");
  236.         if (Verbose || Debug)
  237.             putc ('\t', stderr);
  238.         process (tblptr);
  239.         }
  240.         if ((tblptr = ch_tbsrch[ind] -> ch_outdest) != (Table *) 0)
  241.         {
  242.         if (Debug)
  243.             fprintf (stderr, "Destination outbound filter\n");
  244.         if (Verbose || Debug)
  245.             putc ('\t', stderr);
  246.         process (tblptr);
  247.         }
  248.     }
  249.  
  250.     for (ind = 0; (tblptr = tb_list[ind]) != (Table *) 0; ind++)
  251.     {                           /* in case table used by chan */
  252.         if (tblptr -> tb_fp != (FILE *) EOF)
  253.         {
  254.         if (Debug)
  255.             fprintf (stderr, "Table '%s'\n", tblptr -> tb_name);
  256.         process (tblptr);
  257.         }
  258.     }
  259.     }
  260.     else
  261.     while (argc-- > 0)
  262.     {
  263.         if ((tblptr = tb_nm2struct (*argv++)) == (Table *) NOTOK)
  264.         {
  265.          (void) fflush (stdout);
  266.          fprintf (stderr, "Table '%s' is unknown\n", *--argv);
  267.          cleanup (-1);
  268.         };
  269.         process (tblptr);
  270.     }
  271.  
  272.     cleanup (theend (newflag));
  273. }
  274.  
  275. /* */
  276.  
  277. theinit (new)               /* initialize the dbm files */
  278. int new;
  279. {
  280.     char tmpfile[100];
  281.  
  282.     if (new)                /* start with fresh files */
  283.     {
  284.     if (Verbose || Debug)
  285.         fprintf (stderr, "Temporary database:  %s$\n", dbfile);
  286.     (void) sprintf (tmpfile, "%s$.pag", dbfile);
  287.     if(Debug)
  288.         fprintf (stderr, "creating '%s'\n", tmpfile);
  289.  
  290.     if (close (creat (tmpfile, 0644)) < 0)
  291.     {                       /* create and/or zero the file */
  292.         fprintf (stderr, "could not creat '%s':  ", tmpfile);
  293.         perror ("");
  294.         cleanup (-1);
  295.     }
  296.     chmod (tmpfile, 0644);  /* in case umask screwed us */
  297.  
  298.     (void) sprintf (tmpfile, "%s$.dir", dbfile);
  299.     if(Debug)
  300.         fprintf (stderr, "creating '%s'\n", tmpfile);
  301.  
  302.     if (close (creat (tmpfile, 0644)) < 0)
  303.     {                       /* create and/or zero the file */
  304.         fprintf (stderr, "could not creat '%s':  ", tmpfile);
  305.         perror ("");
  306.         cleanup (-1);
  307.     }
  308.     chmod (tmpfile, 0644);  /* in case umask screwed us */
  309.     (void) sprintf (tmpfile, "%s$", dbfile);
  310.     return (dbfinit (tmpfile));
  311.     }
  312.  
  313.     return (dbfinit (dbfile));
  314. }
  315.  
  316. theend (new)               /* cleanup the dbm files */
  317. int new;
  318. {
  319.     char fromfile[100];
  320.     char tofile[100];
  321.  
  322. #ifdef DBMCACHE
  323.     dbmcachedump();
  324. #endif
  325.  
  326.     dbfclose();
  327.  
  328.     if (new)                /* started with fresh files */
  329.     {
  330.     if (Verbose || Debug)
  331.         fprintf(stderr, "Moving to database:  %s\n", dbfile);
  332.  
  333.     (void) sprintf (fromfile, "%s$.pag", dbfile);
  334.     (void) sprintf (tofile, "%s.pag", dbfile);
  335.     if (Debug)
  336.         fprintf (stderr, "moving '%s'\n", fromfile);
  337.  
  338.     (void) unlink (tofile);
  339.  
  340.     if ((link (fromfile, tofile ) < 0) || (unlink (fromfile) < 0))
  341.     {                       /* create and/or zero the file */
  342.         fprintf (stderr, "could not link to '%s':  ", tofile);
  343.         perror ("");
  344.         cleanup (-1);
  345.     }
  346.  
  347.     (void) sprintf (fromfile, "%s$.dir", dbfile);
  348.     (void) sprintf (tofile, "%s.dir", dbfile);
  349.     if(Debug)
  350.         fprintf (stderr, "moving '%s'\n", fromfile);
  351.  
  352.     (void) unlink (tofile);
  353.  
  354.     if ((link (fromfile, tofile ) < 0) || (unlink (fromfile) < 0))
  355.     {                       /* create and/or zero the file */
  356.         fprintf (stderr, "could not link to '%s':  ", tofile);
  357.         perror ("");
  358.         cleanup (-1);
  359.     }
  360.  
  361.     return (TRUE);
  362.     }
  363.  
  364.     return (TRUE);
  365. }
  366.  
  367. /*
  368.  * Initialize the dbm file.
  369.  * Fetch the local name datum
  370.  * Init to 1 and store it if there is no datum by that name.
  371.  */
  372.  
  373. dbfinit(filename)
  374. char *filename;
  375. {
  376.     if(dbminit(filename) < 0)
  377.     {
  378.         fprintf (stderr, "could not initialize data base '%s'", filename);
  379.         perror("");
  380.         return (0);
  381.     }
  382.     return (1);
  383. }
  384.  
  385. /*
  386.  * Close the dbm datafile.
  387.  * We can't close the file because the library does not provide the call...
  388.  */
  389.  
  390. dbfclose()
  391. {
  392.     return (1);
  393. }
  394.  
  395. /*
  396.  *      Process a sequential file and insert items into the database
  397.  *      Opens argument assumes database is initialized.
  398.  */
  399.  
  400. process (tblptr)
  401.     Table *tblptr;
  402. {
  403.     datum key, value;
  404.     char tbkey[LINESIZE],
  405.      tbvalue[LINESIZE];
  406.     char *cp;
  407.  
  408.     if (Verbose || Debug)
  409.     fprintf (stderr, tblptr -> tb_fp == (FILE *)EOF ?
  410.         "%s (%s) already done\n" : "%s (%s)\n",
  411.         tblptr -> tb_show, tblptr -> tb_name);
  412.     if (tblptr -> tb_fp == (FILE *)EOF)
  413.     return;
  414.  
  415. #ifdef NAMESERVER
  416.     if ((tblptr -> tb_flags & TB_SRC) == TB_NS) {
  417.         if (Debug || Verbose)
  418.         fprintf (stderr, "   (Nameserver table)\n");
  419.     return;
  420.     }
  421. #endif /* NAMESERVER */
  422.     if (!tb_open (tblptr, TRUE)) /* gain access to a channel table */
  423.     {
  424.     fprintf (stderr, "could not open table \"%s\" (%s, file = '%s'):\n\t",
  425.             tblptr -> tb_show, tblptr -> tb_name,
  426.             tblptr -> tb_file);
  427.     perror("");
  428.     tblptr -> tb_fp = (FILE *) EOF;        /* Don't try again */
  429.         if (keepgoing)
  430.             return;
  431.         cleanup(-1);
  432.     }
  433.  
  434.     while (tb_read (tblptr, tbkey, tbvalue))
  435.     {                           /* read a table's record        */
  436.     switch (tbkey[0])
  437.     {
  438.         case '\0':
  439.         case '#':
  440.         case ';':
  441.         continue;       /* empty lines and comments ok */
  442.     }
  443.  
  444.     if(tbvalue[0] == '\0')
  445.     {                       /* empty value field            */
  446.         value.dptr = "";
  447.         value.dsize = 1;
  448.     }
  449.     else
  450.     {
  451.         value.dptr = tbvalue;
  452.         value.dsize = strlen (tbvalue) + 1;
  453.     }
  454.         for (cp = tbkey; *cp != 0; cp++)
  455.             *cp = uptolow(*cp);            /* All keys are lower case */
  456.     key.dptr = tbkey;
  457.     key.dsize = strlen (tbkey) + 1;
  458.     if(Debug)
  459.         fprintf (stderr, "(%d)'%s': (%d)'%s'\n",
  460.              key.dsize, key.dptr, value.dsize, value.dptr);
  461.     install(key, value, tblptr -> tb_name);
  462.     }
  463.  
  464.     if (ferror (tblptr -> tb_fp))
  465.     {
  466.     fprintf (stderr, "i/o error with table %s (%s, file = %s):  ",
  467.                 tblptr -> tb_show, tblptr -> tb_name,
  468.                 tblptr -> tb_file);
  469.     perror ("");
  470.     }
  471.     tb_close (tblptr);
  472.     tblptr -> tb_fp = (FILE *) EOF;        /* Don't try again */
  473. }
  474.  
  475. /*
  476.  * Install a datum into the database..
  477.  * Fetch entry first to see if we have to append
  478.  * name for building entry.
  479.  */
  480.  
  481. install(key, value, tbname)
  482. datum key, value;
  483. char tbname[];
  484. {
  485.     datum old;
  486.     char newentry[ENTRYSIZE];
  487.     register char *p;
  488.  
  489.     p = newentry;
  490.     old = fetch (key);
  491.     if (old.dptr != NULL) {
  492.     if (Debug) {
  493.         fprintf (stderr, "\tFound old entry\n\t");
  494.         prdatum (old);
  495.     }
  496.  
  497.     p = blt (old.dptr, p, old.dsize - 1);
  498.     *p++ = FS;            /* end with a record seperator */
  499.     }
  500.     p = blt (tbname, p, strlen (tbname));
  501.     *p++ = ' ';
  502.     p = blt (value.dptr, p, value.dsize);
  503.  
  504.     old.dptr = newentry;
  505.     old.dsize = p - newentry;
  506.     if (Debug) {
  507.     fprintf (stderr, "\tNew datum\n\t");
  508.     prdatum (old);
  509.     }
  510.     if (store (key, old) < 0) {          /* put the datum back */
  511.     fprintf (stderr, "dbmbuild, install:  store failed; key='%s', value=",
  512.                                 key.dptr);
  513.     prdatum (old);
  514.     cleanup (NOTOK);
  515.     }
  516.     return (1);
  517. }
  518. /*
  519.  *      Print a datum.
  520.  *      Takes the datum argument and prints it so that we can read
  521.  *      it as either a key or an entry.
  522.  */
  523.  
  524. prdatum(value)
  525. datum value;
  526. {
  527.     int cnt;
  528.     char data[512];
  529.  
  530.     blt (value.dptr, data, value.dsize);
  531.  
  532.     for (cnt = 0; cnt < value.dsize; cnt++) {
  533.         if (value.dptr[cnt] >= ' ' && value.dptr[cnt] <= '~')
  534.             putc (value.dptr[cnt], stderr);
  535.         else
  536.             fprintf (stderr, "<\\%03o>", value.dptr[cnt]);
  537.     }
  538.     putc ('\n', stderr);
  539. }
  540.  
  541. check (tblptr)
  542. Table *tblptr;
  543. {
  544. #ifdef NAMESERVER
  545.     if ((tblptr -> tb_flags & TB_SRC) == TB_NS)
  546.     return(0);
  547. #endif /* NAMESERVER */
  548.     if (tblptr -> tb_fp == (FILE *)EOF)
  549.     return(1);        /* We already know its bad */
  550.     if (!tb_open (tblptr, TRUE)) /* gain access to a channel table */
  551.     {
  552.     fprintf (stderr, "could not open table \"%s\" (%s, file = '%s'):\n\t",
  553.             tblptr -> tb_show, tblptr -> tb_name,
  554.             tblptr -> tb_file);
  555.     perror("");
  556.     tblptr -> tb_fp = (FILE *) EOF;
  557.     return(1);
  558.     }
  559.     tb_close (tblptr);
  560.     tblptr -> tb_fp = (FILE *) NULL;
  561.     return(0);
  562. }
  563.  
  564. cleanup (exitval)
  565. int     exitval;
  566. {
  567.     lk_close (lckfd, dblock, (char *)0, (char *)0);
  568.     exit (exitval == TRUE? 0 : 1);    /* TRUE is non-zero */
  569. }
  570.