Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

zmodem.c 37.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/* zmodem.c */

/* Synchronet ZMODEM Functions */

/* $Id$ */

/******************************************************************************/
/* Project : Unite!       File : zmodem general        Version : 1.02         */
/*                                                                            */
/* (C) Mattheij Computer Service 1994                                         */
/*                                                                            */
/* contact us through (in order of preference)                                */
/*                                                                            */
/*   email:          jacquesm@hacktic.nl                                      */
/*   mail:           MCS                                                      */
/*                   Prinses Beatrixlaan 535                                  */
/*                   2284 AT  RIJSWIJK                                        */
/*                   The Netherlands                                          */
/*   voice phone:    31+070-3936926                                           */
/******************************************************************************/

/*
 * zmodem primitives and other code common to zmtx and zmrx
 */

#include <stdio.h>
deuce's avatar
deuce committed
27
#include <stdarg.h>	/* va_list */
28 29 30
#include <sys/stat.h>	/* struct stat */

#include "genwrap.h"
31
#include "dirwrap.h"
32 33 34 35 36

#include "zmodem.h"
#include "crc16.h"
#include "crc32.h"

37 38
#include "sexyz.h"

39 40 41 42 43 44 45 46 47
#define ENDOFFRAME 2
#define FRAMEOK    1
#define TIMEOUT   -1	/* rx routine did not receive a character within timeout */
#define INVHDR    -2	/* invalid header received; but within timeout */
#define INVDATA   -3	/* invalid data subpacket received */
#define ZDLEESC 0x8000	/* one of ZCRCE; ZCRCG; ZCRCQ or ZCRCW was received; ZDLE escaped */

#define HDRLEN     5	/* size of a zmodem header */

rswindell's avatar
rswindell committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static int lprintf(zmodem_t* zm, int level, const char *fmt, ...)
{
	va_list argptr;
	char	sbuf[1024];

	if(zm->lputs==NULL)
		return(-1);

    va_start(argptr,fmt);
    vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
	sbuf[sizeof(sbuf)-1]=0;
    va_end(argptr);
    return(zm->lputs(zm->cbdata,level,sbuf));
}

63 64 65 66 67 68 69
static BOOL is_connected(zmodem_t* zm)
{
	if(zm->is_connected!=NULL)
		return(zm->is_connected(zm->cbdata));
	return(TRUE);
}

70 71 72 73 74 75 76
int zmodem_data_waiting(zmodem_t* zm)
{
	if(zm->data_waiting)
		return(zm->data_waiting(zm->cbdata));
	return(FALSE);
}

77 78 79 80 81
static char *chr(uchar ch)
{
	static char str[25];

	switch(ch) {
82 83 84
		case ZRQINIT:	return("ZRQINIT");
		case ZRINIT:	return("ZRINIT");
		case ZSINIT:	return("ZSINIT");
85
		case ZACK:		return("ZACK");
rswindell's avatar
rswindell committed
86 87 88 89 90 91 92
		case ZFILE:		return("ZFILE");
		case ZSKIP:		return("ZSKIP");
		case ZNAK:		return("ZNAK");
		case ZABORT:	return("ZABORT");
		case ZFIN:		return("ZFIN");
		case ZRPOS:		return("ZRPOS");
		case ZDATA:		return("ZDATA");
93 94
		case ZEOF:		return("ZEOF");
		case ZPAD:		return("ZPAD");
95
		case ZCAN:		return("ZCAN");
96 97 98 99 100 101
		case ZDLE:		return("ZDLE");
		case ZDLEE:		return("ZDLEE");
		case ZBIN:		return("ZBIN");
		case ZHEX:		return("ZHEX");
		case ZBIN32:	return("ZBIN32");
		case ZRESC:		return("ZRESC");
rswindell's avatar
rswindell committed
102 103 104 105 106
		case ZCRCE:		return("ZCRCE");
		case ZCRCG:		return("ZCRCG");
		case ZCRCQ:		return("ZCRCQ");
		case ZCRCW:		return("ZCRCW");

107 108 109 110 111 112 113 114
	}
	if(ch>=' ' && ch<='~')
		sprintf(str,"'%c' (%02Xh)",ch,ch);
	else
		sprintf(str,"%u (%02Xh)",ch,ch);
	return(str); 
}

