4.4BSD/usr/src/contrib/news/trn3/ngdata.c
/* $Id: ngdata.c,v 3.0 1992/02/01 03:09:32 davison Trn $
*/
/* This software is Copyright 1991 by Stan Barber.
*
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction of this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
*
* The author make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
*/
#include "EXTERN.h"
#include "common.h"
#include "rcstuff.h"
#include "trn.h"
#include "cache.h"
#include "bits.h"
#include "head.h"
#include "rthread.h"
#include "rt-select.h"
#include "ng.h"
#include "intrp.h"
#include "kfile.h"
#include "final.h"
#include "rcln.h"
#include "term.h"
#include "util.h"
#include "nntp.h"
#include "ndir.h"
#include "INTERN.h"
#include "ngdata.h"
/* open the active file */
void
ngdata_init()
{
#ifdef USE_NNTP
char *cp;
nntp_command("LIST"); /* tell server we want the active file */
if (nntp_check(TRUE) != NNTP_CLASS_OK) { /* and then see if that's ok */
printf("Can't get active file from server: \n%s\n", ser_line);
finalize(1);
}
time(&lastactfetch);
cp = filexp("%P/rrnact.%$"); /* make a temporary name */
strcpy(active_name, cp);
actfp = fopen(active_name, "w+"); /* and get ready */
if (actfp == Nullfp) {
printf(cantopen,active_name) FLUSH;
finalize(1);
}
activeitems = 0;
while (1) {
nntp_gets(ser_line, sizeof ser_line);
if (ser_line[0] == '.') /* while there's another line */
break; /* get it and write it to */
activeitems++;
fputs(ser_line, actfp);
putc('\n', actfp);
}
if (ferror(actfp)) {
printf("Error writing to active file %s.\n", active_name) FLUSH;
finalize(1);
}
#else /* !USE_NNTP */
ngdatansrv_init();
#endif
if (fseek(actfp,0L,0) == -1) { /* just get to the beginning */
printf("Error seeking in active file.\n") FLUSH;
finalize(1);
}
return;
}
bool
access_ng()
{
#ifdef USE_NNTP
long unread, first, last;
if (!nntp_group(ngname)) {
toread[ng] = TR_BOGUS;
return FALSE;
}
if ((lastart = getngsize(ng)) < 0) /* this cannot happen (laugh here) */
return FALSE;
(void) sscanf(ser_line,"%*d%ld%ld%ld",&unread,&first,&last);
/* NNTP mangles the high/low values when no articles are present. */
if (!unread)
absfirst = lastart+1;
else {
absfirst = (ART_NUM)first;
if (last > lastart)
lastart = (ART_NUM)last;
}
ngmax[ng] = lastart; /* ensure getngsize() knows the new maximum */
first = abs1st[ng];
abs1st[ng] = absfirst;
if (absfirst > first)
checkexpired(ng);
#else /* !USE_NNTP */
if (eaccess(ngdir,5)) { /* directory read protected? */
if (eaccess(ngdir,0)) {
# ifdef VERBOSE
IF(verbose)
printf("\nNewsgroup %s does not have a spool directory!\n",
ngname) FLUSH;
ELSE
# endif
# ifdef TERSE
printf("\nNo spool for %s!\n",ngname) FLUSH;
# endif
# ifdef CATCHUP
catch_up(ng);
# endif
} else {
# ifdef VERBOSE
IF(verbose)
printf("\nNewsgroup %s is not currently accessible.\n",
ngname) FLUSH;
ELSE
# endif
# ifdef TERSE
printf("\n%s not readable.\n",ngname) FLUSH;
# endif
}
toread[ng] = TR_NONE; /* make this newsgroup temporarily invisible */
return FALSE;
}
/* chdir to newsgroup subdirectory */
if (chdir(ngdir)) {
printf(nocd,ngdir) FLUSH;
return FALSE;
}
if ((lastart = getngsize(ng)) < 0) /* this cannot happen (laugh here) */
return FALSE;
absfirst = abs1st[ng];
setfoundbits(); /* might reset absfirst */
#endif /* !USE_NNTP */
dmcount = 0;
build_cache();
return TRUE;
}
void
grow_ng(newlast)
ART_NUM newlast;
{
ART_NUM tmpfirst;
forcegrow = FALSE;
if (newlast > lastart) {
ART_NUM tmpart = art;
toread[ng] += (ART_UNREAD)(newlast-lastart);
grow_cache(newlast);
tmpfirst = lastart+1;
lastart = newlast;
thread_grow();
#ifdef KILLFILES
#ifdef VERBOSE
IF(verbose)
sprintf(buf,
"%ld more article%s arrived -- processing memorized commands...\n\n",
(long)(lastart - tmpfirst + 1),
(lastart > tmpfirst ? "s have" : " has" ) );
ELSE /* my, my, how clever we are */
#endif
#ifdef TERSE
strcpy(buf, "More news -- auto-processing...\n\n");
#endif
if (has_normal_kills)
kill_unwanted(tmpfirst,buf,TRUE);
#endif
art = tmpart;
}
}
void
ng_skip()
{
#ifndef USE_NNTP /* never read it & cannot find it? */
if (errno != ENOENT) { /* has it not been deleted? */
clear();
# ifdef VERBOSE
IF(verbose)
printf("\n(Article %ld exists but is unreadable.)\n",(long)art)
FLUSH;
ELSE
# endif
# ifdef TERSE
printf("\n(%ld unreadable.)\n",(long)art) FLUSH;
# endif
if (novice_delays) {
pad(just_a_sec);
sleep(2);
}
}
inc_art(selected_only,FALSE); /* try next article */
#else /* USE_NNTP */
ART_NUM artnum;
clear();
# ifdef VERBOSE
IF(verbose)
fputs("Skipping unavailable article\n",stdout);
ELSE
# endif /* VERBOSE */
# ifdef TERSE
fputs("Skipping\n",stdout);
# endif /* TERSE */
if (novice_delays) {
pad(just_a_sec/3);
sleep(1);
}
art++;
artp++;
do {
/* tries to grab PREFETCH_SIZE XHDRS, flagging missing articles */
(void) fetchsubj(art, FALSE);
artnum = art+PREFETCH_SIZE-1;
if (artnum > lastart)
artnum = lastart;
while (art <= artnum) {
if (!(artp->flags & AF_MISSING))
return;
art++;
artp++;
}
} while (art <= lastart);
#endif /* USE_NNTP */
}
/* find the maximum article number of a newsgroup */
ART_NUM
getngsize(num)
register NG_NUM num;
{
register int len;
register char *nam;
char tmpbuf[LBUFLEN];
ART_POS oldsoft;
long last, first;
char ch;
nam = rcline[num];
len = rcnums[num] - 1;
softtries++;
#ifdef DEBUG
if (debug & DEB_SOFT_POINTERS)
printf("Softptr = %ld\n",(long)softptr[num]) FLUSH;
#endif
oldsoft = softptr[num];
#ifndef USE_NNTP
fseek(actfp,100000L,1); /* hopefully this forces a reread */
#endif
if ((softptr[num] = findact(tmpbuf, nam, len, (long)oldsoft)) >= 0) {
if (softptr[num] != oldsoft) {
softmisses++;
writesoft = TRUE;
}
}
else {
softptr[num] = 0;
if (RCCHAR(rcchar[num]) == ':')
rcchar[num] = NEGCHAR;
return TR_BOGUS; /* well, not so quietly, actually */
}
#ifdef DEBUG
if (debug & DEB_SOFT_POINTERS) {
printf("Should be %ld\n",(long)softptr[num]) FLUSH;
}
#endif
#ifndef ANCIENT_NEWS
sscanf(tmpbuf+len+1, "%ld %ld %c", &last, &first, &ch);
#else
sscanf(tmpbuf+len+1, "%ld %c", &last, &ch);
first = 1;
#endif
if (!abs1st[num])
abs1st[num] = (ART_NUM)first;
if (!in_ng) {
switch (ch) {
case 'n': moderated = getval("NOPOSTRING"," (no posting)"); break;
case 'm': moderated = getval("MODSTRING", " (moderated)"); break;
/* This shouldn't even occur. What are we doing in a non-existent
group? Disallow it. */
case 'x': return TR_BOGUS;
/* what should be done about refiled groups? rn shouldn't even
be in them (ie, if sci.aquaria is refiled to rec.aquaria, then
get the news there) */
case '=': return TR_BOGUS;
default: moderated = nullstr;
}
}
if (last < ngmax[num])
return ngmax[num];
return ngmax[num] = (ART_NUM)last;
}