/* $Header: bits.c,v 4.3 85/05/01 11:36:15 lwall Exp $
* Revision 4.3 85/05/01 11:36:15 lwall
* Baseline for release with 4.3bsd.
MEM_SIZE ctlsize
; /* size of bitmap in bytes */
dmname
= savestr(filexp(RNDELNAME
));
/* checkpoint the .newsrc */
if (debug
& DEB_CHECKPOINTING
) {
restore_ng(); /* do not restore M articles */
if (debug
& DEB_CHECKPOINTING
) {
/* reconstruct the .newsrc line in a human readable form */
register char *s
, *mybuf
= buf
;
int safelen
= LBUFLEN
- 16;
strcpy(buf
,rcline
[ng
]); /* start with the newsgroup name */
s
= buf
+ rcnums
[ng
] - 1; /* use s for buffer pointer */
*s
++ = rcchar
[ng
]; /* put the requisite : or !*/
*s
++ = ' '; /* put the not-so-requisite space */
for (i
=1; i
<=lastart
; i
++) { /* for each article in newsgroup */
if (s
-mybuf
> safelen
) { /* running out of room? */
if (mybuf
== buf
) { /* currently static? */
mybuf
= safemalloc((MEM_SIZE
)safelen
+ 16);
strcpy(mybuf
,buf
); /* so we must copy it */
/* fix the pointer, too */
else { /* just grow in place, if possible */
newbuf
= saferealloc(mybuf
,(MEM_SIZE
)safelen
+ 16);
if (!was_read(i
)) /* still unread? */
count
++; /* then count it */
else { /* article was read */
sprintf(s
,"%ld",(long)i
); /* put out the min of the range */
s
+= strlen(s
); /* keeping house */
oldi
= i
; /* remember this spot */
do i
++; while (i
<= lastart
&& was_read(i
));
/* find 1st unread article or end */
i
--; /* backup to last read article */
if (i
> oldi
) { /* range of more than 1? */
sprintf(s
,"-%ld,",(long)i
);
/* then it out as a range */
s
+= strlen(s
); /* and housekeep */
*s
++ = ','; /* otherwise, just a comma will do */
if (*(s
-1) == ',') /* is there a final ','? */
*s
++ = '\0'; /* and terminate string */
if (debug
& DEB_NEWSRC_LINE
&& !panic
) {
printf("%s: %s\n",rcline
[ng
],rcline
[ng
]+rcnums
[ng
]) FLUSH
;
printf("%s\n",mybuf
) FLUSH
;
free(rcline
[ng
]); /* return old rc line */
rcline
[ng
] = safemalloc((MEM_SIZE
)(s
-buf
)+1);
strcpy(rcline
[ng
], buf
); /* and load it */
mybuf
= saferealloc(mybuf
,(MEM_SIZE
)(s
-mybuf
)+1);
/* be nice to the heap */
*(rcline
[ng
] + rcnums
[ng
] - 1) = '\0';
if (rcchar
[ng
] == NEGCHAR
) { /* did they unsubscribe? */
printf(unsubto
,ngname
) FLUSH
;
toread
[ng
] = TR_UNSUB
; /* make line invisible */
toread
[ng
] = (ART_UNREAD
)count
; /* remember how many unread there are */
/* mark an article unread, keeping track of toread[] */
if (debug
&& artnum
< firstart
) {
printf("onemore: %d < %d\n",artnum
,firstart
) FLUSH
;
/* mark an article read, keeping track of toread[] */
if (debug
&& artnum
< firstart
) {
printf("oneless: %d < %d\n",artnum
,firstart
) FLUSH
;
if (toread
[ng
] > TR_NONE
)
/* mark an article as unread, making sure that firstart is properly handled */
/* cross-references are left as read in the other newsgroups */
if (!parse_maybe(artnum
))
chase_xrefs(artnum
,FALSE
);
/* temporarily mark article as read. When newsgroup is exited, articles */
/* will be marked as unread. Called via M command */
dmfp
= fopen(dmname
,"w");
printf(cantcreate
,dmname
) FLUSH
;
oneless(artnum
); /* set the correct bit */
fprintf(dmfp
,"%ld\n",(long)artnum
);
/* mark article as read. If article is cross referenced to other */
/* newsgroups, mark them read there also. */
oneless(artnum
); /* set the correct bit */
checkcount
++; /* get more worried about crashes */
chase_xrefs(artnum
,TRUE
);
/* make sure we have bits set correctly down to firstart */
register ART_NUM i
= firstart
;
ctl_set(i
); /* mark as read */
/* bring back articles marked with M */
if (dmfp
) { /* delayed unmarks pending? */
printf("\nReturning %ld Marked article%s...\n",(long)dmcount
,
dmcount
== 1 ? nullstr
: "s") FLUSH
;
if (dmfp
= fopen(dmname
,"r")) {
while (fgets(buf
,sizeof buf
,dmfp
) != Nullch
) {
anum
= (ART_NUM
)atol(buf
);
onemore(anum
); /* then unmark them */
UNLINK(dmname
); /* and be tidy */
printf(cantopen
,dmname
) FLUSH
;
/* run down xref list and mark as read or unread */
chase_xrefs(artnum
,markread
)
if (parse_maybe(artnum
)) /* make sure we have right header */
static FILE * hist_file
= Nullfp
;
htype
[XREF_LINE
].ht_minpos
>= 0) {
/* are there article# xrefs? */
char *xref_buf
, *curxref
;
static char *inews_site
= Nullch
;
rver_buf
= fetchlines(artnum
,NGS_LINE
);
if (!index(rver_buf
,',')) /* if no comma, no Xref! */
if (hist_file
== Nullfp
) { /* Init. file accesses */
printf ("chase_xref: opening files\n");
dbminit(filexp(ARTFILE
));
if ((hist_file
= fopen (filexp(ARTFILE
), "r")) == Nullfp
)
xref_buf
= safemalloc((MEM_SIZE
)BUFSIZ
);
ident_buf
= fetchlines(artnum
,MESSID_LINE
);
printf ("chase_xref: Message-ID: %s\n", ident_buf
);
while (*++idp
) /* make message-id case insensitive */
lhs
.dptr
= ident_buf
; /* look up article by id */
lhs
.dsize
= strlen(lhs
.dptr
) + 1;
rhs
= fetch(lhs
); /* fetch the record */
if (rhs
.dptr
== NULL
) /* if null, nothing there */
fseek (hist_file
, *((long *)rhs
.dptr
), 0);
/* datum returned is position in hist file */
fgets (xref_buf
, BUFSIZ
, hist_file
);
printf ("Xref from history: %s\n", xref_buf
);
curxref
= cpytill(tmpbuf
, xref_buf
, '\t') + 1;
curxref
= cpytill(tmpbuf
, curxref
, '\t') + 1;
printf ("chase_xref: curxref: %s\n", curxref
);
if (htype
[XREF_LINE
].ht_minpos
>= 0)
xref_buf
= fetchlines(artnum
,XREF_LINE
);
xref_buf
= safemalloc((MEM_SIZE
)100);
printf("Give Xref: ") FLUSH
;
if (debug
& DEB_XREF_MARKER
)
printf("Xref: %s\n",xref_buf
) FLUSH
;
curxref
= cpytill(tmpbuf
,xref_buf
,' ') + 1;
/* Make sure site name on Xref matches what inews thinks site is.
* Check first against last inews_site. If it matches, fine.
* If not, fetch inews_site from current Relay-Version line and
* check again. This is so that if the new administrator decides
* to change the system name as known to inews, rn will still do
* Xrefs correctly--each article need only match itself to be valid.
if (inews_site
== Nullch
|| strNE(tmpbuf
,inews_site
)) {
if (inews_site
!= Nullch
)
rver_buf
= fetchlines(artnum
,RVER_LINE
);
if ((t
= instr(rver_buf
,"; site ")) == Nullch
)
inews_site
= savestr(nullstr
);
cpytill(new_site
,t
+ 7,'.');
inews_site
= savestr(new_site
);
if (strNE(tmpbuf
,inews_site
)) {
printf("Xref not from %s--ignoring\n",inews_site
) FLUSH
;
curxref
= cpytill(tmpbuf
,curxref
,' ');
xartnum
= index(tmpbuf
,'/');
xartnum
= index(tmpbuf
,':');
if (!xartnum
) /* probably an old-style Xref */
if (strNE(tmpbuf
,ngname
)) {/* not the current newsgroup? */
while (*curxref
&& isspace(*curxref
))
char *mybuf
= buf
; /* place to decode rc line */
register char *s
, *c
, *h
;
if ((lastart
= getngsize(ng
)) < 0) /* this cannot happen (laugh here) */
absfirst
= getabsfirst(ng
,lastart
); /* remember first existing article */
if (!absfirst
) /* no articles at all? */
absfirst
= 1; /* pretend there is one */
ctlsize
= (MEM_SIZE
)(OFFSET(lastart
)/BITSPERBYTE
+20);
ctlarea
= safemalloc(ctlsize
); /* allocate control area */
/* now modify ctlarea to reflect what has already been read */
for (s
= rcline
[ng
] + rcnums
[ng
]; *s
== ' '; s
++) ;
/* find numbers in rc line */
if (i
>= LBUFLEN
-2) /* bigger than buf? */
mybuf
= safemalloc((MEM_SIZE
)(i
+2));
strcpy(mybuf
,s
); /* make scratch copy of line */
mybuf
[i
++] = ','; /* put extra comma on the end */
s
= mybuf
; /* initialize the for loop below */
if (strnEQ(s
,"1-",2)) { /* can we save some time here? */
firstart
= atol(s
+2)+1; /* ignore first range thusly */
firstart
= 1; /* all the bits are valid for now */
if (absfirst
> firstart
) { /* do we know already? */
firstart
= absfirst
; /* no point calling getngmin again */
else if (artopen(firstart
) == Nullfp
) {
/* first unread article missing? */
i
= getngmin(".",firstart
); /* see if expire has been busy */
if (i
) { /* avoid a bunch of extra opens */
unread
= lastart
- firstart
+ 1; /* assume this range unread */
for (i
=OFFSET(firstart
)/BITSPERBYTE
; i
<ctlsize
; i
++)
ctlarea
[i
] = 0; /* assume unread */
if (debug
& DEB_CTLAREA_BITMAP
) {
printf("\n%s\n",mybuf
) FLUSH
;
for (i
=1; i
<= lastart
; i
++)
printf("%ld ",(long)i
) FLUSH
;
for ( ; (c
= index(s
,',')) != Nullch
; s
= ++c
) {
*c
= '\0'; /* do not let index see past comma */
if ((h
= index(s
,'-')) != Nullch
) { /* is there a -? */
if (min
< firstart
) /* make sure range is in range */
if (min
<= max
) /* non-null range? */
unread
-= max
- min
+ 1;/* adjust unread count */
for (i
=min
; i
<=max
; i
++) /* for all articles in range */
ctl_set(i
); /* mark them read */
else if ((i
= atol(s
)) >= firstart
&& i
<= lastart
) {
/* is single number reasonable? */
ctl_set(i
); /* mark it read */
unread
--; /* decrement articles to read */
if (debug
& DEB_CTLAREA_BITMAP
) {
printf("\n%s\n",s
) FLUSH
;
for (i
=1; i
<= lastart
; i
++)
printf("%ld ",(long)i
) FLUSH
;
if (debug
& DEB_CTLAREA_BITMAP
) {
fputs("\n(hit CR)",stdout
) FLUSH
;
newsize
= (MEM_SIZE
)(OFFSET(newlast
)/BITSPERBYTE
+2);
newsize
= Null(MEM_SIZE
);
ctlarea
= saferealloc(ctlarea
,newsize
);
toread
[ng
] += (ART_UNREAD
)(newlast
-lastart
);
for (i
=lastart
+1; i
<=newlast
; i
++)
ctl_clear(i
); /* these articles are unread */
if (subj_list
!= Null(char**)) {
subj_list
= (char**)saferealloc((char*)subj_list
,
(MEM_SIZE
)((OFFSET(newlast
)+2)*sizeof(char *)) );
for (i
=lastart
+1; i
<=newlast
; i
++)
subj_list
[OFFSET(i
)] = Nullch
;
"%ld more article%s arrived--looking for more to kill...\n\n",
(long)(lastart
- firstart
+ 1),
(lastart
> firstart
? "s have" : " has" ) );
ELSE
/* my, my, how clever we are */
strcpy(buf
, "More news--killing...\n\n");
kill_unwanted(tmpfirst
,buf
,TRUE
);