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