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