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
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;
} 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...
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);
struct pakfire_ctx* ctx;
int nrefs;
- // Flags
- int flags;
-
// Event Loop
sd_event* loop;
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;
// 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
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;
// 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;
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
*/
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)(