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