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