115 116 117 118 119
/*
 * read bytes as long as rdchk indicates that
 * more data is available.
 */

120
void zmodem_recv_purge(zmodem_t* zm)
121
{
rswindell's avatar
rswindell committed
122
	while(zm->recv_byte(zm->cbdata,0)>=0);
123 124 125 126 127 128 129
}

/* 
 * transmit a character. 
 * this is the raw modem interface
 */

130
int zmodem_send_raw(zmodem_t* zm, unsigned char ch)
131
{
132 133 134
	int	result;

	if((result=zm->send_byte(zm->cbdata,ch,zm->send_timeout))!=0)
135
		lprintf(zm,LOG_ERR,"zmodem_send_raw SEND ERROR: %d",result);
136 137

	zm->last_sent = ch;
138 139

	return result;
140 141 142 143 144 145
}

/*
 * transmit a character ZDLE escaped
 */

146
int zmodem_send_esc(zmodem_t* zm, unsigned char c)
147
{
148 149
	int	result;

150
	if((result=zmodem_send_raw(zm, ZDLE))!=0)
151
		return(result);
152 153 154
	/*
	 * exclusive or; not an or so ZDLE becomes ZDLEE
	 */
155
	return zmodem_send_raw(zm, (uchar)(c ^ 0x40));
156 157 158 159 160 161
}

/*
 * transmit a character; ZDLE escaping if appropriate
 */

162
int zmodem_tx(zmodem_t* zm, unsigned char c)
163 164
{
	switch (c) {
165 166 167 168 169 170
		case DLE:
		case DLE|0x80:          /* even if high-bit set */
		case XON:
		case XON|0x80:
		case XOFF:
		case XOFF|0x80:
171
		case ZDLE:
172
			return zmodem_send_esc(zm, c);
173 174
		case CR:
		case CR|0x80:
175
			if(zm->escape_all_control_characters && (zm->last_sent&0x7f) == '@')
176
				return zmodem_send_esc(zm, c);
177 178
			break;
		default:
179
			if(zm->escape_all_control_characters && (c&0x60)==0)
180
				return zmodem_send_esc(zm, c);
181 182 183 184 185
			break;
	}
	/*
	 * anything that ends here is so normal we might as well transmit it.
	 */
186
	return zmodem_send_raw(zm, c);
187 188
}

189 190 191
/**********************************************/
/* Output single byte as two hex ASCII digits */
/**********************************************/
192
int zmodem_send_hex(zmodem_t* zm, uchar val)
193
{
194
	char* xdigit="0123456789abcdef";
195
	int	result;
196

197
	lprintf(zm,LOG_DEBUG,"zmodem_send_hex: %02X ",val);
198

199
	if((result=zmodem_send_raw(zm, xdigit[val>>4]))!=0)
200
		return result;
201
	return zmodem_send_raw(zm, xdigit[val&0xf]);
202 203
}

204
int zmodem_send_padded_zdle(zmodem_t* zm)
205 206 207
{
	int result;

208
	if((result=zmodem_send_raw(zm, ZPAD))!=0)
209
		return result;
210
	if((result=zmodem_send_raw(zm, ZPAD))!=0)
211
		return result;
212
	return zmodem_send_raw(zm, ZDLE);
213 214
}

215 216 217 218 219
/* 
 * transmit a hex header.
 * these routines use tx_raw because we're sure that all the
 * characters are not to be escaped.
 */
