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