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