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.