xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 57212)
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*57212Sdab static char sccsid[] = "@(#)sys_term.c	5.17 (Berkeley) 12/18/92";
1038905Sborman #endif /* not lint */
1138905Sborman 
1238905Sborman #include "telnetd.h"
1338905Sborman #include "pathnames.h"
1438905Sborman 
15*57212Sdab #if	defined(AUTHENTICATION)
1646809Sdab #include <libtelnet/auth.h>
1746809Sdab #endif
1846809Sdab 
1938905Sborman #ifdef	NEWINIT
2038905Sborman #include <initreq.h>
2138905Sborman #else	/* NEWINIT*/
22*57212Sdab # ifdef	UTMPX
23*57212Sdab # include <utmpx.h>
24*57212Sdab # else
25*57212Sdab # include <utmp.h>
26*57212Sdab # endif /* UTMPX */
2738905Sborman struct	utmp wtmp;
2838905Sborman 
29*57212Sdab int	utmp_len = sizeof(wtmp.ut_host);
3038905Sborman # ifndef CRAY
3138905Sborman char	wtmpf[]	= "/usr/adm/wtmp";
3238905Sborman char	utmpf[] = "/etc/utmp";
3338905Sborman # else	/* CRAY */
3438905Sborman char	wtmpf[]	= "/etc/wtmp";
3546809Sdab #include <tmpdir.h>
3646809Sdab #include <sys/wait.h>
37*57212Sdab #  if defined(_SC_CRAY_SECURE_SYS)
38*57212Sdab #include <sys/sysv.h>
39*57212Sdab #include <sys/secstat.h>
40*57212Sdab extern int secflag;
41*57212Sdab extern struct sysv sysv;
42*57212Sdab #  endif /* _SC_CRAY_SECURE_SYS */
4338905Sborman # endif	/* CRAY */
4438905Sborman #endif	/* NEWINIT */
4538905Sborman 
46*57212Sdab #ifdef	STREAMSPTY
47*57212Sdab #include <sac.h>
48*57212Sdab #include <sys/stropts.h>
49*57212Sdab #endif
50*57212Sdab 
5138905Sborman #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
5238905Sborman #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
5338905Sborman 
5444364Sborman #ifdef	STREAMS
5544364Sborman #include <sys/stream.h>
5644364Sborman #endif
5738905Sborman #include <sys/tty.h>
5838905Sborman #ifdef	t_erase
5938905Sborman #undef	t_erase
6038905Sborman #undef	t_kill
6138905Sborman #undef	t_intrc
6238905Sborman #undef	t_quitc
6338905Sborman #undef	t_startc
6438905Sborman #undef	t_stopc
6538905Sborman #undef	t_eofc
6638905Sborman #undef	t_brkc
6738905Sborman #undef	t_suspc
6838905Sborman #undef	t_dsuspc
6938905Sborman #undef	t_rprntc
7038905Sborman #undef	t_flushc
7138905Sborman #undef	t_werasc
7238905Sborman #undef	t_lnextc
7338905Sborman #endif
7438905Sborman 
7544364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
7644364Sborman # define EXTPROC 0400
7744364Sborman #endif
7844364Sborman 
7938905Sborman #ifndef	USE_TERMIO
8038905Sborman struct termbuf {
8138905Sborman 	struct sgttyb sg;
8238905Sborman 	struct tchars tc;
8338905Sborman 	struct ltchars ltc;
8438905Sborman 	int state;
8538905Sborman 	int lflags;
8638905Sborman } termbuf, termbuf2;
8745234Sborman # define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
8845234Sborman # define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
8946809Sdab # define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
9046809Sdab # define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
9138905Sborman #else	/* USE_TERMIO */
9238905Sborman # ifdef	SYSV_TERMIO
9338905Sborman #	define termios termio
9438905Sborman # endif
9545234Sborman # ifndef	TCSANOW
9644364Sborman #  ifdef TCSETS
9745234Sborman #   define	TCSANOW		TCSETS
9845234Sborman #   define	TCSADRAIN	TCSETSW
9946809Sdab #   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
10044364Sborman #  else
10145234Sborman #   ifdef TCSETA
10245234Sborman #    define	TCSANOW		TCSETA
10345234Sborman #    define	TCSADRAIN	TCSETAW
10446809Sdab #    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
10545234Sborman #   else
10645234Sborman #    define	TCSANOW		TIOCSETA
10745234Sborman #    define	TCSADRAIN	TIOCSETAW
10846809Sdab #    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
10945234Sborman #   endif
11044364Sborman #  endif
11145234Sborman #  define	tcsetattr(f, a, t)	ioctl(f, a, t)
11245234Sborman #  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
11345234Sborman 					(tp)->c_cflag |= (val)
11446809Sdab #  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
11545234Sborman #  ifdef CIBAUD
11645234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
11745234Sborman 					(tp)->c_cflag |= ((val)<<IBSHIFT)
11846809Sdab #   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
11945234Sborman #  else
12045234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
12145234Sborman 					(tp)->c_cflag |= (val)
12246809Sdab #   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
12345234Sborman #  endif
12445234Sborman # endif /* TCSANOW */
12538905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
126*57212Sdab int ttyfd = -1;
12738905Sborman #endif	/* USE_TERMIO */
12838905Sborman 
12938905Sborman /*
13038905Sborman  * init_termbuf()
13138905Sborman  * copy_termbuf(cp)
13238905Sborman  * set_termbuf()
13338905Sborman  *
13438905Sborman  * These three routines are used to get and set the "termbuf" structure
13538905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
13638905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
13738905Sborman  * set_termbuf() writes the structure into the kernel.
13838905Sborman  */
13938905Sborman 
14046809Sdab 	void
14138905Sborman init_termbuf()
14238905Sborman {
14338905Sborman #ifndef	USE_TERMIO
14438905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
14538905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
14638905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
14738905Sborman # ifdef	TIOCGSTATE
14838905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
14938905Sborman # endif
15038905Sborman #else
151*57212Sdab 	(void) tcgetattr(ttyfd, &termbuf);
15238905Sborman #endif
15338905Sborman 	termbuf2 = termbuf;
15438905Sborman }
15538905Sborman 
15638905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
15746809Sdab 	void
15838905Sborman copy_termbuf(cp, len)
15946809Sdab 	char *cp;
16046809Sdab 	int len;
16138905Sborman {
16238905Sborman 	if (len > sizeof(termbuf))
16338905Sborman 		len = sizeof(termbuf);
16438905Sborman 	bcopy(cp, (char *)&termbuf, len);
16538905Sborman 	termbuf2 = termbuf;
16638905Sborman }
16738905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
16838905Sborman 
16946809Sdab 	void
17038905Sborman set_termbuf()
17138905Sborman {
17238905Sborman 	/*
17338905Sborman 	 * Only make the necessary changes.
17438905Sborman 	 */
17538905Sborman #ifndef	USE_TERMIO
17638905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
17745234Sborman 		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
17838905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
17938905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
18038905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
18138905Sborman 							sizeof(termbuf.ltc)))
18238905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
18338905Sborman 	if (termbuf.lflags != termbuf2.lflags)
18438905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
18538905Sborman #else	/* USE_TERMIO */
18638905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
187*57212Sdab 		(void) tcsetattr(ttyfd, TCSANOW, &termbuf);
188*57212Sdab # if	defined(CRAY2) && defined(UNICOS5)
18938905Sborman 	needtermstat = 1;
19038905Sborman # endif
19138905Sborman #endif	/* USE_TERMIO */
19238905Sborman }
19338905Sborman 
19438905Sborman 
19538905Sborman /*
19638905Sborman  * spcset(func, valp, valpp)
19738905Sborman  *
19838905Sborman  * This function takes various special characters (func), and
19938905Sborman  * sets *valp to the current value of that character, and
20038905Sborman  * *valpp to point to where in the "termbuf" structure that
20138905Sborman  * value is kept.
20238905Sborman  *
20338905Sborman  * It returns the SLC_ level of support for this function.
20438905Sborman  */
20538905Sborman 
20638905Sborman #ifndef	USE_TERMIO
20746809Sdab 	int
20838905Sborman spcset(func, valp, valpp)
20946809Sdab 	int func;
21046809Sdab 	cc_t *valp;
21146809Sdab 	cc_t **valpp;
21238905Sborman {
21338905Sborman 	switch(func) {
21438905Sborman 	case SLC_EOF:
21538905Sborman 		*valp = termbuf.tc.t_eofc;
21640242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
21738905Sborman 		return(SLC_VARIABLE);
21838905Sborman 	case SLC_EC:
21938905Sborman 		*valp = termbuf.sg.sg_erase;
22040242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
22138905Sborman 		return(SLC_VARIABLE);
22238905Sborman 	case SLC_EL:
22338905Sborman 		*valp = termbuf.sg.sg_kill;
22440242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
22538905Sborman 		return(SLC_VARIABLE);
22638905Sborman 	case SLC_IP:
22738905Sborman 		*valp = termbuf.tc.t_intrc;
22840242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
22938905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
23038905Sborman 	case SLC_ABORT:
23138905Sborman 		*valp = termbuf.tc.t_quitc;
23240242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
23338905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
23438905Sborman 	case SLC_XON:
23538905Sborman 		*valp = termbuf.tc.t_startc;
23640242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
23738905Sborman 		return(SLC_VARIABLE);
23838905Sborman 	case SLC_XOFF:
23938905Sborman 		*valp = termbuf.tc.t_stopc;
24040242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
24138905Sborman 		return(SLC_VARIABLE);
24238905Sborman 	case SLC_AO:
24338905Sborman 		*valp = termbuf.ltc.t_flushc;
24440242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
24538905Sborman 		return(SLC_VARIABLE);
24638905Sborman 	case SLC_SUSP:
24738905Sborman 		*valp = termbuf.ltc.t_suspc;
24840242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
24938905Sborman 		return(SLC_VARIABLE);
25038905Sborman 	case SLC_EW:
25138905Sborman 		*valp = termbuf.ltc.t_werasc;
25240242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
25338905Sborman 		return(SLC_VARIABLE);
25438905Sborman 	case SLC_RP:
25538905Sborman 		*valp = termbuf.ltc.t_rprntc;
25640242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
25738905Sborman 		return(SLC_VARIABLE);
25838905Sborman 	case SLC_LNEXT:
25938905Sborman 		*valp = termbuf.ltc.t_lnextc;
26040242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
26138905Sborman 		return(SLC_VARIABLE);
26240242Sborman 	case SLC_FORW1:
26340242Sborman 		*valp = termbuf.tc.t_brkc;
26440242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
26540242Sborman 		return(SLC_VARIABLE);
26638905Sborman 	case SLC_BRK:
26738905Sborman 	case SLC_SYNCH:
26838905Sborman 	case SLC_AYT:
26938905Sborman 	case SLC_EOR:
27040242Sborman 		*valp = (cc_t)0;
27140242Sborman 		*valpp = (cc_t *)0;
27238905Sborman 		return(SLC_DEFAULT);
27338905Sborman 	default:
27440242Sborman 		*valp = (cc_t)0;
27540242Sborman 		*valpp = (cc_t *)0;
27638905Sborman 		return(SLC_NOSUPPORT);
27738905Sborman 	}
27838905Sborman }
27938905Sborman 
28038905Sborman #else	/* USE_TERMIO */
28138905Sborman 
28246809Sdab 	int
28338905Sborman spcset(func, valp, valpp)
28446809Sdab 	int func;
28546809Sdab 	cc_t *valp;
28646809Sdab 	cc_t **valpp;
28738905Sborman {
28839503Sborman 
28939503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
29039503Sborman 			*valpp = &termbuf.c_cc[a]; \
29139503Sborman 			return(b);
29240242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
29339503Sborman 
29438905Sborman 	switch(func) {
29538905Sborman 	case SLC_EOF:
29639503Sborman 		setval(VEOF, SLC_VARIABLE);
29738905Sborman 	case SLC_EC:
29839503Sborman 		setval(VERASE, SLC_VARIABLE);
29938905Sborman 	case SLC_EL:
30039503Sborman 		setval(VKILL, SLC_VARIABLE);
30138905Sborman 	case SLC_IP:
30239503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
30338905Sborman 	case SLC_ABORT:
30439503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
30538905Sborman 	case SLC_XON:
30639503Sborman #ifdef	VSTART
30739503Sborman 		setval(VSTART, SLC_VARIABLE);
30839503Sborman #else
30939503Sborman 		defval(0x13);
31039503Sborman #endif
31138905Sborman 	case SLC_XOFF:
31239503Sborman #ifdef	VSTOP
31339503Sborman 		setval(VSTOP, SLC_VARIABLE);
31439503Sborman #else
31539503Sborman 		defval(0x11);
31639503Sborman #endif
31738905Sborman 	case SLC_EW:
31839503Sborman #ifdef	VWERASE
31939503Sborman 		setval(VWERASE, SLC_VARIABLE);
32039503Sborman #else
32139503Sborman 		defval(0);
32239503Sborman #endif
32338905Sborman 	case SLC_RP:
32439503Sborman #ifdef	VREPRINT
32539503Sborman 		setval(VREPRINT, SLC_VARIABLE);
32639503Sborman #else
32739503Sborman 		defval(0);
32839503Sborman #endif
32938905Sborman 	case SLC_LNEXT:
33039503Sborman #ifdef	VLNEXT
33139503Sborman 		setval(VLNEXT, SLC_VARIABLE);
33239503Sborman #else
33339503Sborman 		defval(0);
33439503Sborman #endif
33539503Sborman 	case SLC_AO:
33645234Sborman #if	!defined(VDISCARD) && defined(VFLUSHO)
33745234Sborman # define VDISCARD VFLUSHO
33845234Sborman #endif
33945234Sborman #ifdef	VDISCARD
34045234Sborman 		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
34139503Sborman #else
34239503Sborman 		defval(0);
34339503Sborman #endif
34439503Sborman 	case SLC_SUSP:
34539503Sborman #ifdef	VSUSP
34639503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
34739503Sborman #else
34839503Sborman 		defval(0);
34939503Sborman #endif
35040242Sborman #ifdef	VEOL
35140242Sborman 	case SLC_FORW1:
35240242Sborman 		setval(VEOL, SLC_VARIABLE);
35340242Sborman #endif
35440242Sborman #ifdef	VEOL2
35540242Sborman 	case SLC_FORW2:
35640242Sborman 		setval(VEOL2, SLC_VARIABLE);
35740242Sborman #endif
35845234Sborman 	case SLC_AYT:
35945234Sborman #ifdef	VSTATUS
36045234Sborman 		setval(VSTATUS, SLC_VARIABLE);
36145234Sborman #else
36245234Sborman 		defval(0);
36345234Sborman #endif
36439503Sborman 
36538905Sborman 	case SLC_BRK:
36638905Sborman 	case SLC_SYNCH:
36738905Sborman 	case SLC_EOR:
36839503Sborman 		defval(0);
36939503Sborman 
37038905Sborman 	default:
37138905Sborman 		*valp = 0;
37238905Sborman 		*valpp = 0;
37338905Sborman 		return(SLC_NOSUPPORT);
37438905Sborman 	}
37538905Sborman }
37638905Sborman #endif	/* USE_TERMIO */
37738905Sborman 
37840242Sborman #ifdef CRAY
37938905Sborman /*
38040242Sborman  * getnpty()
38140242Sborman  *
38240242Sborman  * Return the number of pty's configured into the system.
38340242Sborman  */
38446809Sdab 	int
38540242Sborman getnpty()
38640242Sborman {
38740242Sborman #ifdef _SC_CRAY_NPTY
38846809Sdab 	int numptys;
38946809Sdab 
39046809Sdab 	if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
39146809Sdab 		return numptys;
39246809Sdab 	else
39340242Sborman #endif /* _SC_CRAY_NPTY */
39446809Sdab 		return 128;
39540242Sborman }
39640242Sborman #endif /* CRAY */
39740242Sborman 
39845234Sborman #ifndef	convex
39940242Sborman /*
40038905Sborman  * getpty()
40138905Sborman  *
40238905Sborman  * Allocate a pty.  As a side effect, the external character
40338905Sborman  * array "line" contains the name of the slave side.
40438905Sborman  *
40538905Sborman  * Returns the file descriptor of the opened pty.
40638905Sborman  */
40745234Sborman #ifndef	__GNUC__
40838905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
40945234Sborman #else
41045234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
41145234Sborman char *line = Xline;
41245234Sborman #endif
41345234Sborman #ifdef	CRAY
41445234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
41545234Sborman #endif	/* CRAY */
41638905Sborman 
41746809Sdab 	int
41838905Sborman getpty()
41938905Sborman {
42038905Sborman 	register int p;
421*57212Sdab #ifdef	STREAMSPTY
422*57212Sdab 	int t;
423*57212Sdab 	char *ptsname();
424*57212Sdab 
425*57212Sdab 	p = open("/dev/ptmx", 2);
426*57212Sdab 	if (p > 0) {
427*57212Sdab 		grantpt(p);
428*57212Sdab 		unlockpt(p);
429*57212Sdab 		strcpy(line, ptsname(p));
430*57212Sdab 		return(p);
431*57212Sdab 	}
432*57212Sdab 
433*57212Sdab #else	/* ! STREAMSPTY */
43438905Sborman #ifndef CRAY
435*57212Sdab 	register char *cp, *p1, *p2;
43638905Sborman 	register int i;
437*57212Sdab #if defined(sun) && defined(TIOCGPGRP)
438*57212Sdab 	int dummy;
439*57212Sdab #endif
44038905Sborman 
44138905Sborman 	(void) sprintf(line, "/dev/ptyXX");
44238905Sborman 	p1 = &line[8];
44338905Sborman 	p2 = &line[9];
44438905Sborman 
445*57212Sdab 	for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
44638905Sborman 		struct stat stb;
44738905Sborman 
448*57212Sdab 		*p1 = *cp;
44938905Sborman 		*p2 = '0';
450*57212Sdab 		/*
451*57212Sdab 		 * This stat() check is just to keep us from
452*57212Sdab 		 * looping through all 256 combinations if there
453*57212Sdab 		 * aren't that many ptys available.
454*57212Sdab 		 */
45538905Sborman 		if (stat(line, &stb) < 0)
45638905Sborman 			break;
45738905Sborman 		for (i = 0; i < 16; i++) {
45838905Sborman 			*p2 = "0123456789abcdef"[i];
45938905Sborman 			p = open(line, 2);
46038905Sborman 			if (p > 0) {
46138905Sborman 				line[5] = 't';
462*57212Sdab 				chown(line, 0, 0);
463*57212Sdab 				chmod(line, 0600);
464*57212Sdab #if defined(sun) && defined(TIOCGPGRP)
465*57212Sdab 				if (ioctl(p, TIOCGPGRP, &dummy) == 0
466*57212Sdab 				    || errno != EIO) {
467*57212Sdab 					chmod(line, 0666);
468*57212Sdab 					close(p);
469*57212Sdab 					line[5] = 'p';
470*57212Sdab 				} else
471*57212Sdab #endif /* defined(sun) && defined(TIOCGPGRP) */
472*57212Sdab 					return(p);
47338905Sborman 			}
47438905Sborman 		}
47538905Sborman 	}
47638905Sborman #else	/* CRAY */
47738905Sborman 	register int npty;
47838905Sborman 	extern lowpty, highpty;
47945234Sborman 	struct stat sb;
48038905Sborman 
48138905Sborman 	for (npty = lowpty; npty <= highpty; npty++) {
48245234Sborman 		(void) sprintf(myline, "/dev/pty/%03d", npty);
48345234Sborman 		p = open(myline, 2);
48438905Sborman 		if (p < 0)
48538905Sborman 			continue;
48638905Sborman 		(void) sprintf(line, "/dev/ttyp%03d", npty);
48745234Sborman 		/*
48845234Sborman 		 * Here are some shenanigans to make sure that there
48945234Sborman 		 * are no listeners lurking on the line.
49045234Sborman 		 */
49145234Sborman 		if(stat(line, &sb) < 0) {
49245234Sborman 			(void) close(p);
49345234Sborman 			continue;
49445234Sborman 		}
49545234Sborman 		if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
49645234Sborman 			chown(line, 0, 0);
49745234Sborman 			chmod(line, 0600);
49845234Sborman 			(void)close(p);
49945234Sborman 			p = open(myline, 2);
50045234Sborman 			if (p < 0)
50145234Sborman 				continue;
50245234Sborman 		}
50345234Sborman 		/*
50445234Sborman 		 * Now it should be safe...check for accessability.
50545234Sborman 		 */
50638905Sborman 		if (access(line, 6) == 0)
50738905Sborman 			return(p);
50838905Sborman 		else {
50938905Sborman 			/* no tty side to pty so skip it */
51038905Sborman 			(void) close(p);
51138905Sborman 		}
51238905Sborman 	}
51338905Sborman #endif	/* CRAY */
514*57212Sdab #endif	/* STREAMSPTY */
51538905Sborman 	return(-1);
51638905Sborman }
51745234Sborman #endif	/* convex */
51838905Sborman 
51938905Sborman #ifdef	LINEMODE
52038905Sborman /*
52138905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
52238905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
52338905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
52438905Sborman  * tty_isecho()		Find out if echoing is turned on.
52538905Sborman  * tty_setecho(on)	Enable/disable character echoing.
52638905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
52738905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
52838905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
52938905Sborman  * tty_isediting()	Find out if line editing is enabled.
53038905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
53138905Sborman  * tty_setedit(on)	Turn on/off line editing.
53238905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
53344364Sborman  * tty_issofttab()	Find out if tab expansion is enabled.
53444364Sborman  * tty_setsofttab(on)	Turn on/off soft tab expansion.
53544364Sborman  * tty_islitecho()	Find out if typed control chars are echoed literally
53644364Sborman  * tty_setlitecho()	Turn on/off literal echo of control chars
53738905Sborman  * tty_tspeed(val)	Set transmit speed to val.
53838905Sborman  * tty_rspeed(val)	Set receive speed to val.
53938905Sborman  */
54038905Sborman 
54146809Sdab 	int
54238905Sborman tty_flowmode()
54338905Sborman {
54438905Sborman #ifndef USE_TERMIO
54546809Sdab 	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
54638905Sborman #else
54738905Sborman 	return(termbuf.c_iflag & IXON ? 1 : 0);
54838905Sborman #endif
54938905Sborman }
55038905Sborman 
551*57212Sdab 	int
552*57212Sdab tty_restartany()
553*57212Sdab {
554*57212Sdab #ifndef USE_TERMIO
555*57212Sdab # ifdef	DECCTQ
556*57212Sdab 	return((termbuf.lflags & DECCTQ) ? 0 : 1);
557*57212Sdab # else
558*57212Sdab 	return(-1);
559*57212Sdab # endif
560*57212Sdab #else
561*57212Sdab 	return(termbuf.c_iflag & IXANY ? 1 : 0);
562*57212Sdab #endif
563*57212Sdab }
564*57212Sdab 
56545234Sborman #ifdef convex
56645234Sborman static int linestate;
56745234Sborman #endif
56845234Sborman 
56946809Sdab 	int
57038905Sborman tty_linemode()
57138905Sborman {
57245234Sborman #ifndef convex
57338905Sborman #ifndef	USE_TERMIO
57438905Sborman 	return(termbuf.state & TS_EXTPROC);
57538905Sborman #else
57638905Sborman 	return(termbuf.c_lflag & EXTPROC);
57738905Sborman #endif
57845234Sborman #else
57945234Sborman 	return(linestate);
58045234Sborman #endif
58138905Sborman }
58238905Sborman 
58346809Sdab 	void
58438905Sborman tty_setlinemode(on)
58546809Sdab 	int on;
58638905Sborman {
58738905Sborman #ifdef	TIOCEXT
58845234Sborman # ifndef convex
58945234Sborman 	set_termbuf();
59045234Sborman # else
59145234Sborman 	linestate = on;
59245234Sborman # endif
59338905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
59445234Sborman # ifndef convex
59545234Sborman 	init_termbuf();
59645234Sborman # endif
59738905Sborman #else	/* !TIOCEXT */
59845234Sborman # ifdef	EXTPROC
59938905Sborman 	if (on)
60038905Sborman 		termbuf.c_lflag |= EXTPROC;
60138905Sborman 	else
60238905Sborman 		termbuf.c_lflag &= ~EXTPROC;
60345234Sborman # endif
60438905Sborman #endif	/* TIOCEXT */
60538905Sborman }
60638905Sborman 
60746809Sdab 	int
60838905Sborman tty_isecho()
60938905Sborman {
61038905Sborman #ifndef USE_TERMIO
61138905Sborman 	return (termbuf.sg.sg_flags & ECHO);
61238905Sborman #else
61338905Sborman 	return (termbuf.c_lflag & ECHO);
61438905Sborman #endif
61538905Sborman }
61638905Sborman #endif	/* LINEMODE */
61738905Sborman 
61846809Sdab 	void
61938905Sborman tty_setecho(on)
62046809Sdab 	int on;
62138905Sborman {
62238905Sborman #ifndef	USE_TERMIO
62338905Sborman 	if (on)
62438905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
62538905Sborman 	else
62638905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
62738905Sborman #else
62838905Sborman 	if (on)
62938905Sborman 		termbuf.c_lflag |= ECHO;
63038905Sborman 	else
63138905Sborman 		termbuf.c_lflag &= ~ECHO;
63238905Sborman #endif
63338905Sborman }
63438905Sborman 
63538905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
63646809Sdab 	int
63738905Sborman tty_israw()
63838905Sborman {
63938905Sborman #ifndef USE_TERMIO
64038905Sborman 	return(termbuf.sg.sg_flags & RAW);
64138905Sborman #else
64238905Sborman 	return(!(termbuf.c_lflag & ICANON));
64338905Sborman #endif
64438905Sborman }
64538905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
64638905Sborman 
64746809Sdab 	void
64838905Sborman tty_binaryin(on)
64946809Sdab 	int on;
65038905Sborman {
65138905Sborman #ifndef	USE_TERMIO
65238905Sborman 	if (on)
65338905Sborman 		termbuf.lflags |= LPASS8;
65438905Sborman 	else
65538905Sborman 		termbuf.lflags &= ~LPASS8;
65638905Sborman #else
65738905Sborman 	if (on) {
65846809Sdab 		termbuf.c_iflag &= ~ISTRIP;
65938905Sborman 	} else {
66046809Sdab 		termbuf.c_iflag |= ISTRIP;
66138905Sborman 	}
66238905Sborman #endif
66338905Sborman }
66438905Sborman 
66546809Sdab 	void
66638905Sborman tty_binaryout(on)
66746809Sdab 	int on;
66838905Sborman {
66938905Sborman #ifndef	USE_TERMIO
67038905Sborman 	if (on)
67138905Sborman 		termbuf.lflags |= LLITOUT;
67238905Sborman 	else
67338905Sborman 		termbuf.lflags &= ~LLITOUT;
67438905Sborman #else
67538905Sborman 	if (on) {
67638905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
67738905Sborman 		termbuf.c_cflag |= CS8;
67838905Sborman 		termbuf.c_oflag &= ~OPOST;
67938905Sborman 	} else {
68038905Sborman 		termbuf.c_cflag &= ~CSIZE;
68138905Sborman 		termbuf.c_cflag |= CS7|PARENB;
68238905Sborman 		termbuf.c_oflag |= OPOST;
68338905Sborman 	}
68438905Sborman #endif
68538905Sborman }
68638905Sborman 
68746809Sdab 	int
68838905Sborman tty_isbinaryin()
68938905Sborman {
69038905Sborman #ifndef	USE_TERMIO
69138905Sborman 	return(termbuf.lflags & LPASS8);
69238905Sborman #else
69339503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
69438905Sborman #endif
69538905Sborman }
69638905Sborman 
69746809Sdab 	int
69838905Sborman tty_isbinaryout()
69938905Sborman {
70038905Sborman #ifndef	USE_TERMIO
70138905Sborman 	return(termbuf.lflags & LLITOUT);
70238905Sborman #else
70339503Sborman 	return(!(termbuf.c_oflag&OPOST));
70438905Sborman #endif
70538905Sborman }
70638905Sborman 
70738905Sborman #ifdef	LINEMODE
70846809Sdab 	int
70938905Sborman tty_isediting()
71038905Sborman {
71138905Sborman #ifndef USE_TERMIO
71238905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
71338905Sborman #else
71438905Sborman 	return(termbuf.c_lflag & ICANON);
71538905Sborman #endif
71638905Sborman }
71738905Sborman 
71846809Sdab 	int
71938905Sborman tty_istrapsig()
72038905Sborman {
72138905Sborman #ifndef USE_TERMIO
72238905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
72338905Sborman #else
72438905Sborman 	return(termbuf.c_lflag & ISIG);
72538905Sborman #endif
72638905Sborman }
72738905Sborman 
72846809Sdab 	void
72938905Sborman tty_setedit(on)
73046809Sdab 	int on;
73138905Sborman {
73238905Sborman #ifndef USE_TERMIO
73338905Sborman 	if (on)
73438905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
73538905Sborman 	else
73638905Sborman 		termbuf.sg.sg_flags |= CBREAK;
73738905Sborman #else
73838905Sborman 	if (on)
73938905Sborman 		termbuf.c_lflag |= ICANON;
74038905Sborman 	else
74138905Sborman 		termbuf.c_lflag &= ~ICANON;
74238905Sborman #endif
74338905Sborman }
74438905Sborman 
74546809Sdab 	void
74638905Sborman tty_setsig(on)
74746809Sdab 	int on;
74838905Sborman {
74938905Sborman #ifndef	USE_TERMIO
75038905Sborman 	if (on)
75138905Sborman 		;
75238905Sborman #else
75338905Sborman 	if (on)
75438905Sborman 		termbuf.c_lflag |= ISIG;
75538905Sborman 	else
75638905Sborman 		termbuf.c_lflag &= ~ISIG;
75738905Sborman #endif
75838905Sborman }
75938905Sborman #endif	/* LINEMODE */
76038905Sborman 
76146809Sdab 	int
76244364Sborman tty_issofttab()
76344364Sborman {
76444364Sborman #ifndef	USE_TERMIO
76544364Sborman 	return (termbuf.sg.sg_flags & XTABS);
76644364Sborman #else
76744364Sborman # ifdef	OXTABS
76844364Sborman 	return (termbuf.c_oflag & OXTABS);
76944364Sborman # endif
77044364Sborman # ifdef	TABDLY
77144364Sborman 	return ((termbuf.c_oflag & TABDLY) == TAB3);
77244364Sborman # endif
77344364Sborman #endif
77444364Sborman }
77544364Sborman 
77646809Sdab 	void
77744364Sborman tty_setsofttab(on)
77846809Sdab 	int on;
77944364Sborman {
78044364Sborman #ifndef	USE_TERMIO
78144364Sborman 	if (on)
78244364Sborman 		termbuf.sg.sg_flags |= XTABS;
78344364Sborman 	else
78444364Sborman 		termbuf.sg.sg_flags &= ~XTABS;
78544364Sborman #else
78644364Sborman 	if (on) {
78744364Sborman # ifdef	OXTABS
78844364Sborman 		termbuf.c_oflag |= OXTABS;
78944364Sborman # endif
79044364Sborman # ifdef	TABDLY
79144364Sborman 		termbuf.c_oflag &= ~TABDLY;
79244364Sborman 		termbuf.c_oflag |= TAB3;
79344364Sborman # endif
79444364Sborman 	} else {
79544364Sborman # ifdef	OXTABS
79644364Sborman 		termbuf.c_oflag &= ~OXTABS;
79744364Sborman # endif
79844364Sborman # ifdef	TABDLY
79944364Sborman 		termbuf.c_oflag &= ~TABDLY;
80044364Sborman 		termbuf.c_oflag |= TAB0;
80144364Sborman # endif
80244364Sborman 	}
80344364Sborman #endif
80444364Sborman }
80544364Sborman 
80646809Sdab 	int
80744364Sborman tty_islitecho()
80844364Sborman {
80944364Sborman #ifndef	USE_TERMIO
81046809Sdab 	return (!(termbuf.lflags & LCTLECH));
81144364Sborman #else
81244364Sborman # ifdef	ECHOCTL
81344364Sborman 	return (!(termbuf.c_lflag & ECHOCTL));
81444364Sborman # endif
81544364Sborman # ifdef	TCTLECH
81644364Sborman 	return (!(termbuf.c_lflag & TCTLECH));
81744364Sborman # endif
81844364Sborman # if	!defined(ECHOCTL) && !defined(TCTLECH)
81944364Sborman 	return (0);	/* assumes ctl chars are echoed '^x' */
82044364Sborman # endif
82144364Sborman #endif
82244364Sborman }
82344364Sborman 
82446809Sdab 	void
82544364Sborman tty_setlitecho(on)
82646809Sdab 	int on;
82744364Sborman {
82844364Sborman #ifndef	USE_TERMIO
82944364Sborman 	if (on)
83046809Sdab 		termbuf.lflags &= ~LCTLECH;
83144364Sborman 	else
83246809Sdab 		termbuf.lflags |= LCTLECH;
83344364Sborman #else
83444364Sborman # ifdef	ECHOCTL
83544364Sborman 	if (on)
83644364Sborman 		termbuf.c_lflag &= ~ECHOCTL;
83744364Sborman 	else
83844364Sborman 		termbuf.c_lflag |= ECHOCTL;
83944364Sborman # endif
84044364Sborman # ifdef	TCTLECH
84144364Sborman 	if (on)
84244364Sborman 		termbuf.c_lflag &= ~TCTLECH;
84344364Sborman 	else
84444364Sborman 		termbuf.c_lflag |= TCTLECH;
84544364Sborman # endif
84644364Sborman #endif
84744364Sborman }
84844364Sborman 
84946809Sdab 	int
85046809Sdab tty_iscrnl()
85146809Sdab {
85246809Sdab #ifndef	USE_TERMIO
85346809Sdab 	return (termbuf.sg.sg_flags & CRMOD);
85446809Sdab #else
85546809Sdab 	return (termbuf.c_iflag & ICRNL);
85646809Sdab #endif
85746809Sdab }
85846809Sdab 
85938905Sborman /*
86038905Sborman  * A table of available terminal speeds
86138905Sborman  */
86238905Sborman struct termspeeds {
86338905Sborman 	int	speed;
86438905Sborman 	int	value;
86538905Sborman } termspeeds[] = {
86638905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
86738905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
86838905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
86938905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
87038905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
87138905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
87238905Sborman };
87338905Sborman 
87446809Sdab 	void
87538905Sborman tty_tspeed(val)
87646809Sdab 	int val;
87738905Sborman {
87838905Sborman 	register struct termspeeds *tp;
87938905Sborman 
88038905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
88138905Sborman 		;
88245234Sborman 	cfsetospeed(&termbuf, tp->value);
88338905Sborman }
88438905Sborman 
88546809Sdab 	void
88638905Sborman tty_rspeed(val)
88746809Sdab 	int val;
88838905Sborman {
88938905Sborman 	register struct termspeeds *tp;
89038905Sborman 
89138905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
89238905Sborman 		;
89345234Sborman 	cfsetispeed(&termbuf, tp->value);
89438905Sborman }
89538905Sborman 
89640242Sborman #if	defined(CRAY2) && defined(UNICOS5)
89746809Sdab 	int
89838905Sborman tty_isnewmap()
89938905Sborman {
90038905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
90138905Sborman 			!(termbuf.c_oflag & ONLRET));
90238905Sborman }
90338905Sborman #endif
90438905Sborman 
90538905Sborman #ifdef	CRAY
90638905Sborman # ifndef NEWINIT
90738905Sborman extern	struct utmp wtmp;
90838905Sborman extern char wtmpf[];
90938905Sborman # else	/* NEWINIT */
91038905Sborman int	gotalarm;
91146809Sdab 
91246809Sdab 	/* ARGSUSED */
91346809Sdab 	void
91440242Sborman nologinproc(sig)
91546809Sdab 	int sig;
91638905Sborman {
91738905Sborman 	gotalarm++;
91838905Sborman }
91938905Sborman # endif	/* NEWINIT */
92038905Sborman #endif /* CRAY */
92138905Sborman 
92246809Sdab #ifndef	NEWINIT
92346809Sdab # ifdef	CRAY
92446809Sdab extern void utmp_sig_init P((void));
92546809Sdab extern void utmp_sig_reset P((void));
92646809Sdab extern void utmp_sig_wait P((void));
92746809Sdab extern void utmp_sig_notify P((int));
92846809Sdab # endif
92946809Sdab #endif
93046809Sdab 
93138905Sborman /*
93238905Sborman  * getptyslave()
93338905Sborman  *
93438905Sborman  * Open the slave side of the pty, and do any initialization
93538905Sborman  * that is necessary.  The return value is a file descriptor
93638905Sborman  * for the slave side.
93738905Sborman  */
93846809Sdab 	int
93938905Sborman getptyslave()
94038905Sborman {
94138905Sborman 	register int t = -1;
94238905Sborman 
94345234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
94445234Sborman # ifdef	LINEMODE
94546809Sdab 	int waslm;
94646809Sdab # endif
94746809Sdab # ifdef	TIOCGWINSZ
94846809Sdab 	struct winsize ws;
94946809Sdab 	extern int def_row, def_col;
95046809Sdab # endif
95146809Sdab 	extern int def_tspeed, def_rspeed;
95238905Sborman 	/*
95345234Sborman 	 * Opening the slave side may cause initilization of the
95446809Sdab 	 * kernel tty structure.  We need remember the state of
95546809Sdab 	 * 	if linemode was turned on
95646809Sdab 	 *	terminal window size
95746809Sdab 	 *	terminal speed
95846809Sdab 	 * so that we can re-set them if we need to.
95938905Sborman 	 */
96046809Sdab # ifdef	LINEMODE
96146809Sdab 	waslm = tty_linemode();
96245234Sborman # endif
96345234Sborman 
96445234Sborman 
96545234Sborman 	/*
96645234Sborman 	 * Make sure that we don't have a controlling tty, and
96745234Sborman 	 * that we are the session (process group) leader.
96845234Sborman 	 */
96945234Sborman # ifdef	TIOCNOTTY
97038905Sborman 	t = open(_PATH_TTY, O_RDWR);
97138905Sborman 	if (t >= 0) {
97238905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
97338905Sborman 		(void) close(t);
97438905Sborman 	}
97545234Sborman # endif
97638905Sborman 
97745234Sborman 
97845234Sborman # ifdef	CRAY
97945234Sborman 	/*
98045234Sborman 	 * Wait for our parent to get the utmp stuff to get done.
98145234Sborman 	 */
98245234Sborman 	utmp_sig_wait();
98345234Sborman # endif
98445234Sborman 
98545234Sborman 	t = cleanopen(line);
98638905Sborman 	if (t < 0)
98738905Sborman 		fatalperror(net, line);
98838905Sborman 
989*57212Sdab #ifdef	USE_TERMIO
990*57212Sdab 	ttyfd = t;
991*57212Sdab #endif
992*57212Sdab #ifdef  STREAMSPTY
993*57212Sdab 	if (ioctl(t, I_PUSH, "ptem") < 0)
994*57212Sdab 		fatal(net, "I_PUSH ptem");
995*57212Sdab 	if (ioctl(t, I_PUSH, "ldterm") < 0)
996*57212Sdab 		fatal(net, "I_PUSH ldterm");
997*57212Sdab 	if (ioctl(t, I_PUSH, "ttcompat") < 0)
998*57212Sdab 		fatal(net, "I_PUSH ttcompat");
999*57212Sdab 	if (ioctl(pty, I_PUSH, "pckt") < 0)
1000*57212Sdab 		fatal(net, "I_PUSH pckt");
1001*57212Sdab #endif
1002*57212Sdab 
100345234Sborman 	/*
100445234Sborman 	 * set up the tty modes as we like them to be.
100545234Sborman 	 */
100638905Sborman 	init_termbuf();
100746809Sdab # ifdef	TIOCGWINSZ
100846809Sdab 	if (def_row || def_col) {
100946809Sdab 		bzero((char *)&ws, sizeof(ws));
101046809Sdab 		ws.ws_col = def_col;
101146809Sdab 		ws.ws_row = def_row;
101246809Sdab 		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
101346809Sdab 	}
101446809Sdab # endif
101545234Sborman 
101645234Sborman 	/*
101745234Sborman 	 * Settings for sgtty based systems
101845234Sborman 	 */
101945234Sborman # ifndef	USE_TERMIO
102040242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
102145234Sborman # endif	/* USE_TERMIO */
102245234Sborman 
102345234Sborman 	/*
102445234Sborman 	 * Settings for UNICOS
102545234Sborman 	 */
102645234Sborman # ifdef	CRAY
102745234Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
102845234Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
102945234Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
103045234Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
103145234Sborman # endif
103245234Sborman 
103345234Sborman 	/*
103445234Sborman 	 * Settings for all other termios/termio based
103545234Sborman 	 * systems, other than 4.4BSD.  In 4.4BSD the
103645234Sborman 	 * kernel does the initial terminal setup.
103745234Sborman 	 */
103845234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43)
103945234Sborman #  ifndef	OXTABS
104045234Sborman #   define OXTABS	0
104145234Sborman #  endif
104238905Sborman 	termbuf.c_lflag |= ECHO;
104338905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
104438905Sborman 	termbuf.c_iflag |= ICRNL;
104538905Sborman 	termbuf.c_iflag &= ~IXOFF;
104645234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
104746996Sdab 	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
104846996Sdab 	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
104946809Sdab # ifdef	LINEMODE
105046809Sdab 	if (waslm)
105146809Sdab 		tty_setlinemode(1);
105246809Sdab # endif	/* LINEMODE */
105345234Sborman 
105445234Sborman 	/*
105545234Sborman 	 * Set the tty modes, and make this our controlling tty.
105645234Sborman 	 */
105745234Sborman 	set_termbuf();
105845234Sborman 	if (login_tty(t) == -1)
105945234Sborman 		fatalperror(net, "login_tty");
106045234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
106145234Sborman 	if (net > 2)
106245234Sborman 		(void) close(net);
106345234Sborman 	if (pty > 2)
106445234Sborman 		(void) close(pty);
106545234Sborman }
106645234Sborman 
106745234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
106845234Sborman #ifndef	O_NOCTTY
106945234Sborman #define	O_NOCTTY	0
107038905Sborman #endif
107145234Sborman /*
107245234Sborman  * Open the specified slave side of the pty,
107345234Sborman  * making sure that we have a clean tty.
107445234Sborman  */
107546809Sdab 	int
107645234Sborman cleanopen(line)
107746809Sdab 	char *line;
107845234Sborman {
107945234Sborman 	register int t;
1080*57212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
1081*57212Sdab 	struct secstat secbuf;
1082*57212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
108345234Sborman 
1084*57212Sdab #ifndef STREAMSPTY
108545234Sborman 	/*
108645234Sborman 	 * Make sure that other people can't open the
108745234Sborman 	 * slave side of the connection.
108845234Sborman 	 */
108938905Sborman 	(void) chown(line, 0, 0);
109038905Sborman 	(void) chmod(line, 0600);
1091*57212Sdab #endif
109245234Sborman 
109345234Sborman # if !defined(CRAY) && (BSD > 43)
109445234Sborman 	(void) revoke(line);
109545234Sborman # endif
1096*57212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
1097*57212Sdab 	if (secflag) {
1098*57212Sdab 		if (secstat(line, &secbuf) < 0)
1099*57212Sdab 			return(-1);
1100*57212Sdab 		if (setulvl(secbuf.st_slevel) < 0)
1101*57212Sdab 			return(-1);
1102*57212Sdab 		if (setucmp(secbuf.st_compart) < 0)
1103*57212Sdab 			return(-1);
1104*57212Sdab 	}
1105*57212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
1106*57212Sdab 
110745234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
1108*57212Sdab 
1109*57212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
1110*57212Sdab 	if (secflag) {
1111*57212Sdab 		if (setulvl(sysv.sy_minlvl) < 0)
1112*57212Sdab 			return(-1);
1113*57212Sdab 		if (setucmp(0) < 0)
1114*57212Sdab 			return(-1);
1115*57212Sdab 	}
1116*57212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
1117*57212Sdab 
111845234Sborman 	if (t < 0)
111945234Sborman 		return(-1);
112045234Sborman 
112145234Sborman 	/*
112245234Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
112345234Sborman 	 * ourselves.
112445234Sborman 	 */
1125*57212Sdab # if !defined(CRAY) && (BSD <= 43) && !defined(STREAMSPTY)
112645234Sborman 	(void) signal(SIGHUP, SIG_IGN);
112745234Sborman 	vhangup();
112845234Sborman 	(void) signal(SIGHUP, SIG_DFL);
112945234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
113045234Sborman 	if (t < 0)
113145234Sborman 		return(-1);
113245234Sborman # endif
113345234Sborman # if	defined(CRAY) && defined(TCVHUP)
113445234Sborman 	{
113545234Sborman 		register int i;
113645234Sborman 		(void) signal(SIGHUP, SIG_IGN);
113745234Sborman 		(void) ioctl(t, TCVHUP, (char *)0);
113845234Sborman 		(void) signal(SIGHUP, SIG_DFL);
113945234Sborman 		setpgrp();
1140*57212Sdab 
1141*57212Sdab #if		defined(_SC_CRAY_SECURE_SYS)
1142*57212Sdab 		if (secflag) {
1143*57212Sdab 			if (secstat(line, &secbuf) < 0)
1144*57212Sdab 				return(-1);
1145*57212Sdab 			if (setulvl(secbuf.st_slevel) < 0)
1146*57212Sdab 				return(-1);
1147*57212Sdab 			if (setucmp(secbuf.st_compart) < 0)
1148*57212Sdab 				return(-1);
1149*57212Sdab 		}
1150*57212Sdab #endif		/* _SC_CRAY_SECURE_SYS */
1151*57212Sdab 
115245234Sborman 		i = open(line, O_RDWR);
1153*57212Sdab 
1154*57212Sdab #if		defined(_SC_CRAY_SECURE_SYS)
1155*57212Sdab 		if (secflag) {
1156*57212Sdab 			if (setulvl(sysv.sy_minlvl) < 0)
1157*57212Sdab 				return(-1);
1158*57212Sdab 			if (setucmp(0) < 0)
1159*57212Sdab 				return(-1);
1160*57212Sdab 		}
1161*57212Sdab #endif		/* _SC_CRAY_SECURE_SYS */
1162*57212Sdab 
116345234Sborman 		if (i < 0)
116446809Sdab 			return(-1);
116545234Sborman 		(void) close(t);
116645234Sborman 		t = i;
116745234Sborman 	}
116845234Sborman # endif	/* defined(CRAY) && defined(TCVHUP) */
116938905Sborman 	return(t);
117038905Sborman }
117145234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
117238905Sborman 
117345234Sborman #if BSD <= 43
117446809Sdab 	int
117545234Sborman login_tty(t)
117646809Sdab 	int t;
117745234Sborman {
117845234Sborman 	if (setsid() < 0)
117945234Sborman 		fatalperror(net, "setsid()");
118045234Sborman # ifdef	TIOCSCTTY
118145234Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
118245234Sborman 		fatalperror(net, "ioctl(sctty)");
1183*57212Sdab #  if defined(CRAY)
118447613Sdab 	/*
118547613Sdab 	 * Close the hard fd to /dev/ttypXXX, and re-open through
118647613Sdab 	 * the indirect /dev/tty interface.
118747613Sdab 	 */
118847613Sdab 	close(t);
118947613Sdab 	if ((t = open("/dev/tty", O_RDWR)) < 0)
119047613Sdab 		fatalperror(net, "open(/dev/tty)");
119147613Sdab #  endif
119245234Sborman # else
119345234Sborman 	close(open(line, O_RDWR));
119445234Sborman # endif
119547613Sdab 	if (t != 0)
119647613Sdab 		(void) dup2(t, 0);
119747613Sdab 	if (t != 1)
119847613Sdab 		(void) dup2(t, 1);
119947613Sdab 	if (t != 2)
120047613Sdab 		(void) dup2(t, 2);
120147613Sdab 	if (t > 2)
120247613Sdab 		close(t);
120346809Sdab 	return(0);
120445234Sborman }
120545234Sborman #endif	/* BSD <= 43 */
120645234Sborman 
120738905Sborman #ifdef	NEWINIT
120838905Sborman char *gen_id = "fe";
120938905Sborman #endif
121038905Sborman 
121138905Sborman /*
121245234Sborman  * startslave(host)
121338905Sborman  *
121445234Sborman  * Given a hostname, do whatever
121538905Sborman  * is necessary to startup the login process on the slave side of the pty.
121638905Sborman  */
121738905Sborman 
121838905Sborman /* ARGSUSED */
121946809Sdab 	void
122046809Sdab startslave(host, autologin, autoname)
122146809Sdab 	char *host;
122246809Sdab 	int autologin;
122346809Sdab 	char *autoname;
122438905Sborman {
122538905Sborman 	register int i;
122638905Sborman 	long time();
122746809Sdab 	char name[256];
122846809Sdab #ifdef	NEWINIT
122946809Sdab 	extern char *ptyip;
123046809Sdab 	struct init_request request;
123146809Sdab 	void nologinproc();
123246809Sdab 	register int n;
123346809Sdab #endif	/* NEWINIT */
123438905Sborman 
1235*57212Sdab #if	defined(AUTHENTICATION)
123646809Sdab 	if (!autoname || !autoname[0])
123746809Sdab 		autologin = 0;
123846809Sdab 
123946809Sdab 	if (autologin < auth_level) {
124046809Sdab 		fatal(net, "Authorization failed");
124146809Sdab 		exit(1);
124246809Sdab 	}
124346809Sdab #endif
124446809Sdab 
124538905Sborman #ifndef	NEWINIT
124638905Sborman # ifdef	CRAY
124738905Sborman 	utmp_sig_init();
124838905Sborman # endif	/* CRAY */
124938905Sborman 
125038905Sborman 	if ((i = fork()) < 0)
125138905Sborman 		fatalperror(net, "fork");
125238905Sborman 	if (i) {
125338905Sborman # ifdef	CRAY
125438905Sborman 		/*
125538905Sborman 		 * Cray parent will create utmp entry for child and send
125638905Sborman 		 * signal to child to tell when done.  Child waits for signal
125738905Sborman 		 * before doing anything important.
125838905Sborman 		 */
125938905Sborman 		register int pid = i;
126046809Sdab 		void sigjob P((int));
126138905Sborman 
126238905Sborman 		setpgrp();
126344364Sborman 		utmp_sig_reset();		/* reset handler to default */
126438905Sborman 		/*
126538905Sborman 		 * Create utmp entry for child
126638905Sborman 		 */
126738905Sborman 		(void) time(&wtmp.ut_time);
126838905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
126938905Sborman 		wtmp.ut_pid = pid;
127038905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
127138905Sborman 		SCPYN(wtmp.ut_host, host);
127238905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
127338905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
127438905Sborman 		pututline(&wtmp);
127538905Sborman 		endutent();
127638905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
127738905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
127838905Sborman 			(void) close(i);
127938905Sborman 		}
128046809Sdab 		(void) signal(WJSIGNAL, sigjob);
128138905Sborman 		utmp_sig_notify(pid);
128238905Sborman # endif	/* CRAY */
128338905Sborman 	} else {
128445234Sborman 		getptyslave();
128546809Sdab 		start_login(host, autologin, autoname);
128638905Sborman 		/*NOTREACHED*/
128738905Sborman 	}
128838905Sborman #else	/* NEWINIT */
128938905Sborman 
129038905Sborman 	/*
129138905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
129238905Sborman 	 * for it to start up and begin normal telnet operation.
129338905Sborman 	 */
129438905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
129538905Sborman 		char tbuf[128];
129638905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
129738905Sborman 		fatalperror(net, tbuf);
129838905Sborman 	}
129938905Sborman 	memset((char *)&request, 0, sizeof(request));
130038905Sborman 	request.magic = INIT_MAGIC;
130138905Sborman 	SCPYN(request.gen_id, gen_id);
130238905Sborman 	SCPYN(request.tty_id, &line[8]);
130338905Sborman 	SCPYN(request.host, host);
130446809Sdab 	SCPYN(request.term_type, terminaltype ? terminaltype : "network");
130544364Sborman #if	!defined(UNICOS5)
130640242Sborman 	request.signal = SIGCLD;
130740242Sborman 	request.pid = getpid();
130840242Sborman #endif
130944364Sborman #ifdef BFTPDAEMON
131044364Sborman 	/*
131144364Sborman 	 * Are we working as the bftp daemon?
131244364Sborman 	 */
131344364Sborman 	if (bftpd) {
131444364Sborman 		SCPYN(request.exec_name, BFTPPATH);
131544364Sborman 	}
131644364Sborman #endif /* BFTPDAEMON */
131738905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
131838905Sborman 		char tbuf[128];
131938905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
132038905Sborman 		fatalperror(net, tbuf);
132138905Sborman 	}
132238905Sborman 	(void) close(i);
132338905Sborman 	(void) signal(SIGALRM, nologinproc);
132438905Sborman 	for (i = 0; ; i++) {
132540242Sborman 		char tbuf[128];
132638905Sborman 		alarm(15);
132738905Sborman 		n = read(pty, ptyip, BUFSIZ);
132838905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
132938905Sborman 			break;
133038905Sborman 		gotalarm = 0;
133140242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
133240242Sborman 		(void) write(net, tbuf, strlen(tbuf));
133338905Sborman 	}
133438905Sborman 	if (n < 0 && gotalarm)
133538905Sborman 		fatal(net, "/etc/init didn't start login process");
133638905Sborman 	pcc += n;
133738905Sborman 	alarm(0);
133838905Sborman 	(void) signal(SIGALRM, SIG_DFL);
133938905Sborman 
134038905Sborman 	return;
134138905Sborman #endif	/* NEWINIT */
134238905Sborman }
134338905Sborman 
134438905Sborman char	*envinit[3];
134544364Sborman extern char **environ;
134638905Sborman 
134746809Sdab 	void
134844364Sborman init_env()
134944364Sborman {
135044364Sborman 	extern char *getenv();
135144364Sborman 	char **envp;
135244364Sborman 
135344364Sborman 	envp = envinit;
135444364Sborman 	if (*envp = getenv("TZ"))
135544364Sborman 		*envp++ -= 3;
135644364Sborman #ifdef	CRAY
135744364Sborman 	else
135844364Sborman 		*envp++ = "TZ=GMT0";
135944364Sborman #endif
136044364Sborman 	*envp = 0;
136144364Sborman 	environ = envinit;
136244364Sborman }
136344364Sborman 
136444364Sborman #ifndef	NEWINIT
136544364Sborman 
136644364Sborman /*
136745234Sborman  * start_login(host)
136838905Sborman  *
136938905Sborman  * Assuming that we are now running as a child processes, this
137038905Sborman  * function will turn us into the login process.
137138905Sborman  */
137238905Sborman 
137346809Sdab 	void
137446809Sdab start_login(host, autologin, name)
137546809Sdab 	char *host;
137646809Sdab 	int autologin;
137746809Sdab 	char *name;
137838905Sborman {
137944364Sborman 	register char *cp;
138044364Sborman 	register char **argv;
138144364Sborman 	char **addarg();
1382*57212Sdab #ifdef	UTMPX
1383*57212Sdab 	register int pid = getpid();
1384*57212Sdab 	struct utmpx utmpx;
1385*57212Sdab #endif
1386*57212Sdab #ifdef __svr4__
1387*57212Sdab 	char *term;
1388*57212Sdab 	char termbuf[64];
1389*57212Sdab #endif
139038905Sborman 
1391*57212Sdab #ifdef	UTMPX
139238905Sborman 	/*
1393*57212Sdab 	 * Create utmp entry for child
1394*57212Sdab 	 */
1395*57212Sdab 
1396*57212Sdab 	bzero(&utmpx, sizeof(utmpx));
1397*57212Sdab 	SCPYN(utmpx.ut_user, ".telnet");
1398*57212Sdab 	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
1399*57212Sdab 	utmpx.ut_pid = pid;
1400*57212Sdab 	utmpx.ut_id[0] = 't';
1401*57212Sdab 	utmpx.ut_id[1] = 'n';
1402*57212Sdab 	utmpx.ut_id[2] = SC_WILDC;
1403*57212Sdab 	utmpx.ut_id[3] = SC_WILDC;
1404*57212Sdab 	utmpx.ut_type = LOGIN_PROCESS;
1405*57212Sdab 	(void) time(&utmpx.ut_tv.tv_sec);
1406*57212Sdab 	if (makeutx(&utmpx) == NULL)
1407*57212Sdab 		fatal(net, "makeutx failed");
1408*57212Sdab #endif
1409*57212Sdab 
1410*57212Sdab 	/*
141138905Sborman 	 * -h : pass on name of host.
141238905Sborman 	 *		WARNING:  -h is accepted by login if and only if
141338905Sborman 	 *			getuid() == 0.
141438905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
141546809Sdab 	 *
141646809Sdab 	 * -f : force this login, he has already been authenticated
141738905Sborman 	 */
141844364Sborman 	argv = addarg(0, "login");
141944364Sborman 	argv = addarg(argv, "-h");
142044364Sborman 	argv = addarg(argv, host);
1421*57212Sdab #ifdef	__svr4__
1422*57212Sdab 	/*
1423*57212Sdab 	 * SVR4 version of -h takes TERM= as second arg, or -
1424*57212Sdab 	 */
1425*57212Sdab 	term = getenv("TERM");
1426*57212Sdab 	if (term == NULL || term[0] == 0) {
1427*57212Sdab 		term = "-";
1428*57212Sdab 	} else {
1429*57212Sdab 		strcpy(termbuf, "TERM=");
1430*57212Sdab 		strncat(termbuf, term, sizeof(termbuf) - 6);
1431*57212Sdab 		term = termbuf;
1432*57212Sdab 	}
1433*57212Sdab 	argv = addarg(argv, term);
1434*57212Sdab #endif
143546809Sdab #if	!defined(NO_LOGIN_P)
143644364Sborman 	argv = addarg(argv, "-p");
143738905Sborman #endif
143844364Sborman #ifdef	BFTPDAEMON
143944364Sborman 	/*
144044364Sborman 	 * Are we working as the bftp daemon?  If so, then ask login
144144364Sborman 	 * to start bftp instead of shell.
144244364Sborman 	 */
144344364Sborman 	if (bftpd) {
144444364Sborman 		argv = addarg(argv, "-e");
144544364Sborman 		argv = addarg(argv, BFTPPATH);
144644364Sborman 	} else
144744364Sborman #endif
144846809Sdab #if	defined (SecurID)
144946809Sdab 	/*
145046809Sdab 	 * don't worry about the -f that might get sent.
145146809Sdab 	 * A -s is supposed to override it anyhow.
145246809Sdab 	 */
145346809Sdab 	if (require_SecurID)
145446809Sdab 		argv = addarg(argv, "-s");
145546809Sdab #endif
1456*57212Sdab #if	defined (AUTHENTICATION)
145746809Sdab 	if (auth_level >= 0 && autologin == AUTH_VALID) {
145846809Sdab # if	!defined(NO_LOGIN_F)
145946809Sdab 		argv = addarg(argv, "-f");
146046809Sdab # endif
146146809Sdab 		argv = addarg(argv, name);
146246809Sdab 	} else
146346809Sdab #endif
146444364Sborman 	if (getenv("USER")) {
146544364Sborman 		argv = addarg(argv, getenv("USER"));
146646809Sdab #if	defined(CRAY) && defined(NO_LOGIN_P)
146746809Sdab 		{
146846809Sdab 			register char **cpp;
146946809Sdab 			for (cpp = environ; *cpp; cpp++)
147046809Sdab 				argv = addarg(argv, *cpp);
147146809Sdab 		}
147246809Sdab #endif
1473*57212Sdab 		/*
1474*57212Sdab 		 * Assume that login will set the USER variable
1475*57212Sdab 		 * correctly.  For SysV systems, this means that
1476*57212Sdab 		 * USER will no longer be set, just LOGNAME by
1477*57212Sdab 		 * login.  (The problem is that if the auto-login
1478*57212Sdab 		 * fails, and the user then specifies a different
1479*57212Sdab 		 * account name, he can get logged in with both
1480*57212Sdab 		 * LOGNAME and USER in his environment, but the
1481*57212Sdab 		 * USER value will be wrong.
1482*57212Sdab 		 */
1483*57212Sdab 		unsetenv("USER");
148444364Sborman 	}
148546809Sdab 	closelog();
148644364Sborman 	execv(_PATH_LOGIN, argv);
148744364Sborman 
148838905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
148938905Sborman 	fatalperror(net, _PATH_LOGIN);
149038905Sborman 	/*NOTREACHED*/
149138905Sborman }
149244364Sborman 
149346809Sdab 	char **
149444364Sborman addarg(argv, val)
149546809Sdab 	register char **argv;
149646809Sdab 	register char *val;
149744364Sborman {
149844364Sborman 	register char **cpp;
149944364Sborman 
150044364Sborman 	if (argv == NULL) {
150144364Sborman 		/*
150244364Sborman 		 * 10 entries, a leading length, and a null
150344364Sborman 		 */
150444364Sborman 		argv = (char **)malloc(sizeof(*argv) * 12);
150544364Sborman 		if (argv == NULL)
150644364Sborman 			return(NULL);
150744364Sborman 		*argv++ = (char *)10;
150844364Sborman 		*argv = (char *)0;
150944364Sborman 	}
151044364Sborman 	for (cpp = argv; *cpp; cpp++)
151144364Sborman 		;
151244364Sborman 	if (cpp == &argv[(int)argv[-1]]) {
151344364Sborman 		--argv;
151444364Sborman 		*argv = (char *)((int)(*argv) + 10);
151544364Sborman 		argv = (char **)realloc(argv, (int)(*argv) + 2);
151644364Sborman 		if (argv == NULL)
151744364Sborman 			return(NULL);
151844364Sborman 		argv++;
151944364Sborman 		cpp = &argv[(int)argv[-1] - 10];
152044364Sborman 	}
152144364Sborman 	*cpp++ = val;
152244364Sborman 	*cpp = 0;
152344364Sborman 	return(argv);
152444364Sborman }
152546809Sdab #endif	/* NEWINIT */
152638905Sborman 
152738905Sborman /*
152838905Sborman  * cleanup()
152938905Sborman  *
153038905Sborman  * This is the routine to call when we are all through, to
153138905Sborman  * clean up anything that needs to be cleaned up.
153238905Sborman  */
153346809Sdab 	/* ARGSUSED */
153446809Sdab 	void
153546809Sdab cleanup(sig)
153646809Sdab 	int sig;
153738905Sborman {
153838905Sborman #ifndef	CRAY
153945234Sborman # if (BSD > 43) || defined(convex)
154038905Sborman 	char *p;
154138905Sborman 
154238905Sborman 	p = line + sizeof("/dev/") - 1;
154338905Sborman 	if (logout(p))
154438905Sborman 		logwtmp(p, "", "");
154538905Sborman 	(void)chmod(line, 0666);
154638905Sborman 	(void)chown(line, 0, 0);
154738905Sborman 	*p = 'p';
154838905Sborman 	(void)chmod(line, 0666);
154938905Sborman 	(void)chown(line, 0, 0);
155046809Sdab 	(void) shutdown(net, 2);
155146809Sdab 	exit(1);
155238905Sborman # else
155346809Sdab 	void rmut();
155446809Sdab 
155538905Sborman 	rmut();
155638905Sborman 	vhangup();	/* XXX */
155746809Sdab 	(void) shutdown(net, 2);
155846809Sdab 	exit(1);
155938905Sborman # endif
156038905Sborman #else	/* CRAY */
156146809Sdab # ifdef	NEWINIT
156238905Sborman 	(void) shutdown(net, 2);
156346809Sdab 	exit(1);
156438905Sborman # else	/* NEWINIT */
156546809Sdab 	static int incleanup = 0;
156646809Sdab 	register int t;
156746809Sdab 
156846809Sdab 	/*
156946809Sdab 	 * 1: Pick up the zombie, if we are being called
157046809Sdab 	 *    as the signal handler.
157146809Sdab 	 * 2: If we are a nested cleanup(), return.
157246809Sdab 	 * 3: Try to clean up TMPDIR.
157346809Sdab 	 * 4: Fill in utmp with shutdown of process.
157446809Sdab 	 * 5: Close down the network and pty connections.
157546809Sdab 	 * 6: Finish up the TMPDIR cleanup, if needed.
157646809Sdab 	 */
157746809Sdab 	if (sig == SIGCHLD)
157846809Sdab 		while (waitpid(-1, 0, WNOHANG) > 0)
157946809Sdab 			;	/* VOID */
158046809Sdab 	t = sigblock(sigmask(SIGCHLD));
158146809Sdab 	if (incleanup) {
158246809Sdab 		sigsetmask(t);
158346809Sdab 		return;
158446809Sdab 	}
158546809Sdab 	incleanup = 1;
158646809Sdab 	sigsetmask(t);
158746809Sdab 
158846809Sdab 	t = cleantmp(&wtmp);
158946809Sdab 	setutent();	/* just to make sure */
159046809Sdab 	rmut(line);
159146809Sdab 	close(pty);
159238905Sborman 	(void) shutdown(net, 2);
159346809Sdab 	if (t == 0)
159446809Sdab 		cleantmp(&wtmp);
159546809Sdab 	exit(1);
159638905Sborman # endif	/* NEWINT */
159738905Sborman #endif	/* CRAY */
159838905Sborman }
159938905Sborman 
160038905Sborman #if	defined(CRAY) && !defined(NEWINIT)
160138905Sborman /*
160238905Sborman  * _utmp_sig_rcv
160338905Sborman  * utmp_sig_init
160438905Sborman  * utmp_sig_wait
160538905Sborman  *	These three functions are used to coordinate the handling of
160638905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
160738905Sborman  *	The server actually creates the utmp structure, the child calls
160838905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
160938905Sborman  *	signals the future-login shell to proceed.
161038905Sborman  */
161138905Sborman static int caught=0;		/* NZ when signal intercepted */
161238905Sborman static void (*func)();		/* address of previous handler */
161338905Sborman 
161446809Sdab 	void
161538905Sborman _utmp_sig_rcv(sig)
161646809Sdab 	int sig;
161738905Sborman {
161838905Sborman 	caught = 1;
161938905Sborman 	(void) signal(SIGUSR1, func);
162038905Sborman }
162138905Sborman 
162246809Sdab 	void
162338905Sborman utmp_sig_init()
162438905Sborman {
162538905Sborman 	/*
162638905Sborman 	 * register signal handler for UTMP creation
162738905Sborman 	 */
162838905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
162938905Sborman 		fatalperror(net, "telnetd/signal");
163038905Sborman }
163138905Sborman 
163246809Sdab 	void
163344364Sborman utmp_sig_reset()
163444364Sborman {
163544364Sborman 	(void) signal(SIGUSR1, func);	/* reset handler to default */
163644364Sborman }
163744364Sborman 
163846809Sdab 	void
163938905Sborman utmp_sig_wait()
164038905Sborman {
164138905Sborman 	/*
164238905Sborman 	 * Wait for parent to write our utmp entry.
164338905Sborman 	 */
164438905Sborman 	sigoff();
164538905Sborman 	while (caught == 0) {
164638905Sborman 		pause();	/* wait until we get a signal (sigon) */
164738905Sborman 		sigoff();	/* turn off signals while we check caught */
164838905Sborman 	}
164938905Sborman 	sigon();		/* turn on signals again */
165038905Sborman }
165138905Sborman 
165246809Sdab 	void
165338905Sborman utmp_sig_notify(pid)
165438905Sborman {
165538905Sborman 	kill(pid, SIGUSR1);
165638905Sborman }
165746809Sdab 
165846809Sdab static int gotsigjob = 0;
165946809Sdab 
166046809Sdab 	/*ARGSUSED*/
166146809Sdab 	void
166246809Sdab sigjob(sig)
166346809Sdab 	int sig;
166446809Sdab {
166546809Sdab 	register int jid;
166646809Sdab 	register struct jobtemp *jp;
166746809Sdab 
166846809Sdab 	while ((jid = waitjob(NULL)) != -1) {
166946809Sdab 		if (jid == 0) {
167046809Sdab 			return;
167146809Sdab 		}
167246809Sdab 		gotsigjob++;
167346809Sdab 		jobend(jid, NULL, NULL);
167446809Sdab 	}
167546809Sdab }
167646809Sdab 
167746809Sdab /*
167846809Sdab  * Clean up the TMPDIR that login created.
167946809Sdab  * The first time this is called we pick up the info
168046809Sdab  * from the utmp.  If the job has already gone away,
168146809Sdab  * then we'll clean up and be done.  If not, then
168246809Sdab  * when this is called the second time it will wait
168346809Sdab  * for the signal that the job is done.
168446809Sdab  */
168546809Sdab 	int
168646809Sdab cleantmp(wtp)
168746809Sdab 	register struct utmp *wtp;
168846809Sdab {
168946809Sdab 	struct utmp *utp;
169046809Sdab 	static int first = 1;
169146809Sdab 	register int mask, omask, ret;
169246809Sdab 	extern struct utmp *getutid P((struct utmp *));
169346809Sdab 
169446809Sdab 	mask = sigmask(WJSIGNAL);
169546809Sdab 
169646809Sdab 	if (first == 0) {
169746809Sdab 		omask = sigblock(mask);
169846809Sdab 		while (gotsigjob == 0)
169946809Sdab 			sigpause(omask);
170046809Sdab 		return(1);
170146809Sdab 	}
170246809Sdab 	first = 0;
170346809Sdab 	setutent();	/* just to make sure */
170446809Sdab 
170546809Sdab 	utp = getutid(wtp);
170646809Sdab 	if (utp == 0) {
170746809Sdab 		syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
170846809Sdab 		return(-1);
170946809Sdab 	}
171046809Sdab 	/*
171146809Sdab 	 * Nothing to clean up if the user shell was never started.
171246809Sdab 	 */
171346809Sdab 	if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
171446809Sdab 		return(1);
171546809Sdab 
171646809Sdab 	/*
171746809Sdab 	 * Block the WJSIGNAL while we are in jobend().
171846809Sdab 	 */
171946809Sdab 	omask = sigblock(mask);
172046809Sdab 	ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
172146809Sdab 	sigsetmask(omask);
172246809Sdab 	return(ret);
172346809Sdab }
172446809Sdab 
172546809Sdab 	int
172646809Sdab jobend(jid, path, user)
172746809Sdab 	register int jid;
172846809Sdab 	register char *path;
172946809Sdab 	register char *user;
173046809Sdab {
173146809Sdab 	static int saved_jid = 0;
173246809Sdab 	static char saved_path[sizeof(wtmp.ut_tpath)+1];
173346809Sdab 	static char saved_user[sizeof(wtmp.ut_user)+1];
173446809Sdab 
173546809Sdab 	if (path) {
173646809Sdab 		strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
173746809Sdab 		strncpy(saved_user, user, sizeof(wtmp.ut_user));
173846809Sdab 		saved_path[sizeof(saved_path)] = '\0';
173946809Sdab 		saved_user[sizeof(saved_user)] = '\0';
174046809Sdab 	}
174146809Sdab 	if (saved_jid == 0) {
174246809Sdab 		saved_jid = jid;
174346809Sdab 		return(0);
174446809Sdab 	}
174546809Sdab 	cleantmpdir(jid, saved_path, saved_user);
174646809Sdab 	return(1);
174746809Sdab }
174846809Sdab 
174946809Sdab /*
175046809Sdab  * Fork a child process to clean up the TMPDIR
175146809Sdab  */
175246809Sdab cleantmpdir(jid, tpath, user)
175346809Sdab 	register int jid;
175446809Sdab 	register char *tpath;
175546809Sdab 	register char *user;
175646809Sdab {
175746809Sdab 	switch(fork()) {
175846809Sdab 	case -1:
175946809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
176046809Sdab 							tpath);
176146809Sdab 		break;
176246809Sdab 	case 0:
176346809Sdab 		execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
176446809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
176546809Sdab 							tpath, CLEANTMPCMD);
176646809Sdab 		exit(1);
176746809Sdab 	default:
176846809Sdab 		/*
176946809Sdab 		 * Forget about child.  We will exit, and
177046809Sdab 		 * /etc/init will pick it up.
177146809Sdab 		 */
177246809Sdab 		break;
177346809Sdab 	}
177446809Sdab }
177538905Sborman #endif	/* defined(CRAY) && !defined(NEWINIT) */
177638905Sborman 
177738905Sborman /*
177838905Sborman  * rmut()
177938905Sborman  *
178038905Sborman  * This is the function called by cleanup() to
178138905Sborman  * remove the utmp entry for this person.
178238905Sborman  */
178338905Sborman 
1784*57212Sdab #ifdef	UTMPX
1785*57212Sdab rmut()
1786*57212Sdab {
1787*57212Sdab 	register f;
1788*57212Sdab 	int found = 0;
1789*57212Sdab 	struct utmp *u, *utmp;
1790*57212Sdab 	int nutmp;
1791*57212Sdab 	struct stat statbf;
1792*57212Sdab 
1793*57212Sdab 	struct utmpx *utxp, utmpx;
1794*57212Sdab 
1795*57212Sdab 	/*
1796*57212Sdab 	 * This updates the utmpx and utmp entries and make a wtmp/x entry
1797*57212Sdab 	 */
1798*57212Sdab 
1799*57212Sdab 	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
1800*57212Sdab 	utxp = getutxline(&utmpx);
1801*57212Sdab 	if (utxp) {
1802*57212Sdab 		utxp->ut_type = DEAD_PROCESS;
1803*57212Sdab 		utxp->ut_exit.e_termination = 0;
1804*57212Sdab 		utxp->ut_exit.e_exit = 0;
1805*57212Sdab 		(void) time(&utmpx.ut_tv.tv_sec);
1806*57212Sdab 		utmpx.ut_tv.tv_usec = 0;
1807*57212Sdab 		modutx(utxp);
1808*57212Sdab 	}
1809*57212Sdab 	endutxent();
1810*57212Sdab }  /* end of rmut */
1811*57212Sdab #endif
1812*57212Sdab 
1813*57212Sdab #if	!defined(UTMPX) && !defined(CRAY) && BSD <= 43
181446809Sdab 	void
181538905Sborman rmut()
181638905Sborman {
181738905Sborman 	register f;
181838905Sborman 	int found = 0;
181938905Sborman 	struct utmp *u, *utmp;
182038905Sborman 	int nutmp;
182138905Sborman 	struct stat statbf;
182238905Sborman 
182338905Sborman 	f = open(utmpf, O_RDWR);
182438905Sborman 	if (f >= 0) {
182538905Sborman 		(void) fstat(f, &statbf);
182638905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
182738905Sborman 		if (!utmp)
182838905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
182938905Sborman 		if (statbf.st_size && utmp) {
183038905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
183138905Sborman 			nutmp /= sizeof(struct utmp);
183238905Sborman 
183338905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
183438905Sborman 				if (SCMPN(u->ut_line, line+5) ||
183538905Sborman 				    u->ut_name[0]==0)
183638905Sborman 					continue;
183738905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
183838905Sborman 				SCPYN(u->ut_name, "");
183938905Sborman 				SCPYN(u->ut_host, "");
184038905Sborman 				(void) time(&u->ut_time);
184138905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
184238905Sborman 				found++;
184338905Sborman 			}
184438905Sborman 		}
184538905Sborman 		(void) close(f);
184638905Sborman 	}
184738905Sborman 	if (found) {
184838905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
184938905Sborman 		if (f >= 0) {
185038905Sborman 			SCPYN(wtmp.ut_line, line+5);
185138905Sborman 			SCPYN(wtmp.ut_name, "");
185238905Sborman 			SCPYN(wtmp.ut_host, "");
185338905Sborman 			(void) time(&wtmp.ut_time);
185438905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
185538905Sborman 			(void) close(f);
185638905Sborman 		}
185738905Sborman 	}
185838905Sborman 	(void) chmod(line, 0666);
185938905Sborman 	(void) chown(line, 0, 0);
186038905Sborman 	line[strlen("/dev/")] = 'p';
186138905Sborman 	(void) chmod(line, 0666);
186238905Sborman 	(void) chown(line, 0, 0);
186338905Sborman }  /* end of rmut */
186438905Sborman #endif	/* CRAY */
1865