LCOV - code coverage report
Current view: top level - basic - env-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 325 388 83.8 %
Date: 2019-08-23 13:36:53 Functions: 21 23 91.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 214 301 71.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <limits.h>
       5                 :            : #include <stdarg.h>
       6                 :            : #include <stdlib.h>
       7                 :            : #include <string.h>
       8                 :            : #include <unistd.h>
       9                 :            : 
      10                 :            : #include "alloc-util.h"
      11                 :            : #include "env-util.h"
      12                 :            : #include "escape.h"
      13                 :            : #include "extract-word.h"
      14                 :            : #include "macro.h"
      15                 :            : #include "parse-util.h"
      16                 :            : #include "string-util.h"
      17                 :            : #include "strv.h"
      18                 :            : #include "utf8.h"
      19                 :            : 
      20                 :            : #define VALID_CHARS_ENV_NAME                    \
      21                 :            :         DIGITS LETTERS                          \
      22                 :            :         "_"
      23                 :            : 
      24                 :        364 : static bool env_name_is_valid_n(const char *e, size_t n) {
      25                 :            :         const char *p;
      26                 :            : 
      27         [ -  + ]:        364 :         if (!e)
      28                 :          0 :                 return false;
      29                 :            : 
      30         [ +  + ]:        364 :         if (n <= 0)
      31                 :         16 :                 return false;
      32                 :            : 
      33   [ +  +  +  + ]:        348 :         if (e[0] >= '0' && e[0] <= '9')
      34                 :          8 :                 return false;
      35                 :            : 
      36                 :            :         /* POSIX says the overall size of the environment block cannot
      37                 :            :          * be > ARG_MAX, an individual assignment hence cannot be
      38                 :            :          * either. Discounting the equal sign and trailing NUL this
      39                 :            :          * hence leaves ARG_MAX-2 as longest possible variable
      40                 :            :          * name. */
      41         [ -  + ]:        340 :         if (n > (size_t) sysconf(_SC_ARG_MAX) - 2)
      42                 :          0 :                 return false;
      43                 :            : 
      44         [ +  + ]:       1668 :         for (p = e; p < e + n; p++)
      45         [ +  + ]:       1396 :                 if (!strchr(VALID_CHARS_ENV_NAME, *p))
      46                 :         68 :                         return false;
      47                 :            : 
      48                 :        272 :         return true;
      49                 :            : }
      50                 :            : 
      51                 :        160 : bool env_name_is_valid(const char *e) {
      52         [ +  + ]:        160 :         if (!e)
      53                 :          4 :                 return false;
      54                 :            : 
      55                 :        156 :         return env_name_is_valid_n(e, strlen(e));
      56                 :            : }
      57                 :            : 
      58                 :        172 : bool env_value_is_valid(const char *e) {
      59         [ -  + ]:        172 :         if (!e)
      60                 :          0 :                 return false;
      61                 :            : 
      62         [ -  + ]:        172 :         if (!utf8_is_valid(e))
      63                 :          0 :                 return false;
      64                 :            : 
      65                 :            :         /* bash allows tabs and newlines in environment variables, and so
      66                 :            :          * should we */
      67         [ -  + ]:        172 :         if (string_has_cc(e, "\t\n"))
      68                 :          0 :                 return false;
      69                 :            : 
      70                 :            :         /* POSIX says the overall size of the environment block cannot
      71                 :            :          * be > ARG_MAX, an individual assignment hence cannot be
      72                 :            :          * either. Discounting the shortest possible variable name of
      73                 :            :          * length 1, the equal sign and trailing NUL this hence leaves
      74                 :            :          * ARG_MAX-3 as longest possible variable value. */
      75         [ -  + ]:        172 :         if (strlen(e) > sc_arg_max() - 3)
      76                 :          0 :                 return false;
      77                 :            : 
      78                 :        172 :         return true;
      79                 :            : }
      80                 :            : 
      81                 :        228 : bool env_assignment_is_valid(const char *e) {
      82                 :            :         const char *eq;
      83                 :            : 
      84                 :        228 :         eq = strchr(e, '=');
      85         [ +  + ]:        228 :         if (!eq)
      86                 :         20 :                 return false;
      87                 :            : 
      88         [ +  + ]:        208 :         if (!env_name_is_valid_n(e, eq - e))
      89                 :         56 :                 return false;
      90                 :            : 
      91         [ -  + ]:        152 :         if (!env_value_is_valid(eq + 1))
      92                 :          0 :                 return false;
      93                 :            : 
      94                 :            :         /* POSIX says the overall size of the environment block cannot
      95                 :            :          * be > ARG_MAX, hence the individual variable assignments
      96                 :            :          * cannot be either, but let's leave room for one trailing NUL
      97                 :            :          * byte. */
      98         [ -  + ]:        152 :         if (strlen(e) > sc_arg_max() - 1)
      99                 :          0 :                 return false;
     100                 :            : 
     101                 :        152 :         return true;
     102                 :            : }
     103                 :            : 
     104                 :          8 : bool strv_env_is_valid(char **e) {
     105                 :            :         char **p, **q;
     106                 :            : 
     107   [ +  -  +  + ]:         32 :         STRV_FOREACH(p, e) {
     108                 :            :                 size_t k;
     109                 :            : 
     110         [ -  + ]:         28 :                 if (!env_assignment_is_valid(*p))
     111                 :          0 :                         return false;
     112                 :            : 
     113                 :            :                 /* Check if there are duplicate assignments */
     114                 :         28 :                 k = strcspn(*p, "=");
     115   [ +  -  +  + ]:         88 :                 STRV_FOREACH(q, p + 1)
     116   [ +  +  +  - ]:         64 :                         if (strneq(*p, *q, k) && (*q)[k] == '=')
     117                 :          4 :                                 return false;
     118                 :            :         }
     119                 :            : 
     120                 :          4 :         return true;
     121                 :            : }
     122                 :            : 
     123                 :          0 : bool strv_env_name_is_valid(char **l) {
     124                 :            :         char **p;
     125                 :            : 
     126   [ #  #  #  # ]:          0 :         STRV_FOREACH(p, l) {
     127         [ #  # ]:          0 :                 if (!env_name_is_valid(*p))
     128                 :          0 :                         return false;
     129                 :            : 
     130         [ #  # ]:          0 :                 if (strv_contains(p + 1, *p))
     131                 :          0 :                         return false;
     132                 :            :         }
     133                 :            : 
     134                 :          0 :         return true;
     135                 :            : }
     136                 :            : 
     137                 :          0 : bool strv_env_name_or_assignment_is_valid(char **l) {
     138                 :            :         char **p;
     139                 :            : 
     140   [ #  #  #  # ]:          0 :         STRV_FOREACH(p, l) {
     141   [ #  #  #  # ]:          0 :                 if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p))
     142                 :          0 :                         return false;
     143                 :            : 
     144         [ #  # ]:          0 :                 if (strv_contains(p + 1, *p))
     145                 :          0 :                         return false;
     146                 :            :         }
     147                 :            : 
     148                 :          0 :         return true;
     149                 :            : }
     150                 :            : 
     151                 :        112 : static int env_append(char **r, char ***k, char **a) {
     152         [ -  + ]:        112 :         assert(r);
     153         [ -  + ]:        112 :         assert(k);
     154         [ -  + ]:        112 :         assert(*k >= r);
     155                 :            : 
     156         [ +  + ]:        112 :         if (!a)
     157                 :         24 :                 return 0;
     158                 :            : 
     159                 :            :         /* Expects the following arguments: 'r' shall point to the beginning of an strv we are going to append to, 'k'
     160                 :            :          * to a pointer pointing to the NULL entry at the end of the same array. 'a' shall point to another strv.
     161                 :            :          *
     162                 :            :          * This call adds every entry of 'a' to 'r', either overriding an existing matching entry, or appending to it.
     163                 :            :          *
     164                 :            :          * This call assumes 'r' has enough pre-allocated space to grow by all of 'a''s items. */
     165                 :            : 
     166         [ +  + ]:       3576 :         for (; *a; a++) {
     167                 :            :                 char **j, *c;
     168                 :            :                 size_t n;
     169                 :            : 
     170                 :       3488 :                 n = strcspn(*a, "=");
     171         [ +  + ]:       3488 :                 if ((*a)[n] == '=')
     172                 :       3480 :                         n++;
     173                 :            : 
     174         [ +  + ]:     124572 :                 for (j = r; j < *k; j++)
     175         [ +  + ]:     121100 :                         if (strneq(*j, *a, n))
     176                 :         16 :                                 break;
     177                 :            : 
     178                 :       3488 :                 c = strdup(*a);
     179         [ -  + ]:       3488 :                 if (!c)
     180                 :          0 :                         return -ENOMEM;
     181                 :            : 
     182         [ +  + ]:       3488 :                 if (j >= *k) { /* Append to the end? */
     183                 :       3472 :                         (*k)[0] = c;
     184                 :       3472 :                         (*k)[1] = NULL;
     185                 :       3472 :                         (*k)++;
     186                 :            :                 } else
     187                 :         16 :                         free_and_replace(*j, c); /* Override existing item */
     188                 :            :         }
     189                 :            : 
     190                 :         88 :         return 0;
     191                 :            : }
     192                 :            : 
     193                 :         52 : char **strv_env_merge(size_t n_lists, ...) {
     194                 :         52 :         _cleanup_strv_free_ char **ret = NULL;
     195                 :         52 :         size_t n = 0, i;
     196                 :            :         char **l, **k;
     197                 :            :         va_list ap;
     198                 :            : 
     199                 :            :         /* Merges an arbitrary number of environment sets */
     200                 :            : 
     201                 :         52 :         va_start(ap, n_lists);
     202         [ +  + ]:        156 :         for (i = 0; i < n_lists; i++) {
     203                 :        104 :                 l = va_arg(ap, char**);
     204                 :        104 :                 n += strv_length(l);
     205                 :            :         }
     206                 :         52 :         va_end(ap);
     207                 :            : 
     208                 :         52 :         ret = new(char*, n+1);
     209         [ -  + ]:         52 :         if (!ret)
     210                 :          0 :                 return NULL;
     211                 :            : 
     212                 :         52 :         *ret = NULL;
     213                 :         52 :         k = ret;
     214                 :            : 
     215                 :         52 :         va_start(ap, n_lists);
     216         [ +  + ]:        156 :         for (i = 0; i < n_lists; i++) {
     217                 :        104 :                 l = va_arg(ap, char**);
     218         [ -  + ]:        104 :                 if (env_append(ret, &k, l) < 0) {
     219                 :          0 :                         va_end(ap);
     220                 :          0 :                         return NULL;
     221                 :            :                 }
     222                 :            :         }
     223                 :         52 :         va_end(ap);
     224                 :            : 
     225                 :         52 :         return TAKE_PTR(ret);
     226                 :            : }
     227                 :            : 
     228                 :      63336 : static bool env_match(const char *t, const char *pattern) {
     229         [ -  + ]:      63336 :         assert(t);
     230         [ -  + ]:      63336 :         assert(pattern);
     231                 :            : 
     232                 :            :         /* pattern a matches string a
     233                 :            :          *         a matches a=
     234                 :            :          *         a matches a=b
     235                 :            :          *         a= matches a=
     236                 :            :          *         a=b matches a=b
     237                 :            :          *         a= does not match a
     238                 :            :          *         a=b does not match a=
     239                 :            :          *         a=b does not match a
     240                 :            :          *         a=b does not match a=c */
     241                 :            : 
     242         [ +  + ]:      63336 :         if (streq(t, pattern))
     243                 :          4 :                 return true;
     244                 :            : 
     245         [ +  + ]:      63332 :         if (!strchr(pattern, '=')) {
     246                 :      63096 :                 size_t l = strlen(pattern);
     247                 :            : 
     248   [ +  +  +  - ]:      63096 :                 return strneq(t, pattern, l) && t[l] == '=';
     249                 :            :         }
     250                 :            : 
     251                 :        236 :         return false;
     252                 :            : }
     253                 :            : 
     254                 :       1276 : static bool env_entry_has_name(const char *entry, const char *name) {
     255                 :            :         const char *t;
     256                 :            : 
     257         [ -  + ]:       1276 :         assert(entry);
     258         [ -  + ]:       1276 :         assert(name);
     259                 :            : 
     260                 :       1276 :         t = startswith(entry, name);
     261         [ +  + ]:       1276 :         if (!t)
     262                 :       1204 :                 return false;
     263                 :            : 
     264                 :         72 :         return *t == '=';
     265                 :            : }
     266                 :            : 
     267                 :          4 : char **strv_env_delete(char **x, size_t n_lists, ...) {
     268                 :          4 :         size_t n, i = 0;
     269                 :            :         char **k, **r;
     270                 :            :         va_list ap;
     271                 :            : 
     272                 :            :         /* Deletes every entry from x that is mentioned in the other
     273                 :            :          * string lists */
     274                 :            : 
     275                 :          4 :         n = strv_length(x);
     276                 :            : 
     277                 :          4 :         r = new(char*, n+1);
     278         [ -  + ]:          4 :         if (!r)
     279                 :          0 :                 return NULL;
     280                 :            : 
     281   [ +  -  +  + ]:         24 :         STRV_FOREACH(k, x) {
     282                 :            :                 size_t v;
     283                 :            : 
     284                 :         20 :                 va_start(ap, n_lists);
     285         [ +  + ]:         40 :                 for (v = 0; v < n_lists; v++) {
     286                 :            :                         char **l, **j;
     287                 :            : 
     288                 :         32 :                         l = va_arg(ap, char**);
     289   [ +  -  +  + ]:         68 :                         STRV_FOREACH(j, l)
     290         [ +  + ]:         48 :                                 if (env_match(*k, *j))
     291                 :         12 :                                         goto skip;
     292                 :            :                 }
     293                 :          8 :                 va_end(ap);
     294                 :            : 
     295                 :          8 :                 r[i] = strdup(*k);
     296         [ -  + ]:          8 :                 if (!r[i]) {
     297                 :          0 :                         strv_free(r);
     298                 :          0 :                         return NULL;
     299                 :            :                 }
     300                 :            : 
     301                 :          8 :                 i++;
     302                 :          8 :                 continue;
     303                 :            : 
     304                 :         12 :         skip:
     305                 :         12 :                 va_end(ap);
     306                 :            :         }
     307                 :            : 
     308                 :          4 :         r[i] = NULL;
     309                 :            : 
     310         [ -  + ]:          4 :         assert(i <= n);
     311                 :            : 
     312                 :          4 :         return r;
     313                 :            : }
     314                 :            : 
     315                 :         72 : char **strv_env_unset(char **l, const char *p) {
     316                 :            : 
     317                 :            :         char **f, **t;
     318                 :            : 
     319         [ -  + ]:         72 :         if (!l)
     320                 :          0 :                 return NULL;
     321                 :            : 
     322         [ -  + ]:         72 :         assert(p);
     323                 :            : 
     324                 :            :         /* Drops every occurrence of the env var setting p in the
     325                 :            :          * string list. Edits in-place. */
     326                 :            : 
     327         [ +  + ]:        320 :         for (f = t = l; *f; f++) {
     328                 :            : 
     329         [ +  + ]:        248 :                 if (env_match(*f, p)) {
     330                 :          4 :                         free(*f);
     331                 :          4 :                         continue;
     332                 :            :                 }
     333                 :            : 
     334                 :        244 :                 *(t++) = *f;
     335                 :            :         }
     336                 :            : 
     337                 :         72 :         *t = NULL;
     338                 :         72 :         return l;
     339                 :            : }
     340                 :            : 
     341                 :         56 : char **strv_env_unset_many(char **l, ...) {
     342                 :            :         char **f, **t;
     343                 :            : 
     344         [ -  + ]:         56 :         if (!l)
     345                 :          0 :                 return NULL;
     346                 :            : 
     347                 :            :         /* Like strv_env_unset() but applies many at once. Edits in-place. */
     348                 :            : 
     349         [ +  + ]:       3996 :         for (f = t = l; *f; f++) {
     350                 :       3940 :                 bool found = false;
     351                 :            :                 const char *p;
     352                 :            :                 va_list ap;
     353                 :            : 
     354                 :       3940 :                 va_start(ap, l);
     355                 :            : 
     356         [ +  + ]:      66980 :                 while ((p = va_arg(ap, const char*))) {
     357         [ -  + ]:      63040 :                         if (env_match(*f, p)) {
     358                 :          0 :                                 found = true;
     359                 :          0 :                                 break;
     360                 :            :                         }
     361                 :            :                 }
     362                 :            : 
     363                 :       3940 :                 va_end(ap);
     364                 :            : 
     365         [ -  + ]:       3940 :                 if (found) {
     366                 :          0 :                         free(*f);
     367                 :          0 :                         continue;
     368                 :            :                 }
     369                 :            : 
     370                 :       3940 :                 *(t++) = *f;
     371                 :            :         }
     372                 :            : 
     373                 :         56 :         *t = NULL;
     374                 :         56 :         return l;
     375                 :            : }
     376                 :            : 
     377                 :        344 : int strv_env_replace(char ***l, char *p) {
     378                 :            :         const char *t, *name;
     379                 :            :         char **f;
     380                 :            :         int r;
     381                 :            : 
     382         [ -  + ]:        344 :         assert(p);
     383                 :            : 
     384                 :            :         /* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits
     385                 :            :          * in-place. Does not copy p.  p must be a valid key=value assignment.
     386                 :            :          */
     387                 :            : 
     388                 :        344 :         t = strchr(p, '=');
     389         [ -  + ]:        344 :         if (!t)
     390                 :          0 :                 return -EINVAL;
     391                 :            : 
     392                 :        344 :         name = strndupa(p, t - p);
     393                 :            : 
     394   [ +  +  +  + ]:       1552 :         STRV_FOREACH(f, *l)
     395         [ +  + ]:       1276 :                 if (env_entry_has_name(*f, name)) {
     396                 :         68 :                         free_and_replace(*f, p);
     397                 :         68 :                         strv_env_unset(f + 1, *f);
     398                 :         68 :                         return 0;
     399                 :            :                 }
     400                 :            : 
     401                 :            :         /* We didn't find a match, we need to append p or create a new strv */
     402                 :        276 :         r = strv_push(l, p);
     403         [ -  + ]:        276 :         if (r < 0)
     404                 :          0 :                 return r;
     405                 :            : 
     406                 :        276 :         return 1;
     407                 :            : }
     408                 :            : 
     409                 :          4 : char **strv_env_set(char **x, const char *p) {
     410                 :          4 :         _cleanup_strv_free_ char **ret = NULL;
     411                 :            :         size_t n, m;
     412                 :            :         char **k;
     413                 :            : 
     414                 :            :         /* Overrides the env var setting of p, returns a new copy */
     415                 :            : 
     416                 :          4 :         n = strv_length(x);
     417                 :          4 :         m = n + 2;
     418         [ -  + ]:          4 :         if (m < n) /* overflow? */
     419                 :          0 :                 return NULL;
     420                 :            : 
     421                 :          4 :         ret = new(char*, m);
     422         [ -  + ]:          4 :         if (!ret)
     423                 :          0 :                 return NULL;
     424                 :            : 
     425                 :          4 :         *ret = NULL;
     426                 :          4 :         k = ret;
     427                 :            : 
     428         [ -  + ]:          4 :         if (env_append(ret, &k, x) < 0)
     429                 :          0 :                 return NULL;
     430                 :            : 
     431         [ -  + ]:          4 :         if (env_append(ret, &k, STRV_MAKE(p)) < 0)
     432                 :          0 :                 return NULL;
     433                 :            : 
     434                 :          4 :         return TAKE_PTR(ret);
     435                 :            : }
     436                 :            : 
     437                 :        380 : char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
     438                 :            :         char **i;
     439                 :            : 
     440         [ -  + ]:        380 :         assert(name);
     441                 :            : 
     442         [ -  + ]:        380 :         if (k <= 0)
     443                 :          0 :                 return NULL;
     444                 :            : 
     445   [ +  -  +  -  :       1280 :         STRV_FOREACH_BACKWARDS(i, l)
                   +  + ]
     446         [ +  + ]:       1208 :                 if (strneq(*i, name, k) &&
     447         [ +  + ]:        312 :                     (*i)[k] == '=')
     448                 :        308 :                         return *i + k + 1;
     449                 :            : 
     450         [ +  + ]:         72 :         if (flags & REPLACE_ENV_USE_ENVIRONMENT) {
     451                 :            :                 const char *t;
     452                 :            : 
     453                 :         36 :                 t = strndupa(name, k);
     454                 :         36 :                 return getenv(t);
     455                 :            :         };
     456                 :            : 
     457                 :         36 :         return NULL;
     458                 :            : }
     459                 :            : 
     460                 :         52 : char *strv_env_get(char **l, const char *name) {
     461         [ -  + ]:         52 :         assert(name);
     462                 :            : 
     463                 :         52 :         return strv_env_get_n(l, name, strlen(name), 0);
     464                 :            : }
     465                 :            : 
     466                 :         12 : char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) {
     467                 :            :         char **p, **q;
     468                 :         12 :         int k = 0;
     469                 :            : 
     470   [ +  -  +  + ]:        152 :         STRV_FOREACH(p, e) {
     471                 :            :                 size_t n;
     472                 :        140 :                 bool duplicate = false;
     473                 :            : 
     474         [ +  + ]:        140 :                 if (!env_assignment_is_valid(*p)) {
     475         [ -  + ]:         40 :                         if (invalid_callback)
     476                 :          0 :                                 invalid_callback(*p, userdata);
     477                 :         40 :                         free(*p);
     478                 :         40 :                         continue;
     479                 :            :                 }
     480                 :            : 
     481                 :        100 :                 n = strcspn(*p, "=");
     482   [ +  -  +  + ]:        608 :                 STRV_FOREACH(q, p + 1)
     483   [ +  +  +  + ]:        516 :                         if (strneq(*p, *q, n) && (*q)[n] == '=') {
     484                 :          8 :                                 duplicate = true;
     485                 :          8 :                                 break;
     486                 :            :                         }
     487                 :            : 
     488         [ +  + ]:        100 :                 if (duplicate) {
     489                 :          8 :                         free(*p);
     490                 :          8 :                         continue;
     491                 :            :                 }
     492                 :            : 
     493                 :         92 :                 e[k++] = *p;
     494                 :            :         }
     495                 :            : 
     496         [ +  - ]:         12 :         if (e)
     497                 :         12 :                 e[k] = NULL;
     498                 :            : 
     499                 :         12 :         return e;
     500                 :            : }
     501                 :            : 
     502                 :        260 : char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
     503                 :            :         enum {
     504                 :            :                 WORD,
     505                 :            :                 CURLY,
     506                 :            :                 VARIABLE,
     507                 :            :                 VARIABLE_RAW,
     508                 :            :                 TEST,
     509                 :            :                 DEFAULT_VALUE,
     510                 :            :                 ALTERNATE_VALUE,
     511                 :        260 :         } state = WORD;
     512                 :            : 
     513                 :        260 :         const char *e, *word = format, *test_value;
     514                 :            :         char *k;
     515                 :        260 :         _cleanup_free_ char *r = NULL;
     516                 :            :         size_t i, len;
     517                 :        260 :         int nest = 0;
     518                 :            : 
     519         [ -  + ]:        260 :         assert(format);
     520                 :            : 
     521   [ +  +  +  + ]:       3876 :         for (e = format, i = 0; *e && i < n; e ++, i ++)
     522   [ +  +  +  +  :       3616 :                 switch (state) {
                +  +  - ]
     523                 :            : 
     524                 :       1252 :                 case WORD:
     525         [ +  + ]:       1252 :                         if (*e == '$')
     526                 :        380 :                                 state = CURLY;
     527                 :       1252 :                         break;
     528                 :            : 
     529                 :        380 :                 case CURLY:
     530         [ +  + ]:        380 :                         if (*e == '{') {
     531                 :        272 :                                 k = strnappend(r, word, e-word-1);
     532         [ -  + ]:        272 :                                 if (!k)
     533                 :          0 :                                         return NULL;
     534                 :            : 
     535                 :        272 :                                 free_and_replace(r, k);
     536                 :            : 
     537                 :        272 :                                 word = e-1;
     538                 :        272 :                                 state = VARIABLE;
     539                 :        272 :                                 nest++;
     540         [ +  + ]:        108 :                         } else if (*e == '$') {
     541                 :          8 :                                 k = strnappend(r, word, e-word);
     542         [ -  + ]:          8 :                                 if (!k)
     543                 :          0 :                                         return NULL;
     544                 :            : 
     545                 :          8 :                                 free_and_replace(r, k);
     546                 :            : 
     547                 :          8 :                                 word = e+1;
     548                 :          8 :                                 state = WORD;
     549                 :            : 
     550   [ +  +  +  - ]:        100 :                         } else if (flags & REPLACE_ENV_ALLOW_BRACELESS && strchr(VALID_CHARS_ENV_NAME, *e)) {
     551                 :         60 :                                 k = strnappend(r, word, e-word-1);
     552         [ -  + ]:         60 :                                 if (!k)
     553                 :          0 :                                         return NULL;
     554                 :            : 
     555                 :         60 :                                 free_and_replace(r, k);
     556                 :            : 
     557                 :         60 :                                 word = e-1;
     558                 :         60 :                                 state = VARIABLE_RAW;
     559                 :            : 
     560                 :            :                         } else
     561                 :         40 :                                 state = WORD;
     562                 :        380 :                         break;
     563                 :            : 
     564                 :       1204 :                 case VARIABLE:
     565         [ +  + ]:       1204 :                         if (*e == '}') {
     566                 :            :                                 const char *t;
     567                 :            : 
     568                 :        164 :                                 t = strv_env_get_n(env, word+2, e-word-2, flags);
     569                 :            : 
     570                 :        164 :                                 k = strjoin(r, t);
     571         [ -  + ]:        164 :                                 if (!k)
     572                 :          0 :                                         return NULL;
     573                 :            : 
     574                 :        164 :                                 free_and_replace(r, k);
     575                 :            : 
     576                 :        164 :                                 word = e+1;
     577                 :        164 :                                 state = WORD;
     578         [ +  + ]:       1040 :                         } else if (*e == ':') {
     579         [ +  + ]:        104 :                                 if (!(flags & REPLACE_ENV_ALLOW_EXTENDED))
     580                 :            :                                         /* Treat this as unsupported syntax, i.e. do no replacement */
     581                 :         48 :                                         state = WORD;
     582                 :            :                                 else {
     583                 :         56 :                                         len = e-word-2;
     584                 :         56 :                                         state = TEST;
     585                 :            :                                 }
     586                 :            :                         }
     587                 :       1204 :                         break;
     588                 :            : 
     589                 :         56 :                 case TEST:
     590         [ +  + ]:         56 :                         if (*e == '-')
     591                 :         28 :                                 state = DEFAULT_VALUE;
     592         [ +  - ]:         28 :                         else if (*e == '+')
     593                 :         28 :                                 state = ALTERNATE_VALUE;
     594                 :            :                         else {
     595                 :          0 :                                 state = WORD;
     596                 :          0 :                                 break;
     597                 :            :                         }
     598                 :            : 
     599                 :         56 :                         test_value = e+1;
     600                 :         56 :                         break;
     601                 :            : 
     602                 :        544 :                 case DEFAULT_VALUE: /* fall through */
     603                 :            :                 case ALTERNATE_VALUE:
     604         [ -  + ]:        544 :                         assert(flags & REPLACE_ENV_ALLOW_EXTENDED);
     605                 :            : 
     606         [ +  + ]:        544 :                         if (*e == '{') {
     607                 :         40 :                                 nest++;
     608                 :         40 :                                 break;
     609                 :            :                         }
     610                 :            : 
     611         [ +  + ]:        504 :                         if (*e != '}')
     612                 :        408 :                                 break;
     613                 :            : 
     614                 :         96 :                         nest--;
     615         [ +  + ]:         96 :                         if (nest == 0) {
     616                 :            :                                 const char *t;
     617         [ +  - ]:         56 :                                 _cleanup_free_ char *v = NULL;
     618                 :            : 
     619                 :         56 :                                 t = strv_env_get_n(env, word+2, len, flags);
     620                 :            : 
     621   [ +  +  +  + ]:         56 :                                 if (t && state == ALTERNATE_VALUE)
     622                 :         12 :                                         t = v = replace_env_n(test_value, e-test_value, env, flags);
     623   [ +  +  +  + ]:         44 :                                 else if (!t && state == DEFAULT_VALUE)
     624                 :         12 :                                         t = v = replace_env_n(test_value, e-test_value, env, flags);
     625                 :            : 
     626                 :         56 :                                 k = strjoin(r, t);
     627         [ -  + ]:         56 :                                 if (!k)
     628                 :          0 :                                         return NULL;
     629                 :            : 
     630                 :         56 :                                 free_and_replace(r, k);
     631                 :            : 
     632                 :         56 :                                 word = e+1;
     633                 :         56 :                                 state = WORD;
     634                 :            :                         }
     635                 :         96 :                         break;
     636                 :            : 
     637                 :        180 :                 case VARIABLE_RAW:
     638         [ -  + ]:        180 :                         assert(flags & REPLACE_ENV_ALLOW_BRACELESS);
     639                 :            : 
     640         [ +  + ]:        180 :                         if (!strchr(VALID_CHARS_ENV_NAME, *e)) {
     641                 :            :                                 const char *t;
     642                 :            : 
     643                 :         48 :                                 t = strv_env_get_n(env, word+1, e-word-1, flags);
     644                 :            : 
     645                 :         48 :                                 k = strjoin(r, t);
     646         [ -  + ]:         48 :                                 if (!k)
     647                 :          0 :                                         return NULL;
     648                 :            : 
     649                 :         48 :                                 free_and_replace(r, k);
     650                 :            : 
     651                 :         48 :                                 word = e--;
     652                 :         48 :                                 i--;
     653                 :         48 :                                 state = WORD;
     654                 :            :                         }
     655                 :        180 :                         break;
     656                 :            :                 }
     657                 :            : 
     658         [ +  + ]:       3876 :         if (state == VARIABLE_RAW) {
     659                 :            :                 const char *t;
     660                 :            : 
     661         [ -  + ]:         12 :                 assert(flags & REPLACE_ENV_ALLOW_BRACELESS);
     662                 :            : 
     663                 :         12 :                 t = strv_env_get_n(env, word+1, e-word-1, flags);
     664                 :         12 :                 return strjoin(r, t);
     665                 :            :         } else
     666                 :        248 :                 return strnappend(r, word, e-word);
     667                 :            : }
     668                 :            : 
     669                 :          4 : char **replace_env_argv(char **argv, char **env) {
     670                 :            :         char **ret, **i;
     671                 :          4 :         size_t k = 0, l = 0;
     672                 :            : 
     673                 :          4 :         l = strv_length(argv);
     674                 :            : 
     675                 :          4 :         ret = new(char*, l+1);
     676         [ -  + ]:          4 :         if (!ret)
     677                 :          0 :                 return NULL;
     678                 :            : 
     679   [ +  -  +  + ]:         72 :         STRV_FOREACH(i, argv) {
     680                 :            : 
     681                 :            :                 /* If $FOO appears as single word, replace it by the split up variable */
     682   [ +  +  +  +  :         68 :                 if ((*i)[0] == '$' && !IN_SET((*i)[1], '{', '$')) {
                   +  + ]
     683                 :            :                         char *e;
     684                 :          8 :                         char **w, **m = NULL;
     685                 :            :                         size_t q;
     686                 :            : 
     687                 :          8 :                         e = strv_env_get(env, *i+1);
     688         [ +  + ]:          8 :                         if (e) {
     689                 :            :                                 int r;
     690                 :            : 
     691                 :          4 :                                 r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE);
     692         [ -  + ]:          4 :                                 if (r < 0) {
     693                 :          0 :                                         ret[k] = NULL;
     694                 :          0 :                                         strv_free(ret);
     695                 :          0 :                                         return NULL;
     696                 :            :                                 }
     697                 :            :                         } else
     698                 :          4 :                                 m = NULL;
     699                 :            : 
     700                 :          8 :                         q = strv_length(m);
     701                 :          8 :                         l = l + q - 1;
     702                 :            : 
     703                 :          8 :                         w = reallocarray(ret, l + 1, sizeof(char *));
     704         [ -  + ]:          8 :                         if (!w) {
     705                 :          0 :                                 ret[k] = NULL;
     706                 :          0 :                                 strv_free(ret);
     707                 :          0 :                                 strv_free(m);
     708                 :          0 :                                 return NULL;
     709                 :            :                         }
     710                 :            : 
     711                 :          8 :                         ret = w;
     712         [ +  + ]:          8 :                         if (m) {
     713                 :          4 :                                 memcpy(ret + k, m, q * sizeof(char*));
     714                 :          4 :                                 free(m);
     715                 :            :                         }
     716                 :            : 
     717                 :          8 :                         k += q;
     718                 :          8 :                         continue;
     719                 :            :                 }
     720                 :            : 
     721                 :            :                 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
     722                 :         60 :                 ret[k] = replace_env(*i, env, 0);
     723         [ -  + ]:         60 :                 if (!ret[k]) {
     724                 :          0 :                         strv_free(ret);
     725                 :          0 :                         return NULL;
     726                 :            :                 }
     727                 :         60 :                 k++;
     728                 :            :         }
     729                 :            : 
     730                 :          4 :         ret[k] = NULL;
     731                 :          4 :         return ret;
     732                 :            : }
     733                 :            : 
     734                 :       1733 : int getenv_bool(const char *p) {
     735                 :            :         const char *e;
     736                 :            : 
     737                 :       1733 :         e = getenv(p);
     738         [ +  + ]:       1733 :         if (!e)
     739                 :       1725 :                 return -ENXIO;
     740                 :            : 
     741                 :          8 :         return parse_boolean(e);
     742                 :            : }
     743                 :            : 
     744                 :       1570 : int getenv_bool_secure(const char *p) {
     745                 :            :         const char *e;
     746                 :            : 
     747                 :       1570 :         e = secure_getenv(p);
     748         [ +  - ]:       1570 :         if (!e)
     749                 :       1570 :                 return -ENXIO;
     750                 :            : 
     751                 :          0 :         return parse_boolean(e);
     752                 :            : }

Generated by: LCOV version 1.14