GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/telnet/utilities.c Lines: 0 356 0.0 %
Date: 2017-11-07 Branches: 0 265 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: utilities.c,v 1.22 2017/08/22 15:04:18 bluhm Exp $	*/
2
/*	$NetBSD: utilities.c,v 1.5 1996/02/28 21:04:21 thorpej Exp $	*/
3
4
/*
5
 * Copyright (c) 1988, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
/* these three defines affect the behavior of <arpa/telnet.h> */
34
#define	TELOPTS
35
#define	TELCMDS
36
#define	SLC_NAMES
37
38
#include "telnet_locl.h"
39
40
#include <arpa/telnet.h>
41
#include <ctype.h>
42
#include <limits.h>
43
#include <poll.h>
44
#include <stdlib.h>
45
#include <string.h>
46
47
static FILE	*NetTrace = NULL;
48
int	prettydump;
49
50
/*
51
 * upcase()
52
 *
53
 *	Upcase (in place) the argument.
54
 */
55
56
void
57
upcase(char *argument)
58
{
59
	int c;
60
61
	while ((c = *argument) != '\0')
62
		*argument++ = toupper((unsigned char)c);
63
}
64
65
/*
66
 * The following are routines used to print out debugging information.
67
 */
68
69
char NetTraceFile[PATH_MAX] = "(standard output)";
70
71
void
72
SetNetTrace(const char *file)
73
{
74
    if (NetTrace && NetTrace != stdout)
75
	fclose(NetTrace);
76
    if (file && (strcmp(file, "-") != 0)) {
77
	NetTrace = fopen(file, "we");
78
	if (NetTrace) {
79
	    strlcpy(NetTraceFile, file, sizeof(NetTraceFile));
80
	    return;
81
	}
82
	fprintf(stderr, "Cannot open %s.\n", file);
83
    }
84
    NetTrace = stdout;
85
    strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile));
