Check return value of XGetWindowProperty in x11_get_address
[platform/upstream/dbus.git] / dbus / dbus-spawn-win.c
index 7d93300..8ac837e 100644 (file)
@@ -1,17 +1,16 @@
-#include "config.h"
+#include <config.h>
 
-#if !defined(DBUS_ENABLE_VERBOSE_MODE) || defined(_MSC_VER)
+//#define SPAWN_DEBUG
+
+#if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
 #define PING()
 #else
 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
 #endif
 
 #include <stdio.h>
-#ifdef DBUS_WINCE
-#include <process.h>
-#endif
 
-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 /* dbus-spawn-win32.c Wrapper around g_spawn
  * 
  * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
@@ -32,7 +31,7 @@
  * 
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
 #include "dbus-spawn.h"
@@ -51,7 +50,9 @@
 
 #include <stdlib.h>
 
+#ifndef DBUS_WINCE
 #include <process.h>
+#endif
 
 /**
  * Babysitter implementation details
@@ -226,7 +227,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
         {
           PING();
           CloseHandle (sitter->start_sync_event);
-          sitter->end_sync_event = NULL;
+          sitter->start_sync_event = NULL;
         }
 
 #ifdef DBUS_BUILD_TESTS
@@ -267,6 +268,33 @@ _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
 }
 
 /**
+ * Gets the exit status of the child. We do this so implementation specific
+ * detail is not cluttering up dbus, for example the system launcher code.
+ * This can only be called if the child has exited, i.e. call
+ * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
+ * did not return a status code, e.g. because the child was signaled
+ * or we failed to ever launch the child in the first place.
+ *
+ * @param sitter the babysitter
+ * @param status the returned status code
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
+                                        int            *status)
+{
+  if (!_dbus_babysitter_get_child_exited (sitter))
+    _dbus_assert_not_reached ("Child has not exited");
+
+  if (!sitter->have_child_status ||
+      sitter->child_status == STILL_ACTIVE)
+    return FALSE;
+
+  *status = sitter->child_status;
+  return TRUE;
+}
+
+/**
  * Sets the #DBusError with an explanation of why the spawned
  * child process exited (on a signal, or whatever). If
  * the child process has not exited, does nothing (error
@@ -286,9 +314,11 @@ _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
   PING();
   if (sitter->have_spawn_errno)
     {
+      char *emsg = _dbus_win_error_string (sitter->spawn_errno);
       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
                       "Failed to execute program %s: %s",
-                      sitter->executable, _dbus_strerror (sitter->spawn_errno));
+                      sitter->executable, emsg);
+      _dbus_win_free_error_string (emsg);
     }
   else if (sitter->have_child_status)
     {
@@ -438,11 +468,97 @@ protect_argv (char  **argv,
   return argc;
 }
 
-static unsigned __stdcall
+
+/* From GPGME, relicensed by g10 Code GmbH.  */
+static char *
+compose_string (char **strings, char separator)
+{
+  int i;
+  int n = 0;
+  char *buf;
+  char *p;
+  const char *ptr;
+  
+  if (!strings || !strings[0])
+    return 0;
+  for (i = 0; strings[i]; i++)
+    n += strlen (strings[i]) + 1;
+  n++;
+
+  buf = p = malloc (n);
+  if (!buf)
+    return NULL;
+  for (i = 0; strings[i]; i++)
+    {
+      strcpy (p, strings[i]);
+      p += strlen (strings[i]);
+      *(p++) = separator;
+    }
+  p--;
+  *(p++) = '\0';
+  *p = '\0';
+
+  return buf;
+}
+
+static char *
+build_commandline (char **argv)
+{
+  return compose_string (argv, ' ');
+}
+
+static char *
+build_env_string (char** envp)
+{
+  return compose_string (envp, '\0');
+}
+
+static HANDLE
+spawn_program (char* name, char** argv, char** envp)
+{
+  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
+  STARTUPINFOA si;
+  char *arg_string, *env_string;
+  BOOL result;
+
+#ifdef DBUS_WINCE
+  if (argv && argv[0])
+    arg_string = build_commandline (argv + 1);
+  else
+    arg_string = NULL;
+#else
+  arg_string = build_commandline (argv);
+#endif
+  if (!arg_string)
+    return INVALID_HANDLE_VALUE;
+
+  env_string = build_env_string(envp);
+
+  memset (&si, 0, sizeof (si));
+  si.cb = sizeof (si);
+#ifdef DBUS_WINCE
+  result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
+#else
+  result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
+#endif
+                          (LPVOID)env_string, NULL, &si, &pi);
+  free (arg_string);
+  if (env_string)
+    free (env_string);
+
+  if (!result)
+    return INVALID_HANDLE_VALUE;
+
+  CloseHandle (pi.hThread);
+  return pi.hProcess;
+}
+
+
+static DWORD __stdcall
 babysitter (void *parameter)
 {
   DBusBabysitter *sitter = (DBusBabysitter *) parameter;
-  DBusSocket *sock;
+  int fd;
   PING();
   _dbus_babysitter_ref (sitter);
 
@@ -453,25 +569,19 @@ babysitter (void *parameter)
     }
 
   _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
-  fprintf (stderr, "babysitter: spawning %s\n", sitter->executable);
 
   PING();
-  if (sitter->envp != NULL)
-    sitter->child_handle = (HANDLE) spawnve (P_NOWAIT, sitter->executable,
-                           (const char * const *) sitter->argv,
-                           (const char * const *) sitter->envp);
-  else
-    sitter->child_handle = (HANDLE) spawnv (P_NOWAIT, sitter->executable,
-                                            (const char * const *) sitter->argv);
+  sitter->child_handle = spawn_program (sitter->executable,
+                                       sitter->argv, sitter->envp);
 
   PING();
   if (sitter->child_handle == (HANDLE) -1)
     {
       sitter->child_handle = NULL;
       sitter->have_spawn_errno = TRUE;
-      sitter->spawn_errno = errno;
+      sitter->spawn_errno = GetLastError();
     }
-
+  
   PING();
   SetEvent (sitter->start_sync_event);
 
@@ -498,8 +608,7 @@ babysitter (void *parameter)
 #endif
 
   PING();
-  _dbus_handle_to_socket (sitter->socket_to_main, &sock);
-  send (sock->fd, " ", 1, 0);
+  send (sitter->socket_to_main, " ", 1, 0);
 
   _dbus_babysitter_unref (sitter);
 
@@ -516,8 +625,8 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
 {
   DBusBabysitter *sitter;
   HANDLE sitter_thread;
-  int sitter_thread_id;
-
+  DWORD sitter_thread_id;
+  
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
   *sitter_p = NULL;
@@ -572,7 +681,7 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
   sitter->envp = envp;
 
   PING();
-  sitter_thread = (HANDLE) _beginthreadex (NULL, 0, babysitter,
+  sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
                   sitter, 0, &sitter_thread_id);
 
   if (sitter_thread == 0)