220
int zmodem_send_hex_header(zmodem_t* zm, unsigned char * p)
221 222
{
	int i;
223
	int result;
rswindell's avatar
rswindell committed
224
	uchar type=*p;
225 226
	unsigned short int crc;

227
	lprintf(zm,LOG_DEBUG,"zmodem_send_hex_header: %s", chr(type));
rswindell's avatar
rswindell committed
228

229
	if((result=zmodem_send_padded_zdle(zm))!=0)
230
		return result;
231

232
	if((result=zmodem_send_raw(zm, ZHEX))!=0)
233
		return result;
234 235 236 237 238 239 240 241 242 243 244

	/*
 	 * initialise the crc
	 */

	crc = 0;

	/*
 	 * transmit the header
	 */

245
	for(i=0;i<HDRLEN;i++) {
246
		if((result=zmodem_send_hex(zm, *p))!=0)
247
			return result;
248
		crc = ucrc16(*p, crc);
249 250 251 252 253 254 255 256 257 258 259
		p++;
	}

	/*
 	 * update the crc as though it were zero
	 */

	/* 
	 * transmit the crc
	 */

260
	if((result=zmodem_send_hex(zm, (uchar)(crc>>8)))!=0)
261
		return result;
262
	if((result=zmodem_send_hex(zm, (uchar)(crc&0xff)))!=0)
263
		return result;
264 265 266 267 268

	/*
	 * end of line sequence
	 */

269
	if((result=zmodem_send_raw(zm, '\r'))!=0)
270
		return result;
271
	if((result=zmodem_send_raw(zm, '\n'))!=0)	/* FDSZ sends 0x8a instead of 0x0a */
272
		return result;
273

rswindell's avatar
rswindell committed
274
	if(type!=ZACK && type!=ZFIN)
275
		result=zmodem_send_raw(zm, XON);
276

277
	return(result);
278 279 280 281 282 283
}

/*
 * Send ZMODEM binary header hdr
 */

284
int zmodem_send_bin32_header(zmodem_t* zm, unsigned char * p)
285 286
{
	int i;
287
	int result;
288 289
	unsigned long crc;

290
	if((result=zmodem_send_padded_zdle(zm))!=0)
291
		return result;
292

293
	if((result=zmodem_send_raw(zm, ZBIN32))!=0)
294
		return result;
295 296 297

	crc = 0xffffffffL;

298
	for(i=0;i<HDRLEN;i++) {
299
		crc = ucrc32(*p,crc);
300 301
		if((result=zmodem_tx(zm, *p++))!=0)
			return result;
302 303 304 305
	}

	crc = ~crc;

306 307 308 309 310 311 312
	if((result=	zmodem_tx(zm, (uchar)((crc      ) & 0xff)))!=0)
		return result;
	if((result=	zmodem_tx(zm, (uchar)((crc >>  8) & 0xff)))!=0)
		return result;
	if((result=	zmodem_tx(zm, (uchar)((crc >> 16) & 0xff)))!=0)
		return result;
	return		zmodem_tx(zm, (uchar)((crc >> 24) & 0xff));
313 314
}

315
int zmodem_send_bin16_header(zmodem_t* zm, unsigned char * p)
316 317
{
	int i;
318
	int result;
319 320
	unsigned int crc;

321
	if((result=zmodem_send_padded_zdle(zm))!=0)
322
		return result;
323

324
	if((result=zmodem_send_raw(zm, ZBIN))!=0)
325
		return result;
326 327 328

	crc = 0;

329
	for(i=0;i<HDRLEN;i++) {
330
		crc = ucrc16(*p,crc);
331 332
		if((result=zmodem_tx(zm, *p++))!=0)
			return result;
333 334
	}

335 336 337
	if((result=	zmodem_tx(zm, (uchar)(crc >> 8)))!=0)
		return result;
	return		zmodem_tx(zm, (uchar)(crc&0xff));
338 339 340 341 342 343 344 345 346 347
}


/* 
 * transmit a header using either hex 16 bit crc or binary 32 bit crc
 * depending on the receivers capabilities
 * we dont bother with variable length headers. I dont really see their
 * advantage and they would clutter the code unneccesarily
 */

