1 /* $NetBSD: tty.c,v 1.10 2021/07/24 21:31:31 andvar Exp $ */
2
3 #include <sys/cdefs.h>
4
5 #ifndef lint
6 __RCSID("$NetBSD: tty.c,v 1.10 2021/07/24 21:31:31 andvar Exp $");
7 #endif
8
9 #include <sys/stat.h>
10
11 #include "sh.h"
12 #define EXTERN
13 #include "tty.h"
14 #undef EXTERN
15
16 int
get_tty(fd,ts)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
set_tty(fd,ts,flags)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/resetting tty modes upon
96 * foreground job completion and for setting up tty process group.
97 */
98 void
tty_init(init_ttystate)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 if ((tfd = open(devtty, O_RDWR, 0)) < 0) {
113 if (tfd < 0) {
114 tty_devtty = 0;
115 warningf(false,
116 "No controlling tty (open %s: %s)",
117 devtty, strerror(errno));
118 }
119 }
120
121 if (tfd < 0) {
122 do_close = 0;
123 if (isatty(0))
124 tfd = 0;
125 else if (isatty(2))
126 tfd = 2;
127 else {
128 warningf(false, "Can't find tty file descriptor");
129 return;
130 }
131 }
132 if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) {
133 warningf(false, "j_ttyinit: dup of tty fd failed: %s",
134 strerror(errno));
135 } else if (fd_clexec(tty_fd) < 0) {
136 warningf(false, "j_ttyinit: can't set close-on-exec flag: %s",
137 strerror(errno));
138 close(tty_fd);
139 tty_fd = -1;
140 } else if (init_ttystate)
141 get_tty(tty_fd, &tty_state);
142 if (do_close)
143 close(tfd);
144 }
145
146 void
tty_close()147 tty_close()
148 {
149 if (tty_fd >= 0) {
150 close(tty_fd);
151 tty_fd = -1;
152 }
153 }
154