home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
honeywellgcosa
/
hd6pri.c
< prev
Wrap
C/C++ Source or Header
|
2020-01-01
|
59KB
|
1,523 lines
/************************************************************************
*
* HD6PRI.C Superkermit protocol modules and primitives.
*
***********************************************************************/
#include "hd6ker.h"
/*
* r d a t a
*
* Receive data
* The receiving of file attribute packets is handled in this module!
*
*/
char rdata()
{
int num, len; /* Packet number, length */
unsigned int j;
unsigned int k_size = 0;
char *bufp, *start, c, d; /* attribute pointers */
float byte_size;
double byte_sz, atof();
char filnam1[50]; /* Holds the converted file name */
if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
switch(rpack(&len,&num,packet)) /* Get packet */
{
/* code added to ACK and use attrib packets if received [FRANK DREANO] */
case 'A':
if (num != n) { /* Right packet number or not */
if (oldtry++ > MAXTRY)
return('A'); /* too many retries, abort */
if (num == ((n==0) ? 63:n-1)) { /* duplicate ? */
spack('Y',num,0,xnull); /* Yes, re-ACK it */
numtry = 0; /* Reset try counter */
return(state); /* stay in this state */
}
else return('A');
}
/* got the right attrib packet */
spack('Y',n,0,xnull); /* ACK the attribute */
oldtry = numtry; /* Reset try counters */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* bump packet counter */
bufp = packet;
while ((*bufp) != '\0') { /* process the attributes */
switch(*bufp++) {
case '1':
d = *bufp;
j = (*bufp) - ' ';
*bufp = '+';
start = bufp; byte_sz = 0;
bufp = ++bufp + j;
c = *bufp;
*bufp = ' '; /* terminate flting point string */
byte_sz = atof(start);
if (debug)
fprintf(dfp,"\nThe file size is: %7.f bytes.\n", byte_sz);
*bufp = c;
*start = d;
break;
case '#': /* just eat all other non-file size attribs */
case '.':
j = (*bufp++) - ' ';
bufp = bufp + j;
break;
case '!':
j = (*bufp++) - ' ';
start = bufp; k_size = 0;
bufp = bufp + j;
c = *bufp;
*bufp = '\0'; /* terminate integer string */
k_size = atoi(start);
if (debug) fprintf(dfp,"\nThe file size is: %u Kilobytes.\n", k_size);
*bufp = c;
break;
default:
j = (*bufp++) - ' ';
bufp = bufp + j;
if (debug) fprintf(dfp,"\nThe attribute is not recognized.");
break;
} /* end switch */
} /* end while */
/* got the incoming file size lets make contiguous efficient space */
if ((k_size == 0) && (byte_sz != 0))
k_size = byte_sz / 1000;
k_size = 32 * ((k_size + 32 - 1)/32); /* round out */
k_size = k_size * 2;
getfiles[49] = 0;
strcpy(filnam1, getfiles); /* Copy filename */
if (k_size > 64) {
if (debug) fprintf(dfp,"\nCI growth size is: %u.\n", k_size);
fclose(fp);
sprintf(cmdstg,">SYSLIB2>MFA %s -GRSZ %u ", filnam1, k_size);
if ((cmdstat = system(cmdstg)) != 0)
fprintf(stderr,"\nCould not modify <%s> growth size.", filnam1);
if ((fileimage == FOREIGN) || (fileimage == BINARY))
fp = fopen(filnam1,"ab");
else
fp = fopen(filnam1, "a");
} /* end if */
if (fileimage == FOREIGN) { /* stuff the attributes in the files */
sprintf(cmdstg,"%s\n",packet);
fputs(cmdstg, fp);
}
/* end of attribute decoding and use [FRANK DREANO] */
return('D'); /* stay in this state */
case 'D': /* Got Data packet */
if (num != n) /* Right packet? */
{ /* No */
if (oldtry++ > MAXTRY)
return('A'); /* If too many tries, abort */
if (num == ((n==0) ? 63:n-1)) { /* duplicate? */
spack('Y',num,0,xnull); /* Yes, re-ACK it */
numtry = 0; /* Reset try counter */
return(state); /* Don't write out data! */
}
else return('A'); /* sorry, wrong number */
}
/* Got data with right packet number */
if ( (num = decode(packet,len)) != 0 ) {
error("Trouble writing file, OS code %xx",num);
return('A');
}
spack('Y',n,0,xnull); /* Acknowledge the packet */
n = (n+1)%64; /* Bump packet number, mod 64 */
oldtry = numtry; /* Reset the try counters */
numtry = 0; /* ... */
return('D'); /* Remain in data state */
case 'F': /* Got a File Header */
if (oldtry++ > MAXTRY)
return('A'); /* If too many tries, "abort" */
if (num == ((n==0) ? 63:n-1)) /* Else check packet number */
{ /* It was the previous one */
spack('Y',num,0,xnull); /* ACK it again */
numtry = 0; /* Reset try counter */
return(state); /* Stay in Data state */
}
else return('A'); /* Not previous packet, "abort" */
case 'Z': /* End-Of-File */
if (num != n) return('A'); /* Must have right packet number */
spack('Y',n,0,xnull); /* OK, ACK it. */
fflush(fp); /* Flush all buffers */
fclose(fp); /* Close the file */
fp = NULL;
/* if attributes were used shrink file then reset growth size */
if ((senda) && (sattrib)) {
sprintf(cmdstg,">SYSLIB2>SHRINK %s", filnam1);
system(cmdstg);
sprintf(cmdstg,">SYSLIB2>MFA %s -GRSZ 20", filnam1);
if ((cmdstat = system(cmdstg)) != 0)
fprintf(stderr,"\nCould not reset <%s> growth size.", filnam1);
}
if (debug) {
if ( (len != 0) && (*packet == 'D') )
fprintf(dfp, "\nFile <%s> truncated by local Kermit\n",filnam);
else
fprintf(dfp,"\nFile <%s> received OK\n",filnam1);
}
n = (n+1)%64; /* Bump packet number */
return('F'); /* Go back to Receive File state */
case 'E': /* Error packet received */
prerrpkt(packet); /* Print it out and */
return('A'); /* abort */
case FALSE: /* Didn't get packet */
spack('N',n,0,xnull); /* Return a NAK */
return(state); /* Keep trying */
default:
error(badpack,prompt,type);
return('A'); /* Some other packet, "abort" */
}
} /* End of rdata() */
/*
* r f i l e
*
* Receive file header
*
*/
char rfile()
{
int num, len; /* Packet number, length */
char filnam1[50]; /* Holds the converted file name */
if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
switch(rpack(&len,&num,packet)) /* 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? */
len = spar(packet); /* our Send-Init parameters */
spack('Y',num,len,packet);
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,xnull);
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 */
decfil(packet, getfiles, len); /* 'unrepeat' filename */
getfiles[49] = 0; /* terminate the string */
strcpy(filnam1, getfiles); /* Copy filename */
if (filnamcnv) { /* Convert upper case to lower */
for (filnam=filnam1; *filnam != '\0'; filnam++)
if (*filnam >= 'A' && *filnam <= 'Z')
*filnam |= 040;
filnam = filnam1;
}
/* should have gotten a file attribute packet instead */
/* if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) {
error(noattrib, prompt);
return('A');
} */
for (filnam=filnam1; *filnam != '\0'; filnam++)
if (*filnam == ',') {
*filnam++ = '\0';
*filnam = '\0';
break;
} /* end for */
filnam = filnam1;
if ((fileimage == BINARY) || (fileimage == FOREIGN)) {
/* create and open binary/foreign type file */
if (debug) fprintf(dfp,
"\nDeleting <%s> if it exists.",filnam1);
sprintf(cmdstg,">SYSLIB2>DL %s -BF", filnam1);
if ( ((cmdstat = system(cmdstg)) !=0) && (debug) )
fprintf(dfp,
"\nFile not deleted; as it did not already exist.");
cmdstat = 0;
if (fileimage == BINARY)
sprintf(cmdstg, ">SYSLIB2>CR %s -F_REL -LRSZ %d -SZ 0", filnam1, lrsz_6);
if (fileimage == FOREIGN)
sprintf(cmdstg, ">SYSLIB2>CR %s -SEQ -DATA_CODE BINARY -SZ 0", filnam1);
if ((cmdstat = system(cmdstg)) != 0) {
syserr("system");
return('A');
} /* end if */
if (debug) fprintf(dfp,"\nOpening <%s> for receiving.",filnam1);
fp=fopen(filnam1,"ab");
} /* end if */
else { /* open ASCII type file */
if (dlflag) { /* overwrite existing file if flag set */
if (debug) fprintf(dfp,
"\nDeleting <%s> if it exists.",filnam1);
sprintf(cmdstg,">SYSLIB2>DL %s ", filnam1);
if ( ((cmdstat = system(cmdstg)) !=0) && (debug) )
fprintf(dfp,"\nFile not deleted; as it did not already exist.");
} /* end if */
if (debug) fprintf(dfp,
"\nOpening <%s> for receiving.",filnam1);
fp=fopen(filnam1,"a");
} /* end else */
if (fp == NULL) {
error("%sCannot create <%s>",prompt,filnam1);
return('A');
} /* end if */
else /* OK, give message */
if (debug) fprintf(dfp,"\nReceiving %s as %s",packet,filnam1);
/* stuff dummy attribute in foreign file if the PC didn't send any */
if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE)))
fputs(",I\n", fp);
spack('Y',n,0,xnull); /* Acknowledge the file header */
oldtry = numtry; /* Reset try counters */
numtry = 0; /* ... */
n = (n+1)%64; /* Bump packet number, mod 64 */
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,xnull); /* Say OK */
if (debug) fprintf(dfp,"All files received\n");
return('C'); /* Go to complete state */
case 'E': /* Error packet received */
prerrpkt(packet); /* Print it out and */
return('A'); /* abort */
case FALSE: /* Didn't get packet */
spack('N',n,0,xnull); /* Return a NAK */
return(state); /* Keep trying */
default:
error(badpack,prompt,type);
return ('A'); /* Some other packet, "abort" */
}
} /* End rfile() */
/*
* r i n i t
*
* Receive initalization
*
*/
char rinit()
{
int len, num; /* Packet length, number */
bctu = 1; /* type-1 blk chk at first */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
switch(rpack(&len,&num,packet)) /* Get a packet */
{
case 'S': /* Send-Init */
rpar(packet,len);
len = spar(packet);
spack('Y',n,len,packet); /* ACK with my parameters */
oldtry = numtry; /* Save old try count */
numtry = 0; /* Start a new counter */
n = (n+1)%64; /* Bump packet number, mod 64 */
bctu = bctr; /* use agreed blk chk type */
return('F'); /* Enter File-Receive state */
case 'E': /* Error packet received */
prerrpkt(packet); /* Print it out and */
return('A'); /* abort */
case 'I': /* Init-parameters */
rpar(packet,len);
len = spar(packet);
spack('Y',n,len,packet); /* ack with our parameters */
n = (n+1)%64; /* Bump packet number, mod 64 */
bctu = bctr; /* use agreed block check type */
return(state); /* & continue */
case FALSE: /* Didn't get packet */
spack('N',n,0,xnull); /* Return a NAK */
return(state); /* Keep trying */
default:
error(badpack,prompt,type);
return('A'); /* Some other packet type, "abort" */
}
} /* End rinit() */
/*
* r p a c k
*
* Read a packet
* Modified for extended packets [FRANK DREANO]
*/
rpack(len,num,data)
int *len, *num; /* Packet length and number */
char *data; /* Packet data */
{
int j,i,done,k,s; /* Data character number, loop exit */
register char *bufp, *datap; /* 'fast' array indexes */
int maxlx1, maxlx2; /* extended packet length */
unsigned char pcb[4]; /* block check char array */
char t, /* Current input character */
rlongp, /* extended packet flag */
buffer[MAXPACKSIZ + 6]; /* area to do CRC block checks */
timoset(timint); /* set timeout */
/* The way timeouts are handled is that the flag stays clear, indicating
that a timeout has occurred, until it is set to a value again
by the next call to timoset(). This means that the effect can
run up thro' the procedures without using longjmp(). */
rlongp = FALSE;
t = 0;
*len = 0; /* in case times out */
while (t != SOH) { /* Wait for packet header */
t = cread() & (char)0x7f;
}
timocan();
done = FALSE; /* Got SOH, init loop */
while (!done) /* Loop to get a packet */
{
t = cread(); /* Get character */
if (t == SOH) continue; /* Resynchronize if SOH */
bufp = buffer; /* init buffer pointer */
*bufp++ = t; /* Start the checksum */
*len = unchar(t) - bctu - 2; /* Character count */
if (*len == -(bctu+2)) rlongp = TRUE; /* long packets */
t = cread(); /* Get character */
if (t == SOH) continue; /* Resynchronize if SOH */
*bufp++ = t; /* Update checksum */
*num = unchar(t); /* Packet number */
t = cread(); /* Get character */
if (t == SOH) continue; /* Resynchronize if SOH */
*bufp++ = type = t; /* Update checksum */
/* extended packet modifications [FRANK DREANO] */
if (rlongp == TRUE) {
t = cread();
if (t == SOH) continue;
*bufp++ = maxlx1 = t; /* Get extended length */
t = cread();
if (t == SOH) continue;
*bufp++ = maxlx2 = t; /* Get extended length */
t = cread();
if (t == SOH) continue;
/* got all of extended packet header; do checksum and length computes */
*bufp = '\0';
if (t != tochar(chk1(buffer))) { /* compute hdr sum */
if (debug)
fprintf(dfp,
"\nExtended hdr chksum error: rec'd %xx computed %xx;",
t, tochar(chk1(buffer)));
return(FALSE);
} /* end if */
*bufp++ = t;
*len = unchar(maxlx1) * 95 + unchar(maxlx2) - bctu;
} /* end if */
datap = data;
for (i=0; i<*len; i++) { /* The data itself, if any */
t = cread(); /* Get character */
if (t == SOH)
break; /* Resynch if SOH */
*bufp++ = *datap++ = t; /* Update checksum */
}
if (t == SOH)
continue;
*bufp = *datap = '\0'; /* Terminate the strings */
/* At this point the data for an entire packet should have been read in */
/* so print it and do the block checks...type 1, 2, or 3. [FRANK DREANO] */
if (debug) fprintf(dfp,"\n Packet %d received; ",*num);
if (debug>1) { /* Display incoming packet */
fprintf(dfp," type: %c;",type);
fprintf(dfp," num: %d;",*num);
fprintf(dfp," len: %d.",*len);
if (*len != 0) {
j = 0;
while (j < *len) {
fprintf(dfp,"\n data: <");
i=0;
while ((i < 60 ) && (j < *len)) {
putc(data[j++],dfp);
i++;
} /* end while */
putc('>',dfp);
} } }
for (s=0; s<bctu; s++) { /* get all of the block check characters */
t = cread();
if (t == SOH) break; /* Get out of loop if SOH */
pcb[s] = t;
} /* end for */
if (t == SOH) continue; /* Resynch if SOH */
pcb[s] = '\0'; /* terminate the string */
done = TRUE; /* I have now read EVERYTHING ! */
} /* end outermost while */
switch (bctu) {
case 1:
if (unchar(*pcb) != chk1(buffer)) {
if (debug)
fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
unchar(*pcb), chk1(buffer));
return(FALSE);
} /* end if */
break;
case 2:
s = unchar(*pcb) << 6;
s = s | unchar(pcb[1]);
if (s != chk2(buffer)) {
if (debug)
fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
s, chk2(buffer));
return(FALSE);
} /* end if */
break;
case 3:
s = unchar(*pcb) << 12;
s = s | unchar(pcb[1]) << 6;
s = s | unchar(pcb[2]);
if (s != chk3(buffer)) {
if (debug)
fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
s, chk3(buffer));
return(FALSE);
} /* end if */
break;
default:
if (debug)
fprintf(dfp,"\n packet format is invalid");
return(FALSE);
} /* end switch */
flushinput();
return(type); /* All OK, return packet type */
} /* End of rpack() */
/*
* r p a r
*
* Get the other side's send-init parameters
* Modified for extended packets [FRANK DREANO]
*/
rpar(data,len)
char *data, len;
/* Set up incoming parameters to either what has been received
or, if nil, to defaults.
No return-code. */
{
char p;
int olen, /* original recv-init packet length */
rpsiz; /* remote's packet length */
olen = len;
spsiz = 80; /* send packet-length 80 chars */
timint = MYTIME; /* timeout as defined */
eol = CR; /* terminator normally CR */
quote = '#'; /* standard control-quote char */
rptflg = FALSE; /* nor repeat-quoting */
sattrib = FALSE; /* no attribute packets yet */
while (len-- > 0) {
p = data[len];
switch (len) { /* for each parameter */
case 0: /* MAXL */
rpsiz = unchar(p);
/* loop goes backwards so set spsiz to what was negotiated */
spsiz = (spsiz < 95) ? rpsiz : spsiz;
break;
case 1: /* TIME */
timint = (unchar(p) < 5) ? 5 : unchar(p);
break;
case 2: /* NPAD */
pad = unchar(p);
break;
case 3: /* PADC */
padchar = ctl(p);
break;
case 4: /* EOL */
eol = unchar(p);
break;
case 5: /* QCTL */
quote = p;
break;
case 6: /* QBIN */
if (image == 2) {
if (p == 'Y')
qu8 = '&';
else if (isalnum(p) == 0) /* provided punctuation */
qu8 = p;
else
image = 0;
break;
}
break;
case 7: /* BLOCK CHECK TYPE */
bctr = p - '0';
bctr = (bctr < 1 || bctr > 3) ? 1 : bctr;
break;
case 8: /* REPT */
if (p == '~')
rptflg = TRUE;
break;
/* extended packet additions [FRANK DREANO]
This routine sets 2 variables slongp = TRUE/FALSE for extended
packets on/off and spsiz = negotiated packet length. */
case 9:
if (slongp == TRUE) { /* did user ask for extended packets ? */
if (((unchar(p) & 0x02)) == 0x02) {
spsiz = MAXPACKSIZ; /* 2000 bytes */
rpsiz = 500; /* set default extended packet length */
if (olen > 9)
rpsiz = unchar(data[11]) * 95 + unchar(data[12]);
/* set final negotiated size no matter what */
spsiz = (spsiz < rpsiz) ? spsiz : rpsiz;
if (debug)
fprintf(dfp,"\nExtended packets used size: %d.", spsiz);
} /* end if */
else
slongp = FALSE; /* turn extended packets off */
} /* end if */ /* if CAPAS bit not set */
if (((unchar(p) & 0x08)) == 0x08) /* user likes attrib packets */
sattrib = TRUE;
break;
default: /* CHKT, CAPAS etc. */
break;
} } /* end while & outer switch */
if ( (qu8 == 0) && (image == 2) ) /* invalid tseting */
image = 0;
if (debug) fprintf(dfp,
"\nParms recd in: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
fileimage,image,qu8,logicval[-rptflg],bctr);
/*
"\nParms rec'd in: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
image,qu8,logicval[-rptflg],bctr); */
return;
} /* End of rpar() */
/*
* s b r e a k
*
* Send break (EOT)
*
*/
char sbreak()
{
int num, len; /* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
spack('B',n,0,packet); /* Send a B packet */
switch (rpack(&len,&num,recpkt)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num<0 ? 63:num); /* unless NAK for previous packet, */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) return(state); /* If wrong ACK, fail */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* and bump packet count */
return('C'); /* Switch state to Complete */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: return('C'); /* Receive failure, count as OK */
/* If timed out or etc. when completing, likely other end has gone away */
default:
error(badpack,prompt,type);
return ('A'); /* Other, "abort" */
}
} /* End sbreak() */
/*
* s d a t a
*
* Send file data
*
*/
char sdata()
{
int num, len; /* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
spack('D',n,size,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 */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) return(state); /* If wrong ACK, persist */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* Bump packet count */
if (len != 0) switch (*recpkt) { /* ACK has data */
case 'Z': /* cancel all */
case 'z':
filecount = 0; /* no more to go */
case 'X': /* cancel file */
case 'x':
return('Z');
default: /* invalid */
if (!senda) { /* Attrib ACK can have data */
recpkt[20] = 0; /* truncate */
error("%sLocal Kermit sent ACK with data: <%s> - goodbye!",prompt,recpkt);
return('A');
} /* end if */
} /* end inner switch */
if ((size = bufill(packet)) != EOF) /* data from file */
return('D'); /* Got data, stay in state D */
/* EOF can mean either really end-of-file or an error */
if ( (num = filerr()) != 0 ) { /* actual error */
error("Problem while reading file, OS code %xx",num);
return('A');
} /* end if */
return('Z'); /* EOF */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: return(state); /* Receive failure, stay in D */
default:
error(badpack,prompt,type);
return('A'); /* Anything else, "abort" */
} /* end outer switch */
} /* End sdata() */
/*
* s e o f
*
* Send End-of-File
*
*/
char seof()
{
int num, len; /* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
spack('Z',n,0,packet); /* Send a 'Z' 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, */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) return(state); /* If wrong ACK, hold out */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* and bump packet count */
if (debug) fprintf(dfp,"\nClosing input file <%s>, ",filnam);
fclose(fp); /* Close the input file */
fp = NULL; /* Set flag indicating no file open */
if (debug) fprintf(dfp,"looking for next file...");
if (gnxtfl() == FALSE) { /* No more files go? */
if (debug) fprintf(dfp,"\nNo more files to send.");
return('B'); /* if not, break, EOT, all done */
}
if (debug) fprintf(dfp,"New file is %s\n",filnam);
senda = TRUE; /* send attrib pkt if negotiated */
return('F'); /* More files, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: return(state); /* Receive failure, stay in Z */
default:
error(badpack,prompt,type);
return('A'); /* Something else, "abort" */
}
} /* End seof() */
/*
* s f i l e
*
* Send file header
*
*/
char sfile()
{
int num, len, lenlen; /* Packet number, length */
unsigned filesize;
char filnam1[50], /* Converted file name */
*newfilnam, /* Pointer to file name to send */
*cp; /* char pointer */
/* MUST use attribute packets with foreign file types!! */
/* if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) {
error(noattrib, prompt);
return('A');
} */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
if (fp == NULL) { /* If not already open, */
if (debug) fprintf(dfp,"\nOpening %s for sending.",filnam);
if ((fileimage == BINARY) || (fileimage == FOREIGN))
fp = fopen(filnam,"rb");
else
fp = fopen(filnam,"r"); /* open the file to be sent */
if (fp == NULL) /* If bad file pointer, give up */
{
error("%sCannot open file <%s>",prompt,filnam);
return('A');
}
}
strcpy(filnam1, filnam); /* 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++)
if (*cp >= 'a' && *cp <= 'z')
*cp ^= 040;
len = cp - newfilnam; /* Compute length of new filename */
if (debug) fprintf(dfp,"\nSending %s as %s",filnam,newfilnam);
if (iflg >= 99)
spack('X',n,len,newfilnam); /* Send an X packet if a 'remote' cmd */
else
spack('F',n,len,newfilnam); /* Send an F packet for file xfer */
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': /* ACK */
if (n != num)
return(state); /* If wrong ACK, stay in F state */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* Bump packet count */
/* if using attributes switch to 'Q' state; else 'D' state */
/* get the attribute from foreign files */
if (fileimage == FOREIGN)
fgets(attrib, 80, fp);
if ((sattrib) && (senda)) {
/* use attribute packets */
if ( (fileimage == FOREIGN) && ((strncmp(",I",attrib,2)!=0)) ) {
size = strlen(attrib)-1; /* drop the newline */
} else { /* not 'foreign' so build some attribs */
lenlen = 0;
while (lenlen < 45) attrib[lenlen++] = 0x0000;
/* compute size in Kilobytes */
if (fileimage == BINARY)
filesize = fsize(filnam,0);
else filesize = 0;
sprintf(attrib, "%u", filesize);
lenlen = strlen(attrib);
/* print to string, include computer attrib as well */
sprintf(attrib, ".\042E3!%c%u", tochar(lenlen), filesize);
size = strlen(attrib);
} /* end else */
return('Q');
} else { /* not using attributes! */
if ((size = bufill(packet)) != EOF) /* data from file */
return('D'); /* Got data, stay in state D */
/* EOF can mean either really end-of-file or an error */
if ( (num = filerr()) != 0 ) { /* actual error */
error("Problem while reading file, OS code %xx",num);
return('A');
}
return('Z'); /* EOF (empty file) */
} /* end outer else */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: return(state); /* Receive failure, stay in F state */
default:
error(badpack,prompt,type);
return('A'); /* Something else, just "abort" */
}
} /* End sfile() */
/*
* s a t t r u
*
* Send file attributes
* A separate state is not required to receive file attributes !
*
*/
char sattru()
{
int num, len, lenlen; /* Packet number, length */
spack('A',n,size,attrib); /* Send an A packet for file xfer */
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': /* ACK */
if (n != num)
return(state); /* If wrong ACK, stay in Q state */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* Bump packet count */
if ((size = bufill(packet)) != EOF) /* data from file */
return('D'); /* Got data, stay in state D */
/* EOF can mean either really end-of-file or an error */
if ( (num = filerr()) != 0 ) { /* actual error */
error("Problem while reading file, OS code %xx",num);
return('A');
}
return('Z'); /* EOF (empty file) */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: return(state); /* Receive failure, stay in Q state */
default:
error(badpack,prompt,type);
return('A'); /* Something else, just "abort" */
}
} /* End sattru() */
/*
* s i n i t
*
* Send initialization parameters and receive other side's back
*
*/
char sinit()
{
int num, len; /* Packet number, length */
flushinput(); /* Flush pending input */
bctu = 1; /* assume type-1 block check */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
len = spar(packet); /* Fill up init info packet */
spack('S',n,len,packet); /* Send an S packet */
switch(rpack(&len,&num,recpkt)) /* What was the reply? */
{
case 'N':
num = (--num<0 ? 63:num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, stay in S state */
return(state); /* and try again */
rpar(recpkt,len); /* Get other side's init info */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* Bump packet count */
bctu = bctr; /* use agreed upon block check */
return('F'); /* OK, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case 'I': /* Init-parameters */
rpar(packet,len);
len = spar(packet);
spack('Y',n,len,packet); /* ack with our parameters */
n = (n+1)%64; /* Bump packet number, mod 64 */
bctu = bctr; /* use agreed upon block check */
return(state); /* & continue */
case FALSE: return(state); /* Receive failure, try again */
default:
error(badpack,prompt,type);
return('A'); /* Anything else, just "abort" */
}
} /* End sinit() */
/*
* s p a c k
*
* Send a packet
* Modified for extended packets [FRANK DREANO]
*/
spack(stype,num,len,d)
char stype, *d;
int num, len;
{
int i, j; /* Character loop counter */
register char *bufp;
char chksum, buffer[MAXPACKSIZ + 6], *lp; /* Checksum, packet buffer */
if (debug > 1) { /* Display outgoing packet */
fprintf(dfp,"\nSending packet; type: %c;",stype);
fprintf(dfp," num: %d;",num);
fprintf(dfp," len: %d;",len);
if (len != 0) {
j = 0;
while (j < len) {
fprintf(dfp,"\n data: <");
i=0;
while ((i < 60 ) && (j < len)) {
putc(d[j++],dfp);
i++;
} /* end while */
putc('>',dfp);
} } }
bufp = buffer;
*bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */
lp = bufp++; /* store LEN pointer for later */
*bufp++ = tochar(num); /* Packet number */
*bufp++ = stype; /* Packet type */
j = len + bctu; /* packet length plus block check characters */
if (j+2 > 94) {
/* if (j > 95) { long packets */
*lp = tochar(0); /* init LEN count */
*bufp++ = tochar(j / 95); /* high part */
*bufp++ = tochar(j % 95); /* lo part */
*bufp = '\0'; /* header checksum */
*bufp++ = tochar(chk1(lp));
} else *lp = tochar(j+2); /* give normal length */
while (len-- > 0) *bufp++ = (*d++);
*bufp = '\0';
switch (bctu) {
case 1:
*bufp++ = tochar(chk1(lp));
break;
case 2:
j = chk2(lp);
*bufp++ = (unsigned) tochar((j >> 6) & 077);
*bufp++ = (unsigned) tochar(j & 077);
break;
case 3:
j = chk3(lp);
*bufp++ = tochar(( (unsigned) (j & 0170000)) >> 12);
*bufp++ = tochar((j >> 6) & 077);
*bufp++ = tochar(j & 077);
break;
}
*bufp++ = eol;
/* *bufp = CR; CR for network */
write(1, buffer, bufp-buffer+1);
if (debug) {
fprintf(dfp," Packet %d sent;\n",num);
}
return;
} /* End of spack() */
/*
* s p a r
*
* Fill the data array with my send-init parameters
* Returns length of parameter block (6, 7, 9 or 13)
* Modified for extended packets [FRANK DREANO]
*/
spar(data)
char *data;
{
char len;
data[0] = tochar((spsiz > 94) ? 94 : spsiz);
data[1] = tochar(MYTIME);
data[2] = tochar(MYPAD);
data[3] = ctl(0);
data[4] = tochar(MYEOL);
data[5] = MYQUOTE;
len = 6;
if (image == 2) { /* 8th-bit prefixing */
if (qu8 == 0)
/* data[6] = 'Y'; this means I don't need to quote !!! */
data[6] = '&';
else
data[6] = qu8; /* feed back 8-quote */
len = 7;
}
else
data[6] = 'N';
data[7] = bctr + '0'; /* set checksum type */
len = 8;
if (rptflg) {
data[8] = '~'; /* only ~ for repeating */
len = 9;
} /* end if */
/* extended packet modifications [FRANK DREANO] */
data[9] = tochar(0x08); /* I can accept attribute packets */
if (slongp == TRUE) {
data[9] = tochar(0x0a); /* attribs & extended packets can be used */
data[10] = tochar(0x00); /* NO sliding windows! */
data[11] = tochar(MAXPACKSIZ / 95); /* set up for 2000 bytes */
data[12] = tochar(MAXPACKSIZ % 95);
len = 13;
if (debug)
fprintf(dfp,"\nExtended packets requested (2000) bytes.");
} /* end if */
if (debug) fprintf(dfp,
"\nParms sent out: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
fileimage,image,qu8,logicval[-rptflg],bctr);
/*
"\nParms sent out: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
image,qu8,logicval[-rptflg],bctr); */
return(len);
} /* End of spar() */
/*
* t i m o c a n
*
* Cancel a scheduled timeout
*
*/
timocan()
{
timoset(0);
timflag = 0xff;
return;
} /* End of timocan() */
/*
* t i m e o x
*
* Indicate timeout condition
*
*/
timoex()
{
timflag = 0; /* clear flag */
if (debug) {
fprintf(dfp,"Timeout ...");
}
return;
} /* End of timoex() */
/*
* f s i z e
*
* This routine gets the APPROXIMATE size of a file in kilobytes
* so that an 'attribute' packet may be sent during transfers.
* It uses very esoteric code and MOD400 macro calls so if it
* causes trouble, skip sending attribute packets.
* If the 'func' arg is other than '1' the size is only computed
* for fixed-length record files as variable-length record file
* size estimates are highly inaccurate. If the 'func' arg is '1'
* AND the file 'fname' contains variable length records a 0 is
* returned if the DATA_CODE is unknown and a 1 if it is BINARY.
*
* [FRANK DREANO]
*/
unsigned
fsize(fname, func) char *fname; int func;
{
#define $GIFIL 0x1060 /* --- get file information --- */
struct mcl_psb {
int *reg_b4;
int *reg_b3;
int *reg_b2;
int *reg_b1;
int reg_r7;
int reg_r6;
int reg_r5;
int reg_r4;
int reg_r3;
int reg_r2; } reg;
union cvt_adr {int address[3]; int *adrint; char *adrchar;} adrtag;
struct gifab {
int gfa_lrsz; /* logical record size */
int gfa_bksz; /* block size (bytes/CI for disk files) */
int gfa_find; /* field indicators (# of CIs in file) */
int gfa_dsw1; /* device specific word 1 */
int gfa_dsw2; /* device specific word 2 */
int gfa_isw1; /* init device specific word 1 */
int gfa_isw2; /* init device specific word 2 */
int gfa_rfu [9]; /* reserved - must be zero */
} fab;
# define gfa_cisz gfa_bksz
struct gipsb {
int gipsb_lfn;
int *gipsb_pthp;
int gipsb_dtyp;
int gipsb_lrn;
char gipsb_ftyp;
char gipsb_rtyp;
struct gifab *gipsb_fabp;
unsigned int gipsb_sdid;
int gipsb_resv;
int *gipsb_kdp;
int gipsb_rdsz;
int gipsb_nrf;
} psb;
int i;
int hunds, tens, units;
int path_name[28];
char rec_type; /* Fixed or variable records */
/* float front; */
unsigned lrsz, cisz, cinum, bytesize; /* multiplicative operands */
/* load up required parameters in arg block */
lrsz = cisz = cinum = bytesize = 0;
/* front = 0; */ i = 0;
while (i < 28) path_name[i++] = 0x2020; /* file name inited to blank */
path_name[28] = 0x2020; /* terminate name array */
strcpy(path_name, fname);
strcat(path_name, " "); /* $GIFIL macro needs terminating blank */
psb.gipsb_lfn = 0x2020; /* blank out LFN field */
psb.gipsb_pthp = &path_name[0]; /* load pointer to pathname */
psb.gipsb_fabp = &fab; /* load ptr to file attribs */
psb.gipsb_kdp = 0x000; /* load NULL ptr, field N/A */
/* set-up arg-block for the mcl call */
adrtag.adrint = &psb; /* get char pointer to argument block */
reg.reg_b4 = adrtag.adrint; /* 'dirty' conversion of pointer */
adrtag.adrint = ®.reg_b4; /* get address of B4 register */
i = mcl($GIFIL,adrtag.adrint);
if (i != 0) {
printf("\n\tERRORCODE: %x\n", i);
return(0);
} /* end if */
rec_type = psb.gipsb_rtyp;
/* if arg = 3 get lrsz for >SYSLIB2>EC to determine operating system */
if (func == 3) {
lrsz_6 = fab.gfa_lrsz;
if (debug) fprintf(dfp, "BU lrsz size = %d\n", lrsz_6);
return(0);
}
lrsz = fab.gfa_lrsz;
cisz = fab.gfa_cisz; /* put Fixed-relative CI size in var. */
cinum = fab.gfa_find;
/* determine if a sequential file has DATA_CODE = BINARY attribute */
/* if (debug)
fprintf(dfp,
"\nFSIZE(): File: %s, rec_type: %c, function: %d, data_code: %x\n",
fname, rec_type, func, (psb.gipsb_resv & 0x1000)); */
if ((rec_type != 'F') && (func == 1))
return(psb.gipsb_resv & 0x1000);
/* recompute the CI size to exclude CI & logical record header info */
if (rec_type != 'F') /* dont try var-length SEQ files */
return(0);
cisz = cisz - (((cisz / lrsz) * 4) + 8);
/* compute file size in kilobytes WITHOUT using floating point ops. */
hunds = cisz/100; tens = (cisz - (hunds * 100)) / 10;
units = cisz - (hunds * 100) - (tens * 10);
hunds = hunds * cinum; tens = tens * cinum; units = units * cinum;
bytesize = (hunds + (tens/ 10) + (units / 100)) / 10;
/* front = cisz; front = front / 1024; front = front * cinum;
bytesize = front; */
if (debug ) {
fprintf(dfp, "\n\tThe logical record size is: %u.", lrsz);
fprintf(dfp, "\n\tThe number of data bytes per CI is: %u.", cisz);
fprintf(dfp, "\n\tThe highest numbered file CI is: %u.", cinum);
fprintf(dfp,
"\n\tThe approximate size in kilobytes is: %u.\n", bytesize);
} /* end if */
return(bytesize); /* return size in bytes */
} /* end fsize */
/*
* Kermit checksum routines:
*
* The following three routines are in keeping with 'classic'
* Kermit and are presented worst to best below [FRANK DREANO]
*
*/
/*
* c h k 1 -- compute type-1 Kermit error-checking;
* a 6-bit checksum.
*
*/
chk1(pkt) char *pkt; {
unsigned int chk;
chk = chk2(pkt);
chk = (((chk & 0300) >> 6) + chk) & 077;
return(chk);
} /* end of chk1 */
/*
* c h k 2 -- compute the numeric sum of all bytes in the packet;
* a 12-bit checksum.
*
*/
unsigned
chk2(pkt) unsigned char *pkt; {
long chk;
for (chk = 0; *pkt != '\0'; pkt++)
chk += *pkt;
return(chk & 07777);
} /* end of chk2 */
/*
* c h k 3 -- compute type-3 Kermit checksum;
* a 16-bit cyclic redundancy check.
*
*/
chk3(s) char *s; {
unsigned int c, q;
unsigned long crc = 0;
while ((c = *s++) != '\0') {
c &= 0177; /* strip high bit if any */
q = (crc ^ c) & 017; /* low order nibble */
crc = (crc >> 4) ^ (q * 010201);
q = (crc ^ (c >> 4)) & 017; /* hi order nibble */
crc = (crc >> 4) ^ (q * 010201);
} /* end while */
return(crc);
} /* end chk3 */
/*
* Kermit printing routines:
*
* help - displays command syntax specific to DHS version of Kermit
* usage - print command line options showing proper syntax
* printmsg - like printf with logo prepended
* error - like printmsg if local Kermit; sends error packet if remote
* prerrpkt - print contents of error packet received from remote
*
*/
/*
* h e l p
*
* The next two routines are user help displays for DHS Kermit
*
*/
help()
{
printf("\nSummary of DPS-6 Superkermit:\n");
help1();
printf("\t\t\t\t hit CR for more ");
timoset(30);
while (timflag != 0)
if (cread() != 0)
break;
printf("\nBasic syntax of the \"superkerm\" command is:\n");
usage(); /* exits */
} /* End of help() */
help1()
{
printf("This is a remote receive/send/server Kermit; normally called with\n");
printf(" command line arguments, if not, server mode is assumed.\n");
printf("CRC error checking is always requested, 7-bit ASCII transfers invoked\n");
printf(" by \"a\"-flag, otherwise 8-bit prefixed transfer is the default;\n");
printf(" mapping between LFs and CR/LF pairs is only done for ASCII transfers.\n");
printf("8-bit image mode is invoked by \"i\"-flag; there is NO Connect facility.\n");
printf("Extended packet (up to 2000 bytes) transfers are always available.\n");
printf("Incoming text files will be concatenated to via the \"c\"-flag.\n");
printf("Server mode supports many advanced server commands...see the files\n");
printf(" >SYSLIB1>SUPERKER.DOC and >SYSLIB1>SUPERKER.BWR for details.\n");
printf("If your transfer breaks down, go into connect-mode and enter\n");
printf(" ESCAPE-C, which will cause Superkermit to quit gracefully;\n");
printf(" alternatively enter ESCAPE-H, which will elicit a reassurance.\n");
printf("If debug is requested by \"-D\" flag(s) on second parameter, then\n");
printf(" debug information is written into a file whose name is \n");
printf(" the rest of the second parameter (after last \"D\"); up to three\n");
printf(" \"D\" flags may be entered (but only one \"-\"):\n");
printf("Debug = 1 gives basic trace of automaton states + error-messages,\n");
printf(" = 2 logs packets as sent/received,\n");
printf(" = 3 also logs all chars as read from line, in hex.\n");
return;
} /* End of help1() */
/*
* u s a g e
*
* Tell the user how to invoke Kermit in any mode and quit
*
*/
usage()
{
cooktty();
printf
("Usage: superkerm s[abfic] [-Ddebug-file] file(s) ... (send mode)\n");
printf
("or: superkerm r[abfic] [-Ddebug-file] (receive mode)\n");
printf
("or: superkerm v[abfic] [-Ddebug-file] (server mode)\n");
printf(" where a = ASCII 7-bit file xfer (default),\n");
printf(" b = BINARY file xfer (usually DPS-6 bound-units),\n");
printf(" f = FOREIGN (MSDOS/UNIX) file xfer: *.exe, *.com, etc,\n");
printf(" i = force 8-bit binary-image xfer (no parity allowed!),\n");
printf(" c = concatenate to ASCII files if they already exist,\n\n");
printf(" Wild card xfers (all files ASCII, BINARY or FOREIGN) are legal.\n");
printf(" Under the 4.0 operating system Superkermit will work with the\n");
printf(" VIP3 Terminal Emulator configured for 7-bit 'other host' Kermit\n");
printf(" (NOT Honeywell's Kermit); it can use the ASYNCH1 AP port.\n");
printf(" debug-file is preceded by \"-\" and up to 3 \"D\"-flags.\n");
printf("or: superkerm h (help display).\n");
printf(crlf);
closeall();
exit(0);
} /* End of usage() */
/*
* p r i n t m s g
*
* Print message on standard output if not remote
*
*/
/*VARARGS1*/
printmsg(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
printf("Superkermit: ");
printf(fmt,a1,a2,a3,a4,a5);
printf("\n\r");
return;
} /* End of printmsg() */
/*
* e r r o r
*
* Print error message
* If remote, send an error packet with the message
*
*/
/*VARARGS1*/
error(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
char msg[100];
int len;
sprintf(msg,fmt,a1,a2,a3,a4,a5); /* Make it a string */
len = strlen(msg);
spack('E',n,len,msg); /* Send the error packet */
if (debug) fprintf(dfp,"%s\n",msg);
return;
} /* End of error() */
/*
* p r e r r p k t
*
* Print contents of error packet received from remote Kermit
*
*/
prerrpkt(msg)
char *msg;
{
if (debug) {
fprintf(dfp,
"\nSuperkermit Aborting with following message from local Kermit:");
msg[50] = 0;
fprintf(dfp,"\n \"%s\"",msg);
}
return;
} /* End prerrpkt() */
/********************* END of FILE hd6pri.c **************************/