home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / uucp / uucico / protz.c < prev    next >
C/C++ Source or Header  |  1995-08-20  |  68KB  |  2,627 lines

  1. /* protz.c        Version 1.5, 92Apr24 */
  2. /* Modified by Ian Lance Taylor for Taylor UUCP 1.04 92Aug4.  */
  3.  
  4. /*
  5.  * Doug Evans, dje@sspiff.UUCP or dje@ersys.edmonton.ab.ca
  6.  *
  7.  * This file provides the Zmodem protocol (by Chuck Forsberg) for
  8.  * Ian Taylor's UUCP package.
  9.  *
  10.  * It was originally developed to establish a uucp link between myself and my
  11.  * employer: Ivation Datasystems, Inc. of Ottawa. 
  12.  *
  13.  * My thanks to Ivation for letting me release this to the public. Given that
  14.  * Zmodem is in the public domain, no additional copyrights have been added.
  15.  *
  16.  *****************************************************************************
  17.  *
  18.  * It's been difficult fitting Zmodem into the UUCP world. I have been guided
  19.  * mostly by trying to plug it into Taylor UUCP. Where "the Zmodem way of doing
  20.  * things" conflicted with "the UUCP way of doing things", I have err'd on the
  21.  * side of UUCP. At the end of it all, I have achieved something that will plug
  22.  * into Taylor UUCP very easily, but some might argue that I have corrupted Z
  23.  * too much. At any rate, compatibility with sz/rz was sacrificed to achieve a
  24.  * clean UUCP protocol. Given that, I took the opportunity to start from
  25.  * scratch when defining protocol constants (EG: ZBIN).
  26.  *
  27.  * 1) I wasn't quite sure how to enhance Zmodem to handle send+receive in one
  28.  *    session, so I added a 'g' protocol like initialization sequence. This
  29.  *    also gets this stuff out of the way, in case we ever try to support
  30.  *    full-duplex.
  31.  *
  32.  *    Caller                Callee
  33.  *    ------                ------
  34.  *    ZINIT        -->    <-- ZINIT
  35.  *    ZDATA (ZCRCF)    -->    <-- ZDATA (ZCRCF)
  36.  *    ZACK        -->    <-- ZACK
  37.  *    ZINITEND    -->    <-- ZINITEND
  38.  *
  39.  *    ZINIT is a combination of ZRINIT and ZSINIT and is intended to exchange
  40.  *    simple protocol information (flags) and the protocol version number.
  41.  *    ZDATA is intended to include window size information as well as the
  42.  *    "Myattn" string (although at the moment it doesn't contain anything).
  43.  *    ZDATA may contain at most 1k bytes of data and is sent out as one ZCRCF
  44.  *    packet. Two ack's (ZACK + ZINITEND) are needed to ensure both sides have
  45.  *    received ZDATA.
  46.  *
  47.  * 2) I've hardcoded several protocol parameters, like 32 bit CRC's for data.
  48.  *    Others are not supported (we don't need them).
  49.  *
  50.  * 3) ZHEX headers use 32 bit CRC's.
  51.  *
  52.  * 4) Zmodem sends the ZFILE message "in one chunk". If there are errors, the
  53.  *    entire string is resent. I have continued this practice. All UUCP
  54.  *    commands are sent "in one chunk". This can be changed down the road if
  55.  *    necessary.
  56.  *
  57.  * 5) The ZEOF message has been replaced with a new ZCRCx value: ZCRCF. ZCRCF
  58.  *    is identical to ZCRCW except that it indicates the end of the message.
  59.  *    The protocol here is *not* a file transfer protocol. It is an end to end
  60.  *    transport protocol (that preserves message boundaries).
  61.  *
  62.  * 6) Zmodem handles restarting a file transfer, but as best as I can tell UUCP
  63.  *    does not. At least Taylor UUCP doesn't. And if UUCP does start handling
  64.  *    file restart, can it be plugged into the existing Zmodem way with zero
  65.  *    changes? Beats me. Therefore I have removed this part of the code. One
  66.  *    can always put it back in if and when UUCP handles it. Ditto for other
  67.  *    pieces of removed code: there's no point in overly complicating this code
  68.  *    when supporting all the bells and whistles requires enhancements to UUCP
  69.  *    itself.
  70.  *
  71.  *    *** It is easier to put code back in in an upward compatible manner ***
  72.  *    *** than it is to correct for misunderstood code or poorly merged   ***
  73.  *    *** (Zmodem vs UUCP) code.                                          ***
  74.  *
  75.  * 7) For the character in the initial "protocol selection" sequence, I have
  76.  *    chosen 'a'. I'm told 'z' is already in use for something that isn't
  77.  *    Zmodem. It's entirely reasonable to believe that if Zmodem ever becomes a
  78.  *    standard UUCP protocol, this won't be it (so I'll leave z/Z for them).
  79.  *    Publicly, this is the 'a' protocol. Internally, it is refered to as 'z'.
  80.  *    A little confusing, I know. Maybe in time I'll refer to it internally as
  81.  *    'a', or maybe in time this will be *the* 'z' protocol.
  82.  *
  83.  * 8) Since we are writing a transport protocol, which isn't supposed to know
  84.  *    anything about what is being transfered or where it is coming from, the
  85.  *    header data value has changed meaning. It no longer means "file position"
  86.  *    but instead means "window position". It is a running counter of the bytes
  87.  *    transfered. Each "message" begins on a 1k boundary so the count isn't a
  88.  *    precise byte count. The counter wraps every 4 gigabytes, although this
  89.  *    wrapping isn't supported yet.
  90.  *
  91.  *    FIXME: At present the max data transfered per session is 4 gigabytes.
  92.  *
  93.  ****************************************************************************
  94.  *
  95.  * A typical message sequence is (master sending file to slave):
  96.  *
  97.  *      Master                          Slave
  98.  *      ------                          -----
  99.  *    ZDATA (S, ZCRCF)    -->
  100.  *                <--    ZACK
  101.  *                <--    ZDATA (SY, ZCRCF)
  102.  *    ZACK            -->
  103.  *    ZDATA            -->
  104.  *                        ...    <--    ZACK/ZRPOS
  105.  *    ZDATA (ZCRCF)        -->
  106.  *                <--    ZACK
  107.  *                <--    ZDATA (CY, ZCRCF)
  108.  *    ZACK            -->
  109.  *
  110.  * A typical message sequence is (master receiving file from slave):
  111.  *
  112.  *    Master                Slave
  113.  *    ------                -----
  114.  *    ZDATA (R, ZCRCF)    -->
  115.  *                <--    ZACK
  116.  *                <--    ZDATA (RY, ZCRCF)
  117.  *    ZACK            -->
  118.  *                <--    ZDATA
  119.  *    ZACK/ZRPOS    ...    -->
  120.  *                <--    ZDATA (ZCRCF)
  121.  *    ZACK            -->
  122.  *    ZDATA (CY, ZCRCF)    -->
  123.  *                <--    ZACK
  124.  *
  125.  *****************************************************************************
  126.  *
  127.  * Notes:
  128.  * 1) For future bidirectional concerns, keep packet types "unidirectional".
  129.  *    Sender always uses:    ZDATA, ZNAK
  130.  *    Receiver always uses:    ZRPOS, ZACK
  131.  *    There is no intersection.
  132.  *
  133.  *    I'm not sure if this is necessary or even useful, but it seems to be.
  134.  *
  135.  * 2) I use to store the byte count / 32 in the data header. This left 5 bits
  136.  *    unused for future concerns. I removed this because of the following
  137.  *    situation when sending a file:
  138.  *
  139.  *    ZDATA (ZCRCG, xx bytes) - received ok
  140.  *    ZDATA (ZCRCF, 0 bytes)  - corrupted
  141.  *
  142.  *    At this point the receiver would like to send back a ZRPOS with a value 
  143.  *    of the size of the file. However, it can't because the value is divided
  144.  *    by 32, and it would have to round up to the next multiple of 32. This
  145.  *    seemed a little ugly, so I went with using the entire header to store
  146.  *    the byte count.
  147.  *
  148.  *****************************************************************************
  149.  *
  150.  * Source version:
  151.  * 
  152.  * 1.1,2,3
  153.  *    Protocol version 0
  154.  *    Early attempts, completely rewritten later.
  155.  *
  156.  * 1.4    Protocol version 1
  157.  *    Beta test sent to Ian for analysis 92Apr18.
  158.  *
  159.  * 1.5    Protocol version 1
  160.  *    Released 92Apr24.
  161.  *
  162.  *****************************************************************************
  163.  *
  164.  * Protocol version:
  165.  *
  166.  * A version number is exchanged in the ZINIT message, so it is possible to
  167.  * correct or enhance the protocol, without breaking existing versions.
  168.  * The purpose of this section is to document these versions as they come out.
  169.  * Remember, this is the protocol version, not the source version.
  170.  *
  171.  * 0    Initial version.
  172.  *    Zmodem controlled file transfer. This was more of a "plug Z
  173.  *    into UUCP as is" port.
  174.  *
  175.  * 1    Complete rewrite.
  176.  *    Made Z more of a transport protocol. UUCP now controls transfer and Z
  177.  *    is on the same footing as the other UUCP protocols.
  178.  *    Theoretically, there will be little pain when UUCP goes bidirectional.
  179.  */
  180.  
  181. #include "uucp.h"
  182.  
  183. #if USE_RCS_ID
  184. const char protz_rcsid[] = "$Id: protz.c,v 1.8 1993/12/20 00:44:49 ian Rel $";
  185. #endif
  186.  
  187. #include <errno.h>
  188.  
  189. #include "uudefs.h"
  190. #include "uuconf.h"
  191. #include "conn.h"
  192. #include "trans.h"
  193. #include "system.h"
  194. #include "prot.h"
  195.  
  196. #define ZPROTOCOL_VERSION    1
  197.  
  198. /*
  199.  * Control message characters ...
  200.  */
  201.  
  202. #define ZPAD    '*'    /* Padding character begins frames */
  203. #define ZDLE    030    /* Ctrl-X Zmodem escape - `ala BISYNC DLE */
  204. #define ZBIN    'A'    /* Binary frame indicator */
  205. #define ZHEX    'B'    /* HEX frame indicator */
  206.  
  207. /*
  208.  * Frame types (see array "frametypes" in zm.c) ...
  209.  *
  210.  * Note that the numbers here have been reorganized, as we don't support
  211.  * all of them (nor do we need to).
  212.  *
  213.  * WARNING: The init sequence assumes ZINIT < ZDATA < ZACK < ZINITEND.
  214.  */
  215.  
  216. #define ZINIT        0    /* Init (contains protocol version, flags) */
  217. #define ZDATA        1    /* Data packet(s) follow */
  218. #define ZRPOS        2    /* Resume data trans at this position */
  219. #define ZACK        3    /* ACK to above */
  220. #define ZNAK        4    /* Last packet was garbled */
  221. #define Zreserved    5    /* reserved (for future concerns) */
  222. #define ZINITEND    6    /* end of init sequence */
  223. #define ZFIN        7    /* Finish session */
  224.  
  225. /*
  226.  * ZDLE sequences ...
  227.  *
  228.  * Note addition of ZCRCF: "end of message".
  229.  */
  230.  
  231. #define ZCRCE 'h'    /* CRC next, frame ends, header packet follows */
  232. #define ZCRCG 'i'    /* CRC next, frame continues nonstop */
  233. #define ZCRCQ 'j'    /* CRC next, frame continues, ZACK expected */
  234. #define ZCRCW 'k'    /* CRC next, ZACK expected, end of frame */
  235. #define ZCRCF 'l'    /* CRC next, ZACK expected, end of message */
  236.  
  237. #define ZRUB0 'm'    /* Translate to rubout 0177 */
  238. #define ZRUB1 'n'    /* Translate to rubout 0377 */
  239.  
  240.  
  241. /*
  242.  * zdlread return values (internal) ...
  243.  * Other values are ZM_ERROR, ZM_TIMEOUT, ZM_RCDO.
  244.  */
  245.  
  246. #define GOTOR    0400
  247. #define GOTCRCE (ZCRCE | GOTOR)    /* ZDLE-ZCRCE received */
  248. #define GOTCRCG (ZCRCG | GOTOR)    /* ZDLE-ZCRCG received */
  249. #define GOTCRCQ (ZCRCQ | GOTOR)    /* ZDLE-ZCRCQ received */
  250. #define GOTCRCW (ZCRCW | GOTOR)    /* ZDLE-ZCRCW received */
  251. #define GOTCRCF (ZCRCF | GOTOR)    /* ZDLE-ZCRCF received */
  252.  
  253. /*
  254.  * Byte positions within header array ...
  255.  */
  256.  
  257. #define ZF0    3    /* First flags byte */
  258. #define ZF1    2
  259. #define ZF2    1
  260. #define ZF3    0
  261.  
  262. #define ZP0    0    /* Low order 8 bits of position */
  263. #define ZP1    1
  264. #define ZP2    2
  265. #define ZP3    3    /* High order 8 bits of position */
  266.  
  267. /*
  268.  * Bit Masks for ZRQINIT flags byte ZF0 ...
  269.  */
  270.  
  271. #define TX_ESCCTL    1    /* Tx will escape control chars */
  272.  
  273. /*
  274.  * Possible errors when running ZMODEM ...
  275.  */
  276.  
  277. #define    ZM_ERROR    (-1)    /* crc error, etc. */
  278. #define ZM_TIMEOUT    (-2)
  279. #define ZM_RCDO        (-3)    /* Carrier Lost */
  280.  
  281. /*
  282.  * ASCII characters ...
  283.  */
  284.  
  285. #define LF        012
  286. #define CR        015
  287. #define XON        021
  288. #define XOFF        023
  289.  
  290. #define XON_WAIT    10    /* seconds */
  291.  
  292. /*
  293.  * Packet sizes ...
  294.  *
  295.  * FIXME: CPACKETSIZE is hardcoded in a lot of places.
  296.  *    It's not clear to me whether changing it's value would be a
  297.  *    "good thing" or not. But of course that doesn't excuse the hardcoding.
  298.  */
  299.  
  300. #define CPACKETSIZE        1024    /* max packet size (data only) */
  301. #define CFRAMELEN        12    /* header size */
  302. #define CSUFFIXLEN        10    /* suffix at end of data packets */
  303. #define CEXCHANGE_INIT_RETRIES    4
  304.  
  305. /* The header CRC value.  */
  306.  
  307. #if ANSI_C
  308. #define IHDRCRC 0xDEBB20E3UL
  309. #else
  310. #define IHDRCRC ((unsigned long) 0xDEBB20E3L)
  311. #endif
  312.  
  313. /* packet buffer size */
  314. #define CPACKBUFSIZE  (CFRAMELEN + 2 * CPACKETSIZE + CSUFFIXLEN + 42 /*slop*/)
  315.  
  316. /*
  317.  * Data types ...
  318.  */
  319.  
  320. typedef unsigned char achdrval_t[4];
  321. typedef unsigned long hdrval_t;
  322. typedef unsigned long winpos_t;
  323.  
  324. /*
  325.  * Configurable parms ...
  326.  *
  327.  * FIXME: <cZrx_buf_len> isn't used yet. It may not be needed.
  328.  */
  329.  
  330. #define CTIMEOUT        10
  331. #define CRETRIES        10
  332. #define CSTARTUP_RETRIES    4
  333. #define CGARBAGE        2400
  334. #define CSEND_WINDOW        16384
  335. #define FESCAPE_CONTROL        FALSE
  336.  
  337. static int cZtimeout = CTIMEOUT;    /* (seconds) */
  338. static int cZretries = CRETRIES;
  339. static int cZstartup_retries = CSTARTUP_RETRIES;
  340. static int cZmax_garbage = CGARBAGE;        /* max garbage before header */
  341. static int cZtx_window = CSEND_WINDOW;        /* our transmission window */
  342. static int cZrx_buf_len = 0;            /* our reception buffer size */
  343. static boolean fZesc_ctl = FESCAPE_CONTROL;    /* escape control chars */
  344.  
  345. struct uuconf_cmdtab asZproto_params[] =
  346. {
  347.     {"timeout", UUCONF_CMDTABTYPE_INT, (pointer) & cZtimeout, NULL},
  348.     {"retries", UUCONF_CMDTABTYPE_INT, (pointer) & cZretries, NULL},
  349.     {"startup-retries", UUCONF_CMDTABTYPE_INT,
  350.        (pointer) & cZstartup_retries, NULL},
  351.     {"garbage", UUCONF_CMDTABTYPE_INT, (pointer) & cZmax_garbage, NULL},
  352.     {"send-window", UUCONF_CMDTABTYPE_INT, (pointer) & cZtx_window, NULL},
  353.     {"escape-control", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) & fZesc_ctl,
  354.        NULL},
  355.     {NULL, 0, NULL, NULL}
  356. };
  357.  
  358. /*
  359.  * Variables for statistic gathering ...
  360.  *
  361.  * We use <wpZtxpos, wpZrxbytes> to record the number of "packets"
  362.  * sent/received. Packets is in double quotes because some of them aren't full.
  363.  */
  364.  
  365. static unsigned long cZheaders_sent;
  366. static unsigned long cZheaders_received;
  367. static unsigned long cZbytes_resent;
  368. static unsigned long cZtimeouts;
  369. static unsigned long cZerrors;
  370.  
  371. /*
  372.  * Data buffers ...
  373.  */
  374.  
  375. static char *zZtx_buf;        /* transmit buffer */
  376.  
  377. static char *zZtx_packet_buf;    /* raw outgoing packet data */
  378. static char *zZrx_packet_buf;    /* raw incoming packet data */
  379.  
  380. /*
  381.  * Transmitter state variables ...
  382.  */
  383.  
  384. static unsigned cZblklen;    /* data length in sent/received packets */
  385. static unsigned cZtxwspac;    /* spacing between ZCRCQ requests */
  386. /*static unsigned cZblklen_override;*//* override value for <cZblklen> */
  387. static unsigned cZtxwcnt;    /* counter used to space ack requests */
  388. static unsigned cZrxwcnt;    /* counter used to watch receiver's buf size */
  389. static winpos_t wpZtxstart;    /* <wpZtxpos> when message started */
  390. static winpos_t wpZtxpos;    /* transmitter position */
  391. static winpos_t wpZlastsync;    /* last offset to which we got a ZRPOS */
  392. static winpos_t wpZlrxpos;    /* receiver's last reported offset */
  393. static winpos_t wpZrxpos;    /* receiver file position */
  394.  
  395. static int iZlast_tx_data_packet; /* type of last ZDATA packet (ZCRCx) */
  396. static int iZjunk_count;    /* amount of garbage characters received */
  397. static int iZtleft;        /* for dynamic packet resizing */
  398.  
  399. static int iZbeenhereb4;    /* times we've been ZRPOS'd to same place */
  400.  
  401. /*
  402.  * Receiver state variables ...
  403.  */
  404.  
  405. static winpos_t wpZrxbytes;    /* receiver byte count */
  406. static int iZlast_rx_data_packet; /* last successfully received ZCRCx packet */
  407.  
  408. /*
  409.  * Misc. globals ...
  410.  */
  411.  
  412. static char xon = XON;
  413.  
  414. #ifdef DJE_TESTING
  415. int uucptest = -1;
  416. int uucptest2;
  417. int uucptestseed;
  418. #endif
  419.  
  420. /*
  421.  * Kludge!!!
  422.  * See fzfinish_tx(). Basically the next two globals are used to record the
  423.  * fact that we got a ZDATA, but aren't quite ready to process it.
  424.  */
  425.  
  426. static int iZpkt_rcvd_kludge;            /* -1 if not valid */
  427. static hdrval_t hvZpkt_hdrval_kludge;
  428.  
  429. /*
  430.  * Packet types ...
  431.  */
  432.  
  433. static const char *azZframe_types[] = {
  434.     "Carrier Lost",        /* -3 */
  435.     "Timeout",        /* -2 */
  436.     "Error",        /* -1 */
  437. #define FTOFFSET 3
  438.     "ZINIT",
  439.     "ZDATA",
  440.     "ZRPOS",
  441.     "ZACK",
  442.     "ZNAK",
  443.     "Zreserved",
  444.     "ZINITEND",
  445.     "ZFIN",
  446.     "UNKNOWN!!!"
  447. };
  448. #define FTNUMBER    (sizeof(azZframe_types) / sizeof(char *))
  449.  
  450. #ifndef min
  451. #define min(a, b)    ((a) < (b) ? (a) : (b))
  452. #endif
  453. #define ZZHEADER_NAME(itype) \
  454.         azZframe_types[min((itype) + FTOFFSET, FTNUMBER - 1)]
  455.  
  456. /*
  457.  * Local functions ...
  458.  */
  459.  
  460. static boolean fzsend_data P((struct sdaemon *qdaemon, char *zdata,
  461.                   size_t cdata, boolean fendofmessage));
  462. static boolean fzprocess P((struct sdaemon *qdaemon));
  463. static boolean fzstart_proto P((struct sdaemon *qdaemon));
  464. static int izexchange_init P((struct sdaemon *qdaemon, int send_type,
  465.                   achdrval_t send_val, achdrval_t recv_val));
  466. static boolean fzshutdown_proto P((struct sdaemon *qdaemon));
  467. static boolean fzstart_tx P((void));
  468. static boolean fzfinish_tx P((struct sdaemon *qdaemon, long *plredo));
  469. static boolean fzstart_rx P((void));
  470. static boolean fzfinish_rx P((struct sdaemon *qdaemon));
  471. static boolean fzsend_hdr P((struct sdaemon *qdaemon, int ipkttype,
  472.                  int ihdrtype, hdrval_t hdrval,
  473.                  boolean fcheckreceive));
  474. static boolean fzsend_data_packet P((struct sdaemon *qdaemon, char *zdata,
  475.                      size_t cdata, int frameend,
  476.                      boolean fcheckreceive));
  477. static int czbuild_header P((char *zresult, int ipkttype, int ihdrtype,
  478.                  hdrval_t hdrval));
  479. static int czbuild_data_packet P((char *zresult, const char *zdata,
  480.                   size_t cdata, int frameend));
  481. /*
  482.  * The rest of the functions do not follow Ian's naming style. I have left
  483.  * the names the same as the original zm source. Over time, they may change.
  484.  */
  485. static int izrecv_hdr P((struct sdaemon *qdaemon, achdrval_t hdr));
  486. static int zrbhdr32 P((struct sdaemon *qdaemon, achdrval_t hdr));
  487. static int zrhhdr P((struct sdaemon *qdaemon, achdrval_t hdr));
  488. static int zrdat32 P((struct sdaemon *qdaemon, char *buf, int length,
  489.               int *iprxcount));
  490. static int getinsync P((struct sdaemon *qdaemon, boolean flag));
  491. static char *zputhex P((char *p, int ch));
  492. static char *zputchar P((char *p, int ch));
  493. static int zgethex P((struct sdaemon *qdaemon));
  494. static int zdlread P((struct sdaemon *qdaemon));
  495. static int noxrd7 P((struct sdaemon *qdaemon));
  496. static int realreadchar P((struct sdaemon *qdaemon, int timeout));
  497. static boolean fzreceive_ready P((void));
  498. static void stohdr P((hdrval_t pos, achdrval_t hdr));
  499. static hdrval_t rclhdr P((achdrval_t hdr));
  500. static hdrval_t hvzencode_data_hdr P((winpos_t cbytes));
  501. static void zdecode_data_hdr P((hdrval_t hdrval, winpos_t *pcbytes));
  502. static winpos_t lzupdate_rxpos P((achdrval_t rx_hdr, winpos_t rxpos,
  503.                   winpos_t lrxpos, winpos_t txpos));
  504.  
  505. /*
  506.  * This macro replaces readchar() because it achieves a noticable speed up. The
  507.  * readchar() function has been renamed realreadchar(). Thanks to Ian for
  508.  * running this stuff through a profiler to find this out. Ian suggests further
  509.  * speed ups may be obtained by doing a similar thing in zrdat32().
  510.  */
  511.  
  512. /* Assign the next character to b. */
  513. #define READCHAR(qdaemon, b, i) \
  514.   (iPrecstart != iPrecend \
  515.    ? ((b) = BUCHAR (abPrecbuf[iPrecstart]), \
  516.       iPrecstart = (iPrecstart + 1) % CRECBUFLEN) \
  517.    : ((b) = realreadchar ((qdaemon), (i))))
  518.  
  519. /************************************************************************/
  520.  
  521.  
  522. /*
  523.  * Start the protocol ...
  524.  */
  525.  
  526. boolean
  527. fzstart(qdaemon, pzlog)
  528. struct sdaemon *qdaemon;
  529. char **pzlog;
  530. {
  531.     *pzlog = zbufalc (sizeof "protocol 'a' starting: , , , , , " + 100);
  532.     sprintf (*pzlog, "protocol 'a' starting: %d, %d, %d, %d, %d, %d",
  533.         cZtimeout, cZretries, cZstartup_retries,
  534.         cZmax_garbage, cZtx_window, fZesc_ctl);
  535.  
  536.         if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
  537.              STRIPSETTING_EIGHTBITS, XONXOFF_OFF))
  538.             return FALSE;
  539.  
  540.     /*
  541.      * For now, we place tight restrictions on the size of the transmit
  542.      * window. This might be relaxed in the future. If it is relaxed,
  543.      * some of these tests will stay, some will go. That is why it is
  544.      * coded like it is.
  545.      */
  546.  
  547.     if (cZtx_window % 1024 != 0 ||
  548.         cZtx_window < 4096 || cZtx_window > 65536 ||
  549.         65536 % cZtx_window != 0
  550.     ) {
  551.         ulog (LOG_ERROR,
  552.        "fzstart: cZtx_window not one of 4096, 8192, 16384, 32768, 65536");
  553.         return FALSE;
  554.     }
  555.  
  556.     zZtx_buf = (char *) xmalloc (CPACKETSIZE);
  557.     zZtx_packet_buf = (char *) xmalloc (CPACKBUFSIZE);
  558.     zZrx_packet_buf = (char *) xmalloc (CPACKBUFSIZE);
  559.  
  560.     iZlast_tx_data_packet = -1;
  561.     iZlast_rx_data_packet = -1;
  562.  
  563.     wpZtxpos = wpZlrxpos = wpZrxpos = wpZrxbytes = 0;
  564.     cZtxwspac = cZtx_window / 4;
  565.  
  566.     cZheaders_sent = cZheaders_received = cZbytes_resent = 0;
  567.     cZtimeouts = cZerrors = 0;
  568.  
  569.     iZpkt_rcvd_kludge = -1;
  570.  
  571. #if 0
  572.     /*
  573.      * We ensure <cZtx_window> is at least 4k, so the following is
  574.      * unnecessary. It can be put back in later if needed.
  575.      */
  576.     if (cZblklen_override > cZtxwspac
  577.         || (!cZblklen_override && cZtxwspac < 1024))
  578.         cZblklen_override = cZtxwspac;
  579. #endif
  580.  
  581. #ifdef DJE_TESTING
  582.     {
  583.         extern int uucptest,uucptest2,uucptestseed;
  584.         FILE *f;
  585.  
  586.         if (uucptest == -1) {
  587.             f = fopen ("/usr/local/src/bin/uucp/uucptest", "r");
  588.             if (f != NULL) {
  589.                 fscanf (f, "%d %d %d",
  590.                     &uucptestseed, &uucptest, &uucptest2);
  591.                 fclose (f);
  592.             }
  593.             srand (uucptestseed);
  594.         }
  595.     }
  596. #endif
  597.  
  598.     /*
  599.      * Fire up the protocol (exchange init messages) ...
  600.      */
  601.  
  602.     if (!fzstart_proto (qdaemon))
  603.         return FALSE;
  604.  
  605.     return TRUE;
  606. }
  607.  
  608. /*
  609.  * Stop the protocol ...
  610.  */
  611.  
  612. boolean
  613. fzshutdown(qdaemon)
  614. struct sdaemon *qdaemon;
  615. {
  616.     (void) fzshutdown_proto (qdaemon);
  617.  
  618.     xfree ((pointer) zZtx_buf);
  619.     xfree ((pointer) zZtx_packet_buf);
  620.     xfree ((pointer) zZrx_packet_buf);
  621.     zZtx_buf = NULL;
  622.     zZtx_packet_buf = NULL;
  623.     zZrx_packet_buf = NULL;
  624.  
  625.     /*
  626.      * Print some informative statistics ...
  627.      *
  628.      * I use the word "messages" here instead of "headers" because the
  629.      * latter is jargonese.
  630.      */
  631.  
  632.     ulog (LOG_NORMAL,
  633.           "Protocol 'a' messages: sent %lu, received %lu",
  634.           cZheaders_sent, cZheaders_received);
  635.     ulog (LOG_NORMAL,
  636.           "Protocol 'a' packets: sent %lu, received %lu",
  637.           wpZtxpos / 1024, wpZrxbytes / 1024);
  638.     if (cZbytes_resent != 0 || cZtimeouts != 0 || cZerrors != 0)
  639.         ulog (LOG_NORMAL,
  640.         "Protocol 'a' errors: bytes resent %lu, timeouts %lu, errors %lu",
  641.               cZbytes_resent, cZtimeouts, cZerrors);
  642.  
  643.     /*
  644.      * Reset all the parameters to their default values, so that the
  645.      * protocol parameters used for this connection do not affect the
  646.      * next one.
  647.      */
  648.  
  649.     cZtimeout = CTIMEOUT;
  650.     cZretries = CRETRIES;
  651.     cZstartup_retries = CSTARTUP_RETRIES;
  652.     cZmax_garbage = CGARBAGE;
  653.     cZtx_window = CSEND_WINDOW;
  654.     fZesc_ctl = FESCAPE_CONTROL;
  655.  
  656.     cZheaders_sent = cZheaders_received = cZbytes_resent = 0;
  657.     cZtimeouts = cZerrors = 0;
  658.  
  659.     return TRUE;
  660. }
  661.  
  662. /*
  663.  * Send a command string ...
  664.  * We send everything up to and including the null byte.
  665.  *
  666.  * We assume the command will fit in the outgoing data buffer.
  667.  * FIXME: A valid assumption?
  668.  */
  669.  
  670. /*ARGSUSED*/
  671. boolean
  672. fzsendcmd(qdaemon, z, ilocal, iremote)
  673. struct sdaemon *qdaemon;
  674. const char *z;
  675. int ilocal;
  676. int iremote;
  677. {
  678.     size_t n,clen;
  679.     long lredo;
  680.     char *zbuf;
  681.  
  682.     clen = strlen (z) + 1;
  683.  
  684.     DEBUG_MESSAGE1 (DEBUG_PROTO, "fzsendcmd: sending command %s", z);
  685.  
  686.     if (!fzstart_tx ())    /* must be called before zzgetspace() */
  687.         return FALSE;
  688.  
  689.     if ((zbuf = zzgetspace (qdaemon, &n)) == NULL)
  690.         return FALSE;
  691.  
  692. #if DEBUG > 0
  693.     if (clen > n)
  694.         ulog (LOG_FATAL, "fzsendcmd: clen > n");
  695. #endif
  696.  
  697.     strcpy (zbuf, z);
  698.  
  699.     /*
  700.      * Send it out ...
  701.      */
  702.  
  703.     do {
  704.         if (!fzsend_data (qdaemon, zbuf, clen, TRUE))
  705.             return FALSE;
  706.         if (!fzfinish_tx (qdaemon, &lredo))
  707.             return FALSE;
  708.     } while (lredo >= 0);
  709.  
  710.     return fzprocess (qdaemon);
  711. }
  712.  
  713. /*
  714.  * Allocate a packet to send out ...
  715.  *
  716.  * Note that 'z' has dynamic packet resizing and that <cZblklen> will range
  717.  * from 32 to 1024, in multiples of 2.
  718.  */
  719.  
  720. /*ARGSUSED*/
  721. char *
  722. zzgetspace(qdaemon, pclen)
  723. struct sdaemon *qdaemon;
  724. size_t *pclen;
  725. {
  726.     *pclen = cZblklen;
  727.     return zZtx_buf;
  728. }
  729.  
  730. /*
  731.  * Send a block of data ...
  732.  *
  733.  * If (cdata == 0) then the end of the file has been reached.
  734.  */
  735.  
  736. /*ARGSUSED*/
  737. boolean
  738. fzsenddata(qdaemon, zdata, cdata, ilocal, iremote, ipos)
  739. struct sdaemon *qdaemon;
  740. char *zdata;
  741. size_t cdata;
  742. int ilocal;
  743. int iremote;
  744. long ipos;
  745. {
  746.     DEBUG_MESSAGE1 (DEBUG_PROTO, "fzsenddata: %d bytes", cdata);
  747.  
  748.     if (! fzsend_data (qdaemon, zdata, cdata, cdata == 0))
  749.         return FALSE;
  750.     return fzprocess (qdaemon);
  751. }
  752.  
  753. /*
  754.  * Send a block of data (command or file) ...
  755.  */
  756.  
  757. /* This should buffer the data internally.  Until it does, it needs to
  758.    be able to reset the file position when it is called.  This is
  759.    really ugly.  */
  760. extern struct stransfer *qTsend;
  761.  
  762. static boolean
  763. fzsend_data(qdaemon, zdata, cdata, fendofmessage)
  764. struct sdaemon *qdaemon;
  765. char *zdata;
  766. size_t cdata;
  767. boolean fendofmessage;
  768. {
  769.     size_t n;
  770.  
  771.     if (iZlast_tx_data_packet == -1 || iZlast_tx_data_packet == ZCRCW) {
  772.         cZtxwcnt = cZrxwcnt = 0;
  773.         iZjunk_count = 0;
  774.         if (!fzsend_hdr (qdaemon, ZBIN, ZDATA,
  775.                  hvzencode_data_hdr (wpZtxpos), TRUE))
  776.             return FALSE;
  777.     }
  778.  
  779.     n = cdata;
  780.  
  781.     if (fendofmessage)
  782.         iZlast_tx_data_packet = ZCRCF;
  783.     else if (iZjunk_count > 3)
  784.         iZlast_tx_data_packet = ZCRCW;
  785.     else if (wpZtxpos == wpZlastsync)
  786.         iZlast_tx_data_packet = ZCRCW;
  787.     else if (cZrx_buf_len && (cZrxwcnt += n) >= cZrx_buf_len)
  788.         iZlast_tx_data_packet = ZCRCW;
  789.     else if ((cZtxwcnt += n) >= cZtxwspac) {
  790.         iZlast_tx_data_packet = ZCRCQ;
  791.         cZtxwcnt = 0;
  792.     } else
  793.         iZlast_tx_data_packet = ZCRCG;
  794.  
  795.     if (++iZtleft > 3) {
  796.         iZtleft = 0;
  797.         if (cZblklen < 1024)
  798.             cZblklen *= 2;
  799. #if 0    /* <cZblklen_override> is currently unnecessary */
  800.         if (cZblklen_override && cZblklen > cZblklen_override)
  801.             cZblklen = cZblklen_override;
  802. #endif
  803.         if (cZblklen > 1024)
  804.             cZblklen = 1024;
  805.         if (cZrx_buf_len && cZblklen > cZrx_buf_len)
  806.             cZblklen = cZrx_buf_len;
  807.     }
  808.  
  809. #if DEBUG > 1
  810.     if (FDEBUGGING(DEBUG_PROTO)) {
  811.         const char *type;
  812.  
  813.         switch (iZlast_tx_data_packet) {
  814.         case ZCRCW: type = "ZCRCW"; break;
  815.         case ZCRCG: type = "ZCRCG"; break;
  816.         case ZCRCQ: type = "ZCRCQ"; break;
  817.         case ZCRCE: type = "ZCRCE"; break;
  818.         case ZCRCF: type = "ZCRCF"; break;
  819.         default : type = "UNKNOWN!!!"; break;
  820.         }
  821.         DEBUG_MESSAGE3 (DEBUG_PROTO,
  822.                 "fzsend_data: %s, pos 0x%lx, %d bytes",
  823.                 type, wpZtxpos, n);
  824.     }
  825. #endif
  826.  
  827.     if (!fzsend_data_packet (qdaemon, zdata, n, iZlast_tx_data_packet,
  828.                  TRUE))
  829.         return FALSE;
  830.  
  831.     wpZtxpos += n;
  832.  
  833.     if (iZlast_tx_data_packet == ZCRCW) {
  834.         /*
  835.          * FIXME: Ideally this would be done in fzprocess. However, it
  836.          *    is only called if there is data pending which there
  837.          *    may not be yet. I could have patched fploop() a bit but
  838.          *    for now, I've done it like this.
  839.          */
  840.         switch (getinsync (qdaemon, FALSE)) {
  841.         case ZACK:
  842.             break;
  843.         case ZRPOS:
  844.             if (qTsend == NULL
  845.                 || ! ffileisopen (qTsend->e)) {
  846.                 ulog (LOG_ERROR, "Can't reset non-file");
  847.                 return FALSE;
  848.             }
  849.             iZlast_tx_data_packet = -1; /* trigger ZDATA */
  850.             DEBUG_MESSAGE1 (DEBUG_PROTO,
  851.                     "fzsend_data: Seeking to %ld",
  852.                     (long) (wpZrxpos - wpZtxstart));
  853.             if (!ffileseek (qTsend->e, wpZrxpos - wpZtxstart)) {
  854.                 ulog (LOG_ERROR, "seek: %s", strerror (errno));
  855.                 return FALSE;
  856.             }
  857.             break;
  858.         default:
  859.             return FALSE;
  860.         }
  861.         return TRUE;
  862.     }
  863.  
  864.     /*
  865.      * If we've reached the maximum transmit window size, let the
  866.      * receiver catch up ...
  867.      *
  868.      * I use (cZtx_window - 2048) to play it safe.
  869.      */
  870.  
  871.     while (wpZtxpos - wpZlrxpos >= cZtx_window - 2048) {
  872.         if (iZlast_tx_data_packet != ZCRCQ) {
  873.             if (!fzsend_data_packet (qdaemon, zdata, (size_t) 0,
  874.                          iZlast_tx_data_packet = ZCRCQ,
  875.                          TRUE))
  876.                 return FALSE;
  877.         }
  878.         /*
  879.          * FIXME: I'd rather not call ffileseek() in this file. When we
  880.          *    start buffering the outgoing data, the following
  881.          *    ffileseek() will disappear.
  882.          */
  883.         switch (getinsync (qdaemon, TRUE)) {
  884.         case ZACK:
  885.             break;
  886.         case ZRPOS:
  887.             if (qTsend == NULL
  888.                 || ! ffileisopen (qTsend->e)) {
  889.                 ulog (LOG_ERROR, "Can't reset non-file");
  890.                 return FALSE;
  891.             }
  892.             iZlast_tx_data_packet = -1; /* trigger ZDATA */
  893.             DEBUG_MESSAGE1 (DEBUG_PROTO,
  894.                     "fzsend_data: Seeking to %ld",
  895.                     (long) (wpZrxpos - wpZtxstart));
  896.             if (!ffileseek (qTsend->e, wpZrxpos - wpZtxstart)) {
  897.                 ulog (LOG_ERROR, "seek: %s", strerror (errno));
  898.                 return FALSE;
  899.             }
  900.             break;
  901.         default:
  902.             return FALSE;
  903.         }
  904.     }
  905.  
  906.     return TRUE;
  907. }
  908.  
  909. /*
  910.  * Process existing data ...
  911.  */
  912.  
  913. static boolean
  914. fzprocess(qdaemon)
  915. struct sdaemon *qdaemon;
  916. {
  917.     int c,ch;
  918.  
  919.     while (fzreceive_ready ()) {
  920.         READCHAR (qdaemon, ch, 1);
  921.         switch (ch) {
  922.         case ZPAD:
  923.             /* see if we're detecting ZRPOS packets quickly */
  924.             DEBUG_MESSAGE0 (DEBUG_PROTO,
  925.                     "fzprocess: possible ZRPOS packet");
  926.             /* We just ate the ZPAD char that getinsync
  927.                expects, so put it back.  */
  928.             iPrecstart = ((iPrecstart + CRECBUFLEN - 1)
  929.                       % CRECBUFLEN);
  930.             c = getinsync (qdaemon, TRUE);
  931.             if (c == ZACK)
  932.                 break;
  933.             /* FIXME: sz does a TCFLSH here */
  934. #if 0    /* FIXME: Not sure if this is needed, or where to put it. */
  935.             /* ZCRCE - dinna wanna starta ping-pong game */
  936.             if (!fzsend_data_packet (qdaemon, zZtx_packet_buf,
  937.                          0, ZCRCE, TRUE))
  938.                 return FALSE;
  939. #endif
  940.             if (c == ZRPOS) {
  941.                 if (qTsend == NULL
  942.                     || ! ffileisopen (qTsend->e)) {
  943.                     ulog (LOG_ERROR,
  944.                           "Attempt to back up non-file");
  945.                     return FALSE;
  946.                 }
  947.                 if (! ffileseek (qTsend->e,
  948.                          wpZrxpos - wpZtxstart)) {
  949.                     ulog (LOG_ERROR,
  950.                           "seek: %s", strerror (errno));
  951.                     return FALSE;
  952.                 }
  953.                 iZlast_tx_data_packet = -1; /* trigger ZDATA */
  954.                 break;    /* not returning is intentional */
  955.             }
  956.             return FALSE;
  957.         case XOFF:
  958.         case XOFF | 0200:
  959.             READCHAR (qdaemon, ch, XON_WAIT);
  960.             break;
  961.         case CR:
  962.             break;
  963.         default:
  964.             iZjunk_count++;
  965.             break;
  966.         }
  967.     }
  968.  
  969.     return TRUE;
  970. }
  971.  
  972. /*
  973.  * Wait for data to come in.
  974.  *
  975.  * This continues processing until a complete file or command has been
  976.  * received.
  977.  */
  978.  
  979. boolean
  980. fzwait(qdaemon)
  981. struct sdaemon *qdaemon;
  982. {
  983.     int c,cerr,rxcount;
  984.     boolean fexit;
  985.     achdrval_t rx_hdr;
  986.  
  987.     if (!fzstart_rx ())
  988.         return FALSE;
  989.  
  990.     cerr = cZretries;
  991.  
  992.     goto nxthdr;
  993.  
  994.     for (;;) {
  995.         if (!fzsend_hdr (qdaemon, ZHEX, ZRPOS,
  996.                  hvzencode_data_hdr (wpZrxbytes), FALSE))
  997.             return FALSE;
  998. nxthdr:
  999.         c = izrecv_hdr (qdaemon, rx_hdr);
  1000.  
  1001.         switch (c) {
  1002.         case ZM_TIMEOUT:
  1003.         case ZNAK:
  1004.             if (--cerr < 0) {
  1005.                 ulog (LOG_ERROR, "fzwait: retries exhausted");
  1006.                 return FALSE;
  1007.             }
  1008.             continue;
  1009.         case ZM_ERROR:
  1010.             if (--cerr < 0) {
  1011.                 ulog (LOG_ERROR, "fzwait: retries exhausted");
  1012.                 return FALSE;
  1013.             }
  1014.             /*fport_break ();*/
  1015.             continue;
  1016.         case ZM_RCDO:
  1017.         case ZFIN:
  1018.             return FALSE;
  1019.         case ZRPOS:
  1020.         case ZACK:
  1021.             goto nxthdr;    /* ignore, partner is out of sync */
  1022.         case ZDATA: {
  1023.             winpos_t rx_bytes;
  1024.  
  1025.             zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
  1026.             DEBUG_MESSAGE2 (DEBUG_PROTO,
  1027.                 "fzwait: bytes(us,them) 0x%lx,0x%lx",
  1028.                 wpZrxbytes, rx_bytes);
  1029.             if (rx_bytes != wpZrxbytes) {
  1030.                 if (--cerr < 0) {
  1031.                     ulog (LOG_ERROR,
  1032.                           "fzwait: retries exhausted");
  1033.                     return FALSE;
  1034.                 }
  1035.                 (void) zrdat32 (qdaemon, zZrx_packet_buf,
  1036.                         1024, &rxcount);
  1037.                 /*fport_break ();*/
  1038.                 /*
  1039.                  * FIXME: Seems to me we should ignore this one
  1040.                  *    and go for a timeout, the theory being
  1041.                  *    that the appropriate ZRPOS has already
  1042.                  *    been sent. We're obviously out of sync.
  1043.                  *    /dje 92Mar10
  1044.                  */
  1045.                 continue;    /* goto nxthdr? */
  1046.             }
  1047. moredata:
  1048.             /*
  1049.              * Do not call fgot_data() with (rxcount == 0) if it's
  1050.              * not ZCRCF. fgot_data() will erroneously think this
  1051.              * is the end of the message.
  1052.              */
  1053.             c = zrdat32 (qdaemon, zZrx_packet_buf, 1024,
  1054.                      &rxcount);
  1055. #if DEBUG > 1
  1056.             if (FDEBUGGING(DEBUG_PROTO)) {
  1057.                 const char *msg;
  1058.  
  1059.                 if (c < 0) {
  1060.                     msg = ZZHEADER_NAME(c);
  1061.                 } else {
  1062.                     switch (c) {
  1063.                     case GOTCRCW: msg = "ZCRCW"; break;
  1064.                     case GOTCRCG: msg = "ZCRCG"; break;
  1065.                     case GOTCRCQ: msg = "ZCRCQ"; break;
  1066.                     case GOTCRCE: msg = "ZCRCE"; break;
  1067.                     case GOTCRCF: msg = "ZCRCF"; break;
  1068.                     default : msg = NULL; break;
  1069.                     }
  1070.                 }
  1071.                 if (msg != NULL)
  1072.                     DEBUG_MESSAGE2 (DEBUG_PROTO,
  1073.                           "fzwait: zrdat32: %s, %d bytes",
  1074.                             msg, rxcount);
  1075.                 else
  1076.                     DEBUG_MESSAGE2 (DEBUG_PROTO,
  1077.                           "fzwait: zrdat32: %d, %d bytes",
  1078.                             c, rxcount);
  1079.             }
  1080. #endif
  1081.             switch (c) {
  1082.             case ZM_ERROR:    /* CRC error */
  1083.                 cZerrors++;
  1084.                 if (--cerr < 0) {
  1085.                     ulog (LOG_ERROR,
  1086.                           "fzwait: retries exhausted");
  1087.                     return FALSE;
  1088.                 }
  1089.                 /*fport_break ();*/
  1090.                 continue;
  1091.             case ZM_TIMEOUT:
  1092.                 cZtimeouts++;
  1093.                 if (--cerr < 0) {
  1094.                     ulog (LOG_ERROR,
  1095.                           "fzwait: retries exhausted");
  1096.                     return FALSE;
  1097.                 }
  1098.                 continue;
  1099.             case ZM_RCDO:
  1100.                 return FALSE;
  1101.             case GOTCRCW:
  1102.                 iZlast_rx_data_packet = ZCRCW;
  1103.                 cerr = cZretries;
  1104.                 if (rxcount != 0
  1105.                     && !fgot_data (qdaemon, zZrx_packet_buf,
  1106.                            (size_t) rxcount,
  1107.                            (const char *) NULL,
  1108.                            (size_t) 0,
  1109.                            -1, -1, (long) -1,
  1110.                            TRUE, &fexit))
  1111.                     return FALSE;
  1112.                 wpZrxbytes += rxcount;
  1113.                 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
  1114.                          hvzencode_data_hdr (wpZrxbytes),
  1115.                          FALSE))
  1116.                     return FALSE;
  1117.                 if (! fsend_data (qdaemon->qconn, &xon,
  1118.                           (size_t) 1, FALSE))
  1119.                   return FALSE;
  1120.                 goto nxthdr;
  1121.             case GOTCRCQ:
  1122.                 iZlast_rx_data_packet = ZCRCQ;
  1123.                 cerr = cZretries;
  1124.                 if (rxcount != 0
  1125.                     && !fgot_data (qdaemon, zZrx_packet_buf,
  1126.                            (size_t) rxcount,
  1127.                            (const char *) NULL,
  1128.                            (size_t) 0,
  1129.                            -1, -1, (long) -1,
  1130.                            TRUE, &fexit))
  1131.                     return FALSE;
  1132.                 wpZrxbytes += rxcount;
  1133.                 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
  1134.                          hvzencode_data_hdr (wpZrxbytes),
  1135.                          FALSE))
  1136.                     return FALSE;
  1137.                 goto moredata;
  1138.             case GOTCRCG:
  1139.                 iZlast_rx_data_packet = ZCRCG;
  1140.                 cerr = cZretries;
  1141.                 if (rxcount != 0
  1142.                     && !fgot_data (qdaemon, zZrx_packet_buf,
  1143.                            (size_t) rxcount,
  1144.                            (const char *) NULL,
  1145.                            (size_t) 0,
  1146.                            -1, -1, (long) -1,
  1147.                            TRUE, &fexit))
  1148.                     return FALSE;
  1149.                 wpZrxbytes += rxcount;
  1150.                 goto moredata;
  1151.             case GOTCRCE:
  1152.                 iZlast_rx_data_packet = ZCRCE;
  1153.                 cerr = cZretries;
  1154.                 if (rxcount != 0
  1155.                     && !fgot_data (qdaemon, zZrx_packet_buf,
  1156.                            (size_t) rxcount,
  1157.                            (const char *) NULL,
  1158.                            (size_t) 0,
  1159.                            -1, -1, (long) -1,
  1160.                            TRUE, &fexit))
  1161.                     return FALSE;
  1162.                 wpZrxbytes += rxcount;
  1163.                 goto nxthdr;
  1164.             case GOTCRCF:
  1165.                 iZlast_rx_data_packet = ZCRCF;
  1166.                 /*
  1167.                  * fzfinish_rx() must be called before
  1168.                  * fgot_data() because fgot_data() will send
  1169.                  * out a UUCP-command but the sender won't be
  1170.                  * ready for it until it receives our final
  1171.                  * ZACK.
  1172.                  */
  1173.                 cerr = cZretries;
  1174.                 wpZrxbytes += rxcount;
  1175.                 if (!fzfinish_rx (qdaemon))
  1176.                     return FALSE;
  1177.                 if (!fgot_data (qdaemon, zZrx_packet_buf,
  1178.                         (size_t) rxcount,
  1179.                         (const char *) NULL,
  1180.                         (size_t) 0, -1, -1,
  1181.                         (long) -1, TRUE, &fexit))
  1182.                     return FALSE;
  1183.                 /*
  1184.                  * FIXME: Examine <fexit>?
  1185.                  * Or maybe ensure it's TRUE?
  1186.                  */
  1187.                 return TRUE;
  1188.             }
  1189.             return FALSE;
  1190.         }
  1191.         default:
  1192.             ulog (LOG_FATAL, "fzwait: received header %s",
  1193.                 ZZHEADER_NAME(c));
  1194.             return FALSE;
  1195.         }
  1196.     }
  1197.  
  1198.     return TRUE;
  1199. }
  1200.  
  1201. /*
  1202.  * File level routine. Called when initiating/terminating file transfers.
  1203.  *
  1204.  * When starting to send a file:    (TRUE, TRUE, cbytes)
  1205.  * When starting to receive a file:    (TRUE, FALSE, -1)
  1206.  * When send EOF, check resend:        (FALSE, TRUE, -1)
  1207.  * When receive EOF, check re-receive:    (FALSE, FALSE, -1)
  1208.  */
  1209.  
  1210. boolean
  1211. fzfile(qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
  1212. struct sdaemon *qdaemon;
  1213. struct stransfer *qtrans;
  1214. boolean fstart;
  1215. boolean fsend;
  1216. long cbytes;
  1217. boolean *pfhandled;
  1218. {
  1219.     long iredo;
  1220.  
  1221.     *pfhandled = FALSE;
  1222.  
  1223.     DEBUG_MESSAGE2 (DEBUG_PROTO, "fzfile: fstart=%d, fsend=%d", fstart,
  1224.             fsend);
  1225.  
  1226.     if (fsend) {
  1227.         if (fstart)
  1228.             return fzstart_tx ();
  1229.         if (! fzfinish_tx (qdaemon, &iredo))
  1230.             return FALSE;
  1231.         if (iredo >= 0) {
  1232.             if (! ffileisopen (qtrans->e)) {
  1233.                 ulog (LOG_ERROR,
  1234.                       "Attempt to back up non-file");
  1235.                 return FALSE;
  1236.             }
  1237.             if (! ffileseek (qtrans->e, iredo)) {
  1238.                 ulog (LOG_ERROR,
  1239.                       "seek: %s", strerror (errno));
  1240.                 return FALSE;
  1241.             }
  1242.             *pfhandled = TRUE;
  1243.             qtrans->fsendfile = TRUE;
  1244.             return fqueue_send (qdaemon, qtrans);
  1245.         }
  1246.     }
  1247.  
  1248.     return TRUE;
  1249. }
  1250.  
  1251. /****************************************************************************/
  1252.  
  1253.  
  1254. #if 0    /* not used, we only use 32 bit crc's */
  1255. /*
  1256.  * crctab calculated by Mark G. Mendel, Network Systems Corporation
  1257.  */
  1258.  
  1259. static unsigned short crctab[256] = {
  1260.     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  1261.     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  1262.     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  1263.     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  1264.     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  1265.     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  1266.     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  1267.     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  1268.     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  1269.     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  1270.     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  1271.     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  1272.     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  1273.     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  1274.     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  1275.     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  1276.     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  1277.     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  1278.     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  1279.     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  1280.     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  1281.     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  1282.     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  1283.     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  1284.     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  1285.     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  1286.     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  1287.     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  1288.     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  1289.     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  1290.     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  1291.     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  1292. };
  1293. #endif    /* crctab */
  1294.  
  1295. /*
  1296.  * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
  1297.  * code or tables extracted from it, as desired without restriction.
  1298.  */
  1299.  
  1300. /* First, the polynomial itself and its table of feedback terms.  The  */
  1301. /* polynomial is                                                       */
  1302. /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
  1303. /* Note that we take it "backwards" and put the highest-order term in  */
  1304. /* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
  1305. /* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
  1306. /* the MSB being 1.                                                    */
  1307.  
  1308. /* Note that the usual hardware shift register implementation, which   */
  1309. /* is what we're using (we're merely optimizing it by doing eight-bit  */
  1310. /* chunks at a time) shifts bits into the lowest-order term.  In our   */
  1311. /* implementation, that means shifting towards the right.  Why do we   */
  1312. /* do it this way?  Because the calculated CRC must be transmitted in  */
  1313. /* order from highest-order term to lowest-order term.  UARTs transmit */
  1314. /* characters in order from LSB to MSB.  By storing the CRC this way,  */
  1315. /* we hand it to the UART in the order low-byte to high-byte; the UART */
  1316. /* sends each low-bit to hight-bit; and the result is transmission bit */
  1317. /* by bit from highest- to lowest-order term without requiring any bit */
  1318. /* shuffling on our part.  Reception works similarly.                  */
  1319.  
  1320. /* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
  1321. /*                                                                     */
  1322. /*     The table can be generated at runtime if desired; code to do so */
  1323. /*     is shown later.  It might not be obvious, but the feedback      */
  1324. /*     terms simply represent the results of eight shift/xor opera-    */
  1325. /*     tions for all combinations of data and CRC register values.     */
  1326. /*                                                                     */
  1327. /*     The values must be right-shifted by eight bits by the "updcrc"  */
  1328. /*     logic; the shift must be unsigned (bring in zeroes).  On some   */
  1329. /*     hardware you could probably optimize the shift in assembler by  */
  1330. /*     using byte-swap instructions.                                   */
  1331.  
  1332. static unsigned long crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  1333.     0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
  1334.     0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
  1335.     0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
  1336.     0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
  1337.     0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  1338.     0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
  1339.     0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
  1340.     0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
  1341.     0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
  1342.     0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  1343.     0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
  1344.     0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
  1345.     0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
  1346.     0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
  1347.     0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  1348.     0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
  1349.     0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
  1350.     0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
  1351.     0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
  1352.     0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  1353.     0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
  1354.     0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
  1355.     0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
  1356.     0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
  1357.     0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  1358.     0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
  1359.     0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
  1360.     0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
  1361.     0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
  1362.     0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  1363.     0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
  1364.     0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
  1365.     0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
  1366.     0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
  1367.     0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  1368.     0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
  1369.     0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
  1370.     0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
  1371.     0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
  1372.     0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  1373.     0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
  1374.     0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
  1375.     0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
  1376.     0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
  1377.     0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  1378.     0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
  1379.     0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
  1380.     0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
  1381.     0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
  1382.     0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  1383.     0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
  1384.     0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
  1385.     0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
  1386.     0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
  1387.     0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  1388.     0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
  1389.     0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
  1390.     0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
  1391.     0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
  1392.     0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  1393.     0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
  1394.     0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
  1395.     0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
  1396.     0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
  1397. };
  1398.  
  1399. /*
  1400.  * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
  1401.  *  NOTE: First argument must be in range 0 to 255.
  1402.  *        Second argument is referenced twice.
  1403.  * 
  1404.  * Programmers may incorporate any or all code into their programs, 
  1405.  * giving proper credit within the source. Publication of the 
  1406.  * source routines is permitted so long as proper credit is given 
  1407.  * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, 
  1408.  * Omen Technology.
  1409.  */
  1410.  
  1411. #define updcrc(cp, crc) (crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
  1412.  
  1413. #define UPDC32(b, crc) \
  1414.   (crc_32_tab[((unsigned)(crc) ^ (unsigned)(b)) & 0xff] \
  1415.    ^ (((crc) >> 8) & 0x00ffffffL))
  1416.  
  1417. /****************************************************************************/
  1418.  
  1419. /*
  1420.  * This section contains the guts of the Zmodem protocol. The intention
  1421.  * is to leave as much of it alone as possible at the start. Overtime it
  1422.  * will be cleaned up (EG: I'd like to clean up the naming of the globals).
  1423.  * Also, Zmodem has a different coding style. Over time this will be converted
  1424.  * to the Taylor UUCP coding style.
  1425.  */
  1426.  
  1427. /*
  1428.  * Start the protocol (exchange init packets) ...
  1429.  *
  1430.  * UUCP can transfer files in both directions in one session. Therefore the
  1431.  * init sequence is a little different.
  1432.  *
  1433.  * 1) ZINIT packets are exchanged
  1434.  *    - contains protocol version and protocol flags
  1435.  * 2) ZDATA packets are exchanged
  1436.  *    - is intended to contain various numeric and string information
  1437.  * 3) ZACK packets are exchanged
  1438.  * 4) ZINITEND packets are exchanged
  1439.  */
  1440.  
  1441. static boolean
  1442. fzstart_proto(qdaemon)
  1443. struct sdaemon *qdaemon;
  1444. {
  1445.     int i;
  1446.     achdrval_t tx_hdr,rx_hdr;
  1447.  
  1448.     for (i = 0; i < cZstartup_retries; i++) {
  1449.         stohdr (0L, tx_hdr);
  1450.         tx_hdr[ZF0] = ZPROTOCOL_VERSION;
  1451.         if (fZesc_ctl)
  1452.             tx_hdr[ZF1] |= TX_ESCCTL;
  1453.         switch (izexchange_init (qdaemon, ZINIT, tx_hdr, rx_hdr)) {
  1454.         case -1: return FALSE;
  1455.         case 0:  continue;
  1456.         case 1:  break;
  1457.         }
  1458. #if 0    /* can't work, but kept for documentation */
  1459.         if (rx_hdr[ZF0] == 0) {
  1460.             ulog (LOG_ERROR, "Old protocol version, init failed");
  1461.             return FALSE;
  1462.         }
  1463. #endif
  1464.         fZesc_ctl = fZesc_ctl || (rx_hdr[ZF1] & TX_ESCCTL) != 0;
  1465.  
  1466.         stohdr (0L, tx_hdr);
  1467.         switch (izexchange_init (qdaemon, ZDATA, tx_hdr, rx_hdr)) {
  1468.         case -1: return FALSE;
  1469.         case 0:  continue;
  1470.         case 1:  break;
  1471.         }
  1472.  
  1473.         stohdr (0L, tx_hdr);
  1474.         switch (izexchange_init (qdaemon, ZACK, tx_hdr, rx_hdr)) {
  1475.         case -1: return FALSE;
  1476.         case 0:  continue;
  1477.         case 1:  break;
  1478.         }
  1479.  
  1480.         stohdr (0L, tx_hdr);
  1481.         switch (izexchange_init (qdaemon, ZINITEND, tx_hdr, rx_hdr)) {
  1482.         case -1: return FALSE;
  1483.         case 0:  continue;
  1484.         case 1:  break;
  1485.         }
  1486.  
  1487.         DEBUG_MESSAGE0 (DEBUG_PROTO,
  1488.                 "fzstart_proto: Protocol started");
  1489.         return TRUE;
  1490.  
  1491.         /* FIXME: see protg.c regarding sequencing here. */
  1492.     }
  1493.  
  1494.     ulog (LOG_ERROR, "Protocol init failed");
  1495.     return FALSE;
  1496. }
  1497.  
  1498. /*
  1499.  * Exchange init messages. This is based on 'g'.
  1500.  * See the comments concerning fgexchange_init() in protg.c.
  1501.  *
  1502.  * We return 1 for success, 0 for restart, -1 for comm failure (terminate).
  1503.  */
  1504.  
  1505. static int
  1506. izexchange_init(qdaemon, send_type, send_val, recv_val)
  1507. struct sdaemon *qdaemon;
  1508. int send_type;
  1509. achdrval_t send_val;
  1510. achdrval_t recv_val;
  1511. {
  1512.     int i,recv_type,count;
  1513.  
  1514.     for (i = 0; i < CEXCHANGE_INIT_RETRIES; i++) {
  1515.         if (!fzsend_hdr (qdaemon, send_type == ZDATA ? ZBIN : ZHEX,
  1516.                  send_type, rclhdr (send_val), FALSE))
  1517.             return -1;
  1518.  
  1519.         /*
  1520.          * The ZDATA packet is intended to contain the <Attn> string
  1521.          * (eventually, if it's ever usable) and allow for anything
  1522.          * else that will need to be thrown in.
  1523.          */
  1524.  
  1525.         if (send_type == ZDATA) {
  1526.             count = czbuild_data_packet (zZtx_packet_buf, "",
  1527.                              (size_t) 1, ZCRCF);
  1528.             if (!fsend_data (qdaemon->qconn, zZtx_packet_buf,
  1529.                      (size_t) count, FALSE))
  1530.                 return -1;
  1531.         }
  1532.  
  1533.         recv_type = izrecv_hdr (qdaemon, recv_val);
  1534.  
  1535.         switch (recv_type) {
  1536.         case ZM_TIMEOUT:
  1537.         case ZM_ERROR:
  1538.             continue;
  1539.         case ZM_RCDO:
  1540.         case ZFIN:
  1541.             return -1;
  1542.         case ZINIT:
  1543.         case ZACK:
  1544.         case ZINITEND:
  1545.             break;
  1546.         case ZDATA:
  1547.             if (zrdat32 (qdaemon, zZrx_packet_buf, 1024, &count)
  1548.                 == GOTCRCF)
  1549.                 break;
  1550.             continue;
  1551.         default:
  1552.             continue;
  1553.         }
  1554.  
  1555.         if (recv_type == send_type)
  1556.             return 1;
  1557.  
  1558.         /*
  1559.          * If the other side is farther along than we are, we have lost
  1560.          * a packet.  Fall immediately back to ZINIT (but don't fail
  1561.          * if we are already doing ZINIT, since that would count
  1562.          * against cStart_retries more than it should).
  1563.          *
  1564.          * FIXME: The ">" test is "<" in protg.c. Check who's right.
  1565.          */
  1566.  
  1567.         if (recv_type > send_type && send_type != ZINIT)
  1568.             return 0;
  1569.  
  1570.         /*
  1571.          * If we are sending ZINITEND and we receive an ZINIT, the
  1572.          * other side has falled back (we know this because we have
  1573.          * seen a ZINIT from them).  Fall back ourselves to start
  1574.          * the whole handshake over again.
  1575.          */
  1576.  
  1577.         if (recv_type == ZINIT && send_type == ZINITEND)
  1578.             return 0;
  1579.     }
  1580.  
  1581.     return 0;
  1582. }
  1583.  
  1584. /*
  1585.  * Shut down the protocol ...
  1586.  */
  1587.  
  1588. static boolean
  1589. fzshutdown_proto(qdaemon)
  1590. struct sdaemon *qdaemon;
  1591. {
  1592.     (void) fzsend_hdr (qdaemon, ZHEX, ZFIN, 0L, FALSE);
  1593.     return TRUE;
  1594. }
  1595.  
  1596. /*
  1597.  * Reset the transmitter side for sending a new message ...
  1598.  */
  1599.  
  1600. static boolean
  1601. fzstart_tx()
  1602. {
  1603.     iZlast_tx_data_packet = -1;
  1604.  
  1605.     /*
  1606.      * <wpZlastsync> is set to -1L to suppress ZCRCW request otherwise
  1607.      * triggered by (wpZlastsync == wpZtxpos).
  1608.      */
  1609.  
  1610.     cZblklen = 1024;
  1611.     wpZlastsync = -1L;
  1612.     iZbeenhereb4 = 0;
  1613.     iZtleft = 0;
  1614.     iZjunk_count = 0;
  1615.  
  1616.     wpZtxpos = (wpZtxpos + 1024L) & ~1023L;    /* next packet boundary */
  1617.     wpZlrxpos = wpZrxpos = wpZtxpos;
  1618.  
  1619.     wpZtxstart = wpZtxpos;    /* so we can compute the "file offset" */
  1620.  
  1621.     return TRUE;
  1622. }
  1623.  
  1624. /*
  1625.  * Finish the sending of a message ...
  1626.  *
  1627.  * Basically, we wait for some indication that the receiver received our last
  1628.  * message. If the receiver tells us to restart from some point, we set
  1629.  * *plredo to that point.
  1630.  *
  1631.  * FIXME: This function is a major kludge at the moment. It is taken from
  1632.  *    getinsync(). It is necessary because I don't yet buffer outgoing data.
  1633.  *    It will go away when we do (buffer outgoing data).
  1634.  */
  1635.  
  1636. static boolean
  1637. fzfinish_tx(qdaemon, plredo)
  1638. struct sdaemon *qdaemon;
  1639. long *plredo;
  1640. {
  1641.     int c,cerr,ctimeouts;
  1642.     achdrval_t rx_hdr;
  1643.     winpos_t rx_bytes;
  1644.  
  1645.     *plredo = -1;
  1646.     cerr = cZretries;
  1647.     ctimeouts = 0;
  1648.  
  1649.     DEBUG_MESSAGE4 (DEBUG_PROTO,
  1650.       "fzfinish_tx: txpos=0x%lx, rxpos=0x%lx, lrxpos=0x%lx, rxbytes=0x%lx",
  1651.             wpZtxpos, wpZrxpos, wpZlrxpos, wpZrxbytes);
  1652.  
  1653.     for (;;) {
  1654.         c = izrecv_hdr (qdaemon, rx_hdr);
  1655.  
  1656.         switch (c) {
  1657.         case ZRPOS:
  1658.             wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
  1659.                            wpZlrxpos, wpZtxpos);
  1660.             /*
  1661.              * If the receiver sends a ZRPOS for the 1k block after
  1662.              * the one we're currently at, we lost the final ZACK.
  1663.              * We cheat and ignore this ZRPOS. Remember: the theory
  1664.              * is that this entire function will go away when we
  1665.              * begin buffering the outgoing data. Of course, one
  1666.              * can reword the protocol definition and say this
  1667.              * isn't cheating at all.
  1668.              */
  1669.             if (((wpZtxpos + 1024) & ~1023) == wpZrxpos)
  1670.                 return TRUE;
  1671.             cZbytes_resent += wpZtxpos - wpZrxpos;
  1672.             wpZlrxpos = wpZtxpos = wpZrxpos;
  1673.             if (wpZlastsync == wpZrxpos) {
  1674.                 if (++iZbeenhereb4 > 4)
  1675.                     if (cZblklen > 32)
  1676.                         cZblklen /= 2;
  1677.                 /* FIXME: shouldn't we reset iZbeenhereb4? */
  1678.             }
  1679.             wpZlastsync = wpZrxpos;
  1680.             iZlast_tx_data_packet = ZCRCW; /* force a timeout */
  1681.             *plredo = wpZrxpos - wpZtxstart;
  1682.             return TRUE;
  1683.         case ZACK:
  1684.             wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
  1685.                            wpZlrxpos, wpZtxpos);
  1686.             wpZlrxpos = wpZrxpos;
  1687.             if (wpZtxpos == wpZrxpos)  /* the ACK we want? */
  1688.                 return TRUE;
  1689.             break;
  1690.         case ZDATA:
  1691.             /*
  1692.              * We cheat here and take advantage of UUCP's current
  1693.              * half duplex nature. If we get a ZDATA starting on
  1694.              * the next 1k boundary, we lost the ZACK. We cheat and
  1695.              * tuck it away so that izrecv_hdr() can later detect
  1696.              * it. Remember: see above.
  1697.              */
  1698.             zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
  1699.             if (((wpZrxbytes + 1024L) & ~1023L) == rx_bytes) {
  1700.                 iZpkt_rcvd_kludge = ZDATA;
  1701.                 hvZpkt_hdrval_kludge = rclhdr (rx_hdr);
  1702.                 return TRUE;
  1703.             }
  1704.             break;    /* ignore, out of sync (old) */
  1705.         case ZNAK:
  1706.             /*
  1707.              * We cheat here and take advantage of UUCP's current
  1708.              * half duplex nature. If we get a ZNAK starting on
  1709.              * the next 1k boundary, we lost the ZACK. We cheat and
  1710.              * throw the ZNAK away. Remember: see above.
  1711.              *
  1712.              * On the other hand, if (rx_bytes == wpZrxbytes) then
  1713.              * the other side is also in fzfinish_tx(). He must
  1714.              * have lost our ZACK, so we send him another.
  1715.              */
  1716.             zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
  1717.             if (((wpZrxbytes + 1024L) & ~1023L) == rx_bytes)
  1718.                 return TRUE;
  1719.             if (rx_bytes == wpZrxbytes) {
  1720.                 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
  1721.                          hvzencode_data_hdr (wpZrxbytes),
  1722.                          TRUE))
  1723.                     return FALSE;
  1724.             }
  1725.             break;    /* ignore, out of sync (old) */
  1726.         case ZFIN:
  1727.         case ZM_RCDO:
  1728.             return FALSE;
  1729.         case ZM_TIMEOUT:
  1730.             if (--cerr < 0) {
  1731.                 ulog (LOG_ERROR,
  1732.                       "fzfinish_tx: retries exhausted");
  1733.                 return FALSE;
  1734.             }
  1735.             /*
  1736.              * Normally the sender doesn't send NAK's for timeouts.
  1737.              * We have to here because of the following scenario:
  1738.              *
  1739.              * - We send ZDATA/ZCRCF
  1740.              * - They send ZACK (corrupted)
  1741.              * - They send ZDATA/ZCRCF (corrupted)
  1742.              *
  1743.              * At this point, both sides are in fzfinish_tx().
  1744.              * We only send ZNAK every second timeout to increase
  1745.              * our timeout delay vs. our partner. This tries to
  1746.              * avoid ZRPOS and ZNAK "passing in transit".
  1747.              */
  1748.             if (++ctimeouts % 2 == 0)
  1749.                 if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
  1750.                          hvzencode_data_hdr (wpZtxpos),
  1751.                          TRUE))
  1752.                     return FALSE;
  1753.             break;
  1754.         case ZM_ERROR:
  1755.         default:
  1756.             if (--cerr < 0) {
  1757.                 ulog (LOG_ERROR,
  1758.                       "fzfinish_tx: retries exhausted");
  1759.                 return FALSE;
  1760.             }
  1761.             if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
  1762.                      hvzencode_data_hdr (wpZtxpos),
  1763.                      TRUE))
  1764.                 return FALSE;
  1765.             break;
  1766.         }
  1767.     }
  1768. }
  1769.  
  1770. /*
  1771.  * Initialize the receiver ...
  1772.  */
  1773.  
  1774. static boolean
  1775. fzstart_rx()
  1776. {
  1777.     wpZrxbytes = (wpZrxbytes + 1024L) & ~1023L; /* next packet boundary */
  1778.  
  1779.     return TRUE;
  1780. }
  1781.  
  1782. /*
  1783.  * Terminate the receiver ...
  1784.  *
  1785.  * Acknowledge the last packet received.
  1786.  */
  1787.  
  1788. static boolean
  1789. fzfinish_rx(qdaemon)
  1790. struct sdaemon *qdaemon;
  1791. {
  1792.     DEBUG_MESSAGE0 (DEBUG_PROTO, "fzfinish_rx: message/file received");
  1793.  
  1794.     return fzsend_hdr (qdaemon, ZHEX, ZACK,
  1795.                hvzencode_data_hdr (wpZrxbytes), FALSE);
  1796. }
  1797.  
  1798. /*
  1799.  * Send a Zmodem header to our partner ...
  1800.  */
  1801.  
  1802. static boolean
  1803. fzsend_hdr(qdaemon, ipkttype, ihdrtype, hdrval, fcheckreceive)
  1804. struct sdaemon *qdaemon;
  1805. int ipkttype;
  1806. int ihdrtype;
  1807. hdrval_t hdrval;
  1808. boolean fcheckreceive;
  1809. {
  1810.     int cpacketlen;
  1811.  
  1812.     DEBUG_MESSAGE2 (DEBUG_PROTO, "fzsend_hdr: %s, data = 0x%lx",
  1813.             ZZHEADER_NAME(ihdrtype), hdrval);
  1814.  
  1815.     cpacketlen = czbuild_header (zZtx_packet_buf, ipkttype,
  1816.                      ihdrtype, hdrval);
  1817.  
  1818. #ifdef DJE_TESTING
  1819. #if 0
  1820.     if (ihdrtype == ZACK && rand () % 100 < uucptest2) {
  1821.         cZheaders_sent++;
  1822.         return TRUE;
  1823.     }
  1824. #else
  1825.     if (ihdrtype == ZACK || ihdrtype == ZDATA) {
  1826.         boolean fresult;
  1827.         int old;
  1828.         extern int uucptest,uucptest2;
  1829.  
  1830.         old = uucptest;
  1831.         uucptest = uucptest2;
  1832.         cZheaders_sent++;
  1833.         fresult = fsend_data (qdaemon->qconn, zZtx_packet_buf,
  1834.                       (size_t) cpacketlen, fcheckreceive);
  1835.         uucptest = old;
  1836.         return fresult;
  1837.     }
  1838. #endif
  1839. #endif
  1840.     cZheaders_sent++;
  1841.     return fsend_data (qdaemon->qconn, zZtx_packet_buf,
  1842.                (size_t) cpacketlen, fcheckreceive);
  1843. }
  1844.  
  1845. /*
  1846.  * Send a data packet to our partner ...
  1847.  * <frameend> is one of ZCRCx.
  1848.  */
  1849.  
  1850. static boolean
  1851. fzsend_data_packet(qdaemon, zdata, cdata, frameend, fcheckreceive)
  1852. struct sdaemon *qdaemon;
  1853. char *zdata;
  1854. size_t cdata;
  1855. int frameend;
  1856. boolean fcheckreceive;
  1857. {
  1858.     int cpacketlen;
  1859.  
  1860.     cpacketlen = czbuild_data_packet (zZtx_packet_buf, zdata, cdata,
  1861.                       frameend);
  1862.  
  1863.     return fsend_data (qdaemon->qconn, zZtx_packet_buf,
  1864.                (size_t) cpacketlen, fcheckreceive);
  1865. }
  1866.  
  1867. /*
  1868.  * Build Zmodem headers ...
  1869.  *
  1870.  * Note that we use 32 bit CRC's for ZHEX headers.
  1871.  *
  1872.  * This function is a combination of zm fns: zsbhdr(), zsbh32(), and zshhdr().
  1873.  */
  1874.  
  1875. static int
  1876. czbuild_header(zresult, ipkttype, ihdrtype, hdrval)
  1877. char *zresult;
  1878. int ipkttype;
  1879. int ihdrtype;
  1880. hdrval_t hdrval;
  1881. {
  1882.     char *p;
  1883.     int i;
  1884.     unsigned long crc;
  1885.     achdrval_t achdrval;
  1886.  
  1887.     p = zresult;
  1888.  
  1889.     switch (ipkttype) {
  1890.     case ZBIN:
  1891.         *p++ = ZPAD;
  1892.         *p++ = ZDLE;
  1893.         *p++ = ZBIN;
  1894.         p = zputchar (p, ihdrtype);
  1895.         crc = ICRCINIT;
  1896.         crc = UPDC32 (ihdrtype, crc);
  1897.         stohdr (hdrval, achdrval);
  1898.         for (i = 0; i < 4; i++) {
  1899.             p = zputchar (p, achdrval[i]);
  1900.             crc = UPDC32 (achdrval[i], crc);
  1901.         }
  1902.         crc = ~crc;
  1903.         for (i = 0; i < 4; i++) {
  1904.             p = zputchar (p, (char) crc);
  1905.             crc >>= 8;
  1906.         }
  1907.         break;
  1908.     case ZHEX:     /* build hex header */
  1909.         *p++ = ZPAD;
  1910.         *p++ = ZPAD;
  1911.         *p++ = ZDLE;
  1912.         *p++ = ZHEX;
  1913.         p = zputhex (p, ihdrtype);
  1914.         crc = ICRCINIT;
  1915.         crc = UPDC32 (ihdrtype, crc);
  1916.         stohdr (hdrval, achdrval);
  1917.         for (i = 0; i < 4; i++) {
  1918.             p = zputhex (p, achdrval[i]);
  1919.             crc = UPDC32 (achdrval[i], crc);
  1920.         }
  1921.         crc = ~crc;
  1922.         for (i = 0; i < 4; i++) {
  1923.             p = zputhex (p, (char) crc);
  1924.             crc >>= 8;
  1925.         }
  1926.         *p++ = CR;
  1927.         /*
  1928.          * Uncork the remote in case a fake XOFF has stopped data flow.
  1929.          */
  1930.         if (ihdrtype != ZFIN && ihdrtype != ZACK) /* FIXME: why? */
  1931.             *p++ = XON;
  1932.         break;
  1933.     default:
  1934.         ulog (LOG_FATAL, "czbuild_header: ipkttype == %d", ipkttype);
  1935.         break;
  1936.     }
  1937.  
  1938.     return p - zresult;
  1939. }
  1940.  
  1941. /*
  1942.  * Build Zmodem data packets ...
  1943.  *
  1944.  * This function is zsdata() and zsda32() from the zm source.
  1945.  */
  1946.  
  1947. static int
  1948. czbuild_data_packet(zresult, zdata, cdata, frameend)
  1949. char *zresult;
  1950. const char *zdata;
  1951. size_t cdata;
  1952. int frameend;
  1953. {
  1954.     char *p;
  1955.     unsigned long crc;
  1956.  
  1957.     p = zresult;
  1958.  
  1959.     crc = ICRCINIT;
  1960.     for ( ; cdata-- != 0; zdata++) {
  1961.         char c;
  1962.  
  1963.         c = *zdata;
  1964.         if (c & 0140)
  1965.             *p++ = c;
  1966.         else
  1967.             p = zputchar (p, c);
  1968.         crc = UPDC32 ((unsigned char) c, crc);
  1969.     }
  1970.     *p++ = ZDLE;
  1971.     *p++ = frameend;
  1972.     crc = UPDC32 (frameend, crc);
  1973.     crc = ~crc;
  1974.     for (cdata = 0; cdata < 4; cdata++) {
  1975.         p = zputchar (p, (char) crc);
  1976.         crc >>= 8;
  1977.     }
  1978.     if (frameend == ZCRCW || frameend == ZCRCE || frameend == ZCRCF) {
  1979.         *p++ = CR;
  1980.         *p++ = XON;
  1981.     }
  1982.  
  1983.     return p - zresult;
  1984. }
  1985.  
  1986. /*
  1987.  * Read in a header ...
  1988.  *
  1989.  * This is function zgethdr() from the Zmodem source.
  1990.  */
  1991.  
  1992. static int
  1993. izrecv_hdr(qdaemon, hdr)
  1994. struct sdaemon *qdaemon;
  1995. achdrval_t hdr;
  1996. {
  1997.     int c,cerr;
  1998.  
  1999.     /*
  2000.      * Kludge alert! If another part of the program received a packet but
  2001.      * wasn't ready to handle it, it is tucked away for us to handle now.
  2002.      */
  2003.  
  2004.     if (iZpkt_rcvd_kludge != -1) {
  2005.         c = iZpkt_rcvd_kludge;
  2006.         iZpkt_rcvd_kludge = -1;
  2007.         stohdr (hvZpkt_hdrval_kludge, hdr);
  2008.         DEBUG_MESSAGE2 (DEBUG_PROTO,
  2009.                 "izrecv_hdr: queued %s, data = 0x%lx",
  2010.                 ZZHEADER_NAME(c), rclhdr (hdr));
  2011.         cZheaders_received++;
  2012.         return c;
  2013.     }
  2014.  
  2015.     cerr = cZmax_garbage;    /* Max bytes before start of frame */
  2016.  
  2017. again:
  2018.     switch (c = noxrd7 (qdaemon)) {
  2019.     case ZM_TIMEOUT:
  2020.     case ZM_ERROR:
  2021.     case ZM_RCDO:
  2022.         goto fifi;
  2023.     case ZPAD:        /* This is what we want */
  2024.         break;
  2025.     case CR:        /* padding at end of previous header */
  2026.     default:
  2027.         if (--cerr < 0) {
  2028.             c = ZM_ERROR;
  2029.             goto fifi;
  2030.         }
  2031.         goto again;
  2032.     }
  2033.  
  2034. splat:
  2035.     switch (c = noxrd7 (qdaemon)) {
  2036.     case ZPAD:
  2037.         if (--cerr < 0) {
  2038.             c = ZM_ERROR;
  2039.             goto fifi;
  2040.         }
  2041.         goto splat;
  2042.     case ZM_TIMEOUT:
  2043.     case ZM_RCDO:
  2044.         goto fifi;
  2045.     case ZDLE:        /* This is what we want */
  2046.         break;
  2047.     default:
  2048.         if (--cerr < 0) {
  2049.             c = ZM_ERROR;
  2050.             goto fifi;
  2051.         }
  2052.         goto again;
  2053.     }
  2054.  
  2055.     switch (c = noxrd7 (qdaemon)) {
  2056.     case ZM_TIMEOUT:
  2057.     case ZM_RCDO:
  2058.         goto fifi;
  2059.     case ZBIN:
  2060.         c = zrbhdr32 (qdaemon, hdr);
  2061.         break;
  2062.     case ZHEX:
  2063.         c = zrhhdr (qdaemon, hdr);
  2064.         break;
  2065.     default:
  2066.         if (--cerr < 0) {
  2067.             c = ZM_ERROR;
  2068.             goto fifi;
  2069.         }
  2070.         goto again;
  2071.     }
  2072.  
  2073. fifi:
  2074.     switch (c) {
  2075.     case ZM_TIMEOUT:
  2076.         cZtimeouts++;
  2077.         break;
  2078.     case ZM_ERROR:
  2079.         cZerrors++;
  2080.         break;
  2081.     case ZM_RCDO:
  2082.         break;
  2083.     default:
  2084.         cZheaders_received++;
  2085.         break;
  2086.     }
  2087.     DEBUG_MESSAGE2 (DEBUG_PROTO, "izrecv_hdr: %s, data = 0x%lx",
  2088.             ZZHEADER_NAME(c), rclhdr (hdr));
  2089.  
  2090.     return c;
  2091. }
  2092.  
  2093. /*
  2094.  * Receive a binary style header (type and position) with 32 bit FCS ...
  2095.  */
  2096.  
  2097. static int
  2098. zrbhdr32(qdaemon, hdr)
  2099. struct sdaemon *qdaemon;
  2100. achdrval_t hdr;
  2101. {
  2102.     int c,i,type;
  2103.     unsigned long crc;
  2104.  
  2105.     if ((c = zdlread (qdaemon)) & ~0377)
  2106.         return c;
  2107.     type = c;
  2108.     crc = ICRCINIT;
  2109.     crc = UPDC32 (c, crc);
  2110.  
  2111.     for (i = 0; i < 4; i++) {
  2112.         if ((c = zdlread (qdaemon)) & ~0377)
  2113.             return c;
  2114.         crc = UPDC32 (c, crc);
  2115.         hdr[i] = (char) c;
  2116.     }
  2117.     for (i = 0; i < 4; i++) {
  2118.         if ((c = zdlread (qdaemon)) & ~0377)
  2119.             return c;
  2120.         crc = UPDC32 (c, crc);
  2121.     }
  2122.     if (crc != IHDRCRC)
  2123.         return ZM_ERROR;
  2124.  
  2125.     return type;
  2126. }
  2127.  
  2128. /*
  2129.  * Receive a hex style header (type and position) ...
  2130.  */
  2131.  
  2132. static int
  2133. zrhhdr(qdaemon, hdr)
  2134. struct sdaemon *qdaemon;
  2135. achdrval_t hdr;
  2136. {
  2137.     int c,i,type;
  2138.     unsigned long crc;
  2139.  
  2140.     if ((c = zgethex (qdaemon)) < 0)
  2141.         return c;
  2142.     type = c;
  2143.     crc = ICRCINIT;
  2144.     crc = UPDC32 (c, crc);
  2145.  
  2146.     for (i = 0; i < 4; i++) {
  2147.         if ((c = zgethex (qdaemon)) < 0)
  2148.             return c;
  2149.         crc = UPDC32 (c, crc);
  2150.         hdr[i] = (char) c;
  2151.     }
  2152.     for (i = 0; i < 4; i++) {
  2153.         if ((c = zgethex (qdaemon)) < 0)
  2154.             return c;
  2155.         crc = UPDC32 (c, crc);
  2156.     }
  2157.     if (crc != IHDRCRC)
  2158.         return ZM_ERROR;
  2159.  
  2160.     return type;
  2161. }
  2162.  
  2163. /*
  2164.  * Receive a data packet ...
  2165.  */
  2166.  
  2167. static int
  2168. zrdat32(qdaemon, buf, length, iprxcount)
  2169. struct sdaemon *qdaemon;
  2170. char *buf;
  2171. int length;
  2172. int *iprxcount;
  2173. {
  2174.     int c,d;
  2175.     unsigned long crc;
  2176.     char *end;
  2177.  
  2178.     crc = ICRCINIT;
  2179.     *iprxcount = 0;
  2180.     end = buf + length;
  2181.     while (buf <= end) {
  2182.         if ((c = zdlread (qdaemon)) & ~0377) {
  2183. crcfoo:
  2184.             switch (c) {
  2185.             case GOTCRCE:
  2186.             case GOTCRCG:
  2187.             case GOTCRCQ:
  2188.             case GOTCRCW:
  2189.             case GOTCRCF:
  2190.                 d = c;
  2191.                 c &= 0377;
  2192.                 crc = UPDC32 (c, crc);
  2193.                 if ((c = zdlread (qdaemon)) & ~0377)
  2194.                     goto crcfoo;
  2195.                 crc = UPDC32 (c, crc);
  2196.                 if ((c = zdlread (qdaemon)) & ~0377)
  2197.                     goto crcfoo;
  2198.                 crc = UPDC32 (c, crc);
  2199.                 if ((c = zdlread (qdaemon)) & ~0377)
  2200.                     goto crcfoo;
  2201.                 crc = UPDC32 (c, crc);
  2202.                 if ((c = zdlread (qdaemon)) & ~0377)
  2203.                     goto crcfoo;
  2204.                 crc = UPDC32 (c, crc);
  2205.                 if (crc != IHDRCRC)
  2206.                     return ZM_ERROR;
  2207.                 *iprxcount = length - (end - buf);
  2208.                 return d;
  2209.             case ZM_TIMEOUT:
  2210.             case ZM_RCDO:
  2211.                 return c;
  2212.             default:
  2213.                 return ZM_ERROR;
  2214.             }
  2215.         }
  2216.         *buf++ = (char) c;
  2217.         crc = UPDC32 (c, crc);
  2218.     }
  2219.  
  2220.     return ZM_ERROR;    /* bad packet, too long */
  2221. }
  2222.  
  2223. /*
  2224.  * Respond to receiver's complaint, get back in sync with receiver ...
  2225.  */
  2226.  
  2227. static int
  2228. getinsync(qdaemon, flag)
  2229. struct sdaemon *qdaemon;
  2230. boolean flag;
  2231. {
  2232.     int c,cerr;
  2233.     achdrval_t rx_hdr;
  2234.  
  2235.     cerr = cZretries;
  2236.  
  2237.     for (;;) {
  2238.         c = izrecv_hdr (qdaemon, rx_hdr);
  2239.  
  2240.         switch (c) {
  2241.         case ZRPOS:
  2242.             wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
  2243.                            wpZlrxpos, wpZtxpos);
  2244.             cZbytes_resent += wpZtxpos - wpZrxpos;
  2245.             wpZlrxpos = wpZtxpos = wpZrxpos;
  2246.             if (wpZlastsync == wpZrxpos) {
  2247.                 if (++iZbeenhereb4 > 4)
  2248.                     if (cZblklen > 32)
  2249.                         cZblklen /= 2;
  2250.                 /* FIXME: shouldn't we reset iZbeenhereb4? */
  2251.             }
  2252.             wpZlastsync = wpZrxpos;
  2253.             return ZRPOS;
  2254.         case ZACK:
  2255.             wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
  2256.                            wpZlrxpos, wpZtxpos);
  2257.             wpZlrxpos = wpZrxpos;
  2258.             if (flag || wpZtxpos == wpZrxpos)
  2259.                 return ZACK;
  2260.             break;
  2261.         case ZNAK: {
  2262.             winpos_t rx_bytes;
  2263.             /*
  2264.              * Our partner is in fzfinish_tx() and is waiting
  2265.              * for ZACK ...
  2266.              */
  2267.             zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
  2268.             if (rx_bytes == wpZrxbytes) {
  2269.                 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
  2270.                          hvzencode_data_hdr (wpZrxbytes),
  2271.                          TRUE))
  2272.                     return FALSE;
  2273.             }
  2274.             break;
  2275.         }
  2276.         case ZFIN:
  2277.         case ZM_RCDO:
  2278.             return c;
  2279.         case ZM_TIMEOUT:
  2280.             if (--cerr < 0) {
  2281.                 ulog (LOG_ERROR,
  2282.                       "getinsync: retries exhausted");
  2283.                 return ZM_ERROR;
  2284.             }
  2285.             break;    /* sender doesn't send ZNAK for timeout */
  2286.         case ZM_ERROR:
  2287.         default:
  2288.             if (--cerr < 0) {
  2289.                 ulog (LOG_ERROR,
  2290.                       "getinsync: retries exhausted");
  2291.                 return ZM_ERROR;
  2292.             }
  2293.             if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
  2294.                      hvzencode_data_hdr (wpZtxpos),
  2295.                      TRUE))
  2296.                 return ZM_ERROR;
  2297.             break;
  2298.         }
  2299.     }
  2300. }
  2301.  
  2302. /*
  2303.  * Send a byte as two hex digits ...
  2304.  */
  2305.  
  2306. static char *
  2307. zputhex(p, ch)
  2308. char *p;
  2309. int ch;
  2310. {
  2311.     static char digits[] = "0123456789abcdef";
  2312.  
  2313.     *p++ = digits[(ch & 0xF0) >> 4];
  2314.     *p++ = digits[ch & 0xF];
  2315.     return p;
  2316. }
  2317.  
  2318. /*
  2319.  * Send character c with ZMODEM escape sequence encoding ...
  2320.  *
  2321.  * Escape XON, XOFF.
  2322.  * FIXME: Escape CR following @ (Telenet net escape) ... disabled for now
  2323.  *    Will need to put back references to <lastsent>.
  2324.  */
  2325.  
  2326. static char *
  2327. zputchar(p, ch)
  2328. char *p;
  2329. int ch;
  2330. {
  2331.     char c = ch;
  2332.  
  2333.     /* Quick check for non control characters */
  2334.  
  2335.     if (c & 0140) {
  2336.         *p++ = c;
  2337.     } else {
  2338.         switch (c & 0377) {
  2339.         case ZDLE:
  2340.             *p++ = ZDLE;
  2341.             *p++ = c ^ 0100;
  2342.             break;
  2343.         case CR:
  2344. #if 0
  2345.             if (!fZesc_ctl && (lastsent & 0177) != '@')
  2346.                 goto sendit;
  2347. #endif
  2348.             /* fall through */
  2349.         case 020:    /* ^P */
  2350.         case XON:
  2351.         case XOFF:
  2352.             *p++ = ZDLE;
  2353.             c ^= 0100;
  2354. /*sendit:*/
  2355.             *p++ = c;
  2356.             break;
  2357.         default:
  2358.             if (fZesc_ctl && !(c & 0140)) {
  2359.                 *p++ = ZDLE;
  2360.                 c ^= 0100;
  2361.             }
  2362.             *p++ = c;
  2363.             break;
  2364.         }
  2365.     }
  2366.  
  2367.     return p;
  2368. }
  2369.  
  2370. /*
  2371.  * Decode two lower case hex digits into an 8 bit byte value ...
  2372.  */
  2373.  
  2374. static int
  2375. zgethex(qdaemon)
  2376. struct sdaemon *qdaemon;
  2377. {
  2378.     int c,n;
  2379.  
  2380.     if ((c = noxrd7 (qdaemon)) < 0)
  2381.         return c;
  2382.     n = c - '0';
  2383.     if (n > 9)
  2384.         n -= ('a' - ':');
  2385.     if (n & ~0xF)
  2386.         return ZM_ERROR;
  2387.     if ((c = noxrd7 (qdaemon)) < 0)
  2388.         return c;
  2389.     c -= '0';
  2390.     if (c > 9)
  2391.         c -= ('a' - ':');
  2392.     if (c & ~0xF)
  2393.         return ZM_ERROR;
  2394.     c += (n << 4);
  2395.  
  2396.     return c;
  2397. }
  2398.  
  2399. /*
  2400.  * Read a byte, checking for ZMODEM escape encoding ...
  2401.  */
  2402.  
  2403. static int
  2404. zdlread(qdaemon)
  2405. struct sdaemon *qdaemon;
  2406. {
  2407.     int c;
  2408.  
  2409. again:
  2410.     READCHAR (qdaemon, c, cZtimeout);
  2411.     if (c < 0)
  2412.         return c;
  2413.     if (c & 0140)        /* quick check for non control characters */
  2414.         return c;
  2415.     switch (c) {
  2416.     case ZDLE:
  2417.         break;
  2418.     case XON:
  2419.         goto again;
  2420.     case XOFF:
  2421.         READCHAR (qdaemon, c, XON_WAIT);
  2422.         goto again;
  2423.     default:
  2424.         if (fZesc_ctl && !(c & 0140))
  2425.             goto again;
  2426.         return c;
  2427.     }
  2428.  
  2429. again2:
  2430.     READCHAR (qdaemon, c, cZtimeout);
  2431.     if (c < 0)
  2432.         return c;
  2433.     switch (c) {
  2434.     case ZCRCE:
  2435.     case ZCRCG:
  2436.     case ZCRCQ:
  2437.     case ZCRCW:
  2438.     case ZCRCF:
  2439.         return c | GOTOR;
  2440.     case ZRUB0:            /* FIXME: This is never generated. */
  2441.         return 0177;
  2442.     case ZRUB1:            /* FIXME: This is never generated. */
  2443.         return 0377;
  2444.     case XON:
  2445.         goto again2;
  2446.     case XOFF:
  2447.         READCHAR (qdaemon, c, XON_WAIT);
  2448.         goto again2;
  2449.     default:
  2450.         if (fZesc_ctl && !(c & 0140))
  2451.             goto again2;        /* FIXME: why again2? */
  2452.         if ((c & 0140) == 0100)
  2453.             return c ^ 0100;
  2454.         break;
  2455.     }
  2456.  
  2457.     return ZM_ERROR;
  2458. }
  2459.  
  2460. /*
  2461.  * Read a character from the modem line with timeout ...
  2462.  * Eat parity bit, XON and XOFF characters.
  2463.  */
  2464.  
  2465. static int
  2466. noxrd7(qdaemon)
  2467. struct sdaemon *qdaemon;
  2468. {
  2469.     int c;
  2470.  
  2471.     for (;;) {
  2472.         READCHAR (qdaemon, c, cZtimeout);
  2473.         if (c < 0)
  2474.             return c;
  2475.         switch (c &= 0177) {
  2476.         case XON:
  2477.             continue;
  2478.         case XOFF:
  2479.             READCHAR (qdaemon, c, XON_WAIT);
  2480.             continue;
  2481.         case CR:
  2482.         case ZDLE:
  2483.             return c;
  2484.         default:
  2485.             if (fZesc_ctl && !(c & 0140))
  2486.                 continue;
  2487.             return c;
  2488.         }
  2489.     }
  2490. }
  2491.  
  2492. /*
  2493.  * Read a character from the receive buffer, or from the line if empty ...
  2494.  *
  2495.  * <timeout> is in seconds (maybe make it tenths of seconds like in Zmodem?)
  2496.  */
  2497.  
  2498. static int
  2499. realreadchar(qdaemon, timeout)
  2500. struct sdaemon *qdaemon;
  2501. int timeout;
  2502. {
  2503.     int c;
  2504.  
  2505.     if ((c = breceive_char (qdaemon->qconn, timeout, TRUE)) >= 0)
  2506.         return c;
  2507.  
  2508.     switch (c) {
  2509.     case -1:
  2510.         return ZM_TIMEOUT;
  2511.     case -2:
  2512.         return ZM_RCDO;
  2513.     }
  2514.  
  2515.     ulog (LOG_FATAL, "realreadchar: breceive_char() returned %d", c);
  2516.     return ZM_ERROR;
  2517. }
  2518.  
  2519.  
  2520. /*
  2521.  * Check if the receive channel has any characters in it.
  2522.  *
  2523.  * At present we can only test the receive buffer. No mechanism is available
  2524.  * to go to the hardware. This should not be a problem though, as long as all
  2525.  * appropriate calls to fsend_data() set <fdoread> to TRUE.
  2526.  */
  2527.  
  2528. static boolean
  2529. fzreceive_ready()
  2530. {
  2531.     return iPrecstart != iPrecend;
  2532. }
  2533.  
  2534. /*
  2535.  * Store integer value in an achdrval_t ...
  2536.  */
  2537.  
  2538. static void
  2539. stohdr(val, hdr)
  2540. hdrval_t val;
  2541. achdrval_t hdr;
  2542. {
  2543.     hdr[ZP0] = (char) val;
  2544.     hdr[ZP1] = (char) (val >> 8);
  2545.     hdr[ZP2] = (char) (val >> 16);
  2546.     hdr[ZP3] = (char) (val >> 24);
  2547. }
  2548.  
  2549. /*
  2550.  * Recover an integer from a header ...
  2551.  */
  2552.  
  2553. static hdrval_t
  2554. rclhdr(hdr)
  2555. achdrval_t hdr;
  2556. {
  2557.     hdrval_t v;
  2558.  
  2559.     v = hdr[ZP3] & 0377;
  2560.     v = (v << 8) | (hdr[ZP2] & 0377);
  2561.     v = (v << 8) | (hdr[ZP1] & 0377);
  2562.     v = (v << 8) | (hdr[ZP0] & 0377);
  2563.  
  2564.     return v;
  2565. }
  2566.  
  2567. /*
  2568.  * Encode a <hdrval_t> from the byte count ...
  2569.  *
  2570.  * We use to store the byte count / 32 and a message sequence number which
  2571.  * made this function very useful. Don't remove it.
  2572.  * FIXME: Well, maybe remove it later.
  2573.  */
  2574.  
  2575. static hdrval_t
  2576. hvzencode_data_hdr(cbytes)
  2577. winpos_t cbytes;
  2578. {
  2579.     return (hdrval_t) cbytes;
  2580. }
  2581.  
  2582. /*
  2583.  * Decode a <hdrval_t> into a byte count ...
  2584.  *
  2585.  * We use to store the byte count / 32 and a message sequence number which
  2586.  * made this function very useful. Don't remove it.
  2587.  * FIXME: Well, maybe remove it later.
  2588.  */
  2589.  
  2590. static void
  2591. zdecode_data_hdr(hdrval, pcbytes)
  2592. hdrval_t hdrval;
  2593. winpos_t *pcbytes;
  2594. {
  2595.     *pcbytes = hdrval;
  2596. }
  2597.  
  2598. /*
  2599.  * Update <wpZrxpos> from the received data header value ...
  2600.  *
  2601.  * FIXME: Here is where we'd handle wrapping around at 4 gigabytes.
  2602.  */
  2603.  
  2604. static winpos_t
  2605. lzupdate_rxpos(rx_hdr, rxpos, lrxpos, txpos)
  2606. achdrval_t rx_hdr;
  2607. winpos_t rxpos,lrxpos,txpos;
  2608. {
  2609.     winpos_t rx_pktpos;
  2610.  
  2611.     zdecode_data_hdr (rclhdr (rx_hdr), &rx_pktpos);
  2612.  
  2613.     DEBUG_MESSAGE4 (DEBUG_PROTO,
  2614.    "lzupdate_rxpos: rx_pktpos=0x%lx, rxpos=0x%lx, lrxpos=0x%lx, txpos=0x%lx",
  2615.             rx_pktpos, rxpos, lrxpos, txpos);
  2616.  
  2617.     /*
  2618.      * Check if <rx_pktpos> valid. It could be old.
  2619.      */
  2620.  
  2621.     if (rx_pktpos < wpZlrxpos
  2622.         || rx_pktpos > ((wpZtxpos + 1024L) & ~1023L))
  2623.         return rxpos;
  2624.  
  2625.     return rx_pktpos;
  2626. }
  2627.