* configure.in: Add test/name-test/Makefile to the generated
[platform/upstream/dbus.git] / dbus / dbus-sysdeps.c
index 4af7093..030d080 100644 (file)
@@ -26,7 +26,7 @@
 #include "dbus-sysdeps.h"
 #include "dbus-threads.h"
 #include "dbus-protocol.h"
-#include "dbus-test.h"
+#include "dbus-string.h"
 #include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
@@ -57,7 +57,9 @@
 #ifdef HAVE_BACKTRACE
 #include <execinfo.h>
 #endif
-
+#ifdef HAVE_GETPEERUCRED
+#include <ucred.h>
+#endif
 
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -71,6 +73,7 @@
  * @addtogroup DBusInternalsUtils
  * @{
  */
+#ifndef DBUS_DISABLE_ASSERT
 /**
  * Aborts the program with SIGABRT (dumping core).
  */
@@ -86,6 +89,7 @@ _dbus_abort (void)
   abort ();
   _exit (1); /* in case someone manages to ignore SIGABRT */
 }
+#endif
 
 /**
  * Wrapper for setenv(). If the value is #NULL, unsets
@@ -394,6 +398,7 @@ _dbus_connect_unix_socket (const char     *path,
                            DBusError      *error)
 {
   int fd;
+  size_t path_len;
   struct sockaddr_un addr;  
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -415,15 +420,23 @@ _dbus_connect_unix_socket (const char     *path,
 
   _DBUS_ZERO (addr);
   addr.sun_family = AF_UNIX;
+  path_len = strlen (path);
 
   if (abstract)
     {
 #ifdef HAVE_ABSTRACT_SOCKETS
-      /* remember that abstract names aren't nul-terminated so we rely
-       * on sun_path being filled in with zeroes above.
-       */
       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
-      strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
+      path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Abstract socket name too long\n");
+          close (fd);
+          return -1;
+       }
+       
+      strncpy (&addr.sun_path[1], path, path_len);
       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
 #else /* HAVE_ABSTRACT_SOCKETS */
       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
@@ -434,10 +447,18 @@ _dbus_connect_unix_socket (const char     *path,
     }
   else
     {
-      strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Socket name too long\n");
+          close (fd);
+          return -1;
+       }
+
+      strncpy (addr.sun_path, path, path_len);
     }
   
-  if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
+  if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
     {      
       dbus_set_error (error,
                       _dbus_error_from_errno (errno),
@@ -485,6 +506,7 @@ _dbus_listen_unix_socket (const char     *path,
 {
   int listen_fd;
   struct sockaddr_un addr;
+  size_t path_len;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
@@ -503,6 +525,7 @@ _dbus_listen_unix_socket (const char     *path,
 
   _DBUS_ZERO (addr);
   addr.sun_family = AF_UNIX;
+  path_len = strlen (path);
   
   if (abstract)
     {
@@ -511,7 +534,17 @@ _dbus_listen_unix_socket (const char     *path,
        * on sun_path being filled in with zeroes above.
        */
       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
-      strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
+      path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Abstract socket name too long\n");
+          close (listen_fd);
+          return -1;
+       }
+      
+      strncpy (&addr.sun_path[1], path, path_len);
       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
 #else /* HAVE_ABSTRACT_SOCKETS */
       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
@@ -540,10 +573,18 @@ _dbus_listen_unix_socket (const char     *path,
           unlink (path);
       }
 
-      strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Abstract socket name too long\n");
+          close (listen_fd);
+          return -1;
+       }
+       
+      strncpy (addr.sun_path, path, path_len);
     }
   
-  if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
+  if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
                       "Failed to bind socket \"%s\": %s",
@@ -622,6 +663,7 @@ _dbus_connect_tcp_socket (const char     *host,
                       _dbus_error_from_errno (errno),
                       "Failed to lookup hostname: %s",
                       host);
+      close (fd);
       return -1;
     }
   
@@ -695,6 +737,7 @@ _dbus_listen_tcp_socket (const char     *host,
                       _dbus_error_from_errno (errno),
                       "Failed to lookup hostname: %s",
                       host);
+      close (listen_fd);
       return -1;
     }
   
@@ -738,12 +781,40 @@ write_credentials_byte (int             server_fd,
 {
   int bytes_written;
   char buf[1] = { '\0' };
+#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+  struct {
+         struct cmsghdr hdr;
+         struct cmsgcred cred;
+  } cmsg;
+  struct iovec iov;
+  struct msghdr msg;
+#endif
+
+#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+  iov.iov_base = buf;
+  iov.iov_len = 1;
+
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+  msg.msg_control = &cmsg;
+  msg.msg_controllen = sizeof (cmsg);
+  memset (&cmsg, 0, sizeof (cmsg));
+  cmsg.hdr.cmsg_len = sizeof (cmsg);
+  cmsg.hdr.cmsg_level = SOL_SOCKET;
+  cmsg.hdr.cmsg_type = SCM_CREDS;
+#endif
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
  again:
 
+#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+  bytes_written = sendmsg (server_fd, &msg, 0);
+#else
   bytes_written = write (server_fd, buf, 1);
+#endif
 
   if (bytes_written < 0 && errno == EINTR)
     goto again;
@@ -797,8 +868,10 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
   char buf;
 
 #ifdef HAVE_CMSGCRED 
-  char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
-  struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
+  struct {
+         struct cmsghdr hdr;
+         struct cmsgcred cred;
+  } cmsg;
 #endif
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -833,9 +906,9 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
   msg.msg_iovlen = 1;
 
 #ifdef HAVE_CMSGCRED
-  memset (cmsgmem, 0, sizeof (cmsgmem));
-  msg.msg_control = cmsgmem;
-  msg.msg_controllen = sizeof (cmsgmem);
+  memset (&cmsg, 0, sizeof (cmsg));
+  msg.msg_control = &cmsg;
+  msg.msg_controllen = sizeof (cmsg);
 #endif
 
  again:
@@ -858,10 +931,10 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
     }
 
 #ifdef HAVE_CMSGCRED
-  if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
+  if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
     {
-      dbus_set_error (error, DBUS_ERROR_FAILED);
-      _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Message from recvmsg() was not SCM_CREDS");
       return FALSE;
     }
 #endif
@@ -886,14 +959,36 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
                       cr_len, (int) sizeof (cr), _dbus_strerror (errno));
       }
 #elif defined(HAVE_CMSGCRED)
