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