summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-11-10 23:44:34 +0100
committerLennart Poettering <lennart@poettering.net>2014-11-10 23:45:12 +0100
commitf88e6be5ee31ff0e45fabcdedaf26d3be0d4817a (patch)
tree6eaee98e65ef337eddc31ea60a47ae444c8e2a1d /src
parent27e9c5af817147ea1c678769e45e83f2e4b4ae96 (diff)
strv: rework strv_split_quoted() to use unquote_first_word()
This should make the unquoting scheme a bit less naive.
Diffstat (limited to 'src')
-rw-r--r--src/journal-remote/journal-remote.c2
-rw-r--r--src/locale/localed.c6
-rw-r--r--src/shared/strv.c69
-rw-r--r--src/shared/strv.h3
-rw-r--r--src/shared/util.c2
-rw-r--r--src/test/test-strv.c12
6 files changed, 48 insertions, 46 deletions
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 7239b8cc6..b3f5c828d 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -149,7 +149,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);
+ r = strv_split_quoted(&words, getter, false);
if (r < 0) {
log_error("Failed to split getter option: %s", strerror(-r));
return r;
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 552ffdf87..9377ce501 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -224,7 +224,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);
+ r = strv_split_quoted(&a, l, false);
if (r < 0)
return r;
@@ -247,7 +247,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);
+ r = strv_split_quoted(&a, l, false);
if (r < 0)
return -ENOMEM;
@@ -533,7 +533,7 @@ static int read_next_mapping(FILE *f, unsigned *n, char ***a) {
if (l[0] == 0 || l[0] == '#')
continue;
- r = strv_split_quoted(&b, l);
+ r = strv_split_quoted(&b, l, false);
if (r < 0)
return r;
diff --git a/src/shared/strv.c b/src/shared/strv.c
index 00857e40a..aeb93eac6 100644
--- a/src/shared/strv.c
+++ b/src/shared/strv.c
@@ -248,40 +248,6 @@ char **strv_split(const char *s, const char *separator) {
return r;
}
-int strv_split_quoted(char ***t, const char *s) {
- const char *word, *state;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_QUOTED(word, l, s, state)
- n++;
- if (!isempty(state))
- /* bad syntax */
- return -EINVAL;
-
- r = new(char*, n+1);
- if (!r)
- return -ENOMEM;
-
- i = 0;
- FOREACH_WORD_QUOTED(word, l, s, state) {
- r[i] = cunescape_length(word, l);
- if (!r[i]) {
- strv_free(r);
- return -ENOMEM;
- }
- i++;
- }
-
- r[i] = NULL;
- *t = r;
- return 0;
-}
-
char **strv_split_newlines(const char *s) {
char **l;
unsigned n;
@@ -307,6 +273,41 @@ char **strv_split_newlines(const char *s) {
return l;
}
+int strv_split_quoted(char ***t, const char *s, bool relax) {
+ size_t n = 0, allocated = 0;
+ _cleanup_strv_free_ char **l = NULL;
+ int r;
+
+ assert(t);
+ assert(s);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = unquote_first_word(&s, &word, relax);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ if (!GREEDY_REALLOC(l, allocated, n + 2))
+ return -ENOMEM;
+
+ l[n++] = word;
+ word = NULL;
+
+ l[n] = NULL;
+ }
+
+ if (!l)
+ l = new0(char*, 1);
+
+ *t = l;
+ l = NULL;
+
+ return 0;
+}
+
char *strv_join(char **l, const char *separator) {
char *r, *e;
char **s;
diff --git a/src/shared/strv.h b/src/shared/strv.h
index 9c9633c51..47618bd26 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -63,9 +63,10 @@ static inline bool strv_isempty(char * const *l) {
}
char **strv_split(const char *s, const char *separator);
-int strv_split_quoted(char ***t, const char *s);
char **strv_split_newlines(const char *s);
+int strv_split_quoted(char ***t, const char *s, bool relax);
+
char *strv_join(char **l, const char *separator);
char *strv_join_quoted(char **l);
diff --git a/src/shared/util.c b/src/shared/util.c
index f0e0c0dd3..2f4fa237d 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -3292,7 +3292,7 @@ char **replace_env_argv(char **argv, char **env) {
if (e) {
int r;
- r = strv_split_quoted(&m, e);
+ r = strv_split_quoted(&m, e, true);
if (r < 0) {
ret[k] = NULL;
strv_free(ret);
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index 915fa4675..180f06239 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);
+ r = strv_split_quoted(&s, quoted, false);
assert_se(r == 0);
assert_se(s);
STRV_FOREACH(t, s) {
@@ -182,7 +182,7 @@ static void test_strv_unquote(const char *quoted, const char **list) {
char **t;
int r;
- r = strv_split_quoted(&s, quoted);
+ r = strv_split_quoted(&s, quoted, false);
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);
+ r = strv_split_quoted(&s, quoted, false);
assert_se(s == NULL);
assert_se(r == -EINVAL);
}
@@ -482,12 +482,12 @@ int main(int argc, char *argv[]) {
test_strv_unquote(" \"x'\" ", (const char*[]) { "x'", NULL });
test_strv_unquote("a '--b=c \"d e\"'", (const char*[]) { "a", "--b=c \"d e\"", NULL });
- test_invalid_unquote("a --b='c \"d e\"'");
- test_invalid_unquote("a --b='c \"d e\" '");
+ test_invalid_unquote("a --b='c \"d e\"''");
+ test_invalid_unquote("a --b='c \"d e\" '\"");
test_invalid_unquote("a --b='c \"d e\"garbage");
test_invalid_unquote("'");
test_invalid_unquote("\"");
- test_invalid_unquote("'x'y");
+ test_invalid_unquote("'x'y'g");
test_strv_split();
test_strv_split_newlines();