-    struct cmsgcred *cred;
-
-    cred = (struct cmsgcred *) CMSG_DATA (cmsg);
-
-    credentials->pid = cred->cmcred_pid;
-    credentials->uid = cred->cmcred_euid;
-    credentials->gid = cred->cmcred_groups[0];
-#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
+    credentials->pid = cmsg.cred.cmcred_pid;
+    credentials->uid = cmsg.cred.cmcred_euid;
+    credentials->gid = cmsg.cred.cmcred_groups[0];
+#elif defined(HAVE_GETPEEREID)
+    uid_t euid;
+    gid_t egid;
+    if (getpeereid (client_fd, &euid, &egid) == 0)
+      {
+        credentials->uid = euid;
+        credentials->gid = egid;
+      }
+    else
+      {
+        _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
+      }
+#elif defined(HAVE_GETPEERUCRED)
+    ucred_t * ucred = NULL;
+    if (getpeerucred (client_fd, &ucred) == 0)
+      {
+        credentials->pid = ucred_getpid (ucred);
+        credentials->uid = ucred_geteuid (ucred);
+        credentials->gid = ucred_getegid (ucred);
+      }
+    else
+      {
+        _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
+      }
+    if (ucred != NULL)
+      ucred_free (ucred);
+#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
     _dbus_verbose ("Socket credentials not supported on this OS\n");
 #endif
   }
@@ -1049,6 +1144,7 @@ _dbus_string_append_uint (DBusString    *str,
   return TRUE;
 }
 
+#ifdef DBUS_BUILD_TESTS
 /**
  * Appends a double to a DBusString.
  * 
@@ -1085,6 +1181,7 @@ _dbus_string_append_double (DBusString *str,
   
   return TRUE;
 }
+#endif /* DBUS_BUILD_TESTS */
 
 /**
  * Parses an integer contained in a DBusString. Either return parameter
@@ -1125,8 +1222,43 @@ _dbus_string_parse_int (const DBusString *str,
   return TRUE;
 }
 
-#ifdef DBUS_BUILD_TESTS
-/* Not currently used, so only built when tests are enabled */
+/**
+* Checks to make sure the given directory is 
+* private to the user 
+*
+* @param dir the name of the directory
+* @param error error return
+* @returns #FALSE on failure
+**/
+dbus_bool_t
+_dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
+{
+  const char *directory;
+  struct stat sb;
+       
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+    
+  directory = _dbus_string_get_const_data (dir);
+       
+  if (stat (directory, &sb) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "%s", _dbus_strerror (errno));
+   
+      return FALSE;
+    }
+    
+  if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
+      (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                     "%s directory is not private to the user", directory);
+      return FALSE;
+    }
+    
+  return TRUE;
+}
+
 /**
  * Parses an unsigned integer contained in a DBusString. Either return
  * parameter may be #NULL if you aren't interested in it. The integer
@@ -1165,8 +1297,8 @@ _dbus_string_parse_uint (const DBusString *str,
 
   return TRUE;
 }
-#endif /* DBUS_BUILD_TESTS */
 
+#ifdef DBUS_BUILD_TESTS
 static dbus_bool_t
 ascii_isspace (char c)
 {
@@ -1177,13 +1309,17 @@ ascii_isspace (char c)
          c == '\t' ||
          c == '\v');
 }
+#endif /* DBUS_BUILD_TESTS */
 
+#ifdef DBUS_BUILD_TESTS
 static dbus_bool_t
 ascii_isdigit (char c)
 {
   return c >= '0' && c <= '9';
 }
+#endif /* DBUS_BUILD_TESTS */
 
+#ifdef DBUS_BUILD_TESTS
 static dbus_bool_t
 ascii_isxdigit (char c)
 {
@@ -1191,8 +1327,9 @@ ascii_isxdigit (char c)
          (c >= 'a' && c <= 'f') ||
          (c >= 'A' && c <= 'F'));
 }
+#endif /* DBUS_BUILD_TESTS */
 
-
+#ifdef DBUS_BUILD_TESTS
 /* Calls strtod in a locale-independent fashion, by looking at
  * the locale data and patching the decimal comma to a point.
  *
@@ -1321,8 +1458,9 @@ ascii_strtod (const char *nptr,
   
   return val;
 }
+#endif /* DBUS_BUILD_TESTS */
 
-
+#ifdef DBUS_BUILD_TESTS
 /**
  * Parses a floating point number contained in a DBusString. Either
  * return parameter may be #NULL if you aren't interested in it. The
@@ -1361,6 +1499,7 @@ _dbus_string_parse_double (const DBusString *str,
 
   return TRUE;
 }
+#endif /* DBUS_BUILD_TESTS */
 
 /** @} */ /* DBusString group */
 
@@ -1420,7 +1559,7 @@ fill_user_info (DBusUserInfo       *info,
    * checks
    */
   
-#if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
+#if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
   {
     struct passwd *p;
     int result;
@@ -1428,8 +1567,8 @@ fill_user_info (DBusUserInfo       *info,
     struct passwd p_str;
 
     p = NULL;
-#ifdef HAVE_POSIX_GETPWNAME_R
-    if (uid >= 0)
+#ifdef HAVE_POSIX_GETPWNAM_R
+    if (uid != DBUS_UID_UNSET)
       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
                            &p);
     else
@@ -1441,7 +1580,7 @@ fill_user_info (DBusUserInfo       *info,
     else
       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
     result = 0;
-#endif /* !HAVE_POSIX_GETPWNAME_R */
+#endif /* !HAVE_POSIX_GETPWNAM_R */
     if (result == 0 && p == &p_str)
       {
         if (!fill_user_info_from_passwd (p, info, error))
@@ -1564,7 +1703,6 @@ fill_user_info (DBusUserInfo       *info,
   
  failed:
   _DBUS_ASSERT_ERROR_IS_SET (error);
-  _dbus_user_info_free (info);
   return FALSE;
 }
 
@@ -1615,149 +1753,6 @@ _dbus_user_info_free (DBusUserInfo *info)
   dbus_free (info->homedir);
 }
 
-static dbus_bool_t
-fill_user_info_from_group (struct group  *g,
-                           DBusGroupInfo *info,
-                           DBusError     *error)
-{
-  _dbus_assert (g->gr_name != NULL);
-  
-  info->gid = g->gr_gid;
-  info->groupname = _dbus_strdup (g->gr_name);
-
-  /* info->members = dbus_strdupv (g->gr_mem) */
-  
-  if (info->groupname == NULL)
-    {
-      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-static dbus_bool_t
-fill_group_info (DBusGroupInfo    *info,
-                 dbus_gid_t        gid,
-                 const DBusString *groupname,
-                 DBusError        *error)
-{
-  const char *group_c_str;
-
-  _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
-  _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
-
-  if (groupname)
-    group_c_str = _dbus_string_get_const_data (groupname);
-  else
-    group_c_str = NULL;
-  
-  /* For now assuming that the getgrnam() and getgrgid() flavors
-   * always correspond to the pwnam flavors, if not we have
-   * to add more configure checks.
-   */
-  
-#if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
-  {
-    struct group *g;
-    int result;
-    char buf[1024];
-    struct group g_str;
-
-    g = NULL;
-#ifdef HAVE_POSIX_GETPWNAME_R
-
-    if (group_c_str)
-      result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
-                           &g);
-    else
-      result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
-                           &g);
-#else
-    p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
-    result = 0;
-#endif /* !HAVE_POSIX_GETPWNAME_R */
-    if (result == 0 && g == &g_str)
-      {
-        return fill_user_info_from_group (g, info, error);
-      }
-    else
-      {
-        dbus_set_error (error, _dbus_error_from_errno (errno),
-                        "Group %s unknown or failed to look it up\n",
-                        group_c_str ? group_c_str : "???");
-        return FALSE;
-      }
-  }
-#else /* ! HAVE_GETPWNAM_R */
-  {
-    /* I guess we're screwed on thread safety here */
-    struct group *g;
-
-    g = getgrnam (group_c_str);
-
-    if (g != NULL)
-      {
-        return fill_user_info_from_group (g, info, error);
-      }
-    else
-      {
-        dbus_set_error (error, _dbus_error_from_errno (errno),
-                        "Group %s unknown or failed to look it up\n",
-                        group_c_str ? group_c_str : "???");
-        return FALSE;
-      }
-  }
-#endif  /* ! HAVE_GETPWNAM_R */
-}
-
-/**
- * Initializes the given DBusGroupInfo struct
- * with information about the given group name.
- *
- * @param info the group info struct
- * @param groupname name of group
- * @param error the error return
- * @returns #FALSE if error is set
- */
-dbus_bool_t
-_dbus_group_info_fill (DBusGroupInfo    *info,
-                       const DBusString *groupname,
-                       DBusError        *error)
-{
-  return fill_group_info (info, DBUS_GID_UNSET,
-                          groupname, error);
-
-}
-
-/**
- * Initializes the given DBusGroupInfo struct
- * with information about the given group ID.
- *
- * @param info the group info struct
- * @param gid group ID
- * @param error the error return
- * @returns #FALSE if error is set
- */
-dbus_bool_t
-_dbus_group_info_fill_gid (DBusGroupInfo *info,
-                           dbus_gid_t     gid,
-                           DBusError     *error)
-{
-  return fill_group_info (info, gid, NULL, error);
-}
-
-/**
- * Frees the members of info (but not info itself).
- *
- * @param info the group info
- */
-void
-_dbus_group_info_free (DBusGroupInfo    *info)
-{
-  dbus_free (info->groupname);
-}
-
 /**
  * Sets fields in DBusCredentials to DBUS_PID_UNSET,
  * DBUS_UID_UNSET, DBUS_GID_UNSET.
@@ -1836,6 +1831,7 @@ _dbus_getuid (void)
   return getuid ();
 }
 
+#ifdef DBUS_BUILD_TESTS
 /** Gets our GID
  * @returns process GID
  */
@@ -1844,6 +1840,7 @@ _dbus_getgid (void)
 {
   return getgid ();
 }
+#endif
 
 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
 
@@ -1968,40 +1965,41 @@ _dbus_poll (DBusPollFD *fds,
 
   for (i = 0; i < n_fds; i++)
     {
-      DBusPollFD f = fds[i];
+      DBusPollFD *fdp = &fds[i];
 
-      if (f.events & _DBUS_POLLIN)
-       FD_SET (f.fd, &read_set);
+      if (fdp->events & _DBUS_POLLIN)
+       FD_SET (fdp->fd, &read_set);
 
-      if (f.events & _DBUS_POLLOUT)
-       FD_SET (f.fd, &write_set);
+      if (fdp->events & _DBUS_POLLOUT)
+       FD_SET (fdp->fd, &write_set);
 
-      FD_SET (f.fd, &err_set);
+      FD_SET (fdp->fd, &err_set);
 
-      max_fd = MAX (max_fd, f.fd);
+      max_fd = MAX (max_fd, fdp->fd);
     }
     
   tv.tv_sec = timeout_milliseconds / 1000;
   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
 
-  ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
+  ready = select (max_fd + 1, &read_set, &write_set, &err_set,
+                  timeout_milliseconds < 0 ? NULL : &tv);
 
   if (ready > 0)
     {
       for (i = 0; i < n_fds; i++)
        {
-         DBusPollFD f = fds[i];
+         DBusPollFD *fdp = &fds[i];
 
-         f.revents = 0;
+         fdp->revents = 0;
 
-         if (FD_ISSET (f.fd, &read_set))
-           f.revents |= _DBUS_POLLIN;
+         if (FD_ISSET (fdp->fd, &read_set))
+           fdp->revents |= _DBUS_POLLIN;
 
-         if (FD_ISSET (f.fd, &write_set))
-           f.revents |= _DBUS_POLLOUT;
+         if (FD_ISSET (fdp->fd, &write_set))
+           fdp->revents |= _DBUS_POLLOUT;
 
-         if (FD_ISSET (f.fd, &err_set))
-           f.revents |= _DBUS_POLLERR;
+         if (FD_ISSET (fdp->fd, &err_set))
+           fdp->revents |= _DBUS_POLLERR;
        }
     }
 
@@ -2120,7 +2118,7 @@ _dbus_file_get_contents (DBusString       *str,
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "File size %lu of \"%s\" is too large.",
-                      filename_c, (unsigned long) sb.st_size);
+                      (unsigned long) sb.st_size, filename_c);
       close (fd);
       return FALSE;
     }
@@ -2415,34 +2413,6 @@ _dbus_create_directory (const DBusString *filename,
 }
 
 /**
- * Removes a directory; Directory must be empty
- * 
- * @param filename directory filename
- * @param error initialized error object
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_delete_directory (const DBusString *filename,
-                       DBusError        *error)
-{
-  const char *filename_c;
-  
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
-  filename_c = _dbus_string_get_const_data (filename);
-
-  if (rmdir (filename_c) != 0)
-    {
-      dbus_set_error (error, DBUS_ERROR_FAILED,
-                     "Failed to remove directory %s: %s\n",
-                     filename_c, _dbus_strerror (errno));
-      return FALSE;
-    }
-  
-  return TRUE;
-}
-
-/**
  * Appends the given filename to the given directory.
  *
  * @todo it might be cute to collapse multiple '/' such as "foo//"
@@ -2482,223 +2452,87 @@ _dbus_concat_dir_and_file (DBusString       *dir,
                             _dbus_string_get_length (dir));
 }
 
-/**
- * Get the directory name from a complete filename
- * @param filename the filename
- * @param dirname string to append directory name to
- * @returns #FALSE if no memory
- */
-dbus_bool_t
-_dbus_string_get_dirname  (const DBusString *filename,
-                           DBusString       *dirname)
+static void
+pseudorandom_generate_random_bytes_buffer (char *buffer,
+                                           int   n_bytes)
 {
-  int sep;
-  
-  _dbus_assert (filename != dirname);
-  _dbus_assert (filename != NULL);
-  _dbus_assert (dirname != NULL);
-
-  /* Ignore any separators on the end */
-  sep = _dbus_string_get_length (filename);
-  if (sep == 0)
-    return _dbus_string_append (dirname, "."); /* empty string passed in */
-    
-  while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
-    --sep;
-
-  _dbus_assert (sep >= 0);
+  unsigned long tv_usec;
+  int i;
   
-  if (sep == 0)
-    return _dbus_string_append (dirname, "/");
+  /* fall back to pseudorandom */
+  _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
+                 n_bytes);
   
-  /* Now find the previous separator */
-  _dbus_string_find_byte_backward (filename, sep, '/', &sep);
-  if (sep < 0)
-    return _dbus_string_append (dirname, ".");
+  _dbus_get_current_time (NULL, &tv_usec);
+  srand (tv_usec);
   
-  /* skip multiple separators */
-  while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
-    --sep;
+  i = 0;
+  while (i < n_bytes)
+    {
+      double r;
+      unsigned int b;
+          
+      r = rand ();
+      b = (r / (double) RAND_MAX) * 255.0;
 
-  _dbus_assert (sep >= 0);
-  
-  if (sep == 0 &&
-      _dbus_string_get_byte (filename, 0) == '/')
-    return _dbus_string_append (dirname, "/");
-  else
-    return _dbus_string_copy_len (filename, 0, sep - 0,
-                                  dirname, _dbus_string_get_length (dirname));
-}
+      buffer[i] = b;
 
-/**
- * Checks whether the filename is an absolute path
- *
- * @param filename the filename
- * @returns #TRUE if an absolute path
- */
-dbus_bool_t
-_dbus_path_is_absolute (const DBusString *filename)
-{
-  if (_dbus_string_get_length (filename) > 0)
-    return _dbus_string_get_byte (filename, 0) == '/';
-  else
-    return FALSE;
+      ++i;
+    }
 }
 
-/**
- * Internals of directory iterator
- */
-struct DBusDirIter
+static dbus_bool_t
+pseudorandom_generate_random_bytes (DBusString *str,
+                                    int         n_bytes)
 {
-  DIR *d; /**< The DIR* from opendir() */
+  int old_len;
+  char *p;
   
-};
+  old_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_lengthen (str, n_bytes))
+    return FALSE;
+
+  p = _dbus_string_get_data_len (str, old_len, n_bytes);
+
+  pseudorandom_generate_random_bytes_buffer (p, n_bytes);
+
+  return TRUE;
+}
 
 /**
- * Open a directory to iterate over.
+ * Fills n_bytes of the given buffer with random bytes.
  *
- * @param filename the directory name
- * @param error exception return object or #NULL
- * @returns new iterator, or #NULL on error
+ * @param buffer an allocated buffer
+ * @param n_bytes the number of bytes in buffer to write to
  */
-DBusDirIter*
-_dbus_directory_open (const DBusString *filename,
-                      DBusError        *error)
+void
+_dbus_generate_random_bytes_buffer (char *buffer,
+                                    int   n_bytes)
 {
-  DIR *d;
-  DBusDirIter *iter;
-  const char *filename_c;
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  filename_c = _dbus_string_get_const_data (filename);
+  DBusString str;
 
-  d = opendir (filename_c);
-  if (d == NULL)
+  if (!_dbus_string_init (&str))
     {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to read directory \"%s\": %s",
-                      filename_c,
-                      _dbus_strerror (errno));
-      return NULL;
+      pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
+      return;
     }
-  iter = dbus_new0 (DBusDirIter, 1);
-  if (iter == NULL)
+
+  if (!_dbus_generate_random_bytes (&str, n_bytes))
     {
-      closedir (d);
-      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
-                      "Could not allocate memory for directory iterator");
-      return NULL;
+      _dbus_string_free (&str);
+      pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
+      return;
     }
 
-  iter->d = d;
+  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
 
-  return iter;
+  _dbus_string_free (&str);
 }
 
 /**
- * Get next file in the directory. Will not return "." or ".."  on
- * UNIX. If an error occurs, the contents of "filename" are
- * undefined. The error is never set if the function succeeds.
- *
- * @todo for thread safety, I think we have to use
- * readdir_r(). (GLib has the same issue, should file a bug.)
- *
- * @param iter the iterator
- * @param filename string to be set to the next file in the dir
- * @param error return location for error
- * @returns #TRUE if filename was filled in with a new filename
- */
-dbus_bool_t
-_dbus_directory_get_next_file (DBusDirIter      *iter,
-                               DBusString       *filename,
-                               DBusError        *error)
-{
-  struct dirent *ent;
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
- again:
-  errno = 0;
-  ent = readdir (iter->d);
-  if (ent == NULL)
-    {
-      if (errno != 0)
-        dbus_set_error (error,
-                        _dbus_error_from_errno (errno),
-                        "%s", _dbus_strerror (errno));
-      return FALSE;
-    }
-  else if (ent->d_name[0] == '.' &&
-           (ent->d_name[1] == '\0' ||
-            (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
-    goto again;
-  else
-    {
-      _dbus_string_set_length (filename, 0);
-      if (!_dbus_string_append (filename, ent->d_name))
-        {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
-                          "No memory to read directory entry");
-          return FALSE;
-        }
-      else
-        return TRUE;
-    }
-}
-
-/**
- * Closes a directory iteration.
- */
-void
-_dbus_directory_close (DBusDirIter *iter)
-{
-  closedir (iter->d);
-  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.
+ * 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
@@ -2937,98 +2771,6 @@ _dbus_exit (int code)
 }
 
 /**
- * stat() wrapper.
- *
- * @param filename the filename to stat
- * @param statbuf the stat info to fill in
- * @param error return location for error
- * @returns #FALSE if error was set
- */
-dbus_bool_t
-_dbus_stat (const DBusString *filename,
-            DBusStat         *statbuf,
-            DBusError        *error)
-{
-  const char *filename_c;
-  struct stat sb;
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  filename_c = _dbus_string_get_const_data (filename);
-
-  if (stat (filename_c, &sb) < 0)
-    {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "%s", _dbus_strerror (errno));
-      return FALSE;
-    }
-
-  statbuf->mode = sb.st_mode;
-  statbuf->nlink = sb.st_nlink;
-  statbuf->uid = sb.st_uid;
-  statbuf->gid = sb.st_gid;
-  statbuf->size = sb.st_size;
-  statbuf->atime = sb.st_atime;
-  statbuf->mtime = sb.st_mtime;
-  statbuf->ctime = sb.st_ctime;
-
-  return TRUE;
-}
-
-/**
- * Creates a full-duplex pipe (as in socketpair()).
- * Sets both ends of the pipe nonblocking.
- *
- * @param fd1 return location for one end
- * @param fd2 return location for the other end
- * @param blocking #TRUE if pipe should be blocking
- * @param error error return
- * @returns #FALSE on failure (if error is set)
- */
-dbus_bool_t
-_dbus_full_duplex_pipe (int        *fd1,
-                        int        *fd2,
-                        dbus_bool_t blocking,
-                        DBusError  *error)
-{
-#ifdef HAVE_SOCKETPAIR
-  int fds[2];
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
-    {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Could not create full-duplex pipe");
-      return FALSE;
-    }
-
-  if (!blocking &&
-      (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
-       !_dbus_set_fd_nonblocking (fds[1], NULL)))
-    {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Could not set full-duplex pipe nonblocking");
-      
-      close (fds[0]);
-      close (fds[1]);
-      
-      return FALSE;
-    }
-  
-  *fd1 = fds[0];
-  *fd2 = fds[1];
-  
-  return TRUE;  
-#else
-  _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
-  dbus_set_error (error, DBUS_ERROR_FAILED,
-                  "_dbus_full_duplex_pipe() not implemented on this OS");
-  return FALSE;
-#endif
-}
-
-/**
  * Closes a file descriptor.
  *
  * @param fd the file descriptor
@@ -3095,6 +2837,7 @@ _dbus_set_fd_nonblocking (int             fd,
   return TRUE;
 }
 
+#if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
 /**
  * On GNU libc systems, print a crude backtrace to the verbose log.
  * On other systems, print "no backtrace support"
@@ -3125,384 +2868,110 @@ _dbus_print_backtrace (void)
   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
 #endif
 }
+#endif /* asserts or tests enabled */
 
-/**
- * Does the chdir, fork, setsid, etc. to become a daemon process.
- *
- * @param pidfile #NULL, or pidfile to create
- * @param error return location for errors
- * @returns #FALSE on failure
- */
-dbus_bool_t
-_dbus_become_daemon (const DBusString *pidfile,
-                     DBusError        *error)
-{
-  const char *s;
-  pid_t child_pid;
-  int dev_null_fd;
-
-  _dbus_verbose ("Becoming a daemon...\n");
-
-  _dbus_verbose ("chdir to /\n");
-  if (chdir ("/") < 0)
-    {
-      dbus_set_error (error, DBUS_ERROR_FAILED,
-                      "Could not chdir() to root directory");
-      return FALSE;
-    }
-
-  _dbus_verbose ("forking...\n");
-  switch ((child_pid = fork ()))
-    {
-    case -1:
-      _dbus_verbose ("fork failed\n");
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to fork daemon: %s", _dbus_strerror (errno));
-      return FALSE;
-      break;
-
-    case 0:
-      _dbus_verbose ("in child, closing std file descriptors\n");
-
-      /* silently ignore failures here, if someone
-       * doesn't have /dev/null we may as well try
-       * to continue anyhow
-       */
-      
-      dev_null_fd = open ("/dev/null", O_RDWR);
-      if (dev_null_fd >= 0)
-        {
-          dup2 (dev_null_fd, 0);
-          dup2 (dev_null_fd, 1);
-          
-          s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
-          if (s == NULL || *s == '\0')
-            dup2 (dev_null_fd, 2);
-          else
-            _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
-        }
-
-      /* Get a predictable umask */
-      _dbus_verbose ("setting umask\n");
-      umask (022);
-      break;
-
-    default:
-      if (pidfile)
-        {
-          _dbus_verbose ("parent writing pid file\n");
-          if (!_dbus_write_pid_file (pidfile,
-                                     child_pid,
-                                     error))
-            {
-              _dbus_verbose ("pid file write failed, killing child\n");
-              kill (child_pid, SIGTERM);
-              return FALSE;
-            }
-        }
-      _dbus_verbose ("parent exiting\n");
-      _exit (0);
-      break;
-    }
-
-  _dbus_verbose ("calling setsid()\n");
-  if (setsid () == -1)
-    _dbus_assert_not_reached ("setsid() failed");
-  
-  return TRUE;
-}
 
 /**
- * Creates a file containing the process ID.
+ * Gets a UID from a UID string.
  *
- * @param filename the filename to write to
- * @param pid our process ID
- * @param error return location for errors
- * @returns #FALSE on failure
+ * @param uid_str the UID in string form
+ * @param uid UID to fill in
+ * @returns #TRUE if successfully filled in UID
  */
 dbus_bool_t
-_dbus_write_pid_file (const DBusString *filename,
-                      unsigned long     pid,
-                     DBusError        *error)
+_dbus_parse_uid (const DBusString      *uid_str,
+                 dbus_uid_t            *uid)
 {
-  const char *cfilename;
-  int fd;
-  FILE *f;
-
-  cfilename = _dbus_string_get_const_data (filename);
-  
-  fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
+  int end;
+  long val;
   
-  if (fd < 0)
+  if (_dbus_string_get_length (uid_str) == 0)
     {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to open \"%s\": %s", cfilename,
-                      _dbus_strerror (errno));
+      _dbus_verbose ("UID string was zero length\n");
       return FALSE;
     }
 
-  if ((f = fdopen (fd, "w")) == NULL)
+  val = -1;
+  end = 0;
+  if (!_dbus_string_parse_int (uid_str, 0, &val,
+                               &end))
     {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
-      close (fd);
+      _dbus_verbose ("could not parse string as a UID\n");
       return FALSE;
     }
   
-  if (fprintf (f, "%lu\n", pid) < 0)
+  if (end != _dbus_string_get_length (uid_str))
     {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to write to \"%s\": %s", cfilename,
-                      _dbus_strerror (errno));
+      _dbus_verbose ("string contained trailing stuff after UID\n");
       return FALSE;
     }
 
