📄 zmodem.cpp
字号:
percentage = (ftell(fp) * 100) / current_file_size;
}
else {
percentage = 100;
}
duration = time(NULL) - transfer_start;
if (duration == 0l) {
duration = 1l;
}
cps = ftell(fp) / duration;
TRACE("zmtx: sending file \"%s\" %8ld bytes (%3d %%/%5d cps) \r",
name,ftell(fp),percentage,cps);
}
*/
/*
* send from the current position in the file
* all the way to end of file or until something goes wrong.
* (ZNAK or ZRPOS received)
* the name is only used to show progress
*/
int Czmodem::send_from(char * name,FILE * fp)
{
int n;
int type = ZCRCG;//ZCRCQ--crc next, frame coninuous, ZACK expected
//old---ZCRCG--crc next, frame coninuous, nonstop
char zdata_frame[] = { ZDATA, 0, 0, 0, 0 };
int nAAA=0;
int nNowHaveSendWindowsSize = 0;
/*
* put the file position in the ZDATA frame
*/
AGAIN://For test
zdata_frame[ZP0] = ftell(fp) & 0xff;
zdata_frame[ZP1] = (ftell(fp) >> 8) & 0xff;
zdata_frame[ZP2] = (ftell(fp) >> 16) & 0xff;
zdata_frame[ZP3] = (ftell(fp) >> 24) & 0xff;
tx_header((unsigned char *)zdata_frame);
tx_raw(XON);//1999.10.20, Send this header
tx_raw(XON);//1999.10.20, Send this header
/*
* send the data in the file
*/
while (!feof(fp)) {
if (opt_v) {
show_progress(name,fp);
}
/*
* read a block from the file
*/
n = fread(tx_data_subpacket,1,subpacket_size,fp);
if (n == 0) {
/*
* nothing to send ?
*/
break;
}
/*
* at end of file wait for an ACK
*/
if (ftell(fp) == current_file_size) {
type = ZCRCW;
}
nNowHaveSendWindowsSize++;
if(nNowHaveSendWindowsSize > WINDOWSSIZE)
{
TRACE("Now type is ZCRCQ!\n");
type = ZCRCQ;
}
tx_data(type,tx_data_subpacket,n);
if(type != ZCRCW)//if type != zcrcw, let multiplex send this data packet
tx_raw(XON); //else, in tx_data function call tx_raw(XON)
//顶出一帧数据, 如果不加这一行,最后的数据无法定位, 0xf0....0xf0
tx_raw(XON);//1999.10.21, by lhf
//Now we manage the windows, add by lhf
if(type != ZCRCW && (nNowHaveSendWindowsSize > WINDOWSSIZE))
{
TRACE("send data > windows size, waiting for ack, znak, zrpos!\n");
int typeAck;
do {
typeAck = rx_header(10000);
if (typeAck == ZNAK || typeAck == ZRPOS) {
return typeAck;
}
} while (typeAck != ZACK);
nNowHaveSendWindowsSize = 0;
type = ZCRCG;//nonstop
continue;
}//end of manage windos
if (type == ZCRCW) {
int type;
do {
type = rx_header(10000);
if(nAAA)//For test
{
fseek(fp, 0, SEEK_SET);
goto AGAIN;
}
//End of test
if (type == ZNAK || type == ZRPOS) {
return type;
}
} while (type != ZACK);
if (ftell(fp) == current_file_size) {
if (opt_d) {
TRACE("end of file\n");
}
return ZACK;
}
}
/*
* characters from the other side
* check out that header
*/
while (rx_poll()) {
int type;
int c;
c = rx_raw(0);
if (c == ZPAD) {
type = rx_header(1000);
if (type != TIMEOUT && type != ACK) {
return type;
}
}
}
}
/*
* end of file reached.
* should receive something... so fake ZACK
*/
return ZACK;
}
/*
* send a file; returns true when session is aborted.
* (using ZABORT frame)
*/
int
Czmodem::send_file(char * name)
{
long pos;
long size;
struct stat s;
FILE * fp;
unsigned char * p;
char zfile_frame[] = { ZFILE, 0, 0, 0, 0 };
char zeof_frame[] = { ZEOF, 0, 0, 0, 0 };
//int wait_for_header;
int type;
char * n;
if (opt_v) {
TRACE("zmtx: sending file \"%s\"\r",name);
}
/*
* before doing a lot of unnecessary work check if the file exists
*/
fp = fopen(name,"rb");
if (fp == NULL) {
if (opt_v) {
TRACE("zmtx: can't open file %s\n",name);
}
return FALSE;
}
fstat(fileno(fp),&s);
size = s.st_size;
current_file_size = size;
/*
* the file exists. now build the ZFILE frame
*/
/*
* set conversion option
* (not used; always binary)
*/
zfile_frame[ZF0] = ZF0_ZCBIN;
/*
* management option
*/
if (management_protect) {
zfile_frame[ZF1] = ZF1_ZMPROT;
if (opt_d) {
TRACE("zmtx: protecting destination\n");
}
}
if (management_clobber) {
zfile_frame[ZF1] = ZF1_ZMCLOB;
if (opt_d) {
TRACE("zmtx: overwriting destination\n");
}
}
if (management_newer) {
zfile_frame[ZF1] = ZF1_ZMNEW;
if (opt_d) {
TRACE("zmtx: overwriting destination if newer\n");
}
}
/*
* transport options
* (just plain normal transfer)
*/
zfile_frame[ZF2] = ZF2_ZTNOR;
/*
* extended options
*/
zfile_frame[ZF3] = 0;
/*
* now build the data subpacket with the file name and lots of other
* useful information.
*/
/*
* first enter the name and a 0
*/
p = tx_data_subpacket;
/*
* strip the path name from the filename
*/
n = strrchr(name,'/');
if (n == NULL) {
n = name;
}
else {
n++;
}
strcpy((char*)p,n);
p += strlen((char*)p) + 1;
/*
* next the file size
*/
sprintf((char*)p,"%ld ",size);
p += strlen((char*)p);
/*
* modification date
*/
sprintf((char*)p,"%lo ",s.st_mtime);
p += strlen((char*)p);
/*
* file mode
*/
sprintf((char*)p,"0 ");
p += strlen((char*)p);
/*
* serial number (??)
*/
sprintf((char*)p,"0 ");
p += strlen((char*)p);
/*
* number of files remaining
*/
sprintf((char*)p,"%d ",n_files_remaining);
p += strlen((char*)p);
/*
* file type
*/
sprintf((char*)p,"0");
p += strlen((char*)p) + 1;
do {
/*
* send the header and the data
*/
tx_header((unsigned char*)zfile_frame);
tx_data(ZCRCW,tx_data_subpacket,p - tx_data_subpacket);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
::Sleep(500);
/*
* wait for anything but an ZACK packet
*/
do {
type = rx_header(10000);
} while (type == ZACK);
if (opt_d) {
TRACE("type : %d\n",type);
}
if (type == ZSKIP) {
fclose(fp);
if (opt_v) {
TRACE("zmtx: skipped file \"%s\" \n",name);
}
return TRUE;
}
} while (type != ZRPOS);
transfer_start = time(NULL);
do {
/*
* fetch pos from the ZRPOS header
*/
if (type == ZRPOS) {
pos = rxd_header[ZP0] | (rxd_header[ZP1] << 8) | (rxd_header[ZP2] << 16) | (rxd_header[ZP3] << 24);
}
/*
* seek to the right place in the file
*/
fseek(fp,pos,0);
/*
* and start sending
*/
type = send_from(n,fp);
if (type == ZFERR || type == ZABORT) {
fclose(fp);
return TRUE;
}
} while (type == ZRPOS || type == ZNAK);
/*
* file sent. send end of file frame
* and wait for zrinit. if it doesnt come then try again
*/
zeof_frame[ZP0] = s.st_size & 0xff;
zeof_frame[ZP1] = (s.st_size >> 8) & 0xff;
zeof_frame[ZP2] = (s.st_size >> 16) & 0xff;
zeof_frame[ZP3] = (s.st_size >> 24) & 0xff;
do {
tx_hex_header((unsigned char*)zeof_frame);
type = rx_header(10000);
} while (type != ZRINIT);
/*
* and close the input file
*/
if (opt_v) {
TRACE("zmtx: sent file \"%s\" \n",name);
}
fclose(fp);
return FALSE;
}
/*
void
cleanup(void)
{
fd_exit();
}
void
usage(void)
{
TRACE("zmtx %s (C) Mattheij Computer Service 1994\n",VERSION);
TRACE("usage : zmtx options files\n");
TRACE(" -lline line to use for io\n");
TRACE(" -n transfer if source is newer\n");
TRACE(" -o overwrite if exists\n");
TRACE(" -p protect (don't overwrite if exists)\n");
TRACE("\n");
TRACE(" -d debug output\n");
TRACE(" -v verbose output\n");
TRACE(" (only one of -n -c or -p may be specified)\n");
cleanup();
exit(1);
}
*/
void Czmodem::SendFile(char* FileName, char* Option)
{
int i;
char * s;
int nCount = 0;
if(Option != NULL)
{
s = Option;
while(s[nCount] != '\0')
{
switch (toupper(s[nCount])) {
OPT_BOOL('D',opt_d);
OPT_BOOL('V',opt_v);
OPT_BOOL('N',management_newer);
OPT_BOOL('O',management_clobber);
OPT_BOOL('P',management_protect);
OPT_STRING('L',line);
default:
TRACE("zmtx: bad option %c\n",*s);
usage();
}
nCount++;
}
}
#ifdef _DEBUG
opt_d = TRUE;
#endif
if (opt_d) {
opt_v = TRUE;
}
if ((management_newer + management_clobber + management_protect) > 1 || FileName == NULL) {
usage();
}
if (line != NULL) {
if (freopen(line,"r",stdin) == NULL) {
TRACE("zmtx can't open line for input %s\n",line);
::ExitThread(2);//return;//exit(2);
}
if (freopen(line,"w",stdout) == NULL) {
TRACE("zmtx can't open line for output %s\n",line);
::ExitThread(2);//return;//exit(2);
}
}
//* set the io device to transparent
fd_init();
// * clear the input queue from any possible garbage
// * this also clears a possible ZRINIT from an already started
// * zmodem receiver. this doesn't harm because we reinvite to
// * receive again below and it may be that the receiver whose
// * ZRINIT we are about to wipe has already died.
rx_purge();
//* establish contact with the receiver
if (opt_v) {
TRACE("zmtx: establishing contact with receiver\n");
}
i = 0;
do {
unsigned char zrqinit_header[] = { ZRQINIT, 0, 0, 0, 0 };
i++;
if (i > 10) {
TRACE("zmtx: can't establish contact with receiver\n");
cleanup();
::ExitThread(3);//return;//exit(3);
}
//1999.10.18 tx_raw('z');
//1999.10.18 tx_raw('m');
//1999.10.18 tx_raw(13);
tx_hex_header(zrqinit_header);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
::Sleep(500);
} while (rx_header(7000) != ZRINIT);
if (opt_v) {
TRACE("zmtx: contact established\n");
TRACE("zmtx: starting file transfer\n");
}
//* decode receiver capability flags
//* forget about encryption and compression.
can_full_duplex = (rxd_header[ZF0] & ZF0_CANFDX) != 0;
can_overlap_io = (rxd_header[ZF0] & ZF0_CANOVIO) != 0;
can_break = (rxd_header[ZF0] & ZF0_CANBRK) != 0;
can_fcs_32 = (rxd_header[ZF0] & ZF0_CANFC32) != 0;
escape_all_control_characters = (rxd_header[ZF0] & ZF0_ESCCTL) != 0;
escape_8th_bit = (rxd_header[ZF0] & ZF0_ESC8) != 0;
use_variable_headers = (rxd_header[ZF1] & ZF1_CANVHDR) != 0;
if (opt_d) {
TRACE("receiver %s full duplex\n" ,can_full_duplex ? "can" : "can't");
TRACE("receiver %s overlap io\n" ,can_overlap_io ? "can" : "can't");
TRACE("receiver %s break\n" ,can_break ? "can" : "can't");
TRACE("receiver %s fcs 32\n" ,can_fcs_32 ? "can" : "can't");
TRACE("receiver %s escaped control chars\n",escape_all_control_characters ? "requests" : "doesn't request");
TRACE("receiver %s escaped 8th bit\n" ,escape_8th_bit ? "re
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -