File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lrzsz / src / zm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Thu Oct 24 15:49:50 2019 UTC (4 years, 11 months ago) by misho
Branches: lrzsz, MAIN
CVS tags: v0_12_20p5, HEAD
lrzsz ver 0.12.20

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>