xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 44364)
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*44364Sborman static char sccsid[] = "@(#)sys_term.c	5.8 (Berkeley) 06/28/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 
32*44364Sborman #ifdef	STREAMS
33*44364Sborman #include <sys/stream.h>
34*44364Sborman #endif
3538905Sborman #include <sys/tty.h>
3638905Sborman #ifdef	t_erase
3738905Sborman #undef	t_erase
3838905Sborman #undef	t_kill
3938905Sborman #undef	t_intrc
4038905Sborman #undef	t_quitc
4138905Sborman #undef	t_startc
4238905Sborman #undef	t_stopc
4338905Sborman #undef	t_eofc
4438905Sborman #undef	t_brkc
4538905Sborman #undef	t_suspc
4638905Sborman #undef	t_dsuspc
4738905Sborman #undef	t_rprntc
4838905Sborman #undef	t_flushc
4938905Sborman #undef	t_werasc
5038905Sborman #undef	t_lnextc
5138905Sborman #endif
5238905Sborman 
53*44364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
54*44364Sborman # define EXTPROC 0400
55*44364Sborman #endif
56*44364Sborman 
5738905Sborman #ifndef	USE_TERMIO
5838905Sborman struct termbuf {
5938905Sborman 	struct sgttyb sg;
6038905Sborman 	struct tchars tc;
6138905Sborman 	struct ltchars ltc;
6238905Sborman 	int state;
6338905Sborman 	int lflags;
6438905Sborman } termbuf, termbuf2;
6538905Sborman #else	/* USE_TERMIO */
6638905Sborman # ifdef	SYSV_TERMIO
6738905Sborman #	define termios termio
6838905Sborman # endif
6939974Ssklower # ifndef TCSETA
70*44364Sborman #  ifdef TCSETS
71*44364Sborman #   define TCSETA TCSETS
72*44364Sborman #   define TCGETA TCGETS
73*44364Sborman #  else
74*44364Sborman #   define TCSETA TIOCSETA
75*44364Sborman #   define TCGETA TIOCGETA
76*44364Sborman #  endif
7739974Ssklower # endif /* 4.4BSD */
7838905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
7938905Sborman #endif	/* USE_TERMIO */
8038905Sborman 
8138905Sborman /*
8238905Sborman  * init_termbuf()
8338905Sborman  * copy_termbuf(cp)
8438905Sborman  * set_termbuf()
8538905Sborman  *
8638905Sborman  * These three routines are used to get and set the "termbuf" structure
8738905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
8838905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
8938905Sborman  * set_termbuf() writes the structure into the kernel.
9038905Sborman  */
9138905Sborman 
9238905Sborman init_termbuf()
9338905Sborman {
9438905Sborman #ifndef	USE_TERMIO
9538905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
9638905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
9738905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
9838905Sborman # ifdef	TIOCGSTATE
9938905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
10038905Sborman # endif
10138905Sborman #else
10238905Sborman 	(void) ioctl(pty, TCGETA, (char *)&termbuf);
10338905Sborman #endif
10438905Sborman 	termbuf2 = termbuf;
10538905Sborman }
10638905Sborman 
10738905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
10838905Sborman copy_termbuf(cp, len)
10938905Sborman char *cp;
11038905Sborman int len;
11138905Sborman {
11238905Sborman 	if (len > sizeof(termbuf))
11338905Sborman 		len = sizeof(termbuf);
11438905Sborman 	bcopy(cp, (char *)&termbuf, len);
11538905Sborman 	termbuf2 = termbuf;
11638905Sborman }
11738905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
11838905Sborman 
11938905Sborman set_termbuf()
12038905Sborman {
12138905Sborman 	/*
12238905Sborman 	 * Only make the necessary changes.
12338905Sborman 	 */
12438905Sborman #ifndef	USE_TERMIO
12538905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
12638905Sborman 		(void) ioctl(pty, TIOCSETP, (char *)&termbuf.sg);
12738905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
12838905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
12938905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
13038905Sborman 							sizeof(termbuf.ltc)))
13138905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
13238905Sborman 	if (termbuf.lflags != termbuf2.lflags)
13338905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
13438905Sborman #else	/* USE_TERMIO */
13538905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
13638905Sborman 		(void) ioctl(pty, TCSETA, (char *)&termbuf);
13740242Sborman # if	defined(CRAY2) && defined(UNCIOS5)
13838905Sborman 	needtermstat = 1;
13938905Sborman # endif
14038905Sborman #endif	/* USE_TERMIO */
14138905Sborman }
14238905Sborman 
14338905Sborman 
14438905Sborman /*
14538905Sborman  * spcset(func, valp, valpp)
14638905Sborman  *
14738905Sborman  * This function takes various special characters (func), and
14838905Sborman  * sets *valp to the current value of that character, and
14938905Sborman  * *valpp to point to where in the "termbuf" structure that
15038905Sborman  * value is kept.
15138905Sborman  *
15238905Sborman  * It returns the SLC_ level of support for this function.
15338905Sborman  */
15438905Sborman 
15538905Sborman #ifndef	USE_TERMIO
15638905Sborman spcset(func, valp, valpp)
15738905Sborman int func;
15840242Sborman cc_t *valp;
15940242Sborman cc_t **valpp;
16038905Sborman {
16138905Sborman 	switch(func) {
16238905Sborman 	case SLC_EOF:
16338905Sborman 		*valp = termbuf.tc.t_eofc;
16440242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
16538905Sborman 		return(SLC_VARIABLE);
16638905Sborman 	case SLC_EC:
16738905Sborman 		*valp = termbuf.sg.sg_erase;
16840242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
16938905Sborman 		return(SLC_VARIABLE);
17038905Sborman 	case SLC_EL:
17138905Sborman 		*valp = termbuf.sg.sg_kill;
17240242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
17338905Sborman 		return(SLC_VARIABLE);
17438905Sborman 	case SLC_IP:
17538905Sborman 		*valp = termbuf.tc.t_intrc;
17640242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
17738905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
17838905Sborman 	case SLC_ABORT:
17938905Sborman 		*valp = termbuf.tc.t_quitc;
18040242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
18138905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
18238905Sborman 	case SLC_XON:
18338905Sborman 		*valp = termbuf.tc.t_startc;
18440242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
18538905Sborman 		return(SLC_VARIABLE);
18638905Sborman 	case SLC_XOFF:
18738905Sborman 		*valp = termbuf.tc.t_stopc;
18840242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
18938905Sborman 		return(SLC_VARIABLE);
19038905Sborman 	case SLC_AO:
19138905Sborman 		*valp = termbuf.ltc.t_flushc;
19240242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
19338905Sborman 		return(SLC_VARIABLE);
19438905Sborman 	case SLC_SUSP:
19538905Sborman 		*valp = termbuf.ltc.t_suspc;
19640242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
19738905Sborman 		return(SLC_VARIABLE);
19838905Sborman 	case SLC_EW:
19938905Sborman 		*valp = termbuf.ltc.t_werasc;
20040242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
20138905Sborman 		return(SLC_VARIABLE);
20238905Sborman 	case SLC_RP:
20338905Sborman 		*valp = termbuf.ltc.t_rprntc;
20440242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
20538905Sborman 		return(SLC_VARIABLE);
20638905Sborman 	case SLC_LNEXT:
20738905Sborman 		*valp = termbuf.ltc.t_lnextc;
20840242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
20938905Sborman 		return(SLC_VARIABLE);
21040242Sborman 	case SLC_FORW1:
21140242Sborman 		*valp = termbuf.tc.t_brkc;
21240242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
21340242Sborman 		return(SLC_VARIABLE);
21438905Sborman 	case SLC_BRK:
21538905Sborman 	case SLC_SYNCH:
21638905Sborman 	case SLC_AYT:
21738905Sborman 	case SLC_EOR:
21840242Sborman 		*valp = (cc_t)0;
21940242Sborman 		*valpp = (cc_t *)0;
22038905Sborman 		return(SLC_DEFAULT);
22138905Sborman 	default:
22240242Sborman 		*valp = (cc_t)0;
22340242Sborman 		*valpp = (cc_t *)0;
22438905Sborman 		return(SLC_NOSUPPORT);
22538905Sborman 	}
22638905Sborman }
22738905Sborman 
22838905Sborman #else	/* USE_TERMIO */
22938905Sborman 
23038905Sborman spcset(func, valp, valpp)
23138905Sborman int func;
23240242Sborman cc_t *valp;
23340242Sborman cc_t **valpp;
23438905Sborman {
23539503Sborman 
23639503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
23739503Sborman 			*valpp = &termbuf.c_cc[a]; \
23839503Sborman 			return(b);
23940242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
24039503Sborman 
24138905Sborman 	switch(func) {
24238905Sborman 	case SLC_EOF:
24339503Sborman 		setval(VEOF, SLC_VARIABLE);
24438905Sborman 	case SLC_EC:
24539503Sborman 		setval(VERASE, SLC_VARIABLE);
24638905Sborman 	case SLC_EL:
24739503Sborman 		setval(VKILL, SLC_VARIABLE);
24838905Sborman 	case SLC_IP:
24939503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
25038905Sborman 	case SLC_ABORT:
25139503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
25238905Sborman 	case SLC_XON:
25339503Sborman #ifdef	VSTART
25439503Sborman 		setval(VSTART, SLC_VARIABLE);
25539503Sborman #else
25639503Sborman 		defval(0x13);
25739503Sborman #endif
25838905Sborman 	case SLC_XOFF:
25939503Sborman #ifdef	VSTOP
26039503Sborman 		setval(VSTOP, SLC_VARIABLE);
26139503Sborman #else
26239503Sborman 		defval(0x11);
26339503Sborman #endif
26438905Sborman 	case SLC_EW:
26539503Sborman #ifdef	VWERASE
26639503Sborman 		setval(VWERASE, SLC_VARIABLE);
26739503Sborman #else
26839503Sborman 		defval(0);
26939503Sborman #endif
27038905Sborman 	case SLC_RP:
27139503Sborman #ifdef	VREPRINT
27239503Sborman 		setval(VREPRINT, SLC_VARIABLE);
27339503Sborman #else
27439503Sborman 		defval(0);
27539503Sborman #endif
27638905Sborman 	case SLC_LNEXT:
27739503Sborman #ifdef	VLNEXT
27839503Sborman 		setval(VLNEXT, SLC_VARIABLE);
27939503Sborman #else
28039503Sborman 		defval(0);
28139503Sborman #endif
28239503Sborman 	case SLC_AO:
283*44364Sborman #ifdef	VFLUSHO
284*44364Sborman 		setval(VFLUSHO, SLC_VARIABLE|SLC_FLUSHOUT);
28539503Sborman #else
28639503Sborman 		defval(0);
28739503Sborman #endif
28839503Sborman 	case SLC_SUSP:
28939503Sborman #ifdef	VSUSP
29039503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
29139503Sborman #else
29239503Sborman 		defval(0);
29339503Sborman #endif
29440242Sborman #ifdef	VEOL
29540242Sborman 	case SLC_FORW1:
29640242Sborman 		setval(VEOL, SLC_VARIABLE);
29740242Sborman #endif
29840242Sborman #ifdef	VEOL2
29940242Sborman 	case SLC_FORW2:
30040242Sborman 		setval(VEOL2, SLC_VARIABLE);
30140242Sborman #endif
30239503Sborman 
30338905Sborman 	case SLC_BRK:
30438905Sborman 	case SLC_SYNCH:
30538905Sborman 	case SLC_AYT:
30638905Sborman 	case SLC_EOR:
30739503Sborman 		defval(0);
30839503Sborman 
30938905Sborman 	default:
31038905Sborman 		*valp = 0;
31138905Sborman 		*valpp = 0;
31238905Sborman 		return(SLC_NOSUPPORT);
31338905Sborman 	}
31438905Sborman }
31538905Sborman #endif	/* USE_TERMIO */
31638905Sborman 
31740242Sborman #ifdef CRAY
31838905Sborman /*
31940242Sborman  * getnpty()
32040242Sborman  *
32140242Sborman  * Return the number of pty's configured into the system.
32240242Sborman  */
32340242Sborman getnpty()
32440242Sborman {
32540242Sborman #ifdef _SC_CRAY_NPTY
32640242Sborman 	return sysconf(_SC_CRAY_NPTY);
32740242Sborman #else
32840242Sborman 	return 128;
32940242Sborman #endif /* _SC_CRAY_NPTY */
33040242Sborman }
33140242Sborman #endif /* CRAY */
33240242Sborman 
33340242Sborman /*
33438905Sborman  * getpty()
33538905Sborman  *
33638905Sborman  * Allocate a pty.  As a side effect, the external character
33738905Sborman  * array "line" contains the name of the slave side.
33838905Sborman  *
33938905Sborman  * Returns the file descriptor of the opened pty.
34038905Sborman  */
34138905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
34238905Sborman 
34338905Sborman getpty()
34438905Sborman {
34538905Sborman 	register int p;
34638905Sborman #ifndef CRAY
34738905Sborman 	register char c, *p1, *p2;
34838905Sborman 	register int i;
34938905Sborman 
35038905Sborman 	(void) sprintf(line, "/dev/ptyXX");
35138905Sborman 	p1 = &line[8];
35238905Sborman 	p2 = &line[9];
35338905Sborman 
35438905Sborman 	for (c = 'p'; c <= 's'; c++) {
35538905Sborman 		struct stat stb;
35638905Sborman 
35738905Sborman 		*p1 = c;
35838905Sborman 		*p2 = '0';
35938905Sborman 		if (stat(line, &stb) < 0)
36038905Sborman 			break;
36138905Sborman 		for (i = 0; i < 16; i++) {
36238905Sborman 			*p2 = "0123456789abcdef"[i];
36338905Sborman 			p = open(line, 2);
36438905Sborman 			if (p > 0) {
36538905Sborman 				line[5] = 't';
36638905Sborman 				return(p);
36738905Sborman 			}
36838905Sborman 		}
36938905Sborman 	}
37038905Sborman #else	/* CRAY */
37138905Sborman 	register int npty;
37238905Sborman 	extern lowpty, highpty;
37338905Sborman 
37438905Sborman 	for (npty = lowpty; npty <= highpty; npty++) {
37538905Sborman 		(void) sprintf(line, "/dev/pty/%03d", npty);
37638905Sborman 		p = open(line, 2);
37738905Sborman 		if (p < 0)
37838905Sborman 			continue;
37938905Sborman 		(void) sprintf(line, "/dev/ttyp%03d", npty);
38038905Sborman 		if (access(line, 6) == 0)
38138905Sborman 			return(p);
38238905Sborman 		else {
38338905Sborman 			/* no tty side to pty so skip it */
38438905Sborman 			(void) close(p);
38538905Sborman 		}
38638905Sborman 	}
38738905Sborman #endif	/* CRAY */
38838905Sborman 	return(-1);
38938905Sborman }
39038905Sborman 
39138905Sborman #ifdef	LINEMODE
39238905Sborman /*
39338905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
39438905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
39538905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
39638905Sborman  * tty_isecho()		Find out if echoing is turned on.
39738905Sborman  * tty_setecho(on)	Enable/disable character echoing.
39838905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
39938905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
40038905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
40138905Sborman  * tty_isediting()	Find out if line editing is enabled.
40238905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
40338905Sborman  * tty_setedit(on)	Turn on/off line editing.
40438905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
405*44364Sborman  * tty_issofttab()	Find out if tab expansion is enabled.
406*44364Sborman  * tty_setsofttab(on)	Turn on/off soft tab expansion.
407*44364Sborman  * tty_islitecho()	Find out if typed control chars are echoed literally
408*44364Sborman  * tty_setlitecho()	Turn on/off literal echo of control chars
40938905Sborman  * tty_tspeed(val)	Set transmit speed to val.
41038905Sborman  * tty_rspeed(val)	Set receive speed to val.
41138905Sborman  */
41238905Sborman 
41338905Sborman tty_flowmode()
41438905Sborman {
41538905Sborman #ifndef USE_TERMIO
41638905Sborman 	return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0);
41738905Sborman #else
41838905Sborman 	return(termbuf.c_iflag & IXON ? 1 : 0);
41938905Sborman #endif
42038905Sborman }
42138905Sborman 
42238905Sborman tty_linemode()
42338905Sborman {
42438905Sborman #ifndef	USE_TERMIO
42538905Sborman 	return(termbuf.state & TS_EXTPROC);
42638905Sborman #else
42738905Sborman 	return(termbuf.c_lflag & EXTPROC);
42838905Sborman #endif
42938905Sborman }
43038905Sborman 
43138905Sborman tty_setlinemode(on)
43238905Sborman int on;
43338905Sborman {
43438905Sborman #ifdef	TIOCEXT
43538905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
43638905Sborman #else	/* !TIOCEXT */
43738905Sborman #ifdef	EXTPROC
43838905Sborman 	if (on)
43938905Sborman 		termbuf.c_lflag |= EXTPROC;
44038905Sborman 	else
44138905Sborman 		termbuf.c_lflag &= ~EXTPROC;
44238905Sborman #endif
44338905Sborman 	set_termbuf();
44438905Sborman #endif	/* TIOCEXT */
44538905Sborman }
44638905Sborman 
44738905Sborman tty_isecho()
44838905Sborman {
44938905Sborman #ifndef USE_TERMIO
45038905Sborman 	return (termbuf.sg.sg_flags & ECHO);
45138905Sborman #else
45238905Sborman 	return (termbuf.c_lflag & ECHO);
45338905Sborman #endif
45438905Sborman }
45538905Sborman #endif	/* LINEMODE */
45638905Sborman 
45738905Sborman tty_setecho(on)
45838905Sborman {
45938905Sborman #ifndef	USE_TERMIO
46038905Sborman 	if (on)
46138905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
46238905Sborman 	else
46338905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
46438905Sborman #else
46538905Sborman 	if (on)
46638905Sborman 		termbuf.c_lflag |= ECHO;
46738905Sborman 	else
46838905Sborman 		termbuf.c_lflag &= ~ECHO;
46938905Sborman #endif
47038905Sborman }
47138905Sborman 
47238905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
47338905Sborman tty_israw()
47438905Sborman {
47538905Sborman #ifndef USE_TERMIO
47638905Sborman 	return(termbuf.sg.sg_flags & RAW);
47738905Sborman #else
47838905Sborman 	return(!(termbuf.c_lflag & ICANON));
47938905Sborman #endif
48038905Sborman }
48138905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
48238905Sborman 
48338905Sborman tty_binaryin(on)
48438905Sborman {
48538905Sborman #ifndef	USE_TERMIO
48638905Sborman 	if (on)
48738905Sborman 		termbuf.lflags |= LPASS8;
48838905Sborman 	else
48938905Sborman 		termbuf.lflags &= ~LPASS8;
49038905Sborman #else
49138905Sborman 	if (on) {
49238905Sborman 		termbuf.c_lflag &= ~ISTRIP;
49338905Sborman 	} else {
49438905Sborman 		termbuf.c_lflag |= ISTRIP;
49538905Sborman 	}
49638905Sborman #endif
49738905Sborman }
49838905Sborman 
49938905Sborman tty_binaryout(on)
50038905Sborman {
50138905Sborman #ifndef	USE_TERMIO
50238905Sborman 	if (on)
50338905Sborman 		termbuf.lflags |= LLITOUT;
50438905Sborman 	else
50538905Sborman 		termbuf.lflags &= ~LLITOUT;
50638905Sborman #else
50738905Sborman 	if (on) {
50838905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
50938905Sborman 		termbuf.c_cflag |= CS8;
51038905Sborman 		termbuf.c_oflag &= ~OPOST;
51138905Sborman 	} else {
51238905Sborman 		termbuf.c_cflag &= ~CSIZE;
51338905Sborman 		termbuf.c_cflag |= CS7|PARENB;
51438905Sborman 		termbuf.c_oflag |= OPOST;
51538905Sborman 	}
51638905Sborman #endif
51738905Sborman }
51838905Sborman 
51938905Sborman tty_isbinaryin()
52038905Sborman {
52138905Sborman #ifndef	USE_TERMIO
52238905Sborman 	return(termbuf.lflags & LPASS8);
52338905Sborman #else
52439503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
52538905Sborman #endif
52638905Sborman }
52738905Sborman 
52838905Sborman tty_isbinaryout()
52938905Sborman {
53038905Sborman #ifndef	USE_TERMIO
53138905Sborman 	return(termbuf.lflags & LLITOUT);
53238905Sborman #else
53339503Sborman 	return(!(termbuf.c_oflag&OPOST));
53438905Sborman #endif
53538905Sborman }
53638905Sborman 
53738905Sborman #ifdef	LINEMODE
53838905Sborman tty_isediting()
53938905Sborman {
54038905Sborman #ifndef USE_TERMIO
54138905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
54238905Sborman #else
54338905Sborman 	return(termbuf.c_lflag & ICANON);
54438905Sborman #endif
54538905Sborman }
54638905Sborman 
54738905Sborman tty_istrapsig()
54838905Sborman {
54938905Sborman #ifndef USE_TERMIO
55038905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
55138905Sborman #else
55238905Sborman 	return(termbuf.c_lflag & ISIG);
55338905Sborman #endif
55438905Sborman }
55538905Sborman 
55638905Sborman tty_setedit(on)
55738905Sborman int on;
55838905Sborman {
55938905Sborman #ifndef USE_TERMIO
56038905Sborman 	if (on)
56138905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
56238905Sborman 	else
56338905Sborman 		termbuf.sg.sg_flags |= CBREAK;
56438905Sborman #else
56538905Sborman 	if (on)
56638905Sborman 		termbuf.c_lflag |= ICANON;
56738905Sborman 	else
56838905Sborman 		termbuf.c_lflag &= ~ICANON;
56938905Sborman #endif
57038905Sborman }
57138905Sborman 
57238905Sborman tty_setsig(on)
57338905Sborman int on;
57438905Sborman {
57538905Sborman #ifndef	USE_TERMIO
57638905Sborman 	if (on)
57738905Sborman 		;
57838905Sborman #else
57938905Sborman 	if (on)
58038905Sborman 		termbuf.c_lflag |= ISIG;
58138905Sborman 	else
58238905Sborman 		termbuf.c_lflag &= ~ISIG;
58338905Sborman #endif
58438905Sborman }
58538905Sborman #endif	/* LINEMODE */
58638905Sborman 
587*44364Sborman tty_issofttab()
588*44364Sborman {
589*44364Sborman #ifndef	USE_TERMIO
590*44364Sborman 	return (termbuf.sg.sg_flags & XTABS);
591*44364Sborman #else
592*44364Sborman # ifdef	OXTABS
593*44364Sborman 	return (termbuf.c_oflag & OXTABS);
594*44364Sborman # endif
595*44364Sborman # ifdef	TABDLY
596*44364Sborman 	return ((termbuf.c_oflag & TABDLY) == TAB3);
597*44364Sborman # endif
598*44364Sborman #endif
599*44364Sborman }
600*44364Sborman 
601*44364Sborman tty_setsofttab(on)
602*44364Sborman int on;
603*44364Sborman {
604*44364Sborman #ifndef	USE_TERMIO
605*44364Sborman 	if (on)
606*44364Sborman 		termbuf.sg.sg_flags |= XTABS;
607*44364Sborman 	else
608*44364Sborman 		termbuf.sg.sg_flags &= ~XTABS;
609*44364Sborman #else
610*44364Sborman 	if (on) {
611*44364Sborman # ifdef	OXTABS
612*44364Sborman 		termbuf.c_oflag |= OXTABS;
613*44364Sborman # endif
614*44364Sborman # ifdef	TABDLY
615*44364Sborman 		termbuf.c_oflag &= ~TABDLY;
616*44364Sborman 		termbuf.c_oflag |= TAB3;
617*44364Sborman # endif
618*44364Sborman 	} else {
619*44364Sborman # ifdef	OXTABS
620*44364Sborman 		termbuf.c_oflag &= ~OXTABS;
621*44364Sborman # endif
622*44364Sborman # ifdef	TABDLY
623*44364Sborman 		termbuf.c_oflag &= ~TABDLY;
624*44364Sborman 		termbuf.c_oflag |= TAB0;
625*44364Sborman # endif
626*44364Sborman 	}
627*44364Sborman #endif
628*44364Sborman }
629*44364Sborman 
630*44364Sborman tty_islitecho()
631*44364Sborman {
632*44364Sborman #ifndef	USE_TERMIO
633*44364Sborman 	return (!(termbuf.sg.sg_flags & CTLECH));
634*44364Sborman #else
635*44364Sborman # ifdef	ECHOCTL
636*44364Sborman 	return (!(termbuf.c_lflag & ECHOCTL));
637*44364Sborman # endif
638*44364Sborman # ifdef	TCTLECH
639*44364Sborman 	return (!(termbuf.c_lflag & TCTLECH));
640*44364Sborman # endif
641*44364Sborman # if	!defined(ECHOCTL) && !defined(TCTLECH)
642*44364Sborman 	return (0);	/* assumes ctl chars are echoed '^x' */
643*44364Sborman # endif
644*44364Sborman #endif
645*44364Sborman }
646*44364Sborman 
647*44364Sborman tty_setlitecho(on)
648*44364Sborman int on;
649*44364Sborman {
650*44364Sborman #ifndef	USE_TERMIO
651*44364Sborman 	if (on)
652*44364Sborman 		termbuf.sg.sg_flags &= ~CTLECH;
653*44364Sborman 	else
654*44364Sborman 		termbuf.sg.sg_flags |= CTLECH;
655*44364Sborman #else
656*44364Sborman # ifdef	ECHOCTL
657*44364Sborman 	if (on)
658*44364Sborman 		termbuf.c_lflag &= ~ECHOCTL;
659*44364Sborman 	else
660*44364Sborman 		termbuf.c_lflag |= ECHOCTL;
661*44364Sborman # endif
662*44364Sborman # ifdef	TCTLECH
663*44364Sborman 	if (on)
664*44364Sborman 		termbuf.c_lflag &= ~TCTLECH;
665*44364Sborman 	else
666*44364Sborman 		termbuf.c_lflag |= TCTLECH;
667*44364Sborman # endif
668*44364Sborman #endif
669*44364Sborman }
670*44364Sborman 
67138905Sborman /*
67238905Sborman  * A table of available terminal speeds
67338905Sborman  */
67438905Sborman struct termspeeds {
67538905Sborman 	int	speed;
67638905Sborman 	int	value;
67738905Sborman } termspeeds[] = {
67838905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
67938905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
68038905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
68138905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
68238905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
68338905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
68438905Sborman };
68538905Sborman 
68638905Sborman tty_tspeed(val)
68738905Sborman {
68838905Sborman 	register struct termspeeds *tp;
68938905Sborman 
69038905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
69138905Sborman 		;
69238905Sborman #ifndef	USE_TERMIO
69338905Sborman 	termbuf.sg.sg_ospeed = tp->value;
69438905Sborman #else
695*44364Sborman # ifdef	CBAUD
69638905Sborman 	termbuf.c_cflag &= ~CBAUD;
69738905Sborman 	termbuf.c_cflag |= tp->value;
69838905Sborman # else
69938905Sborman 	termbuf.c_ospeed = tp->value;
70038905Sborman # endif
70138905Sborman #endif
70238905Sborman }
70338905Sborman 
70438905Sborman tty_rspeed(val)
70538905Sborman {
70638905Sborman 	register struct termspeeds *tp;
70738905Sborman 
70838905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
70938905Sborman 		;
71038905Sborman #ifndef	USE_TERMIO
71138905Sborman 	termbuf.sg.sg_ispeed = tp->value;
71238905Sborman #else
713*44364Sborman # ifdef	CBAUD
71438905Sborman 	termbuf.c_cflag &= ~CBAUD;
71538905Sborman 	termbuf.c_cflag |= tp->value;
71638905Sborman # else
71738905Sborman 	termbuf.c_ispeed = tp->value;
71838905Sborman # endif
71938905Sborman #endif
72038905Sborman }
72138905Sborman 
72240242Sborman #if	defined(CRAY2) && defined(UNICOS5)
72338905Sborman tty_isnewmap()
72438905Sborman {
72538905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
72638905Sborman 			!(termbuf.c_oflag & ONLRET));
72738905Sborman }
72838905Sborman #endif
72938905Sborman 
73038905Sborman #ifdef	CRAY
73138905Sborman # ifndef NEWINIT
73238905Sborman extern	struct utmp wtmp;
73338905Sborman extern char wtmpf[];
73438905Sborman # else	/* NEWINIT */
73538905Sborman int	gotalarm;
73640242Sborman /* ARGSUSED */
73740242Sborman void
73840242Sborman nologinproc(sig)
73940242Sborman int sig;
74038905Sborman {
74138905Sborman 	gotalarm++;
74238905Sborman }
74338905Sborman # endif	/* NEWINIT */
74438905Sborman #endif /* CRAY */
74538905Sborman 
74638905Sborman /*
74738905Sborman  * getptyslave()
74838905Sborman  *
74938905Sborman  * Open the slave side of the pty, and do any initialization
75038905Sborman  * that is necessary.  The return value is a file descriptor
75138905Sborman  * for the slave side.
75238905Sborman  */
75338905Sborman getptyslave()
75438905Sborman {
75538905Sborman 	register int t = -1;
75638905Sborman 
75738905Sborman #ifndef	CRAY
75838905Sborman 	/*
75938905Sborman 	 * Disassociate self from control terminal and open ttyp side.
76038905Sborman 	 * Set important flags on ttyp and ptyp.
76138905Sborman 	 */
76238905Sborman 	t = open(_PATH_TTY, O_RDWR);
76338905Sborman 	if (t >= 0) {
76438905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
76538905Sborman 		(void) close(t);
76638905Sborman 	}
76738905Sborman 
76838905Sborman 	t = open(line, O_RDWR);
76938905Sborman 	if (t < 0)
77038905Sborman 		fatalperror(net, line);
77138905Sborman 	if (fchmod(t, 0))
77238905Sborman 		fatalperror(net, line);
773*44364Sborman #if BSD <= 43
77438905Sborman 	(void) signal(SIGHUP, SIG_IGN);
77538905Sborman 	vhangup();
77638905Sborman 	(void) signal(SIGHUP, SIG_DFL);
77738905Sborman 	t = open(line, O_RDWR);
77838905Sborman 	if (t < 0)
77938905Sborman 		fatalperror(net, line);
780*44364Sborman #endif
78138905Sborman 
78238905Sborman 	init_termbuf();
78338905Sborman #ifndef	USE_TERMIO
78440242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
78538905Sborman 	termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
78638905Sborman #else
78738905Sborman 	termbuf.c_lflag |= ECHO;
788*44364Sborman #ifndef	OXTABS
789*44364Sborman #define OXTABS	0
790*44364Sborman #endif
79138905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
79238905Sborman 	termbuf.c_iflag |= ICRNL;
79338905Sborman 	termbuf.c_iflag &= ~IXOFF;
794*44364Sborman # ifdef	CBAUD
795*44364Sborman 	termbuf.c_cflag &= ~CBAUD;
796*44364Sborman 	termbuf.c_cflag |= B9600;
797*44364Sborman # else	/* CBAUD */
79838905Sborman 	termbuf.c_ospeed = termbuf.c_ispeed = B9600;
799*44364Sborman # endif	/* CBAUD */
80038905Sborman #endif
80138905Sborman 	set_termbuf();
80238905Sborman #else	/* CRAY */
80338905Sborman 	(void) chown(line, 0, 0);
80438905Sborman 	(void) chmod(line, 0600);
80538905Sborman #endif	/* CRAY */
80638905Sborman 	return(t);
80738905Sborman }
80838905Sborman 
80938905Sborman #ifdef	NEWINIT
81038905Sborman char *gen_id = "fe";
81138905Sborman #endif
81238905Sborman 
81338905Sborman /*
81438905Sborman  * startslave(t, host)
81538905Sborman  *
81638905Sborman  * Given a file descriptor (t) for a tty, and a hostname, do whatever
81738905Sborman  * is necessary to startup the login process on the slave side of the pty.
81838905Sborman  */
81938905Sborman 
82038905Sborman /* ARGSUSED */
82138905Sborman startslave(t, host)
82238905Sborman int t;
82338905Sborman char *host;
82438905Sborman {
82538905Sborman 	register int i;
82638905Sborman 	long time();
82738905Sborman 
82838905Sborman #ifndef	NEWINIT
82938905Sborman # ifdef	CRAY
83038905Sborman 	utmp_sig_init();
83138905Sborman # endif	/* CRAY */
83238905Sborman 
83338905Sborman 	if ((i = fork()) < 0)
83438905Sborman 		fatalperror(net, "fork");
83538905Sborman 	if (i) {
83638905Sborman # ifdef	CRAY
83738905Sborman 		/*
83838905Sborman 		 * Cray parent will create utmp entry for child and send
83938905Sborman 		 * signal to child to tell when done.  Child waits for signal
84038905Sborman 		 * before doing anything important.
84138905Sborman 		 */
84238905Sborman 		register int pid = i;
84338905Sborman 
84438905Sborman 		setpgrp();
845*44364Sborman 		utmp_sig_reset();		/* reset handler to default */
84638905Sborman 		/*
84738905Sborman 		 * Create utmp entry for child
84838905Sborman 		 */
84938905Sborman 		(void) time(&wtmp.ut_time);
85038905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
85138905Sborman 		wtmp.ut_pid = pid;
85238905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
85338905Sborman 		SCPYN(wtmp.ut_host, host);
85438905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
85538905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
85638905Sborman 		pututline(&wtmp);
85738905Sborman 		endutent();
85838905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
85938905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
86038905Sborman 			(void) close(i);
86138905Sborman 		}
86238905Sborman 		utmp_sig_notify(pid);
86338905Sborman # endif	/* CRAY */
86438905Sborman 		(void) close(t);
86538905Sborman 	} else {
86638905Sborman 		start_login(t, host);
86738905Sborman 		/*NOTREACHED*/
86838905Sborman 	}
86938905Sborman #else	/* NEWINIT */
87038905Sborman 
87138905Sborman 	extern char *ptyip;
87238905Sborman 	struct init_request request;
87340242Sborman 	void nologinproc();
87438905Sborman 	register int n;
87538905Sborman 
87638905Sborman 	/*
87738905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
87838905Sborman 	 * for it to start up and begin normal telnet operation.
87938905Sborman 	 */
88038905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
88138905Sborman 		char tbuf[128];
88238905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
88338905Sborman 		fatalperror(net, tbuf);
88438905Sborman 	}
88538905Sborman 	memset((char *)&request, 0, sizeof(request));
88638905Sborman 	request.magic = INIT_MAGIC;
88738905Sborman 	SCPYN(request.gen_id, gen_id);
88838905Sborman 	SCPYN(request.tty_id, &line[8]);
88938905Sborman 	SCPYN(request.host, host);
890*44364Sborman 	SCPYN(request.term_type, terminaltype);
891*44364Sborman #if	!defined(UNICOS5)
89240242Sborman 	request.signal = SIGCLD;
89340242Sborman 	request.pid = getpid();
89440242Sborman #endif
895*44364Sborman #ifdef BFTPDAEMON
896*44364Sborman 	/*
897*44364Sborman 	 * Are we working as the bftp daemon?
898*44364Sborman 	 */
899*44364Sborman 	if (bftpd) {
900*44364Sborman 		SCPYN(request.exec_name, BFTPPATH);
901*44364Sborman 	}
902*44364Sborman #endif /* BFTPDAEMON */
90338905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
90438905Sborman 		char tbuf[128];
90538905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
90638905Sborman 		fatalperror(net, tbuf);
90738905Sborman 	}
90838905Sborman 	(void) close(i);
90938905Sborman 	(void) signal(SIGALRM, nologinproc);
91038905Sborman 	for (i = 0; ; i++) {
91140242Sborman 		char tbuf[128];
91238905Sborman 		alarm(15);
91338905Sborman 		n = read(pty, ptyip, BUFSIZ);
91438905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
91538905Sborman 			break;
91638905Sborman 		gotalarm = 0;
91740242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
91840242Sborman 		(void) write(net, tbuf, strlen(tbuf));
91938905Sborman 	}
92038905Sborman 	if (n < 0 && gotalarm)
92138905Sborman 		fatal(net, "/etc/init didn't start login process");
92238905Sborman 	pcc += n;
92338905Sborman 	alarm(0);
92438905Sborman 	(void) signal(SIGALRM, SIG_DFL);
92538905Sborman 
92638905Sborman 	return;
92738905Sborman #endif	/* NEWINIT */
92838905Sborman }
92938905Sborman 
93038905Sborman char	*envinit[3];
931*44364Sborman extern char **environ;
93238905Sborman 
933*44364Sborman init_env()
934*44364Sborman {
935*44364Sborman 	extern char *getenv();
936*44364Sborman 	char **envp;
937*44364Sborman 
938*44364Sborman 	envp = envinit;
939*44364Sborman 	if (*envp = getenv("TZ"))
940*44364Sborman 		*envp++ -= 3;
941*44364Sborman #ifdef	CRAY
942*44364Sborman 	else
943*44364Sborman 		*envp++ = "TZ=GMT0";
944*44364Sborman #endif
945*44364Sborman 	*envp = 0;
946*44364Sborman 	environ = envinit;
947*44364Sborman }
948*44364Sborman 
949*44364Sborman #ifdef	CRAY
95038905Sborman /*
951*44364Sborman  * These are environment variable that we
952*44364Sborman  * don't put on the argument line.
953*44364Sborman  */
954*44364Sborman char *invalid[] = {
955*44364Sborman 	"USER=",	/* Set up by login */
956*44364Sborman 	"HOME=",	/* Set up by login */
957*44364Sborman 	"LOGNAME=",	/* Set up by login */
958*44364Sborman 	"TMPDIR=",	/* Set up by login */
959*44364Sborman 	"SHELL=",	/* Set up by login */
960*44364Sborman 	"PATH=",	/* Set up by login */
961*44364Sborman 	"MAIL=",	/* Set up by login */
962*44364Sborman 	"TZ=",		/* Login gets it from the environment */
963*44364Sborman 	"TERM=",	/* Login gets it from the environment */
964*44364Sborman 	0
965*44364Sborman };
966*44364Sborman #endif
967*44364Sborman 
968*44364Sborman #ifndef	NEWINIT
969*44364Sborman 
970*44364Sborman /*
97138905Sborman  * start_login(t, host)
97238905Sborman  *
97338905Sborman  * Assuming that we are now running as a child processes, this
97438905Sborman  * function will turn us into the login process.
97538905Sborman  */
97638905Sborman 
97738905Sborman start_login(t, host)
97838905Sborman int t;
97938905Sborman char *host;
98038905Sborman {
981*44364Sborman 	register char *cp;
982*44364Sborman 	register char **argv;
983*44364Sborman 	char **addarg();
98438905Sborman #ifdef	CRAY
985*44364Sborman 	register char **cpp, **cpp2;
98638905Sborman 	utmp_sig_wait();
98738905Sborman # ifndef TCVHUP
98838905Sborman 	setpgrp();
98938905Sborman # endif
99038905Sborman 	t = open(line, 2);	/* open ttyp */
99138905Sborman 	if (t < 0)
99238905Sborman 		fatalperror(net, line);
99338905Sborman # ifdef	TCVHUP
99438905Sborman 	/*
99538905Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
99638905Sborman 	 * ourselves.
99738905Sborman 	 */
99838905Sborman 	(void) chown(line, 0, 0);
99938905Sborman 	(void) chmod(line, 0600);
100038905Sborman 	(void) signal(SIGHUP, SIG_IGN);
100138905Sborman 	(void) ioctl(t, TCVHUP, (char *)0);
100238905Sborman 	(void) signal(SIGHUP, SIG_DFL);
100338905Sborman 	setpgrp();
100438905Sborman 	i = open(line, 2);
100538905Sborman 	if (i < 0)
100638905Sborman 		fatalperror(net, line);
100738905Sborman 	(void) close(t);
100838905Sborman 	t = i;
100938905Sborman # endif	/* TCVHUP */
101038905Sborman 	/*
101138905Sborman 	 * set ttyp modes as we like them to be
101238905Sborman 	 */
101338905Sborman 	init_termbuf();
101440242Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
101538905Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
101638905Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
101738905Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
101838905Sborman 	set_termbuf();
101938905Sborman #endif	/* CRAY */
102038905Sborman 
102138905Sborman 	/*
102238905Sborman 	 * set up standard paths before forking to login
102338905Sborman 	 */
1024*44364Sborman #ifndef	NO_SETSID
102538905Sborman 	if (setsid() < 0)
102638905Sborman 		fatalperror(net, "setsid");
1027*44364Sborman #endif
1028*44364Sborman 
1029*44364Sborman #ifdef	TIOCSCTTY
103038905Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
103138905Sborman 		fatalperror(net, "ioctl(sctty)");
103238905Sborman #endif
103338905Sborman 	(void) close(net);
103438905Sborman 	(void) close(pty);
103538905Sborman 	(void) dup2(t, 0);
103638905Sborman 	(void) dup2(t, 1);
103738905Sborman 	(void) dup2(t, 2);
103838905Sborman 	(void) close(t);
103938905Sborman 	/*
104038905Sborman 	 * -h : pass on name of host.
104138905Sborman 	 *		WARNING:  -h is accepted by login if and only if
104238905Sborman 	 *			getuid() == 0.
104338905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
104438905Sborman 	 */
1045*44364Sborman 	argv = addarg(0, "login");
1046*44364Sborman 	argv = addarg(argv, "-h");
1047*44364Sborman 	argv = addarg(argv, host);
1048*44364Sborman #if	!defined(CRAY) && !defined(NO_LOGIN_P)
1049*44364Sborman 	argv = addarg(argv, "-p");
105038905Sborman #endif
1051*44364Sborman #ifdef	BFTPDAEMON
1052*44364Sborman 	/*
1053*44364Sborman 	 * Are we working as the bftp daemon?  If so, then ask login
1054*44364Sborman 	 * to start bftp instead of shell.
1055*44364Sborman 	 */
1056*44364Sborman 	if (bftpd) {
1057*44364Sborman 		argv = addarg(argv, "-e");
1058*44364Sborman 		argv = addarg(argv, BFTPPATH);
1059*44364Sborman 	} else
1060*44364Sborman #endif
1061*44364Sborman 	if (getenv("USER")) {
1062*44364Sborman 		argv = addarg(argv, getenv("USER"));
1063*44364Sborman 	}
1064*44364Sborman #ifdef	CRAY
1065*44364Sborman 	for (cpp = environ; *cpp; cpp++) {
1066*44364Sborman 		for (cpp2 = invalid; *cpp2; cpp2++)
1067*44364Sborman 			if (strncmp(*cpp2, *cpp, strlen(*cpp2)) == 0)
1068*44364Sborman 				break;
1069*44364Sborman 		if (*cpp2)
1070*44364Sborman 			continue;
1071*44364Sborman 		argv = addarg(argv, *cpp);
1072*44364Sborman 	}
1073*44364Sborman #endif
1074*44364Sborman 
1075*44364Sborman 	execv(_PATH_LOGIN, argv);
1076*44364Sborman 
107738905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
107838905Sborman 	fatalperror(net, _PATH_LOGIN);
107938905Sborman 	/*NOTREACHED*/
108038905Sborman }
1081*44364Sborman 
1082*44364Sborman char **
1083*44364Sborman addarg(argv, val)
1084*44364Sborman register char **argv;
1085*44364Sborman register char *val;
1086*44364Sborman {
1087*44364Sborman 	register char **cpp;
1088*44364Sborman 	char *malloc();
1089*44364Sborman 
1090*44364Sborman 	if (argv == NULL) {
1091*44364Sborman 		/*
1092*44364Sborman 		 * 10 entries, a leading length, and a null
1093*44364Sborman 		 */
1094*44364Sborman 		argv = (char **)malloc(sizeof(*argv) * 12);
1095*44364Sborman 		if (argv == NULL)
1096*44364Sborman 			return(NULL);
1097*44364Sborman 		*argv++ = (char *)10;
1098*44364Sborman 		*argv = (char *)0;
1099*44364Sborman 	}
1100*44364Sborman 	for (cpp = argv; *cpp; cpp++)
1101*44364Sborman 		;
1102*44364Sborman 	if (cpp == &argv[(int)argv[-1]]) {
1103*44364Sborman 		--argv;
1104*44364Sborman 		*argv = (char *)((int)(*argv) + 10);
1105*44364Sborman 		argv = (char **)realloc(argv, (int)(*argv) + 2);
1106*44364Sborman 		if (argv == NULL)
1107*44364Sborman 			return(NULL);
1108*44364Sborman 		argv++;
1109*44364Sborman 		cpp = &argv[(int)argv[-1] - 10];
1110*44364Sborman 	}
1111*44364Sborman 	*cpp++ = val;
1112*44364Sborman 	*cpp = 0;
1113*44364Sborman 	return(argv);
1114*44364Sborman }
111538905Sborman #endif	NEWINIT
111638905Sborman 
111738905Sborman /*
111838905Sborman  * cleanup()
111938905Sborman  *
112038905Sborman  * This is the routine to call when we are all through, to
112138905Sborman  * clean up anything that needs to be cleaned up.
112238905Sborman  */
112338905Sborman cleanup()
112438905Sborman {
112538905Sborman 
112638905Sborman #ifndef	CRAY
112738905Sborman # if BSD > 43
112838905Sborman 	char *p;
112938905Sborman 
113038905Sborman 	p = line + sizeof("/dev/") - 1;
113138905Sborman 	if (logout(p))
113238905Sborman 		logwtmp(p, "", "");
113338905Sborman 	(void)chmod(line, 0666);
113438905Sborman 	(void)chown(line, 0, 0);
113538905Sborman 	*p = 'p';
113638905Sborman 	(void)chmod(line, 0666);
113738905Sborman 	(void)chown(line, 0, 0);
113838905Sborman # else
113938905Sborman 	rmut();
114038905Sborman 	vhangup();	/* XXX */
114138905Sborman # endif
114238905Sborman 	(void) shutdown(net, 2);
114338905Sborman #else	/* CRAY */
114438905Sborman # ifndef NEWINIT
114538905Sborman 	rmut(line);
114638905Sborman 	(void) shutdown(net, 2);
114738905Sborman 	kill(0, SIGHUP);
114838905Sborman # else	/* NEWINIT */
114938905Sborman 	(void) shutdown(net, 2);
115038905Sborman # endif	/* NEWINT */
115138905Sborman #endif	/* CRAY */
115238905Sborman 	exit(1);
115338905Sborman }
115438905Sborman 
115538905Sborman #if	defined(CRAY) && !defined(NEWINIT)
115638905Sborman /*
115738905Sborman  * _utmp_sig_rcv
115838905Sborman  * utmp_sig_init
115938905Sborman  * utmp_sig_wait
116038905Sborman  *	These three functions are used to coordinate the handling of
116138905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
116238905Sborman  *	The server actually creates the utmp structure, the child calls
116338905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
116438905Sborman  *	signals the future-login shell to proceed.
116538905Sborman  */
116638905Sborman static int caught=0;		/* NZ when signal intercepted */
116738905Sborman static void (*func)();		/* address of previous handler */
116838905Sborman 
116938905Sborman void
117038905Sborman _utmp_sig_rcv(sig)
117138905Sborman int sig;
117238905Sborman {
117338905Sborman 	caught = 1;
117438905Sborman 	(void) signal(SIGUSR1, func);
117538905Sborman }
117638905Sborman 
117738905Sborman utmp_sig_init()
117838905Sborman {
117938905Sborman 	/*
118038905Sborman 	 * register signal handler for UTMP creation
118138905Sborman 	 */
118238905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
118338905Sborman 		fatalperror(net, "telnetd/signal");
118438905Sborman }
118538905Sborman 
1186*44364Sborman utmp_sig_reset()
1187*44364Sborman {
1188*44364Sborman 	(void) signal(SIGUSR1, func);	/* reset handler to default */
1189*44364Sborman }
1190*44364Sborman 
119138905Sborman utmp_sig_wait()
119238905Sborman {
119338905Sborman 	/*
119438905Sborman 	 * Wait for parent to write our utmp entry.
119538905Sborman 	 */
119638905Sborman 	sigoff();
119738905Sborman 	while (caught == 0) {
119838905Sborman 		pause();	/* wait until we get a signal (sigon) */
119938905Sborman 		sigoff();	/* turn off signals while we check caught */
120038905Sborman 	}
120138905Sborman 	sigon();		/* turn on signals again */
120238905Sborman }
120338905Sborman 
120438905Sborman utmp_sig_notify(pid)
120538905Sborman {
120638905Sborman 	kill(pid, SIGUSR1);
120738905Sborman }
120838905Sborman #endif	/* defined(CRAY) && !defined(NEWINIT) */
120938905Sborman 
121038905Sborman /*
121138905Sborman  * rmut()
121238905Sborman  *
121338905Sborman  * This is the function called by cleanup() to
121438905Sborman  * remove the utmp entry for this person.
121538905Sborman  */
121638905Sborman 
121738905Sborman #if	!defined(CRAY) && BSD <= 43
121838905Sborman rmut()
121938905Sborman {
122038905Sborman 	register f;
122138905Sborman 	int found = 0;
122238905Sborman 	struct utmp *u, *utmp;
122338905Sborman 	int nutmp;
122438905Sborman 	struct stat statbf;
122538905Sborman 	char *malloc();
122638905Sborman 	long time();
122738905Sborman 	off_t lseek();
122838905Sborman 
122938905Sborman 	f = open(utmpf, O_RDWR);
123038905Sborman 	if (f >= 0) {
123138905Sborman 		(void) fstat(f, &statbf);
123238905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
123338905Sborman 		if (!utmp)
123438905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
123538905Sborman 		if (statbf.st_size && utmp) {
123638905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
123738905Sborman 			nutmp /= sizeof(struct utmp);
123838905Sborman 
123938905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
124038905Sborman 				if (SCMPN(u->ut_line, line+5) ||
124138905Sborman 				    u->ut_name[0]==0)
124238905Sborman 					continue;
124338905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
124438905Sborman 				SCPYN(u->ut_name, "");
124538905Sborman 				SCPYN(u->ut_host, "");
124638905Sborman 				(void) time(&u->ut_time);
124738905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
124838905Sborman 				found++;
124938905Sborman 			}
125038905Sborman 		}
125138905Sborman 		(void) close(f);
125238905Sborman 	}
125338905Sborman 	if (found) {
125438905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
125538905Sborman 		if (f >= 0) {
125638905Sborman 			SCPYN(wtmp.ut_line, line+5);
125738905Sborman 			SCPYN(wtmp.ut_name, "");
125838905Sborman 			SCPYN(wtmp.ut_host, "");
125938905Sborman 			(void) time(&wtmp.ut_time);
126038905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
126138905Sborman 			(void) close(f);
126238905Sborman 		}
126338905Sborman 	}
126438905Sborman 	(void) chmod(line, 0666);
126538905Sborman 	(void) chown(line, 0, 0);
126638905Sborman 	line[strlen("/dev/")] = 'p';
126738905Sborman 	(void) chmod(line, 0666);
126838905Sborman 	(void) chown(line, 0, 0);
126938905Sborman }  /* end of rmut */
127038905Sborman #endif	/* CRAY */
1271