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