sys_term.c revision 69825
129088Smarkm/*
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
3429088Smarkm#ifndef lint
3531622Scharnier#if 0
3629181Smarkmstatic const char sccsid[] = "@(#)sys_term.c	8.4+1 (Berkeley) 5/30/95";
3731622Scharnier#endif
3831622Scharnierstatic const char rcsid[] =
3950479Speter  "$FreeBSD: head/contrib/telnet/telnetd/sys_term.c 69825 2000-12-10 20:50:20Z assar $";
4029088Smarkm#endif /* not lint */
4129088Smarkm
4229088Smarkm#include "telnetd.h"
4329088Smarkm#include "pathnames.h"
4429088Smarkm
4529088Smarkm#if	defined(AUTHENTICATION)
4629088Smarkm#include <libtelnet/auth.h>
4729088Smarkm#endif
4829088Smarkm
4929181Smarkmextern char *altlogin;
5029181Smarkmint cleanopen(char *line);
5129181Smarkmvoid scrub_env(void);
5229181Smarkm
5329088Smarkm#if defined(CRAY) || defined(__hpux)
5429088Smarkm# define PARENT_DOES_UTMP
5529088Smarkm#endif
5629088Smarkm
5729088Smarkm#ifdef	NEWINIT
5829088Smarkm#include <initreq.h>
5929088Smarkm#else	/* NEWINIT*/
6029088Smarkm# ifdef	UTMPX
6129088Smarkm# include <utmpx.h>
6229088Smarkmstruct	utmpx wtmp;
6329088Smarkm# else
6429088Smarkm# include <utmp.h>
6529088Smarkmstruct	utmp wtmp;
6629088Smarkm# endif /* UTMPX */
6729088Smarkm
6829088Smarkm# ifndef PARENT_DOES_UTMP
6929181Smarkm#ifdef _PATH_WTMP
7029181Smarkmchar    wtmpf[] = _PATH_WTMP;
7129181Smarkm#else
7229088Smarkmchar	wtmpf[]	= "/usr/adm/wtmp";
7329181Smarkm#endif
7429181Smarkm#ifdef _PATH_UTMP
7529181Smarkmchar    utmpf[] = _PATH_UTMP;
7629181Smarkm#else
7729088Smarkmchar	utmpf[] = "/etc/utmp";
7829181Smarkm#endif
7929088Smarkm# else /* PARENT_DOES_UTMP */
8029088Smarkmchar	wtmpf[]	= "/etc/wtmp";
8129088Smarkm# endif /* PARENT_DOES_UTMP */
8229088Smarkm
8329181Smarkm#include <libutil.h>
8429181Smarkm
8529088Smarkm# ifdef CRAY
8629088Smarkm#include <tmpdir.h>
8729088Smarkm#include <sys/wait.h>
8829088Smarkm#  if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
8929088Smarkm#   define UNICOS7x
9029088Smarkm#  endif
9129088Smarkm
9229088Smarkm#  ifdef UNICOS7x
9329088Smarkm#include <sys/sysv.h>
9429088Smarkm#include <sys/secstat.h>
9529088Smarkmextern int secflag;
9629088Smarkmextern struct sysv sysv;
9729088Smarkm#  endif /* UNICOS7x */
9829088Smarkm# endif	/* CRAY */
9929088Smarkm#endif	/* NEWINIT */
10029088Smarkm
10129088Smarkm#ifdef	STREAMSPTY
10229088Smarkm#include <sac.h>
10329088Smarkm#include <sys/stropts.h>
10429088Smarkm#endif
10529088Smarkm
10629088Smarkm#define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
10729088Smarkm#define SCMPN(a, b)	strncmp(a, b, sizeof(a))
10829088Smarkm
10929088Smarkm#ifdef	STREAMS
11029088Smarkm#include <sys/stream.h>
11129088Smarkm#endif
11229088Smarkm#ifdef __hpux
11329088Smarkm#include <sys/resource.h>
11429088Smarkm#include <sys/proc.h>
11529088Smarkm#endif
11629088Smarkm#include <sys/tty.h>
11729088Smarkm#ifdef	t_erase
11829088Smarkm#undef	t_erase
11929088Smarkm#undef	t_kill
12029088Smarkm#undef	t_intrc
12129088Smarkm#undef	t_quitc
12229088Smarkm#undef	t_startc
12329088Smarkm#undef	t_stopc
12429088Smarkm#undef	t_eofc
12529088Smarkm#undef	t_brkc
12629088Smarkm#undef	t_suspc
12729088Smarkm#undef	t_dsuspc
12829088Smarkm#undef	t_rprntc
12929088Smarkm#undef	t_flushc
13029088Smarkm#undef	t_werasc
13129088Smarkm#undef	t_lnextc
13229088Smarkm#endif
13329088Smarkm
13429088Smarkm#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
13529088Smarkm# define EXTPROC 0400
13629088Smarkm#endif
13729088Smarkm
13829088Smarkm#ifndef	USE_TERMIO
13929088Smarkmstruct termbuf {
14029088Smarkm	struct sgttyb sg;
14129088Smarkm	struct tchars tc;
14229088Smarkm	struct ltchars ltc;
14329088Smarkm	int state;
14429088Smarkm	int lflags;
14529088Smarkm} termbuf, termbuf2;
14629088Smarkm# define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
14729088Smarkm# define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
14829088Smarkm# define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
14929088Smarkm# define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
15029088Smarkm#else	/* USE_TERMIO */
15129088Smarkm# ifdef	SYSV_TERMIO
15229088Smarkm#	define termios termio
15329088Smarkm# endif
15429088Smarkm# ifndef	TCSANOW
15529088Smarkm#  ifdef TCSETS
15629088Smarkm#   define	TCSANOW		TCSETS
15729088Smarkm#   define	TCSADRAIN	TCSETSW
15829088Smarkm#   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
15929088Smarkm#  else
16029088Smarkm#   ifdef TCSETA
16129088Smarkm#    define	TCSANOW		TCSETA
16229088Smarkm#    define	TCSADRAIN	TCSETAW
16329088Smarkm#    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
16429088Smarkm#   else
16529088Smarkm#    define	TCSANOW		TIOCSETA
16629088Smarkm#    define	TCSADRAIN	TIOCSETAW
16729088Smarkm#    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
16829088Smarkm#   endif
16929088Smarkm#  endif
17029088Smarkm#  define	tcsetattr(f, a, t)	ioctl(f, a, t)
17129088Smarkm#  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
17229088Smarkm					(tp)->c_cflag |= (val)
17329088Smarkm#  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
17429088Smarkm#  ifdef CIBAUD
17529088Smarkm#   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
17629088Smarkm					(tp)->c_cflag |= ((val)<<IBSHIFT)
17729088Smarkm#   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
17829088Smarkm#  else
17929088Smarkm#   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
18029088Smarkm					(tp)->c_cflag |= (val)
18129088Smarkm#   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
18229088Smarkm#  endif
18329088Smarkm# endif /* TCSANOW */
18429088Smarkmstruct termios termbuf, termbuf2;	/* pty control structure */
18529088Smarkm# ifdef  STREAMSPTY
18629088Smarkmint ttyfd = -1;
18729088Smarkm# endif
18829088Smarkm#endif	/* USE_TERMIO */
18929088Smarkm
19031622Scharnier#include <sys/types.h>
19131622Scharnier#include <libutil.h>
19231622Scharnier
19331622Scharnierint cleanopen __P((char *));
19431622Scharniervoid scrub_env __P((void));
19531622Scharnier
19629088Smarkm/*
19729088Smarkm * init_termbuf()
19829088Smarkm * copy_termbuf(cp)
19929088Smarkm * set_termbuf()
20029088Smarkm *
20129088Smarkm * These three routines are used to get and set the "termbuf" structure
20229088Smarkm * to and from the kernel.  init_termbuf() gets the current settings.
20329088Smarkm * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
20429088Smarkm * set_termbuf() writes the structure into the kernel.
20529088Smarkm */
20629088Smarkm
20729088Smarkm	void
20829088Smarkminit_termbuf()
20929088Smarkm{
21029088Smarkm#ifndef	USE_TERMIO
21129088Smarkm	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
21229088Smarkm	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
21329088Smarkm	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
21429088Smarkm# ifdef	TIOCGSTATE
21529088Smarkm	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
21629088Smarkm# endif
21729088Smarkm#else
21829088Smarkm# ifdef  STREAMSPTY
21929088Smarkm	(void) tcgetattr(ttyfd, &termbuf);
22029088Smarkm# else
22129088Smarkm	(void) tcgetattr(pty, &termbuf);
22229088Smarkm# endif
22329088Smarkm#endif
22429088Smarkm	termbuf2 = termbuf;
22529088Smarkm}
22629088Smarkm
22729088Smarkm#if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
22829088Smarkm	void
22929088Smarkmcopy_termbuf(cp, len)
23029088Smarkm	char *cp;
23129088Smarkm	int len;
23229088Smarkm{
23329088Smarkm	if (len > sizeof(termbuf))
23429088Smarkm		len = sizeof(termbuf);
23529088Smarkm	memmove((char *)&termbuf, cp, len);
23629088Smarkm	termbuf2 = termbuf;
23729088Smarkm}
23829088Smarkm#endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
23929088Smarkm
24029088Smarkm	void
24129088Smarkmset_termbuf()
24229088Smarkm{
24329088Smarkm	/*
24429088Smarkm	 * Only make the necessary changes.
24529088Smarkm	 */
24629088Smarkm#ifndef	USE_TERMIO
24729088Smarkm	if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
24829088Smarkm							sizeof(termbuf.sg)))
24929088Smarkm		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
25029088Smarkm	if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
25129088Smarkm							sizeof(termbuf.tc)))
25229088Smarkm		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
25329088Smarkm	if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
25429088Smarkm							sizeof(termbuf.ltc)))
25529088Smarkm		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
25629088Smarkm	if (termbuf.lflags != termbuf2.lflags)
25729088Smarkm		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
25829088Smarkm#else	/* USE_TERMIO */
25929088Smarkm	if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
26029088Smarkm# ifdef  STREAMSPTY
26129088Smarkm		(void) tcsetattr(ttyfd, TCSANOW, &termbuf);
26229088Smarkm# else
26329088Smarkm		(void) tcsetattr(pty, TCSANOW, &termbuf);
26429088Smarkm# endif
26529088Smarkm# if	defined(CRAY2) && defined(UNICOS5)
26629088Smarkm	needtermstat = 1;
26729088Smarkm# endif
26829088Smarkm#endif	/* USE_TERMIO */
26929088Smarkm}
27029088Smarkm
27129088Smarkm
27229088Smarkm/*
27329088Smarkm * spcset(func, valp, valpp)
27429088Smarkm *
27529088Smarkm * This function takes various special characters (func), and
27629088Smarkm * sets *valp to the current value of that character, and
27729088Smarkm * *valpp to point to where in the "termbuf" structure that
27829088Smarkm * value is kept.
27929088Smarkm *
28029088Smarkm * It returns the SLC_ level of support for this function.
28129088Smarkm */
28229088Smarkm
28329088Smarkm#ifndef	USE_TERMIO
28429088Smarkm	int
28529088Smarkmspcset(func, valp, valpp)
28629088Smarkm	int func;
28729088Smarkm	cc_t *valp;
28829088Smarkm	cc_t **valpp;
28929088Smarkm{
29029088Smarkm	switch(func) {
29129088Smarkm	case SLC_EOF:
29229088Smarkm		*valp = termbuf.tc.t_eofc;
29329088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_eofc;
29429088Smarkm		return(SLC_VARIABLE);
29529088Smarkm	case SLC_EC:
29629088Smarkm		*valp = termbuf.sg.sg_erase;
29729088Smarkm		*valpp = (cc_t *)&termbuf.sg.sg_erase;
29829088Smarkm		return(SLC_VARIABLE);
29929088Smarkm	case SLC_EL:
30029088Smarkm		*valp = termbuf.sg.sg_kill;
30129088Smarkm		*valpp = (cc_t *)&termbuf.sg.sg_kill;
30229088Smarkm		return(SLC_VARIABLE);
30329088Smarkm	case SLC_IP:
30429088Smarkm		*valp = termbuf.tc.t_intrc;
30529088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_intrc;
30629088Smarkm		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
30729088Smarkm	case SLC_ABORT:
30829088Smarkm		*valp = termbuf.tc.t_quitc;
30929088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_quitc;
31029088Smarkm		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
31129088Smarkm	case SLC_XON:
31229088Smarkm		*valp = termbuf.tc.t_startc;
31329088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_startc;
31429088Smarkm		return(SLC_VARIABLE);
31529088Smarkm	case SLC_XOFF:
31629088Smarkm		*valp = termbuf.tc.t_stopc;
31729088Smarkm		*valpp = (cc_t *)&termbuf.tc.t_stopc;
31829088Smarkm		return(SLC_VARIABLE);
31929088Smarkm	case SLC_AO:
32029088Smarkm		*valp = termbuf.ltc.t_flushc;
32129088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
32229088Smarkm		return(SLC_VARIABLE);
32329088Smarkm	case SLC_SUSP:
32429088Smarkm		*valp = termbuf.ltc.t_suspc;
32529088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
32629088Smarkm		return(SLC_VARIABLE);
32729088Smarkm	case SLC_EW:
32829088Smarkm		*valp = termbuf.ltc.t_werasc;
32929088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
33029088Smarkm		return(SLC_VARIABLE);
33129088Smarkm	case SLC_RP:
33229088Smarkm		*valp = termbuf.ltc.t_rprntc;
33329088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
33429088Smarkm		return(SLC_VARIABLE);
33529088Smarkm	case SLC_LNEXT:
33629088Smarkm		*valp = termbuf.ltc.t_lnextc;
33729088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
33829088Smarkm		return(SLC_VARIABLE);
33929088Smarkm	case SLC_FORW1:
34029088Smarkm		*valp = termbuf.tc.t_brkc;
34129088Smarkm		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
34229088Smarkm		return(SLC_VARIABLE);
34329088Smarkm	case SLC_BRK:
34429088Smarkm	case SLC_SYNCH:
34529088Smarkm	case SLC_AYT:
34629088Smarkm	case SLC_EOR:
34729088Smarkm		*valp = (cc_t)0;
34829088Smarkm		*valpp = (cc_t *)0;
34929088Smarkm		return(SLC_DEFAULT);
35029088Smarkm	default:
35129088Smarkm		*valp = (cc_t)0;
35229088Smarkm		*valpp = (cc_t *)0;
35329088Smarkm		return(SLC_NOSUPPORT);
35429088Smarkm	}
35529088Smarkm}
35629088Smarkm
35729088Smarkm#else	/* USE_TERMIO */
35829088Smarkm
35929088Smarkm	int
36029088Smarkmspcset(func, valp, valpp)
36129088Smarkm	int func;
36229088Smarkm	cc_t *valp;
36329088Smarkm	cc_t **valpp;
36429088Smarkm{
36529088Smarkm
36629088Smarkm#define	setval(a, b)	*valp = termbuf.c_cc[a]; \
36729088Smarkm			*valpp = &termbuf.c_cc[a]; \
36829088Smarkm			return(b);
36929088Smarkm#define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
37029088Smarkm
37129088Smarkm	switch(func) {
37229088Smarkm	case SLC_EOF:
37329088Smarkm		setval(VEOF, SLC_VARIABLE);
37429088Smarkm	case SLC_EC:
37529088Smarkm		setval(VERASE, SLC_VARIABLE);
37629088Smarkm	case SLC_EL:
37729088Smarkm		setval(VKILL, SLC_VARIABLE);
37829088Smarkm	case SLC_IP:
37929088Smarkm		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
38029088Smarkm	case SLC_ABORT:
38129088Smarkm		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
38229088Smarkm	case SLC_XON:
38329088Smarkm#ifdef	VSTART
38429088Smarkm		setval(VSTART, SLC_VARIABLE);
38529088Smarkm#else
38629088Smarkm		defval(0x13);
38729088Smarkm#endif
38829088Smarkm	case SLC_XOFF:
38929088Smarkm#ifdef	VSTOP
39029088Smarkm		setval(VSTOP, SLC_VARIABLE);
39129088Smarkm#else
39229088Smarkm		defval(0x11);
39329088Smarkm#endif
39429088Smarkm	case SLC_EW:
39529088Smarkm#ifdef	VWERASE
39629088Smarkm		setval(VWERASE, SLC_VARIABLE);
39729088Smarkm#else
39829088Smarkm		defval(0);
39929088Smarkm#endif
40029088Smarkm	case SLC_RP:
40129088Smarkm#ifdef	VREPRINT
40229088Smarkm		setval(VREPRINT, SLC_VARIABLE);
40329088Smarkm#else
40429088Smarkm		defval(0);
40529088Smarkm#endif
40629088Smarkm	case SLC_LNEXT:
40729088Smarkm#ifdef	VLNEXT
40829088Smarkm		setval(VLNEXT, SLC_VARIABLE);
40929088Smarkm#else
41029088Smarkm		defval(0);
41129088Smarkm#endif
41229088Smarkm	case SLC_AO:
41329088Smarkm#if	!defined(VDISCARD) && defined(VFLUSHO)
41429088Smarkm# define VDISCARD VFLUSHO
41529088Smarkm#endif
41629088Smarkm#ifdef	VDISCARD
41729088Smarkm		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
41829088Smarkm#else
41929088Smarkm		defval(0);
42029088Smarkm#endif
42129088Smarkm	case SLC_SUSP:
42229088Smarkm#ifdef	VSUSP
42329088Smarkm		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
42429088Smarkm#else
42529088Smarkm		defval(0);
42629088Smarkm#endif
42729088Smarkm#ifdef	VEOL
42829088Smarkm	case SLC_FORW1:
42929088Smarkm		setval(VEOL, SLC_VARIABLE);
43029088Smarkm#endif
43129088Smarkm#ifdef	VEOL2
43229088Smarkm	case SLC_FORW2:
43329088Smarkm		setval(VEOL2, SLC_VARIABLE);
43429088Smarkm#endif
43529088Smarkm	case SLC_AYT:
43629088Smarkm#ifdef	VSTATUS
43729088Smarkm		setval(VSTATUS, SLC_VARIABLE);
43829088Smarkm#else
43929088Smarkm		defval(0);
44029088Smarkm#endif
44129088Smarkm
44229088Smarkm	case SLC_BRK:
44329088Smarkm	case SLC_SYNCH:
44429088Smarkm	case SLC_EOR:
44529088Smarkm		defval(0);
44629088Smarkm
44729088Smarkm	default:
44829088Smarkm		*valp = 0;
44929088Smarkm		*valpp = 0;
45029088Smarkm		return(SLC_NOSUPPORT);
45129088Smarkm	}
45229088Smarkm}
45329088Smarkm#endif	/* USE_TERMIO */
45429088Smarkm
45529088Smarkm#ifdef CRAY
45629088Smarkm/*
45729088Smarkm * getnpty()
45829088Smarkm *
45929088Smarkm * Return the number of pty's configured into the system.
46029088Smarkm */
46129088Smarkm	int
46229088Smarkmgetnpty()
46329088Smarkm{
46429088Smarkm#ifdef _SC_CRAY_NPTY
46529088Smarkm	int numptys;
46629088Smarkm
46729088Smarkm	if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
46829088Smarkm		return numptys;
46929088Smarkm	else
47029088Smarkm#endif /* _SC_CRAY_NPTY */
47129088Smarkm		return 128;
47229088Smarkm}
47329088Smarkm#endif /* CRAY */
47429088Smarkm
47529088Smarkm#ifndef	convex
47629088Smarkm/*
47729088Smarkm * getpty()
47829088Smarkm *
47929088Smarkm * Allocate a pty.  As a side effect, the external character
48029088Smarkm * array "line" contains the name of the slave side.
48129088Smarkm *
48229088Smarkm * Returns the file descriptor of the opened pty.
48329088Smarkm */
48429088Smarkm#ifndef	__GNUC__
48529088Smarkmchar *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
48629088Smarkm#else
48729088Smarkmstatic char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
48829088Smarkmchar *line = Xline;
48929088Smarkm#endif
49029088Smarkm#ifdef	CRAY
49129088Smarkmchar *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
49229088Smarkm#endif	/* CRAY */
49329088Smarkm
49429088Smarkm	int
49529088Smarkmgetpty(ptynum)
49629088Smarkmint *ptynum;
49729088Smarkm{
49829088Smarkm	register int p;
49929088Smarkm#ifdef	STREAMSPTY
50029088Smarkm	int t;
50129088Smarkm	char *ptsname();
50229088Smarkm
50329088Smarkm	p = open("/dev/ptmx", 2);
50429088Smarkm	if (p > 0) {
50529088Smarkm		grantpt(p);
50629088Smarkm		unlockpt(p);
50729088Smarkm		strcpy(line, ptsname(p));
50829088Smarkm		return(p);
50929088Smarkm	}
51029088Smarkm
51129088Smarkm#else	/* ! STREAMSPTY */
51229088Smarkm#ifndef CRAY
51329088Smarkm	register char *cp, *p1, *p2;
51429088Smarkm	register int i;
51529088Smarkm#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
51629088Smarkm	int dummy;
51729088Smarkm#endif
51829088Smarkm
51929088Smarkm#ifndef	__hpux
52032688Simp	(void) strcpy(line, "/dev/ptyXX");
52129088Smarkm	p1 = &line[8];
52229088Smarkm	p2 = &line[9];
52329088Smarkm#else
52432688Simp	(void) strcpy(line, "/dev/ptym/ptyXX");
52529088Smarkm	p1 = &line[13];
52629088Smarkm	p2 = &line[14];
52729088Smarkm#endif
52829088Smarkm
52929181Smarkm	for (cp = "pqrsPQRS"; *cp; cp++) {
53029088Smarkm		struct stat stb;
53129088Smarkm
53229088Smarkm		*p1 = *cp;
53329088Smarkm		*p2 = '0';
53429088Smarkm		/*
53529088Smarkm		 * This stat() check is just to keep us from
53629088Smarkm		 * looping through all 256 combinations if there
53729088Smarkm		 * aren't that many ptys available.
53829088Smarkm		 */
53929088Smarkm		if (stat(line, &stb) < 0)
54029088Smarkm			break;
54129181Smarkm		for (i = 0; i < 32; i++) {
54229181Smarkm			*p2 = "0123456789abcdefghijklmnopqrstuv"[i];
54329088Smarkm			p = open(line, 2);
54429088Smarkm			if (p > 0) {
54529088Smarkm#ifndef	__hpux
54629088Smarkm				line[5] = 't';
54729088Smarkm#else
54829088Smarkm				for (p1 = &line[8]; *p1; p1++)
54929088Smarkm					*p1 = *(p1+1);
55029088Smarkm				line[9] = 't';
55129088Smarkm#endif
55229088Smarkm				chown(line, 0, 0);
55329088Smarkm				chmod(line, 0600);
55429088Smarkm#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
55529088Smarkm				if (ioctl(p, TIOCGPGRP, &dummy) == 0
55629088Smarkm				    || errno != EIO) {
55729088Smarkm					chmod(line, 0666);
55829088Smarkm					close(p);
55929088Smarkm					line[5] = 'p';
56029088Smarkm				} else
56129088Smarkm#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
56229088Smarkm					return(p);
56329088Smarkm			}
56429088Smarkm		}
56529088Smarkm	}
56629088Smarkm#else	/* CRAY */
56729088Smarkm	extern lowpty, highpty;
56829088Smarkm	struct stat sb;
56929088Smarkm
57029088Smarkm	for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
57129088Smarkm		(void) sprintf(myline, "/dev/pty/%03d", *ptynum);
57229088Smarkm		p = open(myline, 2);
57329088Smarkm		if (p < 0)
57429088Smarkm			continue;
57529088Smarkm		(void) sprintf(line, "/dev/ttyp%03d", *ptynum);
57629088Smarkm		/*
57729088Smarkm		 * Here are some shenanigans to make sure that there
57829088Smarkm		 * are no listeners lurking on the line.
57929088Smarkm		 */
58029088Smarkm		if(stat(line, &sb) < 0) {
58129088Smarkm			(void) close(p);
58229088Smarkm			continue;
58329088Smarkm		}
58429088Smarkm		if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
58529088Smarkm			chown(line, 0, 0);
58629088Smarkm			chmod(line, 0600);
58729088Smarkm			(void)close(p);
58829088Smarkm			p = open(myline, 2);
58929088Smarkm			if (p < 0)
59029088Smarkm				continue;
59129088Smarkm		}
59229088Smarkm		/*
59329088Smarkm		 * Now it should be safe...check for accessability.
59429088Smarkm		 */
59529088Smarkm		if (access(line, 6) == 0)
59629088Smarkm			return(p);
59729088Smarkm		else {
59829088Smarkm			/* no tty side to pty so skip it */
59929088Smarkm			(void) close(p);
60029088Smarkm		}
60129088Smarkm	}
60229088Smarkm#endif	/* CRAY */
60329088Smarkm#endif	/* STREAMSPTY */
60429088Smarkm	return(-1);
60529088Smarkm}
60629088Smarkm#endif	/* convex */
60729088Smarkm
60829088Smarkm#ifdef	LINEMODE
60929088Smarkm/*
61029088Smarkm * tty_flowmode()	Find out if flow control is enabled or disabled.
61129088Smarkm * tty_linemode()	Find out if linemode (external processing) is enabled.
61229088Smarkm * tty_setlinemod(on)	Turn on/off linemode.
61329088Smarkm * tty_isecho()		Find out if echoing is turned on.
61429088Smarkm * tty_setecho(on)	Enable/disable character echoing.
61529088Smarkm * tty_israw()		Find out if terminal is in RAW mode.
61629088Smarkm * tty_binaryin(on)	Turn on/off BINARY on input.
61729088Smarkm * tty_binaryout(on)	Turn on/off BINARY on output.
61829088Smarkm * tty_isediting()	Find out if line editing is enabled.
61929088Smarkm * tty_istrapsig()	Find out if signal trapping is enabled.
62029088Smarkm * tty_setedit(on)	Turn on/off line editing.
62129088Smarkm * tty_setsig(on)	Turn on/off signal trapping.
62229088Smarkm * tty_issofttab()	Find out if tab expansion is enabled.
62329088Smarkm * tty_setsofttab(on)	Turn on/off soft tab expansion.
62429088Smarkm * tty_islitecho()	Find out if typed control chars are echoed literally
62529088Smarkm * tty_setlitecho()	Turn on/off literal echo of control chars
62629088Smarkm * tty_tspeed(val)	Set transmit speed to val.
62729088Smarkm * tty_rspeed(val)	Set receive speed to val.
62829088Smarkm */
62929088Smarkm
63029088Smarkm#ifdef convex
63129088Smarkmstatic int linestate;
63229088Smarkm#endif
63329088Smarkm
63429088Smarkm	int
63529088Smarkmtty_linemode()
63629088Smarkm{
63729088Smarkm#ifndef convex
63829088Smarkm#ifndef	USE_TERMIO
63929088Smarkm	return(termbuf.state & TS_EXTPROC);
64029088Smarkm#else
64129088Smarkm	return(termbuf.c_lflag & EXTPROC);
64229088Smarkm#endif
64329088Smarkm#else
64429088Smarkm	return(linestate);
64529088Smarkm#endif
64629088Smarkm}
64729088Smarkm
64829088Smarkm	void
64929088Smarkmtty_setlinemode(on)
65029088Smarkm	int on;
65129088Smarkm{
65229088Smarkm#ifdef	TIOCEXT
65329088Smarkm# ifndef convex
65429088Smarkm	set_termbuf();
65529088Smarkm# else
65629088Smarkm	linestate = on;
65729088Smarkm# endif
65829088Smarkm	(void) ioctl(pty, TIOCEXT, (char *)&on);
65929088Smarkm# ifndef convex
66029088Smarkm	init_termbuf();
66129088Smarkm# endif
66229088Smarkm#else	/* !TIOCEXT */
66329088Smarkm# ifdef	EXTPROC
66429088Smarkm	if (on)
66529088Smarkm		termbuf.c_lflag |= EXTPROC;
66629088Smarkm	else
66729088Smarkm		termbuf.c_lflag &= ~EXTPROC;
66829088Smarkm# endif
66929088Smarkm#endif	/* TIOCEXT */
67029088Smarkm}
67129088Smarkm#endif	/* LINEMODE */
67229088Smarkm
67329088Smarkm	int
67429088Smarkmtty_isecho()
67529088Smarkm{
67629088Smarkm#ifndef USE_TERMIO
67729088Smarkm	return (termbuf.sg.sg_flags & ECHO);
67829088Smarkm#else
67929088Smarkm	return (termbuf.c_lflag & ECHO);
68029088Smarkm#endif
68129088Smarkm}
68229088Smarkm
68329088Smarkm	int
68429088Smarkmtty_flowmode()
68529088Smarkm{
68629088Smarkm#ifndef USE_TERMIO
68729088Smarkm	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
68829088Smarkm#else
68929088Smarkm	return((termbuf.c_iflag & IXON) ? 1 : 0);
69029088Smarkm#endif
69129088Smarkm}
69229088Smarkm
69329088Smarkm	int
69429088Smarkmtty_restartany()
69529088Smarkm{
69629088Smarkm#ifndef USE_TERMIO
69729088Smarkm# ifdef	DECCTQ
69829088Smarkm	return((termbuf.lflags & DECCTQ) ? 0 : 1);
69929088Smarkm# else
70029088Smarkm	return(-1);
70129088Smarkm# endif
70229088Smarkm#else
70329088Smarkm	return((termbuf.c_iflag & IXANY) ? 1 : 0);
70429088Smarkm#endif
70529088Smarkm}
70629088Smarkm
70729088Smarkm	void
70829088Smarkmtty_setecho(on)
70929088Smarkm	int on;
71029088Smarkm{
71129088Smarkm#ifndef	USE_TERMIO
71229088Smarkm	if (on)
71329088Smarkm		termbuf.sg.sg_flags |= ECHO|CRMOD;
71429088Smarkm	else
71529088Smarkm		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
71629088Smarkm#else
71729088Smarkm	if (on)
71829088Smarkm		termbuf.c_lflag |= ECHO;
71929088Smarkm	else
72029088Smarkm		termbuf.c_lflag &= ~ECHO;
72129088Smarkm#endif
72229088Smarkm}
72329088Smarkm
72429088Smarkm	int
72529088Smarkmtty_israw()
72629088Smarkm{
72729088Smarkm#ifndef USE_TERMIO
72829088Smarkm	return(termbuf.sg.sg_flags & RAW);
72929088Smarkm#else
73029088Smarkm	return(!(termbuf.c_lflag & ICANON));
73129088Smarkm#endif
73229088Smarkm}
73329088Smarkm
73429088Smarkm#if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
73529088Smarkm	int
73629088Smarkmtty_setraw(on)
73729088Smarkm{
73829088Smarkm#  ifndef USE_TERMIO
73929088Smarkm	if (on)
74029088Smarkm		termbuf.sg.sg_flags |= RAW;
74129088Smarkm	else
74229088Smarkm		termbuf.sg.sg_flags &= ~RAW;
74329088Smarkm#  else
74429088Smarkm	if (on)
74529088Smarkm		termbuf.c_lflag &= ~ICANON;
74629088Smarkm	else
74729088Smarkm		termbuf.c_lflag |= ICANON;
74829088Smarkm#  endif
74929088Smarkm}
75029088Smarkm#endif
75129088Smarkm
75229088Smarkm	void
75329088Smarkmtty_binaryin(on)
75429088Smarkm	int on;
75529088Smarkm{
75629088Smarkm#ifndef	USE_TERMIO
75729088Smarkm	if (on)
75829088Smarkm		termbuf.lflags |= LPASS8;
75929088Smarkm	else
76029088Smarkm		termbuf.lflags &= ~LPASS8;
76129088Smarkm#else
76229088Smarkm	if (on) {
76329088Smarkm		termbuf.c_iflag &= ~ISTRIP;
76429088Smarkm	} else {
76529088Smarkm		termbuf.c_iflag |= ISTRIP;
76629088Smarkm	}
76729088Smarkm#endif
76829088Smarkm}
76929088Smarkm
77029088Smarkm	void
77129088Smarkmtty_binaryout(on)
77229088Smarkm	int on;
77329088Smarkm{
77429088Smarkm#ifndef	USE_TERMIO
77529088Smarkm	if (on)
77629088Smarkm		termbuf.lflags |= LLITOUT;
77729088Smarkm	else
77829088Smarkm		termbuf.lflags &= ~LLITOUT;
77929088Smarkm#else
78029088Smarkm	if (on) {
78129088Smarkm		termbuf.c_cflag &= ~(CSIZE|PARENB);
78229088Smarkm		termbuf.c_cflag |= CS8;
78329088Smarkm		termbuf.c_oflag &= ~OPOST;
78429088Smarkm	} else {
78529088Smarkm		termbuf.c_cflag &= ~CSIZE;
78629088Smarkm		termbuf.c_cflag |= CS7|PARENB;
78729088Smarkm		termbuf.c_oflag |= OPOST;
78829088Smarkm	}
78929088Smarkm#endif
79029088Smarkm}
79129088Smarkm
79229088Smarkm	int
79329088Smarkmtty_isbinaryin()
79429088Smarkm{
79529088Smarkm#ifndef	USE_TERMIO
79629088Smarkm	return(termbuf.lflags & LPASS8);
79729088Smarkm#else
79829088Smarkm	return(!(termbuf.c_iflag & ISTRIP));
79929088Smarkm#endif
80029088Smarkm}
80129088Smarkm
80229088Smarkm	int
80329088Smarkmtty_isbinaryout()
80429088Smarkm{
80529088Smarkm#ifndef	USE_TERMIO
80629088Smarkm	return(termbuf.lflags & LLITOUT);
80729088Smarkm#else
80829088Smarkm	return(!(termbuf.c_oflag&OPOST));
80929088Smarkm#endif
81029088Smarkm}
81129088Smarkm
81229088Smarkm#ifdef	LINEMODE
81329088Smarkm	int
81429088Smarkmtty_isediting()
81529088Smarkm{
81629088Smarkm#ifndef USE_TERMIO
81729088Smarkm	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
81829088Smarkm#else
81929088Smarkm	return(termbuf.c_lflag & ICANON);
82029088Smarkm#endif
82129088Smarkm}
82229088Smarkm
82329088Smarkm	int
82429088Smarkmtty_istrapsig()
82529088Smarkm{
82629088Smarkm#ifndef USE_TERMIO
82729088Smarkm	return(!(termbuf.sg.sg_flags&RAW));
82829088Smarkm#else
82929088Smarkm	return(termbuf.c_lflag & ISIG);
83029088Smarkm#endif
83129088Smarkm}
83229088Smarkm
83329088Smarkm	void
83429088Smarkmtty_setedit(on)
83529088Smarkm	int on;
83629088Smarkm{
83729088Smarkm#ifndef USE_TERMIO
83829088Smarkm	if (on)
83929088Smarkm		termbuf.sg.sg_flags &= ~CBREAK;
84029088Smarkm	else
84129088Smarkm		termbuf.sg.sg_flags |= CBREAK;
84229088Smarkm#else
84329088Smarkm	if (on)
84429088Smarkm		termbuf.c_lflag |= ICANON;
84529088Smarkm	else
84629088Smarkm		termbuf.c_lflag &= ~ICANON;
84729088Smarkm#endif
84829088Smarkm}
84929088Smarkm
85029088Smarkm	void
85129088Smarkmtty_setsig(on)
85229088Smarkm	int on;
85329088Smarkm{
85429088Smarkm#ifndef	USE_TERMIO
85529088Smarkm	if (on)
85629088Smarkm		;
85729088Smarkm#else
85829088Smarkm	if (on)
85929088Smarkm		termbuf.c_lflag |= ISIG;
86029088Smarkm	else
86129088Smarkm		termbuf.c_lflag &= ~ISIG;
86229088Smarkm#endif
86329088Smarkm}
86429088Smarkm#endif	/* LINEMODE */
86529088Smarkm
86629088Smarkm	int
86729088Smarkmtty_issofttab()
86829088Smarkm{
86929088Smarkm#ifndef	USE_TERMIO
87029088Smarkm	return (termbuf.sg.sg_flags & XTABS);
87129088Smarkm#else
87229088Smarkm# ifdef	OXTABS
87329088Smarkm	return (termbuf.c_oflag & OXTABS);
87429088Smarkm# endif
87529088Smarkm# ifdef	TABDLY
87629088Smarkm	return ((termbuf.c_oflag & TABDLY) == TAB3);
87729088Smarkm# endif
87829088Smarkm#endif
87929088Smarkm}
88029088Smarkm
88129088Smarkm	void
88229088Smarkmtty_setsofttab(on)
88329088Smarkm	int on;
88429088Smarkm{
88529088Smarkm#ifndef	USE_TERMIO
88629088Smarkm	if (on)
88729088Smarkm		termbuf.sg.sg_flags |= XTABS;
88829088Smarkm	else
88929088Smarkm		termbuf.sg.sg_flags &= ~XTABS;
89029088Smarkm#else
89129088Smarkm	if (on) {
89229088Smarkm# ifdef	OXTABS
89329088Smarkm		termbuf.c_oflag |= OXTABS;
89429088Smarkm# endif
89529088Smarkm# ifdef	TABDLY
89629088Smarkm		termbuf.c_oflag &= ~TABDLY;
89729088Smarkm		termbuf.c_oflag |= TAB3;
89829088Smarkm# endif
89929088Smarkm	} else {
90029088Smarkm# ifdef	OXTABS
90129088Smarkm		termbuf.c_oflag &= ~OXTABS;
90229088Smarkm# endif
90329088Smarkm# ifdef	TABDLY
90429088Smarkm		termbuf.c_oflag &= ~TABDLY;
90529088Smarkm		termbuf.c_oflag |= TAB0;
90629088Smarkm# endif
90729088Smarkm	}
90829088Smarkm#endif
90929088Smarkm}
91029088Smarkm
91129088Smarkm	int
91229088Smarkmtty_islitecho()
91329088Smarkm{
91429088Smarkm#ifndef	USE_TERMIO
91529088Smarkm	return (!(termbuf.lflags & LCTLECH));
91629088Smarkm#else
91729088Smarkm# ifdef	ECHOCTL
91829088Smarkm	return (!(termbuf.c_lflag & ECHOCTL));
91929088Smarkm# endif
92029088Smarkm# ifdef	TCTLECH
92129088Smarkm	return (!(termbuf.c_lflag & TCTLECH));
92229088Smarkm# endif
92329088Smarkm# if	!defined(ECHOCTL) && !defined(TCTLECH)
92429088Smarkm	return (0);	/* assumes ctl chars are echoed '^x' */
92529088Smarkm# endif
92629088Smarkm#endif
92729088Smarkm}
92829088Smarkm
92929088Smarkm	void
93029088Smarkmtty_setlitecho(on)
93129088Smarkm	int on;
93229088Smarkm{
93329088Smarkm#ifndef	USE_TERMIO
93429088Smarkm	if (on)
93529088Smarkm		termbuf.lflags &= ~LCTLECH;
93629088Smarkm	else
93729088Smarkm		termbuf.lflags |= LCTLECH;
93829088Smarkm#else
93929088Smarkm# ifdef	ECHOCTL
94029088Smarkm	if (on)
94129088Smarkm		termbuf.c_lflag &= ~ECHOCTL;
94229088Smarkm	else
94329088Smarkm		termbuf.c_lflag |= ECHOCTL;
94429088Smarkm# endif
94529088Smarkm# ifdef	TCTLECH
94629088Smarkm	if (on)
94729088Smarkm		termbuf.c_lflag &= ~TCTLECH;
94829088Smarkm	else
94929088Smarkm		termbuf.c_lflag |= TCTLECH;
95029088Smarkm# endif
95129088Smarkm#endif
95229088Smarkm}
95329088Smarkm
95429088Smarkm	int
95529088Smarkmtty_iscrnl()
95629088Smarkm{
95729088Smarkm#ifndef	USE_TERMIO
95829088Smarkm	return (termbuf.sg.sg_flags & CRMOD);
95929088Smarkm#else
96029088Smarkm	return (termbuf.c_iflag & ICRNL);
96129088Smarkm#endif
96229088Smarkm}
96329088Smarkm
96429088Smarkm/*
96529088Smarkm * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
96629088Smarkm */
96729088Smarkm#if B4800 != 4800
96829088Smarkm#define	DECODE_BAUD
96929088Smarkm#endif
97029088Smarkm
97129088Smarkm#ifdef	DECODE_BAUD
97229088Smarkm
97329088Smarkm/*
97429088Smarkm * A table of available terminal speeds
97529088Smarkm */
97629088Smarkmstruct termspeeds {
97729088Smarkm	int	speed;
97829088Smarkm	int	value;
97929088Smarkm} termspeeds[] = {
98029088Smarkm	{ 0,      B0 },      { 50,    B50 },    { 75,     B75 },
98129088Smarkm	{ 110,    B110 },    { 134,   B134 },   { 150,    B150 },
98229088Smarkm	{ 200,    B200 },    { 300,   B300 },   { 600,    B600 },
98329088Smarkm	{ 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
98429088Smarkm	{ 4800,   B4800 },
98529088Smarkm#ifdef	B7200
98629088Smarkm	{ 7200,  B7200 },
98729088Smarkm#endif
98829088Smarkm	{ 9600,   B9600 },
98929088Smarkm#ifdef	B14400
99029088Smarkm	{ 14400,  B14400 },
99129088Smarkm#endif
99229088Smarkm#ifdef	B19200
99329088Smarkm	{ 19200,  B19200 },
99429088Smarkm#endif
99529088Smarkm#ifdef	B28800
99629088Smarkm	{ 28800,  B28800 },
99729088Smarkm#endif
99829088Smarkm#ifdef	B38400
99929088Smarkm	{ 38400,  B38400 },
100029088Smarkm#endif
100129088Smarkm#ifdef	B57600
100229088Smarkm	{ 57600,  B57600 },
100329088Smarkm#endif
100429088Smarkm#ifdef	B115200
100529088Smarkm	{ 115200, B115200 },
100629088Smarkm#endif
100729088Smarkm#ifdef	B230400
100829088Smarkm	{ 230400, B230400 },
100929088Smarkm#endif
101029088Smarkm	{ -1,     0 }
101129088Smarkm};
101231622Scharnier#endif	/* DECODE_BAUD */
101329088Smarkm
101429088Smarkm	void
101529088Smarkmtty_tspeed(val)
101629088Smarkm	int val;
101729088Smarkm{
101829088Smarkm#ifdef	DECODE_BAUD
101929088Smarkm	register struct termspeeds *tp;
102029088Smarkm
102129088Smarkm	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
102229088Smarkm		;
102329088Smarkm	if (tp->speed == -1)	/* back up to last valid value */
102429088Smarkm		--tp;
102529088Smarkm	cfsetospeed(&termbuf, tp->value);
102631622Scharnier#else	/* DECODE_BAUD */
102729088Smarkm	cfsetospeed(&termbuf, val);
102831622Scharnier#endif	/* DECODE_BAUD */
102929088Smarkm}
103029088Smarkm
103129088Smarkm	void
103229088Smarkmtty_rspeed(val)
103329088Smarkm	int val;
103429088Smarkm{
103529088Smarkm#ifdef	DECODE_BAUD
103629088Smarkm	register struct termspeeds *tp;
103729088Smarkm
103829088Smarkm	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
103929088Smarkm		;
104029088Smarkm	if (tp->speed == -1)	/* back up to last valid value */
104129088Smarkm		--tp;
104229088Smarkm	cfsetispeed(&termbuf, tp->value);
104329088Smarkm#else	/* DECODE_BAUD */
104429088Smarkm	cfsetispeed(&termbuf, val);
104529088Smarkm#endif	/* DECODE_BAUD */
104629088Smarkm}
104729088Smarkm
104829088Smarkm#if	defined(CRAY2) && defined(UNICOS5)
104929088Smarkm	int
105029088Smarkmtty_isnewmap()
105129088Smarkm{
105229088Smarkm	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
105329088Smarkm			!(termbuf.c_oflag & ONLRET));
105429088Smarkm}
105529088Smarkm#endif
105629088Smarkm
105729088Smarkm#ifdef PARENT_DOES_UTMP
105829088Smarkm# ifndef NEWINIT
105929088Smarkmextern	struct utmp wtmp;
106029088Smarkmextern char wtmpf[];
106129088Smarkm# else	/* NEWINIT */
106229088Smarkmint	gotalarm;
106329088Smarkm
106429088Smarkm	/* ARGSUSED */
106529088Smarkm	void
106629088Smarkmnologinproc(sig)
106729088Smarkm	int sig;
106829088Smarkm{
106929088Smarkm	gotalarm++;
107029088Smarkm}
107129088Smarkm# endif	/* NEWINIT */
107229088Smarkm#endif /* PARENT_DOES_UTMP */
107329088Smarkm
107429088Smarkm#ifndef	NEWINIT
107529088Smarkm# ifdef PARENT_DOES_UTMP
107629088Smarkmextern void utmp_sig_init P((void));
107729088Smarkmextern void utmp_sig_reset P((void));
107829088Smarkmextern void utmp_sig_wait P((void));
107929088Smarkmextern void utmp_sig_notify P((int));
108029088Smarkm# endif /* PARENT_DOES_UTMP */
108129088Smarkm#endif
108229088Smarkm
108329088Smarkm/*
108429088Smarkm * getptyslave()
108529088Smarkm *
108629088Smarkm * Open the slave side of the pty, and do any initialization
108731622Scharnier * that is necessary.
108829088Smarkm */
108929181Smarkm	void
109029088Smarkmgetptyslave()
109129088Smarkm{
109229088Smarkm	register int t = -1;
109329181Smarkm	char erase;
109429088Smarkm
109529088Smarkm#if	!defined(CRAY) || !defined(NEWINIT)
109629088Smarkm# ifdef	LINEMODE
109729088Smarkm	int waslm;
109829088Smarkm# endif
109929088Smarkm# ifdef	TIOCGWINSZ
110029088Smarkm	struct winsize ws;
110129088Smarkm	extern int def_row, def_col;
110229088Smarkm# endif
110329088Smarkm	extern int def_tspeed, def_rspeed;
110429088Smarkm	/*
110529088Smarkm	 * Opening the slave side may cause initilization of the
110629088Smarkm	 * kernel tty structure.  We need remember the state of
110729088Smarkm	 * 	if linemode was turned on
110829088Smarkm	 *	terminal window size
110929088Smarkm	 *	terminal speed
111029181Smarkm	 *	erase character
111129088Smarkm	 * so that we can re-set them if we need to.
111229088Smarkm	 */
111329088Smarkm# ifdef	LINEMODE
111429088Smarkm	waslm = tty_linemode();
111529088Smarkm# endif
111629181Smarkm	erase = termbuf.c_cc[VERASE];
111729088Smarkm
111829088Smarkm	/*
111929088Smarkm	 * Make sure that we don't have a controlling tty, and
112029088Smarkm	 * that we are the session (process group) leader.
112129088Smarkm	 */
112229088Smarkm# ifdef	TIOCNOTTY
112329088Smarkm	t = open(_PATH_TTY, O_RDWR);
112429088Smarkm	if (t >= 0) {
112529088Smarkm		(void) ioctl(t, TIOCNOTTY, (char *)0);
112629088Smarkm		(void) close(t);
112729088Smarkm	}
112829088Smarkm# endif
112929088Smarkm
113029088Smarkm
113129088Smarkm# ifdef PARENT_DOES_UTMP
113229088Smarkm	/*
113329088Smarkm	 * Wait for our parent to get the utmp stuff to get done.
113429088Smarkm	 */
113529088Smarkm	utmp_sig_wait();
113629088Smarkm# endif
113729088Smarkm
113829088Smarkm	t = cleanopen(line);
113929088Smarkm	if (t < 0)
114029088Smarkm		fatalperror(net, line);
114129088Smarkm
114229088Smarkm#ifdef  STREAMSPTY
114329088Smarkm#ifdef	USE_TERMIO
114429088Smarkm	ttyfd = t;
114529088Smarkm#endif
114629088Smarkm	if (ioctl(t, I_PUSH, "ptem") < 0)
114729088Smarkm		fatal(net, "I_PUSH ptem");
114829088Smarkm	if (ioctl(t, I_PUSH, "ldterm") < 0)
114929088Smarkm		fatal(net, "I_PUSH ldterm");
115029088Smarkm	if (ioctl(t, I_PUSH, "ttcompat") < 0)
115129088Smarkm		fatal(net, "I_PUSH ttcompat");
115229088Smarkm	if (ioctl(pty, I_PUSH, "pckt") < 0)
115329088Smarkm		fatal(net, "I_PUSH pckt");
115429088Smarkm#endif
115529088Smarkm
115629088Smarkm	/*
115729088Smarkm	 * set up the tty modes as we like them to be.
115829088Smarkm	 */
115929088Smarkm	init_termbuf();
116029088Smarkm# ifdef	TIOCGWINSZ
116129088Smarkm	if (def_row || def_col) {
116229088Smarkm		memset((char *)&ws, 0, sizeof(ws));
116329088Smarkm		ws.ws_col = def_col;
116429088Smarkm		ws.ws_row = def_row;
116529088Smarkm		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
116629088Smarkm	}
116729088Smarkm# endif
116829088Smarkm
116929088Smarkm	/*
117029088Smarkm	 * Settings for sgtty based systems
117129088Smarkm	 */
117229088Smarkm# ifndef	USE_TERMIO
117329088Smarkm	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
117429088Smarkm# endif	/* USE_TERMIO */
117529088Smarkm
117629088Smarkm	/*
117729088Smarkm	 * Settings for UNICOS (and HPUX)
117829088Smarkm	 */
117929088Smarkm# if defined(CRAY) || defined(__hpux)
118029088Smarkm	termbuf.c_oflag = OPOST|ONLCR|TAB3;
118129088Smarkm	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
118229088Smarkm	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
118329088Smarkm	termbuf.c_cflag = EXTB|HUPCL|CS8;
118429088Smarkm# endif
118529088Smarkm
118629088Smarkm	/*
118729088Smarkm	 * Settings for all other termios/termio based
118829088Smarkm	 * systems, other than 4.4BSD.  In 4.4BSD the
118929088Smarkm	 * kernel does the initial terminal setup.
119029088Smarkm	 */
119129088Smarkm# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
119229088Smarkm#  ifndef	OXTABS
119329088Smarkm#   define OXTABS	0
119429088Smarkm#  endif
119529088Smarkm	termbuf.c_lflag |= ECHO;
119629088Smarkm	termbuf.c_oflag |= ONLCR|OXTABS;
119729088Smarkm	termbuf.c_iflag |= ICRNL;
119829088Smarkm	termbuf.c_iflag &= ~IXOFF;
119929088Smarkm# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
120029088Smarkm	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
120129088Smarkm	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
120229181Smarkm	if (erase)
120329181Smarkm		termbuf.c_cc[VERASE] = erase;
120429088Smarkm# ifdef	LINEMODE
120529088Smarkm	if (waslm)
120629088Smarkm		tty_setlinemode(1);
120729088Smarkm# endif	/* LINEMODE */
120829088Smarkm
120929088Smarkm	/*
121029088Smarkm	 * Set the tty modes, and make this our controlling tty.
121129088Smarkm	 */
121229088Smarkm	set_termbuf();
121329088Smarkm	if (login_tty(t) == -1)
121429088Smarkm		fatalperror(net, "login_tty");
121529088Smarkm#endif	/* !defined(CRAY) || !defined(NEWINIT) */
121629088Smarkm	if (net > 2)
121729088Smarkm		(void) close(net);
121829088Smarkm#if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
121929088Smarkm	/*
122029088Smarkm	 * Leave the pty open so that we can write out the rlogin
122129088Smarkm	 * protocol for /bin/login, if the authentication works.
122229088Smarkm	 */
122329088Smarkm#else
122429088Smarkm	if (pty > 2) {
122529088Smarkm		(void) close(pty);
122629088Smarkm		pty = -1;
122729088Smarkm	}
122829088Smarkm#endif
122929088Smarkm}
123029088Smarkm
123129088Smarkm#if	!defined(CRAY) || !defined(NEWINIT)
123229088Smarkm#ifndef	O_NOCTTY
123329088Smarkm#define	O_NOCTTY	0
123429088Smarkm#endif
123529088Smarkm/*
123629088Smarkm * Open the specified slave side of the pty,
123729088Smarkm * making sure that we have a clean tty.
123829088Smarkm */
123929088Smarkm	int
124029088Smarkmcleanopen(line)
124129088Smarkm	char *line;
124229088Smarkm{
124329088Smarkm	register int t;
124429088Smarkm#ifdef	UNICOS7x
124529088Smarkm	struct secstat secbuf;
124629088Smarkm#endif	/* UNICOS7x */
124729088Smarkm
124829088Smarkm#ifndef STREAMSPTY
124929088Smarkm	/*
125029088Smarkm	 * Make sure that other people can't open the
125129088Smarkm	 * slave side of the connection.
125229088Smarkm	 */
125329088Smarkm	(void) chown(line, 0, 0);
125429088Smarkm	(void) chmod(line, 0600);
125529088Smarkm#endif
125629088Smarkm
125729088Smarkm# if !defined(CRAY) && (BSD > 43)
125829088Smarkm	(void) revoke(line);
125929088Smarkm# endif
126029088Smarkm#ifdef	UNICOS7x
126129088Smarkm	if (secflag) {
126229088Smarkm		if (secstat(line, &secbuf) < 0)
126329088Smarkm			return(-1);
126429088Smarkm		if (setulvl(secbuf.st_slevel) < 0)
126529088Smarkm			return(-1);
126629088Smarkm		if (setucmp(secbuf.st_compart) < 0)
126729088Smarkm			return(-1);
126829088Smarkm	}
126929088Smarkm#endif	/* UNICOS7x */
127029088Smarkm
127129088Smarkm	t = open(line, O_RDWR|O_NOCTTY);
127229088Smarkm
127329088Smarkm#ifdef	UNICOS7x
127429088Smarkm	if (secflag) {
127529088Smarkm		if (setulvl(sysv.sy_minlvl) < 0)
127629088Smarkm			return(-1);
127729088Smarkm		if (setucmp(0) < 0)
127829088Smarkm			return(-1);
127929088Smarkm	}
128029088Smarkm#endif	/* UNICOS7x */
128129088Smarkm
128229088Smarkm	if (t < 0)
128329088Smarkm		return(-1);
128429088Smarkm
128529088Smarkm	/*
128629088Smarkm	 * Hangup anybody else using this ttyp, then reopen it for
128729088Smarkm	 * ourselves.
128829088Smarkm	 */
128929088Smarkm# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
129029088Smarkm	(void) signal(SIGHUP, SIG_IGN);
129129088Smarkm	vhangup();
129229088Smarkm	(void) signal(SIGHUP, SIG_DFL);
129329088Smarkm	t = open(line, O_RDWR|O_NOCTTY);
129429088Smarkm	if (t < 0)
129529088Smarkm		return(-1);
129629088Smarkm# endif
129729088Smarkm# if	defined(CRAY) && defined(TCVHUP)
129829088Smarkm	{
129929088Smarkm		register int i;
130029088Smarkm		(void) signal(SIGHUP, SIG_IGN);
130129088Smarkm		(void) ioctl(t, TCVHUP, (char *)0);
130229088Smarkm		(void) signal(SIGHUP, SIG_DFL);
130329088Smarkm
130429088Smarkm#ifdef	UNICOS7x
130529088Smarkm		if (secflag) {
130629088Smarkm			if (secstat(line, &secbuf) < 0)
130729088Smarkm				return(-1);
130829088Smarkm			if (setulvl(secbuf.st_slevel) < 0)
130929088Smarkm				return(-1);
131029088Smarkm			if (setucmp(secbuf.st_compart) < 0)
131129088Smarkm				return(-1);
131229088Smarkm		}
131329088Smarkm#endif	/* UNICOS7x */
131429088Smarkm
131529088Smarkm		i = open(line, O_RDWR);
131629088Smarkm
131729088Smarkm#ifdef	UNICOS7x
131829088Smarkm		if (secflag) {
131929088Smarkm			if (setulvl(sysv.sy_minlvl) < 0)
132029088Smarkm				return(-1);
132129088Smarkm			if (setucmp(0) < 0)
132229088Smarkm				return(-1);
132329088Smarkm		}
132429088Smarkm#endif	/* UNICOS7x */
132529088Smarkm
132629088Smarkm		if (i < 0)
132729088Smarkm			return(-1);
132829088Smarkm		(void) close(t);
132929088Smarkm		t = i;
133029088Smarkm	}
133129088Smarkm# endif	/* defined(CRAY) && defined(TCVHUP) */
133229088Smarkm	return(t);
133329088Smarkm}
133429088Smarkm#endif	/* !defined(CRAY) || !defined(NEWINIT) */
133529088Smarkm
133629088Smarkm#if BSD <= 43
133729088Smarkm
133829088Smarkm	int
133929088Smarkmlogin_tty(t)
134029088Smarkm	int t;
134129088Smarkm{
134229088Smarkm	if (setsid() < 0) {
134329088Smarkm#ifdef ultrix
134429088Smarkm		/*
134529088Smarkm		 * The setsid() may have failed because we
134629088Smarkm		 * already have a pgrp == pid.  Zero out
134729088Smarkm		 * our pgrp and try again...
134829088Smarkm		 */
134929088Smarkm		if ((setpgrp(0, 0) < 0) || (setsid() < 0))
135029088Smarkm#endif
135129088Smarkm			fatalperror(net, "setsid()");
135229088Smarkm	}
135329088Smarkm# ifdef	TIOCSCTTY
135429088Smarkm	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
135529088Smarkm		fatalperror(net, "ioctl(sctty)");
135629088Smarkm#  if defined(CRAY)
135729088Smarkm	/*
135829088Smarkm	 * Close the hard fd to /dev/ttypXXX, and re-open through
135929088Smarkm	 * the indirect /dev/tty interface.
136029088Smarkm	 */
136129088Smarkm	close(t);
136229088Smarkm	if ((t = open("/dev/tty", O_RDWR)) < 0)
136329088Smarkm		fatalperror(net, "open(/dev/tty)");
136429088Smarkm#  endif
136529088Smarkm# else
136629088Smarkm	/*
136729088Smarkm	 * We get our controlling tty assigned as a side-effect
136829088Smarkm	 * of opening up a tty device.  But on BSD based systems,
136929088Smarkm	 * this only happens if our process group is zero.  The
137029088Smarkm	 * setsid() call above may have set our pgrp, so clear
137129088Smarkm	 * it out before opening the tty...
137229088Smarkm	 */
137329088Smarkm#  ifndef SOLARIS
137429088Smarkm	(void) setpgrp(0, 0);
137529088Smarkm#  else
137629088Smarkm	(void) setpgrp();
137729088Smarkm#  endif
137829088Smarkm	close(open(line, O_RDWR));
137929088Smarkm# endif
138029088Smarkm	if (t != 0)
138129088Smarkm		(void) dup2(t, 0);
138229088Smarkm	if (t != 1)
138329088Smarkm		(void) dup2(t, 1);
138429088Smarkm	if (t != 2)
138529088Smarkm		(void) dup2(t, 2);
138629088Smarkm	if (t > 2)
138729088Smarkm		close(t);
138829088Smarkm	return(0);
138929088Smarkm}
139029088Smarkm#endif	/* BSD <= 43 */
139129088Smarkm
139229088Smarkm#ifdef	NEWINIT
139329088Smarkmchar *gen_id = "fe";
139429088Smarkm#endif
139529088Smarkm
139629088Smarkm/*
139729088Smarkm * startslave(host)
139829088Smarkm *
139929088Smarkm * Given a hostname, do whatever
140029088Smarkm * is necessary to startup the login process on the slave side of the pty.
140129088Smarkm */
140229088Smarkm
140329088Smarkm/* ARGSUSED */
140429088Smarkm	void
140529088Smarkmstartslave(host, autologin, autoname)
140629088Smarkm	char *host;
140729088Smarkm	int autologin;
140829088Smarkm	char *autoname;
140929088Smarkm{
141029088Smarkm	register int i;
141129088Smarkm#ifdef	NEWINIT
141229088Smarkm	extern char *ptyip;
141329088Smarkm	struct init_request request;
141429088Smarkm	void nologinproc();
141529088Smarkm	register int n;
141629088Smarkm#endif	/* NEWINIT */
141729088Smarkm
141829088Smarkm#if	defined(AUTHENTICATION)
141929088Smarkm	if (!autoname || !autoname[0])
142029088Smarkm		autologin = 0;
142129088Smarkm
142229088Smarkm	if (autologin < auth_level) {
142329088Smarkm		fatal(net, "Authorization failed");
142429088Smarkm		exit(1);
142529088Smarkm	}
142629088Smarkm#endif
142729088Smarkm
142829088Smarkm#ifndef	NEWINIT
142929088Smarkm# ifdef	PARENT_DOES_UTMP
143029088Smarkm	utmp_sig_init();
143129088Smarkm# endif	/* PARENT_DOES_UTMP */
143229088Smarkm
143329088Smarkm	if ((i = fork()) < 0)
143429088Smarkm		fatalperror(net, "fork");
143529088Smarkm	if (i) {
143629088Smarkm# ifdef PARENT_DOES_UTMP
143729088Smarkm		/*
143829088Smarkm		 * Cray parent will create utmp entry for child and send
143929088Smarkm		 * signal to child to tell when done.  Child waits for signal
144029088Smarkm		 * before doing anything important.
144129088Smarkm		 */
144229088Smarkm		register int pid = i;
144329088Smarkm		void sigjob P((int));
144429088Smarkm
144529088Smarkm		setpgrp();
144629088Smarkm		utmp_sig_reset();		/* reset handler to default */
144729088Smarkm		/*
144829088Smarkm		 * Create utmp entry for child
144929088Smarkm		 */
145029088Smarkm		(void) time(&wtmp.ut_time);
145129088Smarkm		wtmp.ut_type = LOGIN_PROCESS;
145229088Smarkm		wtmp.ut_pid = pid;
145329088Smarkm		SCPYN(wtmp.ut_user, "LOGIN");
145429088Smarkm		SCPYN(wtmp.ut_host, host);
145529088Smarkm		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
145629088Smarkm#ifndef	__hpux
145729088Smarkm		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
145829088Smarkm#else
145929088Smarkm		SCPYN(wtmp.ut_id, wtmp.ut_line+7);
146029088Smarkm#endif
146129088Smarkm		pututline(&wtmp);
146229088Smarkm		endutent();
146329088Smarkm		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
146429088Smarkm			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
146529088Smarkm			(void) close(i);
146629088Smarkm		}
146729088Smarkm#ifdef	CRAY
146829088Smarkm		(void) signal(WJSIGNAL, sigjob);
146929088Smarkm#endif
147029088Smarkm		utmp_sig_notify(pid);
147129088Smarkm# endif	/* PARENT_DOES_UTMP */
147229088Smarkm	} else {
147329088Smarkm		getptyslave(autologin);
147429088Smarkm		start_login(host, autologin, autoname);
147529088Smarkm		/*NOTREACHED*/
147629088Smarkm	}
147729088Smarkm#else	/* NEWINIT */
147829088Smarkm
147929088Smarkm	/*
148029088Smarkm	 * Init will start up login process if we ask nicely.  We only wait
148129088Smarkm	 * for it to start up and begin normal telnet operation.
148229088Smarkm	 */
148329088Smarkm	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
148429088Smarkm		char tbuf[128];
148532688Simp		(void) snprintf(tbuf, sizeof(tbuf), "Can't open %s\n", INIT_FIFO);
148629088Smarkm		fatalperror(net, tbuf);
148729088Smarkm	}
148829088Smarkm	memset((char *)&request, 0, sizeof(request));
148929088Smarkm	request.magic = INIT_MAGIC;
149029088Smarkm	SCPYN(request.gen_id, gen_id);
149129088Smarkm	SCPYN(request.tty_id, &line[8]);
149229088Smarkm	SCPYN(request.host, host);
149329088Smarkm	SCPYN(request.term_type, terminaltype ? terminaltype : "network");
149429088Smarkm#if	!defined(UNICOS5)
149529088Smarkm	request.signal = SIGCLD;
149629088Smarkm	request.pid = getpid();
149729088Smarkm#endif
149829088Smarkm#ifdef BFTPDAEMON
149929088Smarkm	/*
150029088Smarkm	 * Are we working as the bftp daemon?
150129088Smarkm	 */
150229088Smarkm	if (bftpd) {
150329088Smarkm		SCPYN(request.exec_name, BFTPPATH);
150429088Smarkm	}
150529088Smarkm#endif /* BFTPDAEMON */
150629088Smarkm	if (write(i, (char *)&request, sizeof(request)) < 0) {
150729088Smarkm		char tbuf[128];
150832688Simp		(void) snprintf(tbuf, sizeof(tbuf), "Can't write to %s\n", INIT_FIFO);
150929088Smarkm		fatalperror(net, tbuf);
151029088Smarkm	}
151129088Smarkm	(void) close(i);
151229088Smarkm	(void) signal(SIGALRM, nologinproc);
151329088Smarkm	for (i = 0; ; i++) {
151429088Smarkm		char tbuf[128];
151529088Smarkm		alarm(15);
151629088Smarkm		n = read(pty, ptyip, BUFSIZ);
151729088Smarkm		if (i == 3 || n >= 0 || !gotalarm)
151829088Smarkm			break;
151929088Smarkm		gotalarm = 0;
152032688Simp		snprintf(tbuf, sizeof(tbuf), "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
152129088Smarkm		(void) write(net, tbuf, strlen(tbuf));
152229088Smarkm	}
152329088Smarkm	if (n < 0 && gotalarm)
152429088Smarkm		fatal(net, "/etc/init didn't start login process");
152529088Smarkm	pcc += n;
152629088Smarkm	alarm(0);
152729088Smarkm	(void) signal(SIGALRM, SIG_DFL);
152829088Smarkm
152929088Smarkm	return;
153029088Smarkm#endif	/* NEWINIT */
153129088Smarkm}
153229088Smarkm
153329088Smarkmchar	*envinit[3];
153429088Smarkmextern char **environ;
153529088Smarkm
153629088Smarkm	void
153729088Smarkminit_env()
153829088Smarkm{
153929088Smarkm	extern char *getenv();
154029088Smarkm	char **envp;
154129088Smarkm
154229088Smarkm	envp = envinit;
154329181Smarkm	if ((*envp = getenv("TZ")))
154429088Smarkm		*envp++ -= 3;
154529088Smarkm#if	defined(CRAY) || defined(__hpux)
154629088Smarkm	else
154729088Smarkm		*envp++ = "TZ=GMT0";
154829088Smarkm#endif
154929088Smarkm	*envp = 0;
155029088Smarkm	environ = envinit;
155129088Smarkm}
155229088Smarkm
155329088Smarkm#ifndef	NEWINIT
155429088Smarkm
155529088Smarkm/*
155629088Smarkm * start_login(host)
155729088Smarkm *
155829088Smarkm * Assuming that we are now running as a child processes, this
155929088Smarkm * function will turn us into the login process.
156029088Smarkm */
156129088Smarkm
156229088Smarkm	void
156329088Smarkmstart_login(host, autologin, name)
156429088Smarkm	char *host;
156529088Smarkm	int autologin;
156629088Smarkm	char *name;
156729088Smarkm{
156829088Smarkm	register char **argv;
156929181Smarkm	char **addarg(), *user;
157029088Smarkm	extern char *getenv();
157129088Smarkm#ifdef	UTMPX
157229088Smarkm	register int pid = getpid();
157329088Smarkm	struct utmpx utmpx;
157429088Smarkm#endif
157529088Smarkm#ifdef SOLARIS
157629088Smarkm	char *term;
157729088Smarkm	char termbuf[64];
157829088Smarkm#endif
157929088Smarkm
158029088Smarkm#ifdef	UTMPX
158129088Smarkm	/*
158229088Smarkm	 * Create utmp entry for child
158329088Smarkm	 */
158429088Smarkm
158529088Smarkm	memset(&utmpx, 0, sizeof(utmpx));
158629088Smarkm	SCPYN(utmpx.ut_user, ".telnet");
158729088Smarkm	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
158829088Smarkm	utmpx.ut_pid = pid;
158929088Smarkm	utmpx.ut_id[0] = 't';
159029088Smarkm	utmpx.ut_id[1] = 'n';
159129088Smarkm	utmpx.ut_id[2] = SC_WILDC;
159229088Smarkm	utmpx.ut_id[3] = SC_WILDC;
159329088Smarkm	utmpx.ut_type = LOGIN_PROCESS;
159429088Smarkm	(void) time(&utmpx.ut_tv.tv_sec);
159529088Smarkm	if (makeutx(&utmpx) == NULL)
159629088Smarkm		fatal(net, "makeutx failed");
159729088Smarkm#endif
159829088Smarkm
159929088Smarkm	scrub_env();
160029088Smarkm
160129088Smarkm	/*
160229088Smarkm	 * -h : pass on name of host.
160329088Smarkm	 *		WARNING:  -h is accepted by login if and only if
160429088Smarkm	 *			getuid() == 0.
160529088Smarkm	 * -p : don't clobber the environment (so terminal type stays set).
160629088Smarkm	 *
160729088Smarkm	 * -f : force this login, he has already been authenticated
160829088Smarkm	 */
160929088Smarkm	argv = addarg(0, "login");
161029088Smarkm
161129088Smarkm#if	!defined(NO_LOGIN_H)
161229088Smarkm
161329088Smarkm# if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
161429088Smarkm	/*
161529088Smarkm	 * Don't add the "-h host" option if we are going
161629088Smarkm	 * to be adding the "-r host" option down below...
161729088Smarkm	 */
161829088Smarkm	if ((auth_level < 0) || (autologin != AUTH_VALID))
161929088Smarkm# endif
162029088Smarkm	{
162129088Smarkm		argv = addarg(argv, "-h");
162229088Smarkm		argv = addarg(argv, host);
162329088Smarkm#ifdef	SOLARIS
162429088Smarkm		/*
162529088Smarkm		 * SVR4 version of -h takes TERM= as second arg, or -
162629088Smarkm		 */
162729088Smarkm		term = getenv("TERM");
162829088Smarkm		if (term == NULL || term[0] == 0) {
162929088Smarkm			term = "-";
163029088Smarkm		} else {
163129088Smarkm			strcpy(termbuf, "TERM=");
163229088Smarkm			strncat(termbuf, term, sizeof(termbuf) - 6);
163329088Smarkm			term = termbuf;
163429088Smarkm		}
163529088Smarkm		argv = addarg(argv, term);
163629088Smarkm#endif
163729088Smarkm	}
163829088Smarkm#endif
163929088Smarkm#if	!defined(NO_LOGIN_P)
164029088Smarkm	argv = addarg(argv, "-p");
164129088Smarkm#endif
164229088Smarkm#ifdef	LINEMODE
164329088Smarkm	/*
164429088Smarkm	 * Set the environment variable "LINEMODE" to either
164529088Smarkm	 * "real" or "kludge" if we are operating in either
164629088Smarkm	 * real or kludge linemode.
164729088Smarkm	 */
164829088Smarkm	if (lmodetype == REAL_LINEMODE)
164929088Smarkm		setenv("LINEMODE", "real", 1);
165029088Smarkm# ifdef KLUDGELINEMODE
165129088Smarkm	else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
165229088Smarkm		setenv("LINEMODE", "kludge", 1);
165329088Smarkm# endif
165429088Smarkm#endif
165529088Smarkm#ifdef	BFTPDAEMON
165629088Smarkm	/*
165729088Smarkm	 * Are we working as the bftp daemon?  If so, then ask login
165829088Smarkm	 * to start bftp instead of shell.
165929088Smarkm	 */
166029088Smarkm	if (bftpd) {
166129088Smarkm		argv = addarg(argv, "-e");
166229088Smarkm		argv = addarg(argv, BFTPPATH);
166329088Smarkm	} else
166429088Smarkm#endif
166529088Smarkm#if	defined (SecurID)
166629088Smarkm	/*
166729088Smarkm	 * don't worry about the -f that might get sent.
166829088Smarkm	 * A -s is supposed to override it anyhow.
166929088Smarkm	 */
167029088Smarkm	if (require_SecurID)
167129088Smarkm		argv = addarg(argv, "-s");
167229088Smarkm#endif
167329088Smarkm#if	defined (AUTHENTICATION)
167429088Smarkm	if (auth_level >= 0 && autologin == AUTH_VALID) {
167529088Smarkm# if	!defined(NO_LOGIN_F)
167629088Smarkm		argv = addarg(argv, "-f");
167729181Smarkm		argv = addarg(argv, "--");
167829088Smarkm		argv = addarg(argv, name);
167929088Smarkm# else
168029088Smarkm#  if defined(LOGIN_R)
168129088Smarkm		/*
168229088Smarkm		 * We don't have support for "login -f", but we
168329088Smarkm		 * can fool /bin/login into thinking that we are
168429088Smarkm		 * rlogind, and allow us to log in without a
168529088Smarkm		 * password.  The rlogin protocol expects
168629088Smarkm		 *	local-user\0remote-user\0term/speed\0
168729088Smarkm		 */
168829088Smarkm
168929088Smarkm		if (pty > 2) {
169029088Smarkm			register char *cp;
169129088Smarkm			char speed[128];
169229088Smarkm			int isecho, israw, xpty, len;
169329088Smarkm			extern int def_rspeed;
169429088Smarkm#  ifndef LOGIN_HOST
169529088Smarkm			/*
169629088Smarkm			 * Tell login that we are coming from "localhost".
169729088Smarkm			 * If we passed in the real host name, then the
169829088Smarkm			 * user would have to allow .rhost access from
169929088Smarkm			 * every machine that they want authenticated
170029088Smarkm			 * access to work from, which sort of defeats
170129088Smarkm			 * the purpose of an authenticated login...
170229088Smarkm			 * So, we tell login that the session is coming
170329088Smarkm			 * from "localhost", and the user will only have
170429088Smarkm			 * to have "localhost" in their .rhost file.
170529088Smarkm			 */
170629088Smarkm#			define LOGIN_HOST "localhost"
170729088Smarkm#  endif
170829088Smarkm			argv = addarg(argv, "-r");
170929088Smarkm			argv = addarg(argv, LOGIN_HOST);
171029088Smarkm
171129088Smarkm			xpty = pty;
171229088Smarkm# ifndef  STREAMSPTY
171329088Smarkm			pty = 0;
171429088Smarkm# else
171529088Smarkm			ttyfd = 0;
171629088Smarkm# endif
171729088Smarkm			init_termbuf();
171829088Smarkm			isecho = tty_isecho();
171929088Smarkm			israw = tty_israw();
172029088Smarkm			if (isecho || !israw) {
172129088Smarkm				tty_setecho(0);		/* Turn off echo */
172229088Smarkm				tty_setraw(1);		/* Turn on raw */
172329088Smarkm				set_termbuf();
172429088Smarkm			}
172529088Smarkm			len = strlen(name)+1;
172629088Smarkm			write(xpty, name, len);
172729088Smarkm			write(xpty, name, len);
172832688Simp			snprintf(speed, sizeof(speed),
172932688Simp				"%s/%d", (cp = getenv("TERM")) ? cp : "",
173029088Smarkm				(def_rspeed > 0) ? def_rspeed : 9600);
173129088Smarkm			len = strlen(speed)+1;
173229088Smarkm			write(xpty, speed, len);
173329088Smarkm
173429088Smarkm			if (isecho || !israw) {
173529088Smarkm				init_termbuf();
173629088Smarkm				tty_setecho(isecho);
173729088Smarkm				tty_setraw(israw);
173829088Smarkm				set_termbuf();
173929088Smarkm				if (!israw) {
174029088Smarkm					/*
174129088Smarkm					 * Write a newline to ensure
174229088Smarkm					 * that login will be able to
174329088Smarkm					 * read the line...
174429088Smarkm					 */
174529088Smarkm					write(xpty, "\n", 1);
174629088Smarkm				}
174729088Smarkm			}
174829088Smarkm			pty = xpty;
174929088Smarkm		}
175029088Smarkm#  else
175129181Smarkm		argv = addarg(argv, "--");
175229088Smarkm		argv = addarg(argv, name);
175329088Smarkm#  endif
175429088Smarkm# endif
175529088Smarkm	} else
175629088Smarkm#endif
175729088Smarkm	if (getenv("USER")) {
175829181Smarkm 		argv = addarg(argv, "--");
175929088Smarkm		argv = addarg(argv, getenv("USER"));
176029088Smarkm#if	defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
176129088Smarkm		{
176229088Smarkm			register char **cpp;
176329088Smarkm			for (cpp = environ; *cpp; cpp++)
176429088Smarkm				argv = addarg(argv, *cpp);
176529088Smarkm		}
176629088Smarkm#endif
176729088Smarkm		/*
176829088Smarkm		 * Assume that login will set the USER variable
176929088Smarkm		 * correctly.  For SysV systems, this means that
177029088Smarkm		 * USER will no longer be set, just LOGNAME by
177129088Smarkm		 * login.  (The problem is that if the auto-login
177229088Smarkm		 * fails, and the user then specifies a different
177329088Smarkm		 * account name, he can get logged in with both
177429088Smarkm		 * LOGNAME and USER in his environment, but the
177529088Smarkm		 * USER value will be wrong.
177629088Smarkm		 */
177729088Smarkm		unsetenv("USER");
177829088Smarkm	}
177929088Smarkm#ifdef	SOLARIS
178029088Smarkm	else {
178129088Smarkm		char **p;
178229088Smarkm
178329088Smarkm		argv = addarg(argv, "");	/* no login name */
178429088Smarkm		for (p = environ; *p; p++) {
178529088Smarkm			argv = addarg(argv, *p);
178629088Smarkm		}
178729088Smarkm	}
178829088Smarkm#endif	/* SOLARIS */
178929088Smarkm#if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
179029088Smarkm	if (pty > 2)
179129088Smarkm		close(pty);
179229088Smarkm#endif
179329088Smarkm	closelog();
179429088Smarkm
179529181Smarkm	if (altlogin == NULL) {
179629181Smarkm		altlogin = _PATH_LOGIN;
179729181Smarkm	}
179829181Smarkm	execv(altlogin, argv);
179929181Smarkm
180031622Scharnier	syslog(LOG_ERR, "%s: %m", altlogin);
180129181Smarkm	fatalperror(net, altlogin);
180229088Smarkm	/*NOTREACHED*/
180329088Smarkm}
180429088Smarkm
180529088Smarkm	char **
180629088Smarkmaddarg(argv, val)
180729088Smarkm	register char **argv;
180829088Smarkm	register char *val;
180929088Smarkm{
181029088Smarkm	register char **cpp;
181129088Smarkm
181229088Smarkm	if (argv == NULL) {
181329088Smarkm		/*
181429088Smarkm		 * 10 entries, a leading length, and a null
181529088Smarkm		 */
181629088Smarkm		argv = (char **)malloc(sizeof(*argv) * 12);
181729088Smarkm		if (argv == NULL)
181829088Smarkm			return(NULL);
181929088Smarkm		*argv++ = (char *)10;
182029088Smarkm		*argv = (char *)0;
182129088Smarkm	}
182229088Smarkm	for (cpp = argv; *cpp; cpp++)
182329088Smarkm		;
182429088Smarkm	if (cpp == &argv[(int)argv[-1]]) {
182529088Smarkm		--argv;
182629088Smarkm		*argv = (char *)((int)(*argv) + 10);
182729088Smarkm		argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
182829088Smarkm		if (argv == NULL)
182929088Smarkm			return(NULL);
183029088Smarkm		argv++;
183129088Smarkm		cpp = &argv[(int)argv[-1] - 10];
183229088Smarkm	}
183329088Smarkm	*cpp++ = val;
183429088Smarkm	*cpp = 0;
183529088Smarkm	return(argv);
183629088Smarkm}
183729088Smarkm#endif	/* NEWINIT */
183829088Smarkm
183929088Smarkm/*
184029088Smarkm * scrub_env()
184129088Smarkm *
184269825Sassar * We only accept the environment variables listed below.
184329088Smarkm */
184429181Smarkm	void
184529088Smarkmscrub_env()
184629088Smarkm{
184769825Sassar	static const char *reject[] = {
184869825Sassar		"TERMCAP=/",
184969825Sassar		NULL
185069825Sassar	};
185129088Smarkm
185269825Sassar	static const char *accept[] = {
185369825Sassar		"XAUTH=", "XAUTHORITY=", "DISPLAY=",
185469825Sassar		"TERM=",
185569825Sassar		"EDITOR=",
185669825Sassar		"PAGER=",
185769825Sassar		"LOGNAME=",
185869825Sassar		"POSIXLY_CORRECT=",
185969825Sassar		"PRINTER=",
186069825Sassar		NULL
186169825Sassar	};
186269825Sassar
186369825Sassar	char **cpp, **cpp2;
186469825Sassar	const char **p;
186569825Sassar
186669825Sassar 	for (cpp2 = cpp = environ; *cpp; cpp++) {
186769825Sassar		int reject_it = 0;
186869825Sassar
186969825Sassar		for(p = reject; *p; p++)
187069825Sassar			if(strncmp(*cpp, *p, strlen(*p)) == 0) {
187169825Sassar				reject_it = 1;
187269825Sassar				break;
187369825Sassar			}
187469825Sassar		if (reject_it)
187569825Sassar			continue;
187669825Sassar
187769825Sassar		for(p = accept; *p; p++)
187869825Sassar			if(strncmp(*cpp, *p, strlen(*p)) == 0)
187969825Sassar				break;
188069825Sassar		if(*p != NULL)
188169825Sassar 			*cpp2++ = *cpp;
188269825Sassar 	}
188369825Sassar	*cpp2 = NULL;
188429088Smarkm}
188529088Smarkm
188629088Smarkm/*
188729088Smarkm * cleanup()
188829088Smarkm *
188929088Smarkm * This is the routine to call when we are all through, to
189029088Smarkm * clean up anything that needs to be cleaned up.
189129088Smarkm */
189229088Smarkm	/* ARGSUSED */
189329088Smarkm	void
189429088Smarkmcleanup(sig)
189529088Smarkm	int sig;
189629088Smarkm{
189729088Smarkm#ifndef	PARENT_DOES_UTMP
189829088Smarkm# if (BSD > 43) || defined(convex)
189929088Smarkm	char *p;
190029088Smarkm
190129088Smarkm	p = line + sizeof("/dev/") - 1;
190229088Smarkm	if (logout(p))
190329088Smarkm		logwtmp(p, "", "");
190429088Smarkm	(void)chmod(line, 0666);
190529088Smarkm	(void)chown(line, 0, 0);
190629088Smarkm	*p = 'p';
190729088Smarkm	(void)chmod(line, 0666);
190829088Smarkm	(void)chown(line, 0, 0);
190929088Smarkm	(void) shutdown(net, 2);
191029088Smarkm	exit(1);
191129088Smarkm# else
191229088Smarkm	void rmut();
191329088Smarkm
191429088Smarkm	rmut();
191529088Smarkm	vhangup();	/* XXX */
191629088Smarkm	(void) shutdown(net, 2);
191729088Smarkm	exit(1);
191829088Smarkm# endif
191929088Smarkm#else	/* PARENT_DOES_UTMP */
192029088Smarkm# ifdef	NEWINIT
192129088Smarkm	(void) shutdown(net, 2);
192229088Smarkm	exit(1);
192329088Smarkm# else	/* NEWINIT */
192429088Smarkm#  ifdef CRAY
192529088Smarkm	static int incleanup = 0;
192629088Smarkm	register int t;
192729088Smarkm	int child_status; /* status of child process as returned by waitpid */
192829088Smarkm	int flags = WNOHANG|WUNTRACED;
192929088Smarkm
193029088Smarkm	/*
193129088Smarkm	 * 1: Pick up the zombie, if we are being called
193229088Smarkm	 *    as the signal handler.
193329088Smarkm	 * 2: If we are a nested cleanup(), return.
193429088Smarkm	 * 3: Try to clean up TMPDIR.
193529088Smarkm	 * 4: Fill in utmp with shutdown of process.
193629088Smarkm	 * 5: Close down the network and pty connections.
193729088Smarkm	 * 6: Finish up the TMPDIR cleanup, if needed.
193829088Smarkm	 */
193929088Smarkm	if (sig == SIGCHLD) {
194029088Smarkm		while (waitpid(-1, &child_status, flags) > 0)
194129088Smarkm			;	/* VOID */
194229088Smarkm		/* Check if the child process was stopped
194329088Smarkm		 * rather than exited.  We want cleanup only if
194429088Smarkm		 * the child has died.
194529088Smarkm		 */
194629088Smarkm		if (WIFSTOPPED(child_status)) {
194729088Smarkm			return;
194829088Smarkm		}
194929088Smarkm	}
195029088Smarkm	t = sigblock(sigmask(SIGCHLD));
195129088Smarkm	if (incleanup) {
195229088Smarkm		sigsetmask(t);
195329088Smarkm		return;
195429088Smarkm	}
195529088Smarkm	incleanup = 1;
195629088Smarkm	sigsetmask(t);
195729088Smarkm#ifdef	UNICOS7x
195829088Smarkm	if (secflag) {
195929088Smarkm		/*
196029088Smarkm		 *	We need to set ourselves back to a null
196129088Smarkm		 *	label to clean up.
196229088Smarkm		 */
196329088Smarkm
196429088Smarkm		setulvl(sysv.sy_minlvl);
196529088Smarkm		setucmp((long)0);
196629088Smarkm	}
196729088Smarkm#endif	/* UNICOS7x */
196829088Smarkm
196929088Smarkm	t = cleantmp(&wtmp);
197029088Smarkm	setutent();	/* just to make sure */
197129088Smarkm#  endif /* CRAY */
197229088Smarkm	rmut(line);
197329088Smarkm	close(pty);
197429088Smarkm	(void) shutdown(net, 2);
197529088Smarkm#  ifdef CRAY
197629088Smarkm	if (t == 0)
197729088Smarkm		cleantmp(&wtmp);
197829088Smarkm#  endif /* CRAY */
197929088Smarkm	exit(1);
198029088Smarkm# endif	/* NEWINT */
198129088Smarkm#endif	/* PARENT_DOES_UTMP */
198229088Smarkm}
198329088Smarkm
198429088Smarkm#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
198529088Smarkm/*
198629088Smarkm * _utmp_sig_rcv
198729088Smarkm * utmp_sig_init
198829088Smarkm * utmp_sig_wait
198929088Smarkm *	These three functions are used to coordinate the handling of
199029088Smarkm *	the utmp file between the server and the soon-to-be-login shell.
199129088Smarkm *	The server actually creates the utmp structure, the child calls
199229088Smarkm *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
199329088Smarkm *	signals the future-login shell to proceed.
199429088Smarkm */
199529088Smarkmstatic int caught=0;		/* NZ when signal intercepted */
199629088Smarkmstatic void (*func)();		/* address of previous handler */
199729088Smarkm
199829088Smarkm	void
199929088Smarkm_utmp_sig_rcv(sig)
200029088Smarkm	int sig;
200129088Smarkm{
200229088Smarkm	caught = 1;
200329088Smarkm	(void) signal(SIGUSR1, func);
200429088Smarkm}
200529088Smarkm
200629088Smarkm	void
200729088Smarkmutmp_sig_init()
200829088Smarkm{
200929088Smarkm	/*
201029088Smarkm	 * register signal handler for UTMP creation
201129088Smarkm	 */
201229088Smarkm	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
201329088Smarkm		fatalperror(net, "telnetd/signal");
201429088Smarkm}
201529088Smarkm
201629088Smarkm	void
201729088Smarkmutmp_sig_reset()
201829088Smarkm{
201929088Smarkm	(void) signal(SIGUSR1, func);	/* reset handler to default */
202029088Smarkm}
202129088Smarkm
202229088Smarkm# ifdef __hpux
202329088Smarkm# define sigoff() /* do nothing */
202429088Smarkm# define sigon() /* do nothing */
202529088Smarkm# endif
202629088Smarkm
202729088Smarkm	void
202829088Smarkmutmp_sig_wait()
202929088Smarkm{
203029088Smarkm	/*
203129088Smarkm	 * Wait for parent to write our utmp entry.
203229088Smarkm	 */
203329088Smarkm	sigoff();
203429088Smarkm	while (caught == 0) {
203529088Smarkm		pause();	/* wait until we get a signal (sigon) */
203629088Smarkm		sigoff();	/* turn off signals while we check caught */
203729088Smarkm	}
203829088Smarkm	sigon();		/* turn on signals again */
203929088Smarkm}
204029088Smarkm
204129088Smarkm	void
204229088Smarkmutmp_sig_notify(pid)
204329088Smarkm{
204429088Smarkm	kill(pid, SIGUSR1);
204529088Smarkm}
204629088Smarkm
204729088Smarkm# ifdef CRAY
204829088Smarkmstatic int gotsigjob = 0;
204929088Smarkm
205029088Smarkm	/*ARGSUSED*/
205129088Smarkm	void
205229088Smarkmsigjob(sig)
205329088Smarkm	int sig;
205429088Smarkm{
205529088Smarkm	register int jid;
205629088Smarkm	register struct jobtemp *jp;
205729088Smarkm
205829088Smarkm	while ((jid = waitjob(NULL)) != -1) {
205929088Smarkm		if (jid == 0) {
206029088Smarkm			return;
206129088Smarkm		}
206229088Smarkm		gotsigjob++;
206329088Smarkm		jobend(jid, NULL, NULL);
206429088Smarkm	}
206529088Smarkm}
206629088Smarkm
206729088Smarkm/*
206829088Smarkm *	jid_getutid:
206929088Smarkm *		called by jobend() before calling cleantmp()
207029088Smarkm *		to find the correct $TMPDIR to cleanup.
207129088Smarkm */
207229088Smarkm
207329088Smarkm	struct utmp *
207429088Smarkmjid_getutid(jid)
207529088Smarkm	int jid;
207629088Smarkm{
207729088Smarkm	struct utmp *cur = NULL;
207829088Smarkm
207929088Smarkm	setutent();	/* just to make sure */
208029088Smarkm	while (cur = getutent()) {
208129088Smarkm		if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
208229088Smarkm			return(cur);
208329088Smarkm		}
208429088Smarkm	}
208529088Smarkm
208629088Smarkm	return(0);
208729088Smarkm}
208829088Smarkm
208929088Smarkm/*
209029088Smarkm * Clean up the TMPDIR that login created.
209129088Smarkm * The first time this is called we pick up the info
209229088Smarkm * from the utmp.  If the job has already gone away,
209329088Smarkm * then we'll clean up and be done.  If not, then
209429088Smarkm * when this is called the second time it will wait
209529088Smarkm * for the signal that the job is done.
209629088Smarkm */
209729088Smarkm	int
209829088Smarkmcleantmp(wtp)
209929088Smarkm	register struct utmp *wtp;
210029088Smarkm{
210129088Smarkm	struct utmp *utp;
210229088Smarkm	static int first = 1;
210329088Smarkm	register int mask, omask, ret;
210429088Smarkm	extern struct utmp *getutid P((const struct utmp *_Id));
210529088Smarkm
210629088Smarkm
210729088Smarkm	mask = sigmask(WJSIGNAL);
210829088Smarkm
210929088Smarkm	if (first == 0) {
211029088Smarkm		omask = sigblock(mask);
211129088Smarkm		while (gotsigjob == 0)
211229088Smarkm			sigpause(omask);
211329088Smarkm		return(1);
211429088Smarkm	}
211529088Smarkm	first = 0;
211629088Smarkm	setutent();	/* just to make sure */
211729088Smarkm
211829088Smarkm	utp = getutid(wtp);
211929088Smarkm	if (utp == 0) {
212031622Scharnier		syslog(LOG_ERR, "can't get /etc/utmp entry to clean TMPDIR");
212129088Smarkm		return(-1);
212229088Smarkm	}
212329088Smarkm	/*
212429088Smarkm	 * Nothing to clean up if the user shell was never started.
212529088Smarkm	 */
212629088Smarkm	if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
212729088Smarkm		return(1);
212829088Smarkm
212929088Smarkm	/*
213029088Smarkm	 * Block the WJSIGNAL while we are in jobend().
213129088Smarkm	 */
213229088Smarkm	omask = sigblock(mask);
213329088Smarkm	ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
213429088Smarkm	sigsetmask(omask);
213529088Smarkm	return(ret);
213629088Smarkm}
213729088Smarkm
213829088Smarkm	int
213929088Smarkmjobend(jid, path, user)
214029088Smarkm	register int jid;
214129088Smarkm	register char *path;
214229088Smarkm	register char *user;
214329088Smarkm{
214429088Smarkm	static int saved_jid = 0;
214529088Smarkm	static int pty_saved_jid = 0;
214629088Smarkm	static char saved_path[sizeof(wtmp.ut_tpath)+1];
214729088Smarkm	static char saved_user[sizeof(wtmp.ut_user)+1];
214829088Smarkm
214929088Smarkm	/*
215029088Smarkm	 * this little piece of code comes into play
215129088Smarkm	 * only when ptyreconnect is used to reconnect
215229088Smarkm	 * to an previous session.
215329088Smarkm	 *
215429088Smarkm	 * this is the only time when the
215529088Smarkm	 * "saved_jid != jid" code is executed.
215629088Smarkm	 */
215729088Smarkm
215829088Smarkm	if ( saved_jid && saved_jid != jid ) {
215929088Smarkm		if (!path) {	/* called from signal handler */
216029088Smarkm			pty_saved_jid = jid;
216129088Smarkm		} else {
216229088Smarkm			pty_saved_jid = saved_jid;
216329088Smarkm		}
216429088Smarkm	}
216529088Smarkm
216629088Smarkm	if (path) {
216729088Smarkm		strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
216829088Smarkm		strncpy(saved_user, user, sizeof(wtmp.ut_user));
216929088Smarkm		saved_path[sizeof(saved_path)] = '\0';
217029088Smarkm		saved_user[sizeof(saved_user)] = '\0';
217129088Smarkm	}
217229088Smarkm	if (saved_jid == 0) {
217329088Smarkm		saved_jid = jid;
217429088Smarkm		return(0);
217529088Smarkm	}
217629088Smarkm
217729088Smarkm	/* if the jid has changed, get the correct entry from the utmp file */
217829088Smarkm
217929088Smarkm	if ( saved_jid != jid ) {
218029088Smarkm		struct utmp *utp = NULL;
218129088Smarkm		struct utmp *jid_getutid();
218229088Smarkm
218329088Smarkm		utp = jid_getutid(pty_saved_jid);
218429088Smarkm
218529088Smarkm		if (utp == 0) {
218629088Smarkm			syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
218729088Smarkm			return(-1);
218829088Smarkm		}
218929088Smarkm
219029088Smarkm		cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
219129088Smarkm		return(1);
219229088Smarkm	}
219329088Smarkm
219429088Smarkm	cleantmpdir(jid, saved_path, saved_user);
219529088Smarkm	return(1);
219629088Smarkm}
219729088Smarkm
219829088Smarkm/*
219929088Smarkm * Fork a child process to clean up the TMPDIR
220029088Smarkm */
220129088Smarkmcleantmpdir(jid, tpath, user)
220229088Smarkm	register int jid;
220329088Smarkm	register char *tpath;
220429088Smarkm	register char *user;
220529088Smarkm{
220629088Smarkm	switch(fork()) {
220729088Smarkm	case -1:
220831622Scharnier		syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m",
220929088Smarkm							tpath);
221029088Smarkm		break;
221129088Smarkm	case 0:
221229088Smarkm		execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
221331622Scharnier		syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m",
221429088Smarkm							tpath, CLEANTMPCMD);
221529088Smarkm		exit(1);
221629088Smarkm	default:
221729088Smarkm		/*
221829088Smarkm		 * Forget about child.  We will exit, and
221929088Smarkm		 * /etc/init will pick it up.
222029088Smarkm		 */
222129088Smarkm		break;
222229088Smarkm	}
222329088Smarkm}
222429088Smarkm# endif /* CRAY */
222529088Smarkm#endif	/* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
222629088Smarkm
222729088Smarkm/*
222829088Smarkm * rmut()
222929088Smarkm *
223029088Smarkm * This is the function called by cleanup() to
223129088Smarkm * remove the utmp entry for this person.
223229088Smarkm */
223329088Smarkm
223429088Smarkm#ifdef	UTMPX
223529088Smarkm	void
223629088Smarkmrmut()
223729088Smarkm{
223829088Smarkm	register f;
223929088Smarkm	int found = 0;
224029088Smarkm	struct utmp *u, *utmp;
224129088Smarkm	int nutmp;
224229088Smarkm	struct stat statbf;
224329088Smarkm
224429088Smarkm	struct utmpx *utxp, utmpx;
224529088Smarkm
224629088Smarkm	/*
224729088Smarkm	 * This updates the utmpx and utmp entries and make a wtmp/x entry
224829088Smarkm	 */
224929088Smarkm
225029088Smarkm	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
225129088Smarkm	utxp = getutxline(&utmpx);
225229088Smarkm	if (utxp) {
225329088Smarkm		utxp->ut_type = DEAD_PROCESS;
225429088Smarkm		utxp->ut_exit.e_termination = 0;
225529088Smarkm		utxp->ut_exit.e_exit = 0;
225629088Smarkm		(void) time(&utmpx.ut_tv.tv_sec);
225729088Smarkm		utmpx.ut_tv.tv_usec = 0;
225829088Smarkm		modutx(utxp);
225929088Smarkm	}
226029088Smarkm	endutxent();
226129088Smarkm}  /* end of rmut */
226229088Smarkm#endif
226329088Smarkm
226429088Smarkm#if	!defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
226529088Smarkm	void
226629088Smarkmrmut()
226729088Smarkm{
226829088Smarkm	register f;
226929088Smarkm	int found = 0;
227029088Smarkm	struct utmp *u, *utmp;
227129088Smarkm	int nutmp;
227229088Smarkm	struct stat statbf;
227329088Smarkm
227429088Smarkm	f = open(utmpf, O_RDWR);
227529088Smarkm	if (f >= 0) {
227629088Smarkm		(void) fstat(f, &statbf);
227729088Smarkm		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
227829088Smarkm		if (!utmp)
227929088Smarkm			syslog(LOG_ERR, "utmp malloc failed");
228029088Smarkm		if (statbf.st_size && utmp) {
228129088Smarkm			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
228229088Smarkm			nutmp /= sizeof(struct utmp);
228329088Smarkm
228429088Smarkm			for (u = utmp ; u < &utmp[nutmp] ; u++) {
228529088Smarkm				if (SCMPN(u->ut_line, line+5) ||
228629088Smarkm				    u->ut_name[0]==0)
228729088Smarkm					continue;
228829088Smarkm				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
228929088Smarkm				SCPYN(u->ut_name, "");
229029088Smarkm				SCPYN(u->ut_host, "");
229129088Smarkm				(void) time(&u->ut_time);
229229088Smarkm				(void) write(f, (char *)u, sizeof(wtmp));
229329088Smarkm				found++;
229429088Smarkm			}
229529088Smarkm		}
229629088Smarkm		(void) close(f);
229729088Smarkm	}
229829088Smarkm	if (found) {
229929088Smarkm		f = open(wtmpf, O_WRONLY|O_APPEND);
230029088Smarkm		if (f >= 0) {
230129088Smarkm			SCPYN(wtmp.ut_line, line+5);
230229088Smarkm			SCPYN(wtmp.ut_name, "");
230329088Smarkm			SCPYN(wtmp.ut_host, "");
230429088Smarkm			(void) time(&wtmp.ut_time);
230529088Smarkm			(void) write(f, (char *)&wtmp, sizeof(wtmp));
230629088Smarkm			(void) close(f);
230729088Smarkm		}
230829088Smarkm	}
230929088Smarkm	(void) chmod(line, 0666);
231029088Smarkm	(void) chown(line, 0, 0);
231129088Smarkm	line[strlen("/dev/")] = 'p';
231229088Smarkm	(void) chmod(line, 0666);
231329088Smarkm	(void) chown(line, 0, 0);
231429088Smarkm}  /* end of rmut */
231529088Smarkm#endif	/* CRAY */
231629088Smarkm
231729088Smarkm#ifdef __hpux
231829088Smarkmrmut (line)
231929088Smarkmchar *line;
232029088Smarkm{
232129088Smarkm	struct utmp utmp;
232229088Smarkm	struct utmp *utptr;
232329088Smarkm	int fd;			/* for /etc/wtmp */
232429088Smarkm
232529088Smarkm	utmp.ut_type = USER_PROCESS;
232629088Smarkm	(void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
232729088Smarkm	(void) setutent();
232829088Smarkm	utptr = getutid(&utmp);
232929088Smarkm	/* write it out only if it exists */
233029088Smarkm	if (utptr) {
233129088Smarkm		utptr->ut_type = DEAD_PROCESS;
233229088Smarkm		utptr->ut_time = time((long *) 0);
233329088Smarkm		(void) pututline(utptr);
233429088Smarkm		/* set wtmp entry if wtmp file exists */
233529088Smarkm		if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
233629088Smarkm			(void) write(fd, utptr, sizeof(utmp));
233729088Smarkm			(void) close(fd);
233829088Smarkm		}
233929088Smarkm	}
234029088Smarkm	(void) endutent();
234129088Smarkm
234229088Smarkm	(void) chmod(line, 0666);
234329088Smarkm	(void) chown(line, 0, 0);
234429088Smarkm	line[14] = line[13];
234529088Smarkm	line[13] = line[12];
234629088Smarkm	line[8] = 'm';
234729088Smarkm	line[9] = '/';
234829088Smarkm	line[10] = 'p';
234929088Smarkm	line[11] = 't';
235029088Smarkm	line[12] = 'y';
235129088Smarkm	(void) chmod(line, 0666);
235229088Smarkm	(void) chown(line, 0, 0);
235329088Smarkm}
235429088Smarkm#endif
2355