?? transfers.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 ;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -