xref: /minix3/usr.bin/telnet/sys_bsd.c (revision 7348b5c52b47a1c199a1754a40bbfa360b536de2)
1*7348b5c5SDavid van Moolenbroek /*	$NetBSD: sys_bsd.c,v 1.33 2012/01/09 16:08:55 christos Exp $	*/
2*7348b5c5SDavid van Moolenbroek 
3*7348b5c5SDavid van Moolenbroek /*
4*7348b5c5SDavid van Moolenbroek  * Copyright (c) 1988, 1990, 1993
5*7348b5c5SDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
6*7348b5c5SDavid van Moolenbroek  *
7*7348b5c5SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*7348b5c5SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
9*7348b5c5SDavid van Moolenbroek  * are met:
10*7348b5c5SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
11*7348b5c5SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
12*7348b5c5SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
13*7348b5c5SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
14*7348b5c5SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
15*7348b5c5SDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
16*7348b5c5SDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
17*7348b5c5SDavid van Moolenbroek  *    without specific prior written permission.
18*7348b5c5SDavid van Moolenbroek  *
19*7348b5c5SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*7348b5c5SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*7348b5c5SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*7348b5c5SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*7348b5c5SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*7348b5c5SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*7348b5c5SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*7348b5c5SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*7348b5c5SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*7348b5c5SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*7348b5c5SDavid van Moolenbroek  * SUCH DAMAGE.
30*7348b5c5SDavid van Moolenbroek  */
31*7348b5c5SDavid van Moolenbroek 
32*7348b5c5SDavid van Moolenbroek #include <sys/cdefs.h>
33*7348b5c5SDavid van Moolenbroek #ifndef lint
34*7348b5c5SDavid van Moolenbroek #if 0
35*7348b5c5SDavid van Moolenbroek from: static char sccsid[] = "@(#)sys_bsd.c	8.4 (Berkeley) 5/30/95";
36*7348b5c5SDavid van Moolenbroek #else
37*7348b5c5SDavid van Moolenbroek __RCSID("$NetBSD: sys_bsd.c,v 1.33 2012/01/09 16:08:55 christos Exp $");
38*7348b5c5SDavid van Moolenbroek #endif
39*7348b5c5SDavid van Moolenbroek #endif /* not lint */
40*7348b5c5SDavid van Moolenbroek 
41*7348b5c5SDavid van Moolenbroek /*
42*7348b5c5SDavid van Moolenbroek  * The following routines try to encapsulate what is system dependent
43*7348b5c5SDavid van Moolenbroek  * (at least between 4.x and dos) which is used in telnet.c.
44*7348b5c5SDavid van Moolenbroek  */
45*7348b5c5SDavid van Moolenbroek 
46*7348b5c5SDavid van Moolenbroek 
47*7348b5c5SDavid van Moolenbroek #include <fcntl.h>
48*7348b5c5SDavid van Moolenbroek #include <sys/types.h>
49*7348b5c5SDavid van Moolenbroek #include <sys/time.h>
50*7348b5c5SDavid van Moolenbroek #include <sys/socket.h>
51*7348b5c5SDavid van Moolenbroek #include <signal.h>
52*7348b5c5SDavid van Moolenbroek #include <stdlib.h>
53*7348b5c5SDavid van Moolenbroek #include <unistd.h>
54*7348b5c5SDavid van Moolenbroek #include <errno.h>
55*7348b5c5SDavid van Moolenbroek #include <poll.h>
56*7348b5c5SDavid van Moolenbroek #include <arpa/telnet.h>
57*7348b5c5SDavid van Moolenbroek 
58*7348b5c5SDavid van Moolenbroek #include "ring.h"
59*7348b5c5SDavid van Moolenbroek #include "defines.h"
60*7348b5c5SDavid van Moolenbroek #include "externs.h"
61*7348b5c5SDavid van Moolenbroek #include "types.h"
62*7348b5c5SDavid van Moolenbroek 
63*7348b5c5SDavid van Moolenbroek #define	SIG_FUNC_RET	void
64*7348b5c5SDavid van Moolenbroek 
65*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET susp(int);
66*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET ayt(int);
67*7348b5c5SDavid van Moolenbroek 
68*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET intr(int);
69*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET intr2(int);
70*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET sendwin(int);
71*7348b5c5SDavid van Moolenbroek 
72*7348b5c5SDavid van Moolenbroek 
73*7348b5c5SDavid van Moolenbroek int
74*7348b5c5SDavid van Moolenbroek 	tout,			/* Output file descriptor */
75*7348b5c5SDavid van Moolenbroek 	tin,			/* Input file descriptor */
76*7348b5c5SDavid van Moolenbroek 	net;
77*7348b5c5SDavid van Moolenbroek 
78*7348b5c5SDavid van Moolenbroek struct	termios old_tc = { .c_iflag = 0 };
79*7348b5c5SDavid van Moolenbroek extern struct termios new_tc;
80*7348b5c5SDavid van Moolenbroek 
81*7348b5c5SDavid van Moolenbroek # ifndef	TCSANOW
82*7348b5c5SDavid van Moolenbroek #  ifdef TCSETS
83*7348b5c5SDavid van Moolenbroek #   define	TCSANOW		TCSETS
84*7348b5c5SDavid van Moolenbroek #   define	TCSADRAIN	TCSETSW
85*7348b5c5SDavid van Moolenbroek #   define	tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
86*7348b5c5SDavid van Moolenbroek #  else
87*7348b5c5SDavid van Moolenbroek #   ifdef TCSETA
88*7348b5c5SDavid van Moolenbroek #    define	TCSANOW		TCSETA
89*7348b5c5SDavid van Moolenbroek #    define	TCSADRAIN	TCSETAW
90*7348b5c5SDavid van Moolenbroek #    define	tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
91*7348b5c5SDavid van Moolenbroek #   else
92*7348b5c5SDavid van Moolenbroek #    define	TCSANOW		TIOCSETA
93*7348b5c5SDavid van Moolenbroek #    define	TCSADRAIN	TIOCSETAW
94*7348b5c5SDavid van Moolenbroek #    define	tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
95*7348b5c5SDavid van Moolenbroek #   endif
96*7348b5c5SDavid van Moolenbroek #  endif
97*7348b5c5SDavid van Moolenbroek #  define	tcsetattr(f, a, t) ioctl(f, a, (char *)t)
98*7348b5c5SDavid van Moolenbroek #  define	cfgetospeed(ptr)	((ptr)->c_cflag&CBAUD)
99*7348b5c5SDavid van Moolenbroek #  ifdef CIBAUD
100*7348b5c5SDavid van Moolenbroek #   define	cfgetispeed(ptr)	(((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
101*7348b5c5SDavid van Moolenbroek #  else
102*7348b5c5SDavid van Moolenbroek #   define	cfgetispeed(ptr)	cfgetospeed(ptr)
103*7348b5c5SDavid van Moolenbroek #  endif
104*7348b5c5SDavid van Moolenbroek # endif /* TCSANOW */
105*7348b5c5SDavid van Moolenbroek 
106*7348b5c5SDavid van Moolenbroek 
107*7348b5c5SDavid van Moolenbroek void
init_sys(void)108*7348b5c5SDavid van Moolenbroek init_sys(void)
109*7348b5c5SDavid van Moolenbroek {
110*7348b5c5SDavid van Moolenbroek     tout = fileno(stdout);
111*7348b5c5SDavid van Moolenbroek     tin = fileno(stdin);
112*7348b5c5SDavid van Moolenbroek 
113*7348b5c5SDavid van Moolenbroek     errno = 0;
114*7348b5c5SDavid van Moolenbroek }
115*7348b5c5SDavid van Moolenbroek 
116*7348b5c5SDavid van Moolenbroek 
117*7348b5c5SDavid van Moolenbroek int
TerminalWrite(char * buf,int n)118*7348b5c5SDavid van Moolenbroek TerminalWrite(char *buf, int  n)
119*7348b5c5SDavid van Moolenbroek {
120*7348b5c5SDavid van Moolenbroek     return write(tout, buf, n);
121*7348b5c5SDavid van Moolenbroek }
122*7348b5c5SDavid van Moolenbroek 
123*7348b5c5SDavid van Moolenbroek int
TerminalRead(unsigned char * buf,int n)124*7348b5c5SDavid van Moolenbroek TerminalRead(unsigned char *buf, int  n)
125*7348b5c5SDavid van Moolenbroek {
126*7348b5c5SDavid van Moolenbroek     return read(tin, buf, n);
127*7348b5c5SDavid van Moolenbroek }
128*7348b5c5SDavid van Moolenbroek 
129*7348b5c5SDavid van Moolenbroek /*
130*7348b5c5SDavid van Moolenbroek  *
131*7348b5c5SDavid van Moolenbroek  */
132*7348b5c5SDavid van Moolenbroek 
133*7348b5c5SDavid van Moolenbroek int
TerminalAutoFlush(void)134*7348b5c5SDavid van Moolenbroek TerminalAutoFlush(void)
135*7348b5c5SDavid van Moolenbroek {
136*7348b5c5SDavid van Moolenbroek     return 1;
137*7348b5c5SDavid van Moolenbroek }
138*7348b5c5SDavid van Moolenbroek 
139*7348b5c5SDavid van Moolenbroek #ifdef	KLUDGELINEMODE
140*7348b5c5SDavid van Moolenbroek extern int kludgelinemode;
141*7348b5c5SDavid van Moolenbroek #endif
142*7348b5c5SDavid van Moolenbroek /*
143*7348b5c5SDavid van Moolenbroek  * TerminalSpecialChars()
144*7348b5c5SDavid van Moolenbroek  *
145*7348b5c5SDavid van Moolenbroek  * Look at an input character to see if it is a special character
146*7348b5c5SDavid van Moolenbroek  * and decide what to do.
147*7348b5c5SDavid van Moolenbroek  *
148*7348b5c5SDavid van Moolenbroek  * Output:
149*7348b5c5SDavid van Moolenbroek  *
150*7348b5c5SDavid van Moolenbroek  *	0	Don't add this character.
151*7348b5c5SDavid van Moolenbroek  *	1	Do add this character
152*7348b5c5SDavid van Moolenbroek  */
153*7348b5c5SDavid van Moolenbroek 
154*7348b5c5SDavid van Moolenbroek int
TerminalSpecialChars(int c)155*7348b5c5SDavid van Moolenbroek TerminalSpecialChars(int c)
156*7348b5c5SDavid van Moolenbroek {
157*7348b5c5SDavid van Moolenbroek     if (c == termIntChar) {
158*7348b5c5SDavid van Moolenbroek 	intp();
159*7348b5c5SDavid van Moolenbroek 	return 0;
160*7348b5c5SDavid van Moolenbroek     } else if (c == termQuitChar) {
161*7348b5c5SDavid van Moolenbroek #ifdef	KLUDGELINEMODE
162*7348b5c5SDavid van Moolenbroek 	if (kludgelinemode)
163*7348b5c5SDavid van Moolenbroek 	    sendbrk();
164*7348b5c5SDavid van Moolenbroek 	else
165*7348b5c5SDavid van Moolenbroek #endif
166*7348b5c5SDavid van Moolenbroek 	    sendabort();
167*7348b5c5SDavid van Moolenbroek 	return 0;
168*7348b5c5SDavid van Moolenbroek     } else if (c == termEofChar) {
169*7348b5c5SDavid van Moolenbroek 	if (my_want_state_is_will(TELOPT_LINEMODE)) {
170*7348b5c5SDavid van Moolenbroek 	    sendeof();
171*7348b5c5SDavid van Moolenbroek 	    return 0;
172*7348b5c5SDavid van Moolenbroek 	}
173*7348b5c5SDavid van Moolenbroek 	return 1;
174*7348b5c5SDavid van Moolenbroek     } else if (c == termSuspChar) {
175*7348b5c5SDavid van Moolenbroek 	sendsusp();
176*7348b5c5SDavid van Moolenbroek 	return(0);
177*7348b5c5SDavid van Moolenbroek     } else if (c == termFlushChar) {
178*7348b5c5SDavid van Moolenbroek 	xmitAO();		/* Transmit Abort Output */
179*7348b5c5SDavid van Moolenbroek 	return 0;
180*7348b5c5SDavid van Moolenbroek     } else if (!MODE_LOCAL_CHARS(globalmode)) {
181*7348b5c5SDavid van Moolenbroek 	if (c == termKillChar) {
182*7348b5c5SDavid van Moolenbroek 	    xmitEL();
183*7348b5c5SDavid van Moolenbroek 	    return 0;
184*7348b5c5SDavid van Moolenbroek 	} else if (c == termEraseChar) {
185*7348b5c5SDavid van Moolenbroek 	    xmitEC();		/* Transmit Erase Character */
186*7348b5c5SDavid van Moolenbroek 	    return 0;
187*7348b5c5SDavid van Moolenbroek 	}
188*7348b5c5SDavid van Moolenbroek     }
189*7348b5c5SDavid van Moolenbroek     return 1;
190*7348b5c5SDavid van Moolenbroek }
191*7348b5c5SDavid van Moolenbroek 
192*7348b5c5SDavid van Moolenbroek 
193*7348b5c5SDavid van Moolenbroek /*
194*7348b5c5SDavid van Moolenbroek  * Flush output to the terminal
195*7348b5c5SDavid van Moolenbroek  */
196*7348b5c5SDavid van Moolenbroek 
197*7348b5c5SDavid van Moolenbroek void
TerminalFlushOutput(void)198*7348b5c5SDavid van Moolenbroek TerminalFlushOutput(void)
199*7348b5c5SDavid van Moolenbroek {
200*7348b5c5SDavid van Moolenbroek     int com = 0;
201*7348b5c5SDavid van Moolenbroek     (void) ioctl(fileno(stdout), TIOCFLUSH, &com);
202*7348b5c5SDavid van Moolenbroek }
203*7348b5c5SDavid van Moolenbroek 
204*7348b5c5SDavid van Moolenbroek void
TerminalSaveState(void)205*7348b5c5SDavid van Moolenbroek TerminalSaveState(void)
206*7348b5c5SDavid van Moolenbroek {
207*7348b5c5SDavid van Moolenbroek     tcgetattr(0, &old_tc);
208*7348b5c5SDavid van Moolenbroek 
209*7348b5c5SDavid van Moolenbroek     new_tc = old_tc;
210*7348b5c5SDavid van Moolenbroek }
211*7348b5c5SDavid van Moolenbroek 
212*7348b5c5SDavid van Moolenbroek cc_t *
tcval(int func)213*7348b5c5SDavid van Moolenbroek tcval(int func)
214*7348b5c5SDavid van Moolenbroek {
215*7348b5c5SDavid van Moolenbroek     switch(func) {
216*7348b5c5SDavid van Moolenbroek     case SLC_IP:	return(&termIntChar);
217*7348b5c5SDavid van Moolenbroek     case SLC_ABORT:	return(&termQuitChar);
218*7348b5c5SDavid van Moolenbroek     case SLC_EOF:	return(&termEofChar);
219*7348b5c5SDavid van Moolenbroek     case SLC_EC:	return(&termEraseChar);
220*7348b5c5SDavid van Moolenbroek     case SLC_EL:	return(&termKillChar);
221*7348b5c5SDavid van Moolenbroek     case SLC_XON:	return(&termStartChar);
222*7348b5c5SDavid van Moolenbroek     case SLC_XOFF:	return(&termStopChar);
223*7348b5c5SDavid van Moolenbroek     case SLC_FORW1:	return(&termForw1Char);
224*7348b5c5SDavid van Moolenbroek     case SLC_FORW2:	return(&termForw2Char);
225*7348b5c5SDavid van Moolenbroek     case SLC_AO:	return(&termFlushChar);
226*7348b5c5SDavid van Moolenbroek     case SLC_SUSP:	return(&termSuspChar);
227*7348b5c5SDavid van Moolenbroek     case SLC_EW:	return(&termWerasChar);
228*7348b5c5SDavid van Moolenbroek     case SLC_RP:	return(&termRprntChar);
229*7348b5c5SDavid van Moolenbroek     case SLC_LNEXT:	return(&termLiteralNextChar);
230*7348b5c5SDavid van Moolenbroek     case SLC_AYT:	return(&termAytChar);
231*7348b5c5SDavid van Moolenbroek 
232*7348b5c5SDavid van Moolenbroek     case SLC_SYNCH:
233*7348b5c5SDavid van Moolenbroek     case SLC_BRK:
234*7348b5c5SDavid van Moolenbroek     case SLC_EOR:
235*7348b5c5SDavid van Moolenbroek     default:
236*7348b5c5SDavid van Moolenbroek 	return((cc_t *)0);
237*7348b5c5SDavid van Moolenbroek     }
238*7348b5c5SDavid van Moolenbroek }
239*7348b5c5SDavid van Moolenbroek 
240*7348b5c5SDavid van Moolenbroek void
TerminalDefaultChars(void)241*7348b5c5SDavid van Moolenbroek TerminalDefaultChars(void)
242*7348b5c5SDavid van Moolenbroek {
243*7348b5c5SDavid van Moolenbroek     memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
244*7348b5c5SDavid van Moolenbroek }
245*7348b5c5SDavid van Moolenbroek 
246*7348b5c5SDavid van Moolenbroek #ifdef notdef
247*7348b5c5SDavid van Moolenbroek void
TerminalRestoreState(void)248*7348b5c5SDavid van Moolenbroek TerminalRestoreState(void)
249*7348b5c5SDavid van Moolenbroek {
250*7348b5c5SDavid van Moolenbroek }
251*7348b5c5SDavid van Moolenbroek #endif
252*7348b5c5SDavid van Moolenbroek 
253*7348b5c5SDavid van Moolenbroek /*
254*7348b5c5SDavid van Moolenbroek  * TerminalNewMode - set up terminal to a specific mode.
255*7348b5c5SDavid van Moolenbroek  *	MODE_ECHO: do local terminal echo
256*7348b5c5SDavid van Moolenbroek  *	MODE_FLOW: do local flow control
257*7348b5c5SDavid van Moolenbroek  *	MODE_TRAPSIG: do local mapping to TELNET IAC sequences
258*7348b5c5SDavid van Moolenbroek  *	MODE_EDIT: do local line editing
259*7348b5c5SDavid van Moolenbroek  *
260*7348b5c5SDavid van Moolenbroek  *	Command mode:
261*7348b5c5SDavid van Moolenbroek  *		MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
262*7348b5c5SDavid van Moolenbroek  *		local echo
263*7348b5c5SDavid van Moolenbroek  *		local editing
264*7348b5c5SDavid van Moolenbroek  *		local xon/xoff
265*7348b5c5SDavid van Moolenbroek  *		local signal mapping
266*7348b5c5SDavid van Moolenbroek  *
267*7348b5c5SDavid van Moolenbroek  *	Linemode:
268*7348b5c5SDavid van Moolenbroek  *		local/no editing
269*7348b5c5SDavid van Moolenbroek  *	Both Linemode and Single Character mode:
270*7348b5c5SDavid van Moolenbroek  *		local/remote echo
271*7348b5c5SDavid van Moolenbroek  *		local/no xon/xoff
272*7348b5c5SDavid van Moolenbroek  *		local/no signal mapping
273*7348b5c5SDavid van Moolenbroek  */
274*7348b5c5SDavid van Moolenbroek 
275*7348b5c5SDavid van Moolenbroek 
276*7348b5c5SDavid van Moolenbroek void
TerminalNewMode(int f)277*7348b5c5SDavid van Moolenbroek TerminalNewMode(int f)
278*7348b5c5SDavid van Moolenbroek {
279*7348b5c5SDavid van Moolenbroek     static int prevmode = 0;
280*7348b5c5SDavid van Moolenbroek     struct termios tmp_tc;
281*7348b5c5SDavid van Moolenbroek     int onoff;
282*7348b5c5SDavid van Moolenbroek     int old;
283*7348b5c5SDavid van Moolenbroek     cc_t esc;
284*7348b5c5SDavid van Moolenbroek 
285*7348b5c5SDavid van Moolenbroek     globalmode = f&~MODE_FORCE;
286*7348b5c5SDavid van Moolenbroek     if (prevmode == f)
287*7348b5c5SDavid van Moolenbroek 	return;
288*7348b5c5SDavid van Moolenbroek 
289*7348b5c5SDavid van Moolenbroek     /*
290*7348b5c5SDavid van Moolenbroek      * Write any outstanding data before switching modes
291*7348b5c5SDavid van Moolenbroek      * ttyflush() returns 0 only when there is no more data
292*7348b5c5SDavid van Moolenbroek      * left to write out, it returns -1 if it couldn't do
293*7348b5c5SDavid van Moolenbroek      * anything at all, otherwise it returns 1 + the number
294*7348b5c5SDavid van Moolenbroek      * of characters left to write.
295*7348b5c5SDavid van Moolenbroek #ifndef	USE_TERMIO
296*7348b5c5SDavid van Moolenbroek      * We would really like to ask the kernel to wait for the output
297*7348b5c5SDavid van Moolenbroek      * to drain, like we can do with the TCSADRAIN, but we don't have
298*7348b5c5SDavid van Moolenbroek      * that option.  The only ioctl that waits for the output to
299*7348b5c5SDavid van Moolenbroek      * drain, TIOCSETP, also flushes the input queue, which is NOT
300*7348b5c5SDavid van Moolenbroek      * what we want (TIOCSETP is like TCSADFLUSH).
301*7348b5c5SDavid van Moolenbroek #endif
302*7348b5c5SDavid van Moolenbroek      */
303*7348b5c5SDavid van Moolenbroek     old = ttyflush(SYNCHing|flushout);
304*7348b5c5SDavid van Moolenbroek     if (old < 0 || old > 1) {
305*7348b5c5SDavid van Moolenbroek 	tcgetattr(tin, &tmp_tc);
306*7348b5c5SDavid van Moolenbroek 	do {
307*7348b5c5SDavid van Moolenbroek 	    /*
308*7348b5c5SDavid van Moolenbroek 	     * Wait for data to drain, then flush again.
309*7348b5c5SDavid van Moolenbroek 	     */
310*7348b5c5SDavid van Moolenbroek 	    tcsetattr(tin, TCSADRAIN, &tmp_tc);
311*7348b5c5SDavid van Moolenbroek 	    old = ttyflush(SYNCHing|flushout);
312*7348b5c5SDavid van Moolenbroek 	} while (old < 0 || old > 1);
313*7348b5c5SDavid van Moolenbroek     }
314*7348b5c5SDavid van Moolenbroek 
315*7348b5c5SDavid van Moolenbroek     old = prevmode;
316*7348b5c5SDavid van Moolenbroek     prevmode = f&~MODE_FORCE;
317*7348b5c5SDavid van Moolenbroek     tmp_tc = new_tc;
318*7348b5c5SDavid van Moolenbroek 
319*7348b5c5SDavid van Moolenbroek     if (f&MODE_ECHO) {
320*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag |= ECHO;
321*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag |= ONLCR;
322*7348b5c5SDavid van Moolenbroek 	if (crlf)
323*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag |= ICRNL;
324*7348b5c5SDavid van Moolenbroek     } else {
325*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag &= ~ECHO;
326*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag &= ~ONLCR;
327*7348b5c5SDavid van Moolenbroek # ifdef notdef
328*7348b5c5SDavid van Moolenbroek 	if (crlf)
329*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag &= ~ICRNL;
330*7348b5c5SDavid van Moolenbroek # endif
331*7348b5c5SDavid van Moolenbroek     }
332*7348b5c5SDavid van Moolenbroek 
333*7348b5c5SDavid van Moolenbroek     if ((f&MODE_FLOW) == 0) {
334*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_iflag &= ~(IXOFF|IXON);	/* Leave the IXANY bit alone */
335*7348b5c5SDavid van Moolenbroek     } else {
336*7348b5c5SDavid van Moolenbroek 	if (restartany < 0) {
337*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag |= IXOFF|IXON;	/* Leave the IXANY bit alone */
338*7348b5c5SDavid van Moolenbroek 	} else if (restartany > 0) {
339*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
340*7348b5c5SDavid van Moolenbroek 	} else {
341*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag |= IXOFF|IXON;
342*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag &= ~IXANY;
343*7348b5c5SDavid van Moolenbroek 	}
344*7348b5c5SDavid van Moolenbroek     }
345*7348b5c5SDavid van Moolenbroek 
346*7348b5c5SDavid van Moolenbroek     if ((f&MODE_TRAPSIG) == 0) {
347*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag &= ~ISIG;
348*7348b5c5SDavid van Moolenbroek 	localchars = 0;
349*7348b5c5SDavid van Moolenbroek     } else {
350*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag |= ISIG;
351*7348b5c5SDavid van Moolenbroek 	localchars = 1;
352*7348b5c5SDavid van Moolenbroek     }
353*7348b5c5SDavid van Moolenbroek 
354*7348b5c5SDavid van Moolenbroek     if (f&MODE_EDIT) {
355*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag |= ICANON;
356*7348b5c5SDavid van Moolenbroek     } else {
357*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag &= ~ICANON;
358*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_iflag &= ~ICRNL;
359*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_cc[VMIN] = 1;
360*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_cc[VTIME] = 0;
361*7348b5c5SDavid van Moolenbroek     }
362*7348b5c5SDavid van Moolenbroek 
363*7348b5c5SDavid van Moolenbroek     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
364*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag &= ~IEXTEN;
365*7348b5c5SDavid van Moolenbroek     }
366*7348b5c5SDavid van Moolenbroek 
367*7348b5c5SDavid van Moolenbroek     if (f&MODE_SOFT_TAB) {
368*7348b5c5SDavid van Moolenbroek # ifdef	OXTABS
369*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag |= OXTABS;
370*7348b5c5SDavid van Moolenbroek # endif
371*7348b5c5SDavid van Moolenbroek # ifdef	TABDLY
372*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag &= ~TABDLY;
373*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag |= TAB3;
374*7348b5c5SDavid van Moolenbroek # endif
375*7348b5c5SDavid van Moolenbroek     } else {
376*7348b5c5SDavid van Moolenbroek # ifdef	OXTABS
377*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag &= ~OXTABS;
378*7348b5c5SDavid van Moolenbroek # endif
379*7348b5c5SDavid van Moolenbroek # ifdef	TABDLY
380*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_oflag &= ~TABDLY;
381*7348b5c5SDavid van Moolenbroek # endif
382*7348b5c5SDavid van Moolenbroek     }
383*7348b5c5SDavid van Moolenbroek 
384*7348b5c5SDavid van Moolenbroek     if (f&MODE_LIT_ECHO) {
385*7348b5c5SDavid van Moolenbroek # ifdef	ECHOCTL
386*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag &= ~ECHOCTL;
387*7348b5c5SDavid van Moolenbroek # endif
388*7348b5c5SDavid van Moolenbroek     } else {
389*7348b5c5SDavid van Moolenbroek # ifdef	ECHOCTL
390*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag |= ECHOCTL;
391*7348b5c5SDavid van Moolenbroek # endif
392*7348b5c5SDavid van Moolenbroek     }
393*7348b5c5SDavid van Moolenbroek 
394*7348b5c5SDavid van Moolenbroek     if (f == -1) {
395*7348b5c5SDavid van Moolenbroek 	onoff = 0;
396*7348b5c5SDavid van Moolenbroek     } else {
397*7348b5c5SDavid van Moolenbroek 	if (f & MODE_INBIN)
398*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag &= ~ISTRIP;
399*7348b5c5SDavid van Moolenbroek 	else
400*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_iflag |= ISTRIP;
401*7348b5c5SDavid van Moolenbroek 	if (f & MODE_OUTBIN) {
402*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
403*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_cflag |= CS8;
404*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_oflag &= ~OPOST;
405*7348b5c5SDavid van Moolenbroek 	} else {
406*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
407*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
408*7348b5c5SDavid van Moolenbroek 		tmp_tc.c_oflag |= OPOST;
409*7348b5c5SDavid van Moolenbroek 	}
410*7348b5c5SDavid van Moolenbroek 	onoff = 1;
411*7348b5c5SDavid van Moolenbroek     }
412*7348b5c5SDavid van Moolenbroek 
413*7348b5c5SDavid van Moolenbroek     if (f != -1) {
414*7348b5c5SDavid van Moolenbroek 	(void) signal(SIGTSTP, susp);
415*7348b5c5SDavid van Moolenbroek 	(void) signal(SIGINFO, ayt);
416*7348b5c5SDavid van Moolenbroek #if	defined(USE_TERMIO) && defined(NOKERNINFO)
417*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_lflag |= NOKERNINFO;
418*7348b5c5SDavid van Moolenbroek #endif
419*7348b5c5SDavid van Moolenbroek 	/*
420*7348b5c5SDavid van Moolenbroek 	 * We don't want to process ^Y here.  It's just another
421*7348b5c5SDavid van Moolenbroek 	 * character that we'll pass on to the back end.  It has
422*7348b5c5SDavid van Moolenbroek 	 * to process it because it will be processed when the
423*7348b5c5SDavid van Moolenbroek 	 * user attempts to read it, not when we send it.
424*7348b5c5SDavid van Moolenbroek 	 */
425*7348b5c5SDavid van Moolenbroek # ifdef	VDSUSP
426*7348b5c5SDavid van Moolenbroek 	tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
427*7348b5c5SDavid van Moolenbroek # endif
428*7348b5c5SDavid van Moolenbroek 	/*
429*7348b5c5SDavid van Moolenbroek 	 * If the VEOL character is already set, then use VEOL2,
430*7348b5c5SDavid van Moolenbroek 	 * otherwise use VEOL.
431*7348b5c5SDavid van Moolenbroek 	 */
432*7348b5c5SDavid van Moolenbroek 	esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
433*7348b5c5SDavid van Moolenbroek 	if ((tmp_tc.c_cc[VEOL] != esc)
434*7348b5c5SDavid van Moolenbroek # ifdef	VEOL2
435*7348b5c5SDavid van Moolenbroek 	    && (tmp_tc.c_cc[VEOL2] != esc)
436*7348b5c5SDavid van Moolenbroek # endif
437*7348b5c5SDavid van Moolenbroek 	    ) {
438*7348b5c5SDavid van Moolenbroek 		if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
439*7348b5c5SDavid van Moolenbroek 		    tmp_tc.c_cc[VEOL] = esc;
440*7348b5c5SDavid van Moolenbroek # ifdef	VEOL2
441*7348b5c5SDavid van Moolenbroek 		else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
442*7348b5c5SDavid van Moolenbroek 		    tmp_tc.c_cc[VEOL2] = esc;
443*7348b5c5SDavid van Moolenbroek # endif
444*7348b5c5SDavid van Moolenbroek 	}
445*7348b5c5SDavid van Moolenbroek     } else {
446*7348b5c5SDavid van Moolenbroek 	(void) signal(SIGINFO, (void (*)(int)) ayt_status);
447*7348b5c5SDavid van Moolenbroek 	(void) signal(SIGTSTP, SIG_DFL);
448*7348b5c5SDavid van Moolenbroek 	(void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
449*7348b5c5SDavid van Moolenbroek 	tmp_tc = old_tc;
450*7348b5c5SDavid van Moolenbroek     }
451*7348b5c5SDavid van Moolenbroek     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
452*7348b5c5SDavid van Moolenbroek 	tcsetattr(tin, TCSANOW, &tmp_tc);
453*7348b5c5SDavid van Moolenbroek 
454*7348b5c5SDavid van Moolenbroek     ioctl(tin, FIONBIO, (char *)&onoff);
455*7348b5c5SDavid van Moolenbroek     ioctl(tout, FIONBIO, (char *)&onoff);
456*7348b5c5SDavid van Moolenbroek #if	defined(TN3270)
457*7348b5c5SDavid van Moolenbroek     if (noasynchtty == 0) {
458*7348b5c5SDavid van Moolenbroek 	ioctl(tin, FIOASYNC, (char *)&onoff);
459*7348b5c5SDavid van Moolenbroek     }
460*7348b5c5SDavid van Moolenbroek #endif	/* defined(TN3270) */
461*7348b5c5SDavid van Moolenbroek 
462*7348b5c5SDavid van Moolenbroek }
463*7348b5c5SDavid van Moolenbroek 
464*7348b5c5SDavid van Moolenbroek void
TerminalSpeeds(long * ispeed,long * ospeed)465*7348b5c5SDavid van Moolenbroek TerminalSpeeds(long *ispeed, long *ospeed)
466*7348b5c5SDavid van Moolenbroek {
467*7348b5c5SDavid van Moolenbroek     long in, out;
468*7348b5c5SDavid van Moolenbroek 
469*7348b5c5SDavid van Moolenbroek     out = cfgetospeed(&old_tc);
470*7348b5c5SDavid van Moolenbroek     in = cfgetispeed(&old_tc);
471*7348b5c5SDavid van Moolenbroek     if (in == 0)
472*7348b5c5SDavid van Moolenbroek 	in = out;
473*7348b5c5SDavid van Moolenbroek 
474*7348b5c5SDavid van Moolenbroek 	*ispeed = in;
475*7348b5c5SDavid van Moolenbroek 	*ospeed = out;
476*7348b5c5SDavid van Moolenbroek }
477*7348b5c5SDavid van Moolenbroek 
478*7348b5c5SDavid van Moolenbroek int
TerminalWindowSize(long * rows,long * cols)479*7348b5c5SDavid van Moolenbroek TerminalWindowSize(long *rows, long *cols)
480*7348b5c5SDavid van Moolenbroek {
481*7348b5c5SDavid van Moolenbroek     struct winsize ws;
482*7348b5c5SDavid van Moolenbroek 
483*7348b5c5SDavid van Moolenbroek     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
484*7348b5c5SDavid van Moolenbroek 	*rows = ws.ws_row;
485*7348b5c5SDavid van Moolenbroek 	*cols = ws.ws_col;
486*7348b5c5SDavid van Moolenbroek 	return 1;
487*7348b5c5SDavid van Moolenbroek     }
488*7348b5c5SDavid van Moolenbroek     return 0;
489*7348b5c5SDavid van Moolenbroek }
490*7348b5c5SDavid van Moolenbroek 
491*7348b5c5SDavid van Moolenbroek int
NetClose(int fd)492*7348b5c5SDavid van Moolenbroek NetClose(int fd)
493*7348b5c5SDavid van Moolenbroek {
494*7348b5c5SDavid van Moolenbroek     return close(fd);
495*7348b5c5SDavid van Moolenbroek }
496*7348b5c5SDavid van Moolenbroek 
497*7348b5c5SDavid van Moolenbroek 
498*7348b5c5SDavid van Moolenbroek void
NetNonblockingIO(int fd,int onoff)499*7348b5c5SDavid van Moolenbroek NetNonblockingIO(int fd, int onoff)
500*7348b5c5SDavid van Moolenbroek {
501*7348b5c5SDavid van Moolenbroek     ioctl(fd, FIONBIO, (char *)&onoff);
502*7348b5c5SDavid van Moolenbroek }
503*7348b5c5SDavid van Moolenbroek 
504*7348b5c5SDavid van Moolenbroek #ifdef TN3270
505*7348b5c5SDavid van Moolenbroek void
NetSigIO(int fd,int onoff)506*7348b5c5SDavid van Moolenbroek NetSigIO(int fd, int onoff)
507*7348b5c5SDavid van Moolenbroek {
508*7348b5c5SDavid van Moolenbroek     ioctl(fd, FIOASYNC, (char *)&onoff);	/* hear about input */
509*7348b5c5SDavid van Moolenbroek }
510*7348b5c5SDavid van Moolenbroek 
511*7348b5c5SDavid van Moolenbroek void
NetSetPgrp(int fd)512*7348b5c5SDavid van Moolenbroek NetSetPgrp(int fd)
513*7348b5c5SDavid van Moolenbroek {
514*7348b5c5SDavid van Moolenbroek     int myPid;
515*7348b5c5SDavid van Moolenbroek 
516*7348b5c5SDavid van Moolenbroek     myPid = getpid();
517*7348b5c5SDavid van Moolenbroek     fcntl(fd, F_SETOWN, myPid);
518*7348b5c5SDavid van Moolenbroek }
519*7348b5c5SDavid van Moolenbroek #endif	/*defined(TN3270)*/
520*7348b5c5SDavid van Moolenbroek 
521*7348b5c5SDavid van Moolenbroek /*
522*7348b5c5SDavid van Moolenbroek  * Various signal handling routines.
523*7348b5c5SDavid van Moolenbroek  */
524*7348b5c5SDavid van Moolenbroek 
525*7348b5c5SDavid van Moolenbroek /* ARGSUSED */
526*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET
intr(int sig)527*7348b5c5SDavid van Moolenbroek intr(int sig)
528*7348b5c5SDavid van Moolenbroek {
529*7348b5c5SDavid van Moolenbroek     if (localchars) {
530*7348b5c5SDavid van Moolenbroek 	intp();
531*7348b5c5SDavid van Moolenbroek 	return;
532*7348b5c5SDavid van Moolenbroek     }
533*7348b5c5SDavid van Moolenbroek     setcommandmode();
534*7348b5c5SDavid van Moolenbroek     longjmp(toplevel, -1);
535*7348b5c5SDavid van Moolenbroek }
536*7348b5c5SDavid van Moolenbroek 
537*7348b5c5SDavid van Moolenbroek /* ARGSUSED */
538*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET
intr2(int sig)539*7348b5c5SDavid van Moolenbroek intr2(int sig)
540*7348b5c5SDavid van Moolenbroek {
541*7348b5c5SDavid van Moolenbroek     if (localchars) {
542*7348b5c5SDavid van Moolenbroek #ifdef	KLUDGELINEMODE
543*7348b5c5SDavid van Moolenbroek 	if (kludgelinemode)
544*7348b5c5SDavid van Moolenbroek 	    sendbrk();
545*7348b5c5SDavid van Moolenbroek 	else
546*7348b5c5SDavid van Moolenbroek #endif
547*7348b5c5SDavid van Moolenbroek 	    sendabort();
548*7348b5c5SDavid van Moolenbroek 	return;
549*7348b5c5SDavid van Moolenbroek     }
550*7348b5c5SDavid van Moolenbroek }
551*7348b5c5SDavid van Moolenbroek 
552*7348b5c5SDavid van Moolenbroek /* ARGSUSED */
553*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET
susp(int sig)554*7348b5c5SDavid van Moolenbroek susp(int sig)
555*7348b5c5SDavid van Moolenbroek {
556*7348b5c5SDavid van Moolenbroek     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
557*7348b5c5SDavid van Moolenbroek 	return;
558*7348b5c5SDavid van Moolenbroek     if (localchars)
559*7348b5c5SDavid van Moolenbroek 	sendsusp();
560*7348b5c5SDavid van Moolenbroek }
561*7348b5c5SDavid van Moolenbroek 
562*7348b5c5SDavid van Moolenbroek /* ARGSUSED */
563*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET
sendwin(int sig)564*7348b5c5SDavid van Moolenbroek sendwin(int sig)
565*7348b5c5SDavid van Moolenbroek {
566*7348b5c5SDavid van Moolenbroek     if (connected) {
567*7348b5c5SDavid van Moolenbroek 	sendnaws();
568*7348b5c5SDavid van Moolenbroek     }
569*7348b5c5SDavid van Moolenbroek }
570*7348b5c5SDavid van Moolenbroek 
571*7348b5c5SDavid van Moolenbroek /* ARGSUSED */
572*7348b5c5SDavid van Moolenbroek SIG_FUNC_RET
ayt(int sig)573*7348b5c5SDavid van Moolenbroek ayt(int sig)
574*7348b5c5SDavid van Moolenbroek {
575*7348b5c5SDavid van Moolenbroek     if (connected)
576*7348b5c5SDavid van Moolenbroek 	sendayt();
577*7348b5c5SDavid van Moolenbroek     else
578*7348b5c5SDavid van Moolenbroek 	ayt_status();
579*7348b5c5SDavid van Moolenbroek }
580*7348b5c5SDavid van Moolenbroek 
581*7348b5c5SDavid van Moolenbroek 
582*7348b5c5SDavid van Moolenbroek void
sys_telnet_init(void)583*7348b5c5SDavid van Moolenbroek sys_telnet_init(void)
584*7348b5c5SDavid van Moolenbroek {
585*7348b5c5SDavid van Moolenbroek     (void) signal(SIGINT, intr);
586*7348b5c5SDavid van Moolenbroek     (void) signal(SIGQUIT, intr2);
587*7348b5c5SDavid van Moolenbroek     (void) signal(SIGPIPE, SIG_IGN);
588*7348b5c5SDavid van Moolenbroek     (void) signal(SIGWINCH, sendwin);
589*7348b5c5SDavid van Moolenbroek     (void) signal(SIGTSTP, susp);
590*7348b5c5SDavid van Moolenbroek     (void) signal(SIGINFO, ayt);
591*7348b5c5SDavid van Moolenbroek 
592*7348b5c5SDavid van Moolenbroek     setconnmode(0);
593*7348b5c5SDavid van Moolenbroek 
594*7348b5c5SDavid van Moolenbroek     NetNonblockingIO(net, 1);
595*7348b5c5SDavid van Moolenbroek 
596*7348b5c5SDavid van Moolenbroek #ifdef TN3270
597*7348b5c5SDavid van Moolenbroek     if (noasynchnet == 0) {			/* DBX can't handle! */
598*7348b5c5SDavid van Moolenbroek 	NetSigIO(net, 1);
599*7348b5c5SDavid van Moolenbroek 	NetSetPgrp(net);
600*7348b5c5SDavid van Moolenbroek     }
601*7348b5c5SDavid van Moolenbroek #endif	/* defined(TN3270) */
602*7348b5c5SDavid van Moolenbroek 
603*7348b5c5SDavid van Moolenbroek     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
604*7348b5c5SDavid van Moolenbroek 	perror("SetSockOpt");
605*7348b5c5SDavid van Moolenbroek     }
606*7348b5c5SDavid van Moolenbroek }
607*7348b5c5SDavid van Moolenbroek 
608*7348b5c5SDavid van Moolenbroek /*
609*7348b5c5SDavid van Moolenbroek  * Process rings -
610*7348b5c5SDavid van Moolenbroek  *
611*7348b5c5SDavid van Moolenbroek  *	This routine tries to fill up/empty our various rings.
612*7348b5c5SDavid van Moolenbroek  *
613*7348b5c5SDavid van Moolenbroek  *	The parameter specifies whether this is a poll operation,
614*7348b5c5SDavid van Moolenbroek  *	or a block-until-something-happens operation.
615*7348b5c5SDavid van Moolenbroek  *
616*7348b5c5SDavid van Moolenbroek  *	The return value is 1 if something happened, 0 if not, < 0 if an
617*7348b5c5SDavid van Moolenbroek  *	error occurred.
618*7348b5c5SDavid van Moolenbroek  */
619*7348b5c5SDavid van Moolenbroek 
620*7348b5c5SDavid van Moolenbroek int
process_rings(int netin,int netout,int netex,int ttyin,int ttyout,int dopoll)621*7348b5c5SDavid van Moolenbroek process_rings(int netin, int netout, int netex, int ttyin, int ttyout,
622*7348b5c5SDavid van Moolenbroek     int dopoll)		/* If 0, then block until something to do */
623*7348b5c5SDavid van Moolenbroek {
624*7348b5c5SDavid van Moolenbroek     struct pollfd set[3];
625*7348b5c5SDavid van Moolenbroek     int c;
626*7348b5c5SDavid van Moolenbroek 		/* One wants to be a bit careful about setting returnValue
627*7348b5c5SDavid van Moolenbroek 		 * to one, since a one implies we did some useful work,
628*7348b5c5SDavid van Moolenbroek 		 * and therefore probably won't be called to block next
629*7348b5c5SDavid van Moolenbroek 		 * time (TN3270 mode only).
630*7348b5c5SDavid van Moolenbroek 		 */
631*7348b5c5SDavid van Moolenbroek     int returnValue = 0;
632*7348b5c5SDavid van Moolenbroek 
633*7348b5c5SDavid van Moolenbroek     set[0].fd = net;
634*7348b5c5SDavid van Moolenbroek     set[0].events = (netout ? POLLOUT : 0) | (netin ? POLLIN : 0) |
635*7348b5c5SDavid van Moolenbroek 	(netex ? POLLPRI : 0);
636*7348b5c5SDavid van Moolenbroek     set[1].fd = tout;
637*7348b5c5SDavid van Moolenbroek     set[1].events = ttyout ? POLLOUT : 0;
638*7348b5c5SDavid van Moolenbroek     set[2].fd = tin;
639*7348b5c5SDavid van Moolenbroek     set[2].events = ttyin ? POLLIN : 0;
640*7348b5c5SDavid van Moolenbroek 
641*7348b5c5SDavid van Moolenbroek     if ((c = poll(set, 3, dopoll ? 0 : INFTIM)) < 0) {
642*7348b5c5SDavid van Moolenbroek 	if (c == -1) {
643*7348b5c5SDavid van Moolenbroek 		    /*
644*7348b5c5SDavid van Moolenbroek 		     * we can get EINTR if we are in line mode,
645*7348b5c5SDavid van Moolenbroek 		     * and the user does an escape (TSTP), or
646*7348b5c5SDavid van Moolenbroek 		     * some other signal generator.
647*7348b5c5SDavid van Moolenbroek 		     */
648*7348b5c5SDavid van Moolenbroek 	    if (errno == EINTR) {
649*7348b5c5SDavid van Moolenbroek 		return 0;
650*7348b5c5SDavid van Moolenbroek 	    }
651*7348b5c5SDavid van Moolenbroek #ifdef TN3270
652*7348b5c5SDavid van Moolenbroek 		    /*
653*7348b5c5SDavid van Moolenbroek 		     * we can get EBADF if we were in transparent
654*7348b5c5SDavid van Moolenbroek 		     * mode, and the transcom process died.
655*7348b5c5SDavid van Moolenbroek 		    */
656*7348b5c5SDavid van Moolenbroek 	    if (errno == EBADF)
657*7348b5c5SDavid van Moolenbroek 		return 0;
658*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
659*7348b5c5SDavid van Moolenbroek 		    /* I don't like this, does it ever happen? */
660*7348b5c5SDavid van Moolenbroek 	    printf("sleep(5) from telnet, after poll\r\n");
661*7348b5c5SDavid van Moolenbroek 	    sleep(5);
662*7348b5c5SDavid van Moolenbroek 	}
663*7348b5c5SDavid van Moolenbroek 	return 0;
664*7348b5c5SDavid van Moolenbroek     }
665*7348b5c5SDavid van Moolenbroek 
666*7348b5c5SDavid van Moolenbroek     /*
667*7348b5c5SDavid van Moolenbroek      * Any urgent data?
668*7348b5c5SDavid van Moolenbroek      */
669*7348b5c5SDavid van Moolenbroek     if (set[0].revents & POLLPRI) {
670*7348b5c5SDavid van Moolenbroek 	SYNCHing = 1;
671*7348b5c5SDavid van Moolenbroek 	(void) ttyflush(1);	/* flush already enqueued data */
672*7348b5c5SDavid van Moolenbroek     }
673*7348b5c5SDavid van Moolenbroek 
674*7348b5c5SDavid van Moolenbroek     /*
675*7348b5c5SDavid van Moolenbroek      * Something to read from the network...
676*7348b5c5SDavid van Moolenbroek      */
677*7348b5c5SDavid van Moolenbroek     if (set[0].revents & POLLIN) {
678*7348b5c5SDavid van Moolenbroek 	int canread;
679*7348b5c5SDavid van Moolenbroek 
680*7348b5c5SDavid van Moolenbroek 	canread = ring_empty_consecutive(&netiring);
681*7348b5c5SDavid van Moolenbroek 	c = recv(net, (char *)netiring.supply, canread, 0);
682*7348b5c5SDavid van Moolenbroek 	if (c < 0 && errno == EWOULDBLOCK) {
683*7348b5c5SDavid van Moolenbroek 	    c = 0;
684*7348b5c5SDavid van Moolenbroek 	} else if (c <= 0) {
685*7348b5c5SDavid van Moolenbroek 	    return -1;
686*7348b5c5SDavid van Moolenbroek 	}
687*7348b5c5SDavid van Moolenbroek 	if (netdata) {
688*7348b5c5SDavid van Moolenbroek 	    Dump('<', netiring.supply, c);
689*7348b5c5SDavid van Moolenbroek 	}
690*7348b5c5SDavid van Moolenbroek 	if (c)
691*7348b5c5SDavid van Moolenbroek 	    ring_supplied(&netiring, c);
692*7348b5c5SDavid van Moolenbroek 	returnValue = 1;
693*7348b5c5SDavid van Moolenbroek     }
694*7348b5c5SDavid van Moolenbroek 
695*7348b5c5SDavid van Moolenbroek     /*
696*7348b5c5SDavid van Moolenbroek      * Something to read from the tty...
697*7348b5c5SDavid van Moolenbroek      */
698*7348b5c5SDavid van Moolenbroek     if (set[2].revents & POLLIN) {
699*7348b5c5SDavid van Moolenbroek 	c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
700*7348b5c5SDavid van Moolenbroek 	if (c < 0 && errno == EIO)
701*7348b5c5SDavid van Moolenbroek 	    c = 0;
702*7348b5c5SDavid van Moolenbroek 	if (c < 0 && errno == EWOULDBLOCK) {
703*7348b5c5SDavid van Moolenbroek 	    c = 0;
704*7348b5c5SDavid van Moolenbroek 	} else {
705*7348b5c5SDavid van Moolenbroek 	    if (c < 0) {
706*7348b5c5SDavid van Moolenbroek 		return -1;
707*7348b5c5SDavid van Moolenbroek 	    }
708*7348b5c5SDavid van Moolenbroek 	    if (c == 0) {
709*7348b5c5SDavid van Moolenbroek 		/* must be an EOF... */
710*7348b5c5SDavid van Moolenbroek 		if (MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
711*7348b5c5SDavid van Moolenbroek 		    *ttyiring.supply = termEofChar;
712*7348b5c5SDavid van Moolenbroek 		    c = 1;
713*7348b5c5SDavid van Moolenbroek 		} else {
714*7348b5c5SDavid van Moolenbroek 		    clienteof = 1;
715*7348b5c5SDavid van Moolenbroek 		    shutdown(net, 1);
716*7348b5c5SDavid van Moolenbroek 		    return 0;
717*7348b5c5SDavid van Moolenbroek 		}
718*7348b5c5SDavid van Moolenbroek 	    }
719*7348b5c5SDavid van Moolenbroek 	    if (termdata) {
720*7348b5c5SDavid van Moolenbroek 		Dump('<', ttyiring.supply, c);
721*7348b5c5SDavid van Moolenbroek 	    }
722*7348b5c5SDavid van Moolenbroek 	    ring_supplied(&ttyiring, c);
723*7348b5c5SDavid van Moolenbroek 	}
724*7348b5c5SDavid van Moolenbroek 	returnValue = 1;		/* did something useful */
725*7348b5c5SDavid van Moolenbroek     }
726*7348b5c5SDavid van Moolenbroek 
727*7348b5c5SDavid van Moolenbroek     if (set[0].revents & POLLOUT) {
728*7348b5c5SDavid van Moolenbroek 	returnValue |= netflush();
729*7348b5c5SDavid van Moolenbroek     }
730*7348b5c5SDavid van Moolenbroek 
731*7348b5c5SDavid van Moolenbroek     if (set[1].revents & (POLLHUP|POLLNVAL))
732*7348b5c5SDavid van Moolenbroek 	return(-1);
733*7348b5c5SDavid van Moolenbroek 
734*7348b5c5SDavid van Moolenbroek     if (set[1].revents & POLLOUT) {
735*7348b5c5SDavid van Moolenbroek 	returnValue |= (ttyflush(SYNCHing|flushout) > 0);
736*7348b5c5SDavid van Moolenbroek     }
737*7348b5c5SDavid van Moolenbroek 
738*7348b5c5SDavid van Moolenbroek     return returnValue;
739*7348b5c5SDavid van Moolenbroek }
740