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