Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1156 lines
27 KiB

/* File: C:\WACKER\xfer\krm_rcv.c (Created: 28-Jan-1994)
* created from HAWIN source file
* krm_rcv.c -- Routines for handling file transmission using KERMIT
* file transfer protocol.
*
* Copyright 1989,1990,1991,1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 6 $
* $Date: 7/11/02 11:10a $
*/
#include <windows.h>
#pragma hdrstop
#include <time.h>
#include <stdlib.h>
#include <sys\types.h>
#include <sys\utime.h>
#include <term\res.h>
#include <tdll\stdtyp.h>
#include <tdll\mc.h>
#include <tdll\assert.h>
#include <tdll\load_res.h>
#include <tdll\xfer_msc.h>
#include <tdll\globals.h>
#include <tdll\file_io.h>
#include <tdll\session.h>
#include <tdll\htchar.h>
#if !defined(BYTE)
#define BYTE unsigned char
#endif
#include "cmprs.h"
#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 "krm.h"
#include "krm.hh"
// struct s_krm_rcv_control FAR *krc;
// metachar (NEAR *p_kputc)(metachar);
// long kbytes_received;
// #define DO_DATE(hS) ((xfer_flags(hS)&XF_USE_DATETIME)!=0L)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krm_rcv
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
int krm_rcv(HSESSION hS, int attended, int single_file)
{
ST_KRM *kc;
unsigned total_retries;
unsigned uabort_seq = 0;
int kr_state;
int iret;
kc = NULL;
kc = malloc(sizeof(*kc));
if (kc == NULL)
{
xferMsgClose(hS);
return TSC_NO_MEM;
}
kc->hSession = hS;
kc->hCom = sessQueryComHdl(hS);
kc->kbytes_received = 0;
krmGetParameters(kc);
kc->KrmProgress = kr_progress;
kc->fhdl = NULL;
kc->total_thru = 0L;
kc->its_maxl = 80;
kc->its_timeout = 10;
kc->its_npad = 0;
kc->its_padc = '\0';
kc->its_eol = '\r';
kc->its_chkt = 1;
kc->its_qctl = K_QCTL;
kc->its_qbin = '\0';
kc->its_rept = '\0';
kc->its_capat = FALSE;
kc->files_done = 0;
kc->xfertime = -1L;
kc->kr.files_received = kc->kr.files_aborted = 0;
kr_state = KREC_INIT;
kc->ksequence = 0;
kc->packetnum = 1;
kc->tries = total_retries = 0;
kc->kr.lasterr = KE_NOERROR;
kc->abort_code = KA_OK;
kc->kr.uabort_code = '\0';
kc->kr.data_packet_rcvd = FALSE;
kc->kr.dsptries = 0;
kc->kr.store_later = FALSE;
/* normally, the sender initiates a transfer, but if we're the terminal
* end of the transfer, we may be able to get the sender to start up
* without waiting for a timeout by sending a NAK packet as soon as we
* start up.
*/
ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
for ( ; ; )
{
xfer_idle(kc->hSession, XFER_IDLE_IO);
switch(kr_state)
{
case KREC_INIT:
kr_state = krec_init(kc);
if (kr_state == KREC_FILE)
{
/* clear init errors */
xferMsgErrorcnt(kc->hSession, total_retries = 0);
xferMsgLasterror(kc->hSession, 0);
}
break;
case KREC_FILE:
kc->kr.data_packet_rcvd = FALSE;
kc->kr.next_rtype = '\0'; /* init for krec_data routine */
kr_state = krec_file(kc);
if (!kc->tries && kr_state == KREC_DATA)
{
xferMsgNewfile(kc->hSession,
++kc->files_done,
kc->their_fname,
kc->our_fname);
}
break;
case KREC_DATA:
kr_state = krec_data(kc);
if ((kc->kr.uabort_code == 'Z') &&
(uabort_seq > (unsigned)(kc->packetnum + 3)))
kr_state = KREC_ABORT;
break;
case KREC_COMPLETE:
{
int kret;
kret = kresult_code[kc->abort_code];
free(kc);
kc = NULL;
xferMsgClose(hS);
return(kret);
}
/*lint -unreachable*/
break;
case KREC_ABORT:
{
int kret;
xferMsgLasterror(kc->hSession, kc->kr.lasterr);
if (kc->fhdl != NULL)
xfer_close_rcv_file(hS,
kc->fhdl,
kresult_code[kc->abort_code],
kc->their_fname,
kc->our_fname,
FALSE,
0L,
0);
kret = kresult_code[kc->abort_code];
free(kc);
kc = NULL;
xferMsgClose(hS);
return(kret);
}
/*lint -unreachable*/
break;
default:
assert(FALSE);
break;
}
xferMsgPacketErrcnt(kc->hSession,
kc->kr.dsptries ? kc->kr.dsptries : kc->tries);
if (kc->tries || kc->kr.dsptries)
{
xferMsgErrorcnt(kc->hSession, ++kc->total_retries);
xferMsgLasterror(kc->hSession, kc->kr.lasterr);
kc->kr.dsptries = 0;
}
else
xferMsgPacketnumber(kc->hSession, kc->packetnum);
/* check for keyboard abort */
if (iret = xfer_user_interrupt(kc->hSession))
{
if (iret == XFER_ABORT)
{
if (kc->kr.uabort_code) /* not the first time */
{
kc->abort_code = KA_IMMEDIATE;
kr_state = KREC_ABORT;
}
else /* start user abort process */
{
if (single_file)
kc->kr.uabort_code = 'Z';
else
kc->kr.uabort_code = 'X';
/* force it */
kc->kr.uabort_code = 'Z';
uabort_seq = kc->packetnum;
kc->abort_code = (kc->kr.uabort_code == 'X' ?
KA_LABORT1 : KA_LABORTALL);
}
}
else
{
if (kc->kr.uabort_code == 0)
{
kc->kr.uabort_code = 'X';
uabort_seq = kc->packetnum;
kc->abort_code = KA_LABORT1;
}
}
}
if (xfer_carrier_lost(kc->hSession))
{
kc->abort_code = KA_LOST_CARRIER;
kr_state = KREC_ABORT;
}
}
/*lint -unreachable*/
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krec_init
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
int krec_init(ST_KRM *kc)
{
int rtype;
int plen, rseq;
unsigned slen;
unsigned char packet[MAXPCKT];
unsigned char tchkt;
if (kc->tries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT ;
return(KREC_ABORT);
}
switch (rtype = krec_packet(kc, &plen, &rseq, packet))
{
case 'S':
kc->xfertime = (long)startinterval();
getparams(kc, FALSE, packet);
slen = (unsigned)buildparams(kc, FALSE, kc->kr.resp_pckt.pdata);
tchkt = kc->its_chkt;
kc->its_chkt = 1; /* response must use checktype 1 */
ksend_packet(kc, 'Y', slen, kc->ksequence, &kc->kr.resp_pckt);
kc->its_chkt = tchkt;
kc->kr.oldtries = kc->tries;
kc->tries = 0;
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
return(KREC_FILE);
/*lint -unreachable*/
break;
case 'T':
case BAD_PACKET:
kc->kr.lasterr = (rtype == 'T' ? KE_TIMEOUT : KE_BAD_PACKET);
ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
return(KREC_INIT); /* try again */
/*lint -unreachable*/
break;
case 'E':
kc->kr.lasterr = KE_RMTERR;
StrCharCopyN(kc->xtra_err, packet, MAXLINE);
kc->abort_code = KA_RMTERR;
return(KREC_ABORT);
/*lint -unreachable*/
break;
default:
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_BAD_FORMAT;
return(KREC_ABORT);
/*lint -unreachable*/
break;
}
/*lint -unreachable*/
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krec_file
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
int krec_file(ST_KRM *kc)
{
int rtype;
int plen, rseq;
unsigned slen;
int result;
unsigned char packet[MAXPCKT];
struct st_rcv_open stRcv;
// struct fn_parts fns;
// int disk;
if (kc->tries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT ;
return(KREC_ABORT);
}
rtype = krec_packet(kc, &plen, &rseq, packet);
if (kc->kr.store_later && (rtype != 'B' || rseq != kc->ksequence))
{
/* if kc->kr.store_later is TRUE, it means a file has been received
* but it hasn't been closed yet to allow us to come here and
* see if we should stop the transfer timer before closing and
* logging the file. If the transfer isn't over, take care of
* the last file.
*/
// bf_setcheck(NULL);
xfer_close_rcv_file(kc->hSession,
kc->fhdl,
TSC_OK,
kc->their_fname,
kc->our_fname,
FALSE,
kc->basesize + kc->kbytes_received,
kc->k_useattr ? kc->kr.ul_filetime : 0);
kc->kr.store_later = FALSE;
kc->total_thru += kc->kbytes_received;
kc->kbytes_received = 0;
}
switch (rtype)
{
case 'F':
if (rseq != kc->ksequence)
{
kc->kr.lasterr = KE_SEQUENCE;
kc->abort_code = KA_OUT_OF_SEQ;
return(KREC_ABORT);
}
StrCharCopyN(kc->their_fname, packet, MAXPCKT);
stRcv.pszSuggestedName = kc->their_fname;
stRcv.pszActualName = kc->our_fname;
kc->kr.ul_compare_time = 0;
xfer_build_rcv_name(kc->hSession, &stRcv);
result = xfer_open_rcv_file(kc->hSession, &stRcv, 0L);
if (result != 0)
{
unsigned char buffer[64];
LoadString(glblQueryDllHinst(),
IDS_TM_KRM_CANT_OPEN,
buffer, sizeof(buffer) / sizeof(TCHAR));
StrCharCopyN(kc->kr.resp_pckt.pdata, buffer, MAXPCKT);
ksend_packet(kc, 'E', StrCharGetByteCount(kc->kr.resp_pckt.pdata),
kc->ksequence,
&kc->kr.resp_pckt);
kc->kr.lasterr = KE_FATAL;
switch (result)
{
case -6:
kc->abort_code = KA_USER_REFUSED;
break;
case -5:
kc->abort_code = KA_CANT_OPEN;
break;
case -4:
kc->abort_code = KA_NO_FILETIME;
break;
case -3:
kc->abort_code = KA_TOO_MANY;
break;
case -2:
kc->abort_code = KA_OLDER_FILE;
break;
case -1:
default:
kc->abort_code = KA_DISK_ERROR;
break;
}
return(KREC_ABORT);
}
kc->fhdl = stRcv.bfHdl;
kc->basesize = stRcv.lInitialSize;
/* return our file name in Y packet */
StrCharCopyN(kc->kr.resp_pckt.pdata, kc->our_fname, MAXPCKT);
ksend_packet(kc, 'Y', StrCharGetByteCount(kc->our_fname), kc->ksequence,
&kc->kr.resp_pckt);
kc->kr.oldtries = kc->tries;
kc->tries = 0;
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
kc->kr.ul_filetime = 0; /* no date received yet */
kc->kr.size_known = FALSE;
kc->kbytes_received = 0L;
kc->p_kputc = kr_putc;
return(KREC_DATA);
/*lint -unreachable*/
break;
case 'B': /* end of batch */
if (rseq != kc->ksequence)
{
kc->kr.lasterr = KE_SEQUENCE;
kc->abort_code = KA_OUT_OF_SEQ;
return(KREC_ABORT);
}
ksend_packet(kc, 'Y', 0, kc->ksequence, &kc->kr.resp_pckt);
kc->xfertime = (long)interval(kc->xfertime);
kr_progress(kc, TRANSFER_DONE);
//hp_report_xtime((unsigned)(kc->xfertime / 10L));
if (kc->kr.store_later)
{
/* This stuff is here to allow us to stop the transfer timer
before spending time closing the last file and logging the
transfer.
*/
//bf_setcheck(NULL);
xfer_close_rcv_file(kc->hSession,
kc->fhdl,
TSC_OK,
kc->their_fname,
kc->our_fname,
FALSE,
kc->basesize + kc->kbytes_received,
kc->k_useattr ? kc->kr.ul_filetime : 0);
kc->kr.store_later = FALSE;
kc->total_thru += kc->kbytes_received;
kc->kbytes_received = 0;
}
kc->tries = 0;
return(KREC_COMPLETE);
/*lint -unreachable*/
break;
case 'S': /* received another send init packet, maybe they missed ACK */
if (kc->kr.oldtries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT ;
return(KREC_ABORT);
}
if (rseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
{
slen = (unsigned)buildparams(kc, FALSE, kc->kr.resp_pckt.pdata);
ksend_packet(kc, 'Y', slen, rseq, &kc->kr.resp_pckt);
kc->tries = 0;
kc->kr.dsptries = kc->kr.oldtries;
kc->kr.lasterr = KE_REPEAT;
return(KREC_FILE);
}
else
{
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_BAD_FORMAT;
return(KREC_ABORT);
}
/*lint -unreachable*/
break;
case 'Z':
if (kc->kr.oldtries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT ;
return(KREC_ABORT);
}
if (rseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
{
ksend_packet(kc, 'Y', 0, rseq, &kc->kr.resp_pckt);
kc->tries = 0;
kc->kr.dsptries = kc->kr.oldtries;
kc->kr.lasterr = KE_REPEAT;
return(KREC_FILE);
}
else
{
kc->abort_code = KA_BAD_FORMAT;
kc->kr.lasterr = KE_WRONG;
return(KREC_ABORT);
}
/*lint -unreachable*/
break;
case 'T':
case BAD_PACKET:
kc->kr.lasterr = (rtype == 'T' ? KE_TIMEOUT : KE_BAD_PACKET);
ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
return(KREC_FILE); /* try again */
/*lint -unreachable*/
break;
case 'E':
kc->kr.lasterr = KE_RMTERR;
StrCharCopyN(kc->xtra_err, packet, MAXLINE);
kc->abort_code = KA_RMTERR;
return(KREC_ABORT);
/*lint -unreachable*/
break;
default:
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_BAD_FORMAT;
return(KREC_ABORT);
/*lint -unreachable*/
break;
}
/*lint -unreachable*/
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krec_data
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
int krec_data(ST_KRM *kc)
{
int rtype;
int kplen, krseq;
unsigned char packet[MAXPCKT];
if (kc->tries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT;
return(KREC_ABORT);
}
if (kc->kr.next_rtype == '\0')
rtype = krec_packet(kc, &kplen, &krseq, packet);
else
{
rtype = kc->kr.next_rtype;
kplen = kc->kr.next_plen;
krseq = kc->kr.next_rseq;
MemCopy(packet, kc->kr.next_packet, (unsigned)MAXPCKT);
kc->kr.next_rtype = '\0';
}
switch (rtype)
{
case 'A': /* attribute packet */
case 'D': /* data packet */
if (krseq != kc->ksequence)
{
if (kc->kr.oldtries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT;
return(KREC_ABORT);
}
if (krseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
{
ksend_packet(kc, 'Y', 0, krseq, &kc->kr.resp_pckt);
kc->tries = 0;
kc->kr.dsptries = kc->kr.oldtries;
kc->kr.lasterr = KE_REPEAT;
return(KREC_DATA);
}
else
{
kc->abort_code = KA_OUT_OF_SEQ;
return(KREC_ABORT);
}
}
if (rtype == 'D')
{
/* got good data */
/* If the /N option is being used, and an older file is being
* received, a request was made to reject the file in the
* response to the attribute packet. If a data packet comes
* in anyway it means the sender failed to respond appropriately
* and we must abort the transfer.
*/
if (kc->kr.uabort_code == 'N')
{
kc->abort_code = KA_WONT_CANCEL;
return(KREC_ABORT);
}
/* If there is a compare_time still specified, it means the /N
* option was specified but the sender failed to include an
* attribute packet with a filetime. We must abort the transfer
*/
if (kc->kr.ul_compare_time != 0)
{
kc->abort_code = KA_NO_FILETIME;
return(KREC_ABORT);
}
/* check for pending kbd abort and inlcude 'Z' or 'X' in packet */
kc->kr.data_packet_rcvd = TRUE;
kc->kr.resp_pckt.pdata[0] = kc->kr.uabort_code;
ksend_packet(kc, 'Y', kc->kr.uabort_code ? 1 : 0, kc->ksequence,
&kc->kr.resp_pckt);
kr_progress(kc, 0);
if (kunload_packet(kc, kplen, packet) == ERROR)
{ /* storage file error */
kc->kr.lasterr = KE_FATAL;
kc->abort_code = KA_DISK_ERROR;
LoadString(glblQueryDllHinst(),
IDS_TM_KRM_CANT_WRITE,
kc->xtra_err, sizeof(kc->xtra_err) / sizeof(TCHAR));
/* we're already sent response to this packet, wait & send
error packet with next packet number */
Sleep((DWORD)1000);
StrCharCopyN(kc->kr.resp_pckt.pdata, kc->xtra_err, MAXPCKT);
ksend_packet(kc, 'E',
StrCharGetByteCount(kc->kr.resp_pckt.pdata),
(kc->ksequence + 1) % 64, &kc->kr.resp_pckt);
return(KREC_ABORT);
}
}
else if (rtype == 'A')
{
if (kc->kr.data_packet_rcvd) /* all 'A' packets must precede 'D' packets */
{
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_BAD_FORMAT;
return(KREC_ABORT);
}
// strblank(kc->kr.resp_pckt.pdata);
kc->kr.resp_pckt.pdata[0] = TEXT('\0');
kunload_attributes(kc, packet, &kc->kr.resp_pckt);
ksend_packet(kc, 'Y',
StrCharGetByteCount(kc->kr.resp_pckt.pdata),
kc->ksequence,
&kc->kr.resp_pckt);
}
kc->kr.oldtries = kc->tries;
kc->tries = 0;
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
return(KREC_DATA);
/*lint -unreachable*/
break;
case 'Z': /* end of file */
if (krseq != kc->ksequence)
{
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_OUT_OF_SEQ;
return(KREC_ABORT);
}
if (strcmp(packet, "D") == 0) /* discard file? */
{
if (!kc->kr.uabort_code)
kc->abort_code = KA_RABORT1;
xfer_close_rcv_file(kc->hSession,
kc->fhdl,
kresult_code[kc->abort_code],
kc->their_fname,
kc->our_fname,
FALSE,
0L,
kc->k_useattr ? kc->kr.ul_filetime : 0);
kc->total_thru += kc->kbytes_received;
kc->kbytes_received = 0;
++kc->kr.files_aborted;
}
else
{
/* file has been received */
kr_progress(kc, FILE_DONE);
++kc->kr.files_received;
/* if all is well, hold off on closing file and logging tranfer
* until after the next packet is in. This way we can stop the
* transfer timer earlier
*/
if (kc->abort_code == KA_OK)
kc->kr.store_later = TRUE;
else
{
xfer_close_rcv_file(kc->hSession,
kc->fhdl,
kresult_code[kc->abort_code],
kc->their_fname,
kc->our_fname,
FALSE,
kc->basesize + kc->kbytes_received,
kc->k_useattr ? kc->kr.ul_filetime : 0);
kc->total_thru += kc->kbytes_received;
kc->kbytes_received = 0;
}
}
ksend_packet(kc, 'Y', 0, kc->ksequence, &kc->kr.resp_pckt);
if (kc->kr.uabort_code == 'X' || kc->kr.uabort_code == 'N')
kc->kr.uabort_code = '\0', kc->abort_code = KA_OK;
kc->kr.oldtries = kc->tries;
kc->tries = 0;
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
return(KREC_FILE);
/*lint -unreachable*/
break;
case 'F': /* receiving file name again? */
if (kc->kr.oldtries++ > kc->k_retries)
{
kc->abort_code = KA_ERRLIMIT;
return(KREC_ABORT);
}
if (krseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
{
StrCharCopyN(kc->kr.resp_pckt.pdata, kc->our_fname, MAXPCKT);
ksend_packet(kc, 'Y',
StrCharGetByteCount(kc->our_fname),
krseq,
&kc->kr.resp_pckt);
kc->tries = 0;
kc->kr.lasterr = KE_REPEAT;
kc->kr.dsptries = kc->kr.oldtries;
return(KREC_DATA);
}
else
{
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_BAD_FORMAT;
return(KREC_ABORT);
}
/*lint -unreachable*/
break;
/* account for repeated 'X' packet here */
case 'T':
case BAD_PACKET:
kc->kr.lasterr = (rtype == 'T' ? KE_TIMEOUT : KE_BAD_PACKET);
ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
return(KREC_DATA); /* try again */
/*lint -unreachable*/
break;
case 'E':
kc->kr.lasterr = KE_RMTERR;
StrCharCopyN(kc->xtra_err, packet, MAXLINE);
kc->abort_code = KA_RMTERR;
return(KREC_ABORT);
/*lint -unreachable*/
break;
default:
kc->kr.lasterr = KE_WRONG;
kc->abort_code = KA_BAD_FORMAT;
return(KREC_ABORT);
/*lint -unreachable*/
break;
}
/*lint -unreachable*/
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* kr_progress
*
* DESCRIPTION:
* Displays transfer progress indicators for Kermit receive
*
* ARGUMENTS:
* final -- TRUE if final display for a file.
*
* RETURNS:
* nothing
*/
void kr_progress(ST_KRM *kc, int status)
{
long ttime, stime;
long bytes_rcvd;
long cps;
int k_rcvd;
long krm_stime = -1;
long krm_ttime = -1;
long krm_cps = -1;
long krm_file_so_far = -1;
long krm_total_so_far = -1;
if (kc->xfertime == -1L)
return;
ttime = bittest(status, TRANSFER_DONE) ?
kc->xfertime : (long)interval(kc->xfertime);
if ((stime = ttime / 10L) != kc->displayed_time ||
bittest(status, FILE_DONE | TRANSFER_DONE))
{
krm_stime = stime;
bytes_rcvd = kc->total_thru + kc->kbytes_received;
if (bittest(status, FILE_DONE | TRANSFER_DONE))
k_rcvd = (int)PART_HUNKS(bytes_rcvd, 1024);
else
k_rcvd = (int)FULL_HUNKS(bytes_rcvd, 1024);
krm_total_so_far = k_rcvd;
krm_file_so_far = kc->kbytes_received;
if (stime > 0 && (cps = (bytes_rcvd * 10L) / ttime) > 0)
{
krm_cps = cps;
if ((kc->kr.bytes_expected > 0))
{
ttime = (kc->kr.bytes_expected - kc->kbytes_received) / cps;
krm_ttime = ttime;
}
}
kc->displayed_time = stime;
}
xferMsgProgress(kc->hSession,
krm_stime,
krm_ttime,
krm_cps,
krm_file_so_far,
krm_total_so_far);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krm_rcheck
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
#if 0
void krm_rcheck(HSESSION hS, bool before)
{
if (before)
{
/* wait till next packet is in before writing to disk */
Dbg(krm_dbg, D_KRM_RCHECK);
kc->kr.next_rtype = krec_packet(hS, &kc->kr.next_plen, &kc->kr.next_rseq,
kc->kr.next_packet);
}
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krm_check_input
*
* DESCRIPTION:
*
* ARGUEMENTS:
*
* RETURNS:
*
*/
#if 0
void krm_check_input(bool suspend)
{
int disk;
struct fn_parts fns;
static USHORT old_ovr;
USHORT new_ovr;
if (suspend)
{
(VOID)mComGetErrors(comhdl, FALSE, NULL, &old_ovr, NULL, NULL);
}
else
{
(VOID)mComGetErrors(comhdl, FALSE, NULL, &new_ovr, NULL, NULL);
if (new_ovr > old_ovr)
{
/*
* Got an error. Make sure things are taken care of
* so that we don't get any more errors.
*/
if (kc->fhdl != NULL)
{
/* only do this if it might have been our file I/O */
bf_setcheck(NULL);
bf_setcheck(krm_rcheck);
fl_dissect_fn(bf_name(kc->fhdl), &fns);
disk = (fns.fn_drv[0] - 'A') & 0x1F;
transfer_setspeed(disk, cnfg.bit_rate);
}
}
}
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* kunload_attributes
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
void kunload_attributes(ST_KRM *kc, unsigned char *data, KPCKT *rsp_pckt)
{
unsigned char *limit = data + StrCharGetByteCount(data);
unsigned len;
unsigned char attrfield[20];
while (data <= limit - 2)
{
len = (unsigned char)unchar(data[1]);
if ((data + len + 1) >= limit)
break;
if (len <= sizeof(attrfield) - 1)
{
strncpy(attrfield, data + 2, len);
attrfield[len] = '\0';
switch (*data)
{
case '0':
break;
case '1':
/* This attribute gives an exact byte count of a file as it
* it was stored on the senders system. This is what we need
* to display a vu_meter etc. as the file is received
* (There is also a '!' field available that contains the
* filesize expressed in K. We don't currently use that
* field.
*/
if ((kc->kr.bytes_expected = atol(attrfield)) > 0)
{
kc->kr.size_known = TRUE;
xferMsgFilesize(kc->hSession, kc->kr.bytes_expected);
}
break;
case '#':
/* This field specifies the creation date of the file on the
* senders system, expressed as "[yy]yymmdd[ hh:mm[:ss]]".
* We use this for two things: If the user has asked us to use
* received attributes, we set the time/date of the new file
* based on this field. If the user specified the /N receive
* option, we compare this received file time with the filetime
* of any existing file of the same name and reject the file
* unless the incoming file is newer.
*/
/* extract date/time from the packet data field */
krm_settime(attrfield, &kc->kr.ul_filetime);
/* if kc->kr.compare_time contains a valid date/time, it means
* that the /N option was used and the file being received
* already exists. Compare the two times and reject any file
* that is not newer than what we already have.
*/
if (kc->kr.ul_compare_time != 0)
{
/* if incoming file (kc->kr.filetime) <= existing file
* (kc->kr.compare_time), reject the file
*/
if (kc->kr.ul_filetime <= kc->kr.ul_compare_time)
{
/* reject incoming file */
StrCharCopyN(rsp_pckt->pdata, "N#", MAXPCKT);
kc->kr.uabort_code = 'N';
kc->abort_code = KA_OLDER_FILE;
}
else
{
/* clear compare_time or transfer would fail when
* first data packet is received
*/
kc->kr.ul_compare_time = 0;
}
}
/* user may opt not to use received file time/date */
if (!kc->k_useattr)
kc->kr.ul_filetime = 0;
break;
default :
/* ignore */
break;
}
}
data += (len + 2);
}
}
#define atoc(c) ((c) - (CHAR)'0')
#define isadigit(x) ((x >= '0') && (x <= '9'))
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krm_settime
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
void krm_settime(unsigned char *data, unsigned long *ptime)
{
unsigned long ltime;
struct tm sT;
unsigned char *datestr = data;
unsigned char *timestr = NULL;
char ch;
int s;
unsigned i;
unsigned sl;
sT.tm_year = sT.tm_hour = -1;
if ((sl = StrCharGetByteCount(data)) > 7 && data[6] == ' ')
{
data[6] = '\0';
timestr = &data[7];
}
else if (sl > 9 && data[8] == ' ')
{
data[8] = '\0';
timestr = &data[9];
}
/* try to get date */
if ((sl = StrCharGetByteCount(datestr)) == 6 || sl == 8)
{
for (i = 0; i < sl; ++i)
if (!isadigit(datestr[i]))
break;
if (i == sl)
{
if (sl == 8)
{
ch = atoc(datestr[0]);
s = (int)ch;
sT.tm_year = s * 1000;
sT.tm_year += ((int)atoc(datestr[1]) * 100);
datestr += 2;
}
else
{
sT.tm_year = 1900;
}
sT.tm_year += (atoc(datestr[0]) * 10 + atoc(datestr[1]));
sT.tm_mon = atoc(datestr[2]) * 10 + atoc(datestr[3]);
sT.tm_mday = atoc(datestr[4]) * 10 + atoc(datestr[5]);
}
if (sT.tm_mon > 12 || sT.tm_mday > 31)
sT.tm_year = -1;
}
/* try to get a time */
if (timestr)
{
if (((sl = StrCharGetByteCount(timestr)) == 5 || (sl == 8 && timestr[5] == ':'))
&& timestr[2] == ':')
{
sT.tm_hour = atoc(timestr[0]) * 10 + atoc(timestr[1]);
sT.tm_min = atoc(timestr[3]) * 10 + atoc(timestr[4]);
if (sl == 8)
sT.tm_sec = atoc(timestr[6]) * 10 + atoc(timestr[7]);
else
sT.tm_sec = 0;
}
if (sT.tm_hour > 24 || sT.tm_min > 59 || sT.tm_sec > 59)
sT.tm_hour = -1;
}
if (sT.tm_year == -1 || sT.tm_hour == -1)
return;
sT.tm_year -= 1900;
ltime = (unsigned long)mktime(&sT);
ltime += itimeGetBasetime();
*ptime = ltime;
}
/*********************** end of krm_rcv.c ****************************/