1 /* $Id: vm.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
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
);