summaryrefslogtreecommitdiffstats
path: root/src/basic/terminal-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2024-07-10 16:06:30 +0200
committerLennart Poettering <lennart@poettering.net>2024-07-19 11:41:42 +0200
commit1df569b2e650afe254e09b337d598591f3068b61 (patch)
tree3287326e45856c711bfc67e7e29fa0c15e432d8a /src/basic/terminal-util.c
parentterminal-util: return correct error in chvt() (diff)
downloadsystemd-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.c67
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);