windows-nt/Source/XPSP1/NT/shell/osshell/accesory/terminal/kermit.c

1117 lines
43 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*===========================================================================*/
/* Copyright (c) 1987 - 1988, Future Soft Engineering, Inc. */
/* Houston, Texas */
/*===========================================================================*/
#define NOLSTRING TRUE /* jtf win3 mod */
#include <windows.h>
#include "port1632.h"
#include "dcrc.h"
#include "dynacomm.h"
#include "task.h"
#include "kermit.h"
/*---------------------------------------------------------------------------*/
/* KER_Receive() - state table switcher for receiving files [rkh] */
/*---------------------------------------------------------------------------*/
BOOL FAR KER_Receive(BOOL bRemoteServer)
{
INT num, len;
BYTE bySaveState = KER_state;
KER_Init(KER_RCV);
if((KERRCVFLAG == KERSCREEN) || answerMode)
{
KER_n = 1;
KER_state = KER_FILE;
if(bySaveState == KER_TEXT) /* tge nova kermit ... */
{
KER_SndPacket(KER_ACK, KER_n, 0, 0); /* Return a ACK */
KER_state = KER_DATA;
}
}
else
{
flushRBuff();
}
while(TRUE)
{
if(xferStopped && (KER_state != KER_ABORT))
{
KER_RcvPacket(&len, &num, packet);
KER_Abort(STR_KER_RCVABORT);
return(FALSE);
}
if((KER_numtry++ > KER_MAXRETRY) && (KER_state != KER_ABORT))
{
KER_RcvPacket(&len, &num, packet);
KER_Abort(STR_KER_RETRYABORT);
return(FALSE);
}
rxEventLoop();
KER_bSetUp(KER_state);
switch(KER_state)
{
case KER_RCV: /* Receive-Init */
KER_state = KER_ReceiveInit();
break;
case KER_TEXT: /* Receive-Text */
case KER_FILE: /* Receive-File */
KER_state = KER_ReceiveFile();
break; /* Receive-Data */
case KER_DATA:
KER_state = KER_ReceiveData();
break;
case KER_CMPLT: /* Complete state */
delay((WORD) 60, NULL); /* tgex delay 1 sec for last packet */
return(TRUE);
case KER_ABORT: /* Abort state */
default:
delay((WORD) 60, NULL); /* tgex delay 1 sec for last packet */
return(FALSE);
}
} /* while */
}
/*---------------------------------------------------------------------------*/
/* KER_ReceiveInit() - receive initalization [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_ReceiveInit()
{
INT len, num; /* Packet length, number */
KER_parflg = KER_NOPARITY; /* tgex : let parity bits through from sender */
switch(KER_RcvPacket(&len, &num, packet)) /* Get a packet */
{
case KER_SEND: /* Send-Init */
if (KERRCVFLAG == KERFILE) /* set parity off of 'S' packet */
KER_parflg = KER_AutoPar();
KER_RcvPacketInit(packet); /* Get the other side's init data */
KER_SndPacketInit(packet); /* Fill up packet with my init info */
KER_SndPacket(KER_ACK, KER_n, 8, packet); /* ACK with my parameters */
KER_mask = 0xFF; /* set mask so checksum will include 8th bit if parity is used */
/* have to wait until after packet we send back has built
its checksum while ignoring possible parity bits that we
let thru in the first place to be able to check the parity */
KER_oldtry = KER_numtry; /* Save old try count */
KER_numtry = 0; /* Start a new counter */
KER_n = (KER_n+1) % 64; /* Bump packet number, mod 64 */
return(KER_FILE); /* Enter File-Receive state */
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(packet)); /* Print it out and */
case FALSE: /* Didn't get packet */
default:
flushRBuff();
showBErrors(++xferErrors);
KER_SndPacket(KER_NACK, KER_n, 0, 0); /* Return a NAK */
return(KER_state); /* Keep trying */
}
}
/*---------------------------------------------------------------------------*/
/* KER_ReceiveFile() - receive file header [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_ReceiveFile()
{
INT num, len;
BYTE filnam1[50];
OFSTRUCT dummy;
switch(KER_RcvPacket(&len, &num, packet)) /* Get a packet */
{
case KER_SEND: /* Send-Init, maybe our ACK lost */
if(KER_oldtry++ > KER_MAXRETRY) /* If too many tries abort */
return(KER_Abort(STR_KER_RETRYABORT));
if(num==((KER_n==0) ? 63 : KER_n-1))/* Previous packet, mod 64? */
{ /* Yes, ACK it again with */
KER_SndPacketInit(packet); /* our Send-Init parameters */
KER_SndPacket(KER_ACK, num, 8, packet);
showBErrors(++xferErrors);
KER_numtry = 0; /* Reset try counter */
return(KER_state); /* Stay in this state */
}
else /* Not previous packet, abort */
return(KER_Abort(STR_KER_BADPACKNUM));
case KER_EOF: /* End-Of-File */
if(KER_oldtry++ > KER_MAXRETRY) /* If too many tries abort */
return(KER_Abort(STR_KER_RETRYABORT));
if(num == ((KER_n==0) ? 63 : KER_n-1)) /* Previous packet, mod 64? */
{ /* Yes, ACK it again. */
KER_SndPacket(KER_ACK, num, 0, 0);
KER_numtry = 0;
showBErrors(++xferErrors);
return(KER_state); /* Stay in this state */
}
else /* Not previous packet, abort */
return(KER_Abort(STR_KER_BADPACKNUM));
case KER_TEXT:
case KER_FILE: /* File Header (just what we want) */
if(num != KER_n) /* The packet number must be right */
return(KER_Abort(STR_KER_BADPACKNUM));
if(!KER_firstfile)
return(KER_Abort(STR_KER_CREATEFILE));
KER_SndPacket(KER_ACK, KER_n, 0, 0);/* Acknowledge the file header */
KER_oldtry = KER_numtry; /* Reset try counters */
KER_numtry = 0;
KER_n = (KER_n+1) % 64; /* Bump packet number, mod 64 */
KER_bytes = 0l; /* don't have any bytes from file yet */
return(KER_DATA); /* Switch to Data state */
case KER_BREAK: /* Break transmission (EOT) */
if(num != KER_n) /* Need right packet number here */
return(KER_Abort(STR_KER_BADPACKNUM));
KER_SndPacket(KER_ACK, KER_n, 0, 0); /* Say OK */
return(KER_CMPLT); /* Go to complete state */
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(packet)); /* Print it out and */
case FALSE: /* Didn't get packet */
default:
flushRBuff();
KER_SndPacket(KER_NACK, KER_n, 0, 0); /* Return a NAK */
showBErrors(++xferErrors);
return(KER_state); /* Keep trying */
}
}
/*---------------------------------------------------------------------------*/
/* KER_ReceiveData() - receive data packets [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_ReceiveData()
{
INT num, len; /* Packet number, length */
switch(KER_RcvPacket(&len, &num, packet)) /* Get packet */
{
case KER_DATA: /* Got Data packet */
if(num != KER_n) /* Right packet? */
{ /* No */
if(KER_oldtry++ > KER_MAXRETRY) /* If too many tries abort */
return(KER_Abort(STR_KER_RETRYABORT));
if(num == ((KER_n==0) ? 63 : KER_n-1)) /* Else check packet number */
{ /* Previous packet again? */
flushRBuff();
KER_SndPacket(KER_ACK, num, 6, packet); /* Yes, re-ACK it */
KER_numtry = 0; /* Reset try counter */
showBErrors(++xferErrors);
return(KER_state); /* Don't write out data! */
}
else /* sorry, wrong number */
return(KER_Abort(STR_KER_BADPACKNUM));
}
/* Got data with right packet number */
KER_BufferEmpty(packet, len, KERRCVFLAG); /* Write the data to the file */
if(KERRCVFLAG != KERSCREEN)
showBBytes(KER_bytes, FALSE); /* mbbx 2.00: xfer ctrl */
KER_SndPacket(KER_ACK, KER_n, 0, 0); /* Acknowledge the packet */
KER_oldtry = KER_numtry; /* Reset the try counters */
KER_numtry = 0;
KER_n = (KER_n+1) % 64; /* Bump packet number, mod 64 */
return(KER_DATA); /* Remain in data state */
case KER_FILE: /* Got a File Header */
if(KER_oldtry++ > KER_MAXRETRY) /* If too many tries abort */
return(KER_Abort(STR_KER_RETRYABORT));
if(num == ((KER_n==0) ? 63:KER_n-1)) /* Else check packet number */
{ /* It was the previous one */
flushRBuff();
KER_SndPacket(KER_ACK, num, 0, 0); /* ACK it again */
KER_numtry = 0; /* Reset try counter */
showBErrors(++xferErrors);
return(KER_state); /* Stay in Data state */
}
else /* Not previous packet, abort */
return(KER_Abort(STR_KER_BADPACKNUM));
case KER_EOF: /* End-Of-File */
if(num != KER_n) /* Must have right packet number */
return(KER_Abort(STR_KER_BADPACKNUM));
KER_SndPacket(KER_ACK, KER_n, 0, 0); /* OK, ACK it. */
KER_firstfile = FALSE; /* we have got at least one complete file*/
_lclose(xferRefNo); /* Close the file */
KER_n = (KER_n+1)%64; /* Bump packet number */
return(KER_FILE); /* Go back to Receive File state */
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(packet)); /* Print it out and */
case FALSE: /* Didn't get packet */
default:
flushRBuff();
KER_SndPacket(KER_NACK, KER_n, 0, 0); /* Return a NAK */
showBErrors(++xferErrors);
return(KER_state); /* Keep trying */
}
}
/*---------------------------------------------------------------------------*/
/* KER_Send() - state table switcher for sending files [rkh] */
/*---------------------------------------------------------------------------*/
BOOL FAR KER_Send()
{
LONG dummy;
KER_Init(KER_SEND);
if(answerMode)
delay(100, &dummy); /* Sleep to give the guy a chance */
flushRBuff(); /* Flush pending input */
while(TRUE) /* Do this as long as necessary */
{
if(xferStopped && (KER_state != KER_ABORT))
{
KER_Abort(STR_KER_SNDABORT);
return(FALSE);
}
if((KER_numtry++ > KER_MAXRETRY) && (KER_state != KER_ABORT)) /* If too many tries, give up */
{
KER_Abort(STR_KER_RETRYABORT);
return(FALSE);
}
rxEventLoop();
KER_bSetUp(KER_state);
switch(KER_state)
{
case KER_SEND:
KER_state = KER_SendInit();
break;
case KER_FILE:
KER_state = KER_SendFile();
break;
case KER_DATA:
KER_state = KER_SendData();
break;
case KER_EOF:
case KER_BREAK:
KER_state = KER_SendGeneric(KER_state);
break;
case KER_CMPLT:
delay((WORD) 60, NULL); /* tgex delay 1 sec for last packet */
return(TRUE);
default:
KER_bSetUp('?');
/* fall through */
case KER_ABORT:
delay((WORD) 60, NULL); /* tgex delay 1 sec for last packet */
return(FALSE);
}
}
}
/*---------------------------------------------------------------------------*/
/* KER_SendInit() - send parameters to other side [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_SendInit()
{
INT num, len; /* Packet number, length */
LONG dummy;
KER_SndPacketInit(packet); /* Fill up init info packet */
KER_SndPacket(KER_SEND, KER_n, 8, packet);/* Send an S packet */
switch(KER_RcvPacket(&len, &num, recpkt)) /* What was the reply? */
{
case KER_RCV:
return(KER_state); /* remote get */
case KER_NACK:
flushRBuff();
showBErrors(++xferErrors);
return(KER_state); /* NAK, try it again */
case KER_ACK: /* ACK */
if(KER_n != num) /* If wrong ACK, stay in S state */
{
flushRBuff();
showBErrors(++xferErrors);
return(KER_state); /* and try again */
}
KER_RcvPacketInit(recpkt); /* Get other side's init info */
KER_eol = (KER_eol == 0) ? '\n' : KER_eol; /* Check and set defaults */
KER_quote = (KER_quote == 0) ? '#' : KER_quote;
KER_numtry = 0; /* Reset try counter */
KER_n = (KER_n+1) % 64; /* Bump packet count */
return(KER_FILE); /* OK, switch state to F */
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(recpkt)); /* Print it out and */
case FALSE:
default:
flushRBuff();
showBErrors(++xferErrors);
/* debug:rkh 60 ticks ??? */
delay(60,&dummy);
return(KER_state); /* Receive failure, try again */
}
}
/*---------------------------------------------------------------------------*/
/* KER_SendFile() -send the file header [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_SendFile()
{
INT num, len; /* Packet number, length */
BYTE filnam1[50], /* Converted file name */
*newfilnam, /* Pointer to file name to send */
*cp; /* BYTE pointer */
KER_SndPacket(KER_FILE, KER_n, (INT)*xferFname, xferFname+1); /* Send an F packet */
switch(KER_RcvPacket(&len, &num, recpkt)) /* What was the reply? */
{
case KER_NACK: /* NAK, just stay in this state, */
num = ((--num < 0) ? 63 : num); /* unless it's NAK for next packet */
if(KER_n != num) /* which is just like an ACK for */
{ /* this packet so fall thru to... */
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
/* fall through if nacking next packet
... we did not get last ACK, but they sent it */
case KER_ACK: /* ACK */
if(KER_n != num) /* If wrong ACK, stay in F state */
{
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
KER_numtry = 0; /* Reset try counter */
KER_n = (KER_n+1) % 64; /* Bump packet count */
KER_size = KER_BufferFill(packet); /* Get first data from file */
return(KER_DATA); /* Switch state to D */
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(recpkt)); /* Print it out and */
case FALSE: /* Receive failure, stay in F state */
default: /* Something else, just abort */
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
}
/*---------------------------------------------------------------------------*/
/* KER_SendData() -send the data packets [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_SendData()
{
INT num, len; /* Packet number, length */
KER_SndPacket(KER_DATA, KER_n, KER_size, packet); /* Send a D packet */
switch(KER_RcvPacket(&len, &num, recpkt)) /* What was the reply? */
{
case KER_NACK: /* NAK, just stay in this state, */
num = ((--num < 0) ? 63 : num); /* unless it's NAK for next packet */
if(KER_n != num) /* which is just like an ACK for */
{ /* this packet so fall thru to... */
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
/* fall through if nacking next packet
... we did not get last ACK, but they sent it */
case KER_ACK: /* ACK */
if(KER_n != num) /* If wrong ACK, fail */
{
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
updateProgress(FALSE);
updateTimer();
KER_numtry = 0; /* Reset try counter */
KER_n = (KER_n+1) % 64; /* Bump packet count */
if((KER_size = KER_BufferFill(packet)) == EOF) /* Get data from file */
return(KER_EOF); /* If EOF set state to that */
return(KER_DATA); /* Got data, stay in state D */
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(recpkt)); /* Print it out and */
case FALSE: /* Receive failure, stay in D */
default:
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
}
/*---------------------------------------------------------------------------*/
/* KER_SendGeneric() - [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_SendGeneric(BYTE lKER_state)
{
INT num, len;
KER_SndPacket(lKER_state, KER_n, 0, packet); /* Send a KER_EOF packet */
switch(KER_RcvPacket(&len, &num, recpkt)) /* What was the reply? */
{
case KER_NACK: /* NAK, just stay in this state, */
num = ((--num < 0) ? 63 : num); /* unless NAK for previous packet, */
if(KER_n != num) /* which is just like an ACK for */
{ /* this packet so fall thru to... */
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
/* fall through if nacking next packet
... we did not get last ACK, but they sent it */
case KER_ACK: /* ACK */
if(KER_n != num) /* If wrong ACK, hold out */
{
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
KER_numtry = 0; /* Reset try counter */
KER_n = (KER_n+1) % 64; /* and bump packet count */
switch(lKER_state)
{
case KER_EOF:
_lclose (xferRefNo); /* Close the input file */
xferRefNo = 0; /* Set flag indicating no file open */
if(!KER_GetNextFile()) /* No more files go? */
return(KER_BREAK); /* if not, break, EOT, all done */
return(KER_FILE); /* More files, switch state to F */
case KER_BREAK:
return(KER_CMPLT); /* Switch state to Complete */
}
case KER_ERROR: /* Error packet received */
return(KER_PrintErrPacket(recpkt)); /* Print it out and */
case FALSE: /* Receive failure, stay in Z */
default:
flushRBuff();
showBErrors(++xferErrors);
return(KER_state);
}
}
/*---------------------------------------------------------------------------*/
/*
* KERMIT utilities.
*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* KER_Init() initializes kermit variables [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_Init(BYTE state)
{
KER_eol = ((trmParams.emulate == ITMDELTA) && trmParams.localEcho) ? XOFF : CR;
/* mbbx 1.10: CUA */
/* EOL for outgoing packets (half duplex) */
/* EOL for outgoing packets */
KER_escchr = DEFESC; /* Default escape character */
KER_filnamcnv = DEFFNC; /* Default filename case conversion */
KER_firstfile = TRUE; /* First file transfer */
KER_image = DEFIM; /* Default image mode (TRUE) */
KER_lecho = KER_GetLocalEcho(); /* Get local echo info */
KER_n = 0; /* Initialize message number */
KER_numtry = 0; /* Say no tries yet */
KER_pad = 0; /* No padding */
KER_padchar = KER_PADCHAR; /* Use null if any padding wanted */
KER_pktdeb = FALSE; /* No packet file debugging */
KER_quote = '#'; /* Standard control-quote char */
KER_state = state; /* Receive-Init is the start state */
KER_timeout = FALSE; /* No timeout has occurred yet */
KER_timint = KER_SNDTIMEOUT; /* Start with default time outs. */
KER_turn = KER_GetTurnAroundTime(); /* Get turnaround info */
KER_8flag = FALSE; /* start with 8th bit quote flag off */
KER_parMask = 0; /* tgex used for auto parity */
KER_mask = 0xFF; /* used for checksumming with autoparity, to screen parity */
KER_initState = 0; /* tgex */
KER_select8 = '\0'; /* tgex set to illegal value, set later */
xferErrors = 0;
xferStopped = FALSE;
KER_parflg = KER_GetParity(); /* Get parity info -- before changed */
/* if we are sending, we need it. */
}
/*---------------------------------------------------------------------------*/
/* KER_GetParity() - get parity setting [rkh] */
/*---------------------------------------------------------------------------*/
INT NEAR KER_GetParity()
{
switch(trmParams.parity)
{
case ITMODDPARITY:
return(KER_ODDPARITY);
case ITMEVENPARITY:
return(KER_EVENPARITY);
case ITMMARKPARITY:
return(KER_MARKPARITY);
case ITMSPACEPARITY:
return(KER_SPACEPARITY);
case ITMNOPARITY:
default:
return(KER_NOPARITY);
}
}
/*---------------------------------------------------------------------------*/
/* KER_GetTurnAroundTime() - get turnaround parameter [rkh] */
/*---------------------------------------------------------------------------*/
INT NEAR KER_GetTurnAroundTime()
{
return(FALSE);
switch(trmParams.flowControl)
{
case ITMXONFLOW:
return (TRUE);
case ITMNOFLOW:
case ITMHARDFLOW:
default:
return (FALSE);
}
}
/*---------------------------------------------------------------------------*/
/* KER_GetLocalEcho() - get local echo parameter [rkh] */
/*---------------------------------------------------------------------------*/
INT NEAR KER_GetLocalEcho()
{
return(trmParams.localEcho); /* mbbx 1.10: CUA... */
}
/*---------------------------------------------------------------------------*/
/* KER_Abort() - Kermit abort transfer routine [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_Abort(WORD msgID)
{
LONG dummy;
LoadString(hInst, msgID, (LPSTR)taskState.string, 80); /* mbbx 1.04: REZ... */
KER_SndPacket(KER_ERROR, KER_n, strlen(taskState.string), taskState.string);
if(xferFlag == XFRBSND)
sndAbort();
else
rcvAbort();
delay(180, &dummy);
flushRBuff();
return(KER_ABORT);
}
/*---------------------------------------------------------------------------*/
/* KER_DoParity()- do parity on character ch [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_DoParity(BYTE ch)
{
INT a;
if (!KER_parflg) /* tgex: was masking out bit 8 */
return (ch);
ch &= 0177;
switch(KER_parflg)
{
case KER_ODDPARITY:
ch |= 0x80;
case KER_EVENPARITY:
a = (ch & 15) ^ ((ch >> 4) & 15);
a = (a & 3) ^ ((a >> 2) & 3);
a = (a & 1) ^ ((a >> 1) & 1);
return((ch & 0177) | (a << 7));
case KER_MARKPARITY: /* tgex ITMMARKPARITY: */
return(ch | 0x80);
case KER_SPACEPARITY: /* tgex ITMSPACEPARITY: */
return(ch & 0x7F);
default:
return(ch);
}
}
/*---------------------------------------------------------------------------*/
/* KER_SndPacket()- send a kermit packet [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_SndPacket(BYTE type, int num, int len, BYTE *data)
{
INT i; /* Character loop counter */
BYTE chksum, buffer[200]; /* Checksum, packet buffer */
register BYTE *bufp; /* Buffer pointer */
bufp = buffer; /* Set up buffer pointer */
for(i=1; i <= KER_pad; i++)
modemWr(KER_padchar); /* Issue any padding */
*bufp++ = KER_DoParity(CHSOH); /* Packet marker, ASCII 1 (SOH) */
*bufp++ = KER_DoParity(tochar(len+3)); /* Send the character count */
chksum = tochar(len+3) & KER_mask; /* Initialize the checksum */
*bufp++ = KER_DoParity(tochar(num)); /* Packet number */
chksum += tochar(num) & KER_mask; /* Update checksum */
*bufp++ = KER_DoParity(type); /* Packet type */
chksum += type & KER_mask; /* Update checksum */
for(i=0; i<len; i++) /* Loop for all data characters */
{
*bufp++ = KER_DoParity(data[i]); /* Get a character */
chksum += data[i] & KER_mask; /* Update checksum */
}
chksum = (((chksum & 0300) >> 6) + chksum) & 077; /* Compute final checksum */
*bufp++ = KER_DoParity(tochar(chksum)); /* Put it in the packet */
*bufp++ = KER_DoParity(KER_eol); /* Extra-packet line terminator */
modemWrite((LPSTR)buffer, (INT) (bufp - buffer)); /* mbbx 1.03: isolate comm... */
}
/*---------------------------------------------------------------------------*/
/* KER_RcvPacket()- read a kermit packet [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_RcvPacket(INT *len, INT *num, BYTE *data)
{
INT i, tries, done; /* Data character number, loop exit */
BYTE t, /* Current input character */
type, /* Packet type */
rchksum; /* Checksum received from other host */
BOOL resync;
tries = 0;
while(unpar(t = KER_InChar()) != CHSOH) /* Wait for packet header */
{
if(KER_timeout || xferStopped)
{
KER_timeout = FALSE;
return(FALSE);
}
}
done = FALSE; /* Got SOH, init loop */
while(!done) /* Loop to get a packet */
{
KER_parMask = t & 0x80; /* Get SOH parity bit */
KER_cchksum = 0; /* reset checksum */
if((t = unpar(KER_CInChar())) == CHSOH)
continue; /* Resynchronize if SOH */
*len = unchar(t)-3; /* Character count */
if((t = unpar(KER_CInChar())) == CHSOH)
continue; /* Resynchronize if SOH */
*num = unchar(t); /* Packet number */
if(unpar(t = KER_CInChar()) == CHSOH)
continue; /* Resynchronize if SOH */
type = unpar(t); /* Packet type */
KER_parMask |= (t & 0x80) >> 1; /* get packet type parity into bit 6 of KER_parMask */
/* Put len characters from the packet into the data buffer */
resync = FALSE;
for (i=0; i < *len; i++)
{
if((data[i] = KER_mask & (t = KER_CInChar())) == CHSOH) /* Resynch if SOH */
/* tgex ^ use KER_mask to get rid of parity bits in data of initial packet sent */
{
resync = TRUE;
break;
}
if(KER_timeout || xferStopped)
{
KER_timeout = FALSE;
return(FALSE);
}
}
if(resync)
continue;
data[*len] = 0; /* Mark the end of the data */
if((t = unpar(KER_InChar())) == CHSOH)
continue; /* Resynchronize if SOH */
rchksum = unchar(t); /* Convert to numeric */
done = TRUE; /* Got checksum, done */
}
/* Fold in bits 7,8 to compute */
KER_cchksum = (((KER_cchksum & 0300) >> 6) + KER_cchksum) & 077; /* final checksum */
if(KER_timeout || xferStopped)
{
KER_timeout = FALSE;
return(FALSE);
}
if(KER_cchksum != rchksum)
{
return(FALSE);
}
return(type); /* All OK, return packet type */
}
/*---------------------------------------------------------------------------*/
/* KER_CInChar() - get parity adjusted char and update checksum [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_CInChar()
{
BYTE ch;
ch = KER_InChar(); /* Get a character */
KER_cchksum += ch & KER_mask; /* Add to the checksum, drop parity bit if first packet */
return(ch);
}
/*---------------------------------------------------------------------------*/
/* KER_InChar()- get parity adjusted character [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_InChar()
{
BYTE ch;
ch = (BYTE)KER_ModemWait();
return((KER_parflg || KER_parMask) ? ch & 0x7F : ch);
}
/*---------------------------------------------------------------------------*/
/* KER_ModemWait() - [rkh] */
/*---------------------------------------------------------------------------*/
INT NEAR KER_ModemWait() /* mbbx 0.81 */
{
BYTE theChar;
if(!waitRcvChar(&theChar, (KER_timint * 10), 0, 0))
KER_timeout = TRUE; /* rjs */
return((INT) theChar);
}
/*---------------------------------------------------------------------------*/
/* KER_BufferFill() - fill up a buffer from file that is being sent [rkh] */
/*---------------------------------------------------------------------------*/
INT NEAR KER_BufferFill(BYTE *buffer)
{
INT i = 0; /* Loop index */
INT bytes = 0;
INT t; /* Char read from file */
BYTE t7; /* 7-bit version of above */
BYTE t8; /* 8-bit flag */
/* myh swat: if all chars in the buffer have been transfered */
if (KER_bytetran >= KER_buffsiz)
{
/* read in the next buffer from the file */
if ((KER_buffsiz = _lread(xferRefNo, KER_buffer, BUFFSIZE)) <= 0)
return(EOF);
/* reset the number of bytes transfered for next read in buffer */
else
KER_bytetran = 0;
} /* myh swat */
/* myh swat: continue to fill the packet until the full packet size */
/* or the end of the read buffer */
while ((i < KER_spsiz - 9) && (KER_bytetran < KER_buffsiz))
{
xferBytes--;
t = KER_buffer[KER_bytetran++]; /* myh swat: check one char at a time */
t7 = t & 0x7F; /* Get low order 7 bits */
t8 = t & 0x80;
if(KER_8flag && t8) /* do 8th bit quoting, this char */
{
buffer[i++] = KER_select8;
t = t7;
}
if((t7 < SP) || (t7 == DEL))
{
buffer[i++] = KER_quote;
t = ctl(t);
}
else if(t7 == KER_quote)
buffer[i++] = KER_quote;
else if(KER_8flag && (t7 == KER_select8))
buffer[i++] = KER_quote;
buffer[i++] = (BYTE)t;
}
buffer[i] = '\0';
return(i);
}
/*---------------------------------------------------------------------------*/
/* KER_BufferEmpty() - decode an incoming packet [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_BufferEmpty(BYTE *buffer, int len, BYTE flag)
{
INT i; /* Counter*/
INT KER_bufflen = 0; /* buffer length */
BYTE b8, t7, t; /* Character holder */
BYTE WriteBuffer[KER_MAXPACKSIZE]; /* myh swat: create a buffer so later can write */
/* the whole buffer instead of char by char */
for(i=0; i<len; i++) /* Loop thru the data field */
{
t = buffer[i]; /* Get character */
b8 = 0; /* 8th bit flag */
if(KER_8flag && (t == KER_select8))
{
b8 = 128;
t = buffer[++i];
}
if(t == KER_QUOTE) /* Control quote? */
{ /* Yes */
t = buffer[++i]; /* Get the quoted character */
t7 = t & 127;
if((t7 > 62) && (t7 < 96))
t = ctl(t);
}
t |= b8;
if((t == CR) && !KER_image) /* Don't pass CR if in image mode */
continue;
switch (flag)
{
case KERFILE:
WriteBuffer[KER_bufflen++] = t; /* myh swat: store char to a buffer */
KER_bytes++;
break;
case KERSCREEN:
modemInp(t, TRUE);
KER_bytes++;
break;
case KERBUFF:
KER_buff[KER_bufflen++] = t;
break;
}
}
/* myh swat: write the buffer to a file */
if (flag == KERFILE)
_lwrite(xferRefNo, WriteBuffer, KER_bufflen);
KER_buff[KER_bufflen] = 0;
}
/*---------------------------------------------------------------------------*/
/* KER_GetNextFile() - get next file in a file group [rkh] */
/*---------------------------------------------------------------------------*/
BOOL NEAR KER_GetNextFile()
{
return FALSE;
}
/*---------------------------------------------------------------------------*/
/* KER_PrintErrPacket() - print an error packet [rkh] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_PrintErrPacket(BYTE *msg)
{
if(!answerMode)
{
LoadString(hInst, STR_KER_XFERABORT, (LPSTR)taskState.string, 80); /* mbbx 1.04: REZ... */
sprintf(outstr, taskState.string, msg);
KER_PutScreenStr(outstr);
}
xferStopped = TRUE;
return(KER_ABORT); /* abort */
}
/*---------------------------------------------------------------------------*/
/* KER_RcvPacketInit() - get the initalization stuff from other side [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_RcvPacketInit(BYTE *data)
{
BYTE tmp;
/* rjs swat 011 -> unpar()'d each of the characters in data[] per Altitude fix */
KER_spsiz = unchar(unpar(data[0])); /* Maximum send packet size */
KER_timint = unchar(unpar(data[1])); /* When I should time out */
if(KER_timint == 0)
KER_timint = 32000; /* 32000 is close enough to infinite */
else if((KER_timint > KER_MAXTIMEOUT) || (KER_timint < KER_MINTIMEOUT))
KER_timint = (xferFlag == XFRBSND) ? KER_SNDTIMEOUT : KER_RCVTIMEOUT;
KER_pad = unchar(unpar(data[2])); /* Number of pads to send */
KER_padchar = ctl(unpar(data[3])); /* Padding character to send */
if(trmParams.emulate != ITMDELTA) /* (mbbx) for DELTA, send XOFF */
KER_eol = unchar(unpar(data[4])); /* EOL character I must send */
KER_quote = unpar(data[5]); /* Incoming data quote character */
/* tge comment: we need to check the packet length before the next section
to see if they even have the 8bit quote slot present */
tmp = unpar(data[6]);
if (KER_initState <= 0) /* tgex */
{ /* we are the receiver */
if(tmp == 'Y')
{
if (KER_parflg)
{
KER_select8 = '&';
KER_8flag = TRUE;
}
else
KER_select8 = 'N'; /* KER_8flag stays FALSE */
}
else if(tmp == 'N')
KER_select8 = 'N'; /* KER_8flag stays FALSE */
else if(((tmp > ' ') && (tmp < '?')) ||
((tmp > '_') && (tmp < DEL))) /* jtf 3.20 this was > DEL */
{
KER_select8 = tmp;
KER_8flag = TRUE;
}
}
else
{ /* we are the sender */
if (KER_select8 == '&')
{
if ((tmp == '&') || (tmp == 'Y'))
KER_8flag = TRUE;
}
else /* KER_select8 == 'Y' */
if(((tmp > ' ') && (tmp < '?')) ||
((tmp > '_') && (tmp < DEL))) /* jtf 3.20 this was > DEL */
{
KER_select8 = tmp;
KER_8flag = TRUE;
}
}
KER_initState = -1;
}
/*---------------------------------------------------------------------------*/
/* KER_SndPacketInit() - send the initalization stuff to other side [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_SndPacketInit(BYTE *data)
{
data[KER_INIT_MAXL] = tochar(KER_MAXPACKSIZE); /* Biggest packet I can receive */
data[KER_INIT_TIME] = /* When I want to be timed out */
(xferFlag == XFRBSND) ? tochar(KER_SNDTIMEOUT) : tochar(KER_RCVTIMEOUT);
data[KER_INIT_NPAD] = tochar(KER_NPAD); /* How much padding I need */
data[KER_INIT_PADC] = ctl(KER_PADCHAR); /* Padding character I want */
data[KER_INIT_EOL] = tochar(KER_EOL); /* End-Of-Line character I want */
data[KER_INIT_QCTL] = KER_QUOTE; /* Control-Quote character I send */
if (KER_initState >= 0)
{ /* we are the sender */
KER_select8 = (KER_parflg) ? '&' : 'Y';
}
else /* we are the receiver */
{
if (KER_select8 == 'Y') /* they sent us yes */
{
if (KER_parflg)
{
KER_select8 = '&';
KER_8flag = TRUE;
}
else
KER_select8 = 'N'; /* KER_8flag stays FALSE */
}
else /* they told us to quote */
if(((KER_select8 > ' ') && (KER_select8 < '?')) ||
((KER_select8 > '_') && (KER_select8 < DEL)))
{
KER_select8 = data[6];
KER_8flag = TRUE;
}
}
data[KER_INIT_QBIN] = KER_select8; /* 8th bit quote char */
data[KER_INIT_CHKT] = KER_BLOCKCHK1;
data[KER_INIT_CHKT+1] = '\0';
KER_initState = 1;
}
/*---------------------------------------------------------------------------*/
/* KER_PutScreenStr() - put data onto the screen [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_PutScreenStr(BYTE *data)
{
INT i;
#ifdef ORGCODE
for(i=0; i<strlen(data); i++)
#else
for(i=0; i< lstrlen(data); i++)
#endif
modemInp(data[i], FALSE);
modemInp(CR, FALSE);
modemInp(LF, FALSE);
}
/*---------------------------------------------------------------------------*/
/* KER_bSetUp() [rkh] */
/*---------------------------------------------------------------------------*/
VOID NEAR KER_bSetUp(BYTE state)
{
BYTE stateStr[2];
*stateStr = state;
stateStr[1] = 0;
}
/*---------------------------------------------------------------------------*/
/* KER_AutoPar() [tge] */
/*---------------------------------------------------------------------------*/
BYTE NEAR KER_AutoPar()
{
switch(KER_parMask)
{
case 0x80:
return(KER_EVENPARITY);
case 0xC0:
return(KER_MARKPARITY);
case 0x40:
return(KER_ODDPARITY);
case 0x00:
return(KER_NOPARITY);
default:
return(-1);
}
}