-  if (fclose (f) == EOF)
-    {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to close \"%s\": %s", cfilename,
-                      _dbus_strerror (errno));
-      return FALSE;
-    }
-  
+  *uid = val;
+
   return TRUE;
 }
 
 /**
- * Changes the user and group the bus is running as.
+ * Creates a full-duplex pipe (as in socketpair()).
+ * Sets both ends of the pipe nonblocking.
  *
- * @param uid the new user ID
- * @param gid the new group ID
- * @param error return location for errors
- * @returns #FALSE on failure
+ * @todo libdbus only uses this for the debug-pipe server, so in
+ * principle it could be in dbus-sysdeps-util.c, except that
+ * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
+ * debug-pipe server is used.
+ * 
+ * @param fd1 return location for one end
+ * @param fd2 return location for the other end
+ * @param blocking #TRUE if pipe should be blocking
+ * @param error error return
+ * @returns #FALSE on failure (if error is set)
  */
 dbus_bool_t
-_dbus_change_identity  (dbus_uid_t     uid,
-                        dbus_gid_t     gid,
-                        DBusError     *error)
+_dbus_full_duplex_pipe (int        *fd1,
+                        int        *fd2,
+                        dbus_bool_t blocking,
+                        DBusError  *error)
 {
-  /* setgroups() only works if we are a privileged process,
-   * so we don't return error on failure; the only possible
-   * failure is that we don't have perms to do it.
-   * FIXME not sure this is right, maybe if setuid()
-   * is going to work then setgroups() should also work.
-   */
-  if (setgroups (0, NULL) < 0)
-    _dbus_warn ("Failed to drop supplementary groups: %s\n",
-                _dbus_strerror (errno));
-  
-  /* Set GID first, or the setuid may remove our permission
-   * to change the GID
-   */
-  if (setgid (gid) < 0)
-    {
-      dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to set GID to %lu: %s", gid,
-                      _dbus_strerror (errno));
-      return FALSE;
-    }
+#ifdef HAVE_SOCKETPAIR
+  int fds[2];
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  if (setuid (uid) < 0)
+  if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to set UID to %lu: %s", uid,
-                      _dbus_strerror (errno));
-      return FALSE;
-    }
-  
-  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);
-}
-
-/** Checks if a file exists
-*
-* @param file full path to the file
-* @returns #TRUE if file exists
-*/
-dbus_bool_t 
-_dbus_file_exists (const char *file)
-{
-  return (access (file, F_OK) == 0);
-}
-
-/** Checks if user is at the console
-*
-* @param username user to check
-* @param error return location for errors
-* @returns #TRUE is the user is at the consolei and there are no errors
-*/
-dbus_bool_t 
-_dbus_user_at_console (const char *username,
-                       DBusError  *error)
-{
-
-  DBusString f;
-  dbus_bool_t result;
-
-  if (!_dbus_string_init (&f))
-    {
-      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-      return FALSE;
-    }
-
-  if (!_dbus_string_append (&f, DBUS_CONSOLE_DIR))
-    {
-      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                      "Could not create full-duplex pipe");
       return FALSE;
     }
 
