Correct BSD License clause numbering from 1-2-4 to 1-2-3.
[dragonfly.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. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)utilities.c      8.3 (Berkeley) 5/30/95
30  * $FreeBSD: src/crypto/telnet/telnet/utilities.c,v 1.2.8.2 2002/04/13 10:59:08 markm Exp $
31  */
32
33 #define TELOPTS
34 #define TELCMDS
35 #define SLC_NAMES
36 #include <arpa/telnet.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/time.h>
40 #include <ctype.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43
44 #include "general.h"
45
46 #include "fdset.h"
47
48 #include "ring.h"
49
50 #include "defines.h"
51
52 #include "externs.h"
53
54 #ifdef  AUTHENTICATION
55 #include <libtelnet/auth.h>
56 #endif
57 #ifdef  ENCRYPTION
58 #include <libtelnet/encrypt.h>
59 #endif
60
61 FILE    *NetTrace = NULL;               /* Not in bss, since needs to stay */
62 int     prettydump;
63
64 /*
65  * upcase()
66  *
67  *      Upcase (in place) the argument.
68  */
69
70 void
71 upcase(char *argument)
72 {
73     int c;
74
75     while ((c = *argument) != 0) {
76         if (islower(c)) {
77             *argument = toupper(c);
78         }
79         argument++;
80     }
81 }
82
83 /*
84  * SetSockOpt()
85  *
86  * Compensate for differences in 4.2 and 4.3 systems.
87  */
88
89 int
90 SetSockOpt(int fd, int level, int option, int yesno)
91 {
92     return setsockopt(fd, level, option,
93                                 (char *)&yesno, sizeof yesno);
94 }
95 \f
96 /*
97  * The following are routines used to print out debugging information.
98  */
99
100 unsigned char NetTraceFile[256] = "(standard output)";
101
102 void
103 SetNetTrace(char *file)
104 {
105     if (NetTrace && NetTrace != stdout)
106         fclose(NetTrace);
107     if (file  && (strcmp(file, "-") != 0)) {
108         NetTrace = fopen(file, "w");
109         if (NetTrace) {
110             strcpy((char *)NetTraceFile, file);
111             return;
112         }
113         fprintf(stderr, "Cannot open %s.\n", file);
114     }
115     NetTrace = stdout;
116     strcpy((char *)NetTraceFile, "(standard output)");
117 }
118
119 void
120 Dump(char direction, unsigned char *buffer, int length)
121 {
122 #   define BYTES_PER_LINE       32
123 #   define min(x,y)     ((x<y)? x:y)
124     unsigned char *pThis;
125     int offset;
126
127     offset = 0;
128
129     while (length) {
130         /* print one line */
131         fprintf(NetTrace, "%c 0x%x\t", direction, offset);
132         pThis = buffer;
133         if (prettydump) {
134             buffer = buffer + min(length, BYTES_PER_LINE/2);
135             while (pThis < buffer) {
136                 fprintf(NetTrace, "%c%.2x",
137                     (((*pThis)&0xff) == 0xff) ? '*' : ' ',
138                     (*pThis)&0xff);
139                 pThis++;
140             }
141             length -= BYTES_PER_LINE/2;
142             offset += BYTES_PER_LINE/2;
143         } else {
144             buffer = buffer + min(length, BYTES_PER_LINE);
145             while (pThis < buffer) {
146                 fprintf(NetTrace, "%.2x", (*pThis)&0xff);
147                 pThis++;
148             }
149             length -= BYTES_PER_LINE;
150             offset += BYTES_PER_LINE;
151         }
152         if (NetTrace == stdout) {
153             fprintf(NetTrace, "\r\n");
154         } else {
155             fprintf(NetTrace, "\n");
156         }
157         if (length < 0) {
158             fflush(NetTrace);
159             return;
160         }
161         /* find next unique line */
162     }
163     fflush(NetTrace);
164 }
165
166
167 void
168 printoption(const char *direction, int cmd, int option)
169 {
170         if (!showoptions)
171                 return;
172         if (cmd == IAC) {
173                 if (TELCMD_OK(option))
174                     fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
175                 else
176                     fprintf(NetTrace, "%s IAC %d", direction, option);
177         } else {
178                 const char *fmt;
179                 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
180                         (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
181                 if (fmt) {
182                     fprintf(NetTrace, "%s %s ", direction, fmt);
183                     if (TELOPT_OK(option))
184                         fprintf(NetTrace, "%s", TELOPT(option));
185                     else if (option == TELOPT_EXOPL)
186                         fprintf(NetTrace, "EXOPL");
187                     else
188                         fprintf(NetTrace, "%d", option);
189                 } else
190                     fprintf(NetTrace, "%s %d %d", direction, cmd, option);
191         }
192         if (NetTrace == stdout) {
193             fprintf(NetTrace, "\r\n");
194             fflush(NetTrace);
195         } else {
196             fprintf(NetTrace, "\n");
197         }
198         return;
199 }
200
201 void
202 optionstatus(void)
203 {
204     int i;
205     extern char will_wont_resp[], do_dont_resp[];
206
207     for (i = 0; i < 256; i++) {
208         if (do_dont_resp[i]) {
209             if (TELOPT_OK(i))
210                 printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
211             else if (TELCMD_OK(i))
212                 printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
213             else
214                 printf("resp DO_DONT %d: %d\n", i,
215                                 do_dont_resp[i]);
216             if (my_want_state_is_do(i)) {
217                 if (TELOPT_OK(i))
218                     printf("want DO   %s\n", TELOPT(i));
219                 else if (TELCMD_OK(i))
220                     printf("want DO   %s\n", TELCMD(i));
221                 else
222                     printf("want DO   %d\n", i);
223             } else {
224                 if (TELOPT_OK(i))
225                     printf("want DONT %s\n", TELOPT(i));
226                 else if (TELCMD_OK(i))
227                     printf("want DONT %s\n", TELCMD(i));
228                 else
229                     printf("want DONT %d\n", i);
230             }
231         } else {
232             if (my_state_is_do(i)) {
233                 if (TELOPT_OK(i))
234                     printf("     DO   %s\n", TELOPT(i));
235                 else if (TELCMD_OK(i))
236                     printf("     DO   %s\n", TELCMD(i));
237                 else
238                     printf("     DO   %d\n", i);
239             }
240         }
241         if (will_wont_resp[i]) {
242             if (TELOPT_OK(i))
243                 printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
244             else if (TELCMD_OK(i))
245                 printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
246             else
247                 printf("resp WILL_WONT %d: %d\n",
248                                 i, will_wont_resp[i]);
249             if (my_want_state_is_will(i)) {
250                 if (TELOPT_OK(i))
251                     printf("want WILL %s\n", TELOPT(i));
252                 else if (TELCMD_OK(i))
253                     printf("want WILL %s\n", TELCMD(i));
254                 else
255                     printf("want WILL %d\n", i);
256             } else {
257                 if (TELOPT_OK(i))
258                     printf("want WONT %s\n", TELOPT(i));
259                 else if (TELCMD_OK(i))
260                     printf("want WONT %s\n", TELCMD(i));
261                 else
262                     printf("want WONT %d\n", i);
263             }
264         } else {
265             if (my_state_is_will(i)) {
266                 if (TELOPT_OK(i))
267                     printf("     WILL %s\n", TELOPT(i));
268                 else if (TELCMD_OK(i))
269                     printf("     WILL %s\n", TELCMD(i));
270                 else
271                     printf("     WILL %d\n", i);
272             }
273         }
274     }
275
276 }
277
278 void
279 printsub(char direction, unsigned char *pointer, int length)
280 {
281     int i;
282 #ifdef  AUTHENTICATION
283     char buf[512];
284 #endif
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) {
293                 int j;
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 #ifdef  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
474 #ifdef  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  /* ENCRYPTION */
544
545         case TELOPT_LINEMODE:
546             fprintf(NetTrace, "LINEMODE ");
547             if (length < 2) {
548                 fprintf(NetTrace, " (empty suboption??\?)");
549                 break;
550             }
551             switch (pointer[1]) {
552             case WILL:
553                 fprintf(NetTrace, "WILL ");
554                 goto common;
555             case WONT:
556                 fprintf(NetTrace, "WONT ");
557                 goto common;
558             case DO:
559                 fprintf(NetTrace, "DO ");
560                 goto common;
561             case DONT:
562                 fprintf(NetTrace, "DONT ");
563             common:
564                 if (length < 3) {
565                     fprintf(NetTrace, "(no option??\?)");
566                     break;
567                 }
568                 switch (pointer[2]) {
569                 case LM_FORWARDMASK:
570                     fprintf(NetTrace, "Forward Mask");
571                     for (i = 3; i < length; i++)
572                         fprintf(NetTrace, " %x", pointer[i]);
573                     break;
574                 default:
575                     fprintf(NetTrace, "%d (unknown)", pointer[2]);
576                     for (i = 3; i < length; i++)
577                         fprintf(NetTrace, " %d", pointer[i]);
578                     break;
579                 }
580                 break;
581
582             case LM_SLC:
583                 fprintf(NetTrace, "SLC");
584                 for (i = 2; i < length - 2; i += 3) {
585                     if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
586                         fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
587                     else
588                         fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
589                     switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
590                     case SLC_NOSUPPORT:
591                         fprintf(NetTrace, " NOSUPPORT"); break;
592                     case SLC_CANTCHANGE:
593                         fprintf(NetTrace, " CANTCHANGE"); break;
594                     case SLC_VARIABLE:
595                         fprintf(NetTrace, " VARIABLE"); break;
596                     case SLC_DEFAULT:
597                         fprintf(NetTrace, " DEFAULT"); break;
598                     }
599                     fprintf(NetTrace, "%s%s%s",
600                         pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
601                         pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
602                         pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
603                     if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
604                                                 SLC_FLUSHOUT| SLC_LEVELBITS))
605                         fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
606                     fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
607                     if ((pointer[i+SLC_VALUE] == IAC) &&
608                         (pointer[i+SLC_VALUE+1] == IAC))
609                                 i++;
610                 }
611                 for (; i < length; i++)
612                     fprintf(NetTrace, " ?%d?", pointer[i]);
613                 break;
614
615             case LM_MODE:
616                 fprintf(NetTrace, "MODE ");
617                 if (length < 3) {
618                     fprintf(NetTrace, "(no mode??\?)");
619                     break;
620                 }
621                 {
622                     char tbuf[64];
623                     sprintf(tbuf, "%s%s%s%s%s",
624                         pointer[2]&MODE_EDIT ? "|EDIT" : "",
625                         pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
626                         pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
627                         pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
628                         pointer[2]&MODE_ACK ? "|ACK" : "");
629                     fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
630                 }
631                 if (pointer[2]&~(MODE_MASK))
632                     fprintf(NetTrace, " (0x%x)", pointer[2]);
633                 for (i = 3; i < length; i++)
634                     fprintf(NetTrace, " ?0x%x?", pointer[i]);
635                 break;
636             default:
637                 fprintf(NetTrace, "%d (unknown)", pointer[1]);
638                 for (i = 2; i < length; i++)
639                     fprintf(NetTrace, " %d", pointer[i]);
640             }
641             break;
642
643         case TELOPT_STATUS: {
644             const char *cp;
645             int j, k;
646
647             fprintf(NetTrace, "STATUS");
648
649             switch (pointer[1]) {
650             default:
651                 if (pointer[1] == TELQUAL_SEND)
652                     fprintf(NetTrace, " SEND");
653                 else
654                     fprintf(NetTrace, " %d (unknown)", pointer[1]);
655                 for (i = 2; i < length; i++)
656                     fprintf(NetTrace, " ?%d?", pointer[i]);
657                 break;
658             case TELQUAL_IS:
659                 if (--want_status_response < 0)
660                     want_status_response = 0;
661                 if (NetTrace == stdout)
662                     fprintf(NetTrace, " IS\r\n");
663                 else
664                     fprintf(NetTrace, " IS\n");
665
666                 for (i = 2; i < length; i++) {
667                     switch(pointer[i]) {
668                     case DO:    cp = "DO"; goto common2;
669                     case DONT:  cp = "DONT"; goto common2;
670                     case WILL:  cp = "WILL"; goto common2;
671                     case WONT:  cp = "WONT"; goto common2;
672                     common2:
673                         i++;
674                         if (TELOPT_OK((int)pointer[i]))
675                             fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
676                         else
677                             fprintf(NetTrace, " %s %d", cp, pointer[i]);
678
679                         if (NetTrace == stdout)
680                             fprintf(NetTrace, "\r\n");
681                         else
682                             fprintf(NetTrace, "\n");
683                         break;
684
685                     case SB:
686                         fprintf(NetTrace, " SB ");
687                         i++;
688                         j = k = i;
689                         while (j < length) {
690                             if (pointer[j] == SE) {
691                                 if (j+1 == length)
692                                     break;
693                                 if (pointer[j+1] == SE)
694                                     j++;
695                                 else
696                                     break;
697                             }
698                             pointer[k++] = pointer[j++];
699                         }
700                         printsub(0, &pointer[i], k - i);
701                         if (i < length) {
702                             fprintf(NetTrace, " SE");
703                             i = j;
704                         } else
705                             i = j - 1;
706
707                         if (NetTrace == stdout)
708                             fprintf(NetTrace, "\r\n");
709                         else
710                             fprintf(NetTrace, "\n");
711
712                         break;
713
714                     default:
715                         fprintf(NetTrace, " %d", pointer[i]);
716                         break;
717                     }
718                 }
719                 break;
720             }
721             break;
722           }
723
724         case TELOPT_XDISPLOC:
725             fprintf(NetTrace, "X-DISPLAY-LOCATION ");
726             switch (pointer[1]) {
727             case TELQUAL_IS:
728                 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
729                 break;
730             case TELQUAL_SEND:
731                 fprintf(NetTrace, "SEND");
732                 break;
733             default:
734                 fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
735                                 pointer[1], pointer[1]);
736             }
737             break;
738
739         case TELOPT_NEW_ENVIRON:
740             fprintf(NetTrace, "NEW-ENVIRON ");
741 #ifdef  OLD_ENVIRON
742             goto env_common1;
743         case TELOPT_OLD_ENVIRON:
744             fprintf(NetTrace, "OLD-ENVIRON");
745         env_common1:
746 #endif
747             switch (pointer[1]) {
748             case TELQUAL_IS:
749                 fprintf(NetTrace, "IS ");
750                 goto env_common;
751             case TELQUAL_SEND:
752                 fprintf(NetTrace, "SEND ");
753                 goto env_common;
754             case TELQUAL_INFO:
755                 fprintf(NetTrace, "INFO ");
756             env_common:
757                 {
758                     int noquote = 2;
759 #if defined(ENV_HACK) && defined(OLD_ENVIRON)
760                     extern int old_env_var, old_env_value;
761 #endif
762                     for (i = 2; i < length; i++ ) {
763                         switch (pointer[i]) {
764                         case NEW_ENV_VALUE:
765 #ifdef OLD_ENVIRON
766                      /* case NEW_ENV_OVAR: */
767                             if (pointer[0] == TELOPT_OLD_ENVIRON) {
768 # ifdef ENV_HACK
769                                 if (old_env_var == OLD_ENV_VALUE)
770                                     fprintf(NetTrace, "\" (VALUE) " + noquote);
771                                 else
772 # endif
773                                     fprintf(NetTrace, "\" VAR " + noquote);
774                             } else
775 #endif /* OLD_ENVIRON */
776                                 fprintf(NetTrace, "\" VALUE " + noquote);
777                             noquote = 2;
778                             break;
779
780                         case NEW_ENV_VAR:
781 #ifdef OLD_ENVIRON
782                      /* case OLD_ENV_VALUE: */
783                             if (pointer[0] == TELOPT_OLD_ENVIRON) {
784 # ifdef ENV_HACK
785                                 if (old_env_value == OLD_ENV_VAR)
786                                     fprintf(NetTrace, "\" (VAR) " + noquote);
787                                 else
788 # endif
789                                     fprintf(NetTrace, "\" VALUE " + noquote);
790                             } else
791 #endif /* OLD_ENVIRON */
792                                 fprintf(NetTrace, "\" VAR " + noquote);
793                             noquote = 2;
794                             break;
795
796                         case ENV_ESC:
797                             fprintf(NetTrace, "\" ESC " + noquote);
798                             noquote = 2;
799                             break;
800
801                         case ENV_USERVAR:
802                             fprintf(NetTrace, "\" USERVAR " + noquote);
803                             noquote = 2;
804                             break;
805
806                         default:
807                             if (isprint(pointer[i]) && pointer[i] != '"') {
808                                 if (noquote) {
809                                     putc('"', NetTrace);
810                                     noquote = 0;
811                                 }
812                                 putc(pointer[i], NetTrace);
813                             } else {
814                                 fprintf(NetTrace, "\" %03o " + noquote,
815                                                         pointer[i]);
816                                 noquote = 2;
817                             }
818                             break;
819                         }
820                     }
821                     if (!noquote)
822                         putc('"', NetTrace);
823                     break;
824                 }
825             }
826             break;
827
828         default:
829             if (TELOPT_OK(pointer[0]))
830                 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
831             else
832                 fprintf(NetTrace, "%d (unknown)", pointer[0]);
833             for (i = 1; i < length; i++)
834                 fprintf(NetTrace, " %d", pointer[i]);
835             break;
836         }
837         if (direction) {
838             if (NetTrace == stdout)
839                 fprintf(NetTrace, "\r\n");
840             else
841                 fprintf(NetTrace, "\n");
842         }
843         if (NetTrace == stdout)
844             fflush(NetTrace);
845     }
846 }
847
848 /* EmptyTerminal - called to make sure that the terminal buffer is empty.
849  *                      Note that we consider the buffer to run all the
850  *                      way to the kernel (thus the select).
851  */
852
853 static void
854 EmptyTerminal(void)
855 {
856     fd_set      o;
857
858     FD_ZERO(&o);
859
860     if (TTYBYTES() == 0) {
861         FD_SET(tout, &o);
862         (void) select(tout+1, NULL, &o, NULL, NULL);    /* wait for TTLOWAT */
863     } else {
864         while (TTYBYTES()) {
865             (void) ttyflush(0);
866             FD_SET(tout, &o);
867             (void) select(tout+1, NULL, &o, NULL, NULL); /* wait for TTLOWAT */
868         }
869     }
870 }
871
872 static void
873 SetForExit(void)
874 {
875     setconnmode(0);
876     do {
877         (void)telrcv();                 /* Process any incoming data */
878         EmptyTerminal();
879     } while (ring_full_count(&netiring));       /* While there is any */
880     setcommandmode();
881     fflush(stdout);
882     fflush(stderr);
883     setconnmode(0);
884     EmptyTerminal();                    /* Flush the path to the tty */
885     setcommandmode();
886 }
887
888 void
889 Exit(int returnCode)
890 {
891     SetForExit();
892     exit(returnCode);
893 }
894
895 void
896 ExitString(const char *string, int returnCode)
897 {
898     SetForExit();
899     fwrite(string, 1, strlen(string), stderr);
900     exit(returnCode);
901 }