


		****  terminal.c ****

*
 * This module is common to the three terminal_?.c programs
 * It contains a tiny subset of the Telnet protocol, which should normally be 
 *  sufficient to log on to many unix hosts.
 * It also contains some common subroutines.
 * It must be linked with terminal_?.obj.
 *
 *
 * OGA 090991  		MCsocket.lib build
 * efw 092193  		TCP 2.2 build
 *
 *

include <stdio.h>
include systypes.h
include syssocket.h


ifdef __BTOSC__
extern int ZPrint plm far ();
else
define ZPrint @
include <ctos.lib.h>
endif


define IAC  0xFF			* Telnet protocol definitions... *
define DO   0xFD
define DONT 0xFE
define WILL 0xFB
define WONT 0xFC
define SPGA 0x03
define TTYP 0x18
define ECHO 0x01


	**** Global Data ****

int TCPprecedence;
extern unsigned int errno;	* global error code returned from system calls *
extern int Debug;			* Debugging level                           *
extern int S;				* file descriptor returned by socket call  *
extern int N;				* return value of function calls           *
extern int LocalEcho;		* TRUE if remote does not echo             *
extern int RemotePort;		* Default to the Telnet port               *
int recvd=0;
	**** Local functions ****

void CheckArgs(int argc, char *argv[]);	* CheckArgs *
void CheckP(int N, char *msg);	* UNIX style return code check *
void CheckZ(int N, char *msg);	* CTOS Erc check               *
void InitTelnet();              * Telnet startup for unix      *
void RecvTelnet(unsigned char *iBf, int iBfSz);
                                * Telnet input processing for unix  *
void CheckArgs(int argc, char *argv[])
*************************************
 * 	Check Args
 * 	  argv[0] = program name, 	argv[1] = host name;
 *    argv[2] = port number, 	argv[3] = local echo, argv[4] = Debug Level
 *
{
 	if (argc < 2) {
        printf(usage: terminal_1, hostname, port, y (if local echo)\n, 
        	argv[0]);
        exit(0); 
	}
 	if (argc>2) RemotePort=atoi(argv[2]);
 	if (argc>3  (*argv[3]=='y' || *argv[3]=='Y')) LocalEcho=1;
ifdef DEBUG
	Debug=1;
endif
 	if (argc>4){
 		TCPprecedence=atoi(argv[4]);
 		printf(Precedence=d\n, TCPprecedence);
 	}
 	
 	if (RemotePort==23) LocalEcho=0;    * if Telnet, assume unix     *
}

void CheckP (int N, char *msg)
*****************************
 * check N positive else display msg
 *
{
	if (N<0){
		switch(errno){
		 case ECLOSING:
		 case EABORTING:
		 case EABORTED:
			printf( TCP Connection closed by remote Host\n);
			break;
		 default:
			printf( Program terminated: error u in s\n, errno, msg);
		}
		exit(1);
		
	} else {
	 	if (Debug>1)
			printf(Trace OK: s\n, msg);
	}
} 

void CheckZ (int N, char *msg)
*****************************
 * check N zero else display msg
 *
{
	if (N){
		printf( Program terminated: CTOS erc u in s\n, N, msg);
		exit(1);
	}
}

void InitTelnet()
********************************************
 * Simple Telnet startup assumptions for unix
 *
{
char bf[3];
	bf[0]=IAC; bf[1]=DO  ;   bf[2]=SPGA;
	N = ssend (S, bf, 3, 0); CheckP(N, ssend DO SPGA);
	bf[0]=IAC; bf[1]=DO  ;   bf[2]=ECHO;
	N = ssend (S, bf, 3, 0); CheckP(N, ssend DO ECHO);
	bf[0]=IAC; bf[1]=WONT;   bf[2]=ECHO;
	N = ssend (S, bf, 3, 0); CheckP(N, ssend WONT ECHO);

*
 * turn the hardware cursor on
 * using CTOS bytestream escape
 * sequence
 *
 	ZPrint(\0xFFVN);

*
 * turn off the Next Page pause
 *
	ZPrint(0xFFPF);
}

void RecvTelnet(unsigned char *iBf, int iBfSz)
**********************************************
 * Simple Telnet processing input buffer for unix
 *
{
static state=0, verb;
static char *verbTxt, verbTxtBf[8], *cmdTxt, cmdTxtBf[8];
unsigned char  bf[6], c;
int p=0;
recvd+=iBfSz;
 while (p<iBfSz){
  c=iBf[p];
  switch (state){
   case 0:
	if (c==IAC  RemotePort==23)
		state=1;
	else
		if (c>1) putchar(c);
		if (c=='') p=(c0);
	break;
   case 1:
    verb=c;
    switch (c){
     case DO:   verbTxt=DO;   break;
     case DONT: verbTxt=DONT; break;
     case WILL: verbTxt=WILL; break;
     case WONT: verbTxt=WONT; break;
     default: sprintf(verbTxtBf, VERB X, c  255); verbTxt=verbTxtBf; break;
    }
    state++;
	break;
   case 2:
	switch (c){
	 case SPGA: cmdTxt=SPGA; break;
	 case TTYP: cmdTxt=TTYP; break;
	 case ECHO: cmdTxt=ECHO; break;
     default: sprintf(cmdTxtBf, CMD X, c  255); cmdTxt=cmdTxtBf; break;
	}
	bf[0]=IAC; bf[2]=c;
	switch (c){
	 case SPGA:
		if (verb==DO){
			bf[1]=WILL; N=ssend(S, bf, 3, 0); CheckP(N, ssend WILL SPGA);
			if (Debug) printf(\n\r DO SPGA recvd\n\r);
		}
		break;
	 default:
		if (verb==DO || verb==DONT){
			bf[1]=WONT; N=ssend(S, bf, 3, 0); CheckP(N, ssend WONT ...);
		}
		if (Debug) printf(\n\r s s recvd\n\r,  verbTxt, cmdTxt);
	}
    state=0;
	break;
  }
  p++;
 }
}
