|
|
1.1 root 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: }
613:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.