From pa.dec.com!decwrl!uunet!sparky!kent Sun Aug 11 15:43:28 PDT 1991
Article: 2586 of comp.sources.misc
Newsgroups: comp.sources.misc
Path: pa.dec.com!decwrl!uunet!sparky!kent
From: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
Subject:  v21i076:  ecu - ECU async comm package rev 3.10, Part24/37
Message-ID: <1991Aug4.163051.18724@sparky.IMD.Sterling.COM>
X-Md4-Signature: 769429950982656a431ab4af77108c77
Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield)
Organization: Sterling Software, IMD
References: <csm-v21i053=ecu.215539@sparky.imd.sterling.com>
Date: Sun, 4 Aug 1991 16:30:51 GMT
Approved: kent@sparky.imd.sterling.com
Lines: 2071

Submitted-by: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
Posting-number: Volume 21, Issue 76
Archive-name: ecu/part24
Environment: SCO, XENIX, ISC
Supersedes: ecu3: Volume 16, Issue 25-59

---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is ecu310.24 (part 24 of ecu310)
# do not concatenate these parts, unpack them in order with /bin/sh
# file sea/ecusea.c continued
#
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 24; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping sea/ecusea.c'
else
echo 'x - continuing file sea/ecusea.c'
sed 's/^X//' << 'SHAR_EOF' >> 'sea/ecusea.c' &&
X{
Xchar *cancel_msg = "\030\030\030\030\030\030\030\030\b\b\b\b\b\b\b\b";
X
X	ioctl(iofd,TCFLSH,(char *)1);
X	write(iofd,cancel_msg,16);
X	tx_char_count += 16;
X	report_str("CANCELling transfer",1);
X	report_last_txhdr("CAN",0);
X
X}	/* end of xmit_cancel */
X
X/*+-------------------------------------------------------------------------
X	xmit_ack(blknum)
X--------------------------------------------------------------------------*/
Xvoid
Xxmit_ack(blknum)
Xregister int blknum;			/* block number */
X{
Xchar s16[16];
X
X	sprintf(s16,"ACK %3d",blknum);
X	report_last_txhdr(s16,0);
X
X	s16[0] = ACK;
X	s16[1] = blknum;			/* block number */
X	s16[2] = blknum ^ 0xFF;	/* block number check */
X	write(iofd,s16,3);
X	tx_char_count += 3;
X}	/* end of xmit_ack */
X
X/*+-------------------------------------------------------------------------
X	xmit_nak(blknum)
X--------------------------------------------------------------------------*/
Xvoid
Xxmit_nak(blknum)
Xregister int blknum;			/* block number */
X{
Xchar s16[16];
X
X	sprintf(s16,"NAK %d",blknum);
X	report_last_txhdr(s16,1);
X
X	if(crc_in_use)
X		s16[0] = 'C';
X	else
X		s16[0] = NAK;
X
X	s16[1] = blknum;			/* block number */
X	s16[2] = blknum ^ 0xFF;	/* block number check */
X	write(iofd,s16,3);
X	tx_char_count += 3;
X
X}	/* end of xmit_nak */
X
X/*+-------------------------------------------------------------------------
X	lgetc_timeout_SIGALRM() - called when alarm is caught by lgetc_timeout
X--------------------------------------------------------------------------*/
X#if defined(NO_SELECT)
Xvoid
Xlgetc_timeout_SIGALRM()
X{
X	longjmp(lgetc_timeout_setjmp,TIMEOUT);
X}	/* end of lgetc_timeout_SIGALRM */
X#endif
X
X/*+-------------------------------------------------------------------------
X	lgetc_timeout(tenths)
X
X reads one character from line unless timeout in tenths passes
X with no receipt.
X--------------------------------------------------------------------------*/
Xunsigned int
Xlgetc_timeout(tenths)
Xint tenths;
X{
X#if defined(NO_SELECT)
Xunsigned char rdchar;
Xlong msec;
Xint seconds;
Xlong nap(long);
X#else
Xint fdmask;
Xstruct timeval tval;
Xunsigned char rdchar;
X#endif
X
X	if(!tenths)
X	{
X		if(!rdchk(iofd))
X			return(TIMEOUT);
X		else
X		{
X			read(iofd,&rdchar,1);
X			rx_char_count++;
X			return((unsigned int)rdchar);
X		}
X	}
X
X#if defined(NO_SELECT)
X
X/* there is a timeout ... if less than 2 secs, nap it out */
X	if(tenths <= 20)
X	{
X		msec = (tenths < 6) ? 60L : (long)tenths * 10;
X		while(msec)
X		{
X			msec -= nap(20L);
X			if(rdchk(iofd))
X			{
X				read(iofd,&rdchar,1);
X				rx_char_count++;
X				return((unsigned int)rdchar);
X			}
X		}
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X
X/* timeout is > 2 seconds use sleep */
X
X	seconds = (tenths / 10) + 1;
X
X	if(setjmp(lgetc_timeout_setjmp))
X	{
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X
X	signal(SIGALRM,lgetc_timeout_SIGALRM);
X	alarm(seconds);
X	while(read(iofd,&rdchar,1) != 1)
X		;
X	alarm(0);
X	signal(SIGALRM,SIG_DFL);
X
X#else
X
X	if(tenths < 6)
X		tenths = 6;
X	tval.tv_sec = tenths / 10L;
X	tval.tv_usec = (tenths % 10L) * 100000L;
X	fdmask = 1 << iofd;
X	if(select(32,&fdmask,(int *)0,(int *)0,&tval) != 1)
X	{
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X	if((!rdchk(iofd)) || (read(iofd,&rdchar,1) < 0))
X	{
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X
X#endif
X
X	rx_char_count++;
X	return((unsigned int)rdchar);
X
X}	/* end of lgetc_timeout */
X
X/*+-------------------------------------------------------------------------
X	sf_state_text(state)
X--------------------------------------------------------------------------*/
Xchar *
Xsf_state_text(state)
Xregister state;
X{
Xchar unrecog[16];
X
X	switch(state)
X	{
X		case SFS_GND:	return("GND");
X		case SFS_ACK:	return("ACK");
X		case SFS_NAK:	return("NAK");
X		case SFS_ACKW:	return("ACKW");
X		case SFS_NAKW:	return("NAKW");
X		case SFS_RGND:	return("RGND");
X		default:
X			sprintf(unrecog,"SFS_%d",state);
X			return(unrecog);
X	}
X
X}	/* end of sf_state_text */
X
X/*+-------------------------------------------------------------------------
X	set_sf_state(place,new_state)
X--------------------------------------------------------------------------*/
Xvoid
Xset_sf_state(place,new_state)
Xint place;
Xint new_state;
X{
X	if(log_packets)
X	{
X		sprintf(s128,"state from %s to %s (%d)",
X			sf_state_text(sf_state),sf_state_text(new_state),place);
X		report_str(s128,0);
X	}
X	sf_state = new_state;
X}	/* end of set_sf_state */
X
X/*+-------------------------------------------------------------------------
X	wait_for_rcvr_response() - check for ACK or NAK
X sets 'sf_state' to SFS_... value depending on response from file rcvr
X returns 1 if TIMEOUT at state other than ground, else 0
X--------------------------------------------------------------------------*/
Xint
Xwait_for_rcvr_response()
X{
Xint c;						/* one byte of data */
Xstatic int rawblk = 0;		/* raw block number */
X
X	while((c = lgetc_timeout((sf_state == SFS_GND) ? 0 : 6)) != TIMEOUT)
X	{
X		if(c == CAN)
X		{									/* CANcel received? */
X			if((c = lgetc_timeout(20)) == CAN)
X			{
X				sf_nakquan = 11;
X				report_last_rxhdr("CAN",0);	/* error counted at cancel time */
X			}
X			break;
X		}
X		if(sf_state == SFS_ACKW || sf_state == SFS_NAKW)	/* windowed */
X		{
X			sf_slide = 0;						/* assume this will fail */
X			/* see if we believe the number */
X			if(rawblk == (c ^ 0xFF))
X			{
X				rawblk = sf_blknum - ((sf_blknum - rawblk) & 0xFF);
X				if((rawblk >= 0) && (rawblk <= sf_blknum) &&
X					(rawblk > (sf_blknum - 128)))
X				{				/* we have sliding window! */
X					if(sf_state == SFS_ACKW)
X					{
X						sf_ackblk = (sf_ackblk > rawblk) ? sf_ackblk : rawblk;
X						sf_slide = 1;
X						if(no_ack_mode && (++sf_ackw_count > 10))
X						{
X							no_ack_mode = 0;
X							report_str("Overdrive disengaged",0);
X						}
X					}
X					else 
X					{
X						sf_blknum = (rawblk < 0) ? 0 : rawblk;
X						sf_slide = (sf_nakquan < 4);
X					}
X					sprintf(s128,"%s %5d",
X						(sf_state == SFS_ACKW) ? "ACKW" : "NAKW",rawblk);
X					report_last_rxhdr(s128,(sf_state != SFS_ACKW) && rawblk);
X				}
X			}
X			set_sf_state(1,SFS_RGND);	/* return to ground state */
X		}
X
X		if(sf_state == SFS_ACK || sf_state == SFS_NAK)
X		{
X			rawblk = c;
X			if(sf_state == SFS_ACK)
X				set_sf_state(2,SFS_ACKW);
X			else
X				set_sf_state(3,SFS_NAKW);
X		}
X
X		if(!sf_slide || sf_state == SFS_GND)
X		{
X			if(c == ACK)
X			{
X				if(!sf_slide)
X				{
X					sprintf(s128,"ACK %3d",sf_ackblk);
X					report_last_rxhdr(s128,0);
X					sf_ackblk++;
X				}
X				set_sf_state(4,SFS_ACK);
X				sf_nakquan = 0;
X			}
X			else if(c == 'C' || c == NAK)
X			{
X				/* if method not determined yet */
X				if(crc_in_use > 1)	/* then do what rcvr wants */
X				{
X					crc_in_use = (c == 'C');
X					report_protocol_crc_type(crc_in_use ? "/CRC16" : "/CHK");
X				}
X				ioctl(iofd,TCFLSH,(char *)1);
X				if(!sf_slide)
X				{
X					sf_blknum = sf_ackblk + 1;
X					sprintf(s128,"NAK %3d",sf_blknum);
X					report_last_rxhdr(s128,(!!sf_blknum));
X				}
X				set_sf_state(5,SFS_NAK);
X				sf_nakquan++;
X				if(sf_lastnum)
X					error_count++;
X			}
X		}
X
X		if(sf_state == SFS_RGND)
X			set_sf_state(6,SFS_GND);
X	}
X	return((sf_state != SFS_GND) && (c == TIMEOUT));
X}	/* end of wait_for_rcvr_response */
X
X/*+-------------------------------------------------------------------------
X	send_comm_block(blk,blknum) - format and transmit block
X--------------------------------------------------------------------------*/
Xint
Xsend_comm_block(blk,blknum)
Xchar *blk;				/* data to be shipped */
Xint blknum;				/* number of block */
X{
Xregister unsigned short rUINT16 = 0;
Xregister int itmp;
Xunsigned char chksum;
Xchar *cptr = blk;
Xchar s3[3];
X
X	s3[0] = SOH;				/* block header */
X	s3[1] = blknum;				/* block number */
X	s3[2] = blknum ^ 0xFF;		/* block number check value */
X
X/* calculate the crc or checksum */
X	itmp = 128;
X	if(crc_in_use)
X	{
X		while(itmp--)
X		{
X			rUINT16 = crc_update(*cptr,rUINT16);
X			cptr++;
X		}
X		rUINT16 = crc_update(0,rUINT16);
X		rUINT16 = crc_update(0,rUINT16);
X	}
X	else 
X	{
X		while(itmp--)
X			rUINT16 += *cptr++;
X	}
X
X/* write the block */
X
X	write(iofd,s3,3);						/* the header */
X	write(iofd,blk,128);					/* the block */
X	if(crc_in_use)							/* the crc or checksum */
X	{
X		s3[0] = rUINT16 >> 8;
X		s3[1] = rUINT16 & 0xFF;
X		write(iofd,s3,2);
X		tx_char_count += 133;
X	}
X	else
X	{
X		chksum = rUINT16;
X		write(iofd,&chksum,1);
X		tx_char_count += 132;
X	}
X
X	return(1);
X}	/* end of send_comm_block */
X
X/*+-------------------------------------------------------------------------
X	send_file_block(fp,blknum) - read a block from file and send it
X--------------------------------------------------------------------------*/
Xvoid
Xsend_file_block(fp,blknum)
XFILE *fp;
Xint blknum;
X{
Xlong fileaddr;
Xchar buf[128];
X
X	fileaddr = (long)(blknum - 1) * 128L;
X	if(blknum != sf_lastnum + 1)
X		fseek(fp,fileaddr,0);	/* move where to */
X	sf_lastnum = blknum;
X	report_txpos(fileaddr);
X
X	memset(buf,0x1A,sizeof(buf));	/* fill buffer with control Zs */
X	fread(buf,1,sizeof(buf),fp);	/* read in some data */
X	send_comm_block(buf,blknum);	/* pump it out to the receiver */
X}	/* end of send_file_block */
X
X/*+-------------------------------------------------------------------------
X	send_file(name) - transmit a file
X--------------------------------------------------------------------------*/
Xint
Xsend_file(name)
Xchar *name;
X{
Xregister int endblk;	/* block number of EOT */
XFILE *fp = (FILE *)0;	/* file to send */
Xstruct stat fst;
XBLK0 blk0;
Xchar *basename;			/* base filename */
Xchar eot = EOT;
X
X	Filcnt++;
X	if(name && *name)			/* if sending a file */
X	{
X		if((fp = fopen(name,"r")) == NULL)
X		{
X			sprintf(s128,"Cannot open %s",name);
X			report_str(s128,1);
X			exit_code = 253;
X			return(0);
X		}
X
X		memset((char *)&blk0,0,sizeof(blk0)); /* clear out data block */
X
X		stat(name,&fst);	/* get file statistics */
X		blk0.length = (long)fst.st_size;
X
X		/* cnvt time from 1970 base to 1980 */
X		if((blk0.secs_since_1980 = fst.st_mtime-OFFSET_1980) < 0L)
X			blk0.secs_since_1980 = 0;
X
X		if((basename = strrchr(name,'/')) == NULL) /* find basename */
X			strcpy(blk0.filename,name);
X		else 
X		{
X			basename++;
X			strcpy(blk0.filename,basename);
X		}
X
X		strcpy(blk0.sender,"ecusea ");
X		strcat(blk0.sender,revision);
X		blk0.send_no_acks = no_ack_mode;
X
X		endblk = (int)((blk0.length + 127L) / 128L) + 1;
X		report_file_send_open(name,&fst);
X	}
X	else 
X	{
X		endblk = 0;						/* fake for no file */
X		report_str("sending EOT indication",-1);
X		report_txpos(blk0.length);
X	}
X
X
X	sf_blknum = 1;						/* set starting state */
X	sf_ackblk = -1;
X	sf_state = SFS_GND;
X	sf_lastnum = 0;
X	sf_slide = 0;
X	sf_nakquan = 0;
X	error_count = 0;
X	sf_ackw_count = 0;
X	crc_in_use = 2;						/* undetermined */
X
X	while(sf_ackblk < endblk)			/* while not all there yet */
X	{
X		sent_EOT = 0;
X		if(sf_blknum <= sf_ackblk + ((sf_slide && allow_slide) ? WINDOW : 1))
X		{
X			if(sf_blknum < endblk)
X			{
X				if(sf_blknum > 0)
X				{
X					sprintf(s128,"sending block %d",sf_blknum);
X					report_last_txhdr(s128,0);
X					send_file_block(fp,sf_blknum);
X				}
X				else
X				{
X					sprintf(s128,"sending filename",sf_blknum);
X					report_last_txhdr(s128,0);
X					send_comm_block((char *)&blk0,0);
X					report_txpos(0L);
X				}
X				if(no_ack_mode && sf_slide && allow_slide)
X					sf_ackblk = sf_blknum;
X			}
X			else if(sf_blknum == endblk)
X			{
X				report_last_txhdr("EOT",0);
X				write(iofd,&eot,1);
X				sent_EOT = 1;
X				nap(500L);
X				tx_char_count++;
X			}
X			sf_blknum++;
X		}
X
X		if(wait_for_rcvr_response() && sent_EOT)
X		{
X			report_str("Receiver did not ACK our EOT",-1);
X			break;
X		}
X
X		if(sf_nakquan > 10)
X			goto CANCEL_TRANSFER;
X	}
X
X	if(endblk)	/* if sending file, not EOT */
X		fclose(fp);
X	return(1);							/* exit with good status */
X
XCANCEL_TRANSFER:
X	if(endblk)	/* if sending file, not EOT */
X		fclose(fp);
X	xmit_cancel();
X	return(0);                          /* exit with bad status */
X}	/* end of send_file */
X
X/*+-------------------------------------------------------------------------
X	set_utime_1980(filename,secs_since_1980)
X--------------------------------------------------------------------------*/
Xvoid
Xset_utime_1980(filename,secs_since_1980)
Xchar *filename;						/* file to set stamp on */
Xlong secs_since_1980;
X{
Xtime_t times[2];
Xtime_t time();
X
X	times[0] = time((long *) 0);				/* accessed */
X	times[1] = secs_since_1980 + OFFSET_1980;	/* modified (convert time) */
X	utime(filename,times);
X}	/* end of set_utime_1980 */
X
X/*+-------------------------------------------------------------------------
X	receive_block(buf) - get block from line
Xreturn 0 if good chk/CRC, 1 if bad
X--------------------------------------------------------------------------*/
Xint
Xreceive_block(buf)
Xchar *buf;				/* data buffer */
X{
Xregister unsigned int rdchar;	
Xregister unsigned short rUINT16 = 0;	/* calculated CRC or check value */
Xint itmp;
Xint timeout = no_ack_mode ? 200 : 5;	/* short block timeout */
Xunsigned short rcvd_crc;				/* received CRC or check value */
X
X	itmp = 128;
X	while(itmp--)
X	{
X		if((rdchar = lgetc_timeout(timeout)) == TIMEOUT)
X			return(1);
X		if(crc_in_use)
X			rUINT16 = crc_update(rdchar,rUINT16);
X		else
X			rUINT16 += rdchar;
X		*buf++ = rdchar;
X	}
X
X	if(crc_in_use)
X	{
X		rUINT16 = crc_update(0,rUINT16);
X		rUINT16 = crc_update(0,rUINT16);
X		rdchar = lgetc_timeout(timeout);
X		rcvd_crc = (rdchar << 8) | lgetc_timeout(timeout);
X	}
X	else 
X	{
X		rUINT16 &= 0xFF;
X		rcvd_crc = lgetc_timeout(timeout) & 0xFF;
X	}
X
X	if(rUINT16 != rcvd_crc)
X	{
X		sprintf(s128,"bad %s calc=%04x rcvd=%04x",
X			crc_in_use ? "CRC" : "checksum",rcvd_crc,rUINT16);
X		report_str(s128,-1);
X	}
X	return(rUINT16 != rcvd_crc);
X}	/* end of receive_block */
X
X/*+-------------------------------------------------------------------------
X	receive_file()
X--------------------------------------------------------------------------*/
Xchar *
Xreceive_file()
X{
Xint rdchar;					/* received character */
Xint tries;					/* retry counter */
Xint blknum;					/* desired block number */
Xint inblk;					/* this block number */
XFILE *fp;
Xchar buf[128];				/* data buffer */
Xchar tmpname[100];			/* name of temporary file */
Xstatic char outname[100];	/* name of final file */
XBLK0 blk0;					/* file header data storage */
Xint endblk;					/* block number of EOT, if known */
Xlong left = 0;				/* bytes left to output */
Xint itmp;					/* index */
Xint cnvrt;					/* flag -- convert filename? */
Xchar *onp;					/* use to convert filename to l / rdchar */
Xlong ftell();
X
X	*outname = '\0';		/* get name from transmitter */
X	cnvrt = 1;		/* convert to local is necessary */
X	sprintf(tmpname,"./SEA%05d.tmp",getpid());	/* use a unique temp filename */
X
X	if(!(fp = fopen(tmpname,"w")))
X	{	/* open temporary file */
X		sprintf(s128,"Cannot create temp file %s\n",tmpname);
X		report_str(s128,0);
X		xmit_cancel();
X		return(NULL);
X	}
X
X	blknum = 0;
X	tries = -10;				/* kludge for first time around */
X	crc_in_use = 1;				/* try for CRC error checking */
X	error_count = 0;			/* no errors yet */
X	endblk = 0;					/* we don't know the size yet */
X	no_ack_mode = 0;			/* we don't know about this yet */
X	memset((char *)&blk0,0,sizeof(blk0));	/* or much of anything else */
X	report_protocol_crc_type("/CRC16");
X
XSEND_NAK:				/* we got a bad block */
X	if(blknum > 1)
X	{
X		error_count++;
X		report_str("bad block",1);
X	}
X	if(++tries > 10)
X		goto CANCEL_TRANSFER;
X	if(tries == 0)			/* if CRC isn't going */
X	{
X		crc_in_use = 0;		/* then give checksum a try */
X		report_protocol_crc_type("/CHK");
X	}
X
X	xmit_nak(blknum);		/* send the NAK */
X	if(no_ack_mode && error_count > 20)
X	{	/* if no_ack_mode mode isn't working */
X		no_ack_mode = 0;		/* then shut it off */
X		report_str("Overdrive disengaged",0);
X	}
X
XRECEIVE_NEXT_BLOCK:				/* start of "get a block" */
X	report_rxpos(ftell(fp));
X	while((rdchar = lgetc_timeout(30)) != TIMEOUT)
X	{
X		if(rdchar == CAN)
X		{
X			if((rdchar = lgetc_timeout(30)) == CAN)
X			{
X				xmit_cancel();
X				return(NULL);
X			}
X			break;
X		}
X		if(rdchar == EOT)
X		{
X			if(!endblk || endblk == blknum)
X				goto RECEIVE_EOT_SEEN;
X		}
X		else if(rdchar == SOH)
X		{
X			if((inblk = lgetc_timeout(5)) == TIMEOUT)
X				goto SEND_NAK;
X			if(lgetc_timeout(5) == (inblk ^ 0xFF))
X			{
X				sprintf(s128,"receiving %d",inblk);
X				report_last_rxhdr(s128,0);
X				goto GOT_START_OF_BLOCK;	/* we found a start */
X			}
X		}
X	}
X	goto SEND_NAK;
X
XGOT_START_OF_BLOCK:				/* start of block detected */
X	rdchar = blknum & 0xFF;
X	if(inblk == 0 && blknum <= 1)
X	{	/* if this is the header */
X		if(receive_block((char *)&blk0))
X			goto SEND_NAK;		/* bad header block */
X		else 
X		{
X			xmit_ack(inblk);	/* ack the header */
X
X#if defined(M_UNIX)
X			if(fname_too_long(blk0.filename))
X			{
X				strcpy(s128,"truncated: ");
X				strncat(s128,blk0.filename,sizeof(s128) - 12);
X				report_str(s128,-1);
X				strcpy(outname,fname_truncated());
X			}
X			else
X#endif
X				strcpy(outname,blk0.filename);
X			report_file_rcv_started(outname,blk0.length,
X				blk0.secs_since_1980 + OFFSET_1980);
X			if(left = blk0.length)	/* length to transfer */
X				endblk=(int)((left + 127L)/128L)+1;
X			if(no_ack_mode != blk0.send_no_acks)
X			{
X				sprintf(s128,"Overdrive %sengaged",
X					(blk0.send_no_acks) ? "" : "dis");
X				report_str(s128,0);
X			}
X			no_ack_mode = blk0.send_no_acks;
X			blknum = 1;	/* now we want first data block */
X			goto RECEIVE_NEXT_BLOCK;
X		}
X	}
X
X	if(inblk == rdchar)
X	{			/* if this is the one we want */
X		if(!receive_block(buf))
X		{		/* else if we get it okay */
X			if(!no_ack_mode)		/* if we're sending ACKs */
X				xmit_ack(inblk);	/* then ACK the data */
X			for(itmp = 0; itmp < 128; itmp++)
X			{
X				if(endblk)
X				{	/* limit file size if known */
X					if(!left)
X						break;
X					left--;
X				}
X				if(fputc(buf[itmp],fp) == EOF)
X				{
X					report_str("FILE WRITE ERROR",0);
X					goto CANCEL_TRANSFER;
X				}
X			}
X			tries = 0;		/* reset try count */
X			blknum++;		/* we want the next block */
X			goto RECEIVE_NEXT_BLOCK;
X		}
X		goto SEND_NAK;		/* ask for a resend */
X	}
X
X	if(inblk < rdchar || inblk > rdchar + 100)
X	{	/* if resending what we have */
X		receive_block(buf);			/* ignore it */
X		xmit_ack(inblk);			/* but ack it */
X	}
X	goto RECEIVE_NEXT_BLOCK;		/* else if running ahead */
X
XRECEIVE_EOT_SEEN:
X#ifdef NAKEOT
X	xmit_nak(blknum);				/* NAK the EOT, make sure */
X	if(lgetc_timeout(20) != EOT)	/* we're all done */
X		goto SEND_NAK;
X#endif /* NAKEOT */
X	xmit_ack(blknum);				/* ACK it and clean up */
X	report_last_rxhdr("EOT",0);
X	if(blknum > 1)
X	{				/* if we really got anything */
X		fclose(fp);
X		unlink(outname);		/* rename temp to proper name */
X		for(onp = outname;cnvrt && *onp;onp++)
X			/* find out if there's lower- */
X			if(islower(*onp))	/* case letters filename */
X				cnvrt = 0;	/*  there are, don't convert */
X		if(cnvrt)			/* if there aren't, make all */
X			for(onp = outname;*onp;onp++)	/* into uppercase */
X				*onp = tolower(*onp);
X		if(link(tmpname,outname) == 0)
X			unlink(tmpname);
X		if(blk0.secs_since_1980)		/* set stamp, if known */
X			set_utime_1980(outname,blk0.secs_since_1980);
X		return(outname);
X	}
X	else 
X	{				/* else no real file */
X		fclose(fp);
X		unlink(tmpname);		/* discard empty file */
X		report_str("end of transfer",0);
X		rf_done = 1;
X		return(NULL);
X	}
X
XCANCEL_TRANSFER:
X	fclose(fp);
X	xmit_cancel();
X	rf_done = 2;
X	return(NULL);
X}	/* end of receive_file */
X
X/*+-------------------------------------------------------------------------
X	cancel_transaction(sig)
X--------------------------------------------------------------------------*/
XSIGTYPE
Xcancel_transaction(sig)
Xint sig;
X{
X	xmit_cancel();
X	sprintf(s128,"signal %d ... exiting",sig);
X	report_str(s128,1);
X/*
X	report_rx_ind(0);
X	report_tx_ind(0);
X*/
X	report_uninit();
X	if(sig == SIGQUIT)
X		abort();
X	exit(128+sig);
X}	/* end of cancel_transaction */
X
X/*+-------------------------------------------------------------------------
X	getspeed(code)
X--------------------------------------------------------------------------*/
Xstruct B_to_baud { unsigned baud; int B_code; };
Xunsigned
Xgetspeed(code)
Xint code;
X{
Xregister itmp;
Xstatic struct B_to_baud speeds[] = 
X{
X 50, B50, 75, B75, 110, B110, 300, B300, 600, B600, 1200, B1200,
X 2400, B2400, 4800, B4800, 9600, B9600, 19200, EXTA, 38400, EXTB, 0
X};
X
X	code &= CBAUD;
X	for(itmp = 0; speeds[itmp].baud; itmp++)
X		if(speeds[itmp].B_code == code)
X			return(speeds[itmp].baud);
X	return(38400);	/* Assume fifo if ioctl failed */
X}	/* end of getspeed */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
Xint ipaths;
Xint ok = 0;
X#define MAX_PATHS 512
Xchar *paths[MAX_PATHS];
Xchar **ppaths = paths;
Xchar *cptr;
Xchar **gargv = argv;
Xint gargc = argc;
X
X	exit_code = 254;
X	while(--argc)
X	{
X		cptr = *++argv;
X		if(*cptr == '-')
X		{
X			cptr++;
X			switch(*cptr++)
X			{
X			case ',':
X				log_packets = 1;
X				break;
X			case '/':
X				if(--argc < 1)
X					exit(255);
X				strcpy(curr_dir,*++argv);
X				break;
X			case '.':
X				if(--argc < 1)
X					exit(255);
X				iofd = atoi(*++argv);
X				break;
X			case 'r':
X				sending_flag = 0;
X				break;
X			case 's':
X				sending_flag = 1;
X			}
X		}
X		else if(argc > 0)
X		{
X			if(npaths < MAX_PATHS)
X			{
X				*ppaths++ = cptr;
X				npaths++;
X			}
X			else
X			{
X				printf("too many filenames to send\n");
X				exit(255);
X			}
X		}
X	}
X
X	if(sending_flag == -1)
X	{
X		printf("no -r or -s\n");
X		exit(255);
X	}
X
X	if((npaths < 1) && sending_flag)
X		exit(253);
X
X	if(npaths && !sending_flag)
X		exit(255);
X
X	if(log_packets)
X	{
X	char log_packets_name[64];
X	FILE *ftmp;
X	int iargv;
X		sprintf(log_packets_name,"/tmp/sea%05d.plog",getpid());
X		unlink(log_packets_name);
X		ftmp = fopen(log_packets_name,"w");
X		fclose(ftmp);
X		log_packets = open(log_packets_name,O_WRONLY,0644);
X		if(log_packets < 0)
X			log_packets = 0;
X		else
X		{
X			write(log_packets,"exec: ",6);
X			for(iargv = 0; iargv < gargc; iargv++)
X			{
X				write(log_packets,gargv[iargv],strlen(gargv[iargv]));
X				write(log_packets," ",1);
X			}
X			write(log_packets,"\n",1);
X		}
X	}
X
X	sprintf(s128,"ecusea %s",revision);
X	report_init(s128);
X	signal(SIGHUP,cancel_transaction);
X	signal(SIGQUIT,cancel_transaction);
X	signal(SIGINT,cancel_transaction);
X	signal(SIGTERM,cancel_transaction);
X
X	ioctl(iofd,TCGETA,&tio0);
X	tio = tio0;
X
X	tio.c_oflag = 0;
X	tio.c_cflag &= ~PARENB;
X	tio.c_cflag &= ~CSIZE;
X	tio.c_cflag |= CS8;
X
X	baud_rate = getspeed(tio.c_cflag);
X	ioctl(iofd,TCSETA,&tio);
X	report_line(baud_rate,"RAW");
X
X	switch(sending_flag)
X	{
X		case 0:				/* receive files */
X			while(receive_file() != NULL)
X				nap(1000L);
X			ok = (rf_done == 1);
X			break;
X
X		case 1:				/* send files */
X			ipaths = 0;
X			while(ipaths < npaths)
X			{
X				if(!(ok = send_file(paths[ipaths])))
X					break;
X				nap(1000L);
X				ipaths++;
X			}
X			if(ok)		/* no errors, send end marker */
X				send_file("");
X			report_str("end of transfer",0);
X			break;
X	}
X
X	ioctl(iofd,TCSETA,&tio0);
X	report_line(baud_rate,"NORMAL");
X	report_uninit();
X	exit(ok ? 0 : exit_code);	/* and return error status */
X
X}	/* end of main */
X
SHAR_EOF
echo 'File sea/ecusea.c is complete' &&
$TOUCH -am 0725125991 'sea/ecusea.c' &&
chmod 0644 sea/ecusea.c ||
echo 'restore of sea/ecusea.c failed'
Wc_c="`wc -c < 'sea/ecusea.c'`"
test 35323 -eq "$Wc_c" ||
	echo 'sea/ecusea.c: original size 35323, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= sea/lint_args.h ==============
if test -f 'sea/lint_args.h' -a X"$1" != X"-c"; then
	echo 'x - skipping sea/lint_args.h (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting sea/lint_args.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sea/lint_args.h' &&
X/*+-----------------------------------------------------------------------
X	lint_args.h
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-25-1991-12:59-wht@n4hgf-ECU release 3.10 */
X/*:04-29-1991-00:04-afterlint-creation */
X
X#ifndef BUILDING_LINT_ARGS
X#ifdef LINT_ARGS
X
X/* ecusea.c */
Xvoid send_file_block(FILE *fp,int blknum);
Xchar *receive_file(void );
Xchar *sf_state_text(int );
Xint main(int ,char **,char **);
Xint receive_block(char *);
Xint send_comm_block(char *,int );
Xint send_file(char *);
Xint wait_for_rcvr_response(void );
Xunsigned int getspeed(int );
Xunsigned int lgetc_timeout(int );
Xunsigned short crc_update(int ,unsigned int );
Xvoid set_sf_state(int ,int );
Xvoid set_utime_1980(char *,long );
Xvoid xmit_ack(int );
Xvoid xmit_cancel(void );
Xvoid xmit_nak(int );
X/* scurses.c */
Xchar *get_elapsed_time(long );
Xchar *hhmmss(char *);
Xint clear_area(struct _win_st *,int ,int ,int );
Xint clear_area_char(struct _win_st *,int ,int ,int ,char );
Xint report_error_count(void );
Xint report_file_byte_io(long );
Xint report_file_open_length(long );
Xint report_file_rcv_started(char *,long ,long );
Xint report_protocol_crc_type(char *);
Xint report_rx_tx_count(void );
Xvoid report_file_close(void );
Xvoid report_file_open_tod(void );
Xvoid report_file_send_open(char *,struct stat *);
Xvoid report_init(char *);
Xvoid report_last_rxhdr(char *,int );
Xvoid report_last_txhdr(char *,int );
Xvoid report_line(unsigned int ,char *);
Xvoid report_rx_ind(int );
Xvoid report_rxpos(long );
Xvoid report_str(char *,int );
Xvoid report_top_line(char *);
Xvoid report_transaction(char *);
Xvoid report_tx_ind(int );
Xvoid report_txpos(long );
Xvoid report_uninit(void );
X
X#else		/* compiler doesn't know about prototyping */
X
X/* ecusea.c */
X/* void send_file_block();
Xchar *receive_file();
Xchar *sf_state_text();
Xunsigned int getspeed();
Xunsigned int lgetc_timeout();
Xunsigned short crc_update();
Xvoid set_sf_state();
Xvoid set_utime_1980();
Xvoid xmit_ack();
Xvoid xmit_cancel();
Xvoid xmit_nak();
X/* scurses.c */
Xchar *get_elapsed_time();
Xchar *hhmmss();
Xvoid report_file_close();
Xvoid report_file_open_tod();
Xvoid report_file_send_open();
Xvoid report_init();
Xvoid report_last_rxhdr();
Xvoid report_last_txhdr();
Xvoid report_line();
Xvoid report_rx_ind();
Xvoid report_rxpos();
Xvoid report_str();
Xvoid report_top_line();
Xvoid report_transaction();
Xvoid report_tx_ind();
Xvoid report_txpos();
Xvoid report_uninit();
X
X#endif /* LINT_ARGS */
X#endif /* BUILDING_LINT_ARGS */
X
X/* end of lint_args.h */
SHAR_EOF
$TOUCH -am 0725125991 'sea/lint_args.h' &&
chmod 0644 sea/lint_args.h ||
echo 'restore of sea/lint_args.h failed'
Wc_c="`wc -c < 'sea/lint_args.h'`"
test 2512 -eq "$Wc_c" ||
	echo 'sea/lint_args.h: original size 2512, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= sea/scurses.c ==============
if test -f 'sea/scurses.c' -a X"$1" != X"-c"; then
	echo 'x - skipping sea/scurses.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting sea/scurses.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sea/scurses.c' &&
X/*+-------------------------------------------------------------------------
X	scurses.c -- ecu file transfer program curses interface
X
X  000000000011111111112222222222333333333344444444445555555550
X  012345678901234567890123456789012345678901234567890123456789
X00.----------------------------------------------------------.
X01|  SEAlink_6____  _39____________________________________  |
X02|  File ### of ###: _38__________________________________  |
X03|  File position:  _8______ length: _8______               |
X04|  _55____________________________________________________ | transaction
X05|  _55____________________________________________________ | last rx/tx hdr
X06|  Comm I/O: rx _8______  tx _8______ bytes                |
X07|  Baud rate: _5___ BINARY blklen: _____ comm mode: CBREAK |
X08|  Time started: session: HH:MM:SS  this file: HH:MM:SS    |
X09|                elpased: HH:MM:SS       time: HH:MM:SS    |
X10|  Error counts: this file:  _4__  total: _6____           |
X11|  _55____________________________________________________ |  err str
X12|  _55____________________________________________________ |  comment str
X13|  _55____________________________________________________ |  remote info
X14`----------------------------------------------------------'
X
X  Defined functions:
X	clear_area(win,row,col,len)
X	clear_area_char(win,row,col,len,fillchar)
X	get_elapsed_time(elapsed_seconds)
X	hhmmss(tod)
X	report_error_count()
X	report_file_byte_io(count)
X	report_file_close()
X	report_file_open_length(length)
X	report_file_open_tod()
X	report_file_rcv_started(filename,length,last_mod_time)
X	report_file_send_open(filename,filestat)
X	report_init(title)
X	report_last_rxhdr(rptstr,error_flag)
X	report_last_txhdr(rptstr,error_flag)
X	report_line(baud_rate,mode)
X	report_protocol_crc_type(str)
X	report_rx_ind(status)
X	report_rx_tx_count()
X	report_rxpos(rxpos)
X	report_str(rptstr,error_flag)
X	report_top_line(topstr)
X	report_transaction(str)
X	report_tx_ind(status)
X	report_txpos(txpos)
X	report_uninit()
X
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-25-1991-12:59-wht@n4hgf-ECU release 3.10 */
X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
X
X#include "../ecucurses.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <ctype.h>
X#include <signal.h>
X#include <time.h>
X#include <sys/timeb.h>
X#if defined(M_SYSV)
X#   include <sys/machdep.h>
X#else
X#  include <sys/at_ansi.h>
X#  include <sys/kd.h>
X#endif
X
X#include "../pc_scr.h"
X
X#include "../pc_scr.h"
X#include "lint_args.h"
X
Xlong time();
Xextern char *tzname[];
Xstruct tm *localtime();
X
X
X#define WIN_LINES	15
X#define WIN_COLS	60
X#define WIN_TOPY	2
X#define WIN_LEFTX	8
X
Xextern char curr_dir[];
Xextern char s128[];
Xextern int Filcnt;
Xextern int Restricted;
Xextern int sending_flag;	/* send == 1, receive == 0 */
Xextern int npaths;
Xextern long rxpos;
Xextern int log_packets;
X
XWINDOW	*win;
Xint (*original_sigint_handler)();
Xint (*original_sigquit_handler)();
Xint (*original_sigterm_handler)();
Xint curses_installed = 0;		/* curses not yet active */
Xint this_file_errors = 0;
Xint total_errors = 0;
Xlong current_seconds;
Xlong start_seconds;
Xlong elapsed_seconds;
Xunsigned long total_data_chars_xfered = 0L;
X
Xunsigned char sTL = at_TL;
Xunsigned char sTR = at_TR;
Xunsigned char sBL = at_BL;
Xunsigned char sBR = at_BR;
Xunsigned char sLT = at_LT;
Xunsigned char sRT = at_RT;
Xunsigned char sVR = at_VR;
Xunsigned char sHR = at_HR;
X
Xchar *win_template[] =
X{
X/*00000000001111111111222222222233333333334444444444555555555 */
X/*01234567890123456789012345678901234567890123456789012345678 */
X/*.----------------------------------------------------------. */
X  "  SEAlink                                                 ",	/* 1 */
X  "  File ### of ###: _____________________________________  ",	/* 2 */
X  "  File position:  ________ length: ________               ",	/* 3 */
X  "                                                          ",	/* 4 */
X  "  tx: ______________________  rx: ______________________  ",	/* 5 */
X  "  Comm I/O: rx ________  tx ________ bytes                ",	/* 6 */
X  "  Baud rate: _____ BINARY blklen: 128   comm mode: ______ ",	/* 7 */
X  "  Time started: session: --:--:--  this file: --:--:--    ",	/* 8 */
X  "                elapsed: --:--:--    current: --:--:--    ",	/* 9 */
X  "  Error counts: this file:  ____  total: ______           ",	/* 10 */
X  "                                                          ",	/* 11 */
X  "                                                          ",	/* 12 */
X  "                                                          ",	/* 13 */
X/*`----------------------------------------------------------' */
X(char *)0
X};
X
X/*+-----------------------------------------------------------------------
X	char *get_elapsed_time(elapsed_seconds)
X	hh:mm:ss returned
X  static string address is returned
X------------------------------------------------------------------------*/
Xchar *get_elapsed_time(elapsed_seconds)
Xlong elapsed_seconds;
X{
X	static char elapsed_time_str[10];
X	long hh,mm,ss;
X
X	hh = elapsed_seconds / 3600;
X	elapsed_seconds -= hh * 3600;
X	mm = elapsed_seconds / 60L;
X	elapsed_seconds -= mm * 60L;
X	ss = elapsed_seconds;
X
X	sprintf(elapsed_time_str,"%02ld:%02ld:%02ld",hh,mm,ss);
X	return(elapsed_time_str);
X}	/* end of get_elapsed_time */
X
X/*+-----------------------------------------------------------------------
X	char *hhmmss(tod) - get time of day in form "hh:mm:ss"
X
X  static string address is returned
X  if tod != (char *)0, time is returned there too
X------------------------------------------------------------------------*/
Xchar *
Xhhmmss(tod)
Xchar *tod;
X{
X	long cur_time = 0;
X	struct tm *lt;			/* local time */
X	static char tod_str[32];
X
X	cur_time = time((long *)0);
X	lt = localtime(&cur_time);
X
X	sprintf(tod_str,"%02d:%02d:%02d",lt->tm_hour,lt->tm_min,lt->tm_sec);
X
X	if(tod != (char *)0)
X		strcpy(tod,tod_str);
X
X	return(tod_str);
X
X}	/* end of hhmmss */
X
X/*+-------------------------------------------------------------------------
X	clear_area(win,row,col,len)
X--------------------------------------------------------------------------*/
Xclear_area(win,row,col,len)
XWINDOW	*win;
Xint row;
Xint col;
Xint len;
X{
X	wmove(win,row,col);
X	while(len-- > 0)
X		waddch(win,' ');
X	wmove(win,row,col);
X
X}	/* end of clear_area */
X
X/*+-------------------------------------------------------------------------
X	clear_area_char(win,row,col,len,fillchar)
X--------------------------------------------------------------------------*/
Xclear_area_char(win,row,col,len,fillchar)
XWINDOW	*win;
Xint row;
Xint col;
Xint len;
Xchar fillchar;
X{
X	wmove(win,row,col);
X	while(len-- > 0)
X		waddch(win,fillchar);
X	wmove(win,row,col);
X
X}	/* end of clear_area_char */
X
X/*+-------------------------------------------------------------------------
X	report_top_line(topstr)
X   top line: row 1 col 18 length 39
X--------------------------------------------------------------------------*/
Xvoid
Xreport_top_line(topstr)
Xchar *topstr;
X{
Xchar s42[42];
X	clear_area(win,1,18,39);
X	if(strlen(topstr) < 39)
X		waddstr(win,topstr);
X	else
X	{
X		strncpy(s42,topstr,39);
X		s42[39] = 0;
X		waddstr(win,s42);
X	}
X}	/* end of report_top_line */
X
X/*+-------------------------------------------------------------------------
X	report_protocol_crc_type(str)
X
X  protocol crc type:  row 1 col 10 length 6
X--------------------------------------------------------------------------*/
Xreport_protocol_crc_type(str)
Xregister char *str;
X{
Xchar s8[8];
X
X	if(strlen(str) > 6)
X	{
X		strncpy(s8,str,6);
X		s8[6] = 0;
X		str = s8;
X	}
X	clear_area(win,1,10,6);
X	waddstr(win,str);
X	wrefresh(win);
X	if(log_packets)
X	{
X		write(log_packets,"chk:  ",6);
X		write(log_packets,str,strlen(str));
X		write(log_packets,"\n",1);
X	}
X
X}	/* end of report_protocol_crc_type */
X
X/*+-------------------------------------------------------------------------
X	report_uninit()
X--------------------------------------------------------------------------*/
Xvoid
Xreport_uninit()
X{
Xfloat total = (float)total_data_chars_xfered;
X
X	if(curses_installed)
X	{
X		if((total_data_chars_xfered != 0L) && (elapsed_seconds != 0L))
X		{
X			sprintf(s128,"Data xfer rate ~= %6.0f chars/sec",
X			    total / (float)elapsed_seconds);
X			if(log_packets)
X			{
X				write(log_packets,"info: ",6);
X				write(log_packets,s128,strlen(s128));
X				write(log_packets,"\n",1);
X			}
X			report_top_line(s128);
X		}
X		report_file_byte_io(0L);
X		report_rx_tx_count();
X		wmove(win,WIN_LINES - 1,WIN_COLS - 1);
X		wrefresh(win);
X		endwin();
X		fprintf(stderr,"\r\n\r\n\r\n");
X		fflush(stderr);
X		curses_installed = 0;
X	}
X
X}	/* end of report_uninit */
X
X/*+-------------------------------------------------------------------------
X	report_init(title)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_init(title)
Xchar *title;
X{
Xregister int itmp;
Xint monitor_type;
X
X	if(curses_installed)
X		return;
X
X	initscr();
X	crmode();
X	noecho();
X	nonl();
X	clear();
X	curses_installed = 1;
X	win = newwin(WIN_LINES,WIN_COLS,WIN_TOPY,WIN_LEFTX);
X	box(win,sVR,sHR);
X	wmove(win,0,0); waddch(win,sTL);
X	wmove(win,win->_maxy - 1,0); waddch(win,sBL);
X	wmove(win,win->_maxy - 1,win->_maxx - 1); waddch(win,sBR);
X	wmove(win,0,win->_maxx - 1); waddch(win,sTR);
X	wmove(win,0,2);
X	wstandout(win);
X	waddch(win,'[');
X	waddch(win,' ');
X	waddstr(win,title);
X	waddch(win,' ');
X	waddch(win,']');
X	wstandend(win);
X	waddch(win,sHR);
X	waddch(win,sHR);
X	waddstr(win," dir: ");
X	waddstr(win,curr_dir);
X	waddch(win,' ');
X
X	itmp = 0;
X	while(1)
X	{
X		if(win_template[itmp] == (char *)0)
X			break;
X		wmove(win,itmp + 1,1);
X		waddstr(win,win_template[itmp++]);
X	}
X	if(sending_flag)
X	{
X		clear_area(win,2,15,3);
X		sprintf(s128,"%3d",npaths);
X		waddstr(win,s128);
X#if defined(FORK_DEBUG)
X		sprintf(s128,"ecusz pid %d",getpid());
X#endif
X	}
X	else	/* ecurz */
X	{
X		clear_area(win,2,11,8);	/* clear "of ###" */
X		waddstr(win,":");
X#if defined(FORK_DEBUG)
X		sprintf(s128,"ecurz pid %d",getpid());
X#endif
X	}
X
X#if defined(FORK_DEBUG)
X	ecu_log_event(getppid(),s128);
X#endif
X
X	clear_area(win,1,11,47);
X	report_error_count();
X	clear_area(win,8,26,8);		/* starting time */
X	waddstr(win,hhmmss((char *)0));
X	start_seconds = time((long *)0);
X	current_seconds = start_seconds;
X
X	if(ioctl(0,CONS_GET,&monitor_type) < 0)	/* not multiscreen */
X	{
X		sTL = vanilla_TL;
X		sTR = vanilla_TR;
X		sBL = vanilla_BL;
X		sBR = vanilla_BR;
X		sLT = vanilla_LT;
X		sRT = vanilla_RT;
X		sVR = vanilla_VR;
X		sHR = vanilla_HR;
X	}
X
X	wrefresh(win);
X
X}	/* end of report_init */
X
X/*+-------------------------------------------------------------------------
X	report_rx_ind(status)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_rx_ind(status)
Xint status;
X{
X	wmove(win,1,54);
X	waddch(win,(status) ? 'R' : ' ');
X	wmove(win,1,54);
X	wrefresh(win);
X}	/* end of report_rx_ind */
X
X/*+-------------------------------------------------------------------------
X	report_tx_ind(status)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_tx_ind(status)
Xint status;
X{
X	wmove(win,1,56);
X	waddch(win,(status) ? 'T' : ' ');
X	wmove(win,1,56);
X	wrefresh(win);
X}	/* end of report_tx_ind */
X
X/*+-------------------------------------------------------------------------
X	report_rx_tx_count()
X
X  rx char count: row 6 col 16 length 8 unsigned long
X  tx char count: row 6 col 29 length 8 unsigned long
X  now time of day: row 1 col 50 length 8 hh:mm:ss
X  This procedure may be counted upon to perform wrefresh(win)
X
Xelapsed time row 9 col 26 length 8
Xcurrent tod row 9 col 47 length 8
X--------------------------------------------------------------------------*/
Xreport_rx_tx_count()
X{
X	extern unsigned long rx_char_count;
X	extern unsigned long tx_char_count;
X
X	register char *cptr;
X
X	sprintf(s128,"%8ld",rx_char_count);
X	wmove(win,6,16);
X	waddstr(win,s128);
X	sprintf(s128,"%8ld",tx_char_count);
X	wmove(win,6,29);
X	waddstr(win,s128);
X
X	/* now time of day */
X	clear_area(win,9,47,8);
X	cptr = hhmmss((char *)0);
X	waddstr(win,cptr);
X	current_seconds = time((long *)0);
X	elapsed_seconds = current_seconds - start_seconds;
X	cptr = get_elapsed_time(elapsed_seconds);
X	clear_area(win,9,26,8);
X	waddstr(win,cptr);
X	wrefresh(win);		/* calling procs expect this to occur always */
X
X}	/* end of report_rx_tx_count */
X
X/*+-------------------------------------------------------------------------
X	report_line(baud_rate,mode)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_line(baud_rate,mode)
Xunsigned baud_rate;
Xchar *mode;
X{
Xchar s16[16];
X	wmove(win,7,14);
X	sprintf(s16,"%5u",baud_rate);
X	waddstr(win,s16);
X	clear_area(win,7,52,6);
X	waddstr(win,mode);
X	wrefresh(win);
X}	/* end of report_line */
X
X/*+-------------------------------------------------------------------------
X	report_rxpos(rxpos) row 3 col 19 len 8
X--------------------------------------------------------------------------*/
Xvoid
Xreport_rxpos(rxpos)
Xlong rxpos;
X{
Xchar tmp[16];
Xchar refr;
X
X	if(rdchk(0))
X	{
X		read(0,&refr,1);
X		if(refr == 0x0C || refr == 0x012)	/* ^L or ^R */
X		{
X			write(2,"\033[2J",4);
X			nap((long)60);
X			touchwin(stdscr);
X			wrefresh(stdscr);
X			touchwin(win);
X			wrefresh(win);
X		}
X	}
X
X	if((rxpos > 99999999L) || (rxpos < 0L))
X		return;
X
X	sprintf(tmp,"%8lu",rxpos);
X	wmove(win,3,19);
X	waddstr(win,tmp);
X	wrefresh(win);
X	report_rx_tx_count();	/* which will do a refresh */
X}	/* end of report_rxpos */
X
X/*+-------------------------------------------------------------------------
X	report_txpos(txpos)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_txpos(txpos)
Xlong txpos;
X{
X	report_rxpos(txpos);
X}	/* end of report_txpos */
X
X/*+-------------------------------------------------------------------------
X	report_error_count()
X	DOES NOT PERFORM A REFRESH CYCLE
X  this file: row 10 col 29 len 4
X  total:     row 10 col 42 len 6
X--------------------------------------------------------------------------*/
Xreport_error_count()
X{
X	char tmp[16];
X
X	clear_area(win,10,29,4);
X	sprintf(tmp,"%4d",this_file_errors);
X	waddstr(win,tmp);
X
X	clear_area(win,10,42,6);
X	sprintf(tmp,"%6d",total_errors);
X	waddstr(win,tmp);
X	wrefresh(win);
X
X}	/* end of report_error_count */
X
X/*+-------------------------------------------------------------------------
X	report_last_txhdr(rptstr,error_flag)
X	5,7,22
X--------------------------------------------------------------------------*/
Xvoid
Xreport_last_txhdr(rptstr,error_flag)
Xregister char *rptstr;
Xint error_flag;
X{
Xchar s24[24];
X
X	if(log_packets)
X	{
X		write(log_packets,"tx:   ",6);
X		write(log_packets,rptstr,strlen(rptstr));
X		write(log_packets,"\n",1);
X	}
X
X	if(strlen(rptstr) > 22)
X	{
X		strncpy(s24,rptstr,22);
X		s24[23] = 0;
X		rptstr = s24;
X	}
X	clear_area(win,5,7,22);
X	waddstr(win,rptstr);
X	wrefresh(win);
X
X	if(error_flag)
X	{
X		++this_file_errors;
X		++total_errors;
X		report_error_count();
X	}
X}	/* end of report_last_txhdr */
X
X/*+-------------------------------------------------------------------------
X	report_last_rxhdr(rptstr,error_flag)
X	5,35,22
X--------------------------------------------------------------------------*/
Xvoid
Xreport_last_rxhdr(rptstr,error_flag)
Xregister char *rptstr;
Xint error_flag;
X{
Xchar s24[24];
Xextern int log_packets;
X
X	if(log_packets)
X	{
X		write(log_packets,"rx: ",4);
X		write(log_packets,(error_flag) ? "E " : "  ",2);
X		write(log_packets,rptstr,strlen(rptstr));
X		write(log_packets,"\n",1);
X	}
X
X	if(strlen(rptstr) > 22)
X	{
X		strncpy(s24,rptstr,22);
X		s24[23] = 0;
X		rptstr = s24;
X	}
X	clear_area(win,5,35,22);
X	waddstr(win,rptstr);
X	wrefresh(win);
X
X	if(error_flag)
X	{
X		++this_file_errors;
X		++total_errors;
X		report_error_count();
X	}
X
X}	/* end of report_last_rxhdr */
X
X/*+-------------------------------------------------------------------------
X	report_str(rptstr,error_flag) row 11/12 col 3 len 55
X
X  error_flag == 0 for status/progress message
X             == 1 for bump error count, unless rptstr is null
X                  in which case, merely clear error string area
X             == 2 write string on bottom line (not an error)
X             == 3 write string on transaction line (not an error)
X             == -1 use error line but do not bump error count
X--------------------------------------------------------------------------*/
Xvoid
Xreport_str(rptstr,error_flag)
Xregister char *rptstr;
Xint error_flag;
X{
Xchar s60[60];
Xextern int log_packets;
X
X	if(strlen(rptstr) > 55)
X	{
X		strncpy(s60,rptstr,55);
X		s60[56] = 0;
X		rptstr = s60;
X	}
X
X	switch(error_flag)
X	{
X		case 0:
X			clear_area(win,12,3,55);
X			break;
X		case 1:
X			++this_file_errors;
X			++total_errors;
X			report_error_count();
X		case -1:
X			clear_area(win,11,3,55);
X			break;
X		case 2:
X			clear_area(win,13,3,55);
X			break;
X		case 3:
X			clear_area(win,4,3,55);
X			break;
X	}
X
X	waddstr(win,rptstr);
X	wrefresh(win);
X
X	if(log_packets)
X	{
X		write(log_packets,"info: ",6);
X		sprintf(s60,"%2d ",error_flag);
X		write(log_packets,s60,3);
X		write(log_packets,rptstr,strlen(rptstr));
X		write(log_packets,"\n",1);
X	}
X
X}	/* end of report_str */
X
X/*+-------------------------------------------------------------------------
X	report_transaction()
X--------------------------------------------------------------------------*/
Xvoid
Xreport_transaction(str)
Xchar *str;
X{
X	report_str(str,3);
X}	/* end of report_transaction */
X
X/*+-------------------------------------------------------------------------
X	report_file_open_tod() -- time of start of this file
X
X  this file open time: row 8 col 47 length 8
X--------------------------------------------------------------------------*/
Xvoid
Xreport_file_open_tod()
X{
X	clear_area(win,8,47,8);
X	waddstr(win,hhmmss((char *)0));
X	wrefresh(win);
X}	/* end of report_file_open_tod */
X
X/*+-------------------------------------------------------------------------
X	report_file_open_length(long_length)
X  length:   row 3 col 36 len  8
X--------------------------------------------------------------------------*/
Xreport_file_open_length(length)
Xlong length;
X{
X	clear_area(win,3,36,8);
X	if(length <= 0)
X		waddstr(win,"unknown");
X	else
X	{
X		sprintf(s128,"%8lu",length);
X		waddstr(win,s128);
X	}
X	wrefresh(win);
X}	/* end of report_file_open_length */
X
X/*+-------------------------------------------------------------------------
X	report_file_send_open(filename,filestat)
X
X  filename: row 2 col 20 len 38
X  number:   row 2 col 8 len 3
X  length:   row 3 col 36 len  8
X  mode:     row 3 col 46 len 10
X  time of start of this file: row 4 col 47 length 8 hh:mm:ss
X--------------------------------------------------------------------------*/
Xvoid
Xreport_file_send_open(filename,filestat)
Xchar *filename;
Xstruct stat *filestat;
X{
Xchar s50[50];
Xregister char *cptr = filename;
X
X	if(log_packets)
X	{
X		write(log_packets,"file: ",6);
X		write(log_packets,filename,strlen(filename));
X		write(log_packets,"\n",1);
X	}
X
X	/* number */
X	clear_area(win,2,8,3);
X	sprintf(s50,"%3d",Filcnt);
X	waddstr(win,s50);
X
X	/* filename */
X	if(strlen(filename) > 38)
X	{
X		strncpy(s50,filename,38);
X		s50[39] = 0;
X		cptr = s50;
X	}
X	clear_area(win,2,20,38);
X	waddstr(win,cptr);
X
X#if defined(LOG_XFER)
X	sprintf(s128,"sending %s",filename);
X	ecu_log_event(getppid(),s128);
X#endif
X
X	/* length */
X	report_file_open_length(filestat->st_size);
X
X	/* time of start of this file */
X	report_file_open_tod();
X
X	this_file_errors = 0;
X	report_error_count();
X}	/* end of report_file_send_open */
X
X/*+-------------------------------------------------------------------------
X	report_file_rcv_started(filename,length,last_mod_time)
X
X  filename: row 2 col 7 len 50
X  length:   row 3 col 36 len  8 if not xmodem
X  time of start of this file: row 4 col 47 length 8 hh:mm:ss
X--------------------------------------------------------------------------*/
Xreport_file_rcv_started(filename,length,last_mod_time)
Xchar *filename;
Xlong length;					/* if < 0, "UNKNOWN" */
Xlong last_mod_time;			/* not currently displayed */
X{
Xregister char *cptr;
Xchar s50[50];
X
X	if(log_packets)
X	{
X		write(log_packets,"file: ",6);
X		write(log_packets,filename,strlen(filename));
X		write(log_packets,"\n",1);
X	}
X
X	/* filename */
X	if(strlen(filename) > 38)
X	{
X		strncpy(s50,filename,38);
X		s50[39] = 0;
X		cptr = s50;
X	}
X	else
X		cptr = filename;
X
X#if defined(LOG_XFER)
X	sprintf(s128,"receiving %s",filename);
X	ecu_log_event(getppid(),s128);
X#endif
X
X	clear_area(win,2,20,38);
X	waddstr(win,cptr);
X
X	/* file number */
X	clear_area(win,2,8,3);
X	sprintf(s50,"%3d",Filcnt);	/* rz uses as file number 1-n */
X	waddstr(win,s50);
X
X/* if remote sender provides a file count, display it */
X	if(npaths)
X	{
X		clear_area(win,2,12,7);	/* clear "of ###" */
X		sprintf(s50,"of %3d:",npaths);
X		waddstr(win,s50);
X	}
X
X	/* length */
X	report_file_open_length(length);
X
X	/* time of start of this file */
X	report_file_open_tod();
X
X	this_file_errors = 0;
X	report_error_count();
X}	/* end of report_file_rcv_started */
X
X/*+-------------------------------------------------------------------------
X	report_file_close()
X--------------------------------------------------------------------------*/
Xvoid report_file_close()
X{
X	report_str("End of file",0);
X	wrefresh(win);
X
X}	/* end of report_file_close */
X
X/*+-------------------------------------------------------------------------
X	report_file_byte_io(count)
X--------------------------------------------------------------------------*/
Xreport_file_byte_io(count)
Xlong count;
X{
X
X	total_data_chars_xfered += (long)count;
X	if(total_data_chars_xfered)
X	{
X		sprintf(s128,"Total file bytes transferred: %lu",
X			total_data_chars_xfered);
X		report_str(s128,-1);
X	}
X
X}	/* end of report_file_byte_io */
X
X/* end of scurses.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 0725125991 'sea/scurses.c' &&
chmod 0644 sea/scurses.c ||
echo 'restore of sea/scurses.c failed'
Wc_c="`wc -c < 'sea/scurses.c'`"
test 21582 -eq "$Wc_c" ||
	echo 'sea/scurses.c: original size 21582, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= sea/sealink.doc ==============
if test -f 'sea/sealink.doc' -a X"$1" != X"-c"; then
	echo 'x - skipping sea/sealink.doc (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting sea/sealink.doc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sea/sealink.doc' &&
X                                     SEALINK
X
X                             File Transfer Protocol
X
X                                 9 February 1987
X
X
X
X          (C) COPYRIGHT 1986,87 by System Enhancement Associates, Inc.
X
X
X
X     This document describes briefly the  SEAlink  file  transfer  protocol
X     developers' package.  SEAlink is a sliding  window  protocol  that  is
X     fully  backwards compatible with XMODEM in all tested implementations.
X
X     The intent of SEAlink is to provide a file transfer protocol that does
X     not  suffer  from  propagation  delays,  such  as  are  introduced  by
X     satellite relays or packet switched  networks.  Actual  tests  of  the
X     enclosed  routines  has  shown  that  SEAlink  is capable of virtually
X     eliminating propagation delays and turnaround delays.  File  transfers
X     between New Jersey and Hawaii,  which normally suffer a degradation of
X     50% or more  due  to  satellite  relays,  proceed  as  fast  as  local
X     transfers.  Even transfers within the local exchange are speeded up by
X     up to 20% at 2400 baud by the elimination of turnaround delays.  Large
X     volume  tests  show  that SEAlink is capable of coming to within 2% of
X     the theoretical minimum time for data transfer.
X
X
X
X     The developers' package contains the following files:
X
X         SEALINK.DOC    This document.
X         SEALINK.C      A set of C routines for implementing SEAlink.
X         CLINK.EXE      A sample TTY program that implements SEAlink.
X
X
X
X     You are granted a license to use this code in your  programs,  and  to
X     adapt  it to your particular situation and needs,  subject only to the
X     following conditions:
X
X     1) You must refer to it as the SEAlink protocol,  and  you  must  give
X        credit to System Enhancement Associates.
X
X     2) If  you  modify  it in such a way that your version cannot converse
X        with the original code as supplied by us,  then you should refer to
X        it as "SEAlink derived",  or as a "variation of SEAlink",  or words
X        to that effect.
X
X     In short,  we're not asking for any money,  but we'd like to get  some
X     credit for our work.
X
X
X     This  document  is  not  meant  to  be  a  rigorous  definition of the
SHAR_EOF
true || echo 'restore of sea/sealink.doc failed'
fi
echo 'End of ecu310 part 24'
echo 'File sea/sealink.doc is continued in part 25'
echo 25 > _shar_seq_.tmp
exit 0
--------------------------------------------------------------------
Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.


