self->max_length = max_length;
}
+size_t pakfire_buffer_length(struct pakfire_buffer* self) {
+ return self->used;
+}
+
+int pakfire_buffer_is_empty(struct pakfire_buffer* self) {
+ return (self->used == 0);
+}
+
+int pakfire_buffer_is_full(struct pakfire_buffer* self) {
+ // Cannot be full if we don't have no maximum size
+ if (!self->max_length)
+ return 0;
+
+ return (self->used >= self->max_length);
+}
+
void pakfire_buffer_free(struct pakfire_buffer* buffer) {
if (buffer->data)
free(buffer->data);
return 0;
}
-int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd) {
+int pakfire_buffer_pop(struct pakfire_buffer* self, size_t length) {
+ // Check if we actually have enough data
+ if (self->used < length)
+ return -EINVAL;
+
+ memmove(self->data, self->data + length, self->used - length);
+ self->used -= length;
+
+ // Shrink the buffer if we need to
+ return pakfire_buffer_shrink(self);
+}
+
+int pakfire_buffer_read(struct pakfire_buffer* self, int fd) {
+ ssize_t total_bytes_read = 0;
ssize_t bytes_read = 0;
int r;
// Read into the buffer
bytes_read = read(fd, self->data + self->used, self->length - self->used);
if (bytes_read < 0)
- return bytes_read;
+ return -errno;
+
+ // Update the total counter
+ total_bytes_read += bytes_read;
// We now use more space
self->used += bytes_read;
break;
}
- return 0;
+ return total_bytes_read;
}
-int pakfire_buffer_pop(struct pakfire_buffer* self, size_t length) {
- // Check if we actually have enough data
- if (self->used < length)
- return -EINVAL;
+int pakfire_buffer_write(struct pakfire_buffer* self, int fd) {
+ ssize_t bytes_written = 0;
+ int r;
- memmove(self->data, self->data + length, self->used - length);
- self->used -= length;
+ // Do nothing if the buffer is empty
+ if (!self->used)
+ return 0;
- // Shrink the buffer if we need to
- return pakfire_buffer_shrink(self);
+ // Write as much data as possible
+ bytes_written = write(fd, self->data, self->used);
+ if (bytes_written < 0)
+ return -errno;
+
+ // Remove any written data
+ r = pakfire_buffer_pop(self, bytes_written);
+ if (r < 0)
+ return r;
+
+ return bytes_written;
}
size_t pakfire_buffer_find_line(struct pakfire_buffer* self) {
#include <systemd/sd-event.h>
+#include <pakfire/buffer.h>
#include <pakfire/ctx.h>
#include <pakfire/file.h>
#include <pakfire/filelist.h>
unsigned close_fd:1;
// Buffer
- char buffer[MAX_LINE_LENGTH];
- size_t buffered;
+ struct pakfire_buffer buffer;
// Terminal Attributes
struct termios attrs;
return 0;
}
-static int pakfire_pty_buffer_is_full(struct pakfire_pty* pty, const struct pakfire_pty_stdio* stdio) {
- if (stdio->buffered >= sizeof(stdio->buffer))
- return 1;
-
- return 0;
-}
-
-static int pakfire_pty_buffer_has_data(struct pakfire_pty* pty, const struct pakfire_pty_stdio* stdio) {
- if (stdio->buffered)
- return 1;
-
- return 0;
-}
-
static int pakfire_pty_disconnect(struct pakfire_pty* pty) {
DEBUG(pty->ctx, "Disconnecting the PTY\n");
return 1;
// We still have data in the buffer
- if (pakfire_pty_buffer_has_data(pty, &pty->stdout))
+ if (!pakfire_buffer_is_empty(&pty->stdout.buffer))
return 0;
// There is still data in the PTY buffer
return 0;
}
-/*
- Reads as much data as possible into the buffer
-*/
-static int pakfire_pty_fill_buffer(struct pakfire_pty* pty, int fd, struct pakfire_pty_stdio* stdio) {
- ssize_t bytes_read = 0;
-
- // Read from the file descriptor
- bytes_read = read(fd, stdio->buffer + stdio->buffered, sizeof(stdio->buffer) - stdio->buffered);
-
- // Abort on errors
- if (bytes_read < 0)
- return -errno;
-
- // Successful read
- stdio->buffered += bytes_read;
-
- return bytes_read;
-}
-
-/*
- Writes as much data as possible from the buffer
-*/
-static int pakfire_pty_drain_buffer(struct pakfire_pty* pty, int fd, struct pakfire_pty_stdio* stdio) {
- ssize_t bytes_written = 0;
-
- // Write to the file descriptor
- bytes_written = write(fd, stdio->buffer, stdio->buffered);
-
- // Abort on error
- if (bytes_written < 0)
- return -errno;
-
- // Successful write
- memmove(stdio->buffer, stdio->buffer + bytes_written, stdio->buffered - bytes_written);
- stdio->buffered -= bytes_written;
-
- return bytes_written;
-}
-
/*
This function handles the forwarding between the different pipes...
*/
// Read from standard input if we are asked to read and
// there is still space in the buffer..
if ((pty->stdin.io & PAKFIRE_PTY_READY_TO_READ)
- && !pakfire_pty_buffer_is_full(pty, &pty->stdin)) {
- DEBUG(pty->ctx, "Reading from standard input...\n");
-
- // Fill up the buffer
- r = pakfire_pty_fill_buffer(pty, pty->stdin.fd, &pty->stdin);
+ && !pakfire_buffer_is_full(&pty->stdin.buffer)) {
+ r = pakfire_buffer_read(&pty->stdin.buffer, pty->stdin.fd);
if (r < 0) {
switch (-r) {
// We have been signaled, that currently there is no data available to read
// Write to the master if there is any input data
if ((pty->master.io & PAKFIRE_PTY_READY_TO_WRITE)
- && pakfire_pty_buffer_has_data(pty, &pty->stdin)) {
- DEBUG(pty->ctx, "Writing to master...\n");
-
- // Drain the input buffer...
- r = pakfire_pty_drain_buffer(pty, pty->master.fd, &pty->stdin);
+ && !pakfire_buffer_is_empty(&pty->stdin.buffer)) {
+ r = pakfire_buffer_write(&pty->stdin.buffer, pty->master.fd);
if (r < 0) {
switch (-r) {
// We have been signaled that we cannot write any more data...
// Read from the master until the buffer is full
if ((pty->master.io & PAKFIRE_PTY_READY_TO_READ)
- && !pakfire_pty_buffer_is_full(pty, &pty->stdout)) {
- DEBUG(pty->ctx, "Reading from master...\n");
-
- r = pakfire_pty_fill_buffer(pty, pty->master.fd, &pty->stdout);
+ && !pakfire_buffer_is_full(&pty->stdout.buffer)) {
+ r = pakfire_buffer_read(&pty->stdout.buffer, pty->master.fd);
if (r < 0) {
switch (-r) {
// We have been signalled that we cannot send any more data...
// Write to standard output until the buffer is drained
if ((pty->stdout.io & PAKFIRE_PTY_READY_TO_WRITE)
- && pakfire_pty_buffer_has_data(pty, &pty->stdout)) {
- DEBUG(pty->ctx, "Writing to standard output...\n");
-
- r = pakfire_pty_drain_buffer(pty, pty->stdout.fd, &pty->stdout);
+ && !pakfire_buffer_is_empty(&pty->stdout.buffer)) {
+ r = pakfire_buffer_write(&pty->stdout.buffer, pty->stdout.fd);
if (r < 0) {
switch (-r) {
// We have been signalled that we are no longer able to write...
DEBUG(pty->ctx, "Something hung up...\n");
// Terminate the event loop after all buffers have been emptied or cannot be emptied
- if ((!pakfire_pty_buffer_has_data(pty, &pty->stdout)
+ if ((pakfire_buffer_is_empty(&pty->stdout.buffer)
|| (pty->stdout.io & PAKFIRE_PTY_HANGUP))
- && (!pakfire_pty_buffer_has_data(pty, &pty->stdin)
+ && (pakfire_buffer_is_empty(&pty->stdin.buffer)
|| (pty->stdin.io & PAKFIRE_PTY_HANGUP)))
return pakfire_pty_done(pty, 0);
}
if (pty->exit_event)
sd_event_source_unref(pty->exit_event);
+ // Free buffers
+ pakfire_buffer_free(&pty->stdin.buffer);
+ pakfire_buffer_free(&pty->stdout.buffer);
+
if (pty->loop)
sd_event_unref(pty->loop);
if (pty->ctx)
goto ERROR;
}
+ // Set buffer sizes
+ pakfire_buffer_set_max_length(&p->stdin.buffer, MAX_LINE_LENGTH);
+ pakfire_buffer_set_max_length(&p->stdout.buffer, MAX_LINE_LENGTH);
+
// Return the pointer
*pty = p;