xref: /csrg-svn/usr.bin/telnet/commands.c (revision 32144)
1*32144Sminshall #include <sys/types.h>
2*32144Sminshall #include <sys/socket.h>
3*32144Sminshall #include <netinet/in.h>
4*32144Sminshall 
5*32144Sminshall #include <signal.h>
6*32144Sminshall #include <netdb.h>
7*32144Sminshall #include <ctype.h>
8*32144Sminshall 
9*32144Sminshall #include <arpa/telnet.h>
10*32144Sminshall 
11*32144Sminshall #include "externs.h"
12*32144Sminshall #include "defines.h"
13*32144Sminshall #include "types.h"
14*32144Sminshall 
15*32144Sminshall char	*hostname;
16*32144Sminshall 
17*32144Sminshall #define Ambiguous(s)	((char *)s == ambiguous)
18*32144Sminshall static char *ambiguous;		/* special return value for command routines */
19*32144Sminshall 
20*32144Sminshall typedef struct {
21*32144Sminshall 	char	*name;		/* command name */
22*32144Sminshall 	char	*help;		/* help string */
23*32144Sminshall 	int	(*handler)();	/* routine which executes command */
24*32144Sminshall 	int	dohelp;		/* Should we give general help information? */
25*32144Sminshall 	int	needconnect;	/* Do we need to be connected to execute? */
26*32144Sminshall } Command;
27*32144Sminshall 
28*32144Sminshall static char line[200];
29*32144Sminshall static int margc;
30*32144Sminshall static char *margv[20];
31*32144Sminshall 
32*32144Sminshall /*
33*32144Sminshall  * Various utility routines.
34*32144Sminshall  */
35*32144Sminshall 
36*32144Sminshall static void
37*32144Sminshall makeargv()
38*32144Sminshall {
39*32144Sminshall     register char *cp;
40*32144Sminshall     register char **argp = margv;
41*32144Sminshall 
42*32144Sminshall     margc = 0;
43*32144Sminshall     cp = line;
44*32144Sminshall     if (*cp == '!') {		/* Special case shell escape */
45*32144Sminshall 	*argp++ = "!";		/* No room in string to get this */
46*32144Sminshall 	margc++;
47*32144Sminshall 	cp++;
48*32144Sminshall     }
49*32144Sminshall     while (*cp) {
50*32144Sminshall 	while (isspace(*cp))
51*32144Sminshall 	    cp++;
52*32144Sminshall 	if (*cp == '\0')
53*32144Sminshall 	    break;
54*32144Sminshall 	*argp++ = cp;
55*32144Sminshall 	margc += 1;
56*32144Sminshall 	while (*cp != '\0' && !isspace(*cp))
57*32144Sminshall 	    cp++;
58*32144Sminshall 	if (*cp == '\0')
59*32144Sminshall 	    break;
60*32144Sminshall 	*cp++ = '\0';
61*32144Sminshall     }
62*32144Sminshall     *argp++ = 0;
63*32144Sminshall }
64*32144Sminshall 
65*32144Sminshall 
66*32144Sminshall static char **
67*32144Sminshall genget(name, table, next)
68*32144Sminshall char	*name;		/* name to match */
69*32144Sminshall char	**table;		/* name entry in table */
70*32144Sminshall char	**(*next)();	/* routine to return next entry in table */
71*32144Sminshall {
72*32144Sminshall 	register char *p, *q;
73*32144Sminshall 	register char **c, **found;
74*32144Sminshall 	register int nmatches, longest;
75*32144Sminshall 
76*32144Sminshall 	if (name == 0) {
77*32144Sminshall 	    return 0;
78*32144Sminshall 	}
79*32144Sminshall 	longest = 0;
80*32144Sminshall 	nmatches = 0;
81*32144Sminshall 	found = 0;
82*32144Sminshall 	for (c = table; (p = *c) != 0; c = (*next)(c)) {
83*32144Sminshall 		for (q = name;
84*32144Sminshall 		    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
85*32144Sminshall 			if (*q == 0)		/* exact match? */
86*32144Sminshall 				return (c);
87*32144Sminshall 		if (!*q) {			/* the name was a prefix */
88*32144Sminshall 			if (q - name > longest) {
89*32144Sminshall 				longest = q - name;
90*32144Sminshall 				nmatches = 1;
91*32144Sminshall 				found = c;
92*32144Sminshall 			} else if (q - name == longest)
93*32144Sminshall 				nmatches++;
94*32144Sminshall 		}
95*32144Sminshall 	}
96*32144Sminshall 	if (nmatches > 1)
97*32144Sminshall 		return (char **)ambiguous;
98*32144Sminshall 	return (found);
99*32144Sminshall }
100*32144Sminshall 
101*32144Sminshall /*
102*32144Sminshall  * Make a character string into a number.
103*32144Sminshall  *
104*32144Sminshall  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
105*32144Sminshall  */
106*32144Sminshall 
107*32144Sminshall static
108*32144Sminshall special(s)
109*32144Sminshall register char *s;
110*32144Sminshall {
111*32144Sminshall 	register char c;
112*32144Sminshall 	char b;
113*32144Sminshall 
114*32144Sminshall 	switch (*s) {
115*32144Sminshall 	case '^':
116*32144Sminshall 		b = *++s;
117*32144Sminshall 		if (b == '?') {
118*32144Sminshall 		    c = b | 0x40;		/* DEL */
119*32144Sminshall 		} else {
120*32144Sminshall 		    c = b & 0x1f;
121*32144Sminshall 		}
122*32144Sminshall 		break;
123*32144Sminshall 	default:
124*32144Sminshall 		c = *s;
125*32144Sminshall 		break;
126*32144Sminshall 	}
127*32144Sminshall 	return c;
128*32144Sminshall }
129*32144Sminshall 
130*32144Sminshall /*
131*32144Sminshall  * Construct a control character sequence
132*32144Sminshall  * for a special character.
133*32144Sminshall  */
134*32144Sminshall static char *
135*32144Sminshall control(c)
136*32144Sminshall 	register int c;
137*32144Sminshall {
138*32144Sminshall 	static char buf[3];
139*32144Sminshall 
140*32144Sminshall 	if (c == 0x7f)
141*32144Sminshall 		return ("^?");
142*32144Sminshall 	if (c == '\377') {
143*32144Sminshall 		return "off";
144*32144Sminshall 	}
145*32144Sminshall 	if (c >= 0x20) {
146*32144Sminshall 		buf[0] = c;
147*32144Sminshall 		buf[1] = 0;
148*32144Sminshall 	} else {
149*32144Sminshall 		buf[0] = '^';
150*32144Sminshall 		buf[1] = '@'+c;
151*32144Sminshall 		buf[2] = 0;
152*32144Sminshall 	}
153*32144Sminshall 	return (buf);
154*32144Sminshall }
155*32144Sminshall 
156*32144Sminshall 
157*32144Sminshall 
158*32144Sminshall /*
159*32144Sminshall  *	The following are data structures and routines for
160*32144Sminshall  *	the "send" command.
161*32144Sminshall  *
162*32144Sminshall  */
163*32144Sminshall 
164*32144Sminshall struct sendlist {
165*32144Sminshall     char	*name;		/* How user refers to it (case independent) */
166*32144Sminshall     int		what;		/* Character to be sent (<0 ==> special) */
167*32144Sminshall     char	*help;		/* Help information (0 ==> no help) */
168*32144Sminshall #if	defined(NOT43)
169*32144Sminshall     int		(*routine)();	/* Routine to perform (for special ops) */
170*32144Sminshall #else	/* defined(NOT43) */
171*32144Sminshall     void	(*routine)();	/* Routine to perform (for special ops) */
172*32144Sminshall #endif	/* defined(NOT43) */
173*32144Sminshall };
174*32144Sminshall 
175*32144Sminshall #define	SENDQUESTION	-1
176*32144Sminshall #define	SENDESCAPE	-3
177*32144Sminshall 
178*32144Sminshall static struct sendlist Sendlist[] = {
179*32144Sminshall     { "ao", AO, "Send Telnet Abort output" },
180*32144Sminshall     { "ayt", AYT, "Send Telnet 'Are You There'" },
181*32144Sminshall     { "brk", BREAK, "Send Telnet Break" },
182*32144Sminshall     { "ec", EC, "Send Telnet Erase Character" },
183*32144Sminshall     { "el", EL, "Send Telnet Erase Line" },
184*32144Sminshall     { "escape", SENDESCAPE, "Send current escape character" },
185*32144Sminshall     { "ga", GA, "Send Telnet 'Go Ahead' sequence" },
186*32144Sminshall     { "ip", IP, "Send Telnet Interrupt Process" },
187*32144Sminshall     { "nop", NOP, "Send Telnet 'No operation'" },
188*32144Sminshall     { "synch", SYNCH, "Perform Telnet 'Synch operation'", dosynch },
189*32144Sminshall     { "?", SENDQUESTION, "Display send options" },
190*32144Sminshall     { 0 }
191*32144Sminshall };
192*32144Sminshall 
193*32144Sminshall static struct sendlist Sendlist2[] = {		/* some synonyms */
194*32144Sminshall 	{ "break", BREAK, 0 },
195*32144Sminshall 
196*32144Sminshall 	{ "intp", IP, 0 },
197*32144Sminshall 	{ "interrupt", IP, 0 },
198*32144Sminshall 	{ "intr", IP, 0 },
199*32144Sminshall 
200*32144Sminshall 	{ "help", SENDQUESTION, 0 },
201*32144Sminshall 
202*32144Sminshall 	{ 0 }
203*32144Sminshall };
204*32144Sminshall 
205*32144Sminshall static char **
206*32144Sminshall getnextsend(name)
207*32144Sminshall char *name;
208*32144Sminshall {
209*32144Sminshall     struct sendlist *c = (struct sendlist *) name;
210*32144Sminshall 
211*32144Sminshall     return (char **) (c+1);
212*32144Sminshall }
213*32144Sminshall 
214*32144Sminshall static struct sendlist *
215*32144Sminshall getsend(name)
216*32144Sminshall char *name;
217*32144Sminshall {
218*32144Sminshall     struct sendlist *sl;
219*32144Sminshall 
220*32144Sminshall     if ((sl = (struct sendlist *)
221*32144Sminshall 			genget(name, (char **) Sendlist, getnextsend)) != 0) {
222*32144Sminshall 	return sl;
223*32144Sminshall     } else {
224*32144Sminshall 	return (struct sendlist *)
225*32144Sminshall 				genget(name, (char **) Sendlist2, getnextsend);
226*32144Sminshall     }
227*32144Sminshall }
228*32144Sminshall 
229*32144Sminshall static
230*32144Sminshall sendcmd(argc, argv)
231*32144Sminshall int	argc;
232*32144Sminshall char	**argv;
233*32144Sminshall {
234*32144Sminshall     int what;		/* what we are sending this time */
235*32144Sminshall     int count;		/* how many bytes we are going to need to send */
236*32144Sminshall     int i;
237*32144Sminshall     int question = 0;	/* was at least one argument a question */
238*32144Sminshall     struct sendlist *s;	/* pointer to current command */
239*32144Sminshall 
240*32144Sminshall     if (argc < 2) {
241*32144Sminshall 	printf("need at least one argument for 'send' command\n");
242*32144Sminshall 	printf("'send ?' for help\n");
243*32144Sminshall 	return 0;
244*32144Sminshall     }
245*32144Sminshall     /*
246*32144Sminshall      * First, validate all the send arguments.
247*32144Sminshall      * In addition, we see how much space we are going to need, and
248*32144Sminshall      * whether or not we will be doing a "SYNCH" operation (which
249*32144Sminshall      * flushes the network queue).
250*32144Sminshall      */
251*32144Sminshall     count = 0;
252*32144Sminshall     for (i = 1; i < argc; i++) {
253*32144Sminshall 	s = getsend(argv[i]);
254*32144Sminshall 	if (s == 0) {
255*32144Sminshall 	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
256*32144Sminshall 			argv[i]);
257*32144Sminshall 	    return 0;
258*32144Sminshall 	} else if (Ambiguous(s)) {
259*32144Sminshall 	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
260*32144Sminshall 			argv[i]);
261*32144Sminshall 	    return 0;
262*32144Sminshall 	}
263*32144Sminshall 	switch (s->what) {
264*32144Sminshall 	case SENDQUESTION:
265*32144Sminshall 	    break;
266*32144Sminshall 	case SENDESCAPE:
267*32144Sminshall 	    count += 1;
268*32144Sminshall 	    break;
269*32144Sminshall 	case SYNCH:
270*32144Sminshall 	    count += 2;
271*32144Sminshall 	    break;
272*32144Sminshall 	default:
273*32144Sminshall 	    count += 2;
274*32144Sminshall 	    break;
275*32144Sminshall 	}
276*32144Sminshall     }
277*32144Sminshall     /* Now, do we have enough room? */
278*32144Sminshall     if (NETROOM() < count) {
279*32144Sminshall 	printf("There is not enough room in the buffer TO the network\n");
280*32144Sminshall 	printf("to process your request.  Nothing will be done.\n");
281*32144Sminshall 	printf("('send synch' will throw away most data in the network\n");
282*32144Sminshall 	printf("buffer, if this might help.)\n");
283*32144Sminshall 	return 0;
284*32144Sminshall     }
285*32144Sminshall     /* OK, they are all OK, now go through again and actually send */
286*32144Sminshall     for (i = 1; i < argc; i++) {
287*32144Sminshall 	if ((s = getsend(argv[i])) == 0) {
288*32144Sminshall 	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
289*32144Sminshall 	    quit();
290*32144Sminshall 	    /*NOTREACHED*/
291*32144Sminshall 	}
292*32144Sminshall 	if (s->routine) {
293*32144Sminshall 	    (*s->routine)(s);
294*32144Sminshall 	} else {
295*32144Sminshall 	    switch (what = s->what) {
296*32144Sminshall 	    case SYNCH:
297*32144Sminshall 		dosynch();
298*32144Sminshall 		break;
299*32144Sminshall 	    case SENDQUESTION:
300*32144Sminshall 		for (s = Sendlist; s->name; s++) {
301*32144Sminshall 		    if (s->help) {
302*32144Sminshall 			printf(s->name);
303*32144Sminshall 			if (s->help) {
304*32144Sminshall 			    printf("\t%s", s->help);
305*32144Sminshall 			}
306*32144Sminshall 			printf("\n");
307*32144Sminshall 		    }
308*32144Sminshall 		}
309*32144Sminshall 		question = 1;
310*32144Sminshall 		break;
311*32144Sminshall 	    case SENDESCAPE:
312*32144Sminshall 		NETADD(escape);
313*32144Sminshall 		break;
314*32144Sminshall 	    default:
315*32144Sminshall 		NET2ADD(IAC, what);
316*32144Sminshall 		break;
317*32144Sminshall 	    }
318*32144Sminshall 	}
319*32144Sminshall     }
320*32144Sminshall     return !question;
321*32144Sminshall }
322*32144Sminshall 
323*32144Sminshall /*
324*32144Sminshall  * The following are the routines and data structures referred
325*32144Sminshall  * to by the arguments to the "toggle" command.
326*32144Sminshall  */
327*32144Sminshall 
328*32144Sminshall static
329*32144Sminshall lclchars()
330*32144Sminshall {
331*32144Sminshall     donelclchars = 1;
332*32144Sminshall     return 1;
333*32144Sminshall }
334*32144Sminshall 
335*32144Sminshall static
336*32144Sminshall togdebug()
337*32144Sminshall {
338*32144Sminshall #ifndef	NOT43
339*32144Sminshall     if (net > 0 &&
340*32144Sminshall 	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
341*32144Sminshall 	    perror("setsockopt (SO_DEBUG)");
342*32144Sminshall     }
343*32144Sminshall #else	/* NOT43 */
344*32144Sminshall     if (debug) {
345*32144Sminshall 	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
346*32144Sminshall 	    perror("setsockopt (SO_DEBUG)");
347*32144Sminshall     } else
348*32144Sminshall 	printf("Cannot turn off socket debugging\n");
349*32144Sminshall #endif	/* NOT43 */
350*32144Sminshall     return 1;
351*32144Sminshall }
352*32144Sminshall 
353*32144Sminshall 
354*32144Sminshall static int
355*32144Sminshall togcrlf()
356*32144Sminshall {
357*32144Sminshall     if (crlf) {
358*32144Sminshall 	printf("Will send carriage returns as telnet <CR><LF>.\n");
359*32144Sminshall     } else {
360*32144Sminshall 	printf("Will send carriage returns as telnet <CR><NUL>.\n");
361*32144Sminshall     }
362*32144Sminshall     return 1;
363*32144Sminshall }
364*32144Sminshall 
365*32144Sminshall 
366*32144Sminshall static int
367*32144Sminshall togbinary()
368*32144Sminshall {
369*32144Sminshall     donebinarytoggle = 1;
370*32144Sminshall 
371*32144Sminshall     if (myopts[TELOPT_BINARY] == 0) {	/* Go into binary mode */
372*32144Sminshall 	NET2ADD(IAC, DO);
373*32144Sminshall 	NETADD(TELOPT_BINARY);
374*32144Sminshall 	printoption("<SENT", doopt, TELOPT_BINARY, 0);
375*32144Sminshall 	NET2ADD(IAC, WILL);
376*32144Sminshall 	NETADD(TELOPT_BINARY);
377*32144Sminshall 	printoption("<SENT", doopt, TELOPT_BINARY, 0);
378*32144Sminshall 	hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 1;
379*32144Sminshall 	printf("Negotiating binary mode with remote host.\n");
380*32144Sminshall     } else {				/* Turn off binary mode */
381*32144Sminshall 	NET2ADD(IAC, DONT);
382*32144Sminshall 	NETADD(TELOPT_BINARY);
383*32144Sminshall 	printoption("<SENT", dont, TELOPT_BINARY, 0);
384*32144Sminshall 	NET2ADD(IAC, DONT);
385*32144Sminshall 	NETADD(TELOPT_BINARY);
386*32144Sminshall 	printoption("<SENT", dont, TELOPT_BINARY, 0);
387*32144Sminshall 	hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 0;
388*32144Sminshall 	printf("Negotiating network ascii mode with remote host.\n");
389*32144Sminshall     }
390*32144Sminshall     return 1;
391*32144Sminshall }
392*32144Sminshall 
393*32144Sminshall 
394*32144Sminshall 
395*32144Sminshall extern int togglehelp();
396*32144Sminshall 
397*32144Sminshall struct togglelist {
398*32144Sminshall     char	*name;		/* name of toggle */
399*32144Sminshall     char	*help;		/* help message */
400*32144Sminshall     int		(*handler)();	/* routine to do actual setting */
401*32144Sminshall     int		dohelp;		/* should we display help information */
402*32144Sminshall     int		*variable;
403*32144Sminshall     char	*actionexplanation;
404*32144Sminshall };
405*32144Sminshall 
406*32144Sminshall static struct togglelist Togglelist[] = {
407*32144Sminshall     { "autoflush",
408*32144Sminshall 	"toggle flushing of output when sending interrupt characters",
409*32144Sminshall 	    0,
410*32144Sminshall 		1,
411*32144Sminshall 		    &autoflush,
412*32144Sminshall 			"flush output when sending interrupt characters" },
413*32144Sminshall     { "autosynch",
414*32144Sminshall 	"toggle automatic sending of interrupt characters in urgent mode",
415*32144Sminshall 	    0,
416*32144Sminshall 		1,
417*32144Sminshall 		    &autosynch,
418*32144Sminshall 			"send interrupt characters in urgent mode" },
419*32144Sminshall     { "binary",
420*32144Sminshall 	"toggle sending and receiving of binary data",
421*32144Sminshall 	    togbinary,
422*32144Sminshall 		1,
423*32144Sminshall 		    0,
424*32144Sminshall 			0 },
425*32144Sminshall     { "crlf",
426*32144Sminshall 	"toggle sending carriage returns as telnet <CR><LF>",
427*32144Sminshall 	    togcrlf,
428*32144Sminshall 		1,
429*32144Sminshall 		    &crlf,
430*32144Sminshall 			0 },
431*32144Sminshall     { "crmod",
432*32144Sminshall 	"toggle mapping of received carriage returns",
433*32144Sminshall 	    0,
434*32144Sminshall 		1,
435*32144Sminshall 		    &crmod,
436*32144Sminshall 			"map carriage return on output" },
437*32144Sminshall     { "localchars",
438*32144Sminshall 	"toggle local recognition of certain control characters",
439*32144Sminshall 	    lclchars,
440*32144Sminshall 		1,
441*32144Sminshall 		    &localchars,
442*32144Sminshall 			"recognize certain control characters" },
443*32144Sminshall     { " ", "", 0, 1 },		/* empty line */
444*32144Sminshall     { "debug",
445*32144Sminshall 	"(debugging) toggle debugging",
446*32144Sminshall 	    togdebug,
447*32144Sminshall 		1,
448*32144Sminshall 		    &debug,
449*32144Sminshall 			"turn on socket level debugging" },
450*32144Sminshall     { "netdata",
451*32144Sminshall 	"(debugging) toggle printing of hexadecimal network data",
452*32144Sminshall 	    0,
453*32144Sminshall 		1,
454*32144Sminshall 		    &netdata,
455*32144Sminshall 			"print hexadecimal representation of network traffic" },
456*32144Sminshall     { "options",
457*32144Sminshall 	"(debugging) toggle viewing of options processing",
458*32144Sminshall 	    0,
459*32144Sminshall 		1,
460*32144Sminshall 		    &showoptions,
461*32144Sminshall 			"show option processing" },
462*32144Sminshall     { " ", "", 0, 1 },		/* empty line */
463*32144Sminshall     { "?",
464*32144Sminshall 	"display help information",
465*32144Sminshall 	    togglehelp,
466*32144Sminshall 		1 },
467*32144Sminshall     { "help",
468*32144Sminshall 	"display help information",
469*32144Sminshall 	    togglehelp,
470*32144Sminshall 		0 },
471*32144Sminshall     { 0 }
472*32144Sminshall };
473*32144Sminshall 
474*32144Sminshall static
475*32144Sminshall togglehelp()
476*32144Sminshall {
477*32144Sminshall     struct togglelist *c;
478*32144Sminshall 
479*32144Sminshall     for (c = Togglelist; c->name; c++) {
480*32144Sminshall 	if (c->dohelp) {
481*32144Sminshall 	    printf("%s\t%s\n", c->name, c->help);
482*32144Sminshall 	}
483*32144Sminshall     }
484*32144Sminshall     return 0;
485*32144Sminshall }
486*32144Sminshall 
487*32144Sminshall static char **
488*32144Sminshall getnexttoggle(name)
489*32144Sminshall char *name;
490*32144Sminshall {
491*32144Sminshall     struct togglelist *c = (struct togglelist *) name;
492*32144Sminshall 
493*32144Sminshall     return (char **) (c+1);
494*32144Sminshall }
495*32144Sminshall 
496*32144Sminshall static struct togglelist *
497*32144Sminshall gettoggle(name)
498*32144Sminshall char *name;
499*32144Sminshall {
500*32144Sminshall     return (struct togglelist *)
501*32144Sminshall 			genget(name, (char **) Togglelist, getnexttoggle);
502*32144Sminshall }
503*32144Sminshall 
504*32144Sminshall static
505*32144Sminshall toggle(argc, argv)
506*32144Sminshall int	argc;
507*32144Sminshall char	*argv[];
508*32144Sminshall {
509*32144Sminshall     int retval = 1;
510*32144Sminshall     char *name;
511*32144Sminshall     struct togglelist *c;
512*32144Sminshall 
513*32144Sminshall     if (argc < 2) {
514*32144Sminshall 	fprintf(stderr,
515*32144Sminshall 	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
516*32144Sminshall 	return 0;
517*32144Sminshall     }
518*32144Sminshall     argc--;
519*32144Sminshall     argv++;
520*32144Sminshall     while (argc--) {
521*32144Sminshall 	name = *argv++;
522*32144Sminshall 	c = gettoggle(name);
523*32144Sminshall 	if (Ambiguous(c)) {
524*32144Sminshall 	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
525*32144Sminshall 					name);
526*32144Sminshall 	    return 0;
527*32144Sminshall 	} else if (c == 0) {
528*32144Sminshall 	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
529*32144Sminshall 					name);
530*32144Sminshall 	    return 0;
531*32144Sminshall 	} else {
532*32144Sminshall 	    if (c->variable) {
533*32144Sminshall 		*c->variable = !*c->variable;		/* invert it */
534*32144Sminshall 		if (c->actionexplanation) {
535*32144Sminshall 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
536*32144Sminshall 							c->actionexplanation);
537*32144Sminshall 		}
538*32144Sminshall 		printf("%s %s.\n", *c->variable? "Will" : "Won't",
539*32144Sminshall 							c->actionexplanation);
540*32144Sminshall 	    }
541*32144Sminshall 	    if (c->handler) {
542*32144Sminshall 		retval &= (*c->handler)(c);
543*32144Sminshall 	    }
544*32144Sminshall 	}
545*32144Sminshall     }
546*32144Sminshall     return retval;
547*32144Sminshall }
548*32144Sminshall 
549*32144Sminshall /*
550*32144Sminshall  * The following perform the "set" command.
551*32144Sminshall  */
552*32144Sminshall 
553*32144Sminshall struct setlist {
554*32144Sminshall     char *name;				/* name */
555*32144Sminshall     char *help;				/* help information */
556*32144Sminshall     char *charp;			/* where it is located at */
557*32144Sminshall };
558*32144Sminshall 
559*32144Sminshall static struct setlist Setlist[] = {
560*32144Sminshall     { "echo", 	"character to toggle local echoing on/off", &echoc },
561*32144Sminshall     { "escape",	"character to escape back to telnet command mode", &escape },
562*32144Sminshall     { " ", "" },
563*32144Sminshall     { " ", "The following need 'localchars' to be toggled true", 0 },
564*32144Sminshall     { "erase",	"character to cause an Erase Character", &termEraseChar },
565*32144Sminshall     { "flushoutput", "character to cause an Abort Oubput", &termFlushChar },
566*32144Sminshall     { "interrupt", "character to cause an Interrupt Process", &termIntChar },
567*32144Sminshall     { "kill",	"character to cause an Erase Line", &termKillChar },
568*32144Sminshall     { "quit",	"character to cause a Break", &termQuitChar },
569*32144Sminshall     { "eof",	"character to cause an EOF ", &termEofChar },
570*32144Sminshall     { 0 }
571*32144Sminshall };
572*32144Sminshall 
573*32144Sminshall static char **
574*32144Sminshall getnextset(name)
575*32144Sminshall char *name;
576*32144Sminshall {
577*32144Sminshall     struct setlist *c = (struct setlist *)name;
578*32144Sminshall 
579*32144Sminshall     return (char **) (c+1);
580*32144Sminshall }
581*32144Sminshall 
582*32144Sminshall static struct setlist *
583*32144Sminshall getset(name)
584*32144Sminshall char *name;
585*32144Sminshall {
586*32144Sminshall     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
587*32144Sminshall }
588*32144Sminshall 
589*32144Sminshall static
590*32144Sminshall setcmd(argc, argv)
591*32144Sminshall int	argc;
592*32144Sminshall char	*argv[];
593*32144Sminshall {
594*32144Sminshall     int value;
595*32144Sminshall     struct setlist *ct;
596*32144Sminshall 
597*32144Sminshall     /* XXX back we go... sigh */
598*32144Sminshall     if (argc != 3) {
599*32144Sminshall 	if ((argc == 2) &&
600*32144Sminshall 		    ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
601*32144Sminshall 	    for (ct = Setlist; ct->name; ct++) {
602*32144Sminshall 		printf("%s\t%s\n", ct->name, ct->help);
603*32144Sminshall 	    }
604*32144Sminshall 	    printf("?\tdisplay help information\n");
605*32144Sminshall 	} else {
606*32144Sminshall 	    printf("Format is 'set Name Value'\n'set ?' for help.\n");
607*32144Sminshall 	}
608*32144Sminshall 	return 0;
609*32144Sminshall     }
610*32144Sminshall 
611*32144Sminshall     ct = getset(argv[1]);
612*32144Sminshall     if (ct == 0) {
613*32144Sminshall 	fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
614*32144Sminshall 			argv[1]);
615*32144Sminshall 	return 0;
616*32144Sminshall     } else if (Ambiguous(ct)) {
617*32144Sminshall 	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
618*32144Sminshall 			argv[1]);
619*32144Sminshall 	return 0;
620*32144Sminshall     } else {
621*32144Sminshall 	if (strcmp("off", argv[2])) {
622*32144Sminshall 	    value = special(argv[2]);
623*32144Sminshall 	} else {
624*32144Sminshall 	    value = -1;
625*32144Sminshall 	}
626*32144Sminshall 	*(ct->charp) = value;
627*32144Sminshall 	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
628*32144Sminshall     }
629*32144Sminshall     return 1;
630*32144Sminshall }
631*32144Sminshall 
632*32144Sminshall /*
633*32144Sminshall  * The following are the data structures and routines for the
634*32144Sminshall  * 'mode' command.
635*32144Sminshall  */
636*32144Sminshall 
637*32144Sminshall static
638*32144Sminshall dolinemode()
639*32144Sminshall {
640*32144Sminshall     if (hisopts[TELOPT_SGA]) {
641*32144Sminshall 	wontoption(TELOPT_SGA, 0);
642*32144Sminshall     }
643*32144Sminshall     if (hisopts[TELOPT_ECHO]) {
644*32144Sminshall 	wontoption(TELOPT_ECHO, 0);
645*32144Sminshall     }
646*32144Sminshall     return 1;
647*32144Sminshall }
648*32144Sminshall 
649*32144Sminshall static
650*32144Sminshall docharmode()
651*32144Sminshall {
652*32144Sminshall     if (!hisopts[TELOPT_SGA]) {
653*32144Sminshall 	willoption(TELOPT_SGA, 0);
654*32144Sminshall     }
655*32144Sminshall     if (!hisopts[TELOPT_ECHO]) {
656*32144Sminshall 	willoption(TELOPT_ECHO, 0);
657*32144Sminshall     }
658*32144Sminshall     return 1;
659*32144Sminshall }
660*32144Sminshall 
661*32144Sminshall static Command Mode_commands[] = {
662*32144Sminshall     { "character",	"character-at-a-time mode",	docharmode, 1, 1 },
663*32144Sminshall     { "line",		"line-by-line mode",		dolinemode, 1, 1 },
664*32144Sminshall     { 0 },
665*32144Sminshall };
666*32144Sminshall 
667*32144Sminshall static char **
668*32144Sminshall getnextmode(name)
669*32144Sminshall char *name;
670*32144Sminshall {
671*32144Sminshall     Command *c = (Command *) name;
672*32144Sminshall 
673*32144Sminshall     return (char **) (c+1);
674*32144Sminshall }
675*32144Sminshall 
676*32144Sminshall static Command *
677*32144Sminshall getmodecmd(name)
678*32144Sminshall char *name;
679*32144Sminshall {
680*32144Sminshall     return (Command *) genget(name, (char **) Mode_commands, getnextmode);
681*32144Sminshall }
682*32144Sminshall 
683*32144Sminshall static
684*32144Sminshall modecmd(argc, argv)
685*32144Sminshall int	argc;
686*32144Sminshall char	*argv[];
687*32144Sminshall {
688*32144Sminshall     Command *mt;
689*32144Sminshall 
690*32144Sminshall     if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) {
691*32144Sminshall 	printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
692*32144Sminshall 	for (mt = Mode_commands; mt->name; mt++) {
693*32144Sminshall 	    printf("%s\t%s\n", mt->name, mt->help);
694*32144Sminshall 	}
695*32144Sminshall 	return 0;
696*32144Sminshall     }
697*32144Sminshall     mt = getmodecmd(argv[1]);
698*32144Sminshall     if (mt == 0) {
699*32144Sminshall 	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
700*32144Sminshall 	return 0;
701*32144Sminshall     } else if (Ambiguous(mt)) {
702*32144Sminshall 	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
703*32144Sminshall 	return 0;
704*32144Sminshall     } else {
705*32144Sminshall 	(*mt->handler)();
706*32144Sminshall     }
707*32144Sminshall     return 1;
708*32144Sminshall }
709*32144Sminshall 
710*32144Sminshall /*
711*32144Sminshall  * The following data structures and routines implement the
712*32144Sminshall  * "display" command.
713*32144Sminshall  */
714*32144Sminshall 
715*32144Sminshall static
716*32144Sminshall display(argc, argv)
717*32144Sminshall int	argc;
718*32144Sminshall char	*argv[];
719*32144Sminshall {
720*32144Sminshall #define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
721*32144Sminshall 			    if (*tl->variable) { \
722*32144Sminshall 				printf("will"); \
723*32144Sminshall 			    } else { \
724*32144Sminshall 				printf("won't"); \
725*32144Sminshall 			    } \
726*32144Sminshall 			    printf(" %s.\n", tl->actionexplanation); \
727*32144Sminshall 			}
728*32144Sminshall 
729*32144Sminshall #define	doset(sl)   if (sl->name && *sl->name != ' ') { \
730*32144Sminshall 			printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \
731*32144Sminshall 		    }
732*32144Sminshall 
733*32144Sminshall     struct togglelist *tl;
734*32144Sminshall     struct setlist *sl;
735*32144Sminshall 
736*32144Sminshall     if (argc == 1) {
737*32144Sminshall 	for (tl = Togglelist; tl->name; tl++) {
738*32144Sminshall 	    dotog(tl);
739*32144Sminshall 	}
740*32144Sminshall 	printf("\n");
741*32144Sminshall 	for (sl = Setlist; sl->name; sl++) {
742*32144Sminshall 	    doset(sl);
743*32144Sminshall 	}
744*32144Sminshall     } else {
745*32144Sminshall 	int i;
746*32144Sminshall 
747*32144Sminshall 	for (i = 1; i < argc; i++) {
748*32144Sminshall 	    sl = getset(argv[i]);
749*32144Sminshall 	    tl = gettoggle(argv[i]);
750*32144Sminshall 	    if (Ambiguous(sl) || Ambiguous(tl)) {
751*32144Sminshall 		printf("?Ambiguous argument '%s'.\n", argv[i]);
752*32144Sminshall 		return 0;
753*32144Sminshall 	    } else if (!sl && !tl) {
754*32144Sminshall 		printf("?Unknown argument '%s'.\n", argv[i]);
755*32144Sminshall 		return 0;
756*32144Sminshall 	    } else {
757*32144Sminshall 		if (tl) {
758*32144Sminshall 		    dotog(tl);
759*32144Sminshall 		}
760*32144Sminshall 		if (sl) {
761*32144Sminshall 		    doset(sl);
762*32144Sminshall 		}
763*32144Sminshall 	    }
764*32144Sminshall 	}
765*32144Sminshall     }
766*32144Sminshall     return 1;
767*32144Sminshall #undef	doset
768*32144Sminshall #undef	dotog
769*32144Sminshall }
770*32144Sminshall 
771*32144Sminshall /*
772*32144Sminshall  * The following are the data structures, and many of the routines,
773*32144Sminshall  * relating to command processing.
774*32144Sminshall  */
775*32144Sminshall 
776*32144Sminshall /*
777*32144Sminshall  * Set the escape character.
778*32144Sminshall  */
779*32144Sminshall static
780*32144Sminshall setescape(argc, argv)
781*32144Sminshall 	int argc;
782*32144Sminshall 	char *argv[];
783*32144Sminshall {
784*32144Sminshall 	register char *arg;
785*32144Sminshall 	char buf[50];
786*32144Sminshall 
787*32144Sminshall 	printf(
788*32144Sminshall 	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
789*32144Sminshall 				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
790*32144Sminshall 	if (argc > 2)
791*32144Sminshall 		arg = argv[1];
792*32144Sminshall 	else {
793*32144Sminshall 		printf("new escape character: ");
794*32144Sminshall 		gets(buf);
795*32144Sminshall 		arg = buf;
796*32144Sminshall 	}
797*32144Sminshall 	if (arg[0] != '\0')
798*32144Sminshall 		escape = arg[0];
799*32144Sminshall 	if (!In3270) {
800*32144Sminshall 		printf("Escape character is '%s'.\n", control(escape));
801*32144Sminshall 	}
802*32144Sminshall 	fflush(stdout);
803*32144Sminshall 	return 1;
804*32144Sminshall }
805*32144Sminshall 
806*32144Sminshall /*VARARGS*/
807*32144Sminshall static
808*32144Sminshall togcrmod()
809*32144Sminshall {
810*32144Sminshall     crmod = !crmod;
811*32144Sminshall     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
812*32144Sminshall     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
813*32144Sminshall     fflush(stdout);
814*32144Sminshall     return 1;
815*32144Sminshall }
816*32144Sminshall 
817*32144Sminshall /*VARARGS*/
818*32144Sminshall suspend()
819*32144Sminshall {
820*32144Sminshall 	setcommandmode();
821*32144Sminshall #if	defined(unix)
822*32144Sminshall 	kill(0, SIGTSTP);
823*32144Sminshall #endif	/* defined(unix) */
824*32144Sminshall 	/* reget parameters in case they were changed */
825*32144Sminshall 	TerminalSaveState();
826*32144Sminshall 	setconnmode();
827*32144Sminshall 	return 1;
828*32144Sminshall }
829*32144Sminshall 
830*32144Sminshall /*VARARGS*/
831*32144Sminshall static
832*32144Sminshall bye(argc, argv)
833*32144Sminshall int	argc;		/* Number of arguments */
834*32144Sminshall char	*argv[];	/* arguments */
835*32144Sminshall {
836*32144Sminshall     if (connected) {
837*32144Sminshall 	shutdown(net, 2);
838*32144Sminshall 	printf("Connection closed.\n");
839*32144Sminshall 	NetClose(net);
840*32144Sminshall 	connected = 0;
841*32144Sminshall 	/* reset options */
842*32144Sminshall 	tninit();
843*32144Sminshall #if	defined(TN3270)
844*32144Sminshall 	SetIn3270();		/* Get out of 3270 mode */
845*32144Sminshall #endif	/* defined(TN3270) */
846*32144Sminshall     }
847*32144Sminshall     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
848*32144Sminshall 	longjmp(toplevel, 1);
849*32144Sminshall 	/* NOTREACHED */
850*32144Sminshall     }
851*32144Sminshall     return 1;			/* Keep lint, etc., happy */
852*32144Sminshall }
853*32144Sminshall 
854*32144Sminshall /*VARARGS*/
855*32144Sminshall quit()
856*32144Sminshall {
857*32144Sminshall 	(void) call(bye, "bye", "fromquit", 0);
858*32144Sminshall 	Exit(0);
859*32144Sminshall 	/*NOTREACHED*/
860*32144Sminshall 	return 1;			/* just to keep lint happy */
861*32144Sminshall }
862*32144Sminshall 
863*32144Sminshall /*
864*32144Sminshall  * Print status about the connection.
865*32144Sminshall  */
866*32144Sminshall static
867*32144Sminshall status(argc, argv)
868*32144Sminshall int	argc;
869*32144Sminshall char	*argv[];
870*32144Sminshall {
871*32144Sminshall     if (connected) {
872*32144Sminshall 	printf("Connected to %s.\n", hostname);
873*32144Sminshall 	if (argc < 2) {
874*32144Sminshall 	    printf("Operating in %s.\n",
875*32144Sminshall 				modelist[getconnmode()].modedescriptions);
876*32144Sminshall 	    if (localchars) {
877*32144Sminshall 		printf("Catching signals locally.\n");
878*32144Sminshall 	    }
879*32144Sminshall 	}
880*32144Sminshall     } else {
881*32144Sminshall 	printf("No connection.\n");
882*32144Sminshall     }
883*32144Sminshall #   if !defined(TN3270)
884*32144Sminshall     printf("Escape character is '%s'.\n", control(escape));
885*32144Sminshall     fflush(stdout);
886*32144Sminshall #   else /* !defined(TN3270) */
887*32144Sminshall     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
888*32144Sminshall 	printf("Escape character is '%s'.\n", control(escape));
889*32144Sminshall     }
890*32144Sminshall #   if defined(unix)
891*32144Sminshall     if (In3270 && transcom) {
892*32144Sminshall        printf("Transparent mode command is '%s'.\n", transcom);
893*32144Sminshall     }
894*32144Sminshall #   endif /* defined(unix) */
895*32144Sminshall     fflush(stdout);
896*32144Sminshall     if (In3270) {
897*32144Sminshall 	return 0;
898*32144Sminshall     }
899*32144Sminshall #   endif /* defined(TN3270) */
900*32144Sminshall     return 1;
901*32144Sminshall }
902*32144Sminshall 
903*32144Sminshall #if	defined(TN3270) && defined(unix)
904*32144Sminshall static
905*32144Sminshall settranscom(argc, argv)
906*32144Sminshall 	int argc;
907*32144Sminshall 	char *argv[];
908*32144Sminshall {
909*32144Sminshall 	int i, len = 0;
910*32144Sminshall 	char *strcpy(), *strcat();
911*32144Sminshall 
912*32144Sminshall 	if (argc == 1 && transcom) {
913*32144Sminshall 	   transcom = 0;
914*32144Sminshall 	}
915*32144Sminshall 	if (argc == 1) {
916*32144Sminshall 	   return;
917*32144Sminshall 	}
918*32144Sminshall 	for (i = 1; i < argc; ++i) {
919*32144Sminshall 	    len += 1 + strlen(argv[1]);
920*32144Sminshall 	}
921*32144Sminshall 	transcom = tline;
922*32144Sminshall 	(void) strcpy(transcom, argv[1]);
923*32144Sminshall 	for (i = 2; i < argc; ++i) {
924*32144Sminshall 	    (void) strcat(transcom, " ");
925*32144Sminshall 	    (void) strcat(transcom, argv[i]);
926*32144Sminshall 	}
927*32144Sminshall }
928*32144Sminshall #endif	/* defined(TN3270) && defined(unix) */
929*32144Sminshall 
930*32144Sminshall 
931*32144Sminshall 
932*32144Sminshall int
933*32144Sminshall tn(argc, argv)
934*32144Sminshall 	int argc;
935*32144Sminshall 	char *argv[];
936*32144Sminshall {
937*32144Sminshall     register struct hostent *host = 0;
938*32144Sminshall     struct sockaddr_in sin;
939*32144Sminshall     struct servent *sp = 0;
940*32144Sminshall     static char	hnamebuf[32];
941*32144Sminshall 
942*32144Sminshall 
943*32144Sminshall #if defined(MSDOS)
944*32144Sminshall     char *cp;
945*32144Sminshall #endif	/* defined(MSDOS) */
946*32144Sminshall 
947*32144Sminshall     if (connected) {
948*32144Sminshall 	printf("?Already connected to %s\n", hostname);
949*32144Sminshall 	return 0;
950*32144Sminshall     }
951*32144Sminshall     if (argc < 2) {
952*32144Sminshall 	(void) strcpy(line, "Connect ");
953*32144Sminshall 	printf("(to) ");
954*32144Sminshall 	gets(&line[strlen(line)]);
955*32144Sminshall 	makeargv();
956*32144Sminshall 	argc = margc;
957*32144Sminshall 	argv = margv;
958*32144Sminshall     }
959*32144Sminshall     if ((argc < 2) || (argc > 3)) {
960*32144Sminshall 	printf("usage: %s host-name [port]\n", argv[0]);
961*32144Sminshall 	return 0;
962*32144Sminshall     }
963*32144Sminshall #if	defined(MSDOS)
964*32144Sminshall     for (cp = argv[1]; *cp; cp++) {
965*32144Sminshall 	if (isupper(*cp)) {
966*32144Sminshall 	    *cp = tolower(*cp);
967*32144Sminshall 	}
968*32144Sminshall     }
969*32144Sminshall #endif	/* defined(MSDOS) */
970*32144Sminshall     sin.sin_addr.s_addr = inet_addr(argv[1]);
971*32144Sminshall     if (sin.sin_addr.s_addr != -1) {
972*32144Sminshall 	sin.sin_family = AF_INET;
973*32144Sminshall 	(void) strcpy(hnamebuf, argv[1]);
974*32144Sminshall 	hostname = hnamebuf;
975*32144Sminshall     } else {
976*32144Sminshall 	host = gethostbyname(argv[1]);
977*32144Sminshall 	if (host) {
978*32144Sminshall 	    sin.sin_family = host->h_addrtype;
979*32144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
980*32144Sminshall 	    memcpy((caddr_t)&sin.sin_addr,
981*32144Sminshall 				host->h_addr_list[0], host->h_length);
982*32144Sminshall #else	/* defined(h_addr) */
983*32144Sminshall 	    memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
984*32144Sminshall #endif	/* defined(h_addr) */
985*32144Sminshall 	    hostname = host->h_name;
986*32144Sminshall 	} else {
987*32144Sminshall 	    printf("%s: unknown host\n", argv[1]);
988*32144Sminshall 	    return 0;
989*32144Sminshall 	}
990*32144Sminshall     }
991*32144Sminshall     if (argc == 3) {
992*32144Sminshall 	sin.sin_port = atoi(argv[2]);
993*32144Sminshall 	if (sin.sin_port == 0) {
994*32144Sminshall 	    sp = getservbyname(argv[2], "tcp");
995*32144Sminshall 	    if (sp)
996*32144Sminshall 		sin.sin_port = sp->s_port;
997*32144Sminshall 	    else {
998*32144Sminshall 		printf("%s: bad port number\n", argv[2]);
999*32144Sminshall 		return 0;
1000*32144Sminshall 	    }
1001*32144Sminshall 	} else {
1002*32144Sminshall 	    sin.sin_port = atoi(argv[2]);
1003*32144Sminshall 	    sin.sin_port = htons(sin.sin_port);
1004*32144Sminshall 	}
1005*32144Sminshall 	telnetport = 0;
1006*32144Sminshall     } else {
1007*32144Sminshall 	if (sp == 0) {
1008*32144Sminshall 	    sp = getservbyname("telnet", "tcp");
1009*32144Sminshall 	    if (sp == 0) {
1010*32144Sminshall 		fprintf(stderr, "telnet: tcp/telnet: unknown service\n",1);
1011*32144Sminshall 		return 0;
1012*32144Sminshall 	    }
1013*32144Sminshall 	    sin.sin_port = sp->s_port;
1014*32144Sminshall 	}
1015*32144Sminshall 	telnetport = 1;
1016*32144Sminshall     }
1017*32144Sminshall #if	defined(unix)
1018*32144Sminshall     signal(SIGINT, intr);
1019*32144Sminshall     signal(SIGQUIT, intr2);
1020*32144Sminshall     signal(SIGPIPE, deadpeer);
1021*32144Sminshall #endif	/* defined(unix) */
1022*32144Sminshall     printf("Trying...\n");
1023*32144Sminshall     do {
1024*32144Sminshall 	net = socket(AF_INET, SOCK_STREAM, 0);
1025*32144Sminshall 	if (net < 0) {
1026*32144Sminshall 	    perror("telnet: socket");
1027*32144Sminshall 	    return 0;
1028*32144Sminshall 	}
1029*32144Sminshall 	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
1030*32144Sminshall 		perror("setsockopt (SO_DEBUG)");
1031*32144Sminshall 	}
1032*32144Sminshall 
1033*32144Sminshall 	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
1034*32144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
1035*32144Sminshall 	    if (host && host->h_addr_list[1]) {
1036*32144Sminshall 		int oerrno = errno;
1037*32144Sminshall 
1038*32144Sminshall 		fprintf(stderr, "telnet: connect to address %s: ",
1039*32144Sminshall 						inet_ntoa(sin.sin_addr));
1040*32144Sminshall 		errno = oerrno;
1041*32144Sminshall 		perror((char *)0);
1042*32144Sminshall 		host->h_addr_list++;
1043*32144Sminshall 		memcpy((caddr_t)&sin.sin_addr,
1044*32144Sminshall 			host->h_addr_list[0], host->h_length);
1045*32144Sminshall 		fprintf(stderr, "Trying %s...\n",
1046*32144Sminshall 			inet_ntoa(sin.sin_addr));
1047*32144Sminshall 		(void) NetClose(net);
1048*32144Sminshall 		continue;
1049*32144Sminshall 	    }
1050*32144Sminshall #endif	/* defined(h_addr) */
1051*32144Sminshall 	    perror("telnet: Unable to connect to remote host");
1052*32144Sminshall #if defined(unix)
1053*32144Sminshall 	    signal(SIGINT, SIG_DFL);
1054*32144Sminshall 	    signal(SIGQUIT, SIG_DFL);
1055*32144Sminshall #endif	/* defined(unix) */
1056*32144Sminshall 	    return 0;
1057*32144Sminshall 	    }
1058*32144Sminshall 	connected++;
1059*32144Sminshall     } while (connected == 0);
1060*32144Sminshall     call(status, "status", "notmuch", 0);
1061*32144Sminshall     if (setjmp(peerdied) == 0)
1062*32144Sminshall 	telnet();
1063*32144Sminshall     NetClose(net);
1064*32144Sminshall     ExitString(stderr, "Connection closed by foreign host.\n",1);
1065*32144Sminshall     /*NOTREACHED*/
1066*32144Sminshall }
1067*32144Sminshall 
1068*32144Sminshall 
1069*32144Sminshall #define HELPINDENT (sizeof ("connect"))
1070*32144Sminshall 
1071*32144Sminshall static char
1072*32144Sminshall 	openhelp[] =	"connect to a site",
1073*32144Sminshall 	closehelp[] =	"close current connection",
1074*32144Sminshall 	quithelp[] =	"exit telnet",
1075*32144Sminshall 	statushelp[] =	"print status information",
1076*32144Sminshall 	helphelp[] =	"print help information",
1077*32144Sminshall 	sendhelp[] =	"transmit special characters ('send ?' for more)",
1078*32144Sminshall 	sethelp[] = 	"set operating parameters ('set ?' for more)",
1079*32144Sminshall 	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
1080*32144Sminshall 	displayhelp[] =	"display operating parameters",
1081*32144Sminshall #if	defined(TN3270) && defined(unix)
1082*32144Sminshall 	transcomhelp[] = "specify Unix command for transparent mode pipe",
1083*32144Sminshall #endif	/* defined(TN3270) && defined(unix) */
1084*32144Sminshall #if	defined(unix)
1085*32144Sminshall 	zhelp[] =	"suspend telnet",
1086*32144Sminshall #endif	/* defined(unix */
1087*32144Sminshall #if	defined(TN3270)
1088*32144Sminshall 	shellhelp[] =	"invoke a subshell",
1089*32144Sminshall #endif	/* defined(TN3270) */
1090*32144Sminshall 	modehelp[] = "try to enter line-by-line or character-at-a-time mode";
1091*32144Sminshall 
1092*32144Sminshall extern int	help(), shell();
1093*32144Sminshall 
1094*32144Sminshall static Command cmdtab[] = {
1095*32144Sminshall 	{ "close",	closehelp,	bye,		1, 1 },
1096*32144Sminshall 	{ "display",	displayhelp,	display,	1, 0 },
1097*32144Sminshall 	{ "mode",	modehelp,	modecmd,	1, 1 },
1098*32144Sminshall 	{ "open",	openhelp,	tn,		1, 0 },
1099*32144Sminshall 	{ "quit",	quithelp,	quit,		1, 0 },
1100*32144Sminshall 	{ "send",	sendhelp,	sendcmd,	1, 1 },
1101*32144Sminshall 	{ "set",	sethelp,	setcmd,		1, 0 },
1102*32144Sminshall 	{ "status",	statushelp,	status,		1, 0 },
1103*32144Sminshall 	{ "toggle",	togglestring,	toggle,		1, 0 },
1104*32144Sminshall #if	defined(TN3270) && defined(unix)
1105*32144Sminshall 	{ "transcom",	transcomhelp,	settranscom,	1, 0 },
1106*32144Sminshall #endif	/* defined(TN3270) && defined(unix) */
1107*32144Sminshall #if	defined(unix)
1108*32144Sminshall 	{ "z",		zhelp,		suspend,	1, 0 },
1109*32144Sminshall #endif	/* defined(unix) */
1110*32144Sminshall #if	defined(TN3270)
1111*32144Sminshall 	{ "!",		shellhelp,	shell,		1, 1 },
1112*32144Sminshall #endif	/* defined(TN3270) */
1113*32144Sminshall 	{ "?",		helphelp,	help,		1, 0 },
1114*32144Sminshall 	0
1115*32144Sminshall };
1116*32144Sminshall 
1117*32144Sminshall static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
1118*32144Sminshall static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
1119*32144Sminshall 
1120*32144Sminshall static Command cmdtab2[] = {
1121*32144Sminshall 	{ "help",	helphelp,	help,		0, 0 },
1122*32144Sminshall 	{ "escape",	escapehelp,	setescape,	1, 0 },
1123*32144Sminshall 	{ "crmod",	crmodhelp,	togcrmod,	1, 0 },
1124*32144Sminshall 	0
1125*32144Sminshall };
1126*32144Sminshall 
1127*32144Sminshall /*
1128*32144Sminshall  * Call routine with argc, argv set from args (terminated by 0).
1129*32144Sminshall  * VARARGS2
1130*32144Sminshall  */
1131*32144Sminshall static
1132*32144Sminshall call(routine, args)
1133*32144Sminshall 	int (*routine)();
1134*32144Sminshall 	char *args;
1135*32144Sminshall {
1136*32144Sminshall 	register char **argp;
1137*32144Sminshall 	register int argc;
1138*32144Sminshall 
1139*32144Sminshall 	for (argc = 0, argp = &args; *argp++ != 0; argc++)
1140*32144Sminshall 		;
1141*32144Sminshall 	return (*routine)(argc, &args);
1142*32144Sminshall }
1143*32144Sminshall 
1144*32144Sminshall static char **
1145*32144Sminshall getnextcmd(name)
1146*32144Sminshall char *name;
1147*32144Sminshall {
1148*32144Sminshall     Command *c = (Command *) name;
1149*32144Sminshall 
1150*32144Sminshall     return (char **) (c+1);
1151*32144Sminshall }
1152*32144Sminshall 
1153*32144Sminshall static Command *
1154*32144Sminshall getcmd(name)
1155*32144Sminshall char *name;
1156*32144Sminshall {
1157*32144Sminshall     Command *cm;
1158*32144Sminshall 
1159*32144Sminshall     if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
1160*32144Sminshall 	return cm;
1161*32144Sminshall     } else {
1162*32144Sminshall 	return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
1163*32144Sminshall     }
1164*32144Sminshall }
1165*32144Sminshall 
1166*32144Sminshall void
1167*32144Sminshall command(top)
1168*32144Sminshall 	int top;
1169*32144Sminshall {
1170*32144Sminshall     register Command *c;
1171*32144Sminshall 
1172*32144Sminshall     setcommandmode();
1173*32144Sminshall     if (!top) {
1174*32144Sminshall 	putchar('\n');
1175*32144Sminshall     } else {
1176*32144Sminshall #if	defined(unix)
1177*32144Sminshall 	signal(SIGINT, SIG_DFL);
1178*32144Sminshall 	signal(SIGQUIT, SIG_DFL);
1179*32144Sminshall #endif	/* defined(unix) */
1180*32144Sminshall     }
1181*32144Sminshall     for (;;) {
1182*32144Sminshall 	printf("%s> ", prompt);
1183*32144Sminshall 	if (gets(line) == NULL) {
1184*32144Sminshall 	    if (feof(stdin) || ferror(stdin))
1185*32144Sminshall 		quit();
1186*32144Sminshall 	    break;
1187*32144Sminshall 	}
1188*32144Sminshall 	if (line[0] == 0)
1189*32144Sminshall 	    break;
1190*32144Sminshall 	makeargv();
1191*32144Sminshall 	c = getcmd(margv[0]);
1192*32144Sminshall 	if (Ambiguous(c)) {
1193*32144Sminshall 	    printf("?Ambiguous command\n");
1194*32144Sminshall 	    continue;
1195*32144Sminshall 	}
1196*32144Sminshall 	if (c == 0) {
1197*32144Sminshall 	    printf("?Invalid command\n");
1198*32144Sminshall 	    continue;
1199*32144Sminshall 	}
1200*32144Sminshall 	if (c->needconnect && !connected) {
1201*32144Sminshall 	    printf("?Need to be connected first.\n");
1202*32144Sminshall 	    continue;
1203*32144Sminshall 	}
1204*32144Sminshall 	if ((*c->handler)(margc, margv)) {
1205*32144Sminshall 	    break;
1206*32144Sminshall 	}
1207*32144Sminshall     }
1208*32144Sminshall     if (!top) {
1209*32144Sminshall 	if (!connected) {
1210*32144Sminshall 	    longjmp(toplevel, 1);
1211*32144Sminshall 	    /*NOTREACHED*/
1212*32144Sminshall 	}
1213*32144Sminshall #if	defined(TN3270)
1214*32144Sminshall 	if (shell_active == 0) {
1215*32144Sminshall 	    setconnmode();
1216*32144Sminshall 	}
1217*32144Sminshall #else	/* defined(TN3270) */
1218*32144Sminshall 	setconnmode();
1219*32144Sminshall #endif	/* defined(TN3270) */
1220*32144Sminshall     }
1221*32144Sminshall }
1222*32144Sminshall 
1223*32144Sminshall /*
1224*32144Sminshall  * Help command.
1225*32144Sminshall  */
1226*32144Sminshall static
1227*32144Sminshall help(argc, argv)
1228*32144Sminshall 	int argc;
1229*32144Sminshall 	char *argv[];
1230*32144Sminshall {
1231*32144Sminshall 	register Command *c;
1232*32144Sminshall 
1233*32144Sminshall 	if (argc == 1) {
1234*32144Sminshall 		printf("Commands may be abbreviated.  Commands are:\n\n");
1235*32144Sminshall 		for (c = cmdtab; c->name; c++)
1236*32144Sminshall 			if (c->dohelp) {
1237*32144Sminshall 				printf("%-*s\t%s\n", HELPINDENT, c->name,
1238*32144Sminshall 								    c->help);
1239*32144Sminshall 			}
1240*32144Sminshall 		return 0;
1241*32144Sminshall 	}
1242*32144Sminshall 	while (--argc > 0) {
1243*32144Sminshall 		register char *arg;
1244*32144Sminshall 		arg = *++argv;
1245*32144Sminshall 		c = getcmd(arg);
1246*32144Sminshall 		if (Ambiguous(c))
1247*32144Sminshall 			printf("?Ambiguous help command %s\n", arg);
1248*32144Sminshall 		else if (c == (Command *)0)
1249*32144Sminshall 			printf("?Invalid help command %s\n", arg);
1250*32144Sminshall 		else
1251*32144Sminshall 			printf("%s\n", c->help);
1252*32144Sminshall 	}
1253*32144Sminshall 	return 0;
1254*32144Sminshall }
1255