[comp.sources.atari.st] v01i047: zmdm -- terminal program with file transfer part07/08

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