tty.c
1/* $OpenBSD: tty.c,v 1.19 2021/10/24 21:24:21 deraadt Exp $ */
2
3#include <errno.h>
4#include <fcntl.h>
5#include <string.h>
6#include <unistd.h>
7
8#include "sh.h"
9#include "tty.h"
10
11int tty_fd = -1; /* dup'd tty file descriptor */
12int tty_devtty; /* true if tty_fd is from /dev/tty */
13struct termios tty_state; /* saved tty state */
14
15void
16tty_close(void)
17{
18 if (tty_fd >= 0) {
19 close(tty_fd);
20 tty_fd = -1;
21 }
22}
23
24/* Initialize tty_fd. Used for saving/resetting tty modes upon
25 * foreground job completion and for setting up tty process group.
26 */
27void
28tty_init(int init_ttystate)
29{
30 int do_close = 1;
31 int tfd;
32
33 tty_close();
34 tty_devtty = 1;
35
36 tfd = open("/dev/tty", O_RDWR);
37 if (tfd == -1) {
38 tty_devtty = 0;
39 warningf(false, "No controlling tty (open /dev/tty: %s)",
40 strerror(errno));
41
42 do_close = 0;
43 if (isatty(0))
44 tfd = 0;
45 else if (isatty(2))
46 tfd = 2;
47 else {
48 warningf(false, "Can't find tty file descriptor");
49 return;
50 }
51 }
52#ifdef F_DUPFD_CLOEXEC
53 if ((tty_fd = fcntl(tfd, F_DUPFD_CLOEXEC, FDBASE)) == -1) {
54 warningf(false, "%s: dup of tty fd failed: %s",
55 __func__, strerror(errno));
56#else
57 if ((tty_fd = fcntl(tfd, F_DUPFD, FDBASE)) == -1) {
58 warningf(false, "%s: dup of tty fd failed: %s",
59 __func__, strerror(errno));
60 } else if (fcntl(tty_fd, F_SETFD, FD_CLOEXEC) == -1) {
61 warningf(false, "%s: set tty fd close-on-exec flag failed: %s",
62 __func__, strerror(errno));
63 close(tty_fd);
64 tty_fd = -1;
65#endif
66 } else if (init_ttystate)
67 tcgetattr(tty_fd, &tty_state);
68 if (do_close)
69 close(tfd);
70}