home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
BTMTSRC3.ZIP
/
ZRECEIVE.C
< prev
next >
Wrap
Text File
|
1991-12-21
|
31KB
|
1,147 lines
/*--------------------------------------------------------------------------*/
/* */
/* */
/* ------------ Bit-Bucket Software, Co. */
/* \ 10001101 / Writers and Distributors of */
/* \ 011110 / Freely Available<tm> Software. */
/* \ 1011 / */
/* ------ */
/* */
/* (C) Copyright 1987-90, Bit Bucket Software Co., a Delaware Corporation. */
/* */
/* */
/* Zmodem file reception module */
/* */
/* */
/* For complete details of the licensing restrictions, please refer */
/* to the License agreement, which is published in its entirety in */
/* the MAKEFILE and BT.C, and also contained in the file LICENSE.240. */
/* */
/* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */
/* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */
/* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */
/* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */
/* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */
/* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */
/* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */
/* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */
/* */
/* */
/* You can contact Bit Bucket Software Co. at any one of the following */
/* addresses: */
/* */
/* Bit Bucket Software Co. FidoNet 1:104/501, 1:132/491, 1:141/491 */
/* P.O. Box 460398 AlterNet 7:491/0 */
/* Aurora, CO 80046 BBS-Net 86:2030/1 */
/* Internet f491.n132.z1.fidonet.org */
/* */
/* Please feel free to contact us at any time to share your comments about */
/* our software and/or licensing policies. */
/* */
/* */
/* This module is based largely on a similar module in OPUS-CBCS V1.03b. */
/* The original work is (C) Copyright 1986, Wynn Wagner III. The original */
/* authors have graciously allowed us to use their code in this work. */
/* */
/*--------------------------------------------------------------------------*/
#include <sys\types.h>
#include <sys\stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
#include <conio.h>
#include <io.h>
#include <stdlib.h>
#ifdef __TURBOC__
#include "tc_utime.h"
#else
#include <sys/utime.h>
#endif
#include "com.h"
#include "xfer.h"
#include "zmodem.h"
#include "keybd.h"
#include "sbuf.h"
#include "sched.h"
#include "externs.h"
#include "prototyp.h"
/*--------------------------------------------------------------------------*/
/* Local routines */
static int RZ_ReceiveData (byte *, int);
static int RZ_32ReceiveData (byte *, int);
static int RZ_InitReceiver (void);
static int RZ_ReceiveBatch (FILE *);
static int RZ_ReceiveFile (FILE *);
static int RZ_GetHeader (void);
static int RZ_SaveToDisk (unsigned long *);
static void RZ_AckBibi (void);
/*--------------------------------------------------------------------------*/
/* Private declarations */
/*--------------------------------------------------------------------------*/
static long DiskAvail;
static long filetime;
static byte realname[64];
/*--------------------------------------------------------------------------*/
/* Private data */
/*--------------------------------------------------------------------------*/
/* Parameters for ZSINIT frame */
#define ZATTNLEN 32
static char Attn[ZATTNLEN + 1]; /* String rx sends to tx on
* err */
static FILE *Outfile; /* Handle of file being
* received */
static int Tryzhdrtype; /* Hdr type to send for Last
* rx close */
static char isBinary; /* Current file is binary
* mode */
static char EOFseen; /* indicates cpm eof (^Z)
* was received */
static char Zconv; /* ZMODEM file conversion
* request */
static int RxCount; /* Count of data bytes
* received */
static byte Upload_path[PATHLEN]; /* Dest. path of file being
* received */
static long Filestart; /* File offset we started
* this xfer from */
extern long filelength (); /* returns length of file
* ref'd in stream */
/*--------------------------------------------------------------------------*/
/* GET ZMODEM */
/* Receive a batch of files. */
/* returns TRUE (1) for good xfer, FALSE (0) for bad */
/* can be called from f_upload or to get mail from a WaZOO Opus */
/*--------------------------------------------------------------------------*/
int get_Zmodem (rcvpath, xferinfo)
char *rcvpath;
FILE *xferinfo;
{
byte namebuf[PATHLEN];
int i;
byte *p;
char *HoldName;
long t;
#ifdef DEBUG
show_debug_name ("get_Zmodem");
#endif
filetime = 0;
_BRK_DISABLE ();
IN_XON_ENABLE ();
/* Secbuf = NULL;*/
Outfile = NULL;
z_size = 0;
Rxtimeout = 100;
Tryzhdrtype = ZRINIT;
strcpy (namebuf, rcvpath);
Filename = namebuf;
strcpy (Upload_path, rcvpath);
p = Upload_path + strlen (Upload_path) - 1;
while (p >= Upload_path && *p != '\\')
--p;
*(++p) = '\0';
HoldName = HoldAreaNameMunge(&called_addr);
sprintf (Abortlog_name, "%s%s.Z\0",
HoldName, Hex_Addr_Str (&remote_addr));
DiskAvail = zfree (Upload_path);
if (((i = RZ_InitReceiver ()) == ZCOMPL) ||
((i == ZFILE) && ((RZ_ReceiveBatch (xferinfo)) == OK)))
{
XON_DISABLE ();
XON_ENABLE (); /* Make sure xmitter is
* unstuck */
return 1;
}
CLEAR_OUTBOUND ();
XON_DISABLE (); /* Make sure xmitter is
* unstuck */
send_can (); /* transmit at least 10 cans */
t = timerset (200); /* wait no more than 2
* seconds */
while (!timeup (t) && !OUT_EMPTY () && CARRIER)
time_release (); /* Give up slice while
* waiting */
XON_ENABLE (); /* Turn XON/XOFF back on... */
/*
if (Secbuf)
free (Secbuf);
*/
if (Outfile)
fclose (Outfile);
return 0;
} /* get_Zmodem */
/*--------------------------------------------------------------------------*/
/* RZ RECEIVE DATA */
/* Receive array buf of max length with ending ZDLE sequence */
/* and CRC. Returns the ending character or error code. */
/*--------------------------------------------------------------------------*/
static int RZ_ReceiveData (buf, length)
register byte *buf;
register int length;
{
register int c;
register word crc;
char *endpos;
int d;
#ifdef DEBUG
show_debug_name ("RZ_ReceiveData");
#endif
if (Rxframeind == ZBIN32)
return RZ_32ReceiveData (buf, length);
crc = RxCount = 0;
buf[0] = buf[1] = 0;
endpos = buf + length;
while (buf <= endpos)
{
if ((c = Z_GetZDL ()) & ~0xFF)
{
CRCfoo:
switch (c)
{
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
/*-----------------------------------*/
/* C R C s */
/*-----------------------------------*/
crc = Z_UpdateCRC (((d = c) & 0xFF), crc);
if ((c = Z_GetZDL ()) & ~0xFF)
goto CRCfoo;
crc = Z_UpdateCRC (c, crc);
if ((c = Z_GetZDL ()) & ~0xFF)
goto CRCfoo;
crc = Z_UpdateCRC (c, crc);
if (crc & 0xFFFF)
{
z_message (msgtxt[M_CRC_MSG]);
return ERROR;
}
RxCount = length - (endpos - buf);
return d;
case GOTCAN:
/*-----------------------------------*/
/* Cancel */
/*-----------------------------------*/
z_log (msgtxt[M_CAN_MSG]);
return ZCAN;
case TIMEOUT:
/*-----------------------------------*/
/* Timeout */
/*-----------------------------------*/
z_message (msgtxt[M_TIMEOUT]);
return c;
case RCDO:
/*-----------------------------------*/
/* No carrier */
/*-----------------------------------*/
z_log (msgtxt[M_NO_CARRIER]);
CLEAR_INBOUND ();
return c;
default:
/*-----------------------------------*/
/* Something bizarre */
/*-----------------------------------*/
z_message (msgtxt[M_DEBRIS]);
CLEAR_INBOUND ();
return c;
} /* switch */
} /* if */
*buf++ = (unsigned char) c;
crc = Z_UpdateCRC (c, crc);
} /* while(1) */
z_message (msgtxt[M_LONG_PACKET]);
return ERROR;
} /* RZ_ReceiveData */
/*--------------------------------------------------------------------------*/
/* RZ RECEIVE DATA with 32 bit CRC */
/* Receive array buf of max length with ending ZDLE sequence */
/* and CRC. Returns the ending character or error code. */
/*--------------------------------------------------------------------------*/
static int RZ_32ReceiveData (buf, length)
register byte *buf;
register int length;
{
register int c;
unsigned long crc;
char *endpos;
int d;
#ifdef DEBUG
show_debug_name ("RZ_32ReceiveData");
#endif
crc = 0xFFFFFFFF;
RxCount = 0;
buf[0] = buf[1] = 0;
endpos = buf + length;
while (buf <= endpos)
{
if ((c = Z_GetZDL ()) & ~0xFF)
{
CRCfoo:
switch (c)
{
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
/*-----------------------------------*/
/* C R C s */
/*-----------------------------------*/
d = c;
c &= 0377;
crc = Z_32UpdateCRC (c, crc);
if ((c = Z_GetZDL ()) & ~0xFF)
goto CRCfoo;
crc = Z_32UpdateCRC (c, crc);
if ((c = Z_GetZDL ()) & ~0xFF)
goto CRCfoo;
crc = Z_32UpdateCRC (c, crc);
if ((c = Z_GetZDL ()) & ~0xFF)
goto CRCfoo;
crc = Z_32UpdateCRC (c, crc);
if ((c = Z_GetZDL ()) & ~0xFF)
goto CRCfoo;
crc = Z_32UpdateCRC (c, crc);
if (crc != 0xDEBB20E3)
{
z_message (msgtxt[M_CRC_MSG]);
return ERROR;
}
RxCount = length - (endpos - buf);
return d;
case GOTCAN:
/*-----------------------------------*/
/* Cancel */
/*-----------------------------------*/
z_log (msgtxt[M_CAN_MSG]);
return ZCAN;
case TIMEOUT:
/*-----------------------------------*/
/* Timeout */
/*-----------------------------------*/
z_message (msgtxt[M_TIMEOUT]);
return c;
case RCDO:
/*-----------------------------------*/
/* No carrier */
/*-----------------------------------*/
z_log (msgtxt[M_NO_CARRIER]);
CLEAR_INBOUND ();
return c;
default:
/*-----------------------------------*/
/* Something bizarre */
/*-----------------------------------*/
z_message (msgtxt[M_DEBRIS]);
CLEAR_INBOUND ();
return c;
} /* switch */
} /* if */
*buf++ = (unsigned char) c;
crc = Z_32UpdateCRC (c, crc);
} /* while(1) */
z_message (msgtxt[M_LONG_PACKET]);
return ERROR;
} /* RZ_ReceiveData */
/*--------------------------------------------------------------------------*/
/* RZ INIT RECEIVER */
/* Initialize for Zmodem receive attempt, try to activate Zmodem sender */
/* Handles ZSINIT, ZFREECNT, and ZCOMMAND frames */
/* */
/* Return codes: */
/* ZFILE .... Zmodem filename received */
/* ZCOMPL ... transaction finished */
/* ERROR .... any other condition */
/*--------------------------------------------------------------------------*/
static int RZ_InitReceiver ()
{
register int n;
int errors = 0;
char *sptr;
#ifdef DEBUG
show_debug_name ("RZ_InitReceiver");
#endif
for (n = 12; --n >= 0;)
{
/*--------------------------------------------------------------*/
/* Set buffer length (0=unlimited, don't wait). */
/* Also set capability flags */
/*--------------------------------------------------------------*/
Z_PutLongIntoHeader (0L);
Txhdr[ZF0] = CANFC32 | CANFDX | CANOVIO;
Z_SendHexHeader (Tryzhdrtype, Txhdr);
if (Tryzhdrtype == ZSKIP)
Tryzhdrtype = ZRINIT;
AGAIN:
switch (Z_GetHeader (Rxhdr))
{
case ZFILE:
Zconv = Rxhdr[ZF0];
Tryzhdrtype = ZRINIT;
if (RZ_ReceiveData (Secbuf, WAZOOMAX) == GOTCRCW)
return ZFILE;
Z_SendHexHeader (ZNAK, Txhdr);
if (--n < 0)
{
sptr = "ZFILE";
goto Err;
}
goto AGAIN;
case ZSINIT:
if (RZ_ReceiveData (Attn, ZATTNLEN) == GOTCRCW)
{
Z_PutLongIntoHeader (1L);
Z_SendHexHeader (ZACK, Txhdr);
}
else Z_SendHexHeader (ZNAK, Txhdr);
if (--n < 0)
{
sptr = "ZSINIT";
goto Err;
}
goto AGAIN;
case ZFREECNT:
Z_PutLongIntoHeader (DiskAvail);
Z_SendHexHeader (ZACK, Txhdr);
goto AGAIN;
case ZCOMMAND:
/*-----------------------------------------*/
/* Paranoia is good for you... */
/* Ignore command from remote, but lie and */
/* say we did the command ok. */
/*-----------------------------------------*/
if (RZ_ReceiveData (Secbuf, WAZOOMAX) == GOTCRCW)
{
status_line (msgtxt[M_Z_IGNORING], Secbuf);
Z_PutLongIntoHeader (0L);
do
{
Z_SendHexHeader (ZCOMPL, Txhdr);
}
while (++errors < 10 && Z_GetHeader (Rxhdr) != ZFIN);
RZ_AckBibi ();
return ZCOMPL;
}
else Z_SendHexHeader (ZNAK, Txhdr);
if (--n < 0)
{
sptr = "CMD";
goto Err;
}
goto AGAIN;
case ZCOMPL:
if (--n < 0)
{
sptr = "COMPL";
goto Err;
}
goto AGAIN;
case ZFIN:
RZ_AckBibi ();
return ZCOMPL;
case ZCAN:
sptr = msgtxt[M_CAN_MSG];
goto Err;
case RCDO:
sptr = &(msgtxt[M_NO_CARRIER][1]);
CLEAR_INBOUND ();
goto Err;
} /* switch */
} /* for */
sptr = msgtxt[M_TIMEOUT];
Err:
sprintf (e_input, msgtxt[M_Z_INITRECV], sptr);
z_log (e_input);
return ERROR;
} /* RZ_InitReceiver */
/*--------------------------------------------------------------------------*/
/* RZFILES */
/* Receive a batch of files using ZMODEM protocol */
/*--------------------------------------------------------------------------*/
static int RZ_ReceiveBatch (xferinfo)
FILE *xferinfo;
{
register int c;
byte namebuf[PATHLEN];
#ifdef DEBUG
show_debug_name ("RZ_ReceiveBatch");
#endif
while (1)
{
switch (c = RZ_ReceiveFile (xferinfo))
{
case ZEOF:
if (Resume_WaZOO)
{
remove_abort (Abortlog_name, Resume_name);
strcpy (namebuf, Upload_path);
strcat (namebuf, Resume_name);
unique_name (namebuf);
rename (Filename, namebuf);
}
/* fallthrough */
case ZSKIP:
switch (RZ_InitReceiver ())
{
case ZCOMPL:
return OK;
default:
return ERROR;
case ZFILE:
break;
} /* switch */
break;
default:
fclose (Outfile);
Outfile = NULL;
if (remote_capabilities)
{
if (!Resume_WaZOO)
{
add_abort (Abortlog_name, Resume_name, Filename, Upload_path, Resume_info);
}
}
else unlink (Filename);
return c;
} /* switch */
} /* while */
} /* RZ_ReceiveBatch */
/*--------------------------------------------------------------------------*/
/* RZ RECEIVE FILE */
/* Receive one file; assumes file name frame is preloaded in Secbuf */
/*--------------------------------------------------------------------------*/
static int RZ_ReceiveFile (xferinfo)
FILE *xferinfo;
{
register int c;
int n;
long rxbytes;
char *sptr;
struct utimbuf utimes;
char j[50];
#ifdef DEBUG
show_debug_name ("RZ_ReceiveFile");
#endif
EOFseen = FALSE;
c = RZ_GetHeader ();
if (c == ERROR || c == ZSKIP)
return (Tryzhdrtype = ZSKIP);
n = 10;
rxbytes = Filestart;
while (1)
{
Z_PutLongIntoHeader (rxbytes);
Z_SendHexHeader (ZRPOS, Txhdr);
NxtHdr:
switch (c = Z_GetHeader (Rxhdr))
{
case ZDATA:
/*-----------------------------------------*/
/* Data Packet */
/*-----------------------------------------*/
if (Rxpos != rxbytes)
{
if (--n < 0)
{
sptr = msgtxt[M_FUBAR_MSG];
goto Err;
}
sprintf (j, "%s; %ld/%ld", msgtxt[M_BAD_POS], rxbytes, Rxpos);
z_message (j);
Z_PutString (Attn);
continue;
}
MoreData:
switch (c = RZ_ReceiveData (Secbuf, WAZOOMAX))
{
case ZCAN:
sptr = msgtxt[M_CAN_MSG];
goto Err;
case RCDO:
sptr = &(msgtxt[M_NO_CARRIER][1]);
CLEAR_INBOUND ();
goto Err;
case ERROR:
/*-----------------------*/
/* CRC error */
/*-----------------------*/
if (--n < 0)
{
sptr = msgtxt[M_FUBAR_MSG];
goto Err;
}
show_loc (rxbytes, n);
Z_PutString (Attn);
continue;
case TIMEOUT:
if (--n < 0)
{
sptr = msgtxt[M_TIMEOUT];
goto Err;
}
show_loc (rxbytes, n);
continue;
case GOTCRCW:
/*---------------------*/
/* End of frame */
/*-----------------------*/
n = 10;
if (RZ_SaveToDisk (&rxbytes) == ERROR)
return ERROR;
Z_PutLongIntoHeader (rxbytes);
Z_SendHexHeader (ZACK, Txhdr);
goto NxtHdr;
case GOTCRCQ:
/*---------------------*/
/* Zack expected */
/*-----------------------*/
n = 10;
if (RZ_SaveToDisk (&rxbytes) == ERROR)
return ERROR;
Z_PutLongIntoHeader (rxbytes);
Z_SendHexHeader (ZACK, Txhdr);
goto MoreData;
case GOTCRCG:
/*---------------------*/
/* Non-stop */
/*-----------------------*/
n = 10;
if (RZ_SaveToDisk (&rxbytes) == ERROR)
return ERROR;
goto MoreData;
case GOTCRCE:
/*---------------------*/
/* Header to follow */
/*-----------------------*/
n = 10;
if (RZ_SaveToDisk (&rxbytes) == ERROR)
return ERROR;
goto NxtHdr;
} /* switch */
case ZNAK:
case TIMEOUT:
/*-----------------------------------------*/
/* Packet was probably garbled */
/*-----------------------------------------*/
if (--n < 0)
{
sptr = msgtxt[M_JUNK_BLOCK];
goto Err;
}
show_loc (rxbytes, n);
continue;
case ZFILE:
/*-----------------------------------------*/
/* Sender didn't see our ZRPOS yet */
/*-----------------------------------------*/
RZ_ReceiveData (Secbuf, WAZOOMAX);
continue;
case ZEOF:
/*-----------------------------------------*/
/* End of the file */
/* Ignore EOF if it's at wrong place; force */
/* a timeout because the eof might have */
/* gone out before we sent our ZRPOS */
/*-----------------------------------------*/
if (locate_y && !(fullscreen && un_attended))
gotoxy (2, (byte) locate_y - 1);
if (Rxpos != rxbytes)
goto NxtHdr;
throughput (2, rxbytes - Filestart);
fclose (Outfile);
status_line ("%s-Z%s %s", msgtxt[M_FILE_RECEIVED], Crc32 ? "/32" : "", realname);
update_files (0);
if (filetime)
{
utimes.actime = filetime;
utimes.modtime = filetime;
utime (Filename, &utimes);
}
Outfile = NULL;
if (xferinfo != NULL)
{
fprintf (xferinfo, "%s\n", Filename);
}
return c;
case ERROR:
/*-----------------------------------------*/
/* Too much garbage in header search error */
/*-----------------------------------------*/
if (--n < 0)
{
sptr = msgtxt[M_JUNK_BLOCK];
goto Err;
}
show_loc (rxbytes, n);
Z_PutString (Attn);
continue;
case ZSKIP:
return c;
default:
sptr = IDUNNO_msg;
CLEAR_INBOUND ();
goto Err;
} /* switch */
} /* while */
Err:sprintf (e_input, msgtxt[M_Z_RZ], sptr);
z_log (e_input);
return ERROR;
} /* RZ_ReceiveFile */
/*--------------------------------------------------------------------------*/
/* RZ GET HEADER */
/* Process incoming file information header */
/*--------------------------------------------------------------------------*/
static int RZ_GetHeader ()
{
register byte *p;
struct stat f;
int i;
byte *ourname;
byte *theirname;
unsigned long filesize;
byte *fileinfo;
char j[80];
char fullname[20];
char fname[9];
char ext[4];
char *cptr;
char *cptr1;
#ifdef DEBUG
show_debug_name ("RZ_GetHeader");
#endif
/*--------------------------------------------------------------------*/
/* Setup the transfer mode */
/*--------------------------------------------------------------------*/
isBinary = (char) ((!RXBINARY && Zconv == ZCNL) ? 0 : 1);
Resume_WaZOO = 0;
/*--------------------------------------------------------------------*/
/* Extract and verify filesize, if given. */
/* Reject file if not at least 10K free */
/*--------------------------------------------------------------------*/
filesize = 0L;
filetime = 0L;
fileinfo = Secbuf + 1 + strlen (Secbuf);
if (*fileinfo)
sscanf (fileinfo, "%ld %lo", &filesize, &filetime);
if (filesize + 10240 > DiskAvail)
{
status_line (msgtxt[M_OUT_OF_DISK_SPACE]);
return ERROR;
}
/*--------------------------------------------------------------------*/
/* Get and/or fix filename for uploaded file */
/*--------------------------------------------------------------------*/
p = Filename + strlen (Filename) - 1; /* Find end of upload path */
while (p >= Filename && *p != '\\')
p--;
ourname = ++p;
p = Secbuf + strlen (Secbuf) - 1; /* Find transmitted simple
* filename */
while (p >= Secbuf && *p != '\\' && *p != '/' && *p != ':')
p--;
theirname = ++p;
/*----------------*/
cptr = fname;
cptr1 = theirname;
while (*cptr1 && *cptr1 != '.' && cptr < (fname + 8)) /* CML - cut to 8.3 for now */
*cptr++ = *cptr1++;
*cptr = '\0';
while (*cptr1 && *cptr1 != '.')
++cptr1;
if (*cptr1 == '.')
++cptr1;
cptr = ext;
while (*cptr1 && *cptr1 != '.' && cptr < (ext + 3))
*cptr++ = *cptr1++;
*cptr = '\0';
sprintf(fullname,"%s%s%s",fname,(char *)(ext[0] ? "." : ""),ext);
theirname = fullname;
/*----------------*/
strcpy (ourname, theirname); /* Start w/ our path & their
* name */
strcpy (realname, Filename);
/*--------------------------------------------------------------------*/
/* Save info on WaZOO transfer in case of abort */
/*--------------------------------------------------------------------*/
if (remote_capabilities)
{
strcpy (Resume_name, theirname);
sprintf (Resume_info, "%ld %lo", filesize, filetime);
}
/*--------------------------------------------------------------------*/
/* Check if this is a failed WaZOO transfer which should be resumed */
/*--------------------------------------------------------------------*/
if (remote_capabilities && dexists (Abortlog_name))
{
Resume_WaZOO = (byte) check_failed (Abortlog_name, theirname, Resume_info, ourname);
}
/*--------------------------------------------------------------------*/
/* Open either the old or a new file, as appropriate */
/*--------------------------------------------------------------------*/
if (Resume_WaZOO)
{
if (dexists (Filename))
p = "r+b";
else p = write_binary;
}
else
{
strcpy (ourname, theirname);
/*--------------------------------------------------------------------*/
/* If the file already exists: */
/* 1) And the new file has the same time and size, return ZSKIP */
/* 2) And OVERWRITE is turned on, delete the old copy */
/* 3) Else create a unique file name in which to store new data */
/*--------------------------------------------------------------------*/
if (dexists (Filename))
{ /* If file already exists... */
if ((Outfile = fopen (Filename, read_binary)) == NULL)
{
(void) got_error (msgtxt[M_OPEN_MSG], Filename);
return ERROR;
}
fstat (fileno (Outfile), &f);
fclose (Outfile);
if (filesize == f.st_size && filetime == f.st_mtime)
{
status_line (msgtxt[M_ALREADY_HAVE], Filename);
return ZSKIP;
}
i = strlen (Filename) - 1;
if ((!overwrite) || (is_arcmail (Filename, i)))
{
unique_name (Filename);
}
else
{
unlink (Filename);
}
} /* if exist */
if (strcmp (ourname, theirname))
{
status_line (msgtxt[M_RENAME_MSG], ourname);
}
p = write_binary;
}
if ((Outfile = fopen (Filename, p)) == NULL)
{
(void) got_error (msgtxt[M_OPEN_MSG], Filename);
return ERROR;
}
if (isatty (fileno (Outfile)))
{
errno = 1;
(void) got_error (msgtxt[M_DEVICE_MSG], Filename);
fclose (Outfile);
return (ERROR);
}
Filestart = (Resume_WaZOO) ? filelength (fileno (Outfile)) : 0L;
if (Resume_WaZOO)
status_line (msgtxt[M_SYNCHRONIZING_OFFSET], Filestart);
fseek (Outfile, Filestart, SEEK_SET);
if (remote_capabilities)
p = check_netfile(theirname);
else p = NULL;
if (lock_baud) /* CML calculate correct time */
sprintf (j, "%s %s; %s%ldb, %d min.",(p) ? p : msgtxt[M_RECEIVING],realname,(isBinary) ? "" : "ASCII ",filesize,(int) ((filesize - Filestart) * 10 / actual_baud + 53) / 54);
else
sprintf (j, "%s %s; %s%ldb, %d min.",(p) ? p : msgtxt[M_RECEIVING],realname,(isBinary) ? "" : "ASCII ",filesize,(int) ((filesize - Filestart) * 10 / cur_baud + 53) / 54);
file_length = filesize;
if (un_attended && fullscreen)
{
clear_filetransfer ();
sb_move (filewin, 1, 2);
sb_puts (filewin, j);
elapse_time ();
if (lock_baud) /* CML calculate correct time */
i = (int) (filesize * 10 / actual_baud + 53) / 54;
else
i = (int) (filesize * 10 / cur_baud + 53) / 54;
sb_move (filewin, 2, 69);
sprintf(j, "%3d min", i);
sb_puts (filewin, j);
sb_show ();
}
else
{
set_xy (j);
set_xy (NULL);
locate_x += 2;
}
throughput (0, 0L);
return OK;
} /* RZ_GetHeader */
/*--------------------------------------------------------------------------*/
/* RZ SAVE TO DISK */
/* Writes the received file data to the output file. */
/* If in ASCII mode, stops writing at first ^Z, and converts all */
/* solo CR's or LF's to CR/LF pairs. */
/*--------------------------------------------------------------------------*/
static int RZ_SaveToDisk (rxbytes)
unsigned long *rxbytes;
{
static byte lastsent;
register byte *p;
register int count;
int i;
char j[100];
#ifdef DEBUG
show_debug_name ("RZ_SaveToDisk");
#endif
count = RxCount;
if (got_ESC ())
{
send_can (); /* Cancel file */
while ((i = Z_GetByte (20)) != TIMEOUT && i != RCDO) /* Wait for line to
* clear */
CLEAR_INBOUND ();
send_can (); /* and Cancel Batch */
z_log (msgtxt[M_KBD_MSG]);
return ERROR;
}
if (count != z_size)
{
if (fullscreen && un_attended)
{
sb_move (filewin, 2, 12);
sb_puts (filewin, ultoa (((unsigned long) (z_size = count)), e_input, 10));
sb_puts (filewin, " ");
elapse_time ();
sb_show ();
}
else
{
gotoxy (locate_x + 10, locate_y);
cputs (ultoa (((unsigned long) (z_size = count)), e_input, 10));
putch (' ');
}
}
if (isBinary)
{
if (fwrite (Secbuf, 1, count, Outfile) != count)
goto oops;
}
else
{
if (EOFseen)
return OK;
for (p = Secbuf; --count >= 0; ++p)
{
if (*p == CPMEOF)
{
EOFseen = TRUE;
return OK;
}
if (*p == '\n')
{
if (lastsent != '\r' && putc ('\r', Outfile) == EOF)
goto oops;
}
else
{
if (lastsent == '\r' && putc ('\n', Outfile) == EOF)
goto oops;
}
if (putc ((lastsent = *p), Outfile) == EOF)
goto oops;
}
}
*rxbytes += RxCount;
i = (int) ((file_length - *rxbytes)* 10 / cur_baud + 53) / 54;
sprintf (j, "%3d min", i);
if (fullscreen && un_attended)
{
elapse_time();
sb_move (filewin, 2, 2);
sb_puts (filewin, ultoa (((unsigned long) (*rxbytes)), e_input, 10));
sb_move (filewin, 2, 69);
sb_puts (filewin, j);
elapse_time ();
sb_show ();
}
else
{
gotoxy (locate_x, locate_y);
cputs (ultoa (((unsigned long) (*rxbytes)), e_input, 10));
gotoxy (locate_x + 20, locate_y);
printf ("%s", j);
putch (' ');
}
return OK;
oops:
got_error (msgtxt[M_WRITE_MSG], Filename);
return ERROR;
} /* RZ_SaveToDisk */
/*--------------------------------------------------------------------------*/
/* RZ ACK BIBI */
/* Ack a ZFIN packet, let byegones be byegones */
/*--------------------------------------------------------------------------*/
static void RZ_AckBibi ()
{
register int n;
#ifdef DEBUG
show_debug_name ("RZ_AckBiBi");
#endif
Z_PutLongIntoHeader (0L);
for (n = 4; --n;)
{
Z_SendHexHeader (ZFIN, Txhdr);
switch (Z_GetByte (100))
{
case 'O':
Z_GetByte (1); /* Discard 2nd 'O' */
case TIMEOUT:
case RCDO:
return;
} /* switch */
} /* for */
} /* RZ_AckBibi */