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