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