utilities.c revision 272461
11592Srgrimes/*
21592Srgrimes * Copyright (c) 1988, 1993
31592Srgrimes *	The Regents of the University of California.  All rights reserved.
41592Srgrimes *
51592Srgrimes * Redistribution and use in source and binary forms, with or without
61592Srgrimes * modification, are permitted provided that the following conditions
71592Srgrimes * are met:
81592Srgrimes * 1. Redistributions of source code must retain the above copyright
91592Srgrimes *    notice, this list of conditions and the following disclaimer.
101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111592Srgrimes *    notice, this list of conditions and the following disclaimer in the
121592Srgrimes *    documentation and/or other materials provided with the distribution.
131592Srgrimes * 3. All advertising materials mentioning features or use of this software
141592Srgrimes *    must display the following acknowledgement:
151592Srgrimes *	This product includes software developed by the University of
161592Srgrimes *	California, Berkeley and its contributors.
171592Srgrimes * 4. Neither the name of the University nor the names of its contributors
181592Srgrimes *    may be used to endorse or promote products derived from this software
191592Srgrimes *    without specific prior written permission.
201592Srgrimes *
211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241592Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311592Srgrimes * SUCH DAMAGE.
321592Srgrimes */
331592Srgrimes
341592Srgrimes#if 0
351592Srgrimes#ifndef lint
361592Srgrimesstatic const char sccsid[] = "@(#)utilities.c	8.3 (Berkeley) 5/30/95";
371592Srgrimes#endif
381592Srgrimes#endif
391592Srgrimes#include <sys/cdefs.h>
401592Srgrimes__FBSDID("$FreeBSD: releng/10.1/contrib/telnet/telnet/utilities.c 228651 2011-12-17 18:18:36Z dim $");
411592Srgrimes
421592Srgrimes#define	TELOPTS
431592Srgrimes#define	TELCMDS
441592Srgrimes#define	SLC_NAMES
451592Srgrimes#include <arpa/telnet.h>
461592Srgrimes#include <sys/types.h>
471592Srgrimes#include <sys/socket.h>
481592Srgrimes#include <sys/time.h>
491592Srgrimes#include <ctype.h>
501592Srgrimes#include <stdlib.h>
511592Srgrimes#include <unistd.h>
521592Srgrimes
531592Srgrimes#include "general.h"
541592Srgrimes
551592Srgrimes#include "fdset.h"
561592Srgrimes
571592Srgrimes#include "ring.h"
581592Srgrimes
591592Srgrimes#include "defines.h"
601592Srgrimes
611592Srgrimes#include "externs.h"
621592Srgrimes
631592Srgrimes#ifdef	AUTHENTICATION
641592Srgrimes#include <libtelnet/auth.h>
651592Srgrimes#endif
661592Srgrimes#ifdef	ENCRYPTION
671592Srgrimes#include <libtelnet/encrypt.h>
681592Srgrimes#endif
691592Srgrimes
701592SrgrimesFILE	*NetTrace = 0;		/* Not in bss, since needs to stay */
711592Srgrimesint	prettydump;
721592Srgrimes
731592Srgrimes/*
741592Srgrimes * upcase()
751592Srgrimes *
761592Srgrimes *	Upcase (in place) the argument.
771592Srgrimes */
781592Srgrimes
791592Srgrimesvoid
801592Srgrimesupcase(char *argument)
811592Srgrimes{
821592Srgrimes    int c;
831592Srgrimes
841592Srgrimes    while ((c = *argument) != 0) {
851592Srgrimes	if (islower(c)) {
861592Srgrimes	    *argument = toupper(c);
871592Srgrimes	}
881592Srgrimes	argument++;
891592Srgrimes    }
901592Srgrimes}
911592Srgrimes
921592Srgrimes/*
931592Srgrimes * SetSockOpt()
941592Srgrimes *
951592Srgrimes * Compensate for differences in 4.2 and 4.3 systems.
961592Srgrimes */
971592Srgrimes
981592Srgrimesint
991592SrgrimesSetSockOpt(int fd, int level, int option, int yesno)
1001592Srgrimes{
1011592Srgrimes    return setsockopt(fd, level, option,
1021592Srgrimes				(char *)&yesno, sizeof yesno);
1031592Srgrimes}
1041592Srgrimes
1051592Srgrimes/*
1061592Srgrimes * The following are routines used to print out debugging information.
1071592Srgrimes */
1081592Srgrimes
1091592Srgrimesunsigned char NetTraceFile[256] = "(standard output)";
1101592Srgrimes
1111592Srgrimesvoid
1121592SrgrimesSetNetTrace(char *file)
1131592Srgrimes{
1141592Srgrimes    if (NetTrace && NetTrace != stdout)
1151592Srgrimes	fclose(NetTrace);
1161592Srgrimes    if (file  && (strcmp(file, "-") != 0)) {
1171592Srgrimes	NetTrace = fopen(file, "w");
1181592Srgrimes	if (NetTrace) {
1191592Srgrimes	    strcpy((char *)NetTraceFile, file);
1201592Srgrimes	    return;
1211592Srgrimes	}
1221592Srgrimes	fprintf(stderr, "Cannot open %s.\n", file);
1231592Srgrimes    }
1241592Srgrimes    NetTrace = stdout;
1251592Srgrimes    strcpy((char *)NetTraceFile, "(standard output)");
1261592Srgrimes}
1271592Srgrimes
1281592Srgrimesvoid
1291592SrgrimesDump(char direction, unsigned char *buffer, int length)
1301592Srgrimes{
1311592Srgrimes#   define BYTES_PER_LINE	32
1321592Srgrimes#   define min(x,y)	((x<y)? x:y)
1331592Srgrimes    unsigned char *pThis;
1341592Srgrimes    int offset;
1351592Srgrimes
1361592Srgrimes    offset = 0;
1371592Srgrimes
1381592Srgrimes    while (length) {
1391592Srgrimes	/* print one line */
1401592Srgrimes	fprintf(NetTrace, "%c 0x%x\t", direction, offset);
1411592Srgrimes	pThis = buffer;
1421592Srgrimes	if (prettydump) {
1431592Srgrimes	    buffer = buffer + min(length, BYTES_PER_LINE/2);
1441592Srgrimes	    while (pThis < buffer) {
1451592Srgrimes		fprintf(NetTrace, "%c%.2x",
1461592Srgrimes		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
1471592Srgrimes		    (*pThis)&0xff);
1481592Srgrimes		pThis++;
1491592Srgrimes	    }
1501592Srgrimes	    length -= BYTES_PER_LINE/2;
1511592Srgrimes	    offset += BYTES_PER_LINE/2;
1521592Srgrimes	} else {
1531592Srgrimes	    buffer = buffer + min(length, BYTES_PER_LINE);
1541592Srgrimes	    while (pThis < buffer) {
1551592Srgrimes		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
1561592Srgrimes		pThis++;
1571592Srgrimes	    }
1581592Srgrimes	    length -= BYTES_PER_LINE;
1591592Srgrimes	    offset += BYTES_PER_LINE;
1601592Srgrimes	}
1611592Srgrimes	if (NetTrace == stdout) {
1621592Srgrimes	    fprintf(NetTrace, "\r\n");
1631592Srgrimes	} else {
1641592Srgrimes	    fprintf(NetTrace, "\n");
1651592Srgrimes	}
1661592Srgrimes	if (length < 0) {
1671592Srgrimes	    fflush(NetTrace);
1681592Srgrimes	    return;
1691592Srgrimes	}
1701592Srgrimes	/* find next unique line */
1711592Srgrimes    }
1721592Srgrimes    fflush(NetTrace);
1731592Srgrimes}
1741592Srgrimes
1751592Srgrimes
1761592Srgrimesvoid
1771592Srgrimesprintoption(const char *direction, int cmd, int option)
1781592Srgrimes{
1791592Srgrimes	if (!showoptions)
1801592Srgrimes		return;
1811592Srgrimes	if (cmd == IAC) {
1821592Srgrimes		if (TELCMD_OK(option))
1831592Srgrimes		    fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
1841592Srgrimes		else
1851592Srgrimes		    fprintf(NetTrace, "%s IAC %d", direction, option);
1861592Srgrimes	} else {
1871592Srgrimes		const char *fmt;
1881592Srgrimes		fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
1891592Srgrimes			(cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
1901592Srgrimes		if (fmt) {
1911592Srgrimes		    fprintf(NetTrace, "%s %s ", direction, fmt);
1921592Srgrimes		    if (TELOPT_OK(option))
1931592Srgrimes			fprintf(NetTrace, "%s", TELOPT(option));
1941592Srgrimes		    else if (option == TELOPT_EXOPL)
1951592Srgrimes			fprintf(NetTrace, "EXOPL");
1961592Srgrimes		    else
1971592Srgrimes			fprintf(NetTrace, "%d", option);
1981592Srgrimes		} else
1991592Srgrimes		    fprintf(NetTrace, "%s %d %d", direction, cmd, option);
2001592Srgrimes	}
2011592Srgrimes	if (NetTrace == stdout) {
2021592Srgrimes	    fprintf(NetTrace, "\r\n");
2031592Srgrimes	    fflush(NetTrace);
2041592Srgrimes	} else {
2051592Srgrimes	    fprintf(NetTrace, "\n");
2061592Srgrimes	}
2071592Srgrimes	return;
2081592Srgrimes}
2091592Srgrimes
2101592Srgrimesvoid
2111592Srgrimesoptionstatus(void)
2121592Srgrimes{
2131592Srgrimes    int i;
2141592Srgrimes    extern char will_wont_resp[], do_dont_resp[];
2151592Srgrimes
2161592Srgrimes    for (i = 0; i < 256; i++) {
2171592Srgrimes	if (do_dont_resp[i]) {
2181592Srgrimes	    if (TELOPT_OK(i))
2191592Srgrimes		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
2201592Srgrimes	    else if (TELCMD_OK(i))
2211592Srgrimes		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
2221592Srgrimes	    else
2231592Srgrimes		printf("resp DO_DONT %d: %d\n", i,
2241592Srgrimes				do_dont_resp[i]);
2251592Srgrimes	    if (my_want_state_is_do(i)) {
2261592Srgrimes		if (TELOPT_OK(i))
2271592Srgrimes		    printf("want DO   %s\n", TELOPT(i));
2281592Srgrimes		else if (TELCMD_OK(i))
2291592Srgrimes		    printf("want DO   %s\n", TELCMD(i));
2301592Srgrimes		else
2311592Srgrimes		    printf("want DO   %d\n", i);
2321592Srgrimes	    } else {
2331592Srgrimes		if (TELOPT_OK(i))
2341592Srgrimes		    printf("want DONT %s\n", TELOPT(i));
2351592Srgrimes		else if (TELCMD_OK(i))
2361592Srgrimes		    printf("want DONT %s\n", TELCMD(i));
2371592Srgrimes		else
2381592Srgrimes		    printf("want DONT %d\n", i);
2391592Srgrimes	    }
2401592Srgrimes	} else {
2411592Srgrimes	    if (my_state_is_do(i)) {
2421592Srgrimes		if (TELOPT_OK(i))
2431592Srgrimes		    printf("     DO   %s\n", TELOPT(i));
2441592Srgrimes		else if (TELCMD_OK(i))
2451592Srgrimes		    printf("     DO   %s\n", TELCMD(i));
2461592Srgrimes		else
2471592Srgrimes		    printf("     DO   %d\n", i);
2481592Srgrimes	    }
2491592Srgrimes	}
2501592Srgrimes	if (will_wont_resp[i]) {
2511592Srgrimes	    if (TELOPT_OK(i))
2521592Srgrimes		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
2531592Srgrimes	    else if (TELCMD_OK(i))
2541592Srgrimes		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
2551592Srgrimes	    else
2561592Srgrimes		printf("resp WILL_WONT %d: %d\n",
2571592Srgrimes				i, will_wont_resp[i]);
2581592Srgrimes	    if (my_want_state_is_will(i)) {
2591592Srgrimes		if (TELOPT_OK(i))
2601592Srgrimes		    printf("want WILL %s\n", TELOPT(i));
2611592Srgrimes		else if (TELCMD_OK(i))
2621592Srgrimes		    printf("want WILL %s\n", TELCMD(i));
2631592Srgrimes		else
2641592Srgrimes		    printf("want WILL %d\n", i);
2651592Srgrimes	    } else {
2661592Srgrimes		if (TELOPT_OK(i))
2671592Srgrimes		    printf("want WONT %s\n", TELOPT(i));
2681592Srgrimes		else if (TELCMD_OK(i))
2691592Srgrimes		    printf("want WONT %s\n", TELCMD(i));
2701592Srgrimes		else
2711592Srgrimes		    printf("want WONT %d\n", i);
2721592Srgrimes	    }
2731592Srgrimes	} else {
2741592Srgrimes	    if (my_state_is_will(i)) {
2751592Srgrimes		if (TELOPT_OK(i))
2761592Srgrimes		    printf("     WILL %s\n", TELOPT(i));
2771592Srgrimes		else if (TELCMD_OK(i))
2781592Srgrimes		    printf("     WILL %s\n", TELCMD(i));
2791592Srgrimes		else
2801592Srgrimes		    printf("     WILL %d\n", i);
2811592Srgrimes	    }
2821592Srgrimes	}
2831592Srgrimes    }
2841592Srgrimes
2851592Srgrimes}
2861592Srgrimes
2871592Srgrimesvoid
2881592Srgrimesprintsub(char direction, unsigned char *pointer, int length)
2891592Srgrimes{
2901592Srgrimes    int i;
2911592Srgrimes#ifdef	AUTHENTICATION
2921592Srgrimes    char buf[512];
2931592Srgrimes#endif
2941592Srgrimes    extern int want_status_response;
2951592Srgrimes
2961592Srgrimes    if (showoptions || direction == 0 ||
2971592Srgrimes	(want_status_response && (pointer[0] == TELOPT_STATUS))) {
2981592Srgrimes	if (direction) {
2991592Srgrimes	    fprintf(NetTrace, "%s IAC SB ",
3001592Srgrimes				(direction == '<')? "RCVD":"SENT");
3011592Srgrimes	    if (length >= 3) {
3021592Srgrimes		int j;
3031592Srgrimes
3041592Srgrimes		i = pointer[length-2];
3051592Srgrimes		j = pointer[length-1];
3061592Srgrimes
3071592Srgrimes		if (i != IAC || j != SE) {
3081592Srgrimes		    fprintf(NetTrace, "(terminated by ");
3091592Srgrimes		    if (TELOPT_OK(i))
3101592Srgrimes			fprintf(NetTrace, "%s ", TELOPT(i));
3111592Srgrimes		    else if (TELCMD_OK(i))
3121592Srgrimes			fprintf(NetTrace, "%s ", TELCMD(i));
3131592Srgrimes		    else
3141592Srgrimes			fprintf(NetTrace, "%d ", i);
3151592Srgrimes		    if (TELOPT_OK(j))
3161592Srgrimes			fprintf(NetTrace, "%s", TELOPT(j));
3171592Srgrimes		    else if (TELCMD_OK(j))
3181592Srgrimes			fprintf(NetTrace, "%s", TELCMD(j));
3191592Srgrimes		    else
3201592Srgrimes			fprintf(NetTrace, "%d", j);
3211592Srgrimes		    fprintf(NetTrace, ", not IAC SE!) ");
3221592Srgrimes		}
3231592Srgrimes	    }
3241592Srgrimes	    length -= 2;
3251592Srgrimes	}
3261592Srgrimes	if (length < 1) {
3271592Srgrimes	    fprintf(NetTrace, "(Empty suboption??\?)");
3281592Srgrimes	    if (NetTrace == stdout)
3291592Srgrimes		fflush(NetTrace);
3301592Srgrimes	    return;
3311592Srgrimes	}
3321592Srgrimes	switch (pointer[0]) {
3331592Srgrimes	case TELOPT_TTYPE:
3341592Srgrimes	    fprintf(NetTrace, "TERMINAL-TYPE ");
3351592Srgrimes	    switch (pointer[1]) {
3361592Srgrimes	    case TELQUAL_IS:
3371592Srgrimes		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
3381592Srgrimes		break;
3391592Srgrimes	    case TELQUAL_SEND:
3401592Srgrimes		fprintf(NetTrace, "SEND");
3411592Srgrimes		break;
3421592Srgrimes	    default:
3431592Srgrimes		fprintf(NetTrace,
3441592Srgrimes				"- unknown qualifier %d (0x%x).",
3451592Srgrimes				pointer[1], pointer[1]);
3461592Srgrimes	    }
3471592Srgrimes	    break;
3481592Srgrimes	case TELOPT_TSPEED:
3491592Srgrimes	    fprintf(NetTrace, "TERMINAL-SPEED");
3501592Srgrimes	    if (length < 2) {
3511592Srgrimes		fprintf(NetTrace, " (empty suboption??\?)");
3521592Srgrimes		break;
3531592Srgrimes	    }
3541592Srgrimes	    switch (pointer[1]) {
3551592Srgrimes	    case TELQUAL_IS:
3561592Srgrimes		fprintf(NetTrace, " IS ");
3571592Srgrimes		fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
3581592Srgrimes		break;
3591592Srgrimes	    default:
3601592Srgrimes		if (pointer[1] == 1)
3611592Srgrimes		    fprintf(NetTrace, " SEND");
3621592Srgrimes		else
3631592Srgrimes		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
3641592Srgrimes		for (i = 2; i < length; i++)
3651592Srgrimes		    fprintf(NetTrace, " ?%d?", pointer[i]);
3661592Srgrimes		break;
3671592Srgrimes	    }
3681592Srgrimes	    break;
3691592Srgrimes
3701592Srgrimes	case TELOPT_LFLOW:
3711592Srgrimes	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
3721592Srgrimes	    if (length < 2) {
3731592Srgrimes		fprintf(NetTrace, " (empty suboption??\?)");
3741592Srgrimes		break;
3751592Srgrimes	    }
3761592Srgrimes	    switch (pointer[1]) {
3771592Srgrimes	    case LFLOW_OFF:
3781592Srgrimes		fprintf(NetTrace, " OFF"); break;
3791592Srgrimes	    case LFLOW_ON:
3801592Srgrimes		fprintf(NetTrace, " ON"); break;
3811592Srgrimes	    case LFLOW_RESTART_ANY:
3821592Srgrimes		fprintf(NetTrace, " RESTART-ANY"); break;
3831592Srgrimes	    case LFLOW_RESTART_XON:
3841592Srgrimes		fprintf(NetTrace, " RESTART-XON"); break;
3851592Srgrimes	    default:
3861592Srgrimes		fprintf(NetTrace, " %d (unknown)", pointer[1]);
3871592Srgrimes	    }
3881592Srgrimes	    for (i = 2; i < length; i++)
3891592Srgrimes		fprintf(NetTrace, " ?%d?", pointer[i]);
3901592Srgrimes	    break;
3911592Srgrimes
3921592Srgrimes	case TELOPT_NAWS:
3931592Srgrimes	    fprintf(NetTrace, "NAWS");
3941592Srgrimes	    if (length < 2) {
3951592Srgrimes		fprintf(NetTrace, " (empty suboption??\?)");
3961592Srgrimes		break;
3971592Srgrimes	    }
3981592Srgrimes	    if (length == 2) {
3991592Srgrimes		fprintf(NetTrace, " ?%d?", pointer[1]);
4001592Srgrimes		break;
4011592Srgrimes	    }
4021592Srgrimes	    fprintf(NetTrace, " %d %d (%d)",
4031592Srgrimes		pointer[1], pointer[2],
4041592Srgrimes		(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
4051592Srgrimes	    if (length == 4) {
4061592Srgrimes		fprintf(NetTrace, " ?%d?", pointer[3]);
4071592Srgrimes		break;
4081592Srgrimes	    }
4091592Srgrimes	    fprintf(NetTrace, " %d %d (%d)",
4101592Srgrimes		pointer[3], pointer[4],
4111592Srgrimes		(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
4121592Srgrimes	    for (i = 5; i < length; i++)
4131592Srgrimes		fprintf(NetTrace, " ?%d?", pointer[i]);
4141592Srgrimes	    break;
4151592Srgrimes
4161592Srgrimes#ifdef	AUTHENTICATION
4171592Srgrimes	case TELOPT_AUTHENTICATION:
4181592Srgrimes	    fprintf(NetTrace, "AUTHENTICATION");
4191592Srgrimes	    if (length < 2) {
4201592Srgrimes		fprintf(NetTrace, " (empty suboption??\?)");
4211592Srgrimes		break;
4221592Srgrimes	    }
4231592Srgrimes	    switch (pointer[1]) {
4241592Srgrimes	    case TELQUAL_REPLY:
4251592Srgrimes	    case TELQUAL_IS:
4261592Srgrimes		fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
4271592Srgrimes							"IS" : "REPLY");
4281592Srgrimes		if (AUTHTYPE_NAME_OK(pointer[2]))
4291592Srgrimes		    fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
4301592Srgrimes		else
4311592Srgrimes		    fprintf(NetTrace, "%d ", pointer[2]);
4321592Srgrimes		if (length < 3) {
4331592Srgrimes		    fprintf(NetTrace, "(partial suboption??\?)");
4341592Srgrimes		    break;
4351592Srgrimes		}
4361592Srgrimes		fprintf(NetTrace, "%s|%s",
4371592Srgrimes			((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
4381592Srgrimes			"CLIENT" : "SERVER",
4391592Srgrimes			((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
4401592Srgrimes			"MUTUAL" : "ONE-WAY");
4411592Srgrimes
4421592Srgrimes		auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
4431592Srgrimes		fprintf(NetTrace, "%s", buf);
4441592Srgrimes		break;
4451592Srgrimes
4461592Srgrimes	    case TELQUAL_SEND:
4471592Srgrimes		i = 2;
4481592Srgrimes		fprintf(NetTrace, " SEND ");
4491592Srgrimes		while (i < length) {
4501592Srgrimes		    if (AUTHTYPE_NAME_OK(pointer[i]))
4511592Srgrimes			fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
4521592Srgrimes		    else
4531592Srgrimes			fprintf(NetTrace, "%d ", pointer[i]);
4541592Srgrimes		    if (++i >= length) {
4551592Srgrimes			fprintf(NetTrace, "(partial suboption??\?)");
4561592Srgrimes			break;
4571592Srgrimes		    }
4581592Srgrimes		    fprintf(NetTrace, "%s|%s ",
4591592Srgrimes			((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
4601592Srgrimes							"CLIENT" : "SERVER",
4611592Srgrimes			((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
4621592Srgrimes							"MUTUAL" : "ONE-WAY");
4631592Srgrimes		    ++i;
4641592Srgrimes		}
4651592Srgrimes		break;
4661592Srgrimes
4671592Srgrimes	    case TELQUAL_NAME:
4681592Srgrimes		i = 2;
4691592Srgrimes		fprintf(NetTrace, " NAME \"");
4701592Srgrimes		while (i < length)
4711592Srgrimes		    putc(pointer[i++], NetTrace);
4721592Srgrimes		putc('"', NetTrace);
4731592Srgrimes		break;
4741592Srgrimes
4751592Srgrimes	    default:
4761592Srgrimes		    for (i = 2; i < length; i++)
4771592Srgrimes			fprintf(NetTrace, " ?%d?", pointer[i]);
4781592Srgrimes		    break;
4791592Srgrimes	    }
4801592Srgrimes	    break;
4811592Srgrimes#endif
4821592Srgrimes
4831592Srgrimes#ifdef	ENCRYPTION
4841592Srgrimes	case TELOPT_ENCRYPT:
4851592Srgrimes	    fprintf(NetTrace, "ENCRYPT");
4861592Srgrimes	    if (length < 2) {
4871592Srgrimes		fprintf(NetTrace, " (empty suboption??\?)");
4881592Srgrimes		break;
4891592Srgrimes	    }
4901592Srgrimes	    switch (pointer[1]) {
4911592Srgrimes	    case ENCRYPT_START:
4921592Srgrimes		fprintf(NetTrace, " START");
4931592Srgrimes		break;
4941592Srgrimes
4951592Srgrimes	    case ENCRYPT_END:
4961592Srgrimes		fprintf(NetTrace, " END");
4971592Srgrimes		break;
4981592Srgrimes
4991592Srgrimes	    case ENCRYPT_REQSTART:
5001592Srgrimes		fprintf(NetTrace, " REQUEST-START");
5011592Srgrimes		break;
5021592Srgrimes
5031592Srgrimes	    case ENCRYPT_REQEND:
5041592Srgrimes		fprintf(NetTrace, " REQUEST-END");
5051592Srgrimes		break;
5061592Srgrimes
5071592Srgrimes	    case ENCRYPT_IS:
5081592Srgrimes	    case ENCRYPT_REPLY:
5091592Srgrimes		fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
5101592Srgrimes							"IS" : "REPLY");
5111592Srgrimes		if (length < 3) {
5121592Srgrimes		    fprintf(NetTrace, " (partial suboption??\?)");
5131592Srgrimes		    break;
5141592Srgrimes		}
5151592Srgrimes		if (ENCTYPE_NAME_OK(pointer[2]))
5161592Srgrimes		    fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
5171592Srgrimes		else
5181592Srgrimes		    fprintf(NetTrace, " %d (unknown)", pointer[2]);
5191592Srgrimes
5201592Srgrimes		encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
5211592Srgrimes		fprintf(NetTrace, "%s", buf);
5221592Srgrimes		break;
5231592Srgrimes
5241592Srgrimes	    case ENCRYPT_SUPPORT:
5251592Srgrimes		i = 2;
5261592Srgrimes		fprintf(NetTrace, " SUPPORT ");
5271592Srgrimes		while (i < length) {
5281592Srgrimes		    if (ENCTYPE_NAME_OK(pointer[i]))
5291592Srgrimes			fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
5301592Srgrimes		    else
5311592Srgrimes			fprintf(NetTrace, "%d ", pointer[i]);
5321592Srgrimes		    i++;
5331592Srgrimes		}
5341592Srgrimes		break;
5351592Srgrimes
5361592Srgrimes	    case ENCRYPT_ENC_KEYID:
5371592Srgrimes		fprintf(NetTrace, " ENC_KEYID ");
5381592Srgrimes		goto encommon;
5391592Srgrimes
5401592Srgrimes	    case ENCRYPT_DEC_KEYID:
5411592Srgrimes		fprintf(NetTrace, " DEC_KEYID ");
5421592Srgrimes		goto encommon;
5431592Srgrimes
5441592Srgrimes	    default:
5451592Srgrimes		fprintf(NetTrace, " %d (unknown)", pointer[1]);
5461592Srgrimes	    encommon:
5471592Srgrimes		for (i = 2; i < length; i++)
5481592Srgrimes		    fprintf(NetTrace, " %d", pointer[i]);
5491592Srgrimes		break;
5501592Srgrimes	    }
5511592Srgrimes	    break;
5521592Srgrimes#endif	/* ENCRYPTION */
5531592Srgrimes
5541592Srgrimes	case TELOPT_LINEMODE:
5551592Srgrimes	    fprintf(NetTrace, "LINEMODE ");
5561592Srgrimes	    if (length < 2) {
5571592Srgrimes		fprintf(NetTrace, " (empty suboption??\?)");
5581592Srgrimes		break;
5591592Srgrimes	    }
5601592Srgrimes	    switch (pointer[1]) {
5611592Srgrimes	    case WILL:
5621592Srgrimes		fprintf(NetTrace, "WILL ");
5631592Srgrimes		goto common;
5641592Srgrimes	    case WONT:
5651592Srgrimes		fprintf(NetTrace, "WONT ");
5661592Srgrimes		goto common;
5671592Srgrimes	    case DO:
5681592Srgrimes		fprintf(NetTrace, "DO ");
5691592Srgrimes		goto common;
5701592Srgrimes	    case DONT:
5711592Srgrimes		fprintf(NetTrace, "DONT ");
5721592Srgrimes	    common:
5731592Srgrimes		if (length < 3) {
5741592Srgrimes		    fprintf(NetTrace, "(no option??\?)");
5751592Srgrimes		    break;
5761592Srgrimes		}
5771592Srgrimes		switch (pointer[2]) {
5781592Srgrimes		case LM_FORWARDMASK:
5791592Srgrimes		    fprintf(NetTrace, "Forward Mask");
5801592Srgrimes		    for (i = 3; i < length; i++)
5811592Srgrimes			fprintf(NetTrace, " %x", pointer[i]);
5821592Srgrimes		    break;
5831592Srgrimes		default:
5841592Srgrimes		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
5851592Srgrimes		    for (i = 3; i < length; i++)
5861592Srgrimes			fprintf(NetTrace, " %d", pointer[i]);
5871592Srgrimes		    break;
5881592Srgrimes		}
5891592Srgrimes		break;
5901592Srgrimes
5911592Srgrimes	    case LM_SLC:
5921592Srgrimes		fprintf(NetTrace, "SLC");
5931592Srgrimes		for (i = 2; i < length - 2; i += 3) {
5941592Srgrimes		    if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
5951592Srgrimes			fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
5961592Srgrimes		    else
5971592Srgrimes			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
5981592Srgrimes		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
5991592Srgrimes		    case SLC_NOSUPPORT:
6001592Srgrimes			fprintf(NetTrace, " NOSUPPORT"); break;
6011592Srgrimes		    case SLC_CANTCHANGE:
6021592Srgrimes			fprintf(NetTrace, " CANTCHANGE"); break;
6031592Srgrimes		    case SLC_VARIABLE:
6041592Srgrimes			fprintf(NetTrace, " VARIABLE"); break;
6051592Srgrimes		    case SLC_DEFAULT:
6061592Srgrimes			fprintf(NetTrace, " DEFAULT"); break;
6071592Srgrimes		    }
6081592Srgrimes		    fprintf(NetTrace, "%s%s%s",
6091592Srgrimes			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
6101592Srgrimes			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
6111592Srgrimes			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
6121592Srgrimes		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
6131592Srgrimes						SLC_FLUSHOUT| SLC_LEVELBITS))
6141592Srgrimes			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
6151592Srgrimes		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
6161592Srgrimes		    if ((pointer[i+SLC_VALUE] == IAC) &&
6171592Srgrimes			(pointer[i+SLC_VALUE+1] == IAC))
6181592Srgrimes				i++;
6191592Srgrimes		}
6201592Srgrimes		for (; i < length; i++)
6211592Srgrimes		    fprintf(NetTrace, " ?%d?", pointer[i]);
6221592Srgrimes		break;
6231592Srgrimes
6241592Srgrimes	    case LM_MODE:
6251592Srgrimes		fprintf(NetTrace, "MODE ");
6261592Srgrimes		if (length < 3) {
6271592Srgrimes		    fprintf(NetTrace, "(no mode??\?)");
6281592Srgrimes		    break;
6291592Srgrimes		}
6301592Srgrimes		{
6311592Srgrimes		    char tbuf[64];
6321592Srgrimes		    sprintf(tbuf, "%s%s%s%s%s",
6331592Srgrimes			pointer[2]&MODE_EDIT ? "|EDIT" : "",
6341592Srgrimes			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
6351592Srgrimes			pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
6361592Srgrimes			pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
6371592Srgrimes			pointer[2]&MODE_ACK ? "|ACK" : "");
6381592Srgrimes		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
6391592Srgrimes		}
6401592Srgrimes		if (pointer[2]&~(MODE_MASK))
6411592Srgrimes		    fprintf(NetTrace, " (0x%x)", pointer[2]);
6421592Srgrimes		for (i = 3; i < length; i++)
6431592Srgrimes		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
6441592Srgrimes		break;
6451592Srgrimes	    default:
6461592Srgrimes		fprintf(NetTrace, "%d (unknown)", pointer[1]);
6471592Srgrimes		for (i = 2; i < length; i++)
6481592Srgrimes		    fprintf(NetTrace, " %d", pointer[i]);
6491592Srgrimes	    }
6501592Srgrimes	    break;
6511592Srgrimes
6521592Srgrimes	case TELOPT_STATUS: {
6531592Srgrimes	    const char *cp;
6541592Srgrimes	    int j, k;
6551592Srgrimes
6561592Srgrimes	    fprintf(NetTrace, "STATUS");
6571592Srgrimes
6581592Srgrimes	    switch (pointer[1]) {
6591592Srgrimes	    default:
6601592Srgrimes		if (pointer[1] == TELQUAL_SEND)
6611592Srgrimes		    fprintf(NetTrace, " SEND");
6621592Srgrimes		else
6631592Srgrimes		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
6641592Srgrimes		for (i = 2; i < length; i++)
6651592Srgrimes		    fprintf(NetTrace, " ?%d?", pointer[i]);
6661592Srgrimes		break;
6671592Srgrimes	    case TELQUAL_IS:
6681592Srgrimes		if (--want_status_response < 0)
6691592Srgrimes		    want_status_response = 0;
6701592Srgrimes		if (NetTrace == stdout)
6711592Srgrimes		    fprintf(NetTrace, " IS\r\n");
6721592Srgrimes		else
6731592Srgrimes		    fprintf(NetTrace, " IS\n");
6741592Srgrimes
6751592Srgrimes		for (i = 2; i < length; i++) {
6761592Srgrimes		    switch(pointer[i]) {
6771592Srgrimes		    case DO:	cp = "DO"; goto common2;
6781592Srgrimes		    case DONT:	cp = "DONT"; goto common2;
6791592Srgrimes		    case WILL:	cp = "WILL"; goto common2;
6801592Srgrimes		    case WONT:	cp = "WONT"; goto common2;
6811592Srgrimes		    common2:
6821592Srgrimes			i++;
6831592Srgrimes			if (TELOPT_OK((int)pointer[i]))
6841592Srgrimes			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
6851592Srgrimes			else
6861592Srgrimes			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
6871592Srgrimes
6881592Srgrimes			if (NetTrace == stdout)
6891592Srgrimes			    fprintf(NetTrace, "\r\n");
6901592Srgrimes			else
6911592Srgrimes			    fprintf(NetTrace, "\n");
6921592Srgrimes			break;
6931592Srgrimes
6941592Srgrimes		    case SB:
6951592Srgrimes			fprintf(NetTrace, " SB ");
6961592Srgrimes			i++;
6971592Srgrimes			j = k = i;
6981592Srgrimes			while (j < length) {
6991592Srgrimes			    if (pointer[j] == SE) {
7001592Srgrimes				if (j+1 == length)
7011592Srgrimes				    break;
7021592Srgrimes				if (pointer[j+1] == SE)
7031592Srgrimes				    j++;
7041592Srgrimes				else
7051592Srgrimes				    break;
7061592Srgrimes			    }
7071592Srgrimes			    pointer[k++] = pointer[j++];
7081592Srgrimes			}
7091592Srgrimes			printsub(0, &pointer[i], k - i);
7101592Srgrimes			if (i < length) {
7111592Srgrimes			    fprintf(NetTrace, " SE");
7121592Srgrimes			    i = j;
7131592Srgrimes			} else
7141592Srgrimes			    i = j - 1;
7151592Srgrimes
7161592Srgrimes			if (NetTrace == stdout)
7171592Srgrimes			    fprintf(NetTrace, "\r\n");
7181592Srgrimes			else
7191592Srgrimes			    fprintf(NetTrace, "\n");
7201592Srgrimes
7211592Srgrimes			break;
7221592Srgrimes
7231592Srgrimes		    default:
7241592Srgrimes			fprintf(NetTrace, " %d", pointer[i]);
7251592Srgrimes			break;
7261592Srgrimes		    }
7271592Srgrimes		}
7281592Srgrimes		break;
7291592Srgrimes	    }
7301592Srgrimes	    break;
7311592Srgrimes	  }
7321592Srgrimes
7331592Srgrimes	case TELOPT_XDISPLOC:
7341592Srgrimes	    fprintf(NetTrace, "X-DISPLAY-LOCATION ");
7351592Srgrimes	    switch (pointer[1]) {
7361592Srgrimes	    case TELQUAL_IS:
7371592Srgrimes		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
7381592Srgrimes		break;
7391592Srgrimes	    case TELQUAL_SEND:
7401592Srgrimes		fprintf(NetTrace, "SEND");
7411592Srgrimes		break;
7421592Srgrimes	    default:
7431592Srgrimes		fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
7441592Srgrimes				pointer[1], pointer[1]);
7451592Srgrimes	    }
7461592Srgrimes	    break;
7471592Srgrimes
7481592Srgrimes	case TELOPT_NEW_ENVIRON:
7491592Srgrimes	    fprintf(NetTrace, "NEW-ENVIRON ");
7501592Srgrimes#ifdef	OLD_ENVIRON
7511592Srgrimes	    goto env_common1;
7521592Srgrimes	case TELOPT_OLD_ENVIRON:
7531592Srgrimes	    fprintf(NetTrace, "OLD-ENVIRON");
7541592Srgrimes	env_common1:
7551592Srgrimes#endif
7561592Srgrimes	    switch (pointer[1]) {
7571592Srgrimes	    case TELQUAL_IS:
7581592Srgrimes		fprintf(NetTrace, "IS ");
7591592Srgrimes		goto env_common;
7601592Srgrimes	    case TELQUAL_SEND:
7611592Srgrimes		fprintf(NetTrace, "SEND ");
7621592Srgrimes		goto env_common;
7631592Srgrimes	    case TELQUAL_INFO:
7641592Srgrimes		fprintf(NetTrace, "INFO ");
7651592Srgrimes	    env_common:
7661592Srgrimes		{
7671592Srgrimes		    int noquote = 2;
7681592Srgrimes#if defined(ENV_HACK) && defined(OLD_ENVIRON)
7691592Srgrimes		    extern int old_env_var, old_env_value;
7701592Srgrimes#endif
7711592Srgrimes		    for (i = 2; i < length; i++ ) {
7721592Srgrimes			switch (pointer[i]) {
7731592Srgrimes			case NEW_ENV_VALUE:
7741592Srgrimes#ifdef OLD_ENVIRON
7751592Srgrimes		     /*	case NEW_ENV_OVAR: */
7761592Srgrimes			    if (pointer[0] == TELOPT_OLD_ENVIRON) {
7771592Srgrimes# ifdef	ENV_HACK
7781592Srgrimes				if (old_env_var == OLD_ENV_VALUE)
7791592Srgrimes				    fprintf(NetTrace, "\" (VALUE) " + noquote);
7801592Srgrimes				else
7811592Srgrimes# endif
7821592Srgrimes				    fprintf(NetTrace, "\" VAR " + noquote);
7831592Srgrimes			    } else
7841592Srgrimes#endif /* OLD_ENVIRON */
7851592Srgrimes				fprintf(NetTrace, "%s", "\" VALUE " + noquote);
7861592Srgrimes			    noquote = 2;
7871592Srgrimes			    break;
7881592Srgrimes
7891592Srgrimes			case NEW_ENV_VAR:
7901592Srgrimes#ifdef OLD_ENVIRON
7911592Srgrimes		     /* case OLD_ENV_VALUE: */
7921592Srgrimes			    if (pointer[0] == TELOPT_OLD_ENVIRON) {
7931592Srgrimes# ifdef	ENV_HACK
7941592Srgrimes				if (old_env_value == OLD_ENV_VAR)
7951592Srgrimes				    fprintf(NetTrace, "\" (VAR) " + noquote);
7961592Srgrimes				else
7971592Srgrimes# endif
7981592Srgrimes				    fprintf(NetTrace, "\" VALUE " + noquote);
7991592Srgrimes			    } else
8001592Srgrimes#endif /* OLD_ENVIRON */
8011592Srgrimes				fprintf(NetTrace, "%s", "\" VAR " + noquote);
8021592Srgrimes			    noquote = 2;
8031592Srgrimes			    break;
8041592Srgrimes
8051592Srgrimes			case ENV_ESC:
8061592Srgrimes			    fprintf(NetTrace, "%s", "\" ESC " + noquote);
8071592Srgrimes			    noquote = 2;
8081592Srgrimes			    break;
8091592Srgrimes
8101592Srgrimes			case ENV_USERVAR:
8111592Srgrimes			    fprintf(NetTrace, "%s", "\" USERVAR " + noquote);
8121592Srgrimes			    noquote = 2;
8131592Srgrimes			    break;
8141592Srgrimes
8151592Srgrimes			default:
8161592Srgrimes			    if (isprint(pointer[i]) && pointer[i] != '"') {
8171592Srgrimes				if (noquote) {
8181592Srgrimes				    putc('"', NetTrace);
8191592Srgrimes				    noquote = 0;
8201592Srgrimes				}
8211592Srgrimes				putc(pointer[i], NetTrace);
8221592Srgrimes			    } else {
8231592Srgrimes				fprintf(NetTrace, "\" %03o " + noquote,
8241592Srgrimes							pointer[i]);
8251592Srgrimes				noquote = 2;
8261592Srgrimes			    }
8271592Srgrimes			    break;
8281592Srgrimes			}
8291592Srgrimes		    }
8301592Srgrimes		    if (!noquote)
8311592Srgrimes			putc('"', NetTrace);
8321592Srgrimes		    break;
8331592Srgrimes		}
8341592Srgrimes	    }
8351592Srgrimes	    break;
8361592Srgrimes
8371592Srgrimes	default:
8381592Srgrimes	    if (TELOPT_OK(pointer[0]))
8391592Srgrimes		fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
8401592Srgrimes	    else
8411592Srgrimes		fprintf(NetTrace, "%d (unknown)", pointer[0]);
8421592Srgrimes	    for (i = 1; i < length; i++)
8431592Srgrimes		fprintf(NetTrace, " %d", pointer[i]);
8441592Srgrimes	    break;
8451592Srgrimes	}
8461592Srgrimes	if (direction) {
8471592Srgrimes	    if (NetTrace == stdout)
8481592Srgrimes		fprintf(NetTrace, "\r\n");
8491592Srgrimes	    else
8501592Srgrimes		fprintf(NetTrace, "\n");
8511592Srgrimes	}
8521592Srgrimes	if (NetTrace == stdout)
8531592Srgrimes	    fflush(NetTrace);
8541592Srgrimes    }
8551592Srgrimes}
8561592Srgrimes
8571592Srgrimes/* EmptyTerminal - called to make sure that the terminal buffer is empty.
8581592Srgrimes *			Note that we consider the buffer to run all the
8591592Srgrimes *			way to the kernel (thus the select).
8601592Srgrimes */
8611592Srgrimes
8621592Srgrimesstatic void
8631592SrgrimesEmptyTerminal(void)
8641592Srgrimes{
8651592Srgrimes    fd_set	o;
8661592Srgrimes
8671592Srgrimes    FD_ZERO(&o);
8681592Srgrimes
8691592Srgrimes    if (TTYBYTES() == 0) {
8701592Srgrimes	FD_SET(tout, &o);
8711592Srgrimes	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
8721592Srgrimes			(struct timeval *) 0);	/* wait for TTLOWAT */
8731592Srgrimes    } else {
8741592Srgrimes	while (TTYBYTES()) {
8751592Srgrimes	    (void) ttyflush(0);
8761592Srgrimes	    FD_SET(tout, &o);
8771592Srgrimes	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
8781592Srgrimes				(struct timeval *) 0);	/* wait for TTLOWAT */
8791592Srgrimes	}
8801592Srgrimes    }
8811592Srgrimes}
8821592Srgrimes
8831592Srgrimesstatic void
8841592SrgrimesSetForExit(void)
8851592Srgrimes{
8861592Srgrimes    setconnmode(0);
8871592Srgrimes    do {
8881592Srgrimes	(void)telrcv();			/* Process any incoming data */
8891592Srgrimes	EmptyTerminal();
8901592Srgrimes    } while (ring_full_count(&netiring));	/* While there is any */
8911592Srgrimes    setcommandmode();
8921592Srgrimes    fflush(stdout);
8931592Srgrimes    fflush(stderr);
8941592Srgrimes    setconnmode(0);
8951592Srgrimes    EmptyTerminal();			/* Flush the path to the tty */
8961592Srgrimes    setcommandmode();
8971592Srgrimes}
8981592Srgrimes
8991592Srgrimesvoid
9001592SrgrimesExit(int returnCode)
9011592Srgrimes{
9021592Srgrimes    SetForExit();
9031592Srgrimes    exit(returnCode);
9041592Srgrimes}
9051592Srgrimes
9061592Srgrimesvoid
9071592SrgrimesExitString(const char *string, int returnCode)
9081592Srgrimes{
9091592Srgrimes    SetForExit();
9101592Srgrimes    fwrite(string, 1, strlen(string), stderr);
9111592Srgrimes    exit(returnCode);
9121592Srgrimes}
9131592Srgrimes