diff options
Diffstat (limited to 'src/libudev/util.c')
-rw-r--r-- | src/libudev/util.c | 100 |
1 files changed, 42 insertions, 58 deletions
diff --git a/src/libudev/util.c b/src/libudev/util.c index 116d723a0f..5ff767b6a7 100644 --- a/src/libudev/util.c +++ b/src/libudev/util.c @@ -263,79 +263,63 @@ int safe_atolli(const char *s, long long int *ret_lli) { return 0; } +static size_t strcspn_escaped(const char *s, const char *reject) { + bool escaped = false; + size_t n; + + for (n=0; s[n]; n++) { + if (escaped) + escaped = false; + else if (s[n] == '\\') + escaped = true; + else if (strchr(reject, s[n])) + break; + } + /* if s ends in \, return index of previous char */ + return n - escaped; +} + /* Split a string into words. */ -char *split(const char *c, size_t *l, const char *separator, char **state) { - char *current; +const char* split(const char **state, size_t *l, const char *separator, bool quoted) { + const char *current; - current = *state ? *state : (char*) c; + current = *state; - if (!*current || *c == 0) + if (!*current) { + assert(**state == '\0'); return NULL; + } current += strspn(current, separator); - *l = strcspn(current, separator); - *state = current+*l; - - return (char*) current; -} - -/* Split a string into words, but consider strings enclosed in '' and - * "" as words even if they include spaces. */ -char *split_quoted(const char *c, size_t *l, char **state) { - char *current, *e; - bool escaped = false; - - current = *state ? *state : (char*) c; - - if (!*current || *c == 0) + if (!*current) { + *state = current; return NULL; + } - current += strspn(current, WHITESPACE); - - if (*current == '\'') { - current ++; + if (quoted && strchr("\'\"", *current)) { + char quotechars[2] = {*current, '\0'}; - for (e = current; *e; e++) { - if (escaped) - escaped = false; - else if (*e == '\\') - escaped = true; - else if (*e == '\'') - break; + *l = strcspn_escaped(current + 1, quotechars); + if (current[*l + 1] == '\0' || + (current[*l + 2] && !strchr(separator, current[*l + 2]))) { + /* right quote missing or garbage at the end*/ + *state = current; + return NULL; } - - *l = e-current; - *state = *e == 0 ? e : e+1; - } else if (*current == '\"') { - current ++; - - for (e = current; *e; e++) { - if (escaped) - escaped = false; - else if (*e == '\\') - escaped = true; - else if (*e == '\"') - break; - } - - *l = e-current; - *state = *e == 0 ? e : e+1; + assert(current[*l + 1] == quotechars[0]); + *state = current++ + *l + 2; + } else if (quoted) { + *l = strcspn_escaped(current, separator); + *state = current + *l; } else { - for (e = current; *e; e++) { - if (escaped) - escaped = false; - else if (*e == '\\') - escaped = true; - else if (strchr(WHITESPACE, *e)) - break; - } - *l = e-current; - *state = e; + *l = strcspn(current, separator); + *state = current + *l; } - return (char*) current; + return current; } + char *truncate_nl(char *s) { assert(s); |