xref: /csrg-svn/usr.bin/telnet/utilities.c (revision 43320)
133686Sbostic /*
233686Sbostic  * Copyright (c) 1988 Regents of the University of California.
333686Sbostic  * All rights reserved.
433686Sbostic  *
5*43320Skfall  * Redistribution and use in source and binary forms are permitted
6*43320Skfall  * provided that: (1) source distributions retain this entire copyright
7*43320Skfall  * notice and comment, and (2) distributions including binaries display
8*43320Skfall  * the following acknowledgement:  ``This product includes software
9*43320Skfall  * developed by the University of California, Berkeley and its contributors''
10*43320Skfall  * in the documentation or other materials provided with the distribution
11*43320Skfall  * and in all advertising materials mentioning features or use of this
12*43320Skfall  * software. Neither the name of the University nor the names of its
13*43320Skfall  * contributors may be used to endorse or promote products derived
14*43320Skfall  * from this software without specific prior written permission.
15*43320Skfall  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16*43320Skfall  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17*43320Skfall  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1833686Sbostic  */
1933686Sbostic 
2033686Sbostic #ifndef lint
21*43320Skfall static char sccsid[] = "@(#)utilities.c	1.17 (Berkeley) 6/1/90";
2233686Sbostic #endif /* not lint */
2333686Sbostic 
2432149Sminshall #define	TELOPTS
2538690Sborman #define	TELCMDS
2632149Sminshall #include <arpa/telnet.h>
2732381Sminshall #include <sys/types.h>
2832149Sminshall 
2932149Sminshall #include <ctype.h>
3032149Sminshall 
3134305Sminshall #include "general.h"
3234305Sminshall 
3336280Sminshall #include "fdset.h"
3436280Sminshall 
3532381Sminshall #include "ring.h"
3632381Sminshall 
3736278Sminshall #include "defines.h"
3836278Sminshall 
3932149Sminshall #include "externs.h"
4032149Sminshall 
4132149Sminshall FILE	*NetTrace = 0;		/* Not in bss, since needs to stay */
4238690Sborman int	prettydump;
4332149Sminshall 
4432149Sminshall /*
4532149Sminshall  * upcase()
4632149Sminshall  *
4732149Sminshall  *	Upcase (in place) the argument.
4832149Sminshall  */
4932149Sminshall 
5032149Sminshall void
5132149Sminshall upcase(argument)
5232149Sminshall register char *argument;
5332149Sminshall {
5432149Sminshall     register int c;
5532149Sminshall 
5632149Sminshall     while ((c = *argument) != 0) {
5732149Sminshall 	if (islower(c)) {
5832149Sminshall 	    *argument = toupper(c);
5932149Sminshall 	}
6032149Sminshall 	argument++;
6132149Sminshall     }
6232149Sminshall }
6332149Sminshall 
6432149Sminshall /*
6532149Sminshall  * SetSockOpt()
6632149Sminshall  *
6732149Sminshall  * Compensate for differences in 4.2 and 4.3 systems.
6832149Sminshall  */
6932149Sminshall 
7032149Sminshall int
7132149Sminshall SetSockOpt(fd, level, option, yesno)
7232149Sminshall int
7332149Sminshall 	fd,
7432149Sminshall 	level,
7532149Sminshall 	option,
7632149Sminshall 	yesno;
7732149Sminshall {
7832149Sminshall #ifndef	NOT43
7932149Sminshall     return setsockopt(fd, level, option,
8032149Sminshall 				(char *)&yesno, sizeof yesno);
8132149Sminshall #else	/* NOT43 */
8232149Sminshall     if (yesno == 0) {		/* Can't do that in 4.2! */
8332149Sminshall 	fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
8432149Sminshall 				option);
8532149Sminshall 	return -1;
8632149Sminshall     }
8732149Sminshall     return setsockopt(fd, level, option, 0, 0);
8832149Sminshall #endif	/* NOT43 */
8932149Sminshall }
9032149Sminshall 
9132149Sminshall /*
9232149Sminshall  * The following are routines used to print out debugging information.
9332149Sminshall  */
9432149Sminshall 
9539529Sborman unsigned char NetTraceFile[256] = "(standard output)";
9632149Sminshall 
9732149Sminshall void
9838690Sborman SetNetTrace(file)
9938690Sborman register char *file;
10038690Sborman {
10138690Sborman     if (NetTrace && NetTrace != stdout)
10238690Sborman 	fclose(NetTrace);
10338690Sborman     if (file  && (strcmp(file, "-") != 0)) {
10438690Sborman 	NetTrace = fopen(file, "w");
10538690Sborman 	if (NetTrace) {
10638690Sborman 	    strcpy(NetTraceFile, file);
10738690Sborman 	    return;
10838690Sborman 	}
10938690Sborman 	fprintf(stderr, "Cannot open %s.\n", file);
11038690Sborman     }
11138690Sborman     NetTrace = stdout;
11238690Sborman     strcpy(NetTraceFile, "(standard output)");
11338690Sborman }
11438690Sborman 
11538690Sborman void
11632149Sminshall Dump(direction, buffer, length)
11732149Sminshall char	direction;
11832149Sminshall char	*buffer;
11932149Sminshall int	length;
12032149Sminshall {
12132149Sminshall #   define BYTES_PER_LINE	32
12232149Sminshall #   define min(x,y)	((x<y)? x:y)
12332149Sminshall     char *pThis;
12432149Sminshall     int offset;
12538690Sborman     extern pettydump;
12632149Sminshall 
12732149Sminshall     offset = 0;
12832149Sminshall 
12932149Sminshall     while (length) {
13032149Sminshall 	/* print one line */
13132149Sminshall 	fprintf(NetTrace, "%c 0x%x\t", direction, offset);
13232149Sminshall 	pThis = buffer;
13338690Sborman 	if (prettydump) {
13438909Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE/2);
13538690Sborman 	    while (pThis < buffer) {
13638690Sborman 		fprintf(NetTrace, "%c%.2x",
13738690Sborman 		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
13838690Sborman 		    (*pThis)&0xff);
13938690Sborman 		pThis++;
14038690Sborman 	    }
14138909Sborman 	    length -= BYTES_PER_LINE/2;
14238909Sborman 	    offset += BYTES_PER_LINE/2;
14338690Sborman 	} else {
14438909Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE);
14538690Sborman 	    while (pThis < buffer) {
14638690Sborman 		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
14738690Sborman 		pThis++;
14838690Sborman 	    }
14938909Sborman 	    length -= BYTES_PER_LINE;
15038909Sborman 	    offset += BYTES_PER_LINE;
15132149Sminshall 	}
15237226Sminshall 	if (NetTrace == stdout) {
15338207Sminshall 	    fprintf(NetTrace, "\r\n");
15438207Sminshall 	} else {
15537226Sminshall 	    fprintf(NetTrace, "\n");
15637226Sminshall 	}
15732149Sminshall 	if (length < 0) {
15836693Sminshall 	    fflush(NetTrace);
15932149Sminshall 	    return;
16032149Sminshall 	}
16132149Sminshall 	/* find next unique line */
16232149Sminshall     }
16336693Sminshall     fflush(NetTrace);
16432149Sminshall }
16532149Sminshall 
16632149Sminshall 
16732149Sminshall void
16837226Sminshall printoption(direction, fmt, option)
16932149Sminshall 	char *direction, *fmt;
17037226Sminshall 	int option;
17132149Sminshall {
17232149Sminshall 	if (!showoptions)
17332149Sminshall 		return;
17437226Sminshall 	fprintf(NetTrace, "%s ", direction);
17538690Sborman 	if (TELOPT_OK(option))
17638690Sborman 		fprintf(NetTrace, "%s %s", fmt, TELOPT(option));
17738690Sborman 	else if (TELCMD_OK(option))
17838690Sborman 		fprintf(NetTrace, "%s %s", fmt, TELCMD(option));
17932149Sminshall 	else
18032149Sminshall 		fprintf(NetTrace, "%s %d", fmt, option);
18138690Sborman 	if (NetTrace == stdout)
18237226Sminshall 	    fprintf(NetTrace, "\r\n");
18338690Sborman 	else
18437226Sminshall 	    fprintf(NetTrace, "\n");
18537226Sminshall 	return;
18632149Sminshall }
18732149Sminshall 
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 
26438690Sborman char *slcnames[] = { SLC_NAMES };
26538690Sborman 
266*43320Skfall #ifdef	KERBEROS
267*43320Skfall static char *authtypes[3] = { "NONE", "PRIVATE", "KERBEROS" };
268*43320Skfall #else
269*43320Skfall static char *authtypes[2] = { "NONE", "PRIVATE" };
270*43320Skfall #endif
271*43320Skfall 
27232149Sminshall void
27332149Sminshall printsub(direction, pointer, length)
27438690Sborman char	direction;		/* '<' or '>' */
27538690Sborman unsigned char	*pointer;	/* where suboption data sits */
27632149Sminshall int	length;			/* length of suboption data */
27732149Sminshall {
27838690Sborman     register int i;
27938690Sborman 
28032149Sminshall     if (showoptions) {
28138909Sborman 	if (direction) {
28238909Sborman 	    fprintf(NetTrace, "%s suboption ",
28338690Sborman 				(direction == '<')? "Received":"Sent");
28438909Sborman 	    if (length >= 3) {
28538909Sborman 		register int j;
28638690Sborman 
28738909Sborman 		i = pointer[length-2];
28838909Sborman 		j = pointer[length-1];
28938690Sborman 
29038909Sborman 		if (i != IAC || j != SE) {
29138909Sborman 		    fprintf(NetTrace, "(terminated by ");
29238909Sborman 		    if (TELOPT_OK(i))
29338909Sborman 			fprintf(NetTrace, "%s ", TELOPT(i));
29438909Sborman 		    else if (TELCMD_OK(i))
29538909Sborman 			fprintf(NetTrace, "%s ", TELCMD(i));
29638909Sborman 		    else
29738909Sborman 			fprintf(NetTrace, "%d ", i);
29838909Sborman 		    if (TELOPT_OK(j))
29938909Sborman 			fprintf(NetTrace, "%s", TELOPT(j));
30038909Sborman 		    else if (TELCMD_OK(j))
30138909Sborman 			fprintf(NetTrace, "%s", TELCMD(j));
30238909Sborman 		    else
30338909Sborman 			fprintf(NetTrace, "%d", j);
30438909Sborman 		    fprintf(NetTrace, ", not IAC SE!) ");
30538909Sborman 		}
30638690Sborman 	    }
30738909Sborman 	    length -= 2;
30838690Sborman 	}
30938690Sborman 	if (length < 1) {
31038690Sborman 	    fprintf(NetTrace, "(Empty suboption???)");
31138690Sborman 	    return;
31238690Sborman 	}
31332149Sminshall 	switch (pointer[0]) {
31432149Sminshall 	case TELOPT_TTYPE:
31538690Sborman 	    fprintf(NetTrace, "TERMINAL-TYPE ");
31632149Sminshall 	    switch (pointer[1]) {
31732149Sminshall 	    case TELQUAL_IS:
31838690Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, pointer+2);
31932149Sminshall 		break;
32032149Sminshall 	    case TELQUAL_SEND:
32138690Sborman 		fprintf(NetTrace, "SEND");
32232149Sminshall 		break;
32332149Sminshall 	    default:
32432149Sminshall 		fprintf(NetTrace,
32538690Sborman 				"- unknown qualifier %d (0x%x).",
32634849Sminshall 				pointer[1], pointer[1]);
32732149Sminshall 	    }
32832149Sminshall 	    break;
32938690Sborman 	case TELOPT_TSPEED:
33038690Sborman 	    fprintf(NetTrace, "TERMINAL-SPEED");
33138690Sborman 	    if (length < 2) {
33238690Sborman 		fprintf(NetTrace, " (empty suboption???)");
33338690Sborman 		break;
33438690Sborman 	    }
33538690Sborman 	    switch (pointer[1]) {
33638909Sborman 	    case TELQUAL_IS:
33738690Sborman 		fprintf(NetTrace, " IS ");
33838690Sborman 		fprintf(NetTrace, "%.*s", length-2, pointer+2);
33938690Sborman 		break;
34038690Sborman 	    default:
34138690Sborman 		if (pointer[1] == 1)
34238690Sborman 		    fprintf(NetTrace, " SEND");
34338690Sborman 		else
34438690Sborman 		    fprintf(NetTrace, " %d (unknown)");
34538690Sborman 		for (i = 2; i < length; i++)
34638690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
34738690Sborman 		break;
34838690Sborman 	    }
34938690Sborman 	    break;
35038690Sborman 
35138690Sborman 	case TELOPT_LFLOW:
35238690Sborman 	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
35338690Sborman 	    if (length < 2) {
35438690Sborman 		fprintf(NetTrace, " (empty suboption???)");
35538690Sborman 		break;
35638690Sborman 	    }
35738690Sborman 	    switch (pointer[1]) {
35838690Sborman 	    case 0:
35938690Sborman 		fprintf(NetTrace, " OFF"); break;
36038690Sborman 	    case 1:
36138690Sborman 		fprintf(NetTrace, " ON"); break;
36238690Sborman 	    default:
36338690Sborman 		fprintf(NetTrace, " %d (unknown)");
36438690Sborman 	    }
36538690Sborman 	    for (i = 2; i < length; i++)
36638690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
36738690Sborman 	    break;
36838690Sborman 
36938690Sborman 	case TELOPT_NAWS:
37038690Sborman 	    fprintf(NetTrace, "NAWS");
37138690Sborman 	    if (length < 2) {
37238690Sborman 		fprintf(NetTrace, " (empty suboption???)");
37338690Sborman 		break;
37438690Sborman 	    }
37538690Sborman 	    if (length == 2) {
37638690Sborman 		fprintf(NetTrace, " ?%d?", pointer[1]);
37738690Sborman 		break;
37838690Sborman 	    }
37938690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
38038690Sborman 		pointer[1], pointer[2],
38138690Sborman 		(((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]));
38238690Sborman 	    if (length == 4) {
38338690Sborman 		fprintf(NetTrace, " ?%d?", pointer[3]);
38438690Sborman 		break;
38538690Sborman 	    }
38638690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
38738690Sborman 		pointer[3], pointer[4],
38838690Sborman 		(((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]));
38938690Sborman 	    for (i = 5; i < length; i++)
39038690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
39138690Sborman 	    break;
39238690Sborman 
393*43320Skfall #ifdef	KERBEROS
394*43320Skfall 	case TELOPT_AUTHENTICATION:
395*43320Skfall 	    fprintf(NetTrace, "Authentication information ");
396*43320Skfall 	    switch (pointer[1]) {
397*43320Skfall 	    case TELQUAL_IS:
398*43320Skfall 		switch (pointer[2]) {
399*43320Skfall 		case TELQUAL_AUTHTYPE_NONE:
400*43320Skfall 		case TELQUAL_AUTHTYPE_PRIVATE:
401*43320Skfall 		case TELQUAL_AUTHTYPE_KERBEROS:
402*43320Skfall 
403*43320Skfall 			fprintf(NetTrace, "is type %s\r\n", authtypes[pointer[2]]);
404*43320Skfall 			break;
405*43320Skfall 		default:
406*43320Skfall 			fprintf(NetTrace, "is type unknown\r\n");
407*43320Skfall 			break;
408*43320Skfall 		}
409*43320Skfall 
410*43320Skfall 	    case TELQUAL_SEND:
411*43320Skfall 	    {
412*43320Skfall 		int	idx = 2;
413*43320Skfall 		fprintf(NetTrace, "- request to send, types");
414*43320Skfall 		for (idx = 2; idx < length - 1; idx++)
415*43320Skfall 			switch (pointer[idx]) {
416*43320Skfall 			case TELQUAL_AUTHTYPE_NONE:
417*43320Skfall 			case TELQUAL_AUTHTYPE_PRIVATE:
418*43320Skfall 			case TELQUAL_AUTHTYPE_KERBEROS:
419*43320Skfall 				fprintf(NetTrace, " %s",
420*43320Skfall 					authtypes[pointer[idx]]);
421*43320Skfall 					break;
422*43320Skfall 			default:
423*43320Skfall 				fprintf(NetTrace, " <unknown %u>",
424*43320Skfall 					pointer[idx]);
425*43320Skfall 				break;
426*43320Skfall 			}
427*43320Skfall 		fprintf(NetTrace, "\r\n");
428*43320Skfall 	    }
429*43320Skfall 		break;
430*43320Skfall 
431*43320Skfall 	    default:
432*43320Skfall 		fprintf(NetTrace, " - unknown qualifier %d (0x%x).\r\n",
433*43320Skfall 			pointer[1], pointer[1]);
434*43320Skfall 	    }
435*43320Skfall 	    break;
436*43320Skfall #endif /* KERBEROS */
437*43320Skfall 
43838690Sborman 	case TELOPT_LINEMODE:
43938690Sborman 	    fprintf(NetTrace, "LINEMODE ");
44038690Sborman 	    if (length < 2) {
44138690Sborman 		fprintf(NetTrace, " (empty suboption???)");
44238690Sborman 		break;
44338690Sborman 	    }
44438690Sborman 	    switch (pointer[1]) {
44538690Sborman 	    case WILL:
44638690Sborman 		fprintf(NetTrace, "WILL ");
44738690Sborman 		goto common;
44838690Sborman 	    case WONT:
44938690Sborman 		fprintf(NetTrace, "WONT ");
45038690Sborman 		goto common;
45138690Sborman 	    case DO:
45238690Sborman 		fprintf(NetTrace, "DO ");
45338690Sborman 		goto common;
45438690Sborman 	    case DONT:
45538690Sborman 		fprintf(NetTrace, "DONT ");
45638690Sborman 	    common:
45738690Sborman 		if (length < 3) {
45838690Sborman 		    fprintf(NetTrace, "(no option???)");
45938690Sborman 		    break;
46038690Sborman 		}
46138690Sborman 		switch (pointer[2]) {
46238690Sborman 		case LM_FORWARDMASK:
46338690Sborman 		    fprintf(NetTrace, "Forward Mask");
46438690Sborman 		    for (i = 3; i < length; i++)
46538690Sborman 			fprintf(NetTrace, " %x", pointer[i]);
46638690Sborman 		    break;
46738690Sborman 		default:
46838690Sborman 		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
46938690Sborman 		    for (i = 3; i < length; i++)
47038690Sborman 			fprintf(NetTrace, " %d", pointer[i]);
47138690Sborman 		    break;
47238690Sborman 		}
47338690Sborman 		break;
47438690Sborman 
47538690Sborman 	    case LM_SLC:
47638690Sborman 		fprintf(NetTrace, "SLC");
47738690Sborman 		for (i = 2; i < length - 2; i += 3) {
47838690Sborman 		    if (pointer[i+SLC_FUNC] <= NSLC)
47938690Sborman 			fprintf(NetTrace, " %s", slcnames[pointer[i+SLC_FUNC]]);
48038690Sborman 		    else
48138690Sborman 			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
48238690Sborman 		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
48338690Sborman 		    case SLC_NOSUPPORT:
48438690Sborman 			fprintf(NetTrace, " NOSUPPORT"); break;
48538690Sborman 		    case SLC_CANTCHANGE:
48638690Sborman 			fprintf(NetTrace, " CANTCHANGE"); break;
48738690Sborman 		    case SLC_VARIABLE:
48838690Sborman 			fprintf(NetTrace, " VARIABLE"); break;
48938690Sborman 		    case SLC_DEFAULT:
49038690Sborman 			fprintf(NetTrace, " DEFAULT"); break;
49138690Sborman 		    }
49238690Sborman 		    fprintf(NetTrace, "%s%s%s",
49338690Sborman 			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
49438690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
49538690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
49638690Sborman 		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
49738690Sborman 						SLC_FLUSHOUT| SLC_LEVELBITS))
49838690Sborman 			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
49938690Sborman 		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
50038690Sborman 		}
50138690Sborman 		for (; i < length; i++)
50238690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
50338690Sborman 		break;
50438690Sborman 
50538690Sborman 	    case LM_MODE:
50638690Sborman 		fprintf(NetTrace, "MODE ");
50738690Sborman 		if (length < 3) {
50838690Sborman 		    fprintf(NetTrace, "(no mode???)");
50938690Sborman 		    break;
51038690Sborman 		}
51138690Sborman 		{
51238690Sborman 		    char tbuf[32];
51338690Sborman 		    sprintf(tbuf, "%s%s%s",
51438690Sborman 			pointer[2]&MODE_EDIT ? "|EDIT" : "",
51538690Sborman 			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
51638690Sborman 			pointer[2]&MODE_ACK ? "|ACK" : "");
51738690Sborman 		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
51838690Sborman 		}
51938690Sborman 		if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
52038690Sborman 		    fprintf(NetTrace, " (0x%x)", pointer[2]);
52138690Sborman 		for (i = 3; i < length; i++)
52238690Sborman 		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
52338690Sborman 		break;
52438690Sborman 	    default:
52538690Sborman 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
52638690Sborman 		for (i = 2; i < length; i++)
52738690Sborman 		    fprintf(NetTrace, " %d", pointer[i]);
52838690Sborman 	    }
52938690Sborman 	    break;
53038690Sborman 
53138909Sborman 	case TELOPT_STATUS: {
53238909Sborman 	    register char *cp;
53338909Sborman 	    register int j, k;
53438909Sborman 
53538909Sborman 	    fprintf(NetTrace, "STATUS");
53638909Sborman 
53738909Sborman 	    switch (pointer[1]) {
53838909Sborman 	    default:
53938909Sborman 		if (pointer[1] == TELQUAL_SEND)
54038909Sborman 		    fprintf(NetTrace, " SEND");
54138909Sborman 		else
54238909Sborman 		    fprintf(NetTrace, " %d (unknown)");
54338909Sborman 		for (i = 2; i < length; i++)
54438909Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
54538909Sborman 		break;
54638909Sborman 	    case TELQUAL_IS:
54738909Sborman 		if (NetTrace == stdout)
54838909Sborman 		    fprintf(NetTrace, " IS\r\n");
54938909Sborman 		else
55038909Sborman 		    fprintf(NetTrace, " IS\n");
55138909Sborman 
55238909Sborman 		for (i = 2; i < length; i++) {
55338909Sborman 		    switch(pointer[i]) {
55438909Sborman 		    case DO:	cp = "DO"; goto common2;
55538909Sborman 		    case DONT:	cp = "DONT"; goto common2;
55638909Sborman 		    case WILL:	cp = "WILL"; goto common2;
55738909Sborman 		    case WONT:	cp = "WONT"; goto common2;
55838909Sborman 		    common2:
55938909Sborman 			i++;
56038909Sborman 			if (TELOPT_OK(pointer[i]))
56138909Sborman 			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
56238909Sborman 			else
56338909Sborman 			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
56438909Sborman 
56538909Sborman 			if (NetTrace == stdout)
56638909Sborman 			    fprintf(NetTrace, "\r\n");
56738909Sborman 			else
56838909Sborman 			    fprintf(NetTrace, "\n");
56938909Sborman 			break;
57038909Sborman 
57138909Sborman 		    case SB:
57238909Sborman 			fprintf(NetTrace, " SB ");
57338909Sborman 			i++;
57438909Sborman 			j = k = i;
57538909Sborman 			while (j < length) {
57638909Sborman 			    if (pointer[j] == SE) {
57738909Sborman 				if (j+1 == length)
57838909Sborman 				    break;
57938909Sborman 				if (pointer[j+1] == SE)
58038909Sborman 				    j++;
58138909Sborman 				else
58238909Sborman 				    break;
58338909Sborman 			    }
58438909Sborman 			    pointer[k++] = pointer[j++];
58538909Sborman 			}
58638909Sborman 			printsub(0, &pointer[i], k - i);
58738909Sborman 			if (i < length) {
58838909Sborman 			    fprintf(NetTrace, " SE");
58938909Sborman 			    i = j;
59038909Sborman 			} else
59138909Sborman 			    i = j - 1;
59238909Sborman 
59338909Sborman 			if (NetTrace == stdout)
59438909Sborman 			    fprintf(NetTrace, "\r\n");
59538909Sborman 			else
59638909Sborman 			    fprintf(NetTrace, "\n");
59738909Sborman 
59838909Sborman 			break;
59938909Sborman 
60038909Sborman 		    default:
60138909Sborman 			fprintf(NetTrace, " %d", pointer[i]);
60238909Sborman 			break;
60338909Sborman 		    }
60438909Sborman 		}
60538909Sborman 		break;
60638909Sborman 	    }
60738909Sborman 	    break;
60838909Sborman 	  }
60938909Sborman 
61032149Sminshall 	default:
61138690Sborman 	    fprintf(NetTrace, "Unknown option ");
61238690Sborman 	    for (i = 0; i < length; i++)
61338690Sborman 		fprintf(NetTrace, " %d", pointer[i]);
61438690Sborman 	    break;
61532149Sminshall 	}
61638909Sborman 	if (direction) {
61738909Sborman 	    if (NetTrace == stdout)
61838909Sborman 		fprintf(NetTrace, "\r\n");
61938909Sborman 	    else
62038909Sborman 		fprintf(NetTrace, "\n");
62138909Sborman 	}
62232149Sminshall     }
62332149Sminshall }
62436278Sminshall 
62536278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
62636278Sminshall  *			Note that we consider the buffer to run all the
62736278Sminshall  *			way to the kernel (thus the select).
62836278Sminshall  */
62936278Sminshall 
63036278Sminshall void
63136278Sminshall EmptyTerminal()
63236278Sminshall {
63336278Sminshall #if	defined(unix)
63436278Sminshall     fd_set	o;
63536278Sminshall 
63636278Sminshall     FD_ZERO(&o);
63736278Sminshall #endif	/* defined(unix) */
63836278Sminshall 
63936278Sminshall     if (TTYBYTES() == 0) {
64036278Sminshall #if	defined(unix)
64136278Sminshall 	FD_SET(tout, &o);
64236278Sminshall 	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
64336278Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
64436278Sminshall #endif	/* defined(unix) */
64536278Sminshall     } else {
64636278Sminshall 	while (TTYBYTES()) {
64736278Sminshall 	    ttyflush(0);
64836278Sminshall #if	defined(unix)
64936278Sminshall 	    FD_SET(tout, &o);
65036278Sminshall 	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
65136278Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
65236278Sminshall #endif	/* defined(unix) */
65336278Sminshall 	}
65436278Sminshall     }
65536278Sminshall }
65636278Sminshall 
65736278Sminshall void
65836278Sminshall SetForExit()
65936278Sminshall {
66038690Sborman     setconnmode(0);
66136278Sminshall #if	defined(TN3270)
66236278Sminshall     if (In3270) {
66336278Sminshall 	Finish3270();
66436278Sminshall     }
66536279Sminshall #else	/* defined(TN3270) */
66636279Sminshall     do {
66736279Sminshall 	telrcv();			/* Process any incoming data */
66836279Sminshall 	EmptyTerminal();
66936279Sminshall     } while (ring_full_count(&netiring));	/* While there is any */
67036278Sminshall #endif	/* defined(TN3270) */
67136278Sminshall     setcommandmode();
67236278Sminshall     fflush(stdout);
67336278Sminshall     fflush(stderr);
67436278Sminshall #if	defined(TN3270)
67536278Sminshall     if (In3270) {
67636278Sminshall 	StopScreen(1);
67736278Sminshall     }
67836278Sminshall #endif	/* defined(TN3270) */
67938690Sborman     setconnmode(0);
68036278Sminshall     EmptyTerminal();			/* Flush the path to the tty */
68136278Sminshall     setcommandmode();
68236278Sminshall }
68336278Sminshall 
68436278Sminshall void
68536278Sminshall Exit(returnCode)
68636278Sminshall int returnCode;
68736278Sminshall {
68836278Sminshall     SetForExit();
68936278Sminshall     exit(returnCode);
69036278Sminshall }
69136278Sminshall 
69236278Sminshall void
69336278Sminshall ExitString(string, returnCode)
69436278Sminshall char *string;
69536278Sminshall int returnCode;
69636278Sminshall {
69736278Sminshall     SetForExit();
69836278Sminshall     fwrite(string, 1, strlen(string), stderr);
69936278Sminshall     exit(returnCode);
70036278Sminshall }
701