uuid patch

Havoc Pennington hp at redhat.com
Sat Sep 30 20:29:56 PDT 2006


Hi,

I reworked the uuid patch completely and just checked it in. I have not 
yet integrated it with the autolaunch patch. Attaching the patch for 
ease of reviewing.

The public API and protocol additions are:

  - add dbus_get_local_machine_id() which returns the UUID
    of the current machine

  - add org.freedesktop.DBus.Peer method GetMachineId, which
    returns the machine UUID of the remote application

  - dbus_connection_set_route_peer_messages():
    - allows the bus to ask for org.freedesktop.DBus.Peer messages
      to be passed through to the bus for routing, instead of
      being auto-handled by DBusConnection.
    - the practical effect is that Ping and GetMachineId
      can be routed over the bus using a bus name, before
      they could only be invoked on the bus daemon itself

  - add dbus-uuidgen executable - this will need to go in
    everyone's post-install scripts

The primary purpose of this is to replace the hostname in the autolaunch 
filename/selection-name, and in other per-machine-scoped selection names 
or bus names defined by applications.

A secondary purpose is that you can compare your machine id with that of 
a remote app to see if you are on the same machine, the reason I 
consider this secondary is that if you want to e.g. use shared memory, 
you could also just try using shared memory and see if it works, instead 
of first testing whether you're on the same machine. So I'm not sure the 
same machine check is that useful.

Since I'm not sure dbus_connection_peer_on_same_machine() is very 
useful, I didn't add that convenience API for now. It can be done 
manually with GetMachineId/dbus_get_local_machine_id() if someone needs 
to do it.

Havoc

-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /cvs/dbus/dbus/ChangeLog,v
retrieving revision 1.1130
diff -u -p -r1.1130 ChangeLog
--- ChangeLog	30 Sep 2006 19:38:34 -0000	1.1130
+++ ChangeLog	1 Oct 2006 03:13:58 -0000
@@ -1,3 +1,64 @@
+2006-09-30  Havoc Pennington  <hp at redhat.com>
+
+	* configure.in (LT_CURRENT, LT_AGE): increment current and age to
+	reflect addition of interfaces.
+
+	* doc/dbus-specification.xml: describe a new
+	org.freedesktop.DBus.Peer.GetMachineId method
+
+	* dbus/dbus-string.c (_dbus_string_skip_white_reverse): new function
+	(_dbus_string_skip_white, _dbus_string_skip_blank): use new
+	DBUS_IS_ASCII_BLANK, DBUS_IS_ASCII_WHITE macros and fix assertion
+	at end of skip_white
+	(_dbus_string_chop_white): new function
+
+	* bus/connection.c (bus_connections_setup_connection): call
+	dbus_connection_set_route_peer_messages.
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_peer_filter_unlocked_no_update): modify to
+	support a GetMachineId method.
+
+	Also, support a new flag to let the bus pass peer methods through
+	to apps on the bus, which can be set with
+	dbus_connection_set_route_peer_messages.
+
+	Finally, handle and return an error for anything unknown on the
+	Peer interface, which will allow us to extend the Peer interface
+	in the future without fear that we're now intercepting something
+	apps were wanting to see.
+	
+	* tools/dbus-uuidgen.c: a thin wrapper around the functions in 
+	dbus/dbus-uuidgen.c
+
+	* dbus/dbus-uuidgen.c: implement the bulk of the dbus-uuidgen
+	binary here, since most of the code is already in libdbus
+
+	* dbus/dbus-sysdeps.c (_dbus_read_local_machine_uuid): read the
+	uuid from the system config file
+
+	* dbus/dbus-internals.c (_dbus_generate_uuid, _dbus_uuid_encode) 
+	(_dbus_read_uuid_file_without_creating) 
+	(_dbus_create_uuid_file_exclusively, _dbus_read_uuid_file): new
+	uuid-related functions, partly factored out from dbus-server.c
+
+	* dbus/dbus-sysdeps.c (_dbus_error_from_errno): convert EEXIST to
+	DBUS_ERROR_FILE_EXISTS instead of EEXIST
+
+	* dbus/dbus-protocol.h (DBUS_ERROR_FILE_EXISTS): add file exists error
+
+	* tools/dbus-cleanup-sockets.1: explain what the point of this
+	thing is a bit more
+
+	* autogen.sh (run_configure): add --config-cache to default
+	configure args
+
+	* dbus/dbus-internals.h (_DBUS_ASSERT_ERROR_IS_SET): disable the
+	error set/clear assertions when DBUS_DISABLE_CHECKS is defined
+
+	* tools/dbus-launch.c (main): if xdisplay hasn't been opened,
+	don't try to save address, fixes crash in make check
+	
 2006-09-30  Thiago Macieira  <thiago at kde.org>
 
 	* configure.in: add DBUS_BINDIR as a #define to C source code.
Index: autogen.sh
===================================================================
RCS file: /cvs/dbus/dbus/autogen.sh,v
retrieving revision 1.6
diff -u -p -r1.6 autogen.sh
--- autogen.sh	31 Jan 2005 02:55:12 -0000	1.6
+++ autogen.sh	1 Oct 2006 03:13:58 -0000
@@ -83,7 +83,7 @@ for arg in $*; do
 done
 
 if $run_configure; then
-    $srcdir/configure --enable-maintainer-mode "$@"
+    $srcdir/configure --enable-maintainer-mode --config-cache "$@"
     echo 
     echo "Now type 'make' to compile $PROJECT."
 else
Index: configure.in
===================================================================
RCS file: /cvs/dbus/dbus/configure.in,v
retrieving revision 1.180
diff -u -p -r1.180 configure.in
--- configure.in	30 Sep 2006 19:38:34 -0000	1.180
+++ configure.in	1 Oct 2006 03:13:59 -0000
@@ -25,7 +25,7 @@ AM_MAINTAINER_MODE
 #
 
 ## increment if the interface has additions, changes, removals.
-LT_CURRENT=4
+LT_CURRENT=5
 
 ## increment any time the source changes; set to
 ##  0 if you increment CURRENT
@@ -34,7 +34,7 @@ LT_REVISION=0
 ## increment if any interfaces have been added; set to 0
 ## if any interfaces have been changed or removed. removal has
 ## precedence over adding, so set to 0 if both happened.
-LT_AGE=1
+LT_AGE=2
 
 AC_SUBST(LT_CURRENT)
 AC_SUBST(LT_REVISION)
Index: bus/connection.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/connection.c,v
retrieving revision 1.64
diff -u -p -r1.64 connection.c
--- bus/connection.c	11 Sep 2006 17:41:21 -0000	1.64
+++ bus/connection.c	1 Oct 2006 03:14:01 -0000
@@ -564,6 +564,8 @@ bus_connections_setup_connection (BusCon
       return FALSE;
     }
 
+  dbus_connection_set_route_peer_messages (connection, TRUE);
+  
   retval = FALSE;
 
   dbus_error_init (&error);
