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