Annotation of coherent/g/usr/lib/uucp/tay104/protz.c, revision 1.1

1.1     ! root        1: /* protz.c             Version 1.5, 92Apr24 */
        !             2: /* Modified by Ian Lance Taylor for Taylor UUCP 1.04 92Aug4.  */
        !             3: 
        !             4: /*
        !             5:  * Doug Evans, [email protected] or [email protected]
        !             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.1 93/07/30 07:53:39 bin Exp Locker: bin $";
        !           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%x",
        !          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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.