86
}
87
88
void
89
Dump(char direction, unsigned char *buffer, int length)
90
{
91
#   define BYTES_PER_LINE	32
92
#   define min(x,y)	((x<y)? x:y)
93
    unsigned char *pThis;
94
    int offset;
95
96
    offset = 0;
97
98
    while (length) {
99
	/* print one line */
100
	fprintf(NetTrace, "%c 0x%x\t", direction, offset);
101
	pThis = buffer;
102
	if (prettydump) {
103
	    buffer = buffer + min(length, BYTES_PER_LINE/2);
104
	    while (pThis < buffer) {
105
		fprintf(NetTrace, "%c%.2x",
106
		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
107
		    (*pThis)&0xff);
108
		pThis++;
109
	    }
110
	    length -= BYTES_PER_LINE/2;
111
	    offset += BYTES_PER_LINE/2;
112
	} else {
113
	    buffer = buffer + min(length, BYTES_PER_LINE);
114
	    while (pThis < buffer) {
115
		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
116
		pThis++;
117
	    }
118
	    length -= BYTES_PER_LINE;
119
	    offset += BYTES_PER_LINE;
120
	}
121
	if (NetTrace == stdout) {
122
	    fprintf(NetTrace, "\r\n");
123
	} else {
124
	    fprintf(NetTrace, "\n");
125
	}
126
	if (length < 0) {
127
	    fflush(NetTrace);
128
	    return;
129
	}
130
	/* find next unique line */
131
    }
132
    fflush(NetTrace);
133
}
134
135
void
136
printoption(char *direction, int cmd, int option)
137
{
138
	if (!showoptions)
139
		return;
140
	if (cmd == IAC) {
141
		if (TELCMD_OK(option))
142
		    fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
143
		else
144
		    fprintf(NetTrace, "%s IAC %d", direction, option);
145
	} else {
146
		char *fmt;
147
		fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
148
			(cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
149
		if (fmt) {
150
		    fprintf(NetTrace, "%s %s ", direction, fmt);
151
		    if (TELOPT_OK(option))
152
			fprintf(NetTrace, "%s", TELOPT(option));
153
		    else if (option == TELOPT_EXOPL)
154
			fprintf(NetTrace, "EXOPL");
155
		    else
156
			fprintf(NetTrace, "%d", option);
157
		} else
158
		    fprintf(NetTrace, "%s %d %d", direction, cmd, option);
159
	}
160
	if (NetTrace == stdout) {
161
	    fprintf(NetTrace, "\r\n");
162
	    fflush(NetTrace);
163
	} else {
164
	    fprintf(NetTrace, "\n");
165
	}
166
	return;
167
}
168
169
void
170
optionstatus(void)
171
{
172
    int i;
173
174
    for (i = 0; i < 256; i++) {
175
	if (do_dont_resp[i]) {
176
	    if (TELOPT_OK(i))
177
		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
178
	    else if (TELCMD_OK(i))
179
		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
180
	    else
181
		printf("resp DO_DONT %d: %d\n", i,
182
				do_dont_resp[i]);
183
	    if (my_want_state_is_do(i)) {
184
		if (TELOPT_OK(i))
185
		    printf("want DO   %s\n", TELOPT(i));
186
		else if (TELCMD_OK(i))
187
		    printf("want DO   %s\n", TELCMD(i));
188
		else
189
		    printf("want DO   %d\n", i);
190
	    } else {
191
		if (TELOPT_OK(i))
192
		    printf("want DONT %s\n", TELOPT(i));
193
		else if (TELCMD_OK(i))
194
		    printf("want DONT %s\n", TELCMD(i));
195
		else
196
		    printf("want DONT %d\n", i);
197
	    }
198
	} else {
199
	    if (my_state_is_do(i)) {
200
		if (TELOPT_OK(i))
201
		    printf("     DO   %s\n", TELOPT(i));
202
		else if (TELCMD_OK(i))
203
		    printf("     DO   %s\n", TELCMD(i));
204
		else
205
		    printf("     DO   %d\n", i);
206
	    }
207
	}
208
	if (will_wont_resp[i]) {
209
	    if (TELOPT_OK(i))
210
		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
211
	    else if (TELCMD_OK(i))
212
		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
213
	    else
214
		printf("resp WILL_WONT %d: %d\n",
215
				i, will_wont_resp[i]);
216
	    if (my_want_state_is_will(i)) {
217
		if (TELOPT_OK(i))
218
		    printf("want WILL %s\n", TELOPT(i));
219
		else if (TELCMD_OK(i))
220
		    printf("want WILL %s\n", TELCMD(i));
221
		else
222
		    printf("want WILL %d\n", i);
223
	    } else {
224
		if (TELOPT_OK(i))
225
		    printf("want WONT %s\n", TELOPT(i));
226
		else if (TELCMD_OK(i))
227
		    printf("want WONT %s\n", TELCMD(i));
228
		else
229
		    printf("want WONT %d\n", i);
230
	    }
231
	} else {
232
	    if (my_state_is_will(i)) {
233
		if (TELOPT_OK(i))
234
		    printf("     WILL %s\n", TELOPT(i));
235
		else if (TELCMD_OK(i))
236
		    printf("     WILL %s\n", TELCMD(i));
237
		else
238
		    printf("     WILL %d\n", i);
239
	    }
240
	}
241
    }
242
243
}
244
245
void
246
printsub(char direction,	/* '<' or '>' */
247
    unsigned char *pointer,	/* where suboption data sits */
248
    int length)			/* length of suboption data */
249
{
250
    int i;
251
252
    if (showoptions || direction == 0 ||
253
	(want_status_response && (pointer[0] == TELOPT_STATUS))) {
254
	if (direction) {
255
	    fprintf(NetTrace, "%s IAC SB ",
256
				(direction == '<')? "RCVD":"SENT");
257
	    if (length >= 3) {
258
		int j;
259
260
		i = pointer[length-2];
261
		j = pointer[length-1];
262
263
		if (i != IAC || j != SE) {
264
		    fprintf(NetTrace, "(terminated by ");
265
		    if (TELOPT_OK(i))
266
			fprintf(NetTrace, "%s ", TELOPT(i));
267
		    else if (TELCMD_OK(i))
268
			fprintf(NetTrace, "%s ", TELCMD(i));
269
		    else
270
			fprintf(NetTrace, "%d ", i);
271
		    if (TELOPT_OK(j))
272
			fprintf(NetTrace, "%s", TELOPT(j));
273
		    else if (TELCMD_OK(j))
274
			fprintf(NetTrace, "%s", TELCMD(j));
275
		    else
276
			fprintf(NetTrace, "%d", j);
277
		    fprintf(NetTrace, ", not IAC SE!) ");
278
		}
279
	    }
280
	    length -= 2;
281
	}
282
	if (length < 1) {
283
	    fprintf(NetTrace, "(Empty suboption??\?)");
284
	    if (NetTrace == stdout)
285
		fflush(NetTrace);
286
	    return;
287
	}
288
	switch (pointer[0]) {
289
	case TELOPT_TTYPE:
290
	    fprintf(NetTrace, "TERMINAL-TYPE ");
291
	    switch (pointer[1]) {
292
	    case TELQUAL_IS:
293
		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
294
		break;
295
	    case TELQUAL_SEND:
296
		fprintf(NetTrace, "SEND");
297
		break;
298
	    default:
299
		fprintf(NetTrace,
300
				"- unknown qualifier %d (0x%x).",
301
				pointer[1], pointer[1]);
302
	    }
303
	    break;
304
	case TELOPT_TSPEED:
305
	    fprintf(NetTrace, "TERMINAL-SPEED");
306
	    if (length < 2) {
307
		fprintf(NetTrace, " (empty suboption??\?)");
308
		break;
309
	    }
310
	    switch (pointer[1]) {
311
	    case TELQUAL_IS:
312
		fprintf(NetTrace, " IS ");
313
		fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
314
		break;
315
	    default:
316
		if (pointer[1] == 1)
317
		    fprintf(NetTrace, " SEND");
318
		else
319
		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
320
		for (i = 2; i < length; i++)
321
		    fprintf(NetTrace, " ?%d?", pointer[i]);
322
		break;
323
	    }
324
	    break;
325
326
	case TELOPT_LFLOW:
327
	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
328
	    if (length < 2) {
329
		fprintf(NetTrace, " (empty suboption??\?)");
330
		break;
331
	    }
332
	    switch (pointer[1]) {
333
	    case LFLOW_OFF:
334
		fprintf(NetTrace, " OFF"); break;
335
	    case LFLOW_ON:
336
		fprintf(NetTrace, " ON"); break;
337
	    case LFLOW_RESTART_ANY:
338
		fprintf(NetTrace, " RESTART-ANY"); break;
339
	    case LFLOW_RESTART_XON:
340
		fprintf(NetTrace, " RESTART-XON"); break;
341
	    default:
342
		fprintf(NetTrace, " %d (unknown)", pointer[1]);
343
	    }
344
	    for (i = 2; i < length; i++)
345
		fprintf(NetTrace, " ?%d?", pointer[i]);
346
	    break;
347
348
	case TELOPT_NAWS:
349
	    fprintf(NetTrace, "NAWS");
350
	    if (length < 2) {
351
		fprintf(NetTrace, " (empty suboption??\?)");
352
		break;
353
	    }
354
	    if (length == 2) {
355
		fprintf(NetTrace, " ?%d?", pointer[1]);
356
		break;
357
	    }
358
	    fprintf(NetTrace, " %d %d (%d)",
359
		pointer[1], pointer[2], (pointer[1]<<8) | pointer[2]);
360
	    if (length == 4) {
361
		fprintf(NetTrace, " ?%d?", pointer[3]);
362
		break;
363
	    }
364
	    fprintf(NetTrace, " %d %d (%d)",
365
		pointer[3], pointer[4], (pointer[3]<<8) | pointer[4]);
366
	    for (i = 5; i < length; i++)
367
		fprintf(NetTrace, " ?%d?", pointer[i]);
368
	    break;
369
370
	case TELOPT_LINEMODE:
371
	    fprintf(NetTrace, "LINEMODE ");
372
	    if (length < 2) {
373
		fprintf(NetTrace, " (empty suboption??\?)");
374
		break;
375
	    }
376
	    switch (pointer[1]) {
377
	    case WILL:
378
		fprintf(NetTrace, "WILL ");
379
		goto common;
380
	    case WONT:
381
		fprintf(NetTrace, "WONT ");
382
		goto common;
383
	    case DO:
384
		fprintf(NetTrace, "DO ");
385
		goto common;
386
	    case DONT:
387
		fprintf(NetTrace, "DONT ");
388
	    common:
389
		if (length < 3) {
390
		    fprintf(NetTrace, "(no option??\?)");
391
		    break;
392
		}
393
		switch (pointer[2]) {
394
		case LM_FORWARDMASK:
395
		    fprintf(NetTrace, "Forward Mask");
396
		    for (i = 3; i < length; i++)
397
			fprintf(NetTrace, " %x", pointer[i]);
398
		    break;
399
		default:
400
		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
401
		    for (i = 3; i < length; i++)
402
			fprintf(NetTrace, " %d", pointer[i]);
403
		    break;
404
		}
405
		break;
406
407
	    case LM_SLC:
408
		fprintf(NetTrace, "SLC");
409
		for (i = 2; i < length - 2; i += 3) {
410
		    if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
411
			fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
412
		    else
413
			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
414
		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
415
		    case SLC_NOSUPPORT:
416
			fprintf(NetTrace, " NOSUPPORT"); break;
417
		    case SLC_CANTCHANGE:
418
			fprintf(NetTrace, " CANTCHANGE"); break;
419
		    case SLC_VARIABLE:
420
			fprintf(NetTrace, " VARIABLE"); break;
421
		    case SLC_DEFAULT:
422
			fprintf(NetTrace, " DEFAULT"); break;
423
		    }
424
		    fprintf(NetTrace, "%s%s%s",
425
			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
426
			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
427
			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
428
		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
429
						SLC_FLUSHOUT| SLC_LEVELBITS))
430
			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
431
		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
432
		    if ((pointer[i+SLC_VALUE] == IAC) &&
433
			(pointer[i+SLC_VALUE+1] == IAC))
434
				i++;
435
		}
436
		for (; i < length; i++)
437
		    fprintf(NetTrace, " ?%d?", pointer[i]);
438
		break;
439
440
	    case LM_MODE:
441
		fprintf(NetTrace, "MODE ");
442
		if (length < 3) {
443
		    fprintf(NetTrace, "(no mode??\?)");
444
		    break;
445
		}
446
		{
447
		    char tbuf[64];
448
		    snprintf(tbuf, sizeof(tbuf),
449
			     "%s%s%s%s%s",
450
			     pointer[2]&MODE_EDIT ? "|EDIT" : "",
451
			     pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
452
			     pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
453
			     pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
454
			     pointer[2]&MODE_ACK ? "|ACK" : "");
455
		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
456
		}
457
		if (pointer[2]&~(MODE_MASK))
458
		    fprintf(NetTrace, " (0x%x)", pointer[2]);
459
		for (i = 3; i < length; i++)
460
		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
461
		break;
462
	    default:
463
		fprintf(NetTrace, "%d (unknown)", pointer[1]);
464
		for (i = 2; i < length; i++)
465
		    fprintf(NetTrace, " %d", pointer[i]);
466
	    }
467
	    break;
468
469
	case TELOPT_STATUS: {
470
	    char *cp;
471
	    int j, k;
472
473
	    fprintf(NetTrace, "STATUS");
474
475
	    switch (pointer[1]) {
476
	    default:
477
		if (pointer[1] == TELQUAL_SEND)
478
		    fprintf(NetTrace, " SEND");
479
		else
480
		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
481
		for (i = 2; i < length; i++)
482
		    fprintf(NetTrace, " ?%d?", pointer[i]);
483
		break;
484
	    case TELQUAL_IS:
485
		if (--want_status_response < 0)
486
		    want_status_response = 0;
487
		if (NetTrace == stdout)
488
		    fprintf(NetTrace, " IS\r\n");
489
		else
490
		    fprintf(NetTrace, " IS\n");
491
492
		for (i = 2; i < length; i++) {
493
		    switch(pointer[i]) {
494
		    case DO:	cp = "DO"; goto common2;
495
		    case DONT:	cp = "DONT"; goto common2;
496
		    case WILL:	cp = "WILL"; goto common2;
497
		    case WONT:	cp = "WONT"; goto common2;
498
		    common2:
499
			i++;
500
			if (TELOPT_OK(pointer[i]))
501
			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
502
			else
503
			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
504
505
			if (NetTrace == stdout)
506
			    fprintf(NetTrace, "\r\n");
507
			else
508
			    fprintf(NetTrace, "\n");
509
			break;
510
511
		    case SB:
512
			fprintf(NetTrace, " SB ");
513
			i++;
514
			j = k = i;
515
			while (j < length) {
516
			    if (pointer[j] == SE) {
517
				if (j+1 == length)
518
				    break;
519
				if (pointer[j+1] == SE)
520
				    j++;
521
				else
522
				    break;
523
			    }
524
			    pointer[k++] = pointer[j++];
525
			}
526
			printsub(0, &pointer[i], k - i);
527
			if (i < length) {
528
			    fprintf(NetTrace, " SE");
529
			    i = j;
530
			} else
531
			    i = j - 1;
532
533
			if (NetTrace == stdout)
534
			    fprintf(NetTrace, "\r\n");
535
			else
536
			    fprintf(NetTrace, "\n");
537
538
			break;
539
540
		    default:
541
			fprintf(NetTrace, " %d", pointer[i]);
542
			break;
543
		    }
544
		}
545
		break;
546
	    }
547
	    break;
548
	  }
549
550
	case TELOPT_XDISPLOC:
551
	    fprintf(NetTrace, "X-DISPLAY-LOCATION ");
552
	    switch (pointer[1]) {
553
	    case TELQUAL_IS:
554
		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
555
		break;
556
	    case TELQUAL_SEND:
557
		fprintf(NetTrace, "SEND");
558
		break;
559
	    default:
560
		fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
561
				pointer[1], pointer[1]);
562
	    }
563
	    break;
564
565
	case TELOPT_NEW_ENVIRON:
566
	    fprintf(NetTrace, "NEW-ENVIRON ");
567
	    switch (pointer[1]) {
568
	    case TELQUAL_IS:
569
		fprintf(NetTrace, "IS ");
570
		goto env_common;
571
	    case TELQUAL_SEND:
572
		fprintf(NetTrace, "SEND ");
573
		goto env_common;
574
	    case TELQUAL_INFO:
575
		fprintf(NetTrace, "INFO ");
576
	    env_common:
577
		{
578
		    int quote = 0;
579
		    for (i = 2; i < length; i++ ) {
580
			switch (pointer[i]) {
581
			case NEW_ENV_VALUE:
582
			    fprintf(NetTrace, "%sVALUE ", quote ? "\" " : "");
583
			    quote = 0;
584
			    break;
585
586
			case NEW_ENV_VAR:
587
			    fprintf(NetTrace, "%sVAR ", quote ? "\" " : "");
588
			    quote = 0;
589
			    break;
590
591
			case ENV_ESC:
592
			    fprintf(NetTrace, "%sESC ", quote ? "\" " : "");
593
			    quote = 0;
594
			    break;
595
596
			case ENV_USERVAR:
597
			    fprintf(NetTrace, "%sUSERVAR ", quote ? "\" " : "");
598
			    quote = 0;
599
			    break;
600
601
			default:
602
			    if (isprint((unsigned char)pointer[i]) &&
603
				pointer[i] != '"') {
604
				    fprintf(NetTrace, "%s%c",
605
					quote ? "" : "\"", pointer[i]);
606
				    quote = 1;
607
			    } else {
608
				    fprintf(NetTrace, "%s%03o ",
609
					quote ? "\" " : "", pointer[i]);
610
				    quote = 0;
611
			    }
612
			    break;
613
			}
614
		    }
615
		    if (quote)
616
			putc('"', NetTrace);
617
		    break;
618
		}
619
	    }
620
	    break;
621
622
	default:
623
	    if (TELOPT_OK(pointer[0]))
624
		fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
625
	    else
626
		fprintf(NetTrace, "%d (unknown)", pointer[0]);
627
	    for (i = 1; i < length; i++)
628
		fprintf(NetTrace, " %d", pointer[i]);
629
	    break;
630
	}
