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