X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fenv-util.c;h=038246d21b7cd134fa34997be73d036d9ac036b2;hp=7a213a77c0ea8ea9261045c65e6f015960a20040;hb=da054c3782f25b3b18243f6c76dcfcf90ba70274;hpb=4d1a69043862ed979642f5688097160355d4cc81 diff --git a/src/shared/env-util.c b/src/shared/env-util.c index 7a213a77c..038246d21 100644 --- a/src/shared/env-util.c +++ b/src/shared/env-util.c @@ -27,11 +27,10 @@ #include "utf8.h" #include "util.h" #include "env-util.h" +#include "def.h" #define VALID_CHARS_ENV_NAME \ - "0123456789" \ - "abcdefghijklmnopqrstuvwxyz" \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + DIGITS LETTERS \ "_" #ifndef ARG_MAX @@ -79,7 +78,9 @@ bool env_value_is_valid(const char *e) { if (!utf8_is_valid(e)) return false; - if (string_has_cc(e)) + /* bash allows tabs in environment variables, and so should + * we */ + if (string_has_cc(e, "\t")) return false; /* POSIX says the overall size of the environment block cannot @@ -108,7 +109,7 @@ bool env_assignment_is_valid(const char *e) { /* POSIX says the overall size of the environment block cannot * be > ARG_MAX, hence the individual variable assignments - * cannot be either, but let's room for one trailing NUL + * cannot be either, but let's leave room for one trailing NUL * byte. */ if (strlen(e) > ARG_MAX - 1) return false; @@ -128,7 +129,22 @@ bool strv_env_is_valid(char **e) { /* Check if there are duplicate assginments */ k = strcspn(*p, "="); STRV_FOREACH(q, p + 1) - if (strncmp(*p, *q, k) == 0 && (*q)[k] == '=') + if (strneq(*p, *q, k) && (*q)[k] == '=') + return false; + } + + return true; +} + +bool strv_env_name_or_assignment_is_valid(char **l) { + char **p, **q; + + STRV_FOREACH(p, l) { + if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p)) + return false; + + STRV_FOREACH(q, p + 1) + if (streq(*p, *q)) return false; } @@ -156,7 +172,7 @@ static int env_append(char **r, char ***k, char **a) { n++; for (j = r; j < *k; j++) - if (strncmp(*j, *a, n) == 0) + if (strneq(*j, *a, n)) break; if (j >= *k) @@ -212,7 +228,7 @@ fail: return NULL; } -static bool env_match(const char *t, const char *pattern) { +_pure_ static bool env_match(const char *t, const char *pattern) { assert(t); assert(pattern); @@ -232,7 +248,7 @@ static bool env_match(const char *t, const char *pattern) { if (!strchr(pattern, '=')) { size_t l = strlen(pattern); - return strncmp(t, pattern, l) == 0 && t[l] == '='; + return strneq(t, pattern, l) && t[l] == '='; } return false; @@ -296,7 +312,7 @@ char **strv_env_unset(char **l, const char *p) { assert(p); /* Drops every occurrence of the env var setting p in the - * string list. edits in-place. */ + * string list. Edits in-place. */ for (f = t = l; *f; f++) { @@ -312,6 +328,43 @@ char **strv_env_unset(char **l, const char *p) { return l; } +char **strv_env_unset_many(char **l, ...) { + + char **f, **t; + + if (!l) + return NULL; + + /* Like strv_env_unset() but applies many at once. Edits in-place. */ + + for (f = t = l; *f; f++) { + bool found = false; + const char *p; + va_list ap; + + va_start(ap, l); + + while ((p = va_arg(ap, const char*))) { + if (env_match(*f, p)) { + found = true; + break; + } + } + + va_end(ap); + + if (found) { + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return l; +} + char **strv_env_set(char **x, const char *p) { char **k, **r; @@ -348,7 +401,7 @@ char *strv_env_get_n(char **l, const char *name, size_t k) { return NULL; STRV_FOREACH(i, l) - if (strncmp(*i, name, k) == 0 && + if (strneq(*i, name, k) && (*i)[k] == '=') return *i + k + 1; @@ -361,7 +414,7 @@ char *strv_env_get(char **l, const char *name) { return strv_env_get_n(l, name, strlen(name)); } -char **strv_env_clean(char **e) { +char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) { char **p, **q; int k = 0; @@ -370,13 +423,15 @@ char **strv_env_clean(char **e) { bool duplicate = false; if (!env_assignment_is_valid(*p)) { + if (invalid_callback) + invalid_callback(*p, userdata); free(*p); continue; } n = strcspn(*p, "="); STRV_FOREACH(q, p + 1) - if (strncmp(*p, *q, n) == 0 && (*q)[n] == '=') { + if (strneq(*p, *q, n) && (*q)[n] == '=') { duplicate = true; break; } @@ -389,6 +444,8 @@ char **strv_env_clean(char **e) { e[k++] = *p; } - e[k] = NULL; + if (e) + e[k] = NULL; + return e; }