xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 65158)
138905Sborman /*
261451Sbostic  * Copyright (c) 1989, 1993
361451Sbostic  *	The Regents of the University of California.  All rights reserved.
438905Sborman  *
542673Sbostic  * %sccs.include.redist.c%
638905Sborman  */
738905Sborman 
838905Sborman #ifndef lint
9*65158Sdab static char sccsid[] = "@(#)sys_term.c	8.2 (Berkeley) 12/15/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 
1960151Sdab #if defined(CRAY) || defined(__hpux)
2060151Sdab # define PARENT_DOES_UTMP
2160151Sdab #endif
2260151Sdab 
2338905Sborman #ifdef	NEWINIT
2438905Sborman #include <initreq.h>
2560151Sdab int	utmp_len = MAXHOSTNAMELEN;	/* sizeof(init_request.host) */
2638905Sborman #else	/* NEWINIT*/
2757212Sdab # ifdef	UTMPX
2857212Sdab # include <utmpx.h>
29*65158Sdab struct	utmpx wtmp;
3057212Sdab # else
3157212Sdab # include <utmp.h>
32*65158Sdab struct	utmp wtmp;
3357212Sdab # endif /* UTMPX */
3438905Sborman 
3557212Sdab int	utmp_len = sizeof(wtmp.ut_host);
3660151Sdab # ifndef PARENT_DOES_UTMP
3738905Sborman char	wtmpf[]	= "/usr/adm/wtmp";
3838905Sborman char	utmpf[] = "/etc/utmp";
3960151Sdab # else /* PARENT_DOES_UTMP */
4038905Sborman char	wtmpf[]	= "/etc/wtmp";
4160151Sdab # endif /* PARENT_DOES_UTMP */
4260151Sdab 
4360151Sdab # ifdef CRAY
4446809Sdab #include <tmpdir.h>
4546809Sdab #include <sys/wait.h>
4660151Sdab #  if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY)
4760151Sdab    /*
4860151Sdab     * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can
4960151Sdab     * use it to tell us to turn off all the socket security code,
5060151Sdab     * since that is only used in UNICOS 7.0 and later.
5160151Sdab     */
5260151Sdab #   undef _SC_CRAY_SECURE_SYS
5360151Sdab #  endif
5460151Sdab 
5557212Sdab #  if defined(_SC_CRAY_SECURE_SYS)
5657212Sdab #include <sys/sysv.h>
5757212Sdab #include <sys/secstat.h>
5857212Sdab extern int secflag;
5957212Sdab extern struct sysv sysv;
6057212Sdab #  endif /* _SC_CRAY_SECURE_SYS */
6138905Sborman # endif	/* CRAY */
6238905Sborman #endif	/* NEWINIT */
6338905Sborman 
6457212Sdab #ifdef	STREAMSPTY
6557212Sdab #include <sac.h>
6657212Sdab #include <sys/stropts.h>
6757212Sdab #endif
6857212Sdab 
6938905Sborman #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
7038905Sborman #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
7138905Sborman 
7244364Sborman #ifdef	STREAMS
7344364Sborman #include <sys/stream.h>
7444364Sborman #endif
7560151Sdab #ifdef __hpux
7660151Sdab #include <sys/resource.h>
7760151Sdab #include <sys/proc.h>
7860151Sdab #endif
7938905Sborman #include <sys/tty.h>
8038905Sborman #ifdef	t_erase
8138905Sborman #undef	t_erase
8238905Sborman #undef	t_kill
8338905Sborman #undef	t_intrc
8438905Sborman #undef	t_quitc
8538905Sborman #undef	t_startc
8638905Sborman #undef	t_stopc
8738905Sborman #undef	t_eofc
8838905Sborman #undef	t_brkc
8938905Sborman #undef	t_suspc
9038905Sborman #undef	t_dsuspc
9138905Sborman #undef	t_rprntc
9238905Sborman #undef	t_flushc
9338905Sborman #undef	t_werasc
9438905Sborman #undef	t_lnextc
9538905Sborman #endif
9638905Sborman 
9744364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
9844364Sborman # define EXTPROC 0400
9944364Sborman #endif
10044364Sborman 
10138905Sborman #ifndef	USE_TERMIO
10238905Sborman struct termbuf {
10338905Sborman 	struct sgttyb sg;
10438905Sborman 	struct tchars tc;
10538905Sborman 	struct ltchars ltc;
10638905Sborman 	int state;
10738905Sborman 	int lflags;
10838905Sborman } termbuf, termbuf2;
10945234Sborman # define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
11045234Sborman # define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
11146809Sdab # define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
11246809Sdab # define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
11338905Sborman #else	/* USE_TERMIO */
11438905Sborman # ifdef	SYSV_TERMIO
11538905Sborman #	define termios termio
11638905Sborman # endif
11745234Sborman # ifndef	TCSANOW
11844364Sborman #  ifdef TCSETS
11945234Sborman #   define	TCSANOW		TCSETS
12045234Sborman #   define	TCSADRAIN	TCSETSW
12146809Sdab #   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
12244364Sborman #  else
12345234Sborman #   ifdef TCSETA
12445234Sborman #    define	TCSANOW		TCSETA
12545234Sborman #    define	TCSADRAIN	TCSETAW
12646809Sdab #    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
12745234Sborman #   else
12845234Sborman #    define	TCSANOW		TIOCSETA
12945234Sborman #    define	TCSADRAIN	TIOCSETAW
13046809Sdab #    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
13145234Sborman #   endif
13244364Sborman #  endif
13345234Sborman #  define	tcsetattr(f, a, t)	ioctl(f, a, t)
13445234Sborman #  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
13545234Sborman 					(tp)->c_cflag |= (val)
13646809Sdab #  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
13745234Sborman #  ifdef CIBAUD
13845234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
13945234Sborman 					(tp)->c_cflag |= ((val)<<IBSHIFT)
14046809Sdab #   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
14145234Sborman #  else
14245234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
14345234Sborman 					(tp)->c_cflag |= (val)
14446809Sdab #   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
14545234Sborman #  endif
14645234Sborman # endif /* TCSANOW */
14738905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
14857592Sdab # ifdef  STREAMSPTY
14957212Sdab int ttyfd = -1;
15057592Sdab # endif
15138905Sborman #endif	/* USE_TERMIO */
15238905Sborman 
15338905Sborman /*
15438905Sborman  * init_termbuf()
15538905Sborman  * copy_termbuf(cp)
15638905Sborman  * set_termbuf()
15738905Sborman  *
15838905Sborman  * These three routines are used to get and set the "termbuf" structure
15938905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
16038905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
16138905Sborman  * set_termbuf() writes the structure into the kernel.
16238905Sborman  */
16338905Sborman 
16446809Sdab 	void
16538905Sborman init_termbuf()
16638905Sborman {
16738905Sborman #ifndef	USE_TERMIO
16838905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
16938905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
17038905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
17138905Sborman # ifdef	TIOCGSTATE
17238905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
17338905Sborman # endif
17438905Sborman #else
17557592Sdab # ifdef  STREAMSPTY
17657212Sdab 	(void) tcgetattr(ttyfd, &termbuf);
17757592Sdab # else
17857592Sdab 	(void) tcgetattr(pty, &termbuf);
17957592Sdab # endif
18038905Sborman #endif
18138905Sborman 	termbuf2 = termbuf;
18238905Sborman }
18338905Sborman 
18438905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
18546809Sdab 	void
18638905Sborman copy_termbuf(cp, len)
18746809Sdab 	char *cp;
18846809Sdab 	int len;
18938905Sborman {
19038905Sborman 	if (len > sizeof(termbuf))
19138905Sborman 		len = sizeof(termbuf);
19238905Sborman 	bcopy(cp, (char *)&termbuf, len);
19338905Sborman 	termbuf2 = termbuf;
19438905Sborman }
19538905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
19638905Sborman 
19746809Sdab 	void
19838905Sborman set_termbuf()
19938905Sborman {
20038905Sborman 	/*
20138905Sborman 	 * Only make the necessary changes.
20238905Sborman 	 */
20338905Sborman #ifndef	USE_TERMIO
20438905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
20545234Sborman 		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
20638905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
20738905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
20838905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
20938905Sborman 							sizeof(termbuf.ltc)))
21038905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
21138905Sborman 	if (termbuf.lflags != termbuf2.lflags)
21238905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
21338905Sborman #else	/* USE_TERMIO */
21438905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
21557592Sdab # ifdef  STREAMSPTY
21657212Sdab 		(void) tcsetattr(ttyfd, TCSANOW, &termbuf);
21757592Sdab # else
21857592Sdab 		(void) tcsetattr(pty, TCSANOW, &termbuf);
21957592Sdab # endif
22057212Sdab # if	defined(CRAY2) && defined(UNICOS5)
22138905Sborman 	needtermstat = 1;
22238905Sborman # endif
22338905Sborman #endif	/* USE_TERMIO */
22438905Sborman }
22538905Sborman 
22638905Sborman 
22738905Sborman /*
22838905Sborman  * spcset(func, valp, valpp)
22938905Sborman  *
23038905Sborman  * This function takes various special characters (func), and
23138905Sborman  * sets *valp to the current value of that character, and
23238905Sborman  * *valpp to point to where in the "termbuf" structure that
23338905Sborman  * value is kept.
23438905Sborman  *
23538905Sborman  * It returns the SLC_ level of support for this function.
23638905Sborman  */
23738905Sborman 
23838905Sborman #ifndef	USE_TERMIO
23946809Sdab 	int
24038905Sborman spcset(func, valp, valpp)
24146809Sdab 	int func;
24246809Sdab 	cc_t *valp;
24346809Sdab 	cc_t **valpp;
24438905Sborman {
24538905Sborman 	switch(func) {
24638905Sborman 	case SLC_EOF:
24738905Sborman 		*valp = termbuf.tc.t_eofc;
24840242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
24938905Sborman 		return(SLC_VARIABLE);
25038905Sborman 	case SLC_EC:
25138905Sborman 		*valp = termbuf.sg.sg_erase;
25240242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
25338905Sborman 		return(SLC_VARIABLE);
25438905Sborman 	case SLC_EL:
25538905Sborman 		*valp = termbuf.sg.sg_kill;
25640242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
25738905Sborman 		return(SLC_VARIABLE);
25838905Sborman 	case SLC_IP:
25938905Sborman 		*valp = termbuf.tc.t_intrc;
26040242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
26138905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
26238905Sborman 	case SLC_ABORT:
26338905Sborman 		*valp = termbuf.tc.t_quitc;
26440242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
26538905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
26638905Sborman 	case SLC_XON:
26738905Sborman 		*valp = termbuf.tc.t_startc;
26840242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
26938905Sborman 		return(SLC_VARIABLE);
27038905Sborman 	case SLC_XOFF:
27138905Sborman 		*valp = termbuf.tc.t_stopc;
27240242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
27338905Sborman 		return(SLC_VARIABLE);
27438905Sborman 	case SLC_AO:
27538905Sborman 		*valp = termbuf.ltc.t_flushc;
27640242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
27738905Sborman 		return(SLC_VARIABLE);
27838905Sborman 	case SLC_SUSP:
27938905Sborman 		*valp = termbuf.ltc.t_suspc;
28040242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
28138905Sborman 		return(SLC_VARIABLE);
28238905Sborman 	case SLC_EW:
28338905Sborman 		*valp = termbuf.ltc.t_werasc;
28440242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
28538905Sborman 		return(SLC_VARIABLE);
28638905Sborman 	case SLC_RP:
28738905Sborman 		*valp = termbuf.ltc.t_rprntc;
28840242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
28938905Sborman 		return(SLC_VARIABLE);
29038905Sborman 	case SLC_LNEXT:
29138905Sborman 		*valp = termbuf.ltc.t_lnextc;
29240242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
29338905Sborman 		return(SLC_VARIABLE);
29440242Sborman 	case SLC_FORW1:
29540242Sborman 		*valp = termbuf.tc.t_brkc;
29640242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
29740242Sborman 		return(SLC_VARIABLE);
29838905Sborman 	case SLC_BRK:
29938905Sborman 	case SLC_SYNCH:
30038905Sborman 	case SLC_AYT:
30138905Sborman 	case SLC_EOR:
30240242Sborman 		*valp = (cc_t)0;
30340242Sborman 		*valpp = (cc_t *)0;
30438905Sborman 		return(SLC_DEFAULT);
30538905Sborman 	default:
30640242Sborman 		*valp = (cc_t)0;
30740242Sborman 		*valpp = (cc_t *)0;
30838905Sborman 		return(SLC_NOSUPPORT);
30938905Sborman 	}
31038905Sborman }
31138905Sborman 
31238905Sborman #else	/* USE_TERMIO */
31338905Sborman 
31446809Sdab 	int
31538905Sborman spcset(func, valp, valpp)
31646809Sdab 	int func;
31746809Sdab 	cc_t *valp;
31846809Sdab 	cc_t **valpp;
31938905Sborman {
32039503Sborman 
32139503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
32239503Sborman 			*valpp = &termbuf.c_cc[a]; \
32339503Sborman 			return(b);
32440242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
32539503Sborman 
32638905Sborman 	switch(func) {
32738905Sborman 	case SLC_EOF:
32839503Sborman 		setval(VEOF, SLC_VARIABLE);
32938905Sborman 	case SLC_EC:
33039503Sborman 		setval(VERASE, SLC_VARIABLE);
33138905Sborman 	case SLC_EL:
33239503Sborman 		setval(VKILL, SLC_VARIABLE);
33338905Sborman 	case SLC_IP:
33439503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
33538905Sborman 	case SLC_ABORT:
33639503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
33738905Sborman 	case SLC_XON:
33839503Sborman #ifdef	VSTART
33939503Sborman 		setval(VSTART, SLC_VARIABLE);
34039503Sborman #else
34139503Sborman 		defval(0x13);
34239503Sborman #endif
34338905Sborman 	case SLC_XOFF:
34439503Sborman #ifdef	VSTOP
34539503Sborman 		setval(VSTOP, SLC_VARIABLE);
34639503Sborman #else
34739503Sborman 		defval(0x11);
34839503Sborman #endif
34938905Sborman 	case SLC_EW:
35039503Sborman #ifdef	VWERASE
35139503Sborman 		setval(VWERASE, SLC_VARIABLE);
35239503Sborman #else
35339503Sborman 		defval(0);
35439503Sborman #endif
35538905Sborman 	case SLC_RP:
35639503Sborman #ifdef	VREPRINT
35739503Sborman 		setval(VREPRINT, SLC_VARIABLE);
35839503Sborman #else
35939503Sborman 		defval(0);
36039503Sborman #endif
36138905Sborman 	case SLC_LNEXT:
36239503Sborman #ifdef	VLNEXT
36339503Sborman 		setval(VLNEXT, SLC_VARIABLE);
36439503Sborman #else
36539503Sborman 		defval(0);
36639503Sborman #endif
36739503Sborman 	case SLC_AO:
36845234Sborman #if	!defined(VDISCARD) && defined(VFLUSHO)
36945234Sborman # define VDISCARD VFLUSHO
37045234Sborman #endif
37145234Sborman #ifdef	VDISCARD
37245234Sborman 		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
37339503Sborman #else
37439503Sborman 		defval(0);
37539503Sborman #endif
37639503Sborman 	case SLC_SUSP:
37739503Sborman #ifdef	VSUSP
37839503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
37939503Sborman #else
38039503Sborman 		defval(0);
38139503Sborman #endif
38240242Sborman #ifdef	VEOL
38340242Sborman 	case SLC_FORW1:
38440242Sborman 		setval(VEOL, SLC_VARIABLE);
38540242Sborman #endif
38640242Sborman #ifdef	VEOL2
38740242Sborman 	case SLC_FORW2:
38840242Sborman 		setval(VEOL2, SLC_VARIABLE);
38940242Sborman #endif
39045234Sborman 	case SLC_AYT:
39145234Sborman #ifdef	VSTATUS
39245234Sborman 		setval(VSTATUS, SLC_VARIABLE);
39345234Sborman #else
39445234Sborman 		defval(0);
39545234Sborman #endif
39639503Sborman 
39738905Sborman 	case SLC_BRK:
39838905Sborman 	case SLC_SYNCH:
39938905Sborman 	case SLC_EOR:
40039503Sborman 		defval(0);
40139503Sborman 
40238905Sborman 	default:
40338905Sborman 		*valp = 0;
40438905Sborman 		*valpp = 0;
40538905Sborman 		return(SLC_NOSUPPORT);
40638905Sborman 	}
40738905Sborman }
40838905Sborman #endif	/* USE_TERMIO */
40938905Sborman 
41040242Sborman #ifdef CRAY
41138905Sborman /*
41240242Sborman  * getnpty()
41340242Sborman  *
41440242Sborman  * Return the number of pty's configured into the system.
41540242Sborman  */
41646809Sdab 	int
41740242Sborman getnpty()
41840242Sborman {
41940242Sborman #ifdef _SC_CRAY_NPTY
42046809Sdab 	int numptys;
42146809Sdab 
42246809Sdab 	if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
42346809Sdab 		return numptys;
42446809Sdab 	else
42540242Sborman #endif /* _SC_CRAY_NPTY */
42646809Sdab 		return 128;
42740242Sborman }
42840242Sborman #endif /* CRAY */
42940242Sborman 
43045234Sborman #ifndef	convex
43140242Sborman /*
43238905Sborman  * getpty()
43338905Sborman  *
43438905Sborman  * Allocate a pty.  As a side effect, the external character
43538905Sborman  * array "line" contains the name of the slave side.
43638905Sborman  *
43738905Sborman  * Returns the file descriptor of the opened pty.
43838905Sborman  */
43945234Sborman #ifndef	__GNUC__
44038905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44145234Sborman #else
44245234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44345234Sborman char *line = Xline;
44445234Sborman #endif
44545234Sborman #ifdef	CRAY
44645234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44745234Sborman #endif	/* CRAY */
44838905Sborman 
44946809Sdab 	int
45060151Sdab getpty(ptynum)
45160151Sdab int *ptynum;
45238905Sborman {
45338905Sborman 	register int p;
45457212Sdab #ifdef	STREAMSPTY
45557212Sdab 	int t;
45657212Sdab 	char *ptsname();
45757212Sdab 
45857212Sdab 	p = open("/dev/ptmx", 2);
45957212Sdab 	if (p > 0) {
46057212Sdab 		grantpt(p);
46157212Sdab 		unlockpt(p);
46257212Sdab 		strcpy(line, ptsname(p));
46357212Sdab 		return(p);
46457212Sdab 	}
46557212Sdab 
46657212Sdab #else	/* ! STREAMSPTY */
46738905Sborman #ifndef CRAY
46857212Sdab 	register char *cp, *p1, *p2;
46938905Sborman 	register int i;
47059050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
47157212Sdab 	int dummy;
47257212Sdab #endif
47338905Sborman 
47460151Sdab #ifndef	__hpux
47538905Sborman 	(void) sprintf(line, "/dev/ptyXX");
47638905Sborman 	p1 = &line[8];
47738905Sborman 	p2 = &line[9];
47860151Sdab #else
47960151Sdab 	(void) sprintf(line, "/dev/ptym/ptyXX");
48060151Sdab 	p1 = &line[13];
48160151Sdab 	p2 = &line[14];
48260151Sdab #endif
48338905Sborman 
48457212Sdab 	for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
48538905Sborman 		struct stat stb;
48638905Sborman 
48757212Sdab 		*p1 = *cp;
48838905Sborman 		*p2 = '0';
48957212Sdab 		/*
49057212Sdab 		 * This stat() check is just to keep us from
49157212Sdab 		 * looping through all 256 combinations if there
49257212Sdab 		 * aren't that many ptys available.
49357212Sdab 		 */
49438905Sborman 		if (stat(line, &stb) < 0)
49538905Sborman 			break;
49638905Sborman 		for (i = 0; i < 16; i++) {
49738905Sborman 			*p2 = "0123456789abcdef"[i];
49838905Sborman 			p = open(line, 2);
49938905Sborman 			if (p > 0) {
50060151Sdab #ifndef	__hpux
50138905Sborman 				line[5] = 't';
50260151Sdab #else
50360151Sdab 				for (p1 = &line[8]; *p1; p1++)
50460151Sdab 					*p1 = *(p1+1);
50560151Sdab 				line[9] = 't';
50660151Sdab #endif
50757212Sdab 				chown(line, 0, 0);
50857212Sdab 				chmod(line, 0600);
50959050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
51057212Sdab 				if (ioctl(p, TIOCGPGRP, &dummy) == 0
51157212Sdab 				    || errno != EIO) {
51257212Sdab 					chmod(line, 0666);
51357212Sdab 					close(p);
51457212Sdab 					line[5] = 'p';
51557212Sdab 				} else
51659050Storek #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
51757212Sdab 					return(p);
51838905Sborman 			}
51938905Sborman 		}
52038905Sborman 	}
52138905Sborman #else	/* CRAY */
52238905Sborman 	extern lowpty, highpty;
52345234Sborman 	struct stat sb;
52438905Sborman 
52560151Sdab 	for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
52660151Sdab 		(void) sprintf(myline, "/dev/pty/%03d", *ptynum);
52745234Sborman 		p = open(myline, 2);
52838905Sborman 		if (p < 0)
52938905Sborman 			continue;
53060151Sdab 		(void) sprintf(line, "/dev/ttyp%03d", *ptynum);
53145234Sborman 		/*
53245234Sborman 		 * Here are some shenanigans to make sure that there
53345234Sborman 		 * are no listeners lurking on the line.
53445234Sborman 		 */
53545234Sborman 		if(stat(line, &sb) < 0) {
53645234Sborman 			(void) close(p);
53745234Sborman 			continue;
53845234Sborman 		}
53945234Sborman 		if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
54045234Sborman 			chown(line, 0, 0);
54145234Sborman 			chmod(line, 0600);
54245234Sborman 			(void)close(p);
54345234Sborman 			p = open(myline, 2);
54445234Sborman 			if (p < 0)
54545234Sborman 				continue;
54645234Sborman 		}
54745234Sborman 		/*
54845234Sborman 		 * Now it should be safe...check for accessability.
54945234Sborman 		 */
55038905Sborman 		if (access(line, 6) == 0)
55138905Sborman 			return(p);
55238905Sborman 		else {
55338905Sborman 			/* no tty side to pty so skip it */
55438905Sborman 			(void) close(p);
55538905Sborman 		}
55638905Sborman 	}
55738905Sborman #endif	/* CRAY */
55857212Sdab #endif	/* STREAMSPTY */
55938905Sborman 	return(-1);
56038905Sborman }
56145234Sborman #endif	/* convex */
56238905Sborman 
56338905Sborman #ifdef	LINEMODE
56438905Sborman /*
56538905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
56638905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
56738905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
56838905Sborman  * tty_isecho()		Find out if echoing is turned on.
56938905Sborman  * tty_setecho(on)	Enable/disable character echoing.
57038905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
57138905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
57238905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
57338905Sborman  * tty_isediting()	Find out if line editing is enabled.
57438905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
57538905Sborman  * tty_setedit(on)	Turn on/off line editing.
57638905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
57744364Sborman  * tty_issofttab()	Find out if tab expansion is enabled.
57844364Sborman  * tty_setsofttab(on)	Turn on/off soft tab expansion.
57944364Sborman  * tty_islitecho()	Find out if typed control chars are echoed literally
58044364Sborman  * tty_setlitecho()	Turn on/off literal echo of control chars
58138905Sborman  * tty_tspeed(val)	Set transmit speed to val.
58238905Sborman  * tty_rspeed(val)	Set receive speed to val.
58338905Sborman  */
58438905Sborman 
58545234Sborman #ifdef convex
58645234Sborman static int linestate;
58745234Sborman #endif
58845234Sborman 
58946809Sdab 	int
59038905Sborman tty_linemode()
59138905Sborman {
59245234Sborman #ifndef convex
59338905Sborman #ifndef	USE_TERMIO
59438905Sborman 	return(termbuf.state & TS_EXTPROC);
59538905Sborman #else
59638905Sborman 	return(termbuf.c_lflag & EXTPROC);
59738905Sborman #endif
59845234Sborman #else
59945234Sborman 	return(linestate);
60045234Sborman #endif
60138905Sborman }
60238905Sborman 
60346809Sdab 	void
60438905Sborman tty_setlinemode(on)
60546809Sdab 	int on;
60638905Sborman {
60738905Sborman #ifdef	TIOCEXT
60845234Sborman # ifndef convex
60945234Sborman 	set_termbuf();
61045234Sborman # else
61145234Sborman 	linestate = on;
61245234Sborman # endif
61338905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
61445234Sborman # ifndef convex
61545234Sborman 	init_termbuf();
61645234Sborman # endif
61738905Sborman #else	/* !TIOCEXT */
61845234Sborman # ifdef	EXTPROC
61938905Sborman 	if (on)
62038905Sborman 		termbuf.c_lflag |= EXTPROC;
62138905Sborman 	else
62238905Sborman 		termbuf.c_lflag &= ~EXTPROC;
62345234Sborman # endif
62438905Sborman #endif	/* TIOCEXT */
62538905Sborman }
626*65158Sdab #endif	/* LINEMODE */
62738905Sborman 
62846809Sdab 	int
62938905Sborman tty_isecho()
63038905Sborman {
63138905Sborman #ifndef USE_TERMIO
63238905Sborman 	return (termbuf.sg.sg_flags & ECHO);
63338905Sborman #else
63438905Sborman 	return (termbuf.c_lflag & ECHO);
63538905Sborman #endif
63638905Sborman }
63738905Sborman 
63858971Sdab 	int
63958971Sdab tty_flowmode()
64058971Sdab {
64158971Sdab #ifndef USE_TERMIO
64258971Sdab 	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
64358971Sdab #else
64458971Sdab 	return((termbuf.c_iflag & IXON) ? 1 : 0);
64558971Sdab #endif
64658971Sdab }
64758971Sdab 
64858971Sdab 	int
64958971Sdab tty_restartany()
65058971Sdab {
65158971Sdab #ifndef USE_TERMIO
65258971Sdab # ifdef	DECCTQ
65358971Sdab 	return((termbuf.lflags & DECCTQ) ? 0 : 1);
65458971Sdab # else
65558971Sdab 	return(-1);
65658971Sdab # endif
65758971Sdab #else
65858971Sdab 	return((termbuf.c_iflag & IXANY) ? 1 : 0);
65958971Sdab #endif
66058971Sdab }
66158971Sdab 
66246809Sdab 	void
66338905Sborman tty_setecho(on)
66446809Sdab 	int on;
66538905Sborman {
66638905Sborman #ifndef	USE_TERMIO
66738905Sborman 	if (on)
66838905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
66938905Sborman 	else
67038905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
67138905Sborman #else
67238905Sborman 	if (on)
67338905Sborman 		termbuf.c_lflag |= ECHO;
67438905Sborman 	else
67538905Sborman 		termbuf.c_lflag &= ~ECHO;
67638905Sborman #endif
67738905Sborman }
67838905Sborman 
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 
689*65158Sdab #if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
690*65158Sdab 	int
691*65158Sdab tty_setraw(on)
692*65158Sdab {
693*65158Sdab #  ifndef USE_TERMIO
694*65158Sdab 	if (on)
695*65158Sdab 		termbuf.sg.sg_flags |= RAW;
696*65158Sdab 	else
697*65158Sdab 		termbuf.sg.sg_flags &= ~RAW;
698*65158Sdab #  else
699*65158Sdab 	if (on)
700*65158Sdab 		termbuf.c_lflag &= ~ICANON;
701*65158Sdab 	else
702*65158Sdab 		termbuf.c_lflag |= ICANON;
703*65158Sdab #  endif
704*65158Sdab }
705*65158Sdab #endif
706*65158Sdab 
70746809Sdab 	void
70838905Sborman tty_binaryin(on)
70946809Sdab 	int on;
71038905Sborman {
71138905Sborman #ifndef	USE_TERMIO
71238905Sborman 	if (on)
71338905Sborman 		termbuf.lflags |= LPASS8;
71438905Sborman 	else
71538905Sborman 		termbuf.lflags &= ~LPASS8;
71638905Sborman #else
71738905Sborman 	if (on) {
71846809Sdab 		termbuf.c_iflag &= ~ISTRIP;
71938905Sborman 	} else {
72046809Sdab 		termbuf.c_iflag |= ISTRIP;
72138905Sborman 	}
72238905Sborman #endif
72338905Sborman }
72438905Sborman 
72546809Sdab 	void
72638905Sborman tty_binaryout(on)
72746809Sdab 	int on;
72838905Sborman {
72938905Sborman #ifndef	USE_TERMIO
73038905Sborman 	if (on)
73138905Sborman 		termbuf.lflags |= LLITOUT;
73238905Sborman 	else
73338905Sborman 		termbuf.lflags &= ~LLITOUT;
73438905Sborman #else
73538905Sborman 	if (on) {
73638905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
73738905Sborman 		termbuf.c_cflag |= CS8;
73838905Sborman 		termbuf.c_oflag &= ~OPOST;
73938905Sborman 	} else {
74038905Sborman 		termbuf.c_cflag &= ~CSIZE;
74138905Sborman 		termbuf.c_cflag |= CS7|PARENB;
74238905Sborman 		termbuf.c_oflag |= OPOST;
74338905Sborman 	}
74438905Sborman #endif
74538905Sborman }
74638905Sborman 
74746809Sdab 	int
74838905Sborman tty_isbinaryin()
74938905Sborman {
75038905Sborman #ifndef	USE_TERMIO
75138905Sborman 	return(termbuf.lflags & LPASS8);
75238905Sborman #else
75339503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
75438905Sborman #endif
75538905Sborman }
75638905Sborman 
75746809Sdab 	int
75838905Sborman tty_isbinaryout()
75938905Sborman {
76038905Sborman #ifndef	USE_TERMIO
76138905Sborman 	return(termbuf.lflags & LLITOUT);
76238905Sborman #else
76339503Sborman 	return(!(termbuf.c_oflag&OPOST));
76438905Sborman #endif
76538905Sborman }
76638905Sborman 
76738905Sborman #ifdef	LINEMODE
76846809Sdab 	int
76938905Sborman tty_isediting()
77038905Sborman {
77138905Sborman #ifndef USE_TERMIO
77238905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
77338905Sborman #else
77438905Sborman 	return(termbuf.c_lflag & ICANON);
77538905Sborman #endif
77638905Sborman }
77738905Sborman 
77846809Sdab 	int
77938905Sborman tty_istrapsig()
78038905Sborman {
78138905Sborman #ifndef USE_TERMIO
78238905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
78338905Sborman #else
78438905Sborman 	return(termbuf.c_lflag & ISIG);
78538905Sborman #endif
78638905Sborman }
78738905Sborman 
78846809Sdab 	void
78938905Sborman tty_setedit(on)
79046809Sdab 	int on;
79138905Sborman {
79238905Sborman #ifndef USE_TERMIO
79338905Sborman 	if (on)
79438905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
79538905Sborman 	else
79638905Sborman 		termbuf.sg.sg_flags |= CBREAK;
79738905Sborman #else
79838905Sborman 	if (on)
79938905Sborman 		termbuf.c_lflag |= ICANON;
80038905Sborman 	else
80138905Sborman 		termbuf.c_lflag &= ~ICANON;
80238905Sborman #endif
80338905Sborman }
80438905Sborman 
80546809Sdab 	void
80638905Sborman tty_setsig(on)
80746809Sdab 	int on;
80838905Sborman {
80938905Sborman #ifndef	USE_TERMIO
81038905Sborman 	if (on)
81138905Sborman 		;
81238905Sborman #else
81338905Sborman 	if (on)
81438905Sborman 		termbuf.c_lflag |= ISIG;
81538905Sborman 	else
81638905Sborman 		termbuf.c_lflag &= ~ISIG;
81738905Sborman #endif
81838905Sborman }
81938905Sborman #endif	/* LINEMODE */
82038905Sborman 
82146809Sdab 	int
82244364Sborman tty_issofttab()
82344364Sborman {
82444364Sborman #ifndef	USE_TERMIO
82544364Sborman 	return (termbuf.sg.sg_flags & XTABS);
82644364Sborman #else
82744364Sborman # ifdef	OXTABS
82844364Sborman 	return (termbuf.c_oflag & OXTABS);
82944364Sborman # endif
83044364Sborman # ifdef	TABDLY
83144364Sborman 	return ((termbuf.c_oflag & TABDLY) == TAB3);
83244364Sborman # endif
83344364Sborman #endif
83444364Sborman }
83544364Sborman 
83646809Sdab 	void
83744364Sborman tty_setsofttab(on)
83846809Sdab 	int on;
83944364Sborman {
84044364Sborman #ifndef	USE_TERMIO
84144364Sborman 	if (on)
84244364Sborman 		termbuf.sg.sg_flags |= XTABS;
84344364Sborman 	else
84444364Sborman 		termbuf.sg.sg_flags &= ~XTABS;
84544364Sborman #else
84644364Sborman 	if (on) {
84744364Sborman # ifdef	OXTABS
84844364Sborman 		termbuf.c_oflag |= OXTABS;
84944364Sborman # endif
85044364Sborman # ifdef	TABDLY
85144364Sborman 		termbuf.c_oflag &= ~TABDLY;
85244364Sborman 		termbuf.c_oflag |= TAB3;
85344364Sborman # endif
85444364Sborman 	} else {
85544364Sborman # ifdef	OXTABS
85644364Sborman 		termbuf.c_oflag &= ~OXTABS;
85744364Sborman # endif
85844364Sborman # ifdef	TABDLY
85944364Sborman 		termbuf.c_oflag &= ~TABDLY;
86044364Sborman 		termbuf.c_oflag |= TAB0;
86144364Sborman # endif
86244364Sborman 	}
86344364Sborman #endif
86444364Sborman }
86544364Sborman 
86646809Sdab 	int
86744364Sborman tty_islitecho()
86844364Sborman {
86944364Sborman #ifndef	USE_TERMIO
87046809Sdab 	return (!(termbuf.lflags & LCTLECH));
87144364Sborman #else
87244364Sborman # ifdef	ECHOCTL
87344364Sborman 	return (!(termbuf.c_lflag & ECHOCTL));
87444364Sborman # endif
87544364Sborman # ifdef	TCTLECH
87644364Sborman 	return (!(termbuf.c_lflag & TCTLECH));
87744364Sborman # endif
87844364Sborman # if	!defined(ECHOCTL) && !defined(TCTLECH)
87944364Sborman 	return (0);	/* assumes ctl chars are echoed '^x' */
88044364Sborman # endif
88144364Sborman #endif
88244364Sborman }
88344364Sborman 
88446809Sdab 	void
88544364Sborman tty_setlitecho(on)
88646809Sdab 	int on;
88744364Sborman {
88844364Sborman #ifndef	USE_TERMIO
88944364Sborman 	if (on)
89046809Sdab 		termbuf.lflags &= ~LCTLECH;
89144364Sborman 	else
89246809Sdab 		termbuf.lflags |= LCTLECH;
89344364Sborman #else
89444364Sborman # ifdef	ECHOCTL
89544364Sborman 	if (on)
89644364Sborman 		termbuf.c_lflag &= ~ECHOCTL;
89744364Sborman 	else
89844364Sborman 		termbuf.c_lflag |= ECHOCTL;
89944364Sborman # endif
90044364Sborman # ifdef	TCTLECH
90144364Sborman 	if (on)
90244364Sborman 		termbuf.c_lflag &= ~TCTLECH;
90344364Sborman 	else
90444364Sborman 		termbuf.c_lflag |= TCTLECH;
90544364Sborman # endif
90644364Sborman #endif
90744364Sborman }
90844364Sborman 
90946809Sdab 	int
91046809Sdab tty_iscrnl()
91146809Sdab {
91246809Sdab #ifndef	USE_TERMIO
91346809Sdab 	return (termbuf.sg.sg_flags & CRMOD);
91446809Sdab #else
91546809Sdab 	return (termbuf.c_iflag & ICRNL);
91646809Sdab #endif
91746809Sdab }
91846809Sdab 
91938905Sborman /*
92038905Sborman  * A table of available terminal speeds
92138905Sborman  */
92238905Sborman struct termspeeds {
92338905Sborman 	int	speed;
92438905Sborman 	int	value;
92538905Sborman } termspeeds[] = {
92638905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
92738905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
92838905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
92938905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
93038905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
93138905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
93238905Sborman };
93338905Sborman 
93446809Sdab 	void
93538905Sborman tty_tspeed(val)
93646809Sdab 	int val;
93738905Sborman {
93838905Sborman 	register struct termspeeds *tp;
93938905Sborman 
94038905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
94138905Sborman 		;
94245234Sborman 	cfsetospeed(&termbuf, tp->value);
94338905Sborman }
94438905Sborman 
94546809Sdab 	void
94638905Sborman tty_rspeed(val)
94746809Sdab 	int val;
94838905Sborman {
94938905Sborman 	register struct termspeeds *tp;
95038905Sborman 
95138905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
95238905Sborman 		;
95345234Sborman 	cfsetispeed(&termbuf, tp->value);
95438905Sborman }
95538905Sborman 
95640242Sborman #if	defined(CRAY2) && defined(UNICOS5)
95746809Sdab 	int
95838905Sborman tty_isnewmap()
95938905Sborman {
96038905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
96138905Sborman 			!(termbuf.c_oflag & ONLRET));
96238905Sborman }
96338905Sborman #endif
96438905Sborman 
96560151Sdab #ifdef PARENT_DOES_UTMP
96638905Sborman # ifndef NEWINIT
96738905Sborman extern	struct utmp wtmp;
96838905Sborman extern char wtmpf[];
96938905Sborman # else	/* NEWINIT */
97038905Sborman int	gotalarm;
97146809Sdab 
97246809Sdab 	/* ARGSUSED */
97346809Sdab 	void
97440242Sborman nologinproc(sig)
97546809Sdab 	int sig;
97638905Sborman {
97738905Sborman 	gotalarm++;
97838905Sborman }
97938905Sborman # endif	/* NEWINIT */
98060151Sdab #endif /* PARENT_DOES_UTMP */
98138905Sborman 
98246809Sdab #ifndef	NEWINIT
98360151Sdab # ifdef PARENT_DOES_UTMP
98446809Sdab extern void utmp_sig_init P((void));
98546809Sdab extern void utmp_sig_reset P((void));
98646809Sdab extern void utmp_sig_wait P((void));
98746809Sdab extern void utmp_sig_notify P((int));
98860151Sdab # endif /* PARENT_DOES_UTMP */
98946809Sdab #endif
99046809Sdab 
99138905Sborman /*
99238905Sborman  * getptyslave()
99338905Sborman  *
99438905Sborman  * Open the slave side of the pty, and do any initialization
99538905Sborman  * that is necessary.  The return value is a file descriptor
99638905Sborman  * for the slave side.
99738905Sborman  */
99846809Sdab 	int
99938905Sborman getptyslave()
100038905Sborman {
100138905Sborman 	register int t = -1;
100238905Sborman 
100345234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
100445234Sborman # ifdef	LINEMODE
100546809Sdab 	int waslm;
100646809Sdab # endif
100746809Sdab # ifdef	TIOCGWINSZ
100846809Sdab 	struct winsize ws;
100946809Sdab 	extern int def_row, def_col;
101046809Sdab # endif
101146809Sdab 	extern int def_tspeed, def_rspeed;
101238905Sborman 	/*
101345234Sborman 	 * Opening the slave side may cause initilization of the
101446809Sdab 	 * kernel tty structure.  We need remember the state of
101546809Sdab 	 * 	if linemode was turned on
101646809Sdab 	 *	terminal window size
101746809Sdab 	 *	terminal speed
101846809Sdab 	 * so that we can re-set them if we need to.
101938905Sborman 	 */
102046809Sdab # ifdef	LINEMODE
102146809Sdab 	waslm = tty_linemode();
102245234Sborman # endif
102345234Sborman 
102445234Sborman 
102545234Sborman 	/*
102645234Sborman 	 * Make sure that we don't have a controlling tty, and
102745234Sborman 	 * that we are the session (process group) leader.
102845234Sborman 	 */
102945234Sborman # ifdef	TIOCNOTTY
103038905Sborman 	t = open(_PATH_TTY, O_RDWR);
103138905Sborman 	if (t >= 0) {
103238905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
103338905Sborman 		(void) close(t);
103438905Sborman 	}
103545234Sborman # endif
103638905Sborman 
103745234Sborman 
103860151Sdab # ifdef PARENT_DOES_UTMP
103945234Sborman 	/*
104045234Sborman 	 * Wait for our parent to get the utmp stuff to get done.
104145234Sborman 	 */
104245234Sborman 	utmp_sig_wait();
104345234Sborman # endif
104445234Sborman 
104545234Sborman 	t = cleanopen(line);
104638905Sborman 	if (t < 0)
104738905Sborman 		fatalperror(net, line);
104838905Sborman 
104957592Sdab #ifdef  STREAMSPTY
105057212Sdab #ifdef	USE_TERMIO
105157212Sdab 	ttyfd = t;
105257212Sdab #endif
105357212Sdab 	if (ioctl(t, I_PUSH, "ptem") < 0)
105457212Sdab 		fatal(net, "I_PUSH ptem");
105557212Sdab 	if (ioctl(t, I_PUSH, "ldterm") < 0)
105657212Sdab 		fatal(net, "I_PUSH ldterm");
105757212Sdab 	if (ioctl(t, I_PUSH, "ttcompat") < 0)
105857212Sdab 		fatal(net, "I_PUSH ttcompat");
105957212Sdab 	if (ioctl(pty, I_PUSH, "pckt") < 0)
106057212Sdab 		fatal(net, "I_PUSH pckt");
106157212Sdab #endif
106257212Sdab 
106345234Sborman 	/*
106445234Sborman 	 * set up the tty modes as we like them to be.
106545234Sborman 	 */
106638905Sborman 	init_termbuf();
106746809Sdab # ifdef	TIOCGWINSZ
106846809Sdab 	if (def_row || def_col) {
106946809Sdab 		bzero((char *)&ws, sizeof(ws));
107046809Sdab 		ws.ws_col = def_col;
107146809Sdab 		ws.ws_row = def_row;
107246809Sdab 		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
107346809Sdab 	}
107446809Sdab # endif
107545234Sborman 
107645234Sborman 	/*
107745234Sborman 	 * Settings for sgtty based systems
107845234Sborman 	 */
107945234Sborman # ifndef	USE_TERMIO
108040242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
108145234Sborman # endif	/* USE_TERMIO */
108245234Sborman 
108345234Sborman 	/*
108460151Sdab 	 * Settings for UNICOS (and HPUX)
108545234Sborman 	 */
108660151Sdab # if defined(CRAY) || defined(__hpux)
108745234Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
108845234Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
108945234Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
109045234Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
109145234Sborman # endif
109245234Sborman 
109345234Sborman 	/*
109445234Sborman 	 * Settings for all other termios/termio based
109545234Sborman 	 * systems, other than 4.4BSD.  In 4.4BSD the
109645234Sborman 	 * kernel does the initial terminal setup.
109745234Sborman 	 */
109860151Sdab # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
109945234Sborman #  ifndef	OXTABS
110045234Sborman #   define OXTABS	0
110145234Sborman #  endif
110238905Sborman 	termbuf.c_lflag |= ECHO;
110338905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
110438905Sborman 	termbuf.c_iflag |= ICRNL;
110538905Sborman 	termbuf.c_iflag &= ~IXOFF;
110645234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
110746996Sdab 	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
110846996Sdab 	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
110946809Sdab # ifdef	LINEMODE
111046809Sdab 	if (waslm)
111146809Sdab 		tty_setlinemode(1);
111246809Sdab # endif	/* LINEMODE */
111345234Sborman 
111445234Sborman 	/*
111545234Sborman 	 * Set the tty modes, and make this our controlling tty.
111645234Sborman 	 */
111745234Sborman 	set_termbuf();
111845234Sborman 	if (login_tty(t) == -1)
111945234Sborman 		fatalperror(net, "login_tty");
112045234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
112145234Sborman 	if (net > 2)
112245234Sborman 		(void) close(net);
1123*65158Sdab #if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1124*65158Sdab 	/*
1125*65158Sdab 	 * Leave the pty open so that we can write out the rlogin
1126*65158Sdab 	 * protocol for /bin/login, if the authentication works.
1127*65158Sdab 	 */
1128*65158Sdab #else
1129*65158Sdab 	if (pty > 2) {
113045234Sborman 		(void) close(pty);
1131*65158Sdab 		pty = -1;
1132*65158Sdab 	}
1133*65158Sdab #endif
113445234Sborman }
113545234Sborman 
113645234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
113745234Sborman #ifndef	O_NOCTTY
113845234Sborman #define	O_NOCTTY	0
113938905Sborman #endif
114045234Sborman /*
114145234Sborman  * Open the specified slave side of the pty,
114245234Sborman  * making sure that we have a clean tty.
114345234Sborman  */
114446809Sdab 	int
114545234Sborman cleanopen(line)
114646809Sdab 	char *line;
114745234Sborman {
114845234Sborman 	register int t;
114957212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
115057212Sdab 	struct secstat secbuf;
115157212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
115245234Sborman 
115357212Sdab #ifndef STREAMSPTY
115445234Sborman 	/*
115545234Sborman 	 * Make sure that other people can't open the
115645234Sborman 	 * slave side of the connection.
115745234Sborman 	 */
115838905Sborman 	(void) chown(line, 0, 0);
115938905Sborman 	(void) chmod(line, 0600);
116057212Sdab #endif
116145234Sborman 
116245234Sborman # if !defined(CRAY) && (BSD > 43)
116345234Sborman 	(void) revoke(line);
116445234Sborman # endif
116557212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
116657212Sdab 	if (secflag) {
116757212Sdab 		if (secstat(line, &secbuf) < 0)
116857212Sdab 			return(-1);
116957212Sdab 		if (setulvl(secbuf.st_slevel) < 0)
117057212Sdab 			return(-1);
117157212Sdab 		if (setucmp(secbuf.st_compart) < 0)
117257212Sdab 			return(-1);
117357212Sdab 	}
117457212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
117557212Sdab 
117645234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
117757212Sdab 
117857212Sdab #if	defined(_SC_CRAY_SECURE_SYS)
117957212Sdab 	if (secflag) {
118057212Sdab 		if (setulvl(sysv.sy_minlvl) < 0)
118157212Sdab 			return(-1);
118257212Sdab 		if (setucmp(0) < 0)
118357212Sdab 			return(-1);
118457212Sdab 	}
118557212Sdab #endif	/* _SC_CRAY_SECURE_SYS */
118657212Sdab 
118745234Sborman 	if (t < 0)
118845234Sborman 		return(-1);
118945234Sborman 
119045234Sborman 	/*
119145234Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
119245234Sborman 	 * ourselves.
119345234Sborman 	 */
119460151Sdab # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
119545234Sborman 	(void) signal(SIGHUP, SIG_IGN);
119645234Sborman 	vhangup();
119745234Sborman 	(void) signal(SIGHUP, SIG_DFL);
119845234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
119945234Sborman 	if (t < 0)
120045234Sborman 		return(-1);
120145234Sborman # endif
120245234Sborman # if	defined(CRAY) && defined(TCVHUP)
120345234Sborman 	{
120445234Sborman 		register int i;
120545234Sborman 		(void) signal(SIGHUP, SIG_IGN);
120645234Sborman 		(void) ioctl(t, TCVHUP, (char *)0);
120745234Sborman 		(void) signal(SIGHUP, SIG_DFL);
120845234Sborman 		setpgrp();
120957212Sdab 
121057212Sdab #if		defined(_SC_CRAY_SECURE_SYS)
121157212Sdab 		if (secflag) {
121257212Sdab 			if (secstat(line, &secbuf) < 0)
121357212Sdab 				return(-1);
121457212Sdab 			if (setulvl(secbuf.st_slevel) < 0)
121557212Sdab 				return(-1);
121657212Sdab 			if (setucmp(secbuf.st_compart) < 0)
121757212Sdab 				return(-1);
121857212Sdab 		}
121957212Sdab #endif		/* _SC_CRAY_SECURE_SYS */
122057212Sdab 
122145234Sborman 		i = open(line, O_RDWR);
122257212Sdab 
122357212Sdab #if		defined(_SC_CRAY_SECURE_SYS)
122457212Sdab 		if (secflag) {
122557212Sdab 			if (setulvl(sysv.sy_minlvl) < 0)
122657212Sdab 				return(-1);
122757212Sdab 			if (setucmp(0) < 0)
122857212Sdab 				return(-1);
122957212Sdab 		}
123057212Sdab #endif		/* _SC_CRAY_SECURE_SYS */
123157212Sdab 
123245234Sborman 		if (i < 0)
123346809Sdab 			return(-1);
123445234Sborman 		(void) close(t);
123545234Sborman 		t = i;
123645234Sborman 	}
123745234Sborman # endif	/* defined(CRAY) && defined(TCVHUP) */
123838905Sborman 	return(t);
123938905Sborman }
124045234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
124138905Sborman 
124245234Sborman #if BSD <= 43
1243*65158Sdab 
124446809Sdab 	int
124545234Sborman login_tty(t)
124646809Sdab 	int t;
124745234Sborman {
1248*65158Sdab 	if (setsid() < 0) {
1249*65158Sdab #ifdef ultrix
1250*65158Sdab 		/*
1251*65158Sdab 		 * The setsid() may have failed because we
1252*65158Sdab 		 * already have a pgrp == pid.  Zero out
1253*65158Sdab 		 * our pgrp and try again...
1254*65158Sdab 		 */
1255*65158Sdab 		if ((setpgrp(0, 0) < 0) || (setsid() < 0))
1256*65158Sdab #endif
1257*65158Sdab 			fatalperror(net, "setsid()");
1258*65158Sdab 	}
125945234Sborman # ifdef	TIOCSCTTY
126045234Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
126145234Sborman 		fatalperror(net, "ioctl(sctty)");
126257212Sdab #  if defined(CRAY)
126347613Sdab 	/*
126447613Sdab 	 * Close the hard fd to /dev/ttypXXX, and re-open through
126547613Sdab 	 * the indirect /dev/tty interface.
126647613Sdab 	 */
126747613Sdab 	close(t);
126847613Sdab 	if ((t = open("/dev/tty", O_RDWR)) < 0)
126947613Sdab 		fatalperror(net, "open(/dev/tty)");
127047613Sdab #  endif
127145234Sborman # else
1272*65158Sdab 	/*
1273*65158Sdab 	 * We get our controlling tty assigned as a side-effect
1274*65158Sdab 	 * of opening up a tty device.  But on BSD based systems,
1275*65158Sdab 	 * this only happens if our process group is zero.  The
1276*65158Sdab 	 * setsid() call above may have set our pgrp, so clear
1277*65158Sdab 	 * it out before opening the tty...
1278*65158Sdab 	 */
1279*65158Sdab 	(void) setpgrp(0, 0);
128045234Sborman 	close(open(line, O_RDWR));
128145234Sborman # endif
128247613Sdab 	if (t != 0)
128347613Sdab 		(void) dup2(t, 0);
128447613Sdab 	if (t != 1)
128547613Sdab 		(void) dup2(t, 1);
128647613Sdab 	if (t != 2)
128747613Sdab 		(void) dup2(t, 2);
128847613Sdab 	if (t > 2)
128947613Sdab 		close(t);
129046809Sdab 	return(0);
129145234Sborman }
129245234Sborman #endif	/* BSD <= 43 */
129345234Sborman 
129438905Sborman #ifdef	NEWINIT
129538905Sborman char *gen_id = "fe";
129638905Sborman #endif
129738905Sborman 
129838905Sborman /*
129945234Sborman  * startslave(host)
130038905Sborman  *
130145234Sborman  * Given a hostname, do whatever
130238905Sborman  * is necessary to startup the login process on the slave side of the pty.
130338905Sborman  */
130438905Sborman 
130538905Sborman /* ARGSUSED */
130646809Sdab 	void
130746809Sdab startslave(host, autologin, autoname)
130846809Sdab 	char *host;
130946809Sdab 	int autologin;
131046809Sdab 	char *autoname;
131138905Sborman {
131238905Sborman 	register int i;
131338905Sborman 	long time();
131446809Sdab 	char name[256];
131546809Sdab #ifdef	NEWINIT
131646809Sdab 	extern char *ptyip;
131746809Sdab 	struct init_request request;
131846809Sdab 	void nologinproc();
131946809Sdab 	register int n;
132046809Sdab #endif	/* NEWINIT */
132138905Sborman 
132257212Sdab #if	defined(AUTHENTICATION)
132346809Sdab 	if (!autoname || !autoname[0])
132446809Sdab 		autologin = 0;
132546809Sdab 
132646809Sdab 	if (autologin < auth_level) {
132746809Sdab 		fatal(net, "Authorization failed");
132846809Sdab 		exit(1);
132946809Sdab 	}
133046809Sdab #endif
133146809Sdab 
133238905Sborman #ifndef	NEWINIT
133360151Sdab # ifdef	PARENT_DOES_UTMP
133438905Sborman 	utmp_sig_init();
133560151Sdab # endif	/* PARENT_DOES_UTMP */
133638905Sborman 
133738905Sborman 	if ((i = fork()) < 0)
133838905Sborman 		fatalperror(net, "fork");
133938905Sborman 	if (i) {
134060151Sdab # ifdef PARENT_DOES_UTMP
134138905Sborman 		/*
134238905Sborman 		 * Cray parent will create utmp entry for child and send
134338905Sborman 		 * signal to child to tell when done.  Child waits for signal
134438905Sborman 		 * before doing anything important.
134538905Sborman 		 */
134638905Sborman 		register int pid = i;
134746809Sdab 		void sigjob P((int));
134838905Sborman 
134938905Sborman 		setpgrp();
135044364Sborman 		utmp_sig_reset();		/* reset handler to default */
135138905Sborman 		/*
135238905Sborman 		 * Create utmp entry for child
135338905Sborman 		 */
135438905Sborman 		(void) time(&wtmp.ut_time);
135538905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
135638905Sborman 		wtmp.ut_pid = pid;
135738905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
135838905Sborman 		SCPYN(wtmp.ut_host, host);
135938905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
136060151Sdab #ifndef	__hpux
136138905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
136260151Sdab #else
136360151Sdab 		SCPYN(wtmp.ut_id, wtmp.ut_line+7);
136460151Sdab #endif
136538905Sborman 		pututline(&wtmp);
136638905Sborman 		endutent();
136738905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
136838905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
136938905Sborman 			(void) close(i);
137038905Sborman 		}
137160151Sdab #ifdef	CRAY
137246809Sdab 		(void) signal(WJSIGNAL, sigjob);
137360151Sdab #endif
137438905Sborman 		utmp_sig_notify(pid);
137560151Sdab # endif	/* PARENT_DOES_UTMP */
137638905Sborman 	} else {
1377*65158Sdab 		getptyslave(autologin);
137846809Sdab 		start_login(host, autologin, autoname);
137938905Sborman 		/*NOTREACHED*/
138038905Sborman 	}
138138905Sborman #else	/* NEWINIT */
138238905Sborman 
138338905Sborman 	/*
138438905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
138538905Sborman 	 * for it to start up and begin normal telnet operation.
138638905Sborman 	 */
138738905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
138838905Sborman 		char tbuf[128];
138938905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
139038905Sborman 		fatalperror(net, tbuf);
139138905Sborman 	}
139238905Sborman 	memset((char *)&request, 0, sizeof(request));
139338905Sborman 	request.magic = INIT_MAGIC;
139438905Sborman 	SCPYN(request.gen_id, gen_id);
139538905Sborman 	SCPYN(request.tty_id, &line[8]);
139638905Sborman 	SCPYN(request.host, host);
139746809Sdab 	SCPYN(request.term_type, terminaltype ? terminaltype : "network");
139844364Sborman #if	!defined(UNICOS5)
139940242Sborman 	request.signal = SIGCLD;
140040242Sborman 	request.pid = getpid();
140140242Sborman #endif
140244364Sborman #ifdef BFTPDAEMON
140344364Sborman 	/*
140444364Sborman 	 * Are we working as the bftp daemon?
140544364Sborman 	 */
140644364Sborman 	if (bftpd) {
140744364Sborman 		SCPYN(request.exec_name, BFTPPATH);
140844364Sborman 	}
140944364Sborman #endif /* BFTPDAEMON */
141038905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
141138905Sborman 		char tbuf[128];
141238905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
141338905Sborman 		fatalperror(net, tbuf);
141438905Sborman 	}
141538905Sborman 	(void) close(i);
141638905Sborman 	(void) signal(SIGALRM, nologinproc);
141738905Sborman 	for (i = 0; ; i++) {
141840242Sborman 		char tbuf[128];
141938905Sborman 		alarm(15);
142038905Sborman 		n = read(pty, ptyip, BUFSIZ);
142138905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
142238905Sborman 			break;
142338905Sborman 		gotalarm = 0;
142440242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
142540242Sborman 		(void) write(net, tbuf, strlen(tbuf));
142638905Sborman 	}
142738905Sborman 	if (n < 0 && gotalarm)
142838905Sborman 		fatal(net, "/etc/init didn't start login process");
142938905Sborman 	pcc += n;
143038905Sborman 	alarm(0);
143138905Sborman 	(void) signal(SIGALRM, SIG_DFL);
143238905Sborman 
143338905Sborman 	return;
143438905Sborman #endif	/* NEWINIT */
143538905Sborman }
143638905Sborman 
143738905Sborman char	*envinit[3];
143844364Sborman extern char **environ;
143938905Sborman 
144046809Sdab 	void
144144364Sborman init_env()
144244364Sborman {
144344364Sborman 	extern char *getenv();
144444364Sborman 	char **envp;
144544364Sborman 
144644364Sborman 	envp = envinit;
144744364Sborman 	if (*envp = getenv("TZ"))
144844364Sborman 		*envp++ -= 3;
144960151Sdab #if	defined(CRAY) || defined(__hpux)
145044364Sborman 	else
145144364Sborman 		*envp++ = "TZ=GMT0";
145244364Sborman #endif
145344364Sborman 	*envp = 0;
145444364Sborman 	environ = envinit;
145544364Sborman }
145644364Sborman 
145744364Sborman #ifndef	NEWINIT
145844364Sborman 
145944364Sborman /*
146045234Sborman  * start_login(host)
146138905Sborman  *
146238905Sborman  * Assuming that we are now running as a child processes, this
146338905Sborman  * function will turn us into the login process.
146438905Sborman  */
146538905Sborman 
146646809Sdab 	void
146746809Sdab start_login(host, autologin, name)
146846809Sdab 	char *host;
146946809Sdab 	int autologin;
147046809Sdab 	char *name;
147138905Sborman {
147244364Sborman 	register char *cp;
147344364Sborman 	register char **argv;
147444364Sborman 	char **addarg();
1475*65158Sdab 	extern char *getenv();
147657212Sdab #ifdef	UTMPX
147757212Sdab 	register int pid = getpid();
147857212Sdab 	struct utmpx utmpx;
147957212Sdab #endif
1480*65158Sdab #ifdef SOLARIS
148157212Sdab 	char *term;
148257212Sdab 	char termbuf[64];
148357212Sdab #endif
148438905Sborman 
148557212Sdab #ifdef	UTMPX
148638905Sborman 	/*
148757212Sdab 	 * Create utmp entry for child
148857212Sdab 	 */
148957212Sdab 
149057212Sdab 	bzero(&utmpx, sizeof(utmpx));
149157212Sdab 	SCPYN(utmpx.ut_user, ".telnet");
149257212Sdab 	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
149357212Sdab 	utmpx.ut_pid = pid;
149457212Sdab 	utmpx.ut_id[0] = 't';
149557212Sdab 	utmpx.ut_id[1] = 'n';
149657212Sdab 	utmpx.ut_id[2] = SC_WILDC;
149757212Sdab 	utmpx.ut_id[3] = SC_WILDC;
149857212Sdab 	utmpx.ut_type = LOGIN_PROCESS;
149957212Sdab 	(void) time(&utmpx.ut_tv.tv_sec);
150057212Sdab 	if (makeutx(&utmpx) == NULL)
150157212Sdab 		fatal(net, "makeutx failed");
150257212Sdab #endif
150357212Sdab 
150457212Sdab 	/*
150538905Sborman 	 * -h : pass on name of host.
150638905Sborman 	 *		WARNING:  -h is accepted by login if and only if
150738905Sborman 	 *			getuid() == 0.
150838905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
150946809Sdab 	 *
151046809Sdab 	 * -f : force this login, he has already been authenticated
151138905Sborman 	 */
151244364Sborman 	argv = addarg(0, "login");
1513*65158Sdab 
151460151Sdab #if	!defined(NO_LOGIN_H)
1515*65158Sdab 
1516*65158Sdab # if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
151757212Sdab 	/*
1518*65158Sdab 	 * Don't add the "-h host" option if we are going
1519*65158Sdab 	 * to be adding the "-r host" option down below...
152057212Sdab 	 */
1521*65158Sdab 	if ((auth_level < 0) || (autologin != AUTH_VALID))
1522*65158Sdab # endif
1523*65158Sdab 	{
1524*65158Sdab 		argv = addarg(argv, "-h");
1525*65158Sdab 		argv = addarg(argv, host);
1526*65158Sdab #ifdef	SOLARIS
1527*65158Sdab 		/*
1528*65158Sdab 		 * SVR4 version of -h takes TERM= as second arg, or -
1529*65158Sdab 		 */
1530*65158Sdab 		term = getenv("TERM");
1531*65158Sdab 		if (term == NULL || term[0] == 0) {
1532*65158Sdab 			term = "-";
1533*65158Sdab 		} else {
1534*65158Sdab 			strcpy(termbuf, "TERM=");
1535*65158Sdab 			strncat(termbuf, term, sizeof(termbuf) - 6);
1536*65158Sdab 			term = termbuf;
1537*65158Sdab 		}
1538*65158Sdab 		argv = addarg(argv, term);
1539*65158Sdab #endif
154057212Sdab 	}
154157212Sdab #endif
154246809Sdab #if	!defined(NO_LOGIN_P)
154344364Sborman 	argv = addarg(argv, "-p");
154438905Sborman #endif
154544364Sborman #ifdef	BFTPDAEMON
154644364Sborman 	/*
154744364Sborman 	 * Are we working as the bftp daemon?  If so, then ask login
154844364Sborman 	 * to start bftp instead of shell.
154944364Sborman 	 */
155044364Sborman 	if (bftpd) {
155144364Sborman 		argv = addarg(argv, "-e");
155244364Sborman 		argv = addarg(argv, BFTPPATH);
155344364Sborman 	} else
155444364Sborman #endif
155546809Sdab #if	defined (SecurID)
155646809Sdab 	/*
155746809Sdab 	 * don't worry about the -f that might get sent.
155846809Sdab 	 * A -s is supposed to override it anyhow.
155946809Sdab 	 */
156046809Sdab 	if (require_SecurID)
156146809Sdab 		argv = addarg(argv, "-s");
156246809Sdab #endif
156357212Sdab #if	defined (AUTHENTICATION)
156446809Sdab 	if (auth_level >= 0 && autologin == AUTH_VALID) {
156546809Sdab # if	!defined(NO_LOGIN_F)
156646809Sdab 		argv = addarg(argv, "-f");
1567*65158Sdab 		argv = addarg(argv, name);
1568*65158Sdab # else
1569*65158Sdab #  if defined(LOGIN_R)
1570*65158Sdab 		/*
1571*65158Sdab 		 * We don't have support for "login -f", but we
1572*65158Sdab 		 * can fool /bin/login into thinking that we are
1573*65158Sdab 		 * rlogind, and allow us to log in without a
1574*65158Sdab 		 * password.  The rlogin protocol expects
1575*65158Sdab 		 *	local-user\0remote-user\0term/speed\0
1576*65158Sdab 		 */
1577*65158Sdab 
1578*65158Sdab 		if (pty > 2) {
1579*65158Sdab 			register char *cp;
1580*65158Sdab 			char speed[128];
1581*65158Sdab 			int isecho, israw, xpty, len;
1582*65158Sdab 			extern int def_rspeed;
1583*65158Sdab #  ifndef LOGIN_HOST
1584*65158Sdab 			/*
1585*65158Sdab 			 * Tell login that we are coming from "localhost".
1586*65158Sdab 			 * If we passed in the real host name, then the
1587*65158Sdab 			 * user would have to allow .rhost access from
1588*65158Sdab 			 * every machine that they want authenticated
1589*65158Sdab 			 * access to work from, which sort of defeats
1590*65158Sdab 			 * the purpose of an authenticated login...
1591*65158Sdab 			 * So, we tell login that the session is coming
1592*65158Sdab 			 * from "localhost", and the user will only have
1593*65158Sdab 			 * to have "localhost" in their .rhost file.
1594*65158Sdab 			 */
1595*65158Sdab #			define LOGIN_HOST "localhost"
1596*65158Sdab #  endif
1597*65158Sdab 			argv = addarg(argv, "-r");
1598*65158Sdab 			argv = addarg(argv, LOGIN_HOST);
1599*65158Sdab 
1600*65158Sdab 			xpty = pty;
1601*65158Sdab # ifndef  STREAMSPTY
1602*65158Sdab 			pty = 0;
1603*65158Sdab # else
1604*65158Sdab 			ttyfd = 0;
160546809Sdab # endif
1606*65158Sdab 			init_termbuf();
1607*65158Sdab 			isecho = tty_isecho();
1608*65158Sdab 			israw = tty_israw();
1609*65158Sdab 			if (isecho || !israw) {
1610*65158Sdab 				tty_setecho(0);		/* Turn off echo */
1611*65158Sdab 				tty_setraw(1);		/* Turn on raw */
1612*65158Sdab 				set_termbuf();
1613*65158Sdab 			}
1614*65158Sdab 			len = strlen(name)+1;
1615*65158Sdab 			write(xpty, name, len);
1616*65158Sdab 			write(xpty, name, len);
1617*65158Sdab 			sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
1618*65158Sdab 				(def_rspeed > 0) ? def_rspeed : 9600);
1619*65158Sdab 			len = strlen(speed)+1;
1620*65158Sdab 			write(xpty, speed, len);
1621*65158Sdab 
1622*65158Sdab 			if (isecho || !israw) {
1623*65158Sdab 				init_termbuf();
1624*65158Sdab 				tty_setecho(isecho);
1625*65158Sdab 				tty_setraw(israw);
1626*65158Sdab 				set_termbuf();
1627*65158Sdab 				if (!israw) {
1628*65158Sdab 					/*
1629*65158Sdab 					 * Write a newline to ensure
1630*65158Sdab 					 * that login will be able to
1631*65158Sdab 					 * read the line...
1632*65158Sdab 					 */
1633*65158Sdab 					write(xpty, "\n", 1);
1634*65158Sdab 				}
1635*65158Sdab 			}
1636*65158Sdab 			pty = xpty;
1637*65158Sdab 		}
1638*65158Sdab #  else
163946809Sdab 		argv = addarg(argv, name);
1640*65158Sdab #  endif
1641*65158Sdab # endif
164246809Sdab 	} else
164346809Sdab #endif
164444364Sborman 	if (getenv("USER")) {
164544364Sborman 		argv = addarg(argv, getenv("USER"));
1646*65158Sdab #if	defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
164746809Sdab 		{
164846809Sdab 			register char **cpp;
164946809Sdab 			for (cpp = environ; *cpp; cpp++)
165046809Sdab 				argv = addarg(argv, *cpp);
165146809Sdab 		}
165246809Sdab #endif
165357212Sdab 		/*
165457212Sdab 		 * Assume that login will set the USER variable
165557212Sdab 		 * correctly.  For SysV systems, this means that
165657212Sdab 		 * USER will no longer be set, just LOGNAME by
165757212Sdab 		 * login.  (The problem is that if the auto-login
165857212Sdab 		 * fails, and the user then specifies a different
165957212Sdab 		 * account name, he can get logged in with both
166057212Sdab 		 * LOGNAME and USER in his environment, but the
166157212Sdab 		 * USER value will be wrong.
166257212Sdab 		 */
166357212Sdab 		unsetenv("USER");
166444364Sborman 	}
1665*65158Sdab #if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1666*65158Sdab 	if (pty > 2)
1667*65158Sdab 		close(pty);
1668*65158Sdab #endif
166946809Sdab 	closelog();
167044364Sborman 	execv(_PATH_LOGIN, argv);
167144364Sborman 
167238905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
167338905Sborman 	fatalperror(net, _PATH_LOGIN);
167438905Sborman 	/*NOTREACHED*/
167538905Sborman }
167644364Sborman 
167746809Sdab 	char **
167844364Sborman addarg(argv, val)
167946809Sdab 	register char **argv;
168046809Sdab 	register char *val;
168144364Sborman {
168244364Sborman 	register char **cpp;
168344364Sborman 
168444364Sborman 	if (argv == NULL) {
168544364Sborman 		/*
168644364Sborman 		 * 10 entries, a leading length, and a null
168744364Sborman 		 */
168844364Sborman 		argv = (char **)malloc(sizeof(*argv) * 12);
168944364Sborman 		if (argv == NULL)
169044364Sborman 			return(NULL);
169144364Sborman 		*argv++ = (char *)10;
169244364Sborman 		*argv = (char *)0;
169344364Sborman 	}
169444364Sborman 	for (cpp = argv; *cpp; cpp++)
169544364Sborman 		;
169644364Sborman 	if (cpp == &argv[(int)argv[-1]]) {
169744364Sborman 		--argv;
169844364Sborman 		*argv = (char *)((int)(*argv) + 10);
169944364Sborman 		argv = (char **)realloc(argv, (int)(*argv) + 2);
170044364Sborman 		if (argv == NULL)
170144364Sborman 			return(NULL);
170244364Sborman 		argv++;
170344364Sborman 		cpp = &argv[(int)argv[-1] - 10];
170444364Sborman 	}
170544364Sborman 	*cpp++ = val;
170644364Sborman 	*cpp = 0;
170744364Sborman 	return(argv);
170844364Sborman }
170946809Sdab #endif	/* NEWINIT */
171038905Sborman 
171138905Sborman /*
171238905Sborman  * cleanup()
171338905Sborman  *
171438905Sborman  * This is the routine to call when we are all through, to
171538905Sborman  * clean up anything that needs to be cleaned up.
171638905Sborman  */
171746809Sdab 	/* ARGSUSED */
171846809Sdab 	void
171946809Sdab cleanup(sig)
172046809Sdab 	int sig;
172138905Sborman {
172260151Sdab #ifndef	PARENT_DOES_UTMP
172345234Sborman # if (BSD > 43) || defined(convex)
172438905Sborman 	char *p;
172538905Sborman 
172638905Sborman 	p = line + sizeof("/dev/") - 1;
172738905Sborman 	if (logout(p))
172838905Sborman 		logwtmp(p, "", "");
172938905Sborman 	(void)chmod(line, 0666);
173038905Sborman 	(void)chown(line, 0, 0);
173138905Sborman 	*p = 'p';
173238905Sborman 	(void)chmod(line, 0666);
173338905Sborman 	(void)chown(line, 0, 0);
173446809Sdab 	(void) shutdown(net, 2);
173546809Sdab 	exit(1);
173638905Sborman # else
173746809Sdab 	void rmut();
173846809Sdab 
173938905Sborman 	rmut();
174038905Sborman 	vhangup();	/* XXX */
174146809Sdab 	(void) shutdown(net, 2);
174246809Sdab 	exit(1);
174338905Sborman # endif
174460151Sdab #else	/* PARENT_DOES_UTMP */
174546809Sdab # ifdef	NEWINIT
174638905Sborman 	(void) shutdown(net, 2);
174746809Sdab 	exit(1);
174838905Sborman # else	/* NEWINIT */
174960151Sdab #  ifdef CRAY
175046809Sdab 	static int incleanup = 0;
175146809Sdab 	register int t;
175246809Sdab 
175346809Sdab 	/*
175446809Sdab 	 * 1: Pick up the zombie, if we are being called
175546809Sdab 	 *    as the signal handler.
175646809Sdab 	 * 2: If we are a nested cleanup(), return.
175746809Sdab 	 * 3: Try to clean up TMPDIR.
175846809Sdab 	 * 4: Fill in utmp with shutdown of process.
175946809Sdab 	 * 5: Close down the network and pty connections.
176046809Sdab 	 * 6: Finish up the TMPDIR cleanup, if needed.
176146809Sdab 	 */
176246809Sdab 	if (sig == SIGCHLD)
176346809Sdab 		while (waitpid(-1, 0, WNOHANG) > 0)
176446809Sdab 			;	/* VOID */
176546809Sdab 	t = sigblock(sigmask(SIGCHLD));
176646809Sdab 	if (incleanup) {
176746809Sdab 		sigsetmask(t);
176846809Sdab 		return;
176946809Sdab 	}
177046809Sdab 	incleanup = 1;
177146809Sdab 	sigsetmask(t);
177260151Sdab 	if (secflag) {
177360151Sdab 		/*
177460151Sdab 		 *	We need to set ourselves back to a null
177560151Sdab 		 *	label to clean up.
177660151Sdab 		 */
177746809Sdab 
177860151Sdab 		setulvl(sysv.sy_minlvl);
177960151Sdab 		setucmp((long)0);
178060151Sdab 	}
178160151Sdab 
178246809Sdab 	t = cleantmp(&wtmp);
178346809Sdab 	setutent();	/* just to make sure */
178460151Sdab #  endif /* CRAY */
178546809Sdab 	rmut(line);
178646809Sdab 	close(pty);
178738905Sborman 	(void) shutdown(net, 2);
178860151Sdab #  ifdef CRAY
178946809Sdab 	if (t == 0)
179046809Sdab 		cleantmp(&wtmp);
179160151Sdab #  endif /* CRAY */
179246809Sdab 	exit(1);
179338905Sborman # endif	/* NEWINT */
179460151Sdab #endif	/* PARENT_DOES_UTMP */
179538905Sborman }
179638905Sborman 
179760151Sdab #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
179838905Sborman /*
179938905Sborman  * _utmp_sig_rcv
180038905Sborman  * utmp_sig_init
180138905Sborman  * utmp_sig_wait
180238905Sborman  *	These three functions are used to coordinate the handling of
180338905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
180438905Sborman  *	The server actually creates the utmp structure, the child calls
180538905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
180638905Sborman  *	signals the future-login shell to proceed.
180738905Sborman  */
180838905Sborman static int caught=0;		/* NZ when signal intercepted */
180938905Sborman static void (*func)();		/* address of previous handler */
181038905Sborman 
181146809Sdab 	void
181238905Sborman _utmp_sig_rcv(sig)
181346809Sdab 	int sig;
181438905Sborman {
181538905Sborman 	caught = 1;
181638905Sborman 	(void) signal(SIGUSR1, func);
181738905Sborman }
181838905Sborman 
181946809Sdab 	void
182038905Sborman utmp_sig_init()
182138905Sborman {
182238905Sborman 	/*
182338905Sborman 	 * register signal handler for UTMP creation
182438905Sborman 	 */
182538905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
182638905Sborman 		fatalperror(net, "telnetd/signal");
182738905Sborman }
182838905Sborman 
182946809Sdab 	void
183044364Sborman utmp_sig_reset()
183144364Sborman {
183244364Sborman 	(void) signal(SIGUSR1, func);	/* reset handler to default */
183344364Sborman }
183444364Sborman 
183560151Sdab # ifdef __hpux
183660151Sdab # define sigoff() /* do nothing */
183760151Sdab # define sigon() /* do nothing */
183860151Sdab # endif
183960151Sdab 
184046809Sdab 	void
184138905Sborman utmp_sig_wait()
184238905Sborman {
184338905Sborman 	/*
184438905Sborman 	 * Wait for parent to write our utmp entry.
184538905Sborman 	 */
184638905Sborman 	sigoff();
184738905Sborman 	while (caught == 0) {
184838905Sborman 		pause();	/* wait until we get a signal (sigon) */
184938905Sborman 		sigoff();	/* turn off signals while we check caught */
185038905Sborman 	}
185138905Sborman 	sigon();		/* turn on signals again */
185238905Sborman }
185338905Sborman 
185446809Sdab 	void
185538905Sborman utmp_sig_notify(pid)
185638905Sborman {
185738905Sborman 	kill(pid, SIGUSR1);
185838905Sborman }
185946809Sdab 
186060151Sdab # ifdef CRAY
186146809Sdab static int gotsigjob = 0;
186246809Sdab 
186346809Sdab 	/*ARGSUSED*/
186446809Sdab 	void
186546809Sdab sigjob(sig)
186646809Sdab 	int sig;
186746809Sdab {
186846809Sdab 	register int jid;
186946809Sdab 	register struct jobtemp *jp;
187046809Sdab 
187146809Sdab 	while ((jid = waitjob(NULL)) != -1) {
187246809Sdab 		if (jid == 0) {
187346809Sdab 			return;
187446809Sdab 		}
187546809Sdab 		gotsigjob++;
187646809Sdab 		jobend(jid, NULL, NULL);
187746809Sdab 	}
187846809Sdab }
187946809Sdab 
188046809Sdab /*
188146809Sdab  * Clean up the TMPDIR that login created.
188246809Sdab  * The first time this is called we pick up the info
188346809Sdab  * from the utmp.  If the job has already gone away,
188446809Sdab  * then we'll clean up and be done.  If not, then
188546809Sdab  * when this is called the second time it will wait
188646809Sdab  * for the signal that the job is done.
188746809Sdab  */
188846809Sdab 	int
188946809Sdab cleantmp(wtp)
189046809Sdab 	register struct utmp *wtp;
189146809Sdab {
189246809Sdab 	struct utmp *utp;
189346809Sdab 	static int first = 1;
189446809Sdab 	register int mask, omask, ret;
1895*65158Sdab 	extern struct utmp *getutid P((const struct utmp *_Id));
189646809Sdab 
1897*65158Sdab 
189846809Sdab 	mask = sigmask(WJSIGNAL);
189946809Sdab 
190046809Sdab 	if (first == 0) {
190146809Sdab 		omask = sigblock(mask);
190246809Sdab 		while (gotsigjob == 0)
190346809Sdab 			sigpause(omask);
190446809Sdab 		return(1);
190546809Sdab 	}
190646809Sdab 	first = 0;
190746809Sdab 	setutent();	/* just to make sure */
190846809Sdab 
190946809Sdab 	utp = getutid(wtp);
191046809Sdab 	if (utp == 0) {
191146809Sdab 		syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
191246809Sdab 		return(-1);
191346809Sdab 	}
191446809Sdab 	/*
191546809Sdab 	 * Nothing to clean up if the user shell was never started.
191646809Sdab 	 */
191746809Sdab 	if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
191846809Sdab 		return(1);
191946809Sdab 
192046809Sdab 	/*
192146809Sdab 	 * Block the WJSIGNAL while we are in jobend().
192246809Sdab 	 */
192346809Sdab 	omask = sigblock(mask);
192446809Sdab 	ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
192546809Sdab 	sigsetmask(omask);
192646809Sdab 	return(ret);
192746809Sdab }
192846809Sdab 
192946809Sdab 	int
193046809Sdab jobend(jid, path, user)
193146809Sdab 	register int jid;
193246809Sdab 	register char *path;
193346809Sdab 	register char *user;
193446809Sdab {
193546809Sdab 	static int saved_jid = 0;
193646809Sdab 	static char saved_path[sizeof(wtmp.ut_tpath)+1];
193746809Sdab 	static char saved_user[sizeof(wtmp.ut_user)+1];
193846809Sdab 
193946809Sdab 	if (path) {
194046809Sdab 		strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
194146809Sdab 		strncpy(saved_user, user, sizeof(wtmp.ut_user));
194246809Sdab 		saved_path[sizeof(saved_path)] = '\0';
194346809Sdab 		saved_user[sizeof(saved_user)] = '\0';
194446809Sdab 	}
194546809Sdab 	if (saved_jid == 0) {
194646809Sdab 		saved_jid = jid;
194746809Sdab 		return(0);
194846809Sdab 	}
194946809Sdab 	cleantmpdir(jid, saved_path, saved_user);
195046809Sdab 	return(1);
195146809Sdab }
195246809Sdab 
195346809Sdab /*
195446809Sdab  * Fork a child process to clean up the TMPDIR
195546809Sdab  */
195646809Sdab cleantmpdir(jid, tpath, user)
195746809Sdab 	register int jid;
195846809Sdab 	register char *tpath;
195946809Sdab 	register char *user;
196046809Sdab {
196146809Sdab 	switch(fork()) {
196246809Sdab 	case -1:
196346809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
196446809Sdab 							tpath);
196546809Sdab 		break;
196646809Sdab 	case 0:
196746809Sdab 		execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
196846809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
196946809Sdab 							tpath, CLEANTMPCMD);
197046809Sdab 		exit(1);
197146809Sdab 	default:
197246809Sdab 		/*
197346809Sdab 		 * Forget about child.  We will exit, and
197446809Sdab 		 * /etc/init will pick it up.
197546809Sdab 		 */
197646809Sdab 		break;
197746809Sdab 	}
197846809Sdab }
197960151Sdab # endif /* CRAY */
198060151Sdab #endif	/* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
198138905Sborman 
198238905Sborman /*
198338905Sborman  * rmut()
198438905Sborman  *
198538905Sborman  * This is the function called by cleanup() to
198638905Sborman  * remove the utmp entry for this person.
198738905Sborman  */
198838905Sborman 
198957212Sdab #ifdef	UTMPX
1990*65158Sdab 	void
199157212Sdab rmut()
199257212Sdab {
199357212Sdab 	register f;
199457212Sdab 	int found = 0;
199557212Sdab 	struct utmp *u, *utmp;
199657212Sdab 	int nutmp;
199757212Sdab 	struct stat statbf;
199857212Sdab 
199957212Sdab 	struct utmpx *utxp, utmpx;
200057212Sdab 
200157212Sdab 	/*
200257212Sdab 	 * This updates the utmpx and utmp entries and make a wtmp/x entry
200357212Sdab 	 */
200457212Sdab 
200557212Sdab 	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
200657212Sdab 	utxp = getutxline(&utmpx);
200757212Sdab 	if (utxp) {
200857212Sdab 		utxp->ut_type = DEAD_PROCESS;
200957212Sdab 		utxp->ut_exit.e_termination = 0;
201057212Sdab 		utxp->ut_exit.e_exit = 0;
201157212Sdab 		(void) time(&utmpx.ut_tv.tv_sec);
201257212Sdab 		utmpx.ut_tv.tv_usec = 0;
201357212Sdab 		modutx(utxp);
201457212Sdab 	}
201557212Sdab 	endutxent();
201657212Sdab }  /* end of rmut */
201757212Sdab #endif
201857212Sdab 
201960151Sdab #if	!defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
202046809Sdab 	void
202138905Sborman rmut()
202238905Sborman {
202338905Sborman 	register f;
202438905Sborman 	int found = 0;
202538905Sborman 	struct utmp *u, *utmp;
202638905Sborman 	int nutmp;
202738905Sborman 	struct stat statbf;
202838905Sborman 
202938905Sborman 	f = open(utmpf, O_RDWR);
203038905Sborman 	if (f >= 0) {
203138905Sborman 		(void) fstat(f, &statbf);
203238905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
203338905Sborman 		if (!utmp)
203438905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
203538905Sborman 		if (statbf.st_size && utmp) {
203638905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
203738905Sborman 			nutmp /= sizeof(struct utmp);
203838905Sborman 
203938905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
204038905Sborman 				if (SCMPN(u->ut_line, line+5) ||
204138905Sborman 				    u->ut_name[0]==0)
204238905Sborman 					continue;
204338905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
204438905Sborman 				SCPYN(u->ut_name, "");
204538905Sborman 				SCPYN(u->ut_host, "");
204638905Sborman 				(void) time(&u->ut_time);
204738905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
204838905Sborman 				found++;
204938905Sborman 			}
205038905Sborman 		}
205138905Sborman 		(void) close(f);
205238905Sborman 	}
205338905Sborman 	if (found) {
205438905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
205538905Sborman 		if (f >= 0) {
205638905Sborman 			SCPYN(wtmp.ut_line, line+5);
205738905Sborman 			SCPYN(wtmp.ut_name, "");
205838905Sborman 			SCPYN(wtmp.ut_host, "");
205938905Sborman 			(void) time(&wtmp.ut_time);
206038905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
206138905Sborman 			(void) close(f);
206238905Sborman 		}
206338905Sborman 	}
206438905Sborman 	(void) chmod(line, 0666);
206538905Sborman 	(void) chown(line, 0, 0);
206638905Sborman 	line[strlen("/dev/")] = 'p';
206738905Sborman 	(void) chmod(line, 0666);
206838905Sborman 	(void) chown(line, 0, 0);
206938905Sborman }  /* end of rmut */
207038905Sborman #endif	/* CRAY */
207160151Sdab 
207260151Sdab #ifdef __hpux
207360151Sdab rmut (line)
207460151Sdab char *line;
207560151Sdab {
207660151Sdab 	struct utmp utmp;
207760151Sdab 	struct utmp *utptr;
207860151Sdab 	int fd;			/* for /etc/wtmp */
207960151Sdab 
208060151Sdab 	utmp.ut_type = USER_PROCESS;
208160151Sdab 	(void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
208260151Sdab 	(void) setutent();
208360151Sdab 	utptr = getutid(&utmp);
208460151Sdab 	/* write it out only if it exists */
208560151Sdab 	if (utptr) {
208660151Sdab 		utptr->ut_type = DEAD_PROCESS;
208760151Sdab 		utptr->ut_time = time((long *) 0);
208860151Sdab 		(void) pututline(utptr);
208960151Sdab 		/* set wtmp entry if wtmp file exists */
209060151Sdab 		if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
209160151Sdab 			(void) write(fd, utptr, sizeof(utmp));
209260151Sdab 			(void) close(fd);
209360151Sdab 		}
209460151Sdab 	}
209560151Sdab 	(void) endutent();
209660151Sdab 
209760151Sdab 	(void) chmod(line, 0666);
209860151Sdab 	(void) chown(line, 0, 0);
209960151Sdab 	line[14] = line[13];
210060151Sdab 	line[13] = line[12];
210160151Sdab 	line[8] = 'm';
210260151Sdab 	line[9] = '/';
210360151Sdab 	line[10] = 'p';
210460151Sdab 	line[11] = 't';
210560151Sdab 	line[12] = 'y';
210660151Sdab 	(void) chmod(line, 0666);
210760151Sdab 	(void) chown(line, 0, 0);
210860151Sdab }
210960151Sdab #endif
2110