From: Zbigniew Jędrzejewski-Szmek Date: Tue, 10 Aug 2021 15:03:12 +0000 (+0200) Subject: basic/env-util: add a mode where we pull in the variable value from environment X-Git-Tag: v250-rc1~842^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a14af47e64ca811c17470e021b22d05a16f4d46e;p=thirdparty%2Fsystemd.git basic/env-util: add a mode where we pull in the variable value from environment --- diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 0c30ddc2775..cb491256441 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -421,6 +421,32 @@ int strv_env_replace_strdup(char ***l, const char *assignment) { return strv_env_replace_consume(l, p); } +int strv_env_replace_strdup_passthrough(char ***l, const char *assignment) { + /* Like strv_env_replace_strdup(), but pulls the variable from the environment of + * the calling program, if a variable name without value is specified. + */ + char *p; + + if (strchr(assignment, '=')) { + if (!env_assignment_is_valid(assignment)) + return -EINVAL; + + p = strdup(assignment); + } else { + if (!env_name_is_valid(assignment)) + return -EINVAL; + + /* If we can't find the variable in our environment, we will use + * the empty string. This way "passthrough" is equivalent to passing + * --setenv=FOO=$FOO in the shell. */ + p = strjoin(assignment, "=", secure_getenv(assignment)); + } + if (!p) + return -ENOMEM; + + return strv_env_replace_consume(l, p); +} + int strv_env_assign(char ***l, const char *key, const char *value) { if (!env_name_is_valid(key)) return -EINVAL; diff --git a/src/basic/env-util.h b/src/basic/env-util.h index 18d10ebab8f..bee284b1684 100644 --- a/src/basic/env-util.h +++ b/src/basic/env-util.h @@ -47,6 +47,7 @@ char **strv_env_unset(char **l, const char *p); /* In place ... */ char **strv_env_unset_many(char **l, ...) _sentinel_; int strv_env_replace_consume(char ***l, char *p); /* In place ... */ int strv_env_replace_strdup(char ***l, const char *assignment); +int strv_env_replace_strdup_passthrough(char ***l, const char *assignment); int strv_env_assign(char ***l, const char *key, const char *value); char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_; diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c index 91c3c252de4..c689d5590ee 100644 --- a/src/test/test-env-util.c +++ b/src/test/test-env-util.c @@ -105,6 +105,7 @@ static void test_strv_env_replace_strdup(void) { assert_se(strv_env_replace_strdup(&a, "a=a") == 1); assert_se(strv_env_replace_strdup(&a, "b=b") == 1); assert_se(strv_env_replace_strdup(&a, "a=A") == 0); + assert_se(strv_env_replace_strdup(&a, "c") == -EINVAL); assert_se(strv_length(a) == 2); strv_sort(a); @@ -112,6 +113,27 @@ static void test_strv_env_replace_strdup(void) { assert_se(streq(a[1], "b=b")); } +static void test_strv_env_replace_strdup_passthrough(void) { + log_info("/* %s */", __func__); + + _cleanup_strv_free_ char **a = NULL; + + assert_se(putenv((char*) "a=a") == 0); + assert_se(putenv((char*) "b=") == 0); + assert_se(unsetenv("c") == 0); + + assert_se(strv_env_replace_strdup_passthrough(&a, "a") == 1); + assert_se(strv_env_replace_strdup_passthrough(&a, "b") == 1); + assert_se(strv_env_replace_strdup_passthrough(&a, "c") == 1); + assert_se(strv_env_replace_strdup_passthrough(&a, "a") == 0); + assert_se(strv_env_replace_strdup_passthrough(&a, "$a") == -EINVAL); + + assert_se(strv_length(a) == 3); + assert_se(streq(a[0], "a=a")); + assert_se(streq(a[1], "b=")); + assert_se(streq(a[2], "c=")); +} + static void test_strv_env_assign(void) { log_info("/* %s */", __func__); @@ -415,6 +437,7 @@ int main(int argc, char *argv[]) { test_strv_env_unset(); test_strv_env_merge(); test_strv_env_replace_strdup(); + test_strv_env_replace_strdup_passthrough(); test_strv_env_assign(); test_env_strv_get_n(); test_replace_env(false);