📄 zmodemr.c
字号:
info->date = ZmGetLong(fileinfo, & pos, 8); /* %lo */ info->mode = ZmGetLong(fileinfo, & pos, 8); /* %o */ serial = ZmGetLong(fileinfo, & pos, 8); /* %o */ info->filesRem = ZmGetLong(fileinfo, & pos, 10); /* %d */ info->bytesRem = ZmGetLong(fileinfo, & pos, 10); /* %d */ info->fileType = ZmGetLong(fileinfo, & pos, 10); /* %d */ } /* got filename. Parse arguments from it and execute * policy function ZOpenFile(), provided by caller */int ZmGotFileName( ZModem *info, int crcGood ){ info->InputState = Idle; info->chrCount=0 ; if( !crcGood ) {#ifdef ZMODEMLOG zmodemlog("GotFileName[%s]: bad crc, send ZNAK\n", ZmSname(info)) ; info->state = RStart ;#endif // ZMODEMLOG return ZXmitHdrHex(ZNAK, ZmZeros, info) ; } ZmParseFileName(info, (char *)info->buffer) ; if( (info->f1 & ZMMASK) == ZMCRC ) { info->state = RCrc ; return ZXmitHdrHex(ZCRC, ZmZeros, info) ; }#ifdef ZMODEMLOG zmodemlog("GotFileName[%s]: good crc, call requestFile\n", ZmSname(info)) ;#endif // ZMODEMLOG info->state = RFile ; return ZmRequestFile(info,0) ;}int ZmResendCrcReq(ZModem *info){#ifdef ZMODEMLOG zmodemlog("ResendCrcReq[%s]: send ZCRC\n", ZmSname(info)) ;#endif // ZMODEMLOG return ZXmitHdrHex(ZCRC, ZmZeros, info) ;} /* received file CRC, now we're ready to accept or reject */static int ZmGotFileCrc( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("GotFileCrc[%s]: call requestFile\n", ZmSname(info)) ;#endif // ZMODEMLOG return ZmRequestFile(info, ZDec4(info->hdrData+1)) ;} /* last ZRPOS was bad, resend it */int ZmResendRpos( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("ResendRpos[%s]: send ZRPOS(%ld)\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;} /* recevied ZDATA header */static int ZmGotData( ZModem *info ){ int err ;#ifdef ZMODEMLOG zmodemlog("GotData[%s]:\n", ZmSname(info)) ;#endif // ZMODEMLOG if( ZDec4(info->hdrData+1) != info->offset ) { if( info->attn != NULL && (err=ZAttn(info)) != 0 ) return err ;#ifdef ZMODEMLOG zmodemlog(" bad, send ZRPOS(%ld)\n", info->offset);#endif // ZMODEMLOG return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ; } /* Let's do it! */#ifdef ZMODEMLOG zmodemlog(" call dataSetup\n");#endif // ZMODEMLOG return ZmDataSetup(info) ;} /* Utility: flush input, send attn, send specified header */static int ZmFileError( ZModem *info, int type, int data ){ int err ; info->InputState = Idle; info->chrCount=0 ; if( info->attn != NULL && (err=ZAttn(info)) != 0 ) return err ; return ZXmitHdrHex(type, ZEnc4(data), info) ;} /* received file data */int ZmGotFileData( ZModem *info, int crcGood ){ /* OK, now what? Fushing the buffers and executing the * attn sequence has likely chopped off the input stream * mid-packet. Now we switch to idle mode and treat all * incoming stuff like noise until we get a new valid * packet. */ if( !crcGood ) { /* oh bugger, an error. */#ifdef ZMODEMLOG zmodemlog( "GotFileData[%s]: bad crc, send ZRPOS(%ld), new state = RFile\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG ZStatus(DataErr, ++info->errCount, NULL) ; if( info->errCount > MaxErrs ) { ZmAbort(info) ; return ZmDataErr ; } else { info->state = RFile ; info->InputState = Idle; info->chrCount = 0; return ZmFileError(info, ZRPOS, info->offset) ; } } if( ZWriteFile(info->buffer, info->chrCount, info->file, info) ) { /* RED ALERT! Could not write the file. */ ZStatus(FileErr, 0, NULL) ; /* errno -> 0 */ info->state = RFinish ; info->InputState = Idle; info->chrCount=0 ; return(ZmFileError(info, ZFERR, 0)); /* errno -> 0 */ }#ifdef ZMODEMLOG zmodemlog("GotFileData[%s]: %ld.%d,", ZmSname(info), info->offset, info->chrCount) ;#endif // ZMODEMLOG info->offset += info->chrCount ; ZStatus(RcvByteCount, info->offset, NULL) ; /* if this was the last data subpacket, leave data mode */ if( info->PacketType == ZCRCE || info->PacketType == ZCRCW ) {#ifdef ZMODEMLOG zmodemlog(" ZCRCE|ZCRCW, new state RFile") ;#endif // ZMODEMLOG info->state = RFile ; info->InputState = Idle; info->chrCount=0 ; } else {#ifdef ZMODEMLOG zmodemlog(" call dataSetup") ;#endif // ZMODEMLOG (void) ZmDataSetup(info) ; } if( info->PacketType == ZCRCQ || info->PacketType == ZCRCW ) {#ifdef ZMODEMLOG zmodemlog(", send ZACK\n") ;#endif // ZMODEMLOG return ZXmitHdrHex(ZACK, ZEnc4(info->offset), info) ; } else#ifdef ZMODEMLOG zmodemlog("\n") ;#endif // ZMODEMLOG return 0 ;} /* received ZEOF packet, file is now complete */static int ZmGotEof( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("GotEof[%s]: offset=%ld\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG if( ZDec4(info->hdrData+1) != info->offset ) {#ifdef ZMODEMLOG zmodemlog(" bad length, state = RFile\n") ;#endif // ZMODEMLOG info->state = RFile ; return 0 ; /* it was probably spurious */ } /* TODO: if we can't close the file, send a ZFERR */ ZCloseFile(info->file, info); info->file = NULL; ZStatus(FileEnd, 0, info->filename); if(info->filename != NULL) { info->filename = NULL; } return(ZmSendRinit(info));}/* got ZFIN, respond in kind */static int ZmGotFin( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("GotFin[%s]: send ZFIN\n", ZmSname(info)) ;#endif // ZMODEMLOG info->InputState = Finish; info->chrCount = 0 ; if(info->filename != NULL) { info->filename = NULL; }// return ZXmitHdrHex(ZFIN, ZmZeros, info) ;}static int ZmGotFreecnt( ZModem *info ){ /* TODO: how do we find free space on system? */ return ZXmitHdrHex(ZACK, ZEnc4(0xffffffff), info) ;} /* YMODEM */static u_char AckStr[1] = {ACK} ;static u_char NakStr[1] = {NAK} ;static u_char CanStr[2] = {CAN,CAN} ;int YrcvChar( char c, ZModem *info ){ int err ; if( info->canCount >= 2 ) { ZStatus(RmtCancel, 0, NULL) ; return(ZmErrCancel); } switch( info->state ) { case YREOF: if( c == EOT ) { ZCloseFile(info->file, info) ; info->file = NULL ; ZStatus(FileEnd, 0, info->filename) ; if( info->filename != NULL ) { info->filename = NULL; } if( (err = ZmAcceptPacket(info)) != 0 ) return err ; info->packetCount = -1 ; info->offset = 0 ; info->state = YRStart ; return ZXmitStr((u_char *)"C", 1, info) ; }/* else, drop through */ case YRStart: case YRDataWait: switch( c ) { case SOH: case STX: info->pktLen = c == SOH ? (128+4) : (1024+4) ; info->state = YRData ; info->chrCount = 0 ; info->timeout = 1 ; info->noiseCount = 0 ; info->crc = 0 ; break ; case EOT: /* ignore first EOT to protect against false eot */ info->state = YREOF ; return ZmRejectPacket(info) ; default: if( ++info->noiseCount > 135 ) return ZXmitStr(NakStr, 1, info) ; break ; } break ; case YRData: info->buffer[info->chrCount++] = c ; if( info->chrCount >= info->pktLen ) return(ZmProcessPacket(info)); break ; default: break ; } return(0);}int YrcvTimeout( ZModem *info ){ switch( info->state ) { case YRStart: if( info->timeoutCount >= 10 ) { (void) ZXmitStr(CanStr, 2, info) ; return ZmErrInitTo ; } return ZXmitStr((u_char *)"C", 1, info) ; case YRDataWait: case YREOF: case YRData: if( info->timeoutCount >= 10 ) { (void) ZXmitStr(CanStr, 2, info) ; return ZmErrRcvTo ; } return ZXmitStr(NakStr, 1, info) ; default: return 0 ; }}static int ZmProcessPacket( ZModem *info ){ int idx = (u_char) info->buffer[0] ; int idxc = (u_char) info->buffer[1] ; int crc0, crc1 ; int err ; info->state = YRDataWait ; if( idxc != 255 - idx ) { ZStatus(DataErr, ++info->errCount, NULL) ; return(ZmRejectPacket(info)); } if( idx == (info->packetCount%256) ) /* quietly ignore dup */ return(ZmAcceptPacket(info)); if( idx != (info->packetCount+1)%256 ) { /* out of sequence */ (void) ZXmitStr(CanStr, 2, info) ; return ZmErrSequence ; } crc0 = (u_char)info->buffer[info->pktLen-2] << 8 | (u_char)info->buffer[info->pktLen-1] ; crc1 = ZmCalcCrc(info->buffer+2, info->pktLen-4) ; if( crc0 != crc1 ) { ZStatus(DataErr, ++info->errCount, NULL) ; return(ZmRejectPacket(info)); } ++info->packetCount ; if( info->packetCount == 0 ) /* packet 0 is filename */ { if( info->buffer[2] == '\0' ) { /* null filename is FIN */ (void)ZmAcceptPacket(info); return ZmDone ; } ZmParseFileName(info, (char *)info->buffer+2) ; info->file = ZOpenFile(info->filename, 0, info, 1); /* in write mode */ if( info->file == NULL ) { (void) ZXmitStr(CanStr, 2, info) ; return ZmErrCantOpen ; } if( (err = ZmAcceptPacket(info)) != 0 ) return err ; return ZXmitStr((u_char *)"C", 1, info) ; } if( ZWriteFile(info->buffer+2, info->pktLen-4, info->file, info) ) { ZStatus(FileErr, 0, NULL) ; /* errno -> 0 */ (void) ZXmitStr(CanStr, 2, info) ; return ZmErrSys ; } info->offset += info->pktLen-4 ; ZStatus(RcvByteCount, info->offset, NULL) ; (void) ZmAcceptPacket(info) ; return 0 ;}static int ZmRejectPacket( ZModem *info ){ info->timeout = 10 ; return ZXmitStr(NakStr, 1, info) ;}static int ZmAcceptPacket( ZModem *info ){ info->state = YRDataWait ; info->timeout = 10 ; return ZXmitStr(AckStr, 1, info) ;}static int ZmCalcCrc( u_char *str, int len ){ int crc = 0 ; while( --len >= 0 ) crc = updcrc(*str++, crc) ; crc = updcrc(0,crc) ; crc = updcrc(0,crc) ; return crc & 0xffff ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -