From 70245c2cd5c34586fa91eb784e58471869ba66bd Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 17 Sep 2018 13:43:27 +0100 Subject: swaybar: rewrite text protocol handling This now uses getline to correctly handle multiple or long statuses. It also removes the struct text_protocol_state and moves its members into the status_line struct. --- include/swaybar/status_line.h | 8 ++------ swaybar/status_line.c | 40 ++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 150267cd..857948a5 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -12,11 +12,6 @@ enum status_protocol { PROTOCOL_I3BAR, }; -struct text_protocol_state { - char *buffer; - size_t buffer_size; -}; - enum json_node_type { JSON_NODE_UNKNOWN, JSON_NODE_ARRAY, @@ -63,7 +58,8 @@ struct status_line { const char *text; struct wl_list blocks; // i3bar_block::link - struct text_protocol_state text_state; + char *buffer; + size_t buffer_size; struct i3bar_protocol_state i3bar_state; }; diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 09ed2375..54a68b40 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -30,27 +30,17 @@ void status_error(struct status_line *status, const char *text) { } bool status_handle_readable(struct status_line *status) { + ssize_t read_bytes = 1; char *line; switch (status->protocol) { - case PROTOCOL_ERROR: - return false; case PROTOCOL_I3BAR: if (i3bar_handle_readable(status) > 0) { return true; } break; - case PROTOCOL_TEXT: - line = read_line_buffer(status->read, - status->text_state.buffer, status->text_state.buffer_size); - if (!line) { - status_error(status, "[error reading from status command]"); - } else { - status->text = line; - } - return true; case PROTOCOL_UNDEF: line = read_line_buffer(status->read, - status->text_state.buffer, status->text_state.buffer_size); + status->buffer, status->buffer_size); if (!line) { status_error(status, "[error reading from status command]"); return false; @@ -81,7 +71,7 @@ bool status_handle_readable(struct status_line *status) { } status->protocol = PROTOCOL_I3BAR; - free(status->text_state.buffer); + free(status->buffer); wl_list_init(&status->blocks); status->i3bar_state.buffer_size = 4096; status->i3bar_state.buffer = @@ -91,14 +81,32 @@ bool status_handle_readable(struct status_line *status) { status->text = line; } return true; + case PROTOCOL_TEXT: + errno = 0; + while (true) { + if (status->buffer[read_bytes - 1] == '\n') { + status->buffer[read_bytes - 1] = '\0'; + } + read_bytes = getline(&status->buffer, + &status->buffer_size, status->read); + if (errno == EAGAIN) { + clearerr(status->read); + return true; + } else if (errno) { + status_error(status, "[error reading from status command]"); + return true; + } + } + default: + return false; } return false; } struct status_line *status_line_init(char *cmd) { struct status_line *status = calloc(1, sizeof(struct status_line)); - status->text_state.buffer_size = 8192; - status->text_state.buffer = malloc(status->text_state.buffer_size); + status->buffer_size = 8192; + status->buffer = malloc(status->buffer_size); int pipe_read_fd[2]; int pipe_write_fd[2]; @@ -148,7 +156,7 @@ void status_line_free(struct status_line *status) { break; } default: - free(status->text_state.buffer); + free(status->buffer); break; } free(status); -- cgit v1.2.3-70-g09d2