Annotation of src/usr.bin/telnet/utilities.c, Revision 1.16
1.16 ! guenther 1: /* $OpenBSD: utilities.c,v 1.15 2014/07/20 07:34:43 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:
47: FILE *NetTrace = 0; /* Not in bss, since needs to stay */
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: extern char will_wont_resp[], do_dont_resp[];
181:
182: for (i = 0; i < 256; i++) {
183: if (do_dont_resp[i]) {
184: if (TELOPT_OK(i))
185: printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
186: else if (TELCMD_OK(i))
187: printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
188: else
189: printf("resp DO_DONT %d: %d\n", i,
190: do_dont_resp[i]);
191: if (my_want_state_is_do(i)) {
192: if (TELOPT_OK(i))
193: printf("want DO %s\n", TELOPT(i));
194: else if (TELCMD_OK(i))
195: printf("want DO %s\n", TELCMD(i));
196: else
197: printf("want DO %d\n", i);
198: } else {
199: if (TELOPT_OK(i))
200: printf("want DONT %s\n", TELOPT(i));
201: else if (TELCMD_OK(i))
202: printf("want DONT %s\n", TELCMD(i));
203: else
204: printf("want DONT %d\n", i);
205: }
206: } else {
207: if (my_state_is_do(i)) {
208: if (TELOPT_OK(i))
209: printf(" DO %s\n", TELOPT(i));
210: else if (TELCMD_OK(i))
211: printf(" DO %s\n", TELCMD(i));
212: else
213: printf(" DO %d\n", i);
214: }
215: }
216: if (will_wont_resp[i]) {
217: if (TELOPT_OK(i))
218: printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
219: else if (TELCMD_OK(i))
220: printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
221: else
222: printf("resp WILL_WONT %d: %d\n",
223: i, will_wont_resp[i]);
224: if (my_want_state_is_will(i)) {
225: if (TELOPT_OK(i))
226: printf("want WILL %s\n", TELOPT(i));
227: else if (TELCMD_OK(i))
228: printf("want WILL %s\n", TELCMD(i));
229: else
230: printf("want WILL %d\n", i);
231: } else {
232: if (TELOPT_OK(i))
233: printf("want WONT %s\n", TELOPT(i));
234: else if (TELCMD_OK(i))
235: printf("want WONT %s\n", TELCMD(i));
236: else
237: printf("want WONT %d\n", i);
238: }
239: } else {
240: if (my_state_is_will(i)) {
241: if (TELOPT_OK(i))
242: printf(" WILL %s\n", TELOPT(i));
243: else if (TELCMD_OK(i))
244: printf(" WILL %s\n", TELCMD(i));
245: else
246: printf(" WILL %d\n", i);
247: }
248: }
249: }
250:
251: }
252:
253: void
254: printsub(direction, pointer, length)
255: char direction; /* '<' or '>' */
256: unsigned char *pointer; /* where suboption data sits */
257: int length; /* length of suboption data */
258: {
1.6 mpech 259: int i;
1.1 deraadt 260: extern int want_status_response;
261:
262: if (showoptions || direction == 0 ||
263: (want_status_response && (pointer[0] == TELOPT_STATUS))) {
264: if (direction) {
265: fprintf(NetTrace, "%s IAC SB ",
266: (direction == '<')? "RCVD":"SENT");
267: if (length >= 3) {
1.6 mpech 268: int j;
1.1 deraadt 269:
270: i = pointer[length-2];
271: j = pointer[length-1];
272:
273: if (i != IAC || j != SE) {
274: fprintf(NetTrace, "(terminated by ");
275: if (TELOPT_OK(i))
276: fprintf(NetTrace, "%s ", TELOPT(i));
277: else if (TELCMD_OK(i))
278: fprintf(NetTrace, "%s ", TELCMD(i));
279: else
280: fprintf(NetTrace, "%d ", i);
281: if (TELOPT_OK(j))
282: fprintf(NetTrace, "%s", TELOPT(j));
283: else if (TELCMD_OK(j))
284: fprintf(NetTrace, "%s", TELCMD(j));
285: else
286: fprintf(NetTrace, "%d", j);
287: fprintf(NetTrace, ", not IAC SE!) ");
288: }
289: }
290: length -= 2;
291: }
292: if (length < 1) {
293: fprintf(NetTrace, "(Empty suboption??\?)");
294: if (NetTrace == stdout)
295: fflush(NetTrace);
296: return;
297: }
298: switch (pointer[0]) {
299: case TELOPT_TTYPE:
300: fprintf(NetTrace, "TERMINAL-TYPE ");
301: switch (pointer[1]) {
302: case TELQUAL_IS:
303: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
304: break;
305: case TELQUAL_SEND:
306: fprintf(NetTrace, "SEND");
307: break;
308: default:
309: fprintf(NetTrace,
310: "- unknown qualifier %d (0x%x).",
311: pointer[1], pointer[1]);
312: }
313: break;
314: case TELOPT_TSPEED:
315: fprintf(NetTrace, "TERMINAL-SPEED");
316: if (length < 2) {
317: fprintf(NetTrace, " (empty suboption??\?)");
318: break;
319: }
320: switch (pointer[1]) {
321: case TELQUAL_IS:
322: fprintf(NetTrace, " IS ");
323: fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
324: break;
325: default:
326: if (pointer[1] == 1)
327: fprintf(NetTrace, " SEND");
328: else
329: fprintf(NetTrace, " %d (unknown)", pointer[1]);
330: for (i = 2; i < length; i++)
331: fprintf(NetTrace, " ?%d?", pointer[i]);
332: break;
333: }
334: break;
335:
336: case TELOPT_LFLOW:
337: fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
338: if (length < 2) {
339: fprintf(NetTrace, " (empty suboption??\?)");
340: break;
341: }
342: switch (pointer[1]) {
343: case LFLOW_OFF:
344: fprintf(NetTrace, " OFF"); break;
345: case LFLOW_ON:
346: fprintf(NetTrace, " ON"); break;
347: case LFLOW_RESTART_ANY:
348: fprintf(NetTrace, " RESTART-ANY"); break;
349: case LFLOW_RESTART_XON:
350: fprintf(NetTrace, " RESTART-XON"); break;
351: default:
352: fprintf(NetTrace, " %d (unknown)", pointer[1]);
353: }
354: for (i = 2; i < length; i++)
355: fprintf(NetTrace, " ?%d?", pointer[i]);
356: break;
357:
358: case TELOPT_NAWS:
359: fprintf(NetTrace, "NAWS");
360: if (length < 2) {
361: fprintf(NetTrace, " (empty suboption??\?)");
362: break;
363: }
364: if (length == 2) {
365: fprintf(NetTrace, " ?%d?", pointer[1]);
366: break;
367: }
368: fprintf(NetTrace, " %d %d (%d)",
369: pointer[1], pointer[2],
370: (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
371: if (length == 4) {
372: fprintf(NetTrace, " ?%d?", pointer[3]);
373: break;
374: }
375: fprintf(NetTrace, " %d %d (%d)",
376: pointer[3], pointer[4],
377: (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
378: for (i = 5; i < length; i++)
379: fprintf(NetTrace, " ?%d?", pointer[i]);
380: break;
381:
382: case TELOPT_LINEMODE:
383: fprintf(NetTrace, "LINEMODE ");
384: if (length < 2) {
385: fprintf(NetTrace, " (empty suboption??\?)");
386: break;
387: }
388: switch (pointer[1]) {
389: case WILL:
390: fprintf(NetTrace, "WILL ");
391: goto common;
392: case WONT:
393: fprintf(NetTrace, "WONT ");
394: goto common;
395: case DO:
396: fprintf(NetTrace, "DO ");
397: goto common;
398: case DONT:
399: fprintf(NetTrace, "DONT ");
400: common:
401: if (length < 3) {
402: fprintf(NetTrace, "(no option??\?)");
403: break;
404: }
405: switch (pointer[2]) {
406: case LM_FORWARDMASK:
407: fprintf(NetTrace, "Forward Mask");
408: for (i = 3; i < length; i++)
409: fprintf(NetTrace, " %x", pointer[i]);
410: break;
411: default:
412: fprintf(NetTrace, "%d (unknown)", pointer[2]);
413: for (i = 3; i < length; i++)
414: fprintf(NetTrace, " %d", pointer[i]);
415: break;
416: }
417: break;
1.2 niklas 418:
1.1 deraadt 419: case LM_SLC:
420: fprintf(NetTrace, "SLC");
421: for (i = 2; i < length - 2; i += 3) {
422: if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
423: fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
424: else
425: fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
426: switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
427: case SLC_NOSUPPORT:
428: fprintf(NetTrace, " NOSUPPORT"); break;
429: case SLC_CANTCHANGE:
430: fprintf(NetTrace, " CANTCHANGE"); break;
431: case SLC_VARIABLE:
432: fprintf(NetTrace, " VARIABLE"); break;
433: case SLC_DEFAULT:
434: fprintf(NetTrace, " DEFAULT"); break;
435: }
436: fprintf(NetTrace, "%s%s%s",
437: pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
438: pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
439: pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
440: if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
441: SLC_FLUSHOUT| SLC_LEVELBITS))
442: fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
443: fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
444: if ((pointer[i+SLC_VALUE] == IAC) &&
445: (pointer[i+SLC_VALUE+1] == IAC))
446: i++;
447: }
448: for (; i < length; i++)
449: fprintf(NetTrace, " ?%d?", pointer[i]);
450: break;
451:
452: case LM_MODE:
453: fprintf(NetTrace, "MODE ");
454: if (length < 3) {
455: fprintf(NetTrace, "(no mode??\?)");
456: break;
457: }
458: {
459: char tbuf[64];
1.5 art 460: snprintf(tbuf, sizeof(tbuf),
461: "%s%s%s%s%s",
462: pointer[2]&MODE_EDIT ? "|EDIT" : "",
463: pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
464: pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
465: pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
466: pointer[2]&MODE_ACK ? "|ACK" : "");
1.1 deraadt 467: fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
468: }
469: if (pointer[2]&~(MODE_MASK))
470: fprintf(NetTrace, " (0x%x)", pointer[2]);
471: for (i = 3; i < length; i++)
472: fprintf(NetTrace, " ?0x%x?", pointer[i]);
473: break;
474: default:
475: fprintf(NetTrace, "%d (unknown)", pointer[1]);
476: for (i = 2; i < length; i++)
477: fprintf(NetTrace, " %d", pointer[i]);
478: }
479: break;
480:
481: case TELOPT_STATUS: {
1.6 mpech 482: char *cp;
483: int j, k;
1.1 deraadt 484:
485: fprintf(NetTrace, "STATUS");
486:
487: switch (pointer[1]) {
488: default:
489: if (pointer[1] == TELQUAL_SEND)
490: fprintf(NetTrace, " SEND");
491: else
492: fprintf(NetTrace, " %d (unknown)", pointer[1]);
493: for (i = 2; i < length; i++)
494: fprintf(NetTrace, " ?%d?", pointer[i]);
495: break;
496: case TELQUAL_IS:
497: if (--want_status_response < 0)
498: want_status_response = 0;
499: if (NetTrace == stdout)
500: fprintf(NetTrace, " IS\r\n");
501: else
502: fprintf(NetTrace, " IS\n");
503:
504: for (i = 2; i < length; i++) {
505: switch(pointer[i]) {
506: case DO: cp = "DO"; goto common2;
507: case DONT: cp = "DONT"; goto common2;
508: case WILL: cp = "WILL"; goto common2;
509: case WONT: cp = "WONT"; goto common2;
510: common2:
511: i++;
512: if (TELOPT_OK((int)pointer[i]))
513: fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
514: else
515: fprintf(NetTrace, " %s %d", cp, pointer[i]);
516:
517: if (NetTrace == stdout)
518: fprintf(NetTrace, "\r\n");
519: else
520: fprintf(NetTrace, "\n");
521: break;
522:
523: case SB:
524: fprintf(NetTrace, " SB ");
525: i++;
526: j = k = i;
527: while (j < length) {
528: if (pointer[j] == SE) {
529: if (j+1 == length)
530: break;
531: if (pointer[j+1] == SE)
532: j++;
533: else
534: break;
535: }
536: pointer[k++] = pointer[j++];
537: }
538: printsub(0, &pointer[i], k - i);
539: if (i < length) {
540: fprintf(NetTrace, " SE");
541: i = j;
542: } else
543: i = j - 1;
544:
545: if (NetTrace == stdout)
546: fprintf(NetTrace, "\r\n");
547: else
548: fprintf(NetTrace, "\n");
549:
550: break;
1.2 niklas 551:
1.1 deraadt 552: default:
553: fprintf(NetTrace, " %d", pointer[i]);
554: break;
555: }
556: }
557: break;
558: }
559: break;
560: }
561:
562: case TELOPT_XDISPLOC:
563: fprintf(NetTrace, "X-DISPLAY-LOCATION ");
564: switch (pointer[1]) {
565: case TELQUAL_IS:
566: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
567: break;
568: case TELQUAL_SEND:
569: fprintf(NetTrace, "SEND");
570: break;
571: default:
572: fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
573: pointer[1], pointer[1]);
574: }
575: break;
576:
577: case TELOPT_NEW_ENVIRON:
578: fprintf(NetTrace, "NEW-ENVIRON ");
579: switch (pointer[1]) {
580: case TELQUAL_IS:
581: fprintf(NetTrace, "IS ");
582: goto env_common;
583: case TELQUAL_SEND:
584: fprintf(NetTrace, "SEND ");
585: goto env_common;
586: case TELQUAL_INFO:
587: fprintf(NetTrace, "INFO ");
588: env_common:
589: {
1.6 mpech 590: int noquote = 2;
1.1 deraadt 591: for (i = 2; i < length; i++ ) {
592: switch (pointer[i]) {
593: case NEW_ENV_VALUE:
594: fprintf(NetTrace, "\" VALUE " + noquote);
595: noquote = 2;
596: break;
597:
598: case NEW_ENV_VAR:
599: fprintf(NetTrace, "\" VAR " + noquote);
600: noquote = 2;
601: break;
602:
603: case ENV_ESC:
604: fprintf(NetTrace, "\" ESC " + noquote);
605: noquote = 2;
606: break;
607:
608: case ENV_USERVAR:
609: fprintf(NetTrace, "\" USERVAR " + noquote);
610: noquote = 2;
611: break;
612:
613: default:
1.14 guenther 614: if (isprint((unsigned char)pointer[i]) &&
615: pointer[i] != '"') {
1.1 deraadt 616: if (noquote) {
617: putc('"', NetTrace);
618: noquote = 0;
619: }
620: putc(pointer[i], NetTrace);
621: } else {
622: fprintf(NetTrace, "\" %03o " + noquote,
623: pointer[i]);
624: noquote = 2;
625: }
626: break;
627: }
628: }
629: if (!noquote)
630: putc('"', NetTrace);
631: break;
632: }
633: }
634: break;
635:
636: default:
637: if (TELOPT_OK(pointer[0]))
638: fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
639: else
640: fprintf(NetTrace, "%d (unknown)", pointer[0]);
641: for (i = 1; i < length; i++)
642: fprintf(NetTrace, " %d", pointer[i]);
643: break;
644: }
645: if (direction) {
646: if (NetTrace == stdout)
647: fprintf(NetTrace, "\r\n");
648: else
649: fprintf(NetTrace, "\n");
650: }
651: if (NetTrace == stdout)
652: fflush(NetTrace);
653: }
654: }
655:
656: /* EmptyTerminal - called to make sure that the terminal buffer is empty.
657: * Note that we consider the buffer to run all the
1.11 millert 658: * way to the kernel (thus the poll).
1.1 deraadt 659: */
660:
661: void
662: EmptyTerminal()
663: {
1.11 millert 664: struct pollfd pfd[1];
1.1 deraadt 665:
1.11 millert 666: pfd[0].fd = tout;
667: pfd[0].events = POLLOUT;
1.1 deraadt 668:
669: if (TTYBYTES() == 0) {
1.11 millert 670: (void) poll(pfd, 1, -1); /* wait for TTLOWAT */
1.1 deraadt 671: } else {
672: while (TTYBYTES()) {
673: (void) ttyflush(0);
1.11 millert 674: (void) poll(pfd, 1, -1); /* wait for TTLOWAT */
1.1 deraadt 675: }
676: }
677: }
678:
679: void
680: SetForExit()
681: {
682: setconnmode(0);
683: do {
684: (void)telrcv(); /* Process any incoming data */
685: EmptyTerminal();
686: } while (ring_full_count(&netiring)); /* While there is any */
687: setcommandmode();
688: fflush(stdout);
689: fflush(stderr);
690: setconnmode(0);
691: EmptyTerminal(); /* Flush the path to the tty */
692: setcommandmode();
693: }
694:
695: void
696: Exit(returnCode)
697: int returnCode;
698: {
699: SetForExit();
700: exit(returnCode);
701: }
702:
703: void
704: ExitString(string, returnCode)
705: char *string;
706: int returnCode;
707: {
708: SetForExit();
709: fwrite(string, 1, strlen(string), stderr);
710: exit(returnCode);
711: }