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 lastsent
; /* Last char we sent */
41 static 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(type
, hdr
)
81 register unsigned short crc
;
83 vfile("zsbhdr: %s %lx", frametypes
[type
+FTOFFSET
], rclhdr(hdr
));
85 for (n
= Znulls
; --n
>=0; )
88 xsendline(ZPAD
); xsendline(ZDLE
);
93 xsendline(ZBIN
); zsendline(type
); crc
= updcrc(type
, 0);
95 for (n
=4; --n
>= 0; ++hdr
) {
97 crc
= updcrc((0377& *hdr
), crc
);
99 crc
= updcrc(0,updcrc(0,crc
));
108 /* Send ZMODEM binary header hdr of type type */
109 void zsbh32(hdr
, type
)
114 register UNSL
long crc
;
116 xsendline(ZBIN32
); zsendline(type
);
117 crc
= 0xFFFFFFFFL
; crc
= UPDC32(type
, crc
);
119 for (n
=4; --n
>= 0; ++hdr
) {
120 crc
= UPDC32((0377 & *hdr
), crc
);
124 for (n
=4; --n
>= 0;) {
130 /* Send ZMODEM HEX header hdr of type type */
131 void zshhdr(type
, hdr
)
136 register unsigned short crc
;
138 vfile("zshhdr: %s %lx", frametypes
[type
+FTOFFSET
], rclhdr(hdr
));
139 sendline(ZPAD
); sendline(ZPAD
); sendline(ZDLE
); sendline(ZHEX
);
143 crc
= updcrc(type
, 0);
144 for (n
=4; --n
>= 0; ++hdr
) {
145 zputhex(*hdr
); crc
= updcrc((0377 & *hdr
), crc
);
147 crc
= updcrc(0,updcrc(0,crc
));
148 zputhex(crc
>>8); zputhex(crc
);
150 /* Make it printable on remote machine */
151 sendline(015); sendline(0212);
153 * Uncork the remote in case a fake XOFF has stopped data flow
155 if (type
!= ZFIN
&& type
!= ZACK
)
161 * Send binary array buf of length length, with ending ZDLE sequence frameend
163 static char *Zendnames
[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
165 void zsdata(buf
, length
, frameend
)
170 register unsigned short crc
;
172 vfile("zsdata: %d %s", length
, Zendnames
[(frameend
-ZCRCE
)&3]);
174 zsda32(buf
, length
, frameend
);
177 for (;--length
>= 0; ++buf
) {
178 zsendline(*buf
); crc
= updcrc((0377 & *buf
), crc
);
180 xsendline(ZDLE
); xsendline(frameend
);
181 crc
= updcrc(frameend
, crc
);
183 crc
= updcrc(0,updcrc(0,crc
));
184 zsendline(crc
>>8); zsendline(crc
);
186 if (frameend
== ZCRCW
) {
187 xsendline(XON
); flushmo();
191 void zsda32(buf
, length
, frameend
)
197 register UNSL
long crc
;
200 for (;--length
>= 0; ++buf
) {
203 xsendline(lastsent
= c
);
206 crc
= UPDC32(c
, crc
);
208 xsendline(ZDLE
); xsendline(frameend
);
209 crc
= UPDC32(frameend
, crc
);
212 for (length
=4; --length
>= 0;) {
213 zsendline((int)crc
); crc
>>= 8;
218 * Receive array buf of max length with ending ZDLE sequence
219 * and CRC. Returns the ending character or error code.
220 * NB: On errors may store length+1 bytes!
222 int zrdata(buf
, length
)
227 register unsigned short crc
;
231 if (Rxframeind
== ZBIN32
)
232 return zrdat32(buf
, length
);
234 crc
= Rxcount
= 0; end
= buf
+ length
;
236 if ((c
= zdlread()) & ~0377) {
243 crc
= updcrc((d
=c
)&0377, crc
);
244 if ((c
= zdlread()) & ~0377)
246 crc
= updcrc(c
, crc
);
247 if ((c
= zdlread()) & ~0377)
249 crc
= updcrc(c
, crc
);
254 Rxcount
= length
- (end
- buf
);
255 vfile("zrdata: %d %s", Rxcount
,
256 Zendnames
[(d
-GOTCRCE
)&3]);
259 zperr("Sender Canceled");
265 zperr("Bad data subpacket");
270 crc
= updcrc(c
, crc
);
272 zperr("Data subpacket too long");
276 int zrdat32(buf
, length
)
281 register UNSL
long crc
;
285 crc
= 0xFFFFFFFFL
; Rxcount
= 0; end
= buf
+ length
;
287 if ((c
= zdlread()) & ~0377) {
295 crc
= UPDC32(c
, crc
);
296 if ((c
= zdlread()) & ~0377)
298 crc
= UPDC32(c
, crc
);
299 if ((c
= zdlread()) & ~0377)
301 crc
= UPDC32(c
, crc
);
302 if ((c
= zdlread()) & ~0377)
304 crc
= UPDC32(c
, crc
);
305 if ((c
= zdlread()) & ~0377)
307 crc
= UPDC32(c
, crc
);
308 if (crc
!= 0xDEBB20E3) {
312 Rxcount
= length
- (end
- buf
);
313 vfile("zrdat32: %d %s", Rxcount
,
314 Zendnames
[(d
-GOTCRCE
)&3]);
317 zperr("Sender Canceled");
323 zperr("Bad data subpacket");
328 crc
= UPDC32(c
, crc
);
330 zperr("Data subpacket too long");
336 * Read a ZMODEM header to hdr, either binary or hex.
337 * eflag controls local display of non zmodem characters:
339 * 1: display printing characters only
340 * 2: display all non ZMODEM characters
341 * On success, set Zmodem to 1, set Rxpos and return type of header.
342 * Otherwise return negative on error.
343 * Return ERROR instantly if ZCRCW sequence, for fast error recovery.
345 int zgethdr(hdr
, eflag
)
349 register int c
, n
, cancount
;
351 n
= Zrwindow
+ Baudrate
; /* Max bytes before start of frame */
352 Rxframeind
= Rxtype
= 0;
357 /* Return immediate ERROR if ZCRCW sequence seen */
358 switch (c
= readline(Rxtimeout
)) {
364 if (--cancount
<= 0) {
367 switch (c
= readline(1)) {
372 /* **** FALL THRU TO **** */
378 if (--cancount
<= 0) {
383 /* **** FALL THRU TO **** */
387 zperr("Garbage count exceeded");
390 if (eflag
&& ((c
&= 0177) & 0140))
398 case ZPAD
|0200: /* This is what we want. */
400 case ZPAD
: /* This is what we want. */
405 switch (c
= noxrd7()) {
413 case ZDLE
: /* This is what we want. */
417 switch (c
= noxrd7()) {
422 Rxframeind
= ZBIN
; Crc32
= FALSE
;
426 Crc32
= Rxframeind
= ZBIN32
;
430 Rxframeind
= ZHEX
; Crc32
= FALSE
;
438 Rxpos
= hdr
[ZP3
] & 0377;
439 Rxpos
= (Rxpos
<<8) + (hdr
[ZP2
] & 0377);
440 Rxpos
= (Rxpos
<<8) + (hdr
[ZP1
] & 0377);
441 Rxpos
= (Rxpos
<<8) + (hdr
[ZP0
] & 0377);
446 /* **** FALL THRU TO **** */
452 zperr("Got %s", frametypes
[c
+FTOFFSET
]);
453 /* **** FALL THRU TO **** */
455 if (c
>= -3 && c
<= FRTYPES
)
456 vfile("zgethdr: %s %lx", frametypes
[c
+FTOFFSET
], Rxpos
);
458 vfile("zgethdr: %d %lx", c
, Rxpos
);
463 /* Receive a binary style header (type and position) */
468 register unsigned short crc
;
470 if ((c
= zdlread()) & ~0377)
475 for (n
=4; --n
>= 0; ++hdr
) {
476 if ((c
= zdlread()) & ~0377)
478 crc
= updcrc(c
, crc
);
481 if ((c
= zdlread()) & ~0377)
483 crc
= updcrc(c
, crc
);
484 if ((c
= zdlread()) & ~0377)
486 crc
= updcrc(c
, crc
);
498 /* Receive a binary style header (type and position) with 32 bit FCS */
503 register UNSL
long crc
;
505 if ((c
= zdlread()) & ~0377)
508 crc
= 0xFFFFFFFFL
; crc
= UPDC32(c
, crc
);
510 vfile("zrbhdr32 c=%X crc=%lX", c
, crc
);
513 for (n
=4; --n
>= 0; ++hdr
) {
514 if ((c
= zdlread()) & ~0377)
516 crc
= UPDC32(c
, crc
);
519 vfile("zrbhdr32 c=%X crc=%lX", c
, crc
);
522 for (n
=4; --n
>= 0;) {
523 if ((c
= zdlread()) & ~0377)
525 crc
= UPDC32(c
, crc
);
527 vfile("zrbhdr32 c=%X crc=%lX", c
, crc
);
530 if (crc
!= 0xDEBB20E3) {
542 /* Receive a hex style header (type and position) */
547 register unsigned short crc
;
550 if ((c
= zgethex()) < 0)
555 for (n
=4; --n
>= 0; ++hdr
) {
556 if ((c
= zgethex()) < 0)
558 crc
= updcrc(c
, crc
);
561 if ((c
= zgethex()) < 0)
563 crc
= updcrc(c
, crc
);
564 if ((c
= zgethex()) < 0)
566 crc
= updcrc(c
, crc
);
568 zperr(badcrc
); return ERROR
;
570 switch ( c
= readline(1)) {
573 /* **** FALL THRU TO **** */
575 /* Throw away possible cr/lf */
576 switch (c
= readline(1)) {
584 Zmodem
= 1; return Rxtype
;
587 /* Send a byte as two hex digits */
591 static char digits
[] = "0123456789abcdef";
594 vfile("zputhex: %02X", c
);
595 sendline(digits
[(c
&0xF0)>>4]);
596 sendline(digits
[(c
)&0xF]);
600 * Send character c with ZMODEM escape sequence encoding.
601 * Escape XON, XOFF. Escape CR following @ (Telenet net escape)
607 /* Quick check for non control characters */
609 xsendline(lastsent
= c
);
614 xsendline (lastsent
= (c
^= 0100));
618 if (!Zctlesc
&& (lastsent
& 0177) != '@')
620 /* **** FALL THRU TO **** */
630 xsendline(lastsent
= c
);
633 if (Zctlesc
&& ! (c
& 0140)) {
637 xsendline(lastsent
= c
);
642 /* Decode two lower case hex digits into an 8 bit byte value */
649 vfile("zgethex: %02X", c
);
656 if ((c
= noxrd7()) < 0)
663 if ((c
= noxrd7()) < 0)
675 * Read a byte, checking for ZMODEM escape encoding
676 * including CAN*5 which represents a quick abort
683 /* Quick check for non control characters */
684 if ((c
= readline(Rxtimeout
)) & 0140)
695 if (Zctlesc
&& !(c
& 0140)) {
701 if ((c
= readline(Rxtimeout
)) < 0)
703 if (c
== CAN
&& (c
= readline(Rxtimeout
)) < 0)
705 if (c
== CAN
&& (c
= readline(Rxtimeout
)) < 0)
707 if (c
== CAN
&& (c
= readline(Rxtimeout
)) < 0)
727 if (Zctlesc
&& ! (c
& 0140)) {
730 if ((c
& 0140) == 0100)
735 zperr("Bad escape sequence %x", c
);
740 * Read a character from the modem line with timeout.
741 * Eat parity, XON and XOFF characters.
748 if ((c
= readline(Rxtimeout
)) < 0)
755 if (Zctlesc
&& !(c
& 0140))
765 /* Store long integer pos in Txhdr */
771 Txhdr
[ZP2
] = pos
>>16;
772 Txhdr
[ZP3
] = pos
>>24;
775 /* Recover a long integer from a header */
782 l
= (hdr
[ZP3
] & 0377);
783 l
= (l
<< 8) | (hdr
[ZP2
] & 0377);
784 l
= (l
<< 8) | (hdr
[ZP1
] & 0377);
785 l
= (l
<< 8) | (hdr
[ZP0
] & 0377);