]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
condition: add ConditionEnvironment=
authorLennart Poettering <lennart@poettering.net>
Thu, 14 May 2020 17:13:03 +0000 (19:13 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 15 May 2020 14:05:33 +0000 (16:05 +0200)
Prompted by the discussions in #15180.

This is a bit more complex than I hoped, since for PID 1 we need to pass
in the synethetic environment block in we generate on demand.

src/analyze/analyze-condition.c
src/core/unit.c
src/network/netdev/netdev.c
src/network/networkd-network.c
src/network/networkd-util.c
src/shared/condition.c
src/shared/condition.h
src/test/test-condition.c
src/udev/net/link-config.c

index 370256b4339c32709dccbe14c54742027ba73aac..d18ee9d043adaf4d3a4327cca0440c6ee6fdfbc8 100644 (file)
@@ -145,11 +145,11 @@ int verify_conditions(char **lines, UnitFileScope scope) {
                         return r;
         }
 
-        r = condition_test_list(u->asserts, assert_type_to_string, log_helper, u);
+        r = condition_test_list(u->asserts, environ, assert_type_to_string, log_helper, u);
         if (u->asserts)
                 log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed");
 
-        q = condition_test_list(u->conditions, condition_type_to_string, log_helper, u);
+        q = condition_test_list(u->conditions, environ, condition_type_to_string, log_helper, u);
         if (u->conditions)
                 log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed");
 
index 6f65ff7d056416cc1be7ef045bb797d12d4ce848..c5eb72163b85f8b84b3453a375072dbd0b3c357d 100644 (file)
@@ -1705,24 +1705,50 @@ static int log_unit_internal(void *userdata, int level, int error, const char *f
 }
 
 static bool unit_test_condition(Unit *u) {
+        _cleanup_strv_free_ char **env = NULL;
+        int r;
+
         assert(u);
 
         dual_timestamp_get(&u->condition_timestamp);
-        u->condition_result = condition_test_list(u->conditions, condition_type_to_string, log_unit_internal, u);
 
-        unit_add_to_dbus_queue(u);
+        r = manager_get_effective_environment(u->manager, &env);
+        if (r < 0) {
+                log_unit_error_errno(u, r, "Failed to determine effective environment: %m");
+                u->condition_result = CONDITION_ERROR;
+        } else
+                u->condition_result = condition_test_list(
+                                u->conditions,
+                                env,
+                                condition_type_to_string,
+                                log_unit_internal,
+                                u);
 
+        unit_add_to_dbus_queue(u);
         return u->condition_result;
 }
 
 static bool unit_test_assert(Unit *u) {
+        _cleanup_strv_free_ char **env = NULL;
+        int r;
+
         assert(u);
 
         dual_timestamp_get(&u->assert_timestamp);
-        u->assert_result = condition_test_list(u->asserts, assert_type_to_string, log_unit_internal, u);
 
-        unit_add_to_dbus_queue(u);
+        r = manager_get_effective_environment(u->manager, &env);
+        if (r < 0) {
+                log_unit_error_errno(u, r, "Failed to determine effective environment: %m");
+                u->assert_result = CONDITION_ERROR;
+        } else
+                u->assert_result = condition_test_list(
+                                u->asserts,
+                                env,
+                                assert_type_to_string,
+                                log_unit_internal,
+                                u);
 
+        unit_add_to_dbus_queue(u);
         return u->assert_result;
 }
 
index bc85d4babb734a411beae9aa62c085ba2dd1e287..997dafa719f124dd5606a565b5a423877466befb 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <net/if.h>
 #include <netinet/in.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "bond.h"
@@ -693,7 +694,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
                 return r;
 
         /* skip out early if configuration does not match the environment */
-        if (!condition_test_list(netdev_raw->conditions, NULL, NULL, NULL)) {
+        if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
                 log_debug("%s: Conditions in the file do not match the system environment, skipping.", filename);
                 return 0;
         }
index d9646a21cba844626c6861ae7818ab1d9029ef17..4ba46d28e308752c826e35d39a275ad22eb76a3f 100644 (file)
@@ -3,6 +3,7 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <linux/netdevice.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "conf-files.h"
@@ -172,7 +173,7 @@ int network_verify(Network *network) {
                                          network->filename);
 
         /* skip out early if configuration does not match the environment */
-        if (!condition_test_list(network->conditions, NULL, NULL, NULL))
+        if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "%s: Conditions in the file do not match the system environment, skipping.",
                                        network->filename);
