xref: /csrg-svn/usr.bin/telnet/utilities.c (revision 39529)
133686Sbostic /*
233686Sbostic  * Copyright (c) 1988 Regents of the University of California.
333686Sbostic  * All rights reserved.
433686Sbostic  *
533686Sbostic  * Redistribution and use in source and binary forms are permitted
634898Sbostic  * provided that the above copyright notice and this paragraph are
734898Sbostic  * duplicated in all such forms and that any documentation,
834898Sbostic  * advertising materials, and other materials related to such
934898Sbostic  * distribution and use acknowledge that the software was developed
1034898Sbostic  * by the University of California, Berkeley.  The name of the
1134898Sbostic  * University may not be used to endorse or promote products derived
1234898Sbostic  * from this software without specific prior written permission.
1334898Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434898Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534898Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633686Sbostic  */
1733686Sbostic 
1833686Sbostic #ifndef lint
19*39529Sborman static char sccsid[] = "@(#)utilities.c	1.16 (Berkeley) 11/14/89";
2033686Sbostic #endif /* not lint */
2133686Sbostic 
2232149Sminshall #define	TELOPTS
2338690Sborman #define	TELCMDS
2432149Sminshall #include <arpa/telnet.h>
2532381Sminshall #include <sys/types.h>
2632149Sminshall 
2732149Sminshall #include <ctype.h>
2832149Sminshall 
2934305Sminshall #include "general.h"
3034305Sminshall 
3136280Sminshall #include "fdset.h"
3236280Sminshall 
3332381Sminshall #include "ring.h"
3432381Sminshall 
3536278Sminshall #include "defines.h"
3636278Sminshall 
3732149Sminshall #include "externs.h"
3832149Sminshall 
3932149Sminshall FILE	*NetTrace = 0;		/* Not in bss, since needs to stay */
4038690Sborman int	prettydump;
4132149Sminshall 
4232149Sminshall /*
4332149Sminshall  * upcase()
4432149Sminshall  *
4532149Sminshall  *	Upcase (in place) the argument.
4632149Sminshall  */
4732149Sminshall 
4832149Sminshall void
4932149Sminshall upcase(argument)
5032149Sminshall register char *argument;
5132149Sminshall {
5232149Sminshall     register int c;
5332149Sminshall 
5432149Sminshall     while ((c = *argument) != 0) {
5532149Sminshall 	if (islower(c)) {
5632149Sminshall 	    *argument = toupper(c);
5732149Sminshall 	}
5832149Sminshall 	argument++;
5932149Sminshall     }
6032149Sminshall }
6132149Sminshall 
6232149Sminshall /*
6332149Sminshall  * SetSockOpt()
6432149Sminshall  *
6532149Sminshall  * Compensate for differences in 4.2 and 4.3 systems.
6632149Sminshall  */
6732149Sminshall 
6832149Sminshall int
6932149Sminshall SetSockOpt(fd, level, option, yesno)
7032149Sminshall int
7132149Sminshall 	fd,
7232149Sminshall 	level,
7332149Sminshall 	option,
7432149Sminshall 	yesno;
7532149Sminshall {
7632149Sminshall #ifndef	NOT43
7732149Sminshall     return setsockopt(fd, level, option,
7832149Sminshall 				(char *)&yesno, sizeof yesno);
7932149Sminshall #else	/* NOT43 */
8032149Sminshall     if (yesno == 0) {		/* Can't do that in 4.2! */
8132149Sminshall 	fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
8232149Sminshall 				option);
8332149Sminshall 	return -1;
8432149Sminshall     }
8532149Sminshall     return setsockopt(fd, level, option, 0, 0);
8632149Sminshall #endif	/* NOT43 */
8732149Sminshall }
8832149Sminshall 
8932149Sminshall /*
9032149Sminshall  * The following are routines used to print out debugging information.
9132149Sminshall  */
9232149Sminshall 
93*39529Sborman unsigned char NetTraceFile[256] = "(standard output)";
9432149Sminshall 
9532149Sminshall void
9638690Sborman SetNetTrace(file)
9738690Sborman register char *file;
9838690Sborman {
9938690Sborman     if (NetTrace && NetTrace != stdout)
10038690Sborman 	fclose(NetTrace);
10138690Sborman     if (file  && (strcmp(file, "-") != 0)) {
10238690Sborman 	NetTrace = fopen(file, "w");
10338690Sborman 	if (NetTrace) {
10438690Sborman 	    strcpy(NetTraceFile, file);
10538690Sborman 	    return;
10638690Sborman 	}
10738690Sborman 	fprintf(stderr, "Cannot open %s.\n", file);
10838690Sborman     }
10938690Sborman     NetTrace = stdout;
11038690Sborman     strcpy(NetTraceFile, "(standard output)");
11138690Sborman }
11238690Sborman 
11338690Sborman void
11432149Sminshall Dump(direction, buffer, length)
11532149Sminshall char	direction;
11632149Sminshall char	*buffer;
11732149Sminshall int	length;
11832149Sminshall {
11932149Sminshall #   define BYTES_PER_LINE	32
12032149Sminshall #   define min(x,y)	((x<y)? x:y)
12132149Sminshall     char *pThis;
12232149Sminshall     int offset;
12338690Sborman     extern pettydump;
12432149Sminshall 
12532149Sminshall     offset = 0;
12632149Sminshall 
12732149Sminshall     while (length) {
12832149Sminshall 	/* print one line */
12932149Sminshall 	fprintf(NetTrace, "%c 0x%x\t", direction, offset);
13032149Sminshall 	pThis = buffer;
13138690Sborman 	if (prettydump) {
13238909Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE/2);
13338690Sborman 	    while (pThis < buffer) {
13438690Sborman 		fprintf(NetTrace, "%c%.2x",
13538690Sborman 		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
13638690Sborman 		    (*pThis)&0xff);
13738690Sborman 		pThis++;
13838690Sborman 	    }
13938909Sborman 	    length -= BYTES_PER_LINE/2;
14038909Sborman 	    offset += BYTES_PER_LINE/2;
14138690Sborman 	} else {
14238909Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE);
14338690Sborman 	    while (pThis < buffer) {
14438690Sborman 		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
14538690Sborman 		pThis++;
14638690Sborman 	    }
14738909Sborman 	    length -= BYTES_PER_LINE;
14838909Sborman 	    offset += BYTES_PER_LINE;
14932149Sminshall 	}
15037226Sminshall 	if (NetTrace == stdout) {
15138207Sminshall 	    fprintf(NetTrace, "\r\n");
15238207Sminshall 	} else {
15337226Sminshall 	    fprintf(NetTrace, "\n");
15437226Sminshall 	}
15532149Sminshall 	if (length < 0) {
15636693Sminshall 	    fflush(NetTrace);
15732149Sminshall 	    return;
15832149Sminshall 	}
15932149Sminshall 	/* find next unique line */
16032149Sminshall     }
16136693Sminshall     fflush(NetTrace);
16232149Sminshall }
16332149Sminshall 
16432149Sminshall 
16532149Sminshall void
16637226Sminshall printoption(direction, fmt, option)
16732149Sminshall 	char *direction, *fmt;
16837226Sminshall 	int option;
16932149Sminshall {
17032149Sminshall 	if (!showoptions)
17132149Sminshall 		return;
17237226Sminshall 	fprintf(NetTrace, "%s ", direction);
17338690Sborman 	if (TELOPT_OK(option))
17438690Sborman 		fprintf(NetTrace, "%s %s", fmt, TELOPT(option));
17538690Sborman 	else if (TELCMD_OK(option))
17638690Sborman 		fprintf(NetTrace, "%s %s", fmt, TELCMD(option));
17732149Sminshall 	else
17832149Sminshall 		fprintf(NetTrace, "%s %d", fmt, option);
17938690Sborman 	if (NetTrace == stdout)
18037226Sminshall 	    fprintf(NetTrace, "\r\n");
18138690Sborman 	else
18237226Sminshall 	    fprintf(NetTrace, "\n");
18337226Sminshall 	return;
18432149Sminshall }
18532149Sminshall 
18638690Sborman optionstatus()
18738690Sborman {
18838690Sborman     register int i;
18938690Sborman     extern char will_wont_resp[], do_dont_resp[];
19038690Sborman 
19138690Sborman     for (i = 0; i < 256; i++) {
19238690Sborman 	if (do_dont_resp[i]) {
19338690Sborman 	    if (TELOPT_OK(i))
19438690Sborman 		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
19538690Sborman 	    else if (TELCMD_OK(i))
19638690Sborman 		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
19738690Sborman 	    else
19838690Sborman 		printf("resp DO_DONT %d: %d\n", i,
19938690Sborman 				do_dont_resp[i]);
20038690Sborman 	    if (my_want_state_is_do(i)) {
20138690Sborman 		if (TELOPT_OK(i))
20238690Sborman 		    printf("want DO   %s\n", TELOPT(i));
20338690Sborman 		else if (TELCMD_OK(i))
20438690Sborman 		    printf("want DO   %s\n", TELCMD(i));
20538690Sborman 		else
20638690Sborman 		    printf("want DO   %d\n", i);
20738690Sborman 	    } else {
20838690Sborman 		if (TELOPT_OK(i))
20938690Sborman 		    printf("want DONT %s\n", TELOPT(i));
21038690Sborman 		else if (TELCMD_OK(i))
21138690Sborman 		    printf("want DONT %s\n", TELCMD(i));
21238690Sborman 		else
21338690Sborman 		    printf("want DONT %d\n", i);
21438690Sborman 	    }
21538690Sborman 	} else {
21638690Sborman 	    if (my_state_is_do(i)) {
21738690Sborman 		if (TELOPT_OK(i))
21838690Sborman 		    printf("     DO   %s\n", TELOPT(i));
21938690Sborman 		else if (TELCMD_OK(i))
22038690Sborman 		    printf("     DO   %s\n", TELCMD(i));
22138690Sborman 		else
22238690Sborman 		    printf("     DO   %d\n", i);
22338690Sborman 	    }
22438690Sborman 	}
22538690Sborman 	if (will_wont_resp[i]) {
22638690Sborman 	    if (TELOPT_OK(i))
22738690Sborman 		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
22838690Sborman 	    else if (TELCMD_OK(i))
22938690Sborman 		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
23038690Sborman 	    else
23138690Sborman 		printf("resp WILL_WONT %d: %d\n",
23238690Sborman 				i, will_wont_resp[i]);
23338690Sborman 	    if (my_want_state_is_will(i)) {
23438690Sborman 		if (TELOPT_OK(i))
23538690Sborman 		    printf("want WILL %s\n", TELOPT(i));
23638690Sborman 		else if (TELCMD_OK(i))
23738690Sborman 		    printf("want WILL %s\n", TELCMD(i));
23838690Sborman 		else
23938690Sborman 		    printf("want WILL %d\n", i);
24038690Sborman 	    } else {
24138690Sborman 		if (TELOPT_OK(i))
24238690Sborman 		    printf("want WONT %s\n", TELOPT(i));
24338690Sborman 		else if (TELCMD_OK(i))
24438690Sborman 		    printf("want WONT %s\n", TELCMD(i));
24538690Sborman 		else
24638690Sborman 		    printf("want WONT %d\n", i);
24738690Sborman 	    }
24838690Sborman 	} else {
24938690Sborman 	    if (my_state_is_will(i)) {
25038690Sborman 		if (TELOPT_OK(i))
25138690Sborman 		    printf("     WILL %s\n", TELOPT(i));
25238690Sborman 		else if (TELCMD_OK(i))
25338690Sborman 		    printf("     WILL %s\n", TELCMD(i));
25438690Sborman 		else
25538690Sborman 		    printf("     WILL %d\n", i);
25638690Sborman 	    }
25738690Sborman 	}
25838690Sborman     }
25938690Sborman 
26038690Sborman }
26138690Sborman 
26238690Sborman char *slcnames[] = { SLC_NAMES };
26338690Sborman 
26432149Sminshall void
26532149Sminshall printsub(direction, pointer, length)
26638690Sborman char	direction;		/* '<' or '>' */
26738690Sborman unsigned char	*pointer;	/* where suboption data sits */
26832149Sminshall int	length;			/* length of suboption data */
26932149Sminshall {
27038690Sborman     register int i;
27138690Sborman 
27232149Sminshall     if (showoptions) {
27338909Sborman 	if (direction) {
27438909Sborman 	    fprintf(NetTrace, "%s suboption ",
27538690Sborman 				(direction == '<')? "Received":"Sent");
27638909Sborman 	    if (length >= 3) {
27738909Sborman 		register int j;
27838690Sborman 
27938909Sborman 		i = pointer[length-2];
28038909Sborman 		j = pointer[length-1];
28138690Sborman 
28238909Sborman 		if (i != IAC || j != SE) {
28338909Sborman 		    fprintf(NetTrace, "(terminated by ");
28438909Sborman 		    if (TELOPT_OK(i))
28538909Sborman 			fprintf(NetTrace, "%s ", TELOPT(i));
28638909Sborman 		    else if (TELCMD_OK(i))
28738909Sborman 			fprintf(NetTrace, "%s ", TELCMD(i));
28838909Sborman 		    else
28938909Sborman 			fprintf(NetTrace, "%d ", i);
29038909Sborman 		    if (TELOPT_OK(j))
29138909Sborman 			fprintf(NetTrace, "%s", TELOPT(j));
29238909Sborman 		    else if (TELCMD_OK(j))
29338909Sborman 			fprintf(NetTrace, "%s", TELCMD(j));
29438909Sborman 		    else
29538909Sborman 			fprintf(NetTrace, "%d", j);
29638909Sborman 		    fprintf(NetTrace, ", not IAC SE!) ");
29738909Sborman 		}
29838690Sborman 	    }
29938909Sborman 	    length -= 2;
30038690Sborman 	}
30138690Sborman 	if (length < 1) {
30238690Sborman 	    fprintf(NetTrace, "(Empty suboption???)");
30338690Sborman 	    return;
30438690Sborman 	}
30532149Sminshall 	switch (pointer[0]) {
30632149Sminshall 	case TELOPT_TTYPE:
30738690Sborman 	    fprintf(NetTrace, "TERMINAL-TYPE ");
30832149Sminshall 	    switch (pointer[1]) {
30932149Sminshall 	    case TELQUAL_IS:
31038690Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, pointer+2);
31132149Sminshall 		break;
31232149Sminshall 	    case TELQUAL_SEND:
31338690Sborman 		fprintf(NetTrace, "SEND");
31432149Sminshall 		break;
31532149Sminshall 	    default:
31632149Sminshall 		fprintf(NetTrace,
31738690Sborman 				"- unknown qualifier %d (0x%x).",
31834849Sminshall 				pointer[1], pointer[1]);
31932149Sminshall 	    }
32032149Sminshall 	    break;
32138690Sborman 	case TELOPT_TSPEED:
32238690Sborman 	    fprintf(NetTrace, "TERMINAL-SPEED");
32338690Sborman 	    if (length < 2) {
32438690Sborman 		fprintf(NetTrace, " (empty suboption???)");
32538690Sborman 		break;
32638690Sborman 	    }
32738690Sborman 	    switch (pointer[1]) {
32838909Sborman 	    case TELQUAL_IS:
32938690Sborman 		fprintf(NetTrace, " IS ");
33038690Sborman 		fprintf(NetTrace, "%.*s", length-2, pointer+2);
33138690Sborman 		break;
33238690Sborman 	    default:
33338690Sborman 		if (pointer[1] == 1)
33438690Sborman 		    fprintf(NetTrace, " SEND");
33538690Sborman 		else
33638690Sborman 		    fprintf(NetTrace, " %d (unknown)");
33738690Sborman 		for (i = 2; i < length; i++)
33838690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
33938690Sborman 		break;
34038690Sborman 	    }
34138690Sborman 	    break;
34238690Sborman 
34338690Sborman 	case TELOPT_LFLOW:
34438690Sborman 	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
34538690Sborman 	    if (length < 2) {
34638690Sborman 		fprintf(NetTrace, " (empty suboption???)");
34738690Sborman 		break;
34838690Sborman 	    }
34938690Sborman 	    switch (pointer[1]) {
35038690Sborman 	    case 0:
35138690Sborman 		fprintf(NetTrace, " OFF"); break;
35238690Sborman 	    case 1:
35338690Sborman 		fprintf(NetTrace, " ON"); break;
35438690Sborman 	    default:
35538690Sborman 		fprintf(NetTrace, " %d (unknown)");
35638690Sborman 	    }
35738690Sborman 	    for (i = 2; i < length; i++)
35838690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
35938690Sborman 	    break;
36038690Sborman 
36138690Sborman 	case TELOPT_NAWS:
36238690Sborman 	    fprintf(NetTrace, "NAWS");
36338690Sborman 	    if (length < 2) {
36438690Sborman 		fprintf(NetTrace, " (empty suboption???)");
36538690Sborman 		break;
36638690Sborman 	    }
36738690Sborman 	    if (length == 2) {
36838690Sborman 		fprintf(NetTrace, " ?%d?", pointer[1]);
36938690Sborman 		break;
37038690Sborman 	    }
37138690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
37238690Sborman 		pointer[1], pointer[2],
37338690Sborman 		(((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]));
37438690Sborman 	    if (length == 4) {
37538690Sborman 		fprintf(NetTrace, " ?%d?", pointer[3]);
37638690Sborman 		break;
37738690Sborman 	    }
37838690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
37938690Sborman 		pointer[3], pointer[4],
38038690Sborman 		(((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]));
38138690Sborman 	    for (i = 5; i < length; i++)
38238690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
38338690Sborman 	    break;
38438690Sborman 
38538690Sborman 	case TELOPT_LINEMODE:
38638690Sborman 	    fprintf(NetTrace, "LINEMODE ");
38738690Sborman 	    if (length < 2) {
38838690Sborman 		fprintf(NetTrace, " (empty suboption???)");
38938690Sborman 		break;
39038690Sborman 	    }
39138690Sborman 	    switch (pointer[1]) {
39238690Sborman 	    case WILL:
39338690Sborman 		fprintf(NetTrace, "WILL ");
39438690Sborman 		goto common;
39538690Sborman 	    case WONT:
39638690Sborman 		fprintf(NetTrace, "WONT ");
39738690Sborman 		goto common;
39838690Sborman 	    case DO:
39938690Sborman 		fprintf(NetTrace, "DO ");
40038690Sborman 		goto common;
40138690Sborman 	    case DONT:
40238690Sborman 		fprintf(NetTrace, "DONT ");
40338690Sborman 	    common:
40438690Sborman 		if (length < 3) {
40538690Sborman 		    fprintf(NetTrace, "(no option???)");
40638690Sborman 		    break;
40738690Sborman 		}
40838690Sborman 		switch (pointer[2]) {
40938690Sborman 		case LM_FORWARDMASK:
41038690Sborman 		    fprintf(NetTrace, "Forward Mask");
41138690Sborman 		    for (i = 3; i < length; i++)
41238690Sborman 			fprintf(NetTrace, " %x", pointer[i]);
41338690Sborman 		    break;
41438690Sborman 		default:
41538690Sborman 		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
41638690Sborman 		    for (i = 3; i < length; i++)
41738690Sborman 			fprintf(NetTrace, " %d", pointer[i]);
41838690Sborman 		    break;
41938690Sborman 		}
42038690Sborman 		break;
42138690Sborman 
42238690Sborman 	    case LM_SLC:
42338690Sborman 		fprintf(NetTrace, "SLC");
42438690Sborman 		for (i = 2; i < length - 2; i += 3) {
42538690Sborman 		    if (pointer[i+SLC_FUNC] <= NSLC)
42638690Sborman 			fprintf(NetTrace, " %s", slcnames[pointer[i+SLC_FUNC]]);
42738690Sborman 		    else
42838690Sborman 			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
42938690Sborman 		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
43038690Sborman 		    case SLC_NOSUPPORT:
43138690Sborman 			fprintf(NetTrace, " NOSUPPORT"); break;
43238690Sborman 		    case SLC_CANTCHANGE:
43338690Sborman 			fprintf(NetTrace, " CANTCHANGE"); break;
43438690Sborman 		    case SLC_VARIABLE:
43538690Sborman 			fprintf(NetTrace, " VARIABLE"); break;
43638690Sborman 		    case SLC_DEFAULT:
43738690Sborman 			fprintf(NetTrace, " DEFAULT"); break;
43838690Sborman 		    }
43938690Sborman 		    fprintf(NetTrace, "%s%s%s",
44038690Sborman 			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
44138690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
44238690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
44338690Sborman 		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
44438690Sborman 						SLC_FLUSHOUT| SLC_LEVELBITS))
44538690Sborman 			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
44638690Sborman 		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
44738690Sborman 		}
44838690Sborman 		for (; i < length; i++)
44938690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
45038690Sborman 		break;
45138690Sborman 
45238690Sborman 	    case LM_MODE:
45338690Sborman 		fprintf(NetTrace, "MODE ");
45438690Sborman 		if (length < 3) {
45538690Sborman 		    fprintf(NetTrace, "(no mode???)");
45638690Sborman 		    break;
45738690Sborman 		}
45838690Sborman 		{
45938690Sborman 		    char tbuf[32];
46038690Sborman 		    sprintf(tbuf, "%s%s%s",
46138690Sborman 			pointer[2]&MODE_EDIT ? "|EDIT" : "",
46238690Sborman 			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
46338690Sborman 			pointer[2]&MODE_ACK ? "|ACK" : "");
46438690Sborman 		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
46538690Sborman 		}
46638690Sborman 		if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
46738690Sborman 		    fprintf(NetTrace, " (0x%x)", pointer[2]);
46838690Sborman 		for (i = 3; i < length; i++)
46938690Sborman 		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
47038690Sborman 		break;
47138690Sborman 	    default:
47238690Sborman 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
47338690Sborman 		for (i = 2; i < length; i++)
47438690Sborman 		    fprintf(NetTrace, " %d", pointer[i]);
47538690Sborman 	    }
47638690Sborman 	    break;
47738690Sborman 
47838909Sborman 	case TELOPT_STATUS: {
47938909Sborman 	    register char *cp;
48038909Sborman 	    register int j, k;
48138909Sborman 
48238909Sborman 	    fprintf(NetTrace, "STATUS");
48338909Sborman 
48438909Sborman 	    switch (pointer[1]) {
48538909Sborman 	    default:
48638909Sborman 		if (pointer[1] == TELQUAL_SEND)
48738909Sborman 		    fprintf(NetTrace, " SEND");
48838909Sborman 		else
48938909Sborman 		    fprintf(NetTrace, " %d (unknown)");
49038909Sborman 		for (i = 2; i < length; i++)
49138909Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
49238909Sborman 		break;
49338909Sborman 	    case TELQUAL_IS:
49438909Sborman 		if (NetTrace == stdout)
49538909Sborman 		    fprintf(NetTrace, " IS\r\n");
49638909Sborman 		else
49738909Sborman 		    fprintf(NetTrace, " IS\n");
49838909Sborman 
49938909Sborman 		for (i = 2; i < length; i++) {
50038909Sborman 		    switch(pointer[i]) {
50138909Sborman 		    case DO:	cp = "DO"; goto common2;
50238909Sborman 		    case DONT:	cp = "DONT"; goto common2;
50338909Sborman 		    case WILL:	cp = "WILL"; goto common2;
50438909Sborman 		    case WONT:	cp = "WONT"; goto common2;
50538909Sborman 		    common2:
50638909Sborman 			i++;
50738909Sborman 			if (TELOPT_OK(pointer[i]))
50838909Sborman 			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
50938909Sborman 			else
51038909Sborman 			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
51138909Sborman 
51238909Sborman 			if (NetTrace == stdout)
51338909Sborman 			    fprintf(NetTrace, "\r\n");
51438909Sborman 			else
51538909Sborman 			    fprintf(NetTrace, "\n");
51638909Sborman 			break;
51738909Sborman 
51838909Sborman 		    case SB:
51938909Sborman 			fprintf(NetTrace, " SB ");
52038909Sborman 			i++;
52138909Sborman 			j = k = i;
52238909Sborman 			while (j < length) {
52338909Sborman 			    if (pointer[j] == SE) {
52438909Sborman 				if (j+1 == length)
52538909Sborman 				    break;
52638909Sborman 				if (pointer[j+1] == SE)
52738909Sborman 				    j++;
52838909Sborman 				else
52938909Sborman 				    break;
53038909Sborman 			    }
53138909Sborman 			    pointer[k++] = pointer[j++];
53238909Sborman 			}
53338909Sborman 			printsub(0, &pointer[i], k - i);
53438909Sborman 			if (i < length) {
53538909Sborman 			    fprintf(NetTrace, " SE");
53638909Sborman 			    i = j;
53738909Sborman 			} else
53838909Sborman 			    i = j - 1;
53938909Sborman 
54038909Sborman 			if (NetTrace == stdout)
54138909Sborman 			    fprintf(NetTrace, "\r\n");
54238909Sborman 			else
54338909Sborman 			    fprintf(NetTrace, "\n");
54438909Sborman 
54538909Sborman 			break;
54638909Sborman 
54738909Sborman 		    default:
54838909Sborman 			fprintf(NetTrace, " %d", pointer[i]);
54938909Sborman 			break;
55038909Sborman 		    }
55138909Sborman 		}
55238909Sborman 		break;
55338909Sborman 	    }
55438909Sborman 	    break;
55538909Sborman 	  }
55638909Sborman 
55732149Sminshall 	default:
55838690Sborman 	    fprintf(NetTrace, "Unknown option ");
55938690Sborman 	    for (i = 0; i < length; i++)
56038690Sborman 		fprintf(NetTrace, " %d", pointer[i]);
56138690Sborman 	    break;
56232149Sminshall 	}
56338909Sborman 	if (direction) {
56438909Sborman 	    if (NetTrace == stdout)
56538909Sborman 		fprintf(NetTrace, "\r\n");
56638909Sborman 	    else
56738909Sborman 		fprintf(NetTrace, "\n");
56838909Sborman 	}
56932149Sminshall     }
57032149Sminshall }
57136278Sminshall 
57236278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
57336278Sminshall  *			Note that we consider the buffer to run all the
57436278Sminshall  *			way to the kernel (thus the select).
57536278Sminshall  */
57636278Sminshall 
57736278Sminshall void
57836278Sminshall EmptyTerminal()
57936278Sminshall {
58036278Sminshall #if	defined(unix)
58136278Sminshall     fd_set	o;
58236278Sminshall 
58336278Sminshall     FD_ZERO(&o);
58436278Sminshall #endif	/* defined(unix) */
58536278Sminshall 
58636278Sminshall     if (TTYBYTES() == 0) {
58736278Sminshall #if	defined(unix)
58836278Sminshall 	FD_SET(tout, &o);
58936278Sminshall 	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
59036278Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
59136278Sminshall #endif	/* defined(unix) */
59236278Sminshall     } else {
59336278Sminshall 	while (TTYBYTES()) {
59436278Sminshall 	    ttyflush(0);
59536278Sminshall #if	defined(unix)
59636278Sminshall 	    FD_SET(tout, &o);
59736278Sminshall 	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
59836278Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
59936278Sminshall #endif	/* defined(unix) */
60036278Sminshall 	}
60136278Sminshall     }
60236278Sminshall }
60336278Sminshall 
60436278Sminshall void
60536278Sminshall SetForExit()
60636278Sminshall {
60738690Sborman     setconnmode(0);
60836278Sminshall #if	defined(TN3270)
60936278Sminshall     if (In3270) {
61036278Sminshall 	Finish3270();
61136278Sminshall     }
61236279Sminshall #else	/* defined(TN3270) */
61336279Sminshall     do {
61436279Sminshall 	telrcv();			/* Process any incoming data */
61536279Sminshall 	EmptyTerminal();
61636279Sminshall     } while (ring_full_count(&netiring));	/* While there is any */
61736278Sminshall #endif	/* defined(TN3270) */
61836278Sminshall     setcommandmode();
61936278Sminshall     fflush(stdout);
62036278Sminshall     fflush(stderr);
62136278Sminshall #if	defined(TN3270)
62236278Sminshall     if (In3270) {
62336278Sminshall 	StopScreen(1);
62436278Sminshall     }
62536278Sminshall #endif	/* defined(TN3270) */
62638690Sborman     setconnmode(0);
62736278Sminshall     EmptyTerminal();			/* Flush the path to the tty */
62836278Sminshall     setcommandmode();
62936278Sminshall }
63036278Sminshall 
63136278Sminshall void
63236278Sminshall Exit(returnCode)
63336278Sminshall int returnCode;
63436278Sminshall {
63536278Sminshall     SetForExit();
63636278Sminshall     exit(returnCode);
63736278Sminshall }
63836278Sminshall 
63936278Sminshall void
64036278Sminshall ExitString(string, returnCode)
64136278Sminshall char *string;
64236278Sminshall int returnCode;
64336278Sminshall {
64436278Sminshall     SetForExit();
64536278Sminshall     fwrite(string, 1, strlen(string), stderr);
64636278Sminshall     exit(returnCode);
64736278Sminshall }
648