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