348
int zmodem_send_bin_header(zmodem_t* zm, unsigned char * p)
349
{
350
	if(zm->can_fcs_32 && !zm->want_fcs_16)
351 352
		return zmodem_send_bin32_header(zm, p);
	return zmodem_send_bin16_header(zm, p);
353 354 355 356 357 358
}

/*
 * data subpacket transmission
 */

359
int zmodem_send_data32(zmodem_t* zm, uchar sub_frame_type, unsigned char * p, int l)
360
{
361
	int	result;
362 363
	unsigned long crc;

364
	lprintf(zm,LOG_DEBUG,"zmodem_send_data32");
365 366 367

	crc = 0xffffffffl;

368
	while(l > 0) {
369
		crc = ucrc32(*p,crc);
370 371
		if((result=zmodem_tx(zm, *p++))!=0)
			return result;
372 373 374
		l--;
	}

375
	crc = ucrc32(sub_frame_type, crc);
376

377
	if((result=zmodem_send_raw(zm, ZDLE))!=0)
378
		return result;
379
	if((result=zmodem_send_raw(zm, sub_frame_type))!=0)
380
		return result;
381 382 383

	crc = ~crc;

384 385 386 387 388 389 390
	if((result=	zmodem_tx(zm, (uchar) ((crc      ) & 0xff)))!=0)
		return result;
	if((result=	zmodem_tx(zm, (uchar) ((crc >> 8 ) & 0xff)))!=0)
		return result;
	if((result=	zmodem_tx(zm, (uchar) ((crc >> 16) & 0xff)))!=0)
		return result;
	return		zmodem_tx(zm, (uchar) ((crc >> 24) & 0xff));
391 392
}

393
int zmodem_send_data16(zmodem_t* zm, uchar sub_frame_type,unsigned char * p,int l)
394
{
395
	int	result;
396 397
	unsigned short crc;

398
	lprintf(zm,LOG_DEBUG,"zmodem_send_data16");
399 400 401

	crc = 0;

402
	while(l > 0) {
403
		crc = ucrc16(*p,crc);
404 405
		if((result=zmodem_tx(zm, *p++))!=0)
			return result;
406 407 408
		l--;
	}

409
	crc = ucrc16(sub_frame_type,crc);
410

411
	if((result=zmodem_send_raw(zm, ZDLE))!=0)
412
		return result;
413
	if((result=zmodem_send_raw(zm, sub_frame_type))!=0)
414
		return result;
415
	
416 417 418
	if((result=	zmodem_tx(zm, (uchar)(crc >> 8)))!=0)
		return result;
	return		zmodem_tx(zm, (uchar)(crc&0xff));
419 420 421 422 423 424
}

/*
 * send a data subpacket using crc 16 or crc 32 as desired by the receiver
 */

425
int zmodem_send_data(zmodem_t* zm, uchar sub_frame_type, unsigned char * p, int l)
426
{
427
	int result;
428

429
	if(!zm->want_fcs_16 && zm->can_fcs_32) {
430
		if((result=zmodem_send_data32(zm, sub_frame_type,p,l))!=0)
431
			return result;
432 433
	}
	else {	
434
		if((result=zmodem_send_data16(zm, sub_frame_type,p,l))!=0)
435
			return result;
436 437
	}

438
	if(sub_frame_type == ZCRCW)
439
		result=zmodem_send_raw(zm, XON);
440 441

	return result;
442 443
}

444
int zmodem_send_pos_header(zmodem_t* zm, int type, long pos, BOOL hex) 
445
{
446
	uchar header[5];
447 448

	header[0]   = type;
449
	header[ZP0] = (uchar) (pos        & 0xff);
rswindell's avatar
rswindell committed
450 451 452
	header[ZP1] = (uchar)((pos >>  8) & 0xff);
	header[ZP2] = (uchar)((pos >> 16) & 0xff);
	header[ZP3] = (uchar)((pos >> 24) & 0xff);
453

454
	if(hex)
455
		return zmodem_send_hex_header(zm, header);
456
	else
457
		return zmodem_send_bin_header(zm, header);
458 459
}

