📄 zmodem.c
字号:
#ifndef lintstatic const char rcsid[] = "$Id: zmodem.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;#endif/* * Copyright (c) 1995 by Edward A. Falk *//********** * * * @@@@@ @ @ @@@ @@@@ @@@@@ @ @ * @ @@ @@ @ @ @ @ @ @@ @@ * @ @ @ @ @ @ @ @ @@@ @ @ @ * @ @ @ @ @ @ @ @ @ @ @ @ * @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @ @ * * ZMODEM - main logic parser for zmodem library * * * Routines provided here: * * * name (args) * Brief description. * * int ZmodemRcv(u_char *buffer, int len, ZModem *info) * Call whenever characters are received. If this function * returns ZmDone, previous function has completed successfully, * either call ZmodemTFile() to start next file, or call * ZmodemTFinish() to terminate the session. * * * int * ZmodemTimeout(ZModem *info) * Call whenever the timeout period expires and no * characters have been received. * * int * ZmodemAttention(ZModem *info) * Call whenever the attention sequence has been received * from the remote end. It is safe to call this function * from an interrupt handler. * * int * ZmodemAbort(ZModem *info) * Call to abort transfer. Physical connection remains * open until you close it. * * * * * Edward A. Falk * * January, 1995 * * * **********/#include <stdio.h>/**** * * Constants, typedefs, externals, globals, statics, macros, block data * ****//* TODO: sample input before initial send *//* TODO: more intelligent timeout dispatch *//* TODO: read all pending input before sending next data packet out *//* TODO: if received ZDATA while waiting for ZFILE/ZFIN, it's probably leftovers *//* TODO: enable flow control for zmodem, disable for X/YModem */#include <ctype.h>#include <errno.h>#include <string.h>#include "zmodem.h"#include "crctab.h"static u_char zeros[4] = {0,0,0,0} ;extern int YrcvChar( char c, register ZModem *info ) ;extern int YrcvTimeout( register ZModem *info ) ;extern void ZIdleStr(u_char *buffer, int len, ZModem *info) ; /* LEXICAL BOX: handle characters received from remote end. * These may be header, data or noise. * * This section is a finite state machine for parsing headers * and reading input data. The info->chrCount field is effectively * the state variable. */static int FinishChar( char c, register ZModem *info ) ;static int DataChar( u_char c, register ZModem *info ) ;static int HdrChar( u_char c, register ZModem *info ) ;static int IdleChar(u_char c, register ZModem *info) ;extern int YsendChar() ;static int ZProtocol(), ZDataReceived() ;intZmodemRcv( register u_char *str, int len, register ZModem *info ){register u_char c ; int err ; info->rcvlen = len ; while( --info->rcvlen >= 0 ) { c = *str++ ; if( c == CAN ) { if( ++info->canCount >= 5 ) { ZStatus(RmtCancel, 0, NULL) ; return ZmErrCancel ; } } else info->canCount = 0 ; if( info->InputState == Ysend ) { if( (err = YsendChar(c, info)) ) return err ; } else if( info->InputState == Yrcv ) { if( (err = YrcvChar(c, info)) ) return err ; } else if( c != XON && c != XOFF ) { /* now look at what we have */ switch( info->InputState ) { case Idle: if( (err = IdleChar(c, info)) ) return err ; break ; case Inhdr: if( (err = HdrChar(c, info)) ) return err ; break ; case Indata: if( (err = DataChar(c, info)) ) return err ; break ; case Finish: if( (err = FinishChar(c, info)) ) return err ; break ; default: break ; } } } return 0 ;} /* handle character input while idling * looking for ZPAD-ZDLE sequence which introduces a header */static intIdleChar(u_char c, register ZModem *info){ if( info->chrCount == 0 ) { if( c == ZPAD ) ++info->chrCount ; else if( info->state == Sending && ++info->noiseCount > MaxNoise ) info->waitflag = 1 ; else if( info->state == TStart && (c == 'C' || c == 'G' || c == NAK) ) { /* switch to ymodem */ info->state = YTStart ; info->InputState = Ysend ; info->Protocol = YMODEM ; return YsendChar(c, info) ; } else ZIdleStr(&c, 1, info) ; } else { switch( c ) { case ZPAD: ++info->chrCount ; break ; case ZDLE: info->InputState = Inhdr ; info->chrCount=0 ; break ; default: while( --info->chrCount >= 0 ) ZIdleStr((u_char *)"*", 1, info) ; info->chrCount = 0 ; break ; } } return 0 ;}static u_intrcvHex( u_int i, char c ){ if( c <= '9' ) c -= '0' ; else if( c <= 'F' ) c -= 'A'-10 ; else c -= 'a'-10 ; return (i<<4)+c ;} /* handle character input in a header */static intHdrChar( u_char c, register ZModem *info ){ int i ; int crc=0 ; if( c == ZDLE ) { info->escape = 1 ; return 0 ; } if( info->escape ) { info->escape = 0 ; switch( c ) { case ZRUB0: c = 0177 ; break ; case ZRUB1: c = 0377 ; break ; default: c ^= 0100 ; break ; } } if( info->chrCount == 0 ) { /* waiting for format */ switch( c ) { case ZHEX: case ZBIN: case ZBIN32: info->DataType = c ; info->chrCount = 1 ; info->crc = (info->DataType != ZBIN32) ? 0 : 0xffffffffL ; memset(info->hdrData,0,sizeof(info->hdrData)) ; break ; default: info->InputState = Idle ; info->chrCount = 0 ; return ZXmitHdrHex(ZNAK, zeros, info) ; } return 0 ; } switch( info->DataType ) { /* hex header is 14 hex digits, cr, lf. Optional xon is ignored */ case ZHEX: if( info->chrCount <= 14 && !isxdigit(c) ) { info->InputState = Idle ; info->chrCount = 0 ; return ZXmitHdrHex(ZNAK, zeros, info) ; } if( info->chrCount <= 14 ) { i = (info->chrCount-1)/2 ; info->hdrData[i] = rcvHex(info->hdrData[i], c) ; } if( info->chrCount == 16 ) { crc = 0 ; for(i=0; i<7; ++i) crc = updcrc(info->hdrData[i], crc) ; info->InputState = Idle ; info->chrCount = 0 ; if( (crc&0xffff) != 0 ) return ZXmitHdrHex(ZNAK, zeros, info) ; else return ZProtocol(info) ; } else ++info->chrCount ; break ; case ZBIN: /* binary header is type, 4 bytes data, 2 bytes CRC */ info->hdrData[info->chrCount-1] = c ; info->crc = updcrc(c, info->crc) ; if( ++info->chrCount > 7 ) { info->InputState = Idle ; info->chrCount = 0 ; if( (crc&0xffff) != 0 ) return ZXmitHdrHex(ZNAK, zeros, info) ; else return ZProtocol(info) ; } break ; case ZBIN32: /* binary32 header is type, 4 bytes data, 4 bytes CRC */ info->hdrData[info->chrCount-1] = c ; info->crc = UPDC32(c, info->crc) ; if( ++info->chrCount > 9 ) { info->InputState = Idle ; info->chrCount = 0 ; if( info->crc != 0xdebb20e3 ) /* see note below */ return ZXmitHdrHex(ZNAK, zeros, info) ; else return ZProtocol(info) ; } break ; } return 0 ;} /* handle character input in a data buffer */static intDataChar( u_char c, register ZModem *info ){ if( c == ZDLE ) { info->escape = 1 ; return 0 ; } if( info->escape ) { info->escape = 0 ; switch( c ) { case ZCRCE: case ZCRCG: case ZCRCQ: case ZCRCW: info->PacketType = c ; info->crcCount = (info->DataType == ZBIN32) ? 4 : 2 ; if( info->DataType == ZBIN ) info->crc = updcrc(c, info->crc) ; else info->crc = UPDC32(c, info->crc) ; return 0 ; case ZRUB0: c = 0177 ; break ; case ZRUB1: c = 0377 ; break ; default: c ^= 0100 ; break ; } } switch( info->DataType ) { /* TODO: are hex data packets ever used? */ case ZBIN: info->crc = updcrc(c, info->crc) ; if( info->crcCount == 0 ) info->buffer[info->chrCount++] = c ; else if( --info->crcCount == 0 ) { return ZDataReceived(info, (info->crc&0xffff) == 0) ; } break ; case ZBIN32: info->crc = UPDC32(c, info->crc) ; if( info->crcCount == 0 ) info->buffer[info->chrCount++] = c ; else if( --info->crcCount == 0 ) { return ZDataReceived(info, info->crc == 0xdebb20e3) ; } break ; } return 0 ;} /* wait for "OO" */static intFinishChar( char c, register ZModem *info ){ if( c == 'O' ) { if( ++info->chrCount >= 2 ) return ZmDone ; } else info->chrCount = 0 ; return 0 ;} int ZPF() ; int Ignore() ; int AnswerChallenge() ; int GotAbort() ; int GotCancel() ; int GotCommand() ; int GotStderr() ; int RetDone() ;static int GotCommandData() ;static int GotStderrData() ; /* PROTOCOL LOGIC: This section of code handles the actual * protocol. This is also driven by a finite state machine * * State tables are sorted by approximate frequency order to * reduce search time. */ /* Extra ZRINIT headers are the receiver trying to resync. */ /* If compiling for Send Only or Receive Only, convert table * entries to no-ops so we don't have to link zmodem[rt].o */#if SendOnly#define RStartOps DoneOps#define RSinitWaitOps DoneOps#define RFileNameOps DoneOps#define RCrcOps DoneOps#define RFileOps DoneOps
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -