⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zmodem.c

📁 Gcomm is a serial communications program similar to seyon, but more modern, and easier to use. Works
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -