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