132147Sminshall /* 233685Sbostic * Copyright (c) 1988 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 533685Sbostic * Redistribution and use in source and binary forms are permitted 634898Sbostic * provided that the above copyright notice and this paragraph are 734898Sbostic * duplicated in all such forms and that any documentation, 834898Sbostic * advertising materials, and other materials related to such 934898Sbostic * distribution and use acknowledge that the software was developed 1034898Sbostic * by the University of California, Berkeley. The name of the 1134898Sbostic * University may not be used to endorse or promote products derived 1234898Sbostic * from this software without specific prior written permission. 1334898Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434898Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534898Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633685Sbostic */ 1733685Sbostic 1833685Sbostic #ifndef lint 19*39529Sborman static char sccsid[] = "@(#)sys_bsd.c 1.22 (Berkeley) 11/14/89"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2233685Sbostic /* 2332147Sminshall * The following routines try to encapsulate what is system dependent 2432147Sminshall * (at least between 4.x and dos) which is used in telnet.c. 2532147Sminshall */ 2632147Sminshall 2732147Sminshall 2836274Sminshall #include <fcntl.h> 2932381Sminshall #include <sys/types.h> 3032147Sminshall #include <sys/time.h> 3132531Sminshall #include <sys/socket.h> 3232147Sminshall #include <signal.h> 3332531Sminshall #include <errno.h> 3438689Sborman #include <arpa/telnet.h> 3532147Sminshall 3632381Sminshall #include "ring.h" 3732381Sminshall 3832657Sminshall #include "fdset.h" 3932657Sminshall 4032147Sminshall #include "defines.h" 4132147Sminshall #include "externs.h" 4232147Sminshall #include "types.h" 4332147Sminshall 4432147Sminshall int 4532531Sminshall tout, /* Output file descriptor */ 4632531Sminshall tin, /* Input file descriptor */ 4736242Sminshall net; 4832147Sminshall 4938689Sborman #ifndef USE_TERMIO 5038689Sborman struct tchars otc = { 0 }, ntc = { 0 }; 5138689Sborman struct ltchars oltc = { 0 }, nltc = { 0 }; 5238689Sborman struct sgttyb ottyb = { 0 }, nttyb = { 0 }; 5338909Sborman int olmode = 0; 5432147Sminshall 5538689Sborman #else /* USE_TERMIO */ 5638689Sborman struct termio old_tc = { 0 }; 5738689Sborman extern struct termio new_tc; 5838689Sborman 5938689Sborman #endif /* USE_TERMIO */ 6038689Sborman 6132531Sminshall static fd_set ibits, obits, xbits; 6232147Sminshall 6332531Sminshall 6432531Sminshall init_sys() 6532531Sminshall { 6632531Sminshall tout = fileno(stdout); 6732531Sminshall tin = fileno(stdin); 6832531Sminshall FD_ZERO(&ibits); 6932531Sminshall FD_ZERO(&obits); 7032531Sminshall FD_ZERO(&xbits); 7132531Sminshall 7232531Sminshall errno = 0; 7332531Sminshall } 7432531Sminshall 7532531Sminshall 7633286Sminshall TerminalWrite(buf, n) 7732147Sminshall char *buf; 7832147Sminshall int n; 7932147Sminshall { 8033286Sminshall return write(tout, buf, n); 8132147Sminshall } 8232147Sminshall 8333286Sminshall TerminalRead(buf, n) 8432147Sminshall char *buf; 8532147Sminshall int n; 8632147Sminshall { 8733286Sminshall return read(tin, buf, n); 8832147Sminshall } 8932147Sminshall 9032147Sminshall /* 9132147Sminshall * 9232147Sminshall */ 9332147Sminshall 9432147Sminshall int 9532553Sminshall TerminalAutoFlush() 9632147Sminshall { 9732147Sminshall #if defined(LNOFLSH) 9832147Sminshall int flush; 9932147Sminshall 10032147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 10132147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 10232147Sminshall #else /* LNOFLSH */ 10332147Sminshall return 1; 10432147Sminshall #endif /* LNOFLSH */ 10532147Sminshall } 10632147Sminshall 10738689Sborman #ifdef KLUDGELINEMODE 10838689Sborman extern int kludgelinemode; 10938689Sborman #endif 11032147Sminshall /* 11132147Sminshall * TerminalSpecialChars() 11232147Sminshall * 11332147Sminshall * Look at an input character to see if it is a special character 11432147Sminshall * and decide what to do. 11532147Sminshall * 11632147Sminshall * Output: 11732147Sminshall * 11832147Sminshall * 0 Don't add this character. 11932147Sminshall * 1 Do add this character 12032147Sminshall */ 12132147Sminshall 12232147Sminshall int 12332553Sminshall TerminalSpecialChars(c) 12432147Sminshall int c; 12532147Sminshall { 12632553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 12732147Sminshall 12838689Sborman if (c == termIntChar) { 12932147Sminshall intp(); 13032147Sminshall return 0; 13138689Sborman } else if (c == termQuitChar) { 13238689Sborman #ifdef KLUDGELINEMODE 13338689Sborman if (kludgelinemode) 13438689Sborman sendbrk(); 13538689Sborman else 13638689Sborman #endif 13738689Sborman sendabort(); 13832147Sminshall return 0; 13938689Sborman } else if (c == termEofChar) { 14038689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 14138689Sborman sendeof(); 14238689Sborman return 0; 14338689Sborman } 14438689Sborman return 1; 14538689Sborman } else if (c == termSuspChar) { 14638689Sborman sendsusp(); 14738689Sborman return(0); 14838689Sborman } else if (c == termFlushChar) { 14932147Sminshall xmitAO(); /* Transmit Abort Output */ 15032147Sminshall return 0; 15132147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 15238689Sborman if (c == termKillChar) { 15332147Sminshall xmitEL(); 15432147Sminshall return 0; 15538689Sborman } else if (c == termEraseChar) { 15632147Sminshall xmitEC(); /* Transmit Erase Character */ 15732147Sminshall return 0; 15832147Sminshall } 15932147Sminshall } 16032147Sminshall return 1; 16132147Sminshall } 16232147Sminshall 16332147Sminshall 16432147Sminshall /* 16532147Sminshall * Flush output to the terminal 16632147Sminshall */ 16732147Sminshall 16832147Sminshall void 16932553Sminshall TerminalFlushOutput() 17032147Sminshall { 171*39529Sborman #ifdef TIOCFLUSH 17232147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 17338689Sborman #else 17438689Sborman (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); 17538689Sborman #endif 17632147Sminshall } 17732147Sminshall 17832147Sminshall void 17932553Sminshall TerminalSaveState() 18032147Sminshall { 18138689Sborman #ifndef USE_TERMIO 18232147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 18332147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 18432147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 18538909Sborman ioctl(0, TIOCLGET, (char *)&olmode); 18632147Sminshall 18732147Sminshall ntc = otc; 18832147Sminshall nltc = oltc; 18932147Sminshall nttyb = ottyb; 19032254Sminshall 19138689Sborman #else /* USE_TERMIO */ 19238689Sborman ioctl(0, TCGETA, &old_tc); 19338689Sborman 19438689Sborman new_tc = old_tc; 19538689Sborman 19638689Sborman termFlushChar = 'O'&0x37; 19738689Sborman termWerasChar = 'W'&0x37; 19838689Sborman termRprntChar = 'R'&0x37; 19938689Sborman termLiteralNextChar = 'V'&0x37; 20038689Sborman termStartChar = 'Q'&0x37; 20138689Sborman termStopChar = 'S'&0x37; 20238689Sborman #endif /* USE_TERMIO */ 20332147Sminshall } 20432147Sminshall 205*39529Sborman unsigned 20638689Sborman char * 20738689Sborman tcval(func) 20838689Sborman register int func; 20938689Sborman { 21038689Sborman switch(func) { 211*39529Sborman case SLC_IP: return((unsigned char *)&termIntChar); 212*39529Sborman case SLC_ABORT: return((unsigned char *)&termQuitChar); 213*39529Sborman case SLC_EOF: return((unsigned char *)&termEofChar); 214*39529Sborman case SLC_EC: return((unsigned char *)&termEraseChar); 215*39529Sborman case SLC_EL: return((unsigned char *)&termKillChar); 216*39529Sborman case SLC_XON: return((unsigned char *)&termStartChar); 217*39529Sborman case SLC_XOFF: return((unsigned char *)&termStopChar); 218*39529Sborman #ifndef SYSV_TERMIO 219*39529Sborman case SLC_AO: return((unsigned char *)&termFlushChar); 220*39529Sborman case SLC_SUSP: return((unsigned char *)&termSuspChar); 221*39529Sborman case SLC_EW: return((unsigned char *)&termWerasChar); 222*39529Sborman case SLC_RP: return((unsigned char *)&termRprntChar); 223*39529Sborman case SLC_LNEXT: return((unsigned char *)&termLiteralNextChar); 224*39529Sborman #endif /* SYSV_TERMIO */ 22538689Sborman 22638689Sborman case SLC_SYNCH: 22738689Sborman case SLC_BRK: 22838689Sborman case SLC_AYT: 22938689Sborman case SLC_EOR: 23038689Sborman case SLC_FORW1: 23138689Sborman case SLC_FORW2: 23238689Sborman default: 233*39529Sborman return((unsigned char *)0); 23438689Sborman } 23538689Sborman } 23638689Sborman 23732147Sminshall void 23838689Sborman TerminalDefaultChars() 23938689Sborman { 24038689Sborman #ifndef USE_TERMIO 24138689Sborman ntc = otc; 24238689Sborman nltc = oltc; 24338689Sborman nttyb.sg_kill = ottyb.sg_kill; 24438689Sborman nttyb.sg_erase = ottyb.sg_erase; 24538689Sborman #else /* USE_TERMIO */ 24638689Sborman memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 247*39529Sborman # ifndef VFLUSHO 24838689Sborman termFlushChar = 'O'&0x37; 249*39529Sborman # endif 250*39529Sborman # ifndef VWERASE 25138689Sborman termWerasChar = 'W'&0x37; 252*39529Sborman # endif 253*39529Sborman # ifndef VREPRINT 25438689Sborman termRprntChar = 'R'&0x37; 255*39529Sborman # endif 256*39529Sborman # ifndef VLNEXT 25738689Sborman termLiteralNextChar = 'V'&0x37; 258*39529Sborman # endif 259*39529Sborman # ifndef VSTART 26038689Sborman termStartChar = 'Q'&0x37; 261*39529Sborman # endif 262*39529Sborman # ifndef VSTOP 26338689Sborman termStopChar = 'S'&0x37; 264*39529Sborman # endif 26538689Sborman #endif /* USE_TERMIO */ 26638689Sborman } 26738689Sborman 26838689Sborman void 26932553Sminshall TerminalRestoreState() 27032147Sminshall { 27132147Sminshall } 27232147Sminshall 27332147Sminshall /* 27432147Sminshall * TerminalNewMode - set up terminal to a specific mode. 27538689Sborman * MODE_ECHO: do local terminal echo 27638689Sborman * MODE_FLOW: do local flow control 27738689Sborman * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 27838689Sborman * MODE_EDIT: do local line editing 27938689Sborman * 28038689Sborman * Command mode: 28138689Sborman * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 28238689Sborman * local echo 28338689Sborman * local editing 28438689Sborman * local xon/xoff 28538689Sborman * local signal mapping 28638689Sborman * 28738689Sborman * Linemode: 28838689Sborman * local/no editing 28938689Sborman * Both Linemode and Single Character mode: 29038689Sborman * local/remote echo 29138689Sborman * local/no xon/xoff 29238689Sborman * local/no signal mapping 29332147Sminshall */ 29432147Sminshall 29532147Sminshall 29632147Sminshall void 29733286Sminshall TerminalNewMode(f) 29832147Sminshall register int f; 29932147Sminshall { 30032147Sminshall static int prevmode = 0; 30138689Sborman #ifndef USE_TERMIO 30238689Sborman struct tchars tc; 30338689Sborman struct ltchars ltc; 30432147Sminshall struct sgttyb sb; 30538909Sborman int lmode; 30638689Sborman #else /* USE_TERMIO */ 30738689Sborman struct termio tmp_tc; 30838689Sborman #endif /* USE_TERMIO */ 30932147Sminshall int onoff; 31032147Sminshall int old; 31132147Sminshall 31238689Sborman globalmode = f&~MODE_FORCE; 31332147Sminshall if (prevmode == f) 31432147Sminshall return; 31538689Sborman 31638689Sborman /* 31738689Sborman * Write any outstanding data before switching modes 31838689Sborman * ttyflush() returns 0 only when there is no more data 31938689Sborman * left to write out, it returns -1 if it couldn't do 32038689Sborman * anything at all, otherwise it returns 1 + the number 32138689Sborman * of characters left to write. 32238689Sborman */ 32338689Sborman old = ttyflush(SYNCHing|flushout); 32438689Sborman if (old < 0 || old > 1) { 32538689Sborman #ifndef USE_TERMIO 32638689Sborman ioctl(tin, TIOCGETP, (char *)&sb); 32738689Sborman #else /* USE_TERMIO */ 32838689Sborman ioctl(tin, TCGETA, (char *)&tmp_tc); 32938689Sborman #endif /* USE_TERMIO */ 33038689Sborman do { 33138689Sborman /* 33238689Sborman * Wait for data to drain, then flush again. 33338689Sborman */ 33438689Sborman #ifndef USE_TERMIO 33538689Sborman ioctl(tin, TIOCSETP, (char *)&sb); 33638689Sborman #else /* USE_TERMIO */ 33738689Sborman ioctl(tin, TCSETAW, (char *)&tmp_tc); 33838689Sborman #endif /* USE_TERMIO */ 33938689Sborman old = ttyflush(SYNCHing|flushout); 34038689Sborman } while (old < 0 || old > 1); 34138689Sborman } 34238689Sborman 34332147Sminshall old = prevmode; 34438689Sborman prevmode = f&~MODE_FORCE; 34538689Sborman #ifndef USE_TERMIO 34632147Sminshall sb = nttyb; 34738689Sborman tc = ntc; 34838689Sborman ltc = nltc; 34938909Sborman lmode = olmode; 35038689Sborman #else 35138689Sborman tmp_tc = new_tc; 35238689Sborman #endif 35332147Sminshall 35438689Sborman if (f&MODE_ECHO) { 35538689Sborman #ifndef USE_TERMIO 35638689Sborman sb.sg_flags |= ECHO; 35738689Sborman #else 35838689Sborman tmp_tc.c_lflag |= ECHO; 35938689Sborman tmp_tc.c_oflag |= ONLCR; 360*39529Sborman # ifdef notdef 36138689Sborman tmp_tc.c_iflag |= ICRNL; 362*39529Sborman # endif 36338689Sborman #endif 36438689Sborman } else { 36538689Sborman #ifndef USE_TERMIO 36638689Sborman sb.sg_flags &= ~ECHO; 36738689Sborman #else 36838689Sborman tmp_tc.c_lflag &= ~ECHO; 36938689Sborman tmp_tc.c_oflag &= ~ONLCR; 370*39529Sborman # ifdef notdef 37138689Sborman tmp_tc.c_iflag &= ~ICRNL; 372*39529Sborman # endif 37338689Sborman #endif 37438689Sborman } 37532147Sminshall 37638689Sborman if ((f&MODE_FLOW) == 0) { 37738689Sborman #ifndef USE_TERMIO 37838689Sborman tc.t_startc = -1; 37938689Sborman tc.t_stopc = -1; 38038689Sborman #else 38138689Sborman tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON); 38238689Sborman } else { 38338689Sborman tmp_tc.c_iflag |= IXANY|IXOFF|IXON; 38438689Sborman #endif 38538689Sborman } 38632147Sminshall 38738689Sborman if ((f&MODE_TRAPSIG) == 0) { 38838689Sborman #ifndef USE_TERMIO 38938689Sborman tc.t_intrc = -1; 39038689Sborman tc.t_quitc = -1; 39138689Sborman tc.t_eofc = -1; 39238689Sborman ltc.t_suspc = -1; 39338689Sborman ltc.t_dsuspc = -1; 39438689Sborman #else 39538689Sborman tmp_tc.c_lflag &= ~ISIG; 39638689Sborman #endif 39738689Sborman localchars = 0; 39838689Sborman } else { 39938689Sborman #ifdef USE_TERMIO 40038689Sborman tmp_tc.c_lflag |= ISIG; 40138689Sborman #endif 40238689Sborman localchars = 1; 40338689Sborman } 40438689Sborman 40538689Sborman if (f&MODE_EDIT) { 40638689Sborman #ifndef USE_TERMIO 40738689Sborman sb.sg_flags &= ~CBREAK; 40838689Sborman sb.sg_flags |= CRMOD; 40938689Sborman #else 41038689Sborman tmp_tc.c_lflag |= ICANON; 41138689Sborman #endif 41238689Sborman } else { 41338689Sborman #ifndef USE_TERMIO 41438689Sborman sb.sg_flags |= CBREAK; 41538689Sborman if (f&MODE_ECHO) 41632147Sminshall sb.sg_flags |= CRMOD; 41738689Sborman else 41838689Sborman sb.sg_flags &= ~CRMOD; 41938689Sborman #else 42038689Sborman tmp_tc.c_lflag &= ~ICANON; 42138689Sborman tmp_tc.c_iflag &= ~ICRNL; 42238689Sborman tmp_tc.c_cc[VMIN] = 1; 42338689Sborman tmp_tc.c_cc[VTIME] = 0; 42438689Sborman #endif 42538689Sborman } 42632147Sminshall 42738689Sborman if (f == -1) { 42838689Sborman onoff = 0; 42938689Sborman } else { 43038909Sborman #ifndef USE_TERMIO 431*39529Sborman if (f & MODE_OUTBIN) 43238909Sborman lmode |= LLITOUT; 43338909Sborman else 43438909Sborman lmode &= ~LLITOUT; 435*39529Sborman 436*39529Sborman if (f & MODE_INBIN) 43738909Sborman lmode |= LPASS8; 43838909Sborman else 43938909Sborman lmode &= ~LPASS8; 44038909Sborman #else 441*39529Sborman if (f & MODE_OUTBIN) 442*39529Sborman tmp_tc.c_lflag &= ~ISTRIP; 44338909Sborman else 444*39529Sborman tmp_tc.c_lflag |= ISTRIP; 445*39529Sborman if (f & MODE_INBIN) { 446*39529Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB); 447*39529Sborman tmp_tc.c_cflag |= CS8; 448*39529Sborman tmp_tc.c_cflag &= ~OPOST; 449*39529Sborman } else { 450*39529Sborman tmp_tc.c_cflag &= ~CSIZE; 451*39529Sborman tmp_tc.c_cflag |= CS7|PARENB; 452*39529Sborman tmp_tc.c_cflag |= OPOST; 453*39529Sborman } 45438909Sborman #endif 45538689Sborman onoff = 1; 45632147Sminshall } 45738689Sborman 45838689Sborman if (f != -1) { 459*39529Sborman #ifdef SIGTSTP 46038689Sborman if (f&MODE_EDIT) { 46138689Sborman void doescape(); 46238689Sborman 463*39529Sborman # ifndef USE_TERMIO 46438689Sborman ltc.t_suspc = escape; 465*39529Sborman # else 466*39529Sborman tmp_tc.c_cc[VSUSP] = escape; 467*39529Sborman # endif 46838689Sborman (void) signal(SIGTSTP, (int (*)())doescape); 46938689Sborman } else if (old&MODE_EDIT) { 47038689Sborman (void) signal(SIGTSTP, SIG_DFL); 47138689Sborman sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 47238689Sborman } 473*39529Sborman #endif /* SIGTSTP */ 47438689Sborman } else { 475*39529Sborman #ifdef SIGTSTP 47638689Sborman (void) signal(SIGTSTP, SIG_DFL); 47738689Sborman sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 478*39529Sborman #endif /* SIGTSTP */ 479*39529Sborman #ifndef USE_TERMIO 480*39529Sborman ltc = oltc; 481*39529Sborman tc = otc; 482*39529Sborman sb = ottyb; 483*39529Sborman #endif 48438689Sborman } 485*39529Sborman #ifndef USE_TERMIO 486*39529Sborman ioctl(tin, TIOCLSET, (char *)&lmode); 487*39529Sborman ioctl(tin, TIOCSLTC, (char *)<c); 488*39529Sborman ioctl(tin, TIOCSETC, (char *)&tc); 489*39529Sborman ioctl(tin, TIOCSETP, (char *)&sb); 490*39529Sborman #else 491*39529Sborman if (ioctl(tin, TCSETAW, &tmp_tc) < 0) 492*39529Sborman ioctl(tin, TCSETA, &tmp_tc); 493*39529Sborman #endif 494*39529Sborman 49532147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 49633286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 49733286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 49832147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 49932147Sminshall #if defined(TN3270) 50036242Sminshall if (noasynchtty == 0) { 50133286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 50232147Sminshall } 50332147Sminshall #endif /* defined(TN3270) */ 50432147Sminshall } 50532147Sminshall 506*39529Sborman #ifndef B19200 507*39529Sborman # define B19200 B9600 508*39529Sborman #endif 509*39529Sborman 510*39529Sborman #ifndef B38400 511*39529Sborman # define B38400 B19200 512*39529Sborman #endif 513*39529Sborman 514*39529Sborman /* 515*39529Sborman * This code assumes that the values B0, B50, B75... 516*39529Sborman * are in ascending order. They do not have to be 517*39529Sborman * contiguous. 518*39529Sborman */ 519*39529Sborman struct termspeeds { 520*39529Sborman long speed; 521*39529Sborman long value; 522*39529Sborman } termspeeds[] = { 523*39529Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 524*39529Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 525*39529Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 526*39529Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 527*39529Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, 528*39529Sborman { 38400, B38400 }, { -1, B38400 } 529*39529Sborman }; 530*39529Sborman 531*39529Sborman #ifndef USE_TERMIO 532*39529Sborman # define ISPEED ottyb.sg_ispeed 533*39529Sborman # define OSPEED ottyb.sg_ospeed 534*39529Sborman #else 535*39529Sborman # ifdef SYSV_TERMIO 536*39529Sborman # define ISPEED (old_tc.c_cflag&CBAUD) 537*39529Sborman # define OSPEED ISPEED 538*39529Sborman # else 539*39529Sborman # define ISPEED old_tc.c_ispeed 540*39529Sborman # define OSPEED old_tc.c_ospeed 541*39529Sborman # endif 542*39529Sborman #endif 543*39529Sborman 54437219Sminshall void 54537219Sminshall TerminalSpeeds(ispeed, ospeed) 54637219Sminshall long *ispeed; 54737219Sminshall long *ospeed; 54837219Sminshall { 549*39529Sborman register struct termspeeds *tp; 55032147Sminshall 551*39529Sborman tp = termspeeds; 552*39529Sborman while ((tp->speed != -1) && (tp->value < ISPEED)) 553*39529Sborman tp++; 554*39529Sborman *ispeed = tp->speed; 555*39529Sborman 556*39529Sborman tp = termspeeds; 557*39529Sborman while ((tp->speed != -1) && (tp->value < OSPEED)) 558*39529Sborman tp++; 559*39529Sborman *ospeed = tp->speed; 56037219Sminshall } 56137219Sminshall 56232147Sminshall int 56337219Sminshall TerminalWindowSize(rows, cols) 56437219Sminshall long *rows, *cols; 56537219Sminshall { 56638689Sborman #ifdef TIOCGWINSZ 56737219Sminshall struct winsize ws; 56837219Sminshall 56938689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 57038689Sborman *rows = ws.ws_row; 57138689Sborman *cols = ws.ws_col; 57238689Sborman return 1; 57337219Sminshall } 57438810Sborman #endif /* TIOCGWINSZ */ 57538689Sborman return 0; 57637219Sminshall } 57737219Sminshall 57837219Sminshall int 57935417Sminshall NetClose(fd) 58035417Sminshall int fd; 58132147Sminshall { 58235417Sminshall return close(fd); 58332147Sminshall } 58432147Sminshall 58532147Sminshall 58632147Sminshall void 58732553Sminshall NetNonblockingIO(fd, onoff) 58832147Sminshall int 58932147Sminshall fd, 59032147Sminshall onoff; 59132147Sminshall { 59232147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 59332147Sminshall } 59432147Sminshall 59534849Sminshall #if defined(TN3270) 59632147Sminshall void 59732553Sminshall NetSigIO(fd, onoff) 59832147Sminshall int 59932147Sminshall fd, 60032147Sminshall onoff; 60132147Sminshall { 60232147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 60332147Sminshall } 60432147Sminshall 60532147Sminshall void 60632553Sminshall NetSetPgrp(fd) 60732147Sminshall int fd; 60832147Sminshall { 60932147Sminshall int myPid; 61032147Sminshall 61132147Sminshall myPid = getpid(); 61236274Sminshall fcntl(fd, F_SETOWN, myPid); 61332147Sminshall } 61434849Sminshall #endif /*defined(TN3270)*/ 61532553Sminshall 61632553Sminshall /* 61732553Sminshall * Various signal handling routines. 61832553Sminshall */ 61932147Sminshall 62033286Sminshall static void 62132553Sminshall deadpeer() 62232553Sminshall { 62332553Sminshall setcommandmode(); 62432553Sminshall longjmp(peerdied, -1); 62532553Sminshall } 62632147Sminshall 62733286Sminshall static void 62832553Sminshall intr() 62932553Sminshall { 63032553Sminshall if (localchars) { 63132553Sminshall intp(); 63232553Sminshall return; 63332553Sminshall } 63432553Sminshall setcommandmode(); 63532553Sminshall longjmp(toplevel, -1); 63632553Sminshall } 63732553Sminshall 63833286Sminshall static void 63932553Sminshall intr2() 64032553Sminshall { 64132553Sminshall if (localchars) { 64238689Sborman #ifdef KLUDGELINEMODE 64338689Sborman if (kludgelinemode) 64438689Sborman sendbrk(); 64538689Sborman else 64638689Sborman #endif 64738689Sborman sendabort(); 64832553Sminshall return; 64932553Sminshall } 65032553Sminshall } 65132553Sminshall 65233286Sminshall static void 65337219Sminshall sendwin() 65437219Sminshall { 65537219Sminshall if (connected) { 65637219Sminshall sendnaws(); 65737219Sminshall } 65837219Sminshall } 65937219Sminshall 66037219Sminshall static void 66132553Sminshall doescape() 66232553Sminshall { 66338689Sborman command(0, 0, 0); 66432553Sminshall } 66532553Sminshall 66632553Sminshall void 66732531Sminshall sys_telnet_init() 66832531Sminshall { 669*39529Sborman #ifndef VOID_SIGNAL 67034849Sminshall (void) signal(SIGINT, (int (*)())intr); 67134849Sminshall (void) signal(SIGQUIT, (int (*)())intr2); 67234849Sminshall (void) signal(SIGPIPE, (int (*)())deadpeer); 67338689Sborman #else 67438689Sborman (void) signal(SIGINT, (void (*)())intr); 67538689Sborman (void) signal(SIGQUIT, (void (*)())intr2); 67638689Sborman (void) signal(SIGPIPE, (void (*)())deadpeer); 67738689Sborman #endif 67838689Sborman #ifdef SIGWINCH 67937219Sminshall (void) signal(SIGWINCH, (int (*)())sendwin); 68038689Sborman #endif 68132553Sminshall 68238689Sborman setconnmode(0); 68332531Sminshall 68432531Sminshall NetNonblockingIO(net, 1); 68532531Sminshall 68632531Sminshall #if defined(TN3270) 68736242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 68832531Sminshall NetSigIO(net, 1); 68932531Sminshall NetSetPgrp(net); 69032531Sminshall } 69132531Sminshall #endif /* defined(TN3270) */ 69232531Sminshall 69332531Sminshall #if defined(SO_OOBINLINE) 69434849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 69534849Sminshall perror("SetSockOpt"); 69634849Sminshall } 69732531Sminshall #endif /* defined(SO_OOBINLINE) */ 69832531Sminshall } 69932531Sminshall 70032531Sminshall /* 70132531Sminshall * Process rings - 70232531Sminshall * 70332531Sminshall * This routine tries to fill up/empty our various rings. 70432531Sminshall * 70532531Sminshall * The parameter specifies whether this is a poll operation, 70632531Sminshall * or a block-until-something-happens operation. 70732531Sminshall * 70832531Sminshall * The return value is 1 if something happened, 0 if not. 70932531Sminshall */ 71032531Sminshall 71132531Sminshall int 71232531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 71332531Sminshall int poll; /* If 0, then block until something to do */ 71432531Sminshall { 71532531Sminshall register int c; 71632531Sminshall /* One wants to be a bit careful about setting returnValue 71732531Sminshall * to one, since a one implies we did some useful work, 71832531Sminshall * and therefore probably won't be called to block next 71932531Sminshall * time (TN3270 mode only). 72032531Sminshall */ 72132531Sminshall int returnValue = 0; 72232531Sminshall static struct timeval TimeValue = { 0 }; 72332531Sminshall 72432531Sminshall if (netout) { 72532531Sminshall FD_SET(net, &obits); 72632531Sminshall } 72732531Sminshall if (ttyout) { 72832531Sminshall FD_SET(tout, &obits); 72932531Sminshall } 73032531Sminshall #if defined(TN3270) 73132531Sminshall if (ttyin) { 73232531Sminshall FD_SET(tin, &ibits); 73332531Sminshall } 73432531Sminshall #else /* defined(TN3270) */ 73532531Sminshall if (ttyin) { 73632531Sminshall FD_SET(tin, &ibits); 73732531Sminshall } 73832531Sminshall #endif /* defined(TN3270) */ 73932531Sminshall #if defined(TN3270) 74032531Sminshall if (netin) { 74132531Sminshall FD_SET(net, &ibits); 74232531Sminshall } 74332531Sminshall # else /* !defined(TN3270) */ 74432531Sminshall if (netin) { 74532531Sminshall FD_SET(net, &ibits); 74632531Sminshall } 74732531Sminshall # endif /* !defined(TN3270) */ 74832531Sminshall if (netex) { 74932531Sminshall FD_SET(net, &xbits); 75032531Sminshall } 75132531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 75232531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 75332531Sminshall if (c == -1) { 75432531Sminshall /* 75532531Sminshall * we can get EINTR if we are in line mode, 75632531Sminshall * and the user does an escape (TSTP), or 75732531Sminshall * some other signal generator. 75832531Sminshall */ 75932531Sminshall if (errno == EINTR) { 76032531Sminshall return 0; 76132531Sminshall } 76232531Sminshall # if defined(TN3270) 76332531Sminshall /* 76432531Sminshall * we can get EBADF if we were in transparent 76532531Sminshall * mode, and the transcom process died. 76632531Sminshall */ 76732531Sminshall if (errno == EBADF) { 76832531Sminshall /* 76932531Sminshall * zero the bits (even though kernel does it) 77032531Sminshall * to make sure we are selecting on the right 77132531Sminshall * ones. 77232531Sminshall */ 77332531Sminshall FD_ZERO(&ibits); 77432531Sminshall FD_ZERO(&obits); 77532531Sminshall FD_ZERO(&xbits); 77632531Sminshall return 0; 77732531Sminshall } 77832531Sminshall # endif /* defined(TN3270) */ 77932531Sminshall /* I don't like this, does it ever happen? */ 78032531Sminshall printf("sleep(5) from telnet, after select\r\n"); 78132531Sminshall sleep(5); 78232531Sminshall } 78332531Sminshall return 0; 78432531Sminshall } 78532531Sminshall 78632531Sminshall /* 78732531Sminshall * Any urgent data? 78832531Sminshall */ 78932531Sminshall if (FD_ISSET(net, &xbits)) { 79032531Sminshall FD_CLR(net, &xbits); 79132531Sminshall SYNCHing = 1; 79232531Sminshall ttyflush(1); /* flush already enqueued data */ 79332531Sminshall } 79432531Sminshall 79532531Sminshall /* 79632531Sminshall * Something to read from the network... 79732531Sminshall */ 79832531Sminshall if (FD_ISSET(net, &ibits)) { 79932531Sminshall int canread; 80032531Sminshall 80132531Sminshall FD_CLR(net, &ibits); 80232531Sminshall canread = ring_empty_consecutive(&netiring); 80332531Sminshall #if !defined(SO_OOBINLINE) 80432531Sminshall /* 80532531Sminshall * In 4.2 (and some early 4.3) systems, the 80632531Sminshall * OOB indication and data handling in the kernel 80732531Sminshall * is such that if two separate TCP Urgent requests 80832531Sminshall * come in, one byte of TCP data will be overlaid. 80932531Sminshall * This is fatal for Telnet, but we try to live 81032531Sminshall * with it. 81132531Sminshall * 81232531Sminshall * In addition, in 4.2 (and...), a special protocol 81332531Sminshall * is needed to pick up the TCP Urgent data in 81432531Sminshall * the correct sequence. 81532531Sminshall * 81632531Sminshall * What we do is: if we think we are in urgent 81732531Sminshall * mode, we look to see if we are "at the mark". 81832531Sminshall * If we are, we do an OOB receive. If we run 81932531Sminshall * this twice, we will do the OOB receive twice, 82032531Sminshall * but the second will fail, since the second 82132531Sminshall * time we were "at the mark", but there wasn't 82232531Sminshall * any data there (the kernel doesn't reset 82332531Sminshall * "at the mark" until we do a normal read). 82432531Sminshall * Once we've read the OOB data, we go ahead 82532531Sminshall * and do normal reads. 82632531Sminshall * 82732531Sminshall * There is also another problem, which is that 82832531Sminshall * since the OOB byte we read doesn't put us 82932531Sminshall * out of OOB state, and since that byte is most 83032531Sminshall * likely the TELNET DM (data mark), we would 83132531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 83232531Sminshall * So, clocks to the rescue. If we've "just" 83332531Sminshall * received a DM, then we test for the 83432531Sminshall * presence of OOB data when the receive OOB 83532531Sminshall * fails (and AFTER we did the normal mode read 83632531Sminshall * to clear "at the mark"). 83732531Sminshall */ 83832531Sminshall if (SYNCHing) { 83932531Sminshall int atmark; 84032531Sminshall 84132531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 84232531Sminshall if (atmark) { 84332531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 84432531Sminshall if ((c == -1) && (errno == EINVAL)) { 84532531Sminshall c = recv(net, netiring.supply, canread, 0); 84632531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 84732531Sminshall SYNCHing = stilloob(net); 84832531Sminshall } 84932531Sminshall } 85032531Sminshall } else { 85132531Sminshall c = recv(net, netiring.supply, canread, 0); 85232531Sminshall } 85332531Sminshall } else { 85432531Sminshall c = recv(net, netiring.supply, canread, 0); 85532531Sminshall } 85632531Sminshall settimer(didnetreceive); 85732531Sminshall #else /* !defined(SO_OOBINLINE) */ 85832531Sminshall c = recv(net, netiring.supply, canread, 0); 85932531Sminshall #endif /* !defined(SO_OOBINLINE) */ 86032531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 86132531Sminshall c = 0; 86232531Sminshall } else if (c <= 0) { 86332531Sminshall return -1; 86432531Sminshall } 86532531Sminshall if (netdata) { 86632531Sminshall Dump('<', netiring.supply, c); 86732531Sminshall } 86832667Sminshall if (c) 86932667Sminshall ring_supplied(&netiring, c); 87032531Sminshall returnValue = 1; 87132531Sminshall } 87232531Sminshall 87332531Sminshall /* 87432531Sminshall * Something to read from the tty... 87532531Sminshall */ 87632531Sminshall if (FD_ISSET(tin, &ibits)) { 87732531Sminshall FD_CLR(tin, &ibits); 87833286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 87932531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 88032531Sminshall c = 0; 88132531Sminshall } else { 88232531Sminshall /* EOF detection for line mode!!!! */ 88333281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 88432531Sminshall /* must be an EOF... */ 88532531Sminshall *ttyiring.supply = termEofChar; 88632531Sminshall c = 1; 88732531Sminshall } 88832531Sminshall if (c <= 0) { 88932531Sminshall return -1; 89032531Sminshall } 89138208Sminshall if (termdata) { 89238208Sminshall Dump('<', ttyiring.supply, c); 89338208Sminshall } 89432667Sminshall ring_supplied(&ttyiring, c); 89532531Sminshall } 89632531Sminshall returnValue = 1; /* did something useful */ 89732531Sminshall } 89832531Sminshall 89932531Sminshall if (FD_ISSET(net, &obits)) { 90032531Sminshall FD_CLR(net, &obits); 90132531Sminshall returnValue |= netflush(); 90232531Sminshall } 90332531Sminshall if (FD_ISSET(tout, &obits)) { 90432531Sminshall FD_CLR(tout, &obits); 90538689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0); 90632531Sminshall } 90732531Sminshall 90832531Sminshall return returnValue; 90932531Sminshall } 910