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