|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.