From: Lennart Poettering Date: Wed, 10 Jul 2024 14:06:30 +0000 (+0200) Subject: terminal-util: don't process the same data twice when reading back bg color info X-Git-Tag: v257-rc1~873^2~41 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1df569b2e650afe254e09b337d598591f3068b61;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 9d3e0ae07be..ad225995532 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);