Path: utzoo!attcan!uunet!husc6!mailrus!rutgers!ucsd!ucbvax!agate!saturn!ssyx!koreth
From: koreth@ssyx.ucsc.edu (Steven Grimm)
Newsgroups: comp.sources.atari.st
Subject: v01i047: zmdm -- terminal program with file transfer part07/08
Keywords: mwc, alcyon, shar
Message-ID: <3513@saturn.ucsc.edu>
Date: 30 May 88 16:16:11 GMT
Sender: usenet@saturn.ucsc.edu
Lines: 1358
Approved: koreth@ssyx.ucsc.edu
Submitted-by: bammi@mandrill.ces.cwru.edu (Jwahar R. Bammi)
Posting-number: Volume 1, Issue 47
Archive-name: zmdm/part07
#!/bin/sh
# this is part 7 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file YMODEM.DOC continued
#
CurArch=7
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 YMODEM.DOC"
sed 's/^X//' << 'SHAR_EOF' >> YMODEM.DOC
X
X + The last block sent is no different from others, i.e. there is no
X "short block".
X Figure 7. XMODEM Message Block Level Protocol
X
X Each block of the transfer looks like:
X <255-blk #><--128 data bytes-->
X in which:
X = 01 hex
X = binary number, starts at 01 increments by 1, and
X wraps 0FFH to 00H (not to 01)
X <255-blk #> = blk # after going thru 8080 "CMA" instr, i.e.
X each bit complemented in the 8-bit block number.
X Formally, this is the "ones complement".
X = the sum of the data bytes only. Toss any carry.
X
X
X
X
X
X
X
X
X Chapter 6 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 16
X
X
X
X 6.3 File Level Protocol
X
X 6.3.1 Common_to_Both_Sender_and_Receiver
X All errors are retried 10 times. For versions running with an operator
X (i.e. NOT with XMODEM), a message is typed after 10 errors asking the
X operator whether to "retry or quit".
X
X Some versions of the protocol use , ASCII ^X, to cancel
X transmission. This was never adopted as a standard, as having a
X single "abort" character makes the transmission susceptible to
X false termination due to an or being corrupted
X into a and aborting transmission.
X
X The protocol may be considered "receiver driven", that is, the
X sender need not automatically re-transmit, although it does in
X the current implementations.
X
X
X 6.3.2 Receive_Program_Considerations
X The receiver has a 10-second timeout. It sends a every time it
X times out. The receiver's first timeout, which sends a ,
X signals the transmitter to start. Optionally, the receiver
X could send a immediately, in case the sender was ready.
X This would save the initial 10 second timeout. However, the
X receiver MUST continue to timeout every 10 seconds in case the
X sender wasn't ready.
X
X Once into a receiving a block, the receiver goes into a
X one-second timeout for each character and the checksum. If the
X receiver wishes to a block for any reason (invalid header,
X timeout receiving data), it must wait for the line to clear.
X See "programming tips" for ideas.
X
X Synchronizing: If a valid block number is received, it will be: 1) the
X expected one, in which case everything is fine; or 2) a repeat of the
X previously received block. This should be considered OK, and only
X indicates that the receivers got glitched, and the sender re-
X transmitted; 3) any other block number indicates a fatal loss of
X synchronization, such as the rare case of the sender getting a
X line-glitch that looked like an . Abort the transmission,
X sending a
X
X
X 6.3.3 Sending_program_considerations
X While waiting for transmission to begin, the sender has only a
X single very long timeout, say one minute. In the current
X protocol, the sender has a 10 second timeout before retrying. I
X suggest NOT doing this, and letting the protocol be completely
X receiver-driven. This will be compatible with existing programs.
X
X When the sender has no more data, it sends an , and awaits an ,
X resending the if it doesn't get one. Again, the protocol could be
X receiver-driven, with the sender only having the high-level 1-minute
X timeout to abort.
X
X
X
X
X Chapter 6 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 17
X
X
X
X Here is a sample of the data flow, sending a 3-block message.
X It includes the two most common line hits - a garbaged block,
X and an reply getting garbaged. represents the checksum byte.
X
X Figure 8. Data flow including Error Recovery
X
X SENDER RECEIVER
X times out after 10 seconds,
X <---
X 01 FE -data- --->
X <---
X 02 FD -data- xx ---> (data gets line hit)
X <---
X 02 FD -data- xx --->
X <---
X 03 FC -data- xx --->
X (ack gets garbaged) <---
X 03 FC -data- xx --->
X --->
X <---
X --->
X <---
X (finished)
X
X 6.4 Programming Tips
X
X + The character-receive subroutine should be called with a parameter
X specifying the number of seconds to wait. The receiver should first
X call it with a time of 10, then and try again, 10 times.
X
X After receiving the , the receiver should call the character
X receive subroutine with a 1-second timeout, for the remainder of the
X message and the . Since they are sent as a
X continuous stream, timing out of this implies a serious
X like glitch that caused, say, 127 characters to be seen
X instead of 128.
X
X + When the receiver wishes to , it should call a "PURGE"
X subroutine, to wait for the line to clear. Recall the sender tosses
X any characters in its UART buffer immediately upon
X completing sending a block, to ensure no glitches were mis-
X interpreted.
X
X The most common technique is for "PURGE" to call the character
X receive subroutine, specifying a 1-second timeout,[1] and looping
X back to PURGE until a timeout occurs. The is then sent,
X ensuring the other end will see it.
X
X
X __________
X
X 1. These times should be adjusted for use with timesharing systems.
X
X
X
X
X Chapter 6 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 18
X
X
X
X + You may wish to add code recommended by John Mahr to your character
X receive routine - to set an error flag if the UART shows framing
X error, or overrun. This will help catch a few more glitches - the
X most common of which is a hit in the high bits of the byte in two
X consecutive bytes. The comes out OK since counting
X in 1-byte produces the same result of adding 80H + 80H as
X with adding 00H + 00H.
X
X
X
X 7. XMODEM/CRC Overview
X
X 1/13/85 by John Byrns -- CRC option.
X
X Please pass on any reports of errors in this document or suggestions for
X improvement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312)
X 885-1105.
X
X The CRC used in the Modem Protocol is an alternate form of block check
X which provides more robust error detection than the original checksum.
X Andrew S. Tanenbaum says in his book, Computer Networks, that the CRC-
X CCITT used by the Modem Protocol will detect all single and double bit
X errors, all errors with an odd number of bits, all burst errors of length
X 16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit and
X longer bursts.
X
X The changes to the Modem Protocol to replace the checksum with
X the CRC are straight forward. If that were all that we did we
X would not be able to communicate between a program using the old
X checksum protocol and one using the new CRC protocol. An initial
X handshake was added to solve this problem. The handshake allows
X a receiving program with CRC capability to determine whether the
X sending program supports the CRC option, and to switch it to CRC
X mode if it does. This handshake is designed so that it will work
X properly with programs which implement only the original
X protocol. A description of this handshake is presented in section 10.
X
X Figure 9. Message Block Level Protocol, CRC mode
X
X Each block of the transfer in CRC mode looks like:
X <255-blk #><--128 data bytes-->
X in which:
X = 01 hex
X = binary number, starts at 01 increments by 1, and
X wraps 0FFH to 00H (not to 01)
X <255-blk #> = ones complement of blk #.
X = byte containing the 8 hi order coefficients of the CRC.
X = byte containing the 8 lo order coefficients of the CRC.
X
X
X
X
X
X
X
X Chapter 7 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 19
X
X
X
X 7.1 CRC Calculation
X
X 7.1.1 Formal_Definition
X To calculate the 16 bit CRC the message bits are considered to be the
X coefficients of a polynomial. This message polynomial is first multiplied
X by X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 +
X 1) using modulo two arithmetic. The remainder left after the division is
X the desired CRC. Since a message block in the Modem Protocol is 128 bytes
X or 1024 bits, the message polynomial will be of order X^1023.
X The hi order bit of the first byte of the message block is the
X coefficient of X^1023 in the message polynomial. The lo order
X bit of the last byte of the message block is the coefficient of
X X^0 in the message polynomial.
X
X Figure 10. Example of CRC Calculation written in C
X UPDCRC update routine from "rbsb.c". Refer to the source code for these
X programs (contained in RZSZ1.SHQ and RZSZ2.SHQ) for usage. A fast table
X driven macro is also included in this file.
X /* update CRC */
X unsigned short
X updcrc(c, crc)
X register c;
X register unsigned crc;
X {
X register count;
X
X for (count=8; --count>=0;) {
X if (crc & 0x8000) {
X crc <<= 1;
X crc += (((c<<=1) & 0400) != 0);
X crc ^= 0x1021;
X }
X else {
X crc <<= 1;
X crc += (((c<<=1) & 0400) != 0);
X }
X }
X return crc;
X }
X
X 7.2 CRC File Level Protocol Changes
X
X 7.2.1 Common_to_Both_Sender_and_Receiver
X The only change to the File Level Protocol for the CRC option is the
X initial handshake which is used to determine if both the sending and the
X receiving programs support the CRC mode. All Modem Programs
X should support the checksum mode for compatibility with older
X versions. A receiving program that wishes to receive in CRC
X mode implements the mode setting handshake by sending a in
X place of the initial . If the sending program supports CRC
X mode it will recognize the and will set itself into CRC
X mode, and respond by sending the first block as if a had
X been received. If the sending program does not support CRC mode it will
X
X
X
X Chapter 7 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 20
X
X
X
X not respond to the at all. After the receiver has sent the
X it will wait up to 3 seconds for the that starts the
X first block. If it receives a within 3 seconds it will
X assume the sender supports CRC mode and will proceed with the
X file exchange in CRC mode. If no is received within 3
X seconds the receiver will switch to checksum mode, send a ,
X and proceed in checksum mode. If the receiver wishes to use
X checksum mode it should send an initial and the sending program
X should respond to the as defined in the original Modem Protocol.
X After the mode has been set by the initial or the protocol
X follows the original Modem Protocol and is identical whether the checksum
X or CRC is being used.
X
X
X 7.2.2 Receive_Program_Considerations
X There are at least 4 things that can go wrong with the mode setting
X handshake.
X
X 1. the initial can be garbled or lost.
X
X 2. the initial can be garbled.
X
X 3. the initial can be changed to a .
X
X 4. the initial from a receiver which wants to receive
X in checksum can be changed to a .
X
X The first problem can be solved if the receiver sends a second after
X it times out the first time. This process can be repeated several times.
X It must not be repeated too many times before sending a and
X switching to checksum mode or a sending program without CRC support may
X time out and abort. Repeating the will also fix the second problem if
X the sending program cooperates by responding as if a were received
X instead of ignoring the extra .
X
X It is possible to fix problems 3 and 4 but probably not worth the trouble
X since they will occur very infrequently. They could be fixed by switching
X modes in either the sending or the receiving program after a large number
X of successive s. This solution would risk other problems however.
X
X
X 7.2.3 Sending_Program_Considerations
X The sending program should start in the checksum mode. This will insure
X compatibility with checksum only receiving programs. Anytime a is
X received before the first or the sending program should set
X itself into CRC mode and respond as if a were received. The sender
X should respond to additional s as if they were s until the first
X is received. This will assist the receiving program in determining
X the correct mode when the is lost or garbled. After the first
X is received the sending program should ignore s.
X
X
X
X
X
X Chapter 7 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 21
X
X
X
X 7.3 Data Flow Examples with CRC Option
X
X Here is a data flow example for the case where the receiver requests
X transmission in the CRC mode but the sender does not support the CRC
X option. This example also includes various transmission errors.
X represents the checksum byte.
X
X Figure 11. Data Flow: Receiver has CRC Option, Sender Doesn't
X
X SENDER RECEIVER
X <---
X times out after 3 seconds,
X <---
X times out after 3 seconds,
X <---
X times out after 3 seconds,
X <---
X times out after 3 seconds,
X <---
X 01 FE -data- --->
X <---
X 02 FD -data- ---> (data gets line hit)
X <---
X 02 FD -data- --->
X <---
X 03 FC -data- --->
X (ack gets garbaged) <---
X times out after 10 seconds,
X <---
X 03 FC -data- --->
X <---
X --->
X <---
X
X Here is a data flow example for the case where the receiver requests
X transmission in the CRC mode and the sender supports the CRC
X option. This example also includes various transmission errors.
X represents the 2 CRC bytes.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X Chapter 7 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 22
X
X
X
X Figure 12. Receiver and Sender Both have CRC Option
X
X SENDER RECEIVER
X <---
X 01 FE -data- --->
X <---
X 02 FD -data- ---> (data gets line hit)
X <---
X 02 FD -data- --->
X <---
X 03 FC -data- --->
X (ack gets garbaged) <---
X times out after 10 seconds,
X <---
X 03 FC -data- --->
X <---
X --->
X <---
X
X
X 8. MORE INFORMATION
X
X More information may be obtained by calling Telegodzilla at 503-621-3746.
X Hit RETURNs for baud rate detection.Speed detection is automatic for 300,
X 1200, and 2400 bps.
X
X A version this file with boldface, underlining, and superscripts for
X printing on Epson or Gemini printers is available on Telegodzilla as
X "YMODEME.DOC" or "YMODEME.DQC".
X
X UUCP sites can obtain this file with
X uucp omen!/usr/spool/uucppublic/ymodem.doc /tmp
X A continually updated list of available files is stored in
X /usr/spool/uucppublic/FILES.
X
X The following L.sys line calls Telegodzilla (Pro-YAM in host operation).
X Telegodzilla waits for carriage returns to determine the incoming speed.
X If none is detected, 1200 bps is assumed and a greeting is displayed.
X
X In response to "Name Please:" uucico gives the Pro-YAM "link"
X command as a user name. The password (Giznoid) controls access
X to the Xenix system connected to the IBM PC's other serial port.
X Communications between Pro-YAM and Xenix use 9600 bps; YAM
X converts this to the caller's speed.
X
X Finally, the calling uucico logs in as uucp.
X
X omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
X
X Contact omen!caf if you wish the troff source files.
X
X
X
X
X
X Chapter 8 Xmodem Protocol Overview
X
X
X
X
X
X
X
X X/YMODEM Protocol Reference 09-11-86 23
X
X
X
X 9. Document Revisions
X
X The September 11 1986 edition clarifies nomenclature and some minor
X points. The April 15 1986 edition clarifies some points concerning CRC
X calculations and spaces in the header.
X
X
X 10. YMODEM Programs
X
X A demonstration version of Professional-YAM is available as ZMODEM.ARC
X This may be used to test YMODEM amd ZMODEM implementations.
X
X Unix programs supporting the YMODEM protocol are available on
X Telegodzilla as RZSZ1.SHQ and RZSZ2.SHQ (SQueezed shell archives).
X Most Unix like systems are supported, including V7, Xenix, Sys III,
X 4.2 BSD, SYS V, Idris, Coherent, and Regulus.
X
X A version for VAX-VMS is available in VRBSB.SHQ.
X
X Irv Hoff has added YMODEM 1k packets and basic YMODEM batch transfers to
X the KMD and IMP series programs, which replace the XMODEM and
X MODEM7/MDM7xx series respectively. Overlays are available for a wide
X variety of CP/M systems.
X
X Questions about YMODEM, the Professional-YAM communications program, and
X requests for evaluation copies may be directed to:
X Chuck Forsberg
X Omen Technology Inc
X 17505-V Sauvie Island Road
X Portland Oregon 97231
X Voice: 503-621-3406
X Modem: 503-621-3746 Speed: 2400,1200,300
X Usenet: ...!tektronix!reed!omen!caf
X Compuserve: 70007,2304
X Source: TCE022
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X Chapter 10 Xmodem Protocol Overview
X
X
X
X
X
X
X
X
X
X
X
X CONTENTS
X
X
X 1. ROSETTA STONE.................................................... 2
X
X 2. YET ANOTHER PROTOCOL?............................................ 2
X 2.1 Some Messages from the Pioneer.............................. 4
X
X 3. XMODEM PROTOCOL ENHANCEMENTS..................................... 5
X 3.1 Graceful Abort.............................................. 6
X 3.2 CRC-16 Option............................................... 6
X 3.3 XMODEM-1k 1024 Byte Packet.................................. 7
X
X 4. YMODEM Batch File Transmission................................... 7
X 4.1 KMD/IMP Exceptions to YMODEM................................ 13
X
X 5. YMODEM-g File Transmission....................................... 13
X
X 6. XMODEM PROTOCOL OVERVIEW......................................... 14
X 6.1 Definitions................................................. 14
X 6.2 Transmission Medium Level Protocol.......................... 15
X 6.3 File Level Protocol......................................... 16
X 6.4 Programming Tips............................................ 17
X
X 7. XMODEM/CRC Overview.............................................. 18
X 7.1 CRC Calculation............................................. 19
X 7.2 CRC File Level Protocol Changes............................. 19
X 7.3 Data Flow Examples with CRC Option.......................... 21
X
X 8. MORE INFORMATION................................................. 22
X
X 9. Document Revisions............................................... 23
X
X 10. YMODEM Programs.................................................. 23
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - i -
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X LIST OF FIGURES
X
X
X Figure 1. 1024 byte Packets......................................... 7
X
X Figure 2. Mixed 1024 and 128 byte Packets........................... 7
X
X Figure 3. YMODEM Batch Transmission Session......................... 12
X
X Figure 4. YMODEM Filename packet transmitted by sz.................. 12
X
X Figure 5. YMODEM Header Information used by various programs........ 13
X
X Figure 6. YMODEM-g Transmission Session............................. 14
X
X Figure 7. XMODEM Message Block Level Protocol....................... 15
X
X Figure 8. Data flow including Error Recovery........................ 17
X
X Figure 9. Message Block Level Protocol, CRC mode.................... 18
X
X Figure 10. Example of CRC Calculation written in C................... 19
X
X Figure 11. Data Flow: Receiver has CRC Option, Sender Doesn't........ 21
X
X Figure 12. Receiver and Sender Both have CRC Option.................. 22
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - ii -
X
X
X
X
SHAR_EOF
echo "File YMODEM.DOC is complete"
chmod 0600 YMODEM.DOC || echo "restore of YMODEM.DOC fails"
echo "x - extracting ZM.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > ZM.C &&
X/*
X * ACKNOWLEDGEMENTS
X *
X * ZMDM was derived from rz/sz for Unix posted by
X * Chuck Forsberg (...!tektronix!reed!omen!caf ). We
X * thank him for his excellent code, and for giving
X * us permission to use and distribute his code and
X * documentation.
X *
X * Atari St version by:
X * Jwahar Bammi
X * usenet: mandrill!bammi@{decvax,sun}.UUCP
X * csnet: bammi@mandrill.ces.CWRU.edu
X * arpa: bammi@mandrill.ces.CWRU.edu
X * CompuServe: 71515,155
X */
X
X/*
X * Z M . C
X * ZMODEM protocol primitives
X * 01-15-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#include "config.h"
X#include "zmdm.h"
X#include "common.h"
X
X#ifndef CANFDX
X#include "zmodem.h"
X#endif
X
X#define xsendline(X) sendline(X)
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
X/* Send ZMODEM binary header hdr of type type */
Xzsbhdr(type, hdr)
Xregister int type;
Xregister char *hdr;
X{
X register int n;
X register unsigned int crc;
X
X vfile2("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
X if (type == ZDATA)
X for (n = Znulls; --n >=0; )
X zsendline(0);
X
X xsendline(ZPAD); xsendline(ZDLE);
X
X if (Txfcs32)
X zsbh32(hdr, type);
X else {
X xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
X
X for (n=4; --n >= 0;) {
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 flush_modem();
X}
X
X
X/* Send ZMODEM binary header hdr of type type */
Xzsbh32(hdr, type)
Xregister char *hdr;
Xregister int type;
X{
X register int n;
X register unsigned long crc;
X
X xsendline(ZBIN32); zsendline(type);
X crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
X
X for (n=4; --n >= 0;) {
X zsendline(*hdr);
X crc = UPDC32((0377& *hdr++), crc);
X }
X crc = ~crc;
X for (n=4; --n >= 0;) {
X zsendline((unsigned int)(crc&0xFFFF)); crc >>= 8;
X }
X}
X
X/* Send ZMODEM HEX header hdr of type type */
Xzshhdr(type, hdr)
Xregister int type;
Xregister char *hdr;
X{
X register int n;
X register unsigned int crc;
X
X vfile2("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
X sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
X zputhex(type);
X
X crc = updcrc(type, 0);
X for (n=4; --n >= 0;) {
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)
X sendline(021);
X flush_modem();
X}
X
X/*
X * Send binary array buf of length length, with ending ZDLE sequence frameend
X */
Xzsdata(buf, length, frameend)
Xregister char *buf;
Xregister int length, frameend;
X{
X register unsigned int crc;
X
X vfile("zsdata: length=%d end=%x", length, frameend);
X if (Txfcs32)
X zsda32(buf, length, frameend);
X else {
X crc = 0;
X for (;--length >= 0;) {
X zsendline(*buf);
X 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); flush_modem();
X }
X}
X
Xzsda32(buf, length, frameend)
Xregister char *buf;
Xregister int length, frameend;
X{
X register unsigned long crc;
X
X crc = 0xFFFFFFFFL;
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((unsigned int)(crc&0xFFFF)); 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;
Xregister int length;
X{
X register int c;
X register unsigned int crc;
X register int 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 log2("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 log2("ZMODEM: Sender Canceled");
X return ZCAN;
X case TIMEOUT:
X log2("ZMODEM data TIMEOUT");
X return c;
X default:
X log2("ZMODEM bad data subpacket ret=%x", c);
X return c;
X }
X }
X if (--length < 0) {
X log2("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;
Xregister int length;
X{
X register int c;
X register unsigned long crc;
X register int d;
X
X crc = 0xFFFFFFFFL; 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 != 0xDEBB20E3L) {
X log2("Bad data CRC");
X return ERROR;
X }
X vfile2("zrdat32: cnt = %ld ret = %x", Rxcount, d);
X return d;
X case GOTCAN:
X log2("ZMODEM: Sender Canceled");
X return ZCAN;
X case TIMEOUT:
X log2("ZMODEM data TIMEOUT");
X return c;
X default:
X log2("ZMODEM bad data subpacket ret");
X return c;
X }
X }
X if (--length < 0) {
X log2("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)
Xregister char *hdr;
Xregister int eflag;
X{
X register int c, n, cancount;
X
X n = Baudrate; /* Max characters before start of frame */
X cancount = 5;
Xagain:
X Rxframeind = Rxtype = 0;
X switch (c = noxread7()) {
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 log2("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 = noxread7()) {
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 = noxread7()) {
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 vfile2("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 vfile2("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
X else
X vfile2("zgethdr: %ld %lx", (long)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 int 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 log2("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 int c, n;
X register unsigned long crc;
X
X if ((c = zdlread()) & ~0377)
X return c;
X Rxtype = c;
X crc = 0xFFFFFFFFL; 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 != 0xDEBB20E3L) {
X log2("Bad Header 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 int c;
X register unsigned int 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;) {
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 log2("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 int 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 int c;
X{
X static int 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 if(SendType)
X {
X if (Zctlesc<0)
X goto sendit;
X }
X
X xsendline(ZDLE);
X c ^= 0100;
Xsendit:
X xsendline(lastsent = c);
X break;
X default:
X if(SendType)
X {
X if (Zctlesc>0 && ! (c & 0140)) {
X xsendline(ZDLE);
X c ^= 0100;
X }
X }
X
X xsendline(lastsent = c);
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>4)
X vfile("zgethex: %x", c);
X return c;
X}
Xzgeth1()
X{
X register int c, n;
X
X if ((c = noxread7()) < 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 = noxread7()) < 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
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)
SHAR_EOF
echo "End of part 7"
echo "File ZM.C is continued in part 8"
echo "8" > s2_seq_.tmp
exit 0