xref: /csrg-svn/usr.bin/telnet/utilities.c (revision 69785)
133686Sbostic /*
262313Sbostic  * Copyright (c) 1988, 1993
362313Sbostic  *	The Regents of the University of California.  All rights reserved.
433686Sbostic  *
544361Sborman  * %sccs.include.redist.c%
633686Sbostic  */
733686Sbostic 
833686Sbostic #ifndef lint
9*69785Sdab static char sccsid[] = "@(#)utilities.c	8.3 (Berkeley) 05/30/95";
1033686Sbostic #endif /* not lint */
1133686Sbostic 
1232149Sminshall #define	TELOPTS
1338690Sborman #define	TELCMDS
1446808Sdab #define	SLC_NAMES
1532149Sminshall #include <arpa/telnet.h>
1632381Sminshall #include <sys/types.h>
1744361Sborman #include <sys/time.h>
1832149Sminshall 
1932149Sminshall #include <ctype.h>
2032149Sminshall 
2134305Sminshall #include "general.h"
2234305Sminshall 
2336280Sminshall #include "fdset.h"
2436280Sminshall 
2532381Sminshall #include "ring.h"
2632381Sminshall 
2736278Sminshall #include "defines.h"
2836278Sminshall 
2932149Sminshall #include "externs.h"
3032149Sminshall 
3132149Sminshall FILE	*NetTrace = 0;		/* Not in bss, since needs to stay */
3238690Sborman int	prettydump;
3332149Sminshall 
3432149Sminshall /*
3532149Sminshall  * upcase()
3632149Sminshall  *
3732149Sminshall  *	Upcase (in place) the argument.
3832149Sminshall  */
3932149Sminshall 
4046808Sdab     void
upcase(argument)4132149Sminshall upcase(argument)
4246808Sdab     register char *argument;
4332149Sminshall {
4432149Sminshall     register int c;
4532149Sminshall 
4632149Sminshall     while ((c = *argument) != 0) {
4732149Sminshall 	if (islower(c)) {
4832149Sminshall 	    *argument = toupper(c);
4932149Sminshall 	}
5032149Sminshall 	argument++;
5132149Sminshall     }
5232149Sminshall }
5332149Sminshall 
5432149Sminshall /*
5532149Sminshall  * SetSockOpt()
5632149Sminshall  *
5732149Sminshall  * Compensate for differences in 4.2 and 4.3 systems.
5832149Sminshall  */
5932149Sminshall 
6046808Sdab     int
SetSockOpt(fd,level,option,yesno)6132149Sminshall SetSockOpt(fd, level, option, yesno)
6246808Sdab     int fd, level, option, yesno;
6332149Sminshall {
6432149Sminshall #ifndef	NOT43
6532149Sminshall     return setsockopt(fd, level, option,
6632149Sminshall 				(char *)&yesno, sizeof yesno);
6732149Sminshall #else	/* NOT43 */
6832149Sminshall     if (yesno == 0) {		/* Can't do that in 4.2! */
6932149Sminshall 	fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
7032149Sminshall 				option);
7132149Sminshall 	return -1;
7232149Sminshall     }
7332149Sminshall     return setsockopt(fd, level, option, 0, 0);
7432149Sminshall #endif	/* NOT43 */
7532149Sminshall }
7632149Sminshall 
7732149Sminshall /*
7832149Sminshall  * The following are routines used to print out debugging information.
7932149Sminshall  */
8032149Sminshall 
8139529Sborman unsigned char NetTraceFile[256] = "(standard output)";
8232149Sminshall 
8346808Sdab     void
SetNetTrace(file)8438690Sborman SetNetTrace(file)
8546808Sdab     register char *file;
8638690Sborman {
8738690Sborman     if (NetTrace && NetTrace != stdout)
8838690Sborman 	fclose(NetTrace);
8938690Sborman     if (file  && (strcmp(file, "-") != 0)) {
9038690Sborman 	NetTrace = fopen(file, "w");
9138690Sborman 	if (NetTrace) {
9246808Sdab 	    strcpy((char *)NetTraceFile, file);
9338690Sborman 	    return;
9438690Sborman 	}
9538690Sborman 	fprintf(stderr, "Cannot open %s.\n", file);
9638690Sborman     }
9738690Sborman     NetTrace = stdout;
9846808Sdab     strcpy((char *)NetTraceFile, "(standard output)");
9938690Sborman }
10038690Sborman 
10146808Sdab     void
Dump(direction,buffer,length)10232149Sminshall Dump(direction, buffer, length)
10346808Sdab     char direction;
10446808Sdab     unsigned char *buffer;
10546808Sdab     int length;
10632149Sminshall {
10732149Sminshall #   define BYTES_PER_LINE	32
10832149Sminshall #   define min(x,y)	((x<y)? x:y)
10946808Sdab     unsigned char *pThis;
11032149Sminshall     int offset;
11138690Sborman     extern pettydump;
11232149Sminshall 
11332149Sminshall     offset = 0;
11432149Sminshall 
11532149Sminshall     while (length) {
11632149Sminshall 	/* print one line */
11732149Sminshall 	fprintf(NetTrace, "%c 0x%x\t", direction, offset);
11832149Sminshall 	pThis = buffer;
11938690Sborman 	if (prettydump) {
12038909Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE/2);
12138690Sborman 	    while (pThis < buffer) {
12238690Sborman 		fprintf(NetTrace, "%c%.2x",
12338690Sborman 		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
12438690Sborman 		    (*pThis)&0xff);
12538690Sborman 		pThis++;
12638690Sborman 	    }
12738909Sborman 	    length -= BYTES_PER_LINE/2;
12838909Sborman 	    offset += BYTES_PER_LINE/2;
12938690Sborman 	} else {
13038909Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE);
13138690Sborman 	    while (pThis < buffer) {
13238690Sborman 		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
13338690Sborman 		pThis++;
13438690Sborman 	    }
13538909Sborman 	    length -= BYTES_PER_LINE;
13638909Sborman 	    offset += BYTES_PER_LINE;
13732149Sminshall 	}
13837226Sminshall 	if (NetTrace == stdout) {
13938207Sminshall 	    fprintf(NetTrace, "\r\n");
14038207Sminshall 	} else {
14137226Sminshall 	    fprintf(NetTrace, "\n");
14237226Sminshall 	}
14332149Sminshall 	if (length < 0) {
14436693Sminshall 	    fflush(NetTrace);
14532149Sminshall 	    return;
14632149Sminshall 	}
14732149Sminshall 	/* find next unique line */
14832149Sminshall     }
14936693Sminshall     fflush(NetTrace);
15032149Sminshall }
15132149Sminshall 
15232149Sminshall 
15346808Sdab 	void
printoption(direction,cmd,option)15446808Sdab printoption(direction, cmd, option)
15546808Sdab 	char *direction;
15646808Sdab 	int cmd, option;
15732149Sminshall {
15832149Sminshall 	if (!showoptions)
15932149Sminshall 		return;
16046808Sdab 	if (cmd == IAC) {
16146808Sdab 		if (TELCMD_OK(option))
16246808Sdab 		    fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
16346808Sdab 		else
16446808Sdab 		    fprintf(NetTrace, "%s IAC %d", direction, option);
16546808Sdab 	} else {
16646808Sdab 		register char *fmt;
16746808Sdab 		fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
16846808Sdab 			(cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
16946808Sdab 		if (fmt) {
17046808Sdab 		    fprintf(NetTrace, "%s %s ", direction, fmt);
17146808Sdab 		    if (TELOPT_OK(option))
17246808Sdab 			fprintf(NetTrace, "%s", TELOPT(option));
17346808Sdab 		    else if (option == TELOPT_EXOPL)
17446808Sdab 			fprintf(NetTrace, "EXOPL");
17546808Sdab 		    else
17646808Sdab 			fprintf(NetTrace, "%d", option);
17746808Sdab 		} else
17846808Sdab 		    fprintf(NetTrace, "%s %d %d", direction, cmd, option);
17946808Sdab 	}
18065157Sdab 	if (NetTrace == stdout) {
18137226Sminshall 	    fprintf(NetTrace, "\r\n");
18265157Sdab 	    fflush(NetTrace);
18365157Sdab 	} else {
18437226Sminshall 	    fprintf(NetTrace, "\n");
18565157Sdab 	}
18637226Sminshall 	return;
18732149Sminshall }
18832149Sminshall 
18946808Sdab     void
optionstatus()19038690Sborman optionstatus()
19138690Sborman {
19238690Sborman     register int i;
19338690Sborman     extern char will_wont_resp[], do_dont_resp[];
19438690Sborman 
19538690Sborman     for (i = 0; i < 256; i++) {
19638690Sborman 	if (do_dont_resp[i]) {
19738690Sborman 	    if (TELOPT_OK(i))
19838690Sborman 		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
19938690Sborman 	    else if (TELCMD_OK(i))
20038690Sborman 		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
20138690Sborman 	    else
20238690Sborman 		printf("resp DO_DONT %d: %d\n", i,
20338690Sborman 				do_dont_resp[i]);
20438690Sborman 	    if (my_want_state_is_do(i)) {
20538690Sborman 		if (TELOPT_OK(i))
20638690Sborman 		    printf("want DO   %s\n", TELOPT(i));
20738690Sborman 		else if (TELCMD_OK(i))
20838690Sborman 		    printf("want DO   %s\n", TELCMD(i));
20938690Sborman 		else
21038690Sborman 		    printf("want DO   %d\n", i);
21138690Sborman 	    } else {
21238690Sborman 		if (TELOPT_OK(i))
21338690Sborman 		    printf("want DONT %s\n", TELOPT(i));
21438690Sborman 		else if (TELCMD_OK(i))
21538690Sborman 		    printf("want DONT %s\n", TELCMD(i));
21638690Sborman 		else
21738690Sborman 		    printf("want DONT %d\n", i);
21838690Sborman 	    }
21938690Sborman 	} else {
22038690Sborman 	    if (my_state_is_do(i)) {
22138690Sborman 		if (TELOPT_OK(i))
22238690Sborman 		    printf("     DO   %s\n", TELOPT(i));
22338690Sborman 		else if (TELCMD_OK(i))
22438690Sborman 		    printf("     DO   %s\n", TELCMD(i));
22538690Sborman 		else
22638690Sborman 		    printf("     DO   %d\n", i);
22738690Sborman 	    }
22838690Sborman 	}
22938690Sborman 	if (will_wont_resp[i]) {
23038690Sborman 	    if (TELOPT_OK(i))
23138690Sborman 		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
23238690Sborman 	    else if (TELCMD_OK(i))
23338690Sborman 		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
23438690Sborman 	    else
23538690Sborman 		printf("resp WILL_WONT %d: %d\n",
23638690Sborman 				i, will_wont_resp[i]);
23738690Sborman 	    if (my_want_state_is_will(i)) {
23838690Sborman 		if (TELOPT_OK(i))
23938690Sborman 		    printf("want WILL %s\n", TELOPT(i));
24038690Sborman 		else if (TELCMD_OK(i))
24138690Sborman 		    printf("want WILL %s\n", TELCMD(i));
24238690Sborman 		else
24338690Sborman 		    printf("want WILL %d\n", i);
24438690Sborman 	    } else {
24538690Sborman 		if (TELOPT_OK(i))
24638690Sborman 		    printf("want WONT %s\n", TELOPT(i));
24738690Sborman 		else if (TELCMD_OK(i))
24838690Sborman 		    printf("want WONT %s\n", TELCMD(i));
24938690Sborman 		else
25038690Sborman 		    printf("want WONT %d\n", i);
25138690Sborman 	    }
25238690Sborman 	} else {
25338690Sborman 	    if (my_state_is_will(i)) {
25438690Sborman 		if (TELOPT_OK(i))
25538690Sborman 		    printf("     WILL %s\n", TELOPT(i));
25638690Sborman 		else if (TELCMD_OK(i))
25738690Sborman 		    printf("     WILL %s\n", TELCMD(i));
25838690Sborman 		else
25938690Sborman 		    printf("     WILL %d\n", i);
26038690Sborman 	    }
26138690Sborman 	}
26238690Sborman     }
26338690Sborman 
26438690Sborman }
26538690Sborman 
26646808Sdab     void
printsub(direction,pointer,length)26732149Sminshall printsub(direction, pointer, length)
26846808Sdab     char direction;	/* '<' or '>' */
26946808Sdab     unsigned char *pointer;	/* where suboption data sits */
27046808Sdab     int		  length;	/* length of suboption data */
27132149Sminshall {
27238690Sborman     register int i;
27347608Sdab     char buf[512];
27446808Sdab     extern int want_status_response;
27538690Sborman 
27646808Sdab     if (showoptions || direction == 0 ||
27746808Sdab 	(want_status_response && (pointer[0] == TELOPT_STATUS))) {
27838909Sborman 	if (direction) {
27946808Sdab 	    fprintf(NetTrace, "%s IAC SB ",
28046808Sdab 				(direction == '<')? "RCVD":"SENT");
28138909Sborman 	    if (length >= 3) {
28238909Sborman 		register int j;
28338690Sborman 
28438909Sborman 		i = pointer[length-2];
28538909Sborman 		j = pointer[length-1];
28638690Sborman 
28738909Sborman 		if (i != IAC || j != SE) {
28838909Sborman 		    fprintf(NetTrace, "(terminated by ");
28938909Sborman 		    if (TELOPT_OK(i))
29038909Sborman 			fprintf(NetTrace, "%s ", TELOPT(i));
29138909Sborman 		    else if (TELCMD_OK(i))
29238909Sborman 			fprintf(NetTrace, "%s ", TELCMD(i));
29338909Sborman 		    else
29438909Sborman 			fprintf(NetTrace, "%d ", i);
29538909Sborman 		    if (TELOPT_OK(j))
29638909Sborman 			fprintf(NetTrace, "%s", TELOPT(j));
29738909Sborman 		    else if (TELCMD_OK(j))
29838909Sborman 			fprintf(NetTrace, "%s", TELCMD(j));
29938909Sborman 		    else
30038909Sborman 			fprintf(NetTrace, "%d", j);
30138909Sborman 		    fprintf(NetTrace, ", not IAC SE!) ");
30238909Sborman 		}
30338690Sborman 	    }
30438909Sborman 	    length -= 2;
30538690Sborman 	}
30638690Sborman 	if (length < 1) {
30765157Sdab 	    fprintf(NetTrace, "(Empty suboption??\?)");
30865157Sdab 	    if (NetTrace == stdout)
30965157Sdab 		fflush(NetTrace);
31038690Sborman 	    return;
31138690Sborman 	}
31232149Sminshall 	switch (pointer[0]) {
31332149Sminshall 	case TELOPT_TTYPE:
31438690Sborman 	    fprintf(NetTrace, "TERMINAL-TYPE ");
31532149Sminshall 	    switch (pointer[1]) {
31632149Sminshall 	    case TELQUAL_IS:
31744361Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
31832149Sminshall 		break;
31932149Sminshall 	    case TELQUAL_SEND:
32038690Sborman 		fprintf(NetTrace, "SEND");
32132149Sminshall 		break;
32232149Sminshall 	    default:
32332149Sminshall 		fprintf(NetTrace,
32438690Sborman 				"- unknown qualifier %d (0x%x).",
32534849Sminshall 				pointer[1], pointer[1]);
32632149Sminshall 	    }
32732149Sminshall 	    break;
32838690Sborman 	case TELOPT_TSPEED:
32938690Sborman 	    fprintf(NetTrace, "TERMINAL-SPEED");
33038690Sborman 	    if (length < 2) {
33165157Sdab 		fprintf(NetTrace, " (empty suboption??\?)");
33238690Sborman 		break;
33338690Sborman 	    }
33438690Sborman 	    switch (pointer[1]) {
33538909Sborman 	    case TELQUAL_IS:
33638690Sborman 		fprintf(NetTrace, " IS ");
33744361Sborman 		fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
33838690Sborman 		break;
33938690Sborman 	    default:
34038690Sborman 		if (pointer[1] == 1)
34138690Sborman 		    fprintf(NetTrace, " SEND");
34238690Sborman 		else
34344361Sborman 		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
34438690Sborman 		for (i = 2; i < length; i++)
34538690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
34638690Sborman 		break;
34738690Sborman 	    }
34838690Sborman 	    break;
34938690Sborman 
35038690Sborman 	case TELOPT_LFLOW:
35138690Sborman 	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
35238690Sborman 	    if (length < 2) {
35365157Sdab 		fprintf(NetTrace, " (empty suboption??\?)");
35438690Sborman 		break;
35538690Sborman 	    }
35638690Sborman 	    switch (pointer[1]) {
35757598Sdab 	    case LFLOW_OFF:
35838690Sborman 		fprintf(NetTrace, " OFF"); break;
35957598Sdab 	    case LFLOW_ON:
36038690Sborman 		fprintf(NetTrace, " ON"); break;
36157598Sdab 	    case LFLOW_RESTART_ANY:
36257598Sdab 		fprintf(NetTrace, " RESTART-ANY"); break;
36357598Sdab 	    case LFLOW_RESTART_XON:
36457598Sdab 		fprintf(NetTrace, " RESTART-XON"); break;
36538690Sborman 	    default:
36644361Sborman 		fprintf(NetTrace, " %d (unknown)", pointer[1]);
36738690Sborman 	    }
36838690Sborman 	    for (i = 2; i < length; i++)
36938690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
37038690Sborman 	    break;
37138690Sborman 
37238690Sborman 	case TELOPT_NAWS:
37338690Sborman 	    fprintf(NetTrace, "NAWS");
37438690Sborman 	    if (length < 2) {
37565157Sdab 		fprintf(NetTrace, " (empty suboption??\?)");
37638690Sborman 		break;
37738690Sborman 	    }
37838690Sborman 	    if (length == 2) {
37938690Sborman 		fprintf(NetTrace, " ?%d?", pointer[1]);
38038690Sborman 		break;
38138690Sborman 	    }
38238690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
38338690Sborman 		pointer[1], pointer[2],
38444361Sborman 		(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
38538690Sborman 	    if (length == 4) {
38638690Sborman 		fprintf(NetTrace, " ?%d?", pointer[3]);
38738690Sborman 		break;
38838690Sborman 	    }
38938690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
39038690Sborman 		pointer[3], pointer[4],
39144361Sborman 		(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
39238690Sborman 	    for (i = 5; i < length; i++)
39338690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
39438690Sborman 	    break;
39538690Sborman 
39657213Sdab #if	defined(AUTHENTICATION)
39743320Skfall 	case TELOPT_AUTHENTICATION:
39846808Sdab 	    fprintf(NetTrace, "AUTHENTICATION");
39946808Sdab 	    if (length < 2) {
40065157Sdab 		fprintf(NetTrace, " (empty suboption??\?)");
40146808Sdab 		break;
40246808Sdab 	    }
40343320Skfall 	    switch (pointer[1]) {
40446808Sdab 	    case TELQUAL_REPLY:
40543320Skfall 	    case TELQUAL_IS:
40646808Sdab 		fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
40746808Sdab 							"IS" : "REPLY");
40846808Sdab 		if (AUTHTYPE_NAME_OK(pointer[2]))
40946808Sdab 		    fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
41046808Sdab 		else
41146808Sdab 		    fprintf(NetTrace, "%d ", pointer[2]);
41246808Sdab 		if (length < 3) {
41365157Sdab 		    fprintf(NetTrace, "(partial suboption??\?)");
41446808Sdab 		    break;
41546808Sdab 		}
41646808Sdab 		fprintf(NetTrace, "%s|%s",
41747608Sdab 			((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
41846808Sdab 			"CLIENT" : "SERVER",
41947608Sdab 			((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
42046808Sdab 			"MUTUAL" : "ONE-WAY");
42143320Skfall 
42246808Sdab 		auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
42346808Sdab 		fprintf(NetTrace, "%s", buf);
42446808Sdab 		break;
42546808Sdab 
42646808Sdab 	    case TELQUAL_SEND:
42746808Sdab 		i = 2;
42846808Sdab 		fprintf(NetTrace, " SEND ");
42946808Sdab 		while (i < length) {
43046808Sdab 		    if (AUTHTYPE_NAME_OK(pointer[i]))
43146808Sdab 			fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
43246808Sdab 		    else
43346808Sdab 			fprintf(NetTrace, "%d ", pointer[i]);
43446808Sdab 		    if (++i >= length) {
43565157Sdab 			fprintf(NetTrace, "(partial suboption??\?)");
43643320Skfall 			break;
43746808Sdab 		    }
43846808Sdab 		    fprintf(NetTrace, "%s|%s ",
43947608Sdab 			((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
44046808Sdab 							"CLIENT" : "SERVER",
44147608Sdab 			((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
44246808Sdab 							"MUTUAL" : "ONE-WAY");
44346808Sdab 		    ++i;
44443320Skfall 		}
44546808Sdab 		break;
44643320Skfall 
44747608Sdab 	    case TELQUAL_NAME:
44847608Sdab 		i = 2;
44947608Sdab 		fprintf(NetTrace, " NAME \"");
45047608Sdab 		while (i < length)
45147608Sdab 		    putc(pointer[i++], NetTrace);
45247608Sdab 		putc('"', NetTrace);
45347608Sdab 		break;
45447608Sdab 
45546808Sdab 	    default:
45646808Sdab 		    for (i = 2; i < length; i++)
45746808Sdab 			fprintf(NetTrace, " ?%d?", pointer[i]);
45846808Sdab 		    break;
45943320Skfall 	    }
46046808Sdab 	    break;
46146808Sdab #endif
46246808Sdab 
46360149Sdab #ifdef	ENCRYPTION
46446808Sdab 	case TELOPT_ENCRYPT:
46546808Sdab 	    fprintf(NetTrace, "ENCRYPT");
46646808Sdab 	    if (length < 2) {
46765157Sdab 		fprintf(NetTrace, " (empty suboption??\?)");
46843320Skfall 		break;
46946808Sdab 	    }
47046808Sdab 	    switch (pointer[1]) {
47146808Sdab 	    case ENCRYPT_START:
47246808Sdab 		fprintf(NetTrace, " START");
47346808Sdab 		break;
47443320Skfall 
47546808Sdab 	    case ENCRYPT_END:
47646808Sdab 		fprintf(NetTrace, " END");
47746808Sdab 		break;
47846808Sdab 
47946808Sdab 	    case ENCRYPT_REQSTART:
48046808Sdab 		fprintf(NetTrace, " REQUEST-START");
48146808Sdab 		break;
48246808Sdab 
48346808Sdab 	    case ENCRYPT_REQEND:
48446808Sdab 		fprintf(NetTrace, " REQUEST-END");
48546808Sdab 		break;
48646808Sdab 
48746808Sdab 	    case ENCRYPT_IS:
48846808Sdab 	    case ENCRYPT_REPLY:
48946808Sdab 		fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
49046808Sdab 							"IS" : "REPLY");
49146808Sdab 		if (length < 3) {
49265157Sdab 		    fprintf(NetTrace, " (partial suboption??\?)");
49346808Sdab 		    break;
49446808Sdab 		}
49546808Sdab 		if (ENCTYPE_NAME_OK(pointer[2]))
49646808Sdab 		    fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
49746808Sdab 		else
49846808Sdab 		    fprintf(NetTrace, " %d (unknown)", pointer[2]);
49946808Sdab 
50046808Sdab 		encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
50146808Sdab 		fprintf(NetTrace, "%s", buf);
50246808Sdab 		break;
50346808Sdab 
50446808Sdab 	    case ENCRYPT_SUPPORT:
50546808Sdab 		i = 2;
50646808Sdab 		fprintf(NetTrace, " SUPPORT ");
50746808Sdab 		while (i < length) {
50846808Sdab 		    if (ENCTYPE_NAME_OK(pointer[i]))
50946808Sdab 			fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
51046808Sdab 		    else
51146808Sdab 			fprintf(NetTrace, "%d ", pointer[i]);
51246808Sdab 		    i++;
51346808Sdab 		}
51446808Sdab 		break;
51546808Sdab 
51647608Sdab 	    case ENCRYPT_ENC_KEYID:
51747608Sdab 		fprintf(NetTrace, " ENC_KEYID ");
51847608Sdab 		goto encommon;
51947608Sdab 
52047608Sdab 	    case ENCRYPT_DEC_KEYID:
52147608Sdab 		fprintf(NetTrace, " DEC_KEYID ");
52247608Sdab 		goto encommon;
52347608Sdab 
52443320Skfall 	    default:
52547608Sdab 		fprintf(NetTrace, " %d (unknown)", pointer[1]);
52647608Sdab 	    encommon:
52746808Sdab 		for (i = 2; i < length; i++)
52846808Sdab 		    fprintf(NetTrace, " %d", pointer[i]);
52946808Sdab 		break;
53043320Skfall 	    }
53143320Skfall 	    break;
53260149Sdab #endif	/* ENCRYPTION */
53343320Skfall 
53438690Sborman 	case TELOPT_LINEMODE:
53538690Sborman 	    fprintf(NetTrace, "LINEMODE ");
53638690Sborman 	    if (length < 2) {
53765157Sdab 		fprintf(NetTrace, " (empty suboption??\?)");
53838690Sborman 		break;
53938690Sborman 	    }
54038690Sborman 	    switch (pointer[1]) {
54138690Sborman 	    case WILL:
54238690Sborman 		fprintf(NetTrace, "WILL ");
54338690Sborman 		goto common;
54438690Sborman 	    case WONT:
54538690Sborman 		fprintf(NetTrace, "WONT ");
54638690Sborman 		goto common;
54738690Sborman 	    case DO:
54838690Sborman 		fprintf(NetTrace, "DO ");
54938690Sborman 		goto common;
55038690Sborman 	    case DONT:
55138690Sborman 		fprintf(NetTrace, "DONT ");
55238690Sborman 	    common:
55338690Sborman 		if (length < 3) {
55465157Sdab 		    fprintf(NetTrace, "(no option??\?)");
55538690Sborman 		    break;
55638690Sborman 		}
55738690Sborman 		switch (pointer[2]) {
55838690Sborman 		case LM_FORWARDMASK:
55938690Sborman 		    fprintf(NetTrace, "Forward Mask");
56038690Sborman 		    for (i = 3; i < length; i++)
56138690Sborman 			fprintf(NetTrace, " %x", pointer[i]);
56238690Sborman 		    break;
56338690Sborman 		default:
56438690Sborman 		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
56538690Sborman 		    for (i = 3; i < length; i++)
56638690Sborman 			fprintf(NetTrace, " %d", pointer[i]);
56738690Sborman 		    break;
56838690Sborman 		}
56938690Sborman 		break;
570*69785Sdab 
57138690Sborman 	    case LM_SLC:
57238690Sborman 		fprintf(NetTrace, "SLC");
57338690Sborman 		for (i = 2; i < length - 2; i += 3) {
57446808Sdab 		    if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
57546808Sdab 			fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
57638690Sborman 		    else
57738690Sborman 			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
57838690Sborman 		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
57938690Sborman 		    case SLC_NOSUPPORT:
58038690Sborman 			fprintf(NetTrace, " NOSUPPORT"); break;
58138690Sborman 		    case SLC_CANTCHANGE:
58238690Sborman 			fprintf(NetTrace, " CANTCHANGE"); break;
58338690Sborman 		    case SLC_VARIABLE:
58438690Sborman 			fprintf(NetTrace, " VARIABLE"); break;
58538690Sborman 		    case SLC_DEFAULT:
58638690Sborman 			fprintf(NetTrace, " DEFAULT"); break;
58738690Sborman 		    }
58838690Sborman 		    fprintf(NetTrace, "%s%s%s",
58938690Sborman 			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
59038690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
59138690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
59238690Sborman 		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
59338690Sborman 						SLC_FLUSHOUT| SLC_LEVELBITS))
59438690Sborman 			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
59538690Sborman 		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
59644361Sborman 		    if ((pointer[i+SLC_VALUE] == IAC) &&
59744361Sborman 			(pointer[i+SLC_VALUE+1] == IAC))
59844361Sborman 				i++;
59938690Sborman 		}
60038690Sborman 		for (; i < length; i++)
60138690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
60238690Sborman 		break;
60338690Sborman 
60438690Sborman 	    case LM_MODE:
60538690Sborman 		fprintf(NetTrace, "MODE ");
60638690Sborman 		if (length < 3) {
60765157Sdab 		    fprintf(NetTrace, "(no mode??\?)");
60838690Sborman 		    break;
60938690Sborman 		}
61038690Sborman 		{
61144361Sborman 		    char tbuf[64];
61244361Sborman 		    sprintf(tbuf, "%s%s%s%s%s",
61338690Sborman 			pointer[2]&MODE_EDIT ? "|EDIT" : "",
61438690Sborman 			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
61544361Sborman 			pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
61644361Sborman 			pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
61738690Sborman 			pointer[2]&MODE_ACK ? "|ACK" : "");
61838690Sborman 		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
61938690Sborman 		}
62046808Sdab 		if (pointer[2]&~(MODE_MASK))
62138690Sborman 		    fprintf(NetTrace, " (0x%x)", pointer[2]);
62238690Sborman 		for (i = 3; i < length; i++)
62338690Sborman 		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
62438690Sborman 		break;
62538690Sborman 	    default:
62638690Sborman 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
62738690Sborman 		for (i = 2; i < length; i++)
62838690Sborman 		    fprintf(NetTrace, " %d", pointer[i]);
62938690Sborman 	    }
63038690Sborman 	    break;
63138690Sborman 
63238909Sborman 	case TELOPT_STATUS: {
63338909Sborman 	    register char *cp;
63438909Sborman 	    register int j, k;
63538909Sborman 
63638909Sborman 	    fprintf(NetTrace, "STATUS");
63738909Sborman 
63838909Sborman 	    switch (pointer[1]) {
63938909Sborman 	    default:
64038909Sborman 		if (pointer[1] == TELQUAL_SEND)
64138909Sborman 		    fprintf(NetTrace, " SEND");
64238909Sborman 		else
64344361Sborman 		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
64438909Sborman 		for (i = 2; i < length; i++)
64538909Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
64638909Sborman 		break;
64738909Sborman 	    case TELQUAL_IS:
64846808Sdab 		if (--want_status_response < 0)
64946808Sdab 		    want_status_response = 0;
65038909Sborman 		if (NetTrace == stdout)
65138909Sborman 		    fprintf(NetTrace, " IS\r\n");
65238909Sborman 		else
65338909Sborman 		    fprintf(NetTrace, " IS\n");
65438909Sborman 
65538909Sborman 		for (i = 2; i < length; i++) {
65638909Sborman 		    switch(pointer[i]) {
65738909Sborman 		    case DO:	cp = "DO"; goto common2;
65838909Sborman 		    case DONT:	cp = "DONT"; goto common2;
65938909Sborman 		    case WILL:	cp = "WILL"; goto common2;
66038909Sborman 		    case WONT:	cp = "WONT"; goto common2;
66138909Sborman 		    common2:
66238909Sborman 			i++;
66344361Sborman 			if (TELOPT_OK((int)pointer[i]))
66438909Sborman 			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
66538909Sborman 			else
66638909Sborman 			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
66738909Sborman 
66838909Sborman 			if (NetTrace == stdout)
66938909Sborman 			    fprintf(NetTrace, "\r\n");
67038909Sborman 			else
67138909Sborman 			    fprintf(NetTrace, "\n");
67238909Sborman 			break;
67338909Sborman 
67438909Sborman 		    case SB:
67538909Sborman 			fprintf(NetTrace, " SB ");
67638909Sborman 			i++;
67738909Sborman 			j = k = i;
67838909Sborman 			while (j < length) {
67938909Sborman 			    if (pointer[j] == SE) {
68038909Sborman 				if (j+1 == length)
68138909Sborman 				    break;
68238909Sborman 				if (pointer[j+1] == SE)
68338909Sborman 				    j++;
68438909Sborman 				else
68538909Sborman 				    break;
68638909Sborman 			    }
68738909Sborman 			    pointer[k++] = pointer[j++];
68838909Sborman 			}
68938909Sborman 			printsub(0, &pointer[i], k - i);
69038909Sborman 			if (i < length) {
69138909Sborman 			    fprintf(NetTrace, " SE");
69238909Sborman 			    i = j;
69338909Sborman 			} else
69438909Sborman 			    i = j - 1;
69538909Sborman 
69638909Sborman 			if (NetTrace == stdout)
69738909Sborman 			    fprintf(NetTrace, "\r\n");
69838909Sborman 			else
69938909Sborman 			    fprintf(NetTrace, "\n");
70038909Sborman 
70138909Sborman 			break;
702*69785Sdab 
70338909Sborman 		    default:
70438909Sborman 			fprintf(NetTrace, " %d", pointer[i]);
70538909Sborman 			break;
70638909Sborman 		    }
70738909Sborman 		}
70838909Sborman 		break;
70938909Sborman 	    }
71038909Sborman 	    break;
71138909Sborman 	  }
71238909Sborman 
71344361Sborman 	case TELOPT_XDISPLOC:
71444361Sborman 	    fprintf(NetTrace, "X-DISPLAY-LOCATION ");
71544361Sborman 	    switch (pointer[1]) {
71644361Sborman 	    case TELQUAL_IS:
71744361Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
71844361Sborman 		break;
71944361Sborman 	    case TELQUAL_SEND:
72044361Sborman 		fprintf(NetTrace, "SEND");
72144361Sborman 		break;
72244361Sborman 	    default:
72344361Sborman 		fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
72444361Sborman 				pointer[1], pointer[1]);
72544361Sborman 	    }
72644361Sborman 	    break;
72744361Sborman 
72865157Sdab 	case TELOPT_NEW_ENVIRON:
72965157Sdab 	    fprintf(NetTrace, "NEW-ENVIRON ");
73065157Sdab #ifdef	OLD_ENVIRON
73165157Sdab 	    goto env_common1;
73265157Sdab 	case TELOPT_OLD_ENVIRON:
73365157Sdab 	    fprintf(NetTrace, "OLD-ENVIRON");
73465157Sdab 	env_common1:
73565157Sdab #endif
73644361Sborman 	    switch (pointer[1]) {
73744361Sborman 	    case TELQUAL_IS:
73844361Sborman 		fprintf(NetTrace, "IS ");
73944361Sborman 		goto env_common;
74044361Sborman 	    case TELQUAL_SEND:
74144361Sborman 		fprintf(NetTrace, "SEND ");
74244361Sborman 		goto env_common;
74344361Sborman 	    case TELQUAL_INFO:
74444361Sborman 		fprintf(NetTrace, "INFO ");
74544361Sborman 	    env_common:
74644361Sborman 		{
74744361Sborman 		    register int noquote = 2;
74865157Sdab #if defined(ENV_HACK) && defined(OLD_ENVIRON)
74965157Sdab 		    extern int old_env_var, old_env_value;
75058972Sdab #endif
75144361Sborman 		    for (i = 2; i < length; i++ ) {
75244361Sborman 			switch (pointer[i]) {
75365157Sdab 			case NEW_ENV_VALUE:
75465157Sdab #ifdef OLD_ENVIRON
75565157Sdab 		     /*	case NEW_ENV_OVAR: */
75665157Sdab 			    if (pointer[0] == TELOPT_OLD_ENVIRON) {
75765157Sdab # ifdef	ENV_HACK
75865157Sdab 				if (old_env_var == OLD_ENV_VALUE)
75965157Sdab 				    fprintf(NetTrace, "\" (VALUE) " + noquote);
76065157Sdab 				else
76165157Sdab # endif
76265157Sdab 				    fprintf(NetTrace, "\" VAR " + noquote);
76365157Sdab 			    } else
76465157Sdab #endif /* OLD_ENVIRON */
76565157Sdab 				fprintf(NetTrace, "\" VALUE " + noquote);
76644361Sborman 			    noquote = 2;
76744361Sborman 			    break;
76844361Sborman 
76965157Sdab 			case NEW_ENV_VAR:
77065157Sdab #ifdef OLD_ENVIRON
77165157Sdab 		     /* case OLD_ENV_VALUE: */
77265157Sdab 			    if (pointer[0] == TELOPT_OLD_ENVIRON) {
77365157Sdab # ifdef	ENV_HACK
77465157Sdab 				if (old_env_value == OLD_ENV_VAR)
77565157Sdab 				    fprintf(NetTrace, "\" (VAR) " + noquote);
77665157Sdab 				else
77765157Sdab # endif
77865157Sdab 				    fprintf(NetTrace, "\" VALUE " + noquote);
77965157Sdab 			    } else
78065157Sdab #endif /* OLD_ENVIRON */
78165157Sdab 				fprintf(NetTrace, "\" VAR " + noquote);
78244361Sborman 			    noquote = 2;
78344361Sborman 			    break;
78444361Sborman 
78544361Sborman 			case ENV_ESC:
78644361Sborman 			    fprintf(NetTrace, "\" ESC " + noquote);
78744361Sborman 			    noquote = 2;
78844361Sborman 			    break;
78944361Sborman 
79057213Sdab 			case ENV_USERVAR:
79157213Sdab 			    fprintf(NetTrace, "\" USERVAR " + noquote);
79257213Sdab 			    noquote = 2;
79357213Sdab 			    break;
79457213Sdab 
79544361Sborman 			default:
79644361Sborman 			def_case:
79744361Sborman 			    if (isprint(pointer[i]) && pointer[i] != '"') {
79844361Sborman 				if (noquote) {
79944361Sborman 				    putc('"', NetTrace);
80044361Sborman 				    noquote = 0;
80144361Sborman 				}
80244361Sborman 				putc(pointer[i], NetTrace);
80344361Sborman 			    } else {
80444361Sborman 				fprintf(NetTrace, "\" %03o " + noquote,
80544361Sborman 							pointer[i]);
80644361Sborman 				noquote = 2;
80744361Sborman 			    }
80844361Sborman 			    break;
80944361Sborman 			}
81044361Sborman 		    }
81144361Sborman 		    if (!noquote)
81244361Sborman 			putc('"', NetTrace);
81344361Sborman 		    break;
81444361Sborman 		}
81544361Sborman 	    }
81644361Sborman 	    break;
81744361Sborman 
81832149Sminshall 	default:
81946808Sdab 	    if (TELOPT_OK(pointer[0]))
82046808Sdab 		fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
82146808Sdab 	    else
82256860Storek 		fprintf(NetTrace, "%d (unknown)", pointer[0]);
82346808Sdab 	    for (i = 1; i < length; i++)
82438690Sborman 		fprintf(NetTrace, " %d", pointer[i]);
82538690Sborman 	    break;
82632149Sminshall 	}
82738909Sborman 	if (direction) {
82838909Sborman 	    if (NetTrace == stdout)
82938909Sborman 		fprintf(NetTrace, "\r\n");
83038909Sborman 	    else
83138909Sborman 		fprintf(NetTrace, "\n");
83238909Sborman 	}
83365157Sdab 	if (NetTrace == stdout)
83465157Sdab 	    fflush(NetTrace);
83532149Sminshall     }
83632149Sminshall }
83736278Sminshall 
83836278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
83936278Sminshall  *			Note that we consider the buffer to run all the
84036278Sminshall  *			way to the kernel (thus the select).
84136278Sminshall  */
84236278Sminshall 
84346808Sdab     void
EmptyTerminal()84436278Sminshall EmptyTerminal()
84536278Sminshall {
84636278Sminshall #if	defined(unix)
84736278Sminshall     fd_set	o;
84836278Sminshall 
84936278Sminshall     FD_ZERO(&o);
85036278Sminshall #endif	/* defined(unix) */
85136278Sminshall 
85236278Sminshall     if (TTYBYTES() == 0) {
85336278Sminshall #if	defined(unix)
85436278Sminshall 	FD_SET(tout, &o);
85536278Sminshall 	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
85636278Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
85736278Sminshall #endif	/* defined(unix) */
85836278Sminshall     } else {
85936278Sminshall 	while (TTYBYTES()) {
86044361Sborman 	    (void) ttyflush(0);
86136278Sminshall #if	defined(unix)
86236278Sminshall 	    FD_SET(tout, &o);
86336278Sminshall 	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
86436278Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
86536278Sminshall #endif	/* defined(unix) */
86636278Sminshall 	}
86736278Sminshall     }
86836278Sminshall }
86936278Sminshall 
87046808Sdab     void
SetForExit()87136278Sminshall SetForExit()
87236278Sminshall {
87338690Sborman     setconnmode(0);
87436278Sminshall #if	defined(TN3270)
87536278Sminshall     if (In3270) {
87636278Sminshall 	Finish3270();
87736278Sminshall     }
87836279Sminshall #else	/* defined(TN3270) */
87936279Sminshall     do {
88044361Sborman 	(void)telrcv();			/* Process any incoming data */
88136279Sminshall 	EmptyTerminal();
88236279Sminshall     } while (ring_full_count(&netiring));	/* While there is any */
88336278Sminshall #endif	/* defined(TN3270) */
88436278Sminshall     setcommandmode();
88536278Sminshall     fflush(stdout);
88636278Sminshall     fflush(stderr);
88736278Sminshall #if	defined(TN3270)
88836278Sminshall     if (In3270) {
88936278Sminshall 	StopScreen(1);
89036278Sminshall     }
89136278Sminshall #endif	/* defined(TN3270) */
89238690Sborman     setconnmode(0);
89336278Sminshall     EmptyTerminal();			/* Flush the path to the tty */
89436278Sminshall     setcommandmode();
89536278Sminshall }
89636278Sminshall 
89746808Sdab     void
Exit(returnCode)89836278Sminshall Exit(returnCode)
89946808Sdab     int returnCode;
90036278Sminshall {
90136278Sminshall     SetForExit();
90236278Sminshall     exit(returnCode);
90336278Sminshall }
90436278Sminshall 
90546808Sdab     void
ExitString(string,returnCode)90636278Sminshall ExitString(string, returnCode)
90746808Sdab     char *string;
90846808Sdab     int returnCode;
90936278Sminshall {
91036278Sminshall     SetForExit();
91136278Sminshall     fwrite(string, 1, strlen(string), stderr);
91236278Sminshall     exit(returnCode);
91336278Sminshall }
914