From: Michael Tremer Date: Sun, 6 Oct 2024 14:58:27 +0000 (+0000) Subject: pty: Re-open standard input/output X-Git-Tag: 0.9.30~1132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=759ad7fbbd1c2db8860eaf65f6ab5ac602466d53;p=pakfire.git pty: Re-open standard input/output This is helpful so that we don't have to worry about resetting the original file descriptors in case we crash unintentionally. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/pty.c b/src/libpakfire/pty.c index 67b49e173..6e3d2a798 100644 --- a/src/libpakfire/pty.c +++ b/src/libpakfire/pty.c @@ -29,6 +29,7 @@ #include #include +#include #include struct pakfire_pty_stdio { @@ -473,6 +474,45 @@ static int pakfire_pty_enable_raw_mode(struct pakfire_pty* pty, struct pakfire_p return 0; } +static int pakfire_pty_reopen(struct pakfire_pty* pty, int fd, int flags) { + char path[PATH_MAX]; + int existing_flags; + off_t offset; + int r; + + // Make the path + r = pakfire_string_format(path, "/proc/self/fd/%d", fd); + if (r < 0) + return r; + + // Fetch flags + existing_flags = fcntl(fd, F_GETFL); + if (existing_flags < 0) + return -errno; + + // Apply O_APPEND if set before + flags |= existing_flags & O_APPEND; + + // Fetch the offset + offset = lseek(fd, 0, SEEK_CUR); + + // Duplicate the file descriptor + fd = open(path, flags); + if (fd < 0) + return fd; + + CTX_DEBUG(pty->ctx, "Re-opened %s as fd %d\n", path, fd); + + // Try to re-apply the offset to the new file descriptor + if (offset > 0) { + r = lseek(fd, offset, SEEK_SET); + if (r < 0) + CTX_DEBUG(pty->ctx, "Failed to apply offset: %m\n"); + } + + return fd; +} + /* Sets up PTY forwarding... */ @@ -485,9 +525,21 @@ static int pakfire_pty_setup_forwarding(struct pakfire_pty* pty) { // Mark as forwarding pty->state = PAKFIRE_PTY_STATE_FORWARDING; - // Connect to standard input/output - pty->stdin.fd = STDIN_FILENO; - pty->stdout.fd = STDOUT_FILENO; + // Connect to standard input + if (!pakfire_pty_has_flag(pty, PAKFIRE_PTY_READ_ONLY)) { + pty->stdin.fd = pakfire_pty_reopen(pty, STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (pty->stdin.fd < 0) { + CTX_ERROR(pty->ctx, "Could not re-open standard input: %s\n", strerror(-pty->stdin.fd)); + return -pty->stdin.fd; + } + } + + // Connect to standard output + pty->stdout.fd = pakfire_pty_reopen(pty, STDOUT_FILENO, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (pty->stdout.fd < 0) { + CTX_ERROR(pty->ctx, "Could not re-open standard output: %s\n", strerror(-pty->stdout.fd)); + return -pty->stdout.fd; + } // Copy the terminal dimensions to the PTY if (isatty(pty->stdout.fd)) {