]> git.ipfire.org Git - pakfire.git/commitdiff
pty: Re-open standard input/output
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 6 Oct 2024 14:58:27 +0000 (14:58 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 6 Oct 2024 14:58:27 +0000 (14:58 +0000)
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 <michael.tremer@ipfire.org>
src/libpakfire/pty.c

index 67b49e1732a69aa603a2f2d1b3076bd03ada0ebf..6e3d2a7983331777b877b7db2d467db94c96eaed 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <pakfire/ctx.h>
 #include <pakfire/pty.h>
+#include <pakfire/string.h>
 #include <pakfire/util.h>
 
 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)) {