/*
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;
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;
// 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;
}
// 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;
}
}
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) {