xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 46996)
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*46996Sdab static char sccsid[] = "@(#)sys_term.c	5.15 (Berkeley) 03/05/91";
1038905Sborman #endif /* not lint */
1138905Sborman 
1238905Sborman #include "telnetd.h"
1338905Sborman #include "pathnames.h"
1438905Sborman 
1546809Sdab #if	defined(AUTHENTICATE)
1646809Sdab #include <libtelnet/auth.h>
1746809Sdab #endif
1846809Sdab 
1938905Sborman #ifdef	NEWINIT
2038905Sborman #include <initreq.h>
2138905Sborman #else	/* NEWINIT*/
2238905Sborman #include <utmp.h>
2338905Sborman struct	utmp wtmp;
2438905Sborman 
2538905Sborman # ifndef CRAY
2638905Sborman char	wtmpf[]	= "/usr/adm/wtmp";
2738905Sborman char	utmpf[] = "/etc/utmp";
2838905Sborman # else	/* CRAY */
2938905Sborman char	wtmpf[]	= "/etc/wtmp";
3046809Sdab #include <tmpdir.h>
3146809Sdab #include <sys/wait.h>
3238905Sborman # endif	/* CRAY */
3338905Sborman #endif	/* NEWINIT */
3438905Sborman 
3538905Sborman #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
3638905Sborman #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
3738905Sborman 
3844364Sborman #ifdef	STREAMS
3944364Sborman #include <sys/stream.h>
4044364Sborman #endif
4138905Sborman #include <sys/tty.h>
4238905Sborman #ifdef	t_erase
4338905Sborman #undef	t_erase
4438905Sborman #undef	t_kill
4538905Sborman #undef	t_intrc
4638905Sborman #undef	t_quitc
4738905Sborman #undef	t_startc
4838905Sborman #undef	t_stopc
4938905Sborman #undef	t_eofc
5038905Sborman #undef	t_brkc
5138905Sborman #undef	t_suspc
5238905Sborman #undef	t_dsuspc
5338905Sborman #undef	t_rprntc
5438905Sborman #undef	t_flushc
5538905Sborman #undef	t_werasc
5638905Sborman #undef	t_lnextc
5738905Sborman #endif
5838905Sborman 
5944364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
6044364Sborman # define EXTPROC 0400
6144364Sborman #endif
6244364Sborman 
6338905Sborman #ifndef	USE_TERMIO
6438905Sborman struct termbuf {
6538905Sborman 	struct sgttyb sg;
6638905Sborman 	struct tchars tc;
6738905Sborman 	struct ltchars ltc;
6838905Sborman 	int state;
6938905Sborman 	int lflags;
7038905Sborman } termbuf, termbuf2;
7145234Sborman # define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
7245234Sborman # define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
7346809Sdab # define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
7446809Sdab # define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
7538905Sborman #else	/* USE_TERMIO */
7638905Sborman # ifdef	SYSV_TERMIO
7738905Sborman #	define termios termio
7838905Sborman # endif
7945234Sborman # ifndef	TCSANOW
8044364Sborman #  ifdef TCSETS
8145234Sborman #   define	TCSANOW		TCSETS
8245234Sborman #   define	TCSADRAIN	TCSETSW
8346809Sdab #   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
8444364Sborman #  else
8545234Sborman #   ifdef TCSETA
8645234Sborman #    define	TCSANOW		TCSETA
8745234Sborman #    define	TCSADRAIN	TCSETAW
8846809Sdab #    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
8945234Sborman #   else
9045234Sborman #    define	TCSANOW		TIOCSETA
9145234Sborman #    define	TCSADRAIN	TIOCSETAW
9246809Sdab #    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
9345234Sborman #   endif
9444364Sborman #  endif
9545234Sborman #  define	tcsetattr(f, a, t)	ioctl(f, a, t)
9645234Sborman #  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
9745234Sborman 					(tp)->c_cflag |= (val)
9846809Sdab #  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
9945234Sborman #  ifdef CIBAUD
10045234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
10145234Sborman 					(tp)->c_cflag |= ((val)<<IBSHIFT)
10246809Sdab #   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
10345234Sborman #  else
10445234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
10545234Sborman 					(tp)->c_cflag |= (val)
10646809Sdab #   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
10745234Sborman #  endif
10845234Sborman # endif /* TCSANOW */
10938905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
11038905Sborman #endif	/* USE_TERMIO */
11138905Sborman 
11238905Sborman /*
11338905Sborman  * init_termbuf()
11438905Sborman  * copy_termbuf(cp)
11538905Sborman  * set_termbuf()
11638905Sborman  *
11738905Sborman  * These three routines are used to get and set the "termbuf" structure
11838905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
11938905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
12038905Sborman  * set_termbuf() writes the structure into the kernel.
12138905Sborman  */
12238905Sborman 
12346809Sdab 	void
12438905Sborman init_termbuf()
12538905Sborman {
12638905Sborman #ifndef	USE_TERMIO
12738905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
12838905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
12938905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
13038905Sborman # ifdef	TIOCGSTATE
13138905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
13238905Sborman # endif
13338905Sborman #else
13446685Sbostic 	(void) tcgetattr(pty, &termbuf);
13538905Sborman #endif
13638905Sborman 	termbuf2 = termbuf;
13738905Sborman }
13838905Sborman 
13938905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
14046809Sdab 	void
14138905Sborman copy_termbuf(cp, len)
14246809Sdab 	char *cp;
14346809Sdab 	int len;
14438905Sborman {
14538905Sborman 	if (len > sizeof(termbuf))
14638905Sborman 		len = sizeof(termbuf);
14738905Sborman 	bcopy(cp, (char *)&termbuf, len);
14838905Sborman 	termbuf2 = termbuf;
14938905Sborman }
15038905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
15138905Sborman 
15246809Sdab 	void
15338905Sborman set_termbuf()
15438905Sborman {
15538905Sborman 	/*
15638905Sborman 	 * Only make the necessary changes.
15738905Sborman 	 */
15838905Sborman #ifndef	USE_TERMIO
15938905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
16045234Sborman 		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
16138905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
16238905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
16338905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
16438905Sborman 							sizeof(termbuf.ltc)))
16538905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
16638905Sborman 	if (termbuf.lflags != termbuf2.lflags)
16738905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
16838905Sborman #else	/* USE_TERMIO */
16938905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
17046809Sdab 		(void) tcsetattr(pty, TCSANOW, &termbuf);
17140242Sborman # if	defined(CRAY2) && defined(UNCIOS5)
17238905Sborman 	needtermstat = 1;
17338905Sborman # endif
17438905Sborman #endif	/* USE_TERMIO */
17538905Sborman }
17638905Sborman 
17738905Sborman 
17838905Sborman /*
17938905Sborman  * spcset(func, valp, valpp)
18038905Sborman  *
18138905Sborman  * This function takes various special characters (func), and
18238905Sborman  * sets *valp to the current value of that character, and
18338905Sborman  * *valpp to point to where in the "termbuf" structure that
18438905Sborman  * value is kept.
18538905Sborman  *
18638905Sborman  * It returns the SLC_ level of support for this function.
18738905Sborman  */
18838905Sborman 
18938905Sborman #ifndef	USE_TERMIO
19046809Sdab 	int
19138905Sborman spcset(func, valp, valpp)
19246809Sdab 	int func;
19346809Sdab 	cc_t *valp;
19446809Sdab 	cc_t **valpp;
19538905Sborman {
19638905Sborman 	switch(func) {
19738905Sborman 	case SLC_EOF:
19838905Sborman 		*valp = termbuf.tc.t_eofc;
19940242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
20038905Sborman 		return(SLC_VARIABLE);
20138905Sborman 	case SLC_EC:
20238905Sborman 		*valp = termbuf.sg.sg_erase;
20340242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
20438905Sborman 		return(SLC_VARIABLE);
20538905Sborman 	case SLC_EL:
20638905Sborman 		*valp = termbuf.sg.sg_kill;
20740242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
20838905Sborman 		return(SLC_VARIABLE);
20938905Sborman 	case SLC_IP:
21038905Sborman 		*valp = termbuf.tc.t_intrc;
21140242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
21238905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
21338905Sborman 	case SLC_ABORT:
21438905Sborman 		*valp = termbuf.tc.t_quitc;
21540242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
21638905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
21738905Sborman 	case SLC_XON:
21838905Sborman 		*valp = termbuf.tc.t_startc;
21940242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
22038905Sborman 		return(SLC_VARIABLE);
22138905Sborman 	case SLC_XOFF:
22238905Sborman 		*valp = termbuf.tc.t_stopc;
22340242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
22438905Sborman 		return(SLC_VARIABLE);
22538905Sborman 	case SLC_AO:
22638905Sborman 		*valp = termbuf.ltc.t_flushc;
22740242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
22838905Sborman 		return(SLC_VARIABLE);
22938905Sborman 	case SLC_SUSP:
23038905Sborman 		*valp = termbuf.ltc.t_suspc;
23140242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
23238905Sborman 		return(SLC_VARIABLE);
23338905Sborman 	case SLC_EW:
23438905Sborman 		*valp = termbuf.ltc.t_werasc;
23540242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
23638905Sborman 		return(SLC_VARIABLE);
23738905Sborman 	case SLC_RP:
23838905Sborman 		*valp = termbuf.ltc.t_rprntc;
23940242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
24038905Sborman 		return(SLC_VARIABLE);
24138905Sborman 	case SLC_LNEXT:
24238905Sborman 		*valp = termbuf.ltc.t_lnextc;
24340242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
24438905Sborman 		return(SLC_VARIABLE);
24540242Sborman 	case SLC_FORW1:
24640242Sborman 		*valp = termbuf.tc.t_brkc;
24740242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
24840242Sborman 		return(SLC_VARIABLE);
24938905Sborman 	case SLC_BRK:
25038905Sborman 	case SLC_SYNCH:
25138905Sborman 	case SLC_AYT:
25238905Sborman 	case SLC_EOR:
25340242Sborman 		*valp = (cc_t)0;
25440242Sborman 		*valpp = (cc_t *)0;
25538905Sborman 		return(SLC_DEFAULT);
25638905Sborman 	default:
25740242Sborman 		*valp = (cc_t)0;
25840242Sborman 		*valpp = (cc_t *)0;
25938905Sborman 		return(SLC_NOSUPPORT);
26038905Sborman 	}
26138905Sborman }
26238905Sborman 
26338905Sborman #else	/* USE_TERMIO */
26438905Sborman 
26546809Sdab 	int
26638905Sborman spcset(func, valp, valpp)
26746809Sdab 	int func;
26846809Sdab 	cc_t *valp;
26946809Sdab 	cc_t **valpp;
27038905Sborman {
27139503Sborman 
27239503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
27339503Sborman 			*valpp = &termbuf.c_cc[a]; \
27439503Sborman 			return(b);
27540242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
27639503Sborman 
27738905Sborman 	switch(func) {
27838905Sborman 	case SLC_EOF:
27939503Sborman 		setval(VEOF, SLC_VARIABLE);
28038905Sborman 	case SLC_EC:
28139503Sborman 		setval(VERASE, SLC_VARIABLE);
28238905Sborman 	case SLC_EL:
28339503Sborman 		setval(VKILL, SLC_VARIABLE);
28438905Sborman 	case SLC_IP:
28539503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
28638905Sborman 	case SLC_ABORT:
28739503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
28838905Sborman 	case SLC_XON:
28939503Sborman #ifdef	VSTART
29039503Sborman 		setval(VSTART, SLC_VARIABLE);
29139503Sborman #else
29239503Sborman 		defval(0x13);
29339503Sborman #endif
29438905Sborman 	case SLC_XOFF:
29539503Sborman #ifdef	VSTOP
29639503Sborman 		setval(VSTOP, SLC_VARIABLE);
29739503Sborman #else
29839503Sborman 		defval(0x11);
29939503Sborman #endif
30038905Sborman 	case SLC_EW:
30139503Sborman #ifdef	VWERASE
30239503Sborman 		setval(VWERASE, SLC_VARIABLE);
30339503Sborman #else
30439503Sborman 		defval(0);
30539503Sborman #endif
30638905Sborman 	case SLC_RP:
30739503Sborman #ifdef	VREPRINT
30839503Sborman 		setval(VREPRINT, SLC_VARIABLE);
30939503Sborman #else
31039503Sborman 		defval(0);
31139503Sborman #endif
31238905Sborman 	case SLC_LNEXT:
31339503Sborman #ifdef	VLNEXT
31439503Sborman 		setval(VLNEXT, SLC_VARIABLE);
31539503Sborman #else
31639503Sborman 		defval(0);
31739503Sborman #endif
31839503Sborman 	case SLC_AO:
31945234Sborman #if	!defined(VDISCARD) && defined(VFLUSHO)
32045234Sborman # define VDISCARD VFLUSHO
32145234Sborman #endif
32245234Sborman #ifdef	VDISCARD
32345234Sborman 		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
32439503Sborman #else
32539503Sborman 		defval(0);
32639503Sborman #endif
32739503Sborman 	case SLC_SUSP:
32839503Sborman #ifdef	VSUSP
32939503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
33039503Sborman #else
33139503Sborman 		defval(0);
33239503Sborman #endif
33340242Sborman #ifdef	VEOL
33440242Sborman 	case SLC_FORW1:
33540242Sborman 		setval(VEOL, SLC_VARIABLE);
33640242Sborman #endif
33740242Sborman #ifdef	VEOL2
33840242Sborman 	case SLC_FORW2:
33940242Sborman 		setval(VEOL2, SLC_VARIABLE);
34040242Sborman #endif
34145234Sborman 	case SLC_AYT:
34245234Sborman #ifdef	VSTATUS
34345234Sborman 		setval(VSTATUS, SLC_VARIABLE);
34445234Sborman #else
34545234Sborman 		defval(0);
34645234Sborman #endif
34739503Sborman 
34838905Sborman 	case SLC_BRK:
34938905Sborman 	case SLC_SYNCH:
35038905Sborman 	case SLC_EOR:
35139503Sborman 		defval(0);
35239503Sborman 
35338905Sborman 	default:
35438905Sborman 		*valp = 0;
35538905Sborman 		*valpp = 0;
35638905Sborman 		return(SLC_NOSUPPORT);
35738905Sborman 	}
35838905Sborman }
35938905Sborman #endif	/* USE_TERMIO */
36038905Sborman 
36140242Sborman #ifdef CRAY
36238905Sborman /*
36340242Sborman  * getnpty()
36440242Sborman  *
36540242Sborman  * Return the number of pty's configured into the system.
36640242Sborman  */
36746809Sdab 	int
36840242Sborman getnpty()
36940242Sborman {
37040242Sborman #ifdef _SC_CRAY_NPTY
37146809Sdab 	int numptys;
37246809Sdab 
37346809Sdab 	if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
37446809Sdab 		return numptys;
37546809Sdab 	else
37640242Sborman #endif /* _SC_CRAY_NPTY */
37746809Sdab 		return 128;
37840242Sborman }
37940242Sborman #endif /* CRAY */
38040242Sborman 
38145234Sborman #ifndef	convex
38240242Sborman /*
38338905Sborman  * getpty()
38438905Sborman  *
38538905Sborman  * Allocate a pty.  As a side effect, the external character
38638905Sborman  * array "line" contains the name of the slave side.
38738905Sborman  *
38838905Sborman  * Returns the file descriptor of the opened pty.
38938905Sborman  */
39045234Sborman #ifndef	__GNUC__
39138905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
39245234Sborman #else
39345234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
39445234Sborman char *line = Xline;
39545234Sborman #endif
39645234Sborman #ifdef	CRAY
39745234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
39845234Sborman #endif	/* CRAY */
39938905Sborman 
40046809Sdab 	int
40138905Sborman getpty()
40238905Sborman {
40338905Sborman 	register int p;
40438905Sborman #ifndef CRAY
40538905Sborman 	register char c, *p1, *p2;
40638905Sborman 	register int i;
40738905Sborman 
40838905Sborman 	(void) sprintf(line, "/dev/ptyXX");
40938905Sborman 	p1 = &line[8];
41038905Sborman 	p2 = &line[9];
41138905Sborman 
41238905Sborman 	for (c = 'p'; c <= 's'; c++) {
41338905Sborman 		struct stat stb;
41438905Sborman 
41538905Sborman 		*p1 = c;
41638905Sborman 		*p2 = '0';
41738905Sborman 		if (stat(line, &stb) < 0)
41838905Sborman 			break;
41938905Sborman 		for (i = 0; i < 16; i++) {
42038905Sborman 			*p2 = "0123456789abcdef"[i];
42138905Sborman 			p = open(line, 2);
42238905Sborman 			if (p > 0) {
42338905Sborman 				line[5] = 't';
42438905Sborman 				return(p);
42538905Sborman 			}
42638905Sborman 		}
42738905Sborman 	}
42838905Sborman #else	/* CRAY */
42938905Sborman 	register int npty;
43038905Sborman 	extern lowpty, highpty;
43145234Sborman 	struct stat sb;
43238905Sborman 
43338905Sborman 	for (npty = lowpty; npty <= highpty; npty++) {
43445234Sborman 		(void) sprintf(myline, "/dev/pty/%03d", npty);
43545234Sborman 		p = open(myline, 2);
43638905Sborman 		if (p < 0)
43738905Sborman 			continue;
43838905Sborman 		(void) sprintf(line, "/dev/ttyp%03d", npty);
43945234Sborman 		/*
44045234Sborman 		 * Here are some shenanigans to make sure that there
44145234Sborman 		 * are no listeners lurking on the line.
44245234Sborman 		 */
44345234Sborman 		if(stat(line, &sb) < 0) {
44445234Sborman 			(void) close(p);
44545234Sborman 			continue;
44645234Sborman 		}
44745234Sborman 		if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
44845234Sborman 			chown(line, 0, 0);
44945234Sborman 			chmod(line, 0600);
45045234Sborman 			(void)close(p);
45145234Sborman 			p = open(myline, 2);
45245234Sborman 			if (p < 0)
45345234Sborman 				continue;
45445234Sborman 		}
45545234Sborman 		/*
45645234Sborman 		 * Now it should be safe...check for accessability.
45745234Sborman 		 */
45838905Sborman 		if (access(line, 6) == 0)
45938905Sborman 			return(p);
46038905Sborman 		else {
46138905Sborman 			/* no tty side to pty so skip it */
46238905Sborman 			(void) close(p);
46338905Sborman 		}
46438905Sborman 	}
46538905Sborman #endif	/* CRAY */
46638905Sborman 	return(-1);
46738905Sborman }
46845234Sborman #endif	/* convex */
46938905Sborman 
47038905Sborman #ifdef	LINEMODE
47138905Sborman /*
47238905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
47338905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
47438905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
47538905Sborman  * tty_isecho()		Find out if echoing is turned on.
47638905Sborman  * tty_setecho(on)	Enable/disable character echoing.
47738905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
47838905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
47938905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
48038905Sborman  * tty_isediting()	Find out if line editing is enabled.
48138905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
48238905Sborman  * tty_setedit(on)	Turn on/off line editing.
48338905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
48444364Sborman  * tty_issofttab()	Find out if tab expansion is enabled.
48544364Sborman  * tty_setsofttab(on)	Turn on/off soft tab expansion.
48644364Sborman  * tty_islitecho()	Find out if typed control chars are echoed literally
48744364Sborman  * tty_setlitecho()	Turn on/off literal echo of control chars
48838905Sborman  * tty_tspeed(val)	Set transmit speed to val.
48938905Sborman  * tty_rspeed(val)	Set receive speed to val.
49038905Sborman  */
49138905Sborman 
49246809Sdab 	int
49338905Sborman tty_flowmode()
49438905Sborman {
49538905Sborman #ifndef USE_TERMIO
49646809Sdab 	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
49738905Sborman #else
49838905Sborman 	return(termbuf.c_iflag & IXON ? 1 : 0);
49938905Sborman #endif
50038905Sborman }
50138905Sborman 
50245234Sborman #ifdef convex
50345234Sborman static int linestate;
50445234Sborman #endif
50545234Sborman 
50646809Sdab 	int
50738905Sborman tty_linemode()
50838905Sborman {
50945234Sborman #ifndef convex
51038905Sborman #ifndef	USE_TERMIO
51138905Sborman 	return(termbuf.state & TS_EXTPROC);
51238905Sborman #else
51338905Sborman 	return(termbuf.c_lflag & EXTPROC);
51438905Sborman #endif
51545234Sborman #else
51645234Sborman 	return(linestate);
51745234Sborman #endif
51838905Sborman }
51938905Sborman 
52046809Sdab 	void
52138905Sborman tty_setlinemode(on)
52246809Sdab 	int on;
52338905Sborman {
52438905Sborman #ifdef	TIOCEXT
52545234Sborman # ifndef convex
52645234Sborman 	set_termbuf();
52745234Sborman # else
52845234Sborman 	linestate = on;
52945234Sborman # endif
53038905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
53145234Sborman # ifndef convex
53245234Sborman 	init_termbuf();
53345234Sborman # endif
53438905Sborman #else	/* !TIOCEXT */
53545234Sborman # ifdef	EXTPROC
53638905Sborman 	if (on)
53738905Sborman 		termbuf.c_lflag |= EXTPROC;
53838905Sborman 	else
53938905Sborman 		termbuf.c_lflag &= ~EXTPROC;
54045234Sborman # endif
54138905Sborman #endif	/* TIOCEXT */
54238905Sborman }
54338905Sborman 
54446809Sdab 	int
54538905Sborman tty_isecho()
54638905Sborman {
54738905Sborman #ifndef USE_TERMIO
54838905Sborman 	return (termbuf.sg.sg_flags & ECHO);
54938905Sborman #else
55038905Sborman 	return (termbuf.c_lflag & ECHO);
55138905Sborman #endif
55238905Sborman }
55338905Sborman #endif	/* LINEMODE */
55438905Sborman 
55546809Sdab 	void
55638905Sborman tty_setecho(on)
55746809Sdab 	int on;
55838905Sborman {
55938905Sborman #ifndef	USE_TERMIO
56038905Sborman 	if (on)
56138905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
56238905Sborman 	else
56338905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
56438905Sborman #else
56538905Sborman 	if (on)
56638905Sborman 		termbuf.c_lflag |= ECHO;
56738905Sborman 	else
56838905Sborman 		termbuf.c_lflag &= ~ECHO;
56938905Sborman #endif
57038905Sborman }
57138905Sborman 
57238905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
57346809Sdab 	int
57438905Sborman tty_israw()
57538905Sborman {
57638905Sborman #ifndef USE_TERMIO
57738905Sborman 	return(termbuf.sg.sg_flags & RAW);
57838905Sborman #else
57938905Sborman 	return(!(termbuf.c_lflag & ICANON));
58038905Sborman #endif
58138905Sborman }
58238905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
58338905Sborman 
58446809Sdab 	void
58538905Sborman tty_binaryin(on)
58646809Sdab 	int on;
58738905Sborman {
58838905Sborman #ifndef	USE_TERMIO
58938905Sborman 	if (on)
59038905Sborman 		termbuf.lflags |= LPASS8;
59138905Sborman 	else
59238905Sborman 		termbuf.lflags &= ~LPASS8;
59338905Sborman #else
59438905Sborman 	if (on) {
59546809Sdab 		termbuf.c_iflag &= ~ISTRIP;
59638905Sborman 	} else {
59746809Sdab 		termbuf.c_iflag |= ISTRIP;
59838905Sborman 	}
59938905Sborman #endif
60038905Sborman }
60138905Sborman 
60246809Sdab 	void
60338905Sborman tty_binaryout(on)
60446809Sdab 	int on;
60538905Sborman {
60638905Sborman #ifndef	USE_TERMIO
60738905Sborman 	if (on)
60838905Sborman 		termbuf.lflags |= LLITOUT;
60938905Sborman 	else
61038905Sborman 		termbuf.lflags &= ~LLITOUT;
61138905Sborman #else
61238905Sborman 	if (on) {
61338905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
61438905Sborman 		termbuf.c_cflag |= CS8;
61538905Sborman 		termbuf.c_oflag &= ~OPOST;
61638905Sborman 	} else {
61738905Sborman 		termbuf.c_cflag &= ~CSIZE;
61838905Sborman 		termbuf.c_cflag |= CS7|PARENB;
61938905Sborman 		termbuf.c_oflag |= OPOST;
62038905Sborman 	}
62138905Sborman #endif
62238905Sborman }
62338905Sborman 
62446809Sdab 	int
62538905Sborman tty_isbinaryin()
62638905Sborman {
62738905Sborman #ifndef	USE_TERMIO
62838905Sborman 	return(termbuf.lflags & LPASS8);
62938905Sborman #else
63039503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
63138905Sborman #endif
63238905Sborman }
63338905Sborman 
63446809Sdab 	int
63538905Sborman tty_isbinaryout()
63638905Sborman {
63738905Sborman #ifndef	USE_TERMIO
63838905Sborman 	return(termbuf.lflags & LLITOUT);
63938905Sborman #else
64039503Sborman 	return(!(termbuf.c_oflag&OPOST));
64138905Sborman #endif
64238905Sborman }
64338905Sborman 
64438905Sborman #ifdef	LINEMODE
64546809Sdab 	int
64638905Sborman tty_isediting()
64738905Sborman {
64838905Sborman #ifndef USE_TERMIO
64938905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
65038905Sborman #else
65138905Sborman 	return(termbuf.c_lflag & ICANON);
65238905Sborman #endif
65338905Sborman }
65438905Sborman 
65546809Sdab 	int
65638905Sborman tty_istrapsig()
65738905Sborman {
65838905Sborman #ifndef USE_TERMIO
65938905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
66038905Sborman #else
66138905Sborman 	return(termbuf.c_lflag & ISIG);
66238905Sborman #endif
66338905Sborman }
66438905Sborman 
66546809Sdab 	void
66638905Sborman tty_setedit(on)
66746809Sdab 	int on;
66838905Sborman {
66938905Sborman #ifndef USE_TERMIO
67038905Sborman 	if (on)
67138905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
67238905Sborman 	else
67338905Sborman 		termbuf.sg.sg_flags |= CBREAK;
67438905Sborman #else
67538905Sborman 	if (on)
67638905Sborman 		termbuf.c_lflag |= ICANON;
67738905Sborman 	else
67838905Sborman 		termbuf.c_lflag &= ~ICANON;
67938905Sborman #endif
68038905Sborman }
68138905Sborman 
68246809Sdab 	void
68338905Sborman tty_setsig(on)
68446809Sdab 	int on;
68538905Sborman {
68638905Sborman #ifndef	USE_TERMIO
68738905Sborman 	if (on)
68838905Sborman 		;
68938905Sborman #else
69038905Sborman 	if (on)
69138905Sborman 		termbuf.c_lflag |= ISIG;
69238905Sborman 	else
69338905Sborman 		termbuf.c_lflag &= ~ISIG;
69438905Sborman #endif
69538905Sborman }
69638905Sborman #endif	/* LINEMODE */
69738905Sborman 
69846809Sdab 	int
69944364Sborman tty_issofttab()
70044364Sborman {
70144364Sborman #ifndef	USE_TERMIO
70244364Sborman 	return (termbuf.sg.sg_flags & XTABS);
70344364Sborman #else
70444364Sborman # ifdef	OXTABS
70544364Sborman 	return (termbuf.c_oflag & OXTABS);
70644364Sborman # endif
70744364Sborman # ifdef	TABDLY
70844364Sborman 	return ((termbuf.c_oflag & TABDLY) == TAB3);
70944364Sborman # endif
71044364Sborman #endif
71144364Sborman }
71244364Sborman 
71346809Sdab 	void
71444364Sborman tty_setsofttab(on)
71546809Sdab 	int on;
71644364Sborman {
71744364Sborman #ifndef	USE_TERMIO
71844364Sborman 	if (on)
71944364Sborman 		termbuf.sg.sg_flags |= XTABS;
72044364Sborman 	else
72144364Sborman 		termbuf.sg.sg_flags &= ~XTABS;
72244364Sborman #else
72344364Sborman 	if (on) {
72444364Sborman # ifdef	OXTABS
72544364Sborman 		termbuf.c_oflag |= OXTABS;
72644364Sborman # endif
72744364Sborman # ifdef	TABDLY
72844364Sborman 		termbuf.c_oflag &= ~TABDLY;
72944364Sborman 		termbuf.c_oflag |= TAB3;
73044364Sborman # endif
73144364Sborman 	} else {
73244364Sborman # ifdef	OXTABS
73344364Sborman 		termbuf.c_oflag &= ~OXTABS;
73444364Sborman # endif
73544364Sborman # ifdef	TABDLY
73644364Sborman 		termbuf.c_oflag &= ~TABDLY;
73744364Sborman 		termbuf.c_oflag |= TAB0;
73844364Sborman # endif
73944364Sborman 	}
74044364Sborman #endif
74144364Sborman }
74244364Sborman 
74346809Sdab 	int
74444364Sborman tty_islitecho()
74544364Sborman {
74644364Sborman #ifndef	USE_TERMIO
74746809Sdab 	return (!(termbuf.lflags & LCTLECH));
74844364Sborman #else
74944364Sborman # ifdef	ECHOCTL
75044364Sborman 	return (!(termbuf.c_lflag & ECHOCTL));
75144364Sborman # endif
75244364Sborman # ifdef	TCTLECH
75344364Sborman 	return (!(termbuf.c_lflag & TCTLECH));
75444364Sborman # endif
75544364Sborman # if	!defined(ECHOCTL) && !defined(TCTLECH)
75644364Sborman 	return (0);	/* assumes ctl chars are echoed '^x' */
75744364Sborman # endif
75844364Sborman #endif
75944364Sborman }
76044364Sborman 
76146809Sdab 	void
76244364Sborman tty_setlitecho(on)
76346809Sdab 	int on;
76444364Sborman {
76544364Sborman #ifndef	USE_TERMIO
76644364Sborman 	if (on)
76746809Sdab 		termbuf.lflags &= ~LCTLECH;
76844364Sborman 	else
76946809Sdab 		termbuf.lflags |= LCTLECH;
77044364Sborman #else
77144364Sborman # ifdef	ECHOCTL
77244364Sborman 	if (on)
77344364Sborman 		termbuf.c_lflag &= ~ECHOCTL;
77444364Sborman 	else
77544364Sborman 		termbuf.c_lflag |= ECHOCTL;
77644364Sborman # endif
77744364Sborman # ifdef	TCTLECH
77844364Sborman 	if (on)
77944364Sborman 		termbuf.c_lflag &= ~TCTLECH;
78044364Sborman 	else
78144364Sborman 		termbuf.c_lflag |= TCTLECH;
78244364Sborman # endif
78344364Sborman #endif
78444364Sborman }
78544364Sborman 
78646809Sdab 	int
78746809Sdab tty_iscrnl()
78846809Sdab {
78946809Sdab #ifndef	USE_TERMIO
79046809Sdab 	return (termbuf.sg.sg_flags & CRMOD);
79146809Sdab #else
79246809Sdab 	return (termbuf.c_iflag & ICRNL);
79346809Sdab #endif
79446809Sdab }
79546809Sdab 
79638905Sborman /*
79738905Sborman  * A table of available terminal speeds
79838905Sborman  */
79938905Sborman struct termspeeds {
80038905Sborman 	int	speed;
80138905Sborman 	int	value;
80238905Sborman } termspeeds[] = {
80338905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
80438905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
80538905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
80638905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
80738905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
80838905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
80938905Sborman };
81038905Sborman 
81146809Sdab 	void
81238905Sborman tty_tspeed(val)
81346809Sdab 	int val;
81438905Sborman {
81538905Sborman 	register struct termspeeds *tp;
81638905Sborman 
81738905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
81838905Sborman 		;
81945234Sborman 	cfsetospeed(&termbuf, tp->value);
82038905Sborman }
82138905Sborman 
82246809Sdab 	void
82338905Sborman tty_rspeed(val)
82446809Sdab 	int val;
82538905Sborman {
82638905Sborman 	register struct termspeeds *tp;
82738905Sborman 
82838905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
82938905Sborman 		;
83045234Sborman 	cfsetispeed(&termbuf, tp->value);
83138905Sborman }
83238905Sborman 
83340242Sborman #if	defined(CRAY2) && defined(UNICOS5)
83446809Sdab 	int
83538905Sborman tty_isnewmap()
83638905Sborman {
83738905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
83838905Sborman 			!(termbuf.c_oflag & ONLRET));
83938905Sborman }
84038905Sborman #endif
84138905Sborman 
84238905Sborman #ifdef	CRAY
84338905Sborman # ifndef NEWINIT
84438905Sborman extern	struct utmp wtmp;
84538905Sborman extern char wtmpf[];
84638905Sborman # else	/* NEWINIT */
84738905Sborman int	gotalarm;
84846809Sdab 
84946809Sdab 	/* ARGSUSED */
85046809Sdab 	void
85140242Sborman nologinproc(sig)
85246809Sdab 	int sig;
85338905Sborman {
85438905Sborman 	gotalarm++;
85538905Sborman }
85638905Sborman # endif	/* NEWINIT */
85738905Sborman #endif /* CRAY */
85838905Sborman 
85946809Sdab #ifndef	NEWINIT
86046809Sdab # ifdef	CRAY
86146809Sdab extern void utmp_sig_init P((void));
86246809Sdab extern void utmp_sig_reset P((void));
86346809Sdab extern void utmp_sig_wait P((void));
86446809Sdab extern void utmp_sig_notify P((int));
86546809Sdab # endif
86646809Sdab #endif
86746809Sdab 
86838905Sborman /*
86938905Sborman  * getptyslave()
87038905Sborman  *
87138905Sborman  * Open the slave side of the pty, and do any initialization
87238905Sborman  * that is necessary.  The return value is a file descriptor
87338905Sborman  * for the slave side.
87438905Sborman  */
87546809Sdab 	int
87638905Sborman getptyslave()
87738905Sborman {
87838905Sborman 	register int t = -1;
87938905Sborman 
88045234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
88145234Sborman # ifdef	LINEMODE
88246809Sdab 	int waslm;
88346809Sdab # endif
88446809Sdab # ifdef	TIOCGWINSZ
88546809Sdab 	struct winsize ws;
88646809Sdab 	extern int def_row, def_col;
88746809Sdab # endif
88846809Sdab 	extern int def_tspeed, def_rspeed;
88938905Sborman 	/*
89045234Sborman 	 * Opening the slave side may cause initilization of the
89146809Sdab 	 * kernel tty structure.  We need remember the state of
89246809Sdab 	 * 	if linemode was turned on
89346809Sdab 	 *	terminal window size
89446809Sdab 	 *	terminal speed
89546809Sdab 	 * so that we can re-set them if we need to.
89638905Sborman 	 */
89746809Sdab # ifdef	LINEMODE
89846809Sdab 	waslm = tty_linemode();
89945234Sborman # endif
90045234Sborman 
90145234Sborman 
90245234Sborman 	/*
90345234Sborman 	 * Make sure that we don't have a controlling tty, and
90445234Sborman 	 * that we are the session (process group) leader.
90545234Sborman 	 */
90645234Sborman # ifdef	TIOCNOTTY
90738905Sborman 	t = open(_PATH_TTY, O_RDWR);
90838905Sborman 	if (t >= 0) {
90938905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
91038905Sborman 		(void) close(t);
91138905Sborman 	}
91245234Sborman # endif
91338905Sborman 
91445234Sborman 
91545234Sborman # ifdef	CRAY
91645234Sborman 	/*
91745234Sborman 	 * Wait for our parent to get the utmp stuff to get done.
91845234Sborman 	 */
91945234Sborman 	utmp_sig_wait();
92045234Sborman # endif
92145234Sborman 
92245234Sborman 	t = cleanopen(line);
92338905Sborman 	if (t < 0)
92438905Sborman 		fatalperror(net, line);
92538905Sborman 
92645234Sborman 	/*
92745234Sborman 	 * set up the tty modes as we like them to be.
92845234Sborman 	 */
92938905Sborman 	init_termbuf();
93046809Sdab # ifdef	TIOCGWINSZ
93146809Sdab 	if (def_row || def_col) {
93246809Sdab 		bzero((char *)&ws, sizeof(ws));
93346809Sdab 		ws.ws_col = def_col;
93446809Sdab 		ws.ws_row = def_row;
93546809Sdab 		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
93646809Sdab 	}
93746809Sdab # endif
93845234Sborman 
93945234Sborman 	/*
94045234Sborman 	 * Settings for sgtty based systems
94145234Sborman 	 */
94245234Sborman # ifndef	USE_TERMIO
94340242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
94445234Sborman # endif	/* USE_TERMIO */
94545234Sborman 
94645234Sborman 	/*
94745234Sborman 	 * Settings for UNICOS
94845234Sborman 	 */
94945234Sborman # ifdef	CRAY
95045234Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
95145234Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
95245234Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
95345234Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
95445234Sborman # endif
95545234Sborman 
95645234Sborman 	/*
95745234Sborman 	 * Settings for all other termios/termio based
95845234Sborman 	 * systems, other than 4.4BSD.  In 4.4BSD the
95945234Sborman 	 * kernel does the initial terminal setup.
96045234Sborman 	 */
96145234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43)
96245234Sborman #  ifndef	OXTABS
96345234Sborman #   define OXTABS	0
96445234Sborman #  endif
96538905Sborman 	termbuf.c_lflag |= ECHO;
96638905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
96738905Sborman 	termbuf.c_iflag |= ICRNL;
96838905Sborman 	termbuf.c_iflag &= ~IXOFF;
96945234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
970*46996Sdab 	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
971*46996Sdab 	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
97246809Sdab # ifdef	LINEMODE
97346809Sdab 	if (waslm)
97446809Sdab 		tty_setlinemode(1);
97546809Sdab # endif	/* LINEMODE */
97645234Sborman 
97745234Sborman 	/*
97845234Sborman 	 * Set the tty modes, and make this our controlling tty.
97945234Sborman 	 */
98045234Sborman 	set_termbuf();
98145234Sborman 	if (login_tty(t) == -1)
98245234Sborman 		fatalperror(net, "login_tty");
98345234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
98445234Sborman 	if (net > 2)
98545234Sborman 		(void) close(net);
98645234Sborman 	if (pty > 2)
98745234Sborman 		(void) close(pty);
98845234Sborman }
98945234Sborman 
99045234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
99145234Sborman #ifndef	O_NOCTTY
99245234Sborman #define	O_NOCTTY	0
99338905Sborman #endif
99445234Sborman /*
99545234Sborman  * Open the specified slave side of the pty,
99645234Sborman  * making sure that we have a clean tty.
99745234Sborman  */
99846809Sdab 	int
99945234Sborman cleanopen(line)
100046809Sdab 	char *line;
100145234Sborman {
100245234Sborman 	register int t;
100345234Sborman 
100445234Sborman 	/*
100545234Sborman 	 * Make sure that other people can't open the
100645234Sborman 	 * slave side of the connection.
100745234Sborman 	 */
100838905Sborman 	(void) chown(line, 0, 0);
100938905Sborman 	(void) chmod(line, 0600);
101045234Sborman 
101145234Sborman # if !defined(CRAY) && (BSD > 43)
101245234Sborman 	(void) revoke(line);
101345234Sborman # endif
101445234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
101545234Sborman 	if (t < 0)
101645234Sborman 		return(-1);
101745234Sborman 
101845234Sborman 	/*
101945234Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
102045234Sborman 	 * ourselves.
102145234Sborman 	 */
102245234Sborman # if !defined(CRAY) && (BSD <= 43)
102345234Sborman 	(void) signal(SIGHUP, SIG_IGN);
102445234Sborman 	vhangup();
102545234Sborman 	(void) signal(SIGHUP, SIG_DFL);
102645234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
102745234Sborman 	if (t < 0)
102845234Sborman 		return(-1);
102945234Sborman # endif
103045234Sborman # if	defined(CRAY) && defined(TCVHUP)
103145234Sborman 	{
103245234Sborman 		register int i;
103345234Sborman 		(void) signal(SIGHUP, SIG_IGN);
103445234Sborman 		(void) ioctl(t, TCVHUP, (char *)0);
103545234Sborman 		(void) signal(SIGHUP, SIG_DFL);
103645234Sborman 		setpgrp();
103745234Sborman 		i = open(line, O_RDWR);
103845234Sborman 		if (i < 0)
103946809Sdab 			return(-1);
104045234Sborman 		(void) close(t);
104145234Sborman 		t = i;
104245234Sborman 	}
104345234Sborman # endif	/* defined(CRAY) && defined(TCVHUP) */
104438905Sborman 	return(t);
104538905Sborman }
104645234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
104738905Sborman 
104845234Sborman #if BSD <= 43
104946809Sdab 	int
105045234Sborman login_tty(t)
105146809Sdab 	int t;
105245234Sborman {
105345234Sborman 	if (setsid() < 0)
105445234Sborman 		fatalperror(net, "setsid()");
105545234Sborman # ifdef	TIOCSCTTY
105645234Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
105745234Sborman 		fatalperror(net, "ioctl(sctty)");
105845234Sborman # else
105945234Sborman 	close(open(line, O_RDWR));
106045234Sborman # endif
106145234Sborman 	(void) dup2(t, 0);
106245234Sborman 	(void) dup2(t, 1);
106345234Sborman 	(void) dup2(t, 2);
106445234Sborman 	close(t);
106546809Sdab 	return(0);
106645234Sborman }
106745234Sborman #endif	/* BSD <= 43 */
106845234Sborman 
106938905Sborman #ifdef	NEWINIT
107038905Sborman char *gen_id = "fe";
107138905Sborman #endif
107238905Sborman 
107338905Sborman /*
107445234Sborman  * startslave(host)
107538905Sborman  *
107645234Sborman  * Given a hostname, do whatever
107738905Sborman  * is necessary to startup the login process on the slave side of the pty.
107838905Sborman  */
107938905Sborman 
108038905Sborman /* ARGSUSED */
108146809Sdab 	void
108246809Sdab startslave(host, autologin, autoname)
108346809Sdab 	char *host;
108446809Sdab 	int autologin;
108546809Sdab 	char *autoname;
108638905Sborman {
108738905Sborman 	register int i;
108838905Sborman 	long time();
108946809Sdab 	char name[256];
109046809Sdab #ifdef	NEWINIT
109146809Sdab 	extern char *ptyip;
109246809Sdab 	struct init_request request;
109346809Sdab 	void nologinproc();
109446809Sdab 	register int n;
109546809Sdab #endif	/* NEWINIT */
109638905Sborman 
109746809Sdab #if	defined(AUTHENTICATE)
109846809Sdab 	if (!autoname || !autoname[0])
109946809Sdab 		autologin = 0;
110046809Sdab 
110146809Sdab 	if (autologin < auth_level) {
110246809Sdab 		fatal(net, "Authorization failed");
110346809Sdab 		exit(1);
110446809Sdab 	}
110546809Sdab #endif
110646809Sdab 
110738905Sborman #ifndef	NEWINIT
110838905Sborman # ifdef	CRAY
110938905Sborman 	utmp_sig_init();
111038905Sborman # endif	/* CRAY */
111138905Sborman 
111238905Sborman 	if ((i = fork()) < 0)
111338905Sborman 		fatalperror(net, "fork");
111438905Sborman 	if (i) {
111538905Sborman # ifdef	CRAY
111638905Sborman 		/*
111738905Sborman 		 * Cray parent will create utmp entry for child and send
111838905Sborman 		 * signal to child to tell when done.  Child waits for signal
111938905Sborman 		 * before doing anything important.
112038905Sborman 		 */
112138905Sborman 		register int pid = i;
112246809Sdab 		void sigjob P((int));
112338905Sborman 
112438905Sborman 		setpgrp();
112544364Sborman 		utmp_sig_reset();		/* reset handler to default */
112638905Sborman 		/*
112738905Sborman 		 * Create utmp entry for child
112838905Sborman 		 */
112938905Sborman 		(void) time(&wtmp.ut_time);
113038905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
113138905Sborman 		wtmp.ut_pid = pid;
113238905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
113338905Sborman 		SCPYN(wtmp.ut_host, host);
113438905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
113538905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
113638905Sborman 		pututline(&wtmp);
113738905Sborman 		endutent();
113838905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
113938905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
114038905Sborman 			(void) close(i);
114138905Sborman 		}
114246809Sdab 		(void) signal(WJSIGNAL, sigjob);
114338905Sborman 		utmp_sig_notify(pid);
114438905Sborman # endif	/* CRAY */
114538905Sborman 	} else {
114645234Sborman 		getptyslave();
114746809Sdab 		start_login(host, autologin, autoname);
114838905Sborman 		/*NOTREACHED*/
114938905Sborman 	}
115038905Sborman #else	/* NEWINIT */
115138905Sborman 
115238905Sborman 	/*
115338905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
115438905Sborman 	 * for it to start up and begin normal telnet operation.
115538905Sborman 	 */
115638905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
115738905Sborman 		char tbuf[128];
115838905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
115938905Sborman 		fatalperror(net, tbuf);
116038905Sborman 	}
116138905Sborman 	memset((char *)&request, 0, sizeof(request));
116238905Sborman 	request.magic = INIT_MAGIC;
116338905Sborman 	SCPYN(request.gen_id, gen_id);
116438905Sborman 	SCPYN(request.tty_id, &line[8]);
116538905Sborman 	SCPYN(request.host, host);
116646809Sdab 	SCPYN(request.term_type, terminaltype ? terminaltype : "network");
116744364Sborman #if	!defined(UNICOS5)
116840242Sborman 	request.signal = SIGCLD;
116940242Sborman 	request.pid = getpid();
117040242Sborman #endif
117144364Sborman #ifdef BFTPDAEMON
117244364Sborman 	/*
117344364Sborman 	 * Are we working as the bftp daemon?
117444364Sborman 	 */
117544364Sborman 	if (bftpd) {
117644364Sborman 		SCPYN(request.exec_name, BFTPPATH);
117744364Sborman 	}
117844364Sborman #endif /* BFTPDAEMON */
117938905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
118038905Sborman 		char tbuf[128];
118138905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
118238905Sborman 		fatalperror(net, tbuf);
118338905Sborman 	}
118438905Sborman 	(void) close(i);
118538905Sborman 	(void) signal(SIGALRM, nologinproc);
118638905Sborman 	for (i = 0; ; i++) {
118740242Sborman 		char tbuf[128];
118838905Sborman 		alarm(15);
118938905Sborman 		n = read(pty, ptyip, BUFSIZ);
119038905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
119138905Sborman 			break;
119238905Sborman 		gotalarm = 0;
119340242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
119440242Sborman 		(void) write(net, tbuf, strlen(tbuf));
119538905Sborman 	}
119638905Sborman 	if (n < 0 && gotalarm)
119738905Sborman 		fatal(net, "/etc/init didn't start login process");
119838905Sborman 	pcc += n;
119938905Sborman 	alarm(0);
120038905Sborman 	(void) signal(SIGALRM, SIG_DFL);
120138905Sborman 
120238905Sborman 	return;
120338905Sborman #endif	/* NEWINIT */
120438905Sborman }
120538905Sborman 
120638905Sborman char	*envinit[3];
120744364Sborman extern char **environ;
120838905Sborman 
120946809Sdab 	void
121044364Sborman init_env()
121144364Sborman {
121244364Sborman 	extern char *getenv();
121344364Sborman 	char **envp;
121444364Sborman 
121544364Sborman 	envp = envinit;
121644364Sborman 	if (*envp = getenv("TZ"))
121744364Sborman 		*envp++ -= 3;
121844364Sborman #ifdef	CRAY
121944364Sborman 	else
122044364Sborman 		*envp++ = "TZ=GMT0";
122144364Sborman #endif
122244364Sborman 	*envp = 0;
122344364Sborman 	environ = envinit;
122444364Sborman }
122544364Sborman 
122644364Sborman #ifndef	NEWINIT
122744364Sborman 
122844364Sborman /*
122945234Sborman  * start_login(host)
123038905Sborman  *
123138905Sborman  * Assuming that we are now running as a child processes, this
123238905Sborman  * function will turn us into the login process.
123338905Sborman  */
123438905Sborman 
123546809Sdab 	void
123646809Sdab start_login(host, autologin, name)
123746809Sdab 	char *host;
123846809Sdab 	int autologin;
123946809Sdab 	char *name;
124038905Sborman {
124144364Sborman 	register char *cp;
124244364Sborman 	register char **argv;
124344364Sborman 	char **addarg();
124438905Sborman 
124538905Sborman 	/*
124638905Sborman 	 * -h : pass on name of host.
124738905Sborman 	 *		WARNING:  -h is accepted by login if and only if
124838905Sborman 	 *			getuid() == 0.
124938905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
125046809Sdab 	 *
125146809Sdab 	 * -f : force this login, he has already been authenticated
125238905Sborman 	 */
125344364Sborman 	argv = addarg(0, "login");
125444364Sborman 	argv = addarg(argv, "-h");
125544364Sborman 	argv = addarg(argv, host);
125646809Sdab #if	!defined(NO_LOGIN_P)
125744364Sborman 	argv = addarg(argv, "-p");
125838905Sborman #endif
125944364Sborman #ifdef	BFTPDAEMON
126044364Sborman 	/*
126144364Sborman 	 * Are we working as the bftp daemon?  If so, then ask login
126244364Sborman 	 * to start bftp instead of shell.
126344364Sborman 	 */
126444364Sborman 	if (bftpd) {
126544364Sborman 		argv = addarg(argv, "-e");
126644364Sborman 		argv = addarg(argv, BFTPPATH);
126744364Sborman 	} else
126844364Sborman #endif
126946809Sdab #if	defined (SecurID)
127046809Sdab 	/*
127146809Sdab 	 * don't worry about the -f that might get sent.
127246809Sdab 	 * A -s is supposed to override it anyhow.
127346809Sdab 	 */
127446809Sdab 	if (require_SecurID)
127546809Sdab 		argv = addarg(argv, "-s");
127646809Sdab #endif
127746809Sdab #if	defined (AUTHENTICATE)
127846809Sdab 	if (auth_level >= 0 && autologin == AUTH_VALID) {
127946809Sdab # if	!defined(NO_LOGIN_F)
128046809Sdab 		argv = addarg(argv, "-f");
128146809Sdab # endif
128246809Sdab 		argv = addarg(argv, name);
128346809Sdab 	} else
128446809Sdab #endif
128544364Sborman 	if (getenv("USER")) {
128644364Sborman 		argv = addarg(argv, getenv("USER"));
128746809Sdab #if	defined(CRAY) && defined(NO_LOGIN_P)
128846809Sdab 		{
128946809Sdab 			register char **cpp;
129046809Sdab 			for (cpp = environ; *cpp; cpp++)
129146809Sdab 				argv = addarg(argv, *cpp);
129246809Sdab 		}
129346809Sdab #endif
129444364Sborman 	}
129546809Sdab 	closelog();
129644364Sborman 	execv(_PATH_LOGIN, argv);
129744364Sborman 
129838905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
129938905Sborman 	fatalperror(net, _PATH_LOGIN);
130038905Sborman 	/*NOTREACHED*/
130138905Sborman }
130244364Sborman 
130346809Sdab 	char **
130444364Sborman addarg(argv, val)
130546809Sdab 	register char **argv;
130646809Sdab 	register char *val;
130744364Sborman {
130844364Sborman 	register char **cpp;
130944364Sborman 
131044364Sborman 	if (argv == NULL) {
131144364Sborman 		/*
131244364Sborman 		 * 10 entries, a leading length, and a null
131344364Sborman 		 */
131444364Sborman 		argv = (char **)malloc(sizeof(*argv) * 12);
131544364Sborman 		if (argv == NULL)
131644364Sborman 			return(NULL);
131744364Sborman 		*argv++ = (char *)10;
131844364Sborman 		*argv = (char *)0;
131944364Sborman 	}
132044364Sborman 	for (cpp = argv; *cpp; cpp++)
132144364Sborman 		;
132244364Sborman 	if (cpp == &argv[(int)argv[-1]]) {
132344364Sborman 		--argv;
132444364Sborman 		*argv = (char *)((int)(*argv) + 10);
132544364Sborman 		argv = (char **)realloc(argv, (int)(*argv) + 2);
132644364Sborman 		if (argv == NULL)
132744364Sborman 			return(NULL);
132844364Sborman 		argv++;
132944364Sborman 		cpp = &argv[(int)argv[-1] - 10];
133044364Sborman 	}
133144364Sborman 	*cpp++ = val;
133244364Sborman 	*cpp = 0;
133344364Sborman 	return(argv);
133444364Sborman }
133546809Sdab #endif	/* NEWINIT */
133638905Sborman 
133738905Sborman /*
133838905Sborman  * cleanup()
133938905Sborman  *
134038905Sborman  * This is the routine to call when we are all through, to
134138905Sborman  * clean up anything that needs to be cleaned up.
134238905Sborman  */
134346809Sdab 	/* ARGSUSED */
134446809Sdab 	void
134546809Sdab cleanup(sig)
134646809Sdab 	int sig;
134738905Sborman {
134838905Sborman #ifndef	CRAY
134945234Sborman # if (BSD > 43) || defined(convex)
135038905Sborman 	char *p;
135138905Sborman 
135238905Sborman 	p = line + sizeof("/dev/") - 1;
135338905Sborman 	if (logout(p))
135438905Sborman 		logwtmp(p, "", "");
135538905Sborman 	(void)chmod(line, 0666);
135638905Sborman 	(void)chown(line, 0, 0);
135738905Sborman 	*p = 'p';
135838905Sborman 	(void)chmod(line, 0666);
135938905Sborman 	(void)chown(line, 0, 0);
136046809Sdab 	(void) shutdown(net, 2);
136146809Sdab 	exit(1);
136238905Sborman # else
136346809Sdab 	void rmut();
136446809Sdab 
136538905Sborman 	rmut();
136638905Sborman 	vhangup();	/* XXX */
136746809Sdab 	(void) shutdown(net, 2);
136846809Sdab 	exit(1);
136938905Sborman # endif
137038905Sborman #else	/* CRAY */
137146809Sdab # ifdef	NEWINIT
137238905Sborman 	(void) shutdown(net, 2);
137346809Sdab 	exit(1);
137438905Sborman # else	/* NEWINIT */
137546809Sdab 	static int incleanup = 0;
137646809Sdab 	register int t;
137746809Sdab 
137846809Sdab 	/*
137946809Sdab 	 * 1: Pick up the zombie, if we are being called
138046809Sdab 	 *    as the signal handler.
138146809Sdab 	 * 2: If we are a nested cleanup(), return.
138246809Sdab 	 * 3: Try to clean up TMPDIR.
138346809Sdab 	 * 4: Fill in utmp with shutdown of process.
138446809Sdab 	 * 5: Close down the network and pty connections.
138546809Sdab 	 * 6: Finish up the TMPDIR cleanup, if needed.
138646809Sdab 	 */
138746809Sdab 	if (sig == SIGCHLD)
138846809Sdab 		while (waitpid(-1, 0, WNOHANG) > 0)
138946809Sdab 			;	/* VOID */
139046809Sdab 	t = sigblock(sigmask(SIGCHLD));
139146809Sdab 	if (incleanup) {
139246809Sdab 		sigsetmask(t);
139346809Sdab 		return;
139446809Sdab 	}
139546809Sdab 	incleanup = 1;
139646809Sdab 	sigsetmask(t);
139746809Sdab 
139846809Sdab 	t = cleantmp(&wtmp);
139946809Sdab 	setutent();	/* just to make sure */
140046809Sdab 	rmut(line);
140146809Sdab 	close(pty);
140238905Sborman 	(void) shutdown(net, 2);
140346809Sdab 	if (t == 0)
140446809Sdab 		cleantmp(&wtmp);
140546809Sdab 	exit(1);
140638905Sborman # endif	/* NEWINT */
140738905Sborman #endif	/* CRAY */
140838905Sborman }
140938905Sborman 
141038905Sborman #if	defined(CRAY) && !defined(NEWINIT)
141138905Sborman /*
141238905Sborman  * _utmp_sig_rcv
141338905Sborman  * utmp_sig_init
141438905Sborman  * utmp_sig_wait
141538905Sborman  *	These three functions are used to coordinate the handling of
141638905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
141738905Sborman  *	The server actually creates the utmp structure, the child calls
141838905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
141938905Sborman  *	signals the future-login shell to proceed.
142038905Sborman  */
142138905Sborman static int caught=0;		/* NZ when signal intercepted */
142238905Sborman static void (*func)();		/* address of previous handler */
142338905Sborman 
142446809Sdab 	void
142538905Sborman _utmp_sig_rcv(sig)
142646809Sdab 	int sig;
142738905Sborman {
142838905Sborman 	caught = 1;
142938905Sborman 	(void) signal(SIGUSR1, func);
143038905Sborman }
143138905Sborman 
143246809Sdab 	void
143338905Sborman utmp_sig_init()
143438905Sborman {
143538905Sborman 	/*
143638905Sborman 	 * register signal handler for UTMP creation
143738905Sborman 	 */
143838905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
143938905Sborman 		fatalperror(net, "telnetd/signal");
144038905Sborman }
144138905Sborman 
144246809Sdab 	void
144344364Sborman utmp_sig_reset()
144444364Sborman {
144544364Sborman 	(void) signal(SIGUSR1, func);	/* reset handler to default */
144644364Sborman }
144744364Sborman 
144846809Sdab 	void
144938905Sborman utmp_sig_wait()
145038905Sborman {
145138905Sborman 	/*
145238905Sborman 	 * Wait for parent to write our utmp entry.
145338905Sborman 	 */
145438905Sborman 	sigoff();
145538905Sborman 	while (caught == 0) {
145638905Sborman 		pause();	/* wait until we get a signal (sigon) */
145738905Sborman 		sigoff();	/* turn off signals while we check caught */
145838905Sborman 	}
145938905Sborman 	sigon();		/* turn on signals again */
146038905Sborman }
146138905Sborman 
146246809Sdab 	void
146338905Sborman utmp_sig_notify(pid)
146438905Sborman {
146538905Sborman 	kill(pid, SIGUSR1);
146638905Sborman }
146746809Sdab 
146846809Sdab static int gotsigjob = 0;
146946809Sdab 
147046809Sdab 	/*ARGSUSED*/
147146809Sdab 	void
147246809Sdab sigjob(sig)
147346809Sdab 	int sig;
147446809Sdab {
147546809Sdab 	register int jid;
147646809Sdab 	register struct jobtemp *jp;
147746809Sdab 
147846809Sdab 	while ((jid = waitjob(NULL)) != -1) {
147946809Sdab 		if (jid == 0) {
148046809Sdab 			return;
148146809Sdab 		}
148246809Sdab 		gotsigjob++;
148346809Sdab 		jobend(jid, NULL, NULL);
148446809Sdab 	}
148546809Sdab }
148646809Sdab 
148746809Sdab /*
148846809Sdab  * Clean up the TMPDIR that login created.
148946809Sdab  * The first time this is called we pick up the info
149046809Sdab  * from the utmp.  If the job has already gone away,
149146809Sdab  * then we'll clean up and be done.  If not, then
149246809Sdab  * when this is called the second time it will wait
149346809Sdab  * for the signal that the job is done.
149446809Sdab  */
149546809Sdab 	int
149646809Sdab cleantmp(wtp)
149746809Sdab 	register struct utmp *wtp;
149846809Sdab {
149946809Sdab 	struct utmp *utp;
150046809Sdab 	static int first = 1;
150146809Sdab 	register int mask, omask, ret;
150246809Sdab 	extern struct utmp *getutid P((struct utmp *));
150346809Sdab 
150446809Sdab 	mask = sigmask(WJSIGNAL);
150546809Sdab 
150646809Sdab 	if (first == 0) {
150746809Sdab 		omask = sigblock(mask);
150846809Sdab 		while (gotsigjob == 0)
150946809Sdab 			sigpause(omask);
151046809Sdab 		return(1);
151146809Sdab 	}
151246809Sdab 	first = 0;
151346809Sdab 	setutent();	/* just to make sure */
151446809Sdab 
151546809Sdab 	utp = getutid(wtp);
151646809Sdab 	if (utp == 0) {
151746809Sdab 		syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
151846809Sdab 		return(-1);
151946809Sdab 	}
152046809Sdab 	/*
152146809Sdab 	 * Nothing to clean up if the user shell was never started.
152246809Sdab 	 */
152346809Sdab 	if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
152446809Sdab 		return(1);
152546809Sdab 
152646809Sdab 	/*
152746809Sdab 	 * Block the WJSIGNAL while we are in jobend().
152846809Sdab 	 */
152946809Sdab 	omask = sigblock(mask);
153046809Sdab 	ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
153146809Sdab 	sigsetmask(omask);
153246809Sdab 	return(ret);
153346809Sdab }
153446809Sdab 
153546809Sdab 	int
153646809Sdab jobend(jid, path, user)
153746809Sdab 	register int jid;
153846809Sdab 	register char *path;
153946809Sdab 	register char *user;
154046809Sdab {
154146809Sdab 	static int saved_jid = 0;
154246809Sdab 	static char saved_path[sizeof(wtmp.ut_tpath)+1];
154346809Sdab 	static char saved_user[sizeof(wtmp.ut_user)+1];
154446809Sdab 
154546809Sdab 	if (path) {
154646809Sdab 		strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
154746809Sdab 		strncpy(saved_user, user, sizeof(wtmp.ut_user));
154846809Sdab 		saved_path[sizeof(saved_path)] = '\0';
154946809Sdab 		saved_user[sizeof(saved_user)] = '\0';
155046809Sdab 	}
155146809Sdab 	if (saved_jid == 0) {
155246809Sdab 		saved_jid = jid;
155346809Sdab 		return(0);
155446809Sdab 	}
155546809Sdab 	cleantmpdir(jid, saved_path, saved_user);
155646809Sdab 	return(1);
155746809Sdab }
155846809Sdab 
155946809Sdab /*
156046809Sdab  * Fork a child process to clean up the TMPDIR
156146809Sdab  */
156246809Sdab cleantmpdir(jid, tpath, user)
156346809Sdab 	register int jid;
156446809Sdab 	register char *tpath;
156546809Sdab 	register char *user;
156646809Sdab {
156746809Sdab 	switch(fork()) {
156846809Sdab 	case -1:
156946809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
157046809Sdab 							tpath);
157146809Sdab 		break;
157246809Sdab 	case 0:
157346809Sdab 		execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
157446809Sdab 		syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
157546809Sdab 							tpath, CLEANTMPCMD);
157646809Sdab 		exit(1);
157746809Sdab 	default:
157846809Sdab 		/*
157946809Sdab 		 * Forget about child.  We will exit, and
158046809Sdab 		 * /etc/init will pick it up.
158146809Sdab 		 */
158246809Sdab 		break;
158346809Sdab 	}
158446809Sdab }
158538905Sborman #endif	/* defined(CRAY) && !defined(NEWINIT) */
158638905Sborman 
158738905Sborman /*
158838905Sborman  * rmut()
158938905Sborman  *
159038905Sborman  * This is the function called by cleanup() to
159138905Sborman  * remove the utmp entry for this person.
159238905Sborman  */
159338905Sborman 
159438905Sborman #if	!defined(CRAY) && BSD <= 43
159546809Sdab 	void
159638905Sborman rmut()
159738905Sborman {
159838905Sborman 	register f;
159938905Sborman 	int found = 0;
160038905Sborman 	struct utmp *u, *utmp;
160138905Sborman 	int nutmp;
160238905Sborman 	struct stat statbf;
160338905Sborman 
160438905Sborman 	f = open(utmpf, O_RDWR);
160538905Sborman 	if (f >= 0) {
160638905Sborman 		(void) fstat(f, &statbf);
160738905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
160838905Sborman 		if (!utmp)
160938905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
161038905Sborman 		if (statbf.st_size && utmp) {
161138905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
161238905Sborman 			nutmp /= sizeof(struct utmp);
161338905Sborman 
161438905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
161538905Sborman 				if (SCMPN(u->ut_line, line+5) ||
161638905Sborman 				    u->ut_name[0]==0)
161738905Sborman 					continue;
161838905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
161938905Sborman 				SCPYN(u->ut_name, "");
162038905Sborman 				SCPYN(u->ut_host, "");
162138905Sborman 				(void) time(&u->ut_time);
162238905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
162338905Sborman 				found++;
162438905Sborman 			}
162538905Sborman 		}
162638905Sborman 		(void) close(f);
162738905Sborman 	}
162838905Sborman 	if (found) {
162938905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
163038905Sborman 		if (f >= 0) {
163138905Sborman 			SCPYN(wtmp.ut_line, line+5);
163238905Sborman 			SCPYN(wtmp.ut_name, "");
163338905Sborman 			SCPYN(wtmp.ut_host, "");
163438905Sborman 			(void) time(&wtmp.ut_time);
163538905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
163638905Sborman 			(void) close(f);
163738905Sborman 		}
163838905Sborman 	}
163938905Sborman 	(void) chmod(line, 0666);
164038905Sborman 	(void) chown(line, 0, 0);
164138905Sborman 	line[strlen("/dev/")] = 'p';
164238905Sborman 	(void) chmod(line, 0666);
164338905Sborman 	(void) chown(line, 0, 0);
164438905Sborman }  /* end of rmut */
164538905Sborman #endif	/* CRAY */
1646