460 461 462 463 464 465 466 467 468 469 470 471 472 473
int zmodem_send_ack(zmodem_t* zm, long pos)
{
	return zmodem_send_pos_header(zm, ZACK, pos, /* Hex? */ TRUE);
}

int zmodem_send_nak(zmodem_t* zm)
{
	return zmodem_send_pos_header(zm, ZNAK, 0, /* Hex? */ TRUE);
}

int zmodem_send_zfin(zmodem_t* zm)
{
	unsigned char zfin_header[] = { ZFIN, 0, 0, 0, 0 };

474
	return zmodem_send_hex_header(zm,zfin_header);
475 476 477 478 479 480 481
}

int zmodem_abort_receive(zmodem_t* zm)
{
	return zmodem_send_pos_header(zm, ZABORT, 0, /* Hex? */ TRUE);
}

482
int zmodem_send_znak(zmodem_t* zm)
483
{
484
	return zmodem_send_pos_header(zm, ZNAK, zm->ack_file_pos, /* Hex? */ TRUE);
485 486
}

487
int zmodem_send_zskip(zmodem_t* zm)
488
{
489
	return zmodem_send_pos_header(zm, ZSKIP, 0L, /* Hex? */ TRUE);
490 491 492 493 494 495 496 497 498 499 500
}

/*
 * rx_raw ; receive a single byte from the line.
 * reads as many are available and then processes them one at a time
 * check the data stream for 5 consecutive CAN characters;
 * and if you see them abort. this saves a lot of clutter in
 * the rest of the code; even though it is a very strange place
 * for an exit. (but that was wat session abort was all about.)
 */

501
int zmodem_recv_raw(zmodem_t* zm)
502 503 504
{
	int c;

505
	if((c=zm->recv_byte(zm->cbdata,zm->recv_timeout)) < 0)
rswindell's avatar
rswindell committed
506
		return(TIMEOUT);
507

508
	if(c == CAN) {
509
		zm->n_cans++;
510
		if(zm->n_cans == 5) {
rswindell's avatar
rswindell committed
511
			zm->cancelled=TRUE;
512
			lprintf(zm,LOG_WARNING,"zmodem_recv_raw: Cancelled remotely");
rswindell's avatar
rswindell committed
513
			return(TIMEOUT);
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
		}
	}
	else {
		zm->n_cans = 0;
	}

	return c;
}

/*
 * rx; receive a single byte undoing any escaping at the
 * sending site. this bit looks like a mess. sorry for that
 * but there seems to be no other way without incurring a lot
 * of overhead. at least like this the path for a normal character
 * is relatively short.
 */

