diff options
author | Lennart Poettering <lennart@poettering.net> | 2024-07-10 16:06:30 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2024-07-19 11:41:42 +0200 |
commit | 1df569b2e650afe254e09b337d598591f3068b61 (patch) | |
tree | 3287326e45856c711bfc67e7e29fa0c15e432d8a /src/basic/terminal-util.c | |
parent | terminal-util: return correct error in chvt() (diff) | |
download | systemd-1df569b2e650afe254e09b337d598591f3068b61.tar.xz systemd-1df569b2e650afe254e09b337d598591f3068b61.zip |
terminal-util: don't process the same data twice when reading back bg color info
If we only read partial information from the tty we ended up parsing it
again and again, confusing the state machine. hence, return how much
data we actually processed and drop it from the buffer.
Diffstat (limited to '')
-rw-r--r-- | src/basic/terminal-util.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 9d3e0ae07b..ad22599553 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1601,7 +1601,8 @@ typedef struct BackgroundColorContext { static int scan_background_color_response( BackgroundColorContext *context, const char *buf, - size_t size) { + size_t size, + size_t *ret_processed) { assert(context); assert(buf || size == 0); @@ -1677,8 +1678,12 @@ static int scan_background_color_response( case BACKGROUND_BLUE: if (c == '\x07') { - if (context->blue_bits > 0) + if (context->blue_bits > 0) { + if (ret_processed) + *ret_processed = i + 1; + return 1; /* success! */ + } context->state = BACKGROUND_TEXT; } else if (c == '\x1b') @@ -1695,8 +1700,12 @@ static int scan_background_color_response( break; case BACKGROUND_STRING_TERMINATOR: - if (c == '\\') + if (c == '\\') { + if (ret_processed) + *ret_processed = i + 1; + return 1; /* success! */ + } context->state = c == ']' ? BACKGROUND_ESCAPE : BACKGROUND_TEXT; break; @@ -1711,6 +1720,9 @@ static int scan_background_color_response( } } + if (ret_processed) + *ret_processed = size; + return 0; /* all good, but not enough data yet */ } @@ -1753,34 +1765,41 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret BackgroundColorContext context = {}; for (;;) { - usec_t n = now(CLOCK_MONOTONIC); + if (buf_full == 0) { + usec_t n = now(CLOCK_MONOTONIC); - if (n >= end) { - r = -EOPNOTSUPP; - goto finish; - } + if (n >= end) { + r = -EOPNOTSUPP; + goto finish; + } - r = fd_wait_for_event(STDIN_FILENO, POLLIN, usec_sub_unsigned(end, n)); - if (r < 0) - goto finish; - if (r == 0) { - r = -EOPNOTSUPP; - goto finish; - } + r = fd_wait_for_event(STDIN_FILENO, POLLIN, usec_sub_unsigned(end, n)); + if (r < 0) + goto finish; + if (r == 0) { + r = -EOPNOTSUPP; + goto finish; + } - ssize_t l; - l = read(STDIN_FILENO, buf, sizeof(buf) - buf_full); - if (l < 0) { - r = -errno; - goto finish; - } + ssize_t l = read(STDIN_FILENO, buf, sizeof(buf)); + if (l < 0) { + r = -errno; + goto finish; + } - buf_full += l; - assert(buf_full <= sizeof(buf)); + assert((size_t) l <= sizeof(buf)); + buf_full = l; + } - r = scan_background_color_response(&context, buf, buf_full); + size_t processed; + r = scan_background_color_response(&context, buf, buf_full, &processed); if (r < 0) goto finish; + + assert(processed <= buf_full); + buf_full -= processed; + memmove(buf, buf + processed, buf_full); + if (r > 0) { assert(context.red_bits > 0); *ret_red = (double) context.red / ((UINT64_C(1) << context.red_bits) - 1); |