📄 zmodem.c
字号:
#define RDataOps DoneOps#define RFinishOps DoneOps#define GotFileName Ignore#define ResendCrcReq Ignore#define GotSinitData Ignore#define ResendRpos Ignore#define GotFileData Ignore#define SendRinit Ignore#elseextern StateTable RStartOps[] ;extern StateTable RSinitWaitOps[] ;extern StateTable RFileNameOps[] ;extern StateTable RCrcOps[] ;extern StateTable RFileOps[] ;extern StateTable RDataOps[] ;extern StateTable RFinishOps[] ;extern int GotFileName() ;extern int ResendCrcReq() ;extern int GotSinitData() ;extern int ResendRpos() ;extern int GotFileData() ;extern int SendRinit() ;#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 SendMoreFileData Ignore#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[] ;extern int SendMoreFileData() ;#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,ZPF,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,ZPF,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,ZPF,0,0,StderrData}, } ;static StateTable DoneOps[] = { {99,ZPF,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 ZmodemRcv() * function when a full header has been received. */static intZProtocol( register ZModem *info ){register StateTable *table ; 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)) ; /* 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 ; zmodemlog(" state %s => %s, iflush=%d, oflush=%d, call %x\n", sname(info), sname2(table->newstate), table->IFlush, table->OFlush, table->func) ; info->state = table->newstate ; if( table->IFlush ) {info->rcvlen = 0 ; ZIFlush(info) ;} if( table->OFlush ) ZOFlush(info) ; return table->func(info) ;}static intZDataReceived( register ZModem *info, int crcGood ){ switch( info->state ) { case RSinitWait: return GotSinitData(info, crcGood) ; case RFileName: return GotFileName(info, crcGood) ; case RData: return GotFileData(info, crcGood) ; case CommandData: return GotCommandData(info, crcGood) ; case StderrData: return GotStderrData(info, crcGood) ; default: return ZPF(info) ; }}intZmodemTimeout( register ZModem *info ){ /* timed out while waiting for input */ ++info->timeoutCount ; zmodemlog("timeout %d [%s]\n", info->timeoutCount, sname(info) ) ; 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 SendRinit(info) ; case RCrc: case RFile: case RData: ZStatus(SndTimeout, info->timeoutCount, NULL) ; if( info->timeoutCount > 2 ) { info->timeoutCount = 0 ; info->state = RStart ; return SendRinit(info) ; } return info->state == RCrc ? ResendCrcReq(info) : ResendRpos(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 SendMoreFileData(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 ; }}intZmodemAttention( register ZModem *info ){ /* attention received from remote end */ if( info->state == Sending ) { ZOFlush(info) ; info->interrupt = 1 ; } return 0 ;}intZmodemAbort( register 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 */intIgnore( ZModem *info ){ return 0 ;} /* ignore header contents, return ZmDone */intRetDone( ZModem *info ){ return ZmDone ;} /* ignore header contents, return ZmErrCancel */intGotCancel( ZModem *info ){ return ZmErrCancel ;} /* utility: set up to receive a data packet */intdataSetup( register 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. */intGotCommand( ZModem *info ){ u_char rbuf[4] ; /* TODO: add command capability */ rbuf[0] = EPERM ; rbuf[1] = rbuf[2] = rbuf[3] = 0 ; return ZXmitHdrHex(ZCOMPL, rbuf, info) ;}static intGotCommandData( register ZModem *info ){/* TODO */return 0 ;} /* called when the remote system wants to put something to * stderr */intGotStderr( register ZModem *info ){ info->InputState = Indata ; info->chrCount = 0 ; return 0 ;}static intGotStderrData( register 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. */intZPF( ZModem *info ){ info->waitflag = 1 ; /* pause any in-progress transmission */ ZStatus(ProtocolErr, info->hdrData[0], NULL) ; return 0 ;}intAnswerChallenge( register ZModem *info ){ return ZXmitHdrHex(ZACK, info->hdrData+1, info) ;}intGotAbort( register ZModem *info ){ ZStatus(RmtCancel, 0, NULL) ; return ZXmitHdrHex(ZFIN, zeros, info) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -