2003-04-06 Havoc Pennington <hp@pobox.com>

* bus/bus.c (bus_context_new): fix wrong handling of
	server_data_slot_unref() in the error case.

	* dbus/dbus-internals.h (_dbus_assert): change so it passes
	"(condition) != 0" to _dbus_real_assert so that
	"_dbus_assert (pointer)" doesn't cause a warning

	* bus/main.c (main): accept --print-address option to print out
	the message bus address

	* dbus/dbus-sysdeps.c (_dbus_generate_random_ascii): export this

	* dbus/dbus-transport.c (_dbus_transport_open): special error for
	"tmpdir" option to unix: address on client side

	* dbus/dbus-server.c (dbus_server_listen): handle "tmpdir" option
	to unix: address

	* configure.in (TEST_SOCKET_DIR): locate a temporary directory
	we can use to create sockets in the test suite.

	* bus/main.c (signal_handler): on SIGTERM, exit the daemon
	cleanly. To be used for testing.

	* dbus/dbus-spawn.c (babysit): use _dbus_set_signal_handler()

	* dbus/dbus-sysdeps.c (_dbus_set_signal_handler): new

	* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
	handle trying to call this when there's no servers active
This commit is contained in:
Havoc Pennington 2003-04-06 18:03:03 +00:00
parent 2618e1a973
commit e45e438227
14 changed files with 441 additions and 137 deletions

View file

@ -1,3 +1,36 @@
2003-04-06 Havoc Pennington <hp@pobox.com>
* bus/bus.c (bus_context_new): fix wrong handling of
server_data_slot_unref() in the error case.
* dbus/dbus-internals.h (_dbus_assert): change so it passes
"(condition) != 0" to _dbus_real_assert so that
"_dbus_assert (pointer)" doesn't cause a warning
* bus/main.c (main): accept --print-address option to print out
the message bus address
* dbus/dbus-sysdeps.c (_dbus_generate_random_ascii): export this
* dbus/dbus-transport.c (_dbus_transport_open): special error for
"tmpdir" option to unix: address on client side
* dbus/dbus-server.c (dbus_server_listen): handle "tmpdir" option
to unix: address
* configure.in (TEST_SOCKET_DIR): locate a temporary directory
we can use to create sockets in the test suite.
* bus/main.c (signal_handler): on SIGTERM, exit the daemon
cleanly. To be used for testing.
* dbus/dbus-spawn.c (babysit): use _dbus_set_signal_handler()
* dbus/dbus-sysdeps.c (_dbus_set_signal_handler): new
* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
handle trying to call this when there's no servers active
2003-04-05 Havoc Pennington <hp@pobox.com> 2003-04-05 Havoc Pennington <hp@pobox.com>
* NEWS: update * NEWS: update

View file

