Blob Blame History Raw
From 1ccda26d327a16e6345b00748295b857cbbde166 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sun, 7 May 2017 12:43:48 +0200
Subject: [PATCH 1/2] dbus needs to be updated to get all user-defined
 environment when the session starts.

dbus-update-activation-environment excepts certain environment
variables, that systemd won't.  We're going to want to eventually
send the environment to systemd, too, so we should make sure the
same set of variables get sent to both.

See: https://bugzilla.gnome.org/show_bug.cgi?id=736660
---
 mate-session/gsm-util.c | 123 ++++++++++++++++++++++++++++++++++++------------
 mate-session/gsm-util.h |   2 +
 mate-session/main.c     |   3 ++
 3 files changed, 99 insertions(+), 29 deletions(-)

diff --git a/mate-session/gsm-util.c b/mate-session/gsm-util.c
index 6320b24..b026f12 100644
--- a/mate-session/gsm-util.c
+++ b/mate-session/gsm-util.c
@@ -435,54 +435,119 @@ gsm_util_update_activation_environment (const char  *variable,
                                         const char  *value,
                                         GError     **error)
 {
-        DBusGConnection *dbus_connection;
-        DBusGProxy      *bus_proxy;
-        GHashTable      *environment;
+        GDBusConnection *connection;
         gboolean         environment_updated;
+        GVariantBuilder  builder;
+        GVariant        *reply;
+        GError          *bus_error = NULL;
 
         environment_updated = FALSE;
-        bus_proxy = NULL;
-        environment = NULL;
+        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
 
-        dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+        if (connection == NULL) {
+                return FALSE;
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+        g_variant_builder_add (&builder, "{ss}", variable, value);
+
+        reply = g_dbus_connection_call_sync (connection,
+                                             "org.freedesktop.DBus",
+                                             "/org/freedesktop/DBus",
+                                             "org.freedesktop.DBus",
+                                             "UpdateActivationEnvironment",
+                                             g_variant_new ("(@a{ss})",
+                                                            g_variant_builder_end (&builder)),
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1, NULL, &bus_error);
+
+        if (bus_error != NULL) {
+                g_propagate_error (error, bus_error);
+        } else {
+                environment_updated = TRUE;
+                g_variant_unref (reply);
+        }
 
-        if (dbus_connection == NULL) {
+        g_clear_object (&connection);
+
+        return environment_updated;
+}
+
+gboolean
+gsm_util_export_activation_environment (GError     **error)
+{
+        GDBusConnection *connection;
+        gboolean         environment_updated = FALSE;
+        char           **entry_names;
+        int              i = 0;
+        GVariantBuilder  builder;
+        GRegex          *name_regex, *value_regex;
+        GVariant        *reply;
+        GError          *bus_error = NULL;
+
+        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+
+        if (connection == NULL) {
                 return FALSE;
         }
 
-        bus_proxy = dbus_g_proxy_new_for_name_owner (dbus_connection,
-                                                     DBUS_SERVICE_DBUS,
-                                                     DBUS_PATH_DBUS,
-                                                     DBUS_INTERFACE_DBUS,
-                                                     error);
+        name_regex = g_regex_new ("^[a-zA-Z_][a-zA-Z0-9_]*$", G_REGEX_OPTIMIZE, 0, error);
 
-        if (bus_proxy == NULL) {
-                goto out;
+        if (name_regex == NULL) {
+                return FALSE;
         }
 
-        environment = g_hash_table_new (g_str_hash, g_str_equal);
+        value_regex = g_regex_new ("^([[:blank:]]|[^[:cntrl:]])*$", G_REGEX_OPTIMIZE, 0, error);
 
-        g_hash_table_insert (environment, (void *) variable, (void *) value);
+        if (value_regex == NULL) {
+                return FALSE;
+        }
 
-        if (!dbus_g_proxy_call (bus_proxy,
-                                "UpdateActivationEnvironment", error,
-                                DBUS_TYPE_G_STRING_STRING_HASHTABLE,
-                                environment, G_TYPE_INVALID,
-                                G_TYPE_INVALID))
-                goto out;
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+        for (entry_names = g_listenv (); entry_names[i] != NULL; i++) {
+                const char *entry_name = entry_names[i];
+                const char *entry_value = g_getenv (entry_name);
 
-        environment_updated = TRUE;
+                if (!g_utf8_validate (entry_name, -1, NULL))
+                    continue;
 
- out:
+                if (!g_regex_match (name_regex, entry_name, 0, NULL))
+                    continue;
 
-        if (bus_proxy != NULL) {
-                g_object_unref (bus_proxy);
-        }
+                if (!g_utf8_validate (entry_value, -1, NULL))
+                    continue;
 
-        if (environment != NULL) {
-                g_hash_table_destroy (environment);
+                if (!g_regex_match (value_regex, entry_value, 0, NULL))
+                    continue;
+
+                g_variant_builder_add (&builder, "{ss}", entry_name, entry_value);
+        }
+        g_regex_unref (name_regex);
+        g_regex_unref (value_regex);
+
+        g_strfreev (entry_names);
+
+        reply = g_dbus_connection_call_sync (connection,
+                                             "org.freedesktop.DBus",
+                                             "/org/freedesktop/DBus",
+                                             "org.freedesktop.DBus",
+                                             "UpdateActivationEnvironment",
+                                             g_variant_new ("(@a{ss})",
+                                                            g_variant_builder_end (&builder)),
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1, NULL, &bus_error);
+
+        if (bus_error != NULL) {
+                g_propagate_error (error, bus_error);
+        } else {
+                environment_updated = TRUE;
+                g_variant_unref (reply);
         }
 
+        g_clear_object (&connection);
+
         return environment_updated;
 }
 
diff --git a/mate-session/gsm-util.h b/mate-session/gsm-util.h
index efc980c..112ce6f 100644
--- a/mate-session/gsm-util.h
+++ b/mate-session/gsm-util.h
@@ -48,6 +48,8 @@ void        gsm_util_init_error                     (gboolean    fatal,
 
 char *      gsm_util_generate_startup_id            (void);
 
+gboolean    gsm_util_export_activation_environment  (GError     **error);
+
 void        gsm_util_setenv                         (const char *variable,
                                                      const char *value);
 
diff --git a/mate-session/main.c b/mate-session/main.c
index db55ebd..da931af 100644
--- a/mate-session/main.c
+++ b/mate-session/main.c
@@ -620,6 +620,8 @@ int main(int argc, char** argv)
 		exit(1);
 	}
 
+        gsm_util_export_activation_environment (NULL);
+
 	mdm_log_init();
 
 	/* Allows to enable/disable debug from GSettings only if it is not set from argument */
@@ -727,3 +729,4 @@ int main(int argc, char** argv)
 
 	return 0;
 }
+

From f992dd90dab0814085dcc2e09f787ec8dd4b7da6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sun, 7 May 2017 12:48:32 +0200
Subject: [PATCH 2/2] systemd user-session needs to be updated to get all
 user-defined enviroment when the session starts.

If we get passed an environment variable, send it along to the
systemd --user session so things running in that context can pick
it up.

See: https://bugzilla.gnome.org/show_bug.cgi?id=736660
---
 mate-session/gsm-util.c | 131 +++++++++++++++++++++++++++++++++++++++++++++---
 mate-session/gsm-util.h |   4 ++
 mate-session/main.c     |   4 ++
 3 files changed, 133 insertions(+), 6 deletions(-)

diff --git a/mate-session/gsm-util.c b/mate-session/gsm-util.c
index b026f12..92e813b 100644
--- a/mate-session/gsm-util.c
+++ b/mate-session/gsm-util.c
@@ -551,21 +551,140 @@ gsm_util_export_activation_environment (GError     **error)
         return environment_updated;
 }
 
+#ifdef HAVE_SYSTEMD
+gboolean
+gsm_util_export_user_environment (GError     **error)
+{
+        GDBusConnection *connection;
+        gboolean         environment_updated = FALSE;
+        char           **entries;
+        int              i = 0;
+        GVariantBuilder  builder;
+        GRegex          *regex;
+        GVariant        *reply;
+        GError          *bus_error = NULL;
+
+        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+
+        if (connection == NULL) {
+                return FALSE;
+        }
+
+        regex = g_regex_new ("^[a-zA-Z_][a-zA-Z0-9_]*=([[:blank:]]|[^[:cntrl:]])*$", G_REGEX_OPTIMIZE, 0, error);
+
+        if (regex == NULL) {
+                return FALSE;
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+        for (entries = g_get_environ (); entries[i] != NULL; i++) {
+                const char *entry = entries[i];
+
+                if (!g_utf8_validate (entry, -1, NULL))
+                    continue;
+
+                if (!g_regex_match (regex, entry, 0, NULL))
+                    continue;
+
+                g_variant_builder_add (&builder, "s", entry);
+        }
+        g_regex_unref (regex);
+
+        g_strfreev (entries);
+
+        reply = g_dbus_connection_call_sync (connection,
+                                             "org.freedesktop.systemd1",
+                                             "/org/freedesktop/systemd1",
+                                             "org.freedesktop.systemd1.Manager",
+                                             "SetEnvironment",
+                                             g_variant_new ("(@as)",
+                                                            g_variant_builder_end (&builder)),
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1, NULL, &bus_error);
+
+        if (bus_error != NULL) {
+                g_propagate_error (error, bus_error);
+        } else {
+                environment_updated = TRUE;
+                g_variant_unref (reply);
+        }
+
+        g_clear_object (&connection);
+
+        return environment_updated;
+}
+
+static gboolean
+gsm_util_update_user_environment (const char  *variable,
+                                  const char  *value,
+                                  GError     **error)
+{
+        GDBusConnection *connection;
+        gboolean         environment_updated;
+        char            *entry;
+        GVariantBuilder  builder;
+        GVariant        *reply;
+        GError          *bus_error = NULL;
+
+        environment_updated = FALSE;
+        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+
+        if (connection == NULL) {
+                return FALSE;
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+        entry = g_strdup_printf ("%s=%s", variable, value);
+        g_variant_builder_add (&builder, "s", entry);
+        g_free (entry);
+
+        reply = g_dbus_connection_call_sync (connection,
+                                             "org.freedesktop.systemd1",
+                                             "/org/freedesktop/systemd1",
+                                             "org.freedesktop.systemd1.Manager",
+                                             "SetEnvironment",
+                                             g_variant_new ("(@as)",
+                                                            g_variant_builder_end (&builder)),
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1, NULL, &bus_error);
+
+        if (bus_error != NULL) {
+                g_propagate_error (error, bus_error);
+        } else {
+                environment_updated = TRUE;
+                g_variant_unref (reply);
+        }
+
+        g_clear_object (&connection);
+
+        return environment_updated;
+}
+#endif
+
 void
 gsm_util_setenv (const char *variable,
                  const char *value)
 {
-        GError *bus_error;
+        GError *error = NULL;
 
         g_setenv (variable, value, TRUE);
 
-        bus_error = NULL;
-
         /* If this fails it isn't fatal, it means some things like session
          * management and keyring won't work in activated clients.
          */
-        if (!gsm_util_update_activation_environment (variable, value, &bus_error)) {
-                g_warning ("Could not make bus activated clients aware of %s=%s environment variable: %s", variable, value, bus_error->message);
-                g_error_free (bus_error);
+        if (!gsm_util_update_activation_environment (variable, value, &error)) {
+                g_warning ("Could not make bus activated clients aware of %s=%s environment variable: %s", variable, value, error->message);
+                g_clear_error (&error);
+        }
+
+#ifdef HAVE_SYSTEMD
+        /* If this fails, the system user session won't get the updated environment
+         */
+        if (!gsm_util_update_user_environment (variable, value, &error)) {
+                g_debug ("Could not make systemd aware of %s=%s environment variable: %s", variable, value, error->message);
+                g_clear_error (&error);
         }
+#endif
 }
diff --git a/mate-session/gsm-util.h b/mate-session/gsm-util.h
index 112ce6f..2c406af 100644
--- a/mate-session/gsm-util.h
+++ b/mate-session/gsm-util.h
@@ -50,6 +50,10 @@ char *      gsm_util_generate_startup_id            (void);
 
 gboolean    gsm_util_export_activation_environment  (GError     **error);
 
+#ifdef HAVE_SYSTEMD
+gboolean    gsm_util_export_user_environment        (GError     **error);
+#endif
+
 void        gsm_util_setenv                         (const char *variable,
                                                      const char *value);
 
diff --git a/mate-session/main.c b/mate-session/main.c
index da931af..161772d 100644
--- a/mate-session/main.c
+++ b/mate-session/main.c
@@ -622,6 +622,10 @@ int main(int argc, char** argv)
 
         gsm_util_export_activation_environment (NULL);
 
+#ifdef HAVE_SYSTEMD
+        gsm_util_export_user_environment (NULL);
+#endif
+
 	mdm_log_init();
 
 	/* Allows to enable/disable debug from GSettings only if it is not set from argument */