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