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

📄 transfers.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: transfers.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;#endif/* file transfers for gcomm */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/param.h>extern	int	errno ;#include "Xmodem/zmodem.h"#include "transfers.h"#include "gcomm.h"#include "serial.h"#include "buffers.h"#include "winutils.h"static	ZModem	info ;static	int	oldFlowControl ;static	bool	sending ;static	char	*filenames = NULL, *filenamePtr ;static	char	*filenameExpand() ;static	bool	TransferTimeout(void *) ;	bool	transferActive ;static	int	timeoutSec ;voidUpload(char *files){	int	i ;	if( xferProtocol == XferKermit )	{	  WindowStatus("Kermit not yet supported") ;	  return ;	}	oldFlowControl = flowControl ;	info.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32 ;	info.zsinitflags = 0 ;	info.attn = NULL ;	if( packetSize != 0 )	  info.packetsize = packetSize ;	else if( connectionType == ConnectionSerial ) {	  if( baudRate < 2400 )	    info.packetsize = 256 ;	  else if( baudRate == 2400 )	    info.packetsize = 512 ;	  else	    info.packetsize = 1024 ;	}	else	  info.packetsize = 1024 ;	info.windowsize = windowSize ;	filenames = filenameExpand(files) ;	filenamePtr = filenames ;	transferActive = True ;	sending = True ;	SelectTermBuf() ;	if( connectionType == ConnectionSerial )	  SerialPortControl(-1, 8, ParityNone, -1, 0) ;	switch( xferProtocol ) {	  case XferZmodem: i = ZmodemTInit(&info) ; break ;	  case XferYmodem: i = YmodemTInit(&info) ; break ;	  case XferXmodem: i = XmodemTInit(&info) ; break ;	}	WindowStatus("Waiting for remote to respond...") ;	dialogTimeout = info.timeout ;	zmodemlog("Upload: set TransferTimout to %d\n", dialogTimeout) ;	timeoutSec = 0 ;	InstallDialogTimeout(dialogTimeout == 0 ? 0 : 1000, TransferTimeout) ;}	/* TODO: handle wild cards */	/* TODO: handle ZmodemTFile return code */static	voidUploadNext(){	int		f0,f1 ;	struct stat	buf ;static	char		filename[256], *ptr ;	int		len ;	if( filenamePtr != NULL ) {	  if( (ptr = strchr(filenamePtr, ' ')) == NULL ) {	    strcpy(filename, filenamePtr) ;	    filenamePtr = NULL ;	  }	  else {	    len = ptr-filenamePtr ;	    bcopy(filenamePtr, filename, len) ;	    filename[len] = '\0' ;	    filenamePtr += len+1 ;	  }	  WindowStatus("Sending %s", filename) ;	  if( stat(filename, &buf) == 0 )	    WindowXferGaugeMax(buf.st_size) ;	  else	    WindowXferGaugeMax(0) ;	  if( xferResume )	    f0 = ZCRESUM ;	  else if( xferAscii )	    f0 = ZCNL ;#ifdef	COMMENT	  else if( binary )	    f0 = ZCBIN ;#endif	/* COMMENT */	  else	    f0 = 0 ;	  f1 = xferType ;	  if( noLoc )	    f1 |= ZMSKNOLOC ;	  ZmodemTFile(filename, filename, f0,f1,0,0, 0,0, &info) ;	}	else	{	  WindowStatus("End of Transfers") ;	  WindowXferGaugeMax(0) ;	  ZmodemTFinish(&info) ;	  sending = False ;	}}voidDownload(char *files){	int	i ;	if( xferProtocol == XferKermit )	{	  WindowStatus("Kermit not yet supported") ;	  return ;	}	oldFlowControl = flowControl ;	info.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32 ;	info.zsinitflags = 0 ;	info.attn = NULL ;#ifdef	COMMENT	info.bufsize = BufLen ;#endif	/* COMMENT */	info.bufsize = 0 ;	/* full streaming */	filenamePtr = files ;	transferActive = True ;	sending = False ;	SelectTermBuf() ;	if( connectionType == ConnectionSerial )	  SerialPortControl(-1, 8, ParityNone, -1, 0) ;	switch( xferProtocol ) {	  case XferZmodem: i = ZmodemRInit(&info) ; break ;	  case XferYmodem: i = YmodemRInit(&info) ; break ;	  case XferXmodem: WindowStatus("Xmodem not yet supported") ; return ;	}	WindowStatus("Waiting for remote to respond...") ;	dialogTimeout = info.timeout ;	zmodemlog("Download: set TransferTimout to %d\n", dialogTimeout) ;	timeoutSec = 0 ;	InstallDialogTimeout(dialogTimeout == 0 ? 0 : 1000, TransferTimeout) ;}voidXferCancel(){	ZmodemAbort(&info) ;	TransferFinish() ;}voidTransferFinish(){	transferActive = False ;	RemoveDialogTimeout() ;	SelectTermBuf() ;	if( connectionType == ConnectionSerial	    && oldFlowControl != flowControl )	{	  flowControl = oldFlowControl ;	  SerialSettings() ;	}	WindowTransferActive(False) ;	if( filenames != NULL ) {	  free(filenames) ;	  filenames = NULL ;	}}	/* data received from remote, pass it to Zmodem funcs */static	inttransferSendData(u_char *buffer, int len){	int	i ;	timeoutSec = 0 ;	i = ZmodemRcv(buffer, len, &info) ;	switch( i ) {	  case 0:	    return 0 ;	  case ZmDone:	  case ZmErrCantOpen:	  case ZmFileTooLong:	    if( sending )	      UploadNext() ;	    else	      TransferFinish() ;	    return 1 ;	  case ZmErrInt:	/* all of these have already displayed status */	  case ZmErrSys:	  case ZmErrNotOpen:	  case ZmFileCantWrite:	  case ZmErrInitTo:	  case ZmErrSequence:	  case ZmErrCancel:	  case ZmErrRcvTo:	  case ZmErrSndTo:	  case ZmErrCmdTo:	    TransferFinish() ;	    return 1 ;	}	return 0 ;}	/* data received from remote */voidTransferData(){	int	len ;	int	i ;	while( inputBuf.cnt > 0 )	{	  len = inputBuf.cnt ;	  if( inputBuf.ptr > 0 ) {	/* wrapped buffer, common case */	    if( inputBuf.ptr + len > BufLen )	      len = BufLen - inputBuf.ptr ;	  }	  i = transferSendData((u_char *)inputBuf.buffer+inputBuf.ptr, len) ;	  if( info.timeout != dialogTimeout ) {	    dialogTimeout = info.timeout ;	    zmodemlog("TransferData: reset TransferTimout to %d\n",		dialogTimeout) ;	    RemoveDialogTimeout() ;	    timeoutSec = 0 ;	    InstallDialogTimeout(dialogTimeout == 0 ? 0:1000, TransferTimeout);	  }	  if( (inputBuf.ptr += len) >= BufLen )	    inputBuf.ptr -= BufLen ;	  inputBuf.cnt -= len ;	  if( i != 0 )	    return ;	}	/* lucky us, we emptied the buffer.  Reset start pointer too,	 * to reduce wrapped buffers.	 */	inputBuf.ptr = 0 ;}	/* timeout from remote */static	boolTransferTimeout(void *data){	int	i ;	if( ++timeoutSec < dialogTimeout )	  return True ;	i = ZmodemTimeout(&info) ;	zmodemlog("TransferTimeout, ZmodemTimeout() returns %d\n", i);	if( info.timeout != dialogTimeout ) {	  dialogTimeout = info.timeout ;	  zmodemlog("TransferTimeout: reset TransferTimout to %d\n",	      dialogTimeout) ;	  RemoveDialogTimeout() ;	  InstallDialogTimeout(dialogTimeout == 0 ? 0 : 1000, TransferTimeout);	}	timeoutSec = 0 ;	switch( i ) {	  case ZmDone:	  case ZmErrCantOpen:	  case ZmFileTooLong:	    if( sending )	      UploadNext() ;	    else	      TransferFinish() ;	    break ;	  case ZmErrInt:	/* all of these have already displayed status */	  case ZmErrSys:	  case ZmErrNotOpen:	  case ZmFileCantWrite:	  case ZmErrInitTo:	  case ZmErrSequence:	  case ZmErrCancel:	  case ZmErrRcvTo:	  case ZmErrSndTo:	  case ZmErrCmdTo:	    TransferFinish() ;	    break ;	}	return transferActive ;}	/* user hit CANCEL */voidTransferCancel(){	ZmodemAttention(&info) ;}intZXmitStr(u_char *str, int len, ZModem *info){	if( ofd < 0 ) return -1 ;	append_buffer(&outputBuf, (char *)str, len, ofd) ;	flush_buffer(&outputBuf, ofd) ;	return 0 ;}voidZIFlush(ZModem *info){	if( connectionType == ConnectionSerial )	  SerialFlush(0) ;}voidZOFlush(ZModem *info){	if( connectionType == ConnectionSerial )	  SerialFlush(1) ;}intZAttn(ZModem *info){	char	*ptr ;	if( info->attn == NULL )	  return 0 ;	for(ptr = info->attn; *ptr != '\0'; ++ptr) {	  if( *ptr == ATTNBRK )	    SerialBreak() ;	  else if( *ptr == ATTNPSE )	    sleep(1) ;	  else	    append_buffer(&outputBuf, ptr, 1, ofd) ;	}	return 0 ;}	/* set flow control as required by protocol.  If original flow	 * control was hardware, do not change it.  Otherwise, toggle	 * software flow control	 */voidZFlowControl(int onoff, ZModem *info){	if( connectionType == ConnectionSerial && oldFlowControl != FlowRtsCts )	{	  flowControl = onoff ? FlowXonXoff : FlowNone ;	  SetHardwareFlow() ;	}}voidZStatus(int type, int value, char *msg){	switch( type )	{	  case RcvByteCount:	    WindowXferStatus("%d bytes received", value) ;	    WindowXferGauge(value) ;	    break ;	  case SndByteCount:	    WindowXferStatus("%d bytes sent", value) ;	    WindowXferGauge(value) ;	    break ;	  case RcvTimeout:	    WindowStatus("Receiver did not respond, aborting") ;	    break ;	  case SndTimeout:	    WindowStatus("%d send timeouts", value) ;	    break ;	  case RmtCancel:	    WindowStatus("Remote end has cancelled") ;	    break ;	  case ProtocolErr:	    WindowStatus("Protocol error, header=%d", value) ;	    break ;	  case RemoteMessage:	/* message from remote end */	    WindowStatus("MESSAGE: %s", msg) ;	    break ;	  case DataErr:		/* data error, val=error count */	    WindowStatus("%d data errors", value) ;	    break ;	  case FileErr:		/* error writing file, val=errno */	    WindowStatus("Cannot write file: %s", strerror(errno)) ;	    break ;	  case FileBegin:	/* file transfer begins, str=name */	    WindowStatus("Transfering %s", msg) ;	    break ;	  case FileEnd:		/* file transfer ends, str=name */	    WindowStatus("%s finished", msg) ;	    break ;	  case FileSkip:	/* file transfer ends, str=name */	    WindowStatus("Skipping %s", msg) ;	    break ;	}}FILE *ZOpenFile(char *name, u_long crc, ZModem *info){	struct stat	buf ;	bool		exists ;	/* file already exists */static	int		changeCount = 0 ;	char		name2[MAXPATHLEN] ;	int		apnd = 0 ;	int		f0,f1 ;	FILE		*ofile ;	char		path[1024] ;	/* TODO: if absolute path, do we want to allow it?	 * if relative path, do we want to prepend something?	 */	if( *name == '/' )	/* for now, disallow absolute paths */	  return NULL ;	buf.st_size = 0 ;	if( stat(name, &buf) == 0 )	  exists = True ;	else if( errno == ENOENT )	  exists = False ;	else	  return NULL ;	/* if remote end has not specified transfer flags, we can	 * accept the local definitions	 */	if( (f0=info->f0) == 0 ) {	  if( xferResume )	    f0 = ZCRESUM ;	  else if( xferAscii )	    f0 = ZCNL ;#ifdef	COMMENT	  else if( binary )	    f0 = ZCBIN ;#endif	/* COMMENT */	  else	    f0 = 0 ;	}	if( (f1=info->f1) == 0 ) {	  f1 = xferType ;	  if( noLoc )	    f1 |= ZMSKNOLOC ;	}	zmodemlog("ZOpenFile: %s, f0=%x, f1=%x, exists=%d, size=%d/%d\n",	  name, f0,f1, exists, buf.st_size, info->len) ;	if( f0 == ZCRESUM ) {	/* if exists, and we already have it, return */	  if( exists  &&  buf.st_size == info->len )	    return NULL ;	  apnd = 1 ;	}	/* reject if file not found and it must be there (ZMSKNOLOC) */	if( !exists && (f1 & ZMSKNOLOC) )	  return NULL ;	switch( f1 & ZMMASK ) {	  case 0:	/* Implementation-dependent.  In this case, we			 * reject if file exists (and ZMSKNOLOC not set) */	    if( exists && !(f1 & ZMSKNOLOC) )	      return NULL ;	    break ;	  case ZMNEWL:	/* take if newer or longer than file on disk */	    if( exists  &&  info->date <= buf.st_mtime  &&		info->len <= buf.st_size )	      return NULL ;	    break ;	  case ZMCRC:		/* take if different CRC or length */	    zmodemlog("  ZMCRC: crc=%x, FileCrc=%x\n", crc, FileCrc(name) );	    if( exists  &&  info->len == buf.st_size && crc == FileCrc(name) )	      return NULL ;	    break ;	  case ZMAPND:	/* append */	    apnd = 1 ;	  case ZMCLOB:	/* unconditional replace */	    break ;	  case ZMNEW:	/* take if newer than file on disk */	    if( exists  &&  info->date <= buf.st_mtime )	      return NULL ;	    break ;	  case ZMDIFF:	/* take if different date or length */	    if( exists  &&  info->date == buf.st_mtime  &&		info->len == buf.st_size )	      return NULL ;	    break ;	  case ZMPROT:	/* only if dest does not exist */	    if( exists )	      return NULL ;	    break ;	  case ZMCHNG:	/* invent new filename if exists */	    if( exists ) {	      while( exists ) {		sprintf(name2, "%s_%d", name, changeCount++) ;		exists = stat(name2, &buf) == 0 || errno != ENOENT ;	      }	      name = name2 ;	    }	    break ;	}	/* here if we've decided to accept */	if( exists && !apnd && unlink(name) != 0 )	  return NULL ;	/* TODO: build directory path if needed */	WindowStatus("Receiving: \"%s\"", name) ;	WindowXferGaugeMax(info->len) ;	ofile = fopen(name, apnd ? "a" : "w") ;	zmodemlog("  ready to open %s/%s: apnd = %d, file = %lx\n",	  getcwd(path,sizeof(path)), name, apnd, (long)ofile) ;	return ofile ;}intZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info){	/* If ZCNL set in info->f0, convert	 * newlines to unix convention	 */	if( info->f0 == ZCNL )	{	  int	i, j, c ;	  static int lastc = '\0' ;	  for(i=0; i < len ; ++i)	  {	    switch( (c=*buffer++) ) {	      case '\n': if( lastc != '\r' ) j = putc('\n', file) ; break ;	      case '\r': if( lastc != '\n' ) j = putc('\n', file) ; break ;	      default: j = putc(c, file) ; break ;	    }	    lastc = c ;	    if( j == EOF )	      return ZmErrSys ;	  }	  return 0 ;	}	else	  return fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys ;}intZCloseFile(ZModem *info){	struct timeval tvp[2] ;	fclose(info->file) ;#ifdef	TODO	if( ymodem )	  truncate(info->filename, info->len) ;#endif	/* TODO */	if( info->date != 0 ) {	  tvp[0].tv_sec = tvp[1].tv_sec = info->date ;	  tvp[0].tv_usec = tvp[1].tv_usec = 0 ;	  utimes(info->filename, tvp) ;	}	if( info->mode & 01000000 )	  chmod(info->filename, info->mode&0777) ;	return 0 ;}voidZIdleStr(char *buf, int len, ZModem *info){	PutTerm(buf, len) ;}	/* marvelous kludge.  I want to perform a filename expansion	 * on the filename list, but I don't feel like writing that	 * code.  So instead, I let the shell do that for me.	 */static	char *filenameExpand(char *files){	char	*cmd, *rval, *ptr ;	int	i, len, max ;	FILE	*ifile ;	if( (cmd = malloc(strlen(files) + 10)) == NULL )	  return "" ;	sprintf(cmd, "echo %s", files) ;	ifile = popen(cmd, "r") ;	free(cmd) ;	/* if can't execute command, at least return *something* */	if( ifile == NULL )	  return strdup(files) ;	max = 512 ;	len = 0 ;	rval = malloc(max) ;	/* start reading results, increasing buffer if needed */	while( (i = fread(rval+len, 1, max-len-1, ifile)) > 0 )	{	  len += i ;	  if( len >= max-2 ) {	    max *= 2 ;	    if( (rval = realloc(rval, max)) == NULL ) {	      rval[len] = '\0' ;	      pclose(ifile) ;	      return rval ;	    }	  }	}	pclose(ifile) ;	rval[len] = '\0' ;	if( (ptr = strchr(rval, '\n')) != NULL )	  *ptr = '\0' ;	return rval ;}

⌨️ 快捷键说明

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