@ -107,7 +107,10 @@ server_get_context (DBusServer *server)
bd = BUS_SERVER_DATA (server); bd = BUS_SERVER_DATA (server);
if (bd == NULL) if (bd == NULL)
{
server_data_slot_unref ();
return NULL; return NULL;
}
context = bd->context; context = bd->context;
@ -339,6 +342,12 @@ bus_context_new (const DBusString *config_file,
context->refcount = 1; context->refcount = 1;
/* we need another ref of the server data slot for the context
* to own
*/
if (!server_data_slot_ref ())
_dbus_assert_not_reached ("second ref of server data slot failed");
#ifdef DBUS_BUILD_TESTS #ifdef DBUS_BUILD_TESTS
context->activation_timeout = 6000; /* 6 seconds */ context->activation_timeout = 6000; /* 6 seconds */
#else #else
@ -542,6 +551,7 @@ bus_context_new (const DBusString *config_file,
bus_config_parser_unref (parser); bus_config_parser_unref (parser);
_dbus_string_free (&full_address); _dbus_string_free (&full_address);
dbus_free_string_array (auth_mechanisms); dbus_free_string_array (auth_mechanisms);
server_data_slot_unref ();
return context; return context;
@ -678,6 +688,12 @@ bus_context_get_type (BusContext *context)
return context->type; return context->type;
} }
const char*
bus_context_get_address (BusContext *context)
{
return context->address;
}
BusRegistry* BusRegistry*
bus_context_get_registry (BusContext *context) bus_context_get_registry (BusContext *context)
{ {

View file

@ -46,6 +46,7 @@ void bus_context_shutdown (BusContext *context)
void bus_context_ref (BusContext *context); void bus_context_ref (BusContext *context);
void bus_context_unref (BusContext *context); void bus_context_unref (BusContext *context);
const char* bus_context_get_type (BusContext *context); const char* bus_context_get_type (BusContext *context);
const char* bus_context_get_address (BusContext *context);
BusRegistry* bus_context_get_registry (BusContext *context); BusRegistry* bus_context_get_registry (BusContext *context);
BusConnections* bus_context_get_connections (BusContext *context); BusConnections* bus_context_get_connections (BusContext *context);
BusActivation* bus_context_get_activation (BusContext *context); BusActivation* bus_context_get_activation (BusContext *context);

View file

@ -26,11 +26,29 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <signal.h>
#include <errno.h>
static BusContext *context;
static dbus_bool_t got_sighup = FALSE;
static void
signal_handler (int sig)
{
switch (sig)
{
case SIGHUP:
got_sighup = TRUE;
case SIGTERM:
bus_loop_quit (bus_context_get_loop (context));
break;
}
}
static void static void
usage (void) usage (void)
{ {
fprintf (stderr, "dbus-daemon-1 [--session] [--system] [--config-file=FILE] [--version]\n"); fprintf (stderr, "dbus-daemon-1 [--version] [--session] [--system] [--config-file=FILE] [--print-address[=descriptor]]\n");
exit (1); exit (1);
} }
@ -57,18 +75,37 @@ check_two_config_files (const DBusString *config_file,
} }
} }
static void
check_two_addr_descriptors (const DBusString *addr_fd,
const char *extra_arg)
{
if (_dbus_string_get_length (addr_fd) > 0)
{
fprintf (stderr, "--%s specified but printing address to %s already requested\n",
extra_arg, _dbus_string_get_const_data (addr_fd));
exit (1);
}
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
BusContext *context;
DBusError error; DBusError error;
DBusString config_file; DBusString config_file;
DBusString addr_fd;
const char *prev_arg; const char *prev_arg;
int print_addr_fd;
int i; int i;
dbus_bool_t print_address;
if (!_dbus_string_init (&config_file)) if (!_dbus_string_init (&config_file))
return 1; return 1;
if (!_dbus_string_init (&addr_fd))
return 1;
print_address = FALSE;
prev_arg = NULL; prev_arg = NULL;
i = 1; i = 1;
while (i < argc) while (i < argc)
@ -117,6 +154,32 @@ main (int argc, char **argv)
} }
else if (strcmp (arg, "--config-file") == 0) else if (strcmp (arg, "--config-file") == 0)
; /* wait for next arg */ ; /* wait for next arg */
else if (strstr (arg, "--print-address=") == arg)
{
const char *desc;
check_two_addr_descriptors (&addr_fd, "print-address");
desc = strchr (arg, '=');
++desc;
if (!_dbus_string_append (&addr_fd, desc))
exit (1);
print_address = TRUE;
}
else if (prev_arg &&
strcmp (prev_arg, "--print-address") == 0)
{
check_two_addr_descriptors (&addr_fd, "print-address");
if (!_dbus_string_append (&addr_fd, arg))
exit (1);
print_address = TRUE;
}
else if (strcmp (arg, "--print-address") == 0)
print_address = TRUE; /* and we'll get the next arg if appropriate */
else else
usage (); usage ();
@ -131,6 +194,27 @@ main (int argc, char **argv)
usage (); usage ();
} }
print_addr_fd = -1;
if (print_address)
{
print_addr_fd = 1; /* stdout */
if (_dbus_string_get_length (&addr_fd) > 0)
{
long val;
int end;
if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) ||
end != _dbus_string_get_length (&addr_fd) ||
val < 0 || val > _DBUS_INT_MAX)
{
fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
_dbus_string_get_const_data (&addr_fd));
exit (1);
}
print_addr_fd = val;
}
}
dbus_error_init (&error); dbus_error_init (&error);
context = bus_context_new (&config_file, &error); context = bus_context_new (&config_file, &error);
_dbus_string_free (&config_file); _dbus_string_free (&config_file);
@ -139,14 +223,56 @@ main (int argc, char **argv)
_dbus_warn ("Failed to start message bus: %s\n", _dbus_warn ("Failed to start message bus: %s\n",
error.message); error.message);
dbus_error_free (&error); dbus_error_free (&error);
return 1; exit (1);
} }
/* Note that we don't know whether the print_addr_fd is
* one of the sockets we're using to listen on, or some
* other random thing. But I think the answer is "don't do
* that then"
*/
if (print_addr_fd >= 0)
{
DBusString addr;
const char *a = bus_context_get_address (context);
int bytes;
_dbus_assert (a != NULL);
if (!_dbus_string_init (&addr) ||
!_dbus_string_append (&addr, a) ||
!_dbus_string_append (&addr, "\n"))
exit (1);
bytes = _dbus_string_get_length (&addr);
if (_dbus_write (print_addr_fd, &addr, 0, bytes) != bytes)
{
_dbus_warn ("Failed to print message bus address: %s\n",
_dbus_strerror (errno));
exit (1);
}
if (print_addr_fd > 2)
_dbus_close (print_addr_fd, NULL);
_dbus_string_free (&addr);
}
/* FIXME we have to handle this properly below _dbus_set_signal_handler (SIGHUP, signal_handler); */
_dbus_set_signal_handler (SIGTERM, signal_handler);
_dbus_verbose ("We are on D-Bus...\n"); _dbus_verbose ("We are on D-Bus...\n");
bus_loop_run (bus_context_get_loop (context)); bus_loop_run (bus_context_get_loop (context));
bus_context_shutdown (context); bus_context_shutdown (context);
bus_context_unref (context); bus_context_unref (context);
/* If we exited on TERM we just exit, if we exited on
* HUP we restart the daemon.
*/
if (got_sighup)
{
/* FIXME execv (argv) basically */
}
return 0; return 0;
} }

