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