summaryrefslogtreecommitdiff
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
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.
-rw-r--r--Makefile.am6
-rw-r--r--src/core/macros.systemd.in2
-rw-r--r--src/core/manager.c70
3 files changed, 66 insertions, 12 deletions
diff --git a/Makefile.am b/Makefile.am
index 003ec9bfb7..f6699252d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -80,6 +80,8 @@ networkdir=$(rootprefix)/lib/systemd/network
pkgincludedir=$(includedir)/systemd
systemgeneratordir=$(rootlibexecdir)/system-generators
usergeneratordir=$(prefix)/lib/systemd/user-generators
+systemenvgeneratordir=$(prefix)/lib/systemd/system-environment-generators
+userenvgeneratordir=$(prefix)/lib/systemd/user-environment-generators
systemshutdowndir=$(rootlibexecdir)/system-shutdown
systemsleepdir=$(rootlibexecdir)/system-sleep
systemunitdir=$(rootprefix)/lib/systemd/system
@@ -205,6 +207,8 @@ AM_CPPFLAGS = \
-DSYSTEMD_CRYPTSETUP_PATH=\"$(rootlibexecdir)/systemd-cryptsetup\" \
-DSYSTEM_GENERATOR_PATH=\"$(systemgeneratordir)\" \
-DUSER_GENERATOR_PATH=\"$(usergeneratordir)\" \
+ -DSYSTEM_ENV_GENERATOR_PATH=\"$(systemenvgeneratordir)\" \
+ -DUSER_ENV_GENERATOR_PATH=\"$(userenvgeneratordir)\" \
-DSYSTEM_SHUTDOWN_PATH=\"$(systemshutdowndir)\" \
-DSYSTEM_SLEEP_PATH=\"$(systemsleepdir)\" \
-DSYSTEMD_KBD_MODEL_MAP=\"$(pkgdatadir)/kbd-model-map\" \
@@ -6210,6 +6214,8 @@ substitutions = \
'|sysctldir=$(sysctldir)|' \
'|systemgeneratordir=$(systemgeneratordir)|' \
'|usergeneratordir=$(usergeneratordir)|' \
+ '|systemenvgeneratordir=$(systemenvgeneratordir)|' \
+ '|userenvgeneratordir=$(userenvgeneratordir)|' \
'|CERTIFICATEROOT=$(CERTIFICATEROOT)|' \
'|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
'|PACKAGE_NAME=$(PACKAGE_NAME)|' \
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index 8d7ce1c238..a2a7edd1ee 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -31,6 +31,8 @@
%_binfmtdir @binfmtdir@
%_systemdgeneratordir @systemgeneratordir@
%_systemdusergeneratordir @usergeneratordir@
+%_systemd_system_env_generator_dir @systemenvgeneratordir@
+%_systemd_user_env_generator_dir @userenvgeneratordir@
%systemd_requires \
Requires(post): systemd \
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;