xref: /csrg-svn/usr.bin/telnet/utilities.c (revision 38690)
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*38690Sborman static char sccsid[] = "@(#)utilities.c	1.14 (Berkeley) 08/21/89";
2033686Sbostic #endif /* not lint */
2133686Sbostic 
2232149Sminshall #define	TELOPTS
23*38690Sborman #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 */
40*38690Sborman 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*38690Sborman char NetTraceFile[256] = "(standard output)";
9432149Sminshall 
9532149Sminshall void
96*38690Sborman SetNetTrace(file)
97*38690Sborman register char *file;
98*38690Sborman {
99*38690Sborman     if (NetTrace && NetTrace != stdout)
100*38690Sborman 	fclose(NetTrace);
101*38690Sborman     if (file  && (strcmp(file, "-") != 0)) {
102*38690Sborman 	NetTrace = fopen(file, "w");
103*38690Sborman 	if (NetTrace) {
104*38690Sborman 	    strcpy(NetTraceFile, file);
105*38690Sborman 	    return;
106*38690Sborman 	}
107*38690Sborman 	fprintf(stderr, "Cannot open %s.\n", file);
108*38690Sborman     }
109*38690Sborman     NetTrace = stdout;
110*38690Sborman     strcpy(NetTraceFile, "(standard output)");
111*38690Sborman }
112*38690Sborman 
113*38690Sborman 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;
123*38690Sborman     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;
131*38690Sborman 	if (prettydump) {
132*38690Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE);
133*38690Sborman 	    while (pThis < buffer) {
134*38690Sborman 		fprintf(NetTrace, "%c%.2x",
135*38690Sborman 		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
136*38690Sborman 		    (*pThis)&0xff);
137*38690Sborman 		pThis++;
138*38690Sborman 	    }
139*38690Sborman 	} else {
140*38690Sborman 	    buffer = buffer + min(length, BYTES_PER_LINE/2);
141*38690Sborman 	    while (pThis < buffer) {
142*38690Sborman 		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
143*38690Sborman 		pThis++;
144*38690Sborman 	    }
14532149Sminshall 	}
14637226Sminshall 	if (NetTrace == stdout) {
14738207Sminshall 	    fprintf(NetTrace, "\r\n");
14838207Sminshall 	} else {
14937226Sminshall 	    fprintf(NetTrace, "\n");
15037226Sminshall 	}
15132149Sminshall 	length -= BYTES_PER_LINE;
15232149Sminshall 	offset += BYTES_PER_LINE;
15332149Sminshall 	if (length < 0) {
15436693Sminshall 	    fflush(NetTrace);
15532149Sminshall 	    return;
15632149Sminshall 	}
15732149Sminshall 	/* find next unique line */
15832149Sminshall     }
15936693Sminshall     fflush(NetTrace);
16032149Sminshall }
16132149Sminshall 
16232149Sminshall 
16332149Sminshall void
16437226Sminshall printoption(direction, fmt, option)
16532149Sminshall 	char *direction, *fmt;
16637226Sminshall 	int option;
16732149Sminshall {
16832149Sminshall 	if (!showoptions)
16932149Sminshall 		return;
17037226Sminshall 	fprintf(NetTrace, "%s ", direction);
171*38690Sborman 	if (TELOPT_OK(option))
172*38690Sborman 		fprintf(NetTrace, "%s %s", fmt, TELOPT(option));
173*38690Sborman 	else if (TELCMD_OK(option))
174*38690Sborman 		fprintf(NetTrace, "%s %s", fmt, TELCMD(option));
17532149Sminshall 	else
17632149Sminshall 		fprintf(NetTrace, "%s %d", fmt, option);
177*38690Sborman 	if (NetTrace == stdout)
17837226Sminshall 	    fprintf(NetTrace, "\r\n");
179*38690Sborman 	else
18037226Sminshall 	    fprintf(NetTrace, "\n");
18137226Sminshall 	return;
18232149Sminshall }
18332149Sminshall 
184*38690Sborman optionstatus()
185*38690Sborman {
186*38690Sborman     register int i;
187*38690Sborman     extern char will_wont_resp[], do_dont_resp[];
188*38690Sborman 
189*38690Sborman     for (i = 0; i < 256; i++) {
190*38690Sborman 	if (do_dont_resp[i]) {
191*38690Sborman 	    if (TELOPT_OK(i))
192*38690Sborman 		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
193*38690Sborman 	    else if (TELCMD_OK(i))
194*38690Sborman 		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
195*38690Sborman 	    else
196*38690Sborman 		printf("resp DO_DONT %d: %d\n", i,
197*38690Sborman 				do_dont_resp[i]);
198*38690Sborman 	    if (my_want_state_is_do(i)) {
199*38690Sborman 		if (TELOPT_OK(i))
200*38690Sborman 		    printf("want DO   %s\n", TELOPT(i));
201*38690Sborman 		else if (TELCMD_OK(i))
202*38690Sborman 		    printf("want DO   %s\n", TELCMD(i));
203*38690Sborman 		else
204*38690Sborman 		    printf("want DO   %d\n", i);
205*38690Sborman 	    } else {
206*38690Sborman 		if (TELOPT_OK(i))
207*38690Sborman 		    printf("want DONT %s\n", TELOPT(i));
208*38690Sborman 		else if (TELCMD_OK(i))
209*38690Sborman 		    printf("want DONT %s\n", TELCMD(i));
210*38690Sborman 		else
211*38690Sborman 		    printf("want DONT %d\n", i);
212*38690Sborman 	    }
213*38690Sborman 	} else {
214*38690Sborman 	    if (my_state_is_do(i)) {
215*38690Sborman 		if (TELOPT_OK(i))
216*38690Sborman 		    printf("     DO   %s\n", TELOPT(i));
217*38690Sborman 		else if (TELCMD_OK(i))
218*38690Sborman 		    printf("     DO   %s\n", TELCMD(i));
219*38690Sborman 		else
220*38690Sborman 		    printf("     DO   %d\n", i);
221*38690Sborman 	    }
222*38690Sborman 	}
223*38690Sborman 	if (will_wont_resp[i]) {
224*38690Sborman 	    if (TELOPT_OK(i))
225*38690Sborman 		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
226*38690Sborman 	    else if (TELCMD_OK(i))
227*38690Sborman 		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
228*38690Sborman 	    else
229*38690Sborman 		printf("resp WILL_WONT %d: %d\n",
230*38690Sborman 				i, will_wont_resp[i]);
231*38690Sborman 	    if (my_want_state_is_will(i)) {
232*38690Sborman 		if (TELOPT_OK(i))
233*38690Sborman 		    printf("want WILL %s\n", TELOPT(i));
234*38690Sborman 		else if (TELCMD_OK(i))
235*38690Sborman 		    printf("want WILL %s\n", TELCMD(i));
236*38690Sborman 		else
237*38690Sborman 		    printf("want WILL %d\n", i);
238*38690Sborman 	    } else {
239*38690Sborman 		if (TELOPT_OK(i))
240*38690Sborman 		    printf("want WONT %s\n", TELOPT(i));
241*38690Sborman 		else if (TELCMD_OK(i))
242*38690Sborman 		    printf("want WONT %s\n", TELCMD(i));
243*38690Sborman 		else
244*38690Sborman 		    printf("want WONT %d\n", i);
245*38690Sborman 	    }
246*38690Sborman 	} else {
247*38690Sborman 	    if (my_state_is_will(i)) {
248*38690Sborman 		if (TELOPT_OK(i))
249*38690Sborman 		    printf("     WILL %s\n", TELOPT(i));
250*38690Sborman 		else if (TELCMD_OK(i))
251*38690Sborman 		    printf("     WILL %s\n", TELCMD(i));
252*38690Sborman 		else
253*38690Sborman 		    printf("     WILL %d\n", i);
254*38690Sborman 	    }
255*38690Sborman 	}
256*38690Sborman     }
257*38690Sborman 
258*38690Sborman }
259*38690Sborman 
260*38690Sborman char *slcnames[] = { SLC_NAMES };
261*38690Sborman 
26232149Sminshall void
26332149Sminshall printsub(direction, pointer, length)
264*38690Sborman char	direction;		/* '<' or '>' */
265*38690Sborman unsigned char	*pointer;	/* where suboption data sits */
26632149Sminshall int	length;			/* length of suboption data */
26732149Sminshall {
268*38690Sborman     register int i;
269*38690Sborman 
27032149Sminshall     if (showoptions) {
27132149Sminshall 	fprintf(NetTrace, "%s suboption ",
272*38690Sborman 				(direction == '<')? "Received":"Sent");
273*38690Sborman 	if (length >= 3) {
274*38690Sborman 	    register int j;
275*38690Sborman 
276*38690Sborman 	    i = pointer[length-2];
277*38690Sborman 	    j = pointer[length-1];
278*38690Sborman 
279*38690Sborman 	    if (i != IAC || j != SE) {
280*38690Sborman 		fprintf(NetTrace, "(terminated by ");
281*38690Sborman 		if (TELOPT_OK(i))
282*38690Sborman 		    fprintf(NetTrace, "%s ", TELOPT(i));
283*38690Sborman 		else if (TELCMD_OK(i))
284*38690Sborman 		    fprintf(NetTrace, "%s ", TELCMD(i));
285*38690Sborman 		else
286*38690Sborman 		    fprintf(NetTrace, "%d ", i);
287*38690Sborman 		if (TELOPT_OK(j))
288*38690Sborman 		    fprintf(NetTrace, "%s", TELOPT(j));
289*38690Sborman 		else if (TELCMD_OK(j))
290*38690Sborman 		    fprintf(NetTrace, "%s", TELCMD(j));
291*38690Sborman 		else
292*38690Sborman 		    fprintf(NetTrace, "%d", j);
293*38690Sborman 		fprintf(NetTrace, ", not IAC SE!) ");
294*38690Sborman 	    }
295*38690Sborman 	}
296*38690Sborman 	length -= 2;
297*38690Sborman 	if (length < 1) {
298*38690Sborman 	    fprintf(NetTrace, "(Empty suboption???)");
299*38690Sborman 	    return;
300*38690Sborman 	}
30132149Sminshall 	switch (pointer[0]) {
30232149Sminshall 	case TELOPT_TTYPE:
303*38690Sborman 	    fprintf(NetTrace, "TERMINAL-TYPE ");
30432149Sminshall 	    switch (pointer[1]) {
30532149Sminshall 	    case TELQUAL_IS:
306*38690Sborman 		fprintf(NetTrace, "IS \"%.*s\"", length-2, pointer+2);
30732149Sminshall 		break;
30832149Sminshall 	    case TELQUAL_SEND:
309*38690Sborman 		fprintf(NetTrace, "SEND");
31032149Sminshall 		break;
31132149Sminshall 	    default:
31232149Sminshall 		fprintf(NetTrace,
313*38690Sborman 				"- unknown qualifier %d (0x%x).",
31434849Sminshall 				pointer[1], pointer[1]);
31532149Sminshall 	    }
31632149Sminshall 	    break;
317*38690Sborman 	case TELOPT_TSPEED:
318*38690Sborman 	    fprintf(NetTrace, "TERMINAL-SPEED");
319*38690Sborman 	    if (length < 2) {
320*38690Sborman 		fprintf(NetTrace, " (empty suboption???)");
321*38690Sborman 		break;
322*38690Sborman 	    }
323*38690Sborman 	    switch (pointer[1]) {
324*38690Sborman 	    case 0:
325*38690Sborman 		fprintf(NetTrace, " IS ");
326*38690Sborman 		fprintf(NetTrace, "%.*s", length-2, pointer+2);
327*38690Sborman 		break;
328*38690Sborman 	    default:
329*38690Sborman 		if (pointer[1] == 1)
330*38690Sborman 		    fprintf(NetTrace, " SEND");
331*38690Sborman 		else
332*38690Sborman 		    fprintf(NetTrace, " %d (unknown)");
333*38690Sborman 		for (i = 2; i < length; i++)
334*38690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
335*38690Sborman 		break;
336*38690Sborman 	    }
337*38690Sborman 	    break;
338*38690Sborman 
339*38690Sborman 	case TELOPT_LFLOW:
340*38690Sborman 	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
341*38690Sborman 	    if (length < 2) {
342*38690Sborman 		fprintf(NetTrace, " (empty suboption???)");
343*38690Sborman 		break;
344*38690Sborman 	    }
345*38690Sborman 	    switch (pointer[1]) {
346*38690Sborman 	    case 0:
347*38690Sborman 		fprintf(NetTrace, " OFF"); break;
348*38690Sborman 	    case 1:
349*38690Sborman 		fprintf(NetTrace, " ON"); break;
350*38690Sborman 	    default:
351*38690Sborman 		fprintf(NetTrace, " %d (unknown)");
352*38690Sborman 	    }
353*38690Sborman 	    for (i = 2; i < length; i++)
354*38690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
355*38690Sborman 	    break;
356*38690Sborman 
357*38690Sborman 	case TELOPT_NAWS:
358*38690Sborman 	    fprintf(NetTrace, "NAWS");
359*38690Sborman 	    if (length < 2) {
360*38690Sborman 		fprintf(NetTrace, " (empty suboption???)");
361*38690Sborman 		break;
362*38690Sborman 	    }
363*38690Sborman 	    if (length == 2) {
364*38690Sborman 		fprintf(NetTrace, " ?%d?", pointer[1]);
365*38690Sborman 		break;
366*38690Sborman 	    }
367*38690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
368*38690Sborman 		pointer[1], pointer[2],
369*38690Sborman 		(((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]));
370*38690Sborman 	    if (length == 4) {
371*38690Sborman 		fprintf(NetTrace, " ?%d?", pointer[3]);
372*38690Sborman 		break;
373*38690Sborman 	    }
374*38690Sborman 	    fprintf(NetTrace, " %d %d (%d)",
375*38690Sborman 		pointer[3], pointer[4],
376*38690Sborman 		(((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]));
377*38690Sborman 	    for (i = 5; i < length; i++)
378*38690Sborman 		fprintf(NetTrace, " ?%d?", pointer[i]);
379*38690Sborman 	    break;
380*38690Sborman 
381*38690Sborman 	case TELOPT_LINEMODE:
382*38690Sborman 	    fprintf(NetTrace, "LINEMODE ");
383*38690Sborman 	    if (length < 2) {
384*38690Sborman 		fprintf(NetTrace, " (empty suboption???)");
385*38690Sborman 		break;
386*38690Sborman 	    }
387*38690Sborman 	    switch (pointer[1]) {
388*38690Sborman 	    case WILL:
389*38690Sborman 		fprintf(NetTrace, "WILL ");
390*38690Sborman 		goto common;
391*38690Sborman 	    case WONT:
392*38690Sborman 		fprintf(NetTrace, "WONT ");
393*38690Sborman 		goto common;
394*38690Sborman 	    case DO:
395*38690Sborman 		fprintf(NetTrace, "DO ");
396*38690Sborman 		goto common;
397*38690Sborman 	    case DONT:
398*38690Sborman 		fprintf(NetTrace, "DONT ");
399*38690Sborman 	    common:
400*38690Sborman 		if (length < 3) {
401*38690Sborman 		    fprintf(NetTrace, "(no option???)");
402*38690Sborman 		    break;
403*38690Sborman 		}
404*38690Sborman 		switch (pointer[2]) {
405*38690Sborman 		case LM_FORWARDMASK:
406*38690Sborman 		    fprintf(NetTrace, "Forward Mask");
407*38690Sborman 		    for (i = 3; i < length; i++)
408*38690Sborman 			fprintf(NetTrace, " %x", pointer[i]);
409*38690Sborman 		    break;
410*38690Sborman 		default:
411*38690Sborman 		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
412*38690Sborman 		    for (i = 3; i < length; i++)
413*38690Sborman 			fprintf(NetTrace, " %d", pointer[i]);
414*38690Sborman 		    break;
415*38690Sborman 		}
416*38690Sborman 		break;
417*38690Sborman 
418*38690Sborman 	    case LM_SLC:
419*38690Sborman 		fprintf(NetTrace, "SLC");
420*38690Sborman 		for (i = 2; i < length - 2; i += 3) {
421*38690Sborman 		    if (pointer[i+SLC_FUNC] <= NSLC)
422*38690Sborman 			fprintf(NetTrace, " %s", slcnames[pointer[i+SLC_FUNC]]);
423*38690Sborman 		    else
424*38690Sborman 			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
425*38690Sborman 		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
426*38690Sborman 		    case SLC_NOSUPPORT:
427*38690Sborman 			fprintf(NetTrace, " NOSUPPORT"); break;
428*38690Sborman 		    case SLC_CANTCHANGE:
429*38690Sborman 			fprintf(NetTrace, " CANTCHANGE"); break;
430*38690Sborman 		    case SLC_VARIABLE:
431*38690Sborman 			fprintf(NetTrace, " VARIABLE"); break;
432*38690Sborman 		    case SLC_DEFAULT:
433*38690Sborman 			fprintf(NetTrace, " DEFAULT"); break;
434*38690Sborman 		    }
435*38690Sborman 		    fprintf(NetTrace, "%s%s%s",
436*38690Sborman 			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
437*38690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
438*38690Sborman 			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
439*38690Sborman 		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
440*38690Sborman 						SLC_FLUSHOUT| SLC_LEVELBITS))
441*38690Sborman 			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
442*38690Sborman 		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
443*38690Sborman 		}
444*38690Sborman 		for (; i < length; i++)
445*38690Sborman 		    fprintf(NetTrace, " ?%d?", pointer[i]);
446*38690Sborman 		break;
447*38690Sborman 
448*38690Sborman 	    case LM_MODE:
449*38690Sborman 		fprintf(NetTrace, "MODE ");
450*38690Sborman 		if (length < 3) {
451*38690Sborman 		    fprintf(NetTrace, "(no mode???)");
452*38690Sborman 		    break;
453*38690Sborman 		}
454*38690Sborman 		{
455*38690Sborman 		    char tbuf[32];
456*38690Sborman 		    sprintf(tbuf, "%s%s%s",
457*38690Sborman 			pointer[2]&MODE_EDIT ? "|EDIT" : "",
458*38690Sborman 			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
459*38690Sborman 			pointer[2]&MODE_ACK ? "|ACK" : "");
460*38690Sborman 		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
461*38690Sborman 		}
462*38690Sborman 		if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
463*38690Sborman 		    fprintf(NetTrace, " (0x%x)", pointer[2]);
464*38690Sborman 		for (i = 3; i < length; i++)
465*38690Sborman 		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
466*38690Sborman 		break;
467*38690Sborman 	    default:
468*38690Sborman 		fprintf(NetTrace, "%d (unknown)", pointer[1]);
469*38690Sborman 		for (i = 2; i < length; i++)
470*38690Sborman 		    fprintf(NetTrace, " %d", pointer[i]);
471*38690Sborman 	    }
472*38690Sborman 	    break;
473*38690Sborman 
47432149Sminshall 	default:
475*38690Sborman 	    fprintf(NetTrace, "Unknown option ");
476*38690Sborman 	    for (i = 0; i < length; i++)
477*38690Sborman 		fprintf(NetTrace, " %d", pointer[i]);
478*38690Sborman 	    break;
47932149Sminshall 	}
480*38690Sborman 	if (NetTrace == stdout)
481*38690Sborman 	    fprintf(NetTrace, "\r\n");
482*38690Sborman 	else
483*38690Sborman 	    fprintf(NetTrace, "\n");
48432149Sminshall     }
48532149Sminshall }
48636278Sminshall 
48736278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
48836278Sminshall  *			Note that we consider the buffer to run all the
48936278Sminshall  *			way to the kernel (thus the select).
49036278Sminshall  */
49136278Sminshall 
49236278Sminshall void
49336278Sminshall EmptyTerminal()
49436278Sminshall {
49536278Sminshall #if	defined(unix)
49636278Sminshall     fd_set	o;
49736278Sminshall 
49836278Sminshall     FD_ZERO(&o);
49936278Sminshall #endif	/* defined(unix) */
50036278Sminshall 
50136278Sminshall     if (TTYBYTES() == 0) {
50236278Sminshall #if	defined(unix)
50336278Sminshall 	FD_SET(tout, &o);
50436278Sminshall 	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
50536278Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
50636278Sminshall #endif	/* defined(unix) */
50736278Sminshall     } else {
50836278Sminshall 	while (TTYBYTES()) {
50936278Sminshall 	    ttyflush(0);
51036278Sminshall #if	defined(unix)
51136278Sminshall 	    FD_SET(tout, &o);
51236278Sminshall 	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
51336278Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
51436278Sminshall #endif	/* defined(unix) */
51536278Sminshall 	}
51636278Sminshall     }
51736278Sminshall }
51836278Sminshall 
51936278Sminshall void
52036278Sminshall SetForExit()
52136278Sminshall {
522*38690Sborman     setconnmode(0);
52336278Sminshall #if	defined(TN3270)
52436278Sminshall     if (In3270) {
52536278Sminshall 	Finish3270();
52636278Sminshall     }
52736279Sminshall #else	/* defined(TN3270) */
52836279Sminshall     do {
52936279Sminshall 	telrcv();			/* Process any incoming data */
53036279Sminshall 	EmptyTerminal();
53136279Sminshall     } while (ring_full_count(&netiring));	/* While there is any */
53236278Sminshall #endif	/* defined(TN3270) */
53336278Sminshall     setcommandmode();
53436278Sminshall     fflush(stdout);
53536278Sminshall     fflush(stderr);
53636278Sminshall #if	defined(TN3270)
53736278Sminshall     if (In3270) {
53836278Sminshall 	StopScreen(1);
53936278Sminshall     }
54036278Sminshall #endif	/* defined(TN3270) */
541*38690Sborman     setconnmode(0);
54236278Sminshall     EmptyTerminal();			/* Flush the path to the tty */
54336278Sminshall     setcommandmode();
54436278Sminshall }
54536278Sminshall 
54636278Sminshall void
54736278Sminshall Exit(returnCode)
54836278Sminshall int returnCode;
54936278Sminshall {
55036278Sminshall     SetForExit();
55136278Sminshall     exit(returnCode);
55236278Sminshall }
55336278Sminshall 
55436278Sminshall void
55536278Sminshall ExitString(string, returnCode)
55636278Sminshall char *string;
55736278Sminshall int returnCode;
55836278Sminshall {
55936278Sminshall     SetForExit();
56036278Sminshall     fwrite(string, 1, strlen(string), stderr);
56136278Sminshall     exit(returnCode);
56236278Sminshall }
56336278Sminshall 
56436278Sminshall #if defined(MSDOS)
56536278Sminshall void
56636278Sminshall ExitPerror(string, returnCode)
56736278Sminshall char *string;
56836278Sminshall int returnCode;
56936278Sminshall {
57036278Sminshall     SetForExit();
57136278Sminshall     perror(string);
57236278Sminshall     exit(returnCode);
57336278Sminshall }
57436278Sminshall #endif /* defined(MSDOS) */
575