xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 60151)
138905Sborman /*
238905Sborman  * Copyright (c) 1989 Regents of the University of California.
338905Sborman  * All rights reserved.
438905Sborman  *
542673Sbostic  * %sccs.include.redist.c%
638905Sborman  */
738905Sborman 
838905Sborman #ifndef lint
9*60151Sdab static char sccsid[] = "@(#)sys_term.c	5.22 (Berkeley) 05/20/93";
1038905Sborman #endif /* not lint */
1138905Sborman 
1238905Sborman #include "telnetd.h"
1338905Sborman #include "pathnames.h"
1438905Sborman 
1557212Sdab #if	defined(AUTHENTICATION)
1646809Sdab #include <libtelnet/auth.h>
1746809Sdab #endif
1846809Sdab 
19*60151Sdab #if defined(CRAY) || defined(__hpux)
20*60151Sdab # define PARENT_DOES_UTMP
21*60151Sdab #endif
22*60151Sdab 
2338905Sborman #ifdef	NEWINIT
2438905Sborman #include <initreq.h>
25*60151Sdab int	utmp_len = MAXHOSTNAMELEN;	/* sizeof(init_request.host) */
2638905Sborman #else	/* NEWINIT*/
2757212Sdab # ifdef	UTMPX
2857212Sdab # include <utmpx.h>
2957212Sdab # else
3057212Sdab # include <utmp.h>
3157212Sdab # endif /* UTMPX */
3238905Sborman struct	utmp wtmp;
3338905Sborman 
3457212Sdab int	utmp_len = sizeof(wtmp.ut_host);
35*60151Sdab # ifndef PARENT_DOES_UTMP
3638905Sborman char	wtmpf[]	= "/usr/adm/wtmp";
3738905Sborman char	utmpf[] = "/etc/utmp";
38*60151Sdab # else /* PARENT_DOES_UTMP */
3938905Sborman char	wtmpf[]	= "/etc/wtmp";
40*60151Sdab # endif /* PARENT_DOES_UTMP */
41*60151Sdab 
42*60151Sdab # ifdef CRAY
4346809Sdab #include <tmpdir.h>
4446809Sdab #include <sys/wait.h>
45*60151Sdab #  if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY)
46*60151Sdab    /*
47*60151Sdab     * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can
48*60151Sdab     * use it to tell us to turn off all the socket security code,
49*60151Sdab     * since that is only used in UNICOS 7.0 and later.
50*60151Sdab     */
51*60151Sdab #   undef _SC_CRAY_SECURE_SYS
52*60151Sdab #  endif
53*60151Sdab 
5457212Sdab #  if defined(_SC_CRAY_SECURE_SYS)
5557212Sdab #include <sys/sysv.h>
5657212Sdab #include <sys/secstat.h>
5757212Sdab extern int secflag;
5857212Sdab extern struct sysv sysv;
5957212Sdab #  endif /* _SC_CRAY_SECURE_SYS */
6038905Sborman # endif	/* CRAY */
6138905Sborman #endif	/* NEWINIT */
6238905Sborman 
6357212Sdab #ifdef	STREAMSPTY
6457212Sdab #include <sac.h>
6557212Sdab #include <sys/stropts.h>
6657212Sdab #endif
6757212Sdab 
6838905Sborman #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
6938905Sborman #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
7038905Sborman 
7144364Sborman #ifdef	STREAMS
7244364Sborman #include <sys/stream.h>
7344364Sborman #endif
74*60151Sdab #ifdef __hpux
75*60151Sdab #include <sys/resource.h>
76*60151Sdab #include <sys/proc.h>
77*60151Sdab #endif
7838905Sborman #include <sys/tty.h>
7938905Sborman #ifdef	t_erase
8038905Sborman #undef	t_erase
8138905Sborman #undef	t_kill
8238905Sborman #undef	t_intrc
8338905Sborman #undef	t_quitc
8438905Sborman #undef	t_startc
8538905Sborman #undef	t_stopc
8638905Sborman #undef	t_eofc
8738905Sborman #undef	t_brkc
8838905Sborman #undef	t_suspc
8938905Sborman #undef	t_dsuspc
9038905Sborman #undef	t_rprntc
9138905Sborman #undef	t_flushc
9238905Sborman #undef	t_werasc
9338905Sborman #undef	t_lnextc
9438905Sborman #endif
9538905Sborman 
9644364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
9744364Sborman # define EXTPROC 0400
9844364Sborman #endif
9944364Sborman 
10038905Sborman #ifndef	USE_TERMIO
10138905Sborman struct termbuf {
10238905Sborman 	struct sgttyb sg;
10338905Sborman 	struct tchars tc;
10438905Sborman 	struct ltchars ltc;
10538905Sborman 	int state;
10638905Sborman 	int lflags;
10738905Sborman } termbuf, termbuf2;
10845234Sborman # define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
10945234Sborman # define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
11046809Sdab # define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
11146809Sdab # define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
11238905Sborman #else	/* USE_TERMIO */
11338905Sborman # ifdef	SYSV_TERMIO
11438905Sborman #	define termios termio
11538905Sborman # endif
11645234Sborman # ifndef	TCSANOW
11744364Sborman #  ifdef TCSETS
11845234Sborman #   define	TCSANOW		TCSETS
11945234Sborman #   define	TCSADRAIN	TCSETSW
12046809Sdab #   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
12144364Sborman #  else
12245234Sborman #   ifdef TCSETA
12345234Sborman #    define	TCSANOW		TCSETA
12445234Sborman #    define	TCSADRAIN	TCSETAW
12546809Sdab #    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
12645234Sborman #   else
12745234Sborman #    define	TCSANOW		TIOCSETA
12845234Sborman #    define	TCSADRAIN	TIOCSETAW
12946809Sdab #    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
13045234Sborman #   endif
13144364Sborman #  endif
13245234Sborman #  define	tcsetattr(f, a, t)	ioctl(f, a, t)
13345234Sborman #  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
13445234Sborman 					(tp)->c_cflag |= (val)
13546809Sdab #  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
13645234Sborman #  ifdef CIBAUD
13745234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
13845234Sborman 					(tp)->c_cflag |= ((val)<<IBSHIFT)
13946809Sdab #   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
14045234Sborman #  else
14145234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
14245234Sborman 					(tp)->c_cflag |= (val)
14346809Sdab #   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
14445234Sborman #  endif
14545234Sborman # endif /* TCSANOW */
14638905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
14757592Sdab # ifdef  STREAMSPTY
14857212Sdab int ttyfd = -1;
14957592Sdab # endif
15038905Sborman #endif	/* USE_TERMIO */
15138905Sborman 
15238905Sborman /*
15338905Sborman  * init_termbuf()
15438905Sborman  * copy_termbuf(cp)
15538905Sborman  * set_termbuf()
15638905Sborman  *
15738905Sborman  * These three routines are used to get and set the "termbuf" structure
15838905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
15938905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
16038905Sborman  * set_termbuf() writes the structure into the kernel.
16138905Sborman  */
16238905Sborman 
16346809Sdab 	void
16438905Sborman init_termbuf()
16538905Sborman {
16638905Sborman #ifndef	USE_TERMIO
16738905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
16838905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
16938905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
17038905Sborman # ifdef	TIOCGSTATE
17138905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
17238905Sborman # endif
17338905Sborman #else
17457592Sdab # ifdef  STREAMSPTY
17557212Sdab 	(void) tcgetattr(ttyfd, &termbuf);
17657592Sdab # else
17757592Sdab 	(void) tcgetattr(pty, &termbuf);
17857592Sdab # endif
17938905Sborman #endif
18038905Sborman 	termbuf2 = termbuf;
18138905Sborman }
18238905Sborman 
18338905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
18446809Sdab 	void
18538905Sborman copy_termbuf(cp, len)
18646809Sdab 	char *cp;
18746809Sdab 	int len;
18838905Sborman {
18938905Sborman 	if (len > sizeof(termbuf))
19038905Sborman 		len = sizeof(termbuf);
19138905Sborman 	bcopy(cp, (char *)&termbuf, len);
19238905Sborman 	termbuf2 = termbuf;
19338905Sborman }
19438905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
19538905Sborman 
19646809Sdab 	void
19738905Sborman set_termbuf()
19838905Sborman {
19938905Sborman 	/*
20038905Sborman 	 * Only make the necessary changes.
20138905Sborman 	 */
20238905Sborman #ifndef	USE_TERMIO
20338905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
20445234Sborman 		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
20538905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
20638905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
20738905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
20838905Sborman 							sizeof(termbuf.ltc)))
20938905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
21038905Sborman 	if (termbuf.lflags != termbuf2.lflags)
21138905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
21238905Sborman #else	/* USE_TERMIO */
21338905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
21457592Sdab # ifdef  STREAMSPTY
21557212Sdab 		(void) tcsetattr(ttyfd, TCSANOW, &termbuf);
21657592Sdab # else
21757592Sdab 		(void) tcsetattr(pty, TCSANOW, &termbuf);
21857592Sdab # endif
21957212Sdab # if	defined(CRAY2) && defined(UNICOS5)
22038905Sborman 	needtermstat = 1;
22138905Sborman # endif
22238905Sborman #endif	/* USE_TERMIO */
22338905Sborman }
22438905Sborman 
22538905Sborman 
22638905Sborman /*
22738905Sborman  * spcset(func, valp, valpp)
22838905Sborman  *
22938905Sborman  * This function takes various special characters (func), and
23038905Sborman  * sets *valp to the current value of that character, and
23138905Sborman  * *valpp to point to where in the "termbuf" structure that
23238905Sborman  * value is kept.
23338905Sborman  *
23438905Sborman  * It returns the SLC_ level of support for this function.
23538905Sborman  */
23638905Sborman 
23738905Sborman #ifndef	USE_TERMIO
23846809Sdab 	int
23938905Sborman spcset(func, valp, valpp)
24046809Sdab 	int func;
24146809Sdab 	cc_t *valp;
24246809Sdab 	cc_t **valpp;
24338905Sborman {
24438905Sborman 	switch(func) {
24538905Sborman 	case SLC_EOF:
24638905Sborman 		*valp = termbuf.tc.t_eofc;
24740242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
24838905Sborman 		return(SLC_VARIABLE);
24938905Sborman 	case SLC_EC:
25038905Sborman 		*valp = termbuf.sg.sg_erase;
25140242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
25238905Sborman 		return(SLC_VARIABLE);
25338905Sborman 	case SLC_EL:
25438905Sborman 		*valp = termbuf.sg.sg_kill;
25540242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
25638905Sborman 		return(SLC_VARIABLE);
25738905Sborman 	case SLC_IP:
25838905Sborman 		*valp = termbuf.tc.t_intrc;
25940242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
26038905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
26138905Sborman 	case SLC_ABORT:
26238905Sborman 		*valp = termbuf.tc.t_quitc;
26340242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
26438905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
26538905Sborman 	case SLC_XON:
26638905Sborman 		*valp = termbuf.tc.t_startc;
26740242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
26838905Sborman 		return(SLC_VARIABLE);
26938905Sborman 	case SLC_XOFF:
27038905Sborman 		*valp = termbuf.tc.t_stopc;
27140242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
27238905Sborman 		return(SLC_VARIABLE);
27338905Sborman 	case SLC_AO:
27438905Sborman 		*valp = termbuf.ltc.t_flushc;
27540242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
27638905Sborman 		return(SLC_VARIABLE);
27738905Sborman 	case SLC_SUSP:
27838905Sborman 		*valp = termbuf.ltc.t_suspc;
27940242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
28038905Sborman 		return(SLC_VARIABLE);
28138905Sborman 	case SLC_EW:
28238905Sborman 		*valp = termbuf.ltc.t_werasc;
28340242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
28438905Sborman 		return(SLC_VARIABLE);
28538905Sborman 	case SLC_RP:
28638905Sborman 		*valp = termbuf.ltc.t_rprntc;
28740242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
28838905Sborman 		return(SLC_VARIABLE);
28938905Sborman 	case SLC_LNEXT:
29038905Sborman 		*valp = termbuf.ltc.t_lnextc;
29140242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
29238905Sborman 		return(SLC_VARIABLE);
29340242Sborman 	case SLC_FORW1:
29440242Sborman 		*valp = termbuf.tc.t_brkc;
29540242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
29640242Sborman 		return(SLC_VARIABLE);
29738905Sborman 	case SLC_BRK:
29838905Sborman 	case SLC_SYNCH:
29938905Sborman 	case SLC_AYT:
30038905Sborman 	case SLC_EOR:
30140242Sborman 		*valp = (cc_t)0;
30240242Sborman 		*valpp = (cc_t *)0;
30338905Sborman 		return(SLC_DEFAULT);
30438905Sborman 	default:
30540242Sborman 		*valp = (cc_t)0;
30640242Sborman 		*valpp = (cc_t *)0;
30738905Sborman 		return(SLC_NOSUPPORT);
30838905Sborman 	}
30938905Sborman }
31038905Sborman 
31138905Sborman #else	/* USE_TERMIO */
31238905Sborman 
31346809Sdab 	int
31438905Sborman spcset(func, valp, valpp)
31546809Sdab 	int func;
31646809Sdab 	cc_t *valp;
31746809Sdab 	cc_t **valpp;
31838905Sborman {
31939503Sborman 
32039503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
32139503Sborman 			*valpp = &termbuf.c_cc[a]; \
32239503Sborman 			return(b);
32340242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
32439503Sborman 
32538905Sborman 	switch(func) {
32638905Sborman 	case SLC_EOF:
32739503Sborman 		setval(VEOF, SLC_VARIABLE);
32838905Sborman 	case SLC_EC:
32939503Sborman 		setval(VERASE, SLC_VARIABLE);
33038905Sborman 	case SLC_EL:
33139503Sborman 		setval(VKILL, SLC_VARIABLE);
33238905Sborman 	case SLC_IP:
33339503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
33438905Sborman 	case SLC_ABORT:
33539503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
33638905Sborman 	case SLC_XON:
33739503Sborman #ifdef	VSTART
33839503Sborman 		setval(VSTART, SLC_VARIABLE);
33939503Sborman #else
34039503Sborman 		defval(0x13);
34139503Sborman #endif
34238905Sborman 	case SLC_XOFF:
34339503Sborman #ifdef	VSTOP
34439503Sborman 		setval(VSTOP, SLC_VARIABLE);
34539503Sborman #else
34639503Sborman 		defval(0x11);
34739503Sborman #endif
34838905Sborman 	case SLC_EW:
34939503Sborman #ifdef	VWERASE
35039503Sborman 		setval(VWERASE, SLC_VARIABLE);
35139503Sborman #else
35239503Sborman 		defval(0);
35339503Sborman #endif
35438905Sborman 	case SLC_RP:
35539503Sborman #ifdef	VREPRINT
35639503Sborman 		setval(VREPRINT, SLC_VARIABLE);
35739503Sborman #else
35839503Sborman 		defval(0);
35939503Sborman #endif
36038905Sborman 	case SLC_LNEXT:
36139503Sborman #ifdef	VLNEXT
36239503Sborman 		setval(VLNEXT, SLC_VARIABLE);
36339503Sborman #else
36439503Sborman 		defval(0);
36539503Sborman #endif
36639503Sborman 	case SLC_AO:
36745234Sborman #if	!defined(VDISCARD) && defined(VFLUSHO)
36845234Sborman # define VDISCARD VFLUSHO
36945234Sborman #endif
37045234Sborman #ifdef	VDISCARD
37145234Sborman 		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
37239503Sborman #else
37339503Sborman 		defval(0);
37439503Sborman #endif
37539503Sborman 	case SLC_SUSP:
37639503Sborman #ifdef	VSUSP
37739503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
37839503Sborman #else
37939503Sborman 		defval(0);
38039503Sborman #endif
38140242Sborman #ifdef	VEOL
38240242Sborman 	case SLC_FORW1:
38340242Sborman 		setval(VEOL, SLC_VARIABLE);
38440242Sborman #endif
38540242Sborman #ifdef	VEOL2
38640242Sborman 	case SLC_FORW2:
38740242Sborman 		setval(VEOL2, SLC_VARIABLE);
38840242Sborman #endif
38945234Sborman 	case SLC_AYT:
39045234Sborman #ifdef	VSTATUS
39145234Sborman 		setval(VSTATUS, SLC_VARIABLE);
39245234Sborman #else
39345234Sborman 		defval(0);
39445234Sborman #endif
39539503Sborman 
39638905Sborman 	case SLC_BRK:
39738905Sborman 	case SLC_SYNCH:
39838905Sborman 	case SLC_EOR:
39939503Sborman 		defval(0);
40039503Sborman 
40138905Sborman 	default:
40238905Sborman 		*valp = 0;
40338905Sborman 		*valpp = 0;
40438905Sborman 		return(SLC_NOSUPPORT);
40538905Sborman 	}
40638905Sborman }
40738905Sborman #endif	/* USE_TERMIO */
40838905Sborman 
40940242Sborman #ifdef CRAY
41038905Sborman /*
41140242Sborman  * getnpty()
41240242Sborman  *
41340242Sborman  * Return the number of pty's configured into the system.
41440242Sborman  */
41546809Sdab 	int
41640242Sborman getnpty()
41740242Sborman {
41840242Sborman #ifdef _SC_CRAY_NPTY
41946809Sdab 	int numptys;
42046809Sdab 
42146809Sdab 	if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
42246809Sdab 		return numptys;
42346809Sdab 	else
42440242Sborman #endif /* _SC_CRAY_NPTY */
42546809Sdab 		return 128;
42640242Sborman }
42740242Sborman #endif /* CRAY */
42840242Sborman 
42945234Sborman #ifndef	convex
43040242Sborman /*
43138905Sborman  * getpty()
43238905Sborman  *
43338905Sborman  * Allocate a pty.  As a side effect, the external character
43438905Sborman  * array "line" contains the name of the slave side.
43538905Sborman  *
43638905Sborman  * Returns the file descriptor of the opened pty.
43738905Sborman  */
43845234Sborman #ifndef	__GNUC__
43938905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44045234Sborman #else
44145234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44245234Sborman char *line = Xline;
44345234Sborman #endif
44445234Sborman #ifdef	CRAY
44545234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44645234Sborman #endif	/* CRAY */
44738905Sborman 
44846809Sdab 	int
449*60151Sdab getpty(ptynum)
450*60151Sdab int *ptynum;
45138905Sborman {
45238905Sborman 	register int p;
45357212Sdab #ifdef	STREAMSPTY
45457212Sdab 	int t;
45557212Sdab 	char *ptsname();
45657212Sdab 
45757212Sdab 	p = open("/dev/ptmx", 2);
45857212Sdab 	if (p > 0) {
45957212Sdab 		grantpt(p);
46057212Sdab 		unlockpt(p);
46157212Sdab 		strcpy(line, ptsname(p));
46257212Sdab 		return(p);
46357212Sdab 	}
46457212Sdab 
46557212Sdab #else	/* ! STREAMSPTY */
46638905Sborman #ifndef CRAY
46757212Sdab 	register char *cp, *p1, *p2;
46838905Sborman 	register int i;
46959050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
47057212Sdab 	int dummy;
47157212Sdab #endif
47238905Sborman 
473*60151Sdab #ifndef	__hpux
47438905Sborman 	(void) sprintf(line, "/dev/ptyXX");
47538905Sborman 	p1 = &line[8];
47638905Sborman 	p2 = &line[9];
477*60151Sdab #else
478*60151Sdab 	(void) sprintf(line, "/dev/ptym/ptyXX");
479*60151Sdab 	p1 = &line[13];
480*60151Sdab 	p2 = &line[14];
481*60151Sdab #endif
48238905Sborman 
48357212Sdab 	for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
48438905Sborman 		struct stat stb;
48538905Sborman 
48657212Sdab 		*p1 = *cp;
48738905Sborman 		*p2 = '0';
48857212Sdab 		/*
48957212Sdab 		 * This stat() check is just to keep us from
49057212Sdab 		 * looping through all 256 combinations if there
49157212Sdab 		 * aren't that many ptys available.
49257212Sdab 		 */
49338905Sborman 		if (stat(line, &stb) < 0)
49438905Sborman 			break;
49538905Sborman 		for (i = 0; i < 16; i++) {
49638905Sborman 			*p2 = "0123456789abcdef"[i];
49738905Sborman 			p = open(line, 2);
49838905Sborman 			if (p > 0) {
499*60151Sdab #ifndef	__hpux
50038905Sborman 				line[5] = 't';
501*60151Sdab #else
502*60151Sdab 				for (p1 = &line[8]; *p1; p1++)
503*60151Sdab 					*p1 = *(p1+1);
504*60151Sdab 				line[9] = 't';
505*60151Sdab #endif
50657212Sdab 				chown(line, 0, 0);
50757212Sdab 				chmod(line, 0600);
50859050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
50957212Sdab 				if (ioctl(p, TIOCGPGRP, &dummy) == 0
51057212Sdab 				    || errno != EIO) {
51157212Sdab 					chmod(line, 0666);
51257212Sdab 					close(p);
51357212Sdab 					line[5] = 'p';
51457212Sdab 				} else
51559050Storek #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
51657212Sdab 					return(p);
51738905Sborman 			}
51838905Sborman 		}
51938905Sborman 	}
52038905Sborman #else	/* CRAY */
52138905Sborman 	extern lowpty, highpty;
52245234Sborman 	struct stat sb;
52338905Sborman 
524*60151Sdab 	for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
525*60151Sdab 		(void) sprintf(myline, "/dev/pty/%03d", *ptynum);
52645234Sborman 		p = open(myline, 2);
52738905Sborman 		if (p < 0)
52838905Sborman 			continue;
529*60151Sdab 		(void) sprintf(line, "/dev/ttyp%03d", *ptynum);
53045234Sborman 		/*
53145234Sborman 		 * Here are some shenanigans to make sure that there
53245234Sborman 		 * are no listeners lurking on the line.
53345234Sborman 		 */
53445234Sborman 		if(stat(line, &sb) < 0) {
53545234Sborman 			(void) close(p);
53645234Sborman 			continue;
53745234Sborman 		}
53845234Sborman 		if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
53945234Sborman 			chown(line, 0, 0);
54045234Sborman 			chmod(line, 0600);
54145234Sborman 			(void)close(p);
54245234Sborman 			p = open(myline, 2);
54345234Sborman 			if (p < 0)
54445234Sborman 				continue;
54545234Sborman 		}
54645234Sborman 		/*
54745234Sborman 		 * Now it should be safe...check for accessability.
54845234Sborman 		 */
54938905Sborman 		if (access(line, 6) == 0)
55038905Sborman 			return(p);
55138905Sborman 		else {
55238905Sborman 			/* no tty side to pty so skip it */
55338905Sborman 			(void) close(p);
55438905Sborman 		}
55538905Sborman 	}
55638905Sborman #endif	/* CRAY */
55757212Sdab #endif	/* STREAMSPTY */
55838905Sborman 	return(-1);
55938905Sborman }
56045234Sborman #endif	/* convex */
56138905Sborman 
56238905Sborman #ifdef	LINEMODE
56338905Sborman /*
56438905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
56538905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
56638905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
56738905Sborman  * tty_isecho()		Find out if echoing is turned on.
56838905Sborman  * tty_setecho(on)	Enable/disable character echoing.
56938905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
57038905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
57138905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
57238905Sborman  * tty_isediting()	Find out if line editing is enabled.
57338905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
57438905Sborman  * tty_setedit(on)	Turn on/off line editing.
57538905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
57644364Sborman  * tty_issofttab()	Find out if tab expansion is enabled.
57744364Sborman  * tty_setsofttab(on)	Turn on/off soft tab expansion.
57844364Sborman  * tty_islitecho()	Find out if typed control chars are echoed literally
57944364Sborman  * tty_setlitecho()	Turn on/off literal echo of control chars
58038905Sborman  * tty_tspeed(val)	Set transmit speed to val.
58138905Sborman  * tty_rspeed(val)	Set receive speed to val.
58238905Sborman  */
58338905Sborman 
58445234Sborman #ifdef convex
58545234Sborman static int linestate;
58645234Sborman #endif
58745234Sborman 
58846809Sdab 	int
58938905Sborman tty_linemode()
59038905Sborman {
59145234Sborman #ifndef convex
59238905Sborman #ifndef	USE_TERMIO
59338905Sborman 	return(termbuf.state & TS_EXTPROC);
59438905Sborman #else
59538905Sborman 	return(termbuf.c_lflag & EXTPROC);
59638905Sborman #endif
59745234Sborman #else
59845234Sborman 	return(linestate);
59945234Sborman #endif
60038905Sborman }
60138905Sborman 
60246809Sdab 	void
60338905Sborman tty_setlinemode(on)
60446809Sdab 	int on;
60538905Sborman {
60638905Sborman #ifdef	TIOCEXT
60745234Sborman # ifndef convex
60845234Sborman 	set_termbuf();
60945234Sborman # else
61045234Sborman 	linestate = on;
61145234Sborman # endif
61238905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
61345234Sborman # ifndef convex
61445234Sborman 	init_termbuf();
61545234Sborman # endif
61638905Sborman #else	/* !TIOCEXT */
61745234Sborman # ifdef	EXTPROC
61838905Sborman 	if (on)
61938905Sborman 		termbuf.c_lflag |= EXTPROC;
62038905Sborman 	else
62138905Sborman 		termbuf.c_lflag &= ~EXTPROC;
62245234Sborman # endif
62338905Sborman #endif	/* TIOCEXT */
62438905Sborman }
62538905Sborman 
62646809Sdab 	int
62738905Sborman tty_isecho()
62838905Sborman {
62938905Sborman #ifndef USE_TERMIO
63038905Sborman 	return (termbuf.sg.sg_flags & ECHO);
63138905Sborman #else
63238905Sborman 	return (termbuf.c_lflag & ECHO);
63338905Sborman #endif
63438905Sborman }
63538905Sborman #endif	/* LINEMODE */
63638905Sborman 
63758971Sdab 	int
63858971Sdab tty_flowmode()
63958971Sdab {
64058971Sdab #ifndef USE_TERMIO
64158971Sdab 	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
64258971Sdab #else
64358971Sdab 	return((termbuf.c_iflag & IXON) ? 1 : 0);
64458971Sdab #endif
64558971Sdab }
64658971Sdab 
64758971Sdab 	int
64858971Sdab tty_restartany()
64958971Sdab {
65058971Sdab #ifndef USE_TERMIO
65158971Sdab # ifdef	DECCTQ
65258971Sdab 	return((termbuf.lflags & DECCTQ) ? 0 : 1);
65358971Sdab # else
65458971Sdab 	return(-1);
65558971Sdab # endif
65658971Sdab #else
65758971Sdab 	return((termbuf.c_iflag & IXANY) ? 1 : 0);
65858971Sdab #endif
65958971Sdab }
66058971Sdab 
66146809Sdab 	void
66238905Sborman tty_setecho(on)
66346809Sdab 	int on;
66438905Sborman {
66538905Sborman #ifndef	USE_TERMIO
66638905Sborman 	if (on)
66738905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
66838905Sborman 	else
66938905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
67038905Sborman #else
67138905Sborman 	if (on)
67238905Sborman 		termbuf.c_lflag |= ECHO;
67338905Sborman 	else
67438905Sborman 		termbuf.c_lflag &= ~ECHO;
67538905Sborman #endif
67638905Sborman }
67738905Sborman 
67838905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
67946809Sdab 	int
68038905Sborman tty_israw()
68138905Sborman {
68238905Sborman #ifndef USE_TERMIO
68338905Sborman 	return(termbuf.sg.sg_flags & RAW);
68438905Sborman #else
68538905Sborman 	return(!(termbuf.c_lflag & ICANON));
68638905Sborman #endif
68738905Sborman }
68838905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
68938905Sborman 
69046809Sdab 	void
69138905Sborman tty_binaryin(on)
69246809Sdab 	int on;
69338905Sborman {
69438905Sborman #ifndef	USE_TERMIO
69538905Sborman 	if (on)
69638905Sborman 		termbuf.lflags |= LPASS8;
69738905Sborman 	else
69838905Sborman 		termbuf.lflags &= ~LPASS8;
69938905Sborman #else
70038905Sborman 	if (on) {
70146809Sdab 		termbuf.c_iflag &= ~ISTRIP;
70238905Sborman 	} else {
70346809Sdab 		termbuf.c_iflag |= ISTRIP;
70438905Sborman 	}
70538905Sborman #endif
70638905Sborman }
70738905Sborman 
70846809Sdab 	void
70938905Sborman tty_binaryout(on)
71046809Sdab 	int on;
71138905Sborman {
71238905Sborman #ifndef	USE_TERMIO
71338905Sborman 	if (on)
71438905Sborman 		termbuf.lflags |= LLITOUT;
71538905Sborman 	else
71638905Sborman 		termbuf.lflags &= ~LLITOUT;
71738905Sborman #else
71838905Sborman 	if (on) {
71938905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
72038905Sborman 		termbuf.c_cflag |= CS8;
72138905Sborman 		termbuf.c_oflag &= ~OPOST;
72238905Sborman 	} else {
72338905Sborman 		termbuf.c_cflag &= ~CSIZE;
72438905Sborman 		termbuf.c_cflag |= CS7|PARENB;
72538905Sborman 		termbuf.c_oflag |= OPOST;
72638905Sborman 	}
72738905Sborman #endif
72838905Sborman }
72938905Sborman 
73046809Sdab 	int
73138905Sborman tty_isbinaryin()
73238905Sborman {
73338905Sborman #ifndef	USE_TERMIO
73438905Sborman 	return(termbuf.lflags & LPASS8);
73538905Sborman #else
73639503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
73738905Sborman #endif
73838905Sborman }
73938905Sborman 
74046809Sdab 	int
74138905Sborman tty_isbinaryout()
74238905Sborman {
74338905Sborman #ifndef	USE_TERMIO
74438905Sborman 	return(termbuf.lflags & LLITOUT);
74538905Sborman #else
74639503Sborman 	return(!(termbuf.c_oflag&OPOST));
74738905Sborman #endif
74838905Sborman }
74938905Sborman 
75038905Sborman #ifdef	LINEMODE
75146809Sdab 	int
75238905Sborman tty_isediting()
75338905Sborman {
75438905Sborman #ifndef USE_TERMIO
75538905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
75638905Sborman #else
75738905Sborman 	return(termbuf.c_lflag & ICANON);
75838905Sborman #endif
75938905Sborman }
76038905Sborman 
76146809Sdab 	int
76238905Sborman tty_istrapsig()
76338905Sborman {
76438905Sborman #ifndef USE_TERMIO
76538905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
76638905Sborman #else
76738905Sborman 	return(termbuf.c_lflag & ISIG);
76838905Sborman #endif
76938905Sborman }
77038905Sborman 
77146809Sdab 	void
77238905Sborman tty_setedit(on)
77346809Sdab 	int on;
77438905Sborman {
77538905Sborman #ifndef USE_TERMIO
77638905Sborman 	if (on)
77738905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
77838905Sborman 	else
77938905Sborman 		termbuf.sg.sg_flags |= CBREAK;
78038905Sborman #else
78138905Sborman 	if (on)
78238905Sborman 		termbuf.c_lflag |= ICANON;
78338905Sborman 	else
78438905Sborman 		termbuf.c_lflag &= ~ICANON;
78538905Sborman #endif
78638905Sborman }
78738905Sborman 
78846809Sdab 	void
78938905Sborman tty_setsig(on)
79046809Sdab 	int on;
79138905Sborman {
79238905Sborman #ifndef	USE_TERMIO
79338905Sborman 	if (on)
79438905Sborman 		;
79538905Sborman #else
79638905Sborman 	if (on)
79738905Sborman 		termbuf.c_lflag |= ISIG;
79838905Sborman 	else
79938905Sborman 		termbuf.c_lflag &= ~ISIG;
80038905Sborman #endif
80138905Sborman }
80238905Sborman #endif	/* LINEMODE */
80338905Sborman 
80446809Sdab 	int
80544364Sborman tty_issofttab()
80644364Sborman {
80744364Sborman #ifndef	USE_TERMIO
80844364Sborman 	return (termbuf.sg.sg_flags & XTABS);
80944364Sborman #else
81044364Sborman # ifdef	OXTABS
81144364Sborman 	return (termbuf.c_oflag & OXTABS);
81244364Sborman # endif
81344364Sborman # ifdef	TABDLY
81444364Sborman 	return ((termbuf.c_oflag & TABDLY) == TAB3);
81544364Sborman # endif
81644364Sborman #endif
81744364Sborman }
81844364Sborman 
81946809Sdab 	void
82044364Sborman tty_setsofttab(on)
82146809Sdab 	int on;
82244364Sborman {
82344364Sborman #ifndef	USE_TERMIO
82444364Sborman 	if (on)
82544364Sborman 		termbuf.sg.sg_flags |= XTABS;
82644364Sborman 	else
82744364Sborman 		termbuf.sg.sg_flags &= ~XTABS;
82844364Sborman #else
82944364Sborman 	if (on) {
83044364Sborman # ifdef	OXTABS
83144364Sborman 		termbuf.c_oflag |= OXTABS;
83244364Sborman # endif
83344364Sborman # ifdef	TABDLY
83444364Sborman 		termbuf.c_oflag &= ~TABDLY;
83544364Sborman 		termbuf.c_oflag |= TAB3;
83644364Sborman # endif
83744364Sborman 	} else {
83844364Sborman # ifdef	OXTABS
83944364Sborman 		termbuf.c_oflag &= ~OXTABS;
84044364Sborman # endif
84144364Sborman # ifdef	TABDLY
84244364Sborman 		termbuf.c_oflag &= ~TABDLY;
84344364Sborman 		termbuf.c_oflag |= TAB0;
84444364Sborman # endif
84544364Sborman 	}
84644364Sborman #endif
84744364Sborman }
84844364Sborman 
84946809Sdab 	int
85044364Sborman tty_islitecho()
85144364Sborman {
85244364Sborman #ifndef	USE_TERMIO
85346809Sdab 	return (!(termbuf.lflags & LCTLECH));
85444364Sborman #else
85544364Sborman # ifdef	ECHOCTL
85644364Sborman 	return (!(termbuf.c_lflag & ECHOCTL));
85744364Sborman # endif
85844364Sborman # ifdef	TCTLECH
85944364Sborman 	return (!(termbuf.c_lflag & TCTLECH));
86044364Sborman # endif
86144364Sborman # if	!defined(ECHOCTL) && !defined(TCTLECH)
86244364Sborman 	return (0);	/* assumes ctl chars are echoed '^x' */
86344364Sborman # endif
86444364Sborman #endif
86544364Sborman }
86644364Sborman 
86746809Sdab 	void
86844364Sborman tty_setlitecho(on)
86946809Sdab 	int on;
87044364Sborman {
87144364Sborman #ifndef	USE_TERMIO
87244364Sborman 	if (on)
87346809Sdab 		termbuf.lflags &= ~LCTLECH;
87444364Sborman 	else
87546809Sdab 		termbuf.lflags |= LCTLECH;
87644364Sborman #else
87744364Sborman # ifdef	ECHOCTL
87844364Sborman 	if (on)
87944364Sborman 		termbuf.c_lflag &= ~ECHOCTL;
88044364Sborman 	else
88144364Sborman 		termbuf.c_lflag |= ECHOCTL;
88244364Sborman # endif
88344364Sborman # ifdef	TCTLECH
88444364Sborman 	if (on)
88544364Sborman 		termbuf.c_lflag &= ~TCTLECH;
88644364Sborman 	else
88744364Sborman 		termbuf.c_lflag |= TCTLECH;
88844364Sborman # endif
88944364Sborman #endif
89044364Sborman }
89144364Sborman 
89246809Sdab 	int
89346809Sdab tty_iscrnl()
89446809Sdab {
89546809Sdab #ifndef	USE_TERMIO
89646809Sdab 	return (termbuf.sg.sg_flags & CRMOD);
89746809Sdab #else
89846809Sdab 	return (termbuf.c_iflag & ICRNL);
89946809Sdab #endif
90046809Sdab }
90146809Sdab 
90238905Sborman /*
90338905Sborman  * A table of available terminal speeds
90438905Sborman  */
90538905Sborman struct termspeeds {
90638905Sborman 	int	speed;
90738905Sborman 	int	value;
90838905Sborman } termspeeds[] = {
90938905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
91038905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
91138905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
91238905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
91338905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
91438905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
91538905Sborman };
91638905Sborman 
91746809Sdab 	void
91838905Sborman tty_tspeed(val)
91946809Sdab 	int val;
92038905Sborman {
92138905Sborman 	register struct termspeeds *tp;
92238905Sborman 
92338905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
92438905Sborman 		;
92545234Sborman 	cfsetospeed(&termbuf, tp->value);
92638905Sborman }
92738905Sborman 
92846809Sdab 	void
92938905Sborman tty_rspeed(val)
93046809Sdab 	int val;
93138905Sborman {
93238905Sborman 	register struct termspeeds *tp;
93338905Sborman 
93438905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
93538905Sborman 		;
93645234Sborman 	cfsetispeed(&termbuf, tp->value);
93738905Sborman }
93838905Sborman 
93940242Sborman #if	defined(CRAY2) && defined(UNICOS5)
94046809Sdab 	int
94138905Sborman tty_isnewmap()
94238905Sborman {
94338905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
94438905Sborman 			!(termbuf.c_oflag & ONLRET));
94538905Sborman }
94638905Sborman #endif
94738905Sborman 
948*60151Sdab #ifdef PARENT_DOES_UTMP
94938905Sborman # ifndef NEWINIT
95038905Sborman extern	struct utmp wtmp;
95138905Sborman extern char wtmpf[];
95238905Sborman # else	/* NEWINIT */
95338905Sborman int	gotalarm;
95446809Sdab 
95546809Sdab 	/* ARGSUSED */
95646809Sdab 	void
95740242Sborman nologinproc(sig)
95846809Sdab 	int sig;
95938905Sborman {
96038905Sborman 	gotalarm++;
96138905Sborman }
96238905Sborman # endif	/* NEWINIT */
963*60151Sdab #endif /* PARENT_DOES_UTMP */
96438905Sborman 
96546809Sdab #ifndef	NEWINIT
966*60151Sdab # ifdef PARENT_DOES_UTMP
96746809Sdab extern void utmp_sig_init P((void));
96846809Sdab extern void utmp_sig_reset P((void));
96946809Sdab extern void utmp_sig_wait P((void));
97046809Sdab extern void utmp_sig_notify P((int));
971*60151Sdab # endif /* PARENT_DOES_UTMP */
97246809Sdab #endif
97346809Sdab 
97438905Sborman /*
97538905Sborman  * getptyslave()
97638905Sborman  *
97738905Sborman  * Open the slave side of the pty, and do any initialization
97838905Sborman  * that is necessary.  The return value is a file descriptor
97938905Sborman  * for the slave side.
98038905Sborman  */
98146809Sdab 	int
98238905Sborman getptyslave()
98338905Sborman {
98438905Sborman 	register int t = -1;
98538905Sborman 
98645234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
98745234Sborman # ifdef	LINEMODE
98846809Sdab 	int waslm;
98946809Sdab # endif
99046809Sdab # ifdef	TIOCGWINSZ
99146809Sdab 	struct winsize ws;
99246809Sdab 	extern int def_row, def_col;
99346809Sdab # endif
99446809Sdab 	extern int def_tspeed, def_rspeed;
99538905Sborman 	/*
99645234Sborman 	 * Opening the slave side may cause initilization of the
99746809Sdab 	 * kernel tty structure.  We need remember the state of
99846809Sdab 	 * 	if linemode was turned on
99946809Sdab 	 *	terminal window size
100046809Sdab 	 *	terminal speed
100146809Sdab 	 * so that we can re-set them if we need to.
100238905Sborman 	 */
100346809Sdab # ifdef	LINEMODE
100446809Sdab 	waslm = tty_linemode();
100545234Sborman # endif
100645234Sborman 
100745234Sborman 
100845234Sborman 	/*
100945234Sborman 	 * Make sure that we don't have a controlling tty, and
101045234Sborman 	 * that we are the session (process group) leader.
101145234Sborman 	 */
101245234Sborman # ifdef	TIOCNOTTY
101338905Sborman 	t = open(_PATH_TTY, O_RDWR);
101438905Sborman 	if (t >= 0) {
101538905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
101638905Sborman 		(void) close(t);
101738905Sborman 	}
101845234Sborman # endif
101938905Sborman 
102045234Sborman 
1021*60151Sdab # ifdef PARENT_DOES_UTMP
102245234Sborman 	/*
102345234Sborman 	 * Wait for our parent to get the utmp stuff to get done.
102445234Sborman 	 */
102545234Sborman 	utmp_sig_wait();
102645234Sborman # endif
102745234Sborman 
102845234Sborman 	t = cleanopen(line);
102938905Sborman 	if (t < 0)
103038905Sborman 		fatalperror(net, line);
103138905Sborman 
103257592Sdab #ifdef  STREAMSPTY
103357212Sdab #ifdef	USE_TERMIO
103457212Sdab 	ttyfd = t;
103557212Sdab #endif
103657212Sdab 	if (ioctl(t, I_PUSH, "ptem") < 0)
103757212Sdab 		fatal(net, "I_PUSH ptem");
103857212Sdab 	if (ioctl(t, I_PUSH, "ldterm") < 0)
103957212Sdab 		fatal(net, "I_PUSH ldterm");
104057212Sdab 	if (ioctl(t, I_PUSH, "ttcompat") < 0)
104157212Sdab 		fatal(net, "I_PUSH ttcompat");
104257212Sdab 	if (ioctl(pty, I_PUSH, "pckt") < 0)
104357212Sdab 		fatal(net, "I_PUSH pckt");
104457212Sdab #endif
104557212Sdab 
104645234Sborman 	/*
104745234Sborman 	 * set up the tty modes as we like them to be.
104845234Sborman 	 */
104938905Sborman 	init_termbuf();
105046809Sdab # ifdef	TIOCGWINSZ
105146809Sdab 	if (def_row || def_col) {
105246809Sdab 		bzero((char *)&ws, sizeof(ws));
105346809Sdab 		ws.ws_col = def_col;
105446809Sdab 		ws.ws_row = def_row;
105546809Sdab 		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
105646809Sdab 	}
105746809Sdab # endif
105845234Sborman 
105945234Sborman 	/*
106045234Sborman 	 * Settings for sgtty based systems
106145234Sborman 	 */
106245234Sborman # ifndef	USE_TERMIO
106340242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
106445234Sborman # endif	/* USE_TERMIO */
106545234Sborman 
106645234Sborman 	/*
1067*60151Sdab 	 * Settings for UNICOS (and HPUX)
106845234Sborman 	 */
1069*60151Sdab # if defined(CRAY) || defined(__hpux)
107045234Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
107145234Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
107245234Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
107345234Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
107445234Sborman # endif
107545234Sborman 
107645234Sborman 	/*
107745234Sborman 	 * Settings for all other termios/termio based
107845234Sborman 	 * systems, other than 4.4BSD.  In 4.4BSD the
107945234Sborman 	 * kernel does the initial terminal setup.
108045234Sborman 	 */
1081*60151Sdab # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
108245234Sborman #  ifndef	OXTABS
108345234Sborman #   define OXTABS	0
108445234Sborman #  endif
108538905Sborman 	termbuf.c_lflag |= ECHO;
108638905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
108738905Sborman 	termbuf.c_iflag |= ICRNL;
108838905Sborman 	termbuf.c_iflag &= ~IXOFF;
108945234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
109046996Sdab 	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
109146996Sdab 	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
109246809Sdab # ifdef	LINEMODE
109346809Sdab 	if (waslm)
109446809Sdab 		tty_setlinemode(1);
109546809Sdab # endif	/* LINEMODE */
109645234Sborman 
109745234Sborman 	/*
109845234Sborman 	 * Set the tty modes, and make this our controlling tty.
109945234Sborman 	 */
110045234Sborman 	set_termbuf();
110145234Sborman 	if (login_tty(t) == -1)
110245234Sborman 		fatalperror(net, "login_tty");
110345234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
110445234Sborman 	if (net > 2)
110545234Sborman 		(void) close(net);
110645234Sborman 	if (pty > 2)
110745234Sborman 		(void) close(pty);
110845234Sborman }
110945234Sborman 
111045234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
111145234Sborman #ifndef	O_NOCTTY
111245234Sborman #define	O_NOCTTY	0
111338905Sborman #endif
111445234Sborman /*
111545234Sborman  * Open the specified slave side of the pty,
111645234Sborman  * making sure that we have a clean tty.
111745234Sborman  */
111846809Sdab 	int
111945234Sborman cleanopen(line)
112046809Sdab 	char *line;
112145234Sborman {
112245234Sborman 	register int t;
112357212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
112457212Sdab 	struct secstat secbuf;
112557212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
112645234Sborman 
112757212Sdab #ifndef STREAMSPTY
112845234Sborman 	/*
112945234Sborman 	 * Make sure that other people can't open the
113045234Sborman 	 * slave side of the connection.
113145234Sborman 	 */
113238905Sborman 	(void) chown(line, 0, 0);
113338905Sborman 	(void) chmod(line, 0600);
113457212Sdab #endif
113545234Sborman 
113645234Sborman # if !defined(CRAY) && (BSD > 43)
113745234Sborman 	(void) revoke(line);
113845234Sborman # endif
113957212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
114057212Sdab 	if (secflag) {
114157212Sdab 		if (secstat(line, &secbuf) < 0)
114257212Sdab 			return(-1);
114357212Sdab 		if (setulvl(secbuf.st_slevel) < 0)
114457212Sdab 			return(-1);
114557212Sdab 		if (setucmp(secbuf.st_compart) < 0)
114657212Sdab 			return(-1);
114757212Sdab 	}
114857212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
114957212Sdab 
115045234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
115157212Sdab 
115257212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
115357212Sdab 	if (secflag) {
115457212Sdab 		if (setulvl(sysv.sy_minlvl) < 0)
115557212Sdab 			return(-1);
115657212Sdab 		if (setucmp(0) < 0)
115757212Sdab 			return(-1);
115857212Sdab 	}
115957212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
116057212Sdab 
116145234Sborman 	if (t < 0)
116245234Sborman 		return(-1);
116345234Sborman 
116445234Sborman 	/*
116545234Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
116645234Sborman 	 * ourselves.
116745234Sborman 	 */
1168*60151Sdab # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
116945234Sborman 	(void) signal(SIGHUP, SIG_IGN);
117045234Sborman 	vhangup();
117145234Sborman 	(void) signal(SIGHUP, SIG_DFL);
117245234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
117345234Sborman 	if (t < 0)
117445234Sborman 		return(-1);
117545234Sborman # endif
117645234Sborman # if	defined(CRAY) && defined(TCVHUP)
117745234Sborman 	{
117845234Sborman 		register int i;
117945234Sborman 		(void) signal(SIGHUP, SIG_IGN);
118045234Sborman 		(void) ioctl(t, TCVHUP, (char *)0);
118145234Sborman 		(void) signal(SIGHUP, SIG_DFL);
118245234Sborman 		setpgrp();
118357212Sdab 
118457212Sdab #if		defined(_SC_CRAY_SECURE_SYS)
118557212Sdab 		if (secflag) {
118657212Sdab 			if (secstat(line, &secbuf) < 0)
118757212Sdab 				return(-1);
118857212Sdab 			if (setulvl(secbuf.st_slevel) < 0)
118957212Sdab 				return(-1);
119057212Sdab 			if (setucmp(secbuf.st_compart) < 0)
119157212Sdab 				return(-1);
119257212Sdab 		}
119357212Sdab #endif		/* _SC_CRAY_SECURE_SYS */
119457212Sdab 
119545234Sborman 		i = open(line, O_RDWR);
119657212Sdab 
119757212Sdab #if		defined(_SC_CRAY_SECURE_SYS)
119857212Sdab 		if (secflag) {
119957212Sdab 			if (setulvl(sysv.sy_minlvl) < 0)
120057212Sdab 				return(-1);
120157212Sdab 			if (setucmp(0) < 0)
120257212Sdab 				return(-1);
120357212Sdab 		}
120457212Sdab #endif		/* _SC_CRAY_SECURE_SYS */
120557212Sdab 
120645234Sborman 		if (i < 0)
120746809Sdab 			return(-1);
120845234Sborman 		(void) close(t);
120945234Sborman 		t = i;
121045234Sborman 	}
121145234Sborman # endif	/* defined(CRAY) && defined(TCVHUP) */
121238905Sborman 	return(t);
121338905Sborman }
121445234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
121538905Sborman 
121645234Sborman #if BSD <= 43
121746809Sdab 	int
121845234Sborman login_tty(t)
121946809Sdab 	int t;
122045234Sborman {
122145234Sborman 	if (setsid() < 0)
122245234Sborman 		fatalperror(net, "setsid()");
122345234Sborman # ifdef	TIOCSCTTY
122445234Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
122545234Sborman 		fatalperror(net, "ioctl(sctty)");
122657212Sdab #  if defined(CRAY)
122747613Sdab 	/*
122847613Sdab 	 * Close the hard fd to /dev/ttypXXX, and re-open through
122947613Sdab 	 * the indirect /dev/tty interface.
123047613Sdab 	 */
123147613Sdab 	close(t);
123247613Sdab 	if ((t = open("/dev/tty", O_RDWR)) < 0)
123347613Sdab 		fatalperror(net, "open(/dev/tty)");
123447613Sdab #  endif
123545234Sborman # else
123645234Sborman 	close(open(line, O_RDWR));
123745234Sborman # endif
123847613Sdab 	if (t != 0)
123947613Sdab 		(void) dup2(t, 0);
124047613Sdab 	if (t != 1)
124147613Sdab 		(void) dup2(t, 1);
124247613Sdab 	if (t != 2)
124347613Sdab 		(void) dup2(t, 2);
124447613Sdab 	if (t > 2)
124547613Sdab 		close(t);
124646809Sdab 	return(0);
124745234Sborman }
124845234Sborman #endif	/* BSD <= 43 */
124945234Sborman 
125038905Sborman #ifdef	NEWINIT
125138905Sborman char *gen_id = "fe";
125238905Sborman #endif
125338905Sborman 
125438905Sborman /*
125545234Sborman  * startslave(host)
125638905Sborman  *
125745234Sborman  * Given a hostname, do whatever
125838905Sborman  * is necessary to startup the login process on the slave side of the pty.
125938905Sborman  */
126038905Sborman 
126138905Sborman /* ARGSUSED */
126246809Sdab 	void
126346809Sdab startslave(host, autologin, autoname)
126446809Sdab 	char *host;
126546809Sdab 	int autologin;
126646809Sdab 	char *autoname;
126738905Sborman {
126838905Sborman 	register int i;
126938905Sborman 	long time();
127046809Sdab 	char name[256];
127146809Sdab #ifdef	NEWINIT
127246809Sdab 	extern char *ptyip;
127346809Sdab 	struct init_request request;
127446809Sdab 	void nologinproc();
127546809Sdab 	register int n;
127646809Sdab #endif	/* NEWINIT */
127738905Sborman 
127857212Sdab #if	defined(AUTHENTICATION)
127946809Sdab 	if (!autoname || !autoname[0])
128046809Sdab 		autologin = 0;
128146809Sdab 
128246809Sdab 	if (autologin < auth_level) {
128346809Sdab 		fatal(net, "Authorization failed");
128446809Sdab 		exit(1);
128546809Sdab 	}
128646809Sdab #endif
128746809Sdab 
128838905Sborman #ifndef	NEWINIT
1289*60151Sdab # ifdef	PARENT_DOES_UTMP
129038905Sborman 	utmp_sig_init();
1291*60151Sdab # endif	/* PARENT_DOES_UTMP */
129238905Sborman 
129338905Sborman 	if ((i = fork()) < 0)
129438905Sborman 		fatalperror(net, "fork");
129538905Sborman 	if (i) {
1296*60151Sdab # ifdef PARENT_DOES_UTMP
129738905Sborman 		/*
129838905Sborman 		 * Cray parent will create utmp entry for child and send
129938905Sborman 		 * signal to child to tell when done.  Child waits for signal
130038905Sborman 		 * before doing anything important.
130138905Sborman 		 */
130238905Sborman 		register int pid = i;
130346809Sdab 		void sigjob P((int));
130438905Sborman 
130538905Sborman 		setpgrp();
130644364Sborman 		utmp_sig_reset();		/* reset handler to default */
130738905Sborman 		/*
130838905Sborman 		 * Create utmp entry for child
130938905Sborman 		 */
131038905Sborman 		(void) time(&wtmp.ut_time);
131138905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
131238905Sborman 		wtmp.ut_pid = pid;
131338905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
131438905Sborman 		SCPYN(wtmp.ut_host, host);
131538905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
1316*60151Sdab #ifndef	__hpux
131738905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
1318*60151Sdab #else
1319*60151Sdab 		SCPYN(wtmp.ut_id, wtmp.ut_line+7);
1320*60151Sdab #endif
132138905Sborman 		pututline(&wtmp);
132238905Sborman 		endutent();
132338905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
132438905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
132538905Sborman 			(void) close(i);
132638905Sborman 		}
1327*60151Sdab #ifdef	CRAY
132846809Sdab 		(void) signal(WJSIGNAL, sigjob);
1329*60151Sdab #endif
133038905Sborman 		utmp_sig_notify(pid);
1331*60151Sdab # endif	/* PARENT_DOES_UTMP */
133238905Sborman 	} else {
133345234Sborman 		getptyslave();
133446809Sdab 		start_login(host, autologin, autoname);
133538905Sborman 		/*NOTREACHED*/
133638905Sborman 	}
133738905Sborman #else	/* NEWINIT */
133838905Sborman 
133938905Sborman 	/*
134038905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
134138905Sborman 	 * for it to start up and begin normal telnet operation.
134238905Sborman 	 */
134338905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
134438905Sborman 		char tbuf[128];
134538905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
134638905Sborman 		fatalperror(net, tbuf);
134738905Sborman 	}
134838905Sborman 	memset((char *)&request, 0, sizeof(request));
134938905Sborman 	request.magic = INIT_MAGIC;
135038905Sborman 	SCPYN(request.gen_id, gen_id);
135138905Sborman 	SCPYN(request.tty_id, &line[8]);
135238905Sborman 	SCPYN(request.host, host);
135346809Sdab 	SCPYN(request.term_type, terminaltype ? terminaltype : "network");
135444364Sborman #if	!defined(UNICOS5)
135540242Sborman 	request.signal = SIGCLD;
135640242Sborman 	request.pid = getpid();
135740242Sborman #endif
135844364Sborman #ifdef BFTPDAEMON
135944364Sborman 	/*
136044364Sborman 	 * Are we working as the bftp daemon?
136144364Sborman 	 */
136244364Sborman 	if (bftpd) {
136344364Sborman 		SCPYN(request.exec_name, BFTPPATH);
136444364Sborman 	}
136544364Sborman #endif /* BFTPDAEMON */
136638905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
136738905Sborman 		char tbuf[128];
136838905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
136938905Sborman 		fatalperror(net, tbuf);
137038905Sborman 	}
137138905Sborman 	(void) close(i);
137238905Sborman 	(void) signal(SIGALRM, nologinproc);
137338905Sborman 	for (i = 0; ; i++) {
137440242Sborman 		char tbuf[128];
137538905Sborman 		alarm(15);
137638905Sborman 		n = read(pty, ptyip, BUFSIZ);
137738905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
137838905Sborman 			break;
137938905Sborman 		gotalarm = 0;
138040242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
138140242Sborman 		(void) write(net, tbuf, strlen(tbuf));
138238905Sborman 	}
138338905Sborman 	if (n < 0 && gotalarm)
138438905Sborman 		fatal(net, "/etc/init didn't start login process");
138538905Sborman 	pcc += n;
138638905Sborman 	alarm(0);
138738905Sborman 	(void) signal(SIGALRM, SIG_DFL);
138838905Sborman 
138938905Sborman 	return;
139038905Sborman #endif	/* NEWINIT */
139138905Sborman }
139238905Sborman 
139338905Sborman char	*envinit[3];
139444364Sborman extern char **environ;
139538905Sborman 
139646809Sdab 	void
139744364Sborman init_env()
139844364Sborman {
139944364Sborman 	extern char *getenv();
140044364Sborman 	char **envp;
140144364Sborman 
140244364Sborman 	envp = envinit;
140344364Sborman 	if (*envp = getenv("TZ"))
140444364Sborman 		*envp++ -= 3;
1405*60151Sdab #if	defined(CRAY) || defined(__hpux)
140644364Sborman 	else
140744364Sborman 		*envp++ = "TZ=GMT0";
140844364Sborman #endif
140944364Sborman 	*envp = 0;
141044364Sborman 	environ = envinit;
141144364Sborman }
141244364Sborman 
141344364Sborman #ifndef	NEWINIT
141444364Sborman 
141544364Sborman /*
141645234Sborman  * start_login(host)
141738905Sborman  *
141838905Sborman  * Assuming that we are now running as a child processes, this
141938905Sborman  * function will turn us into the login process.
142038905Sborman  */
142138905Sborman 
142246809Sdab 	void
142346809Sdab start_login(host, autologin, name)
142446809Sdab 	char *host;
142546809Sdab 	int autologin;
142646809Sdab 	char *name;
142738905Sborman {
142844364Sborman 	register char *cp;
142944364Sborman 	register char **argv;
143044364Sborman 	char **addarg();
143157212Sdab #ifdef	UTMPX
143257212Sdab 	register int pid = getpid();
143357212Sdab 	struct utmpx utmpx;
143457212Sdab #endif
143557212Sdab #ifdef __svr4__
143657212Sdab 	char *term;
143757212Sdab 	char termbuf[64];
143857212Sdab #endif
143938905Sborman 
144057212Sdab #ifdef	UTMPX
144138905Sborman 	/*
144257212Sdab 	 * Create utmp entry for child
144357212Sdab 	 */
144457212Sdab 
144557212Sdab 	bzero(&utmpx, sizeof(utmpx));
144657212Sdab 	SCPYN(utmpx.ut_user, ".telnet");
144757212Sdab 	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
144857212Sdab 	utmpx.ut_pid = pid;
144957212Sdab 	utmpx.ut_id[0] = 't';
145057212Sdab 	utmpx.ut_id[1] = 'n';
145157212Sdab 	utmpx.ut_id[2] = SC_WILDC;
145257212Sdab 	utmpx.ut_id[3] = SC_WILDC;
145357212Sdab 	utmpx.ut_type = LOGIN_PROCESS;
145457212Sdab 	(void) time(&utmpx.ut_tv.tv_sec);
145557212Sdab 	if (makeutx(&utmpx) == NULL)
145657212Sdab 		fatal(net, "makeutx failed");
145757212Sdab #endif
145857212Sdab 
145957212Sdab 	/*
146038905Sborman 	 * -h : pass on name of host.
146138905Sborman 	 *		WARNING:  -h is accepted by login if and only if
146238905Sborman 	 *			getuid() == 0.
146338905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
146446809Sdab 	 *
146546809Sdab 	 * -f : force this login, he has already been authenticated
146638905Sborman 	 */
146744364Sborman 	argv = addarg(0, "login");
1468*60151Sdab #if	!defined(NO_LOGIN_H)
146944364Sborman 	argv = addarg(argv, "-h");
147044364Sborman 	argv = addarg(argv, host);
1471*60151Sdab #endif
147257212Sdab #ifdef	__svr4__
147357212Sdab 	/*
147457212Sdab 	 * SVR4 version of -h takes TERM= as second arg, or -
147557212Sdab 	 */
147657212Sdab 	term = getenv("TERM");
147757212Sdab 	if (term == NULL || term[0] == 0) {
147857212Sdab 		term = "-";
147957212Sdab 	} else {
148057212Sdab 		strcpy(termbuf, "TERM=");
148157212Sdab 		strncat(termbuf, term, sizeof(termbuf) - 6);
148257212Sdab 		term = termbuf;
148357212Sdab 	}
148457212Sdab 	argv = addarg(argv, term);
148557212Sdab #endif
148646809Sdab #if	!defined(NO_LOGIN_P)
148744364Sborman 	argv = addarg(argv, "-p");
148838905Sborman #endif
148944364Sborman #ifdef	BFTPDAEMON
149044364Sborman 	/*
149144364Sborman 	 * Are we working as the bftp daemon?  If so, then ask login
149244364Sborman 	 * to start bftp instead of shell.
149344364Sborman 	 */
149444364Sborman 	if (bftpd) {
149544364Sborman 		argv = addarg(argv, "-e");
149644364Sborman 		argv = addarg(argv, BFTPPATH);
149744364Sborman 	} else
149844364Sborman #endif
149946809Sdab #if	defined (SecurID)
150046809Sdab 	/*
150146809Sdab 	 * don't worry about the -f that might get sent.
150246809Sdab 	 * A -s is supposed to override it anyhow.
150346809Sdab 	 */
150446809Sdab 	if (require_SecurID)
150546809Sdab 		argv = addarg(argv, "-s");
150646809Sdab #endif
150757212Sdab #if	defined (AUTHENTICATION)
150846809Sdab 	if (auth_level >= 0 && autologin == AUTH_VALID) {
150946809Sdab # if	!defined(NO_LOGIN_F)
151046809Sdab 		argv = addarg(argv, "-f");
151146809Sdab # endif
151246809Sdab 		argv = addarg(argv, name);
151346809Sdab 	} else
151446809Sdab #endif
151544364Sborman 	if (getenv("USER")) {
151644364Sborman 		argv = addarg(argv, getenv("USER"));
1517*60151Sdab #if	(defined(CRAY) || defined(__hpux)) && defined(NO_LOGIN_P)
151846809Sdab 		{
151946809Sdab 			register char **cpp;
152046809Sdab 			for (cpp = environ; *cpp; cpp++)
152146809Sdab 				argv = addarg(argv, *cpp);
152246809Sdab 		}
152346809Sdab #endif
152457212Sdab 		/*
152557212Sdab 		 * Assume that login will set the USER variable
152657212Sdab 		 * correctly.  For SysV systems, this means that
152757212Sdab 		 * USER will no longer be set, just LOGNAME by
152857212Sdab 		 * login.  (The problem is that if the auto-login
152957212Sdab 		 * fails, and the user then specifies a different
153057212Sdab 		 * account name, he can get logged in with both
153157212Sdab 		 * LOGNAME and USER in his environment, but the
153257212Sdab 		 * USER value will be wrong.
153357212Sdab 		 */
153457212Sdab 		unsetenv("USER");
153544364Sborman 	}
153646809Sdab 	closelog();
153744364Sborman 	execv(_PATH_LOGIN, argv);
153844364Sborman 
153938905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
154038905Sborman 	fatalperror(net, _PATH_LOGIN);
154138905Sborman 	/*NOTREACHED*/
154238905Sborman }
154344364Sborman 
154446809Sdab 	char **
154544364Sborman addarg(argv, val)
154646809Sdab 	register char **argv;
154746809Sdab 	register char *val;
154844364Sborman {
154944364Sborman 	register char **cpp;
155044364Sborman 
155144364Sborman 	if (argv == NULL) {
155244364Sborman 		/*
155344364Sborman 		 * 10 entries, a leading length, and a null
155444364Sborman 		 */
155544364Sborman 		argv = (char **)malloc(sizeof(*argv) * 12);
155644364Sborman 		if (argv == NULL)
155744364Sborman 			return(NULL);
155844364Sborman 		*argv++ = (char *)10;
155944364Sborman 		*argv = (char *)0;
156044364Sborman 	}
156144364Sborman 	for (cpp = argv; *cpp; cpp++)
156244364Sborman 		;
156344364Sborman 	if (cpp == &argv[(int)argv[-1]]) {
156444364Sborman 		--argv;
156544364Sborman 		*argv = (char *)((int)(*argv) + 10);
156644364Sborman 		argv = (char **)realloc(argv, (int)(*argv) + 2);
156744364Sborman 		if (argv == NULL)
156844364Sborman 			return(NULL);
156944364Sborman 		argv++;
157044364Sborman 		cpp = &argv[(int)argv[-1] - 10];
157144364Sborman 	}
157244364Sborman 	*cpp++ = val;
157344364Sborman 	*cpp = 0;
157444364Sborman 	return(argv);
157544364Sborman }
157646809Sdab #endif	/* NEWINIT */
157738905Sborman 
157838905Sborman /*
157938905Sborman  * cleanup()
158038905Sborman  *
158138905Sborman  * This is the routine to call when we are all through, to
158238905Sborman  * clean up anything that needs to be cleaned up.
158338905Sborman  */
158446809Sdab 	/* ARGSUSED */
158546809Sdab 	void
158646809Sdab cleanup(sig)
158746809Sdab 	int sig;
158838905Sborman {
1589*60151Sdab #ifndef	PARENT_DOES_UTMP
159045234Sborman # if (BSD > 43) || defined(convex)
159138905Sborman 	char *p;
159238905Sborman 
159338905Sborman 	p = line + sizeof("/dev/") - 1;
159438905Sborman 	if (logout(p))
159538905Sborman 		logwtmp(p, "", "");
159638905Sborman 	(void)chmod(line, 0666);
159738905Sborman 	(void)chown(line, 0, 0);
159838905Sborman 	*p = 'p';
159938905Sborman 	(void)chmod(line, 0666);
160038905Sborman 	(void)chown(line, 0, 0);
160146809Sdab 	(void) shutdown(net, 2);
160246809Sdab 	exit(1);
160338905Sborman # else
160446809Sdab 	void rmut();
160546809Sdab 
160638905Sborman 	rmut();
160738905Sborman 	vhangup();	/* XXX */
160846809Sdab 	(void) shutdown(net, 2);
160946809Sdab 	exit(1);
161038905Sborman # endif
1611*60151Sdab #else	/* PARENT_DOES_UTMP */
161246809Sdab # ifdef	NEWINIT
161338905Sborman 	(void) shutdown(net, 2);
161446809Sdab 	exit(1);
161538905Sborman # else	/* NEWINIT */
1616*60151Sdab #  ifdef CRAY
161746809Sdab 	static int incleanup = 0;
161846809Sdab 	register int t;
161946809Sdab 
162046809Sdab 	/*
162146809Sdab 	 * 1: Pick up the zombie, if we are being called
162246809Sdab 	 *    as the signal handler.
162346809Sdab 	 * 2: If we are a nested cleanup(), return.
162446809Sdab 	 * 3: Try to clean up TMPDIR.
162546809Sdab 	 * 4: Fill in utmp with shutdown of process.
162646809Sdab 	 * 5: Close down the network and pty connections.
162746809Sdab 	 * 6: Finish up the TMPDIR cleanup, if needed.
162846809Sdab 	 */
162946809Sdab 	if (sig == SIGCHLD)
163046809Sdab 		while (waitpid(-1, 0, WNOHANG) > 0)
163146809Sdab 			;	/* VOID */
163246809Sdab 	t = sigblock(sigmask(SIGCHLD));
163346809Sdab 	if (incleanup) {
163446809Sdab 		sigsetmask(t);
163546809Sdab 		return;
163646809Sdab 	}
163746809Sdab 	incleanup = 1;
163846809Sdab 	sigsetmask(t);
1639*60151Sdab 	if (secflag) {
1640*60151Sdab 		/*
1641*60151Sdab 		 *	We need to set ourselves back to a null
1642*60151Sdab 		 *	label to clean up.
1643*60151Sdab 		 */
164446809Sdab 
1645*60151Sdab 		setulvl(sysv.sy_minlvl);
1646*60151Sdab 		setucmp((long)0);
1647*60151Sdab 	}
1648*60151Sdab 
164946809Sdab 	t = cleantmp(&wtmp);
165046809Sdab 	setutent();	/* just to make sure */
1651*60151Sdab #  endif /* CRAY */
165246809Sdab 	rmut(line);
165346809Sdab 	close(pty);
165438905Sborman 	(void) shutdown(net, 2);
1655*60151Sdab #  ifdef CRAY
165646809Sdab 	if (t == 0)
165746809Sdab 		cleantmp(&wtmp);
1658*60151Sdab #  endif /* CRAY */
165946809Sdab 	exit(1);
166038905Sborman # endif	/* NEWINT */
1661*60151Sdab #endif	/* PARENT_DOES_UTMP */
166238905Sborman }
166338905Sborman 
1664*60151Sdab #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
166538905Sborman /*
166638905Sborman  * _utmp_sig_rcv
166738905Sborman  * utmp_sig_init
166838905Sborman  * utmp_sig_wait
166938905Sborman  *	These three functions are used to coordinate the handling of
167038905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
167138905Sborman  *	The server actually creates the utmp structure, the child calls
167238905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
167338905Sborman  *	signals the future-login shell to proceed.
167438905Sborman  */
167538905Sborman static int caught=0;		/* NZ when signal intercepted */
167638905Sborman static void (*func)();		/* address of previous handler */
167738905Sborman 
167846809Sdab 	void
167938905Sborman _utmp_sig_rcv(sig)
168046809Sdab 	int sig;
168138905Sborman {
168238905Sborman 	caught = 1;
168338905Sborman 	(void) signal(SIGUSR1, func);
168438905Sborman }
168538905Sborman 
168646809Sdab 	void
168738905Sborman utmp_sig_init()
168838905Sborman {
168938905Sborman 	/*
169038905Sborman 	 * register signal handler for UTMP creation
169138905Sborman 	 */
169238905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
169338905Sborman 		fatalperror(net, "telnetd/signal");
169438905Sborman }
169538905Sborman 
169646809Sdab 	void
169744364Sborman utmp_sig_reset()
169844364Sborman {
169944364Sborman 	(void) signal(SIGUSR1, func);	/* reset handler to default */
170044364Sborman }
170144364Sborman 
1702*60151Sdab # ifdef __hpux
1703*60151Sdab # define sigoff() /* do nothing */
1704*60151Sdab # define sigon() /* do nothing */
1705*60151Sdab # endif
1706*60151Sdab 
170746809Sdab 	void
170838905Sborman utmp_sig_wait()
170938905Sborman {
171038905Sborman 	/*
171138905Sborman 	 * Wait for parent to write our utmp entry.
171238905Sborman 	 */
171338905Sborman 	sigoff();
171438905Sborman 	while (caught == 0) {
171538905Sborman 		pause();	/* wait until we get a signal (sigon) */
171638905Sborman 		sigoff();	/* turn off signals while we check caught */
171738905Sborman 	}
171838905Sborman 	sigon();		/* turn on signals again */
171938905Sborman }
172038905Sborman 
172146809Sdab 	void
172238905Sborman utmp_sig_notify(pid)
172338905Sborman {
172438905Sborman 	kill(pid, SIGUSR1);
172538905Sborman }
172646809Sdab 
1727*60151Sdab # ifdef CRAY
172846809Sdab static int gotsigjob = 0;
172946809Sdab 
173046809Sdab 	/*ARGSUSED*/
173146809Sdab 	void
173246809Sdab sigjob(sig)
173346809Sdab 	int sig;
173446809Sdab {
173546809Sdab 	register int jid;
173646809Sdab 	register struct jobtemp *jp;
173746809Sdab 
173846809Sdab 	while ((jid = waitjob(NULL)) != -1) {
173946809Sdab 		if (jid == 0) {
174046809Sdab 			return;
174146809Sdab 		}
174246809Sdab 		gotsigjob++;
174346809Sdab 		jobend(jid, NULL, NULL);
174446809Sdab 	}
174546809Sdab }
174646809Sdab 
174746809Sdab /*
174846809Sdab  * Clean up the TMPDIR that login created.
174946809Sdab  * The first time this is called we pick up the info
175046809Sdab  * from the utmp.  If the job has already gone away,
175146809Sdab  * then we'll clean up and be done.  If not, then
175246809Sdab  * when this is called the second time it will wait
175346809Sdab  * for the signal that the job is done.
175446809Sdab  */
175546809Sdab 	int
175646809Sdab cleantmp(wtp)
175746809Sdab 	register struct utmp *wtp;
175846809Sdab {
175946809Sdab 	struct utmp *utp;
176046809Sdab 	static int first = 1;
176146809Sdab 	register int mask, omask, ret;
176246809Sdab 	extern struct utmp *getutid P((struct utmp *));
176346809Sdab 
176446809Sdab 	mask = sigmask(WJSIGNAL);
176546809Sdab 
176646809Sdab 	if (first == 0) {
176746809Sdab 		omask = sigblock(mask);
176846809Sdab 		while (gotsigjob == 0)
176946809Sdab 			sigpause(omask);
177046809Sdab 		return(1);
177146809Sdab 	}
177246809Sdab 	first = 0;
177346809Sdab 	setutent();	/* just to make sure */
177446809Sdab 
177546809Sdab 	utp = getutid(wtp);
177646809Sdab 	if (utp == 0) {
177746809Sdab 		syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
177846809Sdab 		return(-1);
177946809Sdab 	}
178046809Sdab 	/*
178146809Sdab 	 * Nothing to clean up if the user shell was never started.
178246809Sdab 	 */
178346809Sdab 	if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
178446809Sdab 		return(1);
178546809Sdab 
178646809Sdab 	/*
178746809Sdab 	 * Block the WJSIGNAL while we are in jobend().
178846809Sdab 	 */
178946809Sdab 	omask = sigblock(mask);
179046809Sdab 	ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
179146809Sdab 	sigsetmask(omask);
179246809Sdab 	return(ret);
179346809Sdab }
179446809Sdab 
179546809Sdab 	int
179646809Sdab jobend(jid, path, user)
179746809Sdab 	register int jid;
179846809Sdab 	register char *path;
179946809Sdab 	register char *user;
180046809Sdab {
180146809Sdab 	static int saved_jid = 0;
180246809Sdab 	static char saved_path[sizeof(wtmp.ut_tpath)+1];
180346809Sdab 	static char saved_user[sizeof(wtmp.ut_user)+1];
180446809Sdab 
180546809Sdab 	if (path) {
180646809Sdab 		strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
180746809Sdab 		strncpy(saved_user, user, sizeof(wtmp.ut_user));
180846809Sdab 		saved_path[sizeof(saved_path)] = '\0';
180946809Sdab 		saved_user[sizeof(saved_user)] = '\0';
181046809Sdab 	}
181146809Sdab 	if (saved_jid == 0) {
181246809Sdab 		saved_jid = jid;
181346809Sdab 		return(0);
181446809Sdab 	}
181546809Sdab 	cleantmpdir(jid, saved_path, saved_user);
181646809Sdab 	return(1);
181746809Sdab }
181846809Sdab 
181946809Sdab /*
182046809Sdab  * Fork a child process to clean up the TMPDIR
182146809Sdab  */
182246809Sdab cleantmpdir(jid, tpath, user)
182346809Sdab 	register int jid;
182446809Sdab 	register char *tpath;
182546809Sdab 	register char *user;
182646809Sdab {
182746809Sdab 	switch(fork()) {
182846809Sdab 	case -1:
182946809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
183046809Sdab 							tpath);
183146809Sdab 		break;
183246809Sdab 	case 0:
183346809Sdab 		execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
183446809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
183546809Sdab 							tpath, CLEANTMPCMD);
183646809Sdab 		exit(1);
183746809Sdab 	default:
183846809Sdab 		/*
183946809Sdab 		 * Forget about child.  We will exit, and
184046809Sdab 		 * /etc/init will pick it up.
184146809Sdab 		 */
184246809Sdab 		break;
184346809Sdab 	}
184446809Sdab }
1845*60151Sdab # endif /* CRAY */
1846*60151Sdab #endif	/* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
184738905Sborman 
184838905Sborman /*
184938905Sborman  * rmut()
185038905Sborman  *
185138905Sborman  * This is the function called by cleanup() to
185238905Sborman  * remove the utmp entry for this person.
185338905Sborman  */
185438905Sborman 
185557212Sdab #ifdef	UTMPX
185657212Sdab rmut()
185757212Sdab {
185857212Sdab 	register f;
185957212Sdab 	int found = 0;
186057212Sdab 	struct utmp *u, *utmp;
186157212Sdab 	int nutmp;
186257212Sdab 	struct stat statbf;
186357212Sdab 
186457212Sdab 	struct utmpx *utxp, utmpx;
186557212Sdab 
186657212Sdab 	/*
186757212Sdab 	 * This updates the utmpx and utmp entries and make a wtmp/x entry
186857212Sdab 	 */
186957212Sdab 
187057212Sdab 	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
187157212Sdab 	utxp = getutxline(&utmpx);
187257212Sdab 	if (utxp) {
187357212Sdab 		utxp->ut_type = DEAD_PROCESS;
187457212Sdab 		utxp->ut_exit.e_termination = 0;
187557212Sdab 		utxp->ut_exit.e_exit = 0;
187657212Sdab 		(void) time(&utmpx.ut_tv.tv_sec);
187757212Sdab 		utmpx.ut_tv.tv_usec = 0;
187857212Sdab 		modutx(utxp);
187957212Sdab 	}
188057212Sdab 	endutxent();
188157212Sdab }  /* end of rmut */
188257212Sdab #endif
188357212Sdab 
1884*60151Sdab #if	!defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
188546809Sdab 	void
188638905Sborman rmut()
188738905Sborman {
188838905Sborman 	register f;
188938905Sborman 	int found = 0;
189038905Sborman 	struct utmp *u, *utmp;
189138905Sborman 	int nutmp;
189238905Sborman 	struct stat statbf;
189338905Sborman 
189438905Sborman 	f = open(utmpf, O_RDWR);
189538905Sborman 	if (f >= 0) {
189638905Sborman 		(void) fstat(f, &statbf);
189738905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
189838905Sborman 		if (!utmp)
189938905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
190038905Sborman 		if (statbf.st_size && utmp) {
190138905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
190238905Sborman 			nutmp /= sizeof(struct utmp);
190338905Sborman 
190438905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
190538905Sborman 				if (SCMPN(u->ut_line, line+5) ||
190638905Sborman 				    u->ut_name[0]==0)
190738905Sborman 					continue;
190838905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
190938905Sborman 				SCPYN(u->ut_name, "");
191038905Sborman 				SCPYN(u->ut_host, "");
191138905Sborman 				(void) time(&u->ut_time);
191238905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
191338905Sborman 				found++;
191438905Sborman 			}
191538905Sborman 		}
191638905Sborman 		(void) close(f);
191738905Sborman 	}
191838905Sborman 	if (found) {
191938905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
192038905Sborman 		if (f >= 0) {
192138905Sborman 			SCPYN(wtmp.ut_line, line+5);
192238905Sborman 			SCPYN(wtmp.ut_name, "");
192338905Sborman 			SCPYN(wtmp.ut_host, "");
192438905Sborman 			(void) time(&wtmp.ut_time);
192538905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
192638905Sborman 			(void) close(f);
192738905Sborman 		}
192838905Sborman 	}
192938905Sborman 	(void) chmod(line, 0666);
193038905Sborman 	(void) chown(line, 0, 0);
193138905Sborman 	line[strlen("/dev/")] = 'p';
193238905Sborman 	(void) chmod(line, 0666);
193338905Sborman 	(void) chown(line, 0, 0);
193438905Sborman }  /* end of rmut */
193538905Sborman #endif	/* CRAY */
1936*60151Sdab 
1937*60151Sdab #ifdef __hpux
1938*60151Sdab rmut (line)
1939*60151Sdab char *line;
1940*60151Sdab {
1941*60151Sdab 	struct utmp utmp;
1942*60151Sdab 	struct utmp *utptr;
1943*60151Sdab 	int fd;			/* for /etc/wtmp */
1944*60151Sdab 
1945*60151Sdab 	utmp.ut_type = USER_PROCESS;
1946*60151Sdab 	(void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
1947*60151Sdab 	(void) setutent();
1948*60151Sdab 	utptr = getutid(&utmp);
1949*60151Sdab 	/* write it out only if it exists */
1950*60151Sdab 	if (utptr) {
1951*60151Sdab 		utptr->ut_type = DEAD_PROCESS;
1952*60151Sdab 		utptr->ut_time = time((long *) 0);
1953*60151Sdab 		(void) pututline(utptr);
1954*60151Sdab 		/* set wtmp entry if wtmp file exists */
1955*60151Sdab 		if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
1956*60151Sdab 			(void) write(fd, utptr, sizeof(utmp));
1957*60151Sdab 			(void) close(fd);
1958*60151Sdab 		}
1959*60151Sdab 	}
1960*60151Sdab 	(void) endutent();
1961*60151Sdab 
1962*60151Sdab 	(void) chmod(line, 0666);
1963*60151Sdab 	(void) chown(line, 0, 0);
1964*60151Sdab 	line[14] = line[13];
1965*60151Sdab 	line[13] = line[12];
1966*60151Sdab 	line[8] = 'm';
1967*60151Sdab 	line[9] = '/';
1968*60151Sdab 	line[10] = 'p';
1969*60151Sdab 	line[11] = 't';
1970*60151Sdab 	line[12] = 'y';
1971*60151Sdab 	(void) chmod(line, 0666);
1972*60151Sdab 	(void) chown(line, 0, 0);
1973*60151Sdab }
1974*60151Sdab #endif
1975