[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