home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / dnews / group.c < prev    next >
C/C++ Source or Header  |  1990-09-29  |  9KB  |  518 lines

  1.  
  2. /*
  3.  *  GROUP.C
  4.  *
  5.  */
  6.  
  7. #include "defs.h"
  8.  
  9. Prototype void LoadGroups(char *);
  10. Prototype void UnloadGroups(char *);
  11. Prototype void CreateNewsrc(char *);
  12. Prototype void RangeAdd(Range **, short, short);
  13. Prototype void RangeDel(Range **, short, short);
  14. Prototype int  NextInRange(Range *, short);
  15. Prototype int  NextNotInRange(Range *, short);
  16.  
  17. Prototype void ClearGroupCache(NGroup *);
  18. Prototype FNode **FindFNCache(FNode **, long);
  19. Prototype void AddFNCache(FNode **, long, char *);
  20.  
  21. Local void  cns_tag(char *, char *, FILE *);
  22. Local char  *fgetstring(FILE *);
  23. Local Range *ReadRange(FILE *);
  24. Local void  WriteRange(FILE *, Range *);
  25. Local void  FreeRange(Range *);
  26. Local void  PrintRange(Range *);
  27. Local long  GetMaxArtNo(char *);
  28. Local void  ClearGroupChain(FNode *);
  29. Local void  CreateFNCache(FNode ***);
  30.  
  31. static FNode    *FreeFNBase;
  32.  
  33. extern NGroup *GBase;
  34.  
  35. /*
  36.  *  LoadGroups()
  37.  *
  38.  *  Load the newsrc file for the specified user and check for new groups
  39.  */
  40.  
  41. void
  42. LoadGroups(user)
  43. char *user;
  44. {
  45.     FILE *fi;
  46.     char buf[64];
  47.     NGroup *ng;
  48.     NGroup **png = &GBase;
  49.  
  50.     sprintf(buf, "%s.dnewsrc", user);
  51.     if (fi = openlib(buf)) {
  52.     short c;
  53.     while ((c = fgetc(fi)) != EOF) {
  54.         switch(c) {
  55.         case '\n':
  56.         continue;
  57.         case 'y':
  58.         case 'n':
  59.         ng = malloc(sizeof(NGroup));
  60.         setmem(ng, sizeof(NGroup), 0);
  61.         if (c == 'y')
  62.             ng->Enabled = 1;
  63.         ng->Name = fgetstring(fi);
  64.         ng->RList= ReadRange(fi);
  65.         ng->MList= ReadRange(fi);
  66.         ng->KList= ReadRange(fi);
  67.         CreateFNCache(&ng->IdBase);
  68.         CreateFNCache(&ng->RefBase);
  69.  
  70.         ng->CurNo = NextNotInRange(ng->RList, 0);
  71.         ng->MaxNo = GetMaxArtNo(ng->Name);
  72.         if (ng->CurNo > ng->MaxNo)
  73.             ng->CurNo = ng->MaxNo;
  74.  
  75.         while (ng->CurNo < ng->MaxNo && !FileExists(FileForArticle(ng, ng->CurNo))) {
  76.             RangeAdd(&ng->RList, ng->CurNo, ng->CurNo);
  77.             ng->CurNo = NextNotInRange(ng->RList, ng->CurNo);
  78.         }
  79.  
  80.         *png = ng;
  81.         png = &ng->Next;
  82.         break;
  83.         default:
  84.         puts("dnewsrc format error");
  85.         break;
  86.         }
  87.  
  88.         /*
  89.          *    skip to next newline.
  90.          */
  91.  
  92.         while ((c = fgetc(fi)) != EOF && c != '\n');
  93.     }
  94.     *png = NULL;
  95.     fclose(fi);
  96.     }
  97. }
  98.  
  99. void
  100. UnloadGroups(user)
  101. char *user;
  102. {
  103.     FILE *fi;
  104.     char buf[64];
  105.     NGroup *grp;
  106.     NGroup *gnext;
  107.  
  108.     sprintf(buf, "%s.dnewsrc", user);
  109.     fi = openlib_write(buf);
  110.     if (fi == NULL)
  111.     printf("Unable to open %s\n", buf);
  112.     for (grp = GBase; grp; grp = gnext) {
  113.     gnext = grp->Next;
  114.  
  115.     if (fi) {
  116.         if (grp->Enabled)
  117.         fputc('y', fi);
  118.         else
  119.         fputc('n', fi);
  120.         fprintf(fi, " %-20s ", grp->Name);
  121.         WriteRange(fi, grp->RList);
  122.         fputc(' ', fi);
  123.         WriteRange(fi, grp->MList);
  124.         fputc(' ', fi);
  125.         WriteRange(fi, grp->KList);
  126.         fputc('\n', fi);
  127.     }
  128.     free(grp->Name);
  129.     FreeRange(grp->RList);
  130.     FreeRange(grp->MList);
  131.     FreeRange(grp->KList);
  132.     free(grp);
  133.     }
  134.     if (fi)
  135.     fclose(fi);
  136.     GBase = NULL;
  137. }
  138.  
  139. /*
  140.  *  Create a new Newsrc file for a user
  141.  */
  142.  
  143. void
  144. CreateNewsrc(user)
  145. char *user;
  146. {
  147.     char buf[64];
  148.     FILE *fi;
  149.  
  150.     sprintf(buf, "%s.dnewsrc", user);
  151.     if (fi = openlib_write(buf)) {
  152.     ScanNewsDirs(cns_tag, fi);
  153.     fclose(fi);
  154.     }
  155. }
  156.  
  157. static void
  158. cns_tag(path, tail, fi)
  159. char *path;
  160. char *tail;
  161. FILE *fi;
  162. {
  163.     FILE *fj;
  164.  
  165.     sprintf(TmpBuf, "%s/.next", path);
  166.     if (fj = fopen(TmpBuf, "r")) {
  167.     int artno;
  168.     if (fscanf(fj, "%d", &artno) == 1) {
  169.         artno -= 50;
  170.         if (artno < 0)
  171.         artno = 0;
  172.         fprintf(fi, "y %-20s 0-%d - -\n", tail, artno);
  173.         printf("Adding %s\n", tail);
  174.     }
  175.     fclose(fj);
  176.     }
  177. }
  178.  
  179. /*
  180.  *  support
  181.  */
  182.  
  183. static char *
  184. fgetstring(fi)
  185. FILE *fi;
  186. {
  187.     char buf[128];
  188.     short i = 0;
  189.     short c;
  190.  
  191.     while ((c = fgetc(fi)) == ' ' || c == 9);
  192.     while (c != EOF && c != ' ' && c != 9 && i < sizeof(buf) - 1) {
  193.     buf[i++] = c;
  194.     c = fgetc(fi);
  195.     }
  196.     buf[i] = 0;
  197.     if (c != EOF)
  198.     ungetc(c, fi);
  199.     return(strdup(buf));
  200. }
  201.  
  202. static Range *
  203. ReadRange(fi)
  204. FILE *fi;
  205. {
  206.     Range *rb;
  207.     Range **rp = &rb;
  208.     short c;
  209.     short is, ie;
  210.  
  211.     while ((c = fgetc(fi)) == ' ' || c == 9);
  212.     if (c == '-')       /*  no range    */
  213.     return(NULL);
  214.     while (c != EOF) {
  215.     is = 0;
  216.     while (c >= '0' && c <= '9') {
  217.         is = is * 10 + c - '0';
  218.         c = getc(fi);
  219.     }
  220.     if (c == '-') {
  221.         ie = 0;
  222.         c = getc(fi);
  223.         while (c >= '0' && c <= '9') {
  224.         ie = ie * 10 + c - '0';
  225.         c = getc(fi);
  226.         }
  227.     } else {
  228.         ie = is;
  229.     }
  230.     {
  231.         Range *r = malloc(sizeof(Range));
  232.         r->SNo = is;
  233.         r->ENo = ie;
  234.         *rp = r;
  235.         rp = &r->Next;
  236.     }
  237.     if (c != ',')
  238.         break;
  239.     c = fgetc(fi);
  240.     }
  241.     if (c != EOF)
  242.     ungetc(c, fi);
  243.     *rp = NULL;
  244.     return(rb);
  245. }
  246.  
  247. static void
  248. WriteRange(fi, r)
  249. FILE *fi;
  250. Range *r;
  251. {
  252.     short first = 1;
  253.  
  254.     if (r == NULL) {
  255.     fputc('-', fi);
  256.     return;
  257.     }
  258.     while (r) {
  259.     if (!first)
  260.         putc(',', fi);
  261.     if (r->SNo == r->ENo)
  262.         fprintf(fi, "%d", r->SNo);
  263.     else
  264.         fprintf(fi, "%d-%d", r->SNo, r->ENo);
  265.     first = 0;
  266.     r = r->Next;
  267.     }
  268. }
  269.  
  270. void
  271. RangeAdd(rp, sno, eno)
  272. Range **rp;
  273. short sno;
  274. short eno;
  275. {
  276.     Range *r;
  277.     Range *rn;
  278.  
  279.     for (r = *rp; r; r = *rp) {
  280.     if (eno < r->SNo - 1) {     /*  insert before   */
  281.         rn = malloc(sizeof(Range));
  282.         *rp = rn;
  283.         rn->Next = r;
  284.         rn->SNo = sno;
  285.         rn->ENo = eno;
  286.         return;
  287.     }
  288.     if (sno <= r->ENo + 1) {     /*  extend this ran */
  289.         if (sno < r->SNo)
  290.         r->SNo = sno;
  291.         if (eno > r->ENo)
  292.         r->ENo = eno;
  293.  
  294.         /*
  295.          *    delete/combine later rans that the new range overlaps
  296.          */
  297.         while ((rn = r->Next) && r->ENo >= rn->SNo - 1) {
  298.         if (r->ENo < rn->ENo)
  299.             r->ENo = rn->ENo;
  300.         r->Next = rn->Next;
  301.         free(rn);
  302.         }
  303.         return;
  304.     }
  305.     rp = &r->Next;
  306.     }
  307.     /*
  308.      *    Append to end
  309.      */
  310.     rn = malloc(sizeof(Range));
  311.     rn->Next = NULL;
  312.     rn->SNo = sno;
  313.     rn->ENo = eno;
  314.     *rp = rn;
  315. }
  316.  
  317. void
  318. RangeDel(rp, sno, eno)
  319. Range **rp;
  320. short sno;
  321. short eno;
  322. {
  323.     Range *r;
  324.     Range *rn;
  325.  
  326.     for (r = *rp; r; r = *rp) {
  327.     if (sno <= r->ENo && eno >= r->SNo) {
  328.         if (sno <= r->SNo && eno >= r->ENo) {   /*  delete entirely */
  329.         *rp = r->Next;
  330.         free(r);
  331.         continue;
  332.         } else if (sno > r->SNo && eno < r->ENo) {  /*  split   */
  333.         rn = malloc(sizeof(Range));
  334.         rn->Next = r->Next;
  335.         r->Next = rn;
  336.         rn->ENo = r->ENo;
  337.         r->ENo = sno - 1;
  338.         rn->SNo = eno + 1;
  339.         break;
  340.         } else if (sno <= r->SNo) {              /*  else reduce an end */
  341.         r->SNo = eno + 1;
  342.         } else if (eno >= r->ENo) {
  343.         r->ENo = sno - 1;
  344.         }
  345.     } else {
  346.         if (eno < r->SNo)   /*  done    */
  347.         break;
  348.     }
  349.     rp = &r->Next;
  350.     }
  351. }
  352.  
  353. /*
  354.  *  Returns index after idx that is in the range
  355.  */
  356.  
  357. int
  358. NextInRange(r, idx)
  359. Range *r;
  360. short idx;
  361. {
  362.     while (r && idx >= r->ENo)
  363.     r = r->Next;
  364.     if (r) {
  365.     if (idx < r->SNo)
  366.         return(r->SNo);
  367.     return(idx + 1);
  368.     }
  369.     return(-1);
  370. }
  371.  
  372. /*
  373.  *  Returns index after idx that is not in the range
  374.  */
  375.  
  376. int
  377. NextNotInRange(r, idx)
  378. Range *r;
  379. short idx;
  380. {
  381.     while (r && idx >= r->ENo)
  382.     r = r->Next;
  383.     if (r) {
  384.     if (idx < r->SNo - 1)
  385.         return(idx + 1);
  386.     return(r->ENo + 1);
  387.     }
  388.     return(idx + 1);
  389. }
  390.  
  391. static void
  392. FreeRange(r)
  393. Range *r;
  394. {
  395.     Range *rn;
  396.  
  397.     while (r) {
  398.     rn = r->Next;
  399.     free(r);
  400.     r = rn;
  401.     }
  402. }
  403.  
  404.  
  405. /*
  406.  *  debugging
  407.  */
  408.  
  409. static void
  410. PrintRange(r)
  411. Range *r;
  412. {
  413.     WriteRange(stdout, r);
  414.     puts("");
  415. }
  416.  
  417. static long
  418. GetMaxArtNo(group)
  419. char *group;
  420. {
  421.     FILE *fi;
  422.     int max = 0;
  423.  
  424.     sprintf(TmpBuf, "%s/.next", MakeConfigPath(UUNEWS, group));
  425.     if (fi = fopen(TmpBuf, "r")) {
  426.     fscanf(fi, "%d", &max);
  427.     fclose(fi);
  428.     }
  429.     return(max);
  430. }
  431.  
  432. /*
  433.  *  References: and Message-ID: cache
  434.  */
  435.  
  436. void
  437. ClearGroupCache(grp)
  438. NGroup *grp;
  439. {
  440.     FNode **fn;
  441.     short i;
  442.  
  443.     if (grp->IdBase) {
  444.     for (fn = grp->IdBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
  445.         ClearGroupChain(*fn);
  446.         *fn = NULL;
  447.     }
  448.     }
  449.  
  450.     if (grp->RefBase) {
  451.     for (fn = grp->RefBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
  452.         ClearGroupChain(*fn);
  453.         *fn = NULL;
  454.     }
  455.     }
  456.  
  457. }
  458.  
  459. void
  460. ClearGroupChain(fn)
  461. FNode *fn;
  462. {
  463.     FNode *fnext;
  464.  
  465.     while (fn) {
  466.     fnext = fn->Next;
  467.     if (fn->Id)
  468.         free(fn->Id);
  469.     free(fn);
  470.     fn = fnext;
  471.     }
  472. }
  473.  
  474. void
  475. CreateFNCache(pht)
  476. FNode ***pht;
  477. {
  478.     if (*pht == NULL) {
  479.     *pht = malloc(FNHASHSIZE * sizeof(FNode *));
  480.     setmem(*pht, FNHASHSIZE * sizeof(FNode *), 0);
  481.     }
  482. }
  483.  
  484. FNode **
  485. FindFNCache(htab, msgno)
  486. FNode **htab;
  487. {
  488.     FNode **pfn = htab + (msgno & FNHASHMASK);
  489.     FNode *fn;
  490.  
  491.     if (htab == NULL)
  492.     return(NULL);
  493.     while (fn = *pfn) {
  494.     if (fn->MsgNo == msgno)
  495.         break;
  496.     pfn = &fn->Next;
  497.     }
  498.     return(pfn);
  499. }
  500.  
  501. void
  502. AddFNCache(pfn, msgno, id)
  503. FNode **pfn;
  504. long msgno;
  505. char *id;
  506. {
  507.     FNode *fn = malloc(sizeof(FNode));
  508.  
  509.     if (fn) {
  510.     *pfn = fn;
  511.     fn->MsgNo = msgno;
  512.     fn->Id = id;
  513.     fn->Next = NULL;
  514.     }
  515. }
  516.  
  517.  
  518.