Portage's env-update currently transforms the environment information from /etc/env.d into /etc/profile.env, which is typically sourced by every user session, setting up its environment.
However, /etc/profile.env is not sourced by systemd user services. Instead, for the definition of a systemd user session environment, the 'environment.d' machinery exists. Unfortunately, up to now, env-update does not produce a profile.env equivalent for this machinery, causing issues for systemd user services. For example, an emacs daemon run as user systemd service does not have a complete PATH (bug #704412 [1]), because some PATH components are injected by packages via /etc/env.d. For example, an LLVM ebuild may set PATH="/usr/lib/llvm/9/bin". This commit changes env-update so that a systemd user session environment configuration file named /etc/environment.d/10-gentoo-env.conf is created. Thanks to Michael 'veremitz' Everitt, Arfrever Frehtes Taifersar Arahesis, Ulrich Müller, Joakim Tjernlund, and Zac Medico for the useful feedback. 1: https://bugs.gentoo.org/704412 Closes: https://bugs.gentoo.org/704416 Signed-off-by: Florian Schmaus <f...@geekplace.eu> --- Notes: - Shorten created filename to 10-gentoo-env.conf - Minor fixes in the commit message - Use atomic_ofstream() - Use os.makedirs() (Thanks Zac) lib/portage/util/env_update.py | 42 +++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py index f130b6f6b..ab3caee47 100644 --- a/lib/portage/util/env_update.py +++ b/lib/portage/util/env_update.py @@ -333,14 +333,16 @@ def _env_update(makelinks, target_root, prev_mtimes, contents, env, del specials["LDPATH"] - penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n" - penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n" + notice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n" + notice += "# DO NOT EDIT THIS FILE." + penvnotice = notice + " CHANGES TO STARTUP PROFILES\n" cenvnotice = penvnotice[:] penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n" cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n" #create /etc/profile.env for bash support - outfile = atomic_ofstream(os.path.join(eroot, "etc", "profile.env")) + profile_env_path = os.path.join(eroot, "etc", "profile.env") + outfile = atomic_ofstream(profile_env_path) outfile.write(penvnotice) env_keys = [x for x in env if x != "LDPATH"] @@ -353,6 +355,40 @@ def _env_update(makelinks, target_root, prev_mtimes, contents, env, outfile.write("export %s='%s'\n" % (k, v)) outfile.close() + # Create the systemd user environment configuration file + # /etc/environment.d/10-gentoo-env.conf with the + # environment configuration from /etc/env.d. + systemd_environment_dir = os.path.join(eroot, "etc", "environment.d") + os.makedirs(systemd_environment_dir, exist_ok=True) + + systemd_gentoo_env_path = os.path.join(systemd_environment_dir, + "10-gentoo-env.conf") + systemd_gentoo_env = atomic_ofstream(systemd_gentoo_env_path) + try: + senvnotice = notice + "\n\n" + systemd_gentoo_env.write(senvnotice) + + for env_key in env_keys: + env_key_value = env[env_key] + + # Skip variables with the empty string + # as value. Those sometimes appear in + # profile.env (e.g. "export GCC_SPECS=''"), + # but are invalid in systemd's syntax. + if not env_key_value: + continue + + # Transform into systemd environment.d + # conf syntax, basically shell variable + # assignment (without "export "). + line = f"{env_key}={env_key_value}\n" + + systemd_gentoo_env.write(line) + except: + systemd_gentoo_env.abort() + raise + systemd_gentoo_env.close() + #create /etc/csh.env for (t)csh support outfile = atomic_ofstream(os.path.join(eroot, "etc", "csh.env")) outfile.write(cenvnotice) -- 2.26.2