⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rz.c

📁 Embedded zModem C sources
💻 C
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "zmodem.h"
#include "rbsb.h"
#include "zm.h"
#include "zport.h"
#include "v2cfg.h"

#if defined(RZ_MODULE)


#define MAXZTRY		5		// max number of zTry() in receiving
extern int gzCtlEsc;		// encode control chacracters
extern int gfUseVHdrs;
extern int gfCrc32;
extern char gszAttn[];		// Attention string rx sends to tx on err

//int  gfBinary;		/* binary transfer */
/* file operation */
//char gcLFileManage;		/* Local file management request */
//char gcLFileConversion;	/* Local ZMODEM file conversion reqeust */
//char gcFileConversion;	/* ZMODEM file conversion reqeust */
//char gcFileManage;		/* ZMODEM file management reqeust */
//char gcFileTrans;			/* ZMODEM file transport request */

#define DEFBYTL		2000000000L;		/* default rx file size */
long glBytesLeft;			/* number of bytes of incoming file left */
long glModTime;				/* Unix style modified time for incoming file */
int	 gnFileMode;			/* Unix style mode for incoming file */
long glTotalBytes, glTotalLeft;
long glTotalFiles, glFilesLeft;
//#define PATHLEN 257		/* ready for 4.2 bsd ? */
#define UNIXFILE 0xF000		/* The S_IFMT file mask bit for stat */
//char gszPathname[PATHLEN];
char gcaSecBuf[ZMAXSPLEN+1];

#ifdef ZD_FILESAVE
static char *pzFileSave;
static long lFileSavePos;
#endif

///////////////////////////////////////////////////////////////////////////////
// int zProcFileHeader(char *szFilename)
// Process incoming file information header
// returns 0 for sucess, other codes for errors or skip conditions.
int zProcFileHeader(char *szFilename)
{
	char *pFileInfo;
//	static int dummy;
	
	/* set default parameters and overrides */
//	if(gcFileConversion == ZCBIN && gcLFileConversion != ZCRESUM)
//		gcLFileConversion = gcFileConversion; 	/* remote binary override */
//	if(gcLFileConversion)
//		gcFileConversion = gcLFileConversion;
//	if(gcLFileManage)
//		gcFileManage = gcLFileManage;
	
	/* process ZMODEM remote file management req */
//	if(gcFileConversion == ZCNL)	/* remote ASCII override */
//		gfBinary = 0;
//	if(gcFileConversion == ZCBIN)
//		gfBinary = 1;

	if(!szFilename || !(*szFilename))
		return 0;

	pFileInfo = szFilename + (1 + strlen(szFilename));	/* +1 is trailing '\0' */
	if(*pFileInfo)
	{	/* file incoming from Unix or DOS system */
		/* YYY
		sscanf(pFileInfo, "%ld%lo%o%lo%d%ld%d%d", \
		&glBytesLeft, &glModTime, &gnFileMode, &dummy, &glFilesLeft, &glTotalLeft, &dummy, &dummy);
		*/
		glBytesLeft = strtoul(pFileInfo, &pFileInfo, 10);
//		if(gnFileMode & UNIXFILE)
//		{
//			++gfBinary;
//		}
		++glTotalFiles;
		glTotalBytes += glBytesLeft;
	}
	return 0;
}

