#include #include "vt.h" #include "keyboard.h" #include "tcp.h" #define IAC 255 #define DONT 254 #define DO 253 #define WONT 252 #define WILL 251 #define SB 250 #define BREAK 241 #define SE 240 #define TELOPT_ECHO 1 #define TELOPT_SGA 3 #define TELOPT_STATUS 5 #define TELOPT_TTYPE 24 #define NTELOPTS 24 tcp_Socket* s; tcp_Socket socketdata; int port = 23; int echo = 1; int sgaflg = 0; #define TSBUFSIZ 41 char sb[TSBUFSIZ]; longword host; COM_PutStr( char* buf ) { sock_fastwrite( s, buf, strlen(buf) ); } Connect( char* h ) { int status; SCR_PutString( 0, "Attempting to connect to " ); SCR_PutString( 0, h ); SCR_PutString( 0, "...\r\n\n" ); host = resolve( h ); if( host == 0 ) return 0; s = &socketdata; if( !tcp_open( s, 0, host, port, 0 ) ) return 0; sock_wait_established( s, sock_delay, 0, &status ); sock_mode( s, TCP_MODE_NAGLE ); SendIAC( WILL, TELOPT_TTYPE ); SendIAC( DO, TELOPT_SGA ); SendIAC( WONT, TELOPT_ECHO); SendIAC( DO, TELOPT_ECHO); return 1; sock_err: return 0; } SendIAC( byte cmd, byte opt ) { byte io_data[3]; io_data[0] = IAC; io_data[1] = cmd; io_data[2] = opt; sock_fastwrite( s, io_data, 3 ); return( !tcp_tick( s ) ); } ProcessIAC() { int cmd, opt, n, y, flag; cmd = GetCharTN(); if( cmd == IAC ) return; opt = GetCharTN(); switch( opt ) { case TELOPT_ECHO : if( cmd == WILL ) { if( echo ) { echo = 0; SendIAC( DO, TELOPT_ECHO ); } } else if( cmd == WONT ) { if( !echo ) { echo = 1; SendIAC( DONT, TELOPT_ECHO ); } } else if( cmd == DO ) { echo = 0; SendIAC( WONT, TELOPT_ECHO ); SendIAC( DO, TELOPT_ECHO ); } else if( cmd == DONT ) { echo = 0; SendIAC( WONT, TELOPT_ECHO ); } break; case TELOPT_SGA : if( cmd == WONT ) { sgaflg = 1; if( !echo ) { SendIAC( DONT, TELOPT_SGA ); echo = 1; } } else if( cmd == WILL ) { sgaflg = 0; if( echo ) { SendIAC( DO, TELOPT_SGA ); SendIAC( DO, TELOPT_ECHO ); } } break; case TELOPT_TTYPE : if( cmd == DO ) SendIAC( WILL, TELOPT_TTYPE ); else if( cmd == SB ) { n = 0; flag = 0; while( n < TSBUFSIZ ) { y = GetCharTN(); sb[n++] = y; if( y == IAC ) flag = 1; else { if( flag && y == SE ) break; else flag = 0; } } if( !flag ) return; if( *sb == 1 ) { SendIAC( SB, TELOPT_TTYPE ); sock_fastwrite( s, "\000UNKNOWN\377ð", 10 ); } } break; default : if( cmd == WILL ) SendIAC( DONT, opt ); else if( cmd == DO ) { SendIAC( WONT, opt ); SendIAC( DONT, opt ); } else if( cmd == DONT ) SendIAC( WONT, opt ); break; } } int GetCharTN() { int status; byte c; sock_tick( s, &status ); if( sock_dataready( s ) ) { sock_fastread( s, &c, 1 ); return c; } sock_err: return -1; } int GetChar() { int c; c = GetCharTN(); if( c == IAC ) { ProcessIAC(); return -1; } return c; } PutChar( int ch ) { sock_fastwrite( s, &ch, 1 ); } main( int argc, char* argv[] ) { int status; int ok = 1; int ch; int len; int i; int k, x; long key; char* t; if( argc == 1 ) { printf( "MiniTerm - by Mark Morley\r\n\n" ); printf( "Usage: MT hostname [-Pport] [-Eemulation] [-Kkeyboard]\r\n\n" ); printf( "ALT-X exits the program, ALT-R resets the emulation\r\n" ); return; } sock_init(); VT_Init(); KEY_Init(); KEY_LoadDriver( "VT-AT" ); for( i = 2; i < argc; i++ ) { if( *argv[i] == '-' || *argv[i] == '/' ) { switch( argv[i][1] ) { case 'p' : case 'P' : port = atoi( &argv[i][2] ); break; case 'k' : case 'K' : KEY_LoadDriver( &argv[i][2] ); break; case 'e' : case 'E' : if( !stricmp( &argv[i][2], "vt52" ) ) VT_Mode( VT52 ); else if( !stricmp( &argv[i][2], "heath19" ) ) VT_Mode( HEATH19 ); else if( !stricmp( &argv[i][2], "vt100" ) || !stricmp( &argv[i][2], "vt102" ) || !stricmp( &argv[i][2], "vt" ) ) VT_Mode( VT102 ); else if( !stricmp( &argv[i][2], "vt200" ) ) VT_Mode( VT200 ); else if( !stricmp( &argv[i][2], "ansi" ) || !stricmp( &argv[i][2], "sco" ) ) VT_Mode( ANSI ); break; } } } if( !Connect( argv[1] ) ) { printf( "Couldn't connect to %s\r\n", argv[1] ); goto sock_err; } while( ok ) { while( (ch = GetChar()) != -1 ) VT_Process( ch ); while( kbhit() && (k = KEY_GetKey( &x )) != -1 ) { if( k == ALTX ) ok = 0; else if( k == ALTR ) VT_Init(); else { key = k + (((long)x) << 16); if( key > 255 ) { t = (char*) KEY_Translate( key ); if( t ) COM_PutStr( t ); } else PutChar( k ); } } } end: sock_close( s ); sock_wait_closed( s, sock_delay, 0, &status ); sock_err: KEY_Term(); SCR_Term(); VT_Term(); }