diff -rc inn-2.1/nnrpd/article.c inn-2.1-sg/nnrpd/article.c *** inn-2.1/nnrpd/article.c Fri Jul 24 09:13:00 1998 --- inn-2.1-sg/nnrpd/article.c Fri Aug 14 15:53:31 1998 *************** *** 97,102 **** --- 97,106 ---- STATIC struct iovec iov[IOV_MAX]; STATIC int queued_iov = 0; + /* Prototypes */ + STATIC BOOL IsCancelled(int artnum); + STATIC BOOL IsCancelledByIndex(int i, int artnum); + BOOL PushIOv(void) { fflush(stdout); if (writev(STDOUT_FILENO, iov, queued_iov) <= 0) { *************** *** 229,234 **** --- 233,241 ---- ARTHANDLE *art; struct timeval stv, etv; + if (IsCancelledByIndex(i,0)) + return FALSE; + if (ARTnumbers[i].Tokenretrieved) token = ARTnumbers[i].Token; else { *************** *** 277,297 **** return -1; top = &ARTnumbers[ARTsize - 1]; ! if (ARTcache && (++ARTcache <= top) && (ARTcache->ArtNum <= i)) { ! if (ARTcache->ArtNum == i) { if (needcheck) { return ARTinstore(ARTcache - ARTnumbers) ? (ARTcache - ARTnumbers) : -1; } ! return ARTcache - ARTnumbers; ! } ! bottom = ARTcache; } ! else { ! ARTcache = NULL; ! bottom = ARTnumbers; ! } for ( ; ; ) { if ((i < bottom->ArtNum) || (i > top->ArtNum)) break; --- 284,345 ---- return -1; top = &ARTnumbers[ARTsize - 1]; ! if (ARTcache) { ! /* They're finding the same article again. */ ! if (ARTcache->ArtNum == i) { if (needcheck) { return ARTinstore(ARTcache - ARTnumbers) ? (ARTcache - ARTnumbers) : -1; } ! else ! return ARTcache - ARTnumbers; ! } ! else if ((++ARTcache <= top) && (ARTcache->ArtNum <= i)) { ! /* Next article. */ ! if (ARTcache->ArtNum == i) { ! if (needcheck) { ! return ARTinstore(ARTcache - ARTnumbers) ! ? (ARTcache - ARTnumbers) : -1; ! } ! else ! return ARTcache - ARTnumbers; ! } ! bottom = ARTcache; ! } ! else if ( (ARTcache->ArtNum > i) && ((--ARTcache)->ArtNum < i) ) { ! /* Missing article. */ ! return -1; ! } ! else { ! ARTcache=NULL; ! bottom = ARTnumbers; ! } } ! else ! bottom=ARTnumbers; + /* The first hit when looping through is always bottom. + * This is a common case, and also happens to be the worst-case + * for this binary search. + * So take the gamble, and check it. + */ + if (bottom->ArtNum >= i) + { + ARTcache=bottom; + if (bottom->ArtNum == i) + { + if (needcheck) { + return ARTinstore(bottom - ARTnumbers) + ? (bottom-ARTnumbers) : -1; + } + return bottom-ARTnumbers; + } + else + { + /* The first article requested has already been cancelled. */ + return -1; + } + } for ( ; ; ) { if ((i < bottom->ArtNum) || (i > top->ArtNum)) break; *************** *** 342,349 **** return FALSE; if ((ARTnumbers[i].ArtNum == artnum) && innconf->storageapi) { ! if (ARTnumbers[i].Token.cancelled) ! return FALSE; if (ARTnumbers[i].Tokenretrieved) token = ARTnumbers[i].Token; else { --- 390,398 ---- return FALSE; if ((ARTnumbers[i].ArtNum == artnum) && innconf->storageapi) { ! if (IsCancelledByIndex(i,artnum)) ! return FALSE; ! if (ARTnumbers[i].Tokenretrieved) token = ARTnumbers[i].Token; else { *************** *** 463,468 **** --- 512,581 ---- } /* + * Figure out if an article has been cancelled. + * As a side-effect (and a very important one), sets + * the Token for the article. + * IsCancelled uses the article number proper. + * IsCancelledByIndex uses an index into ARTnumbers. + */ + STATIC BOOL IsCancelled(int artnum) + { + int i; + + if (!innconf->storageapi) + return FALSE; + + if ((i = ARTfind(artnum, FALSE)) < 0) + return TRUE; + + + return IsCancelledByIndex(i,artnum); + } + + STATIC BOOL IsCancelledByIndex(int i, int artnum) + { + OVERINDEX index; + char *tokentext; + + if (!innconf->storageapi) + return FALSE; + + if (ARTnumbers[i].Token.cancelled) + return TRUE; + if (ARTnumbers[i].Tokenretrieved) { + if (ARTnumbers[i].Token.type == TOKEN_EMPTY) + return TRUE; + return FALSE; + } + + if ((artnum && (ARTnumbers[i].ArtNum != artnum)) || !ARTnumbers[i].Index) + return ARTnumbers[i].Token.cancelled = TRUE; + + UnpackOverIndex(*(ARTnumbers[i].Index), &index); + if (artnum && (index.artnum != artnum)) + return ARTnumbers[i].Token.cancelled = TRUE; + + #ifndef DO_TAGGED_HASH + if (innconf->extendeddbz) { + if (!OVERgetent(&index.hash, &ARTnumbers[i].Token)) + return ARTnumbers[i].Token.cancelled = TRUE; + } else { + if (HISgetent(&index.hash, FALSE, &ARTnumbers[i].Offset) == (char *)NULL) + return ARTnumbers[i].Token.cancelled = TRUE; + } + if (innconf->extendeddbz) + return FALSE; + #endif + + ARTnumbers[i].Tokenretrieved = TRUE; + if ((tokentext = HISgetent(&index.hash, TRUE, &ARTnumbers[i].Offset)) == (char *)NULL) + return ARTnumbers[i].Token.cancelled = TRUE; + + ARTnumbers[i].Token = TextToToken(tokentext); + + return FALSE; + } + /* ** Send a (part of) a file to stdout, doing newline and dot conversion. */ STATIC void ARTsendmmap(SENDTYPE what) *************** *** 894,959 **** return FALSE; } rp->High = rp->Low = ARTnumbers[ARTindex].ArtNum; ! if (!innconf->storageapi) ! return TRUE; ! if ((i = ARTfind(rp->High, FALSE)) < 0) ! return FALSE; ! if (ARTnumbers[i].Token.cancelled) ! return FALSE; ! if (ARTnumbers[i].Tokenretrieved) { ! if (ARTnumbers[i].Token.type == TOKEN_EMPTY) ! return FALSE; ! return TRUE; ! } ! if ((ARTnumbers[i].ArtNum != rp->High) || !ARTnumbers[i].Index) { ! ARTnumbers[i].Token.cancelled = TRUE; ! return FALSE; ! } ! UnpackOverIndex(*(ARTnumbers[i].Index), &index); ! if (index.artnum != rp->High) { ! ARTnumbers[i].Token.cancelled = TRUE; ! return FALSE; ! } ! ARTnumbers[i].Tokenretrieved = TRUE; ! if ((tokentext = HISgetent(&index.hash, FALSE, NULL)) == (char *)NULL) { ! ARTnumbers[i].Token.cancelled = TRUE; ! return FALSE; ! } ! ARTnumbers[i].Token = TextToToken(tokentext); ! return TRUE; } /* Got just a single number? */ if ((p = strchr(av[1], '-')) == NULL) { rp->Low = rp->High = atol(av[1]); ! if (!innconf->storageapi) { ! return TRUE; ! } ! if ((i = ARTfind(rp->Low, FALSE)) < 0) ! return FALSE; ! if (ARTnumbers[i].Token.cancelled) ! return FALSE; ! if (ARTnumbers[i].Tokenretrieved) { ! if (ARTnumbers[i].Token.type == TOKEN_EMPTY) ! return FALSE; ! return TRUE; ! } ! if ((ARTnumbers[i].ArtNum != rp->Low) || !ARTnumbers[i].Index) { ! ARTnumbers[i].Token.cancelled = TRUE; ! return FALSE; ! } ! UnpackOverIndex(*(ARTnumbers[i].Index), &index); ! if (index.artnum != rp->Low) { ! ARTnumbers[i].Token.cancelled = TRUE; ! return FALSE; ! } ! ARTnumbers[i].Tokenretrieved = TRUE; ! if ((tokentext = HISgetent(&index.hash, FALSE, NULL)) == (char *)NULL) { ! ARTnumbers[i].Token.cancelled = TRUE; ! return FALSE; ! } ! ARTnumbers[i].Token = TextToToken(tokentext); ! return TRUE; } /* Parse range. */ --- 1007,1019 ---- return FALSE; } rp->High = rp->Low = ARTnumbers[ARTindex].ArtNum; ! return !IsCancelled(rp->High); } /* Got just a single number? */ if ((p = strchr(av[1], '-')) == NULL) { rp->Low = rp->High = atol(av[1]); ! return !IsCancelled(rp->Low); } /* Parse range. */ *************** *** 968,1038 **** if (rp->Low < ARTnumbers[0].ArtNum) rp->Low = ARTnumbers[0].ArtNum; } ! else ! /* No articles; make sure loops don't run. */ ! rp->High = rp->Low ? rp->Low - 1 : 0; ! if (!innconf->storageapi) ! return TRUE; ! for (artnum = rp->Low; artnum <= rp->High; artnum++) { ! if ((i = ARTfind(artnum, FALSE)) < 0) ! continue; ! if (ARTnumbers[i].Token.cancelled) ! continue; ! if (ARTnumbers[i].Token.type != TOKEN_EMPTY) ! continue; ! if ((ARTnumbers[i].ArtNum != artnum) || !ARTnumbers[i].Index) { ! ARTnumbers[i].Token.cancelled = TRUE; ! continue; ! } ! UnpackOverIndex(*(ARTnumbers[i].Index), &index); ! if (index.artnum != artnum) { ! ARTnumbers[i].Token.cancelled = TRUE; ! continue; ! } ! #ifdef DO_TAGGED_HASH ! ARTnumbers[i].Tokenretrieved = TRUE; ! if (HISgetent(&index.hash, FALSE, &ARTnumbers[i].Offset) == (char *)NULL) { ! ARTnumbers[i].Token.cancelled = TRUE; ! continue; ! } ! if ((tokentext = HISgetent(&index.hash, TRUE, &ARTnumbers[i].Offset)) == (char *)NULL) { ! ARTnumbers[i].Token.cancelled = TRUE; ! continue; ! } ! ARTnumbers[i].Token = TextToToken(tokentext); ! #else ! if (innconf->extendeddbz) { ! if (!OVERgetent(&index.hash, &ARTnumbers[i].Token)) { ! ARTnumbers[i].Token.cancelled = TRUE; ! continue; ! } ! } else { ! if (HISgetent(&index.hash, FALSE, &ARTnumbers[i].Offset) == (char *)NULL) { ! ARTnumbers[i].Token.cancelled = TRUE; ! continue; ! } ! } ! #endif ! } ! #ifdef DO_TAGGED_HASH return TRUE; - #else - if (innconf->extendeddbz) - return TRUE; - for (artnum = rp->Low; artnum <= rp->High; artnum++) { - if ((i = ARTfind(artnum, FALSE)) < 0) - continue; - if (ARTnumbers[i].Token.cancelled) - continue; - ARTnumbers[i].Tokenretrieved = TRUE; - if ((tokentext = HISgetent(&index.hash, TRUE, &ARTnumbers[i].Offset)) == (char *)NULL) { - ARTnumbers[i].Token.cancelled = TRUE; - continue; - } - ARTnumbers[i].Token = TextToToken(tokentext); - } - return TRUE; - #endif } --- 1028,1035 ---- if (rp->Low < ARTnumbers[0].ArtNum) rp->Low = ARTnumbers[0].ArtNum; } ! return TRUE; } *************** *** 1486,1492 **** continue; /* Get it from the overview? */ ! if (Overview && (p = OVERfind(i, &linelen)) != NULL) { p = OVERGetHeader(p, Overview); Printf("%ld %s\r\n", i, p && *p ? p : "(none)"); continue; --- 1483,1489 ---- continue; /* Get it from the overview? */ ! if (Overview && !IsCancelled(i) && (p = OVERfind(i, &linelen)) != NULL) { p = OVERGetHeader(p, Overview); Printf("%ld %s\r\n", i, p && *p ? p : "(none)"); continue; *************** *** 1542,1548 **** OVERcount++; Reply("%d data follows\r\n", NNTP_OVERVIEW_FOLLOWS_VAL); for (Opened = OVERopen(), i = range.Low; i <= range.High; i++) { ! if (ARTfind(i, innconf->storageapi && innconf->nnrpdcheckart) < 0) { if (innconf->storageapi) OVERmiss++; continue; --- 1539,1545 ---- OVERcount++; Reply("%d data follows\r\n", NNTP_OVERVIEW_FOLLOWS_VAL); for (Opened = OVERopen(), i = range.Low; i <= range.High; i++) { ! if (IsCancelled(i)) { if (innconf->storageapi) OVERmiss++; continue; *************** *** 1668,1673 **** --- 1665,1671 ---- /* Get it from the Overview? */ if (Overview + && !IsCancelled(i) && (p = OVERfind(i, &linelen)) != NULL && (p = OVERGetHeader(p, Overview)) != NULL) { if (wildmat(p, pattern)) diff -rc inn-2.1/nnrpd/nnrpd.c inn-2.1-sg/nnrpd/nnrpd.c *** inn-2.1/nnrpd/nnrpd.c Fri Jul 24 09:13:00 1998 --- inn-2.1-sg/nnrpd/nnrpd.c Fri Aug 14 16:00:11 1998 *************** *** 493,504 **** length = sizeof sin; ClientAddr = NULL; if (getpeername(STDIN, (struct sockaddr *)&sin, &length) < 0) { ! if (!isatty(STDIN)) { syslog(L_TRACE, "%s cant getpeername %m", "?"); (void)strcpy(ClientHost, "?"); /* so stats generation looks correct. */ Printf("%d I can't get your name. Goodbye.\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } (void)strcpy(ClientHost, "stdin"); ClientIP = 0L; } --- 493,506 ---- length = sizeof sin; ClientAddr = NULL; if (getpeername(STDIN, (struct sockaddr *)&sin, &length) < 0) { ! #ifndef DEBUG ! if (!isatty(STDIN)) { syslog(L_TRACE, "%s cant getpeername %m", "?"); (void)strcpy(ClientHost, "?"); /* so stats generation looks correct. */ Printf("%d I can't get your name. Goodbye.\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } + #endif (void)strcpy(ClientHost, "stdin"); ClientIP = 0L; } *************** *** 561,566 **** --- 563,569 ---- #if !defined(VAR_NONE) + #if !defined(VAR_NONE) #if defined(VAR_VARARGS) #if defined(lint) #define START_VARARG(fmt, vp, type) va_start(vp); fmt = NULL *************** *** 571,576 **** --- 574,580 ---- #if defined(VAR_STDARGS) #define START_VARARG(fmt, vp, type) va_start(vp, fmt) #endif /* defined(VAR_STDARGS) */ + #endif /* defined(VAR_NONE) */ /* ** Send a reply, possibly with debugging output.