summaryrefslogtreecommitdiff
path: root/src/core/manager.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-01-22 01:13:47 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-02-20 18:49:14 -0500
commit64691d2024d3bd202c85c52069f185afee2b8e43 (patch)
treea38e863f935614e0fda9aebe03e77c69b2a0f11d /src/core/manager.c
parent3303d1b2dc3f9ac88927c23abce020fc77c1e92c (diff)
manager: run environment generators
Environment file generators are a lot like unit file generators, but not exactly: 1. environment file generators are run for each manager instance, and their output is (or at least can be) individualized. The generators themselves are system-wide, the same for all users. 2. environment file generators are run sequentially, in priority order. Thus, the lifetime of those files is tied to lifecycle of the manager instance. Because generators are run sequentially, later generators can use or modify the output of earlier generators. Each generator is run with no arguments, and the whole state is stored in the environment variables. The generator can echo a set of variable assignments to standard output: VAR_A=something VAR_B=something else This output is parsed, and the next and subsequent generators run with those updated variables in the environment. After the last generator is done, the environment that the manager itself exports is updated. Each generator must return 0, otherwise the output is ignored. The generators in */user-env-generator are for the user session managers, including root, and the ones in */system-env-generator are for pid1.
Diffstat (limited to 'src/core/manager.c')
-rw-r--r--src/core/manager.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/src/core/manager.c b/src/core/manager.c
index 6bbda1af0d..aefe4ca780 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -103,6 +103,7 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32
static int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
static int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
+static int manager_run_environment_generators(Manager *m);
static int manager_run_generators(Manager *m);
static void manager_watch_jobs_in_progress(Manager *m) {
@@ -1262,6 +1263,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
if (r < 0)
return r;
+ r = manager_run_environment_generators(m);
+ if (r < 0)
+ return r;
+
/* Make sure the transient directory always exists, so that it remains in the search path */
if (!m->test_run) {
r = mkdir_p_label(m->lookup_paths.transient, 0755);
@@ -2795,6 +2800,10 @@ int manager_reload(Manager *m) {
if (q < 0 && r >= 0)
r = q;
+ q = manager_run_environment_generators(m);
+ if (q < 0 && r >= 0)
+ r = q;
+
/* Find new unit paths */
q = manager_run_generators(m);
if (q < 0 && r >= 0)
@@ -2986,10 +2995,56 @@ void manager_check_finished(Manager *m) {
manager_invalidate_startup_units(m);
}
+static bool generator_path_any(const char* const* paths) {
+ char **path;
+ bool found = false;
+
+ /* Optimize by skipping the whole process by not creating output directories
+ * if no generators are found. */
+ STRV_FOREACH(path, (char**) paths)
+ if (access(*path, F_OK) == 0)
+ found = true;
+ else if (errno != ENOENT)
+ log_warning_errno(errno, "Failed to open generator directory %s: %m", *path);
+
+ return found;
+}
+
+static const char* system_env_generator_binary_paths[] = {
+ "/run/systemd/system-environment-generators",
+ "/etc/systemd/system-environment-generators",
+ "/usr/local/lib/systemd/system-environment-generators",
+ SYSTEM_ENV_GENERATOR_PATH,
+ NULL
+};
+
+static const char* user_env_generator_binary_paths[] = {
+ "/run/systemd/user-environment-generators",
+ "/etc/systemd/user-environment-generators",
+ "/usr/local/lib/systemd/user-environment-generators",
+ USER_ENV_GENERATOR_PATH,
+ NULL
+};
+
+static int manager_run_environment_generators(Manager *m) {
+ char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
+ const char **paths;
+ void* args[] = {&tmp, &tmp, &m->environment};
+
+ if (m->test_run)
+ return 0;
+
+ paths = MANAGER_IS_SYSTEM(m) ? system_env_generator_binary_paths : user_env_generator_binary_paths;
+
+ if (!generator_path_any(paths))
+ return 0;
+
+ return execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL);
+}
+
static int manager_run_generators(Manager *m) {
_cleanup_strv_free_ char **paths = NULL;
const char *argv[5];
- char **path;
int r;
assert(m);
@@ -3001,18 +3056,9 @@ static int manager_run_generators(Manager *m) {
if (!paths)
return log_oom();
- /* Optimize by skipping the whole process by not creating output directories
- * if no generators are found. */
- STRV_FOREACH(path, paths) {
- if (access(*path, F_OK) >= 0)
- goto found;
- if (errno != ENOENT)
- log_warning_errno(errno, "Failed to open generator directory %s: %m", *path);
- }
-
- return 0;
+ if (!generator_path_any((const char* const*) paths))
+ return 0;
- found:
r = lookup_paths_mkdir_generator(&m->lookup_paths);
if (r < 0)
goto finish;