home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / cnews.tar / relay / active.c next >
C/C++ Source or Header  |  1993-03-13  |  6KB  |  250 lines

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