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

📄 zmodemt.c

📁 Gcomm is a serial communications program similar to seyon, but more modern, and easier to use. Works
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic const char rcsid[] = "$Id: zmodemt.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;#endif/* * Copyright (c) 1995 by Edward A. Falk *//********** * * *	@@@@@  @   @   @@@   @@@@   @@@@@  @   @  @@@@@   *	   @   @@ @@  @   @  @   @  @      @@ @@    @     *	  @    @ @ @  @   @  @   @  @@@    @ @ @    @     *	 @     @ @ @  @   @  @   @  @      @ @ @    @     *	@@@@@  @ @ @   @@@   @@@@   @@@@@  @ @ @    @     * *	ZMODEMT - transmit side of zmodem protocol * * transmit side of zmodem protocol * * Caller sets flags defined in zmodem.h as appropriate. * (default is basic zmodem) * * functions: * *	ZmodemTInit(ZModem *info) *	YmodemTInit(ZModem *info) *	XmodemTInit(ZModem *info) *		Initiate a connection * *	ZmodemTFile(char *filename, u_char flags[4], ZModem *info) *		Initiate a file transfer.  Flags are as specified *		under "ZCBIN" in zmodem.h * *	ZmodemTFinish(ZModem *info) *		last file * *	ZmodemTAbort(ZModem *info) *		abort transfer * * all functions return 0 on success, 1 on abort * * *	Edward A. Falk * *	January, 1995 * * * **********/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/stat.h>#include "zmodem.h"#include "crctab.h"	int	SendMoreFileData( register ZModem *info ) ;extern	int	ZXmitData(int, int, u_char, u_char *data, ZModem *) ;extern	void	ZFlowControl(int onoff, ZModem *info) ;static	int	YXmitData() ;static	int	YSendFilename() ;static	int	YSendData() ;static	int	YSendFin() ;static	int	sendFilename() ;static	u_char	zeros[4] = {0,0,0,0} ;	/* called by user to establish protocol */intZmodemTInit( register ZModem *info ){	int	err ;	int	i ;	info->state = TStart ;	info->Protocol = ZMODEM ;	info->crc32 = 0 ;	info->packetCount = 0 ;	info->errCount = 0 ;	info->escCtrl = info->escHibit = info->atSign = info->escape = 0 ;	info->InputState = Idle ;	info->canCount = info->chrCount = 0 ;	info->windowCount = 0 ;	info->filename = NULL ;	info->bufsize = 0 ;	info->interrupt = 0 ;	info->waitflag = 0 ;	if( info->packetsize == 0 )	  info->packetsize = 256 ;	/* we won't be receiving much data, pick a reasonable buffer	 * size (largest packet will do)	 */	i = info->packetsize*2 ;	if( i < 1024 ) i = 1024 ;	info->buffer = (u_char *)malloc(i) ;	ZIFlush(info) ;	/* optional: send "rz\r" to remote end */	if( DoInitRZ ) {	  if( (err = ZXmitStr((u_char *)"rz\r", 3, info)) )	    return err ;	}	if( (err = ZXmitHdr(ZRQINIT, ZHEX, zeros, info)) ) /* nudge receiver */	  return err ;	info->timeout = 60 ;	zmodemlog("ZmodemTInit[%s]: sent ZRQINIT\n", sname(info)) ;	return 0 ;}	/* called by user to establish Ymodem protocol */intYmodemTInit( register ZModem *info ){	info->state = YTStart ;	info->Protocol = YMODEM ;	info->errCount = 0 ;	info->InputState = Ysend ;	info->canCount = info->chrCount = 0 ;	info->windowCount = 0 ;	info->filename = NULL ;	if( info->packetsize != 1024 )	  info->packetsize = 128 ;	info->buffer = (u_char *)malloc(1024) ;	ZIFlush(info) ;	ZFlowControl(0, info) ;	info->timeout = 60 ;	return 0 ;}	/* called by user to establish Xmodem protocol */intXmodemTInit( register ZModem *info ){	(void) YmodemTInit(info) ;	info->Protocol = XMODEM ;	return 0 ;}	/* called by user to begin transmission of a file */intZmodemTFile(	char	*file,	char	*rfile,	u_int	f0,	u_int	f1,	u_int	f2,	u_int	f3,	int	filesRem,	int	bytesRem,	ZModem	*info){	if( file == NULL || (info->file = fopen(file, "r")) == NULL )	  return ZmErrCantOpen ;	info->fileEof = 0 ;	info->filename = file ;	info->rfilename = (rfile != NULL) ? rfile : "noname" ;	info->filesRem = filesRem ;	info->bytesRem = bytesRem ;	info->fileFlags[3] = f0 ;	info->fileFlags[2] = f1 ;	info->fileFlags[1] = f2 ;	info->fileFlags[0] = f3 ;	info->offset = info->lastOffset = 0 ;	info->len = info->date = info->fileType = info->mode = 0 ;	if( info->filename != NULL )	{	  struct stat buf ;	  if( stat(info->filename, &buf) == 0 ) {	    info->len = buf.st_size ;	    info->date = buf.st_mtime ;	    info->fileType = 0 ;	    info->mode = (buf.st_mode&0777)|0100000 ;	  }	}	if( info->Protocol == XMODEM )	  return YSendData(info) ;	if( info->Protocol == YMODEM )	  return YSendFilename(info) ;	info->state = FileWait ;	zmodemlog("ZmodemTFile[%s]: send ZFILE(%s)\n",		sname(info), info->rfilename) ;	return sendFilename(info) ;}	/* send ZFILE header and filename & info.  Wait for response	 * from receiver.	 */static	intsendFilename( ZModem *info ){	int	err ;	int	i ;	u_char	obuf[2048] ;	u_char	*ptr = obuf ;	info->state = FileWait ;	if( (err = ZXmitHdr(ZFILE, ZBIN, info->fileFlags, info)) )	  return err ;	i = strlen(info->rfilename) ;	memcpy(ptr, info->rfilename, i+1) ;  ptr += i+1 ;	sprintf((char *)ptr, "%d %lo %o 0 %d %d 0", info->len, info->date,	  info->mode, info->filesRem, info->bytesRem) ;	ptr += strlen((char *)ptr) ;	*ptr++ = '\0' ;	return ZXmitData(ZBIN, ptr-obuf, ZCRCW, obuf, info) ;}	/* called by user when there are no more files to send */intZmodemTFinish( ZModem *info ){	if( info->Protocol == XMODEM )	  return ZmDone ;	if( info->Protocol == YMODEM )	  return YSendFin(info) ;	info->state = TFinish ;	if( info->buffer != NULL ) {	    free(info->buffer) ;	    info->buffer = NULL ;	}	zmodemlog("ZmodemTFinish[%s]: send ZFIN\n", sname(info)) ;	return ZXmitHdr(ZFIN, ZHEX, zeros, info) ;}extern	int	ZPF() ;extern	int	AnswerChallenge() ;extern	int	GotAbort() ;extern	int	Ignore() ;extern	int	RetDone() ;extern	int	GotCommand() ;extern	int	GotStderr() ;static	int	GotRinit() ;static	int	SendZSInit() ;static	int	SendFileCrc() ;static	int	GotSendAck() ;static	int	GotSendDoneAck() ;static	int	GotSendNak() ;static	int	GotSendWaitAck() ;static	int	SkipFile() ;static	int	GotSendPos() ;static	int	SendFileData() ;static	int	ResendEof() ;static	int	OverAndOut() ;		/* sent ZRQINIT, waiting for response */	StateTable	TStartOps[] = {		  {ZRINIT,GotRinit,1,1,TStart},	  {ZCHALLENGE,AnswerChallenge,1,0,TStart},	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {ZNAK,Ignore,0,0,TStart},	  {ZCOMMAND,GotCommand,0,0,CommandData},	  {ZSTDERR,GotStderr,0,0,StderrData},	  {99,ZPF,0,0,TStart},	} ;		/* sent ZSINIT, waiting for response */	StateTable	TInitOps[] = {	  {ZACK,RetDone,1,0,TInit},	  {ZNAK,SendZSInit,1,0,TInit},	  {ZRINIT,GotRinit,1,1,TInit},	/* redundant, but who cares */	  {ZCHALLENGE,AnswerChallenge,1,0,TInit},	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {ZCOMMAND,GotCommand,0,0,CommandData},	  {ZSTDERR,GotStderr,0,0,StderrData},	  {99,ZPF,0,0,TInit},	} ;		/* sent ZFILE, waiting for response */	StateTable	FileWaitOps[] = {	  {ZRPOS,SendFileData,1,0,Sending},	  {ZSKIP,SkipFile,1,0,FileWait},	  {ZCRC,SendFileCrc,1,0,FileWait},	  {ZNAK,sendFilename,1,0,FileWait},	  {ZRINIT,sendFilename,1,1,FileWait},	/* rcvr confused, retry file */	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {ZCHALLENGE,AnswerChallenge,1,0,FileWait},	  {ZCOMMAND,GotCommand,0,0,CommandData},	  {ZSTDERR,GotStderr,0,0,StderrData},	  {99,ZPF,0,0,FileWait},	} ;		/* sent file CRC, waiting for response */	StateTable	CrcWaitOps[] = {	  {ZRPOS,SendFileData,1,0,Sending},	  {ZSKIP,SkipFile,1,0,FileWait},	  {ZNAK,SendFileCrc,1,0,CrcWait},	  {ZRINIT,sendFilename,1,1,FileWait},	/* rcvr confused, retry file */	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {ZCRC,SendFileCrc,0,0,CrcWait},	  {ZCHALLENGE,AnswerChallenge,0,0,CrcWait},	  {ZCOMMAND,GotCommand,0,0,CommandData},	  {ZSTDERR,GotStderr,0,0,StderrData},	  {99,ZPF,0,0,CrcWait},	} ;		/* sending data, interruptable */	StateTable	SendingOps[] = {	  {ZACK,GotSendAck,0,0,Sending},	  {ZRPOS,GotSendPos,1,1,Sending},	  {ZSKIP,SkipFile,1,1,FileWait},	  {ZNAK,GotSendNak,1,1,Sending},	  {ZRINIT,sendFilename,1,1,FileWait},	/* rcvr confused, retry file */	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {99,ZPF,0,0,SendWait},	} ;		/* sent data, need to send EOF */	StateTable	SendDoneOps[] = {	  {ZACK,GotSendDoneAck,0,0,SendWait},	  {ZRPOS,GotSendPos,1,1,Sending},	  {ZSKIP,SkipFile,1,1,FileWait},	  {ZNAK,GotSendNak,1,1,Sending},	  {ZRINIT,sendFilename,1,1,FileWait},	/* rcvr confused, retry file */	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {99,ZPF,0,0,SendWait},	} ;		/* sending data, waiting for ACK */	StateTable	SendWaitOps[] = {	  {ZACK,GotSendWaitAck,0,0,Sending},	  {ZRPOS,GotSendPos,0,0,SendWait},	  {ZSKIP,SkipFile,1,1,FileWait},	  {ZNAK,GotSendNak,0,0,Sending},	  {ZRINIT,sendFilename,1,1,FileWait},	/* rcvr confused, retry file */	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {99,ZPF,0,0,SendWait},	} ;		/* sent ZEOF, waiting for new RINIT */	StateTable	SendEofOps[] = {	  {ZRINIT,SkipFile,1,0,TStart},	/* successful completion */	  {ZACK,Ignore,0,0,SendEof},	/* probably ACK from last packet */	  {ZRPOS,GotSendPos,1,1,SendWait},	  {ZSKIP,SkipFile,1,1,TStart},	  {ZNAK,ResendEof,1,0,SendEof},	  {ZRINIT,sendFilename,1,1,FileWait},	/* rcvr confused, retry file */	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {99,ZPF,0,0,SendEof},	} ;	StateTable	TFinishOps[] = {	  {ZFIN,OverAndOut,1,1,Done},	  {ZNAK,ZmodemTFinish,1,1,TFinish},	  {ZRINIT,ZmodemTFinish,1,1,TFinish},	  {ZABORT,GotAbort,1,1,TFinish},	  {ZFERR,GotAbort,1,1,TFinish},	  {99,ZPF,0,0,TFinish},	} ;extern	char	*hdrnames[] ;	/* Received Rinit.  Usually received while in start state,	 * this can also be an attempt to resync after a protocol	 * failure	 */static	intGotRinit( register ZModem *info ){	info->bufsize = info->hdrData[1] + info->hdrData[2]*256 ;	info->zrinitflags = info->hdrData[4] + info->hdrData[3]*256 ;	info->crc32 = info->zrinitflags & CANFC32 ;	info->escCtrl = info->zrinitflags & ESCCTL ;	info->escHibit = info->zrinitflags & ESC8 ;	/* Full streaming: If receiver can overlap I/O, and if	 * the sender can sample the reverse channel without hanging,	 * and the receiver has not specified a buffer size, then we	 * can simply blast away with ZCRCG packets.  If the receiver	 * detects an error, it sends an attn sequence and a new ZRPOS	 * header to restart the file where the error occurred.	 *	 * [note that zmodem8.doc does not define how much noise is	 * required to trigger a ZCRCW packet.  We arbitrarily choose	 * 64 bytes]	 *	 * If 'windowsize' is nonzero, and the receiver can do full	 * duplex, ZCRCQ packets are sent instead of ZCRCG, to keep track	 * of the number of characters in the queue.  If the queue fills	 * up, we pause and wait for a ZACK.	 *	 *	 * Full Streaming with Reverse Interrupt:  If sender cannot	 * sample the input stream, then we define an Attn sequence	 * that will be used to interrupt transmission.	 *	 *	 * Full Streaming with Sliding Window:  If sender cannot	 * sample input stream or respond to Attn signal, we send	 * several ZCRCQ packets until we're sure the receiver must	 * have sent back at least one ZACK.  Then we stop sending and	 * read that ZACK.  Then we send one more packet and so on.	 *	 *	 * Segmented Streaming:  If receiver cannot overlap I/O or can't do	 * full duplex and has specified a maximum receive buffer size,	 * whenever the buffer size is reached, we send a ZCRCW packet.	 *	 * TODO: what if receiver can't overlap, but hasn't set a buffer	 * size?	 *	 * ZCRCE: CRC next, frame ends, header follows	 * ZCRCG: CRC next, frame continues nonstop	 * ZCRCQ: CRC next, send ZACK, frame continues nonstop	 * ZCRCW: CRC next, send ZACK, frame ends, header follows	 */	ZFlowControl(1,info) ;	if( (info->zrinitflags & (CANFDX|CANOVIO)) == (CANFDX|CANOVIO) &&	    (SendSample||SendAttn)  &&	    info->bufsize == 0 )	{	  if( info->windowsize == 0 )	    info->Streaming = Full ;	  else	    info->Streaming = StrWindow ;	}	else if( (info->zrinitflags & (CANFDX|CANOVIO)) == (CANFDX|CANOVIO) &&	    info->bufsize == 0 )	{	  info->Streaming = SlidingWindow ;	}	else	  info->Streaming = Segmented ;	zmodemlog("GotRinit[%s]\n", sname(info)) ;	if( AlwaysSinit || info->zsinitflags != 0  ||  info->attn != NULL )	  return SendZSInit(info) ;	else	  return ZmDone ;	/* caller now calls ZmodemTFile() */}static	intSendZSInit( ZModem *info ){	int	err ;	char	*at = (info->attn != NULL) ? info->attn : "" ;	u_char	fbuf[4] ;	/* TODO: zmodem8.doc states: "If the ZSINIT header specifies	 * ESCCTL or ESC8, a HEX header is used, and the receiver	 * activates the specified ESC modes before reading the following	 * data subpacket." What does that mean?	 */	zmodemlog("SendZSInit[%s]\n", sname(info)) ;	info->state = TInit ;	fbuf[0] = fbuf[1] = fbuf[2] = 0 ;	fbuf[3] = info->zsinitflags ;	if( (err = ZXmitHdr(ZSINIT, ZBIN, fbuf, info))  ||	    (err = ZXmitData(ZBIN, strlen(at)+1, ZCRCW, (u_char *)at, info)) )	  return err ;	return 0 ;}static	intSendFileCrc( register ZModem *info ){	u_long	crc ;	crc = FileCrc(info->filename) ;	zmodemlog("SendFileCrc[%s]: %lx\n", sname(info), crc) ;	return ZXmitHdrHex(ZCRC, ZEnc4(crc), info) ;}	/* Utility: start sending data. */static	intstartFileData( register ZModem *info ){	int	err ;	info->offset =	info->lastOffset =	info->zrposOffset = ZDec4(info->hdrData+1) ;	fseek(info->file, info->offset, 0) ;	/* TODO: what if fseek fails?  Send EOF? */	zmodemlog("startFileData[%s]: %ld\n", sname(info), info->offset) ;	if( (err = ZXmitHdr(ZDATA, ZBIN, info->hdrData+1, info)) )	  return err ;	return SendMoreFileData(info) ;}	/* send a chunk of file data in response to a ZRPOS.  Whether this	 * is followed by a ZCRCE, ZCRCG, ZCRCQ or ZCRCW depends on all	 * sorts of protocol flags	 */static	intSendFileData( register ZModem *info ){	info->waitflag = 0 ;	return startFileData(info) ;}

⌨️ 快捷键说明

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