[comp.binaries.ibm.pc] Zmodem for Unix and VAX/VMS, part 4of4

w8sdz@brl-smoke.ARPA (Keith B. Petersen ) (04/28/88)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 4 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file vvmodem.c continued
#
CurArch=4
if test ! -r ._seq_
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
) < ._seq_ || exit 1
echo "x - Continuing file vvmodem.c"
sed 's/^X//' << 'SHAR_EOF' >> vvmodem.c
X
X	if (tt_chan == -1)
X		assign_channel();
X
X	status	= sys$qiow(0, tt_chan, IO$_SENSEMODE,
X	  &(tt_characteristics->dev_modes), NULL, 0,
X	  &(tt_characteristics->dev_characteristics), 12,
X	  0, 0, 0, 0);
X	if (status != SS$_NORMAL ||
X	  tt_characteristics->dev_modes.status != SS$_NORMAL)
X		fatal("GTTY:  sense mode QIO error return.\n");
X
X	c = tt_characteristics.dev_modes.t_speed % 17;
X	Baudrate = speeds[c];
X
X	return(status);
X}
X
X/*
X *	Return the number of characters waiting in TTY input buffer
X */
Xrdchk()
X{
X	int		status;
X	struct	tt_io_iosb	iosb;
X	struct	tt_io_tacf typeahead;
X
X	status	= sys$qiow(0, tt_chan, IO$_SENSEMODE|IO$M_TYPEAHDCNT,
X	  &iosb, NULL, 0,
X	  &typeahead, 0,
X	  0, 0, 0, 0);
X
X	return(typeahead.byte_count);
X}
X
X/*
X *	Read NCHAR characters from the terminal without echoing or
X *	interpretation.
X *	If the argument SECONDS is non-zero, use that as the
X *	timeout period in seconds for the read.
X *
X *	Returns SS$_TIMEOUT in case of timeout or other error.
X *	  Otherwise, returns the number of characters read.
X */
Xraw_read(nchar, charbuf, seconds)
Xchar		*charbuf;
Xint		nchar;
Xunsigned	seconds;
X{
X	short			function;
X	int			status;
X	struct	tt_io_iosb	iosb;
X
X	if (tt_chan == -1)
X		assign_channel();
X
X	function	= IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR;
X
X	if (seconds)
X		status	= sys$qiow(0, tt_chan, function | IO$M_TIMED,
X		  &iosb, NULL, 0,
X		  charbuf, nchar, seconds,
X		  &termin_mask, NULL, 0);
X	else
X		status	= sys$qiow(0, tt_chan, function,
X		  &iosb, NULL, 0,
X		  charbuf, nchar, 0,
X		  &termin_mask, NULL, 0);
X
X	if (iosb.byte_count)
X		return iosb.byte_count;
X	return SS$_TIMEOUT;
X}
X
X/*
X *	Writes a character to the terminal without echoing or
X *	interpretation.
X */
Xraw_write(c)
Xchar	c;
X{
X	int			status;
X	struct	tt_io_iosb	iosb;
X
X	if (tt_chan == -1)
X		assign_channel();
X
X	status	= sys$qiow(0, tt_chan,
X	  IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT,
X	  &iosb, NULL, 0,
X	  &c, 1, 0, 0, 0, 0);
X
X	if (status != SS$_NORMAL || iosb.status != SS$_NORMAL)
X		fatal("RAW_WRITE:  write QIO error return.\n");
X
X	return;
X}
X
X/*
X *	Writes a buffer to the terminal without echoing or
X *	interpretation.
X */
Xraw_wbuf(nchar, charbuf)
Xchar		*charbuf;
Xint		nchar;
X{
X	int			status;
X	struct	tt_io_iosb	iosb;
X
X	if (tt_chan == -1)
X		assign_channel();
X
X	status	= sys$qiow(0, tt_chan,
X	  IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT,
X	  &iosb, NULL, 0,
X	  charbuf, nchar, 0, 0, 0, 0);
X
X	if (status != SS$_NORMAL || iosb.status != SS$_NORMAL)
X		fatal("RAW_WRITE:  write QIO error return.\n");
X
X	return;
X}
X
X/*
X *  Sets terminal information from VMS.
X *	 Modified 12-85 Larry Farr/Chuck Forsberg to not use
X *	 bad parity returned by VMS 4.
X */
Xstty(tt_characteristics)
Xstruct	tt_info	*tt_characteristics;
X{
X	short			*f_ptr, /* *p_ptr, */ *s_ptr;
X	int			status;
X	struct	tt_mode_iosb	iosb;
X
X	if (tt_chan == -1)
X		assign_channel();
X
X/*
X *	We do the following in order to get a full short, concatenating
X *	two adjacent chars:
X */
X	s_ptr	= &(tt_characteristics->dev_modes.t_speed);	/*  Speeds  */
X	f_ptr	= &(tt_characteristics->dev_modes.CR_fill);	/*  Fills  */
X	/* p_ptr	= &(tt_characteristics->dev_modes.parity_flags); */
X
X	status	= sys$qiow(0, tt_chan, IO$_SETMODE,
X	  &iosb, NULL, 0,
X	  &(tt_characteristics->dev_characteristics), 12,
X	  /* *s_ptr, *f_ptr, *p_ptr, 0);	*/
X	  *s_ptr, *f_ptr, 0, 0);
X	if (status != SS$_NORMAL || iosb.status != SS$_NORMAL)
X		printf("STTY:  set mode QIO returned %d\n", status);
X
X	return(status);
X}
X
SHAR_EOF
echo "File vvmodem.c is complete"
chmod 0644 vvmodem.c || echo "restore of vvmodem.c fails"
fi
if test -f zm.c; then echo "File zm.c exists"; else
echo "x - extracting zm.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > zm.c &&
X/*
X *   Z M . C
X *    ZMODEM protocol primitives
X *    11-10-87  Chuck Forsberg Omen Technology Inc
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
X#ifndef CANFDX
X#include "zmodem.h"
Xint Rxtimeout = 100;		/* Tenths of seconds to wait for something */
X#endif
X
X#ifndef UNSL
X#define UNSL
X#endif
X
X
X/* Globals used by ZMODEM functions */
Xint Rxframeind;		/* ZBIN ZBIN32, or ZHEX type of frame received */
Xint Rxtype;		/* Type of header received */
Xint Rxcount;		/* Count of data bytes received */
Xchar Rxhdr[4];		/* Received header */
Xchar Txhdr[4];		/* Transmitted header */
Xlong Rxpos;		/* Received file position */
Xlong Txpos;		/* Transmitted file position */
Xint Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
Xint Crc32t;		/* Display flag indicating 32 bit CRC being sent */
Xint Crc32;		/* Display flag indicating 32 bit CRC being received */
Xint Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
Xchar Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
X
Xstatic lastsent;	/* Last char we sent */
Xstatic evenp;		/* Even parity seen on header */
X
Xstatic char *frametypes[] = {
X	"Carrier Lost",		/* -3 */
X	"TIMEOUT",		/* -2 */
X	"ERROR",		/* -1 */
X#define FTOFFSET 3
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 char *hdr;
X{
X	register int n;
X	register unsigned short crc;
X
X	vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
X	if (type == ZDATA)
X		for (n = Znulls; --n >=0; )
X			xsendline(0);
X
X	xsendline(ZPAD); xsendline(ZDLE);
X
X	if (Crc32t=Txfcs32)
X		zsbh32(hdr, type);
X	else {
X		xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
X
X		for (n=4; --n >= 0; ++hdr) {
X			zsendline(*hdr);
X			crc = updcrc((0377& *hdr), crc);
X		}
X		crc = updcrc(0,updcrc(0,crc));
X		zsendline(crc>>8);
X		zsendline(crc);
X	}
X	if (type != ZDATA)
X		flushmo();
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	xsendline(ZBIN32);  zsendline(type);
X	crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
X
X	for (n=4; --n >= 0; ++hdr) {
X		crc = UPDC32((0377 & *hdr), crc);
X		zsendline(*hdr);
X	}
X	crc = ~crc;
X	for (n=4; --n >= 0;) {
X		zsendline((int)crc);
X		crc >>= 8;
X	}
X}
X
X/* Send ZMODEM HEX header hdr of type type */
Xzshhdr(type, hdr)
Xregister char *hdr;
X{
X	register int n;
X	register unsigned short crc;
X
X	vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
X	sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
X	zputhex(type);
X	Crc32t = 0;
X
X	crc = updcrc(type, 0);
X	for (n=4; --n >= 0; ++hdr) {
X		zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
X	}
X	crc = updcrc(0,updcrc(0,crc));
X	zputhex(crc>>8); zputhex(crc);
X
X	/* Make it printable on remote machine */
X	sendline(015); 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	flushmo();
X}
X
X/*
X * Send binary array buf of length length, with ending ZDLE sequence frameend
X */
Xstatic char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
Xzsdata(buf, length, frameend)
Xregister char *buf;
X{
X	register unsigned short crc;
X
X	vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
X	if (Crc32t)
X		zsda32(buf, length, frameend);
X	else {
X		crc = 0;
X		for (;--length >= 0; ++buf) {
X			zsendline(*buf); crc = updcrc((0377 & *buf), crc);
X		}
X		xsendline(ZDLE); xsendline(frameend);
X		crc = updcrc(frameend, crc);
X
X		crc = updcrc(0,updcrc(0,crc));
X		zsendline(crc>>8); zsendline(crc);
X	}
X	if (frameend == ZCRCW) {
X		xsendline(XON);  flushmo();
X	}
X}
X
Xzsda32(buf, length, frameend)
Xregister char *buf;
X{
X	register int c;
X	register UNSL long crc;
X
X	crc = 0xFFFFFFFFL;
X	for (;--length >= 0; ++buf) {
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); xsendline(frameend);
X	crc = UPDC32(frameend, crc);
X
X	crc = ~crc;
X	for (length=4; --length >= 0;) {
X		zsendline((int)crc);  crc >>= 8;
X	}
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	if (Rxframeind == ZBIN32)
X		return zrdat32(buf, length);
X
X	crc = Rxcount = 0;  end = buf + length;
X	while (buf <= end) {
X		if ((c = zdlread()) & ~0377) {
Xcrcfoo:
X			switch (c) {
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					zperr(badcrc);
X					return ERROR;
X				}
X				Rxcount = length - (end - buf);
X				vfile("zrdata: %d  %s", Rxcount,
X				 Zendnames[d-GOTCRCE&3]);
X				return d;
X			case GOTCAN:
X				zperr("Sender Canceled");
X				return ZCAN;
X			case TIMEOUT:
X				zperr("TIMEOUT");
X				return c;
X			default:
X				zperr("Bad data subpacket");
X				return c;
X			}
X		}
X		*buf++ = c;
X		crc = updcrc(c, crc);
X	}
X	zperr("Data subpacket too long");
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	crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
X	while (buf <= end) {
X		if ((c = zdlread()) & ~0377) {
Xcrcfoo:
X			switch (c) {
X			case GOTCRCE:
X			case GOTCRCG:
X			case GOTCRCQ:
X			case GOTCRCW:
X				d = c;  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					zperr(badcrc);
X					return ERROR;
X				}
X				Rxcount = length - (end - buf);
X				vfile("zrdat32: %d %s", Rxcount,
X				 Zendnames[d-GOTCRCE&3]);
X				return d;
X			case GOTCAN:
X				zperr("Sender Canceled");
X				return ZCAN;
X			case TIMEOUT:
X				zperr("TIMEOUT");
X				return c;
X			default:
X				zperr("Bad data subpacket");
X				return c;
X			}
X		}
X		*buf++ = c;
X		crc = UPDC32(c, crc);
X	}
X	zperr("Data subpacket too long");
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{
X	register int c, n, cancount;
X
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	case RCDO:
X	case TIMEOUT:
X		goto fifi;
X	case CAN:
Xgotcan:
X		if (--cancount <= 0) {
X			c = ZCAN; goto fifi;
X		}
X		switch (c = readline(1)) {
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				c = ZCAN; goto fifi;
X			}
X			goto again;
X		}
X	/* **** FALL THRU TO **** */
X	default:
Xagn2:
X		if ( --n == 0) {
X			zperr("Garbage count exceeded");
X			return(ERROR);
X		}
X		if (eflag && ((c &= 0177) & 0140))
X			bttyout(c);
X		else if (eflag > 1)
X			bttyout(c);
X#ifdef UNIX
X		fflush(stderr);
X#endif
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	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	case RCDO:
X	case TIMEOUT:
X		goto fifi;
X	case ZBIN:
X		Rxframeind = ZBIN;  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;  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	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		zperr("Got %s", frametypes[c+FTOFFSET]);
X	/* **** FALL THRU TO **** */
X	default:
X		if (c >= -3 && c <= FRTYPES)
X			vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
X		else
X			vfile("zgethdr: %d %lx", c, Rxpos);
X	}
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		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		if (evenp)
X			zperr(masked);
X		zperr(badcrc);
X		return ERROR;
X	}
X#ifdef 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; crc = UPDC32(c, crc);
X#ifdef DEBUGZ
X	vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
X#endif
X
X	for (n=4; --n >= 0; ++hdr) {
X		if ((c = zdlread()) & ~0377)
X			return c;
X		crc = UPDC32(c, crc);
X		*hdr = c;
X#ifdef DEBUGZ
X		vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
X#endif
X	}
X	for (n=4; --n >= 0;) {
X		if ((c = zdlread()) & ~0377)
X			return c;
X		crc = UPDC32(c, crc);
X#ifdef DEBUGZ
X		vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
X#endif
X	}
X	if (crc != 0xDEBB20E3) {
X		if (evenp)
X			zperr(masked);
X		zperr(badcrc);
X		return ERROR;
X	}
X#ifdef 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		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		zperr(badcrc); return ERROR;
X	}
X	if (readline(1) == '\r')	/* Throw away possible cr/lf */
X		readline(1);
X#ifdef ZMODEM
X	Protocol = ZMODEM;
X#endif
X	Zmodem = 1; 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	if (Verbose>8)
X		vfile("zputhex: %02X", c);
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		switch (c &= 0377) {
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:
X			xsendline(ZDLE);
X			c ^= 0100;
X	sendit:
X			xsendline(lastsent = c);
X			break;
X		default:
X			if (Zctlesc && ! (c & 0140)) {
X				xsendline(ZDLE);
X				c ^= 0100;
X			}
X			xsendline(lastsent = c);
X		}
X	}
X}
X
X/* Decode two lower case hex digits into an 8 bit byte value */
Xzgethex()
X{
X	register int c;
X
X	c = zgeth1();
X	if (Verbose>8)
X		vfile("zgethex: %02X", c);
X	return c;
X}
Xzgeth1()
X{
X	register int c, n;
X
X	if ((c = noxrd7()) < 0)
X		return c;
X	n = c - '0';
X	if (n > 9)
X		n -= ('a' - ':');
X	if (n & ~0xF)
X		return ERROR;
X	if ((c = noxrd7()) < 0)
X		return c;
X	c -= '0';
X	if (c > 9)
X		c -= ('a' - ':');
X	if (c & ~0xF)
X		return ERROR;
X	c += (n<<4);
X	return c;
X}
X
X/*
X * Read a byte, checking for ZMODEM escape encoding
X *  including CAN*5 which represents a quick abort
X */
Xzdlread()
X{
X	register int c;
X
Xagain:
X	/* Quick check for non control characters */
X	if ((c = readline(Rxtimeout)) & 0140)
X		return c;
X	switch (c) {
X	case ZDLE:
X		break;
X	case 023:
X	case 0223:
X	case 021:
X	case 0221:
X		goto again;
X	default:
X		if (Zctlesc && !(c & 0140)) {
X			goto again;
X		}
X		return c;
X	}
Xagain2:
X	if ((c = readline(Rxtimeout)) < 0)
X		return c;
X	if (c == CAN && (c = readline(Rxtimeout)) < 0)
X		return c;
X	if (c == CAN && (c = readline(Rxtimeout)) < 0)
X		return c;
X	if (c == CAN && (c = readline(Rxtimeout)) < 0)
X		return c;
X	switch (c) {
X	case CAN:
X		return GOTCAN;
X	case ZCRCE:
X	case ZCRCG:
X	case ZCRCQ:
X	case ZCRCW:
X		return (c | GOTOR);
X	case ZRUB0:
X		return 0177;
X	case ZRUB1:
X		return 0377;
X	case 023:
X	case 0223:
X	case 021:
X	case 0221:
X		goto again2;
X	default:
X		if (Zctlesc && ! (c & 0140)) {
X			goto again2;
X		}
X		if ((c & 0140) ==  0100)
X			return (c ^ 0100);
X		break;
X	}
X	if (Verbose>1)
X		zperr("Bad escape sequence %x", c);
X	return ERROR;
X}
X
X/*
X * Read a character from the modem line with timeout.
X *  Eat parity, XON and XOFF characters.
X */
Xnoxrd7()
X{
X	register int c;
X
X	for (;;) {
X		if ((c = readline(Rxtimeout)) < 0)
X			return c;
X		switch (c &= 0177) {
X		case XON:
X		case XOFF:
X			continue;
X		default:
X			if (Zctlesc && !(c & 0140))
X				continue;
X		case '\r':
X		case '\n':
X		case ZDLE:
X			return c;
X		}
X	}
X}
X
X/* Store long integer pos in Txhdr */
Xstohdr(pos)
Xlong pos;
X{
X	Txhdr[ZP0] = pos;
X	Txhdr[ZP1] = pos>>8;
X	Txhdr[ZP2] = pos>>16;
X	Txhdr[ZP3] = pos>>24;
X}
X
X/* Recover a long integer from a header */
Xlong
Xrclhdr(hdr)
Xregister char *hdr;
X{
X	register long l;
X
X	l = (hdr[ZP3] & 0377);
X	l = (l << 8) | (hdr[ZP2] & 0377);
X	l = (l << 8) | (hdr[ZP1] & 0377);
X	l = (l << 8) | (hdr[ZP0] & 0377);
X	return l;
X}
X
X/* End of zm.c */
SHAR_EOF
chmod 0644 zm.c || echo "restore of zm.c fails"
fi
if test -f zmodem.h; then echo "File zmodem.h exists"; else
echo "x - extracting zmodem.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > zmodem.h &&
X/*
X *   Z M O D E M . H     Manifest constants for ZMODEM
X *    application to application file transfer protocol
X *    05-23-87  Chuck Forsberg Omen Technology Inc
X */
X#define ZPAD '*'	/* 052 Padding character begins frames */
X#define ZDLE 030	/* Ctrl-X Zmodem escape - `ala BISYNC DLE */
X#define ZDLEE (ZDLE^0100)	/* Escaped ZDLE as transmitted */
X#define ZBIN 'A'	/* Binary frame indicator */
X#define ZHEX 'B'	/* HEX frame indicator */
X#define ZBIN32 'C'	/* Binary frame with 32 bit FCS */
X
X/* Frame types (see array "frametypes" in zm.c) */
X#define ZRQINIT	0	/* Request receive init */
X#define ZRINIT	1	/* Receive init */
X#define ZSINIT 2	/* Send init sequence (optional) */
X#define ZACK 3		/* ACK to above */
X#define ZFILE 4		/* File name from sender */
X#define ZSKIP 5		/* To sender: skip this file */
X#define ZNAK 6		/* Last packet was garbled */
X#define ZABORT 7	/* Abort batch transfers */
X#define ZFIN 8		/* Finish session */
X#define ZRPOS 9		/* Resume data trans at this position */
X#define ZDATA 10	/* Data packet(s) follow */
X#define ZEOF 11		/* End of file */
X#define ZFERR 12	/* Fatal Read or Write error Detected */
X#define ZCRC 13		/* Request for file CRC and response */
X#define ZCHALLENGE 14	/* Receiver's Challenge */
X#define ZCOMPL 15	/* Request is complete */
X#define ZCAN 16		/* Other end canned session with CAN*5 */
X#define ZFREECNT 17	/* Request for free bytes on filesystem */
X#define ZCOMMAND 18	/* Command from sending program */
X#define ZSTDERR 19	/* Output to standard error, data follows */
X
X/* ZDLE sequences */
X#define ZCRCE 'h'	/* CRC next, frame ends, header packet follows */
X#define ZCRCG 'i'	/* CRC next, frame continues nonstop */
X#define ZCRCQ 'j'	/* CRC next, frame continues, ZACK expected */
X#define ZCRCW 'k'	/* CRC next, ZACK expected, end of frame */
X#define ZRUB0 'l'	/* Translate to rubout 0177 */
X#define ZRUB1 'm'	/* Translate to rubout 0377 */
X
X/* zdlread return values (internal) */
X/* -1 is general error, -2 is timeout */
X#define GOTOR 0400
X#define GOTCRCE (ZCRCE|GOTOR)	/* ZDLE-ZCRCE received */
X#define GOTCRCG (ZCRCG|GOTOR)	/* ZDLE-ZCRCG received */
X#define GOTCRCQ (ZCRCQ|GOTOR)	/* ZDLE-ZCRCQ received */
X#define GOTCRCW (ZCRCW|GOTOR)	/* ZDLE-ZCRCW received */
X#define GOTCAN	(GOTOR|030)	/* CAN*5 seen */
X
X/* Byte positions within header array */
X#define ZF0	3	/* First flags byte */
X#define ZF1	2
X#define ZF2	1
X#define ZF3	0
X#define ZP0	0	/* Low order 8 bits of position */
X#define ZP1	1
X#define ZP2	2
X#define ZP3	3	/* High order 8 bits of file position */
X
X/* Bit Masks for ZRINIT flags byte ZF0 */
X#define CANFDX	01	/* Rx can send and receive true FDX */
X#define CANOVIO	02	/* Rx can receive data during disk I/O */
X#define CANBRK	04	/* Rx can send a break signal */
X#define CANCRY	010	/* Receiver can decrypt */
X#define CANLZW	020	/* Receiver can uncompress */
X#define CANFC32	040	/* Receiver can use 32 bit Frame Check */
X#define ESCCTL 0100	/* Receiver expects ctl chars to be escaped */
X#define ESC8   0200	/* Receiver expects 8th bit to be escaped */
X
X/* Parameters for ZSINIT frame */
X#define ZATTNLEN 32	/* Max length of attention string */
X/* Bit Masks for ZSINIT flags byte ZF0 */
X#define TESCCTL 0100	/* Transmitter expects ctl chars to be escaped */
X#define TESC8   0200	/* Transmitter expects 8th bit to be escaped */
X
X/* Parameters for ZFILE frame */
X/* Conversion options one of these in ZF0 */
X#define ZCBIN	1	/* Binary transfer - inhibit conversion */
X#define ZCNL	2	/* Convert NL to local end of line convention */
X#define ZCRESUM	3	/* Resume interrupted file transfer */
X/* Management include options, one of these ored in ZF1 */
X#define ZMSKNOLOC	0200	/* Skip file if not present at rx */
X/* Management options, one of these ored in ZF1 */
X#define ZMMASK	037	/* Mask for the choices below */
X#define ZMNEWL	1	/* Transfer if source newer or longer */
X#define ZMCRC	2	/* Transfer if different file CRC or length */
X#define ZMAPND	3	/* Append contents to existing file (if any) */
X#define ZMCLOB	4	/* Replace existing file */
X#define ZMNEW	5	/* Transfer if source newer */
X	/* Number 5 is alive ... */
X#define ZMDIFF	6	/* Transfer if dates or lengths different */
X#define ZMPROT	7	/* Protect destination file */
X/* Transport options, one of these in ZF2 */
X#define ZTLZW	1	/* Lempel-Ziv compression */
X#define ZTCRYPT	2	/* Encryption */
X#define ZTRLE	3	/* Run Length encoding */
X/* Extended options for ZF3, bit encoded */
X#define ZXSPARS	64	/* Encoding for sparse file operations */
X
X/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */
X#define ZCACK1	1	/* Acknowledge, then do command */
X
Xlong rclhdr();
X
X/* Globals used by ZMODEM functions */
Xextern Rxframeind;	/* ZBIN ZBIN32, or ZHEX type of frame received */
Xextern Rxtype;		/* Type of header received */
Xextern Rxcount;		/* Count of data bytes received */
Xextern Zrwindow;	/* RX window size (controls garbage count) */
Xextern Rxtimeout;	/* Tenths of seconds to wait for something */
Xextern char Rxhdr[4];	/* Received header */
Xextern char Txhdr[4];	/* Transmitted header */
Xextern long Rxpos;	/* Received file position */
Xextern long Txpos;	/* Transmitted file position */
Xextern Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
Xextern Crc32t;		/* Display flag indicating 32 bit CRC being sent */
Xextern Crc32;		/* Display flag indicating 32 bit CRC being received */
Xextern Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
Xextern char Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
X
X/* End of ZMODEM.H */
SHAR_EOF
chmod 0644 zmodem.h || echo "restore of zmodem.h fails"
fi
if test -f zupl.t; then echo "File zupl.t exists"; else
echo "x - extracting zupl.t (Text)"
sed 's/^X//' << 'SHAR_EOF' > zupl.t &&
X	:: ProYAM/ZCOMM script to upload minirb and rz/sz to *nix
X	if S>1200 pt1
X	ena -t
X	if !fminirb.c echo "Can't find minirb.c !!";  abort
X	putw "stty -echo; cat >minirb.c\r"
X	f -xHr minirb.c
X	putw "\r\4"
X	putw "stty echo\r"
X	dis -h
X	pat 1 "rwx"
X	pat 2 "%"
X	put "cc minirb.c -o minirb; ls -l minirb\r"
X	wait -f120
X	if 1 goto okok
X	echo "The compiiation appears to have failed."
X	echo "Please compile minirb.c to minirb, then"
X	echo "hit F5 to upload the rest of the rz/sz files."
X	set f5
X@putw minirb\r; sb README zmodem.h zm.c sz.c rz.c crctab.c rbsb.c *.1 gz ptest.sh
X	t
X	return
Xokok:	echo "Minirb Compilation Appears Successful."
X	put minirb\r
X	sb README zmodem.h zm.c sz.c rz.c crctab.c rbsb.c *.1 gz ptest.sh
X	t
X	return
SHAR_EOF
chmod 0644 zupl.t || echo "restore of zupl.t fails"
fi
rm -f ._seq_
echo "You have unpacked the last part"
exit 0
-- 
Keith Petersen
Arpa: W8SDZ@SIMTEL20.ARPA
Uucp: {bellcore,decwrl,harvard,lll-crg,ucbvax,uw-beaver}!simtel20.arpa!w8sdz
GEnie: W8SDZ