View file

@ -8,19 +8,7 @@
<!-- Our well-known bus type, don't change this --> <!-- Our well-known bus type, don't change this -->
<type>session</type> <type>session</type>
<!-- FIXME - this is fairly complicated to fix. <listen>unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@</listen>
Propose the following:
- add "unix:tmpdir=/tmp" which means unix domain transport
creates a socket with a random secure name
- add dbus_server_get_address() that gets the actual
server address
- add command line option or env variable to the daemon
causing it to print its list of addresses to a given
file descriptor
- session manager or whatever launches the session bus
reads the address from there and sets the env variable
-->
<listen>unix:path=/tmp/foobar</listen>
<policy context="default"> <policy context="default">
<!-- Allow everything --> <!-- Allow everything -->

View file

@ -33,6 +33,8 @@ AC_ARG_ENABLE(gcov, [ --enable-gcov compile with coverage profiling instrume
AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use]) AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use])
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install]) AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
AC_ARG_WITH(session-socket-dir, [ --with-session-socket-dir=[dirname] Where to put sockets for the per-login-session message bus])
AC_ARG_WITH(test-socket-dir, [ --with-test-socket-dir=[dirname] Where to put sockets for make check])
dnl DBUS_BUILD_TESTS controls unit tests built in to .c files dnl DBUS_BUILD_TESTS controls unit tests built in to .c files
dnl and also some stuff in the test/ subdir dnl and also some stuff in the test/ subdir
@ -123,6 +125,9 @@ else
fi fi
fi fi
# compress spaces in cflags
CFLAGS=`echo "$CFLAGS" | sed -e 's/ +/ /g'`
if test x$enable_gcov = xyes; then if test x$enable_gcov = xyes; then
## so that config.h changes when you toggle gcov support ## so that config.h changes when you toggle gcov support
AC_DEFINE_UNQUOTED(DBUS_GCOV_ENABLED, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing]) AC_DEFINE_UNQUOTED(DBUS_GCOV_ENABLED, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing])
@ -160,6 +165,7 @@ AC_DEFINE_UNQUOTED(DBUS_INT64_TYPE, $dbusint64, [64-bit integer type])
## byte order ## byte order
AC_C_BIGENDIAN AC_C_BIGENDIAN
#### Various functions
AC_CHECK_LIB(socket,socket) AC_CHECK_LIB(socket,socket)
AC_CHECK_LIB(nsl,gethostbyname) AC_CHECK_LIB(nsl,gethostbyname)
@ -443,6 +449,32 @@ TEST_PATH(EXIT_BINARY, test-exit)
TEST_PATH(SEGFAULT_BINARY, test-segfault) TEST_PATH(SEGFAULT_BINARY, test-segfault)
TEST_PATH(SLEEP_FOREVER_BINARY, test-sleep-forever) TEST_PATH(SLEEP_FOREVER_BINARY, test-sleep-forever)
#### Find socket directories
if ! test -z "$TMPDIR" ; then
DEFAULT_SOCKET_DIR=$TMPDIR
elif ! test -z "$TEMP" ; then
DEFAULT_SOCKET_DIR=$TEMP
elif ! test -z "$TMP" ; then
DEFAULT_SOCKET_DIR=$TMP
else
DEFAULT_SOCKET_DIR=/tmp
fi
if ! test -z "$with_test_socket_dir" ; then
TEST_SOCKET_DIR="$with_test_socket_dir"
else
TEST_SOCKET_DIR=$DEFAULT_SOCKET_DIR
fi
AC_SUBST(TEST_SOCKET_DIR)
if ! test -z "$with_session_socket_dir" ; then
DBUS_SESSION_SOCKET_DIR="$with_session_socket_dir"
else
DBUS_SESSION_SOCKET_DIR=$DEFAULT_SOCKET_DIR
fi
AC_SUBST(DBUS_SESSION_SOCKET_DIR)
AC_OUTPUT([ AC_OUTPUT([
Doxyfile Doxyfile
bus/system.conf bus/system.conf
@ -479,8 +511,10 @@ echo "
Building Qt bindings: ${have_qt} Building Qt bindings: ${have_qt}
Building GLib bindings: ${have_glib} Building GLib bindings: ${have_glib}
Using XML parser: ${with_xml} Using XML parser: ${with_xml}
System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET}
Init scripts style: ${with_init_scripts} Init scripts style: ${with_init_scripts}
System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET}
Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR}
'make check' socket dir: ${TEST_SOCKET_DIR}
" "
if test x$enable_tests = xyes; then if test x$enable_tests = xyes; then

View file

@ -93,7 +93,7 @@ message_from_error (const char *error)
else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0) else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0)
return "Could not authenticate to server"; return "Could not authenticate to server";
else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0) else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0)
return "No server"; return "No server available at address";
else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0) else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0)
return "Connection timed out"; return "Connection timed out";
else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0) else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0)