Index: bus/dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.75
diff -u -p -r1.75 dispatch.c
--- bus/dispatch.c	14 Jul 2006 01:17:59 -0000	1.75
+++ bus/dispatch.c	1 Oct 2006 03:14:03 -0000
@@ -2941,6 +2941,87 @@ check_existent_ping (BusContext     *con
  * but the correct thing may include OOM errors.
  */
 static dbus_bool_t
+check_existent_get_machine_id (BusContext     *context,
+                               DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  const char *machine_id;
+  
+  message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.DBus.Peer",
+                                          "GetMachineId");
+  
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
+      
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
+      return FALSE;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+    {
+      _dbus_warn ("Unexpected message return during GetMachineId\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  machine_id = NULL;
+  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
+    {
+      _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  if (machine_id == NULL || strlen (machine_id) != 32)
+    {
+      _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+  
+  /* We can't check that the machine id is correct because during make check it is
+   * just made up for each process separately
+   */
+  
+  dbus_message_unref (message);
+  message = NULL;
+      
+  return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
 check_existent_service_auto_start (BusContext     *context,
                                    DBusConnection *connection)
 {
@@ -3115,6 +3196,9 @@ check_existent_service_auto_start (BusCo
   if (!check_existent_ping (context, connection))
     goto out;
 
+  if (!check_existent_get_machine_id (context, connection))
+    goto out;
+  
   if (!check_existent_hello_from_self (context, connection))
     goto out;
 
Index: dbus/Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/dbus/Makefile.am,v
retrieving revision 1.83
diff -u -p -r1.83 Makefile.am
--- dbus/Makefile.am	16 Sep 2006 17:38:24 -0000	1.83
+++ dbus/Makefile.am	1 Oct 2006 03:14:03 -0000
@@ -1,5 +1,7 @@
 
-INCLUDES=-I$(top_builddir) -I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION
+configdir=$(sysconfdir)/dbus-1
+
+INCLUDES=-I$(top_builddir) -I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION -DDBUS_MACHINE_UUID_FILE=\""$(configdir)/machine-id"\"
 
 dbusincludedir=$(includedir)/dbus-1.0/dbus
 dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus
@@ -80,6 +82,8 @@ DBUS_LIB_SOURCES=				\
 	dbus-transport-socket.h			\
 	dbus-transport-unix.c			\
 	dbus-transport-unix.h			\
+	dbus-uuidgen.c				\
+	dbus-uuidgen.h				\
 	dbus-watch.c				\
 	dbus-watch.h
 
Index: dbus/dbus-connection.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.c,v
retrieving revision 1.134
diff -u -p -r1.134 dbus-connection.c
--- dbus/dbus-connection.c	30 Sep 2006 19:38:34 -0000	1.134
+++ dbus/dbus-connection.c	1 Oct 2006 03:14:07 -0000
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-connection.c DBusConnection object
  *
- * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
+ * Copyright (C) 2002-2006  Red Hat Inc.
  *
  * Licensed under the Academic Free License version 2.1
  * 
@@ -246,6 +246,8 @@ struct DBusConnection
   unsigned int io_path_acquired : 1;  /**< Someone has transport io path (can use the transport to read/write messages) */
   
   unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */
+
+  unsigned int route_peer_messages : 1; /**< If #TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don't handle them automatically */
   
 #ifndef DBUS_DISABLE_CHECKS
   unsigned int have_connection_lock : 1; /**< Used to check locking */
@@ -1175,6 +1177,8 @@ _dbus_connection_new_for_transport (DBus
   connection->objects = objects;
   connection->exit_on_disconnect = FALSE;
   connection->shareable = FALSE;
+  connection->route_peer_messages = FALSE;
+  
 #ifndef DBUS_DISABLE_CHECKS
   connection->generation = _dbus_current_generation;
 #endif
@@ -3575,15 +3579,20 @@ dbus_connection_get_dispatch_status (DBu
 }
 
 /**
-* Filter funtion for handling the Peer standard interface
-**/
+ * Filter funtion for handling the Peer standard interface.
+ */
 static DBusHandlerResult
 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
                                                  DBusMessage    *message)
 {
-  if (dbus_message_is_method_call (message,
-                                   DBUS_INTERFACE_PEER,
-                                   "Ping"))
+  if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
+    {
+      /* This means we're letting the bus route this message */
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+  else if (dbus_message_is_method_call (message,
+                                        DBUS_INTERFACE_PEER,
+                                        "Ping"))
     {
       DBusMessage *ret;
       dbus_bool_t sent;
@@ -3601,9 +3610,68 @@ _dbus_connection_peer_filter_unlocked_no
       
       return DBUS_HANDLER_RESULT_HANDLED;
     }
-                                   
-  
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  else if (dbus_message_is_method_call (message,
+                                        DBUS_INTERFACE_PEER,
+                                        "GetMachineId"))
+    {
+      DBusMessage *ret;
+      dbus_bool_t sent;
+      DBusString uuid;
+      
+      ret = dbus_message_new_method_return (message);
+      if (ret == NULL)
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+      sent = FALSE;
+      _dbus_string_init (&uuid);
+      if (_dbus_get_local_machine_uuid_encoded (&uuid))
+        {
+          const char *v_STRING = _dbus_string_get_const_data (&uuid);
+          if (dbus_message_append_args (ret,
+                                        DBUS_TYPE_STRING, &v_STRING,
+                                        DBUS_TYPE_INVALID))
+            {
+              sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+            }
+        }
+      _dbus_string_free (&uuid);
+      
+      dbus_message_unref (ret);
+
+      if (!sent)
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+      
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+    {
+      /* We need to bounce anything else with this interface, otherwise apps
+       * could start extending the interface and when we added extensions
+       * here to DBusConnection we'd break those apps.
+       */
+      
+      DBusMessage *ret;
+      dbus_bool_t sent;
+      
+      ret = dbus_message_new_error (message,
+                                    DBUS_ERROR_UNKNOWN_METHOD,
+                                    "Unknown method invoked on org.freedesktop.DBus.Peer interface");
+      if (ret == NULL)
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+      
+      sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+      
+      dbus_message_unref (ret);
+      
+      if (!sent)
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+      
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else
+    {
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
 }
 
 /**
@@ -4409,6 +4477,35 @@ dbus_connection_set_unix_user_function (
 }
 
 /**
+ *
+ * Normally #DBusConnection automatically handles all messages to the
+ * org.freedesktop.DBus.Peer interface. However, the message bus wants
+ * to be able to route methods on that interface through the bus and
+ * to other applications. If routing peer messages is enabled, then
+ * messages with the org.freedesktop.DBus.Peer interface that also
+ * have a bus destination name set will not be automatically
+ * handled by the #DBusConnection and instead will be dispatched
+ * normally to the application.
+ *
+ *
+ * If a normal application sets this flag, it can break things badly.
+ * So don't set this unless you are the message bus.
+ *
+ * @param connection the connection
+ * @param value #TRUE to pass through org.freedesktop.DBus.Peer messages with a bus name set
+ */
+void
+dbus_connection_set_route_peer_messages (DBusConnection             *connection,
+                                         dbus_bool_t                 value)
+{
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  connection->route_peer_messages = TRUE;
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
  * Adds a message filter. Filters are handlers that are run on all
  * incoming messages, prior to the objects registered with
  * dbus_connection_register_object_path().  Filters are run in the
@@ -4968,4 +5065,58 @@ dbus_connection_get_outgoing_size (DBusC
   return res;
 }
 
+/**
+ * Obtains the machine UUID of the machine this process is running on.
+ *
+ * The returned string must be freed with dbus_free().
+ * 
+ * This UUID is guaranteed to remain the same until the next reboot
+ * (unless the sysadmin foolishly changes it and screws themselves).
+ * It will usually remain the same across reboots also, but hardware
+ * configuration changes or rebuilding the machine could break that.
+ *
+ * The idea is that two processes with the same machine ID should be
+ * able to use shared memory, UNIX domain sockets, process IDs, and other
+ * features of the OS that require both processes to be running
+ * on the same OS kernel instance.
+ *
+ * The machine ID can also be used to create unique per-machine
+ * instances. For example, you could use it in bus names or
+ * X selection names.
+ *
+ * The machine ID is preferred over the machine hostname, because
+ * the hostname is frequently set to "localhost.localdomain" and
+ * may also change at runtime.
+ *
+ * You can get the machine ID of a remote application by invoking the
+ * method GetMachineId from interface org.freedesktop.DBus.Peer.
+ *
+ * If the remote application has the same machine ID as the one
+ * returned by this function, then the remote application is on the
+ * same machine as your application.
+ * 
+ * @returns a 32-byte-long hex-encoded UUID string, or #NULL if insufficient memory
+ */
+char*
+dbus_get_local_machine_id (void)
+{
+  DBusString uuid;
+  char *s;
+
+  s = NULL;
+  _dbus_string_init (&uuid);
+  if (!_dbus_get_local_machine_uuid_encoded (&uuid) ||
+      !_dbus_string_steal_data (&uuid, &s))
+    {
+      _dbus_string_free (&uuid);
+      return FALSE;
+    }
+  else
+    {
+      _dbus_string_free (&uuid);
+      return s;
+    }
+
+}
+
 /** @} */
Index: dbus/dbus-connection.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.h,v
retrieving revision 1.43
diff -u -p -r1.43 dbus-connection.h
--- dbus/dbus-connection.h	16 Sep 2006 18:46:48 -0000	1.43
+++ dbus/dbus-connection.h	1 Oct 2006 03:14:08 -0000
@@ -151,6 +151,8 @@ void               dbus_connection_set_u
                                                                  DBusAllowUnixUserFunction   function,
                                                                  void                       *data,
                                                                  DBusFreeFunction            free_data_function);
+void               dbus_connection_set_route_peer_messages      (DBusConnection             *connection,
+                                                                 dbus_bool_t                 value);
 
 
 int          dbus_watch_get_fd      (DBusWatch        *watch);
@@ -258,6 +260,8 @@ dbus_bool_t dbus_connection_get_unix_fd 
 dbus_bool_t dbus_connection_get_socket             (DBusConnection              *connection,
                                                     int                         *fd);
 
+char*       dbus_get_local_machine_id              (void);
+
 DBUS_END_DECLS
 
 #endif /* DBUS_CONNECTION_H */
Index: dbus/dbus-internals.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-internals.c,v
retrieving revision 1.48
diff -u -p -r1.48 dbus-internals.c
--- dbus/dbus-internals.c	16 Sep 2006 17:38:24 -0000	1.48
+++ dbus/dbus-internals.c	1 Oct 2006 03:14:08 -0000
@@ -413,6 +413,258 @@ _dbus_string_array_contains (const char 
   return FALSE;
 }
 
+/**
+ * Generates a new UUID. If you change how this is done,
+ * there's some text about it in the spec that should also change.
+ *
+ * @param uuid the uuid to initialize
+ */
+void
+_dbus_generate_uuid (DBusGUID *uuid)
+{
+  long now;
+  char *p;
+  int ts_size;
+
+  _dbus_get_current_time (&now, NULL);
+
+  uuid->as_uint32s[0] = now;
+
+  ts_size = sizeof (uuid->as_uint32s[0]);
+  p = ((char*)uuid->as_bytes) + ts_size;
+  
+  _dbus_generate_random_bytes_buffer (p,
+                                      sizeof (uuid->as_bytes) - ts_size);
+}
+
+/**
+ * Hex-encode a UUID.
+ *
+ * @param uuid the uuid
+ * @param encoded string to append hex uuid to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_uuid_encode (const DBusGUID *uuid,
+                   DBusString     *encoded)
+{
+  DBusString binary;
+  _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
+  return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
+}
+
+static dbus_bool_t
+_dbus_read_uuid_file_without_creating (const DBusString *filename,
+                                       DBusGUID         *uuid,
+                                       DBusError        *error)
+{
+  DBusString contents;
+  DBusString decoded;
+  int end;
+  
+  _dbus_string_init (&contents);
+  _dbus_string_init (&decoded);
+  
+  if (!_dbus_file_get_contents (&contents, filename, error))
+    goto error;
+
+  _dbus_string_chop_white (&contents);
+
+  if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+                      "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
+                      _dbus_string_get_const_data (filename),
+                      DBUS_UUID_LENGTH_HEX,
+                      _dbus_string_get_length (&contents));
+      goto error;
+    }
+
+  if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+
+  if (end == 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+                      "UUID file '%s' contains invalid hex data",
+                      _dbus_string_get_const_data (filename));
+      goto error;
+    }
+
+  if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+                      "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
+                      _dbus_string_get_const_data (filename),
+                      _dbus_string_get_length (&decoded),
+                      DBUS_UUID_LENGTH_BYTES);
+      goto error;
+    }
+
+  _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
+
+  _dbus_string_free (&decoded);
+  _dbus_string_free (&contents);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  return TRUE;
+  
+ error:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  _dbus_string_free (&contents);
+  _dbus_string_free (&decoded);
+  return FALSE;
+}
+
+static dbus_bool_t
+_dbus_create_uuid_file_exclusively (const DBusString *filename,
+                                    DBusGUID         *uuid,
+                                    DBusError        *error)
+{
+  DBusString encoded;
+
+  _dbus_string_init (&encoded);
+
+  _dbus_generate_uuid (uuid);
+  
+  if (!_dbus_uuid_encode (uuid, &encoded))
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+  
+  /* FIXME this is racy; we need a save_file_exclusively
+   * function. But in practice this should be fine for now.
+   *
+   * - first be sure we can create the file and it
+   *   doesn't exist by creating it empty with O_EXCL
+   * - then create it by creating a temporary file and
+   *   overwriting atomically with rename()
+   */
+  if (!_dbus_create_file_exclusively (filename, error))
+    goto error;
+
+  if (!_dbus_string_append_byte (&encoded, '\n'))
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+  
+  if (!_dbus_string_save_to_file (&encoded, filename, error))
+    goto error;
+
+
+  _dbus_string_free (&encoded);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return TRUE;
+  
+ error:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  _dbus_string_free (&encoded);
+  return FALSE;        
+}
+
+/**
+ * Reads (and optionally writes) a uuid to a file. Initializes the uuid
+ * unless an error is returned.
+ *
+ * @param filename the name of the file
+ * @param uuid uuid to be initialized with the loaded uuid
+ * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist
+ * @param error the error return
+ * @returns #FALSE if the error is set
+ */
+dbus_bool_t
+_dbus_read_uuid_file (const DBusString *filename,
+                      DBusGUID         *uuid,
+                      dbus_bool_t       create_if_not_found,
+                      DBusError        *error)
+{
+  DBusError read_error;
+
+  dbus_error_init (&read_error);
+
+  if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
+    return TRUE;
+
+  if (!create_if_not_found)
+    {
+      dbus_move_error (&read_error, error);
+      return FALSE;
+    }
+
+  /* If the file exists and contains junk, we want to keep that error
+   * message instead of overwriting it with a "file exists" error
+   * message when we try to write
+   */
+  if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
+    {
+      dbus_move_error (&read_error, error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_error_free (&read_error);
+      return _dbus_create_uuid_file_exclusively (filename, uuid, error);
+    }
+}
+
+_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
+static int machine_uuid_initialized_generation = 0;
+static DBusGUID machine_uuid;
+
+/**
+ * Gets the hex-encoded UUID of the machine this function is
+ * executed on. This UUID is guaranteed to be the same for a given
+ * machine at least until it next reboots, though it also
+ * makes some effort to be the same forever, it may change if the
+ * machine is reconfigured or its hardware is modified.
+ * 
+ * @param uuid_str string to append hex-encoded machine uuid to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
+{
+  dbus_bool_t ok;
+  
+  _DBUS_LOCK (machine_uuid);
+  if (machine_uuid_initialized_generation != _dbus_current_generation)
+    {
+      DBusError error;
+      dbus_error_init (&error);
+      if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
+                                          &error))
+        {          
+#ifndef DBUS_BUILD_TESTS
+          /* For the test suite, we may not be installed so just continue silently
+           * here. But in a production build, we want to be nice and loud about
+           * this.
+           */
+          _dbus_warn ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n",
+                      error.message);
+          _dbus_warn ("See the manual page for dbus-uuidgen to correct this issue.\n");
+          _dbus_warn ("Continuing with a bogus made-up machine UUID, which may cause problems.");
+#endif
+          
+          dbus_error_free (&error);
+          
+          _dbus_generate_uuid (&machine_uuid);
+        }
+    }
+
+  ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
+
+  _DBUS_UNLOCK (machine_uuid);
+
+  return ok;
+}
+
 #ifdef DBUS_BUILD_TESTS
 /**
  * Returns a string describing the given name.
Index: dbus/dbus-internals.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-internals.h,v
retrieving revision 1.60
diff -u -p -r1.60 dbus-internals.h
--- dbus/dbus-internals.h	30 Sep 2006 19:38:34 -0000	1.60
+++ dbus/dbus-internals.h	1 Oct 2006 03:14:09 -0000
@@ -157,8 +157,16 @@ extern const char _dbus_return_if_fail_w
 #define _DBUS_STRUCT_OFFSET(struct_type, member)	\
     ((long) ((unsigned char*) &((struct_type*) 0)->member))
 
+#ifdef DBUS_DISABLE_CHECKS
+/* this is an assert and not an error, but in the typical --disable-checks case (you're trying
+ * to really minimize code size), disabling these assertions makes sense.
+ */
+#define _DBUS_ASSERT_ERROR_IS_SET(error)
+#define _DBUS_ASSERT_ERROR_IS_CLEAR(error)
+#else
 #define _DBUS_ASSERT_ERROR_IS_SET(error)   _dbus_assert ((error) == NULL || dbus_error_is_set ((error)))
 #define _DBUS_ASSERT_ERROR_IS_CLEAR(error) _dbus_assert ((error) == NULL || !dbus_error_is_set ((error)))
+#endif
 
 #define _dbus_return_if_error_is_set(error) _dbus_return_if_fail ((error) == NULL || !dbus_error_is_set ((error)))
 #define _dbus_return_val_if_error_is_set(error, val) _dbus_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), (val))
@@ -288,7 +296,8 @@ _DBUS_DECLARE_GLOBAL_LOCK (message_cache
 _DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
 _DBUS_DECLARE_GLOBAL_LOCK (win_fds);
 _DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
-#define _DBUS_N_GLOBAL_LOCKS (13)
+_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+#define _DBUS_N_GLOBAL_LOCKS (14)
 
 dbus_bool_t _dbus_threads_init_debug (void);
 
@@ -300,6 +309,28 @@ void          _dbus_set_bad_address     
                                             const char        *address_problem_field,
                                             const char        *address_problem_other);
 
+#define DBUS_UUID_LENGTH_BYTES 16
+#define DBUS_UUID_LENGTH_HEX (DBUS_UUID_LENGTH_BYTES * 2)
+
+/**
+ * A globally unique ID ; we have one for each DBusServer, and also one for each
+ * machine with libdbus installed on it.
+ */
+union DBusGUID
+{
+  dbus_uint32_t as_uint32s[DBUS_UUID_LENGTH_BYTES / 4];
+  char as_bytes[DBUS_UUID_LENGTH_BYTES];
+};
+
+void        _dbus_generate_uuid  (DBusGUID         *uuid);
+dbus_bool_t _dbus_uuid_encode    (const DBusGUID   *uuid,
+                                  DBusString       *encoded);
+dbus_bool_t _dbus_read_uuid_file (const DBusString *filename,
+                                  DBusGUID         *uuid,
+                                  dbus_bool_t       create_if_not_found,
+                                  DBusError        *error);
+
+dbus_bool_t _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str);
 
 DBUS_END_DECLS
 
Index: dbus/dbus-protocol.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-protocol.h,v
retrieving revision 1.46
diff -u -p -r1.46 dbus-protocol.h
--- dbus/dbus-protocol.h	19 Dec 2005 23:58:22 -0000	1.46
+++ dbus/dbus-protocol.h	1 Oct 2006 03:14:09 -0000
@@ -242,6 +242,7 @@ extern "C" {
 #define DBUS_ERROR_DISCONNECTED               "org.freedesktop.DBus.Error.Disconnected"
 #define DBUS_ERROR_INVALID_ARGS               "org.freedesktop.DBus.Error.InvalidArgs"
 #define DBUS_ERROR_FILE_NOT_FOUND             "org.freedesktop.DBus.Error.FileNotFound"
+#define DBUS_ERROR_FILE_EXISTS                "org.freedesktop.DBus.Error.FileExists"
 #define DBUS_ERROR_UNKNOWN_METHOD             "org.freedesktop.DBus.Error.UnknownMethod"
 #define DBUS_ERROR_TIMED_OUT                  "org.freedesktop.DBus.Error.TimedOut"
 #define DBUS_ERROR_MATCH_RULE_NOT_FOUND       "org.freedesktop.DBus.Error.MatchRuleNotFound"
@@ -253,6 +254,7 @@ extern "C" {
 #define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
 #define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN    "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
 #define DBUS_ERROR_INVALID_SIGNATURE          "org.freedesktop.DBus.Error.InvalidSignature"
+#define DBUS_ERROR_INVALID_FILE_CONTENT       "org.freedesktop.DBus.Error.InvalidFileContent"
 #define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN    "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"
 
 #define DBUS_INTROSPECT_1_0_XML_NAMESPACE         "http://www.freedesktop.org/standards/dbus"
Index: dbus/dbus-server-protected.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-server-protected.h,v
retrieving revision 1.22
diff -u -p -r1.22 dbus-server-protected.h
--- dbus/dbus-server-protected.h	16 Sep 2006 19:24:08 -0000	1.22
+++ dbus/dbus-server-protected.h	1 Oct 2006 03:14:09 -0000
@@ -37,16 +37,6 @@
 DBUS_BEGIN_DECLS
 
 typedef struct DBusServerVTable DBusServerVTable;
-typedef union DBusGUID DBusGUID;
-
-/**
- * A server's globally unique ID
- */
-union DBusGUID
-{
-  dbus_uint32_t as_uint32s[4];
-  unsigned char as_bytes[16];
-};
 
 /**
  * Virtual table to be implemented by all server "subclasses"
Index: dbus/dbus-server.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-server.c,v
retrieving revision 1.48
diff -u -p -r1.48 dbus-server.c
--- dbus/dbus-server.c	16 Sep 2006 19:24:08 -0000	1.48
+++ dbus/dbus-server.c	1 Oct 2006 03:14:10 -0000
@@ -53,24 +53,6 @@
  * @{
  */
 
-static void
-init_guid (DBusGUID *guid)
-{
-  long now;
-  char *p;
-  int ts_size;
-
-  _dbus_get_current_time (&now, NULL);
-
-  guid->as_uint32s[0] = now;
-
-  ts_size = sizeof (guid->as_uint32s[0]);
-  p = ((char*)guid->as_bytes) + ts_size;
-  
-  _dbus_generate_random_bytes_buffer (p,
-                                      sizeof (guid->as_bytes) - ts_size);
-}
-
 /* this is a little fragile since it assumes the address doesn't
  * already have a guid, but it shouldn't
  */
@@ -116,8 +98,6 @@ _dbus_server_init_base (DBusServer      
                         const DBusServerVTable *vtable,
                         const DBusString       *address)
 {
-  DBusString guid_raw;
-  
   server->vtable = vtable;
   server->refcount.value = 1;
 
@@ -128,13 +108,9 @@ _dbus_server_init_base (DBusServer      
   if (!_dbus_string_init (&server->guid_hex))
     return FALSE;
 
-  init_guid (&server->guid);
+  _dbus_generate_uuid (&server->guid);
 
-  _dbus_string_init_const_len (&guid_raw, (signed char*) server->guid.as_bytes,
-                               sizeof (server->guid.as_bytes));
-  if (!_dbus_string_hex_encode (&guid_raw, 0,
-                                &server->guid_hex,
-                                _dbus_string_get_length (&server->guid_hex)))
+  if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
     goto failed;
   
   server->address = copy_address_with_guid_appended (address,
Index: dbus/dbus-string-private.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string-private.h,v
retrieving revision 1.7
diff -u -p -r1.7 dbus-string-private.h
--- dbus/dbus-string-private.h	3 Aug 2006 20:34:36 -0000	1.7
+++ dbus/dbus-string-private.h	1 Oct 2006 03:14:10 -0000
@@ -107,6 +107,18 @@ typedef struct
 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
   DBUS_GENERIC_STRING_PREAMBLE (real)
 
+/**
+ * Checks for ASCII blank byte
+ * @param c the byte
+ */
+#define DBUS_IS_ASCII_BLANK(c) ((c) == ' ' || (c) == '\t')
+
+/**
+ * Checks for ASCII whitespace byte
+ * @param c the byte
+ */
+#define DBUS_IS_ASCII_WHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
+
 /** @} */
 
 DBUS_END_DECLS
Index: dbus/dbus-string-util.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string-util.c,v
retrieving revision 1.3
diff -u -p -r1.3 dbus-string-util.c
--- dbus/dbus-string-util.c	25 Feb 2005 22:03:30 -0000	1.3
+++ dbus/dbus-string-util.c	1 Oct 2006 03:14:11 -0000
@@ -111,43 +111,6 @@ _dbus_string_find_byte_backward (const D
   return i >= 0;
 }
 
-/**
- * Skips whitespace from start, storing the first non-whitespace in *end.
- * (whitespace is space, tab, newline, CR).
- *
- * @param str the string
- * @param start where to start
- * @param end where to store the first non-whitespace byte index
- */
-void
-_dbus_string_skip_white (const DBusString *str,
-                         int               start,
-                         int              *end)
-{
-  int i;
-  DBUS_CONST_STRING_PREAMBLE (str);
-  _dbus_assert (start <= real->len);
-  _dbus_assert (start >= 0);
-  
-  i = start;
-  while (i < real->len)
-    {
-      if (!(real->str[i] == ' ' ||
-            real->str[i] == '\n' ||
-            real->str[i] == '\r' ||
-            real->str[i] == '\t'))
-        break;
-      
-      ++i;
-    }
-
-  _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
-                                    real->str[i] == '\t'));
-  
-  if (end)
-    *end = i;
-}
-
 /** @} */
 
 #ifdef DBUS_BUILD_TESTS
Index: dbus/dbus-string.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.c,v
retrieving revision 1.72
diff -u -p -r1.72 dbus-string.c
--- dbus/dbus-string.c	8 Aug 2006 22:08:39 -0000	1.72
+++ dbus/dbus-string.c	1 Oct 2006 03:14:12 -0000
@@ -1924,21 +1924,85 @@ _dbus_string_skip_blank (const DBusStrin
   i = start;
   while (i < real->len)
     {
-      if (!(real->str[i] == ' ' ||
-            real->str[i] == '\t'))
+      if (!DBUS_IS_ASCII_BLANK (real->str[i]))
         break;
       
       ++i;
     }
 
-  _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
-                                    real->str[i] == '\t'));
+  _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
+  
+  if (end)
+    *end = i;
+}
+
+
+/**
+ * Skips whitespace from start, storing the first non-whitespace in *end.
+ * (whitespace is space, tab, newline, CR).
+ *
+ * @param str the string
+ * @param start where to start
+ * @param end where to store the first non-whitespace byte index
+ */
+void
+_dbus_string_skip_white (const DBusString *str,
+                         int               start,
+                         int              *end)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  
+  i = start;
+  while (i < real->len)
+    {
+      if (!DBUS_IS_ASCII_WHITE (real->str[i]))
+        break;
+      
+      ++i;
+    }
+
+  _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
   
   if (end)
     *end = i;
 }
 
 /**
+ * Skips whitespace from end, storing the start index of the trailing
+ * whitespace in *start. (whitespace is space, tab, newline, CR).
+ *
+ * @param str the string
+ * @param end where to start scanning backward
+ * @param start where to store the start of whitespace chars
+ */
+void
+_dbus_string_skip_white_reverse (const DBusString *str,
+                                 int               end,
+                                 int              *start)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (end <= real->len);
+  _dbus_assert (end >= 0);
+  
+  i = end;
+  while (i > 0)
+    {
+      if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
+        break;
+      --i;
+    }
+
+  _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
+  
+  if (start)
+    *start = i;
+}
+
+/**
  * Assigns a newline-terminated or \\r\\n-terminated line from the front
  * of the string to the given dest string. The dest string's previous
  * contents are deleted. If the source string contains no newline,
@@ -2043,6 +2107,26 @@ _dbus_string_delete_leading_blanks (DBus
 #endif
 
 /**
+ * Deletes leading and trailing whitespace
+ * 
+ * @param str the string
+ */
+void
+_dbus_string_chop_white(DBusString *str)
+{
+  int i;
+  
+  _dbus_string_skip_white (str, 0, &i);
+
+  if (i > 0)
+    _dbus_string_delete (str, 0, i);
+  
+  _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
+
+  _dbus_string_set_length (str, i);
+}
+
+/**
  * Tests two DBusString for equality.
  *
  * @todo memcmp is probably faster
Index: dbus/dbus-string.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.h,v
retrieving revision 1.40
diff -u -p -r1.40 dbus-string.h
--- dbus/dbus-string.h	3 Aug 2006 20:34:36 -0000	1.40
+++ dbus/dbus-string.h	1 Oct 2006 03:14:12 -0000
@@ -233,6 +233,9 @@ void          _dbus_string_skip_blank   
 void          _dbus_string_skip_white            (const DBusString  *str,
                                                   int                start,
                                                   int               *end);
+void          _dbus_string_skip_white_reverse    (const DBusString  *str,
+                                                  int                end,
+                                                  int               *start);
 dbus_bool_t   _dbus_string_equal                 (const DBusString  *a,
                                                   const DBusString  *b);
 dbus_bool_t   _dbus_string_equal_c_str           (const DBusString  *a,
@@ -253,6 +256,7 @@ dbus_bool_t   _dbus_string_pop_line     
                                                   DBusString        *dest);
 void          _dbus_string_delete_first_word     (DBusString        *str);
 void          _dbus_string_delete_leading_blanks (DBusString        *str);
+void          _dbus_string_chop_white            (DBusString        *str); 
 dbus_bool_t   _dbus_string_append_byte_as_hex    (DBusString        *str,
                                                   int                byte);
 dbus_bool_t   _dbus_string_hex_encode            (const DBusString  *source,
Index: dbus/dbus-sysdeps-unix.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps-unix.c,v
retrieving revision 1.6
diff -u -p -r1.6 dbus-sysdeps-unix.c
--- dbus/dbus-sysdeps-unix.c	30 Sep 2006 19:38:34 -0000	1.6
+++ dbus/dbus-sysdeps-unix.c	1 Oct 2006 03:14:14 -0000
@@ -2297,10 +2297,12 @@ _dbus_get_autolaunch_address (DBusString
   pid_t pid;
   int ret;
   int status;
-  int orig_len = _dbus_string_get_length (address);
+  int orig_len;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
+  orig_len = _dbus_string_get_length (address);
+  
 #define READ_END        0
 #define WRITE_END       1
   if (pipe (address_pipe) < 0)
@@ -2388,6 +2390,34 @@ _dbus_get_autolaunch_address (DBusString
   return TRUE;
 }
 
+/**
+ * Reads the uuid of the machine we're running on from
+ * the dbus configuration. Optionally try to create it
+ * (only root can do this usually).
+ *
+ * On UNIX, reads a file that gets created by dbus-uuidgen
+ * in a post-install script. On Windows, if there's a standard
+ * machine uuid we could just use that, but I can't find one
+ * with the right properties (the hardware profile guid can change
+ * without rebooting I believe). If there's no standard one
+ * we might want to use the registry instead of a file for
+ * this, and I'm not sure how we'd ensure the uuid gets created.
+ *
+ * @param guid to init with the machine's uuid
+ * @param create_if_not_found try to create the uuid if it doesn't exist
+ * @param error the error return
+ * @returns #FALSE if the error is set
+ */
+dbus_bool_t
+_dbus_read_local_machine_uuid (DBusGUID   *machine_id,
+                               dbus_bool_t create_if_not_found,
+                               DBusError  *error)
+{
+  DBusString filename;
+  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
+  return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
+}
+
 /** @} end of sysdeps */
 
 /* tests in dbus-sysdeps-util.c */
Index: dbus/dbus-sysdeps.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.c,v
retrieving revision 1.113
diff -u -p -r1.113 dbus-sysdeps.c
--- dbus/dbus-sysdeps.c	11 Sep 2006 17:41:21 -0000	1.113
+++ dbus/dbus-sysdeps.c	1 Oct 2006 03:14:14 -0000
@@ -919,7 +919,7 @@ _dbus_error_from_errno (int error_number
 #endif
 #ifdef EEXIST
     case EEXIST:
-      return DBUS_ERROR_FILE_NOT_FOUND;
+      return DBUS_ERROR_FILE_EXISTS;
 #endif
 #ifdef ENOENT
     case ENOENT:
Index: dbus/dbus-sysdeps.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.h,v
retrieving revision 1.60
diff -u -p -r1.60 dbus-sysdeps.h
--- dbus/dbus-sysdeps.h	30 Sep 2006 19:38:34 -0000	1.60
+++ dbus/dbus-sysdeps.h	1 Oct 2006 03:14:15 -0000
@@ -379,6 +379,13 @@ dbus_bool_t _dbus_parse_uid (const DBusS
 dbus_bool_t _dbus_get_autolaunch_address (DBusString *address, 
 					  DBusError *error);
 
+typedef union DBusGUID DBusGUID;
+
+dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
+                                             dbus_bool_t       create_if_not_found,
+                                             DBusError        *error);
+
+
 DBUS_END_DECLS
 
 #endif /* DBUS_SYSDEPS_H */
Index: dbus/dbus-threads.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-threads.c,v
retrieving revision 1.29
diff -u -p -r1.29 dbus-threads.c
--- dbus/dbus-threads.c	14 Sep 2006 04:26:00 -0000	1.29
+++ dbus/dbus-threads.c	1 Oct 2006 03:14:15 -0000
@@ -450,7 +450,8 @@ init_locks (void)
     LOCK_ADDR (shutdown_funcs),
     LOCK_ADDR (system_users),
     LOCK_ADDR (message_cache),
-    LOCK_ADDR (shared_connections)
+    LOCK_ADDR (shared_connections),
+    LOCK_ADDR (machine_uuid)
 #undef LOCK_ADDR
   };
 
Index: dbus/dbus-uuidgen.c
===================================================================
RCS file: dbus/dbus-uuidgen.c
diff -N dbus/dbus-uuidgen.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbus/dbus-uuidgen.c	1 Oct 2006 03:14:15 -0000
@@ -0,0 +1,123 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-uuidgen.c  The guts of the dbus-uuidgen binary live in libdbus, in this file.
+ *
+ * Copyright (C) 2006  Red Hat, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "dbus-uuidgen.h"
+#include "dbus-internals.h"
+#include "dbus-string.h"
+#include "dbus-protocol.h"
+
+#ifdef DBUS_WIN
+#error "dbus-uuidgen should not be needed on Windows"
+#endif
+
+/**
+ * @defgroup DBusInternalsUuidgen dbus-uuidgen implementation
+ * @ingroup DBusInternals
+ * @brief Functions for dbus-uuidgen binary
+ *
+ * These are not considered part of the ABI, and if you call them
+ * you will get screwed by future changes.
+ * 
+ * @{
+ */
+
+static dbus_bool_t
+return_uuid (DBusGUID   *uuid,
+             char      **uuid_p,
+             DBusError  *error)
+{
+  if (uuid_p)
+    {
+      DBusString encoded;
+      _dbus_string_init (&encoded);
+      if (!_dbus_uuid_encode (uuid, &encoded) ||
+          !_dbus_string_steal_data (&encoded, uuid_p))
+        {
+          _DBUS_SET_OOM (error);
+          _dbus_string_free (&encoded);
+          return FALSE;
+        }
+      _dbus_string_free (&encoded);
+    }
+  return TRUE;
+}
+
+/**
+ * For use by the dbus-uuidgen binary ONLY, do not call this.
+ * We can and will change this function without modifying
+ * the libdbus soname.
+ *
+ * @param filename the file or #NULL for the machine ID file
+ * @param uuid_p out param to return the uuid
+ * @param create_if_not_found whether to create it if not already there
+ * @param error error return
+ * @param returns #FALSE if error is set
+ */
+dbus_bool_t
+dbus_internal_do_not_use_get_uuid (const char *filename,
+                                   char      **uuid_p,
+                                   dbus_bool_t create_if_not_found,
+                                   DBusError  *error)
+{
+  DBusGUID uuid;
+  
+  if (filename)
+    {
+      DBusString filename_str;
+      _dbus_string_init_const (&filename_str, filename);
+      if (!_dbus_read_uuid_file (&filename_str, &uuid, create_if_not_found, error))
+        goto error;
+    }
+  else
+    {
+      if (!_dbus_read_local_machine_uuid (&uuid, create_if_not_found, error))
+        goto error;
+    }
+
+  if (!return_uuid(&uuid, uuid_p, error))
+    goto error;
+
+  return TRUE;
+  
+ error:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  return FALSE;
+}
+
+/**
+ * For use by the dbus-uuidgen binary ONLY, do not call this.
+ * We can and will change this function without modifying
+ * the libdbus soname.
+ *
+ * @param uuid_p out param to return the uuid
+ * @param returns #FALSE if no memory
+ */
+dbus_bool_t
+dbus_internal_do_not_use_create_uuid (char      **uuid_p)
+{
+  DBusGUID uuid;
+
+  _dbus_generate_uuid (&uuid);
+  return return_uuid (&uuid, uuid_p, NULL);
+}
+
+/** @} */
Index: dbus/dbus-uuidgen.h
===================================================================
RCS file: dbus/dbus-uuidgen.h
diff -N dbus/dbus-uuidgen.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbus/dbus-uuidgen.h	1 Oct 2006 03:14:16 -0000
@@ -0,0 +1,47 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-uuidgen.h  The guts of the dbus-uuidgen binary live in libdbus, in this file.
+ *
+ * Copyright (C) 2006  Red Hat, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifdef DBUS_INSIDE_DBUS_H
+#error "You can't include dbus-uuidgen.h in the public header dbus.h"
+#endif
+
+#ifndef DBUS_UUIDGEN_H
+#define DBUS_UUIDGEN_H
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+dbus_bool_t dbus_internal_do_not_use_get_uuid    (const char *filename,
+                                                  char      **uuid_p,
+                                                  dbus_bool_t create_if_not_found,
+                                                  DBusError  *error);
+dbus_bool_t dbus_internal_do_not_use_ensure_uuid (const char *filename,
+                                                  char      **uuid_p,
+                                                  DBusError  *error);
+dbus_bool_t dbus_internal_do_not_use_create_uuid (char      **uuid_p);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_UUIDGEN_H */
Index: doc/dbus-specification.xml
===================================================================
RCS file: /cvs/dbus/dbus/doc/dbus-specification.xml,v
retrieving revision 1.42
diff -u -p -r1.42 dbus-specification.xml
--- doc/dbus-specification.xml	17 Aug 2006 21:20:13 -0000	1.42
+++ doc/dbus-specification.xml	1 Oct 2006 03:14:19 -0000
@@ -2290,9 +2290,10 @@
       <title><literal>org.freedesktop.DBus.Peer</literal></title>
       <para>
         The <literal>org.freedesktop.DBus.Peer</literal> interface 
-        has one method:
+        has two methods:
         <programlisting>
           org.freedesktop.DBus.Peer.Ping ()
+          org.freedesktop.DBus.Peer.GetMachineId (out STRING machine_uuid)
         </programlisting>
       </para>
       <para>
@@ -2300,9 +2301,33 @@
         <literal>org.freedesktop.DBus.Peer.Ping</literal>, an application should do
         nothing other than reply with a <literal>METHOD_RETURN</literal> as
         usual.  It does not matter which object path a ping is sent to.  The
-        reference implementation should simply handle this method on behalf of
-        all objects, though it doesn't yet. (The point is, you're really pinging
-        the peer process, not a specific object.)
+        reference implementation handles this method automatically.
+      </para>
+      <para>
+        On receipt of the <literal>METHOD_CALL</literal> message
+        <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should 
+        reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded 
+        UUID representing the identity of the machine the process is running on.
+        This UUID must be the same for all processes on a single system at least
+        until that system next reboots. It should be the same across reboots 
+        if possible, but may change due to reconfiguration or hardware changes.
+        It does not matter which object path a GetMachineId is sent to.  The
+        reference implementation handles this method automatically.
+      </para>
+      <para>
+        The UUID must contain 128 bits of data and be hex-encoded (meaning, the hex 
+        string contains 32 ASCII characters). The hex-encoded string may not contain 
+        hyphens or other non-hex-digit characters, and it must be exactly 32 characters long.
+        To generate a UUID, the recommended algorithm is to put the current time in seconds
+        since the UNIX epoch in the last 32 bits of the UUID, and to put randomly-generated bits
+        in the first 96 bits of the UUID.
+      </para>
+      <para>
+        The UUID is intended to be per-instance-of-the-operating-system, so may represent
+        a virtual machine running on a hypervisor, rather than a physical machine.
+        Basically if two processes see the same UUID, they should also see the same
+        shared memory, UNIX domain sockets, process IDs, and other features that require 
+        a running OS kernel in common between the processes.
       </para>
     </sect2>
 
Index: tools/Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/tools/Makefile.am,v
retrieving revision 1.22
diff -u -p -r1.22 Makefile.am
--- tools/Makefile.am	30 Sep 2006 19:38:34 -0000	1.22
+++ tools/Makefile.am	1 Oct 2006 03:14:20 -0000
@@ -1,6 +1,6 @@
 INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\"
 
-bin_PROGRAMS=dbus-send dbus-monitor dbus-launch dbus-cleanup-sockets
+bin_PROGRAMS=dbus-send dbus-monitor dbus-launch dbus-cleanup-sockets dbus-uuidgen
 
 dbus_send_SOURCES=				\
 	dbus-print-message.c			\
@@ -19,11 +19,15 @@ dbus_launch_SOURCES=				\
 dbus_cleanup_sockets_SOURCES=			\
 	dbus-cleanup-sockets.c
 
+dbus_uuidgen_SOURCES=				\
+	dbus-uuidgen.c
+
 dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la
 dbus_monitor_LDADD= $(top_builddir)/dbus/libdbus-1.la
+dbus_uuidgen_LDADD= $(top_builddir)/dbus/libdbus-1.la
 dbus_launch_LDADD= $(DBUS_X_LIBS)
 
-man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1
+man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1 dbus-uuidgen.1
 EXTRA_DIST = $(man_MANS) run-with-tmp-session-bus.sh
 CLEANFILES = 				\
 	run-with-tmp-session-bus.conf
Index: tools/dbus-cleanup-sockets.1
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-cleanup-sockets.1,v
retrieving revision 1.2
diff -u -p -r1.2 dbus-cleanup-sockets.1
--- tools/dbus-cleanup-sockets.1	3 Aug 2006 20:34:36 -0000	1.2
+++ tools/dbus-cleanup-sockets.1	1 Oct 2006 03:14:20 -0000
@@ -11,8 +11,8 @@ dbus-cleanup-sockets \- clean up leftove
 
 .SH DESCRIPTION
 
-The \fIdbus-cleanup-sockets\fP command cleans up sockets used for
-D-Bus connections. See http://www.freedesktop.org/software/dbus/ for
+The \fIdbus-cleanup-sockets\fP command cleans up unused D-Bus
+connection sockets. See http://www.freedesktop.org/software/dbus/ for
 more information about the big picture.
 
 .PP
@@ -21,6 +21,19 @@ in the standard default socket directory
 per-user-login-session message bus; this is usually /tmp. 
 Optionally, you can pass a different directory on the command line.
 
+.PP
+On Linux, this program is essentially useless, because D-Bus defaults
+to using "abstract sockets" that exist only in memory and don't have a
+corresponding file in /tmp. 
+
+.PP
+On most other flavors of UNIX, it's possible for the socket files to
+leak when programs using D-Bus exit abnormally or without closing
+their D-Bus connections. Thus, it might be interesting to run
+dbus-cleanup-sockets in a cron job to mop up any leaked sockets.
+Or you can just ignore the leaked sockets, they aren't really hurting
+anything, other than cluttering the output of "ls /tmp"
+
 .SH AUTHOR
 dbus-cleanup-sockets was adapted by Havoc Pennington from
 linc-cleanup-sockets written by Michael Meeks.
Index: tools/dbus-launch-x11.c
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch-x11.c,v
retrieving revision 1.1
diff -u -p -r1.1 dbus-launch-x11.c
--- tools/dbus-launch-x11.c	30 Sep 2006 19:38:34 -0000	1.1
+++ tools/dbus-launch-x11.c	1 Oct 2006 03:14:20 -0000
@@ -33,7 +33,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 
-Display *xdisplay;
+Display *xdisplay = NULL;
 static Atom selection_atom;
 static Atom address_atom;
 static Atom pid_atom;
Index: tools/dbus-launch.c
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch.c,v
retrieving revision 1.17
diff -u -p -r1.17 dbus-launch.c
--- tools/dbus-launch.c	30 Sep 2006 19:38:34 -0000	1.17
+++ tools/dbus-launch.c	1 Oct 2006 03:14:20 -0000
@@ -799,7 +799,7 @@ main (int argc, char **argv)
       fprintf (stderr,
                "Failed to execute message bus daemon %s: %s.  Will try again without full path.\n",
                DBUS_DAEMONDIR"/dbus-daemon", strerror (errno));
-
+      
       /*
        * If it failed, try running without full PATH.  Note this is needed
        * because the build process builds the run-with-tmp-session-bus.conf
@@ -902,33 +902,36 @@ main (int argc, char **argv)
       close (bus_pid_to_launcher_pipe[READ_END]);
 
 #ifdef DBUS_BUILD_X11
-      ret2 = x11_save_address (bus_address, bus_pid, &wid);
-      if (ret2 == 0)
-	{
-	  /* another window got added. Return its address */
-	  char *address;
-	  pid_t pid;
-	  long wid;
-
-	  if (x11_get_address (&address, &pid, &wid) && address != NULL)
-	    {
-	      verbose ("dbus-daemon is already running. Returning existing parameters.\n");
-	      print_variables (address, pid, wid, c_shell_syntax,
-			       bourne_shell_syntax, binary_syntax);
-	      free (address);
-
-	      bus_pid_to_kill = bus_pid;
-	      kill_bus_and_exit (0);
-	    }
-
-	  /* if failed, fall through */
-	}
-      if (ret2 <= 0)
-	{
-	  fprintf (stderr, "Error saving bus information.\n");
-	  bus_pid_to_kill = bus_pid;
-	  kill_bus_and_exit (1);
-	}
+      if (xdisplay != NULL)
+        {
+          ret2 = x11_save_address (bus_address, bus_pid, &wid);
+          if (ret2 == 0)
+            {
+              /* another window got added. Return its address */
+              char *address;
+              pid_t pid;
+              long wid;
+              
+              if (x11_get_address (&address, &pid, &wid) && address != NULL)
+                {
+                  verbose ("dbus-daemon is already running. Returning existing parameters.\n");
+                  print_variables (address, pid, wid, c_shell_syntax,
+                                   bourne_shell_syntax, binary_syntax);
+                  free (address);
+                  
+                  bus_pid_to_kill = bus_pid;
+                  kill_bus_and_exit (0);
+                }
+              
+              /* if failed, fall through */
+            }
+          if (ret2 <= 0)
+            {
+              fprintf (stderr, "Error saving bus information.\n");
+              bus_pid_to_kill = bus_pid;
+              kill_bus_and_exit (1);
+            }
+        }
 #endif
 
       /* Forward the pid to the babysitter */
Index: tools/dbus-uuidgen.1
===================================================================
RCS file: tools/dbus-uuidgen.1
diff -N tools/dbus-uuidgen.1
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/dbus-uuidgen.1	1 Oct 2006 03:14:20 -0000
@@ -0,0 +1,91 @@
+.\" 
+.\" dbus-uuidgen manual page.
+.\" Copyright (C) 2006 Red Hat, Inc.
+.\"
+.TH dbus-uuidgen 1
+.SH NAME
+dbus-uuidgen \- Utility to generate UUIDs
+.SH SYNOPSIS
+.PP
+.B dbus-uuidgen [\-\-version] [\-\-ensure[=FILENAME]] [\-\-get[=FILENAME]]
+
+.SH DESCRIPTION
+
+The \fIdbus-uuidgen\fP command generates or reads a universally unique ID.
+
+.PP
+See http://www.freedesktop.org/software/dbus/ for more information
+about D-Bus.
+
+.PP
+The primary usage of \fIdbus-uuidgen\fP is to run in the post-install
+script of a D-Bus package like this:
+.nf
+  dbus-uuidgen --ensure
+.fi
+
+.PP
+This will ensure that /etc/dbus-1/machine-id exists and has the uuid in it.
+It won't overwrite an existing uuid, since this id should remain fixed
+for a single machine until the next reboot at least.
+
+.PP
+The important properties of the machine UUID are that 1) it remains
+unchanged until the next reboot and 2) it is different for any two 
+running instances of the OS kernel. That is, if two processes see the 
+same UUID, they should also see the same shared memory, UNIX domain
+sockets, local X displays, localhost.localdomain resolution, process
+IDs, and so forth.
+
+.PP
+If you run \fIdbus-uuidgen\fP with no options it just prints a new uuid made
+up out of thin air. This is similar to the regular "uuidgen" command.
+
+.PP
+If you run it with --get, it prints the machine uuid by default, or
+the uuid in the specified file if you specify a file.
+
+.PP
+The D-Bus UUID has no relationship to RFC 4122 and does not generate
+UUIDs compatible with that spec.
+
+.PP
+If you try to change an existing /etc/dbus-1/machine-id on a running
+system, it will probably result in bad things happening. Don't try 
+to change this file. Also, don't make it the same on two different 
+systems; it needs to be different anytime there are two different 
+kernels running.
+
+.PP
+If you need to share /etc between two different kernels, a possible solution
+is to symlink the machine ID to /var, and run "dbus-uuidgen
+--ensure=/var/whatever" from an early boot script or the system
+message bus boot script.
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.I "--get[=FILENAME]"
+If a filename is not given, defaults to sysconfdir/dbus-1/machine-id
+(sysconfdir is usually /etc). If this file exists and is valid, the
+uuid in the file is printed on stdout. Otherwise, the command exits 
+with a nonzero status.
+
+.TP
+.I "--ensure[=FILENAME]"
+If a filename is not given, defaults to sysconfdir/dbus-1/machine-id
+(sysconfdir is usually /etc). If this file exists then it will be
+validated, and a failure code returned if it contains the wrong thing.
+If the file does not exist, it will be created with a new uuid in it.
+On success, prints no output.
+
+.TP
+.I "--version"
+Print the version of dbus-uuidgen
+
+.SH AUTHOR
+See http://www.freedesktop.org/software/dbus/doc/AUTHORS
+
+.SH BUGS
+Please send bug reports to the D-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
Index: tools/dbus-uuidgen.c
===================================================================
RCS file: tools/dbus-uuidgen.c
diff -N tools/dbus-uuidgen.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/dbus-uuidgen.c	1 Oct 2006 03:14:20 -0000
@@ -0,0 +1,161 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-uuidgen.c  Utility program to create UUIDs
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dbus/dbus-uuidgen.h>
+#include <dbus/dbus.h>
+
+static void
+usage (char *name, int ecode)
+{
+  if (name == NULL)
+    name = "dbus-uuidgen";
+  
+  fprintf (stderr, "Usage: %s [--ensure[=FILENAME]] [--get[=FILENAME]]\n", name);
+  exit (ecode);
+}
+
+static void
+version (void)
+{
+  printf ("D-Bus UUID Generator %s\n"
+          "Copyright (C) 2006 Red Hat, Inc.\n"
+          "This is free software; see the source for copying conditions.\n"
+          "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+          VERSION);
+  exit (0);
+}
+
+static dbus_bool_t
+get_arg (const char  *arg,
+         const char  *option,
+         const char **value_p)
+{
+  const char *fn;
+
+  if (strlen(arg) < strlen(option))
+    return FALSE;
+  
+  fn = arg + strlen(option);
+
+  if (!(*fn == '=' || *fn == ' ' || *fn == '\0'))
+    {
+      usage (NULL, 1);
+    }
+  
+  if (*fn == '=')
+    ++fn;
+  
+  while (*fn == ' ' && *fn != '\0')
+    ++fn;
+  
+  if (*fn != '\0')
+    {
+      *value_p = fn;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  const char *filename;
+  dbus_bool_t ensure_uuid;
+  dbus_bool_t get_uuid;
+  DBusError error;
+
+  ensure_uuid = FALSE;
+  get_uuid = FALSE;
+  
+  filename = NULL;
+
+  for (i = 1; i < argc; i++)
+    {
+      char *arg = argv[i];
+
+      if (strncmp (arg, "--ensure", strlen("--ensure")) == 0)
+        {
+          get_arg (arg, "--ensure", &filename);
+          ensure_uuid = TRUE;
+        }
+      else if (strncmp (arg, "--get", strlen("--get")) == 0)
+        {
+          get_arg (arg, "--get", &filename);
+          get_uuid = TRUE;
+        }
+      else if (strcmp (arg, "--help") == 0)
+	usage (argv[0], 0);
+      else if (strcmp (arg, "--version") == 0)
+        version ();
+      else
+        usage (argv[0], 1);
+    }
+
+  if (get_uuid && ensure_uuid)
+    {
+      fprintf (stderr, "Can't specify both --get and --ensure\n");
+      exit (1);
+    }
+
+  dbus_error_init (&error);
+  
+  if (get_uuid || ensure_uuid)
+    {
+      char *uuid;
+      if (dbus_internal_do_not_use_get_uuid (filename, &uuid, ensure_uuid, &error))
+        {
+          if (get_uuid) /* print nothing on --ensure */
+            printf ("%s\n", uuid);
+          dbus_free (uuid);
+        }
+    }
+  else
+    {
+      char *uuid;
+      if (dbus_internal_do_not_use_create_uuid (&uuid))
+        {
+          printf ("%s\n", uuid);
+          dbus_free (uuid);
+        }
+      else
+        {
+          dbus_set_error (&error, DBUS_ERROR_NO_MEMORY, "No memory");
+        }
+    }
+
+  if (dbus_error_is_set (&error))
+    {
+      fprintf (stderr, "%s\n", error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+  else
+    {
+      exit (0);
+    }
+}
Index: tools/run-with-tmp-session-bus.sh
===================================================================
RCS file: /cvs/dbus/dbus/tools/run-with-tmp-session-bus.sh,v
retrieving revision 1.3
diff -u -p -r1.3 run-with-tmp-session-bus.sh
--- tools/run-with-tmp-session-bus.sh	10 Aug 2006 21:44:00 -0000	1.3
+++ tools/run-with-tmp-session-bus.sh	1 Oct 2006 03:14:20 -0000
@@ -34,7 +34,11 @@ cat $DBUS_TOP_BUILDDIR/bus/session.conf 
 
 echo "Created configuration file $CONFIG_FILE" >&2
 
-export PATH=$DBUS_TOP_BUILDDIR/bus:$PATH
+if ! test -e "$DBUS_TOP_BUILDDIR"/bus/dbus-daemon ; then
+    die "$DBUS_TOP_BUILDDIR/bus/dbus-daemon does not exist"
+fi
+
+export PATH="$DBUS_TOP_BUILDDIR"/bus:$PATH
 ## the libtool script found by the path search should already do this, but
 export LD_LIBRARY_PATH=$DBUS_TOP_BUILDDIR/dbus/.libs:$LD_LIBRARY_PATH
 
@@ -46,7 +50,7 @@ echo "Running $DBUS_TOP_BUILDDIR/tools/d
 eval `$DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE`
 
 if test -z "$DBUS_SESSION_BUS_PID" ; then
-    die "Failed to launch message bus for introspection generation to run"
+    die "Failed to launch message bus for test script to run"
 fi
 
 echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2


More information about the dbus mailing list