koreth@ssyx.ucsc.edu (Steven Grimm) (05/30/88)
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 <SOH><blk #><255-blk #><--128 data bytes--><cksum> X in which: X <SOH> = 01 hex X <blk #> = 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 <cksum> = 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 <can>, 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 <ack> <nak> or <soh> being corrupted X into a <can> 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 <nak> every time it X times out. The receiver's first timeout, which sends a <nak>, X signals the transmitter to start. Optionally, the receiver X could send a <nak> 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 <nak> 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 <ack> 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 <ack>. Abort the transmission, X sending a <can> 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 <eot>, and awaits an <ack>, X resending the <eot> 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 <ack> reply getting garbaged. <xx> represents the checksum byte. X X Figure 8. Data flow including Error Recovery X X SENDER RECEIVER X times out after 10 seconds, X <--- <nak> X <soh> 01 FE -data- <xx> ---> X <--- <ack> X <soh> 02 FD -data- xx ---> (data gets line hit) X <--- <nak> X <soh> 02 FD -data- xx ---> X <--- <ack> X <soh> 03 FC -data- xx ---> X (ack gets garbaged) <--- <ack> X <soh> 03 FC -data- xx ---> <ack> X <eot> ---> X <--- <anything except ack> X <eot> ---> X <--- <ack> 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 <nak> and try again, 10 times. X X After receiving the <soh>, the receiver should call the character X receive subroutine with a 1-second timeout, for the remainder of the X message and the <cksum>. 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 <nak>, 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 <nak> 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 <cksum> 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 <SOH><blk #><255-blk #><--128 data bytes--><CRC hi><CRC lo> X in which: X <SOH> = 01 hex X <blk #> = 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 <CRC hi> = byte containing the 8 hi order coefficients of the CRC. X <CRC lo> = 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 <C> in X place of the initial <nak>. If the sending program supports CRC X mode it will recognize the <C> and will set itself into CRC X mode, and respond by sending the first block as if a <nak> 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 <C> at all. After the receiver has sent the X <C> it will wait up to 3 seconds for the <soh> that starts the X first block. If it receives a <soh> 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 <soh> is received within 3 X seconds the receiver will switch to checksum mode, send a <nak>, X and proceed in checksum mode. If the receiver wishes to use X checksum mode it should send an initial <nak> and the sending program X should respond to the <nak> as defined in the original Modem Protocol. X After the mode has been set by the initial <C> or <nak> 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 <C> can be garbled or lost. X X 2. the initial <soh> can be garbled. X X 3. the initial <C> can be changed to a <nak>. X X 4. the initial <nak> from a receiver which wants to receive X in checksum can be changed to a <C>. X X The first problem can be solved if the receiver sends a second <C> 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 <nak> and X switching to checksum mode or a sending program without CRC support may X time out and abort. Repeating the <C> will also fix the second problem if X the sending program cooperates by responding as if a <nak> were received X instead of ignoring the extra <C>. 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 <nak>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 <C> is X received before the first <nak> or <ack> the sending program should set X itself into CRC mode and respond as if a <nak> were received. The sender X should respond to additional <C>s as if they were <nak>s until the first X <ack> is received. This will assist the receiving program in determining X the correct mode when the <soh> is lost or garbled. After the first <ack> X is received the sending program should ignore <C>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. <xx> X represents the checksum byte. X X Figure 11. Data Flow: Receiver has CRC Option, Sender Doesn't X X SENDER RECEIVER X <--- <C> X times out after 3 seconds, X <--- <C> X times out after 3 seconds, X <--- <C> X times out after 3 seconds, X <--- <C> X times out after 3 seconds, X <--- <nak> X <soh> 01 FE -data- <xx> ---> X <--- <ack> X <soh> 02 FD -data- <xx> ---> (data gets line hit) X <--- <nak> X <soh> 02 FD -data- <xx> ---> X <--- <ack> X <soh> 03 FC -data- <xx> ---> X (ack gets garbaged) <--- <ack> X times out after 10 seconds, X <--- <nak> X <soh> 03 FC -data- <xx> ---> X <--- <ack> X <eot> ---> X <--- <ack> 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 <xxxx> 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 <--- <C> X <soh> 01 FE -data- <xxxx> ---> X <--- <ack> X <soh> 02 FD -data- <xxxx> ---> (data gets line hit) X <--- <nak> X <soh> 02 FD -data- <xxxx> ---> X <--- <ack> X <soh> 03 FC -data- <xxxx> ---> X (ack gets garbaged) <--- <ack> X times out after 10 seconds, X <--- <nak> X <soh> 03 FC -data- <xxxx> ---> X <--- <ack> X <eot> ---> X <--- <ack> 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