xref: /csrg-svn/usr.bin/telnet/commands.c (revision 58972)
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*58972Sdab static char sccsid[] = "@(#)commands.c	5.10 (Berkeley) 04/05/93";
1033685Sbostic #endif /* not lint */
1133685Sbostic 
1236274Sminshall #if	defined(unix)
1345241Swilliam #include <sys/param.h>
1457213Sdab #if	defined(CRAY) || defined(sysV88)
1546808Sdab #include <sys/types.h>
1646808Sdab #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
2446808Sdab #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>
3246808Sdab #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 
4457213Sdab #if !defined(CRAY) && !defined(sysV88)
4546808Sdab #include <netinet/in_systm.h>
4646808Sdab # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
4746808Sdab # include <machine/endian.h>
4846808Sdab # endif /* vax */
4957213Sdab #endif /* !defined(CRAY) && !defined(sysV88) */
5044361Sborman #include <netinet/ip.h>
5138689Sborman 
5238689Sborman 
5346808Sdab #ifndef       MAXHOSTNAMELEN
5446808Sdab #define       MAXHOSTNAMELEN 64
5546808Sdab #endif        MAXHOSTNAMELEN
5640248Sborman 
5746815Sdab #if	defined(IPPROTO_IP) && defined(IP_TOS)
5846815Sdab int tos = -1;
5946815Sdab #endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
6046815Sdab 
6132144Sminshall char	*hostname;
6246808Sdab static char _hostname[MAXHOSTNAMELEN];
6346808Sdab 
6438689Sborman extern char *getenv();
6532144Sminshall 
6646808Sdab extern int isprefix();
6746808Sdab extern char **genget();
6846808Sdab extern int Ambiguous();
6946808Sdab 
7044361Sborman static call();
7132144Sminshall 
7232144Sminshall typedef struct {
7332144Sminshall 	char	*name;		/* command name */
7438689Sborman 	char	*help;		/* help string (NULL for no help) */
7532144Sminshall 	int	(*handler)();	/* routine which executes command */
7632144Sminshall 	int	needconnect;	/* Do we need to be connected to execute? */
7732144Sminshall } Command;
7832144Sminshall 
7938689Sborman static char line[256];
8038689Sborman static char saveline[256];
8132144Sminshall static int margc;
8232144Sminshall static char *margv[20];
8332144Sminshall 
8446808Sdab     static void
8532144Sminshall makeargv()
8632144Sminshall {
8744361Sborman     register char *cp, *cp2, c;
8832144Sminshall     register char **argp = margv;
8932144Sminshall 
9032144Sminshall     margc = 0;
9132144Sminshall     cp = line;
9232144Sminshall     if (*cp == '!') {		/* Special case shell escape */
9338689Sborman 	strcpy(saveline, line);	/* save for shell command */
9432144Sminshall 	*argp++ = "!";		/* No room in string to get this */
9532144Sminshall 	margc++;
9632144Sminshall 	cp++;
9732144Sminshall     }
9844361Sborman     while (c = *cp) {
9944361Sborman 	register int inquote = 0;
10044361Sborman 	while (isspace(c))
10144361Sborman 	    c = *++cp;
10244361Sborman 	if (c == '\0')
10332144Sminshall 	    break;
10432144Sminshall 	*argp++ = cp;
10532144Sminshall 	margc += 1;
10644361Sborman 	for (cp2 = cp; c != '\0'; c = *++cp) {
10744361Sborman 	    if (inquote) {
10844361Sborman 		if (c == inquote) {
10944361Sborman 		    inquote = 0;
11044361Sborman 		    continue;
11144361Sborman 		}
11244361Sborman 	    } else {
11344361Sborman 		if (c == '\\') {
11444361Sborman 		    if ((c = *++cp) == '\0')
11544361Sborman 			break;
11644361Sborman 		} else if (c == '"') {
11744361Sborman 		    inquote = '"';
11844361Sborman 		    continue;
11944361Sborman 		} else if (c == '\'') {
12044361Sborman 		    inquote = '\'';
12144361Sborman 		    continue;
12244361Sborman 		} else if (isspace(c))
12344361Sborman 		    break;
12444361Sborman 	    }
12544361Sborman 	    *cp2++ = c;
12644361Sborman 	}
12744361Sborman 	*cp2 = '\0';
12844361Sborman 	if (c == '\0')
12932144Sminshall 	    break;
13044361Sborman 	cp++;
13132144Sminshall     }
13232144Sminshall     *argp++ = 0;
13332144Sminshall }
13432144Sminshall 
13532144Sminshall /*
13632144Sminshall  * Make a character string into a number.
13732144Sminshall  *
13832144Sminshall  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
13932144Sminshall  */
14032144Sminshall 
14146808Sdab 	static
14232144Sminshall special(s)
14346808Sdab 	register char *s;
14432144Sminshall {
14532144Sminshall 	register char c;
14632144Sminshall 	char b;
14732144Sminshall 
14832144Sminshall 	switch (*s) {
14932144Sminshall 	case '^':
15032144Sminshall 		b = *++s;
15132144Sminshall 		if (b == '?') {
15232144Sminshall 		    c = b | 0x40;		/* DEL */
15332144Sminshall 		} else {
15432144Sminshall 		    c = b & 0x1f;
15532144Sminshall 		}
15632144Sminshall 		break;
15732144Sminshall 	default:
15832144Sminshall 		c = *s;
15932144Sminshall 		break;
16032144Sminshall 	}
16132144Sminshall 	return c;
16232144Sminshall }
16332144Sminshall 
16432144Sminshall /*
16532144Sminshall  * Construct a control character sequence
16632144Sminshall  * for a special character.
16732144Sminshall  */
16846808Sdab 	static char *
16932144Sminshall control(c)
17040245Sborman 	register cc_t c;
17132144Sminshall {
17244361Sborman 	static char buf[5];
17346808Sdab 	/*
17446808Sdab 	 * The only way I could get the Sun 3.5 compiler
17546808Sdab 	 * to shut up about
17646808Sdab 	 *	if ((unsigned int)c >= 0x80)
17746808Sdab 	 * was to assign "c" to an unsigned int variable...
17846808Sdab 	 * Arggg....
17946808Sdab 	 */
18046808Sdab 	register unsigned int uic = (unsigned int)c;
18132144Sminshall 
18246808Sdab 	if (uic == 0x7f)
18332144Sminshall 		return ("^?");
18445233Sborman 	if (c == (cc_t)_POSIX_VDISABLE) {
18532144Sminshall 		return "off";
18632144Sminshall 	}
18746808Sdab 	if (uic >= 0x80) {
18844361Sborman 		buf[0] = '\\';
18944361Sborman 		buf[1] = ((c>>6)&07) + '0';
19044361Sborman 		buf[2] = ((c>>3)&07) + '0';
19144361Sborman 		buf[3] = (c&07) + '0';
19244361Sborman 		buf[4] = 0;
19346808Sdab 	} else if (uic >= 0x20) {
19432144Sminshall 		buf[0] = c;
19532144Sminshall 		buf[1] = 0;
19632144Sminshall 	} else {
19732144Sminshall 		buf[0] = '^';
19832144Sminshall 		buf[1] = '@'+c;
19932144Sminshall 		buf[2] = 0;
20032144Sminshall 	}
20132144Sminshall 	return (buf);
20232144Sminshall }
20332144Sminshall 
20432144Sminshall 
20532144Sminshall 
20632144Sminshall /*
20732144Sminshall  *	The following are data structures and routines for
20832144Sminshall  *	the "send" command.
20932144Sminshall  *
21032144Sminshall  */
21132144Sminshall 
21232144Sminshall struct sendlist {
21332144Sminshall     char	*name;		/* How user refers to it (case independent) */
21432144Sminshall     char	*help;		/* Help information (0 ==> no help) */
21546808Sdab     int		needconnect;	/* Need to be connected */
21646808Sdab     int		narg;		/* Number of arguments */
21738689Sborman     int		(*handler)();	/* Routine to perform (for special ops) */
21846808Sdab     int		nbyte;		/* Number of bytes to send this command */
21938689Sborman     int		what;		/* Character to be sent (<0 ==> special) */
22032144Sminshall };
22132144Sminshall 
22232144Sminshall 
22356642Sralph static int
22446808Sdab 	send_esc P((void)),
22546808Sdab 	send_help P((void)),
22646808Sdab 	send_docmd P((char *)),
22746808Sdab 	send_dontcmd P((char *)),
22846808Sdab 	send_willcmd P((char *)),
22946808Sdab 	send_wontcmd P((char *));
23046808Sdab 
23132144Sminshall static struct sendlist Sendlist[] = {
23246808Sdab     { "ao",	"Send Telnet Abort output",		1, 0, 0, 2, AO },
23346808Sdab     { "ayt",	"Send Telnet 'Are You There'",		1, 0, 0, 2, AYT },
23446808Sdab     { "brk",	"Send Telnet Break",			1, 0, 0, 2, BREAK },
23546808Sdab     { "break",	0,					1, 0, 0, 2, BREAK },
23646808Sdab     { "ec",	"Send Telnet Erase Character",		1, 0, 0, 2, EC },
23746808Sdab     { "el",	"Send Telnet Erase Line",		1, 0, 0, 2, EL },
23846808Sdab     { "escape",	"Send current escape character",	1, 0, send_esc, 1, 0 },
23946808Sdab     { "ga",	"Send Telnet 'Go Ahead' sequence",	1, 0, 0, 2, GA },
24046808Sdab     { "ip",	"Send Telnet Interrupt Process",	1, 0, 0, 2, IP },
24146808Sdab     { "intp",	0,					1, 0, 0, 2, IP },
24246808Sdab     { "interrupt", 0,					1, 0, 0, 2, IP },
24346808Sdab     { "intr",	0,					1, 0, 0, 2, IP },
24446808Sdab     { "nop",	"Send Telnet 'No operation'",		1, 0, 0, 2, NOP },
24546808Sdab     { "eor",	"Send Telnet 'End of Record'",		1, 0, 0, 2, EOR },
24646808Sdab     { "abort",	"Send Telnet 'Abort Process'",		1, 0, 0, 2, ABORT },
24746808Sdab     { "susp",	"Send Telnet 'Suspend Process'",	1, 0, 0, 2, SUSP },
24846808Sdab     { "eof",	"Send Telnet End of File Character",	1, 0, 0, 2, xEOF },
24946808Sdab     { "synch",	"Perform Telnet 'Synch operation'",	1, 0, dosynch, 2, 0 },
25046808Sdab     { "getstatus", "Send request for STATUS",		1, 0, get_status, 6, 0 },
25146808Sdab     { "?",	"Display send options",			0, 0, send_help, 0, 0 },
25246808Sdab     { "help",	0,					0, 0, send_help, 0, 0 },
25346808Sdab     { "do",	0,					0, 1, send_docmd, 3, 0 },
25446808Sdab     { "dont",	0,					0, 1, send_dontcmd, 3, 0 },
25546808Sdab     { "will",	0,					0, 1, send_willcmd, 3, 0 },
25646808Sdab     { "wont",	0,					0, 1, send_wontcmd, 3, 0 },
25732144Sminshall     { 0 }
25832144Sminshall };
25932144Sminshall 
26046808Sdab #define	GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
26146808Sdab 				sizeof(struct sendlist)))
26232144Sminshall 
26346808Sdab     static int
26432144Sminshall sendcmd(argc, argv)
26546808Sdab     int  argc;
26646808Sdab     char **argv;
26732144Sminshall {
26832144Sminshall     int count;		/* how many bytes we are going to need to send */
26932144Sminshall     int i;
27032144Sminshall     int question = 0;	/* was at least one argument a question */
27132144Sminshall     struct sendlist *s;	/* pointer to current command */
27246808Sdab     int success = 0;
27346808Sdab     int needconnect = 0;
27432144Sminshall 
27532144Sminshall     if (argc < 2) {
27632144Sminshall 	printf("need at least one argument for 'send' command\n");
27732144Sminshall 	printf("'send ?' for help\n");
27832144Sminshall 	return 0;
27932144Sminshall     }
28032144Sminshall     /*
28132144Sminshall      * First, validate all the send arguments.
28232144Sminshall      * In addition, we see how much space we are going to need, and
28332144Sminshall      * whether or not we will be doing a "SYNCH" operation (which
28432144Sminshall      * flushes the network queue).
28532144Sminshall      */
28632144Sminshall     count = 0;
28732144Sminshall     for (i = 1; i < argc; i++) {
28846808Sdab 	s = GETSEND(argv[i]);
28932144Sminshall 	if (s == 0) {
29032144Sminshall 	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
29132144Sminshall 			argv[i]);
29232144Sminshall 	    return 0;
29332144Sminshall 	} else if (Ambiguous(s)) {
29432144Sminshall 	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
29532144Sminshall 			argv[i]);
29632144Sminshall 	    return 0;
29732144Sminshall 	}
29846808Sdab 	if (i + s->narg >= argc) {
29946808Sdab 	    fprintf(stderr,
30046808Sdab 	    "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
30146808Sdab 		s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
30246808Sdab 	    return 0;
30332144Sminshall 	}
30446808Sdab 	count += s->nbyte;
30546808Sdab 	if (s->handler == send_help) {
30646808Sdab 	    send_help();
30746808Sdab 	    return 0;
30846808Sdab 	}
30946808Sdab 
31046808Sdab 	i += s->narg;
31146808Sdab 	needconnect += s->needconnect;
31232144Sminshall     }
31346808Sdab     if (!connected && needconnect) {
31446808Sdab 	printf("?Need to be connected first.\n");
31546808Sdab 	printf("'send ?' for help\n");
31646808Sdab 	return 0;
31738689Sborman     }
31832144Sminshall     /* Now, do we have enough room? */
31932144Sminshall     if (NETROOM() < count) {
32032144Sminshall 	printf("There is not enough room in the buffer TO the network\n");
32132144Sminshall 	printf("to process your request.  Nothing will be done.\n");
32232144Sminshall 	printf("('send synch' will throw away most data in the network\n");
32332144Sminshall 	printf("buffer, if this might help.)\n");
32432144Sminshall 	return 0;
32532144Sminshall     }
32632144Sminshall     /* OK, they are all OK, now go through again and actually send */
32746808Sdab     count = 0;
32832144Sminshall     for (i = 1; i < argc; i++) {
32946808Sdab 	if ((s = GETSEND(argv[i])) == 0) {
33032144Sminshall 	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
33144361Sborman 	    (void) quit();
33232144Sminshall 	    /*NOTREACHED*/
33332144Sminshall 	}
33438689Sborman 	if (s->handler) {
33546808Sdab 	    count++;
33646808Sdab 	    success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
33746808Sdab 				  (s->narg > 1) ? argv[i+2] : 0);
33846808Sdab 	    i += s->narg;
33932144Sminshall 	} else {
34056859Storek 	    NET2ADD(IAC, s->what);
34156859Storek 	    printoption("SENT", IAC, s->what);
34246808Sdab 	}
34346808Sdab     }
34446808Sdab     return (count == success);
34546808Sdab }
34646808Sdab 
34746808Sdab     static int
34846808Sdab send_esc()
34946808Sdab {
35046808Sdab     NETADD(escape);
35146808Sdab     return 1;
35246808Sdab }
35346808Sdab 
35446808Sdab     static int
35546808Sdab send_docmd(name)
35646808Sdab     char *name;
35746808Sdab {
35846808Sdab     return(send_tncmd(send_do, "do", name));
35946808Sdab }
36046808Sdab 
36146808Sdab     static int
36246808Sdab send_dontcmd(name)
36346808Sdab     char *name;
36446808Sdab {
36546808Sdab     return(send_tncmd(send_dont, "dont", name));
36646808Sdab }
36746808Sdab     static int
36846808Sdab send_willcmd(name)
36946808Sdab     char *name;
37046808Sdab {
37146808Sdab     return(send_tncmd(send_will, "will", name));
37246808Sdab }
37346808Sdab     static int
37446808Sdab send_wontcmd(name)
37546808Sdab     char *name;
37646808Sdab {
37746808Sdab     return(send_tncmd(send_wont, "wont", name));
37846808Sdab }
37946808Sdab 
38046808Sdab     int
38146808Sdab send_tncmd(func, cmd, name)
38246808Sdab     void	(*func)();
38346808Sdab     char	*cmd, *name;
38446808Sdab {
38546808Sdab     char **cpp;
38646808Sdab     extern char *telopts[];
38757213Sdab     register int val = 0;
38846808Sdab 
38946808Sdab     if (isprefix(name, "help") || isprefix(name, "?")) {
39046808Sdab 	register int col, len;
39146808Sdab 
39257213Sdab 	printf("Usage: send %s <value|option>\n", cmd);
39357213Sdab 	printf("\"value\" must be from 0 to 255\n");
39446808Sdab 	printf("Valid options are:\n\t");
39546808Sdab 
39646808Sdab 	col = 8;
39746808Sdab 	for (cpp = telopts; *cpp; cpp++) {
39857213Sdab 	    len = strlen(*cpp) + 3;
39946808Sdab 	    if (col + len > 65) {
40046808Sdab 		printf("\n\t");
40146808Sdab 		col = 8;
40232144Sminshall 	    }
40357213Sdab 	    printf(" \"%s\"", *cpp);
40446808Sdab 	    col += len;
40532144Sminshall 	}
40646808Sdab 	printf("\n");
40746808Sdab 	return 0;
40832144Sminshall     }
40946808Sdab     cpp = (char **)genget(name, telopts, sizeof(char *));
41046808Sdab     if (Ambiguous(cpp)) {
41146808Sdab 	fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
41246808Sdab 					name, cmd);
41346808Sdab 	return 0;
41446808Sdab     }
41557213Sdab     if (cpp) {
41657213Sdab 	val = cpp - telopts;
41757213Sdab     } else {
41857213Sdab 	register char *cp = name;
41957213Sdab 
42057213Sdab 	while (*cp >= '0' && *cp <= '9') {
42157213Sdab 	    val *= 10;
42257213Sdab 	    val += *cp - '0';
42357213Sdab 	    cp++;
42457213Sdab 	}
42557213Sdab 	if (*cp != 0) {
42657213Sdab 	    fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
42746808Sdab 					name, cmd);
42857213Sdab 	    return 0;
42957213Sdab 	} else if (val < 0 || val > 255) {
43057213Sdab 	    fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
43157213Sdab 					name, cmd);
43257213Sdab 	    return 0;
43357213Sdab 	}
43446808Sdab     }
43546808Sdab     if (!connected) {
43646808Sdab 	printf("?Need to be connected first.\n");
43746808Sdab 	return 0;
43846808Sdab     }
43957213Sdab     (*func)(val, 1);
44046808Sdab     return 1;
44132144Sminshall }
44246808Sdab 
44346808Sdab     static int
44446808Sdab send_help()
44546808Sdab {
44646808Sdab     struct sendlist *s;	/* pointer to current command */
44746808Sdab     for (s = Sendlist; s->name; s++) {
44846808Sdab 	if (s->help)
44946808Sdab 	    printf("%-15s %s\n", s->name, s->help);
45046808Sdab     }
45146808Sdab     return(0);
45246808Sdab }
45332144Sminshall 
45432144Sminshall /*
45532144Sminshall  * The following are the routines and data structures referred
45632144Sminshall  * to by the arguments to the "toggle" command.
45732144Sminshall  */
45832144Sminshall 
45946808Sdab     static int
46032144Sminshall lclchars()
46132144Sminshall {
46232144Sminshall     donelclchars = 1;
46332144Sminshall     return 1;
46432144Sminshall }
46532144Sminshall 
46646808Sdab     static int
46732144Sminshall togdebug()
46832144Sminshall {
46932144Sminshall #ifndef	NOT43
47032144Sminshall     if (net > 0 &&
47132144Sminshall 	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
47232144Sminshall 	    perror("setsockopt (SO_DEBUG)");
47332144Sminshall     }
47432144Sminshall #else	/* NOT43 */
47532144Sminshall     if (debug) {
47632144Sminshall 	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
47732144Sminshall 	    perror("setsockopt (SO_DEBUG)");
47832144Sminshall     } else
47932144Sminshall 	printf("Cannot turn off socket debugging\n");
48032144Sminshall #endif	/* NOT43 */
48132144Sminshall     return 1;
48232144Sminshall }
48332144Sminshall 
48432144Sminshall 
48546808Sdab     static int
48632144Sminshall togcrlf()
48732144Sminshall {
48832144Sminshall     if (crlf) {
48932144Sminshall 	printf("Will send carriage returns as telnet <CR><LF>.\n");
49032144Sminshall     } else {
49132144Sminshall 	printf("Will send carriage returns as telnet <CR><NUL>.\n");
49232144Sminshall     }
49332144Sminshall     return 1;
49432144Sminshall }
49532144Sminshall 
49638909Sborman int binmode;
49732144Sminshall 
49846808Sdab     static int
49938689Sborman togbinary(val)
50046808Sdab     int val;
50132144Sminshall {
50232144Sminshall     donebinarytoggle = 1;
50332144Sminshall 
50438909Sborman     if (val >= 0) {
50538909Sborman 	binmode = val;
50638909Sborman     } else {
50738909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
50838909Sborman 				my_want_state_is_do(TELOPT_BINARY)) {
50938909Sborman 	    binmode = 1;
51038909Sborman 	} else if (my_want_state_is_wont(TELOPT_BINARY) &&
51138909Sborman 				my_want_state_is_dont(TELOPT_BINARY)) {
51238909Sborman 	    binmode = 0;
51338909Sborman 	}
51438909Sborman 	val = binmode ? 0 : 1;
51538909Sborman     }
51638909Sborman 
51738909Sborman     if (val == 1) {
51838909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
51938909Sborman 					my_want_state_is_do(TELOPT_BINARY)) {
52038689Sborman 	    printf("Already operating in binary mode with remote host.\n");
52138909Sborman 	} else {
52238909Sborman 	    printf("Negotiating binary mode with remote host.\n");
52338909Sborman 	    tel_enter_binary(3);
52438689Sborman 	}
52538909Sborman     } else {
52638909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY) &&
52738909Sborman 					my_want_state_is_dont(TELOPT_BINARY)) {
52838689Sborman 	    printf("Already in network ascii mode with remote host.\n");
52938909Sborman 	} else {
53038909Sborman 	    printf("Negotiating network ascii mode with remote host.\n");
53138909Sborman 	    tel_leave_binary(3);
53238689Sborman 	}
53332144Sminshall     }
53432144Sminshall     return 1;
53532144Sminshall }
53632144Sminshall 
53746808Sdab     static int
53838909Sborman togrbinary(val)
53946808Sdab     int val;
54038909Sborman {
54138909Sborman     donebinarytoggle = 1;
54232144Sminshall 
54338909Sborman     if (val == -1)
54438909Sborman 	val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
54532144Sminshall 
54638909Sborman     if (val == 1) {
54738909Sborman 	if (my_want_state_is_do(TELOPT_BINARY)) {
54838909Sborman 	    printf("Already receiving in binary mode.\n");
54938909Sborman 	} else {
55038909Sborman 	    printf("Negotiating binary mode on input.\n");
55138909Sborman 	    tel_enter_binary(1);
55238909Sborman 	}
55338909Sborman     } else {
55438909Sborman 	if (my_want_state_is_dont(TELOPT_BINARY)) {
55538909Sborman 	    printf("Already receiving in network ascii mode.\n");
55638909Sborman 	} else {
55738909Sborman 	    printf("Negotiating network ascii mode on input.\n");
55838909Sborman 	    tel_leave_binary(1);
55938909Sborman 	}
56038909Sborman     }
56138909Sborman     return 1;
56238909Sborman }
56338909Sborman 
56446808Sdab     static int
56538909Sborman togxbinary(val)
56646808Sdab     int val;
56738909Sborman {
56838909Sborman     donebinarytoggle = 1;
56938909Sborman 
57038909Sborman     if (val == -1)
57138909Sborman 	val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
57238909Sborman 
57338909Sborman     if (val == 1) {
57438909Sborman 	if (my_want_state_is_will(TELOPT_BINARY)) {
57538909Sborman 	    printf("Already transmitting in binary mode.\n");
57638909Sborman 	} else {
57738909Sborman 	    printf("Negotiating binary mode on output.\n");
57838909Sborman 	    tel_enter_binary(2);
57938909Sborman 	}
58038909Sborman     } else {
58138909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY)) {
58238909Sborman 	    printf("Already transmitting in network ascii mode.\n");
58338909Sborman 	} else {
58438909Sborman 	    printf("Negotiating network ascii mode on output.\n");
58538909Sborman 	    tel_leave_binary(2);
58638909Sborman 	}
58738909Sborman     }
58838909Sborman     return 1;
58938909Sborman }
59038909Sborman 
59138909Sborman 
59256642Sralph static int togglehelp P((void));
59357213Sdab #if	defined(AUTHENTICATION)
59447609Sdab extern int auth_togdebug P((int));
59547609Sdab #endif
59657213Sdab #if	defined(ENCRYPTION)
59747609Sdab extern int EncryptAutoEnc P((int));
59847609Sdab extern int EncryptAutoDec P((int));
59947609Sdab extern int EncryptDebug P((int));
60047609Sdab extern int EncryptVerbose P((int));
60147609Sdab #endif
60232144Sminshall 
60332144Sminshall struct togglelist {
60432144Sminshall     char	*name;		/* name of toggle */
60532144Sminshall     char	*help;		/* help message */
60632144Sminshall     int		(*handler)();	/* routine to do actual setting */
60732144Sminshall     int		*variable;
60832144Sminshall     char	*actionexplanation;
60932144Sminshall };
61032144Sminshall 
61132144Sminshall static struct togglelist Togglelist[] = {
61232144Sminshall     { "autoflush",
61338689Sborman 	"flushing of output when sending interrupt characters",
61432144Sminshall 	    0,
61538689Sborman 		&autoflush,
61638689Sborman 		    "flush output when sending interrupt characters" },
61732144Sminshall     { "autosynch",
61838689Sborman 	"automatic sending of interrupt characters in urgent mode",
61932144Sminshall 	    0,
62038689Sborman 		&autosynch,
62138689Sborman 		    "send interrupt characters in urgent mode" },
62257213Sdab #if	defined(AUTHENTICATION)
62347609Sdab     { "autologin",
62447609Sdab 	"automatic sending of login and/or authentication info",
62547609Sdab 	    0,
62647609Sdab 		&autologin,
62747609Sdab 		    "send login name and/or authentication information" },
62847609Sdab     { "authdebug",
62947609Sdab 	"Toggle authentication debugging",
63047609Sdab 	    auth_togdebug,
63147609Sdab 		0,
63247609Sdab 		     "print authentication debugging information" },
63347609Sdab #endif
63457213Sdab #if	defined(ENCRYPTION)
63547609Sdab     { "autoencrypt",
63647609Sdab 	"automatic encryption of data stream",
63747609Sdab 	    EncryptAutoEnc,
63847609Sdab 		0,
63947609Sdab 		    "automatically encrypt output" },
64047609Sdab     { "autodecrypt",
64147609Sdab 	"automatic decryption of data stream",
64247609Sdab 	    EncryptAutoDec,
64347609Sdab 		0,
64447609Sdab 		    "automatically decrypt input" },
64547609Sdab     { "verbose_encrypt",
64647609Sdab 	"Toggle verbose encryption output",
64747609Sdab 	    EncryptVerbose,
64847609Sdab 		0,
64947609Sdab 		    "print verbose encryption output" },
65047609Sdab     { "encdebug",
65147609Sdab 	"Toggle encryption debugging",
65247609Sdab 	    EncryptDebug,
65347609Sdab 		0,
65447609Sdab 		    "print encryption debugging information" },
65547609Sdab #endif
65647609Sdab     { "skiprc",
65747609Sdab 	"don't read ~/.telnetrc file",
65847609Sdab 	    0,
65947609Sdab 		&skiprc,
66057848Sdab 		    "skip reading of ~/.telnetrc file" },
66132144Sminshall     { "binary",
66238689Sborman 	"sending and receiving of binary data",
66332144Sminshall 	    togbinary,
66438689Sborman 		0,
66538689Sborman 		    0 },
66638909Sborman     { "inbinary",
66738909Sborman 	"receiving of binary data",
66838909Sborman 	    togrbinary,
66938909Sborman 		0,
67038909Sborman 		    0 },
67138909Sborman     { "outbinary",
67238909Sborman 	"sending of binary data",
67338909Sborman 	    togxbinary,
67438909Sborman 		0,
67538909Sborman 		    0 },
67632144Sminshall     { "crlf",
67738689Sborman 	"sending carriage returns as telnet <CR><LF>",
67832144Sminshall 	    togcrlf,
67938689Sborman 		&crlf,
68038689Sborman 		    0 },
68132144Sminshall     { "crmod",
68238689Sborman 	"mapping of received carriage returns",
68332144Sminshall 	    0,
68438689Sborman 		&crmod,
68538689Sborman 		    "map carriage return on output" },
68632144Sminshall     { "localchars",
68738689Sborman 	"local recognition of certain control characters",
68832144Sminshall 	    lclchars,
68938689Sborman 		&localchars,
69038689Sborman 		    "recognize certain control characters" },
69138689Sborman     { " ", "", 0 },		/* empty line */
69238208Sminshall #if	defined(unix) && defined(TN3270)
69338920Sminshall     { "apitrace",
69438920Sminshall 	"(debugging) toggle tracing of API transactions",
69538920Sminshall 	    0,
69638920Sminshall 		&apitrace,
69738920Sminshall 		    "trace API transactions" },
69838208Sminshall     { "cursesdata",
69938208Sminshall 	"(debugging) toggle printing of hexadecimal curses data",
70038208Sminshall 	    0,
70138689Sborman 		&cursesdata,
70238689Sborman 		    "print hexadecimal representation of curses data" },
70338208Sminshall #endif	/* defined(unix) && defined(TN3270) */
70432144Sminshall     { "debug",
70538689Sborman 	"debugging",
70632144Sminshall 	    togdebug,
70738689Sborman 		&debug,
70838689Sborman 		    "turn on socket level debugging" },
70932144Sminshall     { "netdata",
71038689Sborman 	"printing of hexadecimal network data (debugging)",
71132144Sminshall 	    0,
71238689Sborman 		&netdata,
71338689Sborman 		    "print hexadecimal representation of network traffic" },
71438689Sborman     { "prettydump",
71538689Sborman 	"output of \"netdata\" to user readable format (debugging)",
71638689Sborman 	    0,
71738689Sborman 		&prettydump,
71838689Sborman 		    "print user readable output for \"netdata\"" },
71932144Sminshall     { "options",
72038689Sborman 	"viewing of options processing (debugging)",
72132144Sminshall 	    0,
72238689Sborman 		&showoptions,
72338689Sborman 		    "show option processing" },
72438208Sminshall #if	defined(unix)
72538208Sminshall     { "termdata",
72638208Sminshall 	"(debugging) toggle printing of hexadecimal terminal data",
72738208Sminshall 	    0,
72838689Sborman 		&termdata,
72938689Sborman 		    "print hexadecimal representation of terminal traffic" },
73038208Sminshall #endif	/* defined(unix) */
73132144Sminshall     { "?",
73238689Sborman 	0,
73338689Sborman 	    togglehelp },
73432144Sminshall     { "help",
73538689Sborman 	0,
73638689Sborman 	    togglehelp },
73732144Sminshall     { 0 }
73832144Sminshall };
73932144Sminshall 
74046808Sdab     static int
74132144Sminshall togglehelp()
74232144Sminshall {
74332144Sminshall     struct togglelist *c;
74432144Sminshall 
74532144Sminshall     for (c = Togglelist; c->name; c++) {
74638689Sborman 	if (c->help) {
74738689Sborman 	    if (*c->help)
74838689Sborman 		printf("%-15s toggle %s\n", c->name, c->help);
74938689Sborman 	    else
75038689Sborman 		printf("\n");
75132144Sminshall 	}
75232144Sminshall     }
75338689Sborman     printf("\n");
75438689Sborman     printf("%-15s %s\n", "?", "display help information");
75532144Sminshall     return 0;
75632144Sminshall }
75732144Sminshall 
75846808Sdab     static void
75938689Sborman settogglehelp(set)
76046808Sdab     int set;
76138689Sborman {
76238689Sborman     struct togglelist *c;
76338689Sborman 
76438689Sborman     for (c = Togglelist; c->name; c++) {
76538689Sborman 	if (c->help) {
76638689Sborman 	    if (*c->help)
76738689Sborman 		printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
76838689Sborman 						c->help);
76938689Sborman 	    else
77038689Sborman 		printf("\n");
77138689Sborman 	}
77238689Sborman     }
77338689Sborman }
77438689Sborman 
77546808Sdab #define	GETTOGGLE(name) (struct togglelist *) \
77646808Sdab 		genget(name, (char **) Togglelist, sizeof(struct togglelist))
77732144Sminshall 
77846808Sdab     static int
77932144Sminshall toggle(argc, argv)
78046808Sdab     int  argc;
78146808Sdab     char *argv[];
78232144Sminshall {
78332144Sminshall     int retval = 1;
78432144Sminshall     char *name;
78532144Sminshall     struct togglelist *c;
78632144Sminshall 
78732144Sminshall     if (argc < 2) {
78832144Sminshall 	fprintf(stderr,
78932144Sminshall 	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
79032144Sminshall 	return 0;
79132144Sminshall     }
79232144Sminshall     argc--;
79332144Sminshall     argv++;
79432144Sminshall     while (argc--) {
79532144Sminshall 	name = *argv++;
79646808Sdab 	c = GETTOGGLE(name);
79732144Sminshall 	if (Ambiguous(c)) {
79832144Sminshall 	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
79932144Sminshall 					name);
80032144Sminshall 	    return 0;
80132144Sminshall 	} else if (c == 0) {
80232144Sminshall 	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
80332144Sminshall 					name);
80432144Sminshall 	    return 0;
80532144Sminshall 	} else {
80632144Sminshall 	    if (c->variable) {
80732144Sminshall 		*c->variable = !*c->variable;		/* invert it */
80832144Sminshall 		if (c->actionexplanation) {
80932144Sminshall 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
81032144Sminshall 							c->actionexplanation);
81132144Sminshall 		}
81232144Sminshall 	    }
81332144Sminshall 	    if (c->handler) {
81438689Sborman 		retval &= (*c->handler)(-1);
81532144Sminshall 	    }
81632144Sminshall 	}
81732144Sminshall     }
81832144Sminshall     return retval;
81932144Sminshall }
82032144Sminshall 
82132144Sminshall /*
82232144Sminshall  * The following perform the "set" command.
82332144Sminshall  */
82432144Sminshall 
82538689Sborman #ifdef	USE_TERMIO
82638689Sborman struct termio new_tc = { 0 };
82738689Sborman #endif
82838689Sborman 
82932144Sminshall struct setlist {
83032144Sminshall     char *name;				/* name */
83132144Sminshall     char *help;				/* help information */
83238689Sborman     void (*handler)();
83340245Sborman     cc_t *charp;			/* where it is located at */
83432144Sminshall };
83532144Sminshall 
83632144Sminshall static struct setlist Setlist[] = {
83744361Sborman #ifdef	KLUDGELINEMODE
83838689Sborman     { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
83944361Sborman #endif
84038689Sborman     { "escape",	"character to escape back to telnet command mode", 0, &escape },
84146808Sdab     { "rlogin", "rlogin escape character", 0, &rlogin },
84245233Sborman     { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
84332144Sminshall     { " ", "" },
84438689Sborman     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
84545233Sborman     { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
84638689Sborman     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
84738689Sborman     { "quit",	"character to cause an Abort process", 0, termQuitCharp },
84838689Sborman     { "eof",	"character to cause an EOF ", 0, termEofCharp },
84938689Sborman     { " ", "" },
85038689Sborman     { " ", "The following are for local editing in linemode", 0, 0 },
85138689Sborman     { "erase",	"character to use to erase a character", 0, termEraseCharp },
85238689Sborman     { "kill",	"character to use to erase a line", 0, termKillCharp },
85338689Sborman     { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
85444361Sborman     { "susp",	"character to cause a Suspend Process", 0, termSuspCharp },
85538689Sborman     { "reprint", "character to use for line reprint", 0, termRprntCharp },
85638689Sborman     { "worderase", "character to use to erase a word", 0, termWerasCharp },
85738689Sborman     { "start",	"character to use for XON", 0, termStartCharp },
85844361Sborman     { "stop",	"character to use for XOFF", 0, termStopCharp },
85944361Sborman     { "forw1",	"alternate end of line character", 0, termForw1Charp },
86044361Sborman     { "forw2",	"alternate end of line character", 0, termForw2Charp },
86145233Sborman     { "ayt",	"alternate AYT character", 0, termAytCharp },
86232144Sminshall     { 0 }
86332144Sminshall };
86432144Sminshall 
86545233Sborman #if	defined(CRAY) && !defined(__STDC__)
86645233Sborman /* Work around compiler bug in pcc 4.1.5 */
86746808Sdab     void
86838689Sborman _setlist_init()
86938689Sborman {
87044361Sborman #ifndef	KLUDGELINEMODE
87146808Sdab #define	N 5
87244361Sborman #else
87346808Sdab #define	N 6
87444361Sborman #endif
87544361Sborman 	Setlist[N+0].charp = &termFlushChar;
87644361Sborman 	Setlist[N+1].charp = &termIntChar;
87744361Sborman 	Setlist[N+2].charp = &termQuitChar;
87844361Sborman 	Setlist[N+3].charp = &termEofChar;
87944361Sborman 	Setlist[N+6].charp = &termEraseChar;
88044361Sborman 	Setlist[N+7].charp = &termKillChar;
88144361Sborman 	Setlist[N+8].charp = &termLiteralNextChar;
88244361Sborman 	Setlist[N+9].charp = &termSuspChar;
88344361Sborman 	Setlist[N+10].charp = &termRprntChar;
88444361Sborman 	Setlist[N+11].charp = &termWerasChar;
88544361Sborman 	Setlist[N+12].charp = &termStartChar;
88644361Sborman 	Setlist[N+13].charp = &termStopChar;
88744361Sborman 	Setlist[N+14].charp = &termForw1Char;
88844361Sborman 	Setlist[N+15].charp = &termForw2Char;
88945233Sborman 	Setlist[N+16].charp = &termAytChar;
89044361Sborman #undef	N
89138689Sborman }
89245233Sborman #endif	/* defined(CRAY) && !defined(__STDC__) */
89338689Sborman 
89446808Sdab     static struct setlist *
89532144Sminshall getset(name)
89646808Sdab     char *name;
89732144Sminshall {
89846808Sdab     return (struct setlist *)
89946808Sdab 		genget(name, (char **) Setlist, sizeof(struct setlist));
90032144Sminshall }
90132144Sminshall 
90246808Sdab     void
90344361Sborman set_escape_char(s)
90446808Sdab     char *s;
90544361Sborman {
90646808Sdab 	if (rlogin != _POSIX_VDISABLE) {
90746808Sdab 		rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
90846808Sdab 		printf("Telnet rlogin escape character is '%s'.\n",
90946808Sdab 					control(rlogin));
91046808Sdab 	} else {
91146808Sdab 		escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
91246808Sdab 		printf("Telnet escape character is '%s'.\n", control(escape));
91346808Sdab 	}
91444361Sborman }
91544361Sborman 
91646808Sdab     static int
91732144Sminshall setcmd(argc, argv)
91846808Sdab     int  argc;
91946808Sdab     char *argv[];
92032144Sminshall {
92132144Sminshall     int value;
92232144Sminshall     struct setlist *ct;
92338689Sborman     struct togglelist *c;
92432144Sminshall 
92538689Sborman     if (argc < 2 || argc > 3) {
92638689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
92732144Sminshall 	return 0;
92832144Sminshall     }
92946808Sdab     if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
93038689Sborman 	for (ct = Setlist; ct->name; ct++)
93138689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
93238689Sborman 	printf("\n");
93338689Sborman 	settogglehelp(1);
93438689Sborman 	printf("%-15s %s\n", "?", "display help information");
93538689Sborman 	return 0;
93638689Sborman     }
93732144Sminshall 
93832144Sminshall     ct = getset(argv[1]);
93932144Sminshall     if (ct == 0) {
94046808Sdab 	c = GETTOGGLE(argv[1]);
94138689Sborman 	if (c == 0) {
94238689Sborman 	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
94332144Sminshall 			argv[1]);
94438689Sborman 	    return 0;
94538689Sborman 	} else if (Ambiguous(c)) {
94638689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
94738689Sborman 			argv[1]);
94838689Sborman 	    return 0;
94938689Sborman 	}
95038689Sborman 	if (c->variable) {
95138689Sborman 	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
95238689Sborman 		*c->variable = 1;
95338689Sborman 	    else if (strcmp("off", argv[2]) == 0)
95438689Sborman 		*c->variable = 0;
95538689Sborman 	    else {
95638689Sborman 		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
95738689Sborman 		return 0;
95838689Sborman 	    }
95938689Sborman 	    if (c->actionexplanation) {
96038689Sborman 		printf("%s %s.\n", *c->variable? "Will" : "Won't",
96138689Sborman 							c->actionexplanation);
96238689Sborman 	    }
96338689Sborman 	}
96438689Sborman 	if (c->handler)
96538689Sborman 	    (*c->handler)(1);
96638689Sborman     } else if (argc != 3) {
96738689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
96832144Sminshall 	return 0;
96932144Sminshall     } else if (Ambiguous(ct)) {
97032144Sminshall 	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
97132144Sminshall 			argv[1]);
97232144Sminshall 	return 0;
97338689Sborman     } else if (ct->handler) {
97438689Sborman 	(*ct->handler)(argv[2]);
97544361Sborman 	printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
97632144Sminshall     } else {
97732144Sminshall 	if (strcmp("off", argv[2])) {
97832144Sminshall 	    value = special(argv[2]);
97932144Sminshall 	} else {
98045233Sborman 	    value = _POSIX_VDISABLE;
98132144Sminshall 	}
98240245Sborman 	*(ct->charp) = (cc_t)value;
98332144Sminshall 	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
98432144Sminshall     }
98538689Sborman     slc_check();
98632144Sminshall     return 1;
98732144Sminshall }
98838689Sborman 
98946808Sdab     static int
99038689Sborman unsetcmd(argc, argv)
99146808Sdab     int  argc;
99246808Sdab     char *argv[];
99338689Sborman {
99438689Sborman     struct setlist *ct;
99538689Sborman     struct togglelist *c;
99638689Sborman     register char *name;
99738689Sborman 
99838689Sborman     if (argc < 2) {
99938689Sborman 	fprintf(stderr,
100038689Sborman 	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
100138689Sborman 	return 0;
100238689Sborman     }
100346808Sdab     if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
100438689Sborman 	for (ct = Setlist; ct->name; ct++)
100538689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
100638689Sborman 	printf("\n");
100738689Sborman 	settogglehelp(0);
100838689Sborman 	printf("%-15s %s\n", "?", "display help information");
100938689Sborman 	return 0;
101038689Sborman     }
101138689Sborman 
101238689Sborman     argc--;
101338689Sborman     argv++;
101438689Sborman     while (argc--) {
101538689Sborman 	name = *argv++;
101638689Sborman 	ct = getset(name);
101738689Sborman 	if (ct == 0) {
101846808Sdab 	    c = GETTOGGLE(name);
101938689Sborman 	    if (c == 0) {
102038689Sborman 		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
102138689Sborman 			name);
102238689Sborman 		return 0;
102338689Sborman 	    } else if (Ambiguous(c)) {
102438689Sborman 		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
102538689Sborman 			name);
102638689Sborman 		return 0;
102738689Sborman 	    }
102838689Sborman 	    if (c->variable) {
102938689Sborman 		*c->variable = 0;
103038689Sborman 		if (c->actionexplanation) {
103138689Sborman 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
103238689Sborman 							c->actionexplanation);
103338689Sborman 		}
103438689Sborman 	    }
103538689Sborman 	    if (c->handler)
103638689Sborman 		(*c->handler)(0);
103738689Sborman 	} else if (Ambiguous(ct)) {
103838689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
103938689Sborman 			name);
104038689Sborman 	    return 0;
104138689Sborman 	} else if (ct->handler) {
104238689Sborman 	    (*ct->handler)(0);
104344361Sborman 	    printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
104438689Sborman 	} else {
104545233Sborman 	    *(ct->charp) = _POSIX_VDISABLE;
104638689Sborman 	    printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
104738689Sborman 	}
104838689Sborman     }
104938689Sborman     return 1;
105038689Sborman }
105132144Sminshall 
105232144Sminshall /*
105332144Sminshall  * The following are the data structures and routines for the
105432144Sminshall  * 'mode' command.
105532144Sminshall  */
105638689Sborman #ifdef	KLUDGELINEMODE
105738689Sborman extern int kludgelinemode;
105844361Sborman 
105946808Sdab     static int
106044361Sborman dokludgemode()
106144361Sborman {
106244361Sborman     kludgelinemode = 1;
106344361Sborman     send_wont(TELOPT_LINEMODE, 1);
106444361Sborman     send_dont(TELOPT_SGA, 1);
106544361Sborman     send_dont(TELOPT_ECHO, 1);
106644361Sborman }
106738689Sborman #endif
106832144Sminshall 
106946808Sdab     static int
107032144Sminshall dolinemode()
107132144Sminshall {
107238689Sborman #ifdef	KLUDGELINEMODE
107338689Sborman     if (kludgelinemode)
107438689Sborman 	send_dont(TELOPT_SGA, 1);
107538689Sborman #endif
107638689Sborman     send_will(TELOPT_LINEMODE, 1);
107738689Sborman     send_dont(TELOPT_ECHO, 1);
107832144Sminshall     return 1;
107932144Sminshall }
108032144Sminshall 
108146808Sdab     static int
108232144Sminshall docharmode()
108332144Sminshall {
108438689Sborman #ifdef	KLUDGELINEMODE
108538689Sborman     if (kludgelinemode)
108638689Sborman 	send_do(TELOPT_SGA, 1);
108738689Sborman     else
108838689Sborman #endif
108938689Sborman     send_wont(TELOPT_LINEMODE, 1);
109038689Sborman     send_do(TELOPT_ECHO, 1);
109138689Sborman     return 1;
109238689Sborman }
109338689Sborman 
109446808Sdab     static int
109538689Sborman dolmmode(bit, on)
109646808Sdab     int bit, on;
109738689Sborman {
109846808Sdab     unsigned char c;
109938689Sborman     extern int linemode;
110038689Sborman 
110138689Sborman     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
110238689Sborman 	printf("?Need to have LINEMODE option enabled first.\n");
110338689Sborman 	printf("'mode ?' for help.\n");
110438689Sborman 	return 0;
110532144Sminshall     }
110638689Sborman 
110738689Sborman     if (on)
110838689Sborman 	c = (linemode | bit);
110938689Sborman     else
111038689Sborman 	c = (linemode & ~bit);
111138689Sborman     lm_mode(&c, 1, 1);
111232144Sminshall     return 1;
111332144Sminshall }
111432144Sminshall 
111546808Sdab     int
111646808Sdab setmode(bit)
111746808Sdab {
111846808Sdab     return dolmmode(bit, 1);
111946808Sdab }
112046808Sdab 
112146808Sdab     int
112246808Sdab clearmode(bit)
112346808Sdab {
112446808Sdab     return dolmmode(bit, 0);
112546808Sdab }
112646808Sdab 
112738689Sborman struct modelist {
112838689Sborman 	char	*name;		/* command name */
112938689Sborman 	char	*help;		/* help string */
113038689Sborman 	int	(*handler)();	/* routine which executes command */
113138689Sborman 	int	needconnect;	/* Do we need to be connected to execute? */
113238689Sborman 	int	arg1;
113338689Sborman };
113438689Sborman 
113538689Sborman extern int modehelp();
113638689Sborman 
113738689Sborman static struct modelist ModeList[] = {
113838689Sborman     { "character", "Disable LINEMODE option",	docharmode, 1 },
113939529Sborman #ifdef	KLUDGELINEMODE
114039529Sborman     { "",	"(or disable obsolete line-by-line mode)", 0 },
114138689Sborman #endif
114238689Sborman     { "line",	"Enable LINEMODE option",	dolinemode, 1 },
114339529Sborman #ifdef	KLUDGELINEMODE
114439529Sborman     { "",	"(or enable obsolete line-by-line mode)", 0 },
114538689Sborman #endif
114638689Sborman     { "", "", 0 },
114738689Sborman     { "",	"These require the LINEMODE option to be enabled", 0 },
114838689Sborman     { "isig",	"Enable signal trapping",	setmode, 1, MODE_TRAPSIG },
114938689Sborman     { "+isig",	0,				setmode, 1, MODE_TRAPSIG },
115038689Sborman     { "-isig",	"Disable signal trapping",	clearmode, 1, MODE_TRAPSIG },
115138689Sborman     { "edit",	"Enable character editing",	setmode, 1, MODE_EDIT },
115238689Sborman     { "+edit",	0,				setmode, 1, MODE_EDIT },
115338689Sborman     { "-edit",	"Disable character editing",	clearmode, 1, MODE_EDIT },
115444361Sborman     { "softtabs", "Enable tab expansion",	setmode, 1, MODE_SOFT_TAB },
115544361Sborman     { "+softtabs", 0,				setmode, 1, MODE_SOFT_TAB },
115644361Sborman     { "-softtabs", "Disable character editing",	clearmode, 1, MODE_SOFT_TAB },
115744361Sborman     { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
115844361Sborman     { "+litecho", 0,				setmode, 1, MODE_LIT_ECHO },
115944361Sborman     { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
116038689Sborman     { "help",	0,				modehelp, 0 },
116144361Sborman #ifdef	KLUDGELINEMODE
116244361Sborman     { "kludgeline", 0,				dokludgemode, 1 },
116344361Sborman #endif
116444361Sborman     { "", "", 0 },
116538689Sborman     { "?",	"Print help information",	modehelp, 0 },
116632144Sminshall     { 0 },
116732144Sminshall };
116832144Sminshall 
116932144Sminshall 
117046808Sdab     int
117138689Sborman modehelp()
117238689Sborman {
117338689Sborman     struct modelist *mt;
117438689Sborman 
117538689Sborman     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
117638689Sborman     for (mt = ModeList; mt->name; mt++) {
117738689Sborman 	if (mt->help) {
117838689Sborman 	    if (*mt->help)
117938689Sborman 		printf("%-15s %s\n", mt->name, mt->help);
118038689Sborman 	    else
118138689Sborman 		printf("\n");
118238689Sborman 	}
118338689Sborman     }
118438689Sborman     return 0;
118538689Sborman }
118638689Sborman 
118746808Sdab #define	GETMODECMD(name) (struct modelist *) \
118846808Sdab 		genget(name, (char **) ModeList, sizeof(struct modelist))
118946808Sdab 
119046808Sdab     static int
119132144Sminshall modecmd(argc, argv)
119246808Sdab     int  argc;
119346808Sdab     char *argv[];
119432144Sminshall {
119538689Sborman     struct modelist *mt;
119632144Sminshall 
119738689Sborman     if (argc != 2) {
119838689Sborman 	printf("'mode' command requires an argument\n");
119938689Sborman 	printf("'mode ?' for help.\n");
120046808Sdab     } else if ((mt = GETMODECMD(argv[1])) == 0) {
120132144Sminshall 	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
120232144Sminshall     } else if (Ambiguous(mt)) {
120332144Sminshall 	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
120438689Sborman     } else if (mt->needconnect && !connected) {
120538689Sborman 	printf("?Need to be connected first.\n");
120638689Sborman 	printf("'mode ?' for help.\n");
120738689Sborman     } else if (mt->handler) {
120838689Sborman 	return (*mt->handler)(mt->arg1);
120932144Sminshall     }
121038689Sborman     return 0;
121132144Sminshall }
121232144Sminshall 
121332144Sminshall /*
121432144Sminshall  * The following data structures and routines implement the
121532144Sminshall  * "display" command.
121632144Sminshall  */
121732144Sminshall 
121846808Sdab     static int
121932144Sminshall display(argc, argv)
122046808Sdab     int  argc;
122146808Sdab     char *argv[];
122232144Sminshall {
122346808Sdab     struct togglelist *tl;
122446808Sdab     struct setlist *sl;
122546808Sdab 
122632144Sminshall #define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
122732144Sminshall 			    if (*tl->variable) { \
122832144Sminshall 				printf("will"); \
122932144Sminshall 			    } else { \
123032144Sminshall 				printf("won't"); \
123132144Sminshall 			    } \
123232144Sminshall 			    printf(" %s.\n", tl->actionexplanation); \
123332144Sminshall 			}
123432144Sminshall 
123532144Sminshall #define	doset(sl)   if (sl->name && *sl->name != ' ') { \
123638689Sborman 			if (sl->handler == 0) \
123738689Sborman 			    printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
123838689Sborman 			else \
123944361Sborman 			    printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
124032144Sminshall 		    }
124132144Sminshall 
124232144Sminshall     if (argc == 1) {
124332144Sminshall 	for (tl = Togglelist; tl->name; tl++) {
124432144Sminshall 	    dotog(tl);
124532144Sminshall 	}
124632144Sminshall 	printf("\n");
124732144Sminshall 	for (sl = Setlist; sl->name; sl++) {
124832144Sminshall 	    doset(sl);
124932144Sminshall 	}
125032144Sminshall     } else {
125132144Sminshall 	int i;
125232144Sminshall 
125332144Sminshall 	for (i = 1; i < argc; i++) {
125432144Sminshall 	    sl = getset(argv[i]);
125546808Sdab 	    tl = GETTOGGLE(argv[i]);
125632144Sminshall 	    if (Ambiguous(sl) || Ambiguous(tl)) {
125732144Sminshall 		printf("?Ambiguous argument '%s'.\n", argv[i]);
125832144Sminshall 		return 0;
125932144Sminshall 	    } else if (!sl && !tl) {
126032144Sminshall 		printf("?Unknown argument '%s'.\n", argv[i]);
126132144Sminshall 		return 0;
126232144Sminshall 	    } else {
126332144Sminshall 		if (tl) {
126432144Sminshall 		    dotog(tl);
126532144Sminshall 		}
126632144Sminshall 		if (sl) {
126732144Sminshall 		    doset(sl);
126832144Sminshall 		}
126932144Sminshall 	    }
127032144Sminshall 	}
127132144Sminshall     }
127238689Sborman /*@*/optionstatus();
127357213Sdab #if	defined(ENCRYPTION)
127446808Sdab     EncryptStatus();
127546808Sdab #endif
127632144Sminshall     return 1;
127732144Sminshall #undef	doset
127832144Sminshall #undef	dotog
127932144Sminshall }
128032144Sminshall 
128132144Sminshall /*
128232144Sminshall  * The following are the data structures, and many of the routines,
128332144Sminshall  * relating to command processing.
128432144Sminshall  */
128532144Sminshall 
128632144Sminshall /*
128732144Sminshall  * Set the escape character.
128832144Sminshall  */
128946808Sdab 	static int
129032144Sminshall setescape(argc, argv)
129132144Sminshall 	int argc;
129232144Sminshall 	char *argv[];
129332144Sminshall {
129432144Sminshall 	register char *arg;
129532144Sminshall 	char buf[50];
129632144Sminshall 
129732144Sminshall 	printf(
129832144Sminshall 	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
129932144Sminshall 				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
130032144Sminshall 	if (argc > 2)
130132144Sminshall 		arg = argv[1];
130232144Sminshall 	else {
130332144Sminshall 		printf("new escape character: ");
130446808Sdab 		(void) fgets(buf, sizeof(buf), stdin);
130532144Sminshall 		arg = buf;
130632144Sminshall 	}
130732144Sminshall 	if (arg[0] != '\0')
130832144Sminshall 		escape = arg[0];
130932144Sminshall 	if (!In3270) {
131032144Sminshall 		printf("Escape character is '%s'.\n", control(escape));
131132144Sminshall 	}
131234849Sminshall 	(void) fflush(stdout);
131332144Sminshall 	return 1;
131432144Sminshall }
131532144Sminshall 
131646808Sdab     /*VARARGS*/
131746808Sdab     static int
131832144Sminshall togcrmod()
131932144Sminshall {
132032144Sminshall     crmod = !crmod;
132132144Sminshall     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
132232144Sminshall     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
132334849Sminshall     (void) fflush(stdout);
132432144Sminshall     return 1;
132532144Sminshall }
132632144Sminshall 
132746808Sdab     /*VARARGS*/
132846808Sdab     int
132932144Sminshall suspend()
133032144Sminshall {
133138689Sborman #ifdef	SIGTSTP
133237219Sminshall     setcommandmode();
133337219Sminshall     {
133444361Sborman 	long oldrows, oldcols, newrows, newcols, err;
133537219Sminshall 
133657213Sdab 	err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
133734849Sminshall 	(void) kill(0, SIGTSTP);
133857213Sdab 	/*
133957213Sdab 	 * If we didn't get the window size before the SUSPEND, but we
134057213Sdab 	 * can get them now (???), then send the NAWS to make sure that
134157213Sdab 	 * we are set up for the right window size.
134257213Sdab 	 */
134357213Sdab 	if (TerminalWindowSize(&newrows, &newcols) && connected &&
134457213Sdab 	    (err || ((oldrows != newrows) || (oldcols != newcols)))) {
134537219Sminshall 		sendnaws();
134637219Sminshall 	}
134737219Sminshall     }
134837219Sminshall     /* reget parameters in case they were changed */
134937219Sminshall     TerminalSaveState();
135038689Sborman     setconnmode(0);
135138689Sborman #else
135238689Sborman     printf("Suspend is not supported.  Try the '!' command instead\n");
135338689Sborman #endif
135437219Sminshall     return 1;
135532144Sminshall }
135632144Sminshall 
135738689Sborman #if	!defined(TN3270)
135846808Sdab     /*ARGSUSED*/
135946808Sdab     int
136038689Sborman shell(argc, argv)
136146808Sdab     int argc;
136246808Sdab     char *argv[];
136338689Sborman {
136457213Sdab     long oldrows, oldcols, newrows, newcols, err;
136557213Sdab 
136638689Sborman     setcommandmode();
136757213Sdab 
136857213Sdab     err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
136938689Sborman     switch(vfork()) {
137038689Sborman     case -1:
137138689Sborman 	perror("Fork failed\n");
137238689Sborman 	break;
137338689Sborman 
137438689Sborman     case 0:
137538689Sborman 	{
137638689Sborman 	    /*
137738689Sborman 	     * Fire up the shell in the child.
137838689Sborman 	     */
137946808Sdab 	    register char *shellp, *shellname;
138046808Sdab 	    extern char *rindex();
138138689Sborman 
138246808Sdab 	    shellp = getenv("SHELL");
138346808Sdab 	    if (shellp == NULL)
138446808Sdab 		shellp = "/bin/sh";
138546808Sdab 	    if ((shellname = rindex(shellp, '/')) == 0)
138646808Sdab 		shellname = shellp;
138738689Sborman 	    else
138838689Sborman 		shellname++;
138938689Sborman 	    if (argc > 1)
139046808Sdab 		execl(shellp, shellname, "-c", &saveline[1], 0);
139138689Sborman 	    else
139246808Sdab 		execl(shellp, shellname, 0);
139338689Sborman 	    perror("Execl");
139438689Sborman 	    _exit(1);
139538689Sborman 	}
139638689Sborman     default:
139744361Sborman 	    (void)wait((int *)0);	/* Wait for the shell to complete */
139857213Sdab 
139957213Sdab 	    if (TerminalWindowSize(&newrows, &newcols) && connected &&
140057213Sdab 		(err || ((oldrows != newrows) || (oldcols != newcols)))) {
140157213Sdab 		    sendnaws();
140257213Sdab 	    }
140357213Sdab 	    break;
140438689Sborman     }
140546808Sdab     return 1;
140638689Sborman }
140738689Sborman #endif	/* !defined(TN3270) */
140838689Sborman 
140946808Sdab     /*VARARGS*/
141046808Sdab     static
141132144Sminshall bye(argc, argv)
141246808Sdab     int  argc;		/* Number of arguments */
141346808Sdab     char *argv[];	/* arguments */
141432144Sminshall {
141546808Sdab     extern int resettermname;
141646808Sdab 
141732144Sminshall     if (connected) {
141834849Sminshall 	(void) shutdown(net, 2);
141932144Sminshall 	printf("Connection closed.\n");
142034849Sminshall 	(void) NetClose(net);
142132144Sminshall 	connected = 0;
142246808Sdab 	resettermname = 1;
142357213Sdab #if	defined(AUTHENTICATION) || defined(ENCRYPTION)
142446808Sdab 	auth_encrypt_connect(connected);
142546808Sdab #endif
142632144Sminshall 	/* reset options */
142732144Sminshall 	tninit();
142832144Sminshall #if	defined(TN3270)
142932144Sminshall 	SetIn3270();		/* Get out of 3270 mode */
143032144Sminshall #endif	/* defined(TN3270) */
143132144Sminshall     }
143232144Sminshall     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
143332144Sminshall 	longjmp(toplevel, 1);
143432144Sminshall 	/* NOTREACHED */
143532144Sminshall     }
143632144Sminshall     return 1;			/* Keep lint, etc., happy */
143732144Sminshall }
143832144Sminshall 
143932144Sminshall /*VARARGS*/
144032144Sminshall quit()
144132144Sminshall {
144232144Sminshall 	(void) call(bye, "bye", "fromquit", 0);
144332144Sminshall 	Exit(0);
144444361Sborman 	/*NOTREACHED*/
144532144Sminshall }
144646808Sdab 
144746808Sdab /*VARARGS*/
144846808Sdab 	int
144946808Sdab logout()
145046808Sdab {
145146808Sdab 	send_do(TELOPT_LOGOUT, 1);
145246808Sdab 	(void) netflush();
145346808Sdab 	return 1;
145446808Sdab }
145546808Sdab 
145638689Sborman 
145738689Sborman /*
145838689Sborman  * The SLC command.
145938689Sborman  */
146032144Sminshall 
146138689Sborman struct slclist {
146238689Sborman 	char	*name;
146338689Sborman 	char	*help;
146446808Sdab 	void	(*handler)();
146538689Sborman 	int	arg;
146638689Sborman };
146738689Sborman 
146856642Sralph static void slc_help();
146938689Sborman 
147038689Sborman struct slclist SlcList[] = {
147138689Sborman     { "export",	"Use local special character definitions",
147238689Sborman 						slc_mode_export,	0 },
147338689Sborman     { "import",	"Use remote special character definitions",
147438689Sborman 						slc_mode_import,	1 },
147538689Sborman     { "check",	"Verify remote special character definitions",
147638689Sborman 						slc_mode_import,	0 },
147738689Sborman     { "help",	0,				slc_help,		0 },
147838689Sborman     { "?",	"Print help information",	slc_help,		0 },
147938689Sborman     { 0 },
148038689Sborman };
148138689Sborman 
148246808Sdab     static void
148338689Sborman slc_help()
148438689Sborman {
148538689Sborman     struct slclist *c;
148638689Sborman 
148738689Sborman     for (c = SlcList; c->name; c++) {
148838689Sborman 	if (c->help) {
148938689Sborman 	    if (*c->help)
149038689Sborman 		printf("%-15s %s\n", c->name, c->help);
149138689Sborman 	    else
149238689Sborman 		printf("\n");
149338689Sborman 	}
149438689Sborman     }
149538689Sborman }
149638689Sborman 
149746808Sdab     static struct slclist *
149838689Sborman getslc(name)
149946808Sdab     char *name;
150038689Sborman {
150146808Sdab     return (struct slclist *)
150246808Sdab 		genget(name, (char **) SlcList, sizeof(struct slclist));
150338689Sborman }
150438689Sborman 
150546808Sdab     static
150638689Sborman slccmd(argc, argv)
150746808Sdab     int  argc;
150846808Sdab     char *argv[];
150938689Sborman {
151038689Sborman     struct slclist *c;
151138689Sborman 
151238689Sborman     if (argc != 2) {
151338689Sborman 	fprintf(stderr,
151438689Sborman 	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
151538689Sborman 	return 0;
151638689Sborman     }
151738689Sborman     c = getslc(argv[1]);
151838689Sborman     if (c == 0) {
151938689Sborman         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
152038689Sborman     				argv[1]);
152138689Sborman         return 0;
152238689Sborman     }
152338689Sborman     if (Ambiguous(c)) {
152438689Sborman         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
152538689Sborman     				argv[1]);
152638689Sborman         return 0;
152738689Sborman     }
152838689Sborman     (*c->handler)(c->arg);
152938689Sborman     slcstate();
153038689Sborman     return 1;
153138689Sborman }
153244361Sborman 
153344361Sborman /*
153444361Sborman  * The ENVIRON command.
153544361Sborman  */
153638689Sborman 
153744361Sborman struct envlist {
153844361Sborman 	char	*name;
153944361Sborman 	char	*help;
154046808Sdab 	void	(*handler)();
154144361Sborman 	int	narg;
154244361Sborman };
154344361Sborman 
154446808Sdab extern struct env_lst *
154546808Sdab 	env_define P((unsigned char *, unsigned char *));
154646808Sdab extern void
154746808Sdab 	env_undefine P((unsigned char *)),
154846808Sdab 	env_export P((unsigned char *)),
154946808Sdab 	env_unexport P((unsigned char *)),
155046808Sdab 	env_send P((unsigned char *)),
1551*58972Sdab #ifdef	ENV_HACK
1552*58972Sdab 	env_varval P((unsigned char *)),
1553*58972Sdab #endif
155456642Sralph 	env_list P((void));
155556642Sralph static void
155646808Sdab 	env_help P((void));
155744361Sborman 
155844361Sborman struct envlist EnvList[] = {
155944361Sborman     { "define",	"Define an environment variable",
156046808Sdab 						(void (*)())env_define,	2 },
156144361Sborman     { "undefine", "Undefine an environment variable",
156244361Sborman 						env_undefine,	1 },
156344361Sborman     { "export",	"Mark an environment variable for automatic export",
156444361Sborman 						env_export,	1 },
156546808Sdab     { "unexport", "Don't mark an environment variable for automatic export",
156644361Sborman 						env_unexport,	1 },
156745233Sborman     { "send",	"Send an environment variable", env_send,	1 },
156844361Sborman     { "list",	"List the current environment variables",
156944361Sborman 						env_list,	0 },
1570*58972Sdab #ifdef	ENV_HACK
1571*58972Sdab     { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
1572*58972Sdab 						env_varval,    1 },
1573*58972Sdab #endif
157444361Sborman     { "help",	0,				env_help,		0 },
157544361Sborman     { "?",	"Print help information",	env_help,		0 },
157644361Sborman     { 0 },
157744361Sborman };
157844361Sborman 
157946808Sdab     static void
158044361Sborman env_help()
158144361Sborman {
158244361Sborman     struct envlist *c;
158344361Sborman 
158444361Sborman     for (c = EnvList; c->name; c++) {
158544361Sborman 	if (c->help) {
158644361Sborman 	    if (*c->help)
158744361Sborman 		printf("%-15s %s\n", c->name, c->help);
158844361Sborman 	    else
158944361Sborman 		printf("\n");
159044361Sborman 	}
159144361Sborman     }
159244361Sborman }
159344361Sborman 
159446808Sdab     static struct envlist *
159544361Sborman getenvcmd(name)
159646808Sdab     char *name;
159744361Sborman {
159846808Sdab     return (struct envlist *)
159946808Sdab 		genget(name, (char **) EnvList, sizeof(struct envlist));
160044361Sborman }
160144361Sborman 
160244361Sborman env_cmd(argc, argv)
160346808Sdab     int  argc;
160446808Sdab     char *argv[];
160544361Sborman {
160644361Sborman     struct envlist *c;
160744361Sborman 
160844361Sborman     if (argc < 2) {
160944361Sborman 	fprintf(stderr,
161044361Sborman 	    "Need an argument to 'environ' command.  'environ ?' for help.\n");
161144361Sborman 	return 0;
161244361Sborman     }
161344361Sborman     c = getenvcmd(argv[1]);
161444361Sborman     if (c == 0) {
161544361Sborman         fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
161644361Sborman     				argv[1]);
161744361Sborman         return 0;
161844361Sborman     }
161944361Sborman     if (Ambiguous(c)) {
162044361Sborman         fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
162144361Sborman     				argv[1]);
162244361Sborman         return 0;
162344361Sborman     }
162444361Sborman     if (c->narg + 2 != argc) {
162544361Sborman 	fprintf(stderr,
162644361Sborman 	    "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
162744361Sborman 		c->narg < argc + 2 ? "only " : "",
162844361Sborman 		c->narg, c->narg == 1 ? "" : "s", c->name);
162944361Sborman 	return 0;
163044361Sborman     }
163146808Sdab     (*c->handler)(argv[2], argv[3]);
163244361Sborman     return 1;
163344361Sborman }
163444361Sborman 
163544361Sborman struct env_lst {
163644361Sborman 	struct env_lst *next;	/* pointer to next structure */
163757213Sdab 	struct env_lst *prev;	/* pointer to previous structure */
163846808Sdab 	unsigned char *var;	/* pointer to variable name */
163957213Sdab 	unsigned char *value;	/* pointer to variable value */
164044361Sborman 	int export;		/* 1 -> export with default list of variables */
164157213Sdab 	int welldefined;	/* A well defined variable */
164244361Sborman };
164344361Sborman 
164444361Sborman struct env_lst envlisthead;
164544361Sborman 
164646808Sdab 	struct env_lst *
164744361Sborman env_find(var)
164846808Sdab 	unsigned char *var;
164944361Sborman {
165044361Sborman 	register struct env_lst *ep;
165144361Sborman 
165244361Sborman 	for (ep = envlisthead.next; ep; ep = ep->next) {
165346808Sdab 		if (strcmp((char *)ep->var, (char *)var) == 0)
165444361Sborman 			return(ep);
165544361Sborman 	}
165644361Sborman 	return(NULL);
165744361Sborman }
165844361Sborman 
165946808Sdab 	void
166044361Sborman env_init()
166144361Sborman {
166246808Sdab 	extern char **environ;
166344361Sborman 	register char **epp, *cp;
166444361Sborman 	register struct env_lst *ep;
166546808Sdab 	extern char *index();
166644361Sborman 
166744361Sborman 	for (epp = environ; *epp; epp++) {
166844361Sborman 		if (cp = index(*epp, '=')) {
166944361Sborman 			*cp = '\0';
167046808Sdab 			ep = env_define((unsigned char *)*epp,
167146808Sdab 					(unsigned char *)cp+1);
167244361Sborman 			ep->export = 0;
167344361Sborman 			*cp = '=';
167444361Sborman 		}
167544361Sborman 	}
167644361Sborman 	/*
167744361Sborman 	 * Special case for DISPLAY variable.  If it is ":0.0" or
167844361Sborman 	 * "unix:0.0", we have to get rid of "unix" and insert our
167944361Sborman 	 * hostname.
168044361Sborman 	 */
168146808Sdab 	if ((ep = env_find("DISPLAY"))
168246808Sdab 	    && ((*ep->value == ':')
168346808Sdab 	        || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
168444361Sborman 		char hbuf[256+1];
168546808Sdab 		char *cp2 = index((char *)ep->value, ':');
168644361Sborman 
168744361Sborman 		gethostname(hbuf, 256);
168844361Sborman 		hbuf[256] = '\0';
168944361Sborman 		cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
169046808Sdab 		sprintf((char *)cp, "%s%s", hbuf, cp2);
169144361Sborman 		free(ep->value);
169246808Sdab 		ep->value = (unsigned char *)cp;
169344361Sborman 	}
169444361Sborman 	/*
169544361Sborman 	 * If USER is not defined, but LOGNAME is, then add
169645233Sborman 	 * USER with the value from LOGNAME.  By default, we
169745233Sborman 	 * don't export the USER variable.
169844361Sborman 	 */
169945233Sborman 	if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
170046808Sdab 		env_define((unsigned char *)"USER", ep->value);
170146808Sdab 		env_unexport((unsigned char *)"USER");
170245233Sborman 	}
170346808Sdab 	env_export((unsigned char *)"DISPLAY");
170446808Sdab 	env_export((unsigned char *)"PRINTER");
170544361Sborman }
170644361Sborman 
170746808Sdab 	struct env_lst *
170844361Sborman env_define(var, value)
170946808Sdab 	unsigned char *var, *value;
171044361Sborman {
171144361Sborman 	register struct env_lst *ep;
171244361Sborman 
171344361Sborman 	if (ep = env_find(var)) {
171444361Sborman 		if (ep->var)
171544361Sborman 			free(ep->var);
171644361Sborman 		if (ep->value)
171744361Sborman 			free(ep->value);
171844361Sborman 	} else {
171944361Sborman 		ep = (struct env_lst *)malloc(sizeof(struct env_lst));
172044361Sborman 		ep->next = envlisthead.next;
172144361Sborman 		envlisthead.next = ep;
172244361Sborman 		ep->prev = &envlisthead;
172344361Sborman 		if (ep->next)
172444361Sborman 			ep->next->prev = ep;
172544361Sborman 	}
172657213Sdab 	ep->welldefined = opt_welldefined(var);
172745009Skarels 	ep->export = 1;
172846808Sdab 	ep->var = (unsigned char *)strdup((char *)var);
172946808Sdab 	ep->value = (unsigned char *)strdup((char *)value);
173044361Sborman 	return(ep);
173144361Sborman }
173244361Sborman 
173346808Sdab 	void
173444361Sborman env_undefine(var)
173546808Sdab 	unsigned char *var;
173644361Sborman {
173744361Sborman 	register struct env_lst *ep;
173844361Sborman 
173944361Sborman 	if (ep = env_find(var)) {
174044361Sborman 		ep->prev->next = ep->next;
174145233Sborman 		if (ep->next)
174245233Sborman 			ep->next->prev = ep->prev;
174344361Sborman 		if (ep->var)
174444361Sborman 			free(ep->var);
174544361Sborman 		if (ep->value)
174644361Sborman 			free(ep->value);
174744361Sborman 		free(ep);
174844361Sborman 	}
174944361Sborman }
175044361Sborman 
175146808Sdab 	void
175244361Sborman env_export(var)
175346808Sdab 	unsigned char *var;
175444361Sborman {
175544361Sborman 	register struct env_lst *ep;
175644361Sborman 
175744361Sborman 	if (ep = env_find(var))
175844361Sborman 		ep->export = 1;
175944361Sborman }
176044361Sborman 
176146808Sdab 	void
176244361Sborman env_unexport(var)
176346808Sdab 	unsigned char *var;
176444361Sborman {
176544361Sborman 	register struct env_lst *ep;
176644361Sborman 
176744361Sborman 	if (ep = env_find(var))
176844361Sborman 		ep->export = 0;
176944361Sborman }
177044361Sborman 
177146808Sdab 	void
177245233Sborman env_send(var)
177346808Sdab 	unsigned char *var;
177445233Sborman {
177545233Sborman 	register struct env_lst *ep;
177645233Sborman 
177745233Sborman         if (my_state_is_wont(TELOPT_ENVIRON)) {
177845233Sborman 		fprintf(stderr,
177945233Sborman 		    "Cannot send '%s': Telnet ENVIRON option not enabled\n",
178045233Sborman 									var);
178145233Sborman 		return;
178245233Sborman 	}
178345233Sborman 	ep = env_find(var);
178445233Sborman 	if (ep == 0) {
178545233Sborman 		fprintf(stderr, "Cannot send '%s': variable not defined\n",
178645233Sborman 									var);
178745233Sborman 		return;
178845233Sborman 	}
178945233Sborman 	env_opt_start_info();
179045233Sborman 	env_opt_add(ep->var);
179145233Sborman 	env_opt_end(0);
179245233Sborman }
179345233Sborman 
179446808Sdab 	void
179544361Sborman env_list()
179644361Sborman {
179744361Sborman 	register struct env_lst *ep;
179844361Sborman 
179944361Sborman 	for (ep = envlisthead.next; ep; ep = ep->next) {
180044361Sborman 		printf("%c %-20s %s\n", ep->export ? '*' : ' ',
180144361Sborman 					ep->var, ep->value);
180244361Sborman 	}
180344361Sborman }
180444361Sborman 
180546808Sdab 	unsigned char *
180657213Sdab env_default(init, welldefined)
180746808Sdab 	int init;
180844361Sborman {
180944361Sborman 	static struct env_lst *nep = NULL;
181044361Sborman 
181144361Sborman 	if (init) {
181244361Sborman 		nep = &envlisthead;
181344361Sborman 		return;
181444361Sborman 	}
181544361Sborman 	if (nep) {
181644361Sborman 		while (nep = nep->next) {
181757213Sdab 			if (nep->export && (nep->welldefined == welldefined))
181844361Sborman 				return(nep->var);
181944361Sborman 		}
182044361Sborman 	}
182144361Sborman 	return(NULL);
182244361Sborman }
182344361Sborman 
182446808Sdab 	unsigned char *
182544361Sborman env_getvalue(var)
182646808Sdab 	unsigned char *var;
182744361Sborman {
182844361Sborman 	register struct env_lst *ep;
182944361Sborman 
183044361Sborman 	if (ep = env_find(var))
183144361Sborman 		return(ep->value);
183244361Sborman 	return(NULL);
183344361Sborman }
183444361Sborman 
1835*58972Sdab #ifdef	ENV_HACK
1836*58972Sdab 	void
1837*58972Sdab env_varval(what)
1838*58972Sdab 	unsigned char *what;
1839*58972Sdab {
1840*58972Sdab 	extern int env_var, env_value, env_auto;
1841*58972Sdab 	int len = strlen(what);
1842*58972Sdab 
1843*58972Sdab 	if (len == 0)
1844*58972Sdab 		goto unknown;
1845*58972Sdab 
1846*58972Sdab 	if (strncasecmp(what, "status", len) == 0) {
1847*58972Sdab 		if (env_auto)
1848*58972Sdab 			printf("%s%s", "VAR and VALUE are/will be ",
1849*58972Sdab 					"determined automatically\n");
1850*58972Sdab 		if (env_var == ENV_VAR)
1851*58972Sdab 			printf("VAR and VALUE set to correct definitions\n");
1852*58972Sdab 		else
1853*58972Sdab 			printf("VAR and VALUE definitions are reversed\n");
1854*58972Sdab 	} else if (strncasecmp(what, "auto", len) == 0) {
1855*58972Sdab 		env_auto = 1;
1856*58972Sdab 		env_var = ENV_VALUE;
1857*58972Sdab 		env_value = ENV_VAR;
1858*58972Sdab 	} else if (strncasecmp(what, "right", len) == 0) {
1859*58972Sdab 		env_auto = 0;
1860*58972Sdab 		env_var = ENV_VAR;
1861*58972Sdab 		env_value = ENV_VALUE;
1862*58972Sdab 	} else if (strncasecmp(what, "wrong", len) == 0) {
1863*58972Sdab 		env_auto = 0;
1864*58972Sdab 		env_var = ENV_VALUE;
1865*58972Sdab 		env_value = ENV_VAR;
1866*58972Sdab 	} else {
1867*58972Sdab unknown:
1868*58972Sdab 		printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
1869*58972Sdab 	}
1870*58972Sdab }
1871*58972Sdab #endif
1872*58972Sdab 
187357213Sdab #if	defined(AUTHENTICATION)
187446808Sdab /*
187546808Sdab  * The AUTHENTICATE command.
187646808Sdab  */
187746808Sdab 
187846808Sdab struct authlist {
187946808Sdab 	char	*name;
188046808Sdab 	char	*help;
188146808Sdab 	int	(*handler)();
188246808Sdab 	int	narg;
188346808Sdab };
188446808Sdab 
188546808Sdab extern int
188646808Sdab 	auth_enable P((int)),
188746808Sdab 	auth_disable P((int)),
188856642Sralph 	auth_status P((void));
188956642Sralph static int
189046808Sdab 	auth_help P((void));
189146808Sdab 
189246808Sdab struct authlist AuthList[] = {
189346808Sdab     { "status",	"Display current status of authentication information",
189446808Sdab 						auth_status,	0 },
189546808Sdab     { "disable", "Disable an authentication type ('auth disable ?' for more)",
189646808Sdab 						auth_disable,	1 },
189746808Sdab     { "enable", "Enable an authentication type ('auth enable ?' for more)",
189846808Sdab 						auth_enable,	1 },
189946808Sdab     { "help",	0,				auth_help,		0 },
190046808Sdab     { "?",	"Print help information",	auth_help,		0 },
190146808Sdab     { 0 },
190246808Sdab };
190346808Sdab 
190446808Sdab     static int
190546808Sdab auth_help()
190644361Sborman {
190746808Sdab     struct authlist *c;
190846808Sdab 
190946808Sdab     for (c = AuthList; c->name; c++) {
191046808Sdab 	if (c->help) {
191146808Sdab 	    if (*c->help)
191246808Sdab 		printf("%-15s %s\n", c->name, c->help);
191346808Sdab 	    else
191446808Sdab 		printf("\n");
191546808Sdab 	}
191646808Sdab     }
191746808Sdab     return 0;
191844361Sborman }
191946808Sdab 
192046808Sdab auth_cmd(argc, argv)
192146808Sdab     int  argc;
192246808Sdab     char *argv[];
192346808Sdab {
192446808Sdab     struct authlist *c;
192546808Sdab 
192646808Sdab     c = (struct authlist *)
192746808Sdab 		genget(argv[1], (char **) AuthList, sizeof(struct authlist));
192846808Sdab     if (c == 0) {
192946808Sdab         fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
193046808Sdab     				argv[1]);
193146808Sdab         return 0;
193246808Sdab     }
193346808Sdab     if (Ambiguous(c)) {
193446808Sdab         fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
193546808Sdab     				argv[1]);
193646808Sdab         return 0;
193746808Sdab     }
193846808Sdab     if (c->narg + 2 != argc) {
193946808Sdab 	fprintf(stderr,
194046808Sdab 	    "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
194146808Sdab 		c->narg < argc + 2 ? "only " : "",
194246808Sdab 		c->narg, c->narg == 1 ? "" : "s", c->name);
194346808Sdab 	return 0;
194446808Sdab     }
194546808Sdab     return((*c->handler)(argv[2], argv[3]));
194646808Sdab }
194745233Sborman #endif
194844361Sborman 
194957213Sdab #if	defined(ENCRYPTION)
195032144Sminshall /*
195146808Sdab  * The ENCRYPT command.
195236274Sminshall  */
195336274Sminshall 
195446808Sdab struct encryptlist {
195546808Sdab 	char	*name;
195646808Sdab 	char	*help;
195746808Sdab 	int	(*handler)();
195846808Sdab 	int	needconnect;
195946808Sdab 	int	minarg;
196046808Sdab 	int	maxarg;
196146808Sdab };
196246808Sdab 
196346808Sdab extern int
196446808Sdab 	EncryptEnable P((char *, char *)),
196547609Sdab 	EncryptDisable P((char *, char *)),
196646808Sdab 	EncryptType P((char *, char *)),
196746808Sdab 	EncryptStart P((char *)),
196846808Sdab 	EncryptStartInput P((void)),
196946808Sdab 	EncryptStartOutput P((void)),
197046808Sdab 	EncryptStop P((char *)),
197146808Sdab 	EncryptStopInput P((void)),
197246808Sdab 	EncryptStopOutput P((void)),
197356642Sralph 	EncryptStatus P((void));
197456642Sralph static int
197546808Sdab 	EncryptHelp P((void));
197646808Sdab 
197746808Sdab struct encryptlist EncryptList[] = {
197846808Sdab     { "enable", "Enable encryption. ('encrypt enable ?' for more)",
197946808Sdab 						EncryptEnable, 1, 1, 2 },
198047609Sdab     { "disable", "Disable encryption. ('encrypt enable ?' for more)",
198147609Sdab 						EncryptDisable, 0, 1, 2 },
198246808Sdab     { "type", "Set encryptiong type. ('encrypt type ?' for more)",
198346808Sdab 						EncryptType, 0, 1, 1 },
198446808Sdab     { "start", "Start encryption. ('encrypt start ?' for more)",
198546808Sdab 						EncryptStart, 1, 0, 1 },
198646808Sdab     { "stop", "Stop encryption. ('encrypt stop ?' for more)",
198746808Sdab 						EncryptStop, 1, 0, 1 },
198846808Sdab     { "input", "Start encrypting the input stream",
198946808Sdab 						EncryptStartInput, 1, 0, 0 },
199046808Sdab     { "-input", "Stop encrypting the input stream",
199146808Sdab 						EncryptStopInput, 1, 0, 0 },
199246808Sdab     { "output", "Start encrypting the output stream",
199346808Sdab 						EncryptStartOutput, 1, 0, 0 },
199446808Sdab     { "-output", "Stop encrypting the output stream",
199546808Sdab 						EncryptStopOutput, 1, 0, 0 },
199646808Sdab 
199746808Sdab     { "status",	"Display current status of authentication information",
199846808Sdab 						EncryptStatus,	0, 0, 0 },
199946808Sdab     { "help",	0,				EncryptHelp,	0, 0, 0 },
200046808Sdab     { "?",	"Print help information",	EncryptHelp,	0, 0, 0 },
200146808Sdab     { 0 },
200246808Sdab };
200346808Sdab 
200446808Sdab     static int
200546808Sdab EncryptHelp()
200636274Sminshall {
200746808Sdab     struct encryptlist *c;
200846808Sdab 
200946808Sdab     for (c = EncryptList; c->name; c++) {
201046808Sdab 	if (c->help) {
201146808Sdab 	    if (*c->help)
201246808Sdab 		printf("%-15s %s\n", c->name, c->help);
201346808Sdab 	    else
201446808Sdab 		printf("\n");
201536274Sminshall 	}
201646808Sdab     }
201746808Sdab     return 0;
201846808Sdab }
201936274Sminshall 
202046808Sdab encrypt_cmd(argc, argv)
202146808Sdab     int  argc;
202246808Sdab     char *argv[];
202346808Sdab {
202446808Sdab     struct encryptlist *c;
202536274Sminshall 
202646808Sdab     c = (struct encryptlist *)
202746808Sdab 		genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
202846808Sdab     if (c == 0) {
202946808Sdab         fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
203046808Sdab     				argv[1]);
203146808Sdab         return 0;
203246808Sdab     }
203346808Sdab     if (Ambiguous(c)) {
203446808Sdab         fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
203546808Sdab     				argv[1]);
203646808Sdab         return 0;
203746808Sdab     }
203846808Sdab     argc -= 2;
203946808Sdab     if (argc < c->minarg || argc > c->maxarg) {
204046808Sdab 	if (c->minarg == c->maxarg) {
204146808Sdab 	    fprintf(stderr, "Need %s%d argument%s ",
204246808Sdab 		c->minarg < argc ? "only " : "", c->minarg,
204346808Sdab 		c->minarg == 1 ? "" : "s");
204446808Sdab 	} else {
204546808Sdab 	    fprintf(stderr, "Need %s%d-%d arguments ",
204646808Sdab 		c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
204746808Sdab 	}
204846808Sdab 	fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
204946808Sdab 		c->name);
205046808Sdab 	return 0;
205146808Sdab     }
205246808Sdab     if (c->needconnect && !connected) {
205346808Sdab 	if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
205446808Sdab 	    printf("?Need to be connected first.\n");
205546808Sdab 	    return 0;
205646808Sdab 	}
205746808Sdab     }
205846808Sdab     return ((*c->handler)(argc > 0 ? argv[2] : 0,
205946808Sdab 			argc > 1 ? argv[3] : 0,
206046808Sdab 			argc > 2 ? argv[4] : 0));
206146808Sdab }
206236274Sminshall #endif
206336274Sminshall 
206446808Sdab #if	defined(unix) && defined(TN3270)
206546808Sdab     static void
206636274Sminshall filestuff(fd)
206746808Sdab     int fd;
206836274Sminshall {
206936274Sminshall     int res;
207036274Sminshall 
207138689Sborman #ifdef	F_GETOWN
207238689Sborman     setconnmode(0);
207336274Sminshall     res = fcntl(fd, F_GETOWN, 0);
207436274Sminshall     setcommandmode();
207536274Sminshall 
207636274Sminshall     if (res == -1) {
207736274Sminshall 	perror("fcntl");
207836274Sminshall 	return;
207936274Sminshall     }
208036274Sminshall     printf("\tOwner is %d.\n", res);
208138689Sborman #endif
208236274Sminshall 
208338689Sborman     setconnmode(0);
208436274Sminshall     res = fcntl(fd, F_GETFL, 0);
208536274Sminshall     setcommandmode();
208636274Sminshall 
208736274Sminshall     if (res == -1) {
208836274Sminshall 	perror("fcntl");
208936274Sminshall 	return;
209036274Sminshall     }
209136274Sminshall     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
209236274Sminshall }
209346808Sdab #endif /* defined(unix) && defined(TN3270) */
209436274Sminshall 
209536274Sminshall /*
209632144Sminshall  * Print status about the connection.
209732144Sminshall  */
209846808Sdab     /*ARGSUSED*/
209946808Sdab     static
210032144Sminshall status(argc, argv)
210146808Sdab     int	 argc;
210246808Sdab     char *argv[];
210332144Sminshall {
210432144Sminshall     if (connected) {
210532144Sminshall 	printf("Connected to %s.\n", hostname);
210636242Sminshall 	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
210738689Sborman 	    int mode = getconnmode();
210838689Sborman 
210938689Sborman 	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
211038689Sborman 		printf("Operating with LINEMODE option\n");
211138689Sborman 		printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
211238689Sborman 		printf("%s catching of signals\n",
211338689Sborman 					(mode&MODE_TRAPSIG) ? "Local" : "No");
211438689Sborman 		slcstate();
211538689Sborman #ifdef	KLUDGELINEMODE
211639529Sborman 	    } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
211738689Sborman 		printf("Operating in obsolete linemode\n");
211838689Sborman #endif
211938689Sborman 	    } else {
212038689Sborman 		printf("Operating in single character mode\n");
212138689Sborman 		if (localchars)
212238689Sborman 		    printf("Catching signals locally\n");
212332144Sminshall 	    }
212438689Sborman 	    printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
212538689Sborman 	    if (my_want_state_is_will(TELOPT_LFLOW))
212638689Sborman 		printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
212757213Sdab #if	defined(ENCRYPTION)
212846808Sdab 	    encrypt_display();
212946808Sdab #endif
213032144Sminshall 	}
213132144Sminshall     } else {
213232144Sminshall 	printf("No connection.\n");
213332144Sminshall     }
213432144Sminshall #   if !defined(TN3270)
213532144Sminshall     printf("Escape character is '%s'.\n", control(escape));
213634849Sminshall     (void) fflush(stdout);
213732144Sminshall #   else /* !defined(TN3270) */
213832144Sminshall     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
213932144Sminshall 	printf("Escape character is '%s'.\n", control(escape));
214032144Sminshall     }
214132144Sminshall #   if defined(unix)
214236242Sminshall     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
214336242Sminshall 	printf("SIGIO received %d time%s.\n",
214436242Sminshall 				sigiocount, (sigiocount == 1)? "":"s");
214536274Sminshall 	if (In3270) {
214636274Sminshall 	    printf("Process ID %d, process group %d.\n",
214736274Sminshall 					    getpid(), getpgrp(getpid()));
214836274Sminshall 	    printf("Terminal input:\n");
214936274Sminshall 	    filestuff(tin);
215036274Sminshall 	    printf("Terminal output:\n");
215136274Sminshall 	    filestuff(tout);
215236274Sminshall 	    printf("Network socket:\n");
215336274Sminshall 	    filestuff(net);
215436274Sminshall 	}
215536242Sminshall     }
215632144Sminshall     if (In3270 && transcom) {
215732144Sminshall        printf("Transparent mode command is '%s'.\n", transcom);
215832144Sminshall     }
215932144Sminshall #   endif /* defined(unix) */
216034849Sminshall     (void) fflush(stdout);
216132144Sminshall     if (In3270) {
216232144Sminshall 	return 0;
216332144Sminshall     }
216432144Sminshall #   endif /* defined(TN3270) */
216532144Sminshall     return 1;
216632144Sminshall }
216732144Sminshall 
216845233Sborman #ifdef	SIGINFO
216945233Sborman /*
217045233Sborman  * Function that gets called when SIGINFO is received.
217145233Sborman  */
217245233Sborman ayt_status()
217345233Sborman {
217445233Sborman     (void) call(status, "status", "notmuch", 0);
217545233Sborman }
217645233Sborman #endif
217732144Sminshall 
2178*58972Sdab unsigned long inet_addr();
2179*58972Sdab 
218046808Sdab     int
218132144Sminshall tn(argc, argv)
218246808Sdab     int argc;
218346808Sdab     char *argv[];
218432144Sminshall {
218532144Sminshall     register struct hostent *host = 0;
218632144Sminshall     struct sockaddr_in sin;
218732144Sminshall     struct servent *sp = 0;
2188*58972Sdab     unsigned long temp;
218937219Sminshall     extern char *inet_ntoa();
219046808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
219138689Sborman     char *srp = 0, *strrchr();
219238689Sborman     unsigned long sourceroute(), srlen;
219338689Sborman #endif
219444361Sborman     char *cmd, *hostp = 0, *portp = 0, *user = 0;
219532144Sminshall 
219645233Sborman     /* clear the socket address prior to use */
219745233Sborman     bzero((char *)&sin, sizeof(sin));
219832144Sminshall 
219932144Sminshall     if (connected) {
220032144Sminshall 	printf("?Already connected to %s\n", hostname);
220146808Sdab 	setuid(getuid());
220232144Sminshall 	return 0;
220332144Sminshall     }
220432144Sminshall     if (argc < 2) {
220546808Sdab 	(void) strcpy(line, "open ");
220632144Sminshall 	printf("(to) ");
220746808Sdab 	(void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
220832144Sminshall 	makeargv();
220932144Sminshall 	argc = margc;
221032144Sminshall 	argv = margv;
221132144Sminshall     }
221244361Sborman     cmd = *argv;
221344361Sborman     --argc; ++argv;
221444361Sborman     while (argc) {
221546808Sdab 	if (isprefix(*argv, "help") || isprefix(*argv, "?"))
221646808Sdab 	    goto usage;
221744361Sborman 	if (strcmp(*argv, "-l") == 0) {
221844361Sborman 	    --argc; ++argv;
221944361Sborman 	    if (argc == 0)
222044361Sborman 		goto usage;
222144361Sborman 	    user = *argv++;
222244361Sborman 	    --argc;
222344361Sborman 	    continue;
222444361Sborman 	}
222545233Sborman 	if (strcmp(*argv, "-a") == 0) {
222645233Sborman 	    --argc; ++argv;
222745233Sborman 	    autologin = 1;
222845233Sborman 	    continue;
222945233Sborman 	}
223044361Sborman 	if (hostp == 0) {
223144361Sborman 	    hostp = *argv++;
223244361Sborman 	    --argc;
223344361Sborman 	    continue;
223444361Sborman 	}
223544361Sborman 	if (portp == 0) {
223644361Sborman 	    portp = *argv++;
223744361Sborman 	    --argc;
223844361Sborman 	    continue;
223944361Sborman 	}
224044361Sborman     usage:
224145233Sborman 	printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
224246808Sdab 	setuid(getuid());
224332144Sminshall 	return 0;
224432144Sminshall     }
224546808Sdab     if (hostp == 0)
224646808Sdab 	goto usage;
224746808Sdab 
224846808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
224944361Sborman     if (hostp[0] == '@' || hostp[0] == '!') {
225044361Sborman 	if ((hostname = strrchr(hostp, ':')) == NULL)
225144361Sborman 	    hostname = strrchr(hostp, '@');
225238689Sborman 	hostname++;
225338689Sborman 	srp = 0;
225444361Sborman 	temp = sourceroute(hostp, &srp, &srlen);
225538689Sborman 	if (temp == 0) {
225638689Sborman 	    herror(srp);
225746808Sdab 	    setuid(getuid());
225838689Sborman 	    return 0;
225938689Sborman 	} else if (temp == -1) {
226044361Sborman 	    printf("Bad source route option: %s\n", hostp);
226146808Sdab 	    setuid(getuid());
226238689Sborman 	    return 0;
226338689Sborman 	} else {
226438689Sborman 	    sin.sin_addr.s_addr = temp;
226538689Sborman 	    sin.sin_family = AF_INET;
226638689Sborman 	}
226732144Sminshall     } else {
226838689Sborman #endif
226944361Sborman 	temp = inet_addr(hostp);
227038689Sborman 	if (temp != (unsigned long) -1) {
227138689Sborman 	    sin.sin_addr.s_addr = temp;
227238689Sborman 	    sin.sin_family = AF_INET;
227346808Sdab 	    (void) strcpy(_hostname, hostp);
227446808Sdab 	    hostname = _hostname;
227538689Sborman 	} else {
227644361Sborman 	    host = gethostbyname(hostp);
227738689Sborman 	    if (host) {
227838689Sborman 		sin.sin_family = host->h_addrtype;
227932144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
228038689Sborman 		memcpy((caddr_t)&sin.sin_addr,
228132144Sminshall 				host->h_addr_list[0], host->h_length);
228232144Sminshall #else	/* defined(h_addr) */
228338689Sborman 		memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
228432144Sminshall #endif	/* defined(h_addr) */
228546808Sdab 		strncpy(_hostname, host->h_name, sizeof(_hostname));
228646808Sdab 		_hostname[sizeof(_hostname)-1] = '\0';
228746808Sdab 		hostname = _hostname;
228838689Sborman 	    } else {
228944361Sborman 		herror(hostp);
229046808Sdab 	        setuid(getuid());
229138689Sborman 		return 0;
229238689Sborman 	    }
229332144Sminshall 	}
229446808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
229532144Sminshall     }
229638689Sborman #endif
229744361Sborman     if (portp) {
229844361Sborman 	if (*portp == '-') {
229944361Sborman 	    portp++;
230038689Sborman 	    telnetport = 1;
230138689Sborman 	} else
230238689Sborman 	    telnetport = 0;
230344361Sborman 	sin.sin_port = atoi(portp);
230432144Sminshall 	if (sin.sin_port == 0) {
230544361Sborman 	    sp = getservbyname(portp, "tcp");
230632144Sminshall 	    if (sp)
230732144Sminshall 		sin.sin_port = sp->s_port;
230832144Sminshall 	    else {
230944361Sborman 		printf("%s: bad port number\n", portp);
231046808Sdab 	        setuid(getuid());
231132144Sminshall 		return 0;
231232144Sminshall 	    }
231332144Sminshall 	} else {
231457213Sdab #if	!defined(htons)
231557213Sdab 	    u_short htons();
231657213Sdab #endif	/* !defined(htons) */
231732144Sminshall 	    sin.sin_port = htons(sin.sin_port);
231832144Sminshall 	}
231932144Sminshall     } else {
232032144Sminshall 	if (sp == 0) {
232132144Sminshall 	    sp = getservbyname("telnet", "tcp");
232232144Sminshall 	    if (sp == 0) {
232334849Sminshall 		fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
232446808Sdab 	        setuid(getuid());
232532144Sminshall 		return 0;
232632144Sminshall 	    }
232732144Sminshall 	    sin.sin_port = sp->s_port;
232832144Sminshall 	}
232932144Sminshall 	telnetport = 1;
233032144Sminshall     }
233137219Sminshall     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
233232144Sminshall     do {
233332144Sminshall 	net = socket(AF_INET, SOCK_STREAM, 0);
233446808Sdab 	setuid(getuid());
233532144Sminshall 	if (net < 0) {
233632144Sminshall 	    perror("telnet: socket");
233732144Sminshall 	    return 0;
233832144Sminshall 	}
233946808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
234038689Sborman 	if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
234138689Sborman 		perror("setsockopt (IP_OPTIONS)");
234238689Sborman #endif
234346808Sdab #if	defined(IPPROTO_IP) && defined(IP_TOS)
234446808Sdab 	{
234546808Sdab # if	defined(HAS_GETTOS)
234646808Sdab 	    struct tosent *tp;
234746815Sdab 	    if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
234846808Sdab 		tos = tp->t_tos;
234946808Sdab # endif
235046815Sdab 	    if (tos < 0)
235146815Sdab 		tos = 020;	/* Low Delay bit */
235246815Sdab 	    if (tos
235357213Sdab 		&& (setsockopt(net, IPPROTO_IP, IP_TOS,
235457213Sdab 		    (char *)&tos, sizeof(int)) < 0)
235546815Sdab 		&& (errno != ENOPROTOOPT))
235646815Sdab 		    perror("telnet: setsockopt (IP_TOS) (ignored)");
235746808Sdab 	}
235846808Sdab #endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
235940245Sborman 
236032144Sminshall 	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
236132144Sminshall 		perror("setsockopt (SO_DEBUG)");
236232144Sminshall 	}
236332144Sminshall 
236432144Sminshall 	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
236532144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
236632144Sminshall 	    if (host && host->h_addr_list[1]) {
236732144Sminshall 		int oerrno = errno;
236832144Sminshall 
236932144Sminshall 		fprintf(stderr, "telnet: connect to address %s: ",
237032144Sminshall 						inet_ntoa(sin.sin_addr));
237132144Sminshall 		errno = oerrno;
237232144Sminshall 		perror((char *)0);
237332144Sminshall 		host->h_addr_list++;
237432144Sminshall 		memcpy((caddr_t)&sin.sin_addr,
237532144Sminshall 			host->h_addr_list[0], host->h_length);
237632144Sminshall 		(void) NetClose(net);
237732144Sminshall 		continue;
237832144Sminshall 	    }
237932144Sminshall #endif	/* defined(h_addr) */
238032144Sminshall 	    perror("telnet: Unable to connect to remote host");
238132144Sminshall 	    return 0;
238237219Sminshall 	}
238332144Sminshall 	connected++;
238457213Sdab #if	defined(AUTHENTICATION) || defined(ENCRYPTION)
238546808Sdab 	auth_encrypt_connect(connected);
238646808Sdab #endif
238732144Sminshall     } while (connected == 0);
238844361Sborman     cmdrc(hostp, hostname);
238945008Skarels     if (autologin && user == NULL) {
239045008Skarels 	struct passwd *pw;
239145008Skarels 
239245233Sborman 	user = getenv("USER");
239345008Skarels 	if (user == NULL ||
239445233Sborman 	    (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
239545233Sborman 		if (pw = getpwuid(getuid()))
239645008Skarels 			user = pw->pw_name;
239745008Skarels 		else
239845008Skarels 			user = NULL;
239945233Sborman 	}
240045008Skarels     }
240145008Skarels     if (user) {
240246808Sdab 	env_define((unsigned char *)"USER", (unsigned char *)user);
240346808Sdab 	env_export((unsigned char *)"USER");
240445008Skarels     }
240534849Sminshall     (void) call(status, "status", "notmuch", 0);
240632144Sminshall     if (setjmp(peerdied) == 0)
240746808Sdab 	telnet(user);
240834849Sminshall     (void) NetClose(net);
240932381Sminshall     ExitString("Connection closed by foreign host.\n",1);
241032144Sminshall     /*NOTREACHED*/
241132144Sminshall }
241232144Sminshall 
241332144Sminshall #define HELPINDENT (sizeof ("connect"))
241432144Sminshall 
241532144Sminshall static char
241632144Sminshall 	openhelp[] =	"connect to a site",
241732144Sminshall 	closehelp[] =	"close current connection",
241846808Sdab 	logouthelp[] =	"forcibly logout remote user and close the connection",
241932144Sminshall 	quithelp[] =	"exit telnet",
242032144Sminshall 	statushelp[] =	"print status information",
242132144Sminshall 	helphelp[] =	"print help information",
242232144Sminshall 	sendhelp[] =	"transmit special characters ('send ?' for more)",
242332144Sminshall 	sethelp[] = 	"set operating parameters ('set ?' for more)",
242438689Sborman 	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
242532144Sminshall 	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
242638689Sborman 	slchelp[] =	"change state of special charaters ('slc ?' for more)",
242732144Sminshall 	displayhelp[] =	"display operating parameters",
242832144Sminshall #if	defined(TN3270) && defined(unix)
242932144Sminshall 	transcomhelp[] = "specify Unix command for transparent mode pipe",
243032144Sminshall #endif	/* defined(TN3270) && defined(unix) */
243157213Sdab #if	defined(AUTHENTICATION)
243246808Sdab 	authhelp[] =	"turn on (off) authentication ('auth ?' for more)",
243346808Sdab #endif
243457213Sdab #if	defined(ENCRYPTION)
243546808Sdab 	encrypthelp[] =	"turn on (off) encryption ('encrypt ?' for more)",
243646808Sdab #endif
243732144Sminshall #if	defined(unix)
243832144Sminshall 	zhelp[] =	"suspend telnet",
243943317Skfall #endif	/* defined(unix) */
244032144Sminshall 	shellhelp[] =	"invoke a subshell",
244144361Sborman 	envhelp[] =	"change environment variables ('environ ?' for more)",
244244361Sborman 	modestring[] = "try to enter line or character mode ('mode ?' for more)";
244332144Sminshall 
244456642Sralph static int	help();
244532144Sminshall 
244632144Sminshall static Command cmdtab[] = {
244738689Sborman 	{ "close",	closehelp,	bye,		1 },
244846808Sdab 	{ "logout",	logouthelp,	logout,		1 },
244938689Sborman 	{ "display",	displayhelp,	display,	0 },
245038689Sborman 	{ "mode",	modestring,	modecmd,	0 },
245138689Sborman 	{ "open",	openhelp,	tn,		0 },
245238689Sborman 	{ "quit",	quithelp,	quit,		0 },
245338689Sborman 	{ "send",	sendhelp,	sendcmd,	0 },
245438689Sborman 	{ "set",	sethelp,	setcmd,		0 },
245538689Sborman 	{ "unset",	unsethelp,	unsetcmd,	0 },
245638689Sborman 	{ "status",	statushelp,	status,		0 },
245738689Sborman 	{ "toggle",	togglestring,	toggle,		0 },
245838689Sborman 	{ "slc",	slchelp,	slccmd,		0 },
245932144Sminshall #if	defined(TN3270) && defined(unix)
246038689Sborman 	{ "transcom",	transcomhelp,	settranscom,	0 },
246132144Sminshall #endif	/* defined(TN3270) && defined(unix) */
246257213Sdab #if	defined(AUTHENTICATION)
246346808Sdab 	{ "auth",	authhelp,	auth_cmd,	0 },
246446808Sdab #endif
246557213Sdab #if	defined(ENCRYPTION)
246646808Sdab 	{ "encrypt",	encrypthelp,	encrypt_cmd,	0 },
246746808Sdab #endif
246832144Sminshall #if	defined(unix)
246938689Sborman 	{ "z",		zhelp,		suspend,	0 },
247032144Sminshall #endif	/* defined(unix) */
247132144Sminshall #if	defined(TN3270)
247238689Sborman 	{ "!",		shellhelp,	shell,		1 },
247338689Sborman #else
247438689Sborman 	{ "!",		shellhelp,	shell,		0 },
247538689Sborman #endif
247644361Sborman 	{ "environ",	envhelp,	env_cmd,	0 },
247738689Sborman 	{ "?",		helphelp,	help,		0 },
247832144Sminshall 	0
247932144Sminshall };
248032144Sminshall 
248132144Sminshall static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
248232144Sminshall static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
248332144Sminshall 
248432144Sminshall static Command cmdtab2[] = {
248538689Sborman 	{ "help",	0,		help,		0 },
248638689Sborman 	{ "escape",	escapehelp,	setescape,	0 },
248738689Sborman 	{ "crmod",	crmodhelp,	togcrmod,	0 },
248832144Sminshall 	0
248932144Sminshall };
249032144Sminshall 
249135298Sminshall 
249232144Sminshall /*
249332144Sminshall  * Call routine with argc, argv set from args (terminated by 0).
249432144Sminshall  */
249535298Sminshall 
249646808Sdab     /*VARARGS1*/
249746808Sdab     static
249835298Sminshall call(va_alist)
249946808Sdab     va_dcl
250032144Sminshall {
250135298Sminshall     va_list ap;
250235298Sminshall     typedef int (*intrtn_t)();
250335298Sminshall     intrtn_t routine;
250435298Sminshall     char *args[100];
250535298Sminshall     int argno = 0;
250635298Sminshall 
250735298Sminshall     va_start(ap);
250835298Sminshall     routine = (va_arg(ap, intrtn_t));
250935495Sminshall     while ((args[argno++] = va_arg(ap, char *)) != 0) {
251035298Sminshall 	;
251135495Sminshall     }
251235298Sminshall     va_end(ap);
251335495Sminshall     return (*routine)(argno-1, args);
251432144Sminshall }
251532144Sminshall 
251635298Sminshall 
251746808Sdab     static Command *
251832144Sminshall getcmd(name)
251946808Sdab     char *name;
252032144Sminshall {
252132144Sminshall     Command *cm;
252232144Sminshall 
252346808Sdab     if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))
252432144Sminshall 	return cm;
252546808Sdab     return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
252632144Sminshall }
252732144Sminshall 
252846808Sdab     void
252938689Sborman command(top, tbuf, cnt)
253046808Sdab     int top;
253146808Sdab     char *tbuf;
253246808Sdab     int cnt;
253332144Sminshall {
253432144Sminshall     register Command *c;
253532144Sminshall 
253632144Sminshall     setcommandmode();
253732144Sminshall     if (!top) {
253832144Sminshall 	putchar('\n');
253937219Sminshall #if	defined(unix)
254032144Sminshall     } else {
254144361Sborman 	(void) signal(SIGINT, SIG_DFL);
254244361Sborman 	(void) signal(SIGQUIT, SIG_DFL);
254332144Sminshall #endif	/* defined(unix) */
254432144Sminshall     }
254532144Sminshall     for (;;) {
254646808Sdab 	if (rlogin == _POSIX_VDISABLE)
254746808Sdab 		printf("%s> ", prompt);
254838689Sborman 	if (tbuf) {
254938689Sborman 	    register char *cp;
255038689Sborman 	    cp = line;
255138689Sborman 	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
255238689Sborman 		cnt--;
255338689Sborman 	    tbuf = 0;
255438689Sborman 	    if (cp == line || *--cp != '\n' || cp == line)
255538689Sborman 		goto getline;
255638689Sborman 	    *cp = '\0';
255746808Sdab 	    if (rlogin == _POSIX_VDISABLE)
255846808Sdab 	        printf("%s\n", line);
255938689Sborman 	} else {
256038689Sborman 	getline:
256146808Sdab 	    if (rlogin != _POSIX_VDISABLE)
256246808Sdab 		printf("%s> ", prompt);
256346808Sdab 	    if (fgets(line, sizeof(line), stdin) == NULL) {
256444361Sborman 		if (feof(stdin) || ferror(stdin)) {
256544361Sborman 		    (void) quit();
256644361Sborman 		    /*NOTREACHED*/
256744361Sborman 		}
256838689Sborman 		break;
256938689Sborman 	    }
257032144Sminshall 	}
257132144Sminshall 	if (line[0] == 0)
257232144Sminshall 	    break;
257332144Sminshall 	makeargv();
257437219Sminshall 	if (margv[0] == 0) {
257537219Sminshall 	    break;
257637219Sminshall 	}
257732144Sminshall 	c = getcmd(margv[0]);
257832144Sminshall 	if (Ambiguous(c)) {
257932144Sminshall 	    printf("?Ambiguous command\n");
258032144Sminshall 	    continue;
258132144Sminshall 	}
258232144Sminshall 	if (c == 0) {
258332144Sminshall 	    printf("?Invalid command\n");
258432144Sminshall 	    continue;
258532144Sminshall 	}
258632144Sminshall 	if (c->needconnect && !connected) {
258732144Sminshall 	    printf("?Need to be connected first.\n");
258832144Sminshall 	    continue;
258932144Sminshall 	}
259032144Sminshall 	if ((*c->handler)(margc, margv)) {
259132144Sminshall 	    break;
259232144Sminshall 	}
259332144Sminshall     }
259432144Sminshall     if (!top) {
259532144Sminshall 	if (!connected) {
259632144Sminshall 	    longjmp(toplevel, 1);
259732144Sminshall 	    /*NOTREACHED*/
259832144Sminshall 	}
259932144Sminshall #if	defined(TN3270)
260032144Sminshall 	if (shell_active == 0) {
260138689Sborman 	    setconnmode(0);
260232144Sminshall 	}
260332144Sminshall #else	/* defined(TN3270) */
260438689Sborman 	setconnmode(0);
260532144Sminshall #endif	/* defined(TN3270) */
260632144Sminshall     }
260732144Sminshall }
260832144Sminshall 
260932144Sminshall /*
261032144Sminshall  * Help command.
261132144Sminshall  */
261246808Sdab 	static
261332144Sminshall help(argc, argv)
261432144Sminshall 	int argc;
261532144Sminshall 	char *argv[];
261632144Sminshall {
261732144Sminshall 	register Command *c;
261832144Sminshall 
261932144Sminshall 	if (argc == 1) {
262032144Sminshall 		printf("Commands may be abbreviated.  Commands are:\n\n");
262132144Sminshall 		for (c = cmdtab; c->name; c++)
262238689Sborman 			if (c->help) {
262332144Sminshall 				printf("%-*s\t%s\n", HELPINDENT, c->name,
262432144Sminshall 								    c->help);
262532144Sminshall 			}
262632144Sminshall 		return 0;
262732144Sminshall 	}
262832144Sminshall 	while (--argc > 0) {
262932144Sminshall 		register char *arg;
263032144Sminshall 		arg = *++argv;
263132144Sminshall 		c = getcmd(arg);
263232144Sminshall 		if (Ambiguous(c))
263332144Sminshall 			printf("?Ambiguous help command %s\n", arg);
263432144Sminshall 		else if (c == (Command *)0)
263532144Sminshall 			printf("?Invalid help command %s\n", arg);
263632144Sminshall 		else
263732144Sminshall 			printf("%s\n", c->help);
263832144Sminshall 	}
263932144Sminshall 	return 0;
264032144Sminshall }
264138689Sborman 
264238689Sborman static char *rcname = 0;
264338689Sborman static char rcbuf[128];
264438689Sborman 
264538689Sborman cmdrc(m1, m2)
264638689Sborman 	char *m1, *m2;
264738689Sborman {
264838689Sborman     register Command *c;
264938689Sborman     FILE *rcfile;
265038689Sborman     int gotmachine = 0;
265138689Sborman     int l1 = strlen(m1);
265238689Sborman     int l2 = strlen(m2);
265338689Sborman     char m1save[64];
265438689Sborman 
265547609Sdab     if (skiprc)
265647609Sdab 	return;
265747609Sdab 
265838689Sborman     strcpy(m1save, m1);
265938689Sborman     m1 = m1save;
266038689Sborman 
266138689Sborman     if (rcname == 0) {
266238689Sborman 	rcname = getenv("HOME");
266338689Sborman 	if (rcname)
266438689Sborman 	    strcpy(rcbuf, rcname);
266538689Sborman 	else
266638689Sborman 	    rcbuf[0] = '\0';
266738689Sborman 	strcat(rcbuf, "/.telnetrc");
266838689Sborman 	rcname = rcbuf;
266938689Sborman     }
267038689Sborman 
267138689Sborman     if ((rcfile = fopen(rcname, "r")) == 0) {
267238689Sborman 	return;
267338689Sborman     }
267438689Sborman 
267538689Sborman     for (;;) {
267638689Sborman 	if (fgets(line, sizeof(line), rcfile) == NULL)
267738689Sborman 	    break;
267838689Sborman 	if (line[0] == 0)
267938689Sborman 	    break;
268038689Sborman 	if (line[0] == '#')
268138689Sborman 	    continue;
268247609Sdab 	if (gotmachine) {
268347609Sdab 	    if (!isspace(line[0]))
268447609Sdab 		gotmachine = 0;
268547609Sdab 	}
268638689Sborman 	if (gotmachine == 0) {
268738689Sborman 	    if (isspace(line[0]))
268838689Sborman 		continue;
268938689Sborman 	    if (strncasecmp(line, m1, l1) == 0)
269038689Sborman 		strncpy(line, &line[l1], sizeof(line) - l1);
269138689Sborman 	    else if (strncasecmp(line, m2, l2) == 0)
269238689Sborman 		strncpy(line, &line[l2], sizeof(line) - l2);
269347609Sdab 	    else if (strncasecmp(line, "DEFAULT", 7) == 0)
269447609Sdab 		strncpy(line, &line[7], sizeof(line) - 7);
269538689Sborman 	    else
269638689Sborman 		continue;
269747609Sdab 	    if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
269847609Sdab 		continue;
269938689Sborman 	    gotmachine = 1;
270038689Sborman 	}
270138689Sborman 	makeargv();
270238689Sborman 	if (margv[0] == 0)
270338689Sborman 	    continue;
270438689Sborman 	c = getcmd(margv[0]);
270538689Sborman 	if (Ambiguous(c)) {
270638689Sborman 	    printf("?Ambiguous command: %s\n", margv[0]);
270738689Sborman 	    continue;
270838689Sborman 	}
270938689Sborman 	if (c == 0) {
271038689Sborman 	    printf("?Invalid command: %s\n", margv[0]);
271138689Sborman 	    continue;
271238689Sborman 	}
271338689Sborman 	/*
271438689Sborman 	 * This should never happen...
271538689Sborman 	 */
271638689Sborman 	if (c->needconnect && !connected) {
271738689Sborman 	    printf("?Need to be connected first for %s.\n", margv[0]);
271838689Sborman 	    continue;
271938689Sborman 	}
272038689Sborman 	(*c->handler)(margc, margv);
272138689Sborman     }
272238689Sborman     fclose(rcfile);
272338689Sborman }
272438689Sborman 
272546808Sdab #if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
272638689Sborman 
272738689Sborman /*
272838689Sborman  * Source route is handed in as
272938689Sborman  *	[!]@hop1@hop2...[@|:]dst
273038689Sborman  * If the leading ! is present, it is a
273138689Sborman  * strict source route, otherwise it is
273238689Sborman  * assmed to be a loose source route.
273338689Sborman  *
273438689Sborman  * We fill in the source route option as
273538689Sborman  *	hop1,hop2,hop3...dest
273638689Sborman  * and return a pointer to hop1, which will
273738689Sborman  * be the address to connect() to.
273838689Sborman  *
273938689Sborman  * Arguments:
274038689Sborman  *	arg:	pointer to route list to decipher
274138689Sborman  *
274238689Sborman  *	cpp: 	If *cpp is not equal to NULL, this is a
274338689Sborman  *		pointer to a pointer to a character array
274438689Sborman  *		that should be filled in with the option.
274538689Sborman  *
274638689Sborman  *	lenp:	pointer to an integer that contains the
274738689Sborman  *		length of *cpp if *cpp != NULL.
274838689Sborman  *
274938689Sborman  * Return values:
275038689Sborman  *
275138689Sborman  *	Returns the address of the host to connect to.  If the
275238689Sborman  *	return value is -1, there was a syntax error in the
275338689Sborman  *	option, either unknown characters, or too many hosts.
275438689Sborman  *	If the return value is 0, one of the hostnames in the
275538689Sborman  *	path is unknown, and *cpp is set to point to the bad
275638689Sborman  *	hostname.
275738689Sborman  *
275838689Sborman  *	*cpp:	If *cpp was equal to NULL, it will be filled
275938689Sborman  *		in with a pointer to our static area that has
276038689Sborman  *		the option filled in.  This will be 32bit aligned.
276138689Sborman  *
276238689Sborman  *	*lenp:	This will be filled in with how long the option
276338689Sborman  *		pointed to by *cpp is.
276438689Sborman  *
276538689Sborman  */
276646808Sdab 	unsigned long
276738689Sborman sourceroute(arg, cpp, lenp)
276846808Sdab 	char	*arg;
276946808Sdab 	char	**cpp;
277046808Sdab 	int	*lenp;
277138689Sborman {
277238689Sborman 	static char lsr[44];
277357213Sdab #ifdef	sysV88
277457213Sdab 	static IOPTN ipopt;
277557213Sdab #endif
277646808Sdab 	char *cp, *cp2, *lsrp, *lsrep;
277738689Sborman 	register int tmp;
277838689Sborman 	struct in_addr sin_addr;
277938689Sborman 	register struct hostent *host = 0;
278038689Sborman 	register char c;
278138689Sborman 
278238689Sborman 	/*
278338689Sborman 	 * Verify the arguments, and make sure we have
278438689Sborman 	 * at least 7 bytes for the option.
278538689Sborman 	 */
278638689Sborman 	if (cpp == NULL || lenp == NULL)
278738689Sborman 		return((unsigned long)-1);
278838689Sborman 	if (*cpp != NULL && *lenp < 7)
278938689Sborman 		return((unsigned long)-1);
279038689Sborman 	/*
279138689Sborman 	 * Decide whether we have a buffer passed to us,
279238689Sborman 	 * or if we need to use our own static buffer.
279338689Sborman 	 */
279438689Sborman 	if (*cpp) {
279538689Sborman 		lsrp = *cpp;
279638689Sborman 		lsrep = lsrp + *lenp;
279738689Sborman 	} else {
279838689Sborman 		*cpp = lsrp = lsr;
279938689Sborman 		lsrep = lsrp + 44;
280038689Sborman 	}
280138689Sborman 
280238689Sborman 	cp = arg;
280338689Sborman 
280438689Sborman 	/*
280538689Sborman 	 * Next, decide whether we have a loose source
280638689Sborman 	 * route or a strict source route, and fill in
280738689Sborman 	 * the begining of the option.
280838689Sborman 	 */
280957213Sdab #ifndef	sysV88
281038689Sborman 	if (*cp == '!') {
281138689Sborman 		cp++;
281238689Sborman 		*lsrp++ = IPOPT_SSRR;
281338689Sborman 	} else
281438689Sborman 		*lsrp++ = IPOPT_LSRR;
281557213Sdab #else
281657213Sdab 	if (*cp == '!') {
281757213Sdab 		cp++;
281857213Sdab 		ipopt.io_type = IPOPT_SSRR;
281957213Sdab 	} else
282057213Sdab 		ipopt.io_type = IPOPT_LSRR;
282157213Sdab #endif
282238689Sborman 
282338689Sborman 	if (*cp != '@')
282438689Sborman 		return((unsigned long)-1);
282538689Sborman 
282657213Sdab #ifndef	sysV88
282738689Sborman 	lsrp++;		/* skip over length, we'll fill it in later */
282838689Sborman 	*lsrp++ = 4;
282957213Sdab #endif
283038689Sborman 
283138689Sborman 	cp++;
283238689Sborman 
283338689Sborman 	sin_addr.s_addr = 0;
283438689Sborman 
283538689Sborman 	for (c = 0;;) {
283638689Sborman 		if (c == ':')
283738689Sborman 			cp2 = 0;
283838689Sborman 		else for (cp2 = cp; c = *cp2; cp2++) {
283938689Sborman 			if (c == ',') {
284038689Sborman 				*cp2++ = '\0';
284138689Sborman 				if (*cp2 == '@')
284238689Sborman 					cp2++;
284338689Sborman 			} else if (c == '@') {
284438689Sborman 				*cp2++ = '\0';
284538689Sborman 			} else if (c == ':') {
284638689Sborman 				*cp2++ = '\0';
284738689Sborman 			} else
284838689Sborman 				continue;
284938689Sborman 			break;
285038689Sborman 		}
285138689Sborman 		if (!c)
285238689Sborman 			cp2 = 0;
285338689Sborman 
285438689Sborman 		if ((tmp = inet_addr(cp)) != -1) {
285538689Sborman 			sin_addr.s_addr = tmp;
285638689Sborman 		} else if (host = gethostbyname(cp)) {
285738689Sborman #if	defined(h_addr)
285838689Sborman 			memcpy((caddr_t)&sin_addr,
285938689Sborman 				host->h_addr_list[0], host->h_length);
286038689Sborman #else
286138689Sborman 			memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
286238689Sborman #endif
286338689Sborman 		} else {
286438689Sborman 			*cpp = cp;
286538689Sborman 			return(0);
286638689Sborman 		}
286738689Sborman 		memcpy(lsrp, (char *)&sin_addr, 4);
286838689Sborman 		lsrp += 4;
286938689Sborman 		if (cp2)
287038689Sborman 			cp = cp2;
287138689Sborman 		else
287238689Sborman 			break;
287338689Sborman 		/*
287438689Sborman 		 * Check to make sure there is space for next address
287538689Sborman 		 */
287638689Sborman 		if (lsrp + 4 > lsrep)
287738689Sborman 			return((unsigned long)-1);
287838689Sborman 	}
287957213Sdab #ifndef	sysV88
288038689Sborman 	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
288138689Sborman 		*cpp = 0;
288238689Sborman 		*lenp = 0;
288338689Sborman 		return((unsigned long)-1);
288438689Sborman 	}
288538689Sborman 	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
288638689Sborman 	*lenp = lsrp - *cpp;
288757213Sdab #else
288857213Sdab 	ipopt.io_len = lsrp - *cpp;
288957213Sdab 	if (ipopt.io_len <= 5) {		/* Is 3 better ? */
289057213Sdab 		*cpp = 0;
289157213Sdab 		*lenp = 0;
289257213Sdab 		return((unsigned long)-1);
289357213Sdab 	}
289457213Sdab 	*lenp = sizeof(ipopt);
289557213Sdab 	*cpp = (char *) &ipopt;
289657213Sdab #endif
289738689Sborman 	return(sin_addr.s_addr);
289838689Sborman }
289938689Sborman #endif
2900