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