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, <c);
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