home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / telnet / sys_bsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  24.4 KB  |  1,152 lines

  1. /*
  2.  * Copyright (c) 1988, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)sys_bsd.c    5.2 (Berkeley) 3/1/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * The following routines try to encapsulate what is system dependent
  40.  * (at least between 4.x and dos) which is used in telnet.c.
  41.  */
  42.  
  43.  
  44. #include <fcntl.h>
  45. #include <sys/types.h>
  46. #include <sys/time.h>
  47. #include <sys/socket.h>
  48. #include <signal.h>
  49. #include <errno.h>
  50. #include <arpa/telnet.h>
  51.  
  52. #include "ring.h"
  53.  
  54. #include "fdset.h"
  55.  
  56. #include "defines.h"
  57. #include "externs.h"
  58. #include "types.h"
  59.  
  60. #if    defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
  61. #define    SIG_FUNC_RET    void
  62. #else
  63. #define    SIG_FUNC_RET    int
  64. #endif
  65.  
  66. int
  67.     tout,            /* Output file descriptor */
  68.     tin,            /* Input file descriptor */
  69.     net;
  70.  
  71. #ifndef    USE_TERMIO
  72. struct    tchars otc = { 0 }, ntc = { 0 };
  73. struct    ltchars oltc = { 0 }, nltc = { 0 };
  74. struct    sgttyb ottyb = { 0 }, nttyb = { 0 };
  75. int    olmode = 0;
  76. # define cfgetispeed(ptr)    (ptr)->sg_ispeed
  77. # define cfgetospeed(ptr)    (ptr)->sg_ospeed
  78. # define old_tc ottyb
  79.  
  80. #else    /* USE_TERMIO */
  81. struct    termio old_tc = { 0 };
  82. extern struct termio new_tc;
  83.  
  84. # ifndef    TCSANOW
  85. #  ifdef TCSETS
  86. #   define    TCSANOW        TCSETS
  87. #   define    TCSADRAIN    TCSETSW
  88. #   define    tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
  89. #  else
  90. #   ifdef TCSETA
  91. #    define    TCSANOW        TCSETA
  92. #    define    TCSADRAIN    TCSETAW
  93. #    define    tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
  94. #   else
  95. #    define    TCSANOW        TIOCSETA
  96. #    define    TCSADRAIN    TIOCSETAW
  97. #    define    tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
  98. #   endif
  99. #  endif
  100. #  define    tcsetattr(f, a, t) ioctl(f, a, (char *)t)
  101. #  define    cfgetospeed(ptr)    ((ptr)->c_cflag&CBAUD)
  102. #  ifdef CIBAUD
  103. #   define    cfgetispeed(ptr)    (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
  104. #  else
  105. #   define    cfgetispeed(ptr)    cfgetospeed(ptr)
  106. #  endif
  107. # endif /* TCSANOW */
  108. #endif    /* USE_TERMIO */
  109.  
  110. static fd_set ibits, obits, xbits;
  111.  
  112.  
  113.     void
  114. init_sys()
  115. {
  116.     tout = fileno(stdout);
  117.     tin = fileno(stdin);
  118.     FD_ZERO(&ibits);
  119.     FD_ZERO(&obits);
  120.     FD_ZERO(&xbits);
  121.  
  122.     errno = 0;
  123. }
  124.  
  125.  
  126.     int
  127. TerminalWrite(buf, n)
  128.     char *buf;
  129.     int  n;
  130. {
  131.     return write(tout, buf, n);
  132. }
  133.  
  134.     int
  135. TerminalRead(buf, n)
  136.     char *buf;
  137.     int  n;
  138. {
  139.     return read(tin, buf, n);
  140. }
  141.  
  142. /*
  143.  *
  144.  */
  145.  
  146.     int
  147. TerminalAutoFlush()
  148. {
  149. #if    defined(LNOFLSH)
  150.     int flush;
  151.  
  152.     ioctl(0, TIOCLGET, (char *)&flush);
  153.     return !(flush&LNOFLSH);    /* if LNOFLSH, no autoflush */
  154. #else    /* LNOFLSH */
  155.     return 1;
  156. #endif    /* LNOFLSH */
  157. }
  158.  
  159. #ifdef    KLUDGELINEMODE
  160. extern int kludgelinemode;
  161. #endif
  162. /*
  163.  * TerminalSpecialChars()
  164.  *
  165.  * Look at an input character to see if it is a special character
  166.  * and decide what to do.
  167.  *
  168.  * Output:
  169.  *
  170.  *    0    Don't add this character.
  171.  *    1    Do add this character
  172.  */
  173.  
  174.     int
  175. TerminalSpecialChars(c)
  176.     int    c;
  177. {
  178.     void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
  179.  
  180.     if (c == termIntChar) {
  181.     intp();
  182.     return 0;
  183.     } else if (c == termQuitChar) {
  184. #ifdef    KLUDGELINEMODE
  185.     if (kludgelinemode)
  186.         sendbrk();
  187.     else
  188. #endif
  189.         sendabort();
  190.     return 0;
  191.     } else if (c == termEofChar) {
  192.     if (my_want_state_is_will(TELOPT_LINEMODE)) {
  193.         sendeof();
  194.         return 0;
  195.     }
  196.     return 1;
  197.     } else if (c == termSuspChar) {
  198.     sendsusp();
  199.     return(0);
  200.     } else if (c == termFlushChar) {
  201.     xmitAO();        /* Transmit Abort Output */
  202.     return 0;
  203.     } else if (!MODE_LOCAL_CHARS(globalmode)) {
  204.     if (c == termKillChar) {
  205.         xmitEL();
  206.         return 0;
  207.     } else if (c == termEraseChar) {
  208.         xmitEC();        /* Transmit Erase Character */
  209.         return 0;
  210.     }
  211.     }
  212.     return 1;
  213. }
  214.  
  215.  
  216. /*
  217.  * Flush output to the terminal
  218.  */
  219.  
  220.     void
  221. TerminalFlushOutput()
  222. {
  223. #ifdef    TIOCFLUSH
  224.     (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
  225. #else
  226.     (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
  227. #endif
  228. }
  229.  
  230.     void
  231. TerminalSaveState()
  232. {
  233. #ifndef    USE_TERMIO
  234.     ioctl(0, TIOCGETP, (char *)&ottyb);
  235.     ioctl(0, TIOCGETC, (char *)&otc);
  236.     ioctl(0, TIOCGLTC, (char *)&oltc);
  237.     ioctl(0, TIOCLGET, (char *)&olmode);
  238.  
  239.     ntc = otc;
  240.     nltc = oltc;
  241.     nttyb = ottyb;
  242.  
  243. #else    /* USE_TERMIO */
  244.     tcgetattr(0, &old_tc);
  245.  
  246.     new_tc = old_tc;
  247.  
  248. #ifndef    VDISCARD
  249.     termFlushChar = CONTROL('O');
  250. #endif
  251. #ifndef    VWERASE
  252.     termWerasChar = CONTROL('W');
  253. #endif
  254. #ifndef    VREPRINT
  255.     termRprntChar = CONTROL('R');
  256. #endif
  257. #ifndef    VLNEXT
  258.     termLiteralNextChar = CONTROL('V');
  259. #endif
  260. #ifndef    VSTART
  261.     termStartChar = CONTROL('Q');
  262. #endif
  263. #ifndef    VSTOP
  264.     termStopChar = CONTROL('S');
  265. #endif
  266. #ifndef    VSTATUS
  267.     termAytChar = CONTROL('T');
  268. #endif
  269. #endif    /* USE_TERMIO */
  270. }
  271.  
  272.     cc_t *
  273. tcval(func)
  274.     register int func;
  275. {
  276.     switch(func) {
  277.     case SLC_IP:    return(&termIntChar);
  278.     case SLC_ABORT:    return(&termQuitChar);
  279.     case SLC_EOF:    return(&termEofChar);
  280.     case SLC_EC:    return(&termEraseChar);
  281.     case SLC_EL:    return(&termKillChar);
  282.     case SLC_XON:    return(&termStartChar);
  283.     case SLC_XOFF:    return(&termStopChar);
  284.     case SLC_FORW1:    return(&termForw1Char);
  285. #ifdef    USE_TERMIO
  286.     case SLC_FORW2:    return(&termForw2Char);
  287. # ifdef    VDISCARD
  288.     case SLC_AO:    return(&termFlushChar);
  289. # endif
  290. # ifdef    VSUSP
  291.     case SLC_SUSP:    return(&termSuspChar);
  292. # endif
  293. # ifdef    VWERASE
  294.     case SLC_EW:    return(&termWerasChar);
  295. # endif
  296. # ifdef    VREPRINT
  297.     case SLC_RP:    return(&termRprntChar);
  298. # endif
  299. # ifdef    VLNEXT
  300.     case SLC_LNEXT:    return(&termLiteralNextChar);
  301. # endif
  302. # ifdef    VSTATUS
  303.     case SLC_AYT:    return(&termAytChar);
  304. # endif
  305. #endif
  306.  
  307.     case SLC_SYNCH:
  308.     case SLC_BRK:
  309.     case SLC_EOR:
  310.     default:
  311.     return((cc_t *)0);
  312.     }
  313. }
  314.  
  315.     void
  316. TerminalDefaultChars()
  317. {
  318. #ifndef    USE_TERMIO
  319.     ntc = otc;
  320.     nltc = oltc;
  321.     nttyb.sg_kill = ottyb.sg_kill;
  322.     nttyb.sg_erase = ottyb.sg_erase;
  323. #else    /* USE_TERMIO */
  324.     memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
  325. # ifndef    VDISCARD
  326.     termFlushChar = CONTROL('O');
  327. # endif
  328. # ifndef    VWERASE
  329.     termWerasChar = CONTROL('W');
  330. # endif
  331. # ifndef    VREPRINT
  332.     termRprntChar = CONTROL('R');
  333. # endif
  334. # ifndef    VLNEXT
  335.     termLiteralNextChar = CONTROL('V');
  336. # endif
  337. # ifndef    VSTART
  338.     termStartChar = CONTROL('Q');
  339. # endif
  340. # ifndef    VSTOP
  341.     termStopChar = CONTROL('S');
  342. # endif
  343. # ifndef    VSTATUS
  344.     termAytChar = CONTROL('T');
  345. # endif
  346. #endif    /* USE_TERMIO */
  347. }
  348.  
  349. #ifdef notdef
  350. void
  351. TerminalRestoreState()
  352. {
  353. }
  354. #endif
  355.  
  356. /*
  357.  * TerminalNewMode - set up terminal to a specific mode.
  358.  *    MODE_ECHO: do local terminal echo
  359.  *    MODE_FLOW: do local flow control
  360.  *    MODE_TRAPSIG: do local mapping to TELNET IAC sequences
  361.  *    MODE_EDIT: do local line editing
  362.  *
  363.  *    Command mode:
  364.  *        MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
  365.  *        local echo
  366.  *        local editing
  367.  *        local xon/xoff
  368.  *        local signal mapping
  369.  *
  370.  *    Linemode:
  371.  *        local/no editing
  372.  *    Both Linemode and Single Character mode:
  373.  *        local/remote echo
  374.  *        local/no xon/xoff
  375.  *        local/no signal mapping
  376.  */
  377.  
  378.  
  379.     void
  380. TerminalNewMode(f)
  381.     register int f;
  382. {
  383.     static int prevmode = 0;
  384. #ifndef    USE_TERMIO
  385.     struct tchars tc;
  386.     struct ltchars ltc;
  387.     struct sgttyb sb;
  388.     int lmode;
  389. #else    /* USE_TERMIO */
  390.     struct termio tmp_tc;
  391. #endif    /* USE_TERMIO */
  392.     int onoff;
  393.     int old;
  394.     cc_t esc;
  395.  
  396.     globalmode = f&~MODE_FORCE;
  397.     if (prevmode == f)
  398.     return;
  399.  
  400.     /*
  401.      * Write any outstanding data before switching modes
  402.      * ttyflush() returns 0 only when there is no more data
  403.      * left to write out, it returns -1 if it couldn't do
  404.      * anything at all, otherwise it returns 1 + the number
  405.      * of characters left to write.
  406. #ifndef    USE_TERMIO
  407.      * We would really like ask the kernel to wait for the output
  408.      * to drain, like we can do with the TCSADRAIN, but we don't have
  409.      * that option.  The only ioctl that waits for the output to
  410.      * drain, TIOCSETP, also flushes the input queue, which is NOT
  411.      * what we want (TIOCSETP is like TCSADFLUSH).
  412. #endif
  413.      */
  414.     old = ttyflush(SYNCHing|flushout);
  415.     if (old < 0 || old > 1) {
  416. #ifdef    USE_TERMIO
  417.     tcgetattr(tin, &tmp_tc);
  418. #endif    /* USE_TERMIO */
  419.     do {
  420.         /*
  421.          * Wait for data to drain, then flush again.
  422.          */
  423. #ifdef    USE_TERMIO
  424.         tcsetattr(tin, TCSADRAIN, &tmp_tc);
  425. #endif    /* USE_TERMIO */
  426.         old = ttyflush(SYNCHing|flushout);
  427.     } while (old < 0 || old > 1);
  428.     }
  429.  
  430.     old = prevmode;
  431.     prevmode = f&~MODE_FORCE;
  432. #ifndef    USE_TERMIO
  433.     sb = nttyb;
  434.     tc = ntc;
  435.     ltc = nltc;
  436.     lmode = olmode;
  437. #else
  438.     tmp_tc = new_tc;
  439. #endif
  440.  
  441.     if (f&MODE_ECHO) {
  442. #ifndef    USE_TERMIO
  443.     sb.sg_flags |= ECHO;
  444. #else
  445.     tmp_tc.c_lflag |= ECHO;
  446.     tmp_tc.c_oflag |= ONLCR;
  447.     if (crlf)
  448.         tmp_tc.c_iflag |= ICRNL;
  449. #endif
  450.     } else {
  451. #ifndef    USE_TERMIO
  452.     sb.sg_flags &= ~ECHO;
  453. #else
  454.     tmp_tc.c_lflag &= ~ECHO;
  455.     tmp_tc.c_oflag &= ~ONLCR;
  456. # ifdef notdef
  457.     if (crlf)
  458.         tmp_tc.c_iflag &= ~ICRNL;
  459. # endif
  460. #endif
  461.     }
  462.  
  463.     if ((f&MODE_FLOW) == 0) {
  464. #ifndef    USE_TERMIO
  465.     tc.t_startc = _POSIX_VDISABLE;
  466.     tc.t_stopc = _POSIX_VDISABLE;
  467. #else
  468.     tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON);
  469.     } else {
  470.     tmp_tc.c_iflag |= IXANY|IXOFF|IXON;
  471. #endif
  472.     }
  473.  
  474.     if ((f&MODE_TRAPSIG) == 0) {
  475. #ifndef    USE_TERMIO
  476.     tc.t_intrc = _POSIX_VDISABLE;
  477.     tc.t_quitc = _POSIX_VDISABLE;
  478.     tc.t_eofc = _POSIX_VDISABLE;
  479.     ltc.t_suspc = _POSIX_VDISABLE;
  480.     ltc.t_dsuspc = _POSIX_VDISABLE;
  481. #else
  482.     tmp_tc.c_lflag &= ~ISIG;
  483. #endif
  484.     localchars = 0;
  485.     } else {
  486. #ifdef    USE_TERMIO
  487.     tmp_tc.c_lflag |= ISIG;
  488. #endif
  489.     localchars = 1;
  490.     }
  491.  
  492.     if (f&MODE_EDIT) {
  493. #ifndef    USE_TERMIO
  494.     sb.sg_flags &= ~CBREAK;
  495.     sb.sg_flags |= CRMOD;
  496. #else
  497.     tmp_tc.c_lflag |= ICANON;
  498. #endif
  499.     } else {
  500. #ifndef    USE_TERMIO
  501.     sb.sg_flags |= CBREAK;
  502.     if (f&MODE_ECHO)
  503.         sb.sg_flags |= CRMOD;
  504.     else
  505.         sb.sg_flags &= ~CRMOD;
  506. #else
  507.     tmp_tc.c_lflag &= ~ICANON;
  508.     tmp_tc.c_iflag &= ~ICRNL;
  509.     tmp_tc.c_cc[VMIN] = 1;
  510.     tmp_tc.c_cc[VTIME] = 0;
  511. #endif
  512.     }
  513.  
  514.     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
  515. #ifndef    USE_TERMIO
  516.     ltc.t_lnextc = _POSIX_VDISABLE;
  517. #else
  518. # ifdef VLNEXT
  519.     tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
  520. # endif
  521. #endif
  522.     }
  523.  
  524.     if (f&MODE_SOFT_TAB) {
  525. #ifndef USE_TERMIO
  526.     sb.sg_flags |= XTABS;
  527. #else
  528. # ifdef    OXTABS
  529.     tmp_tc.c_oflag |= OXTABS;
  530. # endif
  531. # ifdef    TABDLY
  532.     tmp_tc.c_oflag &= ~TABDLY;
  533.     tmp_tc.c_oflag |= TAB3;
  534. # endif
  535. #endif
  536.     } else {
  537. #ifndef USE_TERMIO
  538.     sb.sg_flags &= ~XTABS;
  539. #else
  540. # ifdef    OXTABS
  541.     tmp_tc.c_oflag &= ~OXTABS;
  542. # endif
  543. # ifdef    TABDLY
  544.     tmp_tc.c_oflag &= ~TABDLY;
  545. # endif
  546. #endif
  547.     }
  548.  
  549.     if (f&MODE_LIT_ECHO) {
  550. #ifndef USE_TERMIO
  551.     lmode &= ~LCTLECH;
  552. #else
  553. # ifdef    ECHOCTL
  554.     tmp_tc.c_lflag &= ~ECHOCTL;
  555. # endif
  556. #endif
  557.     } else {
  558. #ifndef USE_TERMIO
  559.     lmode |= LCTLECH;
  560. #else
  561. # ifdef    ECHOCTL
  562.     tmp_tc.c_lflag |= ECHOCTL;
  563. # endif
  564. #endif
  565.     }
  566.  
  567.     if (f == -1) {
  568.     onoff = 0;
  569.     } else {
  570. #ifndef    USE_TERMIO
  571.     if (f & MODE_OUTBIN)
  572.         lmode |= LLITOUT;
  573.     else
  574.         lmode &= ~LLITOUT;
  575.  
  576.     if (f & MODE_INBIN)
  577.         lmode |= LPASS8;
  578.     else
  579.         lmode &= ~LPASS8;
  580. #else
  581.     if (f & MODE_INBIN)
  582.         tmp_tc.c_iflag &= ~ISTRIP;
  583.     else
  584.         tmp_tc.c_iflag |= ISTRIP;
  585.     if (f & MODE_OUTBIN) {
  586.         tmp_tc.c_cflag &= ~(CSIZE|PARENB);
  587.         tmp_tc.c_cflag |= CS8;
  588.         tmp_tc.c_oflag &= ~OPOST;
  589.     } else {
  590.         tmp_tc.c_cflag &= ~(CSIZE|PARENB);
  591.         tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
  592.         tmp_tc.c_oflag |= OPOST;
  593.     }
  594. #endif
  595.     onoff = 1;
  596.     }
  597.  
  598.     if (f != -1) {
  599. #ifdef    SIGTSTP
  600.     static SIG_FUNC_RET susp();
  601. #endif    /* SIGTSTP */
  602. #ifdef    SIGINFO
  603.     static SIG_FUNC_RET ayt();
  604. #endif    SIGINFO
  605.  
  606. #ifdef    SIGTSTP
  607.     (void) signal(SIGTSTP, susp);
  608. #endif    /* SIGTSTP */
  609. #ifdef    SIGINFO
  610.     (void) signal(SIGINFO, ayt);
  611. #endif    SIGINFO
  612. #if    defined(USE_TERMIO) && defined(NOKERNINFO)
  613.     tmp_tc.c_lflag |= NOKERNINFO;
  614. #endif
  615.     /*
  616.      * We don't want to process ^Y here.  It's just another
  617.      * character that we'll pass on to the back end.  It has
  618.      * to process it because it will be processed when the
  619.      * user attempts to read it, not when we send it.
  620.      */
  621. #ifndef    USE_TERMIO
  622.     ltc.t_dsuspc = _POSIX_VDISABLE;
  623. #else
  624. # ifdef    VDSUSP
  625.     tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
  626. # endif
  627. #endif
  628. #ifdef    USE_TERMIO
  629.     /*
  630.      * If the VEOL character is already set, then use VEOL2,
  631.      * otherwise use VEOL.
  632.      */
  633.     esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
  634.     if ((tmp_tc.c_cc[VEOL] != esc)
  635. # ifdef    VEOL2
  636.         && (tmp_tc.c_cc[VEOL2] != esc)
  637. # endif
  638.         ) {
  639.         if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
  640.             tmp_tc.c_cc[VEOL] = esc;
  641. # ifdef    VEOL2
  642.         else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
  643.             tmp_tc.c_cc[VEOL2] = esc;
  644. # endif
  645.     }
  646. #else
  647.     if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
  648.         tc.t_brkc = esc;
  649. #endif
  650.     } else {
  651. #ifdef    SIGINFO
  652.     SIG_FUNC_RET ayt_status();
  653.  
  654.     (void) signal(SIGINFO, ayt_status);
  655. #endif    SIGINFO
  656. #ifdef    SIGTSTP
  657.     (void) signal(SIGTSTP, SIG_DFL);
  658.     (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
  659. #endif    /* SIGTSTP */
  660. #ifndef USE_TERMIO
  661.     ltc = oltc;
  662.     tc = otc;
  663.     sb = ottyb;
  664.     lmode = olmode;
  665. #else
  666.     tmp_tc = old_tc;
  667. #endif
  668.     }
  669. #ifndef USE_TERMIO
  670.     ioctl(tin, TIOCLSET, (char *)&lmode);
  671.     ioctl(tin, TIOCSLTC, (char *)<c);
  672.     ioctl(tin, TIOCSETC, (char *)&tc);
  673.     ioctl(tin, TIOCSETN, (char *)&sb);
  674. #else
  675.     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
  676.     tcsetattr(tin, TCSANOW, &tmp_tc);
  677. #endif
  678.  
  679. #if    (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
  680.     ioctl(tin, FIONBIO, (char *)&onoff);
  681.     ioctl(tout, FIONBIO, (char *)&onoff);
  682. #endif    /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
  683. #if    defined(TN3270)
  684.     if (noasynchtty == 0) {
  685.     ioctl(tin, FIOASYNC, (char *)&onoff);
  686.     }
  687. #endif    /* defined(TN3270) */
  688.  
  689. }
  690.  
  691. #ifndef    B19200
  692. # define B19200 B9600
  693. #endif
  694.  
  695. #ifndef    B38400
  696. # define B38400 B19200
  697. #endif
  698.  
  699. /*
  700.  * This code assumes that the values B0, B50, B75...
  701.  * are in ascending order.  They do not have to be
  702.  * contiguous.
  703.  */
  704. struct termspeeds {
  705.     long speed;
  706.     long value;
  707. } termspeeds[] = {
  708.     { 0,     B0 },     { 50,    B50 },   { 75,    B75 },
  709.     { 110,   B110 },   { 134,   B134 },  { 150,   B150 },
  710.     { 200,   B200 },   { 300,   B300 },  { 600,   B600 },
  711.     { 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },
  712.     { 4800,  B4800 },  { 9600,  B9600 }, { 19200, B19200 },
  713.     { 38400, B38400 }, { -1,    B38400 }
  714. };
  715.  
  716.     void
  717. TerminalSpeeds(ispeed, ospeed)
  718.     long *ispeed;
  719.     long *ospeed;
  720. {
  721.     register struct termspeeds *tp;
  722.     register long in, out;
  723.  
  724.     out = cfgetospeed(&old_tc);
  725.     in = cfgetispeed(&old_tc);
  726.     if (in == 0)
  727.     in = out;
  728.  
  729.     tp = termspeeds;
  730.     while ((tp->speed != -1) && (tp->value < in))
  731.     tp++;
  732.     *ispeed = tp->speed;
  733.  
  734.     tp = termspeeds;
  735.     while ((tp->speed != -1) && (tp->value < out))
  736.     tp++;
  737.     *ospeed = tp->speed;
  738. }
  739.  
  740.     int
  741. TerminalWindowSize(rows, cols)
  742.     long *rows, *cols;
  743. {
  744. #ifdef    TIOCGWINSZ
  745.     struct winsize ws;
  746.  
  747.     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
  748.     *rows = ws.ws_row;
  749.     *cols = ws.ws_col;
  750.     return 1;
  751.     }
  752. #endif    /* TIOCGWINSZ */
  753.     return 0;
  754. }
  755.  
  756.     int
  757. NetClose(fd)
  758.     int    fd;
  759. {
  760.     return close(fd);
  761. }
  762.  
  763.  
  764.     void
  765. NetNonblockingIO(fd, onoff)
  766.     int fd;
  767.     int onoff;
  768. {
  769.     ioctl(fd, FIONBIO, (char *)&onoff);
  770. }
  771.  
  772. #if    defined(TN3270)
  773.     void
  774. NetSigIO(fd, onoff)
  775.     int fd;
  776.     int onoff;
  777. {
  778.     ioctl(fd, FIOASYNC, (char *)&onoff);    /* hear about input */
  779. }
  780.  
  781.     void
  782. NetSetPgrp(fd)
  783.     int fd;
  784. {
  785.     int myPid;
  786.  
  787.     myPid = getpid();
  788.     fcntl(fd, F_SETOWN, myPid);
  789. }
  790. #endif    /*defined(TN3270)*/
  791.  
  792. /*
  793.  * Various signal handling routines.
  794.  */
  795.  
  796.     /* ARGSUSED */
  797.     static SIG_FUNC_RET
  798. deadpeer(sig)
  799.     int sig;
  800. {
  801.     setcommandmode();
  802.     longjmp(peerdied, -1);
  803. }
  804.  
  805.     /* ARGSUSED */
  806.     static SIG_FUNC_RET
  807. intr(sig)
  808.     int sig;
  809. {
  810.     if (localchars) {
  811.     intp();
  812.     return;
  813.     }
  814.     setcommandmode();
  815.     longjmp(toplevel, -1);
  816. }
  817.  
  818.     /* ARGSUSED */
  819.     static SIG_FUNC_RET
  820. intr2(sig)
  821.     int sig;
  822. {
  823.     if (localchars) {
  824. #ifdef    KLUDGELINEMODE
  825.     if (kludgelinemode)
  826.         sendbrk();
  827.     else
  828. #endif
  829.         sendabort();
  830.     return;
  831.     }
  832. }
  833.  
  834. #ifdef    SIGTSTP
  835.     /* ARGSUSED */
  836.     static SIG_FUNC_RET
  837. susp(sig)
  838.     int sig;
  839. {
  840.     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
  841.     return;
  842.     if (localchars)
  843.     sendsusp();
  844. }
  845. #endif
  846.  
  847. #ifdef    SIGWINCH
  848.     /* ARGSUSED */
  849.     static SIG_FUNC_RET
  850. sendwin(sig)
  851.     int sig;
  852. {
  853.     if (connected) {
  854.     sendnaws();
  855.     }
  856. }
  857. #endif
  858.  
  859. #ifdef    SIGINFO
  860.     /* ARGSUSED */
  861.     static SIG_FUNC_RET
  862. ayt(sig)
  863.     int sig;
  864. {
  865.     if (connected)
  866.     sendayt();
  867.     else
  868.     ayt_status();
  869. }
  870. #endif
  871.  
  872.  
  873.     void
  874. sys_telnet_init()
  875. {
  876.     (void) signal(SIGINT, intr);
  877.     (void) signal(SIGQUIT, intr2);
  878.     (void) signal(SIGPIPE, deadpeer);
  879. #ifdef    SIGWINCH
  880.     (void) signal(SIGWINCH, sendwin);
  881. #endif
  882. #ifdef    SIGTSTP
  883.     (void) signal(SIGTSTP, susp);
  884. #endif
  885. #ifdef    SIGINFO
  886.     (void) signal(SIGINFO, ayt);
  887. #endif
  888.  
  889.     setconnmode(0);
  890.  
  891.     NetNonblockingIO(net, 1);
  892.  
  893. #if    defined(TN3270)
  894.     if (noasynchnet == 0) {            /* DBX can't handle! */
  895.     NetSigIO(net, 1);
  896.     NetSetPgrp(net);
  897.     }
  898. #endif    /* defined(TN3270) */
  899.  
  900. #if    defined(SO_OOBINLINE)
  901.     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
  902.     perror("SetSockOpt");
  903.     }
  904. #endif    /* defined(SO_OOBINLINE) */
  905. }
  906.  
  907. /*
  908.  * Process rings -
  909.  *
  910.  *    This routine tries to fill up/empty our various rings.
  911.  *
  912.  *    The parameter specifies whether this is a poll operation,
  913.  *    or a block-until-something-happens operation.
  914.  *
  915.  *    The return value is 1 if something happened, 0 if not.
  916.  */
  917.  
  918.     int
  919. process_rings(netin, netout, netex, ttyin, ttyout, poll)
  920.     int poll;        /* If 0, then block until something to do */
  921. {
  922.     register int c;
  923.         /* One wants to be a bit careful about setting returnValue
  924.          * to one, since a one implies we did some useful work,
  925.          * and therefore probably won't be called to block next
  926.          * time (TN3270 mode only).
  927.          */
  928.     int returnValue = 0;
  929.     static struct timeval TimeValue = { 0 };
  930.  
  931.     if (netout) {
  932.     FD_SET(net, &obits);
  933.     } 
  934.     if (ttyout) {
  935.     FD_SET(tout, &obits);
  936.     }
  937. #if    defined(TN3270)
  938.     if (ttyin) {
  939.     FD_SET(tin, &ibits);
  940.     }
  941. #else    /* defined(TN3270) */
  942.     if (ttyin) {
  943.     FD_SET(tin, &ibits);
  944.     }
  945. #endif    /* defined(TN3270) */
  946. #if    defined(TN3270)
  947.     if (netin) {
  948.     FD_SET(net, &ibits);
  949.     }
  950. #   else /* !defined(TN3270) */
  951.     if (netin) {
  952.     FD_SET(net, &ibits);
  953.     }
  954. #   endif /* !defined(TN3270) */
  955.     if (netex) {
  956.     FD_SET(net, &xbits);
  957.     }
  958.     if ((c = select(16, &ibits, &obits, &xbits,
  959.             (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
  960.     if (c == -1) {
  961.             /*
  962.              * we can get EINTR if we are in line mode,
  963.              * and the user does an escape (TSTP), or
  964.              * some other signal generator.
  965.              */
  966.         if (errno == EINTR) {
  967.         return 0;
  968.         }
  969. #        if defined(TN3270)
  970.             /*
  971.              * we can get EBADF if we were in transparent
  972.              * mode, and the transcom process died.
  973.             */
  974.         if (errno == EBADF) {
  975.             /*
  976.              * zero the bits (even though kernel does it)
  977.              * to make sure we are selecting on the right
  978.              * ones.
  979.             */
  980.         FD_ZERO(&ibits);
  981.         FD_ZERO(&obits);
  982.         FD_ZERO(&xbits);
  983.         return 0;
  984.         }
  985. #        endif /* defined(TN3270) */
  986.             /* I don't like this, does it ever happen? */
  987.         printf("sleep(5) from telnet, after select\r\n");
  988.         sleep(5);
  989.     }
  990.     return 0;
  991.     }
  992.  
  993.     /*
  994.      * Any urgent data?
  995.      */
  996.     if (FD_ISSET(net, &xbits)) {
  997.     FD_CLR(net, &xbits);
  998.     SYNCHing = 1;
  999.     (void) ttyflush(1);    /* flush already enqueued data */
  1000.     }
  1001.  
  1002.     /*
  1003.      * Something to read from the network...
  1004.      */
  1005.     if (FD_ISSET(net, &ibits)) {
  1006.     int canread;
  1007.  
  1008.     FD_CLR(net, &ibits);
  1009.     canread = ring_empty_consecutive(&netiring);
  1010. #if    !defined(SO_OOBINLINE)
  1011.         /*
  1012.          * In 4.2 (and some early 4.3) systems, the
  1013.          * OOB indication and data handling in the kernel
  1014.          * is such that if two separate TCP Urgent requests
  1015.          * come in, one byte of TCP data will be overlaid.
  1016.          * This is fatal for Telnet, but we try to live
  1017.          * with it.
  1018.          *
  1019.          * In addition, in 4.2 (and...), a special protocol
  1020.          * is needed to pick up the TCP Urgent data in
  1021.          * the correct sequence.
  1022.          *
  1023.          * What we do is:  if we think we are in urgent
  1024.          * mode, we look to see if we are "at the mark".
  1025.          * If we are, we do an OOB receive.  If we run
  1026.          * this twice, we will do the OOB receive twice,
  1027.          * but the second will fail, since the second
  1028.          * time we were "at the mark", but there wasn't
  1029.          * any data there (the kernel doesn't reset
  1030.          * "at the mark" until we do a normal read).
  1031.          * Once we've read the OOB data, we go ahead
  1032.          * and do normal reads.
  1033.          *
  1034.          * There is also another problem, which is that
  1035.          * since the OOB byte we read doesn't put us
  1036.          * out of OOB state, and since that byte is most
  1037.          * likely the TELNET DM (data mark), we would
  1038.          * stay in the TELNET SYNCH (SYNCHing) state.
  1039.          * So, clocks to the rescue.  If we've "just"
  1040.          * received a DM, then we test for the
  1041.          * presence of OOB data when the receive OOB
  1042.          * fails (and AFTER we did the normal mode read
  1043.          * to clear "at the mark").
  1044.          */
  1045.     if (SYNCHing) {
  1046.         int atmark;
  1047.         static int bogus_oob = 0, first = 1;
  1048.  
  1049.         ioctl(net, SIOCATMARK, (char *)&atmark);
  1050.         if (atmark) {
  1051.         c = recv(net, netiring.supply, canread, MSG_OOB);
  1052.         if ((c == -1) && (errno == EINVAL)) {
  1053.             c = recv(net, netiring.supply, canread, 0);
  1054.             if (clocks.didnetreceive < clocks.gotDM) {
  1055.             SYNCHing = stilloob(net);
  1056.             }
  1057.         } else if (first && c > 0) {
  1058.             /*
  1059.              * Bogosity check.  Systems based on 4.2BSD
  1060.              * do not return an error if you do a second
  1061.              * recv(MSG_OOB).  So, we do one.  If it
  1062.              * succeeds and returns exactly the same
  1063.              * data, then assume that we are running
  1064.              * on a broken system and set the bogus_oob
  1065.              * flag.  (If the data was different, then
  1066.              * we probably got some valid new data, so
  1067.              * increment the count...)
  1068.              */
  1069.             int i;
  1070.             i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
  1071.             if (i == c &&
  1072.               bcmp(netiring.supply, netiring.supply + c, i) == 0) {
  1073.             bogus_oob = 1;
  1074.             first = 0;
  1075.             } else if (i < 0) {
  1076.             bogus_oob = 0;
  1077.             first = 0;
  1078.             } else
  1079.             c += i;
  1080.         }
  1081.         if (bogus_oob && c > 0) {
  1082.             int i;
  1083.             /*
  1084.              * Bogosity.  We have to do the read
  1085.              * to clear the atmark to get out of
  1086.              * an infinate loop.
  1087.              */
  1088.             i = read(net, netiring.supply + c, canread - c);
  1089.             if (i > 0)
  1090.             c += i;
  1091.         }
  1092.         } else {
  1093.         c = recv(net, netiring.supply, canread, 0);
  1094.         }
  1095.     } else {
  1096.         c = recv(net, netiring.supply, canread, 0);
  1097.     }
  1098.     settimer(didnetreceive);
  1099. #else    /* !defined(SO_OOBINLINE) */
  1100.     c = recv(net, netiring.supply, canread, 0);
  1101. #endif    /* !defined(SO_OOBINLINE) */
  1102.     if (c < 0 && errno == EWOULDBLOCK) {
  1103.         c = 0;
  1104.     } else if (c <= 0) {
  1105.         return -1;
  1106.     }
  1107.     if (netdata) {
  1108.         Dump('<', netiring.supply, c);
  1109.     }
  1110.     if (c)
  1111.         ring_supplied(&netiring, c);
  1112.     returnValue = 1;
  1113.     }
  1114.  
  1115.     /*
  1116.      * Something to read from the tty...
  1117.      */
  1118.     if (FD_ISSET(tin, &ibits)) {
  1119.     FD_CLR(tin, &ibits);
  1120.     c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
  1121.     if (c < 0 && errno == EWOULDBLOCK) {
  1122.         c = 0;
  1123.     } else {
  1124.         /* EOF detection for line mode!!!! */
  1125.         if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
  1126.             /* must be an EOF... */
  1127.         *ttyiring.supply = termEofChar;
  1128.         c = 1;
  1129.         }
  1130.         if (c <= 0) {
  1131.         return -1;
  1132.         }
  1133.         if (termdata) {
  1134.         Dump('<', ttyiring.supply, c);
  1135.         }
  1136.         ring_supplied(&ttyiring, c);
  1137.     }
  1138.     returnValue = 1;        /* did something useful */
  1139.     }
  1140.  
  1141.     if (FD_ISSET(net, &obits)) {
  1142.     FD_CLR(net, &obits);
  1143.     returnValue |= netflush();
  1144.     }
  1145.     if (FD_ISSET(tout, &obits)) {
  1146.     FD_CLR(tout, &obits);
  1147.     returnValue |= (ttyflush(SYNCHing|flushout) > 0);
  1148.     }
  1149.  
  1150.     return returnValue;
  1151. }
  1152.