Blob Blame History Raw
From b92cc4ed3c71413a10f64a86e548d47133d203eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sat, 6 May 2017 23:04:08 +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
---
 cinnamon-session/csm-util.c | 123 +++++++++++++++++++++++++++++++++-----------
 cinnamon-session/csm-util.h |   2 +
 cinnamon-session/main.c     |   2 +
 3 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/cinnamon-session/csm-util.c b/cinnamon-session/csm-util.c
index 4fdd6d7..94d16fd 100644
--- a/cinnamon-session/csm-util.c
+++ b/cinnamon-session/csm-util.c
@@ -505,54 +505,119 @@ csm_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
+csm_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/cinnamon-session/csm-util.h b/cinnamon-session/csm-util.h
index 6076867..b2392b9 100644
--- a/cinnamon-session/csm-util.h
+++ b/cinnamon-session/csm-util.h
@@ -52,6 +52,8 @@ void        csm_util_init_error                     (gboolean    fatal,
 
 char *      csm_util_generate_startup_id            (void);
 
+gboolean    csm_util_export_activation_environment  (GError     **error);
+
 void        csm_util_setenv                         (const char *variable,
                                                      const char *value);
 
diff --git a/cinnamon-session/main.c b/cinnamon-session/main.c
index f909819..221235b 100644
--- a/cinnamon-session/main.c
+++ b/cinnamon-session/main.c
@@ -341,6 +341,8 @@ main (int argc, char **argv)
                 exit (1);
         }
 
+        csm_util_export_activation_environment (NULL);
+
         mdm_log_init ();
         mdm_log_set_debug (debug);
 

From 1f76506af33cb72348ee980b651e3dd8746174bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sat, 6 May 2017 23:20:28 +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
---
 cinnamon-session/csm-util.c | 127 +++++++++++++++++++++++++++++++++++++++++---
 cinnamon-session/csm-util.h |   2 +
 cinnamon-session/main.c     |   1 +
 3 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/cinnamon-session/csm-util.c b/cinnamon-session/csm-util.c
index 94d16fd..fa4e2bd 100644
--- a/cinnamon-session/csm-util.c
+++ b/cinnamon-session/csm-util.c
@@ -621,22 +621,137 @@ csm_util_export_activation_environment (GError     **error)
         return environment_updated;
 }
 
+gboolean
+csm_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
+csm_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;
+}
+
 void
 csm_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 (!csm_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 (!csm_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);
+        }
+
+        /* If this fails, the system user session won't get the updated environment
+         */
+        if (!csm_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);
         }
 }
 
diff --git a/cinnamon-session/csm-util.h b/cinnamon-session/csm-util.h
index b2392b9..cfd5ddd 100644
--- a/cinnamon-session/csm-util.h
+++ b/cinnamon-session/csm-util.h
@@ -54,6 +54,8 @@ char *      csm_util_generate_startup_id            (void);
 
 gboolean    csm_util_export_activation_environment  (GError     **error);
 
+gboolean    csm_util_export_user_environment        (GError     **error);
+
 void        csm_util_setenv                         (const char *variable,
                                                      const char *value);
 
diff --git a/cinnamon-session/main.c b/cinnamon-session/main.c
index 221235b..79578a6 100644
--- a/cinnamon-session/main.c
+++ b/cinnamon-session/main.c
@@ -342,6 +342,7 @@ main (int argc, char **argv)
         }
 
         csm_util_export_activation_environment (NULL);
+        csm_util_export_user_environment (NULL);
 
         mdm_log_init ();
         mdm_log_set_debug (debug);