home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
c
/
umkermit.sou
< prev
next >
Wrap
Text File
|
2020-01-01
|
45KB
|
1,240 lines
* KERMIT FOR U-MAN 1000 UNDER CP/M-68k
* ====================================
*
*
* This is a concatenation of the source files for U-MAN Kermit. Each file
* begins with a line of the form
*
* **** <name> ******.....
*
* where <name> is the name the file should have on the U-MAN discs. End of
* file is marked by a line
*
* **** END OF FILE *****.......
*
**** FILE UMBDOS.S *************************************************************
.globl _bdos
_bdos: move.w 4(sp),d0
move.l 6(sp),d1
trap #2
rts
.globl _bios
_bios: move.w 4(sp),d0
move.l 6(sp),d1
move.l 10(sp),d2
trap #3
rts
.end
**** FILE UMTERM.C *************************************************************
/* This is a very simple terminal program for the UMAN */
main()
{
register long iobyte;
iobyte=bios(19) & ~3; /* Get iobyte */
while (1)
{
iobyte |=1;
bios(20,iobyte); /* Set console device to keyboard */
if (bios(2)) bios(6,(long)readcon()); /* Check for input */
iobyte &= ~3; /* Set console device to serial */
bios(20,iobyte);
if (bios(2)) /* There is a character at serial */
{
iobyte |=1;
bios(20,iobyte);
bios(4,(long)(bios(7)& 0x7f));
}
}
}
readcon()
{
/* This reads the console */
register int c;
c=bios(3); /* Read the keyboard */
if (c!=0x1d) return(c); /* If not CTRL ] */
exit(0);
}
**** FILE UMKERM.C *************************************************************
/*
* K e r m i t File Transfer Utility
*
*/
#include <stdio.h>
/* Symbol Definitions */
#define MAXPACKSIZ 94 /* Maximum packet size */
#define MYPACKSIZ 94 /* My packet size */
#define SOH 1 /* Start of header */
#define CR 13 /* ASCII Carriage Return */
#define SP 32 /* ASCII space */
#define DEL 127 /* Delete (rubout) */
#define ESCCHR '^' /* Default escape character for CONNECT */
#define DEFPAR '\0' /* Default no parity */
#define MAXTRY 10 /* Times to retry a packet */
#define MYQUOTE '#' /* Quote character I will use */
#define MYPAD 0 /* Number of padding characters I will need */
#define MYPCHAR 0 /* Padding character I need (0) */
#define DEFMAXL 80 /* Default packer size */
#define DEFTIME 5 /* Default timeout */
#define DEFPAD 0 /* Default pad characters */
#define DEFPADC 0 /* Default pad character */
#define DEFEOL '\r' /* Default EOL character */
#define DEFQUOTE '#' /* Default QUOTE character */
#define DEFQBIN 'N' /* Default QBIN character */
#define QBIN '&' /* Character for binary quoting */
#define MYEOL '\n' /* End-Of-Line character I need */
#define MYTIME 10 /* Seconds after which I should be timed out */
#define MAXTIM 60 /* Maximum timeout interval */
#define MINTIM 2 /* Minumum timeout interval */
#define TRUE -1 /* Boolean constants */
#define FALSE 0
/* Macro Definitions */
/*
* tochar: converts a control character to a printable one by adding a space.
*
* unchar: undoes tochar.
*
* ctl: converts between control characters and printable characters by
* toggling the control bit (ie. ^A becomes A and A becomes ^A).
*/
#define tochar(ch) ((ch) + ' ')
#define unchar(ch) ((ch) - ' ')
#define ctl(ch) ((ch) ^ 64 )
/* Global Variables */
char version[]="Uman Kermit. Version 0.02\n";
int size, /* Size of present data */
spsiz, /* Maximum send packet size */
pad, /* How much padding to send */
timint, /* Timeout for foreign host on sends */
n, /* Packet number */
numtry, /* Times this packet retried */
oldtry, /* Times previous packet retried */
parity, /* o,e,s,m or 0 */
debug, /* indicates level of debugging output (0=none) */
qflag, /* -1 if doing 8 bit quoting */
filecount; /* Number of files left to send */
char state, /* Present state of the automaton */
padchar, /* Padding character to send */
eol, /* End-Of-Line character to send */
escchr, /* Connect command escape character */
quote, /* Quote character in incoming data */
qbin, /* character for binary quoting */
**filelist, /* List of files to be sent */
*filnam, /* Current file name */
recpkt[MAXPACKSIZ], /* Receive packet buffer */
packet[MAXPACKSIZ]; /* Packet buffer */
FILE *fp,*fopen(); /* File pointer for current disk file */
FILE *fopenb(),*(*kfopen)(); /* jgc dec 25th 1985 */
/*
* m a i n
*
* Main routine - parse command and options, set up the
* tty lines, and dispatch to the appropriate routine.
*/
main(argc,argv)
int argc; /* Character pointers to and count of */
char **argv; /* command line arguments */
{
char *cp; /* char pointer */
int cflg, rflg, sflg; /* flags for CONNECT, RECEIVE, SEND */
printf("%s",version); /* Print out the version number */
if (argc < 2) usage(); /* Make sure there's a command line */
cp = *++argv;
argv++;
argc -= 2; /* Set up pointers to args */
/* Initialize these values */
/* Hope the first packet will get across OK */
eol = CR; /* EOL for outgoing packets */
quote = '#'; /* Standard control-quote char "#" */
pad = 0; /* No padding */
padchar = '\0'; /* Use null if any padding wanted */
timint = DEFTIME ; /* Default timeout */
cflg = sflg = rflg = 0; /* Turn off all parse flags */
/* qflag = FALSE; */ en8quote(FALSE); /* jgc dec 25th. 1985 */
/* and not 8 bit quoting */
escchr = ESCCHR; /* Default escape character */
parity = DEFPAR; /* Default to no parity */
while ((*cp) != NULLPTR) /* Parse characters in first arg. */
switch (*cp++)
{
case 'c': /* C = Connect command */
cflg++;
break;
case 's': /* S = Send command */
sflg++;
break;
case 'r': /* R = Receive command */
rflg++;
break;
case 'd': /* D = Increment debug mode count */
debug++;
break;
case 'p': /* P = Set parity */
parity = *cp++;
if ((parity=='n')||(parity=='N')) parity='\0';
if (!parity) break; /* jgc dec 25th. 1985 */
case 'q': /* q = Do 8 bit quoting */
/* qflag = TRUE; */ en8quote(TRUE); /* jgc dec 25th. 1985 */
break;
}
/* Done parsing */
if ((cflg+sflg+rflg) != 1) usage(); /* Only one command allowed */
/* All set up, now execute the command that was given. */
if (debug)
{
printf("Debugging level = %d\n\n",debug);
if (cflg) printf("Connect command\n\n");
if (sflg) printf("Send command\n\n");
if (rflg) printf("Receive command\n\n");
}
if (cflg) connect(); /* Connect command */
if (sflg) /* Send command */
{
if (argc--) filnam = *argv++; /* Get file to send */
else
{
usage();
}
fp = NULLPTR; /* Indicate no file open yet */
filelist = argv; /* Set up the rest of the file list */
filecount = argc; /* Number of files left to send */
if (sendsw() == FALSE) /* Send the file(s) */
printmsg("Send failed."); /* Report failure */
else /* or */
printmsg("done."); /* success */
}
if (rflg) /* Receive command */
{
if (recsw() == FALSE) /* Receive the file(s) */
printmsg("Receive failed.");
else /* Report failure */
printmsg("done."); /* or success */
}
/* Restore controlling tty's modes */
}
/*
* s e n d s w
*
* Sendsw is the state table switcher for sending files. It loops until
* either it finishes, or an error is encountered. The routines called
* by sendsw are responsible for changing the state.
*
*/
sendsw()
{
char sinit(), sfile(), sdata(), seof(), sbreak();
state = 'S'; /* Send initiate is the start state */
n = 0; /* Initialize message number */
numtry = 0; /* Say no tries yet */
while(TRUE) /* Do this as long as necessary */
{
if (debug) printf("sendsw state: %c\n",state);
switch(state)
{
case 'S':
state = sinit();
break; /* Send-Init */
case 'F':
state = sfile();
break; /* Send-File */
case 'D':
state = sdata();
break; /* Send-Data */
case 'Z':
state = seof();
break; /* Send-End-of-File */
case 'B':
state = sbreak();
break; /* Send-Break */
case 'C':
return (TRUE); /* Complete */
case 'A':
return (FALSE); /* "Abort" */
default:
return (FALSE); /* Unknown, fail */
}
}
}
/*
* s i n i t
*
* Send Initiate: send this host's parameters and get other side's back.
*/
char sinit()
{
int num, len; /* Packet number, length */
/* If too many tries, give up */
if (numtry++ > MAXTRY) return('A');
len = spar(packet); /* Fill up init info packet */
flushinput(); /* Flush pending input */
spack('S',n,len,packet); /* Send an S packet */
switch(rpack(&len,&num,recpkt)) /* What was the reply? */
{
case 'N':
return(state); /* NAK, try it again */
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 */
return('F'); /* OK, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE:
return(state); /* Receive failure, try again */
default:
return('A'); /* Anything else, just "abort" */
}
}
/*
* s f i l e
*
* Send File Header.
*/
char sfile()
{
int num, len; /* Packet number, length */
char filnam1[50], /* Converted file name */
*newfilnam, /* Pointer to file name to send */
*cp; /* char pointer */
/* If too many tries, give up */
if (numtry++ > MAXTRY) return('A');
if (fp == NULLPTR) /* If not already open, */
{
if (debug) printf("\tOpening %s for sending.\n",filnam);
fp = (*kfopen)(filnam,"r"); /* open the file to be sent */
if (fp == NULLPTR) /* If bad file pointer, give up */
{
error("Cannot open file %s",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;
for (cp = newfilnam; *cp != '\0'; cp++)
if (*cp >= 'a' && *cp <= 'z')
*cp ^= 040;
len = (int)(cp - newfilnam); /* Compute length of new filename */
printmsg("Sending %s as %s",filnam,newfilnam);
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, */
/* unless it's NAK for next packet */
num = (--num<0 ? 63:num);
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, stay in F state */
numtry = 0; /* Reset try counter */
n = (n+1)%64; /* Bump packet count */
size = bufill(packet); /* Get first data from file */
return('D'); /* Switch state to D */
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:
return('A'); /* Something else, just "abort" */
}
}
/*
* 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); /* Send a D packet */
switch(rpack(&len,&num,recpkt)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
/* unless it's NAK for next packet */
num = (--num<0 ? 63:num);
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; /* Bump packet count */
if ((size = bufill(packet)) == EOF) /* Get data from file */
return('Z'); /* If EOF set state to that */
return('D'); /* Got data, stay in state D */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE:
return(state); /* Receive failure, stay in D */
default:
return('A'); /* Anything else, "abort" */
}
}
/*
* 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, */
/* unless it's NAK for next packet, */
num = (--num<0 ? 63:num);
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) printf("\tClosing input file %s, ",filnam);
fclose(fp); /* Close the input file */
fp = NULLPTR; /* Set flag indicating no file open */
if (debug) printf("looking for next file...\n");
if (gnxtfl() == FALSE) /* No more files go? */
return('B'); /* if not, break, EOT, all done */
if (debug) printf("\tNew file is %s\n",filnam);
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:
return('A'); /* Something else, "abort" */
}
}
/*
* 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, */
/* unless NAK for previous packet, */
num = (--num<0 ? 63:num);
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(state); /* Receive failure, stay in B */
default:
return ('A'); /* Other, "abort" */
}
}
/*
* r e c s w
*
* This is the state table switcher for receiving files.
*/
recsw()
{
char rinit(), rfile(), rdata(); /* Use these procedures */
state = 'R'; /* Receive-Init is the start state */
n = 0; /* Initialize message number */
numtry = 0; /* Say no tries yet */
while(TRUE)
{
if (debug) printf("\trecsw state: %c\n",state);
switch(state) /* Do until done */
{
case 'R':
state = rinit();
break; /* Receive-Init */
case 'F':
state = rfile();
break; /* Receive-File */
case 'D':
state = rdata();
break; /* Receive-Data */
case 'C':
return(TRUE); /* Complete state */
case 'A':
return(FALSE); /* "Abort" state */
}
}
}
/*
* r i n i t
*
* Receive Initialization
*/
char rinit()
{
int len, num; /* Packet length, number */
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); /* Get the other side's init data */
len = spar(packet); /* Fill up packet with my init info */
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 */
return('F'); /* Enter File-Receive state */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: /* Didn't get packet */
spack('N',n,0,NULLPTR); /* Return a NAK */
return(state); /* Keep trying */
default:
return('A'); /* Some other packet type, "abort" */
}
}
/*
* 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 too many tries "abort" */
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
{ /* Yes, ACK it again with */
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,NULLPTR);
numtry = 0;
return(state); /* Stay in this state */
}
else return('A'); /* Not previous packet, "abort" */
case 'F': /* File Header (just what we want) */
/* The packet number must be right */
if (num != n) return('A');
strcpy(filnam1, packet); /* Copy the file name */
if ((fp=(*kfopen)(filnam1,"w"))==NULLPTR) /* Try to open a new file */
{ /* Give up if can't */
error("Cannot create %s",filnam1);
return('A');
}
else /* OK, give message */
printmsg("Receiving %s as %s",packet,filnam1);
spack('Y',n,0,NULLPTR); /* 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,NULLPTR); /* Say OK */
return('C'); /* Go to complete state */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: /* Didn't get packet */
spack('N',n,0,NULLPTR); /* Return a NAK */
return(state); /* Keep trying */
default:
return ('A'); /* Some other packet, "abort" */
}
}
/*
* r d a t a
*
* Receive Data
*/
char rdata()
{
int num, len; /* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
switch(rpack(&len,&num,packet)) /* Get packet */
{
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))
{ /* Else check previous packet again? */
spack('Y',num,0,NULLPTR); /* 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 */
bufemp(packet,len); /* Write the data to the file */
spack('Y',n,0,NULLPTR); /* Acknowledge the packet */
oldtry = numtry; /* Reset the try counters */
numtry = 0; /* ... */
n = (n+1)%64; /* Bump packet number, mod 64 */
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,NULLPTR); /* 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 */
/* Must have right packet number */
if (num != n) return('A');
spack('Y',n,0,NULLPTR); /* OK, ACK it. */
fclose(fp); /* Close the file */
n = (n+1)%64; /* Bump packet number */
return('F'); /* Go back to Receive File state */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case FALSE: /* Didn't get packet */
spack('N',n,0,NULLPTR); /* Return a NAK */
return(state); /* Keep trying */
default:
return('A'); /* Some other packet, "abort" */
}
}
/*
* c o n n e c t
*
* Establish a virtual terminal connection with the remote host, over an
* assigned tty line.
*/
connect()
{
/* This routine assumes that iobyte has been fully implemented */
/* so that the program can check for input at the serial port. */
/* It assumes that the normal keyboard is the CRT: device. */
/* and the serial port is the TTY: device */
/* This routine is the one most likely to need changing for other machines */
register long iobyte;
iobyte=bios(19) & ~3;
printf("Connected\n");
while (1)
{
iobyte |=1;
bios(20,iobyte); /* Set console device to keyboard */
/* Check for console input */
if (bios(2)) readcon();
iobyte &= ~3; /* Set console device to serial */
bios(20,iobyte);
if (bios(2))
{
iobyte |=1;
bios(20,iobyte);
bios(4,(long)(bios(7)& 0x7f));
}
}
}
readcon()
{
/* This reads the console */
register int c;
c=bios(3); /* Read the keyboard */
if (c!=0x1d) sendaux(c); /* If not CTRL ] */
else exit(0);
}
/*
* KERMIT utilities.
*/
/*
* s p a c k
*
* Send a Packet
*/
spack(type,num,len,data)
char type, *data;
int num, len;
{
int i; /* Character loop counter */
char chksum, buffer[100]; /* Checksum, packet buffer */
register char *bufp; /* Buffer pointer */
if (debug>1) /* Display outgoing packet */
{ /* Null-terminate data to print it */
if (data != NULLPTR) data[len] = '\0';
printf("\tspack type: %c\n",type);
printf("\t\tnum: %d\n",num);
printf("\t\tlen: %d\n",len);
if (data != NULLPTR)
printf("\tdata: \"%s\"\n",data);
}
bufp = buffer; /* Set up buffer pointer */
for (i=1; i<=pad; i++) sendaux(padchar); /* Issue any padding */
*bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */
*bufp++ = tochar(len+3); /* Send the character count */
chksum = tochar(len+3); /* Initialize the checksum */
*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]; /* Get 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 = eol; /* Extra-packet line terminator */
sauxstr( buffer,(int)(bufp-buffer+1)); /* Send the packet */
}
/*
* r p a c k
*
* Read a Packet
*/
rpack(len,num,data)
int *len, *num; /* Packet length, number */
char *data; /* Packet data */
{
int i, done; /* Data character number, loop exit */
char t, /* Current input character */
type, /* Packet type */
cchksum, /* Our (computed) checksum */
rchksum; /* Checksum received from other host */
do
{
t=readaux()& 0x7f;
}while (t != SOH); /* Wait for packet header */
done = FALSE; /* Got SOH, init loop */
while (!done) /* Loop to get a packet */
{
t=readaux(); /* Get character */
if (t == SOH) continue; /* Resynchronize if SOH */
cchksum = t; /* Start the checksum */
*len = unchar(t)-3; /* Character count */
t=readaux(); /* Get character */
if (t == SOH) continue; /* Resynchronize if SOH */
cchksum += t; /* Update checksum */
*num = unchar(t); /* Packet number */
t=readaux(); /* Get character */
if (t == SOH) continue; /* Resynchronize if SOH */
cchksum += t; /* Update checksum */
type = t; /* Packet type */
for (i=0; i<*len; i++) /* The data itself, if any */
{ /* Loop for character count */
t=readaux(); /* Get character */
if (t == SOH) continue; /* Resynch if SOH */
cchksum += t; /* Update checksum */
data[i] = t; /* Put it in the data buffer */
}
data[*len] = 0; /* Mark the end of the data */
t=readaux(); /* Get last character (checksum) */
rchksum = unchar(t); /* Convert to numeric */
t=readaux(); /* get EOL character and toss it */
if (t == SOH) continue; /* Resynchronize if SOH */
done = TRUE; /* Got checksum, done */
}
if (debug>1) /* Display incoming packet */
{
data[*len] = '\0'; /* Null-terminate data to print it */
printf("\trpack type: %c\n",type);
printf("\t\tnum: %d\n",*num);
printf("\t\tlen: %d\n",*len);
printf("\tdata: \"%s\"\n",data);
}
/* Fold in bits 7,8 to compute */
cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */
if (cchksum != rchksum) return(FALSE);
return(type); /* All OK, return packet type */
}
/*
* b u f i l l
*
* Get a bufferful of data from the file that's being sent.
* Only control-quoting and 8-bit quoting is done;
* repeat count prefixes are not handled.
*/
bufill(buffer)
char buffer[]; /* Buffer */
{
register int t; /* Char read from file */
register char t7; /* 7-bit version of above */
register char *buffend; /* End of buffer pointer */
register char *buffp; /* Pointer into buffer */
register int unprintable; /* Is a character printable ?*/
buffend = &buffer[spsiz-9]; /* set up end of buffer pointer */
buffp=buffer; /* and the current position */
while((t = getc(fp)) != EOF) /* Get the next character */
{
t7 = t & 0177; /* Get low order 7 bits */
/* If doing 8-bit quoting, then quote if needed */
if ((t != t7) && qflag) *buffp++ = qbin;
unprintable = ((t7<SP)||(t7==DEL));
/* Does this char require special handling? */
if ((unprintable) || t7==quote ||(qflag && (t7==qbin)))
{
*buffp++ = quote; /* Quote the character */
if (unprintable)
{ /* will be printable if a quote char */
t = ctl(t); /* and uncontrolify */
t7 = ctl(t7);
}
}
*buffp++ = t;
/* Check length */
if (buffp >=buffend) return((int)(buffp-buffer));
}
if (buffp == buffer) return(EOF); /* Wind up here only on EOF */
return((int)(buffp - buffer)); /* Handle partial buffer */
}
/*
* b u f e m p
*
* Put data from an incoming packet into a file.
*/
bufemp(buffer,len)
char buffer[]; /* Buffer */
int len; /* Length */
{
register int i; /* Counter */
register char t; /* Character holder */
register int highbit; /* place to hold quoted highbit */
highbit = 0;
for (i=0; i<len; i++) /* Loop thru the data field */
{
t = buffer[i]; /* Get a character */
/* If doing 8-bit quoting and this is such a quote
then note it */
if (qflag && (t==qbin)) {
highbit = 0x80;
t=buffer[++i];
}
if (t == MYQUOTE) /* Control quote? */
{ /* Yes */
t = buffer[++i]; /* Get the quoted character */
/* Low order bits match quote char? */
if (((t & 0177) != MYQUOTE) &&
(!qflag || ((t & 0x7F)!=qbin)))
t = ctl(t); /* No, uncontrollify it */
}
t |= highbit; /* set top bit if needed */
highbit=0;
putc(t,fp);
}
}
/*
* g n x t f l
*
* Get next file in a file group
*/
gnxtfl()
{
filnam = *(filelist++);
if (filecount-- == 0) return FALSE; /* If no more, fail */
else return TRUE; /* else succeed */
}
/*
* s p a r
*
* Fill the data array with my send-init parameters
*
*/
int
spar(data)
char data[];
{
data[0] = tochar(MYPACKSIZ); /* 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 */
data[6] = qflag?QBIN:'Y'; /* Request 8 bit quoting */
return (7); /* return number of parameters */
}
/* r p a r
*
* Get the other host's send-init parameters
*
*/
rpar(data,len)
char data[];
int len;
{
spsiz = DEFMAXL; /* default packet size */
timint = DEFTIME;
pad = DEFPAD;
padchar = DEFPADC;
eol = DEFEOL;
quote = DEFQUOTE;
qbin = DEFQBIN;
switch (len){
default:
case 10: /* attributes */
case 9: /* repeat count */
case 8: /* Check type */
case 7: /* 8 bit quoting */
qbin = data[6];
if (((qbin >='!') && (qbin <= '>'))
|| ((qbin >= '`')&&(qbin <= '~')))
/* qflag = TRUE; */ en8quote(TRUE); /* jgc dec 25th. 1985 */
case 6: /* Incoming data quote character */
quote = data[5];
case 5: /* EOL character I must send */
eol = unchar(data[4]);
case 4: /* Padding character I must send */
padchar = ctl(data[3]);
case 3: /* Number of pads to send */
pad = unchar(data[2]);
case 2: /* When I should time out */
timint = unchar(data[1]);
if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME;
case 1: /* Maximum send packet size */
spsiz = unchar(data[0]);
case 0:
break;
}
if (qflag) {
if (qbin == 'N') error("Can't do 8 bit quoting\n");
else if (qbin == 'Y') qbin = QBIN;
}
}
int
readaux()
{
int c;
c=bios(7);
if (parity) c &= 0x7f;
return (c);
}
sauxstr(buf,len)
char *buf;
int len;
{
for(;len>0;len--)
sendaux(*buf++);
}
sendaux(c)
int c;
{
/* A table giving even parity, used also to get odd parity */
static char partab[128]={
0x00,0x81,0x82,0x03,0x84,0x05,0x06,0x87,
0x88,0x09,0x0A,0x8B,0x0C,0x8D,0x8E,0x0F,
0x90,0x11,0x12,0x93,0x14,0x95,0x96,0x17,
0x18,0x99,0x9A,0x1B,0x9C,0x1D,0x1E,0x9F,
0xA0,0x21,0x22,0xA3,0x24,0xA5,0xA6,0x27,
0x28,0xA9,0xAA,0x2B,0xAC,0x2D,0x2E,0xAF,
0x30,0xB1,0xB2,0x33,0xB4,0x35,0x36,0xB7,
0xB8,0x39,0x3A,0xBB,0x3C,0xBD,0xBE,0x3F,
0xC0,0x41,0x42,0xC3,0x44,0xC5,0xC6,0x47,
0x48,0xC9,0xCA,0x4B,0xCC,0x4D,0x4E,0xCF,
0x50,0xD1,0xD2,0x53,0xD4,0x55,0x56,0xD7,
0xD8,0x59,0x5A,0xDB,0x5C,0xDD,0xDE,0x5F,
0x60,0xE1,0xE2,0x63,0xE4,0x65,0x66,0xE7,
0xE8,0x69,0x6A,0xEB,0x6C,0xED,0xEE,0x6F,
0xF0,0x71,0x72,0xF3,0x74,0xF5,0xF6,0x77,
0x78,0xF9,0xFA,0x7B,0xFC,0x7D,0x7E,0xFF
};
if (parity)
{
c &= 0x7f;
switch(parity)
{
case 'o':
case 'O':
c=partab[c] ^ 0x80;
break;
case 'e':
case 'E':
c=partab[c];
break;
case 'm':
case 'M':
c |= 0x80;
break;
/* Otherwise assume space parity */
}
}
bios(6,(long)c); /* Send character */
}
/*
* f l u s h i n p u t
*
* Dump all pending input to clear stacked up NACK's.
* (Implemented only for Berkeley Unix at this time).
*/
flushinput() /* Null version for non-Berkeley Unix */
{
}
/*
* Kermit printing routines:
*
* usage - print command line options showing proper syntax
* printmsg - like printf with "Kermit: " prepended
* error - like printmsg
* prerrpkt - print contents of error packet received from remote host
*/
/*
* u s a g e
*
* Print summary of usage info and quit
*/
usage()
{
printf("Usage: kermit c[p[msoeN]]\t\t(connect mode)\n");
printf("or:\tkermit s[dqp[msoeN]] file ...\t\t(send mode)\n");
printf("or:\tkermit r[dqp[msoeN]]\t\t\t(receive mode)\n");
exit(1);
}
/*
* 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("Kermit: ");
printf(fmt,a1,a2,a3,a4,a5);
printf("\n");
fflush(stdout); /* force output (UTS needs it) */
}
/*
* e r r o r
*
* Print error message.
*
* If local, print error message with printmsg.
* If remote, send an error packet with the message.
*/
/*VARARGS1*/
error(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
printmsg(fmt, a1, a2, a3, a4, a5);
}
/*
* p r e r r p k t
*
* Print contents of error packet received from remote host.
*/
prerrpkt(msg)
char *msg;
{
printf("Kermit aborting with following error from remote host:\n%s\n",
msg);
return;
}
en8quote(t) int t; { /* jgc dec 25th. 1985 */
if (qflag = t) kfopen = fopenb; /* jgc dec 25th. 1985 */
else kfopen = fopen; /* jgc dec 25th. 1985 */
} /* jgc dec 25th. 1985 */
} /* jgc dec
**** END OF FILE ***************************************************************