2003-04-06 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Sun, 6 Apr 2003 18:03:03 +0000 (18:03 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 6 Apr 2003 18:03:03 +0000 (18:03 +0000)
* 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

14 files changed:
ChangeLog
bus/bus.c
bus/bus.h
bus/main.c
bus/session.conf.in
configure.in
dbus/dbus-errors.c
dbus/dbus-internals.h
dbus/dbus-server-debug-pipe.c
dbus/dbus-server.c
dbus/dbus-spawn.c
dbus/dbus-sysdeps.c
dbus/dbus-sysdeps.h
dbus/dbus-transport.c

index ebb4886..ef4c155 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 6c5a3f2..e426706 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -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)
 {
index 8b26cff..aa9f848 100644 (file)
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -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);
index 099219c..119520f 100644 (file)
 #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;
 }
index 2847895..d430d99 100644 (file)
@@ -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 -->
index 2748357..d37a7c4 100644 (file)
@@ -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
index 7e3aa69..0f70bcb 100644 (file)
@@ -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)
index dbfd068..f37009b 100644 (file)
@@ -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
index 905349b..151e32b 100644 (file)
@@ -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;
     }
 
index 566e917..3f877a0 100644 (file)
@@ -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;
index 2273a4e..87e1ffc 100644 (file)
@@ -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);
 
index 3588f76..7a38995 100644 (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,
  * 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
index 77d54c8..933e277 100644 (file)
@@ -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 */
index e56c8b0..d074480 100644 (file)
@@ -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;