home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
sinclairqla.tar.gz
/
sinclairqla.tar
/
qlkfns.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-05-08
|
17KB
|
432 lines
/*
FNS_C - QL-Kermit protocol functions
Based on ckcfns.c, (C) Columbia University
*/
/* Include files */
#include "ram1_ker_h" /* Kermit definitions */
/* External variables */
extern int slen; /* Maximum send packet size */
extern int rlen; /* Maximum receive packet size */
extern int tslen; /* Send packet size in use */
extern int stmo; /* Timeout remote is to use */
extern int rtmo; /* Timeout we will use */
extern int n; /* Packet number */
extern int ttyfd; /* FD of TTY for I/O, 0 if remote */
extern int ttychid; /* Channel ID for ttyfd */
extern int tvalue; /* Current timeout value */
extern int debug; /* Level of debugging output */
extern int parity; /* Current parity setting */
extern int npad; /* Amount of padding remote needs */
extern int tnpad; /* Padding count in use */
extern int xfertyp; /* File transfer mode */
extern long filein; /* File bytes received */
extern long fileout; /* File bytes sent */
extern long totin; /* Total bytes received */
extern long totout; /* Total bytes sent */
extern bool timer; /* Timer enabled */
extern bool cxseen; /* File interruption flag */
extern bool czseen; /* Group interruption flag */
extern bool toscr; /* Screen data flag */
extern bool ebqflg; /* 8-bit quoting being done */
extern char ssop; /* SOP remote needs */
extern char rsop; /* SOP I need */
extern char seol; /* EOL for sending packets */
extern char reol; /* EOL for receiving packets */
extern char tseol; /* Sending EOL in use */
extern char quote; /* Sending control quote */
extern char pebq; /* 8-bit quote prefix */
extern char tquote; /* Receiving control quote */
extern char ebq; /* 8-bit quote in use */
extern unsigned char padch; /* Pad character remote needs */
extern unsigned char tpadc; /* Pad character in use */
extern char *ttyname; /* Name of TTY for transfer */
extern int fp; /* Local file for data transfer */
extern int _oserr; /* QDOS error code */
extern int oserr; /* Copy of above */
extern bool warn8; /* Lost 8th bit warning given */
extern int state; /* Current switcher state */
/* External functions */
extern bool chkquote(); /* Check for valid quote character */
extern bool tfput(); /* Put a byte to transfer file */
extern int tfget(); /* Get a byte from transfer file */
/* Local variables */
static int length; /* Length of last packet read */
/* TINIT - Initialise transaction */
tinit()
{
tseol = seol; /* Initialise sending EOL, */
tslen = slen; /* packet length */
tvalue = 50*rtmo; /* and timeout */
czseen = FALSE; /* Clear interrupt flags */
cxseen = FALSE;
tnpad = npad; /* Initialise padding */
tpadc = padch;
tquote = quote; /* and quote characters */
ebq = 0;
ebqflg = FALSE; /* Reset 8-bit quote flag */
totin = totout = 0; /* Clear character counts */
}
/* SPACK - Send a packet */
spack(type,num,len,data)
char type;
int num,len;
char *data;
{
int i; /* Character loop counter */
char chksum; /* Checksum */
char buffer[110]; /* Packet buffer */
char *bufp; /* Buffer pointer */
if (debfull) /* Display outgoing packet? */
{
if (data!=NULL) data[len] = '\0'; /* Null-terminate data for printing */
printf("spack: type=%c, num=%d, len=%d\n",type,num,len);
if (data!=NULL) printf(" data=\"%s\"\n",data);
}
bufp = buffer; /* Set up buffer pointer */
*bufp++ = ssop; /* Packet marker (SOH) */
chksum = *bufp++ = tochar(len+3); /* Character count */
*bufp++ = tochar(num); /* Packet number */
chksum += tochar(num); /* Update checksum */
*bufp++ = type; /* Packet type */
chksum += type; /* Update checksum */
for (i=0; i<len; i++) /* Loop for all data characters */
{
*bufp++ = data[i]; /* Put a character */
chksum += data[i]; /* Update checksum */
}
chksum = (((chksum&0300)>>6)+chksum)&077; /* Compute final checksum */
*bufp++ = tochar(chksum); /* Put it in the packet */
*bufp = tseol; /* Add packet line terminator */
write(ttyfd,buffer,bufp-buffer+1); /* and send the packet */
for (i = 0; i<tnpad; i++)
write(ttyfd,&tpadc,1); /* Put out any padding needed */
}
/* RPACK - Read a packet */
int rpack(len,num,data)
int *len,*num;
char *data;
{
int i; /* Loop counter */
bool done; /* Loop exit */
char type; /* Packet type */
int t; /* Current input character */
char ccsum; /* Our (computed) checksum */
char rcsum; /* Checksum received from host */
done = FALSE; /* Start to look for a packet */
do
{
if ((t = tread())<0) return(t); /* Error */
} while (t!=rsop); /* Look for start of packet */
while (!done) /* Got SOP, loop to get packet */
{
if ((t = tread())<0) return(t); /* Error */
if (t==rsop) continue; /* Aborted packet */
ccsum = t; /* Start the checksum */
*len = unchar(t)-3; /* Character count */
if ((t = tread())<0) return(t); /* Error */
if (t==rsop) continue; /* Aborted packet */
ccsum += t; /* Update checksum */
*num = unchar(t); /* Packet number */
if ((t = tread())<0) return(t); /* Error */
if (t==rsop) continue; /* Aborted packet */
ccsum += t; /* Update checksum */
type = t; /* Packet type */
for (i=0; i<*len; i++) /* Loop for data */
{
if ((t = tread())<0) return(t); /* Error */
if (t==rsop) goto xx; /* Aborted packet */
ccsum += t; /* Update checksum */
data[i] = t; /* Put it in the data buffer */
}
data[*len] = '\0'; /* Mark the end of the data */
if ((t = tread())<0) return(t); /* Error */
xx: if (t==rsop) continue; /* Aborted packet */
rcsum = unchar(t); /* Convert checksum to numeric */
done = TRUE; /* Got checksum, done */
length = *len; /* Save length for rpar() */
}
if (debfull) /* Display incoming packet */
{
if (data!=NULL) data[*len] = '\0'; /* Null-terminate data for printing */
printf("rpack type: %c, num: %d, len: %d\n",type,*num,*len);
if (data!=NULL) printf(" data: \"%s\"\n",data);
}
/* Fold in bits 7,8 to */
ccsum = (((ccsum&0300)>>6)+ccsum)&077; /* compute final checksum */
if (ccsum!=rcsum) /* Checksum correct? */
{
if (debon) printf("Received bad checksum\n");
return(BAD);
}
return((int) type); /* All OK, return packet type */
}
/* BUFILL - Get a bufferful of data from the file that's being sent and
encode it for transmission.
*/
int bufill(buff)
char buff[];
{
int i; /* Loop index */
char t; /* Character read from file */
int tt; /* For testing EOF */
int a7,b8; /* Split-up versions of above */
i = 0; /* Set up data buffer pointer */
while ((tt = tfget())!=EOF) /* Get the next character */
{
fileout++; /* Count it */
t = (char) tt;
a7 = t&0177; /* Get lower 7 bits */
b8 = t&0200; /* and 8th bit */
if (a7!=t && !warn8 && !ebqflg && parity!=PYNONE)
{ /* Check for data loss */
printf("Warning: 8th bits lost\n");
warn8 = TRUE;
}
if (ebqflg && b8!=0) /* EBQ required? */
{
buff[i++] = ebq; /* Yes, put out prefix */
t = a7; /* and work on 7-bit character */
}
if (a7<SP || a7==DEL) /* Control quote required? */
{
buff[i++] = quote; /* Yes, output prefix */
if (t==LF && xfertyp==FTASC) /* EOL in ASCII mode */
{
buff[i++] = 'M'; /* Standard Kermit EOL sequence */
buff[i++] = quote;
t = 'J';
}
else t = ctl(t); /* Uncontrollify */
}
if (a7==quote || (a7==ebq && ebqflg))
{
buff[i++] = quote; /* Quote control prefix or EBQ */
}
buff[i++] = t; /* Finally output the character */
if (i>=tslen-9) return(i); /* Conservative length check */
}
if (i==0) return(EOF); /* Here only on EOF */
return(i); /* Handle partial buffer */
}
/* BUFEMP - Put data from an incoming packet into a file */
bool bufemp(buff,len)
char buff[];
int len;
{
int i; /* Counter */
char t; /* Character holder */
int a,a7,b8; /* Component parts of above */
char fbuf[MAXPACK]; /* File data buffer */
int fbufp = 0; /* Index into above */
for (i=0; i<len; i++) /* Loop through the data */
{
a = buff[i]; /* Get character */
b8 = 0; /* Clear high bit flag */
if (ebqflg && a==ebq) /* An 8-bit prefixed sequence? */
{
b8 = 0200; /* Set 8th bit for later */
a = buff[++i]; /* and get prefixed character */
}
if (a==tquote) /* Control quote? */
{
a = buff[++i]; /* Yes, get what it prefixes */
a7 = a&0177; /* Split off lower 7 bits */
if ((a7>=0100 && a7<=0137) || a7=='?')
a = ctl(a); /* Uncontrollify */
}
t = (char) a | b8; /* Add in 8th bit */
if (toscr && t!=CR) putch(t); /* Screen output */
else if (!(t==CR && xfertyp==FTASC)) /* File output */
fbuf[fbufp++] = t;
filein++; /* Count the character */
}
if (!toscr) /* File output */
{
if (write(fp,fbuf,fbufp)!=fbufp) /* Write to file */
{
oserr = _oserr; /* Save error code */
return(FALSE);
}
}
else if (n==1) putch('\n'); /* Set screen for DO results */
return(TRUE);
}
/* SPAR - Fill the data array with my Send-Init parameters */
int spar(data)
char data[];
{
data[0] = tochar(rlen); /* Biggest packet I can receive */
data[1] = tochar(stmo); /* When I want to be timed out */
data[2] = tochar(0); /* How much padding I need */
data[3] = ctl('\0'); /* Padding character I need */
data[4] = tochar(reol); /* End-Of-Line character I need */
data[5] = quote; /* Quote character I send */
if (parity!=PYNONE || ebqflg) /* 8-bit quoting required? */
{
data[6] = pebq; /* Ask for what we have SET */
if (chkquote(ebq) || ebq=='Y')
ebqflg = TRUE; /* If valid reply, set flag */
}
else data[6] = 'Y'; /* Not required, just say we're willing */
data[7] = '1'; /* Checksum type 1 */
data[8] = ' '; /* No repeat count capability */
return(9); /* Return the length */
}
/* RPAR - Get and analyse the remote's Send-Init parameters */
#define IFP if (length-->0) /* If field is present */
rpar(data)
char data[];
{
IFP tslen = min(unchar(data[0]),tslen); /* Maximum send packet size */
IFP tvalue = max(50*unchar(data[1]),tvalue); /* When I should time out */
IFP tnpad = max(unchar(data[2]),tnpad); /* Padding required */
IFP tpadc = ctl(data[3]); /* Padding character */
IFP tseol = unchar(data[4]); /* EOL character I must send */
IFP tquote = data[5]; /* Incoming data quote character */
IFP
{
ebq = data[6]; /* EBQ remote will use */
if (chkquote(ebq)) ebqflg = TRUE; /* If acceptable, we will too */
else if ((parity!=PYNONE || ebqflg) && ebq=='Y')
{ /* We need it, remote says OK */
ebqflg = TRUE;
ebq = pebq; /* Use what we have SET */
}
else if (ebq=='N')
{
ebqflg = FALSE; /* We need it, remote can't do */
}
else ebqflg = FALSE; /* Some other reply */
}
else ebqflg = FALSE; /* No reply */
if (tseol==0) tseol = '\r'; /* Check and set defaults */
if (tquote==0) tquote = quote;
if (tslen<10) tslen = 10;
if (debon)
{
printf("rpar: timeout=%d, length=%d, EOL=%d\n",tvalue/50,tslen,tseol);
printf(" npad=%d, padchar=0%o, quote=%c\n",tnpad,tpadc,tquote);
printf(" 8-bit quoting %s",(ebqflg ? "yes" : "no"));
if (ebqflg) printf(", with %c",ebq);
printf("\n");
}
}
/* ACK - Send an acknowledgement with no data */
ack()
{
spack('Y',n,0,0);
}
/* ACK1 - Send an acknowledgement with 1 character of data */
ack1(s)
char *s;
{
spack('Y',n,1,s);
}
/* ACKN - Acknowledge a specific packet number */
ackn(num)
int num;
{
spack('Y',num,0,0);
}
/* NAK - Send a negative acknowledegement */
nak()
{
spack('N',n,0,0);
}