home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnunet10.zip / source / telnet / sys_bsd.c < prev    next >
C/C++ Source or Header  |  1996-07-27  |  27KB  |  1,220 lines

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