xref: /csrg-svn/usr.bin/telnet/utilities.c (revision 57213)
133686Sbostic /*
233686Sbostic  * Copyright (c) 1988 Regents of the University of California.
333686Sbostic  * All rights reserved.
433686Sbostic  *
544361Sborman  * %sccs.include.redist.c%
633686Sbostic  */
733686Sbostic 
833686Sbostic #ifndef lint
9*57213Sdab static char sccsid[] = "@(#)utilities.c	5.5 (Berkeley) 12/18/92";
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
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
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
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
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
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 	}
18038690Sborman 	if (NetTrace == stdout)
18137226Sminshall 	    fprintf(NetTrace, "\r\n");
18238690Sborman 	else
18337226Sminshall 	    fprintf(NetTrace, "\n");
18437226Sminshall 	return;
18532149Sminshall }
18632149Sminshall 
18746808Sdab     void
18838690Sborman optionstatus()
18938690Sborman {
19038690Sborman     register int i;
19138690Sborman     extern char will_wont_resp[], do_dont_resp[];
19238690Sborman 
19338690Sborman     for (i = 0; i < 256; i++) {
19438690Sborman 	if (do_dont_resp[i]) {
19538690Sborman 	    if (TELOPT_OK(i))
19638690Sborman 		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
19738690Sborman 	    else if (TELCMD_OK(i))
19838690Sborman 		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
19938690Sborman 	    else
20038690Sborman 		printf("resp DO_DONT %d: %d\n", i,
20138690Sborman 				do_dont_resp[i]);
20238690Sborman 	    if (my_want_state_is_do(i)) {
20338690Sborman 		if (TELOPT_OK(i))
20438690Sborman 		    printf("want DO   %s\n", TELOPT(i));
20538690Sborman 		else if (TELCMD_OK(i))
20638690Sborman 		    printf("want DO   %s\n", TELCMD(i));
20738690Sborman 		else
20838690Sborman 		    printf("want DO   %d\n", i);
20938690Sborman 	    } else {
21038690Sborman 		if (TELOPT_OK(i))
21138690Sborman 		    printf("want DONT %s\n", TELOPT(i));
21238690Sborman 		else if (TELCMD_OK(i))
21338690Sborman 		    printf("want DONT %s\n", TELCMD(i));
21438690Sborman 		else
21538690Sborman 		    printf("want DONT %d\n", i);
21638690Sborman 	    }
21738690Sborman 	} else {
21838690Sborman 	    if (my_state_is_do(i)) {
21938690Sborman 		if (TELOPT_OK(i))
22038690Sborman 		    printf("     DO   %s\n", TELOPT(i));
22138690Sborman 		else if (TELCMD_OK(i))
22238690Sborman 		    printf("     DO   %s\n", TELCMD(i));
22338690Sborman 		else
22438690Sborman 		    printf("     DO   %d\n", i);
22538690Sborman 	    }
22638690Sborman 	}
22738690Sborman 	if (will_wont_resp[i]) {
22838690Sborman 	    if (TELOPT_OK(i))
22938690Sborman 		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
23038690Sborman 	    else if (TELCMD_OK(i))
23138690Sborman 		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
23238690Sborman 	    else
23338690Sborman 		printf("resp WILL_WONT %d: %d\n",
23438690Sborman 				i, will_wont_resp[i]);
23538690Sborman 	    if (my_want_state_is_will(i)) {
23638690Sborman 		if (TELOPT_OK(i))
23738690Sborman 		    printf("want WILL %s\n", TELOPT(i));
23838690Sborman 		else if (TELCMD_OK(i))
23938690Sborman 		    printf("want WILL %s\n", TELCMD(i));
24038690Sborman 		else
24138690Sborman 		    printf("want WILL %d\n", i);
24238690Sborman 	    } else {
24338690Sborman 		if (TELOPT_OK(i))
24438690Sborman 		    printf("want WONT %s\n", TELOPT(i));
24538690Sborman 		else if (TELCMD_OK(i))
24638690Sborman 		    printf("want WONT %s\n", TELCMD(i));
24738690Sborman 		else
24838690Sborman 		    printf("want WONT %d\n", i);
24938690Sborman 	    }
25038690Sborman 	} else {
25138690Sborman 	    if (my_state_is_will(i)) {
25238690Sborman 		if (TELOPT_OK(i))
25338690Sborman 		    printf("     WILL %s\n", TELOPT(i));
25438690Sborman 		else if (TELCMD_OK(i))
25538690Sborman 		    printf("     WILL %s\n", TELCMD(i));
25638690Sborman 		else
25738690Sborman 		    printf("     WILL %d\n", i);
25838690Sborman 	    }
25938690Sborman 	}
26038690Sborman     }
26138690Sborman 
26238690Sborman }
26338690Sborman 
26446808Sdab     void
26532149Sminshall printsub(direction, pointer, length)
26646808Sdab     char direction;	/* '<' or '>' */
26746808Sdab     unsigned char *pointer;	/* where suboption data sits */
26846808Sdab     int		  length;	/* length of suboption data */
26932149Sminshall {
27038690Sborman     register int i;
27147608Sdab     char buf[512];
27246808Sdab     extern int want_status_response;
27338690Sborman 
27446808Sdab     if (showoptions || direction == 0 ||
27546808Sdab 	(want_status_response && (pointer[0] == TELOPT_STATUS))) {
27638909Sborman 	if (direction) {
27746808Sdab 	    fprintf(NetTrace, "%s IAC SB ",
27846808Sdab 				(direction == '<')? "RCVD":"SENT");
27938909Sborman 	    if (length >= 3) {
28038909Sborman 		register int j;
28138690Sborman 
28238909Sborman 		i = pointer[length-2];
28338909Sborman 		j = pointer[length-1];
28438690Sborman 
28538909Sborman 		if (i != IAC || j != SE) {
28638909Sborman 		    fprintf(NetTrace, "(terminated by ");
28738909Sborman 		    if (TELOPT_OK(i))
28838909Sborman 			fprintf(NetTrace, "%s ", TELOPT(i));
28938909Sborman 		    else if (TELCMD_OK(i))
29038909Sborman 			fprintf(NetTrace, "%s ", TELCMD(i));
29138909Sborman 		    else
29238909Sborman 			fprintf(NetTrace, "%d ", i);
29338909Sborman 		    if (TELOPT_OK(j))
29438909Sborman 			fprintf(NetTrace, "%s", TELOPT(j));
29538909Sborman 		    else if (TELCMD_OK(j))
29638909Sborman 			fprintf(NetTrace, "%s", TELCMD(j));
29738909Sborman 		    else
29838909Sborman 			fprintf(NetTrace, "%d", j);
29938909Sborman 		    fprintf(NetTrace, ", not IAC SE!) ");
30038909Sborman 		}
30138690Sborman 	    }
30238909Sborman 	    length -= 2;
30338690Sborman 	}
30438690Sborman 	if (length < 1) {
30538690Sborman 	    fprintf(NetTrace, "(Empty suboption???)");
30638690Sborman 	    return;
30738690Sborman 	}
30832149Sminshall 	switch (pointer[0]) {
30932149Sminshall 	case TELOPT_TTYPE:
31038690Sborman 	    fprintf(NetTrace, "TERMINAL-TYPE ");
31132149Sminshall 	    switch (pointer[1]) {
31232149Sminshall 	    case TELQUAL_IS:
31344361Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
31432149Sminshall 		break;
31532149Sminshall 	    case TELQUAL_SEND:
31638690Sborman 		fprintf(NetTrace, "SEND");
31732149Sminshall 		break;
31832149Sminshall 	    default:
31932149Sminshall 		fprintf(NetTrace,
32038690Sborman 				"- unknown qualifier %d (0x%x).",
32134849Sminshall 				pointer[1], pointer[1]);
32232149Sminshall 	    }
32332149Sminshall 	    break;
32438690Sborman 	case TELOPT_TSPEED:
32538690Sborman 	    fprintf(NetTrace, "TERMINAL-SPEED");
32638690Sborman 	    if (length < 2) {
32738690Sborman 		fprintf(NetTrace, " (empty suboption???)");
32838690Sborman 		break;
32938690Sborman 	    }
33038690Sborman 	    switch (pointer[1]) {
33138909Sborman 	    case TELQUAL_IS:
33238690Sborman 		fprintf(NetTrace, " IS ");
33344361Sborman 		fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
33438690Sborman 		break;
33538690Sborman 	    default:
33638690Sborman 		if (pointer[1] == 1)
33738690Sborman 		    fprintf(NetTrace, " SEND");
33838690Sborman 		else
33944361Sborman 		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
34038690Sborman 		for (i = 2; i < length; i++)
34138690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
34238690Sborman 		break;
34338690Sborman 	    }
34438690Sborman 	    break;
34538690Sborman 
34638690Sborman 	case TELOPT_LFLOW:
34738690Sborman 	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
34838690Sborman 	    if (length < 2) {
34938690Sborman 		fprintf(NetTrace, " (empty suboption???)");
35038690Sborman 		break;
35138690Sborman 	    }
35238690Sborman 	    switch (pointer[1]) {
35338690Sborman 	    case 0:
35438690Sborman 		fprintf(NetTrace, " OFF"); break;
35538690Sborman 	    case 1:
35638690Sborman 		fprintf(NetTrace, " ON"); break;
35738690Sborman 	    default:
35844361Sborman 		fprintf(NetTrace, " %d (unknown)", pointer[1]);
35938690Sborman 	    }
36038690Sborman 	    for (i = 2; i < length; i++)
36138690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
36238690Sborman 	    break;
36338690Sborman 
36438690Sborman 	case TELOPT_NAWS:
36538690Sborman 	    fprintf(NetTrace, "NAWS");
36638690Sborman 	    if (length < 2) {
36738690Sborman 		fprintf(NetTrace, " (empty suboption???)");
36838690Sborman 		break;
36938690Sborman 	    }
37038690Sborman 	    if (length == 2) {
37138690Sborman 		fprintf(NetTrace, " ?%d?", pointer[1]);
37238690Sborman 		break;
37338690Sborman 	    }
37438690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
37538690Sborman 		pointer[1], pointer[2],
37644361Sborman 		(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
37738690Sborman 	    if (length == 4) {
37838690Sborman 		fprintf(NetTrace, " ?%d?", pointer[3]);
37938690Sborman 		break;
38038690Sborman 	    }
38138690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
38238690Sborman 		pointer[3], pointer[4],
38344361Sborman 		(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
38438690Sborman 	    for (i = 5; i < length; i++)
38538690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
38638690Sborman 	    break;
38738690Sborman 
388*57213Sdab #if	defined(AUTHENTICATION)
38943320Skfall 	case TELOPT_AUTHENTICATION:
39046808Sdab 	    fprintf(NetTrace, "AUTHENTICATION");
39146808Sdab 	    if (length < 2) {
39246808Sdab 		fprintf(NetTrace, " (empty suboption???)");
39346808Sdab 		break;
39446808Sdab 	    }
39543320Skfall 	    switch (pointer[1]) {
39646808Sdab 	    case TELQUAL_REPLY:
39743320Skfall 	    case TELQUAL_IS:
39846808Sdab 		fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
39946808Sdab 							"IS" : "REPLY");
40046808Sdab 		if (AUTHTYPE_NAME_OK(pointer[2]))
40146808Sdab 		    fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
40246808Sdab 		else
40346808Sdab 		    fprintf(NetTrace, "%d ", pointer[2]);
40446808Sdab 		if (length < 3) {
40546808Sdab 		    fprintf(NetTrace, "(partial suboption???)");
40646808Sdab 		    break;
40746808Sdab 		}
40846808Sdab 		fprintf(NetTrace, "%s|%s",
40947608Sdab 			((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
41046808Sdab 			"CLIENT" : "SERVER",
41147608Sdab 			((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
41246808Sdab 			"MUTUAL" : "ONE-WAY");
41343320Skfall 
41446808Sdab 		auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
41546808Sdab 		fprintf(NetTrace, "%s", buf);
41646808Sdab 		break;
41746808Sdab 
41846808Sdab 	    case TELQUAL_SEND:
41946808Sdab 		i = 2;
42046808Sdab 		fprintf(NetTrace, " SEND ");
42146808Sdab 		while (i < length) {
42246808Sdab 		    if (AUTHTYPE_NAME_OK(pointer[i]))
42346808Sdab 			fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
42446808Sdab 		    else
42546808Sdab 			fprintf(NetTrace, "%d ", pointer[i]);
42646808Sdab 		    if (++i >= length) {
42746808Sdab 			fprintf(NetTrace, "(partial suboption???)");
42843320Skfall 			break;
42946808Sdab 		    }
43046808Sdab 		    fprintf(NetTrace, "%s|%s ",
43147608Sdab 			((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
43246808Sdab 							"CLIENT" : "SERVER",
43347608Sdab 			((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
43446808Sdab 							"MUTUAL" : "ONE-WAY");
43546808Sdab 		    ++i;
43643320Skfall 		}
43746808Sdab 		break;
43843320Skfall 
43947608Sdab 	    case TELQUAL_NAME:
44047608Sdab 		i = 2;
44147608Sdab 		fprintf(NetTrace, " NAME \"");
44247608Sdab 		while (i < length)
44347608Sdab 		    putc(pointer[i++], NetTrace);
44447608Sdab 		putc('"', NetTrace);
44547608Sdab 		break;
44647608Sdab 
44746808Sdab 	    default:
44846808Sdab 		    for (i = 2; i < length; i++)
44946808Sdab 			fprintf(NetTrace, " ?%d?", pointer[i]);
45046808Sdab 		    break;
45143320Skfall 	    }
45246808Sdab 	    break;
45346808Sdab #endif
45446808Sdab 
455*57213Sdab #if	defined(ENCRYPTION)
45646808Sdab 	case TELOPT_ENCRYPT:
45746808Sdab 	    fprintf(NetTrace, "ENCRYPT");
45846808Sdab 	    if (length < 2) {
45946808Sdab 		fprintf(NetTrace, " (empty suboption???)");
46043320Skfall 		break;
46146808Sdab 	    }
46246808Sdab 	    switch (pointer[1]) {
46346808Sdab 	    case ENCRYPT_START:
46446808Sdab 		fprintf(NetTrace, " START");
46546808Sdab 		break;
46643320Skfall 
46746808Sdab 	    case ENCRYPT_END:
46846808Sdab 		fprintf(NetTrace, " END");
46946808Sdab 		break;
47046808Sdab 
47146808Sdab 	    case ENCRYPT_REQSTART:
47246808Sdab 		fprintf(NetTrace, " REQUEST-START");
47346808Sdab 		break;
47446808Sdab 
47546808Sdab 	    case ENCRYPT_REQEND:
47646808Sdab 		fprintf(NetTrace, " REQUEST-END");
47746808Sdab 		break;
47846808Sdab 
47946808Sdab 	    case ENCRYPT_IS:
48046808Sdab 	    case ENCRYPT_REPLY:
48146808Sdab 		fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
48246808Sdab 							"IS" : "REPLY");
48346808Sdab 		if (length < 3) {
48446808Sdab 		    fprintf(NetTrace, " (partial suboption???)");
48546808Sdab 		    break;
48646808Sdab 		}
48746808Sdab 		if (ENCTYPE_NAME_OK(pointer[2]))
48846808Sdab 		    fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
48946808Sdab 		else
49046808Sdab 		    fprintf(NetTrace, " %d (unknown)", pointer[2]);
49146808Sdab 
49246808Sdab 		encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
49346808Sdab 		fprintf(NetTrace, "%s", buf);
49446808Sdab 		break;
49546808Sdab 
49646808Sdab 	    case ENCRYPT_SUPPORT:
49746808Sdab 		i = 2;
49846808Sdab 		fprintf(NetTrace, " SUPPORT ");
49946808Sdab 		while (i < length) {
50046808Sdab 		    if (ENCTYPE_NAME_OK(pointer[i]))
50146808Sdab 			fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
50246808Sdab 		    else
50346808Sdab 			fprintf(NetTrace, "%d ", pointer[i]);
50446808Sdab 		    i++;
50546808Sdab 		}
50646808Sdab 		break;
50746808Sdab 
50847608Sdab 	    case ENCRYPT_ENC_KEYID:
50947608Sdab 		fprintf(NetTrace, " ENC_KEYID ");
51047608Sdab 		goto encommon;
51147608Sdab 
51247608Sdab 	    case ENCRYPT_DEC_KEYID:
51347608Sdab 		fprintf(NetTrace, " DEC_KEYID ");
51447608Sdab 		goto encommon;
51547608Sdab 
51643320Skfall 	    default:
51747608Sdab 		fprintf(NetTrace, " %d (unknown)", pointer[1]);
51847608Sdab 	    encommon:
51946808Sdab 		for (i = 2; i < length; i++)
52046808Sdab 		    fprintf(NetTrace, " %d", pointer[i]);
52146808Sdab 		break;
52243320Skfall 	    }
52343320Skfall 	    break;
52446808Sdab #endif
52543320Skfall 
52638690Sborman 	case TELOPT_LINEMODE:
52738690Sborman 	    fprintf(NetTrace, "LINEMODE ");
52838690Sborman 	    if (length < 2) {
52938690Sborman 		fprintf(NetTrace, " (empty suboption???)");
53038690Sborman 		break;
53138690Sborman 	    }
53238690Sborman 	    switch (pointer[1]) {
53338690Sborman 	    case WILL:
53438690Sborman 		fprintf(NetTrace, "WILL ");
53538690Sborman 		goto common;
53638690Sborman 	    case WONT:
53738690Sborman 		fprintf(NetTrace, "WONT ");
53838690Sborman 		goto common;
53938690Sborman 	    case DO:
54038690Sborman 		fprintf(NetTrace, "DO ");
54138690Sborman 		goto common;
54238690Sborman 	    case DONT:
54338690Sborman 		fprintf(NetTrace, "DONT ");
54438690Sborman 	    common:
54538690Sborman 		if (length < 3) {
54638690Sborman 		    fprintf(NetTrace, "(no option???)");
54738690Sborman 		    break;
54838690Sborman 		}
54938690Sborman 		switch (pointer[2]) {
55038690Sborman 		case LM_FORWARDMASK:
55138690Sborman 		    fprintf(NetTrace, "Forward Mask");
55238690Sborman 		    for (i = 3; i < length; i++)
55338690Sborman 			fprintf(NetTrace, " %x", pointer[i]);
55438690Sborman 		    break;
55538690Sborman 		default:
55638690Sborman 		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
55738690Sborman 		    for (i = 3; i < length; i++)
55838690Sborman 			fprintf(NetTrace, " %d", pointer[i]);
55938690Sborman 		    break;
56038690Sborman 		}
56138690Sborman 		break;
56238690Sborman 
56338690Sborman 	    case LM_SLC:
56438690Sborman 		fprintf(NetTrace, "SLC");
56538690Sborman 		for (i = 2; i < length - 2; i += 3) {
56646808Sdab 		    if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
56746808Sdab 			fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
56838690Sborman 		    else
56938690Sborman 			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
57038690Sborman 		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
57138690Sborman 		    case SLC_NOSUPPORT:
57238690Sborman 			fprintf(NetTrace, " NOSUPPORT"); break;
57338690Sborman 		    case SLC_CANTCHANGE:
57438690Sborman 			fprintf(NetTrace, " CANTCHANGE"); break;
57538690Sborman 		    case SLC_VARIABLE:
57638690Sborman 			fprintf(NetTrace, " VARIABLE"); break;
57738690Sborman 		    case SLC_DEFAULT:
57838690Sborman 			fprintf(NetTrace, " DEFAULT"); break;
57938690Sborman 		    }
58038690Sborman 		    fprintf(NetTrace, "%s%s%s",
58138690Sborman 			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
58238690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
58338690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
58438690Sborman 		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
58538690Sborman 						SLC_FLUSHOUT| SLC_LEVELBITS))
58638690Sborman 			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
58738690Sborman 		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
58844361Sborman 		    if ((pointer[i+SLC_VALUE] == IAC) &&
58944361Sborman 			(pointer[i+SLC_VALUE+1] == IAC))
59044361Sborman 				i++;
59138690Sborman 		}
59238690Sborman 		for (; i < length; i++)
59338690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
59438690Sborman 		break;
59538690Sborman 
59638690Sborman 	    case LM_MODE:
59738690Sborman 		fprintf(NetTrace, "MODE ");
59838690Sborman 		if (length < 3) {
59938690Sborman 		    fprintf(NetTrace, "(no mode???)");
60038690Sborman 		    break;
60138690Sborman 		}
60238690Sborman 		{
60344361Sborman 		    char tbuf[64];
60444361Sborman 		    sprintf(tbuf, "%s%s%s%s%s",
60538690Sborman 			pointer[2]&MODE_EDIT ? "|EDIT" : "",
60638690Sborman 			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
60744361Sborman 			pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
60844361Sborman 			pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
60938690Sborman 			pointer[2]&MODE_ACK ? "|ACK" : "");
61038690Sborman 		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
61138690Sborman 		}
61246808Sdab 		if (pointer[2]&~(MODE_MASK))
61338690Sborman 		    fprintf(NetTrace, " (0x%x)", pointer[2]);
61438690Sborman 		for (i = 3; i < length; i++)
61538690Sborman 		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
61638690Sborman 		break;
61738690Sborman 	    default:
61838690Sborman 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
61938690Sborman 		for (i = 2; i < length; i++)
62038690Sborman 		    fprintf(NetTrace, " %d", pointer[i]);
62138690Sborman 	    }
62238690Sborman 	    break;
62338690Sborman 
62438909Sborman 	case TELOPT_STATUS: {
62538909Sborman 	    register char *cp;
62638909Sborman 	    register int j, k;
62738909Sborman 
62838909Sborman 	    fprintf(NetTrace, "STATUS");
62938909Sborman 
63038909Sborman 	    switch (pointer[1]) {
63138909Sborman 	    default:
63238909Sborman 		if (pointer[1] == TELQUAL_SEND)
63338909Sborman 		    fprintf(NetTrace, " SEND");
63438909Sborman 		else
63544361Sborman 		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
63638909Sborman 		for (i = 2; i < length; i++)
63738909Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
63838909Sborman 		break;
63938909Sborman 	    case TELQUAL_IS:
64046808Sdab 		if (--want_status_response < 0)
64146808Sdab 		    want_status_response = 0;
64238909Sborman 		if (NetTrace == stdout)
64338909Sborman 		    fprintf(NetTrace, " IS\r\n");
64438909Sborman 		else
64538909Sborman 		    fprintf(NetTrace, " IS\n");
64638909Sborman 
64738909Sborman 		for (i = 2; i < length; i++) {
64838909Sborman 		    switch(pointer[i]) {
64938909Sborman 		    case DO:	cp = "DO"; goto common2;
65038909Sborman 		    case DONT:	cp = "DONT"; goto common2;
65138909Sborman 		    case WILL:	cp = "WILL"; goto common2;
65238909Sborman 		    case WONT:	cp = "WONT"; goto common2;
65338909Sborman 		    common2:
65438909Sborman 			i++;
65544361Sborman 			if (TELOPT_OK((int)pointer[i]))
65638909Sborman 			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
65738909Sborman 			else
65838909Sborman 			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
65938909Sborman 
66038909Sborman 			if (NetTrace == stdout)
66138909Sborman 			    fprintf(NetTrace, "\r\n");
66238909Sborman 			else
66338909Sborman 			    fprintf(NetTrace, "\n");
66438909Sborman 			break;
66538909Sborman 
66638909Sborman 		    case SB:
66738909Sborman 			fprintf(NetTrace, " SB ");
66838909Sborman 			i++;
66938909Sborman 			j = k = i;
67038909Sborman 			while (j < length) {
67138909Sborman 			    if (pointer[j] == SE) {
67238909Sborman 				if (j+1 == length)
67338909Sborman 				    break;
67438909Sborman 				if (pointer[j+1] == SE)
67538909Sborman 				    j++;
67638909Sborman 				else
67738909Sborman 				    break;
67838909Sborman 			    }
67938909Sborman 			    pointer[k++] = pointer[j++];
68038909Sborman 			}
68138909Sborman 			printsub(0, &pointer[i], k - i);
68238909Sborman 			if (i < length) {
68338909Sborman 			    fprintf(NetTrace, " SE");
68438909Sborman 			    i = j;
68538909Sborman 			} else
68638909Sborman 			    i = j - 1;
68738909Sborman 
68838909Sborman 			if (NetTrace == stdout)
68938909Sborman 			    fprintf(NetTrace, "\r\n");
69038909Sborman 			else
69138909Sborman 			    fprintf(NetTrace, "\n");
69238909Sborman 
69338909Sborman 			break;
69438909Sborman 
69538909Sborman 		    default:
69638909Sborman 			fprintf(NetTrace, " %d", pointer[i]);
69738909Sborman 			break;
69838909Sborman 		    }
69938909Sborman 		}
70038909Sborman 		break;
70138909Sborman 	    }
70238909Sborman 	    break;
70338909Sborman 	  }
70438909Sborman 
70544361Sborman 	case TELOPT_XDISPLOC:
70644361Sborman 	    fprintf(NetTrace, "X-DISPLAY-LOCATION ");
70744361Sborman 	    switch (pointer[1]) {
70844361Sborman 	    case TELQUAL_IS:
70944361Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
71044361Sborman 		break;
71144361Sborman 	    case TELQUAL_SEND:
71244361Sborman 		fprintf(NetTrace, "SEND");
71344361Sborman 		break;
71444361Sborman 	    default:
71544361Sborman 		fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
71644361Sborman 				pointer[1], pointer[1]);
71744361Sborman 	    }
71844361Sborman 	    break;
71944361Sborman 
72044361Sborman 	case TELOPT_ENVIRON:
72144361Sborman 	    fprintf(NetTrace, "ENVIRON ");
72244361Sborman 	    switch (pointer[1]) {
72344361Sborman 	    case TELQUAL_IS:
72444361Sborman 		fprintf(NetTrace, "IS ");
72544361Sborman 		goto env_common;
72644361Sborman 	    case TELQUAL_SEND:
72744361Sborman 		fprintf(NetTrace, "SEND ");
72844361Sborman 		goto env_common;
72944361Sborman 	    case TELQUAL_INFO:
73044361Sborman 		fprintf(NetTrace, "INFO ");
73144361Sborman 	    env_common:
73244361Sborman 		{
73344361Sborman 		    register int noquote = 2;
73444361Sborman 		    for (i = 2; i < length; i++ ) {
73544361Sborman 			switch (pointer[i]) {
73644361Sborman 			case ENV_VAR:
73744361Sborman 			    if (pointer[1] == TELQUAL_SEND)
73844361Sborman 				goto def_case;
73944361Sborman 			    fprintf(NetTrace, "\" VAR " + noquote);
74044361Sborman 			    noquote = 2;
74144361Sborman 			    break;
74244361Sborman 
74344361Sborman 			case ENV_VALUE:
74444361Sborman 			    fprintf(NetTrace, "\" VALUE " + noquote);
74544361Sborman 			    noquote = 2;
74644361Sborman 			    break;
74744361Sborman 
74844361Sborman 			case ENV_ESC:
74944361Sborman 			    fprintf(NetTrace, "\" ESC " + noquote);
75044361Sborman 			    noquote = 2;
75144361Sborman 			    break;
75244361Sborman 
753*57213Sdab 			case ENV_USERVAR:
754*57213Sdab 			    if (pointer[1] == TELQUAL_SEND)
755*57213Sdab 				goto def_case;
756*57213Sdab 			    fprintf(NetTrace, "\" USERVAR " + noquote);
757*57213Sdab 			    noquote = 2;
758*57213Sdab 			    break;
759*57213Sdab 
76044361Sborman 			default:
76144361Sborman 			def_case:
76244361Sborman 			    if (isprint(pointer[i]) && pointer[i] != '"') {
76344361Sborman 				if (noquote) {
76444361Sborman 				    putc('"', NetTrace);
76544361Sborman 				    noquote = 0;
76644361Sborman 				}
76744361Sborman 				putc(pointer[i], NetTrace);
76844361Sborman 			    } else {
76944361Sborman 				fprintf(NetTrace, "\" %03o " + noquote,
77044361Sborman 							pointer[i]);
77144361Sborman 				noquote = 2;
77244361Sborman 			    }
77344361Sborman 			    break;
77444361Sborman 			}
77544361Sborman 		    }
77644361Sborman 		    if (!noquote)
77744361Sborman 			putc('"', NetTrace);
77844361Sborman 		    break;
77944361Sborman 		}
78044361Sborman 	    }
78144361Sborman 	    break;
78244361Sborman 
78332149Sminshall 	default:
78446808Sdab 	    if (TELOPT_OK(pointer[0]))
78546808Sdab 		fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
78646808Sdab 	    else
78756860Storek 		fprintf(NetTrace, "%d (unknown)", pointer[0]);
78846808Sdab 	    for (i = 1; i < length; i++)
78938690Sborman 		fprintf(NetTrace, " %d", pointer[i]);
79038690Sborman 	    break;
79132149Sminshall 	}
79238909Sborman 	if (direction) {
79338909Sborman 	    if (NetTrace == stdout)
79438909Sborman 		fprintf(NetTrace, "\r\n");
79538909Sborman 	    else
79638909Sborman 		fprintf(NetTrace, "\n");
79738909Sborman 	}
79832149Sminshall     }
79932149Sminshall }
80036278Sminshall 
80136278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
80236278Sminshall  *			Note that we consider the buffer to run all the
80336278Sminshall  *			way to the kernel (thus the select).
80436278Sminshall  */
80536278Sminshall 
80646808Sdab     void
80736278Sminshall EmptyTerminal()
80836278Sminshall {
80936278Sminshall #if	defined(unix)
81036278Sminshall     fd_set	o;
81136278Sminshall 
81236278Sminshall     FD_ZERO(&o);
81336278Sminshall #endif	/* defined(unix) */
81436278Sminshall 
81536278Sminshall     if (TTYBYTES() == 0) {
81636278Sminshall #if	defined(unix)
81736278Sminshall 	FD_SET(tout, &o);
81836278Sminshall 	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
81936278Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
82036278Sminshall #endif	/* defined(unix) */
82136278Sminshall     } else {
82236278Sminshall 	while (TTYBYTES()) {
82344361Sborman 	    (void) ttyflush(0);
82436278Sminshall #if	defined(unix)
82536278Sminshall 	    FD_SET(tout, &o);
82636278Sminshall 	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
82736278Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
82836278Sminshall #endif	/* defined(unix) */
82936278Sminshall 	}
83036278Sminshall     }
83136278Sminshall }
83236278Sminshall 
83346808Sdab     void
83436278Sminshall SetForExit()
83536278Sminshall {
83638690Sborman     setconnmode(0);
83736278Sminshall #if	defined(TN3270)
83836278Sminshall     if (In3270) {
83936278Sminshall 	Finish3270();
84036278Sminshall     }
84136279Sminshall #else	/* defined(TN3270) */
84236279Sminshall     do {
84344361Sborman 	(void)telrcv();			/* Process any incoming data */
84436279Sminshall 	EmptyTerminal();
84536279Sminshall     } while (ring_full_count(&netiring));	/* While there is any */
84636278Sminshall #endif	/* defined(TN3270) */
84736278Sminshall     setcommandmode();
84836278Sminshall     fflush(stdout);
84936278Sminshall     fflush(stderr);
85036278Sminshall #if	defined(TN3270)
85136278Sminshall     if (In3270) {
85236278Sminshall 	StopScreen(1);
85336278Sminshall     }
85436278Sminshall #endif	/* defined(TN3270) */
85538690Sborman     setconnmode(0);
85636278Sminshall     EmptyTerminal();			/* Flush the path to the tty */
85736278Sminshall     setcommandmode();
85836278Sminshall }
85936278Sminshall 
86046808Sdab     void
86136278Sminshall Exit(returnCode)
86246808Sdab     int returnCode;
86336278Sminshall {
86436278Sminshall     SetForExit();
86536278Sminshall     exit(returnCode);
86636278Sminshall }
86736278Sminshall 
86846808Sdab     void
86936278Sminshall ExitString(string, returnCode)
87046808Sdab     char *string;
87146808Sdab     int returnCode;
87236278Sminshall {
87336278Sminshall     SetForExit();
87436278Sminshall     fwrite(string, 1, strlen(string), stderr);
87536278Sminshall     exit(returnCode);
87636278Sminshall }
877