Index: gnome-session/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	Bug #101351:
	* remote.c (normal_exec): New function.
	(remote_start): Use it.  Changed API.  Use g_spawn_async.
	* manager.c (run_command_prop): Updated.
	(close_child): New function.
	* remote.h (remote_start): Updated.

Index: gnome-session/remote.c
===================================================================
RCS file: /cvs/gnome/gnome-session/gnome-session/remote.c,v
retrieving revision 1.6
diff -u -r1.6 remote.c
--- gnome-session/remote.c 8 Jul 2002 04:25:34 -0000 1.6
+++ gnome-session/remote.c 30 Sep 2006 03:50:31 -0000
@@ -34,172 +34,150 @@
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <stdlib.h>
 
 #include <X11/ICE/ICElib.h>
 #include <X11/ICE/ICEutil.h>
 
-#include <libgnome/libgnome.h>
-
 #include "remote.h"
 
 static char *format_rstart_env (char *);
+static gboolean normal_exec (char *cwd, char **argv, char **envp,
+			     GPid *child_pid, GError **error);
+
+static gboolean
+normal_exec (char *cwd, char **argv, char **envp,
+	     GPid *child_pid, GError **error)
+{
+  return g_spawn_async (cwd, argv, envp,
+			G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+			NULL, NULL, child_pid, error);
+}
 
