Annotation of src/usr.bin/telnet/sys_bsd.c, Revision 1.23
1.23 ! guenther 1: /* $OpenBSD: sys_bsd.c,v 1.22 2014/07/20 09:31:25 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:
566: /* ARGSUSED */
1.5 art 567: void
1.1 deraadt 568: deadpeer(sig)
569: int sig;
570: {
571: setcommandmode();
572: longjmp(peerdied, -1);
573: }
574:
575: /* ARGSUSED */
1.5 art 576: void
1.1 deraadt 577: intr(sig)
578: int sig;
579: {
580: if (localchars) {
581: intp();
582: return;
583: }
584: setcommandmode();
585: longjmp(toplevel, -1);
586: }
587:
588: /* ARGSUSED */
1.5 art 589: void
1.1 deraadt 590: intr2(sig)
591: int sig;
592: {
593: if (localchars) {
594: #ifdef KLUDGELINEMODE
595: if (kludgelinemode)
596: sendbrk();
597: else
598: #endif
599: sendabort();
600: return;
601: }
602: }
603:
604: /* ARGSUSED */
1.5 art 605: void
1.1 deraadt 606: susp(sig)
607: int sig;
608: {
609: if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
610: return;
611: if (localchars)
612: sendsusp();
613: }
614:
615: #ifdef SIGWINCH
616: /* ARGSUSED */
1.5 art 617: void
1.1 deraadt 618: sendwin(sig)
619: int sig;
620: {
621: if (connected) {
622: sendnaws();
623: }
624: }
625: #endif
626:
627: #ifdef SIGINFO
628: /* ARGSUSED */
1.5 art 629: void
1.1 deraadt 630: ayt(sig)
631: int sig;
632: {
633: if (connected)
634: sendayt();
635: else
636: ayt_status();
637: }
638: #endif
639:
640:
641: void
642: sys_telnet_init()
643: {
1.16 guenther 644: int one = 1;
645:
1.1 deraadt 646: (void) signal(SIGINT, intr);
647: (void) signal(SIGQUIT, intr2);
648: (void) signal(SIGPIPE, deadpeer);
649: #ifdef SIGWINCH
650: (void) signal(SIGWINCH, sendwin);
651: #endif
652: (void) signal(SIGTSTP, susp);
653: #ifdef SIGINFO
654: (void) signal(SIGINFO, ayt);
655: #endif
656:
657: setconnmode(0);
658:
659: NetNonblockingIO(net, 1);
660:
1.16 guenther 661: if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) {
662: perror("setsockopt");
1.1 deraadt 663: }
664: }
665:
666: /*
667: * Process rings -
668: *
669: * This routine tries to fill up/empty our various rings.
670: *
671: * The parameter specifies whether this is a poll operation,
672: * or a block-until-something-happens operation.
673: *
674: * The return value is 1 if something happened, 0 if not.
675: */
676:
677: int
1.15 millert 678: process_rings(netin, netout, netex, ttyin, ttyout, dopoll)
679: int dopoll; /* If 0, then block until something to do */
1.1 deraadt 680: {
1.10 mpech 681: int c;
1.1 deraadt 682: /* One wants to be a bit careful about setting returnValue
683: * to one, since a one implies we did some useful work,
684: * and therefore probably won't be called to block next
685: * time (TN3270 mode only).
686: */
687: int returnValue = 0;
1.15 millert 688: struct pollfd pfd[TELNET_FD_NUM];
689:
690: if (ttyout) {
691: pfd[TELNET_FD_TOUT].fd = tout;
692: pfd[TELNET_FD_TOUT].events = POLLOUT;
693: } else {
694: pfd[TELNET_FD_TOUT].fd = -1;
695: }
696: if (ttyin) {
697: pfd[TELNET_FD_TIN].fd = tin;
698: pfd[TELNET_FD_TIN].events = POLLIN;
699: } else {
700: pfd[TELNET_FD_TIN].fd = -1;
701: }
702: if (netout || netin || netex) {
703: pfd[TELNET_FD_NET].fd = net;
704: pfd[TELNET_FD_NET].events = 0;
705: if (netout)
706: pfd[TELNET_FD_NET].events |= POLLOUT;
707: if (netin)
708: pfd[TELNET_FD_NET].events |= POLLIN;
709: if (netex)
710: pfd[TELNET_FD_NET].events |= POLLRDBAND;
711: } else {
712: pfd[TELNET_FD_NET].fd = -1;
713: }
1.1 deraadt 714:
1.21 guenther 715: if ((c = poll(pfd, TELNET_FD_NUM, dopoll ? 0 : INFTIM)) < 0) {
1.1 deraadt 716: return 0;
717: }
718:
719: /*
720: * Any urgent data?
721: */
1.15 millert 722: if (pfd[TELNET_FD_NET].revents & POLLRDBAND) {
1.1 deraadt 723: SYNCHing = 1;
724: (void) ttyflush(1); /* flush already enqueued data */
725: }
726:
727: /*
728: * Something to read from the network...
729: */
1.15 millert 730: if (pfd[TELNET_FD_NET].revents & (POLLIN|POLLHUP)) {
1.1 deraadt 731: int canread;
732:
733: canread = ring_empty_consecutive(&netiring);
734: c = recv(net, (char *)netiring.supply, canread, 0);
735: if (c < 0 && errno == EWOULDBLOCK) {
736: c = 0;
737: } else if (c <= 0) {
738: return -1;
739: }
740: if (netdata) {
741: Dump('<', netiring.supply, c);
742: }
743: if (c)
744: ring_supplied(&netiring, c);
745: returnValue = 1;
746: }
747:
748: /*
749: * Something to read from the tty...
750: */
1.15 millert 751: if (pfd[TELNET_FD_TIN].revents & (POLLIN|POLLHUP)) {
1.19 guenther 752: c = read(tin, ttyiring.supply, ring_empty_consecutive(&ttyiring));
1.3 niklas 753: if (c < 0 && errno == EIO)
754: c = 0;
1.1 deraadt 755: if (c < 0 && errno == EWOULDBLOCK) {
756: c = 0;
757: } else {
1.5 art 758: /* EOF detection for line mode!!!! */
759: if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
760: /* must be an EOF... */
761: *ttyiring.supply = termEofChar;
762: c = 1;
763: }
764: if (c <= 0) {
1.1 deraadt 765: return -1;
766: }
767: if (termdata) {
768: Dump('<', ttyiring.supply, c);
769: }
770: ring_supplied(&ttyiring, c);
771: }
772: returnValue = 1; /* did something useful */
773: }
774:
1.15 millert 775: if (pfd[TELNET_FD_NET].revents & POLLOUT) {
1.1 deraadt 776: returnValue |= netflush();
777: }
1.15 millert 778: if (pfd[TELNET_FD_TOUT].revents & POLLOUT) {
1.1 deraadt 779: returnValue |= (ttyflush(SYNCHing|flushout) > 0);
780: }
781:
782: return returnValue;
783: }