From: Michael Tremer Date: Mon, 24 Mar 2025 16:49:40 +0000 (+0000) Subject: pty: Use our own buffer implementation X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=adecf64ebf40f9f23a7e07f89ee3820e5d894e98;p=pakfire.git pty: Use our own buffer implementation Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/buffer.c b/src/pakfire/buffer.c index ae8fd113..ddf5543e 100644 --- a/src/pakfire/buffer.c +++ b/src/pakfire/buffer.c @@ -34,6 +34,22 @@ void pakfire_buffer_set_max_length(struct pakfire_buffer* self, size_t max_lengt 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); @@ -108,7 +124,20 @@ int pakfire_buffer_push(struct pakfire_buffer* self, const char* data, size_t le 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; @@ -122,7 +151,10 @@ int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd) { // 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; @@ -132,19 +164,28 @@ int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd) { 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) { diff --git a/src/pakfire/buffer.h b/src/pakfire/buffer.h index 6c69afdd..97a521a1 100644 --- a/src/pakfire/buffer.h +++ b/src/pakfire/buffer.h @@ -34,13 +34,18 @@ struct pakfire_buffer { void pakfire_buffer_set_max_length(struct pakfire_buffer* buffer, size_t max_length); +size_t pakfire_buffer_length(struct pakfire_buffer* self); +int pakfire_buffer_is_empty(struct pakfire_buffer* self); +int pakfire_buffer_is_full(struct pakfire_buffer* self); + void pakfire_buffer_free(struct pakfire_buffer* buffer); int pakfire_buffer_push(struct pakfire_buffer* self, const char* data, size_t length); -int pakfire_buffer_push_from_fd(struct pakfire_buffer* self, int fd); - int pakfire_buffer_pop(struct pakfire_buffer* self, size_t length); +int pakfire_buffer_read(struct pakfire_buffer* self, int fd); +int pakfire_buffer_write(struct pakfire_buffer* self, int fd); + size_t pakfire_buffer_find_line(struct pakfire_buffer* self); #endif /* PAKFIRE_BUFFER_H */ diff --git a/src/pakfire/log_stream.c b/src/pakfire/log_stream.c index 7148f0a7..01858bc2 100644 --- a/src/pakfire/log_stream.c +++ b/src/pakfire/log_stream.c @@ -277,7 +277,7 @@ static int __pakfire_log_stream(sd_event_source* s, int fd, uint32_t events, voi if (events & EPOLLIN) { // Fill the buffer - r = pakfire_buffer_push_from_fd(&stream->buffer, fd); + r = pakfire_buffer_read(&stream->buffer, fd); if (r < 0) return r; diff --git a/src/pakfire/pty.c b/src/pakfire/pty.c index b830f84b..8541c50d 100644 --- a/src/pakfire/pty.c +++ b/src/pakfire/pty.c @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -44,8 +45,7 @@ struct pakfire_pty_stdio { unsigned close_fd:1; // Buffer - char buffer[MAX_LINE_LENGTH]; - size_t buffered; + struct pakfire_buffer buffer; // Terminal Attributes struct termios attrs; @@ -197,20 +197,6 @@ static int pakfire_pty_store_attrs(struct pakfire_pty* pty, 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"); @@ -246,7 +232,7 @@ static int pakfire_pty_drained(struct pakfire_pty* pty) { 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 @@ -299,45 +285,6 @@ static int pakfire_pty_done(struct pakfire_pty* pty, int code) { 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... */ @@ -374,11 +321,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) { // 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 @@ -429,11 +373,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) { // 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... @@ -471,10 +412,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) { // 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... @@ -525,10 +464,8 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) { // 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... @@ -570,9 +507,9 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) { 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); } @@ -1092,6 +1029,10 @@ static void pakfire_pty_free(struct pakfire_pty* pty) { 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) @@ -1141,6 +1082,10 @@ int pakfire_pty_create(struct pakfire_pty** pty, struct pakfire_ctx* ctx, sd_eve 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;