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