]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Setup PTY in the master process and add it to the event loop
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 8 Dec 2023 17:22:43 +0000 (17:22 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 8 Dec 2023 17:22:43 +0000 (17:22 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/jail.c

index 6313d894f1c647ab9cf9435541594a95984e9c6d..bdf3f320d545b57b264a183a497dcf698108ec72 100644 (file)
@@ -862,12 +862,102 @@ static int pakfire_jail_epoll_add_fd(struct pakfire_jail* jail, int epollfd, int
        return 0;
 }
 
+// PTY Forwarding
+
+static int pakfire_jail_enable_raw_mode(struct pakfire_jail* jail,
+               struct pakfire_jail_pty_stdio* stdio) {
+       struct termios raw_attrs;
+       int r;
+
+       // Fetch all attributes
+       r = tcgetattr(stdio->fd, &stdio->attrs);
+       if (r) {
+               CTX_ERROR(jail->ctx, "Could not fetch terminal attributes from fd %d: %s\n",
+                       stdio->fd, strerror(errno));
+               return -errno;
+       }
+
+       // Copy all attributes
+       raw_attrs = stdio->attrs;
+
+       // Make it RAW
+       cfmakeraw(&raw_attrs);
+
+       // Restore the attributes
+       r = tcsetattr(stdio->fd, TCSANOW, &raw_attrs);
+       if (r) {
+               CTX_ERROR(jail->ctx, "Could not restore terminal attributes for fd %d: %s\n",
+                       stdio->fd, strerror(errno));
+               return -errno;
+       }
+
+       return 0;
+}
+
+static void pakfire_jail_restore_attrs(struct pakfire_jail* jail,
+               const struct pakfire_jail_pty_stdio* stdio) {
+       int r;
+
+       // Restore the attributes
+       r = tcsetattr(stdio->fd, TCSANOW, &stdio->attrs);
+       if (r) {
+               CTX_DEBUG(jail->ctx, "Could not restore terminal attributes for %d, ignoring: %s\n",
+                       stdio->fd, strerror(errno));
+       }
+}
+
 static int pakfire_jail_setup_pty_forwarding(struct pakfire_jail* jail,
                struct pakfire_jail_exec* ctx, const int epollfd, const int fd) {
+       struct winsize size;
+       int r;
+
+       CTX_DEBUG(jail->ctx, "Setting up PTY forwarding on fd %d\n", fd);
+
        // Store the file descriptor
-       ctx->consolefd = fd;
+       ctx->pty.master.fd = fd;
 
-       // XXX TODO
+       // Configure stdin/stdout
+       ctx->pty.stdin.fd  = STDIN_FILENO;
+       ctx->pty.stdout.fd = STDOUT_FILENO;
+
+       // Fetch dimensions
+       r = ioctl(ctx->pty.stdout.fd, TIOCGWINSZ, &size);
+       if (r) {
+               CTX_ERROR(jail->ctx, "Failed to determine terminal dimensions: %s\n", strerror(errno));
+               return -errno;
+       }
+
+       // Set dimensions
+       r = ioctl(ctx->pty.master.fd, TIOCSWINSZ, &size);
+       if (r) {
+               CTX_ERROR(jail->ctx, "Failed setting dimensions: %s\n", strerror(errno));
+               return -errno;
+       }
+
+       // Enable RAW mode on standard input
+       r = pakfire_jail_enable_raw_mode(jail, &ctx->pty.stdin);
+       if (r)
+               return r;
+
+       // Enable RAW mode on standard output
+       r = pakfire_jail_enable_raw_mode(jail, &ctx->pty.stdout);
+       if (r)
+               return r;
+
+       // Add the master to the event loop
+       r = pakfire_jail_epoll_add_fd(jail, epollfd, ctx->pty.master.fd, EPOLLIN|EPOLLOUT|EPOLLET);
+       if (r)
+               return r;
+
+       // Add standard input to the event loop
+       r = pakfire_jail_epoll_add_fd(jail, epollfd, ctx->pty.stdin.fd, EPOLLIN|EPOLLET);
+       if (r)
+               return r;
+
+       // Add standard output to the event loop
+       r = pakfire_jail_epoll_add_fd(jail, epollfd, ctx->pty.stdout.fd, EPOLLOUT|EPOLLET);
+       if (r)
+               return r;
 
        return 0;
 }
@@ -1129,6 +1219,10 @@ ERROR:
        if (timerfd >= 0)
                close(timerfd);
 
+       // Restore any changed terminal attributes
+       pakfire_jail_restore_attrs(jail, &ctx->pty.stdin);
+       pakfire_jail_restore_attrs(jail, &ctx->pty.stdout);
+
        return r;
 }