index 5471e74592338c5cdc63791fbd90ae71090a080e..d9ad647a15a8ce62fd0bb8971843a1ac68335d79 100644 (file)
@@ -107,7 +107,7 @@ int kernel_route_expiration_supported(void) {
                         .type = CONDITION_KERNEL_VERSION,
                         .parameter = (char *) ">= 4.5"
                 };
-                r = condition_test(&c);
+                r = condition_test(&c, NULL);
                 if (r < 0)
                         return r;
 
index 3c76c86a0fd22555aa6fb69c8e536ac6f210c1f9..c83a4ba0eb8a86a297e3a78e18d58a1ea53b595d 100644 (file)
@@ -93,7 +93,7 @@ Condition* condition_free_list_type(Condition *head, ConditionType type) {
         return head;
 }
 
-static int condition_test_kernel_command_line(Condition *c) {
+static int condition_test_kernel_command_line(Condition *c, char **env) {
         _cleanup_free_ char *line = NULL;
         const char *p;
         bool equal;
@@ -202,7 +202,7 @@ static bool test_order(int k, OrderOperator p) {
         }
 }
 
-static int condition_test_kernel_version(Condition *c) {
+static int condition_test_kernel_version(Condition *c, char **env) {
         OrderOperator order;
         struct utsname u;
         const char *p;
@@ -260,7 +260,7 @@ static int condition_test_kernel_version(Condition *c) {
         return true;
 }
 
-static int condition_test_memory(Condition *c) {
+static int condition_test_memory(Condition *c, char **env) {
         OrderOperator order;
         uint64_t m, k;
         const char *p;
@@ -284,7 +284,7 @@ static int condition_test_memory(Condition *c) {
         return test_order(CMP(m, k), order);
 }
 
-static int condition_test_cpus(Condition *c) {
+static int condition_test_cpus(Condition *c, char **env) {
         OrderOperator order;
         const char *p;
         unsigned k;
@@ -310,7 +310,7 @@ static int condition_test_cpus(Condition *c) {
         return test_order(CMP((unsigned) n, k), order);
 }
 
-static int condition_test_user(Condition *c) {
+static int condition_test_user(Condition *c, char **env) {
         uid_t id;
         int r;
         _cleanup_free_ char *username = NULL;
@@ -345,7 +345,7 @@ static int condition_test_user(Condition *c) {
         return id == getuid() || id == geteuid();
 }
 
-static int condition_test_control_group_controller(Condition *c) {
+static int condition_test_control_group_controller(Condition *c, char **env) {
         int r;
         CGroupMask system_mask, wanted_mask = 0;
 
@@ -369,7 +369,7 @@ static int condition_test_control_group_controller(Condition *c) {
         return FLAGS_SET(system_mask, wanted_mask);
 }
 
-static int condition_test_group(Condition *c) {
+static int condition_test_group(Condition *c, char **env) {
         gid_t id;
         int r;
 
@@ -388,7 +388,7 @@ static int condition_test_group(Condition *c) {
         return in_group(c->parameter) > 0;
 }
 
-static int condition_test_virtualization(Condition *c) {
+static int condition_test_virtualization(Condition *c, char **env) {
         int b, v;
 
         assert(c);
@@ -418,7 +418,7 @@ static int condition_test_virtualization(Condition *c) {
         return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v));
 }
 
-static int condition_test_architecture(Condition *c) {
+static int condition_test_architecture(Condition *c, char **env) {
         int a, b;
 
         assert(c);
@@ -440,7 +440,7 @@ static int condition_test_architecture(Condition *c) {
         return a == b;
 }
 
-static int condition_test_host(Condition *c) {
+static int condition_test_host(Condition *c, char **env) {
         _cleanup_free_ char *h = NULL;
         sd_id128_t x, y;
         int r;
@@ -465,7 +465,7 @@ static int condition_test_host(Condition *c) {
         return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
 }
 
-static int condition_test_ac_power(Condition *c) {
+static int condition_test_ac_power(Condition *c, char **env) {
         int r;
 
         assert(c);
@@ -479,7 +479,7 @@ static int condition_test_ac_power(Condition *c) {
         return (on_ac_power() != 0) == !!r;
 }
 
-static int condition_test_security(Condition *c) {
+static int condition_test_security(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_SECURITY);
@@ -502,7 +502,7 @@ static int condition_test_security(Condition *c) {
         return false;
 }
 
-static int condition_test_capability(Condition *c) {
+static int condition_test_capability(Condition *c, char **env) {
         unsigned long long capabilities = (unsigned long long) -1;
         _cleanup_fclose_ FILE *f = NULL;
         int value, r;
@@ -545,7 +545,7 @@ static int condition_test_capability(Condition *c) {
         return !!(capabilities & (1ULL << value));
 }
 
-static int condition_test_needs_update(Condition *c) {
+static int condition_test_needs_update(Condition *c, char **env) {
         const char *p;
         struct stat usr, other;
 
@@ -611,7 +611,7 @@ static int condition_test_needs_update(Condition *c) {
         return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
 }
 
-static int condition_test_first_boot(Condition *c) {
+static int condition_test_first_boot(Condition *c, char **env) {
         int r;
 
         assert(c);
@@ -625,7 +625,36 @@ static int condition_test_first_boot(Condition *c) {
         return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
 }
 
-static int condition_test_path_exists(Condition *c) {
+static int condition_test_environment(Condition *c, char **env) {
+        bool equal;
+        char **i;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_ENVIRONMENT);
+
+        equal = strchr(c->parameter, '=');
+
+        STRV_FOREACH(i, env) {
+                bool found;
+
+                if (equal)
+                        found = streq(c->parameter, *i);
+                else {
+                        const char *f;
+
+                        f = startswith(*i, c->parameter);
+                        found = f && IN_SET(*f, 0, '=');
+                }
+
+                if (found)
+                        return true;
+        }
+
+        return false;
+}
+
+static int condition_test_path_exists(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_PATH_EXISTS);
@@ -633,7 +662,7 @@ static int condition_test_path_exists(Condition *c) {
         return access(c->parameter, F_OK) >= 0;
 }
 
-static int condition_test_path_exists_glob(Condition *c) {
+static int condition_test_path_exists_glob(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_PATH_EXISTS_GLOB);
@@ -641,7 +670,7 @@ static int condition_test_path_exists_glob(Condition *c) {
         return glob_exists(c->parameter) > 0;
 }
 
-static int condition_test_path_is_directory(Condition *c) {
+static int condition_test_path_is_directory(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_PATH_IS_DIRECTORY);
@@ -649,7 +678,7 @@ static int condition_test_path_is_directory(Condition *c) {
         return is_dir(c->parameter, true) > 0;
 }
 
-static int condition_test_path_is_symbolic_link(Condition *c) {
+static int condition_test_path_is_symbolic_link(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
@@ -657,7 +686,7 @@ static int condition_test_path_is_symbolic_link(Condition *c) {
         return is_symlink(c->parameter) > 0;
 }
 
-static int condition_test_path_is_mount_point(Condition *c) {
+static int condition_test_path_is_mount_point(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
@@ -665,7 +694,7 @@ static int condition_test_path_is_mount_point(Condition *c) {
         return path_is_mount_point(c->parameter, NULL, AT_SYMLINK_FOLLOW) > 0;
 }
 
-static int condition_test_path_is_read_write(Condition *c) {
+static int condition_test_path_is_read_write(Condition *c, char **env) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_PATH_IS_READ_WRITE);
@@ -673,7 +702,7 @@ static int condition_test_path_is_read_write(Condition *c) {
         return path_is_read_only_fs(c->parameter) <= 0;
 }
 
-static int condition_test_path_is_encrypted(Condition *c) {
+static int condition_test_path_is_encrypted(Condition *c, char **env) {
         int r;
 
         assert(c);
@@ -687,7 +716,7 @@ static int condition_test_path_is_encrypted(Condition *c) {
         return r > 0;
 }
 
-static int condition_test_directory_not_empty(Condition *c) {
+static int condition_test_directory_not_empty(Condition *c, char **env) {
         int r;
 
         assert(c);
@@ -698,7 +727,7 @@ static int condition_test_directory_not_empty(Condition *c) {
         return r <= 0 && r != -ENOENT;
 }
 
-static int condition_test_file_not_empty(Condition *c) {
+static int condition_test_file_not_empty(Condition *c, char **env) {
         struct stat st;
 
         assert(c);
@@ -710,7 +739,7 @@ static int condition_test_file_not_empty(Condition *c) {
                 st.st_size > 0);
 }
 
-static int condition_test_file_is_executable(Condition *c) {
+static int condition_test_file_is_executable(Condition *c, char **env) {
         struct stat st;
 
         assert(c);
@@ -722,7 +751,7 @@ static int condition_test_file_is_executable(Condition *c) {
                 (st.st_mode & 0111));
 }
 
-static int condition_test_null(Condition *c) {
+static int condition_test_null(Condition *c, char **env) {
         assert(c);
         assert(c->type == CONDITION_NULL);
 
@@ -731,9 +760,9 @@ static int condition_test_null(Condition *c) {
         return true;
 }
 
-int condition_test(Condition *c) {
+int condition_test(Condition *c, char **env) {
 
-        static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = {
+        static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c, char **env) = {
                 [CONDITION_PATH_EXISTS]              = condition_test_path_exists,
                 [CONDITION_PATH_EXISTS_GLOB]         = condition_test_path_exists_glob,
                 [CONDITION_PATH_IS_DIRECTORY]        = condition_test_path_is_directory,
@@ -760,6 +789,7 @@ int condition_test(Condition *c) {
                 [CONDITION_NULL]                     = condition_test_null,
                 [CONDITION_CPUS]                     = condition_test_cpus,
                 [CONDITION_MEMORY]                   = condition_test_memory,
+                [CONDITION_ENVIRONMENT]              = condition_test_environment,
         };
 
         int r, b;
@@ -768,7 +798,7 @@ int condition_test(Condition *c) {
         assert(c->type >= 0);
         assert(c->type < _CONDITION_TYPE_MAX);
 
-        r = condition_tests[c->type](c);
+        r = condition_tests[c->type](c, env);
         if (r < 0) {
                 c->result = CONDITION_ERROR;
                 return r;
@@ -781,6 +811,7 @@ int condition_test(Condition *c) {
 
 bool condition_test_list(
                 Condition *first,
+                char **env,
                 condition_to_string_t to_string,
                 condition_test_logger_t logger,
                 void *userdata) {
@@ -800,7 +831,7 @@ bool condition_test_list(
         LIST_FOREACH(conditions, c, first) {
                 int r;
 
-                r = condition_test(c);
+                r = condition_test(c, env);
 
                 if (logger) {
                         const char *p = c->type == CONDITION_NULL ? "true" : c->parameter;
@@ -884,6 +915,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_NULL] = "ConditionNull",
         [CONDITION_CPUS] = "ConditionCPUs",
         [CONDITION_MEMORY] = "ConditionMemory",
+        [CONDITION_ENVIRONMENT] = "ConditionEnvironment",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
@@ -915,6 +947,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_NULL] = "AssertNull",
         [CONDITION_CPUS] = "AssertCPUs",
         [CONDITION_MEMORY] = "AssertMemory",
+        [CONDITION_ENVIRONMENT] = "AssertEnvironment",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);
index 11dfc7425b810af9f71b969ce5000e99eed2afea..fea74d228d8d0210433c438f524fb1b50829293e 100644 (file)
@@ -18,6 +18,7 @@ typedef enum ConditionType {
         CONDITION_AC_POWER,
         CONDITION_MEMORY,
         CONDITION_CPUS,
+        CONDITION_ENVIRONMENT,
 
         CONDITION_NEEDS_UPDATE,
         CONDITION_FIRST_BOOT,
@@ -73,11 +74,11 @@ static inline Condition* condition_free_list(Condition *first) {
         return condition_free_list_type(first, _CONDITION_TYPE_INVALID);
 }
 
-int condition_test(Condition *c);
+int condition_test(Condition *c, char **env);
 
 typedef int (*condition_test_logger_t)(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8);
-typedef const char* (*condition_to_string_t)(ConditionType t);
-bool condition_test_list(Condition *first, condition_to_string_t, condition_test_logger_t logger, void *userdata);
+typedef const char* (*condition_to_string_t)(ConditionType t) _const_;
+bool condition_test_list(Condition *first, char **env, condition_to_string_t to_string, condition_test_logger_t logger, void *userdata);
 
 void condition_dump(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string);
 void condition_dump_list(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string);
index 0c78194185d2b9e2795c5a4e1100695a37ddc0c9..ddf2e669c03c4f98fa3e795beb1c9069e1cd02bb 100644 (file)
@@ -39,87 +39,87 @@ static void test_condition_test_path(void) {
 
         condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition));
+        assert_se(condition_test(condition, environ));
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_ENCRYPTED, "/sys", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 }
 
@@ -139,12 +139,12 @@ static void test_condition_test_control_group_controller(void) {
         /* Invalid controllers are ignored */
         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         assert_se(cg_mask_supported(&system_mask) >= 0);
@@ -157,23 +157,23 @@ static void test_condition_test_control_group_controller(void) {
                         log_info("this controller is available");
                         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false);
                         assert_se(condition);
-                        assert_se(condition_test(condition) > 0);
+                        assert_se(condition_test(condition, environ) > 0);
                         condition_free(condition);
 
                         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
                         assert_se(condition);
-                        assert_se(condition_test(condition) == 0);
+                        assert_se(condition_test(condition, environ) == 0);
                         condition_free(condition);
                 } else {
                         log_info("this controller is unavailable");
                         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false);
                         assert_se(condition);
-                        assert_se(condition_test(condition) == 0);
+                        assert_se(condition_test(condition, environ) == 0);
                         condition_free(condition);
 
                         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
                         assert_se(condition);
-                        assert_se(condition_test(condition) > 0);
+                        assert_se(condition_test(condition, environ) > 0);
                         condition_free(condition);
                 }
         }
@@ -183,12 +183,12 @@ static void test_condition_test_control_group_controller(void) {
 
         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 }
 
@@ -197,17 +197,17 @@ static void test_condition_test_ac_power(void) {
 
         condition = condition_new(CONDITION_AC_POWER, "true", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == on_ac_power());
+        assert_se(condition_test(condition, environ) == on_ac_power());
         condition_free(condition);
 
         condition = condition_new(CONDITION_AC_POWER, "false", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) != on_ac_power());
+        assert_se(condition_test(condition, environ) != on_ac_power());
         condition_free(condition);
 
         condition = condition_new(CONDITION_AC_POWER, "false", false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == on_ac_power());
+        assert_se(condition_test(condition, environ) == on_ac_power());
         condition_free(condition);
 }
 
@@ -224,17 +224,17 @@ static void test_condition_test_host(void) {
 
         condition = condition_new(CONDITION_HOST, sid, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_HOST, sid, false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         hostname = gethostname_malloc();
@@ -246,7 +246,7 @@ static void test_condition_test_host(void) {
         else {
                 condition = condition_new(CONDITION_HOST, hostname, false, false);
                 assert_se(condition);
-                assert_se(condition_test(condition) > 0);
+                assert_se(condition_test(condition, environ) > 0);
                 condition_free(condition);
         }
 }
@@ -264,17 +264,17 @@ static void test_condition_test_architecture(void) {
 
         condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 }
 
@@ -284,7 +284,7 @@ static void test_condition_test_kernel_command_line(void) {
 
         condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         if (ERRNO_IS_PRIVILEGE(r))
                 return;
         assert_se(r == 0);
@@ -292,7 +292,7 @@ static void test_condition_test_kernel_command_line(void) {
 
         condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 }
 
@@ -303,26 +303,26 @@ static void test_condition_test_kernel_version(void) {
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         /* An artificially empty condition. It evaluates to true, but normally
          * such condition cannot be created, because the condition list is reset instead. */
         condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         assert_se(uname(&u) >= 0);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         strshorten(u.release, 4);
@@ -330,79 +330,79 @@ static void test_condition_test_kernel_version(void) {
 
         condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         /* 0.1.2 would be a very very very old kernel */
         condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == -EINVAL);
+        assert_se(condition_test(condition, environ) == -EINVAL);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == -EINVAL);
+        assert_se(condition_test(condition, environ) == -EINVAL);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         /* 4711.8.15 is a very very very future kernel */
         condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         assert_se(uname(&u) >= 0);
@@ -410,31 +410,31 @@ static void test_condition_test_kernel_version(void) {
         v = strjoina(">=", u.release);
         condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         v = strjoina("=  ", u.release);
         condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         v = strjoina("<=", u.release);
         condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         v = strjoina("> ", u.release);
         condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         v = strjoina("<   ", u.release);
         condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 }
 
@@ -443,12 +443,12 @@ static void test_condition_test_null(void) {
 
         condition = condition_new(CONDITION_NULL, NULL, false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) > 0);
+        assert_se(condition_test(condition, environ) > 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_NULL, NULL, false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 }
 
@@ -457,42 +457,42 @@ static void test_condition_test_security(void) {
 
         condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == 0);
+        assert_se(condition_test(condition, environ) == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) != mac_selinux_use());
+        assert_se(condition_test(condition, environ) != mac_selinux_use());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == mac_apparmor_use());
+        assert_se(condition_test(condition, environ) == mac_apparmor_use());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == mac_tomoyo_use());
+        assert_se(condition_test(condition, environ) == mac_tomoyo_use());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "ima", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == use_ima());
+        assert_se(condition_test(condition, environ) == use_ima());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "smack", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == mac_smack_use());
+        assert_se(condition_test(condition, environ) == mac_smack_use());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "audit", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == use_audit());
+        assert_se(condition_test(condition, environ) == use_audit());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "uefi-secureboot", false, false);
         assert_se(condition);
-        assert_se(condition_test(condition) == is_efi_secure_boot());
+        assert_se(condition_test(condition, environ) == is_efi_secure_boot());
         condition_free(condition);
 }
 
@@ -515,7 +515,7 @@ static void test_condition_test_virtualization(void) {
 
         condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         if (ERRNO_IS_PRIVILEGE(r))
                 return;
         log_info("ConditionVirtualization=garbage → %i", r);
@@ -524,21 +524,21 @@ static void test_condition_test_virtualization(void) {
 
         condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionVirtualization=container → %i", r);
         assert_se(r == !!detect_container());
         condition_free(condition);
 
         condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionVirtualization=vm → %i", r);
         assert_se(r == (detect_vm() && !detect_container()));
         condition_free(condition);
 
         condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionVirtualization=private-users → %i", r);
         assert_se(r == !!running_in_userns());
         condition_free(condition);
@@ -559,7 +559,7 @@ static void test_condition_test_virtualization(void) {
 
                 condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false);
                 assert_se(condition);
-                r = condition_test(condition);
+                r = condition_test(condition, environ);
                 log_info("ConditionVirtualization=%s → %i", virt, r);
                 assert_se(r >= 0);
                 condition_free(condition);
@@ -574,7 +574,7 @@ static void test_condition_test_user(void) {
 
         condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=garbage → %i", r);
         assert_se(r == 0);
         condition_free(condition);
@@ -582,7 +582,7 @@ static void test_condition_test_user(void) {
         assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0);
         condition = condition_new(CONDITION_USER, uid, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=%s → %i", uid, r);
         assert_se(r == 0);
         condition_free(condition);
@@ -591,7 +591,7 @@ static void test_condition_test_user(void) {
         assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0);
         condition = condition_new(CONDITION_USER, uid, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=%s → %i", uid, r);
         assert_se(r > 0);
         condition_free(condition);
@@ -600,7 +600,7 @@ static void test_condition_test_user(void) {
         assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0);
         condition = condition_new(CONDITION_USER, uid, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=%s → %i", uid, r);
         assert_se(r == 0);
         condition_free(condition);
@@ -610,7 +610,7 @@ static void test_condition_test_user(void) {
         assert_se(username);
         condition = condition_new(CONDITION_USER, username, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=%s → %i", username, r);
         assert_se(r > 0);
         condition_free(condition);
@@ -619,14 +619,14 @@ static void test_condition_test_user(void) {
         username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root");
         condition = condition_new(CONDITION_USER, username, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=%s → %i", username, r);
         assert_se(r == 0);
         condition_free(condition);
 
         condition = condition_new(CONDITION_USER, "@system", false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionUser=@system → %i", r);
         if (uid_is_system(getuid()) || uid_is_system(geteuid()))
                 assert_se(r > 0);
@@ -645,7 +645,7 @@ static void test_condition_test_group(void) {
         assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF)));
         condition = condition_new(CONDITION_GROUP, gid, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionGroup=%s → %i", gid, r);
         assert_se(r == 0);
         condition_free(condition);
@@ -654,7 +654,7 @@ static void test_condition_test_group(void) {
         assert_se(0 < asprintf(&gid, "%u", getgid()));
         condition = condition_new(CONDITION_GROUP, gid, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionGroup=%s → %i", gid, r);
         assert_se(r > 0);
         condition_free(condition);
@@ -673,7 +673,7 @@ static void test_condition_test_group(void) {
                 assert_se(0 < asprintf(&gid, "%u", gids[i]));
                 condition = condition_new(CONDITION_GROUP, gid, false, false);
                 assert_se(condition);
-                r = condition_test(condition);
+                r = condition_test(condition, environ);
                 log_info("ConditionGroup=%s → %i", gid, r);
                 assert_se(r > 0);
                 condition_free(condition);
@@ -684,7 +684,7 @@ static void test_condition_test_group(void) {
                 assert_se(groupname);
                 condition = condition_new(CONDITION_GROUP, groupname, false, false);
                 assert_se(condition);
-                r = condition_test(condition);
+                r = condition_test(condition, environ);
                 log_info("ConditionGroup=%s → %i", groupname, r);
                 assert_se(r > 0);
                 condition_free(condition);
@@ -695,7 +695,7 @@ static void test_condition_test_group(void) {
         assert_se(0 < asprintf(&gid, "%u", max_gid+1));
         condition = condition_new(CONDITION_GROUP, gid, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionGroup=%s → %i", gid, r);
         assert_se(r == 0);
         condition_free(condition);
@@ -704,7 +704,7 @@ static void test_condition_test_group(void) {
         groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root");
         condition = condition_new(CONDITION_GROUP, groupname, false, false);
         assert_se(condition);
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         log_info("ConditionGroup=%s → %i", groupname, r);
         assert_se(r == 0);
         condition_free(condition);
@@ -719,7 +719,7 @@ static void test_condition_test_cpus_one(const char *s, bool result) {
         condition = condition_new(CONDITION_CPUS, s, false, false);
         assert_se(condition);
 
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         assert_se(r >= 0);
         assert_se(r == result);
         condition_free(condition);
@@ -780,7 +780,7 @@ static void test_condition_test_memory_one(const char *s, bool result) {
         condition = condition_new(CONDITION_MEMORY, s, false, false);
         assert_se(condition);
 
-        r = condition_test(condition);
+        r = condition_test(condition, environ);
         assert_se(r >= 0);
         assert_se(r == result);
         condition_free(condition);
@@ -831,6 +831,34 @@ static void test_condition_test_memory(void) {
         t = mfree(t);
 }
 
+static void test_condition_test_environment_one(const char *s, bool result) {
+        Condition *condition;
+        int r;
+
+        log_debug("%s=%s", condition_type_to_string(CONDITION_ENVIRONMENT), s);
+
+        condition = condition_new(CONDITION_ENVIRONMENT, s, false, false);
+        assert_se(condition);
+
+        r = condition_test(condition, environ);
+        assert_se(r >= 0);
+        assert_se(r == result);
+        condition_free(condition);
+}
+
+static void test_condition_test_environment(void) {
+        assert_se(setenv("EXISTINGENVVAR", "foo", false) >= 0);
+
+        test_condition_test_environment_one("MISSINGENVVAR", false);
+        test_condition_test_environment_one("MISSINGENVVAR=foo", false);
+        test_condition_test_environment_one("MISSINGENVVAR=", false);
+
+        test_condition_test_environment_one("EXISTINGENVVAR", true);
+        test_condition_test_environment_one("EXISTINGENVVAR=foo", true);
+        test_condition_test_environment_one("EXISTINGENVVAR=bar", false);
+        test_condition_test_environment_one("EXISTINGENVVAR=", false);
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
@@ -849,6 +877,7 @@ int main(int argc, char *argv[]) {
         test_condition_test_control_group_controller();
         test_condition_test_cpus();
         test_condition_test_memory();
+        test_condition_test_environment();
 
         return 0;
 }
index e4ace761b72c22fab646d17b1e9a48f16207a702..530ef57e734874961992bed0bbe6bf2daa2529ad 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <linux/netdevice.h>
 #include <netinet/ether.h>
+#include <unistd.h>
 
 #include "sd-device.h"
 #include "sd-netlink.h"
@@ -173,7 +174,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
                 return 0;
         }
 
-        if (!condition_test_list(link->conditions, NULL, NULL, NULL)) {
+        if (!condition_test_list(link->conditions, environ, NULL, NULL, NULL)) {
                 log_debug("%s: Conditions do not match the system environment, skipping.", filename);
                 return 0;
         }