📄 zmodem.cpp
字号:
/*
* spurious ZPAD check
*/
if (c != ZDLE) {
TRACE("expected ZDLE; got %c\n",c);
continue;
}
/*
* now read the header style
*/
c = rx(to);
if (c == TIMEOUT) {
return c;
}
TRACE("\n");
switch (c) {
case ZBIN:
rx_bin16_header(to);
receive_32_bit_data = FALSE;
break;
case ZHEX:
rx_hex_header(to);
receive_32_bit_data = FALSE;
break;
case ZBIN32:
rx_bin32_header(to);
receive_32_bit_data = TRUE;
break;
default:
/*
* unrecognized header style
*/
TRACE("unrecognized header style %c\n",c);
if (errors) {
return INVHDR;
}
continue;
break;
}
if (errors && rxd_header_len == 0) {
return INVHDR;
}
} while (rxd_header_len == 0);
/*
* this appears to have been a valid header.
* return its type.
*/
if (rxd_header[0] == ZDATA) {
ack_file_pos = rxd_header[ZP0] | (rxd_header[ZP1] << 8) |
(rxd_header[ZP2] << 16) | (rxd_header[ZP3] << 24);
}
if (rxd_header[0] == ZFILE) {
ack_file_pos = 0l;
}
TRACE("type %d\n",rxd_header[0]);
return rxd_header[0];
}
int
Czmodem::rx_header(int timeout)
{
return rx_header_raw(timeout,FALSE);
}
int Czmodem::rx_header_and_check(int timeout)
{
int type;
while (TRUE) {
type = rx_header_raw(timeout,TRUE);
if (type != INVHDR) {
break;
}
tx_znak();
}
return type;
}
//f test 37474 -ne `wc -c <zmodem.doc`; then
//cho shar: \"zmodem.doc\" unpacked with wrong size!
//i
// end of overwriting check
//i
//f test -f zmodem.h -a "${1}" != "-c" ; then
//cho shar: Will not over-write existing file \"zmodem.h\"
//lse
//cho shar: Extracting \"zmodem.h\" \(5734 characters\)
//ed "s/^X//" >zmodem.h <<'END_OF_zmodem.h'
///*
// * zmodem.h
// * zmodem constants
// * (C) Mattheij Computer Service 1994
// */
//
//.TH ZMRX 1 "July 1994"
//.SH NAME
//zmrx \- receive file using ZMODEM protocol
//.SH SYNOPSIS
//.B zmrx
//[
//.B \-jnopdvq
//] [
//.B \-l\fIline\fP
//]
//.SH DESCRIPTION
//.I zmrx
//receives a file using the ZMODEM file transfer protocol.
//By default,
//.I zmrx
//reads
//.I stdin
//and writes
//.IR stdout.
//.SH OPTIONS
//.TP
//.B \-l\fIline\fP
//File (typically a tty) to use for the transfer instead
//of
//.IR stdin/stdout.
//.TP
//.B \-j
//Junk any path components of the filename: receive into the
//base filename in the current directory.
//.TP
//.B \-n
//Transfer only if source is newer than destination.
//.TP
//.B \-o,\-p
//Overwrite (protect) the destination if it exists.
//The default is to protect the destination. These
//flags interact in a complicated way with similar
//options at the receiving end -- see the protocol
//specification, or be careful.
/******************************************************************************/
/* Project : Unite! File : zmodem receive Version : 1.02 */
/* */
/* (C) Mattheij Computer Service 1994 */
/* */
/* contact us through (in order of preference) */
/* */
/* email: jacquesm@hacktic.nl */
/* mail: MCS */
/* Prinses Beatrixlaan 535 */
/* 2284 AT RIJSWIJK */
/* The Netherlands */
/* voice phone: 31+070-3936926 */
/******************************************************************************/
/*
* show the progress of the transfer like this:
* zmrx: receiving file "garbage" 4096 bytes ( 20%)
* avoids the use of floating point.
*/
void Czmodem::
show_progress(char * name,FILE * fp)
{
int percentage;
time_t duration;
int cps;
if (current_file_size > 0) {
percentage = (ftell(fp) * 100) / current_file_size;
}
else {
percentage = 100;
}
duration = time(NULL) - transfer_start;
if (duration == 0l) {
duration = 1;
}
cps = ftell(fp) / duration;
TRACE("zmrx: receiving file \"%s\" %8ld bytes (%3d %%/%5d cps) \r",
name,ftell(fp),percentage,cps);
}
/*
* receive a header and check for garbage
*/
/*
* receive file data until the end of the file or until something goes wrong.
* the name is only used to show progress
*/
int Czmodem::receive_file_data(char * name,FILE * fp)
{
static int first = TRUE;
long pos;
int n;
int type;
/*
* create a ZRPOS frame and send it to the other side
*/
tx_pos_header(ZRPOS,ftell(fp));
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
TRACE("re-transmit from %d\n",ftell(fp));
/*
* wait for a ZDATA header with the right file offset
* or a timeout or a ZFIN
*/
do {
do {
type = rx_header(10000);
if (type == TIMEOUT) {
return TIMEOUT;
}
} while (type != ZDATA);
pos = rxd_header[ZP0] | (rxd_header[ZP1] << 8) |
(rxd_header[ZP2] << 16) | (rxd_header[ZP3] << 24);
} while (pos != ftell(fp));
do {
type = rx_data(rx_data_subpacket,&n);
/* TRACE("packet len %d type %d\n",n,type);
*/
if (type == ENDOFFRAME || type == FRAMEOK) {
fwrite(rx_data_subpacket,1,n,fp);
}
if (opt_v) {
show_progress(name,fp);
}
} while (type == FRAMEOK);
return type;
}
void Czmodem::tx_zrinit()
{
unsigned char zrinit_header[] = { ZRINIT, 0, 0, 0, 4 | ZF0_CANFDX | ZF0_CANOVIO | ZF0_CANFC32 | ZF0_ESCCTL};
tx_hex_header(zrinit_header);
}
/*
* receive a file
* if the file header info packet was garbled then send a ZNAK and return
* (using ZABORT frame)
*/
void Czmodem::receive_file()
{
long size;
struct stat s;
int type;
int l;
int clobber;
int protect;
int newer;
int exists;
//struct utimbuf tv;
char * mode = "wb";
/*
* fetch the management info bits from the ZRFILE header
*/
/*
* management option
*/
if (management_protect || (rxd_header[ZF1] & ZF1_ZMPROT)) {
protect = TRUE;
}
else {
if (management_clobber || (rxd_header[ZF1] & ZF1_ZMCLOB)) {
clobber = TRUE;
}
}
if (management_newer || (rxd_header[ZF1] & ZF1_ZMNEW)) {
newer = TRUE;
}
/*
* read the data subpacket containing the file information
*/
type = rx_data(rx_data_subpacket,&l);
if (type != FRAMEOK && type != ENDOFFRAME) {
if (type != TIMEOUT) {
/*
* file info data subpacket was trashed
*/
tx_znak();
}
return;
}
/*
* extract the relevant info from the header.
*/
strcpy(filename,(char *)rx_data_subpacket);
if (junk_pathnames) {
name = strrchr(filename,'/');
if (name != NULL) {
name++;
}
else {
name = filename;
}
}
else {
name = filename;
}
if (opt_v) {
TRACE("zmrx: receiving file \"%s\"\r",name);
}
sscanf((char *)rx_data_subpacket + strlen((char *)rx_data_subpacket) + 1,
"%ld %lo",&size,&mdate);
current_file_size = size;
/*
* decide whether to transfer the file or skip it
*/
fp = fopen(name,"rb");
if (fp != NULL) {
exists = TRUE;
fstat(fileno(fp),&s);
fclose(fp);
}
else {
exists = FALSE;
}
/*
* if the file already exists here the management options need to
* be checked..
*/
if (exists) {
if (mdate == s.st_mtime) {
/*
* this is crash recovery
*/
mode = "ab";
}
else {
/*
* if the file needs to be protected then exit here.
*/
if (protect) {
tx_pos_header(ZSKIP,0L);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zskip
return;
}
/*
* if it is not ok to just overwrite it
*/
if (!clobber) {
/*
* if the remote file has to be newer
*/
if (newer) {
if (mdate < s.st_mtime) {
tx_pos_header(ZSKIP,0L);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
/*
* and it isnt then exit here.
*/
return;
}
}
}
}
}
/*
* transfer the file
* either not present; remote newer; ok to clobber or no options set.
* (no options->clobber anyway)
*/
fp = fopen(name,mode);
if (fp == NULL) {
tx_pos_header(ZSKIP,0L);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
if (opt_v) {
TRACE("zmrx: can't open file %s\n",name);
}
return;
}
transfer_start = time(NULL);
while (ftell(fp) < size) {//!=
type = receive_file_data(filename,fp);
if (type == ZEOF) {
break;
}
}
/*
* wait for the eof header
*/
while (type != ZEOF) {
type = rx_header_and_check(10000);
}
/*
* close and exit
*/
fclose(fp);
fp = NULL;
/*
* set the time
*/
//tv.actime = mdate;
//tv.modtime = mdate;
//utime(name, &tv);
/*
* and close the input file
*/
if (opt_v) {
TRACE("zmrx: received file \"%s\" \n",name);
}
}
void Czmodem::
cleanup(void)
{
//struct utimbuf tv;
if (fp) {
fflush(fp);
fclose(fp);
/*
* set the time (so crash recovery may work)
*/
//tv.actime = mdate;
//tv.modtime = mdate;
//utime(name, &tv);
}
fd_exit();
}
void Czmodem::usage(void)
{
TRACE("zmrx %s (C) Mattheij Computer Service 1994\n",VERSION);
TRACE("usage : zmrx options\n");
TRACE(" -lline line to use for io\n");
TRACE(" -j junk pathnames\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(" -q quiet\n");
TRACE(" (only one of -n -c or -p may be specified)\n");
cleanup();
//return;//exit(1);
::ExitThread(1);
}
//END_OF_zmrx.c
/******************************************************************************/
/* Project : Unite! File : zmodem transmit Version : 1.02 */
/* */
/* (C) Mattheij Computer Service 1994 */
/* */
/* contact us through (in order of preference) */
/* */
/* email: jacquesm@hacktic.nl */
/* mail: MCS */
/* Prinses Beatrixlaan 535 */
/* 2284 AT RIJSWIJK */
/* The Netherlands */
/* voice phone: 31+070-3936926 */
/******************************************************************************/
/*
* show the progress of the transfer like this:
* zmtx: sending file "garbage" 4096 bytes ( 20%)
*/
/*
void
show_progress(char * name,FILE * fp)
{
time_t duration;
int cps;
int percentage;
if (current_file_size > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -