diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2015-05-22 12:34:48 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2015-05-26 16:44:37 +0000 |
commit | e42ba5a8d14451fae6066ef771ef93d8ddfc62e4 (patch) | |
tree | e20f796326e9fbcee71de2826aac6291dede766b | |
parent | 185abfc3d6b4e8f804a3f7216cd8b0459593af87 (diff) | |
download | systemd-e42ba5a8d14451fae6066ef771ef93d8ddfc62e4.tar.gz |
util: Add unescape_first_word()
This is a superset of the functionality of unquote_first_word, allowing
non-whitespace separators, and doesn't interpret quotes unless
UNQUOTE_QUOTES is included in flags.
This also adds UNQUOTE_SEPARATOR_SPLIT, which has it return multiple
empty strings when there is a span of separator characters.
-rw-r--r-- | src/shared/util.c | 35 | ||||
-rw-r--r-- | src/shared/util.h | 7 |
2 files changed, 30 insertions, 12 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index 34024bacc4..4ac95ecf04 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5344,7 +5344,7 @@ int is_device_node(const char *path) { return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); } -int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { +int unescape_first_word(const char **p, char **ret, const char *separators, UnquoteFlags flags) { _cleanup_free_ char *s = NULL; size_t allocated = 0, sz = 0; int r; @@ -5357,7 +5357,7 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { SINGLE_QUOTE_ESCAPE, DOUBLE_QUOTE, DOUBLE_QUOTE_ESCAPE, - SPACE, + SEPARATOR, } state = START; assert(p); @@ -5377,8 +5377,14 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { case START: if (c == 0) goto finish; - else if (strchr(WHITESPACE, c)) + else if (strchr(separators, c)) { + if (!(flags & UNQUOTE_SEPARATOR_SPLIT)) + break; + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; + state = SEPARATOR; break; + } state = VALUE; /* fallthrough */ @@ -5386,14 +5392,14 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { case VALUE: if (c == 0) goto finish; - else if (c == '\'') + else if (c == '\'' && (flags & UNQUOTE_QUOTES)) state = SINGLE_QUOTE; else if (c == '\\') state = VALUE_ESCAPE; - else if (c == '\"') + else if (c == '\"' && (flags & UNQUOTE_QUOTES)) state = DOUBLE_QUOTE; - else if (strchr(WHITESPACE, c)) - state = SPACE; + else if (strchr(separators, c)) + state = SEPARATOR; else { if (!GREEDY_REALLOC(s, allocated, sz+2)) return -ENOMEM; @@ -5524,12 +5530,17 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { state = DOUBLE_QUOTE; break; - case SPACE: + case SEPARATOR: if (c == 0) goto finish; - if (!strchr(WHITESPACE, c)) + if (flags & UNQUOTE_SEPARATOR_SPLIT) { + /* Ensure we allocated "" */ + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; + goto finish; + } + if (!strchr(separators, c)) goto finish; - break; } @@ -5549,6 +5560,10 @@ finish: return 1; } +int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { + return unescape_first_word(p, ret, WHITESPACE, flags|UNQUOTE_QUOTES); +} + int unquote_many_words(const char **p, UnquoteFlags flags, ...) { va_list ap; char **l; diff --git a/src/shared/util.h b/src/shared/util.h index eb3595250d..dd86ddc4a1 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -855,10 +855,13 @@ int is_dir(const char *path, bool follow); int is_device_node(const char *path); typedef enum UnquoteFlags { - UNQUOTE_RELAX = 1, - UNQUOTE_CUNESCAPE = 2, + UNQUOTE_RELAX = 1, + UNQUOTE_CUNESCAPE = 2, + UNQUOTE_QUOTES = 3, + UNQUOTE_SEPARATOR_SPLIT = 4, } UnquoteFlags; +int unescape_first_word(const char **p, char **ret, const char *separators, UnquoteFlags flags); int unquote_first_word(const char **p, char **ret, UnquoteFlags flags); int unquote_many_words(const char **p, UnquoteFlags flags, ...) _sentinel_; |