[news.software.nntp] nntplink yet again: patch for 1.10.1 --> 1.10.2

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.