From 49346b0bf62ee2a887b843646df9f1f6b6f80183 Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Sat, 28 Nov 2020 07:18:06 -0800 Subject: [PATCH] Support importing environment variables from environment.d systemd provides a desktop diagnostic place for user to set environment variables. Currently we only export to it but didn't import from it. This would also import from it so we are able to use environment.d to set environment even systemd unit based plasma is not used. --- startkde/startplasma-wayland.cpp | 5 +++ startkde/startplasma-x11.cpp | 5 +++ startkde/startplasma.cpp | 60 ++++++++++++++++++++++++++------ startkde/startplasma.h | 1 + 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/startkde/startplasma-wayland.cpp b/startkde/startplasma-wayland.cpp index 500435853..1c87b3734 100644 --- a/startkde/startplasma-wayland.cpp +++ b/startkde/startplasma-wayland.cpp @@ -86,6 +86,11 @@ int main(int argc, char** argv) return 1; } + // We import systemd environment after we sync the dbus environment here. + // Otherwise it may leads to some unwanted order of applying environment + // variables (e.g. LANG and LC_*) + importSystemdEnvrionment(); + QStringList args; if (argc > 1) { args.reserve(argc); diff --git a/startkde/startplasma-x11.cpp b/startkde/startplasma-x11.cpp index ae1c4d101..198f078f9 100644 --- a/startkde/startplasma-x11.cpp +++ b/startkde/startplasma-x11.cpp @@ -101,6 +101,11 @@ int main(int argc, char** argv) return 1; } + // We import systemd environment after we sync the dbus environment here. + // Otherwise it may leads to some unwanted order of applying environment + // variables (e.g. LANG and LC_*) + importSystemdEnvrionment(); + if (!startPlasmaSession(false)) return 1; diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp index 77ea56cd1..756806942 100644 --- a/startkde/startplasma.cpp +++ b/startkde/startplasma.cpp @@ -88,6 +88,23 @@ int runSync(const QString& program, const QStringList &args, const QStringList & return p.exitCode(); } +// A helper function to set an environment string in the form of VAR=VALUE. +void setEnvironmentVariable(const QByteArray &env) { + if (env.startsWith("_=") || env.startsWith("SHLVL")) { + return; + } + + const int idx = env.indexOf('='); + if (Q_UNLIKELY(idx <= 0)) { + return; + } + + if (qgetenv(env.left(idx)) != env.mid(idx+1)) { +// qCDebug(PLASMA_STARTUP) << "setting..." << env.left(idx) << env.mid(idx+1) << "was" << qgetenv(env.left(idx)); + qputenv(env.left(idx), env.mid(idx+1)); + } +} + void sourceFiles(const QStringList &files) { QStringList filteredFiles; @@ -106,17 +123,7 @@ void sourceFiles(const QStringList &files) auto envs = fullEnv.split('\0'); for (auto &env: envs) { - if (env.startsWith("_=") || env.startsWith("SHLVL")) - continue; - - const int idx = env.indexOf('='); - if (Q_UNLIKELY(idx <= 0)) - continue; - - if (qgetenv(env.left(idx)) != env.mid(idx+1)) { -// qCDebug(PLASMA_STARTUP) << "setting..." << env.left(idx) << env.mid(idx+1) << "was" << qgetenv(env.left(idx)); - qputenv(env.left(idx), env.mid(idx+1)); - } + setEnvironmentVariable(env); } } @@ -181,6 +188,37 @@ void setupCursor(bool wayland) qputenv("XCURSOR_SIZE", QByteArray::number(kcminputrc_mouse_cursorsize)); } +// Import systemd user environment. +// +// Systemd read ~/.config/environment.d which applies to all systemd user unit. +// But it won't work if plasma is not started by systemd. +void importSystemdEnvrionment() { + + auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), + QStringLiteral("/org/freedesktop/systemd1"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("Get")); + msg << QStringLiteral("org.freedesktop.systemd1.Manager") << QStringLiteral("Environment"); + auto reply = QDBusConnection::sessionBus().call(msg); + if (reply.type() == QDBusMessage::ErrorMessage) { + return; + } + + // Make sure the returned type is correct. + auto arguments = reply.arguments(); + if (arguments.isEmpty() || arguments[0].userType() != qMetaTypeId()) { + return; + } + auto variant = qdbus_cast(arguments[0]); + if (variant.type() != QVariant::StringList) { + return; + } + + for (auto &envString : variant.toStringList()) { + setEnvironmentVariable(envString.toLocal8Bit()); + } +} + // Source scripts found in /plasma-workspace/env/*.sh // (where correspond to the system and user's configuration // directory. diff --git a/startkde/startplasma.h b/startkde/startplasma.h index 1703d62c4..8d56b9b84 100644 --- a/startkde/startplasma.h +++ b/startkde/startplasma.h @@ -34,6 +34,7 @@ void messageBox(const QString &text); void createConfigDirectory(); void runStartupConfig(); void setupCursor(bool wayland); +void importSystemdEnvrionment(); void runEnvironmentScripts(); void setupPlasmaEnvironment(); void cleanupPlasmaEnvironment();