1dbecdeabb20e0ce11121819c63373f0afba57c58Marcus Brinkmann#include <config.h>
270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
30c0df1910d8ab15b214f5129a72e10f54941524fRalf Habacker//#define SPAWN_DEBUG
40c0df1910d8ab15b214f5129a72e10f54941524fRalf Habacker
51f9f66bba806475dc38f225f9a394742ad3f8d69Ralf Habacker#if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define PING()
770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#else
870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
1070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
1170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <stdio.h>
1270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13d012387afef0ba02185ebe27bc6bb15551912e92Havoc Pennington/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/* dbus-spawn-win32.c Wrapper around g_spawn
1570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
1670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
1770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Copyright (C) 2003 CodeFactory AB
1870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Copyright (C) 2005 Novell, Inc.
1970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
2070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Licensed under the Academic Free License version 2.1
2170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
2270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * This program is free software; you can redistribute it and/or modify
2370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * it under the terms of the GNU General Public License as published by
2470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * the Free Software Foundation; either version 2 of the License, or
2570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * (at your option) any later version.
2670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
2770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * This program is distributed in the hope that it will be useful,
2870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * but WITHOUT ANY WARRANTY; without even the implied warranty of
2970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * GNU General Public License for more details.
3170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
3270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * You should have received a copy of the GNU General Public License
3370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * along with this program; if not, write to the Free Software
345baf2f856a9c6625993234855b07680da1c8916fTobias Mueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
3570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
3670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
3770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-spawn.h"
3870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-sysdeps.h"
3970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-sysdeps-win.h"
4070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-internals.h"
4170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-test.h"
4270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-protocol.h"
4370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
4470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define WIN32_LEAN_AND_MEAN
4570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker//#define STRICT
4670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker//#include <windows.h>
4770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker//#undef STRICT
4870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <winsock2.h>
4970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#undef interface
5070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
5170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <stdlib.h>
5270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
533404bb7238f2bb6dd5d678bc8f782810f3079241Marcus Brinkmann#ifndef DBUS_WINCE
5470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <process.h>
553404bb7238f2bb6dd5d678bc8f782810f3079241Marcus Brinkmann#endif
5670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
5770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
5870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Babysitter implementation details
5970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
6070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstruct DBusBabysitter
6170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  {
6270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int refcount;
6370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
6470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    HANDLE start_sync_event;
6570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
6670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
6770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    HANDLE end_sync_event;
6870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
6970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
7070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    char *executable;
7170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    DBusSpawnChildSetupFunc child_setup;
7270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    void *user_data;
7370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
7470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int argc;
7570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    char **argv;
7670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    char **envp;
7770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
7870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    HANDLE child_handle;
7970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int socket_to_babysitter;	/* Connection to the babysitter thread */
8070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int socket_to_main;
8170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
8270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    DBusWatchList *watches;
8370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    DBusWatch *sitter_watch;
8470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
8570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    dbus_bool_t have_spawn_errno;
8670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int spawn_errno;
8770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    dbus_bool_t have_child_status;
8870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int child_status;
8970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  };
9070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
9170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic DBusBabysitter*
9270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_new (void)
9370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
9470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
9570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
9670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = dbus_new0 (DBusBabysitter, 1);
9770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter == NULL)
9870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return NULL;
9970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
10070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->refcount = 1;
10170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
10270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
10370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->start_sync_event == NULL)
10470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
10570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_unref (sitter);
10670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return NULL;
10770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
10870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
10970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
11070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
11170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->end_sync_event == NULL)
11270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
11370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_unref (sitter);
11470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return NULL;
11570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
11670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
11770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
11870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->child_handle = NULL;
11970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
12070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->socket_to_babysitter = sitter->socket_to_main = -1;
12170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
12270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->argc = 0;
12370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->argv = NULL;
12470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->envp = NULL;
12570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
12670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->watches = _dbus_watch_list_new ();
12770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->watches == NULL)
12870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
12970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_unref (sitter);
13070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return NULL;
13170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
13270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->have_spawn_errno = FALSE;
13470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->have_child_status = FALSE;
13570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return sitter;
13770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
13870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
14070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Increment the reference count on the babysitter object.
14170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
14270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
14370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @returns the babysitter
14470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
14570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf HabackerDBusBabysitter *
14670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_ref (DBusBabysitter *sitter)
14770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
14870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
14970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter != NULL);
15070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter->refcount > 0);
15170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
15270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->refcount += 1;
15370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
15470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return sitter;
15570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
15670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
15770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
15870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Decrement the reference count on the babysitter object.
15970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
16070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
16170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
16270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackervoid
16370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_unref (DBusBabysitter *sitter)
16470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
16570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int i;
16670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
16770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
16870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter != NULL);
16970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter->refcount > 0);
17070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
17170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->refcount -= 1;
17270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
17370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->refcount == 0)
17470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
17570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->socket_to_babysitter != -1)
17670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
17770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_close_socket (sitter->socket_to_babysitter, NULL);
17870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->socket_to_babysitter = -1;
17970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
18070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
18170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->socket_to_main != -1)
18270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
18370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_close_socket (sitter->socket_to_main, NULL);
18470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->socket_to_main = -1;
18570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
18670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
18770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
18870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->argv != NULL)
18970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
19070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          for (i = 0; i < sitter->argc; i++)
19170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            if (sitter->argv[i] != NULL)
19270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              {
19370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                dbus_free (sitter->argv[i]);
19470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                sitter->argv[i] = NULL;
19570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              }
19670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          dbus_free (sitter->argv);
19770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->argv = NULL;
19870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
19970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
20070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->envp != NULL)
20170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
20270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          char **e = sitter->envp;
20370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
20470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          while (*e)
20570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            dbus_free (*e++);
20670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          dbus_free (sitter->envp);
20770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->envp = NULL;
20870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
20970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
21070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->child_handle != NULL)
21170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
21270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          CloseHandle (sitter->child_handle);
21370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->child_handle = NULL;
21470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
21570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
21670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->sitter_watch)
21770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
21870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_watch_invalidate (sitter->sitter_watch);
21970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_watch_unref (sitter->sitter_watch);
22070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->sitter_watch = NULL;
22170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
22270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
22370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->watches)
22470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        _dbus_watch_list_free (sitter->watches);
22570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
22670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->start_sync_event != NULL)
22770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
22870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          PING();
22970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          CloseHandle (sitter->start_sync_event);
230e73985bb144b5de819baa3f9f47a892f8ce21618Christian Ehrlicher          sitter->start_sync_event = NULL;
23170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
23270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
23370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
23470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->end_sync_event != NULL)
23570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
23670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          CloseHandle (sitter->end_sync_event);
23770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->end_sync_event = NULL;
23870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
23970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
24070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
24170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_free (sitter->executable);
24270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
24370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_free (sitter);
24470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
24570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
24670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
24770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackervoid
24870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_kill_child (DBusBabysitter *sitter)
24970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
25070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
25170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle == NULL)
25270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return; /* child is already dead, or we're so hosed we'll never recover */
25370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
25470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
25570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  TerminateProcess (sitter->child_handle, 12345);
25670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
25770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
25870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
25970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Checks whether the child has exited, without blocking.
26070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
26170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
26270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
26370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
26470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
26570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
26670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
26770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return (sitter->child_handle == NULL);
26870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
26970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
27070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
271722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * Gets the exit status of the child. We do this so implementation specific
272722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * detail is not cluttering up dbus, for example the system launcher code.
273722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * This can only be called if the child has exited, i.e. call
274722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
275722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * did not return a status code, e.g. because the child was signaled
276722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * or we failed to ever launch the child in the first place.
277722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher *
278722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * @param sitter the babysitter
279722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * @param status the returned status code
280722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher * @returns #FALSE on failure
281722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher */
282722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicherdbus_bool_t
283722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher_dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
284722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher                                        int            *status)
285722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher{
286722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  if (!_dbus_babysitter_get_child_exited (sitter))
287722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher    _dbus_assert_not_reached ("Child has not exited");
288722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
289722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  if (!sitter->have_child_status ||
290722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher      sitter->child_status == STILL_ACTIVE)
291722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher    return FALSE;
292722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
293722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  *status = sitter->child_status;
294722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  return TRUE;
295722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher}
296722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
297722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher/**
29870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Sets the #DBusError with an explanation of why the spawned
29970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * child process exited (on a signal, or whatever). If
30070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * the child process has not exited, does nothing (error
30170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * will remain unset).
30270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
30370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
30470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param error an error to fill in
30570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
30670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackervoid
30770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
30870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                       DBusError      *error)
30970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
31070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
31170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_babysitter_get_child_exited (sitter))
31270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return;
31370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
31470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
31570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->have_spawn_errno)
31670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
3176e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann      char *emsg = _dbus_win_error_string (sitter->spawn_errno);
31870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
31970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      "Failed to execute program %s: %s",
3206e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann                      sitter->executable, emsg);
3216e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann      _dbus_win_free_error_string (emsg);
32270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
32370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else if (sitter->have_child_status)
32470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
32570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
32670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
32770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      "Process %s exited with status %d",
32870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      sitter->executable, sitter->child_status);
32970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
33070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else
33170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
33270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
33370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error (error, DBUS_ERROR_FAILED,
33470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      "Process %s exited, status unknown",
33570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      sitter->executable);
33670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
33770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
33870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
33970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
34070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
34170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
34270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusAddWatchFunction       add_function,
34370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusRemoveWatchFunction    remove_function,
34470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusWatchToggledFunction   toggled_function,
34570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      void                      *data,
34670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusFreeFunction           free_data_function)
34770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
34870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
34970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return _dbus_watch_list_set_functions (sitter->watches,
35070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         add_function,
35170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         remove_function,
35270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         toggled_function,
35370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         data,
35470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         free_data_function);
35570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
35670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
35770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
35870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerhandle_watch (DBusWatch       *watch,
35970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              unsigned int     condition,
36070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              void            *data)
36170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
36270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter = data;
36370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
36470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
36570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * actually send the exit statuses, error codes and whatnot through
36670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * sockets and/or pipes. On Win32, the babysitter is jus a thread,
36770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * so it can set the status fields directly in the babysitter struct
36870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * just fine. The socket pipe is used just so we can watch it with
36970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * select(), as soon as anything is written to it we know that the
37070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * babysitter thread has recorded the status in the babysitter
37170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * struct.
37270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   */
37370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
37470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
37570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_close_socket (sitter->socket_to_babysitter, NULL);
37670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
37770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->socket_to_babysitter = -1;
37870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
37970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
38070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
38170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
38270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
38370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic int
38470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerprotect_argv (char  **argv,
38570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              char ***new_argv)
38670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
38770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int i;
38870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int argc = 0;
38970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
39070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  while (argv[argc])
39170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    ++argc;
39270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
39370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (*new_argv == NULL)
39470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return -1;
39570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
39670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  for (i = 0; i < argc; i++)
39770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    (*new_argv)[i] = NULL;
39870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
39970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /* Quote each argv element if necessary, so that it will get
40070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * reconstructed correctly in the C runtime startup code.  Note that
40170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * the unquoting algorithm in the C runtime is really weird, and
40270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * rather different than what Unix shells do. See stdargv.c in the C
40370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * runtime sources (in the Platform SDK, in src/crt).
40470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   *
40570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * Note that an new_argv[0] constructed by this function should
40670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * *not* be passed as the filename argument to a spawn* or exec*
40770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * family function. That argument should be the real file name
40870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * without any quoting.
40970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   */
41070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  for (i = 0; i < argc; i++)
41170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
41270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      char *p = argv[i];
41370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      char *q;
41470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      int len = 0;
41570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      int need_dblquotes = FALSE;
41670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      while (*p)
41770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
41870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          if (*p == ' ' || *p == '\t')
41970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            need_dblquotes = TRUE;
42070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          else if (*p == '"')
42170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            len++;
42270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          else if (*p == '\\')
42370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            {
42470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              char *pp = p;
42570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              while (*pp && *pp == '\\')
42670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                pp++;
42770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              if (*pp == '"')
42870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                len++;
42970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            }
43070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          len++;
43170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          p++;
43270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
43370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
43470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
43570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
43670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (q == NULL)
43770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        return -1;
43870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
43970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
44070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      p = argv[i];
44170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
44270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (need_dblquotes)
44370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        *q++ = '"';
44470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
44570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      while (*p)
44670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
44770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          if (*p == '"')
44870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            *q++ = '\\';
44970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          else if (*p == '\\')
45070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            {
45170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              char *pp = p;
45270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              while (*pp && *pp == '\\')
45370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                pp++;
45470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              if (*pp == '"')
45570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                *q++ = '\\';
45670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            }
45770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          *q++ = *p;
45870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          p++;
45970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
46070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
46170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (need_dblquotes)
46270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        *q++ = '"';
46370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      *q++ = '\0';
46470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
46570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
46670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  (*new_argv)[argc] = NULL;
46770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
46870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return argc;
46970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
47070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
4716e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
4726e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann/* From GPGME, relicensed by g10 Code GmbH.  */
4736e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmannstatic char *
474ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trbacompose_string (char **strings, char separator)
4756e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann{
4766e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  int i;
4776e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  int n = 0;
4786e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  char *buf;
4796e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  char *p;
4806e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  const char *ptr;
4816e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
482ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  if (!strings || !strings[0])
483ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba    return 0;
484ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  for (i = 0; strings[i]; i++)
485ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba    n += strlen (strings[i]) + 1;
4866e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  n++;
4876e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
4886e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  buf = p = malloc (n);
4896e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  if (!buf)
4906e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann    return NULL;
491ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  for (i = 0; strings[i]; i++)
4926e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann    {
493ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba      strcpy (p, strings[i]);
494ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba      p += strlen (strings[i]);
495ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba      *(p++) = separator;
4966e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann    }
497ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  p--;
498ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  *(p++) = '\0';
4996e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  *p = '\0';
5006e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
5016e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  return buf;
5026e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann}
5036e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
504ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trbastatic char *
505ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trbabuild_commandline (char **argv)
506ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba{
507ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  return compose_string (argv, ' ');
508ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba}
509ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba
510ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trbastatic char *
511ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trbabuild_env_string (char** envp)
512ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba{
513ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  return compose_string (envp, '\0');
514ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba}
5156e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
5166e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmannstatic HANDLE
517ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trbaspawn_program (char* name, char** argv, char** envp)
5186e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann{
5196e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
5206e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  STARTUPINFOA si;
521ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  char *arg_string, *env_string;
5226e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  BOOL result;
5236e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
52448801c87df51f3864c9bcae28e34233222497e20Marcus Brinkmann#ifdef DBUS_WINCE
5259165229a0a4eb95c5709dd048e0e12470971a899Marcus Brinkmann  if (argv && argv[0])
5269165229a0a4eb95c5709dd048e0e12470971a899Marcus Brinkmann    arg_string = build_commandline (argv + 1);
5279165229a0a4eb95c5709dd048e0e12470971a899Marcus Brinkmann  else
5289165229a0a4eb95c5709dd048e0e12470971a899Marcus Brinkmann    arg_string = NULL;
52948801c87df51f3864c9bcae28e34233222497e20Marcus Brinkmann#else
5306e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  arg_string = build_commandline (argv);
53148801c87df51f3864c9bcae28e34233222497e20Marcus Brinkmann#endif
5326e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  if (!arg_string)
5336e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann    return INVALID_HANDLE_VALUE;
5346e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
535ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  env_string = build_env_string(envp);
536ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba
5376e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  memset (&si, 0, sizeof (si));
5386e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  si.cb = sizeof (si);
539f578ad20ef9b6db635c5178651def600fb5ccbe9Fridrich Å trba#ifdef DBUS_WINCE
5406e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
541f578ad20ef9b6db635c5178651def600fb5ccbe9Fridrich Å trba#else
542f578ad20ef9b6db635c5178651def600fb5ccbe9Fridrich Å trba  result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
543f578ad20ef9b6db635c5178651def600fb5ccbe9Fridrich Å trba#endif
544ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba			   (LPVOID)env_string, NULL, &si, &pi);
5456e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  free (arg_string);
546ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba  if (env_string)
547ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba    free (env_string);
548ecb7a5606cdb077c86ed81a7db81df5038824de6Fridrich Å trba
5496e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  if (!result)
5506e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann    return INVALID_HANDLE_VALUE;
5516e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
5526e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  CloseHandle (pi.hThread);
5536e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  return pi.hProcess;
5546e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann}
5556e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
5566e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
5576e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmannstatic DWORD __stdcall
55870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerbabysitter (void *parameter)
55970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
56070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter = (DBusBabysitter *) parameter;
561a1a285b10d92708515977d8e9e5f07cb920e92c6Ralf Habacker  int fd;
56270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
56370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_babysitter_ref (sitter);
56470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
56570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_setup)
56670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
56770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
56870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      (*sitter->child_setup) (sitter->user_data);
56970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
57070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
57170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
57270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
57370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
5746e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  sitter->child_handle = spawn_program (sitter->executable,
5756e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann					sitter->argv, sitter->envp);
57670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
57770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
57870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle == (HANDLE) -1)
57970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
58070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->child_handle = NULL;
58170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->have_spawn_errno = TRUE;
5826e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann      sitter->spawn_errno = GetLastError();
58370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
5846e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
58570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
58670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  SetEvent (sitter->start_sync_event);
58770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
58870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle != NULL)
58970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
59070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      int ret;
59170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      DWORD status;
59270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
59370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
59470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      WaitForSingleObject (sitter->child_handle, INFINITE);
59570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
59670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
59770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      ret = GetExitCodeProcess (sitter->child_handle, &status);
59870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
59970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->child_status = status;
60070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->have_child_status = TRUE;
60170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
60270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      CloseHandle (sitter->child_handle);
60370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->child_handle = NULL;
60470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
60570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
60670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
60770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  SetEvent (sitter->end_sync_event);
60870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
60970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
61070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
611a1a285b10d92708515977d8e9e5f07cb920e92c6Ralf Habacker  send (sitter->socket_to_main, " ", 1, 0);
61270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
61370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_babysitter_unref (sitter);
61470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
61570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return 0;
61670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
61770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
61870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
61970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
62070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   char                     **argv,
62170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   char                     **envp,
62270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   DBusSpawnChildSetupFunc    child_setup,
62370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   void                      *user_data,
62470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   DBusError                 *error)
62570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
62670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
62770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  HANDLE sitter_thread;
6286e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  DWORD sitter_thread_id;
6296e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann
63070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
63170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
63270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  *sitter_p = NULL;
63370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
63470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
63570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = _dbus_babysitter_new ();
63670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter == NULL)
63770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
63870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
63970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
64070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
64170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
64270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->child_setup = child_setup;
64370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->user_data = user_data;
64470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
64570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->executable = _dbus_strdup (argv[0]);
64670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->executable == NULL)
64770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
64870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
64970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
65070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
65170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
65270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
65370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
65470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                               &sitter->socket_to_main,
65570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                               FALSE, error))
65670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    goto out0;
65770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
65870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
65970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                          DBUS_WATCH_READABLE,
66070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                          TRUE, handle_watch, sitter, NULL);
66170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
66270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->sitter_watch == NULL)
66370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
66470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
66570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
66670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
66770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
66870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
66970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
67070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
67170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
67270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
67370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
67470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
67570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->argc = protect_argv (argv, &sitter->argv);
67670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->argc == -1)
67770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
67870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
67970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
68070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
68170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->envp = envp;
68270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
68370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
6846e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann  sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
68570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  sitter, 0, &sitter_thread_id);
68670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
68770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter_thread == 0)
68870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
68970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
69070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
69170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                            "Failed to create new thread");
69270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
69370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
69470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  CloseHandle (sitter_thread);
69570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
69670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
69770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  WaitForSingleObject (sitter->start_sync_event, INFINITE);
69870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
69970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
70070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter_p != NULL)
70170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    *sitter_p = sitter;
70270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else
70370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
70470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
70570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
70670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
70770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
70870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
70970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerout0:
71170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_babysitter_unref (sitter);
71270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return FALSE;
71470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
71570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
71770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
71970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
72070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic void
72170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
72270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
72370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle == NULL)
72470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return;
72570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
72670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  WaitForSingleObject (sitter->end_sync_event, INFINITE);
72770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
72870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
72970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
73070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_nonexistent (void *data)
73170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
73270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
733722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusBabysitter *sitter;
734722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusError error;
735722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
736722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  sitter = NULL;
737722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
738722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  dbus_error_init (&error);
73970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
74070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching nonexistent binary */
74170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
74270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
74370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
74470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
74570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
74670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
74770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
74870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
74970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
75070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
75170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
75270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
75370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
75470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
75570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
75670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error launching nonexistent executable\n");
75770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
75870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
75970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
76070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
76170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
76270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
76370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
76470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
76570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
76670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
76770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
76870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
76970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
77070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
77170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
77270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
77370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
77470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
77570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_segfault (void *data)
77670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
77770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
778722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusBabysitter *sitter;
779722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusError error;
780722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
781722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  sitter = NULL;
782722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
783722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  dbus_error_init (&error);
78470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
78570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching segfault binary */
78670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
78770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = TEST_SEGFAULT_BINARY;
78870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
78970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
79070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
79170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
79270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
79370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
79470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
79570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
79670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
79770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
79870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
79970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
80070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
80170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error launching segfaulting binary\n");
80270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
80370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
80470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
80570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
80670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
80770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
80870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
80970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
81070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
81170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
81270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
81370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
81470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
81570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
81670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
81770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
81870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
81970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
82070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_exit (void *data)
82170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
82270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
823722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusBabysitter *sitter;
824722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusError error;
825722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
826722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  sitter = NULL;
827722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
828722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  dbus_error_init (&error);
82970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
83070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching exit failure binary */
83170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
83270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = TEST_EXIT_BINARY;
83370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
83470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
83570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
83670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
83770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
83870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
83970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
84070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
84170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
84270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
84370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
84470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
84570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
84670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
84770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
84870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
84970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
85070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
85170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
85270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
85370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
85470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
85570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
85670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
85770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
85870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
85970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
86070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
86170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
86270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
86370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
86470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
86570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_and_kill (void *data)
86670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
86770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
868722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusBabysitter *sitter;
869722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  DBusError error;
870722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
871722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  sitter = NULL;
872722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher
873722a90c9cbc7368ffde9ad768ef4f2e45c3a620dChristian Ehrlicher  dbus_error_init (&error);
87470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
87570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching sleeping binary then killing it */
87670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
87770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = TEST_SLEEP_FOREVER_BINARY;
87870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
87970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
88070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
88170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
88270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_kill_child (sitter);
88370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
88470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
88570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
88670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
88770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
88870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
88970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
89070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
89170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
89270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
89370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
89470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error after killing spawned binary\n");
89570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
89670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
89770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
89870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
89970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
90070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
90170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
90270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
90370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
90470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
90570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
90670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
90770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
90870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
90970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
91070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
91170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
91270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
91370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_spawn_test (const char *test_data_dir)
91470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
91570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_test_oom_handling ("spawn_nonexistent",
91670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                check_spawn_nonexistent,
91770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                NULL))
91870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return FALSE;
91970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
92070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /* Don't run the obnoxious segfault test by default,
92170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * it's a pain to have to click all those error boxes.
92270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   */
92370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (getenv ("DO_SEGFAULT_TEST"))
92470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    if (!_dbus_test_oom_handling ("spawn_segfault",
92570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                  check_spawn_segfault,
92670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                  NULL))
92770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
92870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
92970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_test_oom_handling ("spawn_exit",
93070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                check_spawn_exit,
93170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                NULL))
93270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return FALSE;
93370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
93470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_test_oom_handling ("spawn_and_kill",
93570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                check_spawn_and_kill,
93670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                NULL))
93770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return FALSE;
93870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
93970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
94070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
94170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
942