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.2 (Berkeley) 12/15/93"; 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 * A table of available terminal speeds 921 */ 922 struct termspeeds { 923 int speed; 924 int value; 925 } termspeeds[] = { 926 { 0, B0 }, { 50, B50 }, { 75, B75 }, 927 { 110, B110 }, { 134, B134 }, { 150, B150 }, 928 { 200, B200 }, { 300, B300 }, { 600, B600 }, 929 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 930 { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 931 { 38400, B9600 }, { -1, B9600 } 932 }; 933 934 void 935 tty_tspeed(val) 936 int val; 937 { 938 register struct termspeeds *tp; 939 940 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 941 ; 942 cfsetospeed(&termbuf, tp->value); 943 } 944 945 void 946 tty_rspeed(val) 947 int val; 948 { 949 register struct termspeeds *tp; 950 951 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 952 ; 953 cfsetispeed(&termbuf, tp->value); 954 } 955 956 #if defined(CRAY2) && defined(UNICOS5) 957 int 958 tty_isnewmap() 959 { 960 return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 961 !(termbuf.c_oflag & ONLRET)); 962 } 963 #endif 964 965 #ifdef PARENT_DOES_UTMP 966 # ifndef NEWINIT 967 extern struct utmp wtmp; 968 extern char wtmpf[]; 969 # else /* NEWINIT */ 970 int gotalarm; 971 972 /* ARGSUSED */ 973 void 974 nologinproc(sig) 975 int sig; 976 { 977 gotalarm++; 978 } 979 # endif /* NEWINIT */ 980 #endif /* PARENT_DOES_UTMP */ 981 982 #ifndef NEWINIT 983 # ifdef PARENT_DOES_UTMP 984 extern void utmp_sig_init P((void)); 985 extern void utmp_sig_reset P((void)); 986 extern void utmp_sig_wait P((void)); 987 extern void utmp_sig_notify P((int)); 988 # endif /* PARENT_DOES_UTMP */ 989 #endif 990 991 /* 992 * getptyslave() 993 * 994 * Open the slave side of the pty, and do any initialization 995 * that is necessary. The return value is a file descriptor 996 * for the slave side. 997 */ 998 int 999 getptyslave() 1000 { 1001 register int t = -1; 1002 1003 #if !defined(CRAY) || !defined(NEWINIT) 1004 # ifdef LINEMODE 1005 int waslm; 1006 # endif 1007 # ifdef TIOCGWINSZ 1008 struct winsize ws; 1009 extern int def_row, def_col; 1010 # endif 1011 extern int def_tspeed, def_rspeed; 1012 /* 1013 * Opening the slave side may cause initilization of the 1014 * kernel tty structure. We need remember the state of 1015 * if linemode was turned on 1016 * terminal window size 1017 * terminal speed 1018 * so that we can re-set them if we need to. 1019 */ 1020 # ifdef LINEMODE 1021 waslm = tty_linemode(); 1022 # endif 1023 1024 1025 /* 1026 * Make sure that we don't have a controlling tty, and 1027 * that we are the session (process group) leader. 1028 */ 1029 # ifdef TIOCNOTTY 1030 t = open(_PATH_TTY, O_RDWR); 1031 if (t >= 0) { 1032 (void) ioctl(t, TIOCNOTTY, (char *)0); 1033 (void) close(t); 1034 } 1035 # endif 1036 1037 1038 # ifdef PARENT_DOES_UTMP 1039 /* 1040 * Wait for our parent to get the utmp stuff to get done. 1041 */ 1042 utmp_sig_wait(); 1043 # endif 1044 1045 t = cleanopen(line); 1046 if (t < 0) 1047 fatalperror(net, line); 1048 1049 #ifdef STREAMSPTY 1050 #ifdef USE_TERMIO 1051 ttyfd = t; 1052 #endif 1053 if (ioctl(t, I_PUSH, "ptem") < 0) 1054 fatal(net, "I_PUSH ptem"); 1055 if (ioctl(t, I_PUSH, "ldterm") < 0) 1056 fatal(net, "I_PUSH ldterm"); 1057 if (ioctl(t, I_PUSH, "ttcompat") < 0) 1058 fatal(net, "I_PUSH ttcompat"); 1059 if (ioctl(pty, I_PUSH, "pckt") < 0) 1060 fatal(net, "I_PUSH pckt"); 1061 #endif 1062 1063 /* 1064 * set up the tty modes as we like them to be. 1065 */ 1066 init_termbuf(); 1067 # ifdef TIOCGWINSZ 1068 if (def_row || def_col) { 1069 bzero((char *)&ws, sizeof(ws)); 1070 ws.ws_col = def_col; 1071 ws.ws_row = def_row; 1072 (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 1073 } 1074 # endif 1075 1076 /* 1077 * Settings for sgtty based systems 1078 */ 1079 # ifndef USE_TERMIO 1080 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 1081 # endif /* USE_TERMIO */ 1082 1083 /* 1084 * Settings for UNICOS (and HPUX) 1085 */ 1086 # if defined(CRAY) || defined(__hpux) 1087 termbuf.c_oflag = OPOST|ONLCR|TAB3; 1088 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 1089 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 1090 termbuf.c_cflag = EXTB|HUPCL|CS8; 1091 # endif 1092 1093 /* 1094 * Settings for all other termios/termio based 1095 * systems, other than 4.4BSD. In 4.4BSD the 1096 * kernel does the initial terminal setup. 1097 */ 1098 # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 1099 # ifndef OXTABS 1100 # define OXTABS 0 1101 # endif 1102 termbuf.c_lflag |= ECHO; 1103 termbuf.c_oflag |= ONLCR|OXTABS; 1104 termbuf.c_iflag |= ICRNL; 1105 termbuf.c_iflag &= ~IXOFF; 1106 # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 1107 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 1108 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 1109 # ifdef LINEMODE 1110 if (waslm) 1111 tty_setlinemode(1); 1112 # endif /* LINEMODE */ 1113 1114 /* 1115 * Set the tty modes, and make this our controlling tty. 1116 */ 1117 set_termbuf(); 1118 if (login_tty(t) == -1) 1119 fatalperror(net, "login_tty"); 1120 #endif /* !defined(CRAY) || !defined(NEWINIT) */ 1121 if (net > 2) 1122 (void) close(net); 1123 #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1124 /* 1125 * Leave the pty open so that we can write out the rlogin 1126 * protocol for /bin/login, if the authentication works. 1127 */ 1128 #else 1129 if (pty > 2) { 1130 (void) close(pty); 1131 pty = -1; 1132 } 1133 #endif 1134 } 1135 1136 #if !defined(CRAY) || !defined(NEWINIT) 1137 #ifndef O_NOCTTY 1138 #define O_NOCTTY 0 1139 #endif 1140 /* 1141 * Open the specified slave side of the pty, 1142 * making sure that we have a clean tty. 1143 */ 1144 int 1145 cleanopen(line) 1146 char *line; 1147 { 1148 register int t; 1149 #if defined(_SC_CRAY_SECURE_SYS) 1150 struct secstat secbuf; 1151 #endif /* _SC_CRAY_SECURE_SYS */ 1152 1153 #ifndef STREAMSPTY 1154 /* 1155 * Make sure that other people can't open the 1156 * slave side of the connection. 1157 */ 1158 (void) chown(line, 0, 0); 1159 (void) chmod(line, 0600); 1160 #endif 1161 1162 # if !defined(CRAY) && (BSD > 43) 1163 (void) revoke(line); 1164 # endif 1165 #if defined(_SC_CRAY_SECURE_SYS) 1166 if (secflag) { 1167 if (secstat(line, &secbuf) < 0) 1168 return(-1); 1169 if (setulvl(secbuf.st_slevel) < 0) 1170 return(-1); 1171 if (setucmp(secbuf.st_compart) < 0) 1172 return(-1); 1173 } 1174 #endif /* _SC_CRAY_SECURE_SYS */ 1175 1176 t = open(line, O_RDWR|O_NOCTTY); 1177 1178 #if defined(_SC_CRAY_SECURE_SYS) 1179 if (secflag) { 1180 if (setulvl(sysv.sy_minlvl) < 0) 1181 return(-1); 1182 if (setucmp(0) < 0) 1183 return(-1); 1184 } 1185 #endif /* _SC_CRAY_SECURE_SYS */ 1186 1187 if (t < 0) 1188 return(-1); 1189 1190 /* 1191 * Hangup anybody else using this ttyp, then reopen it for 1192 * ourselves. 1193 */ 1194 # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 1195 (void) signal(SIGHUP, SIG_IGN); 1196 vhangup(); 1197 (void) signal(SIGHUP, SIG_DFL); 1198 t = open(line, O_RDWR|O_NOCTTY); 1199 if (t < 0) 1200 return(-1); 1201 # endif 1202 # if defined(CRAY) && defined(TCVHUP) 1203 { 1204 register int i; 1205 (void) signal(SIGHUP, SIG_IGN); 1206 (void) ioctl(t, TCVHUP, (char *)0); 1207 (void) signal(SIGHUP, SIG_DFL); 1208 setpgrp(); 1209 1210 #if defined(_SC_CRAY_SECURE_SYS) 1211 if (secflag) { 1212 if (secstat(line, &secbuf) < 0) 1213 return(-1); 1214 if (setulvl(secbuf.st_slevel) < 0) 1215 return(-1); 1216 if (setucmp(secbuf.st_compart) < 0) 1217 return(-1); 1218 } 1219 #endif /* _SC_CRAY_SECURE_SYS */ 1220 1221 i = open(line, O_RDWR); 1222 1223 #if defined(_SC_CRAY_SECURE_SYS) 1224 if (secflag) { 1225 if (setulvl(sysv.sy_minlvl) < 0) 1226 return(-1); 1227 if (setucmp(0) < 0) 1228 return(-1); 1229 } 1230 #endif /* _SC_CRAY_SECURE_SYS */ 1231 1232 if (i < 0) 1233 return(-1); 1234 (void) close(t); 1235 t = i; 1236 } 1237 # endif /* defined(CRAY) && defined(TCVHUP) */ 1238 return(t); 1239 } 1240 #endif /* !defined(CRAY) || !defined(NEWINIT) */ 1241 1242 #if BSD <= 43 1243 1244 int 1245 login_tty(t) 1246 int t; 1247 { 1248 if (setsid() < 0) { 1249 #ifdef ultrix 1250 /* 1251 * The setsid() may have failed because we 1252 * already have a pgrp == pid. Zero out 1253 * our pgrp and try again... 1254 */ 1255 if ((setpgrp(0, 0) < 0) || (setsid() < 0)) 1256 #endif 1257 fatalperror(net, "setsid()"); 1258 } 1259 # ifdef TIOCSCTTY 1260 if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 1261 fatalperror(net, "ioctl(sctty)"); 1262 # if defined(CRAY) 1263 /* 1264 * Close the hard fd to /dev/ttypXXX, and re-open through 1265 * the indirect /dev/tty interface. 1266 */ 1267 close(t); 1268 if ((t = open("/dev/tty", O_RDWR)) < 0) 1269 fatalperror(net, "open(/dev/tty)"); 1270 # endif 1271 # else 1272 /* 1273 * We get our controlling tty assigned as a side-effect 1274 * of opening up a tty device. But on BSD based systems, 1275 * this only happens if our process group is zero. The 1276 * setsid() call above may have set our pgrp, so clear 1277 * it out before opening the tty... 1278 */ 1279 (void) setpgrp(0, 0); 1280 close(open(line, O_RDWR)); 1281 # endif 1282 if (t != 0) 1283 (void) dup2(t, 0); 1284 if (t != 1) 1285 (void) dup2(t, 1); 1286 if (t != 2) 1287 (void) dup2(t, 2); 1288 if (t > 2) 1289 close(t); 1290 return(0); 1291 } 1292 #endif /* BSD <= 43 */ 1293 1294 #ifdef NEWINIT 1295 char *gen_id = "fe"; 1296 #endif 1297 1298 /* 1299 * startslave(host) 1300 * 1301 * Given a hostname, do whatever 1302 * is necessary to startup the login process on the slave side of the pty. 1303 */ 1304 1305 /* ARGSUSED */ 1306 void 1307 startslave(host, autologin, autoname) 1308 char *host; 1309 int autologin; 1310 char *autoname; 1311 { 1312 register int i; 1313 long time(); 1314 char name[256]; 1315 #ifdef NEWINIT 1316 extern char *ptyip; 1317 struct init_request request; 1318 void nologinproc(); 1319 register int n; 1320 #endif /* NEWINIT */ 1321 1322 #if defined(AUTHENTICATION) 1323 if (!autoname || !autoname[0]) 1324 autologin = 0; 1325 1326 if (autologin < auth_level) { 1327 fatal(net, "Authorization failed"); 1328 exit(1); 1329 } 1330 #endif 1331 1332 #ifndef NEWINIT 1333 # ifdef PARENT_DOES_UTMP 1334 utmp_sig_init(); 1335 # endif /* PARENT_DOES_UTMP */ 1336 1337 if ((i = fork()) < 0) 1338 fatalperror(net, "fork"); 1339 if (i) { 1340 # ifdef PARENT_DOES_UTMP 1341 /* 1342 * Cray parent will create utmp entry for child and send 1343 * signal to child to tell when done. Child waits for signal 1344 * before doing anything important. 1345 */ 1346 register int pid = i; 1347 void sigjob P((int)); 1348 1349 setpgrp(); 1350 utmp_sig_reset(); /* reset handler to default */ 1351 /* 1352 * Create utmp entry for child 1353 */ 1354 (void) time(&wtmp.ut_time); 1355 wtmp.ut_type = LOGIN_PROCESS; 1356 wtmp.ut_pid = pid; 1357 SCPYN(wtmp.ut_user, "LOGIN"); 1358 SCPYN(wtmp.ut_host, host); 1359 SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 1360 #ifndef __hpux 1361 SCPYN(wtmp.ut_id, wtmp.ut_line+3); 1362 #else 1363 SCPYN(wtmp.ut_id, wtmp.ut_line+7); 1364 #endif 1365 pututline(&wtmp); 1366 endutent(); 1367 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 1368 (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 1369 (void) close(i); 1370 } 1371 #ifdef CRAY 1372 (void) signal(WJSIGNAL, sigjob); 1373 #endif 1374 utmp_sig_notify(pid); 1375 # endif /* PARENT_DOES_UTMP */ 1376 } else { 1377 getptyslave(autologin); 1378 start_login(host, autologin, autoname); 1379 /*NOTREACHED*/ 1380 } 1381 #else /* NEWINIT */ 1382 1383 /* 1384 * Init will start up login process if we ask nicely. We only wait 1385 * for it to start up and begin normal telnet operation. 1386 */ 1387 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 1388 char tbuf[128]; 1389 (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 1390 fatalperror(net, tbuf); 1391 } 1392 memset((char *)&request, 0, sizeof(request)); 1393 request.magic = INIT_MAGIC; 1394 SCPYN(request.gen_id, gen_id); 1395 SCPYN(request.tty_id, &line[8]); 1396 SCPYN(request.host, host); 1397 SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 1398 #if !defined(UNICOS5) 1399 request.signal = SIGCLD; 1400 request.pid = getpid(); 1401 #endif 1402 #ifdef BFTPDAEMON 1403 /* 1404 * Are we working as the bftp daemon? 1405 */ 1406 if (bftpd) { 1407 SCPYN(request.exec_name, BFTPPATH); 1408 } 1409 #endif /* BFTPDAEMON */ 1410 if (write(i, (char *)&request, sizeof(request)) < 0) { 1411 char tbuf[128]; 1412 (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 1413 fatalperror(net, tbuf); 1414 } 1415 (void) close(i); 1416 (void) signal(SIGALRM, nologinproc); 1417 for (i = 0; ; i++) { 1418 char tbuf[128]; 1419 alarm(15); 1420 n = read(pty, ptyip, BUFSIZ); 1421 if (i == 3 || n >= 0 || !gotalarm) 1422 break; 1423 gotalarm = 0; 1424 sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 1425 (void) write(net, tbuf, strlen(tbuf)); 1426 } 1427 if (n < 0 && gotalarm) 1428 fatal(net, "/etc/init didn't start login process"); 1429 pcc += n; 1430 alarm(0); 1431 (void) signal(SIGALRM, SIG_DFL); 1432 1433 return; 1434 #endif /* NEWINIT */ 1435 } 1436 1437 char *envinit[3]; 1438 extern char **environ; 1439 1440 void 1441 init_env() 1442 { 1443 extern char *getenv(); 1444 char **envp; 1445 1446 envp = envinit; 1447 if (*envp = getenv("TZ")) 1448 *envp++ -= 3; 1449 #if defined(CRAY) || defined(__hpux) 1450 else 1451 *envp++ = "TZ=GMT0"; 1452 #endif 1453 *envp = 0; 1454 environ = envinit; 1455 } 1456 1457 #ifndef NEWINIT 1458 1459 /* 1460 * start_login(host) 1461 * 1462 * Assuming that we are now running as a child processes, this 1463 * function will turn us into the login process. 1464 */ 1465 1466 void 1467 start_login(host, autologin, name) 1468 char *host; 1469 int autologin; 1470 char *name; 1471 { 1472 register char *cp; 1473 register char **argv; 1474 char **addarg(); 1475 extern char *getenv(); 1476 #ifdef UTMPX 1477 register int pid = getpid(); 1478 struct utmpx utmpx; 1479 #endif 1480 #ifdef SOLARIS 1481 char *term; 1482 char termbuf[64]; 1483 #endif 1484 1485 #ifdef UTMPX 1486 /* 1487 * Create utmp entry for child 1488 */ 1489 1490 bzero(&utmpx, sizeof(utmpx)); 1491 SCPYN(utmpx.ut_user, ".telnet"); 1492 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 1493 utmpx.ut_pid = pid; 1494 utmpx.ut_id[0] = 't'; 1495 utmpx.ut_id[1] = 'n'; 1496 utmpx.ut_id[2] = SC_WILDC; 1497 utmpx.ut_id[3] = SC_WILDC; 1498 utmpx.ut_type = LOGIN_PROCESS; 1499 (void) time(&utmpx.ut_tv.tv_sec); 1500 if (makeutx(&utmpx) == NULL) 1501 fatal(net, "makeutx failed"); 1502 #endif 1503 1504 /* 1505 * -h : pass on name of host. 1506 * WARNING: -h is accepted by login if and only if 1507 * getuid() == 0. 1508 * -p : don't clobber the environment (so terminal type stays set). 1509 * 1510 * -f : force this login, he has already been authenticated 1511 */ 1512 argv = addarg(0, "login"); 1513 1514 #if !defined(NO_LOGIN_H) 1515 1516 # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1517 /* 1518 * Don't add the "-h host" option if we are going 1519 * to be adding the "-r host" option down below... 1520 */ 1521 if ((auth_level < 0) || (autologin != AUTH_VALID)) 1522 # endif 1523 { 1524 argv = addarg(argv, "-h"); 1525 argv = addarg(argv, host); 1526 #ifdef SOLARIS 1527 /* 1528 * SVR4 version of -h takes TERM= as second arg, or - 1529 */ 1530 term = getenv("TERM"); 1531 if (term == NULL || term[0] == 0) { 1532 term = "-"; 1533 } else { 1534 strcpy(termbuf, "TERM="); 1535 strncat(termbuf, term, sizeof(termbuf) - 6); 1536 term = termbuf; 1537 } 1538 argv = addarg(argv, term); 1539 #endif 1540 } 1541 #endif 1542 #if !defined(NO_LOGIN_P) 1543 argv = addarg(argv, "-p"); 1544 #endif 1545 #ifdef BFTPDAEMON 1546 /* 1547 * Are we working as the bftp daemon? If so, then ask login 1548 * to start bftp instead of shell. 1549 */ 1550 if (bftpd) { 1551 argv = addarg(argv, "-e"); 1552 argv = addarg(argv, BFTPPATH); 1553 } else 1554 #endif 1555 #if defined (SecurID) 1556 /* 1557 * don't worry about the -f that might get sent. 1558 * A -s is supposed to override it anyhow. 1559 */ 1560 if (require_SecurID) 1561 argv = addarg(argv, "-s"); 1562 #endif 1563 #if defined (AUTHENTICATION) 1564 if (auth_level >= 0 && autologin == AUTH_VALID) { 1565 # if !defined(NO_LOGIN_F) 1566 argv = addarg(argv, "-f"); 1567 argv = addarg(argv, name); 1568 # else 1569 # if defined(LOGIN_R) 1570 /* 1571 * We don't have support for "login -f", but we 1572 * can fool /bin/login into thinking that we are 1573 * rlogind, and allow us to log in without a 1574 * password. The rlogin protocol expects 1575 * local-user\0remote-user\0term/speed\0 1576 */ 1577 1578 if (pty > 2) { 1579 register char *cp; 1580 char speed[128]; 1581 int isecho, israw, xpty, len; 1582 extern int def_rspeed; 1583 # ifndef LOGIN_HOST 1584 /* 1585 * Tell login that we are coming from "localhost". 1586 * If we passed in the real host name, then the 1587 * user would have to allow .rhost access from 1588 * every machine that they want authenticated 1589 * access to work from, which sort of defeats 1590 * the purpose of an authenticated login... 1591 * So, we tell login that the session is coming 1592 * from "localhost", and the user will only have 1593 * to have "localhost" in their .rhost file. 1594 */ 1595 # define LOGIN_HOST "localhost" 1596 # endif 1597 argv = addarg(argv, "-r"); 1598 argv = addarg(argv, LOGIN_HOST); 1599 1600 xpty = pty; 1601 # ifndef STREAMSPTY 1602 pty = 0; 1603 # else 1604 ttyfd = 0; 1605 # endif 1606 init_termbuf(); 1607 isecho = tty_isecho(); 1608 israw = tty_israw(); 1609 if (isecho || !israw) { 1610 tty_setecho(0); /* Turn off echo */ 1611 tty_setraw(1); /* Turn on raw */ 1612 set_termbuf(); 1613 } 1614 len = strlen(name)+1; 1615 write(xpty, name, len); 1616 write(xpty, name, len); 1617 sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", 1618 (def_rspeed > 0) ? def_rspeed : 9600); 1619 len = strlen(speed)+1; 1620 write(xpty, speed, len); 1621 1622 if (isecho || !israw) { 1623 init_termbuf(); 1624 tty_setecho(isecho); 1625 tty_setraw(israw); 1626 set_termbuf(); 1627 if (!israw) { 1628 /* 1629 * Write a newline to ensure 1630 * that login will be able to 1631 * read the line... 1632 */ 1633 write(xpty, "\n", 1); 1634 } 1635 } 1636 pty = xpty; 1637 } 1638 # else 1639 argv = addarg(argv, name); 1640 # endif 1641 # endif 1642 } else 1643 #endif 1644 if (getenv("USER")) { 1645 argv = addarg(argv, getenv("USER")); 1646 #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 1647 { 1648 register char **cpp; 1649 for (cpp = environ; *cpp; cpp++) 1650 argv = addarg(argv, *cpp); 1651 } 1652 #endif 1653 /* 1654 * Assume that login will set the USER variable 1655 * correctly. For SysV systems, this means that 1656 * USER will no longer be set, just LOGNAME by 1657 * login. (The problem is that if the auto-login 1658 * fails, and the user then specifies a different 1659 * account name, he can get logged in with both 1660 * LOGNAME and USER in his environment, but the 1661 * USER value will be wrong. 1662 */ 1663 unsetenv("USER"); 1664 } 1665 #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1666 if (pty > 2) 1667 close(pty); 1668 #endif 1669 closelog(); 1670 execv(_PATH_LOGIN, argv); 1671 1672 syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 1673 fatalperror(net, _PATH_LOGIN); 1674 /*NOTREACHED*/ 1675 } 1676 1677 char ** 1678 addarg(argv, val) 1679 register char **argv; 1680 register char *val; 1681 { 1682 register char **cpp; 1683 1684 if (argv == NULL) { 1685 /* 1686 * 10 entries, a leading length, and a null 1687 */ 1688 argv = (char **)malloc(sizeof(*argv) * 12); 1689 if (argv == NULL) 1690 return(NULL); 1691 *argv++ = (char *)10; 1692 *argv = (char *)0; 1693 } 1694 for (cpp = argv; *cpp; cpp++) 1695 ; 1696 if (cpp == &argv[(int)argv[-1]]) { 1697 --argv; 1698 *argv = (char *)((int)(*argv) + 10); 1699 argv = (char **)realloc(argv, (int)(*argv) + 2); 1700 if (argv == NULL) 1701 return(NULL); 1702 argv++; 1703 cpp = &argv[(int)argv[-1] - 10]; 1704 } 1705 *cpp++ = val; 1706 *cpp = 0; 1707 return(argv); 1708 } 1709 #endif /* NEWINIT */ 1710 1711 /* 1712 * cleanup() 1713 * 1714 * This is the routine to call when we are all through, to 1715 * clean up anything that needs to be cleaned up. 1716 */ 1717 /* ARGSUSED */ 1718 void 1719 cleanup(sig) 1720 int sig; 1721 { 1722 #ifndef PARENT_DOES_UTMP 1723 # if (BSD > 43) || defined(convex) 1724 char *p; 1725 1726 p = line + sizeof("/dev/") - 1; 1727 if (logout(p)) 1728 logwtmp(p, "", ""); 1729 (void)chmod(line, 0666); 1730 (void)chown(line, 0, 0); 1731 *p = 'p'; 1732 (void)chmod(line, 0666); 1733 (void)chown(line, 0, 0); 1734 (void) shutdown(net, 2); 1735 exit(1); 1736 # else 1737 void rmut(); 1738 1739 rmut(); 1740 vhangup(); /* XXX */ 1741 (void) shutdown(net, 2); 1742 exit(1); 1743 # endif 1744 #else /* PARENT_DOES_UTMP */ 1745 # ifdef NEWINIT 1746 (void) shutdown(net, 2); 1747 exit(1); 1748 # else /* NEWINIT */ 1749 # ifdef CRAY 1750 static int incleanup = 0; 1751 register int t; 1752 1753 /* 1754 * 1: Pick up the zombie, if we are being called 1755 * as the signal handler. 1756 * 2: If we are a nested cleanup(), return. 1757 * 3: Try to clean up TMPDIR. 1758 * 4: Fill in utmp with shutdown of process. 1759 * 5: Close down the network and pty connections. 1760 * 6: Finish up the TMPDIR cleanup, if needed. 1761 */ 1762 if (sig == SIGCHLD) 1763 while (waitpid(-1, 0, WNOHANG) > 0) 1764 ; /* VOID */ 1765 t = sigblock(sigmask(SIGCHLD)); 1766 if (incleanup) { 1767 sigsetmask(t); 1768 return; 1769 } 1770 incleanup = 1; 1771 sigsetmask(t); 1772 if (secflag) { 1773 /* 1774 * We need to set ourselves back to a null 1775 * label to clean up. 1776 */ 1777 1778 setulvl(sysv.sy_minlvl); 1779 setucmp((long)0); 1780 } 1781 1782 t = cleantmp(&wtmp); 1783 setutent(); /* just to make sure */ 1784 # endif /* CRAY */ 1785 rmut(line); 1786 close(pty); 1787 (void) shutdown(net, 2); 1788 # ifdef CRAY 1789 if (t == 0) 1790 cleantmp(&wtmp); 1791 # endif /* CRAY */ 1792 exit(1); 1793 # endif /* NEWINT */ 1794 #endif /* PARENT_DOES_UTMP */ 1795 } 1796 1797 #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 1798 /* 1799 * _utmp_sig_rcv 1800 * utmp_sig_init 1801 * utmp_sig_wait 1802 * These three functions are used to coordinate the handling of 1803 * the utmp file between the server and the soon-to-be-login shell. 1804 * The server actually creates the utmp structure, the child calls 1805 * utmp_sig_wait(), until the server calls utmp_sig_notify() and 1806 * signals the future-login shell to proceed. 1807 */ 1808 static int caught=0; /* NZ when signal intercepted */ 1809 static void (*func)(); /* address of previous handler */ 1810 1811 void 1812 _utmp_sig_rcv(sig) 1813 int sig; 1814 { 1815 caught = 1; 1816 (void) signal(SIGUSR1, func); 1817 } 1818 1819 void 1820 utmp_sig_init() 1821 { 1822 /* 1823 * register signal handler for UTMP creation 1824 */ 1825 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 1826 fatalperror(net, "telnetd/signal"); 1827 } 1828 1829 void 1830 utmp_sig_reset() 1831 { 1832 (void) signal(SIGUSR1, func); /* reset handler to default */ 1833 } 1834 1835 # ifdef __hpux 1836 # define sigoff() /* do nothing */ 1837 # define sigon() /* do nothing */ 1838 # endif 1839 1840 void 1841 utmp_sig_wait() 1842 { 1843 /* 1844 * Wait for parent to write our utmp entry. 1845 */ 1846 sigoff(); 1847 while (caught == 0) { 1848 pause(); /* wait until we get a signal (sigon) */ 1849 sigoff(); /* turn off signals while we check caught */ 1850 } 1851 sigon(); /* turn on signals again */ 1852 } 1853 1854 void 1855 utmp_sig_notify(pid) 1856 { 1857 kill(pid, SIGUSR1); 1858 } 1859 1860 # ifdef CRAY 1861 static int gotsigjob = 0; 1862 1863 /*ARGSUSED*/ 1864 void 1865 sigjob(sig) 1866 int sig; 1867 { 1868 register int jid; 1869 register struct jobtemp *jp; 1870 1871 while ((jid = waitjob(NULL)) != -1) { 1872 if (jid == 0) { 1873 return; 1874 } 1875 gotsigjob++; 1876 jobend(jid, NULL, NULL); 1877 } 1878 } 1879 1880 /* 1881 * Clean up the TMPDIR that login created. 1882 * The first time this is called we pick up the info 1883 * from the utmp. If the job has already gone away, 1884 * then we'll clean up and be done. If not, then 1885 * when this is called the second time it will wait 1886 * for the signal that the job is done. 1887 */ 1888 int 1889 cleantmp(wtp) 1890 register struct utmp *wtp; 1891 { 1892 struct utmp *utp; 1893 static int first = 1; 1894 register int mask, omask, ret; 1895 extern struct utmp *getutid P((const struct utmp *_Id)); 1896 1897 1898 mask = sigmask(WJSIGNAL); 1899 1900 if (first == 0) { 1901 omask = sigblock(mask); 1902 while (gotsigjob == 0) 1903 sigpause(omask); 1904 return(1); 1905 } 1906 first = 0; 1907 setutent(); /* just to make sure */ 1908 1909 utp = getutid(wtp); 1910 if (utp == 0) { 1911 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 1912 return(-1); 1913 } 1914 /* 1915 * Nothing to clean up if the user shell was never started. 1916 */ 1917 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 1918 return(1); 1919 1920 /* 1921 * Block the WJSIGNAL while we are in jobend(). 1922 */ 1923 omask = sigblock(mask); 1924 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 1925 sigsetmask(omask); 1926 return(ret); 1927 } 1928 1929 int 1930 jobend(jid, path, user) 1931 register int jid; 1932 register char *path; 1933 register char *user; 1934 { 1935 static int saved_jid = 0; 1936 static char saved_path[sizeof(wtmp.ut_tpath)+1]; 1937 static char saved_user[sizeof(wtmp.ut_user)+1]; 1938 1939 if (path) { 1940 strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 1941 strncpy(saved_user, user, sizeof(wtmp.ut_user)); 1942 saved_path[sizeof(saved_path)] = '\0'; 1943 saved_user[sizeof(saved_user)] = '\0'; 1944 } 1945 if (saved_jid == 0) { 1946 saved_jid = jid; 1947 return(0); 1948 } 1949 cleantmpdir(jid, saved_path, saved_user); 1950 return(1); 1951 } 1952 1953 /* 1954 * Fork a child process to clean up the TMPDIR 1955 */ 1956 cleantmpdir(jid, tpath, user) 1957 register int jid; 1958 register char *tpath; 1959 register char *user; 1960 { 1961 switch(fork()) { 1962 case -1: 1963 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 1964 tpath); 1965 break; 1966 case 0: 1967 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 1968 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 1969 tpath, CLEANTMPCMD); 1970 exit(1); 1971 default: 1972 /* 1973 * Forget about child. We will exit, and 1974 * /etc/init will pick it up. 1975 */ 1976 break; 1977 } 1978 } 1979 # endif /* CRAY */ 1980 #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 1981 1982 /* 1983 * rmut() 1984 * 1985 * This is the function called by cleanup() to 1986 * remove the utmp entry for this person. 1987 */ 1988 1989 #ifdef UTMPX 1990 void 1991 rmut() 1992 { 1993 register f; 1994 int found = 0; 1995 struct utmp *u, *utmp; 1996 int nutmp; 1997 struct stat statbf; 1998 1999 struct utmpx *utxp, utmpx; 2000 2001 /* 2002 * This updates the utmpx and utmp entries and make a wtmp/x entry 2003 */ 2004 2005 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 2006 utxp = getutxline(&utmpx); 2007 if (utxp) { 2008 utxp->ut_type = DEAD_PROCESS; 2009 utxp->ut_exit.e_termination = 0; 2010 utxp->ut_exit.e_exit = 0; 2011 (void) time(&utmpx.ut_tv.tv_sec); 2012 utmpx.ut_tv.tv_usec = 0; 2013 modutx(utxp); 2014 } 2015 endutxent(); 2016 } /* end of rmut */ 2017 #endif 2018 2019 #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 2020 void 2021 rmut() 2022 { 2023 register f; 2024 int found = 0; 2025 struct utmp *u, *utmp; 2026 int nutmp; 2027 struct stat statbf; 2028 2029 f = open(utmpf, O_RDWR); 2030 if (f >= 0) { 2031 (void) fstat(f, &statbf); 2032 utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 2033 if (!utmp) 2034 syslog(LOG_ERR, "utmp malloc failed"); 2035 if (statbf.st_size && utmp) { 2036 nutmp = read(f, (char *)utmp, (int)statbf.st_size); 2037 nutmp /= sizeof(struct utmp); 2038 2039 for (u = utmp ; u < &utmp[nutmp] ; u++) { 2040 if (SCMPN(u->ut_line, line+5) || 2041 u->ut_name[0]==0) 2042 continue; 2043 (void) lseek(f, ((long)u)-((long)utmp), L_SET); 2044 SCPYN(u->ut_name, ""); 2045 SCPYN(u->ut_host, ""); 2046 (void) time(&u->ut_time); 2047 (void) write(f, (char *)u, sizeof(wtmp)); 2048 found++; 2049 } 2050 } 2051 (void) close(f); 2052 } 2053 if (found) { 2054 f = open(wtmpf, O_WRONLY|O_APPEND); 2055 if (f >= 0) { 2056 SCPYN(wtmp.ut_line, line+5); 2057 SCPYN(wtmp.ut_name, ""); 2058 SCPYN(wtmp.ut_host, ""); 2059 (void) time(&wtmp.ut_time); 2060 (void) write(f, (char *)&wtmp, sizeof(wtmp)); 2061 (void) close(f); 2062 } 2063 } 2064 (void) chmod(line, 0666); 2065 (void) chown(line, 0, 0); 2066 line[strlen("/dev/")] = 'p'; 2067 (void) chmod(line, 0666); 2068 (void) chown(line, 0, 0); 2069 } /* end of rmut */ 2070 #endif /* CRAY */ 2071 2072 #ifdef __hpux 2073 rmut (line) 2074 char *line; 2075 { 2076 struct utmp utmp; 2077 struct utmp *utptr; 2078 int fd; /* for /etc/wtmp */ 2079 2080 utmp.ut_type = USER_PROCESS; 2081 (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 2082 (void) setutent(); 2083 utptr = getutid(&utmp); 2084 /* write it out only if it exists */ 2085 if (utptr) { 2086 utptr->ut_type = DEAD_PROCESS; 2087 utptr->ut_time = time((long *) 0); 2088 (void) pututline(utptr); 2089 /* set wtmp entry if wtmp file exists */ 2090 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 2091 (void) write(fd, utptr, sizeof(utmp)); 2092 (void) close(fd); 2093 } 2094 } 2095 (void) endutent(); 2096 2097 (void) chmod(line, 0666); 2098 (void) chown(line, 0, 0); 2099 line[14] = line[13]; 2100 line[13] = line[12]; 2101 line[8] = 'm'; 2102 line[9] = '/'; 2103 line[10] = 'p'; 2104 line[11] = 't'; 2105 line[12] = 'y'; 2106 (void) chmod(line, 0666); 2107 (void) chown(line, 0, 0); 2108 } 2109 #endif 2110