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