Annotation of src/usr.bin/telnet/sys_bsd.c, Revision 1.19
1.19 ! guenther 1: /* $OpenBSD: sys_bsd.c,v 1.18 2014/07/20 06:39:41 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>
36: #include <poll.h>
1.18 guenther 37: #include <unistd.h>
1.1 deraadt 38:
39: /*
40: * The following routines try to encapsulate what is system dependent
41: * (at least between 4.x and dos) which is used in telnet.c.
42: */
43:
44: int
45: tout, /* Output file descriptor */
46: tin, /* Input file descriptor */
47: net;
48:
1.15 millert 49: #define TELNET_FD_TOUT 0
50: #define TELNET_FD_TIN 1
51: #define TELNET_FD_NET 2
52: #define TELNET_FD_NUM 3
53:
1.5 art 54: struct termios old_tc = { 0 };
55: extern struct termios new_tc;
1.1 deraadt 56:
57: void
58: init_sys()
59: {
60: tout = fileno(stdout);
61: tin = fileno(stdin);
62:
63: errno = 0;
64: }
65:
66:
67: #ifdef KLUDGELINEMODE
68: extern int kludgelinemode;
69: #endif
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);
165: # ifdef VDISCARD
166: case SLC_AO: return(&termFlushChar);
167: # endif
168: # ifdef VSUSP
169: case SLC_SUSP: return(&termSuspChar);
170: # endif
171: # ifdef VWERASE
172: case SLC_EW: return(&termWerasChar);
173: # endif
174: # ifdef VREPRINT
175: case SLC_RP: return(&termRprntChar);
176: # endif
177: # ifdef VLNEXT
178: case SLC_LNEXT: return(&termLiteralNextChar);
179: # endif
180: # ifdef VSTATUS
181: case SLC_AYT: return(&termAytChar);
182: # endif
183:
184: case SLC_SYNCH:
185: case SLC_BRK:
186: case SLC_EOR:
187: default:
188: return((cc_t *)0);
189: }
190: }
191:
192: void
193: TerminalDefaultChars()
194: {
1.3 niklas 195: memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
1.1 deraadt 196: # ifndef VDISCARD
197: termFlushChar = CONTROL('O');
198: # endif
199: # ifndef VWERASE
200: termWerasChar = CONTROL('W');
201: # endif
202: # ifndef VREPRINT
203: termRprntChar = CONTROL('R');
204: # endif
205: # ifndef VLNEXT
206: termLiteralNextChar = CONTROL('V');
207: # endif
208: # ifndef VSTART
209: termStartChar = CONTROL('Q');
210: # endif
211: # ifndef VSTOP
212: termStopChar = CONTROL('S');
213: # endif
214: # ifndef VSTATUS
215: termAytChar = CONTROL('T');
216: # endif
217: }
218:
219: /*
220: * TerminalNewMode - set up terminal to a specific mode.
221: * MODE_ECHO: do local terminal echo
222: * MODE_FLOW: do local flow control
223: * MODE_TRAPSIG: do local mapping to TELNET IAC sequences
224: * MODE_EDIT: do local line editing
225: *
226: * Command mode:
227: * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
228: * local echo
229: * local editing
230: * local xon/xoff
231: * local signal mapping
232: *
233: * Linemode:
234: * local/no editing
235: * Both Linemode and Single Character mode:
236: * local/remote echo
237: * local/no xon/xoff
238: * local/no signal mapping
239: */
240:
1.5 art 241: #ifdef SIGTSTP
242: static void susp();
243: #endif /* SIGTSTP */
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: #ifdef SIGTSTP
381: (void) signal(SIGTSTP, susp);
382: #endif /* SIGTSTP */
383: #ifdef SIGINFO
384: (void) signal(SIGINFO, ayt);
385: #endif
1.16 guenther 386: #if defined(NOKERNINFO)
1.1 deraadt 387: tmp_tc.c_lflag |= NOKERNINFO;
388: #endif
389: /*
390: * We don't want to process ^Y here. It's just another
391: * character that we'll pass on to the back end. It has
392: * to process it because it will be processed when the
393: * user attempts to read it, not when we send it.
394: */
395: # ifdef VDSUSP
396: tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
397: # endif
398: /*
399: * If the VEOL character is already set, then use VEOL2,
400: * otherwise use VEOL.
401: */
402: esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
403: if ((tmp_tc.c_cc[VEOL] != esc)
404: # ifdef VEOL2
405: && (tmp_tc.c_cc[VEOL2] != esc)
406: # endif
407: ) {
408: if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
409: tmp_tc.c_cc[VEOL] = esc;
410: # ifdef VEOL2
411: else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
412: tmp_tc.c_cc[VEOL2] = esc;
413: # endif
414: }
415: } else {
1.9 millert 416: #ifdef SIGTSTP
417: sigset_t mask;
418: #endif /* SIGTSTP */
1.1 deraadt 419: #ifdef SIGINFO
1.5 art 420: void ayt_status();
1.1 deraadt 421:
1.5 art 422: (void) signal(SIGINFO, (void (*)(int))ayt_status);
1.1 deraadt 423: #endif
424: #ifdef SIGTSTP
425: (void) signal(SIGTSTP, SIG_DFL);
1.9 millert 426: sigemptyset(&mask);
427: sigaddset(&mask, SIGTSTP);
428: sigprocmask(SIG_UNBLOCK, &mask, NULL);
1.1 deraadt 429: #endif /* SIGTSTP */
430: tmp_tc = old_tc;
431: }
432: if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
433: tcsetattr(tin, TCSANOW, &tmp_tc);
434:
435: ioctl(tin, FIONBIO, (char *)&onoff);
436: ioctl(tout, FIONBIO, (char *)&onoff);
437: }
438:
1.3 niklas 439: /*
440: * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
441: */
442: #if B4800 != 4800
443: #define DECODE_BAUD
444: #endif
445:
446: #ifdef DECODE_BAUD
447: #ifndef B7200
448: #define B7200 B4800
449: #endif
450:
451: #ifndef B14400
452: #define B14400 B9600
453: #endif
454:
1.1 deraadt 455: #ifndef B19200
1.3 niklas 456: # define B19200 B14400
457: #endif
458:
459: #ifndef B28800
460: #define B28800 B19200
1.1 deraadt 461: #endif
462:
463: #ifndef B38400
1.3 niklas 464: # define B38400 B28800
465: #endif
466:
467: #ifndef B57600
468: #define B57600 B38400
1.1 deraadt 469: #endif
470:
1.3 niklas 471: #ifndef B76800
472: #define B76800 B57600
473: #endif
474:
475: #ifndef B115200
476: #define B115200 B76800
477: #endif
478:
479: #ifndef B230400
480: #define B230400 B115200
481: #endif
482:
483:
1.1 deraadt 484: /*
485: * This code assumes that the values B0, B50, B75...
486: * are in ascending order. They do not have to be
487: * contiguous.
488: */
489: struct termspeeds {
490: long speed;
491: long value;
492: } termspeeds[] = {
1.3 niklas 493: { 0, B0 }, { 50, B50 }, { 75, B75 },
494: { 110, B110 }, { 134, B134 }, { 150, B150 },
495: { 200, B200 }, { 300, B300 }, { 600, B600 },
496: { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
497: { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 },
498: { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 },
499: { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 },
500: { 230400, B230400 }, { -1, B230400 }
1.1 deraadt 501: };
1.3 niklas 502: #endif /* DECODE_BAUD */
1.1 deraadt 503:
504: void
505: TerminalSpeeds(ispeed, ospeed)
506: long *ispeed;
507: long *ospeed;
508: {
1.3 niklas 509: #ifdef DECODE_BAUD
1.10 mpech 510: struct termspeeds *tp;
1.3 niklas 511: #endif /* DECODE_BAUD */
1.10 mpech 512: long in, out;
1.1 deraadt 513:
514: out = cfgetospeed(&old_tc);
515: in = cfgetispeed(&old_tc);
516: if (in == 0)
517: in = out;
518:
1.3 niklas 519: #ifdef DECODE_BAUD
1.1 deraadt 520: tp = termspeeds;
521: while ((tp->speed != -1) && (tp->value < in))
522: tp++;
523: *ispeed = tp->speed;
524:
525: tp = termspeeds;
526: while ((tp->speed != -1) && (tp->value < out))
527: tp++;
528: *ospeed = tp->speed;
1.3 niklas 529: #else /* DECODE_BAUD */
530: *ispeed = in;
531: *ospeed = out;
532: #endif /* DECODE_BAUD */
1.1 deraadt 533: }
534:
535: int
536: TerminalWindowSize(rows, cols)
537: long *rows, *cols;
538: {
539: #ifdef TIOCGWINSZ
540: struct winsize ws;
541:
542: if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
543: *rows = ws.ws_row;
544: *cols = ws.ws_col;
545: return 1;
546: }
547: #endif /* TIOCGWINSZ */
548: return 0;
549: }
550:
551: int
552: NetClose(fd)
553: int fd;
554: {
555: return close(fd);
556: }
557:
558:
559: void
560: NetNonblockingIO(fd, onoff)
561: int fd;
562: int onoff;
563: {
564: ioctl(fd, FIONBIO, (char *)&onoff);
565: }
566:
567:
568: /*
569: * Various signal handling routines.
570: */
571:
572: /* ARGSUSED */
1.5 art 573: void
1.1 deraadt 574: deadpeer(sig)
575: int sig;
576: {
577: setcommandmode();
578: longjmp(peerdied, -1);
579: }
580:
1.12 hin 581: volatile sig_atomic_t intr_happened = 0;
582: volatile sig_atomic_t intr_waiting = 0;
1.11 hin 583:
1.1 deraadt 584: /* ARGSUSED */
1.5 art 585: void
1.1 deraadt 586: intr(sig)
587: int sig;
588: {
1.11 hin 589: if (intr_waiting) {
590: intr_happened = 1;
591: return;
592: }
1.1 deraadt 593: if (localchars) {
594: intp();
595: return;
596: }
597: setcommandmode();
598: longjmp(toplevel, -1);
599: }
600:
601: /* ARGSUSED */
1.5 art 602: void
1.1 deraadt 603: intr2(sig)
604: int sig;
605: {
606: if (localchars) {
607: #ifdef KLUDGELINEMODE
608: if (kludgelinemode)
609: sendbrk();
610: else
611: #endif
612: sendabort();
613: return;
614: }
615: }
616:
617: #ifdef SIGTSTP
618: /* ARGSUSED */
1.5 art 619: void
1.1 deraadt 620: susp(sig)
621: int sig;
622: {
623: if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
624: return;
625: if (localchars)
626: sendsusp();
627: }
628: #endif
629:
630: #ifdef SIGWINCH
631: /* ARGSUSED */
1.5 art 632: void
1.1 deraadt 633: sendwin(sig)
634: int sig;
635: {
636: if (connected) {
637: sendnaws();
638: }
639: }
640: #endif
641:
642: #ifdef SIGINFO
643: /* ARGSUSED */
1.5 art 644: void
1.1 deraadt 645: ayt(sig)
646: int sig;
647: {
648: if (connected)
649: sendayt();
650: else
651: ayt_status();
652: }
653: #endif
654:
655:
656: void
657: sys_telnet_init()
658: {
1.16 guenther 659: int one = 1;
660:
1.1 deraadt 661: (void) signal(SIGINT, intr);
662: (void) signal(SIGQUIT, intr2);
663: (void) signal(SIGPIPE, deadpeer);
664: #ifdef SIGWINCH
665: (void) signal(SIGWINCH, sendwin);
666: #endif
667: #ifdef SIGTSTP
668: (void) signal(SIGTSTP, susp);
669: #endif
670: #ifdef SIGINFO
671: (void) signal(SIGINFO, ayt);
672: #endif
673:
674: setconnmode(0);
675:
676: NetNonblockingIO(net, 1);
677:
1.16 guenther 678: if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) {
679: perror("setsockopt");
1.1 deraadt 680: }
681: }
682:
683: /*
684: * Process rings -
685: *
686: * This routine tries to fill up/empty our various rings.
687: *
688: * The parameter specifies whether this is a poll operation,
689: * or a block-until-something-happens operation.
690: *
691: * The return value is 1 if something happened, 0 if not.
692: */
693:
694: int
1.15 millert 695: process_rings(netin, netout, netex, ttyin, ttyout, dopoll)
696: int dopoll; /* If 0, then block until something to do */
1.1 deraadt 697: {
1.10 mpech 698: int c;
1.1 deraadt 699: /* One wants to be a bit careful about setting returnValue
700: * to one, since a one implies we did some useful work,
701: * and therefore probably won't be called to block next
702: * time (TN3270 mode only).
703: */
704: int returnValue = 0;
1.15 millert 705: struct pollfd pfd[TELNET_FD_NUM];
706:
707: if (ttyout) {
708: pfd[TELNET_FD_TOUT].fd = tout;
709: pfd[TELNET_FD_TOUT].events = POLLOUT;
710: } else {
711: pfd[TELNET_FD_TOUT].fd = -1;
712: }
713: if (ttyin) {
714: pfd[TELNET_FD_TIN].fd = tin;
715: pfd[TELNET_FD_TIN].events = POLLIN;
716: } else {
717: pfd[TELNET_FD_TIN].fd = -1;
718: }
719: if (netout || netin || netex) {
720: pfd[TELNET_FD_NET].fd = net;
721: pfd[TELNET_FD_NET].events = 0;
722: if (netout)
723: pfd[TELNET_FD_NET].events |= POLLOUT;
724: if (netin)
725: pfd[TELNET_FD_NET].events |= POLLIN;
726: if (netex)
727: pfd[TELNET_FD_NET].events |= POLLRDBAND;
728: } else {
729: pfd[TELNET_FD_NET].fd = -1;
730: }
1.1 deraadt 731:
1.15 millert 732: if ((c = poll(pfd, TELNET_FD_NUM, dopoll ? 0 : -1)) < 0) {
1.1 deraadt 733: if (c == -1) {
734: /*
735: * we can get EINTR if we are in line mode,
736: * and the user does an escape (TSTP), or
737: * some other signal generator.
738: */
739: if (errno == EINTR) {
740: return 0;
741: }
742: /* I don't like this, does it ever happen? */
1.15 millert 743: printf("sleep(5) from telnet, after poll\r\n");
1.1 deraadt 744: sleep(5);
745: }
746: return 0;
747: }
748:
749: /*
750: * Any urgent data?
751: */
1.15 millert 752: if (pfd[TELNET_FD_NET].revents & POLLRDBAND) {
1.1 deraadt 753: SYNCHing = 1;
754: (void) ttyflush(1); /* flush already enqueued data */
755: }
756:
757: /*
758: * Something to read from the network...
759: */
1.15 millert 760: if (pfd[TELNET_FD_NET].revents & (POLLIN|POLLHUP)) {
1.1 deraadt 761: int canread;
762:
763: canread = ring_empty_consecutive(&netiring);
764: c = recv(net, (char *)netiring.supply, canread, 0);
765: if (c < 0 && errno == EWOULDBLOCK) {
766: c = 0;
767: } else if (c <= 0) {
768: return -1;
769: }
770: if (netdata) {
771: Dump('<', netiring.supply, c);
772: }
773: if (c)
774: ring_supplied(&netiring, c);
775: returnValue = 1;
776: }
777:
778: /*
779: * Something to read from the tty...
780: */
1.15 millert 781: if (pfd[TELNET_FD_TIN].revents & (POLLIN|POLLHUP)) {
1.19 ! guenther 782: c = read(tin, ttyiring.supply, ring_empty_consecutive(&ttyiring));
1.3 niklas 783: if (c < 0 && errno == EIO)
784: c = 0;
1.1 deraadt 785: if (c < 0 && errno == EWOULDBLOCK) {
786: c = 0;
787: } else {
1.5 art 788: /* EOF detection for line mode!!!! */
789: if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
790: /* must be an EOF... */
791: *ttyiring.supply = termEofChar;
792: c = 1;
793: }
794: if (c <= 0) {
1.1 deraadt 795: return -1;
796: }
797: if (termdata) {
798: Dump('<', ttyiring.supply, c);
799: }
800: ring_supplied(&ttyiring, c);
801: }
802: returnValue = 1; /* did something useful */
803: }
804:
1.15 millert 805: if (pfd[TELNET_FD_NET].revents & POLLOUT) {
1.1 deraadt 806: returnValue |= netflush();
807: }
1.15 millert 808: if (pfd[TELNET_FD_TOUT].revents & POLLOUT) {
1.1 deraadt 809: returnValue |= (ttyflush(SYNCHing|flushout) > 0);
810: }
811:
812: return returnValue;
813: }