xref: /minix/minix/commands/zmodem/zm.c (revision 83133719)
1 /*
2  *   Z M . C
3  *    ZMODEM protocol primitives
4  *    05-09-88  Chuck Forsberg Omen Technology Inc
5  *
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
14  */
15 
16 #ifndef CANFDX
17 #include "zmodem.h"
18 #endif
19 int Rxtimeout = 100;		/* Tenths of seconds to wait for something */
20 
21 #ifndef UNSL
22 #define UNSL
23 #endif
24 
25 
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 */
39 
40 static int lastsent;	/* Last char we sent */
41 static int Not8bit;	/* Seven bits seen on header */
42 
43 static char *frametypes[] = {
44 	"Carrier Lost",		/* -3 */
45 	"TIMEOUT",		/* -2 */
46 	"ERROR",		/* -1 */
47 #define FTOFFSET 3
48 	"ZRQINIT",
49 	"ZRINIT",
50 	"ZSINIT",
51 	"ZACK",
52 	"ZFILE",
53 	"ZSKIP",
54 	"ZNAK",
55 	"ZABORT",
56 	"ZFIN",
57 	"ZRPOS",
58 	"ZDATA",
59 	"ZEOF",
60 	"ZFERR",
61 	"ZCRC",
62 	"ZCHALLENGE",
63 	"ZCOMPL",
64 	"ZCAN",
65 	"ZFREECNT",
66 	"ZCOMMAND",
67 	"ZSTDERR",
68 	"xxxxx"
69 #define FRTYPES 22	/* Total number of frame types in this array */
70 			/*  not including psuedo negative entries */
71 };
72 
73 static char badcrc[] = "Bad CRC";
74 
75 /* Send ZMODEM binary header hdr of type type */
76 void zsbhdr(int type, char *hdr)
77 {
78 	register int n;
79 	register unsigned short crc;
80 
81 	vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
82 	if (type == ZDATA)
83 		for (n = Znulls; --n >=0; )
84 			xsendline(0);
85 
86 	xsendline(ZPAD); xsendline(ZDLE);
87 
88 	if ((Crc32t=Txfcs32))
89 		zsbh32(hdr, type);
90 	else {
91 		xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
92 
93 		for (n=4; --n >= 0; ++hdr) {
94 			zsendline(*hdr);
95 			crc = updcrc((0377& *hdr), crc);
96 		}
97 		crc = updcrc(0,updcrc(0,crc));
98 		zsendline(crc>>8);
99 		zsendline(crc);
100 	}
101 	if (type != ZDATA)
102 		flushmo();
103 }
104 
105 
106 /* Send ZMODEM binary header hdr of type type */
107 void zsbh32(char *hdr, int type)
108 {
109 	register int n;
110 	register UNSL long crc;
111 
112 	xsendline(ZBIN32);  zsendline(type);
113 	crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
114 
115 	for (n=4; --n >= 0; ++hdr) {
116 		crc = UPDC32((0377 & *hdr), crc);
117 		zsendline(*hdr);
118 	}
119 	crc = ~crc;
120 	for (n=4; --n >= 0;) {
121 		zsendline((int)crc);
122 		crc >>= 8;
123 	}
124 }
125 
126 /* Send ZMODEM HEX header hdr of type type */
127 void zshhdr(int type, char *hdr)
128 {
129 	register int n;
130 	register unsigned short crc;
131 
132 	vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
133 	sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
134 	zputhex(type);
135 	Crc32t = 0;
136 
137 	crc = updcrc(type, 0);
138 	for (n=4; --n >= 0; ++hdr) {
139 		zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
140 	}
141 	crc = updcrc(0,updcrc(0,crc));
142 	zputhex(crc>>8); zputhex(crc);
143 
144 	/* Make it printable on remote machine */
145 	sendline(015); sendline(0212);
146 	/*
147 	 * Uncork the remote in case a fake XOFF has stopped data flow
148 	 */
149 	if (type != ZFIN && type != ZACK)
150 		sendline(021);
151 	flushmo();
152 }
153 
154 /*
155  * Send binary array buf of length length, with ending ZDLE sequence frameend
156  */
157 static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
158 
159 void zsdata(char *buf, int length, int frameend)
160 {
161 	register unsigned short crc;
162 
163 	vfile("zsdata: %d %s", length, Zendnames[(frameend-ZCRCE)&3]);
164 	if (Crc32t)
165 		zsda32(buf, length, frameend);
166 	else {
167 		crc = 0;
168 		for (;--length >= 0; ++buf) {
169 			zsendline(*buf); crc = updcrc((0377 & *buf), crc);
170 		}
171 		xsendline(ZDLE); xsendline(frameend);
172 		crc = updcrc(frameend, crc);
173 
174 		crc = updcrc(0,updcrc(0,crc));
175 		zsendline(crc>>8); zsendline(crc);
176 	}
177 	if (frameend == ZCRCW) {
178 		xsendline(XON);  flushmo();
179 	}
180 }
181 
182 void zsda32(char *buf, int length, int frameend)
183 {
184 	register int c;
185 	register UNSL long crc;
186 
187 	crc = 0xFFFFFFFFL;
188 	for (;--length >= 0; ++buf) {
189 		c = *buf & 0377;
190 		if (c & 0140)
191 			xsendline(lastsent = c);
192 		else
193 			zsendline(c);
194 		crc = UPDC32(c, crc);
195 	}
196 	xsendline(ZDLE); xsendline(frameend);
197 	crc = UPDC32(frameend, crc);
198 
199 	crc = ~crc;
200 	for (length=4; --length >= 0;) {
201 		zsendline((int)crc);  crc >>= 8;
202 	}
203 }
204 
205 /*
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!
209  */
210 int zrdata(char *buf, int length)
211 {
212 	register int c;
213 	register unsigned short crc;
214 	register char *end;
215 	register int d;
216 
217 	if (Rxframeind == ZBIN32)
218 		return zrdat32(buf, length);
219 
220 	crc = Rxcount = 0;  end = buf + length;
221 	while (buf <= end) {
222 		if ((c = zdlread()) & ~0377) {
223 crcfoo:
224 			switch (c) {
225 			case GOTCRCE:
226 			case GOTCRCG:
227 			case GOTCRCQ:
228 			case GOTCRCW:
229 				crc = updcrc((((d=c))&0377), crc);
230 				if ((c = zdlread()) & ~0377)
231 					goto crcfoo;
232 				crc = updcrc(c, crc);
233 				if ((c = zdlread()) & ~0377)
234 					goto crcfoo;
235 				crc = updcrc(c, crc);
236 				if (crc & 0xFFFF) {
237 					zperr(badcrc);
238 					return ERROR;
239 				}
240 				Rxcount = length - (end - buf);
241 				vfile("zrdata: %d  %s", Rxcount,
242 				 Zendnames[(d-GOTCRCE)&3]);
243 				return d;
244 			case GOTCAN:
245 				zperr("Sender Canceled");
246 				return ZCAN;
247 			case TIMEOUT:
248 				zperr("TIMEOUT");
249 				return c;
250 			default:
251 				zperr("Bad data subpacket");
252 				return c;
253 			}
254 		}
255 		*buf++ = c;
256 		crc = updcrc(c, crc);
257 	}
258 	zperr("Data subpacket too long");
259 	return ERROR;
260 }
261 
262 int zrdat32(char *buf, int length)
263 {
264 	register int c;
265 	register UNSL long crc;
266 	register char *end;
267 	register int d;
268 
269 	crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
270 	while (buf <= end) {
271 		if ((c = zdlread()) & ~0377) {
272 crcfoo:
273 			switch (c) {
274 			case GOTCRCE:
275 			case GOTCRCG:
276 			case GOTCRCQ:
277 			case GOTCRCW:
278 				d = c;  c &= 0377;
279 				crc = UPDC32(c, crc);
280 				if ((c = zdlread()) & ~0377)
281 					goto crcfoo;
282 				crc = UPDC32(c, crc);
283 				if ((c = zdlread()) & ~0377)
284 					goto crcfoo;
285 				crc = UPDC32(c, crc);
286 				if ((c = zdlread()) & ~0377)
287 					goto crcfoo;
288 				crc = UPDC32(c, crc);
289 				if ((c = zdlread()) & ~0377)
290 					goto crcfoo;
291 				crc = UPDC32(c, crc);
292 				if (crc != 0xDEBB20E3) {
293 					zperr(badcrc);
294 					return ERROR;
295 				}
296 				Rxcount = length - (end - buf);
297 				vfile("zrdat32: %d %s", Rxcount,
298 				 Zendnames[(d-GOTCRCE)&3]);
299 				return d;
300 			case GOTCAN:
301 				zperr("Sender Canceled");
302 				return ZCAN;
303 			case TIMEOUT:
304 				zperr("TIMEOUT");
305 				return c;
306 			default:
307 				zperr("Bad data subpacket");
308 				return c;
309 			}
310 		}
311 		*buf++ = c;
312 		crc = UPDC32(c, crc);
313 	}
314 	zperr("Data subpacket too long");
315 	return ERROR;
316 }
317 
318 
319 /*
320  * Read a ZMODEM header to hdr, either binary or hex.
321  *  eflag controls local display of non zmodem characters:
322  *	0:  no display
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.
328  */
329 int zgethdr(char *hdr, int eflag)
330 {
331 	register int c, n, cancount;
332 
333 	n = Zrwindow + Baudrate;	/* Max bytes before start of frame */
334 	Rxframeind = Rxtype = 0;
335 
336 startover:
337 	cancount = 5;
338 again:
339 	/* Return immediate ERROR if ZCRCW sequence seen */
340 	switch (c = readline(Rxtimeout)) {
341 	case RCDO:
342 	case TIMEOUT:
343 		goto fifi;
344 	case CAN:
345 gotcan:
346 		if (--cancount <= 0) {
347 			c = ZCAN; goto fifi;
348 		}
349 		switch (c = readline(1)) {
350 		case TIMEOUT:
351 			goto again;
352 		case ZCRCW:
353 			c = ERROR;
354 		/* **** FALL THRU TO **** */
355 		case RCDO:
356 			goto fifi;
357 		default:
358 			break;
359 		case CAN:
360 			if (--cancount <= 0) {
361 				c = ZCAN; goto fifi;
362 			}
363 			goto again;
364 		}
365 	/* **** FALL THRU TO **** */
366 	default:
367 agn2:
368 		if ( --n == 0) {
369 			zperr("Garbage count exceeded");
370 			return(ERROR);
371 		}
372 		if (eflag && ((c &= 0177) & 0140))
373 			bttyout(c);
374 		else if (eflag > 1)
375 			bttyout(c);
376 #ifdef UNIX
377 		fflush(stderr);
378 #endif
379 		goto startover;
380 	case ZPAD|0200:		/* This is what we want. */
381 		Not8bit = c;
382 	case ZPAD:		/* This is what we want. */
383 		break;
384 	}
385 	cancount = 5;
386 splat:
387 	switch (c = noxrd7()) {
388 	case ZPAD:
389 		goto splat;
390 	case RCDO:
391 	case TIMEOUT:
392 		goto fifi;
393 	default:
394 		goto agn2;
395 	case ZDLE:		/* This is what we want. */
396 		break;
397 	}
398 
399 	switch (c = noxrd7()) {
400 	case RCDO:
401 	case TIMEOUT:
402 		goto fifi;
403 	case ZBIN:
404 		Rxframeind = ZBIN;  Crc32 = FALSE;
405 		c =  zrbhdr(hdr);
406 		break;
407 	case ZBIN32:
408 		Crc32 = Rxframeind = ZBIN32;
409 		c =  zrbhdr32(hdr);
410 		break;
411 	case ZHEX:
412 		Rxframeind = ZHEX;  Crc32 = FALSE;
413 		c =  zrhhdr(hdr);
414 		break;
415 	case CAN:
416 		goto gotcan;
417 	default:
418 		goto agn2;
419 	}
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);
424 fifi:
425 	switch (c) {
426 	case GOTCAN:
427 		c = ZCAN;
428 	/* **** FALL THRU TO **** */
429 	case ZNAK:
430 	case ZCAN:
431 	case ERROR:
432 	case TIMEOUT:
433 	case RCDO:
434 		zperr("Got %s", frametypes[c+FTOFFSET]);
435 	/* **** FALL THRU TO **** */
436 	default:
437 		if (c >= -3 && c <= FRTYPES)
438 			vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
439 		else
440 			vfile("zgethdr: %d %lx", c, Rxpos);
441 	}
442 	return c;
443 }
444 
445 /* Receive a binary style header (type and position) */
446 int zrbhdr(char *hdr)
447 {
448 	register int c, n;
449 	register unsigned short crc;
450 
451 	if ((c = zdlread()) & ~0377)
452 		return c;
453 	Rxtype = c;
454 	crc = updcrc(c, 0);
455 
456 	for (n=4; --n >= 0; ++hdr) {
457 		if ((c = zdlread()) & ~0377)
458 			return c;
459 		crc = updcrc(c, crc);
460 		*hdr = c;
461 	}
462 	if ((c = zdlread()) & ~0377)
463 		return c;
464 	crc = updcrc(c, crc);
465 	if ((c = zdlread()) & ~0377)
466 		return c;
467 	crc = updcrc(c, crc);
468 	if (crc & 0xFFFF) {
469 		zperr(badcrc);
470 		return ERROR;
471 	}
472 #ifdef ZMODEM
473 	Protocol = ZMODEM;
474 #endif
475 	Zmodem = 1;
476 	return Rxtype;
477 }
478 
479 /* Receive a binary style header (type and position) with 32 bit FCS */
480 int zrbhdr32(char *hdr)
481 {
482 	register int c, n;
483 	register UNSL long crc;
484 
485 	if ((c = zdlread()) & ~0377)
486 		return c;
487 	Rxtype = c;
488 	crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
489 #ifdef DEBUGZ
490 	vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
491 #endif
492 
493 	for (n=4; --n >= 0; ++hdr) {
494 		if ((c = zdlread()) & ~0377)
495 			return c;
496 		crc = UPDC32(c, crc);
497 		*hdr = c;
498 #ifdef DEBUGZ
499 		vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
500 #endif
501 	}
502 	for (n=4; --n >= 0;) {
503 		if ((c = zdlread()) & ~0377)
504 			return c;
505 		crc = UPDC32(c, crc);
506 #ifdef DEBUGZ
507 		vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
508 #endif
509 	}
510 	if (crc != 0xDEBB20E3) {
511 		zperr(badcrc);
512 		return ERROR;
513 	}
514 #ifdef ZMODEM
515 	Protocol = ZMODEM;
516 #endif
517 	Zmodem = 1;
518 	return Rxtype;
519 }
520 
521 
522 /* Receive a hex style header (type and position) */
523 int zrhhdr(char *hdr)
524 {
525 	register int c;
526 	register unsigned short crc;
527 	register int n;
528 
529 	if ((c = zgethex()) < 0)
530 		return c;
531 	Rxtype = c;
532 	crc = updcrc(c, 0);
533 
534 	for (n=4; --n >= 0; ++hdr) {
535 		if ((c = zgethex()) < 0)
536 			return c;
537 		crc = updcrc(c, crc);
538 		*hdr = c;
539 	}
540 	if ((c = zgethex()) < 0)
541 		return c;
542 	crc = updcrc(c, crc);
543 	if ((c = zgethex()) < 0)
544 		return c;
545 	crc = updcrc(c, crc);
546 	if (crc & 0xFFFF) {
547 		zperr(badcrc); return ERROR;
548 	}
549 	switch ( c = readline(1)) {
550 	case 0215:
551 		Not8bit = c;
552 		/* **** FALL THRU TO **** */
553 	case 015:
554 	 	/* Throw away possible cr/lf */
555 		switch (c = readline(1)) {
556 		case 012:
557 			Not8bit |= c;
558 		}
559 	}
560 #ifdef ZMODEM
561 	Protocol = ZMODEM;
562 #endif
563 	Zmodem = 1; return Rxtype;
564 }
565 
566 /* Send a byte as two hex digits */
567 void zputhex(int c)
568 {
569 	static char	digits[]	= "0123456789abcdef";
570 
571 	if (Verbose>8)
572 		vfile("zputhex: %02X", c);
573 	sendline(digits[(c&0xF0)>>4]);
574 	sendline(digits[(c)&0xF]);
575 }
576 
577 /*
578  * Send character c with ZMODEM escape sequence encoding.
579  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
580  */
581 void zsendline(int c)
582 {
583 
584 	/* Quick check for non control characters */
585 	if (c & 0140)
586 		xsendline(lastsent = c);
587 	else {
588 		switch (c &= 0377) {
589 		case ZDLE:
590 			xsendline(ZDLE);
591 			xsendline (lastsent = (c ^= 0100));
592 			break;
593 		case 015:
594 		case 0215:
595 			if (!Zctlesc && (lastsent & 0177) != '@')
596 				goto sendit;
597 		/* **** FALL THRU TO **** */
598 		case 020:
599 		case 021:
600 		case 023:
601 		case 0220:
602 		case 0221:
603 		case 0223:
604 			xsendline(ZDLE);
605 			c ^= 0100;
606 	sendit:
607 			xsendline(lastsent = c);
608 			break;
609 		default:
610 			if (Zctlesc && ! (c & 0140)) {
611 				xsendline(ZDLE);
612 				c ^= 0100;
613 			}
614 			xsendline(lastsent = c);
615 		}
616 	}
617 }
618 
619 /* Decode two lower case hex digits into an 8 bit byte value */
620 int zgethex()
621 {
622 	register int c;
623 
624 	c = zgeth1();
625 	if (Verbose>8)
626 		vfile("zgethex: %02X", c);
627 	return c;
628 }
629 int zgeth1()
630 {
631 	register int c, n;
632 
633 	if ((c = noxrd7()) < 0)
634 		return c;
635 	n = c - '0';
636 	if (n > 9)
637 		n -= ('a' - ':');
638 	if (n & ~0xF)
639 		return ERROR;
640 	if ((c = noxrd7()) < 0)
641 		return c;
642 	c -= '0';
643 	if (c > 9)
644 		c -= ('a' - ':');
645 	if (c & ~0xF)
646 		return ERROR;
647 	c += (n<<4);
648 	return c;
649 }
650 
651 /*
652  * Read a byte, checking for ZMODEM escape encoding
653  *  including CAN*5 which represents a quick abort
654  */
655 int zdlread()
656 {
657 	register int c;
658 
659 again:
660 	/* Quick check for non control characters */
661 	if ((c = readline(Rxtimeout)) & 0140)
662 		return c;
663 	switch (c) {
664 	case ZDLE:
665 		break;
666 	case 023:
667 	case 0223:
668 	case 021:
669 	case 0221:
670 		goto again;
671 	default:
672 		if (Zctlesc && !(c & 0140)) {
673 			goto again;
674 		}
675 		return c;
676 	}
677 again2:
678 	if ((c = readline(Rxtimeout)) < 0)
679 		return c;
680 	if (c == CAN && (c = readline(Rxtimeout)) < 0)
681 		return c;
682 	if (c == CAN && (c = readline(Rxtimeout)) < 0)
683 		return c;
684 	if (c == CAN && (c = readline(Rxtimeout)) < 0)
685 		return c;
686 	switch (c) {
687 	case CAN:
688 		return GOTCAN;
689 	case ZCRCE:
690 	case ZCRCG:
691 	case ZCRCQ:
692 	case ZCRCW:
693 		return (c | GOTOR);
694 	case ZRUB0:
695 		return 0177;
696 	case ZRUB1:
697 		return 0377;
698 	case 023:
699 	case 0223:
700 	case 021:
701 	case 0221:
702 		goto again2;
703 	default:
704 		if (Zctlesc && ! (c & 0140)) {
705 			goto again2;
706 		}
707 		if ((c & 0140) ==  0100)
708 			return (c ^ 0100);
709 		break;
710 	}
711 	if (Verbose>1)
712 		zperr("Bad escape sequence %x", c);
713 	return ERROR;
714 }
715 
716 /*
717  * Read a character from the modem line with timeout.
718  *  Eat parity, XON and XOFF characters.
719  */
720 int noxrd7()
721 {
722 	register int c;
723 
724 	for (;;) {
725 		if ((c = readline(Rxtimeout)) < 0)
726 			return c;
727 		switch (c &= 0177) {
728 		case XON:
729 		case XOFF:
730 			continue;
731 		default:
732 			if (Zctlesc && !(c & 0140))
733 				continue;
734 		case '\r':
735 		case '\n':
736 		case ZDLE:
737 			return c;
738 		}
739 	}
740 }
741 
742 /* Store long integer pos in Txhdr */
743 void stohdr(long pos)
744 {
745 	Txhdr[ZP0] = pos;
746 	Txhdr[ZP1] = pos>>8;
747 	Txhdr[ZP2] = pos>>16;
748 	Txhdr[ZP3] = pos>>24;
749 }
750 
751 /* Recover a long integer from a header */
752 long
753 rclhdr(char *hdr)
754 {
755 	register long l;
756 
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);
761 	return l;
762 }
763 
764 /* End of zm.c */
765