xref: /csrg-svn/usr.bin/telnet/commands.c (revision 46808)
133685Sbostic /*
245233Sborman  * Copyright (c) 1988, 1990 Regents of the University of California.
333685Sbostic  * All rights reserved.
433685Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
633685Sbostic  */
733685Sbostic 
833685Sbostic #ifndef lint
9*46808Sdab static char sccsid[] = "@(#)commands.c	5.3 (Berkeley) 03/01/91";
1033685Sbostic #endif /* not lint */
1133685Sbostic 
1236274Sminshall #if	defined(unix)
1345241Swilliam #include <sys/param.h>
14*46808Sdab #ifdef	CRAY
15*46808Sdab #include <sys/types.h>
16*46808Sdab #endif
1736274Sminshall #include <sys/file.h>
1845241Swilliam #else
1945241Swilliam #include <sys/types.h>
2036274Sminshall #endif	/* defined(unix) */
2132144Sminshall #include <sys/socket.h>
2232144Sminshall #include <netinet/in.h>
2338689Sborman #ifdef	CRAY
24*46808Sdab #include <fcntl.h>
2538810Sborman #endif	/* CRAY */
2632144Sminshall 
2732144Sminshall #include <signal.h>
2832144Sminshall #include <netdb.h>
2932144Sminshall #include <ctype.h>
3045008Skarels #include <pwd.h>
3135298Sminshall #include <varargs.h>
32*46808Sdab #include <errno.h>
3332144Sminshall 
3432144Sminshall #include <arpa/telnet.h>
3532144Sminshall 
3634305Sminshall #include "general.h"
3734305Sminshall 
3832381Sminshall #include "ring.h"
3932381Sminshall 
4032144Sminshall #include "externs.h"
4132144Sminshall #include "defines.h"
4232144Sminshall #include "types.h"
4332144Sminshall 
44*46808Sdab #ifndef CRAY
45*46808Sdab #include <netinet/in_systm.h>
46*46808Sdab # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
47*46808Sdab # include <machine/endian.h>
48*46808Sdab # endif /* vax */
49*46808Sdab #endif /* CRAY */
5044361Sborman #include <netinet/ip.h>
5138689Sborman 
5238689Sborman 
53*46808Sdab #ifndef       MAXHOSTNAMELEN
54*46808Sdab #define       MAXHOSTNAMELEN 64
55*46808Sdab #endif        MAXHOSTNAMELEN
5640248Sborman 
5732144Sminshall char	*hostname;
58*46808Sdab static char _hostname[MAXHOSTNAMELEN];
59*46808Sdab 
6038689Sborman extern char *getenv();
6132144Sminshall 
62*46808Sdab extern int isprefix();
63*46808Sdab extern char **genget();
64*46808Sdab extern int Ambiguous();
65*46808Sdab 
6644361Sborman static call();
6732144Sminshall 
6832144Sminshall typedef struct {
6932144Sminshall 	char	*name;		/* command name */
7038689Sborman 	char	*help;		/* help string (NULL for no help) */
7132144Sminshall 	int	(*handler)();	/* routine which executes command */
7232144Sminshall 	int	needconnect;	/* Do we need to be connected to execute? */
7332144Sminshall } Command;
7432144Sminshall 
7538689Sborman static char line[256];
7638689Sborman static char saveline[256];
7732144Sminshall static int margc;
7832144Sminshall static char *margv[20];
7932144Sminshall 
80*46808Sdab     static void
8132144Sminshall makeargv()
8232144Sminshall {
8344361Sborman     register char *cp, *cp2, c;
8432144Sminshall     register char **argp = margv;
8532144Sminshall 
8632144Sminshall     margc = 0;
8732144Sminshall     cp = line;
8832144Sminshall     if (*cp == '!') {		/* Special case shell escape */
8938689Sborman 	strcpy(saveline, line);	/* save for shell command */
9032144Sminshall 	*argp++ = "!";		/* No room in string to get this */
9132144Sminshall 	margc++;
9232144Sminshall 	cp++;
9332144Sminshall     }
9444361Sborman     while (c = *cp) {
9544361Sborman 	register int inquote = 0;
9644361Sborman 	while (isspace(c))
9744361Sborman 	    c = *++cp;
9844361Sborman 	if (c == '\0')
9932144Sminshall 	    break;
10032144Sminshall 	*argp++ = cp;
10132144Sminshall 	margc += 1;
10244361Sborman 	for (cp2 = cp; c != '\0'; c = *++cp) {
10344361Sborman 	    if (inquote) {
10444361Sborman 		if (c == inquote) {
10544361Sborman 		    inquote = 0;
10644361Sborman 		    continue;
10744361Sborman 		}
10844361Sborman 	    } else {
10944361Sborman 		if (c == '\\') {
11044361Sborman 		    if ((c = *++cp) == '\0')
11144361Sborman 			break;
11244361Sborman 		} else if (c == '"') {
11344361Sborman 		    inquote = '"';
11444361Sborman 		    continue;
11544361Sborman 		} else if (c == '\'') {
11644361Sborman 		    inquote = '\'';
11744361Sborman 		    continue;
11844361Sborman 		} else if (isspace(c))
11944361Sborman 		    break;
12044361Sborman 	    }
12144361Sborman 	    *cp2++ = c;
12244361Sborman 	}
12344361Sborman 	*cp2 = '\0';
12444361Sborman 	if (c == '\0')
12532144Sminshall 	    break;
12644361Sborman 	cp++;
12732144Sminshall     }
12832144Sminshall     *argp++ = 0;
12932144Sminshall }
13032144Sminshall 
13132144Sminshall /*
13232144Sminshall  * Make a character string into a number.
13332144Sminshall  *
13432144Sminshall  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
13532144Sminshall  */
13632144Sminshall 
137*46808Sdab 	static
13832144Sminshall special(s)
139*46808Sdab 	register char *s;
14032144Sminshall {
14132144Sminshall 	register char c;
14232144Sminshall 	char b;
14332144Sminshall 
14432144Sminshall 	switch (*s) {
14532144Sminshall 	case '^':
14632144Sminshall 		b = *++s;
14732144Sminshall 		if (b == '?') {
14832144Sminshall 		    c = b | 0x40;		/* DEL */
14932144Sminshall 		} else {
15032144Sminshall 		    c = b & 0x1f;
15132144Sminshall 		}
15232144Sminshall 		break;
15332144Sminshall 	default:
15432144Sminshall 		c = *s;
15532144Sminshall 		break;
15632144Sminshall 	}
15732144Sminshall 	return c;
15832144Sminshall }
15932144Sminshall 
16032144Sminshall /*
16132144Sminshall  * Construct a control character sequence
16232144Sminshall  * for a special character.
16332144Sminshall  */
164*46808Sdab 	static char *
16532144Sminshall control(c)
16640245Sborman 	register cc_t c;
16732144Sminshall {
16844361Sborman 	static char buf[5];
169*46808Sdab 	/*
170*46808Sdab 	 * The only way I could get the Sun 3.5 compiler
171*46808Sdab 	 * to shut up about
172*46808Sdab 	 *	if ((unsigned int)c >= 0x80)
173*46808Sdab 	 * was to assign "c" to an unsigned int variable...
174*46808Sdab 	 * Arggg....
175*46808Sdab 	 */
176*46808Sdab 	register unsigned int uic = (unsigned int)c;
17732144Sminshall 
178*46808Sdab 	if (uic == 0x7f)
17932144Sminshall 		return ("^?");
18045233Sborman 	if (c == (cc_t)_POSIX_VDISABLE) {
18132144Sminshall 		return "off";
18232144Sminshall 	}
183*46808Sdab 	if (uic >= 0x80) {
18444361Sborman 		buf[0] = '\\';
18544361Sborman 		buf[1] = ((c>>6)&07) + '0';
18644361Sborman 		buf[2] = ((c>>3)&07) + '0';
18744361Sborman 		buf[3] = (c&07) + '0';
18844361Sborman 		buf[4] = 0;
189*46808Sdab 	} else if (uic >= 0x20) {
19032144Sminshall 		buf[0] = c;
19132144Sminshall 		buf[1] = 0;
19232144Sminshall 	} else {
19332144Sminshall 		buf[0] = '^';
19432144Sminshall 		buf[1] = '@'+c;
19532144Sminshall 		buf[2] = 0;
19632144Sminshall 	}
19732144Sminshall 	return (buf);
19832144Sminshall }
19932144Sminshall 
20032144Sminshall 
20132144Sminshall 
20232144Sminshall /*
20332144Sminshall  *	The following are data structures and routines for
20432144Sminshall  *	the "send" command.
20532144Sminshall  *
20632144Sminshall  */
20732144Sminshall 
20832144Sminshall struct sendlist {
20932144Sminshall     char	*name;		/* How user refers to it (case independent) */
21032144Sminshall     char	*help;		/* Help information (0 ==> no help) */
211*46808Sdab     int		needconnect;	/* Need to be connected */
212*46808Sdab     int		narg;		/* Number of arguments */
21338689Sborman     int		(*handler)();	/* Routine to perform (for special ops) */
214*46808Sdab     int		nbyte;		/* Number of bytes to send this command */
21538689Sborman     int		what;		/* Character to be sent (<0 ==> special) */
21632144Sminshall };
21732144Sminshall 
21832144Sminshall 
219*46808Sdab extern int
220*46808Sdab 	send_esc P((void)),
221*46808Sdab 	send_help P((void)),
222*46808Sdab 	send_docmd P((char *)),
223*46808Sdab 	send_dontcmd P((char *)),
224*46808Sdab 	send_willcmd P((char *)),
225*46808Sdab 	send_wontcmd P((char *));
226*46808Sdab 
22732144Sminshall static struct sendlist Sendlist[] = {
228*46808Sdab     { "ao",	"Send Telnet Abort output",		1, 0, 0, 2, AO },
229*46808Sdab     { "ayt",	"Send Telnet 'Are You There'",		1, 0, 0, 2, AYT },
230*46808Sdab     { "brk",	"Send Telnet Break",			1, 0, 0, 2, BREAK },
231*46808Sdab     { "break",	0,					1, 0, 0, 2, BREAK },
232*46808Sdab     { "ec",	"Send Telnet Erase Character",		1, 0, 0, 2, EC },
233*46808Sdab     { "el",	"Send Telnet Erase Line",		1, 0, 0, 2, EL },
234*46808Sdab     { "escape",	"Send current escape character",	1, 0, send_esc, 1, 0 },
235*46808Sdab     { "ga",	"Send Telnet 'Go Ahead' sequence",	1, 0, 0, 2, GA },
236*46808Sdab     { "ip",	"Send Telnet Interrupt Process",	1, 0, 0, 2, IP },
237*46808Sdab     { "intp",	0,					1, 0, 0, 2, IP },
238*46808Sdab     { "interrupt", 0,					1, 0, 0, 2, IP },
239*46808Sdab     { "intr",	0,					1, 0, 0, 2, IP },
240*46808Sdab     { "nop",	"Send Telnet 'No operation'",		1, 0, 0, 2, NOP },
241*46808Sdab     { "eor",	"Send Telnet 'End of Record'",		1, 0, 0, 2, EOR },
242*46808Sdab     { "abort",	"Send Telnet 'Abort Process'",		1, 0, 0, 2, ABORT },
243*46808Sdab     { "susp",	"Send Telnet 'Suspend Process'",	1, 0, 0, 2, SUSP },
244*46808Sdab     { "eof",	"Send Telnet End of File Character",	1, 0, 0, 2, xEOF },
245*46808Sdab     { "synch",	"Perform Telnet 'Synch operation'",	1, 0, dosynch, 2, 0 },
246*46808Sdab     { "getstatus", "Send request for STATUS",		1, 0, get_status, 6, 0 },
247*46808Sdab     { "?",	"Display send options",			0, 0, send_help, 0, 0 },
248*46808Sdab     { "help",	0,					0, 0, send_help, 0, 0 },
249*46808Sdab     { "do",	0,					0, 1, send_docmd, 3, 0 },
250*46808Sdab     { "dont",	0,					0, 1, send_dontcmd, 3, 0 },
251*46808Sdab     { "will",	0,					0, 1, send_willcmd, 3, 0 },
252*46808Sdab     { "wont",	0,					0, 1, send_wontcmd, 3, 0 },
25332144Sminshall     { 0 }
25432144Sminshall };
25532144Sminshall 
256*46808Sdab #define	GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
257*46808Sdab 				sizeof(struct sendlist)))
25832144Sminshall 
259*46808Sdab     static int
26032144Sminshall sendcmd(argc, argv)
261*46808Sdab     int  argc;
262*46808Sdab     char **argv;
26332144Sminshall {
26432144Sminshall     int what;		/* what we are sending this time */
26532144Sminshall     int count;		/* how many bytes we are going to need to send */
26632144Sminshall     int i;
26732144Sminshall     int question = 0;	/* was at least one argument a question */
26832144Sminshall     struct sendlist *s;	/* pointer to current command */
269*46808Sdab     int success = 0;
270*46808Sdab     int needconnect = 0;
27132144Sminshall 
27232144Sminshall     if (argc < 2) {
27332144Sminshall 	printf("need at least one argument for 'send' command\n");
27432144Sminshall 	printf("'send ?' for help\n");
27532144Sminshall 	return 0;
27632144Sminshall     }
27732144Sminshall     /*
27832144Sminshall      * First, validate all the send arguments.
27932144Sminshall      * In addition, we see how much space we are going to need, and
28032144Sminshall      * whether or not we will be doing a "SYNCH" operation (which
28132144Sminshall      * flushes the network queue).
28232144Sminshall      */
28332144Sminshall     count = 0;
28432144Sminshall     for (i = 1; i < argc; i++) {
285*46808Sdab 	s = GETSEND(argv[i]);
28632144Sminshall 	if (s == 0) {
28732144Sminshall 	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
28832144Sminshall 			argv[i]);
28932144Sminshall 	    return 0;
29032144Sminshall 	} else if (Ambiguous(s)) {
29132144Sminshall 	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
29232144Sminshall 			argv[i]);
29332144Sminshall 	    return 0;
29432144Sminshall 	}
295*46808Sdab 	if (i + s->narg >= argc) {
296*46808Sdab 	    fprintf(stderr,
297*46808Sdab 	    "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
298*46808Sdab 		s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
299*46808Sdab 	    return 0;
30032144Sminshall 	}
301*46808Sdab 	count += s->nbyte;
302*46808Sdab 	if (s->handler == send_help) {
303*46808Sdab 	    send_help();
304*46808Sdab 	    return 0;
305*46808Sdab 	}
306*46808Sdab 
307*46808Sdab 	i += s->narg;
308*46808Sdab 	needconnect += s->needconnect;
30932144Sminshall     }
310*46808Sdab     if (!connected && needconnect) {
311*46808Sdab 	printf("?Need to be connected first.\n");
312*46808Sdab 	printf("'send ?' for help\n");
313*46808Sdab 	return 0;
31438689Sborman     }
31532144Sminshall     /* Now, do we have enough room? */
31632144Sminshall     if (NETROOM() < count) {
31732144Sminshall 	printf("There is not enough room in the buffer TO the network\n");
31832144Sminshall 	printf("to process your request.  Nothing will be done.\n");
31932144Sminshall 	printf("('send synch' will throw away most data in the network\n");
32032144Sminshall 	printf("buffer, if this might help.)\n");
32132144Sminshall 	return 0;
32232144Sminshall     }
32332144Sminshall     /* OK, they are all OK, now go through again and actually send */
324*46808Sdab     count = 0;
32532144Sminshall     for (i = 1; i < argc; i++) {
326*46808Sdab 	if ((s = GETSEND(argv[i])) == 0) {
32732144Sminshall 	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
32844361Sborman 	    (void) quit();
32932144Sminshall 	    /*NOTREACHED*/
33032144Sminshall 	}
33138689Sborman 	if (s->handler) {
332*46808Sdab 	    count++;
333*46808Sdab 	    success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
334*46808Sdab 				  (s->narg > 1) ? argv[i+2] : 0);
335*46808Sdab 	    i += s->narg;
33632144Sminshall 	} else {
337*46808Sdab 	    NET2ADD(IAC, what);
338*46808Sdab 	    printoption("SENT", IAC, what);
339*46808Sdab 	}
340*46808Sdab     }
341*46808Sdab     return (count == success);
342*46808Sdab }
343*46808Sdab 
344*46808Sdab     static int
345*46808Sdab send_esc()
346*46808Sdab {
347*46808Sdab     NETADD(escape);
348*46808Sdab     return 1;
349*46808Sdab }
350*46808Sdab 
351*46808Sdab     static int
352*46808Sdab send_docmd(name)
353*46808Sdab     char *name;
354*46808Sdab {
355*46808Sdab     void send_do();
356*46808Sdab     return(send_tncmd(send_do, "do", name));
357*46808Sdab }
358*46808Sdab 
359*46808Sdab     static int
360*46808Sdab send_dontcmd(name)
361*46808Sdab     char *name;
362*46808Sdab {
363*46808Sdab     void send_dont();
364*46808Sdab     return(send_tncmd(send_dont, "dont", name));
365*46808Sdab }
366*46808Sdab     static int
367*46808Sdab send_willcmd(name)
368*46808Sdab     char *name;
369*46808Sdab {
370*46808Sdab     void send_will();
371*46808Sdab     return(send_tncmd(send_will, "will", name));
372*46808Sdab }
373*46808Sdab     static int
374*46808Sdab send_wontcmd(name)
375*46808Sdab     char *name;
376*46808Sdab {
377*46808Sdab     void send_wont();
378*46808Sdab     return(send_tncmd(send_wont, "wont", name));
379*46808Sdab }
380*46808Sdab 
381*46808Sdab     int
382*46808Sdab send_tncmd(func, cmd, name)
383*46808Sdab     void	(*func)();
384*46808Sdab     char	*cmd, *name;
385*46808Sdab {
386*46808Sdab     char **cpp;
387*46808Sdab     extern char *telopts[];
388*46808Sdab 
389*46808Sdab     if (isprefix(name, "help") || isprefix(name, "?")) {
390*46808Sdab 	register int col, len;
391*46808Sdab 
392*46808Sdab 	printf("Usage: send %s <option>\n", cmd);
393*46808Sdab 	printf("Valid options are:\n\t");
394*46808Sdab 
395*46808Sdab 	col = 8;
396*46808Sdab 	for (cpp = telopts; *cpp; cpp++) {
397*46808Sdab 	    len = strlen(*cpp) + 1;
398*46808Sdab 	    if (col + len > 65) {
399*46808Sdab 		printf("\n\t");
400*46808Sdab 		col = 8;
40132144Sminshall 	    }
402*46808Sdab 	    printf(" %s", *cpp);
403*46808Sdab 	    col += len;
40432144Sminshall 	}
405*46808Sdab 	printf("\n");
406*46808Sdab 	return 0;
40732144Sminshall     }
408*46808Sdab     cpp = (char **)genget(name, telopts, sizeof(char *));
409*46808Sdab     if (Ambiguous(cpp)) {
410*46808Sdab 	fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
411*46808Sdab 					name, cmd);
412*46808Sdab 	return 0;
413*46808Sdab     }
414*46808Sdab     if (cpp == 0) {
415*46808Sdab 	fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
416*46808Sdab 					name, cmd);
417*46808Sdab 	return 0;
418*46808Sdab     }
419*46808Sdab     if (!connected) {
420*46808Sdab 	printf("?Need to be connected first.\n");
421*46808Sdab 	return 0;
422*46808Sdab     }
423*46808Sdab     (*func)(cpp - telopts, 1);
424*46808Sdab     return 1;
42532144Sminshall }
426*46808Sdab 
427*46808Sdab     static int
428*46808Sdab send_help()
429*46808Sdab {
430*46808Sdab     struct sendlist *s;	/* pointer to current command */
431*46808Sdab     for (s = Sendlist; s->name; s++) {
432*46808Sdab 	if (s->help)
433*46808Sdab 	    printf("%-15s %s\n", s->name, s->help);
434*46808Sdab     }
435*46808Sdab     return(0);
436*46808Sdab }
43732144Sminshall 
43832144Sminshall /*
43932144Sminshall  * The following are the routines and data structures referred
44032144Sminshall  * to by the arguments to the "toggle" command.
44132144Sminshall  */
44232144Sminshall 
443*46808Sdab     static int
44432144Sminshall lclchars()
44532144Sminshall {
44632144Sminshall     donelclchars = 1;
44732144Sminshall     return 1;
44832144Sminshall }
44932144Sminshall 
450*46808Sdab     static int
45132144Sminshall togdebug()
45232144Sminshall {
45332144Sminshall #ifndef	NOT43
45432144Sminshall     if (net > 0 &&
45532144Sminshall 	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
45632144Sminshall 	    perror("setsockopt (SO_DEBUG)");
45732144Sminshall     }
45832144Sminshall #else	/* NOT43 */
45932144Sminshall     if (debug) {
46032144Sminshall 	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
46132144Sminshall 	    perror("setsockopt (SO_DEBUG)");
46232144Sminshall     } else
46332144Sminshall 	printf("Cannot turn off socket debugging\n");
46432144Sminshall #endif	/* NOT43 */
46532144Sminshall     return 1;
46632144Sminshall }
46732144Sminshall 
46832144Sminshall 
469*46808Sdab     static int
47032144Sminshall togcrlf()
47132144Sminshall {
47232144Sminshall     if (crlf) {
47332144Sminshall 	printf("Will send carriage returns as telnet <CR><LF>.\n");
47432144Sminshall     } else {
47532144Sminshall 	printf("Will send carriage returns as telnet <CR><NUL>.\n");
47632144Sminshall     }
47732144Sminshall     return 1;
47832144Sminshall }
47932144Sminshall 
48038909Sborman int binmode;
48132144Sminshall 
482*46808Sdab     static int
48338689Sborman togbinary(val)
484*46808Sdab     int val;
48532144Sminshall {
48632144Sminshall     donebinarytoggle = 1;
48732144Sminshall 
48838909Sborman     if (val >= 0) {
48938909Sborman 	binmode = val;
49038909Sborman     } else {
49138909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
49238909Sborman 				my_want_state_is_do(TELOPT_BINARY)) {
49338909Sborman 	    binmode = 1;
49438909Sborman 	} else if (my_want_state_is_wont(TELOPT_BINARY) &&
49538909Sborman 				my_want_state_is_dont(TELOPT_BINARY)) {
49638909Sborman 	    binmode = 0;
49738909Sborman 	}
49838909Sborman 	val = binmode ? 0 : 1;
49938909Sborman     }
50038909Sborman 
50138909Sborman     if (val == 1) {
50238909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
50338909Sborman 					my_want_state_is_do(TELOPT_BINARY)) {
50438689Sborman 	    printf("Already operating in binary mode with remote host.\n");
50538909Sborman 	} else {
50638909Sborman 	    printf("Negotiating binary mode with remote host.\n");
50738909Sborman 	    tel_enter_binary(3);
50838689Sborman 	}
50938909Sborman     } else {
51038909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY) &&
51138909Sborman 					my_want_state_is_dont(TELOPT_BINARY)) {
51238689Sborman 	    printf("Already in network ascii mode with remote host.\n");
51338909Sborman 	} else {
51438909Sborman 	    printf("Negotiating network ascii mode with remote host.\n");
51538909Sborman 	    tel_leave_binary(3);
51638689Sborman 	}
51732144Sminshall     }
51832144Sminshall     return 1;
51932144Sminshall }
52032144Sminshall 
521*46808Sdab     static int
52238909Sborman togrbinary(val)
523*46808Sdab     int val;
52438909Sborman {
52538909Sborman     donebinarytoggle = 1;
52632144Sminshall 
52738909Sborman     if (val == -1)
52838909Sborman 	val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
52932144Sminshall 
53038909Sborman     if (val == 1) {
53138909Sborman 	if (my_want_state_is_do(TELOPT_BINARY)) {
53238909Sborman 	    printf("Already receiving in binary mode.\n");
53338909Sborman 	} else {
53438909Sborman 	    printf("Negotiating binary mode on input.\n");
53538909Sborman 	    tel_enter_binary(1);
53638909Sborman 	}
53738909Sborman     } else {
53838909Sborman 	if (my_want_state_is_dont(TELOPT_BINARY)) {
53938909Sborman 	    printf("Already receiving in network ascii mode.\n");
54038909Sborman 	} else {
54138909Sborman 	    printf("Negotiating network ascii mode on input.\n");
54238909Sborman 	    tel_leave_binary(1);
54338909Sborman 	}
54438909Sborman     }
54538909Sborman     return 1;
54638909Sborman }
54738909Sborman 
548*46808Sdab     static int
54938909Sborman togxbinary(val)
550*46808Sdab     int val;
55138909Sborman {
55238909Sborman     donebinarytoggle = 1;
55338909Sborman 
55438909Sborman     if (val == -1)
55538909Sborman 	val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
55638909Sborman 
55738909Sborman     if (val == 1) {
55838909Sborman 	if (my_want_state_is_will(TELOPT_BINARY)) {
55938909Sborman 	    printf("Already transmitting in binary mode.\n");
56038909Sborman 	} else {
56138909Sborman 	    printf("Negotiating binary mode on output.\n");
56238909Sborman 	    tel_enter_binary(2);
56338909Sborman 	}
56438909Sborman     } else {
56538909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY)) {
56638909Sborman 	    printf("Already transmitting in network ascii mode.\n");
56738909Sborman 	} else {
56838909Sborman 	    printf("Negotiating network ascii mode on output.\n");
56938909Sborman 	    tel_leave_binary(2);
57038909Sborman 	}
57138909Sborman     }
57238909Sborman     return 1;
57338909Sborman }
57438909Sborman 
57538909Sborman 
576*46808Sdab extern int togglehelp P((void));
57732144Sminshall 
57832144Sminshall struct togglelist {
57932144Sminshall     char	*name;		/* name of toggle */
58032144Sminshall     char	*help;		/* help message */
58132144Sminshall     int		(*handler)();	/* routine to do actual setting */
58232144Sminshall     int		*variable;
58332144Sminshall     char	*actionexplanation;
58432144Sminshall };
58532144Sminshall 
58632144Sminshall static struct togglelist Togglelist[] = {
58732144Sminshall     { "autoflush",
58838689Sborman 	"flushing of output when sending interrupt characters",
58932144Sminshall 	    0,
59038689Sborman 		&autoflush,
59138689Sborman 		    "flush output when sending interrupt characters" },
59232144Sminshall     { "autosynch",
59338689Sborman 	"automatic sending of interrupt characters in urgent mode",
59432144Sminshall 	    0,
59538689Sborman 		&autosynch,
59638689Sborman 		    "send interrupt characters in urgent mode" },
59732144Sminshall     { "binary",
59838689Sborman 	"sending and receiving of binary data",
59932144Sminshall 	    togbinary,
60038689Sborman 		0,
60138689Sborman 		    0 },
60238909Sborman     { "inbinary",
60338909Sborman 	"receiving of binary data",
60438909Sborman 	    togrbinary,
60538909Sborman 		0,
60638909Sborman 		    0 },
60738909Sborman     { "outbinary",
60838909Sborman 	"sending of binary data",
60938909Sborman 	    togxbinary,
61038909Sborman 		0,
61138909Sborman 		    0 },
61232144Sminshall     { "crlf",
61338689Sborman 	"sending carriage returns as telnet <CR><LF>",
61432144Sminshall 	    togcrlf,
61538689Sborman 		&crlf,
61638689Sborman 		    0 },
61732144Sminshall     { "crmod",
61838689Sborman 	"mapping of received carriage returns",
61932144Sminshall 	    0,
62038689Sborman 		&crmod,
62138689Sborman 		    "map carriage return on output" },
62232144Sminshall     { "localchars",
62338689Sborman 	"local recognition of certain control characters",
62432144Sminshall 	    lclchars,
62538689Sborman 		&localchars,
62638689Sborman 		    "recognize certain control characters" },
62738689Sborman     { " ", "", 0 },		/* empty line */
62838208Sminshall #if	defined(unix) && defined(TN3270)
62938920Sminshall     { "apitrace",
63038920Sminshall 	"(debugging) toggle tracing of API transactions",
63138920Sminshall 	    0,
63238920Sminshall 		&apitrace,
63338920Sminshall 		    "trace API transactions" },
63438208Sminshall     { "cursesdata",
63538208Sminshall 	"(debugging) toggle printing of hexadecimal curses data",
63638208Sminshall 	    0,
63738689Sborman 		&cursesdata,
63838689Sborman 		    "print hexadecimal representation of curses data" },
63938208Sminshall #endif	/* defined(unix) && defined(TN3270) */
64032144Sminshall     { "debug",
64138689Sborman 	"debugging",
64232144Sminshall 	    togdebug,
64338689Sborman 		&debug,
64438689Sborman 		    "turn on socket level debugging" },
64532144Sminshall     { "netdata",
64638689Sborman 	"printing of hexadecimal network data (debugging)",
64732144Sminshall 	    0,
64838689Sborman 		&netdata,
64938689Sborman 		    "print hexadecimal representation of network traffic" },
65038689Sborman     { "prettydump",
65138689Sborman 	"output of \"netdata\" to user readable format (debugging)",
65238689Sborman 	    0,
65338689Sborman 		&prettydump,
65438689Sborman 		    "print user readable output for \"netdata\"" },
65532144Sminshall     { "options",
65638689Sborman 	"viewing of options processing (debugging)",
65732144Sminshall 	    0,
65838689Sborman 		&showoptions,
65938689Sborman 		    "show option processing" },
66038208Sminshall #if	defined(unix)
66138208Sminshall     { "termdata",
66238208Sminshall 	"(debugging) toggle printing of hexadecimal terminal data",
66338208Sminshall 	    0,
66438689Sborman 		&termdata,
66538689Sborman 		    "print hexadecimal representation of terminal traffic" },
66638208Sminshall #endif	/* defined(unix) */
66732144Sminshall     { "?",
66838689Sborman 	0,
66938689Sborman 	    togglehelp },
67032144Sminshall     { "help",
67138689Sborman 	0,
67238689Sborman 	    togglehelp },
67332144Sminshall     { 0 }
67432144Sminshall };
67532144Sminshall 
676*46808Sdab     static int
67732144Sminshall togglehelp()
67832144Sminshall {
67932144Sminshall     struct togglelist *c;
68032144Sminshall 
68132144Sminshall     for (c = Togglelist; c->name; c++) {
68238689Sborman 	if (c->help) {
68338689Sborman 	    if (*c->help)
68438689Sborman 		printf("%-15s toggle %s\n", c->name, c->help);
68538689Sborman 	    else
68638689Sborman 		printf("\n");
68732144Sminshall 	}
68832144Sminshall     }
68938689Sborman     printf("\n");
69038689Sborman     printf("%-15s %s\n", "?", "display help information");
69132144Sminshall     return 0;
69232144Sminshall }
69332144Sminshall 
694*46808Sdab     static void
69538689Sborman settogglehelp(set)
696*46808Sdab     int set;
69738689Sborman {
69838689Sborman     struct togglelist *c;
69938689Sborman 
70038689Sborman     for (c = Togglelist; c->name; c++) {
70138689Sborman 	if (c->help) {
70238689Sborman 	    if (*c->help)
70338689Sborman 		printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
70438689Sborman 						c->help);
70538689Sborman 	    else
70638689Sborman 		printf("\n");
70738689Sborman 	}
70838689Sborman     }
70938689Sborman }
71038689Sborman 
711*46808Sdab #define	GETTOGGLE(name) (struct togglelist *) \
712*46808Sdab 		genget(name, (char **) Togglelist, sizeof(struct togglelist))
71332144Sminshall 
714*46808Sdab     static int
71532144Sminshall toggle(argc, argv)
716*46808Sdab     int  argc;
717*46808Sdab     char *argv[];
71832144Sminshall {
71932144Sminshall     int retval = 1;
72032144Sminshall     char *name;
72132144Sminshall     struct togglelist *c;
72232144Sminshall 
72332144Sminshall     if (argc < 2) {
72432144Sminshall 	fprintf(stderr,
72532144Sminshall 	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
72632144Sminshall 	return 0;
72732144Sminshall     }
72832144Sminshall     argc--;
72932144Sminshall     argv++;
73032144Sminshall     while (argc--) {
73132144Sminshall 	name = *argv++;
732*46808Sdab 	c = GETTOGGLE(name);
73332144Sminshall 	if (Ambiguous(c)) {
73432144Sminshall 	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
73532144Sminshall 					name);
73632144Sminshall 	    return 0;
73732144Sminshall 	} else if (c == 0) {
73832144Sminshall 	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
73932144Sminshall 					name);
74032144Sminshall 	    return 0;
74132144Sminshall 	} else {
74232144Sminshall 	    if (c->variable) {
74332144Sminshall 		*c->variable = !*c->variable;		/* invert it */
74432144Sminshall 		if (c->actionexplanation) {
74532144Sminshall 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
74632144Sminshall 							c->actionexplanation);
74732144Sminshall 		}
74832144Sminshall 	    }
74932144Sminshall 	    if (c->handler) {
75038689Sborman 		retval &= (*c->handler)(-1);
75132144Sminshall 	    }
75232144Sminshall 	}
75332144Sminshall     }
75432144Sminshall     return retval;
75532144Sminshall }
75632144Sminshall 
75732144Sminshall /*
75832144Sminshall  * The following perform the "set" command.
75932144Sminshall  */
76032144Sminshall 
76138689Sborman #ifdef	USE_TERMIO
76238689Sborman struct termio new_tc = { 0 };
76338689Sborman #endif
76438689Sborman 
76532144Sminshall struct setlist {
76632144Sminshall     char *name;				/* name */
76732144Sminshall     char *help;				/* help information */
76838689Sborman     void (*handler)();
76940245Sborman     cc_t *charp;			/* where it is located at */
77032144Sminshall };
77132144Sminshall 
77232144Sminshall static struct setlist Setlist[] = {
77344361Sborman #ifdef	KLUDGELINEMODE
77438689Sborman     { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
77544361Sborman #endif
77638689Sborman     { "escape",	"character to escape back to telnet command mode", 0, &escape },
777*46808Sdab     { "rlogin", "rlogin escape character", 0, &rlogin },
77845233Sborman     { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
77932144Sminshall     { " ", "" },
78038689Sborman     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
78145233Sborman     { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
78238689Sborman     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
78338689Sborman     { "quit",	"character to cause an Abort process", 0, termQuitCharp },
78438689Sborman     { "eof",	"character to cause an EOF ", 0, termEofCharp },
78538689Sborman     { " ", "" },
78638689Sborman     { " ", "The following are for local editing in linemode", 0, 0 },
78738689Sborman     { "erase",	"character to use to erase a character", 0, termEraseCharp },
78838689Sborman     { "kill",	"character to use to erase a line", 0, termKillCharp },
78938689Sborman     { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
79044361Sborman     { "susp",	"character to cause a Suspend Process", 0, termSuspCharp },
79138689Sborman     { "reprint", "character to use for line reprint", 0, termRprntCharp },
79238689Sborman     { "worderase", "character to use to erase a word", 0, termWerasCharp },
79338689Sborman     { "start",	"character to use for XON", 0, termStartCharp },
79444361Sborman     { "stop",	"character to use for XOFF", 0, termStopCharp },
79544361Sborman     { "forw1",	"alternate end of line character", 0, termForw1Charp },
79644361Sborman     { "forw2",	"alternate end of line character", 0, termForw2Charp },
79745233Sborman     { "ayt",	"alternate AYT character", 0, termAytCharp },
79832144Sminshall     { 0 }
79932144Sminshall };
80032144Sminshall 
80145233Sborman #if	defined(CRAY) && !defined(__STDC__)
80245233Sborman /* Work around compiler bug in pcc 4.1.5 */
803*46808Sdab     void
80438689Sborman _setlist_init()
80538689Sborman {
80644361Sborman #ifndef	KLUDGELINEMODE
807*46808Sdab #define	N 5
80844361Sborman #else
809*46808Sdab #define	N 6
81044361Sborman #endif
81144361Sborman 	Setlist[N+0].charp = &termFlushChar;
81244361Sborman 	Setlist[N+1].charp = &termIntChar;
81344361Sborman 	Setlist[N+2].charp = &termQuitChar;
81444361Sborman 	Setlist[N+3].charp = &termEofChar;
81544361Sborman 	Setlist[N+6].charp = &termEraseChar;
81644361Sborman 	Setlist[N+7].charp = &termKillChar;
81744361Sborman 	Setlist[N+8].charp = &termLiteralNextChar;
81844361Sborman 	Setlist[N+9].charp = &termSuspChar;
81944361Sborman 	Setlist[N+10].charp = &termRprntChar;
82044361Sborman 	Setlist[N+11].charp = &termWerasChar;
82144361Sborman 	Setlist[N+12].charp = &termStartChar;
82244361Sborman 	Setlist[N+13].charp = &termStopChar;
82344361Sborman 	Setlist[N+14].charp = &termForw1Char;
82444361Sborman 	Setlist[N+15].charp = &termForw2Char;
82545233Sborman 	Setlist[N+16].charp = &termAytChar;
82644361Sborman #undef	N
82738689Sborman }
82845233Sborman #endif	/* defined(CRAY) && !defined(__STDC__) */
82938689Sborman 
830*46808Sdab     static struct setlist *
83132144Sminshall getset(name)
832*46808Sdab     char *name;
83332144Sminshall {
834*46808Sdab     return (struct setlist *)
835*46808Sdab 		genget(name, (char **) Setlist, sizeof(struct setlist));
83632144Sminshall }
83732144Sminshall 
838*46808Sdab     void
83944361Sborman set_escape_char(s)
840*46808Sdab     char *s;
84144361Sborman {
842*46808Sdab 	if (rlogin != _POSIX_VDISABLE) {
843*46808Sdab 		rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
844*46808Sdab 		printf("Telnet rlogin escape character is '%s'.\n",
845*46808Sdab 					control(rlogin));
846*46808Sdab 	} else {
847*46808Sdab 		escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
848*46808Sdab 		printf("Telnet escape character is '%s'.\n", control(escape));
849*46808Sdab 	}
85044361Sborman }
85144361Sborman 
852*46808Sdab     static int
85332144Sminshall setcmd(argc, argv)
854*46808Sdab     int  argc;
855*46808Sdab     char *argv[];
85632144Sminshall {
85732144Sminshall     int value;
85832144Sminshall     struct setlist *ct;
85938689Sborman     struct togglelist *c;
86032144Sminshall 
86138689Sborman     if (argc < 2 || argc > 3) {
86238689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
86332144Sminshall 	return 0;
86432144Sminshall     }
865*46808Sdab     if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
86638689Sborman 	for (ct = Setlist; ct->name; ct++)
86738689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
86838689Sborman 	printf("\n");
86938689Sborman 	settogglehelp(1);
87038689Sborman 	printf("%-15s %s\n", "?", "display help information");
87138689Sborman 	return 0;
87238689Sborman     }
87332144Sminshall 
87432144Sminshall     ct = getset(argv[1]);
87532144Sminshall     if (ct == 0) {
876*46808Sdab 	c = GETTOGGLE(argv[1]);
87738689Sborman 	if (c == 0) {
87838689Sborman 	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
87932144Sminshall 			argv[1]);
88038689Sborman 	    return 0;
88138689Sborman 	} else if (Ambiguous(c)) {
88238689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
88338689Sborman 			argv[1]);
88438689Sborman 	    return 0;
88538689Sborman 	}
88638689Sborman 	if (c->variable) {
88738689Sborman 	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
88838689Sborman 		*c->variable = 1;
88938689Sborman 	    else if (strcmp("off", argv[2]) == 0)
89038689Sborman 		*c->variable = 0;
89138689Sborman 	    else {
89238689Sborman 		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
89338689Sborman 		return 0;
89438689Sborman 	    }
89538689Sborman 	    if (c->actionexplanation) {
89638689Sborman 		printf("%s %s.\n", *c->variable? "Will" : "Won't",
89738689Sborman 							c->actionexplanation);
89838689Sborman 	    }
89938689Sborman 	}
90038689Sborman 	if (c->handler)
90138689Sborman 	    (*c->handler)(1);
90238689Sborman     } else if (argc != 3) {
90338689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
90432144Sminshall 	return 0;
90532144Sminshall     } else if (Ambiguous(ct)) {
90632144Sminshall 	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
90732144Sminshall 			argv[1]);
90832144Sminshall 	return 0;
90938689Sborman     } else if (ct->handler) {
91038689Sborman 	(*ct->handler)(argv[2]);
91144361Sborman 	printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
91232144Sminshall     } else {
91332144Sminshall 	if (strcmp("off", argv[2])) {
91432144Sminshall 	    value = special(argv[2]);
91532144Sminshall 	} else {
91645233Sborman 	    value = _POSIX_VDISABLE;
91732144Sminshall 	}
91840245Sborman 	*(ct->charp) = (cc_t)value;
91932144Sminshall 	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
92032144Sminshall     }
92138689Sborman     slc_check();
92232144Sminshall     return 1;
92332144Sminshall }
92438689Sborman 
925*46808Sdab     static int
92638689Sborman unsetcmd(argc, argv)
927*46808Sdab     int  argc;
928*46808Sdab     char *argv[];
92938689Sborman {
93038689Sborman     struct setlist *ct;
93138689Sborman     struct togglelist *c;
93238689Sborman     register char *name;
93338689Sborman 
93438689Sborman     if (argc < 2) {
93538689Sborman 	fprintf(stderr,
93638689Sborman 	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
93738689Sborman 	return 0;
93838689Sborman     }
939*46808Sdab     if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
94038689Sborman 	for (ct = Setlist; ct->name; ct++)
94138689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
94238689Sborman 	printf("\n");
94338689Sborman 	settogglehelp(0);
94438689Sborman 	printf("%-15s %s\n", "?", "display help information");
94538689Sborman 	return 0;
94638689Sborman     }
94738689Sborman 
94838689Sborman     argc--;
94938689Sborman     argv++;
95038689Sborman     while (argc--) {
95138689Sborman 	name = *argv++;
95238689Sborman 	ct = getset(name);
95338689Sborman 	if (ct == 0) {
954*46808Sdab 	    c = GETTOGGLE(name);
95538689Sborman 	    if (c == 0) {
95638689Sborman 		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
95738689Sborman 			name);
95838689Sborman 		return 0;
95938689Sborman 	    } else if (Ambiguous(c)) {
96038689Sborman 		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
96138689Sborman 			name);
96238689Sborman 		return 0;
96338689Sborman 	    }
96438689Sborman 	    if (c->variable) {
96538689Sborman 		*c->variable = 0;
96638689Sborman 		if (c->actionexplanation) {
96738689Sborman 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
96838689Sborman 							c->actionexplanation);
96938689Sborman 		}
97038689Sborman 	    }
97138689Sborman 	    if (c->handler)
97238689Sborman 		(*c->handler)(0);
97338689Sborman 	} else if (Ambiguous(ct)) {
97438689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
97538689Sborman 			name);
97638689Sborman 	    return 0;
97738689Sborman 	} else if (ct->handler) {
97838689Sborman 	    (*ct->handler)(0);
97944361Sborman 	    printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
98038689Sborman 	} else {
98145233Sborman 	    *(ct->charp) = _POSIX_VDISABLE;
98238689Sborman 	    printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
98338689Sborman 	}
98438689Sborman     }
98538689Sborman     return 1;
98638689Sborman }
98732144Sminshall 
98832144Sminshall /*
98932144Sminshall  * The following are the data structures and routines for the
99032144Sminshall  * 'mode' command.
99132144Sminshall  */
99238689Sborman #ifdef	KLUDGELINEMODE
99338689Sborman extern int kludgelinemode;
99444361Sborman 
995*46808Sdab     static int
99644361Sborman dokludgemode()
99744361Sborman {
99844361Sborman     kludgelinemode = 1;
99944361Sborman     send_wont(TELOPT_LINEMODE, 1);
100044361Sborman     send_dont(TELOPT_SGA, 1);
100144361Sborman     send_dont(TELOPT_ECHO, 1);
100244361Sborman }
100338689Sborman #endif
100432144Sminshall 
1005*46808Sdab     static int
100632144Sminshall dolinemode()
100732144Sminshall {
100838689Sborman #ifdef	KLUDGELINEMODE
100938689Sborman     if (kludgelinemode)
101038689Sborman 	send_dont(TELOPT_SGA, 1);
101138689Sborman #endif
101238689Sborman     send_will(TELOPT_LINEMODE, 1);
101338689Sborman     send_dont(TELOPT_ECHO, 1);
101432144Sminshall     return 1;
101532144Sminshall }
101632144Sminshall 
1017*46808Sdab     static int
101832144Sminshall docharmode()
101932144Sminshall {
102038689Sborman #ifdef	KLUDGELINEMODE
102138689Sborman     if (kludgelinemode)
102238689Sborman 	send_do(TELOPT_SGA, 1);
102338689Sborman     else
102438689Sborman #endif
102538689Sborman     send_wont(TELOPT_LINEMODE, 1);
102638689Sborman     send_do(TELOPT_ECHO, 1);
102738689Sborman     return 1;
102838689Sborman }
102938689Sborman 
1030*46808Sdab     static int
103138689Sborman dolmmode(bit, on)
1032*46808Sdab     int bit, on;
103338689Sborman {
1034*46808Sdab     unsigned char c;
103538689Sborman     extern int linemode;
103638689Sborman 
103738689Sborman     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
103838689Sborman 	printf("?Need to have LINEMODE option enabled first.\n");
103938689Sborman 	printf("'mode ?' for help.\n");
104038689Sborman 	return 0;
104132144Sminshall     }
104238689Sborman 
104338689Sborman     if (on)
104438689Sborman 	c = (linemode | bit);
104538689Sborman     else
104638689Sborman 	c = (linemode & ~bit);
104738689Sborman     lm_mode(&c, 1, 1);
104832144Sminshall     return 1;
104932144Sminshall }
105032144Sminshall 
1051*46808Sdab     int
1052*46808Sdab setmode(bit)
1053*46808Sdab {
1054*46808Sdab     return dolmmode(bit, 1);
1055*46808Sdab }
1056*46808Sdab 
1057*46808Sdab     int
1058*46808Sdab clearmode(bit)
1059*46808Sdab {
1060*46808Sdab     return dolmmode(bit, 0);
1061*46808Sdab }
1062*46808Sdab 
106338689Sborman struct modelist {
106438689Sborman 	char	*name;		/* command name */
106538689Sborman 	char	*help;		/* help string */
106638689Sborman 	int	(*handler)();	/* routine which executes command */
106738689Sborman 	int	needconnect;	/* Do we need to be connected to execute? */
106838689Sborman 	int	arg1;
106938689Sborman };
107038689Sborman 
107138689Sborman extern int modehelp();
107238689Sborman 
107338689Sborman static struct modelist ModeList[] = {
107438689Sborman     { "character", "Disable LINEMODE option",	docharmode, 1 },
107539529Sborman #ifdef	KLUDGELINEMODE
107639529Sborman     { "",	"(or disable obsolete line-by-line mode)", 0 },
107738689Sborman #endif
107838689Sborman     { "line",	"Enable LINEMODE option",	dolinemode, 1 },
107939529Sborman #ifdef	KLUDGELINEMODE
108039529Sborman     { "",	"(or enable obsolete line-by-line mode)", 0 },
108138689Sborman #endif
108238689Sborman     { "", "", 0 },
108338689Sborman     { "",	"These require the LINEMODE option to be enabled", 0 },
108438689Sborman     { "isig",	"Enable signal trapping",	setmode, 1, MODE_TRAPSIG },
108538689Sborman     { "+isig",	0,				setmode, 1, MODE_TRAPSIG },
108638689Sborman     { "-isig",	"Disable signal trapping",	clearmode, 1, MODE_TRAPSIG },
108738689Sborman     { "edit",	"Enable character editing",	setmode, 1, MODE_EDIT },
108838689Sborman     { "+edit",	0,				setmode, 1, MODE_EDIT },
108938689Sborman     { "-edit",	"Disable character editing",	clearmode, 1, MODE_EDIT },
109044361Sborman     { "softtabs", "Enable tab expansion",	setmode, 1, MODE_SOFT_TAB },
109144361Sborman     { "+softtabs", 0,				setmode, 1, MODE_SOFT_TAB },
109244361Sborman     { "-softtabs", "Disable character editing",	clearmode, 1, MODE_SOFT_TAB },
109344361Sborman     { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
109444361Sborman     { "+litecho", 0,				setmode, 1, MODE_LIT_ECHO },
109544361Sborman     { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
109638689Sborman     { "help",	0,				modehelp, 0 },
109744361Sborman #ifdef	KLUDGELINEMODE
109844361Sborman     { "kludgeline", 0,				dokludgemode, 1 },
109944361Sborman #endif
110044361Sborman     { "", "", 0 },
110138689Sborman     { "?",	"Print help information",	modehelp, 0 },
110232144Sminshall     { 0 },
110332144Sminshall };
110432144Sminshall 
110532144Sminshall 
1106*46808Sdab     int
110738689Sborman modehelp()
110838689Sborman {
110938689Sborman     struct modelist *mt;
111038689Sborman 
111138689Sborman     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
111238689Sborman     for (mt = ModeList; mt->name; mt++) {
111338689Sborman 	if (mt->help) {
111438689Sborman 	    if (*mt->help)
111538689Sborman 		printf("%-15s %s\n", mt->name, mt->help);
111638689Sborman 	    else
111738689Sborman 		printf("\n");
111838689Sborman 	}
111938689Sborman     }
112038689Sborman     return 0;
112138689Sborman }
112238689Sborman 
1123*46808Sdab #define	GETMODECMD(name) (struct modelist *) \
1124*46808Sdab 		genget(name, (char **) ModeList, sizeof(struct modelist))
1125*46808Sdab 
1126*46808Sdab     static int
112732144Sminshall modecmd(argc, argv)
1128*46808Sdab     int  argc;
1129*46808Sdab     char *argv[];
113032144Sminshall {
113138689Sborman     struct modelist *mt;
113232144Sminshall 
113338689Sborman     if (argc != 2) {
113438689Sborman 	printf("'mode' command requires an argument\n");
113538689Sborman 	printf("'mode ?' for help.\n");
1136*46808Sdab     } else if ((mt = GETMODECMD(argv[1])) == 0) {
113732144Sminshall 	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
113832144Sminshall     } else if (Ambiguous(mt)) {
113932144Sminshall 	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
114038689Sborman     } else if (mt->needconnect && !connected) {
114138689Sborman 	printf("?Need to be connected first.\n");
114238689Sborman 	printf("'mode ?' for help.\n");
114338689Sborman     } else if (mt->handler) {
114438689Sborman 	return (*mt->handler)(mt->arg1);
114532144Sminshall     }
114638689Sborman     return 0;
114732144Sminshall }
114832144Sminshall 
114932144Sminshall /*
115032144Sminshall  * The following data structures and routines implement the
115132144Sminshall  * "display" command.
115232144Sminshall  */
115332144Sminshall 
1154*46808Sdab     static int
115532144Sminshall display(argc, argv)
1156*46808Sdab     int  argc;
1157*46808Sdab     char *argv[];
115832144Sminshall {
1159*46808Sdab     struct togglelist *tl;
1160*46808Sdab     struct setlist *sl;
1161*46808Sdab 
116232144Sminshall #define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
116332144Sminshall 			    if (*tl->variable) { \
116432144Sminshall 				printf("will"); \
116532144Sminshall 			    } else { \
116632144Sminshall 				printf("won't"); \
116732144Sminshall 			    } \
116832144Sminshall 			    printf(" %s.\n", tl->actionexplanation); \
116932144Sminshall 			}
117032144Sminshall 
117132144Sminshall #define	doset(sl)   if (sl->name && *sl->name != ' ') { \
117238689Sborman 			if (sl->handler == 0) \
117338689Sborman 			    printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
117438689Sborman 			else \
117544361Sborman 			    printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
117632144Sminshall 		    }
117732144Sminshall 
117832144Sminshall     if (argc == 1) {
117932144Sminshall 	for (tl = Togglelist; tl->name; tl++) {
118032144Sminshall 	    dotog(tl);
118132144Sminshall 	}
118232144Sminshall 	printf("\n");
118332144Sminshall 	for (sl = Setlist; sl->name; sl++) {
118432144Sminshall 	    doset(sl);
118532144Sminshall 	}
118632144Sminshall     } else {
118732144Sminshall 	int i;
118832144Sminshall 
118932144Sminshall 	for (i = 1; i < argc; i++) {
119032144Sminshall 	    sl = getset(argv[i]);
1191*46808Sdab 	    tl = GETTOGGLE(argv[i]);
119232144Sminshall 	    if (Ambiguous(sl) || Ambiguous(tl)) {
119332144Sminshall 		printf("?Ambiguous argument '%s'.\n", argv[i]);
119432144Sminshall 		return 0;
119532144Sminshall 	    } else if (!sl && !tl) {
119632144Sminshall 		printf("?Unknown argument '%s'.\n", argv[i]);
119732144Sminshall 		return 0;
119832144Sminshall 	    } else {
119932144Sminshall 		if (tl) {
120032144Sminshall 		    dotog(tl);
120132144Sminshall 		}
120232144Sminshall 		if (sl) {
120332144Sminshall 		    doset(sl);
120432144Sminshall 		}
120532144Sminshall 	    }
120632144Sminshall 	}
120732144Sminshall     }
120838689Sborman /*@*/optionstatus();
1209*46808Sdab #if	defined(ENCRYPT)
1210*46808Sdab     EncryptStatus();
1211*46808Sdab #endif
121232144Sminshall     return 1;
121332144Sminshall #undef	doset
121432144Sminshall #undef	dotog
121532144Sminshall }
121632144Sminshall 
121732144Sminshall /*
121832144Sminshall  * The following are the data structures, and many of the routines,
121932144Sminshall  * relating to command processing.
122032144Sminshall  */
122132144Sminshall 
122232144Sminshall /*
122332144Sminshall  * Set the escape character.
122432144Sminshall  */
1225*46808Sdab 	static int
122632144Sminshall setescape(argc, argv)
122732144Sminshall 	int argc;
122832144Sminshall 	char *argv[];
122932144Sminshall {
123032144Sminshall 	register char *arg;
123132144Sminshall 	char buf[50];
123232144Sminshall 
123332144Sminshall 	printf(
123432144Sminshall 	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
123532144Sminshall 				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
123632144Sminshall 	if (argc > 2)
123732144Sminshall 		arg = argv[1];
123832144Sminshall 	else {
123932144Sminshall 		printf("new escape character: ");
1240*46808Sdab 		(void) fgets(buf, sizeof(buf), stdin);
124132144Sminshall 		arg = buf;
124232144Sminshall 	}
124332144Sminshall 	if (arg[0] != '\0')
124432144Sminshall 		escape = arg[0];
124532144Sminshall 	if (!In3270) {
124632144Sminshall 		printf("Escape character is '%s'.\n", control(escape));
124732144Sminshall 	}
124834849Sminshall 	(void) fflush(stdout);
124932144Sminshall 	return 1;
125032144Sminshall }
125132144Sminshall 
1252*46808Sdab     /*VARARGS*/
1253*46808Sdab     static int
125432144Sminshall togcrmod()
125532144Sminshall {
125632144Sminshall     crmod = !crmod;
125732144Sminshall     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
125832144Sminshall     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
125934849Sminshall     (void) fflush(stdout);
126032144Sminshall     return 1;
126132144Sminshall }
126232144Sminshall 
1263*46808Sdab     /*VARARGS*/
1264*46808Sdab     int
126532144Sminshall suspend()
126632144Sminshall {
126738689Sborman #ifdef	SIGTSTP
126837219Sminshall     setcommandmode();
126937219Sminshall     {
127044361Sborman 	long oldrows, oldcols, newrows, newcols, err;
127137219Sminshall 
127244361Sborman 	err = TerminalWindowSize(&oldrows, &oldcols);
127334849Sminshall 	(void) kill(0, SIGTSTP);
127444361Sborman 	err += TerminalWindowSize(&newrows, &newcols);
127544361Sborman 	if (connected && !err &&
127644361Sborman 	    ((oldrows != newrows) || (oldcols != newcols))) {
127737219Sminshall 		sendnaws();
127837219Sminshall 	}
127937219Sminshall     }
128037219Sminshall     /* reget parameters in case they were changed */
128137219Sminshall     TerminalSaveState();
128238689Sborman     setconnmode(0);
128338689Sborman #else
128438689Sborman     printf("Suspend is not supported.  Try the '!' command instead\n");
128538689Sborman #endif
128637219Sminshall     return 1;
128732144Sminshall }
128832144Sminshall 
128938689Sborman #if	!defined(TN3270)
1290*46808Sdab     /*ARGSUSED*/
1291*46808Sdab     int
129238689Sborman shell(argc, argv)
1293*46808Sdab     int argc;
1294*46808Sdab     char *argv[];
129538689Sborman {
129638689Sborman     setcommandmode();
129738689Sborman     switch(vfork()) {
129838689Sborman     case -1:
129938689Sborman 	perror("Fork failed\n");
130038689Sborman 	break;
130138689Sborman 
130238689Sborman     case 0:
130338689Sborman 	{
130438689Sborman 	    /*
130538689Sborman 	     * Fire up the shell in the child.
130638689Sborman 	     */
1307*46808Sdab 	    register char *shellp, *shellname;
1308*46808Sdab 	    extern char *rindex();
130938689Sborman 
1310*46808Sdab 	    shellp = getenv("SHELL");
1311*46808Sdab 	    if (shellp == NULL)
1312*46808Sdab 		shellp = "/bin/sh";
1313*46808Sdab 	    if ((shellname = rindex(shellp, '/')) == 0)
1314*46808Sdab 		shellname = shellp;
131538689Sborman 	    else
131638689Sborman 		shellname++;
131738689Sborman 	    if (argc > 1)
1318*46808Sdab 		execl(shellp, shellname, "-c", &saveline[1], 0);
131938689Sborman 	    else
1320*46808Sdab 		execl(shellp, shellname, 0);
132138689Sborman 	    perror("Execl");
132238689Sborman 	    _exit(1);
132338689Sborman 	}
132438689Sborman     default:
132544361Sborman 	    (void)wait((int *)0);	/* Wait for the shell to complete */
132638689Sborman     }
1327*46808Sdab     return 1;
132838689Sborman }
132938689Sborman #endif	/* !defined(TN3270) */
133038689Sborman 
1331*46808Sdab     /*VARARGS*/
1332*46808Sdab     static
133332144Sminshall bye(argc, argv)
1334*46808Sdab     int  argc;		/* Number of arguments */
1335*46808Sdab     char *argv[];	/* arguments */
133632144Sminshall {
1337*46808Sdab     extern int resettermname;
1338*46808Sdab 
133932144Sminshall     if (connected) {
134034849Sminshall 	(void) shutdown(net, 2);
134132144Sminshall 	printf("Connection closed.\n");
134234849Sminshall 	(void) NetClose(net);
134332144Sminshall 	connected = 0;
1344*46808Sdab 	resettermname = 1;
1345*46808Sdab #if	defined(AUTHENTICATE) || defined(ENCRYPT)
1346*46808Sdab 	auth_encrypt_connect(connected);
1347*46808Sdab #endif
134832144Sminshall 	/* reset options */
134932144Sminshall 	tninit();
135032144Sminshall #if	defined(TN3270)
135132144Sminshall 	SetIn3270();		/* Get out of 3270 mode */
135232144Sminshall #endif	/* defined(TN3270) */
135332144Sminshall     }
135432144Sminshall     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
135532144Sminshall 	longjmp(toplevel, 1);
135632144Sminshall 	/* NOTREACHED */
135732144Sminshall     }
135832144Sminshall     return 1;			/* Keep lint, etc., happy */
135932144Sminshall }
136032144Sminshall 
136132144Sminshall /*VARARGS*/
136232144Sminshall quit()
136332144Sminshall {
136432144Sminshall 	(void) call(bye, "bye", "fromquit", 0);
136532144Sminshall 	Exit(0);
136644361Sborman 	/*NOTREACHED*/
136732144Sminshall }
1368*46808Sdab 
1369*46808Sdab /*VARARGS*/
1370*46808Sdab 	int
1371*46808Sdab logout()
1372*46808Sdab {
1373*46808Sdab 	send_do(TELOPT_LOGOUT, 1);
1374*46808Sdab 	(void) netflush();
1375*46808Sdab 	return 1;
1376*46808Sdab }
1377*46808Sdab 
137838689Sborman 
137938689Sborman /*
138038689Sborman  * The SLC command.
138138689Sborman  */
138232144Sminshall 
138338689Sborman struct slclist {
138438689Sborman 	char	*name;
138538689Sborman 	char	*help;
1386*46808Sdab 	void	(*handler)();
138738689Sborman 	int	arg;
138838689Sborman };
138938689Sborman 
1390*46808Sdab extern void slc_help();
139138689Sborman 
139238689Sborman struct slclist SlcList[] = {
139338689Sborman     { "export",	"Use local special character definitions",
139438689Sborman 						slc_mode_export,	0 },
139538689Sborman     { "import",	"Use remote special character definitions",
139638689Sborman 						slc_mode_import,	1 },
139738689Sborman     { "check",	"Verify remote special character definitions",
139838689Sborman 						slc_mode_import,	0 },
139938689Sborman     { "help",	0,				slc_help,		0 },
140038689Sborman     { "?",	"Print help information",	slc_help,		0 },
140138689Sborman     { 0 },
140238689Sborman };
140338689Sborman 
1404*46808Sdab     static void
140538689Sborman slc_help()
140638689Sborman {
140738689Sborman     struct slclist *c;
140838689Sborman 
140938689Sborman     for (c = SlcList; c->name; c++) {
141038689Sborman 	if (c->help) {
141138689Sborman 	    if (*c->help)
141238689Sborman 		printf("%-15s %s\n", c->name, c->help);
141338689Sborman 	    else
141438689Sborman 		printf("\n");
141538689Sborman 	}
141638689Sborman     }
141738689Sborman }
141838689Sborman 
1419*46808Sdab     static struct slclist *
142038689Sborman getslc(name)
1421*46808Sdab     char *name;
142238689Sborman {
1423*46808Sdab     return (struct slclist *)
1424*46808Sdab 		genget(name, (char **) SlcList, sizeof(struct slclist));
142538689Sborman }
142638689Sborman 
1427*46808Sdab     static
142838689Sborman slccmd(argc, argv)
1429*46808Sdab     int  argc;
1430*46808Sdab     char *argv[];
143138689Sborman {
143238689Sborman     struct slclist *c;
143338689Sborman 
143438689Sborman     if (argc != 2) {
143538689Sborman 	fprintf(stderr,
143638689Sborman 	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
143738689Sborman 	return 0;
143838689Sborman     }
143938689Sborman     c = getslc(argv[1]);
144038689Sborman     if (c == 0) {
144138689Sborman         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
144238689Sborman     				argv[1]);
144338689Sborman         return 0;
144438689Sborman     }
144538689Sborman     if (Ambiguous(c)) {
144638689Sborman         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
144738689Sborman     				argv[1]);
144838689Sborman         return 0;
144938689Sborman     }
145038689Sborman     (*c->handler)(c->arg);
145138689Sborman     slcstate();
145238689Sborman     return 1;
145338689Sborman }
145444361Sborman 
145544361Sborman /*
145644361Sborman  * The ENVIRON command.
145744361Sborman  */
145838689Sborman 
145944361Sborman struct envlist {
146044361Sborman 	char	*name;
146144361Sborman 	char	*help;
1462*46808Sdab 	void	(*handler)();
146344361Sborman 	int	narg;
146444361Sborman };
146544361Sborman 
1466*46808Sdab extern struct env_lst *
1467*46808Sdab 	env_define P((unsigned char *, unsigned char *));
1468*46808Sdab extern void
1469*46808Sdab 	env_undefine P((unsigned char *)),
1470*46808Sdab 	env_export P((unsigned char *)),
1471*46808Sdab 	env_unexport P((unsigned char *)),
1472*46808Sdab 	env_send P((unsigned char *)),
1473*46808Sdab 	env_list P((void)),
1474*46808Sdab 	env_help P((void));
147544361Sborman 
147644361Sborman struct envlist EnvList[] = {
147744361Sborman     { "define",	"Define an environment variable",
1478*46808Sdab 						(void (*)())env_define,	2 },
147944361Sborman     { "undefine", "Undefine an environment variable",
148044361Sborman 						env_undefine,	1 },
148144361Sborman     { "export",	"Mark an environment variable for automatic export",
148244361Sborman 						env_export,	1 },
1483*46808Sdab     { "unexport", "Don't mark an environment variable for automatic export",
148444361Sborman 						env_unexport,	1 },
148545233Sborman     { "send",	"Send an environment variable", env_send,	1 },
148644361Sborman     { "list",	"List the current environment variables",
148744361Sborman 						env_list,	0 },
148844361Sborman     { "help",	0,				env_help,		0 },
148944361Sborman     { "?",	"Print help information",	env_help,		0 },
149044361Sborman     { 0 },
149144361Sborman };
149244361Sborman 
1493*46808Sdab     static void
149444361Sborman env_help()
149544361Sborman {
149644361Sborman     struct envlist *c;
149744361Sborman 
149844361Sborman     for (c = EnvList; c->name; c++) {
149944361Sborman 	if (c->help) {
150044361Sborman 	    if (*c->help)
150144361Sborman 		printf("%-15s %s\n", c->name, c->help);
150244361Sborman 	    else
150344361Sborman 		printf("\n");
150444361Sborman 	}
150544361Sborman     }
150644361Sborman }
150744361Sborman 
1508*46808Sdab     static struct envlist *
150944361Sborman getenvcmd(name)
1510*46808Sdab     char *name;
151144361Sborman {
1512*46808Sdab     return (struct envlist *)
1513*46808Sdab 		genget(name, (char **) EnvList, sizeof(struct envlist));
151444361Sborman }
151544361Sborman 
151644361Sborman env_cmd(argc, argv)
1517*46808Sdab     int  argc;
1518*46808Sdab     char *argv[];
151944361Sborman {
152044361Sborman     struct envlist *c;
152144361Sborman 
152244361Sborman     if (argc < 2) {
152344361Sborman 	fprintf(stderr,
152444361Sborman 	    "Need an argument to 'environ' command.  'environ ?' for help.\n");
152544361Sborman 	return 0;
152644361Sborman     }
152744361Sborman     c = getenvcmd(argv[1]);
152844361Sborman     if (c == 0) {
152944361Sborman         fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
153044361Sborman     				argv[1]);
153144361Sborman         return 0;
153244361Sborman     }
153344361Sborman     if (Ambiguous(c)) {
153444361Sborman         fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
153544361Sborman     				argv[1]);
153644361Sborman         return 0;
153744361Sborman     }
153844361Sborman     if (c->narg + 2 != argc) {
153944361Sborman 	fprintf(stderr,
154044361Sborman 	    "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
154144361Sborman 		c->narg < argc + 2 ? "only " : "",
154244361Sborman 		c->narg, c->narg == 1 ? "" : "s", c->name);
154344361Sborman 	return 0;
154444361Sborman     }
1545*46808Sdab     (*c->handler)(argv[2], argv[3]);
154644361Sborman     return 1;
154744361Sborman }
154844361Sborman 
154944361Sborman struct env_lst {
155044361Sborman 	struct env_lst *next;	/* pointer to next structure */
155144361Sborman 	struct env_lst *prev;	/* pointer to next structure */
1552*46808Sdab 	unsigned char *var;	/* pointer to variable name */
1553*46808Sdab 	unsigned char *value;	/* pointer to varialbe value */
155444361Sborman 	int export;		/* 1 -> export with default list of variables */
155544361Sborman };
155644361Sborman 
155744361Sborman struct env_lst envlisthead;
155844361Sborman 
1559*46808Sdab 	struct env_lst *
156044361Sborman env_find(var)
1561*46808Sdab 	unsigned char *var;
156244361Sborman {
156344361Sborman 	register struct env_lst *ep;
156444361Sborman 
156544361Sborman 	for (ep = envlisthead.next; ep; ep = ep->next) {
1566*46808Sdab 		if (strcmp((char *)ep->var, (char *)var) == 0)
156744361Sborman 			return(ep);
156844361Sborman 	}
156944361Sborman 	return(NULL);
157044361Sborman }
157144361Sborman 
1572*46808Sdab 	void
157344361Sborman env_init()
157444361Sborman {
1575*46808Sdab 	extern char **environ;
157644361Sborman 	register char **epp, *cp;
157744361Sborman 	register struct env_lst *ep;
1578*46808Sdab 	extern char *index();
157944361Sborman 
158044361Sborman 	for (epp = environ; *epp; epp++) {
158144361Sborman 		if (cp = index(*epp, '=')) {
158244361Sborman 			*cp = '\0';
1583*46808Sdab 			ep = env_define((unsigned char *)*epp,
1584*46808Sdab 					(unsigned char *)cp+1);
158544361Sborman 			ep->export = 0;
158644361Sborman 			*cp = '=';
158744361Sborman 		}
158844361Sborman 	}
158944361Sborman 	/*
159044361Sborman 	 * Special case for DISPLAY variable.  If it is ":0.0" or
159144361Sborman 	 * "unix:0.0", we have to get rid of "unix" and insert our
159244361Sborman 	 * hostname.
159344361Sborman 	 */
1594*46808Sdab 	if ((ep = env_find("DISPLAY"))
1595*46808Sdab 	    && ((*ep->value == ':')
1596*46808Sdab 	        || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
159744361Sborman 		char hbuf[256+1];
1598*46808Sdab 		char *cp2 = index((char *)ep->value, ':');
159944361Sborman 
160044361Sborman 		gethostname(hbuf, 256);
160144361Sborman 		hbuf[256] = '\0';
160244361Sborman 		cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
1603*46808Sdab 		sprintf((char *)cp, "%s%s", hbuf, cp2);
160444361Sborman 		free(ep->value);
1605*46808Sdab 		ep->value = (unsigned char *)cp;
160644361Sborman 	}
160744361Sborman 	/*
160844361Sborman 	 * If USER is not defined, but LOGNAME is, then add
160945233Sborman 	 * USER with the value from LOGNAME.  By default, we
161045233Sborman 	 * don't export the USER variable.
161144361Sborman 	 */
161245233Sborman 	if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
1613*46808Sdab 		env_define((unsigned char *)"USER", ep->value);
1614*46808Sdab 		env_unexport((unsigned char *)"USER");
161545233Sborman 	}
1616*46808Sdab 	env_export((unsigned char *)"DISPLAY");
1617*46808Sdab 	env_export((unsigned char *)"PRINTER");
161844361Sborman }
161944361Sborman 
1620*46808Sdab 	struct env_lst *
162144361Sborman env_define(var, value)
1622*46808Sdab 	unsigned char *var, *value;
162344361Sborman {
162444361Sborman 	register struct env_lst *ep;
162544361Sborman 
162644361Sborman 	if (ep = env_find(var)) {
162744361Sborman 		if (ep->var)
162844361Sborman 			free(ep->var);
162944361Sborman 		if (ep->value)
163044361Sborman 			free(ep->value);
163144361Sborman 	} else {
163244361Sborman 		ep = (struct env_lst *)malloc(sizeof(struct env_lst));
163344361Sborman 		ep->next = envlisthead.next;
163444361Sborman 		envlisthead.next = ep;
163544361Sborman 		ep->prev = &envlisthead;
163644361Sborman 		if (ep->next)
163744361Sborman 			ep->next->prev = ep;
163844361Sborman 	}
163945009Skarels 	ep->export = 1;
1640*46808Sdab 	ep->var = (unsigned char *)strdup((char *)var);
1641*46808Sdab 	ep->value = (unsigned char *)strdup((char *)value);
164244361Sborman 	return(ep);
164344361Sborman }
164444361Sborman 
1645*46808Sdab 	void
164644361Sborman env_undefine(var)
1647*46808Sdab 	unsigned char *var;
164844361Sborman {
164944361Sborman 	register struct env_lst *ep;
165044361Sborman 
165144361Sborman 	if (ep = env_find(var)) {
165244361Sborman 		ep->prev->next = ep->next;
165345233Sborman 		if (ep->next)
165445233Sborman 			ep->next->prev = ep->prev;
165544361Sborman 		if (ep->var)
165644361Sborman 			free(ep->var);
165744361Sborman 		if (ep->value)
165844361Sborman 			free(ep->value);
165944361Sborman 		free(ep);
166044361Sborman 	}
166144361Sborman }
166244361Sborman 
1663*46808Sdab 	void
166444361Sborman env_export(var)
1665*46808Sdab 	unsigned char *var;
166644361Sborman {
166744361Sborman 	register struct env_lst *ep;
166844361Sborman 
166944361Sborman 	if (ep = env_find(var))
167044361Sborman 		ep->export = 1;
167144361Sborman }
167244361Sborman 
1673*46808Sdab 	void
167444361Sborman env_unexport(var)
1675*46808Sdab 	unsigned char *var;
167644361Sborman {
167744361Sborman 	register struct env_lst *ep;
167844361Sborman 
167944361Sborman 	if (ep = env_find(var))
168044361Sborman 		ep->export = 0;
168144361Sborman }
168244361Sborman 
1683*46808Sdab 	void
168445233Sborman env_send(var)
1685*46808Sdab 	unsigned char *var;
168645233Sborman {
168745233Sborman 	register struct env_lst *ep;
168845233Sborman 
168945233Sborman         if (my_state_is_wont(TELOPT_ENVIRON)) {
169045233Sborman 		fprintf(stderr,
169145233Sborman 		    "Cannot send '%s': Telnet ENVIRON option not enabled\n",
169245233Sborman 									var);
169345233Sborman 		return;
169445233Sborman 	}
169545233Sborman 	ep = env_find(var);
169645233Sborman 	if (ep == 0) {
169745233Sborman 		fprintf(stderr, "Cannot send '%s': variable not defined\n",
169845233Sborman 									var);
169945233Sborman 		return;
170045233Sborman 	}
170145233Sborman 	env_opt_start_info();
170245233Sborman 	env_opt_add(ep->var);
170345233Sborman 	env_opt_end(0);
170445233Sborman }
170545233Sborman 
1706*46808Sdab 	void
170744361Sborman env_list()
170844361Sborman {
170944361Sborman 	register struct env_lst *ep;
171044361Sborman 
171144361Sborman 	for (ep = envlisthead.next; ep; ep = ep->next) {
171244361Sborman 		printf("%c %-20s %s\n", ep->export ? '*' : ' ',
171344361Sborman 					ep->var, ep->value);
171444361Sborman 	}
171544361Sborman }
171644361Sborman 
1717*46808Sdab 	unsigned char *
171844361Sborman env_default(init)
1719*46808Sdab 	int init;
172044361Sborman {
172144361Sborman 	static struct env_lst *nep = NULL;
172244361Sborman 
172344361Sborman 	if (init) {
172444361Sborman 		nep = &envlisthead;
172544361Sborman 		return;
172644361Sborman 	}
172744361Sborman 	if (nep) {
172844361Sborman 		while (nep = nep->next) {
172944361Sborman 			if (nep->export)
173044361Sborman 				return(nep->var);
173144361Sborman 		}
173244361Sborman 	}
173344361Sborman 	return(NULL);
173444361Sborman }
173544361Sborman 
1736*46808Sdab 	unsigned char *
173744361Sborman env_getvalue(var)
1738*46808Sdab 	unsigned char *var;
173944361Sborman {
174044361Sborman 	register struct env_lst *ep;
174144361Sborman 
174244361Sborman 	if (ep = env_find(var))
174344361Sborman 		return(ep->value);
174444361Sborman 	return(NULL);
174544361Sborman }
174644361Sborman 
1747*46808Sdab #if	defined(AUTHENTICATE)
1748*46808Sdab /*
1749*46808Sdab  * The AUTHENTICATE command.
1750*46808Sdab  */
1751*46808Sdab 
1752*46808Sdab struct authlist {
1753*46808Sdab 	char	*name;
1754*46808Sdab 	char	*help;
1755*46808Sdab 	int	(*handler)();
1756*46808Sdab 	int	narg;
1757*46808Sdab };
1758*46808Sdab 
1759*46808Sdab extern int
1760*46808Sdab 	auth_enable P((int)),
1761*46808Sdab 	auth_disable P((int)),
1762*46808Sdab 	auth_status P((void)),
1763*46808Sdab 	auth_togdebug P((void)),
1764*46808Sdab 	auth_help P((void));
1765*46808Sdab 
1766*46808Sdab struct authlist AuthList[] = {
1767*46808Sdab     { "status",	"Display current status of authentication information",
1768*46808Sdab 						auth_status,	0 },
1769*46808Sdab     { "debug",	"Toggle authentication debugging",
1770*46808Sdab 						auth_togdebug,	0 },
1771*46808Sdab     { "disable", "Disable an authentication type ('auth disable ?' for more)",
1772*46808Sdab 						auth_disable,	1 },
1773*46808Sdab     { "enable", "Enable an authentication type ('auth enable ?' for more)",
1774*46808Sdab 						auth_enable,	1 },
1775*46808Sdab     { "help",	0,				auth_help,		0 },
1776*46808Sdab     { "?",	"Print help information",	auth_help,		0 },
1777*46808Sdab     { 0 },
1778*46808Sdab };
1779*46808Sdab 
1780*46808Sdab     static int
1781*46808Sdab auth_help()
178244361Sborman {
1783*46808Sdab     struct authlist *c;
1784*46808Sdab 
1785*46808Sdab     for (c = AuthList; c->name; c++) {
1786*46808Sdab 	if (c->help) {
1787*46808Sdab 	    if (*c->help)
1788*46808Sdab 		printf("%-15s %s\n", c->name, c->help);
1789*46808Sdab 	    else
1790*46808Sdab 		printf("\n");
1791*46808Sdab 	}
1792*46808Sdab     }
1793*46808Sdab     return 0;
179444361Sborman }
1795*46808Sdab 
1796*46808Sdab auth_cmd(argc, argv)
1797*46808Sdab     int  argc;
1798*46808Sdab     char *argv[];
1799*46808Sdab {
1800*46808Sdab     struct authlist *c;
1801*46808Sdab 
1802*46808Sdab     c = (struct authlist *)
1803*46808Sdab 		genget(argv[1], (char **) AuthList, sizeof(struct authlist));
1804*46808Sdab     if (c == 0) {
1805*46808Sdab         fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
1806*46808Sdab     				argv[1]);
1807*46808Sdab         return 0;
1808*46808Sdab     }
1809*46808Sdab     if (Ambiguous(c)) {
1810*46808Sdab         fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
1811*46808Sdab     				argv[1]);
1812*46808Sdab         return 0;
1813*46808Sdab     }
1814*46808Sdab     if (c->narg + 2 != argc) {
1815*46808Sdab 	fprintf(stderr,
1816*46808Sdab 	    "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
1817*46808Sdab 		c->narg < argc + 2 ? "only " : "",
1818*46808Sdab 		c->narg, c->narg == 1 ? "" : "s", c->name);
1819*46808Sdab 	return 0;
1820*46808Sdab     }
1821*46808Sdab     return((*c->handler)(argv[2], argv[3]));
1822*46808Sdab }
182345233Sborman #endif
182444361Sborman 
1825*46808Sdab #if	defined(ENCRYPT)
182632144Sminshall /*
1827*46808Sdab  * The ENCRYPT command.
182836274Sminshall  */
182936274Sminshall 
1830*46808Sdab struct encryptlist {
1831*46808Sdab 	char	*name;
1832*46808Sdab 	char	*help;
1833*46808Sdab 	int	(*handler)();
1834*46808Sdab 	int	needconnect;
1835*46808Sdab 	int	minarg;
1836*46808Sdab 	int	maxarg;
1837*46808Sdab };
1838*46808Sdab 
1839*46808Sdab extern int
1840*46808Sdab 	EncryptEnable P((char *, char *)),
1841*46808Sdab 	EncryptType P((char *, char *)),
1842*46808Sdab 	EncryptStart P((char *)),
1843*46808Sdab 	EncryptStartInput P((void)),
1844*46808Sdab 	EncryptStartOutput P((void)),
1845*46808Sdab 	EncryptStop P((char *)),
1846*46808Sdab 	EncryptStopInput P((void)),
1847*46808Sdab 	EncryptStopOutput P((void)),
1848*46808Sdab 	EncryptTogAuto P((void)),
1849*46808Sdab 	EncryptTogDebug P((void)),
1850*46808Sdab 	EncryptTogVerbose P((void)),
1851*46808Sdab 	EncryptStatus P((void)),
1852*46808Sdab 	EncryptHelp P((void));
1853*46808Sdab 
1854*46808Sdab struct encryptlist EncryptList[] = {
1855*46808Sdab     { "enable", "Enable encryption. ('encrypt enable ?' for more)",
1856*46808Sdab 						EncryptEnable, 1, 1, 2 },
1857*46808Sdab     { "type", "Set encryptiong type. ('encrypt type ?' for more)",
1858*46808Sdab 						EncryptType, 0, 1, 1 },
1859*46808Sdab     { "start", "Start encryption. ('encrypt start ?' for more)",
1860*46808Sdab 						EncryptStart, 1, 0, 1 },
1861*46808Sdab     { "stop", "Stop encryption. ('encrypt stop ?' for more)",
1862*46808Sdab 						EncryptStop, 1, 0, 1 },
1863*46808Sdab     { "input", "Start encrypting the input stream",
1864*46808Sdab 						EncryptStartInput, 1, 0, 0 },
1865*46808Sdab     { "-input", "Stop encrypting the input stream",
1866*46808Sdab 						EncryptStopInput, 1, 0, 0 },
1867*46808Sdab     { "output", "Start encrypting the output stream",
1868*46808Sdab 						EncryptStartOutput, 1, 0, 0 },
1869*46808Sdab     { "-output", "Stop encrypting the output stream",
1870*46808Sdab 						EncryptStopOutput, 1, 0, 0 },
1871*46808Sdab 
1872*46808Sdab     { "status",	"Display current status of authentication information",
1873*46808Sdab 						EncryptStatus,	0, 0, 0 },
1874*46808Sdab     { "auto", "Toggle automatic enabling of encryption",
1875*46808Sdab 						EncryptTogAuto, 0, 0, 0 },
1876*46808Sdab     { "verbose", "Toggle verbose encryption output",
1877*46808Sdab 						EncryptTogVerbose, 0, 0, 0 },
1878*46808Sdab     { "debug",	"Toggle encryption debugging",
1879*46808Sdab 						EncryptTogDebug, 0, 0, 0 },
1880*46808Sdab     { "help",	0,				EncryptHelp,	0, 0, 0 },
1881*46808Sdab     { "?",	"Print help information",	EncryptHelp,	0, 0, 0 },
1882*46808Sdab     { 0 },
1883*46808Sdab };
1884*46808Sdab 
1885*46808Sdab     static int
1886*46808Sdab EncryptHelp()
188736274Sminshall {
1888*46808Sdab     struct encryptlist *c;
1889*46808Sdab 
1890*46808Sdab     for (c = EncryptList; c->name; c++) {
1891*46808Sdab 	if (c->help) {
1892*46808Sdab 	    if (*c->help)
1893*46808Sdab 		printf("%-15s %s\n", c->name, c->help);
1894*46808Sdab 	    else
1895*46808Sdab 		printf("\n");
189636274Sminshall 	}
1897*46808Sdab     }
1898*46808Sdab     return 0;
1899*46808Sdab }
190036274Sminshall 
1901*46808Sdab encrypt_cmd(argc, argv)
1902*46808Sdab     int  argc;
1903*46808Sdab     char *argv[];
1904*46808Sdab {
1905*46808Sdab     struct encryptlist *c;
190636274Sminshall 
1907*46808Sdab     c = (struct encryptlist *)
1908*46808Sdab 		genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
1909*46808Sdab     if (c == 0) {
1910*46808Sdab         fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
1911*46808Sdab     				argv[1]);
1912*46808Sdab         return 0;
1913*46808Sdab     }
1914*46808Sdab     if (Ambiguous(c)) {
1915*46808Sdab         fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
1916*46808Sdab     				argv[1]);
1917*46808Sdab         return 0;
1918*46808Sdab     }
1919*46808Sdab     argc -= 2;
1920*46808Sdab     if (argc < c->minarg || argc > c->maxarg) {
1921*46808Sdab 	if (c->minarg == c->maxarg) {
1922*46808Sdab 	    fprintf(stderr, "Need %s%d argument%s ",
1923*46808Sdab 		c->minarg < argc ? "only " : "", c->minarg,
1924*46808Sdab 		c->minarg == 1 ? "" : "s");
1925*46808Sdab 	} else {
1926*46808Sdab 	    fprintf(stderr, "Need %s%d-%d arguments ",
1927*46808Sdab 		c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
1928*46808Sdab 	}
1929*46808Sdab 	fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
1930*46808Sdab 		c->name);
1931*46808Sdab 	return 0;
1932*46808Sdab     }
1933*46808Sdab     if (c->needconnect && !connected) {
1934*46808Sdab 	if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
1935*46808Sdab 	    printf("?Need to be connected first.\n");
1936*46808Sdab 	    return 0;
1937*46808Sdab 	}
1938*46808Sdab     }
1939*46808Sdab     return ((*c->handler)(argc > 0 ? argv[2] : 0,
1940*46808Sdab 			argc > 1 ? argv[3] : 0,
1941*46808Sdab 			argc > 2 ? argv[4] : 0));
1942*46808Sdab }
194336274Sminshall #endif
194436274Sminshall 
1945*46808Sdab #if	defined(unix) && defined(TN3270)
1946*46808Sdab     static void
194736274Sminshall filestuff(fd)
1948*46808Sdab     int fd;
194936274Sminshall {
195036274Sminshall     int res;
195136274Sminshall 
195238689Sborman #ifdef	F_GETOWN
195338689Sborman     setconnmode(0);
195436274Sminshall     res = fcntl(fd, F_GETOWN, 0);
195536274Sminshall     setcommandmode();
195636274Sminshall 
195736274Sminshall     if (res == -1) {
195836274Sminshall 	perror("fcntl");
195936274Sminshall 	return;
196036274Sminshall     }
196136274Sminshall     printf("\tOwner is %d.\n", res);
196238689Sborman #endif
196336274Sminshall 
196438689Sborman     setconnmode(0);
196536274Sminshall     res = fcntl(fd, F_GETFL, 0);
196636274Sminshall     setcommandmode();
196736274Sminshall 
196836274Sminshall     if (res == -1) {
196936274Sminshall 	perror("fcntl");
197036274Sminshall 	return;
197136274Sminshall     }
197236274Sminshall     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
197336274Sminshall }
1974*46808Sdab #endif /* defined(unix) && defined(TN3270) */
197536274Sminshall 
197636274Sminshall /*
197732144Sminshall  * Print status about the connection.
197832144Sminshall  */
1979*46808Sdab     /*ARGSUSED*/
1980*46808Sdab     static
198132144Sminshall status(argc, argv)
1982*46808Sdab     int	 argc;
1983*46808Sdab     char *argv[];
198432144Sminshall {
198532144Sminshall     if (connected) {
198632144Sminshall 	printf("Connected to %s.\n", hostname);
198736242Sminshall 	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
198838689Sborman 	    int mode = getconnmode();
198938689Sborman 
199038689Sborman 	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
199138689Sborman 		printf("Operating with LINEMODE option\n");
199238689Sborman 		printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
199338689Sborman 		printf("%s catching of signals\n",
199438689Sborman 					(mode&MODE_TRAPSIG) ? "Local" : "No");
199538689Sborman 		slcstate();
199638689Sborman #ifdef	KLUDGELINEMODE
199739529Sborman 	    } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
199838689Sborman 		printf("Operating in obsolete linemode\n");
199938689Sborman #endif
200038689Sborman 	    } else {
200138689Sborman 		printf("Operating in single character mode\n");
200238689Sborman 		if (localchars)
200338689Sborman 		    printf("Catching signals locally\n");
200432144Sminshall 	    }
200538689Sborman 	    printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
200638689Sborman 	    if (my_want_state_is_will(TELOPT_LFLOW))
200738689Sborman 		printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
2008*46808Sdab #if	defined(ENCRYPT)
2009*46808Sdab 	    encrypt_display();
2010*46808Sdab #endif
201132144Sminshall 	}
201232144Sminshall     } else {
201332144Sminshall 	printf("No connection.\n");
201432144Sminshall     }
201532144Sminshall #   if !defined(TN3270)
201632144Sminshall     printf("Escape character is '%s'.\n", control(escape));
201734849Sminshall     (void) fflush(stdout);
201832144Sminshall #   else /* !defined(TN3270) */
201932144Sminshall     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
202032144Sminshall 	printf("Escape character is '%s'.\n", control(escape));
202132144Sminshall     }
202232144Sminshall #   if defined(unix)
202336242Sminshall     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
202436242Sminshall 	printf("SIGIO received %d time%s.\n",
202536242Sminshall 				sigiocount, (sigiocount == 1)? "":"s");
202636274Sminshall 	if (In3270) {
202736274Sminshall 	    printf("Process ID %d, process group %d.\n",
202836274Sminshall 					    getpid(), getpgrp(getpid()));
202936274Sminshall 	    printf("Terminal input:\n");
203036274Sminshall 	    filestuff(tin);
203136274Sminshall 	    printf("Terminal output:\n");
203236274Sminshall 	    filestuff(tout);
203336274Sminshall 	    printf("Network socket:\n");
203436274Sminshall 	    filestuff(net);
203536274Sminshall 	}
203636242Sminshall     }
203732144Sminshall     if (In3270 && transcom) {
203832144Sminshall        printf("Transparent mode command is '%s'.\n", transcom);
203932144Sminshall     }
204032144Sminshall #   endif /* defined(unix) */
204134849Sminshall     (void) fflush(stdout);
204232144Sminshall     if (In3270) {
204332144Sminshall 	return 0;
204432144Sminshall     }
204532144Sminshall #   endif /* defined(TN3270) */
204632144Sminshall     return 1;
204732144Sminshall }
204832144Sminshall 
204945233Sborman #ifdef	SIGINFO
205045233Sborman /*
205145233Sborman  * Function that gets called when SIGINFO is received.
205245233Sborman  */
205345233Sborman ayt_status()
205445233Sborman {
205545233Sborman     (void) call(status, "status", "notmuch", 0);
205645233Sborman }
205745233Sborman #endif
205832144Sminshall 
2059*46808Sdab     int
206032144Sminshall tn(argc, argv)
2061*46808Sdab     int argc;
2062*46808Sdab     char *argv[];
206332144Sminshall {
206432144Sminshall     register struct hostent *host = 0;
206532144Sminshall     struct sockaddr_in sin;
206632144Sminshall     struct servent *sp = 0;
206738689Sborman     unsigned long temp, inet_addr();
206837219Sminshall     extern char *inet_ntoa();
2069*46808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
207038689Sborman     char *srp = 0, *strrchr();
207138689Sborman     unsigned long sourceroute(), srlen;
207238689Sborman #endif
207344361Sborman     char *cmd, *hostp = 0, *portp = 0, *user = 0;
207432144Sminshall 
207545233Sborman     /* clear the socket address prior to use */
207645233Sborman     bzero((char *)&sin, sizeof(sin));
207732144Sminshall 
207832144Sminshall     if (connected) {
207932144Sminshall 	printf("?Already connected to %s\n", hostname);
2080*46808Sdab 	setuid(getuid());
208132144Sminshall 	return 0;
208232144Sminshall     }
208332144Sminshall     if (argc < 2) {
2084*46808Sdab 	(void) strcpy(line, "open ");
208532144Sminshall 	printf("(to) ");
2086*46808Sdab 	(void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
208732144Sminshall 	makeargv();
208832144Sminshall 	argc = margc;
208932144Sminshall 	argv = margv;
209032144Sminshall     }
209144361Sborman     cmd = *argv;
209244361Sborman     --argc; ++argv;
209344361Sborman     while (argc) {
2094*46808Sdab 	if (isprefix(*argv, "help") || isprefix(*argv, "?"))
2095*46808Sdab 	    goto usage;
209644361Sborman 	if (strcmp(*argv, "-l") == 0) {
209744361Sborman 	    --argc; ++argv;
209844361Sborman 	    if (argc == 0)
209944361Sborman 		goto usage;
210044361Sborman 	    user = *argv++;
210144361Sborman 	    --argc;
210244361Sborman 	    continue;
210344361Sborman 	}
210445233Sborman 	if (strcmp(*argv, "-a") == 0) {
210545233Sborman 	    --argc; ++argv;
210645233Sborman 	    autologin = 1;
210745233Sborman 	    continue;
210845233Sborman 	}
210944361Sborman 	if (hostp == 0) {
211044361Sborman 	    hostp = *argv++;
211144361Sborman 	    --argc;
211244361Sborman 	    continue;
211344361Sborman 	}
211444361Sborman 	if (portp == 0) {
211544361Sborman 	    portp = *argv++;
211644361Sborman 	    --argc;
211744361Sborman 	    continue;
211844361Sborman 	}
211944361Sborman     usage:
212045233Sborman 	printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
2121*46808Sdab 	setuid(getuid());
212232144Sminshall 	return 0;
212332144Sminshall     }
2124*46808Sdab     if (hostp == 0)
2125*46808Sdab 	goto usage;
2126*46808Sdab 
2127*46808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
212844361Sborman     if (hostp[0] == '@' || hostp[0] == '!') {
212944361Sborman 	if ((hostname = strrchr(hostp, ':')) == NULL)
213044361Sborman 	    hostname = strrchr(hostp, '@');
213138689Sborman 	hostname++;
213238689Sborman 	srp = 0;
213344361Sborman 	temp = sourceroute(hostp, &srp, &srlen);
213438689Sborman 	if (temp == 0) {
213538689Sborman 	    herror(srp);
2136*46808Sdab 	    setuid(getuid());
213738689Sborman 	    return 0;
213838689Sborman 	} else if (temp == -1) {
213944361Sborman 	    printf("Bad source route option: %s\n", hostp);
2140*46808Sdab 	    setuid(getuid());
214138689Sborman 	    return 0;
214238689Sborman 	} else {
214338689Sborman 	    sin.sin_addr.s_addr = temp;
214438689Sborman 	    sin.sin_family = AF_INET;
214538689Sborman 	}
214632144Sminshall     } else {
214738689Sborman #endif
214844361Sborman 	temp = inet_addr(hostp);
214938689Sborman 	if (temp != (unsigned long) -1) {
215038689Sborman 	    sin.sin_addr.s_addr = temp;
215138689Sborman 	    sin.sin_family = AF_INET;
2152*46808Sdab 	    (void) strcpy(_hostname, hostp);
2153*46808Sdab 	    hostname = _hostname;
215438689Sborman 	} else {
215544361Sborman 	    host = gethostbyname(hostp);
215638689Sborman 	    if (host) {
215738689Sborman 		sin.sin_family = host->h_addrtype;
215832144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
215938689Sborman 		memcpy((caddr_t)&sin.sin_addr,
216032144Sminshall 				host->h_addr_list[0], host->h_length);
216132144Sminshall #else	/* defined(h_addr) */
216238689Sborman 		memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
216332144Sminshall #endif	/* defined(h_addr) */
2164*46808Sdab 		strncpy(_hostname, host->h_name, sizeof(_hostname));
2165*46808Sdab 		_hostname[sizeof(_hostname)-1] = '\0';
2166*46808Sdab 		hostname = _hostname;
216738689Sborman 	    } else {
216844361Sborman 		herror(hostp);
2169*46808Sdab 	        setuid(getuid());
217038689Sborman 		return 0;
217138689Sborman 	    }
217232144Sminshall 	}
2173*46808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
217432144Sminshall     }
217538689Sborman #endif
217644361Sborman     if (portp) {
217744361Sborman 	if (*portp == '-') {
217844361Sborman 	    portp++;
217938689Sborman 	    telnetport = 1;
218038689Sborman 	} else
218138689Sborman 	    telnetport = 0;
218244361Sborman 	sin.sin_port = atoi(portp);
218332144Sminshall 	if (sin.sin_port == 0) {
218444361Sborman 	    sp = getservbyname(portp, "tcp");
218532144Sminshall 	    if (sp)
218632144Sminshall 		sin.sin_port = sp->s_port;
218732144Sminshall 	    else {
218844361Sborman 		printf("%s: bad port number\n", portp);
2189*46808Sdab 	        setuid(getuid());
219032144Sminshall 		return 0;
219132144Sminshall 	    }
219232144Sminshall 	} else {
219334849Sminshall #if	!defined(htons)
219434849Sminshall 	    u_short htons();
219534849Sminshall #endif	/* !defined(htons) */
219632144Sminshall 	    sin.sin_port = htons(sin.sin_port);
219732144Sminshall 	}
219832144Sminshall     } else {
219932144Sminshall 	if (sp == 0) {
220032144Sminshall 	    sp = getservbyname("telnet", "tcp");
220132144Sminshall 	    if (sp == 0) {
220234849Sminshall 		fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
2203*46808Sdab 	        setuid(getuid());
220432144Sminshall 		return 0;
220532144Sminshall 	    }
220632144Sminshall 	    sin.sin_port = sp->s_port;
220732144Sminshall 	}
220832144Sminshall 	telnetport = 1;
220932144Sminshall     }
221037219Sminshall     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
221132144Sminshall     do {
221232144Sminshall 	net = socket(AF_INET, SOCK_STREAM, 0);
2213*46808Sdab 	setuid(getuid());
221432144Sminshall 	if (net < 0) {
221532144Sminshall 	    perror("telnet: socket");
221632144Sminshall 	    return 0;
221732144Sminshall 	}
2218*46808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
221938689Sborman 	if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
222038689Sborman 		perror("setsockopt (IP_OPTIONS)");
222138689Sborman #endif
2222*46808Sdab #if	defined(IPPROTO_IP) && defined(IP_TOS)
2223*46808Sdab 	{
2224*46808Sdab 	    int tos = 020; /* Low Delay bit */
2225*46808Sdab # if	defined(HAS_GETTOS)
2226*46808Sdab 	    struct tosent *tp;
2227*46808Sdab 	    if (tp = gettosbyname("telnet", "tcp"))
2228*46808Sdab 		tos = tp->t_tos;
2229*46808Sdab # endif
2230*46808Sdab 	    (void)setsockopt(net, IPPROTO_IP, IP_TOS, &tos, sizeof(int));
2231*46808Sdab 	}
2232*46808Sdab #endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
223340245Sborman 
223432144Sminshall 	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
223532144Sminshall 		perror("setsockopt (SO_DEBUG)");
223632144Sminshall 	}
223732144Sminshall 
223832144Sminshall 	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
223932144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
224032144Sminshall 	    if (host && host->h_addr_list[1]) {
224132144Sminshall 		int oerrno = errno;
224232144Sminshall 
224332144Sminshall 		fprintf(stderr, "telnet: connect to address %s: ",
224432144Sminshall 						inet_ntoa(sin.sin_addr));
224532144Sminshall 		errno = oerrno;
224632144Sminshall 		perror((char *)0);
224732144Sminshall 		host->h_addr_list++;
224832144Sminshall 		memcpy((caddr_t)&sin.sin_addr,
224932144Sminshall 			host->h_addr_list[0], host->h_length);
225032144Sminshall 		(void) NetClose(net);
225132144Sminshall 		continue;
225232144Sminshall 	    }
225332144Sminshall #endif	/* defined(h_addr) */
225432144Sminshall 	    perror("telnet: Unable to connect to remote host");
225532144Sminshall 	    return 0;
225637219Sminshall 	}
225732144Sminshall 	connected++;
2258*46808Sdab #if	defined(AUTHENTICATE) || defined(ENCRYPT)
2259*46808Sdab 	auth_encrypt_connect(connected);
2260*46808Sdab #endif
226132144Sminshall     } while (connected == 0);
226244361Sborman     cmdrc(hostp, hostname);
226345008Skarels     if (autologin && user == NULL) {
226445008Skarels 	struct passwd *pw;
226545008Skarels 
226645233Sborman 	user = getenv("USER");
226745008Skarels 	if (user == NULL ||
226845233Sborman 	    (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
226945233Sborman 		if (pw = getpwuid(getuid()))
227045008Skarels 			user = pw->pw_name;
227145008Skarels 		else
227245008Skarels 			user = NULL;
227345233Sborman 	}
227445008Skarels     }
227545008Skarels     if (user) {
2276*46808Sdab 	env_define((unsigned char *)"USER", (unsigned char *)user);
2277*46808Sdab 	env_export((unsigned char *)"USER");
227845008Skarels     }
227934849Sminshall     (void) call(status, "status", "notmuch", 0);
228032144Sminshall     if (setjmp(peerdied) == 0)
2281*46808Sdab 	telnet(user);
228234849Sminshall     (void) NetClose(net);
228332381Sminshall     ExitString("Connection closed by foreign host.\n",1);
228432144Sminshall     /*NOTREACHED*/
228532144Sminshall }
228632144Sminshall 
228732144Sminshall #define HELPINDENT (sizeof ("connect"))
228832144Sminshall 
228932144Sminshall static char
229032144Sminshall 	openhelp[] =	"connect to a site",
229132144Sminshall 	closehelp[] =	"close current connection",
2292*46808Sdab 	logouthelp[] =	"forcibly logout remote user and close the connection",
229332144Sminshall 	quithelp[] =	"exit telnet",
229432144Sminshall 	statushelp[] =	"print status information",
229532144Sminshall 	helphelp[] =	"print help information",
229632144Sminshall 	sendhelp[] =	"transmit special characters ('send ?' for more)",
229732144Sminshall 	sethelp[] = 	"set operating parameters ('set ?' for more)",
229838689Sborman 	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
229932144Sminshall 	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
230038689Sborman 	slchelp[] =	"change state of special charaters ('slc ?' for more)",
230132144Sminshall 	displayhelp[] =	"display operating parameters",
230232144Sminshall #if	defined(TN3270) && defined(unix)
230332144Sminshall 	transcomhelp[] = "specify Unix command for transparent mode pipe",
230432144Sminshall #endif	/* defined(TN3270) && defined(unix) */
2305*46808Sdab #if	defined(AUTHENTICATE)
2306*46808Sdab 	authhelp[] =	"turn on (off) authentication ('auth ?' for more)",
2307*46808Sdab #endif
2308*46808Sdab #if	defined(ENCRYPT)
2309*46808Sdab 	encrypthelp[] =	"turn on (off) encryption ('encrypt ?' for more)",
2310*46808Sdab #endif
231132144Sminshall #if	defined(unix)
231232144Sminshall 	zhelp[] =	"suspend telnet",
231343317Skfall #endif	/* defined(unix) */
231432144Sminshall 	shellhelp[] =	"invoke a subshell",
231544361Sborman 	envhelp[] =	"change environment variables ('environ ?' for more)",
231644361Sborman 	modestring[] = "try to enter line or character mode ('mode ?' for more)";
231732144Sminshall 
2318*46808Sdab extern int	help();
231932144Sminshall 
232032144Sminshall static Command cmdtab[] = {
232138689Sborman 	{ "close",	closehelp,	bye,		1 },
2322*46808Sdab 	{ "logout",	logouthelp,	logout,		1 },
232338689Sborman 	{ "display",	displayhelp,	display,	0 },
232438689Sborman 	{ "mode",	modestring,	modecmd,	0 },
232538689Sborman 	{ "open",	openhelp,	tn,		0 },
232638689Sborman 	{ "quit",	quithelp,	quit,		0 },
232738689Sborman 	{ "send",	sendhelp,	sendcmd,	0 },
232838689Sborman 	{ "set",	sethelp,	setcmd,		0 },
232938689Sborman 	{ "unset",	unsethelp,	unsetcmd,	0 },
233038689Sborman 	{ "status",	statushelp,	status,		0 },
233138689Sborman 	{ "toggle",	togglestring,	toggle,		0 },
233238689Sborman 	{ "slc",	slchelp,	slccmd,		0 },
233332144Sminshall #if	defined(TN3270) && defined(unix)
233438689Sborman 	{ "transcom",	transcomhelp,	settranscom,	0 },
233532144Sminshall #endif	/* defined(TN3270) && defined(unix) */
2336*46808Sdab #if	defined(AUTHENTICATE)
2337*46808Sdab 	{ "auth",	authhelp,	auth_cmd,	0 },
2338*46808Sdab #endif
2339*46808Sdab #if	defined(ENCRYPT)
2340*46808Sdab 	{ "encrypt",	encrypthelp,	encrypt_cmd,	0 },
2341*46808Sdab #endif
234232144Sminshall #if	defined(unix)
234338689Sborman 	{ "z",		zhelp,		suspend,	0 },
234432144Sminshall #endif	/* defined(unix) */
234532144Sminshall #if	defined(TN3270)
234638689Sborman 	{ "!",		shellhelp,	shell,		1 },
234738689Sborman #else
234838689Sborman 	{ "!",		shellhelp,	shell,		0 },
234938689Sborman #endif
235044361Sborman 	{ "environ",	envhelp,	env_cmd,	0 },
235138689Sborman 	{ "?",		helphelp,	help,		0 },
235232144Sminshall 	0
235332144Sminshall };
235432144Sminshall 
235532144Sminshall static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
235632144Sminshall static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
235732144Sminshall 
235832144Sminshall static Command cmdtab2[] = {
235938689Sborman 	{ "help",	0,		help,		0 },
236038689Sborman 	{ "escape",	escapehelp,	setescape,	0 },
236138689Sborman 	{ "crmod",	crmodhelp,	togcrmod,	0 },
236232144Sminshall 	0
236332144Sminshall };
236432144Sminshall 
236535298Sminshall 
236632144Sminshall /*
236732144Sminshall  * Call routine with argc, argv set from args (terminated by 0).
236832144Sminshall  */
236935298Sminshall 
2370*46808Sdab     /*VARARGS1*/
2371*46808Sdab     static
237235298Sminshall call(va_alist)
2373*46808Sdab     va_dcl
237432144Sminshall {
237535298Sminshall     va_list ap;
237635298Sminshall     typedef int (*intrtn_t)();
237735298Sminshall     intrtn_t routine;
237835298Sminshall     char *args[100];
237935298Sminshall     int argno = 0;
238035298Sminshall 
238135298Sminshall     va_start(ap);
238235298Sminshall     routine = (va_arg(ap, intrtn_t));
238335495Sminshall     while ((args[argno++] = va_arg(ap, char *)) != 0) {
238435298Sminshall 	;
238535495Sminshall     }
238635298Sminshall     va_end(ap);
238735495Sminshall     return (*routine)(argno-1, args);
238832144Sminshall }
238932144Sminshall 
239035298Sminshall 
2391*46808Sdab     static Command *
239232144Sminshall getcmd(name)
2393*46808Sdab     char *name;
239432144Sminshall {
239532144Sminshall     Command *cm;
239632144Sminshall 
2397*46808Sdab     if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))
239832144Sminshall 	return cm;
2399*46808Sdab     return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
240032144Sminshall }
240132144Sminshall 
2402*46808Sdab     void
240338689Sborman command(top, tbuf, cnt)
2404*46808Sdab     int top;
2405*46808Sdab     char *tbuf;
2406*46808Sdab     int cnt;
240732144Sminshall {
240832144Sminshall     register Command *c;
240932144Sminshall 
241032144Sminshall     setcommandmode();
241132144Sminshall     if (!top) {
241232144Sminshall 	putchar('\n');
241337219Sminshall #if	defined(unix)
241432144Sminshall     } else {
241544361Sborman 	(void) signal(SIGINT, SIG_DFL);
241644361Sborman 	(void) signal(SIGQUIT, SIG_DFL);
241732144Sminshall #endif	/* defined(unix) */
241832144Sminshall     }
241932144Sminshall     for (;;) {
2420*46808Sdab 	if (rlogin == _POSIX_VDISABLE)
2421*46808Sdab 		printf("%s> ", prompt);
242238689Sborman 	if (tbuf) {
242338689Sborman 	    register char *cp;
242438689Sborman 	    cp = line;
242538689Sborman 	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
242638689Sborman 		cnt--;
242738689Sborman 	    tbuf = 0;
242838689Sborman 	    if (cp == line || *--cp != '\n' || cp == line)
242938689Sborman 		goto getline;
243038689Sborman 	    *cp = '\0';
2431*46808Sdab 	    if (rlogin == _POSIX_VDISABLE)
2432*46808Sdab 	        printf("%s\n", line);
243338689Sborman 	} else {
243438689Sborman 	getline:
2435*46808Sdab 	    if (rlogin != _POSIX_VDISABLE)
2436*46808Sdab 		printf("%s> ", prompt);
2437*46808Sdab 	    if (fgets(line, sizeof(line), stdin) == NULL) {
243844361Sborman 		if (feof(stdin) || ferror(stdin)) {
243944361Sborman 		    (void) quit();
244044361Sborman 		    /*NOTREACHED*/
244144361Sborman 		}
244238689Sborman 		break;
244338689Sborman 	    }
244432144Sminshall 	}
244532144Sminshall 	if (line[0] == 0)
244632144Sminshall 	    break;
244732144Sminshall 	makeargv();
244837219Sminshall 	if (margv[0] == 0) {
244937219Sminshall 	    break;
245037219Sminshall 	}
245132144Sminshall 	c = getcmd(margv[0]);
245232144Sminshall 	if (Ambiguous(c)) {
245332144Sminshall 	    printf("?Ambiguous command\n");
245432144Sminshall 	    continue;
245532144Sminshall 	}
245632144Sminshall 	if (c == 0) {
245732144Sminshall 	    printf("?Invalid command\n");
245832144Sminshall 	    continue;
245932144Sminshall 	}
246032144Sminshall 	if (c->needconnect && !connected) {
246132144Sminshall 	    printf("?Need to be connected first.\n");
246232144Sminshall 	    continue;
246332144Sminshall 	}
246432144Sminshall 	if ((*c->handler)(margc, margv)) {
246532144Sminshall 	    break;
246632144Sminshall 	}
246732144Sminshall     }
246832144Sminshall     if (!top) {
246932144Sminshall 	if (!connected) {
247032144Sminshall 	    longjmp(toplevel, 1);
247132144Sminshall 	    /*NOTREACHED*/
247232144Sminshall 	}
247332144Sminshall #if	defined(TN3270)
247432144Sminshall 	if (shell_active == 0) {
247538689Sborman 	    setconnmode(0);
247632144Sminshall 	}
247732144Sminshall #else	/* defined(TN3270) */
247838689Sborman 	setconnmode(0);
247932144Sminshall #endif	/* defined(TN3270) */
248032144Sminshall     }
248132144Sminshall }
248232144Sminshall 
248332144Sminshall /*
248432144Sminshall  * Help command.
248532144Sminshall  */
2486*46808Sdab 	static
248732144Sminshall help(argc, argv)
248832144Sminshall 	int argc;
248932144Sminshall 	char *argv[];
249032144Sminshall {
249132144Sminshall 	register Command *c;
249232144Sminshall 
249332144Sminshall 	if (argc == 1) {
249432144Sminshall 		printf("Commands may be abbreviated.  Commands are:\n\n");
249532144Sminshall 		for (c = cmdtab; c->name; c++)
249638689Sborman 			if (c->help) {
249732144Sminshall 				printf("%-*s\t%s\n", HELPINDENT, c->name,
249832144Sminshall 								    c->help);
249932144Sminshall 			}
250032144Sminshall 		return 0;
250132144Sminshall 	}
250232144Sminshall 	while (--argc > 0) {
250332144Sminshall 		register char *arg;
250432144Sminshall 		arg = *++argv;
250532144Sminshall 		c = getcmd(arg);
250632144Sminshall 		if (Ambiguous(c))
250732144Sminshall 			printf("?Ambiguous help command %s\n", arg);
250832144Sminshall 		else if (c == (Command *)0)
250932144Sminshall 			printf("?Invalid help command %s\n", arg);
251032144Sminshall 		else
251132144Sminshall 			printf("%s\n", c->help);
251232144Sminshall 	}
251332144Sminshall 	return 0;
251432144Sminshall }
251538689Sborman 
251638689Sborman static char *rcname = 0;
251738689Sborman static char rcbuf[128];
251838689Sborman 
251938689Sborman cmdrc(m1, m2)
252038689Sborman 	char *m1, *m2;
252138689Sborman {
252238689Sborman     register Command *c;
252338689Sborman     FILE *rcfile;
252438689Sborman     int gotmachine = 0;
252538689Sborman     int l1 = strlen(m1);
252638689Sborman     int l2 = strlen(m2);
252738689Sborman     char m1save[64];
252838689Sborman 
252938689Sborman     strcpy(m1save, m1);
253038689Sborman     m1 = m1save;
253138689Sborman 
253238689Sborman     if (rcname == 0) {
253338689Sborman 	rcname = getenv("HOME");
253438689Sborman 	if (rcname)
253538689Sborman 	    strcpy(rcbuf, rcname);
253638689Sborman 	else
253738689Sborman 	    rcbuf[0] = '\0';
253838689Sborman 	strcat(rcbuf, "/.telnetrc");
253938689Sborman 	rcname = rcbuf;
254038689Sborman     }
254138689Sborman 
254238689Sborman     if ((rcfile = fopen(rcname, "r")) == 0) {
254338689Sborman 	return;
254438689Sborman     }
254538689Sborman 
254638689Sborman     for (;;) {
254738689Sborman 	if (fgets(line, sizeof(line), rcfile) == NULL)
254838689Sborman 	    break;
254938689Sborman 	if (line[0] == 0)
255038689Sborman 	    break;
255138689Sborman 	if (line[0] == '#')
255238689Sborman 	    continue;
255338689Sborman 	if (gotmachine == 0) {
255438689Sborman 	    if (isspace(line[0]))
255538689Sborman 		continue;
255638689Sborman 	    if (strncasecmp(line, m1, l1) == 0)
255738689Sborman 		strncpy(line, &line[l1], sizeof(line) - l1);
255838689Sborman 	    else if (strncasecmp(line, m2, l2) == 0)
255938689Sborman 		strncpy(line, &line[l2], sizeof(line) - l2);
256038689Sborman 	    else
256138689Sborman 		continue;
256238689Sborman 	    gotmachine = 1;
256338689Sborman 	} else {
256438689Sborman 	    if (!isspace(line[0])) {
256538689Sborman 		gotmachine = 0;
256638689Sborman 		continue;
256738689Sborman 	    }
256838689Sborman 	}
256938689Sborman 	makeargv();
257038689Sborman 	if (margv[0] == 0)
257138689Sborman 	    continue;
257238689Sborman 	c = getcmd(margv[0]);
257338689Sborman 	if (Ambiguous(c)) {
257438689Sborman 	    printf("?Ambiguous command: %s\n", margv[0]);
257538689Sborman 	    continue;
257638689Sborman 	}
257738689Sborman 	if (c == 0) {
257838689Sborman 	    printf("?Invalid command: %s\n", margv[0]);
257938689Sborman 	    continue;
258038689Sborman 	}
258138689Sborman 	/*
258238689Sborman 	 * This should never happen...
258338689Sborman 	 */
258438689Sborman 	if (c->needconnect && !connected) {
258538689Sborman 	    printf("?Need to be connected first for %s.\n", margv[0]);
258638689Sborman 	    continue;
258738689Sborman 	}
258838689Sborman 	(*c->handler)(margc, margv);
258938689Sborman     }
259038689Sborman     fclose(rcfile);
259138689Sborman }
259238689Sborman 
2593*46808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
259438689Sborman 
259538689Sborman /*
259638689Sborman  * Source route is handed in as
259738689Sborman  *	[!]@hop1@hop2...[@|:]dst
259838689Sborman  * If the leading ! is present, it is a
259938689Sborman  * strict source route, otherwise it is
260038689Sborman  * assmed to be a loose source route.
260138689Sborman  *
260238689Sborman  * We fill in the source route option as
260338689Sborman  *	hop1,hop2,hop3...dest
260438689Sborman  * and return a pointer to hop1, which will
260538689Sborman  * be the address to connect() to.
260638689Sborman  *
260738689Sborman  * Arguments:
260838689Sborman  *	arg:	pointer to route list to decipher
260938689Sborman  *
261038689Sborman  *	cpp: 	If *cpp is not equal to NULL, this is a
261138689Sborman  *		pointer to a pointer to a character array
261238689Sborman  *		that should be filled in with the option.
261338689Sborman  *
261438689Sborman  *	lenp:	pointer to an integer that contains the
261538689Sborman  *		length of *cpp if *cpp != NULL.
261638689Sborman  *
261738689Sborman  * Return values:
261838689Sborman  *
261938689Sborman  *	Returns the address of the host to connect to.  If the
262038689Sborman  *	return value is -1, there was a syntax error in the
262138689Sborman  *	option, either unknown characters, or too many hosts.
262238689Sborman  *	If the return value is 0, one of the hostnames in the
262338689Sborman  *	path is unknown, and *cpp is set to point to the bad
262438689Sborman  *	hostname.
262538689Sborman  *
262638689Sborman  *	*cpp:	If *cpp was equal to NULL, it will be filled
262738689Sborman  *		in with a pointer to our static area that has
262838689Sborman  *		the option filled in.  This will be 32bit aligned.
262938689Sborman  *
263038689Sborman  *	*lenp:	This will be filled in with how long the option
263138689Sborman  *		pointed to by *cpp is.
263238689Sborman  *
263338689Sborman  */
2634*46808Sdab 	unsigned long
263538689Sborman sourceroute(arg, cpp, lenp)
2636*46808Sdab 	char	*arg;
2637*46808Sdab 	char	**cpp;
2638*46808Sdab 	int	*lenp;
263938689Sborman {
264038689Sborman 	static char lsr[44];
2641*46808Sdab 	char *cp, *cp2, *lsrp, *lsrep;
264238689Sborman 	register int tmp;
264338689Sborman 	struct in_addr sin_addr;
264438689Sborman 	register struct hostent *host = 0;
264538689Sborman 	register char c;
264638689Sborman 
264738689Sborman 	/*
264838689Sborman 	 * Verify the arguments, and make sure we have
264938689Sborman 	 * at least 7 bytes for the option.
265038689Sborman 	 */
265138689Sborman 	if (cpp == NULL || lenp == NULL)
265238689Sborman 		return((unsigned long)-1);
265338689Sborman 	if (*cpp != NULL && *lenp < 7)
265438689Sborman 		return((unsigned long)-1);
265538689Sborman 	/*
265638689Sborman 	 * Decide whether we have a buffer passed to us,
265738689Sborman 	 * or if we need to use our own static buffer.
265838689Sborman 	 */
265938689Sborman 	if (*cpp) {
266038689Sborman 		lsrp = *cpp;
266138689Sborman 		lsrep = lsrp + *lenp;
266238689Sborman 	} else {
266338689Sborman 		*cpp = lsrp = lsr;
266438689Sborman 		lsrep = lsrp + 44;
266538689Sborman 	}
266638689Sborman 
266738689Sborman 	cp = arg;
266838689Sborman 
266938689Sborman 	/*
267038689Sborman 	 * Next, decide whether we have a loose source
267138689Sborman 	 * route or a strict source route, and fill in
267238689Sborman 	 * the begining of the option.
267338689Sborman 	 */
267438689Sborman 	if (*cp == '!') {
267538689Sborman 		cp++;
267638689Sborman 		*lsrp++ = IPOPT_SSRR;
267738689Sborman 	} else
267838689Sborman 		*lsrp++ = IPOPT_LSRR;
267938689Sborman 
268038689Sborman 	if (*cp != '@')
268138689Sborman 		return((unsigned long)-1);
268238689Sborman 
268338689Sborman 	lsrp++;		/* skip over length, we'll fill it in later */
268438689Sborman 	*lsrp++ = 4;
268538689Sborman 
268638689Sborman 	cp++;
268738689Sborman 
268838689Sborman 	sin_addr.s_addr = 0;
268938689Sborman 
269038689Sborman 	for (c = 0;;) {
269138689Sborman 		if (c == ':')
269238689Sborman 			cp2 = 0;
269338689Sborman 		else for (cp2 = cp; c = *cp2; cp2++) {
269438689Sborman 			if (c == ',') {
269538689Sborman 				*cp2++ = '\0';
269638689Sborman 				if (*cp2 == '@')
269738689Sborman 					cp2++;
269838689Sborman 			} else if (c == '@') {
269938689Sborman 				*cp2++ = '\0';
270038689Sborman 			} else if (c == ':') {
270138689Sborman 				*cp2++ = '\0';
270238689Sborman 			} else
270338689Sborman 				continue;
270438689Sborman 			break;
270538689Sborman 		}
270638689Sborman 		if (!c)
270738689Sborman 			cp2 = 0;
270838689Sborman 
270938689Sborman 		if ((tmp = inet_addr(cp)) != -1) {
271038689Sborman 			sin_addr.s_addr = tmp;
271138689Sborman 		} else if (host = gethostbyname(cp)) {
271238689Sborman #if	defined(h_addr)
271338689Sborman 			memcpy((caddr_t)&sin_addr,
271438689Sborman 				host->h_addr_list[0], host->h_length);
271538689Sborman #else
271638689Sborman 			memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
271738689Sborman #endif
271838689Sborman 		} else {
271938689Sborman 			*cpp = cp;
272038689Sborman 			return(0);
272138689Sborman 		}
272238689Sborman 		memcpy(lsrp, (char *)&sin_addr, 4);
272338689Sborman 		lsrp += 4;
272438689Sborman 		if (cp2)
272538689Sborman 			cp = cp2;
272638689Sborman 		else
272738689Sborman 			break;
272838689Sborman 		/*
272938689Sborman 		 * Check to make sure there is space for next address
273038689Sborman 		 */
273138689Sborman 		if (lsrp + 4 > lsrep)
273238689Sborman 			return((unsigned long)-1);
273338689Sborman 	}
273438689Sborman 	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
273538689Sborman 		*cpp = 0;
273638689Sborman 		*lenp = 0;
273738689Sborman 		return((unsigned long)-1);
273838689Sborman 	}
273938689Sborman 	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
274038689Sborman 	*lenp = lsrp - *cpp;
274138689Sborman 	return(sin_addr.s_addr);
274238689Sborman }
274338689Sborman #endif
2744