diff --git a/src/core/manager.c b/src/core/manager.c index 2f60b14159..a68324affc 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3665,9 +3665,67 @@ static int manager_run_environment_generators(Manager *m) { return r; } +static int build_generator_environment(Manager *m, char ***ret) { + _cleanup_strv_free_ char **nl = NULL; + Virtualization v; + int r; + + assert(m); + assert(ret); + + /* Generators oftentimes want to know some basic facts about the environment they run in, in order to + * adjust generated units to that. Let's pass down some bits of information that are easy for us to + * determine (but a bit harder for generator scripts to determine), as environment variables. */ + + nl = strv_copy(m->transient_environment); + if (!nl) + return -ENOMEM; + + r = strv_env_assign(&nl, "SYSTEMD_SCOPE", MANAGER_IS_SYSTEM(m) ? "system" : "user"); + if (r < 0) + return r; + + if (MANAGER_IS_SYSTEM(m)) { + /* Note that $SYSTEMD_IN_INITRD may be used to override the initrd detection in much of our + * codebase. This is hence more than purely informational. It will shortcut detection of the + * initrd state if generators invoke our own tools. But that's OK, as it would come to the + * same results (hopefully). */ + r = strv_env_assign(&nl, "SYSTEMD_IN_INITRD", one_zero(in_initrd())); + if (r < 0) + return r; + + if (m->first_boot >= 0) { + r = strv_env_assign(&nl, "SYSTEMD_FIRST_BOOT", one_zero(m->first_boot)); + if (r < 0) + return r; + } + } + + v = detect_virtualization(); + if (v < 0) + log_debug_errno(v, "Failed to detect virtualization, ignoring: %m"); + else if (v > 0) { + const char *s; + + s = strjoina(VIRTUALIZATION_IS_VM(v) ? "vm:" : + VIRTUALIZATION_IS_CONTAINER(v) ? "container:" : ":", + virtualization_to_string(v)); + + r = strv_env_assign(&nl, "SYSTEMD_VIRTUALIZATION", s); + if (r < 0) + return r; + } + + r = strv_env_assign(&nl, "SYSTEMD_ARCHITECTURE", architecture_to_string(uname_architecture())); + if (r < 0) + return r; + + *ret = TAKE_PTR(nl); + return 0; +} + static int manager_run_generators(Manager *m) { - _cleanup_strv_free_ char **paths = NULL; - const char *argv[5]; + _cleanup_strv_free_ char **paths = NULL, **ge = NULL; int r; assert(m); @@ -3688,16 +3746,28 @@ static int manager_run_generators(Manager *m) { goto finish; } - argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */ - argv[1] = m->lookup_paths.generator; - argv[2] = m->lookup_paths.generator_early; - argv[3] = m->lookup_paths.generator_late; - argv[4] = NULL; + const char *argv[] = { + NULL, /* Leave this empty, execute_directory() will fill something in */ + m->lookup_paths.generator, + m->lookup_paths.generator_early, + m->lookup_paths.generator_late, + NULL, + }; + + r = build_generator_environment(m, &ge); + if (r < 0) { + log_error_errno(r, "Failed to build generator environment: %m"); + goto finish; + } RUN_WITH_UMASK(0022) - (void) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, NULL, NULL, - (char**) argv, m->transient_environment, - EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS | EXEC_DIR_SET_SYSTEMD_EXEC_PID); + (void) execute_directories( + (const char* const*) paths, + DEFAULT_TIMEOUT_USEC, + /* callbacks= */ NULL, /* callback_args= */ NULL, + (char**) argv, + ge, + EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS | EXEC_DIR_SET_SYSTEMD_EXEC_PID); r = 0;