#include <pakfire/ctx.h>
#include <pakfire/pty.h>
+#include <pakfire/string.h>
#include <pakfire/util.h>
struct pakfire_pty_stdio {
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...
*/
// 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)) {