1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)sys_term.c 8.4 (Berkeley) 05/30/95"; 10 #endif /* not lint */ 11 12 #include "telnetd.h" 13 #include "pathnames.h" 14 15 #if defined(AUTHENTICATION) 16 #include <libtelnet/auth.h> 17 #endif 18 19 #if defined(CRAY) || defined(__hpux) 20 # define PARENT_DOES_UTMP 21 #endif 22 23 #ifdef NEWINIT 24 #include <initreq.h> 25 int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */ 26 #else /* NEWINIT*/ 27 # ifdef UTMPX 28 # include <utmpx.h> 29 struct utmpx wtmp; 30 # else 31 # include <utmp.h> 32 struct utmp wtmp; 33 # endif /* UTMPX */ 34 35 int utmp_len = sizeof(wtmp.ut_host); 36 # ifndef PARENT_DOES_UTMP 37 char wtmpf[] = "/usr/adm/wtmp"; 38 char utmpf[] = "/etc/utmp"; 39 # else /* PARENT_DOES_UTMP */ 40 char wtmpf[] = "/etc/wtmp"; 41 # endif /* PARENT_DOES_UTMP */ 42 43 # ifdef CRAY 44 #include <tmpdir.h> 45 #include <sys/wait.h> 46 # if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') 47 # define UNICOS7x 48 # endif 49 50 # ifdef UNICOS7x 51 #include <sys/sysv.h> 52 #include <sys/secstat.h> 53 extern int secflag; 54 extern struct sysv sysv; 55 # endif /* UNICOS7x */ 56 # endif /* CRAY */ 57 #endif /* NEWINIT */ 58 59 #ifdef STREAMSPTY 60 #include <sac.h> 61 #include <sys/stropts.h> 62 #endif 63 64 #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 65 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 66 67 #ifdef STREAMS 68 #include <sys/stream.h> 69 #endif 70 #ifdef __hpux 71 #include <sys/resource.h> 72 #include <sys/proc.h> 73 #endif 74 #include <sys/tty.h> 75 #ifdef t_erase 76 #undef t_erase 77 #undef t_kill 78 #undef t_intrc 79 #undef t_quitc 80 #undef t_startc 81 #undef t_stopc 82 #undef t_eofc 83 #undef t_brkc 84 #undef t_suspc 85 #undef t_dsuspc 86 #undef t_rprntc 87 #undef t_flushc 88 #undef t_werasc 89 #undef t_lnextc 90 #endif 91 92 #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 93 # define EXTPROC 0400 94 #endif 95 96 #ifndef USE_TERMIO 97 struct termbuf { 98 struct sgttyb sg; 99 struct tchars tc; 100 struct ltchars ltc; 101 int state; 102 int lflags; 103 } termbuf, termbuf2; 104 # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 105 # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 106 # define cfgetospeed(tp) (tp)->sg.sg_ospeed 107 # define cfgetispeed(tp) (tp)->sg.sg_ispeed 108 #else /* USE_TERMIO */ 109 # ifdef SYSV_TERMIO 110 # define termios termio 111 # endif 112 # ifndef TCSANOW 113 # ifdef TCSETS 114 # define TCSANOW TCSETS 115 # define TCSADRAIN TCSETSW 116 # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 117 # else 118 # ifdef TCSETA 119 # define TCSANOW TCSETA 120 # define TCSADRAIN TCSETAW 121 # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 122 # else 123 # define TCSANOW TIOCSETA 124 # define TCSADRAIN TIOCSETAW 125 # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 126 # endif 127 # endif 128 # define tcsetattr(f, a, t) ioctl(f, a, t) 129 # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 130 (tp)->c_cflag |= (val) 131 # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 132 # ifdef CIBAUD 133 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 134 (tp)->c_cflag |= ((val)<<IBSHIFT) 135 # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 136 # else 137 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 138 (tp)->c_cflag |= (val) 139 # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 140 # endif 141 # endif /* TCSANOW */ 142 struct termios termbuf, termbuf2; /* pty control structure */ 143 # ifdef STREAMSPTY 144 int ttyfd = -1; 145 # endif 146 #endif /* USE_TERMIO */ 147 148 /* 149 * init_termbuf() 150 * copy_termbuf(cp) 151 * set_termbuf() 152 * 153 * These three routines are used to get and set the "termbuf" structure 154 * to and from the kernel. init_termbuf() gets the current settings. 155 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 156 * set_termbuf() writes the structure into the kernel. 157 */ 158 159 void 160 init_termbuf() 161 { 162 #ifndef USE_TERMIO 163 (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 164 (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 165 (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 166 # ifdef TIOCGSTATE 167 (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 168 # endif 169 #else 170 # ifdef STREAMSPTY 171 (void) tcgetattr(ttyfd, &termbuf); 172 # else 173 (void) tcgetattr(pty, &termbuf); 174 # endif 175 #endif 176 termbuf2 = termbuf; 177 } 178 179 #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 180 void 181 copy_termbuf(cp, len) 182 char *cp; 183 int len; 184 { 185 if (len > sizeof(termbuf)) 186 len = sizeof(termbuf); 187 memmove((char *)&termbuf, cp, len); 188 termbuf2 = termbuf; 189 } 190 #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 191 192 void 193 set_termbuf() 194 { 195 /* 196 * Only make the necessary changes. 197 */ 198 #ifndef USE_TERMIO 199 if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, 200 sizeof(termbuf.sg))) 201 (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 202 if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, 203 sizeof(termbuf.tc))) 204 (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 205 if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 206 sizeof(termbuf.ltc))) 207 (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 208 if (termbuf.lflags != termbuf2.lflags) 209 (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 210 #else /* USE_TERMIO */ 211 if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 212 # ifdef STREAMSPTY 213 (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 214 # else 215 (void) tcsetattr(pty, TCSANOW, &termbuf); 216 # endif 217 # if defined(CRAY2) && defined(UNICOS5) 218 needtermstat = 1; 219 # endif 220 #endif /* USE_TERMIO */ 221 } 222 223 224 /* 225 * spcset(func, valp, valpp) 226 * 227 * This function takes various special characters (func), and 228 * sets *valp to the current value of that character, and 229 * *valpp to point to where in the "termbuf" structure that 230 * value is kept. 231 * 232 * It returns the SLC_ level of support for this function. 233 */ 234 235 #ifndef USE_TERMIO 236 int 237 spcset(func, valp, valpp) 238 int func; 239 cc_t *valp; 240 cc_t **valpp; 241 { 242 switch(func) { 243 case SLC_EOF: 244 *valp = termbuf.tc.t_eofc; 245 *valpp = (cc_t *)&termbuf.tc.t_eofc; 246 return(SLC_VARIABLE); 247 case SLC_EC: 248 *valp = termbuf.sg.sg_erase; 249 *valpp = (cc_t *)&termbuf.sg.sg_erase; 250 return(SLC_VARIABLE); 251 case SLC_EL: 252 *valp = termbuf.sg.sg_kill; 253 *valpp = (cc_t *)&termbuf.sg.sg_kill; 254 return(SLC_VARIABLE); 255 case SLC_IP: 256 *valp = termbuf.tc.t_intrc; 257 *valpp = (cc_t *)&termbuf.tc.t_intrc; 258 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 259 case SLC_ABORT: 260 *valp = termbuf.tc.t_quitc; 261 *valpp = (cc_t *)&termbuf.tc.t_quitc; 262 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 263 case SLC_XON: 264 *valp = termbuf.tc.t_startc; 265 *valpp = (cc_t *)&termbuf.tc.t_startc; 266 return(SLC_VARIABLE); 267 case SLC_XOFF: 268 *valp = termbuf.tc.t_stopc; 269 *valpp = (cc_t *)&termbuf.tc.t_stopc; 270 return(SLC_VARIABLE); 271 case SLC_AO: 272 *valp = termbuf.ltc.t_flushc; 273 *valpp = (cc_t *)&termbuf.ltc.t_flushc; 274 return(SLC_VARIABLE); 275 case SLC_SUSP: 276 *valp = termbuf.ltc.t_suspc; 277 *valpp = (cc_t *)&termbuf.ltc.t_suspc; 278 return(SLC_VARIABLE); 279 case SLC_EW: 280 *valp = termbuf.ltc.t_werasc; 281 *valpp = (cc_t *)&termbuf.ltc.t_werasc; 282 return(SLC_VARIABLE); 283 case SLC_RP: 284 *valp = termbuf.ltc.t_rprntc; 285 *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 286 return(SLC_VARIABLE); 287 case SLC_LNEXT: 288 *valp = termbuf.ltc.t_lnextc; 289 *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 290 return(SLC_VARIABLE); 291 case SLC_FORW1: 292 *valp = termbuf.tc.t_brkc; 293 *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 294 return(SLC_VARIABLE); 295 case SLC_BRK: 296 case SLC_SYNCH: 297 case SLC_AYT: 298 case SLC_EOR: 299 *valp = (cc_t)0; 300 *valpp = (cc_t *)0; 301 return(SLC_DEFAULT); 302 default: 303 *valp = (cc_t)0; 304 *valpp = (cc_t *)0; 305 return(SLC_NOSUPPORT); 306 } 307 } 308 309 #else /* USE_TERMIO */ 310 311 int 312 spcset(func, valp, valpp) 313 int func; 314 cc_t *valp; 315 cc_t **valpp; 316 { 317 318 #define setval(a, b) *valp = termbuf.c_cc[a]; \ 319 *valpp = &termbuf.c_cc[a]; \ 320 return(b); 321 #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 322 323 switch(func) { 324 case SLC_EOF: 325 setval(VEOF, SLC_VARIABLE); 326 case SLC_EC: 327 setval(VERASE, SLC_VARIABLE); 328 case SLC_EL: 329 setval(VKILL, SLC_VARIABLE); 330 case SLC_IP: 331 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 332 case SLC_ABORT: 333 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 334 case SLC_XON: 335 #ifdef VSTART 336 setval(VSTART, SLC_VARIABLE); 337 #else 338 defval(0x13); 339 #endif 340 case SLC_XOFF: 341 #ifdef VSTOP 342 setval(VSTOP, SLC_VARIABLE); 343 #else 344 defval(0x11); 345 #endif 346 case SLC_EW: 347 #ifdef VWERASE 348 setval(VWERASE, SLC_VARIABLE); 349 #else 350 defval(0); 351 #endif 352 case SLC_RP: 353 #ifdef VREPRINT 354 setval(VREPRINT, SLC_VARIABLE); 355 #else 356 defval(0); 357 #endif 358 case SLC_LNEXT: 359 #ifdef VLNEXT 360 setval(VLNEXT, SLC_VARIABLE); 361 #else 362 defval(0); 363 #endif 364 case SLC_AO: 365 #if !defined(VDISCARD) && defined(VFLUSHO) 366 # define VDISCARD VFLUSHO 367 #endif 368 #ifdef VDISCARD 369 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 370 #else 371 defval(0); 372 #endif 373 case SLC_SUSP: 374 #ifdef VSUSP 375 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 376 #else 377 defval(0); 378 #endif 379 #ifdef VEOL 380 case SLC_FORW1: 381 setval(VEOL, SLC_VARIABLE); 382 #endif 383 #ifdef VEOL2 384 case SLC_FORW2: 385 setval(VEOL2, SLC_VARIABLE); 386 #endif 387 case SLC_AYT: 388 #ifdef VSTATUS 389 setval(VSTATUS, SLC_VARIABLE); 390 #else 391 defval(0); 392 #endif 393 394 case SLC_BRK: 395 case SLC_SYNCH: 396 case SLC_EOR: 397 defval(0); 398 399 default: 400 *valp = 0; 401 *valpp = 0; 402 return(SLC_NOSUPPORT); 403 } 404 } 405 #endif /* USE_TERMIO */ 406 407 #ifdef CRAY 408 /* 409 * getnpty() 410 * 411 * Return the number of pty's configured into the system. 412 */ 413 int 414 getnpty() 415 { 416 #ifdef _SC_CRAY_NPTY 417 int numptys; 418 419 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 420 return numptys; 421 else 422 #endif /* _SC_CRAY_NPTY */ 423 return 128; 424 } 425 #endif /* CRAY */ 426 427 #ifndef convex 428 /* 429 * getpty() 430 * 431 * Allocate a pty. As a side effect, the external character 432 * array "line" contains the name of the slave side. 433 * 434 * Returns the file descriptor of the opened pty. 435 */ 436 #ifndef __GNUC__ 437 char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 438 #else 439 static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 440 char *line = Xline; 441 #endif 442 #ifdef CRAY 443 char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 444 #endif /* CRAY */ 445 446 int 447 getpty(ptynum) 448 int *ptynum; 449 { 450 register int p; 451 #ifdef STREAMSPTY 452 int t; 453 char *ptsname(); 454 455 p = open("/dev/ptmx", 2); 456 if (p > 0) { 457 grantpt(p); 458 unlockpt(p); 459 strcpy(line, ptsname(p)); 460 return(p); 461 } 462 463 #else /* ! STREAMSPTY */ 464 #ifndef CRAY 465 register char *cp, *p1, *p2; 466 register int i; 467 #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 468 int dummy; 469 #endif 470 471 #ifndef __hpux 472 (void) sprintf(line, "/dev/ptyXX"); 473 p1 = &line[8]; 474 p2 = &line[9]; 475 #else 476 (void) sprintf(line, "/dev/ptym/ptyXX"); 477 p1 = &line[13]; 478 p2 = &line[14]; 479 #endif 480 481 for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { 482 struct stat stb; 483 484 *p1 = *cp; 485 *p2 = '0'; 486 /* 487 * This stat() check is just to keep us from 488 * looping through all 256 combinations if there 489 * aren't that many ptys available. 490 */ 491 if (stat(line, &stb) < 0) 492 break; 493 for (i = 0; i < 16; i++) { 494 *p2 = "0123456789abcdef"[i]; 495 p = open(line, 2); 496 if (p > 0) { 497 #ifndef __hpux 498 line[5] = 't'; 499 #else 500 for (p1 = &line[8]; *p1; p1++) 501 *p1 = *(p1+1); 502 line[9] = 't'; 503 #endif 504 chown(line, 0, 0); 505 chmod(line, 0600); 506 #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 507 if (ioctl(p, TIOCGPGRP, &dummy) == 0 508 || errno != EIO) { 509 chmod(line, 0666); 510 close(p); 511 line[5] = 'p'; 512 } else 513 #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ 514 return(p); 515 } 516 } 517 } 518 #else /* CRAY */ 519 extern lowpty, highpty; 520 struct stat sb; 521 522 for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { 523 (void) sprintf(myline, "/dev/pty/%03d", *ptynum); 524 p = open(myline, 2); 525 if (p < 0) 526 continue; 527 (void) sprintf(line, "/dev/ttyp%03d", *ptynum); 528 /* 529 * Here are some shenanigans to make sure that there 530 * are no listeners lurking on the line. 531 */ 532 if(stat(line, &sb) < 0) { 533 (void) close(p); 534 continue; 535 } 536 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 537 chown(line, 0, 0); 538 chmod(line, 0600); 539 (void)close(p); 540 p = open(myline, 2); 541 if (p < 0) 542 continue; 543 } 544 /* 545 * Now it should be safe...check for accessability. 546 */ 547 if (access(line, 6) == 0) 548 return(p); 549 else { 550 /* no tty side to pty so skip it */ 551 (void) close(p); 552 } 553 } 554 #endif /* CRAY */ 555 #endif /* STREAMSPTY */ 556 return(-1); 557 } 558 #endif /* convex */ 559 560 #ifdef LINEMODE 561 /* 562 * tty_flowmode() Find out if flow control is enabled or disabled. 563 * tty_linemode() Find out if linemode (external processing) is enabled. 564 * tty_setlinemod(on) Turn on/off linemode. 565 * tty_isecho() Find out if echoing is turned on. 566 * tty_setecho(on) Enable/disable character echoing. 567 * tty_israw() Find out if terminal is in RAW mode. 568 * tty_binaryin(on) Turn on/off BINARY on input. 569 * tty_binaryout(on) Turn on/off BINARY on output. 570 * tty_isediting() Find out if line editing is enabled. 571 * tty_istrapsig() Find out if signal trapping is enabled. 572 * tty_setedit(on) Turn on/off line editing. 573 * tty_setsig(on) Turn on/off signal trapping. 574 * tty_issofttab() Find out if tab expansion is enabled. 575 * tty_setsofttab(on) Turn on/off soft tab expansion. 576 * tty_islitecho() Find out if typed control chars are echoed literally 577 * tty_setlitecho() Turn on/off literal echo of control chars 578 * tty_tspeed(val) Set transmit speed to val. 579 * tty_rspeed(val) Set receive speed to val. 580 */ 581 582 #ifdef convex 583 static int linestate; 584 #endif 585 586 int 587 tty_linemode() 588 { 589 #ifndef convex 590 #ifndef USE_TERMIO 591 return(termbuf.state & TS_EXTPROC); 592 #else 593 return(termbuf.c_lflag & EXTPROC); 594 #endif 595 #else 596 return(linestate); 597 #endif 598 } 599 600 void 601 tty_setlinemode(on) 602 int on; 603 { 604 #ifdef TIOCEXT 605 # ifndef convex 606 set_termbuf(); 607 # else 608 linestate = on; 609 # endif 610 (void) ioctl(pty, TIOCEXT, (char *)&on); 611 # ifndef convex 612 init_termbuf(); 613 # endif 614 #else /* !TIOCEXT */ 615 # ifdef EXTPROC 616 if (on) 617 termbuf.c_lflag |= EXTPROC; 618 else 619 termbuf.c_lflag &= ~EXTPROC; 620 # endif 621 #endif /* TIOCEXT */ 622 } 623 #endif /* LINEMODE */ 624 625 int 626 tty_isecho() 627 { 628 #ifndef USE_TERMIO 629 return (termbuf.sg.sg_flags & ECHO); 630 #else 631 return (termbuf.c_lflag & ECHO); 632 #endif 633 } 634 635 int 636 tty_flowmode() 637 { 638 #ifndef USE_TERMIO 639 return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 640 #else 641 return((termbuf.c_iflag & IXON) ? 1 : 0); 642 #endif 643 } 644 645 int 646 tty_restartany() 647 { 648 #ifndef USE_TERMIO 649 # ifdef DECCTQ 650 return((termbuf.lflags & DECCTQ) ? 0 : 1); 651 # else 652 return(-1); 653 # endif 654 #else 655 return((termbuf.c_iflag & IXANY) ? 1 : 0); 656 #endif 657 } 658 659 void 660 tty_setecho(on) 661 int on; 662 { 663 #ifndef USE_TERMIO 664 if (on) 665 termbuf.sg.sg_flags |= ECHO|CRMOD; 666 else 667 termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 668 #else 669 if (on) 670 termbuf.c_lflag |= ECHO; 671 else 672 termbuf.c_lflag &= ~ECHO; 673 #endif 674 } 675 676 int 677 tty_israw() 678 { 679 #ifndef USE_TERMIO 680 return(termbuf.sg.sg_flags & RAW); 681 #else 682 return(!(termbuf.c_lflag & ICANON)); 683 #endif 684 } 685 686 #if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 687 int 688 tty_setraw(on) 689 { 690 # ifndef USE_TERMIO 691 if (on) 692 termbuf.sg.sg_flags |= RAW; 693 else 694 termbuf.sg.sg_flags &= ~RAW; 695 # else 696 if (on) 697 termbuf.c_lflag &= ~ICANON; 698 else 699 termbuf.c_lflag |= ICANON; 700 # endif 701 } 702 #endif 703 704 void 705 tty_binaryin(on) 706 int on; 707 { 708 #ifndef USE_TERMIO 709 if (on) 710 termbuf.lflags |= LPASS8; 711 else 712 termbuf.lflags &= ~LPASS8; 713 #else 714 if (on) { 715 termbuf.c_iflag &= ~ISTRIP; 716 } else { 717 termbuf.c_iflag |= ISTRIP; 718 } 719 #endif 720 } 721 722 void 723 tty_binaryout(on) 724 int on; 725 { 726 #ifndef USE_TERMIO 727 if (on) 728 termbuf.lflags |= LLITOUT; 729 else 730 termbuf.lflags &= ~LLITOUT; 731 #else 732 if (on) { 733 termbuf.c_cflag &= ~(CSIZE|PARENB); 734 termbuf.c_cflag |= CS8; 735 termbuf.c_oflag &= ~OPOST; 736 } else { 737 termbuf.c_cflag &= ~CSIZE; 738 termbuf.c_cflag |= CS7|PARENB; 739 termbuf.c_oflag |= OPOST; 740 } 741 #endif 742 } 743 744 int 745 tty_isbinaryin() 746 { 747 #ifndef USE_TERMIO 748 return(termbuf.lflags & LPASS8); 749 #else 750 return(!(termbuf.c_iflag & ISTRIP)); 751 #endif 752 } 753 754 int 755 tty_isbinaryout() 756 { 757 #ifndef USE_TERMIO 758 return(termbuf.lflags & LLITOUT); 759 #else 760 return(!(termbuf.c_oflag&OPOST)); 761 #endif 762 } 763 764 #ifdef LINEMODE 765 int 766 tty_isediting() 767 { 768 #ifndef USE_TERMIO 769 return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 770 #else 771 return(termbuf.c_lflag & ICANON); 772 #endif 773 } 774 775 int 776 tty_istrapsig() 777 { 778 #ifndef USE_TERMIO 779 return(!(termbuf.sg.sg_flags&RAW)); 780 #else 781 return(termbuf.c_lflag & ISIG); 782 #endif 783 } 784 785 void 786 tty_setedit(on) 787 int on; 788 { 789 #ifndef USE_TERMIO 790 if (on) 791 termbuf.sg.sg_flags &= ~CBREAK; 792 else 793 termbuf.sg.sg_flags |= CBREAK; 794 #else 795 if (on) 796 termbuf.c_lflag |= ICANON; 797 else 798 termbuf.c_lflag &= ~ICANON; 799 #endif 800 } 801 802 void 803 tty_setsig(on) 804 int on; 805 { 806 #ifndef USE_TERMIO 807 if (on) 808 ; 809 #else 810 if (on) 811 termbuf.c_lflag |= ISIG; 812 else 813 termbuf.c_lflag &= ~ISIG; 814 #endif 815 } 816 #endif /* LINEMODE */ 817 818 int 819 tty_issofttab() 820 { 821 #ifndef USE_TERMIO 822 return (termbuf.sg.sg_flags & XTABS); 823 #else 824 # ifdef OXTABS 825 return (termbuf.c_oflag & OXTABS); 826 # endif 827 # ifdef TABDLY 828 return ((termbuf.c_oflag & TABDLY) == TAB3); 829 # endif 830 #endif 831 } 832 833 void 834 tty_setsofttab(on) 835 int on; 836 { 837 #ifndef USE_TERMIO 838 if (on) 839 termbuf.sg.sg_flags |= XTABS; 840 else 841 termbuf.sg.sg_flags &= ~XTABS; 842 #else 843 if (on) { 844 # ifdef OXTABS 845 termbuf.c_oflag |= OXTABS; 846 # endif 847 # ifdef TABDLY 848 termbuf.c_oflag &= ~TABDLY; 849 termbuf.c_oflag |= TAB3; 850 # endif 851 } else { 852 # ifdef OXTABS 853 termbuf.c_oflag &= ~OXTABS; 854 # endif 855 # ifdef TABDLY 856 termbuf.c_oflag &= ~TABDLY; 857 termbuf.c_oflag |= TAB0; 858 # endif 859 } 860 #endif 861 } 862 863 int 864 tty_islitecho() 865 { 866 #ifndef USE_TERMIO 867 return (!(termbuf.lflags & LCTLECH)); 868 #else 869 # ifdef ECHOCTL 870 return (!(termbuf.c_lflag & ECHOCTL)); 871 # endif 872 # ifdef TCTLECH 873 return (!(termbuf.c_lflag & TCTLECH)); 874 # endif 875 # if !defined(ECHOCTL) && !defined(TCTLECH) 876 return (0); /* assumes ctl chars are echoed '^x' */ 877 # endif 878 #endif 879 } 880 881 void 882 tty_setlitecho(on) 883 int on; 884 { 885 #ifndef USE_TERMIO 886 if (on) 887 termbuf.lflags &= ~LCTLECH; 888 else 889 termbuf.lflags |= LCTLECH; 890 #else 891 # ifdef ECHOCTL 892 if (on) 893 termbuf.c_lflag &= ~ECHOCTL; 894 else 895 termbuf.c_lflag |= ECHOCTL; 896 # endif 897 # ifdef TCTLECH 898 if (on) 899 termbuf.c_lflag &= ~TCTLECH; 900 else 901 termbuf.c_lflag |= TCTLECH; 902 # endif 903 #endif 904 } 905 906 int 907 tty_iscrnl() 908 { 909 #ifndef USE_TERMIO 910 return (termbuf.sg.sg_flags & CRMOD); 911 #else 912 return (termbuf.c_iflag & ICRNL); 913 #endif 914 } 915 916 /* 917 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 918 */ 919 #if B4800 != 4800 920 #define DECODE_BAUD 921 #endif 922 923 #ifdef DECODE_BAUD 924 925 /* 926 * A table of available terminal speeds 927 */ 928 struct termspeeds { 929 int speed; 930 int value; 931 } termspeeds[] = { 932 { 0, B0 }, { 50, B50 }, { 75, B75 }, 933 { 110, B110 }, { 134, B134 }, { 150, B150 }, 934 { 200, B200 }, { 300, B300 }, { 600, B600 }, 935 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 936 { 4800, B4800 }, 937 #ifdef B7200 938 { 7200, B7200 }, 939 #endif 940 { 9600, B9600 }, 941 #ifdef B14400 942 { 14400, B14400 }, 943 #endif 944 #ifdef B19200 945 { 19200, B19200 }, 946 #endif 947 #ifdef B28800 948 { 28800, B28800 }, 949 #endif 950 #ifdef B38400 951 { 38400, B38400 }, 952 #endif 953 #ifdef B57600 954 { 57600, B57600 }, 955 #endif 956 #ifdef B115200 957 { 115200, B115200 }, 958 #endif 959 #ifdef B230400 960 { 230400, B230400 }, 961 #endif 962 { -1, 0 } 963 }; 964 #endif /* DECODE_BUAD */ 965 966 void 967 tty_tspeed(val) 968 int val; 969 { 970 #ifdef DECODE_BAUD 971 register struct termspeeds *tp; 972 973 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 974 ; 975 if (tp->speed == -1) /* back up to last valid value */ 976 --tp; 977 cfsetospeed(&termbuf, tp->value); 978 #else /* DECODE_BUAD */ 979 cfsetospeed(&termbuf, val); 980 #endif /* DECODE_BUAD */ 981 } 982 983 void 984 tty_rspeed(val) 985 int val; 986 { 987 #ifdef DECODE_BAUD 988 register struct termspeeds *tp; 989 990 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 991 ; 992 if (tp->speed == -1) /* back up to last valid value */ 993 --tp; 994 cfsetispeed(&termbuf, tp->value); 995 #else /* DECODE_BAUD */ 996 cfsetispeed(&termbuf, val); 997 #endif /* DECODE_BAUD */ 998 } 999 1000 #if defined(CRAY2) && defined(UNICOS5) 1001 int 1002 tty_isnewmap() 1003 { 1004 return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 1005 !(termbuf.c_oflag & ONLRET)); 1006 } 1007 #endif 1008 1009 #ifdef PARENT_DOES_UTMP 1010 # ifndef NEWINIT 1011 extern struct utmp wtmp; 1012 extern char wtmpf[]; 1013 # else /* NEWINIT */ 1014 int gotalarm; 1015 1016 /* ARGSUSED */ 1017 void 1018 nologinproc(sig) 1019 int sig; 1020 { 1021 gotalarm++; 1022 } 1023 # endif /* NEWINIT */ 1024 #endif /* PARENT_DOES_UTMP */ 1025 1026 #ifndef NEWINIT 1027 # ifdef PARENT_DOES_UTMP 1028 extern void utmp_sig_init P((void)); 1029 extern void utmp_sig_reset P((void)); 1030 extern void utmp_sig_wait P((void)); 1031 extern void utmp_sig_notify P((int)); 1032 # endif /* PARENT_DOES_UTMP */ 1033 #endif 1034 1035 /* 1036 * getptyslave() 1037 * 1038 * Open the slave side of the pty, and do any initialization 1039 * that is necessary. The return value is a file descriptor 1040 * for the slave side. 1041 */ 1042 int 1043 getptyslave() 1044 { 1045 register int t = -1; 1046 1047 #if !defined(CRAY) || !defined(NEWINIT) 1048 # ifdef LINEMODE 1049 int waslm; 1050 # endif 1051 # ifdef TIOCGWINSZ 1052 struct winsize ws; 1053 extern int def_row, def_col; 1054 # endif 1055 extern int def_tspeed, def_rspeed; 1056 /* 1057 * Opening the slave side may cause initilization of the 1058 * kernel tty structure. We need remember the state of 1059 * if linemode was turned on 1060 * terminal window size 1061 * terminal speed 1062 * so that we can re-set them if we need to. 1063 */ 1064 # ifdef LINEMODE 1065 waslm = tty_linemode(); 1066 # endif 1067 1068 1069 /* 1070 * Make sure that we don't have a controlling tty, and 1071 * that we are the session (process group) leader. 1072 */ 1073 # ifdef TIOCNOTTY 1074 t = open(_PATH_TTY, O_RDWR); 1075 if (t >= 0) { 1076 (void) ioctl(t, TIOCNOTTY, (char *)0); 1077 (void) close(t); 1078 } 1079 # endif 1080 1081 1082 # ifdef PARENT_DOES_UTMP 1083 /* 1084 * Wait for our parent to get the utmp stuff to get done. 1085 */ 1086 utmp_sig_wait(); 1087 # endif 1088 1089 t = cleanopen(line); 1090 if (t < 0) 1091 fatalperror(net, line); 1092 1093 #ifdef STREAMSPTY 1094 #ifdef USE_TERMIO 1095 ttyfd = t; 1096 #endif 1097 if (ioctl(t, I_PUSH, "ptem") < 0) 1098 fatal(net, "I_PUSH ptem"); 1099 if (ioctl(t, I_PUSH, "ldterm") < 0) 1100 fatal(net, "I_PUSH ldterm"); 1101 if (ioctl(t, I_PUSH, "ttcompat") < 0) 1102 fatal(net, "I_PUSH ttcompat"); 1103 if (ioctl(pty, I_PUSH, "pckt") < 0) 1104 fatal(net, "I_PUSH pckt"); 1105 #endif 1106 1107 /* 1108 * set up the tty modes as we like them to be. 1109 */ 1110 init_termbuf(); 1111 # ifdef TIOCGWINSZ 1112 if (def_row || def_col) { 1113 memset((char *)&ws, 0, sizeof(ws)); 1114 ws.ws_col = def_col; 1115 ws.ws_row = def_row; 1116 (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 1117 } 1118 # endif 1119 1120 /* 1121 * Settings for sgtty based systems 1122 */ 1123 # ifndef USE_TERMIO 1124 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 1125 # endif /* USE_TERMIO */ 1126 1127 /* 1128 * Settings for UNICOS (and HPUX) 1129 */ 1130 # if defined(CRAY) || defined(__hpux) 1131 termbuf.c_oflag = OPOST|ONLCR|TAB3; 1132 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 1133 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 1134 termbuf.c_cflag = EXTB|HUPCL|CS8; 1135 # endif 1136 1137 /* 1138 * Settings for all other termios/termio based 1139 * systems, other than 4.4BSD. In 4.4BSD the 1140 * kernel does the initial terminal setup. 1141 */ 1142 # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 1143 # ifndef OXTABS 1144 # define OXTABS 0 1145 # endif 1146 termbuf.c_lflag |= ECHO; 1147 termbuf.c_oflag |= ONLCR|OXTABS; 1148 termbuf.c_iflag |= ICRNL; 1149 termbuf.c_iflag &= ~IXOFF; 1150 # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 1151 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 1152 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 1153 # ifdef LINEMODE 1154 if (waslm) 1155 tty_setlinemode(1); 1156 # endif /* LINEMODE */ 1157 1158 /* 1159 * Set the tty modes, and make this our controlling tty. 1160 */ 1161 set_termbuf(); 1162 if (login_tty(t) == -1) 1163 fatalperror(net, "login_tty"); 1164 #endif /* !defined(CRAY) || !defined(NEWINIT) */ 1165 if (net > 2) 1166 (void) close(net); 1167 #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1168 /* 1169 * Leave the pty open so that we can write out the rlogin 1170 * protocol for /bin/login, if the authentication works. 1171 */ 1172 #else 1173 if (pty > 2) { 1174 (void) close(pty); 1175 pty = -1; 1176 } 1177 #endif 1178 } 1179 1180 #if !defined(CRAY) || !defined(NEWINIT) 1181 #ifndef O_NOCTTY 1182 #define O_NOCTTY 0 1183 #endif 1184 /* 1185 * Open the specified slave side of the pty, 1186 * making sure that we have a clean tty. 1187 */ 1188 int 1189 cleanopen(line) 1190 char *line; 1191 { 1192 register int t; 1193 #ifdef UNICOS7x 1194 struct secstat secbuf; 1195 #endif /* UNICOS7x */ 1196 1197 #ifndef STREAMSPTY 1198 /* 1199 * Make sure that other people can't open the 1200 * slave side of the connection. 1201 */ 1202 (void) chown(line, 0, 0); 1203 (void) chmod(line, 0600); 1204 #endif 1205 1206 # if !defined(CRAY) && (BSD > 43) 1207 (void) revoke(line); 1208 # endif 1209 #ifdef UNICOS7x 1210 if (secflag) { 1211 if (secstat(line, &secbuf) < 0) 1212 return(-1); 1213 if (setulvl(secbuf.st_slevel) < 0) 1214 return(-1); 1215 if (setucmp(secbuf.st_compart) < 0) 1216 return(-1); 1217 } 1218 #endif /* UNICOS7x */ 1219 1220 t = open(line, O_RDWR|O_NOCTTY); 1221 1222 #ifdef UNICOS7x 1223 if (secflag) { 1224 if (setulvl(sysv.sy_minlvl) < 0) 1225 return(-1); 1226 if (setucmp(0) < 0) 1227 return(-1); 1228 } 1229 #endif /* UNICOS7x */ 1230 1231 if (t < 0) 1232 return(-1); 1233 1234 /* 1235 * Hangup anybody else using this ttyp, then reopen it for 1236 * ourselves. 1237 */ 1238 # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 1239 (void) signal(SIGHUP, SIG_IGN); 1240 vhangup(); 1241 (void) signal(SIGHUP, SIG_DFL); 1242 t = open(line, O_RDWR|O_NOCTTY); 1243 if (t < 0) 1244 return(-1); 1245 # endif 1246 # if defined(CRAY) && defined(TCVHUP) 1247 { 1248 register int i; 1249 (void) signal(SIGHUP, SIG_IGN); 1250 (void) ioctl(t, TCVHUP, (char *)0); 1251 (void) signal(SIGHUP, SIG_DFL); 1252 1253 #ifdef UNICOS7x 1254 if (secflag) { 1255 if (secstat(line, &secbuf) < 0) 1256 return(-1); 1257 if (setulvl(secbuf.st_slevel) < 0) 1258 return(-1); 1259 if (setucmp(secbuf.st_compart) < 0) 1260 return(-1); 1261 } 1262 #endif /* UNICOS7x */ 1263 1264 i = open(line, O_RDWR); 1265 1266 #ifdef UNICOS7x 1267 if (secflag) { 1268 if (setulvl(sysv.sy_minlvl) < 0) 1269 return(-1); 1270 if (setucmp(0) < 0) 1271 return(-1); 1272 } 1273 #endif /* UNICOS7x */ 1274 1275 if (i < 0) 1276 return(-1); 1277 (void) close(t); 1278 t = i; 1279 } 1280 # endif /* defined(CRAY) && defined(TCVHUP) */ 1281 return(t); 1282 } 1283 #endif /* !defined(CRAY) || !defined(NEWINIT) */ 1284 1285 #if BSD <= 43 1286 1287 int 1288 login_tty(t) 1289 int t; 1290 { 1291 if (setsid() < 0) { 1292 #ifdef ultrix 1293 /* 1294 * The setsid() may have failed because we 1295 * already have a pgrp == pid. Zero out 1296 * our pgrp and try again... 1297 */ 1298 if ((setpgrp(0, 0) < 0) || (setsid() < 0)) 1299 #endif 1300 fatalperror(net, "setsid()"); 1301 } 1302 # ifdef TIOCSCTTY 1303 if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 1304 fatalperror(net, "ioctl(sctty)"); 1305 # if defined(CRAY) 1306 /* 1307 * Close the hard fd to /dev/ttypXXX, and re-open through 1308 * the indirect /dev/tty interface. 1309 */ 1310 close(t); 1311 if ((t = open("/dev/tty", O_RDWR)) < 0) 1312 fatalperror(net, "open(/dev/tty)"); 1313 # endif 1314 # else 1315 /* 1316 * We get our controlling tty assigned as a side-effect 1317 * of opening up a tty device. But on BSD based systems, 1318 * this only happens if our process group is zero. The 1319 * setsid() call above may have set our pgrp, so clear 1320 * it out before opening the tty... 1321 */ 1322 # ifndef SOLARIS 1323 (void) setpgrp(0, 0); 1324 # else 1325 (void) setpgrp(); 1326 # endif 1327 close(open(line, O_RDWR)); 1328 # endif 1329 if (t != 0) 1330 (void) dup2(t, 0); 1331 if (t != 1) 1332 (void) dup2(t, 1); 1333 if (t != 2) 1334 (void) dup2(t, 2); 1335 if (t > 2) 1336 close(t); 1337 return(0); 1338 } 1339 #endif /* BSD <= 43 */ 1340 1341 #ifdef NEWINIT 1342 char *gen_id = "fe"; 1343 #endif 1344 1345 /* 1346 * startslave(host) 1347 * 1348 * Given a hostname, do whatever 1349 * is necessary to startup the login process on the slave side of the pty. 1350 */ 1351 1352 /* ARGSUSED */ 1353 void 1354 startslave(host, autologin, autoname) 1355 char *host; 1356 int autologin; 1357 char *autoname; 1358 { 1359 register int i; 1360 long time(); 1361 char name[256]; 1362 #ifdef NEWINIT 1363 extern char *ptyip; 1364 struct init_request request; 1365 void nologinproc(); 1366 register int n; 1367 #endif /* NEWINIT */ 1368 1369 #if defined(AUTHENTICATION) 1370 if (!autoname || !autoname[0]) 1371 autologin = 0; 1372 1373 if (autologin < auth_level) { 1374 fatal(net, "Authorization failed"); 1375 exit(1); 1376 } 1377 #endif 1378 1379 #ifndef NEWINIT 1380 # ifdef PARENT_DOES_UTMP 1381 utmp_sig_init(); 1382 # endif /* PARENT_DOES_UTMP */ 1383 1384 if ((i = fork()) < 0) 1385 fatalperror(net, "fork"); 1386 if (i) { 1387 # ifdef PARENT_DOES_UTMP 1388 /* 1389 * Cray parent will create utmp entry for child and send 1390 * signal to child to tell when done. Child waits for signal 1391 * before doing anything important. 1392 */ 1393 register int pid = i; 1394 void sigjob P((int)); 1395 1396 setpgrp(); 1397 utmp_sig_reset(); /* reset handler to default */ 1398 /* 1399 * Create utmp entry for child 1400 */ 1401 (void) time(&wtmp.ut_time); 1402 wtmp.ut_type = LOGIN_PROCESS; 1403 wtmp.ut_pid = pid; 1404 SCPYN(wtmp.ut_user, "LOGIN"); 1405 SCPYN(wtmp.ut_host, host); 1406 SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 1407 #ifndef __hpux 1408 SCPYN(wtmp.ut_id, wtmp.ut_line+3); 1409 #else 1410 SCPYN(wtmp.ut_id, wtmp.ut_line+7); 1411 #endif 1412 pututline(&wtmp); 1413 endutent(); 1414 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 1415 (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 1416 (void) close(i); 1417 } 1418 #ifdef CRAY 1419 (void) signal(WJSIGNAL, sigjob); 1420 #endif 1421 utmp_sig_notify(pid); 1422 # endif /* PARENT_DOES_UTMP */ 1423 } else { 1424 getptyslave(autologin); 1425 start_login(host, autologin, autoname); 1426 /*NOTREACHED*/ 1427 } 1428 #else /* NEWINIT */ 1429 1430 /* 1431 * Init will start up login process if we ask nicely. We only wait 1432 * for it to start up and begin normal telnet operation. 1433 */ 1434 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 1435 char tbuf[128]; 1436 (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 1437 fatalperror(net, tbuf); 1438 } 1439 memset((char *)&request, 0, sizeof(request)); 1440 request.magic = INIT_MAGIC; 1441 SCPYN(request.gen_id, gen_id); 1442 SCPYN(request.tty_id, &line[8]); 1443 SCPYN(request.host, host); 1444 SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 1445 #if !defined(UNICOS5) 1446 request.signal = SIGCLD; 1447 request.pid = getpid(); 1448 #endif 1449 #ifdef BFTPDAEMON 1450 /* 1451 * Are we working as the bftp daemon? 1452 */ 1453 if (bftpd) { 1454 SCPYN(request.exec_name, BFTPPATH); 1455 } 1456 #endif /* BFTPDAEMON */ 1457 if (write(i, (char *)&request, sizeof(request)) < 0) { 1458 char tbuf[128]; 1459 (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 1460 fatalperror(net, tbuf); 1461 } 1462 (void) close(i); 1463 (void) signal(SIGALRM, nologinproc); 1464 for (i = 0; ; i++) { 1465 char tbuf[128]; 1466 alarm(15); 1467 n = read(pty, ptyip, BUFSIZ); 1468 if (i == 3 || n >= 0 || !gotalarm) 1469 break; 1470 gotalarm = 0; 1471 sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 1472 (void) write(net, tbuf, strlen(tbuf)); 1473 } 1474 if (n < 0 && gotalarm) 1475 fatal(net, "/etc/init didn't start login process"); 1476 pcc += n; 1477 alarm(0); 1478 (void) signal(SIGALRM, SIG_DFL); 1479 1480 return; 1481 #endif /* NEWINIT */ 1482 } 1483 1484 char *envinit[3]; 1485 extern char **environ; 1486 1487 void 1488 init_env() 1489 { 1490 extern char *getenv(); 1491 char **envp; 1492 1493 envp = envinit; 1494 if (*envp = getenv("TZ")) 1495 *envp++ -= 3; 1496 #if defined(CRAY) || defined(__hpux) 1497 else 1498 *envp++ = "TZ=GMT0"; 1499 #endif 1500 *envp = 0; 1501 environ = envinit; 1502 } 1503 1504 #ifndef NEWINIT 1505 1506 /* 1507 * start_login(host) 1508 * 1509 * Assuming that we are now running as a child processes, this 1510 * function will turn us into the login process. 1511 */ 1512 1513 void 1514 start_login(host, autologin, name) 1515 char *host; 1516 int autologin; 1517 char *name; 1518 { 1519 register char *cp; 1520 register char **argv; 1521 char **addarg(); 1522 extern char *getenv(); 1523 #ifdef UTMPX 1524 register int pid = getpid(); 1525 struct utmpx utmpx; 1526 #endif 1527 #ifdef SOLARIS 1528 char *term; 1529 char termbuf[64]; 1530 #endif 1531 1532 #ifdef UTMPX 1533 /* 1534 * Create utmp entry for child 1535 */ 1536 1537 memset(&utmpx, 0, sizeof(utmpx)); 1538 SCPYN(utmpx.ut_user, ".telnet"); 1539 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 1540 utmpx.ut_pid = pid; 1541 utmpx.ut_id[0] = 't'; 1542 utmpx.ut_id[1] = 'n'; 1543 utmpx.ut_id[2] = SC_WILDC; 1544 utmpx.ut_id[3] = SC_WILDC; 1545 utmpx.ut_type = LOGIN_PROCESS; 1546 (void) time(&utmpx.ut_tv.tv_sec); 1547 if (pututxline(&utmpx) == NULL) 1548 fatal(net, "pututxline failed"); 1549 #endif 1550 1551 /* 1552 * -h : pass on name of host. 1553 * WARNING: -h is accepted by login if and only if 1554 * getuid() == 0. 1555 * -p : don't clobber the environment (so terminal type stays set). 1556 * 1557 * -f : force this login, he has already been authenticated 1558 */ 1559 argv = addarg(0, "login"); 1560 1561 #if !defined(NO_LOGIN_H) 1562 1563 # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1564 /* 1565 * Don't add the "-h host" option if we are going 1566 * to be adding the "-r host" option down below... 1567 */ 1568 if ((auth_level < 0) || (autologin != AUTH_VALID)) 1569 # endif 1570 { 1571 argv = addarg(argv, "-h"); 1572 argv = addarg(argv, host); 1573 #ifdef SOLARIS 1574 /* 1575 * SVR4 version of -h takes TERM= as second arg, or - 1576 */ 1577 term = getenv("TERM"); 1578 if (term == NULL || term[0] == 0) { 1579 term = "-"; 1580 } else { 1581 strcpy(termbuf, "TERM="); 1582 strncat(termbuf, term, sizeof(termbuf) - 6); 1583 term = termbuf; 1584 } 1585 argv = addarg(argv, term); 1586 #endif 1587 } 1588 #endif 1589 #if !defined(NO_LOGIN_P) 1590 argv = addarg(argv, "-p"); 1591 #endif 1592 #ifdef LINEMODE 1593 /* 1594 * Set the environment variable "LINEMODE" to either 1595 * "real" or "kludge" if we are operating in either 1596 * real or kludge linemode. 1597 */ 1598 if (lmodetype == REAL_LINEMODE) 1599 setenv("LINEMODE", "real", 1); 1600 # ifdef KLUDGELINEMODE 1601 else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) 1602 setenv("LINEMODE", "kludge", 1); 1603 # endif 1604 #endif 1605 #ifdef BFTPDAEMON 1606 /* 1607 * Are we working as the bftp daemon? If so, then ask login 1608 * to start bftp instead of shell. 1609 */ 1610 if (bftpd) { 1611 argv = addarg(argv, "-e"); 1612 argv = addarg(argv, BFTPPATH); 1613 } else 1614 #endif 1615 #if defined (SecurID) 1616 /* 1617 * don't worry about the -f that might get sent. 1618 * A -s is supposed to override it anyhow. 1619 */ 1620 if (require_SecurID) 1621 argv = addarg(argv, "-s"); 1622 #endif 1623 #if defined (AUTHENTICATION) 1624 if (auth_level >= 0 && autologin == AUTH_VALID) { 1625 # if !defined(NO_LOGIN_F) 1626 argv = addarg(argv, "-f"); 1627 argv = addarg(argv, name); 1628 # else 1629 # if defined(LOGIN_R) 1630 /* 1631 * We don't have support for "login -f", but we 1632 * can fool /bin/login into thinking that we are 1633 * rlogind, and allow us to log in without a 1634 * password. The rlogin protocol expects 1635 * local-user\0remote-user\0term/speed\0 1636 */ 1637 1638 if (pty > 2) { 1639 register char *cp; 1640 char speed[128]; 1641 int isecho, israw, xpty, len; 1642 extern int def_rspeed; 1643 # ifndef LOGIN_HOST 1644 /* 1645 * Tell login that we are coming from "localhost". 1646 * If we passed in the real host name, then the 1647 * user would have to allow .rhost access from 1648 * every machine that they want authenticated 1649 * access to work from, which sort of defeats 1650 * the purpose of an authenticated login... 1651 * So, we tell login that the session is coming 1652 * from "localhost", and the user will only have 1653 * to have "localhost" in their .rhost file. 1654 */ 1655 # define LOGIN_HOST "localhost" 1656 # endif 1657 argv = addarg(argv, "-r"); 1658 argv = addarg(argv, LOGIN_HOST); 1659 1660 xpty = pty; 1661 # ifndef STREAMSPTY 1662 pty = 0; 1663 # else 1664 ttyfd = 0; 1665 # endif 1666 init_termbuf(); 1667 isecho = tty_isecho(); 1668 israw = tty_israw(); 1669 if (isecho || !israw) { 1670 tty_setecho(0); /* Turn off echo */ 1671 tty_setraw(1); /* Turn on raw */ 1672 set_termbuf(); 1673 } 1674 len = strlen(name)+1; 1675 write(xpty, name, len); 1676 write(xpty, name, len); 1677 sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", 1678 (def_rspeed > 0) ? def_rspeed : 9600); 1679 len = strlen(speed)+1; 1680 write(xpty, speed, len); 1681 1682 if (isecho || !israw) { 1683 init_termbuf(); 1684 tty_setecho(isecho); 1685 tty_setraw(israw); 1686 set_termbuf(); 1687 if (!israw) { 1688 /* 1689 * Write a newline to ensure 1690 * that login will be able to 1691 * read the line... 1692 */ 1693 write(xpty, "\n", 1); 1694 } 1695 } 1696 pty = xpty; 1697 } 1698 # else 1699 argv = addarg(argv, name); 1700 # endif 1701 # endif 1702 } else 1703 #endif 1704 if (getenv("USER")) { 1705 argv = addarg(argv, getenv("USER")); 1706 #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 1707 { 1708 register char **cpp; 1709 for (cpp = environ; *cpp; cpp++) 1710 argv = addarg(argv, *cpp); 1711 } 1712 #endif 1713 /* 1714 * Assume that login will set the USER variable 1715 * correctly. For SysV systems, this means that 1716 * USER will no longer be set, just LOGNAME by 1717 * login. (The problem is that if the auto-login 1718 * fails, and the user then specifies a different 1719 * account name, he can get logged in with both 1720 * LOGNAME and USER in his environment, but the 1721 * USER value will be wrong. 1722 */ 1723 unsetenv("USER"); 1724 } 1725 #ifdef SOLARIS 1726 else { 1727 char **p; 1728 1729 argv = addarg(argv, ""); /* no login name */ 1730 for (p = environ; *p; p++) { 1731 argv = addarg(argv, *p); 1732 } 1733 } 1734 #endif /* SOLARIS */ 1735 #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1736 if (pty > 2) 1737 close(pty); 1738 #endif 1739 closelog(); 1740 /* 1741 * This sleep(1) is in here so that telnetd can 1742 * finish up with the tty. There's a race condition 1743 * the login banner message gets lost... 1744 */ 1745 sleep(1); 1746 execv(_PATH_LOGIN, argv); 1747 1748 syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 1749 fatalperror(net, _PATH_LOGIN); 1750 /*NOTREACHED*/ 1751 } 1752 1753 char ** 1754 addarg(argv, val) 1755 register char **argv; 1756 register char *val; 1757 { 1758 register char **cpp; 1759 1760 if (argv == NULL) { 1761 /* 1762 * 10 entries, a leading length, and a null 1763 */ 1764 argv = (char **)malloc(sizeof(*argv) * 12); 1765 if (argv == NULL) 1766 return(NULL); 1767 *argv++ = (char *)10; 1768 *argv = (char *)0; 1769 } 1770 for (cpp = argv; *cpp; cpp++) 1771 ; 1772 if (cpp == &argv[(int)argv[-1]]) { 1773 --argv; 1774 *argv = (char *)((int)(*argv) + 10); 1775 argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); 1776 if (argv == NULL) 1777 return(NULL); 1778 argv++; 1779 cpp = &argv[(int)argv[-1] - 10]; 1780 } 1781 *cpp++ = val; 1782 *cpp = 0; 1783 return(argv); 1784 } 1785 #endif /* NEWINIT */ 1786 1787 /* 1788 * cleanup() 1789 * 1790 * This is the routine to call when we are all through, to 1791 * clean up anything that needs to be cleaned up. 1792 */ 1793 /* ARGSUSED */ 1794 void 1795 cleanup(sig) 1796 int sig; 1797 { 1798 #ifndef PARENT_DOES_UTMP 1799 # if (BSD > 43) || defined(convex) 1800 char *p; 1801 1802 p = line + sizeof("/dev/") - 1; 1803 if (logout(p)) 1804 logwtmp(p, "", ""); 1805 (void)chmod(line, 0666); 1806 (void)chown(line, 0, 0); 1807 *p = 'p'; 1808 (void)chmod(line, 0666); 1809 (void)chown(line, 0, 0); 1810 (void) shutdown(net, 2); 1811 exit(1); 1812 # else 1813 void rmut(); 1814 1815 rmut(); 1816 vhangup(); /* XXX */ 1817 (void) shutdown(net, 2); 1818 exit(1); 1819 # endif 1820 #else /* PARENT_DOES_UTMP */ 1821 # ifdef NEWINIT 1822 (void) shutdown(net, 2); 1823 exit(1); 1824 # else /* NEWINIT */ 1825 # ifdef CRAY 1826 static int incleanup = 0; 1827 register int t; 1828 int child_status; /* status of child process as returned by waitpid */ 1829 int flags = WNOHANG|WUNTRACED; 1830 1831 /* 1832 * 1: Pick up the zombie, if we are being called 1833 * as the signal handler. 1834 * 2: If we are a nested cleanup(), return. 1835 * 3: Try to clean up TMPDIR. 1836 * 4: Fill in utmp with shutdown of process. 1837 * 5: Close down the network and pty connections. 1838 * 6: Finish up the TMPDIR cleanup, if needed. 1839 */ 1840 if (sig == SIGCHLD) { 1841 while (waitpid(-1, &child_status, flags) > 0) 1842 ; /* VOID */ 1843 /* Check if the child process was stopped 1844 * rather than exited. We want cleanup only if 1845 * the child has died. 1846 */ 1847 if (WIFSTOPPED(child_status)) { 1848 return; 1849 } 1850 } 1851 t = sigblock(sigmask(SIGCHLD)); 1852 if (incleanup) { 1853 sigsetmask(t); 1854 return; 1855 } 1856 incleanup = 1; 1857 sigsetmask(t); 1858 #ifdef UNICOS7x 1859 if (secflag) { 1860 /* 1861 * We need to set ourselves back to a null 1862 * label to clean up. 1863 */ 1864 1865 setulvl(sysv.sy_minlvl); 1866 setucmp((long)0); 1867 } 1868 #endif /* UNICOS7x */ 1869 1870 t = cleantmp(&wtmp); 1871 setutent(); /* just to make sure */ 1872 # endif /* CRAY */ 1873 rmut(line); 1874 close(pty); 1875 (void) shutdown(net, 2); 1876 # ifdef CRAY 1877 if (t == 0) 1878 cleantmp(&wtmp); 1879 # endif /* CRAY */ 1880 exit(1); 1881 # endif /* NEWINT */ 1882 #endif /* PARENT_DOES_UTMP */ 1883 } 1884 1885 #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 1886 /* 1887 * _utmp_sig_rcv 1888 * utmp_sig_init 1889 * utmp_sig_wait 1890 * These three functions are used to coordinate the handling of 1891 * the utmp file between the server and the soon-to-be-login shell. 1892 * The server actually creates the utmp structure, the child calls 1893 * utmp_sig_wait(), until the server calls utmp_sig_notify() and 1894 * signals the future-login shell to proceed. 1895 */ 1896 static int caught=0; /* NZ when signal intercepted */ 1897 static void (*func)(); /* address of previous handler */ 1898 1899 void 1900 _utmp_sig_rcv(sig) 1901 int sig; 1902 { 1903 caught = 1; 1904 (void) signal(SIGUSR1, func); 1905 } 1906 1907 void 1908 utmp_sig_init() 1909 { 1910 /* 1911 * register signal handler for UTMP creation 1912 */ 1913 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 1914 fatalperror(net, "telnetd/signal"); 1915 } 1916 1917 void 1918 utmp_sig_reset() 1919 { 1920 (void) signal(SIGUSR1, func); /* reset handler to default */ 1921 } 1922 1923 # ifdef __hpux 1924 # define sigoff() /* do nothing */ 1925 # define sigon() /* do nothing */ 1926 # endif 1927 1928 void 1929 utmp_sig_wait() 1930 { 1931 /* 1932 * Wait for parent to write our utmp entry. 1933 */ 1934 sigoff(); 1935 while (caught == 0) { 1936 pause(); /* wait until we get a signal (sigon) */ 1937 sigoff(); /* turn off signals while we check caught */ 1938 } 1939 sigon(); /* turn on signals again */ 1940 } 1941 1942 void 1943 utmp_sig_notify(pid) 1944 { 1945 kill(pid, SIGUSR1); 1946 } 1947 1948 # ifdef CRAY 1949 static int gotsigjob = 0; 1950 1951 /*ARGSUSED*/ 1952 void 1953 sigjob(sig) 1954 int sig; 1955 { 1956 register int jid; 1957 register struct jobtemp *jp; 1958 1959 while ((jid = waitjob(NULL)) != -1) { 1960 if (jid == 0) { 1961 return; 1962 } 1963 gotsigjob++; 1964 jobend(jid, NULL, NULL); 1965 } 1966 } 1967 1968 /* 1969 * jid_getutid: 1970 * called by jobend() before calling cleantmp() 1971 * to find the correct $TMPDIR to cleanup. 1972 */ 1973 1974 struct utmp * 1975 jid_getutid(jid) 1976 int jid; 1977 { 1978 struct utmp *cur = NULL; 1979 1980 setutent(); /* just to make sure */ 1981 while (cur = getutent()) { 1982 if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { 1983 return(cur); 1984 } 1985 } 1986 1987 return(0); 1988 } 1989 1990 /* 1991 * Clean up the TMPDIR that login created. 1992 * The first time this is called we pick up the info 1993 * from the utmp. If the job has already gone away, 1994 * then we'll clean up and be done. If not, then 1995 * when this is called the second time it will wait 1996 * for the signal that the job is done. 1997 */ 1998 int 1999 cleantmp(wtp) 2000 register struct utmp *wtp; 2001 { 2002 struct utmp *utp; 2003 static int first = 1; 2004 register int mask, omask, ret; 2005 extern struct utmp *getutid P((const struct utmp *_Id)); 2006 2007 2008 mask = sigmask(WJSIGNAL); 2009 2010 if (first == 0) { 2011 omask = sigblock(mask); 2012 while (gotsigjob == 0) 2013 sigpause(omask); 2014 return(1); 2015 } 2016 first = 0; 2017 setutent(); /* just to make sure */ 2018 2019 utp = getutid(wtp); 2020 if (utp == 0) { 2021 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 2022 return(-1); 2023 } 2024 /* 2025 * Nothing to clean up if the user shell was never started. 2026 */ 2027 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 2028 return(1); 2029 2030 /* 2031 * Block the WJSIGNAL while we are in jobend(). 2032 */ 2033 omask = sigblock(mask); 2034 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 2035 sigsetmask(omask); 2036 return(ret); 2037 } 2038 2039 int 2040 jobend(jid, path, user) 2041 register int jid; 2042 register char *path; 2043 register char *user; 2044 { 2045 static int saved_jid = 0; 2046 static int pty_saved_jid = 0; 2047 static char saved_path[sizeof(wtmp.ut_tpath)+1]; 2048 static char saved_user[sizeof(wtmp.ut_user)+1]; 2049 2050 /* 2051 * this little piece of code comes into play 2052 * only when ptyreconnect is used to reconnect 2053 * to an previous session. 2054 * 2055 * this is the only time when the 2056 * "saved_jid != jid" code is executed. 2057 */ 2058 2059 if ( saved_jid && saved_jid != jid ) { 2060 if (!path) { /* called from signal handler */ 2061 pty_saved_jid = jid; 2062 } else { 2063 pty_saved_jid = saved_jid; 2064 } 2065 } 2066 2067 if (path) { 2068 strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 2069 strncpy(saved_user, user, sizeof(wtmp.ut_user)); 2070 saved_path[sizeof(saved_path)] = '\0'; 2071 saved_user[sizeof(saved_user)] = '\0'; 2072 } 2073 if (saved_jid == 0) { 2074 saved_jid = jid; 2075 return(0); 2076 } 2077 2078 /* if the jid has changed, get the correct entry from the utmp file */ 2079 2080 if ( saved_jid != jid ) { 2081 struct utmp *utp = NULL; 2082 struct utmp *jid_getutid(); 2083 2084 utp = jid_getutid(pty_saved_jid); 2085 2086 if (utp == 0) { 2087 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 2088 return(-1); 2089 } 2090 2091 cleantmpdir(jid, utp->ut_tpath, utp->ut_user); 2092 return(1); 2093 } 2094 2095 cleantmpdir(jid, saved_path, saved_user); 2096 return(1); 2097 } 2098 2099 /* 2100 * Fork a child process to clean up the TMPDIR 2101 */ 2102 cleantmpdir(jid, tpath, user) 2103 register int jid; 2104 register char *tpath; 2105 register char *user; 2106 { 2107 switch(fork()) { 2108 case -1: 2109 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 2110 tpath); 2111 break; 2112 case 0: 2113 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 2114 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 2115 tpath, CLEANTMPCMD); 2116 exit(1); 2117 default: 2118 /* 2119 * Forget about child. We will exit, and 2120 * /etc/init will pick it up. 2121 */ 2122 break; 2123 } 2124 } 2125 # endif /* CRAY */ 2126 #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 2127 2128 /* 2129 * rmut() 2130 * 2131 * This is the function called by cleanup() to 2132 * remove the utmp entry for this person. 2133 */ 2134 2135 #ifdef UTMPX 2136 void 2137 rmut() 2138 { 2139 register f; 2140 int found = 0; 2141 struct utmp *u, *utmp; 2142 int nutmp; 2143 struct stat statbf; 2144 2145 struct utmpx *utxp, utmpx; 2146 2147 /* 2148 * This updates the utmpx and utmp entries and make a wtmp/x entry 2149 */ 2150 2151 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 2152 utxp = getutxline(&utmpx); 2153 if (utxp) { 2154 utxp->ut_type = DEAD_PROCESS; 2155 utxp->ut_exit.e_termination = 0; 2156 utxp->ut_exit.e_exit = 0; 2157 (void) time(&utmpx.ut_tv.tv_sec); 2158 utmpx.ut_tv.tv_usec = 0; 2159 modutx(utxp); 2160 } 2161 endutxent(); 2162 } /* end of rmut */ 2163 #endif 2164 2165 #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 2166 void 2167 rmut() 2168 { 2169 register f; 2170 int found = 0; 2171 struct utmp *u, *utmp; 2172 int nutmp; 2173 struct stat statbf; 2174 2175 f = open(utmpf, O_RDWR); 2176 if (f >= 0) { 2177 (void) fstat(f, &statbf); 2178 utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 2179 if (!utmp) 2180 syslog(LOG_ERR, "utmp malloc failed"); 2181 if (statbf.st_size && utmp) { 2182 nutmp = read(f, (char *)utmp, (int)statbf.st_size); 2183 nutmp /= sizeof(struct utmp); 2184 2185 for (u = utmp ; u < &utmp[nutmp] ; u++) { 2186 if (SCMPN(u->ut_line, line+5) || 2187 u->ut_name[0]==0) 2188 continue; 2189 (void) lseek(f, ((long)u)-((long)utmp), L_SET); 2190 SCPYN(u->ut_name, ""); 2191 SCPYN(u->ut_host, ""); 2192 (void) time(&u->ut_time); 2193 (void) write(f, (char *)u, sizeof(wtmp)); 2194 found++; 2195 } 2196 } 2197 (void) close(f); 2198 } 2199 if (found) { 2200 f = open(wtmpf, O_WRONLY|O_APPEND); 2201 if (f >= 0) { 2202 SCPYN(wtmp.ut_line, line+5); 2203 SCPYN(wtmp.ut_name, ""); 2204 SCPYN(wtmp.ut_host, ""); 2205 (void) time(&wtmp.ut_time); 2206 (void) write(f, (char *)&wtmp, sizeof(wtmp)); 2207 (void) close(f); 2208 } 2209 } 2210 (void) chmod(line, 0666); 2211 (void) chown(line, 0, 0); 2212 line[strlen("/dev/")] = 'p'; 2213 (void) chmod(line, 0666); 2214 (void) chown(line, 0, 0); 2215 } /* end of rmut */ 2216 #endif /* CRAY */ 2217 2218 #ifdef __hpux 2219 rmut (line) 2220 char *line; 2221 { 2222 struct utmp utmp; 2223 struct utmp *utptr; 2224 int fd; /* for /etc/wtmp */ 2225 2226 utmp.ut_type = USER_PROCESS; 2227 (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 2228 (void) setutent(); 2229 utptr = getutid(&utmp); 2230 /* write it out only if it exists */ 2231 if (utptr) { 2232 utptr->ut_type = DEAD_PROCESS; 2233 utptr->ut_time = time((long *) 0); 2234 (void) pututline(utptr); 2235 /* set wtmp entry if wtmp file exists */ 2236 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 2237 (void) write(fd, utptr, sizeof(utmp)); 2238 (void) close(fd); 2239 } 2240 } 2241 (void) endutent(); 2242 2243 (void) chmod(line, 0666); 2244 (void) chown(line, 0, 0); 2245 line[14] = line[13]; 2246 line[13] = line[12]; 2247 line[8] = 'm'; 2248 line[9] = '/'; 2249 line[10] = 'p'; 2250 line[11] = 't'; 2251 line[12] = 'y'; 2252 (void) chmod(line, 0666); 2253 (void) chown(line, 0, 0); 2254 } 2255 #endif 2256