diff --git a/TODO b/TODO index bb4d878c1a..81cd353a5a 100644 --- a/TODO +++ b/TODO @@ -6,7 +6,7 @@ Bugfixes: automount points even when the original .automount file did not exist anymore. Only the .mount unit was still around. -* ExecStart with unicode characters fails in strv_split_quoted: +* ExecStart with unicode characters fails in strv_split_extract: [Service] Environment=ONE='one' "TWO='two two' too" THREE= diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 9517fbc802..4804a67f91 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -550,7 +550,7 @@ char **replace_env_argv(char **argv, char **env) { if (e) { int r; - r = strv_split_quoted(&m, e, EXTRACT_RELAX); + r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_QUOTES); if (r < 0) { ret[k] = NULL; strv_free(ret); diff --git a/src/basic/strv.c b/src/basic/strv.c index 72964a166a..79a9d8d421 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -278,7 +278,7 @@ char **strv_split_newlines(const char *s) { return l; } -int strv_split_quoted(char ***t, const char *s, ExtractFlags flags) { +int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { size_t n = 0, allocated = 0; _cleanup_strv_free_ char **l = NULL; int r; @@ -289,11 +289,12 @@ int strv_split_quoted(char ***t, const char *s, ExtractFlags flags) { for (;;) { _cleanup_free_ char *word = NULL; - r = extract_first_word(&s, &word, NULL, flags|EXTRACT_QUOTES); + r = extract_first_word(&s, &word, separators, flags); if (r < 0) return r; - if (r == 0) + if (r == 0) { break; + } if (!GREEDY_REALLOC(l, allocated, n + 2)) return -ENOMEM; diff --git a/src/basic/strv.h b/src/basic/strv.h index fe3dfd245c..954da06fcb 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -73,7 +73,7 @@ static inline bool strv_isempty(char * const *l) { char **strv_split(const char *s, const char *separator); char **strv_split_newlines(const char *s); -int strv_split_quoted(char ***t, const char *s, ExtractFlags flags); +int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); char *strv_join(char **l, const char *separator); char *strv_join_quoted(char **l); diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index e3bd76051b..cdcda1cb52 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -148,7 +148,7 @@ static int spawn_getter(const char *getter, const char *url) { _cleanup_strv_free_ char **words = NULL; assert(getter); - r = strv_split_quoted(&words, getter, 0); + r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return log_error_errno(r, "Failed to split getter option: %m"); diff --git a/src/locale/localed.c b/src/locale/localed.c index cb4052fdd5..e9489f04c2 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -222,7 +222,7 @@ static int x11_read_data(Context *c) { if (in_section && first_word(l, "Option")) { _cleanup_strv_free_ char **a = NULL; - r = strv_split_quoted(&a, l, 0); + r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return r; @@ -245,7 +245,7 @@ static int x11_read_data(Context *c) { } else if (!in_section && first_word(l, "Section")) { _cleanup_strv_free_ char **a = NULL; - r = strv_split_quoted(&a, l, 0); + r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return -ENOMEM; @@ -544,7 +544,7 @@ static int read_next_mapping(const char* filename, if (l[0] == 0 || l[0] == '#') continue; - r = strv_split_quoted(&b, l, 0); + r = strv_split_extract(&b, l, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return r; diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 6e3c81395c..53074b4b65 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -165,7 +165,7 @@ static void test_strv_quote_unquote(const char* const *split, const char *quoted assert_se(p); assert_se(streq(p, quoted)); - r = strv_split_quoted(&s, quoted, 0); + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); assert_se(r == 0); assert_se(s); STRV_FOREACH(t, s) { @@ -182,7 +182,7 @@ static void test_strv_unquote(const char *quoted, char **list) { char **t; int r; - r = strv_split_quoted(&s, quoted, 0); + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); assert_se(r == 0); assert_se(s); j = strv_join(s, " | "); @@ -199,7 +199,7 @@ static void test_invalid_unquote(const char *quoted) { char **s = NULL; int r; - r = strv_split_quoted(&s, quoted, 0); + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); assert_se(s == NULL); assert_se(r == -EINVAL); } @@ -219,6 +219,21 @@ static void test_strv_split(void) { } } +static void test_strv_split_extract(void) { + _cleanup_strv_free_ char **l = NULL; + const char *str = ":foo\\:bar::waldo:"; + int r; + + r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + assert_se(r == 0); + assert_se(streq_ptr(l[0], "")); + assert_se(streq_ptr(l[1], "foo:bar")); + assert_se(streq_ptr(l[2], "")); + assert_se(streq_ptr(l[3], "waldo")); + assert_se(streq_ptr(l[4], "")); + assert_se(streq_ptr(l[5], NULL)); +} + static void test_strv_split_newlines(void) { unsigned i = 0; char **s; @@ -583,6 +598,7 @@ int main(int argc, char *argv[]) { test_invalid_unquote("'x'y'g"); test_strv_split(); + test_strv_split_extract(); test_strv_split_newlines(); test_strv_split_nulstr(); test_strv_parse_nulstr();