631
	if (direction) {
632
	    if (NetTrace == stdout)
633
		fprintf(NetTrace, "\r\n");
634
	    else
635
		fprintf(NetTrace, "\n");
636
	}
637
	if (NetTrace == stdout)
638
	    fflush(NetTrace);
639
    }
640
}
641
642
/* EmptyTerminal - called to make sure that the terminal buffer is empty.
643
 *			Note that we consider the buffer to run all the
644
 *			way to the kernel (thus the poll).
645
 */
646
647
void
648
EmptyTerminal(void)
649
{
650
    struct pollfd pfd[1];
651
652
    pfd[0].fd = tout;
653
    pfd[0].events = POLLOUT;
654
655
    if (TTYBYTES() == 0) {
656
	(void) poll(pfd, 1, INFTIM); /* wait for TTLOWAT */
657
    } else {
658
	while (TTYBYTES()) {
659
	    (void) ttyflush(0);
660
	    (void) poll(pfd, 1, INFTIM); /* wait for TTLOWAT */
661
	}
662
    }
663
}
664
665
void
666
SetForExit(void)
667
{
668
    setconnmode(0);
669
    do {
670
	(void)telrcv();			/* Process any incoming data */
671
	EmptyTerminal();
672
    } while (ring_full_count(&netiring));	/* While there is any */
673
    setcommandmode();
674
    fflush(stdout);
675
    fflush(stderr);
676
    setconnmode(0);
677
    EmptyTerminal();			/* Flush the path to the tty */
678
    setcommandmode();
679
}
680
681
void
682
Exit(int returnCode)
683
{
684
    SetForExit();
685
    exit(returnCode);
686
}
687
688
void
689
ExitString(char *string, int returnCode)
690
{
691
    SetForExit();
692
    fwrite(string, 1, strlen(string), stderr);
693
    exit(returnCode);
694
}