xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 42673)
138905Sborman /*
238905Sborman  * Copyright (c) 1989 Regents of the University of California.
338905Sborman  * All rights reserved.
438905Sborman  *
5*42673Sbostic  * %sccs.include.redist.c%
638905Sborman  */
738905Sborman 
838905Sborman #ifndef lint
9*42673Sbostic static char sccsid[] = "@(#)sys_term.c	5.6 (Berkeley) 06/01/90";
1038905Sborman #endif /* not lint */
1138905Sborman 
1238905Sborman #include "telnetd.h"
1338905Sborman #include "pathnames.h"
1438905Sborman 
1538905Sborman #ifdef	NEWINIT
1638905Sborman #include <initreq.h>
1738905Sborman #else	/* NEWINIT*/
1838905Sborman #include <utmp.h>
1938905Sborman struct	utmp wtmp;
2038905Sborman 
2138905Sborman # ifndef CRAY
2238905Sborman char	wtmpf[]	= "/usr/adm/wtmp";
2338905Sborman char	utmpf[] = "/etc/utmp";
2438905Sborman # else	/* CRAY */
2538905Sborman char	wtmpf[]	= "/etc/wtmp";
2638905Sborman # endif	/* CRAY */
2738905Sborman #endif	/* NEWINIT */
2838905Sborman 
2938905Sborman #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
3038905Sborman #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
3138905Sborman 
3238905Sborman #include <sys/tty.h>
3338905Sborman #ifdef	t_erase
3438905Sborman #undef	t_erase
3538905Sborman #undef	t_kill
3638905Sborman #undef	t_intrc
3738905Sborman #undef	t_quitc
3838905Sborman #undef	t_startc
3938905Sborman #undef	t_stopc
4038905Sborman #undef	t_eofc
4138905Sborman #undef	t_brkc
4238905Sborman #undef	t_suspc
4338905Sborman #undef	t_dsuspc
4438905Sborman #undef	t_rprntc
4538905Sborman #undef	t_flushc
4638905Sborman #undef	t_werasc
4738905Sborman #undef	t_lnextc
4838905Sborman #endif
4938905Sborman 
5038905Sborman #ifndef	USE_TERMIO
5138905Sborman struct termbuf {
5238905Sborman 	struct sgttyb sg;
5338905Sborman 	struct tchars tc;
5438905Sborman 	struct ltchars ltc;
5538905Sborman 	int state;
5638905Sborman 	int lflags;
5738905Sborman } termbuf, termbuf2;
5838905Sborman #else	/* USE_TERMIO */
5938905Sborman # ifndef EXTPROC
6038905Sborman # define EXTPROC 0400
6138905Sborman # endif
6238905Sborman # ifdef	SYSV_TERMIO
6338905Sborman #	define termios termio
6438905Sborman # endif
6539974Ssklower # ifndef TCSETA
6639974Ssklower # define TCSETA TIOCSETA
6739974Ssklower # define TCGETA TIOCGETA
6839974Ssklower # endif /* 4.4BSD */
6938905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
7038905Sborman #endif	/* USE_TERMIO */
7138905Sborman 
7238905Sborman /*
7338905Sborman  * init_termbuf()
7438905Sborman  * copy_termbuf(cp)
7538905Sborman  * set_termbuf()
7638905Sborman  *
7738905Sborman  * These three routines are used to get and set the "termbuf" structure
7838905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
7938905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
8038905Sborman  * set_termbuf() writes the structure into the kernel.
8138905Sborman  */
8238905Sborman 
8338905Sborman init_termbuf()
8438905Sborman {
8538905Sborman #ifndef	USE_TERMIO
8638905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
8738905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
8838905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
8938905Sborman # ifdef	TIOCGSTATE
9038905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
9138905Sborman # endif
9238905Sborman #else
9338905Sborman 	(void) ioctl(pty, TCGETA, (char *)&termbuf);
9438905Sborman #endif
9538905Sborman 	termbuf2 = termbuf;
9638905Sborman }
9738905Sborman 
9838905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
9938905Sborman copy_termbuf(cp, len)
10038905Sborman char *cp;
10138905Sborman int len;
10238905Sborman {
10338905Sborman 	if (len > sizeof(termbuf))
10438905Sborman 		len = sizeof(termbuf);
10538905Sborman 	bcopy(cp, (char *)&termbuf, len);
10638905Sborman 	termbuf2 = termbuf;
10738905Sborman }
10838905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
10938905Sborman 
11038905Sborman set_termbuf()
11138905Sborman {
11238905Sborman 	/*
11338905Sborman 	 * Only make the necessary changes.
11438905Sborman 	 */
11538905Sborman #ifndef	USE_TERMIO
11638905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
11738905Sborman 		(void) ioctl(pty, TIOCSETP, (char *)&termbuf.sg);
11838905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
11938905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
12038905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
12138905Sborman 							sizeof(termbuf.ltc)))
12238905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
12338905Sborman 	if (termbuf.lflags != termbuf2.lflags)
12438905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
12538905Sborman #else	/* USE_TERMIO */
12638905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
12738905Sborman 		(void) ioctl(pty, TCSETA, (char *)&termbuf);
12840242Sborman # if	defined(CRAY2) && defined(UNCIOS5)
12938905Sborman 	needtermstat = 1;
13038905Sborman # endif
13138905Sborman #endif	/* USE_TERMIO */
13238905Sborman }
13338905Sborman 
13438905Sborman 
13538905Sborman /*
13638905Sborman  * spcset(func, valp, valpp)
13738905Sborman  *
13838905Sborman  * This function takes various special characters (func), and
13938905Sborman  * sets *valp to the current value of that character, and
14038905Sborman  * *valpp to point to where in the "termbuf" structure that
14138905Sborman  * value is kept.
14238905Sborman  *
14338905Sborman  * It returns the SLC_ level of support for this function.
14438905Sborman  */
14538905Sborman 
14638905Sborman #ifndef	USE_TERMIO
14738905Sborman spcset(func, valp, valpp)
14838905Sborman int func;
14940242Sborman cc_t *valp;
15040242Sborman cc_t **valpp;
15138905Sborman {
15238905Sborman 	switch(func) {
15338905Sborman 	case SLC_EOF:
15438905Sborman 		*valp = termbuf.tc.t_eofc;
15540242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
15638905Sborman 		return(SLC_VARIABLE);
15738905Sborman 	case SLC_EC:
15838905Sborman 		*valp = termbuf.sg.sg_erase;
15940242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
16038905Sborman 		return(SLC_VARIABLE);
16138905Sborman 	case SLC_EL:
16238905Sborman 		*valp = termbuf.sg.sg_kill;
16340242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
16438905Sborman 		return(SLC_VARIABLE);
16538905Sborman 	case SLC_IP:
16638905Sborman 		*valp = termbuf.tc.t_intrc;
16740242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
16838905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
16938905Sborman 	case SLC_ABORT:
17038905Sborman 		*valp = termbuf.tc.t_quitc;
17140242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
17238905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
17338905Sborman 	case SLC_XON:
17438905Sborman 		*valp = termbuf.tc.t_startc;
17540242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
17638905Sborman 		return(SLC_VARIABLE);
17738905Sborman 	case SLC_XOFF:
17838905Sborman 		*valp = termbuf.tc.t_stopc;
17940242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
18038905Sborman 		return(SLC_VARIABLE);
18138905Sborman 	case SLC_AO:
18238905Sborman 		*valp = termbuf.ltc.t_flushc;
18340242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
18438905Sborman 		return(SLC_VARIABLE);
18538905Sborman 	case SLC_SUSP:
18638905Sborman 		*valp = termbuf.ltc.t_suspc;
18740242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
18838905Sborman 		return(SLC_VARIABLE);
18938905Sborman 	case SLC_EW:
19038905Sborman 		*valp = termbuf.ltc.t_werasc;
19140242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
19238905Sborman 		return(SLC_VARIABLE);
19338905Sborman 	case SLC_RP:
19438905Sborman 		*valp = termbuf.ltc.t_rprntc;
19540242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
19638905Sborman 		return(SLC_VARIABLE);
19738905Sborman 	case SLC_LNEXT:
19838905Sborman 		*valp = termbuf.ltc.t_lnextc;
19940242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
20038905Sborman 		return(SLC_VARIABLE);
20140242Sborman 	case SLC_FORW1:
20240242Sborman 		*valp = termbuf.tc.t_brkc;
20340242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
20440242Sborman 		return(SLC_VARIABLE);
20538905Sborman 	case SLC_BRK:
20638905Sborman 	case SLC_SYNCH:
20738905Sborman 	case SLC_AYT:
20838905Sborman 	case SLC_EOR:
20940242Sborman 		*valp = (cc_t)0;
21040242Sborman 		*valpp = (cc_t *)0;
21138905Sborman 		return(SLC_DEFAULT);
21238905Sborman 	default:
21340242Sborman 		*valp = (cc_t)0;
21440242Sborman 		*valpp = (cc_t *)0;
21538905Sborman 		return(SLC_NOSUPPORT);
21638905Sborman 	}
21738905Sborman }
21838905Sborman 
21938905Sborman #else	/* USE_TERMIO */
22038905Sborman 
22138905Sborman spcset(func, valp, valpp)
22238905Sborman int func;
22340242Sborman cc_t *valp;
22440242Sborman cc_t **valpp;
22538905Sborman {
22639503Sborman 
22739503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
22839503Sborman 			*valpp = &termbuf.c_cc[a]; \
22939503Sborman 			return(b);
23040242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
23139503Sborman 
23238905Sborman 	switch(func) {
23338905Sborman 	case SLC_EOF:
23439503Sborman 		setval(VEOF, SLC_VARIABLE);
23538905Sborman 	case SLC_EC:
23639503Sborman 		setval(VERASE, SLC_VARIABLE);
23738905Sborman 	case SLC_EL:
23839503Sborman 		setval(VKILL, SLC_VARIABLE);
23938905Sborman 	case SLC_IP:
24039503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
24138905Sborman 	case SLC_ABORT:
24239503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
24338905Sborman 	case SLC_XON:
24439503Sborman #ifdef	VSTART
24539503Sborman 		setval(VSTART, SLC_VARIABLE);
24639503Sborman #else
24739503Sborman 		defval(0x13);
24839503Sborman #endif
24938905Sborman 	case SLC_XOFF:
25039503Sborman #ifdef	VSTOP
25139503Sborman 		setval(VSTOP, SLC_VARIABLE);
25239503Sborman #else
25339503Sborman 		defval(0x11);
25439503Sborman #endif
25538905Sborman 	case SLC_EW:
25639503Sborman #ifdef	VWERASE
25739503Sborman 		setval(VWERASE, SLC_VARIABLE);
25839503Sborman #else
25939503Sborman 		defval(0);
26039503Sborman #endif
26138905Sborman 	case SLC_RP:
26239503Sborman #ifdef	VREPRINT
26339503Sborman 		setval(VREPRINT, SLC_VARIABLE);
26439503Sborman #else
26539503Sborman 		defval(0);
26639503Sborman #endif
26738905Sborman 	case SLC_LNEXT:
26839503Sborman #ifdef	VLNEXT
26939503Sborman 		setval(VLNEXT, SLC_VARIABLE);
27039503Sborman #else
27139503Sborman 		defval(0);
27239503Sborman #endif
27339503Sborman 	case SLC_AO:
27439503Sborman #ifdef	VFLUSHO
27539503Sborman 		setval(VFLUSHO, SLC_VARIABLE|SLC_FLUSHOUT);
27639503Sborman #else
27739503Sborman 		defval(0);
27839503Sborman #endif
27939503Sborman 	case SLC_SUSP:
28039503Sborman #ifdef	VSUSP
28139503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
28239503Sborman #else
28339503Sborman 		defval(0);
28439503Sborman #endif
28540242Sborman #ifdef	VEOL
28640242Sborman 	case SLC_FORW1:
28740242Sborman 		setval(VEOL, SLC_VARIABLE);
28840242Sborman #endif
28940242Sborman #ifdef	VEOL2
29040242Sborman 	case SLC_FORW2:
29140242Sborman 		setval(VEOL2, SLC_VARIABLE);
29240242Sborman #endif
29339503Sborman 
29438905Sborman 	case SLC_BRK:
29538905Sborman 	case SLC_SYNCH:
29638905Sborman 	case SLC_AYT:
29738905Sborman 	case SLC_EOR:
29839503Sborman 		defval(0);
29939503Sborman 
30038905Sborman 	default:
30138905Sborman 		*valp = 0;
30238905Sborman 		*valpp = 0;
30338905Sborman 		return(SLC_NOSUPPORT);
30438905Sborman 	}
30538905Sborman }
30638905Sborman #endif	/* USE_TERMIO */
30738905Sborman 
30840242Sborman #ifdef CRAY
30938905Sborman /*
31040242Sborman  * getnpty()
31140242Sborman  *
31240242Sborman  * Return the number of pty's configured into the system.
31340242Sborman  */
31440242Sborman getnpty()
31540242Sborman {
31640242Sborman #ifdef _SC_CRAY_NPTY
31740242Sborman 	return sysconf(_SC_CRAY_NPTY);
31840242Sborman #else
31940242Sborman 	return 128;
32040242Sborman #endif /* _SC_CRAY_NPTY */
32140242Sborman }
32240242Sborman #endif /* CRAY */
32340242Sborman 
32440242Sborman /*
32538905Sborman  * getpty()
32638905Sborman  *
32738905Sborman  * Allocate a pty.  As a side effect, the external character
32838905Sborman  * array "line" contains the name of the slave side.
32938905Sborman  *
33038905Sborman  * Returns the file descriptor of the opened pty.
33138905Sborman  */
33238905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
33338905Sborman 
33438905Sborman getpty()
33538905Sborman {
33638905Sborman 	register int p;
33738905Sborman #ifndef CRAY
33838905Sborman 	register char c, *p1, *p2;
33938905Sborman 	register int i;
34038905Sborman 
34138905Sborman 	(void) sprintf(line, "/dev/ptyXX");
34238905Sborman 	p1 = &line[8];
34338905Sborman 	p2 = &line[9];
34438905Sborman 
34538905Sborman 	for (c = 'p'; c <= 's'; c++) {
34638905Sborman 		struct stat stb;
34738905Sborman 
34838905Sborman 		*p1 = c;
34938905Sborman 		*p2 = '0';
35038905Sborman 		if (stat(line, &stb) < 0)
35138905Sborman 			break;
35238905Sborman 		for (i = 0; i < 16; i++) {
35338905Sborman 			*p2 = "0123456789abcdef"[i];
35438905Sborman 			p = open(line, 2);
35538905Sborman 			if (p > 0) {
35638905Sborman 				line[5] = 't';
35738905Sborman 				return(p);
35838905Sborman 			}
35938905Sborman 		}
36038905Sborman 	}
36138905Sborman #else	/* CRAY */
36238905Sborman 	register int npty;
36338905Sborman 	extern lowpty, highpty;
36438905Sborman 
36538905Sborman 	for (npty = lowpty; npty <= highpty; npty++) {
36638905Sborman 		(void) sprintf(line, "/dev/pty/%03d", npty);
36738905Sborman 		p = open(line, 2);
36838905Sborman 		if (p < 0)
36938905Sborman 			continue;
37038905Sborman 		(void) sprintf(line, "/dev/ttyp%03d", npty);
37138905Sborman 		if (access(line, 6) == 0)
37238905Sborman 			return(p);
37338905Sborman 		else {
37438905Sborman 			/* no tty side to pty so skip it */
37538905Sborman 			(void) close(p);
37638905Sborman 		}
37738905Sborman 	}
37838905Sborman #endif	/* CRAY */
37938905Sborman 	return(-1);
38038905Sborman }
38138905Sborman 
38238905Sborman #ifdef	LINEMODE
38338905Sborman /*
38438905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
38538905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
38638905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
38738905Sborman  * tty_isecho()		Find out if echoing is turned on.
38838905Sborman  * tty_setecho(on)	Enable/disable character echoing.
38938905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
39038905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
39138905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
39238905Sborman  * tty_isediting()	Find out if line editing is enabled.
39338905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
39438905Sborman  * tty_setedit(on)	Turn on/off line editing.
39538905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
39638905Sborman  * tty_tspeed(val)	Set transmit speed to val.
39738905Sborman  * tty_rspeed(val)	Set receive speed to val.
39838905Sborman  */
39938905Sborman 
40038905Sborman tty_flowmode()
40138905Sborman {
40238905Sborman #ifndef USE_TERMIO
40338905Sborman 	return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0);
40438905Sborman #else
40538905Sborman 	return(termbuf.c_iflag & IXON ? 1 : 0);
40638905Sborman #endif
40738905Sborman }
40838905Sborman 
40938905Sborman tty_linemode()
41038905Sborman {
41138905Sborman #ifndef	USE_TERMIO
41238905Sborman 	return(termbuf.state & TS_EXTPROC);
41338905Sborman #else
41438905Sborman 	return(termbuf.c_lflag & EXTPROC);
41538905Sborman #endif
41638905Sborman }
41738905Sborman 
41838905Sborman tty_setlinemode(on)
41938905Sborman int on;
42038905Sborman {
42138905Sborman #ifdef	TIOCEXT
42238905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
42338905Sborman #else	/* !TIOCEXT */
42438905Sborman #ifdef	EXTPROC
42538905Sborman 	if (on)
42638905Sborman 		termbuf.c_lflag |= EXTPROC;
42738905Sborman 	else
42838905Sborman 		termbuf.c_lflag &= ~EXTPROC;
42938905Sborman #endif
43038905Sborman 	set_termbuf();
43138905Sborman #endif	/* TIOCEXT */
43238905Sborman }
43338905Sborman 
43438905Sborman tty_isecho()
43538905Sborman {
43638905Sborman #ifndef USE_TERMIO
43738905Sborman 	return (termbuf.sg.sg_flags & ECHO);
43838905Sborman #else
43938905Sborman 	return (termbuf.c_lflag & ECHO);
44038905Sborman #endif
44138905Sborman }
44238905Sborman #endif	/* LINEMODE */
44338905Sborman 
44438905Sborman tty_setecho(on)
44538905Sborman {
44638905Sborman #ifndef	USE_TERMIO
44738905Sborman 	if (on)
44838905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
44938905Sborman 	else
45038905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
45138905Sborman #else
45238905Sborman 	if (on)
45338905Sborman 		termbuf.c_lflag |= ECHO;
45438905Sborman 	else
45538905Sborman 		termbuf.c_lflag &= ~ECHO;
45638905Sborman #endif
45738905Sborman }
45838905Sborman 
45938905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
46038905Sborman tty_israw()
46138905Sborman {
46238905Sborman #ifndef USE_TERMIO
46338905Sborman 	return(termbuf.sg.sg_flags & RAW);
46438905Sborman #else
46538905Sborman 	return(!(termbuf.c_lflag & ICANON));
46638905Sborman #endif
46738905Sborman }
46838905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
46938905Sborman 
47038905Sborman tty_binaryin(on)
47138905Sborman {
47238905Sborman #ifndef	USE_TERMIO
47338905Sborman 	if (on)
47438905Sborman 		termbuf.lflags |= LPASS8;
47538905Sborman 	else
47638905Sborman 		termbuf.lflags &= ~LPASS8;
47738905Sborman #else
47838905Sborman 	if (on) {
47938905Sborman 		termbuf.c_lflag &= ~ISTRIP;
48038905Sborman 	} else {
48138905Sborman 		termbuf.c_lflag |= ISTRIP;
48238905Sborman 	}
48338905Sborman #endif
48438905Sborman }
48538905Sborman 
48638905Sborman tty_binaryout(on)
48738905Sborman {
48838905Sborman #ifndef	USE_TERMIO
48938905Sborman 	if (on)
49038905Sborman 		termbuf.lflags |= LLITOUT;
49138905Sborman 	else
49238905Sborman 		termbuf.lflags &= ~LLITOUT;
49338905Sborman #else
49438905Sborman 	if (on) {
49538905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
49638905Sborman 		termbuf.c_cflag |= CS8;
49738905Sborman 		termbuf.c_oflag &= ~OPOST;
49838905Sborman 	} else {
49938905Sborman 		termbuf.c_cflag &= ~CSIZE;
50038905Sborman 		termbuf.c_cflag |= CS7|PARENB;
50138905Sborman 		termbuf.c_oflag |= OPOST;
50238905Sborman 	}
50338905Sborman #endif
50438905Sborman }
50538905Sborman 
50638905Sborman tty_isbinaryin()
50738905Sborman {
50838905Sborman #ifndef	USE_TERMIO
50938905Sborman 	return(termbuf.lflags & LPASS8);
51038905Sborman #else
51139503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
51238905Sborman #endif
51338905Sborman }
51438905Sborman 
51538905Sborman tty_isbinaryout()
51638905Sborman {
51738905Sborman #ifndef	USE_TERMIO
51838905Sborman 	return(termbuf.lflags & LLITOUT);
51938905Sborman #else
52039503Sborman 	return(!(termbuf.c_oflag&OPOST));
52138905Sborman #endif
52238905Sborman }
52338905Sborman 
52438905Sborman #ifdef	LINEMODE
52538905Sborman tty_isediting()
52638905Sborman {
52738905Sborman #ifndef USE_TERMIO
52838905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
52938905Sborman #else
53038905Sborman 	return(termbuf.c_lflag & ICANON);
53138905Sborman #endif
53238905Sborman }
53338905Sborman 
53438905Sborman tty_istrapsig()
53538905Sborman {
53638905Sborman #ifndef USE_TERMIO
53738905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
53838905Sborman #else
53938905Sborman 	return(termbuf.c_lflag & ISIG);
54038905Sborman #endif
54138905Sborman }
54238905Sborman 
54338905Sborman tty_setedit(on)
54438905Sborman int on;
54538905Sborman {
54638905Sborman #ifndef USE_TERMIO
54738905Sborman 	if (on)
54838905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
54938905Sborman 	else
55038905Sborman 		termbuf.sg.sg_flags |= CBREAK;
55138905Sborman #else
55238905Sborman 	if (on)
55338905Sborman 		termbuf.c_lflag |= ICANON;
55438905Sborman 	else
55538905Sborman 		termbuf.c_lflag &= ~ICANON;
55638905Sborman #endif
55738905Sborman }
55838905Sborman 
55938905Sborman tty_setsig(on)
56038905Sborman int on;
56138905Sborman {
56238905Sborman #ifndef	USE_TERMIO
56338905Sborman 	if (on)
56438905Sborman 		;
56538905Sborman #else
56638905Sborman 	if (on)
56738905Sborman 		termbuf.c_lflag |= ISIG;
56838905Sborman 	else
56938905Sborman 		termbuf.c_lflag &= ~ISIG;
57038905Sborman #endif
57138905Sborman }
57238905Sborman #endif	/* LINEMODE */
57338905Sborman 
57438905Sborman /*
57538905Sborman  * A table of available terminal speeds
57638905Sborman  */
57738905Sborman struct termspeeds {
57838905Sborman 	int	speed;
57938905Sborman 	int	value;
58038905Sborman } termspeeds[] = {
58138905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
58238905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
58338905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
58438905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
58538905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
58638905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
58738905Sborman };
58838905Sborman 
58938905Sborman tty_tspeed(val)
59038905Sborman {
59138905Sborman 	register struct termspeeds *tp;
59238905Sborman 
59338905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
59438905Sborman 		;
59538905Sborman #ifndef	USE_TERMIO
59638905Sborman 	termbuf.sg.sg_ospeed = tp->value;
59738905Sborman #else
59838905Sborman # ifdef	SYSV_TERMIO
59938905Sborman 	termbuf.c_cflag &= ~CBAUD;
60038905Sborman 	termbuf.c_cflag |= tp->value;
60138905Sborman # else
60238905Sborman 	termbuf.c_ospeed = tp->value;
60338905Sborman # endif
60438905Sborman #endif
60538905Sborman }
60638905Sborman 
60738905Sborman tty_rspeed(val)
60838905Sborman {
60938905Sborman 	register struct termspeeds *tp;
61038905Sborman 
61138905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
61238905Sborman 		;
61338905Sborman #ifndef	USE_TERMIO
61438905Sborman 	termbuf.sg.sg_ispeed = tp->value;
61538905Sborman #else
61638905Sborman # ifdef	SYSV_TERMIO
61738905Sborman 	termbuf.c_cflag &= ~CBAUD;
61838905Sborman 	termbuf.c_cflag |= tp->value;
61938905Sborman # else
62038905Sborman 	termbuf.c_ispeed = tp->value;
62138905Sborman # endif
62238905Sborman #endif
62338905Sborman }
62438905Sborman 
62540242Sborman #if	defined(CRAY2) && defined(UNICOS5)
62638905Sborman tty_isnewmap()
62738905Sborman {
62838905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
62938905Sborman 			!(termbuf.c_oflag & ONLRET));
63038905Sborman }
63138905Sborman #endif
63238905Sborman 
63338905Sborman #ifdef	CRAY
63438905Sborman # ifndef NEWINIT
63538905Sborman extern	struct utmp wtmp;
63638905Sborman extern char wtmpf[];
63738905Sborman # else	/* NEWINIT */
63838905Sborman int	gotalarm;
63940242Sborman /* ARGSUSED */
64040242Sborman void
64140242Sborman nologinproc(sig)
64240242Sborman int sig;
64338905Sborman {
64438905Sborman 	gotalarm++;
64538905Sborman }
64638905Sborman # endif	/* NEWINIT */
64738905Sborman #endif /* CRAY */
64838905Sborman 
64938905Sborman /*
65038905Sborman  * getptyslave()
65138905Sborman  *
65238905Sborman  * Open the slave side of the pty, and do any initialization
65338905Sborman  * that is necessary.  The return value is a file descriptor
65438905Sborman  * for the slave side.
65538905Sborman  */
65638905Sborman getptyslave()
65738905Sborman {
65838905Sborman 	register int t = -1;
65938905Sborman 
66038905Sborman #ifndef	CRAY
66138905Sborman 	/*
66238905Sborman 	 * Disassociate self from control terminal and open ttyp side.
66338905Sborman 	 * Set important flags on ttyp and ptyp.
66438905Sborman 	 */
66538905Sborman 	t = open(_PATH_TTY, O_RDWR);
66638905Sborman 	if (t >= 0) {
66738905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
66838905Sborman 		(void) close(t);
66938905Sborman 	}
67038905Sborman 
67138905Sborman 	t = open(line, O_RDWR);
67238905Sborman 	if (t < 0)
67338905Sborman 		fatalperror(net, line);
67438905Sborman 	if (fchmod(t, 0))
67538905Sborman 		fatalperror(net, line);
67638905Sborman 	(void) signal(SIGHUP, SIG_IGN);
67738905Sborman 	vhangup();
67838905Sborman 	(void) signal(SIGHUP, SIG_DFL);
67938905Sborman 	t = open(line, O_RDWR);
68038905Sborman 	if (t < 0)
68138905Sborman 		fatalperror(net, line);
68238905Sborman 
68338905Sborman 	init_termbuf();
68438905Sborman #ifndef	USE_TERMIO
68540242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
68638905Sborman 	termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
68738905Sborman #else
68838905Sborman 	termbuf.c_lflag |= ECHO;
68938905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
69038905Sborman 	termbuf.c_iflag |= ICRNL;
69138905Sborman 	termbuf.c_iflag &= ~IXOFF;
69238905Sborman # ifdef	SYSV_TERMIO
69338905Sborman 	termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
69438905Sborman # else SYSV_TERMIO
69538905Sborman 	termbuf.c_ospeed = termbuf.c_ispeed = B9600;
69638905Sborman # endif
69738905Sborman #endif
69838905Sborman 	set_termbuf();
69938905Sborman #else	/* CRAY */
70038905Sborman 	(void) chown(line, 0, 0);
70138905Sborman 	(void) chmod(line, 0600);
70238905Sborman #endif	/* CRAY */
70338905Sborman 	return(t);
70438905Sborman }
70538905Sborman 
70638905Sborman #ifdef	NEWINIT
70738905Sborman char *gen_id = "fe";
70838905Sborman #endif
70938905Sborman 
71038905Sborman /*
71138905Sborman  * startslave(t, host)
71238905Sborman  *
71338905Sborman  * Given a file descriptor (t) for a tty, and a hostname, do whatever
71438905Sborman  * is necessary to startup the login process on the slave side of the pty.
71538905Sborman  */
71638905Sborman 
71738905Sborman /* ARGSUSED */
71838905Sborman startslave(t, host)
71938905Sborman int t;
72038905Sborman char *host;
72138905Sborman {
72238905Sborman 	register int i;
72338905Sborman 	long time();
72438905Sborman 
72538905Sborman #ifndef	NEWINIT
72638905Sborman # ifdef	CRAY
72738905Sborman 	utmp_sig_init();
72838905Sborman # endif	/* CRAY */
72938905Sborman 
73038905Sborman 	if ((i = fork()) < 0)
73138905Sborman 		fatalperror(net, "fork");
73238905Sborman 	if (i) {
73338905Sborman # ifdef	CRAY
73438905Sborman 		/*
73538905Sborman 		 * Cray parent will create utmp entry for child and send
73638905Sborman 		 * signal to child to tell when done.  Child waits for signal
73738905Sborman 		 * before doing anything important.
73838905Sborman 		 */
73938905Sborman 		register int pid = i;
74038905Sborman 
74138905Sborman 		setpgrp();
74238905Sborman 		(void) signal(SIGUSR1, func);	/* reset handler to default */
74338905Sborman 		/*
74438905Sborman 		 * Create utmp entry for child
74538905Sborman 		 */
74638905Sborman 		(void) time(&wtmp.ut_time);
74738905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
74838905Sborman 		wtmp.ut_pid = pid;
74938905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
75038905Sborman 		SCPYN(wtmp.ut_host, host);
75138905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
75238905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
75338905Sborman 		pututline(&wtmp);
75438905Sborman 		endutent();
75538905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
75638905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
75738905Sborman 			(void) close(i);
75838905Sborman 		}
75938905Sborman 		utmp_sig_notify(pid);
76038905Sborman # endif	/* CRAY */
76138905Sborman 		(void) close(t);
76238905Sborman 	} else {
76338905Sborman 		start_login(t, host);
76438905Sborman 		/*NOTREACHED*/
76538905Sborman 	}
76638905Sborman #else	/* NEWINIT */
76738905Sborman 
76838905Sborman 	extern char *ptyip;
76938905Sborman 	struct init_request request;
77040242Sborman 	void nologinproc();
77138905Sborman 	register int n;
77238905Sborman 
77338905Sborman 	/*
77438905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
77538905Sborman 	 * for it to start up and begin normal telnet operation.
77638905Sborman 	 */
77738905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
77838905Sborman 		char tbuf[128];
77938905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
78038905Sborman 		fatalperror(net, tbuf);
78138905Sborman 	}
78238905Sborman 	memset((char *)&request, 0, sizeof(request));
78338905Sborman 	request.magic = INIT_MAGIC;
78438905Sborman 	SCPYN(request.gen_id, gen_id);
78538905Sborman 	SCPYN(request.tty_id, &line[8]);
78638905Sborman 	SCPYN(request.host, host);
78738905Sborman 	SCPYN(request.term_type, &terminaltype[5]);
78840242Sborman #if	defined(UNICOS5)
78940242Sborman 	request.signal = SIGCLD;
79040242Sborman 	request.pid = getpid();
79140242Sborman #endif
79238905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
79338905Sborman 		char tbuf[128];
79438905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
79538905Sborman 		fatalperror(net, tbuf);
79638905Sborman 	}
79738905Sborman 	(void) close(i);
79838905Sborman 	(void) signal(SIGALRM, nologinproc);
79938905Sborman 	for (i = 0; ; i++) {
80040242Sborman 		char tbuf[128];
80138905Sborman 		alarm(15);
80238905Sborman 		n = read(pty, ptyip, BUFSIZ);
80338905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
80438905Sborman 			break;
80538905Sborman 		gotalarm = 0;
80640242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
80740242Sborman 		(void) write(net, tbuf, strlen(tbuf));
80838905Sborman 	}
80938905Sborman 	if (n < 0 && gotalarm)
81038905Sborman 		fatal(net, "/etc/init didn't start login process");
81138905Sborman 	pcc += n;
81238905Sborman 	alarm(0);
81338905Sborman 	(void) signal(SIGALRM, SIG_DFL);
81438905Sborman 
81538905Sborman 	return;
81638905Sborman #endif	/* NEWINIT */
81738905Sborman }
81838905Sborman 
81938905Sborman #ifndef	NEWINIT
82038905Sborman char	*envinit[3];
82138905Sborman 
82238905Sborman /*
82338905Sborman  * start_login(t, host)
82438905Sborman  *
82538905Sborman  * Assuming that we are now running as a child processes, this
82638905Sborman  * function will turn us into the login process.
82738905Sborman  */
82838905Sborman 
82938905Sborman start_login(t, host)
83038905Sborman int t;
83138905Sborman char *host;
83238905Sborman {
83338905Sborman 	extern char *getenv();
83438905Sborman 	char **envp;
83538905Sborman 
83638905Sborman #ifdef	CRAY
83738905Sborman 	utmp_sig_wait();
83838905Sborman # ifndef TCVHUP
83938905Sborman 	setpgrp();
84038905Sborman # endif
84138905Sborman 	t = open(line, 2);	/* open ttyp */
84238905Sborman 	if (t < 0)
84338905Sborman 		fatalperror(net, line);
84438905Sborman # ifdef	TCVHUP
84538905Sborman 	/*
84638905Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
84738905Sborman 	 * ourselves.
84838905Sborman 	 */
84938905Sborman 	(void) chown(line, 0, 0);
85038905Sborman 	(void) chmod(line, 0600);
85138905Sborman 	(void) signal(SIGHUP, SIG_IGN);
85238905Sborman 	(void) ioctl(t, TCVHUP, (char *)0);
85338905Sborman 	(void) signal(SIGHUP, SIG_DFL);
85438905Sborman 	setpgrp();
85538905Sborman 	i = open(line, 2);
85638905Sborman 	if (i < 0)
85738905Sborman 		fatalperror(net, line);
85838905Sborman 	(void) close(t);
85938905Sborman 	t = i;
86038905Sborman # endif	/* TCVHUP */
86138905Sborman 	/*
86238905Sborman 	 * set ttyp modes as we like them to be
86338905Sborman 	 */
86438905Sborman 	init_termbuf();
86540242Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
86638905Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
86738905Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
86838905Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
86938905Sborman 	set_termbuf();
87038905Sborman #endif	/* CRAY */
87138905Sborman 
87238905Sborman 	/*
87338905Sborman 	 * set up standard paths before forking to login
87438905Sborman 	 */
87538999Sborman #if	BSD >43
87638905Sborman 	if (setsid() < 0)
87738905Sborman 		fatalperror(net, "setsid");
87838905Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
87938905Sborman 		fatalperror(net, "ioctl(sctty)");
88038905Sborman #endif
88138905Sborman 	(void) close(net);
88238905Sborman 	(void) close(pty);
88338905Sborman 	(void) dup2(t, 0);
88438905Sborman 	(void) dup2(t, 1);
88538905Sborman 	(void) dup2(t, 2);
88638905Sborman 	(void) close(t);
88738905Sborman 	envp = envinit;
88838905Sborman 	*envp++ = terminaltype;
88938905Sborman 	if (*envp = getenv("TZ"))
89038905Sborman 		*envp++ -= 3;
89138905Sborman #ifdef	CRAY
89238905Sborman 	else
89338905Sborman 		*envp++ = "TZ=GMT0";
89438905Sborman #endif
89538905Sborman 	*envp = 0;
89638905Sborman 	environ = envinit;
89738905Sborman 	/*
89838905Sborman 	 * -h : pass on name of host.
89938905Sborman 	 *		WARNING:  -h is accepted by login if and only if
90038905Sborman 	 *			getuid() == 0.
90138905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
90238905Sborman 	 */
90338905Sborman 	execl(_PATH_LOGIN, "login", "-h", host,
90438905Sborman #ifndef CRAY
90538905Sborman 					terminaltype ? "-p" : 0,
90638905Sborman #endif
90738905Sborman 								0);
90838905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
90938905Sborman 	fatalperror(net, _PATH_LOGIN);
91038905Sborman 	/*NOTREACHED*/
91138905Sborman }
91238905Sborman #endif	NEWINIT
91338905Sborman 
91438905Sborman /*
91538905Sborman  * cleanup()
91638905Sborman  *
91738905Sborman  * This is the routine to call when we are all through, to
91838905Sborman  * clean up anything that needs to be cleaned up.
91938905Sborman  */
92038905Sborman cleanup()
92138905Sborman {
92238905Sborman 
92338905Sborman #ifndef	CRAY
92438905Sborman # if BSD > 43
92538905Sborman 	char *p;
92638905Sborman 
92738905Sborman 	p = line + sizeof("/dev/") - 1;
92838905Sborman 	if (logout(p))
92938905Sborman 		logwtmp(p, "", "");
93038905Sborman 	(void)chmod(line, 0666);
93138905Sborman 	(void)chown(line, 0, 0);
93238905Sborman 	*p = 'p';
93338905Sborman 	(void)chmod(line, 0666);
93438905Sborman 	(void)chown(line, 0, 0);
93538905Sborman # else
93638905Sborman 	rmut();
93738905Sborman 	vhangup();	/* XXX */
93838905Sborman # endif
93938905Sborman 	(void) shutdown(net, 2);
94038905Sborman #else	/* CRAY */
94138905Sborman # ifndef NEWINIT
94238905Sborman 	rmut(line);
94338905Sborman 	(void) shutdown(net, 2);
94438905Sborman 	kill(0, SIGHUP);
94538905Sborman # else	/* NEWINIT */
94638905Sborman 	(void) shutdown(net, 2);
94740242Sborman 	sleep(2);
94838905Sborman # endif	/* NEWINT */
94938905Sborman #endif	/* CRAY */
95038905Sborman 	exit(1);
95138905Sborman }
95238905Sborman 
95338905Sborman #if	defined(CRAY) && !defined(NEWINIT)
95438905Sborman /*
95538905Sborman  * _utmp_sig_rcv
95638905Sborman  * utmp_sig_init
95738905Sborman  * utmp_sig_wait
95838905Sborman  *	These three functions are used to coordinate the handling of
95938905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
96038905Sborman  *	The server actually creates the utmp structure, the child calls
96138905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
96238905Sborman  *	signals the future-login shell to proceed.
96338905Sborman  */
96438905Sborman static int caught=0;		/* NZ when signal intercepted */
96538905Sborman static void (*func)();		/* address of previous handler */
96638905Sborman 
96738905Sborman void
96838905Sborman _utmp_sig_rcv(sig)
96938905Sborman int sig;
97038905Sborman {
97138905Sborman 	caught = 1;
97238905Sborman 	(void) signal(SIGUSR1, func);
97338905Sborman }
97438905Sborman 
97538905Sborman utmp_sig_init()
97638905Sborman {
97738905Sborman 	/*
97838905Sborman 	 * register signal handler for UTMP creation
97938905Sborman 	 */
98038905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
98138905Sborman 		fatalperror(net, "telnetd/signal");
98238905Sborman }
98338905Sborman 
98438905Sborman utmp_sig_wait()
98538905Sborman {
98638905Sborman 	/*
98738905Sborman 	 * Wait for parent to write our utmp entry.
98838905Sborman 	 */
98938905Sborman 	sigoff();
99038905Sborman 	while (caught == 0) {
99138905Sborman 		pause();	/* wait until we get a signal (sigon) */
99238905Sborman 		sigoff();	/* turn off signals while we check caught */
99338905Sborman 	}
99438905Sborman 	sigon();		/* turn on signals again */
99538905Sborman }
99638905Sborman 
99738905Sborman utmp_sig_notify(pid)
99838905Sborman {
99938905Sborman 	kill(pid, SIGUSR1);
100038905Sborman }
100138905Sborman #endif	/* defined(CRAY) && !defined(NEWINIT) */
100238905Sborman 
100338905Sborman /*
100438905Sborman  * rmut()
100538905Sborman  *
100638905Sborman  * This is the function called by cleanup() to
100738905Sborman  * remove the utmp entry for this person.
100838905Sborman  */
100938905Sborman 
101038905Sborman #if	!defined(CRAY) && BSD <= 43
101138905Sborman rmut()
101238905Sborman {
101338905Sborman 	register f;
101438905Sborman 	int found = 0;
101538905Sborman 	struct utmp *u, *utmp;
101638905Sborman 	int nutmp;
101738905Sborman 	struct stat statbf;
101838905Sborman 	char *malloc();
101938905Sborman 	long time();
102038905Sborman 	off_t lseek();
102138905Sborman 
102238905Sborman 	f = open(utmpf, O_RDWR);
102338905Sborman 	if (f >= 0) {
102438905Sborman 		(void) fstat(f, &statbf);
102538905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
102638905Sborman 		if (!utmp)
102738905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
102838905Sborman 		if (statbf.st_size && utmp) {
102938905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
103038905Sborman 			nutmp /= sizeof(struct utmp);
103138905Sborman 
103238905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
103338905Sborman 				if (SCMPN(u->ut_line, line+5) ||
103438905Sborman 				    u->ut_name[0]==0)
103538905Sborman 					continue;
103638905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
103738905Sborman 				SCPYN(u->ut_name, "");
103838905Sborman 				SCPYN(u->ut_host, "");
103938905Sborman 				(void) time(&u->ut_time);
104038905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
104138905Sborman 				found++;
104238905Sborman 			}
104338905Sborman 		}
104438905Sborman 		(void) close(f);
104538905Sborman 	}
104638905Sborman 	if (found) {
104738905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
104838905Sborman 		if (f >= 0) {
104938905Sborman 			SCPYN(wtmp.ut_line, line+5);
105038905Sborman 			SCPYN(wtmp.ut_name, "");
105138905Sborman 			SCPYN(wtmp.ut_host, "");
105238905Sborman 			(void) time(&wtmp.ut_time);
105338905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
105438905Sborman 			(void) close(f);
105538905Sborman 		}
105638905Sborman 	}
105738905Sborman 	(void) chmod(line, 0666);
105838905Sborman 	(void) chown(line, 0, 0);
105938905Sborman 	line[strlen("/dev/")] = 'p';
106038905Sborman 	(void) chmod(line, 0666);
106138905Sborman 	(void) chown(line, 0, 0);
106238905Sborman }  /* end of rmut */
106338905Sborman #endif	/* CRAY */
1064