You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1414 lines
32 KiB
1414 lines
32 KiB
/* zmdm_rcv.c -- ZMODEM compatible file receiving routines for HyperACCESS
|
|
*
|
|
* Copyright 1990 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 15 $
|
|
* $Date: 7/12/02 8:35a $
|
|
*/
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
//#define DEBUGSTR
|
|
|
|
#include <setjmp.h>
|
|
#include <time.h>
|
|
#include <term\res.h>
|
|
#include <sys\types.h>
|
|
#include <sys\utime.h>
|
|
|
|
#include <tdll\stdtyp.h>
|
|
#include <tdll\mc.h>
|
|
#include <tdll\com.h>
|
|
#include <tdll\assert.h>
|
|
#include <tdll\session.h>
|
|
#include <tdll\load_res.h>
|
|
#include <tdll\xfer_msc.h>
|
|
#include <tdll\globals.h>
|
|
#include <tdll\file_io.h>
|
|
#include <tdll\file_msc.h>
|
|
#include <tdll\htchar.h>
|
|
|
|
#define BYTE unsigned char
|
|
|
|
#include "itime.h"
|
|
#include "xfr_dsp.h"
|
|
#include "xfr_todo.h"
|
|
#include "xfr_srvc.h"
|
|
|
|
#include "xfer.h"
|
|
#include "xfer.hh"
|
|
#include "xfer_tsc.h"
|
|
|
|
#include "foo.h"
|
|
|
|
#include "zmodem.hh"
|
|
#include "zmodem.h"
|
|
|
|
/* * * * * * * * * * * * *
|
|
* Function Prototypes *
|
|
* * * * * * * * * * * * */
|
|
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
#include <stdio.h>
|
|
FILE* fpPacket;
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
|
|
int procheader (ZC *zc, TCHAR *name);
|
|
int putsec (ZC *zc, BYTE *buf, int n);
|
|
|
|
int isvalid (TCHAR c, int base);
|
|
TCHAR *stoi (TCHAR *ptr, int *val, int base);
|
|
TCHAR *stol (TCHAR *ptr, long *val, int base);
|
|
int IsAnyLower (TCHAR *s);
|
|
long getfree (void);
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* zmdm_rcv
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
USHORT zmdm_rcv(HSESSION h, int method, int attended, int single_file)
|
|
{
|
|
ZC *zc = NULL;
|
|
BOOL still_trying = TRUE;
|
|
BOOL override = FALSE;
|
|
int nJmpVal = 0;
|
|
int xstatus;
|
|
unsigned int uiOldOptions;
|
|
int tvar;
|
|
TCHAR ch;
|
|
XFR_Z_PARAMS *pZ;
|
|
#if defined(DEADWOOD)
|
|
DWORD nLen;
|
|
#endif // defined(DEADWOOD)
|
|
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fpPacket = fopen("zpacket.dbg", "a");
|
|
assert(fpPacket);
|
|
fputs("----- Starting Zmodem rcv -----\n", fpPacket);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
|
|
(void)&single_file;
|
|
|
|
xstatus = TSC_NO_MEM;
|
|
|
|
zc = malloc(sizeof(ZC));
|
|
if (zc == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
memset(zc, 0, sizeof(ZC));
|
|
|
|
zc->nMethod = method; // Zmodem, or Zmodem crash recovery
|
|
// This makes it easy to override some settings when
|
|
// Zmodem crash recovery is selected.
|
|
if (method == XF_ZMODEM_CR)
|
|
{
|
|
zc->fSavePartial = TRUE; // Leave partial files around
|
|
zc->ulOverride = XFR_RO_ALWAYS; // Always overwrite existing file
|
|
}
|
|
else
|
|
{
|
|
// Use default settings otherwise.
|
|
//
|
|
zc->fSavePartial = xfer_save_partial(h);
|
|
zc->ulOverride = (unsigned long)0;
|
|
}
|
|
|
|
zc->hSession = h;
|
|
zc->hCom = sessQueryComHdl(h);
|
|
zc->secbuf = NULL;
|
|
zc->fname = NULL;
|
|
zc->our_fname = NULL;
|
|
zc->z_crctab = NULL;
|
|
zc->z_cr3tab = NULL;
|
|
|
|
/* allocate space for large packets since we don't necessarily know what
|
|
* we'll be getting.
|
|
*/
|
|
zc->secbuf = malloc(1025 * sizeof(TCHAR));
|
|
if (zc->secbuf == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
|
|
zc->fname = malloc(FNAME_LEN * sizeof(TCHAR));
|
|
if (zc->fname == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
|
|
zc->our_fname = malloc(FNAME_LEN * sizeof(TCHAR));
|
|
if (zc->our_fname == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
|
|
#if defined(DEADWOOD)
|
|
resLoadDataBlock(glblQueryDllHinst(),
|
|
IDT_CSB_CRC_TABLE,
|
|
&zc->z_crctab,
|
|
&nLen);
|
|
assert(nLen != 0);
|
|
#else // defined(DEADWOOD)
|
|
zc->z_crctab = usCrc16Lookup;
|
|
#endif // defined(DEADWOOD)
|
|
|
|
if (zc->z_crctab == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
|
|
#if defined(DEADWOOD)
|
|
resLoadDataBlock(glblQueryDllHinst(),
|
|
IDT_CRC_32_TAB,
|
|
&zc->z_cr3tab,
|
|
&nLen);
|
|
assert(nLen != 0);
|
|
#else // defined(DEADWOOD)
|
|
zc->z_cr3tab = ulCrc32Lookup;
|
|
#endif // defined(DEADWOOD)
|
|
if (zc->z_cr3tab == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
|
|
xstatus = TSC_OK;
|
|
|
|
if (xfer_set_comport(h, FALSE, &uiOldOptions) != TRUE)
|
|
{
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
override = TRUE;
|
|
}
|
|
|
|
zmdm_retval (zc, TRUE, ZACK);
|
|
|
|
zc->file_bytes = 0L;
|
|
zc->real_bytes = 0L;
|
|
zc->total_bytes = 0L;
|
|
zc->actual_bytes = 0L;
|
|
zc->nSkip = FALSE;
|
|
zc->fh = NULL;
|
|
zc->pstatus = zc->last_event = -4;
|
|
zc->xfertimer = -1L;
|
|
zc->nfiles = 0;
|
|
zc->filen = 0;
|
|
zc->filesize = -1L;
|
|
zc->nbytes = -1L;
|
|
zc->errors = 0;
|
|
|
|
// Capture the current execution environment into the flagkey_buf buffer.
|
|
// The Trow() function will later use it to restore the execution
|
|
// environment (i.e., the state of all system registers and the instruction
|
|
// counter.
|
|
//
|
|
nJmpVal = setjmp(zc->flagkey_buf);
|
|
if (nJmpVal != 0)
|
|
{
|
|
if (nJmpVal == 4)
|
|
{
|
|
xstatus = TSC_DISK_FULL;
|
|
zmdm_retval(zc, TRUE, ZFERR);
|
|
}
|
|
else
|
|
{
|
|
xstatus = TSC_USER_CANNED;
|
|
zmdm_retval(zc, TRUE, ZCAN);
|
|
}
|
|
zc->xfertime = (long)interval(zc->xfertimer);
|
|
stohdr(zc, 0L);
|
|
zshhdr(zc, ZCAN, zc->Txhdr);
|
|
canit(zc);
|
|
if (zc->fh)
|
|
xfer_close_rcv_file(h,
|
|
zc->fh,
|
|
xstatus,
|
|
zc->fname,
|
|
zc->our_fname,
|
|
zc->fSavePartial,
|
|
zc->basesize + zc->filesize,
|
|
0);
|
|
zc->fh = NULL;
|
|
// zmdm_retval(zc, TRUE, ZABORT); jkh, 2/12/95 see above
|
|
goto done;
|
|
}
|
|
|
|
pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
|
|
assert(pZ);
|
|
|
|
if (pZ == NULL)
|
|
{
|
|
xstatus = TSC_NO_MEM;
|
|
goto done;
|
|
}
|
|
|
|
zc->Zctlesc = pZ->nEscCtrlCodes;
|
|
zc->Rxtimeout = pZ->nRetryWait;
|
|
if (zc->Rxtimeout <= 0)
|
|
{
|
|
zc->Rxtimeout = 10;
|
|
}
|
|
zc->Rxtimeout *= 10;
|
|
|
|
zc->do_init = TRUE; // Always start right up since we may be autostarted
|
|
|
|
zc->tryzhdrtype = ZRINIT;
|
|
|
|
if (tryz(zc) == ZFILE)
|
|
{
|
|
// tzset();
|
|
|
|
if (zc->xfertimer == (-1L))
|
|
{
|
|
zc->xfertimer = (long)startinterval();
|
|
}
|
|
|
|
// Receive files with Z-modem protocol.
|
|
//
|
|
switch (xstatus = rzfiles(zc))
|
|
{
|
|
case OK:
|
|
xstatus = TSC_OK;
|
|
break;
|
|
case ZABORT:
|
|
xstatus = TSC_USER_CANNED;
|
|
do {
|
|
// purgeline(zc);
|
|
ComRcvBufrClear(zc->hCom);
|
|
Sleep(100);
|
|
} while (mComRcvBufrPeek(zc->hCom, &ch) != 0);
|
|
// } while (rdchk(h) != ERROR);
|
|
|
|
/* we try to eat any characters until the other end quits */
|
|
break;
|
|
case RCDO: /* Not too sure about this one */
|
|
case ZCARRIER_LOST:
|
|
xstatus = TSC_LOST_CARRIER;
|
|
break;
|
|
case ERROR:
|
|
canit(zc);
|
|
/* fall through */
|
|
case ZMDM_VIRUS:
|
|
do {
|
|
// purgeline(zc);
|
|
ComRcvBufrClear(zc->hCom);
|
|
Sleep(100);
|
|
} while (mComRcvBufrPeek(zc->hCom, &ch) != 0);
|
|
// } while (rdchk(zc) != ERROR);
|
|
|
|
/* fall thru to the default case */
|
|
default:
|
|
xstatus = zmdm_error(zc, xstatus);
|
|
break;
|
|
}
|
|
}
|
|
done:
|
|
|
|
zmdmr_progress(zc, TRANSFER_DONE);
|
|
|
|
if (override)
|
|
{
|
|
xfer_restore_comport(h, uiOldOptions);
|
|
}
|
|
|
|
// Fool around with the return code to get a useful status return
|
|
if ((tvar = zmdm_retval(zc, FALSE, 0)) != ZACK)
|
|
// Retrieve last error message
|
|
{
|
|
if (tvar == ZMDM_VIRUS)
|
|
{
|
|
do {
|
|
// purgeline(zc);
|
|
ComRcvBufrClear(zc->hCom);
|
|
Sleep(100);
|
|
} while (mComRcvBufrPeek(zc->hCom, &ch) != 0);
|
|
// } while (rdchk(zc) != ERROR);
|
|
}
|
|
xstatus = zmdm_error(zc, tvar);
|
|
}
|
|
|
|
if (xstatus != TSC_OK)
|
|
{
|
|
if (zc->fh)
|
|
{
|
|
xfer_close_rcv_file(h,
|
|
zc->fh,
|
|
xstatus,
|
|
zc->fname,
|
|
zc->our_fname,
|
|
zc->fSavePartial,
|
|
zc->basesize + zc->filesize,
|
|
0);
|
|
}
|
|
}
|
|
|
|
if (zc->secbuf != NULL)
|
|
{
|
|
free(zc->secbuf);
|
|
zc->secbuf = NULL;
|
|
}
|
|
if (zc->fname != NULL)
|
|
{
|
|
free(zc->fname);
|
|
zc->fname = NULL;
|
|
}
|
|
if (zc->our_fname != NULL)
|
|
{
|
|
free(zc->our_fname);
|
|
zc->our_fname = NULL;
|
|
}
|
|
if (zc->z_crctab != NULL)
|
|
{
|
|
#if defined(DEADWOOD)
|
|
resFreeDataBlock(h, zc->z_crctab);
|
|
zc->z_crctab = NULL;
|
|
#else // defined(DEADWOOD
|
|
//
|
|
// We don't need to free zc->z_crctab since it is pointing
|
|
// to a static constant array. REV: 4/10/2002
|
|
//
|
|
zc->z_crctab = NULL;
|
|
#endif // defined(DEADWOOD)
|
|
}
|
|
if (zc->z_cr3tab)
|
|
{
|
|
#if defined(DEADWOOD)
|
|
resFreeDataBlock(h, zc->z_cr3tab);
|
|
zc->z_cr3tab = NULL;
|
|
#else // defined(DEADWOOD
|
|
//
|
|
// We don't need to free zc->z_cr3tab since it is pointing
|
|
// to a static constant array. REV: 4/10/2002
|
|
//
|
|
zc->z_cr3tab = NULL;
|
|
#endif // defined(DEADWOOD)
|
|
}
|
|
|
|
if (zc != NULL)
|
|
{
|
|
free(zc);
|
|
zc = NULL;
|
|
}
|
|
|
|
xferMsgClose(h);
|
|
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fputs("------- Ending Zmodem rcv -----\n", fpPacket);
|
|
fclose(fpPacket);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
|
|
return((USHORT)xstatus);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| getfree - Calculates the free bytes on the current file system.
|
|
| ~0 means many free bytes (unknown).
|
|
+----------------------------------------------------------------------*/
|
|
long getfree(void)
|
|
{
|
|
return(~0L); /* many free bytes ... */
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| tryz - Initialize for ZMODEM receive attempt, try to activate ZMODEM
|
|
| sender. Handles ZSINIT frame. Returns ZFILE if ZMODEM filename
|
|
| received, -1 on error, ZCOMPL if transaction finished, else 0.
|
|
+----------------------------------------------------------------------*/
|
|
int tryz(ZC *zc)
|
|
{
|
|
register int c;
|
|
register int n;
|
|
int x;
|
|
int retrys;
|
|
|
|
for ( n = 10; --n >= 0; )
|
|
{
|
|
/* Set buffer length (0) and capability flags */
|
|
stohdr(zc, 0L);
|
|
|
|
/* Do we need an option to set the block size ? */
|
|
|
|
zc->Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO /* |CANBRK */ ;
|
|
if (zc->Zctlesc)
|
|
zc->Txhdr[ZF0] |= TESCCTL;
|
|
if (n <= 8)
|
|
zc->do_init = TRUE;
|
|
if (zc->do_init)
|
|
zshhdr(zc, zc->tryzhdrtype, zc->Txhdr);
|
|
if (zc->tryzhdrtype == ZSKIP) /* Don't skip too far */
|
|
zc->tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
|
|
|
|
retrys = 25;
|
|
|
|
again:
|
|
|
|
switch (x = xfer_user_interrupt(zc->hSession))
|
|
{
|
|
case XFER_ABORT:
|
|
zmdmr_update(zc, ZCAN);
|
|
longjmp(zc->flagkey_buf, 1);
|
|
break;
|
|
|
|
case XFER_SKIP:
|
|
/* This MUST only happen while receiving */
|
|
stohdr(zc, zc->filesize);
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fputs("tryz: User skipped. ZRPOS\n", fpPacket);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
zshhdr(zc, ZRPOS, zc->Txhdr);
|
|
zc->nSkip = TRUE;
|
|
zc->file_bytes = zc->filesize;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (xfer_carrier_lost(zc->hSession))
|
|
{
|
|
zmdm_retval(zc, TRUE, ZCARRIER_LOST);
|
|
return ZCARRIER_LOST;
|
|
}
|
|
|
|
switch (zgethdr(zc, zc->Rxhdr, 'R'))
|
|
{
|
|
case ZRQINIT:
|
|
zc->do_init = TRUE;
|
|
continue;
|
|
case ZEOF:
|
|
zc->do_init = TRUE;
|
|
continue;
|
|
case TIMEOUT:
|
|
continue;
|
|
case ZFILE:
|
|
zc->zconv = zc->Rxhdr[ZF0];
|
|
zc->zmanag = zc->Rxhdr[ZF1];
|
|
zc->ztrans = zc->Rxhdr[ZF2];
|
|
zc->tryzhdrtype = ZRINIT;
|
|
c = zrdata(zc, zc->secbuf, 1024);
|
|
/* mode(3); TODO: figure out what this was supposed to do */
|
|
if (c == GOTCRCW)
|
|
return ZFILE;
|
|
if (--retrys <= 0)
|
|
{
|
|
zmdm_retval(zc, TRUE, ZNAK);
|
|
return ZNAK;
|
|
}
|
|
zshhdr(zc, ZNAK, zc->Txhdr);
|
|
goto again;
|
|
case ZSINIT:
|
|
zc->Zctlesc = TESCCTL & zc->Rxhdr[ZF0];
|
|
if (zrdata(zc, zc->Attn, ZATTNLEN) == GOTCRCW)
|
|
{
|
|
stohdr(zc, 1L);
|
|
zshhdr(zc, ZACK, zc->Txhdr);
|
|
goto again;
|
|
}
|
|
if (--retrys <= 0)
|
|
{
|
|
zmdm_retval(zc, TRUE, ZNAK);
|
|
return ZNAK;
|
|
}
|
|
zshhdr(zc, ZNAK, zc->Txhdr);
|
|
goto again;
|
|
case ZFREECNT:
|
|
stohdr(zc, getfree());
|
|
zshhdr(zc, ZACK, zc->Txhdr);
|
|
goto again;
|
|
case ZCOMMAND:
|
|
zmdm_retval(zc, TRUE, ZCOMMAND);
|
|
return ZCOMMAND;
|
|
case ZCOMPL:
|
|
goto again;
|
|
default:
|
|
zc->do_init = TRUE;
|
|
continue;
|
|
case ZFIN:
|
|
zc->xfertime = (long)interval(zc->xfertimer);
|
|
ackbibi(zc);
|
|
return ZCOMPL;
|
|
case ZCAN:
|
|
zmdm_retval(zc, TRUE, ZABORT);
|
|
return ZCAN;
|
|
}
|
|
}
|
|
zmdm_retval(zc, TRUE, TIMEOUT);
|
|
return TIMEOUT;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| rzfiles - Receive 1 or more files with ZMODEM protocol.
|
|
+----------------------------------------------------------------------*/
|
|
int rzfiles(ZC *zc)
|
|
{
|
|
register int c;
|
|
register int d;
|
|
|
|
for (;;)
|
|
{
|
|
switch (c = rzfile(zc))
|
|
{
|
|
case ZEOF:
|
|
case ZSKIP:
|
|
switch (d = tryz(zc))
|
|
{
|
|
case ZCOMPL:
|
|
return OK;
|
|
default:
|
|
return d;
|
|
case ZFILE:
|
|
break;
|
|
}
|
|
continue;
|
|
case ERROR:
|
|
default:
|
|
return c;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| rzfile - Receive single file with ZMODEM protocol.
|
|
| NOTE: Assumes file name frame is in secbuf.
|
|
+----------------------------------------------------------------------*/
|
|
int rzfile(ZC *zc)
|
|
{
|
|
register int c;
|
|
register int n;
|
|
int x;
|
|
int fBlocking = FALSE;
|
|
long lBlockStart = 0L;
|
|
|
|
zc->Eofseen = FALSE;
|
|
|
|
zc->file_bytes = 0L;
|
|
zc->real_bytes = 0L;
|
|
|
|
if (procheader(zc, (TCHAR *)zc->secbuf) == ERROR)
|
|
{
|
|
return (zc->tryzhdrtype = ZSKIP);
|
|
}
|
|
|
|
n = 20;
|
|
|
|
for (;;)
|
|
{
|
|
// If we're blocking and we've timed out, reset for another ZRPOS
|
|
if( fBlocking && (long)interval( lBlockStart ) > 100L )
|
|
fBlocking = FALSE;
|
|
|
|
// If we're not blocking already, set up for ZRPOS
|
|
if( ! fBlocking )
|
|
{
|
|
DbgOutStr( "Sending ZRPOS to %ld", zc->file_bytes, 0, 0, 0, 0 );
|
|
stohdr(zc, zc->file_bytes);
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fprintf(fpPacket, "rzfile: ZRPOS to %ld\n", zc->file_bytes);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
zshhdr(zc, ZRPOS, zc->Txhdr);
|
|
|
|
fBlocking = 1;
|
|
lBlockStart = (long)startinterval( );
|
|
DbgOutStr("Now blocked at t=%lu",lBlockStart,0,0,0,0);
|
|
}
|
|
nxthdr:
|
|
switch (x = xfer_user_interrupt(zc->hSession))
|
|
{
|
|
case XFER_ABORT:
|
|
zmdmr_update(zc, ZCAN);
|
|
longjmp(zc->flagkey_buf, 1);
|
|
break;
|
|
|
|
case XFER_SKIP:
|
|
/* This MUST only happen while receiving */
|
|
stohdr(zc, zc->filesize);
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fputs("rzfile: User skipped (1). ZRPOS\n", fpPacket);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
zshhdr(zc, ZRPOS, zc->Txhdr);
|
|
zc->nSkip = TRUE;
|
|
zc->file_bytes = zc->filesize;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (xfer_carrier_lost(zc->hSession))
|
|
{
|
|
zmdm_retval(zc, TRUE, ZCARRIER_LOST);
|
|
return ZCARRIER_LOST;
|
|
}
|
|
|
|
switch (c = zgethdr(zc, zc->Rxhdr, 'R'))
|
|
{
|
|
default:
|
|
if (--n < 0) /* A little fix from Delrina */
|
|
{
|
|
/* return ERROR; */
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zmdm_retval(zc, TRUE, c);
|
|
return c;
|
|
}
|
|
continue;
|
|
case ZCARRIER_LOST:
|
|
zmdm_retval(zc, TRUE, ZCARRIER_LOST);
|
|
return c;
|
|
case ZNAK:
|
|
case TIMEOUT:
|
|
if ( --n < 0)
|
|
{
|
|
/* return ERROR; */
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zmdm_retval(zc, TRUE, TIMEOUT);
|
|
return c;
|
|
}
|
|
continue; /* Another fix from Delrina */
|
|
case ZFILE:
|
|
if( fBlocking )
|
|
{
|
|
DbgOutStr( "rzfile: ZFILE && fBlocking!\n", 0, 0, 0, 0, 0 );
|
|
}
|
|
else
|
|
zrdata(zc, zc->secbuf, 1024);
|
|
continue;
|
|
case ZEOF:
|
|
if (rclhdr(zc->Rxhdr) != zc->file_bytes)
|
|
{
|
|
/*
|
|
* Ignore eof if it's at wrong place - force
|
|
* a timeout because the eof might have gone
|
|
* out before we sent our zrpos.
|
|
*/
|
|
goto nxthdr;
|
|
}
|
|
if (closeit(zc))
|
|
{
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zc->tryzhdrtype = ZFERR;
|
|
/* return ERROR; */
|
|
return ZEOF;
|
|
}
|
|
zmdmr_progress(zc, FILE_DONE);
|
|
|
|
return c;
|
|
case ERROR: /* Too much garbage in header search error */
|
|
if ( --n < 0)
|
|
{
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zmdm_retval(zc, TRUE, ERROR);
|
|
return ERROR;
|
|
}
|
|
if( ! fBlocking )
|
|
zmputs(zc, zc->Attn);
|
|
continue;
|
|
case ZSKIP:
|
|
closeit(zc);
|
|
zmdmr_progress(zc, FILE_DONE);
|
|
|
|
return c;
|
|
case ZDATA:
|
|
if( ! fBlocking )
|
|
{
|
|
if( rclhdr(zc->Rxhdr) != zc->file_bytes)
|
|
{
|
|
// DbgOutStr( "rzfile: ZDATA: n=%d\n", n, 0, 0, 0, 0 );
|
|
if ( --n < 0)
|
|
{
|
|
DbgOutStr("ZMODEM error %s %d", TEXT(__FILE__), __LINE__,0,0,0);
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fprintf(fpPacket, "rzfile: ZDATA pos = 0x%08lX vs. 0x%08lX\n",
|
|
rclhdr(zc->Rxhdr), zc->file_bytes);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
zmdm_retval(zc, TRUE, ZBADFMT);
|
|
return ERROR;
|
|
}
|
|
zmputs(zc, zc->Attn); continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Did sender finally respond to our ZRPOS?
|
|
if( rclhdr(zc->Rxhdr) == zc->file_bytes )
|
|
{
|
|
// DbgOutStr("Now unblocked after %lu t-sec\n",interval(lBlockStart),0,0,0,0);
|
|
fBlocking = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// Read the buffer and toss it
|
|
c = zrdata(zc, zc->secbuf, 1024);
|
|
continue;
|
|
}
|
|
}
|
|
moredata:
|
|
zmdmr_update(zc, ZDATA);
|
|
|
|
switch (x = xfer_user_interrupt(zc->hSession))
|
|
{
|
|
case XFER_ABORT:
|
|
zmdmr_update(zc, ZCAN);
|
|
longjmp(zc->flagkey_buf, 1);
|
|
break;
|
|
|
|
case XFER_SKIP:
|
|
/* This MUST only happen while receiving */
|
|
stohdr(zc, zc->filesize);
|
|
#if defined(DEBUG_DUMPPACKET)
|
|
fputs("rzfile: User skipped (2). ZRPOS\n", fpPacket);
|
|
#endif // defined(DEBUG_DUMPPACKET)
|
|
zshhdr(zc, ZRPOS, zc->Txhdr);
|
|
zc->nSkip = TRUE;
|
|
zc->file_bytes = zc->filesize;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (xfer_carrier_lost(zc->hSession))
|
|
{
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zmdm_retval(zc, TRUE, ZCARRIER_LOST);
|
|
return ZCARRIER_LOST;
|
|
}
|
|
|
|
switch (c = zrdata(zc, zc->secbuf, 1024))
|
|
{
|
|
case ZCAN:
|
|
zmdm_retval(zc, TRUE, ZABORT);
|
|
return c;
|
|
case ERROR: /* CRC error */
|
|
if ( --n < 0)
|
|
{
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zmdm_retval(zc, TRUE, ERROR);
|
|
return ERROR;
|
|
}
|
|
zmputs(zc, zc->Attn);
|
|
continue;
|
|
case TIMEOUT:
|
|
if ( --n < 0)
|
|
{
|
|
/* return ERROR; */
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
zmdm_retval(zc, TRUE, c);
|
|
return c;
|
|
}
|
|
continue;
|
|
case GOTCRCW:
|
|
n = 20;
|
|
putsec(zc, zc->secbuf, zc->Rxcount);
|
|
zc->file_bytes += zc->Rxcount;
|
|
zc->real_bytes += zc->Rxcount;
|
|
zmdmr_update(zc, ZMDM_ACKED);
|
|
zmdmr_progress(zc, 0);
|
|
stohdr(zc, zc->file_bytes);
|
|
zshhdr(zc, ZACK, zc->Txhdr);
|
|
sendline(zc, &zc->stP, XON);
|
|
goto nxthdr;
|
|
case GOTCRCQ:
|
|
n = 20;
|
|
putsec(zc, zc->secbuf, zc->Rxcount);
|
|
zc->file_bytes += zc->Rxcount;
|
|
zc->real_bytes += zc->Rxcount;
|
|
zmdmr_update(zc, ZMDM_ACKED);
|
|
zmdmr_progress(zc, 0);
|
|
stohdr(zc, zc->file_bytes);
|
|
zshhdr(zc, ZACK, zc->Txhdr);
|
|
goto moredata;
|
|
case GOTCRCG:
|
|
n = 20;
|
|
putsec(zc, zc->secbuf, zc->Rxcount);
|
|
zc->file_bytes += zc->Rxcount;
|
|
zc->real_bytes += zc->Rxcount;
|
|
zmdmr_progress(zc, 0);
|
|
goto moredata;
|
|
case GOTCRCE:
|
|
n = 20;
|
|
putsec(zc, zc->secbuf, zc->Rxcount);
|
|
zc->file_bytes += zc->Rxcount;
|
|
zc->real_bytes += zc->Rxcount;
|
|
zmdmr_progress(zc, 0);
|
|
goto nxthdr;
|
|
}
|
|
} /* switch */
|
|
} /* end for */
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| zmputs - Send a string to the modem, processing for \336 (sleep 1 sec)
|
|
| and \335 (break signal).
|
|
+----------------------------------------------------------------------*/
|
|
void zmputs(ZC *zc, char *s)
|
|
{
|
|
register c;
|
|
|
|
while (*s)
|
|
{
|
|
switch (c = *s++)
|
|
{
|
|
case '\336':
|
|
Sleep(1000);
|
|
continue;
|
|
case '\335':
|
|
/* TODO: put in a call to sendbreak */
|
|
// sendbreak(h);
|
|
continue;
|
|
default:
|
|
sendline(zc, &zc->stP, (UCHAR)c);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| IsAnyLower - Returns TRUE if string s has lower case letters.
|
|
+----------------------------------------------------------------------*/
|
|
int IsAnyLower(char *s)
|
|
{
|
|
for ( ; *s; ++s)
|
|
// Don't use this stuff in a Chicago DLL
|
|
// if (islower(*s))
|
|
if ((*s >= 'a') && (*s <= 'z'))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| closeit - Close the receive dataset, return OK or ERROR
|
|
+----------------------------------------------------------------------*/
|
|
int closeit(ZC *zc)
|
|
{
|
|
// struct utimbuf timep;
|
|
int reason;
|
|
XFR_PARAMS *pX;
|
|
|
|
reason = TSC_COMPLETE; /* TODO: Get the real reason */
|
|
if (zc->nSkip)
|
|
{
|
|
reason = TSC_USER_SKIP;
|
|
}
|
|
|
|
if (xfer_close_rcv_file(zc->hSession,
|
|
zc->fh,
|
|
reason,
|
|
zc->fname,
|
|
zc->our_fname,
|
|
zc->fSavePartial,
|
|
0,
|
|
0) == ERROR)
|
|
{
|
|
return ERROR;
|
|
}
|
|
zc->fh = NULL;
|
|
|
|
zc->actual_bytes += zc->real_bytes;
|
|
zc->real_bytes = 0L;
|
|
zc->total_bytes += zc->file_bytes;
|
|
zc->file_bytes = 0L;
|
|
zc->filesize = 0L;
|
|
|
|
zc->nSkip = FALSE;
|
|
|
|
pX = (XFR_PARAMS *)0;
|
|
xfrQueryParameters(sessQueryXferHdl(zc->hSession), (VOID **)&pX);
|
|
if ((pX != (XFR_PARAMS *)0) && (pX->fUseDateTime))
|
|
{
|
|
if (zc->Modtime)
|
|
{
|
|
// BYTE acName[FNAME_LEN];
|
|
// zc->Modtime += timezone; /* Convert from GMT to local timezone */
|
|
// timep.actime = time(NULL);
|
|
// timep.modtime = zc->Modtime;
|
|
// CharToOem(zc->our_fname, acName);
|
|
// utime(acName, (void FAR *)&timep);
|
|
itimeSetFileTime(zc->our_fname, zc->Modtime);
|
|
}
|
|
}
|
|
|
|
// Disable this, it needs conversion and we only ever got complaints
|
|
// about it anyway
|
|
//if ((zc->Filemode & S_IFMT) == S_IFREG)
|
|
// far_chmod(zc->our_fname, (07777 & zc->Filemode));
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| ackbibi - Ack a ZFIN packet, let byegones be byegones
|
|
+----------------------------------------------------------------------*/
|
|
void ackbibi(ZC *zc)
|
|
{
|
|
register int n;
|
|
|
|
stohdr(zc, 0L);
|
|
for (n = 3; --n >= 0; )
|
|
{
|
|
// purgeline(zc);
|
|
ComRcvBufrClear(zc->hCom);
|
|
zshhdr(zc, ZFIN, zc->Txhdr);
|
|
// switch (readline(h, 100))
|
|
switch (readline(zc, zc->Rxtimeout)) // Mobidem
|
|
{
|
|
case 'O':
|
|
// readline(h, 1); /* Discard 2nd 'O' */
|
|
readline(zc, zc->Rxtimeout); /* Discard 2nd 'O' */ // Mobidem
|
|
return;
|
|
case RCDO:
|
|
return;
|
|
case TIMEOUT:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| isvalid
|
|
+----------------------------------------------------------------------*/
|
|
int isvalid(char c, int base)
|
|
{
|
|
if (c < '0')
|
|
return FALSE;
|
|
switch (base)
|
|
{
|
|
case 8:
|
|
if (c > '7')
|
|
return FALSE;
|
|
break;
|
|
case 10:
|
|
if (c > '9')
|
|
return FALSE;
|
|
break;
|
|
case 16:
|
|
if (c <= '9')
|
|
return TRUE;
|
|
// Don't use this stuff in a Chicago DLL
|
|
// if (toupper(c) < 'A')
|
|
// return FALSE;
|
|
//if (toupper(c) > 'F')
|
|
// return FALSE;
|
|
if ((c >= 'a') && (c <= 'f'))
|
|
break;
|
|
if ((c >= 'A') && (c <= 'F'))
|
|
break;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| ourspace -- replacement for isspace
|
|
+----------------------------------------------------------------------*/
|
|
int ourspace(char c)
|
|
{
|
|
if (c == 0x20)
|
|
return TRUE;
|
|
if ((c >= 0x9) && (c <= 0xD))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| stoi - string to integer.
|
|
+----------------------------------------------------------------------*/
|
|
char *stoi(char *ptr, int *val, int base)
|
|
{
|
|
int cnt;
|
|
|
|
if (ptr == NULL)
|
|
return NULL;
|
|
// Don't do this in a Chicago DLL
|
|
// while ((*ptr) && (isspace(*ptr)))
|
|
while ((*ptr) && ourspace(*ptr))
|
|
ptr++;
|
|
cnt = 0;
|
|
while ((*ptr) && (isvalid(*ptr, base)))
|
|
{
|
|
cnt *= base;
|
|
cnt += (*ptr++ - '0');
|
|
}
|
|
*val = cnt;
|
|
return ptr;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| stol - string to long.
|
|
+----------------------------------------------------------------------*/
|
|
char *stol(char *ptr, long *val, int base)
|
|
{
|
|
long cnt;
|
|
|
|
if (ptr == NULL)
|
|
return NULL;
|
|
// Don't do this in a Chicago DLL
|
|
// while ((*ptr) && (isspace(*ptr)))
|
|
while ((*ptr) && (ourspace(*ptr)))
|
|
ptr++;
|
|
cnt = 0;
|
|
while ((*ptr) && (isvalid(*ptr, base)))
|
|
{
|
|
cnt *= base;
|
|
cnt += (*ptr++ - '0');
|
|
}
|
|
*val = cnt;
|
|
return ptr;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| procheader - Process incoming file information header.
|
|
+----------------------------------------------------------------------*/
|
|
int procheader(ZC *zc, TCHAR *name)
|
|
{
|
|
int zRecover = FALSE;
|
|
int lconv = 0;
|
|
int file_err;
|
|
register char *p;
|
|
int serial_number;
|
|
int files_remaining;
|
|
long bytes_remaining;
|
|
long our_size;
|
|
LONG lOptions = 0;
|
|
XFR_Z_PARAMS *pZ;
|
|
struct st_rcv_open stRcv;
|
|
TCHAR loc_fname[FNAME_LEN];
|
|
|
|
StrCharCopy(zc->fname, name);
|
|
|
|
#if !defined(NT_EDITION)
|
|
//
|
|
// Removed uppercasing the filename per MS request. REV: 11/12/2001
|
|
//
|
|
CharUpper(zc->fname);
|
|
#endif //!defined(NT_EDITION)
|
|
|
|
zc->Thisbinary = FALSE;
|
|
|
|
zc->filesize = 0L;
|
|
zc->Filemode = 0;
|
|
zc->Modtime = 0L;
|
|
serial_number = 0;
|
|
files_remaining = -1;
|
|
bytes_remaining = -1L;
|
|
|
|
p = name + 1 + StrCharGetByteCount(name);
|
|
if (*p)
|
|
{ /* file coming from Unix or DOS system */
|
|
if (*p)
|
|
p = stol(p, &zc->filesize, 10);
|
|
if (*p)
|
|
p = stol(p, &zc->Modtime, 8);
|
|
if (*p)
|
|
p = stoi(p, &zc->Filemode, 8);
|
|
if (*p)
|
|
p = stoi(p, &serial_number, 10);
|
|
if (*p)
|
|
p = stoi(p, &files_remaining, 10);
|
|
if (*p)
|
|
p = stol(p, &bytes_remaining, 10);
|
|
|
|
if ((zc->nfiles == 0) && (files_remaining != -1))
|
|
{
|
|
zc->nfiles = files_remaining;
|
|
zmdmr_filecnt (zc, zc->nfiles);
|
|
}
|
|
|
|
if ((zc->nbytes == (-1L)) && (bytes_remaining != (-1L)))
|
|
{
|
|
zc->nbytes = bytes_remaining;
|
|
zmdmr_totalsize (zc, zc->nbytes);
|
|
}
|
|
|
|
}
|
|
else
|
|
{ /* File coming from CP/M system */
|
|
for (p = zc->fname; *p; ++p) /* change / to _ */
|
|
if ( *p == '/')
|
|
*p = '_';
|
|
|
|
if ( *--p == '.') /* zap trailing period */
|
|
*p = 0;
|
|
}
|
|
|
|
StrCharCopy(zc->our_fname, zc->fname);
|
|
StrCharCopy(loc_fname, zc->fname);
|
|
|
|
stRcv.pszSuggestedName = loc_fname;
|
|
stRcv.pszActualName = zc->our_fname;
|
|
stRcv.lFileTime = zc->Modtime;
|
|
|
|
xfer_build_rcv_name(zc->hSession, &stRcv);
|
|
|
|
//zc->ssMch = stRcv.ssmchVscanHdl;
|
|
|
|
lconv = 0;
|
|
|
|
pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
|
|
assert(pZ);
|
|
|
|
if (pZ)
|
|
{
|
|
switch (pZ->nCrashRecRecv)
|
|
{
|
|
case ZP_CRR_ALWAYS:
|
|
lconv = ZCRECOV;
|
|
break;
|
|
case ZP_CRR_NEVER:
|
|
if ((lconv = zc->zconv) == ZCRECOV)
|
|
lconv = 0;
|
|
break;
|
|
case ZP_CRR_NEG:
|
|
default:
|
|
lconv = zc->zconv;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (lconv)
|
|
{
|
|
case ZCNL:
|
|
zc->Thisbinary = FALSE;
|
|
break;
|
|
case ZCRECOV:
|
|
/*
|
|
* This is a little complicated. To do recovery, we need to check
|
|
* the following:
|
|
* 1. Does the file exist on OUR side.
|
|
* 2. Has the sender sent over a file size.
|
|
* 3. Is the size sent greater than the size of OUR file.
|
|
* If so, we fudge around a little with the file and let things rip.
|
|
*/
|
|
zRecover = TRUE;
|
|
|
|
our_size = 0L;
|
|
if (zRecover)
|
|
{
|
|
if (GetFileSizeFromName(stRcv.pszActualName, &our_size))
|
|
zRecover = TRUE;
|
|
else
|
|
zRecover = FALSE;
|
|
}
|
|
|
|
if (zRecover)
|
|
{
|
|
/* Has the sender sent over a file size ? */
|
|
if (zc->filesize <= 0)
|
|
zRecover = FALSE;
|
|
}
|
|
|
|
if (zRecover)
|
|
{
|
|
/* This gets set up above after checking for existance */
|
|
if (our_size != 0L)
|
|
{
|
|
if (our_size < zc->filesize)
|
|
{
|
|
/*
|
|
* We do this in the vain hope of avoiding problems with
|
|
* files terminated by ^Z and padded last blocks
|
|
*
|
|
* Given that we don't know if it is necessary, it might be
|
|
* possible to eliminate it
|
|
*/
|
|
our_size = (our_size - 1) & ~255L;
|
|
}
|
|
else
|
|
{
|
|
return ERROR;
|
|
//zRecover = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zRecover = FALSE;
|
|
}
|
|
}
|
|
|
|
if (zRecover)
|
|
{
|
|
zc->file_bytes = our_size;
|
|
}
|
|
|
|
/* FALL THROUGH */
|
|
case ZCBIN:
|
|
default:
|
|
zc->Thisbinary = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (zRecover)
|
|
{
|
|
lOptions = XFR_RO_APPEND;
|
|
}
|
|
else if (pZ && pZ->nFileExists == ZP_FE_SENDER)
|
|
{
|
|
switch (zc->zmanag & ZMMASK)
|
|
{
|
|
case ZMNEWL:
|
|
/* TODO: complete this option */
|
|
lOptions = 0;
|
|
break;
|
|
case ZMCRC:
|
|
/* TODO: complete this option */
|
|
lOptions = 0;
|
|
break;
|
|
case ZMAPND:
|
|
lOptions = XFR_RO_APPEND;
|
|
break;
|
|
case ZMCLOB:
|
|
lOptions = XFR_RO_ALWAYS;
|
|
break;
|
|
case ZMNEW:
|
|
lOptions = XFR_RO_NEWER;
|
|
break;
|
|
case ZMDIFF:
|
|
/* TODO: complete this option */
|
|
lOptions = 0;
|
|
break;
|
|
case ZMPROT:
|
|
lOptions = XFR_RO_NEVER;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lOptions = zc->ulOverride;
|
|
}
|
|
|
|
StrCharCopy(zc->our_fname, zc->fname);
|
|
StrCharCopy(loc_fname, zc->fname);
|
|
|
|
stRcv.pszSuggestedName = loc_fname;
|
|
stRcv.pszActualName = zc->our_fname;
|
|
stRcv.lFileTime = zc->Modtime;
|
|
|
|
/* TODO: pick up override options as necessary, like above */
|
|
file_err = xfer_open_rcv_file(zc->hSession, &stRcv, lOptions);
|
|
|
|
if (file_err != 0)
|
|
{
|
|
DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
|
|
switch (file_err)
|
|
{
|
|
case -8:
|
|
zmdm_retval(zc, TRUE, ZMDM_INUSE);
|
|
break;
|
|
case -6: // File was rejected unconditionally
|
|
zmdm_retval(zc, TRUE, ZMDM_REFUSE);
|
|
break;
|
|
case -5: // Were unable to create needed directories
|
|
zmdm_retval(zc, TRUE, ZFERR);
|
|
break;
|
|
case -4: // No date, time supplied when required
|
|
zmdm_retval(zc, TRUE, ZFERR);
|
|
break;
|
|
case -3: // File could not be saved
|
|
zmdm_retval(zc, TRUE, ZFERR);
|
|
break;
|
|
case -2: // File was rejected due to date
|
|
zmdm_retval(zc, TRUE, ZMDM_OLDER);
|
|
break;
|
|
case -1: // Read/Write error occured
|
|
default:
|
|
zmdm_retval(zc, TRUE, ZFERR);
|
|
break;
|
|
}
|
|
|
|
zc->total_bytes += zc->filesize;
|
|
zc->filen += 1;
|
|
zmdmr_newfile (zc, zc->filen, zc->fname, stRcv.pszActualName);
|
|
return ERROR;
|
|
}
|
|
else
|
|
{
|
|
zmdm_retval(zc, TRUE, ZACK);
|
|
}
|
|
|
|
zc->fh = stRcv.bfHdl;
|
|
zc->basesize = stRcv.lInitialSize;
|
|
|
|
if (zRecover)
|
|
{
|
|
//jmh 04-02-96 Sure we opened it in "append" mode (which really
|
|
// opens the file for write and seeks to the end), but we
|
|
// might actually seek to a spot just before that due to the
|
|
// possible padding of the file with ^Z's.
|
|
//
|
|
fio_seek(zc->fh, zc->file_bytes, FIO_SEEK_SET);
|
|
}
|
|
|
|
zc->filen += 1;
|
|
|
|
zmdmr_newfile (zc, zc->filen, zc->fname, stRcv.pszActualName);
|
|
zmdmr_filesize(zc, zc->filesize);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------+
|
|
| putsec - Putsec writes the n characters of buf to receive file.
|
|
| If not in binary mode, carriage returns, and all characters
|
|
| starting with CPMEOF are discarded.
|
|
+----------------------------------------------------------------------*/
|
|
int putsec(ZC *zc, BYTE *buf, int n)
|
|
{
|
|
register BYTE *p;
|
|
register int ii;
|
|
|
|
if (n == 0)
|
|
return OK;
|
|
|
|
if (zc->Thisbinary)
|
|
{
|
|
// jkh, 2/11 Added error check
|
|
if (fio_write(buf, 1, n, zc->fh) != n)
|
|
longjmp(zc->flagkey_buf, 4);
|
|
}
|
|
else
|
|
{
|
|
if (zc->Eofseen)
|
|
return OK;
|
|
ii = FALSE;
|
|
for (p=buf; --n>=0; ++p )
|
|
{
|
|
if ( *p == '\n')
|
|
{
|
|
/*
|
|
* If we get a <NL> that wasn't preceeded by a <CR>
|
|
*/
|
|
if (ii == FALSE)
|
|
fio_putc('\r', zc->fh);
|
|
}
|
|
|
|
ii = (*p == '\r');
|
|
|
|
if (*p == CPMEOF)
|
|
{
|
|
zc->Eofseen=TRUE;
|
|
return OK;
|
|
}
|
|
fio_putc(*p, zc->fh);
|
|
}
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
/* *********** end of zmdm_rcv.c *********** */
|