xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 46685)
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*46685Sbostic static char sccsid[] = "@(#)sys_term.c	5.12 (Berkeley) 02/26/91";
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 
3244364Sborman #ifdef	STREAMS
3344364Sborman #include <sys/stream.h>
3444364Sborman #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 
5344364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
5444364Sborman # define EXTPROC 0400
5544364Sborman #endif
5644364Sborman 
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;
6545234Sborman # define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
6645234Sborman # define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
6738905Sborman #else	/* USE_TERMIO */
6838905Sborman # ifdef	SYSV_TERMIO
6938905Sborman #	define termios termio
7038905Sborman # endif
7145234Sborman # ifndef	TCSANOW
7244364Sborman #  ifdef TCSETS
7345234Sborman #   define	TCSANOW		TCSETS
7445234Sborman #   define	TCSADRAIN	TCSETSW
7545234Sborman #   define	tcgetattr(f, t)	iotcl(f, TCGETS, t)
7644364Sborman #  else
7745234Sborman #   ifdef TCSETA
7845234Sborman #    define	TCSANOW		TCSETA
7945234Sborman #    define	TCSADRAIN	TCSETAW
8045234Sborman #    define	tcgetattr(f, t)	ioctl(f, TCGETA, t)
8145234Sborman #   else
8245234Sborman #    define	TCSANOW		TIOCSETA
8345234Sborman #    define	TCSADRAIN	TIOCSETAW
8445234Sborman #    define	tcgetattr(f, t)	iotcl(f, TIOCGETA, t)
8545234Sborman #   endif
8644364Sborman #  endif
8745234Sborman #  define	tcsetattr(f, a, t)	ioctl(f, a, t)
8845234Sborman #  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
8945234Sborman 					(tp)->c_cflag |= (val)
9045234Sborman #  ifdef CIBAUD
9145234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
9245234Sborman 					(tp)->c_cflag |= ((val)<<IBSHIFT)
9345234Sborman #  else
9445234Sborman #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
9545234Sborman 					(tp)->c_cflag |= (val)
9645234Sborman #  endif
9745234Sborman # endif /* TCSANOW */
9838905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
9938905Sborman #endif	/* USE_TERMIO */
10038905Sborman 
10138905Sborman /*
10238905Sborman  * init_termbuf()
10338905Sborman  * copy_termbuf(cp)
10438905Sborman  * set_termbuf()
10538905Sborman  *
10638905Sborman  * These three routines are used to get and set the "termbuf" structure
10738905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
10838905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
10938905Sborman  * set_termbuf() writes the structure into the kernel.
11038905Sborman  */
11138905Sborman 
11238905Sborman init_termbuf()
11338905Sborman {
11438905Sborman #ifndef	USE_TERMIO
11538905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
11638905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
11738905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
11838905Sborman # ifdef	TIOCGSTATE
11938905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
12038905Sborman # endif
12138905Sborman #else
122*46685Sbostic 	(void) tcgetattr(pty, &termbuf);
12338905Sborman #endif
12438905Sborman 	termbuf2 = termbuf;
12538905Sborman }
12638905Sborman 
12738905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
12838905Sborman copy_termbuf(cp, len)
12938905Sborman char *cp;
13038905Sborman int len;
13138905Sborman {
13238905Sborman 	if (len > sizeof(termbuf))
13338905Sborman 		len = sizeof(termbuf);
13438905Sborman 	bcopy(cp, (char *)&termbuf, len);
13538905Sborman 	termbuf2 = termbuf;
13638905Sborman }
13738905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
13838905Sborman 
13938905Sborman set_termbuf()
14038905Sborman {
14138905Sborman 	/*
14238905Sborman 	 * Only make the necessary changes.
14338905Sborman 	 */
14438905Sborman #ifndef	USE_TERMIO
14538905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
14645234Sborman 		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
14738905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
14838905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
14938905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
15038905Sborman 							sizeof(termbuf.ltc)))
15138905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
15238905Sborman 	if (termbuf.lflags != termbuf2.lflags)
15338905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
15438905Sborman #else	/* USE_TERMIO */
15538905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
156*46685Sbostic 		(void) tcsetattr(pty, TCSADRAIN, &termbuf);
15740242Sborman # if	defined(CRAY2) && defined(UNCIOS5)
15838905Sborman 	needtermstat = 1;
15938905Sborman # endif
16038905Sborman #endif	/* USE_TERMIO */
16138905Sborman }
16238905Sborman 
16338905Sborman 
16438905Sborman /*
16538905Sborman  * spcset(func, valp, valpp)
16638905Sborman  *
16738905Sborman  * This function takes various special characters (func), and
16838905Sborman  * sets *valp to the current value of that character, and
16938905Sborman  * *valpp to point to where in the "termbuf" structure that
17038905Sborman  * value is kept.
17138905Sborman  *
17238905Sborman  * It returns the SLC_ level of support for this function.
17338905Sborman  */
17438905Sborman 
17538905Sborman #ifndef	USE_TERMIO
17638905Sborman spcset(func, valp, valpp)
17738905Sborman int func;
17840242Sborman cc_t *valp;
17940242Sborman cc_t **valpp;
18038905Sborman {
18138905Sborman 	switch(func) {
18238905Sborman 	case SLC_EOF:
18338905Sborman 		*valp = termbuf.tc.t_eofc;
18440242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_eofc;
18538905Sborman 		return(SLC_VARIABLE);
18638905Sborman 	case SLC_EC:
18738905Sborman 		*valp = termbuf.sg.sg_erase;
18840242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_erase;
18938905Sborman 		return(SLC_VARIABLE);
19038905Sborman 	case SLC_EL:
19138905Sborman 		*valp = termbuf.sg.sg_kill;
19240242Sborman 		*valpp = (cc_t *)&termbuf.sg.sg_kill;
19338905Sborman 		return(SLC_VARIABLE);
19438905Sborman 	case SLC_IP:
19538905Sborman 		*valp = termbuf.tc.t_intrc;
19640242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_intrc;
19738905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
19838905Sborman 	case SLC_ABORT:
19938905Sborman 		*valp = termbuf.tc.t_quitc;
20040242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_quitc;
20138905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
20238905Sborman 	case SLC_XON:
20338905Sborman 		*valp = termbuf.tc.t_startc;
20440242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_startc;
20538905Sborman 		return(SLC_VARIABLE);
20638905Sborman 	case SLC_XOFF:
20738905Sborman 		*valp = termbuf.tc.t_stopc;
20840242Sborman 		*valpp = (cc_t *)&termbuf.tc.t_stopc;
20938905Sborman 		return(SLC_VARIABLE);
21038905Sborman 	case SLC_AO:
21138905Sborman 		*valp = termbuf.ltc.t_flushc;
21240242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
21338905Sborman 		return(SLC_VARIABLE);
21438905Sborman 	case SLC_SUSP:
21538905Sborman 		*valp = termbuf.ltc.t_suspc;
21640242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
21738905Sborman 		return(SLC_VARIABLE);
21838905Sborman 	case SLC_EW:
21938905Sborman 		*valp = termbuf.ltc.t_werasc;
22040242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
22138905Sborman 		return(SLC_VARIABLE);
22238905Sborman 	case SLC_RP:
22338905Sborman 		*valp = termbuf.ltc.t_rprntc;
22440242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
22538905Sborman 		return(SLC_VARIABLE);
22638905Sborman 	case SLC_LNEXT:
22738905Sborman 		*valp = termbuf.ltc.t_lnextc;
22840242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
22938905Sborman 		return(SLC_VARIABLE);
23040242Sborman 	case SLC_FORW1:
23140242Sborman 		*valp = termbuf.tc.t_brkc;
23240242Sborman 		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
23340242Sborman 		return(SLC_VARIABLE);
23438905Sborman 	case SLC_BRK:
23538905Sborman 	case SLC_SYNCH:
23638905Sborman 	case SLC_AYT:
23738905Sborman 	case SLC_EOR:
23840242Sborman 		*valp = (cc_t)0;
23940242Sborman 		*valpp = (cc_t *)0;
24038905Sborman 		return(SLC_DEFAULT);
24138905Sborman 	default:
24240242Sborman 		*valp = (cc_t)0;
24340242Sborman 		*valpp = (cc_t *)0;
24438905Sborman 		return(SLC_NOSUPPORT);
24538905Sborman 	}
24638905Sborman }
24738905Sborman 
24838905Sborman #else	/* USE_TERMIO */
24938905Sborman 
25038905Sborman spcset(func, valp, valpp)
25138905Sborman int func;
25240242Sborman cc_t *valp;
25340242Sborman cc_t **valpp;
25438905Sborman {
25539503Sborman 
25639503Sborman #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
25739503Sborman 			*valpp = &termbuf.c_cc[a]; \
25839503Sborman 			return(b);
25940242Sborman #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
26039503Sborman 
26138905Sborman 	switch(func) {
26238905Sborman 	case SLC_EOF:
26339503Sborman 		setval(VEOF, SLC_VARIABLE);
26438905Sborman 	case SLC_EC:
26539503Sborman 		setval(VERASE, SLC_VARIABLE);
26638905Sborman 	case SLC_EL:
26739503Sborman 		setval(VKILL, SLC_VARIABLE);
26838905Sborman 	case SLC_IP:
26939503Sborman 		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
27038905Sborman 	case SLC_ABORT:
27139503Sborman 		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
27238905Sborman 	case SLC_XON:
27339503Sborman #ifdef	VSTART
27439503Sborman 		setval(VSTART, SLC_VARIABLE);
27539503Sborman #else
27639503Sborman 		defval(0x13);
27739503Sborman #endif
27838905Sborman 	case SLC_XOFF:
27939503Sborman #ifdef	VSTOP
28039503Sborman 		setval(VSTOP, SLC_VARIABLE);
28139503Sborman #else
28239503Sborman 		defval(0x11);
28339503Sborman #endif
28438905Sborman 	case SLC_EW:
28539503Sborman #ifdef	VWERASE
28639503Sborman 		setval(VWERASE, SLC_VARIABLE);
28739503Sborman #else
28839503Sborman 		defval(0);
28939503Sborman #endif
29038905Sborman 	case SLC_RP:
29139503Sborman #ifdef	VREPRINT
29239503Sborman 		setval(VREPRINT, SLC_VARIABLE);
29339503Sborman #else
29439503Sborman 		defval(0);
29539503Sborman #endif
29638905Sborman 	case SLC_LNEXT:
29739503Sborman #ifdef	VLNEXT
29839503Sborman 		setval(VLNEXT, SLC_VARIABLE);
29939503Sborman #else
30039503Sborman 		defval(0);
30139503Sborman #endif
30239503Sborman 	case SLC_AO:
30345234Sborman #if	!defined(VDISCARD) && defined(VFLUSHO)
30445234Sborman # define VDISCARD VFLUSHO
30545234Sborman #endif
30645234Sborman #ifdef	VDISCARD
30745234Sborman 		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
30839503Sborman #else
30939503Sborman 		defval(0);
31039503Sborman #endif
31139503Sborman 	case SLC_SUSP:
31239503Sborman #ifdef	VSUSP
31339503Sborman 		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
31439503Sborman #else
31539503Sborman 		defval(0);
31639503Sborman #endif
31740242Sborman #ifdef	VEOL
31840242Sborman 	case SLC_FORW1:
31940242Sborman 		setval(VEOL, SLC_VARIABLE);
32040242Sborman #endif
32140242Sborman #ifdef	VEOL2
32240242Sborman 	case SLC_FORW2:
32340242Sborman 		setval(VEOL2, SLC_VARIABLE);
32440242Sborman #endif
32545234Sborman 	case SLC_AYT:
32645234Sborman #ifdef	VSTATUS
32745234Sborman 		setval(VSTATUS, SLC_VARIABLE);
32845234Sborman #else
32945234Sborman 		defval(0);
33045234Sborman #endif
33139503Sborman 
33238905Sborman 	case SLC_BRK:
33338905Sborman 	case SLC_SYNCH:
33438905Sborman 	case SLC_EOR:
33539503Sborman 		defval(0);
33639503Sborman 
33738905Sborman 	default:
33838905Sborman 		*valp = 0;
33938905Sborman 		*valpp = 0;
34038905Sborman 		return(SLC_NOSUPPORT);
34138905Sborman 	}
34238905Sborman }
34338905Sborman #endif	/* USE_TERMIO */
34438905Sborman 
34540242Sborman #ifdef CRAY
34638905Sborman /*
34740242Sborman  * getnpty()
34840242Sborman  *
34940242Sborman  * Return the number of pty's configured into the system.
35040242Sborman  */
35140242Sborman getnpty()
35240242Sborman {
35340242Sborman #ifdef _SC_CRAY_NPTY
35440242Sborman 	return sysconf(_SC_CRAY_NPTY);
35540242Sborman #else
35640242Sborman 	return 128;
35740242Sborman #endif /* _SC_CRAY_NPTY */
35840242Sborman }
35940242Sborman #endif /* CRAY */
36040242Sborman 
36145234Sborman #ifndef	convex
36240242Sborman /*
36338905Sborman  * getpty()
36438905Sborman  *
36538905Sborman  * Allocate a pty.  As a side effect, the external character
36638905Sborman  * array "line" contains the name of the slave side.
36738905Sborman  *
36838905Sborman  * Returns the file descriptor of the opened pty.
36938905Sborman  */
37045234Sborman #ifndef	__GNUC__
37138905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
37245234Sborman #else
37345234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
37445234Sborman char *line = Xline;
37545234Sborman #endif
37645234Sborman #ifdef	CRAY
37745234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
37845234Sborman #endif	/* CRAY */
37938905Sborman 
38038905Sborman getpty()
38138905Sborman {
38238905Sborman 	register int p;
38338905Sborman #ifndef CRAY
38438905Sborman 	register char c, *p1, *p2;
38538905Sborman 	register int i;
38638905Sborman 
38738905Sborman 	(void) sprintf(line, "/dev/ptyXX");
38838905Sborman 	p1 = &line[8];
38938905Sborman 	p2 = &line[9];
39038905Sborman 
39138905Sborman 	for (c = 'p'; c <= 's'; c++) {
39238905Sborman 		struct stat stb;
39338905Sborman 
39438905Sborman 		*p1 = c;
39538905Sborman 		*p2 = '0';
39638905Sborman 		if (stat(line, &stb) < 0)
39738905Sborman 			break;
39838905Sborman 		for (i = 0; i < 16; i++) {
39938905Sborman 			*p2 = "0123456789abcdef"[i];
40038905Sborman 			p = open(line, 2);
40138905Sborman 			if (p > 0) {
40238905Sborman 				line[5] = 't';
40338905Sborman 				return(p);
40438905Sborman 			}
40538905Sborman 		}
40638905Sborman 	}
40738905Sborman #else	/* CRAY */
40838905Sborman 	register int npty;
40938905Sborman 	extern lowpty, highpty;
41045234Sborman 	struct stat sb;
41138905Sborman 
41238905Sborman 	for (npty = lowpty; npty <= highpty; npty++) {
41345234Sborman 		(void) sprintf(myline, "/dev/pty/%03d", npty);
41445234Sborman 		p = open(myline, 2);
41538905Sborman 		if (p < 0)
41638905Sborman 			continue;
41738905Sborman 		(void) sprintf(line, "/dev/ttyp%03d", npty);
41845234Sborman 		/*
41945234Sborman 		 * Here are some shenanigans to make sure that there
42045234Sborman 		 * are no listeners lurking on the line.
42145234Sborman 		 */
42245234Sborman 		if(stat(line, &sb) < 0) {
42345234Sborman 			(void) close(p);
42445234Sborman 			continue;
42545234Sborman 		}
42645234Sborman 		if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
42745234Sborman 			chown(line, 0, 0);
42845234Sborman 			chmod(line, 0600);
42945234Sborman 			(void)close(p);
43045234Sborman 			p = open(myline, 2);
43145234Sborman 			if (p < 0)
43245234Sborman 				continue;
43345234Sborman 		}
43445234Sborman 		/*
43545234Sborman 		 * Now it should be safe...check for accessability.
43645234Sborman 		 */
43738905Sborman 		if (access(line, 6) == 0)
43838905Sborman 			return(p);
43938905Sborman 		else {
44038905Sborman 			/* no tty side to pty so skip it */
44138905Sborman 			(void) close(p);
44238905Sborman 		}
44338905Sborman 	}
44438905Sborman #endif	/* CRAY */
44538905Sborman 	return(-1);
44638905Sborman }
44745234Sborman #endif	/* convex */
44838905Sborman 
44938905Sborman #ifdef	LINEMODE
45038905Sborman /*
45138905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
45238905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
45338905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
45438905Sborman  * tty_isecho()		Find out if echoing is turned on.
45538905Sborman  * tty_setecho(on)	Enable/disable character echoing.
45638905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
45738905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
45838905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
45938905Sborman  * tty_isediting()	Find out if line editing is enabled.
46038905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
46138905Sborman  * tty_setedit(on)	Turn on/off line editing.
46238905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
46344364Sborman  * tty_issofttab()	Find out if tab expansion is enabled.
46444364Sborman  * tty_setsofttab(on)	Turn on/off soft tab expansion.
46544364Sborman  * tty_islitecho()	Find out if typed control chars are echoed literally
46644364Sborman  * tty_setlitecho()	Turn on/off literal echo of control chars
46738905Sborman  * tty_tspeed(val)	Set transmit speed to val.
46838905Sborman  * tty_rspeed(val)	Set receive speed to val.
46938905Sborman  */
47038905Sborman 
47138905Sborman tty_flowmode()
47238905Sborman {
47338905Sborman #ifndef USE_TERMIO
47438905Sborman 	return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0);
47538905Sborman #else
47638905Sborman 	return(termbuf.c_iflag & IXON ? 1 : 0);
47738905Sborman #endif
47838905Sborman }
47938905Sborman 
48045234Sborman #ifdef convex
48145234Sborman static int linestate;
48245234Sborman #endif
48345234Sborman 
48438905Sborman tty_linemode()
48538905Sborman {
48645234Sborman #ifndef convex
48738905Sborman #ifndef	USE_TERMIO
48838905Sborman 	return(termbuf.state & TS_EXTPROC);
48938905Sborman #else
49038905Sborman 	return(termbuf.c_lflag & EXTPROC);
49138905Sborman #endif
49245234Sborman #else
49345234Sborman 	return(linestate);
49445234Sborman #endif
49538905Sborman }
49638905Sborman 
49738905Sborman tty_setlinemode(on)
49838905Sborman int on;
49938905Sborman {
50038905Sborman #ifdef	TIOCEXT
50145234Sborman # ifndef convex
50245234Sborman 	set_termbuf();
50345234Sborman # else
50445234Sborman 	linestate = on;
50545234Sborman # endif
50638905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
50745234Sborman # ifndef convex
50845234Sborman 	init_termbuf();
50945234Sborman # endif
51038905Sborman #else	/* !TIOCEXT */
51145234Sborman # ifdef	EXTPROC
51238905Sborman 	if (on)
51338905Sborman 		termbuf.c_lflag |= EXTPROC;
51438905Sborman 	else
51538905Sborman 		termbuf.c_lflag &= ~EXTPROC;
51645234Sborman # endif
51738905Sborman #endif	/* TIOCEXT */
51838905Sborman }
51938905Sborman 
52038905Sborman tty_isecho()
52138905Sborman {
52238905Sborman #ifndef USE_TERMIO
52338905Sborman 	return (termbuf.sg.sg_flags & ECHO);
52438905Sborman #else
52538905Sborman 	return (termbuf.c_lflag & ECHO);
52638905Sborman #endif
52738905Sborman }
52838905Sborman #endif	/* LINEMODE */
52938905Sborman 
53038905Sborman tty_setecho(on)
53138905Sborman {
53238905Sborman #ifndef	USE_TERMIO
53338905Sborman 	if (on)
53438905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
53538905Sborman 	else
53638905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
53738905Sborman #else
53838905Sborman 	if (on)
53938905Sborman 		termbuf.c_lflag |= ECHO;
54038905Sborman 	else
54138905Sborman 		termbuf.c_lflag &= ~ECHO;
54238905Sborman #endif
54338905Sborman }
54438905Sborman 
54538905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
54638905Sborman tty_israw()
54738905Sborman {
54838905Sborman #ifndef USE_TERMIO
54938905Sborman 	return(termbuf.sg.sg_flags & RAW);
55038905Sborman #else
55138905Sborman 	return(!(termbuf.c_lflag & ICANON));
55238905Sborman #endif
55338905Sborman }
55438905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
55538905Sborman 
55638905Sborman tty_binaryin(on)
55738905Sborman {
55838905Sborman #ifndef	USE_TERMIO
55938905Sborman 	if (on)
56038905Sborman 		termbuf.lflags |= LPASS8;
56138905Sborman 	else
56238905Sborman 		termbuf.lflags &= ~LPASS8;
56338905Sborman #else
56438905Sborman 	if (on) {
56538905Sborman 		termbuf.c_lflag &= ~ISTRIP;
56638905Sborman 	} else {
56738905Sborman 		termbuf.c_lflag |= ISTRIP;
56838905Sborman 	}
56938905Sborman #endif
57038905Sborman }
57138905Sborman 
57238905Sborman tty_binaryout(on)
57338905Sborman {
57438905Sborman #ifndef	USE_TERMIO
57538905Sborman 	if (on)
57638905Sborman 		termbuf.lflags |= LLITOUT;
57738905Sborman 	else
57838905Sborman 		termbuf.lflags &= ~LLITOUT;
57938905Sborman #else
58038905Sborman 	if (on) {
58138905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
58238905Sborman 		termbuf.c_cflag |= CS8;
58338905Sborman 		termbuf.c_oflag &= ~OPOST;
58438905Sborman 	} else {
58538905Sborman 		termbuf.c_cflag &= ~CSIZE;
58638905Sborman 		termbuf.c_cflag |= CS7|PARENB;
58738905Sborman 		termbuf.c_oflag |= OPOST;
58838905Sborman 	}
58938905Sborman #endif
59038905Sborman }
59138905Sborman 
59238905Sborman tty_isbinaryin()
59338905Sborman {
59438905Sborman #ifndef	USE_TERMIO
59538905Sborman 	return(termbuf.lflags & LPASS8);
59638905Sborman #else
59739503Sborman 	return(!(termbuf.c_iflag & ISTRIP));
59838905Sborman #endif
59938905Sborman }
60038905Sborman 
60138905Sborman tty_isbinaryout()
60238905Sborman {
60338905Sborman #ifndef	USE_TERMIO
60438905Sborman 	return(termbuf.lflags & LLITOUT);
60538905Sborman #else
60639503Sborman 	return(!(termbuf.c_oflag&OPOST));
60738905Sborman #endif
60838905Sborman }
60938905Sborman 
61038905Sborman #ifdef	LINEMODE
61138905Sborman tty_isediting()
61238905Sborman {
61338905Sborman #ifndef USE_TERMIO
61438905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
61538905Sborman #else
61638905Sborman 	return(termbuf.c_lflag & ICANON);
61738905Sborman #endif
61838905Sborman }
61938905Sborman 
62038905Sborman tty_istrapsig()
62138905Sborman {
62238905Sborman #ifndef USE_TERMIO
62338905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
62438905Sborman #else
62538905Sborman 	return(termbuf.c_lflag & ISIG);
62638905Sborman #endif
62738905Sborman }
62838905Sborman 
62938905Sborman tty_setedit(on)
63038905Sborman int on;
63138905Sborman {
63238905Sborman #ifndef USE_TERMIO
63338905Sborman 	if (on)
63438905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
63538905Sborman 	else
63638905Sborman 		termbuf.sg.sg_flags |= CBREAK;
63738905Sborman #else
63838905Sborman 	if (on)
63938905Sborman 		termbuf.c_lflag |= ICANON;
64038905Sborman 	else
64138905Sborman 		termbuf.c_lflag &= ~ICANON;
64238905Sborman #endif
64338905Sborman }
64438905Sborman 
64538905Sborman tty_setsig(on)
64638905Sborman int on;
64738905Sborman {
64838905Sborman #ifndef	USE_TERMIO
64938905Sborman 	if (on)
65038905Sborman 		;
65138905Sborman #else
65238905Sborman 	if (on)
65338905Sborman 		termbuf.c_lflag |= ISIG;
65438905Sborman 	else
65538905Sborman 		termbuf.c_lflag &= ~ISIG;
65638905Sborman #endif
65738905Sborman }
65838905Sborman #endif	/* LINEMODE */
65938905Sborman 
66044364Sborman tty_issofttab()
66144364Sborman {
66244364Sborman #ifndef	USE_TERMIO
66344364Sborman 	return (termbuf.sg.sg_flags & XTABS);
66444364Sborman #else
66544364Sborman # ifdef	OXTABS
66644364Sborman 	return (termbuf.c_oflag & OXTABS);
66744364Sborman # endif
66844364Sborman # ifdef	TABDLY
66944364Sborman 	return ((termbuf.c_oflag & TABDLY) == TAB3);
67044364Sborman # endif
67144364Sborman #endif
67244364Sborman }
67344364Sborman 
67444364Sborman tty_setsofttab(on)
67544364Sborman int on;
67644364Sborman {
67744364Sborman #ifndef	USE_TERMIO
67844364Sborman 	if (on)
67944364Sborman 		termbuf.sg.sg_flags |= XTABS;
68044364Sborman 	else
68144364Sborman 		termbuf.sg.sg_flags &= ~XTABS;
68244364Sborman #else
68344364Sborman 	if (on) {
68444364Sborman # ifdef	OXTABS
68544364Sborman 		termbuf.c_oflag |= OXTABS;
68644364Sborman # endif
68744364Sborman # ifdef	TABDLY
68844364Sborman 		termbuf.c_oflag &= ~TABDLY;
68944364Sborman 		termbuf.c_oflag |= TAB3;
69044364Sborman # endif
69144364Sborman 	} else {
69244364Sborman # ifdef	OXTABS
69344364Sborman 		termbuf.c_oflag &= ~OXTABS;
69444364Sborman # endif
69544364Sborman # ifdef	TABDLY
69644364Sborman 		termbuf.c_oflag &= ~TABDLY;
69744364Sborman 		termbuf.c_oflag |= TAB0;
69844364Sborman # endif
69944364Sborman 	}
70044364Sborman #endif
70144364Sborman }
70244364Sborman 
70344364Sborman tty_islitecho()
70444364Sborman {
70544364Sborman #ifndef	USE_TERMIO
70644364Sborman 	return (!(termbuf.sg.sg_flags & CTLECH));
70744364Sborman #else
70844364Sborman # ifdef	ECHOCTL
70944364Sborman 	return (!(termbuf.c_lflag & ECHOCTL));
71044364Sborman # endif
71144364Sborman # ifdef	TCTLECH
71244364Sborman 	return (!(termbuf.c_lflag & TCTLECH));
71344364Sborman # endif
71444364Sborman # if	!defined(ECHOCTL) && !defined(TCTLECH)
71544364Sborman 	return (0);	/* assumes ctl chars are echoed '^x' */
71644364Sborman # endif
71744364Sborman #endif
71844364Sborman }
71944364Sborman 
72044364Sborman tty_setlitecho(on)
72144364Sborman int on;
72244364Sborman {
72344364Sborman #ifndef	USE_TERMIO
72444364Sborman 	if (on)
72544364Sborman 		termbuf.sg.sg_flags &= ~CTLECH;
72644364Sborman 	else
72744364Sborman 		termbuf.sg.sg_flags |= CTLECH;
72844364Sborman #else
72944364Sborman # ifdef	ECHOCTL
73044364Sborman 	if (on)
73144364Sborman 		termbuf.c_lflag &= ~ECHOCTL;
73244364Sborman 	else
73344364Sborman 		termbuf.c_lflag |= ECHOCTL;
73444364Sborman # endif
73544364Sborman # ifdef	TCTLECH
73644364Sborman 	if (on)
73744364Sborman 		termbuf.c_lflag &= ~TCTLECH;
73844364Sborman 	else
73944364Sborman 		termbuf.c_lflag |= TCTLECH;
74044364Sborman # endif
74144364Sborman #endif
74244364Sborman }
74344364Sborman 
74438905Sborman /*
74538905Sborman  * A table of available terminal speeds
74638905Sborman  */
74738905Sborman struct termspeeds {
74838905Sborman 	int	speed;
74938905Sborman 	int	value;
75038905Sborman } termspeeds[] = {
75138905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
75238905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
75338905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
75438905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
75538905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
75638905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
75738905Sborman };
75838905Sborman 
75938905Sborman tty_tspeed(val)
76038905Sborman {
76138905Sborman 	register struct termspeeds *tp;
76238905Sborman 
76338905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
76438905Sborman 		;
76545234Sborman 	cfsetospeed(&termbuf, tp->value);
76638905Sborman }
76738905Sborman 
76838905Sborman tty_rspeed(val)
76938905Sborman {
77038905Sborman 	register struct termspeeds *tp;
77138905Sborman 
77238905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
77338905Sborman 		;
77445234Sborman 	cfsetispeed(&termbuf, tp->value);
77538905Sborman }
77638905Sborman 
77740242Sborman #if	defined(CRAY2) && defined(UNICOS5)
77838905Sborman tty_isnewmap()
77938905Sborman {
78038905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
78138905Sborman 			!(termbuf.c_oflag & ONLRET));
78238905Sborman }
78338905Sborman #endif
78438905Sborman 
78538905Sborman #ifdef	CRAY
78638905Sborman # ifndef NEWINIT
78738905Sborman extern	struct utmp wtmp;
78838905Sborman extern char wtmpf[];
78938905Sborman # else	/* NEWINIT */
79038905Sborman int	gotalarm;
79140242Sborman /* ARGSUSED */
79240242Sborman void
79340242Sborman nologinproc(sig)
79440242Sborman int sig;
79538905Sborman {
79638905Sborman 	gotalarm++;
79738905Sborman }
79838905Sborman # endif	/* NEWINIT */
79938905Sborman #endif /* CRAY */
80038905Sborman 
80138905Sborman /*
80238905Sborman  * getptyslave()
80338905Sborman  *
80438905Sborman  * Open the slave side of the pty, and do any initialization
80538905Sborman  * that is necessary.  The return value is a file descriptor
80638905Sborman  * for the slave side.
80738905Sborman  */
80838905Sborman getptyslave()
80938905Sborman {
81038905Sborman 	register int t = -1;
81138905Sborman 
81245234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
81345234Sborman # ifdef	LINEMODE
81438905Sborman 	/*
81545234Sborman 	 * Opening the slave side may cause initilization of the
81645234Sborman 	 * kernel tty structure.  We need remember whether or not
81745234Sborman 	 * linemode was turned on, so that we can re-set it if we
81845234Sborman 	 * need to.
81938905Sborman 	 */
82045234Sborman 	int waslm = tty_linemode();
82145234Sborman # endif
82245234Sborman 
82345234Sborman 
82445234Sborman 	/*
82545234Sborman 	 * Make sure that we don't have a controlling tty, and
82645234Sborman 	 * that we are the session (process group) leader.
82745234Sborman 	 */
82845234Sborman # ifdef	TIOCNOTTY
82938905Sborman 	t = open(_PATH_TTY, O_RDWR);
83038905Sborman 	if (t >= 0) {
83138905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
83238905Sborman 		(void) close(t);
83338905Sborman 	}
83445234Sborman # endif
83538905Sborman 
83645234Sborman 
83745234Sborman # ifdef	CRAY
83845234Sborman 	/*
83945234Sborman 	 * Wait for our parent to get the utmp stuff to get done.
84045234Sborman 	 */
84145234Sborman 	utmp_sig_wait();
84245234Sborman # endif
84345234Sborman 
84445234Sborman 	t = cleanopen(line);
84538905Sborman 	if (t < 0)
84638905Sborman 		fatalperror(net, line);
84738905Sborman 
84845234Sborman 	/*
84945234Sborman 	 * set up the tty modes as we like them to be.
85045234Sborman 	 */
85138905Sborman 	init_termbuf();
85245234Sborman # ifdef	LINEMODE
85345234Sborman 	if (waslm)
85445234Sborman 		tty_setlinemode();
85545234Sborman # endif	LINEMODE
85645234Sborman 
85745234Sborman 	/*
85845234Sborman 	 * Settings for sgtty based systems
85945234Sborman 	 */
86045234Sborman # ifndef	USE_TERMIO
86140242Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
86238905Sborman 	termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
86345234Sborman # endif	/* USE_TERMIO */
86445234Sborman 
86545234Sborman 	/*
86645234Sborman 	 * Settings for UNICOS
86745234Sborman 	 */
86845234Sborman # ifdef	CRAY
86945234Sborman 	termbuf.c_oflag = OPOST|ONLCR|TAB3;
87045234Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
87145234Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
87245234Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
87345234Sborman # endif
87445234Sborman 
87545234Sborman 	/*
87645234Sborman 	 * Settings for all other termios/termio based
87745234Sborman 	 * systems, other than 4.4BSD.  In 4.4BSD the
87845234Sborman 	 * kernel does the initial terminal setup.
87945234Sborman 	 */
88045234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43)
88145234Sborman #  ifndef	OXTABS
88245234Sborman #   define OXTABS	0
88345234Sborman #  endif
88438905Sborman 	termbuf.c_lflag |= ECHO;
88538905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
88638905Sborman 	termbuf.c_iflag |= ICRNL;
88738905Sborman 	termbuf.c_iflag &= ~IXOFF;
88845234Sborman 	cfsetospeed(&termbuf, B9600);
88945234Sborman 	cfsetispeed(&termbuf, B9600);
89045234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
89145234Sborman 
89245234Sborman 	/*
89345234Sborman 	 * Set the tty modes, and make this our controlling tty.
89445234Sborman 	 */
89545234Sborman 	set_termbuf();
89645234Sborman 	if (login_tty(t) == -1)
89745234Sborman 		fatalperror(net, "login_tty");
89845234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
89945234Sborman 	if (net > 2)
90045234Sborman 		(void) close(net);
90145234Sborman 	if (pty > 2)
90245234Sborman 		(void) close(pty);
90345234Sborman }
90445234Sborman 
90545234Sborman #if	!defined(CRAY) || !defined(NEWINIT)
90645234Sborman #ifndef	O_NOCTTY
90745234Sborman #define	O_NOCTTY	0
90838905Sborman #endif
90945234Sborman /*
91045234Sborman  * Open the specified slave side of the pty,
91145234Sborman  * making sure that we have a clean tty.
91245234Sborman  */
91345234Sborman cleanopen(line)
91445234Sborman char *line;
91545234Sborman {
91645234Sborman 	register int t;
91745234Sborman 
91845234Sborman 	/*
91945234Sborman 	 * Make sure that other people can't open the
92045234Sborman 	 * slave side of the connection.
92145234Sborman 	 */
92238905Sborman 	(void) chown(line, 0, 0);
92338905Sborman 	(void) chmod(line, 0600);
92445234Sborman 
92545234Sborman # if !defined(CRAY) && (BSD > 43)
92645234Sborman 	(void) revoke(line);
92745234Sborman # endif
92845234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
92945234Sborman 	if (t < 0)
93045234Sborman 		return(-1);
93145234Sborman 
93245234Sborman 	/*
93345234Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
93445234Sborman 	 * ourselves.
93545234Sborman 	 */
93645234Sborman # if !defined(CRAY) && (BSD <= 43)
93745234Sborman 	(void) signal(SIGHUP, SIG_IGN);
93845234Sborman 	vhangup();
93945234Sborman 	(void) signal(SIGHUP, SIG_DFL);
94045234Sborman 	t = open(line, O_RDWR|O_NOCTTY);
94145234Sborman 	if (t < 0)
94245234Sborman 		return(-1);
94345234Sborman # endif
94445234Sborman # if	defined(CRAY) && defined(TCVHUP)
94545234Sborman 	{
94645234Sborman 		register int i;
94745234Sborman 		(void) signal(SIGHUP, SIG_IGN);
94845234Sborman 		(void) ioctl(t, TCVHUP, (char *)0);
94945234Sborman 		(void) signal(SIGHUP, SIG_DFL);
95045234Sborman 		setpgrp();
95145234Sborman 		i = open(line, O_RDWR);
95245234Sborman 		if (i < 0)
95345234Sborman 			return(-1)
95445234Sborman 		(void) close(t);
95545234Sborman 		t = i;
95645234Sborman 	}
95745234Sborman # endif	/* defined(CRAY) && defined(TCVHUP) */
95838905Sborman 	return(t);
95938905Sborman }
96045234Sborman #endif	/* !defined(CRAY) || !defined(NEWINIT) */
96138905Sborman 
96245234Sborman #if BSD <= 43
96345234Sborman login_tty(t)
96445234Sborman int t;
96545234Sborman {
96645234Sborman # ifndef NO_SETSID
96745234Sborman 	if (setsid() < 0)
96845234Sborman 		fatalperror(net, "setsid()");
96945234Sborman # else
97045234Sborman #  ifndef convex
97145234Sborman 	if (setpgrp(0,0) < 0)
97245234Sborman 		fatalperror(net, "setpgrp()");
97345234Sborman #  endif
97445234Sborman # endif
97545234Sborman # ifdef	TIOCSCTTY
97645234Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
97745234Sborman 		fatalperror(net, "ioctl(sctty)");
97845234Sborman # else
97945234Sborman 	close(open(line, O_RDWR));
98045234Sborman # endif
98145234Sborman 	(void) dup2(t, 0);
98245234Sborman 	(void) dup2(t, 1);
98345234Sborman 	(void) dup2(t, 2);
98445234Sborman 	close(t);
98545234Sborman }
98645234Sborman #endif	/* BSD <= 43 */
98745234Sborman 
98838905Sborman #ifdef	NEWINIT
98938905Sborman char *gen_id = "fe";
99038905Sborman #endif
99138905Sborman 
99238905Sborman /*
99345234Sborman  * startslave(host)
99438905Sborman  *
99545234Sborman  * Given a hostname, do whatever
99638905Sborman  * is necessary to startup the login process on the slave side of the pty.
99738905Sborman  */
99838905Sborman 
99938905Sborman /* ARGSUSED */
100045234Sborman startslave(host)
100138905Sborman char *host;
100238905Sborman {
100338905Sborman 	register int i;
100438905Sborman 	long time();
100538905Sborman 
100638905Sborman #ifndef	NEWINIT
100738905Sborman # ifdef	CRAY
100838905Sborman 	utmp_sig_init();
100938905Sborman # endif	/* CRAY */
101038905Sborman 
101138905Sborman 	if ((i = fork()) < 0)
101238905Sborman 		fatalperror(net, "fork");
101338905Sborman 	if (i) {
101438905Sborman # ifdef	CRAY
101538905Sborman 		/*
101638905Sborman 		 * Cray parent will create utmp entry for child and send
101738905Sborman 		 * signal to child to tell when done.  Child waits for signal
101838905Sborman 		 * before doing anything important.
101938905Sborman 		 */
102038905Sborman 		register int pid = i;
102138905Sborman 
102238905Sborman 		setpgrp();
102344364Sborman 		utmp_sig_reset();		/* reset handler to default */
102438905Sborman 		/*
102538905Sborman 		 * Create utmp entry for child
102638905Sborman 		 */
102738905Sborman 		(void) time(&wtmp.ut_time);
102838905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
102938905Sborman 		wtmp.ut_pid = pid;
103038905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
103138905Sborman 		SCPYN(wtmp.ut_host, host);
103238905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
103338905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
103438905Sborman 		pututline(&wtmp);
103538905Sborman 		endutent();
103638905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
103738905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
103838905Sborman 			(void) close(i);
103938905Sborman 		}
104038905Sborman 		utmp_sig_notify(pid);
104138905Sborman # endif	/* CRAY */
104238905Sborman 	} else {
104345234Sborman 		getptyslave();
104445234Sborman 		start_login(host);
104538905Sborman 		/*NOTREACHED*/
104638905Sborman 	}
104738905Sborman #else	/* NEWINIT */
104838905Sborman 
104938905Sborman 	extern char *ptyip;
105038905Sborman 	struct init_request request;
105140242Sborman 	void nologinproc();
105238905Sborman 	register int n;
105338905Sborman 
105438905Sborman 	/*
105538905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
105638905Sborman 	 * for it to start up and begin normal telnet operation.
105738905Sborman 	 */
105838905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
105938905Sborman 		char tbuf[128];
106038905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
106138905Sborman 		fatalperror(net, tbuf);
106238905Sborman 	}
106338905Sborman 	memset((char *)&request, 0, sizeof(request));
106438905Sborman 	request.magic = INIT_MAGIC;
106538905Sborman 	SCPYN(request.gen_id, gen_id);
106638905Sborman 	SCPYN(request.tty_id, &line[8]);
106738905Sborman 	SCPYN(request.host, host);
106844364Sborman 	SCPYN(request.term_type, terminaltype);
106944364Sborman #if	!defined(UNICOS5)
107040242Sborman 	request.signal = SIGCLD;
107140242Sborman 	request.pid = getpid();
107240242Sborman #endif
107344364Sborman #ifdef BFTPDAEMON
107444364Sborman 	/*
107544364Sborman 	 * Are we working as the bftp daemon?
107644364Sborman 	 */
107744364Sborman 	if (bftpd) {
107844364Sborman 		SCPYN(request.exec_name, BFTPPATH);
107944364Sborman 	}
108044364Sborman #endif /* BFTPDAEMON */
108138905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
108238905Sborman 		char tbuf[128];
108338905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
108438905Sborman 		fatalperror(net, tbuf);
108538905Sborman 	}
108638905Sborman 	(void) close(i);
108738905Sborman 	(void) signal(SIGALRM, nologinproc);
108838905Sborman 	for (i = 0; ; i++) {
108940242Sborman 		char tbuf[128];
109038905Sborman 		alarm(15);
109138905Sborman 		n = read(pty, ptyip, BUFSIZ);
109238905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
109338905Sborman 			break;
109438905Sborman 		gotalarm = 0;
109540242Sborman 		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
109640242Sborman 		(void) write(net, tbuf, strlen(tbuf));
109738905Sborman 	}
109838905Sborman 	if (n < 0 && gotalarm)
109938905Sborman 		fatal(net, "/etc/init didn't start login process");
110038905Sborman 	pcc += n;
110138905Sborman 	alarm(0);
110238905Sborman 	(void) signal(SIGALRM, SIG_DFL);
110338905Sborman 
110438905Sborman 	return;
110538905Sborman #endif	/* NEWINIT */
110638905Sborman }
110738905Sborman 
110838905Sborman char	*envinit[3];
110944364Sborman extern char **environ;
111038905Sborman 
111144364Sborman init_env()
111244364Sborman {
111344364Sborman 	extern char *getenv();
111444364Sborman 	char **envp;
111544364Sborman 
111644364Sborman 	envp = envinit;
111744364Sborman 	if (*envp = getenv("TZ"))
111844364Sborman 		*envp++ -= 3;
111944364Sborman #ifdef	CRAY
112044364Sborman 	else
112144364Sborman 		*envp++ = "TZ=GMT0";
112244364Sborman #endif
112344364Sborman 	*envp = 0;
112444364Sborman 	environ = envinit;
112544364Sborman }
112644364Sborman 
112744364Sborman #ifdef	CRAY
112838905Sborman /*
112944364Sborman  * These are environment variable that we
113044364Sborman  * don't put on the argument line.
113144364Sborman  */
113244364Sborman char *invalid[] = {
113344364Sborman 	"USER=",	/* Set up by login */
113444364Sborman 	"HOME=",	/* Set up by login */
113544364Sborman 	"LOGNAME=",	/* Set up by login */
113644364Sborman 	"TMPDIR=",	/* Set up by login */
113744364Sborman 	"SHELL=",	/* Set up by login */
113844364Sborman 	"PATH=",	/* Set up by login */
113944364Sborman 	"MAIL=",	/* Set up by login */
114044364Sborman 	"TZ=",		/* Login gets it from the environment */
114144364Sborman 	"TERM=",	/* Login gets it from the environment */
114244364Sborman 	0
114344364Sborman };
114444364Sborman #endif
114544364Sborman 
114644364Sborman #ifndef	NEWINIT
114744364Sborman 
114844364Sborman /*
114945234Sborman  * start_login(host)
115038905Sborman  *
115138905Sborman  * Assuming that we are now running as a child processes, this
115238905Sborman  * function will turn us into the login process.
115338905Sborman  */
115438905Sborman 
115545234Sborman start_login(host)
115638905Sborman char *host;
115738905Sborman {
115844364Sborman 	register char *cp;
115944364Sborman 	register char **argv;
116044364Sborman 	char **addarg();
116138905Sborman #ifdef	CRAY
116244364Sborman 	register char **cpp, **cpp2;
116338905Sborman #endif	/* CRAY */
116438905Sborman 
116538905Sborman 	/*
116638905Sborman 	 * -h : pass on name of host.
116738905Sborman 	 *		WARNING:  -h is accepted by login if and only if
116838905Sborman 	 *			getuid() == 0.
116938905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
117038905Sborman 	 */
117144364Sborman 	argv = addarg(0, "login");
117244364Sborman 	argv = addarg(argv, "-h");
117344364Sborman 	argv = addarg(argv, host);
117444364Sborman #if	!defined(CRAY) && !defined(NO_LOGIN_P)
117544364Sborman 	argv = addarg(argv, "-p");
117638905Sborman #endif
117744364Sborman #ifdef	BFTPDAEMON
117844364Sborman 	/*
117944364Sborman 	 * Are we working as the bftp daemon?  If so, then ask login
118044364Sborman 	 * to start bftp instead of shell.
118144364Sborman 	 */
118244364Sborman 	if (bftpd) {
118344364Sborman 		argv = addarg(argv, "-e");
118444364Sborman 		argv = addarg(argv, BFTPPATH);
118544364Sborman 	} else
118644364Sborman #endif
118744364Sborman 	if (getenv("USER")) {
118844364Sborman 		argv = addarg(argv, getenv("USER"));
118944364Sborman 	}
119044364Sborman #ifdef	CRAY
119144364Sborman 	for (cpp = environ; *cpp; cpp++) {
119244364Sborman 		for (cpp2 = invalid; *cpp2; cpp2++)
119344364Sborman 			if (strncmp(*cpp2, *cpp, strlen(*cpp2)) == 0)
119444364Sborman 				break;
119544364Sborman 		if (*cpp2)
119644364Sborman 			continue;
119744364Sborman 		argv = addarg(argv, *cpp);
119844364Sborman 	}
119944364Sborman #endif
120044364Sborman 
120144364Sborman 	execv(_PATH_LOGIN, argv);
120244364Sborman 
120338905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
120438905Sborman 	fatalperror(net, _PATH_LOGIN);
120538905Sborman 	/*NOTREACHED*/
120638905Sborman }
120744364Sborman 
120844364Sborman char **
120944364Sborman addarg(argv, val)
121044364Sborman register char **argv;
121144364Sborman register char *val;
121244364Sborman {
121344364Sborman 	register char **cpp;
121444364Sborman 	char *malloc();
121544364Sborman 
121644364Sborman 	if (argv == NULL) {
121744364Sborman 		/*
121844364Sborman 		 * 10 entries, a leading length, and a null
121944364Sborman 		 */
122044364Sborman 		argv = (char **)malloc(sizeof(*argv) * 12);
122144364Sborman 		if (argv == NULL)
122244364Sborman 			return(NULL);
122344364Sborman 		*argv++ = (char *)10;
122444364Sborman 		*argv = (char *)0;
122544364Sborman 	}
122644364Sborman 	for (cpp = argv; *cpp; cpp++)
122744364Sborman 		;
122844364Sborman 	if (cpp == &argv[(int)argv[-1]]) {
122944364Sborman 		--argv;
123044364Sborman 		*argv = (char *)((int)(*argv) + 10);
123144364Sborman 		argv = (char **)realloc(argv, (int)(*argv) + 2);
123244364Sborman 		if (argv == NULL)
123344364Sborman 			return(NULL);
123444364Sborman 		argv++;
123544364Sborman 		cpp = &argv[(int)argv[-1] - 10];
123644364Sborman 	}
123744364Sborman 	*cpp++ = val;
123844364Sborman 	*cpp = 0;
123944364Sborman 	return(argv);
124044364Sborman }
124138905Sborman #endif	NEWINIT
124238905Sborman 
124338905Sborman /*
124438905Sborman  * cleanup()
124538905Sborman  *
124638905Sborman  * This is the routine to call when we are all through, to
124738905Sborman  * clean up anything that needs to be cleaned up.
124838905Sborman  */
124945234Sborman void
125038905Sborman cleanup()
125138905Sborman {
125238905Sborman 
125338905Sborman #ifndef	CRAY
125445234Sborman # if (BSD > 43) || defined(convex)
125538905Sborman 	char *p;
125638905Sborman 
125738905Sborman 	p = line + sizeof("/dev/") - 1;
125838905Sborman 	if (logout(p))
125938905Sborman 		logwtmp(p, "", "");
126038905Sborman 	(void)chmod(line, 0666);
126138905Sborman 	(void)chown(line, 0, 0);
126238905Sborman 	*p = 'p';
126338905Sborman 	(void)chmod(line, 0666);
126438905Sborman 	(void)chown(line, 0, 0);
126538905Sborman # else
126638905Sborman 	rmut();
126738905Sborman 	vhangup();	/* XXX */
126838905Sborman # endif
126938905Sborman 	(void) shutdown(net, 2);
127038905Sborman #else	/* CRAY */
127138905Sborman # ifndef NEWINIT
127238905Sborman 	rmut(line);
127338905Sborman 	(void) shutdown(net, 2);
127438905Sborman 	kill(0, SIGHUP);
127538905Sborman # else	/* NEWINIT */
127638905Sborman 	(void) shutdown(net, 2);
127738905Sborman # endif	/* NEWINT */
127838905Sborman #endif	/* CRAY */
127938905Sborman 	exit(1);
128038905Sborman }
128138905Sborman 
128238905Sborman #if	defined(CRAY) && !defined(NEWINIT)
128338905Sborman /*
128438905Sborman  * _utmp_sig_rcv
128538905Sborman  * utmp_sig_init
128638905Sborman  * utmp_sig_wait
128738905Sborman  *	These three functions are used to coordinate the handling of
128838905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
128938905Sborman  *	The server actually creates the utmp structure, the child calls
129038905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
129138905Sborman  *	signals the future-login shell to proceed.
129238905Sborman  */
129338905Sborman static int caught=0;		/* NZ when signal intercepted */
129438905Sborman static void (*func)();		/* address of previous handler */
129538905Sborman 
129638905Sborman void
129738905Sborman _utmp_sig_rcv(sig)
129838905Sborman int sig;
129938905Sborman {
130038905Sborman 	caught = 1;
130138905Sborman 	(void) signal(SIGUSR1, func);
130238905Sborman }
130338905Sborman 
130438905Sborman utmp_sig_init()
130538905Sborman {
130638905Sborman 	/*
130738905Sborman 	 * register signal handler for UTMP creation
130838905Sborman 	 */
130938905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
131038905Sborman 		fatalperror(net, "telnetd/signal");
131138905Sborman }
131238905Sborman 
131344364Sborman utmp_sig_reset()
131444364Sborman {
131544364Sborman 	(void) signal(SIGUSR1, func);	/* reset handler to default */
131644364Sborman }
131744364Sborman 
131838905Sborman utmp_sig_wait()
131938905Sborman {
132038905Sborman 	/*
132138905Sborman 	 * Wait for parent to write our utmp entry.
132238905Sborman 	 */
132338905Sborman 	sigoff();
132438905Sborman 	while (caught == 0) {
132538905Sborman 		pause();	/* wait until we get a signal (sigon) */
132638905Sborman 		sigoff();	/* turn off signals while we check caught */
132738905Sborman 	}
132838905Sborman 	sigon();		/* turn on signals again */
132938905Sborman }
133038905Sborman 
133138905Sborman utmp_sig_notify(pid)
133238905Sborman {
133338905Sborman 	kill(pid, SIGUSR1);
133438905Sborman }
133538905Sborman #endif	/* defined(CRAY) && !defined(NEWINIT) */
133638905Sborman 
133738905Sborman /*
133838905Sborman  * rmut()
133938905Sborman  *
134038905Sborman  * This is the function called by cleanup() to
134138905Sborman  * remove the utmp entry for this person.
134238905Sborman  */
134338905Sborman 
134438905Sborman #if	!defined(CRAY) && BSD <= 43
134538905Sborman rmut()
134638905Sborman {
134738905Sborman 	register f;
134838905Sborman 	int found = 0;
134938905Sborman 	struct utmp *u, *utmp;
135038905Sborman 	int nutmp;
135138905Sborman 	struct stat statbf;
135238905Sborman 	char *malloc();
135338905Sborman 	long time();
135438905Sborman 	off_t lseek();
135538905Sborman 
135638905Sborman 	f = open(utmpf, O_RDWR);
135738905Sborman 	if (f >= 0) {
135838905Sborman 		(void) fstat(f, &statbf);
135938905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
136038905Sborman 		if (!utmp)
136138905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
136238905Sborman 		if (statbf.st_size && utmp) {
136338905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
136438905Sborman 			nutmp /= sizeof(struct utmp);
136538905Sborman 
136638905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
136738905Sborman 				if (SCMPN(u->ut_line, line+5) ||
136838905Sborman 				    u->ut_name[0]==0)
136938905Sborman 					continue;
137038905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
137138905Sborman 				SCPYN(u->ut_name, "");
137238905Sborman 				SCPYN(u->ut_host, "");
137338905Sborman 				(void) time(&u->ut_time);
137438905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
137538905Sborman 				found++;
137638905Sborman 			}
137738905Sborman 		}
137838905Sborman 		(void) close(f);
137938905Sborman 	}
138038905Sborman 	if (found) {
138138905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
138238905Sborman 		if (f >= 0) {
138338905Sborman 			SCPYN(wtmp.ut_line, line+5);
138438905Sborman 			SCPYN(wtmp.ut_name, "");
138538905Sborman 			SCPYN(wtmp.ut_host, "");
138638905Sborman 			(void) time(&wtmp.ut_time);
138738905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
138838905Sborman 			(void) close(f);
138938905Sborman 		}
139038905Sborman 	}
139138905Sborman 	(void) chmod(line, 0666);
139238905Sborman 	(void) chown(line, 0, 0);
139338905Sborman 	line[strlen("/dev/")] = 'p';
139438905Sborman 	(void) chmod(line, 0666);
139538905Sborman 	(void) chown(line, 0, 0);
139638905Sborman }  /* end of rmut */
139738905Sborman #endif	/* CRAY */
1398