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