///////////////////////////////////////////////////////////////////////////////
// Ack a ZFIN packet.
//
void zAckFin(void)
{
	int i, c;
	char caTxHdrFlag[ZMAXHLEN];

	zLongToChar4(caTxHdrFlag, 0l);
	// try 3 times
	for(i=0; i<3; i++)
	{
		zSndHexHdr(4, ZFIN, caTxHdrFlag);
		switch((c = ReadLine(10000)))
		{
			case 'O' :	/* two "00" (Over and Out) */
				ReadLine(1000);	/* discard 2nd '0' */
				return;
			case RCD0 :
				return;
			case TIMEOUT :
				break;
			default :
				break;
		}
	}
}
///////////////////////////////////////////////////////////////////////////////
// initialize for Zmodem receive attempt, try to activate Zmodem sender.
// handles ZSINIT frame.
// return ZFILE if Zmodem filename received.
//        ZCOMPL if transaction finished.
//        -1 on error.
//        0  otherwise.
int zTry(void)
{
	register int c, n;
	int  nzTryHdrType = ZRINIT;	// Header type to send corresponding to Last rx close
	char caTxHdrFlag[ZMAXHLEN], caRxHdrFlag[ZMAXHLEN];
	int	 bSkipSendHeader = 1;	// send header at first
	int	 nRxCnt;
	char cFileConversion;
	char cFileManage;	
	char cFileTrans;	

//	zFPrintf_T("zTry init\n");
	for(n=0; n<=MAXZTRY; n++)
	{	/* set buffer length (0) and capability flags */
		if(!bSkipSendHeader)
		{
			zLongToChar4(caTxHdrFlag, 0L);
//			caTxHdrFlag[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
			caTxHdrFlag[ZF0] = CANFC32|CANFDX|CANOVIO;
			if(gzCtlEsc)
				caTxHdrFlag[ZF0] |= TESCCTL;
			caTxHdrFlag[ZF0] |= CANRLE;
			caTxHdrFlag[ZF1] = CANVHDR;
			// nzTryHdrType may be ZRINIT
			zSndHexHdr(4, nzTryHdrType, caTxHdrFlag);
		}
		switch(c = zGetHeader(caRxHdrFlag))
		{
			case ZRQINIT :
				if(caRxHdrFlag[ZF3] & 0x80)
					gfUseVHdrs = 1;
				bSkipSendHeader = 0;	// send header again.
				continue;
			case ZEOF : 
				bSkipSendHeader = 0;	// send header again.
				continue;
			case TIMEOUT :
				bSkipSendHeader = 0;	// send header again.
				continue;
			case ZFILE :
				cFileConversion = caRxHdrFlag[ZF0];
				cFileManage = caRxHdrFlag[ZF1];	
				cFileTrans = caRxHdrFlag[ZF2];	

				if(caRxHdrFlag[ZF3] & ZCANVHDR)
					gfUseVHdrs = 1;
				nzTryHdrType = ZRINIT;
				c = zRcvData(gcaSecBuf, ZMAXSPLEN, &nRxCnt);
				if(c == GOTCRCW)
				{
					return ZFILE;
				}
				zSndHexHdr(4, ZNAK, caTxHdrFlag);
				bSkipSendHeader = 1;	// skip send header next time.
				break;
			case ZSINIT :
				gzCtlEsc = TESCCTL & caRxHdrFlag[ZF0];
				if(zRcvData(gszAttn, ZATTNLEN, &nRxCnt) == GOTCRCW)
				{
					zLongToChar4(caTxHdrFlag, 1l);
					zSndHexHdr(4, ZACK, caTxHdrFlag);
				}
				else
				{
					zLongToChar4(caTxHdrFlag, 0l);
					zSndHexHdr(4, ZNAK, caTxHdrFlag);
				}
				bSkipSendHeader = 1;	// skip send header next time.
				break;
			case ZFREECNT :
				zLongToChar4(caTxHdrFlag, 2147483647);	/* many free cnt. this is just guess. */
				zSndHexHdr(4, ZACK, caTxHdrFlag);
				bSkipSendHeader = 1;	// skip send header next time.
				break;
			case ZCOMMAND :
				break;
			case ZCOMPL : 
				bSkipSendHeader = 1;	// skip send header.
				break;
			case ZFIN : 
				zAckFin();
				return ZCOMPL;
			case ZCAN : 
				return ERROR;
			default :
				bSkipSendHeader = 0;	// send header again.
				break;
		}
	}
	return 0;
}

