zmodemr.c

来自「Gcomm is a serial communications program」· C语言 代码 · 共 751 行 · 第 1/2 页

C
751
字号
ResendCrcReq(ZModem *info){	zmodemlog("ResendCrcReq[%s]: send ZCRC\n", sname(info)) ;	return ZXmitHdrHex(ZCRC, zeros, info) ;}	/* received file CRC, now we're ready to accept or reject */static	intGotFileCrc( register ZModem *info ){	zmodemlog("GotFileCrc[%s]: call requestFile\n", sname(info)) ;	return requestFile(info, ZDec4(info->hdrData+1)) ;}	/* last ZRPOS was bad, resend it */intResendRpos( register ZModem *info ){	zmodemlog("ResendRpos[%s]: send ZRPOS(%ld)\n",	  sname(info), info->offset) ;	return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;}	/* recevied ZDATA header */static	intGotData( register ZModem *info ){	int	err ;	zmodemlog("GotData[%s]:\n", sname(info)) ;	if( ZDec4(info->hdrData+1) != info->offset ) {	  if( info->attn != NULL  &&  (err=ZAttn(info)) != 0 )	    return err ;	  zmodemlog("  bad, send ZRPOS(%ld)\n", info->offset);	  return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;	}	/* Let's do it! */	zmodemlog("  call dataSetup\n");	return dataSetup(info) ;}	/* Utility: flush input, send attn, send specified header */static	intfileError( register 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 */intGotFileData( register 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. */	  zmodemlog(	    "GotFileData[%s]: bad crc, send ZRPOS(%ld), new state = RFile\n",	    sname(info), info->offset) ;	  ZStatus(DataErr, ++info->errCount, NULL) ;	  if( info->errCount > MaxErrs ) {	    ZmodemAbort(info) ;	    return ZmDataErr ;	  }	  else {	    info->state = RFile ;	    info->InputState = Idle ;	    info->chrCount=0 ;	    return fileError(info, ZRPOS, info->offset) ;	  }	}	if( ZWriteFile(info->buffer, info->chrCount, info->file, info) )	{	  /* RED ALERT!  Could not write the file. */	  ZStatus(FileErr, errno, NULL) ;	  info->state = RFinish ;	  info->InputState = Idle ;	  info->chrCount=0 ;	  return fileError(info, ZFERR, errno) ;	}	zmodemlog("GotFileData[%s]: %ld.%d,",	  sname(info), info->offset, info->chrCount) ;	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 ) {	  zmodemlog("  ZCRCE|ZCRCW, new state RFile") ;	  info->state = RFile ;	  info->InputState = Idle ;	  info->chrCount=0 ;	}	else {	  zmodemlog("  call dataSetup") ;	  (void) dataSetup(info) ;	}	if( info->PacketType == ZCRCQ || info->PacketType == ZCRCW ) {	  zmodemlog(",  send ZACK\n") ;	  return ZXmitHdrHex(ZACK, ZEnc4(info->offset), info) ;	}	else	zmodemlog("\n") ;	return 0 ;}	/* received ZEOF packet, file is now complete */static	intGotEof( register ZModem *info ){	zmodemlog("GotEof[%s]: offset=%ld\n", sname(info), info->offset) ;	if( ZDec4(info->hdrData+1) != info->offset ) {	  zmodemlog("  bad length, state = RFile\n") ;	  info->state = RFile ;	  return 0 ;		/* it was probably spurious */	}	/* TODO: if we can't close the file, send a ZFERR */	ZCloseFile(info) ; info->file = NULL ;	ZStatus(FileEnd, 0, info->filename) ;	if( info->filename != NULL ) {	  free(info->filename) ;	  info->filename = NULL ;	}	return SendRinit(info) ;}	/* got ZFIN, respond in kind */static	intGotFin( register ZModem *info ){	zmodemlog("GotFin[%s]: send ZFIN\n", sname(info)) ;	info->InputState = Finish ;	info->chrCount = 0 ;	if( info->filename != NULL )	  free(info->filename) ;	return ZXmitHdrHex(ZFIN, zeros, info) ;}static	intGotFreecnt( register 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} ;static	int	ProcessPacket() ;static	int	acceptPacket() ;static	int	rejectPacket() ;static	int	calcCrc() ;intYrcvChar( char c, register ZModem *info ){	int	err ;	if( info->canCount >= 2 ) {	  ZStatus(RmtCancel, 0, NULL) ;	  return ZmErrCancel ;	}	switch( info->state ) {	  case YREOF:	    if( c == EOT ) {	      ZCloseFile(info) ; info->file = NULL ;	      ZStatus(FileEnd, 0, info->filename) ;	      if( info->filename != NULL )		free(info->filename) ;	      if( (err = acceptPacket(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 rejectPacket(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 ProcessPacket(info) ;	    break ;	  default:	    break ;	}	return 0 ;}intYrcvTimeout( register 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	intProcessPacket( register 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 rejectPacket(info) ;	}	if( idx == (info->packetCount%256) )	/* quietly ignore dup */	  return acceptPacket(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 = calcCrc(info->buffer+2, info->pktLen-4) ;	if( crc0 != crc1 ) {	  ZStatus(DataErr, ++info->errCount, NULL) ;	  return rejectPacket(info) ;	}	++info->packetCount ;	if( info->packetCount == 0 )		/* packet 0 is filename */	{	  if( info->buffer[2] == '\0' ) {	/* null filename is FIN */	    (void) acceptPacket(info) ;	    return ZmDone ;	  }	  parseFileName(info, (char *)info->buffer+2) ;	  info->file = ZOpenFile(info->filename, 0, info) ;	  if( info->file == NULL ) {	    (void) ZXmitStr(CanStr, 2, info) ;	    return ZmErrCantOpen ;	  }	  if( (err = acceptPacket(info)) != 0 )	    return err ;	  return ZXmitStr((u_char *)"C", 1, info) ;	}	if( ZWriteFile(info->buffer+2, info->pktLen-4, info->file, info) ) {	  ZStatus(FileErr, errno, NULL) ;	  (void) ZXmitStr(CanStr, 2, info) ;	  return ZmErrSys ;	}	info->offset += info->pktLen-4 ;	ZStatus(RcvByteCount, info->offset, NULL) ;	(void) acceptPacket(info) ;	return 0 ;}static	intrejectPacket( register ZModem *info ){	info->timeout = 10 ;	return ZXmitStr(NakStr, 1, info) ;}static	intacceptPacket( register ZModem *info ){	info->state = YRDataWait ;	info->timeout = 10 ;	return ZXmitStr(AckStr, 1, info) ;}static	intcalcCrc( 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 + =
减小字号Ctrl + -
显示快捷键?