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