home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
victor9000.tar.gz
/
victor9000.tar
/
vickermit.c
next >
Wrap
Text File
|
1991-04-18
|
54KB
|
2,055 lines
/************************************************************************
* *
* VICTOR VERSION 1.0 *
* *
*************************************************************************/
/************************************************************************
* *
* KERMIT *
* *
* This implementation is based on the sample implementation *
* supplied in chapter 2 of the Kermit Protocol Manual. This *
* version of Kermit was code (copied) and augmented (my own *
* ideas) by: *
* W. Hertha *
* Victor Technologies (Canada) Ltd. *
* 55 Savage Drive *
* Cambridge, Ontario, Canada *
* N1R 5T1 *
* *
* Thanks are in order to Dr. Joe Angel of the University of *
* Saskatchewan for taking care of all the details of getting *
* the code and documentation, and providing a DEC TOPS 20 *
* system to "talk" to and his efforts in the debugging of *
* this product. *
* *
*************************************************************************
* *
* This implementation is missing (or varies in)the following *
* - The SET command is implemented using softkeys *
* - Only ASCII files may be transmitted *
* - Server functions are not implemented *
* - There is limited massaging of the file name supplied by the host *
* thus hosts with weird naming conventions may cause problems on a *
* receive *
* *
*************************************************************************/
/************************************************************************
* *
* Coding Conventions *
* *
* This is a list of conventions *
* [1] All #define names are capitalised *
* [2] All global variables have the first character capitalised *
* [3] Local variables, function names are in lower case *
* [4] Other than a module prolog, in-line commenting is limited *
* *
*************************************************************************/
/************************************************************************
* *
* System dependancies *
* *
* An attempt has been made to reduce system dependancies. The areas *
* which are system dependant are as follows: *
* 1. Serial port interfaceing *
* 2. CRT display interfaceing *
* 3. File system (MS-DOS file naming conventions) *
* *
* Serial Port Interface *
* In order to reduce the effects, all interfaceing to the serial port *
* is done through a series of routines grouped together towards the *
* end of the listing. *
* *
* CRT display interface *
* Here also most of the interfaces to the display is performed by *
* low level routine. In fact many are actually just defines. Defines *
* where used so that systems that do not support VT-52 escape sequences *
* may replace these with functions. It is worth while to note the *
* following features of the display (further information may be found *
* in the Operators Reference Guide or the Supplemental Technical *
* Reference material). *
* 1. Screen addressing is 1 relative, that is HOME is (1,1) *
* *
*************************************************************************/
#include "stdio.h"
#define MAXPACK 94 /* Maximum Packet Size */
#define SOH '\001' /* Start of header */
#define SP ' ' /* Space */
#define CR '\015' /* Carriage Return */
#define LF '\012' /* Line feed */
#define BEL '\007' /* Bell */
#define BS '\010' /* Back Space */
#define DEL '\177' /* Delete (Rubout) */
#define REQCAN '?'
#define MAXTRY 5 /* # of times to retry a package */
#define MYQUOTE '#' /* Quote Character used Locally */
#define MYPAD 0 /* Number of Padding characters */
#define MYPCHAR 0 /* Local padding character */
#define MYEOL CR /* Local End-Of-Line character */
#define MYTIME 10 /* Local time out time in seconds */
#define PORTA 0 /* Code for port A */
#define PORTB 1 /* Code for Port B */
#define CR2 2 /* Code for control register 2 */
#define CR3 3
#define CR4 4
#define CR5 5
#define RX 1 /* Receive character available */
#define TX 4 /* Send buffer empty */
#define DCD 8 /* Data Carrier Detect */
#define SEND 1 /* Sending mode code */
#define RECEIVE 2 /* Receiving mode code */
#define STATUS_LINE 25 /* Line number of status line on CRT */
#define SHOW_BASE 5 /* Starting line of "Show" data */
#define POS_MAXPACK 0+SHOW_BASE
#define POS_MYPCHAR 1+SHOW_BASE
#define POS_MYPAD 2+SHOW_BASE
#define POS_MYTIME 3+SHOW_BASE
#define POS_MYEOL 4+SHOW_BASE
#define POS_MYQUOTE 5+SHOW_BASE
#define POS_WARN 6+SHOW_BASE
#define POS_ECHO 7+SHOW_BASE
#define POS_BAUD 8+SHOW_BASE
#define POS_BREAK 9+SHOW_BASE
#define POS_PORT 10+SHOW_BASE
#define ENDFIL '\034' /* End of Logical file */
#define ENDSEC '\035' /* End of help message section */
#define ENDPAG '\037' /* End of page */
#define ENDSS '\003' /* End of subsection */
#define ENQUIRE '\005' /* Enquirey during help */
#define ROOT_H 1 /* Root help */
#define SET_H 2
#define ON_H 3
#define ECHO_H 4
#define WARN_H 5
#define BAUD_H 6
#define TRACE_H 7
#define GETCP_H 8
#define tochar(ch) (char) (ch + ' ')
#define unchar(ch) (ch - ' ')
#define ctl(ch) ((ch ^ 64) & 0x0ff)
/************************************************************************
* Get character from keyboard but do not echo
*/
#define getnec() (bdos(7) & 0x0ff)
/************************************************************************
* Get keyboard status
*/
#define getkbs() (bdos(11) & 0x0ff)
/************************************************************************
* Clear keyboard buffer
*/
#define clrkb() for (;getkbs();getnec())
/************************************************************************
* Get MSDOS Version ID
*/
#define dosid() ((bdos(30) >> 8) & 0x0ff)
/************************************************************************
* Put a string to standard output
*/
#define putstr(str) puts(str,stdout)
/************************************************************************
* Put a string in inverse video to standard output
*/
#define putistr(str) printf("\033p%s\033q",str)
/************************************************************************
* Put out a menu on the 25th line
*/
#define putmenu(str) printf("\033j\033x1\033Y8 \033K%s\033y1\033k",str)
/************************************************************************
* Turn on the cursor
*/
#define cursr_on() puts("\033y5",stdout)
/************************************************************************
* Turn off cursor
*/
#define cursr_off() puts("\033x5",stdout)
/************************************************************************
* Clear to end of line X starting at column Y
*/
#define clear_eol(x,y) printf("\033Y%c%c\033K",x+31,y+31)
/************************************************************************
* Clear the screen
*/
#define clear_screen() puts("\033E",stdout)
/************************************************************************
* Move the cursor to home position
*/
#define home() puts("\033H",stdout)
/************************************************************************
* Position cursor at row X, column Y
*/
#define pos(x,y) printf("\033Y%c%c",x+31,y+31)
/************************************************************************
* Position cursor at row X, column Y and output character ch
*/
#define plotc(x,y,ch) printf("\033Y%c%c%c",x+31,y+31,ch)
/************************************************************************
* Position cursor at row X, column Y and output inverse video character ch
*/
#define plotic(x,y,ch) printf("\033Y%c%c\033p%c\033q",x+31,y+31,ch)
/************************************************************************
* Position cursor at row X, column Y and output decimal (integer) number
*/
#define plotd(x,y,n) printf("\033Y%c%c%d",x+31,y+31,n)
/************************************************************************
* Position cursor at row X, column Y and output Unsigned long
*/
#define plotU(x,y,n) printf("\033Y%c%c%U",x+31,y+31,n)
/************************************************************************
* Position cursor at row X, column Y and output string s
*/
#define plotstr(x,y,str) printf("\033Y%c%c%s",x+31,y+31,str)
/************************************************************************
* Position cursor at row X, column Y and output inverse video string s
*/
#define plotistr(x,y,str) printf("\033Y%c%c\033p%s\033q",x+31,y+31,str)
/************************************************************************
* Position cursor at row X, column Y and output inverse video string s
*/
#define plotustr(x,y,str) printf("\033Y%c%c\0330%s\0331",x+31,y+31,str)
/************************************************************************
* Check status of port
*/
#define sstatus(s,p) (peek(p+2,0x0e004) & s)
/**/
/************************************************************************
* *
* Defintion of Global Variables *
* *
*************************************************************************/
typedef struct {
int si; /* Position in (send)trace buffer */
int smnum[256]; /* (Send) message number */
char smtype[256]; /* (Send) message type */
int ri; /* Position in (receive) trace buffer */
int rmnum[256]; /* (Receive) message number */
char rmtype[256]; /* (Receive) message type */
} TRACE_BUF;
TRACE_BUF
Trace;
int
Size, /* Size of Present data */
N, /* Message Number */
Rpsiz, /* Maximum Receive packet size */
Spsiz, /* Maximum Send Packet Size */
Pad, /* How much padding to send */
Timint, /* Time out for remote host */
Numtry, /* Number of retries for a package */
Oldtry; /* Times Previous package retried */
char
State, /* Present state of the automaton */
Padchar, /* Padding character to send */
Eol, /* End-of-line character to send */
Quote, /* Quote character in in-coming data */
Filnam[50], /* The file name */
Recpkt[MAXPACK], /* Receive packet buffer */
Packet[MAXPACK]; /* Packet buffer */
int
Mypad = MYPAD,
Mytime = MYTIME,
Maxpack = MAXPACK;
char
Break = '\03', /* Break code for DEC */
Mydel = DEL,
Mypchar = MYPCHAR,
Myquote = MYQUOTE,
Myeol = MYEOL;
int
Msdos20 = FALSE, /* Operating system */
Display = FALSE, /* Display data as it is transmitted */
Echo = FALSE, /* Local Echo ON */
Warn = TRUE, /* File warning */
Port = PORTA, /* Serial Port to perform I/O */
Speed = B1200; /* Baud Rate */
unsigned char
Rate[] ={4,1, /* 300 baud */
0x082,0, /* 600 baud */
0x041,0, /* 1200 baud */
0x020,0, /* 2400 baud */
0x010,0, /* 4800 baud */
0x008,0 }, /* 9600 baud */
cr2[2] = {0x10, 0x10},
cr3[2] = {0xe1, 0xe1},
cr4[2] = {0x44, 0x44},
cr5[2] = {0xea, 0xea};
FILE *Fptr; /* File pointer */
unsigned long int
Nch, /* Number of characters transmitted */
Nmess; /* Number of messages(Packetes) transmitted */
jmp_buf escape; /* Define environment of Longjump */
int Msem; /* Message semaphore */
/**/
/************************************************************************
* *
* MESSAGES *
* *
*************************************************************************/
char *Pa[] = {
"Packet Size",
"Padding Character",
"Number of Padding characters",
"Time out (seconds)",
"End of Line character",
"Quote Character",
"File Warning",
"Local Echo",
"Baud Rate",
"Break Character",
"Port"};
char *Ba[] = {
"300 Baud ",
"600 Baud ",
"1200 Baud",
"2400 Baud",
"4800 Baud",
"9600 Baud"};
char Startms[] ="\033w\033H\033E\033i1";
char Endms[] ="\033H\033z";
char Sys_id[] ="KERMIT VICTOR 9000 ";
char Root_m[] ="\033p1 EXIT \033q \033p2 SEND \033q\
\033p3 RECEIVE\033q \033p4 SET \033q \033p5 SHOW \033q\
\033p6 TRACE \033q \033p7 HELP \033q \033p8 EXEC \033q";
char Set_m[] ="\033p1 BAUD \033q \033p2 ECHO \033q\
\033p3 WARNING\033q \033p4 PARAMS.\033q \033p5 \033q\
\033p6 RETURN \033q \033p7 HELP \033q";
char Onoff_m[] ="\033p1 YES \033q \033p2 NO \033q\
\033p \033q \033p \033q \033p \033q\
\033p6 RETURN \033q \033p7 HELP \033q";
char Baud_m[] ="\033p1 300 \033q \033p2 600 \033q\
\033p3 1200 \033q \033p4 2400 \033q \033p5 4800 \033q\
\033p6 9600 \033q \033p7 HELP \033q";
char Show_m[] ="\033p Hit <RETURN> to continue\033q";
char Help_m[] ="\033p Hit <RETURN> to continue\033q";
char Trace_m[] ="\033p1 PAGE \033q \033p2 NEXT \033q\
\033p3 PREV. \033q \033p4 \033q \033p5 \033q\
\033p6 RETURN \033q \033p7 HELP \033q";
char Parm_m[] =" ";
char Getcp_m[] ="\033p1 ENTER \033q \033p2NUMERIC \033q\
\033p3 \033q \033p4 \033q \033p5 \033q\
\033p6 \033q \033p7 HELP \033q";
char Getnp_m[] ="\033p Hit <RETURN> to enter \033q";
/**/
/************************************************************************
* *
* MAIN LINE OF KERMIT *
* *
*************************************************************************/
main(){
int i,j;
putstr(Startms);
for (i=80,j=strlen(Sys_id)+81; i > 30; --i, --j){
plotstr(5,i,Sys_id);
clear_eol(5,j);
}
portopen(PORTA,Speed);
Msdos20 = (dosid() >= 2)?TRUE: FALSE;
termem();
putstr(Endms);
}
portopen(port,baud)
int port;
{
Port = port;
portinit(port);
sbaud(baud,port);
if (sstatus(DCD,port))
putstr("\n\n\nConnection to host established\n");
else{
putchar(BEL);
putstr("\n\n\nConnection to host NOT established\n");
}
}
/**/
/************************************************************************
* *
* THE PROTOCOL *
* *
*************************************************************************/
/************************************************************************
* *
* Module: send *
* Purpose: To set up environment to perform a file send *
* Interface: send() *
* Parameters: None *
* Globals: Filnam (char[]): File name(s) to send *
* *
*************************************************************************/
send()
{
while (TRUE){
Nmess = 0;
Nch = 0;
putmenu("Name of file to Send: ");
Size = getln(Filnam);
minit("SEND FILE",Filnam);
if (sendsw() == TRUE){
clrkb();
putmenu("File transfer complete Do you wish to Send more files (y/n): ");
switch (getnec()){
case 'N':
case 'n': return;
}
}else{ /* An error occurred */
clrkb();
putmenu("ERROR DURING FILE TRANSFER (A)bort or (C)ontinue");
switch(getnec()){
case 'A':
case 'a': return;
}
}
}
}
/************************************************************************
* *
* Module: sendsw *
* Purpose: To maintain the file sending sub-automoton *
* Interface: sendsw() *
* Parameters: None *
* Globals: State (char): State of machine *
* Numtry (int): Number of retries *
* *
*************************************************************************/
sendsw()
{
char sinit(), sfile(), sdata(), seof(), sbreak();
State = 'S'; /* Initialise to start state */
N = 0; /* Initialise message number */
Numtry = 0; /* Initialise Number of trys */
setjmp (escape); /* Return here if time out */
while (TRUE){
switch (State){
case 'D': State = sdata();
break;
case 'F': State = sfile();
break;
case 'Z': State = seof();
break;
case 'S': State = sinit();
break;
case 'B': State = sbreak();
break;
case 'C': return(TRUE);
case 'A': return(FALSE);
default: return(FALSE);
}
}
}
/************************************************************************
* *
* Module: sinit() *
* Purpose: To initialise connection with the host. *
* Interface: sinit() *
* Parameters: *
* Input: None *
* Output: Through function name (char) *
* Globals: *
* Eol (char): End of line character for host *
* Quote (char): Quote character for host *
* Numtry (int): Number of attempts/retries to contact *
* the host. *
* Packet (char[]): Packet to be sent *
* Recpkt (char[]): Packet received from host *
* N (int): Message number *
* Fptr (->FILE): Pointer to file *
* *
*************************************************************************/
char sinit()
{
int num,
len;
FILE *fopen();
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries exceeded - INIT"));
spar(Packet); /* Setup packet for host */
spack('S',N,6,Packet); /* Send it to the host */
switch (rpack(&len,&num,Recpkt)){
case 'N': if (N != num--)
return(State);
case 'Y': if (N != num)
return(State);
rpar(Recpkt); /* Get the initialisation info */
if (Eol == 0)
Eol = '\n';
if (Quote == 0)
Quote = '#';
Numtry = 0;
Nch = 0;
Nmess = 0;
N = (N + 1) % 64;
return( ((Fptr=fopen(Filnam,"rb")) == 0)?
abort("Unable to open file"):
'F' /* Ok- File opened */
);
case FALSE:
return(State);
case 'E': return (abort(Recpkt));
default: return(abort("Unexpected response - INIT"));
}
}
/************************************************************************
* *
* Module: sfile *
* Purpose: To send file name to host *
* Interface: sfile() *
* Parameters: *
* Input: None *
* Output: Through function name (char): *
* Globals: *
* Numtry (int): number of trys *
* Filnam (char[]): File name to send *
* N (int): Message number *
* Recpkt (char[]): Received packet *
* Packet (char[]): Packet to send *
* Size (int): Size of data sent from host *
* *
*************************************************************************/
char sfile()
{
int num,
len;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - SEND FILE"));
for (len=0; Filnam[len] != '\0'; len++); /* get length of name */
len++;
spack('F',N,len,Filnam);
switch (rpack(&len,&num,Recpkt)){
case 'N': if (N != num--)
return(State);
case 'Y': if (N != num)
return(State);
Numtry = 0;
N = (N + 1) % 64;
Size = bufill(Packet);
return('D');
case FALSE:
return(State);
case 'E': return(abort(Recpkt));
default: return(abort("Unexpected response - SEND FILE"));
}
}
/************************************************************************
* *
* Module: sdata *
* Purpose: To send data to the host (generally file contents) *
* Interface: sdata() *
* Parameters: *
* Input: None *
* Output: Through function name (char): *
* Globals: *
* Numtry (int): Number of tries *
* Packet (char[]): packet data sent to host *
* Recpkt (char[]): Packet sent from host *
* N (int): Message number *
* Size (int): Size of packet (amount of data) received *
* *
*************************************************************************/
char sdata()
{
int num,
len;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - SEND DATA"));
spack('D',N,Size,Packet);
switch(rpack(&len,&num,Recpkt)){
case 'N': if (N != num--)
return(State);
case 'Y': if (N != num)
return(State);
Nch += Size;
Numtry = 0;
N = (N + 1) % 64;
return (((Size = bufill(Packet)) == EOF)?
'Z':
'D'
);
case FALSE:
return(State);
case 'E': return(abort(Recpkt));
default: return(abort("Unexpected response - SEND DATA"));
}
}
/************************************************************************
* *
* Module: seof *
* Purpose: To send an EOF Packet *
* Interface: seof() *
* Parameters: *
* Input: None *
* Ouptut: Through function name (char) *
* Globals: *
* Numtry (int): Number of tries *
* Packet (char[]): Packet *
* *
*************************************************************************/
char seof()
{
int num,
len;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - SEND EOF"));
spack('Z',N,0,Packet);
switch (rpack(&len,&num,Recpkt)){
case 'N': if (N != num--)
return(State);
case 'Y': if (N != num)
return(State);
Numtry = 0;
N = (N + 1) % 64;
return ((gnxtfl() == EOF)?'B':'F');
case FALSE:
return(State);
case 'E': return(abort(Recpkt));
default: return(abort("Unexpected response - SEND EOF"));
}
}
/************************************************************************
* *
* Module: sbreak *
* Purpose: To send a break (end of transmission) package *
* Interface: sbreak() *
* *
*************************************************************************/
char sbreak()
{
int num,
len;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - SEND EOT"));
spack('B',N,0,Packet);
switch(rpack(&len,&num,Recpkt)){
case 'N': if (N != num--)
return(State);
case 'Y': if (N != num)
return(State);
Numtry = 0;
N = (N + 1) % 64;
return('C');
case FALSE:
return(State);
case 'E': return(abort(Recpkt));
default: return(abort("Unexpected response - SEND EOT"));
}
}
/************************************************************************
* *
* Module: spack *
* Purpose: To assemble and send out the supplied Package *
* Interface: spack(type,num,len,data) *
* Input: type (char): Type of package *
* num (int): Message number *
* len (int): Size (length) of massage data *
* data (char[]): Data to be packaged *
* Output: None *
* *
************************************************************************/
spack(type,num,len,data)
char type,data[];
int num,len;
{
int i,
chksum;
char abort();
if (getkbs() && (getnec() == REQCAN)){
State = abort("Message Break");
longjmp(escape);
}
plotc(9,66,'S');
prpack(SEND,len,num,type,data);
for (i=1; i <= Pad; i++)
sputc(Padchar,Port);
sputc(SOH,Port);
chksum = tochar(len+3);
sputc(tochar(len+3),Port);
chksum += tochar(num);
sputc(tochar(num),Port);
chksum += type;
sputc(type,Port);
for (i=0; i < len; i++){
sputc(data[i],Port);
chksum += data[i] & 0x0ff; /* Prevent Sign extension */
}
chksum = (chksum + ((chksum & 192) /64)) & 63;
sputc(tochar(chksum),Port);
sputc(Eol,Port);
Trace.smtype[Trace.si] = type;
Trace.smnum[Trace.si] = num;
if (++Trace.si > 255)
Trace.si = 0;
Nmess++;
plotc(9,66,'W');
}
/************************************************************************
* *
* Module: rpack *
* Purpose: To wait for the receipt of a package *
* Interface: rpack(len,num,data) *
* Input: len (int): Length of message (data portion) *
* num (int): Message Number *
* data (char[]): Vector which maintaines data received *
* *
*************************************************************************/
rpack(len,num,data)
int *len, *num;
char *data;
{
static int semaphore;
int i,
fld,
chksum,
t,
type;
char abort();
chksum = 0;
t = 0;
plotc(9,66,'R');
while ((t=sgetc(Port)) != SOH);
for (fld=1; fld <= 5; fld++){
if (fld != 5 || i != 0)
if ((t=sgetc(Port)) == SOH) fld = 0;
if (fld <= 3) chksum += t;
switch (fld){
case 0: chksum = 0;
break;
case 1: *len = unchar(t)-3;
break;
case 2: *num = unchar(t);
break;
case 3: type = t;
break;
case 4: for (i=0; i < *len; i++){
if (i != 0)
if ((t=sgetc(Port)) == SOH){
fld = -1;
break;
}
chksum += t;
data[i] = t;
}
break;
case 5: chksum = (chksum + ((chksum & 192) / 64)) & 63;
break;
}
}
if (getkbs() && (getnec() == REQCAN)){
State = abort("Message Break");
longjmp(escape);
}
Trace.rmtype[Trace.ri] = type;
Trace.rmnum[Trace.ri] = *num;
if (++Trace.ri > 255)
Trace.ri = 0;
Nmess++;
prpack(RECEIVE,*len,*num,type,data,chksum);
plotc(9,66,'W');
if (chksum != unchar(t)){
clear_eol(5,1);
putchar(BEL);
plotistr(5,5,"Bad Checksum");
semaphore = TRUE;
return(FALSE);
}
if (semaphore){
semaphore = FALSE;
clear_eol(5,1);
}
return(type);
}
/************************************************************************
* *
* Module: receive *
* Purpose: To set up environment to receive a file *
* Interface: receive() *
* Parameters: None *
* Globals: Filnam (char[]): Name of file to receive *
* *
*************************************************************************/
receive()
{
while (TRUE){
Nmess = 0;
Nch = 0;
putmenu(" Name of file to Receive: ");
Size = getln(Filnam);
minit("RECEIVE FILE",Filnam);
if (recsw() == TRUE){
clrkb();
putmenu(" File transfer complete Do you wish to Receive more files (y/n): ");
switch (getnec()){
case 'N':
case 'n': return;
}
}else{ /* An error occurred */
clrkb();
putmenu("ERROR DURING FILE TRANSFER (A)bort or (C)ontinue");
switch(getnec()){
case 'A':
case 'a': return;
}
}
}
}
/************************************************************************
* *
* Module: recsw *
* Purpose: To maintain the receive file automoton *
* Interface: recsw() *
* *
*************************************************************************/
recsw()
{
char rinit(), rfile(), rdata();
State = 'R';
N = 0;
Numtry = 0;
if (setjmp (escape)) /* Return here on SIO time out */
spack('N',N,0,0); /* Send NAK */
while (TRUE){
switch(State){
case 'D':
State = rdata();
break;
case 'F':
State = rfile();
break;
case 'R':
State = rinit();
break;
case 'C':
return(TRUE);
case 'A':
return(FALSE);
default:
return(FALSE);
}
}
}
/************************************************************************
* *
* Module: rinit *
* Purpose: To initialise the conection to the host *
* Interface: rinit() *
* *
*************************************************************************/
char rinit()
{
int len,
num;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - RECEIVE INIT"));
switch (rpack(&len,&num,Packet) ){
case 'S': N = num;
rpar(Packet);
spar(Packet);
spack('Y',N,6,Packet);
Oldtry = Numtry;
Numtry = 0;
Nch = 0;
Nmess = 0;
N = (N + 1) % 64;
return('F');
case 'N': spack('Y',num,0,0);
return(State);
case FALSE:
spack('N',num,0,0);
return(State);
case 'E': return(abort(Packet));
default: return(abort("Unexpected response - RECEIVE INIT"));
}
}
/************************************************************************
* *
* Module: rfile *
* Purpose; To receive a file from the host *
* Interface: rfile() *
* *
*************************************************************************/
char rfile()
{
int num,
len;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - RECEIVE FILE"));
switch ( rpack(&len,&num,Packet) ){
case 'S': if (Oldtry++ > MAXTRY)
return(abort("Maximum number of attempts - RECEIVE FILE"));
if (num == N-1){
spar(Packet);
spack('Y',num,6,Packet);
Numtry = 0;
return(State);
}else
return(abort("Message number mismatch - RECEIVE FILE"));
case 'Z': if (Oldtry++ > MAXTRY)
return(abort("Maximum number of attempts - RECEIVE FILE"));
if (num == N-1){
spack('Y',num,0,0);
Numtry = 0;
return(State);
}else
return(abort("Message number mismatch - RECEIVE FILE"));
case 'F': if (num != N)
return(abort("Message number mismatch - RECEIVE FILE"));
if (getfil(Filnam) == FALSE)
return(abort("Unable to open file"));
spack('Y',N,0,0);
Oldtry = Numtry;
Numtry = 0;
N = (N + 1) % 64;
return('D');
case 'B': if (num != N)
return(abort("Message number mismatch - RECEIVE FILE"));
spack('Y',N,0,0);
return('C');
case 'N': spack('Y',num,0,0);
return(State);
case FALSE:
spack('N',num,0,0);
return(State);
case 'E': return(abort(Packet));
default: return(abort("Unexpected response - RECEIVE FILE"));
}
}
/************************************************************************
* *
* Module: rdata *
* Purpose; To receive data from the host *
* Interface: rdata() *
* *
*************************************************************************/
char rdata()
{
int i,
num,
len;
char abort();
if (Numtry++ > MAXTRY)
return(abort("Maximum number of retries - RECEIVE DATA"));
switch ( rpack(&len,&num,Packet) ){
case 'D': if (num != N){
if (Oldtry++ > MAXTRY)
return(abort("Maximum number of attempts - RECEIVE DATA"));
if (num == N-1){
spack('Y',num,0,0);
Numtry = 0;
return(State);
}else
return(abort("Message number mismatch - RECEIVE DATA"));
}
Nch += len;
bufemp(Packet,Fptr,len);
spack('Y',N,0,0);
Oldtry = Numtry;
Numtry = 0;
N = (N + 1) % 64;
return('D');
case 'Z': if (num != N)
return(abort("Message number mismatch - RECEIVE DATA"));
i = (fclose(Fptr) == -1)?
abort("Unable to close file"):
'F';
spack('Y',num,0,0);
N = (N + 1) % 64;
return(i);
case 'F': if (Oldtry++ > MAXTRY)
return(abort("Maximum number of attempts - RECEIVE DATA"));
if (num != N-1){
spack('Y',N,0,0);
Numtry = 0;
return(State);
}else
return(abort("Message number mismatch - RECEIVE DATA"));
case 'B': if (num != N)
return(abort("Message number mismatch - RECEIVE DATA"));
spack('Y',N,0,0);
return('C');
case 'N': spack('Y',num,0,0);
return(State);
case FALSE:
spack('N',num,0,0);
return(State);
case 'E': return(abort(Packet));
default: return(abort("Unexpected response - RECEIVE DATA"));
}
}
/**/
/************************************************************************
* *
* TERMINAL EMULATION ROUTINES *
* *
*************************************************************************/
/************************************************************************
* *
* Module: termem *
* Purpose: To emulate a terminal *
* Interface: termem() *
* *
*************************************************************************/
termem()
{
unsigned char ch;
putmenu(Root_m);
setjmp (escape);
while (TRUE){
if (getkbs()){ /* Check for character @ keyboard */
if (((ch=getnec()) >= F1) && (ch <= F8)){
clear_screen();
/* cursr_off();*/
switch (ch){
case F1: return;
case F2: send();
break;
case F3: receive();
break;
case F4: set();
break;
case F5: show();
getnec();
break;
case F6: dtrace();
break;
case F7: help(ROOT_H);
break;
case F8: putchar('!');
docmd();
}
clear_screen();
putmenu(Root_m);
home();
/* cursr_on();*/
}else{
sputc(((ch == REQCAN)?Break:ch),Port);
if (Echo)
putchar(ch);
}
}else if ((ch=scheck(Port)) > 0){
putchar(ch&0x07f); /* Else echo chararacter from Port */
}
}
}
/************************************************************************
* *
* Module: docmd() *
* Purpose: To execute a MS-DOS command *
* Input: None *
* Output: None *
* *
*************************************************************************/
docmd()
{
struct regval {int ax,bx,cx,dx,si,di,ds,es;} srv,rrv;
char line[256];
if (!Msdos20){
putstr("Requires MSDOS 2.0 or greater ... request ignored\n");
}else
putstr("Feature not implemented at this time\n");
putmenu(Help_m);
getnec();
}
/************************************************************************
* *
* Module: dtrace() *
* Purpose: To display trace information collected during data *
* transmition *
* Input: Trace: Trace buffer (Global data) *
* Output: None *
* *
*************************************************************************/
dtrace()
{
int j,
d,
k,
i;
printf("\033Y!7\0330Local\0331\033Y!L\0330Host\0331\033Y7 ");
putmenu(Trace_m);
for (i=Trace.si-1, j=(i+1) & 0x0ff;
Trace.smtype[i] != 'S' && Trace.rmtype[i] != 'S' && i != j; \
i = (i - 1) & 0x0ff);
if (i == j){
printf("\n No transactions in Trace Buffer");
}else{
Trace.smtype[j] = 0; /* Mark top of list */
d = (Trace.smtype[i] == 'S')?SEND: RECEIVE;
j = 10;
i = (Trace.si - 1) & 0x0ff;
while (TRUE){
if (d == SEND){
printf("\033Y# \033M\033Y7D<------- %c(%d)",\
Trace.rmtype[i],Trace.rmnum[i]);
printf("\033Y# \033M\033Y77%c(%d) ------->",\
Trace.smtype[i],Trace.smnum[i]);
}else{
printf("\033Y# \033M\033Y77%c(%d) ------->",\
Trace.smtype[i],Trace.smnum[i]);
printf("\033Y# \033M\033Y7D<------- %c(%d)",\
Trace.rmtype[i],Trace.rmnum[i]);
}
if ((Trace.smtype[i] == 'S') || (Trace.rmtype[i] == 'S'))
break;
i = (i - 1) & 0x0ff;
while (--j < 1){
switch (getnec()){
case F1:
j = 10;
break;
case F2:
break;
case F3:
printf("\033j");
k = (i + 11) & 0x0ff;
if (d == SEND){
printf("\033Y# \033L\033Y#7%c(%d) ------->",\
Trace.smtype[k],Trace.smnum[k]);
printf("\033Y# \033L\033Y#D<------- %c(%d)",\
Trace.rmtype[k],Trace.rmnum[k]);
}else{
printf("\033Y# \033L\033Y#D<------- %c(%d)",\
Trace.rmtype[k],Trace.rmnum[k]);
printf("\033Y# \033L\033Y#7%c(%d) ------->",\
Trace.smtype[k],Trace.smnum[k]);
}
printf("\033k");
if (Trace.smtype[i] != 0)
i = (i + 1) & 0x0ff;
continue;
case F6:
return;
case F7:
help(TRACE_H);
break;
default:
putchar(BEL);
continue;
}
break;
}
}
}
getnec();
}
prtrace(d,i,l)
int d,i,l;
{
}
/************************************************************************
* *
* Module: set *
* Purpose: To set or reset system variable *
* Interface: set() *
* *
*************************************************************************/
set()
{
show();
while (TRUE){
putmenu(Set_m);
switch (getnec()){
case F1: set_baud();
break;
case F2: set_echo();
break;
case F3: set_warning();
break;
case F4: set_parms();
break;
case F6: return;
case F7: help(SET_H);
show();
break;
default: putchar(BEL);
}
}
}
set_baud()
{
plotistr(POS_BAUD,4,Pa[8]);
plotistr(POS_BAUD,50,Ba[Speed]);
while (TRUE){
putmenu(Baud_m);
switch (getnec()){
case F1: Speed = B300;
break;
case F2: Speed = B600;
break;
case F3: Speed = B1200;
break;
case F4: Speed = B2400;
break;
case F5: Speed = B4800;
break;
case F6: Speed = B9600;
break;
case F7: help(BAUD_H);
show();
continue;
default: putchar(BEL);
continue;
}
break;
}
sbaud(Speed,Port);
clear_eol(POS_BAUD,1);
plotstr(POS_BAUD,4,Pa[8]);
plotstr(POS_BAUD,50,Ba[Speed]);
}
set_echo()
{
plotistr(POS_ECHO,4,Pa[7]);
plotistr(POS_ECHO,50,(Echo)?"YES":"NO ");
while (TRUE){
putmenu(Onoff_m);
switch (getnec()){
case F1: Echo = TRUE;
break;
case F2: Echo = FALSE;
break;
case F6: break;
case F7: help(ECHO_H);
show();
continue;
default: putchar(BEL);
continue;
}
break;
}
clear_eol(POS_ECHO,1);
plotstr(POS_ECHO,4,Pa[7]);
plotstr(POS_ECHO,50,(Echo)?"YES":"NO ");
}
set_warning()
{
plotistr(POS_WARN,4,Pa[6]);
plotistr(POS_WARN,50,(Warn)?"YES":"NO ");
while (TRUE){
putmenu(Onoff_m);
switch (getnec()){
case F1: Warn = TRUE;
break;
case F2: Warn = FALSE;
break;
case F6: break;
case F7: help(WARN_H);
show();
continue;
default: putchar(BEL);
continue;
}
break;
}
clear_eol(POS_WARN,1);
plotstr(POS_WARN,4,Pa[6]);
plotstr(POS_WARN,50,(Warn)?"YES":"NO ");
}
set_parms()
{
/* cursr_on();*/
putmenu(Parm_m);
pos(POS_MAXPACK,50);
Maxpack = getnp(Maxpack,MAXPACK);
putmenu(Parm_m);
pos(POS_MYPCHAR,50);
Mypchar = getcp(Mypchar);
putmenu(Parm_m);
pos(POS_MYPAD,50);
Mypad = getnp(Mypad,NULL);
putmenu(Parm_m);
pos(POS_MYTIME,50);
Mytime = getnp(Mytime,NULL);
putmenu(Parm_m);
pos(POS_MYEOL,50);
Myeol = getcp(Myeol);
putmenu(Parm_m);
pos(POS_MYQUOTE,50);
Myquote = getcp(Myquote);
pos(POS_BREAK,50);
Break = getcp(Break);
/* cursr_off();*/
}
show()
{
int i;
clear_screen();
putmenu(Show_m);
for (i=0; i < 11;i++){
plotistr(SHOW_BASE+i,4,Pa[i]);
plotstr(SHOW_BASE+i,4,Pa[i]);
}
plotd(POS_MAXPACK,50,Maxpack);
plotstr(POS_MYPCHAR,50,(Mypchar < ' ')?"^":" ");
plotc(POS_MYPCHAR,51,(Mypchar < ' ')?Mypchar+'@':Mypchar);
plotd(POS_MYPAD,50,Mypad);
plotd(POS_MYTIME,50,Mytime);
plotstr(POS_MYEOL,50,(Myeol < ' ')?"^":" ");
plotc(POS_MYEOL,51,(Myeol < ' ')?Myeol+'@':Myeol);
plotstr(POS_MYQUOTE,50,(Myquote < ' ')?"^":" ");
plotc(POS_MYQUOTE,51,(Myquote < ' ')?Myquote+'@':Myquote);
plotstr(POS_WARN,50,(Warn)?"YES":"NO ");
plotstr(POS_ECHO,50,(Echo)?"YES":"NO ");
plotstr(POS_BAUD,50,Ba[Speed]);
plotstr(POS_BREAK,50,(Break < ' ')?"^":" ");
plotc(POS_BREAK,51,(Break < ' ')?Break+'@':Break);
plotstr(POS_PORT,50,(Port == PORTA)?"PORT A":"PORT B ");
}
/************************************************************************
* *
* Module: help *
* Purpose: To print out help messages *
* Interface: help(message) *
* Input: message (->char): Help message to be printed *
* Output: None *
* *
*************************************************************************/
help(message)
int message;
{
FILE *fp;
int i;
int ch;
clear_screen();
putmenu(Help_m);
if ((fp=fopen("KERMIT.HEP","r")) != 0){
i = 0;
while (i != message){
while (getc(fp) != ENDSEC);
++i;
}
while (TRUE){
switch (ch=getc(fp)){
case ENDPAG:
getnec();
clear_screen();
continue;
case ENDSEC:
case ENDSS:
case ENDFIL:
case EOF:
break;
case ENQUIRE:
i = getnp(1,NULL);
putmenu(Help_m);
while (i > 0){
switch (ch=getc(fp)){
case ENDSEC:
case ENDFIL:
case EOF:
ungetc(ch,fp);
break;
case ENDSS:
--i;
break;
}
}
clear_screen();
continue;
case '\n':
if ((ch=getc(fp)) == ';'){
while (getc(fp) != '\n');
ungetc('\n',fp);
}else{
putchar('\n');
ungetc(ch,fp);
}
continue;
default:
putchar(ch);
continue;
}
break;
}
fclose(fp);
}else{
putstr("Help file not found");
}
getnec();
}
/**/
/************************************************************************
* *
* UTILITES *
* *
*************************************************************************/
/************************************************************************
* *
* Module: abort *
* Purpose: To print out the abort message, return an Abort *
* code, and send an Error packet to the host. *
* Interface: abort(message) *
* Input: message (->char): Message to be printed *
* Output: Through function name (char): *
* 'A': Abort code *
* *
*************************************************************************/
char abort(message)
char *message;
{
clear_eol(5,1);
plotistr(5,(38-(strlen(message)/2)),message);
spack('E',N,strlen(message),message);
return('A');
}
/************************************************************************
* *
* Module: basenm *
* Purpose: To strip off any device specifiers and/or path names *
* supplied with the file name. *
* Interface: basenm(fname) *
* Input: fname (->char): Name of file *
* Output: Through function name (->char): *
* pointer to position of "base name" *
* *
*************************************************************************/
char *basenm(fname)
char fname[];
{
int i,j,k;
for (j=strlen( &fname[ (fname[1] == ':')? 2: 0 ] ), k = j;
(j >= 0) && (fname[j] != '/') ; --j);
for (i=j; i < k; i++){
if (fname[i] == '.'){
if (i+3 < k){
fname[i+4] = '\0';
break;
}
}
}
return(&fname[j+1]);
}
/************************************************************************
* *
* Module: bufemp *
* Purpose: To write data received to the appropriate file *
* Interface: bufemp(buffer,filptr,len) *
* *
*************************************************************************/
bufemp(buffer,filptr,len)
char buffer[];
FILE *filptr;
int len;
{
int i,
t;
for (i=0; i < len; i++){
if ((t=buffer[i]) == Myquote){
if ((t=buffer[++i]) != Myquote)
t = ctl(t);
}
fputc(t,filptr);
}
}
/************************************************************************
* *
* Module: bufill *
* Purpose: To get data from a file *
* Interface: bufill(buffer) *
* *
*************************************************************************/
bufill(buffer)
char buffer[];
{
int i,
t;
i = 0;
while ((t = fgetc(Fptr)) != EOF){
t &= 0x07f;
if (t < SP || t == DEL || t == Quote){
buffer[i++] = Quote;
if (t != Quote)
t = ctl(t);
}
buffer[i++] = t;
if (i >= Spsiz-6)
return(i);
}
if (i == 0)
return(EOF);
return(i);
}
/************************************************************************
* *
* Module: getcp *
* Purpose: To get a character from the keyboard *
* Interface: getcp(d) *
* Input: d (integer): Default value, if nothing entered *
* Output: Through function name: *
* Keyed, or default value *
* *
*************************************************************************/
getcp(d)
int d;
{
int c,j;
c = -1;
/* cursr_on();*/
putmenu(Getcp_m);
while(TRUE){
switch(j=getnec()){
case F1:/* cursr_off();*/
return((c == -1)?d:c);
case F2: return(getnp(0,128));
case F7: help(GETCP_H);
show();
putmenu(Getcp_m);
break;
default: if (j < ' ')
printf("^%c",j+'@');
else
putchar(j);
c = j;
}
}
}
/************************************************************************
* *
* Module: getfil *
* Purpose: To open a file for data received from host *
* Interface: getfil(filenm) *
* *
*************************************************************************/
getfil(filenm)
char *filenm;
{
FILE *fopen();
char *fln,
*basenm();
if (*filenm == '\0'){ /* Default to name sent by host */
fln = basenm(Packet);
pos(5,(38-(14+strlen(fln))/2));
putistr("RECEIVE FILE: ");
putistr(fln);
}else
fln = filenm;
if (fopen(fln,"r") != 0){ /* File already exists */
while (Warn){
putmenu("File already exists. Do you want to (C)ontinue, (A)bort, or (R)ename: ");
switch (getnec()){
case 'A':
case 'a':
return(FALSE);
case 'C':
case 'c':
break;
case 'R':
case 'r':
clear_eol(5,1);
plotstr(5,1,"Enter new filename: ");
getln(filenm);
return(getfil(filenm));
default:
putchar(BEL);
plotistr(5,1,"Invalid entry ");
continue;
}
break;
}
}
return ( ((Fptr=fopen(fln,"wb")) == 0)? FALSE: TRUE);
}
/************************************************************************
* *
* Module: getlc *
* Purpose: To get the current Line/Column position of the cursor *
* Interface: getlc(line,column) *
* Input: line (->char): Pointer to integer variable *
* column (->char): Pointer to integer variable *
* Output: Line (->char): Current line position (0 releative) *
* column (->char): Current column position (0 rel) *
* *
*************************************************************************/
getlc(line,column)
char *line,*column;
{
printf("\033n"); /*send out control code to CRT */
getnec(); /* By pass garbage ... \033Y */
getnec();
*line = getnec(); /* Get information we want */
*column = getnec();
}
/************************************************************************
* *
* Module: getln *
* Purpose: To get a line from standard input *
* Interface: getln(line) *
* Input: line (->char[]): Pointer to vector which receives *
* keyed data *
* Output: Through function name (integer): *
* Number of characters entered *
* *
*************************************************************************/
getln(line)
char line[];
{
int i;
for (i=0; (line[i]=getchar()) != '\n';++i);
line[i] = '\0';
return(i);
}
/************************************************************************
* *
* Module: getnp *
* Purpose: To get a number (decimal) from the keyboard *
* Interface: getnp(default,max) *
* Input: d (integer): Default value, if nothing entered *
* max (integer): Maximun value. If NULL, then no maximum *
* Output: Through function name: *
* Keyed, or default value *
* *
*************************************************************************/
getnp(d,max)
int d,max;
{
int i,
j,
k;
/* cursr_on();*/
i = 0;
k = 0;
while(TRUE){
putmenu(Getnp_m);
while ((j=getnec()) != CR){
if (j >= '0' && j <= '9'){
k++;
putchar(j);
i = (i * 10) + (j - '0');
}else if (j == BS){
i /= 10;
printf("%c %c",BS,BS);
}else if (j == '\030'){ /* Handle Control X */
while (k-- > 0)
printf("%c %c",BS,BS);
i = 0;
k = 0;
}else
putchar(BEL);
}
if (k == 0){
i = d;
break;
}
if ((max == 0) || (k <= max))
break;
putchar(BEL);
putmenu("Entry too large");
}
/* cursr_off();*/
return(i);
}
/************************************************************************
* *
* Module: gnxtfl *
* Purpose: To get the next file in a group, if there is one *
* Interface: gnxtfl() *
* *
*************************************************************************/
gnxtfl()
{
return(EOF);
}
/************************************************************************
* *
* Module: minit() *
* Purpose: To initialise the message screen for data communications*
* Input: message: Message type (Sending/receiving) *
* name: File name involved *
* Output: None *
* *
*************************************************************************/
minit(message,name)
char *message,*name;
{
int x,y;
clear_screen();
putmenu(Startms);
pos(5,(38-(strlen(message)+strlen(name))/2));
putistr("RECEIVE FILE: ");
putistr(name);
plotstr(7,30,"Transmision Statistics");
plotustr(8,1,
" Send Receive Accumulated Data ");
plotstr(9,1,"Message Type:");
plotstr(10,1,"Message Number:");
plotstr(11,1,"Data Length:");
plotstr(9,40,"Transmision State:");
plotstr(10,40,"Number of Messages:");
plotstr(11,40,"Number of Characters:");
Trace.si = 0;
Trace.ri = 0;
Msem = TRUE;
}
/************************************************************************
* *
* Module: prpack *
* Purpose: To print a packet *
* Interface: prpack(len,num,type,data,chksum) *
* Input: len (int): Length of data to be sent *
* num (int): Message number *
* type (char): Type of message *
* data (char[]): Data to be sent *
* chksum (int): Check sum being sent *
* Output: None *
* *
*************************************************************************/
prpack(state,len,num,type,data)
int state,len,num;
char type,data[];
{
int i,ch;
static y;
ch = (state == SEND)?18: 27;
plotc(9,ch,type);
plotd(10,ch,num);
plotd(11,ch,len);
plotU(10,66,Nmess);
plotU(11,66,Nch);
if (Display){
if (Msem == TRUE){
Msem = FALSE;
y = 32;
}
for (i=0; i < len; i++){
if ((ch=data[i]) == Myquote){
if ((ch=data[++i]) != Myquote)
if ((ch=ctl(ch&0x0ff)) == LF){
y = 32;
plotstr(11,0,"\033M\033Y6 ");
ch = CR;
}
}
plotc(23,y++,ch);
}
}
}
/************************************************************************
* *
* Module: rpar *
* Purpose: To receive initialisation parameters from host *
* Input: data: Parameters sent by host. *
* Output: Spsiz, Timint, Pad, Padchar, Eol, Quote are set *
* *
*************************************************************************/
rpar(data)
char data[];
{
Spsiz = unchar(data[0]);
Timint = unchar(data[1]);
Pad = unchar(data[2]);
Padchar = ctl(data[3]);
Eol = unchar(data[4]);
Quote = data[5];
}
/************************************************************************
* *
* Module: spar *
* Purpose: To send initialisation parameters to the host *
* Input: Spsiz, Timint, Pad, Padchar, Eol, Quote are set *
* Output: data: Parameters to send to the host *
* *
*************************************************************************/
spar(data)
char data[];
{
data[0] = tochar(Maxpack);
data[1] = tochar(Mytime);
data[2] = tochar(Mypad);
data[3] = ctl(Mypchar);
data[4] = tochar(Myeol);
data[5] = Myquote;
}
/**/
/************************************************************************
* *
* SERIAL I/O UTILITIES *
* *
*************************************************************************/
/************************************************************************
* *
* Module: sbaud *
* Purpose: To set the baud rate *
* Interface: sbaud(baud,port) *
* Input: baud (int): Baud rate: 0 = 300 baud *
* 1 = 600 baud *
* 2 = 1200 Baud *
* 3 = 2400 baud *
* 4 = 4800 baud *
* 5 = 9600 baud *
* port (int): Serial Port:0 = Port A *
* 1 = Port B *
* Output: None *
* *
*************************************************************************/
sbaud(baud,port)
int baud, port;
{
pokeb(3,0x0e002, ((port == PORTA)? 0x036: 0x076));
baud *= 2;
pokeb(port,0x0e002,Rate[baud]);
pokeb(port,0x0e002,Rate[baud+1]);
}
/************************************************************************
* *
* Module: scheck *
* Purpose: To check if a character is available at the port *
* and return it if there is one *
* Interface: scheck(port) *
* Parameters: *
* Input: port (int): Port id: 0 = Port A *
* 1 = Port B *
* Output: Through function name (int): *
* Character found,or FALSE (i.e. 0) *
* *
*************************************************************************/
scheck(port)
int port;
{
return( (sstatus(RX,port))? /* Check status */
(peek(port,0x0e004) & 0x0ff): /* Return character */
0
);
}
/************************************************************************
* *
* Module: sgetc *
* Purpose: To get a character from the serial port *
* Interface: sgetc(port) *
* Parameters: *
* Input: port (int): Port id: 0 = Port A *
* 1 = Port B *
* Output: Through function name (char): *
* Character read at port *
* *
*************************************************************************/
sgetc(port)
int port;
{
unsigned timer,
ch;
while (TRUE){
for (timer=0;--timer > 0 && (sstatus(RX,port) == FALSE););
if (timer == 0){
if (getkbs()){ /* TRUE if character present */
if ((ch=getnec()) == CR){
longjmp (escape,RECEIVE);
}else if (ch == DEL){
State = abort("Time out on Input");
longjmp (escape,RECEIVE);
}
}else
putchar(BEL);
}else
return(peek(port,0x0e004) & 0x07f);
}
}
/************************************************************************
* *
* Module: sputc *
* Purpose: To put a character out to the serial port *
* Interface: sputc(ch,port) *
* Parameters: *
* Input: ch (char): Character to output *
* port (int): Port id: 0 = Port A *
* 1 = Port B *
* Output: None *
* *
*************************************************************************/
sputc(ch,port)
char ch;
int port;
{
unsigned timer,
c;
while (TRUE){
for (timer=0;--timer > 0 && sstatus(TX,port) == FALSE;);
if (timer == 0){ /* If timed out */
if (getkbs()){
if ((c=getnec()) == CR)
longjmp (escape,SEND);
else if (c == DEL){
State = abort("Time out on Output");
longjmp (escape,SEND);
}
}else
putchar(BEL);
}else{
pokeb(port,0x0e004,ch & 0x07f);
break;
}
}
}
/************************************************************************
* *
* Module: portinit *
* Purpose: To initialise the specified port *
* Interface: portinit(port) *
* Input: port (int): Id of port to initialise: 0 = Port A *
* 1 = Port B *
* Output: None *
* *
*************************************************************************/
portinit(port)
int port;
{
int control;
control = port + 2; /* Move to "Control" addresses */
pokeb(control,0x0e004,0x018); /* Channel Reset */
pokeb(control,0x0e004,CR2); /* Address control register 2 */
pokeb(control,0x0e004,cr2[port]);
pokeb(control,0x0e004,CR4); /* Address control register 4 */
pokeb(control,0x0e004,cr4[port]);
pokeb(control,0x0e004,CR3); /* Address control register 3 */
pokeb(control,0x0e004,cr3[port]);
pokeb(control,0x0e004,CR5); /* Address control register 5 */
pokeb(control,0x0e004,cr5[port]);
pokeb(control,0x0e004,0x011); /* Disable interupts */
pokeb(control,0x0e004,0);
}