home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 400-499 / ff473.lzh / CNewsSrc / cnews_src.lzh / relay / active.c next >
C/C++ Source or Header  |  1990-05-28  |  5KB  |  244 lines

  1. /* :ts=4
  2.  * active file access functions
  3.  *
  4.  *    $Log$
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #ifdef unix
  10. # include <sys/types.h>
  11. # include <sys/stat.h>
  12. #endif /* unix */
  13. #include "libc.h"
  14. #include "news.h"
  15. #include "config.h"
  16. #include "active.h"
  17.  
  18. /* ordinal numbers of fields */
  19. #define CURRFIELD 2        /* current article # */
  20. #define FLAGFIELD 4        /* y/n/m/x/= flag */
  21.  
  22. /* flag field values */
  23. #define FLAGOKAY 'y'        /* ordinary unmoderated group */
  24. #define FLAGBAD 'n'        /* unmoderated but locally-restricted group */
  25. #define FLAGMOD 'm'        /* moderated group */
  26. #define FLAGNEVER 'x'        /* unwanted group: don't file in this one */
  27. #define FLAGGOTO '='        /* see another group (following) instead */
  28.  
  29. /* imports */
  30. extern char *actfind();
  31. extern statust actfload(), actfsync(), actfwrnum();
  32.  
  33. /* forwards */
  34. extern char *findflag();
  35. FORWARD char *fieldfind();
  36.  
  37. /* exports */
  38. char actrelnm[] = "active";
  39.  
  40. static FILE *actfp = NULL;
  41. static struct lastngcache {
  42.     char *lnc_ng;            /* newsgroup name */
  43.     char *lnc_line;            /* matching active file line */
  44. } lnc = { NULL, NULL };
  45.  
  46. /*
  47.  * return a pointer to the active file entry for ng
  48.  * (or a pointed-to group (by ``=group'')), or 0 if no entry exists.
  49.  * since actlook is called repeatedly for the same newsgroup,
  50.  * actlook caches the last newsgroup looked-up and the result.
  51.  */
  52. STATIC char *
  53. actlook(ang)
  54. register char *ang;
  55. {
  56.     register char *ngline, *ng, *flag;
  57.     register int loopbreak = 100;
  58.  
  59.     if (lnc.lnc_ng != NULL && STREQ(lnc.lnc_ng, ang))
  60.         return lnc.lnc_line;
  61.  
  62.     if (actload() != ST_OKAY)
  63.         return NULL;
  64.     ng = strsave(ang);
  65.     while ((ngline = actfind(actfp, ng, strlen(ng))) != NULL &&
  66.             (flag = findflag(ngline)) != NULL && *flag == FLAGGOTO &&
  67.                 --loopbreak > 0) {
  68.         free(ng);
  69.         ng = strsvto(flag+1, '\n');    /* follow "=ng" pointer */
  70.     }
  71.     if (loopbreak <= 0)            /* "infinite" loop broken */
  72.         ngline = NULL;
  73.  
  74.     nnfree(&lnc.lnc_ng);
  75.     lnc.lnc_ng = ng;
  76.     lnc.lnc_line = ngline;
  77.     return ngline;
  78. }
  79.  
  80. /*
  81.  * Find the active entry for ng (or a pointed-to group (by ``=group''))
  82.  * and add inc to its 2nd field (highest number).
  83.  * Return the resultant number.
  84.  */
  85. long
  86. incartnum(ng, inc)
  87. char *ng;
  88. int inc;
  89. {
  90.     char testnum[40];
  91.     register char *line = actlook(ng);
  92.     register long nextart = -1;
  93.  
  94.     if (line != NULL) {
  95.         register char *artnum, *pastartnum;
  96.  
  97.         pastartnum = artnum = fieldfind(line, CURRFIELD);
  98.         if (artnum == NULL)
  99.             return nextart;
  100.         while (isascii(*pastartnum) && isdigit(*pastartnum))
  101.             ++pastartnum;
  102.         nextart = atol(artnum) + inc;
  103.  
  104.         /* update active file article # in place, from nextart */
  105.         if (pastartnum-artnum > sizeof testnum ||
  106.             !ltozan(testnum, nextart, pastartnum-artnum) ||
  107.             !ltozan(artnum, nextart, pastartnum-artnum)) {
  108.             (void) fprintf(stderr,
  109. "%s: article number (%ld) too big for group `%s' active field of %d digits\n",
  110.                 progname, nextart, ng, pastartnum-artnum);
  111.             return -1;
  112.         }
  113.  
  114.         /* give the implementation a chance to write line to disk */
  115.         if (actfwrnum(actfp, line) != ST_OKAY) {
  116.             warning("can't update active file", "");
  117.             nextart = -1;
  118.         }
  119.     }
  120.     return nextart;
  121. }
  122.  
  123. /*
  124.  * Reload the active file cache.
  125.  */
  126. statust
  127. actload()
  128. {
  129.     register statust status = ST_OKAY;
  130.  
  131.     if (actfp == NULL &&
  132.         (actfp = fopenwclex(ctlfile(actrelnm), "r+")) == NULL)
  133.         status |= ST_DROPPED;
  134.     status |= actfload(actfp);
  135.     return status;
  136. }
  137.  
  138. /*
  139.  * Write back to disk the active file cache, if any, and flush the
  140.  * last-newsgroup-cache, since it refers to the (now invalid) active file cache.
  141.  */
  142. statust
  143. actsync()
  144. {
  145.     register statust status = ST_OKAY;
  146.  
  147.     if (actfp != NULL) {
  148.         nnfree(&lnc.lnc_ng);
  149.         lnc.lnc_ng = lnc.lnc_line = NULL;
  150.         status |= actfsync(actfp);
  151.         if (nfclose(actfp) == EOF || status != ST_OKAY) {
  152.             warning("error writing `%s'", ctlfile(actrelnm));
  153.             status |= ST_DROPPED;
  154.         }
  155.     }
  156.     actfp = NULL;
  157.     return status;
  158. }
  159.  
  160. /*
  161.  * Return YES iff any group in ngs (or a pointed-to group (by ``=group''))
  162.  * matches thisflag.
  163.  */
  164. boolean
  165. isflag(ngs, thisflag)
  166. register char *ngs;
  167. int thisflag;
  168. {
  169.     register char *newng, *flag, *ng;
  170.     register boolean result = NO;
  171.  
  172.     for (ng = ngs; !result && ng != NULL; ng = newng) {
  173.         newng = strchr(ng, NGSEP);
  174.         if (newng != NULL)
  175.             *newng = '\0';        /* restored below */
  176.  
  177.         flag = findflag(actlook(ng));
  178.         if (flag != NULL && *flag == thisflag)
  179.             result = YES;
  180.  
  181.         if (newng != NULL)
  182.             *newng++ = NGSEP;    /* point at next group */
  183.     }
  184.     return result;
  185. }
  186.  
  187. STATIC char *
  188. fieldfind(ngline, fieldno)    /* return address of field "fieldno" in ngline */
  189. register char *ngline;
  190. register int fieldno;
  191. {
  192.     register int field;
  193.  
  194.     for (field = 1; ngline != NULL && field < fieldno; ++field) {
  195.         ngline = strchr(ngline, ' ');
  196.         if (ngline != NULL)
  197.             ngline++;        /* point at next field */
  198.     }
  199.     return ngline;
  200. }
  201.  
  202. char *
  203. findflag(ngline)        /* return address of flag field in ngline */
  204. register char *ngline;
  205. {
  206.     return fieldfind(ngline, FLAGFIELD);
  207. }
  208.  
  209. /*
  210.  * Are any groups in ngs moderated?
  211.  */
  212. boolean
  213. moderated(ngs)
  214. register char *ngs;
  215. {
  216.     return isflag(ngs, FLAGMOD);
  217. }
  218.  
  219. /*
  220.  * Are any groups in ngs unwanted?
  221.  */
  222. boolean
  223. unwanted(ngs)
  224. register char *ngs;
  225. {
  226.     return isflag(ngs, FLAGNEVER);
  227. }
  228.  
  229. /*
  230.  * Return 0 or a malloced newsgroup name corresponding to "ong",
  231.  * but without an "=" flag in its active file entry.
  232.  * This is done by tracing the chain of "=ng" pointers (in actlook()), if any.
  233.  */
  234. char *
  235. realngname(ong)
  236. char *ong;
  237. {
  238.     register char *ngline = actlook(ong);
  239.  
  240.     if (ngline == NULL)
  241.         return NULL;            /* no such ong */
  242.     return strsvto(ngline, ' ');
  243. }
  244.