]> git.ipfire.org Git - pakfire.git/commitdiff
pty: Add a function to set up interactive mode
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 20 Mar 2025 11:30:38 +0000 (11:30 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 20 Mar 2025 11:30:38 +0000 (11:30 +0000)
This way we can split off the initialization code a little bit better
from the main initialization of the PTY object.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/jail.c
src/pakfire/pty.c
src/pakfire/pty.h

index d1d992dd901e4c6d32293015c7d5a9cbc176e40f..b9da3124b93e716cf3ea05d3c1af4877d19e0bc5 100644 (file)
@@ -1344,7 +1344,6 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail,
                pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
                pakfire_pty_stdout_callback stdout_callback, void* stdout_data,
                char** output, size_t* output_length) {
-       int pty_flags = 0;
        int r;
 
        // We cannot have both, an output callback and buffer
@@ -1390,10 +1389,17 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail,
                goto ERROR;
        }
 
+       // Setup the PTY
+       r = pakfire_pty_create(&ctx.pty, jail->ctx, ctx.loop);
+       if (r < 0)
+               goto ERROR;
+
        // Are we running in interactive mode?
        if (pakfire_jail_exec_has_flag(&ctx, PAKFIRE_JAIL_INTERACTIVE)) {
                // Make the PTY interactive
-               pty_flags |= PAKFIRE_PTY_INTERACTIVE;
+               r = pakfire_pty_interactive(ctx.pty);
+               if (r < 0)
+                       goto ERROR;
 
                // Enable networking
                ctx.flags |= PAKFIRE_JAIL_HAS_NETWORKING;
@@ -1409,6 +1415,14 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail,
        } else if (stdout_callback) {
                // Nothing
 
+       // Capture Output?
+       } else if (output) {
+               r = pakfire_pty_capture_output(ctx.pty, output, output_length);
+               if (r < 0) {
+                       ERROR(jail->ctx, "Failed to set up output capture: %s\n", strerror(-r));
+                       goto ERROR;
+               }
+
        // Otherwise we dump everything to the console
        } else {
                // XXX Need to find a solution about what to do here...
@@ -1424,20 +1438,6 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail,
                goto ERROR;
        }
 
-       // Setup the PTY
-       r = pakfire_pty_create(&ctx.pty, jail->ctx, ctx.loop, pty_flags);
-       if (r)
-               goto ERROR;
-
-       // Capture Output?
-       if (output) {
-               r = pakfire_pty_capture_output(ctx.pty, output, output_length);
-               if (r < 0) {
-                       ERROR(jail->ctx, "Failed to set up output capture: %s\n", strerror(-r));
-                       goto ERROR;
-               }
-       }
-
        // Configure the callbacks
        if (stdin_callback)
                pakfire_pty_set_stdin_callback(ctx.pty, stdin_callback, stdin_data);