View file

@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */ /* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-internals.h random utility stuff (internal to D-BUS implementation) /* dbus-internals.h random utility stuff (internal to D-BUS implementation)
* *
* Copyright (C) 2002 Red Hat, Inc. * Copyright (C) 2002, 2003 Red Hat, Inc.
* *
* Licensed under the Academic Free License version 1.2 * Licensed under the Academic Free License version 1.2
* *
@ -81,7 +81,7 @@ void _dbus_real_assert (dbus_bool_t condition,
const char *file, const char *file,
int line); int line);
#define _dbus_assert(condition) \ #define _dbus_assert(condition) \
_dbus_real_assert ((condition), #condition, __FILE__, __LINE__) _dbus_real_assert ((condition) != 0, #condition, __FILE__, __LINE__)
#endif /* !DBUS_DISABLE_ASSERT */ #endif /* !DBUS_DISABLE_ASSERT */
#ifdef DBUS_DISABLE_ASSERT #ifdef DBUS_DISABLE_ASSERT

View file

@ -221,12 +221,18 @@ _dbus_transport_debug_pipe_new (const char *server_name,
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
if (server_pipe_hash == NULL)
{
dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
return NULL;
}
server = _dbus_hash_table_lookup_string (server_pipe_hash, server = _dbus_hash_table_lookup_string (server_pipe_hash,
server_name); server_name);
if (server == NULL || if (server == NULL ||
((DBusServerDebugPipe*)server)->disconnected) ((DBusServerDebugPipe*)server)->disconnected)
{ {
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, NULL); dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
return NULL; return NULL;
} }