///////////////////////////////////////////////////////////////////////////////
// Receive a file with ZMODEM porotocol.
// Assumes fileaname frame is in gcaSecBuf.
int zRcvFile(void)
{
	int c;
	char caTxHdrFlag[ZMAXHLEN], caRxHdrFlag[ZMAXHLEN];
	long lRxBytes;
	int  nRcvFileTry;
	int  bSkipHdrSend;
	int  bMoreData;		// remains more data without header
	int  nRxCnt;		// count of data bytes received actually

	if((c = zProcFileHeader(gcaSecBuf)) != 0)
		return (c);

#ifdef ZD_FILESAVE
	// malloc for file save
	if(pzFileSave == NULL)
	{
		pzFileSave = (char *)zMalloc(glBytesLeft);
		
		// no check for NULL.
		// Anyway, the z procedure must be retained. but you can't save the file if NULL.
		// and after all, the (lFilePos == 0) is returned.
	}
#endif

	nRcvFileTry = 20;
	lRxBytes = 0l;
	bSkipHdrSend = 0;	// send header at first
	while(1)
	{
		if(!bSkipHdrSend)
		{
			zLongToChar4(caTxHdrFlag, lRxBytes);
			zSndHexHdr(4, ZRPOS, caTxHdrFlag);
		}
		switch(c = zGetHeader(caRxHdrFlag))
		{
			case ZCAN :
				return ERROR;
			case ZNAK :
				if(--nRcvFileTry < 0)
					return ERROR;
				bSkipHdrSend = 0;	
				break;
			case TIMEOUT :
				if(--nRcvFileTry < 0)
					return ERROR;
				bSkipHdrSend = 0;	
				break;
			case ZFILE :
				zRcvData(gcaSecBuf, ZMAXSPLEN, &nRxCnt);
				bSkipHdrSend = 0;	
				break;
			case ZEOF :
				if(zChar4ToLong(caRxHdrFlag) != lRxBytes)
				{
					// Ignore EOF if it's at wrong place - force a timeout 
					// because the EOF might have gone out before we sent our ZRPOS
					bSkipHdrSend = 1;
					continue;
				}
				return c;
			case ERROR :	// too much garbage in header search error
				if(--nRcvFileTry < 0)
					return ERROR;
				zPuts(gszAttn);
				bSkipHdrSend = 0;	
				break;
			case ZSKIP :
				return c;
			case ZDATA :
				if(zChar4ToLong(caRxHdrFlag) != lRxBytes)
				{
					if(--nRcvFileTry < 0)
						return ERROR;
					zPuts(gszAttn);
					bSkipHdrSend = 0;	
					continue;
				}
				bMoreData = 1;	// at first, it is initilaized to 1. one time true
				while(bMoreData)
				{
					switch(c = zRcvData(gcaSecBuf, ZMAXSPLEN, &nRxCnt))
					{
						case ZCAN :
							return ERROR;
						case ERROR :
							if(--nRcvFileTry < 0)
								return ERROR;
							zPuts(gszAttn);
							bSkipHdrSend = 0;	// send header
							bMoreData = 0;		// escape from while
							break;
						case TIMEOUT :
							if(--nRcvFileTry < 0)
								return ERROR;
							bSkipHdrSend = 0;	// send header
							bMoreData = 0;		// escape from while
							break;
						case GOTCRCW :
							// CRC next, ZACK expected, end of frame
//							zFPrintf_T("zRF(zDATA) : GOTCRCW\n");
							nRcvFileTry = 20;
							// move gcaSecBuf to safe addr. later
#ifdef ZD_FILESAVE
							if(pzFileSave)
							{
							memcpy(pzFileSave+lFileSavePos, gcaSecBuf, nRxCnt);
							lFileSavePos += nRxCnt;
							}
#endif							
							lRxBytes += nRxCnt;
							zLongToChar4(caTxHdrFlag, lRxBytes);
							SendLine(XON);
							zSndHexHdr(4, ZACK, caTxHdrFlag);
							bSkipHdrSend = 1;	// do not send header
							bMoreData = 0;		// escape from while
							break;
						case GOTCRCQ :
							// CRC next, frame continues, ZACK expected 
//							zFPrintf_T("zRF(zDATA) : GOTCRCQ\n");
							nRcvFileTry = 20;
							// move gcaSecBuf to safe addr. later
#ifdef ZD_FILESAVE
							if(pzFileSave)
							{
							memcpy(pzFileSave+lFileSavePos, gcaSecBuf, nRxCnt);
							lFileSavePos += nRxCnt;
							}
#endif
							lRxBytes += nRxCnt;
							zLongToChar4(caTxHdrFlag, lRxBytes);
							zSndHexHdr(4, ZACK, caTxHdrFlag);

							bSkipHdrSend = 0;	// send header
							bMoreData = 1;		// more data without header
							break;
						case GOTCRCG :
							// CRC next, frame continues nonstop
//							zFPrintf_T("zRF(zDATA) : GOTCRCG\n");
							nRcvFileTry = 20;
							// move gcaSecBuf to safe addr. later
#ifdef ZD_FILESAVE
							if(pzFileSave)
							{
							memcpy(pzFileSave+lFileSavePos, gcaSecBuf, nRxCnt);
							lFileSavePos += nRxCnt;
							}
#endif
							lRxBytes += nRxCnt;
							
							bSkipHdrSend = 0;	// send header
							bMoreData = 1;		// more data without header
							break;
						case GOTCRCE :
							// CRC next, frame ends, header packet follows
//							zFPrintf_T("zRF(zDATA) : GOTCRCE\n");
							nRcvFileTry = 20;
							// move gcaSecBuf to safe addr. later 
#ifdef ZD_FILESAVE
							if(pzFileSave)
							{
							memcpy(pzFileSave+lFileSavePos, gcaSecBuf, nRxCnt);
							lFileSavePos += nRxCnt;
							}
#endif
							lRxBytes += nRxCnt;
							
							bSkipHdrSend = 1;	// skip next header
							bMoreData = 0;		// escape from while
							break;
					}	// switch()
				}	/* while(bMoreData) ? */
				break;
			default :
				if(--nRcvFileTry < 0)
					return ERROR;
				bSkipHdrSend = 1;	// skip next header
				break;
		}	// switch(hdrType)
	}	/* while(1) */
	return 0;
}

