xref: /plan9/sys/src/ape/cmd/pdksh/tty.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include "sh.h"
2*7dd7cddfSDavid du Colombier #include "ksh_stat.h"
3*7dd7cddfSDavid du Colombier #define EXTERN
4*7dd7cddfSDavid du Colombier #include "tty.h"
5*7dd7cddfSDavid du Colombier #undef EXTERN
6*7dd7cddfSDavid du Colombier 
7*7dd7cddfSDavid du Colombier int
get_tty(fd,ts)8*7dd7cddfSDavid du Colombier get_tty(fd, ts)
9*7dd7cddfSDavid du Colombier 	int fd;
10*7dd7cddfSDavid du Colombier 	TTY_state *ts;
11*7dd7cddfSDavid du Colombier {
12*7dd7cddfSDavid du Colombier 	int ret;
13*7dd7cddfSDavid du Colombier 
14*7dd7cddfSDavid du Colombier # ifdef HAVE_TERMIOS_H
15*7dd7cddfSDavid du Colombier 	ret = tcgetattr(fd, ts);
16*7dd7cddfSDavid du Colombier # else /* HAVE_TERIOS_H */
17*7dd7cddfSDavid du Colombier #  ifdef HAVE_TERMIO_H
18*7dd7cddfSDavid du Colombier 	ret = ioctl(fd, TCGETA, ts);
19*7dd7cddfSDavid du Colombier #  else /* HAVE_TERMIO_H */
20*7dd7cddfSDavid du Colombier 	ret = ioctl(fd, TIOCGETP, &ts->sgttyb);
21*7dd7cddfSDavid du Colombier #   ifdef TIOCGATC
22*7dd7cddfSDavid du Colombier 	if (ioctl(fd, TIOCGATC, &ts->lchars) < 0)
23*7dd7cddfSDavid du Colombier 		ret = -1;
24*7dd7cddfSDavid du Colombier #   else
25*7dd7cddfSDavid du Colombier 	if (ioctl(fd, TIOCGETC, &ts->tchars) < 0)
26*7dd7cddfSDavid du Colombier 		ret = -1;
27*7dd7cddfSDavid du Colombier #    ifdef TIOCGLTC
28*7dd7cddfSDavid du Colombier 	if (ioctl(fd, TIOCGLTC, &ts->ltchars) < 0)
29*7dd7cddfSDavid du Colombier 		ret = -1;
30*7dd7cddfSDavid du Colombier #    endif /* TIOCGLTC */
31*7dd7cddfSDavid du Colombier #   endif /* TIOCGATC */
32*7dd7cddfSDavid du Colombier #  endif /* HAVE_TERMIO_H */
33*7dd7cddfSDavid du Colombier # endif /* HAVE_TERIOS_H */
34*7dd7cddfSDavid du Colombier 	return ret;
35*7dd7cddfSDavid du Colombier }
36*7dd7cddfSDavid du Colombier 
37*7dd7cddfSDavid du Colombier int
set_tty(fd,ts,flags)38*7dd7cddfSDavid du Colombier set_tty(fd, ts, flags)
39*7dd7cddfSDavid du Colombier 	int fd;
40*7dd7cddfSDavid du Colombier 	TTY_state *ts;
41*7dd7cddfSDavid du Colombier 	int flags;
42*7dd7cddfSDavid du Colombier {
43*7dd7cddfSDavid du Colombier 	int ret = 0;
44*7dd7cddfSDavid du Colombier 
45*7dd7cddfSDavid du Colombier # ifdef HAVE_TERMIOS_H
46*7dd7cddfSDavid du Colombier 	ret = tcsetattr(fd, TCSADRAIN, ts);
47*7dd7cddfSDavid du Colombier # else /* HAVE_TERIOS_H */
48*7dd7cddfSDavid du Colombier #  ifdef HAVE_TERMIO_H
49*7dd7cddfSDavid du Colombier #   ifndef TCSETAW				/* e.g. Cray-2 */
50*7dd7cddfSDavid du Colombier 		/* first wait for output to drain */
51*7dd7cddfSDavid du Colombier #    ifdef TCSBRK
52*7dd7cddfSDavid du Colombier 		if (ioctl(tty_fd, TCSBRK, 1) < 0)
53*7dd7cddfSDavid du Colombier 			ret = -1;
54*7dd7cddfSDavid du Colombier #    else /* the following kludge is minimally intrusive, but sometimes fails */
55*7dd7cddfSDavid du Colombier 		if (flags & TF_WAIT)
56*7dd7cddfSDavid du Colombier 			sleep((unsigned)1);	/* fake it */
57*7dd7cddfSDavid du Colombier #    endif
58*7dd7cddfSDavid du Colombier #   endif /* !TCSETAW */
59*7dd7cddfSDavid du Colombier #   if defined(_BSD_SYSV) || !defined(TCSETAW)
60*7dd7cddfSDavid du Colombier /* _BSD_SYSV must force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
61*7dd7cddfSDavid du Colombier 		if (ioctl(tty_fd, TCSETA, ts) < 0)
62*7dd7cddfSDavid du Colombier 			ret = -1;
63*7dd7cddfSDavid du Colombier #   else
64*7dd7cddfSDavid du Colombier 		if (ioctl(tty_fd, TCSETAW, ts) < 0)
65*7dd7cddfSDavid du Colombier 			ret = -1;
66*7dd7cddfSDavid du Colombier #   endif
67*7dd7cddfSDavid du Colombier #  else /* HAVE_TERMIO_H */
68*7dd7cddfSDavid du Colombier #   if defined(__mips) && (defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
69*7dd7cddfSDavid du Colombier 	/* Under RISC/os 5.00, bsd43 environment, after a tty driver
70*7dd7cddfSDavid du Colombier 	 * generated interrupt (eg, INTR, TSTP), all output to tty is
71*7dd7cddfSDavid du Colombier 	 * lost until a SETP is done (there must be a better way of
72*7dd7cddfSDavid du Colombier 	 * doing this...).
73*7dd7cddfSDavid du Colombier 	 */
74*7dd7cddfSDavid du Colombier 	if (flags & TF_MIPSKLUDGE)
75*7dd7cddfSDavid du Colombier 		ret = ioctl(fd, TIOCSETP, &ts->sgttyb);
76*7dd7cddfSDavid du Colombier 	else
77*7dd7cddfSDavid du Colombier #   endif /* _SYSTYPE_BSD43 */
78*7dd7cddfSDavid du Colombier 	    ret = ioctl(fd, TIOCSETN, &ts->sgttyb);
79*7dd7cddfSDavid du Colombier #   ifdef TIOCGATC
80*7dd7cddfSDavid du Colombier 	if (ioctl(fd, TIOCSATC, &ts->lchars) < 0)
81*7dd7cddfSDavid du Colombier 		ret = -1;
82*7dd7cddfSDavid du Colombier #   else
83*7dd7cddfSDavid du Colombier 	if (ioctl(fd, TIOCSETC, &ts->tchars) < 0)
84*7dd7cddfSDavid du Colombier 		ret = -1;
85*7dd7cddfSDavid du Colombier #    ifdef TIOCGLTC
86*7dd7cddfSDavid du Colombier 	if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0)
87*7dd7cddfSDavid du Colombier 		ret = -1;
88*7dd7cddfSDavid du Colombier #    endif /* TIOCGLTC */
89*7dd7cddfSDavid du Colombier #   endif /* TIOCGATC */
90*7dd7cddfSDavid du Colombier #  endif /* HAVE_TERMIO_H */
91*7dd7cddfSDavid du Colombier # endif /* HAVE_TERIOS_H */
92*7dd7cddfSDavid du Colombier 	return ret;
93*7dd7cddfSDavid du Colombier }
94*7dd7cddfSDavid du Colombier 
95*7dd7cddfSDavid du Colombier 
96*7dd7cddfSDavid du Colombier /* Initialize tty_fd.  Used for saving/reseting tty modes upon
97*7dd7cddfSDavid du Colombier  * foreground job completion and for setting up tty process group.
98*7dd7cddfSDavid du Colombier  */
99*7dd7cddfSDavid du Colombier void
tty_init(init_ttystate)100*7dd7cddfSDavid du Colombier tty_init(init_ttystate)
101*7dd7cddfSDavid du Colombier 	int init_ttystate;
102*7dd7cddfSDavid du Colombier {
103*7dd7cddfSDavid du Colombier 	int	do_close = 1;
104*7dd7cddfSDavid du Colombier 	int	tfd;
105*7dd7cddfSDavid du Colombier 
106*7dd7cddfSDavid du Colombier 	if (tty_fd >= 0) {
107*7dd7cddfSDavid du Colombier 		close(tty_fd);
108*7dd7cddfSDavid du Colombier 		tty_fd = -1;
109*7dd7cddfSDavid du Colombier 	}
110*7dd7cddfSDavid du Colombier 	tty_devtty = 1;
111*7dd7cddfSDavid du Colombier 
112*7dd7cddfSDavid du Colombier 	/* SCO can't job control on /dev/tty, so don't try... */
113*7dd7cddfSDavid du Colombier #if !defined(__SCO__) && !defined(PLAN9)
114*7dd7cddfSDavid du Colombier 	if ((tfd = open("/dev/tty", O_RDWR, 0)) < 0) {
115*7dd7cddfSDavid du Colombier #ifdef __NeXT
116*7dd7cddfSDavid du Colombier 		/* rlogin on NeXT boxes does not set up the controlling tty,
117*7dd7cddfSDavid du Colombier 		 * so force it to be done here...
118*7dd7cddfSDavid du Colombier 		 */
119*7dd7cddfSDavid du Colombier 		{
120*7dd7cddfSDavid du Colombier 			extern char *ttyname ARGS((int));
121*7dd7cddfSDavid du Colombier 			char *s = ttyname(isatty(2) ? 2 : 0);
122*7dd7cddfSDavid du Colombier 			int fd;
123*7dd7cddfSDavid du Colombier 
124*7dd7cddfSDavid du Colombier 			if (s && (fd = open(s, O_RDWR, 0)) >= 0) {
125*7dd7cddfSDavid du Colombier 				close(fd);
126*7dd7cddfSDavid du Colombier 				tfd = open("/dev/tty", O_RDWR, 0);
127*7dd7cddfSDavid du Colombier 			}
128*7dd7cddfSDavid du Colombier 		}
129*7dd7cddfSDavid du Colombier #endif /* __NeXT */
130*7dd7cddfSDavid du Colombier 
131*7dd7cddfSDavid du Colombier /* X11R5 xterm on mips doesn't set controlling tty properly - temporary hack */
132*7dd7cddfSDavid du Colombier # if !defined(__mips) || !(defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
133*7dd7cddfSDavid du Colombier 		if (tfd < 0) {
134*7dd7cddfSDavid du Colombier 			tty_devtty = 0;
135*7dd7cddfSDavid du Colombier 			warningf(FALSE,
136*7dd7cddfSDavid du Colombier 				"No controlling tty (open /dev/tty: %s)",
137*7dd7cddfSDavid du Colombier 				strerror(errno));
138*7dd7cddfSDavid du Colombier 		}
139*7dd7cddfSDavid du Colombier # endif /* __mips  */
140*7dd7cddfSDavid du Colombier 	}
141*7dd7cddfSDavid du Colombier #else /* !__SCO__ */
142*7dd7cddfSDavid du Colombier 	tfd = -1;
143*7dd7cddfSDavid du Colombier #endif /* __SCO__ */
144*7dd7cddfSDavid du Colombier 
145*7dd7cddfSDavid du Colombier 	if (tfd < 0) {
146*7dd7cddfSDavid du Colombier 		do_close = 0;
147*7dd7cddfSDavid du Colombier 		if (isatty(0))
148*7dd7cddfSDavid du Colombier 			tfd = 0;
149*7dd7cddfSDavid du Colombier 		else if (isatty(2))
150*7dd7cddfSDavid du Colombier 			tfd = 2;
151*7dd7cddfSDavid du Colombier 		else {
152*7dd7cddfSDavid du Colombier 			warningf(FALSE, "Can't find tty file descriptor");
153*7dd7cddfSDavid du Colombier 			return;
154*7dd7cddfSDavid du Colombier 		}
155*7dd7cddfSDavid du Colombier 	}
156*7dd7cddfSDavid du Colombier 	if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) {
157*7dd7cddfSDavid du Colombier 		warningf(FALSE, "j_ttyinit: dup of tty fd failed: %s",
158*7dd7cddfSDavid du Colombier 			strerror(errno));
159*7dd7cddfSDavid du Colombier 	} else if (fd_clexec(tty_fd) < 0) {
160*7dd7cddfSDavid du Colombier 		warningf(FALSE, "j_ttyinit: can't set close-on-exec flag: %s",
161*7dd7cddfSDavid du Colombier 			strerror(errno));
162*7dd7cddfSDavid du Colombier 		close(tty_fd);
163*7dd7cddfSDavid du Colombier 		tty_fd = -1;
164*7dd7cddfSDavid du Colombier 	} else if (init_ttystate)
165*7dd7cddfSDavid du Colombier 		get_tty(tty_fd, &tty_state);
166*7dd7cddfSDavid du Colombier 	if (do_close)
167*7dd7cddfSDavid du Colombier 		close(tfd);
168*7dd7cddfSDavid du Colombier }
169*7dd7cddfSDavid du Colombier 
170*7dd7cddfSDavid du Colombier void
tty_close()171*7dd7cddfSDavid du Colombier tty_close()
172*7dd7cddfSDavid du Colombier {
173*7dd7cddfSDavid du Colombier 	if (tty_fd >= 0) {
174*7dd7cddfSDavid du Colombier 		close(tty_fd);
175*7dd7cddfSDavid du Colombier 		tty_fd = -1;
176*7dd7cddfSDavid du Colombier 	}
177*7dd7cddfSDavid du Colombier }
178