View file

@ -305,18 +305,68 @@ dbus_server_listen (const char *address,
if (strcmp (method, "unix") == 0) if (strcmp (method, "unix") == 0)
{ {
const char *path = dbus_address_entry_get_value (entries[i], "path"); const char *path = dbus_address_entry_get_value (entries[i], "path");
const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
if (path == NULL) if (path == NULL && tmpdir == NULL)
{ {
address_problem_type = "unix"; address_problem_type = "unix";
address_problem_field = "path"; address_problem_field = "path or tmpdir";
goto bad_address; goto bad_address;
} }
server = _dbus_server_new_for_domain_socket (path, error); if (path && tmpdir)
{
address_problem_other = "cannot specify both \"path\" and \"tmpdir\" at the same time";
goto bad_address;
}
if (server) if (tmpdir != NULL)
break; {
DBusString full_path;
DBusString filename;
if (!_dbus_string_init (&full_path))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto out;
}
if (!_dbus_string_init (&filename))
{
_dbus_string_free (&full_path);
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto out;
}
if (!_dbus_string_append (&filename,
"dbus-") ||
!_dbus_generate_random_ascii (&filename, 10) ||
!_dbus_string_append (&full_path, tmpdir) ||
!_dbus_concat_dir_and_file (&full_path, &filename))
{
_dbus_string_free (&full_path);
_dbus_string_free (&filename);
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto out;
}
/* FIXME - we will unconditionally unlink() the path.
* unlink() does not follow symlinks, but would like
* independent confirmation this is safe enough. See
* also _dbus_listen_unix_socket() and comments therein.
*/
server =
_dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
error);
_dbus_string_free (&full_path);
_dbus_string_free (&filename);
}
else
{
server = _dbus_server_new_for_domain_socket (path, error);
}
} }
else if (strcmp (method, "tcp") == 0) else if (strcmp (method, "tcp") == 0)
{ {
@ -361,9 +411,6 @@ dbus_server_listen (const char *address,
} }
server = _dbus_server_debug_new (name, error); server = _dbus_server_debug_new (name, error);
if (server)
break;
} }
else if (strcmp (method, "debug-pipe") == 0) else if (strcmp (method, "debug-pipe") == 0)
{ {
@ -377,9 +424,6 @@ dbus_server_listen (const char *address,
} }
server = _dbus_server_debug_pipe_new (name, error); server = _dbus_server_debug_pipe_new (name, error);
if (server)
break;
} }
#endif #endif
else else
@ -387,8 +431,13 @@ dbus_server_listen (const char *address,
address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")"; address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
goto bad_address; goto bad_address;
} }
if (server)
break;
} }
out:
dbus_address_entries_free (entries); dbus_address_entries_free (entries);
return server; return server;

View file

