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