warren@samsung.COM (Warren Lavallee) (11/16/89)
There seems to have been a bug in 1.10.1. For those of you
who ftp'ed it, and are not on the mailing list, here are the diffs.
1.10.1 dropped articles when the nntpd on the other side was failing.
The linked list stuff has been ripped out. It seems there is a bug
in nntpxmit with the linked list routines. It doesn't free() all
the memory correctly. This never showed up, because nntpxmit exited
quickly. It was easier to rip it out, than to fix it (makes more
sense too, linked lists are not needed.)
Here it is. If if doesn't work, you can ftp the new version from the same
place-- new name: nntplink1.10.2.tar.Z
diff -c -r ./Makefile ../src.1.10.1/Makefile
*** ./Makefile Wed Nov 15 12:19:25 1989
--- ../src.1.10.1/Makefile Wed Nov 15 07:28:48 1989
***************
*** 1,6
# NNTPlink....
DEFS=
# -lresolv needed below for pyramids
LIBS= -lresolv
CFLAGS= -g ${DEFS}
#
--- 1,7 -----
# NNTPlink....
DEFS=
# -lresolv needed below for pyramids
+ # -ldnet needed for DECnet support
LIBS= -lresolv
CFLAGS= -g ${DEFS}
#
***************
*** 9,17
DESTDIR=/usr/lib/news
! HFILES=get_tcp_conn.h sysexits.h nntp.h conf.h
! SRC=nntplink.c remote.c get_tcp_conn.c
! OBJ=nntplink.o remote.o get_tcp_conn.o
FILES=Makefile ${SRC} ${HFILES} nntplinks nntplink-kill README nntplink.8 sysexits.h
all: nntplink
--- 10,18 -----
DESTDIR=/usr/lib/news
! HFILES=get_tcp_conn.h llist.h sysexits.h nntp.h conf.h
! SRC=nntplink.c remote.c llist.c get_tcp_conn.c
! OBJ=nntplink.o remote.o llist.o get_tcp_conn.o
FILES=Makefile ${SRC} ${HFILES} nntplinks nntplink-kill README nntplink.8 sysexits.h
all: nntplink
***************
*** 28,34
cp ${FILES} rel
touch update
! nntplink.o: nntplink.c conf.h
get_tcp_conn.o: get_tcp_conn.c get_tcp_conn.h
--- 29,35 -----
cp ${FILES} rel
touch update
! nntplink.o: nntplink.c llist.h conf.h
get_tcp_conn.o: get_tcp_conn.c get_tcp_conn.h
***************
*** 33,38
get_tcp_conn.o: get_tcp_conn.c get_tcp_conn.h
remote.o: remote.c conf.h get_tcp_conn.h
install: nntplink
cp nntplink ${DESTDIR}
--- 34,41 -----
get_tcp_conn.o: get_tcp_conn.c get_tcp_conn.h
remote.o: remote.c conf.h get_tcp_conn.h
+
+ llist.o: llist.c llist.h
install: nntplink
cp nntplink ${DESTDIR}
diff -c -r ./nntplink.c ../src.1.10.1/nntplink.c
*** ./nntplink.c Wed Nov 15 18:22:46 1989
--- ../src.1.10.1/nntplink.c Wed Nov 15 07:28:53 1989
***************
*** 11,18
** 1.01.3 - 11-08-89 - Fix dprintf bug (big bug) <fletcher@cs.utexas.edu>
** 1.01.4 - 11-10-89 - Added HP/UX support. <icsu6000@cs.montana.edu>
** 1.10.0 - 11-11-89 - Initial public release
! ** 1.10.2 - 11-15-89 - Fixes major bug (dropped articles)---
! ** linked lists removed.
**
** Contributors/Testers:
** karl@tut.cis.ohio-state.edu (Karl Kleinpaste)
--- 11,18 -----
** 1.01.3 - 11-08-89 - Fix dprintf bug (big bug) <fletcher@cs.utexas.edu>
** 1.01.4 - 11-10-89 - Added HP/UX support. <icsu6000@cs.montana.edu>
** 1.10.0 - 11-11-89 - Initial public release
! ** 1.10.1 - 11-15-89 - Fix several bugs. Llist routines were also
! ** rewritten <jef@helios.ee.lbl.gov>.
**
** Contributors/Testers:
** karl@tut.cis.ohio-state.edu (Karl Kleinpaste)
***************
*** 20,25
** mcooper@usc.edu (Micheal Cooper)
** alden@gem.mps.ohio-state.edu (Dave Alden)
** icsu6000@caesar.cs.montana.edu (Mathisen)
**
** Testers:
** dubois@uakari.primate.wisc.edu (Paul Dubois)
--- 20,26 -----
** mcooper@usc.edu (Micheal Cooper)
** alden@gem.mps.ohio-state.edu (Dave Alden)
** icsu6000@caesar.cs.montana.edu (Mathisen)
+ ** jef@helios.ee.lbl.gov (Jef Poskanzer)
**
** Testers:
** dubois@uakari.primate.wisc.edu (Paul Dubois)
***************
*** 67,72
#endif SYSLOG
#include "nntp.h"
#ifdef BSD4_2
#include <sys/wait.h>
--- 68,74 -----
#endif SYSLOG
#include "nntp.h"
+ #include "llist.h"
#ifdef BSD4_2
#include <sys/wait.h>
***************
*** 105,111
char *Qfile; /* current queue file we're operating on */
FILE *Qfp; /* the (FILE *) for above */
char Article[MAXFNAME]; /* current article filename */
- char FailedArticle[MAXFNAME];/* article to requeue */
unsigned short connected = 0;
char nntpfile[128];
--- 107,112 -----
char *Qfile; /* current queue file we're operating on */
FILE *Qfp; /* the (FILE *) for above */
char Article[MAXFNAME]; /* current article filename */
unsigned short connected = 0;
char nntpfile[128];
***************
*** 130,135
FILE *Logfp = (FILE *)NULL;
#endif USELOG
struct {
u_long offered;
u_long accepted;
--- 131,138 -----
FILE *Logfp = (FILE *)NULL;
#endif USELOG
+ ll_t FailedArticles; /* list of failed articles */
+
struct {
u_long offered;
u_long accepted;
***************
*** 452,457
** Given a hostname to connect to, and a file of filenames (which contain
** netnews articles), send those articles to the named host using NNTP.
**
**
** Nntplink only makes sense when isQfile==TRUE.
** The one-shot option should be removed.
--- 455,461 -----
** Given a hostname to connect to, and a file of filenames (which contain
** netnews articles), send those articles to the named host using NNTP.
**
+ ** Return code behavior is different depending upon isQfile.
**
** TRUE - return TRUE if we contacted the remote and started
** transferring news - this is to decide whether to
***************
*** 453,460
** netnews articles), send those articles to the named host using NNTP.
**
**
! ** Nntplink only makes sense when isQfile==TRUE.
! ** The one-shot option should be removed.
**
** Return code:
** TRUE - if at least one article was offered without
--- 457,465 -----
**
** Return code behavior is different depending upon isQfile.
**
! ** TRUE - return TRUE if we contacted the remote and started
! ** transferring news - this is to decide whether to
! ** record CPU and transfer statistics.
**
** FALSE - a one-shot file transfer - return TRUE or FALSE depending
** upon whether we successfully transferred the one article.
***************
*** 456,477
** Nntplink only makes sense when isQfile==TRUE.
** The one-shot option should be removed.
**
! ** Return code:
! ** TRUE - if at least one article was offered without
! ** an error. We don't care whether it was rejected
! ** or not, or whether an error ocurred on any later
! ** article. The object is measure the health of
! ** the server so that we know when to backoff on
! ** the retry frequency. If the server can negotiate
! ** at least one article, it's healthy and we don't
! ** backoff.
! ** Note that any error causes the connection to be closed.
! **
! ** FALSE - if an error ocurred before an article could be
! ** offered. e.g., if the first sendarticle() fails.
! ** This implies the server is not healthy and that we
! ** close/reopen the connection using exponential backoff.
! **
*/
sendnews(host, transport, file, isQfile)
char *host, *file;
--- 461,468 -----
** transferring news - this is to decide whether to
** record CPU and transfer statistics.
**
! ** FALSE - a one-shot file transfer - return TRUE or FALSE depending
! ** upon whether we successfully transferred the one article.
*/
sendnews(host, transport, file, isQfile)
char *host, *file;
***************
*** 522,529
}
if (isQfile) {
- register int progress; /* the number of successful sendarticle()s */
-
/*
** We're sending a batch queue:
** open article
--- 513,518 -----
}
if (isQfile) {
/*
** We're sending a batch queue:
** open article
***************
*** 535,541
*/
catchsig(interrupted);
- progress = 0;
while((fp = getfp(Qfp, Article, sizeof(Article),
mesgid)) != (FILE *)NULL) {
if (!sendarticle(host, fp, mesgid)) {
--- 524,529 -----
*/
catchsig(interrupted);
while((fp = getfp(Qfp, Article, sizeof(Article),
mesgid)) != (FILE *)NULL) {
if (!sendarticle(host, fp, mesgid)) {
***************
*** 541,546
if (!sendarticle(host, fp, mesgid)) {
(void) fclose(fp);
requeue(Article);
cleanup();
goodbye(DONT_WAIT);
connected = 0;
--- 529,535 -----
if (!sendarticle(host, fp, mesgid)) {
(void) fclose(fp);
requeue(Article);
+ Article[0] = '\0';
cleanup();
goodbye(DONT_WAIT);
connected = 0;
***************
*** 545,551
goodbye(DONT_WAIT);
connected = 0;
restsig();
! return progress? TRUE:FALSE;
}
(void) fclose(fp);
progress++;
--- 534,540 -----
goodbye(DONT_WAIT);
connected = 0;
restsig();
! return(TRUE);
}
(void) fclose(fp);
}
***************
*** 548,554
return progress? TRUE:FALSE;
}
(void) fclose(fp);
- progress++;
}
cleanup();
--- 537,542 -----
return(TRUE);
}
(void) fclose(fp);
}
cleanup();
***************
*** 578,587
** if they drop it.
** Watch all network I/O for errors, return FALSE if
** the connection fails and we have to cleanup.
- ** Return TRUE means it was successful, or at least that it
- ** doesn't have to be requeued.
- ** Return FALSE means it needs to be requeued. This implies the
- ** connection is closed and reopened.
*/
sendarticle(host, fp, mesgid)
char *host;
--- 566,571 -----
** if they drop it.
** Watch all network I/O for errors, return FALSE if
** the connection fails and we have to cleanup.
*/
sendarticle(host, fp, mesgid)
char *host;
***************
*** 619,624
sprintf(errbuf, e_xfer, host, Article, buf);
log(L_NOTICE, errbuf);
}
}
if (code == ERR_XFERRJCT) {
/*
--- 603,609 -----
sprintf(errbuf, e_xfer, host, Article, buf);
log(L_NOTICE, errbuf);
}
+ return(FALSE);
}
if (ReQueue_Fails && code != ERR_XFERRJCT) {
requeue(Article);
***************
*** 620,631
log(L_NOTICE, errbuf);
}
}
! if (code == ERR_XFERRJCT) {
! /*
! * it failed, but they don't want it retransfered.
! * we fake success so that it is not requeued.
! */
! return(TRUE);
}
return(FALSE);
}
--- 605,613 -----
}
return(FALSE);
}
! if (ReQueue_Fails && code != ERR_XFERRJCT) {
! requeue(Article);
! Article[0] = '\0';
}
}
break;
***************
*** 627,633
*/
return(TRUE);
}
- return(FALSE);
}
break;
case ERR_GOTIT:
--- 609,614 -----
requeue(Article);
Article[0] = '\0';
}
}
break;
case ERR_GOTIT:
***************
*** 645,650
return(FALSE);
break;
default:
if (code < 0) {
if (errno > 0) {
--- 626,635 -----
return(FALSE);
break;
+ case ERR_COMMAND: /** Something is wrong. Let's ignore it and hope it */
+ case ERR_CMDSYN: /** goes away. */
+ break;
+
default:
if (code < 0) {
if (errno > 0) {
***************
*** 980,985
#ifdef CNEWS
if (index(filename, ' ') != NULL) {
sscanf(filename, "%s %s", buffer, mesgid);
#else
if (index(filename, '\t') != NULL) {
sscanf(filename, "%s\t%s", buffer, mesgid);
--- 965,972 -----
#ifdef CNEWS
if (index(filename, ' ') != NULL) {
sscanf(filename, "%s %s", buffer, mesgid);
+ strcpy(filename, buffer);
+ } else strcpy(mesgid, "");
#else
if (index(filename, '\t') != NULL) {
sscanf(filename, "%s\t%s", buffer, mesgid);
***************
*** 983,989
#else
if (index(filename, '\t') != NULL) {
sscanf(filename, "%s\t%s", buffer, mesgid);
- #endif
strcpy(filename, buffer);
} else strcpy(mesgid, "");
--- 970,975 -----
#else
if (index(filename, '\t') != NULL) {
sscanf(filename, "%s\t%s", buffer, mesgid);
strcpy(filename, buffer);
} else strcpy(mesgid, "");
#endif
***************
*** 986,991
#endif
strcpy(filename, buffer);
} else strcpy(mesgid, "");
if ((newfp = fopen(filename, mode)) == (FILE *)NULL) {
/*
--- 972,978 -----
sscanf(filename, "%s\t%s", buffer, mesgid);
strcpy(filename, buffer);
} else strcpy(mesgid, "");
+ #endif
if ((newfp = fopen(filename, mode)) == (FILE *)NULL) {
/*
***************
*** 1019,1025
if (Qfp == (FILE *)NULL || Qfile == (char *)NULL)
return;
! if ((ReQueue_Fails && FailedArticle[0] != '\0') || !feof(Qfp)) {
rewrite();
} else {
/*
--- 1006,1012 -----
if (Qfp == (FILE *)NULL || Qfile == (char *)NULL)
return;
! if ((ReQueue_Fails && FailedArticles) || !feof(Qfp)) {
rewrite();
} else {
/*
***************
*** 1050,1060
requeue(article)
char *article;
{
- /*
- * A NULL parameter means clear the failed article. This is a hack.
- * This really doesn't belong here (should be a separate function),
- * but it's easy to do that later.
- */
if (article == (char *)NULL) {
dprintf(stderr, "%s: requeue(): reset\n", Pname);
FailedArticle[0] = '\0';
--- 1037,1042 -----
requeue(article)
char *article;
{
if (article == (char *)NULL) {
dprintf(stderr, "%s: requeue(): reset\n", Pname);
l_free(FailedArticles);
***************
*** 1057,1065
*/
if (article == (char *)NULL) {
dprintf(stderr, "%s: requeue(): reset\n", Pname);
! FailedArticle[0] = '\0';
! return;
! }
/*
* We should never have more than one failed article.
--- 1039,1047 -----
{
if (article == (char *)NULL) {
dprintf(stderr, "%s: requeue(): reset\n", Pname);
! l_free(FailedArticles);
! FailedArticles = (ll_t)NULL;
! } else {
if ((article == NULL) || (*article == '\0'))
return;
***************
*** 1061,1076
return;
}
! /*
! * We should never have more than one failed article.
! * Scream loudly if we do.
! */
! if (FailedArticle[0] != '\0') {
! char buf[2*MAXFNAME];
! sprintf(buf, "Two failures: %s and %s\n", FailedArticle, article);
! log(L_NOTICE, buf);
! return;
! }
dprintf(stderr, "%s: requeue(%s)\n", Pname, article);
(void)strncpy(FailedArticle, article, sizeof FailedArticle);
--- 1043,1050 -----
FailedArticles = (ll_t)NULL;
} else {
! if ((article == NULL) || (*article == '\0'))
! return;
dprintf(stderr, "%s: requeue(%s)\n", Pname, article);
***************
*** 1072,1079
return;
}
! dprintf(stderr, "%s: requeue(%s)\n", Pname, article);
! (void)strncpy(FailedArticle, article, sizeof FailedArticle);
}
/*
--- 1046,1060 -----
if ((article == NULL) || (*article == '\0'))
return;
! dprintf(stderr, "%s: requeue(%s)\n", Pname, article);
!
! if ((FailedArticles = l_alloc(FailedArticles, article, strlen(article) + 1)) == (ll_t)NULL) {
! fprintf(stderr, "%s: requeue(%s) failed, dumping fail list\n",
! Pname, article);
! l_free(FailedArticles);
! FailedArticles = (ll_t)NULL;
! }
! }
}
/*
***************
*** 1083,1088
*/
rewrite()
{
register FILE *tmpfp;
char *mode = "w+";
char *template = "/tmp/nntpxmitXXXXXX";
--- 1064,1070 -----
*/
rewrite()
{
+ register ll_t lp;
register FILE *tmpfp;
register int nart = 0;
char *mode = "w+";
***************
*** 1084,1089
rewrite()
{
register FILE *tmpfp;
char *mode = "w+";
char *template = "/tmp/nntpxmitXXXXXX";
char buf[BUFSIZ];
--- 1066,1072 -----
{
register ll_t lp;
register FILE *tmpfp;
+ register int nart = 0;
char *mode = "w+";
char *template = "/tmp/nntpxmitXXXXXX";
char buf[BUFSIZ];
***************
*** 1119,1127
** Here we write out the filenames of articles which
** failed at the remote end.
*/
! if (FailedArticle[0] != '\0') {
! fprintf(tmpfp, "%s\n", FailedArticle);
! dprintf(stderr, "%s: wrote %s to %s\n", Pname, FailedArticle, tempfile);
}
else {
dprintf(stderr, "%s: no failed articles to rewrite.\n", Pname);
--- 1102,1112 -----
** Here we write out the filenames of articles which
** failed at the remote end.
*/
! dprintf(stderr, "%s: writing failed article filenames to %s\n",
! Pname, tempfile);
! L_LOOP(lp, FailedArticles) {
! fprintf(tmpfp, "%s\n", lp->l_item);
! nart++;
}
dprintf(stderr, "%s: wrote %d article filenames to %s\n",
Pname, nart, tempfile);
***************
*** 1123,1131
fprintf(tmpfp, "%s\n", FailedArticle);
dprintf(stderr, "%s: wrote %s to %s\n", Pname, FailedArticle, tempfile);
}
! else {
! dprintf(stderr, "%s: no failed articles to rewrite.\n", Pname);
! }
(void) fflush(tmpfp);
/*
--- 1108,1115 -----
fprintf(tmpfp, "%s\n", lp->l_item);
nart++;
}
! dprintf(stderr, "%s: wrote %d article filenames to %s\n",
! Pname, nart, tempfile);
(void) fflush(tmpfp);
/*
Only in .: nntplink.c.orig
--
Samsung Software America. Warren J. Lavallee
UUCP: ...!uunet!samsung!warren NEARnet/Internet: warren@samsung.com
"Punishment becomes ineffective after a certain point. Men become insensitive."
-- Eneg, "Patterns of Force," stardate 2534.7.