[daemon-fix] Fixed sending daemon match rules for kdbus broadcasts
[platform/upstream/dbus.git] / dbus / dbus-spawn-win.c
index 1365b2c..cd8ca66 100644 (file)
@@ -9,9 +9,6 @@
 #endif
 
 #include <stdio.h>
-#ifdef DBUS_WINCE
-#include <process.h>
-#endif
 
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 /* dbus-spawn-win32.c Wrapper around g_spawn
@@ -45,6 +42,7 @@
 #include "dbus-protocol.h"
 
 #define WIN32_LEAN_AND_MEAN
+#include <windows.h>
 //#define STRICT
 //#include <windows.h>
 //#undef STRICT
@@ -53,7 +51,9 @@
 
 #include <stdlib.h>
 
+#ifndef DBUS_WINCE
 #include <process.h>
+#endif
 
 /**
  * Babysitter implementation details
@@ -63,7 +63,7 @@ struct DBusBabysitter
     int refcount;
 
     HANDLE start_sync_event;
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
 
     HANDLE end_sync_event;
 #endif
@@ -82,6 +82,8 @@ struct DBusBabysitter
 
     DBusWatchList *watches;
     DBusWatch *sitter_watch;
+    DBusBabysitterFinishedFunc finished_cb;
+    void *finished_data;
 
     dbus_bool_t have_spawn_errno;
     int spawn_errno;
@@ -107,7 +109,7 @@ _dbus_babysitter_new (void)
       return NULL;
     }
 
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
   sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
   if (sitter->end_sync_event == NULL)
     {
@@ -155,6 +157,27 @@ _dbus_babysitter_ref (DBusBabysitter *sitter)
   return sitter;
 }
 
+static void
+close_socket_to_babysitter (DBusBabysitter *sitter)
+{
+  _dbus_verbose ("Closing babysitter\n");
+
+  if (sitter->sitter_watch != NULL)
+    {
+      _dbus_assert (sitter->watches != NULL);
+      _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
+      _dbus_watch_invalidate (sitter->sitter_watch);
+      _dbus_watch_unref (sitter->sitter_watch);
+      sitter->sitter_watch = NULL;
+    }
+
+  if (sitter->socket_to_babysitter != -1)
+    {
+      _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+      sitter->socket_to_babysitter = -1;
+    }
+}
+
 /**
  * Decrement the reference count on the babysitter object.
  *
@@ -173,11 +196,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
 
   if (sitter->refcount == 0)
     {
-      if (sitter->socket_to_babysitter != -1)
-        {
-          _dbus_close_socket (sitter->socket_to_babysitter, NULL);
-          sitter->socket_to_babysitter = -1;
-        }
+      close_socket_to_babysitter (sitter);
 
       if (sitter->socket_to_main != -1)
         {
@@ -231,7 +250,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
           sitter->start_sync_event = NULL;
         }
 
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
       if (sitter->end_sync_event != NULL)
         {
           CloseHandle (sitter->end_sync_event);
@@ -373,9 +392,15 @@ handle_watch (DBusWatch       *watch,
    */
 
   PING();
-  _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+  close_socket_to_babysitter (sitter);
   PING();
-  sitter->socket_to_babysitter = -1;
+
+  if (_dbus_babysitter_get_child_exited (sitter) &&
+      sitter->finished_cb != NULL)
+    {
+      sitter->finished_cb (sitter, sitter->finished_data);
+      sitter->finished_cb = NULL;
+    }
 
   return TRUE;
 }