531
int zmodem_rx(zmodem_t* zm)
532 533 534 535 536 537 538 539 540
{
	int c;

	/*
	 * outer loop for ever so for sure something valid
	 * will come in; a timeout will occur or a session abort
	 * will be received.
	 */

541
	while(is_connected(zm)) {
542 543 544 545 546 547 548

		/*
	 	 * fake do loop so we may continue
		 * in case a character should be dropped.
		 */

		do {
549
			if((c = zmodem_recv_raw(zm)) < 0)
rswindell's avatar
rswindell committed
550
				return(c);
551 552 553 554
	
			switch (c) {
				case ZDLE:
					break;
555 556 557 558
				case XON:
				case XON|0x80:
				case XOFF:
				case XOFF|0x80:
559 560 561 562 563 564
					continue;			
				default:
					/*
	 				 * if all control characters should be escaped and 
					 * this one wasnt then its spurious and should be dropped.
					 */
565
					if(zm->escape_all_control_characters && (c & 0x60) == 0) {
566 567 568 569 570 571 572
						continue;
					}
					/*
					 * normal character; return it.
					 */
					return c;
			}
573
		} while(FALSE);
574 575 576 577 578 579 580
	
		/*
	 	 * ZDLE encoded sequence or session abort.
		 * (or something illegal; then back to the top)
		 */

		do {
581
			if((c = zmodem_recv_raw(zm)) < 0)
rswindell's avatar
rswindell committed
582
				return(c);
583

584
			if(c == XON || c == (XON|0x80) || c == XOFF || c == (XOFF|0x80) || c == ZDLE) {
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
				/*
				 * these can be dropped.
				 */
				continue;
			}

			switch (c) {
				/*
				 * these four are really nasty.
				 * for convenience we just change them into 
				 * special characters by setting a bit outside the
				 * first 8. that way they can be recognized and still
				 * be processed as characters by the rest of the code.
				 */
				case ZCRCE:
				case ZCRCG:
				case ZCRCQ:
				case ZCRCW:
603 604
					lprintf(zm,LOG_DEBUG,"zmodem_rx: encoding data subpacket type: %s"
						,chr((uchar)c));
605 606 607 608 609 610
					return (c | ZDLEESC);
				case ZRUB0:
					return 0x7f;
				case ZRUB1:
					return 0xff;
				default:
611
					if(zm->escape_all_control_characters && (c & 0x60) == 0) {
612 613 614 615 616 617 618 619 620 621
						/*
						 * a not escaped control character; probably
						 * something from a network. just drop it.
						 */
						continue;
					}
					/*
					 * legitimate escape sequence.
					 * rebuild the orignal and return it.
					 */
622
					if((c & 0x60) == 0x40) {
623 624 625 626
						return c ^ 0x40;
					}
					break;
			}
627
		} while(FALSE);
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
	}

	/*
	 * not reached.
	 */

	return 0;
}

/*
 * receive a data subpacket as dictated by the last received header.
 * return 2 with correct packet and end of frame
 * return 1 with correct packet frame continues
 * return 0 with incorrect frame.
 * return TIMEOUT with a timeout
 * if an acknowledgement is requested it is generated automatically
 * here. 
 */

/*
 * data subpacket reception
 */

651
int zmodem_recv_data32(zmodem_t* zm, unsigned char * p, unsigned maxlen, unsigned* l)
652 653 654 655 656 657
{
	int c;
	unsigned long rxd_crc;
	unsigned long crc;
	int sub_frame_type;

658
	lprintf(zm,LOG_DEBUG,"zmodem_recv_data32");
659 660 661 662

	crc = 0xffffffffl;

	do {
663
		c = zmodem_rx(zm);
664

665
		if(c == TIMEOUT) {
666 667
			return TIMEOUT;
		}
rswindell's avatar
rswindell committed
668
		if(c < 0x100 && *l < maxlen) {
669
			crc = ucrc32(c,crc);
670 671 672 673
			*p++ = c;
			(*l)++;
			continue;
		}
674
	} while(c < 0x100);
675 676 677

	sub_frame_type = c & 0xff;

678
	crc = ucrc32(sub_frame_type, crc);
679 680 681

	crc = ~crc;

682 683 684 685
	rxd_crc  = zmodem_rx(zm);
	rxd_crc |= zmodem_rx(zm) << 8;
	rxd_crc |= zmodem_rx(zm) << 16;
	rxd_crc |= zmodem_rx(zm) << 24;
686

687
	if(rxd_crc != crc) {
688 689
		lprintf(zm,LOG_WARNING,"CRC32 ERROR (%08lX, expected: %08lX) Bytes=%u, sub-frame-type=%s"
			,rxd_crc, crc, *l, chr((char)sub_frame_type));
690 691
		return FALSE;
	}
692 693
	lprintf(zm,LOG_DEBUG,"GOOD CRC32: %08lX (Bytes=%u, sub-frame-type=%s)"
		,crc, *l, chr((char)sub_frame_type));
694 695 696 697 698 699

	zm->ack_file_pos += *l;

	return sub_frame_type;
}

