📄 zmodem.c
字号:
extern StateTable RFileOps[] ;extern StateTable RDataOps[] ;extern StateTable RFinishOps[] ;#endif#if RcvOnly#define TStartOps DoneOps#define TInitOps DoneOps#define FileWaitOps DoneOps#define CrcWaitOps DoneOps#define SendingOps DoneOps#define SendDoneOps DoneOps#define SendWaitOps DoneOps#define SendEofOps DoneOps#define TFinishOps DoneOps#define ZmSendMoreFileData ZmIgnore#elseextern StateTable TStartOps[] ;extern StateTable TInitOps[] ;extern StateTable FileWaitOps[] ;extern StateTable CrcWaitOps[] ;extern StateTable SendingOps[] ;extern StateTable SendDoneOps[] ;extern StateTable SendWaitOps[] ;extern StateTable SendEofOps[] ;extern StateTable TFinishOps[] ;#endifstatic StateTable CommandDataOps[] = {#ifdef COMMENT {ZRQINIT,f,1,1}, {ZRINIT,f,1,1}, {ZSINIT,f,1,1}, {ZACK,f,1,1}, {ZFILE,f,1,1}, {ZSKIP,f,1,1}, {ZNAK,f,1,1}, {ZABORT,f,1,1,TFinish}, {ZFIN,f,1,1}, {ZRPOS,f,1,1}, {ZDATA,f,1,1}, {ZEOF,f,1,1}, {ZFERR,f,1,1,TFinish}, {ZCRC,f,1,1}, {ZCHALLENGE,f,1,1}, {ZCOMPL,f,1,1}, {ZCAN,f,1,1}, {ZFREECNT,f,1,1}, {ZCOMMAND,f,1,1}, {ZSTDERR,f,1,1},#endif /* COMMENT */ {99,ZmZPF,0,0,CommandData}, } ;static StateTable CommandWaitOps[] = {#ifdef COMMENT {ZRQINIT,f,1,1}, {ZRINIT,f,1,1}, {ZSINIT,f,1,1}, {ZACK,f,1,1}, {ZFILE,f,1,1}, {ZSKIP,f,1,1}, {ZNAK,f,1,1}, {ZABORT,f,1,1,TFinish}, {ZFIN,f,1,1}, {ZRPOS,f,1,1}, {ZDATA,f,1,1}, {ZEOF,f,1,1}, {ZFERR,f,1,1,TFinish}, {ZCRC,f,1,1}, {ZCHALLENGE,f,1,1}, {ZCOMPL,f,1,1}, {ZCAN,f,1,1}, {ZFREECNT,f,1,1}, {ZCOMMAND,f,1,1}, {ZSTDERR,f,1,1},#endif /* COMMENT */ {99,ZmZPF,0,0,CommandWait}, } ;static StateTable StderrDataOps[] = {#ifdef COMMENT {ZRQINIT,f,1,1}, {ZRINIT,f,1,1}, {ZSINIT,f,1,1}, {ZACK,f,1,1}, {ZFILE,f,1,1}, {ZSKIP,f,1,1}, {ZNAK,f,1,1}, {ZABORT,f,1,1,TFinish}, {ZFIN,f,1,1}, {ZRPOS,f,1,1}, {ZDATA,f,1,1}, {ZEOF,f,1,1}, {ZFERR,f,1,1,TFinish}, {ZCRC,f,1,1}, {ZCHALLENGE,f,1,1}, {ZCOMPL,f,1,1}, {ZCAN,f,1,1}, {ZFREECNT,f,1,1}, {ZCOMMAND,f,1,1}, {ZSTDERR,f,1,1},#endif /* COMMENT */ {99,ZmZPF,0,0,StderrData}, } ;static StateTable DoneOps[] = { {99,ZmZPF,0,0,Done}, } ;static StateTable *tables[] = { RStartOps, RSinitWaitOps, RFileNameOps, RCrcOps, RFileOps, RDataOps, RDataOps, /* RDataErr is the same as RData */ RFinishOps, TStartOps, TInitOps, FileWaitOps, CrcWaitOps, SendingOps, SendWaitOps, SendDoneOps, SendEofOps, TFinishOps, CommandDataOps, CommandWaitOps, StderrDataOps, DoneOps, } ; char *hdrnames[] = { "ZRQINIT", "ZRINIT", "ZSINIT", "ZACK", "ZFILE", "ZSKIP", "ZNAK", "ZABORT", "ZFIN", "ZRPOS", "ZDATA", "ZEOF", "ZFERR", "ZCRC", "ZCHALLENGE", "ZCOMPL", "ZCAN", "ZFREECNT", "ZCOMMAND", "ZSTDERR", } ; /* This function is called (indirectly) by the ZmRcv() * function when a full header has been received. */static int ZmProtocol( ZModem *info ){ StateTable *table ;#ifdef ZMODEMLOG zmodemlog ( "received %s: %2.2x %2.2x %2.2x %2.2x = %lx\n", hdrnames[info->hdrData[0]] , info->hdrData[1] , info->hdrData[2] , info->hdrData[3] , info->hdrData[4] , ZDec4(info->hdrData+1) );#endif // ZMODEMLOG/* Flags are sent in F3 F2 F1 F0 order. Data is sent in P0 P1 P2 P3 */ info->timeoutCount = 0 ; info->noiseCount = 0 ; table = tables[(int)info->state] ; while( table->type != 99 && table->type != info->hdrData[0] ) ++table ;#ifdef ZMODEMLOG zmodemlog( " state %s => %s, iflush=%d, oflush=%d, call %x\n", ZmSname(info), ZmSname2(table->newstate), table->IFlush, table->OFlush, table->func);#endif // ZMODEMLOG info->state = table->newstate ; if( table->IFlush ) {info->rcvlen = 0 ; ZIFlush(info) ;} if( table->OFlush ) ZOFlush(info) ; return table->func(info) ;}static int ZmDataReceived( ZModem *info, int crcGood ){ switch( info->state ) { case RSinitWait : return(ZmGotSinitData(info, crcGood)); case RFileName : return(ZmGotFileName(info, crcGood)); case RData : return(ZmGotFileData(info, crcGood)); case CommandData: return(ZmGotCommandData(info /*, crcGood */)) ; case StderrData : return(ZmGotStderrData(info)) ; default: return ZmZPF(info) ; }}int ZmTimeout(ZModem *info ){ /* timed out while waiting for input */ ++info->timeoutCount ;#ifdef ZMODEMLOG zmodemlog("timeout %d [%s]\n", info->timeoutCount, ZmSname(info) ) ;#endif // ZMODEMLOG switch( info->state ) { /* receive */ case RStart: /* waiting for INIT frame from other end */ if( info->timeoutCount > 4 ) return YmodemRInit(info) ; case RSinitWait: case RFileName: if( info->timeout > 0 ) ZStatus(SndTimeout, info->timeoutCount, NULL) ; if( info->timeoutCount > 4 ) return ZmErrRcvTo ; info->state = RStart ; return (ZmSendRinit(info)) ; case RCrc: case RFile: case RData: ZStatus(SndTimeout, info->timeoutCount, NULL) ; if( info->timeoutCount > 2 ) { info->timeoutCount = 0 ; info->state = RStart ; return (ZmSendRinit(info)); } return info->state == RCrc ? ZmResendCrcReq(info) : ZmResendRpos(info) ; case RFinish: ZStatus(SndTimeout, info->timeoutCount, NULL) ; return ZmDone ; case YRStart: case YRDataWait: case YRData: case YREOF: return YrcvTimeout(info) ; /* transmit */ case TStart: /* waiting for INIT frame from other end */ case TInit: /* sent INIT, waiting for ZACK */ case FileWait: /* sent file header, waiting for ZRPOS */ case CrcWait: /* sent file crc, waiting for ZRPOS */ case SendWait: /* waiting for ZACK */ case SendEof: /* sent EOF, waiting for ZACK */ case TFinish: /* sent ZFIN, waiting for ZFIN */ case YTStart: case YTFile: case YTDataWait: case YTData: case YTEOF: case YTFin: ZStatus(RcvTimeout,0,NULL) ; return ZmErrRcvTo ; case Sending: /* sending data subpackets, ready for int */ return (ZmSendMoreFileData(info)); /* general */ case CommandData: /* waiting for command data */ case StderrData: /* waiting for stderr data */ return ZmErrSndTo ; case CommandWait: /* waiting for command to execute */ return ZmErrCmdTo ; case Done: return ZmDone ; default: return 0 ; }}int ZmAttention( ZModem *info ){ /* attention received from remote end */ if( info->state == Sending ) { ZOFlush(info) ; info->interrupt = 1 ; } return 0 ;}int ZmAbort( ZModem *info ){static u_char canistr[] = { CAN,CAN,CAN,CAN,CAN,CAN,CAN,CAN,8,8,8,8,8,8,8,8,8,8 } ; info->state = Done ; ZIFlush(info) ; ZOFlush(info) ; return ZXmitStr(canistr, sizeof(canistr), info) ;} /* used to completely ignore headers */int ZmIgnore( ZModem *info ){ return 0 ;} /* ignore header contents, return ZmDone */int ZmRetDone( ZModem *info ){ return ZmDone ;} /* ignore header contents, return ZmErrCancel */int ZmGotCancel( ZModem *info ){ return ZmErrCancel ;} /* utility: set up to receive a data packet */int ZmDataSetup( ZModem *info ){ info->InputState = Indata; info->chrCount = 0; info->crcCount = 0; info->crc = (info->DataType != ZBIN32) ? 0 : 0xffffffffL ; return 0 ;}/* called when a remote command received. For now, we * refuse to execute commands. Send EPERM and ignore. */int ZmGotCommand( ZModem *info ){ u_char rbuf[4] ;/* TODO: add command capability */ rbuf[0] = 1; /* EPERM */ rbuf[1] = rbuf[2] = rbuf[3] = 0 ; return ZXmitHdrHex(ZCOMPL, rbuf, info) ;}static int ZmGotCommandData( ZModem *info ){/* TODO */return 0 ;} /* called when the remote system wants to put something to * stderr */int ZmGotStderr( ZModem *info ){ info->InputState = Indata; info->chrCount = 0 ; return(0);}static int ZmGotStderrData( ZModem *info){ info->buffer[info->chrCount] = '\0' ; ZStatus(RemoteMessage, info->chrCount, (char *)info->buffer) ; return(0);}/* Protocol failure: An unexpected packet arrived. This could * be from many sources, such as old pipelined info finally arriving * or a serial line with echo enabled. Report it and ignore it. */int ZmZPF( ZModem *info ){ info->waitflag = 1 ; /* pause any in-progress transmission */ ZStatus(ProtocolErr, info->hdrData[0], NULL) ; return(0);}int ZmAnswerChallenge( ZModem *info ){ return ZXmitHdrHex(ZACK, info->hdrData+1, info) ;}int ZmGotAbort( ZModem *info ){ ZStatus(RmtCancel, 0, NULL) ; return ZXmitHdrHex(ZFIN, ZmZeros, info) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -