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