|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 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_term.c 5.10 (Berkeley) 6/30/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include "telnetd.h" ! 25: #include "pathnames.h" ! 26: ! 27: #ifdef NEWINIT ! 28: #include <initreq.h> ! 29: #else /* NEWINIT*/ ! 30: #include <utmp.h> ! 31: struct utmp wtmp; ! 32: ! 33: # ifndef CRAY ! 34: char wtmpf[] = "/usr/adm/wtmp"; ! 35: char utmpf[] = "/etc/utmp"; ! 36: # else /* CRAY */ ! 37: char wtmpf[] = "/etc/wtmp"; ! 38: # endif /* CRAY */ ! 39: #endif /* NEWINIT */ ! 40: ! 41: #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) ! 42: #define SCMPN(a, b) strncmp(a, b, sizeof(a)) ! 43: ! 44: #ifdef STREAMS ! 45: #include <sys/stream.h> ! 46: #endif ! 47: #include <sys/tty.h> ! 48: #ifdef t_erase ! 49: #undef t_erase ! 50: #undef t_kill ! 51: #undef t_intrc ! 52: #undef t_quitc ! 53: #undef t_startc ! 54: #undef t_stopc ! 55: #undef t_eofc ! 56: #undef t_brkc ! 57: #undef t_suspc ! 58: #undef t_dsuspc ! 59: #undef t_rprntc ! 60: #undef t_flushc ! 61: #undef t_werasc ! 62: #undef t_lnextc ! 63: #endif ! 64: ! 65: #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) ! 66: # define EXTPROC 0400 ! 67: #endif ! 68: ! 69: #ifndef USE_TERMIO ! 70: struct termbuf { ! 71: struct sgttyb sg; ! 72: struct tchars tc; ! 73: struct ltchars ltc; ! 74: int state; ! 75: int lflags; ! 76: } termbuf, termbuf2; ! 77: #else /* USE_TERMIO */ ! 78: # ifdef SYSV_TERMIO ! 79: # define termios termio ! 80: # endif ! 81: # ifndef TCSETA ! 82: # ifdef TCSETS ! 83: # define TCSETA TCSETS ! 84: # define TCGETA TCGETS ! 85: # else ! 86: # define TCSETA TIOCSETAW ! 87: # define TCGETA TIOCGETA ! 88: # endif ! 89: # endif /* 4.4BSD */ ! 90: struct termios termbuf, termbuf2; /* pty control structure */ ! 91: #endif /* USE_TERMIO */ ! 92: ! 93: /* ! 94: * init_termbuf() ! 95: * copy_termbuf(cp) ! 96: * set_termbuf() ! 97: * ! 98: * These three routines are used to get and set the "termbuf" structure ! 99: * to and from the kernel. init_termbuf() gets the current settings. ! 100: * copy_termbuf() hands in a new "termbuf" to write to the kernel, and ! 101: * set_termbuf() writes the structure into the kernel. ! 102: */ ! 103: ! 104: init_termbuf() ! 105: { ! 106: #ifndef USE_TERMIO ! 107: (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); ! 108: (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); ! 109: (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); ! 110: # ifdef TIOCGSTATE ! 111: (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); ! 112: # endif ! 113: #else ! 114: (void) ioctl(pty, TCGETA, (char *)&termbuf); ! 115: #endif ! 116: termbuf2 = termbuf; ! 117: } ! 118: ! 119: #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) ! 120: copy_termbuf(cp, len) ! 121: char *cp; ! 122: int len; ! 123: { ! 124: if (len > sizeof(termbuf)) ! 125: len = sizeof(termbuf); ! 126: bcopy(cp, (char *)&termbuf, len); ! 127: termbuf2 = termbuf; ! 128: } ! 129: #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ ! 130: ! 131: set_termbuf() ! 132: { ! 133: /* ! 134: * Only make the necessary changes. ! 135: */ ! 136: #ifndef USE_TERMIO ! 137: if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) ! 138: (void) ioctl(pty, TIOCSETP, (char *)&termbuf.sg); ! 139: if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) ! 140: (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); ! 141: if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, ! 142: sizeof(termbuf.ltc))) ! 143: (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); ! 144: if (termbuf.lflags != termbuf2.lflags) ! 145: (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); ! 146: #else /* USE_TERMIO */ ! 147: if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) ! 148: (void) ioctl(pty, TCSETA, (char *)&termbuf); ! 149: # if defined(CRAY2) && defined(UNCIOS5) ! 150: needtermstat = 1; ! 151: # endif ! 152: #endif /* USE_TERMIO */ ! 153: } ! 154: ! 155: ! 156: /* ! 157: * spcset(func, valp, valpp) ! 158: * ! 159: * This function takes various special characters (func), and ! 160: * sets *valp to the current value of that character, and ! 161: * *valpp to point to where in the "termbuf" structure that ! 162: * value is kept. ! 163: * ! 164: * It returns the SLC_ level of support for this function. ! 165: */ ! 166: ! 167: #ifndef USE_TERMIO ! 168: spcset(func, valp, valpp) ! 169: int func; ! 170: cc_t *valp; ! 171: cc_t **valpp; ! 172: { ! 173: switch(func) { ! 174: case SLC_EOF: ! 175: *valp = termbuf.tc.t_eofc; ! 176: *valpp = (cc_t *)&termbuf.tc.t_eofc; ! 177: return(SLC_VARIABLE); ! 178: case SLC_EC: ! 179: *valp = termbuf.sg.sg_erase; ! 180: *valpp = (cc_t *)&termbuf.sg.sg_erase; ! 181: return(SLC_VARIABLE); ! 182: case SLC_EL: ! 183: *valp = termbuf.sg.sg_kill; ! 184: *valpp = (cc_t *)&termbuf.sg.sg_kill; ! 185: return(SLC_VARIABLE); ! 186: case SLC_IP: ! 187: *valp = termbuf.tc.t_intrc; ! 188: *valpp = (cc_t *)&termbuf.tc.t_intrc; ! 189: return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); ! 190: case SLC_ABORT: ! 191: *valp = termbuf.tc.t_quitc; ! 192: *valpp = (cc_t *)&termbuf.tc.t_quitc; ! 193: return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); ! 194: case SLC_XON: ! 195: *valp = termbuf.tc.t_startc; ! 196: *valpp = (cc_t *)&termbuf.tc.t_startc; ! 197: return(SLC_VARIABLE); ! 198: case SLC_XOFF: ! 199: *valp = termbuf.tc.t_stopc; ! 200: *valpp = (cc_t *)&termbuf.tc.t_stopc; ! 201: return(SLC_VARIABLE); ! 202: case SLC_AO: ! 203: *valp = termbuf.ltc.t_flushc; ! 204: *valpp = (cc_t *)&termbuf.ltc.t_flushc; ! 205: return(SLC_VARIABLE); ! 206: case SLC_SUSP: ! 207: *valp = termbuf.ltc.t_suspc; ! 208: *valpp = (cc_t *)&termbuf.ltc.t_suspc; ! 209: return(SLC_VARIABLE); ! 210: case SLC_EW: ! 211: *valp = termbuf.ltc.t_werasc; ! 212: *valpp = (cc_t *)&termbuf.ltc.t_werasc; ! 213: return(SLC_VARIABLE); ! 214: case SLC_RP: ! 215: *valp = termbuf.ltc.t_rprntc; ! 216: *valpp = (cc_t *)&termbuf.ltc.t_rprntc; ! 217: return(SLC_VARIABLE); ! 218: case SLC_LNEXT: ! 219: *valp = termbuf.ltc.t_lnextc; ! 220: *valpp = (cc_t *)&termbuf.ltc.t_lnextc; ! 221: return(SLC_VARIABLE); ! 222: case SLC_FORW1: ! 223: *valp = termbuf.tc.t_brkc; ! 224: *valpp = (cc_t *)&termbuf.ltc.t_lnextc; ! 225: return(SLC_VARIABLE); ! 226: case SLC_BRK: ! 227: case SLC_SYNCH: ! 228: case SLC_AYT: ! 229: case SLC_EOR: ! 230: *valp = (cc_t)0; ! 231: *valpp = (cc_t *)0; ! 232: return(SLC_DEFAULT); ! 233: default: ! 234: *valp = (cc_t)0; ! 235: *valpp = (cc_t *)0; ! 236: return(SLC_NOSUPPORT); ! 237: } ! 238: } ! 239: ! 240: #else /* USE_TERMIO */ ! 241: ! 242: spcset(func, valp, valpp) ! 243: int func; ! 244: cc_t *valp; ! 245: cc_t **valpp; ! 246: { ! 247: ! 248: #define setval(a, b) *valp = termbuf.c_cc[a]; \ ! 249: *valpp = &termbuf.c_cc[a]; \ ! 250: return(b); ! 251: #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); ! 252: ! 253: switch(func) { ! 254: case SLC_EOF: ! 255: setval(VEOF, SLC_VARIABLE); ! 256: case SLC_EC: ! 257: setval(VERASE, SLC_VARIABLE); ! 258: case SLC_EL: ! 259: setval(VKILL, SLC_VARIABLE); ! 260: case SLC_IP: ! 261: setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); ! 262: case SLC_ABORT: ! 263: setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); ! 264: case SLC_XON: ! 265: #ifdef VSTART ! 266: setval(VSTART, SLC_VARIABLE); ! 267: #else ! 268: defval(0x13); ! 269: #endif ! 270: case SLC_XOFF: ! 271: #ifdef VSTOP ! 272: setval(VSTOP, SLC_VARIABLE); ! 273: #else ! 274: defval(0x11); ! 275: #endif ! 276: case SLC_EW: ! 277: #ifdef VWERASE ! 278: setval(VWERASE, SLC_VARIABLE); ! 279: #else ! 280: defval(0); ! 281: #endif ! 282: case SLC_RP: ! 283: #ifdef VREPRINT ! 284: setval(VREPRINT, SLC_VARIABLE); ! 285: #else ! 286: defval(0); ! 287: #endif ! 288: case SLC_LNEXT: ! 289: #ifdef VLNEXT ! 290: setval(VLNEXT, SLC_VARIABLE); ! 291: #else ! 292: defval(0); ! 293: #endif ! 294: case SLC_AO: ! 295: #ifdef VFLUSHO ! 296: setval(VFLUSHO, SLC_VARIABLE|SLC_FLUSHOUT); ! 297: #else ! 298: defval(0); ! 299: #endif ! 300: case SLC_SUSP: ! 301: #ifdef VSUSP ! 302: setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); ! 303: #else ! 304: defval(0); ! 305: #endif ! 306: #ifdef VEOL ! 307: case SLC_FORW1: ! 308: setval(VEOL, SLC_VARIABLE); ! 309: #endif ! 310: #ifdef VEOL2 ! 311: case SLC_FORW2: ! 312: setval(VEOL2, SLC_VARIABLE); ! 313: #endif ! 314: ! 315: case SLC_BRK: ! 316: case SLC_SYNCH: ! 317: case SLC_AYT: ! 318: case SLC_EOR: ! 319: defval(0); ! 320: ! 321: default: ! 322: *valp = 0; ! 323: *valpp = 0; ! 324: return(SLC_NOSUPPORT); ! 325: } ! 326: } ! 327: #endif /* USE_TERMIO */ ! 328: ! 329: #ifdef CRAY ! 330: /* ! 331: * getnpty() ! 332: * ! 333: * Return the number of pty's configured into the system. ! 334: */ ! 335: getnpty() ! 336: { ! 337: #ifdef _SC_CRAY_NPTY ! 338: return sysconf(_SC_CRAY_NPTY); ! 339: #else ! 340: return 128; ! 341: #endif /* _SC_CRAY_NPTY */ ! 342: } ! 343: #endif /* CRAY */ ! 344: ! 345: /* ! 346: * getpty() ! 347: * ! 348: * Allocate a pty. As a side effect, the external character ! 349: * array "line" contains the name of the slave side. ! 350: * ! 351: * Returns the file descriptor of the opened pty. ! 352: */ ! 353: char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; ! 354: ! 355: getpty() ! 356: { ! 357: register int p; ! 358: #ifndef CRAY ! 359: register char c, *p1, *p2; ! 360: register int i; ! 361: ! 362: (void) sprintf(line, "/dev/ptyXX"); ! 363: p1 = &line[8]; ! 364: p2 = &line[9]; ! 365: ! 366: for (c = 'p'; c <= 's'; c++) { ! 367: struct stat stb; ! 368: ! 369: *p1 = c; ! 370: *p2 = '0'; ! 371: if (stat(line, &stb) < 0) ! 372: break; ! 373: for (i = 0; i < 16; i++) { ! 374: *p2 = "0123456789abcdef"[i]; ! 375: p = open(line, 2); ! 376: if (p > 0) { ! 377: line[5] = 't'; ! 378: return(p); ! 379: } ! 380: } ! 381: } ! 382: #else /* CRAY */ ! 383: register int npty; ! 384: extern lowpty, highpty; ! 385: ! 386: for (npty = lowpty; npty <= highpty; npty++) { ! 387: (void) sprintf(line, "/dev/pty/%03d", npty); ! 388: p = open(line, 2); ! 389: if (p < 0) ! 390: continue; ! 391: (void) sprintf(line, "/dev/ttyp%03d", npty); ! 392: if (access(line, 6) == 0) ! 393: return(p); ! 394: else { ! 395: /* no tty side to pty so skip it */ ! 396: (void) close(p); ! 397: } ! 398: } ! 399: #endif /* CRAY */ ! 400: return(-1); ! 401: } ! 402: ! 403: #ifdef LINEMODE ! 404: /* ! 405: * tty_flowmode() Find out if flow control is enabled or disabled. ! 406: * tty_linemode() Find out if linemode (external processing) is enabled. ! 407: * tty_setlinemod(on) Turn on/off linemode. ! 408: * tty_isecho() Find out if echoing is turned on. ! 409: * tty_setecho(on) Enable/disable character echoing. ! 410: * tty_israw() Find out if terminal is in RAW mode. ! 411: * tty_binaryin(on) Turn on/off BINARY on input. ! 412: * tty_binaryout(on) Turn on/off BINARY on output. ! 413: * tty_isediting() Find out if line editing is enabled. ! 414: * tty_istrapsig() Find out if signal trapping is enabled. ! 415: * tty_setedit(on) Turn on/off line editing. ! 416: * tty_setsig(on) Turn on/off signal trapping. ! 417: * tty_issofttab() Find out if tab expansion is enabled. ! 418: * tty_setsofttab(on) Turn on/off soft tab expansion. ! 419: * tty_islitecho() Find out if typed control chars are echoed literally ! 420: * tty_setlitecho() Turn on/off literal echo of control chars ! 421: * tty_tspeed(val) Set transmit speed to val. ! 422: * tty_rspeed(val) Set receive speed to val. ! 423: */ ! 424: ! 425: tty_flowmode() ! 426: { ! 427: #ifndef USE_TERMIO ! 428: return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0); ! 429: #else ! 430: return(termbuf.c_iflag & IXON ? 1 : 0); ! 431: #endif ! 432: } ! 433: ! 434: tty_linemode() ! 435: { ! 436: #ifndef USE_TERMIO ! 437: return(termbuf.state & TS_EXTPROC); ! 438: #else ! 439: return(termbuf.c_lflag & EXTPROC); ! 440: #endif ! 441: } ! 442: ! 443: tty_setlinemode(on) ! 444: int on; ! 445: { ! 446: #ifdef TIOCEXT ! 447: (void) ioctl(pty, TIOCEXT, (char *)&on); ! 448: #else /* !TIOCEXT */ ! 449: #ifdef EXTPROC ! 450: if (on) ! 451: termbuf.c_lflag |= EXTPROC; ! 452: else ! 453: termbuf.c_lflag &= ~EXTPROC; ! 454: #endif ! 455: set_termbuf(); ! 456: #endif /* TIOCEXT */ ! 457: } ! 458: ! 459: tty_isecho() ! 460: { ! 461: #ifndef USE_TERMIO ! 462: return (termbuf.sg.sg_flags & ECHO); ! 463: #else ! 464: return (termbuf.c_lflag & ECHO); ! 465: #endif ! 466: } ! 467: #endif /* LINEMODE */ ! 468: ! 469: tty_setecho(on) ! 470: { ! 471: #ifndef USE_TERMIO ! 472: if (on) ! 473: termbuf.sg.sg_flags |= ECHO|CRMOD; ! 474: else ! 475: termbuf.sg.sg_flags &= ~(ECHO|CRMOD); ! 476: #else ! 477: if (on) ! 478: termbuf.c_lflag |= ECHO; ! 479: else ! 480: termbuf.c_lflag &= ~ECHO; ! 481: #endif ! 482: } ! 483: ! 484: #if defined(LINEMODE) && defined(KLUDGELINEMODE) ! 485: tty_israw() ! 486: { ! 487: #ifndef USE_TERMIO ! 488: return(termbuf.sg.sg_flags & RAW); ! 489: #else ! 490: return(!(termbuf.c_lflag & ICANON)); ! 491: #endif ! 492: } ! 493: #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ ! 494: ! 495: tty_binaryin(on) ! 496: { ! 497: #ifndef USE_TERMIO ! 498: if (on) ! 499: termbuf.lflags |= LPASS8; ! 500: else ! 501: termbuf.lflags &= ~LPASS8; ! 502: #else ! 503: if (on) { ! 504: termbuf.c_lflag &= ~ISTRIP; ! 505: } else { ! 506: termbuf.c_lflag |= ISTRIP; ! 507: } ! 508: #endif ! 509: } ! 510: ! 511: tty_binaryout(on) ! 512: { ! 513: #ifndef USE_TERMIO ! 514: if (on) ! 515: termbuf.lflags |= LLITOUT; ! 516: else ! 517: termbuf.lflags &= ~LLITOUT; ! 518: #else ! 519: if (on) { ! 520: termbuf.c_cflag &= ~(CSIZE|PARENB); ! 521: termbuf.c_cflag |= CS8; ! 522: termbuf.c_oflag &= ~OPOST; ! 523: } else { ! 524: termbuf.c_cflag &= ~CSIZE; ! 525: termbuf.c_cflag |= CS7|PARENB; ! 526: termbuf.c_oflag |= OPOST; ! 527: } ! 528: #endif ! 529: } ! 530: ! 531: tty_isbinaryin() ! 532: { ! 533: #ifndef USE_TERMIO ! 534: return(termbuf.lflags & LPASS8); ! 535: #else ! 536: return(!(termbuf.c_iflag & ISTRIP)); ! 537: #endif ! 538: } ! 539: ! 540: tty_isbinaryout() ! 541: { ! 542: #ifndef USE_TERMIO ! 543: return(termbuf.lflags & LLITOUT); ! 544: #else ! 545: return(!(termbuf.c_oflag&OPOST)); ! 546: #endif ! 547: } ! 548: ! 549: #ifdef LINEMODE ! 550: tty_isediting() ! 551: { ! 552: #ifndef USE_TERMIO ! 553: return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); ! 554: #else ! 555: return(termbuf.c_lflag & ICANON); ! 556: #endif ! 557: } ! 558: ! 559: tty_istrapsig() ! 560: { ! 561: #ifndef USE_TERMIO ! 562: return(!(termbuf.sg.sg_flags&RAW)); ! 563: #else ! 564: return(termbuf.c_lflag & ISIG); ! 565: #endif ! 566: } ! 567: ! 568: tty_setedit(on) ! 569: int on; ! 570: { ! 571: #ifndef USE_TERMIO ! 572: if (on) ! 573: termbuf.sg.sg_flags &= ~CBREAK; ! 574: else ! 575: termbuf.sg.sg_flags |= CBREAK; ! 576: #else ! 577: if (on) ! 578: termbuf.c_lflag |= ICANON; ! 579: else ! 580: termbuf.c_lflag &= ~ICANON; ! 581: #endif ! 582: } ! 583: ! 584: tty_setsig(on) ! 585: int on; ! 586: { ! 587: #ifndef USE_TERMIO ! 588: if (on) ! 589: ; ! 590: #else ! 591: if (on) ! 592: termbuf.c_lflag |= ISIG; ! 593: else ! 594: termbuf.c_lflag &= ~ISIG; ! 595: #endif ! 596: } ! 597: #endif /* LINEMODE */ ! 598: ! 599: tty_issofttab() ! 600: { ! 601: #ifndef USE_TERMIO ! 602: return (termbuf.sg.sg_flags & XTABS); ! 603: #else ! 604: # ifdef OXTABS ! 605: return (termbuf.c_oflag & OXTABS); ! 606: # endif ! 607: # ifdef TABDLY ! 608: return ((termbuf.c_oflag & TABDLY) == TAB3); ! 609: # endif ! 610: #endif ! 611: } ! 612: ! 613: tty_setsofttab(on) ! 614: int on; ! 615: { ! 616: #ifndef USE_TERMIO ! 617: if (on) ! 618: termbuf.sg.sg_flags |= XTABS; ! 619: else ! 620: termbuf.sg.sg_flags &= ~XTABS; ! 621: #else ! 622: if (on) { ! 623: # ifdef OXTABS ! 624: termbuf.c_oflag |= OXTABS; ! 625: # endif ! 626: # ifdef TABDLY ! 627: termbuf.c_oflag &= ~TABDLY; ! 628: termbuf.c_oflag |= TAB3; ! 629: # endif ! 630: } else { ! 631: # ifdef OXTABS ! 632: termbuf.c_oflag &= ~OXTABS; ! 633: # endif ! 634: # ifdef TABDLY ! 635: termbuf.c_oflag &= ~TABDLY; ! 636: termbuf.c_oflag |= TAB0; ! 637: # endif ! 638: } ! 639: #endif ! 640: } ! 641: ! 642: tty_islitecho() ! 643: { ! 644: #ifndef USE_TERMIO ! 645: return (!(termbuf.sg.sg_flags & CTLECH)); ! 646: #else ! 647: # ifdef ECHOCTL ! 648: return (!(termbuf.c_lflag & ECHOCTL)); ! 649: # endif ! 650: # ifdef TCTLECH ! 651: return (!(termbuf.c_lflag & TCTLECH)); ! 652: # endif ! 653: # if !defined(ECHOCTL) && !defined(TCTLECH) ! 654: return (0); /* assumes ctl chars are echoed '^x' */ ! 655: # endif ! 656: #endif ! 657: } ! 658: ! 659: tty_setlitecho(on) ! 660: int on; ! 661: { ! 662: #ifndef USE_TERMIO ! 663: if (on) ! 664: termbuf.sg.sg_flags &= ~CTLECH; ! 665: else ! 666: termbuf.sg.sg_flags |= CTLECH; ! 667: #else ! 668: # ifdef ECHOCTL ! 669: if (on) ! 670: termbuf.c_lflag &= ~ECHOCTL; ! 671: else ! 672: termbuf.c_lflag |= ECHOCTL; ! 673: # endif ! 674: # ifdef TCTLECH ! 675: if (on) ! 676: termbuf.c_lflag &= ~TCTLECH; ! 677: else ! 678: termbuf.c_lflag |= TCTLECH; ! 679: # endif ! 680: #endif ! 681: } ! 682: ! 683: /* ! 684: * A table of available terminal speeds ! 685: */ ! 686: struct termspeeds { ! 687: int speed; ! 688: int value; ! 689: } termspeeds[] = { ! 690: { 0, B0 }, { 50, B50 }, { 75, B75 }, ! 691: { 110, B110 }, { 134, B134 }, { 150, B150 }, ! 692: { 200, B200 }, { 300, B300 }, { 600, B600 }, ! 693: { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, ! 694: { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, ! 695: { 38400, B9600 }, { -1, B9600 } ! 696: }; ! 697: ! 698: tty_tspeed(val) ! 699: { ! 700: register struct termspeeds *tp; ! 701: ! 702: for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ! 703: ; ! 704: #ifndef USE_TERMIO ! 705: termbuf.sg.sg_ospeed = tp->value; ! 706: #else ! 707: # ifdef CBAUD ! 708: termbuf.c_cflag &= ~CBAUD; ! 709: termbuf.c_cflag |= tp->value; ! 710: # else ! 711: termbuf.c_ospeed = tp->value; ! 712: # endif ! 713: #endif ! 714: } ! 715: ! 716: tty_rspeed(val) ! 717: { ! 718: register struct termspeeds *tp; ! 719: ! 720: for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ! 721: ; ! 722: #ifndef USE_TERMIO ! 723: termbuf.sg.sg_ispeed = tp->value; ! 724: #else ! 725: # ifdef CBAUD ! 726: termbuf.c_cflag &= ~CBAUD; ! 727: termbuf.c_cflag |= tp->value; ! 728: # else ! 729: termbuf.c_ispeed = tp->value; ! 730: # endif ! 731: #endif ! 732: } ! 733: ! 734: #if defined(CRAY2) && defined(UNICOS5) ! 735: tty_isnewmap() ! 736: { ! 737: return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && ! 738: !(termbuf.c_oflag & ONLRET)); ! 739: } ! 740: #endif ! 741: ! 742: #ifdef CRAY ! 743: # ifndef NEWINIT ! 744: extern struct utmp wtmp; ! 745: extern char wtmpf[]; ! 746: # else /* NEWINIT */ ! 747: int gotalarm; ! 748: /* ARGSUSED */ ! 749: void ! 750: nologinproc(sig) ! 751: int sig; ! 752: { ! 753: gotalarm++; ! 754: } ! 755: # endif /* NEWINIT */ ! 756: #endif /* CRAY */ ! 757: ! 758: /* ! 759: * getptyslave() ! 760: * ! 761: * Open the slave side of the pty, and do any initialization ! 762: * that is necessary. The return value is a file descriptor ! 763: * for the slave side. ! 764: */ ! 765: getptyslave() ! 766: { ! 767: register int t = -1; ! 768: ! 769: #ifndef CRAY ! 770: /* ! 771: * Disassociate self from control terminal and open ttyp side. ! 772: * Set important flags on ttyp and ptyp. ! 773: */ ! 774: t = open(_PATH_TTY, O_RDWR); ! 775: if (t >= 0) { ! 776: (void) ioctl(t, TIOCNOTTY, (char *)0); ! 777: (void) close(t); ! 778: } ! 779: ! 780: t = open(line, O_RDWR); ! 781: if (t < 0) ! 782: fatalperror(net, line); ! 783: if (fchmod(t, 0)) ! 784: fatalperror(net, line); ! 785: #if BSD <= 43 ! 786: (void) signal(SIGHUP, SIG_IGN); ! 787: vhangup(); ! 788: (void) signal(SIGHUP, SIG_DFL); ! 789: t = open(line, O_RDWR); ! 790: if (t < 0) ! 791: fatalperror(net, line); ! 792: #endif ! 793: ! 794: init_termbuf(); ! 795: #ifndef USE_TERMIO ! 796: termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; ! 797: termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600; ! 798: #else ! 799: termbuf.c_lflag |= ECHO; ! 800: #ifndef OXTABS ! 801: #define OXTABS 0 ! 802: #endif ! 803: termbuf.c_oflag |= ONLCR|OXTABS; ! 804: termbuf.c_iflag |= ICRNL; ! 805: termbuf.c_iflag &= ~IXOFF; ! 806: # ifdef CBAUD ! 807: termbuf.c_cflag &= ~CBAUD; ! 808: termbuf.c_cflag |= B9600; ! 809: # else /* CBAUD */ ! 810: termbuf.c_ospeed = termbuf.c_ispeed = B9600; ! 811: # endif /* CBAUD */ ! 812: #endif ! 813: set_termbuf(); ! 814: #else /* CRAY */ ! 815: (void) chown(line, 0, 0); ! 816: (void) chmod(line, 0600); ! 817: #endif /* CRAY */ ! 818: return(t); ! 819: } ! 820: ! 821: #ifdef NEWINIT ! 822: char *gen_id = "fe"; ! 823: #endif ! 824: ! 825: /* ! 826: * startslave(t, host) ! 827: * ! 828: * Given a file descriptor (t) for a tty, and a hostname, do whatever ! 829: * is necessary to startup the login process on the slave side of the pty. ! 830: */ ! 831: ! 832: /* ARGSUSED */ ! 833: startslave(t, host) ! 834: int t; ! 835: char *host; ! 836: { ! 837: register int i; ! 838: long time(); ! 839: ! 840: #ifndef NEWINIT ! 841: # ifdef CRAY ! 842: utmp_sig_init(); ! 843: # endif /* CRAY */ ! 844: ! 845: if ((i = fork()) < 0) ! 846: fatalperror(net, "fork"); ! 847: if (i) { ! 848: # ifdef CRAY ! 849: /* ! 850: * Cray parent will create utmp entry for child and send ! 851: * signal to child to tell when done. Child waits for signal ! 852: * before doing anything important. ! 853: */ ! 854: register int pid = i; ! 855: ! 856: setpgrp(); ! 857: utmp_sig_reset(); /* reset handler to default */ ! 858: /* ! 859: * Create utmp entry for child ! 860: */ ! 861: (void) time(&wtmp.ut_time); ! 862: wtmp.ut_type = LOGIN_PROCESS; ! 863: wtmp.ut_pid = pid; ! 864: SCPYN(wtmp.ut_user, "LOGIN"); ! 865: SCPYN(wtmp.ut_host, host); ! 866: SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); ! 867: SCPYN(wtmp.ut_id, wtmp.ut_line+3); ! 868: pututline(&wtmp); ! 869: endutent(); ! 870: if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { ! 871: (void) write(i, (char *)&wtmp, sizeof(struct utmp)); ! 872: (void) close(i); ! 873: } ! 874: utmp_sig_notify(pid); ! 875: # endif /* CRAY */ ! 876: (void) close(t); ! 877: } else { ! 878: start_login(t, host); ! 879: /*NOTREACHED*/ ! 880: } ! 881: #else /* NEWINIT */ ! 882: ! 883: extern char *ptyip; ! 884: struct init_request request; ! 885: void nologinproc(); ! 886: register int n; ! 887: ! 888: /* ! 889: * Init will start up login process if we ask nicely. We only wait ! 890: * for it to start up and begin normal telnet operation. ! 891: */ ! 892: if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { ! 893: char tbuf[128]; ! 894: (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); ! 895: fatalperror(net, tbuf); ! 896: } ! 897: memset((char *)&request, 0, sizeof(request)); ! 898: request.magic = INIT_MAGIC; ! 899: SCPYN(request.gen_id, gen_id); ! 900: SCPYN(request.tty_id, &line[8]); ! 901: SCPYN(request.host, host); ! 902: SCPYN(request.term_type, terminaltype); ! 903: #if !defined(UNICOS5) ! 904: request.signal = SIGCLD; ! 905: request.pid = getpid(); ! 906: #endif ! 907: #ifdef BFTPDAEMON ! 908: /* ! 909: * Are we working as the bftp daemon? ! 910: */ ! 911: if (bftpd) { ! 912: SCPYN(request.exec_name, BFTPPATH); ! 913: } ! 914: #endif /* BFTPDAEMON */ ! 915: if (write(i, (char *)&request, sizeof(request)) < 0) { ! 916: char tbuf[128]; ! 917: (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); ! 918: fatalperror(net, tbuf); ! 919: } ! 920: (void) close(i); ! 921: (void) signal(SIGALRM, nologinproc); ! 922: for (i = 0; ; i++) { ! 923: char tbuf[128]; ! 924: alarm(15); ! 925: n = read(pty, ptyip, BUFSIZ); ! 926: if (i == 3 || n >= 0 || !gotalarm) ! 927: break; ! 928: gotalarm = 0; ! 929: sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); ! 930: (void) write(net, tbuf, strlen(tbuf)); ! 931: } ! 932: if (n < 0 && gotalarm) ! 933: fatal(net, "/etc/init didn't start login process"); ! 934: pcc += n; ! 935: alarm(0); ! 936: (void) signal(SIGALRM, SIG_DFL); ! 937: ! 938: return; ! 939: #endif /* NEWINIT */ ! 940: } ! 941: ! 942: char *envinit[3]; ! 943: extern char **environ; ! 944: ! 945: init_env() ! 946: { ! 947: extern char *getenv(); ! 948: char **envp; ! 949: ! 950: envp = envinit; ! 951: if (*envp = getenv("TZ")) ! 952: *envp++ -= 3; ! 953: #ifdef CRAY ! 954: else ! 955: *envp++ = "TZ=GMT0"; ! 956: #endif ! 957: *envp = 0; ! 958: environ = envinit; ! 959: } ! 960: ! 961: #ifdef CRAY ! 962: /* ! 963: * These are environment variable that we ! 964: * don't put on the argument line. ! 965: */ ! 966: char *invalid[] = { ! 967: "USER=", /* Set up by login */ ! 968: "HOME=", /* Set up by login */ ! 969: "LOGNAME=", /* Set up by login */ ! 970: "TMPDIR=", /* Set up by login */ ! 971: "SHELL=", /* Set up by login */ ! 972: "PATH=", /* Set up by login */ ! 973: "MAIL=", /* Set up by login */ ! 974: "TZ=", /* Login gets it from the environment */ ! 975: "TERM=", /* Login gets it from the environment */ ! 976: 0 ! 977: }; ! 978: #endif ! 979: ! 980: #ifndef NEWINIT ! 981: ! 982: /* ! 983: * start_login(t, host) ! 984: * ! 985: * Assuming that we are now running as a child processes, this ! 986: * function will turn us into the login process. ! 987: */ ! 988: ! 989: start_login(t, host) ! 990: int t; ! 991: char *host; ! 992: { ! 993: register char *cp; ! 994: register char **argv; ! 995: char **addarg(); ! 996: #ifdef CRAY ! 997: register char **cpp, **cpp2; ! 998: utmp_sig_wait(); ! 999: # ifndef TCVHUP ! 1000: setpgrp(); ! 1001: # endif ! 1002: t = open(line, 2); /* open ttyp */ ! 1003: if (t < 0) ! 1004: fatalperror(net, line); ! 1005: # ifdef TCVHUP ! 1006: /* ! 1007: * Hangup anybody else using this ttyp, then reopen it for ! 1008: * ourselves. ! 1009: */ ! 1010: (void) chown(line, 0, 0); ! 1011: (void) chmod(line, 0600); ! 1012: (void) signal(SIGHUP, SIG_IGN); ! 1013: (void) ioctl(t, TCVHUP, (char *)0); ! 1014: (void) signal(SIGHUP, SIG_DFL); ! 1015: setpgrp(); ! 1016: i = open(line, 2); ! 1017: if (i < 0) ! 1018: fatalperror(net, line); ! 1019: (void) close(t); ! 1020: t = i; ! 1021: # endif /* TCVHUP */ ! 1022: /* ! 1023: * set ttyp modes as we like them to be ! 1024: */ ! 1025: init_termbuf(); ! 1026: termbuf.c_oflag = OPOST|ONLCR|TAB3; ! 1027: termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; ! 1028: termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; ! 1029: termbuf.c_cflag = EXTB|HUPCL|CS8; ! 1030: set_termbuf(); ! 1031: #endif /* CRAY */ ! 1032: ! 1033: /* ! 1034: * set up standard paths before forking to login ! 1035: */ ! 1036: #if BSD > 43 ! 1037: if (login_tty(t) == -1) ! 1038: fatalperror(net, "login_tty"); ! 1039: #else ! 1040: (void) dup2(t, 0); ! 1041: (void) dup2(t, 1); ! 1042: (void) dup2(t, 2); ! 1043: (void) close(t); ! 1044: #endif ! 1045: if (net > 2) ! 1046: (void) close(net); ! 1047: if (pty > 2) ! 1048: (void) close(pty); ! 1049: /* ! 1050: * -h : pass on name of host. ! 1051: * WARNING: -h is accepted by login if and only if ! 1052: * getuid() == 0. ! 1053: * -p : don't clobber the environment (so terminal type stays set). ! 1054: */ ! 1055: argv = addarg(0, "login"); ! 1056: argv = addarg(argv, "-h"); ! 1057: argv = addarg(argv, host); ! 1058: #if !defined(CRAY) && !defined(NO_LOGIN_P) ! 1059: argv = addarg(argv, "-p"); ! 1060: #endif ! 1061: #ifdef BFTPDAEMON ! 1062: /* ! 1063: * Are we working as the bftp daemon? If so, then ask login ! 1064: * to start bftp instead of shell. ! 1065: */ ! 1066: if (bftpd) { ! 1067: argv = addarg(argv, "-e"); ! 1068: argv = addarg(argv, BFTPPATH); ! 1069: } else ! 1070: #endif ! 1071: if (getenv("USER")) { ! 1072: argv = addarg(argv, getenv("USER")); ! 1073: } ! 1074: #ifdef CRAY ! 1075: for (cpp = environ; *cpp; cpp++) { ! 1076: for (cpp2 = invalid; *cpp2; cpp2++) ! 1077: if (strncmp(*cpp2, *cpp, strlen(*cpp2)) == 0) ! 1078: break; ! 1079: if (*cpp2) ! 1080: continue; ! 1081: argv = addarg(argv, *cpp); ! 1082: } ! 1083: #endif ! 1084: ! 1085: execv(_PATH_LOGIN, argv); ! 1086: ! 1087: syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); ! 1088: fatalperror(net, _PATH_LOGIN); ! 1089: /*NOTREACHED*/ ! 1090: } ! 1091: ! 1092: char ** ! 1093: addarg(argv, val) ! 1094: register char **argv; ! 1095: register char *val; ! 1096: { ! 1097: register char **cpp; ! 1098: char *malloc(); ! 1099: ! 1100: if (argv == NULL) { ! 1101: /* ! 1102: * 10 entries, a leading length, and a null ! 1103: */ ! 1104: argv = (char **)malloc(sizeof(*argv) * 12); ! 1105: if (argv == NULL) ! 1106: return(NULL); ! 1107: *argv++ = (char *)10; ! 1108: *argv = (char *)0; ! 1109: } ! 1110: for (cpp = argv; *cpp; cpp++) ! 1111: ; ! 1112: if (cpp == &argv[(int)argv[-1]]) { ! 1113: --argv; ! 1114: *argv = (char *)((int)(*argv) + 10); ! 1115: argv = (char **)realloc(argv, (int)(*argv) + 2); ! 1116: if (argv == NULL) ! 1117: return(NULL); ! 1118: argv++; ! 1119: cpp = &argv[(int)argv[-1] - 10]; ! 1120: } ! 1121: *cpp++ = val; ! 1122: *cpp = 0; ! 1123: return(argv); ! 1124: } ! 1125: #endif NEWINIT ! 1126: ! 1127: /* ! 1128: * cleanup() ! 1129: * ! 1130: * This is the routine to call when we are all through, to ! 1131: * clean up anything that needs to be cleaned up. ! 1132: */ ! 1133: cleanup() ! 1134: { ! 1135: ! 1136: #ifndef CRAY ! 1137: # if BSD > 43 ! 1138: char *p; ! 1139: ! 1140: p = line + sizeof("/dev/") - 1; ! 1141: if (logout(p)) ! 1142: logwtmp(p, "", ""); ! 1143: (void)chmod(line, 0666); ! 1144: (void)chown(line, 0, 0); ! 1145: *p = 'p'; ! 1146: (void)chmod(line, 0666); ! 1147: (void)chown(line, 0, 0); ! 1148: # else ! 1149: rmut(); ! 1150: vhangup(); /* XXX */ ! 1151: # endif ! 1152: (void) shutdown(net, 2); ! 1153: #else /* CRAY */ ! 1154: # ifndef NEWINIT ! 1155: rmut(line); ! 1156: (void) shutdown(net, 2); ! 1157: kill(0, SIGHUP); ! 1158: # else /* NEWINIT */ ! 1159: (void) shutdown(net, 2); ! 1160: # endif /* NEWINT */ ! 1161: #endif /* CRAY */ ! 1162: exit(1); ! 1163: } ! 1164: ! 1165: #if defined(CRAY) && !defined(NEWINIT) ! 1166: /* ! 1167: * _utmp_sig_rcv ! 1168: * utmp_sig_init ! 1169: * utmp_sig_wait ! 1170: * These three functions are used to coordinate the handling of ! 1171: * the utmp file between the server and the soon-to-be-login shell. ! 1172: * The server actually creates the utmp structure, the child calls ! 1173: * utmp_sig_wait(), until the server calls utmp_sig_notify() and ! 1174: * signals the future-login shell to proceed. ! 1175: */ ! 1176: static int caught=0; /* NZ when signal intercepted */ ! 1177: static void (*func)(); /* address of previous handler */ ! 1178: ! 1179: void ! 1180: _utmp_sig_rcv(sig) ! 1181: int sig; ! 1182: { ! 1183: caught = 1; ! 1184: (void) signal(SIGUSR1, func); ! 1185: } ! 1186: ! 1187: utmp_sig_init() ! 1188: { ! 1189: /* ! 1190: * register signal handler for UTMP creation ! 1191: */ ! 1192: if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) ! 1193: fatalperror(net, "telnetd/signal"); ! 1194: } ! 1195: ! 1196: utmp_sig_reset() ! 1197: { ! 1198: (void) signal(SIGUSR1, func); /* reset handler to default */ ! 1199: } ! 1200: ! 1201: utmp_sig_wait() ! 1202: { ! 1203: /* ! 1204: * Wait for parent to write our utmp entry. ! 1205: */ ! 1206: sigoff(); ! 1207: while (caught == 0) { ! 1208: pause(); /* wait until we get a signal (sigon) */ ! 1209: sigoff(); /* turn off signals while we check caught */ ! 1210: } ! 1211: sigon(); /* turn on signals again */ ! 1212: } ! 1213: ! 1214: utmp_sig_notify(pid) ! 1215: { ! 1216: kill(pid, SIGUSR1); ! 1217: } ! 1218: #endif /* defined(CRAY) && !defined(NEWINIT) */ ! 1219: ! 1220: /* ! 1221: * rmut() ! 1222: * ! 1223: * This is the function called by cleanup() to ! 1224: * remove the utmp entry for this person. ! 1225: */ ! 1226: ! 1227: #if !defined(CRAY) && BSD <= 43 ! 1228: rmut() ! 1229: { ! 1230: register f; ! 1231: int found = 0; ! 1232: struct utmp *u, *utmp; ! 1233: int nutmp; ! 1234: struct stat statbf; ! 1235: char *malloc(); ! 1236: long time(); ! 1237: off_t lseek(); ! 1238: ! 1239: f = open(utmpf, O_RDWR); ! 1240: if (f >= 0) { ! 1241: (void) fstat(f, &statbf); ! 1242: utmp = (struct utmp *)malloc((unsigned)statbf.st_size); ! 1243: if (!utmp) ! 1244: syslog(LOG_ERR, "utmp malloc failed"); ! 1245: if (statbf.st_size && utmp) { ! 1246: nutmp = read(f, (char *)utmp, (int)statbf.st_size); ! 1247: nutmp /= sizeof(struct utmp); ! 1248: ! 1249: for (u = utmp ; u < &utmp[nutmp] ; u++) { ! 1250: if (SCMPN(u->ut_line, line+5) || ! 1251: u->ut_name[0]==0) ! 1252: continue; ! 1253: (void) lseek(f, ((long)u)-((long)utmp), L_SET); ! 1254: SCPYN(u->ut_name, ""); ! 1255: SCPYN(u->ut_host, ""); ! 1256: (void) time(&u->ut_time); ! 1257: (void) write(f, (char *)u, sizeof(wtmp)); ! 1258: found++; ! 1259: } ! 1260: } ! 1261: (void) close(f); ! 1262: } ! 1263: if (found) { ! 1264: f = open(wtmpf, O_WRONLY|O_APPEND); ! 1265: if (f >= 0) { ! 1266: SCPYN(wtmp.ut_line, line+5); ! 1267: SCPYN(wtmp.ut_name, ""); ! 1268: SCPYN(wtmp.ut_host, ""); ! 1269: (void) time(&wtmp.ut_time); ! 1270: (void) write(f, (char *)&wtmp, sizeof(wtmp)); ! 1271: (void) close(f); ! 1272: } ! 1273: } ! 1274: (void) chmod(line, 0666); ! 1275: (void) chown(line, 0, 0); ! 1276: line[strlen("/dev/")] = 'p'; ! 1277: (void) chmod(line, 0666); ! 1278: (void) chown(line, 0, 0); ! 1279: } /* end of rmut */ ! 1280: #endif /* CRAY */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.