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.
 
 
 
 
 
 

802 lines
18 KiB

/* File: C:\WACKER\xfer\krm_snd.c (Created: 28-Jan-1994)
* created from HAWIN source code
* krm_snd.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: 5 $
* $Date: 7/11/02 11:10a $
*/
// #define DEBUGSTR 1
#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>
#include <tdll\com.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"
// unsigned total_retries;
// metachar (NEAR *p_kgetc)(void);
// long kbytes_sent = 0L;
// KPCKT FAR * this_kpckt;
// KPCKT FAR * next_kpckt;
/* local funtion prototypes */
void build_attributes(ST_KRM *kc,
unsigned char *bufr,
long size,
unsigned long ul_time);
int ksend_init(ST_KRM *kc);
int ksend_break(ST_KRM *kc);
int ksend_file(ST_KRM *kc, long fsize);
int wldindexx(const char *string,
const char FAR *substr,
char wildcard,
int ic);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* krm_snd
*
* DESCRIPTION:
* send a file or files using kermit protocol
*
* This routine also handles logging of kermit sending operations to the
* optional log file.
*
* ARGUMENTS:
* attended -- TRUE if transfer is run manually, FALSE if run under automation
* such as in host or hyperpilot
* nfile -- number of files to be sent
* nbytes -- total number of bytes to be sent in all files
*
* RETURNS:
* Returns TRUE if all files are sent successfully or if all cancellations
* were user-requested, 'graceful' ones. Returns FALSE if an error occurs
* at either end of transfer or if user forces an immediate exit.
*/
int krm_snd(HSESSION hS, int attended, int nfiles, long nbytes)
{
ST_KRM *kc;
int result;
long sndsize;
unsigned long filetime;
long ttime;
kc = malloc(sizeof(ST_KRM));
if (kc == NULL)
{
xferMsgClose(hS);
return TSC_NO_MEM;
}
memset(kc, 0, sizeof(ST_KRM));
kc->hSession = hS;
kc->hCom = sessQueryComHdl(hS);
kc->kbytes_sent = 0L;
kc->this_kpckt = NULL;
kc->next_kpckt = NULL;
if (kc != NULL)
kc->this_kpckt = malloc(sizeof(KPCKT));
if (kc->this_kpckt != NULL)
kc->next_kpckt = malloc(sizeof(KPCKT));
if (kc->next_kpckt == NULL)
{
if (kc->this_kpckt != NULL)
{
free(kc->this_kpckt);
kc->this_kpckt = NULL;
}
if (kc != NULL)
{
free(kc);
kc = NULL;
}
xferMsgClose(hS);
return TSC_NO_MEM;
}
krmGetParameters(kc);
kc->KrmProgress = ks_progress;
kc->total_retries = 0;
xferMsgFilecnt(kc->hSession, nfiles);
xferMsgTotalsize(kc->hSession, nbytes);
kc->nbytes = nbytes;
kc->file_cnt = nfiles;
kc->files_done = 0;
kc->its_maxl = 80;
kc->its_timeout = 15;
kc->its_npad = 0;
kc->its_padc = '\0';
kc->its_eol = kc->k_eol;
kc->its_chkt = 1;
kc->its_qctl = K_QCTL;
kc->its_qbin = '\0';
kc->its_rept = '\0';
kc->its_capat = FALSE;
kc->ksequence = 0;
kc->packetnum = 1;
kc->abort_code = KA_OK;
kc->xfertime = -1L;
if (!ksend_init(kc))
{
int kret;
kret = kresult_code[kc->abort_code];
free(kc->this_kpckt);
kc->this_kpckt = NULL;
free(kc->next_kpckt);
kc->next_kpckt = NULL;
free(kc);
kc = NULL;
xferMsgClose(hS);
return(kret);
}
/* don't show init errors once transfer has started */
kc->total_dsp = kc->total_thru = 0L; /* new transfer starting */
while(xfer_nextfile(kc->hSession, kc->our_fname))
{
// xfer_idle(kc->hSession, XFER_IDLE_IO);
if (kc->abort_code == KA_LABORT1) /* TODO: figure this out */
kc->abort_code = KA_LABORTALL;
if (kc->abort_code >= KA_LABORTALL)
break;
kc->abort_code = KA_OK;
result = xfer_opensendfile(kc->hSession,
&kc->fhdl,
kc->our_fname,
&sndsize,
kc->their_fname,
&filetime);
if (result != 0)
{
kc->abort_code = KA_CANT_OPEN;
break;
}
if (kc->its_capat)
build_attributes(kc, kc->next_kpckt->pdata, sndsize, filetime);
ksend_file(kc, sndsize);
++kc->files_done;
if (kc->fhdl)
{
fio_close(kc->fhdl);
kc->fhdl = NULL;
}
/* log transfer status here based on kc->abort_code */
xfer_log_xfer(kc->hSession,
TRUE,
kc->our_fname,
NULL,
kresult_code[kc->abort_code]);
}
if (kc->abort_code < KA_IMMEDIATE)
ksend_break(kc);
ks_progress(kc, TRANSFER_DONE);
ttime = ((long)interval(kc->xfertime) / 10L);
result = kresult_code[kc->abort_code];
xferMsgClose(kc->hSession);
free(kc->this_kpckt);
kc->this_kpckt = NULL;
free(kc->next_kpckt);
kc->next_kpckt = NULL;
free(kc);
kc = NULL;
xferMsgClose(hS);
return(result);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* build_attributes
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
void build_attributes(ST_KRM *kc,
unsigned char *bufr,
long size,
unsigned long ul_time)
{
char str[15];
int sl;
struct tm *pt;
/* add file size in K */
wsprintf((LPSTR)str,
(LPSTR)"%d",
(int)(FULL_HUNKS(size, 1024)));
wsprintf((LPSTR)bufr,
(LPSTR)"!%c%s",
tochar(sl = (int)StrCharGetByteCount(str)),
(LPSTR)str);
bufr += (sl + 2);
/* add file size in bytes */
wsprintf((LPSTR)str,
(LPSTR)"%ld",
(ULONG)size);
wsprintf((LPSTR)bufr,
(LPSTR)"1%c%s",
tochar(sl = (int)StrCharGetByteCount(str)),
(LPSTR)str);
bufr += (sl + 2);
/* add file date and time */
ul_time += itimeGetBasetime(); /* Adjust to C7 and later */
pt = localtime((time_t*)&ul_time);
assert(pt);
if (pt)
{
/*
* Dimwitted thing sometimes returns 0
*/
wsprintf((LPSTR)bufr,
(LPSTR)"#%c%04d%02d%02d %02d:%02d:%02d",
tochar(17),
pt->tm_year + 1900,
pt->tm_mon + 1,
pt->tm_mday,
pt->tm_hour,
pt->tm_min,
pt->tm_sec);
bufr += 19;
}
/* system of origin */
StrCharCat(bufr, ".\"U8");
bufr += 4;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ksend_init
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
int ksend_init(ST_KRM *kc)
{
unsigned plen; /* length of outgoing packet data */
char rpacket[MAXPCKT]; /* space to receive response packet */
int rlen, rseq; /* length and sequence of response packet */
int tries = 0;
/* set init parameters as sender */
plen = (unsigned)buildparams(kc, TRUE, kc->this_kpckt->pdata);
xferMsgPacketnumber(kc->hSession, kc->packetnum);
while (tries < kc->k_retries)
{
// xfer_idle(kc->hSession, XFER_IDLE_IO);
xferMsgPacketErrcnt(kc->hSession, tries);
ksend_packet(kc, 'S', plen, kc->ksequence, kc->this_kpckt);
switch (krec_packet(kc, &rlen, &rseq, rpacket))
{
case 'Y':
if (rseq == kc->ksequence)
{
kc->xfertime = (long)startinterval();
getparams(kc, TRUE, rpacket);
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
return(TRUE);
}
/* fall through */
case 'N':
xferMsgLasterror(kc->hSession, KE_NAK);
++tries;
break;
case 'T':
xferMsgLasterror(kc->hSession, KE_TIMEOUT);
++tries;
break;
case BAD_PACKET:
if (xfer_user_interrupt(kc->hSession))
{
kc->abort_code = KA_IMMEDIATE;
return (FALSE);
}
if (xfer_carrier_lost(kc->hSession))
{
kc->abort_code = KA_LOST_CARRIER;
return (FALSE);
}
xferMsgLasterror(kc->hSession, KE_BAD_PACKET);
++tries;
break;
case 'E':
/* received error packet, abort transfer */
xferMsgLasterror(kc->hSession, KE_RMTERR);
strncpy(kc->xtra_err, rpacket, (unsigned)65);
kc->abort_code = KA_RMTERR;
return(FALSE);
/*lint -unreachable*/
break;
default:
/* unexpected packet type */
kc->abort_code = KA_BAD_FORMAT;
return(FALSE);
/*lint -unreachable*/
break;
}
}
/* error count has been exceeded */
kc->abort_code = KA_ERRLIMIT;
return(FALSE);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ksend_break
*
* DESCRIPTION:
* Send 'B' packet to indicate end of transaction
*
* ARGUMENTS:
* none
*
* RETURNS:
*
*/
int ksend_break(ST_KRM *kc)
{
char rpacket[MAXPCKT]; /* space to receive response packet */
int rlen, rseq; /* length and sequence of response packet */
int tries = 0;
while (tries < kc->k_retries)
{
// xfer_idle(kc->hSession, XFER_IDLE_IO);
ksend_packet(kc, 'B', 0, kc->ksequence, kc->this_kpckt);
switch (krec_packet(kc, &rlen, &rseq, rpacket))
{
case 'Y':
if (rseq == kc->ksequence)
{
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
return(TRUE);
}
/* fall through */
case 'N':
case 'T':
case BAD_PACKET:
if (xfer_user_interrupt(kc->hSession))
{
kc->abort_code = KA_IMMEDIATE;
return FALSE;
}
if (xfer_carrier_lost(kc->hSession))
{
kc->abort_code = KA_LOST_CARRIER;
return FALSE;
}
++tries;
break;
case 'E':
/* received error packet, abort transfer */
StrCharCopyN(kc->xtra_err, rpacket, MAXLINE);
kc->abort_code = KA_RMTERR;
return(FALSE);
/*lint -unreachable*/
break;
default:
/* unexpected packet type */
kc->abort_code = KA_BAD_FORMAT;
return(FALSE);
/*lint -unreachable*/
break;
}
}
/* error count has been exceeded */
kc->abort_code = KA_ERRLIMIT;
return(FALSE);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ksend_file
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
int ksend_file(ST_KRM *kc, long fsize)
{
int tries = 0;
int file_sent = FALSE;
int packet_sent = FALSE;
int kbd_abort = KA_OK;
char rtype;
int rlen, rseq;
char rpacket[MAXPCKT];
int sendattr;
KPCKT *tmp;
DbgOutStr("ksend_file %s\r\n", (LPSTR)kc->our_fname, 0,0,0,0);
xferMsgNewfile(kc->hSession,
kc->files_done + 1,
kc->our_fname,
kc->our_fname);
xferMsgFilesize(kc->hSession, fsize);
xferMsgPacketErrcnt(kc->hSession, 0);
xferMsgPacketnumber(kc->hSession, 0);
kc->p_kgetc = ks_getc;
kc->kbytes_sent = 0;
/* prepare file-header packet in this_kpckt */
kc->this_kpckt->ptype = 'F';
StrCharCopyN(kc->this_kpckt->pdata, kc->their_fname, MAXPCKT);
kc->this_kpckt->datalen = (int)StrCharGetByteCount(kc->this_kpckt->pdata);
sendattr = kc->its_capat &&
(size_t)StrCharGetByteCount(kc->next_kpckt->pdata) <= (size_t)(kc->its_maxl - 5);
while (!file_sent && kc->abort_code == KA_OK) /* for each packet */
{
// xfer_idle(kc->hSession, XFER_IDLE_IO);
tries = 0;
packet_sent = FALSE;
while (!packet_sent && tries++ < kc->k_retries && kc->abort_code == KA_OK)
{
// xfer_idle(kc->hSession, XFER_IDLE_IO);
if (kbd_abort != KA_OK && tries == 1)
{
kc->this_kpckt->ptype = 'Z';
kc->this_kpckt->datalen = 1;
StrCharCopyN(kc->this_kpckt->pdata, "D", MAXPCKT);
}
DbgOutStr("Calling ksend_packet %d %c (0x%x)",
tries, kc->this_kpckt->ptype, kc->this_kpckt->ptype, 0,0);
ksend_packet(kc, kc->this_kpckt->ptype,
(unsigned)kc->this_kpckt->datalen,
kc->ksequence, kc->this_kpckt);
if (xfer_carrier_lost(kc->hSession))
{
kc->abort_code = KA_LOST_CARRIER;
break;
}
if (tries == 1) /* first try for this packet */
{
xferMsgPacketnumber(kc->hSession, kc->packetnum);
if (fsize > 0)
ks_progress(kc, 0);
/* get next packet ready while first is being sent */
if (sendattr) /* data alreay prepared in next_kpckt */
{
kc->next_kpckt->datalen = (int)StrCharGetByteCount(kc->next_kpckt->pdata);
kc->next_kpckt->ptype = 'A';
sendattr = FALSE;
}
else if ((kc->next_kpckt->datalen =
kload_packet(kc, kc->next_kpckt->pdata)) == ERROR)
{
kc->next_kpckt->ptype = 'E';
kc->next_kpckt->datalen = (int)StrCharGetByteCount(kc->xtra_err);
StrCharCopyN(kc->next_kpckt->pdata, kc->xtra_err, MAXPCKT);
}
else
kc->next_kpckt->ptype = (char)(kc->next_kpckt->datalen ? 'D':'Z');
DbgOutStr(" next packet %c (0x%x)\r\n",
kc->next_kpckt->ptype, kc->next_kpckt->ptype, 0,0,0);
} /* end of if (tries == 1) */
else
{
xferMsgPacketErrcnt(kc->hSession, tries - 1);
xferMsgErrorcnt(kc->hSession, ++kc->total_retries);
DbgOutStr(" retry\r\n", 0,0,0,0,0);
}
rtype = (char)krec_packet(kc, &rlen, &rseq, rpacket);
if (rtype == 'N' && (--rseq < 0 ? 63 : rseq) == kc->ksequence)
rtype = 'Y';
DbgOutStr("called krec_packet %c (0x%x)\r\n", rtype, rtype, 0,0,0);
switch(rtype)
{
case 'Y':
if (rseq == kc->ksequence)
{
packet_sent = TRUE;
kc->ksequence = (kc->ksequence + 1) % 64;
++kc->packetnum;
if (kc->this_kpckt->ptype == 'A')/* response to attr pckt */
{
/* If receiver responded to an attribute packet with
* an 'N' in the data field, do not transfer the file.
*/
if (rlen > 0 && *rpacket == 'N')
kbd_abort = KA_RABORT1;
}
if (kc->this_kpckt->ptype == 'Z')/* have we sent last one?*/
{
file_sent = TRUE;
kc->abort_code = kbd_abort;
kbd_abort = KA_OK;
}
if (rlen == 1)
{
if (*rpacket == 'X')
kbd_abort = KA_RABORT1;
else if (*rpacket == 'Z')
kbd_abort = KA_RABORTALL;
}
tmp = kc->this_kpckt;
kc->this_kpckt = kc->next_kpckt;
kc->next_kpckt = tmp;
}
else
xferMsgLasterror(kc->hSession, KE_SEQUENCE);
break;
case 'N':
xferMsgLasterror(kc->hSession, KE_NAK);
break;
case BAD_PACKET:
xferMsgLasterror(kc->hSession, KE_BAD_PACKET);
break;
case 'T':
xferMsgLasterror(kc->hSession, KE_TIMEOUT);
break;
case 'E':
xferMsgLasterror(kc->hSession, KE_RMTERR);
StrCharCopyN(kc->xtra_err, rpacket, MAXLINE);
kc->abort_code = KA_RMTERR;
return(FALSE);
/*lint -unreachable*/
break;
default:
xferMsgLasterror(kc->hSession, KE_WRONG);
kc->abort_code = KA_BAD_FORMAT;
return(FALSE);
/*lint -unreachable*/
break;
}
if (xfer_user_interrupt(kc->hSession))
{
if (kbd_abort == KA_OK) /* first time */
{
kbd_abort = KA_LABORT1;
}
else
kc->abort_code = KA_IMMEDIATE;
}
if (xfer_carrier_lost(kc->hSession))
kc->abort_code = KA_LOST_CARRIER;
} /* end while (!packet_sent && etc.) */
xferMsgPacketErrcnt(kc->hSession, tries = 0);
if (kc->abort_code == KA_OK && !packet_sent) /* error count exceeded */
kc->abort_code = KA_ERRLIMIT;
} /* end while (!file_sent etc.) */
xferMsgPacketnumber(kc->hSession, kc->packetnum);
ks_progress(kc, FILE_DONE);
kc->total_dsp += fsize;
kc->total_thru += kc->kbytes_sent;
kc->kbytes_sent = 0;
return(file_sent);
} /* end ksend_file() */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ks_progress
*
* DESCRIPTION:
* Displays transfer progress indicators for Kermit Send
*
* ARGUMENTS:
* final -- TRUE if final display for a file.
*
* RETURNS:
* nothing
*/
void ks_progress(ST_KRM *kc, int status)
{
long ttime, stime;
long bytes_sent;
long cps;
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 = (long)interval(kc->xfertime);
if ((stime = ttime / 10L) != kc->displayed_time ||
bittest(status, FILE_DONE | TRANSFER_DONE))
{
/* Display elapsed time */
krm_stime = stime;
/* Display amount transferred */
bytes_sent = kc->total_dsp + kc->kbytes_sent;
krm_file_so_far = kc->kbytes_sent;
krm_total_so_far = bytes_sent;
/* Display throughput and est. time to completion */
if ((stime > 2 ||
ttime > 0 && bittest(status, FILE_DONE | TRANSFER_DONE)) &&
(cps = ((kc->total_thru + kc->kbytes_sent) * 10L) / ttime) > 0)
{
krm_cps = cps;
if ((kc->nbytes > 0))
{
ttime = ((kc->nbytes - bytes_sent) / cps) +
kc->file_cnt - kc->files_done;
krm_ttime = ttime;
}
}
kc->displayed_time = stime;
}
xferMsgProgress(kc->hSession,
krm_stime,
krm_ttime,
krm_cps,
krm_file_so_far,
krm_total_so_far);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define toupper(x) ((x)-'a'+'A')
int wldindexx(const char *string,
const char *substr,
char wildcard,
int ic)
/* ic - ignore case */
{
short index, limit;
const char *s;
const char *ss;
if (*substr == '\0')
return(0);
index = 0;
limit = (short)StrCharGetByteCount(string) - (short)StrCharGetByteCount(substr);
while (index <= limit)
{
s = &string[index];
ss = substr;
while (*ss == wildcard || *s == *ss || (ic && isascii(*s)
&& isascii(*ss) && toupper(*s) == toupper(*ss)))
{
++s;
if (*++ss == '\0')
return(index);
}
++index;
}
return(-1);
}
/********************* end of krm_snd.c ********************/