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