]> git.ipfire.org Git - pakfire.git/commitdiff
pty: Be less smart about the forwarding and make it work again
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 6 Oct 2024 12:39:09 +0000 (12:39 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 6 Oct 2024 12:39:09 +0000 (12:39 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/pty.c

index 098b45cd1a62144572cccf347de6ad8fd6ef771e..0d63d8bc3599c7eb579b1c533de8a80621dff605 100644 (file)
@@ -79,70 +79,68 @@ struct pakfire_pty {
 /*
        Reads as much data as possible into the buffer
 */
-static int pakfire_pty_fill_buffer(struct pakfire_pty* pty, struct pakfire_pty_stdio* stdio) {
+static int pakfire_pty_fill_buffer(struct pakfire_pty* pty, int fd, struct pakfire_pty_stdio* stdio) {
        int r;
 
-       for (;;) {
-               // Skip this if there is not space left in the buffer
-               if (stdio->buffered >= sizeof(stdio->buffer))
-                       return 0;
-
-               // Fill the buffer
-               r = read(stdio->fd, stdio->buffer + stdio->buffered, sizeof(stdio->buffer) - stdio->buffered);
-               if (r < 0) {
-                       switch (errno) {
-                               case EAGAIN:
-                               case EIO:
-                                       return 0;
-
-                               default:
-                                       return -errno;
-                       }
+       // Skip this if there is not space left in the buffer
+       if (stdio->buffered >= sizeof(stdio->buffer))
+               return 0;
 
-               // EOF
-               } else if (r == 0) {
-                       return 0;
+       // Fill the buffer
+       r = read(fd, stdio->buffer + stdio->buffered, sizeof(stdio->buffer) - stdio->buffered);
+       if (r < 0) {
+               switch (errno) {
+                       case EAGAIN:
+                       case EIO:
+                               break;
 
-               // Successful read
-               } else {
-                       stdio->buffered += r;
+                       default:
+                               return -errno;
                }
+
+       // EOF
+       } else if (r == 0) {
+               return 0;
+
+       // Successful read
+       } else {
+               stdio->buffered += r;
        }
+
+       return 0;
 }
 
 /*
        Writes as much data as possible from the buffer
 */
-static int pakfire_pty_drain_buffer(struct pakfire_pty* pty, struct pakfire_pty_stdio* stdio) {
+static int pakfire_pty_drain_buffer(struct pakfire_pty* pty, int fd, struct pakfire_pty_stdio* stdio) {
        int r;
 
        // Do not try to write to an invalid file descriptor
-       if (stdio->fd < 0)
+       if (fd < 0)
                return 0;
 
-       for (;;) {
-               // Nothing to do if the buffer is empty
-               if (!stdio->buffered)
-                       return 0;
-
-               // Drain the buffer
-               r = write(stdio->fd, stdio->buffer, stdio->buffered);
-               if (r < 0) {
-                       switch (errno) {
-                               case EAGAIN:
-                               case EIO:
-                                       return 0;
-
-                               default:
-                                       return -errno;
-                       }
+       // Nothing to do if the buffer is empty
+       if (!stdio->buffered)
+               return 0;
 
-               // Successful write
-               } else {
-                       memmove(stdio->buffer, stdio->buffer + r, stdio->buffered - r);
+       // Drain the buffer
+       r = write(fd, stdio->buffer, stdio->buffered);
+       if (r < 0) {
+               switch (errno) {
+                       case EAGAIN:
+                       case EIO:
+                               break;
 
-                       stdio->buffered -= r;
+                       default:
+                               return -errno;
                }
+
+       // Successful write
+       } else {
+               memmove(stdio->buffer, stdio->buffer + r, stdio->buffered - r);
+
+               stdio->buffered -= r;
        }
 
        return 0;
@@ -157,7 +155,7 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
        while (pty->master.io || pty->stdin.io || pty->stdout.io) {
                // Read from standard input
                if (pty->stdin.io & PAKFIRE_PTY_READY_TO_READ) {
-                       r = pakfire_pty_fill_buffer(pty, &pty->stdin);
+                       r = pakfire_pty_fill_buffer(pty, pty->stdin.fd, &pty->stdin);
                        if (r < 0) {
                                CTX_ERROR(pty->ctx, "Failed reading from standard input: %s\n", strerror(-r));
                                return r;
@@ -173,20 +171,21 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
 
                // Write to the master
                if (pty->master.io & PAKFIRE_PTY_READY_TO_WRITE) {
-                       r = pakfire_pty_drain_buffer(pty, &pty->master);
-                       if (r) {
+                       r = pakfire_pty_drain_buffer(pty, pty->master.fd, &pty->stdin);
+                       if (r < 0) {
                                CTX_ERROR(pty->ctx, "Failed writing to the PTY: %s\n", strerror(-r));
                                return r;
                        }
 
                        // We are done writing for now
-                       pty->master.io &= ~PAKFIRE_PTY_READY_TO_WRITE;
+                       if (!pty->stdin.buffered)
+                               pty->master.io &= ~PAKFIRE_PTY_READY_TO_WRITE;
                }
 
                // Read from the master
                if (pty->master.io & PAKFIRE_PTY_READY_TO_READ) {
-                       r = pakfire_pty_fill_buffer(pty, &pty->master);
-                       if (r) {
+                       r = pakfire_pty_fill_buffer(pty, pty->master.fd, &pty->stdout);
+                       if (r < 0) {
                                CTX_ERROR(pty->ctx, "Failed reading from the PTY: %s\n", strerror(-r));
                                return r;
                        }
@@ -201,14 +200,15 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
 
                // Write to standard output
                if (pty->stdout.io & PAKFIRE_PTY_READY_TO_WRITE) {
-                       r = pakfire_pty_drain_buffer(pty, &pty->stdout);
-                       if (r) {
+                       r = pakfire_pty_drain_buffer(pty, pty->stdout.fd, &pty->stdout);
+                       if (r < 0) {
                                CTX_ERROR(pty->ctx, "Failed writing to standard output: %s\n", strerror(-r));
                                return r;
                        }
 
                        // We are done writing for now
-                       pty->stdout.io &= ~PAKFIRE_PTY_READY_TO_WRITE;
+                       if (!pty->stdout.buffered)
+                               pty->stdout.io &= ~PAKFIRE_PTY_READY_TO_WRITE;
                }
        }
 
@@ -288,6 +288,8 @@ static int pakfire_pty_enable_raw_mode(struct pakfire_pty* pty, struct pakfire_p
        if (!isatty(stdio->fd))
                return 0;
 
+       CTX_DEBUG(pty->ctx, "Enabling raw mode on fd %d\n", stdio->fd);
+
        // Store flags
        stdio->flags = fcntl(stdio->fd, F_GETFL);
        if (stdio->flags < 0) {