X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=e2c955bc0700594620a7c517d2a368c7593f296e;hb=e70bc43cdf75b36e7ad3d29e9a6f8ee1461e7d5e;hp=d8a75bdc6a5c156af242e42090d83bfc62f0efc4;hpb=b914e211f3a40f507b3cdc572838ec7f3fd5e4cf;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index d8a75bdc6..e2c955bc0 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -140,26 +140,38 @@ char* endswith(const char *s, const char *postfix) { return (char*) s + sl - pl; } -bool first_word(const char *s, const char *word) { +char* first_word(const char *s, const char *word) { size_t sl, wl; + const char *p; assert(s); assert(word); + /* Checks if the string starts with the specified word, either + * followed by NUL or by whitespace. Returns a pointer to the + * NUL or the first character after the whitespace. */ + sl = strlen(s); wl = strlen(word); if (sl < wl) - return false; + return NULL; if (wl == 0) - return true; + return (char*) s; if (memcmp(s, word, wl) != 0) - return false; + return NULL; + + p = s + wl; + if (*p == 0) + return (char*) p; - return s[wl] == 0 || - strchr(WHITESPACE, s[wl]); + if (!strchr(WHITESPACE, *p)) + return NULL; + + p += strspn(p, WHITESPACE); + return (char*) p; } int close_nointr(int fd) { @@ -415,37 +427,50 @@ static size_t strcspn_escaped(const char *s, const char *reject) { else if (s[n] == '\\') escaped = true; else if (strchr(reject, s[n])) - return n; + break; } - return n; + /* 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, bool quoted, 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); - if (!*current) + if (!*current) { + *state = current; return NULL; + } if (quoted && strchr("\'\"", *current)) { - char quotechar = *(current++); - *l = strcspn_escaped(current, (char[]){quotechar, '\0'}); - *state = current+*l+1; + char quotechars[2] = {*current, '\0'}; + + *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; + } + assert(current[*l + 1] == quotechars[0]); + *state = current++ + *l + 2; } else if (quoted) { *l = strcspn_escaped(current, separator); - *state = current+*l; + *state = current + *l; } else { *l = strcspn(current, separator); - *state = current+*l; + *state = current + *l; } - return (char*) current; + return current; } int get_parent_of_pid(pid_t pid, pid_t *_ppid) { @@ -1217,7 +1242,7 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre r = new(char, pl+length+1); if (!r) - return r; + return NULL; if (prefix) memcpy(r, prefix, pl); @@ -3150,12 +3175,13 @@ fail: } char **replace_env_argv(char **argv, char **env) { - char **r, **i; + char **ret, **i; unsigned k = 0, l = 0; l = strv_length(argv); - if (!(r = new(char*, l+1))) + ret = new(char*, l+1); + if (!ret) return NULL; STRV_FOREACH(i, argv) { @@ -3168,10 +3194,12 @@ char **replace_env_argv(char **argv, char **env) { e = strv_env_get(env, *i+1); if (e) { + int r; - if (!(m = strv_split_quoted(e))) { - r[k] = NULL; - strv_free(r); + r = strv_split_quoted(&m, e); + if (r < 0) { + ret[k] = NULL; + strv_free(ret); return NULL; } } else @@ -3180,16 +3208,17 @@ char **replace_env_argv(char **argv, char **env) { q = strv_length(m); l = l + q - 1; - if (!(w = realloc(r, sizeof(char*) * (l+1)))) { - r[k] = NULL; - strv_free(r); + w = realloc(ret, sizeof(char*) * (l+1)); + if (!w) { + ret[k] = NULL; + strv_free(ret); strv_free(m); return NULL; } - r = w; + ret = w; if (m) { - memcpy(r + k, m, q * sizeof(char*)); + memcpy(ret + k, m, q * sizeof(char*)); free(m); } @@ -3198,14 +3227,16 @@ char **replace_env_argv(char **argv, char **env) { } /* If ${FOO} appears as part of a word, replace it by the variable as-is */ - if (!(r[k++] = replace_env(*i, env))) { - strv_free(r); + ret[k] = replace_env(*i, env); + if (!ret[k]) { + strv_free(ret); return NULL; } + k++; } - r[k] = NULL; - return r; + ret[k] = NULL; + return ret; } int fd_columns(int fd) { @@ -6059,7 +6090,7 @@ int split_pair(const char *s, const char *sep, char **l, char **r) { int shall_restore_state(void) { _cleanup_free_ char *line = NULL; - char *w, *state; + const char *word, *state; size_t l; int r; @@ -6071,12 +6102,12 @@ int shall_restore_state(void) { r = 1; - FOREACH_WORD_QUOTED(w, l, line, state) { + FOREACH_WORD_QUOTED(word, l, line, state) { const char *e; char n[l+1]; int k; - memcpy(n, w, l); + memcpy(n, word, l); n[l] = 0; e = startswith(n, "systemd.restore_state="); @@ -6120,7 +6151,7 @@ int proc_cmdline(char **ret) { int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { _cleanup_free_ char *line = NULL; - char *w, *state; + const char *w, *state; size_t l; int r;