Annotation of src/usr.bin/telnet/utilities.c, Revision 1.19
1.19 ! guenther 1: /* $OpenBSD: utilities.c,v 1.18 2014/07/20 09:20:48 guenther Exp $ */
1.2 niklas 2: /* $NetBSD: utilities.c,v 1.5 1996/02/28 21:04:21 thorpej Exp $ */
3:
1.1 deraadt 4: /*
5: * Copyright (c) 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.9 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.13 guenther 33: /* these three defines affect the behavior of <arpa/telnet.h> */
1.1 deraadt 34: #define TELOPTS
35: #define TELCMDS
36: #define SLC_NAMES
37:
1.5 art 38: #include "telnet_locl.h"
1.14 guenther 39:
1.16 guenther 40: #include <arpa/telnet.h>
1.14 guenther 41: #include <ctype.h>
1.15 guenther 42: #include <limits.h>
1.13 guenther 43: #include <poll.h>
1.16 guenther 44: #include <stdlib.h>
45: #include <string.h>
1.1 deraadt 46:
1.17 guenther 47: static FILE *NetTrace = NULL;
1.1 deraadt 48: int prettydump;
49:
50: /*
51: * upcase()
52: *
53: * Upcase (in place) the argument.
54: */
55:
1.14 guenther 56: void
57: upcase(char *argument)
1.1 deraadt 58: {
1.14 guenther 59: int c;
1.1 deraadt 60:
1.14 guenther 61: while ((c = *argument) != '\0')
62: *argument++ = toupper((unsigned char)c);
1.1 deraadt 63: }
64:
65: /*
66: * The following are routines used to print out debugging information.
67: */
68:
1.15 guenther 69: unsigned char NetTraceFile[PATH_MAX] = "(standard output)";
1.1 deraadt 70:
71: void
72: SetNetTrace(file)
1.6 mpech 73: char *file;
1.1 deraadt 74: {
75: if (NetTrace && NetTrace != stdout)
76: fclose(NetTrace);
77: if (file && (strcmp(file, "-") != 0)) {
78: NetTrace = fopen(file, "w");
79: if (NetTrace) {
1.7 itojun 80: strlcpy((char *)NetTraceFile, file, sizeof(NetTraceFile));
1.1 deraadt 81: return;
82: }
83: fprintf(stderr, "Cannot open %s.\n", file);
84: }
85: NetTrace = stdout;
1.8 hin 86: strlcpy((char *)NetTraceFile, "(standard output)", sizeof(NetTraceFile));
1.1 deraadt 87: }
88:
89: void
90: Dump(direction, buffer, length)
91: char direction;
92: unsigned char *buffer;
93: int length;
94: {
95: # define BYTES_PER_LINE 32
96: # define min(x,y) ((x<y)? x:y)
97: unsigned char *pThis;
98: int offset;
99:
100: offset = 0;
101:
102: while (length) {
103: /* print one line */
104: fprintf(NetTrace, "%c 0x%x\t", direction, offset);
105: pThis = buffer;
106: if (prettydump) {
107: buffer = buffer + min(length, BYTES_PER_LINE/2);
108: while (pThis < buffer) {
109: fprintf(NetTrace, "%c%.2x",
110: (((*pThis)&0xff) == 0xff) ? '*' : ' ',
111: (*pThis)&0xff);
112: pThis++;
113: }
114: length -= BYTES_PER_LINE/2;
115: offset += BYTES_PER_LINE/2;
116: } else {
117: buffer = buffer + min(length, BYTES_PER_LINE);
118: while (pThis < buffer) {
119: fprintf(NetTrace, "%.2x", (*pThis)&0xff);
120: pThis++;
121: }
122: length -= BYTES_PER_LINE;
123: offset += BYTES_PER_LINE;
124: }
125: if (NetTrace == stdout) {
126: fprintf(NetTrace, "\r\n");
127: } else {
128: fprintf(NetTrace, "\n");
129: }
130: if (length < 0) {
131: fflush(NetTrace);
132: return;
133: }
134: /* find next unique line */
135: }
136: fflush(NetTrace);
137: }
138:
139:
140: void
141: printoption(direction, cmd, option)
142: char *direction;
143: int cmd, option;
144: {
145: if (!showoptions)
146: return;
147: if (cmd == IAC) {
148: if (TELCMD_OK(option))
149: fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
150: else
151: fprintf(NetTrace, "%s IAC %d", direction, option);
152: } else {
1.6 mpech 153: char *fmt;
1.1 deraadt 154: fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
155: (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
156: if (fmt) {
157: fprintf(NetTrace, "%s %s ", direction, fmt);
158: if (TELOPT_OK(option))
159: fprintf(NetTrace, "%s", TELOPT(option));
160: else if (option == TELOPT_EXOPL)
161: fprintf(NetTrace, "EXOPL");
162: else
163: fprintf(NetTrace, "%d", option);
164: } else
165: fprintf(NetTrace, "%s %d %d", direction, cmd, option);
166: }
167: if (NetTrace == stdout) {
168: fprintf(NetTrace, "\r\n");
169: fflush(NetTrace);
170: } else {
171: fprintf(NetTrace, "\n");
172: }
173: return;
174: }
175:
176: void
177: optionstatus()
178: {
1.6 mpech 179: int i;
1.1 deraadt 180:
181: for (i = 0; i < 256; i++) {
182: if (do_dont_resp[i]) {
183: if (TELOPT_OK(i))
184: printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
185: else if (TELCMD_OK(i))
186: printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
187: else
188: printf("resp DO_DONT %d: %d\n", i,
189: do_dont_resp[i]);
190: if (my_want_state_is_do(i)) {
191: if (TELOPT_OK(i))
192: printf("want DO %s\n", TELOPT(i));
193: else if (TELCMD_OK(i))
194: printf("want DO %s\n", TELCMD(i));
195: else
196: printf("want DO %d\n", i);
197: } else {
198: if (TELOPT_OK(i))
199: printf("want DONT %s\n", TELOPT(i));
200: else if (TELCMD_OK(i))
201: printf("want DONT %s\n", TELCMD(i));
202: else
203: printf("want DONT %d\n", i);
204: }
205: } else {
206: if (my_state_is_do(i)) {
207: if (TELOPT_OK(i))
208: printf(" DO %s\n", TELOPT(i));
209: else if (TELCMD_OK(i))
210: printf(" DO %s\n", TELCMD(i));
211: else
212: printf(" DO %d\n", i);
213: }
214: }
215: if (will_wont_resp[i]) {
216: if (TELOPT_OK(i))
217: printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
218: else if (TELCMD_OK(i))
219: printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
220: else
221: printf("resp WILL_WONT %d: %d\n",
222: i, will_wont_resp[i]);
223: if (my_want_state_is_will(i)) {
224: if (TELOPT_OK(i))
225: printf("want WILL %s\n", TELOPT(i));
226: else if (TELCMD_OK(i))
227: printf("want WILL %s\n", TELCMD(i));
228: else
229: printf("want WILL %d\n", i);
230: } else {
231: if (TELOPT_OK(i))
232: printf("want WONT %s\n", TELOPT(i));
233: else if (TELCMD_OK(i))
234: printf("want WONT %s\n", TELCMD(i));
235: else
236: printf("want WONT %d\n", i);
237: }
238: } else {
239: if (my_state_is_will(i)) {
240: if (TELOPT_OK(i))
241: printf(" WILL %s\n", TELOPT(i));
242: else if (TELCMD_OK(i))
243: printf(" WILL %s\n", TELCMD(i));
244: else
245: printf(" WILL %d\n", i);
246: }
247: }
248: }
249:
250: }
251:
252: void
253: printsub(direction, pointer, length)
254: char direction; /* '<' or '>' */
255: unsigned char *pointer; /* where suboption data sits */
256: int length; /* length of suboption data */
257: {
1.6 mpech 258: int i;
1.1 deraadt 259:
260: if (showoptions || direction == 0 ||
261: (want_status_response && (pointer[0] == TELOPT_STATUS))) {
262: if (direction) {
263: fprintf(NetTrace, "%s IAC SB ",
264: (direction == '<')? "RCVD":"SENT");
265: if (length >= 3) {
1.6 mpech 266: int j;
1.1 deraadt 267:
268: i = pointer[length-2];
269: j = pointer[length-1];
270:
271: if (i != IAC || j != SE) {
272: fprintf(NetTrace, "(terminated by ");
273: if (TELOPT_OK(i))
274: fprintf(NetTrace, "%s ", TELOPT(i));
275: else if (TELCMD_OK(i))
276: fprintf(NetTrace, "%s ", TELCMD(i));
277: else
278: fprintf(NetTrace, "%d ", i);
279: if (TELOPT_OK(j))
280: fprintf(NetTrace, "%s", TELOPT(j));
281: else if (TELCMD_OK(j))
282: fprintf(NetTrace, "%s", TELCMD(j));
283: else
284: fprintf(NetTrace, "%d", j);
285: fprintf(NetTrace, ", not IAC SE!) ");
286: }
287: }
288: length -= 2;
289: }
290: if (length < 1) {
291: fprintf(NetTrace, "(Empty suboption??\?)");
292: if (NetTrace == stdout)
293: fflush(NetTrace);
294: return;
295: }
296: switch (pointer[0]) {
297: case TELOPT_TTYPE:
298: fprintf(NetTrace, "TERMINAL-TYPE ");
299: switch (pointer[1]) {
300: case TELQUAL_IS:
301: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
302: break;
303: case TELQUAL_SEND:
304: fprintf(NetTrace, "SEND");
305: break;
306: default:
307: fprintf(NetTrace,
308: "- unknown qualifier %d (0x%x).",
309: pointer[1], pointer[1]);
310: }
311: break;
312: case TELOPT_TSPEED:
313: fprintf(NetTrace, "TERMINAL-SPEED");
314: if (length < 2) {
315: fprintf(NetTrace, " (empty suboption??\?)");
316: break;
317: }
318: switch (pointer[1]) {
319: case TELQUAL_IS:
320: fprintf(NetTrace, " IS ");
321: fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
322: break;
323: default:
324: if (pointer[1] == 1)
325: fprintf(NetTrace, " SEND");
326: else
327: fprintf(NetTrace, " %d (unknown)", pointer[1]);
328: for (i = 2; i < length; i++)
329: fprintf(NetTrace, " ?%d?", pointer[i]);
330: break;
331: }
332: break;
333:
334: case TELOPT_LFLOW:
335: fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
336: if (length < 2) {
337: fprintf(NetTrace, " (empty suboption??\?)");
338: break;
339: }
340: switch (pointer[1]) {
341: case LFLOW_OFF:
342: fprintf(NetTrace, " OFF"); break;
343: case LFLOW_ON:
344: fprintf(NetTrace, " ON"); break;
345: case LFLOW_RESTART_ANY:
346: fprintf(NetTrace, " RESTART-ANY"); break;
347: case LFLOW_RESTART_XON:
348: fprintf(NetTrace, " RESTART-XON"); break;
349: default:
350: fprintf(NetTrace, " %d (unknown)", pointer[1]);
351: }
352: for (i = 2; i < length; i++)
353: fprintf(NetTrace, " ?%d?", pointer[i]);
354: break;
355:
356: case TELOPT_NAWS:
357: fprintf(NetTrace, "NAWS");
358: if (length < 2) {
359: fprintf(NetTrace, " (empty suboption??\?)");
360: break;
361: }
362: if (length == 2) {
363: fprintf(NetTrace, " ?%d?", pointer[1]);
364: break;
365: }
366: fprintf(NetTrace, " %d %d (%d)",
367: pointer[1], pointer[2],
368: (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
369: if (length == 4) {
370: fprintf(NetTrace, " ?%d?", pointer[3]);
371: break;
372: }
373: fprintf(NetTrace, " %d %d (%d)",
374: pointer[3], pointer[4],
375: (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
376: for (i = 5; i < length; i++)
377: fprintf(NetTrace, " ?%d?", pointer[i]);
378: break;
379:
380: case TELOPT_LINEMODE:
381: fprintf(NetTrace, "LINEMODE ");
382: if (length < 2) {
383: fprintf(NetTrace, " (empty suboption??\?)");
384: break;
385: }
386: switch (pointer[1]) {
387: case WILL:
388: fprintf(NetTrace, "WILL ");
389: goto common;
390: case WONT:
391: fprintf(NetTrace, "WONT ");
392: goto common;
393: case DO:
394: fprintf(NetTrace, "DO ");
395: goto common;
396: case DONT:
397: fprintf(NetTrace, "DONT ");
398: common:
399: if (length < 3) {
400: fprintf(NetTrace, "(no option??\?)");
401: break;
402: }
403: switch (pointer[2]) {
404: case LM_FORWARDMASK:
405: fprintf(NetTrace, "Forward Mask");
406: for (i = 3; i < length; i++)
407: fprintf(NetTrace, " %x", pointer[i]);
408: break;
409: default:
410: fprintf(NetTrace, "%d (unknown)", pointer[2]);
411: for (i = 3; i < length; i++)
412: fprintf(NetTrace, " %d", pointer[i]);
413: break;
414: }
415: break;
1.2 niklas 416:
1.1 deraadt 417: case LM_SLC:
418: fprintf(NetTrace, "SLC");
419: for (i = 2; i < length - 2; i += 3) {
420: if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
421: fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
422: else
423: fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
424: switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
425: case SLC_NOSUPPORT:
426: fprintf(NetTrace, " NOSUPPORT"); break;
427: case SLC_CANTCHANGE:
428: fprintf(NetTrace, " CANTCHANGE"); break;
429: case SLC_VARIABLE:
430: fprintf(NetTrace, " VARIABLE"); break;
431: case SLC_DEFAULT:
432: fprintf(NetTrace, " DEFAULT"); break;
433: }
434: fprintf(NetTrace, "%s%s%s",
435: pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
436: pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
437: pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
438: if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
439: SLC_FLUSHOUT| SLC_LEVELBITS))
440: fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
441: fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
442: if ((pointer[i+SLC_VALUE] == IAC) &&
443: (pointer[i+SLC_VALUE+1] == IAC))
444: i++;
445: }
446: for (; i < length; i++)
447: fprintf(NetTrace, " ?%d?", pointer[i]);
448: break;
449:
450: case LM_MODE:
451: fprintf(NetTrace, "MODE ");
452: if (length < 3) {
453: fprintf(NetTrace, "(no mode??\?)");
454: break;
455: }
456: {
457: char tbuf[64];
1.5 art 458: snprintf(tbuf, sizeof(tbuf),
459: "%s%s%s%s%s",
460: pointer[2]&MODE_EDIT ? "|EDIT" : "",
461: pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
462: pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
463: pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
464: pointer[2]&MODE_ACK ? "|ACK" : "");
1.1 deraadt 465: fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
466: }
467: if (pointer[2]&~(MODE_MASK))
468: fprintf(NetTrace, " (0x%x)", pointer[2]);
469: for (i = 3; i < length; i++)
470: fprintf(NetTrace, " ?0x%x?", pointer[i]);
471: break;
472: default:
473: fprintf(NetTrace, "%d (unknown)", pointer[1]);
474: for (i = 2; i < length; i++)
475: fprintf(NetTrace, " %d", pointer[i]);
476: }
477: break;
478:
479: case TELOPT_STATUS: {
1.6 mpech 480: char *cp;
481: int j, k;
1.1 deraadt 482:
483: fprintf(NetTrace, "STATUS");
484:
485: switch (pointer[1]) {
486: default:
487: if (pointer[1] == TELQUAL_SEND)
488: fprintf(NetTrace, " SEND");
489: else
490: fprintf(NetTrace, " %d (unknown)", pointer[1]);
491: for (i = 2; i < length; i++)
492: fprintf(NetTrace, " ?%d?", pointer[i]);
493: break;
494: case TELQUAL_IS:
495: if (--want_status_response < 0)
496: want_status_response = 0;
497: if (NetTrace == stdout)
498: fprintf(NetTrace, " IS\r\n");
499: else
500: fprintf(NetTrace, " IS\n");
501:
502: for (i = 2; i < length; i++) {
503: switch(pointer[i]) {
504: case DO: cp = "DO"; goto common2;
505: case DONT: cp = "DONT"; goto common2;
506: case WILL: cp = "WILL"; goto common2;
507: case WONT: cp = "WONT"; goto common2;
508: common2:
509: i++;
510: if (TELOPT_OK((int)pointer[i]))
511: fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
512: else
513: fprintf(NetTrace, " %s %d", cp, pointer[i]);
514:
515: if (NetTrace == stdout)
516: fprintf(NetTrace, "\r\n");
517: else
518: fprintf(NetTrace, "\n");
519: break;
520:
521: case SB:
522: fprintf(NetTrace, " SB ");
523: i++;
524: j = k = i;
525: while (j < length) {
526: if (pointer[j] == SE) {
527: if (j+1 == length)
528: break;
529: if (pointer[j+1] == SE)
530: j++;
531: else
532: break;
533: }
534: pointer[k++] = pointer[j++];
535: }
536: printsub(0, &pointer[i], k - i);
537: if (i < length) {
538: fprintf(NetTrace, " SE");
539: i = j;
540: } else
541: i = j - 1;
542:
543: if (NetTrace == stdout)
544: fprintf(NetTrace, "\r\n");
545: else
546: fprintf(NetTrace, "\n");
547:
548: break;
1.2 niklas 549:
1.1 deraadt 550: default:
551: fprintf(NetTrace, " %d", pointer[i]);
552: break;
553: }
554: }
555: break;
556: }
557: break;
558: }
559:
560: case TELOPT_XDISPLOC:
561: fprintf(NetTrace, "X-DISPLAY-LOCATION ");
562: switch (pointer[1]) {
563: case TELQUAL_IS:
564: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
565: break;
566: case TELQUAL_SEND:
567: fprintf(NetTrace, "SEND");
568: break;
569: default:
570: fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
571: pointer[1], pointer[1]);
572: }
573: break;
574:
575: case TELOPT_NEW_ENVIRON:
576: fprintf(NetTrace, "NEW-ENVIRON ");
577: switch (pointer[1]) {
578: case TELQUAL_IS:
579: fprintf(NetTrace, "IS ");
580: goto env_common;
581: case TELQUAL_SEND:
582: fprintf(NetTrace, "SEND ");
583: goto env_common;
584: case TELQUAL_INFO:
585: fprintf(NetTrace, "INFO ");
586: env_common:
587: {
1.6 mpech 588: int noquote = 2;
1.1 deraadt 589: for (i = 2; i < length; i++ ) {
590: switch (pointer[i]) {
591: case NEW_ENV_VALUE:
592: fprintf(NetTrace, "\" VALUE " + noquote);
593: noquote = 2;
594: break;
595:
596: case NEW_ENV_VAR:
597: fprintf(NetTrace, "\" VAR " + noquote);
598: noquote = 2;
599: break;
600:
601: case ENV_ESC:
602: fprintf(NetTrace, "\" ESC " + noquote);
603: noquote = 2;
604: break;
605:
606: case ENV_USERVAR:
607: fprintf(NetTrace, "\" USERVAR " + noquote);
608: noquote = 2;
609: break;
610:
611: default:
1.14 guenther 612: if (isprint((unsigned char)pointer[i]) &&
613: pointer[i] != '"') {
1.1 deraadt 614: if (noquote) {
615: putc('"', NetTrace);
616: noquote = 0;
617: }
618: putc(pointer[i], NetTrace);
619: } else {
620: fprintf(NetTrace, "\" %03o " + noquote,
621: pointer[i]);
622: noquote = 2;
623: }
624: break;
625: }
626: }
627: if (!noquote)
628: putc('"', NetTrace);
629: break;
630: }
631: }
632: break;
633:
634: default:
635: if (TELOPT_OK(pointer[0]))
636: fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
637: else
638: fprintf(NetTrace, "%d (unknown)", pointer[0]);
639: for (i = 1; i < length; i++)
640: fprintf(NetTrace, " %d", pointer[i]);
641: break;
642: }
643: if (direction) {
644: if (NetTrace == stdout)
645: fprintf(NetTrace, "\r\n");
646: else
647: fprintf(NetTrace, "\n");
648: }
649: if (NetTrace == stdout)
650: fflush(NetTrace);
651: }
652: }
653:
654: /* EmptyTerminal - called to make sure that the terminal buffer is empty.
655: * Note that we consider the buffer to run all the
1.11 millert 656: * way to the kernel (thus the poll).
1.1 deraadt 657: */
658:
659: void
660: EmptyTerminal()
661: {
1.11 millert 662: struct pollfd pfd[1];
1.1 deraadt 663:
1.11 millert 664: pfd[0].fd = tout;
665: pfd[0].events = POLLOUT;
1.1 deraadt 666:
667: if (TTYBYTES() == 0) {
1.18 guenther 668: (void) poll(pfd, 1, INFTIM); /* wait for TTLOWAT */
1.1 deraadt 669: } else {
670: while (TTYBYTES()) {
671: (void) ttyflush(0);
1.18 guenther 672: (void) poll(pfd, 1, INFTIM); /* wait for TTLOWAT */
1.1 deraadt 673: }
674: }
675: }
676:
677: void
678: SetForExit()
679: {
680: setconnmode(0);
681: do {
682: (void)telrcv(); /* Process any incoming data */
683: EmptyTerminal();
684: } while (ring_full_count(&netiring)); /* While there is any */
685: setcommandmode();
686: fflush(stdout);
687: fflush(stderr);
688: setconnmode(0);
689: EmptyTerminal(); /* Flush the path to the tty */
690: setcommandmode();
691: }
692:
693: void
694: Exit(returnCode)
695: int returnCode;
696: {
697: SetForExit();
698: exit(returnCode);
699: }
700:
701: void
702: ExitString(string, returnCode)
703: char *string;
704: int returnCode;
705: {
706: SetForExit();
707: fwrite(string, 1, strlen(string), stderr);
708: exit(returnCode);
709: }