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