-rw-r--r-- | kinsole.cpp | 736 |
1 files changed, 736 insertions, 0 deletions
diff --git a/kinsole.cpp b/kinsole.cpp new file mode 100644 index 0000000..463db1c --- a/dev/null +++ b/kinsole.cpp | |||
@@ -0,0 +1,736 @@ | |||
1 | #include <stdio.h> | ||
2 | |||
3 | #ifdef_DEBUG | ||
4 | #include <afxwin.h> | ||
5 | #else | ||
6 | #define ASSERT(f) ((void)0) | ||
7 | #define VERIFY(f) ((void)(f)) | ||
8 | #define TRACE0(sz) | ||
9 | #define TRACE1(sz, p1) | ||
10 | #define TRACE2(sz, p1, p2) | ||
11 | #define TRACE3(sz, p1, p2, p3) | ||
12 | #endif | ||
13 | |||
14 | #include <winsock.h> | ||
15 | #include "resource.h" | ||
16 | #include "windowsx.h" | ||
17 | |||
18 | #define DAMN_KIN_NAME "KINSole" | ||
19 | #define DAMN_KIN_VERSION"v1.00 Beta 3" | ||
20 | |||
21 | #ifdef _DEBUG | ||
22 | #define new DEBUG_NEW | ||
23 | #undef THIS_FILE | ||
24 | static char THIS_FILE[] = __FILE__; | ||
25 | #endif | ||
26 | |||
27 | enum { | ||
28 | WM_USERSOCKET = WM_USER+16, | ||
29 | WM_USERKEY, | ||
30 | WM_USERNOP | ||
31 | }; | ||
32 | enum { | ||
33 | tnIAC = 255, | ||
34 | tnSE = 240, | ||
35 | tnNOP = 241, | ||
36 | tnDM = 242, | ||
37 | tnBreak = 243, | ||
38 | tnIP = 244, | ||
39 | tnAO = 245, | ||
40 | tnAYT = 246, | ||
41 | tnEC = 247, | ||
42 | tnEL = 248, | ||
43 | tnGA = 249, | ||
44 | tnSB = 250, | ||
45 | tnWILL = 251, | ||
46 | tnWONT = 252, | ||
47 | tnDO = 253, | ||
48 | tnDONT = 254 | ||
49 | }; | ||
50 | |||
51 | WSADATA wsaData; | ||
52 | ATOM wsaWC = NULL; | ||
53 | HWND wsaW = NULL; | ||
54 | |||
55 | CHAR remoteHost[256]; | ||
56 | CHAR remoteProt[256]; | ||
57 | sockaddr_in remoteSIN; | ||
58 | |||
59 | |||
60 | SOCKET telnetSocket; | ||
61 | HANDLE hConsoleInput; | ||
62 | HANDLE hConsoleOutput; | ||
63 | HWND hConsoleWindow; | ||
64 | HANDLE hConsoleThread; | ||
65 | DWORD consoleThreadID; | ||
66 | HANDLE hDispatchThread; | ||
67 | DWORD dispatchThreadID; | ||
68 | BOOL bTelnet,bTermPulled; | ||
69 | |||
70 | enum_cState { | ||
71 | cstateNone = 0, cstateIAC, cstateDO, cstateSB, cstateSBData, | ||
72 | cstateSBDataIAC, cstateWILL, cstateDONT,cstateWONT, | ||
73 | }connState = cstateNone; | ||
74 | BYTE negOption = 0; | ||
75 | |||
76 | |||
77 | BOOL SelectSocket() { | ||
78 | return WSAAsyncSelect(telnetSocket,wsaW,WM_USERSOCKET,FD_READ|FD_OOB|FD_CLOSE)!=SOCKET_ERROR; | ||
79 | } | ||
80 | |||
81 | BOOL ShowWill(BYTE o) | ||
82 | { | ||
83 | TRACE1("We're WILLing to %d\n",(WORD)o); | ||
84 | static | ||
85 | BYTE d[3] = {tnIAC,tnWILL,0}; | ||
86 | d[2] = o; | ||
87 | BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d); | ||
88 | SelectSocket(); | ||
89 | return rv; | ||
90 | } | ||
91 | BOOL ShowUnwill(BYTE o) | ||
92 | { | ||
93 | TRACE1("We're NOT WILLing to %d\n",(WORD)o); | ||
94 | static | ||
95 | BYTE d[3] = {tnIAC,tnWONT,0}; | ||
96 | d[2] = o; | ||
97 | BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d); | ||
98 | SelectSocket(); | ||
99 | return rv; | ||
100 | } | ||
101 | BOOL BegDo(BYTE o) | ||
102 | { | ||
103 | TRACE1("We beg to DO %d\n",(WORD)o); | ||
104 | static | ||
105 | BYTE d[3] = {tnIAC,tnDO,0}; | ||
106 | d[2] = o; | ||
107 | BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d); | ||
108 | SelectSocket(); | ||
109 | return rv; | ||
110 | } | ||
111 | BOOL BegDont(BYTE o) | ||
112 | { | ||
113 | TRACE1("We beg DONT'T %d\n",(WORD)o); | ||
114 | static | ||
115 | BYTE d[3] = {tnIAC,tnDONT,0}; | ||
116 | d[2] = o; | ||
117 | BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d); | ||
118 | SelectSocket(); | ||
119 | return rv; | ||
120 | } | ||
121 | BOOL SubNegotiate(BYTE o,LPBYTE data,UINT size) | ||
122 | { | ||
123 | LPBYTE d = new BYTE[3+size*2+2]; | ||
124 | int ds = 0; | ||
125 | d[ds++]=tnIAC; d[ds++]=tnSB; d[ds++]=o; | ||
126 | for(UINT tmp=0;tmp<size;tmp++) | ||
127 | if(data[tmp]!=tnIAC) | ||
128 | d[ds++]=data[tmp]; | ||
129 | else{ | ||
130 | d[ds++]=tnIAC; d[ds++]=tnIAC; | ||
131 | } | ||
132 | d[ds++]=tnIAC;d[ds++]=tnSE; | ||
133 | BOOL rv = send(telnetSocket,(char*)d,ds,0)==ds; | ||
134 | delete d; | ||
135 | SelectSocket(); | ||
136 | return rv; | ||
137 | } | ||
138 | BOOL SendLiteral(CHAR c) | ||
139 | { | ||
140 | BYTE d[2] = {tnIAC,0}; | ||
141 | BOOL rv = FALSE; | ||
142 | if(c==tnIAC){ | ||
143 | d[1]=c; | ||
144 | rv = send(telnetSocket,(char*)d,2,0)==2; | ||
145 | }else | ||
146 | rv = send(telnetSocket,&c,1,0)==1; | ||
147 | return rv; | ||
148 | } | ||
149 | BOOL SendLiteral(LPCTSTR c,UINT size) | ||
150 | { | ||
151 | for(UINT tmp=0;tmp<size;tmp++) | ||
152 | SendLiteral(c[tmp]); | ||
153 | return TRUE; | ||
154 | } | ||
155 | BOOL SendLiteral(LPCTSTR c) | ||
156 | { | ||
157 | return SendLiteral(c,strlen(c)); | ||
158 | } | ||
159 | BOOL SendCommand(BYTE c) | ||
160 | { | ||
161 | TRACE1("Issuing %d command\n",(WORD)c); | ||
162 | static | ||
163 | BYTE d[2] = {tnIAC,0}; | ||
164 | d[1] = c; | ||
165 | BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d); | ||
166 | SelectSocket(); | ||
167 | return rv; | ||
168 | |||
169 | } | ||
170 | |||
171 | BOOL CALLBACK consoleCtrlHandler(DWORD dwCtrlType) | ||
172 | { | ||
173 | switch(dwCtrlType){ | ||
174 | case CTRL_BREAK_EVENT: | ||
175 | SendCommand(tnIP); | ||
176 | return TRUE; | ||
177 | case CTRL_CLOSE_EVENT: | ||
178 | case CTRL_LOGOFF_EVENT: | ||
179 | case CTRL_SHUTDOWN_EVENT: | ||
180 | PostMessage(wsaW,WM_QUIT,0,0); | ||
181 | return TRUE; | ||
182 | } | ||
183 | return FALSE; | ||
184 | } | ||
185 | |||
186 | #include "options.cpp" | ||
187 | |||
188 | BOOL ProcessConsoleInput() | ||
189 | { | ||
190 | INPUT_RECORD ir[512]; | ||
191 | DWORD got; | ||
192 | while(GetNumberOfConsoleInputEvents(hConsoleInput,&got) && got){ | ||
193 | VERIFY(ReadConsoleInput(hConsoleInput,ir,(sizeof(ir)/sizeof(*ir)),&got)); | ||
194 | for(DWORD tmp=0;tmp<got;tmp++){ | ||
195 | if(ir[tmp].EventType==KEY_EVENT && ir[tmp].Event.KeyEvent.bKeyDown){ | ||
196 | if(( | ||
197 | ir[tmp].Event.KeyEvent.wVirtualKeyCode=='X' || | ||
198 | ir[tmp].Event.KeyEvent.wVirtualKeyCode=='Q' | ||
199 | ) && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED) | ||
200 | ){ | ||
201 | PostMessage(wsaW,WM_QUIT,0,0); | ||
202 | return FALSE; | ||
203 | }else if( | ||
204 | ir[tmp].Event.KeyEvent.wVirtualKeyCode=='O' | ||
205 | && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED) | ||
206 | ){ | ||
207 | SendCommand(tnAO); | ||
208 | }else if( | ||
209 | ir[tmp].Event.KeyEvent.wVirtualKeyCode=='Y' | ||
210 | && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED) | ||
211 | ){ | ||
212 | SendCommand(tnAYT); | ||
213 | }else if( | ||
214 | ir[tmp].Event.KeyEvent.wVirtualKeyCode=='T' | ||
215 | && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED) | ||
216 | ){ | ||
217 | BegDo(toTimingMark); | ||
218 | }else if( | ||
219 | ir[tmp].Event.KeyEvent.wVirtualKeyCode==VK_INSERT | ||
220 | && ir[tmp].Event.KeyEvent.dwControlKeyState&SHIFT_PRESSED | ||
221 | ){ | ||
222 | if(IsClipboardFormatAvailable(CF_OEMTEXT)){ | ||
223 | ASSERT(wsaW); | ||
224 | if(OpenClipboard(wsaW)){ | ||
225 | HANDLE h = GetClipboardData(CF_OEMTEXT); | ||
226 | LPVOID gl = GlobalLock(h); | ||
227 | TerminalIn((LPCTSTR)gl); | ||
228 | GlobalUnlock(h); | ||
229 | // GlobalFree(h); | ||
230 | CloseClipboard(); | ||
231 | } | ||
232 | } | ||
233 | }else if( | ||
234 | ir[tmp].Event.KeyEvent.wVirtualKeyCode==VK_INSERT | ||
235 | && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED) | ||
236 | ){ | ||
237 | if(hConsoleWindow) | ||
238 | SendNotifyMessage(hConsoleWindow,WM_COMMAND,MAKELONG(0xE003,0),NULL); | ||
239 | }else | ||
240 | TerminalIn(ir[tmp].Event.KeyEvent); | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | return TRUE; | ||
246 | } | ||
247 | |||
248 | ULONG CALLBACK ConsoleThreadProc(LPVOID) | ||
249 | { | ||
250 | for(;;){ | ||
251 | DWORD eves; | ||
252 | if(!(GetNumberOfConsoleInputEvents(hConsoleInput,&eves) && eves)) | ||
253 | WaitForSingleObject(hConsoleInput,INFINITE); | ||
254 | ASSERT(wsaW); | ||
255 | SendMessage(wsaW,WM_USERKEY,0,0); | ||
256 | } | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | BOOL SINTelnet(sockaddr_in& sin) | ||
261 | { | ||
262 | protoent* pe = getprotobyname("tcp"); | ||
263 | short proto = pe?pe->p_proto:6; | ||
264 | telnetSocket = socket(sin.sin_family,SOCK_STREAM,proto); | ||
265 | if(telnetSocket==INVALID_SOCKET){ | ||
266 | printf("Failed to create socket\n"); | ||
267 | return FALSE; | ||
268 | } | ||
269 | static | ||
270 | BOOL bOOBInline = FALSE; | ||
271 | if(setsockopt(telnetSocket,SOL_SOCKET,SO_OOBINLINE,(const char*)&bOOBInline,sizeof(bOOBInline))){ | ||
272 | TRACE0("Failed to setsockopt for OOB data\n"); | ||
273 | } | ||
274 | printf("Trying %s..",inet_ntoa(sin.sin_addr)); | ||
275 | if(connect(telnetSocket,(sockaddr*)&sin,sizeof(sin))){ | ||
276 | switch(WSAGetLastError()){ | ||
277 | case WSAECONNREFUSED: printf("\nConnection refused\n"); break; | ||
278 | case WSAEHOSTUNREACH: printf("\nNo route to host\n"); break; | ||
279 | case WSAENETDOWN: printf("\nNetwork is down\n"); break; | ||
280 | case WSAENETUNREACH: printf("\nNetwork is unreachable\n"); break; | ||
281 | case WSAETIMEDOUT: printf("\nConnection timed out\n"); break; | ||
282 | default: printf("\nFailed to connect\n"); break; | ||
283 | } | ||
284 | return FALSE; | ||
285 | } | ||
286 | printf("\nConnected. Alt-X/Alt-Q - Close telnet connection\n"); | ||
287 | //***hConsoleInput = ::GetStdHandle(STD_INPUT_HANDLE); | ||
288 | //***hConsoleOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); | ||
289 | hConsoleInput = CreateFile("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, | ||
290 | NULL,OPEN_EXISTING,0,NULL); | ||
291 | hConsoleOutput = CreateFile("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, | ||
292 | NULL,OPEN_EXISTING,0,NULL); | ||
293 | ASSERT(hConsoleInput!=INVALID_HANDLE_VALUE && | ||
294 | hConsoleOutput!=INVALID_HANDLE_VALUE); | ||
295 | if(!(bTelnet || bTermPulled)) | ||
296 | TerminalPullType("TTY"); | ||
297 | InitOptionsTable(); | ||
298 | TRACE0("Connected\n"); | ||
299 | VERIFY(SetConsoleCtrlHandler(&consoleCtrlHandler,TRUE)); | ||
300 | hConsoleThread = CreateThread(NULL,0,ConsoleThreadProc,NULL,0,&consoleThreadID); | ||
301 | ASSERT(hConsoleThread); | ||
302 | if(bTelnet){ | ||
303 | AskDo(toSuppressGA); | ||
304 | AskWill(toTerminalType); | ||
305 | AskWill(toNAWS); | ||
306 | AskUnwill(toEcho); | ||
307 | AskDo(toEcho); | ||
308 | if(Envars && nEnvars) | ||
309 | AskWill(toNewEnviron);// *** Or better (what's better?) | ||
310 | //AskWill(toLineMode); | ||
311 | // *** STATUS | ||
312 | } | ||
313 | MSG msg; | ||
314 | int rvgm; | ||
315 | PostMessage(wsaW,WM_USERNOP,0,0); | ||
316 | VERIFY(SelectSocket()); | ||
317 | while(rvgm=GetMessage(&msg,NULL,NULL,NULL)){ | ||
318 | if(rvgm<0) | ||
319 | break;// Some wheeping needed | ||
320 | TranslateMessage(&msg); | ||
321 | DispatchMessage(&msg); | ||
322 | //LRESULT CALLBACK WSWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); | ||
323 | // WSWndProc(msg.hwnd,msg.message,msg.wParam,msg.lParam); | ||
324 | VERIFY(SelectSocket()); | ||
325 | } | ||
326 | VERIFY(TerminateThread(hConsoleThread,0xFFFFFFFF)); | ||
327 | VERIFY(SetConsoleCtrlHandler(&consoleCtrlHandler,FALSE)); | ||
328 | closesocket(telnetSocket); | ||
329 | return TRUE; | ||
330 | } | ||
331 | |||
332 | BOOL Telnet(LPCTSTR hostName,UINT port) | ||
333 | { | ||
334 | memset(&remoteSIN,0,sizeof(remoteSIN)); | ||
335 | remoteSIN.sin_family = AF_INET; | ||
336 | remoteSIN.sin_port = htons(port); | ||
337 | |||
338 | remoteSIN.sin_addr.s_addr = inet_addr(hostName); | ||
339 | if(remoteSIN.sin_addr.s_addr==INADDR_NONE){ | ||
340 | hostent* he = gethostbyname(hostName); | ||
341 | if(!he){ | ||
342 | printf("Failed to resolve host name\n"); | ||
343 | return FALSE; | ||
344 | } | ||
345 | ASSERT(he->h_addrtype==AF_INET); | ||
346 | ASSERT(he->h_length==sizeof(remoteSIN.sin_addr)); | ||
347 | memmove(&remoteSIN.sin_addr,*he->h_addr_list,sizeof(remoteSIN.sin_addr)); | ||
348 | } | ||
349 | strcpy(remoteHost,hostName); | ||
350 | return SINTelnet(remoteSIN); | ||
351 | } | ||
352 | |||
353 | |||
354 | void ProcessIACByte(BYTE c) | ||
355 | { | ||
356 | connState = cstateNone; | ||
357 | switch(c){ | ||
358 | case tnIAC: | ||
359 | TerminalOut(c); | ||
360 | break; | ||
361 | case tnSE: | ||
362 | TRACE0("SE\n");break; | ||
363 | case tnNOP: | ||
364 | TRACE0("NOP\n");break; | ||
365 | case tnDM: | ||
366 | TRACE0("DM\n");break; | ||
367 | case tnBreak: | ||
368 | TRACE0("Break\n");break; | ||
369 | case tnIP: | ||
370 | TRACE0("IP\n");break; | ||
371 | case tnAO: | ||
372 | TRACE0("AO\n");break; | ||
373 | case tnAYT: | ||
374 | TRACE0("AYT\n");break; | ||
375 | case tnEC: | ||
376 | TRACE0("EC\n");break; | ||
377 | case tnEL: | ||
378 | TRACE0("EL\n");break; | ||
379 | case tnGA: | ||
380 | TRACE0("GA\n");break; | ||
381 | case tnSB: | ||
382 | connState = cstateSB; | ||
383 | break; | ||
384 | case tnWILL: | ||
385 | connState = cstateWILL; | ||
386 | break; | ||
387 | case tnWONT: | ||
388 | connState = cstateWONT; | ||
389 | break; | ||
390 | case tnDO: | ||
391 | connState = cstateDO; | ||
392 | break; | ||
393 | case tnDONT: | ||
394 | connState = cstateDONT; | ||
395 | break; | ||
396 | default: | ||
397 | TRACE1("Unknown OpCode = %d\n",(WORD)c); | ||
398 | break; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | void ProcessNetByte(BYTE c) | ||
403 | { | ||
404 | //TRACE1("<%d>",connState); | ||
405 | switch(connState){ | ||
406 | case cstateWONT: | ||
407 | ProcessWONT(c); | ||
408 | break; | ||
409 | case cstateDO: | ||
410 | ProcessDO(c); | ||
411 | break; | ||
412 | case cstateWILL: | ||
413 | ProcessWILL(c); | ||
414 | break; | ||
415 | case cstateDONT: | ||
416 | ProcessDONT(c); | ||
417 | break; | ||
418 | case cstateSB: | ||
419 | negOption = c; | ||
420 | connState = cstateSBData; | ||
421 | break; | ||
422 | case cstateSBData: | ||
423 | case cstateSBDataIAC: | ||
424 | ProcessSBData(c); | ||
425 | break; | ||
426 | case cstateIAC: | ||
427 | ProcessIACByte(c); | ||
428 | break; | ||
429 | case cstateNone: | ||
430 | default: | ||
431 | ASSERT(connState==cstateNone); | ||
432 | if(c==tnIAC) | ||
433 | connState=cstateIAC; | ||
434 | else | ||
435 | TerminalOut(c); | ||
436 | break; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | LRESULT WSMessage(WPARAM wP,LPARAM lP) | ||
441 | { | ||
442 | if(WSAGETSELECTERROR(lP)){ | ||
443 | TRACE0("SelectError\n"); | ||
444 | PostMessage(wsaW,WM_QUIT,0,0); | ||
445 | return 0; | ||
446 | } | ||
447 | if(WSAGETSELECTEVENT(lP)&FD_READ){ | ||
448 | //?? TRACE0("FD_READ\n"); | ||
449 | BYTE input[80*12]; | ||
450 | int got; | ||
451 | TerminalPreO(); | ||
452 | //?? TRACE0("rv\n"); | ||
453 | got=recv(telnetSocket,(CHAR*)input,sizeof(input),0); | ||
454 | //?? TRACE1("/rv %d\n",got); | ||
455 | for(int tmp=0;tmp<got;tmp++) | ||
456 | ProcessNetByte(input[tmp]); | ||
457 | TerminalPostO(); | ||
458 | //?? TRACE0("/FD_READ\n"); | ||
459 | return 0; | ||
460 | } | ||
461 | if(WSAGETSELECTEVENT(lP)&FD_OOB){ | ||
462 | TRACE0("OOB\n"); | ||
463 | } | ||
464 | if(WSAGETSELECTEVENT(lP)&FD_CLOSE){ | ||
465 | TRACE0("CLOSE\n"); | ||
466 | PostMessage(wsaW,WM_QUIT,0,0); | ||
467 | return 0; | ||
468 | } | ||
469 | VERIFY(SelectSocket()); | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | LRESULT CALLBACK WSWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) | ||
474 | { | ||
475 | switch(uMsg){ | ||
476 | case WM_USERSOCKET: | ||
477 | return WSMessage(wParam,lParam); | ||
478 | case WM_USERKEY: | ||
479 | return ProcessConsoleInput(); | ||
480 | default: | ||
481 | TRACE0("DEFWINDOWPROC\n"); | ||
482 | return ::DefWindowProc(hWnd,uMsg,wParam,lParam); | ||
483 | } | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | |||
488 | BOOL InitializeWinsock() | ||
489 | { | ||
490 | if(WSAStartup(0x101,&wsaData)){ | ||
491 | printf("Failed to initialize winsock services\n"); | ||
492 | return FALSE; | ||
493 | } | ||
494 | WNDCLASS wc; | ||
495 | memset(&wc,0,sizeof(wc)); | ||
496 | wc.lpfnWndProc=WSWndProc; wc.hInstance=::GetModuleHandle(NULL); | ||
497 | wc.lpszClassName = "_WSTFWC_"; | ||
498 | wsaWC = RegisterClass(&wc); | ||
499 | if(!wsaWC){ | ||
500 | printf("Failed to initialize winsock services - 1\n"); | ||
501 | return FALSE; | ||
502 | } | ||
503 | wsaW = ::CreateWindow("_WSTFWC_","KIN Sole Mio",0,0,0,0,0,NULL,NULL,::GetModuleHandle(NULL),NULL); | ||
504 | if(!wsaW){ | ||
505 | printf("Failed to initialize winsock services\n"); | ||
506 | return FALSE; | ||
507 | } | ||
508 | return TRUE; | ||
509 | } | ||
510 | void DeinitializeWinsock() | ||
511 | { | ||
512 | if(wsaW) | ||
513 | ::DestroyWindow(wsaW); | ||
514 | wsaW=NULL; | ||
515 | if(wsaWC) | ||
516 | ::UnregisterClass("_WSTFWC_",::GetModuleHandle(NULL)); | ||
517 | wsaWC=NULL; | ||
518 | WSACleanup(); | ||
519 | } | ||
520 | |||
521 | HWND GetThisConsoleWnd() | ||
522 | { | ||
523 | DWORD pid = GetCurrentProcessId(); | ||
524 | CHAR title[512]; | ||
525 | CHAR* t = title; | ||
526 | if(!GetConsoleTitle(title,sizeof(title))) | ||
527 | t = NULL; | ||
528 | HWND hrv = FindWindowEx(NULL,NULL,"tty",t); | ||
529 | HWND nopro = NULL; | ||
530 | UINT nopros=0; | ||
531 | do{ | ||
532 | DWORD wpid; | ||
533 | if(!GetWindowThreadProcessId(hrv,&wpid)) | ||
534 | continue; | ||
535 | if(wpid==pid) | ||
536 | return hrv; | ||
537 | nopro=hrv; | ||
538 | nopros++; | ||
539 | hrv = FindWindowEx(NULL,hrv,"tty",t); | ||
540 | }while(hrv); | ||
541 | if(nopros==1){ | ||
542 | ASSERT(nopro); | ||
543 | return nopro; | ||
544 | } | ||
545 | return NULL; | ||
546 | } | ||
547 | |||
548 | main(int argc,char*argv[]) | ||
549 | { | ||
550 | if(argc<2){ | ||
551 | usagebye: | ||
552 | printf( | ||
553 | DAMN_KIN_NAME " " DAMN_KIN_VERSION ", Copyright (c) 1998, 2002 Klever Group (http://www.klever.net/)\n\n" | ||
554 | "Usage:\t" DAMN_KIN_NAME " [<options> ]<host-name/ip-address>[ <port>]\n\n" | ||
555 | "Options are:\n" | ||
556 | "-r## or -##\tSet number of rows in console screenbuffer\n" | ||
557 | "-c##\t\tSet number of columns in console screenbuffer\n" | ||
558 | "\tnote: changing console screenbuffer size may not work properly\n" | ||
559 | "\twhen in full-screen mode\n" | ||
560 | "-l<user>\tPass username to remote server in environment\n" | ||
561 | "-e<var>=<val>\tPass environment variable to remote server\n" | ||
562 | "-v<var>=<val>\tPass user environment variable to remote server\n" | ||
563 | "-t<termtype>\tChange preferred terminal type\n" | ||
564 | "\tnote: there are only two different terminal emulations in this\n" | ||
565 | "\tbeta release - one for dumb terminal and one for vt terminal\n" | ||
566 | ); | ||
567 | CleanEnvars(); | ||
568 | return 1; | ||
569 | } | ||
570 | if(!InitializeWinsock()){ | ||
571 | DeinitializeWinsock(); | ||
572 | return 2; | ||
573 | } | ||
574 | CONSOLE_SCREEN_BUFFER_INFO csbi; | ||
575 | int ac = 0; | ||
576 | CHAR *ho = NULL, *po = NULL; | ||
577 | HANDLE hConsole = CreateFile("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, | ||
578 | NULL,OPEN_EXISTING,0,NULL); | ||
579 | ASSERT(hConsole); | ||
580 | // *** GetStdHandle(STD_OUTPUT_HANDLE);// *?*?* Do something about redirections and not only here. | ||
581 | VERIFY(GetConsoleScreenBufferInfo(hConsole,&csbi)); | ||
582 | BOOL bSized=FALSE; | ||
583 | bTermPulled=FALSE; | ||
584 | for(int tmp=1;tmp<argc;tmp++){ | ||
585 | char* v = argv[tmp]; | ||
586 | ASSERT(v && *v); | ||
587 | if((*v)=='/' || (*v)=='-'){ | ||
588 | int lines = atoi(&v[1]); | ||
589 | if(lines){ | ||
590 | if(lines<csbi.dwSize.Y){ | ||
591 | SMALL_RECT wi = {0,0,csbi.dwSize.X-1,lines-1}; | ||
592 | VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi)); | ||
593 | } | ||
594 | COORD ns = {csbi.dwSize.X,lines}; | ||
595 | if(SetConsoleScreenBufferSize(hConsole,ns)) | ||
596 | bSized=TRUE; | ||
597 | }else if(v[1]=='r'){ | ||
598 | int lines = atoi(&v[2]); | ||
599 | if(lines){ | ||
600 | if(lines<csbi.dwSize.Y){ | ||
601 | SMALL_RECT wi = {0,0,csbi.dwSize.X-1,lines-1}; | ||
602 | VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi)); | ||
603 | } | ||
604 | COORD ns = {csbi.dwSize.X,lines}; | ||
605 | if(SetConsoleScreenBufferSize(hConsole,ns)) | ||
606 | bSized=TRUE; | ||
607 | }else | ||
608 | goto usagebye; | ||
609 | }else if(v[1]=='c'){ | ||
610 | int rows = atoi(&v[2]); | ||
611 | if(rows){ | ||
612 | if(rows<csbi.dwSize.X){ | ||
613 | SMALL_RECT wi = {0,0,rows-1,csbi.dwSize.Y-1}; | ||
614 | VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi)); | ||
615 | } | ||
616 | COORD ns = {rows,csbi.dwSize.Y}; | ||
617 | if(SetConsoleScreenBufferSize(hConsole,ns)) | ||
618 | bSized=TRUE; | ||
619 | }else | ||
620 | goto usagebye; | ||
621 | }else if(v[1]=='l'){ | ||
622 | CHAR* vv = &v[2]; | ||
623 | VERIFY(AddEnvar(nesbVar,"USER",vv)); | ||
624 | }else if(v[1]=='e'){ // -e<name>=<value>VAR | ||
625 | CHAR* n = &v[2]; | ||
626 | CHAR* vv = strchr(&v[2],'='); | ||
627 | if(!vv) | ||
628 | goto usagebye; | ||
629 | *(vv++)=0; | ||
630 | VERIFY(AddEnvar(nesbVar,n,vv)); | ||
631 | }else if(v[1]=='v'){ // -v<name>=<value>USERVAR | ||
632 | CHAR* n = &v[2]; | ||
633 | CHAR* vv = strchr(n,'='); | ||
634 | if(!vv) | ||
635 | goto usagebye; | ||
636 | *(vv++)=0; | ||
637 | VERIFY(AddEnvar(nesbUserVar,n,vv)); | ||
638 | }else if(v[1]=='t'){// -t<ttype> -t<tname>=<ttype> | ||
639 | CHAR* n = &v[2]; | ||
640 | CHAR* nn = strchr(n,'='); | ||
641 | if(nn){ | ||
642 | *(nn++)=0; | ||
643 | if(!*nn) | ||
644 | nn=NULL; | ||
645 | } | ||
646 | if(!TerminalPullType(nn?nn:n,nn?n:NULL)){ | ||
647 | printf("Available terminal types are:"); | ||
648 | TerminalPrintTypes(); | ||
649 | printf("\n"); | ||
650 | goto usagebye; | ||
651 | } | ||
652 | bTermPulled=TRUE; | ||
653 | }else if(v[1]=='#'){ | ||
654 | int cp = atoi(&v[2]); | ||
655 | #ifdef_DEBUG | ||
656 | TRACE2("SetCP(%d)=%d\n",cp,SetConsoleCP(cp)); | ||
657 | TRACE2("SetOutCP(%d)=%d\n",cp,SetConsoleOutputCP(cp)); | ||
658 | #else | ||
659 | SetConsoleCP(cp); | ||
660 | SetConsoleOutputCP(cp); | ||
661 | #endif | ||
662 | TRACE2("CP,OCP=%d,%d\n",GetConsoleCP(),GetConsoleOutputCP()); | ||
663 | }else | ||
664 | goto usagebye; | ||
665 | }else{ | ||
666 | if(ac==0){ | ||
667 | ho = v; | ||
668 | ac++; | ||
669 | }else if(ac==1){ | ||
670 | po = v; | ||
671 | ac++; | ||
672 | }else | ||
673 | goto usagebye; | ||
674 | } | ||
675 | } | ||
676 | if(!ho) | ||
677 | goto usagebye; | ||
678 | servent* se = getservbyname("telnet","tcp"); | ||
679 | UINT port = po?atol(po):(se?ntohs(se->s_port):23); | ||
680 | if(port==23 || (se && port==ntohs(se->s_port))) | ||
681 | bTelnet = TRUE; | ||
682 | if(po && !port){ | ||
683 | se = getservbyname(po,"tcp"); | ||
684 | if(!se){ | ||
685 | printf("Failed to resolve tcp-service port name\n"); | ||
686 | DeinitializeWinsock(); | ||
687 | return 2; | ||
688 | } | ||
689 | port = ntohs(se->s_port); | ||
690 | if(!stricmp(po,"telnet")) | ||
691 | bTelnet = TRUE; | ||
692 | else | ||
693 | bTelnet = FALSE; | ||
694 | }else{ | ||
695 | se = getservbyport(htons(port),"tcp"); | ||
696 | if(se){ | ||
697 | po = se->s_name; | ||
698 | if(!stricmp(po,"telnet")) | ||
699 | bTelnet=TRUE; | ||
700 | }else{ | ||
701 | VERIFY(_itoa(port,remoteProt,10)); | ||
702 | po = NULL; | ||
703 | bTelnet=FALSE; | ||
704 | } | ||
705 | } | ||
706 | if(po) | ||
707 | strcpy(remoteProt,po); | ||
708 | HICON hIcon = LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_IKON)); | ||
709 | LONG oldBIcon = NULL, oldSIcon = NULL; | ||
710 | hConsoleWindow = GetThisConsoleWnd(); | ||
711 | if(hConsoleWindow){ | ||
712 | oldBIcon = SendMessage(hConsoleWindow,WM_SETICON,ICON_BIG,(LPARAM)hIcon); | ||
713 | oldSIcon = SendMessage(hConsoleWindow,WM_SETICON,ICON_SMALL,(LPARAM)hIcon); | ||
714 | } | ||
715 | Telnet(ho,port); | ||
716 | CleanEnvars(); | ||
717 | if(hConsoleWindow){ | ||
718 | SendMessage(hConsoleWindow,WM_SETICON,ICON_BIG,(LPARAM)oldBIcon); | ||
719 | SendMessage(hConsoleWindow,WM_SETICON,ICON_SMALL,(LPARAM)oldSIcon); | ||
720 | } | ||
721 | Sleep(150); | ||
722 | if(bSized){ | ||
723 | CONSOLE_SCREEN_BUFFER_INFO CSBI; | ||
724 | VERIFY(GetConsoleScreenBufferInfo(hConsole,&CSBI)); | ||
725 | if(CSBI.dwSize.Y>csbi.dwSize.Y || CSBI.dwSize.X>csbi.dwSize.X){ | ||
726 | SMALL_RECT wi = {0,0,csbi.dwSize.X-1,csbi.dwSize.Y-1}; | ||
727 | VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi)); | ||
728 | } | ||
729 | COORD ns = {csbi.dwSize.X,csbi.dwSize.Y}; | ||
730 | VERIFY(SetConsoleScreenBufferSize(hConsole,ns)); | ||
731 | } | ||
732 | Sleep(100); | ||
733 | DeinitializeWinsock(); | ||
734 | Sleep(100); | ||
735 | return 0; | ||
736 | } | ||