koreth@ssyx.ucsc.edu (Steven Grimm) (05/28/88)
Submitted-by: bammi@mandrill.ces.cwru.edu (Jwahar R. Bammi)
Posting-number: Volume 1, Issue 40
Archive-name: rzsz/part05
#!/bin/sh
# this is part 5 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file zm.c continued
#
CurArch=5
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
sed 's/^X//' << 'SHAR_EOF' >> zm.c
X crc = 0;
X for (;--length >= 0;) {
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 unsigned long crc;
X
X crc = 0xFFFFFFFF;
X for (;--length >= 0;) {
X zsendline(*buf); crc = UPDC32((0377& *buf++), crc);
X }
X xsendline(ZDLE); xsendline(frameend);
X crc = UPDC32(frameend, crc);
X
X crc = ~crc;
X for (length=4; --length >= 0;) {
X zsendline(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 */
Xzrdata(buf, length)
Xregister char *buf;
X{
X register c;
X register unsigned short crc;
X register d;
X
X if (Rxframeind == ZBIN32)
X return zrdat32(buf, length);
X
X crc = Rxcount = 0;
X for (;;) {
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("Bad data CRC %x", crc);
X return ERROR;
X }
X vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
X return d;
X case GOTCAN:
X zperr("ZMODEM: Sender Canceled");
X return ZCAN;
X case TIMEOUT:
X zperr("ZMODEM data TIMEOUT");
X return c;
X default:
X zperr("ZMODEM bad data subpacket ret=%x", c);
X return c;
X }
X }
X if (--length < 0) {
X zperr("ZMODEM data subpacket too long");
X return ERROR;
X }
X ++Rxcount;
X *buf++ = c;
X crc = updcrc(c, crc);
X continue;
X }
X}
Xzrdat32(buf, length)
Xregister char *buf;
X{
X register c;
X register unsigned long crc;
X register d;
X
X crc = 0xFFFFFFFF; Rxcount = 0;
X for (;;) {
X if ((c = zdlread()) & ~0377) {
Xcrcfoo:
X switch (c) {
X case GOTCRCE:
X case GOTCRCG:
X case GOTCRCQ:
X case GOTCRCW:
X crc = UPDC32((d=c)&0377, 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("Bad data CRC %lX", crc);
X return ERROR;
X }
X vfile("zrdat32: cnt = %d ret = %x", Rxcount, d);
X return d;
X case GOTCAN:
X zperr("ZMODEM: Sender Canceled");
X return ZCAN;
X case TIMEOUT:
X zperr("ZMODEM data TIMEOUT");
X return c;
X default:
X zperr("ZMODEM bad data subpacket ret=%x", c);
X return c;
X }
X }
X if (--length < 0) {
X zperr("ZMODEM data subpacket too long");
X return ERROR;
X }
X ++Rxcount;
X *buf++ = c;
X crc = UPDC32(c, crc);
X continue;
X }
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 and return type of header.
X * Otherwise return negative on error
X */
Xzgethdr(hdr, eflag)
Xchar *hdr;
X{
X register c, n, cancount;
X
X n = Baudrate; /* Max characters before start of frame */
X cancount = 5;
Xagain:
X Rxframeind = Rxtype = 0;
X switch (c = noxrd7()) {
X case RCDO:
X case TIMEOUT:
X goto fifi;
X case CAN:
X if (--cancount <= 0) {
X c = ZCAN; goto fifi;
X }
X /* **** FALL THRU TO **** */
X default:
Xagn2:
X if ( --n == 0) {
X zperr("ZMODEM 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 if (c != CAN)
X cancount = 5;
X goto again;
X case ZPAD: /* This is what we want. */
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;
X c = zrbhdr(hdr);
X break;
X case ZBIN32:
X Rxframeind = ZBIN32;
X c = zrbhdr32(hdr);
X break;
X case ZHEX:
X Rxframeind = ZHEX;
X c = zrhhdr(hdr);
X break;
X case CAN:
X if (--cancount <= 0) {
X c = ZCAN; goto fifi;
X }
X goto agn2;
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("ZMODEM: Got %s %s", frametypes[c+FTOFFSET],
X (c >= 0) ? "header" : "error");
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 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;) {
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 zperr("Bad Header CRC"); return ERROR;
X }
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 c, n;
X register unsigned long crc;
X
X if ((c = zdlread()) & ~0377)
X return c;
X Rxtype = c;
X crc = 0xFFFFFFFF; crc = UPDC32(c, crc);
X
X for (n=4; --n >= 0;) {
X if ((c = zdlread()) & ~0377)
X return c;
X crc = UPDC32(c, crc);
X *hdr++ = c;
X }
X for (n=4; --n >= 0;) {
X if ((c = zdlread()) & ~0377)
X return c;
X crc = UPDC32(c, crc);
X }
X if (crc != 0xDEBB20E3) {
X zperr("Bad Header CRC %lX", crc); return ERROR;
X }
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 c;
X register unsigned short crc;
X register 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;) {
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("Bad Header CRC"); return ERROR;
X }
X if (readline(1) == '\r') /* Throw away possible cr/lf */
X readline(1);
X Zmodem = 1; return Rxtype;
X}
X
X/* Send a byte as two hex digits */
Xzputhex(c)
Xregister c;
X{
X static char digits[] = "0123456789abcdef";
X
X if (Verbose>4)
X vfile("zputhex: %x", 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)
Xregister c;
X{
X static lastsent;
X
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 ((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#ifdef ZKER
X if (Zctlesc<0)
X goto sendit;
X#endif
X xsendline(ZDLE);
X c ^= 0100;
Xsendit:
X xsendline(lastsent = c);
X break;
X default:
X#ifdef ZKER
X if (Zctlesc>0 && ! (c & 0140)) {
X xsendline(ZDLE);
X c ^= 0100;
X }
X#endif
X xsendline(lastsent = c);
X }
X}
X
X/* Decode two lower case hex digits into an 8 bit byte value */
Xzgethex()
X{
X register c;
X
X c = zgeth1();
X if (Verbose>4)
X vfile("zgethex: %x", c);
X return c;
X}
Xzgeth1()
X{
X register 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 c;
X
X if ((c = readline(Rxtimeout)) != ZDLE)
X return c;
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 default:
X if ((c & 0140) == 0100)
X return (c ^ 0100);
X break;
X }
X zperr("Got bad ZMODEM 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 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 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
SHAR_EOF
chmod 0600 zm.c || echo "restore of zm.c fails"
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 * 01-15-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
X/* Parameters for ZSINIT frame */
X#define ZATTNLEN 32 /* Max length of attention string */
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 options, one of these in ZF1 */
X#define ZMNEW 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 ZMSPARS 5 /* Encoding for sparse file */
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
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 */
Xint Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */
Xint Rxtype; /* Type of header received */
Xint Rxcount; /* Count of data bytes received */
Xextern Rxtimeout; /* Tenths of seconds to wait for something */
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 Znulls; /* Number of nulls to send at beginning of ZDATA hdr */
Xchar Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */
X
SHAR_EOF
chmod 0600 zmodem.h || echo "restore of zmodem.h fails"
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0