Fix up the code that deals with the
[unix-history] / usr / src / usr.bin / telnet / utilities.c
CommitLineData
897ce52e
KB
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
4a8a7128 5 * %sccs.include.redist.c%
897ce52e
KB
6 */
7
8#ifndef lint
8832c633 9static char sccsid[] = "@(#)utilities.c 5.5 (Berkeley) %G%";
897ce52e
KB
10#endif /* not lint */
11
788caa15 12#define TELOPTS
6055a9f6 13#define TELCMDS
15d31b7e 14#define SLC_NAMES
788caa15 15#include <arpa/telnet.h>
115a5494 16#include <sys/types.h>
4a8a7128 17#include <sys/time.h>
788caa15
GM
18
19#include <ctype.h>
20
2dde2af0
GM
21#include "general.h"
22
6d0564c5
GM
23#include "fdset.h"
24
115a5494
GM
25#include "ring.h"
26
cf9305fa
GM
27#include "defines.h"
28
788caa15
GM
29#include "externs.h"
30
31FILE *NetTrace = 0; /* Not in bss, since needs to stay */
6055a9f6 32int prettydump;
788caa15
GM
33
34/*
35 * upcase()
36 *
37 * Upcase (in place) the argument.
38 */
39
15d31b7e 40 void
788caa15 41upcase(argument)
15d31b7e 42 register char *argument;
788caa15
GM
43{
44 register int c;
45
46 while ((c = *argument) != 0) {
47 if (islower(c)) {
48 *argument = toupper(c);
49 }
50 argument++;
51 }
52}
53
54/*
55 * SetSockOpt()
56 *
57 * Compensate for differences in 4.2 and 4.3 systems.
58 */
59
15d31b7e 60 int
788caa15 61SetSockOpt(fd, level, option, yesno)
15d31b7e 62 int fd, level, option, yesno;
788caa15
GM
63{
64#ifndef NOT43
65 return setsockopt(fd, level, option,
66 (char *)&yesno, sizeof yesno);
67#else /* NOT43 */
68 if (yesno == 0) { /* Can't do that in 4.2! */
69 fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
70 option);
71 return -1;
72 }
73 return setsockopt(fd, level, option, 0, 0);
74#endif /* NOT43 */
75}
76\f
77/*
78 * The following are routines used to print out debugging information.
79 */
80
7daa10bf 81unsigned char NetTraceFile[256] = "(standard output)";
6055a9f6 82
15d31b7e 83 void
6055a9f6 84SetNetTrace(file)
15d31b7e 85 register char *file;
6055a9f6
PB
86{
87 if (NetTrace && NetTrace != stdout)
88 fclose(NetTrace);
89 if (file && (strcmp(file, "-") != 0)) {
90 NetTrace = fopen(file, "w");
91 if (NetTrace) {
15d31b7e 92 strcpy((char *)NetTraceFile, file);
6055a9f6
PB
93 return;
94 }
95 fprintf(stderr, "Cannot open %s.\n", file);
96 }
97 NetTrace = stdout;
15d31b7e 98 strcpy((char *)NetTraceFile, "(standard output)");
6055a9f6 99}
788caa15 100
15d31b7e 101 void
788caa15 102Dump(direction, buffer, length)
15d31b7e
DB
103 char direction;
104 unsigned char *buffer;
105 int length;
788caa15
GM
106{
107# define BYTES_PER_LINE 32
108# define min(x,y) ((x<y)? x:y)
15d31b7e 109 unsigned char *pThis;
788caa15 110 int offset;
6055a9f6 111 extern pettydump;
788caa15
GM
112
113 offset = 0;
114
115 while (length) {
116 /* print one line */
117 fprintf(NetTrace, "%c 0x%x\t", direction, offset);
118 pThis = buffer;
6055a9f6 119 if (prettydump) {
6570c863 120 buffer = buffer + min(length, BYTES_PER_LINE/2);
6055a9f6
PB
121 while (pThis < buffer) {
122 fprintf(NetTrace, "%c%.2x",
123 (((*pThis)&0xff) == 0xff) ? '*' : ' ',
124 (*pThis)&0xff);
125 pThis++;
126 }
6570c863
PB
127 length -= BYTES_PER_LINE/2;
128 offset += BYTES_PER_LINE/2;
6055a9f6 129 } else {
6570c863 130 buffer = buffer + min(length, BYTES_PER_LINE);
6055a9f6
PB
131 while (pThis < buffer) {
132 fprintf(NetTrace, "%.2x", (*pThis)&0xff);
133 pThis++;
134 }
6570c863
PB
135 length -= BYTES_PER_LINE;
136 offset += BYTES_PER_LINE;
788caa15 137 }
32d22a68 138 if (NetTrace == stdout) {
32d22a68 139 fprintf(NetTrace, "\r\n");
6b5250cf
GM
140 } else {
141 fprintf(NetTrace, "\n");
32d22a68 142 }
788caa15 143 if (length < 0) {
e3f3aa94 144 fflush(NetTrace);
788caa15
GM
145 return;
146 }
147 /* find next unique line */
148 }
e3f3aa94 149 fflush(NetTrace);
788caa15
GM
150}
151
152
15d31b7e
DB
153 void
154printoption(direction, cmd, option)
155 char *direction;
156 int cmd, option;
788caa15
GM
157{
158 if (!showoptions)
159 return;
15d31b7e
DB
160 if (cmd == IAC) {
161 if (TELCMD_OK(option))
162 fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
163 else
164 fprintf(NetTrace, "%s IAC %d", direction, option);
165 } else {
166 register char *fmt;
167 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
168 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
169 if (fmt) {
170 fprintf(NetTrace, "%s %s ", direction, fmt);
171 if (TELOPT_OK(option))
172 fprintf(NetTrace, "%s", TELOPT(option));
173 else if (option == TELOPT_EXOPL)
174 fprintf(NetTrace, "EXOPL");
175 else
176 fprintf(NetTrace, "%d", option);
177 } else
178 fprintf(NetTrace, "%s %d %d", direction, cmd, option);
179 }
6055a9f6 180 if (NetTrace == stdout)
32d22a68 181 fprintf(NetTrace, "\r\n");
6055a9f6 182 else
32d22a68 183 fprintf(NetTrace, "\n");
32d22a68 184 return;
788caa15
GM
185}
186
15d31b7e 187 void
6055a9f6
PB
188optionstatus()
189{
190 register int i;
191 extern char will_wont_resp[], do_dont_resp[];
192
193 for (i = 0; i < 256; i++) {
194 if (do_dont_resp[i]) {
195 if (TELOPT_OK(i))
196 printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
197 else if (TELCMD_OK(i))
198 printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
199 else
200 printf("resp DO_DONT %d: %d\n", i,
201 do_dont_resp[i]);
202 if (my_want_state_is_do(i)) {
203 if (TELOPT_OK(i))
204 printf("want DO %s\n", TELOPT(i));
205 else if (TELCMD_OK(i))
206 printf("want DO %s\n", TELCMD(i));
207 else
208 printf("want DO %d\n", i);
209 } else {
210 if (TELOPT_OK(i))
211 printf("want DONT %s\n", TELOPT(i));
212 else if (TELCMD_OK(i))
213 printf("want DONT %s\n", TELCMD(i));
214 else
215 printf("want DONT %d\n", i);
216 }
217 } else {
218 if (my_state_is_do(i)) {
219 if (TELOPT_OK(i))
220 printf(" DO %s\n", TELOPT(i));
221 else if (TELCMD_OK(i))
222 printf(" DO %s\n", TELCMD(i));
223 else
224 printf(" DO %d\n", i);
225 }
226 }
227 if (will_wont_resp[i]) {
228 if (TELOPT_OK(i))
229 printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
230 else if (TELCMD_OK(i))
231 printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
232 else
233 printf("resp WILL_WONT %d: %d\n",
234 i, will_wont_resp[i]);
235 if (my_want_state_is_will(i)) {
236 if (TELOPT_OK(i))
237 printf("want WILL %s\n", TELOPT(i));
238 else if (TELCMD_OK(i))
239 printf("want WILL %s\n", TELCMD(i));
240 else
241 printf("want WILL %d\n", i);
242 } else {
243 if (TELOPT_OK(i))
244 printf("want WONT %s\n", TELOPT(i));
245 else if (TELCMD_OK(i))
246 printf("want WONT %s\n", TELCMD(i));
247 else
248 printf("want WONT %d\n", i);
249 }
250 } else {
251 if (my_state_is_will(i)) {
252 if (TELOPT_OK(i))
253 printf(" WILL %s\n", TELOPT(i));
254 else if (TELCMD_OK(i))
255 printf(" WILL %s\n", TELCMD(i));
256 else
257 printf(" WILL %d\n", i);
258 }
259 }
260 }
261
262}
263
15d31b7e 264 void
788caa15 265printsub(direction, pointer, length)
15d31b7e
DB
266 char direction; /* '<' or '>' */
267 unsigned char *pointer; /* where suboption data sits */
268 int length; /* length of suboption data */
788caa15 269{
6055a9f6 270 register int i;
b7c8f459 271 char buf[512];
15d31b7e 272 extern int want_status_response;
6055a9f6 273
15d31b7e
DB
274 if (showoptions || direction == 0 ||
275 (want_status_response && (pointer[0] == TELOPT_STATUS))) {
6570c863 276 if (direction) {
15d31b7e
DB
277 fprintf(NetTrace, "%s IAC SB ",
278 (direction == '<')? "RCVD":"SENT");
6570c863
PB
279 if (length >= 3) {
280 register int j;
281
282 i = pointer[length-2];
283 j = pointer[length-1];
284
285 if (i != IAC || j != SE) {
286 fprintf(NetTrace, "(terminated by ");
287 if (TELOPT_OK(i))
288 fprintf(NetTrace, "%s ", TELOPT(i));
289 else if (TELCMD_OK(i))
290 fprintf(NetTrace, "%s ", TELCMD(i));
291 else
292 fprintf(NetTrace, "%d ", i);
293 if (TELOPT_OK(j))
294 fprintf(NetTrace, "%s", TELOPT(j));
295 else if (TELCMD_OK(j))
296 fprintf(NetTrace, "%s", TELCMD(j));
297 else
298 fprintf(NetTrace, "%d", j);
299 fprintf(NetTrace, ", not IAC SE!) ");
300 }
6055a9f6 301 }
6570c863 302 length -= 2;
6055a9f6 303 }
6055a9f6
PB
304 if (length < 1) {
305 fprintf(NetTrace, "(Empty suboption???)");
306 return;
307 }
788caa15
GM
308 switch (pointer[0]) {
309 case TELOPT_TTYPE:
6055a9f6 310 fprintf(NetTrace, "TERMINAL-TYPE ");
788caa15
GM
311 switch (pointer[1]) {
312 case TELQUAL_IS:
4a8a7128 313 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
788caa15
GM
314 break;
315 case TELQUAL_SEND:
6055a9f6 316 fprintf(NetTrace, "SEND");
788caa15
GM
317 break;
318 default:
319 fprintf(NetTrace,
6055a9f6 320 "- unknown qualifier %d (0x%x).",
80a47e22 321 pointer[1], pointer[1]);
788caa15
GM
322 }
323 break;
6055a9f6
PB
324 case TELOPT_TSPEED:
325 fprintf(NetTrace, "TERMINAL-SPEED");
326 if (length < 2) {
327 fprintf(NetTrace, " (empty suboption???)");
328 break;
329 }
330 switch (pointer[1]) {
6570c863 331 case TELQUAL_IS:
6055a9f6 332 fprintf(NetTrace, " IS ");
4a8a7128 333 fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
6055a9f6
PB
334 break;
335 default:
336 if (pointer[1] == 1)
337 fprintf(NetTrace, " SEND");
338 else
4a8a7128 339 fprintf(NetTrace, " %d (unknown)", pointer[1]);
6055a9f6
PB
340 for (i = 2; i < length; i++)
341 fprintf(NetTrace, " ?%d?", pointer[i]);
342 break;
343 }
344 break;
345
346 case TELOPT_LFLOW:
347 fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
348 if (length < 2) {
349 fprintf(NetTrace, " (empty suboption???)");
350 break;
351 }
352 switch (pointer[1]) {
353 case 0:
354 fprintf(NetTrace, " OFF"); break;
355 case 1:
356 fprintf(NetTrace, " ON"); break;
357 default:
4a8a7128 358 fprintf(NetTrace, " %d (unknown)", pointer[1]);
6055a9f6
PB
359 }
360 for (i = 2; i < length; i++)
361 fprintf(NetTrace, " ?%d?", pointer[i]);
362 break;
363
364 case TELOPT_NAWS:
365 fprintf(NetTrace, "NAWS");
366 if (length < 2) {
367 fprintf(NetTrace, " (empty suboption???)");
368 break;
369 }
370 if (length == 2) {
371 fprintf(NetTrace, " ?%d?", pointer[1]);
372 break;
373 }
374 fprintf(NetTrace, " %d %d (%d)",
375 pointer[1], pointer[2],
4a8a7128 376 (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
6055a9f6
PB
377 if (length == 4) {
378 fprintf(NetTrace, " ?%d?", pointer[3]);
379 break;
380 }
381 fprintf(NetTrace, " %d %d (%d)",
382 pointer[3], pointer[4],
4a8a7128 383 (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
6055a9f6
PB
384 for (i = 5; i < length; i++)
385 fprintf(NetTrace, " ?%d?", pointer[i]);
386 break;
387
8832c633 388#if defined(AUTHENTICATION)
4d09a147 389 case TELOPT_AUTHENTICATION:
15d31b7e
DB
390 fprintf(NetTrace, "AUTHENTICATION");
391 if (length < 2) {
392 fprintf(NetTrace, " (empty suboption???)");
393 break;
394 }
4d09a147 395 switch (pointer[1]) {
15d31b7e 396 case TELQUAL_REPLY:
4d09a147 397 case TELQUAL_IS:
15d31b7e
DB
398 fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
399 "IS" : "REPLY");
400 if (AUTHTYPE_NAME_OK(pointer[2]))
401 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
402 else
403 fprintf(NetTrace, "%d ", pointer[2]);
404 if (length < 3) {
405 fprintf(NetTrace, "(partial suboption???)");
406 break;
407 }
408 fprintf(NetTrace, "%s|%s",
b7c8f459 409 ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
15d31b7e 410 "CLIENT" : "SERVER",
b7c8f459 411 ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
15d31b7e
DB
412 "MUTUAL" : "ONE-WAY");
413
414 auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
415 fprintf(NetTrace, "%s", buf);
416 break;
4d09a147 417
15d31b7e
DB
418 case TELQUAL_SEND:
419 i = 2;
420 fprintf(NetTrace, " SEND ");
421 while (i < length) {
422 if (AUTHTYPE_NAME_OK(pointer[i]))
423 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
424 else
425 fprintf(NetTrace, "%d ", pointer[i]);
426 if (++i >= length) {
427 fprintf(NetTrace, "(partial suboption???)");
4d09a147 428 break;
15d31b7e
DB
429 }
430 fprintf(NetTrace, "%s|%s ",
b7c8f459 431 ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
15d31b7e 432 "CLIENT" : "SERVER",
b7c8f459 433 ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
15d31b7e
DB
434 "MUTUAL" : "ONE-WAY");
435 ++i;
4d09a147 436 }
15d31b7e 437 break;
4d09a147 438
b7c8f459
DB
439 case TELQUAL_NAME:
440 i = 2;
441 fprintf(NetTrace, " NAME \"");
442 while (i < length)
443 putc(pointer[i++], NetTrace);
444 putc('"', NetTrace);
445 break;
446
15d31b7e
DB
447 default:
448 for (i = 2; i < length; i++)
449 fprintf(NetTrace, " ?%d?", pointer[i]);
450 break;
4d09a147 451 }
15d31b7e
DB
452 break;
453#endif
454
8832c633 455#if defined(ENCRYPTION)
15d31b7e
DB
456 case TELOPT_ENCRYPT:
457 fprintf(NetTrace, "ENCRYPT");
458 if (length < 2) {
459 fprintf(NetTrace, " (empty suboption???)");
460 break;
461 }
462 switch (pointer[1]) {
463 case ENCRYPT_START:
464 fprintf(NetTrace, " START");
465 break;
466
467 case ENCRYPT_END:
468 fprintf(NetTrace, " END");
469 break;
470
471 case ENCRYPT_REQSTART:
472 fprintf(NetTrace, " REQUEST-START");
473 break;
474
475 case ENCRYPT_REQEND:
476 fprintf(NetTrace, " REQUEST-END");
477 break;
478
479 case ENCRYPT_IS:
480 case ENCRYPT_REPLY:
481 fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
482 "IS" : "REPLY");
483 if (length < 3) {
484 fprintf(NetTrace, " (partial suboption???)");
485 break;
486 }
487 if (ENCTYPE_NAME_OK(pointer[2]))
488 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
489 else
490 fprintf(NetTrace, " %d (unknown)", pointer[2]);
491
492 encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
493 fprintf(NetTrace, "%s", buf);
494 break;
495
496 case ENCRYPT_SUPPORT:
497 i = 2;
498 fprintf(NetTrace, " SUPPORT ");
499 while (i < length) {
500 if (ENCTYPE_NAME_OK(pointer[i]))
501 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
502 else
503 fprintf(NetTrace, "%d ", pointer[i]);
504 i++;
505 }
4d09a147
KF
506 break;
507
b7c8f459
DB
508 case ENCRYPT_ENC_KEYID:
509 fprintf(NetTrace, " ENC_KEYID ");
510 goto encommon;
511
512 case ENCRYPT_DEC_KEYID:
513 fprintf(NetTrace, " DEC_KEYID ");
514 goto encommon;
515
4d09a147 516 default:
b7c8f459
DB
517 fprintf(NetTrace, " %d (unknown)", pointer[1]);
518 encommon:
15d31b7e
DB
519 for (i = 2; i < length; i++)
520 fprintf(NetTrace, " %d", pointer[i]);
521 break;
4d09a147
KF
522 }
523 break;
15d31b7e 524#endif
4d09a147 525
6055a9f6
PB
526 case TELOPT_LINEMODE:
527 fprintf(NetTrace, "LINEMODE ");
528 if (length < 2) {
529 fprintf(NetTrace, " (empty suboption???)");
530 break;
531 }
532 switch (pointer[1]) {
533 case WILL:
534 fprintf(NetTrace, "WILL ");
535 goto common;
536 case WONT:
537 fprintf(NetTrace, "WONT ");
538 goto common;
539 case DO:
540 fprintf(NetTrace, "DO ");
541 goto common;
542 case DONT:
543 fprintf(NetTrace, "DONT ");
544 common:
545 if (length < 3) {
546 fprintf(NetTrace, "(no option???)");
547 break;
548 }
549 switch (pointer[2]) {
550 case LM_FORWARDMASK:
551 fprintf(NetTrace, "Forward Mask");
552 for (i = 3; i < length; i++)
553 fprintf(NetTrace, " %x", pointer[i]);
554 break;
555 default:
556 fprintf(NetTrace, "%d (unknown)", pointer[2]);
557 for (i = 3; i < length; i++)
558 fprintf(NetTrace, " %d", pointer[i]);
559 break;
560 }
561 break;
562
563 case LM_SLC:
564 fprintf(NetTrace, "SLC");
565 for (i = 2; i < length - 2; i += 3) {
15d31b7e
DB
566 if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
567 fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
6055a9f6
PB
568 else
569 fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
570 switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
571 case SLC_NOSUPPORT:
572 fprintf(NetTrace, " NOSUPPORT"); break;
573 case SLC_CANTCHANGE:
574 fprintf(NetTrace, " CANTCHANGE"); break;
575 case SLC_VARIABLE:
576 fprintf(NetTrace, " VARIABLE"); break;
577 case SLC_DEFAULT:
578 fprintf(NetTrace, " DEFAULT"); break;
579 }
580 fprintf(NetTrace, "%s%s%s",
581 pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
582 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
583 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
584 if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
585 SLC_FLUSHOUT| SLC_LEVELBITS))
586 fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
587 fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
4a8a7128
PB
588 if ((pointer[i+SLC_VALUE] == IAC) &&
589 (pointer[i+SLC_VALUE+1] == IAC))
590 i++;
6055a9f6
PB
591 }
592 for (; i < length; i++)
593 fprintf(NetTrace, " ?%d?", pointer[i]);
594 break;
595
596 case LM_MODE:
597 fprintf(NetTrace, "MODE ");
598 if (length < 3) {
599 fprintf(NetTrace, "(no mode???)");
600 break;
601 }
602 {
4a8a7128
PB
603 char tbuf[64];
604 sprintf(tbuf, "%s%s%s%s%s",
6055a9f6
PB
605 pointer[2]&MODE_EDIT ? "|EDIT" : "",
606 pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
4a8a7128
PB
607 pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
608 pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
6055a9f6
PB
609 pointer[2]&MODE_ACK ? "|ACK" : "");
610 fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
611 }
15d31b7e 612 if (pointer[2]&~(MODE_MASK))
6055a9f6
PB
613 fprintf(NetTrace, " (0x%x)", pointer[2]);
614 for (i = 3; i < length; i++)
615 fprintf(NetTrace, " ?0x%x?", pointer[i]);
616 break;
617 default:
618 fprintf(NetTrace, "%d (unknown)", pointer[1]);
619 for (i = 2; i < length; i++)
620 fprintf(NetTrace, " %d", pointer[i]);
621 }
622 break;
623
6570c863
PB
624 case TELOPT_STATUS: {
625 register char *cp;
626 register int j, k;
627
628 fprintf(NetTrace, "STATUS");
629
630 switch (pointer[1]) {
631 default:
632 if (pointer[1] == TELQUAL_SEND)
633 fprintf(NetTrace, " SEND");
634 else
4a8a7128 635 fprintf(NetTrace, " %d (unknown)", pointer[1]);
6570c863
PB
636 for (i = 2; i < length; i++)
637 fprintf(NetTrace, " ?%d?", pointer[i]);
638 break;
639 case TELQUAL_IS:
15d31b7e
DB
640 if (--want_status_response < 0)
641 want_status_response = 0;
6570c863
PB
642 if (NetTrace == stdout)
643 fprintf(NetTrace, " IS\r\n");
644 else
645 fprintf(NetTrace, " IS\n");
646
647 for (i = 2; i < length; i++) {
648 switch(pointer[i]) {
649 case DO: cp = "DO"; goto common2;
650 case DONT: cp = "DONT"; goto common2;
651 case WILL: cp = "WILL"; goto common2;
652 case WONT: cp = "WONT"; goto common2;
653 common2:
654 i++;
4a8a7128 655 if (TELOPT_OK((int)pointer[i]))
6570c863
PB
656 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
657 else
658 fprintf(NetTrace, " %s %d", cp, pointer[i]);
659
660 if (NetTrace == stdout)
661 fprintf(NetTrace, "\r\n");
662 else
663 fprintf(NetTrace, "\n");
664 break;
665
666 case SB:
667 fprintf(NetTrace, " SB ");
668 i++;
669 j = k = i;
670 while (j < length) {
671 if (pointer[j] == SE) {
672 if (j+1 == length)
673 break;
674 if (pointer[j+1] == SE)
675 j++;
676 else
677 break;
678 }
679 pointer[k++] = pointer[j++];
680 }
681 printsub(0, &pointer[i], k - i);
682 if (i < length) {
683 fprintf(NetTrace, " SE");
684 i = j;
685 } else
686 i = j - 1;
687
688 if (NetTrace == stdout)
689 fprintf(NetTrace, "\r\n");
690 else
691 fprintf(NetTrace, "\n");
692
693 break;
694
695 default:
696 fprintf(NetTrace, " %d", pointer[i]);
697 break;
698 }
699 }
700 break;
701 }
702 break;
703 }
704
4a8a7128
PB
705 case TELOPT_XDISPLOC:
706 fprintf(NetTrace, "X-DISPLAY-LOCATION ");
707 switch (pointer[1]) {
708 case TELQUAL_IS:
709 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
710 break;
711 case TELQUAL_SEND:
712 fprintf(NetTrace, "SEND");
713 break;
714 default:
715 fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
716 pointer[1], pointer[1]);
717 }
718 break;
719
720 case TELOPT_ENVIRON:
721 fprintf(NetTrace, "ENVIRON ");
722 switch (pointer[1]) {
723 case TELQUAL_IS:
724 fprintf(NetTrace, "IS ");
725 goto env_common;
726 case TELQUAL_SEND:
727 fprintf(NetTrace, "SEND ");
728 goto env_common;
729 case TELQUAL_INFO:
730 fprintf(NetTrace, "INFO ");
731 env_common:
732 {
733 register int noquote = 2;
734 for (i = 2; i < length; i++ ) {
735 switch (pointer[i]) {
736 case ENV_VAR:
737 if (pointer[1] == TELQUAL_SEND)
738 goto def_case;
739 fprintf(NetTrace, "\" VAR " + noquote);
740 noquote = 2;
741 break;
742
743 case ENV_VALUE:
744 fprintf(NetTrace, "\" VALUE " + noquote);
745 noquote = 2;
746 break;
747
748 case ENV_ESC:
749 fprintf(NetTrace, "\" ESC " + noquote);
750 noquote = 2;
751 break;
752
8832c633
DB
753 case ENV_USERVAR:
754 if (pointer[1] == TELQUAL_SEND)
755 goto def_case;
756 fprintf(NetTrace, "\" USERVAR " + noquote);
757 noquote = 2;
758 break;
759
4a8a7128
PB
760 default:
761 def_case:
762 if (isprint(pointer[i]) && pointer[i] != '"') {
763 if (noquote) {
764 putc('"', NetTrace);
765 noquote = 0;
766 }
767 putc(pointer[i], NetTrace);
768 } else {
769 fprintf(NetTrace, "\" %03o " + noquote,
770 pointer[i]);
771 noquote = 2;
772 }
773 break;
774 }
775 }
776 if (!noquote)
777 putc('"', NetTrace);
778 break;
779 }
780 }
781 break;
782
788caa15 783 default:
15d31b7e
DB
784 if (TELOPT_OK(pointer[0]))
785 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
786 else
6e549b07 787 fprintf(NetTrace, "%d (unknown)", pointer[0]);
15d31b7e 788 for (i = 1; i < length; i++)
6055a9f6
PB
789 fprintf(NetTrace, " %d", pointer[i]);
790 break;
788caa15 791 }
6570c863
PB
792 if (direction) {
793 if (NetTrace == stdout)
794 fprintf(NetTrace, "\r\n");
795 else
796 fprintf(NetTrace, "\n");
797 }
788caa15
GM
798 }
799}
cf9305fa
GM
800
801/* EmptyTerminal - called to make sure that the terminal buffer is empty.
802 * Note that we consider the buffer to run all the
803 * way to the kernel (thus the select).
804 */
805
15d31b7e 806 void
cf9305fa
GM
807EmptyTerminal()
808{
809#if defined(unix)
810 fd_set o;
811
812 FD_ZERO(&o);
813#endif /* defined(unix) */
814
815 if (TTYBYTES() == 0) {
816#if defined(unix)
817 FD_SET(tout, &o);
818 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
819 (struct timeval *) 0); /* wait for TTLOWAT */
820#endif /* defined(unix) */
821 } else {
822 while (TTYBYTES()) {
4a8a7128 823 (void) ttyflush(0);
cf9305fa
GM
824#if defined(unix)
825 FD_SET(tout, &o);
826 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
827 (struct timeval *) 0); /* wait for TTLOWAT */
828#endif /* defined(unix) */
829 }
830 }
831}
832
15d31b7e 833 void
cf9305fa
GM
834SetForExit()
835{
6055a9f6 836 setconnmode(0);
cf9305fa
GM
837#if defined(TN3270)
838 if (In3270) {
839 Finish3270();
840 }
6da40c06
GM
841#else /* defined(TN3270) */
842 do {
4a8a7128 843 (void)telrcv(); /* Process any incoming data */
6da40c06
GM
844 EmptyTerminal();
845 } while (ring_full_count(&netiring)); /* While there is any */
cf9305fa
GM
846#endif /* defined(TN3270) */
847 setcommandmode();
848 fflush(stdout);
849 fflush(stderr);
850#if defined(TN3270)
851 if (In3270) {
852 StopScreen(1);
853 }
854#endif /* defined(TN3270) */
6055a9f6 855 setconnmode(0);
cf9305fa
GM
856 EmptyTerminal(); /* Flush the path to the tty */
857 setcommandmode();
858}
859
15d31b7e 860 void
cf9305fa 861Exit(returnCode)
15d31b7e 862 int returnCode;
cf9305fa
GM
863{
864 SetForExit();
865 exit(returnCode);
866}
867
15d31b7e 868 void
cf9305fa 869ExitString(string, returnCode)
15d31b7e
DB
870 char *string;
871 int returnCode;
cf9305fa
GM
872{
873 SetForExit();
874 fwrite(string, 1, strlen(string), stderr);
875 exit(returnCode);
876}