//#define DEBUG //****************************************************************************} //program TelnetClient } #define VeRsIoN "1.04" //----------------------------------------------------------------------------} // date of origin : 15.12. 1996 } //define LaSt_DaTe "6. Jan 1996" // last change time : 17.30 } // Author : Petr Jaklin , V Z vetr¡ 1678, Teplice 415 01 } //----------------------------------------------------------------------------} // Open telnet session to specified host } // not supported: scr attributes // support for TERMINAL TYPE disabled: NW xconsole use ANSI term as Xterm ... // v1.02: displayInputCursor // v1.03: new ESC sequences for XCONSOLE compatibility (e[?2J is supposed to // be CLRSCR; at e[12h I switch from 0-based cursor to 1-based one) // v1.04: TermType VT100 //****************************************************************************} #include #include #include #include #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------} /* DESCRIPTION FILE copyright "Copyright (C) 1996, Petr Jaklin, 3NET s.r.o." version VeRsIoN description "Telnet client" screenname "Telnet" threadname "telnet" output f:\tc\tel input tel g:\progbase\c386\novi\prelude stack 8192 type 0 debug multiple import __WATCOM_Prelude import @g:\progbase\c386\novi\clib.imp import @g:\progbase\c386\novi\socklib.imp #import @f:\tc\h\server4.imp module clib, tcpip */ //--------------------------------------------------------------------------- // TYPEs typedef enum { TSdata, TSiac, TSdo, TSdn, TSwl, TSwn, TSsub, TSsubOpt, TSsubIac } TelnetStatus; typedef enum { ASdata, ASesc, ASprefix, AScharSet, ASnum, ASchar, AScharEnd, ASsepar, } ANSIStatus; char protErr[]="PROTO_ERROR: "; char eraseLine[80] = { " " " "}; //--------------------------------------------------------------------------- // variables TelnetStatus telStat=TSdata; // telnet automat status ANSIStatus ansiStat=ASdata; // ansi automat status char *myname; // prg name string char host[80]; // name of host to telnet char iobuf[4097]; // reading buffer struct sockaddr_in server_sockaddr; // IP target address int sock; // IP socket int readData=FALSE; // do read flag int endTel=FALSE; // main quit flag char oline[120]; // keyboard buffer LONG wrtSem; // IP write semaphore (I dont know // if 'write' is reentrant LONG readID; // read thread ID char *CMD[] = // telnet cmd names for 'logging' { "End of subnegotiation", "No operation", "Data Mark", "Break", "Interrupt process", "Abort output", "Are You there ?", "Erase charecter", "Erase line", "Go ahead", "SubNegotiation", "WILL", "WON'T", "DO", "DON'T", "IAC" }; char strOpt[20]; // buffer for telnet cmd logging #define SbMax 50 char sbC[SbMax]; // sub negotiation buffer int sbNum; // counter of sbC buffer int remEcho=FALSE; // echo option status int isANSI=TRUE; // is ANSI code supported #define AsMaxNum 20 BYTE asNum[AsMaxNum]; // array of ansi arguments int asNums=0; // # of valid asNum[] int asPrefix=0; // ESC prefix [ ... 1 , ( ... 2 // ) ... 3 , [= ... 4 // [? ... 5 , ... 0 int charSet=0; // 0=ASCII, 1=graphics int asCx=0; // cursor saving vars (for ANSI e[s) int asCy=0; int xy0=0; // cursor home address (0,0) is default int displayInputCursor=FALSE; // cursor state int setCursor=FALSE; // inter-thread flag #ifdef DEBUG int logIt=TRUE; // log traffic into sys:system\tel.log int ctrl=TRUE; // do log control too #else int logIt=FALSE; // log traffic into sys:system\tel.log int ctrl=FALSE; // do log control too #endif FILE *logFile=NULL; // logfile handle //--------------------------------------------------------------------------- void ecprintf ( char *format, ...) // printf + if control echo to log //--------------------------------------------------------------------------- { va_list params; va_start(params,format); vprintf(format,params); va_end(params); if (ctrl) { va_start(params,format); vfprintf(logFile,format,params); va_end(params); } } // ecprintf //--------------------------------------------------------------------------- char * Option ( int opt ) //--------------------------------------------------------------------------- { switch (opt) { case 0 : return("BinaryTransmission"); case 1 : return("ECHO"); case 3 : return("SuppresGA"); case 5 : return("Status"); case 17 : return("Extended ASCII"); case 24 : return("Terminal Type"); default : sprintf(strOpt,"Unknown-%02X",opt); return(strOpt); } } // option //--------------------------------------------------------------------------- int WriteData ( BYTE *buff, int size) //--------------------------------------------------------------------------- { int wr; char str[100]; int i; WaitOnLocalSemaphore(wrtSem); if (logIt) { for (i=0;i' : ; case 'c' : ; // reset terminal break; default : InvalidAnsi(c); } break; case 1 : // '[' switch (c) { case 'f' : ; case 'H' : if (asNums==1) gotoxy(0,asNum[0]-xy0); else if (asNums==2) gotoxy(asNum[1]-xy0,asNum[0]-xy0); else if (asNums==0) gotoxy(0,0); else InvalidAnsi(c); break; case 'A' : if (asNums==1) gotoxy(wherex(),wherey()-asNum[0]); else InvalidAnsi(c); break; case 'B' : if (asNums==1) gotoxy(wherex(),wherey()+asNum[0]); else InvalidAnsi(c); break; case 'C' : if (asNums==1) gotoxy(wherex()+asNum[0],wherey()); else InvalidAnsi(c); break; case 'D' : if (asNums==1) gotoxy(wherex()-asNum[0],wherey()); else InvalidAnsi(c); break; case 'J' : if ((asNums==1) && (asNum[0]==2)) { clrscr(); // cannot be here: waits for kbd free !?! DisplayInputCursor(); displayInputCursor=TRUE; setCursor=TRUE; } else InvalidAnsi(c); break; case 'K' : if (asNums==1) { if (asNum[0]==0) EraseLine(wherex()); else if (asNum[0]==2) EraseLine(0); else InvalidAnsi(c); } else InvalidAnsi(c); break; case 'h' : if ((asNums==1) && (asNum[0]==12)) xy0=1; else InvalidAnsi(c); break; case 'm' : for (i=0;i='0') && (c<='9')) { asNum[0]=c-0x30; asNums=1; ansiStat=ASnum; } else if (c==';') { asNum[0]=0; asNums=1; ansiStat=ASsepar; } else if (c==34) { // " asNums=0; ansiStat=ASchar; } else CompleteAnsi(c); break; case ASnum : if ((c>='0') && (c<='9')) { asNum[asNums-1]*=10; asNum[asNums-1]+=c-0x30; } else if (c==';') ansiStat=ASsepar; else CompleteAnsi(c); break; case ASchar : if (c=='"') ansiStat=AScharEnd; else if (asNums==AsMaxNum) { ecprintf("ANSI_ERROR: TooLongData\r\n"); ansiStat=ASdata; } else asNum[asNums++]=c; break; case AScharEnd : if (c==';') ansiStat=ASsepar; else CompleteAnsi(c); break; case ASsepar : if ((c>='0') && (c<='9')) { if (asNums==AsMaxNum) { ecprintf("ANSI_ERROR: TooLongData\r\n"); ansiStat=ASdata; } asNum[asNums]=c-0x30; asNums+=1; ansiStat=ASnum; } else if (c=='"') ansiStat=ASchar; else { asNum[asNums]=0; asNums+=1; CompleteAnsi(c); } //else break; } else printf("%c",c); } // datadisplay //--------------------------------------------------------------------------- void Display ( char c) // telnet automat engine //--------------------------------------------------------------------------- { switch (telStat) { case TSdata : switch (c) { case 255 : telStat=TSiac; break; case 0 : break; default : DataDisplay(c); } break; case TSiac : if (c<240) { ecprintf("%s IAC/%02x\r\n",protErr,c); telStat=TSdata; } else { switch (c) { case 255 : DataDisplay(255); // iac telStat=TSdata; break; case 240 : ecprintf(protErr); // subnego. end telStat=TSdata; break; case 246 : WriteData("OK",2); // are you there telStat=TSdata; break; case 247 : printf("\8"); // erase character telStat=TSdata; break; case 248 : EraseLine(0); telStat=TSdata; break; case 250 : telStat=TSsub; break; case 251 : telStat=TSwl; break; case 252 : telStat=TSwn; break; case 253 : telStat=TSdo; break; case 254 : telStat=TSdn; break; default : telStat=TSdata; break; } if (c<250) if (ctrl) ecprintf("ReadCTRL(%s)\r\n",CMD[c-240]); } break; case TSdo : if (ctrl) ecprintf("ReadCTRL(DO,%s)\r\n",Option(c)); switch (c) { case 3 : WriteCtrl(251,3); // suppres GA (will) break; case 24 : WriteCtrl(251,24); // terminal type break; default : WriteCtrl(252,c); // won't } telStat=TSdata; break; case TSdn : if (ctrl) ecprintf("ReadCTRL(DON'T,%s)\r\n",Option(c)); WriteCtrl(252,c); // won't telStat=TSdata; break; case TSwl : if (ctrl) ecprintf("ReadCTRL(WILL,%s)\r\n",Option(c)); switch (c) { case 1 : WriteCtrl(253,1); // echo (do) remEcho=TRUE; break; case 3 : WriteCtrl(253,3); // suppres GA (do) break; default : WriteCtrl(254,c); // don't } telStat=TSdata; break; case TSwn : if (ctrl) ecprintf("ReadCTRL(WON'T,%s)\r\n",Option(c)); WriteCtrl(254,c); // don't if (c==1) remEcho=FALSE; telStat=TSdata; break; case TSsub : if (ctrl) ecprintf("ReadCTRL(SubNeg,%s)\r\n",Option(c)); telStat=TSsubOpt; sbNum=1; sbC[0]=c; break; case TSsubOpt : if (sbNum0) && (sbNum [/L] [/C] [/NA]\r\n\n", myname); printf("where /L ... log traffic into SYS:SYSTEM\\TEL.LOG\r\n"); printf(" /C ... log control messages too\r\n"); printf(" /NA ... don't use ANSI control codes\r\n"); exit(err); } // writehelp //--------------------------------------------------------------------------- void ReadParam ( int argc, char **argv) //--------------------------------------------------------------------------- { int i; char str[80]; char host[80]; myname=*argv; if (argc<2) WriteHelp(0); host[0]=0; for (i=1;i0) { WriteData(oline,i); i=0; } } while (!endTel); } // keybinput //--------------------------------------------------------------------------- void main ( int argc, char **argv) //--------------------------------------------------------------------------- { int rc; sock=-1; wrtSem=-1; SetCtrlCharCheckMode(FALSE); SetAutoScreenDestructionMode(FALSE); SetCursorCouplingMode(TRUE); atexit(exitproc); ReadParam(argc,argv); if (server_sockaddr.sin_addr.s_addr == -1) { printf("ERROR: %s is a malformed address\r\n",host); exit(1); } server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(23); printf("Opening socket\r\n"); sock=socket(PF_INET, SOCK_STREAM, 0); if (sock==-1) { perror("socket"); exit(1); } wrtSem=OpenLocalSemaphore(1); readData=FALSE; if ((readID=BeginThread(ReadData,NULL,NULL,NULL))==-1) { printf(" Error creating reading thread.\r\n"); exit(1); } printf("Connecting\r\n"); rc=connect(sock,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr)); if (rc==-1) { perror("connect"); exit(1); } printf("Connected. Press Alt-T to quit session.\r\n"); WriteData("OK",0); // ? begin of communication ? readData=TRUE; delay(800); // wait for negotiation of session KeybInput(); if (logFile!=NULL) { fclose(logFile); logFile=NULL; } ExitThread(EXIT_NLM,0); } // main