[alt.sources] ecu - SCO XENIX V/{2,3}86 Extended CU part 27/47

wht@tridom.uucp (Warren Tucker) (10/11/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 27 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file z/ecusz.c continued
#
CurArch=27
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file z/ecusz.c"
sed 's/^X//' << 'SHAR_EOF' >> z/ecusz.c
X}
X
X/* fill buf with count chars padding with ^Z for CPM */
Xxbuf_build(buf,count)
Xregister char *buf;
X{
Xregister c,m;
Xlong lseek();
Xlong X_txpos = lseek(fileno(in),0L,1);
Xchar diag_str[64];
X
X	report_send_stats(X_txpos);
X	if( !Ascii)
X	{
X		m = read(fileno(in),buf,count);
X		if(log_packets)
X		{
X			sprintf(diag_str,"read rtnd %d of %d",m,count);
X			report_str(diag_str,1);
X		}
X		if(m <= 0)
X			return(0);
X		while(m < count)
X			buf[m++] = 032;
X		return(count);
X	}
X	m=count;
X	if(Lfseen)
X	{
X		*buf++ = 012;
X		--m;
X		Lfseen = 0;
X	}
X	while((c=getc(in))!=EOF)
X	{
X		if(c == 012)
X		{
X			*buf++ = 015;
X			if(--m == 0)
X			{
X				Lfseen = TRUE;
X				break;
X			}
X		}
X		*buf++ =c;
X		if(--m == 0)
X			break;
X	}
X	if(m==count)
X		return(0);
X	else
X		while(--m>=0)
X			*buf++ = CPMEOF;
X	return(count);
X}
X
X/* fill buf with count chars */
Xzbuf_build(buf,count)
Xregister char *buf;
X{
X	register c,m;
X
X	m=count;
X	while((c=getc(in))!=EOF)
X	{
X		*buf++ =c;
X		if(--m == 0)
X			break;
X	}
X	return(count - m);
X}
X
X
XSIGALRM_handler()
X{
X#if defined(M_XENIX)
X	report_rx_ind(0);
X	report_tx_ind(0);
X#endif
X	longjmp(tohere,-1);
X}
X
X
X/*
X * readock(timeout,count)
X * timeout is in tenths of seconds
X * reads character(s) from file descriptor 'fd'
X * read 'count' characters, (1 <= count <= 3)
X * if more than one received, return ERROR unless all are CAN
X * normal response is NAK, ACK, CAN, G or C
X */
Xreadock(timeout,count)
X{
X	register int c;
X	static char byt[5];
X
X	if(setjmp(tohere))
X	{
X		report_str("TIMEOUT",1);
X		return(TIMEOUT);
X	}
X	c = timeout/10;
X	if(c<2)
X		c = 2;
X	signal(SIGALRM,SIGALRM_handler);
X	alarm(c);
X#if defined(ONEREAD)
X	c=read(iofd,byt,1);		/* regulus raw read is unique */
X#else
X	c=read(iofd,byt,count);
X#endif
X	rx_char_count += c;
X	alarm(0);
X	if(c<1)
X		return(TIMEOUT);
X	if(c==1)
X		return(byt[0]&0377);
X	else
X		while(c)
X			if(byt[--c] != CAN)
X				return(ERROR);
X	return(CAN);
X}
X
Xreadline(n)
X{
X	return(readock(n,1));
X}
X
X
Xpurgeline()
X{
X#if defined(M_XENIX)
X	ioctl(iofd,TCFLSH,0);
X#else
X	lseek(iofd,0L,2);
X#endif
X}
X
X/* send cancel string to get the other end to shut up */
Xsend_cancel()
X{
X	static char canistr[] =
X	{
X		24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
X	};
X	register char *cptr = canistr;
X
X	report_last_txhdr("^X CAN",1);
X	while(*cptr)
X		sendline(*cptr++);
X	flushline();
X}
X
X/*
X * substr(string,token) searches for token in string s
X * returns pointer to token within string if found,NULL otherwise
X */
Xchar *
Xsubstr(s,t)
Xregister char *s,*t;
X{
X	register char *ss,*tt;
X	/* search for first char of token */
X	for(ss=s; *s; s++)
X		if(*s == *t)
X			/* compare token with substring */
X			for(ss=s,tt=t; ;)
X			{
X				if(*tt == 0)
X					return(s);
X				if(*ss++ != *tt++)
X					break;
X			}
X	return(NULL);
X}
X
X
Xusage()
X{
X	exit(255);
X}
X
X/*
X * Get the receiver's init parameters
X */
Xgetzrxinit()
X{
X	register n;
X	struct stat f;
X
X	for(n=10; --n>=0; )
X	{
X		switch(zgethdr(Rxhdr,1))
X		{
X		case ZCHALLENGE:	/* Echo receiver's challenge numbr */
X			stohdr(Rxpos);
X			zshhdr(ZACK,Txhdr);
X			continue;
X		case ZCOMMAND:		/* They didn't see out ZRQINIT */
X			stohdr(0L);
X			zshhdr(ZRQINIT,Txhdr);
X			continue;
X		case ZRINIT:
X			Rxflags = 0377 & Rxhdr[ZF0];
X			Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
X			report_protocol_type("ZMODEM");
X			report_protocol_crc_type((Txfcs32) ? "/CRC32" : "/CRC16");
X			Zctlesc |= Rxflags & TESCCTL;
X			Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
X			if( !(Rxflags & CANFDX))
X				Txwindow = 0;
X#if defined(MODE2OK)
X			mode(2);	/* Set cbreak,XON/XOFF,etc. */
X#endif
X#if !defined(READCHECK)
X#if !defined(M_XENIX)
X			/* Use 1024 byte frames if no sample/interrupt */
X			if(Rxbuflen < 32 || Rxbuflen > 1024)
X			{
X				Rxbuflen = 1024;
X			}
X#endif
X#endif
X			/* Override to force shorter frame length */
X			if(Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
X				Rxbuflen = Tframlen;
X			if( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
X				Rxbuflen = Tframlen;
X
X			/* If using a pipe for testing set lower buf len */
X			fstat(iofd,&f);
X			if((f.st_mode & S_IFMT) != S_IFCHR
X			    && (Rxbuflen == 0 || Rxbuflen > 4096))
X				Rxbuflen = 4096;
X			sprintf(s128,"Remote: CRC32 %c  duplex %c",
X			    (Rxflags & CANFC32) ? 'y' : 'n',
X			    (Rxflags & CANFDX)  ? 'y' : 'n');
X			if(Rxbuflen)
X				sprintf(&s128[strlen(s128)],"  buflen %u",Rxbuflen);
X			else
X				strcat(s128,"  continuous stream y");
X			report_str(s128,2);
X			/*
X			 * If input is not a regular file,force ACK's each 1024
X			 *  (A smarter strategey could be used here ...)
X			 */
X			if( !Command)
X			{
X				fstat(fileno(in),&f);
X				if(((f.st_mode & S_IFMT) != S_IFREG)
X				    && (Rxbuflen == 0 || Rxbuflen > 1024))
X					Rxbuflen = 1024;
X			}
X
X			if(Baudrate > 300)	/* Set initial subpacket len */
X				blklen = 256;
X			if(Baudrate > 1200)
X				blklen = 512;
X			if(Baudrate >= 2400)	/* original code had > 2400 here ****/
X				blklen = 1024;
X			if(Rxbuflen && blklen>Rxbuflen)
X				blklen = Rxbuflen;
X			if(blkopt && blklen > blkopt)
X				blklen = blkopt;
X			blklen_original = blklen;
X			report_txblklen(blklen);
X			return(sendzsinit());
X		case ZCAN:
X		case TIMEOUT:
X			return(ERROR);
X		case ZRQINIT:
X			if(Rxhdr[ZF0] == ZCOMMAND)
X				continue;
X		default:
X			zshhdr(ZNAK,Txhdr);
X			continue;
X		}
X	}
X	return(ERROR);
X}
X
X/* Send send-init information */
Xsendzsinit()
X{
X	register c;
X
X	if(Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
X		return(OK);
X	errors = 0;
X	for(;;)
X	{
X		stohdr(0L);
X		if(Zctlesc)
X		{
X			Txhdr[ZF0] |= TESCCTL;
X			zshhdr(ZSINIT,Txhdr);
X		}
X		else
X			zsbhdr(ZSINIT,Txhdr);
X		zsdata(Myattn,1+strlen(Myattn),ZCRCW);
X		c = zgethdr(Rxhdr,1);
X		switch(c)
X		{
X		case ZCAN:
X			return(ERROR);
X		case ZACK:
X			return(OK);
X		default:
X			if(++errors > 19)
X				return(ERROR);
X			continue;
X		}
X	}
X}
X
X/* Send file name and related info */
Xzsendfile(buf,blen)
Xchar *buf;
X{
X	register c;
X
X	for(;;)
X	{
X		blklen = blklen_original;
X		Txhdr[ZF0] = Lzconv;	/* file conversion request */
X		Txhdr[ZF1] = Lzmanag;	/* file management request */
X		Txhdr[ZF2] = Lztrans;	/* file transport request */
X		Txhdr[ZF3] = 0;
X		zsbhdr(ZFILE,Txhdr);
X		zsdata(buf,blen,ZCRCW);
Xagain:
X		c = zgethdr(Rxhdr,1);
X		switch(c)
X		{
X		case ZRINIT:
X			while((c = readline(50)) > 0)
X				if(c == ZPAD)
X				{
X					goto again;
X				}
X			/* **** FALL THRU TO **** */
X		default:
X			continue;
X		case ZCAN:
X		case TIMEOUT:
X		case ZABORT:
X		case ZFIN:
X			return(ERROR);
X		case ZSKIP:
X			report_file_close();
X			fclose(in);
X			return(c);
X		case ZRPOS:
X			/*
X			 * Suppress zcrcw request otherwise triggered by
X			 * lastyunc==bytcnt
X			 */
X			Lastsync = (bytcnt = Txpos = Rxpos) -1;
X			fseek(in,Rxpos,0);
X			Dontread = FALSE;
X			report_send_stats(Txpos);
X			return(zsendfdata());
X		}
X	}
X}
X
X/* Send the data in the file */
Xzsendfdata()
X{
Xregister c,e,n;
Xregister newcnt;
Xregister long tcount = 0;
Xint junkcount;		/* Counts garbage chars received by TX */
Xstatic int tleft = 6;	/* Counter for test mode */
Xint err;
X
X	Lrxpos = 0;
X	junkcount = 0;
X	SameZrposAgain = FALSE;		/* variable was named Beenhereb4 (wht) */
X	this_file_frame_count = 0;	/* we've sent no frames (wht) */
Xsomemore:
X	if(setjmp(intrjmp))
X	{
Xwaitack:
X		junkcount = 0;
X		c = getinsync(0);
Xgotack:
X		switch(c)
X		{
X		default:
X		case ZCAN:
X			report_rcvr_cancelled("zfdata-1");
X			report_file_close();
X			fclose(in);
X			return(ERROR);
X		case ZSKIP:
X			report_file_close();
X			fclose(in);
X			return(c);
X		case ZACK:
X		case ZRPOS:
X			break;
X		case ZRINIT:
X			return(OK);
X		}
X#if defined(READCHECK)
X		/*
X		 * If the reverse channel can be tested for data,
X		 *  this logic may be used to detect error packets
X		 *  sent by the receiver,in place of setjmp/longjmp
X		 *  rdchk(fdes) returns non 0 if a character is available
X		 */
X		while(rdchk(iofd))
X		{
X			switch(readline(1))
X			{
X			case CAN:
X			case ZPAD:
X				c = getinsync(1);
X				goto gotack;
X			case XOFF:		/* Wait a while for an XON */
X			case XOFF|0200:
X				readline(100);
X			}
X		}
X#endif
X	}
X
X	newcnt = Rxbuflen;
X	Txwcnt = 0;
X	stohdr(Txpos);
X	zsbhdr(ZDATA,Txhdr);
X
X	do
X	{
X		if(Dontread)
X		{
X			n = Lastn;
X		} else
X		{
X			n = zbuf_build(txbuf,blklen);
X			Lastread = Txpos;
X			Lastn = n;
X		}
X		Dontread = FALSE;
X		if(n < blklen)
X			e = ZCRCE;
X		else if(junkcount > 3)
X			e = ZCRCW;
X		else if(bytcnt == Lastsync)
X			e = ZCRCW;
X		else if(Rxbuflen && (newcnt -= n) <= 0)
X			e = ZCRCW;
X		else if(Txwindow && (Txwcnt += n) >= Txwspac)
X		{
X			Txwcnt = 0;
X			e = ZCRCQ;
X		}
X		else
X			e = ZCRCG;
X		zsdata(txbuf,n,e);
X		this_file_frame_count++;		/* wht */
X		if(bad_condx_blklen)			/* wht */
X		{
X			/* if we have sent four frames since last ZRPOS to same pos (wht)*/
X			if((this_file_frame_count - bad_condx_frame_count) > 4) /*wht*/
X			{
X				if(blklen == bad_condx_blklen)
X					bad_condx_blklen = 0;
X				else
X					blklen *= 2;
X				SameZrposAgain = 0;
X			}
X		}
X		bytcnt = Txpos += n;
X		report_send_stats(Txpos);
X		if(e == ZCRCW)
X			goto waitack;
X#if defined(READCHECK)
X		/*
X		 * If the reverse channel can be tested for data,
X		 *  this logic may be used to detect error packets
X		 *  sent by the receiver,in place of setjmp/longjmp
X		 *  rdchk(fdes) returns non 0 if a character is available
X		 */
X		while(rdchk(iofd))
X		{
X			switch(readline(1))
X			{
X			case CAN:
X			case ZPAD:
X				c = getinsync(1);
X				if(c == ZACK)
X					break;
X#if defined(TCFLSH)
X				ioctl(iofd,TCFLSH,1);
X#endif
X				/* zcrce - dinna wanna starta ping-pong game */
X				zsdata(txbuf,0,ZCRCE);
X				goto gotack;
X
X			case XOFF:		/* Wait a while for an XON */
X			case XOFF|0200:
X				readline(100);
X
X			default:
X				++junkcount;
X			}
X		}
X#endif	/* READCHECK */
X		if(Txwindow)
X		{
X			while((tcount = Txpos - Lrxpos) >= Txwindow)
X			{
X				if(e != ZCRCQ)
X					zsdata(txbuf,0,e = ZCRCQ);
X				c = getinsync(1);
X				if(c != ZACK)
X				{
X#if defined(TCFLSH)
X					ioctl(iofd,TCFLSH,1);
X#endif
X					zsdata(txbuf,0,ZCRCE);
X					goto gotack;
X				}
X			}
X		}
X	} while(n == blklen);
X
X	for(;;)
X	{
X		stohdr(Txpos);
X		zsbhdr(ZEOF,Txhdr);
X		switch(err = getinsync(0))
X		{
X		case ZACK:
X			continue;
X		case ZRPOS:
X			goto somemore;
X		case ZRINIT:
X			return(OK);
X		case ZSKIP:
X			report_file_close();
X			fclose(in);
X			return(c);
X		default:
X			sprintf(s128,"SEND protocol sync error 0x%04x: %s",err,Pathname);
X			ecu_log_event(s128);	/* always log this */
X			report_str(s128 + 5,1);
X			if(FileRejectCount < 127)
X				FileRejectCount++;
X			report_file_byte_io(this_file_length);
X			report_file_close();
X			fclose(in);
X			return(ERROR);
X		}
X	}
X}
X
X/*
X * Respond to receiver's complaint, get back in sync with receiver
X */
Xgetinsync(flag)
X{
X	register c;
X
X	for(;;)
X	{
X		switch(c = zgethdr(Rxhdr,0))
X		{
X		case ZCAN:
X		case ZABORT:
X		case ZFIN:
X		case TIMEOUT:
X			sprintf(s128,"Receiver %s",frametypes[c+FTOFFSET]);
X			report_str(s128,1);
X			return(ERROR);
X		case ZRPOS:
X			report_str("Receiver ZRPOS",1);
X			/* ************************************* */
X			/*  If sending to a modem buffer,you    */
X			/*   might send a break at this point to */
X			/*   dump the modem's buffer.            */
X			/* ************************************* */
X			if(Lastn >= 0 && Lastread == Rxpos)
X			{
X				Dontread = TRUE;
X			} else
X			{
X				clearerr(in);	/* In case file EOF seen */
X				fseek(in,Rxpos,0);
X			}
X			bytcnt = Lrxpos = Txpos = Rxpos;
X			if(Lastsync == Rxpos)					/* wht - original code */
X			{										/* wht - original code */
X				/* save frame count at time of each occurrence (wht) */
X				bad_condx_frame_count = this_file_frame_count;	/* wht */
X				/* save block length at time of error (wht) */
X				if(++SameZrposAgain > 4)			/* wht - original code */
X				{									/* wht */
X					if(bad_condx_blklen == 0)		/* wht */
X						bad_condx_blklen = blklen;	/* wht */
X					if(blklen > 256)				/* wht - 32->256 */
X						blklen /= 2;				/* wht - original code */
X				}									/* wht */
X			}										/* wht - original code */
X			Lastsync = Rxpos;
X			report_send_stats(Txpos);
X			return(c);
X		case ZACK:
X			Lrxpos = Rxpos;
X			if(flag || Txpos == Rxpos)
X				return(ZACK);
X			continue;
X
X		case ZRINIT:
X#if defined(LOG_XFER)
X			sprintf(s256,"SEND success: %s",Pathname);
X			ecu_log_event(s256);
X#endif
X		case ZSKIP:
X			report_file_byte_io(this_file_length);
X			report_file_close();
X			fclose(in);
X			return(c);
X		case ERROR:
X		default:
X			report_str("Sending ZNAK",1);
X			zsbhdr(ZNAK,Txhdr);
X			continue;
X		}
X	}
X}
X
X
X/* Say "cancel_transaction" to the receiver,try to do it cleanly */
Xsaybibi()
X{
X	for(;;)
X	{
X		stohdr(0L);		/* CAF Was zsbhdr - minor change */
X		zshhdr(ZFIN,Txhdr);	/*  to make debugging easier */
X		switch(zgethdr(Rxhdr,0))
X		{
X		case ZFIN:
X			sendline('O');
X			sendline('O');
X			flushline();
X		case ZCAN:
X		case TIMEOUT:
X			return;
X		}
X	}
X}
X
Xdetermine_transaction_time()
X{
Xregister c;
Xstruct stat f;
Xchar *name;
X
X	rewind_file_list();
X	TotalLeft = 0;
X	Filesleft = 0;
X	while(get_file_list_name(&name))
X	{
X		f.st_size = -1;
X		if((access(name,04) >= 0) && (stat(name,&f) >= 0))
X		{
X			c = f.st_mode & S_IFMT;
X			if(c != S_IFDIR && c != S_IFBLK)
X			{
X				++Filesleft;
X				TotalLeft += f.st_size;
X			}
X		}
X	}
X	FilesTotal = Filesleft;
X	rewind_file_list();
X}
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
echo "File z/ecusz.c is complete"
chmod 0644 z/ecusz.c || echo "restore of z/ecusz.c fails"
echo "x - extracting z/zmodem.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > z/zmodem.c &&
X/* CHK=0x2976 */
X/*+-------------------------------------------------------------------------
X	zmodem.c - ZMODEM protocol primitives
X    based on code by Chuck Forsberg
X
X  Entry point Functions:
X	zsbhdr(type,hdr) send binary header
X	zshhdr(type,hdr) send hex header
X	zgethdr(hdr,eflag) receive header - binary or hex
X	zsdata(buf,len,frameend) send data
X	zrdata(buf,len) receive data
X	stohdr(pos) store position data in Txhdr
X	long rclhdr(hdr) recover position offset from header
X
X  Defined functions:
X	noxrd7()
X	rclhdr(hdr)
X	stohdr(pos)
X	zdlread()
X	zgeth1()
X	zgethdr(hdr,eflag)
X	zgethex()
X	zputhex(c)
X	zrbhdr(hdr)
X	zrbhdr32(hdr)
X	zrdat32(buf,length)
X	zrdata(buf,length)
X	zrhhdr(hdr)
X	zsbh32(hdr,type)
X	zsbhdr(type,hdr)
X	zsda32(buf,length,frameend)
X	zsdata(buf,length,frameend)
X	zsendline(c)
X	zshhdr(type,hdr)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-03-1989-22:58-wht------------- ecu 2.00 ---------------- */
X/*:06-24-1989-16:51-wht-flush edits --- ecu 1.95 */
X
X#include "zmodem.h"			/* wht */
X#include "zlint.h"
X
Xextern char s128[];				/* wht */
Xextern int Zctlesc;				/* wht */
Xextern int Zmodem;				/* wht */
Xextern long cr3tab[];			/* wht */
Xextern unsigned Baudrate;		/* wht */
Xextern unsigned short crctab[];	/* wht */
X
Xint Rxtimeout = 100;		/* Tenths of seconds to wait for something */
X
X#if !defined(UNSL)
X#define UNSL
X#endif
X
X
X
Xstatic lastsent;	/* Last char we sent */
Xstatic evenp;		/* Even parity seen on header */
X
X/* Globals used by ZMODEM functions */
Xchar Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
Xchar Rxhdr[4];		/* Received header */
Xchar Txhdr[4];		/* Transmitted header */
Xint Crc32;		/* Display flag indicating 32 bit CRC being received */
Xint Crc32t;		/* Display flag indicating 32 bit CRC being sent */
Xint Rxcount;		/* Count of data bytes received */
Xint Rxframeind;		/* ZBIN ZBIN32,or ZHEX type of frame received */
Xint Rxtimeout;	/* Tenths of seconds to wait for something */
Xint Rxtype;		/* Type of header received */
Xint Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
Xint Zrwindow;	/* RX window size (controls garbage count) */
Xlong Rxpos;	/* Received file position */
Xlong Txpos;	/* Transmitted file position */
X
Xchar *frametypes[] = 
X{
X	"Carrier Lost",		/* -3 */
X	"TIMEOUT",			/* -2 */
X	"ERROR",			/* -1 */
X/* #define FTOFFSET 3 moved to zmodem.h */
X	"ZRQINIT",
X	"ZRINIT",
X	"ZSINIT",
X	"ZACK ",
X	"ZFILE",
X	"ZSKIP",
X	"ZNAK ",
X	"ZABORT",
X	"ZFIN ",
X	"ZRPOS",
X	"ZDATA",
X	"ZEOF ",
X	"ZFERR",
X	"ZCRC ",
X	"ZCHALLENGE",
X	"ZCOMPL",
X	"ZCAN ",
X	"ZFREECNT",
X	"ZCOMMAND",
X	"ZSTDERR",
X	"xxxxx"
X#define FRTYPES 22	/* Total number of frame types in this array */
X	/*  not including psuedo negative entries */
X};
X
Xstatic char masked[] = "8 bit transparent path required";
Xstatic char badcrc[] = "Bad CRC";
X
X/* Send ZMODEM binary header hdr of type type */
Xzsbhdr(type,hdr)
Xregister unsigned char *hdr;
X{
X	register int n;
X	register unsigned crc;
X
X	report_tx_ind(1);
X	sprintf(s128,"hdr %s %08lx",frametypes[type+FTOFFSET],rclhdr(hdr));
X	report_last_txhdr(s128,0);
X
X	xsendline(ZPAD); 
X	xsendline(ZDLE);
X
X	if(Crc32t=Txfcs32)
X		zsbh32(hdr,type);
X	else 
X	{
X		xsendline(ZBIN); 
X		zsendline(type); 
X		crc = updcrc(type,0);
X
X		for(n=4; --n >= 0; ++hdr)
X		{
X			zsendline(*hdr);
X			crc = updcrc(*hdr,crc);
X		}
X		crc = updcrc(0,updcrc(0,crc));
X		zsendline(crc>>8);
X		zsendline(crc);
X	}
X	if(type != ZDATA)
X		flushline();
X	report_tx_ind(0);
X}
X
X
X/* Send ZMODEM binary header hdr of type type */
Xzsbh32(hdr,type)
Xregister char *hdr;
X{
X	register int n;
X	register UNSL long crc;
X
X	report_tx_ind(1);
X	xsendline(ZBIN32);  
X	zsendline(type);
X	crc = 0xFFFFFFFFL; 
X	crc = UPDC32(type,crc);
X
X	for(n=4; --n >= 0; ++hdr)
X	{
X		crc = UPDC32((0377 & *hdr),crc);
X		zsendline(*hdr);
X	}
X	crc = ~crc;
X	for(n=4; --n >= 0;)
X	{
X		zsendline((int)crc);
X		crc >>= 8;
X	}
X	report_tx_ind(0);
X}
X
X/* Send ZMODEM HEX header hdr of type type */
Xzshhdr(type,hdr)
Xregister unsigned char *hdr;
X{
X	register int n;
X	register unsigned short crc;
X
X	report_tx_ind(1);
X
X	sprintf(s128,"hdr %s %08lx",frametypes[type+FTOFFSET],rclhdr(hdr));
X	report_last_txhdr(s128,0);
X	sendline(ZPAD); 
X	sendline(ZPAD); 
X	sendline(ZDLE); 
X	sendline(ZHEX);
X	zputhex(type);
X	Crc32t = 0;
X
X	crc = updcrc(type,0);
X	for(n=4; --n >= 0; ++hdr)
X	{
X		zputhex(*hdr); 
X		crc = updcrc(*hdr,crc);
X/*		crc = updcrc((0377 & *hdr),crc);  original - wht */
X	}
X	crc = updcrc(0,updcrc(0,crc));
X	zputhex(crc>>8); 
X	zputhex(crc);
X
X	/* Make it printable on remote machine */
X	sendline(015); 
X	sendline(012);
X	/*
X	 * Uncork the remote in case a fake XOFF has stopped data flow
X	 */
X	if(type != ZFIN && type != ZACK)
X		sendline(021);
X	flushline();
X	report_tx_ind(0);
X}
X
X/*
X * Send binary array buf of length length,with ending ZDLE sequence frameend
X */
Xstatic char *Zendnames[] = { "ZCRCE","ZCRCG","ZCRCQ","ZCRCW"};
X
Xzsdata(buf,length,frameend)
Xregister unsigned char *buf;
X{
X	register unsigned short crc;
X
X	report_tx_ind(1);
X
X	sprintf(s128,"data %s %d bytes",Zendnames[frameend-ZCRCE&3],length);
X	report_last_txhdr(s128,0);
X	if(Crc32t)
X		zsda32(buf,length,frameend);
X	else 
X	{
X		crc = 0;
X		for(;--length >= 0; ++buf)
X		{
X			zsendline(*buf); 
X			crc = updcrc(*buf,crc);
X		}
X		xsendline(ZDLE); 
X		xsendline(frameend);
X		crc = updcrc(frameend,crc);
X
X		crc = updcrc(0,updcrc(0,crc));
X		zsendline(crc>>8); 
X		zsendline(crc);
X	}
X	if(frameend == ZCRCW)
X	{
X		xsendline(XON);  
X		flushline();
X	}
X	report_tx_ind(0);
X
X}
X
Xzsda32(buf,length,frameend)
Xregister char *buf;
X{
X	register int c;
X	register UNSL long crc;
X
X	report_tx_ind(1);
X
X	crc = 0xFFFFFFFFL;
X	for(;--length >= 0; ++buf)
X	{
X		c = *buf & 0377;
X		if(c & 0140)
X			xsendline(lastsent = c);
X		else
X			zsendline(c);
X		crc = UPDC32(c,crc);
X	}
X	xsendline(ZDLE); 
X	xsendline(frameend);
X	crc = UPDC32(frameend,crc);
X
X	crc = ~crc;
X	for(length=4; --length >= 0;)
X	{
X		zsendline((int)crc);  
X		crc >>= 8;
X	}
X	report_tx_ind(0);
X}
X
X/*
X * Receive array buf of max length with ending ZDLE sequence
X *  and CRC.  Returns the ending character or error code.
X *  NB: On errors may store length+1 bytes!
X */
Xzrdata(buf,length)
Xregister char *buf;
X{
X	register int c;
X	register unsigned short crc;
X	register char *end;
X	register int d;
X
X	report_rx_ind(1);
X
X	if(Rxframeind == ZBIN32)
X	{
X		report_rx_ind(0);
X		return(zrdat32(buf,length));
X	}
X
X	crc = Rxcount = 0;  
X	end = buf + length;
X	while(buf <= end)
X	{
X		if((c = zdlread()) & ~0377)
X		{
Xcrcfoo:
X			switch(c)
X			{
X			case GOTCRCE:
X			case GOTCRCG:
X			case GOTCRCQ:
X			case GOTCRCW:
X				crc = updcrc(((d=c)&0377),crc);
X				if((c = zdlread()) & ~0377)
X					goto crcfoo;
X				crc = updcrc(c,crc);
X				if((c = zdlread()) & ~0377)
X					goto crcfoo;
X				crc = updcrc(c,crc);
X				if(crc & 0xFFFF)
X				{
X					report_str(badcrc,1);
X					report_rx_ind(0);
X					return(ERROR);
X				}
X				Rxcount = length - (end - buf);
X				report_rxblklen(Rxcount);
X				sprintf(s128,"data %s %d bytes",
X					Zendnames[d-GOTCRCE&3],Rxcount);
X				report_last_rxhdr(s128,0);
X				report_rx_ind(0);
X				return(d);
X			case GOTCAN:
X				report_str("Sender Cancelled",1);
X				report_rx_ind(0);
X				return(ZCAN);
X			case TIMEOUT:
X				report_str("TIMEOUT",1);
X				report_rx_ind(0);
X				return(c);
X			default:
X				report_str("Bad data subpacket",1);
X				report_rx_ind(0);
X				return(c);
X			}
X		}
X		*buf++ = c;
X		crc = updcrc(c,crc);
X	}
X	report_str("Data subpacket too long",1);
X	report_rx_ind(0);
X	return(ERROR);
X}
X
Xzrdat32(buf,length)
Xregister char *buf;
X{
X	register int c;
X	register UNSL long crc;
X	register char *end;
X	register int d;
X
X	report_rx_ind(1);
X	crc = 0xFFFFFFFFL;  
X	Rxcount = 0;  
X	end = buf + length;
X	while(buf <= end)
X	{
X		if((c = zdlread()) & ~0377)
X		{
Xcrcfoo:
X			switch(c)
X			{
X			case GOTCRCE:
X			case GOTCRCG:
X			case GOTCRCQ:
X			case GOTCRCW:
X				d = c;  
X				c &= 0377;
X				crc = UPDC32(c,crc);
X				if((c = zdlread()) & ~0377)
X					goto crcfoo;
X				crc = UPDC32(c,crc);
X				if((c = zdlread()) & ~0377)
X					goto crcfoo;
X				crc = UPDC32(c,crc);
X				if((c = zdlread()) & ~0377)
X					goto crcfoo;
X				crc = UPDC32(c,crc);
X				if((c = zdlread()) & ~0377)
X					goto crcfoo;
X				crc = UPDC32(c,crc);
X				if(crc != 0xDEBB20E3)
X				{
X					report_str(badcrc,1);
X					report_rx_ind(0);
X					return(ERROR);
X				}
X				Rxcount = length - (end - buf);
X				report_rxblklen(Rxcount);
X				sprintf(s128,"data %s %d bytes",
X					Zendnames[d-GOTCRCE&3],Rxcount);
X				report_last_rxhdr(s128,0);
X				report_rx_ind(0);
X				return(d);
X			case GOTCAN:
X				report_str("Sender Canceled",1);
X				report_rx_ind(0);
X				return(ZCAN);
X			case TIMEOUT:
X				report_str("TIMEOUT",1);
X				report_rx_ind(0);
X				return(c);
X			default:
X				report_str("Bad data subpacket",1);
X				report_rx_ind(0);
X				return(c);
X			}
X		}
X		*buf++ = c;
X		crc = UPDC32(c,crc);
X	}
X	report_str("Data subpacket too long",1);
X	report_rx_ind(0);
X	return(ERROR);
X}
X
X
X/*
X * Read a ZMODEM header to hdr,either binary or hex.
X *  eflag controls local display of non zmodem characters:
X *	0:  no display
X *	1:  display printing characters only
X *	2:  display all non ZMODEM characters
X *  On success,set Zmodem to 1,set Rxpos and return type of header.
X *   Otherwise return negative on error.
X *   Return ERROR instantly if ZCRCW sequence,for fast error recovery.
X */
Xzgethdr(hdr,eflag)
Xchar *hdr;
X{
Xregister int c,n,cancount;
X
X	report_rx_ind(1);
X	n = Zrwindow + Baudrate;	/* Max bytes before start of frame */
X	Rxframeind = Rxtype = 0;
X
Xstartover:
X	cancount = 5;
Xagain:
X	/* Return immediate ERROR if ZCRCW sequence seen */
X	switch(c = readline(Rxtimeout))
X	{
X	case RCDO:
X	case TIMEOUT:
X		goto fifi;
X	case CAN:
Xgotcan:
X		if(--cancount <= 0)
X		{
X			c = ZCAN; 
X			goto fifi;
X		}
X		switch(c = readline(1))
X		{
X		case TIMEOUT:
X			goto again;
X		case ZCRCW:
X			c = ERROR;
X			/* **** FALL THRU TO **** */
X		case RCDO:
X			goto fifi;
X		default:
X			break;
X		case CAN:
X			if(--cancount <= 0)
X			{
X				c = ZCAN; 
X				goto fifi;
X			}
X			goto again;
X		}
X		/* **** FALL THRU TO **** */
X	default:
Xagn2:
X		if( --n == 0)
X		{
X			report_str("Garbage count exceeded",1);
X			report_last_rxhdr("Noise",0);
X			report_rx_ind(0);
X			return(ERROR);
X		}
X		goto startover;
X	case ZPAD|0200:		/* This is what we want. */
X	case ZPAD:		/* This is what we want. */
X		evenp = c & 0200;
X		break;
X	}
X	cancount = 5;
Xsplat:
X	switch(c = noxrd7())
X	{
X	case ZPAD:
X		goto splat;
X	case RCDO:
X	case TIMEOUT:
X		goto fifi;
X	default:
X		goto agn2;
X	case ZDLE:		/* This is what we want. */
X		break;
X	}
X
X	switch(c = noxrd7())
X	{
X	case RCDO:
X	case TIMEOUT:
X		goto fifi;
X	case ZBIN:
X		Rxframeind = ZBIN;  
X		Crc32 = FALSE;
X		c =  zrbhdr(hdr);
X		break;
X	case ZBIN32:
X		Crc32 = Rxframeind = ZBIN32;
X		c =  zrbhdr32(hdr);
X		break;
X	case ZHEX:
X		Rxframeind = ZHEX;  
X		Crc32 = FALSE;
X		c =  zrhhdr(hdr);
X		break;
X	case CAN:
X		goto gotcan;
X	default:
X		goto agn2;
X	}
X	Rxpos = hdr[ZP3] & 0377;
X	Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
X	Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
X	Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
Xfifi:
X	switch(c)
X	{
X	case GOTCAN:
X		c = ZCAN;
X		/* **** FALL THRU TO **** */
X	case ZNAK:
X	case ZCAN:
X	case ERROR:
X	case TIMEOUT:
X	case RCDO:
X		sprintf(s128,"Got %s",frametypes[c+FTOFFSET]);
X		report_str(s128,1);
X		/* **** FALL THRU TO **** */
X	default:
X		if(c >= -3 && c <= FRTYPES)
X			sprintf(s128,"hdr %s %08lx",frametypes[c+FTOFFSET],Rxpos);
X		else
X			sprintf(s128,"hdr 0x%02x? %08lx",c,Rxpos);
X		report_last_rxhdr(s128,0);
X	}
X	report_rx_ind(0);
X	return(c);
X}
X
X/* Receive a binary style header (type and position) */
Xzrbhdr(hdr)
Xregister char *hdr;
X{
X	register int c,n;
X	register unsigned short crc;
X
X	if((c = zdlread()) & ~0377)
X		return(c);
X	Rxtype = c;
X	crc = updcrc(c,0);
X
X	for(n=4; --n >= 0; ++hdr)
X	{
X		if((c = zdlread()) & ~0377)
X			return(c);
X		crc = updcrc(c,crc);
X		*hdr = c;
X	}
X	if((c = zdlread()) & ~0377)
X		return(c);
X	crc = updcrc(c,crc);
X	if((c = zdlread()) & ~0377)
X		return(c);
X	crc = updcrc(c,crc);
X	if(crc & 0xFFFF)
X	{
X		if(evenp)
X			report_str(masked,1);
X		report_str(badcrc,1);
X		return(ERROR);
X	}
X#if defined(ZMODEM)
X	Protocol = ZMODEM;
X#endif
X	Zmodem = 1;
X	return(Rxtype);
X}
X
X/* Receive a binary style header (type and position) with 32 bit FCS */
Xzrbhdr32(hdr)
Xregister char *hdr;
X{
X	register int c,n;
X	register UNSL long crc;
X
X	if((c = zdlread()) & ~0377)
X		return(c);
X	Rxtype = c;
X	crc = 0xFFFFFFFFL; 
X	crc = UPDC32(c,crc);
X
X	for(n=4; --n >= 0; ++hdr)
X	{
X		if((c = zdlread()) & ~0377)
X			return(c);
X		crc = UPDC32(c,crc);
X		*hdr = c;
X	}
X	for(n=4; --n >= 0;)
X	{
X		if((c = zdlread()) & ~0377)
X			return(c);
X		crc = UPDC32(c,crc);
X	}
X	if(crc != 0xDEBB20E3)
X	{
X		if(evenp)
X			report_str(masked,1);
X		report_str(badcrc,1);
X		return(ERROR);
X	}
X#if defined(ZMODEM)
X	Protocol = ZMODEM;
X#endif
X	Zmodem = 1;
X	return(Rxtype);
X}
X
X
X/* Receive a hex style header (type and position) */
Xzrhhdr(hdr)
Xchar *hdr;
X{
X	register int c;
X	register unsigned short crc;
X	register int n;
X
X	if((c = zgethex()) < 0)
X		return(c);
X	Rxtype = c;
X	crc = updcrc(c,0);
X
X	for(n=4; --n >= 0; ++hdr)
X	{
X		if((c = zgethex()) < 0)
X			return(c);
X		crc = updcrc(c,crc);
X		*hdr = c;
X	}
X	if((c = zgethex()) < 0)
X		return(c);
X	crc = updcrc(c,crc);
X	if((c = zgethex()) < 0)
X		return(c);
X	crc = updcrc(c,crc);
X	if(crc & 0xFFFF)
X	{
X		report_str(badcrc,1); 
X		return(ERROR);
X	}
X	if(readline(1) == '\r')	/* Throw away possible cr/lf */
X		readline(1);
X#if defined(ZMODEM)
X	Protocol = ZMODEM;
X#endif
X	Zmodem = 1; 
X	return(Rxtype);
X}
X
X/* Send a byte as two hex digits */
Xzputhex(c)
Xregister int c;
X{
X	static char digits[]	= "0123456789abcdef";
X
X	sendline(digits[(c&0xF0)>>4]);
X	sendline(digits[(c)&0xF]);
X}
X
X/*
X * Send character c with ZMODEM escape sequence encoding.
X *  Escape XON,XOFF. Escape CR following @ (Telenet net escape)
X */
Xzsendline(c)
X{
X
X	/* Quick check for non control characters */
X	if(c & 0140)
X		xsendline(lastsent = c);
X	else 
X	{
X		switch(c &= 0377)
X		{
X		case ZDLE:
X			xsendline(ZDLE);
X			xsendline(lastsent = (c ^= 0100));
X			break;
X		case 015:
X		case 0215:
X			if(!Zctlesc && (lastsent & 0177) != '@')
X				goto sendit;
X			/* **** FALL THRU TO **** */
X		case 020:
X		case 021:
X		case 023:
X		case 0220:
X		case 0221:
X		case 0223:
SHAR_EOF
echo "End of part 27"
echo "File z/zmodem.c is continued in part 28"
echo "28" > s2_seq_.tmp
exit 0
-- 
-------------------------------------------------------------------
Warren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
Ker-au'-lo-phon.  An 8-foot partial flue-stop, having metal pipes
surmounted by adjustable rings, and with a hole bored near the top
of each pipe, producing a soft and "reedy" tone.