# #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 */ }