]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/libexec/uucp/uucico/protz.c
$Id$ -> $FreeBSD$
[FreeBSD/FreeBSD.git] / gnu / libexec / uucp / uucico / protz.c
1 /* protz.c              Version 1.5, 92Apr24 */
2 /* Modified by Ian Lance Taylor for Taylor UUCP 1.04 92Aug4.  */
3
4 /*
5  * Doug Evans, dje@sspiff.UUCP or dje@ersys.edmonton.ab.ca
6  *
7  * This file provides the Zmodem protocol (by Chuck Forsberg) for
8  * Ian Taylor's UUCP package.
9  *
10  * It was originally developed to establish a uucp link between myself and my
11  * employer: Ivation Datasystems, Inc. of Ottawa. 
12  *
13  * My thanks to Ivation for letting me release this to the public. Given that
14  * Zmodem is in the public domain, no additional copyrights have been added.
15  *
16  *****************************************************************************
17  *
18  * It's been difficult fitting Zmodem into the UUCP world. I have been guided
19  * mostly by trying to plug it into Taylor UUCP. Where "the Zmodem way of doing
20  * things" conflicted with "the UUCP way of doing things", I have err'd on the
21  * side of UUCP. At the end of it all, I have achieved something that will plug
22  * into Taylor UUCP very easily, but some might argue that I have corrupted Z
23  * too much. At any rate, compatibility with sz/rz was sacrificed to achieve a
24  * clean UUCP protocol. Given that, I took the opportunity to start from
25  * scratch when defining protocol constants (EG: ZBIN).
26  *
27  * 1) I wasn't quite sure how to enhance Zmodem to handle send+receive in one
28  *    session, so I added a 'g' protocol like initialization sequence. This
29  *    also gets this stuff out of the way, in case we ever try to support
30  *    full-duplex.
31  *
32  *      Caller                      Callee
33  *      ------                      ------
34  *      ZINIT           -->     <-- ZINIT
35  *      ZDATA (ZCRCF)   -->     <-- ZDATA (ZCRCF)
36  *      ZACK            -->     <-- ZACK
37  *      ZINITEND        -->     <-- ZINITEND
38  *
39  *    ZINIT is a combination of ZRINIT and ZSINIT and is intended to exchange
40  *    simple protocol information (flags) and the protocol version number.
41  *    ZDATA is intended to include window size information as well as the
42  *    "Myattn" string (although at the moment it doesn't contain anything).
43  *    ZDATA may contain at most 1k bytes of data and is sent out as one ZCRCF
44  *    packet. Two ack's (ZACK + ZINITEND) are needed to ensure both sides have
45  *    received ZDATA.
46  *
47  * 2) I've hardcoded several protocol parameters, like 32 bit CRC's for data.
48  *    Others are not supported (we don't need them).
49  *
50  * 3) ZHEX headers use 32 bit CRC's.
51  *
52  * 4) Zmodem sends the ZFILE message "in one chunk". If there are errors, the
53  *    entire string is resent. I have continued this practice. All UUCP
54  *    commands are sent "in one chunk". This can be changed down the road if
55  *    necessary.
56  *
57  * 5) The ZEOF message has been replaced with a new ZCRCx value: ZCRCF. ZCRCF
58  *    is identical to ZCRCW except that it indicates the end of the message.
59  *    The protocol here is *not* a file transfer protocol. It is an end to end
60  *    transport protocol (that preserves message boundaries).
61  *
62  * 6) Zmodem handles restarting a file transfer, but as best as I can tell UUCP
63  *    does not. At least Taylor UUCP doesn't. And if UUCP does start handling
64  *    file restart, can it be plugged into the existing Zmodem way with zero
65  *    changes? Beats me. Therefore I have removed this part of the code. One
66  *    can always put it back in if and when UUCP handles it. Ditto for other
67  *    pieces of removed code: there's no point in overly complicating this code
68  *    when supporting all the bells and whistles requires enhancements to UUCP
69  *    itself.
70  *
71  *    *** It is easier to put code back in in an upward compatible manner ***
72  *    *** than it is to correct for misunderstood code or poorly merged   ***
73  *    *** (Zmodem vs UUCP) code.                                          ***
74  *
75  * 7) For the character in the initial "protocol selection" sequence, I have
76  *    chosen 'a'. I'm told 'z' is already in use for something that isn't
77  *    Zmodem. It's entirely reasonable to believe that if Zmodem ever becomes a
78  *    standard UUCP protocol, this won't be it (so I'll leave z/Z for them).
79  *    Publicly, this is the 'a' protocol. Internally, it is refered to as 'z'.
80  *    A little confusing, I know. Maybe in time I'll refer to it internally as
81  *    'a', or maybe in time this will be *the* 'z' protocol.
82  *
83  * 8) Since we are writing a transport protocol, which isn't supposed to know
84  *    anything about what is being transfered or where it is coming from, the
85  *    header data value has changed meaning. It no longer means "file position"
86  *    but instead means "window position". It is a running counter of the bytes
87  *    transfered. Each "message" begins on a 1k boundary so the count isn't a
88  *    precise byte count. The counter wraps every 4 gigabytes, although this
89  *    wrapping isn't supported yet.
90  *
91  *    FIXME: At present the max data transfered per session is 4 gigabytes.
92  *
93  ****************************************************************************
94  *
95  * A typical message sequence is (master sending file to slave):
96  *
97  *      Master                          Slave
98  *      ------                          -----
99  *      ZDATA (S, ZCRCF)        -->
100  *                              <--     ZACK
101  *                              <--     ZDATA (SY, ZCRCF)
102  *      ZACK                    -->
103  *      ZDATA                   -->
104  *                        ...   <--     ZACK/ZRPOS
105  *      ZDATA (ZCRCF)           -->
106  *                              <--     ZACK
107  *                              <--     ZDATA (CY, ZCRCF)
108  *      ZACK                    -->
109  *
110  * A typical message sequence is (master receiving file from slave):
111  *
112  *      Master                          Slave
113  *      ------                          -----
114  *      ZDATA (R, ZCRCF)        -->
115  *                              <--     ZACK
116  *                              <--     ZDATA (RY, ZCRCF)
117  *      ZACK                    -->
118  *                              <--     ZDATA
119  *      ZACK/ZRPOS      ...     -->
120  *                              <--     ZDATA (ZCRCF)
121  *      ZACK                    -->
122  *      ZDATA (CY, ZCRCF)       -->
123  *                              <--     ZACK
124  *
125  *****************************************************************************
126  *
127  * Notes:
128  * 1) For future bidirectional concerns, keep packet types "unidirectional".
129  *      Sender always uses:     ZDATA, ZNAK
130  *      Receiver always uses:   ZRPOS, ZACK
131  *      There is no intersection.
132  *
133  *    I'm not sure if this is necessary or even useful, but it seems to be.
134  *
135  * 2) I use to store the byte count / 32 in the data header. This left 5 bits
136  *    unused for future concerns. I removed this because of the following
137  *    situation when sending a file:
138  *
139  *      ZDATA (ZCRCG, xx bytes) - received ok
140  *      ZDATA (ZCRCF, 0 bytes)  - corrupted
141  *
142  *    At this point the receiver would like to send back a ZRPOS with a value 
143  *    of the size of the file. However, it can't because the value is divided
144  *    by 32, and it would have to round up to the next multiple of 32. This
145  *    seemed a little ugly, so I went with using the entire header to store
146  *    the byte count.
147  *
148  *****************************************************************************
149  *
150  * Source version:
151  * 
152  * 1.1,2,3
153  *      Protocol version 0
154  *      Early attempts, completely rewritten later.
155  *
156  * 1.4  Protocol version 1
157  *      Beta test sent to Ian for analysis 92Apr18.
158  *
159  * 1.5  Protocol version 1
160  *      Released 92Apr24.
161  *
162  *****************************************************************************
163  *
164  * Protocol version:
165  *
166  * A version number is exchanged in the ZINIT message, so it is possible to
167  * correct or enhance the protocol, without breaking existing versions.
168  * The purpose of this section is to document these versions as they come out.
169  * Remember, this is the protocol version, not the source version.
170  *
171  * 0    Initial version.
172  *      Zmodem controlled file transfer. This was more of a "plug Z
173  *      into UUCP as is" port.
174  *
175  * 1    Complete rewrite.
176  *      Made Z more of a transport protocol. UUCP now controls transfer and Z
177  *      is on the same footing as the other UUCP protocols.
178  *      Theoretically, there will be little pain when UUCP goes bidirectional.
179  */
180
181 #include "uucp.h"
182
183 #if USE_RCS_ID
184 const char protz_rcsid[] = "$FreeBSD$";
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 \f
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 \f
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 \f
1419 /*
1420  * This section contains the guts of the Zmodem protocol. The intention
1421  * is to leave as much of it alone as possible at the start. Overtime it
1422  * will be cleaned up (EG: I'd like to clean up the naming of the globals).
1423  * Also, Zmodem has a different coding style. Over time this will be converted
1424  * to the Taylor UUCP coding style.
1425  */
1426
1427 /*
1428  * Start the protocol (exchange init packets) ...
1429  *
1430  * UUCP can transfer files in both directions in one session. Therefore the
1431  * init sequence is a little different.
1432  *
1433  * 1) ZINIT packets are exchanged
1434  *    - contains protocol version and protocol flags
1435  * 2) ZDATA packets are exchanged
1436  *    - is intended to contain various numeric and string information
1437  * 3) ZACK packets are exchanged
1438  * 4) ZINITEND packets are exchanged
1439  */
1440
1441 static boolean
1442 fzstart_proto(qdaemon)
1443 struct sdaemon *qdaemon;
1444 {
1445         int i;
1446         achdrval_t tx_hdr,rx_hdr;
1447
1448         for (i = 0; i < cZstartup_retries; i++) {
1449                 stohdr (0L, tx_hdr);
1450                 tx_hdr[ZF0] = ZPROTOCOL_VERSION;
1451                 if (fZesc_ctl)
1452                         tx_hdr[ZF1] |= TX_ESCCTL;
1453                 switch (izexchange_init (qdaemon, ZINIT, tx_hdr, rx_hdr)) {
1454                 case -1: return FALSE;
1455                 case 0:  continue;
1456                 case 1:  break;
1457                 }
1458 #if 0   /* can't work, but kept for documentation */
1459                 if (rx_hdr[ZF0] == 0) {
1460                         ulog (LOG_ERROR, "Old protocol version, init failed");
1461                         return FALSE;
1462                 }
1463 #endif
1464                 fZesc_ctl = fZesc_ctl || (rx_hdr[ZF1] & TX_ESCCTL) != 0;
1465
1466                 stohdr (0L, tx_hdr);
1467                 switch (izexchange_init (qdaemon, ZDATA, tx_hdr, rx_hdr)) {
1468                 case -1: return FALSE;
1469                 case 0:  continue;
1470                 case 1:  break;
1471                 }
1472
1473                 stohdr (0L, tx_hdr);
1474                 switch (izexchange_init (qdaemon, ZACK, tx_hdr, rx_hdr)) {
1475                 case -1: return FALSE;
1476                 case 0:  continue;
1477                 case 1:  break;
1478                 }
1479
1480                 stohdr (0L, tx_hdr);
1481                 switch (izexchange_init (qdaemon, ZINITEND, tx_hdr, rx_hdr)) {
1482                 case -1: return FALSE;
1483                 case 0:  continue;
1484                 case 1:  break;
1485                 }
1486
1487                 DEBUG_MESSAGE0 (DEBUG_PROTO,
1488                                 "fzstart_proto: Protocol started");
1489                 return TRUE;
1490
1491                 /* FIXME: see protg.c regarding sequencing here. */
1492         }
1493
1494         ulog (LOG_ERROR, "Protocol init failed");
1495         return FALSE;
1496 }
1497
1498 /*
1499  * Exchange init messages. This is based on 'g'.
1500  * See the comments concerning fgexchange_init() in protg.c.
1501  *
1502  * We return 1 for success, 0 for restart, -1 for comm failure (terminate).
1503  */
1504
1505 static int
1506 izexchange_init(qdaemon, send_type, send_val, recv_val)
1507 struct sdaemon *qdaemon;
1508 int send_type;
1509 achdrval_t send_val;
1510 achdrval_t recv_val;
1511 {
1512         int i,recv_type,count;
1513
1514         for (i = 0; i < CEXCHANGE_INIT_RETRIES; i++) {
1515                 if (!fzsend_hdr (qdaemon, send_type == ZDATA ? ZBIN : ZHEX,
1516                                  send_type, rclhdr (send_val), FALSE))
1517                         return -1;
1518
1519                 /*
1520                  * The ZDATA packet is intended to contain the <Attn> string
1521                  * (eventually, if it's ever usable) and allow for anything
1522                  * else that will need to be thrown in.
1523                  */
1524
1525                 if (send_type == ZDATA) {
1526                         count = czbuild_data_packet (zZtx_packet_buf, "",
1527                                                      (size_t) 1, ZCRCF);
1528                         if (!fsend_data (qdaemon->qconn, zZtx_packet_buf,
1529                                          (size_t) count, FALSE))
1530                                 return -1;
1531                 }
1532
1533                 recv_type = izrecv_hdr (qdaemon, recv_val);
1534
1535                 switch (recv_type) {
1536                 case ZM_TIMEOUT:
1537                 case ZM_ERROR:
1538                         continue;
1539                 case ZM_RCDO:
1540                 case ZFIN:
1541                         return -1;
1542                 case ZINIT:
1543                 case ZACK:
1544                 case ZINITEND:
1545                         break;
1546                 case ZDATA:
1547                         if (zrdat32 (qdaemon, zZrx_packet_buf, 1024, &count)
1548                             == GOTCRCF)
1549                                 break;
1550                         continue;
1551                 default:
1552                         continue;
1553                 }
1554
1555                 if (recv_type == send_type)
1556                         return 1;
1557
1558                 /*
1559                  * If the other side is farther along than we are, we have lost
1560                  * a packet.  Fall immediately back to ZINIT (but don't fail
1561                  * if we are already doing ZINIT, since that would count
1562                  * against cStart_retries more than it should).
1563                  *
1564                  * FIXME: The ">" test is "<" in protg.c. Check who's right.
1565                  */
1566
1567                 if (recv_type > send_type && send_type != ZINIT)
1568                         return 0;
1569
1570                 /*
1571                  * If we are sending ZINITEND and we receive an ZINIT, the
1572                  * other side has falled back (we know this because we have
1573                  * seen a ZINIT from them).  Fall back ourselves to start
1574                  * the whole handshake over again.
1575                  */
1576
1577                 if (recv_type == ZINIT && send_type == ZINITEND)
1578                         return 0;
1579         }
1580
1581         return 0;
1582 }
1583
1584 /*
1585  * Shut down the protocol ...
1586  */
1587
1588 static boolean
1589 fzshutdown_proto(qdaemon)
1590 struct sdaemon *qdaemon;
1591 {
1592         (void) fzsend_hdr (qdaemon, ZHEX, ZFIN, 0L, FALSE);
1593         return TRUE;
1594 }
1595
1596 /*
1597  * Reset the transmitter side for sending a new message ...
1598  */
1599
1600 static boolean
1601 fzstart_tx()
1602 {
1603         iZlast_tx_data_packet = -1;
1604
1605         /*
1606          * <wpZlastsync> is set to -1L to suppress ZCRCW request otherwise
1607          * triggered by (wpZlastsync == wpZtxpos).
1608          */
1609
1610         cZblklen = 1024;
1611         wpZlastsync = -1L;
1612         iZbeenhereb4 = 0;
1613         iZtleft = 0;
1614         iZjunk_count = 0;
1615
1616         wpZtxpos = (wpZtxpos + 1024L) & ~1023L; /* next packet boundary */
1617         wpZlrxpos = wpZrxpos = wpZtxpos;
1618
1619         wpZtxstart = wpZtxpos;  /* so we can compute the "file offset" */
1620
1621         return TRUE;
1622 }
1623
1624 /*
1625  * Finish the sending of a message ...
1626  *
1627  * Basically, we wait for some indication that the receiver received our last
1628  * message. If the receiver tells us to restart from some point, we set
1629  * *plredo to that point.
1630  *
1631  * FIXME: This function is a major kludge at the moment. It is taken from
1632  *      getinsync(). It is necessary because I don't yet buffer outgoing data.
1633  *      It will go away when we do (buffer outgoing data).
1634  */
1635
1636 static boolean
1637 fzfinish_tx(qdaemon, plredo)
1638 struct sdaemon *qdaemon;
1639 long *plredo;
1640 {
1641         int c,cerr,ctimeouts;
1642         achdrval_t rx_hdr;
1643         winpos_t rx_bytes;
1644
1645         *plredo = -1;
1646         cerr = cZretries;
1647         ctimeouts = 0;
1648
1649         DEBUG_MESSAGE4 (DEBUG_PROTO,
1650           "fzfinish_tx: txpos=0x%lx, rxpos=0x%lx, lrxpos=0x%lx, rxbytes=0x%lx",
1651                         wpZtxpos, wpZrxpos, wpZlrxpos, wpZrxbytes);
1652
1653         for (;;) {
1654                 c = izrecv_hdr (qdaemon, rx_hdr);
1655
1656                 switch (c) {
1657                 case ZRPOS:
1658                         wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
1659                                                    wpZlrxpos, wpZtxpos);
1660                         /*
1661                          * If the receiver sends a ZRPOS for the 1k block after
1662                          * the one we're currently at, we lost the final ZACK.
1663                          * We cheat and ignore this ZRPOS. Remember: the theory
1664                          * is that this entire function will go away when we
1665                          * begin buffering the outgoing data. Of course, one
1666                          * can reword the protocol definition and say this
1667                          * isn't cheating at all.
1668                          */
1669                         if (((wpZtxpos + 1024) & ~1023) == wpZrxpos)
1670                                 return TRUE;
1671                         cZbytes_resent += wpZtxpos - wpZrxpos;
1672                         wpZlrxpos = wpZtxpos = wpZrxpos;
1673                         if (wpZlastsync == wpZrxpos) {
1674                                 if (++iZbeenhereb4 > 4)
1675                                         if (cZblklen > 32)
1676                                                 cZblklen /= 2;
1677                                 /* FIXME: shouldn't we reset iZbeenhereb4? */
1678                         }
1679                         wpZlastsync = wpZrxpos;
1680                         iZlast_tx_data_packet = ZCRCW; /* force a timeout */
1681                         *plredo = wpZrxpos - wpZtxstart;
1682                         return TRUE;
1683                 case ZACK:
1684                         wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
1685                                                    wpZlrxpos, wpZtxpos);
1686                         wpZlrxpos = wpZrxpos;
1687                         if (wpZtxpos == wpZrxpos)  /* the ACK we want? */
1688                                 return TRUE;
1689                         break;
1690                 case ZDATA:
1691                         /*
1692                          * We cheat here and take advantage of UUCP's current
1693                          * half duplex nature. If we get a ZDATA starting on
1694                          * the next 1k boundary, we lost the ZACK. We cheat and
1695                          * tuck it away so that izrecv_hdr() can later detect
1696                          * it. Remember: see above.
1697                          */
1698                         zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
1699                         if (((wpZrxbytes + 1024L) & ~1023L) == rx_bytes) {
1700                                 iZpkt_rcvd_kludge = ZDATA;
1701                                 hvZpkt_hdrval_kludge = rclhdr (rx_hdr);
1702                                 return TRUE;
1703                         }
1704                         break;  /* ignore, out of sync (old) */
1705                 case ZNAK:
1706                         /*
1707                          * We cheat here and take advantage of UUCP's current
1708                          * half duplex nature. If we get a ZNAK starting on
1709                          * the next 1k boundary, we lost the ZACK. We cheat and
1710                          * throw the ZNAK away. Remember: see above.
1711                          *
1712                          * On the other hand, if (rx_bytes == wpZrxbytes) then
1713                          * the other side is also in fzfinish_tx(). He must
1714                          * have lost our ZACK, so we send him another.
1715                          */
1716                         zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
1717                         if (((wpZrxbytes + 1024L) & ~1023L) == rx_bytes)
1718                                 return TRUE;
1719                         if (rx_bytes == wpZrxbytes) {
1720                                 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
1721                                              hvzencode_data_hdr (wpZrxbytes),
1722                                              TRUE))
1723                                         return FALSE;
1724                         }
1725                         break;  /* ignore, out of sync (old) */
1726                 case ZFIN:
1727                 case ZM_RCDO:
1728                         return FALSE;
1729                 case ZM_TIMEOUT:
1730                         if (--cerr < 0) {
1731                                 ulog (LOG_ERROR,
1732                                       "fzfinish_tx: retries exhausted");
1733                                 return FALSE;
1734                         }
1735                         /*
1736                          * Normally the sender doesn't send NAK's for timeouts.
1737                          * We have to here because of the following scenario:
1738                          *
1739                          * - We send ZDATA/ZCRCF
1740                          * - They send ZACK (corrupted)
1741                          * - They send ZDATA/ZCRCF (corrupted)
1742                          *
1743                          * At this point, both sides are in fzfinish_tx().
1744                          * We only send ZNAK every second timeout to increase
1745                          * our timeout delay vs. our partner. This tries to
1746                          * avoid ZRPOS and ZNAK "passing in transit".
1747                          */
1748                         if (++ctimeouts % 2 == 0)
1749                                 if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
1750                                                  hvzencode_data_hdr (wpZtxpos),
1751                                                  TRUE))
1752                                         return FALSE;
1753                         break;
1754                 case ZM_ERROR:
1755                 default:
1756                         if (--cerr < 0) {
1757                                 ulog (LOG_ERROR,
1758                                       "fzfinish_tx: retries exhausted");
1759                                 return FALSE;
1760                         }
1761                         if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
1762                                          hvzencode_data_hdr (wpZtxpos),
1763                                          TRUE))
1764                                 return FALSE;
1765                         break;
1766                 }
1767         }
1768 }
1769
1770 /*
1771  * Initialize the receiver ...
1772  */
1773
1774 static boolean
1775 fzstart_rx()
1776 {
1777         wpZrxbytes = (wpZrxbytes + 1024L) & ~1023L; /* next packet boundary */
1778
1779         return TRUE;
1780 }
1781
1782 /*
1783  * Terminate the receiver ...
1784  *
1785  * Acknowledge the last packet received.
1786  */
1787
1788 static boolean
1789 fzfinish_rx(qdaemon)
1790 struct sdaemon *qdaemon;
1791 {
1792         DEBUG_MESSAGE0 (DEBUG_PROTO, "fzfinish_rx: message/file received");
1793
1794         return fzsend_hdr (qdaemon, ZHEX, ZACK,
1795                            hvzencode_data_hdr (wpZrxbytes), FALSE);
1796 }
1797
1798 /*
1799  * Send a Zmodem header to our partner ...
1800  */
1801
1802 static boolean
1803 fzsend_hdr(qdaemon, ipkttype, ihdrtype, hdrval, fcheckreceive)
1804 struct sdaemon *qdaemon;
1805 int ipkttype;
1806 int ihdrtype;
1807 hdrval_t hdrval;
1808 boolean fcheckreceive;
1809 {
1810         int cpacketlen;
1811
1812         DEBUG_MESSAGE2 (DEBUG_PROTO, "fzsend_hdr: %s, data = 0x%lx",
1813                         ZZHEADER_NAME(ihdrtype), hdrval);
1814
1815         cpacketlen = czbuild_header (zZtx_packet_buf, ipkttype,
1816                                      ihdrtype, hdrval);
1817
1818 #ifdef DJE_TESTING
1819 #if 0
1820         if (ihdrtype == ZACK && rand () % 100 < uucptest2) {
1821                 cZheaders_sent++;
1822                 return TRUE;
1823         }
1824 #else
1825         if (ihdrtype == ZACK || ihdrtype == ZDATA) {
1826                 boolean fresult;
1827                 int old;
1828                 extern int uucptest,uucptest2;
1829
1830                 old = uucptest;
1831                 uucptest = uucptest2;
1832                 cZheaders_sent++;
1833                 fresult = fsend_data (qdaemon->qconn, zZtx_packet_buf,
1834                                       (size_t) cpacketlen, fcheckreceive);
1835                 uucptest = old;
1836                 return fresult;
1837         }
1838 #endif
1839 #endif
1840         cZheaders_sent++;
1841         return fsend_data (qdaemon->qconn, zZtx_packet_buf,
1842                            (size_t) cpacketlen, fcheckreceive);
1843 }
1844
1845 /*
1846  * Send a data packet to our partner ...
1847  * <frameend> is one of ZCRCx.
1848  */
1849
1850 static boolean
1851 fzsend_data_packet(qdaemon, zdata, cdata, frameend, fcheckreceive)
1852 struct sdaemon *qdaemon;
1853 char *zdata;
1854 size_t cdata;
1855 int frameend;
1856 boolean fcheckreceive;
1857 {
1858         int cpacketlen;
1859
1860         cpacketlen = czbuild_data_packet (zZtx_packet_buf, zdata, cdata,
1861                                           frameend);
1862
1863         return fsend_data (qdaemon->qconn, zZtx_packet_buf,
1864                            (size_t) cpacketlen, fcheckreceive);
1865 }
1866
1867 /*
1868  * Build Zmodem headers ...
1869  *
1870  * Note that we use 32 bit CRC's for ZHEX headers.
1871  *
1872  * This function is a combination of zm fns: zsbhdr(), zsbh32(), and zshhdr().
1873  */
1874
1875 static int
1876 czbuild_header(zresult, ipkttype, ihdrtype, hdrval)
1877 char *zresult;
1878 int ipkttype;
1879 int ihdrtype;
1880 hdrval_t hdrval;
1881 {
1882         char *p;
1883         int i;
1884         unsigned long crc;
1885         achdrval_t achdrval;
1886
1887         p = zresult;
1888
1889         switch (ipkttype) {
1890         case ZBIN:
1891                 *p++ = ZPAD;
1892                 *p++ = ZDLE;
1893                 *p++ = ZBIN;
1894                 p = zputchar (p, ihdrtype);
1895                 crc = ICRCINIT;
1896                 crc = UPDC32 (ihdrtype, crc);
1897                 stohdr (hdrval, achdrval);
1898                 for (i = 0; i < 4; i++) {
1899                         p = zputchar (p, achdrval[i]);
1900                         crc = UPDC32 (achdrval[i], crc);
1901                 }
1902                 crc = ~crc;
1903                 for (i = 0; i < 4; i++) {
1904                         p = zputchar (p, (char) crc);
1905                         crc >>= 8;
1906                 }
1907                 break;
1908         case ZHEX:      /* build hex header */
1909                 *p++ = ZPAD;
1910                 *p++ = ZPAD;
1911                 *p++ = ZDLE;
1912                 *p++ = ZHEX;
1913                 p = zputhex (p, ihdrtype);
1914                 crc = ICRCINIT;
1915                 crc = UPDC32 (ihdrtype, crc);
1916                 stohdr (hdrval, achdrval);
1917                 for (i = 0; i < 4; i++) {
1918                         p = zputhex (p, achdrval[i]);
1919                         crc = UPDC32 (achdrval[i], crc);
1920                 }
1921                 crc = ~crc;
1922                 for (i = 0; i < 4; i++) {
1923                         p = zputhex (p, (char) crc);
1924                         crc >>= 8;
1925                 }
1926                 *p++ = CR;
1927                 /*
1928                  * Uncork the remote in case a fake XOFF has stopped data flow.
1929                  */
1930                 if (ihdrtype != ZFIN && ihdrtype != ZACK) /* FIXME: why? */
1931                         *p++ = XON;
1932                 break;
1933         default:
1934                 ulog (LOG_FATAL, "czbuild_header: ipkttype == %d", ipkttype);
1935                 break;
1936         }
1937
1938         return p - zresult;
1939 }
1940
1941 /*
1942  * Build Zmodem data packets ...
1943  *
1944  * This function is zsdata() and zsda32() from the zm source.
1945  */
1946
1947 static int
1948 czbuild_data_packet(zresult, zdata, cdata, frameend)
1949 char *zresult;
1950 const char *zdata;
1951 size_t cdata;
1952 int frameend;
1953 {
1954         char *p;
1955         unsigned long crc;
1956
1957         p = zresult;
1958
1959         crc = ICRCINIT;
1960         for ( ; cdata-- != 0; zdata++) {
1961                 char c;
1962
1963                 c = *zdata;
1964                 if (c & 0140)
1965                         *p++ = c;
1966                 else
1967                         p = zputchar (p, c);
1968                 crc = UPDC32 ((unsigned char) c, crc);
1969         }
1970         *p++ = ZDLE;
1971         *p++ = frameend;
1972         crc = UPDC32 (frameend, crc);
1973         crc = ~crc;
1974         for (cdata = 0; cdata < 4; cdata++) {
1975                 p = zputchar (p, (char) crc);
1976                 crc >>= 8;
1977         }
1978         if (frameend == ZCRCW || frameend == ZCRCE || frameend == ZCRCF) {
1979                 *p++ = CR;
1980                 *p++ = XON;
1981         }
1982
1983         return p - zresult;
1984 }
1985
1986 /*
1987  * Read in a header ...
1988  *
1989  * This is function zgethdr() from the Zmodem source.
1990  */
1991
1992 static int
1993 izrecv_hdr(qdaemon, hdr)
1994 struct sdaemon *qdaemon;
1995 achdrval_t hdr;
1996 {
1997         int c,cerr;
1998
1999         /*
2000          * Kludge alert! If another part of the program received a packet but
2001          * wasn't ready to handle it, it is tucked away for us to handle now.
2002          */
2003
2004         if (iZpkt_rcvd_kludge != -1) {
2005                 c = iZpkt_rcvd_kludge;
2006                 iZpkt_rcvd_kludge = -1;
2007                 stohdr (hvZpkt_hdrval_kludge, hdr);
2008                 DEBUG_MESSAGE2 (DEBUG_PROTO,
2009                                 "izrecv_hdr: queued %s, data = 0x%lx",
2010                                 ZZHEADER_NAME(c), rclhdr (hdr));
2011                 cZheaders_received++;
2012                 return c;
2013         }
2014
2015         cerr = cZmax_garbage;   /* Max bytes before start of frame */
2016
2017 again:
2018         switch (c = noxrd7 (qdaemon)) {
2019         case ZM_TIMEOUT:
2020         case ZM_ERROR:
2021         case ZM_RCDO:
2022                 goto fifi;
2023         case ZPAD:              /* This is what we want */
2024                 break;
2025         case CR:                /* padding at end of previous header */
2026         default:
2027                 if (--cerr < 0) {
2028                         c = ZM_ERROR;
2029                         goto fifi;
2030                 }
2031                 goto again;
2032         }
2033
2034 splat:
2035         switch (c = noxrd7 (qdaemon)) {
2036         case ZPAD:
2037                 if (--cerr < 0) {
2038                         c = ZM_ERROR;
2039                         goto fifi;
2040                 }
2041                 goto splat;
2042         case ZM_TIMEOUT:
2043         case ZM_RCDO:
2044                 goto fifi;
2045         case ZDLE:              /* This is what we want */
2046                 break;
2047         default:
2048                 if (--cerr < 0) {
2049                         c = ZM_ERROR;
2050                         goto fifi;
2051                 }
2052                 goto again;
2053         }
2054
2055         switch (c = noxrd7 (qdaemon)) {
2056         case ZM_TIMEOUT:
2057         case ZM_RCDO:
2058                 goto fifi;
2059         case ZBIN:
2060                 c = zrbhdr32 (qdaemon, hdr);
2061                 break;
2062         case ZHEX:
2063                 c = zrhhdr (qdaemon, hdr);
2064                 break;
2065         default:
2066                 if (--cerr < 0) {
2067                         c = ZM_ERROR;
2068                         goto fifi;
2069                 }
2070                 goto again;
2071         }
2072
2073 fifi:
2074         switch (c) {
2075         case ZM_TIMEOUT:
2076                 cZtimeouts++;
2077                 break;
2078         case ZM_ERROR:
2079                 cZerrors++;
2080                 break;
2081         case ZM_RCDO:
2082                 break;
2083         default:
2084                 cZheaders_received++;
2085                 break;
2086         }
2087         DEBUG_MESSAGE2 (DEBUG_PROTO, "izrecv_hdr: %s, data = 0x%lx",
2088                         ZZHEADER_NAME(c), rclhdr (hdr));
2089
2090         return c;
2091 }
2092
2093 /*
2094  * Receive a binary style header (type and position) with 32 bit FCS ...
2095  */
2096
2097 static int
2098 zrbhdr32(qdaemon, hdr)
2099 struct sdaemon *qdaemon;
2100 achdrval_t hdr;
2101 {
2102         int c,i,type;
2103         unsigned long crc;
2104
2105         if ((c = zdlread (qdaemon)) & ~0377)
2106                 return c;
2107         type = c;
2108         crc = ICRCINIT;
2109         crc = UPDC32 (c, crc);
2110
2111         for (i = 0; i < 4; i++) {
2112                 if ((c = zdlread (qdaemon)) & ~0377)
2113                         return c;
2114                 crc = UPDC32 (c, crc);
2115                 hdr[i] = (char) c;
2116         }
2117         for (i = 0; i < 4; i++) {
2118                 if ((c = zdlread (qdaemon)) & ~0377)
2119                         return c;
2120                 crc = UPDC32 (c, crc);
2121         }
2122         if (crc != IHDRCRC)
2123                 return ZM_ERROR;
2124
2125         return type;
2126 }
2127
2128 /*
2129  * Receive a hex style header (type and position) ...
2130  */
2131
2132 static int
2133 zrhhdr(qdaemon, hdr)
2134 struct sdaemon *qdaemon;
2135 achdrval_t hdr;
2136 {
2137         int c,i,type;
2138         unsigned long crc;
2139
2140         if ((c = zgethex (qdaemon)) < 0)
2141                 return c;
2142         type = c;
2143         crc = ICRCINIT;
2144         crc = UPDC32 (c, crc);
2145
2146         for (i = 0; i < 4; i++) {
2147                 if ((c = zgethex (qdaemon)) < 0)
2148                         return c;
2149                 crc = UPDC32 (c, crc);
2150                 hdr[i] = (char) c;
2151         }
2152         for (i = 0; i < 4; i++) {
2153                 if ((c = zgethex (qdaemon)) < 0)
2154                         return c;
2155                 crc = UPDC32 (c, crc);
2156         }
2157         if (crc != IHDRCRC)
2158                 return ZM_ERROR;
2159
2160         return type;
2161 }
2162
2163 /*
2164  * Receive a data packet ...
2165  */
2166
2167 static int
2168 zrdat32(qdaemon, buf, length, iprxcount)
2169 struct sdaemon *qdaemon;
2170 char *buf;
2171 int length;
2172 int *iprxcount;
2173 {
2174         int c,d;
2175         unsigned long crc;
2176         char *end;
2177
2178         crc = ICRCINIT;
2179         *iprxcount = 0;
2180         end = buf + length;
2181         while (buf <= end) {
2182                 if ((c = zdlread (qdaemon)) & ~0377) {
2183 crcfoo:
2184                         switch (c) {
2185                         case GOTCRCE:
2186                         case GOTCRCG:
2187                         case GOTCRCQ:
2188                         case GOTCRCW:
2189                         case GOTCRCF:
2190                                 d = c;
2191                                 c &= 0377;
2192                                 crc = UPDC32 (c, crc);
2193                                 if ((c = zdlread (qdaemon)) & ~0377)
2194                                         goto crcfoo;
2195                                 crc = UPDC32 (c, crc);
2196                                 if ((c = zdlread (qdaemon)) & ~0377)
2197                                         goto crcfoo;
2198                                 crc = UPDC32 (c, crc);
2199                                 if ((c = zdlread (qdaemon)) & ~0377)
2200                                         goto crcfoo;
2201                                 crc = UPDC32 (c, crc);
2202                                 if ((c = zdlread (qdaemon)) & ~0377)
2203                                         goto crcfoo;
2204                                 crc = UPDC32 (c, crc);
2205                                 if (crc != IHDRCRC)
2206                                         return ZM_ERROR;
2207                                 *iprxcount = length - (end - buf);
2208                                 return d;
2209                         case ZM_TIMEOUT:
2210                         case ZM_RCDO:
2211                                 return c;
2212                         default:
2213                                 return ZM_ERROR;
2214                         }
2215                 }
2216                 *buf++ = (char) c;
2217                 crc = UPDC32 (c, crc);
2218         }
2219
2220         return ZM_ERROR;        /* bad packet, too long */
2221 }
2222
2223 /*
2224  * Respond to receiver's complaint, get back in sync with receiver ...
2225  */
2226
2227 static int
2228 getinsync(qdaemon, flag)
2229 struct sdaemon *qdaemon;
2230 boolean flag;
2231 {
2232         int c,cerr;
2233         achdrval_t rx_hdr;
2234
2235         cerr = cZretries;
2236
2237         for (;;) {
2238                 c = izrecv_hdr (qdaemon, rx_hdr);
2239
2240                 switch (c) {
2241                 case ZRPOS:
2242                         wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
2243                                                    wpZlrxpos, wpZtxpos);
2244                         cZbytes_resent += wpZtxpos - wpZrxpos;
2245                         wpZlrxpos = wpZtxpos = wpZrxpos;
2246                         if (wpZlastsync == wpZrxpos) {
2247                                 if (++iZbeenhereb4 > 4)
2248                                         if (cZblklen > 32)
2249                                                 cZblklen /= 2;
2250                                 /* FIXME: shouldn't we reset iZbeenhereb4? */
2251                         }
2252                         wpZlastsync = wpZrxpos;
2253                         return ZRPOS;
2254                 case ZACK:
2255                         wpZrxpos = lzupdate_rxpos (rx_hdr, wpZrxpos,
2256                                                    wpZlrxpos, wpZtxpos);
2257                         wpZlrxpos = wpZrxpos;
2258                         if (flag || wpZtxpos == wpZrxpos)
2259                                 return ZACK;
2260                         break;
2261                 case ZNAK: {
2262                         winpos_t rx_bytes;
2263                         /*
2264                          * Our partner is in fzfinish_tx() and is waiting
2265                          * for ZACK ...
2266                          */
2267                         zdecode_data_hdr (rclhdr (rx_hdr), &rx_bytes);
2268                         if (rx_bytes == wpZrxbytes) {
2269                                 if (!fzsend_hdr (qdaemon, ZHEX, ZACK,
2270                                              hvzencode_data_hdr (wpZrxbytes),
2271                                              TRUE))
2272                                         return FALSE;
2273                         }
2274                         break;
2275                 }
2276                 case ZFIN:
2277                 case ZM_RCDO:
2278                         return c;
2279                 case ZM_TIMEOUT:
2280                         if (--cerr < 0) {
2281                                 ulog (LOG_ERROR,
2282                                       "getinsync: retries exhausted");
2283                                 return ZM_ERROR;
2284                         }
2285                         break;  /* sender doesn't send ZNAK for timeout */
2286                 case ZM_ERROR:
2287                 default:
2288                         if (--cerr < 0) {
2289                                 ulog (LOG_ERROR,
2290                                       "getinsync: retries exhausted");
2291                                 return ZM_ERROR;
2292                         }
2293                         if (!fzsend_hdr (qdaemon, ZHEX, ZNAK,
2294                                          hvzencode_data_hdr (wpZtxpos),
2295                                          TRUE))
2296                                 return ZM_ERROR;
2297                         break;
2298                 }
2299         }
2300 }
2301
2302 /*
2303  * Send a byte as two hex digits ...
2304  */
2305
2306 static char *
2307 zputhex(p, ch)
2308 char *p;
2309 int ch;
2310 {
2311         static char digits[] = "0123456789abcdef";
2312
2313         *p++ = digits[(ch & 0xF0) >> 4];
2314         *p++ = digits[ch & 0xF];
2315         return p;
2316 }
2317
2318 /*
2319  * Send character c with ZMODEM escape sequence encoding ...
2320  *
2321  * Escape XON, XOFF.
2322  * FIXME: Escape CR following @ (Telenet net escape) ... disabled for now
2323  *      Will need to put back references to <lastsent>.
2324  */
2325
2326 static char *
2327 zputchar(p, ch)
2328 char *p;
2329 int ch;
2330 {
2331         char c = ch;
2332
2333         /* Quick check for non control characters */
2334
2335         if (c & 0140) {
2336                 *p++ = c;
2337         } else {
2338                 switch (c & 0377) {
2339                 case ZDLE:
2340                         *p++ = ZDLE;
2341                         *p++ = c ^ 0100;
2342                         break;
2343                 case CR:
2344 #if 0
2345                         if (!fZesc_ctl && (lastsent & 0177) != '@')
2346                                 goto sendit;
2347 #endif
2348                         /* fall through */
2349                 case 020:       /* ^P */
2350                 case XON:
2351                 case XOFF:
2352                         *p++ = ZDLE;
2353                         c ^= 0100;
2354 /*sendit:*/
2355                         *p++ = c;
2356                         break;
2357                 default:
2358                         if (fZesc_ctl && !(c & 0140)) {
2359                                 *p++ = ZDLE;
2360                                 c ^= 0100;
2361                         }
2362                         *p++ = c;
2363                         break;
2364                 }
2365         }
2366
2367         return p;
2368 }
2369
2370 /*
2371  * Decode two lower case hex digits into an 8 bit byte value ...
2372  */
2373
2374 static int
2375 zgethex(qdaemon)
2376 struct sdaemon *qdaemon;
2377 {
2378         int c,n;
2379
2380         if ((c = noxrd7 (qdaemon)) < 0)
2381                 return c;
2382         n = c - '0';
2383         if (n > 9)
2384                 n -= ('a' - ':');
2385         if (n & ~0xF)
2386                 return ZM_ERROR;
2387         if ((c = noxrd7 (qdaemon)) < 0)
2388                 return c;
2389         c -= '0';
2390         if (c > 9)
2391                 c -= ('a' - ':');
2392         if (c & ~0xF)
2393                 return ZM_ERROR;
2394         c += (n << 4);
2395
2396         return c;
2397 }
2398
2399 /*
2400  * Read a byte, checking for ZMODEM escape encoding ...
2401  */
2402
2403 static int
2404 zdlread(qdaemon)
2405 struct sdaemon *qdaemon;
2406 {
2407         int c;
2408
2409 again:
2410         READCHAR (qdaemon, c, cZtimeout);
2411         if (c < 0)
2412                 return c;
2413         if (c & 0140)           /* quick check for non control characters */
2414                 return c;
2415         switch (c) {
2416         case ZDLE:
2417                 break;
2418         case XON:
2419                 goto again;
2420         case XOFF:
2421                 READCHAR (qdaemon, c, XON_WAIT);
2422                 goto again;
2423         default:
2424                 if (fZesc_ctl && !(c & 0140))
2425                         goto again;
2426                 return c;
2427         }
2428
2429 again2:
2430         READCHAR (qdaemon, c, cZtimeout);
2431         if (c < 0)
2432                 return c;
2433         switch (c) {
2434         case ZCRCE:
2435         case ZCRCG:
2436         case ZCRCQ:
2437         case ZCRCW:
2438         case ZCRCF:
2439                 return c | GOTOR;
2440         case ZRUB0:                     /* FIXME: This is never generated. */
2441                 return 0177;
2442         case ZRUB1:                     /* FIXME: This is never generated. */
2443                 return 0377;
2444         case XON:
2445                 goto again2;
2446         case XOFF:
2447                 READCHAR (qdaemon, c, XON_WAIT);
2448                 goto again2;
2449         default:
2450                 if (fZesc_ctl && !(c & 0140))
2451                         goto again2;            /* FIXME: why again2? */
2452                 if ((c & 0140) == 0100)
2453                         return c ^ 0100;
2454                 break;
2455         }
2456
2457         return ZM_ERROR;
2458 }
2459
2460 /*
2461  * Read a character from the modem line with timeout ...
2462  * Eat parity bit, XON and XOFF characters.
2463  */
2464
2465 static int
2466 noxrd7(qdaemon)
2467 struct sdaemon *qdaemon;
2468 {
2469         int c;
2470
2471         for (;;) {
2472                 READCHAR (qdaemon, c, cZtimeout);
2473                 if (c < 0)
2474                         return c;
2475                 switch (c &= 0177) {
2476                 case XON:
2477                         continue;
2478                 case XOFF:
2479                         READCHAR (qdaemon, c, XON_WAIT);
2480                         continue;
2481                 case CR:
2482                 case ZDLE:
2483                         return c;
2484                 default:
2485                         if (fZesc_ctl && !(c & 0140))
2486                                 continue;
2487                         return c;
2488                 }
2489         }
2490 }
2491
2492 /*
2493  * Read a character from the receive buffer, or from the line if empty ...
2494  *
2495  * <timeout> is in seconds (maybe make it tenths of seconds like in Zmodem?)
2496  */
2497
2498 static int
2499 realreadchar(qdaemon, timeout)
2500 struct sdaemon *qdaemon;
2501 int timeout;
2502 {
2503         int c;
2504
2505         if ((c = breceive_char (qdaemon->qconn, timeout, TRUE)) >= 0)
2506                 return c;
2507
2508         switch (c) {
2509         case -1:
2510                 return ZM_TIMEOUT;
2511         case -2:
2512                 return ZM_RCDO;
2513         }
2514
2515         ulog (LOG_FATAL, "realreadchar: breceive_char() returned %d", c);
2516         return ZM_ERROR;
2517 }
2518
2519
2520 /*
2521  * Check if the receive channel has any characters in it.
2522  *
2523  * At present we can only test the receive buffer. No mechanism is available
2524  * to go to the hardware. This should not be a problem though, as long as all
2525  * appropriate calls to fsend_data() set <fdoread> to TRUE.
2526  */
2527
2528 static boolean
2529 fzreceive_ready()
2530 {
2531         return iPrecstart != iPrecend;
2532 }
2533
2534 /*
2535  * Store integer value in an achdrval_t ...
2536  */
2537
2538 static void
2539 stohdr(val, hdr)
2540 hdrval_t val;
2541 achdrval_t hdr;
2542 {
2543         hdr[ZP0] = (char) val;
2544         hdr[ZP1] = (char) (val >> 8);
2545         hdr[ZP2] = (char) (val >> 16);
2546         hdr[ZP3] = (char) (val >> 24);
2547 }
2548
2549 /*
2550  * Recover an integer from a header ...
2551  */
2552
2553 static hdrval_t
2554 rclhdr(hdr)
2555 achdrval_t hdr;
2556 {
2557         hdrval_t v;
2558
2559         v = hdr[ZP3] & 0377;
2560         v = (v << 8) | (hdr[ZP2] & 0377);
2561         v = (v << 8) | (hdr[ZP1] & 0377);
2562         v = (v << 8) | (hdr[ZP0] & 0377);
2563
2564         return v;
2565 }
2566
2567 /*
2568  * Encode a <hdrval_t> from the byte count ...
2569  *
2570  * We use to store the byte count / 32 and a message sequence number which
2571  * made this function very useful. Don't remove it.
2572  * FIXME: Well, maybe remove it later.
2573  */
2574
2575 static hdrval_t
2576 hvzencode_data_hdr(cbytes)
2577 winpos_t cbytes;
2578 {
2579         return (hdrval_t) cbytes;
2580 }
2581
2582 /*
2583  * Decode a <hdrval_t> into a byte count ...
2584  *
2585  * We use to store the byte count / 32 and a message sequence number which
2586  * made this function very useful. Don't remove it.
2587  * FIXME: Well, maybe remove it later.
2588  */
2589
2590 static void
2591 zdecode_data_hdr(hdrval, pcbytes)
2592 hdrval_t hdrval;
2593 winpos_t *pcbytes;
2594 {
2595         *pcbytes = hdrval;
2596 }
2597
2598 /*
2599  * Update <wpZrxpos> from the received data header value ...
2600  *
2601  * FIXME: Here is where we'd handle wrapping around at 4 gigabytes.
2602  */
2603
2604 static winpos_t
2605 lzupdate_rxpos(rx_hdr, rxpos, lrxpos, txpos)
2606 achdrval_t rx_hdr;
2607 winpos_t rxpos,lrxpos,txpos;
2608 {
2609         winpos_t rx_pktpos;
2610
2611         zdecode_data_hdr (rclhdr (rx_hdr), &rx_pktpos);
2612
2613         DEBUG_MESSAGE4 (DEBUG_PROTO,
2614    "lzupdate_rxpos: rx_pktpos=0x%lx, rxpos=0x%lx, lrxpos=0x%lx, txpos=0x%lx",
2615                         rx_pktpos, rxpos, lrxpos, txpos);
2616
2617         /*
2618          * Check if <rx_pktpos> valid. It could be old.
2619          */
2620
2621         if (rx_pktpos < wpZlrxpos
2622             || rx_pktpos > ((wpZtxpos + 1024L) & ~1023L))
2623                 return rxpos;
2624
2625         return rx_pktpos;
2626 }