1 /* protz.c Version 1.5, 92Apr24 */
2 /* Modified by Ian Lance Taylor for Taylor UUCP 1.04 92Aug4. */
5 * Doug Evans, dje@sspiff.UUCP or dje@ersys.edmonton.ab.ca
7 * This file provides the Zmodem protocol (by Chuck Forsberg) for
8 * Ian Taylor's UUCP package.
10 * It was originally developed to establish a uucp link between myself and my
11 * employer: Ivation Datasystems, Inc. of Ottawa.
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.
16 *****************************************************************************
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).
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
35 * ZDATA (ZCRCF) --> <-- ZDATA (ZCRCF)
37 * ZINITEND --> <-- ZINITEND
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
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).
50 * 3) ZHEX headers use 32 bit CRC's.
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
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).
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
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. ***
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.
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.
91 * FIXME: At present the max data transfered per session is 4 gigabytes.
93 ****************************************************************************
95 * A typical message sequence is (master sending file to slave):
99 * ZDATA (S, ZCRCF) -->
101 * <-- ZDATA (SY, ZCRCF)
107 * <-- ZDATA (CY, ZCRCF)
110 * A typical message sequence is (master receiving file from slave):
114 * ZDATA (R, ZCRCF) -->
116 * <-- ZDATA (RY, ZCRCF)
122 * ZDATA (CY, ZCRCF) -->
125 *****************************************************************************
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.
133 * I'm not sure if this is necessary or even useful, but it seems to be.
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:
139 * ZDATA (ZCRCG, xx bytes) - received ok
140 * ZDATA (ZCRCF, 0 bytes) - corrupted
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
148 *****************************************************************************
154 * Early attempts, completely rewritten later.
156 * 1.4 Protocol version 1
157 * Beta test sent to Ian for analysis 92Apr18.
159 * 1.5 Protocol version 1
162 *****************************************************************************
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.
172 * Zmodem controlled file transfer. This was more of a "plug Z
173 * into UUCP as is" port.
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.
184 const char protz_rcsid[] = "$FreeBSD$";
196 #define ZPROTOCOL_VERSION 1
199 * Control message characters ...
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 */
208 * Frame types (see array "frametypes" in zm.c) ...
210 * Note that the numbers here have been reorganized, as we don't support
211 * all of them (nor do we need to).
213 * WARNING: The init sequence assumes ZINIT < ZDATA < ZACK < ZINITEND.
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 */
228 * Note addition of ZCRCF: "end of message".
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 */
237 #define ZRUB0 'm' /* Translate to rubout 0177 */
238 #define ZRUB1 'n' /* Translate to rubout 0377 */
242 * zdlread return values (internal) ...
243 * Other values are ZM_ERROR, ZM_TIMEOUT, ZM_RCDO.
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 */
254 * Byte positions within header array ...
257 #define ZF0 3 /* First flags byte */
262 #define ZP0 0 /* Low order 8 bits of position */
265 #define ZP3 3 /* High order 8 bits of position */
268 * Bit Masks for ZRQINIT flags byte ZF0 ...
271 #define TX_ESCCTL 1 /* Tx will escape control chars */
274 * Possible errors when running ZMODEM ...
277 #define ZM_ERROR (-1) /* crc error, etc. */
278 #define ZM_TIMEOUT (-2)
279 #define ZM_RCDO (-3) /* Carrier Lost */
282 * ASCII characters ...
290 #define XON_WAIT 10 /* seconds */
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.
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
305 /* The header CRC value. */
308 #define IHDRCRC 0xDEBB20E3UL
310 #define IHDRCRC ((unsigned long) 0xDEBB20E3L)
313 /* packet buffer size */
314 #define CPACKBUFSIZE (CFRAMELEN + 2 * CPACKETSIZE + CSUFFIXLEN + 42 /*slop*/)
320 typedef unsigned char achdrval_t[4];
321 typedef unsigned long hdrval_t;
322 typedef unsigned long winpos_t;
325 * Configurable parms ...
327 * FIXME: <cZrx_buf_len> isn't used yet. It may not be needed.
332 #define CSTARTUP_RETRIES 4
333 #define CGARBAGE 2400
334 #define CSEND_WINDOW 16384
335 #define FESCAPE_CONTROL FALSE
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 */
345 struct uuconf_cmdtab asZproto_params[] =
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,
355 {NULL, 0, NULL, NULL}
359 * Variables for statistic gathering ...
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.
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;
375 static char *zZtx_buf; /* transmit buffer */
377 static char *zZtx_packet_buf; /* raw outgoing packet data */
378 static char *zZrx_packet_buf; /* raw incoming packet data */
381 * Transmitter state variables ...
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 */
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 */
399 static int iZbeenhereb4; /* times we've been ZRPOS'd to same place */
402 * Receiver state variables ...
405 static winpos_t wpZrxbytes; /* receiver byte count */
406 static int iZlast_rx_data_packet; /* last successfully received ZCRCx packet */
412 static char xon = XON;
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.
426 static int iZpkt_rcvd_kludge; /* -1 if not valid */
427 static hdrval_t hvZpkt_hdrval_kludge;
433 static const char *azZframe_types[] = {
434 "Carrier Lost", /* -3 */
448 #define FTNUMBER (sizeof(azZframe_types) / sizeof(char *))
451 #define min(a, b) ((a) < (b) ? (a) : (b))
453 #define ZZHEADER_NAME(itype) \
454 azZframe_types[min((itype) + FTOFFSET, FTNUMBER - 1)]
457 * Local functions ...
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,
479 static int czbuild_data_packet P((char *zresult, const char *zdata,
480 size_t cdata, int frameend));
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.
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,
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));
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().
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))))
519 /************************************************************************/
523 * Start the protocol ...
527 fzstart(qdaemon, pzlog)
528 struct sdaemon *qdaemon;
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);
536 if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
537 STRIPSETTING_EIGHTBITS, XONXOFF_OFF))
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
547 if (cZtx_window % 1024 != 0 ||
548 cZtx_window < 4096 || cZtx_window > 65536 ||
549 65536 % cZtx_window != 0
552 "fzstart: cZtx_window not one of 4096, 8192, 16384, 32768, 65536");
556 zZtx_buf = (char *) xmalloc (CPACKETSIZE);
557 zZtx_packet_buf = (char *) xmalloc (CPACKBUFSIZE);
558 zZrx_packet_buf = (char *) xmalloc (CPACKBUFSIZE);
560 iZlast_tx_data_packet = -1;
561 iZlast_rx_data_packet = -1;
563 wpZtxpos = wpZlrxpos = wpZrxpos = wpZrxbytes = 0;
564 cZtxwspac = cZtx_window / 4;
566 cZheaders_sent = cZheaders_received = cZbytes_resent = 0;
567 cZtimeouts = cZerrors = 0;
569 iZpkt_rcvd_kludge = -1;
573 * We ensure <cZtx_window> is at least 4k, so the following is
574 * unnecessary. It can be put back in later if needed.
576 if (cZblklen_override > cZtxwspac
577 || (!cZblklen_override && cZtxwspac < 1024))
578 cZblklen_override = cZtxwspac;
583 extern int uucptest,uucptest2,uucptestseed;
586 if (uucptest == -1) {
587 f = fopen ("/usr/local/src/bin/uucp/uucptest", "r");
589 fscanf (f, "%d %d %d",
590 &uucptestseed, &uucptest, &uucptest2);
593 srand (uucptestseed);
599 * Fire up the protocol (exchange init messages) ...
602 if (!fzstart_proto (qdaemon))
609 * Stop the protocol ...
614 struct sdaemon *qdaemon;
616 (void) fzshutdown_proto (qdaemon);
618 xfree ((pointer) zZtx_buf);
619 xfree ((pointer) zZtx_packet_buf);
620 xfree ((pointer) zZrx_packet_buf);
622 zZtx_packet_buf = NULL;
623 zZrx_packet_buf = NULL;
626 * Print some informative statistics ...
628 * I use the word "messages" here instead of "headers" because the
629 * latter is jargonese.
633 "Protocol 'a' messages: sent %lu, received %lu",
634 cZheaders_sent, cZheaders_received);
636 "Protocol 'a' packets: sent %lu, received %lu",
637 wpZtxpos / 1024, wpZrxbytes / 1024);
638 if (cZbytes_resent != 0 || cZtimeouts != 0 || cZerrors != 0)
640 "Protocol 'a' errors: bytes resent %lu, timeouts %lu, errors %lu",
641 cZbytes_resent, cZtimeouts, cZerrors);
644 * Reset all the parameters to their default values, so that the
645 * protocol parameters used for this connection do not affect the
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;
656 cZheaders_sent = cZheaders_received = cZbytes_resent = 0;
657 cZtimeouts = cZerrors = 0;
663 * Send a command string ...
664 * We send everything up to and including the null byte.
666 * We assume the command will fit in the outgoing data buffer.
667 * FIXME: A valid assumption?
672 fzsendcmd(qdaemon, z, ilocal, iremote)
673 struct sdaemon *qdaemon;
682 clen = strlen (z) + 1;
684 DEBUG_MESSAGE1 (DEBUG_PROTO, "fzsendcmd: sending command %s", z);
686 if (!fzstart_tx ()) /* must be called before zzgetspace() */
689 if ((zbuf = zzgetspace (qdaemon, &n)) == NULL)
694 ulog (LOG_FATAL, "fzsendcmd: clen > n");
704 if (!fzsend_data (qdaemon, zbuf, clen, TRUE))
706 if (!fzfinish_tx (qdaemon, &lredo))
708 } while (lredo >= 0);
710 return fzprocess (qdaemon);
714 * Allocate a packet to send out ...
716 * Note that 'z' has dynamic packet resizing and that <cZblklen> will range
717 * from 32 to 1024, in multiples of 2.
722 zzgetspace(qdaemon, pclen)
723 struct sdaemon *qdaemon;
731 * Send a block of data ...
733 * If (cdata == 0) then the end of the file has been reached.
738 fzsenddata(qdaemon, zdata, cdata, ilocal, iremote, ipos)
739 struct sdaemon *qdaemon;
746 DEBUG_MESSAGE1 (DEBUG_PROTO, "fzsenddata: %d bytes", cdata);
748 if (! fzsend_data (qdaemon, zdata, cdata, cdata == 0))
750 return fzprocess (qdaemon);
754 * Send a block of data (command or file) ...
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
760 extern struct stransfer *qTsend;
763 fzsend_data(qdaemon, zdata, cdata, fendofmessage)
764 struct sdaemon *qdaemon;
767 boolean fendofmessage;
771 if (iZlast_tx_data_packet == -1 || iZlast_tx_data_packet == ZCRCW) {
772 cZtxwcnt = cZrxwcnt = 0;
774 if (!fzsend_hdr (qdaemon, ZBIN, ZDATA,
775 hvzencode_data_hdr (wpZtxpos), TRUE))
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;
793 iZlast_tx_data_packet = ZCRCG;
799 #if 0 /* <cZblklen_override> is currently unnecessary */
800 if (cZblklen_override && cZblklen > cZblklen_override)
801 cZblklen = cZblklen_override;
805 if (cZrx_buf_len && cZblklen > cZrx_buf_len)
806 cZblklen = cZrx_buf_len;
810 if (FDEBUGGING(DEBUG_PROTO)) {
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;
821 DEBUG_MESSAGE3 (DEBUG_PROTO,
822 "fzsend_data: %s, pos 0x%lx, %d bytes",
827 if (!fzsend_data_packet (qdaemon, zdata, n, iZlast_tx_data_packet,
833 if (iZlast_tx_data_packet == ZCRCW) {
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.
840 switch (getinsync (qdaemon, FALSE)) {
845 || ! ffileisopen (qTsend->e)) {
846 ulog (LOG_ERROR, "Can't reset non-file");
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));
865 * If we've reached the maximum transmit window size, let the
866 * receiver catch up ...
868 * I use (cZtx_window - 2048) to play it safe.
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,
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.
883 switch (getinsync (qdaemon, TRUE)) {
888 || ! ffileisopen (qTsend->e)) {
889 ulog (LOG_ERROR, "Can't reset non-file");
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));
910 * Process existing data ...
915 struct sdaemon *qdaemon;
919 while (fzreceive_ready ()) {
920 READCHAR (qdaemon, ch, 1);
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)
930 c = getinsync (qdaemon, TRUE);
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,
942 || ! ffileisopen (qTsend->e)) {
944 "Attempt to back up non-file");
947 if (! ffileseek (qTsend->e,
948 wpZrxpos - wpZtxstart)) {
950 "seek: %s", strerror (errno));
953 iZlast_tx_data_packet = -1; /* trigger ZDATA */
954 break; /* not returning is intentional */
959 READCHAR (qdaemon, ch, XON_WAIT);
973 * Wait for data to come in.
975 * This continues processing until a complete file or command has been
981 struct sdaemon *qdaemon;
995 if (!fzsend_hdr (qdaemon, ZHEX, ZRPOS,
996 hvzencode_data_hdr (wpZrxbytes), FALSE))
999 c = izrecv_hdr (qdaemon, rx_hdr);
1005 ulog (LOG_ERROR, "fzwait: retries exhausted");
1011 ulog (LOG_ERROR, "fzwait: retries exhausted");
1021 goto nxthdr; /* ignore, partner is out of sync */
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) {
1032 "fzwait: retries exhausted");
1035 (void) zrdat32 (qdaemon, zZrx_packet_buf,
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.
1045 continue; /* goto nxthdr? */
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.
1053 c = zrdat32 (qdaemon, zZrx_packet_buf, 1024,
1056 if (FDEBUGGING(DEBUG_PROTO)) {
1060 msg = ZZHEADER_NAME(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;
1072 DEBUG_MESSAGE2 (DEBUG_PROTO,
1073 "fzwait: zrdat32: %s, %d bytes",
1076 DEBUG_MESSAGE2 (DEBUG_PROTO,
1077 "fzwait: zrdat32: %d, %d bytes",
1082 case ZM_ERROR: /* CRC error */
1086 "fzwait: retries exhausted");
1095 "fzwait: retries exhausted");
1102 iZlast_rx_data_packet = ZCRCW;
1105 && !fgot_data (qdaemon, zZrx_packet_buf,
1107 (const char *) NULL,
1112 wpZrxbytes += rxcount;
1113 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
1114 hvzencode_data_hdr (wpZrxbytes),
1117 if (! fsend_data (qdaemon->qconn, &xon,
1122 iZlast_rx_data_packet = ZCRCQ;
1125 && !fgot_data (qdaemon, zZrx_packet_buf,
1127 (const char *) NULL,
1132 wpZrxbytes += rxcount;
1133 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
1134 hvzencode_data_hdr (wpZrxbytes),
1139 iZlast_rx_data_packet = ZCRCG;
1142 && !fgot_data (qdaemon, zZrx_packet_buf,
1144 (const char *) NULL,
1149 wpZrxbytes += rxcount;
1152 iZlast_rx_data_packet = ZCRCE;
1155 && !fgot_data (qdaemon, zZrx_packet_buf,
1157 (const char *) NULL,
1162 wpZrxbytes += rxcount;
1165 iZlast_rx_data_packet = ZCRCF;
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
1174 wpZrxbytes += rxcount;
1175 if (!fzfinish_rx (qdaemon))
1177 if (!fgot_data (qdaemon, zZrx_packet_buf,
1179 (const char *) NULL,
1181 (long) -1, TRUE, &fexit))
1184 * FIXME: Examine <fexit>?
1185 * Or maybe ensure it's TRUE?
1192 ulog (LOG_FATAL, "fzwait: received header %s",
1202 * File level routine. Called when initiating/terminating file transfers.
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)
1211 fzfile(qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
1212 struct sdaemon *qdaemon;
1213 struct stransfer *qtrans;
1223 DEBUG_MESSAGE2 (DEBUG_PROTO, "fzfile: fstart=%d, fsend=%d", fstart,
1228 return fzstart_tx ();
1229 if (! fzfinish_tx (qdaemon, &iredo))
1232 if (! ffileisopen (qtrans->e)) {
1234 "Attempt to back up non-file");
1237 if (! ffileseek (qtrans->e, iredo)) {
1239 "seek: %s", strerror (errno));
1243 qtrans->fsendfile = TRUE;
1244 return fqueue_send (qdaemon, qtrans);
1251 /****************************************************************************/
1254 #if 0 /* not used, we only use 32 bit crc's */
1256 * crctab calculated by Mark G. Mendel, Network Systems Corporation
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
1296 * Copyright (C) 1986 Gary S. Brown. You may use this program, or
1297 * code or tables extracted from it, as desired without restriction.
1300 /* First, the polynomial itself and its table of feedback terms. The */
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. */
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. */
1320 /* The feedback terms table consists of 256, 32-bit entries. Notes: */
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. */
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. */
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
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.
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,
1411 #define updcrc(cp, crc) (crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
1413 #define UPDC32(b, crc) \
1414 (crc_32_tab[((unsigned)(crc) ^ (unsigned)(b)) & 0xff] \
1415 ^ (((crc) >> 8) & 0x00ffffffL))
1417 /****************************************************************************/
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.
1428 * Start the protocol (exchange init packets) ...
1430 * UUCP can transfer files in both directions in one session. Therefore the
1431 * init sequence is a little different.
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
1442 fzstart_proto(qdaemon)
1443 struct sdaemon *qdaemon;
1446 achdrval_t tx_hdr,rx_hdr;
1448 for (i = 0; i < cZstartup_retries; i++) {
1449 stohdr (0L, tx_hdr);
1450 tx_hdr[ZF0] = ZPROTOCOL_VERSION;
1452 tx_hdr[ZF1] |= TX_ESCCTL;
1453 switch (izexchange_init (qdaemon, ZINIT, tx_hdr, rx_hdr)) {
1454 case -1: return FALSE;
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");
1464 fZesc_ctl = fZesc_ctl || (rx_hdr[ZF1] & TX_ESCCTL) != 0;
1466 stohdr (0L, tx_hdr);
1467 switch (izexchange_init (qdaemon, ZDATA, tx_hdr, rx_hdr)) {
1468 case -1: return FALSE;
1473 stohdr (0L, tx_hdr);
1474 switch (izexchange_init (qdaemon, ZACK, tx_hdr, rx_hdr)) {
1475 case -1: return FALSE;
1480 stohdr (0L, tx_hdr);
1481 switch (izexchange_init (qdaemon, ZINITEND, tx_hdr, rx_hdr)) {
1482 case -1: return FALSE;
1487 DEBUG_MESSAGE0 (DEBUG_PROTO,
1488 "fzstart_proto: Protocol started");
1491 /* FIXME: see protg.c regarding sequencing here. */
1494 ulog (LOG_ERROR, "Protocol init failed");
1499 * Exchange init messages. This is based on 'g'.
1500 * See the comments concerning fgexchange_init() in protg.c.
1502 * We return 1 for success, 0 for restart, -1 for comm failure (terminate).
1506 izexchange_init(qdaemon, send_type, send_val, recv_val)
1507 struct sdaemon *qdaemon;
1509 achdrval_t send_val;
1510 achdrval_t recv_val;
1512 int i,recv_type,count;
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))
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.
1525 if (send_type == ZDATA) {
1526 count = czbuild_data_packet (zZtx_packet_buf, "",
1528 if (!fsend_data (qdaemon->qconn, zZtx_packet_buf,
1529 (size_t) count, FALSE))
1533 recv_type = izrecv_hdr (qdaemon, recv_val);
1535 switch (recv_type) {
1547 if (zrdat32 (qdaemon, zZrx_packet_buf, 1024, &count)
1555 if (recv_type == send_type)
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).
1564 * FIXME: The ">" test is "<" in protg.c. Check who's right.
1567 if (recv_type > send_type && send_type != ZINIT)
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.
1577 if (recv_type == ZINIT && send_type == ZINITEND)
1585 * Shut down the protocol ...
1589 fzshutdown_proto(qdaemon)
1590 struct sdaemon *qdaemon;
1592 (void) fzsend_hdr (qdaemon, ZHEX, ZFIN, 0L, FALSE);
1597 * Reset the transmitter side for sending a new message ...
1603 iZlast_tx_data_packet = -1;
1606 * <wpZlastsync> is set to -1L to suppress ZCRCW request otherwise
1607 * triggered by (wpZlastsync == wpZtxpos).
1616 wpZtxpos = (wpZtxpos + 1024L) & ~1023L; /* next packet boundary */
1617 wpZlrxpos = wpZrxpos = wpZtxpos;
1619 wpZtxstart = wpZtxpos; /* so we can compute the "file offset" */
1625 * Finish the sending of a message ...
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.
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).
1637 fzfinish_tx(qdaemon, plredo)
1638 struct sdaemon *qdaemon;
1641 int c,cerr,ctimeouts;
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);
1654 c = izrecv_hdr (qdaemon, rx_hdr);
1658 wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
1659 wpZlrxpos, wpZtxpos);
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.
1669 if (((wpZtxpos + 1024) & ~1023) == wpZrxpos)
1671 cZbytes_resent += wpZtxpos - wpZrxpos;
1672 wpZlrxpos = wpZtxpos = wpZrxpos;
1673 if (wpZlastsync == wpZrxpos) {
1674 if (++iZbeenhereb4 > 4)
1677 /* FIXME: shouldn't we reset iZbeenhereb4? */
1679 wpZlastsync = wpZrxpos;
1680 iZlast_tx_data_packet = ZCRCW; /* force a timeout */
1681 *plredo = wpZrxpos - wpZtxstart;
1684 wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
1685 wpZlrxpos, wpZtxpos);
1686 wpZlrxpos = wpZrxpos;
1687 if (wpZtxpos == wpZrxpos) /* the ACK we want? */
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.
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);
1704 break; /* ignore, out of sync (old) */
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.
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.
1716 zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
1717 if (((wpZrxbytes + 1024L) & ~1023L) == rx_bytes)
1719 if (rx_bytes == wpZrxbytes) {
1720 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
1721 hvzencode_data_hdr (wpZrxbytes),
1725 break; /* ignore, out of sync (old) */
1732 "fzfinish_tx: retries exhausted");
1736 * Normally the sender doesn't send NAK's for timeouts.
1737 * We have to here because of the following scenario:
1739 * - We send ZDATA/ZCRCF
1740 * - They send ZACK (corrupted)
1741 * - They send ZDATA/ZCRCF (corrupted)
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".
1748 if (++ctimeouts % 2 == 0)
1749 if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
1750 hvzencode_data_hdr (wpZtxpos),
1758 "fzfinish_tx: retries exhausted");
1761 if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
1762 hvzencode_data_hdr (wpZtxpos),
1771 * Initialize the receiver ...
1777 wpZrxbytes = (wpZrxbytes + 1024L) & ~1023L; /* next packet boundary */
1783 * Terminate the receiver ...
1785 * Acknowledge the last packet received.
1789 fzfinish_rx(qdaemon)
1790 struct sdaemon *qdaemon;
1792 DEBUG_MESSAGE0 (DEBUG_PROTO, "fzfinish_rx: message/file received");
1794 return fzsend_hdr (qdaemon, ZHEX, ZACK,
1795 hvzencode_data_hdr (wpZrxbytes), FALSE);
1799 * Send a Zmodem header to our partner ...
1803 fzsend_hdr(qdaemon, ipkttype, ihdrtype, hdrval, fcheckreceive)
1804 struct sdaemon *qdaemon;
1808 boolean fcheckreceive;
1812 DEBUG_MESSAGE2 (DEBUG_PROTO, "fzsend_hdr: %s, data = 0x%lx",
1813 ZZHEADER_NAME(ihdrtype), hdrval);
1815 cpacketlen = czbuild_header (zZtx_packet_buf, ipkttype,
1820 if (ihdrtype == ZACK && rand () % 100 < uucptest2) {
1825 if (ihdrtype == ZACK || ihdrtype == ZDATA) {
1828 extern int uucptest,uucptest2;
1831 uucptest = uucptest2;
1833 fresult = fsend_data (qdaemon->qconn, zZtx_packet_buf,
1834 (size_t) cpacketlen, fcheckreceive);
1841 return fsend_data (qdaemon->qconn, zZtx_packet_buf,
1842 (size_t) cpacketlen, fcheckreceive);
1846 * Send a data packet to our partner ...
1847 * <frameend> is one of ZCRCx.
1851 fzsend_data_packet(qdaemon, zdata, cdata, frameend, fcheckreceive)
1852 struct sdaemon *qdaemon;
1856 boolean fcheckreceive;
1860 cpacketlen = czbuild_data_packet (zZtx_packet_buf, zdata, cdata,
1863 return fsend_data (qdaemon->qconn, zZtx_packet_buf,
1864 (size_t) cpacketlen, fcheckreceive);
1868 * Build Zmodem headers ...
1870 * Note that we use 32 bit CRC's for ZHEX headers.
1872 * This function is a combination of zm fns: zsbhdr(), zsbh32(), and zshhdr().
1876 czbuild_header(zresult, ipkttype, ihdrtype, hdrval)
1885 achdrval_t achdrval;
1894 p = zputchar (p, ihdrtype);
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);
1903 for (i = 0; i < 4; i++) {
1904 p = zputchar (p, (char) crc);
1908 case ZHEX: /* build hex header */
1913 p = zputhex (p, ihdrtype);
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);
1922 for (i = 0; i < 4; i++) {
1923 p = zputhex (p, (char) crc);
1928 * Uncork the remote in case a fake XOFF has stopped data flow.
1930 if (ihdrtype != ZFIN && ihdrtype != ZACK) /* FIXME: why? */
1934 ulog (LOG_FATAL, "czbuild_header: ipkttype == %d", ipkttype);
1942 * Build Zmodem data packets ...
1944 * This function is zsdata() and zsda32() from the zm source.
1948 czbuild_data_packet(zresult, zdata, cdata, frameend)
1960 for ( ; cdata-- != 0; zdata++) {
1967 p = zputchar (p, c);
1968 crc = UPDC32 ((unsigned char) c, crc);
1972 crc = UPDC32 (frameend, crc);
1974 for (cdata = 0; cdata < 4; cdata++) {
1975 p = zputchar (p, (char) crc);
1978 if (frameend == ZCRCW || frameend == ZCRCE || frameend == ZCRCF) {
1987 * Read in a header ...
1989 * This is function zgethdr() from the Zmodem source.
1993 izrecv_hdr(qdaemon, hdr)
1994 struct sdaemon *qdaemon;
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.
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++;
2015 cerr = cZmax_garbage; /* Max bytes before start of frame */
2018 switch (c = noxrd7 (qdaemon)) {
2023 case ZPAD: /* This is what we want */
2025 case CR: /* padding at end of previous header */
2035 switch (c = noxrd7 (qdaemon)) {
2045 case ZDLE: /* This is what we want */
2055 switch (c = noxrd7 (qdaemon)) {
2060 c = zrbhdr32 (qdaemon, hdr);
2063 c = zrhhdr (qdaemon, hdr);
2084 cZheaders_received++;
2087 DEBUG_MESSAGE2 (DEBUG_PROTO, "izrecv_hdr: %s, data = 0x%lx",
2088 ZZHEADER_NAME(c), rclhdr (hdr));
2094 * Receive a binary style header (type and position) with 32 bit FCS ...
2098 zrbhdr32(qdaemon, hdr)
2099 struct sdaemon *qdaemon;
2105 if ((c = zdlread (qdaemon)) & ~0377)
2109 crc = UPDC32 (c, crc);
2111 for (i = 0; i < 4; i++) {
2112 if ((c = zdlread (qdaemon)) & ~0377)
2114 crc = UPDC32 (c, crc);
2117 for (i = 0; i < 4; i++) {
2118 if ((c = zdlread (qdaemon)) & ~0377)
2120 crc = UPDC32 (c, crc);
2129 * Receive a hex style header (type and position) ...
2133 zrhhdr(qdaemon, hdr)
2134 struct sdaemon *qdaemon;
2140 if ((c = zgethex (qdaemon)) < 0)
2144 crc = UPDC32 (c, crc);
2146 for (i = 0; i < 4; i++) {
2147 if ((c = zgethex (qdaemon)) < 0)
2149 crc = UPDC32 (c, crc);
2152 for (i = 0; i < 4; i++) {
2153 if ((c = zgethex (qdaemon)) < 0)
2155 crc = UPDC32 (c, crc);
2164 * Receive a data packet ...
2168 zrdat32(qdaemon, buf, length, iprxcount)
2169 struct sdaemon *qdaemon;
2181 while (buf <= end) {
2182 if ((c = zdlread (qdaemon)) & ~0377) {
2192 crc = UPDC32 (c, crc);
2193 if ((c = zdlread (qdaemon)) & ~0377)
2195 crc = UPDC32 (c, crc);
2196 if ((c = zdlread (qdaemon)) & ~0377)
2198 crc = UPDC32 (c, crc);
2199 if ((c = zdlread (qdaemon)) & ~0377)
2201 crc = UPDC32 (c, crc);
2202 if ((c = zdlread (qdaemon)) & ~0377)
2204 crc = UPDC32 (c, crc);
2207 *iprxcount = length - (end - buf);
2217 crc = UPDC32 (c, crc);
2220 return ZM_ERROR; /* bad packet, too long */
2224 * Respond to receiver's complaint, get back in sync with receiver ...
2228 getinsync(qdaemon, flag)
2229 struct sdaemon *qdaemon;
2238 c = izrecv_hdr (qdaemon, rx_hdr);
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)
2250 /* FIXME: shouldn't we reset iZbeenhereb4? */
2252 wpZlastsync = wpZrxpos;
2255 wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
2256 wpZlrxpos, wpZtxpos);
2257 wpZlrxpos = wpZrxpos;
2258 if (flag || wpZtxpos == wpZrxpos)
2264 * Our partner is in fzfinish_tx() and is waiting
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),
2282 "getinsync: retries exhausted");
2285 break; /* sender doesn't send ZNAK for timeout */
2290 "getinsync: retries exhausted");
2293 if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
2294 hvzencode_data_hdr (wpZtxpos),
2303 * Send a byte as two hex digits ...
2311 static char digits[] = "0123456789abcdef";
2313 *p++ = digits[(ch & 0xF0) >> 4];
2314 *p++ = digits[ch & 0xF];
2319 * Send character c with ZMODEM escape sequence encoding ...
2322 * FIXME: Escape CR following @ (Telenet net escape) ... disabled for now
2323 * Will need to put back references to <lastsent>.
2333 /* Quick check for non control characters */
2345 if (!fZesc_ctl && (lastsent & 0177) != '@')
2358 if (fZesc_ctl && !(c & 0140)) {
2371 * Decode two lower case hex digits into an 8 bit byte value ...
2376 struct sdaemon *qdaemon;
2380 if ((c = noxrd7 (qdaemon)) < 0)
2387 if ((c = noxrd7 (qdaemon)) < 0)
2400 * Read a byte, checking for ZMODEM escape encoding ...
2405 struct sdaemon *qdaemon;
2410 READCHAR (qdaemon, c, cZtimeout);
2413 if (c & 0140) /* quick check for non control characters */
2421 READCHAR (qdaemon, c, XON_WAIT);
2424 if (fZesc_ctl && !(c & 0140))
2430 READCHAR (qdaemon, c, cZtimeout);
2440 case ZRUB0: /* FIXME: This is never generated. */
2442 case ZRUB1: /* FIXME: This is never generated. */
2447 READCHAR (qdaemon, c, XON_WAIT);
2450 if (fZesc_ctl && !(c & 0140))
2451 goto again2; /* FIXME: why again2? */
2452 if ((c & 0140) == 0100)
2461 * Read a character from the modem line with timeout ...
2462 * Eat parity bit, XON and XOFF characters.
2467 struct sdaemon *qdaemon;
2472 READCHAR (qdaemon, c, cZtimeout);
2475 switch (c &= 0177) {
2479 READCHAR (qdaemon, c, XON_WAIT);
2485 if (fZesc_ctl && !(c & 0140))
2493 * Read a character from the receive buffer, or from the line if empty ...
2495 * <timeout> is in seconds (maybe make it tenths of seconds like in Zmodem?)
2499 realreadchar(qdaemon, timeout)
2500 struct sdaemon *qdaemon;
2505 if ((c = breceive_char (qdaemon->qconn, timeout, TRUE)) >= 0)
2515 ulog (LOG_FATAL, "realreadchar: breceive_char() returned %d", c);
2521 * Check if the receive channel has any characters in it.
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.
2531 return iPrecstart != iPrecend;
2535 * Store integer value in an achdrval_t ...
2543 hdr[ZP0] = (char) val;
2544 hdr[ZP1] = (char) (val >> 8);
2545 hdr[ZP2] = (char) (val >> 16);
2546 hdr[ZP3] = (char) (val >> 24);
2550 * Recover an integer from a header ...
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);
2568 * Encode a <hdrval_t> from the byte count ...
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.
2576 hvzencode_data_hdr(cbytes)
2579 return (hdrval_t) cbytes;
2583 * Decode a <hdrval_t> into a byte count ...
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.
2591 zdecode_data_hdr(hdrval, pcbytes)
2599 * Update <wpZrxpos> from the received data header value ...
2601 * FIXME: Here is where we'd handle wrapping around at 4 gigabytes.
2605 lzupdate_rxpos(rx_hdr, rxpos, lrxpos, txpos)
2607 winpos_t rxpos,lrxpos,txpos;
2611 zdecode_data_hdr (rclhdr (rx_hdr), &rx_pktpos);
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);
2618 * Check if <rx_pktpos> valid. It could be old.
2621 if (rx_pktpos < wpZlrxpos
2622 || rx_pktpos > ((wpZtxpos + 1024L) & ~1023L))