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