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