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