1c2c66affSColin Finck ///////////////////////////////////////////////////////////////////////////////
2c2c66affSColin Finck //Telnet Win32 : an ANSI telnet client.
3c2c66affSColin Finck //Copyright (C) 1998  Paul Brannan
4c2c66affSColin Finck //Copyright (C) 1998  I.Ioannou
5c2c66affSColin Finck //Copyright (C) 1997  Brad Johnson
6c2c66affSColin Finck //
7c2c66affSColin Finck //This program is free software; you can redistribute it and/or
8c2c66affSColin Finck //modify it under the terms of the GNU General Public License
9c2c66affSColin Finck //as published by the Free Software Foundation; either version 2
10c2c66affSColin Finck //of the License, or (at your option) any later version.
11c2c66affSColin Finck //
12c2c66affSColin Finck //This program is distributed in the hope that it will be useful,
13c2c66affSColin Finck //but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c2c66affSColin Finck //GNU General Public License for more details.
16c2c66affSColin Finck //
17c2c66affSColin Finck //You should have received a copy of the GNU General Public License
18c2c66affSColin Finck //along with this program; if not, write to the Free Software
19c2c66affSColin Finck //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20c2c66affSColin Finck //
21c2c66affSColin Finck //I.Ioannou
22c2c66affSColin Finck //roryt@hol.gr
23c2c66affSColin Finck //
24c2c66affSColin Finck ///////////////////////////////////////////////////////////////////////////
25c2c66affSColin Finck 
26c2c66affSColin Finck ///////////////////////////////////////////////////////////////////////////////
27c2c66affSColin Finck //
28c2c66affSColin Finck // Module:		tnmain.cpp
29c2c66affSColin Finck //
30c2c66affSColin Finck // Contents:	telnet main program
31c2c66affSColin Finck //
32c2c66affSColin Finck // Product:		telnet
33c2c66affSColin Finck //
34c2c66affSColin Finck // Revisions: August 11, 1998	Thomas Briggs <tbriggs@qmetric.com>
35c2c66affSColin Finck //            May 14, 1998		Paul Brannan <pbranna@clemson.edu>
36c2c66affSColin Finck //            5.April.1997		jbj@nounname.com
37c2c66affSColin Finck //            5.Dec.1996		jbj@nounname.com
38c2c66affSColin Finck //            Version 2.0
39c2c66affSColin Finck //
40c2c66affSColin Finck //            02.Apr.1995		igor.milavec@uni-lj.si
41c2c66affSColin Finck //					  Original code
42c2c66affSColin Finck //
43c2c66affSColin Finck ///////////////////////////////////////////////////////////////////////////////
44c2c66affSColin Finck 
45c2c66affSColin Finck #include "precomp.h"
46c2c66affSColin Finck 
47c2c66affSColin Finck #include "tnmain.h"
48c2c66affSColin Finck 
49c2c66affSColin Finck int telCommandLine (Telnet &MyConnection);
50c2c66affSColin Finck 
waitforkey()51c2c66affSColin Finck void waitforkey() {
52c2c66affSColin Finck 	HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
53c2c66affSColin Finck 	INPUT_RECORD InputRecord;
54c2c66affSColin Finck 	DWORD dwInput;
55c2c66affSColin Finck 	BOOL done = FALSE;
56c2c66affSColin Finck 	while (!done){
57c2c66affSColin Finck 		WaitForSingleObject( hConsole, INFINITE );
58c2c66affSColin Finck 		if (!ReadConsoleInput(hConsole, &InputRecord, 1, &dwInput)){
59c2c66affSColin Finck 			done = TRUE;
60c2c66affSColin Finck 			continue;
61c2c66affSColin Finck 		}
62c2c66affSColin Finck 		if (InputRecord.EventType == KEY_EVENT &&
63c2c66affSColin Finck 			InputRecord.Event.KeyEvent.bKeyDown )
64c2c66affSColin Finck 			done = TRUE;
65c2c66affSColin Finck 	}
66c2c66affSColin Finck }
67c2c66affSColin Finck 
68c2c66affSColin Finck //char * cfgets ( char * buf, unsigned int length, char pszHistory[][80], int iHistLength){
cfgets(char * buf,unsigned int length,struct cmdHistory * cmdhist)69c2c66affSColin Finck struct cmdHistory * cfgets (char *buf, unsigned int length, struct cmdHistory *cmdhist) {
70c2c66affSColin Finck 
71c2c66affSColin Finck 	HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
72c2c66affSColin Finck 	unsigned int current=0, cursor =0, iEraseLength=0, i;
73c2c66affSColin Finck 	char chr;
74c2c66affSColin Finck 	char temp[2];
75c2c66affSColin Finck 	char temp1[80];
76c2c66affSColin Finck 
77c2c66affSColin Finck 	INPUT_RECORD InputRecord;
78c2c66affSColin Finck 	BOOL done = FALSE;
79c2c66affSColin Finck 
80c2c66affSColin Finck 	temp[1] = 0;
81c2c66affSColin Finck 	buf[0] = '\0';
82c2c66affSColin Finck 
83c2c66affSColin Finck 	if(!ini.get_input_redir()) {
84c2c66affSColin Finck 		while (!done) {
85c2c66affSColin Finck 			DWORD dwInput;
86c2c66affSColin Finck 			int MustRefresh = 0;
87c2c66affSColin Finck 			WaitForSingleObject( hConsole, INFINITE );
88c2c66affSColin Finck 			if (!ReadConsoleInput(hConsole, &InputRecord, 1, &dwInput)){
89c2c66affSColin Finck 				done = TRUE;
90c2c66affSColin Finck 				continue;
91c2c66affSColin Finck 			}
92c2c66affSColin Finck 			MustRefresh = 0;
93c2c66affSColin Finck 			if (InputRecord.EventType == KEY_EVENT &&
94c2c66affSColin Finck 				InputRecord.Event.KeyEvent.bKeyDown ) {
95c2c66affSColin Finck 
96c2c66affSColin Finck 				if(InputRecord.Event.KeyEvent.dwControlKeyState &
97c2c66affSColin Finck 					(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
98c2c66affSColin Finck 
99c2c66affSColin Finck 					switch(InputRecord.Event.KeyEvent.wVirtualKeyCode) {
100c2c66affSColin Finck 					case 'D': // Thomas Briggs 8/11/98
101c2c66affSColin Finck 						buf[0] = '\04';
102c2c66affSColin Finck 						buf[1] = '\0';
103c2c66affSColin Finck 						current = 1;
104c2c66affSColin Finck 						done = true;
105c2c66affSColin Finck 						continue;
106c2c66affSColin Finck 					case 'U': // Paul Brannan 8/11/98
107c2c66affSColin Finck 						buf[0] = '\0';
108c2c66affSColin Finck 						current = 0;
109c2c66affSColin Finck 						cursor = 0;
110c2c66affSColin Finck 						MustRefresh = 1;
111c2c66affSColin Finck 						break;
112c2c66affSColin Finck 					}
113c2c66affSColin Finck 				}
114c2c66affSColin Finck 
115c2c66affSColin Finck 				switch (InputRecord.Event.KeyEvent.wVirtualKeyCode) {
116c2c66affSColin Finck 				case VK_UP:
117c2c66affSColin Finck 					// crn@ozemail.com.au
118c2c66affSColin Finck 					if (cmdhist != NULL) {
119c2c66affSColin Finck 						if (!strcmp(buf, ""))
120c2c66affSColin Finck 							strncpy(buf, cmdhist->cmd, 79);
121c2c66affSColin Finck 						else if (cmdhist->prev != NULL) {
122c2c66affSColin Finck 							cmdhist = cmdhist->prev;
123c2c66affSColin Finck 							strncpy(buf, cmdhist->cmd, 79);
124c2c66affSColin Finck 						}
125c2c66affSColin Finck 						current = strlen(buf);
126c2c66affSColin Finck 					}
127c2c66affSColin Finck 					///
128c2c66affSColin Finck 					MustRefresh = 1;
129c2c66affSColin Finck 					break;
130c2c66affSColin Finck 				case VK_DOWN:
131c2c66affSColin Finck 					// crn@ozemail.com.au
132c2c66affSColin Finck 					if (cmdhist != NULL) {
133c2c66affSColin Finck 						if (cmdhist->next != NULL) {
134c2c66affSColin Finck 							cmdhist = cmdhist->next;
135c2c66affSColin Finck 							strncpy(buf, cmdhist->cmd, 79);
136c2c66affSColin Finck 						} else {
137c2c66affSColin Finck 							strncpy(buf, "", 79);
138c2c66affSColin Finck 						}
139c2c66affSColin Finck 						current = strlen(buf);
140c2c66affSColin Finck 					}
141c2c66affSColin Finck 					///
142c2c66affSColin Finck 					MustRefresh = 1;
143c2c66affSColin Finck 					break;
144c2c66affSColin Finck 				case VK_RIGHT:		//crn@ozemail.com.au (added ctrl+arrow)
145c2c66affSColin Finck 					if (cursor < current) {
146c2c66affSColin Finck 						if (InputRecord.Event.KeyEvent.dwControlKeyState &
147c2c66affSColin Finck 							(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
148c2c66affSColin Finck 							unsigned int j, k;
149c2c66affSColin Finck                             for (j = cursor; j <= current; j++)
150fdf221cbSTimo Kreuzer                             {
151c2c66affSColin Finck                                 if (buf[j + 1] == ' ' || (j + 1) == current)
152c2c66affSColin Finck                                     break;
153c2c66affSColin Finck                                 for (k = ++j; k <= current; k++)
154fdf221cbSTimo Kreuzer                                 {
155c2c66affSColin Finck                                     if (buf[k] != ' ' || k == current) {
156c2c66affSColin Finck                                         cursor = k == current ? --k : k;
157c2c66affSColin Finck                                         break;
158c2c66affSColin Finck                                     }
159fdf221cbSTimo Kreuzer                                 }
160fdf221cbSTimo Kreuzer                             }
161c2c66affSColin Finck 						} else
162c2c66affSColin Finck 							cursor++;
163c2c66affSColin Finck 						MustRefresh = 1;
164c2c66affSColin Finck 						break;
165c2c66affSColin Finck 					}
166c2c66affSColin Finck 				case VK_LEFT:		//crn@ozemail.com.au (added ctrl+arrow)
167c2c66affSColin Finck 					if (cursor > 0) {
168c2c66affSColin Finck 						if(InputRecord.Event.KeyEvent.dwControlKeyState &
169c2c66affSColin Finck 							(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
170c2c66affSColin Finck 							int j, k;
171c2c66affSColin Finck                             for (j = cursor; j >= 0; j--)
172*194180b1STimo Kreuzer                             {
173c2c66affSColin Finck                                 if (buf[j - 1] != ' ')
174c2c66affSColin Finck                                     break;
175c2c66affSColin Finck                                 for (k = --j; k >= 0; k--)
176*194180b1STimo Kreuzer                                 {
177c2c66affSColin Finck                                     if (buf[k] == ' ' || k == 0) {
178c2c66affSColin Finck                                         cursor = !k ? k : ++k;
179c2c66affSColin Finck                                         break;
180c2c66affSColin Finck                                     }
181*194180b1STimo Kreuzer                                 }
182*194180b1STimo Kreuzer                             }
183c2c66affSColin Finck 						} else
184c2c66affSColin Finck 							cursor--;
185c2c66affSColin Finck 						MustRefresh = 1;
186c2c66affSColin Finck 						break;
187c2c66affSColin Finck 					}
188c2c66affSColin Finck 				case VK_HOME:
189c2c66affSColin Finck 					if (cursor>0) cursor = 0;
190c2c66affSColin Finck 					MustRefresh = 1;
191c2c66affSColin Finck 					break;
192c2c66affSColin Finck 				case VK_END:
193c2c66affSColin Finck 					if (cursor<current) cursor = current;
194c2c66affSColin Finck 					MustRefresh = 1;
195c2c66affSColin Finck 					break;
196c2c66affSColin Finck 				case VK_DELETE:
197c2c66affSColin Finck 					if (current > 0 && current > cursor) {
198c2c66affSColin Finck 						strcpy(&buf[cursor],&buf[cursor+1]);
199c2c66affSColin Finck 						current--;
200c2c66affSColin Finck 						buf[current] = 0;
201c2c66affSColin Finck 						printit("\r");
202c2c66affSColin Finck 						for (i = 0; i < current+strlen("telnet>")+1 ;i++)
203c2c66affSColin Finck 							printit(" ");
204c2c66affSColin Finck 					}
205c2c66affSColin Finck 					MustRefresh = 1;
206c2c66affSColin Finck 					break;
207c2c66affSColin Finck 				case VK_BACK:
208c2c66affSColin Finck 					if (cursor > 0 ) {
209c2c66affSColin Finck 						strcpy(&buf[cursor-1],&buf[cursor]);
210c2c66affSColin Finck 						current--;
211c2c66affSColin Finck 						cursor--;
212c2c66affSColin Finck 						buf[current] = 0;
213c2c66affSColin Finck 						printit("\r");
214c2c66affSColin Finck 						for (i = 0; i < current+strlen("telnet>")+1 ;i++)
215c2c66affSColin Finck 							printit(" ");
216c2c66affSColin Finck 					}
217c2c66affSColin Finck 					MustRefresh = 1;
218c2c66affSColin Finck 					break;
219c2c66affSColin Finck 
220c2c66affSColin Finck 				default:
221c2c66affSColin Finck 					chr = InputRecord.Event.KeyEvent.uChar.AsciiChar;
222c2c66affSColin Finck 					if (chr == '\r') {
223c2c66affSColin Finck 						done = TRUE;
224c2c66affSColin Finck 						continue;
225c2c66affSColin Finck 					}
226c2c66affSColin Finck 					if (current >= length-1){
227c2c66affSColin Finck 						done = TRUE;
228c2c66affSColin Finck 						continue;
229c2c66affSColin Finck 					}
230c2c66affSColin Finck 					if ( isprint (chr) ){
231c2c66affSColin Finck 						strncpy(temp1,&buf[cursor],79);
232c2c66affSColin Finck 						strncpy(&buf[cursor+1],temp1,79-(cursor+1));
233c2c66affSColin Finck 						buf[cursor++]=chr;
234c2c66affSColin Finck 						current++;
235c2c66affSColin Finck 						buf[current] = 0;
236c2c66affSColin Finck 						MustRefresh = 1;
237c2c66affSColin Finck 					}
238c2c66affSColin Finck 					break;
239c2c66affSColin Finck 				}
240c2c66affSColin Finck 				if (MustRefresh == 1)
241c2c66affSColin Finck 				{
242c2c66affSColin Finck 					printit("\rtelnet");
243c2c66affSColin Finck 					for (i = 0; i <= iEraseLength ;i++)
244c2c66affSColin Finck 						printit(" ");
245c2c66affSColin Finck 					printit("\rtelnet>");
246c2c66affSColin Finck 					printit(buf);
247c2c66affSColin Finck 					iEraseLength = strlen(buf);
248c2c66affSColin Finck 					for (i = 0; i < current-cursor; i++)
249c2c66affSColin Finck 						printit("\b");
250c2c66affSColin Finck 				}
251c2c66affSColin Finck 			}
252c2c66affSColin Finck 		}
253c2c66affSColin Finck 		buf[current] = 0;
254c2c66affSColin Finck 		if (strcmp(buf, "")) {
255c2c66affSColin Finck 			if (cmdhist == NULL) {
256c2c66affSColin Finck 				cmdhist = new struct cmdHistory;
257c2c66affSColin Finck 				if (cmdhist == NULL) {
258c2c66affSColin Finck 					printit ("\nUnable to allocate memory for history buffer -- use the \"flush\" command to clear the buffer.\n");
259c2c66affSColin Finck 					return cmdhist;
260c2c66affSColin Finck 				}
261c2c66affSColin Finck 				strncpy(cmdhist->cmd, buf, 79);
262c2c66affSColin Finck 				cmdhist->next = NULL;
263c2c66affSColin Finck 				cmdhist->prev = NULL;
264c2c66affSColin Finck 			} else {
265c2c66affSColin Finck 				while (cmdhist->next != NULL)	//  move to the end of the list
266c2c66affSColin Finck 					cmdhist = cmdhist->next;
267c2c66affSColin Finck 				cmdhist->next = new struct cmdHistory;
268c2c66affSColin Finck 				if (cmdhist->next == NULL) {
269c2c66affSColin Finck 					printit ("\nUnable to allocate memory for history buffer -- use the \"flush\" command to clear the buffer.\n");
270c2c66affSColin Finck 					return cmdhist;
271c2c66affSColin Finck 				}
272c2c66affSColin Finck 				cmdhist->next->prev = cmdhist;	//  previous is where we are now
273c2c66affSColin Finck 				cmdhist = cmdhist->next;
274c2c66affSColin Finck 				strncpy(cmdhist->cmd, buf, 79);
275c2c66affSColin Finck 				cmdhist->next = NULL;
276c2c66affSColin Finck 			}
277c2c66affSColin Finck 			while (cmdhist->next)
278c2c66affSColin Finck 				cmdhist = cmdhist->next;
279c2c66affSColin Finck 		}
280c2c66affSColin Finck 		return cmdhist;
281c2c66affSColin Finck 		///
282c2c66affSColin Finck 	} else {
283c2c66affSColin Finck 		WaitForSingleObject( hConsole, INFINITE );
284c2c66affSColin Finck 		DWORD dwInput;
285c2c66affSColin Finck 		DWORD OldMode;
286c2c66affSColin Finck 		GetConsoleMode(hConsole, &OldMode);
287c2c66affSColin Finck 		SetConsoleMode(hConsole,
288c2c66affSColin Finck 			OldMode &~ (ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT) );
289c2c66affSColin Finck 		while (ReadFile(hConsole, &chr, 1, &dwInput, NULL)) {
290c2c66affSColin Finck 			if (chr == '\r') {
291c2c66affSColin Finck 				temp[0] = chr;
292c2c66affSColin Finck 				printit(&temp[0]);
293c2c66affSColin Finck 				break;
294c2c66affSColin Finck 			}
295c2c66affSColin Finck 			if (chr == '\b' && current > 0) {
296c2c66affSColin Finck 				current--;
297c2c66affSColin Finck 				printit("\b \b");
298c2c66affSColin Finck 			}
299c2c66affSColin Finck 			if (current >= length-1){
300c2c66affSColin Finck 				break;
301c2c66affSColin Finck 			}
302c2c66affSColin Finck 			if ( isprint (chr) ){
303c2c66affSColin Finck 				temp[0] = chr;
304c2c66affSColin Finck 				printit(&temp[0]);
305c2c66affSColin Finck 				buf[current++]=chr;
306c2c66affSColin Finck 			}
307c2c66affSColin Finck 		}
308c2c66affSColin Finck 		buf[current] = 0;
309c2c66affSColin Finck 		SetConsoleMode(hConsole, OldMode);
310c2c66affSColin Finck 		return NULL;
311c2c66affSColin Finck 	}
312c2c66affSColin Finck }
313c2c66affSColin Finck 
314c2c66affSColin Finck // AVS ** for fix bug in command 'keys load keymapname' without file
315c2c66affSColin Finck // static char keyfile[MAX_PATH*2];
316c2c66affSColin Finck 
main(int ArgC,char * ArgV[])317c2c66affSColin Finck int main(int ArgC, char* ArgV[]) {
318c2c66affSColin Finck 
319c2c66affSColin Finck 	CONSOLE_SCREEN_BUFFER_INFO  ConsoleScreenBufferInfo;
320c2c66affSColin Finck 	GetConsoleScreenBufferInfo(
321c2c66affSColin Finck 		GetStdHandle(STD_OUTPUT_HANDLE),
322c2c66affSColin Finck 		&ConsoleScreenBufferInfo
323c2c66affSColin Finck 		);
324c2c66affSColin Finck 
325c2c66affSColin Finck 	char *k;
326c2c66affSColin Finck 	char startdir[MAX_PATH*2];
327c2c66affSColin Finck 	char exename[MAX_PATH];
328c2c66affSColin Finck 
329c2c66affSColin Finck 	// strncpy(startdir, ArgV[0],MAX_PATH);
330c2c66affSColin Finck 	// This should be more accurate than using argv[0] (Paul Brannan 9/16/98)
331c2c66affSColin Finck 	GetModuleFileName(NULL, startdir, sizeof(startdir));
332c2c66affSColin Finck 
333c2c66affSColin Finck 	// Get the current console title so it can be set later
334c2c66affSColin Finck 	// ("Pedro A. Aranda Guti�rrez" <paag@coppi.tid.es>)
335c2c66affSColin Finck 	TCHAR ConsoleTitle[255];
336c2c66affSColin Finck 	GetConsoleTitle(ConsoleTitle, sizeof(ConsoleTitle));
337c2c66affSColin Finck 
338c2c66affSColin Finck 	k = strrchr(startdir, '\\');
339c2c66affSColin Finck 	if (k == NULL){						// if the \ character is not found...
340c2c66affSColin Finck 		strcpy(exename, startdir);
341c2c66affSColin Finck 		strcpy(startdir,"");			// set the path to nothing
342c2c66affSColin Finck 	} else {
343c2c66affSColin Finck 		// end the string after the last '\' to get rid of the file name
344c2c66affSColin Finck 		strcpy(exename, k+1);
345c2c66affSColin Finck 		k[1] = 0;
346c2c66affSColin Finck 	}
347c2c66affSColin Finck 
348c2c66affSColin Finck 	printm(0, FALSE, MSG_COPYRIGHT);
349c2c66affSColin Finck 	printm(0, FALSE, MSG_COPYRIGHT_1);
350c2c66affSColin Finck 
351c2c66affSColin Finck 	// set up the ini class
352c2c66affSColin Finck 	ini.init(startdir, exename);
353c2c66affSColin Finck 
354c2c66affSColin Finck 	// Process the command line arguments and connect to a host if necessary
355c2c66affSColin Finck 	if(ini.Process_Params(ArgC, ArgV)) {
356c2c66affSColin Finck 		const char *szHost = ini.get_host();
357c2c66affSColin Finck 		const char *strPort = ini.get_port();
358c2c66affSColin Finck 		if(!*szHost) {
359c2c66affSColin Finck 			Telnet MyConnection;
360c2c66affSColin Finck 			while(telCommandLine(MyConnection));
361c2c66affSColin Finck 		} else {
362c2c66affSColin Finck 			Telnet MyConnection;
363c2c66affSColin Finck 			if(MyConnection.Open(szHost, strPort) == TNPROMPT) {
364c2c66affSColin Finck 				// still connected
365c2c66affSColin Finck 				printit("\n");
366c2c66affSColin Finck 				telCommandLine(MyConnection);
367c2c66affSColin Finck 			}
368c2c66affSColin Finck 		}
369c2c66affSColin Finck 	}
370c2c66affSColin Finck 	//// (Paul Brannan 5/14/98)
371c2c66affSColin Finck 
372c2c66affSColin Finck 	if(ini.get_term_width() != -1 || ini.get_term_height() != -1) {
373c2c66affSColin Finck 		SetConsoleScreenBufferSize(
374c2c66affSColin Finck 			GetStdHandle(STD_OUTPUT_HANDLE),	// handle of console screen buffer
375c2c66affSColin Finck 			ConsoleScreenBufferInfo.dwSize		// new size in character rows and cols.
376c2c66affSColin Finck 			);
377c2c66affSColin Finck 		SetConsoleWindowInfo(
378c2c66affSColin Finck 			GetStdHandle(STD_OUTPUT_HANDLE),	// handle of console screen buffer
379c2c66affSColin Finck 			TRUE,								// coordinate type flag
380c2c66affSColin Finck 			&ConsoleScreenBufferInfo.srWindow 	// address of new window rectangle
381c2c66affSColin Finck 			);
382c2c66affSColin Finck 	}
383c2c66affSColin Finck 	SetConsoleTextAttribute(
384c2c66affSColin Finck 		GetStdHandle(STD_OUTPUT_HANDLE),		// handle of console screen buffer
385c2c66affSColin Finck 		ConsoleScreenBufferInfo.wAttributes 	// text and background colors
386c2c66affSColin Finck 		);
387c2c66affSColin Finck 
388c2c66affSColin Finck 	// Restore the original console title
389c2c66affSColin Finck 	// ("Pedro A. Aranda Guti�rrez" <paag@coppi.tid.es>)
390c2c66affSColin Finck 	SetConsoleTitle(ConsoleTitle);
391c2c66affSColin Finck 
392c2c66affSColin Finck 	return 0;
393c2c66affSColin Finck }
394c2c66affSColin Finck 
395c2c66affSColin Finck // AVS
396c2c66affSColin Finck enum {
397c2c66affSColin Finck 	BAD_USAGE = -3,
398c2c66affSColin Finck 		EMPTY_LINE = -2,
399c2c66affSColin Finck 		INVALID_CMD = -1,
400c2c66affSColin Finck 		__FIRST_COMMAND = 0,
401c2c66affSColin Finck 
402c2c66affSColin Finck 		OPEN = __FIRST_COMMAND,
403c2c66affSColin Finck 		CLOSE,
404c2c66affSColin Finck 		KEYS,
405c2c66affSColin Finck 		QUIT,
406c2c66affSColin Finck 		HELP,
407c2c66affSColin Finck 		HELP2,				// there is way for synonims
408c2c66affSColin Finck 		K_LOAD,				// subcommand of 'keys'
409c2c66affSColin Finck 		K_SWITCH,			// subcommand of 'keys'
410c2c66affSColin Finck 		K_DISPLAY,			// subcommand of 'keys'
411c2c66affSColin Finck 
412c2c66affSColin Finck 		SET,				// Paul Brannan 5/30/98
413c2c66affSColin Finck 
414c2c66affSColin Finck 		SUSPEND,
415c2c66affSColin Finck 		FASTQUIT,			// Thomas Briggs 8/11/98
416c2c66affSColin Finck 		CMD_HISTORY,		// crn@ozemail.com.au
417c2c66affSColin Finck 		CLEAR_HISTORY,		// crn@ozemail.com.au
418c2c66affSColin Finck 
419c2c66affSColin Finck 		ALIASES,			// Paul Brannan 1/1/99
420c2c66affSColin Finck 
421c2c66affSColin Finck 		__COMMAND_LIST_SIZE	// must be last
422c2c66affSColin Finck };
423c2c66affSColin Finck 
424c2c66affSColin Finck 
425c2c66affSColin Finck struct command {
426c2c66affSColin Finck 	const char* cmd;				// command
427c2c66affSColin Finck 	int   minLen,			// minimal length for match
428c2c66affSColin Finck 		  minParms,			// minimal count of parms
429c2c66affSColin Finck 		  maxParms;			// maximal -/- (negative disables)
430c2c66affSColin Finck 	int   isSubCmd,			// is a subcommand - number of wich command
431c2c66affSColin Finck 		  haveSubCmd;		// have subcommands? 0 or 1
432c2c66affSColin Finck 	const char* usage;			// text of usage
433c2c66affSColin Finck };
434c2c66affSColin Finck 
435c2c66affSColin Finck command cmdList[__COMMAND_LIST_SIZE] = {
436c2c66affSColin Finck 	{"open",     1,	1,  2,	-1,		0,	"o[pen] host [port]\n"},
437c2c66affSColin Finck 	{"close",    2,	0,  0,	-1,		0,	NULL},
438c2c66affSColin Finck 	{"keys",     2,	1,  3,	-1,		1,	"ke[ys] l[oad] keymapname [file]\n"
439c2c66affSColin Finck 										"ke[ys] d[isplay]\n"
440c2c66affSColin Finck 										"ke[ys] s[witch] number\n"},
441c2c66affSColin Finck 	// Ioannou : i change it to q, to be more compatible with unix telnet
442c2c66affSColin Finck 	{"quit",     1,	0,  0,	-1,		0,	NULL}, // must type it exactly
443c2c66affSColin Finck 	{"?",        1,	0,  0,	-1,		0,	NULL},
444c2c66affSColin Finck 	{"help",     1,	0,  0,	-1,		0,	NULL},
445c2c66affSColin Finck 	{"load",     1,	1,  2,	KEYS,	0,	NULL},
446c2c66affSColin Finck 	{"switch",   1,	1,  1,	KEYS,	0,	NULL},
447c2c66affSColin Finck 	{"display",  1,	0,  0,	KEYS,	0,	NULL},
448c2c66affSColin Finck 	// Paul Brannan 5/30/98
449c2c66affSColin Finck 	{"set",      3,	0,	2,	-1,		0,	"set will display available groups.\n"
450c2c66affSColin Finck 										"set groupname will display all variables/values in a group.\n"
451c2c66affSColin Finck 										"set [variable [value]] will set variable to value.\n"},
452c2c66affSColin Finck 	// Thomas Briggs 8/11/98
453c2c66affSColin Finck 	{"z",		1,	0,	0,	-1,		0,	"suspend telnet\n"},
454c2c66affSColin Finck 	{"\04",		1,	0,	0,	-1,		0,	NULL},
455c2c66affSColin Finck 	// crn@ozemail.com.au
456c2c66affSColin Finck 	{"history",	2,	0,	0,	-1,	0,	"show command history"},
457c2c66affSColin Finck 	{"flush",	2,	0,	0,	-1,	0,	"flush history buffer"},
458c2c66affSColin Finck 	// Paul Brannan 1/1/99
459c2c66affSColin Finck 	{"aliases",	5,	0,	0,	-1,		0,	NULL}
460c2c66affSColin Finck };
461c2c66affSColin Finck 
462c2c66affSColin Finck // a maximal count of parms
463c2c66affSColin Finck #define MAX_PARM_COUNT 3
464c2c66affSColin Finck #define MAX_TOKEN_COUNT (MAX_PARM_COUNT+2)
465c2c66affSColin Finck 
cmdMatch(const char * cmd,const char * token,int tokenLen,int minM)466c2c66affSColin Finck static int cmdMatch(const char* cmd, const char* token, int tokenLen, int minM) {
467c2c66affSColin Finck     if ( tokenLen < minM ) return 0;
468c2c66affSColin Finck 	// The (unsigned) gets rid of a compiler warning (Paul Brannan 5/25/98)
469c2c66affSColin Finck     if ( (unsigned)tokenLen > strlen(cmd) ) return 0;
470c2c66affSColin Finck     if ( strcmp(cmd,token) == 0 ) return 1;
471c2c66affSColin Finck 
472c2c66affSColin Finck     int i;
473c2c66affSColin Finck     for ( i = 0; i < minM; i++ ) if ( cmd[i] != token[i] ) return 0;
474c2c66affSColin Finck 
475c2c66affSColin Finck     for ( i = minM; i < tokenLen; i++ ) if ( cmd[i] != token[i] ) return 0;
476c2c66affSColin Finck 
477c2c66affSColin Finck     return 1;
478c2c66affSColin Finck };
479c2c66affSColin Finck 
printUsage(int cmd)480c2c66affSColin Finck static void printUsage(int cmd) {
481c2c66affSColin Finck 	if ( cmdList[cmd].usage != NULL ) {
482c2c66affSColin Finck 		printit(cmdList[cmd].usage);
483c2c66affSColin Finck 		return;
484c2c66affSColin Finck 	};
485c2c66affSColin Finck 	if ( cmdList[cmd].isSubCmd >= 0 ) {
486c2c66affSColin Finck 		printUsage(cmdList[cmd].isSubCmd);
487c2c66affSColin Finck 		return;
488c2c66affSColin Finck 	   }
489c2c66affSColin Finck 	   printm(0, FALSE, MSG_BADUSAGE);
490c2c66affSColin Finck };
491c2c66affSColin Finck 
tokenizeCommand(char * szCommand,int & argc,char ** argv)492c2c66affSColin Finck int tokenizeCommand(char* szCommand, int& argc, char** argv) {
493c2c66affSColin Finck     char* tokens[MAX_TOKEN_COUNT];
494c2c66affSColin Finck     char* p;
495c2c66affSColin Finck     int   args = 0;
496c2c66affSColin Finck 
497c2c66affSColin Finck 	if(!szCommand || !*szCommand) return EMPTY_LINE;
498c2c66affSColin Finck 
499c2c66affSColin Finck 	// Removed strtok to handle tokens with spaces; this is handled with
500c2c66affSColin Finck 	// quotes.  (Paul Brannan 3/18/99)
501c2c66affSColin Finck 	char *token_start = szCommand;
502c2c66affSColin Finck 	for(p = szCommand;; p++) {
503c2c66affSColin Finck 		if(*p == '\"') {
504c2c66affSColin Finck 			char *tmp = p;
505c2c66affSColin Finck 			for(p++; *p != '\"' && *p != 0; p++);	// Find the next quote
506c2c66affSColin Finck 			if(*p != 0) strcpy(p, p + 1);			// Remove quote#2
507c2c66affSColin Finck 			strcpy(tmp, tmp + 1);					// Remove quote#1
508c2c66affSColin Finck 		}
509c2c66affSColin Finck 		if(*p == 0 || *p == ' ' || *p == '\t') {
510c2c66affSColin Finck 			tokens[args] = token_start;
511c2c66affSColin Finck 			args++;
512c2c66affSColin Finck 			if(args >= MAX_TOKEN_COUNT) break;		// Break if too many args
513c2c66affSColin Finck 			token_start = p + 1;
514c2c66affSColin Finck 			if(*p == 0) break;
515c2c66affSColin Finck 			*p = 0;
516c2c66affSColin Finck 		}
517c2c66affSColin Finck 	}
518c2c66affSColin Finck 	// while ( (p = strtok((args?NULL:szCommand), " \t")) != NULL && args < MAX_TOKEN_COUNT ) {
519c2c66affSColin Finck 	// 	tokens[args] = p;
520c2c66affSColin Finck 	// 	args++;
521c2c66affSColin Finck 	// };
522c2c66affSColin Finck 
523c2c66affSColin Finck     if ( !args ) return EMPTY_LINE;
524c2c66affSColin Finck     argc = args - 1;
525c2c66affSColin Finck     args = 0;
526c2c66affSColin Finck     int curCmd = -1;
527c2c66affSColin Finck     int ok = -1;
528c2c66affSColin Finck     while ( ok < 0 ) {
529c2c66affSColin Finck 		int tokenLen = strlen(tokens[args]);
530c2c66affSColin Finck 		int match = 0;
531c2c66affSColin Finck 		for ( int i = 0; i<__COMMAND_LIST_SIZE; i++ ) {
532c2c66affSColin Finck 			if ( cmdMatch(cmdList[i].cmd, tokens[args], tokenLen, cmdList[i].minLen) ) {
533c2c66affSColin Finck 				if (argc < cmdList[i].minParms || argc > cmdList[i].maxParms) {
534c2c66affSColin Finck 					printUsage(i);
535c2c66affSColin Finck 					return BAD_USAGE;
536c2c66affSColin Finck 				};
537c2c66affSColin Finck 				if ( cmdList[i].haveSubCmd && curCmd == cmdList[i].isSubCmd) {
538c2c66affSColin Finck 					curCmd = i;
539c2c66affSColin Finck 					args++;
540c2c66affSColin Finck 					argc--;
541c2c66affSColin Finck 					match = 1;
542c2c66affSColin Finck 					break;
543c2c66affSColin Finck 				};
544c2c66affSColin Finck 				if ( curCmd == cmdList[i].isSubCmd ) {
545c2c66affSColin Finck 					ok = i;
546c2c66affSColin Finck 					match = 1;
547c2c66affSColin Finck 					break;
548c2c66affSColin Finck 				};
549c2c66affSColin Finck 				printUsage(i);
550c2c66affSColin Finck 				return BAD_USAGE;
551c2c66affSColin Finck 			};
552c2c66affSColin Finck 		};
553c2c66affSColin Finck 		if ( !match ) {
554c2c66affSColin Finck 			if ( curCmd < 0 ) return INVALID_CMD;
555c2c66affSColin Finck 			printUsage(curCmd);
556c2c66affSColin Finck 			return -3;
557c2c66affSColin Finck 		};
558c2c66affSColin Finck     };
559c2c66affSColin Finck 
560c2c66affSColin Finck     for ( int i = 0; i<argc; i++ ) {
561c2c66affSColin Finck         argv[i] = tokens[i+args+1];
562c2c66affSColin Finck     };
563c2c66affSColin Finck     return ok;
564c2c66affSColin Finck 
565c2c66affSColin Finck };
566c2c66affSColin Finck 
telCommandLine(Telnet & MyConnection)567c2c66affSColin Finck int telCommandLine (Telnet &MyConnection){
568c2c66affSColin Finck #define HISTLENGTH 25
569c2c66affSColin Finck 	int i, retval;
570c2c66affSColin Finck 	char* Parms[MAX_PARM_COUNT];
571c2c66affSColin Finck 	char szCommand[80];
572c2c66affSColin Finck 	int bDone = 0;
573c2c66affSColin Finck 	char *extitle, *newtitle;
574c2c66affSColin Finck 	struct cmdHistory *cmdhist;
575c2c66affSColin Finck 	cmdhist = NULL;
576c2c66affSColin Finck 
577c2c66affSColin Finck 	// printit("\n");  // crn@ozemail.com.au 14/12/98
578c2c66affSColin Finck 	while (!bDone){
579c2c66affSColin Finck 		// printit("\n"); // Paul Brannan 5/25/98
580c2c66affSColin Finck 		printit( "telnet>");
581c2c66affSColin Finck 		cmdhist = cfgets (szCommand, 79, cmdhist);
582c2c66affSColin Finck 		printit( "\n");
583c2c66affSColin Finck 
584c2c66affSColin Finck 		strlwr(szCommand);  // convert command line to lower
585c2c66affSColin Finck 		// i = sscanf(szCommand,"%80s %80s %80s %80s", szCmd, szArg1, szArg2, szArg3);
586c2c66affSColin Finck 		switch ( tokenizeCommand(szCommand, i, Parms) ) {
587c2c66affSColin Finck 		case BAD_USAGE:   break;
588c2c66affSColin Finck 		case EMPTY_LINE:
589c2c66affSColin Finck 			if(MyConnection.Resume() == TNPROMPT) {
590c2c66affSColin Finck 				printit("\n");
591c2c66affSColin Finck 				break;
592c2c66affSColin Finck 			}
593c2c66affSColin Finck 			else
594c2c66affSColin Finck 			 	return 1;
595c2c66affSColin Finck 		case INVALID_CMD:
596c2c66affSColin Finck 			printm(0, FALSE, MSG_INVCMD);
597c2c66affSColin Finck 			break;
598c2c66affSColin Finck 		case OPEN:
599c2c66affSColin Finck 			if (i == 1)
600c2c66affSColin Finck 				retval = MyConnection.Open(Parms[0], "23");
601c2c66affSColin Finck 			else
602c2c66affSColin Finck 				retval = MyConnection.Open(Parms[0], Parms[1]);
603c2c66affSColin Finck 			if(retval != TNNOCON && retval != TNPROMPT) return 1;
604c2c66affSColin Finck 			if(retval == TNPROMPT) printit("\n");
605c2c66affSColin Finck 			break;
606c2c66affSColin Finck 		case CLOSE:
607c2c66affSColin Finck 			MyConnection.Close();
608c2c66affSColin Finck 			break;
609c2c66affSColin Finck 		case FASTQUIT: // Thomas Briggs 8/11/98
610c2c66affSColin Finck 		case QUIT:
611c2c66affSColin Finck 			MyConnection.Close();
612c2c66affSColin Finck 			bDone = 1;
613c2c66affSColin Finck 			break;
614c2c66affSColin Finck 		case HELP:
615c2c66affSColin Finck 		case HELP2:
616c2c66affSColin Finck 			printm(0, FALSE, MSG_HELP);
617c2c66affSColin Finck 			printm(0, FALSE, MSG_HELP_1);
618c2c66affSColin Finck 			break;
619c2c66affSColin Finck 			// case KEYS: we should never get it
620c2c66affSColin Finck 		case K_LOAD:
621c2c66affSColin Finck 			if ( i == 1 ) {
622c2c66affSColin Finck 				// Ioannou : changed to ini.get_keyfile()
623c2c66affSColin Finck 				if(MyConnection.LoadKeyMap( ini.get_keyfile(), Parms[0]) != 1)
624c2c66affSColin Finck 					printit("Error loading keymap.\n");
625c2c66affSColin Finck 				break;
626c2c66affSColin Finck 			};
627c2c66affSColin Finck 			if(MyConnection.LoadKeyMap( Parms[1], Parms[0]) != 1)
628c2c66affSColin Finck 				printit("Error loading keymap.\n");
629c2c66affSColin Finck 			break;
630c2c66affSColin Finck 		case K_DISPLAY:
631c2c66affSColin Finck 			MyConnection.DisplayKeyMap();
632c2c66affSColin Finck 			break;
633c2c66affSColin Finck 		case K_SWITCH:
634c2c66affSColin Finck 			MyConnection.SwitchKeyMap(atoi(Parms[0]));
635c2c66affSColin Finck 			break;
636c2c66affSColin Finck 
637c2c66affSColin Finck 			// Paul Brannan 5/30/98
638c2c66affSColin Finck 		case SET:
639c2c66affSColin Finck 			if(i == 0) {
640c2c66affSColin Finck 				printit("Available groups:\n");		// Print out groups
641c2c66affSColin Finck 				ini.print_groups();					// (Paul Brannan 9/3/98)
642c2c66affSColin Finck 			} else if(i == 1) {
643c2c66affSColin Finck 				ini.print_vars(Parms[0]);
644c2c66affSColin Finck 			} else if(i >= 2) {
645c2c66affSColin Finck 				ini.set_value(Parms[0], Parms[1]);
646c2c66affSColin Finck 				// FIX ME !!! Ioannou: here we must call the parser routine for
647c2c66affSColin Finck 				// wrap line, not the ini.set_value
648c2c66affSColin Finck 				//  something like Parser.ConLineWrap(Wrap_Line);
649c2c66affSColin Finck 			}
650c2c66affSColin Finck 			break;
651c2c66affSColin Finck 
652c2c66affSColin Finck 		case SUSPEND: // Thomas Briggs 8/11/98
653c2c66affSColin Finck 
654c2c66affSColin Finck 			// remind the user we're suspended -crn@ozemail.com.au 15/12/98
655c2c66affSColin Finck 			extitle = new char[128];
656c2c66affSColin Finck 			GetConsoleTitle (extitle, 128);
657c2c66affSColin Finck 
658c2c66affSColin Finck 			newtitle = new char[128+sizeof("[suspended]")];
659c2c66affSColin Finck 			strcpy(newtitle, extitle);
660c2c66affSColin Finck 			strncat(newtitle, "[suspended]", 128+sizeof("[suspended]"));
661c2c66affSColin Finck 			if(ini.get_set_title()) SetConsoleTitle (newtitle);
662c2c66affSColin Finck 			delete[] newtitle;
663c2c66affSColin Finck 
664c2c66affSColin Finck 			if (getenv("comspec") == NULL) {
665c2c66affSColin Finck 				switch (GetWin32Version()) {
666c2c66affSColin Finck 				case 2:		// 'cmd' is faster than 'command' in NT -crn@ozemail.com.au
667c2c66affSColin Finck 					system ("cmd");
668c2c66affSColin Finck 					break;
669c2c66affSColin Finck 				default:
670c2c66affSColin Finck 					system ("command");
671c2c66affSColin Finck 					break;
672c2c66affSColin Finck 				}
673c2c66affSColin Finck 			} else {
674c2c66affSColin Finck 				system(getenv("comspec"));
675c2c66affSColin Finck 			}
676c2c66affSColin Finck 
677c2c66affSColin Finck 			if(ini.get_set_title()) SetConsoleTitle (extitle);
678c2c66affSColin Finck 			delete[] extitle;
679c2c66affSColin Finck 			///
680c2c66affSColin Finck 
681c2c66affSColin Finck 			break;
682c2c66affSColin Finck 
683c2c66affSColin Finck 		case CMD_HISTORY:	//crn@ozemail.com.au
684c2c66affSColin Finck 			if (cmdhist != NULL) {
685c2c66affSColin Finck 				while (cmdhist->prev != NULL)
686c2c66affSColin Finck 					cmdhist = cmdhist->prev;	//rewind
687c2c66affSColin Finck 				printf ("Command history:\n");
688c2c66affSColin Finck 				while (1) {
689c2c66affSColin Finck 					printf ("\t%s\n", cmdhist->cmd);
690c2c66affSColin Finck 
691c2c66affSColin Finck 					if (cmdhist->next != NULL)
692c2c66affSColin Finck 						cmdhist = cmdhist->next;
693c2c66affSColin Finck 					else
694c2c66affSColin Finck 						break;
695c2c66affSColin Finck 				}
696c2c66affSColin Finck 			} else
697c2c66affSColin Finck 				printf ("No command history available.\n");
698c2c66affSColin Finck 
699c2c66affSColin Finck 			break;
700c2c66affSColin Finck 
701c2c66affSColin Finck 		case CLEAR_HISTORY:	//crn@ozemail.com.au
702c2c66affSColin Finck 			if (cmdhist != NULL) {
703c2c66affSColin Finck 				while (cmdhist->next != NULL)
704c2c66affSColin Finck 					cmdhist = cmdhist->next;	//fast forward
705c2c66affSColin Finck 				while (cmdhist->prev != NULL) {
706c2c66affSColin Finck 					cmdhist = cmdhist->prev;
707c2c66affSColin Finck 					delete cmdhist->next;
708c2c66affSColin Finck 				}
709c2c66affSColin Finck 				delete cmdhist;
710c2c66affSColin Finck 				cmdhist = NULL;
711c2c66affSColin Finck 				printf ("Command history cleared.\n");
712c2c66affSColin Finck 			} else
713c2c66affSColin Finck 				printf ("No command history available.\n");
714c2c66affSColin Finck 
715c2c66affSColin Finck 		case ALIASES: // Paul Brannan 1/1/99
716c2c66affSColin Finck 			ini.print_aliases();
717c2c66affSColin Finck 			break;
718c2c66affSColin Finck 
719c2c66affSColin Finck 		default: // paranoik
720c2c66affSColin Finck 			printm(0, FALSE, MSG_INVCMD);
721c2c66affSColin Finck 			break;
722c2c66affSColin Finck 		}
723c2c66affSColin Finck 
724c2c66affSColin Finck 	}
725c2c66affSColin Finck 
726c2c66affSColin Finck 	return 0;
727c2c66affSColin Finck }
728