dbus-spawn-win.c
#include <config.h>
//#define SPAWN_DEBUG
#if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
#define PING()
#else
#define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, _DBUS_FUNCTION_NAME, __LINE__); fflush (stderr)
#endif
#include <stdio.h>
/* -*- 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.
* Copyright (C) 2003 CodeFactory AB
* Copyright (C) 2005 Novell, Inc.
*
* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "dbus-spawn.h"
#include "dbus-sysdeps.h"
#include "dbus-sysdeps-win.h"
#include "dbus-internals.h"
#include "dbus-test.h"
#include "dbus-protocol.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//#define STRICT
//#include <windows.h>
//#undef STRICT
#include <winsock2.h>
#undef interface
#include <stdlib.h>
#ifndef DBUS_WINCE
#include <process.h>
#endif
struct DBusBabysitter
{
DBusAtomic refcount;
char *log_name;
HANDLE thread_handle;
HANDLE child_handle;
DBusSocket socket_to_babysitter; /* Connection to the babysitter thread */
DBusSocket socket_to_main;
DBusWatchList *watches;
DBusWatch *sitter_watch;
DBusBabysitterFinishedFunc finished_cb;
void *finished_data;
dbus_bool_t have_spawn_errno;
int spawn_errno;
dbus_bool_t have_child_status;
int child_status;
};
static void
_dbus_babysitter_trace_ref (DBusBabysitter *sitter,
int old_refcount,
int new_refcount,
const char *why)
{
#ifdef DBUS_ENABLE_VERBOSE_MODE
static int enabled = -1;
_dbus_trace_ref ("DBusBabysitter", sitter, old_refcount, new_refcount, why,
"DBUS_BABYSITTER_TRACE", &enabled);
#endif
}
static DBusBabysitter*
_dbus_babysitter_new (void)
{
DBusBabysitter *sitter;
dbus_int32_t old_refcount;
sitter = dbus_new0 (DBusBabysitter, 1);
if (sitter == NULL)
return NULL;
old_refcount = _dbus_atomic_inc (&sitter->refcount);
_dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, _DBUS_FUNCTION_NAME);
sitter->child_handle = NULL;
sitter->socket_to_babysitter = sitter->socket_to_main = _dbus_socket_get_invalid ();
sitter->watches = _dbus_watch_list_new ();
if (sitter->watches == NULL)
{
_dbus_babysitter_unref (sitter);
return NULL;
}
sitter->have_spawn_errno = FALSE;
sitter->have_child_status = FALSE;
return sitter;
}
DBusBabysitter *
_dbus_babysitter_ref (DBusBabysitter *sitter)
{
dbus_int32_t old_refcount;
PING();
_dbus_assert (sitter != NULL);
old_refcount = _dbus_atomic_inc (&sitter->refcount);
_dbus_assert (old_refcount > 0);
_dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, _DBUS_FUNCTION_NAME);
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.sock != INVALID_SOCKET)
{
_dbus_close_socket (&sitter->socket_to_babysitter, NULL);
sitter->socket_to_babysitter.sock = INVALID_SOCKET;
}
}
void
_dbus_babysitter_unref (DBusBabysitter *sitter)
{
dbus_int32_t old_refcount;
PING();
_dbus_assert (sitter != NULL);
old_refcount = _dbus_atomic_dec (&sitter->refcount);
_dbus_assert (old_refcount > 0);
_dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, _DBUS_FUNCTION_NAME);
if (old_refcount == 1)
{
close_socket_to_babysitter (sitter);
if (sitter->socket_to_main.sock != INVALID_SOCKET)
{
_dbus_close_socket (&sitter->socket_to_main, NULL);
sitter->socket_to_main.sock = INVALID_SOCKET;
}
if (sitter->child_handle != NULL)
{
CloseHandle (sitter->child_handle);
sitter->child_handle = NULL;
}
if (sitter->sitter_watch)
{
_dbus_watch_invalidate (sitter->sitter_watch);
_dbus_watch_unref (sitter->sitter_watch);
sitter->sitter_watch = NULL;
}
if (sitter->watches)
_dbus_watch_list_free (sitter->watches);
if (sitter->thread_handle)
{
CloseHandle (sitter->thread_handle);
sitter->thread_handle = NULL;
}
dbus_free (sitter->log_name);
dbus_free (sitter);
}
}
void
_dbus_babysitter_kill_child (DBusBabysitter *sitter)
{
PING();
if (sitter->child_handle == NULL)
return; /* child is already dead, or we're so hosed we'll never recover */
PING();
TerminateProcess (sitter->child_handle, 12345);
}
dbus_bool_t
_dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
{
PING();
return (sitter->child_handle == NULL);
}
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;
}
void
_dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
DBusError *error)
{
PING();
if (!_dbus_babysitter_get_child_exited (sitter))
return;
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->log_name, emsg);
_dbus_win_free_error_string (emsg);
}
else if (sitter->have_child_status)
{
PING();
dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
"Process %s exited with status %d",
sitter->log_name, sitter->child_status);
}
else
{
PING();
dbus_set_error (error, DBUS_ERROR_FAILED,
"Process %s exited, status unknown",
sitter->log_name);
}
PING();
}
dbus_bool_t
_dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
DBusWatchToggledFunction toggled_function,
void *data,
DBusFreeFunction free_data_function)
{
PING();
return _dbus_watch_list_set_functions (sitter->watches,
add_function,
remove_function,
toggled_function,
data,
free_data_function);
}
static dbus_bool_t
handle_watch (DBusWatch *watch,
unsigned int condition,
void *data)
{
DBusBabysitter *sitter = data;
/* On Unix dbus-spawn uses a babysitter *process*, thus it has to
* actually send the exit statuses, error codes and whatnot through
* sockets and/or pipes. On Win32, the babysitter is jus a thread,
* so it can set the status fields directly in the babysitter struct
* just fine. The socket pipe is used just so we can watch it with
* select(), as soon as anything is written to it we know that the
* babysitter thread has recorded the status in the babysitter
* struct.
*/
PING();
close_socket_to_babysitter (sitter);
PING();
if (_dbus_babysitter_get_child_exited (sitter) &&
sitter->finished_cb != NULL)
{
sitter->finished_cb (sitter, sitter->finished_data);
sitter->finished_cb = NULL;
}
return TRUE;
}
/* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
static int
protect_argv (char * const *argv,
char ***new_argv)
{
int i;
int argc = 0;
char **args = NULL;
while (argv[argc])
++argc;
args = dbus_malloc ((argc + 1) * sizeof (char *));
if (args == NULL)
return -1;
for (i = 0; i < argc; i++)
(args)[i] = NULL;
/* Quote each argv element if necessary, so that it will get
* reconstructed correctly in the C runtime startup code. Note that
* the unquoting algorithm in the C runtime is really weird, and
* rather different than what Unix shells do. See stdargv.c in the C
* runtime sources (in the Platform SDK, in src/crt).
*
* Note that an new_argv[0] constructed by this function should
* *not* be passed as the filename argument to a spawn* or exec*
* family function. That argument should be the real file name
* without any quoting.
*/
for (i = 0; i < argc; i++)
{
const char *p = argv[i];
char *q;
int len = 0;
int need_dblquotes = FALSE;
while (*p)
{
if (*p == ' ' || *p == '\t')
need_dblquotes = TRUE;
else if (*p == '"')
len++;
else if (*p == '\\')
{
const char *pp = p;
while (*pp && *pp == '\\')
pp++;
if (*pp == '"')
len++;
}
len++;
p++;
}
q = args[i] = dbus_malloc (len + need_dblquotes*2 + 1);
if (q == NULL)
{
dbus_free_string_array (args);
return -1;
}
p = argv[i];
if (need_dblquotes)
*q++ = '"';
while (*p)
{
if (*p == '"')
*q++ = '\\';
else if (*p == '\\')
{
const char *pp = p;
while (*pp && *pp == '\\')
pp++;
if (*pp == '"')
*q++ = '\\';
}
*q++ = *p;
p++;
}
if (need_dblquotes)
*q++ = '"';
*q++ = '\0';
/* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (args)[i]); */
}
args[argc] = NULL;
*new_argv = args;
return argc;
}
static dbus_bool_t
build_commandline (char **argv, DBusString *result)
{
return _dbus_string_append_strings (result, argv, ' ');
}
static dbus_bool_t
build_env_block (char** envp, DBusString *result)
{
if (!_dbus_string_append_strings (result, envp, '\0'))
return FALSE;
/* We need a double `\0` to terminate the environment block.
* DBusString provides one `\0` after the length-counted data,
* so add one more. */
if (!_dbus_string_append_byte (result, '\0'))
return FALSE;
return TRUE;
}
HANDLE
_dbus_spawn_program (const char *name,
char **argv,
char **envp,
dbus_bool_t inherit_handles,
DBusError *error)
{
PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
STARTUPINFOA si;
DBusString arg_string = _DBUS_STRING_INIT_INVALID;
DBusString env_block = _DBUS_STRING_INIT_INVALID;
BOOL result = FALSE;
char *env = NULL;
if (!_dbus_string_init (&arg_string) || !_dbus_string_init (&env_block))
{
_DBUS_SET_OOM (error);
goto out;
}
#ifdef DBUS_WINCE
if (argv && argv[0])
{
if (!build_commandline (argv + 1, &arg_string))
_DBUS_SET_OOM (error);
goto out;
}
#else
if (!build_commandline (argv, &arg_string))
{
_DBUS_SET_OOM (error);
goto out;
}
#endif
if (_dbus_string_get_length (&arg_string) == 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED, "No arguments given to start '%s'", name);
goto out;
}
if (envp != NULL)
{
if (!build_env_block (envp, &env_block))
{
_DBUS_SET_OOM (error);
goto out;
}
/* env_block consists of '0' terminated strings */
env = _dbus_string_get_data (&env_block);
}
memset (&si, 0, sizeof (si));
si.cb = sizeof (si);
#ifdef DBUS_ENABLE_VERBOSE_MODE
{
DBusString temp = _DBUS_STRING_INIT_INVALID;
if (!_dbus_string_init (&temp))
{
_DBUS_SET_OOM (error);
goto out;
}
if (!_dbus_string_append_strings (&temp, envp, ';'))
{
_dbus_string_free (&temp);
_DBUS_SET_OOM (error);
goto out;
}
_dbus_verbose ("spawning '%s'' with args: '%s' env: '%s'\n", name,
_dbus_string_get_const_data (&arg_string),
_dbus_string_get_const_data (&temp));
_dbus_string_free (&temp);
}
#endif
#ifdef DBUS_WINCE
result = CreateProcessA (name, _dbus_string_get_const_data (&arg_string), NULL, NULL, FALSE, 0,
#else
result = CreateProcessA (NULL, /* no application name */
_dbus_string_get_data (&arg_string),
NULL, /* no process attributes */
NULL, /* no thread attributes */
inherit_handles, /* inherit handles */
0, /* flags */
#endif
env, NULL, &si, &pi);
if (!result)
{
_dbus_win_set_error_from_last_error (error, "Unable to start '%s' with arguments '%s'",
name, _dbus_string_get_const_data (&arg_string));
goto out;
}
out:
_DBUS_ASSERT_ERROR_XOR_BOOL (error, result);
_dbus_string_free (&arg_string);
_dbus_string_free (&env_block);
if (result)
{
CloseHandle (pi.hThread);
return pi.hProcess;
}
return NULL;
}
static DWORD __stdcall
babysitter (void *parameter)
{
int ret = 0;
DBusBabysitter *sitter = (DBusBabysitter *) parameter;
PING();
if (sitter->child_handle != NULL)
{
DWORD status;
PING();
// wait until process finished
WaitForSingleObject (sitter->child_handle, INFINITE);
PING();
ret = GetExitCodeProcess (sitter->child_handle, &status);
if (ret)
{
sitter->child_status = status;
sitter->have_child_status = TRUE;
}
CloseHandle (sitter->child_handle);
sitter->child_handle = NULL;
}
PING();
send (sitter->socket_to_main.sock, " ", 1, 0);
_dbus_babysitter_unref (sitter);
return ret ? 0 : 1;
}
dbus_bool_t
_dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
const char *log_name,
char * const *argv,
char * const *envp,
DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
void *user_data _DBUS_GNUC_UNUSED,
DBusError *error)
{
DBusBabysitter *sitter;
DWORD sitter_thread_id;
HANDLE handle;
int argc;
char **my_argv = NULL;
DBusError local_error = DBUS_ERROR_INIT;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_assert (argv[0] != NULL);
if (sitter_p != NULL)
*sitter_p = NULL;
PING();
sitter = _dbus_babysitter_new ();
if (sitter == NULL)
{
_DBUS_SET_OOM (error);
return FALSE;
}
sitter->log_name = _dbus_strdup (log_name);
if (sitter->log_name == NULL && log_name != NULL)
{
_DBUS_SET_OOM (error);
goto out0;
}
if (sitter->log_name == NULL)
sitter->log_name = _dbus_strdup (argv[0]);
if (sitter->log_name == NULL)
{
_DBUS_SET_OOM (error);
goto out0;
}
PING();
if (!_dbus_socketpair (&sitter->socket_to_babysitter,
&sitter->socket_to_main,
FALSE, error))
goto out0;
sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
DBUS_WATCH_READABLE,
TRUE, handle_watch, sitter, NULL);
PING();
if (sitter->sitter_watch == NULL)
{
_DBUS_SET_OOM (error);
goto out0;
}
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;
}
argc = protect_argv (argv, &my_argv);
if (argc == -1)
{
_DBUS_SET_OOM (error);
goto out0;
}
_dbus_verbose ("babysitter: spawn child '%s'\n", my_argv[0]);
PING();
handle = _dbus_spawn_program (sitter->log_name, my_argv, (char **) envp, FALSE, &local_error);
if (my_argv != NULL)
{
dbus_free_string_array (my_argv);
}
PING();
if (handle == NULL)
{
if (dbus_error_has_name (&local_error, DBUS_ERROR_NO_MEMORY))
{
sitter->child_handle = NULL;
sitter->have_spawn_errno = TRUE;
sitter->spawn_errno = ERROR_NOT_ENOUGH_MEMORY;
dbus_move_error (&local_error, error);
}
else
{
sitter->child_handle = NULL;
sitter->have_spawn_errno = TRUE;
sitter->spawn_errno = GetLastError();
dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
"Failed to spawn child: %s", local_error.message);
}
dbus_error_free (&local_error);
goto out0;
}
else
dbus_error_free (&local_error);
sitter->child_handle = handle;
PING();
sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
_dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
if (sitter->thread_handle == NULL)
{
PING();
dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
"Failed to create new thread");
goto out0;
}
PING();
if (sitter_p != NULL)
*sitter_p = sitter;
else
_dbus_babysitter_unref (sitter);
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
PING();
return TRUE;
out0:
_dbus_babysitter_unref (sitter);
return FALSE;
}
void
_dbus_babysitter_set_result_function (DBusBabysitter *sitter,
DBusBabysitterFinishedFunc finished,
void *user_data)
{
sitter->finished_cb = finished;
sitter->finished_data = user_data;
}
#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
void
_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
{
/* The thread terminates after the child does. We want to wait for the thread,
* not just the child, to avoid data races and ensure that it has freed all
* its memory. */
WaitForSingleObject (sitter->thread_handle, INFINITE);
}
DBusWatchToggledFunction
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
Definition dbus-connection.h:100
DBusAddWatchFunction
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
Definition dbus-connection.h:94
DBusRemoveWatchFunction
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
Definition dbus-connection.h:106
DBUS_WATCH_READABLE
@ DBUS_WATCH_READABLE
As in POLLIN.
Definition dbus-connection.h:63
DBUS_ERROR_INIT
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition dbus-errors.h:64
dbus_move_error
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition dbus-errors.c:281
dbus_set_error_const
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
Definition dbus-errors.c:245
dbus_error_has_name
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition dbus-errors.c:304
dbus_set_error
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition dbus-errors.c:356
dbus_error_free
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition dbus-errors.c:213
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition dbus-internals.h:164
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition dbus-internals.h:153
_dbus_babysitter_get_child_exit_status
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
Definition dbus-spawn-win.c:261
_dbus_babysitter_unref
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition dbus-spawn-win.c:176
_dbus_babysitter_get_child_exited
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
Definition dbus-spawn-win.c:242
_dbus_babysitter_set_watch_functions
dbus_bool_t _dbus_babysitter_set_watch_functions(DBusBabysitter *sitter, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets watch functions to notify us when the babysitter object needs to read/write file descriptors.
Definition dbus-spawn-win.c:319
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition dbus-internals.c:621
_dbus_babysitter_set_child_exit_error
void _dbus_babysitter_set_child_exit_error(DBusBabysitter *sitter, DBusError *error)
Sets the DBusError with an explanation of why the spawned child process exited (on a signal,...
Definition dbus-spawn-win.c:285
_dbus_babysitter_kill_child
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
Definition dbus-spawn-win.c:226
_dbus_babysitter_ref
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
Definition dbus-spawn-win.c:136
_dbus_spawn_async_with_babysitter
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char *const *env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
Definition dbus-spawn-unix.c:1279
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:51
TRUE
#define TRUE
Expands to "1".
Definition dbus-macros.h:41
FALSE
#define FALSE
Expands to "0".
Definition dbus-macros.h:44
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition dbus-memory.c:710
DBusFreeFunction
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition dbus-memory.h:65
dbus_new0
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition dbus-memory.h:60
dbus_free_string_array
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition dbus-memory.c:758
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition dbus-memory.c:470
DBUS_ERROR_SPAWN_CHILD_EXITED
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
Definition dbus-protocol.h:426
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition dbus-protocol.h:361
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition dbus-protocol.h:422
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition dbus-protocol.h:363
DBUS_ERROR_SPAWN_FORK_FAILED
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
Definition dbus-protocol.h:424
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition dbus-string.c:182
_dbus_string_append_strings
dbus_bool_t _dbus_string_append_strings(DBusString *str, char **strings, char separator)
Append vector with strings connected by separator.
Definition dbus-string.c:1213
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
Definition dbus-string.c:278
_dbus_string_append_byte
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition dbus-string.c:1190
DBusAtomic
struct DBusAtomic DBusAtomic
Opaque type representing an atomically-modifiable integer that can be used from multiple threads.
Definition dbus-sysdeps.h:334
_dbus_socketpair
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
Definition dbus-sysdeps-unix.c:3884
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition dbus-sysdeps-unix.c:3205
_dbus_close_socket
dbus_bool_t _dbus_close_socket(DBusSocket *fd, DBusError *error)
Closes a socket and invalidates it.
Definition dbus-sysdeps-unix.c:314
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition dbus-sysdeps-unix.c:3178
dbus_int32_t
int dbus_int32_t
A 32-bit signed integer on all platforms.
Definition dbus-arch-deps.h:44
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:37
_dbus_watch_list_add_watch
dbus_bool_t _dbus_watch_list_add_watch(DBusWatchList *watch_list, DBusWatch *watch)
Adds a new watch to the watch list, invoking the application DBusAddWatchFunction if appropriate.
Definition dbus-watch.c:383
_dbus_watch_list_new
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition dbus-watch.c:234
DBusWatchList
struct DBusWatchList DBusWatchList
Opaque data type representing a list of watches and a set of DBusAddWatchFunction/DBusRemoveWatchFunc...
Definition dbus-watch.h:40
_dbus_watch_list_free
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition dbus-watch.c:251
_dbus_watch_list_set_functions
dbus_bool_t _dbus_watch_list_set_functions(DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions.
Definition dbus-watch.c:297
_dbus_watch_new
DBusWatch * _dbus_watch_new(DBusPollable fd, unsigned int flags, dbus_bool_t enabled, DBusWatchHandler handler, void *data, DBusFreeFunction free_data_function)
Creates a new DBusWatch.
Definition dbus-watch.c:90
_dbus_watch_unref
void _dbus_watch_unref(DBusWatch *watch)
Decrements the reference count of a DBusWatch object and finalizes the object if the count reaches ze...
Definition dbus-watch.c:140
_dbus_watch_list_remove_watch
void _dbus_watch_list_remove_watch(DBusWatchList *watch_list, DBusWatch *watch)
Removes a watch from the watch list, invoking the application's DBusRemoveWatchFunction if appropriat...
Definition dbus-watch.c:416
_dbus_watch_invalidate
void _dbus_watch_invalidate(DBusWatch *watch)
Clears the file descriptor from a now-invalid watch object so that no one tries to use it.
Definition dbus-watch.c:171
DBusBabysitter
Babysitter implementation details.
Definition dbus-spawn-unix.c:252
DBusBabysitter::sitter_watch
DBusWatch * sitter_watch
Sitter pipe watch.
Definition dbus-spawn-unix.c:267
DBusBabysitter::socket_to_babysitter
DBusSocket socket_to_babysitter
Connection to the babysitter process.
Definition dbus-spawn-unix.c:258
DBusBabysitter::have_child_status
unsigned int have_child_status
True if child status has been reaped.
Definition dbus-spawn-unix.c:274
DBusBabysitter::log_name
char * log_name
the name under which to log messages about this process being spawned
Definition dbus-spawn-unix.c:255
DBusBabysitter::refcount
int refcount
Reference count.
Definition dbus-spawn-unix.c:253
DBusBabysitter::watches
DBusWatchList * watches
Watches.
Definition dbus-spawn-unix.c:264
DBusError
Object representing an exception.
Definition dbus-errors.h:51
DBusError::message
const char * message
public error message field
Definition dbus-errors.h:53
DBusString
Definition dbus-string.h:47
DBusWatch
Implementation of DBusWatch.
Definition dbus-watch.c:43