xref: /titanic_44/usr/src/cmd/cmd-inet/usr.bin/telnet/sys_bsd.c (revision de81e71e031139a0a7f13b7bf64152c3faa76698)
17c478bd9Sstevel@tonic-gate /*
2*de81e71eSTim Marsland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 1990, 1993
87c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
117c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
127c478bd9Sstevel@tonic-gate  * are met:
137c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
147c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
157c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
167c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
177c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
187c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
197c478bd9Sstevel@tonic-gate  *    must display the following acknowledgement:
207c478bd9Sstevel@tonic-gate  *	This product includes software developed by the University of
217c478bd9Sstevel@tonic-gate  *	California, Berkeley and its contributors.
227c478bd9Sstevel@tonic-gate  * 4. Neither the name of the University nor the names of its contributors
237c478bd9Sstevel@tonic-gate  *    may be used to endorse or promote products derived from this software
247c478bd9Sstevel@tonic-gate  *    without specific prior written permission.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
277c478bd9Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297c478bd9Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
307c478bd9Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
317c478bd9Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
327c478bd9Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
337c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
347c478bd9Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
357c478bd9Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
367c478bd9Sstevel@tonic-gate  * SUCH DAMAGE.
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #ifndef lint
417c478bd9Sstevel@tonic-gate static char sccsid[] = "@(#)sys_bsd.c	8.1 (Berkeley) 6/6/93";
427c478bd9Sstevel@tonic-gate #endif /* not lint */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * The following routines try to encapsulate what is system dependent
467c478bd9Sstevel@tonic-gate  * (at least between 4.x and dos) which is used in telnet.c.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <fcntl.h>
517c478bd9Sstevel@tonic-gate #include <sys/types.h>
527c478bd9Sstevel@tonic-gate #include <sys/time.h>
537c478bd9Sstevel@tonic-gate #include <sys/socket.h>
547c478bd9Sstevel@tonic-gate #include <sys/uio.h>
557c478bd9Sstevel@tonic-gate #include <signal.h>
567c478bd9Sstevel@tonic-gate #include <errno.h>
577c478bd9Sstevel@tonic-gate #include <arpa/telnet.h>
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #include "ring.h"
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #include "defines.h"
627c478bd9Sstevel@tonic-gate #include "externs.h"
637c478bd9Sstevel@tonic-gate #include "types.h"
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	SIG_FUNC_RET	void
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate int tout;			/* Output file descriptor */
687c478bd9Sstevel@tonic-gate static int tin;			/* Input file descriptor */
697c478bd9Sstevel@tonic-gate int net = -1;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
737c478bd9Sstevel@tonic-gate struct	tchars otc = { 0 }, ntc = { 0 };
747c478bd9Sstevel@tonic-gate struct	ltchars oltc = { 0 }, nltc = { 0 };
757c478bd9Sstevel@tonic-gate struct	sgttyb ottyb = { 0 }, nttyb = { 0 };
767c478bd9Sstevel@tonic-gate int	olmode = 0;
777c478bd9Sstevel@tonic-gate #define	cfgetispeed(ptr)	(ptr)->sg_ispeed
787c478bd9Sstevel@tonic-gate #define	cfgetospeed(ptr)	(ptr)->sg_ospeed
797c478bd9Sstevel@tonic-gate #define	old_tc ottyb
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate #else	/* USE_TERMIO */
827c478bd9Sstevel@tonic-gate static struct	termio old_tc = { 0 };
837c478bd9Sstevel@tonic-gate extern struct termio new_tc;
847c478bd9Sstevel@tonic-gate #endif	/* USE_TERMIO */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static fd_set ibits, obits, xbits;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static SIG_FUNC_RET susp(int);
897c478bd9Sstevel@tonic-gate void fatal_tty_error(char *doing_what);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate void
init_sys()937c478bd9Sstevel@tonic-gate init_sys()
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	tout = fileno(stdout);
967c478bd9Sstevel@tonic-gate 	tin = fileno(stdin);
977c478bd9Sstevel@tonic-gate 	FD_ZERO(&ibits);
987c478bd9Sstevel@tonic-gate 	FD_ZERO(&obits);
997c478bd9Sstevel@tonic-gate 	FD_ZERO(&xbits);
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	errno = 0;
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate int
TerminalWrite(buf,n)1067c478bd9Sstevel@tonic-gate TerminalWrite(buf, n)
1077c478bd9Sstevel@tonic-gate 	char *buf;
1087c478bd9Sstevel@tonic-gate 	int  n;
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate 	return (write(tout, buf, n));
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate static int
TerminalRead(buf,n)1147c478bd9Sstevel@tonic-gate TerminalRead(buf, n)
1157c478bd9Sstevel@tonic-gate 	char *buf;
1167c478bd9Sstevel@tonic-gate 	int  n;
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	return (read(tin, buf, n));
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate #ifdef	KLUDGELINEMODE
1227c478bd9Sstevel@tonic-gate extern int kludgelinemode;
1237c478bd9Sstevel@tonic-gate #endif
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate  * TerminalSpecialChars()
1267c478bd9Sstevel@tonic-gate  *
1277c478bd9Sstevel@tonic-gate  * Look at an input character to see if it is a special character
1287c478bd9Sstevel@tonic-gate  * and decide what to do.
1297c478bd9Sstevel@tonic-gate  *
1307c478bd9Sstevel@tonic-gate  * Output:
1317c478bd9Sstevel@tonic-gate  *
1327c478bd9Sstevel@tonic-gate  *	0	Don't add this character.
1337c478bd9Sstevel@tonic-gate  *	1	Do add this character
1347c478bd9Sstevel@tonic-gate  */
1357c478bd9Sstevel@tonic-gate int
TerminalSpecialChars(c)1367c478bd9Sstevel@tonic-gate TerminalSpecialChars(c)
1377c478bd9Sstevel@tonic-gate 	int	c;
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	/*
1407c478bd9Sstevel@tonic-gate 	 * Don't check for signal characters here.  If MODE_TRAPSIG is on,
1417c478bd9Sstevel@tonic-gate 	 * then the various signal handlers will catch the characters.  If
1427c478bd9Sstevel@tonic-gate 	 * the character in question gets here, then it must have been LNEXTed
1437c478bd9Sstevel@tonic-gate 	 */
1447c478bd9Sstevel@tonic-gate 	if (c == termQuitChar) {
1457c478bd9Sstevel@tonic-gate #ifdef	KLUDGELINEMODE
1467c478bd9Sstevel@tonic-gate 		if (kludgelinemode) {
1477c478bd9Sstevel@tonic-gate 			if (sendbrk() == -1) {
1487c478bd9Sstevel@tonic-gate 				/* This won't return. */
1497c478bd9Sstevel@tonic-gate 				fatal_tty_error("write");
1507c478bd9Sstevel@tonic-gate 			}
1517c478bd9Sstevel@tonic-gate 			return (0);
1527c478bd9Sstevel@tonic-gate 		}
1537c478bd9Sstevel@tonic-gate #endif
1547c478bd9Sstevel@tonic-gate 	} else if (c == termFlushChar) {
1557c478bd9Sstevel@tonic-gate 		/* Transmit Abort Output */
1567c478bd9Sstevel@tonic-gate 		if (xmitAO() == -1) {
1577c478bd9Sstevel@tonic-gate 			/* This won't return. */
1587c478bd9Sstevel@tonic-gate 			fatal_tty_error("write");
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 		return (0);
1617c478bd9Sstevel@tonic-gate 	} else if (!MODE_LOCAL_CHARS(globalmode)) {
1627c478bd9Sstevel@tonic-gate 		if (c == termKillChar) {
1637c478bd9Sstevel@tonic-gate 			xmitEL();
1647c478bd9Sstevel@tonic-gate 			return (0);
1657c478bd9Sstevel@tonic-gate 		} else if (c == termEraseChar) {
1667c478bd9Sstevel@tonic-gate 			xmitEC();	/* Transmit Erase Character */
1677c478bd9Sstevel@tonic-gate 			return (0);
1687c478bd9Sstevel@tonic-gate 		}
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 	return (1);
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate  * Flush output to the terminal
1767c478bd9Sstevel@tonic-gate  */
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate void
TerminalFlushOutput()1797c478bd9Sstevel@tonic-gate TerminalFlushOutput()
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate 	if (isatty(fileno(stdout))) {
1827c478bd9Sstevel@tonic-gate 		(void) ioctl(fileno(stdout), TIOCFLUSH, NULL);
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate void
TerminalSaveState()1877c478bd9Sstevel@tonic-gate TerminalSaveState()
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
1907c478bd9Sstevel@tonic-gate 	(void) ioctl(0, TIOCGETP, &ottyb);
1917c478bd9Sstevel@tonic-gate 	(void) ioctl(0, TIOCGETC, &otc);
1927c478bd9Sstevel@tonic-gate 	(void) ioctl(0, TIOCGLTC, &oltc);
1937c478bd9Sstevel@tonic-gate 	(void) ioctl(0, TIOCLGET, &olmode);
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	ntc = otc;
1967c478bd9Sstevel@tonic-gate 	nltc = oltc;
1977c478bd9Sstevel@tonic-gate 	nttyb = ottyb;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate #else	/* USE_TERMIO */
2007c478bd9Sstevel@tonic-gate 	(void) tcgetattr(0, &old_tc);
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	new_tc = old_tc;
2037c478bd9Sstevel@tonic-gate 	termAytChar = CONTROL('T');
2047c478bd9Sstevel@tonic-gate #endif	/* USE_TERMIO */
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate cc_t *
tcval(func)2087c478bd9Sstevel@tonic-gate tcval(func)
2097c478bd9Sstevel@tonic-gate 	register int func;
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate 	switch (func) {
2127c478bd9Sstevel@tonic-gate 	case SLC_IP:	return (&termIntChar);
2137c478bd9Sstevel@tonic-gate 	case SLC_ABORT:	return (&termQuitChar);
2147c478bd9Sstevel@tonic-gate 	case SLC_EOF:	return (&termEofChar);
2157c478bd9Sstevel@tonic-gate 	case SLC_EC:	return (&termEraseChar);
2167c478bd9Sstevel@tonic-gate 	case SLC_EL:	return (&termKillChar);
2177c478bd9Sstevel@tonic-gate 	case SLC_XON:	return (&termStartChar);
2187c478bd9Sstevel@tonic-gate 	case SLC_XOFF:	return (&termStopChar);
2197c478bd9Sstevel@tonic-gate 	case SLC_FORW1:	return (&termForw1Char);
2207c478bd9Sstevel@tonic-gate #ifdef	USE_TERMIO
2217c478bd9Sstevel@tonic-gate 	case SLC_FORW2:	return (&termForw2Char);
2227c478bd9Sstevel@tonic-gate 	case SLC_AO:	return (&termFlushChar);
2237c478bd9Sstevel@tonic-gate 	case SLC_SUSP:	return (&termSuspChar);
2247c478bd9Sstevel@tonic-gate 	case SLC_EW:	return (&termWerasChar);
2257c478bd9Sstevel@tonic-gate 	case SLC_RP:	return (&termRprntChar);
2267c478bd9Sstevel@tonic-gate 	case SLC_LNEXT:	return (&termLiteralNextChar);
2277c478bd9Sstevel@tonic-gate #endif
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	case SLC_SYNCH:
2307c478bd9Sstevel@tonic-gate 	case SLC_BRK:
2317c478bd9Sstevel@tonic-gate 	case SLC_EOR:
2327c478bd9Sstevel@tonic-gate 	default:
2337c478bd9Sstevel@tonic-gate 		return ((cc_t *)0);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate void
TerminalDefaultChars()2387c478bd9Sstevel@tonic-gate TerminalDefaultChars()
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
2417c478bd9Sstevel@tonic-gate 	ntc = otc;
2427c478bd9Sstevel@tonic-gate 	nltc = oltc;
2437c478bd9Sstevel@tonic-gate 	nttyb.sg_kill = ottyb.sg_kill;
2447c478bd9Sstevel@tonic-gate 	nttyb.sg_erase = ottyb.sg_erase;
2457c478bd9Sstevel@tonic-gate #else	/* USE_TERMIO */
2467c478bd9Sstevel@tonic-gate 	(void) memcpy(new_tc.c_cc, old_tc.c_cc, sizeof (old_tc.c_cc));
2477c478bd9Sstevel@tonic-gate 	termAytChar = CONTROL('T');
2487c478bd9Sstevel@tonic-gate #endif	/* USE_TERMIO */
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * TerminalNewMode - set up terminal to a specific mode.
2537c478bd9Sstevel@tonic-gate  *	MODE_ECHO: do local terminal echo
2547c478bd9Sstevel@tonic-gate  *	MODE_FLOW: do local flow control
2557c478bd9Sstevel@tonic-gate  *	MODE_TRAPSIG: do local mapping to TELNET IAC sequences
2567c478bd9Sstevel@tonic-gate  *	MODE_EDIT: do local line editing
2577c478bd9Sstevel@tonic-gate  *
2587c478bd9Sstevel@tonic-gate  *	Command mode:
2597c478bd9Sstevel@tonic-gate  *		MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
2607c478bd9Sstevel@tonic-gate  *		local echo
2617c478bd9Sstevel@tonic-gate  *		local editing
2627c478bd9Sstevel@tonic-gate  *		local xon/xoff
2637c478bd9Sstevel@tonic-gate  *		local signal mapping
2647c478bd9Sstevel@tonic-gate  *
2657c478bd9Sstevel@tonic-gate  *	Linemode:
2667c478bd9Sstevel@tonic-gate  *		local/no editing
2677c478bd9Sstevel@tonic-gate  *	Both Linemode and Single Character mode:
2687c478bd9Sstevel@tonic-gate  *		local/remote echo
2697c478bd9Sstevel@tonic-gate  *		local/no xon/xoff
2707c478bd9Sstevel@tonic-gate  *		local/no signal mapping
2717c478bd9Sstevel@tonic-gate  */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate void
TerminalNewMode(f)2757c478bd9Sstevel@tonic-gate TerminalNewMode(f)
2767c478bd9Sstevel@tonic-gate 	register int f;
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate 	static int prevmode = -2;	/* guaranteed unique */
2797c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
2807c478bd9Sstevel@tonic-gate 	struct tchars tc;
2817c478bd9Sstevel@tonic-gate 	struct ltchars ltc;
2827c478bd9Sstevel@tonic-gate 	struct sgttyb sb;
2837c478bd9Sstevel@tonic-gate 	int lmode;
2847c478bd9Sstevel@tonic-gate #else	/* USE_TERMIO */
2857c478bd9Sstevel@tonic-gate 	struct termio tmp_tc;
2867c478bd9Sstevel@tonic-gate #endif	/* USE_TERMIO */
2877c478bd9Sstevel@tonic-gate 	int onoff;
2887c478bd9Sstevel@tonic-gate 	int old;
2897c478bd9Sstevel@tonic-gate 	cc_t esc;
2907c478bd9Sstevel@tonic-gate 	sigset_t nset;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	globalmode = f&~MODE_FORCE;
2937c478bd9Sstevel@tonic-gate 	if (prevmode == f)
2947c478bd9Sstevel@tonic-gate 		return;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	/*
2977c478bd9Sstevel@tonic-gate 	 * Write any outstanding data before switching modes
2987c478bd9Sstevel@tonic-gate 	 * ttyflush() returns 0 only when there was no data
2997c478bd9Sstevel@tonic-gate 	 * to write out; it returns -1 if it couldn't do
3007c478bd9Sstevel@tonic-gate 	 * anything at all, returns -2 if there was a write
3017c478bd9Sstevel@tonic-gate 	 * error (other than EWOULDBLOCK), and otherwise it
3027c478bd9Sstevel@tonic-gate 	 * returns 1 + the number of characters left to write.
3037c478bd9Sstevel@tonic-gate 	 */
3047c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
3057c478bd9Sstevel@tonic-gate 	/*
3067c478bd9Sstevel@tonic-gate 	 * We would really like ask the kernel to wait for the output
3077c478bd9Sstevel@tonic-gate 	 * to drain, like we can do with the TCSADRAIN, but we don't have
3087c478bd9Sstevel@tonic-gate 	 * that option.  The only ioctl that waits for the output to
3097c478bd9Sstevel@tonic-gate 	 * drain, TIOCSETP, also flushes the input queue, which is NOT
3107c478bd9Sstevel@tonic-gate 	 * what we want(TIOCSETP is like TCSADFLUSH).
3117c478bd9Sstevel@tonic-gate 	 */
3127c478bd9Sstevel@tonic-gate #endif
3137c478bd9Sstevel@tonic-gate 	old = ttyflush(SYNCHing|flushout);
3147c478bd9Sstevel@tonic-gate 	if (old == -1 || old > 1) {
3157c478bd9Sstevel@tonic-gate #ifdef	USE_TERMIO
3167c478bd9Sstevel@tonic-gate 		(void) tcgetattr(tin, &tmp_tc);
3177c478bd9Sstevel@tonic-gate #endif	/* USE_TERMIO */
3187c478bd9Sstevel@tonic-gate 		do {
3197c478bd9Sstevel@tonic-gate 			/*
3207c478bd9Sstevel@tonic-gate 			 * Wait for data to drain, then flush again.
3217c478bd9Sstevel@tonic-gate 			 */
3227c478bd9Sstevel@tonic-gate #ifdef	USE_TERMIO
3237c478bd9Sstevel@tonic-gate 			(void) tcsetattr(tin, TCSADRAIN, &tmp_tc);
3247c478bd9Sstevel@tonic-gate #endif	/* USE_TERMIO */
3257c478bd9Sstevel@tonic-gate 			old = ttyflush(SYNCHing|flushout);
3267c478bd9Sstevel@tonic-gate 		} while (old == -1 || old > 1);
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	old = prevmode;
3307c478bd9Sstevel@tonic-gate 	prevmode = f&~MODE_FORCE;
3317c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
3327c478bd9Sstevel@tonic-gate 	sb = nttyb;
3337c478bd9Sstevel@tonic-gate 	tc = ntc;
3347c478bd9Sstevel@tonic-gate 	ltc = nltc;
3357c478bd9Sstevel@tonic-gate 	lmode = olmode;
3367c478bd9Sstevel@tonic-gate #else
3377c478bd9Sstevel@tonic-gate 	tmp_tc = new_tc;
3387c478bd9Sstevel@tonic-gate #endif
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if (f&MODE_ECHO) {
3417c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
3427c478bd9Sstevel@tonic-gate 		sb.sg_flags |= ECHO;
3437c478bd9Sstevel@tonic-gate #else
3447c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag |= ECHO;
3457c478bd9Sstevel@tonic-gate 		tmp_tc.c_oflag |= ONLCR;
3467c478bd9Sstevel@tonic-gate 		if (crlf)
3477c478bd9Sstevel@tonic-gate 			tmp_tc.c_iflag |= ICRNL;
3487c478bd9Sstevel@tonic-gate #endif
3497c478bd9Sstevel@tonic-gate 	} else {
3507c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
3517c478bd9Sstevel@tonic-gate 		sb.sg_flags &= ~ECHO;
3527c478bd9Sstevel@tonic-gate #else
3537c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag &= ~ECHO;
3547c478bd9Sstevel@tonic-gate 		tmp_tc.c_oflag &= ~ONLCR;
3557c478bd9Sstevel@tonic-gate #ifdef notdef
3567c478bd9Sstevel@tonic-gate 		if (crlf)
3577c478bd9Sstevel@tonic-gate 			tmp_tc.c_iflag &= ~ICRNL;
3587c478bd9Sstevel@tonic-gate #endif
3597c478bd9Sstevel@tonic-gate #endif
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if ((f&MODE_FLOW) == 0) {
3637c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
3647c478bd9Sstevel@tonic-gate 		tc.t_startc = _POSIX_VDISABLE;
3657c478bd9Sstevel@tonic-gate 		tc.t_stopc = _POSIX_VDISABLE;
3667c478bd9Sstevel@tonic-gate #else
3677c478bd9Sstevel@tonic-gate 		tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
3687c478bd9Sstevel@tonic-gate 	} else {
3697c478bd9Sstevel@tonic-gate 		if (restartany < 0) {
3707c478bd9Sstevel@tonic-gate 			/* Leave the IXANY bit alone */
3717c478bd9Sstevel@tonic-gate 			tmp_tc.c_iflag |= IXOFF|IXON;
3727c478bd9Sstevel@tonic-gate 		} else if (restartany > 0) {
3737c478bd9Sstevel@tonic-gate 			tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
3747c478bd9Sstevel@tonic-gate 		} else {
3757c478bd9Sstevel@tonic-gate 			tmp_tc.c_iflag |= IXOFF|IXON;
3767c478bd9Sstevel@tonic-gate 			tmp_tc.c_iflag &= ~IXANY;
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate #endif
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if ((f&MODE_TRAPSIG) == 0) {
3827c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
3837c478bd9Sstevel@tonic-gate 		tc.t_intrc = _POSIX_VDISABLE;
3847c478bd9Sstevel@tonic-gate 		tc.t_quitc = _POSIX_VDISABLE;
3857c478bd9Sstevel@tonic-gate 		tc.t_eofc = _POSIX_VDISABLE;
3867c478bd9Sstevel@tonic-gate 		ltc.t_suspc = _POSIX_VDISABLE;
3877c478bd9Sstevel@tonic-gate 		ltc.t_dsuspc = _POSIX_VDISABLE;
3887c478bd9Sstevel@tonic-gate #else
3897c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag &= ~ISIG;
3907c478bd9Sstevel@tonic-gate #endif
3917c478bd9Sstevel@tonic-gate 		localchars = 0;
3927c478bd9Sstevel@tonic-gate 	} else {
3937c478bd9Sstevel@tonic-gate #ifdef	USE_TERMIO
3947c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag |= ISIG;
3957c478bd9Sstevel@tonic-gate #endif
3967c478bd9Sstevel@tonic-gate 		localchars = 1;
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (f&MODE_EDIT) {
4007c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
4017c478bd9Sstevel@tonic-gate 		sb.sg_flags &= ~CBREAK;
4027c478bd9Sstevel@tonic-gate 		sb.sg_flags |= CRMOD;
4037c478bd9Sstevel@tonic-gate #else
4047c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag |= ICANON;
4057c478bd9Sstevel@tonic-gate #endif
4067c478bd9Sstevel@tonic-gate 	} else {
4077c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
4087c478bd9Sstevel@tonic-gate 		sb.sg_flags |= CBREAK;
4097c478bd9Sstevel@tonic-gate 		if (f&MODE_ECHO)
4107c478bd9Sstevel@tonic-gate 			sb.sg_flags |= CRMOD;
4117c478bd9Sstevel@tonic-gate 		else
4127c478bd9Sstevel@tonic-gate 			sb.sg_flags &= ~CRMOD;
4137c478bd9Sstevel@tonic-gate #else
4147c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag &= ~ICANON;
4157c478bd9Sstevel@tonic-gate 		tmp_tc.c_iflag &= ~ICRNL;
4167c478bd9Sstevel@tonic-gate 		tmp_tc.c_cc[VMIN] = 1;
4177c478bd9Sstevel@tonic-gate 		tmp_tc.c_cc[VTIME] = 0;
4187c478bd9Sstevel@tonic-gate #endif
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
4227c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
4237c478bd9Sstevel@tonic-gate 		ltc.t_lnextc = _POSIX_VDISABLE;
4247c478bd9Sstevel@tonic-gate #else
4257c478bd9Sstevel@tonic-gate 		tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
4267c478bd9Sstevel@tonic-gate #endif
4277c478bd9Sstevel@tonic-gate 	}
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	if (f&MODE_SOFT_TAB) {
4307c478bd9Sstevel@tonic-gate #ifndef USE_TERMIO
4317c478bd9Sstevel@tonic-gate 		sb.sg_flags |= XTABS;
4327c478bd9Sstevel@tonic-gate #else
4337c478bd9Sstevel@tonic-gate 		tmp_tc.c_oflag &= ~TABDLY;
4347c478bd9Sstevel@tonic-gate 		tmp_tc.c_oflag |= TAB3;
4357c478bd9Sstevel@tonic-gate #endif
4367c478bd9Sstevel@tonic-gate 	} else {
4377c478bd9Sstevel@tonic-gate #ifndef USE_TERMIO
4387c478bd9Sstevel@tonic-gate 		sb.sg_flags &= ~XTABS;
4397c478bd9Sstevel@tonic-gate #else
4407c478bd9Sstevel@tonic-gate 		tmp_tc.c_oflag &= ~TABDLY;
4417c478bd9Sstevel@tonic-gate #endif
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	if (f&MODE_LIT_ECHO) {
4457c478bd9Sstevel@tonic-gate #ifndef USE_TERMIO
4467c478bd9Sstevel@tonic-gate 		lmode &= ~LCTLECH;
4477c478bd9Sstevel@tonic-gate #else
4487c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag &= ~ECHOCTL;
4497c478bd9Sstevel@tonic-gate #endif
4507c478bd9Sstevel@tonic-gate 	} else {
4517c478bd9Sstevel@tonic-gate #ifndef USE_TERMIO
4527c478bd9Sstevel@tonic-gate 		lmode |= LCTLECH;
4537c478bd9Sstevel@tonic-gate #else
4547c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag |= ECHOCTL;
4557c478bd9Sstevel@tonic-gate #endif
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	if (f == -1) {
4597c478bd9Sstevel@tonic-gate 		onoff = 0;
4607c478bd9Sstevel@tonic-gate 	} else {
4617c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
4627c478bd9Sstevel@tonic-gate 		if (f & MODE_OUTBIN)
4637c478bd9Sstevel@tonic-gate 			lmode |= LLITOUT;
4647c478bd9Sstevel@tonic-gate 		else
4657c478bd9Sstevel@tonic-gate 			lmode &= ~LLITOUT;
4667c478bd9Sstevel@tonic-gate #else
4677c478bd9Sstevel@tonic-gate 		if (f & MODE_OUTBIN) {
4687c478bd9Sstevel@tonic-gate 			tmp_tc.c_cflag &= ~(CSIZE|PARENB);
4697c478bd9Sstevel@tonic-gate 			tmp_tc.c_cflag |= CS8;
4707c478bd9Sstevel@tonic-gate 			tmp_tc.c_oflag &= ~OPOST;
4717c478bd9Sstevel@tonic-gate 		} else {
4727c478bd9Sstevel@tonic-gate 			tmp_tc.c_cflag &= ~(CSIZE|PARENB);
4737c478bd9Sstevel@tonic-gate 			tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
4747c478bd9Sstevel@tonic-gate 			tmp_tc.c_oflag |= OPOST;
4757c478bd9Sstevel@tonic-gate 		}
4767c478bd9Sstevel@tonic-gate #endif
4777c478bd9Sstevel@tonic-gate 		onoff = 1;
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (f != -1) {
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 		(void) signal(SIGTSTP, susp);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate #if	defined(USE_TERMIO) && defined(NOKERNINFO)
4857c478bd9Sstevel@tonic-gate 		tmp_tc.c_lflag |= NOKERNINFO;
4867c478bd9Sstevel@tonic-gate #endif
4877c478bd9Sstevel@tonic-gate 		/*
4887c478bd9Sstevel@tonic-gate 		 * We don't want to process ^Y here.  It's just another
4897c478bd9Sstevel@tonic-gate 		 * character that we'll pass on to the back end.  It has
4907c478bd9Sstevel@tonic-gate 		 * to process it because it will be processed when the
4917c478bd9Sstevel@tonic-gate 		 * user attempts to read it, not when we send it.
4927c478bd9Sstevel@tonic-gate 		 */
4937c478bd9Sstevel@tonic-gate #ifndef	USE_TERMIO
4947c478bd9Sstevel@tonic-gate 		ltc.t_dsuspc = _POSIX_VDISABLE;
4957c478bd9Sstevel@tonic-gate #else
4967c478bd9Sstevel@tonic-gate 		tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
4977c478bd9Sstevel@tonic-gate #endif
4987c478bd9Sstevel@tonic-gate #ifdef	USE_TERMIO
4997c478bd9Sstevel@tonic-gate 		/*
5007c478bd9Sstevel@tonic-gate 		 * If the VEOL character is already set, then use VEOL2,
5017c478bd9Sstevel@tonic-gate 		 * otherwise use VEOL.
5027c478bd9Sstevel@tonic-gate 		 */
5037c478bd9Sstevel@tonic-gate 		esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
5047c478bd9Sstevel@tonic-gate 		if ((tmp_tc.c_cc[VEOL] != esc)
5057c478bd9Sstevel@tonic-gate 		    /* XXX */ &&
5067c478bd9Sstevel@tonic-gate 		    (tmp_tc.c_cc[VEOL2] != esc)
5077c478bd9Sstevel@tonic-gate 		    /* XXX */) {
5087c478bd9Sstevel@tonic-gate 			if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
5097c478bd9Sstevel@tonic-gate 				tmp_tc.c_cc[VEOL] = esc;
5107c478bd9Sstevel@tonic-gate 			else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
5117c478bd9Sstevel@tonic-gate 				tmp_tc.c_cc[VEOL2] = esc;
5127c478bd9Sstevel@tonic-gate 		}
5137c478bd9Sstevel@tonic-gate #else
5147c478bd9Sstevel@tonic-gate 		if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
5157c478bd9Sstevel@tonic-gate 			tc.t_brkc = esc;
5167c478bd9Sstevel@tonic-gate #endif
5177c478bd9Sstevel@tonic-gate 	} else {
5187c478bd9Sstevel@tonic-gate 		(void) signal(SIGTSTP, SIG_DFL);
5197c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&nset);
5207c478bd9Sstevel@tonic-gate 		(void) sigaddset(&nset, SIGTSTP);
5217c478bd9Sstevel@tonic-gate 		(void) sigprocmask(SIG_UNBLOCK, &nset, 0);
5227c478bd9Sstevel@tonic-gate #ifndef USE_TERMIO
5237c478bd9Sstevel@tonic-gate 		ltc = oltc;
5247c478bd9Sstevel@tonic-gate 		tc = otc;
5257c478bd9Sstevel@tonic-gate 		sb = ottyb;
5267c478bd9Sstevel@tonic-gate 		lmode = olmode;
5277c478bd9Sstevel@tonic-gate #else
5287c478bd9Sstevel@tonic-gate 		tmp_tc = old_tc;
5297c478bd9Sstevel@tonic-gate #endif
5307c478bd9Sstevel@tonic-gate 	}
5317c478bd9Sstevel@tonic-gate 	if (isatty(tin)) {
5327c478bd9Sstevel@tonic-gate #ifndef USE_TERMIO
5337c478bd9Sstevel@tonic-gate 		(void) ioctl(tin, TIOCLSET, &lmode);
5347c478bd9Sstevel@tonic-gate 		(void) ioctl(tin, TIOCSLTC, &ltc);
5357c478bd9Sstevel@tonic-gate 		(void) ioctl(tin, TIOCSETC, &tc);
5367c478bd9Sstevel@tonic-gate 		(void) ioctl(tin, TIOCSETN, &sb);
5377c478bd9Sstevel@tonic-gate #else
5387c478bd9Sstevel@tonic-gate 		if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
5397c478bd9Sstevel@tonic-gate 			(void) tcsetattr(tin, TCSANOW, &tmp_tc);
5407c478bd9Sstevel@tonic-gate #endif
5417c478bd9Sstevel@tonic-gate 		(void) ioctl(tin, FIONBIO, &onoff);
5427c478bd9Sstevel@tonic-gate 		(void) ioctl(tout, FIONBIO, &onoff);
5437c478bd9Sstevel@tonic-gate 	}
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate /*
5487c478bd9Sstevel@tonic-gate  * This code assumes that the values B0, B50, B75...
5497c478bd9Sstevel@tonic-gate  * are in ascending order.  They do not have to be
5507c478bd9Sstevel@tonic-gate  * contiguous.
5517c478bd9Sstevel@tonic-gate  */
5527c478bd9Sstevel@tonic-gate static struct termspeeds {
5537c478bd9Sstevel@tonic-gate 	int speed;
5547c478bd9Sstevel@tonic-gate 	int value;
5557c478bd9Sstevel@tonic-gate } termspeeds[] = {
5567c478bd9Sstevel@tonic-gate 	{ 0,	B0 },		{ 50,	B50 },		{ 75, B75 },
5577c478bd9Sstevel@tonic-gate 	{ 110,	B110 },		{ 134,	B134 },		{ 150, B150 },
5587c478bd9Sstevel@tonic-gate 	{ 200,	B200 },		{ 300,   B300 },	{ 600, B600 },
5597c478bd9Sstevel@tonic-gate 	{ 1200,	B1200 },	{ 1800,  B1800 },	{ 2400, B2400 },
5607c478bd9Sstevel@tonic-gate 	{ 4800,	B4800 },	{ 9600,  B9600 },	{ 19200, B19200 },
5617c478bd9Sstevel@tonic-gate 	{ 38400, B38400 },	{ 57600, B57600 },	{ 76800, B76800 },
5627c478bd9Sstevel@tonic-gate 	{ 115200, B115200 },	{ 153600, B153600 },	{ 230400, B230400 },
563*de81e71eSTim Marsland 	{ 307200, B307200 },	{ 460800, B460800 },	{ 921600, B921600 },
564*de81e71eSTim Marsland 	{ -1, B0 }
5657c478bd9Sstevel@tonic-gate };
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate void
TerminalSpeeds(ispeed,ospeed)5687c478bd9Sstevel@tonic-gate TerminalSpeeds(ispeed, ospeed)
5697c478bd9Sstevel@tonic-gate 	int *ispeed;
5707c478bd9Sstevel@tonic-gate 	int *ospeed;
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	register struct termspeeds *tp;
5737c478bd9Sstevel@tonic-gate 	register int in, out;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	out = cfgetospeed(&old_tc);
5767c478bd9Sstevel@tonic-gate 	in = cfgetispeed(&old_tc);
5777c478bd9Sstevel@tonic-gate 	if (in == 0)
5787c478bd9Sstevel@tonic-gate 		in = out;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	tp = termspeeds;
5817c478bd9Sstevel@tonic-gate 	while ((tp->speed != -1) && (tp->value < in)) {
5827c478bd9Sstevel@tonic-gate 		tp++;
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 	if (tp->speed == -1)
5857c478bd9Sstevel@tonic-gate 		tp--;			/* back up to fastest defined speed */
5867c478bd9Sstevel@tonic-gate 	*ispeed = tp->speed;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	tp = termspeeds;
5897c478bd9Sstevel@tonic-gate 	while ((tp->speed != -1) && (tp->value < out)) {
5907c478bd9Sstevel@tonic-gate 		tp++;
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 	if (tp->speed == -1)
5937c478bd9Sstevel@tonic-gate 		tp--;
5947c478bd9Sstevel@tonic-gate 	*ospeed = tp->speed;
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate int
TerminalWindowSize(rows,cols)5987c478bd9Sstevel@tonic-gate TerminalWindowSize(rows, cols)
5997c478bd9Sstevel@tonic-gate 	unsigned short *rows, *cols;
6007c478bd9Sstevel@tonic-gate {
6017c478bd9Sstevel@tonic-gate 	struct winsize ws;
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) {
6047c478bd9Sstevel@tonic-gate 		*rows = ws.ws_row;
6057c478bd9Sstevel@tonic-gate 		*cols = ws.ws_col;
6067c478bd9Sstevel@tonic-gate 		return (1);
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate 	return (0);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate static void
NetNonblockingIO(fd,onoff)6127c478bd9Sstevel@tonic-gate NetNonblockingIO(fd, onoff)
6137c478bd9Sstevel@tonic-gate 	int fd;
6147c478bd9Sstevel@tonic-gate 	int onoff;
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate 	(void) ioctl(fd, FIONBIO, &onoff);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate  * Various signal handling routines.
6217c478bd9Sstevel@tonic-gate  */
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate /* ARGSUSED */
6247c478bd9Sstevel@tonic-gate static SIG_FUNC_RET
deadpeer(sig)6257c478bd9Sstevel@tonic-gate deadpeer(sig)
6267c478bd9Sstevel@tonic-gate 	int sig;
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate 	/*
6297c478bd9Sstevel@tonic-gate 	 * Once is all we should catch SIGPIPE.  If we get it again,
6307c478bd9Sstevel@tonic-gate 	 * it means we tried to put still more data out to a pipe
6317c478bd9Sstevel@tonic-gate 	 * which has disappeared.  In that case, telnet will exit.
6327c478bd9Sstevel@tonic-gate 	 */
6337c478bd9Sstevel@tonic-gate 	(void) signal(SIGPIPE, SIG_IGN);
6347c478bd9Sstevel@tonic-gate 	flushout = 1;
6357c478bd9Sstevel@tonic-gate 	setcommandmode();
6367c478bd9Sstevel@tonic-gate 	longjmp(peerdied, -1);
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate boolean_t intr_happened	= B_FALSE;
6407c478bd9Sstevel@tonic-gate boolean_t intr_waiting	= B_FALSE;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate /* ARGSUSED */
6437c478bd9Sstevel@tonic-gate static SIG_FUNC_RET
intr(sig)6447c478bd9Sstevel@tonic-gate intr(sig)
6457c478bd9Sstevel@tonic-gate 	int sig;
6467c478bd9Sstevel@tonic-gate {
6477c478bd9Sstevel@tonic-gate 	if (intr_waiting) {
6487c478bd9Sstevel@tonic-gate 		intr_happened = 1;
6497c478bd9Sstevel@tonic-gate 		return;
6507c478bd9Sstevel@tonic-gate 	}
6517c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, intr);
6527c478bd9Sstevel@tonic-gate 	if (localchars) {
6537c478bd9Sstevel@tonic-gate 		intp();
6547c478bd9Sstevel@tonic-gate 		return;
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 	setcommandmode();
6577c478bd9Sstevel@tonic-gate 	longjmp(toplevel, -1);
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate /* ARGSUSED */
6617c478bd9Sstevel@tonic-gate static SIG_FUNC_RET
intr2(sig)6627c478bd9Sstevel@tonic-gate intr2(sig)
6637c478bd9Sstevel@tonic-gate 	int sig;
6647c478bd9Sstevel@tonic-gate {
6657c478bd9Sstevel@tonic-gate 	(void) signal(SIGQUIT, intr2);
6667c478bd9Sstevel@tonic-gate 	if (localchars) {
6677c478bd9Sstevel@tonic-gate 		/*
6687c478bd9Sstevel@tonic-gate 		 * Ignore return to the next two function calls
6697c478bd9Sstevel@tonic-gate 		 * since we're doing SIGQUIT
6707c478bd9Sstevel@tonic-gate 		 */
6717c478bd9Sstevel@tonic-gate #ifdef	KLUDGELINEMODE
6727c478bd9Sstevel@tonic-gate 		if (kludgelinemode) {
6737c478bd9Sstevel@tonic-gate 			(void) sendbrk();
6747c478bd9Sstevel@tonic-gate 		}
6757c478bd9Sstevel@tonic-gate 		else
6767c478bd9Sstevel@tonic-gate #endif
6777c478bd9Sstevel@tonic-gate 			sendabort();
6787c478bd9Sstevel@tonic-gate 		return;
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate /* ARGSUSED */
6837c478bd9Sstevel@tonic-gate static SIG_FUNC_RET
susp(sig)6847c478bd9Sstevel@tonic-gate susp(sig)
6857c478bd9Sstevel@tonic-gate 	int sig;
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 	(void) signal(SIGTSTP, susp);
6887c478bd9Sstevel@tonic-gate 	if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
6897c478bd9Sstevel@tonic-gate 		return;
6907c478bd9Sstevel@tonic-gate 	if (localchars)
6917c478bd9Sstevel@tonic-gate 		sendsusp();
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate /* ARGSUSED */
6957c478bd9Sstevel@tonic-gate static SIG_FUNC_RET
sendwin(sig)6967c478bd9Sstevel@tonic-gate sendwin(sig)
6977c478bd9Sstevel@tonic-gate 	int sig;
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate 	(void) signal(SIGWINCH, sendwin);
7007c478bd9Sstevel@tonic-gate 	if (connected) {
7017c478bd9Sstevel@tonic-gate 		sendnaws();
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate void
sys_telnet_init()7067c478bd9Sstevel@tonic-gate sys_telnet_init()
7077c478bd9Sstevel@tonic-gate {
7087c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, intr);
7097c478bd9Sstevel@tonic-gate 	(void) signal(SIGQUIT, intr2);
7107c478bd9Sstevel@tonic-gate 	(void) signal(SIGPIPE, deadpeer);
7117c478bd9Sstevel@tonic-gate 	(void) signal(SIGWINCH, sendwin);
7127c478bd9Sstevel@tonic-gate 	(void) signal(SIGTSTP, susp);
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	setconnmode(0);
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	NetNonblockingIO(net, 1);
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
7197c478bd9Sstevel@tonic-gate 		perror("SetSockOpt");
7207c478bd9Sstevel@tonic-gate 	}
7217c478bd9Sstevel@tonic-gate }
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate /*
7257c478bd9Sstevel@tonic-gate  * fatal_tty_error -
7267c478bd9Sstevel@tonic-gate  *	Handle case where there is an unrecoverable error on the tty
7277c478bd9Sstevel@tonic-gate  *      connections.  Print an error, reset the terminal settings
7287c478bd9Sstevel@tonic-gate  *	and get out as painlessly as possible.
7297c478bd9Sstevel@tonic-gate  */
7307c478bd9Sstevel@tonic-gate void
fatal_tty_error(char * doing_what)7317c478bd9Sstevel@tonic-gate fatal_tty_error(char *doing_what)
7327c478bd9Sstevel@tonic-gate {
7337c478bd9Sstevel@tonic-gate 	TerminalNewMode(-1);
7347c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Error processing %s:  %s\n", doing_what,
7357c478bd9Sstevel@tonic-gate 	    strerror(errno));
7367c478bd9Sstevel@tonic-gate 	exit(1);
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate /*
7417c478bd9Sstevel@tonic-gate  * Process rings -
7427c478bd9Sstevel@tonic-gate  *
7437c478bd9Sstevel@tonic-gate  *	This routine tries to fill up/empty our various rings.
7447c478bd9Sstevel@tonic-gate  *
7457c478bd9Sstevel@tonic-gate  *	The parameter specifies whether this is a poll operation,
7467c478bd9Sstevel@tonic-gate  *	or a block-until-something-happens operation.
7477c478bd9Sstevel@tonic-gate  *
7487c478bd9Sstevel@tonic-gate  *	The return value is 1 if something happened, 0 if not.
7497c478bd9Sstevel@tonic-gate  */
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate int
process_rings(netin,netout,netex,ttyin,ttyout,poll)7527c478bd9Sstevel@tonic-gate process_rings(netin, netout, netex, ttyin, ttyout, poll)
7537c478bd9Sstevel@tonic-gate 	int poll;		/* If 0, then block until something to do */
7547c478bd9Sstevel@tonic-gate {
7557c478bd9Sstevel@tonic-gate 	register int c;
7567c478bd9Sstevel@tonic-gate 	/*
7577c478bd9Sstevel@tonic-gate 	 * One wants to be a bit careful about setting returnValue
7587c478bd9Sstevel@tonic-gate 	 * to one, since a one implies we did some useful work,
7597c478bd9Sstevel@tonic-gate 	 * and therefore probably won't be called to block next
7607c478bd9Sstevel@tonic-gate 	 * time (TN3270 mode only).
7617c478bd9Sstevel@tonic-gate 	 */
7627c478bd9Sstevel@tonic-gate 	int returnValue = 0;
7637c478bd9Sstevel@tonic-gate 	static struct timeval TimeValue = { 0 };
7647c478bd9Sstevel@tonic-gate 	int i;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	if (netout) {
7677c478bd9Sstevel@tonic-gate 		FD_SET(net, &obits);
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 	if (ttyout) {
7707c478bd9Sstevel@tonic-gate 		FD_SET(tout, &obits);
7717c478bd9Sstevel@tonic-gate 	}
7727c478bd9Sstevel@tonic-gate 	if (ttyin) {
7737c478bd9Sstevel@tonic-gate 		FD_SET(tin, &ibits);
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate 	if (netin) {
7767c478bd9Sstevel@tonic-gate 		FD_SET(net, &ibits);
7777c478bd9Sstevel@tonic-gate 	}
7787c478bd9Sstevel@tonic-gate 	if (netex) {
7797c478bd9Sstevel@tonic-gate 		FD_SET(net, &xbits);
7807c478bd9Sstevel@tonic-gate 	}
7817c478bd9Sstevel@tonic-gate 	if ((c = select(16, &ibits, &obits, &xbits,
7827c478bd9Sstevel@tonic-gate 			(poll == 0) ? NULL : &TimeValue)) < 0) {
7837c478bd9Sstevel@tonic-gate 		if (c == -1) {
7847c478bd9Sstevel@tonic-gate 			/*
7857c478bd9Sstevel@tonic-gate 			 * we can get EINTR if we are in line mode,
7867c478bd9Sstevel@tonic-gate 			 * and the user does an escape (TSTP), or
7877c478bd9Sstevel@tonic-gate 			 * some other signal generator.
7887c478bd9Sstevel@tonic-gate 			 */
7897c478bd9Sstevel@tonic-gate 			if (errno == EINTR) {
7907c478bd9Sstevel@tonic-gate 				return (0);
7917c478bd9Sstevel@tonic-gate 			}
7927c478bd9Sstevel@tonic-gate 			/* I don't like this, does it ever happen? */
7937c478bd9Sstevel@tonic-gate 			(void) printf("sleep(5) from telnet, after select\r\n");
7947c478bd9Sstevel@tonic-gate 			(void) sleep(5);
7957c478bd9Sstevel@tonic-gate 		}
7967c478bd9Sstevel@tonic-gate 		return (0);
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	/*
8007c478bd9Sstevel@tonic-gate 	 * Any urgent data?
8017c478bd9Sstevel@tonic-gate 	 */
8027c478bd9Sstevel@tonic-gate 	if (FD_ISSET(net, &xbits)) {
8037c478bd9Sstevel@tonic-gate 		FD_CLR(net, &xbits);
8047c478bd9Sstevel@tonic-gate 		SYNCHing = 1;
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 		/* flush any data that is already enqueued */
8077c478bd9Sstevel@tonic-gate 		i = ttyflush(1);
8087c478bd9Sstevel@tonic-gate 		if (i == -2) {
8097c478bd9Sstevel@tonic-gate 			/* This will not return. */
8107c478bd9Sstevel@tonic-gate 			fatal_tty_error("write");
8117c478bd9Sstevel@tonic-gate 		}
8127c478bd9Sstevel@tonic-gate 	}
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	/*
8157c478bd9Sstevel@tonic-gate 	 * Something to read from the network...
8167c478bd9Sstevel@tonic-gate 	 */
8177c478bd9Sstevel@tonic-gate 	if (FD_ISSET(net, &ibits)) {
8187c478bd9Sstevel@tonic-gate 		int canread;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 		FD_CLR(net, &ibits);
8217c478bd9Sstevel@tonic-gate 		canread = ring_empty_consecutive(&netiring);
8227c478bd9Sstevel@tonic-gate 		c = recv(net, netiring.supply, canread, 0);
8237c478bd9Sstevel@tonic-gate 		if (c < 0 && errno == EWOULDBLOCK) {
8247c478bd9Sstevel@tonic-gate 			c = 0;
8257c478bd9Sstevel@tonic-gate 		} else if (c <= 0) {
8267c478bd9Sstevel@tonic-gate 			return (-1);
8277c478bd9Sstevel@tonic-gate 		}
8287c478bd9Sstevel@tonic-gate 		if (netdata) {
8297c478bd9Sstevel@tonic-gate 			Dump('<', netiring.supply, c);
8307c478bd9Sstevel@tonic-gate 		}
8317c478bd9Sstevel@tonic-gate 		if (c)
8327c478bd9Sstevel@tonic-gate 			ring_supplied(&netiring, c);
8337c478bd9Sstevel@tonic-gate 		returnValue = 1;
8347c478bd9Sstevel@tonic-gate 	}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	/*
8377c478bd9Sstevel@tonic-gate 	 * Something to read from the tty...
8387c478bd9Sstevel@tonic-gate 	 */
8397c478bd9Sstevel@tonic-gate 	if (FD_ISSET(tin, &ibits)) {
8407c478bd9Sstevel@tonic-gate 		FD_CLR(tin, &ibits);
8417c478bd9Sstevel@tonic-gate 		c = TerminalRead((char *)ttyiring.supply,
8427c478bd9Sstevel@tonic-gate 		    ring_empty_consecutive(&ttyiring));
8437c478bd9Sstevel@tonic-gate 		if (c < 0) {
8447c478bd9Sstevel@tonic-gate 			if (errno != EWOULDBLOCK) {
8457c478bd9Sstevel@tonic-gate 				/* This will not return. */
8467c478bd9Sstevel@tonic-gate 				fatal_tty_error("read");
8477c478bd9Sstevel@tonic-gate 			}
8487c478bd9Sstevel@tonic-gate 			c = 0;
8497c478bd9Sstevel@tonic-gate 		} else {
8507c478bd9Sstevel@tonic-gate 			/* EOF detection for line mode!!!! */
8517c478bd9Sstevel@tonic-gate 			if ((c == 0) && MODE_LOCAL_CHARS(globalmode) &&
8527c478bd9Sstevel@tonic-gate 			    isatty(tin)) {
8537c478bd9Sstevel@tonic-gate 				/* must be an EOF... */
8547c478bd9Sstevel@tonic-gate 				eof_pending = 1;
8557c478bd9Sstevel@tonic-gate 				return (1);
8567c478bd9Sstevel@tonic-gate 			}
8577c478bd9Sstevel@tonic-gate 			if (c <= 0) {
8587c478bd9Sstevel@tonic-gate 				returnValue = -1;
8597c478bd9Sstevel@tonic-gate 				goto next;
8607c478bd9Sstevel@tonic-gate 			}
8617c478bd9Sstevel@tonic-gate 			if (termdata) {
8627c478bd9Sstevel@tonic-gate 				Dump('<', ttyiring.supply, c);
8637c478bd9Sstevel@tonic-gate 			}
8647c478bd9Sstevel@tonic-gate 			ring_supplied(&ttyiring, c);
8657c478bd9Sstevel@tonic-gate 		}
8667c478bd9Sstevel@tonic-gate 		returnValue = 1;		/* did something useful */
8677c478bd9Sstevel@tonic-gate 	}
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate next:
8707c478bd9Sstevel@tonic-gate 	if (FD_ISSET(net, &obits)) {
8717c478bd9Sstevel@tonic-gate 		FD_CLR(net, &obits);
8727c478bd9Sstevel@tonic-gate 		returnValue |= netflush();
8737c478bd9Sstevel@tonic-gate 	}
8747c478bd9Sstevel@tonic-gate 	if (FD_ISSET(tout, &obits)) {
8757c478bd9Sstevel@tonic-gate 		FD_CLR(tout, &obits);
8767c478bd9Sstevel@tonic-gate 		i = ttyflush(SYNCHing|flushout);
8777c478bd9Sstevel@tonic-gate 		if (i == -2) {
8787c478bd9Sstevel@tonic-gate 			/* This will not return. */
8797c478bd9Sstevel@tonic-gate 			fatal_tty_error("write");
8807c478bd9Sstevel@tonic-gate 		}
8817c478bd9Sstevel@tonic-gate 		returnValue |= (i > 0);
8827c478bd9Sstevel@tonic-gate 	}
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 	return (returnValue);
8857c478bd9Sstevel@tonic-gate }
886