tty.c revision 1.6 1 /* $NetBSD: tty.c,v 1.6 2017/06/23 00:09:36 kamil Exp $ */
2
3 #include <sys/cdefs.h>
4
5 #ifndef lint
6 __RCSID("$NetBSD: tty.c,v 1.6 2017/06/23 00:09:36 kamil 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
16 int
17 get_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
46 int
47 set_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 ret = ioctl(fd, TIOCSETN, &ts->sgttyb);
78 # ifdef TIOCGATC
79 if (ioctl(fd, TIOCSATC, &ts->lchars) < 0)
80 ret = -1;
81 # else
82 if (ioctl(fd, TIOCSETC, &ts->tchars) < 0)
83 ret = -1;
84 # ifdef TIOCGLTC
85 if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0)
86 ret = -1;
87 # endif /* TIOCGLTC */
88 # endif /* TIOCGATC */
89 # endif /* HAVE_TERMIO_H */
90 # endif /* HAVE_TERIOS_H */
91 return ret;
92 }
93
94
95 /* Initialize tty_fd. Used for saving/reseting tty modes upon
96 * foreground job completion and for setting up tty process group.
97 */
98 void
99 tty_init(init_ttystate)
100 int init_ttystate;
101 {
102 int do_close = 1;
103 int tfd;
104 const char *devtty = _PATH_TTY;
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__)
114 if ((tfd = open(devtty, O_RDWR, 0)) < 0) {
115 if (tfd < 0) {
116 tty_devtty = 0;
117 warningf(FALSE,
118 "No controlling tty (open %s: %s)",
119 devtty, strerror(errno));
120 }
121 }
122 #else /* !__SCO__ */
123 tfd = -1;
124 #endif /* __SCO__ */
125
126 if (tfd < 0) {
127 do_close = 0;
128 if (isatty(0))
129 tfd = 0;
130 else if (isatty(2))
131 tfd = 2;
132 else {
133 warningf(FALSE, "Can't find tty file descriptor");
134 return;
135 }
136 }
137 if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) {
138 warningf(FALSE, "j_ttyinit: dup of tty fd failed: %s",
139 strerror(errno));
140 } else if (fd_clexec(tty_fd) < 0) {
141 warningf(FALSE, "j_ttyinit: can't set close-on-exec flag: %s",
142 strerror(errno));
143 close(tty_fd);
144 tty_fd = -1;
145 } else if (init_ttystate)
146 get_tty(tty_fd, &tty_state);
147 if (do_close)
148 close(tfd);
149 }
150
151 void
152 tty_close()
153 {
154 if (tty_fd >= 0) {
155 close(tty_fd);
156 tty_fd = -1;
157 }
158 }
159