From 9535bc94ff1d7a52be1c6f30951162e4059c6916 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 8 Jul 2022 22:30:11 +0530 Subject: [PATCH] Use both open and the ioctl to set the controlling terminal --- kitty/child.c | 24 +++++++++++++++--------- kitty/fast_data_types.pyi | 2 +- kitty/prewarm.py | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/kitty/child.c b/kitty/child.c index d8a60b063..46fc20455 100644 --- a/kitty/child.c +++ b/kitty/child.c @@ -121,10 +121,8 @@ spawn(PyObject *self UNUSED, PyObject *args) { // Establish the controlling terminal (see man 7 credentials) int tfd = safe_open(name, O_RDWR, 0); if (tfd == -1) exit_on_err("Failed to open controlling terminal"); -#ifdef TIOCSCTTY // On BSD open() does not establish the controlling terminal if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY"); -#endif safe_close(tfd, __FILE__, __LINE__); // Redirect stdin/stdout/stderr to the pty @@ -185,13 +183,21 @@ spawn(PyObject *self UNUSED, PyObject *args) { static PyObject* establish_controlling_tty(PyObject *self UNUSED, PyObject *args) { - int tty_fd, stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; - if (!PyArg_ParseTuple(args, "i|iii", &tty_fd, &stdin_fd, &stdout_fd, &stderr_fd)) return NULL; - if (ioctl(tty_fd, TIOCSCTTY, 0) == -1) { safe_close(tty_fd, __FILE__, __LINE__); return PyErr_SetFromErrno(PyExc_OSError); } - if (stdin_fd > -1 && safe_dup2(tty_fd, stdin_fd) == -1) { safe_close(tty_fd, __FILE__, __LINE__); return PyErr_SetFromErrno(PyExc_OSError); } - if (stdout_fd > -1 && safe_dup2(tty_fd, stdout_fd) == -1) { safe_close(tty_fd, __FILE__, __LINE__); return PyErr_SetFromErrno(PyExc_OSError); } - if (stderr_fd > -1 && safe_dup2(tty_fd, stderr_fd) == -1) { safe_close(tty_fd, __FILE__, __LINE__); return PyErr_SetFromErrno(PyExc_OSError); } - safe_close(tty_fd, __FILE__, __LINE__); + int tty_fd=-1, stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; + const char *tty_name; + if (!PyArg_ParseTuple(args, "s|iiii", &tty_name, &tty_fd, &stdin_fd, &stdout_fd, &stderr_fd)) return NULL; + int tfd = safe_open(tty_name, O_RDWR, 0); +#define cleanup() if (tfd >= 0) safe_close(tfd, __FILE__, __LINE__); if (tty_fd >= 0) safe_close(tty_fd, __FILE__, __LINE__); +#define fail() { cleanup(); return PyErr_SetFromErrno(PyExc_OSError); } + if (tfd < 0) { cleanup(); return PyErr_SetFromErrnoWithFilename(PyExc_OSError, tty_name); } + if (tty_fd < 0) { tty_fd = tfd; tfd = -1; } + if (ioctl(tty_fd, TIOCSCTTY, 0) == -1) fail(); + if (stdin_fd > -1 && safe_dup2(tty_fd, stdin_fd) == -1) fail(); + if (stdout_fd > -1 && safe_dup2(tty_fd, stdout_fd) == -1) fail(); + if (stderr_fd > -1 && safe_dup2(tty_fd, stderr_fd) == -1) fail(); + cleanup(); +#undef cleanup +#undef fail Py_RETURN_NONE; } diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index dbe164b3e..71e94f15a 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1395,7 +1395,7 @@ def sigqueue(pid: int, signal: int, value: int) -> None: pass -def establish_controlling_tty(tty_fd: int, stdin: int = -1, stdout: int = -1, stderr: int = -1) -> None: +def establish_controlling_tty(tty_name: str, tty_fd: int = -1, stdin: int = -1, stdout: int = -1, stderr: int = -1) -> None: pass diff --git a/kitty/prewarm.py b/kitty/prewarm.py index 4f3e4baa1..93e457faa 100644 --- a/kitty/prewarm.py +++ b/kitty/prewarm.py @@ -351,7 +351,7 @@ def fork(shm_address: str, free_non_child_resources: Callable[[], None]) -> Tupl if tty_name: sys.__stdout__.flush() sys.__stderr__.flush() - establish_controlling_tty(os.open(tty_name, os.O_RDWR | os.O_CLOEXEC, 0), sys.__stdin__.fileno(), sys.__stdout__.fileno(), sys.__stderr__.fileno()) + establish_controlling_tty(tty_name, -1, sys.__stdin__.fileno(), sys.__stdout__.fileno(), sys.__stderr__.fileno()) os.close(w) if shm.unlink_on_exit: child_main(cmd, ready_fd_read) @@ -490,7 +490,7 @@ class SocketChild: sys.__stdout__.flush() sys.__stderr__.flush() establish_controlling_tty( - self.tty_fd, + os.ttyname(self.tty_fd), self.tty_fd, sys.__stdin__.fileno() if self.stdin < 0 else -1, sys.__stdout__.fileno() if self.stdout < 0 else -1, sys.__stderr__.fileno() if self.stderr < 0 else -1)