@@ -472,52 +497,80 @@ protect_argv (char  **argv,
 
 /* From GPGME, relicensed by g10 Code GmbH.  */
 static char *
-build_commandline (char **argv)
+compose_string (char **strings, char separator)
 {
   int i;
   int n = 0;
   char *buf;
   char *p;
-  const char *ptr;
-  
-  for (i = 0; argv[i]; i++)
-    n += strlen (argv[i]) + 1;
+
+  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; argv[i]; i++)
+  for (i = 0; strings[i]; i++)
     {
-      strcpy (p, argv[i]);
-      p += strlen (argv[i]);
-      *(p++) = ' ';
+      strcpy (p, strings[i]);
+      p += strlen (strings[i]);
+      *(p++) = separator;
     }
-  if (i)
-    p--;
+  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 (const char* name, char** argv, char** envp)
+spawn_program (char* name, char** argv, char** envp)
 {
   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
   STARTUPINFOA si;
-  char *arg_string;
+  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,
-                          envp, NULL, &si, &pi);
+#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;
 
@@ -530,7 +583,7 @@ static DWORD __stdcall
 babysitter (void *parameter)
 {
   DBusBabysitter *sitter = (DBusBabysitter *) parameter;
-  int fd;
+
   PING();
   _dbus_babysitter_ref (sitter);
 
@@ -575,7 +628,7 @@ babysitter (void *parameter)
       sitter->child_handle = NULL;
     }
 
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
   SetEvent (sitter->end_sync_event);
 #endif
 
@@ -640,6 +693,12 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
   PING();
   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
     {
+      /* we need to free it early so the destructor won't try to remove it
+       * without it having been added, which DBusLoop doesn't allow */
+      _dbus_watch_invalidate (sitter->sitter_watch);
+      _dbus_watch_unref (sitter->sitter_watch);
+      sitter->sitter_watch = NULL;
+
       _DBUS_SET_OOM (error);
       goto out0;
     }
@@ -685,7 +744,40 @@ out0:
   return FALSE;
 }
 
-#ifdef DBUS_BUILD_TESTS
+void
+_dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
+                                       DBusBabysitterFinishedFunc  finished,
+                                       void                       *user_data)
+{
+  sitter->finished_cb = finished;
+  sitter->finished_data = user_data;
+}
+
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+
+static char *
+get_test_exec (const char *exe,
+               DBusString *scratch_space)
+{
+  const char *dbus_test_exec;
+
+  dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
+
+  if (dbus_test_exec == NULL)
+    dbus_test_exec = DBUS_TEST_EXEC;
+
+  if (!_dbus_string_init (scratch_space))
+    return NULL;
+
+  if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
+                                   dbus_test_exec, exe, DBUS_EXEEXT))
+    {
+      _dbus_string_free (scratch_space);
+      return NULL;
+    }
+
+  return _dbus_string_get_data (scratch_space);
+}
 
 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
 
@@ -749,6 +841,7 @@ check_spawn_segfault (void *data)
   char *argv[4] = { NULL, NULL, NULL, NULL };
   DBusBabysitter *sitter;
   DBusError error;
+  DBusString argv0;
 
   sitter = NULL;
 
@@ -756,7 +849,14 @@ check_spawn_segfault (void *data)
 
   /*** Test launching segfault binary */
 
-  argv[0] = TEST_SEGFAULT_BINARY;
+  argv[0] = get_test_exec ("test-segfault", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
   if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
                                          NULL, NULL,
                                          &error))
@@ -765,6 +865,8 @@ check_spawn_segfault (void *data)
       _dbus_babysitter_set_child_exit_error (sitter, &error);
     }
 
+  _dbus_string_free (&argv0);
+
   if (sitter)
     _dbus_babysitter_unref (sitter);
 
@@ -794,6 +896,7 @@ check_spawn_exit (void *data)
   char *argv[4] = { NULL, NULL, NULL, NULL };
   DBusBabysitter *sitter;
   DBusError error;
+  DBusString argv0;
 
   sitter = NULL;
 
@@ -801,7 +904,14 @@ check_spawn_exit (void *data)
 
   /*** Test launching exit failure binary */
 
-  argv[0] = TEST_EXIT_BINARY;
+  argv[0] = get_test_exec ("test-exit", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
   if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
                                          NULL, NULL,
                                          &error))
@@ -810,6 +920,8 @@ check_spawn_exit (void *data)
       _dbus_babysitter_set_child_exit_error (sitter, &error);
     }
 
+  _dbus_string_free (&argv0);
+
   if (sitter)
     _dbus_babysitter_unref (sitter);
 
@@ -839,6 +951,7 @@ check_spawn_and_kill (void *data)
   char *argv[4] = { NULL, NULL, NULL, NULL };
   DBusBabysitter *sitter;
   DBusError error;
+  DBusString argv0;
 
   sitter = NULL;
 
@@ -846,7 +959,14 @@ check_spawn_and_kill (void *data)
 
   /*** Test launching sleeping binary then killing it */
 
-  argv[0] = TEST_SLEEP_FOREVER_BINARY;
+  argv[0] = get_test_exec ("test-sleep-forever", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
   if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
                                          NULL, NULL,
                                          &error))
@@ -858,6 +978,8 @@ check_spawn_and_kill (void *data)
       _dbus_babysitter_set_child_exit_error (sitter, &error);
     }
 
+  _dbus_string_free (&argv0);
+
   if (sitter)
     _dbus_babysitter_unref (sitter);