xref: /csrg-svn/usr.bin/telnet/commands.c (revision 40248)
133685Sbostic /*
233685Sbostic  * Copyright (c) 1988 Regents of the University of California.
333685Sbostic  * All rights reserved.
433685Sbostic  *
533685Sbostic  * Redistribution and use in source and binary forms are permitted
634898Sbostic  * provided that the above copyright notice and this paragraph are
734898Sbostic  * duplicated in all such forms and that any documentation,
834898Sbostic  * advertising materials, and other materials related to such
934898Sbostic  * distribution and use acknowledge that the software was developed
1034898Sbostic  * by the University of California, Berkeley.  The name of the
1134898Sbostic  * University may not be used to endorse or promote products derived
1234898Sbostic  * from this software without specific prior written permission.
1334898Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434898Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534898Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633685Sbostic  */
1733685Sbostic 
1833685Sbostic #ifndef lint
19*40248Sborman static char sccsid[] = "@(#)commands.c	1.25 (Berkeley) 03/01/90";
2033685Sbostic #endif /* not lint */
2133685Sbostic 
2232144Sminshall #include <sys/types.h>
2336274Sminshall #if	defined(unix)
2436274Sminshall #include <sys/file.h>
2536274Sminshall #endif	/* defined(unix) */
2632144Sminshall #include <sys/socket.h>
2732144Sminshall #include <netinet/in.h>
2838689Sborman #ifdef	CRAY
2938689Sborman #include <sys/fcntl.h>
3038810Sborman #endif	/* CRAY */
3132144Sminshall 
3232144Sminshall #include <signal.h>
3332144Sminshall #include <netdb.h>
3432144Sminshall #include <ctype.h>
3535298Sminshall #include <varargs.h>
3632144Sminshall 
3732144Sminshall #include <arpa/telnet.h>
3832144Sminshall 
3934305Sminshall #include "general.h"
4034305Sminshall 
4132381Sminshall #include "ring.h"
4232381Sminshall 
4332144Sminshall #include "externs.h"
4432144Sminshall #include "defines.h"
4532144Sminshall #include "types.h"
4632144Sminshall 
4738689Sborman #ifdef	SRCRT
4838810Sborman # ifndef CRAY
4938810Sborman # include <netinet/in_systm.h>
5039529Sborman #  if defined(vax) || defined(tahoe)
5138810Sborman #  include <machine/endian.h>
5239529Sborman #  endif /* vax */
5338810Sborman # endif /* CRAY */
5438689Sborman #include <netinet/ip.h>
5538810Sborman #endif /* SRCRT */
5638689Sborman 
57*40248Sborman #if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS)
58*40248Sborman # define HAS_IP_TOS
59*40248Sborman #endif
6038689Sborman 
61*40248Sborman 
6232144Sminshall char	*hostname;
6338689Sborman extern char *getenv();
6432144Sminshall 
6536180Sminshall #define Ambiguous(s)	((char **)s == &ambiguous)
6632144Sminshall static char *ambiguous;		/* special return value for command routines */
6732144Sminshall 
6832144Sminshall typedef struct {
6932144Sminshall 	char	*name;		/* command name */
7038689Sborman 	char	*help;		/* help string (NULL for no help) */
7132144Sminshall 	int	(*handler)();	/* routine which executes command */
7232144Sminshall 	int	needconnect;	/* Do we need to be connected to execute? */
7332144Sminshall } Command;
7432144Sminshall 
7538689Sborman static char line[256];
7638689Sborman static char saveline[256];
7732144Sminshall static int margc;
7832144Sminshall static char *margv[20];
7932144Sminshall 
8032144Sminshall /*
8132144Sminshall  * Various utility routines.
8232144Sminshall  */
8332144Sminshall 
8436180Sminshall #if	!defined(BSD) || (BSD <= 43)
8536180Sminshall 
8636180Sminshall char	*h_errlist[] = {
8736180Sminshall 	"Error 0",
8836180Sminshall 	"Unknown host",				/* 1 HOST_NOT_FOUND */
8936180Sminshall 	"Host name lookup failure",		/* 2 TRY_AGAIN */
9036180Sminshall 	"Unknown server error",			/* 3 NO_RECOVERY */
9136180Sminshall 	"No address associated with name",	/* 4 NO_ADDRESS */
9236180Sminshall };
9336180Sminshall int	h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
9436180Sminshall 
9536274Sminshall int h_errno;		/* In some version of SunOS this is necessary */
9636180Sminshall 
9736180Sminshall /*
9836180Sminshall  * herror --
9936180Sminshall  *	print the error indicated by the h_errno value.
10036180Sminshall  */
10136180Sminshall herror(s)
10236180Sminshall 	char *s;
10336180Sminshall {
10436180Sminshall 	if (s && *s) {
10536180Sminshall 		fprintf(stderr, "%s: ", s);
10636180Sminshall 	}
10736180Sminshall 	if ((h_errno < 0) || (h_errno >= h_nerr)) {
10836180Sminshall 		fprintf(stderr, "Unknown error\n");
10936274Sminshall 	} else if (h_errno == 0) {
11036274Sminshall #if	defined(sun)
11136274Sminshall 		fprintf(stderr, "Host unknown\n");
11236274Sminshall #endif	/* defined(sun) */
11336180Sminshall 	} else {
11436180Sminshall 		fprintf(stderr, "%s\n", h_errlist[h_errno]);
11536180Sminshall 	}
11636180Sminshall }
11736180Sminshall #endif	/* !define(BSD) || (BSD <= 43) */
11836180Sminshall 
11932144Sminshall static void
12032144Sminshall makeargv()
12132144Sminshall {
12232144Sminshall     register char *cp;
12332144Sminshall     register char **argp = margv;
12432144Sminshall 
12532144Sminshall     margc = 0;
12632144Sminshall     cp = line;
12732144Sminshall     if (*cp == '!') {		/* Special case shell escape */
12838689Sborman 	strcpy(saveline, line);	/* save for shell command */
12932144Sminshall 	*argp++ = "!";		/* No room in string to get this */
13032144Sminshall 	margc++;
13132144Sminshall 	cp++;
13232144Sminshall     }
13332144Sminshall     while (*cp) {
13432144Sminshall 	while (isspace(*cp))
13532144Sminshall 	    cp++;
13632144Sminshall 	if (*cp == '\0')
13732144Sminshall 	    break;
13832144Sminshall 	*argp++ = cp;
13932144Sminshall 	margc += 1;
14032144Sminshall 	while (*cp != '\0' && !isspace(*cp))
14132144Sminshall 	    cp++;
14232144Sminshall 	if (*cp == '\0')
14332144Sminshall 	    break;
14432144Sminshall 	*cp++ = '\0';
14532144Sminshall     }
14632144Sminshall     *argp++ = 0;
14732144Sminshall }
14832144Sminshall 
14932144Sminshall 
15032144Sminshall static char **
15132144Sminshall genget(name, table, next)
15232144Sminshall char	*name;		/* name to match */
15332144Sminshall char	**table;		/* name entry in table */
15432144Sminshall char	**(*next)();	/* routine to return next entry in table */
15532144Sminshall {
15632144Sminshall 	register char *p, *q;
15732144Sminshall 	register char **c, **found;
15832144Sminshall 	register int nmatches, longest;
15932144Sminshall 
16032144Sminshall 	if (name == 0) {
16132144Sminshall 	    return 0;
16232144Sminshall 	}
16332144Sminshall 	longest = 0;
16432144Sminshall 	nmatches = 0;
16532144Sminshall 	found = 0;
16632144Sminshall 	for (c = table; (p = *c) != 0; c = (*next)(c)) {
16732144Sminshall 		for (q = name;
16832144Sminshall 		    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
16932144Sminshall 			if (*q == 0)		/* exact match? */
17032144Sminshall 				return (c);
17132144Sminshall 		if (!*q) {			/* the name was a prefix */
17232144Sminshall 			if (q - name > longest) {
17332144Sminshall 				longest = q - name;
17432144Sminshall 				nmatches = 1;
17532144Sminshall 				found = c;
17632144Sminshall 			} else if (q - name == longest)
17732144Sminshall 				nmatches++;
17832144Sminshall 		}
17932144Sminshall 	}
18032144Sminshall 	if (nmatches > 1)
18136180Sminshall 		return &ambiguous;
18232144Sminshall 	return (found);
18332144Sminshall }
18432144Sminshall 
18532144Sminshall /*
18632144Sminshall  * Make a character string into a number.
18732144Sminshall  *
18832144Sminshall  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
18932144Sminshall  */
19032144Sminshall 
19132144Sminshall static
19232144Sminshall special(s)
19332144Sminshall register char *s;
19432144Sminshall {
19532144Sminshall 	register char c;
19632144Sminshall 	char b;
19732144Sminshall 
19832144Sminshall 	switch (*s) {
19932144Sminshall 	case '^':
20032144Sminshall 		b = *++s;
20132144Sminshall 		if (b == '?') {
20232144Sminshall 		    c = b | 0x40;		/* DEL */
20332144Sminshall 		} else {
20432144Sminshall 		    c = b & 0x1f;
20532144Sminshall 		}
20632144Sminshall 		break;
20732144Sminshall 	default:
20832144Sminshall 		c = *s;
20932144Sminshall 		break;
21032144Sminshall 	}
21132144Sminshall 	return c;
21232144Sminshall }
21332144Sminshall 
21432144Sminshall /*
21532144Sminshall  * Construct a control character sequence
21632144Sminshall  * for a special character.
21732144Sminshall  */
21832144Sminshall static char *
21932144Sminshall control(c)
22040245Sborman 	register cc_t c;
22132144Sminshall {
22232144Sminshall 	static char buf[3];
22332144Sminshall 
22432144Sminshall 	if (c == 0x7f)
22532144Sminshall 		return ("^?");
22640245Sborman 	if (c == (cc_t)-1) {
22732144Sminshall 		return "off";
22832144Sminshall 	}
22932144Sminshall 	if (c >= 0x20) {
23032144Sminshall 		buf[0] = c;
23132144Sminshall 		buf[1] = 0;
23232144Sminshall 	} else {
23332144Sminshall 		buf[0] = '^';
23432144Sminshall 		buf[1] = '@'+c;
23532144Sminshall 		buf[2] = 0;
23632144Sminshall 	}
23732144Sminshall 	return (buf);
23832144Sminshall }
23932144Sminshall 
24032144Sminshall 
24132144Sminshall 
24232144Sminshall /*
24332144Sminshall  *	The following are data structures and routines for
24432144Sminshall  *	the "send" command.
24532144Sminshall  *
24632144Sminshall  */
24732144Sminshall 
24832144Sminshall struct sendlist {
24932144Sminshall     char	*name;		/* How user refers to it (case independent) */
25032144Sminshall     char	*help;		/* Help information (0 ==> no help) */
25132144Sminshall #if	defined(NOT43)
25238689Sborman     int		(*handler)();	/* Routine to perform (for special ops) */
25332144Sminshall #else	/* defined(NOT43) */
25438689Sborman     void	(*handler)();	/* Routine to perform (for special ops) */
25532144Sminshall #endif	/* defined(NOT43) */
25638689Sborman     int		what;		/* Character to be sent (<0 ==> special) */
25732144Sminshall };
25832144Sminshall 
25932144Sminshall #define	SENDQUESTION	-1
26032144Sminshall #define	SENDESCAPE	-3
26132144Sminshall 
26232144Sminshall static struct sendlist Sendlist[] = {
26338689Sborman     { "ao",	"Send Telnet Abort output",		0,	AO },
26438689Sborman     { "ayt",	"Send Telnet 'Are You There'",		0,	AYT },
26538689Sborman     { "brk",	"Send Telnet Break",			0,	BREAK },
26638689Sborman     { "ec",	"Send Telnet Erase Character",		0,	EC },
26738689Sborman     { "el",	"Send Telnet Erase Line",		0,	EL },
26838689Sborman     { "escape",	"Send current escape character",	0,	SENDESCAPE },
26938689Sborman     { "ga",	"Send Telnet 'Go Ahead' sequence",	0,	GA },
27038689Sborman     { "ip",	"Send Telnet Interrupt Process",	0,	IP },
27138689Sborman     { "nop",	"Send Telnet 'No operation'",		0,	NOP },
27238689Sborman     { "eor",	"Send Telnet 'End of Record'",		0,	EOR },
27338689Sborman     { "abort",	"Send Telnet 'Abort Process'",		0,	ABORT },
27438689Sborman     { "susp",	"Send Telnet 'Suspend Process'",	0,	SUSP },
27538689Sborman     { "eof",	"Send Telnet End of File Character",	0,	xEOF },
27638689Sborman     { "synch",	"Perform Telnet 'Synch operation'",	dosynch, SYNCH },
27738909Sborman     { "getstatus", "Send request for STATUS",		get_status, 0 },
27838689Sborman     { "?",	"Display send options",			0,	SENDQUESTION },
27932144Sminshall     { 0 }
28032144Sminshall };
28132144Sminshall 
28232144Sminshall static struct sendlist Sendlist2[] = {		/* some synonyms */
28338689Sborman     { "break",		0, 0, BREAK },
28432144Sminshall 
28538689Sborman     { "intp",		0, 0, IP },
28638689Sborman     { "interrupt",	0, 0, IP },
28738689Sborman     { "intr",		0, 0, IP },
28832144Sminshall 
28938689Sborman     { "help",		0, 0, SENDQUESTION },
29032144Sminshall 
29138689Sborman     { 0 }
29232144Sminshall };
29332144Sminshall 
29432144Sminshall static char **
29532144Sminshall getnextsend(name)
29632144Sminshall char *name;
29732144Sminshall {
29832144Sminshall     struct sendlist *c = (struct sendlist *) name;
29932144Sminshall 
30032144Sminshall     return (char **) (c+1);
30132144Sminshall }
30232144Sminshall 
30332144Sminshall static struct sendlist *
30432144Sminshall getsend(name)
30532144Sminshall char *name;
30632144Sminshall {
30732144Sminshall     struct sendlist *sl;
30832144Sminshall 
30932144Sminshall     if ((sl = (struct sendlist *)
31032144Sminshall 			genget(name, (char **) Sendlist, getnextsend)) != 0) {
31132144Sminshall 	return sl;
31232144Sminshall     } else {
31332144Sminshall 	return (struct sendlist *)
31432144Sminshall 				genget(name, (char **) Sendlist2, getnextsend);
31532144Sminshall     }
31632144Sminshall }
31732144Sminshall 
31832144Sminshall static
31932144Sminshall sendcmd(argc, argv)
32032144Sminshall int	argc;
32132144Sminshall char	**argv;
32232144Sminshall {
32332144Sminshall     int what;		/* what we are sending this time */
32432144Sminshall     int count;		/* how many bytes we are going to need to send */
32532144Sminshall     int i;
32632144Sminshall     int question = 0;	/* was at least one argument a question */
32732144Sminshall     struct sendlist *s;	/* pointer to current command */
32832144Sminshall 
32932144Sminshall     if (argc < 2) {
33032144Sminshall 	printf("need at least one argument for 'send' command\n");
33132144Sminshall 	printf("'send ?' for help\n");
33232144Sminshall 	return 0;
33332144Sminshall     }
33432144Sminshall     /*
33532144Sminshall      * First, validate all the send arguments.
33632144Sminshall      * In addition, we see how much space we are going to need, and
33732144Sminshall      * whether or not we will be doing a "SYNCH" operation (which
33832144Sminshall      * flushes the network queue).
33932144Sminshall      */
34032144Sminshall     count = 0;
34132144Sminshall     for (i = 1; i < argc; i++) {
34232144Sminshall 	s = getsend(argv[i]);
34332144Sminshall 	if (s == 0) {
34432144Sminshall 	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
34532144Sminshall 			argv[i]);
34632144Sminshall 	    return 0;
34732144Sminshall 	} else if (Ambiguous(s)) {
34832144Sminshall 	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
34932144Sminshall 			argv[i]);
35032144Sminshall 	    return 0;
35132144Sminshall 	}
35232144Sminshall 	switch (s->what) {
35332144Sminshall 	case SENDQUESTION:
35438689Sborman 	    question = 1;
35532144Sminshall 	    break;
35632144Sminshall 	case SENDESCAPE:
35732144Sminshall 	    count += 1;
35832144Sminshall 	    break;
35932144Sminshall 	case SYNCH:
36032144Sminshall 	    count += 2;
36132144Sminshall 	    break;
36232144Sminshall 	default:
36332144Sminshall 	    count += 2;
36432144Sminshall 	    break;
36532144Sminshall 	}
36632144Sminshall     }
36738689Sborman     if (!connected) {
36838689Sborman 	if (count)
36938689Sborman 	    printf("?Need to be connected first.\n");
37038689Sborman 	if (question) {
37138689Sborman 	    for (s = Sendlist; s->name; s++)
37238689Sborman 		if (s->help)
37338689Sborman 		    printf("%-15s %s\n", s->name, s->help);
37438689Sborman 	} else
37538689Sborman 	    printf("'send ?' for help\n");
37638689Sborman 	return !question;
37738689Sborman     }
37832144Sminshall     /* Now, do we have enough room? */
37932144Sminshall     if (NETROOM() < count) {
38032144Sminshall 	printf("There is not enough room in the buffer TO the network\n");
38132144Sminshall 	printf("to process your request.  Nothing will be done.\n");
38232144Sminshall 	printf("('send synch' will throw away most data in the network\n");
38332144Sminshall 	printf("buffer, if this might help.)\n");
38432144Sminshall 	return 0;
38532144Sminshall     }
38632144Sminshall     /* OK, they are all OK, now go through again and actually send */
38732144Sminshall     for (i = 1; i < argc; i++) {
38832144Sminshall 	if ((s = getsend(argv[i])) == 0) {
38932144Sminshall 	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
39032144Sminshall 	    quit();
39132144Sminshall 	    /*NOTREACHED*/
39232144Sminshall 	}
39338689Sborman 	if (s->handler) {
39438689Sborman 	    (*s->handler)(s);
39532144Sminshall 	} else {
39632144Sminshall 	    switch (what = s->what) {
39732144Sminshall 	    case SYNCH:
39832144Sminshall 		dosynch();
39932144Sminshall 		break;
40032144Sminshall 	    case SENDQUESTION:
40132144Sminshall 		for (s = Sendlist; s->name; s++) {
40238689Sborman 		    if (s->help)
40338689Sborman 			printf("%-15s %s\n", s->name, s->help);
40432144Sminshall 		}
40532144Sminshall 		question = 1;
40632144Sminshall 		break;
40732144Sminshall 	    case SENDESCAPE:
40832144Sminshall 		NETADD(escape);
40932144Sminshall 		break;
41032144Sminshall 	    default:
41132144Sminshall 		NET2ADD(IAC, what);
41232144Sminshall 		break;
41332144Sminshall 	    }
41432144Sminshall 	}
41532144Sminshall     }
41632144Sminshall     return !question;
41732144Sminshall }
41832144Sminshall 
41932144Sminshall /*
42032144Sminshall  * The following are the routines and data structures referred
42132144Sminshall  * to by the arguments to the "toggle" command.
42232144Sminshall  */
42332144Sminshall 
42432144Sminshall static
42532144Sminshall lclchars()
42632144Sminshall {
42732144Sminshall     donelclchars = 1;
42832144Sminshall     return 1;
42932144Sminshall }
43032144Sminshall 
43132144Sminshall static
43232144Sminshall togdebug()
43332144Sminshall {
43432144Sminshall #ifndef	NOT43
43532144Sminshall     if (net > 0 &&
43632144Sminshall 	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
43732144Sminshall 	    perror("setsockopt (SO_DEBUG)");
43832144Sminshall     }
43932144Sminshall #else	/* NOT43 */
44032144Sminshall     if (debug) {
44132144Sminshall 	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
44232144Sminshall 	    perror("setsockopt (SO_DEBUG)");
44332144Sminshall     } else
44432144Sminshall 	printf("Cannot turn off socket debugging\n");
44532144Sminshall #endif	/* NOT43 */
44632144Sminshall     return 1;
44732144Sminshall }
44832144Sminshall 
44932144Sminshall 
45032144Sminshall static int
45132144Sminshall togcrlf()
45232144Sminshall {
45332144Sminshall     if (crlf) {
45432144Sminshall 	printf("Will send carriage returns as telnet <CR><LF>.\n");
45532144Sminshall     } else {
45632144Sminshall 	printf("Will send carriage returns as telnet <CR><NUL>.\n");
45732144Sminshall     }
45832144Sminshall     return 1;
45932144Sminshall }
46032144Sminshall 
46138909Sborman int binmode;
46232144Sminshall 
46332144Sminshall static int
46438689Sborman togbinary(val)
46538689Sborman int val;
46632144Sminshall {
46732144Sminshall     donebinarytoggle = 1;
46832144Sminshall 
46938909Sborman     if (val >= 0) {
47038909Sborman 	binmode = val;
47138909Sborman     } else {
47238909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
47338909Sborman 				my_want_state_is_do(TELOPT_BINARY)) {
47438909Sborman 	    binmode = 1;
47538909Sborman 	} else if (my_want_state_is_wont(TELOPT_BINARY) &&
47638909Sborman 				my_want_state_is_dont(TELOPT_BINARY)) {
47738909Sborman 	    binmode = 0;
47838909Sborman 	}
47938909Sborman 	val = binmode ? 0 : 1;
48038909Sborman     }
48138909Sborman 
48238909Sborman     if (val == 1) {
48338909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
48438909Sborman 					my_want_state_is_do(TELOPT_BINARY)) {
48538689Sborman 	    printf("Already operating in binary mode with remote host.\n");
48638909Sborman 	} else {
48738909Sborman 	    printf("Negotiating binary mode with remote host.\n");
48838909Sborman 	    tel_enter_binary(3);
48938689Sborman 	}
49038909Sborman     } else {
49138909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY) &&
49238909Sborman 					my_want_state_is_dont(TELOPT_BINARY)) {
49338689Sborman 	    printf("Already in network ascii mode with remote host.\n");
49438909Sborman 	} else {
49538909Sborman 	    printf("Negotiating network ascii mode with remote host.\n");
49638909Sborman 	    tel_leave_binary(3);
49738689Sborman 	}
49832144Sminshall     }
49932144Sminshall     return 1;
50032144Sminshall }
50132144Sminshall 
50238909Sborman static int
50338909Sborman togrbinary(val)
50438909Sborman int val;
50538909Sborman {
50638909Sborman     donebinarytoggle = 1;
50732144Sminshall 
50838909Sborman     if (val == -1)
50938909Sborman 	val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
51032144Sminshall 
51138909Sborman     if (val == 1) {
51238909Sborman 	if (my_want_state_is_do(TELOPT_BINARY)) {
51338909Sborman 	    printf("Already receiving in binary mode.\n");
51438909Sborman 	} else {
51538909Sborman 	    printf("Negotiating binary mode on input.\n");
51638909Sborman 	    tel_enter_binary(1);
51738909Sborman 	}
51838909Sborman     } else {
51938909Sborman 	if (my_want_state_is_dont(TELOPT_BINARY)) {
52038909Sborman 	    printf("Already receiving in network ascii mode.\n");
52138909Sborman 	} else {
52238909Sborman 	    printf("Negotiating network ascii mode on input.\n");
52338909Sborman 	    tel_leave_binary(1);
52438909Sborman 	}
52538909Sborman     }
52638909Sborman     return 1;
52738909Sborman }
52838909Sborman 
52938909Sborman static int
53038909Sborman togxbinary(val)
53138909Sborman int val;
53238909Sborman {
53338909Sborman     donebinarytoggle = 1;
53438909Sborman 
53538909Sborman     if (val == -1)
53638909Sborman 	val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
53738909Sborman 
53838909Sborman     if (val == 1) {
53938909Sborman 	if (my_want_state_is_will(TELOPT_BINARY)) {
54038909Sborman 	    printf("Already transmitting in binary mode.\n");
54138909Sborman 	} else {
54238909Sborman 	    printf("Negotiating binary mode on output.\n");
54338909Sborman 	    tel_enter_binary(2);
54438909Sborman 	}
54538909Sborman     } else {
54638909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY)) {
54738909Sborman 	    printf("Already transmitting in network ascii mode.\n");
54838909Sborman 	} else {
54938909Sborman 	    printf("Negotiating network ascii mode on output.\n");
55038909Sborman 	    tel_leave_binary(2);
55138909Sborman 	}
55238909Sborman     }
55338909Sborman     return 1;
55438909Sborman }
55538909Sborman 
55638909Sborman 
55732144Sminshall extern int togglehelp();
55838689Sborman extern int slc_check();
55932144Sminshall 
56032144Sminshall struct togglelist {
56132144Sminshall     char	*name;		/* name of toggle */
56232144Sminshall     char	*help;		/* help message */
56332144Sminshall     int		(*handler)();	/* routine to do actual setting */
56432144Sminshall     int		*variable;
56532144Sminshall     char	*actionexplanation;
56632144Sminshall };
56732144Sminshall 
56832144Sminshall static struct togglelist Togglelist[] = {
56932144Sminshall     { "autoflush",
57038689Sborman 	"flushing of output when sending interrupt characters",
57132144Sminshall 	    0,
57238689Sborman 		&autoflush,
57338689Sborman 		    "flush output when sending interrupt characters" },
57432144Sminshall     { "autosynch",
57538689Sborman 	"automatic sending of interrupt characters in urgent mode",
57632144Sminshall 	    0,
57738689Sborman 		&autosynch,
57838689Sborman 		    "send interrupt characters in urgent mode" },
57932144Sminshall     { "binary",
58038689Sborman 	"sending and receiving of binary data",
58132144Sminshall 	    togbinary,
58238689Sborman 		0,
58338689Sborman 		    0 },
58438909Sborman     { "inbinary",
58538909Sborman 	"receiving of binary data",
58638909Sborman 	    togrbinary,
58738909Sborman 		0,
58838909Sborman 		    0 },
58938909Sborman     { "outbinary",
59038909Sborman 	"sending of binary data",
59138909Sborman 	    togxbinary,
59238909Sborman 		0,
59338909Sborman 		    0 },
59432144Sminshall     { "crlf",
59538689Sborman 	"sending carriage returns as telnet <CR><LF>",
59632144Sminshall 	    togcrlf,
59738689Sborman 		&crlf,
59838689Sborman 		    0 },
59932144Sminshall     { "crmod",
60038689Sborman 	"mapping of received carriage returns",
60132144Sminshall 	    0,
60238689Sborman 		&crmod,
60338689Sborman 		    "map carriage return on output" },
60432144Sminshall     { "localchars",
60538689Sborman 	"local recognition of certain control characters",
60632144Sminshall 	    lclchars,
60738689Sborman 		&localchars,
60838689Sborman 		    "recognize certain control characters" },
60938689Sborman     { " ", "", 0 },		/* empty line */
61038208Sminshall #if	defined(unix) && defined(TN3270)
61138920Sminshall     { "apitrace",
61238920Sminshall 	"(debugging) toggle tracing of API transactions",
61338920Sminshall 	    0,
61438920Sminshall 		&apitrace,
61538920Sminshall 		    "trace API transactions" },
61638208Sminshall     { "cursesdata",
61738208Sminshall 	"(debugging) toggle printing of hexadecimal curses data",
61838208Sminshall 	    0,
61938689Sborman 		&cursesdata,
62038689Sborman 		    "print hexadecimal representation of curses data" },
62138208Sminshall #endif	/* defined(unix) && defined(TN3270) */
62232144Sminshall     { "debug",
62338689Sborman 	"debugging",
62432144Sminshall 	    togdebug,
62538689Sborman 		&debug,
62638689Sborman 		    "turn on socket level debugging" },
62732144Sminshall     { "netdata",
62838689Sborman 	"printing of hexadecimal network data (debugging)",
62932144Sminshall 	    0,
63038689Sborman 		&netdata,
63138689Sborman 		    "print hexadecimal representation of network traffic" },
63238689Sborman     { "prettydump",
63338689Sborman 	"output of \"netdata\" to user readable format (debugging)",
63438689Sborman 	    0,
63538689Sborman 		&prettydump,
63638689Sborman 		    "print user readable output for \"netdata\"" },
63732144Sminshall     { "options",
63838689Sborman 	"viewing of options processing (debugging)",
63932144Sminshall 	    0,
64038689Sborman 		&showoptions,
64138689Sborman 		    "show option processing" },
64238208Sminshall #if	defined(unix)
64338208Sminshall     { "termdata",
64438208Sminshall 	"(debugging) toggle printing of hexadecimal terminal data",
64538208Sminshall 	    0,
64638689Sborman 		&termdata,
64738689Sborman 		    "print hexadecimal representation of terminal traffic" },
64838208Sminshall #endif	/* defined(unix) */
64932144Sminshall     { "?",
65038689Sborman 	0,
65138689Sborman 	    togglehelp },
65232144Sminshall     { "help",
65338689Sborman 	0,
65438689Sborman 	    togglehelp },
65532144Sminshall     { 0 }
65632144Sminshall };
65732144Sminshall 
65832144Sminshall static
65932144Sminshall togglehelp()
66032144Sminshall {
66132144Sminshall     struct togglelist *c;
66232144Sminshall 
66332144Sminshall     for (c = Togglelist; c->name; c++) {
66438689Sborman 	if (c->help) {
66538689Sborman 	    if (*c->help)
66638689Sborman 		printf("%-15s toggle %s\n", c->name, c->help);
66738689Sborman 	    else
66838689Sborman 		printf("\n");
66932144Sminshall 	}
67032144Sminshall     }
67138689Sborman     printf("\n");
67238689Sborman     printf("%-15s %s\n", "?", "display help information");
67332144Sminshall     return 0;
67432144Sminshall }
67532144Sminshall 
67638689Sborman static
67738689Sborman settogglehelp(set)
67838689Sborman int set;
67938689Sborman {
68038689Sborman     struct togglelist *c;
68138689Sborman 
68238689Sborman     for (c = Togglelist; c->name; c++) {
68338689Sborman 	if (c->help) {
68438689Sborman 	    if (*c->help)
68538689Sborman 		printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
68638689Sborman 						c->help);
68738689Sborman 	    else
68838689Sborman 		printf("\n");
68938689Sborman 	}
69038689Sborman     }
69138689Sborman }
69238689Sborman 
69332144Sminshall static char **
69432144Sminshall getnexttoggle(name)
69532144Sminshall char *name;
69632144Sminshall {
69732144Sminshall     struct togglelist *c = (struct togglelist *) name;
69832144Sminshall 
69932144Sminshall     return (char **) (c+1);
70032144Sminshall }
70132144Sminshall 
70232144Sminshall static struct togglelist *
70332144Sminshall gettoggle(name)
70432144Sminshall char *name;
70532144Sminshall {
70632144Sminshall     return (struct togglelist *)
70732144Sminshall 			genget(name, (char **) Togglelist, getnexttoggle);
70832144Sminshall }
70932144Sminshall 
71032144Sminshall static
71132144Sminshall toggle(argc, argv)
71232144Sminshall int	argc;
71332144Sminshall char	*argv[];
71432144Sminshall {
71532144Sminshall     int retval = 1;
71632144Sminshall     char *name;
71732144Sminshall     struct togglelist *c;
71832144Sminshall 
71932144Sminshall     if (argc < 2) {
72032144Sminshall 	fprintf(stderr,
72132144Sminshall 	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
72232144Sminshall 	return 0;
72332144Sminshall     }
72432144Sminshall     argc--;
72532144Sminshall     argv++;
72632144Sminshall     while (argc--) {
72732144Sminshall 	name = *argv++;
72832144Sminshall 	c = gettoggle(name);
72932144Sminshall 	if (Ambiguous(c)) {
73032144Sminshall 	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
73132144Sminshall 					name);
73232144Sminshall 	    return 0;
73332144Sminshall 	} else if (c == 0) {
73432144Sminshall 	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
73532144Sminshall 					name);
73632144Sminshall 	    return 0;
73732144Sminshall 	} else {
73832144Sminshall 	    if (c->variable) {
73932144Sminshall 		*c->variable = !*c->variable;		/* invert it */
74032144Sminshall 		if (c->actionexplanation) {
74132144Sminshall 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
74232144Sminshall 							c->actionexplanation);
74332144Sminshall 		}
74432144Sminshall 	    }
74532144Sminshall 	    if (c->handler) {
74638689Sborman 		retval &= (*c->handler)(-1);
74732144Sminshall 	    }
74832144Sminshall 	}
74932144Sminshall     }
75032144Sminshall     return retval;
75132144Sminshall }
75232144Sminshall 
75332144Sminshall /*
75432144Sminshall  * The following perform the "set" command.
75532144Sminshall  */
75632144Sminshall 
75738689Sborman #ifdef	USE_TERMIO
75838689Sborman struct termio new_tc = { 0 };
75938689Sborman #endif
76038689Sborman 
76132144Sminshall struct setlist {
76232144Sminshall     char *name;				/* name */
76332144Sminshall     char *help;				/* help information */
76438689Sborman     void (*handler)();
76540245Sborman     cc_t *charp;			/* where it is located at */
76632144Sminshall };
76732144Sminshall 
76832144Sminshall static struct setlist Setlist[] = {
76938689Sborman     { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
77038689Sborman     { "escape",	"character to escape back to telnet command mode", 0, &escape },
77140245Sborman     { "tracefile", "file to write trace intormation to", SetNetTrace, (cc_t *)NetTraceFile},
77232144Sminshall     { " ", "" },
77338689Sborman     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
77438689Sborman     { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp },
77538689Sborman     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
77638689Sborman     { "quit",	"character to cause an Abort process", 0, termQuitCharp },
77738689Sborman     { "eof",	"character to cause an EOF ", 0, termEofCharp },
77838689Sborman     { " ", "" },
77938689Sborman     { " ", "The following are for local editing in linemode", 0, 0 },
78038689Sborman     { "erase",	"character to use to erase a character", 0, termEraseCharp },
78138689Sborman     { "kill",	"character to use to erase a line", 0, termKillCharp },
78238689Sborman     { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
78338689Sborman     { "susp",	"character to cuase a Suspend Process", 0, termSuspCharp },
78438689Sborman     { "reprint", "character to use for line reprint", 0, termRprntCharp },
78538689Sborman     { "worderase", "character to use to erase a word", 0, termWerasCharp },
78638689Sborman     { "start",	"character to use for XON", 0, termStartCharp },
78738689Sborman     { "stop",	"character to sue for XOFF", 0, termStopCharp },
78832144Sminshall     { 0 }
78932144Sminshall };
79032144Sminshall 
79138689Sborman #ifdef	CRAY
79238689Sborman /* Work around compiler bug */
79338689Sborman _setlist_init()
79438689Sborman {
79539529Sborman 	Setlist[5].charp = &termFlushChar;
79638689Sborman 	Setlist[6].charp = &termIntChar;
79738689Sborman 	Setlist[7].charp = &termQuitChar;
79838689Sborman 	Setlist[8].charp = &termEofChar;
79938689Sborman 	Setlist[11].charp = &termEraseChar;
80038689Sborman 	Setlist[12].charp = &termKillChar;
80139529Sborman 	Setlist[13].charp = &termLiteralNextChar;
80239529Sborman 	Setlist[14].charp = &termSuspChar;
80339529Sborman 	Setlist[15].charp = &termRprntChar;
80439529Sborman 	Setlist[16].charp = &termWerasChar;
80539529Sborman 	Setlist[17].charp = &termStartChar;
80639529Sborman 	Setlist[18].charp = &termStopChar;
80738689Sborman }
80838810Sborman #endif	/* CRAY */
80938689Sborman 
81032144Sminshall static char **
81132144Sminshall getnextset(name)
81232144Sminshall char *name;
81332144Sminshall {
81432144Sminshall     struct setlist *c = (struct setlist *)name;
81532144Sminshall 
81632144Sminshall     return (char **) (c+1);
81732144Sminshall }
81832144Sminshall 
81932144Sminshall static struct setlist *
82032144Sminshall getset(name)
82132144Sminshall char *name;
82232144Sminshall {
82332144Sminshall     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
82432144Sminshall }
82532144Sminshall 
82632144Sminshall static
82732144Sminshall setcmd(argc, argv)
82832144Sminshall int	argc;
82932144Sminshall char	*argv[];
83032144Sminshall {
83132144Sminshall     int value;
83232144Sminshall     struct setlist *ct;
83338689Sborman     struct togglelist *c;
83432144Sminshall 
83538689Sborman     if (argc < 2 || argc > 3) {
83638689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
83732144Sminshall 	return 0;
83832144Sminshall     }
83938689Sborman     if ((argc == 2) &&
84038689Sborman 		((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
84138689Sborman 	for (ct = Setlist; ct->name; ct++)
84238689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
84338689Sborman 	printf("\n");
84438689Sborman 	settogglehelp(1);
84538689Sborman 	printf("%-15s %s\n", "?", "display help information");
84638689Sborman 	return 0;
84738689Sborman     }
84832144Sminshall 
84932144Sminshall     ct = getset(argv[1]);
85032144Sminshall     if (ct == 0) {
85138689Sborman 	c = gettoggle(argv[1]);
85238689Sborman 	if (c == 0) {
85338689Sborman 	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
85432144Sminshall 			argv[1]);
85538689Sborman 	    return 0;
85638689Sborman 	} else if (Ambiguous(c)) {
85738689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
85838689Sborman 			argv[1]);
85938689Sborman 	    return 0;
86038689Sborman 	}
86138689Sborman 	if (c->variable) {
86238689Sborman 	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
86338689Sborman 		*c->variable = 1;
86438689Sborman 	    else if (strcmp("off", argv[2]) == 0)
86538689Sborman 		*c->variable = 0;
86638689Sborman 	    else {
86738689Sborman 		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
86838689Sborman 		return 0;
86938689Sborman 	    }
87038689Sborman 	    if (c->actionexplanation) {
87138689Sborman 		printf("%s %s.\n", *c->variable? "Will" : "Won't",
87238689Sborman 							c->actionexplanation);
87338689Sborman 	    }
87438689Sborman 	}
87538689Sborman 	if (c->handler)
87638689Sborman 	    (*c->handler)(1);
87738689Sborman     } else if (argc != 3) {
87838689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
87932144Sminshall 	return 0;
88032144Sminshall     } else if (Ambiguous(ct)) {
88132144Sminshall 	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
88232144Sminshall 			argv[1]);
88332144Sminshall 	return 0;
88438689Sborman     } else if (ct->handler) {
88538689Sborman 	(*ct->handler)(argv[2]);
88640245Sborman 	printf("%s set to \"%s\".\n", ct->name, (unsigned char *)ct->charp);
88732144Sminshall     } else {
88832144Sminshall 	if (strcmp("off", argv[2])) {
88932144Sminshall 	    value = special(argv[2]);
89032144Sminshall 	} else {
89132144Sminshall 	    value = -1;
89232144Sminshall 	}
89340245Sborman 	*(ct->charp) = (cc_t)value;
89432144Sminshall 	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
89532144Sminshall     }
89638689Sborman     slc_check();
89732144Sminshall     return 1;
89832144Sminshall }
89938689Sborman 
90038689Sborman static
90138689Sborman unsetcmd(argc, argv)
90238689Sborman int	argc;
90338689Sborman char	*argv[];
90438689Sborman {
90538689Sborman     int value;
90638689Sborman     struct setlist *ct;
90738689Sborman     struct togglelist *c;
90838689Sborman     register char *name;
90938689Sborman 
91038689Sborman     if (argc < 2) {
91138689Sborman 	fprintf(stderr,
91238689Sborman 	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
91338689Sborman 	return 0;
91438689Sborman     }
91538689Sborman     if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) {
91638689Sborman 	for (ct = Setlist; ct->name; ct++)
91738689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
91838689Sborman 	printf("\n");
91938689Sborman 	settogglehelp(0);
92038689Sborman 	printf("%-15s %s\n", "?", "display help information");
92138689Sborman 	return 0;
92238689Sborman     }
92338689Sborman 
92438689Sborman     argc--;
92538689Sborman     argv++;
92638689Sborman     while (argc--) {
92738689Sborman 	name = *argv++;
92838689Sborman 	ct = getset(name);
92938689Sborman 	if (ct == 0) {
93038689Sborman 	    c = gettoggle(name);
93138689Sborman 	    if (c == 0) {
93238689Sborman 		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
93338689Sborman 			name);
93438689Sborman 		return 0;
93538689Sborman 	    } else if (Ambiguous(c)) {
93638689Sborman 		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
93738689Sborman 			name);
93838689Sborman 		return 0;
93938689Sborman 	    }
94038689Sborman 	    if (c->variable) {
94138689Sborman 		*c->variable = 0;
94238689Sborman 		if (c->actionexplanation) {
94338689Sborman 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
94438689Sborman 							c->actionexplanation);
94538689Sborman 		}
94638689Sborman 	    }
94738689Sborman 	    if (c->handler)
94838689Sborman 		(*c->handler)(0);
94938689Sborman 	} else if (Ambiguous(ct)) {
95038689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
95138689Sborman 			name);
95238689Sborman 	    return 0;
95338689Sborman 	} else if (ct->handler) {
95438689Sborman 	    (*ct->handler)(0);
95538689Sborman 	    printf("%s reset to \"%s\".\n", ct->name, ct->charp);
95638689Sborman 	} else {
95738689Sborman 	    value = -1;
95838689Sborman 	    *(ct->charp) = -1;
95938689Sborman 	    printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
96038689Sborman 	}
96138689Sborman     }
96238689Sborman     return 1;
96338689Sborman }
96432144Sminshall 
96532144Sminshall /*
96632144Sminshall  * The following are the data structures and routines for the
96732144Sminshall  * 'mode' command.
96832144Sminshall  */
96938689Sborman #ifdef	KLUDGELINEMODE
97038689Sborman extern int kludgelinemode;
97138689Sborman #endif
97232144Sminshall 
97332144Sminshall static
97432144Sminshall dolinemode()
97532144Sminshall {
97638689Sborman #ifdef	KLUDGELINEMODE
97738689Sborman     if (kludgelinemode)
97838689Sborman 	send_dont(TELOPT_SGA, 1);
97938689Sborman #endif
98038689Sborman     send_will(TELOPT_LINEMODE, 1);
98138689Sborman     send_dont(TELOPT_ECHO, 1);
98232144Sminshall     return 1;
98332144Sminshall }
98432144Sminshall 
98532144Sminshall static
98632144Sminshall docharmode()
98732144Sminshall {
98838689Sborman #ifdef	KLUDGELINEMODE
98938689Sborman     if (kludgelinemode)
99038689Sborman 	send_do(TELOPT_SGA, 1);
99138689Sborman     else
99238689Sborman #endif
99338689Sborman     send_wont(TELOPT_LINEMODE, 1);
99438689Sborman     send_do(TELOPT_ECHO, 1);
99538689Sborman     return 1;
99638689Sborman }
99738689Sborman 
99838689Sborman setmode(bit)
99938689Sborman {
100038689Sborman     return dolmmode(bit, 1);
100138689Sborman }
100238689Sborman 
100338689Sborman clearmode(bit)
100438689Sborman {
100538689Sborman     return dolmmode(bit, 0);
100638689Sborman }
100738689Sborman 
100838689Sborman dolmmode(bit, on)
100938689Sborman int bit, on;
101038689Sborman {
101138689Sborman     char c;
101238689Sborman     extern int linemode;
101338689Sborman 
101438689Sborman     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
101538689Sborman 	printf("?Need to have LINEMODE option enabled first.\n");
101638689Sborman 	printf("'mode ?' for help.\n");
101738689Sborman 	return 0;
101832144Sminshall     }
101938689Sborman 
102038689Sborman     if (on)
102138689Sborman 	c = (linemode | bit);
102238689Sborman     else
102338689Sborman 	c = (linemode & ~bit);
102438689Sborman     lm_mode(&c, 1, 1);
102532144Sminshall     return 1;
102632144Sminshall }
102732144Sminshall 
102838689Sborman struct modelist {
102938689Sborman 	char	*name;		/* command name */
103038689Sborman 	char	*help;		/* help string */
103138689Sborman 	int	(*handler)();	/* routine which executes command */
103238689Sborman 	int	needconnect;	/* Do we need to be connected to execute? */
103338689Sborman 	int	arg1;
103438689Sborman };
103538689Sborman 
103638689Sborman extern int modehelp();
103738689Sborman 
103838689Sborman static struct modelist ModeList[] = {
103938689Sborman     { "character", "Disable LINEMODE option",	docharmode, 1 },
104039529Sborman #ifdef	KLUDGELINEMODE
104139529Sborman     { "",	"(or disable obsolete line-by-line mode)", 0 },
104238689Sborman #endif
104338689Sborman     { "line",	"Enable LINEMODE option",	dolinemode, 1 },
104439529Sborman #ifdef	KLUDGELINEMODE
104539529Sborman     { "",	"(or enable obsolete line-by-line mode)", 0 },
104638689Sborman #endif
104738689Sborman     { "", "", 0 },
104838689Sborman     { "",	"These require the LINEMODE option to be enabled", 0 },
104938689Sborman     { "isig",	"Enable signal trapping",	setmode, 1, MODE_TRAPSIG },
105038689Sborman     { "+isig",	0,				setmode, 1, MODE_TRAPSIG },
105138689Sborman     { "-isig",	"Disable signal trapping",	clearmode, 1, MODE_TRAPSIG },
105238689Sborman     { "edit",	"Enable character editing",	setmode, 1, MODE_EDIT },
105338689Sborman     { "+edit",	0,				setmode, 1, MODE_EDIT },
105438689Sborman     { "-edit",	"Disable character editing",	clearmode, 1, MODE_EDIT },
105538689Sborman     { "help",	0,				modehelp, 0 },
105638689Sborman     { "?",	"Print help information",	modehelp, 0 },
105732144Sminshall     { 0 },
105832144Sminshall };
105932144Sminshall 
106032144Sminshall static char **
106132144Sminshall getnextmode(name)
106232144Sminshall char *name;
106332144Sminshall {
106438689Sborman     return (char **) (((struct modelist *)name)+1);
106532144Sminshall }
106632144Sminshall 
106738689Sborman static struct modelist *
106832144Sminshall getmodecmd(name)
106932144Sminshall char *name;
107032144Sminshall {
107138689Sborman     return (struct modelist *) genget(name, (char **) ModeList, getnextmode);
107232144Sminshall }
107332144Sminshall 
107438689Sborman modehelp()
107538689Sborman {
107638689Sborman     struct modelist *mt;
107738689Sborman 
107838689Sborman     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
107938689Sborman     for (mt = ModeList; mt->name; mt++) {
108038689Sborman 	if (mt->help) {
108138689Sborman 	    if (*mt->help)
108238689Sborman 		printf("%-15s %s\n", mt->name, mt->help);
108338689Sborman 	    else
108438689Sborman 		printf("\n");
108538689Sborman 	}
108638689Sborman     }
108738689Sborman     return 0;
108838689Sborman }
108938689Sborman 
109032144Sminshall static
109132144Sminshall modecmd(argc, argv)
109232144Sminshall int	argc;
109332144Sminshall char	*argv[];
109432144Sminshall {
109538689Sborman     struct modelist *mt;
109632144Sminshall 
109738689Sborman     if (argc != 2) {
109838689Sborman 	printf("'mode' command requires an argument\n");
109938689Sborman 	printf("'mode ?' for help.\n");
110038689Sborman     } else if ((mt = getmodecmd(argv[1])) == 0) {
110132144Sminshall 	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
110232144Sminshall     } else if (Ambiguous(mt)) {
110332144Sminshall 	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
110438689Sborman     } else if (mt->needconnect && !connected) {
110538689Sborman 	printf("?Need to be connected first.\n");
110638689Sborman 	printf("'mode ?' for help.\n");
110738689Sborman     } else if (mt->handler) {
110838689Sborman 	return (*mt->handler)(mt->arg1);
110932144Sminshall     }
111038689Sborman     return 0;
111132144Sminshall }
111232144Sminshall 
111332144Sminshall /*
111432144Sminshall  * The following data structures and routines implement the
111532144Sminshall  * "display" command.
111632144Sminshall  */
111732144Sminshall 
111832144Sminshall static
111932144Sminshall display(argc, argv)
112032144Sminshall int	argc;
112132144Sminshall char	*argv[];
112232144Sminshall {
112332144Sminshall #define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
112432144Sminshall 			    if (*tl->variable) { \
112532144Sminshall 				printf("will"); \
112632144Sminshall 			    } else { \
112732144Sminshall 				printf("won't"); \
112832144Sminshall 			    } \
112932144Sminshall 			    printf(" %s.\n", tl->actionexplanation); \
113032144Sminshall 			}
113132144Sminshall 
113232144Sminshall #define	doset(sl)   if (sl->name && *sl->name != ' ') { \
113338689Sborman 			if (sl->handler == 0) \
113438689Sborman 			    printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
113538689Sborman 			else \
113638689Sborman 			    printf("%-15s \"%s\"\n", sl->name, sl->charp); \
113732144Sminshall 		    }
113832144Sminshall 
113932144Sminshall     struct togglelist *tl;
114032144Sminshall     struct setlist *sl;
114132144Sminshall 
114232144Sminshall     if (argc == 1) {
114332144Sminshall 	for (tl = Togglelist; tl->name; tl++) {
114432144Sminshall 	    dotog(tl);
114532144Sminshall 	}
114632144Sminshall 	printf("\n");
114732144Sminshall 	for (sl = Setlist; sl->name; sl++) {
114832144Sminshall 	    doset(sl);
114932144Sminshall 	}
115032144Sminshall     } else {
115132144Sminshall 	int i;
115232144Sminshall 
115332144Sminshall 	for (i = 1; i < argc; i++) {
115432144Sminshall 	    sl = getset(argv[i]);
115532144Sminshall 	    tl = gettoggle(argv[i]);
115632144Sminshall 	    if (Ambiguous(sl) || Ambiguous(tl)) {
115732144Sminshall 		printf("?Ambiguous argument '%s'.\n", argv[i]);
115832144Sminshall 		return 0;
115932144Sminshall 	    } else if (!sl && !tl) {
116032144Sminshall 		printf("?Unknown argument '%s'.\n", argv[i]);
116132144Sminshall 		return 0;
116232144Sminshall 	    } else {
116332144Sminshall 		if (tl) {
116432144Sminshall 		    dotog(tl);
116532144Sminshall 		}
116632144Sminshall 		if (sl) {
116732144Sminshall 		    doset(sl);
116832144Sminshall 		}
116932144Sminshall 	    }
117032144Sminshall 	}
117132144Sminshall     }
117238689Sborman /*@*/optionstatus();
117332144Sminshall     return 1;
117432144Sminshall #undef	doset
117532144Sminshall #undef	dotog
117632144Sminshall }
117732144Sminshall 
117832144Sminshall /*
117932144Sminshall  * The following are the data structures, and many of the routines,
118032144Sminshall  * relating to command processing.
118132144Sminshall  */
118232144Sminshall 
118332144Sminshall /*
118432144Sminshall  * Set the escape character.
118532144Sminshall  */
118632144Sminshall static
118732144Sminshall setescape(argc, argv)
118832144Sminshall 	int argc;
118932144Sminshall 	char *argv[];
119032144Sminshall {
119132144Sminshall 	register char *arg;
119232144Sminshall 	char buf[50];
119332144Sminshall 
119432144Sminshall 	printf(
119532144Sminshall 	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
119632144Sminshall 				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
119732144Sminshall 	if (argc > 2)
119832144Sminshall 		arg = argv[1];
119932144Sminshall 	else {
120032144Sminshall 		printf("new escape character: ");
120134849Sminshall 		(void) gets(buf);
120232144Sminshall 		arg = buf;
120332144Sminshall 	}
120432144Sminshall 	if (arg[0] != '\0')
120532144Sminshall 		escape = arg[0];
120632144Sminshall 	if (!In3270) {
120732144Sminshall 		printf("Escape character is '%s'.\n", control(escape));
120832144Sminshall 	}
120934849Sminshall 	(void) fflush(stdout);
121032144Sminshall 	return 1;
121132144Sminshall }
121232144Sminshall 
121332144Sminshall /*VARARGS*/
121432144Sminshall static
121532144Sminshall togcrmod()
121632144Sminshall {
121732144Sminshall     crmod = !crmod;
121832144Sminshall     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
121932144Sminshall     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
122034849Sminshall     (void) fflush(stdout);
122132144Sminshall     return 1;
122232144Sminshall }
122332144Sminshall 
122432144Sminshall /*VARARGS*/
122532144Sminshall suspend()
122632144Sminshall {
122738689Sborman #ifdef	SIGTSTP
122837219Sminshall     setcommandmode();
122937219Sminshall     {
123037219Sminshall 	long oldrows, oldcols, newrows, newcols;
123137219Sminshall 
123237219Sminshall 	TerminalWindowSize(&oldrows, &oldcols);
123334849Sminshall 	(void) kill(0, SIGTSTP);
123437219Sminshall 	TerminalWindowSize(&newrows, &newcols);
123537219Sminshall 	if ((oldrows != newrows) || (oldcols != newcols)) {
123637219Sminshall 	    if (connected) {
123737219Sminshall 		sendnaws();
123837219Sminshall 	    }
123937219Sminshall 	}
124037219Sminshall     }
124137219Sminshall     /* reget parameters in case they were changed */
124237219Sminshall     TerminalSaveState();
124338689Sborman     setconnmode(0);
124438689Sborman #else
124538689Sborman     printf("Suspend is not supported.  Try the '!' command instead\n");
124638689Sborman #endif
124737219Sminshall     return 1;
124832144Sminshall }
124932144Sminshall 
125038689Sborman #if	!defined(TN3270)
125138689Sborman shell(argc, argv)
125238689Sborman int argc;
125338689Sborman char *argv[];
125438689Sborman {
125538689Sborman     extern char *rindex();
125638689Sborman     char cmdbuf[256];
125738689Sborman 
125838689Sborman     setcommandmode();
125938689Sborman     switch(vfork()) {
126038689Sborman     case -1:
126138689Sborman 	perror("Fork failed\n");
126238689Sborman 	break;
126338689Sborman 
126438689Sborman     case 0:
126538689Sborman 	{
126638689Sborman 	    /*
126738689Sborman 	     * Fire up the shell in the child.
126838689Sborman 	     */
126938689Sborman 	    register char *shell, *shellname;
127038689Sborman 
127138689Sborman 	    shell = getenv("SHELL");
127238689Sborman 	    if (shell == NULL)
127338689Sborman 		shell = "/bin/sh";
127438689Sborman 	    if ((shellname = rindex(shell, '/')) == 0)
127538689Sborman 		shellname = shell;
127638689Sborman 	    else
127738689Sborman 		shellname++;
127838689Sborman 	    if (argc > 1)
127938689Sborman 		execl(shell, shellname, "-c", &saveline[1], 0);
128038689Sborman 	    else
128138689Sborman 		execl(shell, shellname, 0);
128238689Sborman 	    perror("Execl");
128338689Sborman 	    _exit(1);
128438689Sborman 	}
128538689Sborman     default:
128638689Sborman 	    wait((int *)0);	/* Wait for the shell to complete */
128738689Sborman     }
128838689Sborman }
128938689Sborman #endif	/* !defined(TN3270) */
129038689Sborman 
129132144Sminshall /*VARARGS*/
129232144Sminshall static
129332144Sminshall bye(argc, argv)
129432144Sminshall int	argc;		/* Number of arguments */
129532144Sminshall char	*argv[];	/* arguments */
129632144Sminshall {
129732144Sminshall     if (connected) {
129834849Sminshall 	(void) shutdown(net, 2);
129932144Sminshall 	printf("Connection closed.\n");
130034849Sminshall 	(void) NetClose(net);
130132144Sminshall 	connected = 0;
130232144Sminshall 	/* reset options */
130332144Sminshall 	tninit();
130432144Sminshall #if	defined(TN3270)
130532144Sminshall 	SetIn3270();		/* Get out of 3270 mode */
130632144Sminshall #endif	/* defined(TN3270) */
130732144Sminshall     }
130832144Sminshall     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
130932144Sminshall 	longjmp(toplevel, 1);
131032144Sminshall 	/* NOTREACHED */
131132144Sminshall     }
131232144Sminshall     return 1;			/* Keep lint, etc., happy */
131332144Sminshall }
131432144Sminshall 
131532144Sminshall /*VARARGS*/
131632144Sminshall quit()
131732144Sminshall {
131832144Sminshall 	(void) call(bye, "bye", "fromquit", 0);
131932144Sminshall 	Exit(0);
132032144Sminshall 	return 1;			/* just to keep lint happy */
132132144Sminshall }
132238689Sborman 
132338689Sborman /*
132438689Sborman  * The SLC command.
132538689Sborman  */
132632144Sminshall 
132738689Sborman struct slclist {
132838689Sborman 	char	*name;
132938689Sborman 	char	*help;
133038689Sborman 	int	(*handler)();
133138689Sborman 	int	arg;
133238689Sborman };
133338689Sborman 
133438689Sborman extern int slc_help();
133538689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate();
133638689Sborman 
133738689Sborman struct slclist SlcList[] = {
133838689Sborman     { "export",	"Use local special character definitions",
133938689Sborman 						slc_mode_export,	0 },
134038689Sborman     { "import",	"Use remote special character definitions",
134138689Sborman 						slc_mode_import,	1 },
134238689Sborman     { "check",	"Verify remote special character definitions",
134338689Sborman 						slc_mode_import,	0 },
134438689Sborman     { "help",	0,				slc_help,		0 },
134538689Sborman     { "?",	"Print help information",	slc_help,		0 },
134638689Sborman     { 0 },
134738689Sborman };
134838689Sborman 
134938689Sborman static
135038689Sborman slc_help()
135138689Sborman {
135238689Sborman     struct slclist *c;
135338689Sborman 
135438689Sborman     for (c = SlcList; c->name; c++) {
135538689Sborman 	if (c->help) {
135638689Sborman 	    if (*c->help)
135738689Sborman 		printf("%-15s %s\n", c->name, c->help);
135838689Sborman 	    else
135938689Sborman 		printf("\n");
136038689Sborman 	}
136138689Sborman     }
136238689Sborman }
136338689Sborman 
136438689Sborman static char **
136538689Sborman getnextslc(name)
136638689Sborman char *name;
136738689Sborman {
136838689Sborman     return (char **)(((struct slclist *)name)+1);
136938689Sborman }
137038689Sborman 
137138689Sborman static struct slclist *
137238689Sborman getslc(name)
137338689Sborman char *name;
137438689Sborman {
137538689Sborman     return (struct slclist *)genget(name, (char **) SlcList, getnextslc);
137638689Sborman }
137738689Sborman 
137838689Sborman static
137938689Sborman slccmd(argc, argv)
138038689Sborman int	argc;
138138689Sborman char	*argv[];
138238689Sborman {
138338689Sborman     struct slclist *c;
138438689Sborman 
138538689Sborman     if (argc != 2) {
138638689Sborman 	fprintf(stderr,
138738689Sborman 	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
138838689Sborman 	return 0;
138938689Sborman     }
139038689Sborman     c = getslc(argv[1]);
139138689Sborman     if (c == 0) {
139238689Sborman         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
139338689Sborman     				argv[1]);
139438689Sborman         return 0;
139538689Sborman     }
139638689Sborman     if (Ambiguous(c)) {
139738689Sborman         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
139838689Sborman     				argv[1]);
139938689Sborman         return 0;
140038689Sborman     }
140138689Sborman     (*c->handler)(c->arg);
140238689Sborman     slcstate();
140338689Sborman     return 1;
140438689Sborman }
140538689Sborman 
140636274Sminshall #if	defined(unix)
140732144Sminshall /*
140836274Sminshall  * Some information about our file descriptors.
140936274Sminshall  */
141036274Sminshall 
141136274Sminshall char *
141236274Sminshall decodeflags(mask)
141336274Sminshall int mask;
141436274Sminshall {
141536274Sminshall     static char buffer[100];
141636274Sminshall #define do(m,s) \
141736274Sminshall 	if (mask&(m)) { \
141836274Sminshall 	    strcat(buffer, (s)); \
141936274Sminshall 	}
142036274Sminshall 
142136274Sminshall     buffer[0] = 0;			/* Terminate it */
142236274Sminshall 
142336274Sminshall #ifdef FREAD
142436274Sminshall     do(FREAD, " FREAD");
142536274Sminshall #endif
142636274Sminshall #ifdef FWRITE
142736274Sminshall     do(FWRITE, " FWRITE");
142836274Sminshall #endif
142936274Sminshall #ifdef F_DUPFP
143036274Sminshall     do(F_DUPFD, " F_DUPFD");
143136274Sminshall #endif
143236274Sminshall #ifdef FNDELAY
143336274Sminshall     do(FNDELAY, " FNDELAY");
143436274Sminshall #endif
143536274Sminshall #ifdef FAPPEND
143636274Sminshall     do(FAPPEND, " FAPPEND");
143736274Sminshall #endif
143836274Sminshall #ifdef FMARK
143936274Sminshall     do(FMARK, " FMARK");
144036274Sminshall #endif
144136274Sminshall #ifdef FDEFER
144236274Sminshall     do(FDEFER, " FDEFER");
144336274Sminshall #endif
144436274Sminshall #ifdef FASYNC
144536274Sminshall     do(FASYNC, " FASYNC");
144636274Sminshall #endif
144736274Sminshall #ifdef FSHLOCK
144836274Sminshall     do(FSHLOCK, " FSHLOCK");
144936274Sminshall #endif
145036274Sminshall #ifdef FEXLOCK
145136274Sminshall     do(FEXLOCK, " FEXLOCK");
145236274Sminshall #endif
145336274Sminshall #ifdef FCREAT
145436274Sminshall     do(FCREAT, " FCREAT");
145536274Sminshall #endif
145636274Sminshall #ifdef FTRUNC
145736274Sminshall     do(FTRUNC, " FTRUNC");
145836274Sminshall #endif
145936274Sminshall #ifdef FEXCL
146036274Sminshall     do(FEXCL, " FEXCL");
146136274Sminshall #endif
146236274Sminshall 
146336274Sminshall     return buffer;
146436274Sminshall }
146536274Sminshall #undef do
146636274Sminshall 
146736274Sminshall static void
146836274Sminshall filestuff(fd)
146936274Sminshall int fd;
147036274Sminshall {
147136274Sminshall     int res;
147236274Sminshall 
147338689Sborman #ifdef	F_GETOWN
147438689Sborman     setconnmode(0);
147536274Sminshall     res = fcntl(fd, F_GETOWN, 0);
147636274Sminshall     setcommandmode();
147736274Sminshall 
147836274Sminshall     if (res == -1) {
147936274Sminshall 	perror("fcntl");
148036274Sminshall 	return;
148136274Sminshall     }
148236274Sminshall     printf("\tOwner is %d.\n", res);
148338689Sborman #endif
148436274Sminshall 
148538689Sborman     setconnmode(0);
148636274Sminshall     res = fcntl(fd, F_GETFL, 0);
148736274Sminshall     setcommandmode();
148836274Sminshall 
148936274Sminshall     if (res == -1) {
149036274Sminshall 	perror("fcntl");
149136274Sminshall 	return;
149236274Sminshall     }
149336274Sminshall     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
149436274Sminshall }
149536274Sminshall 
149636274Sminshall 
149736274Sminshall #endif	/* defined(unix) */
149836274Sminshall 
149936274Sminshall /*
150032144Sminshall  * Print status about the connection.
150132144Sminshall  */
150234849Sminshall /*ARGSUSED*/
150332144Sminshall static
150432144Sminshall status(argc, argv)
150532144Sminshall int	argc;
150632144Sminshall char	*argv[];
150732144Sminshall {
150832144Sminshall     if (connected) {
150932144Sminshall 	printf("Connected to %s.\n", hostname);
151036242Sminshall 	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
151138689Sborman 	    int mode = getconnmode();
151238689Sborman 
151338689Sborman 	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
151438689Sborman 		printf("Operating with LINEMODE option\n");
151538689Sborman 		printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
151638689Sborman 		printf("%s catching of signals\n",
151738689Sborman 					(mode&MODE_TRAPSIG) ? "Local" : "No");
151838689Sborman 		slcstate();
151938689Sborman #ifdef	KLUDGELINEMODE
152039529Sborman 	    } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
152138689Sborman 		printf("Operating in obsolete linemode\n");
152238689Sborman #endif
152338689Sborman 	    } else {
152438689Sborman 		printf("Operating in single character mode\n");
152538689Sborman 		if (localchars)
152638689Sborman 		    printf("Catching signals locally\n");
152732144Sminshall 	    }
152838689Sborman 	    printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
152938689Sborman 	    if (my_want_state_is_will(TELOPT_LFLOW))
153038689Sborman 		printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
153132144Sminshall 	}
153232144Sminshall     } else {
153332144Sminshall 	printf("No connection.\n");
153432144Sminshall     }
153532144Sminshall #   if !defined(TN3270)
153632144Sminshall     printf("Escape character is '%s'.\n", control(escape));
153734849Sminshall     (void) fflush(stdout);
153832144Sminshall #   else /* !defined(TN3270) */
153932144Sminshall     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
154032144Sminshall 	printf("Escape character is '%s'.\n", control(escape));
154132144Sminshall     }
154232144Sminshall #   if defined(unix)
154336242Sminshall     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
154436242Sminshall 	printf("SIGIO received %d time%s.\n",
154536242Sminshall 				sigiocount, (sigiocount == 1)? "":"s");
154636274Sminshall 	if (In3270) {
154736274Sminshall 	    printf("Process ID %d, process group %d.\n",
154836274Sminshall 					    getpid(), getpgrp(getpid()));
154936274Sminshall 	    printf("Terminal input:\n");
155036274Sminshall 	    filestuff(tin);
155136274Sminshall 	    printf("Terminal output:\n");
155236274Sminshall 	    filestuff(tout);
155336274Sminshall 	    printf("Network socket:\n");
155436274Sminshall 	    filestuff(net);
155536274Sminshall 	}
155636242Sminshall     }
155732144Sminshall     if (In3270 && transcom) {
155832144Sminshall        printf("Transparent mode command is '%s'.\n", transcom);
155932144Sminshall     }
156032144Sminshall #   endif /* defined(unix) */
156134849Sminshall     (void) fflush(stdout);
156232144Sminshall     if (In3270) {
156332144Sminshall 	return 0;
156432144Sminshall     }
156532144Sminshall #   endif /* defined(TN3270) */
156632144Sminshall     return 1;
156732144Sminshall }
156832144Sminshall 
156932144Sminshall 
1570*40248Sborman #if	defined(NEED_GETTOS)
157140245Sborman struct tosent {
157240245Sborman 	char	*t_name;	/* name */
157340245Sborman 	char	**t_aliases;	/* alias list */
157440245Sborman 	char	*t_proto;	/* protocol */
157540245Sborman 	int	t_tos;		/* Type Of Service bits */
157640245Sborman };
157732144Sminshall 
157840245Sborman struct tosent *
157940245Sborman gettosbyname(name, proto)
158040245Sborman char *name, *proto;
158140245Sborman {
158240245Sborman 	static struct tosent te;
158340245Sborman 	static char *aliasp = 0;
158440245Sborman 
158540245Sborman 	te.t_name = name;
158640245Sborman 	te.t_aliases = &aliasp;
158740245Sborman 	te.t_proto = proto;
158840245Sborman 	te.t_tos = 020; /* Low Delay bit */
158940245Sborman 	return(&te);
159040245Sborman }
159140245Sborman #endif
159240245Sborman 
159332144Sminshall int
159432144Sminshall tn(argc, argv)
159532144Sminshall 	int argc;
159632144Sminshall 	char *argv[];
159732144Sminshall {
159832144Sminshall     register struct hostent *host = 0;
159932144Sminshall     struct sockaddr_in sin;
160032144Sminshall     struct servent *sp = 0;
160132144Sminshall     static char	hnamebuf[32];
160238689Sborman     unsigned long temp, inet_addr();
160337219Sminshall     extern char *inet_ntoa();
160438689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
160538689Sborman     char *srp = 0, *strrchr();
160638689Sborman     unsigned long sourceroute(), srlen;
160738689Sborman #endif
1608*40248Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS)
160940245Sborman     struct tosent *tp;
1610*40248Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
161132144Sminshall 
161232144Sminshall 
161332144Sminshall     if (connected) {
161432144Sminshall 	printf("?Already connected to %s\n", hostname);
161532144Sminshall 	return 0;
161632144Sminshall     }
161732144Sminshall     if (argc < 2) {
161832144Sminshall 	(void) strcpy(line, "Connect ");
161932144Sminshall 	printf("(to) ");
162034849Sminshall 	(void) gets(&line[strlen(line)]);
162132144Sminshall 	makeargv();
162232144Sminshall 	argc = margc;
162332144Sminshall 	argv = margv;
162432144Sminshall     }
162532144Sminshall     if ((argc < 2) || (argc > 3)) {
162632144Sminshall 	printf("usage: %s host-name [port]\n", argv[0]);
162732144Sminshall 	return 0;
162832144Sminshall     }
162938689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
163038689Sborman     if (argv[1][0] == '@' || argv[1][0] == '!') {
163138689Sborman 	if ((hostname = strrchr(argv[1], ':')) == NULL)
163238689Sborman 	    hostname = strrchr(argv[1], '@');
163338689Sborman 	hostname++;
163438689Sborman 	srp = 0;
163538689Sborman 	temp = sourceroute(argv[1], &srp, &srlen);
163638689Sborman 	if (temp == 0) {
163738689Sborman 	    herror(srp);
163838689Sborman 	    return 0;
163938689Sborman 	} else if (temp == -1) {
164038689Sborman 	    printf("Bad source route option: %s\n", argv[1]);
164138689Sborman 	    return 0;
164238689Sborman 	} else {
164338689Sborman 	    sin.sin_addr.s_addr = temp;
164438689Sborman 	    sin.sin_family = AF_INET;
164538689Sborman 	}
164632144Sminshall     } else {
164738689Sborman #endif
164838689Sborman 	temp = inet_addr(argv[1]);
164938689Sborman 	if (temp != (unsigned long) -1) {
165038689Sborman 	    sin.sin_addr.s_addr = temp;
165138689Sborman 	    sin.sin_family = AF_INET;
165238689Sborman 	    (void) strcpy(hnamebuf, argv[1]);
165338689Sborman 	    hostname = hnamebuf;
165438689Sborman 	} else {
165538689Sborman 	    host = gethostbyname(argv[1]);
165638689Sborman 	    if (host) {
165738689Sborman 		sin.sin_family = host->h_addrtype;
165832144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
165938689Sborman 		memcpy((caddr_t)&sin.sin_addr,
166032144Sminshall 				host->h_addr_list[0], host->h_length);
166132144Sminshall #else	/* defined(h_addr) */
166238689Sborman 		memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
166332144Sminshall #endif	/* defined(h_addr) */
166438689Sborman 		hostname = host->h_name;
166538689Sborman 	    } else {
166638689Sborman 		herror(argv[1]);
166738689Sborman 		return 0;
166838689Sborman 	    }
166932144Sminshall 	}
167038689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
167132144Sminshall     }
167238689Sborman #endif
167332144Sminshall     if (argc == 3) {
167438689Sborman 	int tmp;
167538689Sborman 
167638689Sborman 	if (*argv[2] == '-') {
167738689Sborman 	    argv[2]++;
167838689Sborman 	    telnetport = 1;
167938689Sborman 	} else
168038689Sborman 	    telnetport = 0;
168132144Sminshall 	sin.sin_port = atoi(argv[2]);
168232144Sminshall 	if (sin.sin_port == 0) {
168332144Sminshall 	    sp = getservbyname(argv[2], "tcp");
168432144Sminshall 	    if (sp)
168532144Sminshall 		sin.sin_port = sp->s_port;
168632144Sminshall 	    else {
168732144Sminshall 		printf("%s: bad port number\n", argv[2]);
168832144Sminshall 		return 0;
168932144Sminshall 	    }
169032144Sminshall 	} else {
169134849Sminshall #if	!defined(htons)
169234849Sminshall 	    u_short htons();
169334849Sminshall #endif	/* !defined(htons) */
169432144Sminshall 	    sin.sin_port = htons(sin.sin_port);
169532144Sminshall 	}
169632144Sminshall     } else {
169732144Sminshall 	if (sp == 0) {
169832144Sminshall 	    sp = getservbyname("telnet", "tcp");
169932144Sminshall 	    if (sp == 0) {
170034849Sminshall 		fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
170132144Sminshall 		return 0;
170232144Sminshall 	    }
170332144Sminshall 	    sin.sin_port = sp->s_port;
170432144Sminshall 	}
170532144Sminshall 	telnetport = 1;
170632144Sminshall     }
170737219Sminshall     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
170832144Sminshall     do {
170932144Sminshall 	net = socket(AF_INET, SOCK_STREAM, 0);
171032144Sminshall 	if (net < 0) {
171132144Sminshall 	    perror("telnet: socket");
171232144Sminshall 	    return 0;
171332144Sminshall 	}
171438689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
171538689Sborman 	if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
171638689Sborman 		perror("setsockopt (IP_OPTIONS)");
171738689Sborman #endif
1718*40248Sborman #if	defined(HAS_IP_TOS) || defined(NEED_GETTOS)
171940245Sborman 	if ((tp = gettosbyname("telnet", "tcp")) &&
172040245Sborman 	    (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
172140245Sborman 		perror("telnet: setsockopt TOS (ignored)");
1722*40248Sborman #endif	/* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
172340245Sborman 
172432144Sminshall 	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
172532144Sminshall 		perror("setsockopt (SO_DEBUG)");
172632144Sminshall 	}
172732144Sminshall 
172832144Sminshall 	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
172932144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
173032144Sminshall 	    if (host && host->h_addr_list[1]) {
173132144Sminshall 		int oerrno = errno;
173232144Sminshall 
173332144Sminshall 		fprintf(stderr, "telnet: connect to address %s: ",
173432144Sminshall 						inet_ntoa(sin.sin_addr));
173532144Sminshall 		errno = oerrno;
173632144Sminshall 		perror((char *)0);
173732144Sminshall 		host->h_addr_list++;
173832144Sminshall 		memcpy((caddr_t)&sin.sin_addr,
173932144Sminshall 			host->h_addr_list[0], host->h_length);
174032144Sminshall 		(void) NetClose(net);
174132144Sminshall 		continue;
174232144Sminshall 	    }
174332144Sminshall #endif	/* defined(h_addr) */
174432144Sminshall 	    perror("telnet: Unable to connect to remote host");
174532144Sminshall 	    return 0;
174637219Sminshall 	}
174732144Sminshall 	connected++;
174832144Sminshall     } while (connected == 0);
174938689Sborman     cmdrc(argv[1], hostname);
175034849Sminshall     (void) call(status, "status", "notmuch", 0);
175132144Sminshall     if (setjmp(peerdied) == 0)
175232144Sminshall 	telnet();
175334849Sminshall     (void) NetClose(net);
175432381Sminshall     ExitString("Connection closed by foreign host.\n",1);
175532144Sminshall     /*NOTREACHED*/
175632144Sminshall }
175732144Sminshall 
175832144Sminshall 
175932144Sminshall #define HELPINDENT (sizeof ("connect"))
176032144Sminshall 
176132144Sminshall static char
176232144Sminshall 	openhelp[] =	"connect to a site",
176332144Sminshall 	closehelp[] =	"close current connection",
176432144Sminshall 	quithelp[] =	"exit telnet",
176532144Sminshall 	statushelp[] =	"print status information",
176632144Sminshall 	helphelp[] =	"print help information",
176732144Sminshall 	sendhelp[] =	"transmit special characters ('send ?' for more)",
176832144Sminshall 	sethelp[] = 	"set operating parameters ('set ?' for more)",
176938689Sborman 	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
177032144Sminshall 	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
177138689Sborman 	slchelp[] =	"change state of special charaters ('slc ?' for more)",
177232144Sminshall 	displayhelp[] =	"display operating parameters",
177332144Sminshall #if	defined(TN3270) && defined(unix)
177432144Sminshall 	transcomhelp[] = "specify Unix command for transparent mode pipe",
177532144Sminshall #endif	/* defined(TN3270) && defined(unix) */
177632144Sminshall #if	defined(unix)
177732144Sminshall 	zhelp[] =	"suspend telnet",
177832144Sminshall #endif	/* defined(unix */
177932144Sminshall 	shellhelp[] =	"invoke a subshell",
178038689Sborman 	modestring[] = "try to enter line-by-line or character-at-a-time mode";
178132144Sminshall 
178232144Sminshall extern int	help(), shell();
178332144Sminshall 
178432144Sminshall static Command cmdtab[] = {
178538689Sborman 	{ "close",	closehelp,	bye,		1 },
178638689Sborman 	{ "display",	displayhelp,	display,	0 },
178738689Sborman 	{ "mode",	modestring,	modecmd,	0 },
178838689Sborman 	{ "open",	openhelp,	tn,		0 },
178938689Sborman 	{ "quit",	quithelp,	quit,		0 },
179038689Sborman 	{ "send",	sendhelp,	sendcmd,	0 },
179138689Sborman 	{ "set",	sethelp,	setcmd,		0 },
179238689Sborman 	{ "unset",	unsethelp,	unsetcmd,	0 },
179338689Sborman 	{ "status",	statushelp,	status,		0 },
179438689Sborman 	{ "toggle",	togglestring,	toggle,		0 },
179538689Sborman 	{ "slc",	slchelp,	slccmd,		0 },
179632144Sminshall #if	defined(TN3270) && defined(unix)
179738689Sborman 	{ "transcom",	transcomhelp,	settranscom,	0 },
179832144Sminshall #endif	/* defined(TN3270) && defined(unix) */
179932144Sminshall #if	defined(unix)
180038689Sborman 	{ "z",		zhelp,		suspend,	0 },
180132144Sminshall #endif	/* defined(unix) */
180232144Sminshall #if	defined(TN3270)
180338689Sborman 	{ "!",		shellhelp,	shell,		1 },
180438689Sborman #else
180538689Sborman 	{ "!",		shellhelp,	shell,		0 },
180638689Sborman #endif
180738689Sborman 	{ "?",		helphelp,	help,		0 },
180832144Sminshall 	0
180932144Sminshall };
181032144Sminshall 
181132144Sminshall static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
181232144Sminshall static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
181332144Sminshall 
181432144Sminshall static Command cmdtab2[] = {
181538689Sborman 	{ "help",	0,		help,		0 },
181638689Sborman 	{ "escape",	escapehelp,	setescape,	0 },
181738689Sborman 	{ "crmod",	crmodhelp,	togcrmod,	0 },
181832144Sminshall 	0
181932144Sminshall };
182032144Sminshall 
182135298Sminshall 
182232144Sminshall /*
182332144Sminshall  * Call routine with argc, argv set from args (terminated by 0).
182432144Sminshall  */
182535298Sminshall 
182635417Sminshall /*VARARGS1*/
182732144Sminshall static
182835298Sminshall call(va_alist)
182935298Sminshall va_dcl
183032144Sminshall {
183135298Sminshall     va_list ap;
183235298Sminshall     typedef int (*intrtn_t)();
183335298Sminshall     intrtn_t routine;
183435298Sminshall     char *args[100];
183535298Sminshall     int argno = 0;
183635298Sminshall 
183735298Sminshall     va_start(ap);
183835298Sminshall     routine = (va_arg(ap, intrtn_t));
183935495Sminshall     while ((args[argno++] = va_arg(ap, char *)) != 0) {
184035298Sminshall 	;
184135495Sminshall     }
184235298Sminshall     va_end(ap);
184335495Sminshall     return (*routine)(argno-1, args);
184432144Sminshall }
184532144Sminshall 
184635298Sminshall 
184732144Sminshall static char **
184832144Sminshall getnextcmd(name)
184932144Sminshall char *name;
185032144Sminshall {
185132144Sminshall     Command *c = (Command *) name;
185232144Sminshall 
185332144Sminshall     return (char **) (c+1);
185432144Sminshall }
185532144Sminshall 
185632144Sminshall static Command *
185732144Sminshall getcmd(name)
185832144Sminshall char *name;
185932144Sminshall {
186032144Sminshall     Command *cm;
186132144Sminshall 
186232144Sminshall     if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
186332144Sminshall 	return cm;
186432144Sminshall     } else {
186532144Sminshall 	return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
186632144Sminshall     }
186732144Sminshall }
186832144Sminshall 
186932144Sminshall void
187038689Sborman command(top, tbuf, cnt)
187132144Sminshall 	int top;
187238689Sborman 	char *tbuf;
187338689Sborman 	int cnt;
187432144Sminshall {
187532144Sminshall     register Command *c;
187632144Sminshall 
187732144Sminshall     setcommandmode();
187832144Sminshall     if (!top) {
187932144Sminshall 	putchar('\n');
188037219Sminshall #if	defined(unix)
188132144Sminshall     } else {
188232144Sminshall 	signal(SIGINT, SIG_DFL);
188332144Sminshall 	signal(SIGQUIT, SIG_DFL);
188432144Sminshall #endif	/* defined(unix) */
188532144Sminshall     }
188632144Sminshall     for (;;) {
188732144Sminshall 	printf("%s> ", prompt);
188838689Sborman 	if (tbuf) {
188938689Sborman 	    register char *cp;
189038689Sborman 	    cp = line;
189138689Sborman 	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
189238689Sborman 		cnt--;
189338689Sborman 	    tbuf = 0;
189438689Sborman 	    if (cp == line || *--cp != '\n' || cp == line)
189538689Sborman 		goto getline;
189638689Sborman 	    *cp = '\0';
189738689Sborman 	    printf("%s\n", line);
189838689Sborman 	} else {
189938689Sborman 	getline:
190038689Sborman 	    if (gets(line) == NULL) {
190138689Sborman 		if (feof(stdin) || ferror(stdin))
190238689Sborman 		    quit();
190338689Sborman 		break;
190438689Sborman 	    }
190532144Sminshall 	}
190632144Sminshall 	if (line[0] == 0)
190732144Sminshall 	    break;
190832144Sminshall 	makeargv();
190937219Sminshall 	if (margv[0] == 0) {
191037219Sminshall 	    break;
191137219Sminshall 	}
191232144Sminshall 	c = getcmd(margv[0]);
191332144Sminshall 	if (Ambiguous(c)) {
191432144Sminshall 	    printf("?Ambiguous command\n");
191532144Sminshall 	    continue;
191632144Sminshall 	}
191732144Sminshall 	if (c == 0) {
191832144Sminshall 	    printf("?Invalid command\n");
191932144Sminshall 	    continue;
192032144Sminshall 	}
192132144Sminshall 	if (c->needconnect && !connected) {
192232144Sminshall 	    printf("?Need to be connected first.\n");
192332144Sminshall 	    continue;
192432144Sminshall 	}
192532144Sminshall 	if ((*c->handler)(margc, margv)) {
192632144Sminshall 	    break;
192732144Sminshall 	}
192832144Sminshall     }
192932144Sminshall     if (!top) {
193032144Sminshall 	if (!connected) {
193132144Sminshall 	    longjmp(toplevel, 1);
193232144Sminshall 	    /*NOTREACHED*/
193332144Sminshall 	}
193432144Sminshall #if	defined(TN3270)
193532144Sminshall 	if (shell_active == 0) {
193638689Sborman 	    setconnmode(0);
193732144Sminshall 	}
193832144Sminshall #else	/* defined(TN3270) */
193938689Sborman 	setconnmode(0);
194032144Sminshall #endif	/* defined(TN3270) */
194132144Sminshall     }
194232144Sminshall }
194332144Sminshall 
194432144Sminshall /*
194532144Sminshall  * Help command.
194632144Sminshall  */
194732144Sminshall static
194832144Sminshall help(argc, argv)
194932144Sminshall 	int argc;
195032144Sminshall 	char *argv[];
195132144Sminshall {
195232144Sminshall 	register Command *c;
195332144Sminshall 
195432144Sminshall 	if (argc == 1) {
195532144Sminshall 		printf("Commands may be abbreviated.  Commands are:\n\n");
195632144Sminshall 		for (c = cmdtab; c->name; c++)
195738689Sborman 			if (c->help) {
195832144Sminshall 				printf("%-*s\t%s\n", HELPINDENT, c->name,
195932144Sminshall 								    c->help);
196032144Sminshall 			}
196132144Sminshall 		return 0;
196232144Sminshall 	}
196332144Sminshall 	while (--argc > 0) {
196432144Sminshall 		register char *arg;
196532144Sminshall 		arg = *++argv;
196632144Sminshall 		c = getcmd(arg);
196732144Sminshall 		if (Ambiguous(c))
196832144Sminshall 			printf("?Ambiguous help command %s\n", arg);
196932144Sminshall 		else if (c == (Command *)0)
197032144Sminshall 			printf("?Invalid help command %s\n", arg);
197132144Sminshall 		else
197232144Sminshall 			printf("%s\n", c->help);
197332144Sminshall 	}
197432144Sminshall 	return 0;
197532144Sminshall }
197638689Sborman 
197738689Sborman static char *rcname = 0;
197838689Sborman static char rcbuf[128];
197938689Sborman 
198038689Sborman cmdrc(m1, m2)
198138689Sborman 	char *m1, *m2;
198238689Sborman {
198338689Sborman     register Command *c;
198438689Sborman     FILE *rcfile;
198538689Sborman     int gotmachine = 0;
198638689Sborman     int l1 = strlen(m1);
198738689Sborman     int l2 = strlen(m2);
198838689Sborman     char m1save[64];
198938689Sborman 
199038689Sborman     strcpy(m1save, m1);
199138689Sborman     m1 = m1save;
199238689Sborman 
199338689Sborman     if (rcname == 0) {
199438689Sborman 	rcname = getenv("HOME");
199538689Sborman 	if (rcname)
199638689Sborman 	    strcpy(rcbuf, rcname);
199738689Sborman 	else
199838689Sborman 	    rcbuf[0] = '\0';
199938689Sborman 	strcat(rcbuf, "/.telnetrc");
200038689Sborman 	rcname = rcbuf;
200138689Sborman     }
200238689Sborman 
200338689Sborman     if ((rcfile = fopen(rcname, "r")) == 0) {
200438689Sborman 	return;
200538689Sborman     }
200638689Sborman 
200738689Sborman     for (;;) {
200838689Sborman 	if (fgets(line, sizeof(line), rcfile) == NULL)
200938689Sborman 	    break;
201038689Sborman 	if (line[0] == 0)
201138689Sborman 	    break;
201238689Sborman 	if (line[0] == '#')
201338689Sborman 	    continue;
201438689Sborman 	if (gotmachine == 0) {
201538689Sborman 	    if (isspace(line[0]))
201638689Sborman 		continue;
201738689Sborman 	    if (strncasecmp(line, m1, l1) == 0)
201838689Sborman 		strncpy(line, &line[l1], sizeof(line) - l1);
201938689Sborman 	    else if (strncasecmp(line, m2, l2) == 0)
202038689Sborman 		strncpy(line, &line[l2], sizeof(line) - l2);
202138689Sborman 	    else
202238689Sborman 		continue;
202338689Sborman 	    gotmachine = 1;
202438689Sborman 	} else {
202538689Sborman 	    if (!isspace(line[0])) {
202638689Sborman 		gotmachine = 0;
202738689Sborman 		continue;
202838689Sborman 	    }
202938689Sborman 	}
203038689Sborman 	makeargv();
203138689Sborman 	if (margv[0] == 0)
203238689Sborman 	    continue;
203338689Sborman 	c = getcmd(margv[0]);
203438689Sborman 	if (Ambiguous(c)) {
203538689Sborman 	    printf("?Ambiguous command: %s\n", margv[0]);
203638689Sborman 	    continue;
203738689Sborman 	}
203838689Sborman 	if (c == 0) {
203938689Sborman 	    printf("?Invalid command: %s\n", margv[0]);
204038689Sborman 	    continue;
204138689Sborman 	}
204238689Sborman 	/*
204338689Sborman 	 * This should never happen...
204438689Sborman 	 */
204538689Sborman 	if (c->needconnect && !connected) {
204638689Sborman 	    printf("?Need to be connected first for %s.\n", margv[0]);
204738689Sborman 	    continue;
204838689Sborman 	}
204938689Sborman 	(*c->handler)(margc, margv);
205038689Sborman     }
205138689Sborman     fclose(rcfile);
205238689Sborman }
205338689Sborman 
205438689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
205538689Sborman 
205638689Sborman /*
205738689Sborman  * Source route is handed in as
205838689Sborman  *	[!]@hop1@hop2...[@|:]dst
205938689Sborman  * If the leading ! is present, it is a
206038689Sborman  * strict source route, otherwise it is
206138689Sborman  * assmed to be a loose source route.
206238689Sborman  *
206338689Sborman  * We fill in the source route option as
206438689Sborman  *	hop1,hop2,hop3...dest
206538689Sborman  * and return a pointer to hop1, which will
206638689Sborman  * be the address to connect() to.
206738689Sborman  *
206838689Sborman  * Arguments:
206938689Sborman  *	arg:	pointer to route list to decipher
207038689Sborman  *
207138689Sborman  *	cpp: 	If *cpp is not equal to NULL, this is a
207238689Sborman  *		pointer to a pointer to a character array
207338689Sborman  *		that should be filled in with the option.
207438689Sborman  *
207538689Sborman  *	lenp:	pointer to an integer that contains the
207638689Sborman  *		length of *cpp if *cpp != NULL.
207738689Sborman  *
207838689Sborman  * Return values:
207938689Sborman  *
208038689Sborman  *	Returns the address of the host to connect to.  If the
208138689Sborman  *	return value is -1, there was a syntax error in the
208238689Sborman  *	option, either unknown characters, or too many hosts.
208338689Sborman  *	If the return value is 0, one of the hostnames in the
208438689Sborman  *	path is unknown, and *cpp is set to point to the bad
208538689Sborman  *	hostname.
208638689Sborman  *
208738689Sborman  *	*cpp:	If *cpp was equal to NULL, it will be filled
208838689Sborman  *		in with a pointer to our static area that has
208938689Sborman  *		the option filled in.  This will be 32bit aligned.
209038689Sborman  *
209138689Sborman  *	*lenp:	This will be filled in with how long the option
209238689Sborman  *		pointed to by *cpp is.
209338689Sborman  *
209438689Sborman  */
209538689Sborman unsigned long
209638689Sborman sourceroute(arg, cpp, lenp)
209738689Sborman char	*arg;
209838689Sborman char	**cpp;
209938689Sborman int	*lenp;
210038689Sborman {
210138689Sborman 	static char lsr[44];
210238689Sborman 	char *cp, *cp2, *lsrp, *lsrep, *index();
210338689Sborman 	register int tmp;
210438689Sborman 	struct in_addr sin_addr;
210538689Sborman 	register struct hostent *host = 0;
210638689Sborman 	register char c;
210738689Sborman 
210838689Sborman 	/*
210938689Sborman 	 * Verify the arguments, and make sure we have
211038689Sborman 	 * at least 7 bytes for the option.
211138689Sborman 	 */
211238689Sborman 	if (cpp == NULL || lenp == NULL)
211338689Sborman 		return((unsigned long)-1);
211438689Sborman 	if (*cpp != NULL && *lenp < 7)
211538689Sborman 		return((unsigned long)-1);
211638689Sborman 	/*
211738689Sborman 	 * Decide whether we have a buffer passed to us,
211838689Sborman 	 * or if we need to use our own static buffer.
211938689Sborman 	 */
212038689Sborman 	if (*cpp) {
212138689Sborman 		lsrp = *cpp;
212238689Sborman 		lsrep = lsrp + *lenp;
212338689Sborman 	} else {
212438689Sborman 		*cpp = lsrp = lsr;
212538689Sborman 		lsrep = lsrp + 44;
212638689Sborman 	}
212738689Sborman 
212838689Sborman 	cp = arg;
212938689Sborman 
213038689Sborman 	/*
213138689Sborman 	 * Next, decide whether we have a loose source
213238689Sborman 	 * route or a strict source route, and fill in
213338689Sborman 	 * the begining of the option.
213438689Sborman 	 */
213538689Sborman 	if (*cp == '!') {
213638689Sborman 		cp++;
213738689Sborman 		*lsrp++ = IPOPT_SSRR;
213838689Sborman 	} else
213938689Sborman 		*lsrp++ = IPOPT_LSRR;
214038689Sborman 
214138689Sborman 	if (*cp != '@')
214238689Sborman 		return((unsigned long)-1);
214338689Sborman 
214438689Sborman 	lsrp++;		/* skip over length, we'll fill it in later */
214538689Sborman 	*lsrp++ = 4;
214638689Sborman 
214738689Sborman 	cp++;
214838689Sborman 
214938689Sborman 	sin_addr.s_addr = 0;
215038689Sborman 
215138689Sborman 	for (c = 0;;) {
215238689Sborman 		if (c == ':')
215338689Sborman 			cp2 = 0;
215438689Sborman 		else for (cp2 = cp; c = *cp2; cp2++) {
215538689Sborman 			if (c == ',') {
215638689Sborman 				*cp2++ = '\0';
215738689Sborman 				if (*cp2 == '@')
215838689Sborman 					cp2++;
215938689Sborman 			} else if (c == '@') {
216038689Sborman 				*cp2++ = '\0';
216138689Sborman 			} else if (c == ':') {
216238689Sborman 				*cp2++ = '\0';
216338689Sborman 			} else
216438689Sborman 				continue;
216538689Sborman 			break;
216638689Sborman 		}
216738689Sborman 		if (!c)
216838689Sborman 			cp2 = 0;
216938689Sborman 
217038689Sborman 		if ((tmp = inet_addr(cp)) != -1) {
217138689Sborman 			sin_addr.s_addr = tmp;
217238689Sborman 		} else if (host = gethostbyname(cp)) {
217338689Sborman #if	defined(h_addr)
217438689Sborman 			memcpy((caddr_t)&sin_addr,
217538689Sborman 				host->h_addr_list[0], host->h_length);
217638689Sborman #else
217738689Sborman 			memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
217838689Sborman #endif
217938689Sborman 		} else {
218038689Sborman 			*cpp = cp;
218138689Sborman 			return(0);
218238689Sborman 		}
218338689Sborman 		memcpy(lsrp, (char *)&sin_addr, 4);
218438689Sborman 		lsrp += 4;
218538689Sborman 		if (cp2)
218638689Sborman 			cp = cp2;
218738689Sborman 		else
218838689Sborman 			break;
218938689Sborman 		/*
219038689Sborman 		 * Check to make sure there is space for next address
219138689Sborman 		 */
219238689Sborman 		if (lsrp + 4 > lsrep)
219338689Sborman 			return((unsigned long)-1);
219438689Sborman 	}
219538689Sborman 	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
219638689Sborman 		*cpp = 0;
219738689Sborman 		*lenp = 0;
219838689Sborman 		return((unsigned long)-1);
219938689Sborman 	}
220038689Sborman 	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
220138689Sborman 	*lenp = lsrp - *cpp;
220238689Sborman 	return(sin_addr.s_addr);
220338689Sborman }
220438689Sborman #endif
220538689Sborman 
220638909Sborman #if	defined(NOSTRNCASECMP)
220738689Sborman strncasecmp(p1, p2, len)
220838689Sborman register char *p1, *p2;
220938689Sborman int len;
221038689Sborman {
221138689Sborman     while (len--) {
221238689Sborman 	if (tolower(*p1) != tolower(*p2))
221338689Sborman 	   return(tolower(*p1) - tolower(*p2));
221438689Sborman 	if (*p1 == '\0')
221538689Sborman 	    return(0);
221638689Sborman 	p1++, p2++;
221738689Sborman     }
221838689Sborman     return(0);
221938689Sborman }
222038689Sborman #endif
2221