sys_bsd.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:28k
源码类别:

代理服务器

开发平台:

Unix_Linux

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