Index: gnome-session/gnome-session/ChangeLog
===================================================================
--- gnome-session.orig/gnome-session/ChangeLog
+++ gnome-session/gnome-session/ChangeLog
@@ -1,3 +1,11 @@
+2006-10-01  Tom Tromey  <tromey@redhat.com>
+
+	Bug #60697:
+	* Makefile.am (bin_PROGRAMS): Added gnome-session-wrapper.
+	(gnome_session_wrapper_SOURCES): New variable.
+	(gnome_session_wrapper_LDADD): Likewise.
+	* wrap-client.c: New file.
+
 2006-10-03  Tom Tromey  <tromey@redhat.com>
 
 	* save.c (set_session_name): Avoid memory leak.
Index: gnome-session/gnome-session/Makefile.am
===================================================================
--- gnome-session.orig/gnome-session/Makefile.am
+++ gnome-session/gnome-session/Makefile.am
@@ -30,6 +30,7 @@ gnome_session_LDADD = $(X_LIBS) $(GNOME_
 gnome_session_save_LDADD = $(GNOME_SESSION_LIBS)
 gnome_session_remove_LDADD = $(GNOME_SESSION_LIBS)
 gnome_session_properties_LDADD = $(GNOME_SESSION_LIBS)
+gnome_session_wrapper_LDADD = $(GNOME_SESSION_LIBS)
 splash_test_LDADD = $(X_LIBS) $(GNOME_SESSION_LIBS)
 logout_test_LDADD = $(X_LIBS) $(GNOME_SESSION_LIBS)
 
@@ -44,6 +45,7 @@ bin_PROGRAMS = \
 	gnome-session		\
 	gnome-session-save	\
 	gnome-session-remove    \
+	gnome-session-wrapper	\
 	gnome-session-properties
 endif
 
@@ -118,6 +120,9 @@ gnome_session_remove_SOURCES = \
 	gsm-protocol.c \
 	gsm-protocol.h
 
+gnome_session_wrapper_SOURCES = \
+	wrap-client.c
+
 gnome_session_properties_SOURCES = \
 	session-properties-capplet.c	\
 	session-properties-capplet.h	\
Index: gnome-session/gnome-session/wrap-client.c
===================================================================
--- /dev/null
+++ gnome-session/gnome-session/wrap-client.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ *    Tom Tromey <tromey@redhat.com>
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <libgnome/gnome-program.h>
+#include <libgnomeui/gnome-client.h>
+#include <glib.h>
+
+#include <gnome.h>
+
+#include <sys/types.h>
+#include <signal.h>
+#include <string.h>
+
+/* The restart style: "running", "immediately", "always".  Note that
+   we don't support "never", since in that case, why bother with this
+   wrapper?  */
+static gchar *restart_style;
+
+/* The pid of our child process, or -1 for no child.  */
+static GPid child_pid = (GPid) -1;
+
+/* Saved command line arguments.  */
+static gint saved_argc;
+static gchar **saved_argv;
+
+/* Command-line options remaining after parsing.  */
+static int remaining_argc;
+static gchar **remaining_argv;
+
+static GMainLoop *main_loop;
+
+
+static const GOptionEntry wrap_client_opts[] =
+{
+  {
+    "style", 0, 0, G_OPTION_ARG_STRING, &restart_style,
+    N_("Restart style: running (default), immediately, or always"), NULL
+  },
+
+  {
+    G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
+    &remaining_argv, NULL, NULL
+  },
+
+  {NULL}
+};
+
+static GnomeRestartStyle
+parse_restart ()
+{
+  if (restart_style == NULL || ! strcmp (restart_style, "running"))
+    return GNOME_RESTART_IF_RUNNING;
+  if (! strcmp (restart_style, "immediately"))
+    return GNOME_RESTART_IMMEDIATELY;
+  if (! strcmp (restart_style, "always"))
+    return GNOME_RESTART_ANYWAY;
+  fprintf (stderr, _("gnome-session-wrapper: unrecognized style '%s'\n"),
+	   restart_style);
+  fprintf (stderr,
+	   _("gnome-session-wrapper: must be one of 'running', 'immediately', 'always'\n"));
+  exit (1);
+}
+
+static gint
+save_session (GnomeClient *client, gint phase, GnomeSaveStyle save_style,
+	      gint shutdown, GnomeInteractStyle interact_style, gint fast,
+	      void *ignore)
+{
+  return TRUE;
+}
+
+static void
+die (GnomeClient *client, void *ignore)
+{
+  /* Assume the child reacts gracefully to this.  */
+  kill (child_pid, SIGHUP);
+  g_main_loop_quit (main_loop);
+}
+
+static void
+child_closed (GPid pid, gint status, gpointer ignore)
+{
+  g_spawn_close_pid (pid);
+  g_main_loop_quit (main_loop);
+}
+
+static gchar **
+compute_new_args (char *program, gint *new_argc)
+{
+  gchar **new_argv;
+  int i;
+
+  /* Magic number 3 is program + "--style" + "--".  */
+  *new_argc = remaining_argc + 3;
+  /* .. but allocate one more for the terminating NULL. */
+  new_argv = g_new0 (char *, *new_argc + 1);
+
+  new_argv[0] = program;
+  new_argv[1] = g_strconcat ("--style=",
+			     restart_style ? restart_style : "running",
+			     NULL);
+  new_argv[2] = "--";
+
+  for (i = 0; i < remaining_argc; ++i)
+    new_argv[i + 3] = remaining_argv[i];
+
+  return new_argv;
+}
+
+int
+main (int argc, char **argv)
+{
+  GnomeClient *client;
+  GnomeRestartStyle style;
+  GError *error = NULL;
+  GOptionContext *option_context;
+
+  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+
+  option_context = g_option_context_new ("");
+  g_option_context_add_main_entries (option_context, wrap_client_opts,
+				     GETTEXT_PACKAGE);
+
+  gnome_program_init ("gnome-session-wrapper",
+		      VERSION, LIBGNOMEUI_MODULE,
+                      argc, argv,
+		      GNOME_PARAM_GOPTION_CONTEXT, option_context,
+		      GNOME_PROGRAM_STANDARD_PROPERTIES,
+                      GNOME_PARAM_NONE);
+
+  /* Count arguments.  */
+  for (remaining_argc = 0; remaining_argv[remaining_argc]; ++remaining_argc)
+    ;
+
+  if (remaining_argc < 2)
+    {
+      fprintf (stderr, _("usage: gnome-session-wrapper [OPTIONS]... -- PROGRAM [ARGS]...\n"));
+      return 1;
+    }
+
+  client = gnome_master_client ();
+  if (! GNOME_CLIENT_CONNECTED (client))
+    {
+      fprintf (stderr, _("gnome-session-wrapper: could not connect to the session manager\n"));
+      return 1;
+    }
+
+  style = parse_restart ();
+  saved_argv = compute_new_args (argv[0], &saved_argc);
+
+  g_signal_connect (client, "save_yourself", G_CALLBACK (save_session), NULL);
+  g_signal_connect (client, "die", G_CALLBACK (die), NULL);
+
+  if (! g_spawn_async (NULL, remaining_argv, NULL,
+		       G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+		       NULL, NULL, &child_pid, &error))
+    {
+      /* FIXME: handle this better.  */
+      fprintf (stderr, _("gnome-session-wrapper: child failed: %s\n"),
+	       error->message);
+      return 1;
+    }
+  g_child_watch_add (child_pid, child_closed, NULL);
+
+  /* Set this after spawning child.  If the child fails we don't want
+     to be repeatedly restarted.  */
+  gnome_client_set_restart_style (client, style);
+
+  /* Might as well set it now.  */
+  gnome_client_set_restart_command (client, saved_argc, saved_argv);
+
+  main_loop = g_main_loop_new (NULL, TRUE);
+  g_main_loop_run (main_loop);
+
+  return 0;
+}
