Home | History | Annotate | Line # | Download | only in telnetd
sys_term.c revision 1.40
      1 /*	$NetBSD: sys_term.c,v 1.40 2003/09/19 05:54:46 itojun Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1989, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 #if 0
     35 static char sccsid[] = "@(#)sys_term.c	8.4+1 (Berkeley) 5/30/95";
     36 #else
     37 __RCSID("$NetBSD: sys_term.c,v 1.40 2003/09/19 05:54:46 itojun Exp $");
     38 #endif
     39 #endif /* not lint */
     40 
     41 #include "telnetd.h"
     42 #include "pathnames.h"
     43 
     44 #include <util.h>
     45 
     46 #include <sys/cdefs.h>
     47 
     48 #include <utmp.h>
     49 struct	utmp wtmp;
     50 
     51 #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
     52 #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
     53 
     54 struct termios termbuf, termbuf2;	/* pty control structure */
     55 
     56 void getptyslave __P((void));
     57 int cleanopen __P((char *));
     58 char **addarg __P((char **, char *));
     59 void scrub_env __P((void));
     60 int getent __P((char *, char *));
     61 char *getstr __P((const char *, char **));
     62 #ifdef KRB5
     63 extern void kerberos5_cleanup __P((void));
     64 #endif
     65 
     66 /*
     67  * init_termbuf()
     68  * copy_termbuf(cp)
     69  * set_termbuf()
     70  *
     71  * These three routines are used to get and set the "termbuf" structure
     72  * to and from the kernel.  init_termbuf() gets the current settings.
     73  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
     74  * set_termbuf() writes the structure into the kernel.
     75  */
     76 
     77 void
     78 init_termbuf()
     79 {
     80 	(void) tcgetattr(pty, &termbuf);
     81 	termbuf2 = termbuf;
     82 }
     83 
     84 #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
     85 void
     86 copy_termbuf(cp, len)
     87 	char *cp;
     88 	int len;
     89 {
     90 	if (len > sizeof(termbuf))
     91 		len = sizeof(termbuf);
     92 	memmove((char *)&termbuf, cp, len);
     93 	termbuf2 = termbuf;
     94 }
     95 #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
     96 
     97 void
     98 set_termbuf()
     99 {
    100 	/*
    101 	 * Only make the necessary changes.
    102 	 */
    103 	if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
    104 		(void) tcsetattr(pty, TCSANOW, &termbuf);
    105 }
    106 
    107 
    108 /*
    109  * spcset(func, valp, valpp)
    110  *
    111  * This function takes various special characters (func), and
    112  * sets *valp to the current value of that character, and
    113  * *valpp to point to where in the "termbuf" structure that
    114  * value is kept.
    115  *
    116  * It returns the SLC_ level of support for this function.
    117  */
    118 
    119 
    120 int
    121 spcset(func, valp, valpp)
    122 	int func;
    123 	cc_t *valp;
    124 	cc_t **valpp;
    125 {
    126 
    127 #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
    128 			*valpp = &termbuf.c_cc[a]; \
    129 			return(b);
    130 #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
    131 
    132 	switch(func) {
    133 	case SLC_EOF:
    134 		setval(VEOF, SLC_VARIABLE);
    135 	case SLC_EC:
    136 		setval(VERASE, SLC_VARIABLE);
    137 	case SLC_EL:
    138 		setval(VKILL, SLC_VARIABLE);
    139 	case SLC_IP:
    140 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
    141 	case SLC_ABORT:
    142 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
    143 	case SLC_XON:
    144 		setval(VSTART, SLC_VARIABLE);
    145 	case SLC_XOFF:
    146 		setval(VSTOP, SLC_VARIABLE);
    147 	case SLC_EW:
    148 		setval(VWERASE, SLC_VARIABLE);
    149 	case SLC_RP:
    150 		setval(VREPRINT, SLC_VARIABLE);
    151 	case SLC_LNEXT:
    152 		setval(VLNEXT, SLC_VARIABLE);
    153 	case SLC_AO:
    154 		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
    155 	case SLC_SUSP:
    156 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
    157 	case SLC_FORW1:
    158 		setval(VEOL, SLC_VARIABLE);
    159 	case SLC_FORW2:
    160 		setval(VEOL2, SLC_VARIABLE);
    161 	case SLC_AYT:
    162 		setval(VSTATUS, SLC_VARIABLE);
    163 
    164 	case SLC_BRK:
    165 	case SLC_SYNCH:
    166 	case SLC_EOR:
    167 		defval(0);
    168 
    169 	default:
    170 		*valp = 0;
    171 		*valpp = 0;
    172 		return(SLC_NOSUPPORT);
    173 	}
    174 }
    175 
    176 
    177 /*
    178  * getpty()
    179  *
    180  * Allocate a pty.  As a side effect, the external character
    181  * array "line" contains the name of the slave side.
    182  *
    183  * Returns the file descriptor of the opened pty.
    184  */
    185 #ifndef	__GNUC__
    186 char *line = NULL16STR;
    187 #else
    188 static char Xline[] = NULL16STR;
    189 char *line = Xline;
    190 #endif
    191 
    192 
    193 static int ptyslavefd; /* for cleanopen() */
    194 
    195 int
    196 getpty(ptynum)
    197 int *ptynum;
    198 {
    199 	int ptyfd;
    200 
    201 	ptyfd = openpty(ptynum, &ptyslavefd, line, NULL, NULL);
    202 	if (ptyfd == 0)
    203 		return *ptynum;
    204 	ptyslavefd = -1;
    205 	return (-1);
    206 }
    207 
    208 #ifdef	LINEMODE
    209 /*
    210  * tty_flowmode()	Find out if flow control is enabled or disabled.
    211  * tty_linemode()	Find out if linemode (external processing) is enabled.
    212  * tty_setlinemod(on)	Turn on/off linemode.
    213  * tty_isecho()		Find out if echoing is turned on.
    214  * tty_setecho(on)	Enable/disable character echoing.
    215  * tty_israw()		Find out if terminal is in RAW mode.
    216  * tty_binaryin(on)	Turn on/off BINARY on input.
    217  * tty_binaryout(on)	Turn on/off BINARY on output.
    218  * tty_isediting()	Find out if line editing is enabled.
    219  * tty_istrapsig()	Find out if signal trapping is enabled.
    220  * tty_setedit(on)	Turn on/off line editing.
    221  * tty_setsig(on)	Turn on/off signal trapping.
    222  * tty_issofttab()	Find out if tab expansion is enabled.
    223  * tty_setsofttab(on)	Turn on/off soft tab expansion.
    224  * tty_islitecho()	Find out if typed control chars are echoed literally
    225  * tty_setlitecho()	Turn on/off literal echo of control chars
    226  * tty_tspeed(val)	Set transmit speed to val.
    227  * tty_rspeed(val)	Set receive speed to val.
    228  */
    229 
    230 
    231 int
    232 tty_linemode()
    233 {
    234 	return(termbuf.c_lflag & EXTPROC);
    235 }
    236 
    237 void
    238 tty_setlinemode(on)
    239 	int on;
    240 {
    241 	set_termbuf();
    242 	(void) ioctl(pty, TIOCEXT, (char *)&on);
    243 	init_termbuf();
    244 }
    245 #endif	/* LINEMODE */
    246 
    247 int
    248 tty_isecho()
    249 {
    250 	return (termbuf.c_lflag & ECHO);
    251 }
    252 
    253 int
    254 tty_flowmode()
    255 {
    256 	return((termbuf.c_iflag & IXON) ? 1 : 0);
    257 }
    258 
    259 int
    260 tty_restartany()
    261 {
    262 	return((termbuf.c_iflag & IXANY) ? 1 : 0);
    263 }
    264 
    265 void
    266 tty_setecho(on)
    267 	int on;
    268 {
    269 	if (on)
    270 		termbuf.c_lflag |= ECHO;
    271 	else
    272 		termbuf.c_lflag &= ~ECHO;
    273 }
    274 
    275 int
    276 tty_israw()
    277 {
    278 	return(!(termbuf.c_lflag & ICANON));
    279 }
    280 
    281 void
    282 tty_binaryin(on)
    283 	int on;
    284 {
    285 	if (on) {
    286 		termbuf.c_iflag &= ~ISTRIP;
    287 	} else {
    288 		termbuf.c_iflag |= ISTRIP;
    289 	}
    290 }
    291 
    292 void
    293 tty_binaryout(on)
    294 	int on;
    295 {
    296 	if (on) {
    297 		termbuf.c_cflag &= ~(CSIZE|PARENB);
    298 		termbuf.c_cflag |= CS8;
    299 		termbuf.c_oflag &= ~OPOST;
    300 	} else {
    301 		termbuf.c_cflag &= ~CSIZE;
    302 		termbuf.c_cflag |= CS7|PARENB;
    303 		termbuf.c_oflag |= OPOST;
    304 	}
    305 }
    306 
    307 int
    308 tty_isbinaryin()
    309 {
    310 	return(!(termbuf.c_iflag & ISTRIP));
    311 }
    312 
    313 int
    314 tty_isbinaryout()
    315 {
    316 	return(!(termbuf.c_oflag&OPOST));
    317 }
    318 
    319 #ifdef	LINEMODE
    320 int
    321 tty_isediting()
    322 {
    323 	return(termbuf.c_lflag & ICANON);
    324 }
    325 
    326 int
    327 tty_istrapsig()
    328 {
    329 	return(termbuf.c_lflag & ISIG);
    330 }
    331 
    332 void
    333 tty_setedit(on)
    334 	int on;
    335 {
    336 	if (on)
    337 		termbuf.c_lflag |= ICANON;
    338 	else
    339 		termbuf.c_lflag &= ~ICANON;
    340 }
    341 
    342 void
    343 tty_setsig(on)
    344 	int on;
    345 {
    346 	if (on)
    347 		termbuf.c_lflag |= ISIG;
    348 	else
    349 		termbuf.c_lflag &= ~ISIG;
    350 }
    351 #endif	/* LINEMODE */
    352 
    353 int
    354 tty_issofttab()
    355 {
    356 # ifdef	OXTABS
    357 	return (termbuf.c_oflag & OXTABS);
    358 # endif
    359 # ifdef	TABDLY
    360 	return ((termbuf.c_oflag & TABDLY) == TAB3);
    361 # endif
    362 }
    363 
    364 void
    365 tty_setsofttab(on)
    366 	int on;
    367 {
    368 	if (on) {
    369 # ifdef	OXTABS
    370 		termbuf.c_oflag |= OXTABS;
    371 # endif
    372 # ifdef	TABDLY
    373 		termbuf.c_oflag &= ~TABDLY;
    374 		termbuf.c_oflag |= TAB3;
    375 # endif
    376 	} else {
    377 # ifdef	OXTABS
    378 		termbuf.c_oflag &= ~OXTABS;
    379 # endif
    380 # ifdef	TABDLY
    381 		termbuf.c_oflag &= ~TABDLY;
    382 		termbuf.c_oflag |= TAB0;
    383 # endif
    384 	}
    385 }
    386 
    387 int
    388 tty_islitecho()
    389 {
    390 # ifdef	ECHOCTL
    391 	return (!(termbuf.c_lflag & ECHOCTL));
    392 # endif
    393 # ifdef	TCTLECH
    394 	return (!(termbuf.c_lflag & TCTLECH));
    395 # endif
    396 # if	!defined(ECHOCTL) && !defined(TCTLECH)
    397 	return (0);	/* assumes ctl chars are echoed '^x' */
    398 # endif
    399 }
    400 
    401 void
    402 tty_setlitecho(on)
    403 	int on;
    404 {
    405 # ifdef	ECHOCTL
    406 	if (on)
    407 		termbuf.c_lflag &= ~ECHOCTL;
    408 	else
    409 		termbuf.c_lflag |= ECHOCTL;
    410 # endif
    411 # ifdef	TCTLECH
    412 	if (on)
    413 		termbuf.c_lflag &= ~TCTLECH;
    414 	else
    415 		termbuf.c_lflag |= TCTLECH;
    416 # endif
    417 }
    418 
    419 int
    420 tty_iscrnl()
    421 {
    422 	return (termbuf.c_iflag & ICRNL);
    423 }
    424 
    425 void
    426 tty_tspeed(val)
    427 	int val;
    428 {
    429 	cfsetospeed(&termbuf, val);
    430 }
    431 
    432 void
    433 tty_rspeed(val)
    434 	int val;
    435 {
    436 	cfsetispeed(&termbuf, val);
    437 }
    438 
    439 
    440 
    441 
    442 /*
    443  * getptyslave()
    444  *
    445  * Open the slave side of the pty, and do any initialization
    446  * that is necessary.  The return value is a file descriptor
    447  * for the slave side.
    448  */
    449 extern int def_tspeed, def_rspeed;
    450 	extern int def_row, def_col;
    451 
    452     void
    453 getptyslave()
    454 {
    455 	register int t = -1;
    456 
    457 #ifdef	LINEMODE
    458 	int waslm;
    459 #endif
    460 	struct winsize ws;
    461 	/*
    462 	 * Opening the slave side may cause initilization of the
    463 	 * kernel tty structure.  We need remember the state of
    464 	 * 	if linemode was turned on
    465 	 *	terminal window size
    466 	 *	terminal speed
    467 	 * so that we can re-set them if we need to.
    468 	 */
    469 #ifdef	LINEMODE
    470 	waslm = tty_linemode();
    471 #endif
    472 
    473 	/*
    474 	 * Make sure that we don't have a controlling tty, and
    475 	 * that we are the session (process group) leader.
    476 	 */
    477 	t = open(_PATH_TTY, O_RDWR);
    478 	if (t >= 0) {
    479 		(void) ioctl(t, TIOCNOTTY, (char *)0);
    480 		(void) close(t);
    481 	}
    482 
    483 
    484 
    485 	t = cleanopen(line);
    486 	if (t < 0)
    487 		fatalperror(net, line);
    488 
    489 
    490 	/*
    491 	 * set up the tty modes as we like them to be.
    492 	 */
    493 	init_termbuf();
    494 	if (def_row || def_col) {
    495 		memset((char *)&ws, 0, sizeof(ws));
    496 		ws.ws_col = def_col;
    497 		ws.ws_row = def_row;
    498 		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
    499 	}
    500 
    501 	/*
    502 	 * Settings for sgtty based systems
    503 	 */
    504 
    505 	/*
    506 	 * Settings for all other termios/termio based
    507 	 * systems, other than 4.4BSD.  In 4.4BSD the
    508 	 * kernel does the initial terminal setup.
    509 	 */
    510 	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
    511 	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
    512 #ifdef	LINEMODE
    513 	if (waslm)
    514 		tty_setlinemode(1);
    515 #endif	/* LINEMODE */
    516 
    517 	/*
    518 	 * Set the tty modes, and make this our controlling tty.
    519 	 */
    520 	set_termbuf();
    521 	if (login_tty(t) == -1)
    522 		fatalperror(net, "login_tty");
    523 	if (net > 2)
    524 		(void) close(net);
    525 	if (pty > 2) {
    526 		(void) close(pty);
    527 		pty = -1;
    528 	}
    529 }
    530 
    531 /*
    532  * Open the specified slave side of the pty,
    533  * making sure that we have a clean tty.
    534  */
    535 int
    536 cleanopen(ttyline)
    537 	char *ttyline;
    538 {
    539 	return ptyslavefd;
    540 }
    541 
    542 /*
    543  * startslave(host)
    544  *
    545  * Given a hostname, do whatever
    546  * is necessary to startup the login process on the slave side of the pty.
    547  */
    548 
    549 /* ARGSUSED */
    550 void
    551 startslave(host, autologin, autoname)
    552 	char *host;
    553 	int autologin;
    554 	char *autoname;
    555 {
    556 	register int i;
    557 
    558 #ifdef AUTHENTICATION
    559 	if (!autoname || !autoname[0])
    560 		autologin = 0;
    561 
    562 	if (autologin < auth_level) {
    563 		fatal(net, "Authorization failed");
    564 		exit(1);
    565 	}
    566 #endif
    567 
    568 
    569 	if ((i = fork()) < 0)
    570 		fatalperror(net, "fork");
    571 	if (i) {
    572 	} else {
    573 		getptyslave();
    574 		start_login(host, autologin, autoname);
    575 		/*NOTREACHED*/
    576 	}
    577 }
    578 
    579 char	*envinit[3];
    580 
    581 void
    582 init_env()
    583 {
    584 	char **envp;
    585 
    586 	envp = envinit;
    587 	if ((*envp = getenv("TZ")))
    588 		*envp++ -= 3;
    589 	*envp = 0;
    590 	environ = envinit;
    591 }
    592 
    593 
    594 /*
    595  * start_login(host)
    596  *
    597  * Assuming that we are now running as a child processes, this
    598  * function will turn us into the login process.
    599  */
    600 extern char *gettyname;
    601 
    602 void
    603 start_login(host, autologin, name)
    604 	char *host;
    605 	int autologin;
    606 	char *name;
    607 {
    608 	register char **argv;
    609 #define	TABBUFSIZ	512
    610 	char	defent[TABBUFSIZ];
    611 	char	defstrs[TABBUFSIZ];
    612 #undef	TABBUFSIZ
    613 	const char *loginprog = NULL;
    614 
    615 
    616 	scrub_env();
    617 
    618 	/*
    619 	 * -h : pass on name of host.
    620 	 *		WARNING:  -h is accepted by login if and only if
    621 	 *			getuid() == 0.
    622 	 * -p : don't clobber the environment (so terminal type stays set).
    623 	 *
    624 	 * -f : force this login, he has already been authenticated
    625 	 */
    626 	argv = addarg(0, "login");
    627 
    628 	{
    629 		argv = addarg(argv, "-h");
    630 		argv = addarg(argv, host);
    631 	}
    632 	argv = addarg(argv, "-p");
    633 #ifdef	LINEMODE
    634 	/*
    635 	 * Set the environment variable "LINEMODE" to either
    636 	 * "real" or "kludge" if we are operating in either
    637 	 * real or kludge linemode.
    638 	 */
    639 	if (lmodetype == REAL_LINEMODE)
    640 		setenv("LINEMODE", "real", 1);
    641 # ifdef KLUDGELINEMODE
    642 	else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
    643 		setenv("LINEMODE", "kludge", 1);
    644 # endif
    645 #endif
    646 #ifdef SECURELOGIN
    647 	/*
    648 	 * don't worry about the -f that might get sent.
    649 	 * A -s is supposed to override it anyhow.
    650 	 */
    651 	if (require_secure_login)
    652 		argv = addarg(argv, "-s");
    653 #endif
    654 #ifdef AUTHENTICATION
    655 	if (auth_level >= 0 && autologin == AUTH_VALID) {
    656 		argv = addarg(argv, "-f");
    657 		argv = addarg(argv, "--");
    658 		argv = addarg(argv, name);
    659 	} else
    660 #endif
    661 	if (getenv("USER")) {
    662 		argv = addarg(argv, "--");
    663 		argv = addarg(argv, getenv("USER"));
    664 		/*
    665 		 * Assume that login will set the USER variable
    666 		 * correctly.  For SysV systems, this means that
    667 		 * USER will no longer be set, just LOGNAME by
    668 		 * login.  (The problem is that if the auto-login
    669 		 * fails, and the user then specifies a different
    670 		 * account name, he can get logged in with both
    671 		 * LOGNAME and USER in his environment, but the
    672 		 * USER value will be wrong.
    673 		 */
    674 		unsetenv("USER");
    675 	}
    676         if (getent(defent, gettyname) == 1) {
    677                 char *cp = defstrs;
    678 
    679                 loginprog = getstr("lo", &cp);
    680         }
    681         if (loginprog == NULL)
    682                 loginprog = _PATH_LOGIN;
    683 	closelog();
    684 	/*
    685 	 * This sleep(1) is in here so that telnetd can
    686 	 * finish up with the tty.  There's a race condition
    687 	 * the login banner message gets lost...
    688 	 */
    689 	sleep(1);
    690         execv(loginprog, argv);
    691 
    692         syslog(LOG_ERR, "%s: %m", loginprog);
    693         fatalperror(net, loginprog);
    694 	/*NOTREACHED*/
    695 }
    696 
    697 	char **
    698 addarg(argv, val)
    699 	register char **argv;
    700 	register char *val;
    701 {
    702 	register char **cpp;
    703 	char **nargv;
    704 
    705 	if (argv == NULL) {
    706 		/*
    707 		 * 10 entries, a leading length, and a null
    708 		 */
    709 		argv = (char **)malloc(sizeof(*argv) * 12);
    710 		if (argv == NULL)
    711 			return(NULL);
    712 		*argv++ = (char *)10;
    713 		*argv = (char *)0;
    714 	}
    715 	for (cpp = argv; *cpp; cpp++)
    716 		;
    717 	if (cpp == &argv[(long)argv[-1]]) {
    718 		--argv;
    719 		nargv = (char **)realloc(argv,
    720 		    sizeof(*argv) * ((long)(*argv) + 10 + 2));
    721 		if (argv == NULL) {
    722 			fatal(net, "not enough memory");
    723 			/*NOTREACHED*/
    724 		}
    725 		argv = nargv;
    726 		*argv = (char *)((long)(*argv) + 10);
    727 		argv++;
    728 		cpp = &argv[(long)argv[-1] - 10];
    729 	}
    730 	*cpp++ = val;
    731 	*cpp = 0;
    732 	return(argv);
    733 }
    734 
    735 /*
    736  * scrub_env()
    737  *
    738  * We only accept the environment variables listed below.
    739  */
    740 
    741 void
    742 scrub_env()
    743 {
    744 	static const char *reject[] = {
    745 		"TERMCAP=/",
    746 		NULL
    747 	};
    748 
    749 	static const char *acceptstr[] = {
    750 		"XAUTH=", "XAUTHORITY=", "DISPLAY=",
    751 		"TERM=",
    752 		"EDITOR=",
    753 		"PAGER=",
    754 		"LOGNAME=",
    755 		"POSIXLY_CORRECT=",
    756 		"TERMCAP=",
    757 		"PRINTER=",
    758 		NULL
    759 	};
    760 
    761 	char **cpp, **cpp2;
    762 	const char **p;
    763 
    764 	for (cpp2 = cpp = environ; *cpp; cpp++) {
    765 		int reject_it = 0;
    766 
    767 		for(p = reject; *p; p++)
    768 			if(strncmp(*cpp, *p, strlen(*p)) == 0) {
    769 				reject_it = 1;
    770 				break;
    771 			}
    772 		if (reject_it)
    773 			continue;
    774 
    775 		for(p = acceptstr; *p; p++)
    776 			if(strncmp(*cpp, *p, strlen(*p)) == 0)
    777 				break;
    778 		if(*p != NULL)
    779 			*cpp2++ = *cpp;
    780 	}
    781 	*cpp2 = NULL;
    782 }
    783 
    784 /*
    785  * cleanup()
    786  *
    787  * This is the routine to call when we are all through, to
    788  * clean up anything that needs to be cleaned up.
    789  */
    790 /* ARGSUSED */
    791 void
    792 cleanup(sig)
    793 	int sig;
    794 {
    795 	char *p, c;
    796 
    797 	p = line + sizeof("/dev/") - 1;
    798 #ifdef SUPPORT_UTMP
    799 	if (logout(p))
    800 		logwtmp(p, "", "");
    801 #endif
    802 #ifdef SUPPORT_UTMPX
    803 	if (logoutx(p, 0, DEAD_PROCESS))
    804 		logwtmpx(p, "", "", 0, DEAD_PROCESS);
    805 #endif
    806 	(void)chmod(line, 0666);
    807 	(void)chown(line, 0, 0);
    808 	c = *p; *p = 'p';
    809 	(void)chmod(line, 0666);
    810 	(void)chown(line, 0, 0);
    811 	*p = c;
    812 	if (ttyaction(line, "telnetd", "root"))
    813 		syslog(LOG_ERR, "%s: ttyaction failed", line);
    814 	(void) shutdown(net, 2);
    815 	exit(1);
    816 }
    817