@ -917,8 +917,6 @@ static void
babysit (pid_t grandchild_pid, babysit (pid_t grandchild_pid,
int parent_pipe) int parent_pipe)
{ {
struct sigaction act;
sigset_t empty_mask;
int sigchld_pipe[2]; int sigchld_pipe[2];
/* I thought SIGCHLD would just wake up the poll, but /* I thought SIGCHLD would just wake up the poll, but
@ -934,11 +932,7 @@ babysit (pid_t grandchild_pid,
babysit_sigchld_pipe = sigchld_pipe[WRITE_END]; babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
sigemptyset (&empty_mask); _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
act.sa_handler = babysit_signal_handler;
act.sa_mask = empty_mask;
act.sa_flags = 0;
sigaction (SIGCHLD, &act, 0);
write_pid (parent_pipe, grandchild_pid); write_pid (parent_pipe, grandchild_pid);

View file

@ -2007,36 +2007,6 @@ _dbus_file_get_contents (DBusString *str,
} }
} }
static dbus_bool_t
append_unique_chars (DBusString *str)
{
static const char letters[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int i;
int len;
#define N_UNIQUE_CHARS 8
if (!_dbus_generate_random_bytes (str, N_UNIQUE_CHARS))
return FALSE;
len = _dbus_string_get_length (str);
i = len - N_UNIQUE_CHARS;
while (i < len)
{
_dbus_string_set_byte (str, i,
letters[_dbus_string_get_byte (str, i) %
(sizeof (letters) - 1)]);
++i;
}
_dbus_assert (_dbus_string_validate_ascii (str, len - N_UNIQUE_CHARS,
N_UNIQUE_CHARS));
return TRUE;
}
/** /**
* Writes a string out to a file. If the file exists, * Writes a string out to a file. If the file exists,
* it will be atomically overwritten by the new data. * it will be atomically overwritten by the new data.
@ -2084,7 +2054,8 @@ _dbus_string_save_to_file (const DBusString *str,
return FALSE; return FALSE;
} }
if (!append_unique_chars (&tmp_filename)) #define N_TMP_FILENAME_RANDOM_BYTES 8
if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
{ {
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE; return FALSE;
@ -2487,31 +2458,16 @@ _dbus_directory_close (DBusDirIter *iter)
dbus_free (iter); dbus_free (iter);
} }
/** static dbus_bool_t
* Generates the given number of random bytes, pseudorandom_generate_random_bytes (DBusString *str,
* using the best mechanism we can come up with.
*
* @param str the string
* @param n_bytes the number of random bytes to append to string
* @returns #TRUE on success, #FALSE if no memory or other failure
*/
dbus_bool_t
_dbus_generate_random_bytes (DBusString *str,
int n_bytes) int n_bytes)
{ {
int old_len; int old_len;
int fd;
old_len = _dbus_string_get_length (str);
fd = -1;
/* note, urandom on linux will fall back to pseudorandom */
fd = open ("/dev/urandom", O_RDONLY);
if (fd < 0)
{
unsigned long tv_usec; unsigned long tv_usec;
int i; int i;
old_len = _dbus_string_get_length (str);
/* fall back to pseudorandom */ /* fall back to pseudorandom */
_dbus_verbose ("Falling back to pseudorandom for %d bytes\n", _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
n_bytes); n_bytes);
@ -2535,11 +2491,47 @@ _dbus_generate_random_bytes (DBusString *str,
} }
return TRUE; return TRUE;
failed:
_dbus_string_set_length (str, old_len);
return FALSE;
} }
else
/**
* Generates the given number of random bytes,
* using the best mechanism we can come up with.
*
* @param str the string
* @param n_bytes the number of random bytes to append to string
* @returns #TRUE on success, #FALSE if no memory
*/
dbus_bool_t
_dbus_generate_random_bytes (DBusString *str,
int n_bytes)
{ {
int old_len;
int fd;
/* FALSE return means "no memory", if it could
* mean something else then we'd need to return
* a DBusError. So we always fall back to pseudorandom
* if the I/O fails.
*/
old_len = _dbus_string_get_length (str);
fd = -1;
/* note, urandom on linux will fall back to pseudorandom */
fd = open ("/dev/urandom", O_RDONLY);
if (fd < 0)
return pseudorandom_generate_random_bytes (str, n_bytes);
if (_dbus_read (fd, str, n_bytes) != n_bytes) if (_dbus_read (fd, str, n_bytes) != n_bytes)
goto failed; {
close (fd);
_dbus_string_set_length (str, old_len);
return pseudorandom_generate_random_bytes (str, n_bytes);
}
_dbus_verbose ("Read %d bytes from /dev/urandom\n", _dbus_verbose ("Read %d bytes from /dev/urandom\n",
n_bytes); n_bytes);
@ -2549,11 +2541,41 @@ _dbus_generate_random_bytes (DBusString *str,
return TRUE; return TRUE;
} }
failed: /**
_dbus_string_set_length (str, old_len); * Generates the given number of random bytes, where the bytes are
if (fd >= 0) * chosen from the alphanumeric ASCII subset.
close (fd); *
* @param str the string
* @param n_bytes the number of random ASCII bytes to append to string
* @returns #TRUE on success, #FALSE if no memory or other failure
*/
dbus_bool_t
_dbus_generate_random_ascii (DBusString *str,
int n_bytes)
{
static const char letters[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
int i;
int len;
if (!_dbus_generate_random_bytes (str, n_bytes))
return FALSE; return FALSE;
len = _dbus_string_get_length (str);
i = len - n_bytes;
while (i < len)
{
_dbus_string_set_byte (str, i,
letters[_dbus_string_get_byte (str, i) %
(sizeof (letters) - 1)]);
++i;
}
_dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
n_bytes));
return TRUE;
} }
/** /**
@ -3005,6 +3027,26 @@ _dbus_change_identity (unsigned long uid,
return TRUE; return TRUE;
} }
/** Installs a UNIX signal handler
*
* @param sig the signal to handle
* @param handler the handler
*/
void
_dbus_set_signal_handler (int sig,
DBusSignalHandler handler)
{
struct sigaction act;
sigset_t empty_mask;
sigemptyset (&empty_mask);
act.sa_handler = handler;
act.sa_mask = empty_mask;
act.sa_flags = 0;
sigaction (sig, &act, 0);
}
#ifdef DBUS_BUILD_TESTS #ifdef DBUS_BUILD_TESTS
#include <stdlib.h> #include <stdlib.h>
static void static void