index edbb100d7faa33347829a4bf110d23bc40067fe5..b565a6b895160d699b848cd7659f06cff32a4450 100644 (file)
@@ -76,9 +76,6 @@ struct pakfire_pty {
        struct pakfire_ctx* ctx;
        int nrefs;
 
-       // Flags
-       int flags;
-
        // Event Loop
        sd_event* loop;
 
@@ -113,10 +110,6 @@ struct pakfire_pty {
        FILE* output;
 };
 
-static int pakfire_pty_has_flag(struct pakfire_pty* pty, int flag) {
-       return pty->flags & flag;
-}
-
 static int pakfire_pty_same_inode(struct pakfire_pty* pty, int fd1, int fd2) {
        struct stat stat1;
        struct stat stat2;
@@ -1034,50 +1027,6 @@ static int pakfire_pty_setup_forwarding(struct pakfire_pty* pty) {
        // Mark as forwarding
        pty->state = PAKFIRE_PTY_STATE_FORWARDING;
 
-       // Connect to standard input
-       if (pakfire_pty_has_flag(pty, PAKFIRE_PTY_INTERACTIVE)) {
-               pty->stdin.fd = pakfire_pty_reopen(pty, STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
-               if (pty->stdin.fd < 0) {
-                       DEBUG(pty->ctx, "Could not re-open standard input: %s. Ignoring.\n", strerror(-pty->stdin.fd));
-
-                       // Use the original file descriptor
-                       pty->stdin.fd = STDIN_FILENO;
-
-               // Request to close the file descriptor afterwards
-               } else {
-                       pty->stdin.close_fd = 1;
-               }
-       }
-
-       // Create a buffer to capture the output in
-       if (pakfire_pty_has_flag(pty, PAKFIRE_PTY_CAPTURE_OUTPUT)) {
-               pty->stdout.fd = memfd_create("pty-output", MFD_CLOEXEC);
-               if (pty->stdout.fd < 0) {
-                       ERROR(pty->ctx, "Could not create the output buffer: %m\n");
-                       return -errno;
-               }
-
-               // Map any CRNL to NL
-               pty->stdout.io |= PAKFIRE_PTY_MAP_CRNL;
-
-               // Close the buffer in the end
-               pty->stdout.close_fd = 1;
-
-       // Connect to standard output
-       } else if (pakfire_pty_has_flag(pty, PAKFIRE_PTY_INTERACTIVE)) {
-               pty->stdout.fd = pakfire_pty_reopen(pty, STDOUT_FILENO, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
-               if (pty->stdout.fd < 0) {
-                       DEBUG(pty->ctx, "Could not re-open standard output: %s. Ignoring.\n", strerror(-pty->stdout.fd));
-
-                       // Use the original file descriptor
-                       pty->stdout.fd = STDOUT_FILENO;
-
-               // Request to close the file descriptor afterwards
-               } else {
-                       pty->stdout.close_fd = 1;
-               }
-       }
-
        // Copy the terminal dimensions to the PTY
        if (isatty(pty->stdout.fd)) {
                // Fetch dimensions
@@ -1275,8 +1224,7 @@ static void pakfire_pty_free(struct pakfire_pty* pty) {
        free(pty);
 }
 
-int pakfire_pty_create(struct pakfire_pty** pty, struct pakfire_ctx* ctx,
-               sd_event* loop, int flags) {
+int pakfire_pty_create(struct pakfire_pty** pty, struct pakfire_ctx* ctx, sd_event* loop) {
        struct pakfire_pty* p = NULL;
        int r;
 
@@ -1294,19 +1242,6 @@ int pakfire_pty_create(struct pakfire_pty** pty, struct pakfire_ctx* ctx,
        // Store a reference to the event loop
        p->loop = sd_event_ref(loop);
 
-       // Store the flags
-       p->flags = flags;
-
-       // Connect stdout if we want to capture the output
-       if (pakfire_pty_has_flag(p, PAKFIRE_PTY_CAPTURE_OUTPUT))
-               p->stdout.io |= PAKFIRE_PTY_CONNECT;
-
-       // Connect everything when we are in interactive mode
-       else if (pakfire_pty_has_flag(p, PAKFIRE_PTY_INTERACTIVE)) {
-               p->stdin.io  |= PAKFIRE_PTY_CONNECT;
-               p->stdout.io |= PAKFIRE_PTY_CONNECT;
-       }
-
        // Initialize the master file descriptor
        p->master.fd = -EBADF;
 
@@ -1541,6 +1476,47 @@ int pakfire_pty_capture_output(struct pakfire_pty* self, char** output, size_t*
        return 0;
 }
 
+/*
+       Interactive Mode
+*/
+int pakfire_pty_interactive(struct pakfire_pty* self) {
+       // Fail if something is already open
+       if (self->stdin.fd >= 0 || self->stdout.fd >= 0)
+               return -ENOTSUP;
+
+       // Open standard input
+       self->stdin.fd = pakfire_pty_reopen(self, STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+       if (self->stdin.fd < 0) {
+               DEBUG(self->ctx, "Could not re-open standard input: %s. Ignoring.\n", strerror(-self->stdin.fd));
+
+               // Use the original file descriptor
+               self->stdin.fd = STDIN_FILENO;
+
+       // Request to close the file descriptor afterwards
+       } else {
+               self->stdin.close_fd = 1;
+       }
+
+       // Open standard output
+       self->stdout.fd = pakfire_pty_reopen(self, STDOUT_FILENO, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+       if (self->stdout.fd < 0) {
+               DEBUG(self->ctx, "Could not re-open standard output: %s. Ignoring.\n", strerror(-self->stdout.fd));
+
+               // Use the original file descriptor
+               self->stdout.fd = STDOUT_FILENO;
+
+       // Request to close the file descriptor afterwards
+       } else {
+               self->stdout.close_fd = 1;
+       }
+
+       // Connect everything
+       self->stdin.io  |= PAKFIRE_PTY_CONNECT;
+       self->stdout.io |= PAKFIRE_PTY_CONNECT;
+
+       return 0;
+}
+
 /*
        Standard Input/Output Callbacks
 */
index c4af39b48b16597079d3e30d44224b07865cecf5..a45e53f0f40bdb8587d3438427413838ee1eaffc 100644 (file)
 
 struct pakfire_pty;
 
-enum pakfire_pty_flags {
-       PAKFIRE_PTY_NONE           = 0,
-       PAKFIRE_PTY_INTERACTIVE    = (1 << 0),
-       PAKFIRE_PTY_CAPTURE_OUTPUT = (1 << 1),
-};
-
-int pakfire_pty_create(struct pakfire_pty** pty,
-       struct pakfire_ctx* ctx, sd_event* loop, int flags);
+int pakfire_pty_create(struct pakfire_pty** pty, struct pakfire_ctx* ctx, sd_event* loop);
 
 struct pakfire_pty* pakfire_pty_ref(struct pakfire_pty* pty);
 struct pakfire_pty* pakfire_pty_unref(struct pakfire_pty* pty);
 
 int pakfire_pty_open(struct pakfire_pty* pty);
 
+int pakfire_pty_interactive(struct pakfire_pty* pty);
 int pakfire_pty_capture_output(struct pakfire_pty* pty, char** output, size_t* length);
 
 typedef ssize_t (*pakfire_pty_stdin_callback)(