[comp.bugs.4bsd] uucp turnaround fails

jeff@voder.UUCP (03/27/87)

Index:	usr.bin/uucp/cntrl.c 4.3BSD +FIX

Description:
	The 4.3BSD uucp contains some new code that tries to turn
	the line around periodically.  The intent is keep one side
	from being master for a very long period of time.  This is
	implemented by having the slave periodically request to
	become master.

	Unfortunately, the turnaround code doesn't work with 'R'
	requests (i.e., when the master is receiving a file from the
	slave).  When the transfer completes the *master* sends a 'CYM'
	message; the slave tries to turn the line around, but the
	master is trying to send the next work request.

Repeat-By:
	Get another 4.3 site to put a couple of files in their public
	uucp directory.  Make sure their length is such that it will
	take more than a minute to transfer the first.  Queue a couple
	of requests to retrieve these files from the other system, then
	start a uucico.  Note that the first file is transferred, then
	the the protocol breaks down and the slave hangs up the line
	[complaining "BAD READ (expected 'H', got R ..."].

		uucp -r remote!~/publicfile1 ~uucp
		uucp -r remote!~/publicfile2 ~uucp
		/usr/lib/uucp/uucico -r1 -sremote -x5 -t1

Fix:
	The following patch solves the problem.  Basically there are
	two pieces here.  First, make sure that we only try to turn the
	line around if we are the master.  This protects us from other
	4.3 sites running the broken uucp.

	Second, implement the turnaround code for 'R' request so that
	it actually works (assuming the other site has made the same
	change).  This is done by having the slave return 'RY 644 M' if
	it wants the line turned around after this transfer.  (Note
	that we can't return 'RYM 644'.  The receiving end does a
	scanf() to find the file mode, starting at the third character
	of the string.)  This should interroperate properly with
	pre-4.3 uucp's, broken 4.3 uucp's, as well as fixed 4.3
	uucp's.

RCS file: RCS/cntrl.c,v
retrieving revision 1.2
diff -c -r1.2 cntrl.c
*** /tmp/,RCSt1005969	Thu Mar 26 19:23:41 1987
--- cntrl.c	Wed Mar 25 18:47:11 1987
***************
*** 302,308 ****
  		if (role == MASTER) {
  			notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
  		}
! 		if (msg[2] == 'M') {
  			extern int Nfiles;
  			WMESG(HUP, "");
  			RMESG(HUP, msg, 1);
--- 302,308 ----
  		if (role == MASTER) {
  			notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
  		}
! 		if (msg[2] == 'M' && role == MASTER) {
  			extern int Nfiles;
  			WMESG(HUP, "");
  			RMESG(HUP, msg, 1);
***************
*** 569,580 ****
  				strcat(filename, lastpart(W_FILE1));
  			}
  			status = xmv(Dfile, filename);
! 			if (willturn && Now.time > (LastTurned.time+turntime)
! 				&& iswrk(Wfile, "chk", Spool, wkpre)) {
! 					WMESG(RQSTCMPT, status ? EM_RMTCP : "YM");
! 					willturn = -1;
! 			} else
! 				WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
  			notify(mailopt, W_USER, filename, Rmtname,
  				status ? EM_LOCCP : YES);
  			if (status == 0) {
--- 569,575 ----
  				strcat(filename, lastpart(W_FILE1));
  			}
  			status = xmv(Dfile, filename);
! 			WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
  			notify(mailopt, W_USER, filename, Rmtname,
  				status ? EM_LOCCP : YES);
  			if (status == 0) {
***************
*** 588,593 ****
--- 583,602 ----
  				putinpub(filename, Dfile, W_USER);
  				USRF(USR_LOCCP);
  			}
+ 			if (msg[strlen(msg)-1] == 'M') {
+ 				extern int Nfiles;
+ 				WMESG(HUP, "");
+ 				RMESG(HUP, msg, 1);
+ 				logent(Rmtname, "TURNAROUND");
+ #ifdef USG
+ 				time(&LastTurned.time);
+ 				LastTurned.millitm = 0;
+ #else !USG
+ 				ftime(&LastTurned);
+ #endif !USG
+ 				Nfiles = 0; /* force rescan of queue for work */
+ 				goto process;
+ 			}
  			goto top;
  		}
  
***************
*** 635,641 ****
  		ret = fstat(fileno(fp), &stbuf);
  		ASSERT(ret != -1, "STAT FAILED", filename, 0);
  		i = 1 + (int)(stbuf.st_size / XFRRATE);
! 		sprintf(msg, "%s %o", YES, (int)stbuf.st_mode & 0777);
  		WMESG(RCVFILE, msg);
  		if (send_or_receive != SNDFILE) {
  			send_or_receive = SNDFILE;
--- 644,655 ----
  		ret = fstat(fileno(fp), &stbuf);
  		ASSERT(ret != -1, "STAT FAILED", filename, 0);
  		i = 1 + (int)(stbuf.st_size / XFRRATE);
! 		if (willturn && Now.time > (LastTurned.time+turntime)
! 			&& iswrk(Wfile, "chk", Spool, wkpre)) {
! 				willturn = -1;
! 		}
! 		sprintf(msg, "%s %o %s", YES, (int)stbuf.st_mode & 0777,
! 			willturn < 0 ? "M" : "");
  		WMESG(RCVFILE, msg);
  		if (send_or_receive != SNDFILE) {
  			send_or_receive = SNDFILE;

-- 

Jeff Gilliam	{ucbvax,pyramid,nsc}!voder!jeff