1 /* $NetBSD: sys_term.c,v 1.23 2001/07/19 04:57:50 itojun Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; 40 #else 41 __RCSID("$NetBSD: sys_term.c,v 1.23 2001/07/19 04:57:50 itojun Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include "telnetd.h" 46 #include "pathnames.h" 47 48 #include <util.h> 49 50 #include <sys/cdefs.h> 51 #define P __P 52 53 #if defined(CRAY) || defined(__hpux) 54 # define PARENT_DOES_UTMP 55 #endif 56 57 #ifdef NEWINIT 58 #include <initreq.h> 59 int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */ 60 #else /* NEWINIT*/ 61 # ifdef UTMPX 62 # include <utmpx.h> 63 struct utmpx wtmp; 64 # else 65 # include <utmp.h> 66 struct utmp wtmp; 67 # endif /* UTMPX */ 68 69 int utmp_len = sizeof(wtmp.ut_host); 70 # ifndef PARENT_DOES_UTMP 71 char wtmpf[] = "/usr/adm/wtmp"; 72 char utmpf[] = "/etc/utmp"; 73 # else /* PARENT_DOES_UTMP */ 74 char wtmpf[] = "/etc/wtmp"; 75 # endif /* PARENT_DOES_UTMP */ 76 77 # ifdef CRAY 78 #include <tmpdir.h> 79 #include <sys/wait.h> 80 # if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') 81 # define UNICOS7x 82 # endif 83 84 # ifdef UNICOS7x 85 #include <sys/sysv.h> 86 #include <sys/secstat.h> 87 extern int secflag; 88 extern struct sysv sysv; 89 # endif /* UNICOS7x */ 90 # endif /* CRAY */ 91 #endif /* NEWINIT */ 92 93 #ifdef STREAMSPTY 94 #include <sac.h> 95 #include <sys/stropts.h> 96 #endif 97 98 #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 99 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 100 101 #ifdef STREAMS 102 #include <sys/stream.h> 103 #endif 104 #ifdef __hpux 105 #include <sys/resource.h> 106 #include <sys/proc.h> 107 #endif 108 #ifdef t_erase 109 #undef t_erase 110 #undef t_kill 111 #undef t_intrc 112 #undef t_quitc 113 #undef t_startc 114 #undef t_stopc 115 #undef t_eofc 116 #undef t_brkc 117 #undef t_suspc 118 #undef t_dsuspc 119 #undef t_rprntc 120 #undef t_flushc 121 #undef t_werasc 122 #undef t_lnextc 123 #endif 124 125 #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 126 # define EXTPROC 0400 127 #endif 128 129 #ifndef USE_TERMIO 130 struct termbuf { 131 struct sgttyb sg; 132 struct tchars tc; 133 struct ltchars ltc; 134 int state; 135 int lflags; 136 } termbuf, termbuf2; 137 # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 138 # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 139 # define cfgetospeed(tp) (tp)->sg.sg_ospeed 140 # define cfgetispeed(tp) (tp)->sg.sg_ispeed 141 #else /* USE_TERMIO */ 142 # ifdef SYSV_TERMIO 143 # define termios termio 144 # endif 145 # ifndef TCSANOW 146 # ifdef TCSETS 147 # define TCSANOW TCSETS 148 # define TCSADRAIN TCSETSW 149 # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 150 # else 151 # ifdef TCSETA 152 # define TCSANOW TCSETA 153 # define TCSADRAIN TCSETAW 154 # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 155 # else 156 # define TCSANOW TIOCSETA 157 # define TCSADRAIN TIOCSETAW 158 # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 159 # endif 160 # endif 161 # define tcsetattr(f, a, t) ioctl(f, a, t) 162 # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 163 (tp)->c_cflag |= (val) 164 # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 165 # ifdef CIBAUD 166 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 167 (tp)->c_cflag |= ((val)<<IBSHIFT) 168 # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 169 # else 170 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 171 (tp)->c_cflag |= (val) 172 # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 173 # endif 174 # endif /* TCSANOW */ 175 struct termios termbuf, termbuf2; /* pty control structure */ 176 # ifdef STREAMSPTY 177 int ttyfd = -1; 178 # endif 179 #endif /* USE_TERMIO */ 180 181 void getptyslave __P((void)); 182 int cleanopen __P((char *)); 183 char **addarg __P((char **, char *)); 184 void scrub_env __P((void)); 185 int getent __P((char *, char *)); 186 char *getstr __P((const char *, char **)); 187 #ifdef KRB5 188 extern void kerberos5_cleanup __P((void)); 189 #endif 190 191 /* 192 * init_termbuf() 193 * copy_termbuf(cp) 194 * set_termbuf() 195 * 196 * These three routines are used to get and set the "termbuf" structure 197 * to and from the kernel. init_termbuf() gets the current settings. 198 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 199 * set_termbuf() writes the structure into the kernel. 200 */ 201 202 void 203 init_termbuf() 204 { 205 #ifndef USE_TERMIO 206 (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 207 (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 208 (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 209 # ifdef TIOCGSTATE 210 (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 211 # endif 212 #else 213 # ifdef STREAMSPTY 214 (void) tcgetattr(ttyfd, &termbuf); 215 # else 216 (void) tcgetattr(pty, &termbuf); 217 # endif 218 #endif 219 termbuf2 = termbuf; 220 } 221 222 #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 223 void 224 copy_termbuf(cp, len) 225 char *cp; 226 int len; 227 { 228 if (len > sizeof(termbuf)) 229 len = sizeof(termbuf); 230 memmove((char *)&termbuf, cp, len); 231 termbuf2 = termbuf; 232 } 233 #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 234 235 void 236 set_termbuf() 237 { 238 /* 239 * Only make the necessary changes. 240 */ 241 #ifndef USE_TERMIO 242 if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, 243 sizeof(termbuf.sg))) 244 (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 245 if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, 246 sizeof(termbuf.tc))) 247 (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 248 if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 249 sizeof(termbuf.ltc))) 250 (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 251 if (termbuf.lflags != termbuf2.lflags) 252 (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 253 #else /* USE_TERMIO */ 254 if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 255 # ifdef STREAMSPTY 256 (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 257 # else 258 (void) tcsetattr(pty, TCSANOW, &termbuf); 259 # endif 260 # if defined(CRAY2) && defined(UNICOS5) 261 needtermstat = 1; 262 # endif 263 #endif /* USE_TERMIO */ 264 } 265 266 267 /* 268 * spcset(func, valp, valpp) 269 * 270 * This function takes various special characters (func), and 271 * sets *valp to the current value of that character, and 272 * *valpp to point to where in the "termbuf" structure that 273 * value is kept. 274 * 275 * It returns the SLC_ level of support for this function. 276 */ 277 278 #ifndef USE_TERMIO 279 int 280 spcset(func, valp, valpp) 281 int func; 282 cc_t *valp; 283 cc_t **valpp; 284 { 285 switch(func) { 286 case SLC_EOF: 287 *valp = termbuf.tc.t_eofc; 288 *valpp = (cc_t *)&termbuf.tc.t_eofc; 289 return(SLC_VARIABLE); 290 case SLC_EC: 291 *valp = termbuf.sg.sg_erase; 292 *valpp = (cc_t *)&termbuf.sg.sg_erase; 293 return(SLC_VARIABLE); 294 case SLC_EL: 295 *valp = termbuf.sg.sg_kill; 296 *valpp = (cc_t *)&termbuf.sg.sg_kill; 297 return(SLC_VARIABLE); 298 case SLC_IP: 299 *valp = termbuf.tc.t_intrc; 300 *valpp = (cc_t *)&termbuf.tc.t_intrc; 301 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 302 case SLC_ABORT: 303 *valp = termbuf.tc.t_quitc; 304 *valpp = (cc_t *)&termbuf.tc.t_quitc; 305 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 306 case SLC_XON: 307 *valp = termbuf.tc.t_startc; 308 *valpp = (cc_t *)&termbuf.tc.t_startc; 309 return(SLC_VARIABLE); 310 case SLC_XOFF: 311 *valp = termbuf.tc.t_stopc; 312 *valpp = (cc_t *)&termbuf.tc.t_stopc; 313 return(SLC_VARIABLE); 314 case SLC_AO: 315 *valp = termbuf.ltc.t_flushc; 316 *valpp = (cc_t *)&termbuf.ltc.t_flushc; 317 return(SLC_VARIABLE); 318 case SLC_SUSP: 319 *valp = termbuf.ltc.t_suspc; 320 *valpp = (cc_t *)&termbuf.ltc.t_suspc; 321 return(SLC_VARIABLE); 322 case SLC_EW: 323 *valp = termbuf.ltc.t_werasc; 324 *valpp = (cc_t *)&termbuf.ltc.t_werasc; 325 return(SLC_VARIABLE); 326 case SLC_RP: 327 *valp = termbuf.ltc.t_rprntc; 328 *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 329 return(SLC_VARIABLE); 330 case SLC_LNEXT: 331 *valp = termbuf.ltc.t_lnextc; 332 *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 333 return(SLC_VARIABLE); 334 case SLC_FORW1: 335 *valp = termbuf.tc.t_brkc; 336 *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 337 return(SLC_VARIABLE); 338 case SLC_BRK: 339 case SLC_SYNCH: 340 case SLC_AYT: 341 case SLC_EOR: 342 *valp = (cc_t)0; 343 *valpp = (cc_t *)0; 344 return(SLC_DEFAULT); 345 default: 346 *valp = (cc_t)0; 347 *valpp = (cc_t *)0; 348 return(SLC_NOSUPPORT); 349 } 350 } 351 352 #else /* USE_TERMIO */ 353 354 int 355 spcset(func, valp, valpp) 356 int func; 357 cc_t *valp; 358 cc_t **valpp; 359 { 360 361 #define setval(a, b) *valp = termbuf.c_cc[a]; \ 362 *valpp = &termbuf.c_cc[a]; \ 363 return(b); 364 #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 365 366 switch(func) { 367 case SLC_EOF: 368 setval(VEOF, SLC_VARIABLE); 369 case SLC_EC: 370 setval(VERASE, SLC_VARIABLE); 371 case SLC_EL: 372 setval(VKILL, SLC_VARIABLE); 373 case SLC_IP: 374 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 375 case SLC_ABORT: 376 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 377 case SLC_XON: 378 #ifdef VSTART 379 setval(VSTART, SLC_VARIABLE); 380 #else 381 defval(0x13); 382 #endif 383 case SLC_XOFF: 384 #ifdef VSTOP 385 setval(VSTOP, SLC_VARIABLE); 386 #else 387 defval(0x11); 388 #endif 389 case SLC_EW: 390 #ifdef VWERASE 391 setval(VWERASE, SLC_VARIABLE); 392 #else 393 defval(0); 394 #endif 395 case SLC_RP: 396 #ifdef VREPRINT 397 setval(VREPRINT, SLC_VARIABLE); 398 #else 399 defval(0); 400 #endif 401 case SLC_LNEXT: 402 #ifdef VLNEXT 403 setval(VLNEXT, SLC_VARIABLE); 404 #else 405 defval(0); 406 #endif 407 case SLC_AO: 408 #if !defined(VDISCARD) && defined(VFLUSHO) 409 # define VDISCARD VFLUSHO 410 #endif 411 #ifdef VDISCARD 412 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 413 #else 414 defval(0); 415 #endif 416 case SLC_SUSP: 417 #ifdef VSUSP 418 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 419 #else 420 defval(0); 421 #endif 422 #ifdef VEOL 423 case SLC_FORW1: 424 setval(VEOL, SLC_VARIABLE); 425 #endif 426 #ifdef VEOL2 427 case SLC_FORW2: 428 setval(VEOL2, SLC_VARIABLE); 429 #endif 430 case SLC_AYT: 431 #ifdef VSTATUS 432 setval(VSTATUS, SLC_VARIABLE); 433 #else 434 defval(0); 435 #endif 436 437 case SLC_BRK: 438 case SLC_SYNCH: 439 case SLC_EOR: 440 defval(0); 441 442 default: 443 *valp = 0; 444 *valpp = 0; 445 return(SLC_NOSUPPORT); 446 } 447 } 448 #endif /* USE_TERMIO */ 449 450 #ifdef CRAY 451 /* 452 * getnpty() 453 * 454 * Return the number of pty's configured into the system. 455 */ 456 int 457 getnpty() 458 { 459 #ifdef _SC_CRAY_NPTY 460 int numptys; 461 462 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 463 return numptys; 464 else 465 #endif /* _SC_CRAY_NPTY */ 466 return 128; 467 } 468 #endif /* CRAY */ 469 470 #ifndef convex 471 /* 472 * getpty() 473 * 474 * Allocate a pty. As a side effect, the external character 475 * array "line" contains the name of the slave side. 476 * 477 * Returns the file descriptor of the opened pty. 478 */ 479 #ifndef __GNUC__ 480 char *line = NULL16STR; 481 #else 482 static char Xline[] = NULL16STR; 483 char *line = Xline; 484 #endif 485 #ifdef CRAY 486 char *myline = NULL16STR; 487 #endif /* CRAY */ 488 489 #ifdef OPENPTY_PTY 490 491 static int ptyslavefd; /* for cleanopen() */ 492 493 int 494 getpty(ptynum) 495 int *ptynum; 496 { 497 int ptyfd; 498 499 ptyfd = openpty(ptynum, &ptyslavefd, line, NULL, NULL); 500 if (ptyfd == 0) 501 return *ptynum; 502 ptyslavefd = -1; 503 return (-1); 504 } 505 #else /* ! OPENPTY_PTY */ 506 507 int 508 getpty(ptynum) 509 int *ptynum; 510 { 511 register int p; 512 #ifdef STREAMSPTY 513 int t; 514 char *ptsname(); 515 516 p = open("/dev/ptmx", 2); 517 if (p > 0) { 518 grantpt(p); 519 unlockpt(p); 520 (void)strlcpy(line, ptsname(p), sizeof(NULL16STR)); 521 return(p); 522 } 523 524 #else /* ! STREAMSPTY */ 525 #ifndef CRAY 526 register char *cp, *p1, *p2; 527 register int i; 528 #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 529 int dummy; 530 #endif 531 532 #ifndef __hpux 533 (void) sprintf(line, "/dev/ptyXX"); 534 p1 = &line[8]; 535 p2 = &line[9]; 536 #else 537 (void) sprintf(line, "/dev/ptym/ptyXX"); 538 p1 = &line[13]; 539 p2 = &line[14]; 540 #endif 541 542 for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { 543 struct stat stb; 544 545 *p1 = *cp; 546 *p2 = '0'; 547 /* 548 * This stat() check is just to keep us from 549 * looping through all 256 combinations if there 550 * aren't that many ptys available. 551 */ 552 if (stat(line, &stb) < 0) 553 break; 554 for (i = 0; i < 16; i++) { 555 *p2 = "0123456789abcdef"[i]; 556 p = open(line, 2); 557 if (p > 0) { 558 #ifndef __hpux 559 line[5] = 't'; 560 #else 561 for (p1 = &line[8]; *p1; p1++) 562 *p1 = *(p1+1); 563 line[9] = 't'; 564 #endif 565 chown(line, 0, 0); 566 chmod(line, 0600); 567 #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 568 if (ioctl(p, TIOCGPGRP, &dummy) == 0 569 || errno != EIO) { 570 chmod(line, 0666); 571 close(p); 572 line[5] = 'p'; 573 } else 574 #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ 575 return(p); 576 } 577 } 578 } 579 #else /* CRAY */ 580 extern lowpty, highpty; 581 struct stat sb; 582 583 for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { 584 (void) sprintf(myline, "/dev/pty/%03d", *ptynum); 585 p = open(myline, 2); 586 if (p < 0) 587 continue; 588 (void) sprintf(line, "/dev/ttyp%03d", *ptynum); 589 /* 590 * Here are some shenanigans to make sure that there 591 * are no listeners lurking on the line. 592 */ 593 if(stat(line, &sb) < 0) { 594 (void) close(p); 595 continue; 596 } 597 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 598 chown(line, 0, 0); 599 chmod(line, 0600); 600 (void)close(p); 601 p = open(myline, 2); 602 if (p < 0) 603 continue; 604 } 605 /* 606 * Now it should be safe...check for accessability. 607 */ 608 if (access(line, 6) == 0) 609 return(p); 610 else { 611 /* no tty side to pty so skip it */ 612 (void) close(p); 613 } 614 } 615 #endif /* CRAY */ 616 #endif /* STREAMSPTY */ 617 return(-1); 618 } 619 #endif /* OPENPTY_PTY */ 620 #endif /* convex */ 621 622 #ifdef LINEMODE 623 /* 624 * tty_flowmode() Find out if flow control is enabled or disabled. 625 * tty_linemode() Find out if linemode (external processing) is enabled. 626 * tty_setlinemod(on) Turn on/off linemode. 627 * tty_isecho() Find out if echoing is turned on. 628 * tty_setecho(on) Enable/disable character echoing. 629 * tty_israw() Find out if terminal is in RAW mode. 630 * tty_binaryin(on) Turn on/off BINARY on input. 631 * tty_binaryout(on) Turn on/off BINARY on output. 632 * tty_isediting() Find out if line editing is enabled. 633 * tty_istrapsig() Find out if signal trapping is enabled. 634 * tty_setedit(on) Turn on/off line editing. 635 * tty_setsig(on) Turn on/off signal trapping. 636 * tty_issofttab() Find out if tab expansion is enabled. 637 * tty_setsofttab(on) Turn on/off soft tab expansion. 638 * tty_islitecho() Find out if typed control chars are echoed literally 639 * tty_setlitecho() Turn on/off literal echo of control chars 640 * tty_tspeed(val) Set transmit speed to val. 641 * tty_rspeed(val) Set receive speed to val. 642 */ 643 644 #ifdef convex 645 static int linestate; 646 #endif 647 648 int 649 tty_linemode() 650 { 651 #ifndef convex 652 #ifndef USE_TERMIO 653 return(termbuf.state & TS_EXTPROC); 654 #else 655 return(termbuf.c_lflag & EXTPROC); 656 #endif 657 #else 658 return(linestate); 659 #endif 660 } 661 662 void 663 tty_setlinemode(on) 664 int on; 665 { 666 #ifdef TIOCEXT 667 # ifndef convex 668 set_termbuf(); 669 # else 670 linestate = on; 671 # endif 672 (void) ioctl(pty, TIOCEXT, (char *)&on); 673 # ifndef convex 674 init_termbuf(); 675 # endif 676 #else /* !TIOCEXT */ 677 # ifdef EXTPROC 678 if (on) 679 termbuf.c_lflag |= EXTPROC; 680 else 681 termbuf.c_lflag &= ~EXTPROC; 682 # endif 683 #endif /* TIOCEXT */ 684 } 685 #endif /* LINEMODE */ 686 687 int 688 tty_isecho() 689 { 690 #ifndef USE_TERMIO 691 return (termbuf.sg.sg_flags & ECHO); 692 #else 693 return (termbuf.c_lflag & ECHO); 694 #endif 695 } 696 697 int 698 tty_flowmode() 699 { 700 #ifndef USE_TERMIO 701 return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 702 #else 703 return((termbuf.c_iflag & IXON) ? 1 : 0); 704 #endif 705 } 706 707 int 708 tty_restartany() 709 { 710 #ifndef USE_TERMIO 711 # ifdef DECCTQ 712 return((termbuf.lflags & DECCTQ) ? 0 : 1); 713 # else 714 return(-1); 715 # endif 716 #else 717 return((termbuf.c_iflag & IXANY) ? 1 : 0); 718 #endif 719 } 720 721 void 722 tty_setecho(on) 723 int on; 724 { 725 #ifndef USE_TERMIO 726 if (on) 727 termbuf.sg.sg_flags |= ECHO|CRMOD; 728 else 729 termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 730 #else 731 if (on) 732 termbuf.c_lflag |= ECHO; 733 else 734 termbuf.c_lflag &= ~ECHO; 735 #endif 736 } 737 738 int 739 tty_israw() 740 { 741 #ifndef USE_TERMIO 742 return(termbuf.sg.sg_flags & RAW); 743 #else 744 return(!(termbuf.c_lflag & ICANON)); 745 #endif 746 } 747 748 #if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 749 int 750 tty_setraw(on) 751 { 752 # ifndef USE_TERMIO 753 if (on) 754 termbuf.sg.sg_flags |= RAW; 755 else 756 termbuf.sg.sg_flags &= ~RAW; 757 # else 758 if (on) 759 termbuf.c_lflag &= ~ICANON; 760 else 761 termbuf.c_lflag |= ICANON; 762 # endif 763 } 764 #endif 765 766 void 767 tty_binaryin(on) 768 int on; 769 { 770 #ifndef USE_TERMIO 771 if (on) 772 termbuf.lflags |= LPASS8; 773 else 774 termbuf.lflags &= ~LPASS8; 775 #else 776 if (on) { 777 termbuf.c_iflag &= ~ISTRIP; 778 } else { 779 termbuf.c_iflag |= ISTRIP; 780 } 781 #endif 782 } 783 784 void 785 tty_binaryout(on) 786 int on; 787 { 788 #ifndef USE_TERMIO 789 if (on) 790 termbuf.lflags |= LLITOUT; 791 else 792 termbuf.lflags &= ~LLITOUT; 793 #else 794 if (on) { 795 termbuf.c_cflag &= ~(CSIZE|PARENB); 796 termbuf.c_cflag |= CS8; 797 termbuf.c_oflag &= ~OPOST; 798 } else { 799 termbuf.c_cflag &= ~CSIZE; 800 termbuf.c_cflag |= CS7|PARENB; 801 termbuf.c_oflag |= OPOST; 802 } 803 #endif 804 } 805 806 int 807 tty_isbinaryin() 808 { 809 #ifndef USE_TERMIO 810 return(termbuf.lflags & LPASS8); 811 #else 812 return(!(termbuf.c_iflag & ISTRIP)); 813 #endif 814 } 815 816 int 817 tty_isbinaryout() 818 { 819 #ifndef USE_TERMIO 820 return(termbuf.lflags & LLITOUT); 821 #else 822 return(!(termbuf.c_oflag&OPOST)); 823 #endif 824 } 825 826 #ifdef LINEMODE 827 int 828 tty_isediting() 829 { 830 #ifndef USE_TERMIO 831 return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 832 #else 833 return(termbuf.c_lflag & ICANON); 834 #endif 835 } 836 837 int 838 tty_istrapsig() 839 { 840 #ifndef USE_TERMIO 841 return(!(termbuf.sg.sg_flags&RAW)); 842 #else 843 return(termbuf.c_lflag & ISIG); 844 #endif 845 } 846 847 void 848 tty_setedit(on) 849 int on; 850 { 851 #ifndef USE_TERMIO 852 if (on) 853 termbuf.sg.sg_flags &= ~CBREAK; 854 else 855 termbuf.sg.sg_flags |= CBREAK; 856 #else 857 if (on) 858 termbuf.c_lflag |= ICANON; 859 else 860 termbuf.c_lflag &= ~ICANON; 861 #endif 862 } 863 864 void 865 tty_setsig(on) 866 int on; 867 { 868 #ifndef USE_TERMIO 869 if (on) 870 ; 871 #else 872 if (on) 873 termbuf.c_lflag |= ISIG; 874 else 875 termbuf.c_lflag &= ~ISIG; 876 #endif 877 } 878 #endif /* LINEMODE */ 879 880 int 881 tty_issofttab() 882 { 883 #ifndef USE_TERMIO 884 return (termbuf.sg.sg_flags & XTABS); 885 #else 886 # ifdef OXTABS 887 return (termbuf.c_oflag & OXTABS); 888 # endif 889 # ifdef TABDLY 890 return ((termbuf.c_oflag & TABDLY) == TAB3); 891 # endif 892 #endif 893 } 894 895 void 896 tty_setsofttab(on) 897 int on; 898 { 899 #ifndef USE_TERMIO 900 if (on) 901 termbuf.sg.sg_flags |= XTABS; 902 else 903 termbuf.sg.sg_flags &= ~XTABS; 904 #else 905 if (on) { 906 # ifdef OXTABS 907 termbuf.c_oflag |= OXTABS; 908 # endif 909 # ifdef TABDLY 910 termbuf.c_oflag &= ~TABDLY; 911 termbuf.c_oflag |= TAB3; 912 # endif 913 } else { 914 # ifdef OXTABS 915 termbuf.c_oflag &= ~OXTABS; 916 # endif 917 # ifdef TABDLY 918 termbuf.c_oflag &= ~TABDLY; 919 termbuf.c_oflag |= TAB0; 920 # endif 921 } 922 #endif 923 } 924 925 int 926 tty_islitecho() 927 { 928 #ifndef USE_TERMIO 929 return (!(termbuf.lflags & LCTLECH)); 930 #else 931 # ifdef ECHOCTL 932 return (!(termbuf.c_lflag & ECHOCTL)); 933 # endif 934 # ifdef TCTLECH 935 return (!(termbuf.c_lflag & TCTLECH)); 936 # endif 937 # if !defined(ECHOCTL) && !defined(TCTLECH) 938 return (0); /* assumes ctl chars are echoed '^x' */ 939 # endif 940 #endif 941 } 942 943 void 944 tty_setlitecho(on) 945 int on; 946 { 947 #ifndef USE_TERMIO 948 if (on) 949 termbuf.lflags &= ~LCTLECH; 950 else 951 termbuf.lflags |= LCTLECH; 952 #else 953 # ifdef ECHOCTL 954 if (on) 955 termbuf.c_lflag &= ~ECHOCTL; 956 else 957 termbuf.c_lflag |= ECHOCTL; 958 # endif 959 # ifdef TCTLECH 960 if (on) 961 termbuf.c_lflag &= ~TCTLECH; 962 else 963 termbuf.c_lflag |= TCTLECH; 964 # endif 965 #endif 966 } 967 968 int 969 tty_iscrnl() 970 { 971 #ifndef USE_TERMIO 972 return (termbuf.sg.sg_flags & CRMOD); 973 #else 974 return (termbuf.c_iflag & ICRNL); 975 #endif 976 } 977 978 /* 979 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 980 */ 981 #if B4800 != 4800 982 #define DECODE_BAUD 983 #endif 984 985 #ifdef DECODE_BAUD 986 987 /* 988 * A table of available terminal speeds 989 */ 990 struct termspeeds { 991 int speed; 992 int value; 993 } termspeeds[] = { 994 { 0, B0 }, { 50, B50 }, { 75, B75 }, 995 { 110, B110 }, { 134, B134 }, { 150, B150 }, 996 { 200, B200 }, { 300, B300 }, { 600, B600 }, 997 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 998 { 4800, B4800 }, 999 #ifdef B7200 1000 { 7200, B7200 }, 1001 #endif 1002 { 9600, B9600 }, 1003 #ifdef B14400 1004 { 14400, B14400 }, 1005 #endif 1006 #ifdef B19200 1007 { 19200, B19200 }, 1008 #endif 1009 #ifdef B28800 1010 { 28800, B28800 }, 1011 #endif 1012 #ifdef B38400 1013 { 38400, B38400 }, 1014 #endif 1015 #ifdef B57600 1016 { 57600, B57600 }, 1017 #endif 1018 #ifdef B115200 1019 { 115200, B115200 }, 1020 #endif 1021 #ifdef B230400 1022 { 230400, B230400 }, 1023 #endif 1024 { -1, 0 } 1025 }; 1026 #endif /* DECODE_BUAD */ 1027 1028 void 1029 tty_tspeed(val) 1030 int val; 1031 { 1032 #ifdef DECODE_BAUD 1033 register struct termspeeds *tp; 1034 1035 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 1036 ; 1037 if (tp->speed == -1) /* back up to last valid value */ 1038 --tp; 1039 cfsetospeed(&termbuf, tp->value); 1040 #else /* DECODE_BUAD */ 1041 cfsetospeed(&termbuf, val); 1042 #endif /* DECODE_BUAD */ 1043 } 1044 1045 void 1046 tty_rspeed(val) 1047 int val; 1048 { 1049 #ifdef DECODE_BAUD 1050 register struct termspeeds *tp; 1051 1052 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 1053 ; 1054 if (tp->speed == -1) /* back up to last valid value */ 1055 --tp; 1056 cfsetispeed(&termbuf, tp->value); 1057 #else /* DECODE_BAUD */ 1058 cfsetispeed(&termbuf, val); 1059 #endif /* DECODE_BAUD */ 1060 } 1061 1062 #if defined(CRAY2) && defined(UNICOS5) 1063 int 1064 tty_isnewmap() 1065 { 1066 return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 1067 !(termbuf.c_oflag & ONLRET)); 1068 } 1069 #endif 1070 1071 #ifdef PARENT_DOES_UTMP 1072 # ifndef NEWINIT 1073 extern struct utmp wtmp; 1074 extern char wtmpf[]; 1075 # else /* NEWINIT */ 1076 int gotalarm; 1077 1078 /* ARGSUSED */ 1079 void 1080 nologinproc(sig) 1081 int sig; 1082 { 1083 gotalarm++; 1084 } 1085 # endif /* NEWINIT */ 1086 #endif /* PARENT_DOES_UTMP */ 1087 1088 #ifndef NEWINIT 1089 # ifdef PARENT_DOES_UTMP 1090 extern void utmp_sig_init P((void)); 1091 extern void utmp_sig_reset P((void)); 1092 extern void utmp_sig_wait P((void)); 1093 extern void utmp_sig_notify P((int)); 1094 # endif /* PARENT_DOES_UTMP */ 1095 #endif 1096 1097 /* 1098 * getptyslave() 1099 * 1100 * Open the slave side of the pty, and do any initialization 1101 * that is necessary. The return value is a file descriptor 1102 * for the slave side. 1103 */ 1104 #if !defined(CRAY) || !defined(NEWINIT) 1105 extern int def_tspeed, def_rspeed; 1106 # ifdef TIOCGWINSZ 1107 extern int def_row, def_col; 1108 # endif 1109 #endif 1110 1111 void 1112 getptyslave() 1113 { 1114 register int t = -1; 1115 1116 #if !defined(CRAY) || !defined(NEWINIT) 1117 # ifdef LINEMODE 1118 int waslm; 1119 # endif 1120 # ifdef TIOCGWINSZ 1121 struct winsize ws; 1122 # endif 1123 /* 1124 * Opening the slave side may cause initilization of the 1125 * kernel tty structure. We need remember the state of 1126 * if linemode was turned on 1127 * terminal window size 1128 * terminal speed 1129 * so that we can re-set them if we need to. 1130 */ 1131 # ifdef LINEMODE 1132 waslm = tty_linemode(); 1133 # endif 1134 1135 1136 /* 1137 * Make sure that we don't have a controlling tty, and 1138 * that we are the session (process group) leader. 1139 */ 1140 # ifdef TIOCNOTTY 1141 t = open(_PATH_TTY, O_RDWR); 1142 if (t >= 0) { 1143 (void) ioctl(t, TIOCNOTTY, (char *)0); 1144 (void) close(t); 1145 } 1146 # endif 1147 1148 1149 # ifdef PARENT_DOES_UTMP 1150 /* 1151 * Wait for our parent to get the utmp stuff to get done. 1152 */ 1153 utmp_sig_wait(); 1154 # endif 1155 1156 t = cleanopen(line); 1157 if (t < 0) 1158 fatalperror(net, line); 1159 1160 #ifdef STREAMSPTY 1161 #ifdef USE_TERMIO 1162 ttyfd = t; 1163 #endif 1164 if (ioctl(t, I_PUSH, "ptem") < 0) 1165 fatal(net, "I_PUSH ptem"); 1166 if (ioctl(t, I_PUSH, "ldterm") < 0) 1167 fatal(net, "I_PUSH ldterm"); 1168 if (ioctl(t, I_PUSH, "ttcompat") < 0) 1169 fatal(net, "I_PUSH ttcompat"); 1170 if (ioctl(pty, I_PUSH, "pckt") < 0) 1171 fatal(net, "I_PUSH pckt"); 1172 #endif 1173 1174 /* 1175 * set up the tty modes as we like them to be. 1176 */ 1177 init_termbuf(); 1178 # ifdef TIOCGWINSZ 1179 if (def_row || def_col) { 1180 memset((char *)&ws, 0, sizeof(ws)); 1181 ws.ws_col = def_col; 1182 ws.ws_row = def_row; 1183 (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 1184 } 1185 # endif 1186 1187 /* 1188 * Settings for sgtty based systems 1189 */ 1190 # ifndef USE_TERMIO 1191 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 1192 # endif /* USE_TERMIO */ 1193 1194 /* 1195 * Settings for UNICOS (and HPUX) 1196 */ 1197 # if defined(CRAY) || defined(__hpux) 1198 termbuf.c_oflag = OPOST|ONLCR|TAB3; 1199 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 1200 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 1201 termbuf.c_cflag = EXTB|HUPCL|CS8; 1202 # endif 1203 1204 /* 1205 * Settings for all other termios/termio based 1206 * systems, other than 4.4BSD. In 4.4BSD the 1207 * kernel does the initial terminal setup. 1208 */ 1209 # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 1210 # ifndef OXTABS 1211 # define OXTABS 0 1212 # endif 1213 termbuf.c_lflag |= ECHO; 1214 termbuf.c_oflag |= ONLCR|OXTABS; 1215 termbuf.c_iflag |= ICRNL; 1216 termbuf.c_iflag &= ~IXOFF; 1217 # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 1218 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 1219 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 1220 # ifdef LINEMODE 1221 if (waslm) 1222 tty_setlinemode(1); 1223 # endif /* LINEMODE */ 1224 1225 /* 1226 * Set the tty modes, and make this our controlling tty. 1227 */ 1228 set_termbuf(); 1229 if (login_tty(t) == -1) 1230 fatalperror(net, "login_tty"); 1231 #endif /* !defined(CRAY) || !defined(NEWINIT) */ 1232 if (net > 2) 1233 (void) close(net); 1234 #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1235 /* 1236 * Leave the pty open so that we can write out the rlogin 1237 * protocol for /bin/login, if the authentication works. 1238 */ 1239 #else 1240 if (pty > 2) { 1241 (void) close(pty); 1242 pty = -1; 1243 } 1244 #endif 1245 } 1246 1247 #if !defined(CRAY) || !defined(NEWINIT) 1248 #ifndef O_NOCTTY 1249 #define O_NOCTTY 0 1250 #endif 1251 /* 1252 * Open the specified slave side of the pty, 1253 * making sure that we have a clean tty. 1254 */ 1255 int 1256 cleanopen(ttyline) 1257 char *ttyline; 1258 { 1259 #ifdef OPENPTY_PTY 1260 return ptyslavefd; 1261 #else /* ! OPENPTY_PTY */ 1262 register int t; 1263 #ifdef UNICOS7x 1264 struct secstat secbuf; 1265 #endif /* UNICOS7x */ 1266 1267 #ifndef STREAMSPTY 1268 /* 1269 * Make sure that other people can't open the 1270 * slave side of the connection. 1271 */ 1272 (void) chown(ttyline, 0, 0); 1273 (void) chmod(ttyline, 0600); 1274 #endif 1275 1276 # if !defined(CRAY) && (BSD > 43) 1277 (void) revoke(ttyline); 1278 # endif 1279 #ifdef UNICOS7x 1280 if (secflag) { 1281 if (secstat(ttyline, &secbuf) < 0) 1282 return(-1); 1283 if (setulvl(secbuf.st_slevel) < 0) 1284 return(-1); 1285 if (setucmp(secbuf.st_compart) < 0) 1286 return(-1); 1287 } 1288 #endif /* UNICOS7x */ 1289 1290 t = open(ttyline, O_RDWR|O_NOCTTY); 1291 1292 #ifdef UNICOS7x 1293 if (secflag) { 1294 if (setulvl(sysv.sy_minlvl) < 0) 1295 return(-1); 1296 if (setucmp(0) < 0) 1297 return(-1); 1298 } 1299 #endif /* UNICOS7x */ 1300 1301 if (t < 0) 1302 return(-1); 1303 1304 /* 1305 * Hangup anybody else using this ttyp, then reopen it for 1306 * ourselves. 1307 */ 1308 # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 1309 (void) signal(SIGHUP, SIG_IGN); 1310 vhangup(); 1311 (void) signal(SIGHUP, SIG_DFL); 1312 t = open(ttyline, O_RDWR|O_NOCTTY); 1313 if (t < 0) 1314 return(-1); 1315 # endif 1316 # if defined(CRAY) && defined(TCVHUP) 1317 { 1318 register int i; 1319 (void) signal(SIGHUP, SIG_IGN); 1320 (void) ioctl(t, TCVHUP, (char *)0); 1321 (void) signal(SIGHUP, SIG_DFL); 1322 1323 #ifdef UNICOS7x 1324 if (secflag) { 1325 if (secstat(ttyline, &secbuf) < 0) 1326 return(-1); 1327 if (setulvl(secbuf.st_slevel) < 0) 1328 return(-1); 1329 if (setucmp(secbuf.st_compart) < 0) 1330 return(-1); 1331 } 1332 #endif /* UNICOS7x */ 1333 1334 i = open(ttyline, O_RDWR); 1335 1336 #ifdef UNICOS7x 1337 if (secflag) { 1338 if (setulvl(sysv.sy_minlvl) < 0) 1339 return(-1); 1340 if (setucmp(0) < 0) 1341 return(-1); 1342 } 1343 #endif /* UNICOS7x */ 1344 1345 if (i < 0) 1346 return(-1); 1347 (void) close(t); 1348 t = i; 1349 } 1350 # endif /* defined(CRAY) && defined(TCVHUP) */ 1351 return(t); 1352 #endif /* OPENPTY_PTY */ 1353 } 1354 #endif /* !defined(CRAY) || !defined(NEWINIT) */ 1355 1356 #if BSD <= 43 1357 1358 int 1359 login_tty(t) 1360 int t; 1361 { 1362 if (setsid() < 0) { 1363 #ifdef ultrix 1364 /* 1365 * The setsid() may have failed because we 1366 * already have a pgrp == pid. Zero out 1367 * our pgrp and try again... 1368 */ 1369 if ((setpgrp(0, 0) < 0) || (setsid() < 0)) 1370 #endif 1371 fatalperror(net, "setsid()"); 1372 } 1373 # ifdef TIOCSCTTY 1374 if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 1375 fatalperror(net, "ioctl(sctty)"); 1376 # if defined(CRAY) 1377 /* 1378 * Close the hard fd to /dev/ttypXXX, and re-open through 1379 * the indirect /dev/tty interface. 1380 */ 1381 close(t); 1382 if ((t = open("/dev/tty", O_RDWR)) < 0) 1383 fatalperror(net, "open(/dev/tty)"); 1384 # endif 1385 # else 1386 /* 1387 * We get our controlling tty assigned as a side-effect 1388 * of opening up a tty device. But on BSD based systems, 1389 * this only happens if our process group is zero. The 1390 * setsid() call above may have set our pgrp, so clear 1391 * it out before opening the tty... 1392 */ 1393 # ifndef SOLARIS 1394 (void) setpgrp(0, 0); 1395 # else 1396 (void) setpgrp(); 1397 # endif 1398 close(open(ttyline, O_RDWR)); 1399 # endif 1400 if (t != 0) 1401 (void) dup2(t, 0); 1402 if (t != 1) 1403 (void) dup2(t, 1); 1404 if (t != 2) 1405 (void) dup2(t, 2); 1406 if (t > 2) 1407 close(t); 1408 return(0); 1409 } 1410 #endif /* BSD <= 43 */ 1411 1412 #ifdef NEWINIT 1413 char *gen_id = "fe"; 1414 #endif 1415 1416 /* 1417 * startslave(host) 1418 * 1419 * Given a hostname, do whatever 1420 * is necessary to startup the login process on the slave side of the pty. 1421 */ 1422 1423 /* ARGSUSED */ 1424 void 1425 startslave(host, autologin, autoname) 1426 char *host; 1427 int autologin; 1428 char *autoname; 1429 { 1430 register int i; 1431 #ifdef NEWINIT 1432 extern char *ptyip; 1433 struct init_request request; 1434 void nologinproc(); 1435 register int n; 1436 #endif /* NEWINIT */ 1437 1438 #if defined(AUTHENTICATION) 1439 if (!autoname || !autoname[0]) 1440 autologin = 0; 1441 1442 if (autologin < auth_level) { 1443 fatal(net, "Authorization failed"); 1444 exit(1); 1445 } 1446 #endif 1447 1448 #ifndef NEWINIT 1449 # ifdef PARENT_DOES_UTMP 1450 utmp_sig_init(); 1451 # endif /* PARENT_DOES_UTMP */ 1452 1453 if ((i = fork()) < 0) 1454 fatalperror(net, "fork"); 1455 if (i) { 1456 # ifdef PARENT_DOES_UTMP 1457 /* 1458 * Cray parent will create utmp entry for child and send 1459 * signal to child to tell when done. Child waits for signal 1460 * before doing anything important. 1461 */ 1462 register int pid = i; 1463 void sigjob P((int)); 1464 1465 setpgrp(); 1466 utmp_sig_reset(); /* reset handler to default */ 1467 /* 1468 * Create utmp entry for child 1469 */ 1470 (void) time(&wtmp.ut_time); 1471 wtmp.ut_type = LOGIN_PROCESS; 1472 wtmp.ut_pid = pid; 1473 SCPYN(wtmp.ut_user, "LOGIN"); 1474 SCPYN(wtmp.ut_host, host); 1475 SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 1476 #ifndef __hpux 1477 SCPYN(wtmp.ut_id, wtmp.ut_line+3); 1478 #else 1479 SCPYN(wtmp.ut_id, wtmp.ut_line+7); 1480 #endif 1481 pututline(&wtmp); 1482 endutent(); 1483 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 1484 (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 1485 (void) close(i); 1486 } 1487 #ifdef CRAY 1488 (void) signal(WJSIGNAL, sigjob); 1489 #endif 1490 utmp_sig_notify(pid); 1491 # endif /* PARENT_DOES_UTMP */ 1492 } else { 1493 getptyslave(); 1494 start_login(host, autologin, autoname); 1495 /*NOTREACHED*/ 1496 } 1497 #else /* NEWINIT */ 1498 1499 /* 1500 * Init will start up login process if we ask nicely. We only wait 1501 * for it to start up and begin normal telnet operation. 1502 */ 1503 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 1504 char tbuf[128]; 1505 1506 (void)snprintf(tbuf, sizeof tbuf, "Can't open %s\n", INIT_FIFO); 1507 fatalperror(net, tbuf); 1508 } 1509 memset((char *)&request, 0, sizeof(request)); 1510 request.magic = INIT_MAGIC; 1511 SCPYN(request.gen_id, gen_id); 1512 SCPYN(request.tty_id, &line[8]); 1513 SCPYN(request.host, host); 1514 SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 1515 #if !defined(UNICOS5) 1516 request.signal = SIGCLD; 1517 request.pid = getpid(); 1518 #endif 1519 #ifdef BFTPDAEMON 1520 /* 1521 * Are we working as the bftp daemon? 1522 */ 1523 if (bftpd) { 1524 SCPYN(request.exec_name, BFTPPATH); 1525 } 1526 #endif /* BFTPDAEMON */ 1527 if (write(i, (char *)&request, sizeof(request)) < 0) { 1528 char tbuf[128]; 1529 1530 (void)snprintf(tbuf, sizeof tbuf, "Can't write to %s\n", INIT_FIFO); 1531 fatalperror(net, tbuf); 1532 } 1533 (void) close(i); 1534 (void) signal(SIGALRM, nologinproc); 1535 for (i = 0; ; i++) { 1536 char tbuf[128]; 1537 1538 alarm(15); 1539 n = read(pty, ptyip, BUFSIZ); 1540 if (i == 3 || n >= 0 || !gotalarm) 1541 break; 1542 gotalarm = 0; 1543 (void)snprintf(tbuf, sizeof tbuf, 1544 "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 1545 (void)write(net, tbuf, strlen(tbuf)); 1546 } 1547 if (n < 0 && gotalarm) 1548 fatal(net, "/etc/init didn't start login process"); 1549 pcc += n; 1550 alarm(0); 1551 (void) signal(SIGALRM, SIG_DFL); 1552 1553 return; 1554 #endif /* NEWINIT */ 1555 } 1556 1557 char *envinit[3]; 1558 1559 void 1560 init_env() 1561 { 1562 char **envp; 1563 1564 envp = envinit; 1565 if ((*envp = getenv("TZ"))) 1566 *envp++ -= 3; 1567 #if defined(CRAY) || defined(__hpux) 1568 else 1569 *envp++ = "TZ=GMT0"; 1570 #endif 1571 *envp = 0; 1572 environ = envinit; 1573 } 1574 1575 #ifndef NEWINIT 1576 1577 /* 1578 * start_login(host) 1579 * 1580 * Assuming that we are now running as a child processes, this 1581 * function will turn us into the login process. 1582 */ 1583 extern char *gettyname; 1584 1585 void 1586 start_login(host, autologin, name) 1587 char *host; 1588 int autologin; 1589 char *name; 1590 { 1591 register char **argv; 1592 #define TABBUFSIZ 512 1593 char defent[TABBUFSIZ]; 1594 char defstrs[TABBUFSIZ]; 1595 #undef TABBUFSIZ 1596 const char *loginprog = NULL; 1597 #ifdef UTMPX 1598 register int pid = getpid(); 1599 struct utmpx utmpx; 1600 #endif 1601 #ifdef SOLARIS 1602 char *term; 1603 char termnamebuf[64]; 1604 #endif 1605 1606 #ifdef UTMPX 1607 /* 1608 * Create utmp entry for child 1609 */ 1610 1611 memset(&utmpx, 0, sizeof(utmpx)); 1612 SCPYN(utmpx.ut_user, ".telnet"); 1613 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 1614 utmpx.ut_pid = pid; 1615 utmpx.ut_id[0] = 't'; 1616 utmpx.ut_id[1] = 'n'; 1617 utmpx.ut_id[2] = SC_WILDC; 1618 utmpx.ut_id[3] = SC_WILDC; 1619 utmpx.ut_type = LOGIN_PROCESS; 1620 (void) time(&utmpx.ut_tv.tv_sec); 1621 if (makeutx(&utmpx) == NULL) 1622 fatal(net, "makeutx failed"); 1623 #endif 1624 1625 scrub_env(); 1626 1627 /* 1628 * -h : pass on name of host. 1629 * WARNING: -h is accepted by login if and only if 1630 * getuid() == 0. 1631 * -p : don't clobber the environment (so terminal type stays set). 1632 * 1633 * -f : force this login, he has already been authenticated 1634 */ 1635 argv = addarg(0, "login"); 1636 1637 #if !defined(NO_LOGIN_H) 1638 1639 # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1640 /* 1641 * Don't add the "-h host" option if we are going 1642 * to be adding the "-r host" option down below... 1643 */ 1644 if ((auth_level < 0) || (autologin != AUTH_VALID)) 1645 # endif 1646 { 1647 argv = addarg(argv, "-h"); 1648 argv = addarg(argv, host); 1649 #ifdef SOLARIS 1650 /* 1651 * SVR4 version of -h takes TERM= as second arg, or - 1652 */ 1653 term = getenv("TERM"); 1654 if (term == NULL || term[0] == 0) { 1655 term = "-"; 1656 } else { 1657 (void)strlcpy(termnamebuf, "TERM=", 1658 sizeof(termnamebuf)); 1659 (void)strlcat(termnamebuf, term, sizeof(termnamebuf)); 1660 term = termnamebuf; 1661 } 1662 argv = addarg(argv, term); 1663 #endif 1664 } 1665 #endif 1666 #if !defined(NO_LOGIN_P) 1667 argv = addarg(argv, "-p"); 1668 #endif 1669 #ifdef LINEMODE 1670 /* 1671 * Set the environment variable "LINEMODE" to either 1672 * "real" or "kludge" if we are operating in either 1673 * real or kludge linemode. 1674 */ 1675 if (lmodetype == REAL_LINEMODE) 1676 setenv("LINEMODE", "real", 1); 1677 # ifdef KLUDGELINEMODE 1678 else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) 1679 setenv("LINEMODE", "kludge", 1); 1680 # endif 1681 #endif 1682 #ifdef BFTPDAEMON 1683 /* 1684 * Are we working as the bftp daemon? If so, then ask login 1685 * to start bftp instead of shell. 1686 */ 1687 if (bftpd) { 1688 argv = addarg(argv, "-e"); 1689 argv = addarg(argv, BFTPPATH); 1690 } else 1691 #endif 1692 #if defined (SECURELOGIN) 1693 /* 1694 * don't worry about the -f that might get sent. 1695 * A -s is supposed to override it anyhow. 1696 */ 1697 if (require_secure_login) 1698 argv = addarg(argv, "-s"); 1699 #endif 1700 #if defined (AUTHENTICATION) 1701 if (auth_level >= 0 && autologin == AUTH_VALID) { 1702 # if !defined(NO_LOGIN_F) 1703 # if defined(FORWARD) 1704 if (got_forwarded_creds) 1705 argv = addarg(argv, "-F"); 1706 else 1707 # endif /* FORWARD */ 1708 argv = addarg(argv, "-f"); 1709 argv = addarg(argv, "--"); 1710 argv = addarg(argv, name); 1711 # else 1712 # if defined(LOGIN_R) 1713 /* 1714 * We don't have support for "login -f", but we 1715 * can fool /bin/login into thinking that we are 1716 * rlogind, and allow us to log in without a 1717 * password. The rlogin protocol expects 1718 * local-user\0remote-user\0term/speed\0 1719 */ 1720 1721 if (pty > 2) { 1722 register char *cp; 1723 char speed[128]; 1724 int isecho, israw, xpty, len; 1725 extern int def_rspeed; 1726 # ifndef LOGIN_HOST 1727 /* 1728 * Tell login that we are coming from "localhost". 1729 * If we passed in the real host name, then the 1730 * user would have to allow .rhost access from 1731 * every machine that they want authenticated 1732 * access to work from, which sort of defeats 1733 * the purpose of an authenticated login... 1734 * So, we tell login that the session is coming 1735 * from "localhost", and the user will only have 1736 * to have "localhost" in their .rhost file. 1737 */ 1738 # define LOGIN_HOST "localhost" 1739 # endif 1740 argv = addarg(argv, "-r"); 1741 argv = addarg(argv, LOGIN_HOST); 1742 1743 xpty = pty; 1744 # ifndef STREAMSPTY 1745 pty = 0; 1746 # else 1747 ttyfd = 0; 1748 # endif 1749 init_termbuf(); 1750 isecho = tty_isecho(); 1751 israw = tty_israw(); 1752 if (isecho || !israw) { 1753 tty_setecho(0); /* Turn off echo */ 1754 tty_setraw(1); /* Turn on raw */ 1755 set_termbuf(); 1756 } 1757 len = strlen(name)+1; 1758 write(xpty, name, len); 1759 write(xpty, name, len); 1760 sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", 1761 (def_rspeed > 0) ? def_rspeed : 9600); 1762 len = strlen(speed)+1; 1763 write(xpty, speed, len); 1764 1765 if (isecho || !israw) { 1766 init_termbuf(); 1767 tty_setecho(isecho); 1768 tty_setraw(israw); 1769 set_termbuf(); 1770 if (!israw) { 1771 /* 1772 * Write a newline to ensure 1773 * that login will be able to 1774 * read the line... 1775 */ 1776 write(xpty, "\n", 1); 1777 } 1778 } 1779 pty = xpty; 1780 } 1781 # else 1782 argv = addarg(argv, "--"); 1783 argv = addarg(argv, name); 1784 # endif 1785 # endif 1786 } else 1787 #endif 1788 if (getenv("USER")) { 1789 argv = addarg(argv, "--"); 1790 argv = addarg(argv, getenv("USER")); 1791 #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 1792 { 1793 register char **cpp; 1794 for (cpp = environ; *cpp; cpp++) 1795 argv = addarg(argv, *cpp); 1796 } 1797 #endif 1798 /* 1799 * Assume that login will set the USER variable 1800 * correctly. For SysV systems, this means that 1801 * USER will no longer be set, just LOGNAME by 1802 * login. (The problem is that if the auto-login 1803 * fails, and the user then specifies a different 1804 * account name, he can get logged in with both 1805 * LOGNAME and USER in his environment, but the 1806 * USER value will be wrong. 1807 */ 1808 unsetenv("USER"); 1809 } 1810 #ifdef SOLARIS 1811 else { 1812 char **p; 1813 1814 argv = addarg(argv, ""); /* no login name */ 1815 for (p = environ; *p; p++) { 1816 argv = addarg(argv, *p); 1817 } 1818 } 1819 #endif /* SOLARIS */ 1820 #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1821 if (pty > 2) 1822 close(pty); 1823 #endif 1824 if (getent(defent, gettyname) == 1) { 1825 char *cp = defstrs; 1826 1827 loginprog = getstr("lo", &cp); 1828 } 1829 if (loginprog == NULL) 1830 loginprog = _PATH_LOGIN; 1831 closelog(); 1832 /* 1833 * This sleep(1) is in here so that telnetd can 1834 * finish up with the tty. There's a race condition 1835 * the login banner message gets lost... 1836 */ 1837 sleep(1); 1838 execv(loginprog, argv); 1839 1840 syslog(LOG_ERR, "%s: %m\n", loginprog); 1841 fatalperror(net, loginprog); 1842 /*NOTREACHED*/ 1843 } 1844 1845 char ** 1846 addarg(argv, val) 1847 register char **argv; 1848 register char *val; 1849 { 1850 register char **cpp; 1851 1852 if (argv == NULL) { 1853 /* 1854 * 10 entries, a leading length, and a null 1855 */ 1856 argv = (char **)malloc(sizeof(*argv) * 12); 1857 if (argv == NULL) 1858 return(NULL); 1859 *argv++ = (char *)10; 1860 *argv = (char *)0; 1861 } 1862 for (cpp = argv; *cpp; cpp++) 1863 ; 1864 if (cpp == &argv[(long)argv[-1]]) { 1865 --argv; 1866 *argv = (char *)((long)(*argv) + 10); 1867 argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2)); 1868 if (argv == NULL) { 1869 fatal(net, "not enough memory"); 1870 /*NOTREACHED*/ 1871 } 1872 argv++; 1873 cpp = &argv[(long)argv[-1] - 10]; 1874 } 1875 *cpp++ = val; 1876 *cpp = 0; 1877 return(argv); 1878 } 1879 #endif /* NEWINIT */ 1880 1881 /* 1882 * scrub_env() 1883 * 1884 * We only accept the environment variables listed below. 1885 */ 1886 1887 void 1888 scrub_env() 1889 { 1890 static const char *reject[] = { 1891 "TERMCAP=/", 1892 NULL 1893 }; 1894 1895 static const char *accept[] = { 1896 "XAUTH=", "XAUTHORITY=", "DISPLAY=", 1897 "TERM=", 1898 "EDITOR=", 1899 "PAGER=", 1900 "LOGNAME=", 1901 "POSIXLY_CORRECT=", 1902 "TERMCAP=", 1903 "PRINTER=", 1904 NULL 1905 }; 1906 1907 char **cpp, **cpp2; 1908 const char **p; 1909 1910 for (cpp2 = cpp = environ; *cpp; cpp++) { 1911 int reject_it = 0; 1912 1913 for(p = reject; *p; p++) 1914 if(strncmp(*cpp, *p, strlen(*p)) == 0) { 1915 reject_it = 1; 1916 break; 1917 } 1918 if (reject_it) 1919 continue; 1920 1921 for(p = accept; *p; p++) 1922 if(strncmp(*cpp, *p, strlen(*p)) == 0) 1923 break; 1924 if(*p != NULL) 1925 *cpp2++ = *cpp; 1926 } 1927 *cpp2 = NULL; 1928 } 1929 1930 /* 1931 * cleanup() 1932 * 1933 * This is the routine to call when we are all through, to 1934 * clean up anything that needs to be cleaned up. 1935 */ 1936 /* ARGSUSED */ 1937 void 1938 cleanup(sig) 1939 int sig; 1940 { 1941 #ifndef PARENT_DOES_UTMP 1942 # if (BSD > 43) || defined(convex) 1943 char *p, c; 1944 1945 p = line + sizeof("/dev/") - 1; 1946 if (logout(p)) 1947 logwtmp(p, "", ""); 1948 (void)chmod(line, 0666); 1949 (void)chown(line, 0, 0); 1950 c = *p; *p = 'p'; 1951 (void)chmod(line, 0666); 1952 (void)chown(line, 0, 0); 1953 *p = c; 1954 if (ttyaction(line, "telnetd", "root")) 1955 syslog(LOG_ERR, "%s: ttyaction failed", line); 1956 (void) shutdown(net, 2); 1957 exit(1); 1958 # else 1959 void rmut(); 1960 1961 rmut(); 1962 vhangup(); /* XXX */ 1963 (void) shutdown(net, 2); 1964 exit(1); 1965 # endif 1966 #else /* PARENT_DOES_UTMP */ 1967 # ifdef NEWINIT 1968 (void) shutdown(net, 2); 1969 exit(1); 1970 # else /* NEWINIT */ 1971 # ifdef CRAY 1972 static int incleanup = 0; 1973 register int t; 1974 int child_status; /* status of child process as returned by waitpid */ 1975 int flags = WNOHANG|WUNTRACED; 1976 1977 /* 1978 * 1: Pick up the zombie, if we are being called 1979 * as the signal handler. 1980 * 2: If we are a nested cleanup(), return. 1981 * 3: Try to clean up TMPDIR. 1982 * 4: Fill in utmp with shutdown of process. 1983 * 5: Close down the network and pty connections. 1984 * 6: Finish up the TMPDIR cleanup, if needed. 1985 */ 1986 if (sig == SIGCHLD) { 1987 while (waitpid(-1, &child_status, flags) > 0) 1988 ; /* VOID */ 1989 /* Check if the child process was stopped 1990 * rather than exited. We want cleanup only if 1991 * the child has died. 1992 */ 1993 if (WIFSTOPPED(child_status)) { 1994 return; 1995 } 1996 } 1997 t = sigblock(sigmask(SIGCHLD)); 1998 if (incleanup) { 1999 sigsetmask(t); 2000 return; 2001 } 2002 incleanup = 1; 2003 sigsetmask(t); 2004 #ifdef UNICOS7x 2005 if (secflag) { 2006 /* 2007 * We need to set ourselves back to a null 2008 * label to clean up. 2009 */ 2010 2011 setulvl(sysv.sy_minlvl); 2012 setucmp((long)0); 2013 } 2014 #endif /* UNICOS7x */ 2015 2016 t = cleantmp(&wtmp); 2017 setutent(); /* just to make sure */ 2018 # endif /* CRAY */ 2019 rmut(line); 2020 close(pty); 2021 #ifdef KRB5 2022 kerberos5_cleanup(); 2023 #endif 2024 (void) shutdown(net, 2); 2025 # ifdef CRAY 2026 if (t == 0) 2027 cleantmp(&wtmp); 2028 # endif /* CRAY */ 2029 exit(1); 2030 # endif /* NEWINT */ 2031 #endif /* PARENT_DOES_UTMP */ 2032 } 2033 2034 #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 2035 /* 2036 * _utmp_sig_rcv 2037 * utmp_sig_init 2038 * utmp_sig_wait 2039 * These three functions are used to coordinate the handling of 2040 * the utmp file between the server and the soon-to-be-login shell. 2041 * The server actually creates the utmp structure, the child calls 2042 * utmp_sig_wait(), until the server calls utmp_sig_notify() and 2043 * signals the future-login shell to proceed. 2044 */ 2045 static int caught=0; /* NZ when signal intercepted */ 2046 static void (*func)(); /* address of previous handler */ 2047 2048 void 2049 _utmp_sig_rcv(sig) 2050 int sig; 2051 { 2052 caught = 1; 2053 (void) signal(SIGUSR1, func); 2054 } 2055 2056 void 2057 utmp_sig_init() 2058 { 2059 /* 2060 * register signal handler for UTMP creation 2061 */ 2062 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 2063 fatalperror(net, "telnetd/signal"); 2064 } 2065 2066 void 2067 utmp_sig_reset() 2068 { 2069 (void) signal(SIGUSR1, func); /* reset handler to default */ 2070 } 2071 2072 # ifdef __hpux 2073 # define sigoff() /* do nothing */ 2074 # define sigon() /* do nothing */ 2075 # endif 2076 2077 void 2078 utmp_sig_wait() 2079 { 2080 /* 2081 * Wait for parent to write our utmp entry. 2082 */ 2083 sigoff(); 2084 while (caught == 0) { 2085 pause(); /* wait until we get a signal (sigon) */ 2086 sigoff(); /* turn off signals while we check caught */ 2087 } 2088 sigon(); /* turn on signals again */ 2089 } 2090 2091 void 2092 utmp_sig_notify(pid) 2093 { 2094 kill(pid, SIGUSR1); 2095 } 2096 2097 # ifdef CRAY 2098 static int gotsigjob = 0; 2099 2100 /*ARGSUSED*/ 2101 void 2102 sigjob(sig) 2103 int sig; 2104 { 2105 register int jid; 2106 register struct jobtemp *jp; 2107 2108 while ((jid = waitjob(NULL)) != -1) { 2109 if (jid == 0) { 2110 return; 2111 } 2112 gotsigjob++; 2113 jobend(jid, NULL, NULL); 2114 } 2115 } 2116 2117 /* 2118 * jid_getutid: 2119 * called by jobend() before calling cleantmp() 2120 * to find the correct $TMPDIR to cleanup. 2121 */ 2122 2123 struct utmp * 2124 jid_getutid(jid) 2125 int jid; 2126 { 2127 struct utmp *cur = NULL; 2128 2129 setutent(); /* just to make sure */ 2130 while (cur = getutent()) { 2131 if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { 2132 return(cur); 2133 } 2134 } 2135 2136 return(0); 2137 } 2138 2139 /* 2140 * Clean up the TMPDIR that login created. 2141 * The first time this is called we pick up the info 2142 * from the utmp. If the job has already gone away, 2143 * then we'll clean up and be done. If not, then 2144 * when this is called the second time it will wait 2145 * for the signal that the job is done. 2146 */ 2147 int 2148 cleantmp(wtp) 2149 register struct utmp *wtp; 2150 { 2151 struct utmp *utp; 2152 static int first = 1; 2153 register int mask, omask, ret; 2154 extern struct utmp *getutid P((const struct utmp *_Id)); 2155 2156 2157 mask = sigmask(WJSIGNAL); 2158 2159 if (first == 0) { 2160 omask = sigblock(mask); 2161 while (gotsigjob == 0) 2162 sigpause(omask); 2163 return(1); 2164 } 2165 first = 0; 2166 setutent(); /* just to make sure */ 2167 2168 utp = getutid(wtp); 2169 if (utp == 0) { 2170 syslog(LOG_WARNING, 2171 "Can't get /etc/utmp entry to clean TMPDIR"); 2172 return(-1); 2173 } 2174 /* 2175 * Nothing to clean up if the user shell was never started. 2176 */ 2177 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 2178 return(1); 2179 2180 /* 2181 * Block the WJSIGNAL while we are in jobend(). 2182 */ 2183 omask = sigblock(mask); 2184 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 2185 sigsetmask(omask); 2186 return(ret); 2187 } 2188 2189 int 2190 jobend(jid, path, user) 2191 register int jid; 2192 register char *path; 2193 register char *user; 2194 { 2195 static int saved_jid = 0; 2196 static int pty_saved_jid = 0; 2197 static char saved_path[sizeof(wtmp.ut_tpath)+1]; 2198 static char saved_user[sizeof(wtmp.ut_user)+1]; 2199 2200 /* 2201 * this little piece of code comes into play 2202 * only when ptyreconnect is used to reconnect 2203 * to an previous session. 2204 * 2205 * this is the only time when the 2206 * "saved_jid != jid" code is executed. 2207 */ 2208 2209 if ( saved_jid && saved_jid != jid ) { 2210 if (!path) { /* called from signal handler */ 2211 pty_saved_jid = jid; 2212 } else { 2213 pty_saved_jid = saved_jid; 2214 } 2215 } 2216 2217 if (path) { 2218 strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 2219 strncpy(saved_user, user, sizeof(wtmp.ut_user)); 2220 saved_path[sizeof(saved_path)] = '\0'; 2221 saved_user[sizeof(saved_user)] = '\0'; 2222 } 2223 if (saved_jid == 0) { 2224 saved_jid = jid; 2225 return(0); 2226 } 2227 2228 /* if the jid has changed, get the correct entry from the utmp file */ 2229 2230 if ( saved_jid != jid ) { 2231 struct utmp *utp = NULL; 2232 struct utmp *jid_getutid(); 2233 2234 utp = jid_getutid(pty_saved_jid); 2235 2236 if (utp == 0) { 2237 syslog(LOG_WARNING, 2238 "Can't get /etc/utmp entry to clean TMPDIR"); 2239 return(-1); 2240 } 2241 2242 cleantmpdir(jid, utp->ut_tpath, utp->ut_user); 2243 return(1); 2244 } 2245 2246 cleantmpdir(jid, saved_path, saved_user); 2247 return(1); 2248 } 2249 2250 /* 2251 * Fork a child process to clean up the TMPDIR 2252 */ 2253 cleantmpdir(jid, tpath, user) 2254 register int jid; 2255 register char *tpath; 2256 register char *user; 2257 { 2258 switch(fork()) { 2259 case -1: 2260 syslog(LOG_WARNING, "TMPDIR cleanup(%s): fork() failed: %m\n", 2261 tpath); 2262 break; 2263 case 0: 2264 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 2265 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 2266 tpath, CLEANTMPCMD); 2267 exit(1); 2268 default: 2269 /* 2270 * Forget about child. We will exit, and 2271 * /etc/init will pick it up. 2272 */ 2273 break; 2274 } 2275 } 2276 # endif /* CRAY */ 2277 #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 2278 2279 /* 2280 * rmut() 2281 * 2282 * This is the function called by cleanup() to 2283 * remove the utmp entry for this person. 2284 */ 2285 2286 #ifdef UTMPX 2287 void 2288 rmut() 2289 { 2290 register f; 2291 int found = 0; 2292 struct utmp *u, *utmp; 2293 int nutmp; 2294 struct stat statbf; 2295 2296 struct utmpx *utxp, utmpx; 2297 2298 /* 2299 * This updates the utmpx and utmp entries and make a wtmp/x entry 2300 */ 2301 2302 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 2303 utxp = getutxline(&utmpx); 2304 if (utxp) { 2305 utxp->ut_type = DEAD_PROCESS; 2306 utxp->ut_exit.e_termination = 0; 2307 utxp->ut_exit.e_exit = 0; 2308 (void) time(&utmpx.ut_tv.tv_sec); 2309 utmpx.ut_tv.tv_usec = 0; 2310 modutx(utxp); 2311 } 2312 endutxent(); 2313 } /* end of rmut */ 2314 #endif 2315 2316 #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 2317 void 2318 rmut() 2319 { 2320 register f; 2321 int found = 0; 2322 struct utmp *u, *utmp; 2323 int nutmp; 2324 struct stat statbf; 2325 2326 f = open(utmpf, O_RDWR); 2327 if (f >= 0) { 2328 (void) fstat(f, &statbf); 2329 utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 2330 if (!utmp) 2331 syslog(LOG_WARNING, "utmp malloc failed"); 2332 if (statbf.st_size && utmp) { 2333 nutmp = read(f, (char *)utmp, (int)statbf.st_size); 2334 nutmp /= sizeof(struct utmp); 2335 2336 for (u = utmp ; u < &utmp[nutmp] ; u++) { 2337 if (SCMPN(u->ut_line, line+5) || 2338 u->ut_name[0]==0) 2339 continue; 2340 (void)lseek(f, (off_t)((long)u)-((long)utmp), 2341 SEEK_SET); 2342 SCPYN(u->ut_name, ""); 2343 SCPYN(u->ut_host, ""); 2344 (void) time(&u->ut_time); 2345 (void) write(f, (char *)u, sizeof(wtmp)); 2346 found++; 2347 } 2348 } 2349 (void) close(f); 2350 } 2351 if (found) { 2352 f = open(wtmpf, O_WRONLY|O_APPEND); 2353 if (f >= 0) { 2354 SCPYN(wtmp.ut_line, line+5); 2355 SCPYN(wtmp.ut_name, ""); 2356 SCPYN(wtmp.ut_host, ""); 2357 (void) time(&wtmp.ut_time); 2358 (void) write(f, (char *)&wtmp, sizeof(wtmp)); 2359 (void) close(f); 2360 } 2361 } 2362 (void) chmod(line, 0666); 2363 (void) chown(line, 0, 0); 2364 line[strlen("/dev/")] = 'p'; 2365 (void) chmod(line, 0666); 2366 (void) chown(line, 0, 0); 2367 } /* end of rmut */ 2368 #endif /* CRAY */ 2369 2370 #ifdef __hpux 2371 rmut (line) 2372 char *line; 2373 { 2374 struct utmp utmp; 2375 struct utmp *utptr; 2376 int fd; /* for /etc/wtmp */ 2377 2378 utmp.ut_type = USER_PROCESS; 2379 (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 2380 (void) setutent(); 2381 utptr = getutid(&utmp); 2382 /* write it out only if it exists */ 2383 if (utptr) { 2384 utptr->ut_type = DEAD_PROCESS; 2385 utptr->ut_time = time((long *) 0); 2386 (void) pututline(utptr); 2387 /* set wtmp entry if wtmp file exists */ 2388 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 2389 (void) write(fd, utptr, sizeof(utmp)); 2390 (void) close(fd); 2391 } 2392 } 2393 (void) endutent(); 2394 2395 (void) chmod(line, 0666); 2396 (void) chown(line, 0, 0); 2397 line[14] = line[13]; 2398 line[13] = line[12]; 2399 line[8] = 'm'; 2400 line[9] = '/'; 2401 line[10] = 'p'; 2402 line[11] = 't'; 2403 line[12] = 'y'; 2404 (void) chmod(line, 0666); 2405 (void) chown(line, 0, 0); 2406 } 2407 #endif 2408