#############################################################################*/
#include <errno.h>
+#include <ctype.h>
#include <fcntl.h>
#include <systemd/sd-event.h>
#include <pakfire/ctx.h>
#include <pakfire/log_stream.h>
+#define MAX_LINE_LENGTH 16384
+
struct pakfire_log_stream {
struct pakfire_ctx* ctx;
int nrefs;
return NULL;
}
+
+#define pakfire_log_stream_sanitize_line(self, line, buffer, buffer_length) \
+ __pakfire_log_stream_sanitize_line(self, line, sizeof(line), buffer, buffer_length)
+
+static int __pakfire_log_stream_sanitize_line(struct pakfire_log_stream* self,
+ char* line, ssize_t line_length, const char* buffer, ssize_t length) {
+ ssize_t i = 0;
+ int num;
+
+ // The cursor position
+ int cursor = 0;
+
+ while (i < length) {
+ switch (buffer[i]) {
+ // Escape
+ case '\x1b':
+ // Skip the escape character
+ i++;
+
+ // CSI
+ if (i < length && buffer[i] == '[') {
+ i++;
+
+ // Reset number
+ num = 0;
+
+ // Parse the number
+ while (i < length) {
+ // Skip any ';'
+ if (buffer[i] == ';') {
+ i++;
+ continue;
+
+ // Parse any digits
+ } else if (isdigit(buffer[i])) {
+ num = num * 10 + (buffer[i] - '0');
+ i++;
+ continue;
+ }
+
+ // Break on all other characters
+ break;
+ }
+
+ // Parse the command
+ if (i < length) {
+ char command = buffer[i++];
+
+ switch (command) {
+ // Move the cursor to the left
+ case 'D':
+ cursor -= (num > 0) ? num : 1;
+
+ // Don't go too far left
+ if (cursor < 0)
+ cursor = 0;
+ break;
+
+ // Move the cursor to the right
+ case 'C':
+ cursor += (num > 0) ? num : 1;
+
+ // Don't go too far right
+ if (cursor >= length)
+ cursor = length - 1;
+ break;
+
+ // Move to a certain column
+ case 'G':
+ cursor = (num > 0) ? num - 1 : 0;
+
+ // Don't go too far right
+ if (cursor >= length)
+ cursor = length - 1;
+ break;
+
+ // Ignore any other sequences
+ default:
+ break;
+ }
+ }
+ }
+ break;
+
+ // Backspace
+ case '\x08':
+ if (cursor > 0) {
+ cursor--;
+
+ // Erase the previous character
+ line[cursor] = ' ';
+ }
+ i++;
+ break;
+
+ // Carriage Return
+ case '\x0d':
+ // Erase everything up to the cursor
+ memset(line, '\0', cursor);
+
+ cursor = 0;
+ i++;
+ break;
+
+ // Normal characters
+ default:
+ if (cursor < line_length - 1)
+ line[cursor++] = buffer[i];
+ i++;
+ break;
+ }
+ }
+
+ // Return the length of the output
+ return cursor;
+}
+
static int pakfire_log_stream_fill_buffer(struct pakfire_log_stream* stream, int fd) {
ssize_t bytes_read;
}
static int pakfire_log_stream_drain_buffer(struct pakfire_log_stream* stream) {
+ char line[MAX_LINE_LENGTH] = {};
const char* eol = NULL;
size_t length;
int r;
else
length = stream->buffered;
+ // Sanitize the line
+ r = pakfire_log_stream_sanitize_line(stream, line, stream->buffer, length);
+ if (r < 0)
+ return r;
+
// Call the callback
- r = stream->callback(stream, stream->buffer, length, stream->data);
+ r = stream->callback(stream, line, r, stream->data);
if (r)
return r;
return bytes_read;
}
-#define pakfire_pty_sanitize_line(pty, line, buffer, buffer_length) \
- __pakfire_pty_sanitize_line(pty, line, sizeof(line), buffer, buffer_length)
-
-static int __pakfire_pty_sanitize_line(struct pakfire_pty* self,
- char* line, ssize_t line_length, const char* buffer, ssize_t length) {
- ssize_t i = 0;
- int num;
-
- // The cursor position
- int cursor = 0;
-
- while (i < length) {
- switch (buffer[i]) {
- // Escape
- case '\x1b':
- // Skip the escape character
- i++;
-
- // CSI
- if (i < length && buffer[i] == '[') {
- i++;
-
- // Reset number
- num = 0;
-
- // Parse the number
- while (i < length) {
- // Skip any ';'
- if (buffer[i] == ';') {
- i++;
- continue;
-
- // Parse any digits
- } else if (isdigit(buffer[i])) {
- num = num * 10 + (buffer[i] - '0');
- i++;
- continue;
- }
-
- // Break on all other characters
- break;
- }
-
- // Parse the command
- if (i < length) {
- char command = buffer[i++];
-
- switch (command) {
- // Move the cursor to the left
- case 'D':
- cursor -= (num > 0) ? num : 1;
-
- // Don't go too far left
- if (cursor < 0)
- cursor = 0;
- break;
-
- // Move the cursor to the right
- case 'C':
- cursor += (num > 0) ? num : 1;
-
- // Don't go too far right
- if (cursor >= length)
- cursor = length - 1;
- break;
-
- // Move to a certain column
- case 'G':
- cursor = (num > 0) ? num - 1 : 0;
-
- // Don't go too far right
- if (cursor >= length)
- cursor = length - 1;
- break;
-
- // Ignore any other sequences
- default:
- break;
- }
- }
- }
- break;
-
- // Backspace
- case '\x08':
- if (cursor > 0) {
- cursor--;
-
- // Erase the previous character
- line[cursor] = ' ';
- }
- i++;
- break;
-
- // Carriage Return
- case '\x0d':
- // Erase everything up to the cursor
- memset(line, '\0', cursor);
-
- cursor = 0;
- i++;
- break;
-
- // Normal characters
- default:
- if (cursor < line_length - 1)
- line[cursor++] = buffer[i];
- i++;
- break;
- }
- }
-
- return 0;
-}
-
static ssize_t pakfire_pty_send_line(struct pakfire_pty* self,
struct pakfire_pty_stdio* stdio, const char* buffer, ssize_t length) {
- char line[MAX_LINE_LENGTH] = {};
int r;
- // Sanitize the line
- r = pakfire_pty_sanitize_line(self, line, buffer, length);
- if (r < 0)
- return r;
-
// Call the callback
- r = stdio->callbacks.stdout_callback(self->ctx,
- stdio->callbacks.data, line, strlen(line));
+ r = stdio->callbacks.stdout_callback(self->ctx, stdio->callbacks.data, buffer, length);
if (r < 0)
return r;