1: /* $Header: bits.c,v 4.3 85/05/01 11:36:15 lwall Exp $
   2:  *
   3:  * $Log:	bits.c,v $
   4:  * Revision 4.3  85/05/01  11:36:15  lwall
   5:  * Baseline for release with 4.3bsd.
   6:  *
   7:  */
   8: 
   9: #include "EXTERN.h"
  10: #include "common.h"
  11: #include "rcstuff.h"
  12: #include "head.h"
  13: #include "util.h"
  14: #include "final.h"
  15: #include "rn.h"
  16: #include "cheat.h"
  17: #include "ng.h"
  18: #include "artio.h"
  19: #include "intrp.h"
  20: #include "ngdata.h"
  21: #include "rcln.h"
  22: #include "kfile.h"
  23: #include "INTERN.h"
  24: #include "bits.h"
  25: 
  26: #ifdef DBM
  27: #    ifdef NULL
  28: #	undef NULL
  29: #    endif NULL
  30: #    include <dbm.h>
  31: #endif DBM
  32: MEM_SIZE ctlsize;           /* size of bitmap in bytes */
  33: 
  34: void
  35: bits_init()
  36: {
  37: #ifdef DELAYMARK
  38:     dmname = savestr(filexp(RNDELNAME));
  39: #else
  40:     ;
  41: #endif
  42: }
  43: 
  44: /* checkpoint the .newsrc */
  45: 
  46: void
  47: checkpoint_rc()
  48: {
  49: #ifdef DEBUGGING
  50:     if (debug & DEB_CHECKPOINTING) {
  51:     fputs("(ckpt)",stdout);
  52:     fflush(stdout);
  53:     }
  54: #endif
  55:     if (doing_ng)
  56:     restore_ng();           /* do not restore M articles */
  57:     if (rc_changed)
  58:     write_rc();
  59: #ifdef DEBUGGING
  60:     if (debug & DEB_CHECKPOINTING) {
  61:     fputs("(done)",stdout);
  62:     fflush(stdout);
  63:     }
  64: #endif
  65: }
  66: 
  67: /* reconstruct the .newsrc line in a human readable form */
  68: 
  69: void
  70: restore_ng()
  71: {
  72:     register char *s, *mybuf = buf;
  73:     register ART_NUM i;
  74:     ART_NUM count=0;
  75:     int safelen = LBUFLEN - 16;
  76: 
  77:     strcpy(buf,rcline[ng]);     /* start with the newsgroup name */
  78:     s = buf + rcnums[ng] - 1;       /* use s for buffer pointer */
  79:     *s++ = rcchar[ng];          /* put the requisite : or !*/
  80:     *s++ = ' ';             /* put the not-so-requisite space */
  81:     for (i=1; i<=lastart; i++) {    /* for each article in newsgroup */
  82:     if (s-mybuf > safelen) {    /* running out of room? */
  83:         safelen *= 2;
  84:         if (mybuf == buf) {     /* currently static? */
  85:         *s = '\0';
  86:         mybuf = safemalloc((MEM_SIZE)safelen + 16);
  87:         strcpy(mybuf,buf);  /* so we must copy it */
  88:         s = mybuf + (s-buf);
  89:                     /* fix the pointer, too */
  90:         }
  91:         else {          /* just grow in place, if possible */
  92:         char *newbuf;
  93: 
  94:         newbuf = saferealloc(mybuf,(MEM_SIZE)safelen + 16);
  95:         s = newbuf + (s-mybuf);
  96:         mybuf = newbuf;
  97:         }
  98:     }
  99:     if (!was_read(i))       /* still unread? */
 100:         count++;            /* then count it */
 101:     else {              /* article was read */
 102:         ART_NUM oldi;
 103: 
 104:         sprintf(s,"%ld",(long)i);   /* put out the min of the range */
 105:         s += strlen(s);     /* keeping house */
 106:         oldi = i;           /* remember this spot */
 107:         do i++; while (i <= lastart && was_read(i));
 108:                     /* find 1st unread article or end */
 109:         i--;            /* backup to last read article */
 110:         if (i > oldi) {     /* range of more than 1? */
 111:         sprintf(s,"-%ld,",(long)i);
 112:                     /* then it out as a range */
 113:         s += strlen(s);     /* and housekeep */
 114:         }
 115:         else
 116:         *s++ = ',';     /* otherwise, just a comma will do */
 117:     }
 118:     }
 119:     if (*(s-1) == ',')          /* is there a final ','? */
 120:     s--;                /* take it back */
 121:     *s++ = '\0';            /* and terminate string */
 122: #ifdef DEBUGGING
 123:     if (debug & DEB_NEWSRC_LINE && !panic) {
 124:     printf("%s: %s\n",rcline[ng],rcline[ng]+rcnums[ng]) FLUSH;
 125:     printf("%s\n",mybuf) FLUSH;
 126:     }
 127: #endif
 128:     free(rcline[ng]);           /* return old rc line */
 129:     if (mybuf == buf) {
 130:     rcline[ng] = safemalloc((MEM_SIZE)(s-buf)+1);
 131:                     /* grab a new rc line */
 132:     strcpy(rcline[ng], buf);    /* and load it */
 133:     }
 134:     else {
 135:     mybuf = saferealloc(mybuf,(MEM_SIZE)(s-mybuf)+1);
 136:                     /* be nice to the heap */
 137:     rcline[ng] = mybuf;
 138:     }
 139:     *(rcline[ng] + rcnums[ng] - 1) = '\0';
 140:     if (rcchar[ng] == NEGCHAR) {    /* did they unsubscribe? */
 141:     printf(unsubto,ngname) FLUSH;
 142:     toread[ng] = TR_UNSUB;      /* make line invisible */
 143:     }
 144:     else
 145:     /*NOSTRICT*/
 146:     toread[ng] = (ART_UNREAD)count;     /* remember how many unread there are */
 147: }
 148: 
 149: /* mark an article unread, keeping track of toread[] */
 150: 
 151: void
 152: onemore(artnum)
 153: ART_NUM artnum;
 154: {
 155: #ifdef DEBUGGING
 156:     if (debug && artnum < firstart) {
 157:     printf("onemore: %d < %d\n",artnum,firstart) FLUSH;
 158:     return;
 159:     }
 160: #endif
 161:     if (ctl_read(artnum)) {
 162:     ctl_clear(artnum);
 163:     ++toread[ng];
 164:     }
 165: }
 166: 
 167: /* mark an article read, keeping track of toread[] */
 168: 
 169: void
 170: oneless(artnum)
 171: ART_NUM artnum;
 172: {
 173: #ifdef DEBUGGING
 174:     if (debug && artnum < firstart) {
 175:     printf("oneless: %d < %d\n",artnum,firstart) FLUSH;
 176:     return;
 177:     }
 178: #endif
 179:     if (!ctl_read(artnum)) {
 180:     ctl_set(artnum);
 181:     if (toread[ng] > TR_NONE)
 182:         --toread[ng];
 183:     }
 184: }
 185: 
 186: /* mark an article as unread, making sure that firstart is properly handled */
 187: /* cross-references are left as read in the other newsgroups */
 188: 
 189: void
 190: unmark_as_read(artnum)
 191: ART_NUM artnum;
 192: {
 193:     check_first(artnum);
 194:     onemore(artnum);
 195: #ifdef MCHASE
 196:     if (!parse_maybe(artnum))
 197:     chase_xrefs(artnum,FALSE);
 198: #endif
 199: }
 200: 
 201: #ifdef DELAYMARK
 202: /* temporarily mark article as read.  When newsgroup is exited, articles */
 203: /* will be marked as unread.  Called via M command */
 204: 
 205: void
 206: delay_unmark(artnum)
 207: ART_NUM artnum;
 208: {
 209:     if (dmfp == Nullfp) {
 210:     dmfp = fopen(dmname,"w");
 211:     if (dmfp == Nullfp) {
 212:         printf(cantcreate,dmname) FLUSH;
 213:         sig_catcher(0);
 214:     }
 215:     }
 216:     oneless(artnum);            /* set the correct bit */
 217:     dmcount++;
 218:     fprintf(dmfp,"%ld\n",(long)artnum);
 219: }
 220: #endif
 221: 
 222: /* mark article as read.  If article is cross referenced to other */
 223: /* newsgroups, mark them read there also. */
 224: 
 225: void
 226: mark_as_read(artnum)
 227: ART_NUM artnum;
 228: {
 229:     oneless(artnum);            /* set the correct bit */
 230:     checkcount++;           /* get more worried about crashes */
 231:     chase_xrefs(artnum,TRUE);
 232: }
 233: 
 234: /* make sure we have bits set correctly down to firstart */
 235: 
 236: void
 237: check_first(min)
 238: ART_NUM min;
 239: {
 240:     register ART_NUM i = firstart;
 241: 
 242:     if (min < absfirst)
 243:     min = absfirst;
 244:     if (min < i) {
 245:     for (i--; i>=min; i--)
 246:         ctl_set(i);     /* mark as read */
 247:     firstart = min;
 248:     }
 249: }
 250: 
 251: /* bring back articles marked with M */
 252: 
 253: #ifdef DELAYMARK
 254: void
 255: yankback()
 256: {
 257:     register ART_NUM anum;
 258: 
 259:     if (dmfp) {         /* delayed unmarks pending? */
 260: #ifdef VERBOSE
 261:     printf("\nReturning %ld Marked article%s...\n",(long)dmcount,
 262:         dmcount == 1 ? nullstr : "s") FLUSH;
 263: #endif
 264:     fclose(dmfp);
 265:     if (dmfp = fopen(dmname,"r")) {
 266:         while (fgets(buf,sizeof buf,dmfp) != Nullch) {
 267:         anum = (ART_NUM)atol(buf);
 268:         /*NOSTRICT*/
 269:         onemore(anum);             /* then unmark them */
 270: #ifdef MCHASE
 271:         chase_xrefs(anum,FALSE);
 272: #endif
 273:         }
 274:         fclose(dmfp);
 275:         dmfp = Nullfp;
 276:         UNLINK(dmname);     /* and be tidy */
 277:     }
 278:     else {
 279:         printf(cantopen,dmname) FLUSH;
 280:         sig_catcher(0);
 281:     }
 282:     }
 283:     dmcount = 0;
 284: }
 285: #endif
 286: 
 287: /* run down xref list and mark as read or unread */
 288: 
 289: int
 290: chase_xrefs(artnum,markread)
 291: ART_NUM artnum;
 292: int markread;
 293: {
 294: #ifdef ASYNC_PARSE
 295:     if (parse_maybe(artnum))        /* make sure we have right header */
 296:     return -1;
 297: #endif
 298: #ifdef DBM
 299:     {
 300:     datum lhs, rhs;
 301:     datum fetch();
 302:     register char *idp;
 303:     char *ident_buf;
 304:     static FILE * hist_file = Nullfp;
 305: #else
 306:     if (
 307: #ifdef DEBUGGING
 308:     debug & DEB_FEED_XREF ||
 309: #endif
 310:     htype[XREF_LINE].ht_minpos >= 0) {
 311:                     /* are there article# xrefs? */
 312: #endif DBM
 313:     char *xref_buf, *curxref;
 314:     register char *xartnum;
 315:     char *rver_buf = Nullch;
 316:     static char *inews_site = Nullch;
 317:     register ART_NUM x;
 318:     char tmpbuf[128];
 319: 
 320: #ifdef DBM
 321:     rver_buf = fetchlines(artnum,NGS_LINE);
 322:                     /* get Newsgroups */
 323:     if (!index(rver_buf,','))   /* if no comma, no Xref! */
 324:         return 0;
 325:     if (hist_file == Nullfp) {  /* Init. file accesses */
 326: #ifdef DEBUGGING
 327:         if (debug)
 328:         printf ("chase_xref: opening files\n");
 329: #endif
 330:         dbminit(filexp(ARTFILE));
 331:         if ((hist_file = fopen (filexp(ARTFILE), "r")) == Nullfp)
 332:         return 0;
 333:     }
 334:     xref_buf = safemalloc((MEM_SIZE)BUFSIZ);
 335:     ident_buf = fetchlines(artnum,MESSID_LINE);
 336:                     /* get Message-ID */
 337: #ifdef DEBUGGING
 338:     if (debug)
 339:         printf ("chase_xref: Message-ID: %s\n", ident_buf);
 340: #endif
 341:     idp = ident_buf;
 342:     while (*++idp)          /* make message-id case insensitive */
 343:         if (isupper(*idp))
 344:             *idp = tolower (*idp);
 345:     lhs.dptr = ident_buf;       /* look up article by id */
 346:     lhs.dsize = strlen(lhs.dptr) + 1;
 347:     rhs = fetch(lhs);       /* fetch the record */
 348:     if (rhs.dptr == NULL)       /* if null, nothing there */
 349:         goto wild_goose;
 350:     fseek (hist_file, *((long *)rhs.dptr), 0);
 351:                     /* datum returned is position in hist file */
 352:     fgets (xref_buf, BUFSIZ, hist_file);
 353: #ifdef DEBUGGING
 354:     if (debug)
 355:         printf ("Xref from history: %s\n", xref_buf);
 356: #endif
 357:     curxref = cpytill(tmpbuf, xref_buf, '\t') + 1;
 358:     curxref = cpytill(tmpbuf, curxref, '\t') + 1;
 359: #ifdef DEBUGGING
 360:     if (debug)
 361:         printf ("chase_xref: curxref: %s\n", curxref);
 362: #endif
 363: #else !DBM
 364: #ifdef DEBUGGING
 365:     if (htype[XREF_LINE].ht_minpos >= 0)
 366: #endif
 367:         xref_buf = fetchlines(artnum,XREF_LINE);
 368:                     /* get xrefs list */
 369: #ifdef DEBUGGING
 370:     else {
 371:         xref_buf = safemalloc((MEM_SIZE)100);
 372:         printf("Give Xref: ") FLUSH;
 373:         gets(xref_buf);
 374:     }
 375: #endif
 376: #ifdef DEBUGGING
 377:     if (debug & DEB_XREF_MARKER)
 378:         printf("Xref: %s\n",xref_buf) FLUSH;
 379: #endif
 380:     curxref = cpytill(tmpbuf,xref_buf,' ') + 1;
 381: 
 382:     /* Make sure site name on Xref matches what inews thinks site is.
 383: 	 * Check first against last inews_site.  If it matches, fine.
 384: 	 * If not, fetch inews_site from current Relay-Version line and
 385: 	 * check again.  This is so that if the new administrator decides
 386: 	 * to change the system name as known to inews, rn will still do
 387: 	 * Xrefs correctly--each article need only match itself to be valid.
 388: 	 */
 389:     if (inews_site == Nullch || strNE(tmpbuf,inews_site)) {
 390:         char *t;
 391: 
 392:         if (inews_site != Nullch)
 393:         free(inews_site);
 394:         rver_buf = fetchlines(artnum,RVER_LINE);
 395:         if ((t = instr(rver_buf,"; site ")) == Nullch)
 396:         inews_site = savestr(nullstr);
 397:         else {
 398:         char new_site[128];
 399: 
 400:         cpytill(new_site,t + 7,'.');
 401:         inews_site = savestr(new_site);
 402:         }
 403:         if (strNE(tmpbuf,inews_site)) {
 404: #ifdef DEBUGGING
 405:         if (debug)
 406:             printf("Xref not from %s--ignoring\n",inews_site) FLUSH;
 407: #endif
 408:         goto wild_goose;
 409:         }
 410:     }
 411: #endif DBM
 412:     while (*curxref) {
 413:                     /* for each newsgroup */
 414:         curxref = cpytill(tmpbuf,curxref,' ');
 415: #ifdef DBM
 416:         xartnum = index(tmpbuf,'/');
 417: #else
 418:         xartnum = index(tmpbuf,':');
 419: #endif DBM
 420:         if (!xartnum)       /* probably an old-style Xref */
 421:         break;
 422:         *xartnum++ = '\0';
 423:         if (strNE(tmpbuf,ngname)) {/* not the current newsgroup? */
 424:         x = atol(xartnum);
 425:         if (x)
 426:             if (markread) {
 427:             if (addartnum(x,tmpbuf))
 428:                 goto wild_goose;
 429:             }
 430: #ifdef MCHASE
 431:             else
 432:             subartnum(x,tmpbuf);
 433: #endif
 434:         }
 435:         while (*curxref && isspace(*curxref))
 436:         curxref++;
 437:     }
 438:       wild_goose:
 439:     free(xref_buf);
 440: #ifdef DBM
 441:     free(ident_buf);
 442: #endif DBM
 443:     if (rver_buf != Nullch)
 444:         free(rver_buf);
 445:     }
 446:     return 0;
 447: }
 448: 
 449: int
 450: initctl()
 451: {
 452:     char *mybuf = buf;          /* place to decode rc line */
 453:     register char *s, *c, *h;
 454:     register long i;
 455:     register ART_NUM unread;
 456: 
 457: #ifdef DELAYMARK
 458:     dmcount = 0;
 459: #endif
 460:     if ((lastart = getngsize(ng)) < 0)  /* this cannot happen (laugh here) */
 461:     return -1;
 462: 
 463:     absfirst = getabsfirst(ng,lastart); /* remember first existing article */
 464:     if (!absfirst)          /* no articles at all? */
 465:     absfirst = 1;           /* pretend there is one */
 466: #ifndef lint
 467:     ctlsize = (MEM_SIZE)(OFFSET(lastart)/BITSPERBYTE+20);
 468: #endif lint
 469:     ctlarea = safemalloc(ctlsize);  /* allocate control area */
 470: 
 471:     /* now modify ctlarea to reflect what has already been read */
 472: 
 473:     for (s = rcline[ng] + rcnums[ng]; *s == ' '; s++) ;
 474:                     /* find numbers in rc line */
 475:     i = strlen(s);
 476: #ifndef lint
 477:     if (i >= LBUFLEN-2)         /* bigger than buf? */
 478:     mybuf = safemalloc((MEM_SIZE)(i+2));
 479: #endif lint
 480:     strcpy(mybuf,s);            /* make scratch copy of line */
 481:     mybuf[i++] = ',';           /* put extra comma on the end */
 482:     mybuf[i] = '\0';
 483:     s = mybuf;              /* initialize the for loop below */
 484:     if (strnEQ(s,"1-",2)) {     /* can we save some time here? */
 485:     firstart = atol(s+2)+1;     /* ignore first range thusly */
 486:     s=index(s,',') + 1;
 487:     }
 488:     else
 489:     firstart = 1;           /* all the bits are valid for now */
 490:     if (absfirst > firstart) {      /* do we know already? */
 491:     firstart = absfirst;        /* no point calling getngmin again */
 492:     }
 493:     else if (artopen(firstart) == Nullfp) {
 494:                     /* first unread article missing? */
 495:     i = getngmin(".",firstart); /* see if expire has been busy */
 496:     if (i) {            /* avoid a bunch of extra opens */
 497:         firstart = i;
 498:     }
 499:     }
 500: #ifdef PENDING
 501: #   ifdef CACHESUBJ
 502:     subj_to_get = firstart;
 503: #   endif
 504: #endif
 505:     unread = lastart - firstart + 1;    /* assume this range unread */
 506:     for (i=OFFSET(firstart)/BITSPERBYTE; i<ctlsize; i++)
 507:     ctlarea[i] = 0;         /* assume unread */
 508: #ifdef DEBUGGING
 509:     if (debug & DEB_CTLAREA_BITMAP) {
 510:     printf("\n%s\n",mybuf) FLUSH;
 511:     for (i=1; i <= lastart; i++)
 512:         if (! was_read(i))
 513:         printf("%ld ",(long)i) FLUSH;
 514:     }
 515: #endif
 516:     for ( ; (c = index(s,',')) != Nullch; s = ++c) {
 517:                     /* for each range */
 518:     ART_NUM min, max;
 519: 
 520:     *c = '\0';          /* do not let index see past comma */
 521:     if ((h = index(s,'-')) != Nullch) { /* is there a -? */
 522:         min = atol(s);
 523:         max = atol(h+1);
 524:         if (min < firstart)     /* make sure range is in range */
 525:         min = firstart;
 526:         if (max > lastart)
 527:         max = lastart;
 528:         if (min <= max)     /* non-null range? */
 529:         unread -= max - min + 1;/* adjust unread count */
 530:         for (i=min; i<=max; i++)    /* for all articles in range */
 531:         ctl_set(i);     /* mark them read */
 532:     }
 533:     else if ((i = atol(s)) >= firstart && i <= lastart) {
 534:                     /* is single number reasonable? */
 535:         ctl_set(i);         /* mark it read */
 536:         unread--;           /* decrement articles to read */
 537:     }
 538: #ifdef DEBUGGING
 539:     if (debug & DEB_CTLAREA_BITMAP) {
 540:         printf("\n%s\n",s) FLUSH;
 541:         for (i=1; i <= lastart; i++)
 542:         if (! was_read(i))
 543:             printf("%ld ",(long)i) FLUSH;
 544:     }
 545: #endif
 546:     }
 547: #ifdef DEBUGGING
 548:     if (debug & DEB_CTLAREA_BITMAP) {
 549:     fputs("\n(hit CR)",stdout) FLUSH;
 550:     gets(cmd_buf);
 551:     }
 552: #endif
 553:     if (mybuf != buf)
 554:     free(mybuf);
 555:     toread[ng] = unread;
 556:     return 0;
 557: }
 558: 
 559: void
 560: grow_ctl()
 561: {
 562:     ART_NUM newlast;
 563:     ART_NUM tmpfirst;
 564:     MEM_SIZE newsize;
 565:     register ART_NUM i;
 566: 
 567:     forcegrow = FALSE;
 568:     newlast = getngsize(ng);
 569:     if (newlast > lastart) {
 570:     ART_NUM tmpart = art;
 571: #ifndef lint
 572:     newsize = (MEM_SIZE)(OFFSET(newlast)/BITSPERBYTE+2);
 573: #else
 574:     newsize = Null(MEM_SIZE);
 575: #endif lint
 576:     if (newsize > ctlsize) {
 577:         newsize += 20;
 578:         ctlarea = saferealloc(ctlarea,newsize);
 579:         ctlsize = newsize;
 580:     }
 581:     toread[ng] += (ART_UNREAD)(newlast-lastart);
 582:     for (i=lastart+1; i<=newlast; i++)
 583:         ctl_clear(i);   /* these articles are unread */
 584: #ifdef CACHESUBJ
 585:     if (subj_list != Null(char**)) {
 586: #ifndef lint
 587:         subj_list = (char**)saferealloc((char*)subj_list,
 588:           (MEM_SIZE)((OFFSET(newlast)+2)*sizeof(char *)) );
 589: #endif lint
 590:         for (i=lastart+1; i<=newlast; i++)
 591:         subj_list[OFFSET(i)] = Nullch;
 592:     }
 593: #endif
 594:     tmpfirst = lastart+1;
 595:     lastart = newlast;
 596: #ifdef KILLFILES
 597: #ifdef VERBOSE
 598:     IF(verbose)
 599:         sprintf(buf,
 600:         "%ld more article%s arrived--looking for more to kill...\n\n",
 601:         (long)(lastart - firstart + 1),
 602:         (lastart > firstart ? "s have" : " has" ) );
 603:     ELSE            /* my, my, how clever we are */
 604: #endif
 605: #ifdef TERSE
 606:         strcpy(buf, "More news--killing...\n\n");
 607: #endif
 608:     kill_unwanted(tmpfirst,buf,TRUE);
 609: #endif
 610:     art = tmpart;
 611:     }
 612: }

Defined functions

bits_init defined in line 34; used 2 times
chase_xrefs defined in line 289; used 4 times
grow_ctl defined in line 559; used 2 times
initctl defined in line 449; used 2 times
oneless defined in line 169; used 5 times
onemore defined in line 151; used 3 times
restore_ng defined in line 69; used 4 times

Defined variables

ctlsize defined in line 32; used 5 times
Last modified: 1986-03-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2533
Valid CSS Valid XHTML 1.0 Strict