Annotation of coherent/g/usr/lib/uucp/tay104/protz.c, revision 1.1.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.