chiark / gitweb /
hostnamed: introduce systemd-hostnamed
[elogind.git] / src / strv.c
index a749096f9a35c193ea2d16c36091aac5a26ce33f..71b77c9bbf97d857cce44ac0af1c350463d3ff50 100644 (file)
@@ -1,4 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
 /***
   This file is part of systemd.
@@ -31,7 +31,6 @@
 char *strv_find(char **l, const char *name) {
         char **i;
 
-        assert(l);
         assert(name);
 
         STRV_FOREACH(i, l)
@@ -41,6 +40,18 @@ char *strv_find(char **l, const char *name) {
         return NULL;
 }
 
+char *strv_find_prefix(char **l, const char *name) {
+        char **i;
+
+        assert(name);
+
+        STRV_FOREACH(i, l)
+                if (startswith(*i, name))
+                        return *i;
+
+        return NULL;
+}
+
 void strv_free(char **l) {
         char **k;
 
@@ -59,17 +70,20 @@ char **strv_copy(char **l) {
         if (!(r = new(char*, strv_length(l)+1)))
                 return NULL;
 
-        for (k = r; *l; k++, l++)
-                if (!(*k = strdup(*l)))
-                        goto fail;
+        if (l)
+                for (k = r; *l; k++, l++)
+                        if (!(*k = strdup(*l)))
+                                goto fail;
 
         *k = NULL;
         return r;
 
 fail:
-        for (k--, l--; k >= r; k--, l--)
+        for (k--; k >= r; k--)
                 free(*k);
 
+        free(r);
+
         return NULL;
 }
 
@@ -253,7 +267,7 @@ char **strv_split_quoted(const char *s) {
 
         i = 0;
         FOREACH_WORD_QUOTED(w, l, s, state)
-                if (!(r[i++] = strndup(w, l))) {
+                if (!(r[i++] = cunescape_length(w, l))) {
                         strv_free(r);
                         return NULL;
                 }
@@ -344,7 +358,10 @@ char **strv_remove(char **l, const char *s) {
         if (!l)
                 return NULL;
 
-        /* Drops every occurence 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++) {
 
@@ -363,15 +380,22 @@ char **strv_remove(char **l, const char *s) {
 static int env_append(char **r, char ***k, char **a) {
         assert(r);
         assert(k);
-        assert(a);
+
+        if (!a)
+                return 0;
 
         /* Add the entries of a to *k unless they already exist in *r
-         * in which case they are overriden instead. This assumes
-         * there is enough space in the r */
+         * in which case they are overridden instead. This assumes
+         * there is enough space in the r array. */
 
         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)
@@ -389,44 +413,41 @@ static int env_append(char **r, char ***k, char **a) {
         return 0;
 }
 
-char **strv_env_merge(char **x, ...) {
+char **strv_env_merge(unsigned n_lists, ...) {
         size_t n = 0;
         char **l, **k, **r;
         va_list ap;
+        unsigned i;
 
         /* Merges an arbitrary number of environment sets */
 
-        if (x) {
-                n += strv_length(x);
-
-                va_start(ap, x);
-                while ((l = va_arg(ap, char**)))
-                        n += strv_length(l);
-                va_end(ap);
+        va_start(ap, n_lists);
+        for (i = 0; i < n_lists; i++) {
+                l = va_arg(ap, char**);
+                n += strv_length(l);
         }
-
+        va_end(ap);
 
         if (!(r = new(char*, n+1)))
                 return NULL;
 
         k = r;
 
-        if (x) {
-                if (env_append(r, &k, x) < 0)
+        va_start(ap, n_lists);
+        for (i = 0; i < n_lists; i++) {
+                l = va_arg(ap, char**);
+                if (env_append(r, &k, l) < 0)
                         goto fail;
-
-                va_start(ap, x);
-                while ((l = va_arg(ap, char**)))
-                        if (env_append(r, &k, l) < 0)
-                                goto fail;
-                va_end(ap);
         }
+        va_end(ap);
 
         *k = NULL;
 
         return r;
 
 fail:
+        va_end(ap);
+
         for (k--; k >= r; k--)
                 free(*k);
 
@@ -461,12 +482,12 @@ static bool env_match(const char *t, const char *pattern) {
         return false;
 }
 
-char **strv_env_delete(char **x, ...) {
+char **strv_env_delete(char **x, unsigned n_lists, ...) {
         size_t n = 0, i = 0;
         char **l, **k, **r, **j;
         va_list ap;
 
-        /* Deletes every entry fromx that is mentioned in the other
+        /* Deletes every entry from x that is mentioned in the other
          * string lists */
 
         n = strv_length(x);
@@ -475,12 +496,14 @@ char **strv_env_delete(char **x, ...) {
                 return NULL;
 
         STRV_FOREACH(k, x) {
-                va_start(ap, x);
+                va_start(ap, n_lists);
 
-                while ((l = va_arg(ap, char**)))
+                for (i = 0; i < n_lists; i++) {
+                        l = va_arg(ap, char**);
                         STRV_FOREACH(j, l)
                                 if (env_match(*k, *j))
                                         goto delete;
+                }
 
                 va_end(ap);
 
@@ -501,3 +524,140 @@ char **strv_env_delete(char **x, ...) {
 
         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;
+
+        k = r;
+        if (env_append(r, &k, x) < 0)
+                goto fail;
+
+        if (env_append(r, &k, m) < 0)
+                goto fail;
+
+        *k = NULL;
+
+        return r;
+
+fail:
+        for (k--; k >= r; k--)
+                free(*k);
+
+        free(r);
+
+        return NULL;
+
+}
+
+char *strv_env_get_with_length(char **l, const char *name, size_t k) {
+        char **i;
+
+        assert(name);
+
+        STRV_FOREACH(i, l)
+                if (strncmp(*i, name, k) == 0 &&
+                    (*i)[k] == '=')
+                        return *i + k + 1;
+
+        return NULL;
+}
+
+char *strv_env_get(char **l, const char *name) {
+        return strv_env_get_with_length(l, name, strlen(name));
+}
+
+char **strv_env_clean(char **l) {
+        char **r, **ret;
+
+        for (r = ret = l; *l; l++) {
+                const char *equal;
+
+                equal = strchr(*l, '=');
+
+                if (equal && equal[1] == 0) {
+                        free(*l);
+                        continue;
+                }
+
+                *(r++) = *l;
+        }
+
+        *r = NULL;
+
+        return ret;
+}
+
+char **strv_parse_nulstr(const char *s, size_t l) {
+        const char *p;
+        unsigned c = 0, i = 0;
+        char **v;
+
+        assert(s || l <= 0);
+
+        if (l <= 0)
+                return strv_new(NULL, NULL);
+
+        for (p = s; p < s + l; p++)
+                if (*p == 0)
+                        c++;
+
+        if (s[l-1] != 0)
+                c++;
+
+        if (!(v = new0(char*, c+1)))
+                return NULL;
+
+        p = s;
+        while (p < s + l) {
+                const char *e;
+
+                e = memchr(p, 0, s + l - p);
+
+                if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
+                        strv_free(v);
+                        return NULL;
+                }
+
+                if (!e)
+                        break;
+
+                p = e + 1;
+        }
+
+        assert(i == c);
+
+        return v;
+}