diff options
author | Havoc Pennington <hp@redhat.com> | 2003-04-06 18:03:03 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2003-04-06 18:03:03 +0000 |
commit | e45e4382274149ca60c11f068ccca719f3598074 (patch) | |
tree | 5fda8d67759828cd7b8e2f1c9a8f4d66f63b737f | |
parent | 2618e1a973b816ab59422035046111360ab5aa74 (diff) |
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
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | bus/bus.c | 20 | ||||
-rw-r--r-- | bus/bus.h | 1 | ||||
-rw-r--r-- | bus/main.c | 134 | ||||
-rw-r--r-- | bus/session.conf.in | 14 | ||||
-rw-r--r-- | configure.in | 68 | ||||
-rw-r--r-- | dbus/dbus-errors.c | 2 | ||||
-rw-r--r-- | dbus/dbus-internals.h | 4 | ||||
-rw-r--r-- | dbus/dbus-server-debug-pipe.c | 8 | ||||
-rw-r--r-- | dbus/dbus-server.c | 73 | ||||
-rw-r--r-- | dbus/dbus-spawn.c | 12 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.c | 186 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 8 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 11 |
14 files changed, 439 insertions, 135 deletions
@@ -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> * NEWS: update @@ -107,7 +107,10 @@ server_get_context (DBusServer *server) bd = BUS_SERVER_DATA (server); if (bd == NULL) - return NULL; + { + server_data_slot_unref (); + return NULL; + } context = bd->context; @@ -314,7 +317,7 @@ bus_context_new (const DBusString *config_file, BUS_SET_OOM (error); return NULL; } - + if (!server_data_slot_ref ()) { BUS_SET_OOM (error); @@ -339,6 +342,12 @@ bus_context_new (const DBusString *config_file, 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 context->activation_timeout = 6000; /* 6 seconds */ #else @@ -542,6 +551,7 @@ bus_context_new (const DBusString *config_file, bus_config_parser_unref (parser); _dbus_string_free (&full_address); dbus_free_string_array (auth_mechanisms); + server_data_slot_unref (); return context; @@ -678,6 +688,12 @@ bus_context_get_type (BusContext *context) return context->type; } +const char* +bus_context_get_address (BusContext *context) +{ + return context->address; +} + BusRegistry* bus_context_get_registry (BusContext *context) { @@ -46,6 +46,7 @@ void bus_context_shutdown (BusContext *context) void bus_context_ref (BusContext *context); void bus_context_unref (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); BusConnections* bus_context_get_connections (BusContext *context); BusActivation* bus_context_get_activation (BusContext *context); @@ -26,11 +26,29 @@ #include <stdio.h> #include <stdlib.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 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); } @@ -57,17 +75,36 @@ 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 main (int argc, char **argv) { - BusContext *context; DBusError error; DBusString config_file; + DBusString addr_fd; const char *prev_arg; + int print_addr_fd; int i; - + dbus_bool_t print_address; + if (!_dbus_string_init (&config_file)) return 1; + + if (!_dbus_string_init (&addr_fd)) + return 1; + + print_address = FALSE; prev_arg = NULL; i = 1; @@ -117,6 +154,32 @@ main (int argc, char **argv) } else if (strcmp (arg, "--config-file") == 0) ; /* 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 usage (); @@ -130,6 +193,27 @@ main (int argc, char **argv) fprintf (stderr, "No configuration file specified.\n"); 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); context = bus_context_new (&config_file, &error); @@ -139,14 +223,56 @@ main (int argc, char **argv) _dbus_warn ("Failed to start message bus: %s\n", error.message); 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"); bus_loop_run (bus_context_get_loop (context)); bus_context_shutdown (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; } diff --git a/bus/session.conf.in b/bus/session.conf.in index 28478955..d430d990 100644 --- a/bus/session.conf.in +++ b/bus/session.conf.in @@ -8,19 +8,7 @@ <!-- Our well-known bus type, don't change this --> <type>session</type> - <!-- FIXME - this is fairly complicated to fix. - 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> + <listen>unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@</listen> <policy context="default"> <!-- Allow everything --> diff --git a/configure.in b/configure.in index 27483570..d37a7c4b 100644 --- a/configure.in +++ b/configure.in @@ -31,8 +31,10 @@ AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode] AC_ARG_ENABLE(asserts, [ --enable-asserts include assertion checks],enable_asserts=$enableval,enable_asserts=yes) AC_ARG_ENABLE(gcov, [ --enable-gcov compile with coverage profiling instrumentation (gcc only)],enable_gcov=$enableval,enable_gcov=no) -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(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(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 and also some stuff in the test/ subdir @@ -123,6 +125,9 @@ else fi fi +# compress spaces in cflags +CFLAGS=`echo "$CFLAGS" | sed -e 's/ +/ /g'` + if test x$enable_gcov = xyes; then ## 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]) @@ -160,6 +165,7 @@ AC_DEFINE_UNQUOTED(DBUS_INT64_TYPE, $dbusint64, [64-bit integer type]) ## byte order AC_C_BIGENDIAN +#### Various functions AC_CHECK_LIB(socket,socket) AC_CHECK_LIB(nsl,gethostbyname) @@ -443,6 +449,32 @@ TEST_PATH(EXIT_BINARY, test-exit) TEST_PATH(SEGFAULT_BINARY, test-segfault) 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([ Doxyfile bus/system.conf @@ -466,21 +498,23 @@ echo " D-BUS $VERSION ============== - prefix: ${prefix} - source code location: ${srcdir} - compiler: ${CC} - cflags: ${CFLAGS} - - Maintainer mode: ${USE_MAINTAINER_MODE} - gcc coverage profiling: ${enable_gcov} - Building unit tests: ${enable_tests} - Building verbose mode: ${enable_verbose_mode} - Building assertions: ${enable_asserts} - Building Qt bindings: ${have_qt} - Building GLib bindings: ${have_glib} - Using XML parser: ${with_xml} - System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET} - Init scripts style: ${with_init_scripts} + prefix: ${prefix} + source code location: ${srcdir} + compiler: ${CC} + cflags: ${CFLAGS} + + Maintainer mode: ${USE_MAINTAINER_MODE} + gcc coverage profiling: ${enable_gcov} + Building unit tests: ${enable_tests} + Building verbose mode: ${enable_verbose_mode} + Building assertions: ${enable_asserts} + Building Qt bindings: ${have_qt} + Building GLib bindings: ${have_glib} + Using XML parser: ${with_xml} + 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 diff --git a/dbus/dbus-errors.c b/dbus/dbus-errors.c index 7e3aa69b..0f70bcb1 100644 --- a/dbus/dbus-errors.c +++ b/dbus/dbus-errors.c @@ -93,7 +93,7 @@ message_from_error (const char *error) else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0) return "Could not authenticate to server"; 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) return "Connection timed out"; else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0) diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index dbfd0681..f37009b9 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* 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 * @@ -81,7 +81,7 @@ void _dbus_real_assert (dbus_bool_t condition, const char *file, int line); #define _dbus_assert(condition) \ - _dbus_real_assert ((condition), #condition, __FILE__, __LINE__) + _dbus_real_assert ((condition) != 0, #condition, __FILE__, __LINE__) #endif /* !DBUS_DISABLE_ASSERT */ #ifdef DBUS_DISABLE_ASSERT diff --git a/dbus/dbus-server-debug-pipe.c b/dbus/dbus-server-debug-pipe.c index 905349be..151e32b8 100644 --- a/dbus/dbus-server-debug-pipe.c +++ b/dbus/dbus-server-debug-pipe.c @@ -220,13 +220,19 @@ _dbus_transport_debug_pipe_new (const char *server_name, DBusString address; _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_name); if (server == NULL || ((DBusServerDebugPipe*)server)->disconnected) { - dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, NULL); + dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); return NULL; } diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 566e9178..3f877a0f 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -305,18 +305,68 @@ dbus_server_listen (const char *address, if (strcmp (method, "unix") == 0) { const char *path = dbus_address_entry_get_value (entries[i], "path"); - - if (path == NULL) + const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir"); + + if (path == NULL && tmpdir == NULL) { address_problem_type = "unix"; - address_problem_field = "path"; + address_problem_field = "path or tmpdir"; 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) - break; + if (tmpdir != NULL) + { + 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) { @@ -361,9 +411,6 @@ dbus_server_listen (const char *address, } server = _dbus_server_debug_new (name, error); - - if (server) - break; } 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); - - if (server) - break; } #endif else @@ -387,7 +431,12 @@ dbus_server_listen (const char *address, address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")"; goto bad_address; } + + if (server) + break; } + + out: dbus_address_entries_free (entries); return server; diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index 2273a4e3..87e1ffc2 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -916,9 +916,7 @@ babysit_signal_handler (int signo) static void babysit (pid_t grandchild_pid, int parent_pipe) -{ - struct sigaction act; - sigset_t empty_mask; +{ int sigchld_pipe[2]; /* I thought SIGCHLD would just wake up the poll, but @@ -933,12 +931,8 @@ babysit (pid_t grandchild_pid, } babysit_sigchld_pipe = sigchld_pipe[WRITE_END]; - - sigemptyset (&empty_mask); - act.sa_handler = babysit_signal_handler; - act.sa_mask = empty_mask; - act.sa_flags = 0; - sigaction (SIGCHLD, &act, 0); + + _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler); write_pid (parent_pipe, grandchild_pid); diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 3588f762..7a389956 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -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, * it will be atomically overwritten by the new data. @@ -2083,8 +2053,9 @@ _dbus_string_save_to_file (const DBusString *str, dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 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); return FALSE; @@ -2487,13 +2458,52 @@ _dbus_directory_close (DBusDirIter *iter) dbus_free (iter); } +static dbus_bool_t +pseudorandom_generate_random_bytes (DBusString *str, + int n_bytes) +{ + int old_len; + unsigned long tv_usec; + int i; + + old_len = _dbus_string_get_length (str); + + /* fall back to pseudorandom */ + _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", + n_bytes); + + _dbus_get_current_time (NULL, &tv_usec); + srand (tv_usec); + + i = 0; + while (i < n_bytes) + { + double r; + unsigned int b; + + r = rand (); + b = (r / (double) RAND_MAX) * 255.0; + + if (!_dbus_string_append_byte (str, b)) + goto failed; + + ++i; + } + + return TRUE; + + failed: + _dbus_string_set_length (str, old_len); + return FALSE; +} + /** * 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 or other failure + * @returns #TRUE on success, #FALSE if no memory */ dbus_bool_t _dbus_generate_random_bytes (DBusString *str, @@ -2501,6 +2511,12 @@ _dbus_generate_random_bytes (DBusString *str, { 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; @@ -2508,52 +2524,58 @@ _dbus_generate_random_bytes (DBusString *str, /* 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) { - unsigned long tv_usec; - int i; + close (fd); + _dbus_string_set_length (str, old_len); + return pseudorandom_generate_random_bytes (str, n_bytes); + } - /* fall back to pseudorandom */ - _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", - n_bytes); - - _dbus_get_current_time (NULL, &tv_usec); - srand (tv_usec); - - i = 0; - while (i < n_bytes) - { - double r; - unsigned int b; - - r = rand (); - b = (r / (double) RAND_MAX) * 255.0; - - if (!_dbus_string_append_byte (str, b)) - goto failed; - - ++i; - } + _dbus_verbose ("Read %d bytes from /dev/urandom\n", + n_bytes); + + close (fd); + + return TRUE; +} - return TRUE; - } - else +/** + * Generates the given number of random bytes, where the bytes are + * chosen from the alphanumeric ASCII subset. + * + * @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; + + len = _dbus_string_get_length (str); + i = len - n_bytes; + while (i < len) { - if (_dbus_read (fd, str, n_bytes) != n_bytes) - goto failed; - - _dbus_verbose ("Read %d bytes from /dev/urandom\n", - n_bytes); - - close (fd); + _dbus_string_set_byte (str, i, + letters[_dbus_string_get_byte (str, i) % + (sizeof (letters) - 1)]); - return TRUE; + ++i; } - failed: - _dbus_string_set_length (str, old_len); - if (fd >= 0) - close (fd); - return FALSE; + _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; } +/** 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 #include <stdlib.h> static void diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 77d54c8c..933e2775 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -180,6 +180,8 @@ void _dbus_directory_close (DBusDirIter *iter); dbus_bool_t _dbus_generate_random_bytes (DBusString *str, 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_error_from_errno (int error_number); @@ -220,6 +222,12 @@ dbus_bool_t _dbus_change_identity (unsigned long uid, unsigned long gid, DBusError *error); +typedef void (* DBusSignalHandler) (int sig); + +void _dbus_set_signal_handler (int sig, + DBusSignalHandler handler); + + DBUS_END_DECLS; #endif /* DBUS_SYSDEPS_H */ diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index e56c8b0c..d074480a 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -235,7 +235,14 @@ _dbus_transport_open (const char *address, if (strcmp (method, "unix") == 0) { 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) { address_problem_type = "unix"; @@ -243,7 +250,7 @@ _dbus_transport_open (const char *address, goto bad_address; } - transport = _dbus_transport_new_for_domain_socket (path, error); + transport = _dbus_transport_new_for_domain_socket (path, error); } else if (strcmp (method, "tcp") == 0) { @@ -309,7 +316,7 @@ _dbus_transport_open (const char *address, if (transport) break; } - + dbus_address_entries_free (entries); return transport; |