-gint
-remote_start (char *restart_info, int argc, char **argv,
-	      char *cwd, int envpc, char **envp)
+gboolean
+remote_start (char *restart_info, char **argv,
+	      char *cwd, char **envp,
+	      GPid *child_pid, GError **error)
 {
     FILE *fp;
-    int	 pipefd[2];
+    gint pipefd;
     char *machine;
     int  i;
     GSList *list;
-    gint pid;
+    gchar *rargv[4];
 
     if (! restart_info)
     {
-    normal_exec:
-        return gnome_execute_async_with_env (cwd, argc, argv, envpc, envp);
+        return normal_exec (cwd, argv, envp, child_pid, error);
     }
 
     if (strncmp (restart_info, RSTART_RSH, sizeof (RSTART_RSH))
 	|| restart_info[sizeof (RSTART_RSH)] != '/')
-      goto normal_exec;
+    {
+        return normal_exec (cwd, argv, envp, child_pid, error);
+    }
 
     machine = restart_info + sizeof (RSTART_RSH) + 1;
     if (! *machine)
-      goto normal_exec;
-
+    {
+        return normal_exec (cwd, argv, envp, child_pid, error);
+    }
 
     g_message ("Attempting to restart remote client on %s\n",
 	       machine);
 
-    if (pipe (pipefd) < 0)
-    {
-      g_error ("gnome-session: pipe() error during remote start of %s",
-	       argv[0]);
-      pid = -1;
-    }
-    else
-    {
-      pid = fork();
-	switch(pid)
-	{
-	case -1:
-
-	    g_error ("gnome-session: fork() error during remote start of %s",
-		     argv[0]);
-	    break;
-
-	case 0:		/* kid */
-
-	    close (pipefd[1]);
-	    close (0);
-	    dup (pipefd[0]);
-	    close (pipefd[0]);
-
-            if (access (RSH_COMMAND, X_OK) == 0)
-              execlp (RSH_COMMAND, machine, "rstartd", (char *) 0);
+    rargv[0] = RSH_COMMAND;
+    rargv[1] = machine;
+    rargv[2] = "rstartd";
+    rargv[3] = NULL;
+
+    if (! g_spawn_async_with_pipes (NULL, rargv, NULL,
+				    G_SPAWN_DO_NOT_REAP_CHILD,
+				    NULL, NULL, child_pid,
+				    &pipefd, NULL, NULL, error))
+      return 0;
+
+    fp = (FILE *) fdopen (pipefd, "w");
+
+    fprintf (fp, "CONTEXT X\n");
+    fprintf (fp, "DIR %s\n", cwd);
+    fprintf (fp, "DETACH\n");
+
+    if (envp)
+      {
+	/*
+	 * The application saved its environment.
+	 */
 
-	    g_error ("gnome-session: execlp() of rstartd failed for remote start of %s",
-		     argv[0]);
+	for (i = 0; envp[i]; i++)
+	  {
 	    /*
-	     * TODO : We would like to send this log information to the
-	     * log window in the parent.  This would require using the
-	     * pipe between the parent and child.  The child would
-	     * set close-on-exec.  If the exec succeeds, the pipe will
-	     * be closed.  If it fails, the child can write a message
-	     * to the parent.
+	     * rstart requires that any spaces, backslashes, or
+	     * non-printable characters inside of a string be
+	     * represented by octal escape sequences.
 	     */
-	    _exit(127);
-
-	default:		/* parent */
 
-	    close (pipefd[0]);
-	    fp = (FILE *) fdopen (pipefd[1], "w");
-
-	    fprintf (fp, "CONTEXT X\n");
-	    fprintf (fp, "DIR %s\n", cwd);
-	    fprintf (fp, "DETACH\n");
-
-	    if (envp)
-	    {
-		/*
-		 * The application saved its environment.
-		 */
-
-		for (i = 0; envp[i]; i++)
-		{
-		    /*
-		     * rstart requires that any spaces, backslashes, or
-		     * non-printable characters inside of a string be
-		     * represented by octal escape sequences.
-		     */
-
-		    char *temp = format_rstart_env (envp[i]);
-		    fprintf (fp, "MISC X %s\n", temp);
-		    if (temp != envp[i])
-			g_free (temp);
-		}
-	    }
-	    else
-	    {
-		/*
-		 * The application did not save its environment.
-		 * The default PATH set up by rstart may not contain
-		 * the program we want to restart.  We play it safe
-		 * and pass xsm's PATH.  This will most likely contain
-		 * the path we need.
-		 */
-
-		char *path = (char *) getenv ("PATH");
-
-		if (path)
-		    fprintf (fp, "MISC X PATH=%s\n", path);
-	    }
+	    char *temp = format_rstart_env (envp[i]);
+	    fprintf (fp, "MISC X %s\n", temp);
+	    if (temp != envp[i])
+	      g_free (temp);
+	  }
+      }
+    else
+      {
+	/*
+	 * The application did not save its environment.
+	 * The default PATH set up by rstart may not contain
+	 * the program we want to restart.  We play it safe
+	 * and pass xsm's PATH.  This will most likely contain
+	 * the path we need.
+	 */
+
+	char *path = (char *) getenv ("PATH");
+
+	if (path)
+	  fprintf (fp, "MISC X PATH=%s\n", path);
+      }
 
 #if 0
-	    /* FIXME: implement */
-	    fprintf (fp, "MISC X %s\n", non_local_display_env);
-	    fprintf (fp, "MISC X %s\n", non_local_session_env);
+    /* FIXME: implement */
+    fprintf (fp, "MISC X %s\n", non_local_display_env);
+    fprintf (fp, "MISC X %s\n", non_local_session_env);
 #endif
 
-	    /*
-	     * Pass the authentication data.
-	     * Each transport has auth data for ICE and XSMP.
-	     * Don't pass local auth data.
-	     */
-
-	    for (list = auth_entries; list != NULL; list = list->next)
-	    {
-	        IceAuthFileEntry *entry = (IceAuthFileEntry *) list->data;
-		if (strstr (entry->network_id, "local/"))
-		    continue;
-
-		fprintf (fp, "AUTH ICE %s \"\" %s %s ",
-		    entry->protocol_name,
-		    entry->network_id,
-		    entry->auth_name);
+    /*
+     * Pass the authentication data.
+     * Each transport has auth data for ICE and XSMP.
+     * Don't pass local auth data.
+     */
+    for (list = auth_entries; list != NULL; list = list->next)
+      {
+	IceAuthFileEntry *entry = (IceAuthFileEntry *) list->data;
+	if (strstr (entry->network_id, "local/"))
+	  continue;
+
+	fprintf (fp, "AUTH ICE %s \"\" %s %s ",
+		 entry->protocol_name,
+		 entry->network_id,
+		 entry->auth_name);
 		
-		for (i = 0; i < entry->auth_data_length; ++i)
-		  fprintf (fp, "%02x", entry->auth_data[i]);
-
-		fprintf (fp, "\n");
-	    }
+	for (i = 0; i < entry->auth_data_length; ++i)
+	  fprintf (fp, "%02x", entry->auth_data[i]);
 
-	    /*
-	     * And execute the program
-	     */
+	fprintf (fp, "\n");
+      }
 
-	    fprintf (fp, "EXEC %s %s", argv[0], argv[0]);
-	    for (i = 1; argv[i]; i++)
-		fprintf (fp, " %s", argv[i]);
-	    fprintf (fp, "\n\n");
-	    fclose (fp);
-	    break;
-	}
-    }
+    /*
+     * And execute the program
+     */
+    
+    fprintf (fp, "EXEC %s %s", argv[0], argv[0]);
+    for (i = 1; argv[i]; i++)
+      fprintf (fp, " %s", argv[i]);
+    fprintf (fp, "\n\n");
+    fclose (fp);
 
-    return pid;
+    return 1;
 }
 
 
