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

📄 zmodemt.c

📁 Gcomm is a serial communications program similar to seyon, but more modern, and easier to use. Works
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* here if an ACK arrived while transmitting data.  Update	 * last known receiver offset, and try to send some more	 * data.	 */static	intGotSendAck( register ZModem *info ){	u_long offset ;	offset = ZDec4(info->hdrData+1) ;	if( offset > info->lastOffset )	  info->lastOffset = offset ;	zmodemlog("GotSendAck[%s]: %ld\n", sname(info), info->offset) ;	return 0 ;		/* DONT send more data, that will happen				 * later anyway */}	/* here if an ACK arrived after last file packet sent.  Send	 * the EOF.	 */static	intGotSendDoneAck( register ZModem *info ){	u_long offset ;	offset = ZDec4(info->hdrData+1) ;	if( offset > info->lastOffset )	  info->lastOffset = offset ;	zmodemlog("GotSendDoneAck[%s]: %ld\n", sname(info), info->offset) ;	info->state = SendEof ;	info->timeout = 60 ;	return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ;}	/* off to a bad start; ZDATA header was corrupt.  Start	 * from beginning	 */static	intGotSendNak( register ZModem *info ){	info->offset = info->zrposOffset ;	fseek(info->file, info->offset, 0) ;	/* TODO: what if fseek fails?  Send EOF? */	zmodemlog("GotSendNak[%s]: %ld\n", sname(info), info->offset) ;	return SendMoreFileData(info) ;}	/* got a ZSKIP, receiver doesn't want this file.  */static	intSkipFile( register ZModem *info ){	zmodemlog("SkipFile[%s]\n", sname(info)) ;	fclose(info->file) ;	return ZmDone ;}	/* got a ZRPOS packet in the middle of sending a file,	 * set new offset and try again	 */static	intGotSendPos( register ZModem *info ){	ZStatus(DataErr, ++info->errCount, NULL) ;	info->waitflag = 1 ;		/* next pkt should wait, to resync */	zmodemlog("GotSendPos[%s]\n", sname(info), info->offset) ;	return startFileData(info) ;}	/* here if an ACK arrived while waiting while transmitting data.	 * Update last known receiver offset, and try to send some more	 * data.	 */static	intGotSendWaitAck( register ZModem *info ){	u_long	offset ;	int	err ;	offset = ZDec4(info->hdrData+1) ;	if( offset > info->lastOffset )	  info->lastOffset = offset ;	zmodemlog("GotSendWaitAck[%s]\n", sname(info), offset) ;	if( (err = ZXmitHdr(ZDATA, ZBIN, ZEnc4(info->offset), info)) )	  return err ;	return SendMoreFileData(info) ;}	/* utility: send a chunk of file data.  Whether this is followed	 * by a ZCRCE, ZCRCG, ZCRCQ or ZCRCW depends on all	 * sorts of protocol flags, plus 'waitflag'.  Exact amount of file	 * data transmitted is variable, as escape sequences may pad out	 * the buffer.	 */intSendMoreFileData( register ZModem *info ){	int	type ;	int	qfull = 0 ;	int	err ;	int	len ;		/* max # chars to send this packet */	long	pending ;	/* # of characters sent but not acknowledged */	/* ZCRCE: CRC next, frame ends, header follows	 * ZCRCG: CRC next, frame continues nonstop	 * ZCRCQ: CRC next, send ZACK, frame continues nonstop	 * ZCRCW: CRC next, send ZACK, frame ends, header follows	 */	if( info->interrupt ) {	  /* Bugger, receiver sent an interrupt.  Enter a wait state	   * and see what they want.  Next header *should* be ZRPOS.	   */	  info->state = SendWait ;	  info->timeout = 60 ;	  return 0 ;	}	/* Find out how many bytes we can transfer in the next packet */	len = info->packetsize ;	pending = info->offset - info->lastOffset ;	if( info->windowsize != 0 && info->windowsize - pending <= len ){	  len = info->windowsize - pending ;	  qfull = 1 ;	}	if( info->bufsize != 0  &&  info->bufsize - pending <= len ) {	  len = info->bufsize - pending ;	  qfull = 1 ;	}	if( len == 0 ) {	/* window still full, keep waiting */	  info->state = SendWait ;	  info->timeout = 60 ;	  return 0 ;	}	/* OK, we can safely transmit 'len' bytes of data.  Start reading	 * file until buffer is full.	 */	len -= 10 ;	/* Pre-deduct 10 bytes for trailing CRC */	/* find out what kind of packet to send */	if( info->waitflag ) {	  type = ZCRCW ;	  info->waitflag = 0 ;	}#ifdef	COMMENT	else if( info->fileEof )	  type = ZCRCE ;#endif	/* COMMENT */	else if( qfull )	  type = ZCRCW ;	else	  switch( info->Streaming ) {	    case Full:	    case Segmented: type = ZCRCG ; break ;	    case StrWindow:	      if( (info->windowCount += len) < info->windowsize/4 )		type = ZCRCG ;	      else {		type = ZCRCQ ;		info->windowCount = 0 ;	      }	      break ;	    default:	    case SlidingWindow: type = ZCRCQ ; break ;	  }	{	  int	crc32 = info->crc32 ;	  register int c=0, c2, atSign=0 ;	  register u_long crc ;	  register u_char *ptr = info->buffer ;	  crc = crc32 ? 0xffffffff : 0 ;	  /* read characters from file and put into buffer until buffer is	   * full or file is exhausted	   */	  while( len > 0  && (c = getc(info->file)) != EOF )	  {	    if( !crc32 )	      crc = updcrc(c, crc) ;	    else	      crc = UPDC32(c, crc) ;	    /* zmodem protocol requires that CAN(ZDLE), DLE, XON, XOFF and	     * a CR following '@' be escaped.  In addition, I escape '^]'	     * to protect telnet, "<CR>~." to protect rlogin, and ESC for good	     * measure.	     */	    c2 = c & 0177 ;	    if( c == ZDLE || c2 == 020 || c2 == 021 || c2 == 023 ||		c2 == 0177  ||  c2 == '\r'  ||  c2 == '\n'  ||  c2 == 033  ||		c2 == 035  || (c2 < 040 && info->escCtrl) )	    {	      *ptr++ = ZDLE ;	      if( c == 0177 )		*ptr = ZRUB0 ;	      else if( c == 0377 )		*ptr = ZRUB1 ;	      else		*ptr = c^0100 ;	      len -= 2 ;	    }	    else {	      *ptr = c ;	      --len ;	    }	    ++ptr ;	    atSign = c2 == '@' ;	    ++info->offset ;	  }	  /* if we've reached file end, a ZEOF header will follow.  If	   * there's room in the outgoing buffer for it, end the packet	   * with ZCRCE and append the ZEOF header.  If there isn't room,	   * we'll have to do a ZCRCW	   */	  if( (info->fileEof = (c == EOF)) ) {	    if( qfull  ||  (info->bufsize != 0 && len < 24) )	      type = ZCRCW ;	    else	      type = ZCRCE ;	  }	  *ptr++ = ZDLE ;	  if( !crc32 )	    crc = updcrc(type, crc) ;	  else	    crc = UPDC32(type, crc) ;	  *ptr++ = type ;	  if( !crc32 ) {	    crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;	    ptr = putZdle(ptr, (crc>>8)&0xff, info) ;	    ptr = putZdle(ptr, crc&0xff, info) ;	  }	  else {	    crc = ~crc ;	    for(len=4; --len >= 0; crc >>= 8)	      ptr = putZdle(ptr, crc&0xff, info) ;	  }	  len = ptr - info->buffer ;	}	ZStatus(SndByteCount, info->offset, NULL) ;	if( (err = ZXmitStr(info->buffer, len, info)) )	  return err ;#ifdef	COMMENT	if( (err = ZXmitData(ZBIN, info->buffer, len, type, info)) )	  return err ;#endif	/* COMMENT */	/* finally, do we want to wait after this packet? */	switch( type ) {	  case ZCRCE:	    info->state = SendEof ;	    info->timeout = 60 ;	    return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ;	  case ZCRCW:	    info->state = info->fileEof ? SendDone : SendWait ;	    info->timeout = 60 ;	    break ;	  default:	    info->state = Sending ;	    info->timeout = 0 ;	    break ;	}#ifdef	COMMENT	if( info->fileEof ) {	/* Yes, file is done, send EOF and wait */	  info->state = SendEof ;	  info->timeout = 60 ;	  return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ;	}	else if( type == ZCRCW ) {	  info->state = SendWait ;	  info->timeout = 60 ;	}	else {	  info->state = Sending ;	  info->timeout = 0 ;	}#endif	/* COMMENT */	return 0 ;}static	intResendEof( register ZModem *info ){	return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ;}static	intOverAndOut( ZModem *info ){	ZXmitStr((u_char *)"OO", 2, info) ;	return ZmDone ;}	/* YMODEM */static	u_char	eotstr[1] = {EOT} ;	/* ymodem parser */intYsendChar( char c, register ZModem *info ){	int	err ;	if( info->canCount >= 2 ) {	  ZStatus(RmtCancel, 0, NULL) ;	  return ZmErrCancel ;	}	switch( info->state ) {	  case YTStart:		/* wait for 'G', 'C' or NAK */	    switch( c ) {	      case 'G':		/* streaming YModem */	      case 'C':		/* CRC YModem */	      case NAK:		/* checksum YModem */		info->PacketType = c ;		return ZmDone ;	      default:		return 0 ;	    }	  case YTFile:		/* sent filename, waiting for ACK or NAK */	    switch( c ) {	      case NAK:		/* resend */	      case 'C':	      case 'G':		ZStatus(DataErr, ++info->errCount, NULL) ;		return YSendFilename(info) ;	      case ACK:		info->state = YTDataWait ;	      default:		return 0 ;	    }	  case YTDataWait:	/* sent filename, waiting for G,C or NAK */	    switch( c ) {	      case NAK:	      case 'C':	      case 'G':		info->chrCount = 0 ;		if( info->PacketType == 'G' )	/* send it all at once */		{		  while( info->state == YTData )		    if( (err = YSendData(info)) )		      return err ;		  return 0 ;		}		else		  return YSendData(info) ;	      default:		return 0 ;	    }	  case YTData:		/* sent data, waiting for ACK or NAK */	    switch( c ) {	      case 'C':	      case 'G':		/* protocol failure, resend filename */		if( info->Protocol == YMODEM ) {		  ZStatus(DataErr, ++info->errCount, NULL) ;		  info->state = YTFile ;		  rewind(info->file) ;		  return YSendFilename(info) ;		}		/* else XModem, treat it like a NAK */	      case NAK:		ZStatus(DataErr, ++info->errCount, NULL) ;		return YXmitData(info->buffer + info->bufp, info->ylen, info) ;	      case ACK:		info->offset += info->ylen ;		info->bufp += info->ylen ;		info->chrCount -= info->ylen ;		ZStatus(SndByteCount, info->offset, NULL) ;		return YSendData(info) ;	      default:		return 0 ;	    }	  case YTEOF:		/* sent EOF, waiting for ACK or NAK */	    switch( c ) {	      case NAK:		return ZXmitStr(eotstr, 1, info) ;	      case ACK:		info->state = info->Protocol == YMODEM ? YTStart : Done ;		return ZmDone ;	      default:		return 0 ;	    }	  case YTFin:		/* sent Fin, waiting for ACK or NAK */	    switch( c ) {	      case NAK:		return YSendFin(info) ;	      case ACK:		return ZmDone ;	      default:		return 0 ;	    }	  default:	    return 0 ;	}}static	intYXmitData( u_char *buffer, int len, ZModem *info ){	u_char	hdr[3] ;	u_char	trail[2] ;	u_long	crc = 0 ;	int	i, err ;	hdr[0] = len == 1024 ? STX : SOH ;	hdr[1] = info->packetCount ;	hdr[2] = ~hdr[1] ;	if( (err = ZXmitStr(hdr, 3, info)) ||	    (err = ZXmitStr(buffer, len, info)) )	  return err ;	if( info->PacketType == NAK ) {	/* checksum */	  for(i=0; i<len; ++i)	    crc += buffer[i] ;	  trail[0] = crc % 256 ;	  return ZXmitStr(trail,1, info) ;	}	else {	  for(i=0; i<len; ++i)	    crc = updcrc(buffer[i], crc) ;	  crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;	  trail[0] = crc / 256 ;	  trail[1] = crc % 256 ;	  return ZXmitStr(trail,2, info) ;	}}static	intYSendFilename( ZModem *info ){	int	i,len ;	u_char	obuf[1024] ;	u_char	*ptr = obuf ;	info->state = info->PacketType != 'G' ? YTFile : YTDataWait ;	info->packetCount = 0 ;	info->offset = 0 ;	i = strlen(info->rfilename) ;	memcpy(ptr, info->rfilename, i+1) ;  ptr += i+1 ;	sprintf((char *)ptr, "%d %lo %o 0", info->len, info->date, info->mode);	ptr += strlen((char *)ptr) ;	*ptr++ = '\0' ;	/* pad out to 128 bytes or 1024 bytes */	i = ptr-obuf ;	len = i>128 ? 1024 : 128 ;	for(; i<len; ++i)	  *ptr++ = '\0' ;	return YXmitData(obuf, len, info) ;}	/* send next buffer of data */static	intYSendData( ZModem *info ){	int	i ;	/* are there characters still in the read buffer? */	if( info->chrCount <= 0 ) {	  info->bufp = 0 ;	  info->chrCount = fread(info->buffer, 1, info->packetsize, info->file);	  info->fileEof = feof(info->file) ;	}	if( info->chrCount <= 0 ) {	  fclose(info->file) ;	  info->state = YTEOF ;	  return ZXmitStr(eotstr, 1, info) ;	}	/* pad out to 128 bytes if needed */	if( info->chrCount < 128 ) {	  i = 128 - info->chrCount ;	  memset(info->buffer + info->bufp + info->chrCount, 0x1a, i) ;	  info->chrCount = 128 ;	}	info->ylen = info->chrCount >= 1024 ? 1024 : 128 ;	++info->packetCount ;	info->state = YTData ;	return YXmitData(info->buffer + info->bufp, info->ylen, info) ;}static	intYSendFin( ZModem *info ){	u_char	obuf[128] ;	info->state = YTFin ;	info->packetCount = 0 ;	memset(obuf,0,128) ;	return YXmitData(obuf, 128, info) ;}

⌨️ 快捷键说明

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