dbus-sysdeps-unix.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-sysdeps-unix.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-protocol.h"
00030 #include "dbus-transport.h"
00031 #include "dbus-string.h"
00032 #include "dbus-userdb.h"
00033 #include "dbus-list.h"
00034 #include "dbus-credentials.h"
00035 
00036 #include <sys/types.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <signal.h>
00040 #include <unistd.h>
00041 #include <stdio.h>
00042 #include <fcntl.h>
00043 #include <sys/socket.h>
00044 #include <dirent.h>
00045 #include <sys/un.h>
00046 #include <pwd.h>
00047 #include <time.h>
00048 #include <locale.h>
00049 #include <sys/time.h>
00050 #include <sys/stat.h>
00051 #include <sys/wait.h>
00052 #include <netinet/in.h>
00053 #include <netdb.h>
00054 #include <grp.h>
00055 
00056 #ifdef HAVE_ERRNO_H
00057 #include <errno.h>
00058 #endif
00059 #ifdef HAVE_WRITEV
00060 #include <sys/uio.h>
00061 #endif
00062 #ifdef HAVE_POLL
00063 #include <sys/poll.h>
00064 #endif
00065 #ifdef HAVE_BACKTRACE
00066 #include <execinfo.h>
00067 #endif
00068 #ifdef HAVE_GETPEERUCRED
00069 #include <ucred.h>
00070 #endif
00071 
00072 #ifndef O_BINARY
00073 #define O_BINARY 0
00074 #endif
00075 
00076 #ifndef HAVE_SOCKLEN_T
00077 #define socklen_t int
00078 #endif
00079 
00080 static dbus_bool_t
00081 _dbus_open_socket (int              *fd_p,
00082                    int               domain,
00083                    int               type,
00084                    int               protocol,
00085                    DBusError        *error)
00086 {
00087   *fd_p = socket (domain, type, protocol);
00088   if (*fd_p >= 0)
00089     {
00090       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00091       return TRUE;
00092     }
00093   else
00094     {
00095       dbus_set_error(error,
00096                      _dbus_error_from_errno (errno),
00097                      "Failed to open socket: %s",
00098                      _dbus_strerror (errno));
00099       return FALSE;
00100     }
00101 }
00102 
00103 dbus_bool_t
00104 _dbus_open_tcp_socket (int              *fd,
00105                        DBusError        *error)
00106 {
00107   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00108 }
00109 
00117 dbus_bool_t
00118 _dbus_open_unix_socket (int              *fd,
00119                         DBusError        *error)
00120 {
00121   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00122 }
00123 
00132 dbus_bool_t 
00133 _dbus_close_socket (int               fd,
00134                     DBusError        *error)
00135 {
00136   return _dbus_close (fd, error);
00137 }
00138 
00148 int
00149 _dbus_read_socket (int               fd,
00150                    DBusString       *buffer,
00151                    int               count)
00152 {
00153   return _dbus_read (fd, buffer, count);
00154 }
00155 
00166 int
00167 _dbus_write_socket (int               fd,
00168                     const DBusString *buffer,
00169                     int               start,
00170                     int               len)
00171 {
00172   return _dbus_write (fd, buffer, start, len);
00173 }
00174 
00185 int
00186 _dbus_pipe_write (DBusPipe         *pipe,
00187                   const DBusString *buffer,
00188                   int               start,
00189                   int               len,
00190                   DBusError        *error)
00191 {
00192   int written;
00193   
00194   written = _dbus_write (pipe->fd_or_handle, buffer, start, len);
00195   if (written < 0)
00196     {
00197       dbus_set_error (error, DBUS_ERROR_FAILED,
00198                       "Writing to pipe: %s\n",
00199                       _dbus_strerror (errno));
00200     }
00201   return written;
00202 }
00203 
00211 int
00212 _dbus_pipe_close  (DBusPipe         *pipe,
00213                    DBusError        *error)
00214 {
00215   if (_dbus_close (pipe->fd_or_handle, error) < 0)
00216     {
00217       return -1;
00218     }
00219   else
00220     {
00221       _dbus_pipe_invalidate (pipe);
00222       return 0;
00223     }
00224 }
00225 
00239 int
00240 _dbus_write_socket_two (int               fd,
00241                         const DBusString *buffer1,
00242                         int               start1,
00243                         int               len1,
00244                         const DBusString *buffer2,
00245                         int               start2,
00246                         int               len2)
00247 {
00248   return _dbus_write_two (fd, buffer1, start1, len1,
00249                           buffer2, start2, len2);
00250 }
00251 
00252 
00269 int
00270 _dbus_read (int               fd,
00271             DBusString       *buffer,
00272             int               count)
00273 {
00274   int bytes_read;
00275   int start;
00276   char *data;
00277 
00278   _dbus_assert (count >= 0);
00279   
00280   start = _dbus_string_get_length (buffer);
00281 
00282   if (!_dbus_string_lengthen (buffer, count))
00283     {
00284       errno = ENOMEM;
00285       return -1;
00286     }
00287 
00288   data = _dbus_string_get_data_len (buffer, start, count);
00289 
00290  again:
00291   
00292   bytes_read = read (fd, data, count);
00293 
00294   if (bytes_read < 0)
00295     {
00296       if (errno == EINTR)
00297         goto again;
00298       else
00299         {
00300           /* put length back (note that this doesn't actually realloc anything) */
00301           _dbus_string_set_length (buffer, start);
00302           return -1;
00303         }
00304     }
00305   else
00306     {
00307       /* put length back (doesn't actually realloc) */
00308       _dbus_string_set_length (buffer, start + bytes_read);
00309 
00310 #if 0
00311       if (bytes_read > 0)
00312         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00313 #endif
00314       
00315       return bytes_read;
00316     }
00317 }
00318 
00329 int
00330 _dbus_write (int               fd,
00331              const DBusString *buffer,
00332              int               start,
00333              int               len)
00334 {
00335   const char *data;
00336   int bytes_written;
00337   
00338   data = _dbus_string_get_const_data_len (buffer, start, len);
00339   
00340  again:
00341 
00342   bytes_written = write (fd, data, len);
00343 
00344   if (bytes_written < 0 && errno == EINTR)
00345     goto again;
00346 
00347 #if 0
00348   if (bytes_written > 0)
00349     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00350 #endif
00351   
00352   return bytes_written;
00353 }
00354 
00375 int
00376 _dbus_write_two (int               fd,
00377                  const DBusString *buffer1,
00378                  int               start1,
00379                  int               len1,
00380                  const DBusString *buffer2,
00381                  int               start2,
00382                  int               len2)
00383 {
00384   _dbus_assert (buffer1 != NULL);
00385   _dbus_assert (start1 >= 0);
00386   _dbus_assert (start2 >= 0);
00387   _dbus_assert (len1 >= 0);
00388   _dbus_assert (len2 >= 0);
00389   
00390 #ifdef HAVE_WRITEV
00391   {
00392     struct iovec vectors[2];
00393     const char *data1;
00394     const char *data2;
00395     int bytes_written;
00396 
00397     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00398 
00399     if (buffer2 != NULL)
00400       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00401     else
00402       {
00403         data2 = NULL;
00404         start2 = 0;
00405         len2 = 0;
00406       }
00407    
00408     vectors[0].iov_base = (char*) data1;
00409     vectors[0].iov_len = len1;
00410     vectors[1].iov_base = (char*) data2;
00411     vectors[1].iov_len = len2;
00412 
00413   again:
00414    
00415     bytes_written = writev (fd,
00416                             vectors,
00417                             data2 ? 2 : 1);
00418 
00419     if (bytes_written < 0 && errno == EINTR)
00420       goto again;
00421    
00422     return bytes_written;
00423   }
00424 #else /* HAVE_WRITEV */
00425   {
00426     int ret1;
00427     
00428     ret1 = _dbus_write (fd, buffer1, start1, len1);
00429     if (ret1 == len1 && buffer2 != NULL)
00430       {
00431         ret2 = _dbus_write (fd, buffer2, start2, len2);
00432         if (ret2 < 0)
00433           ret2 = 0; /* we can't report an error as the first write was OK */
00434        
00435         return ret1 + ret2;
00436       }
00437     else
00438       return ret1;
00439   }
00440 #endif /* !HAVE_WRITEV */   
00441 }
00442 
00443 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00444 
00472 int
00473 _dbus_connect_unix_socket (const char     *path,
00474                            dbus_bool_t     abstract,
00475                            DBusError      *error)
00476 {
00477   int fd;
00478   size_t path_len;
00479   struct sockaddr_un addr;  
00480 
00481   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00482 
00483   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00484                  path, abstract);
00485   
00486   
00487   if (!_dbus_open_unix_socket (&fd, error))
00488     {
00489       _DBUS_ASSERT_ERROR_IS_SET(error);
00490       return -1;
00491     }
00492   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00493 
00494   _DBUS_ZERO (addr);
00495   addr.sun_family = AF_UNIX;
00496   path_len = strlen (path);
00497 
00498   if (abstract)
00499     {
00500 #ifdef HAVE_ABSTRACT_SOCKETS
00501       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00502       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00503 
00504       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00505         {
00506           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00507                       "Abstract socket name too long\n");
00508           _dbus_close (fd, NULL);
00509           return -1;
00510         }
00511         
00512       strncpy (&addr.sun_path[1], path, path_len);
00513       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00514 #else /* HAVE_ABSTRACT_SOCKETS */
00515       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00516                       "Operating system does not support abstract socket namespace\n");
00517       _dbus_close (fd, NULL);
00518       return -1;
00519 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00520     }
00521   else
00522     {
00523       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00524         {
00525           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00526                       "Socket name too long\n");
00527           _dbus_close (fd, NULL);
00528           return -1;
00529         }
00530 
00531       strncpy (addr.sun_path, path, path_len);
00532     }
00533   
00534   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00535     {      
00536       dbus_set_error (error,
00537                       _dbus_error_from_errno (errno),
00538                       "Failed to connect to socket %s: %s",
00539                       path, _dbus_strerror (errno));
00540 
00541       _dbus_close (fd, NULL);
00542       fd = -1;
00543       
00544       return -1;
00545     }
00546 
00547   if (!_dbus_set_fd_nonblocking (fd, error))
00548     {
00549       _DBUS_ASSERT_ERROR_IS_SET (error);
00550       
00551       _dbus_close (fd, NULL);
00552       fd = -1;
00553 
00554       return -1;
00555     }
00556 
00557   return fd;
00558 }
00559 
00569 static dbus_bool_t
00570 _dbus_set_local_creds (int fd, dbus_bool_t on)
00571 {
00572   dbus_bool_t retval = TRUE;
00573 
00574 #if defined(HAVE_CMSGCRED)
00575   /* NOOP just to make sure only one codepath is used 
00576    *      and to prefer CMSGCRED
00577    */
00578 #elif defined(LOCAL_CREDS) 
00579   int val = on ? 1 : 0;
00580   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00581     {
00582       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00583       retval = FALSE;
00584     }
00585   else
00586     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00587                    on ? "enabled" : "disabled", fd);
00588 #endif
00589 
00590   return retval;
00591 }
00592 
00608 int
00609 _dbus_listen_unix_socket (const char     *path,
00610                           dbus_bool_t     abstract,
00611                           DBusError      *error)
00612 {
00613   int listen_fd;
00614   struct sockaddr_un addr;
00615   size_t path_len;
00616 
00617   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00618 
00619   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00620                  path, abstract);
00621   
00622   if (!_dbus_open_unix_socket (&listen_fd, error))
00623     {
00624       _DBUS_ASSERT_ERROR_IS_SET(error);
00625       return -1;
00626     }
00627   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00628 
00629   _DBUS_ZERO (addr);
00630   addr.sun_family = AF_UNIX;
00631   path_len = strlen (path);
00632   
00633   if (abstract)
00634     {
00635 #ifdef HAVE_ABSTRACT_SOCKETS
00636       /* remember that abstract names aren't nul-terminated so we rely
00637        * on sun_path being filled in with zeroes above.
00638        */
00639       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00640       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00641 
00642       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00643         {
00644           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00645                       "Abstract socket name too long\n");
00646           _dbus_close (listen_fd, NULL);
00647           return -1;
00648         }
00649       
00650       strncpy (&addr.sun_path[1], path, path_len);
00651       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00652 #else /* HAVE_ABSTRACT_SOCKETS */
00653       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00654                       "Operating system does not support abstract socket namespace\n");
00655       _dbus_close (listen_fd, NULL);
00656       return -1;
00657 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00658     }
00659   else
00660     {
00661       /* Discussed security implications of this with Nalin,
00662        * and we couldn't think of where it would kick our ass, but
00663        * it still seems a bit sucky. It also has non-security suckage;
00664        * really we'd prefer to exit if the socket is already in use.
00665        * But there doesn't seem to be a good way to do this.
00666        *
00667        * Just to be extra careful, I threw in the stat() - clearly
00668        * the stat() can't *fix* any security issue, but it at least
00669        * avoids inadvertent/accidental data loss.
00670        */
00671       {
00672         struct stat sb;
00673 
00674         if (stat (path, &sb) == 0 &&
00675             S_ISSOCK (sb.st_mode))
00676           unlink (path);
00677       }
00678 
00679       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00680         {
00681           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00682                       "Abstract socket name too long\n");
00683           _dbus_close (listen_fd, NULL);
00684           return -1;
00685         }
00686         
00687       strncpy (addr.sun_path, path, path_len);
00688     }
00689   
00690   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00691     {
00692       dbus_set_error (error, _dbus_error_from_errno (errno),
00693                       "Failed to bind socket \"%s\": %s",
00694                       path, _dbus_strerror (errno));
00695       _dbus_close (listen_fd, NULL);
00696       return -1;
00697     }
00698 
00699   if (listen (listen_fd, 30 /* backlog */) < 0)
00700     {
00701       dbus_set_error (error, _dbus_error_from_errno (errno),
00702                       "Failed to listen on socket \"%s\": %s",
00703                       path, _dbus_strerror (errno));
00704       _dbus_close (listen_fd, NULL);
00705       return -1;
00706     }
00707 
00708   if (!_dbus_set_local_creds (listen_fd, TRUE))
00709     {
00710       dbus_set_error (error, _dbus_error_from_errno (errno),
00711                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00712                       path, _dbus_strerror (errno));
00713       close (listen_fd);
00714       return -1;
00715     }
00716 
00717   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00718     {
00719       _DBUS_ASSERT_ERROR_IS_SET (error);
00720       _dbus_close (listen_fd, NULL);
00721       return -1;
00722     }
00723   
00724   /* Try opening up the permissions, but if we can't, just go ahead
00725    * and continue, maybe it will be good enough.
00726    */
00727   if (!abstract && chmod (path, 0777) < 0)
00728     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00729                 path);
00730   
00731   return listen_fd;
00732 }
00733 
00744 int
00745 _dbus_connect_tcp_socket (const char     *host,
00746                           dbus_uint32_t   port,
00747                           DBusError      *error)
00748 {
00749   int fd;
00750   struct sockaddr_in addr;
00751   struct hostent *he;
00752   struct in_addr *haddr;
00753 
00754   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00755  
00756   
00757   if (!_dbus_open_tcp_socket (&fd, error))
00758     {
00759       _DBUS_ASSERT_ERROR_IS_SET(error);
00760       
00761       return -1;
00762     }
00763   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00764       
00765   if (host == NULL)
00766     host = "localhost";
00767 
00768   he = gethostbyname (host);
00769   if (he == NULL) 
00770     {
00771       dbus_set_error (error,
00772                       _dbus_error_from_errno (errno),
00773                       "Failed to lookup hostname: %s",
00774                       host);
00775       _dbus_close (fd, NULL);
00776       return -1;
00777     }
00778   
00779   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00780 
00781   _DBUS_ZERO (addr);
00782   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00783   addr.sin_family = AF_INET;
00784   addr.sin_port = htons (port);
00785   
00786   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00787     {      
00788       dbus_set_error (error,
00789                        _dbus_error_from_errno (errno),
00790                       "Failed to connect to socket %s:%d %s",
00791                       host, port, _dbus_strerror (errno));
00792 
00793       _dbus_close (fd, NULL);
00794       fd = -1;
00795       
00796       return -1;
00797     }
00798 
00799   if (!_dbus_set_fd_nonblocking (fd, error))
00800     {
00801       _dbus_close (fd, NULL);
00802       fd = -1;
00803 
00804       return -1;
00805     }
00806 
00807   return fd;
00808 }
00809 
00822 int
00823 _dbus_listen_tcp_socket (const char     *host,
00824                          dbus_uint32_t  *port,
00825                          dbus_bool_t     inaddr_any,
00826                          DBusError      *error)
00827 {
00828   int listen_fd;
00829   struct sockaddr_in addr;
00830   socklen_t len = (socklen_t) sizeof (struct sockaddr);
00831 
00832   _DBUS_ASSERT_ERROR_IS_CLEAR (error);  
00833   
00834   if (!_dbus_open_tcp_socket (&listen_fd, error))
00835     {
00836       _DBUS_ASSERT_ERROR_IS_SET(error);
00837       return -1;
00838     }
00839   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00840 
00841   _DBUS_ZERO (addr);
00842   
00843   if (inaddr_any)
00844     {
00845       addr.sin_addr.s_addr = INADDR_ANY;
00846     }
00847   else
00848     {
00849       struct hostent *he;
00850       struct in_addr *haddr;      
00851 
00852       he = gethostbyname (host);
00853       if (he == NULL) 
00854         {
00855           dbus_set_error (error,
00856                           _dbus_error_from_errno (errno),
00857                           "Failed to lookup hostname: %s",
00858                           host);
00859           _dbus_close (listen_fd, NULL);
00860           return -1;
00861         }
00862   
00863       haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00864       
00865       memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00866     }
00867   
00868   addr.sin_family = AF_INET;
00869   addr.sin_port = htons (*port);
00870 
00871   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00872     {
00873       dbus_set_error (error, _dbus_error_from_errno (errno),
00874                       "Failed to bind socket \"%s:%d\": %s",
00875                       host, *port, _dbus_strerror (errno));
00876       _dbus_close (listen_fd, NULL);
00877       return -1;
00878     }
00879 
00880   if (listen (listen_fd, 30 /* backlog */) < 0)
00881     {
00882       dbus_set_error (error, _dbus_error_from_errno (errno),  
00883                       "Failed to listen on socket \"%s:%d\": %s",
00884                       host, *port, _dbus_strerror (errno));
00885       _dbus_close (listen_fd, NULL);
00886       return -1;
00887     }
00888 
00889   getsockname(listen_fd, (struct sockaddr*) &addr, &len);
00890   *port = (dbus_uint32_t) ntohs(addr.sin_port);
00891 
00892   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00893     {
00894       _dbus_close (listen_fd, NULL);
00895       return -1;
00896     }
00897   
00898   return listen_fd;
00899 }
00900 
00901 static dbus_bool_t
00902 write_credentials_byte (int             server_fd,
00903                         DBusError      *error)
00904 {
00905   int bytes_written;
00906   char buf[1] = { '\0' };
00907 #if defined(HAVE_CMSGCRED) 
00908   struct {
00909           struct cmsghdr hdr;
00910           struct cmsgcred cred;
00911   } cmsg;
00912   struct iovec iov;
00913   struct msghdr msg;
00914   iov.iov_base = buf;
00915   iov.iov_len = 1;
00916 
00917   memset (&msg, 0, sizeof (msg));
00918   msg.msg_iov = &iov;
00919   msg.msg_iovlen = 1;
00920 
00921   msg.msg_control = &cmsg;
00922   msg.msg_controllen = sizeof (cmsg);
00923   memset (&cmsg, 0, sizeof (cmsg));
00924   cmsg.hdr.cmsg_len = sizeof (cmsg);
00925   cmsg.hdr.cmsg_level = SOL_SOCKET;
00926   cmsg.hdr.cmsg_type = SCM_CREDS;
00927 #endif
00928 
00929   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00930   
00931  again:
00932 
00933 #if defined(HAVE_CMSGCRED) 
00934   bytes_written = sendmsg (server_fd, &msg, 0);
00935 #else
00936   bytes_written = write (server_fd, buf, 1);
00937 #endif
00938 
00939   if (bytes_written < 0 && errno == EINTR)
00940     goto again;
00941 
00942   if (bytes_written < 0)
00943     {
00944       dbus_set_error (error, _dbus_error_from_errno (errno),
00945                       "Failed to write credentials byte: %s",
00946                      _dbus_strerror (errno));
00947       return FALSE;
00948     }
00949   else if (bytes_written == 0)
00950     {
00951       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00952                       "wrote zero bytes writing credentials byte");
00953       return FALSE;
00954     }
00955   else
00956     {
00957       _dbus_assert (bytes_written == 1);
00958       _dbus_verbose ("wrote credentials byte\n");
00959       return TRUE;
00960     }
00961 }
00962 
00984 dbus_bool_t
00985 _dbus_read_credentials_socket  (int              client_fd,
00986                                 DBusCredentials *credentials,
00987                                 DBusError       *error)
00988 {
00989   struct msghdr msg;
00990   struct iovec iov;
00991   char buf;
00992   dbus_uid_t uid_read;
00993   dbus_pid_t pid_read;
00994   int bytes_read;
00995   
00996   uid_read = DBUS_UID_UNSET;
00997   pid_read = DBUS_PID_UNSET;
00998   
00999 #ifdef HAVE_CMSGCRED 
01000   struct {
01001     struct cmsghdr hdr;
01002     struct cmsgcred cred;
01003   } cmsg;
01004 
01005 #elif defined(LOCAL_CREDS)
01006   struct {
01007     struct cmsghdr hdr;
01008     struct sockcred cred;
01009   } cmsg;
01010 #endif
01011 
01012   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01013   
01014   /* The POSIX spec certainly doesn't promise this, but
01015    * we need these assertions to fail as soon as we're wrong about
01016    * it so we can do the porting fixups
01017    */
01018   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01019   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01020   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01021 
01022   _dbus_credentials_clear (credentials);
01023 
01024   /* Systems supporting LOCAL_CREDS are configured to have this feature
01025    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01026    * the connection.  Therefore, the received message must carry the
01027    * credentials information without doing anything special.
01028    */
01029 
01030   iov.iov_base = &buf;
01031   iov.iov_len = 1;
01032 
01033   memset (&msg, 0, sizeof (msg));
01034   msg.msg_iov = &iov;
01035   msg.msg_iovlen = 1;
01036 
01037 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01038   memset (&cmsg, 0, sizeof (cmsg));
01039   msg.msg_control = &cmsg;
01040   msg.msg_controllen = sizeof (cmsg);
01041 #endif
01042 
01043  again:
01044   bytes_read = recvmsg (client_fd, &msg, 0);
01045 
01046   if (bytes_read < 0)
01047     {
01048       if (errno == EINTR)
01049         goto again;
01050 
01051       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01052        * normally only call read_credentials if the socket was ready
01053        * for reading
01054        */
01055       
01056       dbus_set_error (error, _dbus_error_from_errno (errno),
01057                       "Failed to read credentials byte: %s",
01058                       _dbus_strerror (errno));
01059       return FALSE;
01060     }
01061   else if (bytes_read == 0)
01062     {
01063       /* this should not happen unless we are using recvmsg wrong,
01064        * so is essentially here for paranoia
01065        */
01066       dbus_set_error (error, DBUS_ERROR_FAILED,
01067                       "Failed to read credentials byte (zero-length read)");
01068       return FALSE;
01069     }
01070   else if (buf != '\0')
01071     {
01072       dbus_set_error (error, DBUS_ERROR_FAILED,
01073                       "Credentials byte was not nul");
01074       return FALSE;
01075     }
01076 
01077 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01078   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
01079     {
01080       dbus_set_error (error, DBUS_ERROR_FAILED,
01081                       "Message from recvmsg() was not SCM_CREDS");
01082       return FALSE;
01083     }
01084 #endif
01085 
01086   _dbus_verbose ("read credentials byte\n");
01087 
01088   {
01089 #ifdef SO_PEERCRED
01090     struct ucred cr;   
01091     int cr_len = sizeof (cr);
01092    
01093     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01094         cr_len == sizeof (cr))
01095       {
01096         pid_read = cr.pid;
01097         uid_read = cr.uid;
01098       }
01099     else
01100       {
01101         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01102                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01103       }
01104 #elif defined(HAVE_CMSGCRED)
01105     pid_read = cmsg.cred.cmcred_pid;
01106     uid_read = cmsg.cred.cmcred_euid;
01107 #elif defined(LOCAL_CREDS)
01108     pid_read = DBUS_PID_UNSET;
01109     uid_read = cmsg.cred.sc_uid;
01110     /* Since we have already got the credentials from this socket, we can
01111      * disable its LOCAL_CREDS flag if it was ever set. */
01112     _dbus_set_local_creds (client_fd, FALSE);
01113 #elif defined(HAVE_GETPEEREID)
01114     uid_t euid;
01115     gid_t egid;
01116     if (getpeereid (client_fd, &euid, &egid) == 0)
01117       {
01118         uid_read = euid;
01119       }
01120     else
01121       {
01122         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01123       }
01124 #elif defined(HAVE_GETPEERUCRED)
01125     ucred_t * ucred = NULL;
01126     if (getpeerucred (client_fd, &ucred) == 0)
01127       {
01128         pid_read = ucred_getpid (ucred);
01129         uid_read = ucred_geteuid (ucred);
01130       }
01131     else
01132       {
01133         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01134       }
01135     if (ucred != NULL)
01136       ucred_free (ucred);
01137 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01138     _dbus_verbose ("Socket credentials not supported on this OS\n");
01139 #endif
01140   }
01141 
01142   _dbus_verbose ("Credentials:"
01143                  "  pid "DBUS_PID_FORMAT
01144                  "  uid "DBUS_UID_FORMAT
01145                  "\n",
01146                  pid_read,
01147                  uid_read);
01148 
01149   if (pid_read != DBUS_PID_UNSET)
01150     {
01151       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01152         {
01153           _DBUS_SET_OOM (error);
01154           return FALSE;
01155         }
01156     }
01157 
01158   if (uid_read != DBUS_UID_UNSET)
01159     {
01160       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01161         {
01162           _DBUS_SET_OOM (error);
01163           return FALSE;
01164         }
01165     }
01166   
01167   return TRUE;
01168 }
01169 
01187 dbus_bool_t
01188 _dbus_send_credentials_socket  (int              server_fd,
01189                                 DBusError       *error)
01190 {
01191   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01192   
01193   if (write_credentials_byte (server_fd, error))
01194     return TRUE;
01195   else
01196     return FALSE;
01197 }
01198 
01206 int
01207 _dbus_accept  (int listen_fd)
01208 {
01209   int client_fd;
01210   struct sockaddr addr;
01211   socklen_t addrlen;
01212 
01213   addrlen = sizeof (addr);
01214   
01215  retry:
01216   client_fd = accept (listen_fd, &addr, &addrlen);
01217   
01218   if (client_fd < 0)
01219     {
01220       if (errno == EINTR)
01221         goto retry;
01222     }
01223 
01224   _dbus_verbose ("client fd %d accepted\n", client_fd);
01225   
01226   return client_fd;
01227 }
01228 
01237 dbus_bool_t
01238 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01239 {
01240   const char *directory;
01241   struct stat sb;
01242         
01243   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01244     
01245   directory = _dbus_string_get_const_data (dir);
01246         
01247   if (stat (directory, &sb) < 0)
01248     {
01249       dbus_set_error (error, _dbus_error_from_errno (errno),
01250                       "%s", _dbus_strerror (errno));
01251    
01252       return FALSE;
01253     }
01254     
01255   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01256       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01257     {
01258       dbus_set_error (error, DBUS_ERROR_FAILED,
01259                      "%s directory is not private to the user", directory);
01260       return FALSE;
01261     }
01262     
01263   return TRUE;
01264 }
01265 
01266 static dbus_bool_t
01267 fill_user_info_from_passwd (struct passwd *p,
01268                             DBusUserInfo  *info,
01269                             DBusError     *error)
01270 {
01271   _dbus_assert (p->pw_name != NULL);
01272   _dbus_assert (p->pw_dir != NULL);
01273   
01274   info->uid = p->pw_uid;
01275   info->primary_gid = p->pw_gid;
01276   info->username = _dbus_strdup (p->pw_name);
01277   info->homedir = _dbus_strdup (p->pw_dir);
01278   
01279   if (info->username == NULL ||
01280       info->homedir == NULL)
01281     {
01282       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01283       return FALSE;
01284     }
01285 
01286   return TRUE;
01287 }
01288 
01289 static dbus_bool_t
01290 fill_user_info (DBusUserInfo       *info,
01291                 dbus_uid_t          uid,
01292                 const DBusString   *username,
01293                 DBusError          *error)
01294 {
01295   const char *username_c;
01296   
01297   /* exactly one of username/uid provided */
01298   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01299   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01300 
01301   info->uid = DBUS_UID_UNSET;
01302   info->primary_gid = DBUS_GID_UNSET;
01303   info->group_ids = NULL;
01304   info->n_group_ids = 0;
01305   info->username = NULL;
01306   info->homedir = NULL;
01307   
01308   if (username != NULL)
01309     username_c = _dbus_string_get_const_data (username);
01310   else
01311     username_c = NULL;
01312 
01313   /* For now assuming that the getpwnam() and getpwuid() flavors
01314    * are always symmetrical, if not we have to add more configure
01315    * checks
01316    */
01317   
01318 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01319   {
01320     struct passwd *p;
01321     int result;
01322     char buf[1024];
01323     struct passwd p_str;
01324 
01325     p = NULL;
01326 #ifdef HAVE_POSIX_GETPWNAM_R
01327     if (uid != DBUS_UID_UNSET)
01328       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01329                            &p);
01330     else
01331       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01332                            &p);
01333 #else
01334     if (uid != DBUS_UID_UNSET)
01335       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01336     else
01337       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01338     result = 0;
01339 #endif /* !HAVE_POSIX_GETPWNAM_R */
01340     if (result == 0 && p == &p_str)
01341       {
01342         if (!fill_user_info_from_passwd (p, info, error))
01343           return FALSE;
01344       }
01345     else
01346       {
01347         dbus_set_error (error, _dbus_error_from_errno (errno),
01348                         "User \"%s\" unknown or no memory to allocate password entry\n",
01349                         username_c ? username_c : "???");
01350         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01351         return FALSE;
01352       }
01353   }
01354 #else /* ! HAVE_GETPWNAM_R */
01355   {
01356     /* I guess we're screwed on thread safety here */
01357     struct passwd *p;
01358 
01359     if (uid != DBUS_UID_UNSET)
01360       p = getpwuid (uid);
01361     else
01362       p = getpwnam (username_c);
01363 
01364     if (p != NULL)
01365       {
01366         if (!fill_user_info_from_passwd (p, info, error))
01367           return FALSE;
01368       }
01369     else
01370       {
01371         dbus_set_error (error, _dbus_error_from_errno (errno),
01372                         "User \"%s\" unknown or no memory to allocate password entry\n",
01373                         username_c ? username_c : "???");
01374         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01375         return FALSE;
01376       }
01377   }
01378 #endif  /* ! HAVE_GETPWNAM_R */
01379 
01380   /* Fill this in so we can use it to get groups */
01381   username_c = info->username;
01382   
01383 #ifdef HAVE_GETGROUPLIST
01384   {
01385     gid_t *buf;
01386     int buf_count;
01387     int i;
01388     
01389     buf_count = 17;
01390     buf = dbus_new (gid_t, buf_count);
01391     if (buf == NULL)
01392       {
01393         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01394         goto failed;
01395       }
01396     
01397     if (getgrouplist (username_c,
01398                       info->primary_gid,
01399                       buf, &buf_count) < 0)
01400       {
01401         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01402         if (new == NULL)
01403           {
01404             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01405             dbus_free (buf);
01406             goto failed;
01407           }
01408         
01409         buf = new;
01410 
01411         errno = 0;
01412         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01413           {
01414             dbus_set_error (error,
01415                             _dbus_error_from_errno (errno),
01416                             "Failed to get groups for username \"%s\" primary GID "
01417                             DBUS_GID_FORMAT ": %s\n",
01418                             username_c, info->primary_gid,
01419                             _dbus_strerror (errno));
01420             dbus_free (buf);
01421             goto failed;
01422           }
01423       }
01424 
01425     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01426     if (info->group_ids == NULL)
01427       {
01428         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01429         dbus_free (buf);
01430         goto failed;
01431       }
01432     
01433     for (i = 0; i < buf_count; ++i)
01434       info->group_ids[i] = buf[i];
01435 
01436     info->n_group_ids = buf_count;
01437     
01438     dbus_free (buf);
01439   }
01440 #else  /* HAVE_GETGROUPLIST */
01441   {
01442     /* We just get the one group ID */
01443     info->group_ids = dbus_new (dbus_gid_t, 1);
01444     if (info->group_ids == NULL)
01445       {
01446         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01447         goto failed;
01448       }
01449 
01450     info->n_group_ids = 1;
01451 
01452     (info->group_ids)[0] = info->primary_gid;
01453   }
01454 #endif /* HAVE_GETGROUPLIST */
01455 
01456   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01457   
01458   return TRUE;
01459   
01460  failed:
01461   _DBUS_ASSERT_ERROR_IS_SET (error);
01462   return FALSE;
01463 }
01464 
01473 dbus_bool_t
01474 _dbus_user_info_fill (DBusUserInfo     *info,
01475                       const DBusString *username,
01476                       DBusError        *error)
01477 {
01478   return fill_user_info (info, DBUS_UID_UNSET,
01479                          username, error);
01480 }
01481 
01490 dbus_bool_t
01491 _dbus_user_info_fill_uid (DBusUserInfo *info,
01492                           dbus_uid_t    uid,
01493                           DBusError    *error)
01494 {
01495   return fill_user_info (info, uid,
01496                          NULL, error);
01497 }
01498 
01506 dbus_bool_t
01507 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01508 {
01509   /* The POSIX spec certainly doesn't promise this, but
01510    * we need these assertions to fail as soon as we're wrong about
01511    * it so we can do the porting fixups
01512    */
01513   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01514   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01515   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01516 
01517   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01518     return FALSE;
01519   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_getuid()))
01520     return FALSE;
01521 
01522   return TRUE;
01523 }
01524 
01536 dbus_bool_t
01537 _dbus_append_user_from_current_process (DBusString *str)
01538 {
01539   return _dbus_string_append_uint (str,
01540                                    _dbus_getuid ());
01541 }
01542 
01547 dbus_pid_t
01548 _dbus_getpid (void)
01549 {
01550   return getpid ();
01551 }
01552 
01556 dbus_uid_t
01557 _dbus_getuid (void)
01558 {
01559   return getuid ();
01560 }
01561 
01568 unsigned long
01569 _dbus_pid_for_log (void)
01570 {
01571   return getpid ();
01572 }
01573 
01581 dbus_bool_t
01582 _dbus_parse_uid (const DBusString      *uid_str,
01583                  dbus_uid_t            *uid)
01584 {
01585   int end;
01586   long val;
01587   
01588   if (_dbus_string_get_length (uid_str) == 0)
01589     {
01590       _dbus_verbose ("UID string was zero length\n");
01591       return FALSE;
01592     }
01593 
01594   val = -1;
01595   end = 0;
01596   if (!_dbus_string_parse_int (uid_str, 0, &val,
01597                                &end))
01598     {
01599       _dbus_verbose ("could not parse string as a UID\n");
01600       return FALSE;
01601     }
01602   
01603   if (end != _dbus_string_get_length (uid_str))
01604     {
01605       _dbus_verbose ("string contained trailing stuff after UID\n");
01606       return FALSE;
01607     }
01608 
01609   *uid = val;
01610 
01611   return TRUE;
01612 }
01613 
01614 
01615 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01616 
01617 #ifdef DBUS_USE_ATOMIC_INT_486
01618 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01619 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01620 static inline dbus_int32_t
01621 atomic_exchange_and_add (DBusAtomic            *atomic,
01622                          volatile dbus_int32_t  val)
01623 {
01624   register dbus_int32_t result;
01625 
01626   __asm__ __volatile__ ("lock; xaddl %0,%1"
01627                         : "=r" (result), "=m" (atomic->value)
01628                         : "0" (val), "m" (atomic->value));
01629   return result;
01630 }
01631 #endif
01632 
01641 dbus_int32_t
01642 _dbus_atomic_inc (DBusAtomic *atomic)
01643 {
01644 #ifdef DBUS_USE_ATOMIC_INT_486
01645   return atomic_exchange_and_add (atomic, 1);
01646 #else
01647   dbus_int32_t res;
01648   _DBUS_LOCK (atomic);
01649   res = atomic->value;
01650   atomic->value += 1;
01651   _DBUS_UNLOCK (atomic);
01652   return res;
01653 #endif
01654 }
01655 
01664 dbus_int32_t
01665 _dbus_atomic_dec (DBusAtomic *atomic)
01666 {
01667 #ifdef DBUS_USE_ATOMIC_INT_486
01668   return atomic_exchange_and_add (atomic, -1);
01669 #else
01670   dbus_int32_t res;
01671   
01672   _DBUS_LOCK (atomic);
01673   res = atomic->value;
01674   atomic->value -= 1;
01675   _DBUS_UNLOCK (atomic);
01676   return res;
01677 #endif
01678 }
01679 
01680 #ifdef DBUS_BUILD_TESTS
01681 
01684 dbus_gid_t
01685 _dbus_getgid (void)
01686 {
01687   return getgid ();
01688 }
01689 #endif
01690 
01699 int
01700 _dbus_poll (DBusPollFD *fds,
01701             int         n_fds,
01702             int         timeout_milliseconds)
01703 {
01704 #ifdef HAVE_POLL
01705   /* This big thing is a constant expression and should get optimized
01706    * out of existence. So it's more robust than a configure check at
01707    * no cost.
01708    */
01709   if (_DBUS_POLLIN == POLLIN &&
01710       _DBUS_POLLPRI == POLLPRI &&
01711       _DBUS_POLLOUT == POLLOUT &&
01712       _DBUS_POLLERR == POLLERR &&
01713       _DBUS_POLLHUP == POLLHUP &&
01714       _DBUS_POLLNVAL == POLLNVAL &&
01715       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01716       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01717       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01718       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01719       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01720       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01721       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01722     {
01723       return poll ((struct pollfd*) fds,
01724                    n_fds, 
01725                    timeout_milliseconds);
01726     }
01727   else
01728     {
01729       /* We have to convert the DBusPollFD to an array of
01730        * struct pollfd, poll, and convert back.
01731        */
01732       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01733       return -1;
01734     }
01735 #else /* ! HAVE_POLL */
01736 
01737   fd_set read_set, write_set, err_set;
01738   int max_fd = 0;
01739   int i;
01740   struct timeval tv;
01741   int ready;
01742   
01743   FD_ZERO (&read_set);
01744   FD_ZERO (&write_set);
01745   FD_ZERO (&err_set);
01746 
01747   for (i = 0; i < n_fds; i++)
01748     {
01749       DBusPollFD *fdp = &fds[i];
01750 
01751       if (fdp->events & _DBUS_POLLIN)
01752         FD_SET (fdp->fd, &read_set);
01753 
01754       if (fdp->events & _DBUS_POLLOUT)
01755         FD_SET (fdp->fd, &write_set);
01756 
01757       FD_SET (fdp->fd, &err_set);
01758 
01759       max_fd = MAX (max_fd, fdp->fd);
01760     }
01761     
01762   tv.tv_sec = timeout_milliseconds / 1000;
01763   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01764 
01765   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01766                   timeout_milliseconds < 0 ? NULL : &tv);
01767 
01768   if (ready > 0)
01769     {
01770       for (i = 0; i < n_fds; i++)
01771         {
01772           DBusPollFD *fdp = &fds[i];
01773 
01774           fdp->revents = 0;
01775 
01776           if (FD_ISSET (fdp->fd, &read_set))
01777             fdp->revents |= _DBUS_POLLIN;
01778 
01779           if (FD_ISSET (fdp->fd, &write_set))
01780             fdp->revents |= _DBUS_POLLOUT;
01781 
01782           if (FD_ISSET (fdp->fd, &err_set))
01783             fdp->revents |= _DBUS_POLLERR;
01784         }
01785     }
01786 
01787   return ready;
01788 #endif
01789 }
01790 
01797 void
01798 _dbus_get_current_time (long *tv_sec,
01799                         long *tv_usec)
01800 {
01801   struct timeval t;
01802 
01803   gettimeofday (&t, NULL);
01804 
01805   if (tv_sec)
01806     *tv_sec = t.tv_sec;
01807   if (tv_usec)
01808     *tv_usec = t.tv_usec;
01809 }
01810 
01821 dbus_bool_t
01822 _dbus_file_get_contents (DBusString       *str,
01823                          const DBusString *filename,
01824                          DBusError        *error)
01825 {
01826   int fd;
01827   struct stat sb;
01828   int orig_len;
01829   int total;
01830   const char *filename_c;
01831 
01832   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01833   
01834   filename_c = _dbus_string_get_const_data (filename);
01835   
01836   /* O_BINARY useful on Cygwin */
01837   fd = open (filename_c, O_RDONLY | O_BINARY);
01838   if (fd < 0)
01839     {
01840       dbus_set_error (error, _dbus_error_from_errno (errno),
01841                       "Failed to open \"%s\": %s",
01842                       filename_c,
01843                       _dbus_strerror (errno));
01844       return FALSE;
01845     }
01846 
01847   _dbus_verbose ("file fd %d opened\n", fd);
01848   
01849   if (fstat (fd, &sb) < 0)
01850     {
01851       dbus_set_error (error, _dbus_error_from_errno (errno),
01852                       "Failed to stat \"%s\": %s",
01853                       filename_c,
01854                       _dbus_strerror (errno));
01855 
01856       _dbus_verbose ("fstat() failed: %s",
01857                      _dbus_strerror (errno));
01858       
01859       _dbus_close (fd, NULL);
01860       
01861       return FALSE;
01862     }
01863 
01864   if (sb.st_size > _DBUS_ONE_MEGABYTE)
01865     {
01866       dbus_set_error (error, DBUS_ERROR_FAILED,
01867                       "File size %lu of \"%s\" is too large.",
01868                       (unsigned long) sb.st_size, filename_c);
01869       _dbus_close (fd, NULL);
01870       return FALSE;
01871     }
01872   
01873   total = 0;
01874   orig_len = _dbus_string_get_length (str);
01875   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
01876     {
01877       int bytes_read;
01878 
01879       while (total < (int) sb.st_size)
01880         {
01881           bytes_read = _dbus_read (fd, str,
01882                                    sb.st_size - total);
01883           if (bytes_read <= 0)
01884             {
01885               dbus_set_error (error, _dbus_error_from_errno (errno),
01886                               "Error reading \"%s\": %s",
01887                               filename_c,
01888                               _dbus_strerror (errno));
01889 
01890               _dbus_verbose ("read() failed: %s",
01891                              _dbus_strerror (errno));
01892               
01893               _dbus_close (fd, NULL);
01894               _dbus_string_set_length (str, orig_len);
01895               return FALSE;
01896             }
01897           else
01898             total += bytes_read;
01899         }
01900 
01901       _dbus_close (fd, NULL);
01902       return TRUE;
01903     }
01904   else if (sb.st_size != 0)
01905     {
01906       _dbus_verbose ("Can only open regular files at the moment.\n");
01907       dbus_set_error (error, DBUS_ERROR_FAILED,
01908                       "\"%s\" is not a regular file",
01909                       filename_c);
01910       _dbus_close (fd, NULL);
01911       return FALSE;
01912     }
01913   else
01914     {
01915       _dbus_close (fd, NULL);
01916       return TRUE;
01917     }
01918 }
01919 
01929 dbus_bool_t
01930 _dbus_string_save_to_file (const DBusString *str,
01931                            const DBusString *filename,
01932                            DBusError        *error)
01933 {
01934   int fd;
01935   int bytes_to_write;
01936   const char *filename_c;
01937   DBusString tmp_filename;
01938   const char *tmp_filename_c;
01939   int total;
01940   dbus_bool_t need_unlink;
01941   dbus_bool_t retval;
01942 
01943   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01944   
01945   fd = -1;
01946   retval = FALSE;
01947   need_unlink = FALSE;
01948   
01949   if (!_dbus_string_init (&tmp_filename))
01950     {
01951       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01952       return FALSE;
01953     }
01954 
01955   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
01956     {
01957       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01958       _dbus_string_free (&tmp_filename);
01959       return FALSE;
01960     }
01961   
01962   if (!_dbus_string_append (&tmp_filename, "."))
01963     {
01964       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01965       _dbus_string_free (&tmp_filename);
01966       return FALSE;
01967     }
01968 
01969 #define N_TMP_FILENAME_RANDOM_BYTES 8
01970   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
01971     {
01972       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01973       _dbus_string_free (&tmp_filename);
01974       return FALSE;
01975     }
01976     
01977   filename_c = _dbus_string_get_const_data (filename);
01978   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
01979 
01980   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01981              0600);
01982   if (fd < 0)
01983     {
01984       dbus_set_error (error, _dbus_error_from_errno (errno),
01985                       "Could not create %s: %s", tmp_filename_c,
01986                       _dbus_strerror (errno));
01987       goto out;
01988     }
01989 
01990   _dbus_verbose ("tmp file fd %d opened\n", fd);
01991   
01992   need_unlink = TRUE;
01993   
01994   total = 0;
01995   bytes_to_write = _dbus_string_get_length (str);
01996 
01997   while (total < bytes_to_write)
01998     {
01999       int bytes_written;
02000 
02001       bytes_written = _dbus_write (fd, str, total,
02002                                    bytes_to_write - total);
02003 
02004       if (bytes_written <= 0)
02005         {
02006           dbus_set_error (error, _dbus_error_from_errno (errno),
02007                           "Could not write to %s: %s", tmp_filename_c,
02008                           _dbus_strerror (errno));
02009           
02010           goto out;
02011         }
02012 
02013       total += bytes_written;
02014     }
02015 
02016   if (!_dbus_close (fd, NULL))
02017     {
02018       dbus_set_error (error, _dbus_error_from_errno (errno),
02019                       "Could not close file %s: %s",
02020                       tmp_filename_c, _dbus_strerror (errno));
02021 
02022       goto out;
02023     }
02024 
02025   fd = -1;
02026   
02027   if (rename (tmp_filename_c, filename_c) < 0)
02028     {
02029       dbus_set_error (error, _dbus_error_from_errno (errno),
02030                       "Could not rename %s to %s: %s",
02031                       tmp_filename_c, filename_c,
02032                       _dbus_strerror (errno));
02033 
02034       goto out;
02035     }
02036 
02037   need_unlink = FALSE;
02038   
02039   retval = TRUE;
02040   
02041  out:
02042   /* close first, then unlink, to prevent ".nfs34234235" garbage
02043    * files
02044    */
02045 
02046   if (fd >= 0)
02047     _dbus_close (fd, NULL);
02048         
02049   if (need_unlink && unlink (tmp_filename_c) < 0)
02050     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02051                    tmp_filename_c, _dbus_strerror (errno));
02052 
02053   _dbus_string_free (&tmp_filename);
02054 
02055   if (!retval)
02056     _DBUS_ASSERT_ERROR_IS_SET (error);
02057   
02058   return retval;
02059 }
02060 
02067 dbus_bool_t
02068 _dbus_make_file_world_readable(const DBusString *filename,
02069                                DBusError *error)
02070 {
02071   const char *filename_c;
02072 
02073   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02074 
02075   filename_c = _dbus_string_get_const_data (filename);
02076   if (chmod (filename_c, 0644) == -1)
02077     {
02078       dbus_set_error (error,
02079                       DBUS_ERROR_FAILED,
02080                       "Could not change permissions of file %s: %s\n",
02081                       filename_c,
02082                       _dbus_strerror (errno));
02083       return FALSE;
02084     }
02085   return TRUE;
02086 }
02087 
02094 dbus_bool_t
02095 _dbus_create_file_exclusively (const DBusString *filename,
02096                                DBusError        *error)
02097 {
02098   int fd;
02099   const char *filename_c;
02100 
02101   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02102   
02103   filename_c = _dbus_string_get_const_data (filename);
02104   
02105   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02106              0600);
02107   if (fd < 0)
02108     {
02109       dbus_set_error (error,
02110                       DBUS_ERROR_FAILED,
02111                       "Could not create file %s: %s\n",
02112                       filename_c,
02113                       _dbus_strerror (errno));
02114       return FALSE;
02115     }
02116 
02117   _dbus_verbose ("exclusive file fd %d opened\n", fd);
02118   
02119   if (!_dbus_close (fd, NULL))
02120     {
02121       dbus_set_error (error,
02122                       DBUS_ERROR_FAILED,
02123                       "Could not close file %s: %s\n",
02124                       filename_c,
02125                       _dbus_strerror (errno));
02126       return FALSE;
02127     }
02128   
02129   return TRUE;
02130 }
02131 
02140 dbus_bool_t
02141 _dbus_delete_file (const DBusString *filename,
02142                    DBusError        *error)
02143 {
02144   const char *filename_c;
02145 
02146   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02147   
02148   filename_c = _dbus_string_get_const_data (filename);
02149 
02150   if (unlink (filename_c) < 0)
02151     {
02152       dbus_set_error (error, DBUS_ERROR_FAILED,
02153                       "Failed to delete file %s: %s\n",
02154                       filename_c, _dbus_strerror (errno));
02155       return FALSE;
02156     }
02157   else
02158     return TRUE;
02159 }
02160 
02169 dbus_bool_t
02170 _dbus_create_directory (const DBusString *filename,
02171                         DBusError        *error)
02172 {
02173   const char *filename_c;
02174 
02175   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02176   
02177   filename_c = _dbus_string_get_const_data (filename);
02178 
02179   if (mkdir (filename_c, 0700) < 0)
02180     {
02181       if (errno == EEXIST)
02182         return TRUE;
02183       
02184       dbus_set_error (error, DBUS_ERROR_FAILED,
02185                       "Failed to create directory %s: %s\n",
02186                       filename_c, _dbus_strerror (errno));
02187       return FALSE;
02188     }
02189   else
02190     return TRUE;
02191 }
02192 
02203 dbus_bool_t
02204 _dbus_concat_dir_and_file (DBusString       *dir,
02205                            const DBusString *next_component)
02206 {
02207   dbus_bool_t dir_ends_in_slash;
02208   dbus_bool_t file_starts_with_slash;
02209 
02210   if (_dbus_string_get_length (dir) == 0 ||
02211       _dbus_string_get_length (next_component) == 0)
02212     return TRUE;
02213   
02214   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02215                                                     _dbus_string_get_length (dir) - 1);
02216 
02217   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02218 
02219   if (dir_ends_in_slash && file_starts_with_slash)
02220     {
02221       _dbus_string_shorten (dir, 1);
02222     }
02223   else if (!(dir_ends_in_slash || file_starts_with_slash))
02224     {
02225       if (!_dbus_string_append_byte (dir, '/'))
02226         return FALSE;
02227     }
02228 
02229   return _dbus_string_copy (next_component, 0, dir,
02230                             _dbus_string_get_length (dir));
02231 }
02232 
02234 #define NANOSECONDS_PER_SECOND       1000000000
02235 
02236 #define MICROSECONDS_PER_SECOND      1000000
02237 
02238 #define MILLISECONDS_PER_SECOND      1000
02239 
02240 #define NANOSECONDS_PER_MILLISECOND  1000000
02241 
02242 #define MICROSECONDS_PER_MILLISECOND 1000
02243 
02248 void
02249 _dbus_sleep_milliseconds (int milliseconds)
02250 {
02251 #ifdef HAVE_NANOSLEEP
02252   struct timespec req;
02253   struct timespec rem;
02254 
02255   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02256   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02257   rem.tv_sec = 0;
02258   rem.tv_nsec = 0;
02259 
02260   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02261     req = rem;
02262 #elif defined (HAVE_USLEEP)
02263   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02264 #else /* ! HAVE_USLEEP */
02265   sleep (MAX (milliseconds / 1000, 1));
02266 #endif
02267 }
02268 
02269 static dbus_bool_t
02270 _dbus_generate_pseudorandom_bytes (DBusString *str,
02271                                    int         n_bytes)
02272 {
02273   int old_len;
02274   char *p;
02275   
02276   old_len = _dbus_string_get_length (str);
02277 
02278   if (!_dbus_string_lengthen (str, n_bytes))
02279     return FALSE;
02280 
02281   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02282 
02283   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02284 
02285   return TRUE;
02286 }
02287 
02296 dbus_bool_t
02297 _dbus_generate_random_bytes (DBusString *str,
02298                              int         n_bytes)
02299 {
02300   int old_len;
02301   int fd;
02302 
02303   /* FALSE return means "no memory", if it could
02304    * mean something else then we'd need to return
02305    * a DBusError. So we always fall back to pseudorandom
02306    * if the I/O fails.
02307    */
02308   
02309   old_len = _dbus_string_get_length (str);
02310   fd = -1;
02311 
02312   /* note, urandom on linux will fall back to pseudorandom */
02313   fd = open ("/dev/urandom", O_RDONLY);
02314   if (fd < 0)
02315     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02316 
02317   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02318   
02319   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02320     {
02321       _dbus_close (fd, NULL);
02322       _dbus_string_set_length (str, old_len);
02323       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02324     }
02325 
02326   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02327                  n_bytes);
02328   
02329   _dbus_close (fd, NULL);
02330   
02331   return TRUE;
02332 }
02333 
02339 void
02340 _dbus_exit (int code)
02341 {
02342   _exit (code);
02343 }
02344 
02353 const char*
02354 _dbus_strerror (int error_number)
02355 {
02356   const char *msg;
02357   
02358   msg = strerror (error_number);
02359   if (msg == NULL)
02360     msg = "unknown";
02361 
02362   return msg;
02363 }
02364 
02368 void
02369 _dbus_disable_sigpipe (void)
02370 {
02371   signal (SIGPIPE, SIG_IGN);
02372 }
02373 
02381 void
02382 _dbus_fd_set_close_on_exec (int fd)
02383 {
02384   int val;
02385   
02386   val = fcntl (fd, F_GETFD, 0);
02387   
02388   if (val < 0)
02389     return;
02390 
02391   val |= FD_CLOEXEC;
02392   
02393   fcntl (fd, F_SETFD, val);
02394 }
02395 
02403 dbus_bool_t
02404 _dbus_close (int        fd,
02405              DBusError *error)
02406 {
02407   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02408   
02409  again:
02410   if (close (fd) < 0)
02411     {
02412       if (errno == EINTR)
02413         goto again;
02414 
02415       dbus_set_error (error, _dbus_error_from_errno (errno),
02416                       "Could not close fd %d", fd);
02417       return FALSE;
02418     }
02419 
02420   return TRUE;
02421 }
02422 
02430 dbus_bool_t
02431 _dbus_set_fd_nonblocking (int             fd,
02432                           DBusError      *error)
02433 {
02434   int val;
02435 
02436   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02437   
02438   val = fcntl (fd, F_GETFL, 0);
02439   if (val < 0)
02440     {
02441       dbus_set_error (error, _dbus_error_from_errno (errno),
02442                       "Failed to get flags from file descriptor %d: %s",
02443                       fd, _dbus_strerror (errno));
02444       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02445                      _dbus_strerror (errno));
02446       return FALSE;
02447     }
02448 
02449   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02450     {
02451       dbus_set_error (error, _dbus_error_from_errno (errno),
02452                       "Failed to set nonblocking flag of file descriptor %d: %s",
02453                       fd, _dbus_strerror (errno));
02454       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02455                      fd, _dbus_strerror (errno));
02456 
02457       return FALSE;
02458     }
02459 
02460   return TRUE;
02461 }
02462 
02468 void
02469 _dbus_print_backtrace (void)
02470 {  
02471 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02472   void *bt[500];
02473   int bt_size;
02474   int i;
02475   char **syms;
02476   
02477   bt_size = backtrace (bt, 500);
02478 
02479   syms = backtrace_symbols (bt, bt_size);
02480   
02481   i = 0;
02482   while (i < bt_size)
02483     {
02484       /* don't use dbus_warn since it can _dbus_abort() */
02485       fprintf (stderr, "  %s\n", syms[i]);
02486       ++i;
02487     }
02488   fflush (stderr);
02489 
02490   free (syms);
02491 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02492   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02493 #else
02494   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02495 #endif
02496 }
02497 
02513 dbus_bool_t
02514 _dbus_full_duplex_pipe (int        *fd1,
02515                         int        *fd2,
02516                         dbus_bool_t blocking,
02517                         DBusError  *error)
02518 {
02519 #ifdef HAVE_SOCKETPAIR
02520   int fds[2];
02521 
02522   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02523   
02524   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02525     {
02526       dbus_set_error (error, _dbus_error_from_errno (errno),
02527                       "Could not create full-duplex pipe");
02528       return FALSE;
02529     }
02530 
02531   if (!blocking &&
02532       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02533        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02534     {
02535       dbus_set_error (error, _dbus_error_from_errno (errno),
02536                       "Could not set full-duplex pipe nonblocking");
02537       
02538       _dbus_close (fds[0], NULL);
02539       _dbus_close (fds[1], NULL);
02540       
02541       return FALSE;
02542     }
02543   
02544   *fd1 = fds[0];
02545   *fd2 = fds[1];
02546 
02547   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02548                  *fd1, *fd2);
02549   
02550   return TRUE;  
02551 #else
02552   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02553   dbus_set_error (error, DBUS_ERROR_FAILED,
02554                   "_dbus_full_duplex_pipe() not implemented on this OS");
02555   return FALSE;
02556 #endif
02557 }
02558 
02559 
02568 int
02569 _dbus_printf_string_upper_bound (const char *format,
02570                                  va_list     args)
02571 {
02572   char c;
02573   return vsnprintf (&c, 1, format, args);
02574 }
02575 
02582 const char*
02583 _dbus_get_tmpdir(void)
02584 {
02585   static const char* tmpdir = NULL;
02586 
02587   if (tmpdir == NULL)
02588     {
02589       /* TMPDIR is what glibc uses, then
02590        * glibc falls back to the P_tmpdir macro which
02591        * just expands to "/tmp"
02592        */
02593       if (tmpdir == NULL)
02594         tmpdir = getenv("TMPDIR");
02595 
02596       /* These two env variables are probably
02597        * broken, but maybe some OS uses them?
02598        */
02599       if (tmpdir == NULL)
02600         tmpdir = getenv("TMP");
02601       if (tmpdir == NULL)
02602         tmpdir = getenv("TEMP");
02603 
02604       /* And this is the sane fallback. */
02605       if (tmpdir == NULL)
02606         tmpdir = "/tmp";
02607     }
02608   
02609   _dbus_assert(tmpdir != NULL);
02610   
02611   return tmpdir;
02612 }
02613 
02626 dbus_bool_t
02627 _dbus_get_autolaunch_address (DBusString *address,
02628                               DBusError  *error)
02629 {
02630   static char *argv[6];
02631   int address_pipe[2] = { -1, -1 };
02632   int errors_pipe[2] = { -1, -1 };
02633   pid_t pid;
02634   int ret;
02635   int status;
02636   int orig_len;
02637   int i;
02638   DBusString uuid;
02639   dbus_bool_t retval;
02640   
02641   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02642   retval = FALSE;
02643 
02644   _dbus_string_init (&uuid);
02645   
02646   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02647     {
02648       _DBUS_SET_OOM (error);
02649       goto out;
02650     }
02651   
02652   i = 0;
02653   argv[i] = "dbus-launch";
02654   ++i;
02655   argv[i] = "--autolaunch";
02656   ++i;
02657   argv[i] = _dbus_string_get_data (&uuid);
02658   ++i;
02659   argv[i] = "--binary-syntax";
02660   ++i;
02661   argv[i] = "--close-stderr";
02662   ++i;
02663   argv[i] = NULL;
02664   ++i;
02665 
02666   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02667   
02668   orig_len = _dbus_string_get_length (address);
02669   
02670 #define READ_END        0
02671 #define WRITE_END       1
02672   if (pipe (address_pipe) < 0)
02673     {
02674       dbus_set_error (error, _dbus_error_from_errno (errno),
02675                       "Failed to create a pipe: %s",
02676                       _dbus_strerror (errno));
02677       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02678                      _dbus_strerror (errno));
02679       goto out;
02680     }
02681   if (pipe (errors_pipe) < 0)
02682     {
02683       dbus_set_error (error, _dbus_error_from_errno (errno),
02684                       "Failed to create a pipe: %s",
02685                       _dbus_strerror (errno));
02686       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02687                      _dbus_strerror (errno));
02688       goto out;
02689     }
02690 
02691   pid = fork ();
02692   if (pid < 0)
02693     {
02694       dbus_set_error (error, _dbus_error_from_errno (errno),
02695                       "Failed to fork(): %s",
02696                       _dbus_strerror (errno));
02697       _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02698                      _dbus_strerror (errno));
02699       goto out;
02700     }
02701 
02702   if (pid == 0)
02703     {
02704       /* child process */
02705       int fd = open ("/dev/null", O_RDWR);
02706       if (fd == -1)
02707         /* huh?! can't open /dev/null? */
02708         _exit (1);
02709 
02710       _dbus_verbose ("/dev/null fd %d opened\n", fd);
02711       
02712       /* set-up stdXXX */
02713       close (address_pipe[READ_END]);
02714       close (errors_pipe[READ_END]);
02715       close (0);                /* close stdin */
02716       close (1);                /* close stdout */
02717       close (2);                /* close stderr */
02718 
02719       if (dup2 (fd, 0) == -1)
02720         _exit (1);
02721       if (dup2 (address_pipe[WRITE_END], 1) == -1)
02722         _exit (1);
02723       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02724         _exit (1);
02725 
02726       close (fd);
02727       close (address_pipe[WRITE_END]);
02728       close (errors_pipe[WRITE_END]);
02729 
02730       execv (DBUS_BINDIR "/dbus-launch", argv);
02731 
02732       /* failed, try searching PATH */
02733       execvp ("dbus-launch", argv);
02734 
02735       /* still nothing, we failed */
02736       _exit (1);
02737     }
02738 
02739   /* parent process */
02740   close (address_pipe[WRITE_END]);
02741   close (errors_pipe[WRITE_END]);
02742   address_pipe[WRITE_END] = -1;
02743   errors_pipe[WRITE_END] = -1;
02744 
02745   ret = 0;
02746   do 
02747     {
02748       ret = _dbus_read (address_pipe[READ_END], address, 1024);
02749     }
02750   while (ret > 0);
02751 
02752   /* reap the child process to avoid it lingering as zombie */
02753   do
02754     {
02755       ret = waitpid (pid, &status, 0);
02756     }
02757   while (ret == -1 && errno == EINTR);
02758 
02759   /* We succeeded if the process exited with status 0 and
02760      anything was read */
02761   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02762       _dbus_string_get_length (address) == orig_len)
02763     {
02764       /* The process ended with error */
02765       DBusString error_message;
02766       _dbus_string_init (&error_message);
02767       ret = 0;
02768       do
02769         {
02770           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
02771         }
02772       while (ret > 0);
02773 
02774       _dbus_string_set_length (address, orig_len);
02775       if (_dbus_string_get_length (&error_message) > 0)
02776         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02777                         "dbus-launch failed to autolaunch D-Bus session: %s",
02778                         _dbus_string_get_data (&error_message));
02779       else
02780         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02781                         "Failed to execute dbus-launch to autolaunch D-Bus session");
02782       goto out;
02783     }
02784 
02785   retval = TRUE;
02786   
02787  out:
02788   if (retval)
02789     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02790   else
02791     _DBUS_ASSERT_ERROR_IS_SET (error);
02792 
02793   if (address_pipe[0] != -1)
02794     close (address_pipe[0]);
02795   if (address_pipe[1] != -1)
02796     close (address_pipe[1]);
02797   if (errors_pipe[0] != -1)
02798     close (errors_pipe[0]);
02799   if (errors_pipe[1] != -1)
02800     close (errors_pipe[1]);
02801 
02802   _dbus_string_free (&uuid);
02803   return retval;
02804 }
02805 
02824 dbus_bool_t
02825 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
02826                                dbus_bool_t create_if_not_found,
02827                                DBusError  *error)
02828 {
02829   DBusString filename;
02830   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
02831   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
02832 }
02833 
02834 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
02835 
02836 
02854 dbus_bool_t 
02855 _dbus_get_standard_session_servicedirs (DBusList **dirs)
02856 {
02857   const char *xdg_data_home;
02858   const char *xdg_data_dirs;
02859   DBusString servicedir_path;
02860 
02861   if (!_dbus_string_init (&servicedir_path))
02862     return FALSE;
02863 
02864   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
02865   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
02866 
02867   if (xdg_data_dirs != NULL)
02868     {
02869       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
02870         goto oom;
02871 
02872       if (!_dbus_string_append (&servicedir_path, ":"))
02873         goto oom;
02874     }
02875   else
02876     {
02877       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
02878         goto oom;
02879     }
02880 
02881   /* 
02882    * add configured datadir to defaults
02883    * this may be the same as an xdg dir
02884    * however the config parser should take 
02885    * care of duplicates 
02886    */
02887   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
02888         goto oom;
02889 
02890   if (xdg_data_home != NULL)
02891     {
02892       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
02893         goto oom;
02894     }
02895   else
02896     {
02897       const DBusString *homedir;
02898       DBusString local_share;
02899 
02900       if (!_dbus_homedir_from_current_process (&homedir))
02901         goto oom;
02902        
02903       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
02904         goto oom;
02905 
02906       _dbus_string_init_const (&local_share, "/.local/share");
02907       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
02908         goto oom;
02909     }
02910 
02911   if (!_dbus_split_paths_and_append (&servicedir_path, 
02912                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
02913                                      dirs))
02914     goto oom;
02915 
02916   _dbus_string_free (&servicedir_path);  
02917   return TRUE;
02918 
02919  oom:
02920   _dbus_string_free (&servicedir_path);
02921   return FALSE;
02922 }
02923 
02932 dbus_bool_t
02933 _dbus_append_system_config_file (DBusString *str)
02934 {
02935   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
02936 }
02937 
02944 dbus_bool_t
02945 _dbus_append_session_config_file (DBusString *str)
02946 {
02947   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
02948 }
02949 
02957 void
02958 _dbus_flush_caches (void)
02959 {
02960   _dbus_user_database_flush_system ();
02961 }
02962 
02976 dbus_bool_t
02977 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
02978                                                 DBusCredentials *credentials)
02979 {
02980   DBusString homedir;
02981   DBusString dotdir;
02982   dbus_uid_t uid;
02983   
02984   _dbus_assert (credentials != NULL);
02985   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
02986   
02987   if (!_dbus_string_init (&homedir))
02988     return FALSE;
02989 
02990   uid = _dbus_credentials_get_unix_uid (credentials);
02991   _dbus_assert (uid != DBUS_UID_UNSET);
02992 
02993   if (!_dbus_homedir_from_uid (uid, &homedir))
02994     goto failed;
02995   
02996 #ifdef DBUS_BUILD_TESTS
02997   {
02998     const char *override;
02999     
03000     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03001     if (override != NULL && *override != '\0')
03002       {
03003         _dbus_string_set_length (&homedir, 0);
03004         if (!_dbus_string_append (&homedir, override))
03005           goto failed;
03006 
03007         _dbus_verbose ("Using fake homedir for testing: %s\n",
03008                        _dbus_string_get_const_data (&homedir));
03009       }
03010     else
03011       {
03012         static dbus_bool_t already_warned = FALSE;
03013         if (!already_warned)
03014           {
03015             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03016             already_warned = TRUE;
03017           }
03018       }
03019   }
03020 #endif
03021 
03022   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03023   if (!_dbus_concat_dir_and_file (&homedir,
03024                                   &dotdir))
03025     goto failed;
03026   
03027   if (!_dbus_string_copy (&homedir, 0,
03028                           directory, _dbus_string_get_length (directory))) {
03029     goto failed;
03030   }
03031 
03032   _dbus_string_free (&homedir);
03033   return TRUE;
03034   
03035  failed: 
03036   _dbus_string_free (&homedir);
03037   return FALSE;
03038 }
03039 
03040 
03047 dbus_bool_t
03048 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03049 {
03050   return errno == EAGAIN || errno == EWOULDBLOCK;
03051 }
03052 
03053 /* tests in dbus-sysdeps-util.c */

Generated on Fri Oct 5 11:45:35 2007 for D-Bus by  doxygen 1.5.3