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