3 * ZMODEM protocol primitives
4 * 05-09-88 Chuck Forsberg Omen Technology Inc
6 * Entry point Functions:
7 * zsbhdr(type, hdr) send binary header
8 * zshhdr(type, hdr) send hex header
9 * zgethdr(hdr, eflag) receive header - binary or hex
10 * zsdata(buf, len, frameend) send data
11 * zrdata(buf, len) receive data
12 * stohdr(pos) store position data in Txhdr
13 * long rclhdr(hdr) recover position offset from header
19 int Rxtimeout
= 100; /* Tenths of seconds to wait for something */
26 /* Globals used by ZMODEM functions */
27 int Rxframeind
; /* ZBIN ZBIN32, or ZHEX type of frame received */
28 int Rxtype
; /* Type of header received */
29 int Rxcount
; /* Count of data bytes received */
30 char Rxhdr
[4]; /* Received header */
31 char Txhdr
[4]; /* Transmitted header */
32 long Rxpos
; /* Received file position */
33 long Txpos
; /* Transmitted file position */
34 int Txfcs32
; /* TURE means send binary frames with 32 bit FCS */
35 int Crc32t
; /* Display flag indicating 32 bit CRC being sent */
36 int Crc32
; /* Display flag indicating 32 bit CRC being received */
37 int Znulls
; /* Number of nulls to send at beginning of ZDATA hdr */
38 char Attn
[ZATTNLEN
+1]; /* Attention string rx sends to tx on err */
40 static int lastsent
; /* Last char we sent */
41 static int Not8bit
; /* Seven bits seen on header */
43 static char *frametypes
[] = {
44 "Carrier Lost", /* -3 */
69 #define FRTYPES 22 /* Total number of frame types in this array */
70 /* not including psuedo negative entries */
73 static char badcrc
[] = "Bad CRC";
75 /* Send ZMODEM binary header hdr of type type */
76 void zsbhdr(int type
, char *hdr
)
79 register unsigned short crc
;
81 vfile("zsbhdr: %s %lx", frametypes
[type
+FTOFFSET
], rclhdr(hdr
));
83 for (n
= Znulls
; --n
>=0; )
86 xsendline(ZPAD
); xsendline(ZDLE
);
91 xsendline(ZBIN
); zsendline(type
); crc
= updcrc(type
, 0);
93 for (n
=4; --n
>= 0; ++hdr
) {
95 crc
= updcrc((0377& *hdr
), crc
);
97 crc
= updcrc(0,updcrc(0,crc
));
106 /* Send ZMODEM binary header hdr of type type */
107 void zsbh32(char *hdr
, int type
)
110 register UNSL
long crc
;
112 xsendline(ZBIN32
); zsendline(type
);
113 crc
= 0xFFFFFFFFL
; crc
= UPDC32(type
, crc
);
115 for (n
=4; --n
>= 0; ++hdr
) {
116 crc
= UPDC32((0377 & *hdr
), crc
);
120 for (n
=4; --n
>= 0;) {
126 /* Send ZMODEM HEX header hdr of type type */
127 void zshhdr(int type
, char *hdr
)
130 register unsigned short crc
;
132 vfile("zshhdr: %s %lx", frametypes
[type
+FTOFFSET
], rclhdr(hdr
));
133 sendline(ZPAD
); sendline(ZPAD
); sendline(ZDLE
); sendline(ZHEX
);
137 crc
= updcrc(type
, 0);
138 for (n
=4; --n
>= 0; ++hdr
) {
139 zputhex(*hdr
); crc
= updcrc((0377 & *hdr
), crc
);
141 crc
= updcrc(0,updcrc(0,crc
));
142 zputhex(crc
>>8); zputhex(crc
);
144 /* Make it printable on remote machine */
145 sendline(015); sendline(0212);
147 * Uncork the remote in case a fake XOFF has stopped data flow
149 if (type
!= ZFIN
&& type
!= ZACK
)
155 * Send binary array buf of length length, with ending ZDLE sequence frameend
157 static char *Zendnames
[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
159 void zsdata(char *buf
, int length
, int frameend
)
161 register unsigned short crc
;
163 vfile("zsdata: %d %s", length
, Zendnames
[(frameend
-ZCRCE
)&3]);
165 zsda32(buf
, length
, frameend
);
168 for (;--length
>= 0; ++buf
) {
169 zsendline(*buf
); crc
= updcrc((0377 & *buf
), crc
);
171 xsendline(ZDLE
); xsendline(frameend
);
172 crc
= updcrc(frameend
, crc
);
174 crc
= updcrc(0,updcrc(0,crc
));
175 zsendline(crc
>>8); zsendline(crc
);
177 if (frameend
== ZCRCW
) {
178 xsendline(XON
); flushmo();
182 void zsda32(char *buf
, int length
, int frameend
)
185 register UNSL
long crc
;
188 for (;--length
>= 0; ++buf
) {
191 xsendline(lastsent
= c
);
194 crc
= UPDC32(c
, crc
);
196 xsendline(ZDLE
); xsendline(frameend
);
197 crc
= UPDC32(frameend
, crc
);
200 for (length
=4; --length
>= 0;) {
201 zsendline((int)crc
); crc
>>= 8;
206 * Receive array buf of max length with ending ZDLE sequence
207 * and CRC. Returns the ending character or error code.
208 * NB: On errors may store length+1 bytes!
210 int zrdata(char *buf
, int length
)
213 register unsigned short crc
;
217 if (Rxframeind
== ZBIN32
)
218 return zrdat32(buf
, length
);
220 crc
= Rxcount
= 0; end
= buf
+ length
;
222 if ((c
= zdlread()) & ~0377) {
229 crc
= updcrc((((d
=c
))&0377), crc
);
230 if ((c
= zdlread()) & ~0377)
232 crc
= updcrc(c
, crc
);
233 if ((c
= zdlread()) & ~0377)
235 crc
= updcrc(c
, crc
);
240 Rxcount
= length
- (end
- buf
);
241 vfile("zrdata: %d %s", Rxcount
,
242 Zendnames
[(d
-GOTCRCE
)&3]);
245 zperr("Sender Canceled");
251 zperr("Bad data subpacket");
256 crc
= updcrc(c
, crc
);
258 zperr("Data subpacket too long");
262 int zrdat32(char *buf
, int length
)
265 register UNSL
long crc
;
269 crc
= 0xFFFFFFFFL
; Rxcount
= 0; end
= buf
+ length
;
271 if ((c
= zdlread()) & ~0377) {
279 crc
= UPDC32(c
, crc
);
280 if ((c
= zdlread()) & ~0377)
282 crc
= UPDC32(c
, crc
);
283 if ((c
= zdlread()) & ~0377)
285 crc
= UPDC32(c
, crc
);
286 if ((c
= zdlread()) & ~0377)
288 crc
= UPDC32(c
, crc
);
289 if ((c
= zdlread()) & ~0377)
291 crc
= UPDC32(c
, crc
);
292 if (crc
!= 0xDEBB20E3) {
296 Rxcount
= length
- (end
- buf
);
297 vfile("zrdat32: %d %s", Rxcount
,
298 Zendnames
[(d
-GOTCRCE
)&3]);
301 zperr("Sender Canceled");
307 zperr("Bad data subpacket");
312 crc
= UPDC32(c
, crc
);
314 zperr("Data subpacket too long");
320 * Read a ZMODEM header to hdr, either binary or hex.
321 * eflag controls local display of non zmodem characters:
323 * 1: display printing characters only
324 * 2: display all non ZMODEM characters
325 * On success, set Zmodem to 1, set Rxpos and return type of header.
326 * Otherwise return negative on error.
327 * Return ERROR instantly if ZCRCW sequence, for fast error recovery.
329 int zgethdr(char *hdr
, int eflag
)
331 register int c
, n
, cancount
;
333 n
= Zrwindow
+ Baudrate
; /* Max bytes before start of frame */
334 Rxframeind
= Rxtype
= 0;
339 /* Return immediate ERROR if ZCRCW sequence seen */
340 switch (c
= readline(Rxtimeout
)) {
346 if (--cancount
<= 0) {
349 switch (c
= readline(1)) {
354 /* **** FALL THRU TO **** */
360 if (--cancount
<= 0) {
365 /* **** FALL THRU TO **** */
369 zperr("Garbage count exceeded");
372 if (eflag
&& ((c
&= 0177) & 0140))
380 case ZPAD
|0200: /* This is what we want. */
382 case ZPAD
: /* This is what we want. */
387 switch (c
= noxrd7()) {
395 case ZDLE
: /* This is what we want. */
399 switch (c
= noxrd7()) {
404 Rxframeind
= ZBIN
; Crc32
= FALSE
;
408 Crc32
= Rxframeind
= ZBIN32
;
412 Rxframeind
= ZHEX
; Crc32
= FALSE
;
420 Rxpos
= hdr
[ZP3
] & 0377;
421 Rxpos
= (Rxpos
<<8) + (hdr
[ZP2
] & 0377);
422 Rxpos
= (Rxpos
<<8) + (hdr
[ZP1
] & 0377);
423 Rxpos
= (Rxpos
<<8) + (hdr
[ZP0
] & 0377);
428 /* **** FALL THRU TO **** */
434 zperr("Got %s", frametypes
[c
+FTOFFSET
]);
435 /* **** FALL THRU TO **** */
437 if (c
>= -3 && c
<= FRTYPES
)
438 vfile("zgethdr: %s %lx", frametypes
[c
+FTOFFSET
], Rxpos
);
440 vfile("zgethdr: %d %lx", c
, Rxpos
);
445 /* Receive a binary style header (type and position) */
446 int zrbhdr(char *hdr
)
449 register unsigned short crc
;
451 if ((c
= zdlread()) & ~0377)
456 for (n
=4; --n
>= 0; ++hdr
) {
457 if ((c
= zdlread()) & ~0377)
459 crc
= updcrc(c
, crc
);
462 if ((c
= zdlread()) & ~0377)
464 crc
= updcrc(c
, crc
);
465 if ((c
= zdlread()) & ~0377)
467 crc
= updcrc(c
, crc
);
479 /* Receive a binary style header (type and position) with 32 bit FCS */
480 int zrbhdr32(char *hdr
)
483 register UNSL
long crc
;
485 if ((c
= zdlread()) & ~0377)
488 crc
= 0xFFFFFFFFL
; crc
= UPDC32(c
, crc
);
490 vfile("zrbhdr32 c=%X crc=%lX", c
, crc
);
493 for (n
=4; --n
>= 0; ++hdr
) {
494 if ((c
= zdlread()) & ~0377)
496 crc
= UPDC32(c
, crc
);
499 vfile("zrbhdr32 c=%X crc=%lX", c
, crc
);
502 for (n
=4; --n
>= 0;) {
503 if ((c
= zdlread()) & ~0377)
505 crc
= UPDC32(c
, crc
);
507 vfile("zrbhdr32 c=%X crc=%lX", c
, crc
);
510 if (crc
!= 0xDEBB20E3) {
522 /* Receive a hex style header (type and position) */
523 int zrhhdr(char *hdr
)
526 register unsigned short crc
;
529 if ((c
= zgethex()) < 0)
534 for (n
=4; --n
>= 0; ++hdr
) {
535 if ((c
= zgethex()) < 0)
537 crc
= updcrc(c
, crc
);
540 if ((c
= zgethex()) < 0)
542 crc
= updcrc(c
, crc
);
543 if ((c
= zgethex()) < 0)
545 crc
= updcrc(c
, crc
);
547 zperr(badcrc
); return ERROR
;
549 switch ( c
= readline(1)) {
552 /* **** FALL THRU TO **** */
554 /* Throw away possible cr/lf */
555 switch (c
= readline(1)) {
563 Zmodem
= 1; return Rxtype
;
566 /* Send a byte as two hex digits */
569 static char digits
[] = "0123456789abcdef";
572 vfile("zputhex: %02X", c
);
573 sendline(digits
[(c
&0xF0)>>4]);
574 sendline(digits
[(c
)&0xF]);
578 * Send character c with ZMODEM escape sequence encoding.
579 * Escape XON, XOFF. Escape CR following @ (Telenet net escape)
581 void zsendline(int c
)
584 /* Quick check for non control characters */
586 xsendline(lastsent
= c
);
591 xsendline (lastsent
= (c
^= 0100));
595 if (!Zctlesc
&& (lastsent
& 0177) != '@')
597 /* **** FALL THRU TO **** */
607 xsendline(lastsent
= c
);
610 if (Zctlesc
&& ! (c
& 0140)) {
614 xsendline(lastsent
= c
);
619 /* Decode two lower case hex digits into an 8 bit byte value */
626 vfile("zgethex: %02X", c
);
633 if ((c
= noxrd7()) < 0)
640 if ((c
= noxrd7()) < 0)
652 * Read a byte, checking for ZMODEM escape encoding
653 * including CAN*5 which represents a quick abort
660 /* Quick check for non control characters */
661 if ((c
= readline(Rxtimeout
)) & 0140)
672 if (Zctlesc
&& !(c
& 0140)) {
678 if ((c
= readline(Rxtimeout
)) < 0)
680 if (c
== CAN
&& (c
= readline(Rxtimeout
)) < 0)
682 if (c
== CAN
&& (c
= readline(Rxtimeout
)) < 0)
684 if (c
== CAN
&& (c
= readline(Rxtimeout
)) < 0)
704 if (Zctlesc
&& ! (c
& 0140)) {
707 if ((c
& 0140) == 0100)
712 zperr("Bad escape sequence %x", c
);
717 * Read a character from the modem line with timeout.
718 * Eat parity, XON and XOFF characters.
725 if ((c
= readline(Rxtimeout
)) < 0)
732 if (Zctlesc
&& !(c
& 0140))
742 /* Store long integer pos in Txhdr */
743 void stohdr(long pos
)
747 Txhdr
[ZP2
] = pos
>>16;
748 Txhdr
[ZP3
] = pos
>>24;
751 /* Recover a long integer from a header */
757 l
= (hdr
[ZP3
] & 0377);
758 l
= (l
<< 8) | (hdr
[ZP2
] & 0377);
759 l
= (l
<< 8) | (hdr
[ZP1
] & 0377);
760 l
= (l
<< 8) | (hdr
[ZP0
] & 0377);