Fix gcc2 warnings.
[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
3c2dafdd 9static char sccsid[] = "@(#)utilities.c 5.7 (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]) {
11e442e1 353 case LFLOW_OFF:
6055a9f6 354 fprintf(NetTrace, " OFF"); break;
11e442e1 355 case LFLOW_ON:
6055a9f6 356 fprintf(NetTrace, " ON"); break;
11e442e1
DB
357 case LFLOW_RESTART_ANY:
358 fprintf(NetTrace, " RESTART-ANY"); break;
359 case LFLOW_RESTART_XON:
360 fprintf(NetTrace, " RESTART-XON"); break;
6055a9f6 361 default:
4a8a7128 362 fprintf(NetTrace, " %d (unknown)", pointer[1]);
6055a9f6
PB
363 }
364 for (i = 2; i < length; i++)
365 fprintf(NetTrace, " ?%d?", pointer[i]);
366 break;
367
368 case TELOPT_NAWS:
369 fprintf(NetTrace, "NAWS");
370 if (length < 2) {
371 fprintf(NetTrace, " (empty suboption???)");
372 break;
373 }
374 if (length == 2) {
375 fprintf(NetTrace, " ?%d?", pointer[1]);
376 break;
377 }
378 fprintf(NetTrace, " %d %d (%d)",
379 pointer[1], pointer[2],
4a8a7128 380 (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
6055a9f6
PB
381 if (length == 4) {
382 fprintf(NetTrace, " ?%d?", pointer[3]);
383 break;
384 }
385 fprintf(NetTrace, " %d %d (%d)",
386 pointer[3], pointer[4],
4a8a7128 387 (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
6055a9f6
PB
388 for (i = 5; i < length; i++)
389 fprintf(NetTrace, " ?%d?", pointer[i]);
390 break;
391
8832c633 392#if defined(AUTHENTICATION)
4d09a147 393 case TELOPT_AUTHENTICATION:
15d31b7e
DB
394 fprintf(NetTrace, "AUTHENTICATION");
395 if (length < 2) {
396 fprintf(NetTrace, " (empty suboption???)");
397 break;
398 }
4d09a147 399 switch (pointer[1]) {
15d31b7e 400 case TELQUAL_REPLY:
4d09a147 401 case TELQUAL_IS:
15d31b7e
DB
402 fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
403 "IS" : "REPLY");
404 if (AUTHTYPE_NAME_OK(pointer[2]))
405 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
406 else
407 fprintf(NetTrace, "%d ", pointer[2]);
408 if (length < 3) {
409 fprintf(NetTrace, "(partial suboption???)");
410 break;
411 }
412 fprintf(NetTrace, "%s|%s",
b7c8f459 413 ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
15d31b7e 414 "CLIENT" : "SERVER",
b7c8f459 415 ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
15d31b7e
DB
416 "MUTUAL" : "ONE-WAY");
417
418 auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
419 fprintf(NetTrace, "%s", buf);
420 break;
4d09a147 421
15d31b7e
DB
422 case TELQUAL_SEND:
423 i = 2;
424 fprintf(NetTrace, " SEND ");
425 while (i < length) {
426 if (AUTHTYPE_NAME_OK(pointer[i]))
427 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
428 else
429 fprintf(NetTrace, "%d ", pointer[i]);
430 if (++i >= length) {
431 fprintf(NetTrace, "(partial suboption???)");
4d09a147 432 break;
15d31b7e
DB
433 }
434 fprintf(NetTrace, "%s|%s ",
b7c8f459 435 ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
15d31b7e 436 "CLIENT" : "SERVER",
b7c8f459 437 ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
15d31b7e
DB
438 "MUTUAL" : "ONE-WAY");
439 ++i;
4d09a147 440 }
15d31b7e 441 break;
4d09a147 442
b7c8f459
DB
443 case TELQUAL_NAME:
444 i = 2;
445 fprintf(NetTrace, " NAME \"");
446 while (i < length)
447 putc(pointer[i++], NetTrace);
448 putc('"', NetTrace);
449 break;
450
15d31b7e
DB
451 default:
452 for (i = 2; i < length; i++)
453 fprintf(NetTrace, " ?%d?", pointer[i]);
454 break;
4d09a147 455 }
15d31b7e
DB
456 break;
457#endif
458
8832c633 459#if defined(ENCRYPTION)
15d31b7e
DB
460 case TELOPT_ENCRYPT:
461 fprintf(NetTrace, "ENCRYPT");
462 if (length < 2) {
463 fprintf(NetTrace, " (empty suboption???)");
464 break;
465 }
466 switch (pointer[1]) {
467 case ENCRYPT_START:
468 fprintf(NetTrace, " START");
469 break;
470
471 case ENCRYPT_END:
472 fprintf(NetTrace, " END");
473 break;
474
475 case ENCRYPT_REQSTART:
476 fprintf(NetTrace, " REQUEST-START");
477 break;
478
479 case ENCRYPT_REQEND:
480 fprintf(NetTrace, " REQUEST-END");
481 break;
482
483 case ENCRYPT_IS:
484 case ENCRYPT_REPLY:
485 fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
486 "IS" : "REPLY");
487 if (length < 3) {
488 fprintf(NetTrace, " (partial suboption???)");
489 break;
490 }
491 if (ENCTYPE_NAME_OK(pointer[2]))
492 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
493 else
494 fprintf(NetTrace, " %d (unknown)", pointer[2]);
495
496 encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
497 fprintf(NetTrace, "%s", buf);
498 break;
499
500 case ENCRYPT_SUPPORT:
501 i = 2;
502 fprintf(NetTrace, " SUPPORT ");
503 while (i < length) {
504 if (ENCTYPE_NAME_OK(pointer[i]))
505 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
506 else
507 fprintf(NetTrace, "%d ", pointer[i]);
508 i++;
509 }
4d09a147
KF
510 break;
511
b7c8f459
DB
512 case ENCRYPT_ENC_KEYID:
513 fprintf(NetTrace, " ENC_KEYID ");
514 goto encommon;
515
516 case ENCRYPT_DEC_KEYID:
517 fprintf(NetTrace, " DEC_KEYID ");
518 goto encommon;
519
4d09a147 520 default:
b7c8f459
DB
521 fprintf(NetTrace, " %d (unknown)", pointer[1]);
522 encommon:
15d31b7e
DB
523 for (i = 2; i < length; i++)
524 fprintf(NetTrace, " %d", pointer[i]);
525 break;
4d09a147
KF
526 }
527 break;
15d31b7e 528#endif
4d09a147 529
6055a9f6
PB
530 case TELOPT_LINEMODE:
531 fprintf(NetTrace, "LINEMODE ");
532 if (length < 2) {
533 fprintf(NetTrace, " (empty suboption???)");
534 break;
535 }
536 switch (pointer[1]) {
537 case WILL:
538 fprintf(NetTrace, "WILL ");
539 goto common;
540 case WONT:
541 fprintf(NetTrace, "WONT ");
542 goto common;
543 case DO:
544 fprintf(NetTrace, "DO ");
545 goto common;
546 case DONT:
547 fprintf(NetTrace, "DONT ");
548 common:
549 if (length < 3) {
550 fprintf(NetTrace, "(no option???)");
551 break;
552 }
553 switch (pointer[2]) {
554 case LM_FORWARDMASK:
555 fprintf(NetTrace, "Forward Mask");
556 for (i = 3; i < length; i++)
557 fprintf(NetTrace, " %x", pointer[i]);
558 break;
559 default:
560 fprintf(NetTrace, "%d (unknown)", pointer[2]);
561 for (i = 3; i < length; i++)
562 fprintf(NetTrace, " %d", pointer[i]);
563 break;
564 }
565 break;
566
567 case LM_SLC:
568 fprintf(NetTrace, "SLC");
569 for (i = 2; i < length - 2; i += 3) {
15d31b7e
DB
570 if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
571 fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
6055a9f6
PB
572 else
573 fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
574 switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
575 case SLC_NOSUPPORT:
576 fprintf(NetTrace, " NOSUPPORT"); break;
577 case SLC_CANTCHANGE:
578 fprintf(NetTrace, " CANTCHANGE"); break;
579 case SLC_VARIABLE:
580 fprintf(NetTrace, " VARIABLE"); break;
581 case SLC_DEFAULT:
582 fprintf(NetTrace, " DEFAULT"); break;
583 }
584 fprintf(NetTrace, "%s%s%s",
585 pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
586 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
587 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
588 if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
589 SLC_FLUSHOUT| SLC_LEVELBITS))
590 fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
591 fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
4a8a7128
PB
592 if ((pointer[i+SLC_VALUE] == IAC) &&
593 (pointer[i+SLC_VALUE+1] == IAC))
594 i++;
6055a9f6
PB
595 }
596 for (; i < length; i++)
597 fprintf(NetTrace, " ?%d?", pointer[i]);
598 break;
599
600 case LM_MODE:
601 fprintf(NetTrace, "MODE ");
602 if (length < 3) {
603 fprintf(NetTrace, "(no mode???)");
604 break;
605 }
606 {
4a8a7128
PB
607 char tbuf[64];
608 sprintf(tbuf, "%s%s%s%s%s",
6055a9f6
PB
609 pointer[2]&MODE_EDIT ? "|EDIT" : "",
610 pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
4a8a7128
PB
611 pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
612 pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
6055a9f6
PB
613 pointer[2]&MODE_ACK ? "|ACK" : "");
614 fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
615 }
15d31b7e 616 if (pointer[2]&~(MODE_MASK))
6055a9f6
PB
617 fprintf(NetTrace, " (0x%x)", pointer[2]);
618 for (i = 3; i < length; i++)
619 fprintf(NetTrace, " ?0x%x?", pointer[i]);
620 break;
621 default:
622 fprintf(NetTrace, "%d (unknown)", pointer[1]);
623 for (i = 2; i < length; i++)
624 fprintf(NetTrace, " %d", pointer[i]);
625 }
626 break;
627
6570c863
PB
628 case TELOPT_STATUS: {
629 register char *cp;
630 register int j, k;
631
632 fprintf(NetTrace, "STATUS");
633
634 switch (pointer[1]) {
635 default:
636 if (pointer[1] == TELQUAL_SEND)
637 fprintf(NetTrace, " SEND");
638 else
4a8a7128 639 fprintf(NetTrace, " %d (unknown)", pointer[1]);
6570c863
PB
640 for (i = 2; i < length; i++)
641 fprintf(NetTrace, " ?%d?", pointer[i]);
642 break;
643 case TELQUAL_IS:
15d31b7e
DB
644 if (--want_status_response < 0)
645 want_status_response = 0;
6570c863
PB
646 if (NetTrace == stdout)
647 fprintf(NetTrace, " IS\r\n");
648 else
649 fprintf(NetTrace, " IS\n");
650
651 for (i = 2; i < length; i++) {
652 switch(pointer[i]) {
653 case DO: cp = "DO"; goto common2;
654 case DONT: cp = "DONT"; goto common2;
655 case WILL: cp = "WILL"; goto common2;
656 case WONT: cp = "WONT"; goto common2;
657 common2:
658 i++;
4a8a7128 659 if (TELOPT_OK((int)pointer[i]))
6570c863
PB
660 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
661 else
662 fprintf(NetTrace, " %s %d", cp, pointer[i]);
663
664 if (NetTrace == stdout)
665 fprintf(NetTrace, "\r\n");
666 else
667 fprintf(NetTrace, "\n");
668 break;
669
670 case SB:
671 fprintf(NetTrace, " SB ");
672 i++;
673 j = k = i;
674 while (j < length) {
675 if (pointer[j] == SE) {
676 if (j+1 == length)
677 break;
678 if (pointer[j+1] == SE)
679 j++;
680 else
681 break;
682 }
683 pointer[k++] = pointer[j++];
684 }
685 printsub(0, &pointer[i], k - i);
686 if (i < length) {
687 fprintf(NetTrace, " SE");
688 i = j;
689 } else
690 i = j - 1;
691
692 if (NetTrace == stdout)
693 fprintf(NetTrace, "\r\n");
694 else
695 fprintf(NetTrace, "\n");
696
697 break;
698
699 default:
700 fprintf(NetTrace, " %d", pointer[i]);
701 break;
702 }
703 }
704 break;
705 }
706 break;
707 }
708
4a8a7128
PB
709 case TELOPT_XDISPLOC:
710 fprintf(NetTrace, "X-DISPLAY-LOCATION ");
711 switch (pointer[1]) {
712 case TELQUAL_IS:
713 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
714 break;
715 case TELQUAL_SEND:
716 fprintf(NetTrace, "SEND");
717 break;
718 default:
719 fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
720 pointer[1], pointer[1]);
721 }
722 break;
723
724 case TELOPT_ENVIRON:
725 fprintf(NetTrace, "ENVIRON ");
726 switch (pointer[1]) {
727 case TELQUAL_IS:
728 fprintf(NetTrace, "IS ");
729 goto env_common;
730 case TELQUAL_SEND:
731 fprintf(NetTrace, "SEND ");
732 goto env_common;
733 case TELQUAL_INFO:
734 fprintf(NetTrace, "INFO ");
735 env_common:
736 {
737 register int noquote = 2;
3c2dafdd
DB
738#ifdef ENV_HACK
739 extern int env_var, env_value;
740#endif
4a8a7128
PB
741 for (i = 2; i < length; i++ ) {
742 switch (pointer[i]) {
743 case ENV_VAR:
3c2dafdd
DB
744#ifdef ENV_HACK
745 if (env_var == ENV_VALUE)
746 fprintf(NetTrace, "\" (VALUE) " + noquote);
747 else
748#endif
4a8a7128
PB
749 fprintf(NetTrace, "\" VAR " + noquote);
750 noquote = 2;
751 break;
752
753 case ENV_VALUE:
3c2dafdd
DB
754#ifdef ENV_HACK
755 if (env_value == ENV_VAR)
756 fprintf(NetTrace, "\" (VAR) " + noquote);
757 else
758#endif
4a8a7128
PB
759 fprintf(NetTrace, "\" VALUE " + noquote);
760 noquote = 2;
761 break;
762
763 case ENV_ESC:
764 fprintf(NetTrace, "\" ESC " + noquote);
765 noquote = 2;
766 break;
767
8832c633 768 case ENV_USERVAR:
8832c633
DB
769 fprintf(NetTrace, "\" USERVAR " + noquote);
770 noquote = 2;
771 break;
772
4a8a7128
PB
773 default:
774 def_case:
775 if (isprint(pointer[i]) && pointer[i] != '"') {
776 if (noquote) {
777 putc('"', NetTrace);
778 noquote = 0;
779 }
780 putc(pointer[i], NetTrace);
781 } else {
782 fprintf(NetTrace, "\" %03o " + noquote,
783 pointer[i]);
784 noquote = 2;
785 }
786 break;
787 }
788 }
789 if (!noquote)
790 putc('"', NetTrace);
791 break;
792 }
793 }
794 break;
795
788caa15 796 default:
15d31b7e
DB
797 if (TELOPT_OK(pointer[0]))
798 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
799 else
6e549b07 800 fprintf(NetTrace, "%d (unknown)", pointer[0]);
15d31b7e 801 for (i = 1; i < length; i++)
6055a9f6
PB
802 fprintf(NetTrace, " %d", pointer[i]);
803 break;
788caa15 804 }
6570c863
PB
805 if (direction) {
806 if (NetTrace == stdout)
807 fprintf(NetTrace, "\r\n");
808 else
809 fprintf(NetTrace, "\n");
810 }
788caa15
GM
811 }
812}
cf9305fa
GM
813
814/* EmptyTerminal - called to make sure that the terminal buffer is empty.
815 * Note that we consider the buffer to run all the
816 * way to the kernel (thus the select).
817 */
818
15d31b7e 819 void
cf9305fa
GM
820EmptyTerminal()
821{
822#if defined(unix)
823 fd_set o;
824
825 FD_ZERO(&o);
826#endif /* defined(unix) */
827
828 if (TTYBYTES() == 0) {
829#if defined(unix)
830 FD_SET(tout, &o);
831 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
832 (struct timeval *) 0); /* wait for TTLOWAT */
833#endif /* defined(unix) */
834 } else {
835 while (TTYBYTES()) {
4a8a7128 836 (void) ttyflush(0);
cf9305fa
GM
837#if defined(unix)
838 FD_SET(tout, &o);
839 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
840 (struct timeval *) 0); /* wait for TTLOWAT */
841#endif /* defined(unix) */
842 }
843 }
844}
845
15d31b7e 846 void
cf9305fa
GM
847SetForExit()
848{
6055a9f6 849 setconnmode(0);
cf9305fa
GM
850#if defined(TN3270)
851 if (In3270) {
852 Finish3270();
853 }
6da40c06
GM
854#else /* defined(TN3270) */
855 do {
4a8a7128 856 (void)telrcv(); /* Process any incoming data */
6da40c06
GM
857 EmptyTerminal();
858 } while (ring_full_count(&netiring)); /* While there is any */
cf9305fa
GM
859#endif /* defined(TN3270) */
860 setcommandmode();
861 fflush(stdout);
862 fflush(stderr);
863#if defined(TN3270)
864 if (In3270) {
865 StopScreen(1);
866 }
867#endif /* defined(TN3270) */
6055a9f6 868 setconnmode(0);
cf9305fa
GM
869 EmptyTerminal(); /* Flush the path to the tty */
870 setcommandmode();
871}
872
15d31b7e 873 void
cf9305fa 874Exit(returnCode)
15d31b7e 875 int returnCode;
cf9305fa
GM
876{
877 SetForExit();
878 exit(returnCode);
879}
880
15d31b7e 881 void
cf9305fa 882ExitString(string, returnCode)
15d31b7e
DB
883 char *string;
884 int returnCode;
cf9305fa
GM
885{
886 SetForExit();
887 fwrite(string, 1, strlen(string), stderr);
888 exit(returnCode);
889}