700
int zmodem_recv_data16(zmodem_t* zm, register unsigned char* p, unsigned maxlen, unsigned* l)
701
{
rswindell's avatar
rswindell committed
702
	int c;
703
	int sub_frame_type;
rswindell's avatar
rswindell committed
704
 	unsigned short crc;
705 706
	unsigned short rxd_crc;

707
	lprintf(zm,LOG_DEBUG,"zmodem_recv_data16");
708 709 710 711

	crc = 0;

	do {
712
		c = zmodem_rx(zm);
713

714
		if(c == TIMEOUT) {
715 716
			return TIMEOUT;
		}
rswindell's avatar
rswindell committed
717
		if(c < 0x100 && *l < maxlen) {
718
			crc = ucrc16(c,crc);
719 720 721
			*p++ = c;
			(*l)++;
		}
722
	} while(c < 0x100);
723 724 725

	sub_frame_type = c & 0xff;

726
	crc = ucrc16(sub_frame_type,crc);
727

728 729
	rxd_crc  = zmodem_rx(zm) << 8;
	rxd_crc |= zmodem_rx(zm);
730

731
	if(rxd_crc != crc) {
732
		lprintf(zm,LOG_WARNING,"CRC16 ERROR (%04hX, expected: %04hX) Bytes=%d"
rswindell's avatar
rswindell committed
733
			,rxd_crc, crc, *l);
734 735
		return FALSE;
	}
736
	lprintf(zm,LOG_DEBUG,"GOOD CRC16: %04hX (Bytes=%d)", crc, *l);
737 738 739 740 741 742

	zm->ack_file_pos += *l;

	return sub_frame_type;
}

743
int zmodem_recv_data(zmodem_t* zm, unsigned char* p, size_t maxlen, unsigned* l)
744 745 746
{
	int sub_frame_type;
	long pos;
747 748 749 750
	unsigned n=0;

	if(l==NULL)
		l=&n;
751

752
	lprintf(zm,LOG_DEBUG,"zmodem_recv_data (%u-bit)", zm->receive_32bit_data ? 32:16);
753

754 755 756 757 758 759 760 761 762 763 764 765 766 767
	/*
	 * fill in the file pointer in case acknowledgement is requested.	
	 * the ack file pointer will be updated in the subpacket read routine;
	 * so we need to get it now
	 */

	pos = zm->ack_file_pos;

	/*
	 * receive the right type of frame
	 */

	*l = 0;

768 769
	if(zm->receive_32bit_data) {
		sub_frame_type = zmodem_recv_data32(zm, p, maxlen, l);
770 771
	}
	else {	
772
		sub_frame_type = zmodem_recv_data16(zm, p, maxlen, l);
773
	}
774 775 776

	if(sub_frame_type==FALSE)
		return(FALSE);
777 778 779 780
	
	if(sub_frame_type==TIMEOUT)
		return(TIMEOUT);
	
781
	lprintf(zm,LOG_DEBUG,"zmodem_recv_data received sub-frame-type: %s"
782
		,chr((uchar)sub_frame_type));
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798

	switch (sub_frame_type)  {
		/*
		 * frame continues non-stop
		 */
		case ZCRCG:
			return FRAMEOK;
		/*
		 * frame ends
		 */
		case ZCRCE:
			return ENDOFFRAME;
		/*
 		 * frame continues; ZACK expected
		 */
		case ZCRCQ:		
799
			zmodem_send_ack(zm, pos);
800 801 802 803 804
			return FRAMEOK;
		/*
		 * frame ends; ZACK expected
		 */
		case ZCRCW:
805
			zmodem_send_ack(zm, pos);
806 807 808
			return ENDOFFRAME;
	}

809
	lprintf(zm,LOG_WARNING,"Invalid sub-frame-type: %s",chr((uchar)sub_frame_type));
810

811 812 813
	return FALSE;
}