@@ -212,7 +190,7 @@
 format_rstart_env (char *str)
 {
     int escape_count = 0, i;
-    unsigned char *temp = str;
+    unsigned char *temp = (unsigned char *) str;
 
     while (*temp != '\0')
     {
@@ -229,7 +207,7 @@
 	char *ret = (char *) g_malloc (len);
 	char *ptr = ret;
 
-	temp = str;
+	temp = (unsigned char *) str;
 	while (*temp != '\0')
 	{
 	    if (!isgraph (*temp) || *temp == '\\')
Index: gnome-session/remote.h
===================================================================
RCS file: /cvs/gnome/gnome-session/gnome-session/remote.h,v
retrieving revision 1.2
diff -u -r1.2 remote.h
--- gnome-session/remote.h 8 Jul 2002 04:25:34 -0000 1.2
+++ gnome-session/remote.h 30 Sep 2006 03:50:31 -0000
@@ -35,7 +35,7 @@
 #define RSTART_RSH "rstart-rsh"
 
 /* Try to start a program remotely, if appropriate, else locally.  */
-gint remote_start (char *restart_info, int argc, char **argv,
-                   char *cwd, int envpc, char **envp);
+gboolean remote_start (char *restart_info, char **argv, char *cwd, char **envp,
+		       GPid *child_pid, GError **error);
 
 #endif /* REMOTE_H */
Index: gnome-session/manager.c
===================================================================
RCS file: /cvs/gnome/gnome-session/gnome-session/manager.c,v
retrieving revision 1.84
diff -u -r1.84 manager.c
--- gnome-session/manager.c 8 Aug 2006 14:00:52 -0000 1.84
+++ gnome-session/manager.c 30 Sep 2006 03:50:34 -0000
@@ -386,14 +364,24 @@
   g_free (client);
 }
 
+static void
+close_child (GPid pid, gint status, gpointer ignore)
+{
+  g_spawn_close_pid (pid);
+}
+
 /* Run a command on a client. */
 static int
 run_command_prop (Client     *client, 
 		  const char *command, 
 		  SmProp     *prop)
 {
-  int argc, envc, envpc, pid = -1;
+  int argc, envc, envpc;
+  gboolean ok;
   char **argv, *dir, **envv, **envp, *restart_info;
+  GPid child_pid;
+  GError *error;
+  int pid = -1;
 
   gsm_verbose ("run_command_prop(): client %p, connection %p, command %s\n", client, client->connection, command);
   gsm_verbose_indent (TRUE);
@@ -434,31 +422,40 @@
 
       restart_info = NULL;
       find_string_property (client, GsmRestartService, &restart_info);
-      pid = remote_start (restart_info, argc, argv, dir, envpc, envp);
+      ok = remote_start (restart_info, argv, dir, envp, &child_pid, &error);
       if (restart_info)
 	g_free (restart_info);
 
-      if (pid < 0)
+      if (ok)
 	{
+	  g_child_watch_add (child_pid, close_child, NULL);
+	  pid = (int) child_pid;
+	}
+      else
+	{
+	  /* FIXME: this looks weird.  We only log an error when
+	     there is a connection or when not running the restart
+	     command?? */
 	  if (strcmp (command, SmRestartCommand) || client->connection)
 	    {
 	      gchar *message;
-	      message = g_strconcat (argv[0], " : Failed to execute : ", g_strerror(errno), NULL);
+	      message = g_strconcat (argv[0], " : Failed to execute : ",
+				     error->message, NULL);
 	      client_reasons (client, FALSE, 1, &message); 
 	      g_free (message);
 	    }
+	  g_error_free (error);
 	  pid = -1;
-	  errno = 0;
 	}
 
       if (envp != NULL)
-	      g_strfreev (envp);
+	g_strfreev (envp);
       if (dir != NULL)
-	      g_free (dir);
+	g_free (dir);
       g_strfreev (argv);
     }
   gsm_verbose_indent (FALSE);
-  
+
   return pid;
 }
 