View file

@ -180,6 +180,8 @@ void _dbus_directory_close (DBusDirIter *iter);
dbus_bool_t _dbus_generate_random_bytes (DBusString *str, dbus_bool_t _dbus_generate_random_bytes (DBusString *str,
int n_bytes); int n_bytes);
dbus_bool_t _dbus_generate_random_ascii (DBusString *str,
int n_bytes);
const char *_dbus_errno_to_string (int errnum); const char *_dbus_errno_to_string (int errnum);
const char* _dbus_error_from_errno (int error_number); const char* _dbus_error_from_errno (int error_number);
@ -220,6 +222,12 @@ dbus_bool_t _dbus_change_identity (unsigned long uid,
unsigned long gid, unsigned long gid,
DBusError *error); DBusError *error);
typedef void (* DBusSignalHandler) (int sig);
void _dbus_set_signal_handler (int sig,
DBusSignalHandler handler);
DBUS_END_DECLS; DBUS_END_DECLS;
#endif /* DBUS_SYSDEPS_H */ #endif /* DBUS_SYSDEPS_H */

View file

@ -235,6 +235,13 @@ _dbus_transport_open (const char *address,
if (strcmp (method, "unix") == 0) if (strcmp (method, "unix") == 0)
{ {
const char *path = dbus_address_entry_get_value (entries[i], "path"); const char *path = dbus_address_entry_get_value (entries[i], "path");
const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
if (tmpdir != NULL)
{
address_problem_other = "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on";
goto bad_address;
}
if (path == NULL) if (path == NULL)
{ {