814 815 816 817
int zmodem_recv_subpacket(zmodem_t* zm)
{
	int type;

818
	type=zmodem_recv_data(zm,zm->rx_data_subpacket,sizeof(zm->rx_data_subpacket),NULL);
819 820 821 822 823 824
	if(type!=FRAMEOK && type!=ENDOFFRAME)
		zmodem_send_nak(zm);

	return(type);
}

825
int zmodem_recv_nibble(zmodem_t* zm) 
826 827 828
{
	int c;

829
	c = zmodem_rx(zm);
830

831
	if(c == TIMEOUT) {
832 833 834
		return c;
	}

835 836
	if(c > '9') {
		if(c < 'a' || c > 'f') {
837 838 839 840 841 842 843 844 845 846
			/*
			 * illegal hex; different than expected.
			 * we might as well time out.
			 */
			return TIMEOUT;
		}

		c -= 'a' - 10;
	}
	else {
847
		if(c < '0') {
848 849 850 851 852 853 854 855 856 857 858 859
			/*
			 * illegal hex; different than expected.
			 * we might as well time out.
			 */
			return TIMEOUT;
		}
		c -= '0';
	}

	return c;
}

860
int zmodem_recv_hex(zmodem_t* zm)
861 862 863
{
	int n1;
	int n0;
864
	int ret;
865

866
	n1 = zmodem_recv_nibble(zm);
867

868
	if(n1 == TIMEOUT) {
869 870 871
		return n1;
	}

872
	n0 = zmodem_recv_nibble(zm);
873

874
	if(n0 == TIMEOUT) {
875 876 877
		return n0;
	}

878 879
	ret = (n1 << 4) | n0;

880
	lprintf(zm,LOG_DEBUG,"zmodem_recv_hex returning: 0x%02X", ret);
881 882

	return ret;
883 884 885 886 887 888 889 890
}

/*
 * receive routines for each of the six different styles of header.
 * each of these leaves zm->rxd_header_len set to 0 if the end result is
 * not a valid header.
 */

891
BOOL zmodem_recv_bin16_header(zmodem_t* zm)
892 893 894 895 896 897
{
	int c;
	int n;
	unsigned short int crc;
	unsigned short int rxd_crc;

898
	lprintf(zm,LOG_DEBUG,"zmodem_recv_bin16_header");
899 900 901

	crc = 0;

902
	for(n=0;n<HDRLEN;n++) {
903
		c = zmodem_rx(zm);
904
		if(c == TIMEOUT) {
905
			lprintf(zm,LOG_WARNING,"zmodem_recv_bin16_header: timeout");
906
			return(FALSE);
907
		}
908
		crc = ucrc16(c,crc);
909 910 911
		zm->rxd_header[n] = c;
	}

912 913
	rxd_crc  = zmodem_rx(zm) << 8;
	rxd_crc |= zmodem_rx(zm);
914

915
	if(rxd_crc != crc) {
916 917
		lprintf(zm,LOG_WARNING,"CRC16 ERROR: 0x%hX, expected: 0x%hX", rxd_crc, crc);
		return(FALSE);
918
	}
919
	lprintf(zm,LOG_DEBUG,"GOOD CRC16: %04hX", crc);
920 921

	zm->rxd_header_len = 5;
922 923

	return(TRUE);
924 925
}

926
void zmodem_recv_hex_header(zmodem_t* zm)
927 928 929 930 931 932
{
	int c;
	int i;
	unsigned short int crc = 0;
	unsigned short int rxd_crc;

933
	lprintf(zm,LOG_DEBUG,"zmodem_recv_hex_header");
934

935
	for(i=0;i<HDRLEN;i++) {
936
		c = zmodem_recv_hex(zm);
937
		if(c == TIMEOUT) {
938 939
			return;
		}
940
		crc = ucrc16(c,crc);