home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / UUPC11XT.ZIP / RN / BITS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-21  |  21.2 KB  |  829 lines

  1. /* $Header: E:\SRC\UUPC\RN\RCS/BITS.C 1.1 1992/11/21 06:14:58 ahd Exp $
  2.  *
  3.  * $Log: BITS.C $
  4.  * Revision 1.1  1992/11/21  06:14:58  ahd
  5.  * Initial
  6.  *
  7.  *
  8.  *    Rev 1.0   18 Nov 1990  0:22:02
  9.  * Initial revision.
  10.  * Revision 4.3.2.3  89/11/28  01:52:02  sob
  11.  * Removed some lint.
  12.  *
  13.  * Revision 4.3.2.2  89/11/27  01:30:04  sob
  14.  * Altered NNTP code per ideas suggested by Bela Lubkin
  15.  * <filbo@gorn.santa-cruz.ca.us>
  16.  *
  17.  * Revision 4.3.1.4  86/10/31  15:23:53  lwall
  18.  * Separated firstart into two variables so KILL on new articles won't
  19.  * accidentally mark articles read.
  20.  *
  21.  * Revision 4.3.1.3  86/09/09  16:01:43  lwall
  22.  * Fixed 'n more articles' bug.
  23.  *
  24.  * Revision 4.3.1.2  86/07/24  14:40:23  lwall
  25.  * Gets host name from path instead of relay-version for news 2.10.3.
  26.  *
  27.  * Revision 4.3.1.1  85/05/10  11:31:41  lwall
  28.  * Branch for patches.
  29.  *
  30.  * Revision 4.3  85/05/01  11:36:15  lwall
  31.  * Baseline for release with 4.3bsd.
  32.  *
  33.  */
  34.  
  35. #include "EXTERN.h"
  36. #include "common.h"
  37. #include "rcstuff.h"
  38. #include "head.h"
  39. #include "util.h"
  40. #include "final.h"
  41. #include "rn.h"
  42. #include "cheat.h"
  43. #include "ng.h"
  44. #include "artio.h"
  45. #include "intrp.h"
  46. #include "ngdata.h"
  47. #include "rcln.h"
  48. #include "kfile.h"
  49. #include "INTERN.h"
  50. #include "bits.h"
  51.  
  52. #ifdef DBM
  53.  
  54. #ifdef NULL
  55. #undef NULL
  56. #endif                       /* NULL */
  57.  
  58. #include <dbm.h>
  59. #endif                       /* DBM */
  60. MEM_SIZE ctlsize;            /* size of bitmap in
  61.                               * bytes */
  62.  
  63. void
  64.   bits_init()
  65. {
  66.  
  67. #ifdef DELAYMARK
  68.    dmname = savestr(filexp(RNDELNAME));
  69. #else
  70.    ;
  71. #endif
  72. }
  73.  
  74. /* checkpoint the .newsrc */
  75.  
  76. void
  77.   checkpoint_rc()
  78. {
  79.  
  80. #ifdef DEBUGGING
  81.    if (debug & DEB_CHECKPOINTING)
  82.    {
  83.       fputs("(ckpt)", stdout);
  84.       fflush(stdout);
  85.    }
  86. #endif
  87.  
  88.    if (doing_ng)
  89.       restore_ng();          /* do not restore M
  90.                               * articles */
  91.    if (rc_changed)
  92.       write_rc();
  93.  
  94. #ifdef DEBUGGING
  95.    if (debug & DEB_CHECKPOINTING)
  96.    {
  97.       fputs("(done)", stdout);
  98.       fflush(stdout);
  99.    }
  100. #endif
  101. }
  102.  
  103. /* reconstruct the .newsrc line in a human readable form */
  104.  
  105. void
  106.   restore_ng()
  107. {
  108.    register char *s, *mybuf = buf;
  109.    register ART_NUM i;
  110.    ART_NUM count = 0;
  111.    int safelen = LBUFLEN - 16;
  112.  
  113.    strcpy(buf, rcline[ng]);  /* start with the
  114.                               * newsgroup name */
  115.    s = buf + rcnums[ng] - 1; /* use s for buffer
  116.                               * pointer */
  117.    *s++ = rcchar[ng];        /* put the requisite :
  118.                               * or ! */
  119.    *s++ = ' ';               /* put the
  120.                               * not-so-requisite
  121.                               * space */
  122.    for (i = 1; i <= lastart; i++)
  123.    {                         /* for each article in
  124.                               * newsgroup */
  125.       if (s - mybuf > safelen)
  126.       {                      /* running out of room? */
  127.          safelen *= 2;
  128.          if (mybuf == buf)
  129.          {                   /* currently static? */
  130.             int tmp;
  131.  
  132.             *s = '\0';
  133.             mybuf = safemalloc((MEM_SIZE) safelen + 16);
  134.             strcpy(mybuf, buf); /* so we must copy it */
  135.             tmp = s - buf;   /* Stupid MSC4 can't
  136.                               * handle the original */
  137.             s = mybuf + tmp;
  138.             /* fix the pointer, too */
  139.          }
  140.          else
  141.          {                   /* just grow in place,
  142.                               * if possible */
  143.             char *newbuf;
  144.  
  145.             newbuf = saferealloc(mybuf, (MEM_SIZE) safelen + 16);
  146.             s = newbuf + (s - mybuf);
  147.             mybuf = newbuf;
  148.          }
  149.       }
  150.       if (!was_read(i))      /* still unread? */
  151.          count++;            /* then count it */
  152.       else
  153.       {                      /* article was read */
  154.          ART_NUM oldi;
  155.  
  156.          sprintf(s, "%ld", (long) i);   /* put out the min of
  157.                                          * the range */
  158.          s += strlen(s);     /* keeping house */
  159.          oldi = i;           /* remember this spot */
  160.          do
  161.             i++;
  162.          while (i <= lastart && was_read(i));
  163.          /* find 1st unread article or end */
  164.          i--;                /* backup to last read
  165.                               * article */
  166.          if (i > oldi)
  167.          {                   /* range of more than 1? */
  168.             sprintf(s, "-%ld,", (long) i);
  169.             /* then it out as a range */
  170.             s += strlen(s);  /* and housekeep */
  171.          }
  172.          else
  173.             *s++ = ',';      /* otherwise, just a
  174.                               * comma will do */
  175.       }
  176.    }
  177.    if (*(s - 1) == ',')      /* is there a final ','? */
  178.       s--;                   /* take it back */
  179.    *s++ = '\0';              /* and terminate string */
  180.  
  181. #ifdef DEBUGGING
  182.    if (debug & DEB_NEWSRC_LINE && !panic)
  183.    {
  184.       printf("%s: %s\n", rcline[ng], rcline[ng] + rcnums[ng]) FLUSH;
  185.       printf("%s\n", mybuf) FLUSH;
  186.    }
  187. #endif
  188.  
  189.    free(rcline[ng]);         /* return old rc line */
  190.    if (mybuf == buf)
  191.    {
  192.       rcline[ng] = safemalloc((MEM_SIZE) (s - buf) + 1);
  193.       /* grab a new rc line */
  194.       strcpy(rcline[ng], buf);  /* and load it */
  195.    }
  196.    else
  197.    {
  198.       mybuf = saferealloc(mybuf, (MEM_SIZE) (s - mybuf) + 1);
  199.       /* be nice to the heap */
  200.       rcline[ng] = mybuf;
  201.    }
  202.    *(rcline[ng] + rcnums[ng] - 1) = '\0';
  203.    if (rcchar[ng] == NEGCHAR)
  204.    {                         /* did they unsubscribe? */
  205.       printf(unsubto, ngname) FLUSH;
  206.       toread[ng] = TR_UNSUB; /* make line invisible */
  207.    }
  208.    else
  209.       /* NOSTRICT */
  210.       toread[ng] = (ART_UNREAD) count;  /* remember how many
  211.                                          * unread there are */
  212. }
  213.  
  214. /* mark an article unread, keeping track of toread[] */
  215.  
  216. void
  217.   onemore(artnum)
  218.    ART_NUM artnum;
  219. {
  220.  
  221. #ifdef DEBUGGING
  222.    if (debug && artnum < firstbit)
  223.    {
  224.       printf("onemore: %d < %d\n", artnum, firstbit) FLUSH;
  225.       return;
  226.    }
  227. #endif
  228.  
  229.    if (ctl_read(artnum))
  230.    {
  231.       ctl_clear(artnum);
  232.       ++toread[ng];
  233.    }
  234. }
  235.  
  236. /* mark an article read, keeping track of toread[] */
  237.  
  238. void
  239.   oneless(artnum)
  240.    ART_NUM artnum;
  241. {
  242.  
  243. #ifdef DEBUGGING
  244.    if (debug && artnum < firstbit)
  245.    {
  246.       printf("oneless: %d < %d\n", artnum, firstbit) FLUSH;
  247.       return;
  248.    }
  249. #endif
  250.  
  251.    if (!ctl_read(artnum))
  252.    {
  253.       ctl_set(artnum);
  254.       if (toread[ng] > TR_NONE)
  255.          --toread[ng];
  256.    }
  257. }
  258.  
  259. /* mark an article as unread, making sure that firstbit is properly handled */
  260. /* cross-references are left as read in the other newsgroups */
  261.  
  262. void
  263.   unmark_as_read(artnum)
  264.    ART_NUM artnum;
  265. {
  266.    check_first(artnum);
  267.    onemore(artnum);
  268.  
  269. #ifdef MCHASE
  270.    if (!parse_maybe(artnum))
  271.       chase_xrefs(artnum, FALSE);
  272. #endif
  273. }
  274.  
  275. #ifdef DELAYMARK
  276. /* temporarily mark article as read.  When newsgroup is exited, articles */
  277. /* will be marked as unread.  Called via M command */
  278.  
  279. void
  280.   delay_unmark(artnum)
  281.    ART_NUM artnum;
  282. {
  283.    if (dmfp == Nullfp)
  284.    {
  285.       dmfp = fopen(dmname, "w");
  286.       if (dmfp == Nullfp)
  287.       {
  288.          printf(cantcreate, dmname) FLUSH;
  289.          sig_catcher(0);
  290.       }
  291.    }
  292.    oneless(artnum);          /* set the correct bit */
  293.    dmcount++;
  294.    fprintf(dmfp, "%ld\n", (long) artnum);
  295. }
  296.  
  297. #endif
  298.  
  299. /* mark article as read.  If article is cross referenced to other */
  300. /* newsgroups, mark them read there also. */
  301.  
  302. void
  303.   mark_as_read(artnum)
  304.    ART_NUM artnum;
  305. {
  306.    oneless(artnum);          /* set the correct bit */
  307.    checkcount++;             /* get more worried
  308.                               * about crashes */
  309.    chase_xrefs(artnum, TRUE);
  310. }
  311.  
  312. /* make sure we have bits set correctly down to firstbit */
  313.  
  314. void
  315.   check_first(min)
  316.    ART_NUM min;
  317. {
  318.    register ART_NUM i = firstbit;
  319.  
  320.    if (min < absfirst)
  321.       min = absfirst;
  322.    if (min < i)
  323.    {
  324.       for (i--; i >= min; i--)
  325.          ctl_set(i);         /* mark as read */
  326.       firstart = firstbit = min;
  327.    }
  328. }
  329.  
  330. /* bring back articles marked with M */
  331.  
  332. #ifdef DELAYMARK
  333. void
  334.   yankback()
  335. {
  336.    register ART_NUM anum;
  337.  
  338.    if (dmfp)
  339.    {                         /* delayed unmarks
  340.                               * pending? */
  341.  
  342. #ifdef VERBOSE
  343.       printf("\nReturning %ld Marked article%s...\n", (long) dmcount,
  344.              dmcount == 1 ? nullstr : "s") FLUSH;
  345. #endif
  346.  
  347.       fclose(dmfp);
  348.       if ((dmfp = fopen(dmname, "r")) != 0)
  349.       {
  350.          while (fgets(buf, sizeof buf, dmfp) != Nullch)
  351.          {
  352.             anum = (ART_NUM) atol(buf);
  353.             /* NOSTRICT */
  354.             onemore(anum);   /* then unmark them */
  355.  
  356. #ifdef MCHASE
  357.             chase_xrefs(anum, FALSE);
  358. #endif
  359.          }
  360.          fclose(dmfp);
  361.          dmfp = Nullfp;
  362.          UNLINK(dmname);     /* and be tidy */
  363.       }
  364.       else
  365.       {
  366.          printf(cantopen, dmname) FLUSH;
  367.          sig_catcher(0);
  368.       }
  369.    }
  370.    dmcount = 0;
  371. }
  372.  
  373. #endif
  374.  
  375. /* run down xref list and mark as read or unread */
  376.  
  377. int
  378.   chase_xrefs(artnum, markread)
  379.    ART_NUM artnum;
  380.    int markread;
  381. {
  382.  
  383. #ifdef ASYNC_PARSE
  384.    if (parse_maybe(artnum))  /* make sure we have
  385.                               * right header */
  386.       return -1;
  387. #endif
  388.  
  389. #ifdef DBM
  390.    {
  391.       datum lhs, rhs;
  392.       datum fetch();
  393.       register char *idp;
  394.       char *ident_buf;
  395.       static FILE *hist_file = Nullfp;
  396.  
  397. #else
  398.    if (
  399.  
  400. #ifdef DEBUGGING
  401.          debug & DEB_FEED_XREF ||
  402. #endif
  403.  
  404.          htype[XREF_LINE].ht_minpos >= 0)
  405.    {
  406.       /* are there article# xrefs? */
  407. #endif                       /* DBM */
  408.       char *xref_buf, *curxref;
  409.       register char *xartnum;
  410.       char *rver_buf = Nullch;
  411.  
  412. #ifdef msdos
  413.       extern char *E_nodename;
  414.       char *inews_site = E_nodename;
  415.  
  416. #else
  417.       static char *inews_site = Nullch;
  418.  
  419. #endif
  420.       register ART_NUM x;
  421.       char tmpbuf[128];
  422.  
  423. #ifdef DBM
  424.       rver_buf = fetchlines(artnum, NGS_LINE);
  425.       /* get Newsgroups */
  426.       if (!index(rver_buf, ','))        /* if no comma, no Xref! */
  427.          return 0;
  428.       if (hist_file == Nullfp)
  429.       {                      /* Init. file accesses */
  430.  
  431. #ifdef DEBUGGING
  432.          if (debug)
  433.             printf("chase_xref: opening files\n");
  434. #endif
  435.  
  436.          dbminit(filexp(ARTFILE));
  437.          if ((hist_file = fopen(filexp(ARTFILE), "r")) == Nullfp)
  438.             return 0;
  439.       }
  440.       xref_buf = safemalloc((MEM_SIZE) BUFSIZ);
  441.       ident_buf = fetchlines(artnum, MESSID_LINE);
  442.       /* get Message-ID */
  443.  
  444. #ifdef DEBUGGING
  445.       if (debug)
  446.          printf("chase_xref: Message-ID: %s\n", ident_buf);
  447. #endif
  448.  
  449.       idp = ident_buf;
  450.       while (*++idp)         /* make message-id case
  451.                               * insensitive */
  452.          if (isupper(*idp))
  453.             *idp = tolower(*idp);
  454.       lhs.dptr = ident_buf;  /* look up article by id */
  455.       lhs.dsize = strlen(lhs.dptr) + 1;
  456.       rhs = fetch(lhs);      /* fetch the record */
  457.       if (rhs.dptr == NULL)  /* if null, nothing
  458.                               * there */
  459.          goto wild_goose;
  460.       fseek(hist_file, *((long *) rhs.dptr), 0);
  461.       /* datum returned is position in hist file */
  462.       fgets(xref_buf, BUFSIZ, hist_file);
  463.  
  464. #ifdef DEBUGGING
  465.       if (debug)
  466.          printf("Xref from history: %s\n", xref_buf);
  467. #endif
  468.  
  469.       curxref = cpytill(tmpbuf, xref_buf, '\t') + 1;
  470.       curxref = cpytill(tmpbuf, curxref, '\t') + 1;
  471.  
  472. #ifdef DEBUGGING
  473.       if (debug)
  474.          printf("chase_xref: curxref: %s\n", curxref);
  475. #endif
  476.  
  477. #else                        /* !DBM */
  478.  
  479. #ifdef DEBUGGING
  480.       if (htype[XREF_LINE].ht_minpos >= 0)
  481. #endif
  482.  
  483.          xref_buf = fetchlines(artnum, XREF_LINE);
  484.       /* get xrefs list */
  485.  
  486. #ifdef DEBUGGING
  487.       else
  488.       {
  489.          xref_buf = safemalloc((MEM_SIZE) 100);
  490.          printf("Give Xref: ") FLUSH;
  491.          gets(xref_buf);
  492.       }
  493. #endif
  494.  
  495. #ifdef DEBUGGING
  496.       if (debug & DEB_XREF_MARKER)
  497.          printf("Xref: %s\n", xref_buf) FLUSH;
  498. #endif
  499.  
  500.       curxref = cpytill(tmpbuf, xref_buf, ' ') + 1;
  501.  
  502.       /* Make sure site name on Xref matches what inews thinks site is. Check
  503.        * first against last inews_site.  If it matches, fine. If not, fetch
  504.        * inews_site from current Relay-Version line and check again.  This is
  505.        * so that if the new administrator decides to change the system name as
  506.        * known to inews, rn will still do Xrefs correctly--each article need
  507.        * only match itself to be valid. */
  508.       if (inews_site == Nullch || strNE(tmpbuf, inews_site))
  509.       {
  510.  
  511. #ifndef NORELAY
  512.          char *t;
  513.  
  514. #endif
  515.  
  516.          if (inews_site != Nullch)
  517.             free(inews_site);
  518.  
  519. #ifndef NORELAY
  520.          rver_buf = fetchlines(artnum, RVER_LINE);
  521.          if ((t = instr(rver_buf, "; site ")) == Nullch)
  522. #else                        /* NORELAY */
  523.          /* In version 2.10.3 of news or afterwards, the Relay-Version and
  524.           * Posting-Version header lines have been removed.  For the code
  525.           * below to work as intended, I have modified it to extract the first
  526.           * component of the Path header line.  This should give the same
  527.           * effect as did the old code with respect to the use of the
  528.           * Relay-Version site name. */
  529.          rver_buf = fetchlines(artnum, PATH_LINE);
  530.          if (instr(rver_buf, "!") == Nullch)
  531. #endif                       /* NORELAY */
  532.  
  533.             inews_site = savestr(nullstr);
  534.          else
  535.          {
  536.             char new_site[128];
  537.  
  538. #ifndef NORELAY
  539.             cpytill(new_site, t + 7, '.');
  540. #else                        /* NORELAY */
  541.             cpytill(new_site, rver_buf, '!');
  542. #endif                       /* NORELAY */
  543.  
  544.             inews_site = savestr(new_site);
  545.          }
  546.          if (strNE(tmpbuf, inews_site))
  547.          {
  548.  
  549. #ifdef DEBUGGING
  550.             if (debug)
  551.                printf("Xref not from %s--ignoring\n", inews_site) FLUSH;
  552. #endif
  553.  
  554.             goto wild_goose;
  555.          }
  556.       }
  557. #endif                       /* DBM */
  558.  
  559.       while (*curxref)
  560.       {
  561.          /* for each newsgroup */
  562.          curxref = cpytill(tmpbuf, curxref, ' ');
  563.  
  564. #ifdef DBM
  565.          xartnum = index(tmpbuf, '/');
  566. #else
  567.          xartnum = index(tmpbuf, ':');
  568. #endif                       /* DBM */
  569.  
  570.          if (!xartnum)       /* probably an old-style
  571.                               * Xref */
  572.             break;
  573.          *xartnum++ = '\0';
  574.          if (strNE(tmpbuf, ngname))
  575.          {                   /* not the current
  576.                               * newsgroup? */
  577.             x = atol(xartnum);
  578.             if (x)
  579.                if (markread)
  580.                {
  581.                   if (addartnum(x, tmpbuf))
  582.                      goto wild_goose;
  583.                }
  584.  
  585. #ifdef MCHASE
  586.                else
  587.                   subartnum(x, tmpbuf);
  588. #endif
  589.          }
  590.          while (*curxref && isspace(*curxref))
  591.             curxref++;
  592.       }
  593. wild_goose:
  594.       free(xref_buf);
  595.  
  596. #ifdef DBM
  597.       free(ident_buf);
  598. #endif                       /* DBM */
  599.  
  600.       if (rver_buf != Nullch)
  601.          free(rver_buf);
  602.    }
  603.    return 0;
  604. }
  605.  
  606. int
  607.   initctl()
  608. {
  609.    char *mybuf = buf;        /* place to decode rc
  610.                               * line */
  611.    register char *s, *c, *h;
  612.    register long i;
  613.    register ART_NUM unread;
  614.  
  615. #ifdef DELAYMARK
  616.    dmcount = 0;
  617. #endif
  618.  
  619.    if ((lastart = getngsize(ng)) < 0)   /* this cannot happen
  620.                                          * (laugh here) */
  621.       return -1;
  622.  
  623.    absfirst = getabsfirst(ng, lastart); /* remember first
  624.                                          * existing article */
  625.    if (!absfirst)            /* no articles at all? */
  626.       absfirst = 1;          /* pretend there is one */
  627.  
  628. #ifndef lint
  629.    ctlsize = (MEM_SIZE) (OFFSET(lastart) / BITSPERBYTE + 20);
  630. #endif                       /* lint */
  631.  
  632.    ctlarea = safemalloc(ctlsize);       /* allocate control area */
  633.  
  634.    /* now modify ctlarea to reflect what has already been read */
  635.  
  636.    for (s = rcline[ng] + rcnums[ng]; *s == ' '; s++);
  637.    /* find numbers in rc line */
  638.    i = strlen(s);
  639.  
  640. #ifndef lint
  641.    if (i >= LBUFLEN - 2)     /* bigger than buf? */
  642.       mybuf = safemalloc((MEM_SIZE) (i + 2));
  643. #endif                       /* lint */
  644.  
  645.    strcpy(mybuf, s);         /* make scratch copy of
  646.                               * line */
  647.    mybuf[i++] = ',';         /* put extra comma on
  648.                               * the end */
  649.    mybuf[i] = '\0';
  650.    s = mybuf;                /* initialize the for
  651.                               * loop below */
  652.    if (strnEQ(s, "1-", 2))
  653.    {                         /* can we save some time
  654.                               * here? */
  655.       firstbit = atol(s + 2) + 1;       /* ignore first range
  656.                                          * thusly */
  657.       s = index(s, ',') + 1;
  658.    }
  659.    else
  660.       firstbit = 1;          /* all the bits are
  661.                               * valid for now */
  662.    if (absfirst > firstbit)
  663.    {                         /* do we know already? */
  664.       firstbit = absfirst;   /* no point calling
  665.                               * getngmin again */
  666.    }
  667.    else if (artopen(firstbit) == Nullfp)
  668.    {
  669.       /* first unread article missing? */
  670.       i = getngmin(".", firstbit);      /* see if expire has
  671.                                          * been busy */
  672.       if (i)
  673.       {                      /* avoid a bunch of
  674.                               * extra opens */
  675.          firstbit = i;
  676.       }
  677.    }
  678.    firstart = firstbit;      /* firstart > firstbit
  679.                               * in KILL */
  680.  
  681. #ifdef PENDING
  682.  
  683. #ifdef CACHESUBJ
  684.    subj_to_get = firstbit;
  685. #endif
  686.  
  687. #endif
  688.  
  689.    unread = lastart - firstbit + 1;     /* assume this range
  690.                                          * unread */
  691.    for (i = OFFSET(firstbit) / BITSPERBYTE; i < ctlsize; i++)
  692.       ctlarea[i] = 0;        /* assume unread */
  693.  
  694. #ifdef DEBUGGING
  695.    if (debug & DEB_CTLAREA_BITMAP)
  696.    {
  697.       printf("\n%s\n", mybuf) FLUSH;
  698.       for (i = 1; i <= lastart; i++)
  699.          if (!was_read(i))
  700.             printf("%ld ", (long) i) FLUSH;
  701.    }
  702. #endif
  703.  
  704.    for (; (c = index(s, ',')) != Nullch; s = ++c)
  705.    {
  706.       /* for each range */
  707.       ART_NUM min, max;
  708.  
  709.       *c = '\0';             /* do not let index see
  710.                               * past comma */
  711.       if ((h = index(s, '-')) != Nullch)
  712.       {                      /* is there a -? */
  713.          min = atol(s);
  714.          max = atol(h + 1);
  715.          if (min < firstbit) /* make sure range is in
  716.                               * range */
  717.             min = firstbit;
  718.          if (max > lastart)
  719.             max = lastart;
  720.          if (min <= max)     /* non-null range? */
  721.             unread -= max - min + 1;    /* adjust unread count */
  722.          for (i = min; i <= max; i++)   /* for all articles in
  723.                                          * range */
  724.             ctl_set(i);      /* mark them read */
  725.       }
  726.       else if ((i = atol(s)) >= firstbit && i <= lastart)
  727.       {
  728.          /* is single number reasonable? */
  729.          ctl_set(i);         /* mark it read */
  730.          unread--;           /* decrement articles to
  731.                               * read */
  732.       }
  733.  
  734. #ifdef DEBUGGING
  735.       if (debug & DEB_CTLAREA_BITMAP)
  736.       {
  737.          printf("\n%s\n", s) FLUSH;
  738.          for (i = 1; i <= lastart; i++)
  739.             if (!was_read(i))
  740.                printf("%ld ", (long) i) FLUSH;
  741.       }
  742. #endif
  743.    }
  744.  
  745. #ifdef DEBUGGING
  746.    if (debug & DEB_CTLAREA_BITMAP)
  747.    {
  748.       fputs("\n(hit CR)", stdout) FLUSH;
  749.       gets(cmd_buf);
  750.    }
  751. #endif
  752.  
  753.    if (mybuf != buf)
  754.       free(mybuf);
  755.    toread[ng] = unread;
  756.    return 0;
  757. }
  758.  
  759. void
  760.   grow_ctl()
  761. {
  762.    ART_NUM newlast;
  763.    ART_NUM tmpfirst;
  764.    MEM_SIZE newsize;
  765.    register ART_NUM i;
  766.  
  767.    forcegrow = FALSE;
  768.    newlast = getngsize(ng);
  769.    if (newlast > lastart)
  770.    {
  771.       ART_NUM tmpart = art;
  772.  
  773. #ifndef lint
  774.       newsize = (MEM_SIZE) (OFFSET(newlast) / BITSPERBYTE + 2);
  775. #else
  776.       newsize = Null(MEM_SIZE);
  777. #endif                       /* lint */
  778.  
  779.       if (newsize > ctlsize)
  780.       {
  781.          newsize += 20;
  782.          ctlarea = saferealloc(ctlarea, newsize);
  783.          ctlsize = newsize;
  784.       }
  785.       toread[ng] += (ART_UNREAD) (newlast - lastart);
  786.       for (i = lastart + 1; i <= newlast; i++)
  787.          ctl_clear(i);       /* these articles are
  788.                               * unread */
  789.  
  790. #ifdef CACHESUBJ
  791.       if (subj_list != Null(char **))
  792.       {
  793.  
  794. #ifndef lint
  795.          subj_list = (char **) saferealloc((char *) subj_list,
  796.                                            (MEM_SIZE) ((OFFSET(newlast) + 2) * sizeof (char *)));
  797. #endif                       /* lint */
  798.  
  799.          for (i = lastart + 1; i <= newlast; i++)
  800.             subj_list[OFFSET(i)] = Nullch;
  801.       }
  802. #endif
  803.  
  804.       tmpfirst = lastart + 1;
  805.       lastart = newlast;
  806.  
  807. #ifdef KILLFILES
  808.  
  809. #ifdef VERBOSE
  810.       IF(verbose)
  811.          sprintf(buf,
  812.                  "%ld more article%s arrived--looking for more to kill...\n\n",
  813.                  (long) (lastart - tmpfirst + 1),
  814.                  (lastart > tmpfirst ? "s have" : " has"));
  815.       ELSE                   /* my, my, how clever we
  816.                               * are */
  817. #endif
  818.  
  819. #ifdef TERSE
  820.          strcpy(buf, "More news--killing...\n\n");
  821. #endif
  822.  
  823.       kill_unwanted(tmpfirst, buf, TRUE);
  824. #endif
  825.  
  826.       art = tmpart;
  827.    }
  828. }
  829.