[systemd-devel] [PATCH 1/9] util: Add unescape_first_word()
Richard Maw
richard.maw at codethink.co.uk
Thu May 28 05:02:07 PDT 2015
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.
---
src/shared/util.c | 35 +++++++++++++++++++++++++----------
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 74a2190..468b5ab 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 eb35952..dd86ddc 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_;
--
1.9.1
More information about the systemd-devel
mailing list