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

📄 xmodemr.c

📁 Gcomm is a serial communications program similar to seyon, but more modern, and easier to use. Works
💻 C
字号:
#ifndef lintstatic const char rcsid[] = "$Id: xmodemr.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;#endif lint/* * Copyright (c) 1995 by Edward A. Falk *//********** * * *	@   @  @   @   @@@   @@@@   @@@@@  @   @  @@@@    *	 @ @   @@ @@  @   @  @   @  @      @@ @@  @   @   *	  @    @ @ @  @   @  @   @  @@@    @ @ @  @@@@    *	 @ @   @ @ @  @   @  @   @  @      @ @ @  @  @    *	@   @  @ @ @   @@@   @@@@   @@@@@  @ @ @  @   @   * *	XMODEMR - receiver side of xmodem/ymodem protocol * *	Caller sets flags defined in xmodem.h as appropriate. *	(default is basic xmodem) * *	This code is designed to be called from inside a larger *	program, so it is implemented as a state machine where *	practical. * * *	functions: * *	XmodemRInit(char *filename, Protocol p) *		Initiate a receive * *	XmodemRTimeout() *		called after timeout expired * *	XmodemRRcv(char c) *		called after character received * *	XmodemRAbort() *		abort transfer * *	all functions return 0 on success, 1 on abort * * * *	Edward A. Falk * *	January, 1995 * * * **********/#include <stdio.h>#include <sys/types.h>#include "xmodem.h"	/* TODO: WXmodem */	bool	xmodem1k = False ;	Protocol protocol = Xmodem ;	int	xmTfd = -1 ;	int	xmRfd = -1 ;	int	xmTimeout = 0 ;	char	xmDefPath[MAXPATHLEN] ;	char	xmFilename[MAXPATHLEN] ;typedef	enum {	  Start,	/* waiting to begin */	  Init,		/* sent initial NAK, 'C' or 'W' */	  Packet,	/* receiving a packet */	  Wait,		/* wait for start of next packet */	} XmodemState ;static	bool		ymodem ;static	XmodemState	state = Start ;static	int		errorCount = 0 ;static	int		errorCount2 ;static	int		ignoreCount ;static	int		eotCount ;	/* count EOT's, reject first one */static	int		inCount ;	/* characters received this packet */static	int		pktLen ;	/* length of this packet data */static	int		pktHdrLen ;	/* id, cmpl, checksum or crc */static	char		packet[MAXPACKET+5], *optr ;static	int		packetId ;	/* id of last received packet */static	int		packetCount ;	/* # packets received */static	FILE		*ofile ;	/* output file fd */static	int		fileLen, fileDate, fileMode ;static	int	XmodemRStart() ;static	int	processPacket() ;static	int	rejectPacket() ;static	int	acceptPacket() ;intXmodemRInit( char *file, Protocol prot ){	int	err ;	state = Start ;	protocol = prot ;	ymodem = prot == Ymodem || prot == YmodemG ;	if( ymodem )	  strcpy(xmDefPath, file) ;	else	  strcpy(xmFilename, file) ;	eotCount = errorCount = errorCount2 = 0 ;	if( err=XmodemRStart() )	  return err ;	state = Init ;	packetId = ymodem ? 255 : 0 ;	packetCount = 0 ;	pktHdrLen = protocol == Xmodem ? 3 : 4 ;	return 0 ;}	/* send startup character */static	intXmodemRStart(){static	char	pchars[5] = {NAK,'C','W','C','C'} ;static	int	timeouts[5] = {INITTO, INITTO2, INITTO2, INITTO, INITTO} ;	char	c = pchars[(int)protocol] ;	int	err ;	if( err=sendFlush(c) )	  return err ;	xmTimeout = timeouts[(int)protocol] ;	return 0 ;}intXmodemRRcv(char c){	errorCount = 0 ;	switch( state ) {	  case Start:		/* shouldn't happen, ignore */	    if( c == CAN )	      return XmErrCancel ;	    break ;	  case Init:		/* waiting */	  case Wait:	    switch( c ) {	      case SOH:	      case STX:		pktLen = c == STX ? 1024 : 128 ;		inCount = 0 ;		optr = packet ;		state = Packet ;		xmTimeout = PKTTO ;		break ;	      case EOT:		if( ++eotCount > 1 ) {		  sendFlush(ACK) ;		  if( ymodem )		    return XmodemRInit() ;	/* restart protocol */		  else		    return XmDone ;		}		else		  return rejectPacket() ;	/* make xmitter try again */	      case CAN: return XmErrCancel ;	      default:		/* ignore all others */		if( ++ignoreCount > 1030 ) {		  ignoreCount = 0 ;		  return sendFlush(NAK) ;		}		break ;	    }	    break ;	  case Packet:		/* mid packet */	    *optr++ = c ;	    if( ++inCount >= pktLen + pktHdrLen )	      ProcessPacket() ;	    break ;	}	return 0 ;}intXmodemRTimeout(){	if( ++errorCount > MAXERROR )	  return state == Init ? XmErrInitTo : XmErrRcvTo ;	switch( state ) {	  case Start: return -1 ;		/* shouldn't happen */	  case Init:	    if( ++errorCount2 >= 3 )	      switch( protocol ) {		case WXmodem: protocol = XmodemCrc ; errorCount2 = 0 ; break ;		case XmodemCrc: protocol = Xmodem ; pktHdrLen = 3 ; break ;	      }	    return XmodemRStart() ;	  case Wait:			/* timeout while waiting */	  case Packet:			/* timeout in mid packet */	    return rejectPacket() ;	}}intXmodemRAbort(){	  return sendCancel() ;}static	intProcessPacket(){	int	id = (u_char)packet[0] ;	int	idc = (u_char)packet[1] ;	int	i ;	if( idc != 255-id )	  return rejectPacket() ;	if( id == packetId )		/* duplicate */	  return acceptPacket() ;	if( id != (packetId+1)%256 ) {	/* out of sequence */	  (void) sendCancel() ;	  return XmErrSequence ;	}	if( protocol == Xmodem )	{	  /* compute checksum */	  register int csum = calcChecksum(packet+2, pktLen) ;	  if( csum != (u_char) packet[2+pktLen] )	    return rejectPacket() ;	}	else	{	  int crc0 = (u_char)packet[pktLen+2] << 8 | (u_char)packet[pktLen+3] ;	  int crc1 = calcrc(packet+2, pktLen) ;	  if( crc0 != crc1 )	    return rejectPacket() ;	}	/* it's a good packet */	packetId = (packetId+1)%256 ;	/* is this the first packet? */	if( packetCount == 0 )	{	  if( ymodem )	  {	    if( packet[2] == '\0' )	/* last file */	    {	      (void) acceptPacket() ;	      return XmDone ;	    }	    if( packet[2] == '/' )	      strcpy(xmFilename, packet+2) ;	    else {	      strcpy(xmFilename, xmDefPath) ;	      strcat(xmFilename, packet+2) ;	    }	    fileLen = fileDate = fileMode = -1 ;	    sscanf(packet+2+strlen(packet)+1, "%d %o %o",		&fileLen, &fileDate, &fileMode) ;	  }	  if( (ofile = fopen(xmFilename, "w")) == NULL ) {	    sendCancel() ;	    return XmErrCantOpen ;	  }	  if( ymodem ) {	    packetCount = 1 ;	    (void) acceptPacket() ;	    return sendFlush('C') ;	  }	  else	    state = Packet ;	}	++packetCount ;	/* TODO: ymodem: if this is last packet, truncate it */	if( (i=fwrite(packet+2, 1, pktLen, ofile)) != pktLen )	{	  sendCancel() ;	  return XmErrSys ;	}	else	  return acceptPacket() ;}static	intrejectPacket(){	state = Wait ;	xmTimeout = INITTO ;	return sendFlush(NAK) ;}static	intacceptPacket(){	state = Wait ;	xmTimeout = INITTO ;	return sendFlush(ACK) ;}#ifdef	COMMENT		/* stand-alone testing */#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/time.h>#include <sys/termios.h>main(argc,argv)	int	argc ;	char	**argv ;{	struct	termios	old_settings, new_settings ;	fd_set	readfds ;	struct timeval timeout ;	int	i ;	int	len ;	char	buffer[1024] ;	bool	done = False ;	if( argc < 2 )	  exit(2) ;	xmTfd = xmRfd = open(argv[1], O_RDWR) ;	if( xmTfd == -1 )	  exit(1) ;	tcgetattr(xmTfd,&old_settings) ;	new_settings = old_settings ;	new_settings.c_iflag &=	  ~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;	new_settings.c_oflag = 0 ;	new_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;	new_settings.c_lflag = 0 ;	new_settings.c_cc[VMIN] = 32 ;	new_settings.c_cc[VTIME] = 1 ;	tcsetattr(xmTfd,TCSADRAIN, &new_settings) ;	xmodem1k = 0 ;	done = XmodemRInit("foo", XmodemCrc) != 0 ;#ifdef	COMMENT	xmodem1k = 1 ;	done = XmodemRInit("./", Ymodem) != 0 ;#endif	/* COMMENT */	while(!done)	{	  FD_ZERO(&readfds) ;	  FD_SET(xmTfd, &readfds) ;	  timeout.tv_sec = xmTimeout ;	  timeout.tv_usec = 0 ;	  i = select(xmTfd+1, &readfds,NULL,NULL, &timeout) ;	  if( i<0 )	    perror("select") ;	  else if( i==0 )	    done = XmodemRTimeout() != 0 ;	  else {	    len = read(xmTfd, buffer, sizeof(buffer)) ;	    for(i=0; !done && i<len; ++i)	      done = XmodemRRcv(buffer[i]) != 0 ;	  }	}	tcsetattr(xmTfd,TCSADRAIN, &old_settings) ;	exit(0) ;}#endif	/* COMMENT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -