Annotation of src/usr.bin/telnet/sys_bsd.c, Revision 1.24
1.24 ! guenther 1: /* $OpenBSD: sys_bsd.c,v 1.23 2014/07/20 09:59:42 guenther Exp $ */
1.3 niklas 2: /* $NetBSD: sys_bsd.c,v 1.11 1996/02/28 21:04:10 thorpej Exp $ */
3:
1.1 deraadt 4: /*
5: * Copyright (c) 1988, 1990, 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.14 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.5 art 33: #include "telnet_locl.h"
1.18 guenther 34:
1.17 guenther 35: #include <sys/ioctl.h>
1.20 guenther 36: #include <sys/socket.h>
37: #include <arpa/telnet.h>
38: #include <errno.h>
1.17 guenther 39: #include <poll.h>
1.20 guenther 40: #include <string.h>
1.18 guenther 41: #include <unistd.h>
1.1 deraadt 42:
43: /*
44: * The following routines try to encapsulate what is system dependent
45: * (at least between 4.x and dos) which is used in telnet.c.
46: */
47:
48: int
49: tout, /* Output file descriptor */
50: tin, /* Input file descriptor */
51: net;
52:
1.15 millert 53: #define TELNET_FD_TOUT 0
54: #define TELNET_FD_TIN 1
55: #define TELNET_FD_NET 2
56: #define TELNET_FD_NUM 3
57:
1.5 art 58: struct termios old_tc = { 0 };
59: extern struct termios new_tc;
1.1 deraadt 60:
61: void
62: init_sys()
63: {
64: tout = fileno(stdout);
65: tin = fileno(stdin);
66:
67: errno = 0;
68: }
69:
70:
71: #ifdef KLUDGELINEMODE
72: extern int kludgelinemode;
73: #endif
74: /*
75: * TerminalSpecialChars()
76: *
77: * Look at an input character to see if it is a special character
78: * and decide what to do.
79: *
80: * Output:
81: *
82: * 0 Don't add this character.
83: * 1 Do add this character
84: */
85:
86: int
87: TerminalSpecialChars(c)
88: int c;
89: {
90: if (c == termIntChar) {
91: intp();
92: return 0;
93: } else if (c == termQuitChar) {
94: #ifdef KLUDGELINEMODE
95: if (kludgelinemode)
96: sendbrk();
97: else
98: #endif
99: sendabort();
100: return 0;
101: } else if (c == termEofChar) {
102: if (my_want_state_is_will(TELOPT_LINEMODE)) {
103: sendeof();
104: return 0;
105: }
106: return 1;
107: } else if (c == termSuspChar) {
108: sendsusp();
109: return(0);
110: } else if (c == termFlushChar) {
111: xmitAO(); /* Transmit Abort Output */
112: return 0;
113: } else if (!MODE_LOCAL_CHARS(globalmode)) {
114: if (c == termKillChar) {
115: xmitEL();
116: return 0;
117: } else if (c == termEraseChar) {
118: xmitEC(); /* Transmit Erase Character */
119: return 0;
120: }
121: }
122: return 1;
123: }
124:
125: void
126: TerminalSaveState()
127: {
128: tcgetattr(0, &old_tc);
129:
130: new_tc = old_tc;
131:
132: #ifndef VDISCARD
133: termFlushChar = CONTROL('O');
134: #endif
135: #ifndef VWERASE
136: termWerasChar = CONTROL('W');
137: #endif
138: #ifndef VREPRINT
139: termRprntChar = CONTROL('R');
140: #endif
141: #ifndef VLNEXT
142: termLiteralNextChar = CONTROL('V');
143: #endif
144: #ifndef VSTART
145: termStartChar = CONTROL('Q');
146: #endif
147: #ifndef VSTOP
148: termStopChar = CONTROL('S');
149: #endif
150: #ifndef VSTATUS
151: termAytChar = CONTROL('T');
152: #endif
153: }
154:
155: cc_t *
156: tcval(func)
1.10 mpech 157: int func;
1.1 deraadt 158: {
159: switch(func) {
160: case SLC_IP: return(&termIntChar);
161: case SLC_ABORT: return(&termQuitChar);
162: case SLC_EOF: return(&termEofChar);
163: case SLC_EC: return(&termEraseChar);
164: case SLC_EL: return(&termKillChar);
165: case SLC_XON: return(&termStartChar);
166: case SLC_XOFF: return(&termStopChar);
167: case SLC_FORW1: return(&termForw1Char);
168: case SLC_FORW2: return(&termForw2Char);
1.22 guenther 169: case SLC_SUSP: return(&termSuspChar);
1.1 deraadt 170: # ifdef VDISCARD
171: case SLC_AO: return(&termFlushChar);
172: # endif
173: # ifdef VWERASE
174: case SLC_EW: return(&termWerasChar);
175: # endif
176: # ifdef VREPRINT
177: case SLC_RP: return(&termRprntChar);
178: # endif
179: # ifdef VLNEXT
180: case SLC_LNEXT: return(&termLiteralNextChar);
181: # endif
182: # ifdef VSTATUS
183: case SLC_AYT: return(&termAytChar);
184: # endif
185:
186: case SLC_SYNCH:
187: case SLC_BRK:
188: case SLC_EOR:
189: default:
190: return((cc_t *)0);
191: }
192: }
193:
194: void
195: TerminalDefaultChars()
196: {
1.23 guenther 197: memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
1.1 deraadt 198: # ifndef VDISCARD
199: termFlushChar = CONTROL('O');
200: # endif
201: # ifndef VWERASE
202: termWerasChar = CONTROL('W');
203: # endif
204: # ifndef VREPRINT
205: termRprntChar = CONTROL('R');
206: # endif
207: # ifndef VLNEXT
208: termLiteralNextChar = CONTROL('V');
209: # endif
210: # ifndef VSTART
211: termStartChar = CONTROL('Q');
212: # endif
213: # ifndef VSTOP
214: termStopChar = CONTROL('S');
215: # endif
216: # ifndef VSTATUS
217: termAytChar = CONTROL('T');
218: # endif
219: }
220:
221: /*
222: * TerminalNewMode - set up terminal to a specific mode.
223: * MODE_ECHO: do local terminal echo
224: * MODE_FLOW: do local flow control
225: * MODE_TRAPSIG: do local mapping to TELNET IAC sequences
226: * MODE_EDIT: do local line editing
227: *
228: * Command mode:
229: * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
230: * local echo
231: * local editing
232: * local xon/xoff
233: * local signal mapping
234: *
235: * Linemode:
236: * local/no editing
237: * Both Linemode and Single Character mode:
238: * local/remote echo
239: * local/no xon/xoff
240: * local/no signal mapping
241: */
242:
1.5 art 243: static void susp();
244: #ifdef SIGINFO
245: static void ayt();
246: #endif
1.1 deraadt 247:
248: void
249: TerminalNewMode(f)
1.10 mpech 250: int f;
1.1 deraadt 251: {
252: static int prevmode = 0;
1.5 art 253: struct termios tmp_tc;
1.1 deraadt 254: int onoff;
255: int old;
256: cc_t esc;
257:
258: globalmode = f&~MODE_FORCE;
259: if (prevmode == f)
260: return;
261:
262: /*
263: * Write any outstanding data before switching modes
264: * ttyflush() returns 0 only when there is no more data
265: * left to write out, it returns -1 if it couldn't do
266: * anything at all, otherwise it returns 1 + the number
267: * of characters left to write.
268: */
269: old = ttyflush(SYNCHing|flushout);
270: if (old < 0 || old > 1) {
271: tcgetattr(tin, &tmp_tc);
272: do {
273: /*
274: * Wait for data to drain, then flush again.
275: */
276: tcsetattr(tin, TCSADRAIN, &tmp_tc);
277: old = ttyflush(SYNCHing|flushout);
278: } while (old < 0 || old > 1);
279: }
280:
281: old = prevmode;
282: prevmode = f&~MODE_FORCE;
283: tmp_tc = new_tc;
284:
285: if (f&MODE_ECHO) {
286: tmp_tc.c_lflag |= ECHO;
287: tmp_tc.c_oflag |= ONLCR;
288: if (crlf)
289: tmp_tc.c_iflag |= ICRNL;
290: } else {
291: tmp_tc.c_lflag &= ~ECHO;
292: tmp_tc.c_oflag &= ~ONLCR;
293: }
294:
295: if ((f&MODE_FLOW) == 0) {
296: tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
297: } else {
298: if (restartany < 0) {
299: tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */
300: } else if (restartany > 0) {
301: tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
302: } else {
303: tmp_tc.c_iflag |= IXOFF|IXON;
304: tmp_tc.c_iflag &= ~IXANY;
305: }
306: }
307:
308: if ((f&MODE_TRAPSIG) == 0) {
309: tmp_tc.c_lflag &= ~ISIG;
310: localchars = 0;
311: } else {
312: tmp_tc.c_lflag |= ISIG;
313: localchars = 1;
314: }
315:
316: if (f&MODE_EDIT) {
317: tmp_tc.c_lflag |= ICANON;
318: } else {
319: tmp_tc.c_lflag &= ~ICANON;
320: tmp_tc.c_iflag &= ~ICRNL;
321: tmp_tc.c_cc[VMIN] = 1;
322: tmp_tc.c_cc[VTIME] = 0;
323: }
324:
325: if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
1.2 niklas 326: tmp_tc.c_lflag &= ~IEXTEN;
1.1 deraadt 327: }
328:
329: if (f&MODE_SOFT_TAB) {
330: # ifdef OXTABS
331: tmp_tc.c_oflag |= OXTABS;
332: # endif
333: # ifdef TABDLY
334: tmp_tc.c_oflag &= ~TABDLY;
335: tmp_tc.c_oflag |= TAB3;
336: # endif
337: } else {
338: # ifdef OXTABS
339: tmp_tc.c_oflag &= ~OXTABS;
340: # endif
341: # ifdef TABDLY
342: tmp_tc.c_oflag &= ~TABDLY;
343: # endif
344: }
345:
346: if (f&MODE_LIT_ECHO) {
347: # ifdef ECHOCTL
348: tmp_tc.c_lflag &= ~ECHOCTL;
349: # endif
350: } else {
351: # ifdef ECHOCTL
352: tmp_tc.c_lflag |= ECHOCTL;
353: # endif
354: }
355:
356: if (f == -1) {
357: onoff = 0;
358: } else {
359: if (f & MODE_INBIN)
360: tmp_tc.c_iflag &= ~ISTRIP;
361: else
362: tmp_tc.c_iflag |= ISTRIP;
1.5 art 363: if ((f & MODE_OUTBIN) || (f & MODE_OUT8)) {
1.1 deraadt 364: tmp_tc.c_cflag &= ~(CSIZE|PARENB);
365: tmp_tc.c_cflag |= CS8;
1.5 art 366: if(f & MODE_OUTBIN)
367: tmp_tc.c_oflag &= ~OPOST;
368: else
369: tmp_tc.c_oflag |= OPOST;
370:
1.1 deraadt 371: } else {
372: tmp_tc.c_cflag &= ~(CSIZE|PARENB);
373: tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
374: tmp_tc.c_oflag |= OPOST;
375: }
376: onoff = 1;
377: }
378:
379: if (f != -1) {
380: (void) signal(SIGTSTP, susp);
381: #ifdef SIGINFO
382: (void) signal(SIGINFO, ayt);
383: #endif
1.16 guenther 384: #if defined(NOKERNINFO)
1.1 deraadt 385: tmp_tc.c_lflag |= NOKERNINFO;
386: #endif
387: /*
388: * We don't want to process ^Y here. It's just another
389: * character that we'll pass on to the back end. It has
390: * to process it because it will be processed when the
391: * user attempts to read it, not when we send it.
392: */
393: # ifdef VDSUSP
394: tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
395: # endif
396: /*
397: * If the VEOL character is already set, then use VEOL2,
398: * otherwise use VEOL.
399: */
400: esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
401: if ((tmp_tc.c_cc[VEOL] != esc)
402: # ifdef VEOL2
403: && (tmp_tc.c_cc[VEOL2] != esc)
404: # endif
405: ) {
406: if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
407: tmp_tc.c_cc[VEOL] = esc;
408: # ifdef VEOL2
409: else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
410: tmp_tc.c_cc[VEOL2] = esc;
411: # endif
412: }
413: } else {
1.9 millert 414: sigset_t mask;
1.1 deraadt 415: #ifdef SIGINFO
1.5 art 416: void ayt_status();
1.1 deraadt 417:
1.5 art 418: (void) signal(SIGINFO, (void (*)(int))ayt_status);
1.1 deraadt 419: #endif
420: (void) signal(SIGTSTP, SIG_DFL);
1.9 millert 421: sigemptyset(&mask);
422: sigaddset(&mask, SIGTSTP);
423: sigprocmask(SIG_UNBLOCK, &mask, NULL);
1.1 deraadt 424: tmp_tc = old_tc;
425: }
426: if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
427: tcsetattr(tin, TCSANOW, &tmp_tc);
428:
429: ioctl(tin, FIONBIO, (char *)&onoff);
430: ioctl(tout, FIONBIO, (char *)&onoff);
431: }
432:
1.3 niklas 433: /*
434: * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
435: */
436: #if B4800 != 4800
437: #define DECODE_BAUD
438: #endif
439:
440: #ifdef DECODE_BAUD
441: #ifndef B7200
442: #define B7200 B4800
443: #endif
444:
445: #ifndef B14400
446: #define B14400 B9600
447: #endif
448:
1.1 deraadt 449: #ifndef B19200
1.3 niklas 450: # define B19200 B14400
451: #endif
452:
453: #ifndef B28800
454: #define B28800 B19200
1.1 deraadt 455: #endif
456:
457: #ifndef B38400
1.3 niklas 458: # define B38400 B28800
459: #endif
460:
461: #ifndef B57600
462: #define B57600 B38400
1.1 deraadt 463: #endif
464:
1.3 niklas 465: #ifndef B76800
466: #define B76800 B57600
467: #endif
468:
469: #ifndef B115200
470: #define B115200 B76800
471: #endif
472:
473: #ifndef B230400
474: #define B230400 B115200
475: #endif
476:
477:
1.1 deraadt 478: /*
479: * This code assumes that the values B0, B50, B75...
480: * are in ascending order. They do not have to be
481: * contiguous.
482: */
483: struct termspeeds {
484: long speed;
485: long value;
486: } termspeeds[] = {
1.3 niklas 487: { 0, B0 }, { 50, B50 }, { 75, B75 },
488: { 110, B110 }, { 134, B134 }, { 150, B150 },
489: { 200, B200 }, { 300, B300 }, { 600, B600 },
490: { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
491: { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 },
492: { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 },
493: { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 },
494: { 230400, B230400 }, { -1, B230400 }
1.1 deraadt 495: };
1.3 niklas 496: #endif /* DECODE_BAUD */
1.1 deraadt 497:
498: void
499: TerminalSpeeds(ispeed, ospeed)
500: long *ispeed;
501: long *ospeed;
502: {
1.3 niklas 503: #ifdef DECODE_BAUD
1.10 mpech 504: struct termspeeds *tp;
1.3 niklas 505: #endif /* DECODE_BAUD */
1.10 mpech 506: long in, out;
1.1 deraadt 507:
508: out = cfgetospeed(&old_tc);
509: in = cfgetispeed(&old_tc);
510: if (in == 0)
511: in = out;
512:
1.3 niklas 513: #ifdef DECODE_BAUD
1.1 deraadt 514: tp = termspeeds;
515: while ((tp->speed != -1) && (tp->value < in))
516: tp++;
517: *ispeed = tp->speed;
518:
519: tp = termspeeds;
520: while ((tp->speed != -1) && (tp->value < out))
521: tp++;
522: *ospeed = tp->speed;
1.3 niklas 523: #else /* DECODE_BAUD */
524: *ispeed = in;
525: *ospeed = out;
526: #endif /* DECODE_BAUD */
1.1 deraadt 527: }
528:
529: int
530: TerminalWindowSize(rows, cols)
531: long *rows, *cols;
532: {
533: #ifdef TIOCGWINSZ
534: struct winsize ws;
535:
536: if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
537: *rows = ws.ws_row;
538: *cols = ws.ws_col;
539: return 1;
540: }
541: #endif /* TIOCGWINSZ */
542: return 0;
543: }
544:
545: int
546: NetClose(fd)
547: int fd;
548: {
549: return close(fd);
550: }
551:
552:
553: void
554: NetNonblockingIO(fd, onoff)
555: int fd;
556: int onoff;
557: {
558: ioctl(fd, FIONBIO, (char *)&onoff);
559: }
560:
561:
562: /*
563: * Various signal handling routines.
564: */
565:
1.5 art 566: void
1.1 deraadt 567: deadpeer(sig)
568: int sig;
569: {
570: setcommandmode();
571: longjmp(peerdied, -1);
572: }
573:
1.5 art 574: void
1.1 deraadt 575: intr(sig)
576: int sig;
577: {
578: if (localchars) {
579: intp();
580: return;
581: }
582: setcommandmode();
583: longjmp(toplevel, -1);
584: }
585:
1.5 art 586: void
1.1 deraadt 587: intr2(sig)
588: int sig;
589: {
590: if (localchars) {
591: #ifdef KLUDGELINEMODE
592: if (kludgelinemode)
593: sendbrk();
594: else
595: #endif
596: sendabort();
597: return;
598: }
599: }
600:
1.5 art 601: void
1.1 deraadt 602: susp(sig)
603: int sig;
604: {
605: if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
606: return;
607: if (localchars)
608: sendsusp();
609: }
610:
611: #ifdef SIGWINCH
1.5 art 612: void
1.1 deraadt 613: sendwin(sig)
614: int sig;
615: {
616: if (connected) {
617: sendnaws();
618: }
619: }
620: #endif
621:
622: #ifdef SIGINFO
1.5 art 623: void
1.1 deraadt 624: ayt(sig)
625: int sig;
626: {
627: if (connected)
628: sendayt();
629: else
630: ayt_status();
631: }
632: #endif
633:
634:
635: void
636: sys_telnet_init()
637: {
1.16 guenther 638: int one = 1;
639:
1.1 deraadt 640: (void) signal(SIGINT, intr);
641: (void) signal(SIGQUIT, intr2);
642: (void) signal(SIGPIPE, deadpeer);
643: #ifdef SIGWINCH
644: (void) signal(SIGWINCH, sendwin);
645: #endif
646: (void) signal(SIGTSTP, susp);
647: #ifdef SIGINFO
648: (void) signal(SIGINFO, ayt);
649: #endif
650:
651: setconnmode(0);
652:
653: NetNonblockingIO(net, 1);
654:
1.16 guenther 655: if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) {
656: perror("setsockopt");
1.1 deraadt 657: }
658: }
659:
660: /*
661: * Process rings -
662: *
663: * This routine tries to fill up/empty our various rings.
664: *
665: * The parameter specifies whether this is a poll operation,
666: * or a block-until-something-happens operation.
667: *
668: * The return value is 1 if something happened, 0 if not.
669: */
670:
671: int
1.15 millert 672: process_rings(netin, netout, netex, ttyin, ttyout, dopoll)
673: int dopoll; /* If 0, then block until something to do */
1.1 deraadt 674: {
1.10 mpech 675: int c;
1.1 deraadt 676: /* One wants to be a bit careful about setting returnValue
677: * to one, since a one implies we did some useful work,
678: * and therefore probably won't be called to block next
679: * time (TN3270 mode only).
680: */
681: int returnValue = 0;
1.15 millert 682: struct pollfd pfd[TELNET_FD_NUM];
683:
684: if (ttyout) {
685: pfd[TELNET_FD_TOUT].fd = tout;
686: pfd[TELNET_FD_TOUT].events = POLLOUT;
687: } else {
688: pfd[TELNET_FD_TOUT].fd = -1;
689: }
690: if (ttyin) {
691: pfd[TELNET_FD_TIN].fd = tin;
692: pfd[TELNET_FD_TIN].events = POLLIN;
693: } else {
694: pfd[TELNET_FD_TIN].fd = -1;
695: }
696: if (netout || netin || netex) {
697: pfd[TELNET_FD_NET].fd = net;
698: pfd[TELNET_FD_NET].events = 0;
699: if (netout)
700: pfd[TELNET_FD_NET].events |= POLLOUT;
701: if (netin)
702: pfd[TELNET_FD_NET].events |= POLLIN;
703: if (netex)
704: pfd[TELNET_FD_NET].events |= POLLRDBAND;
705: } else {
706: pfd[TELNET_FD_NET].fd = -1;
707: }
1.1 deraadt 708:
1.21 guenther 709: if ((c = poll(pfd, TELNET_FD_NUM, dopoll ? 0 : INFTIM)) < 0) {
1.1 deraadt 710: return 0;
711: }
712:
713: /*
714: * Any urgent data?
715: */
1.15 millert 716: if (pfd[TELNET_FD_NET].revents & POLLRDBAND) {
1.1 deraadt 717: SYNCHing = 1;
718: (void) ttyflush(1); /* flush already enqueued data */
719: }
720:
721: /*
722: * Something to read from the network...
723: */
1.15 millert 724: if (pfd[TELNET_FD_NET].revents & (POLLIN|POLLHUP)) {
1.1 deraadt 725: int canread;
726:
727: canread = ring_empty_consecutive(&netiring);
728: c = recv(net, (char *)netiring.supply, canread, 0);
729: if (c < 0 && errno == EWOULDBLOCK) {
730: c = 0;
731: } else if (c <= 0) {
732: return -1;
733: }
734: if (netdata) {
735: Dump('<', netiring.supply, c);
736: }
737: if (c)
738: ring_supplied(&netiring, c);
739: returnValue = 1;
740: }
741:
742: /*
743: * Something to read from the tty...
744: */
1.15 millert 745: if (pfd[TELNET_FD_TIN].revents & (POLLIN|POLLHUP)) {
1.19 guenther 746: c = read(tin, ttyiring.supply, ring_empty_consecutive(&ttyiring));
1.3 niklas 747: if (c < 0 && errno == EIO)
748: c = 0;
1.1 deraadt 749: if (c < 0 && errno == EWOULDBLOCK) {
750: c = 0;
751: } else {
1.5 art 752: /* EOF detection for line mode!!!! */
753: if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
754: /* must be an EOF... */
755: *ttyiring.supply = termEofChar;
756: c = 1;
757: }
758: if (c <= 0) {
1.1 deraadt 759: return -1;
760: }
761: if (termdata) {
762: Dump('<', ttyiring.supply, c);
763: }
764: ring_supplied(&ttyiring, c);
765: }
766: returnValue = 1; /* did something useful */
767: }
768:
1.15 millert 769: if (pfd[TELNET_FD_NET].revents & POLLOUT) {
1.1 deraadt 770: returnValue |= netflush();
771: }
1.15 millert 772: if (pfd[TELNET_FD_TOUT].revents & POLLOUT) {
1.1 deraadt 773: returnValue |= (ttyflush(SYNCHing|flushout) > 0);
774: }
775:
776: return returnValue;
777: }