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