]> git.saurik.com Git - apple/network_cmds.git/blob - telnet.tproj/utilities.c
295729785c047c38e63b78a86dc752a7d882e172
[apple/network_cmds.git] / telnet.tproj / utilities.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1988, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #ifndef lint
58 static char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95";
59 #endif /* not lint */
60
61 #define TELOPTS
62 #define TELCMDS
63 #define SLC_NAMES
64 #include <arpa/telnet.h>
65 #include <sys/types.h>
66 #include <sys/time.h>
67
68 #include <ctype.h>
69
70 #include "general.h"
71
72 #include "fdset.h"
73
74 #include "ring.h"
75
76 #include "defines.h"
77
78 #include "externs.h"
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 register char *argument;
92 {
93 register 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 \f
126 /*
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 register 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 extern pettydump;
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 register 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 register 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 register int i;
322 char buf[512];
323 extern int want_status_response;
324
325 if (showoptions || direction == 0 ||
326 (want_status_response && (pointer[0] == TELOPT_STATUS))) {
327 if (direction) {
328 fprintf(NetTrace, "%s IAC SB ",
329 (direction == '<')? "RCVD":"SENT");
330 if (length >= 3) {
331 register int j;
332
333 i = pointer[length-2];
334 j = pointer[length-1];
335
336 if (i != IAC || j != SE) {
337 fprintf(NetTrace, "(terminated by ");
338 if (TELOPT_OK(i))
339 fprintf(NetTrace, "%s ", TELOPT(i));
340 else if (TELCMD_OK(i))
341 fprintf(NetTrace, "%s ", TELCMD(i));
342 else
343 fprintf(NetTrace, "%d ", i);
344 if (TELOPT_OK(j))
345 fprintf(NetTrace, "%s", TELOPT(j));
346 else if (TELCMD_OK(j))
347 fprintf(NetTrace, "%s", TELCMD(j));
348 else
349 fprintf(NetTrace, "%d", j);
350 fprintf(NetTrace, ", not IAC SE!) ");
351 }
352 }
353 length -= 2;
354 }
355 if (length < 1) {
356 fprintf(NetTrace, "(Empty suboption??\?)");
357 if (NetTrace == stdout)
358 fflush(NetTrace);
359 return;
360 }
361 switch (pointer[0]) {
362 case TELOPT_TTYPE:
363 fprintf(NetTrace, "TERMINAL-TYPE ");
364 switch (pointer[1]) {
365 case TELQUAL_IS:
366 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
367 break;
368 case TELQUAL_SEND:
369 fprintf(NetTrace, "SEND");
370 break;
371 default:
372 fprintf(NetTrace,
373 "- unknown qualifier %d (0x%x).",
374 pointer[1], pointer[1]);
375 }
376 break;
377 case TELOPT_TSPEED:
378 fprintf(NetTrace, "TERMINAL-SPEED");
379 if (length < 2) {
380 fprintf(NetTrace, " (empty suboption??\?)");
381 break;
382 }
383 switch (pointer[1]) {
384 case TELQUAL_IS:
385 fprintf(NetTrace, " IS ");
386 fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
387 break;
388 default:
389 if (pointer[1] == 1)
390 fprintf(NetTrace, " SEND");
391 else
392 fprintf(NetTrace, " %d (unknown)", pointer[1]);
393 for (i = 2; i < length; i++)
394 fprintf(NetTrace, " ?%d?", pointer[i]);
395 break;
396 }
397 break;
398
399 case TELOPT_LFLOW:
400 fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
401 if (length < 2) {
402 fprintf(NetTrace, " (empty suboption??\?)");
403 break;
404 }
405 switch (pointer[1]) {
406 case LFLOW_OFF:
407 fprintf(NetTrace, " OFF"); break;
408 case LFLOW_ON:
409 fprintf(NetTrace, " ON"); break;
410 case LFLOW_RESTART_ANY:
411 fprintf(NetTrace, " RESTART-ANY"); break;
412 case LFLOW_RESTART_XON:
413 fprintf(NetTrace, " RESTART-XON"); break;
414 default:
415 fprintf(NetTrace, " %d (unknown)", pointer[1]);
416 }
417 for (i = 2; i < length; i++)
418 fprintf(NetTrace, " ?%d?", pointer[i]);
419 break;
420
421 case TELOPT_NAWS:
422 fprintf(NetTrace, "NAWS");
423 if (length < 2) {
424 fprintf(NetTrace, " (empty suboption??\?)");
425 break;
426 }
427 if (length == 2) {
428 fprintf(NetTrace, " ?%d?", pointer[1]);
429 break;
430 }
431 fprintf(NetTrace, " %d %d (%d)",
432 pointer[1], pointer[2],
433 (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
434 if (length == 4) {
435 fprintf(NetTrace, " ?%d?", pointer[3]);
436 break;
437 }
438 fprintf(NetTrace, " %d %d (%d)",
439 pointer[3], pointer[4],
440 (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
441 for (i = 5; i < length; i++)
442 fprintf(NetTrace, " ?%d?", pointer[i]);
443 break;
444
445 #if defined(AUTHENTICATION)
446 case TELOPT_AUTHENTICATION:
447 fprintf(NetTrace, "AUTHENTICATION");
448 if (length < 2) {
449 fprintf(NetTrace, " (empty suboption??\?)");
450 break;
451 }
452 switch (pointer[1]) {
453 case TELQUAL_REPLY:
454 case TELQUAL_IS:
455 fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
456 "IS" : "REPLY");
457 if (AUTHTYPE_NAME_OK(pointer[2]))
458 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
459 else
460 fprintf(NetTrace, "%d ", pointer[2]);
461 if (length < 3) {
462 fprintf(NetTrace, "(partial suboption??\?)");
463 break;
464 }
465 fprintf(NetTrace, "%s|%s",
466 ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
467 "CLIENT" : "SERVER",
468 ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
469 "MUTUAL" : "ONE-WAY");
470
471 auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
472 fprintf(NetTrace, "%s", buf);
473 break;
474
475 case TELQUAL_SEND:
476 i = 2;
477 fprintf(NetTrace, " SEND ");
478 while (i < length) {
479 if (AUTHTYPE_NAME_OK(pointer[i]))
480 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
481 else
482 fprintf(NetTrace, "%d ", pointer[i]);
483 if (++i >= length) {
484 fprintf(NetTrace, "(partial suboption??\?)");
485 break;
486 }
487 fprintf(NetTrace, "%s|%s ",
488 ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
489 "CLIENT" : "SERVER",
490 ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
491 "MUTUAL" : "ONE-WAY");
492 ++i;
493 }
494 break;
495
496 case TELQUAL_NAME:
497 i = 2;
498 fprintf(NetTrace, " NAME \"");
499 while (i < length)
500 putc(pointer[i++], NetTrace);
501 putc('"', NetTrace);
502 break;
503
504 default:
505 for (i = 2; i < length; i++)
506 fprintf(NetTrace, " ?%d?", pointer[i]);
507 break;
508 }
509 break;
510 #endif
511
512 #ifdef ENCRYPTION
513 case TELOPT_ENCRYPT:
514 fprintf(NetTrace, "ENCRYPT");
515 if (length < 2) {
516 fprintf(NetTrace, " (empty suboption??\?)");
517 break;
518 }
519 switch (pointer[1]) {
520 case ENCRYPT_START:
521 fprintf(NetTrace, " START");
522 break;
523
524 case ENCRYPT_END:
525 fprintf(NetTrace, " END");
526 break;
527
528 case ENCRYPT_REQSTART:
529 fprintf(NetTrace, " REQUEST-START");
530 break;
531
532 case ENCRYPT_REQEND:
533 fprintf(NetTrace, " REQUEST-END");
534 break;
535
536 case ENCRYPT_IS:
537 case ENCRYPT_REPLY:
538 fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
539 "IS" : "REPLY");
540 if (length < 3) {
541 fprintf(NetTrace, " (partial suboption??\?)");
542 break;
543 }
544 if (ENCTYPE_NAME_OK(pointer[2]))
545 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
546 else
547 fprintf(NetTrace, " %d (unknown)", pointer[2]);
548
549 encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
550 fprintf(NetTrace, "%s", buf);
551 break;
552
553 case ENCRYPT_SUPPORT:
554 i = 2;
555 fprintf(NetTrace, " SUPPORT ");
556 while (i < length) {
557 if (ENCTYPE_NAME_OK(pointer[i]))
558 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
559 else
560 fprintf(NetTrace, "%d ", pointer[i]);
561 i++;
562 }
563 break;
564
565 case ENCRYPT_ENC_KEYID:
566 fprintf(NetTrace, " ENC_KEYID ");
567 goto encommon;
568
569 case ENCRYPT_DEC_KEYID:
570 fprintf(NetTrace, " DEC_KEYID ");
571 goto encommon;
572
573 default:
574 fprintf(NetTrace, " %d (unknown)", pointer[1]);
575 encommon:
576 for (i = 2; i < length; i++)
577 fprintf(NetTrace, " %d", pointer[i]);
578 break;
579 }
580 break;
581 #endif /* ENCRYPTION */
582
583 case TELOPT_LINEMODE:
584 fprintf(NetTrace, "LINEMODE ");
585 if (length < 2) {
586 fprintf(NetTrace, " (empty suboption??\?)");
587 break;
588 }
589 switch (pointer[1]) {
590 case WILL:
591 fprintf(NetTrace, "WILL ");
592 goto common;
593 case WONT:
594 fprintf(NetTrace, "WONT ");
595 goto common;
596 case DO:
597 fprintf(NetTrace, "DO ");
598 goto common;
599 case DONT:
600 fprintf(NetTrace, "DONT ");
601 common:
602 if (length < 3) {
603 fprintf(NetTrace, "(no option??\?)");
604 break;
605 }
606 switch (pointer[2]) {
607 case LM_FORWARDMASK:
608 fprintf(NetTrace, "Forward Mask");
609 for (i = 3; i < length; i++)
610 fprintf(NetTrace, " %x", pointer[i]);
611 break;
612 default:
613 fprintf(NetTrace, "%d (unknown)", pointer[2]);
614 for (i = 3; i < length; i++)
615 fprintf(NetTrace, " %d", pointer[i]);
616 break;
617 }
618 break;
619
620 case LM_SLC:
621 fprintf(NetTrace, "SLC");
622 for (i = 2; i < length - 2; i += 3) {
623 if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
624 fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
625 else
626 fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
627 switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
628 case SLC_NOSUPPORT:
629 fprintf(NetTrace, " NOSUPPORT"); break;
630 case SLC_CANTCHANGE:
631 fprintf(NetTrace, " CANTCHANGE"); break;
632 case SLC_VARIABLE:
633 fprintf(NetTrace, " VARIABLE"); break;
634 case SLC_DEFAULT:
635 fprintf(NetTrace, " DEFAULT"); break;
636 }
637 fprintf(NetTrace, "%s%s%s",
638 pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
639 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
640 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
641 if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
642 SLC_FLUSHOUT| SLC_LEVELBITS))
643 fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
644 fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
645 if ((pointer[i+SLC_VALUE] == IAC) &&
646 (pointer[i+SLC_VALUE+1] == IAC))
647 i++;
648 }
649 for (; i < length; i++)
650 fprintf(NetTrace, " ?%d?", pointer[i]);
651 break;
652
653 case LM_MODE:
654 fprintf(NetTrace, "MODE ");
655 if (length < 3) {
656 fprintf(NetTrace, "(no mode??\?)");
657 break;
658 }
659 {
660 char tbuf[64];
661 sprintf(tbuf, "%s%s%s%s%s",
662 pointer[2]&MODE_EDIT ? "|EDIT" : "",
663 pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
664 pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
665 pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
666 pointer[2]&MODE_ACK ? "|ACK" : "");
667 fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
668 }
669 if (pointer[2]&~(MODE_MASK))
670 fprintf(NetTrace, " (0x%x)", pointer[2]);
671 for (i = 3; i < length; i++)
672 fprintf(NetTrace, " ?0x%x?", pointer[i]);
673 break;
674 default:
675 fprintf(NetTrace, "%d (unknown)", pointer[1]);
676 for (i = 2; i < length; i++)
677 fprintf(NetTrace, " %d", pointer[i]);
678 }
679 break;
680
681 case TELOPT_STATUS: {
682 register char *cp;
683 register int j, k;
684
685 fprintf(NetTrace, "STATUS");
686
687 switch (pointer[1]) {
688 default:
689 if (pointer[1] == TELQUAL_SEND)
690 fprintf(NetTrace, " SEND");
691 else
692 fprintf(NetTrace, " %d (unknown)", pointer[1]);
693 for (i = 2; i < length; i++)
694 fprintf(NetTrace, " ?%d?", pointer[i]);
695 break;
696 case TELQUAL_IS:
697 if (--want_status_response < 0)
698 want_status_response = 0;
699 if (NetTrace == stdout)
700 fprintf(NetTrace, " IS\r\n");
701 else
702 fprintf(NetTrace, " IS\n");
703
704 for (i = 2; i < length; i++) {
705 switch(pointer[i]) {
706 case DO: cp = "DO"; goto common2;
707 case DONT: cp = "DONT"; goto common2;
708 case WILL: cp = "WILL"; goto common2;
709 case WONT: cp = "WONT"; goto common2;
710 common2:
711 i++;
712 if (TELOPT_OK((int)pointer[i]))
713 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
714 else
715 fprintf(NetTrace, " %s %d", cp, pointer[i]);
716
717 if (NetTrace == stdout)
718 fprintf(NetTrace, "\r\n");
719 else
720 fprintf(NetTrace, "\n");
721 break;
722
723 case SB:
724 fprintf(NetTrace, " SB ");
725 i++;
726 j = k = i;
727 while (j < length) {
728 if (pointer[j] == SE) {
729 if (j+1 == length)
730 break;
731 if (pointer[j+1] == SE)
732 j++;
733 else
734 break;
735 }
736 pointer[k++] = pointer[j++];
737 }
738 printsub(0, &pointer[i], k - i);
739 if (i < length) {
740 fprintf(NetTrace, " SE");
741 i = j;
742 } else
743 i = j - 1;
744
745 if (NetTrace == stdout)
746 fprintf(NetTrace, "\r\n");
747 else
748 fprintf(NetTrace, "\n");
749
750 break;
751
752 default:
753 fprintf(NetTrace, " %d", pointer[i]);
754 break;
755 }
756 }
757 break;
758 }
759 break;
760 }
761
762 case TELOPT_XDISPLOC:
763 fprintf(NetTrace, "X-DISPLAY-LOCATION ");
764 switch (pointer[1]) {
765 case TELQUAL_IS:
766 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
767 break;
768 case TELQUAL_SEND:
769 fprintf(NetTrace, "SEND");
770 break;
771 default:
772 fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
773 pointer[1], pointer[1]);
774 }
775 break;
776
777 case TELOPT_NEW_ENVIRON:
778 fprintf(NetTrace, "NEW-ENVIRON ");
779 #ifdef OLD_ENVIRON
780 goto env_common1;
781 case TELOPT_OLD_ENVIRON:
782 fprintf(NetTrace, "OLD-ENVIRON");
783 env_common1:
784 #endif
785 switch (pointer[1]) {
786 case TELQUAL_IS:
787 fprintf(NetTrace, "IS ");
788 goto env_common;
789 case TELQUAL_SEND:
790 fprintf(NetTrace, "SEND ");
791 goto env_common;
792 case TELQUAL_INFO:
793 fprintf(NetTrace, "INFO ");
794 env_common:
795 {
796 register int noquote = 2;
797 #if defined(ENV_HACK) && defined(OLD_ENVIRON)
798 extern int old_env_var, old_env_value;
799 #endif
800 for (i = 2; i < length; i++ ) {
801 switch (pointer[i]) {
802 case NEW_ENV_VALUE:
803 #ifdef OLD_ENVIRON
804 /* case NEW_ENV_OVAR: */
805 if (pointer[0] == TELOPT_OLD_ENVIRON) {
806 # ifdef ENV_HACK
807 if (old_env_var == OLD_ENV_VALUE)
808 fprintf(NetTrace, "\" (VALUE) " + noquote);
809 else
810 # endif
811 fprintf(NetTrace, "\" VAR " + noquote);
812 } else
813 #endif /* OLD_ENVIRON */
814 fprintf(NetTrace, "\" VALUE " + noquote);
815 noquote = 2;
816 break;
817
818 case NEW_ENV_VAR:
819 #ifdef OLD_ENVIRON
820 /* case OLD_ENV_VALUE: */
821 if (pointer[0] == TELOPT_OLD_ENVIRON) {
822 # ifdef ENV_HACK
823 if (old_env_value == OLD_ENV_VAR)
824 fprintf(NetTrace, "\" (VAR) " + noquote);
825 else
826 # endif
827 fprintf(NetTrace, "\" VALUE " + noquote);
828 } else
829 #endif /* OLD_ENVIRON */
830 fprintf(NetTrace, "\" VAR " + noquote);
831 noquote = 2;
832 break;
833
834 case ENV_ESC:
835 fprintf(NetTrace, "\" ESC " + noquote);
836 noquote = 2;
837 break;
838
839 case ENV_USERVAR:
840 fprintf(NetTrace, "\" USERVAR " + noquote);
841 noquote = 2;
842 break;
843
844 default:
845 def_case:
846 if (isprint(pointer[i]) && pointer[i] != '"') {
847 if (noquote) {
848 putc('"', NetTrace);
849 noquote = 0;
850 }
851 putc(pointer[i], NetTrace);
852 } else {
853 fprintf(NetTrace, "\" %03o " + noquote,
854 pointer[i]);
855 noquote = 2;
856 }
857 break;
858 }
859 }
860 if (!noquote)
861 putc('"', NetTrace);
862 break;
863 }
864 }
865 break;
866
867 default:
868 if (TELOPT_OK(pointer[0]))
869 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
870 else
871 fprintf(NetTrace, "%d (unknown)", pointer[0]);
872 for (i = 1; i < length; i++)
873 fprintf(NetTrace, " %d", pointer[i]);
874 break;
875 }
876 if (direction) {
877 if (NetTrace == stdout)
878 fprintf(NetTrace, "\r\n");
879 else
880 fprintf(NetTrace, "\n");
881 }
882 if (NetTrace == stdout)
883 fflush(NetTrace);
884 }
885 }
886
887 /* EmptyTerminal - called to make sure that the terminal buffer is empty.
888 * Note that we consider the buffer to run all the
889 * way to the kernel (thus the select).
890 */
891
892 void
893 EmptyTerminal()
894 {
895 #if defined(unix) || defined(__APPLE__)
896 fd_set o;
897
898 FD_ZERO(&o);
899 #endif /* defined(unix) || defined(__APPLE__) */
900
901 if (TTYBYTES() == 0) {
902 #if defined(unix) || defined(__APPLE__)
903 FD_SET(tout, &o);
904 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
905 (struct timeval *) 0); /* wait for TTLOWAT */
906 #endif /* defined(unix) || defined(__APPLE__) */
907 } else {
908 while (TTYBYTES()) {
909 (void) ttyflush(0);
910 #if defined(unix) || defined(__APPLE__)
911 FD_SET(tout, &o);
912 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
913 (struct timeval *) 0); /* wait for TTLOWAT */
914 #endif /* defined(unix) || defined(__APPLE__) */
915 }
916 }
917 }
918
919 void
920 SetForExit()
921 {
922 setconnmode(0);
923 #if defined(TN3270)
924 if (In3270) {
925 Finish3270();
926 }
927 #else /* defined(TN3270) */
928 do {
929 (void)telrcv(); /* Process any incoming data */
930 EmptyTerminal();
931 } while (ring_full_count(&netiring)); /* While there is any */
932 #endif /* defined(TN3270) */
933 setcommandmode();
934 fflush(stdout);
935 fflush(stderr);
936 #if defined(TN3270)
937 if (In3270) {
938 StopScreen(1);
939 }
940 #endif /* defined(TN3270) */
941 setconnmode(0);
942 EmptyTerminal(); /* Flush the path to the tty */
943 setcommandmode();
944 }
945
946 void
947 Exit(returnCode)
948 int returnCode;
949 {
950 SetForExit();
951 exit(returnCode);
952 }
953
954 void
955 ExitString(string, returnCode)
956 char *string;
957 int returnCode;
958 {
959 SetForExit();
960 fwrite(string, 1, strlen(string), stderr);
961 exit(returnCode);
962 }