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.16 (Berkeley) 03/22/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 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 971 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 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 # if defined(CRAY) && defined(SESS_CTTY) /* SESS_CTTY is in param.h */ 1059 /* 1060 * Close the hard fd to /dev/ttypXXX, and re-open through 1061 * the indirect /dev/tty interface. 1062 */ 1063 close(t); 1064 if ((t = open("/dev/tty", O_RDWR)) < 0) 1065 fatalperror(net, "open(/dev/tty)"); 1066 # endif 1067 # else 1068 close(open(line, O_RDWR)); 1069 # endif 1070 if (t != 0) 1071 (void) dup2(t, 0); 1072 if (t != 1) 1073 (void) dup2(t, 1); 1074 if (t != 2) 1075 (void) dup2(t, 2); 1076 if (t > 2) 1077 close(t); 1078 return(0); 1079 } 1080 #endif /* BSD <= 43 */ 1081 1082 #ifdef NEWINIT 1083 char *gen_id = "fe"; 1084 #endif 1085 1086 /* 1087 * startslave(host) 1088 * 1089 * Given a hostname, do whatever 1090 * is necessary to startup the login process on the slave side of the pty. 1091 */ 1092 1093 /* ARGSUSED */ 1094 void 1095 startslave(host, autologin, autoname) 1096 char *host; 1097 int autologin; 1098 char *autoname; 1099 { 1100 register int i; 1101 long time(); 1102 char name[256]; 1103 #ifdef NEWINIT 1104 extern char *ptyip; 1105 struct init_request request; 1106 void nologinproc(); 1107 register int n; 1108 #endif /* NEWINIT */ 1109 1110 #if defined(AUTHENTICATE) 1111 if (!autoname || !autoname[0]) 1112 autologin = 0; 1113 1114 if (autologin < auth_level) { 1115 fatal(net, "Authorization failed"); 1116 exit(1); 1117 } 1118 #endif 1119 1120 #ifndef NEWINIT 1121 # ifdef CRAY 1122 utmp_sig_init(); 1123 # endif /* CRAY */ 1124 1125 if ((i = fork()) < 0) 1126 fatalperror(net, "fork"); 1127 if (i) { 1128 # ifdef CRAY 1129 /* 1130 * Cray parent will create utmp entry for child and send 1131 * signal to child to tell when done. Child waits for signal 1132 * before doing anything important. 1133 */ 1134 register int pid = i; 1135 void sigjob P((int)); 1136 1137 setpgrp(); 1138 utmp_sig_reset(); /* reset handler to default */ 1139 /* 1140 * Create utmp entry for child 1141 */ 1142 (void) time(&wtmp.ut_time); 1143 wtmp.ut_type = LOGIN_PROCESS; 1144 wtmp.ut_pid = pid; 1145 SCPYN(wtmp.ut_user, "LOGIN"); 1146 SCPYN(wtmp.ut_host, host); 1147 SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 1148 SCPYN(wtmp.ut_id, wtmp.ut_line+3); 1149 pututline(&wtmp); 1150 endutent(); 1151 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 1152 (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 1153 (void) close(i); 1154 } 1155 (void) signal(WJSIGNAL, sigjob); 1156 utmp_sig_notify(pid); 1157 # endif /* CRAY */ 1158 } else { 1159 getptyslave(); 1160 start_login(host, autologin, autoname); 1161 /*NOTREACHED*/ 1162 } 1163 #else /* NEWINIT */ 1164 1165 /* 1166 * Init will start up login process if we ask nicely. We only wait 1167 * for it to start up and begin normal telnet operation. 1168 */ 1169 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 1170 char tbuf[128]; 1171 (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 1172 fatalperror(net, tbuf); 1173 } 1174 memset((char *)&request, 0, sizeof(request)); 1175 request.magic = INIT_MAGIC; 1176 SCPYN(request.gen_id, gen_id); 1177 SCPYN(request.tty_id, &line[8]); 1178 SCPYN(request.host, host); 1179 SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 1180 #if !defined(UNICOS5) 1181 request.signal = SIGCLD; 1182 request.pid = getpid(); 1183 #endif 1184 #ifdef BFTPDAEMON 1185 /* 1186 * Are we working as the bftp daemon? 1187 */ 1188 if (bftpd) { 1189 SCPYN(request.exec_name, BFTPPATH); 1190 } 1191 #endif /* BFTPDAEMON */ 1192 if (write(i, (char *)&request, sizeof(request)) < 0) { 1193 char tbuf[128]; 1194 (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 1195 fatalperror(net, tbuf); 1196 } 1197 (void) close(i); 1198 (void) signal(SIGALRM, nologinproc); 1199 for (i = 0; ; i++) { 1200 char tbuf[128]; 1201 alarm(15); 1202 n = read(pty, ptyip, BUFSIZ); 1203 if (i == 3 || n >= 0 || !gotalarm) 1204 break; 1205 gotalarm = 0; 1206 sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 1207 (void) write(net, tbuf, strlen(tbuf)); 1208 } 1209 if (n < 0 && gotalarm) 1210 fatal(net, "/etc/init didn't start login process"); 1211 pcc += n; 1212 alarm(0); 1213 (void) signal(SIGALRM, SIG_DFL); 1214 1215 return; 1216 #endif /* NEWINIT */ 1217 } 1218 1219 char *envinit[3]; 1220 extern char **environ; 1221 1222 void 1223 init_env() 1224 { 1225 extern char *getenv(); 1226 char **envp; 1227 1228 envp = envinit; 1229 if (*envp = getenv("TZ")) 1230 *envp++ -= 3; 1231 #ifdef CRAY 1232 else 1233 *envp++ = "TZ=GMT0"; 1234 #endif 1235 *envp = 0; 1236 environ = envinit; 1237 } 1238 1239 #ifndef NEWINIT 1240 1241 /* 1242 * start_login(host) 1243 * 1244 * Assuming that we are now running as a child processes, this 1245 * function will turn us into the login process. 1246 */ 1247 1248 void 1249 start_login(host, autologin, name) 1250 char *host; 1251 int autologin; 1252 char *name; 1253 { 1254 register char *cp; 1255 register char **argv; 1256 char **addarg(); 1257 1258 /* 1259 * -h : pass on name of host. 1260 * WARNING: -h is accepted by login if and only if 1261 * getuid() == 0. 1262 * -p : don't clobber the environment (so terminal type stays set). 1263 * 1264 * -f : force this login, he has already been authenticated 1265 */ 1266 argv = addarg(0, "login"); 1267 argv = addarg(argv, "-h"); 1268 argv = addarg(argv, host); 1269 #if !defined(NO_LOGIN_P) 1270 argv = addarg(argv, "-p"); 1271 #endif 1272 #ifdef BFTPDAEMON 1273 /* 1274 * Are we working as the bftp daemon? If so, then ask login 1275 * to start bftp instead of shell. 1276 */ 1277 if (bftpd) { 1278 argv = addarg(argv, "-e"); 1279 argv = addarg(argv, BFTPPATH); 1280 } else 1281 #endif 1282 #if defined (SecurID) 1283 /* 1284 * don't worry about the -f that might get sent. 1285 * A -s is supposed to override it anyhow. 1286 */ 1287 if (require_SecurID) 1288 argv = addarg(argv, "-s"); 1289 #endif 1290 #if defined (AUTHENTICATE) 1291 if (auth_level >= 0 && autologin == AUTH_VALID) { 1292 # if !defined(NO_LOGIN_F) 1293 argv = addarg(argv, "-f"); 1294 # endif 1295 argv = addarg(argv, name); 1296 } else 1297 #endif 1298 if (getenv("USER")) { 1299 argv = addarg(argv, getenv("USER")); 1300 #if defined(CRAY) && defined(NO_LOGIN_P) 1301 { 1302 register char **cpp; 1303 for (cpp = environ; *cpp; cpp++) 1304 argv = addarg(argv, *cpp); 1305 } 1306 #endif 1307 } 1308 closelog(); 1309 execv(_PATH_LOGIN, argv); 1310 1311 syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 1312 fatalperror(net, _PATH_LOGIN); 1313 /*NOTREACHED*/ 1314 } 1315 1316 char ** 1317 addarg(argv, val) 1318 register char **argv; 1319 register char *val; 1320 { 1321 register char **cpp; 1322 1323 if (argv == NULL) { 1324 /* 1325 * 10 entries, a leading length, and a null 1326 */ 1327 argv = (char **)malloc(sizeof(*argv) * 12); 1328 if (argv == NULL) 1329 return(NULL); 1330 *argv++ = (char *)10; 1331 *argv = (char *)0; 1332 } 1333 for (cpp = argv; *cpp; cpp++) 1334 ; 1335 if (cpp == &argv[(int)argv[-1]]) { 1336 --argv; 1337 *argv = (char *)((int)(*argv) + 10); 1338 argv = (char **)realloc(argv, (int)(*argv) + 2); 1339 if (argv == NULL) 1340 return(NULL); 1341 argv++; 1342 cpp = &argv[(int)argv[-1] - 10]; 1343 } 1344 *cpp++ = val; 1345 *cpp = 0; 1346 return(argv); 1347 } 1348 #endif /* NEWINIT */ 1349 1350 /* 1351 * cleanup() 1352 * 1353 * This is the routine to call when we are all through, to 1354 * clean up anything that needs to be cleaned up. 1355 */ 1356 /* ARGSUSED */ 1357 void 1358 cleanup(sig) 1359 int sig; 1360 { 1361 #ifndef CRAY 1362 # if (BSD > 43) || defined(convex) 1363 char *p; 1364 1365 p = line + sizeof("/dev/") - 1; 1366 if (logout(p)) 1367 logwtmp(p, "", ""); 1368 (void)chmod(line, 0666); 1369 (void)chown(line, 0, 0); 1370 *p = 'p'; 1371 (void)chmod(line, 0666); 1372 (void)chown(line, 0, 0); 1373 (void) shutdown(net, 2); 1374 exit(1); 1375 # else 1376 void rmut(); 1377 1378 rmut(); 1379 vhangup(); /* XXX */ 1380 (void) shutdown(net, 2); 1381 exit(1); 1382 # endif 1383 #else /* CRAY */ 1384 # ifdef NEWINIT 1385 (void) shutdown(net, 2); 1386 exit(1); 1387 # else /* NEWINIT */ 1388 static int incleanup = 0; 1389 register int t; 1390 1391 /* 1392 * 1: Pick up the zombie, if we are being called 1393 * as the signal handler. 1394 * 2: If we are a nested cleanup(), return. 1395 * 3: Try to clean up TMPDIR. 1396 * 4: Fill in utmp with shutdown of process. 1397 * 5: Close down the network and pty connections. 1398 * 6: Finish up the TMPDIR cleanup, if needed. 1399 */ 1400 if (sig == SIGCHLD) 1401 while (waitpid(-1, 0, WNOHANG) > 0) 1402 ; /* VOID */ 1403 t = sigblock(sigmask(SIGCHLD)); 1404 if (incleanup) { 1405 sigsetmask(t); 1406 return; 1407 } 1408 incleanup = 1; 1409 sigsetmask(t); 1410 1411 t = cleantmp(&wtmp); 1412 setutent(); /* just to make sure */ 1413 rmut(line); 1414 close(pty); 1415 (void) shutdown(net, 2); 1416 if (t == 0) 1417 cleantmp(&wtmp); 1418 exit(1); 1419 # endif /* NEWINT */ 1420 #endif /* CRAY */ 1421 } 1422 1423 #if defined(CRAY) && !defined(NEWINIT) 1424 /* 1425 * _utmp_sig_rcv 1426 * utmp_sig_init 1427 * utmp_sig_wait 1428 * These three functions are used to coordinate the handling of 1429 * the utmp file between the server and the soon-to-be-login shell. 1430 * The server actually creates the utmp structure, the child calls 1431 * utmp_sig_wait(), until the server calls utmp_sig_notify() and 1432 * signals the future-login shell to proceed. 1433 */ 1434 static int caught=0; /* NZ when signal intercepted */ 1435 static void (*func)(); /* address of previous handler */ 1436 1437 void 1438 _utmp_sig_rcv(sig) 1439 int sig; 1440 { 1441 caught = 1; 1442 (void) signal(SIGUSR1, func); 1443 } 1444 1445 void 1446 utmp_sig_init() 1447 { 1448 /* 1449 * register signal handler for UTMP creation 1450 */ 1451 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 1452 fatalperror(net, "telnetd/signal"); 1453 } 1454 1455 void 1456 utmp_sig_reset() 1457 { 1458 (void) signal(SIGUSR1, func); /* reset handler to default */ 1459 } 1460 1461 void 1462 utmp_sig_wait() 1463 { 1464 /* 1465 * Wait for parent to write our utmp entry. 1466 */ 1467 sigoff(); 1468 while (caught == 0) { 1469 pause(); /* wait until we get a signal (sigon) */ 1470 sigoff(); /* turn off signals while we check caught */ 1471 } 1472 sigon(); /* turn on signals again */ 1473 } 1474 1475 void 1476 utmp_sig_notify(pid) 1477 { 1478 kill(pid, SIGUSR1); 1479 } 1480 1481 static int gotsigjob = 0; 1482 1483 /*ARGSUSED*/ 1484 void 1485 sigjob(sig) 1486 int sig; 1487 { 1488 register int jid; 1489 register struct jobtemp *jp; 1490 1491 while ((jid = waitjob(NULL)) != -1) { 1492 if (jid == 0) { 1493 return; 1494 } 1495 gotsigjob++; 1496 jobend(jid, NULL, NULL); 1497 } 1498 } 1499 1500 /* 1501 * Clean up the TMPDIR that login created. 1502 * The first time this is called we pick up the info 1503 * from the utmp. If the job has already gone away, 1504 * then we'll clean up and be done. If not, then 1505 * when this is called the second time it will wait 1506 * for the signal that the job is done. 1507 */ 1508 int 1509 cleantmp(wtp) 1510 register struct utmp *wtp; 1511 { 1512 struct utmp *utp; 1513 static int first = 1; 1514 register int mask, omask, ret; 1515 extern struct utmp *getutid P((struct utmp *)); 1516 1517 mask = sigmask(WJSIGNAL); 1518 1519 if (first == 0) { 1520 omask = sigblock(mask); 1521 while (gotsigjob == 0) 1522 sigpause(omask); 1523 return(1); 1524 } 1525 first = 0; 1526 setutent(); /* just to make sure */ 1527 1528 utp = getutid(wtp); 1529 if (utp == 0) { 1530 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 1531 return(-1); 1532 } 1533 /* 1534 * Nothing to clean up if the user shell was never started. 1535 */ 1536 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 1537 return(1); 1538 1539 /* 1540 * Block the WJSIGNAL while we are in jobend(). 1541 */ 1542 omask = sigblock(mask); 1543 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 1544 sigsetmask(omask); 1545 return(ret); 1546 } 1547 1548 int 1549 jobend(jid, path, user) 1550 register int jid; 1551 register char *path; 1552 register char *user; 1553 { 1554 static int saved_jid = 0; 1555 static char saved_path[sizeof(wtmp.ut_tpath)+1]; 1556 static char saved_user[sizeof(wtmp.ut_user)+1]; 1557 1558 if (path) { 1559 strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 1560 strncpy(saved_user, user, sizeof(wtmp.ut_user)); 1561 saved_path[sizeof(saved_path)] = '\0'; 1562 saved_user[sizeof(saved_user)] = '\0'; 1563 } 1564 if (saved_jid == 0) { 1565 saved_jid = jid; 1566 return(0); 1567 } 1568 cleantmpdir(jid, saved_path, saved_user); 1569 return(1); 1570 } 1571 1572 /* 1573 * Fork a child process to clean up the TMPDIR 1574 */ 1575 cleantmpdir(jid, tpath, user) 1576 register int jid; 1577 register char *tpath; 1578 register char *user; 1579 { 1580 switch(fork()) { 1581 case -1: 1582 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 1583 tpath); 1584 break; 1585 case 0: 1586 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 1587 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 1588 tpath, CLEANTMPCMD); 1589 exit(1); 1590 default: 1591 /* 1592 * Forget about child. We will exit, and 1593 * /etc/init will pick it up. 1594 */ 1595 break; 1596 } 1597 } 1598 #endif /* defined(CRAY) && !defined(NEWINIT) */ 1599 1600 /* 1601 * rmut() 1602 * 1603 * This is the function called by cleanup() to 1604 * remove the utmp entry for this person. 1605 */ 1606 1607 #if !defined(CRAY) && BSD <= 43 1608 void 1609 rmut() 1610 { 1611 register f; 1612 int found = 0; 1613 struct utmp *u, *utmp; 1614 int nutmp; 1615 struct stat statbf; 1616 1617 f = open(utmpf, O_RDWR); 1618 if (f >= 0) { 1619 (void) fstat(f, &statbf); 1620 utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 1621 if (!utmp) 1622 syslog(LOG_ERR, "utmp malloc failed"); 1623 if (statbf.st_size && utmp) { 1624 nutmp = read(f, (char *)utmp, (int)statbf.st_size); 1625 nutmp /= sizeof(struct utmp); 1626 1627 for (u = utmp ; u < &utmp[nutmp] ; u++) { 1628 if (SCMPN(u->ut_line, line+5) || 1629 u->ut_name[0]==0) 1630 continue; 1631 (void) lseek(f, ((long)u)-((long)utmp), L_SET); 1632 SCPYN(u->ut_name, ""); 1633 SCPYN(u->ut_host, ""); 1634 (void) time(&u->ut_time); 1635 (void) write(f, (char *)u, sizeof(wtmp)); 1636 found++; 1637 } 1638 } 1639 (void) close(f); 1640 } 1641 if (found) { 1642 f = open(wtmpf, O_WRONLY|O_APPEND); 1643 if (f >= 0) { 1644 SCPYN(wtmp.ut_line, line+5); 1645 SCPYN(wtmp.ut_name, ""); 1646 SCPYN(wtmp.ut_host, ""); 1647 (void) time(&wtmp.ut_time); 1648 (void) write(f, (char *)&wtmp, sizeof(wtmp)); 1649 (void) close(f); 1650 } 1651 } 1652 (void) chmod(line, 0666); 1653 (void) chown(line, 0, 0); 1654 line[strlen("/dev/")] = 'p'; 1655 (void) chmod(line, 0666); 1656 (void) chown(line, 0, 0); 1657 } /* end of rmut */ 1658 #endif /* CRAY */ 1659