xref: /rk3399_rockchip-uboot/common/zm.c (revision f8a983e5965e95c7c6bf3eb71de1a91cf440843c)
1 /*
2   zm.c - zmodem protocol handling lowlevelstuff
3   Copyright (C) until 1998 Chuck Forsberg (OMEN Technology Inc)
4   Copyright (C) 1996, 1997 Uwe Ohse
5 
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 
21   originally written by Chuck Forsberg
22 */
23 /* historical comment: -- uwe
24  *   Z M . C
25  *    ZMODEM protocol primitives
26  *    05-09-88  Chuck Forsberg Omen Technology Inc
27  *
28  * Entry point Functions:
29  *	zsbhdr(type, hdr) send binary header
30  *	zshhdr(type, hdr) send hex header
31  *	zgethdr(hdr, eflag) receive header - binary or hex
32  *	zsdata(buf, len, frameend) send data
33  *	zrdata(buf, len, bytes_received) receive data
34  *	stohdr(pos) store position data in Txhdr
35  *	long rclhdr(hdr) recover position offset from header
36  */
37 
38 
39 #include "zglobal.h"
40 
41 #include <stdio.h>
42 
43 unsigned int Rxtimeout = 100;		/* Tenths of seconds to wait for something */
44 
45 /* Globals used by ZMODEM functions */
46 int Rxframeind;		/* ZBIN ZBIN32, or ZHEX type of frame received */
47 int Rxtype;		/* Type of header received */
48 char Rxhdr[4];		/* Received header */
49 char Txhdr[4];		/* Transmitted header */
50 long Txpos;		/* Transmitted file position */
51 int Txfcs32;		/* TRUE means send binary frames with 32 bit FCS */
52 int Crc32t;		/* Display flag indicating 32 bit CRC being sent */
53 int Crc32;		/* Display flag indicating 32 bit CRC being received */
54 int Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
55 char Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
56 
57 static char lastsent;	/* Last char we sent */
58 int turbo_escape;
59 int bytes_per_error=0;
60 
61 static const char *frametypes[] = {
62 	"Carrier Lost",		/* -3 */
63 	"TIMEOUT",		/* -2 */
64 	"ERROR",		/* -1 */
65 #define FTOFFSET 3
66 	"ZRQINIT",
67 	"ZRINIT",
68 	"ZSINIT",
69 	"ZACK",
70 	"ZFILE",
71 	"ZSKIP",
72 	"ZNAK",
73 	"ZABORT",
74 	"ZFIN",
75 	"ZRPOS",
76 	"ZDATA",
77 	"ZEOF",
78 	"ZFERR",
79 	"ZCRC",
80 	"ZCHALLENGE",
81 	"ZCOMPL",
82 	"ZCAN",
83 	"ZFREECNT",
84 	"ZCOMMAND",
85 	"ZSTDERR",
86 	"xxxxx"
87 #define FRTYPES 22	/* Total number of frame types in this array */
88 			/*  not including psuedo negative entries */
89 };
90 
91 #define badcrc _("Bad CRC")
92 /* static char *badcrc = "Bad CRC"; */
93 static inline int noxrd7 __P ((void));
94 static inline int zdlread __P ((void));
95 static int zdlread2 __P ((int)) LRZSZ_ATTRIB_REGPARM(1);
96 static inline int zgeth1 __P ((void));
97 static void zputhex __P ((int c, char *pos));
98 static inline int zgethex __P ((void));
99 static int zrbhdr __P ((char *hdr));
100 static int zrbhdr32 __P ((char *hdr));
101 static int zrhhdr __P ((char *hdr));
102 static char zsendline_tab[256];
103 static int zrdat32 __P ((char *buf, int length, size_t *));
104 static void zsbh32 __P ((char *hdr, int type));
105 
106 extern int zmodem_requested;
107 
108 
109 /*
110  * Read a character from the modem line with timeout.
111  *  Eat parity, XON and XOFF characters.
112  */
113 static inline int
114 noxrd7(void)
115 {
116 	register int c;
117 
118 	for (;;) {
119 		if ((c = READLINE_PF(Rxtimeout)) < 0)
120 			return c;
121 		switch (c &= 0177) {
122 		case XON:
123 		case XOFF:
124 			continue;
125 		default:
126 			if (Zctlesc && !(c & 0140))
127 				continue;
128 		case '\r':
129 		case '\n':
130 		case ZDLE:
131 			return c;
132 		}
133 	}
134 }
135 
136 static inline int
137 zgeth1(void)
138 {
139 	register int c, n;
140 
141 	if ((c = noxrd7()) < 0)
142 		return c;
143 	n = c - '0';
144 	if (n > 9)
145 		n -= ('a' - ':');
146 	if (n & ~0xF)
147 		return ERROR;
148 	if ((c = noxrd7()) < 0)
149 		return c;
150 	c -= '0';
151 	if (c > 9)
152 		c -= ('a' - ':');
153 	if (c & ~0xF)
154 		return ERROR;
155 	c += (n<<4);
156 	return c;
157 }
158 
159 /* Decode two lower case hex digits into an 8 bit byte value */
160 static inline int
161 zgethex(void)
162 {
163 	register int c;
164 
165 	c = zgeth1();
166 	VPRINTF(9,("zgethex: %02X", c));
167 	return c;
168 }
169 
170 /*
171  * Read a byte, checking for ZMODEM escape encoding
172  *  including CAN*5 which represents a quick abort
173  */
174 static inline int
175 zdlread(void)
176 {
177 	int c;
178 	/* Quick check for non control characters */
179 	if ((c = READLINE_PF(Rxtimeout)) & 0140)
180 		return c;
181 	return zdlread2(c);
182 }
183 /* no, i don't like gotos. -- uwe */
184 static int
185 zdlread2(int c)
186 {
187 	goto jump_over; /* bad style */
188 
189 again:
190 	/* Quick check for non control characters */
191 	if ((c = READLINE_PF(Rxtimeout)) & 0140)
192 		return c;
193 jump_over:
194 	switch (c) {
195 	case ZDLE:
196 		break;
197 	case XON:
198 	case (XON|0200):
199 	case XOFF:
200 	case (XOFF|0200):
201 		goto again;
202 	default:
203 		if (Zctlesc && !(c & 0140)) {
204 			goto again;
205 		}
206 		return c;
207 	}
208 again2:
209 	if ((c = READLINE_PF(Rxtimeout)) < 0)
210 		return c;
211 	if (c == CAN && (c = READLINE_PF(Rxtimeout)) < 0)
212 		return c;
213 	if (c == CAN && (c = READLINE_PF(Rxtimeout)) < 0)
214 		return c;
215 	if (c == CAN && (c = READLINE_PF(Rxtimeout)) < 0)
216 		return c;
217 	switch (c) {
218 	case CAN:
219 		return GOTCAN;
220 	case ZCRCE:
221 	case ZCRCG:
222 	case ZCRCQ:
223 	case ZCRCW:
224 		return (c | GOTOR);
225 	case ZRUB0:
226 		return 0177;
227 	case ZRUB1:
228 		return 0377;
229 	case XON:
230 	case (XON|0200):
231 	case XOFF:
232 	case (XOFF|0200):
233 		goto again2;
234 	default:
235 		if (Zctlesc && ! (c & 0140)) {
236 			goto again2;
237 		}
238 		if ((c & 0140) ==  0100)
239 			return (c ^ 0100);
240 		break;
241 	}
242 	VPRINTF(2,(_("Bad escape sequence %x"), c));
243 	return ERROR;
244 }
245 
246 
247 
248 /*
249  * Send character c with ZMODEM escape sequence encoding.
250  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
251  */
252 inline void
253 zsendline(int c)
254 {
255 
256 	switch(zsendline_tab[(unsigned) (c&=0377)])
257 	{
258 	case 0:
259 		xsendline(lastsent = c);
260 		break;
261 	case 1:
262 		xsendline(ZDLE);
263 		c ^= 0100;
264 		xsendline(lastsent = c);
265 		break;
266 	case 2:
267 		if ((lastsent & 0177) != '@') {
268 			xsendline(lastsent = c);
269 		} else {
270 			xsendline(ZDLE);
271 			c ^= 0100;
272 			xsendline(lastsent = c);
273 		}
274 		break;
275 	}
276 }
277 
278 static inline void
279 zsendline_s(const char *s, size_t count)
280 {
281 	const char *end=s+count;
282 	while(s!=end) {
283 		int last_esc=0;
284 		const char *t=s;
285 		while (t!=end) {
286 			last_esc=zsendline_tab[(unsigned) ((*t) & 0377)];
287 			if (last_esc)
288 				break;
289 			t++;
290 		}
291 		if (t!=s) {
292 			//fwrite(s,(size_t)(t-s),1,stdout);
293 			send_data(1, s, t-s);
294 			lastsent=t[-1];
295 			s=t;
296 		}
297 		if (last_esc) {
298 			int c=*s;
299 			switch(last_esc) {
300 			case 0:
301 				xsendline(lastsent = c);
302 				break;
303 			case 1:
304 				xsendline(ZDLE);
305 				c ^= 0100;
306 				xsendline(lastsent = c);
307 				break;
308 			case 2:
309 				if ((lastsent & 0177) != '@') {
310 					xsendline(lastsent = c);
311 				} else {
312 					xsendline(ZDLE);
313 					c ^= 0100;
314 					xsendline(lastsent = c);
315 				}
316 				break;
317 			}
318 			s++;
319 		}
320 	}
321 }
322 
323 
324 /* Send ZMODEM binary header hdr of type type */
325 void
326 zsbhdr(int type, char *hdr)
327 {
328 	register int n;
329 	register unsigned short crc;
330 
331 	VPRINTF(3,("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr)));
332 	if (type == ZDATA)
333 		for (n = Znulls; --n >=0; )
334 			xsendline(0);
335 
336 	xsendline(ZPAD); xsendline(ZDLE);
337 
338 	Crc32t=Txfcs32;
339 	if (Crc32t)
340 		zsbh32(hdr, type);
341 	else {
342 		xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
343 
344 		for (n=4; --n >= 0; ++hdr) {
345 			zsendline(*hdr);
346 			crc = updcrc((0377& *hdr), crc);
347 		}
348 		crc = updcrc(0,updcrc(0,crc));
349 		zsendline(crc>>8);
350 		zsendline(crc);
351 	}
352 	if (type != ZDATA)
353 		flushmo();
354 }
355 
356 
357 /* Send ZMODEM binary header hdr of type type */
358 static void
359 zsbh32(char *hdr, int type)
360 {
361 	register int n;
362 	register unsigned long crc;
363 
364 	xsendline(ZBIN32);  zsendline(type);
365 	crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
366 
367 	for (n=4; --n >= 0; ++hdr) {
368 		crc = UPDC32((0377 & *hdr), crc);
369 		zsendline(*hdr);
370 	}
371 	crc = ~crc;
372 	for (n=4; --n >= 0;) {
373 		zsendline((int)crc);
374 		crc >>= 8;
375 	}
376 }
377 
378 /* Send ZMODEM HEX header hdr of type type */
379 void
380 zshhdr(int type, char *hdr)
381 {
382 	register int n;
383 	register unsigned short crc;
384 	char s[30];
385 	size_t len;
386 
387 	VPRINTF(3,("zshhdr: %s %lx", frametypes[(type & 0x7f)+FTOFFSET], rclhdr(hdr)));
388 	s[0]=ZPAD;
389 	s[1]=ZPAD;
390 	s[2]=ZDLE;
391 	s[3]=ZHEX;
392 	zputhex(type & 0x7f ,s+4);
393 	len=6;
394 	Crc32t = 0;
395 
396 	crc = updcrc((type & 0x7f), 0);
397 	for (n=4; --n >= 0; ++hdr) {
398 		zputhex(*hdr,s+len);
399 		len += 2;
400 		crc = updcrc((0377 & *hdr), crc);
401 	}
402 	crc = updcrc(0,updcrc(0,crc));
403 	zputhex(crc>>8,s+len);
404 	zputhex(crc,s+len+2);
405 	len+=4;
406 
407 	/* Make it printable on remote machine */
408 	s[len++]=015;
409 	s[len++]=0212;
410 	/*
411 	 * Uncork the remote in case a fake XOFF has stopped data flow
412 	 */
413 	if (type != ZFIN && type != ZACK)
414 	{
415 		s[len++]=021;
416 	}
417 	flushmo();
418 	send_data(1,s,len);
419 }
420 
421 /*
422  * Send binary array buf of length length, with ending ZDLE sequence frameend
423  */
424 static const char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
425 void
426 zsdata(const char *buf, size_t length, int frameend)
427 {
428 	register unsigned short crc;
429 
430 	VPRINTF(3,("zsdata: %lu %s", (unsigned long) length,
431 		Zendnames[(frameend-ZCRCE)&3]));
432 	crc = 0;
433 	do {
434 		zsendline(*buf); crc = updcrc((0377 & *buf), crc);
435 		buf++;
436 	} while (--length>0);
437 	xsendline(ZDLE); xsendline(frameend);
438 	crc = updcrc(frameend, crc);
439 
440 	crc = updcrc(0,updcrc(0,crc));
441 	zsendline(crc>>8); zsendline(crc);
442 	if (frameend == ZCRCW) {
443 		xsendline(XON);  flushmo();
444 	}
445 }
446 
447 void
448 zsda32(const char *buf, size_t length, int frameend)
449 {
450 	int c;
451 	unsigned long crc;
452 	int i;
453 	VPRINTF(3,("zsdat32: %d %s", length, Zendnames[(frameend-ZCRCE)&3]));
454 
455 	crc = 0xFFFFFFFFL;
456 	zsendline_s(buf,length);
457 	for (; length; length--) {
458 		c = *buf & 0377;
459 		crc = UPDC32(c, crc);
460 		buf++;
461 	}
462 	xsendline(ZDLE); xsendline(frameend);
463 	crc = UPDC32(frameend, crc);
464 
465 	crc = ~crc;
466 	for (i=4; --i >= 0;) {
467 		c=(int) crc;
468 		if (c & 0140)
469 			xsendline(lastsent = c);
470 		else
471 			zsendline(c);
472 		crc >>= 8;
473 	}
474 	if (frameend == ZCRCW) {
475 		xsendline(XON);  flushmo();
476 	}
477 }
478 
479 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ <= 4)
480 #  undef DEBUG_BLOCKSIZE
481 #endif
482 
483 #ifdef DEBUG_BLOCKSIZE
484 struct debug_blocksize {
485 	int size;
486 	long count;
487 };
488 struct debug_blocksize blocksizes[]={
489 	{32,0},
490 	{64,0},
491 	{128,0},
492 	{256,0},
493 	{512,0},
494 	{1024,0},
495 	{2048,0},
496 	{4096,0},
497 	{8192,0},
498 	{0,0}
499 };
500 static inline void
501 count_blk(int size)
502 {
503 	int i;
504 	for (i=0;blocksizes[i].size;i++) {
505 		if (blocksizes[i].size==size) {
506 			blocksizes[i].count++;
507 			return;
508 		}
509 	}
510 	blocksizes[i].count++;
511 }
512 
513 static void printout_blocksizes(void) __attribute__((__destructor__));
514 static void
515 printout_blocksizes(void)
516 {
517 	int i;
518 	for (i=0;blocksizes[i].size;i++) {
519 		if (blocksizes[i].count) {
520 			lsyslog(LOG_DEBUG,"%4d byte: %ld blocks\n",
521 				   blocksizes[i].size,blocksizes[i].count);
522 		}
523 	}
524 	if (blocksizes[i].count) {
525 		lsyslog(LOG_DEBUG,"unk. byte: %ld blocks",
526 			   blocksizes[i].count);
527 	}
528 }
529 #define COUNT_BLK(x) count_blk(x)
530 #else
531 #define COUNT_BLK(x)
532 #endif
533 
534 /*
535  * Receive array buf of max length with ending ZDLE sequence
536  *  and CRC.  Returns the ending character or error code.
537  *  NB: On errors may store length+1 bytes!
538  */
539 int
540 zrdata(char *buf, int length, size_t *bytes_received)
541 {
542 	register int c;
543 	register unsigned short crc;
544 	register char *end;
545 	register int d;
546 
547 	*bytes_received=0;
548 	if (Rxframeind == ZBIN32)
549 		return zrdat32(buf, length, bytes_received);
550 
551 	crc = 0;  end = buf + length;
552 	while (buf <= end) {
553 		if ((c = zdlread()) & ~0377) {
554 crcfoo:
555 			switch (c) {
556 			case GOTCRCE:
557 			case GOTCRCG:
558 			case GOTCRCQ:
559 			case GOTCRCW:
560 				{
561 					d = c;
562 					c &= 0377;
563 					crc = updcrc(c, crc);
564 					if ((c = zdlread()) & ~0377)
565 						goto crcfoo;
566 					crc = updcrc(c, crc);
567 					if ((c = zdlread()) & ~0377)
568 						goto crcfoo;
569 					crc = updcrc(c, crc);
570 					if (crc & 0xFFFF) {
571 						zperr(badcrc);
572 						return ERROR;
573 					}
574 					*bytes_received = length - (end - buf);
575 					COUNT_BLK(*bytes_received);
576 					VPRINTF(3,("zrdata: %lu  %s", (unsigned long) (*bytes_received),
577 							Zendnames[(d-GOTCRCE)&3]));
578 					return d;
579 				}
580 			case GOTCAN:
581 				zperr(_("Sender Canceled"));
582 				return ZCAN;
583 			case TIMEOUT:
584 				zperr(_("TIMEOUT"));
585 				return c;
586 			default:
587 				zperr(_("Bad data subpacket"));
588 				return c;
589 			}
590 		}
591 		*buf++ = c;
592 		crc = updcrc(c, crc);
593 	}
594 	zperr(_("Data subpacket too long"));
595 	return ERROR;
596 }
597 
598 static int
599 zrdat32(char *buf, int length, size_t *bytes_received)
600 {
601 	register int c;
602 	register unsigned long crc;
603 	register char *end;
604 	register int d;
605 
606 	crc = 0xFFFFFFFFL;  end = buf + length;
607 	while (buf <= end) {
608 		if ((c = zdlread()) & ~0377) {
609 crcfoo:
610 			switch (c) {
611 			case GOTCRCE:
612 			case GOTCRCG:
613 			case GOTCRCQ:
614 			case GOTCRCW:
615 				d = c;
616 				c &= 0377;
617 				crc = UPDC32(c, crc);
618 				if ((c = zdlread()) & ~0377)
619 					goto crcfoo;
620 				crc = UPDC32(c, crc);
621 				if ((c = zdlread()) & ~0377)
622 					goto crcfoo;
623 				crc = UPDC32(c, crc);
624 				if ((c = zdlread()) & ~0377)
625 					goto crcfoo;
626 				crc = UPDC32(c, crc);
627 				if ((c = zdlread()) & ~0377)
628 					goto crcfoo;
629 				crc = UPDC32(c, crc);
630 				if (crc != 0xDEBB20E3) {
631 					zperr(badcrc);
632 					return ERROR;
633 				}
634 				*bytes_received = length - (end - buf);
635 				COUNT_BLK(*bytes_received);
636 				VPRINTF(3,("zrdat32: %lu %s", (unsigned long) *bytes_received,
637 					Zendnames[(d-GOTCRCE)&3]));
638 				return d;
639 			case GOTCAN:
640 				zperr(_("Sender Canceled"));
641 				return ZCAN;
642 			case TIMEOUT:
643 				zperr(_("TIMEOUT"));
644 				return c;
645 			default:
646 				zperr(_("Bad data subpacket"));
647 				return c;
648 			}
649 		}
650 		*buf++ = c;
651 		crc = UPDC32(c, crc);
652 	}
653 	zperr(_("Data subpacket too long"));
654 	return ERROR;
655 }
656 
657 /*
658  * Read a ZMODEM header to hdr, either binary or hex.
659  *  eflag controls local display of non zmodem characters:
660  *	0:  no display
661  *	1:  display printing characters only
662  *	2:  display all non ZMODEM characters
663  *  On success, set Zmodem to 1, set Rxpos and return type of header.
664  *   Otherwise return negative on error.
665  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
666  */
667 int
668 zgethdr(char *hdr, int eflag, size_t *Rxpos)
669 {
670 	register int c, cancount;
671 	unsigned int max_garbage; /* Max bytes before start of frame */
672 	size_t rxpos=0; /* keep gcc happy */
673 
674 	max_garbage = Zrwindow + Baudrate;
675 	Rxframeind = Rxtype = 0;
676 
677 startover:
678 	cancount = 5;
679 again:
680 	/* Return immediate ERROR if ZCRCW sequence seen */
681 	switch (c = READLINE_PF(Rxtimeout)) {
682 	case RCDO:
683 	case TIMEOUT:
684 		goto fifi;
685 	case CAN:
686 gotcan:
687 		if (--cancount <= 0) {
688 			c = ZCAN; goto fifi;
689 		}
690 		switch (c = READLINE_PF(1)) {
691 		case TIMEOUT:
692 			goto again;
693 		case ZCRCW:
694 			c = ERROR;
695 		/* **** FALL THRU TO **** */
696 		case RCDO:
697 			goto fifi;
698 		default:
699 			break;
700 		case CAN:
701 			if (--cancount <= 0) {
702 				c = ZCAN; goto fifi;
703 			}
704 			goto again;
705 		}
706 	/* **** FALL THRU TO **** */
707 	default:
708 agn2:
709 		if ( --max_garbage == 0) {
710 			zperr(_("Garbage count exceeded"));
711 			return(ERROR);
712 		}
713 		//if (eflag && ((c &= 0177) & 0140) && Verbose)
714 		//	vchar(c);
715 		//else if (eflag > 1 && Verbose)
716 		//	vchar(c);
717 		goto startover;
718 	case ZPAD|0200:		/* This is what we want. */
719 	case ZPAD:		/* This is what we want. */
720 		break;
721 	}
722 	cancount = 5;
723 splat:
724 	switch (c = noxrd7()) {
725 	case ZPAD:
726 		goto splat;
727 	case RCDO:
728 	case TIMEOUT:
729 		goto fifi;
730 	default:
731 		goto agn2;
732 	case ZDLE:		/* This is what we want. */
733 		break;
734 	}
735 
736 	switch (c = noxrd7()) {
737 	case RCDO:
738 	case TIMEOUT:
739 		goto fifi;
740 	case ZBIN:
741 		Rxframeind = ZBIN;  Crc32 = FALSE;
742 		c =  zrbhdr(hdr);
743 		break;
744 	case ZBIN32:
745 		Crc32 = Rxframeind = ZBIN32;
746 		c =  zrbhdr32(hdr);
747 		break;
748 	case ZHEX:
749 		Rxframeind = ZHEX;  Crc32 = FALSE;
750 		c =  zrhhdr(hdr);
751 		break;
752 	case CAN:
753 		goto gotcan;
754 	default:
755 		goto agn2;
756 	}
757 	rxpos = hdr[ZP3] & 0377;
758 	rxpos = (rxpos<<8) + (hdr[ZP2] & 0377);
759 	rxpos = (rxpos<<8) + (hdr[ZP1] & 0377);
760 	rxpos = (rxpos<<8) + (hdr[ZP0] & 0377);
761 fifi:
762 	switch (c) {
763 	case GOTCAN:
764 		c = ZCAN;
765 	/* **** FALL THRU TO **** */
766 	case ZNAK:
767 	case ZCAN:
768 	case ERROR:
769 	case TIMEOUT:
770 	case RCDO:
771 		zperr(_("Got %s"), frametypes[c+FTOFFSET]);
772 	/* **** FALL THRU TO **** */
773 	default:
774 		if (c >= -3 && c <= FRTYPES)
775 			VPRINTF(3,("zgethdr: %s %lx", frametypes[c+FTOFFSET], (unsigned long) rxpos));
776 		else
777 			VPRINTF(3,("zgethdr: %d %lx", c, (unsigned long) rxpos));
778 	}
779 	if (Rxpos)
780 		*Rxpos=rxpos;
781 	return c;
782 }
783 
784 /* Receive a binary style header (type and position) */
785 static int
786 zrbhdr(char *hdr)
787 {
788 	register int c, n;
789 	register unsigned short crc;
790 
791 	if ((c = zdlread()) & ~0377)
792 		return c;
793 	Rxtype = c;
794 	crc = updcrc(c, 0);
795 
796 	for (n=4; --n >= 0; ++hdr) {
797 		if ((c = zdlread()) & ~0377)
798 			return c;
799 		crc = updcrc(c, crc);
800 		*hdr = c;
801 	}
802 	if ((c = zdlread()) & ~0377)
803 		return c;
804 	crc = updcrc(c, crc);
805 	if ((c = zdlread()) & ~0377)
806 		return c;
807 	crc = updcrc(c, crc);
808 	if (crc & 0xFFFF) {
809 		zperr(badcrc);
810 		return ERROR;
811 	}
812 	protocol = ZM_ZMODEM;
813 	zmodem_requested=TRUE;
814 	return Rxtype;
815 }
816 
817 /* Receive a binary style header (type and position) with 32 bit FCS */
818 static int
819 zrbhdr32(char *hdr)
820 {
821 	register int c, n;
822 	register unsigned long crc;
823 
824 	if ((c = zdlread()) & ~0377)
825 		return c;
826 	Rxtype = c;
827 	crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
828 #ifdef DEBUGZ
829 	VPRINTF(3,("zrbhdr32 c=%X  crc=%lX", c, crc)i);
830 #endif
831 
832 	for (n=4; --n >= 0; ++hdr) {
833 		if ((c = zdlread()) & ~0377)
834 			return c;
835 		crc = UPDC32(c, crc);
836 		*hdr = c;
837 #ifdef DEBUGZ
838 		VPRINTF(3,("zrbhdr32 c=%X  crc=%lX", c, crc));
839 #endif
840 	}
841 	for (n=4; --n >= 0;) {
842 		if ((c = zdlread()) & ~0377)
843 			return c;
844 		crc = UPDC32(c, crc);
845 #ifdef DEBUGZ
846 		VPRINTF(3,("zrbhdr32 c=%X  crc=%lX", c, crc));
847 #endif
848 	}
849 	if (crc != 0xDEBB20E3) {
850 		zperr(badcrc);
851 		return ERROR;
852 	}
853 	protocol = ZM_ZMODEM;
854 	zmodem_requested=TRUE;
855 	return Rxtype;
856 }
857 
858 
859 /* Receive a hex style header (type and position) */
860 static int
861 zrhhdr(char *hdr)
862 {
863 	register int c;
864 	register unsigned short crc;
865 	register int n;
866 
867 	if ((c = zgethex()) < 0)
868 		return c;
869 	Rxtype = c;
870 	crc = updcrc(c, 0);
871 
872 	for (n=4; --n >= 0; ++hdr) {
873 		if ((c = zgethex()) < 0)
874 			return c;
875 		crc = updcrc(c, crc);
876 		*hdr = c;
877 	}
878 	if ((c = zgethex()) < 0)
879 		return c;
880 	crc = updcrc(c, crc);
881 	if ((c = zgethex()) < 0)
882 		return c;
883 	crc = updcrc(c, crc);
884 	if (crc & 0xFFFF) {
885 		zperr(badcrc); return ERROR;
886 	}
887 	switch ( c = READLINE_PF(1)) {
888 	case 0215:
889 		/* **** FALL THRU TO **** */
890 	case 015:
891 	 	/* Throw away possible cr/lf */
892 		READLINE_PF(1);
893 		break;
894 	}
895 	protocol = ZM_ZMODEM;
896 	zmodem_requested=TRUE;
897 	return Rxtype;
898 }
899 
900 /* Write a byte as two hex digits */
901 static void
902 zputhex(int c, char *pos)
903 {
904 	static char	digits[]	= "0123456789abcdef";
905 
906 	VPRINTF(9,("zputhex: %02X", c));
907 	pos[0]=digits[(c&0xF0)>>4];
908 	pos[1]=digits[c&0x0F];
909 }
910 
911 void
912 zsendline_init(void)
913 {
914 	int i;
915 	for (i=0;i<256;i++) {
916 		if (i & 0140)
917 			zsendline_tab[i]=0;
918 		else {
919 			switch(i)
920 			{
921 			case ZDLE:
922 			case XOFF: /* ^Q */
923 			case XON: /* ^S */
924 			case (XOFF | 0200):
925 			case (XON | 0200):
926 				zsendline_tab[i]=1;
927 				break;
928 			case 020: /* ^P */
929 			case 0220:
930 				if (turbo_escape)
931 					zsendline_tab[i]=0;
932 				else
933 					zsendline_tab[i]=1;
934 				break;
935 			case 015:
936 			case 0215:
937 				if (Zctlesc)
938 					zsendline_tab[i]=1;
939 				else if (!turbo_escape)
940 					zsendline_tab[i]=2;
941 				else
942 					zsendline_tab[i]=0;
943 				break;
944 			default:
945 				if (Zctlesc)
946 					zsendline_tab[i]=1;
947 				else
948 					zsendline_tab[i]=0;
949 			}
950 		}
951 	}
952 }
953 
954 
955 
956 /* Store pos in Txhdr */
957 void
958 stohdr(size_t pos)
959 {
960 	long lpos=(long) pos;
961 	Txhdr[ZP0] = lpos;
962 	Txhdr[ZP1] = lpos>>8;
963 	Txhdr[ZP2] = lpos>>16;
964 	Txhdr[ZP3] = lpos>>24;
965 }
966 
967 /* Recover a long integer from a header */
968 long
969 rclhdr(char *hdr)
970 {
971 	long l;
972 
973 	l = (hdr[ZP3] & 0377);
974 	l = (l << 8) | (hdr[ZP2] & 0377);
975 	l = (l << 8) | (hdr[ZP1] & 0377);
976 	l = (l << 8) | (hdr[ZP0] & 0377);
977 	return l;
978 }
979 
980 /* End of zm.c */
981