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