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*38909Sborman static char sccsid[] = "@(#)sys_bsd.c 1.21 (Berkeley) 09/01/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 #if defined(unix) 2832147Sminshall 2936274Sminshall #include <fcntl.h> 3032381Sminshall #include <sys/types.h> 3132147Sminshall #include <sys/time.h> 3232531Sminshall #include <sys/socket.h> 3332147Sminshall #include <signal.h> 3432531Sminshall #include <errno.h> 3538689Sborman #include <arpa/telnet.h> 3632147Sminshall 3732381Sminshall #include "ring.h" 3832381Sminshall 3932657Sminshall #include "fdset.h" 4032657Sminshall 4132147Sminshall #include "defines.h" 4232147Sminshall #include "externs.h" 4332147Sminshall #include "types.h" 4432147Sminshall 4532147Sminshall int 4632531Sminshall tout, /* Output file descriptor */ 4732531Sminshall tin, /* Input file descriptor */ 4836242Sminshall net; 4932147Sminshall 5038689Sborman #ifndef USE_TERMIO 5138689Sborman struct tchars otc = { 0 }, ntc = { 0 }; 5238689Sborman struct ltchars oltc = { 0 }, nltc = { 0 }; 5338689Sborman struct sgttyb ottyb = { 0 }, nttyb = { 0 }; 54*38909Sborman int olmode = 0; 5532147Sminshall 5638689Sborman #define ISPEED ottyb.sg_ispeed 5738689Sborman #define OSPEED ottyb.sg_ospeed 5838689Sborman #else /* USE_TERMIO */ 5938689Sborman struct termio old_tc = { 0 }; 6038689Sborman extern struct termio new_tc; 6138689Sborman 6238689Sborman #define ISPEED (old_tc.c_cflag&CBAUD) 6338689Sborman #define OSPEED ISPEED 6438689Sborman #endif /* USE_TERMIO */ 6538689Sborman 6632531Sminshall static fd_set ibits, obits, xbits; 6732147Sminshall 6832531Sminshall 6932531Sminshall init_sys() 7032531Sminshall { 7132531Sminshall tout = fileno(stdout); 7232531Sminshall tin = fileno(stdin); 7332531Sminshall FD_ZERO(&ibits); 7432531Sminshall FD_ZERO(&obits); 7532531Sminshall FD_ZERO(&xbits); 7632531Sminshall 7732531Sminshall errno = 0; 7832531Sminshall } 7932531Sminshall 8032531Sminshall 8133286Sminshall TerminalWrite(buf, n) 8232147Sminshall char *buf; 8332147Sminshall int n; 8432147Sminshall { 8533286Sminshall return write(tout, buf, n); 8632147Sminshall } 8732147Sminshall 8833286Sminshall TerminalRead(buf, n) 8932147Sminshall char *buf; 9032147Sminshall int n; 9132147Sminshall { 9233286Sminshall return read(tin, buf, n); 9332147Sminshall } 9432147Sminshall 9532147Sminshall /* 9632147Sminshall * 9732147Sminshall */ 9832147Sminshall 9932147Sminshall int 10032553Sminshall TerminalAutoFlush() 10132147Sminshall { 10232147Sminshall #if defined(LNOFLSH) 10332147Sminshall int flush; 10432147Sminshall 10532147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 10632147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 10732147Sminshall #else /* LNOFLSH */ 10832147Sminshall return 1; 10932147Sminshall #endif /* LNOFLSH */ 11032147Sminshall } 11132147Sminshall 11238689Sborman #ifdef KLUDGELINEMODE 11338689Sborman extern int kludgelinemode; 11438689Sborman #endif 11532147Sminshall /* 11632147Sminshall * TerminalSpecialChars() 11732147Sminshall * 11832147Sminshall * Look at an input character to see if it is a special character 11932147Sminshall * and decide what to do. 12032147Sminshall * 12132147Sminshall * Output: 12232147Sminshall * 12332147Sminshall * 0 Don't add this character. 12432147Sminshall * 1 Do add this character 12532147Sminshall */ 12632147Sminshall 12732147Sminshall int 12832553Sminshall TerminalSpecialChars(c) 12932147Sminshall int c; 13032147Sminshall { 13132553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 13232147Sminshall 13338689Sborman if (c == termIntChar) { 13432147Sminshall intp(); 13532147Sminshall return 0; 13638689Sborman } else if (c == termQuitChar) { 13738689Sborman #ifdef KLUDGELINEMODE 13838689Sborman if (kludgelinemode) 13938689Sborman sendbrk(); 14038689Sborman else 14138689Sborman #endif 14238689Sborman sendabort(); 14332147Sminshall return 0; 14438689Sborman } else if (c == termEofChar) { 14538689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 14638689Sborman sendeof(); 14738689Sborman return 0; 14838689Sborman } 14938689Sborman return 1; 15038689Sborman } else if (c == termSuspChar) { 15138689Sborman sendsusp(); 15238689Sborman return(0); 15338689Sborman } else if (c == termFlushChar) { 15432147Sminshall xmitAO(); /* Transmit Abort Output */ 15532147Sminshall return 0; 15632147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 15738689Sborman if (c == termKillChar) { 15832147Sminshall xmitEL(); 15932147Sminshall return 0; 16038689Sborman } else if (c == termEraseChar) { 16132147Sminshall xmitEC(); /* Transmit Erase Character */ 16232147Sminshall return 0; 16332147Sminshall } 16432147Sminshall } 16532147Sminshall return 1; 16632147Sminshall } 16732147Sminshall 16832147Sminshall 16932147Sminshall /* 17032147Sminshall * Flush output to the terminal 17132147Sminshall */ 17232147Sminshall 17332147Sminshall void 17432553Sminshall TerminalFlushOutput() 17532147Sminshall { 17638689Sborman #ifndef USE_TERMIO 17732147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 17838689Sborman #else 17938689Sborman (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); 18038689Sborman #endif 18132147Sminshall } 18232147Sminshall 18332147Sminshall void 18432553Sminshall TerminalSaveState() 18532147Sminshall { 18638689Sborman #ifndef USE_TERMIO 18732147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 18832147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 18932147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 190*38909Sborman ioctl(0, TIOCLGET, (char *)&olmode); 19132147Sminshall 19232147Sminshall ntc = otc; 19332147Sminshall nltc = oltc; 19432147Sminshall nttyb = ottyb; 19532254Sminshall 19638689Sborman #else /* USE_TERMIO */ 19738689Sborman ioctl(0, TCGETA, &old_tc); 19838689Sborman 19938689Sborman new_tc = old_tc; 20038689Sborman 20138689Sborman termFlushChar = 'O'&0x37; 20238689Sborman termWerasChar = 'W'&0x37; 20338689Sborman termRprntChar = 'R'&0x37; 20438689Sborman termLiteralNextChar = 'V'&0x37; 20538689Sborman termStartChar = 'Q'&0x37; 20638689Sborman termStopChar = 'S'&0x37; 20738689Sborman #endif /* USE_TERMIO */ 20832147Sminshall } 20932147Sminshall 21038689Sborman char * 21138689Sborman tcval(func) 21238689Sborman register int func; 21338689Sborman { 21438689Sborman switch(func) { 21538689Sborman case SLC_IP: return(&termIntChar); 21638689Sborman case SLC_ABORT: return(&termQuitChar); 21738689Sborman case SLC_EOF: return(&termEofChar); 21838689Sborman case SLC_EC: return(&termEraseChar); 21938689Sborman case SLC_EL: return(&termKillChar); 22038689Sborman case SLC_XON: return(&termStartChar); 22138689Sborman case SLC_XOFF: return(&termStopChar); 22238689Sborman #ifndef CRAY 22338689Sborman case SLC_AO: return(&termFlushChar); 22438689Sborman case SLC_SUSP: return(&termSuspChar); 22538689Sborman case SLC_EW: return(&termWerasChar); 22638689Sborman case SLC_RP: return(&termRprntChar); 22738689Sborman case SLC_LNEXT: return(&termLiteralNextChar); 22838810Sborman #endif /* CRAY */ 22938689Sborman 23038689Sborman case SLC_SYNCH: 23138689Sborman case SLC_BRK: 23238689Sborman case SLC_AYT: 23338689Sborman case SLC_EOR: 23438689Sborman case SLC_FORW1: 23538689Sborman case SLC_FORW2: 23638689Sborman default: 23738689Sborman return((char *)0); 23838689Sborman } 23938689Sborman } 24038689Sborman 24132147Sminshall void 24238689Sborman TerminalDefaultChars() 24338689Sborman { 24438689Sborman #ifndef USE_TERMIO 24538689Sborman ntc = otc; 24638689Sborman nltc = oltc; 24738689Sborman nttyb.sg_kill = ottyb.sg_kill; 24838689Sborman nttyb.sg_erase = ottyb.sg_erase; 24938689Sborman #else /* USE_TERMIO */ 25038689Sborman memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 25138689Sborman termFlushChar = 'O'&0x37; 25238689Sborman termWerasChar = 'W'&0x37; 25338689Sborman termRprntChar = 'R'&0x37; 25438689Sborman termLiteralNextChar = 'V'&0x37; 25538689Sborman termStartChar = 'Q'&0x37; 25638689Sborman termStopChar = 'S'&0x37; 25738689Sborman #endif /* USE_TERMIO */ 25838689Sborman } 25938689Sborman 26038689Sborman void 26132553Sminshall TerminalRestoreState() 26232147Sminshall { 26332147Sminshall } 26432147Sminshall 26532147Sminshall /* 26632147Sminshall * TerminalNewMode - set up terminal to a specific mode. 26738689Sborman * MODE_ECHO: do local terminal echo 26838689Sborman * MODE_FLOW: do local flow control 26938689Sborman * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 27038689Sborman * MODE_EDIT: do local line editing 27138689Sborman * 27238689Sborman * Command mode: 27338689Sborman * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 27438689Sborman * local echo 27538689Sborman * local editing 27638689Sborman * local xon/xoff 27738689Sborman * local signal mapping 27838689Sborman * 27938689Sborman * Linemode: 28038689Sborman * local/no editing 28138689Sborman * Both Linemode and Single Character mode: 28238689Sborman * local/remote echo 28338689Sborman * local/no xon/xoff 28438689Sborman * local/no signal mapping 28532147Sminshall */ 28632147Sminshall 28732147Sminshall 28832147Sminshall void 28933286Sminshall TerminalNewMode(f) 29032147Sminshall register int f; 29132147Sminshall { 29232147Sminshall static int prevmode = 0; 29338689Sborman #ifndef USE_TERMIO 29438689Sborman struct tchars tc; 29538689Sborman struct ltchars ltc; 29632147Sminshall struct sgttyb sb; 297*38909Sborman int lmode; 29838689Sborman #else /* USE_TERMIO */ 29938689Sborman struct termio tmp_tc; 30038689Sborman #endif /* USE_TERMIO */ 30132147Sminshall int onoff; 30232147Sminshall int old; 30332147Sminshall 30438689Sborman globalmode = f&~MODE_FORCE; 30532147Sminshall if (prevmode == f) 30632147Sminshall return; 30738689Sborman 30838689Sborman /* 30938689Sborman * Write any outstanding data before switching modes 31038689Sborman * ttyflush() returns 0 only when there is no more data 31138689Sborman * left to write out, it returns -1 if it couldn't do 31238689Sborman * anything at all, otherwise it returns 1 + the number 31338689Sborman * of characters left to write. 31438689Sborman */ 31538689Sborman old = ttyflush(SYNCHing|flushout); 31638689Sborman if (old < 0 || old > 1) { 31738689Sborman #ifndef USE_TERMIO 31838689Sborman ioctl(tin, TIOCGETP, (char *)&sb); 31938689Sborman #else /* USE_TERMIO */ 32038689Sborman ioctl(tin, TCGETA, (char *)&tmp_tc); 32138689Sborman #endif /* USE_TERMIO */ 32238689Sborman do { 32338689Sborman /* 32438689Sborman * Wait for data to drain, then flush again. 32538689Sborman */ 32638689Sborman #ifndef USE_TERMIO 32738689Sborman ioctl(tin, TIOCSETP, (char *)&sb); 32838689Sborman #else /* USE_TERMIO */ 32938689Sborman ioctl(tin, TCSETAW, (char *)&tmp_tc); 33038689Sborman #endif /* USE_TERMIO */ 33138689Sborman old = ttyflush(SYNCHing|flushout); 33238689Sborman } while (old < 0 || old > 1); 33338689Sborman } 33438689Sborman 33532147Sminshall old = prevmode; 33638689Sborman prevmode = f&~MODE_FORCE; 33738689Sborman #ifndef USE_TERMIO 33832147Sminshall sb = nttyb; 33938689Sborman tc = ntc; 34038689Sborman ltc = nltc; 341*38909Sborman lmode = olmode; 34238689Sborman #else 34338689Sborman tmp_tc = new_tc; 34438689Sborman #endif 34532147Sminshall 34638689Sborman if (f&MODE_ECHO) { 34738689Sborman #ifndef USE_TERMIO 34838689Sborman sb.sg_flags |= ECHO; 34938689Sborman #else 35038689Sborman tmp_tc.c_lflag |= ECHO; 35138689Sborman tmp_tc.c_oflag |= ONLCR; 35238689Sborman tmp_tc.c_iflag |= ICRNL; 35338689Sborman #endif 35438689Sborman } else { 35538689Sborman #ifndef USE_TERMIO 35638689Sborman sb.sg_flags &= ~ECHO; 35738689Sborman #else 35838689Sborman tmp_tc.c_lflag &= ~ECHO; 35938689Sborman tmp_tc.c_oflag &= ~ONLCR; 36038689Sborman tmp_tc.c_iflag &= ~ICRNL; 36138689Sborman #endif 36238689Sborman } 36332147Sminshall 36438689Sborman if ((f&MODE_FLOW) == 0) { 36538689Sborman #ifndef USE_TERMIO 36638689Sborman tc.t_startc = -1; 36738689Sborman tc.t_stopc = -1; 36838689Sborman #else 36938689Sborman tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON); 37038689Sborman } else { 37138689Sborman tmp_tc.c_iflag |= IXANY|IXOFF|IXON; 37238689Sborman #endif 37338689Sborman } 37432147Sminshall 37538689Sborman if ((f&MODE_TRAPSIG) == 0) { 37638689Sborman #ifndef USE_TERMIO 37738689Sborman tc.t_intrc = -1; 37838689Sborman tc.t_quitc = -1; 37938689Sborman tc.t_eofc = -1; 38038689Sborman ltc.t_suspc = -1; 38138689Sborman ltc.t_dsuspc = -1; 38238689Sborman #else 38338689Sborman tmp_tc.c_lflag &= ~ISIG; 38438689Sborman #endif 38538689Sborman localchars = 0; 38638689Sborman } else { 38738689Sborman #ifdef USE_TERMIO 38838689Sborman tmp_tc.c_lflag |= ISIG; 38938689Sborman #endif 39038689Sborman localchars = 1; 39138689Sborman } 39238689Sborman 39338689Sborman if (f&MODE_EDIT) { 39438689Sborman #ifndef USE_TERMIO 39538689Sborman sb.sg_flags &= ~CBREAK; 39638689Sborman sb.sg_flags |= CRMOD; 39738689Sborman #else 39838689Sborman tmp_tc.c_lflag |= ICANON; 39938689Sborman #endif 40038689Sborman } else { 40138689Sborman #ifndef USE_TERMIO 40238689Sborman sb.sg_flags |= CBREAK; 40338689Sborman if (f&MODE_ECHO) 40432147Sminshall sb.sg_flags |= CRMOD; 40538689Sborman else 40638689Sborman sb.sg_flags &= ~CRMOD; 40738689Sborman #else 40838689Sborman tmp_tc.c_lflag &= ~ICANON; 40938689Sborman tmp_tc.c_iflag &= ~ICRNL; 41038689Sborman tmp_tc.c_cc[VMIN] = 1; 41138689Sborman tmp_tc.c_cc[VTIME] = 0; 41238689Sborman #endif 41338689Sborman } 41432147Sminshall 41538689Sborman if (f == -1) { 41638689Sborman onoff = 0; 41738689Sborman } else { 418*38909Sborman #ifndef USE_TERMIO 419*38909Sborman if (his_want_state_is_will(TELOPT_BINARY)) 420*38909Sborman lmode |= LLITOUT; 421*38909Sborman else 422*38909Sborman lmode &= ~LLITOUT; 423*38909Sborman if (my_want_state_is_will(TELOPT_BINARY)) 424*38909Sborman lmode |= LPASS8; 425*38909Sborman else 426*38909Sborman lmode &= ~LPASS8; 427*38909Sborman #else 428*38909Sborman if (my_want_state_is_will(TELOPT_BINARY)) 429*38909Sborman tmp.tc.c_lflag &= ~ISTRIP; 430*38909Sborman else 431*38909Sborman tmp.tc.c_lflag |= ISTRIP; 432*38909Sborman #endif 43338689Sborman onoff = 1; 43432147Sminshall } 43538689Sborman 43638689Sborman #ifndef USE_TERMIO 43738689Sborman if (f != -1) { 43838689Sborman if (f&MODE_EDIT) { 43938689Sborman void doescape(); 44038689Sborman 44138689Sborman ltc.t_suspc = escape; 44238689Sborman (void) signal(SIGTSTP, (int (*)())doescape); 44338689Sborman } else if (old&MODE_EDIT) { 44438689Sborman (void) signal(SIGTSTP, SIG_DFL); 44538689Sborman sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 44638689Sborman } 447*38909Sborman ioctl(tin, TIOCLSET, (char *)&lmode); 44838689Sborman ioctl(tin, TIOCSLTC, (char *)<c); 44938689Sborman ioctl(tin, TIOCSETC, (char *)&tc); 45038689Sborman ioctl(tin, TIOCSETP, (char *)&sb); 45138689Sborman } else { 45238689Sborman (void) signal(SIGTSTP, SIG_DFL); 45338689Sborman sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 454*38909Sborman ioctl(tin, TIOCLSET, (char *)&lmode); 45538689Sborman ioctl(tin, TIOCSLTC, (char *)&oltc); 45638689Sborman ioctl(tin, TIOCSETC, (char *)&otc); 45738689Sborman ioctl(tin, TIOCSETP, (char *)&ottyb); 45838689Sborman } 45932147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 46033286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 46133286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 46232147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 46332147Sminshall #if defined(TN3270) 46436242Sminshall if (noasynchtty == 0) { 46533286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 46632147Sminshall } 46732147Sminshall #endif /* defined(TN3270) */ 46838689Sborman #else /* USE_TERMIO */ 46938689Sborman if (ioctl(tin, TCSETAW, &tmp_tc) < 0) 47038689Sborman ioctl(tin, TCSETA, &tmp_tc); 47138689Sborman #endif /* USE_TERMIO */ 47232147Sminshall } 47332147Sminshall 47437219Sminshall void 47537219Sminshall TerminalSpeeds(ispeed, ospeed) 47637219Sminshall long *ispeed; 47737219Sminshall long *ospeed; 47837219Sminshall { 47937219Sminshall /* 48037219Sminshall * The order here is important. The index of each speed needs to 48137219Sminshall * correspond with the sgtty structure value for that speed. 48237219Sminshall * 48337219Sminshall * Additionally, the search algorithm assumes the table is in 48437219Sminshall * ascending sequence. 48537219Sminshall */ 48637219Sminshall static int ttyspeeds[] = { 48737219Sminshall 0, 50, 75, 110, 134, 150, 200, 300, 48837219Sminshall 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 }; 48937219Sminshall #define NUMSPEEDS sizeof ttyspeeds/sizeof ttyspeeds[0] 49032147Sminshall 49138689Sborman if ((OSPEED < 0) || (OSPEED > NUMSPEEDS) || 49238689Sborman (ISPEED < 0) || (ISPEED > NUMSPEEDS)) { 49337219Sminshall ExitString("Invalid terminal speed."); 49437219Sminshall /*NOTREACHED*/ 49537219Sminshall } else { 49638689Sborman *ispeed = ttyspeeds[ISPEED]; 49738689Sborman *ospeed = ttyspeeds[OSPEED]; 49837219Sminshall } 49937219Sminshall } 50037219Sminshall 50132147Sminshall int 50237219Sminshall TerminalWindowSize(rows, cols) 50337219Sminshall long *rows, *cols; 50437219Sminshall { 50538689Sborman #ifdef TIOCGWINSZ 50637219Sminshall struct winsize ws; 50737219Sminshall 50838689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 50938689Sborman *rows = ws.ws_row; 51038689Sborman *cols = ws.ws_col; 51138689Sborman return 1; 51237219Sminshall } 51338810Sborman #endif /* TIOCGWINSZ */ 51438689Sborman return 0; 51537219Sminshall } 51637219Sminshall 51737219Sminshall int 51835417Sminshall NetClose(fd) 51935417Sminshall int fd; 52032147Sminshall { 52135417Sminshall return close(fd); 52232147Sminshall } 52332147Sminshall 52432147Sminshall 52532147Sminshall void 52632553Sminshall NetNonblockingIO(fd, onoff) 52732147Sminshall int 52832147Sminshall fd, 52932147Sminshall onoff; 53032147Sminshall { 53132147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 53232147Sminshall } 53332147Sminshall 53434849Sminshall #if defined(TN3270) 53532147Sminshall void 53632553Sminshall NetSigIO(fd, onoff) 53732147Sminshall int 53832147Sminshall fd, 53932147Sminshall onoff; 54032147Sminshall { 54132147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 54232147Sminshall } 54332147Sminshall 54432147Sminshall void 54532553Sminshall NetSetPgrp(fd) 54632147Sminshall int fd; 54732147Sminshall { 54832147Sminshall int myPid; 54932147Sminshall 55032147Sminshall myPid = getpid(); 55136274Sminshall fcntl(fd, F_SETOWN, myPid); 55232147Sminshall } 55334849Sminshall #endif /*defined(TN3270)*/ 55432553Sminshall 55532553Sminshall /* 55632553Sminshall * Various signal handling routines. 55732553Sminshall */ 55832147Sminshall 55933286Sminshall static void 56032553Sminshall deadpeer() 56132553Sminshall { 56232553Sminshall setcommandmode(); 56332553Sminshall longjmp(peerdied, -1); 56432553Sminshall } 56532147Sminshall 56633286Sminshall static void 56732553Sminshall intr() 56832553Sminshall { 56932553Sminshall if (localchars) { 57032553Sminshall intp(); 57132553Sminshall return; 57232553Sminshall } 57332553Sminshall setcommandmode(); 57432553Sminshall longjmp(toplevel, -1); 57532553Sminshall } 57632553Sminshall 57733286Sminshall static void 57832553Sminshall intr2() 57932553Sminshall { 58032553Sminshall if (localchars) { 58138689Sborman #ifdef KLUDGELINEMODE 58238689Sborman if (kludgelinemode) 58338689Sborman sendbrk(); 58438689Sborman else 58538689Sborman #endif 58638689Sborman sendabort(); 58732553Sminshall return; 58832553Sminshall } 58932553Sminshall } 59032553Sminshall 59133286Sminshall static void 59237219Sminshall sendwin() 59337219Sminshall { 59437219Sminshall if (connected) { 59537219Sminshall sendnaws(); 59637219Sminshall } 59737219Sminshall } 59837219Sminshall 59937219Sminshall static void 60032553Sminshall doescape() 60132553Sminshall { 60238689Sborman command(0, 0, 0); 60332553Sminshall } 60432553Sminshall 60532553Sminshall void 60632531Sminshall sys_telnet_init() 60732531Sminshall { 60838689Sborman #ifndef CRAY 60934849Sminshall (void) signal(SIGINT, (int (*)())intr); 61034849Sminshall (void) signal(SIGQUIT, (int (*)())intr2); 61134849Sminshall (void) signal(SIGPIPE, (int (*)())deadpeer); 61238689Sborman #else 61338689Sborman (void) signal(SIGINT, (void (*)())intr); 61438689Sborman (void) signal(SIGQUIT, (void (*)())intr2); 61538689Sborman (void) signal(SIGPIPE, (void (*)())deadpeer); 61638689Sborman #endif 61738689Sborman #ifdef SIGWINCH 61837219Sminshall (void) signal(SIGWINCH, (int (*)())sendwin); 61938689Sborman #endif 62032553Sminshall 62138689Sborman setconnmode(0); 62232531Sminshall 62332531Sminshall NetNonblockingIO(net, 1); 62432531Sminshall 62532531Sminshall #if defined(TN3270) 62636242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 62732531Sminshall NetSigIO(net, 1); 62832531Sminshall NetSetPgrp(net); 62932531Sminshall } 63032531Sminshall #endif /* defined(TN3270) */ 63132531Sminshall 63232531Sminshall #if defined(SO_OOBINLINE) 63334849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 63434849Sminshall perror("SetSockOpt"); 63534849Sminshall } 63632531Sminshall #endif /* defined(SO_OOBINLINE) */ 63732531Sminshall } 63832531Sminshall 63932531Sminshall /* 64032531Sminshall * Process rings - 64132531Sminshall * 64232531Sminshall * This routine tries to fill up/empty our various rings. 64332531Sminshall * 64432531Sminshall * The parameter specifies whether this is a poll operation, 64532531Sminshall * or a block-until-something-happens operation. 64632531Sminshall * 64732531Sminshall * The return value is 1 if something happened, 0 if not. 64832531Sminshall */ 64932531Sminshall 65032531Sminshall int 65132531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 65232531Sminshall int poll; /* If 0, then block until something to do */ 65332531Sminshall { 65432531Sminshall register int c; 65532531Sminshall /* One wants to be a bit careful about setting returnValue 65632531Sminshall * to one, since a one implies we did some useful work, 65732531Sminshall * and therefore probably won't be called to block next 65832531Sminshall * time (TN3270 mode only). 65932531Sminshall */ 66032531Sminshall int returnValue = 0; 66132531Sminshall static struct timeval TimeValue = { 0 }; 66232531Sminshall 66332531Sminshall if (netout) { 66432531Sminshall FD_SET(net, &obits); 66532531Sminshall } 66632531Sminshall if (ttyout) { 66732531Sminshall FD_SET(tout, &obits); 66832531Sminshall } 66932531Sminshall #if defined(TN3270) 67032531Sminshall if (ttyin) { 67132531Sminshall FD_SET(tin, &ibits); 67232531Sminshall } 67332531Sminshall #else /* defined(TN3270) */ 67432531Sminshall if (ttyin) { 67532531Sminshall FD_SET(tin, &ibits); 67632531Sminshall } 67732531Sminshall #endif /* defined(TN3270) */ 67832531Sminshall #if defined(TN3270) 67932531Sminshall if (netin) { 68032531Sminshall FD_SET(net, &ibits); 68132531Sminshall } 68232531Sminshall # else /* !defined(TN3270) */ 68332531Sminshall if (netin) { 68432531Sminshall FD_SET(net, &ibits); 68532531Sminshall } 68632531Sminshall # endif /* !defined(TN3270) */ 68732531Sminshall if (netex) { 68832531Sminshall FD_SET(net, &xbits); 68932531Sminshall } 69032531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 69132531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 69232531Sminshall if (c == -1) { 69332531Sminshall /* 69432531Sminshall * we can get EINTR if we are in line mode, 69532531Sminshall * and the user does an escape (TSTP), or 69632531Sminshall * some other signal generator. 69732531Sminshall */ 69832531Sminshall if (errno == EINTR) { 69932531Sminshall return 0; 70032531Sminshall } 70132531Sminshall # if defined(TN3270) 70232531Sminshall /* 70332531Sminshall * we can get EBADF if we were in transparent 70432531Sminshall * mode, and the transcom process died. 70532531Sminshall */ 70632531Sminshall if (errno == EBADF) { 70732531Sminshall /* 70832531Sminshall * zero the bits (even though kernel does it) 70932531Sminshall * to make sure we are selecting on the right 71032531Sminshall * ones. 71132531Sminshall */ 71232531Sminshall FD_ZERO(&ibits); 71332531Sminshall FD_ZERO(&obits); 71432531Sminshall FD_ZERO(&xbits); 71532531Sminshall return 0; 71632531Sminshall } 71732531Sminshall # endif /* defined(TN3270) */ 71832531Sminshall /* I don't like this, does it ever happen? */ 71932531Sminshall printf("sleep(5) from telnet, after select\r\n"); 72032531Sminshall sleep(5); 72132531Sminshall } 72232531Sminshall return 0; 72332531Sminshall } 72432531Sminshall 72532531Sminshall /* 72632531Sminshall * Any urgent data? 72732531Sminshall */ 72832531Sminshall if (FD_ISSET(net, &xbits)) { 72932531Sminshall FD_CLR(net, &xbits); 73032531Sminshall SYNCHing = 1; 73132531Sminshall ttyflush(1); /* flush already enqueued data */ 73232531Sminshall } 73332531Sminshall 73432531Sminshall /* 73532531Sminshall * Something to read from the network... 73632531Sminshall */ 73732531Sminshall if (FD_ISSET(net, &ibits)) { 73832531Sminshall int canread; 73932531Sminshall 74032531Sminshall FD_CLR(net, &ibits); 74132531Sminshall canread = ring_empty_consecutive(&netiring); 74232531Sminshall #if !defined(SO_OOBINLINE) 74332531Sminshall /* 74432531Sminshall * In 4.2 (and some early 4.3) systems, the 74532531Sminshall * OOB indication and data handling in the kernel 74632531Sminshall * is such that if two separate TCP Urgent requests 74732531Sminshall * come in, one byte of TCP data will be overlaid. 74832531Sminshall * This is fatal for Telnet, but we try to live 74932531Sminshall * with it. 75032531Sminshall * 75132531Sminshall * In addition, in 4.2 (and...), a special protocol 75232531Sminshall * is needed to pick up the TCP Urgent data in 75332531Sminshall * the correct sequence. 75432531Sminshall * 75532531Sminshall * What we do is: if we think we are in urgent 75632531Sminshall * mode, we look to see if we are "at the mark". 75732531Sminshall * If we are, we do an OOB receive. If we run 75832531Sminshall * this twice, we will do the OOB receive twice, 75932531Sminshall * but the second will fail, since the second 76032531Sminshall * time we were "at the mark", but there wasn't 76132531Sminshall * any data there (the kernel doesn't reset 76232531Sminshall * "at the mark" until we do a normal read). 76332531Sminshall * Once we've read the OOB data, we go ahead 76432531Sminshall * and do normal reads. 76532531Sminshall * 76632531Sminshall * There is also another problem, which is that 76732531Sminshall * since the OOB byte we read doesn't put us 76832531Sminshall * out of OOB state, and since that byte is most 76932531Sminshall * likely the TELNET DM (data mark), we would 77032531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 77132531Sminshall * So, clocks to the rescue. If we've "just" 77232531Sminshall * received a DM, then we test for the 77332531Sminshall * presence of OOB data when the receive OOB 77432531Sminshall * fails (and AFTER we did the normal mode read 77532531Sminshall * to clear "at the mark"). 77632531Sminshall */ 77732531Sminshall if (SYNCHing) { 77832531Sminshall int atmark; 77932531Sminshall 78032531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 78132531Sminshall if (atmark) { 78232531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 78332531Sminshall if ((c == -1) && (errno == EINVAL)) { 78432531Sminshall c = recv(net, netiring.supply, canread, 0); 78532531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 78632531Sminshall SYNCHing = stilloob(net); 78732531Sminshall } 78832531Sminshall } 78932531Sminshall } else { 79032531Sminshall c = recv(net, netiring.supply, canread, 0); 79132531Sminshall } 79232531Sminshall } else { 79332531Sminshall c = recv(net, netiring.supply, canread, 0); 79432531Sminshall } 79532531Sminshall settimer(didnetreceive); 79632531Sminshall #else /* !defined(SO_OOBINLINE) */ 79732531Sminshall c = recv(net, netiring.supply, canread, 0); 79832531Sminshall #endif /* !defined(SO_OOBINLINE) */ 79932531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 80032531Sminshall c = 0; 80132531Sminshall } else if (c <= 0) { 80232531Sminshall return -1; 80332531Sminshall } 80432531Sminshall if (netdata) { 80532531Sminshall Dump('<', netiring.supply, c); 80632531Sminshall } 80732667Sminshall if (c) 80832667Sminshall ring_supplied(&netiring, c); 80932531Sminshall returnValue = 1; 81032531Sminshall } 81132531Sminshall 81232531Sminshall /* 81332531Sminshall * Something to read from the tty... 81432531Sminshall */ 81532531Sminshall if (FD_ISSET(tin, &ibits)) { 81632531Sminshall FD_CLR(tin, &ibits); 81733286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 81832531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 81932531Sminshall c = 0; 82032531Sminshall } else { 82132531Sminshall /* EOF detection for line mode!!!! */ 82233281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 82332531Sminshall /* must be an EOF... */ 82432531Sminshall *ttyiring.supply = termEofChar; 82532531Sminshall c = 1; 82632531Sminshall } 82732531Sminshall if (c <= 0) { 82832531Sminshall return -1; 82932531Sminshall } 83038208Sminshall if (termdata) { 83138208Sminshall Dump('<', ttyiring.supply, c); 83238208Sminshall } 83332667Sminshall ring_supplied(&ttyiring, c); 83432531Sminshall } 83532531Sminshall returnValue = 1; /* did something useful */ 83632531Sminshall } 83732531Sminshall 83832531Sminshall if (FD_ISSET(net, &obits)) { 83932531Sminshall FD_CLR(net, &obits); 84032531Sminshall returnValue |= netflush(); 84132531Sminshall } 84232531Sminshall if (FD_ISSET(tout, &obits)) { 84332531Sminshall FD_CLR(tout, &obits); 84438689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0); 84532531Sminshall } 84632531Sminshall 84732531Sminshall return returnValue; 84832531Sminshall } 84932531Sminshall #endif /* defined(unix) */ 850