SRI-NOSC/ncpp/tel-u/usrtelnetin.c

Compare this file to the similar file:
Show the results in this format:

#
#include "../h/telnet.h"
/* 
	This section begins the code for reading from the network file
	and writing to the terminal

	T E L N E T I N			This reads from netfile and writes
					to its standard output file. The input
					file is inteneded to contain cr(015)
					nl(012) characters as line delimiters.
						And Telnet
					iacs(0377) which prefix a number of
					imbedded telnet protocol requests 
					are dropped on the floor 
*/

char threebyte[]			/* tells which of the telnet requests
					   contain three bytes */
{
	0,		/* tel_se */
	0,		/* tel_nop */
	0,		/* tel_dm */
	0,		/* tel_break */
	0,		/* tel_ip */
	0,		/* tel_ao */
	0,		/* tel_ayt */
	0,		/* tel_ec */
	0,		/* tel_el */
	0,		/* tel_ga */
	0,		/* tel_sb */
	1,		/* tel_will */
	1,		/* tel_wont */
	1,		/* tel_do */
	1,		/* tel_dont */
	0		/* tel_iac */
};


int numsynchs 0;	/* The number of synch sequences to be looked at */
int insflag 0;		/* Set when an INS interrupt occurs */
int exptins 0;		/* expect an ins -- set in response from tty side */
int connopen 1;		/* says file still open */
int netcnt 0;		/* number of bytes in netbuf */
int ttycnt 0;		/* number of bytes to write to stnd output */
int netfile;		/* have to set this somehow */

char netbuf[128];	/* input buffer from the net */
char *netp;		/* ptr to next char to be gotten from netbuf */


/**/
main (argc,argv)int argc;char **argv;
{

	register int c1;
	extern int marksynch();
	extern int expect_an_ins();

	if (argc != 2) {
		printf ("Telnet-input not exec'ed properly.\r\n");
		exit ();
		}

	printf(" Connection open\r\n");
	/* get netfile fid */
	netfile = 0;
	netfile = **++argv;
	if (netfile < 1 | netfile > 15) {
		printf ("Invalid net file ID of %d\r\n",netfile);
		exit ();
		}

	/* ignore interrupts which user might type to subshells */
	signal( 2,1 );
	signal( 3,1 );
	signal( 15,&marksynch );
	signal( 13,&expect_an_ins );

	/* while the connection is open */
	while (1) {
		if((c1 = netchar ()) < 0) {
			destroy (1);
			interpret (c1);
			}
		}
}
/* 

	M A R K S Y N C H		This is associated with an inr signal
					generated by the kernel when one show
					on the host control link.

*/

marksynch()
{

	insflag++;			/* say an ins showed */
	if( exptins-- > 0 )		/* tty side say to expect an ins?? */
		numsynchs++;			/* say an ins showed up start looking fo dm */
	signal( 15,&marksynch );	/* reload the signal */
}
/*
	E X P E C T _ A N _ I N S	This is executed by signal from the
					tty side telling me to expect an ins
					followed by a data-mark as in the new
					telnet protocol.  If an ins arrives
					without this being called, it is ignored
					since no data mark is expected a la old
					telnet protocol.
*/
expect_an_ins()
{
	insflag++;			/* when we exit dont let read think err */
	exptins++;			/* say its ok to look for a data mark */
	signal( 13,&expect_an_ins );
}
/* 
	I N T R P R E T		Interpret telnet protocol. In particular, 
				respond to a telnet will, wont, do or dont.

*/

interpret (c) 
int  c;
{
	register int command;
	register int option;	/* the option that is being negotiated */
	char response;		/* our response */
	char buf [3];		/* output buffer */

	response = 0;
	command = c & 0377;

	if (command != tel_iac) switch (command) { 	/* old telnet protocol */
		case otel_dm: if (--numsynchs == 0) destroy (0);

		case otel_nop:	
		case otel_noecho:
		case otel_echo:

		case otel_hide:	return;

		default:	printf ("Unexpected old telnet protocol %o.\r\n",command);
				return;
		}

	command = netchar () & 0377;
	if (command == tel_iac) return; else destroy (1);

/* New Telnet protocol */
	if (threebyte [((command - tel_se))] == 0)  switch (command) {

		case tel_dm: if (--numsynchs == 0)  destroy (0);

		case tel_nop:

		case tel_ga:

		default:	return;
		}


/* Handle WILL, WONT, DO, DONT */
	option = netchar () & 0377;
	destroy (1);		/* so the user wont see it */
	switch (command) {

	case tel_will: response = ((option == to_echo) ? tel_do : tel_dont);
			break;

	case tel_wont:	break;

	case tel_do:	response = tel_wont;
			break;

	case tel_dont:	response = tel_wont;

	default:	printf ("Possible protocol error!\r\n");
			printf ("command = %o, option = %o.\r\n",command,option);
			break;
			}

	if (response) {
		buf [0] = tel_iac;
		buf [1] = response;
		buf [2] = option;
		write (netfile,buf,3);
		}
}
/*
	N E T C H A R 		Netchar will see if the input buffer needs
				refilling (netcnt == 0) checks to see if
				buffers needs emptying first if so will 
				write to stnd output and refill from stnd
				input, checking to see if file closed. once
				buffer filling and emptying is taken care of
				decrements netcnt and returns a character from
				netbuf

*/

char netchar()
{
	if( netcnt == 0 )	/* buffer empty ?*/
	{
		if(  numsynchs <= 0 && ttycnt>0 )	/* anything to write to output file? */
			write( 1,netbuf,ttycnt );	/* put it out */
		while(( ttycnt=netcnt=read( netfile,netp=netbuf,128 )) < 0 )
		{		/* file closed or eof */
			if( insflag == 0 )
			{
				printf (" Connection Closed.\r\n");
				exit();
			}
			else
				insflag = 0;
		}
		insflag = 0;
	}

	/* dec amt of chars in buffer and return char */
	netcnt--;
	return( *netp++ );
}
/*
	D E S T R O Y		Destroy will to get rid of the character 
				immediately before the one about to be gotten,
				(clear??).  Called when an iac sequence is to be
				removed from dta going to the terminal.

*/

destroy(n)
int	n;			/* number to destroy; 0 --> beginning to current */
{

	register char *src;	/* awwwww come on */
	register char *dest;
	register cnt;

	src = netp;
	if (n > 0) {
		dest = netp - n;
		ttycnt =- n;
		}
	else	{
		dest = netbuf;
		ttycnt = netcnt;
		}

	netp = dest;			/* so netchar will work */
	cnt = netcnt + 1;			/* get num chars left in buffer */

	while( --cnt )			/* thru that many */
		*dest++ = *src++;	/* copy the chars */
}