-#include "config.h"
+#include <config.h>
//#define SPAWN_DEBUG
-#ifndef SPAWN_DEBUG || defined(_MSC_VER)
+#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.
*
* 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"
#include <stdlib.h>
+#ifndef DBUS_WINCE
#include <process.h>
+#endif
/**
* Babysitter implementation details
{
PING();
CloseHandle (sitter->start_sync_event);
- sitter->end_sync_event = NULL;
+ sitter->start_sync_event = NULL;
}
#ifdef DBUS_BUILD_TESTS
}
/**
+ * 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
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)
{
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);
_dbus_verbose ("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);
#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);
{
DBusBabysitter *sitter;
HANDLE sitter_thread;
- int sitter_thread_id;
-
+ DWORD sitter_thread_id;
+
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
*sitter_p = NULL;
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)