home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
perkinelmeridris
/
pe7pta.c
< prev
next >
Wrap
C/C++ Source or Header
|
2020-01-01
|
19KB
|
715 lines
/* pe7pta.c */
/* Include external declarations */
#include "pe7inc.h"
/*
* g i n i t
*
* Get receive Initialization
*
*/
TEXT ginit(l, file)
int l; /* Length of the filename */
TEXT *file; /* File name pointer */
{
int len, num, slen; /* Packet length, number */
if (numtry++ > MAXTRY) return ('A'); /* If too many tries, "abort" */
flushinput(); /* Clear out the i/o channel */
spack('R',n,l,file); /* Send the requested file name */
switch(rpack(&len,&num,recpkt)) /* Get a packet */
{
case 'S': /* Send-Init packet */
if ( n != num)
{
case 'N':
case FALSE:
nxi++;
return (state);
}
if (!rpar(recpkt,&len)) /* Get the other side's init data */
return ('A'); /* error with the packet parameters */
slen = spar(packet0); /* Fill up packet with my init info */
spack('Y',n,slen,packet0);/* ACK with my parameters */
oldtry = numtry; /* Save old try count */
nxtpkt();
return ('F'); /* Enter File-Receive state */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
default:
return ('A'); /* Some other packet type, "abort" */
}
}
/*
* x i n i t
*
* Server command scanning
*/
TEXT xinit()
{
int i, /* A counter */
search, /* Filename search state flag */
len, num, slen; /* Packet length, number */
TEXT *filep; /* Pointer to input buffer */
switch(rpack(&len,&num,recpkt)) /* Get a packet */
{
case 'S': /* Send-Init packet */
if (!rpar(recpkt,&len)) /* Get the other side's init data */
return ('A'); /* error with the packet parameters */
slen = spar(packet0); /* Fill up packet with my init info */
spack('Y',n,slen,packet0); /* ACK with my parameters */
oldtry = numtry; /* Save old try count */
nxtpkt();
return ('F'); /* Enter File-Receive state */
case 'I': /* Send-Init packet */
if (!rpar(recpkt,&len)) /* Get the other side's init data */
return ('A'); /* error with the packet parameters */
slen = spar(packet0); /* Fill up packet with my init info */
spack('Y',n,slen,packet0); /* ACK with my parameters */
oldtry = numtry; /* Save old try count */
n = 0;
numtry = 0;
return (state); /* Say we got our parameters */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return ('A'); /* abort */
case FALSE: /* Didn't get packet */
nxi++;
spack('N',n,0,0); /* Return a NAK */
case 'N':
return (state); /* Keep trying */
case 'R':
/* copy the packet data into a filename_buffer */
/* cpystr(&filename_buffer, &recpkt, NULL); /* */
btobemp(filename_buffer, recpkt, MAXPACKSIZ); /* Uncode packet */
filecount = 0;
filelist = &files;
filep = &filename_buffer;
search = 2;
while (*filep != NULL && filecount < 10)
{
switch (search)
{
case 1: /* Looking for next filename */
if (iswhite(*filep))
break;
search = 2;
case 2: /* Looking for filename */
if (iswhite(*filep))
break;
files[filecount++] = filep;
search = 3;
case 3: /* Looking for end of filename */
if (!iswhite(*filep))
break;
*filep = NULL;
search = 1;
}
filep++;
}
if (debug) printf("Xinit 1: Request for %d files...\n", filecount);
if (gnxtfl() == FALSE) /* Any files to send? */
return ('B'); /* if not, break, EOT, all done */
return ('S'); /* Start sending files, switch state to S */
case 'G':
if (recpkt[0] == 'F')
{
spack('Y',n,0,0); /* say ok */
return ('G');
}
else
{
error("Invalid server command");
return (state); /* keep trying */
}
default:
error("Unknown packet type");
return (state);
}
}
/*
* s f i l e
*
* Send File Header.
*/
TEXT sfile()
{
TEXT filnam1[MAXFNAME], /* Converted file name */
*newfilnam, /* Pointer to file name to send */
*cp; /* char pointer */
int num, len; /* Packet number, length */
ULONG time();
if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
if (fd == NULL) /* If not already open, */
{
if (debug) printf("Sfile 1: Opening %s for sending.\n",filnam);
/* Open file to be sent */
if ((fd = fopen(&pfio, filnam, READ)) == NULL)
/* If bad file pointer, give up */
{
printmsg("Cannot open file %s\n",filnam);
return ('A');
}
/* cpystr(filnam1, filnam, NULL); /* Copy file name */
btobemp(filnam1, filnam, MAXFNAME); /* Copy file name */
newfilnam = cp = filnam1;
while (*cp != '\0') /* Strip off all leading directory */
if (*cp++ == '/') /* names (ie. up to the last /). */
newfilnam = cp;
if (filnamcnv) /* Convert lower case to upper */
for (cp = newfilnam; *cp != '\0'; cp++)
*cp = toupper(*cp);
len = cp - newfilnam; /* Compute length of new filename */
if (vflg)
printmsg("Sending %s as %s",filnam,newfilnam);
}
dostat(2);
spack('F',n,len,newfilnam); /* Send an F packet */
switch(rpack(&len,&num,recpkt)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */
case 'Y':
if (n != num) /* which is just like an ACK for */
{ /* Wrong packet number */
case FALSE: /* Receive failure, stay in F state */
nxi++;
return (state);
}
nxtpkt();
dostat(4);
repeat_count = 0; /* Reset repeat character counter */
empty[1-pknum] = 0; /* Make other buffer empty */
if ((empty[pknum] = size[pknum] = bufill (packet[pknum])) != EOF)
return ('E'); /* Switch to data state */
return ('Z'); /* Must be end of file */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
default:
return ('A'); /* Something else, just "abort" */
}
}
/*
* r f i l e
*
* Receive File Header
*/
TEXT rfile()
{
TEXT filnam1[MAXFNAME]; /* Holds the converted file name */
int num, len, slen; /* Packet number, length */
int dum; /* Holds array pointer */
ULONG time();
if (numtry++ > MAXTRY) return ('A'); /* "abort" if too many tries */
dostat(2);
switch(rpack(&len,&num,recpkt)) /* Get a packet */
{
case 'S': /* Send-Init, maybe our ACK lost */
if (oldtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */
if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
{
/* Yes, ACK it again with */
slen = spar(packet0);/* our Send-Init parameters */
spack('Y',num,slen,packet0);
numtry = 0; /* Reset try counter */
return (state); /* Stay in this state */
}
else return ('A'); /* Not previous packet, "abort" */
case 'Z': /* End-Of-File */
if (oldtry++ > MAXTRY) return ('A');
if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
{
/* Yes, ACK it again. */
spack('Y',num,0,0);
numtry = 0;
return (state); /* Stay in this state */
}
else return ('A'); /* Not previous packet, "abort" */
case 'F': /* File Header (just what we want) */
if (num != n) return ('A');/* The packet number must be right */
/* cpystr(filnam1, recpkt, NULL); /* Copy the file name */
btobemp(filnam1, recpkt, MAXFNAME); /* Copy the file name */
if (filnamcnv) /* Convert upper case to lower */
for (filnam=filnam1; *filnam != '\0'; filnam++)
*filnam = tolower(*filnam);
/* Create the file for writing into */
if ((fd = fcreate(&pfio, filnam1, WRITE)) == NULL)
{
error("Cannot create %s",filnam1); /* Give up if can't */
return ('A');
}
if (vflg)
printmsg("Receiving %s as %s",recpkt,filnam1);
spack('Y',n,0,0); /* Acknowledge the file header */
oldtry = numtry; /* Reset try counters */
nxtpkt();
dostat(4);
return ('D'); /* Switch to Data state */
case 'B': /* Break transmission (EOT) */
if (num != n) return ('A'); /* Need right packet number here */
spack('Y',n,0,0); /* Say OK */
return ('C'); /* Go to complete state */
case FALSE: /* Didn't get packet */
nxi++;
spack('N',n,0,0); /* Return a NAK */
return (state); /* Keep trying */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
default:
return ('A'); /* Some other packet, "abort" */
}
}
/*
* Checksum computations
*
* chk1 - Compute a type 1 Kermit 6 bit checksum
* chk2 - Compute a type 2 Kermit block check
* chk3 - Compute a type 3 Kermit block check
*
*/
chk1(packet)
char *packet;
{
int checksum;
checksum = chk2(packet);
return ((((checksum & 0300) >> 6) + checksum) & 077);
}
chk2(packet)
char *packet;
{
ULONG checksum;
for (checksum = 0; *packet != '\0' ; packet++)
checksum += pflg ? *packet & 0177 : *packet;
return (checksum);
}
chk3(packet)
char *packet;
{
int c, checksum, q;
checksum = 0;
while ((c = pflg ? *packet & 0177 : *packet) != '\0')
{
q = (checksum ^ c) & 017; /* Low order nibble */
checksum = (checksum >> 4) ^ (q * 010201);
q = (checksum ^ (c >> 4)) & 017; /* High order nibble */
checksum = (checksum >> 4) ^ (q * 010201);
packet++;
}
return (checksum);
}
/*
* s p a r
*
* Fill the data array with my send-init parameters
*
*/
spar(data)
TEXT data[];
{
int len;
data[0] = tochar(MAXPACKSIZ);/* Biggest packet I can receive */
data[1] = tochar(MYTIME); /* When I want to be timed out */
data[2] = tochar(MYPAD); /* How much padding I need */
data[3] = ctl(MYPCHAR); /* Padding character I want */
data[4] = tochar(MYEOL); /* End-Of-Line character I want */
data[5] = MYQUOTE; /* Control-Quote character I send */
if (state == 'S')
{
/* Set up the startup parameters */
/* The other side may call the shots if we are a server */
data[6] = sqbin = image ? pflg ? MYQBIN : DEFQBIN : 'N';
data[7] = DEFCHKT; /* I will use this check sum */
data[8] = DEFREPT; /* This is my repeat character */
data[9] = tochar(NULL); /* No bit mask at this time */
data[10] = tochar(NULL);
data[11] = tochar(NULL);
data[12] = tochar(NULL);
data[13] = tochar(NULL);
/* Tell the other side what we set up in the start */
data[14] = image ? tochar( 1 ) : tochar ( NULL );
data[15] = pflg ? pflg : tochar(NULL);
len = 16;
}
else /* Receive flag must be on. We are not the starters */
{
data[6] = rqbin; /* Quote character both sides will use */
data[7] = chkt; /* Checksum type */
data[8] = rrept; /* Set My repeat character */
data[9] = tochar(NULL); /* No bit mask at this time */
len = 10;
}
if (debug > 1)
{
printf("Spar: spsiz=%d, timint=%d\n", spsiz, timint);
printf(" pad=%d, padchar=%d, eol=%d, ", pad, padchar, eol);
printf("quote=%d, qbin=%d, chkt=%d, ", quote, qbin, chkt);
printf("rept=%d\n", rept);
if (len > 10)
printf(" image= %d, pflg= %c, iflg= %d, spflg= %c\n",
image,pflg,iflg,spflg);
}
return ( len );
}
/* r p a r
*
* Get the other host's send-init parameters
*
*/
rpar(data,len)
TEXT data[];
int *len;
{
TEXT chkchar();
/* Maximum send packet size */
spsiz = *len < 1 ? DEFPACKSIZ : unchar(data[0]);
/* When I should time out */
timint = *len < 2 ? MYTIME : unchar(data[1]);
/* Number of pads to send */
pad = *len < 3 ? 0 : unchar(data[2]);
/* Padding character to send */
padchar = dopar(*len < 4 ? NULL : ctl(data[3]));
/* EOL character I must send */
eol = *len < 5 ? CR : unchar(data[4]);
/* Incoming data quote character */
quote = *len < 6 ? '#' : data[5];
/* Force to a type one check sum */
chkt = *len < 8 ? DEFCHKT : data[7] != MYCHKT ? DEFCHKT : MYCHKT;
/* Set up the multi repeat char */
rrept = *len < 9 ? ' ' : data[8];
if (state != 'S')
{
/* Determine the state of image and parity flags from the other side */
image = *len < 15 ? iflg : data[14] == SP ? FALSE : TRUE;
pflg = *len < 16 ? spflg : data[15] == SP ? FALSE : data[15];
/* Determine the state of the sqbin */
sqbin = image ? pflg ? MYQBIN : DEFQBIN : 'N';
/* Determine the quoting mode we will use based on what the other side
* allows and what we are capable of */
rqbin = *len < 7 ? 'N' : data[6] == DEFQBIN ? sqbin : data[6];
qbin = chkchar(rqbin);
/* Determine the repeat mode based on what the other side allows */
rept = chkchar(rrept);
}
else
{
/* Determine the final quoting mode based on what the other side allows */
rqbin = *len < 7 ? 'N' : data[6];
qbin = sqbin == DEFQBIN ?
chkchar(rqbin) : rqbin == MYQBIN ? MYQBIN : FALSE;
/* Determine the final repeat mode based on what the other side allows */
rept = rrept == DEFREPT ? rrept : FALSE;
}
/* Force 8 bit quoting if requested and we are not generating parity */
if (qbin && !pflg)
pflg = 'n';
/* Maybe we can not do image because the other end can
not support binary quote */
if (image && rqbin == 'N')
{
error("Binary file transfer not supported");
return (FALSE);
}
if (debug > 1)
{
printf("Rpar: spsiz=%d, timint=%d\n", spsiz, timint);
printf(" pad=%d, padchar=%d, eol=%d, ", pad, padchar, eol);
printf("quote=%d, qbin=%d, chkt=%d, ", quote, qbin, chkt);
printf("rept=%d\n", rept);
if (*len > 14 )
printf(" image=%d, pflg=%c\n",image,pflg);
}
return (TRUE);
}
/*
* b u f i l l
*
* Get a bufferful of data from the file that's being sent.
*
*/
bufill(buffer)
TEXT buffer[]; /* Buffer */
{
int i; /* Loop index */
METACH t; /* Character that may be output */
static METACH tt {0}; /* For the comparisions of the repeat count */
i = 0; /* Init data buffer pointer */
while ((t = getc(&pfio)) != EOF) /* fetch till end */
{
file.fc++;
if (rept) /* If rept set then true */
{
if (repeat_count) /* If r..c.. set then true */
{
/* Check for repeat character and not too many of them */
if ((tt == t) && (++repeat_count < 95))
continue;
/* The characters were different or we ran out of
repeat count */
if (repeat_count > 3) /* Output repeat string */
{
buffer[i++] = rept;
if (repeat_count >= 95) repeat_count = 94;
buffer[i++] = tochar(repeat_count);
repeat_count = 1; /* Set for next */
}
for (; repeat_count ; repeat_count -= 1)
store_in_buffer(tt, buffer, &i);
/* We have output the repeat count and the repeat character */
}
/* End of repeat_count test */
tt = t; /* Set up temps for next character */
repeat_count = 1;
}
/* End of non NULL rept */
else /* rept = 0 */
store_in_buffer(t, buffer, &i);
if (i >= spsiz-SPOVER) return (i); /* Check length */
}
/* End of while loop */
/* Test if there is an repeat count outstanding.
It could be that we have not inserted any data into
output buffer */
if (repeat_count > 3)
{
buffer[i++] = rept;
buffer[i++] = tochar(repeat_count);
repeat_count = 1; /* Set for next */
}
for (; repeat_count ; --repeat_count)
store_in_buffer(tt, buffer, &i);
if (i==0) return (EOF); /* Wind up here only on EOF */
/* We need to split the packet. Scan backwards for a natural
* break, and then send of the packet. When we return point
* to the data and move to the front the rest and fetch more
* more data. */
/* Natural breaks are the quote character, repeat character
* and the binary character */
return (i); /* Handle partial buffer */
}
/*
* b u f e m p
*
* Put data from an incoming packet into a file.
*
*/
bufemp(buffer,len)
register TEXT buffer[]; /* Buffer */
int len; /* Length */
{
register int i; /* Counter for number of characters */
int ri; /* Repeat counter for repeated characters */
TEXT t, t7, tm; /* Character holders */
for (i = 0; i < len; i++) /* Loop thru the data field */
{
tm = 0; /* Preset for next */
t = buffer[i]; /* Get character */
ri = 1; /* Set repeat count to one (do at least one) */
/* At this point we check for a repeat character
* if the rept char is set then the condition will be tested
* else we can not get here since the character t may
* not be a NULL */
if (t == rept) /* Repeated character? */
{
ri = unchar(buffer[++i]); /* Fetch repeat count */
t = buffer[++i]; /* Fetch next character */
}
if (t == qbin) /* Next character have high bit on? */
{
tm = 0200; /* Set mask to high bit on */
t = buffer[++i];/* Fetch next character */
}
if (t == quote) /* Control quote? */
{
/* Yes */
t = buffer[++i]; /* Get the quoted character */
t7 = t & 0177; /* make a match character */
if (t7 != quote && t7 != rept && t7 != qbin) /* Low bits
match quote, rept or qbin? */
t = ctl(t); /* No, uncontrollify it */
}
if (t==CR && !image) /* Pass CR if in image mode */
continue;
t |= tm;
for (; ri ; --ri) /* We put at least one character away */
{
putc(&pfio, t);
file.fc++;
}
}
}
/*
* b t o b e m p
*
* Put data from an incoming packet into a buffer.
*
*/
btobemp(bout,buffer,len)
register TEXT buffer[]; /* Buffer */
register TEXT bout[]; /* Output Buffer */
int len; /* Length */
{
register int i; /* Counter for number of characters */
register int j; /* Output buffer counter */
int ri; /* Repeat counter for repeated characters */
TEXT t, t7, tm; /* Character holders */
j = 0; /* Initialize output buffer pointer */
if(debug) printf("[btobemp] buffer=>>>%s<<<\n",buffer);
/* for (i = 0; i < len; i++) /* Loop thru the data field */
for (i = 0; buffer[i] != '\0'; i++) /* Loop thru the data field */
{
tm = 0; /* Preset for next */
t = buffer[i]; /* Get character */
ri = 1; /* Set repeat count to one (do at least one) */
/* At this point we check for a repeat character
* if the rept char is set then the condition will be tested
* else we can not get here since the character t may
* not be a NULL */
if (t == rept) /* Repeated character? */
{
ri = unchar(buffer[++i]); /* Fetch repeat count */
t = buffer[++i]; /* Fetch next character */
}
if (t == qbin) /* Next character have high bit on? */
{
tm = 0200; /* Set mask to high bit on */
t = buffer[++i];/* Fetch next character */
}
if (t == quote) /* Control quote? */
{
/* Yes */
t = buffer[++i]; /* Get the quoted character */
t7 = t & 0177; /* make a match character */
if (t7 != quote && t7 != rept && t7 != qbin) /* Low bits
match quote, rept or qbin? */
t = ctl(t); /* No, uncontrollify it */
}
if (t==CR && !image) /* Pass CR if in image mode */
continue;
t |= tm;
for (; ri ; --ri) /* We put at least one character away */
{
if( j >= (len) ) {
printf("Kermit: [btobemp] Expanded packet overflows buffer\
\n j=%d MAXFNAME=%d\n",j,(MAXFNAME));
error("Kermit: [btobemp] Expanded packet overflows buffer\n");
break;
}
bout[j] = t;
j++;
}
}
if( j < len )
bout[j] = '\0';
}
/*
* s t o r e _ i n _ b u f f e r
*
* This routine stores the character into the output buffer
*
*/
store_in_buffer(t, buffer, i)
TEXT t;
register TEXT buffer[];
register int *i;
{
TEXT t7,tm;
t7 = t & 0177; /* Strip high bit */
if (t7 == '\n' && !image)
{
/* Do LF->CRLF mapping if !image */
buffer[(*i)++] = MYQUOTE;
buffer[(*i)++] = ctl('\r');
}
if (qbin != 0 && (pflg ? t & 0200 : 0) != 0) /* Binary quote on? */
buffer[(*i)++] = MYQBIN; /* Output a flag char */
/* Does this character need special handling? */
if (t7 < SP || t7 == DEL)
{
/* Yes this character need some changes */
buffer[(*i)++] = MYQUOTE; /* Quote the character */
t7 = ctl(t7); /* and uncontrolify */
t = ctl(t);
}
else /* it is not a special character */
{
if (t7 == MYQUOTE || t7 == rept || t7 == qbin)
buffer[(*i)++] = MYQUOTE; /* Quote the character */
}
buffer[(*i)++] = pflg ? t7 : t;
}
/* pe7pta.c End-of-file */