diff --git a/mate-session/Makefile.am b/mate-session/Makefile.am index f37a0e2..2c73d63 100644 --- a/mate-session/Makefile.am +++ b/mate-session/Makefile.am @@ -42,6 +42,8 @@ mate_session_SOURCES = \ mdm-signal-handler.c \ mdm-log.h \ mdm-log.c \ + msm-gnome.c \ + msm-gnome.h \ main.c \ gsm-store.h \ gsm-store.c \ diff --git a/mate-session/main.c b/mate-session/main.c index 6cfbbe6..f6bee9a 100644 --- a/mate-session/main.c +++ b/mate-session/main.c @@ -51,6 +51,8 @@ #include "gsm-xsmp-server.h" #include "gsm-store.h" +#include "msm-gnome.h" + #define GSM_SCHEMA "org.mate.session" #define GSM_DEFAULT_SESSION_KEY "default-session" #define GSM_REQUIRED_COMPONENTS_SCHEMA GSM_SCHEMA ".required-components" @@ -542,6 +544,9 @@ int main(int argc, char** argv) */ acquire_name(); + /* Starts gnome compat mode */ + msm_compat_gnome_startup (); + manager = gsm_manager_new(client_store, failsafe); signal_handler = mdm_signal_handler_new(); @@ -583,6 +588,7 @@ int main(int argc, char** argv) g_object_unref(client_store); } + msm_compat_gnome_shutdown(); mdm_log_shutdown(); return 0; diff --git a/mate-session/msm-gnome.c b/mate-session/msm-gnome.c new file mode 100644 index 0000000..5c7d8dc --- /dev/null +++ b/mate-session/msm-gnome.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2004-2005 Benedikt Meurer + * 2013 Stefano Karapetsas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + * + * Most parts of this file where taken from xfce4-session and + * gnome-session. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "msm-gnome.h" + +#define GNOME_KEYRING_DAEMON "gnome-keyring-daemon" + + +static gboolean gnome_compat_started = FALSE; +static int keyring_lifetime_pipe[2]; +static pid_t gnome_keyring_daemon_pid = 0; +static Window gnome_smproxy_window = None; + +static void +child_setup (gpointer user_data) +{ + gint open_max; + gint fd; + char *fd_str; + + open_max = sysconf (_SC_OPEN_MAX); + for (fd = 3; fd < open_max; fd++) + { + if (fd != keyring_lifetime_pipe[0]) + fcntl (fd, F_SETFD, FD_CLOEXEC); + } + + fd_str = g_strdup_printf ("%d", keyring_lifetime_pipe[0]); + g_setenv ("GNOME_KEYRING_LIFETIME_FD", fd_str, TRUE); + g_free (fd_str); +} + + +static void +gnome_keyring_daemon_startup (void) +{ + GError *error = NULL; + gchar *sout; + gchar **lines; + gsize lineno; + gint status; + glong pid; + gchar *end; + gchar *argv[3]; + gchar *p; + gchar *name; + const gchar *value; + + /* Pipe to slave keyring lifetime to */ + if (pipe (keyring_lifetime_pipe)) + { + g_warning ("Failed to set up pipe for gnome-keyring: %s", strerror (errno)); + return; + } + + error = NULL; + argv[0] = GNOME_KEYRING_DAEMON; + argv[1] = "--start"; + argv[2] = NULL; + g_spawn_sync (NULL, argv, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN, + child_setup, NULL, + &sout, NULL, &status, &error); + + close (keyring_lifetime_pipe[0]); + /* We leave keyring_lifetime_pipe[1] open for the lifetime of the session, + in order to slave the keyring daemon lifecycle to the session. */ + + if (error != NULL) + { + g_printerr ("Failed to run gnome-keyring-daemon: %s\n", + error->message); + g_error_free (error); + } + else + { + if (WIFEXITED (status) && WEXITSTATUS (status) == 0 && sout != NULL) + { + lines = g_strsplit (sout, "\n", 0); + + for (lineno = 0; lines[lineno] != NULL; lineno++) + { + p = strchr (lines[lineno], '='); + if (p == NULL) + continue; + + name = g_strndup (lines[lineno], p - lines[lineno]); + value = p + 1; + + g_setenv (name, value, TRUE); + + if (g_strcmp0 (name, "GNOME_KEYRING_PID") == 0) + { + pid = strtol (value, &end, 10); + if (end != value) + gnome_keyring_daemon_pid = pid; + } + + g_free (name); + } + + g_strfreev (lines); + } + else + { + /* daemon failed for some reason */ + g_printerr ("gnome-keyring-daemon failed to start correctly, " + "exit code: %d\n", WEXITSTATUS (status)); + } + + g_free (sout); + } +} + +static void +gnome_keyring_daemon_shutdown (void) +{ + if (gnome_keyring_daemon_pid != 0) + { + kill (gnome_keyring_daemon_pid, SIGTERM); + gnome_keyring_daemon_pid = 0; + } +} + + + +static void +msm_compat_gnome_smproxy_startup (void) +{ + Atom gnome_sm_proxy; + Display *dpy; + Window root; + + gdk_error_trap_push (); + + /* Set GNOME_SM_PROXY property, since some apps (like OOo) seem to require + * it to behave properly. Thanks to Jasper/Francois for reporting this. + * This has another advantage, since it prevents people from running + * gnome-smproxy in xfce4, which would cause trouble otherwise. + */ + dpy = gdk_display; + root = RootWindow (dpy, 0); + + if (gnome_smproxy_window != None) + XDestroyWindow (dpy, gnome_smproxy_window); + + gnome_sm_proxy = XInternAtom (dpy, "GNOME_SM_PROXY", False); + gnome_smproxy_window = XCreateSimpleWindow (dpy, root, 1, 1, 1, 1, 0, 0, 0); + + XChangeProperty (dpy, gnome_smproxy_window, gnome_sm_proxy, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) (void *) &gnome_smproxy_window, 1); + XChangeProperty (dpy, root, gnome_sm_proxy, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) (void *) &gnome_smproxy_window, 1); + + XSync (dpy, False); + + gdk_error_trap_pop (); +} + + +static void +msm_compat_gnome_smproxy_shutdown (void) +{ + gdk_error_trap_push (); + + if (gnome_smproxy_window != None) + { + XDestroyWindow (gdk_display, gnome_smproxy_window); + XSync (gdk_display, False); + gnome_smproxy_window = None; + } + + gdk_error_trap_pop (); +} + + +void +msm_compat_gnome_startup (void) +{ + if (G_UNLIKELY (gnome_compat_started)) + return; + + msm_compat_gnome_smproxy_startup (); + + gnome_keyring_daemon_startup (); + + gnome_compat_started = TRUE; +} + + +void +msm_compat_gnome_shutdown (void) +{ + if (G_UNLIKELY (!gnome_compat_started)) + return; + + /* shutdown the keyring daemon */ + gnome_keyring_daemon_shutdown (); + + msm_compat_gnome_smproxy_shutdown (); + + gnome_compat_started = FALSE; +} + diff --git a/mate-session/msm-gnome.h b/mate-session/msm-gnome.h new file mode 100644 index 0000000..2f15909 --- /dev/null +++ b/mate-session/msm-gnome.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2004 Benedikt Meurer + * 2013 Stefano Karapetsas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + * + * Most parts of this file where taken from xfce4-session and + * gnome-session. + */ + +#ifndef __MSM_GNOME_H__ +#define __MSM_GNOME_H__ + +void msm_compat_gnome_startup (void); +void msm_compat_gnome_shutdown (void); + +#endif /* !__MSM_GNOME_H__ */