• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-sysdeps-unix.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #define _GNU_SOURCE 
00026 
00027 #include "dbus-internals.h"
00028 #include "dbus-sysdeps.h"
00029 #include "dbus-sysdeps-unix.h"
00030 #include "dbus-threads.h"
00031 #include "dbus-protocol.h"
00032 #include "dbus-transport.h"
00033 #include "dbus-string.h"
00034 #include "dbus-userdb.h"
00035 #include "dbus-list.h"
00036 #include "dbus-credentials.h"
00037 
00038 #include <sys/types.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <signal.h>
00042 #include <unistd.h>
00043 #include <stdio.h>
00044 #include <fcntl.h>
00045 #include <sys/socket.h>
00046 #include <dirent.h>
00047 #include <sys/un.h>
00048 #include <pwd.h>
00049 #include <time.h>
00050 #include <locale.h>
00051 #include <sys/time.h>
00052 #include <sys/stat.h>
00053 #include <sys/wait.h>
00054 #include <netinet/in.h>
00055 #include <netdb.h>
00056 #include <grp.h>
00057 
00058 #ifdef HAVE_ERRNO_H
00059 #include <errno.h>
00060 #endif
00061 #ifdef HAVE_WRITEV
00062 #include <sys/uio.h>
00063 #endif
00064 #ifdef HAVE_POLL
00065 #include <sys/poll.h>
00066 #endif
00067 #ifdef HAVE_BACKTRACE
00068 #include <execinfo.h>
00069 #endif
00070 #ifdef HAVE_GETPEERUCRED
00071 #include <ucred.h>
00072 #endif
00073 
00074 #ifdef HAVE_ADT
00075 #include <bsm/adt.h>
00076 #endif
00077 
00078 #ifndef O_BINARY
00079 #define O_BINARY 0
00080 #endif
00081 
00082 #ifndef AI_ADDRCONFIG
00083 #define AI_ADDRCONFIG 0
00084 #endif
00085 
00086 #ifndef HAVE_SOCKLEN_T
00087 #define socklen_t int
00088 #endif
00089 
00090 static dbus_bool_t
00091 _dbus_open_socket (int              *fd_p,
00092                    int               domain,
00093                    int               type,
00094                    int               protocol,
00095                    DBusError        *error)
00096 {
00097   *fd_p = socket (domain, type, protocol);
00098   if (*fd_p >= 0)
00099     {
00100       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00101       return TRUE;
00102     }
00103   else
00104     {
00105       dbus_set_error(error,
00106                      _dbus_error_from_errno (errno),
00107                      "Failed to open socket: %s",
00108                      _dbus_strerror (errno));
00109       return FALSE;
00110     }
00111 }
00112 
00113 dbus_bool_t
00114 _dbus_open_tcp_socket (int              *fd,
00115                        DBusError        *error)
00116 {
00117   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00118 }
00119 
00127 dbus_bool_t
00128 _dbus_open_unix_socket (int              *fd,
00129                         DBusError        *error)
00130 {
00131   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00132 }
00133 
00142 dbus_bool_t 
00143 _dbus_close_socket (int               fd,
00144                     DBusError        *error)
00145 {
00146   return _dbus_close (fd, error);
00147 }
00148 
00158 int
00159 _dbus_read_socket (int               fd,
00160                    DBusString       *buffer,
00161                    int               count)
00162 {
00163   return _dbus_read (fd, buffer, count);
00164 }
00165 
00176 int
00177 _dbus_write_socket (int               fd,
00178                     const DBusString *buffer,
00179                     int               start,
00180                     int               len)
00181 {
00182   return _dbus_write (fd, buffer, start, len);
00183 }
00184 
00195 int
00196 _dbus_pipe_write (DBusPipe         *pipe,
00197                   const DBusString *buffer,
00198                   int               start,
00199                   int               len,
00200                   DBusError        *error)
00201 {
00202   int written;
00203   
00204   written = _dbus_write (pipe->fd_or_handle, buffer, start, len);
00205   if (written < 0)
00206     {
00207       dbus_set_error (error, DBUS_ERROR_FAILED,
00208                       "Writing to pipe: %s\n",
00209                       _dbus_strerror (errno));
00210     }
00211   return written;
00212 }
00213 
00221 int
00222 _dbus_pipe_close  (DBusPipe         *pipe,
00223                    DBusError        *error)
00224 {
00225   if (_dbus_close (pipe->fd_or_handle, error) < 0)
00226     {
00227       return -1;
00228     }
00229   else
00230     {
00231       _dbus_pipe_invalidate (pipe);
00232       return 0;
00233     }
00234 }
00235 
00249 int
00250 _dbus_write_socket_two (int               fd,
00251                         const DBusString *buffer1,
00252                         int               start1,
00253                         int               len1,
00254                         const DBusString *buffer2,
00255                         int               start2,
00256                         int               len2)
00257 {
00258   return _dbus_write_two (fd, buffer1, start1, len1,
00259                           buffer2, start2, len2);
00260 }
00261 
00262 
00279 int
00280 _dbus_read (int               fd,
00281             DBusString       *buffer,
00282             int               count)
00283 {
00284   int bytes_read;
00285   int start;
00286   char *data;
00287 
00288   _dbus_assert (count >= 0);
00289   
00290   start = _dbus_string_get_length (buffer);
00291 
00292   if (!_dbus_string_lengthen (buffer, count))
00293     {
00294       errno = ENOMEM;
00295       return -1;
00296     }
00297 
00298   data = _dbus_string_get_data_len (buffer, start, count);
00299 
00300  again:
00301   
00302   bytes_read = read (fd, data, count);
00303 
00304   if (bytes_read < 0)
00305     {
00306       if (errno == EINTR)
00307         goto again;
00308       else
00309         {
00310           /* put length back (note that this doesn't actually realloc anything) */
00311           _dbus_string_set_length (buffer, start);
00312           return -1;
00313         }
00314     }
00315   else
00316     {
00317       /* put length back (doesn't actually realloc) */
00318       _dbus_string_set_length (buffer, start + bytes_read);
00319 
00320 #if 0
00321       if (bytes_read > 0)
00322         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00323 #endif
00324       
00325       return bytes_read;
00326     }
00327 }
00328 
00339 int
00340 _dbus_write (int               fd,
00341              const DBusString *buffer,
00342              int               start,
00343              int               len)
00344 {
00345   const char *data;
00346   int bytes_written;
00347   
00348   data = _dbus_string_get_const_data_len (buffer, start, len);
00349   
00350  again:
00351 
00352   bytes_written = write (fd, data, len);
00353 
00354   if (bytes_written < 0 && errno == EINTR)
00355     goto again;
00356 
00357 #if 0
00358   if (bytes_written > 0)
00359     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00360 #endif
00361   
00362   return bytes_written;
00363 }
00364 
00385 int
00386 _dbus_write_two (int               fd,
00387                  const DBusString *buffer1,
00388                  int               start1,
00389                  int               len1,
00390                  const DBusString *buffer2,
00391                  int               start2,
00392                  int               len2)
00393 {
00394   _dbus_assert (buffer1 != NULL);
00395   _dbus_assert (start1 >= 0);
00396   _dbus_assert (start2 >= 0);
00397   _dbus_assert (len1 >= 0);
00398   _dbus_assert (len2 >= 0);
00399   
00400 #ifdef HAVE_WRITEV
00401   {
00402     struct iovec vectors[2];
00403     const char *data1;
00404     const char *data2;
00405     int bytes_written;
00406 
00407     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00408 
00409     if (buffer2 != NULL)
00410       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00411     else
00412       {
00413         data2 = NULL;
00414         start2 = 0;
00415         len2 = 0;
00416       }
00417    
00418     vectors[0].iov_base = (char*) data1;
00419     vectors[0].iov_len = len1;
00420     vectors[1].iov_base = (char*) data2;
00421     vectors[1].iov_len = len2;
00422 
00423   again:
00424    
00425     bytes_written = writev (fd,
00426                             vectors,
00427                             data2 ? 2 : 1);
00428 
00429     if (bytes_written < 0 && errno == EINTR)
00430       goto again;
00431    
00432     return bytes_written;
00433   }
00434 #else /* HAVE_WRITEV */
00435   {
00436     int ret1;
00437     
00438     ret1 = _dbus_write (fd, buffer1, start1, len1);
00439     if (ret1 == len1 && buffer2 != NULL)
00440       {
00441         ret2 = _dbus_write (fd, buffer2, start2, len2);
00442         if (ret2 < 0)
00443           ret2 = 0; /* we can't report an error as the first write was OK */
00444        
00445         return ret1 + ret2;
00446       }
00447     else
00448       return ret1;
00449   }
00450 #endif /* !HAVE_WRITEV */   
00451 }
00452 
00453 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00454 
00482 int
00483 _dbus_connect_unix_socket (const char     *path,
00484                            dbus_bool_t     abstract,
00485                            DBusError      *error)
00486 {
00487   int fd;
00488   size_t path_len;
00489   struct sockaddr_un addr;  
00490 
00491   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00492 
00493   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00494                  path, abstract);
00495   
00496   
00497   if (!_dbus_open_unix_socket (&fd, error))
00498     {
00499       _DBUS_ASSERT_ERROR_IS_SET(error);
00500       return -1;
00501     }
00502   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00503 
00504   _DBUS_ZERO (addr);
00505   addr.sun_family = AF_UNIX;
00506   path_len = strlen (path);
00507 
00508   if (abstract)
00509     {
00510 #ifdef HAVE_ABSTRACT_SOCKETS
00511       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00512       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00513 
00514       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00515         {
00516           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00517                       "Abstract socket name too long\n");
00518           _dbus_close (fd, NULL);
00519           return -1;
00520         }
00521         
00522       strncpy (&addr.sun_path[1], path, path_len);
00523       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00524 #else /* HAVE_ABSTRACT_SOCKETS */
00525       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00526                       "Operating system does not support abstract socket namespace\n");
00527       _dbus_close (fd, NULL);
00528       return -1;
00529 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00530     }
00531   else
00532     {
00533       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00534         {
00535           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00536                       "Socket name too long\n");
00537           _dbus_close (fd, NULL);
00538           return -1;
00539         }
00540 
00541       strncpy (addr.sun_path, path, path_len);
00542     }
00543   
00544   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00545     {      
00546       dbus_set_error (error,
00547                       _dbus_error_from_errno (errno),
00548                       "Failed to connect to socket %s: %s",
00549                       path, _dbus_strerror (errno));
00550 
00551       _dbus_close (fd, NULL);
00552       fd = -1;
00553       
00554       return -1;
00555     }
00556 
00557   if (!_dbus_set_fd_nonblocking (fd, error))
00558     {
00559       _DBUS_ASSERT_ERROR_IS_SET (error);
00560       
00561       _dbus_close (fd, NULL);
00562       fd = -1;
00563 
00564       return -1;
00565     }
00566 
00567   return fd;
00568 }
00569 
00579 static dbus_bool_t
00580 _dbus_set_local_creds (int fd, dbus_bool_t on)
00581 {
00582   dbus_bool_t retval = TRUE;
00583 
00584 #if defined(HAVE_CMSGCRED)
00585   /* NOOP just to make sure only one codepath is used 
00586    *      and to prefer CMSGCRED
00587    */
00588 #elif defined(LOCAL_CREDS) 
00589   int val = on ? 1 : 0;
00590   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00591     {
00592       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00593       retval = FALSE;
00594     }
00595   else
00596     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00597                    on ? "enabled" : "disabled", fd);
00598 #endif
00599 
00600   return retval;
00601 }
00602 
00618 int
00619 _dbus_listen_unix_socket (const char     *path,
00620                           dbus_bool_t     abstract,
00621                           DBusError      *error)
00622 {
00623   int listen_fd;
00624   struct sockaddr_un addr;
00625   size_t path_len;
00626   unsigned int reuseaddr;
00627 
00628   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00629 
00630   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00631                  path, abstract);
00632   
00633   if (!_dbus_open_unix_socket (&listen_fd, error))
00634     {
00635       _DBUS_ASSERT_ERROR_IS_SET(error);
00636       return -1;
00637     }
00638   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00639 
00640   _DBUS_ZERO (addr);
00641   addr.sun_family = AF_UNIX;
00642   path_len = strlen (path);
00643   
00644   if (abstract)
00645     {
00646 #ifdef HAVE_ABSTRACT_SOCKETS
00647       /* remember that abstract names aren't nul-terminated so we rely
00648        * on sun_path being filled in with zeroes above.
00649        */
00650       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00651       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00652 
00653       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00654         {
00655           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00656                       "Abstract socket name too long\n");
00657           _dbus_close (listen_fd, NULL);
00658           return -1;
00659         }
00660       
00661       strncpy (&addr.sun_path[1], path, path_len);
00662       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00663 #else /* HAVE_ABSTRACT_SOCKETS */
00664       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00665                       "Operating system does not support abstract socket namespace\n");
00666       _dbus_close (listen_fd, NULL);
00667       return -1;
00668 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00669     }
00670   else
00671     {
00672       /* Discussed security implications of this with Nalin,
00673        * and we couldn't think of where it would kick our ass, but
00674        * it still seems a bit sucky. It also has non-security suckage;
00675        * really we'd prefer to exit if the socket is already in use.
00676        * But there doesn't seem to be a good way to do this.
00677        *
00678        * Just to be extra careful, I threw in the stat() - clearly
00679        * the stat() can't *fix* any security issue, but it at least
00680        * avoids inadvertent/accidental data loss.
00681        */
00682       {
00683         struct stat sb;
00684 
00685         if (stat (path, &sb) == 0 &&
00686             S_ISSOCK (sb.st_mode))
00687           unlink (path);
00688       }
00689 
00690       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00691         {
00692           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00693                       "Abstract socket name too long\n");
00694           _dbus_close (listen_fd, NULL);
00695           return -1;
00696         }
00697         
00698       strncpy (addr.sun_path, path, path_len);
00699     }
00700 
00701   reuseaddr = 1;
00702   if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
00703     {
00704       dbus_set_error (error, _dbus_error_from_errno (errno),
00705                       "Failed to set socket option\"%s\": %s",
00706                       path, _dbus_strerror (errno));
00707     }
00708 
00709   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00710     {
00711       dbus_set_error (error, _dbus_error_from_errno (errno),
00712                       "Failed to bind socket \"%s\": %s",
00713                       path, _dbus_strerror (errno));
00714       _dbus_close (listen_fd, NULL);
00715       return -1;
00716     }
00717 
00718   if (listen (listen_fd, 30 /* backlog */) < 0)
00719     {
00720       dbus_set_error (error, _dbus_error_from_errno (errno),
00721                       "Failed to listen on socket \"%s\": %s",
00722                       path, _dbus_strerror (errno));
00723       _dbus_close (listen_fd, NULL);
00724       return -1;
00725     }
00726 
00727   if (!_dbus_set_local_creds (listen_fd, TRUE))
00728     {
00729       dbus_set_error (error, _dbus_error_from_errno (errno),
00730                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00731                       path, _dbus_strerror (errno));
00732       close (listen_fd);
00733       return -1;
00734     }
00735 
00736   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00737     {
00738       _DBUS_ASSERT_ERROR_IS_SET (error);
00739       _dbus_close (listen_fd, NULL);
00740       return -1;
00741     }
00742   
00743   /* Try opening up the permissions, but if we can't, just go ahead
00744    * and continue, maybe it will be good enough.
00745    */
00746   if (!abstract && chmod (path, 0777) < 0)
00747     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00748                 path);
00749   
00750   return listen_fd;
00751 }
00752 
00764 int
00765 _dbus_connect_tcp_socket (const char     *host,
00766                           const char     *port,
00767                           const char     *family,
00768                           DBusError      *error)
00769 {
00770   int fd = -1, res;
00771   struct addrinfo hints;
00772   struct addrinfo *ai, *tmp;
00773 
00774   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00775 
00776   if (!_dbus_open_tcp_socket (&fd, error))
00777     {
00778       _DBUS_ASSERT_ERROR_IS_SET(error);
00779       return -1;
00780     }
00781 
00782   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00783 
00784   _DBUS_ZERO (hints);
00785 
00786   if (!family)
00787     hints.ai_family = AF_UNSPEC;
00788   else if (!strcmp(family, "ipv4"))
00789     hints.ai_family = AF_INET;
00790   else if (!strcmp(family, "ipv6"))
00791     hints.ai_family = AF_INET6;
00792   else
00793     {
00794       dbus_set_error (error,
00795                       _dbus_error_from_errno (errno),
00796                       "Unknown address family %s", family);
00797       return -1;
00798     }
00799   hints.ai_protocol = IPPROTO_TCP;
00800   hints.ai_socktype = SOCK_STREAM;
00801   hints.ai_flags = AI_ADDRCONFIG;
00802 
00803   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00804     {
00805       dbus_set_error (error,
00806                       _dbus_error_from_errno (errno),
00807                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00808                       host, port, gai_strerror(res), res);
00809       _dbus_close (fd, NULL);
00810       return -1;
00811     }
00812 
00813   tmp = ai;
00814   while (tmp)
00815     {
00816       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00817         {
00818           freeaddrinfo(ai);
00819           _DBUS_ASSERT_ERROR_IS_SET(error);
00820           return -1;
00821         }
00822       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00823 
00824       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00825         {
00826           _dbus_close(fd, NULL);
00827           fd = -1;
00828           tmp = tmp->ai_next;
00829           continue;
00830         }
00831 
00832       break;
00833     }
00834   freeaddrinfo(ai);
00835 
00836   if (fd == -1)
00837     {
00838       dbus_set_error (error,
00839                       _dbus_error_from_errno (errno),
00840                       "Failed to connect to socket \"%s:%s\" %s",
00841                       host, port, _dbus_strerror(errno));
00842       return -1;
00843     }
00844 
00845 
00846   if (!_dbus_set_fd_nonblocking (fd, error))
00847     {
00848       _dbus_close (fd, NULL);
00849       fd = -1;
00850 
00851       return -1;
00852     }
00853 
00854   return fd;
00855 }
00856 
00871 int
00872 _dbus_listen_tcp_socket (const char     *host,
00873                          const char     *port,
00874                          const char     *family,
00875                          DBusString     *retport,
00876                          int           **fds_p,
00877                          DBusError      *error)
00878 {
00879   int nlisten_fd = 0, *listen_fd = NULL, res, i;
00880   struct addrinfo hints;
00881   struct addrinfo *ai, *tmp;
00882   unsigned int reuseaddr;
00883 
00884   *fds_p = NULL;
00885   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00886 
00887   _DBUS_ZERO (hints);
00888 
00889   if (!family)
00890     hints.ai_family = AF_UNSPEC;
00891   else if (!strcmp(family, "ipv4"))
00892     hints.ai_family = AF_INET;
00893   else if (!strcmp(family, "ipv6"))
00894     hints.ai_family = AF_INET6;
00895   else
00896     {
00897       dbus_set_error (error,
00898                       _dbus_error_from_errno (errno),
00899                       "Unknown address family %s", family);
00900       return -1;
00901     }
00902 
00903   hints.ai_protocol = IPPROTO_TCP;
00904   hints.ai_socktype = SOCK_STREAM;
00905   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00906 
00907  redo_lookup_with_port:
00908   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00909     {
00910       dbus_set_error (error,
00911                       _dbus_error_from_errno (errno),
00912                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00913                       host ? host : "*", port, gai_strerror(res), res);
00914       return -1;
00915     }
00916 
00917   tmp = ai;
00918   while (tmp)
00919     {
00920       int fd = -1, *newlisten_fd;
00921       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00922         {
00923           _DBUS_ASSERT_ERROR_IS_SET(error);
00924           goto failed;
00925         }
00926       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00927 
00928       reuseaddr = 1;
00929       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
00930         {
00931           dbus_set_error (error, _dbus_error_from_errno (errno),
00932                           "Failed to set socket option \"%s:%s\": %s",
00933                           host ? host : "*", port, _dbus_strerror (errno));
00934         }
00935 
00936       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00937         {
00938           _dbus_close(fd, NULL);
00939           if (errno == EADDRINUSE)
00940             {
00941               /* Depending on kernel policy, it may or may not
00942                  be neccessary to bind to both IPv4 & 6 addresses
00943                  so ignore EADDRINUSE here */
00944               tmp = tmp->ai_next;
00945               continue;
00946             }
00947           dbus_set_error (error, _dbus_error_from_errno (errno),
00948                           "Failed to bind socket \"%s:%s\": %s",
00949                           host ? host : "*", port, _dbus_strerror (errno));
00950           goto failed;
00951         }
00952 
00953       if (listen (fd, 30 /* backlog */) < 0)
00954         {
00955           _dbus_close (fd, NULL);
00956           dbus_set_error (error, _dbus_error_from_errno (errno),
00957                           "Failed to listen on socket \"%s:%s\": %s",
00958                           host ? host : "*", port, _dbus_strerror (errno));
00959           goto failed;
00960         }
00961 
00962       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00963       if (!newlisten_fd)
00964         {
00965           _dbus_close (fd, NULL);
00966           dbus_set_error (error, _dbus_error_from_errno (errno),
00967                           "Failed to allocate file handle array: %s",
00968                           _dbus_strerror (errno));
00969           goto failed;
00970         }
00971       listen_fd = newlisten_fd;
00972       listen_fd[nlisten_fd] = fd;
00973       nlisten_fd++;
00974 
00975       if (!_dbus_string_get_length(retport))
00976         {
00977           /* If the user didn't specify a port, or used 0, then
00978              the kernel chooses a port. After the first address
00979              is bound to, we need to force all remaining addresses
00980              to use the same port */
00981           if (!port || !strcmp(port, "0"))
00982             {
00983               struct sockaddr_storage addr;
00984               socklen_t addrlen;
00985               char portbuf[50];
00986 
00987               addrlen = sizeof(addr);
00988               getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00989 
00990               if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00991                                      portbuf, sizeof(portbuf),
00992                                      NI_NUMERICHOST)) != 0)
00993                 {
00994                   dbus_set_error (error, _dbus_error_from_errno (errno),
00995                                   "Failed to resolve port \"%s:%s\": %s (%s)",
00996                                   host ? host : "*", port, gai_strerror(res), res);
00997                   goto failed;
00998                 }
00999               if (!_dbus_string_append(retport, portbuf))
01000                 {
01001                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01002                   goto failed;
01003                 }
01004 
01005               /* Release current address list & redo lookup */
01006               port = _dbus_string_get_const_data(retport);
01007               freeaddrinfo(ai);
01008               goto redo_lookup_with_port;
01009             }
01010           else
01011             {
01012               if (!_dbus_string_append(retport, port))
01013                 {
01014                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01015                     goto failed;
01016                 }
01017             }
01018         }
01019 
01020       tmp = tmp->ai_next;
01021     }
01022   freeaddrinfo(ai);
01023   ai = NULL;
01024 
01025   if (!nlisten_fd)
01026     {
01027       errno = EADDRINUSE;
01028       dbus_set_error (error, _dbus_error_from_errno (errno),
01029                       "Failed to bind socket \"%s:%s\": %s",
01030                       host ? host : "*", port, _dbus_strerror (errno));
01031       return -1;
01032     }
01033 
01034   for (i = 0 ; i < nlisten_fd ; i++)
01035     {
01036       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01037         {
01038           goto failed;
01039         }
01040     }
01041 
01042   *fds_p = listen_fd;
01043 
01044   return nlisten_fd;
01045 
01046  failed:
01047   if (ai)
01048     freeaddrinfo(ai);
01049   for (i = 0 ; i < nlisten_fd ; i++)
01050     _dbus_close(listen_fd[i], NULL);
01051   dbus_free(listen_fd);
01052   return -1;
01053 }
01054 
01055 static dbus_bool_t
01056 write_credentials_byte (int             server_fd,
01057                         DBusError      *error)
01058 {
01059   int bytes_written;
01060   char buf[1] = { '\0' };
01061 #if defined(HAVE_CMSGCRED) 
01062   union {
01063           struct cmsghdr hdr;
01064           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01065   } cmsg;
01066   struct iovec iov;
01067   struct msghdr msg;
01068   iov.iov_base = buf;
01069   iov.iov_len = 1;
01070 
01071   memset (&msg, 0, sizeof (msg));
01072   msg.msg_iov = &iov;
01073   msg.msg_iovlen = 1;
01074 
01075   msg.msg_control = (caddr_t) &cmsg;
01076   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01077   memset (&cmsg, 0, sizeof (cmsg));
01078   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01079   cmsg.hdr.cmsg_level = SOL_SOCKET;
01080   cmsg.hdr.cmsg_type = SCM_CREDS;
01081 #endif
01082 
01083   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01084   
01085  again:
01086 
01087 #if defined(HAVE_CMSGCRED) 
01088   bytes_written = sendmsg (server_fd, &msg, 0);
01089 #else
01090   bytes_written = write (server_fd, buf, 1);
01091 #endif
01092 
01093   if (bytes_written < 0 && errno == EINTR)
01094     goto again;
01095 
01096   if (bytes_written < 0)
01097     {
01098       dbus_set_error (error, _dbus_error_from_errno (errno),
01099                       "Failed to write credentials byte: %s",
01100                      _dbus_strerror (errno));
01101       return FALSE;
01102     }
01103   else if (bytes_written == 0)
01104     {
01105       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01106                       "wrote zero bytes writing credentials byte");
01107       return FALSE;
01108     }
01109   else
01110     {
01111       _dbus_assert (bytes_written == 1);
01112       _dbus_verbose ("wrote credentials byte\n");
01113       return TRUE;
01114     }
01115 }
01116 
01138 dbus_bool_t
01139 _dbus_read_credentials_socket  (int              client_fd,
01140                                 DBusCredentials *credentials,
01141                                 DBusError       *error)
01142 {
01143   struct msghdr msg;
01144   struct iovec iov;
01145   char buf;
01146   dbus_uid_t uid_read;
01147   dbus_pid_t pid_read;
01148   int bytes_read;
01149   
01150 #ifdef HAVE_CMSGCRED 
01151   union {
01152     struct cmsghdr hdr;
01153     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01154   } cmsg;
01155 
01156 #elif defined(LOCAL_CREDS)
01157   struct {
01158     struct cmsghdr hdr;
01159     struct sockcred cred;
01160   } cmsg;
01161 #endif
01162 
01163   uid_read = DBUS_UID_UNSET;
01164   pid_read = DBUS_PID_UNSET;
01165 
01166   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01167   
01168   /* The POSIX spec certainly doesn't promise this, but
01169    * we need these assertions to fail as soon as we're wrong about
01170    * it so we can do the porting fixups
01171    */
01172   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01173   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01174   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01175 
01176   _dbus_credentials_clear (credentials);
01177 
01178   /* Systems supporting LOCAL_CREDS are configured to have this feature
01179    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01180    * the connection.  Therefore, the received message must carry the
01181    * credentials information without doing anything special.
01182    */
01183 
01184   iov.iov_base = &buf;
01185   iov.iov_len = 1;
01186 
01187   memset (&msg, 0, sizeof (msg));
01188   msg.msg_iov = &iov;
01189   msg.msg_iovlen = 1;
01190 
01191 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01192   memset (&cmsg, 0, sizeof (cmsg));
01193   msg.msg_control = (caddr_t) &cmsg;
01194   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01195 #endif
01196 
01197  again:
01198   bytes_read = recvmsg (client_fd, &msg, 0);
01199 
01200   if (bytes_read < 0)
01201     {
01202       if (errno == EINTR)
01203         goto again;
01204 
01205       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01206        * normally only call read_credentials if the socket was ready
01207        * for reading
01208        */
01209       
01210       dbus_set_error (error, _dbus_error_from_errno (errno),
01211                       "Failed to read credentials byte: %s",
01212                       _dbus_strerror (errno));
01213       return FALSE;
01214     }
01215   else if (bytes_read == 0)
01216     {
01217       /* this should not happen unless we are using recvmsg wrong,
01218        * so is essentially here for paranoia
01219        */
01220       dbus_set_error (error, DBUS_ERROR_FAILED,
01221                       "Failed to read credentials byte (zero-length read)");
01222       return FALSE;
01223     }
01224   else if (buf != '\0')
01225     {
01226       dbus_set_error (error, DBUS_ERROR_FAILED,
01227                       "Credentials byte was not nul");
01228       return FALSE;
01229     }
01230 
01231 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01232   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01233                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01234     {
01235       dbus_set_error (error, DBUS_ERROR_FAILED,
01236                       "Message from recvmsg() was not SCM_CREDS");
01237       return FALSE;
01238     }
01239 #endif
01240 
01241   _dbus_verbose ("read credentials byte\n");
01242 
01243   {
01244 #ifdef SO_PEERCRED
01245     struct ucred cr;   
01246     int cr_len = sizeof (cr);
01247     
01248     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01249         cr_len == sizeof (cr))
01250       {
01251         pid_read = cr.pid;
01252         uid_read = cr.uid;
01253       }
01254     else
01255       {
01256         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01257                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01258       }
01259 #elif defined(HAVE_CMSGCRED)
01260     struct cmsgcred *cred;
01261 
01262     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01263     pid_read = cred->cmcred_pid;
01264     uid_read = cred->cmcred_euid;
01265 #elif defined(LOCAL_CREDS)
01266     pid_read = DBUS_PID_UNSET;
01267     uid_read = cmsg.cred.sc_uid;
01268     /* Since we have already got the credentials from this socket, we can
01269      * disable its LOCAL_CREDS flag if it was ever set. */
01270     _dbus_set_local_creds (client_fd, FALSE);
01271 #elif defined(HAVE_GETPEEREID)
01272     uid_t euid;
01273     gid_t egid;
01274     if (getpeereid (client_fd, &euid, &egid) == 0)
01275       {
01276         uid_read = euid;
01277       }
01278     else
01279       {
01280         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01281       }
01282 #elif defined(HAVE_GETPEERUCRED)
01283     ucred_t * ucred = NULL;
01284     if (getpeerucred (client_fd, &ucred) == 0)
01285       {
01286         pid_read = ucred_getpid (ucred);
01287         uid_read = ucred_geteuid (ucred);
01288 #ifdef HAVE_ADT
01289         /* generate audit session data based on socket ucred */
01290         adt_session_data_t *adth = NULL;
01291         adt_export_data_t *data = NULL;
01292         size_t size = 0;
01293         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01294           {
01295             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01296           }
01297         else 
01298           {
01299             if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 
01300               {
01301                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01302               }
01303             else
01304               {
01305                 size = adt_export_session_data (adth, &data);
01306                 if (size <= 0)
01307                   {
01308                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01309                   }
01310                 else
01311                   {
01312                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01313                     free (data);
01314                   }
01315               }
01316             (void) adt_end_session (adth);
01317           }
01318 #endif /* HAVE_ADT */
01319       }
01320     else
01321       {
01322         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01323       }
01324     if (ucred != NULL)
01325       ucred_free (ucred);
01326 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01327     _dbus_verbose ("Socket credentials not supported on this OS\n");
01328 #endif
01329   }
01330 
01331   _dbus_verbose ("Credentials:"
01332                  "  pid "DBUS_PID_FORMAT
01333                  "  uid "DBUS_UID_FORMAT
01334                  "\n",
01335                  pid_read,
01336                  uid_read);
01337 
01338   if (pid_read != DBUS_PID_UNSET)
01339     {
01340       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01341         {
01342           _DBUS_SET_OOM (error);
01343           return FALSE;
01344         }
01345     }
01346 
01347   if (uid_read != DBUS_UID_UNSET)
01348     {
01349       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01350         {
01351           _DBUS_SET_OOM (error);
01352           return FALSE;
01353         }
01354     }
01355   
01356   return TRUE;
01357 }
01358 
01376 dbus_bool_t
01377 _dbus_send_credentials_socket  (int              server_fd,
01378                                 DBusError       *error)
01379 {
01380   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01381   
01382   if (write_credentials_byte (server_fd, error))
01383     return TRUE;
01384   else
01385     return FALSE;
01386 }
01387 
01395 int
01396 _dbus_accept  (int listen_fd)
01397 {
01398   int client_fd;
01399   struct sockaddr addr;
01400   socklen_t addrlen;
01401 
01402   addrlen = sizeof (addr);
01403   
01404  retry:
01405   client_fd = accept (listen_fd, &addr, &addrlen);
01406   
01407   if (client_fd < 0)
01408     {
01409       if (errno == EINTR)
01410         goto retry;
01411     }
01412 
01413   _dbus_verbose ("client fd %d accepted\n", client_fd);
01414   
01415   return client_fd;
01416 }
01417 
01426 dbus_bool_t
01427 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01428 {
01429   const char *directory;
01430   struct stat sb;
01431         
01432   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01433     
01434   directory = _dbus_string_get_const_data (dir);
01435         
01436   if (stat (directory, &sb) < 0)
01437     {
01438       dbus_set_error (error, _dbus_error_from_errno (errno),
01439                       "%s", _dbus_strerror (errno));
01440    
01441       return FALSE;
01442     }
01443     
01444   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01445       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01446     {
01447       dbus_set_error (error, DBUS_ERROR_FAILED,
01448                      "%s directory is not private to the user", directory);
01449       return FALSE;
01450     }
01451     
01452   return TRUE;
01453 }
01454 
01455 static dbus_bool_t
01456 fill_user_info_from_passwd (struct passwd *p,
01457                             DBusUserInfo  *info,
01458                             DBusError     *error)
01459 {
01460   _dbus_assert (p->pw_name != NULL);
01461   _dbus_assert (p->pw_dir != NULL);
01462   
01463   info->uid = p->pw_uid;
01464   info->primary_gid = p->pw_gid;
01465   info->username = _dbus_strdup (p->pw_name);
01466   info->homedir = _dbus_strdup (p->pw_dir);
01467   
01468   if (info->username == NULL ||
01469       info->homedir == NULL)
01470     {
01471       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01472       return FALSE;
01473     }
01474 
01475   return TRUE;
01476 }
01477 
01478 static dbus_bool_t
01479 fill_user_info (DBusUserInfo       *info,
01480                 dbus_uid_t          uid,
01481                 const DBusString   *username,
01482                 DBusError          *error)
01483 {
01484   const char *username_c;
01485   
01486   /* exactly one of username/uid provided */
01487   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01488   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01489 
01490   info->uid = DBUS_UID_UNSET;
01491   info->primary_gid = DBUS_GID_UNSET;
01492   info->group_ids = NULL;
01493   info->n_group_ids = 0;
01494   info->username = NULL;
01495   info->homedir = NULL;
01496   
01497   if (username != NULL)
01498     username_c = _dbus_string_get_const_data (username);
01499   else
01500     username_c = NULL;
01501 
01502   /* For now assuming that the getpwnam() and getpwuid() flavors
01503    * are always symmetrical, if not we have to add more configure
01504    * checks
01505    */
01506   
01507 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01508   {
01509     struct passwd *p;
01510     int result;
01511     size_t buflen;
01512     char *buf;
01513     struct passwd p_str;
01514 
01515     /* retrieve maximum needed size for buf */
01516     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01517 
01518     /* sysconf actually returns a long, but everything else expects size_t,
01519      * so just recast here.
01520      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
01521      */
01522     if ((long) buflen <= 0)
01523       buflen = 1024;
01524 
01525     result = -1;
01526     while (1)
01527       {
01528         buf = dbus_malloc (buflen);
01529         if (buf == NULL)
01530           {
01531             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01532             return FALSE;
01533           }
01534 
01535         p = NULL;
01536 #ifdef HAVE_POSIX_GETPWNAM_R
01537         if (uid != DBUS_UID_UNSET)
01538           result = getpwuid_r (uid, &p_str, buf, buflen,
01539                                &p);
01540         else
01541           result = getpwnam_r (username_c, &p_str, buf, buflen,
01542                                &p);
01543 #else
01544         if (uid != DBUS_UID_UNSET)
01545           p = getpwuid_r (uid, &p_str, buf, buflen);
01546         else
01547           p = getpwnam_r (username_c, &p_str, buf, buflen);
01548         result = 0;
01549 #endif /* !HAVE_POSIX_GETPWNAM_R */
01550         //Try a bigger buffer if ERANGE was returned
01551         if (result == ERANGE && buflen < 512 * 1024)
01552           {
01553             dbus_free (buf);
01554             buflen *= 2;
01555           }
01556         else
01557           {
01558             break;
01559           }
01560       }
01561     if (result == 0 && p == &p_str)
01562       {
01563         if (!fill_user_info_from_passwd (p, info, error))
01564           {
01565             dbus_free (buf);
01566             return FALSE;
01567           }
01568         dbus_free (buf);
01569       }
01570     else
01571       {
01572         dbus_set_error (error, _dbus_error_from_errno (errno),
01573                         "User \"%s\" unknown or no memory to allocate password entry\n",
01574                         username_c ? username_c : "???");
01575         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01576         dbus_free (buf);
01577         return FALSE;
01578       }
01579   }
01580 #else /* ! HAVE_GETPWNAM_R */
01581   {
01582     /* I guess we're screwed on thread safety here */
01583     struct passwd *p;
01584 
01585     if (uid != DBUS_UID_UNSET)
01586       p = getpwuid (uid);
01587     else
01588       p = getpwnam (username_c);
01589 
01590     if (p != NULL)
01591       {
01592         if (!fill_user_info_from_passwd (p, info, error))
01593           {
01594             return FALSE;
01595           }
01596       }
01597     else
01598       {
01599         dbus_set_error (error, _dbus_error_from_errno (errno),
01600                         "User \"%s\" unknown or no memory to allocate password entry\n",
01601                         username_c ? username_c : "???");
01602         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01603         return FALSE;
01604       }
01605   }
01606 #endif  /* ! HAVE_GETPWNAM_R */
01607 
01608   /* Fill this in so we can use it to get groups */
01609   username_c = info->username;
01610   
01611 #ifdef HAVE_GETGROUPLIST
01612   {
01613     gid_t *buf;
01614     int buf_count;
01615     int i;
01616     int initial_buf_count;
01617 
01618     initial_buf_count = 17;
01619     buf_count = initial_buf_count;
01620     buf = dbus_new (gid_t, buf_count);
01621     if (buf == NULL)
01622       {
01623         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01624         goto failed;
01625       }
01626     
01627     if (getgrouplist (username_c,
01628                       info->primary_gid,
01629                       buf, &buf_count) < 0)
01630       {
01631         gid_t *new;
01632         /* Presumed cause of negative return code: buf has insufficient
01633            entries to hold the entire group list. The Linux behavior in this
01634            case is to pass back the actual number of groups in buf_count, but
01635            on Mac OS X 10.5, buf_count is unhelpfully left alone.
01636            So as a hack, try to help out a bit by guessing a larger
01637            number of groups, within reason.. might still fail, of course,
01638            but we can at least print a more informative message.  I looked up
01639            the "right way" to do this by downloading Apple's own source code
01640            for the "id" command, and it turns out that they use an
01641            undocumented library function getgrouplist_2 (!) which is not
01642            declared in any header in /usr/include (!!). That did not seem
01643            like the way to go here.  
01644         */
01645         if (buf_count == initial_buf_count) 
01646           { 
01647             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
01648           }
01649         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01650         if (new == NULL)
01651           {
01652             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01653             dbus_free (buf);
01654             goto failed;
01655           }
01656         
01657         buf = new;
01658 
01659         errno = 0;
01660         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01661           {
01662             if (errno == 0)
01663               {
01664                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
01665                             username_c, buf_count, buf_count);
01666               } 
01667             else
01668               {
01669                 dbus_set_error (error,
01670                                 _dbus_error_from_errno (errno),
01671                                 "Failed to get groups for username \"%s\" primary GID "
01672                                 DBUS_GID_FORMAT ": %s\n",
01673                                 username_c, info->primary_gid,
01674                                 _dbus_strerror (errno));
01675                 dbus_free (buf);
01676                 goto failed;
01677               }
01678           }
01679       }
01680 
01681     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01682     if (info->group_ids == NULL)
01683       {
01684         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01685         dbus_free (buf);
01686         goto failed;
01687       }
01688     
01689     for (i = 0; i < buf_count; ++i)
01690       info->group_ids[i] = buf[i];
01691 
01692     info->n_group_ids = buf_count;
01693     
01694     dbus_free (buf);
01695   }
01696 #else  /* HAVE_GETGROUPLIST */
01697   {
01698     /* We just get the one group ID */
01699     info->group_ids = dbus_new (dbus_gid_t, 1);
01700     if (info->group_ids == NULL)
01701       {
01702         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01703         goto failed;
01704       }
01705 
01706     info->n_group_ids = 1;
01707 
01708     (info->group_ids)[0] = info->primary_gid;
01709   }
01710 #endif /* HAVE_GETGROUPLIST */
01711 
01712   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01713   
01714   return TRUE;
01715   
01716  failed:
01717   _DBUS_ASSERT_ERROR_IS_SET (error);
01718   return FALSE;
01719 }
01720 
01729 dbus_bool_t
01730 _dbus_user_info_fill (DBusUserInfo     *info,
01731                       const DBusString *username,
01732                       DBusError        *error)
01733 {
01734   return fill_user_info (info, DBUS_UID_UNSET,
01735                          username, error);
01736 }
01737 
01746 dbus_bool_t
01747 _dbus_user_info_fill_uid (DBusUserInfo *info,
01748                           dbus_uid_t    uid,
01749                           DBusError    *error)
01750 {
01751   return fill_user_info (info, uid,
01752                          NULL, error);
01753 }
01754 
01762 dbus_bool_t
01763 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01764 {
01765   /* The POSIX spec certainly doesn't promise this, but
01766    * we need these assertions to fail as soon as we're wrong about
01767    * it so we can do the porting fixups
01768    */
01769   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01770   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01771   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01772 
01773   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01774     return FALSE;
01775   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01776     return FALSE;
01777 
01778   return TRUE;
01779 }
01780 
01792 dbus_bool_t
01793 _dbus_append_user_from_current_process (DBusString *str)
01794 {
01795   return _dbus_string_append_uint (str,
01796                                    _dbus_geteuid ());
01797 }
01798 
01803 dbus_pid_t
01804 _dbus_getpid (void)
01805 {
01806   return getpid ();
01807 }
01808 
01812 dbus_uid_t
01813 _dbus_getuid (void)
01814 {
01815   return getuid ();
01816 }
01817 
01821 dbus_uid_t
01822 _dbus_geteuid (void)
01823 {
01824   return geteuid ();
01825 }
01826 
01833 unsigned long
01834 _dbus_pid_for_log (void)
01835 {
01836   return getpid ();
01837 }
01838 
01846 dbus_bool_t
01847 _dbus_parse_uid (const DBusString      *uid_str,
01848                  dbus_uid_t            *uid)
01849 {
01850   int end;
01851   long val;
01852   
01853   if (_dbus_string_get_length (uid_str) == 0)
01854     {
01855       _dbus_verbose ("UID string was zero length\n");
01856       return FALSE;
01857     }
01858 
01859   val = -1;
01860   end = 0;
01861   if (!_dbus_string_parse_int (uid_str, 0, &val,
01862                                &end))
01863     {
01864       _dbus_verbose ("could not parse string as a UID\n");
01865       return FALSE;
01866     }
01867   
01868   if (end != _dbus_string_get_length (uid_str))
01869     {
01870       _dbus_verbose ("string contained trailing stuff after UID\n");
01871       return FALSE;
01872     }
01873 
01874   *uid = val;
01875 
01876   return TRUE;
01877 }
01878 
01879 
01880 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01881 
01882 #if DBUS_USE_ATOMIC_INT_486_COND
01883 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01884 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01885 static inline dbus_int32_t
01886 atomic_exchange_and_add (DBusAtomic            *atomic,
01887                          volatile dbus_int32_t  val)
01888 {
01889   register dbus_int32_t result;
01890 
01891   __asm__ __volatile__ ("lock; xaddl %0,%1"
01892                         : "=r" (result), "=m" (atomic->value)
01893                         : "0" (val), "m" (atomic->value));
01894   return result;
01895 }
01896 #endif
01897 
01906 dbus_int32_t
01907 _dbus_atomic_inc (DBusAtomic *atomic)
01908 {
01909 #if DBUS_USE_ATOMIC_INT_486_COND
01910   return atomic_exchange_and_add (atomic, 1);
01911 #else
01912   dbus_int32_t res;
01913   _DBUS_LOCK (atomic);
01914   res = atomic->value;
01915   atomic->value += 1;
01916   _DBUS_UNLOCK (atomic);
01917   return res;
01918 #endif
01919 }
01920 
01929 dbus_int32_t
01930 _dbus_atomic_dec (DBusAtomic *atomic)
01931 {
01932 #if DBUS_USE_ATOMIC_INT_486_COND
01933   return atomic_exchange_and_add (atomic, -1);
01934 #else
01935   dbus_int32_t res;
01936   
01937   _DBUS_LOCK (atomic);
01938   res = atomic->value;
01939   atomic->value -= 1;
01940   _DBUS_UNLOCK (atomic);
01941   return res;
01942 #endif
01943 }
01944 
01945 #ifdef DBUS_BUILD_TESTS
01946 
01949 dbus_gid_t
01950 _dbus_getgid (void)
01951 {
01952   return getgid ();
01953 }
01954 #endif
01955 
01964 int
01965 _dbus_poll (DBusPollFD *fds,
01966             int         n_fds,
01967             int         timeout_milliseconds)
01968 {
01969 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01970   /* This big thing is a constant expression and should get optimized
01971    * out of existence. So it's more robust than a configure check at
01972    * no cost.
01973    */
01974   if (_DBUS_POLLIN == POLLIN &&
01975       _DBUS_POLLPRI == POLLPRI &&
01976       _DBUS_POLLOUT == POLLOUT &&
01977       _DBUS_POLLERR == POLLERR &&
01978       _DBUS_POLLHUP == POLLHUP &&
01979       _DBUS_POLLNVAL == POLLNVAL &&
01980       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01981       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01982       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01983       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01984       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01985       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01986       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01987     {
01988       return poll ((struct pollfd*) fds,
01989                    n_fds, 
01990                    timeout_milliseconds);
01991     }
01992   else
01993     {
01994       /* We have to convert the DBusPollFD to an array of
01995        * struct pollfd, poll, and convert back.
01996        */
01997       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01998       return -1;
01999     }
02000 #else /* ! HAVE_POLL */
02001 
02002   fd_set read_set, write_set, err_set;
02003   int max_fd = 0;
02004   int i;
02005   struct timeval tv;
02006   int ready;
02007   
02008   FD_ZERO (&read_set);
02009   FD_ZERO (&write_set);
02010   FD_ZERO (&err_set);
02011 
02012   for (i = 0; i < n_fds; i++)
02013     {
02014       DBusPollFD *fdp = &fds[i];
02015 
02016       if (fdp->events & _DBUS_POLLIN)
02017         FD_SET (fdp->fd, &read_set);
02018 
02019       if (fdp->events & _DBUS_POLLOUT)
02020         FD_SET (fdp->fd, &write_set);
02021 
02022       FD_SET (fdp->fd, &err_set);
02023 
02024       max_fd = MAX (max_fd, fdp->fd);
02025     }
02026     
02027   tv.tv_sec = timeout_milliseconds / 1000;
02028   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02029 
02030   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02031                   timeout_milliseconds < 0 ? NULL : &tv);
02032 
02033   if (ready > 0)
02034     {
02035       for (i = 0; i < n_fds; i++)
02036         {
02037           DBusPollFD *fdp = &fds[i];
02038 
02039           fdp->revents = 0;
02040 
02041           if (FD_ISSET (fdp->fd, &read_set))
02042             fdp->revents |= _DBUS_POLLIN;
02043 
02044           if (FD_ISSET (fdp->fd, &write_set))
02045             fdp->revents |= _DBUS_POLLOUT;
02046 
02047           if (FD_ISSET (fdp->fd, &err_set))
02048             fdp->revents |= _DBUS_POLLERR;
02049         }
02050     }
02051 
02052   return ready;
02053 #endif
02054 }
02055 
02063 void
02064 _dbus_get_current_time (long *tv_sec,
02065                         long *tv_usec)
02066 {
02067   struct timeval t;
02068 
02069 #ifdef HAVE_MONOTONIC_CLOCK
02070   struct timespec ts;
02071   clock_gettime (CLOCK_MONOTONIC, &ts);
02072 
02073   if (tv_sec)
02074     *tv_sec = ts.tv_sec;
02075   if (tv_usec)
02076     *tv_usec = ts.tv_nsec / 1000;
02077 #else
02078   gettimeofday (&t, NULL);
02079 
02080   if (tv_sec)
02081     *tv_sec = t.tv_sec;
02082   if (tv_usec)
02083     *tv_usec = t.tv_usec;
02084 #endif
02085 }
02086 
02097 dbus_bool_t
02098 _dbus_file_get_contents (DBusString       *str,
02099                          const DBusString *filename,
02100                          DBusError        *error)
02101 {
02102   int fd;
02103   struct stat sb;
02104   int orig_len;
02105   int total;
02106   const char *filename_c;
02107 
02108   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02109   
02110   filename_c = _dbus_string_get_const_data (filename);
02111   
02112   /* O_BINARY useful on Cygwin */
02113   fd = open (filename_c, O_RDONLY | O_BINARY);
02114   if (fd < 0)
02115     {
02116       dbus_set_error (error, _dbus_error_from_errno (errno),
02117                       "Failed to open \"%s\": %s",
02118                       filename_c,
02119                       _dbus_strerror (errno));
02120       return FALSE;
02121     }
02122 
02123   _dbus_verbose ("file fd %d opened\n", fd);
02124   
02125   if (fstat (fd, &sb) < 0)
02126     {
02127       dbus_set_error (error, _dbus_error_from_errno (errno),
02128                       "Failed to stat \"%s\": %s",
02129                       filename_c,
02130                       _dbus_strerror (errno));
02131 
02132       _dbus_verbose ("fstat() failed: %s",
02133                      _dbus_strerror (errno));
02134       
02135       _dbus_close (fd, NULL);
02136       
02137       return FALSE;
02138     }
02139 
02140   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02141     {
02142       dbus_set_error (error, DBUS_ERROR_FAILED,
02143                       "File size %lu of \"%s\" is too large.",
02144                       (unsigned long) sb.st_size, filename_c);
02145       _dbus_close (fd, NULL);
02146       return FALSE;
02147     }
02148   
02149   total = 0;
02150   orig_len = _dbus_string_get_length (str);
02151   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02152     {
02153       int bytes_read;
02154 
02155       while (total < (int) sb.st_size)
02156         {
02157           bytes_read = _dbus_read (fd, str,
02158                                    sb.st_size - total);
02159           if (bytes_read <= 0)
02160             {
02161               dbus_set_error (error, _dbus_error_from_errno (errno),
02162                               "Error reading \"%s\": %s",
02163                               filename_c,
02164                               _dbus_strerror (errno));
02165 
02166               _dbus_verbose ("read() failed: %s",
02167                              _dbus_strerror (errno));
02168               
02169               _dbus_close (fd, NULL);
02170               _dbus_string_set_length (str, orig_len);
02171               return FALSE;
02172             }
02173           else
02174             total += bytes_read;
02175         }
02176 
02177       _dbus_close (fd, NULL);
02178       return TRUE;
02179     }
02180   else if (sb.st_size != 0)
02181     {
02182       _dbus_verbose ("Can only open regular files at the moment.\n");
02183       dbus_set_error (error, DBUS_ERROR_FAILED,
02184                       "\"%s\" is not a regular file",
02185                       filename_c);
02186       _dbus_close (fd, NULL);
02187       return FALSE;
02188     }
02189   else
02190     {
02191       _dbus_close (fd, NULL);
02192       return TRUE;
02193     }
02194 }
02195 
02205 dbus_bool_t
02206 _dbus_string_save_to_file (const DBusString *str,
02207                            const DBusString *filename,
02208                            DBusError        *error)
02209 {
02210   int fd;
02211   int bytes_to_write;
02212   const char *filename_c;
02213   DBusString tmp_filename;
02214   const char *tmp_filename_c;
02215   int total;
02216   dbus_bool_t need_unlink;
02217   dbus_bool_t retval;
02218 
02219   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02220   
02221   fd = -1;
02222   retval = FALSE;
02223   need_unlink = FALSE;
02224   
02225   if (!_dbus_string_init (&tmp_filename))
02226     {
02227       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02228       return FALSE;
02229     }
02230 
02231   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02232     {
02233       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02234       _dbus_string_free (&tmp_filename);
02235       return FALSE;
02236     }
02237   
02238   if (!_dbus_string_append (&tmp_filename, "."))
02239     {
02240       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02241       _dbus_string_free (&tmp_filename);
02242       return FALSE;
02243     }
02244 
02245 #define N_TMP_FILENAME_RANDOM_BYTES 8
02246   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02247     {
02248       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02249       _dbus_string_free (&tmp_filename);
02250       return FALSE;
02251     }
02252     
02253   filename_c = _dbus_string_get_const_data (filename);
02254   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02255 
02256   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02257              0600);
02258   if (fd < 0)
02259     {
02260       dbus_set_error (error, _dbus_error_from_errno (errno),
02261                       "Could not create %s: %s", tmp_filename_c,
02262                       _dbus_strerror (errno));
02263       goto out;
02264     }
02265 
02266   _dbus_verbose ("tmp file fd %d opened\n", fd);
02267   
02268   need_unlink = TRUE;
02269   
02270   total = 0;
02271   bytes_to_write = _dbus_string_get_length (str);
02272 
02273   while (total < bytes_to_write)
02274     {
02275       int bytes_written;
02276 
02277       bytes_written = _dbus_write (fd, str, total,
02278                                    bytes_to_write - total);
02279 
02280       if (bytes_written <= 0)
02281         {
02282           dbus_set_error (error, _dbus_error_from_errno (errno),
02283                           "Could not write to %s: %s", tmp_filename_c,
02284                           _dbus_strerror (errno));
02285           
02286           goto out;
02287         }
02288 
02289       total += bytes_written;
02290     }
02291 
02292   if (fsync(fd))
02293     {
02294       dbus_set_error (error, _dbus_error_from_errno (errno),
02295                       "Could not synchronize file %s: %s",
02296                       tmp_filename_c, _dbus_strerror (errno));
02297 
02298       goto out;
02299   }
02300 
02301   if (!_dbus_close (fd, NULL))
02302     {
02303       dbus_set_error (error, _dbus_error_from_errno (errno),
02304                       "Could not close file %s: %s",
02305                       tmp_filename_c, _dbus_strerror (errno));
02306 
02307       goto out;
02308     }
02309 
02310   fd = -1;
02311   
02312   if (rename (tmp_filename_c, filename_c) < 0)
02313     {
02314       dbus_set_error (error, _dbus_error_from_errno (errno),
02315                       "Could not rename %s to %s: %s",
02316                       tmp_filename_c, filename_c,
02317                       _dbus_strerror (errno));
02318 
02319       goto out;
02320     }
02321 
02322   need_unlink = FALSE;
02323   
02324   retval = TRUE;
02325   
02326  out:
02327   /* close first, then unlink, to prevent ".nfs34234235" garbage
02328    * files
02329    */
02330 
02331   if (fd >= 0)
02332     _dbus_close (fd, NULL);
02333         
02334   if (need_unlink && unlink (tmp_filename_c) < 0)
02335     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02336                    tmp_filename_c, _dbus_strerror (errno));
02337 
02338   _dbus_string_free (&tmp_filename);
02339 
02340   if (!retval)
02341     _DBUS_ASSERT_ERROR_IS_SET (error);
02342   
02343   return retval;
02344 }
02345 
02352 dbus_bool_t
02353 _dbus_make_file_world_readable(const DBusString *filename,
02354                                DBusError *error)
02355 {
02356   const char *filename_c;
02357 
02358   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02359 
02360   filename_c = _dbus_string_get_const_data (filename);
02361   if (chmod (filename_c, 0644) == -1)
02362     {
02363       dbus_set_error (error,
02364                       DBUS_ERROR_FAILED,
02365                       "Could not change permissions of file %s: %s\n",
02366                       filename_c,
02367                       _dbus_strerror (errno));
02368       return FALSE;
02369     }
02370   return TRUE;
02371 }
02372 
02379 dbus_bool_t
02380 _dbus_create_file_exclusively (const DBusString *filename,
02381                                DBusError        *error)
02382 {
02383   int fd;
02384   const char *filename_c;
02385 
02386   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02387   
02388   filename_c = _dbus_string_get_const_data (filename);
02389   
02390   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02391              0600);
02392   if (fd < 0)
02393     {
02394       dbus_set_error (error,
02395                       DBUS_ERROR_FAILED,
02396                       "Could not create file %s: %s\n",
02397                       filename_c,
02398                       _dbus_strerror (errno));
02399       return FALSE;
02400     }
02401 
02402   _dbus_verbose ("exclusive file fd %d opened\n", fd);
02403   
02404   if (!_dbus_close (fd, NULL))
02405     {
02406       dbus_set_error (error,
02407                       DBUS_ERROR_FAILED,
02408                       "Could not close file %s: %s\n",
02409                       filename_c,
02410                       _dbus_strerror (errno));
02411       return FALSE;
02412     }
02413   
02414   return TRUE;
02415 }
02416 
02425 dbus_bool_t
02426 _dbus_delete_file (const DBusString *filename,
02427                    DBusError        *error)
02428 {
02429   const char *filename_c;
02430 
02431   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02432   
02433   filename_c = _dbus_string_get_const_data (filename);
02434 
02435   if (unlink (filename_c) < 0)
02436     {
02437       dbus_set_error (error, DBUS_ERROR_FAILED,
02438                       "Failed to delete file %s: %s\n",
02439                       filename_c, _dbus_strerror (errno));
02440       return FALSE;
02441     }
02442   else
02443     return TRUE;
02444 }
02445 
02454 dbus_bool_t
02455 _dbus_create_directory (const DBusString *filename,
02456                         DBusError        *error)
02457 {
02458   const char *filename_c;
02459 
02460   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02461   
02462   filename_c = _dbus_string_get_const_data (filename);
02463 
02464   if (mkdir (filename_c, 0700) < 0)
02465     {
02466       if (errno == EEXIST)
02467         return TRUE;
02468       
02469       dbus_set_error (error, DBUS_ERROR_FAILED,
02470                       "Failed to create directory %s: %s\n",
02471                       filename_c, _dbus_strerror (errno));
02472       return FALSE;
02473     }
02474   else
02475     return TRUE;
02476 }
02477 
02488 dbus_bool_t
02489 _dbus_concat_dir_and_file (DBusString       *dir,
02490                            const DBusString *next_component)
02491 {
02492   dbus_bool_t dir_ends_in_slash;
02493   dbus_bool_t file_starts_with_slash;
02494 
02495   if (_dbus_string_get_length (dir) == 0 ||
02496       _dbus_string_get_length (next_component) == 0)
02497     return TRUE;
02498   
02499   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02500                                                     _dbus_string_get_length (dir) - 1);
02501 
02502   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02503 
02504   if (dir_ends_in_slash && file_starts_with_slash)
02505     {
02506       _dbus_string_shorten (dir, 1);
02507     }
02508   else if (!(dir_ends_in_slash || file_starts_with_slash))
02509     {
02510       if (!_dbus_string_append_byte (dir, '/'))
02511         return FALSE;
02512     }
02513 
02514   return _dbus_string_copy (next_component, 0, dir,
02515                             _dbus_string_get_length (dir));
02516 }
02517 
02519 #define NANOSECONDS_PER_SECOND       1000000000
02520 
02521 #define MICROSECONDS_PER_SECOND      1000000
02522 
02523 #define MILLISECONDS_PER_SECOND      1000
02524 
02525 #define NANOSECONDS_PER_MILLISECOND  1000000
02526 
02527 #define MICROSECONDS_PER_MILLISECOND 1000
02528 
02533 void
02534 _dbus_sleep_milliseconds (int milliseconds)
02535 {
02536 #ifdef HAVE_NANOSLEEP
02537   struct timespec req;
02538   struct timespec rem;
02539 
02540   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02541   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02542   rem.tv_sec = 0;
02543   rem.tv_nsec = 0;
02544 
02545   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02546     req = rem;
02547 #elif defined (HAVE_USLEEP)
02548   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02549 #else /* ! HAVE_USLEEP */
02550   sleep (MAX (milliseconds / 1000, 1));
02551 #endif
02552 }
02553 
02554 static dbus_bool_t
02555 _dbus_generate_pseudorandom_bytes (DBusString *str,
02556                                    int         n_bytes)
02557 {
02558   int old_len;
02559   char *p;
02560   
02561   old_len = _dbus_string_get_length (str);
02562 
02563   if (!_dbus_string_lengthen (str, n_bytes))
02564     return FALSE;
02565 
02566   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02567 
02568   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02569 
02570   return TRUE;
02571 }
02572 
02581 dbus_bool_t
02582 _dbus_generate_random_bytes (DBusString *str,
02583                              int         n_bytes)
02584 {
02585   int old_len;
02586   int fd;
02587 
02588   /* FALSE return means "no memory", if it could
02589    * mean something else then we'd need to return
02590    * a DBusError. So we always fall back to pseudorandom
02591    * if the I/O fails.
02592    */
02593   
02594   old_len = _dbus_string_get_length (str);
02595   fd = -1;
02596 
02597   /* note, urandom on linux will fall back to pseudorandom */
02598   fd = open ("/dev/urandom", O_RDONLY);
02599   if (fd < 0)
02600     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02601 
02602   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02603   
02604   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02605     {
02606       _dbus_close (fd, NULL);
02607       _dbus_string_set_length (str, old_len);
02608       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02609     }
02610 
02611   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02612                  n_bytes);
02613   
02614   _dbus_close (fd, NULL);
02615   
02616   return TRUE;
02617 }
02618 
02624 void
02625 _dbus_exit (int code)
02626 {
02627   _exit (code);
02628 }
02629 
02638 const char*
02639 _dbus_strerror (int error_number)
02640 {
02641   const char *msg;
02642   
02643   msg = strerror (error_number);
02644   if (msg == NULL)
02645     msg = "unknown";
02646 
02647   return msg;
02648 }
02649 
02653 void
02654 _dbus_disable_sigpipe (void)
02655 {
02656   signal (SIGPIPE, SIG_IGN);
02657 }
02658 
02666 void
02667 _dbus_fd_set_close_on_exec (int fd)
02668 {
02669   int val;
02670   
02671   val = fcntl (fd, F_GETFD, 0);
02672   
02673   if (val < 0)
02674     return;
02675 
02676   val |= FD_CLOEXEC;
02677   
02678   fcntl (fd, F_SETFD, val);
02679 }
02680 
02688 dbus_bool_t
02689 _dbus_close (int        fd,
02690              DBusError *error)
02691 {
02692   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02693   
02694  again:
02695   if (close (fd) < 0)
02696     {
02697       if (errno == EINTR)
02698         goto again;
02699 
02700       dbus_set_error (error, _dbus_error_from_errno (errno),
02701                       "Could not close fd %d", fd);
02702       return FALSE;
02703     }
02704 
02705   return TRUE;
02706 }
02707 
02715 dbus_bool_t
02716 _dbus_set_fd_nonblocking (int             fd,
02717                           DBusError      *error)
02718 {
02719   int val;
02720 
02721   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02722   
02723   val = fcntl (fd, F_GETFL, 0);
02724   if (val < 0)
02725     {
02726       dbus_set_error (error, _dbus_error_from_errno (errno),
02727                       "Failed to get flags from file descriptor %d: %s",
02728                       fd, _dbus_strerror (errno));
02729       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02730                      _dbus_strerror (errno));
02731       return FALSE;
02732     }
02733 
02734   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02735     {
02736       dbus_set_error (error, _dbus_error_from_errno (errno),
02737                       "Failed to set nonblocking flag of file descriptor %d: %s",
02738                       fd, _dbus_strerror (errno));
02739       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02740                      fd, _dbus_strerror (errno));
02741 
02742       return FALSE;
02743     }
02744 
02745   return TRUE;
02746 }
02747 
02753 void
02754 _dbus_print_backtrace (void)
02755 {  
02756 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02757   void *bt[500];
02758   int bt_size;
02759   int i;
02760   char **syms;
02761   
02762   bt_size = backtrace (bt, 500);
02763 
02764   syms = backtrace_symbols (bt, bt_size);
02765   
02766   i = 0;
02767   while (i < bt_size)
02768     {
02769       /* don't use dbus_warn since it can _dbus_abort() */
02770       fprintf (stderr, "  %s\n", syms[i]);
02771       ++i;
02772     }
02773   fflush (stderr);
02774 
02775   free (syms);
02776 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02777   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02778 #else
02779   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02780 #endif
02781 }
02782 
02798 dbus_bool_t
02799 _dbus_full_duplex_pipe (int        *fd1,
02800                         int        *fd2,
02801                         dbus_bool_t blocking,
02802                         DBusError  *error)
02803 {
02804 #ifdef HAVE_SOCKETPAIR
02805   int fds[2];
02806 
02807   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02808   
02809   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02810     {
02811       dbus_set_error (error, _dbus_error_from_errno (errno),
02812                       "Could not create full-duplex pipe");
02813       return FALSE;
02814     }
02815 
02816   if (!blocking &&
02817       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02818        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02819     {
02820       dbus_set_error (error, _dbus_error_from_errno (errno),
02821                       "Could not set full-duplex pipe nonblocking");
02822       
02823       _dbus_close (fds[0], NULL);
02824       _dbus_close (fds[1], NULL);
02825       
02826       return FALSE;
02827     }
02828   
02829   *fd1 = fds[0];
02830   *fd2 = fds[1];
02831 
02832   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02833                  *fd1, *fd2);
02834   
02835   return TRUE;  
02836 #else
02837   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02838   dbus_set_error (error, DBUS_ERROR_FAILED,
02839                   "_dbus_full_duplex_pipe() not implemented on this OS");
02840   return FALSE;
02841 #endif
02842 }
02843 
02852 int
02853 _dbus_printf_string_upper_bound (const char *format,
02854                                  va_list     args)
02855 {
02856   char c;
02857   return vsnprintf (&c, 1, format, args);
02858 }
02859 
02866 const char*
02867 _dbus_get_tmpdir(void)
02868 {
02869   static const char* tmpdir = NULL;
02870 
02871   if (tmpdir == NULL)
02872     {
02873       /* TMPDIR is what glibc uses, then
02874        * glibc falls back to the P_tmpdir macro which
02875        * just expands to "/tmp"
02876        */
02877       if (tmpdir == NULL)
02878         tmpdir = getenv("TMPDIR");
02879 
02880       /* These two env variables are probably
02881        * broken, but maybe some OS uses them?
02882        */
02883       if (tmpdir == NULL)
02884         tmpdir = getenv("TMP");
02885       if (tmpdir == NULL)
02886         tmpdir = getenv("TEMP");
02887 
02888       /* And this is the sane fallback. */
02889       if (tmpdir == NULL)
02890         tmpdir = "/tmp";
02891     }
02892   
02893   _dbus_assert(tmpdir != NULL);
02894   
02895   return tmpdir;
02896 }
02897 
02917 static dbus_bool_t
02918 _read_subprocess_line_argv (const char *progpath,
02919                             dbus_bool_t path_fallback,
02920                             char       * const *argv,
02921                             DBusString *result,
02922                             DBusError  *error)
02923 {
02924   int result_pipe[2] = { -1, -1 };
02925   int errors_pipe[2] = { -1, -1 };
02926   pid_t pid;
02927   int ret;
02928   int status;
02929   int orig_len;
02930   int i;
02931 
02932   dbus_bool_t retval;
02933   sigset_t new_set, old_set;
02934   
02935   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02936   retval = FALSE;
02937 
02938   /* We need to block any existing handlers for SIGCHLD temporarily; they
02939    * will cause waitpid() below to fail.
02940    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
02941    */
02942   sigemptyset (&new_set);
02943   sigaddset (&new_set, SIGCHLD);
02944   sigprocmask (SIG_BLOCK, &new_set, &old_set);
02945   
02946   orig_len = _dbus_string_get_length (result);
02947   
02948 #define READ_END        0
02949 #define WRITE_END       1
02950   if (pipe (result_pipe) < 0)
02951     {
02952       dbus_set_error (error, _dbus_error_from_errno (errno),
02953                       "Failed to create a pipe to call %s: %s",
02954                       progpath, _dbus_strerror (errno));
02955       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02956                      progpath, _dbus_strerror (errno));
02957       goto out;
02958     }
02959   if (pipe (errors_pipe) < 0)
02960     {
02961       dbus_set_error (error, _dbus_error_from_errno (errno),
02962                       "Failed to create a pipe to call %s: %s",
02963                       progpath, _dbus_strerror (errno));
02964       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02965                      progpath, _dbus_strerror (errno));
02966       goto out;
02967     }
02968 
02969   pid = fork ();
02970   if (pid < 0)
02971     {
02972       dbus_set_error (error, _dbus_error_from_errno (errno),
02973                       "Failed to fork() to call %s: %s",
02974                       progpath, _dbus_strerror (errno));
02975       _dbus_verbose ("Failed to fork() to call %s: %s\n",
02976                      progpath, _dbus_strerror (errno));
02977       goto out;
02978     }
02979 
02980   if (pid == 0)
02981     {
02982       /* child process */
02983       int maxfds;
02984       int fd;
02985 
02986       fd = open ("/dev/null", O_RDWR);
02987       if (fd == -1)
02988         /* huh?! can't open /dev/null? */
02989         _exit (1);
02990 
02991       _dbus_verbose ("/dev/null fd %d opened\n", fd);
02992       
02993       /* set-up stdXXX */
02994       close (result_pipe[READ_END]);
02995       close (errors_pipe[READ_END]);
02996       close (0);                /* close stdin */
02997       close (1);                /* close stdout */
02998       close (2);                /* close stderr */
02999 
03000       if (dup2 (fd, 0) == -1)
03001         _exit (1);
03002       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03003         _exit (1);
03004       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03005         _exit (1);
03006 
03007       maxfds = sysconf (_SC_OPEN_MAX);
03008       /* Pick something reasonable if for some reason sysconf
03009        * says unlimited.
03010        */
03011       if (maxfds < 0)
03012         maxfds = 1024;
03013       /* close all inherited fds */
03014       for (i = 3; i < maxfds; i++)
03015         close (i);
03016 
03017       sigprocmask (SIG_SETMASK, &old_set, NULL);
03018 
03019       /* If it looks fully-qualified, try execv first */
03020       if (progpath[0] == '/')
03021         {
03022           execv (progpath, argv);
03023           /* Ok, that failed.  Now if path_fallback is given, let's
03024            * try unqualified.  This is mostly a hack to work
03025            * around systems which ship dbus-launch in /usr/bin
03026            * but everything else in /bin (because dbus-launch
03027            * depends on X11).
03028            */
03029           if (path_fallback)
03030             /* We must have a slash, because we checked above */
03031             execvp (strrchr (progpath, '/')+1, argv);
03032         }
03033       else
03034         execvp (progpath, argv);
03035 
03036       /* still nothing, we failed */
03037       _exit (1);
03038     }
03039 
03040   /* parent process */
03041   close (result_pipe[WRITE_END]);
03042   close (errors_pipe[WRITE_END]);
03043   result_pipe[WRITE_END] = -1;
03044   errors_pipe[WRITE_END] = -1;
03045 
03046   ret = 0;
03047   do 
03048     {
03049       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03050     }
03051   while (ret > 0);
03052 
03053   /* reap the child process to avoid it lingering as zombie */
03054   do
03055     {
03056       ret = waitpid (pid, &status, 0);
03057     }
03058   while (ret == -1 && errno == EINTR);
03059 
03060   /* We succeeded if the process exited with status 0 and
03061      anything was read */
03062   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03063     {
03064       /* The process ended with error */
03065       DBusString error_message;
03066       _dbus_string_init (&error_message);
03067       ret = 0;
03068       do
03069         {
03070           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03071         }
03072       while (ret > 0);
03073 
03074       _dbus_string_set_length (result, orig_len);
03075       if (_dbus_string_get_length (&error_message) > 0)
03076         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03077                         "%s terminated abnormally with the following error: %s",
03078                         progpath, _dbus_string_get_data (&error_message));
03079       else
03080         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03081                         "%s terminated abnormally without any error message",
03082                         progpath);
03083       goto out;
03084     }
03085 
03086   retval = TRUE;
03087   
03088  out:
03089   sigprocmask (SIG_SETMASK, &old_set, NULL);
03090 
03091   if (retval)
03092     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03093   else
03094     _DBUS_ASSERT_ERROR_IS_SET (error);
03095 
03096   if (result_pipe[0] != -1)
03097     close (result_pipe[0]);
03098   if (result_pipe[1] != -1)
03099     close (result_pipe[1]);
03100   if (errors_pipe[0] != -1)
03101     close (errors_pipe[0]);
03102   if (errors_pipe[1] != -1)
03103     close (errors_pipe[1]);
03104 
03105   return retval;  
03106 }
03107 
03119 dbus_bool_t
03120 _dbus_get_autolaunch_address (DBusString *address,
03121                               DBusError  *error)
03122 {
03123   static char *argv[6];
03124   int i;
03125   DBusString uuid;
03126   dbus_bool_t retval;
03127   
03128   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03129   retval = FALSE;
03130 
03131   if (!_dbus_string_init (&uuid))
03132     {
03133       _DBUS_SET_OOM (error);
03134       return FALSE;
03135     }
03136   
03137   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03138     {
03139       _DBUS_SET_OOM (error);
03140       goto out;
03141     }
03142   
03143   i = 0;
03144   argv[i] = "dbus-launch";
03145   ++i;
03146   argv[i] = "--autolaunch";
03147   ++i;
03148   argv[i] = _dbus_string_get_data (&uuid);
03149   ++i;
03150   argv[i] = "--binary-syntax";
03151   ++i;
03152   argv[i] = "--close-stderr";
03153   ++i;
03154   argv[i] = NULL;
03155   ++i;
03156 
03157   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03158 
03159   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03160                                        TRUE,
03161                                        argv, address, error);
03162 
03163  out:
03164   _dbus_string_free (&uuid);
03165   return retval;
03166 }
03167 
03186 dbus_bool_t
03187 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03188                                dbus_bool_t create_if_not_found,
03189                                DBusError  *error)
03190 {
03191   DBusString filename;
03192   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03193   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03194 }
03195 
03196 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03197 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03198 
03218 dbus_bool_t
03219 _dbus_lookup_session_address (dbus_bool_t *supported,
03220                               DBusString  *address,
03221                               DBusError   *error)
03222 {
03223   /* On non-Mac Unix platforms, if the session address isn't already
03224    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03225    * fall back to the autolaunch: global default; see 
03226    * init_session_address in dbus/dbus-bus.c. */
03227   *supported = FALSE;
03228   return TRUE;
03229 }
03230 
03248 dbus_bool_t 
03249 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03250 {
03251   const char *xdg_data_home;
03252   const char *xdg_data_dirs;
03253   DBusString servicedir_path;
03254 
03255   if (!_dbus_string_init (&servicedir_path))
03256     return FALSE;
03257 
03258   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03259   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03260 
03261   if (xdg_data_dirs != NULL)
03262     {
03263       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03264         goto oom;
03265 
03266       if (!_dbus_string_append (&servicedir_path, ":"))
03267         goto oom;
03268     }
03269   else
03270     {
03271       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03272         goto oom;
03273     }
03274 
03275   /* 
03276    * add configured datadir to defaults
03277    * this may be the same as an xdg dir
03278    * however the config parser should take 
03279    * care of duplicates 
03280    */
03281   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03282         goto oom;
03283 
03284   if (xdg_data_home != NULL)
03285     {
03286       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03287         goto oom;
03288     }
03289   else
03290     {
03291       const DBusString *homedir;
03292       DBusString local_share;
03293 
03294       if (!_dbus_homedir_from_current_process (&homedir))
03295         goto oom;
03296        
03297       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03298         goto oom;
03299 
03300       _dbus_string_init_const (&local_share, "/.local/share");
03301       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03302         goto oom;
03303     }
03304 
03305   if (!_dbus_split_paths_and_append (&servicedir_path, 
03306                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
03307                                      dirs))
03308     goto oom;
03309 
03310   _dbus_string_free (&servicedir_path);  
03311   return TRUE;
03312 
03313  oom:
03314   _dbus_string_free (&servicedir_path);
03315   return FALSE;
03316 }
03317 
03318 
03337 dbus_bool_t 
03338 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03339 {
03340   const char *xdg_data_dirs;
03341   DBusString servicedir_path;
03342 
03343   if (!_dbus_string_init (&servicedir_path))
03344     return FALSE;
03345 
03346   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03347 
03348   if (xdg_data_dirs != NULL)
03349     {
03350       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03351         goto oom;
03352 
03353       if (!_dbus_string_append (&servicedir_path, ":"))
03354         goto oom;
03355     }
03356   else
03357     {
03358       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03359         goto oom;
03360     }
03361 
03362   /* 
03363    * add configured datadir to defaults
03364    * this may be the same as an xdg dir
03365    * however the config parser should take 
03366    * care of duplicates 
03367    */
03368   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03369         goto oom;
03370 
03371   if (!_dbus_split_paths_and_append (&servicedir_path, 
03372                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 
03373                                      dirs))
03374     goto oom;
03375 
03376   _dbus_string_free (&servicedir_path);  
03377   return TRUE;
03378 
03379  oom:
03380   _dbus_string_free (&servicedir_path);
03381   return FALSE;
03382 }
03383 
03392 dbus_bool_t
03393 _dbus_append_system_config_file (DBusString *str)
03394 {
03395   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03396 }
03397 
03404 dbus_bool_t
03405 _dbus_append_session_config_file (DBusString *str)
03406 {
03407   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03408 }
03409 
03417 void
03418 _dbus_flush_caches (void)
03419 {
03420   _dbus_user_database_flush_system ();
03421 }
03422 
03436 dbus_bool_t
03437 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03438                                                 DBusCredentials *credentials)
03439 {
03440   DBusString homedir;
03441   DBusString dotdir;
03442   dbus_uid_t uid;
03443   
03444   _dbus_assert (credentials != NULL);
03445   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03446   
03447   if (!_dbus_string_init (&homedir))
03448     return FALSE;
03449 
03450   uid = _dbus_credentials_get_unix_uid (credentials);
03451   _dbus_assert (uid != DBUS_UID_UNSET);
03452 
03453   if (!_dbus_homedir_from_uid (uid, &homedir))
03454     goto failed;
03455   
03456 #ifdef DBUS_BUILD_TESTS
03457   {
03458     const char *override;
03459     
03460     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03461     if (override != NULL && *override != '\0')
03462       {
03463         _dbus_string_set_length (&homedir, 0);
03464         if (!_dbus_string_append (&homedir, override))
03465           goto failed;
03466 
03467         _dbus_verbose ("Using fake homedir for testing: %s\n",
03468                        _dbus_string_get_const_data (&homedir));
03469       }
03470     else
03471       {
03472         static dbus_bool_t already_warned = FALSE;
03473         if (!already_warned)
03474           {
03475             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03476             already_warned = TRUE;
03477           }
03478       }
03479   }
03480 #endif
03481 
03482   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03483   if (!_dbus_concat_dir_and_file (&homedir,
03484                                   &dotdir))
03485     goto failed;
03486   
03487   if (!_dbus_string_copy (&homedir, 0,
03488                           directory, _dbus_string_get_length (directory))) {
03489     goto failed;
03490   }
03491 
03492   _dbus_string_free (&homedir);
03493   return TRUE;
03494   
03495  failed: 
03496   _dbus_string_free (&homedir);
03497   return FALSE;
03498 }
03499 
03500 
03507 dbus_bool_t
03508 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03509 {
03510   return errno == EAGAIN || errno == EWOULDBLOCK;
03511 }
03512 
03513 /* tests in dbus-sysdeps-util.c */

Generated on Sun Feb 20 2011 22:49:19 for D-Bus by  doxygen 1.7.1