4 * AUTHOR : unknown (sources found on www.telnet.org)
5 * PROJECT : ReactOS Operating System
6 * DESCRIPTION: telnet client for the W32 subsystem
9 * 2001-02-21 ea Modified to compile under 0.0.16 src tree
18 #define NUL 0 // No Operation
20 #define BS 8 // Back Space
21 #define HT 9 // Horizontal Tab
22 #define LF 10 // Line Feed
23 #define VT 11 // Vertical Tab
24 #define FF 12 // Form Feed
25 #define CR 13 // Carriage Return
27 // telnet command codes
28 #define SE 240 // End of subnegotiation parameters.
29 #define NOP 241 // No operation.
30 #define DM 242 // Data Mark
31 #define BRK 243 // Break
32 #define IP 244 // Interrupt Process
33 #define AO 245 // Abort output
34 #define AYT 246 // Are You There
35 #define EC 247 // Erase character
36 #define EL 248 // Erase Line
37 #define GA 249 // Go ahead
38 #define SB 250 // SuBnegotiate
43 #define IAC 255 // Interpret As Command
48 // 0x03 - Suppress GA (char at a time)
54 // 0xff - Extended Options List
58 TOPT_BIN = 0, // Binary Transmission
59 TOPT_ECHO = 1, // Echo
60 TOPT_RECN = 2, // Reconnection
61 TOPT_SUPP = 3, // Suppress Go Ahead
62 TOPT_APRX = 4, // Approx Message Size Negotiation
63 TOPT_STAT = 5, // Status
64 TOPT_TIM = 6, // Timing Mark
65 TOPT_REM = 7, // Remote Controlled Trans and Echo
66 TOPT_OLW = 8, // Output Line Width
67 TOPT_OPS = 9, // Output Page Size
68 TOPT_OCRD = 10, // Output Carriage-Return Disposition
69 TOPT_OHT = 11, // Output Horizontal Tabstops
70 TOPT_OHTD = 12, // Output Horizontal Tab Disposition
71 TOPT_OFD = 13, // Output Formfeed Disposition
72 TOPT_OVT = 14, // Output Vertical Tabstops
73 TOPT_OVTD = 15, // Output Vertical Tab Disposition
74 TOPT_OLD = 16, // Output Linefeed Disposition
75 TOPT_EXT = 17, // Extended ASCII
76 TOPT_LOGO = 18, // Logout
77 TOPT_BYTE = 19, // Byte Macro
78 TOPT_DATA = 20, // Data Entry Terminal
79 TOPT_SUP = 21, // SUPDUP
80 TOPT_SUPO = 22, // SUPDUP Output
81 TOPT_SNDL = 23, // Send Location
82 TOPT_TERM = 24, // Terminal Type
83 TOPT_EOR = 25, // End of Record
84 TOPT_TACACS = 26, // TACACS User Identification
85 TOPT_OM = 27, // Output Marking
86 TOPT_TLN = 28, // Terminal Location Number
87 TOPT_3270 = 29, // Telnet 3270 Regime
88 TOPT_X3 = 30, // X.3 PAD
89 TOPT_NAWS = 31, // Negotiate About Window Size
90 TOPT_TS = 32, // Terminal Speed
91 TOPT_RFC = 33, // Remote Flow Control
92 TOPT_LINE = 34, // Linemode
93 TOPT_XDL = 35, // X Display Location
94 TOPT_ENVIR = 36,// Telnet Environment Option
95 TOPT_AUTH = 37, // Telnet Authentication Option
96 TOPT_NENVIR = 39,// Telnet Environment Option
97 TOPT_EXTOP = 255, // Extended-Options-List
98 TOPT_ERROR = 256 // Magic number
101 // Wanted by linux box:
116 state_data, //we expect a data byte
117 state_code, //we expect a code
118 state_option //we expect an option
121 int option_error(_verb,_option,int,SOCKET);
123 typedef void(*LPOPTIONPROC)(SOCKET,_verb,_option);
124 typedef void(*LPDATAPROC)(SOCKET,unsigned char data);
126 ///////////////////////////////////////////////////////////////////////////////
128 inline void yesreply(SOCKET server, _verb verb,_option option)
130 unsigned char buf[3];
132 buf[1] = (verb==verb_do)?WILL:(verb==verb_dont)?WONT:(verb==verb_will)?DO:DONT;
133 buf[2] = (unsigned char)option;
134 send(server,(char*)buf,3,0);
137 inline void noreply(SOCKET server, _verb verb,_option option)
139 unsigned char buf[3];
141 buf[1] = (verb==verb_do)?WONT:(verb==verb_dont)?WILL:(verb==verb_will)?DONT:DO;
142 buf[2] = (unsigned char)option;
143 send(server,(char*)buf,3,0);
146 inline void askfor(SOCKET server, _verb verb,_option option)
148 unsigned char buf[3];
150 buf[1] = (unsigned char)verb;
151 buf[2] = (unsigned char)option;
152 send(server,(char*)buf,3,0);
156 void ddww_error(SOCKET server,_verb verb,_option option)
160 wsprintf(tmp,"Unknown Option Code: %s, %i\n",(verb==verb_do)?"DO":(verb==verb_dont)?"DON'T":(verb==verb_will)?"WILL":"WONT",(int)option);
161 OutputDebugString(tmp);
166 case verb_will: // server wants to support something
167 noreply(server,verb,option); // I don't want that.
169 case verb_wont: // server waants to disable support
170 return; // don't confirm - already disabled.
171 case verb_do: // server wants me to support something
172 noreply(server,verb,option); //I won't do that
174 case verb_dont: // server wants me to disable something
175 return; // don't worry, we don't do that anyway (I hope :)
179 ///////////////////////////////////////////////////////////////////////////////
180 // Option ECHO & SUPPRESS GA
182 // These options are curiously intertwined...
183 // The Win32 console doesn't support ECHO_INPUT (echo) if
184 // LINE_INPUT (==GA) isn't set.
185 // I can't see how to code this negotiation without using
186 // some form of Lock-Step algorythm
187 // ie: if("WILL ECHO")
195 void ddww_echo(SOCKET server,_verb verb, _option option)
198 GetConsoleMode(StandardInput, & mode); // ENABLE_ECHO_INPUT
200 int set = !(mode & ENABLE_ECHO_INPUT);
204 case verb_will: // server wants to echo stuff
205 if(set) return; //don't confirm - already set.
206 SetConsoleMode(StandardInput,mode & (~ENABLE_ECHO_INPUT));
208 case verb_wont: // server don't want to echo
209 if(!set) return; //don't confirm - already unset.
210 SetConsoleMode(StandardInput,mode | ENABLE_ECHO_INPUT);
212 case verb_do: // server wants me to loopback
213 noreply(server,verb,option);
215 case verb_dont: // server doesn't want me to echo
216 break; // don't bother to reply - I don't
218 yesreply(server,verb,option);
222 void ddww_supp(SOCKET server,_verb verb,_option option) //Suppress GA
225 GetConsoleMode(StandardInput,&mode); // ENABLE_LINE_INPUT
227 int set = !(mode & ENABLE_LINE_INPUT);
231 case verb_will: // server wants to suppress GA's
232 if(set) break; //don't confirm - already set.
233 SetConsoleMode(StandardInput,mode & (~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)));
234 askfor(server,verb_do,TOPT_SUPP);
235 askfor(server,verb_will,TOPT_SUPP);
236 askfor(server,verb_do,TOPT_ECHO);
238 case verb_wont: // server wants to send GA's
239 if(!set) break; //don't confirm - already unset.
240 SetConsoleMode(StandardInput,mode | ENABLE_LINE_INPUT);
241 askfor(server,verb_dont,TOPT_SUPP);
242 askfor(server,verb_wont,TOPT_SUPP);
244 case verb_do: // server wants me to suppress GA's
246 askfor(server,verb_do,TOPT_SUPP);
248 case verb_dont: // server wants me to send GA's
250 askfor(server,verb_dont,TOPT_SUPP);
255 ///////////////////////////////////////////////////////////////////////////////
256 // Option TERMINAL-TYPE
258 void ddww_term(SOCKET server,_verb verb,_option option) //Subnegotiate terminal type
263 noreply(server,verb,option); // I don't want terminal info
266 //dat be cool - its not going to send. no need to confirm
269 yesreply(server,verb,option); //I'll send it when asked
271 case verb_dont://Ok - I won't
276 // TERMINAL TYPE subnegotation
283 #define NUM_TERMINALS 2
290 } terminal[NUM_TERMINALS] = {
297 void sbproc_term(SOCKET server,unsigned char data)
300 if(data == SB_TERM_SEND)
302 if(term_index == NUM_TERMINALS)
306 char buf[16]; //pls limit
311 lstrcpy(&buf[4],terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].name);
312 int nlen = lstrlen(&buf[4]);
315 send(server,buf,4+nlen+2,0);
319 ///////////////////////////////////////////////////////////////////////////////
324 LPOPTIONPROC OptionProc;
327 {TOPT_ECHO, ddww_echo, NULL},
328 {TOPT_SUPP, ddww_supp, NULL},
329 {TOPT_TERM, ddww_term, sbproc_term},
330 {TOPT_ERROR, ddww_error, NULL}
334 void vm(SOCKET server,unsigned char code)
336 //These vars are the finite state
337 static int state = state_data;
338 static _verb verb = verb_sb;
339 static LPDATAPROC DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc;
343 //Decide what to do (state based)
349 case IAC: state = state_code; break;
350 default: DataProc(server,code);
357 // State transition back to data
359 DataProc(server,code);
361 // Code state transitions back to data
363 DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc;
383 // Transitions to option state
386 state = state_option;
390 state = state_option;
394 state = state_option;
398 state = state_option;
402 state = state_option;
409 //Find the option entry
412 ol[i].option != TOPT_ERROR && ol[i].option != code;
415 //Do some verb specific stuff
417 DataProc = ol[i].DataProc;
419 ol[i].OptionProc(server,verb,(_option)code);