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