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

  1. #include "util.h"
  2. #include "mmdf.h"
  3. #include "ch.h"                   /* has table state strcture def       */
  4. /*
  5.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  6.  *
  7.  *
  8.  *     Copyright (C) 1979,1980,1981  University of Delaware
  9.  *
  10.  *     Department of Electrical Engineering
  11.  *     University of Delaware
  12.  *     Newark, Delaware  19711
  13.  *
  14.  *     Phone:  (302) 738-1163
  15.  *
  16.  *
  17.  *     This program module was developed as part of the University
  18.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  19.  *
  20.  *     Acquisition, use, and distribution of this module and its listings
  21.  *     are subject restricted to the terms of a license agreement.
  22.  *     Documents describing systems using this module must cite its source.
  23.  *
  24.  *     The above statements must be retained with all copies of this
  25.  *     program and may not be removed without the consent of the
  26.  *     University of Delaware.
  27.  *
  28.  *
  29.  *     version  -1    David H. Crocker    March   1979
  30.  *     version   0    David H. Crocker    April   1980
  31.  *     version  v7    David H. Crocker    May     1981
  32.  *     version   1    David H. Crocker    October 1981
  33.  *
  34.  */
  35.  
  36. /*  READ "NETWORK" HOST NAME TABLES
  37.  *
  38.  *  BNF for the file is:
  39.  *
  40.  *      entries =   entries entry
  41.  *      entry   =   name separator value eol
  42.  *      name    =   {string of chars not containing a <separator>}
  43.  *      separator=  {see the chars in _hkeyend[]}
  44.  *      value   =   {string of chars not containing an <eol>}
  45.  *      eol     =   {see the chars in _hvalend[]}
  46.  *
  47.  *      where
  48.  *
  49.  *          name    is a key
  50.  *          value   is any relevant text, usually the host "address"
  51.  *
  52.  *  There may be any number of entries with the same value string,
  53.  *  thereby allowing name aliases, such as UDel-EE, UDel, and UDEE.
  54.  *
  55.  *  The key of the first entry with a given value is taken as the
  56.  *  "official" "name" of that "address".  (Sorry about all the
  57.  *  quotation marks.)
  58.  *
  59.  *  Turns out that the local machine's alias file can also be accessed
  60.  *  by these routines.
  61.  *
  62.  *  Any number of tables may be supported simultaneously, since a
  63.  *  single table's state information structure is maintained externally,
  64.  *  and passed with each call, through the parameter netinfo.
  65.  *  The state structure's place for the file descriptor MUST
  66.  *  initially be zero.
  67.  *
  68.  *  "Hard" failures are considered not acceptable and hence cause a
  69.  *  call to the external routine err_abrt(); to change this policy,
  70.  *  just change the calls to err_abrt() to be simple failure returns.
  71.  *  The rest of the code should run "transparently".
  72.  */
  73.  
  74. /*  Sep 81  Dave Crocker      added ch_tclose & ch_tfree, to allow
  75.  *                            handling file descriptor overflow
  76.  *  May 82  Dave Crocker      add ch_tread, to focus input
  77.  *  Jun 82  Dave Crocker      split ch_tio off from ch_table
  78.  *  Dec 82  Doug Kingston     Fixed bug in tb_read() that caused it to
  79.  *                            ignore EOF's.   (DPK@BRL)
  80.  *  Apr 83  Steve Kille       Change it back again
  81.  */
  82.  
  83. extern struct ll_struct   *logptr;
  84. extern char *tbldfldir;
  85. extern Table **tb_list;         /* all known tables                     */
  86.                 /* SEK change syntax                    */
  87. extern int   tb_numtables;      /* how many of them there are           */
  88. extern char  *index();
  89. extern char  *compress();
  90.  
  91. LOCVAR char _hkeyend[] = ": \t\n\377",
  92.                   /* chars which delimit end of key     */
  93.         _hvalend[] = "\n\000\377";
  94.                   /* chars which delimit end of value   */
  95. LOCVAR short tb_nopen;            /* number of opened file descriptors  */
  96.  
  97. /*  ******************  BASIC FILE ACTION  *************************** */
  98.  
  99. tb_open (table, fromstart)        /* gain access to a table     */
  100.     register Table  *table;       /* table's state information          */
  101.     int     fromstart;            /* ok to reset, if already open?      */
  102. {
  103.     extern int   errno;           /* in case open fails                 */
  104.     char temppath[128];
  105.  
  106.  
  107. /*  currently, there is one file (descriptor) per table.  for a large
  108.  *  configuration, you will run out of fd's.  until/unless you run
  109.  *  a single-file dbm-based version, there is a hack, below, which
  110.  *  limits the number of open file-descriptors to 6.  Trying to open
  111.  *  a 7th will cause a currently-opened one to be closed.
  112.  */
  113.  
  114.     switch ((int)table)
  115.     {
  116.     case 0:
  117.     case NOTOK:
  118.         return (FALSE);       /* can't open what isn't specified    */
  119.     }
  120.     switch ((int)(table -> tb_fp))
  121.     {
  122.     case 0:                   /* not opened yet                     */
  123. /*HACK*/    table -> tb_pos = 0L;
  124.         if (table -> tb_file != 0)
  125.         {                     /* we have a path string              */
  126.         if (tb_nopen < 6 || tb_free ())
  127.         {
  128.             getfpath (table -> tb_file, tbldfldir, temppath);
  129.                   /* add on directory portion           */
  130. #ifdef DEBUG
  131.             ll_log (logptr, LLOGBTR, "opening '%s'", temppath);
  132. #endif
  133.             if ((table -> tb_fp = fopen (temppath, "r")) != NULL)
  134.             {
  135.             tb_nopen++;
  136.             break;    /* all is well                        */
  137.             }
  138.         }
  139.         ll_err (logptr, (errno == ENOENT) ? LLOGPTR : LLOGTMP,
  140.             "Error opening %s name table '%s' (numfiles open = %d)",
  141.                 table -> tb_show, temppath, tb_nopen);
  142.                   /* major only if file exists          */
  143.         }
  144.         table -> tb_fp = (FILE *) EOF;
  145.                   /* no path str -> quietly fail        */
  146.                   /* DROP ON THROUGH                    */
  147.     case NOTOK:
  148.         return (FALSE);       /* failed earlier try                 */
  149.  
  150.     default:
  151.         if (fromstart)        /* always start from beginning?       */
  152.         tb_seek (table, 0L);
  153.     }
  154.     return (TRUE);
  155. }
  156. /* */
  157.  
  158. tb_close (table)                  /* close  a table                     */
  159. register Table *table;
  160. {
  161.     switch ((int)table)
  162.     {
  163.     case 0:
  164.     case NOTOK:
  165.         return (FALSE);       /* can't close what isn't specified   */
  166.     }
  167.     switch ((int)(table -> tb_fp))
  168.     {
  169.     case NOTOK:
  170.         table -> tb_fp = 0; /* mark as free                       */
  171.     case 0:                   /* not opened yet                     */
  172.         return (FALSE);       /* no close performed                 */
  173.  
  174.     default:
  175.         fclose (table -> tb_fp);
  176.         table -> tb_fp = 0; /* mark as free                       */
  177.         tb_nopen--;
  178.         return (TRUE);
  179.     }
  180.     /* NOTREACHED */
  181. }
  182.  
  183. tb_free ()                       /* create a free file descriptor      */
  184. {
  185. /*  step from the lowest search priority to the highest, looking for a
  186.  *  channel to close.  return success as soon as one is done.
  187.  */
  188.     register Table **tableptr;
  189. #ifdef DEBUG
  190.     ll_log (logptr, LLOGFTR, "tb_free ()");
  191. #endif
  192.     for (tableptr = tb_list + tb_numtables - 1;
  193.                     tableptr >=  tb_list; tableptr--)
  194.     {
  195.     if (tb_close (*tableptr))
  196.         return (TRUE);        /* got a channel closed               */
  197.     }
  198.     return (FALSE);               /* couldn't get any closed            */
  199. }
  200.  
  201. tb_seek (table, thepos)           /* reset table position               */
  202. register Table *table;
  203. long thepos;
  204. {
  205.     switch ((int)table)
  206.     {
  207.     case 0:
  208.     case NOTOK:
  209.         return (NOTOK);       /* can't open what isn't specified    */
  210.     }
  211.     switch ((int)(table -> tb_fp))
  212.     {                             /* not opened yet                     */
  213.     case NULL:
  214.     case EOF:
  215.         return (NOTOK);
  216.     }
  217.     fseek (table -> tb_fp, thepos, 0);
  218. /*HACK*/ table -> tb_pos = thepos;
  219.     return ((ferror (table -> tb_fp)) ? NOTOK : OK);
  220. }
  221. /*  *****************  READ THE NAME TABLE  ************************** */
  222.  
  223. /*
  224.  *  This routine used not to recognise comments, this meant that dbmbuild
  225.  *  could skip real records in the following case.
  226.  *  #<NL>
  227.  *  nott:nott
  228.  *  would be read as key = '#' value = 'nott:nott' and dbmbuild would
  229.  *  throw it away as a comment. (JPO)
  230.  */
  231. tb_read (table, key, value)       /* read a table's record        */
  232.     register Table *table;
  233.     char *key,
  234.      *value;
  235. {
  236.     register int len;
  237.     register FILE *fp;
  238.     char terminator;
  239.  
  240.     fp = table -> tb_fp;
  241.  
  242.     if (feof (fp))
  243.     return (FALSE);
  244.  
  245.     while ((len = qread (fp, key, LINESIZE, _hkeyend, '\\')) > 0)
  246.     {
  247. /*HACK*/    table -> tb_pos += len;
  248.     if( key[0] == '\n' )
  249.         continue;        /* blank line */
  250.     if( key[0] == '#' )
  251.         if( key[len - 1] == '\n' )
  252.         continue;   /* have read up to the newline */
  253.         else
  254.         {
  255.         if((len = gcread(fp, value, LINESIZE, _hvalend)) > 0)
  256.         {
  257. /*HACK*/        table -> tb_pos += len;
  258.             continue;    /* skip to end of line */
  259.         }
  260.         else return (FALSE);    /* EOF I guess */
  261.         }
  262.  
  263.         terminator = key[len - 1];
  264.     key[len - 1] = '\0';  /* get rid of terminator character */
  265.     if (len > 1)
  266.         compress (key, key);
  267.  
  268.     if (index(_hvalend, terminator) > (char *)NULL)
  269.          value[0] = '\0';        /* whole line was a key */
  270.         else {
  271.         if ((len = gcread (fp, value, LINESIZE, _hvalend)) > 0)
  272.         {
  273. /*HACK*/    table -> tb_pos += len;
  274.         value[len - 1] = '\0';
  275.         if (len > 1)
  276.             compress (value, value);
  277.         }
  278.         else               /* Don't worry about errors here... */
  279.         value[0] = '\0';
  280.         }
  281.     return (TRUE);
  282.  
  283.     }
  284.     if( len < 0 )        /* (len < 0) indicating IO error */
  285.     err_abrt (RP_FIO, "Error reading %s name table '%s'",
  286.         table -> tb_show, table -> tb_file);
  287.  
  288.     return (FALSE);             /* EOF on entry boundary,  DPK@BRL */
  289. }
  290.