?? zmodemr.c
字號(hào):
#ifndef lintstatic const char rcsid[] = "$Id: zmodemr.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;#endif/* * Copyright (c) 1995 by Edward A. Falk *//********** * * * @@@@@ @ @ @@@ @@@@ @@@@@ @ @ @@@@ * @ @@ @@ @ @ @ @ @ @@ @@ @ @ * @ @ @ @ @ @ @ @ @@@ @ @ @ @@@@ * @ @ @ @ @ @ @ @ @ @ @ @ @ @ * @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @ @ @ @ * * ZMODEMR - receive side of zmodem protocol * * receive side of zmodem protocol * * This code is designed to be called from inside a larger * program, so it is implemented as a state machine where * practical. * * functions: * * ZmRInit(ZModem *info) * Initiate a connection * * ZmRAbort(ZModem *info) * abort transfer * * all functions return 0 on success, 1 on failure * * * Edward A. Falk * * January, 1995 * * * **********/#include "zmodem.h"#include "crctab.h"// static functions definition ///////////////////////////////////////////////static int ZmGotSinit( ZModem *info );static int ZmGotFile( ZModem *info );static int ZmRequestFile( ZModem *info, u_long crc );static void ZmParseFileName( ZModem *info, char *fileinfo );static int ZmGotFileCrc( ZModem *info );static int ZmGotData( ZModem *info );static int ZmFileError( ZModem *info, int type, int data );static int ZmGotEof( ZModem *info );static int ZmGotFin( ZModem *info );static int ZmGotFreecnt( ZModem *info );static int ZmProcessPacket( ZModem *info );static int ZmRejectPacket( ZModem *info );static int ZmAcceptPacket( ZModem *info );static int ZmCalcCrc( u_char *str, int len );//extern int errno ;static u_char ZmZeros[4] = {0,0,0,0} ;int ZmRInit(ZModem *info){ info->packetCount = 0; info->offset = 0; info->errCount = 0; info->escCtrl = info->escHibit = info->atSign = info->escape = 0; info->InputState = Idle; info->canCount = info->chrCount = 0; info->filename = NULL; info->interrupt = 0; info->waitflag = 0; info->attn = NULL; info->file = NULL;/* set buffer pointer to allocation buffer */ info->buffer = info->bufferalloc; info->state = RStart ; info->timeoutCount = 0 ; ZIFlush(info) ; /* Don't send ZRINIT right away, there might be a ZRQINIT in * the input buffer. Instead, set timeout to zero and return. * This will allow ZmRcv() to check the input stream first. * If nothing found, a ZRINIT will be sent immediately. */ info->timeout = 0 ;#ifdef ZMODEMLOG zmodemlog("ZmRInit[%s]: flush input, new state = RStart\n", ZmSname(info)) ;#endif // ZMODEMLOG return(0);}int YmodemRInit(ZModem *info){ info->errCount = 0; info->InputState = Yrcv; info->canCount = info->chrCount = 0; info->noiseCount = 0; info->filename = NULL; info->file = NULL; if( info->buffer == NULL ) {/* set buffer pointer to allocation buffer */ info->buffer = info->bufferalloc; } info->state = YRStart ; info->packetCount = -1 ; info->timeoutCount = 0 ; info->timeout = 10 ; info->offset = 0 ; ZIFlush(info) ; return(ZXmitStr((u_char *)"C", 1, info));} /* sent ZRINIT, waiting for ZSINIT or ZFILE */ StateTable RStartOps[] = { {ZSINIT,ZmGotSinit,0,1,RSinitWait}, /* SINIT, wait for attn str */ {ZFILE,ZmGotFile,0,0,RFileName}, /* FILE, wait for filename */ {ZRQINIT,ZmSendRinit,0,1,RStart}, /* sender confused, resend */ {ZFIN,ZmGotFin,1,0,RFinish}, /* sender shutting down */ {ZNAK,ZmSendRinit,1,0,RStart}, /* RINIT was bad, resend */#ifdef TODO {ZCOMPL,f,1,1,s},#endif /* TODO */ {ZFREECNT,ZmGotFreecnt,0,0,RStart}, /* sender wants free space */ {ZCOMMAND,ZmGotCommand,0,0,CommandData}, /* sender wants command */ {ZSTDERR,ZmGotStderr,0,0,StderrData}, /* sender wants to send msg */ {99,ZmZPF,0,0,RStart}, /* anything else is an error */ } ; StateTable RSinitWaitOps[] = { /* waiting for data */ {99,ZmZPF,0,0,RSinitWait}, } ; StateTable RFileNameOps[] = { /* waiting for file name */ {99,ZmZPF,0,0,RFileName}, } ; StateTable RCrcOps[] = { /* waiting for CRC */ {ZCRC,ZmGotFileCrc,0,0,RFile}, /* sender sent it */ {ZNAK,ZmResendCrcReq,0,0,RCrc}, /* ZCRC was bad, resend */ {ZRQINIT,ZmSendRinit,1,1,RStart}, /* sender confused, restart */ {ZFIN,ZmGotFin,1,1,RFinish}, /* sender signing off */ {99,ZmZPF,0,0,RCrc}, } ; StateTable RFileOps[] = { /* waiting for ZDATA */ {ZDATA,ZmGotData,0,0,RData}, /* got it */ {ZNAK,ZmResendRpos,0,0,RFile}, /* ZRPOS was bad, resend */ {ZEOF,ZmGotEof,0,0,RStart}, /* end of file */ {ZRQINIT,ZmSendRinit,1,1,RStart}, /* sender confused, restart */ {ZFILE,ZmResendRpos,0,0,RFile}, /* ZRPOS was bad, resend */ {ZFIN,ZmGotFin,1,1,RFinish}, /* sender signing off */ {99,ZmZPF,0,0,RFile}, } ; /* waiting for data, but a packet could possibly arrive due * to error recovery or something */ StateTable RDataOps[] = { {ZRQINIT,ZmSendRinit,1,1,RStart}, /* sender confused, restart */ {ZFILE,ZmGotFile,0,1,RFileName}, /* start a new file (??) */ {ZNAK,ZmResendRpos,1,1,RFile}, /* ZRPOS was bad, resend */ {ZFIN,ZmGotFin,1,1,RFinish}, /* sender signing off */ {ZDATA,ZmGotData,0,1,RData}, /* file data follows */ {ZEOF,ZmGotEof,1,1,RStart}, /* end of file */ {99,ZmZPF,0,0,RData}, } ; /* here if we've sent ZFERR or ZABORT. Waiting for ZFIN */ StateTable RFinishOps[] = { {ZRQINIT,ZmSendRinit,1,1,RStart}, /* sender confused, restart */ {ZFILE,ZmGotFile,1,1,RFileName}, /* start a new file */ {ZNAK,ZmGotFin,1,1,RFinish}, /* resend ZFIN */ {ZFIN,ZmGotFin,1,1,RFinish}, /* sender signing off */ {99,ZmZPF,0,0,RFinish}, } ;extern char *hdrnames[] ;/* RECEIVE-RELATED STUFF BELOW HERE *//* resend ZRINIT header in response to ZRQINIT or ZNAK header */int ZmSendRinit( ZModem *info ){ u_char dbuf[4] ;#ifdef COMMENT if( info->timeoutCount >= 5 ) /* TODO: switch to Ymodem */#endif /* COMMENT */#ifdef ZMODEMLOG zmodemlog("SendRinit[%s]: send ZRINIT\n", ZmSname(info)) ;#endif // ZMODEMLOG info->timeout = ResponseTime ; dbuf[0] = info->bufsize&0xff ; dbuf[1] = (info->bufsize>>8)&0xff ; dbuf[2] = 0 ; dbuf[3] = info->zrinitflags ; return(ZXmitHdrHex(ZRINIT, dbuf, info));} /* received a ZSINIT header in response to ZRINIT */static int ZmGotSinit( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("GotSinit[%s]: call dataSetup\n", ZmSname(info)) ;#endif // ZMODEMLOG info->zsinitflags = info->hdrData[4] ; info->escCtrl = info->zsinitflags & TESCCTL ; info->escHibit = info->zsinitflags & TESC8 ; ZFlowControl(1, info) ; return ZmDataSetup(info) ;} /* received rest of ZSINIT packet */int ZmGotSinitData( ZModem *info, int crcGood ){ info->InputState = Idle; info->chrCount=0 ; info->state = RStart ;#ifdef ZMODEMLOG zmodemlog("GotSinitData[%s]: crcGood=%d\n", ZmSname(info), crcGood) ;#endif // ZMODEMLOG if( !crcGood ) { return ZXmitHdrHex(ZNAK, ZmZeros, info) ; } info->attn = NULL; if(info->buffer[0] != '\0' ) { int pos; /* buffer position */ info->attn = info->attnbuf; /* set attn pointer to buffer */ pos = 0; /* start position */ while(1) { if(pos + 1 >= sizeof(info->attnbuf)) { info->attnbuf[pos] = '\0'; /* terminating character */ break; } info->attnbuf[pos] = *(info->buffer + pos); if(info->attnbuf[pos] == '\0') { break; } // pos++; } } return(ZXmitHdrHex(ZACK, ZEnc4(SerialNo), info));} /* got ZFILE. Cache flags and set up to receive filename */static int ZmGotFile( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("GotFile[%s]: call dataSetup\n", ZmSname(info)) ;#endif // ZMODEMLOG info->errCount = 0 ; info->f0 = info->hdrData[4] ; info->f1 = info->hdrData[3] ; info->f2 = info->hdrData[2] ; info->f3 = info->hdrData[1] ; return ZmDataSetup(info) ;} /* utility: see if ZOpenFile wants this file, and if * so, request it from sender. */static int ZmRequestFile( ZModem *info, u_long crc ){/* open file in write mode (last parameter 1) */ info->file = ZOpenFile((char *)info->buffer, crc, info, 1); if( info->file == NULL ) {#ifdef ZMODEMLOG zmodemlog("requestFile[%s]: send ZSKIP\n", ZmSname(info)) ;#endif // ZMODEMLOG info->state = RStart ; ZStatus(FileSkip, 0, info->filename) ; return ZXmitHdrHex(ZSKIP, ZmZeros, info) ; } else {#ifdef ZMODEMLOG zmodemlog("ZmRequestFile[%s]: send ZRPOS(%ld)\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG info->offset = info->f0 == ZCRESUM ? ZFileTell(info->file, info) : 0 ; info->state = RFile; ZStatus(FileBegin, 0, info->filename) ; return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ; }}/* read long from string */static long ZmGetLong(char * buf, int * pos, int radix){ long val; /* return value */ if(buf == 0 || pos == 0) { return(0); } /* skeep leading zeros */ while(*(buf + *pos) == ' ') { (*pos) += 1; } if(*(buf + *pos) == '\0') { return(0); } // val = 0; /* start return value */ while(1) { u_char ch; ch = *(buf + *pos); /* read character from buffer */ if(radix == 10) {/* decimal */ if(ch >= '0' && ch <= '9') { val = val * 10 + (ch - '0'); } else { break; } } else if(radix == 8) {/* octal */ if(ch >= '0' && ch <= '7') { val = (val << 3) | (ch - '0'); } else { break; } } else if(radix == 16) {/* hexadecimal */ if(ch >= '0' && ch <= '9') { val = (val << 4) | (ch - '0'); } else if(ch >= 'a' && ch <= 'f') { val = (val << 4) | (10 + (ch - 'a')); } else if(ch >= 'A' && ch <= 'F') { val = (val << 4) | (10 + (ch - 'A')); } else { break; } }// (*pos) += 1; /* move to next position */ }// return(val);}/* parse filename info. */static void ZmParseFileName( ZModem *info, char *fileinfo ){ int serial = 0; int pos; info->len = 0; info->mode = 0; info->filesRem = 0; info->bytesRem = 0; info->fileType = 0;// info->filename = info->filenamebuf;// pos = 0; while(*(fileinfo + pos) != '\0') { if(pos < sizeof(info->filenamebuf)) { info->filenamebuf[pos] = *(fileinfo+pos); } pos++; } if(pos >= sizeof(info->filenamebuf)) { info->filenamebuf[sizeof(info->filenamebuf) - 1] = '\0'; } else { info->filenamebuf[pos] = '\0'; }// pos += 1; /* skip terminating null */ info->len = ZmGetLong(fileinfo, & pos, 10); /* %d */
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -