summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2015-05-22 12:34:48 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2015-05-26 16:44:37 +0000
commite42ba5a8d14451fae6066ef771ef93d8ddfc62e4 (patch)
treee20f796326e9fbcee71de2826aac6291dede766b
parent185abfc3d6b4e8f804a3f7216cd8b0459593af87 (diff)
downloadsystemd-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.c35
-rw-r--r--src/shared/util.h7
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_;