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