• 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 
00627   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00628 
00629   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00630                  path, abstract);
00631   
00632   if (!_dbus_open_unix_socket (&listen_fd, error))
00633     {
00634       _DBUS_ASSERT_ERROR_IS_SET(error);
00635       return -1;
00636     }
00637   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00638 
00639   _DBUS_ZERO (addr);
00640   addr.sun_family = AF_UNIX;
00641   path_len = strlen (path);
00642   
00643   if (abstract)
00644     {
00645 #ifdef HAVE_ABSTRACT_SOCKETS
00646       /* remember that abstract names aren't nul-terminated so we rely
00647        * on sun_path being filled in with zeroes above.
00648        */
00649       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00650       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00651 
00652       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00653         {
00654           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00655                       "Abstract socket name too long\n");
00656           _dbus_close (listen_fd, NULL);
00657           return -1;
00658         }
00659       
00660       strncpy (&addr.sun_path[1], path, path_len);
00661       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00662 #else /* HAVE_ABSTRACT_SOCKETS */
00663       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00664                       "Operating system does not support abstract socket namespace\n");
00665       _dbus_close (listen_fd, NULL);
00666       return -1;
00667 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00668     }
00669   else
00670     {
00671       /* Discussed security implications of this with Nalin,
00672        * and we couldn't think of where it would kick our ass, but
00673        * it still seems a bit sucky. It also has non-security suckage;
00674        * really we'd prefer to exit if the socket is already in use.
00675        * But there doesn't seem to be a good way to do this.
00676        *
00677        * Just to be extra careful, I threw in the stat() - clearly
00678        * the stat() can't *fix* any security issue, but it at least
00679        * avoids inadvertent/accidental data loss.
00680        */
00681       {
00682         struct stat sb;
00683 
00684         if (stat (path, &sb) == 0 &&
00685             S_ISSOCK (sb.st_mode))
00686           unlink (path);
00687       }
00688 
00689       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00690         {
00691           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00692                       "Abstract socket name too long\n");
00693           _dbus_close (listen_fd, NULL);
00694           return -1;
00695         }
00696         
00697       strncpy (addr.sun_path, path, path_len);
00698     }
00699   
00700   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00701     {
00702       dbus_set_error (error, _dbus_error_from_errno (errno),
00703                       "Failed to bind socket \"%s\": %s",
00704                       path, _dbus_strerror (errno));
00705       _dbus_close (listen_fd, NULL);
00706       return -1;
00707     }
00708 
00709   if (listen (listen_fd, 30 /* backlog */) < 0)
00710     {
00711       dbus_set_error (error, _dbus_error_from_errno (errno),
00712                       "Failed to listen on socket \"%s\": %s",
00713                       path, _dbus_strerror (errno));
00714       _dbus_close (listen_fd, NULL);
00715       return -1;
00716     }
00717 
00718   if (!_dbus_set_local_creds (listen_fd, TRUE))
00719     {
00720       dbus_set_error (error, _dbus_error_from_errno (errno),
00721                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00722                       path, _dbus_strerror (errno));
00723       close (listen_fd);
00724       return -1;
00725     }
00726 
00727   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00728     {
00729       _DBUS_ASSERT_ERROR_IS_SET (error);
00730       _dbus_close (listen_fd, NULL);
00731       return -1;
00732     }
00733   
00734   /* Try opening up the permissions, but if we can't, just go ahead
00735    * and continue, maybe it will be good enough.
00736    */
00737   if (!abstract && chmod (path, 0777) < 0)
00738     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00739                 path);
00740   
00741   return listen_fd;
00742 }
00743 
00755 int
00756 _dbus_connect_tcp_socket (const char     *host,
00757                           const char     *port,
00758                           const char     *family,
00759                           DBusError      *error)
00760 {
00761   int fd = -1, res;
00762   struct addrinfo hints;
00763   struct addrinfo *ai, *tmp;
00764 
00765   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00766 
00767   if (!_dbus_open_tcp_socket (&fd, error))
00768     {
00769       _DBUS_ASSERT_ERROR_IS_SET(error);
00770       return -1;
00771     }
00772 
00773   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00774 
00775   _DBUS_ZERO (hints);
00776 
00777   if (!family)
00778     hints.ai_family = AF_UNSPEC;
00779   else if (!strcmp(family, "ipv4"))
00780     hints.ai_family = AF_INET;
00781   else if (!strcmp(family, "ipv6"))
00782     hints.ai_family = AF_INET6;
00783   else
00784     {
00785       dbus_set_error (error,
00786                       _dbus_error_from_errno (errno),
00787                       "Unknown address family %s", family);
00788       return -1;
00789     }
00790   hints.ai_protocol = IPPROTO_TCP;
00791   hints.ai_socktype = SOCK_STREAM;
00792   hints.ai_flags = AI_ADDRCONFIG;
00793 
00794   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00795     {
00796       dbus_set_error (error,
00797                       _dbus_error_from_errno (errno),
00798                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00799                       host, port, gai_strerror(res), res);
00800       _dbus_close (fd, NULL);
00801       return -1;
00802     }
00803 
00804   tmp = ai;
00805   while (tmp)
00806     {
00807       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00808         {
00809           freeaddrinfo(ai);
00810           _DBUS_ASSERT_ERROR_IS_SET(error);
00811           return -1;
00812         }
00813       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00814 
00815       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00816         {
00817           _dbus_close(fd, NULL);
00818           fd = -1;
00819           tmp = tmp->ai_next;
00820           continue;
00821         }
00822 
00823       break;
00824     }
00825   freeaddrinfo(ai);
00826 
00827   if (fd == -1)
00828     {
00829       dbus_set_error (error,
00830                       _dbus_error_from_errno (errno),
00831                       "Failed to connect to socket \"%s:%s\" %s",
00832                       host, port, _dbus_strerror(errno));
00833       return -1;
00834     }
00835 
00836 
00837   if (!_dbus_set_fd_nonblocking (fd, error))
00838     {
00839       _dbus_close (fd, NULL);
00840       fd = -1;
00841 
00842       return -1;
00843     }
00844 
00845   return fd;
00846 }
00847 
00862 int
00863 _dbus_listen_tcp_socket (const char     *host,
00864                          const char     *port,
00865                          const char     *family,
00866                          DBusString     *retport,
00867                          int           **fds_p,
00868                          DBusError      *error)
00869 {
00870   int nlisten_fd = 0, *listen_fd = NULL, res, i;
00871   struct addrinfo hints;
00872   struct addrinfo *ai, *tmp;
00873 
00874   *fds_p = NULL;
00875   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00876 
00877   _DBUS_ZERO (hints);
00878 
00879   if (!family)
00880     hints.ai_family = AF_UNSPEC;
00881   else if (!strcmp(family, "ipv4"))
00882     hints.ai_family = AF_INET;
00883   else if (!strcmp(family, "ipv6"))
00884     hints.ai_family = AF_INET6;
00885   else
00886     {
00887       dbus_set_error (error,
00888                       _dbus_error_from_errno (errno),
00889                       "Unknown address family %s", family);
00890       return -1;
00891     }
00892 
00893   hints.ai_protocol = IPPROTO_TCP;
00894   hints.ai_socktype = SOCK_STREAM;
00895   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00896 
00897  redo_lookup_with_port:
00898   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00899     {
00900       dbus_set_error (error,
00901                       _dbus_error_from_errno (errno),
00902                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00903                       host ? host : "*", port, gai_strerror(res), res);
00904       return -1;
00905     }
00906 
00907   tmp = ai;
00908   while (tmp)
00909     {
00910       int fd = -1, *newlisten_fd;
00911       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00912         {
00913           _DBUS_ASSERT_ERROR_IS_SET(error);
00914           goto failed;
00915         }
00916       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00917 
00918       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00919         {
00920           _dbus_close(fd, NULL);
00921           if (errno == EADDRINUSE)
00922             {
00923               /* Depending on kernel policy, it may or may not
00924                  be neccessary to bind to both IPv4 & 6 addresses
00925                  so ignore EADDRINUSE here */
00926               tmp = tmp->ai_next;
00927               continue;
00928             }
00929           dbus_set_error (error, _dbus_error_from_errno (errno),
00930                           "Failed to bind socket \"%s:%s\": %s",
00931                           host ? host : "*", port, _dbus_strerror (errno));
00932           goto failed;
00933         }
00934 
00935       if (listen (fd, 30 /* backlog */) < 0)
00936         {
00937           _dbus_close (fd, NULL);
00938           dbus_set_error (error, _dbus_error_from_errno (errno),
00939                           "Failed to listen on socket \"%s:%s\": %s",
00940                           host ? host : "*", port, _dbus_strerror (errno));
00941           goto failed;
00942         }
00943 
00944       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00945       if (!newlisten_fd)
00946         {
00947           _dbus_close (fd, NULL);
00948           dbus_set_error (error, _dbus_error_from_errno (errno),
00949                           "Failed to allocate file handle array: %s",
00950                           _dbus_strerror (errno));
00951           goto failed;
00952         }
00953       listen_fd = newlisten_fd;
00954       listen_fd[nlisten_fd] = fd;
00955       nlisten_fd++;
00956 
00957       if (!_dbus_string_get_length(retport))
00958         {
00959           /* If the user didn't specify a port, or used 0, then
00960              the kernel chooses a port. After the first address
00961              is bound to, we need to force all remaining addresses
00962              to use the same port */
00963           if (!port || !strcmp(port, "0"))
00964             {
00965               struct sockaddr_storage addr;
00966               socklen_t addrlen;
00967               char portbuf[50];
00968 
00969               addrlen = sizeof(addr);
00970               getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00971 
00972               if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00973                                      portbuf, sizeof(portbuf),
00974                                      NI_NUMERICHOST)) != 0)
00975                 {
00976                   dbus_set_error (error, _dbus_error_from_errno (errno),
00977                                   "Failed to resolve port \"%s:%s\": %s (%s)",
00978                                   host ? host : "*", port, gai_strerror(res), res);
00979                   goto failed;
00980                 }
00981               if (!_dbus_string_append(retport, portbuf))
00982                 {
00983                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00984                   goto failed;
00985                 }
00986 
00987               /* Release current address list & redo lookup */
00988               port = _dbus_string_get_const_data(retport);
00989               freeaddrinfo(ai);
00990               goto redo_lookup_with_port;
00991             }
00992           else
00993             {
00994               if (!_dbus_string_append(retport, port))
00995                 {
00996                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00997                     goto failed;
00998                 }
00999             }
01000         }
01001 
01002       tmp = tmp->ai_next;
01003     }
01004   freeaddrinfo(ai);
01005   ai = NULL;
01006 
01007   if (!nlisten_fd)
01008     {
01009       errno = EADDRINUSE;
01010       dbus_set_error (error, _dbus_error_from_errno (errno),
01011                       "Failed to bind socket \"%s:%s\": %s",
01012                       host ? host : "*", port, _dbus_strerror (errno));
01013       return -1;
01014     }
01015 
01016   for (i = 0 ; i < nlisten_fd ; i++)
01017     {
01018       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01019         {
01020           goto failed;
01021         }
01022     }
01023 
01024   *fds_p = listen_fd;
01025 
01026   return nlisten_fd;
01027 
01028  failed:
01029   if (ai)
01030     freeaddrinfo(ai);
01031   for (i = 0 ; i < nlisten_fd ; i++)
01032     _dbus_close(listen_fd[i], NULL);
01033   dbus_free(listen_fd);
01034   return -1;
01035 }
01036 
01037 static dbus_bool_t
01038 write_credentials_byte (int             server_fd,
01039                         DBusError      *error)
01040 {
01041   int bytes_written;
01042   char buf[1] = { '\0' };
01043 #if defined(HAVE_CMSGCRED) 
01044   union {
01045           struct cmsghdr hdr;
01046           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01047   } cmsg;
01048   struct iovec iov;
01049   struct msghdr msg;
01050   iov.iov_base = buf;
01051   iov.iov_len = 1;
01052 
01053   memset (&msg, 0, sizeof (msg));
01054   msg.msg_iov = &iov;
01055   msg.msg_iovlen = 1;
01056 
01057   msg.msg_control = (caddr_t) &cmsg;
01058   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01059   memset (&cmsg, 0, sizeof (cmsg));
01060   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01061   cmsg.hdr.cmsg_level = SOL_SOCKET;
01062   cmsg.hdr.cmsg_type = SCM_CREDS;
01063 #endif
01064 
01065   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01066   
01067  again:
01068 
01069 #if defined(HAVE_CMSGCRED) 
01070   bytes_written = sendmsg (server_fd, &msg, 0);
01071 #else
01072   bytes_written = write (server_fd, buf, 1);
01073 #endif
01074 
01075   if (bytes_written < 0 && errno == EINTR)
01076     goto again;
01077 
01078   if (bytes_written < 0)
01079     {
01080       dbus_set_error (error, _dbus_error_from_errno (errno),
01081                       "Failed to write credentials byte: %s",
01082                      _dbus_strerror (errno));
01083       return FALSE;
01084     }
01085   else if (bytes_written == 0)
01086     {
01087       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01088                       "wrote zero bytes writing credentials byte");
01089       return FALSE;
01090     }
01091   else
01092     {
01093       _dbus_assert (bytes_written == 1);
01094       _dbus_verbose ("wrote credentials byte\n");
01095       return TRUE;
01096     }
01097 }
01098 
01120 dbus_bool_t
01121 _dbus_read_credentials_socket  (int              client_fd,
01122                                 DBusCredentials *credentials,
01123                                 DBusError       *error)
01124 {
01125   struct msghdr msg;
01126   struct iovec iov;
01127   char buf;
01128   dbus_uid_t uid_read;
01129   dbus_pid_t pid_read;
01130   int bytes_read;
01131   
01132 #ifdef HAVE_CMSGCRED 
01133   union {
01134     struct cmsghdr hdr;
01135     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01136   } cmsg;
01137 
01138 #elif defined(LOCAL_CREDS)
01139   struct {
01140     struct cmsghdr hdr;
01141     struct sockcred cred;
01142   } cmsg;
01143 #endif
01144 
01145   uid_read = DBUS_UID_UNSET;
01146   pid_read = DBUS_PID_UNSET;
01147 
01148   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01149   
01150   /* The POSIX spec certainly doesn't promise this, but
01151    * we need these assertions to fail as soon as we're wrong about
01152    * it so we can do the porting fixups
01153    */
01154   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01155   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01156   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01157 
01158   _dbus_credentials_clear (credentials);
01159 
01160   /* Systems supporting LOCAL_CREDS are configured to have this feature
01161    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01162    * the connection.  Therefore, the received message must carry the
01163    * credentials information without doing anything special.
01164    */
01165 
01166   iov.iov_base = &buf;
01167   iov.iov_len = 1;
01168 
01169   memset (&msg, 0, sizeof (msg));
01170   msg.msg_iov = &iov;
01171   msg.msg_iovlen = 1;
01172 
01173 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01174   memset (&cmsg, 0, sizeof (cmsg));
01175   msg.msg_control = (caddr_t) &cmsg;
01176   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01177 #endif
01178 
01179  again:
01180   bytes_read = recvmsg (client_fd, &msg, 0);
01181 
01182   if (bytes_read < 0)
01183     {
01184       if (errno == EINTR)
01185         goto again;
01186 
01187       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01188        * normally only call read_credentials if the socket was ready
01189        * for reading
01190        */
01191       
01192       dbus_set_error (error, _dbus_error_from_errno (errno),
01193                       "Failed to read credentials byte: %s",
01194                       _dbus_strerror (errno));
01195       return FALSE;
01196     }
01197   else if (bytes_read == 0)
01198     {
01199       /* this should not happen unless we are using recvmsg wrong,
01200        * so is essentially here for paranoia
01201        */
01202       dbus_set_error (error, DBUS_ERROR_FAILED,
01203                       "Failed to read credentials byte (zero-length read)");
01204       return FALSE;
01205     }
01206   else if (buf != '\0')
01207     {
01208       dbus_set_error (error, DBUS_ERROR_FAILED,
01209                       "Credentials byte was not nul");
01210       return FALSE;
01211     }
01212 
01213 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01214   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01215                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01216     {
01217       dbus_set_error (error, DBUS_ERROR_FAILED,
01218                       "Message from recvmsg() was not SCM_CREDS");
01219       return FALSE;
01220     }
01221 #endif
01222 
01223   _dbus_verbose ("read credentials byte\n");
01224 
01225   {
01226 #ifdef SO_PEERCRED
01227     struct ucred cr;   
01228     int cr_len = sizeof (cr);
01229     
01230     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01231         cr_len == sizeof (cr))
01232       {
01233         pid_read = cr.pid;
01234         uid_read = cr.uid;
01235       }
01236     else
01237       {
01238         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01239                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01240       }
01241 #elif defined(HAVE_CMSGCRED)
01242     struct cmsgcred *cred;
01243 
01244     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01245     pid_read = cred->cmcred_pid;
01246     uid_read = cred->cmcred_euid;
01247 #elif defined(LOCAL_CREDS)
01248     pid_read = DBUS_PID_UNSET;
01249     uid_read = cmsg.cred.sc_uid;
01250     /* Since we have already got the credentials from this socket, we can
01251      * disable its LOCAL_CREDS flag if it was ever set. */
01252     _dbus_set_local_creds (client_fd, FALSE);
01253 #elif defined(HAVE_GETPEEREID)
01254     uid_t euid;
01255     gid_t egid;
01256     if (getpeereid (client_fd, &euid, &egid) == 0)
01257       {
01258         uid_read = euid;
01259       }
01260     else
01261       {
01262         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01263       }
01264 #elif defined(HAVE_GETPEERUCRED)
01265     ucred_t * ucred = NULL;
01266     if (getpeerucred (client_fd, &ucred) == 0)
01267       {
01268         pid_read = ucred_getpid (ucred);
01269         uid_read = ucred_geteuid (ucred);
01270 #ifdef HAVE_ADT
01271         /* generate audit session data based on socket ucred */
01272         adt_session_data_t *adth = NULL;
01273         adt_export_data_t *data = NULL;
01274         size_t size = 0;
01275         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01276           {
01277             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01278           }
01279         else 
01280           {
01281             if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 
01282               {
01283                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01284               }
01285             else
01286               {
01287                 size = adt_export_session_data (adth, &data);
01288                 if (size <= 0)
01289                   {
01290                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01291                   }
01292                 else
01293                   {
01294                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01295                     free (data);
01296                   }
01297               }
01298             (void) adt_end_session (adth);
01299           }
01300 #endif /* HAVE_ADT */
01301       }
01302     else
01303       {
01304         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01305       }
01306     if (ucred != NULL)
01307       ucred_free (ucred);
01308 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01309     _dbus_verbose ("Socket credentials not supported on this OS\n");
01310 #endif
01311   }
01312 
01313   _dbus_verbose ("Credentials:"
01314                  "  pid "DBUS_PID_FORMAT
01315                  "  uid "DBUS_UID_FORMAT
01316                  "\n",
01317                  pid_read,
01318                  uid_read);
01319 
01320   if (pid_read != DBUS_PID_UNSET)
01321     {
01322       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01323         {
01324           _DBUS_SET_OOM (error);
01325           return FALSE;
01326         }
01327     }
01328 
01329   if (uid_read != DBUS_UID_UNSET)
01330     {
01331       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01332         {
01333           _DBUS_SET_OOM (error);
01334           return FALSE;
01335         }
01336     }
01337   
01338   return TRUE;
01339 }
01340 
01358 dbus_bool_t
01359 _dbus_send_credentials_socket  (int              server_fd,
01360                                 DBusError       *error)
01361 {
01362   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01363   
01364   if (write_credentials_byte (server_fd, error))
01365     return TRUE;
01366   else
01367     return FALSE;
01368 }
01369 
01377 int
01378 _dbus_accept  (int listen_fd)
01379 {
01380   int client_fd;
01381   struct sockaddr addr;
01382   socklen_t addrlen;
01383 
01384   addrlen = sizeof (addr);
01385   
01386  retry:
01387   client_fd = accept (listen_fd, &addr, &addrlen);
01388   
01389   if (client_fd < 0)
01390     {
01391       if (errno == EINTR)
01392         goto retry;
01393     }
01394 
01395   _dbus_verbose ("client fd %d accepted\n", client_fd);
01396   
01397   return client_fd;
01398 }
01399 
01408 dbus_bool_t
01409 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01410 {
01411   const char *directory;
01412   struct stat sb;
01413         
01414   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01415     
01416   directory = _dbus_string_get_const_data (dir);
01417         
01418   if (stat (directory, &sb) < 0)
01419     {
01420       dbus_set_error (error, _dbus_error_from_errno (errno),
01421                       "%s", _dbus_strerror (errno));
01422    
01423       return FALSE;
01424     }
01425     
01426   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01427       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01428     {
01429       dbus_set_error (error, DBUS_ERROR_FAILED,
01430                      "%s directory is not private to the user", directory);
01431       return FALSE;
01432     }
01433     
01434   return TRUE;
01435 }
01436 
01437 static dbus_bool_t
01438 fill_user_info_from_passwd (struct passwd *p,
01439                             DBusUserInfo  *info,
01440                             DBusError     *error)
01441 {
01442   _dbus_assert (p->pw_name != NULL);
01443   _dbus_assert (p->pw_dir != NULL);
01444   
01445   info->uid = p->pw_uid;
01446   info->primary_gid = p->pw_gid;
01447   info->username = _dbus_strdup (p->pw_name);
01448   info->homedir = _dbus_strdup (p->pw_dir);
01449   
01450   if (info->username == NULL ||
01451       info->homedir == NULL)
01452     {
01453       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01454       return FALSE;
01455     }
01456 
01457   return TRUE;
01458 }
01459 
01460 static dbus_bool_t
01461 fill_user_info (DBusUserInfo       *info,
01462                 dbus_uid_t          uid,
01463                 const DBusString   *username,
01464                 DBusError          *error)
01465 {
01466   const char *username_c;
01467   
01468   /* exactly one of username/uid provided */
01469   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01470   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01471 
01472   info->uid = DBUS_UID_UNSET;
01473   info->primary_gid = DBUS_GID_UNSET;
01474   info->group_ids = NULL;
01475   info->n_group_ids = 0;
01476   info->username = NULL;
01477   info->homedir = NULL;
01478   
01479   if (username != NULL)
01480     username_c = _dbus_string_get_const_data (username);
01481   else
01482     username_c = NULL;
01483 
01484   /* For now assuming that the getpwnam() and getpwuid() flavors
01485    * are always symmetrical, if not we have to add more configure
01486    * checks
01487    */
01488   
01489 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01490   {
01491     struct passwd *p;
01492     int result;
01493     size_t buflen;
01494     char *buf;
01495     struct passwd p_str;
01496 
01497     /* retrieve maximum needed size for buf */
01498     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01499 
01500     /* sysconf actually returns a long, but everything else expects size_t,
01501      * so just recast here.
01502      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
01503      */
01504     if ((long) buflen <= 0)
01505       buflen = 1024;
01506 
01507     result = -1;
01508     while (1)
01509       {
01510         buf = dbus_malloc (buflen);
01511         if (buf == NULL)
01512           {
01513             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01514             return FALSE;
01515           }
01516 
01517         p = NULL;
01518 #ifdef HAVE_POSIX_GETPWNAM_R
01519         if (uid != DBUS_UID_UNSET)
01520           result = getpwuid_r (uid, &p_str, buf, buflen,
01521                                &p);
01522         else
01523           result = getpwnam_r (username_c, &p_str, buf, buflen,
01524                                &p);
01525 #else
01526         if (uid != DBUS_UID_UNSET)
01527           p = getpwuid_r (uid, &p_str, buf, buflen);
01528         else
01529           p = getpwnam_r (username_c, &p_str, buf, buflen);
01530         result = 0;
01531 #endif /* !HAVE_POSIX_GETPWNAM_R */
01532         //Try a bigger buffer if ERANGE was returned
01533         if (result == ERANGE && buflen < 512 * 1024)
01534           {
01535             dbus_free (buf);
01536             buflen *= 2;
01537           }
01538         else
01539           {
01540             break;
01541           }
01542       }
01543     if (result == 0 && p == &p_str)
01544       {
01545         if (!fill_user_info_from_passwd (p, info, error))
01546           {
01547             dbus_free (buf);
01548             return FALSE;
01549           }
01550         dbus_free (buf);
01551       }
01552     else
01553       {
01554         dbus_set_error (error, _dbus_error_from_errno (errno),
01555                         "User \"%s\" unknown or no memory to allocate password entry\n",
01556                         username_c ? username_c : "???");
01557         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01558         dbus_free (buf);
01559         return FALSE;
01560       }
01561   }
01562 #else /* ! HAVE_GETPWNAM_R */
01563   {
01564     /* I guess we're screwed on thread safety here */
01565     struct passwd *p;
01566 
01567     if (uid != DBUS_UID_UNSET)
01568       p = getpwuid (uid);
01569     else
01570       p = getpwnam (username_c);
01571 
01572     if (p != NULL)
01573       {
01574         if (!fill_user_info_from_passwd (p, info, error))
01575           {
01576             return FALSE;
01577           }
01578       }
01579     else
01580       {
01581         dbus_set_error (error, _dbus_error_from_errno (errno),
01582                         "User \"%s\" unknown or no memory to allocate password entry\n",
01583                         username_c ? username_c : "???");
01584         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01585         return FALSE;
01586       }
01587   }
01588 #endif  /* ! HAVE_GETPWNAM_R */
01589 
01590   /* Fill this in so we can use it to get groups */
01591   username_c = info->username;
01592   
01593 #ifdef HAVE_GETGROUPLIST
01594   {
01595     gid_t *buf;
01596     int buf_count;
01597     int i;
01598     int initial_buf_count;
01599 
01600     initial_buf_count = 17;
01601     buf_count = initial_buf_count;
01602     buf = dbus_new (gid_t, buf_count);
01603     if (buf == NULL)
01604       {
01605         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01606         goto failed;
01607       }
01608     
01609     if (getgrouplist (username_c,
01610                       info->primary_gid,
01611                       buf, &buf_count) < 0)
01612       {
01613         gid_t *new;
01614         /* Presumed cause of negative return code: buf has insufficient
01615            entries to hold the entire group list. The Linux behavior in this
01616            case is to pass back the actual number of groups in buf_count, but
01617            on Mac OS X 10.5, buf_count is unhelpfully left alone.
01618            So as a hack, try to help out a bit by guessing a larger
01619            number of groups, within reason.. might still fail, of course,
01620            but we can at least print a more informative message.  I looked up
01621            the "right way" to do this by downloading Apple's own source code
01622            for the "id" command, and it turns out that they use an
01623            undocumented library function getgrouplist_2 (!) which is not
01624            declared in any header in /usr/include (!!). That did not seem
01625            like the way to go here.  
01626         */
01627         if (buf_count == initial_buf_count) 
01628           { 
01629             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
01630           }
01631         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01632         if (new == NULL)
01633           {
01634             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01635             dbus_free (buf);
01636             goto failed;
01637           }
01638         
01639         buf = new;
01640 
01641         errno = 0;
01642         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01643           {
01644             if (errno == 0)
01645               {
01646                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
01647                             username_c, buf_count, buf_count);
01648               } 
01649             else
01650               {
01651                 dbus_set_error (error,
01652                                 _dbus_error_from_errno (errno),
01653                                 "Failed to get groups for username \"%s\" primary GID "
01654                                 DBUS_GID_FORMAT ": %s\n",
01655                                 username_c, info->primary_gid,
01656                                 _dbus_strerror (errno));
01657                 dbus_free (buf);
01658                 goto failed;
01659               }
01660           }
01661       }
01662 
01663     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01664     if (info->group_ids == NULL)
01665       {
01666         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01667         dbus_free (buf);
01668         goto failed;
01669       }
01670     
01671     for (i = 0; i < buf_count; ++i)
01672       info->group_ids[i] = buf[i];
01673 
01674     info->n_group_ids = buf_count;
01675     
01676     dbus_free (buf);
01677   }
01678 #else  /* HAVE_GETGROUPLIST */
01679   {
01680     /* We just get the one group ID */
01681     info->group_ids = dbus_new (dbus_gid_t, 1);
01682     if (info->group_ids == NULL)
01683       {
01684         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01685         goto failed;
01686       }
01687 
01688     info->n_group_ids = 1;
01689 
01690     (info->group_ids)[0] = info->primary_gid;
01691   }
01692 #endif /* HAVE_GETGROUPLIST */
01693 
01694   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01695   
01696   return TRUE;
01697   
01698  failed:
01699   _DBUS_ASSERT_ERROR_IS_SET (error);
01700   return FALSE;
01701 }
01702 
01711 dbus_bool_t
01712 _dbus_user_info_fill (DBusUserInfo     *info,
01713                       const DBusString *username,
01714                       DBusError        *error)
01715 {
01716   return fill_user_info (info, DBUS_UID_UNSET,
01717                          username, error);
01718 }
01719 
01728 dbus_bool_t
01729 _dbus_user_info_fill_uid (DBusUserInfo *info,
01730                           dbus_uid_t    uid,
01731                           DBusError    *error)
01732 {
01733   return fill_user_info (info, uid,
01734                          NULL, error);
01735 }
01736 
01744 dbus_bool_t
01745 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01746 {
01747   /* The POSIX spec certainly doesn't promise this, but
01748    * we need these assertions to fail as soon as we're wrong about
01749    * it so we can do the porting fixups
01750    */
01751   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01752   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01753   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01754 
01755   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01756     return FALSE;
01757   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01758     return FALSE;
01759 
01760   return TRUE;
01761 }
01762 
01774 dbus_bool_t
01775 _dbus_append_user_from_current_process (DBusString *str)
01776 {
01777   return _dbus_string_append_uint (str,
01778                                    _dbus_geteuid ());
01779 }
01780 
01785 dbus_pid_t
01786 _dbus_getpid (void)
01787 {
01788   return getpid ();
01789 }
01790 
01794 dbus_uid_t
01795 _dbus_getuid (void)
01796 {
01797   return getuid ();
01798 }
01799 
01803 dbus_uid_t
01804 _dbus_geteuid (void)
01805 {
01806   return geteuid ();
01807 }
01808 
01815 unsigned long
01816 _dbus_pid_for_log (void)
01817 {
01818   return getpid ();
01819 }
01820 
01828 dbus_bool_t
01829 _dbus_parse_uid (const DBusString      *uid_str,
01830                  dbus_uid_t            *uid)
01831 {
01832   int end;
01833   long val;
01834   
01835   if (_dbus_string_get_length (uid_str) == 0)
01836     {
01837       _dbus_verbose ("UID string was zero length\n");
01838       return FALSE;
01839     }
01840 
01841   val = -1;
01842   end = 0;
01843   if (!_dbus_string_parse_int (uid_str, 0, &val,
01844                                &end))
01845     {
01846       _dbus_verbose ("could not parse string as a UID\n");
01847       return FALSE;
01848     }
01849   
01850   if (end != _dbus_string_get_length (uid_str))
01851     {
01852       _dbus_verbose ("string contained trailing stuff after UID\n");
01853       return FALSE;
01854     }
01855 
01856   *uid = val;
01857 
01858   return TRUE;
01859 }
01860 
01861 
01862 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01863 
01864 #if DBUS_USE_ATOMIC_INT_486_COND
01865 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01866 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01867 static inline dbus_int32_t
01868 atomic_exchange_and_add (DBusAtomic            *atomic,
01869                          volatile dbus_int32_t  val)
01870 {
01871   register dbus_int32_t result;
01872 
01873   __asm__ __volatile__ ("lock; xaddl %0,%1"
01874                         : "=r" (result), "=m" (atomic->value)
01875                         : "0" (val), "m" (atomic->value));
01876   return result;
01877 }
01878 #endif
01879 
01888 dbus_int32_t
01889 _dbus_atomic_inc (DBusAtomic *atomic)
01890 {
01891 #if DBUS_USE_ATOMIC_INT_486_COND
01892   return atomic_exchange_and_add (atomic, 1);
01893 #else
01894   dbus_int32_t res;
01895   _DBUS_LOCK (atomic);
01896   res = atomic->value;
01897   atomic->value += 1;
01898   _DBUS_UNLOCK (atomic);
01899   return res;
01900 #endif
01901 }
01902 
01911 dbus_int32_t
01912 _dbus_atomic_dec (DBusAtomic *atomic)
01913 {
01914 #if DBUS_USE_ATOMIC_INT_486_COND
01915   return atomic_exchange_and_add (atomic, -1);
01916 #else
01917   dbus_int32_t res;
01918   
01919   _DBUS_LOCK (atomic);
01920   res = atomic->value;
01921   atomic->value -= 1;
01922   _DBUS_UNLOCK (atomic);
01923   return res;
01924 #endif
01925 }
01926 
01927 #ifdef DBUS_BUILD_TESTS
01928 
01931 dbus_gid_t
01932 _dbus_getgid (void)
01933 {
01934   return getgid ();
01935 }
01936 #endif
01937 
01946 int
01947 _dbus_poll (DBusPollFD *fds,
01948             int         n_fds,
01949             int         timeout_milliseconds)
01950 {
01951 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01952   /* This big thing is a constant expression and should get optimized
01953    * out of existence. So it's more robust than a configure check at
01954    * no cost.
01955    */
01956   if (_DBUS_POLLIN == POLLIN &&
01957       _DBUS_POLLPRI == POLLPRI &&
01958       _DBUS_POLLOUT == POLLOUT &&
01959       _DBUS_POLLERR == POLLERR &&
01960       _DBUS_POLLHUP == POLLHUP &&
01961       _DBUS_POLLNVAL == POLLNVAL &&
01962       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01963       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01964       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01965       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01966       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01967       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01968       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01969     {
01970       return poll ((struct pollfd*) fds,
01971                    n_fds, 
01972                    timeout_milliseconds);
01973     }
01974   else
01975     {
01976       /* We have to convert the DBusPollFD to an array of
01977        * struct pollfd, poll, and convert back.
01978        */
01979       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01980       return -1;
01981     }
01982 #else /* ! HAVE_POLL */
01983 
01984   fd_set read_set, write_set, err_set;
01985   int max_fd = 0;
01986   int i;
01987   struct timeval tv;
01988   int ready;
01989   
01990   FD_ZERO (&read_set);
01991   FD_ZERO (&write_set);
01992   FD_ZERO (&err_set);
01993 
01994   for (i = 0; i < n_fds; i++)
01995     {
01996       DBusPollFD *fdp = &fds[i];
01997 
01998       if (fdp->events & _DBUS_POLLIN)
01999         FD_SET (fdp->fd, &read_set);
02000 
02001       if (fdp->events & _DBUS_POLLOUT)
02002         FD_SET (fdp->fd, &write_set);
02003 
02004       FD_SET (fdp->fd, &err_set);
02005 
02006       max_fd = MAX (max_fd, fdp->fd);
02007     }
02008     
02009   tv.tv_sec = timeout_milliseconds / 1000;
02010   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02011 
02012   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02013                   timeout_milliseconds < 0 ? NULL : &tv);
02014 
02015   if (ready > 0)
02016     {
02017       for (i = 0; i < n_fds; i++)
02018         {
02019           DBusPollFD *fdp = &fds[i];
02020 
02021           fdp->revents = 0;
02022 
02023           if (FD_ISSET (fdp->fd, &read_set))
02024             fdp->revents |= _DBUS_POLLIN;
02025 
02026           if (FD_ISSET (fdp->fd, &write_set))
02027             fdp->revents |= _DBUS_POLLOUT;
02028 
02029           if (FD_ISSET (fdp->fd, &err_set))
02030             fdp->revents |= _DBUS_POLLERR;
02031         }
02032     }
02033 
02034   return ready;
02035 #endif
02036 }
02037 
02045 void
02046 _dbus_get_current_time (long *tv_sec,
02047                         long *tv_usec)
02048 {
02049   struct timeval t;
02050 
02051 #ifdef HAVE_MONOTONIC_CLOCK
02052   struct timespec ts;
02053   clock_gettime (CLOCK_MONOTONIC, &ts);
02054 
02055   if (tv_sec)
02056     *tv_sec = ts.tv_sec;
02057   if (tv_usec)
02058     *tv_usec = ts.tv_nsec / 1000;
02059 #else
02060   gettimeofday (&t, NULL);
02061 
02062   if (tv_sec)
02063     *tv_sec = t.tv_sec;
02064   if (tv_usec)
02065     *tv_usec = t.tv_usec;
02066 #endif
02067 }
02068 
02079 dbus_bool_t
02080 _dbus_file_get_contents (DBusString       *str,
02081                          const DBusString *filename,
02082                          DBusError        *error)
02083 {
02084   int fd;
02085   struct stat sb;
02086   int orig_len;
02087   int total;
02088   const char *filename_c;
02089 
02090   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02091   
02092   filename_c = _dbus_string_get_const_data (filename);
02093   
02094   /* O_BINARY useful on Cygwin */
02095   fd = open (filename_c, O_RDONLY | O_BINARY);
02096   if (fd < 0)
02097     {
02098       dbus_set_error (error, _dbus_error_from_errno (errno),
02099                       "Failed to open \"%s\": %s",
02100                       filename_c,
02101                       _dbus_strerror (errno));
02102       return FALSE;
02103     }
02104 
02105   _dbus_verbose ("file fd %d opened\n", fd);
02106   
02107   if (fstat (fd, &sb) < 0)
02108     {
02109       dbus_set_error (error, _dbus_error_from_errno (errno),
02110                       "Failed to stat \"%s\": %s",
02111                       filename_c,
02112                       _dbus_strerror (errno));
02113 
02114       _dbus_verbose ("fstat() failed: %s",
02115                      _dbus_strerror (errno));
02116       
02117       _dbus_close (fd, NULL);
02118       
02119       return FALSE;
02120     }
02121 
02122   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02123     {
02124       dbus_set_error (error, DBUS_ERROR_FAILED,
02125                       "File size %lu of \"%s\" is too large.",
02126                       (unsigned long) sb.st_size, filename_c);
02127       _dbus_close (fd, NULL);
02128       return FALSE;
02129     }
02130   
02131   total = 0;
02132   orig_len = _dbus_string_get_length (str);
02133   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02134     {
02135       int bytes_read;
02136 
02137       while (total < (int) sb.st_size)
02138         {
02139           bytes_read = _dbus_read (fd, str,
02140                                    sb.st_size - total);
02141           if (bytes_read <= 0)
02142             {
02143               dbus_set_error (error, _dbus_error_from_errno (errno),
02144                               "Error reading \"%s\": %s",
02145                               filename_c,
02146                               _dbus_strerror (errno));
02147 
02148               _dbus_verbose ("read() failed: %s",
02149                              _dbus_strerror (errno));
02150               
02151               _dbus_close (fd, NULL);
02152               _dbus_string_set_length (str, orig_len);
02153               return FALSE;
02154             }
02155           else
02156             total += bytes_read;
02157         }
02158 
02159       _dbus_close (fd, NULL);
02160       return TRUE;
02161     }
02162   else if (sb.st_size != 0)
02163     {
02164       _dbus_verbose ("Can only open regular files at the moment.\n");
02165       dbus_set_error (error, DBUS_ERROR_FAILED,
02166                       "\"%s\" is not a regular file",
02167                       filename_c);
02168       _dbus_close (fd, NULL);
02169       return FALSE;
02170     }
02171   else
02172     {
02173       _dbus_close (fd, NULL);
02174       return TRUE;
02175     }
02176 }
02177 
02187 dbus_bool_t
02188 _dbus_string_save_to_file (const DBusString *str,
02189                            const DBusString *filename,
02190                            DBusError        *error)
02191 {
02192   int fd;
02193   int bytes_to_write;
02194   const char *filename_c;
02195   DBusString tmp_filename;
02196   const char *tmp_filename_c;
02197   int total;
02198   dbus_bool_t need_unlink;
02199   dbus_bool_t retval;
02200 
02201   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02202   
02203   fd = -1;
02204   retval = FALSE;
02205   need_unlink = FALSE;
02206   
02207   if (!_dbus_string_init (&tmp_filename))
02208     {
02209       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02210       return FALSE;
02211     }
02212 
02213   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02214     {
02215       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02216       _dbus_string_free (&tmp_filename);
02217       return FALSE;
02218     }
02219   
02220   if (!_dbus_string_append (&tmp_filename, "."))
02221     {
02222       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02223       _dbus_string_free (&tmp_filename);
02224       return FALSE;
02225     }
02226 
02227 #define N_TMP_FILENAME_RANDOM_BYTES 8
02228   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02229     {
02230       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02231       _dbus_string_free (&tmp_filename);
02232       return FALSE;
02233     }
02234     
02235   filename_c = _dbus_string_get_const_data (filename);
02236   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02237 
02238   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02239              0600);
02240   if (fd < 0)
02241     {
02242       dbus_set_error (error, _dbus_error_from_errno (errno),
02243                       "Could not create %s: %s", tmp_filename_c,
02244                       _dbus_strerror (errno));
02245       goto out;
02246     }
02247 
02248   _dbus_verbose ("tmp file fd %d opened\n", fd);
02249   
02250   need_unlink = TRUE;
02251   
02252   total = 0;
02253   bytes_to_write = _dbus_string_get_length (str);
02254 
02255   while (total < bytes_to_write)
02256     {
02257       int bytes_written;
02258 
02259       bytes_written = _dbus_write (fd, str, total,
02260                                    bytes_to_write - total);
02261 
02262       if (bytes_written <= 0)
02263         {
02264           dbus_set_error (error, _dbus_error_from_errno (errno),
02265                           "Could not write to %s: %s", tmp_filename_c,
02266                           _dbus_strerror (errno));
02267           
02268           goto out;
02269         }
02270 
02271       total += bytes_written;
02272     }
02273 
02274   if (fsync(fd))
02275     {
02276       dbus_set_error (error, _dbus_error_from_errno (errno),
02277                       "Could not synchronize file %s: %s",
02278                       tmp_filename_c, _dbus_strerror (errno));
02279 
02280       goto out;
02281   }
02282 
02283   if (!_dbus_close (fd, NULL))
02284     {
02285       dbus_set_error (error, _dbus_error_from_errno (errno),
02286                       "Could not close file %s: %s",
02287                       tmp_filename_c, _dbus_strerror (errno));
02288 
02289       goto out;
02290     }
02291 
02292   fd = -1;
02293   
02294   if (rename (tmp_filename_c, filename_c) < 0)
02295     {
02296       dbus_set_error (error, _dbus_error_from_errno (errno),
02297                       "Could not rename %s to %s: %s",
02298                       tmp_filename_c, filename_c,
02299                       _dbus_strerror (errno));
02300 
02301       goto out;
02302     }
02303 
02304   need_unlink = FALSE;
02305   
02306   retval = TRUE;
02307   
02308  out:
02309   /* close first, then unlink, to prevent ".nfs34234235" garbage
02310    * files
02311    */
02312 
02313   if (fd >= 0)
02314     _dbus_close (fd, NULL);
02315         
02316   if (need_unlink && unlink (tmp_filename_c) < 0)
02317     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02318                    tmp_filename_c, _dbus_strerror (errno));
02319 
02320   _dbus_string_free (&tmp_filename);
02321 
02322   if (!retval)
02323     _DBUS_ASSERT_ERROR_IS_SET (error);
02324   
02325   return retval;
02326 }
02327 
02334 dbus_bool_t
02335 _dbus_make_file_world_readable(const DBusString *filename,
02336                                DBusError *error)
02337 {
02338   const char *filename_c;
02339 
02340   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02341 
02342   filename_c = _dbus_string_get_const_data (filename);
02343   if (chmod (filename_c, 0644) == -1)
02344     {
02345       dbus_set_error (error,
02346                       DBUS_ERROR_FAILED,
02347                       "Could not change permissions of file %s: %s\n",
02348                       filename_c,
02349                       _dbus_strerror (errno));
02350       return FALSE;
02351     }
02352   return TRUE;
02353 }
02354 
02361 dbus_bool_t
02362 _dbus_create_file_exclusively (const DBusString *filename,
02363                                DBusError        *error)
02364 {
02365   int fd;
02366   const char *filename_c;
02367 
02368   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02369   
02370   filename_c = _dbus_string_get_const_data (filename);
02371   
02372   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02373              0600);
02374   if (fd < 0)
02375     {
02376       dbus_set_error (error,
02377                       DBUS_ERROR_FAILED,
02378                       "Could not create file %s: %s\n",
02379                       filename_c,
02380                       _dbus_strerror (errno));
02381       return FALSE;
02382     }
02383 
02384   _dbus_verbose ("exclusive file fd %d opened\n", fd);
02385   
02386   if (!_dbus_close (fd, NULL))
02387     {
02388       dbus_set_error (error,
02389                       DBUS_ERROR_FAILED,
02390                       "Could not close file %s: %s\n",
02391                       filename_c,
02392                       _dbus_strerror (errno));
02393       return FALSE;
02394     }
02395   
02396   return TRUE;
02397 }
02398 
02407 dbus_bool_t
02408 _dbus_delete_file (const DBusString *filename,
02409                    DBusError        *error)
02410 {
02411   const char *filename_c;
02412 
02413   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02414   
02415   filename_c = _dbus_string_get_const_data (filename);
02416 
02417   if (unlink (filename_c) < 0)
02418     {
02419       dbus_set_error (error, DBUS_ERROR_FAILED,
02420                       "Failed to delete file %s: %s\n",
02421                       filename_c, _dbus_strerror (errno));
02422       return FALSE;
02423     }
02424   else
02425     return TRUE;
02426 }
02427 
02436 dbus_bool_t
02437 _dbus_create_directory (const DBusString *filename,
02438                         DBusError        *error)
02439 {
02440   const char *filename_c;
02441 
02442   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02443   
02444   filename_c = _dbus_string_get_const_data (filename);
02445 
02446   if (mkdir (filename_c, 0700) < 0)
02447     {
02448       if (errno == EEXIST)
02449         return TRUE;
02450       
02451       dbus_set_error (error, DBUS_ERROR_FAILED,
02452                       "Failed to create directory %s: %s\n",
02453                       filename_c, _dbus_strerror (errno));
02454       return FALSE;
02455     }
02456   else
02457     return TRUE;
02458 }
02459 
02470 dbus_bool_t
02471 _dbus_concat_dir_and_file (DBusString       *dir,
02472                            const DBusString *next_component)
02473 {
02474   dbus_bool_t dir_ends_in_slash;
02475   dbus_bool_t file_starts_with_slash;
02476 
02477   if (_dbus_string_get_length (dir) == 0 ||
02478       _dbus_string_get_length (next_component) == 0)
02479     return TRUE;
02480   
02481   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02482                                                     _dbus_string_get_length (dir) - 1);
02483 
02484   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02485 
02486   if (dir_ends_in_slash && file_starts_with_slash)
02487     {
02488       _dbus_string_shorten (dir, 1);
02489     }
02490   else if (!(dir_ends_in_slash || file_starts_with_slash))
02491     {
02492       if (!_dbus_string_append_byte (dir, '/'))
02493         return FALSE;
02494     }
02495 
02496   return _dbus_string_copy (next_component, 0, dir,
02497                             _dbus_string_get_length (dir));
02498 }
02499 
02501 #define NANOSECONDS_PER_SECOND       1000000000
02502 
02503 #define MICROSECONDS_PER_SECOND      1000000
02504 
02505 #define MILLISECONDS_PER_SECOND      1000
02506 
02507 #define NANOSECONDS_PER_MILLISECOND  1000000
02508 
02509 #define MICROSECONDS_PER_MILLISECOND 1000
02510 
02515 void
02516 _dbus_sleep_milliseconds (int milliseconds)
02517 {
02518 #ifdef HAVE_NANOSLEEP
02519   struct timespec req;
02520   struct timespec rem;
02521 
02522   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02523   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02524   rem.tv_sec = 0;
02525   rem.tv_nsec = 0;
02526 
02527   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02528     req = rem;
02529 #elif defined (HAVE_USLEEP)
02530   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02531 #else /* ! HAVE_USLEEP */
02532   sleep (MAX (milliseconds / 1000, 1));
02533 #endif
02534 }
02535 
02536 static dbus_bool_t
02537 _dbus_generate_pseudorandom_bytes (DBusString *str,
02538                                    int         n_bytes)
02539 {
02540   int old_len;
02541   char *p;
02542   
02543   old_len = _dbus_string_get_length (str);
02544 
02545   if (!_dbus_string_lengthen (str, n_bytes))
02546     return FALSE;
02547 
02548   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02549 
02550   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02551 
02552   return TRUE;
02553 }
02554 
02563 dbus_bool_t
02564 _dbus_generate_random_bytes (DBusString *str,
02565                              int         n_bytes)
02566 {
02567   int old_len;
02568   int fd;
02569 
02570   /* FALSE return means "no memory", if it could
02571    * mean something else then we'd need to return
02572    * a DBusError. So we always fall back to pseudorandom
02573    * if the I/O fails.
02574    */
02575   
02576   old_len = _dbus_string_get_length (str);
02577   fd = -1;
02578 
02579   /* note, urandom on linux will fall back to pseudorandom */
02580   fd = open ("/dev/urandom", O_RDONLY);
02581   if (fd < 0)
02582     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02583 
02584   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02585   
02586   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02587     {
02588       _dbus_close (fd, NULL);
02589       _dbus_string_set_length (str, old_len);
02590       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02591     }
02592 
02593   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02594                  n_bytes);
02595   
02596   _dbus_close (fd, NULL);
02597   
02598   return TRUE;
02599 }
02600 
02606 void
02607 _dbus_exit (int code)
02608 {
02609   _exit (code);
02610 }
02611 
02620 const char*
02621 _dbus_strerror (int error_number)
02622 {
02623   const char *msg;
02624   
02625   msg = strerror (error_number);
02626   if (msg == NULL)
02627     msg = "unknown";
02628 
02629   return msg;
02630 }
02631 
02635 void
02636 _dbus_disable_sigpipe (void)
02637 {
02638   signal (SIGPIPE, SIG_IGN);
02639 }
02640 
02648 void
02649 _dbus_fd_set_close_on_exec (int fd)
02650 {
02651   int val;
02652   
02653   val = fcntl (fd, F_GETFD, 0);
02654   
02655   if (val < 0)
02656     return;
02657 
02658   val |= FD_CLOEXEC;
02659   
02660   fcntl (fd, F_SETFD, val);
02661 }
02662 
02670 dbus_bool_t
02671 _dbus_close (int        fd,
02672              DBusError *error)
02673 {
02674   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02675   
02676  again:
02677   if (close (fd) < 0)
02678     {
02679       if (errno == EINTR)
02680         goto again;
02681 
02682       dbus_set_error (error, _dbus_error_from_errno (errno),
02683                       "Could not close fd %d", fd);
02684       return FALSE;
02685     }
02686 
02687   return TRUE;
02688 }
02689 
02697 dbus_bool_t
02698 _dbus_set_fd_nonblocking (int             fd,
02699                           DBusError      *error)
02700 {
02701   int val;
02702 
02703   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02704   
02705   val = fcntl (fd, F_GETFL, 0);
02706   if (val < 0)
02707     {
02708       dbus_set_error (error, _dbus_error_from_errno (errno),
02709                       "Failed to get flags from file descriptor %d: %s",
02710                       fd, _dbus_strerror (errno));
02711       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02712                      _dbus_strerror (errno));
02713       return FALSE;
02714     }
02715 
02716   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02717     {
02718       dbus_set_error (error, _dbus_error_from_errno (errno),
02719                       "Failed to set nonblocking flag of file descriptor %d: %s",
02720                       fd, _dbus_strerror (errno));
02721       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02722                      fd, _dbus_strerror (errno));
02723 
02724       return FALSE;
02725     }
02726 
02727   return TRUE;
02728 }
02729 
02735 void
02736 _dbus_print_backtrace (void)
02737 {  
02738 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02739   void *bt[500];
02740   int bt_size;
02741   int i;
02742   char **syms;
02743   
02744   bt_size = backtrace (bt, 500);
02745 
02746   syms = backtrace_symbols (bt, bt_size);
02747   
02748   i = 0;
02749   while (i < bt_size)
02750     {
02751       /* don't use dbus_warn since it can _dbus_abort() */
02752       fprintf (stderr, "  %s\n", syms[i]);
02753       ++i;
02754     }
02755   fflush (stderr);
02756 
02757   free (syms);
02758 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02759   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02760 #else
02761   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02762 #endif
02763 }
02764 
02780 dbus_bool_t
02781 _dbus_full_duplex_pipe (int        *fd1,
02782                         int        *fd2,
02783                         dbus_bool_t blocking,
02784                         DBusError  *error)
02785 {
02786 #ifdef HAVE_SOCKETPAIR
02787   int fds[2];
02788 
02789   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02790   
02791   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02792     {
02793       dbus_set_error (error, _dbus_error_from_errno (errno),
02794                       "Could not create full-duplex pipe");
02795       return FALSE;
02796     }
02797 
02798   if (!blocking &&
02799       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02800        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02801     {
02802       dbus_set_error (error, _dbus_error_from_errno (errno),
02803                       "Could not set full-duplex pipe nonblocking");
02804       
02805       _dbus_close (fds[0], NULL);
02806       _dbus_close (fds[1], NULL);
02807       
02808       return FALSE;
02809     }
02810   
02811   *fd1 = fds[0];
02812   *fd2 = fds[1];
02813 
02814   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02815                  *fd1, *fd2);
02816   
02817   return TRUE;  
02818 #else
02819   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02820   dbus_set_error (error, DBUS_ERROR_FAILED,
02821                   "_dbus_full_duplex_pipe() not implemented on this OS");
02822   return FALSE;
02823 #endif
02824 }
02825 
02834 int
02835 _dbus_printf_string_upper_bound (const char *format,
02836                                  va_list     args)
02837 {
02838   char c;
02839   return vsnprintf (&c, 1, format, args);
02840 }
02841 
02848 const char*
02849 _dbus_get_tmpdir(void)
02850 {
02851   static const char* tmpdir = NULL;
02852 
02853   if (tmpdir == NULL)
02854     {
02855       /* TMPDIR is what glibc uses, then
02856        * glibc falls back to the P_tmpdir macro which
02857        * just expands to "/tmp"
02858        */
02859       if (tmpdir == NULL)
02860         tmpdir = getenv("TMPDIR");
02861 
02862       /* These two env variables are probably
02863        * broken, but maybe some OS uses them?
02864        */
02865       if (tmpdir == NULL)
02866         tmpdir = getenv("TMP");
02867       if (tmpdir == NULL)
02868         tmpdir = getenv("TEMP");
02869 
02870       /* And this is the sane fallback. */
02871       if (tmpdir == NULL)
02872         tmpdir = "/tmp";
02873     }
02874   
02875   _dbus_assert(tmpdir != NULL);
02876   
02877   return tmpdir;
02878 }
02879 
02899 static dbus_bool_t
02900 _read_subprocess_line_argv (const char *progpath,
02901                             dbus_bool_t path_fallback,
02902                             char       * const *argv,
02903                             DBusString *result,
02904                             DBusError  *error)
02905 {
02906   int result_pipe[2] = { -1, -1 };
02907   int errors_pipe[2] = { -1, -1 };
02908   pid_t pid;
02909   int ret;
02910   int status;
02911   int orig_len;
02912   int i;
02913 
02914   dbus_bool_t retval;
02915   sigset_t new_set, old_set;
02916   
02917   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02918   retval = FALSE;
02919 
02920   /* We need to block any existing handlers for SIGCHLD temporarily; they
02921    * will cause waitpid() below to fail.
02922    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
02923    */
02924   sigemptyset (&new_set);
02925   sigaddset (&new_set, SIGCHLD);
02926   sigprocmask (SIG_BLOCK, &new_set, &old_set);
02927   
02928   orig_len = _dbus_string_get_length (result);
02929   
02930 #define READ_END        0
02931 #define WRITE_END       1
02932   if (pipe (result_pipe) < 0)
02933     {
02934       dbus_set_error (error, _dbus_error_from_errno (errno),
02935                       "Failed to create a pipe to call %s: %s",
02936                       progpath, _dbus_strerror (errno));
02937       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02938                      progpath, _dbus_strerror (errno));
02939       goto out;
02940     }
02941   if (pipe (errors_pipe) < 0)
02942     {
02943       dbus_set_error (error, _dbus_error_from_errno (errno),
02944                       "Failed to create a pipe to call %s: %s",
02945                       progpath, _dbus_strerror (errno));
02946       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02947                      progpath, _dbus_strerror (errno));
02948       goto out;
02949     }
02950 
02951   pid = fork ();
02952   if (pid < 0)
02953     {
02954       dbus_set_error (error, _dbus_error_from_errno (errno),
02955                       "Failed to fork() to call %s: %s",
02956                       progpath, _dbus_strerror (errno));
02957       _dbus_verbose ("Failed to fork() to call %s: %s\n",
02958                      progpath, _dbus_strerror (errno));
02959       goto out;
02960     }
02961 
02962   if (pid == 0)
02963     {
02964       /* child process */
02965       int maxfds;
02966       int fd;
02967 
02968       fd = open ("/dev/null", O_RDWR);
02969       if (fd == -1)
02970         /* huh?! can't open /dev/null? */
02971         _exit (1);
02972 
02973       _dbus_verbose ("/dev/null fd %d opened\n", fd);
02974       
02975       /* set-up stdXXX */
02976       close (result_pipe[READ_END]);
02977       close (errors_pipe[READ_END]);
02978       close (0);                /* close stdin */
02979       close (1);                /* close stdout */
02980       close (2);                /* close stderr */
02981 
02982       if (dup2 (fd, 0) == -1)
02983         _exit (1);
02984       if (dup2 (result_pipe[WRITE_END], 1) == -1)
02985         _exit (1);
02986       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02987         _exit (1);
02988 
02989       maxfds = sysconf (_SC_OPEN_MAX);
02990       /* Pick something reasonable if for some reason sysconf
02991        * says unlimited.
02992        */
02993       if (maxfds < 0)
02994         maxfds = 1024;
02995       /* close all inherited fds */
02996       for (i = 3; i < maxfds; i++)
02997         close (i);
02998 
02999       sigprocmask (SIG_SETMASK, &old_set, NULL);
03000 
03001       /* If it looks fully-qualified, try execv first */
03002       if (progpath[0] == '/')
03003         {
03004           execv (progpath, argv);
03005           /* Ok, that failed.  Now if path_fallback is given, let's
03006            * try unqualified.  This is mostly a hack to work
03007            * around systems which ship dbus-launch in /usr/bin
03008            * but everything else in /bin (because dbus-launch
03009            * depends on X11).
03010            */
03011           if (path_fallback)
03012             /* We must have a slash, because we checked above */
03013             execvp (strrchr (progpath, '/')+1, argv);
03014         }
03015       else
03016         execvp (progpath, argv);
03017 
03018       /* still nothing, we failed */
03019       _exit (1);
03020     }
03021 
03022   /* parent process */
03023   close (result_pipe[WRITE_END]);
03024   close (errors_pipe[WRITE_END]);
03025   result_pipe[WRITE_END] = -1;
03026   errors_pipe[WRITE_END] = -1;
03027 
03028   ret = 0;
03029   do 
03030     {
03031       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03032     }
03033   while (ret > 0);
03034 
03035   /* reap the child process to avoid it lingering as zombie */
03036   do
03037     {
03038       ret = waitpid (pid, &status, 0);
03039     }
03040   while (ret == -1 && errno == EINTR);
03041 
03042   /* We succeeded if the process exited with status 0 and
03043      anything was read */
03044   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03045     {
03046       /* The process ended with error */
03047       DBusString error_message;
03048       _dbus_string_init (&error_message);
03049       ret = 0;
03050       do
03051         {
03052           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03053         }
03054       while (ret > 0);
03055 
03056       _dbus_string_set_length (result, orig_len);
03057       if (_dbus_string_get_length (&error_message) > 0)
03058         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03059                         "%s terminated abnormally with the following error: %s",
03060                         progpath, _dbus_string_get_data (&error_message));
03061       else
03062         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03063                         "%s terminated abnormally without any error message",
03064                         progpath);
03065       goto out;
03066     }
03067 
03068   retval = TRUE;
03069   
03070  out:
03071   sigprocmask (SIG_SETMASK, &old_set, NULL);
03072 
03073   if (retval)
03074     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03075   else
03076     _DBUS_ASSERT_ERROR_IS_SET (error);
03077 
03078   if (result_pipe[0] != -1)
03079     close (result_pipe[0]);
03080   if (result_pipe[1] != -1)
03081     close (result_pipe[1]);
03082   if (errors_pipe[0] != -1)
03083     close (errors_pipe[0]);
03084   if (errors_pipe[1] != -1)
03085     close (errors_pipe[1]);
03086 
03087   return retval;  
03088 }
03089 
03101 dbus_bool_t
03102 _dbus_get_autolaunch_address (DBusString *address,
03103                               DBusError  *error)
03104 {
03105   static char *argv[6];
03106   int i;
03107   DBusString uuid;
03108   dbus_bool_t retval;
03109 
03110   if (_dbus_check_setuid ())
03111     {
03112       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03113                             "Unable to autolaunch when setuid");
03114       return FALSE;
03115     }
03116 
03117   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03118   retval = FALSE;
03119 
03120   if (!_dbus_string_init (&uuid))
03121     {
03122       _DBUS_SET_OOM (error);
03123       return FALSE;
03124     }
03125   
03126   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03127     {
03128       _DBUS_SET_OOM (error);
03129       goto out;
03130     }
03131   
03132   i = 0;
03133   argv[i] = "dbus-launch";
03134   ++i;
03135   argv[i] = "--autolaunch";
03136   ++i;
03137   argv[i] = _dbus_string_get_data (&uuid);
03138   ++i;
03139   argv[i] = "--binary-syntax";
03140   ++i;
03141   argv[i] = "--close-stderr";
03142   ++i;
03143   argv[i] = NULL;
03144   ++i;
03145 
03146   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03147 
03148   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03149                                        TRUE,
03150                                        argv, address, error);
03151 
03152  out:
03153   _dbus_string_free (&uuid);
03154   return retval;
03155 }
03156 
03175 dbus_bool_t
03176 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03177                                dbus_bool_t create_if_not_found,
03178                                DBusError  *error)
03179 {
03180   DBusString filename;
03181   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03182   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03183 }
03184 
03185 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03186 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03187 
03207 dbus_bool_t
03208 _dbus_lookup_session_address (dbus_bool_t *supported,
03209                               DBusString  *address,
03210                               DBusError   *error)
03211 {
03212   /* On non-Mac Unix platforms, if the session address isn't already
03213    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03214    * fall back to the autolaunch: global default; see 
03215    * init_session_address in dbus/dbus-bus.c. */
03216   *supported = FALSE;
03217   return TRUE;
03218 }
03219 
03237 dbus_bool_t 
03238 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03239 {
03240   const char *xdg_data_home;
03241   const char *xdg_data_dirs;
03242   DBusString servicedir_path;
03243 
03244   if (!_dbus_string_init (&servicedir_path))
03245     return FALSE;
03246 
03247   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03248   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03249 
03250   if (xdg_data_dirs != NULL)
03251     {
03252       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03253         goto oom;
03254 
03255       if (!_dbus_string_append (&servicedir_path, ":"))
03256         goto oom;
03257     }
03258   else
03259     {
03260       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03261         goto oom;
03262     }
03263 
03264   /* 
03265    * add configured datadir to defaults
03266    * this may be the same as an xdg dir
03267    * however the config parser should take 
03268    * care of duplicates 
03269    */
03270   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03271         goto oom;
03272 
03273   if (xdg_data_home != NULL)
03274     {
03275       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03276         goto oom;
03277     }
03278   else
03279     {
03280       const DBusString *homedir;
03281       DBusString local_share;
03282 
03283       if (!_dbus_homedir_from_current_process (&homedir))
03284         goto oom;
03285        
03286       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03287         goto oom;
03288 
03289       _dbus_string_init_const (&local_share, "/.local/share");
03290       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03291         goto oom;
03292     }
03293 
03294   if (!_dbus_split_paths_and_append (&servicedir_path, 
03295                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
03296                                      dirs))
03297     goto oom;
03298 
03299   _dbus_string_free (&servicedir_path);  
03300   return TRUE;
03301 
03302  oom:
03303   _dbus_string_free (&servicedir_path);
03304   return FALSE;
03305 }
03306 
03307 
03326 dbus_bool_t 
03327 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03328 {
03329   const char *xdg_data_dirs;
03330   DBusString servicedir_path;
03331 
03332   if (!_dbus_string_init (&servicedir_path))
03333     return FALSE;
03334 
03335   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03336 
03337   if (xdg_data_dirs != NULL)
03338     {
03339       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03340         goto oom;
03341 
03342       if (!_dbus_string_append (&servicedir_path, ":"))
03343         goto oom;
03344     }
03345   else
03346     {
03347       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03348         goto oom;
03349     }
03350 
03351   /* 
03352    * add configured datadir to defaults
03353    * this may be the same as an xdg dir
03354    * however the config parser should take 
03355    * care of duplicates 
03356    */
03357   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03358         goto oom;
03359 
03360   if (!_dbus_split_paths_and_append (&servicedir_path, 
03361                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 
03362                                      dirs))
03363     goto oom;
03364 
03365   _dbus_string_free (&servicedir_path);  
03366   return TRUE;
03367 
03368  oom:
03369   _dbus_string_free (&servicedir_path);
03370   return FALSE;
03371 }
03372 
03381 dbus_bool_t
03382 _dbus_append_system_config_file (DBusString *str)
03383 {
03384   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03385 }
03386 
03393 dbus_bool_t
03394 _dbus_append_session_config_file (DBusString *str)
03395 {
03396   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03397 }
03398 
03406 void
03407 _dbus_flush_caches (void)
03408 {
03409   _dbus_user_database_flush_system ();
03410 }
03411 
03425 dbus_bool_t
03426 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03427                                                 DBusCredentials *credentials)
03428 {
03429   DBusString homedir;
03430   DBusString dotdir;
03431   dbus_uid_t uid;
03432   
03433   _dbus_assert (credentials != NULL);
03434   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03435   
03436   if (!_dbus_string_init (&homedir))
03437     return FALSE;
03438 
03439   uid = _dbus_credentials_get_unix_uid (credentials);
03440   _dbus_assert (uid != DBUS_UID_UNSET);
03441 
03442   if (!_dbus_homedir_from_uid (uid, &homedir))
03443     goto failed;
03444   
03445 #ifdef DBUS_BUILD_TESTS
03446   {
03447     const char *override;
03448     
03449     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03450     if (override != NULL && *override != '\0')
03451       {
03452         _dbus_string_set_length (&homedir, 0);
03453         if (!_dbus_string_append (&homedir, override))
03454           goto failed;
03455 
03456         _dbus_verbose ("Using fake homedir for testing: %s\n",
03457                        _dbus_string_get_const_data (&homedir));
03458       }
03459     else
03460       {
03461         static dbus_bool_t already_warned = FALSE;
03462         if (!already_warned)
03463           {
03464             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03465             already_warned = TRUE;
03466           }
03467       }
03468   }
03469 #endif
03470 
03471   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03472   if (!_dbus_concat_dir_and_file (&homedir,
03473                                   &dotdir))
03474     goto failed;
03475   
03476   if (!_dbus_string_copy (&homedir, 0,
03477                           directory, _dbus_string_get_length (directory))) {
03478     goto failed;
03479   }
03480 
03481   _dbus_string_free (&homedir);
03482   return TRUE;
03483   
03484  failed: 
03485   _dbus_string_free (&homedir);
03486   return FALSE;
03487 }
03488 
03489 
03496 dbus_bool_t
03497 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03498 {
03499   return errno == EAGAIN || errno == EWOULDBLOCK;
03500 }
03501 
03511 dbus_bool_t
03512 _dbus_check_setuid (void)
03513 {
03514   /* TODO: get __libc_enable_secure exported from glibc.
03515    * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
03516    */
03517 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
03518   {
03519     /* See glibc/include/unistd.h */
03520     extern int __libc_enable_secure;
03521     return __libc_enable_secure;
03522   }
03523 #elif defined(HAVE_ISSETUGID)
03524   /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
03525   return issetugid ();
03526 #else
03527   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
03528   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
03529 
03530   static dbus_bool_t check_setuid_initialised;
03531   static dbus_bool_t is_setuid;
03532 
03533   if (_DBUS_UNLIKELY (!check_setuid_initialised))
03534     {
03535 #ifdef HAVE_GETRESUID
03536       if (getresuid (&ruid, &euid, &suid) != 0 ||
03537           getresgid (&rgid, &egid, &sgid) != 0)
03538 #endif /* HAVE_GETRESUID */
03539         {
03540           suid = ruid = getuid ();
03541           sgid = rgid = getgid ();
03542           euid = geteuid ();
03543           egid = getegid ();
03544         }
03545 
03546       check_setuid_initialised = TRUE;
03547       is_setuid = (ruid != euid || ruid != suid ||
03548                    rgid != egid || rgid != sgid);
03549 
03550     }
03551   return is_setuid;
03552 #endif
03553 }
03554 
03555 /* tests in dbus-sysdeps-util.c */

Generated on Thu Oct 4 2012 08:02:56 for D-Bus by  doxygen 1.7.1