X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fstrv.c;h=92851b223375516b5144f52afcc2ca4b471333fd;hp=c8ebb648d643e9f43667d77ad00c7850e638cefa;hb=f08fce88206f7315cff24678590cd73cd5e75f95;hpb=ede27aab11cda3f55c2cd2e1e28e2385b3f64453 diff --git a/src/strv.c b/src/strv.c index c8ebb648d..92851b223 100644 --- a/src/strv.c +++ b/src/strv.c @@ -67,11 +67,11 @@ void strv_free(char **l) { char **strv_copy(char **l) { char **r, **k; - if (!(r = new(char*, strv_length(l)+1))) + if (!(k = r = new(char*, strv_length(l)+1))) return NULL; if (l) - for (k = r; *l; k++, l++) + for (; *l; k++, l++) if (!(*k = strdup(*l))) goto fail; @@ -105,7 +105,6 @@ char **strv_new_ap(const char *x, va_list ap) { unsigned n = 0, i = 0; va_list aq; - if (x) { n = 1; @@ -358,7 +357,10 @@ char **strv_remove(char **l, const char *s) { if (!l) return NULL; - /* Drops every occurrence of s in the string list */ + assert(s); + + /* Drops every occurrence of s in the string list, edits + * in-place. */ for (f = t = l; *f; f++) { @@ -387,7 +389,12 @@ static int env_append(char **r, char ***k, char **a) { for (; *a; a++) { char **j; - size_t n = strcspn(*a, "=") + 1; + size_t n; + + n = strcspn(*a, "="); + + if ((*a)[n] == '=') + n++; for (j = r; j < *k; j++) if (strncmp(*j, *a, n) == 0) @@ -475,8 +482,8 @@ static bool env_match(const char *t, const char *pattern) { } char **strv_env_delete(char **x, unsigned n_lists, ...) { - size_t n = 0, i = 0; - char **l, **k, **r, **j; + size_t n, i = 0; + char **k, **r; va_list ap; /* Deletes every entry from x that is mentioned in the other @@ -484,29 +491,34 @@ char **strv_env_delete(char **x, unsigned n_lists, ...) { n = strv_length(x); - if (!(r = new(char*, n+1))) + r = new(char*, n+1); + if (!r) return NULL; STRV_FOREACH(k, x) { + unsigned v; + va_start(ap, n_lists); + for (v = 0; v < n_lists; v++) { + char **l, **j; - for (i = 0; i < n_lists; i++) { l = va_arg(ap, char**); STRV_FOREACH(j, l) if (env_match(*k, *j)) - goto delete; + goto skip; } - va_end(ap); - if (!(r[i++] = strdup(*k))) { + r[i] = strdup(*k); + if (!r[i]) { strv_free(r); return NULL; } + i++; continue; - delete: + skip: va_end(ap); } @@ -517,9 +529,38 @@ char **strv_env_delete(char **x, unsigned n_lists, ...) { return r; } +char **strv_env_unset(char **l, const char *p) { + + char **f, **t; + + if (!l) + return NULL; + + assert(p); + + /* Drops every occurrence of the env var setting p in the + * string list. edits in-place. */ + + for (f = t = l; *f; f++) { + + if (env_match(*f, p)) { + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return l; +} + char **strv_env_set(char **x, const char *p) { char **k, **r; + char* m[2] = { (char*) p, NULL }; + + /* Overrides the env var setting of p, returns a new copy */ if (!(r = new(char*, strv_length(x)+2))) return NULL; @@ -528,7 +569,7 @@ char **strv_env_set(char **x, const char *p) { if (env_append(r, &k, x) < 0) goto fail; - if (!(*(k++) = strdup(p))) + if (env_append(r, &k, m) < 0) goto fail; *k = NULL; @@ -624,3 +665,16 @@ char **strv_parse_nulstr(const char *s, size_t l) { return v; } + +bool strv_overlap(char **a, char **b) { + char **i, **j; + + STRV_FOREACH(i, a) { + STRV_FOREACH(j, b) { + if (streq(*i, *j)) + return true; + } + } + + return false; +}