home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff319.lzh / CNewsSrc / cnews.orig.lzh / libbig / active.fast.c next >
C/C++ Source or Header  |  1989-06-27  |  4KB  |  157 lines

  1. /*
  2.  * active file access functions (big, fast, in-memory version)
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include "libc.h"
  9. #include "news.h"
  10. #include "config.h"
  11. #include "active.h"
  12.  
  13. /* private */
  14. static char *active = NULL;    /* cache: points at entire active file */
  15. static int actsize;        /* bytes in active: type int fixed by fread */
  16. static char **actlnps;        /* point at lines in active file */
  17. static unsigned actlines;    /* lines in actlnps actually used */
  18.  
  19. /* imports from active.c */
  20. extern char actrelnm[];
  21.  
  22. /* forwards */
  23. FORWARD statust actmkindx();
  24.  
  25. statust
  26. actfload(fp)
  27. FILE *fp;
  28. {
  29.     statust status = ST_OKAY;
  30.  
  31.     if (fp != NULL && active == NULL) {
  32.         struct stat sb;
  33.  
  34.         errno = 0;
  35.         if (fstat(fileno(fp), &sb) < 0)
  36.             warning("can't fstat `%s'", ctlfile(actrelnm));
  37.         else if (actsize = sb.st_size, /* squeeze into an int */
  38.             (unsigned)actsize != sb.st_size)
  39.             warning("`%s' won't fit into memory", ctlfile(actrelnm));
  40.         else if ((active = malloc((unsigned)actsize+1)) == NULL)
  41.             warning("can't allocate memory for `%s'",
  42.                 ctlfile(actrelnm));
  43.         else {
  44.             rewind(fp);
  45.             /*
  46.              * If we read with fgetms, we might be able to avoid
  47.              * calling linescan().
  48.              */
  49.             if (fread(active, 1, actsize, fp) != actsize) {
  50.                 warning("error reading `%s'", ctlfile(actrelnm));
  51.                 status |= ST_DROPPED;
  52.             } else
  53.                 status |= actmkindx();
  54.         }
  55.         if (active == NULL)
  56.             status |= ST_DROPPED;    /* give up! */
  57.         if (status != ST_OKAY) {
  58.             nnfree(&active);
  59.             nnafree(&actlnps);
  60.         }
  61.     }
  62.     return status;
  63. }
  64.  
  65. static statust
  66. actmkindx()            /* build actlnps index for active */
  67. {
  68.     register statust status = ST_OKAY;
  69.     unsigned lnpsz;
  70.     int maxlines;
  71.  
  72.     active[actsize] = '\0';        /* make a proper string */
  73.     /* +1 for a possible partial line +1 for a dummy to check overflow */
  74.     maxlines = charcount(active, '\n') + 2;
  75.     lnpsz = sizeof(char *) * (long) maxlines;
  76.     if (lnpsz != sizeof(char *) * (long)maxlines ||
  77.         (actlnps = (char **)malloc(lnpsz)) == NULL) {
  78.         warning("`%s' index won't fit in memory", ctlfile(actrelnm));
  79.             status |= ST_DROPPED;
  80.     } else {
  81.         actlnps[maxlines - 2] = "";    /* in case no partial line */
  82.         actlnps[maxlines - 1] = "";    /* end sentinel */
  83.         actlines = linescan(active, actlnps, maxlines);
  84.         if (actlines >= maxlines) {
  85.             (void) fprintf(stderr,
  86.                 "%s: too many newsgroups in `%s' (can't happen)\n",
  87.                 progname, ctlfile(actrelnm));
  88.             status |= ST_DROPPED;
  89.         }
  90.     }
  91.     return status;
  92. }
  93.  
  94. /*
  95.  * Store in lnarray the addresses of the starts of lines in s.
  96.  * Return the number of lines found; if greater than nent,
  97.  * store only nent and return nent.
  98.  * Thus lnarray should be one bigger than needed to detect overflow.
  99.  */
  100. int
  101. linescan(s, lnarray, nent)
  102. char *s;
  103. char **lnarray;
  104. register int nent;
  105. {
  106.     register char **lnarrp = lnarray;
  107.     register int i = 0;
  108.     register char *nlp = s;
  109.  
  110.     if (i < nent)
  111.         *lnarrp++ = nlp;
  112.     while (++i < nent && (nlp = index(nlp, '\n')) != NULL && *++nlp != '\0')
  113.         *lnarrp++ = nlp;
  114.     return i;        /* number of addrs stored */
  115. }
  116.  
  117. statust
  118. actfsync(fp)            /* write to disk, fp is open */
  119. FILE *fp;
  120. {
  121.     statust status = ST_OKAY;
  122.  
  123.     rewind(fp);
  124.     if (active != NULL) {
  125.         if (fwrite(active, actsize, 1, fp) != 1)
  126.             status |= ST_DROPPED;    /* serious loss */
  127.         nnfree(&active);
  128.         nnafree(&actlnps);
  129.     }
  130.     return status;
  131. }
  132.  
  133. /* ARGSUSED fp */
  134. char *
  135. actfind(fp, ng, nglen)
  136. FILE *fp;
  137. register char *ng;
  138. register int nglen;
  139. {
  140.     register char *pos;
  141.     register unsigned line = 0;
  142.  
  143.     while (pos = actlnps[line], line++ < actlines && pos[0] != '\0')
  144.         if (STREQN(pos, ng, nglen) && pos[nglen] == ' ')
  145.             return pos;
  146.     return NULL;
  147. }
  148.  
  149. /* ARGSUSED */
  150. statust
  151. actfwrnum(fp, pos)
  152. FILE *fp;
  153. char *pos;
  154. {
  155.     return ST_OKAY;
  156. }
  157.