xref: /csrg-svn/usr.bin/telnet/utilities.c (revision 46808)
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*46808Sdab static char sccsid[] = "@(#)utilities.c	5.2 (Berkeley) 03/01/91";
1033686Sbostic #endif /* not lint */
1133686Sbostic 
1232149Sminshall #define	TELOPTS
1338690Sborman #define	TELCMDS
14*46808Sdab #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 
40*46808Sdab     void
4132149Sminshall upcase(argument)
42*46808Sdab     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 
60*46808Sdab     int
6132149Sminshall SetSockOpt(fd, level, option, yesno)
62*46808Sdab     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 
83*46808Sdab     void
8438690Sborman SetNetTrace(file)
85*46808Sdab     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) {
92*46808Sdab 	    strcpy((char *)NetTraceFile, file);
9338690Sborman 	    return;
9438690Sborman 	}
9538690Sborman 	fprintf(stderr, "Cannot open %s.\n", file);
9638690Sborman     }
9738690Sborman     NetTrace = stdout;
98*46808Sdab     strcpy((char *)NetTraceFile, "(standard output)");
9938690Sborman }
10038690Sborman 
101*46808Sdab     void
10232149Sminshall Dump(direction, buffer, length)
103*46808Sdab     char direction;
104*46808Sdab     unsigned char *buffer;
105*46808Sdab     int length;
10632149Sminshall {
10732149Sminshall #   define BYTES_PER_LINE	32
10832149Sminshall #   define min(x,y)	((x<y)? x:y)
109*46808Sdab     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 
153*46808Sdab 	void
154*46808Sdab printoption(direction, cmd, option)
155*46808Sdab 	char *direction;
156*46808Sdab 	int cmd, option;
15732149Sminshall {
15832149Sminshall 	if (!showoptions)
15932149Sminshall 		return;
160*46808Sdab 	if (cmd == IAC) {
161*46808Sdab 		if (TELCMD_OK(option))
162*46808Sdab 		    fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
163*46808Sdab 		else
164*46808Sdab 		    fprintf(NetTrace, "%s IAC %d", direction, option);
165*46808Sdab 	} else {
166*46808Sdab 		register char *fmt;
167*46808Sdab 		fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
168*46808Sdab 			(cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
169*46808Sdab 		if (fmt) {
170*46808Sdab 		    fprintf(NetTrace, "%s %s ", direction, fmt);
171*46808Sdab 		    if (TELOPT_OK(option))
172*46808Sdab 			fprintf(NetTrace, "%s", TELOPT(option));
173*46808Sdab 		    else if (option == TELOPT_EXOPL)
174*46808Sdab 			fprintf(NetTrace, "EXOPL");
175*46808Sdab 		    else
176*46808Sdab 			fprintf(NetTrace, "%d", option);
177*46808Sdab 		} else
178*46808Sdab 		    fprintf(NetTrace, "%s %d %d", direction, cmd, option);
179*46808Sdab 	}
18038690Sborman 	if (NetTrace == stdout)
18137226Sminshall 	    fprintf(NetTrace, "\r\n");
18238690Sborman 	else
18337226Sminshall 	    fprintf(NetTrace, "\n");
18437226Sminshall 	return;
18532149Sminshall }
18632149Sminshall 
187*46808Sdab     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 
264*46808Sdab     void
26532149Sminshall printsub(direction, pointer, length)
266*46808Sdab     char direction;	/* '<' or '>' */
267*46808Sdab     unsigned char *pointer;	/* where suboption data sits */
268*46808Sdab     int		  length;	/* length of suboption data */
26932149Sminshall {
27038690Sborman     register int i;
271*46808Sdab     char buf[256];
272*46808Sdab     extern int want_status_response;
27338690Sborman 
274*46808Sdab     if (showoptions || direction == 0 ||
275*46808Sdab 	(want_status_response && (pointer[0] == TELOPT_STATUS))) {
27638909Sborman 	if (direction) {
277*46808Sdab 	    fprintf(NetTrace, "%s IAC SB ",
278*46808Sdab 				(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*46808Sdab #if	defined(AUTHENTICATE)
38943320Skfall 	case TELOPT_AUTHENTICATION:
390*46808Sdab 	    fprintf(NetTrace, "AUTHENTICATION");
391*46808Sdab 	    if (length < 2) {
392*46808Sdab 		fprintf(NetTrace, " (empty suboption???)");
393*46808Sdab 		break;
394*46808Sdab 	    }
39543320Skfall 	    switch (pointer[1]) {
396*46808Sdab 	    case TELQUAL_REPLY:
39743320Skfall 	    case TELQUAL_IS:
398*46808Sdab 		fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
399*46808Sdab 							"IS" : "REPLY");
400*46808Sdab 		if (AUTHTYPE_NAME_OK(pointer[2]))
401*46808Sdab 		    fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
402*46808Sdab 		else
403*46808Sdab 		    fprintf(NetTrace, "%d ", pointer[2]);
404*46808Sdab 		if (length < 3) {
405*46808Sdab 		    fprintf(NetTrace, "(partial suboption???)");
406*46808Sdab 		    break;
407*46808Sdab 		}
408*46808Sdab 		fprintf(NetTrace, "%s|%s",
409*46808Sdab 			(pointer[3] & AUTH_WHO_MASK == AUTH_WHO_CLIENT) ?
410*46808Sdab 			"CLIENT" : "SERVER",
411*46808Sdab 			(pointer[3] & AUTH_HOW_MASK == AUTH_HOW_MUTUAL) ?
412*46808Sdab 			"MUTUAL" : "ONE-WAY");
41343320Skfall 
414*46808Sdab 		auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
415*46808Sdab 		fprintf(NetTrace, "%s", buf);
416*46808Sdab 		break;
417*46808Sdab 
418*46808Sdab 	    case TELQUAL_SEND:
419*46808Sdab 		i = 2;
420*46808Sdab 		fprintf(NetTrace, " SEND ");
421*46808Sdab 		while (i < length) {
422*46808Sdab 		    if (AUTHTYPE_NAME_OK(pointer[i]))
423*46808Sdab 			fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
424*46808Sdab 		    else
425*46808Sdab 			fprintf(NetTrace, "%d ", pointer[i]);
426*46808Sdab 		    if (++i >= length) {
427*46808Sdab 			fprintf(NetTrace, "(partial suboption???)");
42843320Skfall 			break;
429*46808Sdab 		    }
430*46808Sdab 		    fprintf(NetTrace, "%s|%s ",
431*46808Sdab 			(pointer[i] & AUTH_WHO_MASK == AUTH_WHO_CLIENT) ?
432*46808Sdab 							"CLIENT" : "SERVER",
433*46808Sdab 			(pointer[i] & AUTH_HOW_MASK == AUTH_HOW_MUTUAL) ?
434*46808Sdab 							"MUTUAL" : "ONE-WAY");
435*46808Sdab 		    ++i;
43643320Skfall 		}
437*46808Sdab 		break;
43843320Skfall 
439*46808Sdab 	    default:
440*46808Sdab 		    for (i = 2; i < length; i++)
441*46808Sdab 			fprintf(NetTrace, " ?%d?", pointer[i]);
442*46808Sdab 		    break;
44343320Skfall 	    }
444*46808Sdab 	    break;
445*46808Sdab #endif
446*46808Sdab 
447*46808Sdab #if	defined(ENCRYPT)
448*46808Sdab 	case TELOPT_ENCRYPT:
449*46808Sdab 	    fprintf(NetTrace, "ENCRYPT");
450*46808Sdab 	    if (length < 2) {
451*46808Sdab 		fprintf(NetTrace, " (empty suboption???)");
45243320Skfall 		break;
453*46808Sdab 	    }
454*46808Sdab 	    switch (pointer[1]) {
455*46808Sdab 	    case ENCRYPT_START:
456*46808Sdab 		fprintf(NetTrace, " START");
457*46808Sdab 		break;
45843320Skfall 
459*46808Sdab 	    case ENCRYPT_END:
460*46808Sdab 		fprintf(NetTrace, " END");
461*46808Sdab 		break;
462*46808Sdab 
463*46808Sdab 	    case ENCRYPT_REQSTART:
464*46808Sdab 		fprintf(NetTrace, " REQUEST-START");
465*46808Sdab 		break;
466*46808Sdab 
467*46808Sdab 	    case ENCRYPT_REQEND:
468*46808Sdab 		fprintf(NetTrace, " REQUEST-END");
469*46808Sdab 		break;
470*46808Sdab 
471*46808Sdab 	    case ENCRYPT_IS:
472*46808Sdab 	    case ENCRYPT_REPLY:
473*46808Sdab 		fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
474*46808Sdab 							"IS" : "REPLY");
475*46808Sdab 		if (length < 3) {
476*46808Sdab 		    fprintf(NetTrace, " (partial suboption???)");
477*46808Sdab 		    break;
478*46808Sdab 		}
479*46808Sdab 		if (ENCTYPE_NAME_OK(pointer[2]))
480*46808Sdab 		    fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
481*46808Sdab 		else
482*46808Sdab 		    fprintf(NetTrace, " %d (unknown)", pointer[2]);
483*46808Sdab 
484*46808Sdab 		encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
485*46808Sdab 		fprintf(NetTrace, "%s", buf);
486*46808Sdab 		break;
487*46808Sdab 
488*46808Sdab 	    case ENCRYPT_SUPPORT:
489*46808Sdab 		i = 2;
490*46808Sdab 		fprintf(NetTrace, " SUPPORT ");
491*46808Sdab 		while (i < length) {
492*46808Sdab 		    if (ENCTYPE_NAME_OK(pointer[i]))
493*46808Sdab 			fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
494*46808Sdab 		    else
495*46808Sdab 			fprintf(NetTrace, "%d ", pointer[i]);
496*46808Sdab 		    i++;
497*46808Sdab 		}
498*46808Sdab 		break;
499*46808Sdab 
50043320Skfall 	    default:
501*46808Sdab 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
502*46808Sdab 		for (i = 2; i < length; i++)
503*46808Sdab 		    fprintf(NetTrace, " %d", pointer[i]);
504*46808Sdab 		break;
50543320Skfall 	    }
50643320Skfall 	    break;
507*46808Sdab #endif
50843320Skfall 
50938690Sborman 	case TELOPT_LINEMODE:
51038690Sborman 	    fprintf(NetTrace, "LINEMODE ");
51138690Sborman 	    if (length < 2) {
51238690Sborman 		fprintf(NetTrace, " (empty suboption???)");
51338690Sborman 		break;
51438690Sborman 	    }
51538690Sborman 	    switch (pointer[1]) {
51638690Sborman 	    case WILL:
51738690Sborman 		fprintf(NetTrace, "WILL ");
51838690Sborman 		goto common;
51938690Sborman 	    case WONT:
52038690Sborman 		fprintf(NetTrace, "WONT ");
52138690Sborman 		goto common;
52238690Sborman 	    case DO:
52338690Sborman 		fprintf(NetTrace, "DO ");
52438690Sborman 		goto common;
52538690Sborman 	    case DONT:
52638690Sborman 		fprintf(NetTrace, "DONT ");
52738690Sborman 	    common:
52838690Sborman 		if (length < 3) {
52938690Sborman 		    fprintf(NetTrace, "(no option???)");
53038690Sborman 		    break;
53138690Sborman 		}
53238690Sborman 		switch (pointer[2]) {
53338690Sborman 		case LM_FORWARDMASK:
53438690Sborman 		    fprintf(NetTrace, "Forward Mask");
53538690Sborman 		    for (i = 3; i < length; i++)
53638690Sborman 			fprintf(NetTrace, " %x", pointer[i]);
53738690Sborman 		    break;
53838690Sborman 		default:
53938690Sborman 		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
54038690Sborman 		    for (i = 3; i < length; i++)
54138690Sborman 			fprintf(NetTrace, " %d", pointer[i]);
54238690Sborman 		    break;
54338690Sborman 		}
54438690Sborman 		break;
54538690Sborman 
54638690Sborman 	    case LM_SLC:
54738690Sborman 		fprintf(NetTrace, "SLC");
54838690Sborman 		for (i = 2; i < length - 2; i += 3) {
549*46808Sdab 		    if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
550*46808Sdab 			fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
55138690Sborman 		    else
55238690Sborman 			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
55338690Sborman 		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
55438690Sborman 		    case SLC_NOSUPPORT:
55538690Sborman 			fprintf(NetTrace, " NOSUPPORT"); break;
55638690Sborman 		    case SLC_CANTCHANGE:
55738690Sborman 			fprintf(NetTrace, " CANTCHANGE"); break;
55838690Sborman 		    case SLC_VARIABLE:
55938690Sborman 			fprintf(NetTrace, " VARIABLE"); break;
56038690Sborman 		    case SLC_DEFAULT:
56138690Sborman 			fprintf(NetTrace, " DEFAULT"); break;
56238690Sborman 		    }
56338690Sborman 		    fprintf(NetTrace, "%s%s%s",
56438690Sborman 			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
56538690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
56638690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
56738690Sborman 		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
56838690Sborman 						SLC_FLUSHOUT| SLC_LEVELBITS))
56938690Sborman 			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
57038690Sborman 		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
57144361Sborman 		    if ((pointer[i+SLC_VALUE] == IAC) &&
57244361Sborman 			(pointer[i+SLC_VALUE+1] == IAC))
57344361Sborman 				i++;
57438690Sborman 		}
57538690Sborman 		for (; i < length; i++)
57638690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
57738690Sborman 		break;
57838690Sborman 
57938690Sborman 	    case LM_MODE:
58038690Sborman 		fprintf(NetTrace, "MODE ");
58138690Sborman 		if (length < 3) {
58238690Sborman 		    fprintf(NetTrace, "(no mode???)");
58338690Sborman 		    break;
58438690Sborman 		}
58538690Sborman 		{
58644361Sborman 		    char tbuf[64];
58744361Sborman 		    sprintf(tbuf, "%s%s%s%s%s",
58838690Sborman 			pointer[2]&MODE_EDIT ? "|EDIT" : "",
58938690Sborman 			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
59044361Sborman 			pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
59144361Sborman 			pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
59238690Sborman 			pointer[2]&MODE_ACK ? "|ACK" : "");
59338690Sborman 		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
59438690Sborman 		}
595*46808Sdab 		if (pointer[2]&~(MODE_MASK))
59638690Sborman 		    fprintf(NetTrace, " (0x%x)", pointer[2]);
59738690Sborman 		for (i = 3; i < length; i++)
59838690Sborman 		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
59938690Sborman 		break;
60038690Sborman 	    default:
60138690Sborman 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
60238690Sborman 		for (i = 2; i < length; i++)
60338690Sborman 		    fprintf(NetTrace, " %d", pointer[i]);
60438690Sborman 	    }
60538690Sborman 	    break;
60638690Sborman 
60738909Sborman 	case TELOPT_STATUS: {
60838909Sborman 	    register char *cp;
60938909Sborman 	    register int j, k;
61038909Sborman 
61138909Sborman 	    fprintf(NetTrace, "STATUS");
61238909Sborman 
61338909Sborman 	    switch (pointer[1]) {
61438909Sborman 	    default:
61538909Sborman 		if (pointer[1] == TELQUAL_SEND)
61638909Sborman 		    fprintf(NetTrace, " SEND");
61738909Sborman 		else
61844361Sborman 		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
61938909Sborman 		for (i = 2; i < length; i++)
62038909Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
62138909Sborman 		break;
62238909Sborman 	    case TELQUAL_IS:
623*46808Sdab 		if (--want_status_response < 0)
624*46808Sdab 		    want_status_response = 0;
62538909Sborman 		if (NetTrace == stdout)
62638909Sborman 		    fprintf(NetTrace, " IS\r\n");
62738909Sborman 		else
62838909Sborman 		    fprintf(NetTrace, " IS\n");
62938909Sborman 
63038909Sborman 		for (i = 2; i < length; i++) {
63138909Sborman 		    switch(pointer[i]) {
63238909Sborman 		    case DO:	cp = "DO"; goto common2;
63338909Sborman 		    case DONT:	cp = "DONT"; goto common2;
63438909Sborman 		    case WILL:	cp = "WILL"; goto common2;
63538909Sborman 		    case WONT:	cp = "WONT"; goto common2;
63638909Sborman 		    common2:
63738909Sborman 			i++;
63844361Sborman 			if (TELOPT_OK((int)pointer[i]))
63938909Sborman 			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
64038909Sborman 			else
64138909Sborman 			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
64238909Sborman 
64338909Sborman 			if (NetTrace == stdout)
64438909Sborman 			    fprintf(NetTrace, "\r\n");
64538909Sborman 			else
64638909Sborman 			    fprintf(NetTrace, "\n");
64738909Sborman 			break;
64838909Sborman 
64938909Sborman 		    case SB:
65038909Sborman 			fprintf(NetTrace, " SB ");
65138909Sborman 			i++;
65238909Sborman 			j = k = i;
65338909Sborman 			while (j < length) {
65438909Sborman 			    if (pointer[j] == SE) {
65538909Sborman 				if (j+1 == length)
65638909Sborman 				    break;
65738909Sborman 				if (pointer[j+1] == SE)
65838909Sborman 				    j++;
65938909Sborman 				else
66038909Sborman 				    break;
66138909Sborman 			    }
66238909Sborman 			    pointer[k++] = pointer[j++];
66338909Sborman 			}
66438909Sborman 			printsub(0, &pointer[i], k - i);
66538909Sborman 			if (i < length) {
66638909Sborman 			    fprintf(NetTrace, " SE");
66738909Sborman 			    i = j;
66838909Sborman 			} else
66938909Sborman 			    i = j - 1;
67038909Sborman 
67138909Sborman 			if (NetTrace == stdout)
67238909Sborman 			    fprintf(NetTrace, "\r\n");
67338909Sborman 			else
67438909Sborman 			    fprintf(NetTrace, "\n");
67538909Sborman 
67638909Sborman 			break;
67738909Sborman 
67838909Sborman 		    default:
67938909Sborman 			fprintf(NetTrace, " %d", pointer[i]);
68038909Sborman 			break;
68138909Sborman 		    }
68238909Sborman 		}
68338909Sborman 		break;
68438909Sborman 	    }
68538909Sborman 	    break;
68638909Sborman 	  }
68738909Sborman 
68844361Sborman 	case TELOPT_XDISPLOC:
68944361Sborman 	    fprintf(NetTrace, "X-DISPLAY-LOCATION ");
69044361Sborman 	    switch (pointer[1]) {
69144361Sborman 	    case TELQUAL_IS:
69244361Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
69344361Sborman 		break;
69444361Sborman 	    case TELQUAL_SEND:
69544361Sborman 		fprintf(NetTrace, "SEND");
69644361Sborman 		break;
69744361Sborman 	    default:
69844361Sborman 		fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
69944361Sborman 				pointer[1], pointer[1]);
70044361Sborman 	    }
70144361Sborman 	    break;
70244361Sborman 
70344361Sborman 	case TELOPT_ENVIRON:
70444361Sborman 	    fprintf(NetTrace, "ENVIRON ");
70544361Sborman 	    switch (pointer[1]) {
70644361Sborman 	    case TELQUAL_IS:
70744361Sborman 		fprintf(NetTrace, "IS ");
70844361Sborman 		goto env_common;
70944361Sborman 	    case TELQUAL_SEND:
71044361Sborman 		fprintf(NetTrace, "SEND ");
71144361Sborman 		goto env_common;
71244361Sborman 	    case TELQUAL_INFO:
71344361Sborman 		fprintf(NetTrace, "INFO ");
71444361Sborman 	    env_common:
71544361Sborman 		{
71644361Sborman 		    register int noquote = 2;
71744361Sborman 		    for (i = 2; i < length; i++ ) {
71844361Sborman 			switch (pointer[i]) {
71944361Sborman 			case ENV_VAR:
72044361Sborman 			    if (pointer[1] == TELQUAL_SEND)
72144361Sborman 				goto def_case;
72244361Sborman 			    fprintf(NetTrace, "\" VAR " + noquote);
72344361Sborman 			    noquote = 2;
72444361Sborman 			    break;
72544361Sborman 
72644361Sborman 			case ENV_VALUE:
72744361Sborman 			    fprintf(NetTrace, "\" VALUE " + noquote);
72844361Sborman 			    noquote = 2;
72944361Sborman 			    break;
73044361Sborman 
73144361Sborman 			case ENV_ESC:
73244361Sborman 			    fprintf(NetTrace, "\" ESC " + noquote);
73344361Sborman 			    noquote = 2;
73444361Sborman 			    break;
73544361Sborman 
73644361Sborman 			default:
73744361Sborman 			def_case:
73844361Sborman 			    if (isprint(pointer[i]) && pointer[i] != '"') {
73944361Sborman 				if (noquote) {
74044361Sborman 				    putc('"', NetTrace);
74144361Sborman 				    noquote = 0;
74244361Sborman 				}
74344361Sborman 				putc(pointer[i], NetTrace);
74444361Sborman 			    } else {
74544361Sborman 				fprintf(NetTrace, "\" %03o " + noquote,
74644361Sborman 							pointer[i]);
74744361Sborman 				noquote = 2;
74844361Sborman 			    }
74944361Sborman 			    break;
75044361Sborman 			}
75144361Sborman 		    }
75244361Sborman 		    if (!noquote)
75344361Sborman 			putc('"', NetTrace);
75444361Sborman 		    break;
75544361Sborman 		}
75644361Sborman 	    }
75744361Sborman 	    break;
75844361Sborman 
75932149Sminshall 	default:
760*46808Sdab 	    if (TELOPT_OK(pointer[0]))
761*46808Sdab 		fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
762*46808Sdab 	    else
763*46808Sdab 		fprintf(NetTrace, "%d (unknown)", pointer[i]);
764*46808Sdab 	    for (i = 1; i < length; i++)
76538690Sborman 		fprintf(NetTrace, " %d", pointer[i]);
76638690Sborman 	    break;
76732149Sminshall 	}
76838909Sborman 	if (direction) {
76938909Sborman 	    if (NetTrace == stdout)
77038909Sborman 		fprintf(NetTrace, "\r\n");
77138909Sborman 	    else
77238909Sborman 		fprintf(NetTrace, "\n");
77338909Sborman 	}
77432149Sminshall     }
77532149Sminshall }
77636278Sminshall 
77736278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
77836278Sminshall  *			Note that we consider the buffer to run all the
77936278Sminshall  *			way to the kernel (thus the select).
78036278Sminshall  */
78136278Sminshall 
782*46808Sdab     void
78336278Sminshall EmptyTerminal()
78436278Sminshall {
78536278Sminshall #if	defined(unix)
78636278Sminshall     fd_set	o;
78736278Sminshall 
78836278Sminshall     FD_ZERO(&o);
78936278Sminshall #endif	/* defined(unix) */
79036278Sminshall 
79136278Sminshall     if (TTYBYTES() == 0) {
79236278Sminshall #if	defined(unix)
79336278Sminshall 	FD_SET(tout, &o);
79436278Sminshall 	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
79536278Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
79636278Sminshall #endif	/* defined(unix) */
79736278Sminshall     } else {
79836278Sminshall 	while (TTYBYTES()) {
79944361Sborman 	    (void) ttyflush(0);
80036278Sminshall #if	defined(unix)
80136278Sminshall 	    FD_SET(tout, &o);
80236278Sminshall 	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
80336278Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
80436278Sminshall #endif	/* defined(unix) */
80536278Sminshall 	}
80636278Sminshall     }
80736278Sminshall }
80836278Sminshall 
809*46808Sdab     void
81036278Sminshall SetForExit()
81136278Sminshall {
81238690Sborman     setconnmode(0);
81336278Sminshall #if	defined(TN3270)
81436278Sminshall     if (In3270) {
81536278Sminshall 	Finish3270();
81636278Sminshall     }
81736279Sminshall #else	/* defined(TN3270) */
81836279Sminshall     do {
81944361Sborman 	(void)telrcv();			/* Process any incoming data */
82036279Sminshall 	EmptyTerminal();
82136279Sminshall     } while (ring_full_count(&netiring));	/* While there is any */
82236278Sminshall #endif	/* defined(TN3270) */
82336278Sminshall     setcommandmode();
82436278Sminshall     fflush(stdout);
82536278Sminshall     fflush(stderr);
82636278Sminshall #if	defined(TN3270)
82736278Sminshall     if (In3270) {
82836278Sminshall 	StopScreen(1);
82936278Sminshall     }
83036278Sminshall #endif	/* defined(TN3270) */
83138690Sborman     setconnmode(0);
83236278Sminshall     EmptyTerminal();			/* Flush the path to the tty */
83336278Sminshall     setcommandmode();
83436278Sminshall }
83536278Sminshall 
836*46808Sdab     void
83736278Sminshall Exit(returnCode)
838*46808Sdab     int returnCode;
83936278Sminshall {
84036278Sminshall     SetForExit();
84136278Sminshall     exit(returnCode);
84236278Sminshall }
84336278Sminshall 
844*46808Sdab     void
84536278Sminshall ExitString(string, returnCode)
846*46808Sdab     char *string;
847*46808Sdab     int returnCode;
84836278Sminshall {
84936278Sminshall     SetForExit();
85036278Sminshall     fwrite(string, 1, strlen(string), stderr);
85136278Sminshall     exit(returnCode);
85236278Sminshall }
853