187139Smarkm /*
229088Smarkm * Copyright (c) 1989, 1993
329088Smarkm *	The Regents of the University of California.  All rights reserved.
429088Smarkm *
529088Smarkm * Redistribution and use in source and binary forms, with or without
629088Smarkm * modification, are permitted provided that the following conditions
729088Smarkm * are met:
829088Smarkm * 1. Redistributions of source code must retain the above copyright
929088Smarkm *    notice, this list of conditions and the following disclaimer.
1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1129088Smarkm *    notice, this list of conditions and the following disclaimer in the
1229088Smarkm *    documentation and/or other materials provided with the distribution.
1329088Smarkm * 3. All advertising materials mentioning features or use of this software
1429088Smarkm *    must display the following acknowledgement:
1529088Smarkm *	This product includes software developed by the University of
1629088Smarkm *	California, Berkeley and its contributors.
1729088Smarkm * 4. Neither the name of the University nor the names of its contributors
1829088Smarkm *    may be used to endorse or promote products derived from this software
1929088Smarkm *    without specific prior written permission.
2029088Smarkm *
2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2429088Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3129088Smarkm * SUCH DAMAGE.
3229088Smarkm */
3329088Smarkm
34114630Sobrien#if 0
3529088Smarkm#ifndef lint
3629181Smarkmstatic const char sccsid[] = "@(#)sys_term.c	8.4+1 (Berkeley) 5/30/95";
3731622Scharnier#endif
38114630Sobrien#endif
39114630Sobrien#include <sys/cdefs.h>
40114630Sobrien__FBSDID("$FreeBSD: releng/9.3/contrib/telnet/telnetd/sys_term.c 309637 2016-12-06 18:50:06Z glebius $");
4129088Smarkm
4287139Smarkm#include <sys/types.h>
4387139Smarkm#include <sys/tty.h>
4487139Smarkm#include <libutil.h>
4587139Smarkm#include <stdlib.h>
4687139Smarkm
4729088Smarkm#include "telnetd.h"
4829088Smarkm#include "pathnames.h"
4929088Smarkm
5087139Smarkm#ifdef	AUTHENTICATION
5129088Smarkm#include <libtelnet/auth.h>
5229088Smarkm#endif
5329088Smarkm
5487139Smarkmint cleanopen(char *);
5529181Smarkmvoid scrub_env(void);
5629181Smarkm
5787139Smarkmchar	*envinit[3];
5887139Smarkmextern char **environ;
5929181Smarkm
6029088Smarkm#define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
6129088Smarkm#define SCMPN(a, b)	strncmp(a, b, sizeof(a))
6229088Smarkm
6329088Smarkm#ifdef	t_erase
6429088Smarkm#undef	t_erase
6529088Smarkm#undef	t_kill
6629088Smarkm#undef	t_intrc
6729088Smarkm#undef	t_quitc
6829088Smarkm#undef	t_startc
6929088Smarkm#undef	t_stopc
7029088Smarkm#undef	t_eofc
7129088Smarkm#undef	t_brkc
7229088Smarkm#undef	t_suspc
7329088Smarkm#undef	t_dsuspc
7429088Smarkm#undef	t_rprntc
7529088Smarkm#undef	t_flushc
7629088Smarkm#undef	t_werasc
7729088Smarkm#undef	t_lnextc
7829088Smarkm#endif
7929088Smarkm
8029088Smarkm#ifndef	USE_TERMIO
8129088Smarkmstruct termbuf {
8229088Smarkm	struct sgttyb sg;
8329088Smarkm	struct tchars tc;
8429088Smarkm	struct ltchars ltc;
8529088Smarkm	int state;
8629088Smarkm	int lflags;
8729088Smarkm} termbuf, termbuf2;
8829088Smarkm# define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
8929088Smarkm# define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
9029088Smarkm# define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
9129088Smarkm# define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
9229088Smarkm#else	/* USE_TERMIO */
9329088Smarkm# ifndef	TCSANOW
9429088Smarkm#  ifdef TCSETS
9529088Smarkm#   define	TCSANOW		TCSETS
9629088Smarkm#   define	TCSADRAIN	TCSETSW
9729088Smarkm#   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
9829088Smarkm#  else
9929088Smarkm#   ifdef TCSETA
10029088Smarkm#    define	TCSANOW		TCSETA
10129088Smarkm#    define	TCSADRAIN	TCSETAW
10229088Smarkm#    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
10329088Smarkm#   else
10429088Smarkm#    define	TCSANOW		TIOCSETA
10529088Smarkm#    define	TCSADRAIN	TIOCSETAW
10629088Smarkm#    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
10729088Smarkm#   endif
10829088Smarkm#  endif
10929088Smarkm#  define	tcsetattr(f, a, t)	ioctl(f, a, t)
11029088Smarkm#  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
11129088Smarkm					(tp)->c_cflag |= (val)
11229088Smarkm#  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
11329088Smarkm#  ifdef CIBAUD
11429088Smarkm#   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
11529088Smarkm					(tp)->c_cflag |= ((val)<<IBSHIFT)
11629088Smarkm#   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
11729088Smarkm#  else
11829088Smarkm#   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
11929088Smarkm					(tp)->c_cflag |= (val)
12029088Smarkm#   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
12129088Smarkm#  endif
12229088Smarkm# endif /* TCSANOW */
12329088Smarkmstruct termios termbuf, termbuf2;	/* pty control structure */
12429088Smarkm#endif	/* USE_TERMIO */
12529088Smarkm
12631622Scharnier#include <sys/types.h>
12731622Scharnier#include <libutil.h>
12831622Scharnier
12987155Smarkmint cleanopen(char *);
13087155Smarkmvoid scrub_env(void);
13187155Smarkmstatic char **addarg(char **, const char *);
13231622Scharnier
13329088Smarkm/*
13429088Smarkm * init_termbuf()
13529088Smarkm * copy_termbuf(cp)
13629088Smarkm * set_termbuf()
13729088Smarkm *
13829088Smarkm * These three routines are used to get and set the "termbuf" structure
13929088Smarkm * to and from the kernel.  init_termbuf() gets the current settings.
14029088Smarkm * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
14129088Smarkm * set_termbuf() writes the structure into the kernel.
14229088Smarkm */
14329088Smarkm
14487139Smarkmvoid
14587139Smarkminit_termbuf(void)
14629088Smarkm{
14729088Smarkm#ifndef	USE_TERMIO
14829088Smarkm	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
14929088Smarkm	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
15029088Smarkm	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
15129088Smarkm# ifdef	TIOCGSTATE
15229088Smarkm	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
15329088Smarkm# endif
15429088Smarkm#else
15529088Smarkm	(void) tcgetattr(pty, &termbuf);
15629088Smarkm#endif
15729088Smarkm	termbuf2 = termbuf;
15829088Smarkm}
15929088Smarkm
16029088Smarkm#if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
16187139Smarkmvoid
16287139Smarkmcopy_termbuf(char *cp, size_t len)
16329088Smarkm{
16429088Smarkm	if (len > sizeof(termbuf))
16529088Smarkm		len = sizeof(termbuf);
16629088Smarkm	memmove((char *)&termbuf, cp, len);
16729088Smarkm	termbuf2 = termbuf;
16829088Smarkm}
16929088Smarkm#endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
17029088Smarkm
17187139Smarkmvoid
17287139Smarkmset_termbuf(void)
17329088Smarkm{
17429088Smarkm	/*
17529088Smarkm	 * Only make the necessary changes.
17629088Smarkm	 */
17729088Smarkm#ifndef	USE_TERMIO
17829088Smarkm	if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
17929088Smarkm							sizeof(termbuf.sg)))
18029088Smarkm		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
18129088Smarkm	if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
18229088Smarkm							sizeof(termbuf.tc)))
18329088Smarkm		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
18429088Smarkm	if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
18529088Smarkm							sizeof(termbuf.ltc)))
18629088Smarkm		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
18729088Smarkm	if (termbuf.lflags != termbuf2.lflags)
18829088Smarkm		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
18929088Smarkm#else	/* USE_TERMIO */
19029088Smarkm	if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
19129088Smarkm		(void) tcsetattr(pty, TCSANOW, &termbuf);
19229088Smarkm#endif	/* USE_TERMIO */
19329088Smarkm}
19429088Smarkm
19529088Smarkm
19629088Smarkm/*
19729088Smarkm * spcset(func, valp, valpp)
19829088Smarkm *
19929088Smarkm * This function takes various special characters (func), and
20029088Smarkm * sets *valp to the current value of that character, and
20129088Smarkm * *valpp to point to where in the "termbuf" structure that
20229088Smarkm * value is kept.
20329088Smarkm *
20429088Smarkm * It returns the SLC_ level of support for this function.
20529088Smarkm */
20629088Smarkm
20729088Smarkm#ifndef	USE_TERMIO
20887139Smarkmint
20987139Smarkmspcset(int func, cc_t *valp, cc_t **valpp)
21029088Smarkm{
21129088Smarkm	switch(func) {
21229088Smarkm	case SLC_EOF:
21329088Smarkm		*valp = termbuf.tc.t_eofc;
21429088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_eofc;
21529088Smarkm		return(SLC_VARIABLE);
21629088Smarkm	case SLC_EC:
21729088Smarkm		*valp = termbuf.sg.sg_erase;
21829088Smarkm		*valpp = (cc_t *)&termbuf.sg.sg_erase;
21929088Smarkm		return(SLC_VARIABLE);
22029088Smarkm	case SLC_EL:
22129088Smarkm		*valp = termbuf.sg.sg_kill;
22229088Smarkm		*valpp = (cc_t *)&termbuf.sg.sg_kill;
22329088Smarkm		return(SLC_VARIABLE);
22429088Smarkm	case SLC_IP:
22529088Smarkm		*valp = termbuf.tc.t_intrc;
22629088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_intrc;
22729088Smarkm		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
22829088Smarkm	case SLC_ABORT:
22929088Smarkm		*valp = termbuf.tc.t_quitc;
23029088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_quitc;
23129088Smarkm		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
23229088Smarkm	case SLC_XON:
23329088Smarkm		*valp = termbuf.tc.t_startc;
23429088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_startc;
23529088Smarkm		return(SLC_VARIABLE);
23629088Smarkm	case SLC_XOFF:
23729088Smarkm		*valp = termbuf.tc.t_stopc;
23829088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_stopc;
23929088Smarkm		return(SLC_VARIABLE);
24029088Smarkm	case SLC_AO:
24129088Smarkm		*valp = termbuf.ltc.t_flushc;
24229088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
24329088Smarkm		return(SLC_VARIABLE);
24429088Smarkm	case SLC_SUSP:
24529088Smarkm		*valp = termbuf.ltc.t_suspc;
24629088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
24729088Smarkm		return(SLC_VARIABLE);
24829088Smarkm	case SLC_EW:
24929088Smarkm		*valp = termbuf.ltc.t_werasc;
25029088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
25129088Smarkm		return(SLC_VARIABLE);
25229088Smarkm	case SLC_RP:
25329088Smarkm		*valp = termbuf.ltc.t_rprntc;
25429088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
25529088Smarkm		return(SLC_VARIABLE);
25629088Smarkm	case SLC_LNEXT:
25729088Smarkm		*valp = termbuf.ltc.t_lnextc;
25829088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
25929088Smarkm		return(SLC_VARIABLE);
26029088Smarkm	case SLC_FORW1:
26129088Smarkm		*valp = termbuf.tc.t_brkc;
26229088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
26329088Smarkm		return(SLC_VARIABLE);
26429088Smarkm	case SLC_BRK:
26529088Smarkm	case SLC_SYNCH:
26629088Smarkm	case SLC_AYT:
26729088Smarkm	case SLC_EOR:
26829088Smarkm		*valp = (cc_t)0;
26929088Smarkm		*valpp = (cc_t *)0;
27029088Smarkm		return(SLC_DEFAULT);
27129088Smarkm	default:
27229088Smarkm		*valp = (cc_t)0;
27329088Smarkm		*valpp = (cc_t *)0;
27429088Smarkm		return(SLC_NOSUPPORT);
27529088Smarkm	}
27629088Smarkm}
27729088Smarkm
27829088Smarkm#else	/* USE_TERMIO */
27929088Smarkm
28029088Smarkm
28129088Smarkm#define	setval(a, b)	*valp = termbuf.c_cc[a]; \
28229088Smarkm			*valpp = &termbuf.c_cc[a]; \
28329088Smarkm			return(b);
28429088Smarkm#define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
28529088Smarkm
28687139Smarkmint
28787139Smarkmspcset(int func, cc_t *valp, cc_t **valpp)
28887139Smarkm{
28929088Smarkm	switch(func) {
29029088Smarkm	case SLC_EOF:
29129088Smarkm		setval(VEOF, SLC_VARIABLE);
29229088Smarkm	case SLC_EC:
29329088Smarkm		setval(VERASE, SLC_VARIABLE);
29429088Smarkm	case SLC_EL:
29529088Smarkm		setval(VKILL, SLC_VARIABLE);
29629088Smarkm	case SLC_IP:
29729088Smarkm		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
29829088Smarkm	case SLC_ABORT:
29929088Smarkm		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
30029088Smarkm	case SLC_XON:
30129088Smarkm#ifdef	VSTART
30229088Smarkm		setval(VSTART, SLC_VARIABLE);
30329088Smarkm#else
30429088Smarkm		defval(0x13);
30529088Smarkm#endif
30629088Smarkm	case SLC_XOFF:
30729088Smarkm#ifdef	VSTOP
30829088Smarkm		setval(VSTOP, SLC_VARIABLE);
30929088Smarkm#else
31029088Smarkm		defval(0x11);
31129088Smarkm#endif
31229088Smarkm	case SLC_EW:
31329088Smarkm#ifdef	VWERASE
31429088Smarkm		setval(VWERASE, SLC_VARIABLE);
31529088Smarkm#else
31629088Smarkm		defval(0);
31729088Smarkm#endif
31829088Smarkm	case SLC_RP:
31929088Smarkm#ifdef	VREPRINT
32029088Smarkm		setval(VREPRINT, SLC_VARIABLE);
32129088Smarkm#else
32229088Smarkm		defval(0);
32329088Smarkm#endif
32429088Smarkm	case SLC_LNEXT:
32529088Smarkm#ifdef	VLNEXT
32629088Smarkm		setval(VLNEXT, SLC_VARIABLE);
32729088Smarkm#else
32829088Smarkm		defval(0);
32929088Smarkm#endif
33029088Smarkm	case SLC_AO:
33129088Smarkm#if	!defined(VDISCARD) && defined(VFLUSHO)
33229088Smarkm# define VDISCARD VFLUSHO
33329088Smarkm#endif
33429088Smarkm#ifdef	VDISCARD
33529088Smarkm		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
33629088Smarkm#else
33729088Smarkm		defval(0);
33829088Smarkm#endif
33929088Smarkm	case SLC_SUSP:
34029088Smarkm#ifdef	VSUSP
34129088Smarkm		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
34229088Smarkm#else
34329088Smarkm		defval(0);
34429088Smarkm#endif
34529088Smarkm#ifdef	VEOL
34629088Smarkm	case SLC_FORW1:
34729088Smarkm		setval(VEOL, SLC_VARIABLE);
34829088Smarkm#endif
34929088Smarkm#ifdef	VEOL2
35029088Smarkm	case SLC_FORW2:
35129088Smarkm		setval(VEOL2, SLC_VARIABLE);
35229088Smarkm#endif
35329088Smarkm	case SLC_AYT:
35429088Smarkm#ifdef	VSTATUS
35529088Smarkm		setval(VSTATUS, SLC_VARIABLE);
35629088Smarkm#else
35729088Smarkm		defval(0);
35829088Smarkm#endif
35929088Smarkm
36029088Smarkm	case SLC_BRK:
36129088Smarkm	case SLC_SYNCH:
36229088Smarkm	case SLC_EOR:
36329088Smarkm		defval(0);
36429088Smarkm
36529088Smarkm	default:
36629088Smarkm		*valp = 0;
36729088Smarkm		*valpp = 0;
36829088Smarkm		return(SLC_NOSUPPORT);
36929088Smarkm	}
37029088Smarkm}
37129088Smarkm#endif	/* USE_TERMIO */
37229088Smarkm
37329088Smarkm/*
37429088Smarkm * getpty()
37529088Smarkm *
37629088Smarkm * Allocate a pty.  As a side effect, the external character
37729088Smarkm * array "line" contains the name of the slave side.
37829088Smarkm *
37929088Smarkm * Returns the file descriptor of the opened pty.
38029088Smarkm */
381184935Sedchar line[32];
38229088Smarkm
38387139Smarkmint
38487139Smarkmgetpty(int *ptynum __unused)
38529088Smarkm{
38687139Smarkm	int p;
387184935Sed	const char *pn;
38829088Smarkm
389184935Sed	p = posix_openpt(O_RDWR|O_NOCTTY);
390184935Sed	if (p < 0)
391184935Sed		return (-1);
392184935Sed
393184935Sed	if (grantpt(p) == -1)
394184935Sed		return (-1);
39529088Smarkm
396184935Sed	if (unlockpt(p) == -1)
397184935Sed		return (-1);
398184935Sed
399184935Sed	pn = ptsname(p);
400184935Sed	if (pn == NULL)
401184935Sed		return (-1);
402184935Sed
403184938Sed	if (strlcpy(line, pn, sizeof line) >= sizeof line)
404184938Sed		return (-1);
40529088Smarkm
406184935Sed	return (p);
40729088Smarkm}
40829088Smarkm
40929088Smarkm#ifdef	LINEMODE
41029088Smarkm/*
41129088Smarkm * tty_flowmode()	Find out if flow control is enabled or disabled.
41229088Smarkm * tty_linemode()	Find out if linemode (external processing) is enabled.
41329088Smarkm * tty_setlinemod(on)	Turn on/off linemode.
41429088Smarkm * tty_isecho()		Find out if echoing is turned on.
41529088Smarkm * tty_setecho(on)	Enable/disable character echoing.
41629088Smarkm * tty_israw()		Find out if terminal is in RAW mode.
41729088Smarkm * tty_binaryin(on)	Turn on/off BINARY on input.
41829088Smarkm * tty_binaryout(on)	Turn on/off BINARY on output.
41929088Smarkm * tty_isediting()	Find out if line editing is enabled.
42029088Smarkm * tty_istrapsig()	Find out if signal trapping is enabled.
42129088Smarkm * tty_setedit(on)	Turn on/off line editing.
42229088Smarkm * tty_setsig(on)	Turn on/off signal trapping.
42329088Smarkm * tty_issofttab()	Find out if tab expansion is enabled.
42429088Smarkm * tty_setsofttab(on)	Turn on/off soft tab expansion.
42529088Smarkm * tty_islitecho()	Find out if typed control chars are echoed literally
42629088Smarkm * tty_setlitecho()	Turn on/off literal echo of control chars
42729088Smarkm * tty_tspeed(val)	Set transmit speed to val.
42829088Smarkm * tty_rspeed(val)	Set receive speed to val.
42929088Smarkm */
43029088Smarkm
43129088Smarkm
43287139Smarkmint
43387139Smarkmtty_linemode(void)
43429088Smarkm{
43529088Smarkm#ifndef	USE_TERMIO
43629088Smarkm	return(termbuf.state & TS_EXTPROC);
43729088Smarkm#else
43829088Smarkm	return(termbuf.c_lflag & EXTPROC);
43929088Smarkm#endif
44029088Smarkm}
44129088Smarkm
44287139Smarkmvoid
44387139Smarkmtty_setlinemode(int on)
44429088Smarkm{
44529088Smarkm#ifdef	TIOCEXT
44629088Smarkm	set_termbuf();
44729088Smarkm	(void) ioctl(pty, TIOCEXT, (char *)&on);
44829088Smarkm	init_termbuf();
44929088Smarkm#else	/* !TIOCEXT */
45029088Smarkm# ifdef	EXTPROC
45129088Smarkm	if (on)
45229088Smarkm		termbuf.c_lflag |= EXTPROC;
45329088Smarkm	else
45429088Smarkm		termbuf.c_lflag &= ~EXTPROC;
45529088Smarkm# endif
45629088Smarkm#endif	/* TIOCEXT */
45729088Smarkm}
45829088Smarkm#endif	/* LINEMODE */
45929088Smarkm
46087139Smarkmint
46187139Smarkmtty_isecho(void)
46229088Smarkm{
46329088Smarkm#ifndef USE_TERMIO
46429088Smarkm	return (termbuf.sg.sg_flags & ECHO);
46529088Smarkm#else
46629088Smarkm	return (termbuf.c_lflag & ECHO);
46729088Smarkm#endif
46829088Smarkm}
46929088Smarkm
47087139Smarkmint
47187139Smarkmtty_flowmode(void)
47229088Smarkm{
47329088Smarkm#ifndef USE_TERMIO
47429088Smarkm	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
47529088Smarkm#else
47629088Smarkm	return((termbuf.c_iflag & IXON) ? 1 : 0);
47729088Smarkm#endif
47829088Smarkm}
47929088Smarkm
48087139Smarkmint
48187139Smarkmtty_restartany(void)
48229088Smarkm{
48329088Smarkm#ifndef USE_TERMIO
48429088Smarkm# ifdef	DECCTQ
48529088Smarkm	return((termbuf.lflags & DECCTQ) ? 0 : 1);
48629088Smarkm# else
48729088Smarkm	return(-1);
48829088Smarkm# endif
48929088Smarkm#else
49029088Smarkm	return((termbuf.c_iflag & IXANY) ? 1 : 0);
49129088Smarkm#endif
49229088Smarkm}
49329088Smarkm
49487139Smarkmvoid
49587139Smarkmtty_setecho(int on)
49629088Smarkm{
49729088Smarkm#ifndef	USE_TERMIO
49829088Smarkm	if (on)
49929088Smarkm		termbuf.sg.sg_flags |= ECHO|CRMOD;
50029088Smarkm	else
50129088Smarkm		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
50229088Smarkm#else
50329088Smarkm	if (on)
50429088Smarkm		termbuf.c_lflag |= ECHO;
50529088Smarkm	else
50629088Smarkm		termbuf.c_lflag &= ~ECHO;
50729088Smarkm#endif
50829088Smarkm}
50929088Smarkm
51087139Smarkmint
51187139Smarkmtty_israw(void)
51229088Smarkm{
51329088Smarkm#ifndef USE_TERMIO
51429088Smarkm	return(termbuf.sg.sg_flags & RAW);
51529088Smarkm#else
51629088Smarkm	return(!(termbuf.c_lflag & ICANON));
51729088Smarkm#endif
51829088Smarkm}
51929088Smarkm
52087139Smarkm#ifdef	AUTHENTICATION
52187139Smarkm#if	defined(NO_LOGIN_F) && defined(LOGIN_R)
52287139Smarkmint
52387139Smarkmtty_setraw(int on)
52429088Smarkm{
52529088Smarkm#  ifndef USE_TERMIO
52629088Smarkm	if (on)
52729088Smarkm		termbuf.sg.sg_flags |= RAW;
52829088Smarkm	else
52929088Smarkm		termbuf.sg.sg_flags &= ~RAW;
53029088Smarkm#  else
53129088Smarkm	if (on)
53229088Smarkm		termbuf.c_lflag &= ~ICANON;
53329088Smarkm	else
53429088Smarkm		termbuf.c_lflag |= ICANON;
53529088Smarkm#  endif
53629088Smarkm}
53729088Smarkm#endif
53887139Smarkm#endif /* AUTHENTICATION */
53929088Smarkm
54087139Smarkmvoid
54187139Smarkmtty_binaryin(int on)
54229088Smarkm{
54329088Smarkm#ifndef	USE_TERMIO
54429088Smarkm	if (on)
54529088Smarkm		termbuf.lflags |= LPASS8;
54629088Smarkm	else
54729088Smarkm		termbuf.lflags &= ~LPASS8;
54829088Smarkm#else
54929088Smarkm	if (on) {
55029088Smarkm		termbuf.c_iflag &= ~ISTRIP;
55129088Smarkm	} else {
55229088Smarkm		termbuf.c_iflag |= ISTRIP;
55329088Smarkm	}
55429088Smarkm#endif
55529088Smarkm}
55629088Smarkm
55787139Smarkmvoid
55887139Smarkmtty_binaryout(int on)
55929088Smarkm{
56029088Smarkm#ifndef	USE_TERMIO
56129088Smarkm	if (on)
56229088Smarkm		termbuf.lflags |= LLITOUT;
56329088Smarkm	else
56429088Smarkm		termbuf.lflags &= ~LLITOUT;
56529088Smarkm#else
56629088Smarkm	if (on) {
56729088Smarkm		termbuf.c_cflag &= ~(CSIZE|PARENB);
56829088Smarkm		termbuf.c_cflag |= CS8;
56929088Smarkm		termbuf.c_oflag &= ~OPOST;
57029088Smarkm	} else {
57129088Smarkm		termbuf.c_cflag &= ~CSIZE;
57229088Smarkm		termbuf.c_cflag |= CS7|PARENB;
57329088Smarkm		termbuf.c_oflag |= OPOST;
57429088Smarkm	}
57529088Smarkm#endif
57629088Smarkm}
57729088Smarkm
57887139Smarkmint
57987139Smarkmtty_isbinaryin(void)
58029088Smarkm{
58129088Smarkm#ifndef	USE_TERMIO
58229088Smarkm	return(termbuf.lflags & LPASS8);
58329088Smarkm#else
58429088Smarkm	return(!(termbuf.c_iflag & ISTRIP));
58529088Smarkm#endif
58629088Smarkm}
58729088Smarkm
58887139Smarkmint
58987139Smarkmtty_isbinaryout(void)
59029088Smarkm{
59129088Smarkm#ifndef	USE_TERMIO
59229088Smarkm	return(termbuf.lflags & LLITOUT);
59329088Smarkm#else
59429088Smarkm	return(!(termbuf.c_oflag&OPOST));
59529088Smarkm#endif
59629088Smarkm}
59729088Smarkm
59829088Smarkm#ifdef	LINEMODE
59987139Smarkmint
60087139Smarkmtty_isediting(void)
60129088Smarkm{
60229088Smarkm#ifndef USE_TERMIO
60329088Smarkm	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
60429088Smarkm#else
60529088Smarkm	return(termbuf.c_lflag & ICANON);
60629088Smarkm#endif
60729088Smarkm}
60829088Smarkm
60987139Smarkmint
61087139Smarkmtty_istrapsig(void)
61129088Smarkm{
61229088Smarkm#ifndef USE_TERMIO
61329088Smarkm	return(!(termbuf.sg.sg_flags&RAW));
61429088Smarkm#else
61529088Smarkm	return(termbuf.c_lflag & ISIG);
61629088Smarkm#endif
61729088Smarkm}
61829088Smarkm
61987139Smarkmvoid
62087139Smarkmtty_setedit(int on)
62129088Smarkm{
62229088Smarkm#ifndef USE_TERMIO
62329088Smarkm	if (on)
62429088Smarkm		termbuf.sg.sg_flags &= ~CBREAK;
62529088Smarkm	else
62629088Smarkm		termbuf.sg.sg_flags |= CBREAK;
62729088Smarkm#else
62829088Smarkm	if (on)
62929088Smarkm		termbuf.c_lflag |= ICANON;
63029088Smarkm	else
63129088Smarkm		termbuf.c_lflag &= ~ICANON;
63229088Smarkm#endif
63329088Smarkm}
63429088Smarkm
63587139Smarkmvoid
63687139Smarkmtty_setsig(int on)
63729088Smarkm{
63829088Smarkm#ifndef	USE_TERMIO
63929088Smarkm	if (on)
64029088Smarkm		;
64129088Smarkm#else
64229088Smarkm	if (on)
64329088Smarkm		termbuf.c_lflag |= ISIG;
64429088Smarkm	else
64529088Smarkm		termbuf.c_lflag &= ~ISIG;
64629088Smarkm#endif
64729088Smarkm}
64829088Smarkm#endif	/* LINEMODE */
64929088Smarkm
65087139Smarkmint
65187139Smarkmtty_issofttab(void)
65229088Smarkm{
65329088Smarkm#ifndef	USE_TERMIO
65429088Smarkm	return (termbuf.sg.sg_flags & XTABS);
65529088Smarkm#else
65629088Smarkm# ifdef	OXTABS
65729088Smarkm	return (termbuf.c_oflag & OXTABS);
65829088Smarkm# endif
65929088Smarkm# ifdef	TABDLY
66029088Smarkm	return ((termbuf.c_oflag & TABDLY) == TAB3);
66129088Smarkm# endif
66229088Smarkm#endif
66329088Smarkm}
66429088Smarkm
66587139Smarkmvoid
66687139Smarkmtty_setsofttab(int on)
66729088Smarkm{
66829088Smarkm#ifndef	USE_TERMIO
66929088Smarkm	if (on)
67029088Smarkm		termbuf.sg.sg_flags |= XTABS;
67129088Smarkm	else
67229088Smarkm		termbuf.sg.sg_flags &= ~XTABS;
67329088Smarkm#else
67429088Smarkm	if (on) {
67529088Smarkm# ifdef	OXTABS
67629088Smarkm		termbuf.c_oflag |= OXTABS;
67729088Smarkm# endif
67829088Smarkm# ifdef	TABDLY
67929088Smarkm		termbuf.c_oflag &= ~TABDLY;
68029088Smarkm		termbuf.c_oflag |= TAB3;
68129088Smarkm# endif
68229088Smarkm	} else {
68329088Smarkm# ifdef	OXTABS
68429088Smarkm		termbuf.c_oflag &= ~OXTABS;
68529088Smarkm# endif
68629088Smarkm# ifdef	TABDLY
68729088Smarkm		termbuf.c_oflag &= ~TABDLY;
68829088Smarkm		termbuf.c_oflag |= TAB0;
68929088Smarkm# endif
69029088Smarkm	}
69129088Smarkm#endif
69229088Smarkm}
69329088Smarkm
69487139Smarkmint
69587139Smarkmtty_islitecho(void)
69629088Smarkm{
69729088Smarkm#ifndef	USE_TERMIO
69829088Smarkm	return (!(termbuf.lflags & LCTLECH));
69929088Smarkm#else
70029088Smarkm# ifdef	ECHOCTL
70129088Smarkm	return (!(termbuf.c_lflag & ECHOCTL));
70229088Smarkm# endif
70329088Smarkm# ifdef	TCTLECH
70429088Smarkm	return (!(termbuf.c_lflag & TCTLECH));
70529088Smarkm# endif
70629088Smarkm# if	!defined(ECHOCTL) && !defined(TCTLECH)
70729088Smarkm	return (0);	/* assumes ctl chars are echoed '^x' */
70829088Smarkm# endif
70929088Smarkm#endif
71029088Smarkm}
71129088Smarkm
71287139Smarkmvoid
71387139Smarkmtty_setlitecho(int on)
71429088Smarkm{
71529088Smarkm#ifndef	USE_TERMIO
71629088Smarkm	if (on)
71729088Smarkm		termbuf.lflags &= ~LCTLECH;
71829088Smarkm	else
71929088Smarkm		termbuf.lflags |= LCTLECH;
72029088Smarkm#else
72129088Smarkm# ifdef	ECHOCTL
72229088Smarkm	if (on)
72329088Smarkm		termbuf.c_lflag &= ~ECHOCTL;
72429088Smarkm	else
72529088Smarkm		termbuf.c_lflag |= ECHOCTL;
72629088Smarkm# endif
72729088Smarkm# ifdef	TCTLECH
72829088Smarkm	if (on)
72929088Smarkm		termbuf.c_lflag &= ~TCTLECH;
73029088Smarkm	else
73129088Smarkm		termbuf.c_lflag |= TCTLECH;
73229088Smarkm# endif
73329088Smarkm#endif
73429088Smarkm}
73529088Smarkm
73687139Smarkmint
73787139Smarkmtty_iscrnl(void)
73829088Smarkm{
73929088Smarkm#ifndef	USE_TERMIO
74029088Smarkm	return (termbuf.sg.sg_flags & CRMOD);
74129088Smarkm#else
74229088Smarkm	return (termbuf.c_iflag & ICRNL);
74329088Smarkm#endif
74429088Smarkm}
74529088Smarkm
74629088Smarkm/*
74729088Smarkm * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
74829088Smarkm */
74929088Smarkm#if B4800 != 4800
75029088Smarkm#define	DECODE_BAUD
75129088Smarkm#endif
75229088Smarkm
75329088Smarkm#ifdef	DECODE_BAUD
75429088Smarkm
75529088Smarkm/*
75629088Smarkm * A table of available terminal speeds
75729088Smarkm */
75829088Smarkmstruct termspeeds {
75929088Smarkm	int	speed;
76029088Smarkm	int	value;
76129088Smarkm} termspeeds[] = {
76229088Smarkm	{ 0,      B0 },      { 50,    B50 },    { 75,     B75 },
76329088Smarkm	{ 110,    B110 },    { 134,   B134 },   { 150,    B150 },
76429088Smarkm	{ 200,    B200 },    { 300,   B300 },   { 600,    B600 },
76529088Smarkm	{ 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
76629088Smarkm	{ 4800,   B4800 },
76729088Smarkm#ifdef	B7200
76829088Smarkm	{ 7200,  B7200 },
76929088Smarkm#endif
77029088Smarkm	{ 9600,   B9600 },
77129088Smarkm#ifdef	B14400
77229088Smarkm	{ 14400,  B14400 },
77329088Smarkm#endif
77429088Smarkm#ifdef	B19200
77529088Smarkm	{ 19200,  B19200 },
77629088Smarkm#endif
77729088Smarkm#ifdef	B28800
77829088Smarkm	{ 28800,  B28800 },
77929088Smarkm#endif
78029088Smarkm#ifdef	B38400
78129088Smarkm	{ 38400,  B38400 },
78229088Smarkm#endif
78329088Smarkm#ifdef	B57600
78429088Smarkm	{ 57600,  B57600 },
78529088Smarkm#endif
78629088Smarkm#ifdef	B115200
78729088Smarkm	{ 115200, B115200 },
78829088Smarkm#endif
78929088Smarkm#ifdef	B230400
79029088Smarkm	{ 230400, B230400 },
79129088Smarkm#endif
79229088Smarkm	{ -1,     0 }
79329088Smarkm};
79431622Scharnier#endif	/* DECODE_BAUD */
79529088Smarkm
79687139Smarkmvoid
79787139Smarkmtty_tspeed(int val)
79829088Smarkm{
79929088Smarkm#ifdef	DECODE_BAUD
80087139Smarkm	struct termspeeds *tp;
80129088Smarkm
80229088Smarkm	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
80329088Smarkm		;
80429088Smarkm	if (tp->speed == -1)	/* back up to last valid value */
80529088Smarkm		--tp;
80629088Smarkm	cfsetospeed(&termbuf, tp->value);
80731622Scharnier#else	/* DECODE_BAUD */
80829088Smarkm	cfsetospeed(&termbuf, val);
80931622Scharnier#endif	/* DECODE_BAUD */
81029088Smarkm}
81129088Smarkm
81287139Smarkmvoid
81387139Smarkmtty_rspeed(int val)
81429088Smarkm{
81529088Smarkm#ifdef	DECODE_BAUD
81687139Smarkm	struct termspeeds *tp;
81729088Smarkm
81829088Smarkm	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
81929088Smarkm		;
82029088Smarkm	if (tp->speed == -1)	/* back up to last valid value */
82129088Smarkm		--tp;
82229088Smarkm	cfsetispeed(&termbuf, tp->value);
82329088Smarkm#else	/* DECODE_BAUD */
82429088Smarkm	cfsetispeed(&termbuf, val);
82529088Smarkm#endif	/* DECODE_BAUD */
82629088Smarkm}
82729088Smarkm
82829088Smarkm/*
82929088Smarkm * getptyslave()
83029088Smarkm *
83129088Smarkm * Open the slave side of the pty, and do any initialization
83231622Scharnier * that is necessary.
83329088Smarkm */
83487139Smarkmstatic void
83587139Smarkmgetptyslave(void)
83629088Smarkm{
83787139Smarkm	int t = -1;
83829181Smarkm	char erase;
83929088Smarkm
84029088Smarkm# ifdef	LINEMODE
84129088Smarkm	int waslm;
84229088Smarkm# endif
84329088Smarkm# ifdef	TIOCGWINSZ
84429088Smarkm	struct winsize ws;
84529088Smarkm	extern int def_row, def_col;
84629088Smarkm# endif
84729088Smarkm	extern int def_tspeed, def_rspeed;
84829088Smarkm	/*
84929088Smarkm	 * Opening the slave side may cause initilization of the
85029088Smarkm	 * kernel tty structure.  We need remember the state of
85129088Smarkm	 * 	if linemode was turned on
85229088Smarkm	 *	terminal window size
85329088Smarkm	 *	terminal speed
85429181Smarkm	 *	erase character
85529088Smarkm	 * so that we can re-set them if we need to.
85629088Smarkm	 */
85729088Smarkm# ifdef	LINEMODE
85829088Smarkm	waslm = tty_linemode();
85929088Smarkm# endif
86029181Smarkm	erase = termbuf.c_cc[VERASE];
86129088Smarkm
86229088Smarkm	/*
86329088Smarkm	 * Make sure that we don't have a controlling tty, and
86429088Smarkm	 * that we are the session (process group) leader.
86529088Smarkm	 */
86629088Smarkm# ifdef	TIOCNOTTY
86729088Smarkm	t = open(_PATH_TTY, O_RDWR);
86829088Smarkm	if (t >= 0) {
86929088Smarkm		(void) ioctl(t, TIOCNOTTY, (char *)0);
87029088Smarkm		(void) close(t);
87129088Smarkm	}
87229088Smarkm# endif
87329088Smarkm
87429088Smarkm	t = cleanopen(line);
87529088Smarkm	if (t < 0)
87629088Smarkm		fatalperror(net, line);
87729088Smarkm
87829088Smarkm
87929088Smarkm	/*
88029088Smarkm	 * set up the tty modes as we like them to be.
88129088Smarkm	 */
88229088Smarkm	init_termbuf();
88329088Smarkm# ifdef	TIOCGWINSZ
88429088Smarkm	if (def_row || def_col) {
88529088Smarkm		memset((char *)&ws, 0, sizeof(ws));
88629088Smarkm		ws.ws_col = def_col;
88729088Smarkm		ws.ws_row = def_row;
88829088Smarkm		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
88929088Smarkm	}
89029088Smarkm# endif
89129088Smarkm
89229088Smarkm	/*
89329088Smarkm	 * Settings for sgtty based systems
89429088Smarkm	 */
89529088Smarkm# ifndef	USE_TERMIO
89629088Smarkm	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
89729088Smarkm# endif	/* USE_TERMIO */
89829088Smarkm
89929088Smarkm	/*
90029088Smarkm	 * Settings for all other termios/termio based
90129088Smarkm	 * systems, other than 4.4BSD.  In 4.4BSD the
90229088Smarkm	 * kernel does the initial terminal setup.
90329088Smarkm	 */
90429088Smarkm	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
90529088Smarkm	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
90629181Smarkm	if (erase)
90729181Smarkm		termbuf.c_cc[VERASE] = erase;
90829088Smarkm# ifdef	LINEMODE
90929088Smarkm	if (waslm)
91029088Smarkm		tty_setlinemode(1);
91129088Smarkm# endif	/* LINEMODE */
91229088Smarkm
91329088Smarkm	/*
91429088Smarkm	 * Set the tty modes, and make this our controlling tty.
91529088Smarkm	 */
91629088Smarkm	set_termbuf();
91729088Smarkm	if (login_tty(t) == -1)
91829088Smarkm		fatalperror(net, "login_tty");
91929088Smarkm	if (net > 2)
92029088Smarkm		(void) close(net);
92187139Smarkm#ifdef	AUTHENTICATION
92287139Smarkm#if	defined(NO_LOGIN_F) && defined(LOGIN_R)
92329088Smarkm	/*
92429088Smarkm	 * Leave the pty open so that we can write out the rlogin
92529088Smarkm	 * protocol for /bin/login, if the authentication works.
92629088Smarkm	 */
92729088Smarkm#else
92829088Smarkm	if (pty > 2) {
92929088Smarkm		(void) close(pty);
93029088Smarkm		pty = -1;
93129088Smarkm	}
93229088Smarkm#endif
93387139Smarkm#endif /* AUTHENTICATION */
93429088Smarkm}
93529088Smarkm
93629088Smarkm#ifndef	O_NOCTTY
93729088Smarkm#define	O_NOCTTY	0
93829088Smarkm#endif
93929088Smarkm/*
94029088Smarkm * Open the specified slave side of the pty,
94129088Smarkm * making sure that we have a clean tty.
94229088Smarkm */
94387139Smarkmint
94487139Smarkmcleanopen(char *li)
94529088Smarkm{
94687139Smarkm	int t;
94729088Smarkm
94829088Smarkm	/*
94929088Smarkm	 * Make sure that other people can't open the
95029088Smarkm	 * slave side of the connection.
95129088Smarkm	 */
95287139Smarkm	(void) chown(li, 0, 0);
95387139Smarkm	(void) chmod(li, 0600);
95429088Smarkm
95587139Smarkm	(void) revoke(li);
95629088Smarkm
95729088Smarkm	t = open(line, O_RDWR|O_NOCTTY);
95829088Smarkm
95929088Smarkm	if (t < 0)
96029088Smarkm		return(-1);
96129088Smarkm
96229088Smarkm	return(t);
96329088Smarkm}
96429088Smarkm
96529088Smarkm/*
96629088Smarkm * startslave(host)
96729088Smarkm *
96829088Smarkm * Given a hostname, do whatever
96929088Smarkm * is necessary to startup the login process on the slave side of the pty.
97029088Smarkm */
97129088Smarkm
97229088Smarkm/* ARGSUSED */
97387139Smarkmvoid
97487139Smarkmstartslave(char *host, int autologin, char *autoname)
97529088Smarkm{
97687139Smarkm	int i;
97729088Smarkm
97887139Smarkm#ifdef	AUTHENTICATION
97929088Smarkm	if (!autoname || !autoname[0])
98029088Smarkm		autologin = 0;
98129088Smarkm
98229088Smarkm	if (autologin < auth_level) {
98329088Smarkm		fatal(net, "Authorization failed");
98429088Smarkm		exit(1);
98529088Smarkm	}
98629088Smarkm#endif
98729088Smarkm
98829088Smarkm
98929088Smarkm	if ((i = fork()) < 0)
99029088Smarkm		fatalperror(net, "fork");
99129088Smarkm	if (i) {
99229088Smarkm	} else {
99387139Smarkm		getptyslave();
99429088Smarkm		start_login(host, autologin, autoname);
99529088Smarkm		/*NOTREACHED*/
99629088Smarkm	}
99729088Smarkm}
99829088Smarkm
99987139Smarkmvoid
100087139Smarkminit_env(void)
100129088Smarkm{
100229088Smarkm	char **envp;
100329088Smarkm
100429088Smarkm	envp = envinit;
100529181Smarkm	if ((*envp = getenv("TZ")))
100629088Smarkm		*envp++ -= 3;
100729088Smarkm	*envp = 0;
100829088Smarkm	environ = envinit;
100929088Smarkm}
101029088Smarkm
101129088Smarkm
101229088Smarkm/*
101329088Smarkm * start_login(host)
101429088Smarkm *
101529088Smarkm * Assuming that we are now running as a child processes, this
101629088Smarkm * function will turn us into the login process.
101729088Smarkm */
101829088Smarkm
101987139Smarkm#ifndef AUTHENTICATION
102087139Smarkm#define undef1 __unused
102187139Smarkm#else
102287139Smarkm#define undef1
102329088Smarkm#endif
102429088Smarkm
102587139Smarkmvoid
102687139Smarkmstart_login(char *host undef1, int autologin undef1, char *name undef1)
102787139Smarkm{
102887139Smarkm	char **argv;
102929088Smarkm
103029088Smarkm	scrub_env();
103129088Smarkm
103229088Smarkm	/*
103329088Smarkm	 * -h : pass on name of host.
103429088Smarkm	 *		WARNING:  -h is accepted by login if and only if
103529088Smarkm	 *			getuid() == 0.
103629088Smarkm	 * -p : don't clobber the environment (so terminal type stays set).
103729088Smarkm	 *
103829088Smarkm	 * -f : force this login, he has already been authenticated
103929088Smarkm	 */
104029088Smarkm	argv = addarg(0, "login");
104129088Smarkm
104229088Smarkm#if	!defined(NO_LOGIN_H)
104387139Smarkm#ifdef	AUTHENTICATION
104487139Smarkm# if	defined(NO_LOGIN_F) && defined(LOGIN_R)
104529088Smarkm	/*
104629088Smarkm	 * Don't add the "-h host" option if we are going
104729088Smarkm	 * to be adding the "-r host" option down below...
104829088Smarkm	 */
104929088Smarkm	if ((auth_level < 0) || (autologin != AUTH_VALID))
105029088Smarkm# endif
105129088Smarkm	{
105229088Smarkm		argv = addarg(argv, "-h");
105329088Smarkm		argv = addarg(argv, host);
105429088Smarkm	}
105587139Smarkm#endif /* AUTHENTICATION */
105629088Smarkm#endif
105729088Smarkm#if	!defined(NO_LOGIN_P)
105829088Smarkm	argv = addarg(argv, "-p");
105929088Smarkm#endif
106029088Smarkm#ifdef	LINEMODE
106129088Smarkm	/*
106229088Smarkm	 * Set the environment variable "LINEMODE" to either
106329088Smarkm	 * "real" or "kludge" if we are operating in either
106429088Smarkm	 * real or kludge linemode.
106529088Smarkm	 */
106629088Smarkm	if (lmodetype == REAL_LINEMODE)
106729088Smarkm		setenv("LINEMODE", "real", 1);
106829088Smarkm# ifdef KLUDGELINEMODE
106929088Smarkm	else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
107029088Smarkm		setenv("LINEMODE", "kludge", 1);
107129088Smarkm# endif
107229088Smarkm#endif
107329088Smarkm#ifdef	BFTPDAEMON
107429088Smarkm	/*
107529088Smarkm	 * Are we working as the bftp daemon?  If so, then ask login
107629088Smarkm	 * to start bftp instead of shell.
107729088Smarkm	 */
107829088Smarkm	if (bftpd) {
107929088Smarkm		argv = addarg(argv, "-e");
108029088Smarkm		argv = addarg(argv, BFTPPATH);
108129088Smarkm	} else
108229088Smarkm#endif
108387139Smarkm#ifdef	AUTHENTICATION
108429088Smarkm	if (auth_level >= 0 && autologin == AUTH_VALID) {
108529088Smarkm# if	!defined(NO_LOGIN_F)
108629088Smarkm		argv = addarg(argv, "-f");
108729181Smarkm		argv = addarg(argv, "--");
108829088Smarkm		argv = addarg(argv, name);
108929088Smarkm# else
109029088Smarkm#  if defined(LOGIN_R)
109129088Smarkm		/*
109229088Smarkm		 * We don't have support for "login -f", but we
109329088Smarkm		 * can fool /bin/login into thinking that we are
109429088Smarkm		 * rlogind, and allow us to log in without a
109529088Smarkm		 * password.  The rlogin protocol expects
109629088Smarkm		 *	local-user\0remote-user\0term/speed\0
109729088Smarkm		 */
109829088Smarkm
109929088Smarkm		if (pty > 2) {
110087139Smarkm			char *cp;
110129088Smarkm			char speed[128];
110229088Smarkm			int isecho, israw, xpty, len;
110329088Smarkm			extern int def_rspeed;
110429088Smarkm#  ifndef LOGIN_HOST
110529088Smarkm			/*
110629088Smarkm			 * Tell login that we are coming from "localhost".
110729088Smarkm			 * If we passed in the real host name, then the
110829088Smarkm			 * user would have to allow .rhost access from
110929088Smarkm			 * every machine that they want authenticated
111029088Smarkm			 * access to work from, which sort of defeats
111129088Smarkm			 * the purpose of an authenticated login...
111229088Smarkm			 * So, we tell login that the session is coming
111329088Smarkm			 * from "localhost", and the user will only have
111429088Smarkm			 * to have "localhost" in their .rhost file.
111529088Smarkm			 */
111629088Smarkm#			define LOGIN_HOST "localhost"
111729088Smarkm#  endif
111829088Smarkm			argv = addarg(argv, "-r");
111929088Smarkm			argv = addarg(argv, LOGIN_HOST);
112029088Smarkm
112129088Smarkm			xpty = pty;
112229088Smarkm			pty = 0;
112329088Smarkm			init_termbuf();
112429088Smarkm			isecho = tty_isecho();
112529088Smarkm			israw = tty_israw();
112629088Smarkm			if (isecho || !israw) {
112729088Smarkm				tty_setecho(0);		/* Turn off echo */
112829088Smarkm				tty_setraw(1);		/* Turn on raw */
112929088Smarkm				set_termbuf();
113029088Smarkm			}
113129088Smarkm			len = strlen(name)+1;
113229088Smarkm			write(xpty, name, len);
113329088Smarkm			write(xpty, name, len);
113432688Simp			snprintf(speed, sizeof(speed),
113532688Simp				"%s/%d", (cp = getenv("TERM")) ? cp : "",
113629088Smarkm				(def_rspeed > 0) ? def_rspeed : 9600);
113729088Smarkm			len = strlen(speed)+1;
113829088Smarkm			write(xpty, speed, len);
113929088Smarkm
114029088Smarkm			if (isecho || !israw) {
114129088Smarkm				init_termbuf();
114229088Smarkm				tty_setecho(isecho);
114329088Smarkm				tty_setraw(israw);
114429088Smarkm				set_termbuf();
114529088Smarkm				if (!israw) {
114629088Smarkm					/*
114729088Smarkm					 * Write a newline to ensure
114829088Smarkm					 * that login will be able to
114929088Smarkm					 * read the line...
115029088Smarkm					 */
115129088Smarkm					write(xpty, "\n", 1);
115229088Smarkm				}
115329088Smarkm			}
115429088Smarkm			pty = xpty;
115529088Smarkm		}
115629088Smarkm#  else
115729181Smarkm		argv = addarg(argv, "--");
115829088Smarkm		argv = addarg(argv, name);
115929088Smarkm#  endif
116029088Smarkm# endif
116129088Smarkm	} else
116229088Smarkm#endif
116329088Smarkm	if (getenv("USER")) {
116429181Smarkm 		argv = addarg(argv, "--");
116529088Smarkm		argv = addarg(argv, getenv("USER"));
116629088Smarkm#if	defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
116729088Smarkm		{
116887139Smarkm			char **cpp;
116929088Smarkm			for (cpp = environ; *cpp; cpp++)
117029088Smarkm				argv = addarg(argv, *cpp);
117129088Smarkm		}
117229088Smarkm#endif
117329088Smarkm		/*
117429088Smarkm		 * Assume that login will set the USER variable
117529088Smarkm		 * correctly.  For SysV systems, this means that
117629088Smarkm		 * USER will no longer be set, just LOGNAME by
117729088Smarkm		 * login.  (The problem is that if the auto-login
117829088Smarkm		 * fails, and the user then specifies a different
117929088Smarkm		 * account name, he can get logged in with both
118029088Smarkm		 * LOGNAME and USER in his environment, but the
118129088Smarkm		 * USER value will be wrong.
118229088Smarkm		 */
118329088Smarkm		unsetenv("USER");
118429088Smarkm	}
118587139Smarkm#ifdef	AUTHENTICATION
118687139Smarkm#if	defined(NO_LOGIN_F) && defined(LOGIN_R)
118729088Smarkm	if (pty > 2)
118829088Smarkm		close(pty);
118929088Smarkm#endif
119087139Smarkm#endif /* AUTHENTICATION */
119129088Smarkm	closelog();
119229088Smarkm
119329181Smarkm	if (altlogin == NULL) {
119429181Smarkm		altlogin = _PATH_LOGIN;
119529181Smarkm	}
119629181Smarkm	execv(altlogin, argv);
119729181Smarkm
119831622Scharnier	syslog(LOG_ERR, "%s: %m", altlogin);
119929181Smarkm	fatalperror(net, altlogin);
120029088Smarkm	/*NOTREACHED*/
120129088Smarkm}
120229088Smarkm
120387139Smarkmstatic char **
120487139Smarkmaddarg(char **argv, const char *val)
120529088Smarkm{
120687139Smarkm	char **cpp;
120729088Smarkm
120829088Smarkm	if (argv == NULL) {
120929088Smarkm		/*
121029088Smarkm		 * 10 entries, a leading length, and a null
121129088Smarkm		 */
121229088Smarkm		argv = (char **)malloc(sizeof(*argv) * 12);
121329088Smarkm		if (argv == NULL)
1214309637Sglebius			fatal(net, "failure allocating argument space");
121529088Smarkm		*argv++ = (char *)10;
121629088Smarkm		*argv = (char *)0;
121729088Smarkm	}
121829088Smarkm	for (cpp = argv; *cpp; cpp++)
121929088Smarkm		;
122087267Smarkm	if (cpp == &argv[(long)argv[-1]]) {
122129088Smarkm		--argv;
122287267Smarkm		*argv = (char *)((long)(*argv) + 10);
122387267Smarkm		argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2));
122429088Smarkm		if (argv == NULL)
1225309637Sglebius			fatal(net, "failure allocating argument space");
122629088Smarkm		argv++;
122787267Smarkm		cpp = &argv[(long)argv[-1] - 10];
122829088Smarkm	}
1229309637Sglebius	if ((*cpp++ = strdup(val)) == NULL)
1230309637Sglebius		fatal(net, "failure allocating argument space");
123129088Smarkm	*cpp = 0;
123229088Smarkm	return(argv);
123329088Smarkm}
123429088Smarkm
123529088Smarkm/*
123629088Smarkm * scrub_env()
123729088Smarkm *
123869825Sassar * We only accept the environment variables listed below.
123929088Smarkm */
124087139Smarkmvoid
124187139Smarkmscrub_env(void)
124229088Smarkm{
124387139Smarkm	static const char *rej[] = {
124469825Sassar		"TERMCAP=/",
124569825Sassar		NULL
124669825Sassar	};
124729088Smarkm
124887139Smarkm	static const char *acc[] = {
124969825Sassar		"XAUTH=", "XAUTHORITY=", "DISPLAY=",
125069825Sassar		"TERM=",
125169825Sassar		"EDITOR=",
125269825Sassar		"PAGER=",
125369825Sassar		"LOGNAME=",
125469825Sassar		"POSIXLY_CORRECT=",
125569825Sassar		"PRINTER=",
125669825Sassar		NULL
125769825Sassar	};
125869825Sassar
125969825Sassar	char **cpp, **cpp2;
126069825Sassar	const char **p;
1261188699Scperciva	char ** new_environ;
1262188699Scperciva	size_t count;
1263188699Scperciva
1264188699Scperciva	/* Allocate space for scrubbed environment. */
1265188699Scperciva	for (count = 1, cpp = environ; *cpp; count++, cpp++)
1266188699Scperciva		continue;
1267188699Scperciva	if ((new_environ = malloc(count * sizeof(char *))) == NULL) {
1268188699Scperciva		environ = NULL;
1269188699Scperciva		return;
1270188699Scperciva	}
1271188699Scperciva
1272188699Scperciva 	for (cpp2 = new_environ, cpp = environ; *cpp; cpp++) {
127369825Sassar		int reject_it = 0;
127469825Sassar
127587139Smarkm		for(p = rej; *p; p++)
127669825Sassar			if(strncmp(*cpp, *p, strlen(*p)) == 0) {
127769825Sassar				reject_it = 1;
127869825Sassar				break;
127969825Sassar			}
128069825Sassar		if (reject_it)
128169825Sassar			continue;
128269825Sassar
128387139Smarkm		for(p = acc; *p; p++)
128469825Sassar			if(strncmp(*cpp, *p, strlen(*p)) == 0)
128569825Sassar				break;
1286188699Scperciva		if(*p != NULL) {
1287188699Scperciva			if ((*cpp2++ = strdup(*cpp)) == NULL) {
1288188699Scperciva				environ = new_environ;
1289188699Scperciva				return;
1290188699Scperciva			}
1291188699Scperciva		}
129269825Sassar 	}
129369825Sassar	*cpp2 = NULL;
1294188699Scperciva	environ = new_environ;
129529088Smarkm}
129629088Smarkm
129729088Smarkm/*
129829088Smarkm * cleanup()
129929088Smarkm *
130029088Smarkm * This is the routine to call when we are all through, to
130129088Smarkm * clean up anything that needs to be cleaned up.
130229088Smarkm */
130387139Smarkm/* ARGSUSED */
130487139Smarkmvoid
130587139Smarkmcleanup(int sig __unused)
130629088Smarkm{
130729088Smarkm
1308202212Sed	(void) shutdown(net, SHUT_RDWR);
130990242Ssheldonh	_exit(1);
131029088Smarkm}
1311