-
-  if (!_dbus_string_append (&f, username))
+  if (!blocking &&
+      (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
+       !_dbus_set_fd_nonblocking (fds[1], NULL)))
     {
-      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not set full-duplex pipe nonblocking");
+      
+      close (fds[0]);
+      close (fds[1]);
+      
       return FALSE;
     }
-
-  result = _dbus_file_exists (_dbus_string_get_const_data (&f));
-  _dbus_string_free (&f);
-
-  return result;
-}
-
-#ifdef DBUS_BUILD_TESTS
-#include <stdlib.h>
-static void
-check_dirname (const char *filename,
-               const char *dirname)
-{
-  DBusString f, d;
-  
-  _dbus_string_init_const (&f, filename);
-
-  if (!_dbus_string_init (&d))
-    _dbus_assert_not_reached ("no memory");
-
-  if (!_dbus_string_get_dirname (&f, &d))
-    _dbus_assert_not_reached ("no memory");
-
-  if (!_dbus_string_equal_c_str (&d, dirname))
-    {
-      _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
-                  filename,
-                  _dbus_string_get_const_data (&d),
-                  dirname);
-      exit (1);
-    }
-
-  _dbus_string_free (&d);
-}
-
-static void
-check_path_absolute (const char *path,
-                     dbus_bool_t expected)
-{
-  DBusString p;
-
-  _dbus_string_init_const (&p, path);
-
-  if (_dbus_path_is_absolute (&p) != expected)
-    {
-      _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
-                  path, expected, _dbus_path_is_absolute (&p));
-      exit (1);
-    }
-}
-
-/**
- * Unit test for dbus-sysdeps.c.
- * 
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_sysdeps_test (void)
-{
-  DBusString str;
-  double val;
-  int pos;
   
-  check_dirname ("foo", ".");
-  check_dirname ("foo/bar", "foo");
-  check_dirname ("foo//bar", "foo");
-  check_dirname ("foo///bar", "foo");
-  check_dirname ("foo/bar/", "foo");
-  check_dirname ("foo//bar/", "foo");
-  check_dirname ("foo///bar/", "foo");
-  check_dirname ("foo/bar//", "foo");
-  check_dirname ("foo//bar////", "foo");
-  check_dirname ("foo///bar///////", "foo");
-  check_dirname ("/foo", "/");
-  check_dirname ("////foo", "/");
-  check_dirname ("/foo/bar", "/foo");
-  check_dirname ("/foo//bar", "/foo");
-  check_dirname ("/foo///bar", "/foo");
-  check_dirname ("/", "/");
-  check_dirname ("///", "/");
-  check_dirname ("", ".");  
-
-
-  _dbus_string_init_const (&str, "3.5");
-  if (!_dbus_string_parse_double (&str,
-                                 0, &val, &pos))
-    {
-      _dbus_warn ("Failed to parse double");
-      exit (1);
-    }
-  if (val != 3.5)
-    {
-      _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
-      exit (1);
-    }
-  if (pos != 3)
-    {
-      _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
-      exit (1);
-    }
+  *fd1 = fds[0];
+  *fd2 = fds[1];
 
-  _dbus_string_init_const (&str, "0xff");
-  if (!_dbus_string_parse_double (&str,
-                                 0, &val, &pos))
-    {
-      _dbus_warn ("Failed to parse double");
-      exit (1);
-    }
-  if (val != 0xff)
-    {
-      _dbus_warn ("Failed to parse 0xff correctly, got: %f", val);
-      exit (1);
-    }
-  if (pos != 4)
-    {
-      _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
-      exit (1);
-    }
+  _dbus_verbose ("full-duplex pipe %d <-> %d\n",
+                 *fd1, *fd2);
   
-  check_path_absolute ("/", TRUE);
-  check_path_absolute ("/foo", TRUE);
-  check_path_absolute ("", FALSE);
-  check_path_absolute ("foo", FALSE);
-  check_path_absolute ("foo/bar", FALSE);
-  
-  return TRUE;
+  return TRUE;  
+#else
+  _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
+  dbus_set_error (error, DBUS_ERROR_FAILED,
+                  "_dbus_full_duplex_pipe() not implemented on this OS");
+  return FALSE;
+#endif
 }
-#endif /* DBUS_BUILD_TESTS */
 
 /** @} end of sysdeps */
 
+/* tests in dbus-sysdeps-util.c */