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