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;
}
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;
}