diff options
-rw-r--r-- | src/basic/escape.c | 18 | ||||
-rw-r--r-- | src/basic/escape.h | 9 | ||||
-rw-r--r-- | src/shared/bus-util.c | 21 | ||||
-rw-r--r-- | src/test/test-escape.c | 11 |
4 files changed, 42 insertions, 17 deletions
diff --git a/src/basic/escape.c b/src/basic/escape.c index c5c44d2e7d..116efa4119 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -518,22 +518,28 @@ char* shell_maybe_quote(const char *s, EscapeStyle style) { return NULL; t = r; - if (style == ESCAPE_BACKSLASH) + switch (style) { + case ESCAPE_BACKSLASH: + case ESCAPE_BACKSLASH_ONELINE: *(t++) = '"'; - else if (style == ESCAPE_POSIX) { + break; + case ESCAPE_POSIX: *(t++) = '$'; *(t++) = '\''; - } else + break; + default: assert_not_reached("Bad EscapeStyle"); + } t = mempcpy(t, s, p - s); - if (style == ESCAPE_BACKSLASH) - t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false); + if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE)) + t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, + style == ESCAPE_BACKSLASH_ONELINE); else t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true); - if (style == ESCAPE_BACKSLASH) + if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE)) *(t++) = '"'; else *(t++) = '\''; diff --git a/src/basic/escape.h b/src/basic/escape.h index b8eb137c3d..0b00b116ed 100644 --- a/src/basic/escape.h +++ b/src/basic/escape.h @@ -34,8 +34,13 @@ typedef enum UnescapeFlags { } UnescapeFlags; typedef enum EscapeStyle { - ESCAPE_BACKSLASH = 1, - ESCAPE_POSIX = 2, + ESCAPE_BACKSLASH = 1, /* Add shell quotes ("") so the shell will consider this a single + argument, possibly multiline. Tabs and newlines are not escaped. */ + ESCAPE_BACKSLASH_ONELINE = 2, /* Similar to ESCAPE_BACKSLASH, but always produces a single-line + string instead. Shell escape sequences are produced for tabs and + newlines. */ + ESCAPE_POSIX = 3, /* Similar to ESCAPE_BACKSLASH_ONELINE, but uses POSIX shell escape + * syntax (a string enclosed in $'') instead of plain quotes. */ } EscapeStyle; char *cescape(const char *s); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index dbbd0dcae6..05762c68a3 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -21,6 +21,7 @@ #include "bus-util.h" #include "cap-list.h" #include "cgroup-util.h" +#include "escape.h" #include "mountpoint-util.h" #include "nsflags.h" #include "parse-util.h" @@ -500,18 +501,20 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b return r; while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) { - bool good; + _cleanup_free_ char *e = NULL; - if (first && !value) - printf("%s=", name); - - /* This property has multiple space-separated values, so - * neither spaces nor newlines can be allowed in a value. */ - good = str[strcspn(str, " \n")] == '\0'; + e = shell_maybe_quote(str, ESCAPE_BACKSLASH_ONELINE); + if (!e) + return -ENOMEM; - printf("%s%s", first ? "" : " ", good ? str : "[unprintable]"); + if (first) { + if (!value) + printf("%s=", name); + first = false; + } else + fputs(" ", stdout); - first = false; + fputs(e, stdout); } if (r < 0) return r; diff --git a/src/test/test-escape.c b/src/test/test-escape.c index f6aae1eb18..699747fcc3 100644 --- a/src/test/test-escape.c +++ b/src/test/test-escape.c @@ -142,31 +142,42 @@ static void test_shell_maybe_quote_one(const char *s, static void test_shell_maybe_quote(void) { test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, ""); + test_shell_maybe_quote_one("", ESCAPE_BACKSLASH_ONELINE, ""); test_shell_maybe_quote_one("", ESCAPE_POSIX, ""); test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\""); + test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH_ONELINE, "\"\\\\\""); test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'"); test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\""); + test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH_ONELINE, "\"\\\"\""); test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'"); test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar"); + test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH_ONELINE, "foobar"); test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar"); test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\""); + test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH_ONELINE, "\"foo bar\""); test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'"); test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\""); + test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\tbar\""); test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'"); test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\""); + test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\nbar\""); test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'"); test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\""); + test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH_ONELINE, "\"foo \\\"bar\\\" waldo\""); test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'"); test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\""); + test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\$bar\""); test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'"); /* Note that current users disallow control characters, so this "test" * is here merely to establish current behaviour. If control characters * were allowed, they should be quoted, i.e. \001 should become \\001. */ test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\""); + test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH_ONELINE, "\"a\\nb\001\""); test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'"); test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\""); + test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH_ONELINE, "\"foo!bar\""); test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'"); } |