xref: /netbsd-src/usr.bin/telnet/sys_bsd.c (revision 4f0678d2a5e69d811a26d8d5ac2dc11be2e669da)
1*4f0678d2Smaya /*	$NetBSD: sys_bsd.c,v 1.40 2018/12/14 06:28:49 maya Exp $	*/
2077a490aSthorpej 
361f28255Scgd /*
40582c913Scgd  * Copyright (c) 1988, 1990, 1993
50582c913Scgd  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32434ea11bSchristos #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
34077a490aSthorpej #if 0
35077a490aSthorpej from: static char sccsid[] = "@(#)sys_bsd.c	8.4 (Berkeley) 5/30/95";
36077a490aSthorpej #else
37*4f0678d2Smaya __RCSID("$NetBSD: sys_bsd.c,v 1.40 2018/12/14 06:28:49 maya Exp $");
38077a490aSthorpej #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd 
4161f28255Scgd /*
4261f28255Scgd  * The following routines try to encapsulate what is system dependent
4361f28255Scgd  * (at least between 4.x and dos) which is used in telnet.c.
4461f28255Scgd  */
4561f28255Scgd 
4661f28255Scgd 
4761f28255Scgd #include <fcntl.h>
4861f28255Scgd #include <sys/types.h>
4961f28255Scgd #include <sys/time.h>
5061f28255Scgd #include <sys/socket.h>
5161f28255Scgd #include <signal.h>
52434ea11bSchristos #include <stdlib.h>
53434ea11bSchristos #include <unistd.h>
5461f28255Scgd #include <errno.h>
556248b528Sitojun #include <poll.h>
5661f28255Scgd #include <arpa/telnet.h>
5761f28255Scgd 
5861f28255Scgd #include "ring.h"
5961f28255Scgd #include "defines.h"
6061f28255Scgd #include "externs.h"
6161f28255Scgd #include "types.h"
6261f28255Scgd 
636aa0aef1Smaya void susp(int);
646aa0aef1Smaya void ayt(int);
6561f28255Scgd 
666aa0aef1Smaya void intr(int);
676aa0aef1Smaya void intr2(int);
686aa0aef1Smaya void sendwin(int);
69434ea11bSchristos 
70434ea11bSchristos 
7161f28255Scgd int
7261f28255Scgd 	tout,			/* Output file descriptor */
7361f28255Scgd 	tin,			/* Input file descriptor */
7461f28255Scgd 	net;
7561f28255Scgd 
76fcdbba42Schristos struct	termios old_tc = { .c_iflag = 0 };
7721f5307cSitojun extern struct termios new_tc;
7861f28255Scgd 
7961f28255Scgd void
init_sys(void)8026583868Schristos init_sys(void)
8161f28255Scgd {
8261f28255Scgd     tout = fileno(stdout);
8361f28255Scgd     tin = fileno(stdin);
8461f28255Scgd 
8561f28255Scgd     errno = 0;
8661f28255Scgd }
8761f28255Scgd 
8861f28255Scgd 
8961f28255Scgd int
TerminalWrite(char * buf,int n)9026583868Schristos TerminalWrite(char *buf, int  n)
9161f28255Scgd {
9261f28255Scgd     return write(tout, buf, n);
9361f28255Scgd }
9461f28255Scgd 
9561f28255Scgd int
TerminalRead(unsigned char * buf,int n)9626583868Schristos TerminalRead(unsigned char *buf, int  n)
9761f28255Scgd {
9861f28255Scgd     return read(tin, buf, n);
9961f28255Scgd }
10061f28255Scgd 
10161f28255Scgd /*
10261f28255Scgd  *
10361f28255Scgd  */
10461f28255Scgd 
10561f28255Scgd int
TerminalAutoFlush(void)10626583868Schristos TerminalAutoFlush(void)
10761f28255Scgd {
10861f28255Scgd     return 1;
10961f28255Scgd }
11061f28255Scgd 
11161f28255Scgd #ifdef	KLUDGELINEMODE
11261f28255Scgd extern int kludgelinemode;
11361f28255Scgd #endif
11461f28255Scgd /*
11561f28255Scgd  * TerminalSpecialChars()
11661f28255Scgd  *
11761f28255Scgd  * Look at an input character to see if it is a special character
11861f28255Scgd  * and decide what to do.
11961f28255Scgd  *
12061f28255Scgd  * Output:
12161f28255Scgd  *
12261f28255Scgd  *	0	Don't add this character.
12361f28255Scgd  *	1	Do add this character
12461f28255Scgd  */
12561f28255Scgd 
12661f28255Scgd int
TerminalSpecialChars(int c)12726583868Schristos TerminalSpecialChars(int c)
12861f28255Scgd {
12961f28255Scgd     if (c == termIntChar) {
13061f28255Scgd 	intp();
13161f28255Scgd 	return 0;
13261f28255Scgd     } else if (c == termQuitChar) {
13361f28255Scgd #ifdef	KLUDGELINEMODE
13461f28255Scgd 	if (kludgelinemode)
13561f28255Scgd 	    sendbrk();
13661f28255Scgd 	else
13761f28255Scgd #endif
13861f28255Scgd 	    sendabort();
13961f28255Scgd 	return 0;
14061f28255Scgd     } else if (c == termEofChar) {
14161f28255Scgd 	if (my_want_state_is_will(TELOPT_LINEMODE)) {
14261f28255Scgd 	    sendeof();
14361f28255Scgd 	    return 0;
14461f28255Scgd 	}
14561f28255Scgd 	return 1;
14661f28255Scgd     } else if (c == termSuspChar) {
14761f28255Scgd 	sendsusp();
14861f28255Scgd 	return(0);
14961f28255Scgd     } else if (c == termFlushChar) {
15061f28255Scgd 	xmitAO();		/* Transmit Abort Output */
15161f28255Scgd 	return 0;
15261f28255Scgd     } else if (!MODE_LOCAL_CHARS(globalmode)) {
15361f28255Scgd 	if (c == termKillChar) {
15461f28255Scgd 	    xmitEL();
15561f28255Scgd 	    return 0;
15661f28255Scgd 	} else if (c == termEraseChar) {
15761f28255Scgd 	    xmitEC();		/* Transmit Erase Character */
15861f28255Scgd 	    return 0;
15961f28255Scgd 	}
16061f28255Scgd     }
16161f28255Scgd     return 1;
16261f28255Scgd }
16361f28255Scgd 
16461f28255Scgd 
16561f28255Scgd /*
16661f28255Scgd  * Flush output to the terminal
16761f28255Scgd  */
16861f28255Scgd 
16961f28255Scgd void
TerminalFlushOutput(void)17026583868Schristos TerminalFlushOutput(void)
17161f28255Scgd {
172291a252cSjdolecek     int com = 0;
173291a252cSjdolecek     (void) ioctl(fileno(stdout), TIOCFLUSH, &com);
17461f28255Scgd }
17561f28255Scgd 
17661f28255Scgd void
TerminalSaveState(void)17726583868Schristos TerminalSaveState(void)
17861f28255Scgd {
17961f28255Scgd     tcgetattr(0, &old_tc);
18061f28255Scgd 
18161f28255Scgd     new_tc = old_tc;
18261f28255Scgd }
18361f28255Scgd 
18461f28255Scgd cc_t *
tcval(int func)18526583868Schristos tcval(int func)
18661f28255Scgd {
18761f28255Scgd     switch(func) {
18861f28255Scgd     case SLC_IP:	return(&termIntChar);
18961f28255Scgd     case SLC_ABORT:	return(&termQuitChar);
19061f28255Scgd     case SLC_EOF:	return(&termEofChar);
19161f28255Scgd     case SLC_EC:	return(&termEraseChar);
19261f28255Scgd     case SLC_EL:	return(&termKillChar);
19361f28255Scgd     case SLC_XON:	return(&termStartChar);
19461f28255Scgd     case SLC_XOFF:	return(&termStopChar);
19561f28255Scgd     case SLC_FORW1:	return(&termForw1Char);
19661f28255Scgd     case SLC_FORW2:	return(&termForw2Char);
19761f28255Scgd     case SLC_AO:	return(&termFlushChar);
19861f28255Scgd     case SLC_SUSP:	return(&termSuspChar);
19961f28255Scgd     case SLC_EW:	return(&termWerasChar);
20061f28255Scgd     case SLC_RP:	return(&termRprntChar);
20161f28255Scgd     case SLC_LNEXT:	return(&termLiteralNextChar);
20261f28255Scgd     case SLC_AYT:	return(&termAytChar);
20361f28255Scgd 
20461f28255Scgd     case SLC_SYNCH:
20561f28255Scgd     case SLC_BRK:
20661f28255Scgd     case SLC_EOR:
20761f28255Scgd     default:
20861f28255Scgd 	return((cc_t *)0);
20961f28255Scgd     }
21061f28255Scgd }
21161f28255Scgd 
21261f28255Scgd void
TerminalDefaultChars(void)21326583868Schristos TerminalDefaultChars(void)
21461f28255Scgd {
215583a8146Sjtk     memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
21661f28255Scgd }
21761f28255Scgd 
21861f28255Scgd /*
21961f28255Scgd  * TerminalNewMode - set up terminal to a specific mode.
22061f28255Scgd  *	MODE_ECHO: do local terminal echo
22161f28255Scgd  *	MODE_FLOW: do local flow control
22261f28255Scgd  *	MODE_TRAPSIG: do local mapping to TELNET IAC sequences
22361f28255Scgd  *	MODE_EDIT: do local line editing
22461f28255Scgd  *
22561f28255Scgd  *	Command mode:
22661f28255Scgd  *		MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
22761f28255Scgd  *		local echo
22861f28255Scgd  *		local editing
22961f28255Scgd  *		local xon/xoff
23061f28255Scgd  *		local signal mapping
23161f28255Scgd  *
23261f28255Scgd  *	Linemode:
23361f28255Scgd  *		local/no editing
23461f28255Scgd  *	Both Linemode and Single Character mode:
23561f28255Scgd  *		local/remote echo
23661f28255Scgd  *		local/no xon/xoff
23761f28255Scgd  *		local/no signal mapping
23861f28255Scgd  */
23961f28255Scgd 
24061f28255Scgd 
24161f28255Scgd void
TerminalNewMode(int f)24226583868Schristos TerminalNewMode(int f)
24361f28255Scgd {
24461f28255Scgd     static int prevmode = 0;
24521f5307cSitojun     struct termios tmp_tc;
24661f28255Scgd     int onoff;
24761f28255Scgd     int old;
24861f28255Scgd     cc_t esc;
24961f28255Scgd 
25061f28255Scgd     globalmode = f&~MODE_FORCE;
25161f28255Scgd     if (prevmode == f)
25261f28255Scgd 	return;
25361f28255Scgd 
25461f28255Scgd     /*
25561f28255Scgd      * Write any outstanding data before switching modes
25661f28255Scgd      * ttyflush() returns 0 only when there is no more data
25761f28255Scgd      * left to write out, it returns -1 if it couldn't do
25861f28255Scgd      * anything at all, otherwise it returns 1 + the number
25961f28255Scgd      * of characters left to write.
26061f28255Scgd #ifndef	USE_TERMIO
261be6d6ca0Schristos      * We would really like to ask the kernel to wait for the output
26261f28255Scgd      * to drain, like we can do with the TCSADRAIN, but we don't have
26361f28255Scgd      * that option.  The only ioctl that waits for the output to
26461f28255Scgd      * drain, TIOCSETP, also flushes the input queue, which is NOT
26561f28255Scgd      * what we want (TIOCSETP is like TCSADFLUSH).
26661f28255Scgd #endif
26761f28255Scgd      */
26861f28255Scgd     old = ttyflush(SYNCHing|flushout);
26961f28255Scgd     if (old < 0 || old > 1) {
27061f28255Scgd 	tcgetattr(tin, &tmp_tc);
27161f28255Scgd 	do {
27261f28255Scgd 	    /*
27361f28255Scgd 	     * Wait for data to drain, then flush again.
27461f28255Scgd 	     */
27561f28255Scgd 	    tcsetattr(tin, TCSADRAIN, &tmp_tc);
27661f28255Scgd 	    old = ttyflush(SYNCHing|flushout);
27761f28255Scgd 	} while (old < 0 || old > 1);
27861f28255Scgd     }
27961f28255Scgd 
28061f28255Scgd     old = prevmode;
28161f28255Scgd     prevmode = f&~MODE_FORCE;
28261f28255Scgd     tmp_tc = new_tc;
28361f28255Scgd 
28461f28255Scgd     if (f&MODE_ECHO) {
28561f28255Scgd 	tmp_tc.c_lflag |= ECHO;
28661f28255Scgd 	tmp_tc.c_oflag |= ONLCR;
28761f28255Scgd 	if (crlf)
28861f28255Scgd 		tmp_tc.c_iflag |= ICRNL;
28961f28255Scgd     } else {
29061f28255Scgd 	tmp_tc.c_lflag &= ~ECHO;
29161f28255Scgd 	tmp_tc.c_oflag &= ~ONLCR;
29261f28255Scgd # ifdef notdef
29361f28255Scgd 	if (crlf)
29461f28255Scgd 		tmp_tc.c_iflag &= ~ICRNL;
29561f28255Scgd # endif
29661f28255Scgd     }
29761f28255Scgd 
29861f28255Scgd     if ((f&MODE_FLOW) == 0) {
2990582c913Scgd 	tmp_tc.c_iflag &= ~(IXOFF|IXON);	/* Leave the IXANY bit alone */
30061f28255Scgd     } else {
3010582c913Scgd 	if (restartany < 0) {
3020582c913Scgd 		tmp_tc.c_iflag |= IXOFF|IXON;	/* Leave the IXANY bit alone */
3030582c913Scgd 	} else if (restartany > 0) {
3040582c913Scgd 		tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
3050582c913Scgd 	} else {
3060582c913Scgd 		tmp_tc.c_iflag |= IXOFF|IXON;
3070582c913Scgd 		tmp_tc.c_iflag &= ~IXANY;
3080582c913Scgd 	}
30961f28255Scgd     }
31061f28255Scgd 
31161f28255Scgd     if ((f&MODE_TRAPSIG) == 0) {
31261f28255Scgd 	tmp_tc.c_lflag &= ~ISIG;
31361f28255Scgd 	localchars = 0;
31461f28255Scgd     } else {
31561f28255Scgd 	tmp_tc.c_lflag |= ISIG;
31661f28255Scgd 	localchars = 1;
31761f28255Scgd     }
31861f28255Scgd 
31961f28255Scgd     if (f&MODE_EDIT) {
32061f28255Scgd 	tmp_tc.c_lflag |= ICANON;
32161f28255Scgd     } else {
32261f28255Scgd 	tmp_tc.c_lflag &= ~ICANON;
32361f28255Scgd 	tmp_tc.c_iflag &= ~ICRNL;
32461f28255Scgd 	tmp_tc.c_cc[VMIN] = 1;
32561f28255Scgd 	tmp_tc.c_cc[VTIME] = 0;
32661f28255Scgd     }
32761f28255Scgd 
32861f28255Scgd     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
329ebe345eaStls 	tmp_tc.c_lflag &= ~IEXTEN;
33061f28255Scgd     }
33161f28255Scgd 
33261f28255Scgd     if (f&MODE_SOFT_TAB) {
33361f28255Scgd # ifdef	OXTABS
33461f28255Scgd 	tmp_tc.c_oflag |= OXTABS;
33561f28255Scgd # endif
33661f28255Scgd # ifdef	TABDLY
33761f28255Scgd 	tmp_tc.c_oflag &= ~TABDLY;
33861f28255Scgd 	tmp_tc.c_oflag |= TAB3;
33961f28255Scgd # endif
34061f28255Scgd     } else {
34161f28255Scgd # ifdef	OXTABS
34261f28255Scgd 	tmp_tc.c_oflag &= ~OXTABS;
34361f28255Scgd # endif
34461f28255Scgd # ifdef	TABDLY
34561f28255Scgd 	tmp_tc.c_oflag &= ~TABDLY;
34661f28255Scgd # endif
34761f28255Scgd     }
34861f28255Scgd 
34961f28255Scgd     if (f&MODE_LIT_ECHO) {
35061f28255Scgd # ifdef	ECHOCTL
35161f28255Scgd 	tmp_tc.c_lflag &= ~ECHOCTL;
35261f28255Scgd # endif
35361f28255Scgd     } else {
35461f28255Scgd # ifdef	ECHOCTL
35561f28255Scgd 	tmp_tc.c_lflag |= ECHOCTL;
35661f28255Scgd # endif
35761f28255Scgd     }
35861f28255Scgd 
35961f28255Scgd     if (f == -1) {
36061f28255Scgd 	onoff = 0;
36161f28255Scgd     } else {
36261f28255Scgd 	if (f & MODE_INBIN)
36361f28255Scgd 		tmp_tc.c_iflag &= ~ISTRIP;
36461f28255Scgd 	else
36561f28255Scgd 		tmp_tc.c_iflag |= ISTRIP;
36661f28255Scgd 	if (f & MODE_OUTBIN) {
36761f28255Scgd 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
36861f28255Scgd 		tmp_tc.c_cflag |= CS8;
36961f28255Scgd 		tmp_tc.c_oflag &= ~OPOST;
37061f28255Scgd 	} else {
37161f28255Scgd 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
37261f28255Scgd 		tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
37361f28255Scgd 		tmp_tc.c_oflag |= OPOST;
37461f28255Scgd 	}
37561f28255Scgd 	onoff = 1;
37661f28255Scgd     }
37761f28255Scgd 
37861f28255Scgd     if (f != -1) {
37961f28255Scgd 	(void) signal(SIGTSTP, susp);
38061f28255Scgd 	(void) signal(SIGINFO, ayt);
38161f28255Scgd #if	defined(USE_TERMIO) && defined(NOKERNINFO)
38261f28255Scgd 	tmp_tc.c_lflag |= NOKERNINFO;
38361f28255Scgd #endif
38461f28255Scgd 	/*
38561f28255Scgd 	 * We don't want to process ^Y here.  It's just another
38661f28255Scgd 	 * character that we'll pass on to the back end.  It has
38761f28255Scgd 	 * to process it because it will be processed when the
38861f28255Scgd 	 * user attempts to read it, not when we send it.
38961f28255Scgd 	 */
39061f28255Scgd # ifdef	VDSUSP
39161f28255Scgd 	tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
39261f28255Scgd # endif
39361f28255Scgd 	/*
39461f28255Scgd 	 * If the VEOL character is already set, then use VEOL2,
39561f28255Scgd 	 * otherwise use VEOL.
39661f28255Scgd 	 */
39761f28255Scgd 	esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
39861f28255Scgd 	if ((tmp_tc.c_cc[VEOL] != esc)
39961f28255Scgd # ifdef	VEOL2
40061f28255Scgd 	    && (tmp_tc.c_cc[VEOL2] != esc)
40161f28255Scgd # endif
40261f28255Scgd 	    ) {
40361f28255Scgd 		if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
40461f28255Scgd 		    tmp_tc.c_cc[VEOL] = esc;
40561f28255Scgd # ifdef	VEOL2
40661f28255Scgd 		else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
40761f28255Scgd 		    tmp_tc.c_cc[VEOL2] = esc;
40861f28255Scgd # endif
40961f28255Scgd 	}
41061f28255Scgd     } else {
411797d779cSwiz 	(void) signal(SIGINFO, (void (*)(int)) ayt_status);
41261f28255Scgd 	(void) signal(SIGTSTP, SIG_DFL);
41361f28255Scgd 	(void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
41461f28255Scgd 	tmp_tc = old_tc;
41561f28255Scgd     }
41661f28255Scgd     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
41761f28255Scgd 	tcsetattr(tin, TCSANOW, &tmp_tc);
41861f28255Scgd 
419*4f0678d2Smaya     ioctl(tin, FIONBIO, &onoff);
420*4f0678d2Smaya     ioctl(tout, FIONBIO, &onoff);
42161f28255Scgd 
42261f28255Scgd }
42361f28255Scgd 
42461f28255Scgd void
TerminalSpeeds(long * ispeed,long * ospeed)42526583868Schristos TerminalSpeeds(long *ispeed, long *ospeed)
42661f28255Scgd {
427797d779cSwiz     long in, out;
42861f28255Scgd 
42961f28255Scgd     out = cfgetospeed(&old_tc);
43061f28255Scgd     in = cfgetispeed(&old_tc);
431aa20739eSmrg     if (in == 0) {
43261f28255Scgd 	in = out;
43361f28255Scgd 
434583a8146Sjtk 	*ispeed = in;
435583a8146Sjtk 	*ospeed = out;
43661f28255Scgd     }
437aa20739eSmrg }
43861f28255Scgd 
43961f28255Scgd int
TerminalWindowSize(long * rows,long * cols)44026583868Schristos TerminalWindowSize(long *rows, long *cols)
44161f28255Scgd {
44261f28255Scgd     struct winsize ws;
44361f28255Scgd 
44461f28255Scgd     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
44561f28255Scgd 	*rows = ws.ws_row;
44661f28255Scgd 	*cols = ws.ws_col;
44761f28255Scgd 	return 1;
44861f28255Scgd     }
44961f28255Scgd     return 0;
45061f28255Scgd }
45161f28255Scgd 
45261f28255Scgd int
NetClose(int fd)45326583868Schristos NetClose(int fd)
45461f28255Scgd {
45561f28255Scgd     return close(fd);
45661f28255Scgd }
45761f28255Scgd 
45861f28255Scgd /*
45961f28255Scgd  * Various signal handling routines.
46061f28255Scgd  */
46161f28255Scgd 
46261f28255Scgd /* ARGSUSED */
4636aa0aef1Smaya void
intr(int sig)46426583868Schristos intr(int sig)
46561f28255Scgd {
46661f28255Scgd     if (localchars) {
46761f28255Scgd 	intp();
46861f28255Scgd 	return;
46961f28255Scgd     }
47061f28255Scgd     setcommandmode();
47161f28255Scgd     longjmp(toplevel, -1);
47261f28255Scgd }
47361f28255Scgd 
47461f28255Scgd /* ARGSUSED */
4756aa0aef1Smaya void
intr2(int sig)47626583868Schristos intr2(int sig)
47761f28255Scgd {
47861f28255Scgd     if (localchars) {
47961f28255Scgd #ifdef	KLUDGELINEMODE
48061f28255Scgd 	if (kludgelinemode)
48161f28255Scgd 	    sendbrk();
48261f28255Scgd 	else
48361f28255Scgd #endif
48461f28255Scgd 	    sendabort();
48561f28255Scgd 	return;
48661f28255Scgd     }
48761f28255Scgd }
48861f28255Scgd 
48961f28255Scgd /* ARGSUSED */
4906aa0aef1Smaya void
susp(int sig)49126583868Schristos susp(int sig)
49261f28255Scgd {
49361f28255Scgd     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
49461f28255Scgd 	return;
49561f28255Scgd     if (localchars)
49661f28255Scgd 	sendsusp();
49761f28255Scgd }
49861f28255Scgd 
49961f28255Scgd /* ARGSUSED */
5006aa0aef1Smaya void
sendwin(int sig)50126583868Schristos sendwin(int sig)
50261f28255Scgd {
50361f28255Scgd     if (connected) {
50461f28255Scgd 	sendnaws();
50561f28255Scgd     }
50661f28255Scgd }
50761f28255Scgd 
50861f28255Scgd /* ARGSUSED */
5096aa0aef1Smaya void
ayt(int sig)51026583868Schristos ayt(int sig)
51161f28255Scgd {
51261f28255Scgd     if (connected)
51361f28255Scgd 	sendayt();
51461f28255Scgd     else
51561f28255Scgd 	ayt_status();
51661f28255Scgd }
51761f28255Scgd 
51861f28255Scgd 
51961f28255Scgd void
sys_telnet_init(void)52026583868Schristos sys_telnet_init(void)
52161f28255Scgd {
5225b38d170Smaya     int one = 1;
5235b38d170Smaya 
52461f28255Scgd     (void) signal(SIGINT, intr);
52561f28255Scgd     (void) signal(SIGQUIT, intr2);
526209ebbabSheas     (void) signal(SIGPIPE, SIG_IGN);
52761f28255Scgd     (void) signal(SIGWINCH, sendwin);
52861f28255Scgd     (void) signal(SIGTSTP, susp);
52961f28255Scgd     (void) signal(SIGINFO, ayt);
53061f28255Scgd 
53161f28255Scgd     setconnmode(0);
53261f28255Scgd 
5335b38d170Smaya     ioctl(net, FIONBIO, &one);
5345b38d170Smaya     if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) {
5355b38d170Smaya 	perror("setsockopt");
53661f28255Scgd     }
53761f28255Scgd }
53861f28255Scgd 
53961f28255Scgd /*
54061f28255Scgd  * Process rings -
54161f28255Scgd  *
54261f28255Scgd  *	This routine tries to fill up/empty our various rings.
54361f28255Scgd  *
54461f28255Scgd  *	The parameter specifies whether this is a poll operation,
54561f28255Scgd  *	or a block-until-something-happens operation.
54661f28255Scgd  *
547be6d6ca0Schristos  *	The return value is 1 if something happened, 0 if not, < 0 if an
548f05e6f1aSwiz  *	error occurred.
54961f28255Scgd  */
55061f28255Scgd 
55161f28255Scgd int
process_rings(int netin,int netout,int netex,int ttyin,int ttyout,int dopoll)55226583868Schristos process_rings(int netin, int netout, int netex, int ttyin, int ttyout,
55326583868Schristos     int dopoll)		/* If 0, then block until something to do */
55461f28255Scgd {
5556053f554Smycroft     struct pollfd set[3];
556797d779cSwiz     int c;
55761f28255Scgd 		/* One wants to be a bit careful about setting returnValue
55861f28255Scgd 		 * to one, since a one implies we did some useful work,
55961f28255Scgd 		 * and therefore probably won't be called to block next
56061f28255Scgd 		 * time (TN3270 mode only).
56161f28255Scgd 		 */
56261f28255Scgd     int returnValue = 0;
563851f23b9Smcr 
5646053f554Smycroft     set[0].fd = net;
5656053f554Smycroft     set[0].events = (netout ? POLLOUT : 0) | (netin ? POLLIN : 0) |
5666053f554Smycroft 	(netex ? POLLPRI : 0);
5676053f554Smycroft     set[1].fd = tout;
5686053f554Smycroft     set[1].events = ttyout ? POLLOUT : 0;
5696053f554Smycroft     set[2].fd = tin;
5706053f554Smycroft     set[2].events = ttyin ? POLLIN : 0;
57161f28255Scgd 
5726053f554Smycroft     if ((c = poll(set, 3, dopoll ? 0 : INFTIM)) < 0) {
57361f28255Scgd 	if (c == -1) {
57461f28255Scgd 		    /*
57561f28255Scgd 		     * we can get EINTR if we are in line mode,
57661f28255Scgd 		     * and the user does an escape (TSTP), or
57761f28255Scgd 		     * some other signal generator.
57861f28255Scgd 		     */
57961f28255Scgd 	    if (errno == EINTR) {
58061f28255Scgd 		return 0;
58161f28255Scgd 	    }
58261f28255Scgd 		    /* I don't like this, does it ever happen? */
583be6d6ca0Schristos 	    printf("sleep(5) from telnet, after poll\r\n");
58461f28255Scgd 	    sleep(5);
58561f28255Scgd 	}
58661f28255Scgd 	return 0;
58761f28255Scgd     }
58861f28255Scgd 
58961f28255Scgd     /*
59061f28255Scgd      * Any urgent data?
59161f28255Scgd      */
5926053f554Smycroft     if (set[0].revents & POLLPRI) {
59361f28255Scgd 	SYNCHing = 1;
59461f28255Scgd 	(void) ttyflush(1);	/* flush already enqueued data */
59561f28255Scgd     }
59661f28255Scgd 
59761f28255Scgd     /*
59861f28255Scgd      * Something to read from the network...
59961f28255Scgd      */
6006053f554Smycroft     if (set[0].revents & POLLIN) {
60161f28255Scgd 	int canread;
60261f28255Scgd 
60361f28255Scgd 	canread = ring_empty_consecutive(&netiring);
6040582c913Scgd 	c = recv(net, (char *)netiring.supply, canread, 0);
60561f28255Scgd 	if (c < 0 && errno == EWOULDBLOCK) {
60661f28255Scgd 	    c = 0;
60761f28255Scgd 	} else if (c <= 0) {
60861f28255Scgd 	    return -1;
60961f28255Scgd 	}
61061f28255Scgd 	if (netdata) {
61161f28255Scgd 	    Dump('<', netiring.supply, c);
61261f28255Scgd 	}
61361f28255Scgd 	if (c)
61461f28255Scgd 	    ring_supplied(&netiring, c);
61561f28255Scgd 	returnValue = 1;
61661f28255Scgd     }
61761f28255Scgd 
61861f28255Scgd     /*
61961f28255Scgd      * Something to read from the tty...
62061f28255Scgd      */
6216053f554Smycroft     if (set[2].revents & POLLIN) {
62261f28255Scgd 	c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
623583a8146Sjtk 	if (c < 0 && errno == EIO)
624583a8146Sjtk 	    c = 0;
62561f28255Scgd 	if (c < 0 && errno == EWOULDBLOCK) {
62661f28255Scgd 	    c = 0;
62761f28255Scgd 	} else {
62842a670f9Sjtk 	    if (c < 0) {
62942a670f9Sjtk 		return -1;
63042a670f9Sjtk 	    }
63142a670f9Sjtk 	    if (c == 0) {
63261f28255Scgd 		/* must be an EOF... */
63342a670f9Sjtk 		if (MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
63461f28255Scgd 		    *ttyiring.supply = termEofChar;
63561f28255Scgd 		    c = 1;
63642a670f9Sjtk 		} else {
63742a670f9Sjtk 		    clienteof = 1;
63842a670f9Sjtk 		    shutdown(net, 1);
63942a670f9Sjtk 		    return 0;
64061f28255Scgd 		}
64161f28255Scgd 	    }
64261f28255Scgd 	    if (termdata) {
64361f28255Scgd 		Dump('<', ttyiring.supply, c);
64461f28255Scgd 	    }
64561f28255Scgd 	    ring_supplied(&ttyiring, c);
64661f28255Scgd 	}
64761f28255Scgd 	returnValue = 1;		/* did something useful */
64861f28255Scgd     }
64961f28255Scgd 
6506053f554Smycroft     if (set[0].revents & POLLOUT) {
65161f28255Scgd 	returnValue |= netflush();
65261f28255Scgd     }
653209ebbabSheas 
654209ebbabSheas     if (set[1].revents & (POLLHUP|POLLNVAL))
655209ebbabSheas 	return(-1);
656209ebbabSheas 
6576053f554Smycroft     if (set[1].revents & POLLOUT) {
65861f28255Scgd 	returnValue |= (ttyflush(SYNCHing|flushout) > 0);
65961f28255Scgd     }
66061f28255Scgd 
66161f28255Scgd     return returnValue;
66261f28255Scgd }
663