///////////////////////////////////////////////////////////////////////////////
// Receive 1 or more files with ZMODEM protocol.
int zRcvFiles(void)
{
	int c;

	while(1)
	{
		switch(c = zRcvFile())
		{
			case ZEOF :
			case ZSKIP :
			case ZFERR :
				switch(zTry())
				{
					case ZCOMPL :
						return OK;
					case ZFILE :
						break;
					default :
						return ERROR;
				}
				continue;
			case ERROR :
				return ERROR;
			default :
				return c;
		}
	}
	return 0;
}

#ifdef ZD_FILESAVE
long zGetFileSize(void)
{
	return lFileSavePos;
}
char* zGetFiles(void)
{
	return pzFileSave;
}

///////////////////////////////////////////////////////////////////////////////
// free buffer to save receiving files.
void zFreeFiles(void)
{
	if(pzFileSave)
	{
		zFree(pzFileSave);
		pzFileSave = (char *)NULL;
	}
	lFileSavePos = 0;
}
#endif	// ZD_FILESAVE


///////////////////////////////////////////////////////////////////////////////
// long zReceive(unsigned char **pRcvFiles)
// 
// *pRcvFiles == NULL, buffer is malloced inside this function and *pRcvFiles is replaced with the start of buffer.
// *pRcvFiles != NULL, then *pRcvFiles is filled.
// 
// Remark : if you invoke by NULL, then buffer is malloced in the z module.
// so, It's the programmer's resposibility freeing *pRcvFiles after the zReceive().
// In that case, use the function zFreeFiles(); 
// 
// Note that zReceive file doesn't free the buffer unless zFreeFiles() is called.
// return : pRcvFiles's length.
long zReceive(unsigned char **pRcvFiles)
{
	register int c;

	// initialize the variable
//	glBytesLeft = 0;			/* number of bytes of incoming file left */
//	glTotalBytes = 0, glTotalLeft = 0;
//	glTotalFiles = 0, glFilesLeft = 0;

	// initialize file pointer
	pzFileSave = (char *)(*pRcvFiles);
	lFileSavePos = 0;

	// XXX : must delete after you implement malloc
	if(pzFileSave == NULL)
		return 0;
	/* XXX */

	TtyMode(1);		// mode to ZMODEM
	while(1)
	{
		c = ReadLine(0);	// forever
		if(c == 0x18)
			goto zEnd;
		if(c == ZPAD)
			break;
	}

	if((c = zTry()) != 0)
	{
		if(c == ZCOMPL)
		{
			goto zEnd;
		}
		if(c == ERROR)
		{
			goto zEnd;
		}
		c = zRcvFiles();
	}
	else
	{
	}

zEnd :
	// update for return value
	if(*pRcvFiles == NULL)
		*pRcvFiles = (unsigned char *)pzFileSave;
	
	TtyMode(0);	// STDOUT is possible now
	
	return lFileSavePos;
}

#endif//zmodem

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -