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