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 <sys/types.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <signal.h>
00038 #include <unistd.h>
00039 #include <stdio.h>
00040 #include <fcntl.h>
00041 #include <sys/socket.h>
00042 #include <dirent.h>
00043 #include <sys/un.h>
00044 #include <pwd.h>
00045 #include <time.h>
00046 #include <locale.h>
00047 #include <sys/time.h>
00048 #include <sys/stat.h>
00049 #include <sys/wait.h>
00050 #include <netinet/in.h>
00051 #include <netdb.h>
00052 #include <grp.h>
00053 
00054 #ifdef HAVE_ERRNO_H
00055 #include <errno.h>
00056 #endif
00057 #ifdef HAVE_WRITEV
00058 #include <sys/uio.h>
00059 #endif
00060 #ifdef HAVE_POLL
00061 #include <sys/poll.h>
00062 #endif
00063 #ifdef HAVE_BACKTRACE
00064 #include <execinfo.h>
00065 #endif
00066 #ifdef HAVE_GETPEERUCRED
00067 #include <ucred.h>
00068 #endif
00069 
00070 #ifndef O_BINARY
00071 #define O_BINARY 0
00072 #endif
00073 
00074 #ifndef HAVE_SOCKLEN_T
00075 #define socklen_t int
00076 #endif
00077 
00078 static dbus_bool_t
00079 _dbus_open_socket (int              *fd_p,
00080                    int               domain,
00081                    int               type,
00082                    int               protocol,
00083                    DBusError        *error)
00084 {
00085   *fd_p = socket (domain, type, protocol);
00086   if (*fd_p >= 0)
00087     {
00088       return TRUE;
00089     }
00090   else
00091     {
00092       dbus_set_error(error,
00093                      _dbus_error_from_errno (errno),
00094                      "Failed to open socket: %s",
00095                      _dbus_strerror (errno));
00096       return FALSE;
00097     }
00098 }
00099 
00100 dbus_bool_t
00101 _dbus_open_tcp_socket (int              *fd,
00102                        DBusError        *error)
00103 {
00104   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00105 }
00106 
00114 dbus_bool_t
00115 _dbus_open_unix_socket (int              *fd,
00116                         DBusError        *error)
00117 {
00118   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00119 }
00120 
00129 dbus_bool_t 
00130 _dbus_close_socket (int               fd,
00131                     DBusError        *error)
00132 {
00133   return _dbus_close (fd, error);
00134 }
00135 
00145 int
00146 _dbus_read_socket (int               fd,
00147                    DBusString       *buffer,
00148                    int               count)
00149 {
00150   return _dbus_read (fd, buffer, count);
00151 }
00152 
00163 int
00164 _dbus_write_socket (int               fd,
00165                     const DBusString *buffer,
00166                     int               start,
00167                     int               len)
00168 {
00169   return _dbus_write (fd, buffer, start, len);
00170 }
00171 
00185 int
00186 _dbus_write_socket_two (int               fd,
00187                         const DBusString *buffer1,
00188                         int               start1,
00189                         int               len1,
00190                         const DBusString *buffer2,
00191                         int               start2,
00192                         int               len2)
00193 {
00194   return _dbus_write_two (fd, buffer1, start1, len1,
00195                           buffer2, start2, len2);
00196 }
00197 
00198 
00215 int
00216 _dbus_read (int               fd,
00217             DBusString       *buffer,
00218             int               count)
00219 {
00220   int bytes_read;
00221   int start;
00222   char *data;
00223 
00224   _dbus_assert (count >= 0);
00225   
00226   start = _dbus_string_get_length (buffer);
00227 
00228   if (!_dbus_string_lengthen (buffer, count))
00229     {
00230       errno = ENOMEM;
00231       return -1;
00232     }
00233 
00234   data = _dbus_string_get_data_len (buffer, start, count);
00235 
00236  again:
00237   
00238   bytes_read = read (fd, data, count);
00239 
00240   if (bytes_read < 0)
00241     {
00242       if (errno == EINTR)
00243         goto again;
00244       else
00245         {
00246           /* put length back (note that this doesn't actually realloc anything) */
00247           _dbus_string_set_length (buffer, start);
00248           return -1;
00249         }
00250     }
00251   else
00252     {
00253       /* put length back (doesn't actually realloc) */
00254       _dbus_string_set_length (buffer, start + bytes_read);
00255 
00256 #if 0
00257       if (bytes_read > 0)
00258         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00259 #endif
00260       
00261       return bytes_read;
00262     }
00263 }
00264 
00275 int
00276 _dbus_write (int               fd,
00277              const DBusString *buffer,
00278              int               start,
00279              int               len)
00280 {
00281   const char *data;
00282   int bytes_written;
00283   
00284   data = _dbus_string_get_const_data_len (buffer, start, len);
00285   
00286  again:
00287 
00288   bytes_written = write (fd, data, len);
00289 
00290   if (bytes_written < 0 && errno == EINTR)
00291     goto again;
00292 
00293 #if 0
00294   if (bytes_written > 0)
00295     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00296 #endif
00297   
00298   return bytes_written;
00299 }
00300 
00321 int
00322 _dbus_write_two (int               fd,
00323                  const DBusString *buffer1,
00324                  int               start1,
00325                  int               len1,
00326                  const DBusString *buffer2,
00327                  int               start2,
00328                  int               len2)
00329 {
00330   _dbus_assert (buffer1 != NULL);
00331   _dbus_assert (start1 >= 0);
00332   _dbus_assert (start2 >= 0);
00333   _dbus_assert (len1 >= 0);
00334   _dbus_assert (len2 >= 0);
00335   
00336 #ifdef HAVE_WRITEV
00337   {
00338     struct iovec vectors[2];
00339     const char *data1;
00340     const char *data2;
00341     int bytes_written;
00342 
00343     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00344 
00345     if (buffer2 != NULL)
00346       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00347     else
00348       {
00349         data2 = NULL;
00350         start2 = 0;
00351         len2 = 0;
00352       }
00353    
00354     vectors[0].iov_base = (char*) data1;
00355     vectors[0].iov_len = len1;
00356     vectors[1].iov_base = (char*) data2;
00357     vectors[1].iov_len = len2;
00358 
00359   again:
00360    
00361     bytes_written = writev (fd,
00362                             vectors,
00363                             data2 ? 2 : 1);
00364 
00365     if (bytes_written < 0 && errno == EINTR)
00366       goto again;
00367    
00368     return bytes_written;
00369   }
00370 #else /* HAVE_WRITEV */
00371   {
00372     int ret1;
00373     
00374     ret1 = _dbus_write (fd, buffer1, start1, len1);
00375     if (ret1 == len1 && buffer2 != NULL)
00376       {
00377         ret2 = _dbus_write (fd, buffer2, start2, len2);
00378         if (ret2 < 0)
00379           ret2 = 0; /* we can't report an error as the first write was OK */
00380        
00381         return ret1 + ret2;
00382       }
00383     else
00384       return ret1;
00385   }
00386 #endif /* !HAVE_WRITEV */   
00387 }
00388 
00389 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00390 
00418 int
00419 _dbus_connect_unix_socket (const char     *path,
00420                            dbus_bool_t     abstract,
00421                            DBusError      *error)
00422 {
00423   int fd;
00424   size_t path_len;
00425   struct sockaddr_un addr;  
00426 
00427   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00428 
00429   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00430                  path, abstract);
00431   
00432   
00433   if (!_dbus_open_unix_socket (&fd, error))
00434     {
00435       _DBUS_ASSERT_ERROR_IS_SET(error);
00436       return -1;
00437     }
00438   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00439 
00440   _DBUS_ZERO (addr);
00441   addr.sun_family = AF_UNIX;
00442   path_len = strlen (path);
00443 
00444   if (abstract)
00445     {
00446 #ifdef HAVE_ABSTRACT_SOCKETS
00447       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00448       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00449 
00450       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00451         {
00452           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00453                       "Abstract socket name too long\n");
00454           _dbus_close (fd, NULL);
00455           return -1;
00456         }
00457         
00458       strncpy (&addr.sun_path[1], path, path_len);
00459       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00460 #else /* HAVE_ABSTRACT_SOCKETS */
00461       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00462                       "Operating system does not support abstract socket namespace\n");
00463       _dbus_close (fd, NULL);
00464       return -1;
00465 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00466     }
00467   else
00468     {
00469       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00470         {
00471           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00472                       "Socket name too long\n");
00473           _dbus_close (fd, NULL);
00474           return -1;
00475         }
00476 
00477       strncpy (addr.sun_path, path, path_len);
00478     }
00479   
00480   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00481     {      
00482       dbus_set_error (error,
00483                       _dbus_error_from_errno (errno),
00484                       "Failed to connect to socket %s: %s",
00485                       path, _dbus_strerror (errno));
00486 
00487       _dbus_close (fd, NULL);
00488       fd = -1;
00489       
00490       return -1;
00491     }
00492 
00493   if (!_dbus_set_fd_nonblocking (fd, error))
00494     {
00495       _DBUS_ASSERT_ERROR_IS_SET (error);
00496       
00497       _dbus_close (fd, NULL);
00498       fd = -1;
00499 
00500       return -1;
00501     }
00502 
00503   return fd;
00504 }
00505 
00515 static dbus_bool_t
00516 _dbus_set_local_creds (int fd, dbus_bool_t on)
00517 {
00518   dbus_bool_t retval = TRUE;
00519 
00520 #if defined(HAVE_CMSGCRED)
00521   /* NOOP just to make sure only one codepath is used 
00522    *      and to prefer CMSGCRED
00523    */
00524 #elif defined(LOCAL_CREDS) 
00525   int val = on ? 1 : 0;
00526   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00527     {
00528       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00529       retval = FALSE;
00530     }
00531   else
00532     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00533                    on ? "enabled" : "disabled", fd);
00534 #endif
00535 
00536   return retval;
00537 }
00538 
00554 int
00555 _dbus_listen_unix_socket (const char     *path,
00556                           dbus_bool_t     abstract,
00557                           DBusError      *error)
00558 {
00559   int listen_fd;
00560   struct sockaddr_un addr;
00561   size_t path_len;
00562 
00563   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00564 
00565   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00566                  path, abstract);
00567   
00568   if (!_dbus_open_unix_socket (&listen_fd, error))
00569     {
00570       _DBUS_ASSERT_ERROR_IS_SET(error);
00571       return -1;
00572     }
00573   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00574 
00575   _DBUS_ZERO (addr);
00576   addr.sun_family = AF_UNIX;
00577   path_len = strlen (path);
00578   
00579   if (abstract)
00580     {
00581 #ifdef HAVE_ABSTRACT_SOCKETS
00582       /* remember that abstract names aren't nul-terminated so we rely
00583        * on sun_path being filled in with zeroes above.
00584        */
00585       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00586       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00587 
00588       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00589         {
00590           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00591                       "Abstract socket name too long\n");
00592           _dbus_close (listen_fd, NULL);
00593           return -1;
00594         }
00595       
00596       strncpy (&addr.sun_path[1], path, path_len);
00597       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00598 #else /* HAVE_ABSTRACT_SOCKETS */
00599       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00600                       "Operating system does not support abstract socket namespace\n");
00601       _dbus_close (listen_fd, NULL);
00602       return -1;
00603 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00604     }
00605   else
00606     {
00607       /* Discussed security implications of this with Nalin,
00608        * and we couldn't think of where it would kick our ass, but
00609        * it still seems a bit sucky. It also has non-security suckage;
00610        * really we'd prefer to exit if the socket is already in use.
00611        * But there doesn't seem to be a good way to do this.
00612        *
00613        * Just to be extra careful, I threw in the stat() - clearly
00614        * the stat() can't *fix* any security issue, but it at least
00615        * avoids inadvertent/accidental data loss.
00616        */
00617       {
00618         struct stat sb;
00619 
00620         if (stat (path, &sb) == 0 &&
00621             S_ISSOCK (sb.st_mode))
00622           unlink (path);
00623       }
00624 
00625       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00626         {
00627           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00628                       "Abstract socket name too long\n");
00629           _dbus_close (listen_fd, NULL);
00630           return -1;
00631         }
00632         
00633       strncpy (addr.sun_path, path, path_len);
00634     }
00635   
00636   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00637     {
00638       dbus_set_error (error, _dbus_error_from_errno (errno),
00639                       "Failed to bind socket \"%s\": %s",
00640                       path, _dbus_strerror (errno));
00641       _dbus_close (listen_fd, NULL);
00642       return -1;
00643     }
00644 
00645   if (listen (listen_fd, 30 /* backlog */) < 0)
00646     {
00647       dbus_set_error (error, _dbus_error_from_errno (errno),
00648                       "Failed to listen on socket \"%s\": %s",
00649                       path, _dbus_strerror (errno));
00650       _dbus_close (listen_fd, NULL);
00651       return -1;
00652     }
00653 
00654   if (!_dbus_set_local_creds (listen_fd, TRUE))
00655     {
00656       dbus_set_error (error, _dbus_error_from_errno (errno),
00657                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00658                       path, _dbus_strerror (errno));
00659       close (listen_fd);
00660       return -1;
00661     }
00662 
00663   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00664     {
00665       _DBUS_ASSERT_ERROR_IS_SET (error);
00666       _dbus_close (listen_fd, NULL);
00667       return -1;
00668     }
00669   
00670   /* Try opening up the permissions, but if we can't, just go ahead
00671    * and continue, maybe it will be good enough.
00672    */
00673   if (!abstract && chmod (path, 0777) < 0)
00674     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00675                 path);
00676   
00677   return listen_fd;
00678 }
00679 
00690 int
00691 _dbus_connect_tcp_socket (const char     *host,
00692                           dbus_uint32_t   port,
00693                           DBusError      *error)
00694 {
00695   int fd;
00696   struct sockaddr_in addr;
00697   struct hostent *he;
00698   struct in_addr *haddr;
00699 
00700   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00701  
00702   
00703   if (!_dbus_open_tcp_socket (&fd, error))
00704     {
00705       _DBUS_ASSERT_ERROR_IS_SET(error);
00706       
00707       return -1;
00708     }
00709   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00710       
00711   if (host == NULL)
00712     host = "localhost";
00713 
00714   he = gethostbyname (host);
00715   if (he == NULL) 
00716     {
00717       dbus_set_error (error,
00718                       _dbus_error_from_errno (errno),
00719                       "Failed to lookup hostname: %s",
00720                       host);
00721       _dbus_close (fd, NULL);
00722       return -1;
00723     }
00724   
00725   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00726 
00727   _DBUS_ZERO (addr);
00728   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00729   addr.sin_family = AF_INET;
00730   addr.sin_port = htons (port);
00731   
00732   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00733     {      
00734       dbus_set_error (error,
00735                        _dbus_error_from_errno (errno),
00736                       "Failed to connect to socket %s:%d %s",
00737                       host, port, _dbus_strerror (errno));
00738 
00739       _dbus_close (fd, NULL);
00740       fd = -1;
00741       
00742       return -1;
00743     }
00744 
00745   if (!_dbus_set_fd_nonblocking (fd, error))
00746     {
00747       _dbus_close (fd, NULL);
00748       fd = -1;
00749 
00750       return -1;
00751     }
00752 
00753   return fd;
00754 }
00755 
00768 int
00769 _dbus_listen_tcp_socket (const char     *host,
00770                          dbus_uint32_t  *port,
00771                          DBusError      *error)
00772 {
00773   int listen_fd;
00774   struct sockaddr_in addr;
00775   struct hostent *he;
00776   struct in_addr *haddr;
00777   socklen_t len = (socklen_t) sizeof (struct sockaddr);
00778 
00779   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00780   
00781   
00782   if (!_dbus_open_tcp_socket (&listen_fd, error))
00783     {
00784       _DBUS_ASSERT_ERROR_IS_SET(error);
00785       return -1;
00786     }
00787   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00788 
00789   he = gethostbyname (host);
00790   if (he == NULL) 
00791     {
00792       dbus_set_error (error,
00793                       _dbus_error_from_errno (errno),
00794                       "Failed to lookup hostname: %s",
00795                       host);
00796       _dbus_close (listen_fd, NULL);
00797       return -1;
00798     }
00799   
00800   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00801 
00802   _DBUS_ZERO (addr);
00803   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00804   addr.sin_family = AF_INET;
00805   addr.sin_port = htons (*port);
00806 
00807   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00808     {
00809       dbus_set_error (error, _dbus_error_from_errno (errno),
00810                       "Failed to bind socket \"%s:%d\": %s",
00811                       host, *port, _dbus_strerror (errno));
00812       _dbus_close (listen_fd, NULL);
00813       return -1;
00814     }
00815 
00816   if (listen (listen_fd, 30 /* backlog */) < 0)
00817     {
00818       dbus_set_error (error, _dbus_error_from_errno (errno),  
00819                       "Failed to listen on socket \"%s:%d\": %s",
00820                       host, *port, _dbus_strerror (errno));
00821       _dbus_close (listen_fd, NULL);
00822       return -1;
00823     }
00824 
00825   getsockname(listen_fd, (struct sockaddr*) &addr, &len);
00826   *port = (dbus_uint32_t) ntohs(addr.sin_port);
00827 
00828   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00829     {
00830       _dbus_close (listen_fd, NULL);
00831       return -1;
00832     }
00833   
00834   return listen_fd;
00835 }
00836 
00837 static dbus_bool_t
00838 write_credentials_byte (int             server_fd,
00839                         DBusError      *error)
00840 {
00841   int bytes_written;
00842   char buf[1] = { '\0' };
00843 #if defined(HAVE_CMSGCRED) 
00844   struct {
00845           struct cmsghdr hdr;
00846           struct cmsgcred cred;
00847   } cmsg;
00848   struct iovec iov;
00849   struct msghdr msg;
00850   iov.iov_base = buf;
00851   iov.iov_len = 1;
00852 
00853   memset (&msg, 0, sizeof (msg));
00854   msg.msg_iov = &iov;
00855   msg.msg_iovlen = 1;
00856 
00857   msg.msg_control = &cmsg;
00858   msg.msg_controllen = sizeof (cmsg);
00859   memset (&cmsg, 0, sizeof (cmsg));
00860   cmsg.hdr.cmsg_len = sizeof (cmsg);
00861   cmsg.hdr.cmsg_level = SOL_SOCKET;
00862   cmsg.hdr.cmsg_type = SCM_CREDS;
00863 #endif
00864 
00865   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00866   
00867  again:
00868 
00869 #if defined(HAVE_CMSGCRED) 
00870   bytes_written = sendmsg (server_fd, &msg, 0);
00871 #else
00872   bytes_written = write (server_fd, buf, 1);
00873 #endif
00874 
00875   if (bytes_written < 0 && errno == EINTR)
00876     goto again;
00877 
00878   if (bytes_written < 0)
00879     {
00880       dbus_set_error (error, _dbus_error_from_errno (errno),
00881                       "Failed to write credentials byte: %s",
00882                      _dbus_strerror (errno));
00883       return FALSE;
00884     }
00885   else if (bytes_written == 0)
00886     {
00887       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00888                       "wrote zero bytes writing credentials byte");
00889       return FALSE;
00890     }
00891   else
00892     {
00893       _dbus_assert (bytes_written == 1);
00894       _dbus_verbose ("wrote credentials byte\n");
00895       return TRUE;
00896     }
00897 }
00898 
00917 dbus_bool_t
00918 _dbus_read_credentials_unix_socket  (int              client_fd,
00919                                      DBusCredentials *credentials,
00920                                      DBusError       *error)
00921 {
00922   struct msghdr msg;
00923   struct iovec iov;
00924   char buf;
00925 
00926 #ifdef HAVE_CMSGCRED 
00927   struct {
00928           struct cmsghdr hdr;
00929           struct cmsgcred cred;
00930   } cmsg;
00931 
00932 #elif defined(LOCAL_CREDS)
00933   struct {
00934           struct cmsghdr hdr;
00935           struct sockcred cred;
00936   } cmsg;
00937 #endif
00938 
00939   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00940   
00941   /* The POSIX spec certainly doesn't promise this, but
00942    * we need these assertions to fail as soon as we're wrong about
00943    * it so we can do the porting fixups
00944    */
00945   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00946   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00947   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00948 
00949   _dbus_credentials_clear (credentials);
00950 
00951   /* Systems supporting LOCAL_CREDS are configured to have this feature
00952    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
00953    * the connection.  Therefore, the received message must carry the
00954    * credentials information without doing anything special.
00955    */
00956 
00957   iov.iov_base = &buf;
00958   iov.iov_len = 1;
00959 
00960   memset (&msg, 0, sizeof (msg));
00961   msg.msg_iov = &iov;
00962   msg.msg_iovlen = 1;
00963 
00964 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00965   memset (&cmsg, 0, sizeof (cmsg));
00966   msg.msg_control = &cmsg;
00967   msg.msg_controllen = sizeof (cmsg);
00968 #endif
00969 
00970  again:
00971   if (recvmsg (client_fd, &msg, 0) < 0)
00972     {
00973       if (errno == EINTR)
00974         goto again;
00975 
00976       dbus_set_error (error, _dbus_error_from_errno (errno),
00977                       "Failed to read credentials byte: %s",
00978                       _dbus_strerror (errno));
00979       return FALSE;
00980     }
00981 
00982   if (buf != '\0')
00983     {
00984       dbus_set_error (error, DBUS_ERROR_FAILED,
00985                       "Credentials byte was not nul");
00986       return FALSE;
00987     }
00988 
00989 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00990   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00991     {
00992       dbus_set_error (error, DBUS_ERROR_FAILED,
00993                       "Message from recvmsg() was not SCM_CREDS");
00994       return FALSE;
00995     }
00996 #endif
00997 
00998   _dbus_verbose ("read credentials byte\n");
00999 
01000   {
01001 #ifdef SO_PEERCRED
01002     struct ucred cr;   
01003     int cr_len = sizeof (cr);
01004    
01005     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01006         cr_len == sizeof (cr))
01007       {
01008         credentials->pid = cr.pid;
01009         credentials->uid = cr.uid;
01010         credentials->gid = cr.gid;
01011       }
01012     else
01013       {
01014         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01015                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01016       }
01017 #elif defined(HAVE_CMSGCRED)
01018     credentials->pid = cmsg.cred.cmcred_pid;
01019     credentials->uid = cmsg.cred.cmcred_euid;
01020     credentials->gid = cmsg.cred.cmcred_groups[0];
01021 #elif defined(LOCAL_CREDS)
01022     credentials->pid = DBUS_PID_UNSET;
01023     credentials->uid = cmsg.cred.sc_uid;
01024     credentials->gid = cmsg.cred.sc_gid;
01025     /* Since we have already got the credentials from this socket, we can
01026      * disable its LOCAL_CREDS flag if it was ever set. */
01027     _dbus_set_local_creds (client_fd, FALSE);
01028 #elif defined(HAVE_GETPEEREID)
01029     uid_t euid;
01030     gid_t egid;
01031     if (getpeereid (client_fd, &euid, &egid) == 0)
01032       {
01033         credentials->uid = euid;
01034         credentials->gid = egid;
01035       }
01036     else
01037       {
01038         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01039       }
01040 #elif defined(HAVE_GETPEERUCRED)
01041     ucred_t * ucred = NULL;
01042     if (getpeerucred (client_fd, &ucred) == 0)
01043       {
01044         credentials->pid = ucred_getpid (ucred);
01045         credentials->uid = ucred_geteuid (ucred);
01046         credentials->gid = ucred_getegid (ucred);
01047       }
01048     else
01049       {
01050         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01051       }
01052     if (ucred != NULL)
01053       ucred_free (ucred);
01054 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01055     _dbus_verbose ("Socket credentials not supported on this OS\n");
01056 #endif
01057   }
01058 
01059   _dbus_verbose ("Credentials:"
01060                  "  pid "DBUS_PID_FORMAT
01061                  "  uid "DBUS_UID_FORMAT
01062                  "  gid "DBUS_GID_FORMAT"\n",
01063                  credentials->pid,
01064                  credentials->uid,
01065                  credentials->gid);
01066     
01067   return TRUE;
01068 }
01069 
01087 dbus_bool_t
01088 _dbus_send_credentials_unix_socket  (int              server_fd,
01089                                      DBusError       *error)
01090 {
01091   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01092   
01093   if (write_credentials_byte (server_fd, error))
01094     return TRUE;
01095   else
01096     return FALSE;
01097 }
01098 
01106 int
01107 _dbus_accept  (int listen_fd)
01108 {
01109   int client_fd;
01110   struct sockaddr addr;
01111   socklen_t addrlen;
01112 
01113   addrlen = sizeof (addr);
01114   
01115  retry:
01116   client_fd = accept (listen_fd, &addr, &addrlen);
01117   
01118   if (client_fd < 0)
01119     {
01120       if (errno == EINTR)
01121         goto retry;
01122     }
01123   
01124   return client_fd;
01125 }
01126 
01135 dbus_bool_t
01136 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01137 {
01138   const char *directory;
01139   struct stat sb;
01140         
01141   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01142     
01143   directory = _dbus_string_get_const_data (dir);
01144         
01145   if (stat (directory, &sb) < 0)
01146     {
01147       dbus_set_error (error, _dbus_error_from_errno (errno),
01148                       "%s", _dbus_strerror (errno));
01149    
01150       return FALSE;
01151     }
01152     
01153   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01154       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01155     {
01156       dbus_set_error (error, DBUS_ERROR_FAILED,
01157                      "%s directory is not private to the user", directory);
01158       return FALSE;
01159     }
01160     
01161   return TRUE;
01162 }
01163 
01164 static dbus_bool_t
01165 fill_user_info_from_passwd (struct passwd *p,
01166                             DBusUserInfo  *info,
01167                             DBusError     *error)
01168 {
01169   _dbus_assert (p->pw_name != NULL);
01170   _dbus_assert (p->pw_dir != NULL);
01171   
01172   info->uid = p->pw_uid;
01173   info->primary_gid = p->pw_gid;
01174   info->username = _dbus_strdup (p->pw_name);
01175   info->homedir = _dbus_strdup (p->pw_dir);
01176   
01177   if (info->username == NULL ||
01178       info->homedir == NULL)
01179     {
01180       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01181       return FALSE;
01182     }
01183 
01184   return TRUE;
01185 }
01186 
01187 static dbus_bool_t
01188 fill_user_info (DBusUserInfo       *info,
01189                 dbus_uid_t          uid,
01190                 const DBusString   *username,
01191                 DBusError          *error)
01192 {
01193   const char *username_c;
01194   
01195   /* exactly one of username/uid provided */
01196   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01197   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01198 
01199   info->uid = DBUS_UID_UNSET;
01200   info->primary_gid = DBUS_GID_UNSET;
01201   info->group_ids = NULL;
01202   info->n_group_ids = 0;
01203   info->username = NULL;
01204   info->homedir = NULL;
01205   
01206   if (username != NULL)
01207     username_c = _dbus_string_get_const_data (username);
01208   else
01209     username_c = NULL;
01210 
01211   /* For now assuming that the getpwnam() and getpwuid() flavors
01212    * are always symmetrical, if not we have to add more configure
01213    * checks
01214    */
01215   
01216 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01217   {
01218     struct passwd *p;
01219     int result;
01220     char buf[1024];
01221     struct passwd p_str;
01222 
01223     p = NULL;
01224 #ifdef HAVE_POSIX_GETPWNAM_R
01225     if (uid != DBUS_UID_UNSET)
01226       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01227                            &p);
01228     else
01229       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01230                            &p);
01231 #else
01232     if (uid != DBUS_UID_UNSET)
01233       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01234     else
01235       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01236     result = 0;
01237 #endif /* !HAVE_POSIX_GETPWNAM_R */
01238     if (result == 0 && p == &p_str)
01239       {
01240         if (!fill_user_info_from_passwd (p, info, error))
01241           return FALSE;
01242       }
01243     else
01244       {
01245         dbus_set_error (error, _dbus_error_from_errno (errno),
01246                         "User \"%s\" unknown or no memory to allocate password entry\n",
01247                         username_c ? username_c : "???");
01248         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01249         return FALSE;
01250       }
01251   }
01252 #else /* ! HAVE_GETPWNAM_R */
01253   {
01254     /* I guess we're screwed on thread safety here */
01255     struct passwd *p;
01256 
01257     if (uid != DBUS_UID_UNSET)
01258       p = getpwuid (uid);
01259     else
01260       p = getpwnam (username_c);
01261 
01262     if (p != NULL)
01263       {
01264         if (!fill_user_info_from_passwd (p, info, error))
01265           return FALSE;
01266       }
01267     else
01268       {
01269         dbus_set_error (error, _dbus_error_from_errno (errno),
01270                         "User \"%s\" unknown or no memory to allocate password entry\n",
01271                         username_c ? username_c : "???");
01272         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01273         return FALSE;
01274       }
01275   }
01276 #endif  /* ! HAVE_GETPWNAM_R */
01277 
01278   /* Fill this in so we can use it to get groups */
01279   username_c = info->username;
01280   
01281 #ifdef HAVE_GETGROUPLIST
01282   {
01283     gid_t *buf;
01284     int buf_count;
01285     int i;
01286     
01287     buf_count = 17;
01288     buf = dbus_new (gid_t, buf_count);
01289     if (buf == NULL)
01290       {
01291         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01292         goto failed;
01293       }
01294     
01295     if (getgrouplist (username_c,
01296                       info->primary_gid,
01297                       buf, &buf_count) < 0)
01298       {
01299         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01300         if (new == NULL)
01301           {
01302             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01303             dbus_free (buf);
01304             goto failed;
01305           }
01306         
01307         buf = new;
01308 
01309         errno = 0;
01310         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01311           {
01312             dbus_set_error (error,
01313                             _dbus_error_from_errno (errno),
01314                             "Failed to get groups for username \"%s\" primary GID "
01315                             DBUS_GID_FORMAT ": %s\n",
01316                             username_c, info->primary_gid,
01317                             _dbus_strerror (errno));
01318             dbus_free (buf);
01319             goto failed;
01320           }
01321       }
01322 
01323     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01324     if (info->group_ids == NULL)
01325       {
01326         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01327         dbus_free (buf);
01328         goto failed;
01329       }
01330     
01331     for (i = 0; i < buf_count; ++i)
01332       info->group_ids[i] = buf[i];
01333 
01334     info->n_group_ids = buf_count;
01335     
01336     dbus_free (buf);
01337   }
01338 #else  /* HAVE_GETGROUPLIST */
01339   {
01340     /* We just get the one group ID */
01341     info->group_ids = dbus_new (dbus_gid_t, 1);
01342     if (info->group_ids == NULL)
01343       {
01344         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01345         goto failed;
01346       }
01347 
01348     info->n_group_ids = 1;
01349 
01350     (info->group_ids)[0] = info->primary_gid;
01351   }
01352 #endif /* HAVE_GETGROUPLIST */
01353 
01354   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01355   
01356   return TRUE;
01357   
01358  failed:
01359   _DBUS_ASSERT_ERROR_IS_SET (error);
01360   return FALSE;
01361 }
01362 
01371 dbus_bool_t
01372 _dbus_user_info_fill (DBusUserInfo     *info,
01373                       const DBusString *username,
01374                       DBusError        *error)
01375 {
01376   return fill_user_info (info, DBUS_UID_UNSET,
01377                          username, error);
01378 }
01379 
01388 dbus_bool_t
01389 _dbus_user_info_fill_uid (DBusUserInfo *info,
01390                           dbus_uid_t    uid,
01391                           DBusError    *error)
01392 {
01393   return fill_user_info (info, uid,
01394                          NULL, error);
01395 }
01396 
01402 void
01403 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01404 {
01405   /* The POSIX spec certainly doesn't promise this, but
01406    * we need these assertions to fail as soon as we're wrong about
01407    * it so we can do the porting fixups
01408    */
01409   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01410   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01411   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01412   
01413   credentials->pid = getpid ();
01414   credentials->uid = getuid ();
01415   credentials->gid = getgid ();
01416 }
01417 
01422 unsigned long
01423 _dbus_getpid (void)
01424 {
01425   return getpid ();
01426 }
01427 
01431 dbus_uid_t
01432 _dbus_getuid (void)
01433 {
01434   return getuid ();
01435 }
01436 
01437 #ifdef DBUS_BUILD_TESTS
01438 
01441 dbus_gid_t
01442 _dbus_getgid (void)
01443 {
01444   return getgid ();
01445 }
01446 #endif
01447 
01456 int
01457 _dbus_poll (DBusPollFD *fds,
01458             int         n_fds,
01459             int         timeout_milliseconds)
01460 {
01461 #ifdef HAVE_POLL
01462   /* This big thing is a constant expression and should get optimized
01463    * out of existence. So it's more robust than a configure check at
01464    * no cost.
01465    */
01466   if (_DBUS_POLLIN == POLLIN &&
01467       _DBUS_POLLPRI == POLLPRI &&
01468       _DBUS_POLLOUT == POLLOUT &&
01469       _DBUS_POLLERR == POLLERR &&
01470       _DBUS_POLLHUP == POLLHUP &&
01471       _DBUS_POLLNVAL == POLLNVAL &&
01472       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01473       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01474       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01475       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01476       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01477       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01478       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01479     {
01480       return poll ((struct pollfd*) fds,
01481                    n_fds, 
01482                    timeout_milliseconds);
01483     }
01484   else
01485     {
01486       /* We have to convert the DBusPollFD to an array of
01487        * struct pollfd, poll, and convert back.
01488        */
01489       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01490       return -1;
01491     }
01492 #else /* ! HAVE_POLL */
01493 
01494   fd_set read_set, write_set, err_set;
01495   int max_fd = 0;
01496   int i;
01497   struct timeval tv;
01498   int ready;
01499   
01500   FD_ZERO (&read_set);
01501   FD_ZERO (&write_set);
01502   FD_ZERO (&err_set);
01503 
01504   for (i = 0; i < n_fds; i++)
01505     {
01506       DBusPollFD *fdp = &fds[i];
01507 
01508       if (fdp->events & _DBUS_POLLIN)
01509         FD_SET (fdp->fd, &read_set);
01510 
01511       if (fdp->events & _DBUS_POLLOUT)
01512         FD_SET (fdp->fd, &write_set);
01513 
01514       FD_SET (fdp->fd, &err_set);
01515 
01516       max_fd = MAX (max_fd, fdp->fd);
01517     }
01518     
01519   tv.tv_sec = timeout_milliseconds / 1000;
01520   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01521 
01522   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01523                   timeout_milliseconds < 0 ? NULL : &tv);
01524 
01525   if (ready > 0)
01526     {
01527       for (i = 0; i < n_fds; i++)
01528         {
01529           DBusPollFD *fdp = &fds[i];
01530 
01531           fdp->revents = 0;
01532 
01533           if (FD_ISSET (fdp->fd, &read_set))
01534             fdp->revents |= _DBUS_POLLIN;
01535 
01536           if (FD_ISSET (fdp->fd, &write_set))
01537             fdp->revents |= _DBUS_POLLOUT;
01538 
01539           if (FD_ISSET (fdp->fd, &err_set))
01540             fdp->revents |= _DBUS_POLLERR;
01541         }
01542     }
01543 
01544   return ready;
01545 #endif
01546 }
01547 
01554 void
01555 _dbus_get_current_time (long *tv_sec,
01556                         long *tv_usec)
01557 {
01558   struct timeval t;
01559 
01560   gettimeofday (&t, NULL);
01561 
01562   if (tv_sec)
01563     *tv_sec = t.tv_sec;
01564   if (tv_usec)
01565     *tv_usec = t.tv_usec;
01566 }
01567 
01578 dbus_bool_t
01579 _dbus_file_get_contents (DBusString       *str,
01580                          const DBusString *filename,
01581                          DBusError        *error)
01582 {
01583   int fd;
01584   struct stat sb;
01585   int orig_len;
01586   int total;
01587   const char *filename_c;
01588 
01589   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01590   
01591   filename_c = _dbus_string_get_const_data (filename);
01592   
01593   /* O_BINARY useful on Cygwin */
01594   fd = open (filename_c, O_RDONLY | O_BINARY);
01595   if (fd < 0)
01596     {
01597       dbus_set_error (error, _dbus_error_from_errno (errno),
01598                       "Failed to open \"%s\": %s",
01599                       filename_c,
01600                       _dbus_strerror (errno));
01601       return FALSE;
01602     }
01603 
01604   if (fstat (fd, &sb) < 0)
01605     {
01606       dbus_set_error (error, _dbus_error_from_errno (errno),
01607                       "Failed to stat \"%s\": %s",
01608                       filename_c,
01609                       _dbus_strerror (errno));
01610 
01611       _dbus_verbose ("fstat() failed: %s",
01612                      _dbus_strerror (errno));
01613       
01614       _dbus_close (fd, NULL);
01615       
01616       return FALSE;
01617     }
01618 
01619   if (sb.st_size > _DBUS_ONE_MEGABYTE)
01620     {
01621       dbus_set_error (error, DBUS_ERROR_FAILED,
01622                       "File size %lu of \"%s\" is too large.",
01623                       (unsigned long) sb.st_size, filename_c);
01624       _dbus_close (fd, NULL);
01625       return FALSE;
01626     }
01627   
01628   total = 0;
01629   orig_len = _dbus_string_get_length (str);
01630   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
01631     {
01632       int bytes_read;
01633 
01634       while (total < (int) sb.st_size)
01635         {
01636           bytes_read = _dbus_read (fd, str,
01637                                    sb.st_size - total);
01638           if (bytes_read <= 0)
01639             {
01640               dbus_set_error (error, _dbus_error_from_errno (errno),
01641                               "Error reading \"%s\": %s",
01642                               filename_c,
01643                               _dbus_strerror (errno));
01644 
01645               _dbus_verbose ("read() failed: %s",
01646                              _dbus_strerror (errno));
01647               
01648               _dbus_close (fd, NULL);
01649               _dbus_string_set_length (str, orig_len);
01650               return FALSE;
01651             }
01652           else
01653             total += bytes_read;
01654         }
01655 
01656       _dbus_close (fd, NULL);
01657       return TRUE;
01658     }
01659   else if (sb.st_size != 0)
01660     {
01661       _dbus_verbose ("Can only open regular files at the moment.\n");
01662       dbus_set_error (error, DBUS_ERROR_FAILED,
01663                       "\"%s\" is not a regular file",
01664                       filename_c);
01665       _dbus_close (fd, NULL);
01666       return FALSE;
01667     }
01668   else
01669     {
01670       _dbus_close (fd, NULL);
01671       return TRUE;
01672     }
01673 }
01674 
01684 dbus_bool_t
01685 _dbus_string_save_to_file (const DBusString *str,
01686                            const DBusString *filename,
01687                            DBusError        *error)
01688 {
01689   int fd;
01690   int bytes_to_write;
01691   const char *filename_c;
01692   DBusString tmp_filename;
01693   const char *tmp_filename_c;
01694   int total;
01695   dbus_bool_t need_unlink;
01696   dbus_bool_t retval;
01697 
01698   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01699   
01700   fd = -1;
01701   retval = FALSE;
01702   need_unlink = FALSE;
01703   
01704   if (!_dbus_string_init (&tmp_filename))
01705     {
01706       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01707       return FALSE;
01708     }
01709 
01710   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
01711     {
01712       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01713       _dbus_string_free (&tmp_filename);
01714       return FALSE;
01715     }
01716   
01717   if (!_dbus_string_append (&tmp_filename, "."))
01718     {
01719       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01720       _dbus_string_free (&tmp_filename);
01721       return FALSE;
01722     }
01723 
01724 #define N_TMP_FILENAME_RANDOM_BYTES 8
01725   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
01726     {
01727       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01728       _dbus_string_free (&tmp_filename);
01729       return FALSE;
01730     }
01731     
01732   filename_c = _dbus_string_get_const_data (filename);
01733   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
01734 
01735   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01736              0600);
01737   if (fd < 0)
01738     {
01739       dbus_set_error (error, _dbus_error_from_errno (errno),
01740                       "Could not create %s: %s", tmp_filename_c,
01741                       _dbus_strerror (errno));
01742       goto out;
01743     }
01744 
01745   need_unlink = TRUE;
01746   
01747   total = 0;
01748   bytes_to_write = _dbus_string_get_length (str);
01749 
01750   while (total < bytes_to_write)
01751     {
01752       int bytes_written;
01753 
01754       bytes_written = _dbus_write (fd, str, total,
01755                                    bytes_to_write - total);
01756 
01757       if (bytes_written <= 0)
01758         {
01759           dbus_set_error (error, _dbus_error_from_errno (errno),
01760                           "Could not write to %s: %s", tmp_filename_c,
01761                           _dbus_strerror (errno));
01762           
01763           goto out;
01764         }
01765 
01766       total += bytes_written;
01767     }
01768 
01769   if (!_dbus_close (fd, NULL))
01770     {
01771       dbus_set_error (error, _dbus_error_from_errno (errno),
01772                       "Could not close file %s: %s",
01773                       tmp_filename_c, _dbus_strerror (errno));
01774 
01775       goto out;
01776     }
01777 
01778   fd = -1;
01779   
01780   if (rename (tmp_filename_c, filename_c) < 0)
01781     {
01782       dbus_set_error (error, _dbus_error_from_errno (errno),
01783                       "Could not rename %s to %s: %s",
01784                       tmp_filename_c, filename_c,
01785                       _dbus_strerror (errno));
01786 
01787       goto out;
01788     }
01789 
01790   need_unlink = FALSE;
01791   
01792   retval = TRUE;
01793   
01794  out:
01795   /* close first, then unlink, to prevent ".nfs34234235" garbage
01796    * files
01797    */
01798 
01799   if (fd >= 0)
01800     _dbus_close (fd, NULL);
01801         
01802   if (need_unlink && unlink (tmp_filename_c) < 0)
01803     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
01804                    tmp_filename_c, _dbus_strerror (errno));
01805 
01806   _dbus_string_free (&tmp_filename);
01807 
01808   if (!retval)
01809     _DBUS_ASSERT_ERROR_IS_SET (error);
01810   
01811   return retval;
01812 }
01813 
01820 dbus_bool_t
01821 _dbus_make_file_world_readable(const DBusString *filename,
01822                                DBusError *error)
01823 {
01824   const char *filename_c;
01825 
01826   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01827 
01828   filename_c = _dbus_string_get_const_data (filename);
01829   if (chmod (filename_c, 0644) == -1)
01830     {
01831       dbus_set_error (error,
01832                       DBUS_ERROR_FAILED,
01833                       "Could not change permissions of file %s: %s\n",
01834                       filename_c,
01835                       _dbus_strerror (errno));
01836       return FALSE;
01837     }
01838   return TRUE;
01839 }
01840 
01847 dbus_bool_t
01848 _dbus_create_file_exclusively (const DBusString *filename,
01849                                DBusError        *error)
01850 {
01851   int fd;
01852   const char *filename_c;
01853 
01854   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01855   
01856   filename_c = _dbus_string_get_const_data (filename);
01857   
01858   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01859              0600);
01860   if (fd < 0)
01861     {
01862       dbus_set_error (error,
01863                       DBUS_ERROR_FAILED,
01864                       "Could not create file %s: %s\n",
01865                       filename_c,
01866                       _dbus_strerror (errno));
01867       return FALSE;
01868     }
01869 
01870   if (!_dbus_close (fd, NULL))
01871     {
01872       dbus_set_error (error,
01873                       DBUS_ERROR_FAILED,
01874                       "Could not close file %s: %s\n",
01875                       filename_c,
01876                       _dbus_strerror (errno));
01877       return FALSE;
01878     }
01879   
01880   return TRUE;
01881 }
01882 
01891 dbus_bool_t
01892 _dbus_delete_file (const DBusString *filename,
01893                    DBusError        *error)
01894 {
01895   const char *filename_c;
01896 
01897   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01898   
01899   filename_c = _dbus_string_get_const_data (filename);
01900 
01901   if (unlink (filename_c) < 0)
01902     {
01903       dbus_set_error (error, DBUS_ERROR_FAILED,
01904                       "Failed to delete file %s: %s\n",
01905                       filename_c, _dbus_strerror (errno));
01906       return FALSE;
01907     }
01908   else
01909     return TRUE;
01910 }
01911 
01920 dbus_bool_t
01921 _dbus_create_directory (const DBusString *filename,
01922                         DBusError        *error)
01923 {
01924   const char *filename_c;
01925 
01926   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01927   
01928   filename_c = _dbus_string_get_const_data (filename);
01929 
01930   if (mkdir (filename_c, 0700) < 0)
01931     {
01932       if (errno == EEXIST)
01933         return TRUE;
01934       
01935       dbus_set_error (error, DBUS_ERROR_FAILED,
01936                       "Failed to create directory %s: %s\n",
01937                       filename_c, _dbus_strerror (errno));
01938       return FALSE;
01939     }
01940   else
01941     return TRUE;
01942 }
01943 
01954 dbus_bool_t
01955 _dbus_concat_dir_and_file (DBusString       *dir,
01956                            const DBusString *next_component)
01957 {
01958   dbus_bool_t dir_ends_in_slash;
01959   dbus_bool_t file_starts_with_slash;
01960 
01961   if (_dbus_string_get_length (dir) == 0 ||
01962       _dbus_string_get_length (next_component) == 0)
01963     return TRUE;
01964   
01965   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
01966                                                     _dbus_string_get_length (dir) - 1);
01967 
01968   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
01969 
01970   if (dir_ends_in_slash && file_starts_with_slash)
01971     {
01972       _dbus_string_shorten (dir, 1);
01973     }
01974   else if (!(dir_ends_in_slash || file_starts_with_slash))
01975     {
01976       if (!_dbus_string_append_byte (dir, '/'))
01977         return FALSE;
01978     }
01979 
01980   return _dbus_string_copy (next_component, 0, dir,
01981                             _dbus_string_get_length (dir));
01982 }
01983 
01985 #define NANOSECONDS_PER_SECOND       1000000000
01986 
01987 #define MICROSECONDS_PER_SECOND      1000000
01988 
01989 #define MILLISECONDS_PER_SECOND      1000
01990 
01991 #define NANOSECONDS_PER_MILLISECOND  1000000
01992 
01993 #define MICROSECONDS_PER_MILLISECOND 1000
01994 
01999 void
02000 _dbus_sleep_milliseconds (int milliseconds)
02001 {
02002 #ifdef HAVE_NANOSLEEP
02003   struct timespec req;
02004   struct timespec rem;
02005 
02006   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02007   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02008   rem.tv_sec = 0;
02009   rem.tv_nsec = 0;
02010 
02011   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02012     req = rem;
02013 #elif defined (HAVE_USLEEP)
02014   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02015 #else /* ! HAVE_USLEEP */
02016   sleep (MAX (milliseconds / 1000, 1));
02017 #endif
02018 }
02019 
02020 static dbus_bool_t
02021 _dbus_generate_pseudorandom_bytes (DBusString *str,
02022                                    int         n_bytes)
02023 {
02024   int old_len;
02025   char *p;
02026   
02027   old_len = _dbus_string_get_length (str);
02028 
02029   if (!_dbus_string_lengthen (str, n_bytes))
02030     return FALSE;
02031 
02032   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02033 
02034   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02035 
02036   return TRUE;
02037 }
02038 
02047 dbus_bool_t
02048 _dbus_generate_random_bytes (DBusString *str,
02049                              int         n_bytes)
02050 {
02051   int old_len;
02052   int fd;
02053 
02054   /* FALSE return means "no memory", if it could
02055    * mean something else then we'd need to return
02056    * a DBusError. So we always fall back to pseudorandom
02057    * if the I/O fails.
02058    */
02059   
02060   old_len = _dbus_string_get_length (str);
02061   fd = -1;
02062 
02063   /* note, urandom on linux will fall back to pseudorandom */
02064   fd = open ("/dev/urandom", O_RDONLY);
02065   if (fd < 0)
02066     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02067 
02068   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02069     {
02070       _dbus_close (fd, NULL);
02071       _dbus_string_set_length (str, old_len);
02072       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02073     }
02074 
02075   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02076                  n_bytes);
02077   
02078   _dbus_close (fd, NULL);
02079   
02080   return TRUE;
02081 }
02082 
02088 void
02089 _dbus_exit (int code)
02090 {
02091   _exit (code);
02092 }
02093 
02101 const char*
02102 _dbus_strerror (int error_number)
02103 {
02104   const char *msg;
02105   
02106   msg = strerror (error_number);
02107   if (msg == NULL)
02108     msg = "unknown";
02109 
02110   return msg;
02111 }
02112 
02116 void
02117 _dbus_disable_sigpipe (void)
02118 {
02119   signal (SIGPIPE, SIG_IGN);
02120 }
02121 
02129 void
02130 _dbus_fd_set_close_on_exec (int fd)
02131 {
02132   int val;
02133   
02134   val = fcntl (fd, F_GETFD, 0);
02135   
02136   if (val < 0)
02137     return;
02138 
02139   val |= FD_CLOEXEC;
02140   
02141   fcntl (fd, F_SETFD, val);
02142 }
02143 
02151 dbus_bool_t
02152 _dbus_close (int        fd,
02153              DBusError *error)
02154 {
02155   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02156   
02157  again:
02158   if (close (fd) < 0)
02159     {
02160       if (errno == EINTR)
02161         goto again;
02162 
02163       dbus_set_error (error, _dbus_error_from_errno (errno),
02164                       "Could not close fd %d", fd);
02165       return FALSE;
02166     }
02167 
02168   return TRUE;
02169 }
02170 
02178 dbus_bool_t
02179 _dbus_set_fd_nonblocking (int             fd,
02180                           DBusError      *error)
02181 {
02182   int val;
02183 
02184   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02185   
02186   val = fcntl (fd, F_GETFL, 0);
02187   if (val < 0)
02188     {
02189       dbus_set_error (error, _dbus_error_from_errno (errno),
02190                       "Failed to get flags from file descriptor %d: %s",
02191                       fd, _dbus_strerror (errno));
02192       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02193                      _dbus_strerror (errno));
02194       return FALSE;
02195     }
02196 
02197   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02198     {
02199       dbus_set_error (error, _dbus_error_from_errno (errno),
02200                       "Failed to set nonblocking flag of file descriptor %d: %s",
02201                       fd, _dbus_strerror (errno));
02202       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02203                      fd, _dbus_strerror (errno));
02204 
02205       return FALSE;
02206     }
02207 
02208   return TRUE;
02209 }
02210 
02216 void
02217 _dbus_print_backtrace (void)
02218 {  
02219 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02220   void *bt[500];
02221   int bt_size;
02222   int i;
02223   char **syms;
02224   
02225   bt_size = backtrace (bt, 500);
02226 
02227   syms = backtrace_symbols (bt, bt_size);
02228   
02229   i = 0;
02230   while (i < bt_size)
02231     {
02232       /* don't use dbus_warn since it can _dbus_abort() */
02233       fprintf (stderr, "  %s\n", syms[i]);
02234       ++i;
02235     }
02236   fflush (stderr);
02237 
02238   free (syms);
02239 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02240   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02241 #else
02242   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02243 #endif
02244 }
02245 
02261 dbus_bool_t
02262 _dbus_full_duplex_pipe (int        *fd1,
02263                         int        *fd2,
02264                         dbus_bool_t blocking,
02265                         DBusError  *error)
02266 {
02267 #ifdef HAVE_SOCKETPAIR
02268   int fds[2];
02269 
02270   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02271   
02272   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02273     {
02274       dbus_set_error (error, _dbus_error_from_errno (errno),
02275                       "Could not create full-duplex pipe");
02276       return FALSE;
02277     }
02278 
02279   if (!blocking &&
02280       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02281        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02282     {
02283       dbus_set_error (error, _dbus_error_from_errno (errno),
02284                       "Could not set full-duplex pipe nonblocking");
02285       
02286       _dbus_close (fds[0], NULL);
02287       _dbus_close (fds[1], NULL);
02288       
02289       return FALSE;
02290     }
02291   
02292   *fd1 = fds[0];
02293   *fd2 = fds[1];
02294 
02295   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02296                  *fd1, *fd2);
02297   
02298   return TRUE;  
02299 #else
02300   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02301   dbus_set_error (error, DBUS_ERROR_FAILED,
02302                   "_dbus_full_duplex_pipe() not implemented on this OS");
02303   return FALSE;
02304 #endif
02305 }
02306 
02307 
02316 int
02317 _dbus_printf_string_upper_bound (const char *format,
02318                                  va_list     args)
02319 {
02320   char c;
02321   return vsnprintf (&c, 1, format, args);
02322 }
02323 
02330 const char*
02331 _dbus_get_tmpdir(void)
02332 {
02333   static const char* tmpdir = NULL;
02334 
02335   if (tmpdir == NULL)
02336     {
02337       /* TMPDIR is what glibc uses, then
02338        * glibc falls back to the P_tmpdir macro which
02339        * just expands to "/tmp"
02340        */
02341       if (tmpdir == NULL)
02342         tmpdir = getenv("TMPDIR");
02343 
02344       /* These two env variables are probably
02345        * broken, but maybe some OS uses them?
02346        */
02347       if (tmpdir == NULL)
02348         tmpdir = getenv("TMP");
02349       if (tmpdir == NULL)
02350         tmpdir = getenv("TEMP");
02351 
02352       /* And this is the sane fallback. */
02353       if (tmpdir == NULL)
02354         tmpdir = "/tmp";
02355     }
02356   
02357   _dbus_assert(tmpdir != NULL);
02358   
02359   return tmpdir;
02360 }
02361 
02374 dbus_bool_t
02375 _dbus_get_autolaunch_address (DBusString *address,
02376                               DBusError  *error)
02377 {
02378   static char *argv[6];
02379   int address_pipe[2] = { -1, -1 };
02380   int errors_pipe[2] = { -1, -1 };
02381   pid_t pid;
02382   int ret;
02383   int status;
02384   int orig_len;
02385   int i;
02386   DBusString uuid;
02387   dbus_bool_t retval;
02388   
02389   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02390   retval = FALSE;
02391 
02392   _dbus_string_init (&uuid);
02393   
02394   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02395     {
02396       _DBUS_SET_OOM (error);
02397       goto out;
02398     }
02399   
02400   i = 0;
02401   argv[i] = "dbus-launch";
02402   ++i;
02403   argv[i] = "--autolaunch";
02404   ++i;
02405   argv[i] = _dbus_string_get_data (&uuid);
02406   ++i;
02407   argv[i] = "--binary-syntax";
02408   ++i;
02409   argv[i] = "--close-stderr";
02410   ++i;
02411   argv[i] = NULL;
02412   ++i;
02413 
02414   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02415   
02416   orig_len = _dbus_string_get_length (address);
02417   
02418 #define READ_END        0
02419 #define WRITE_END       1
02420   if (pipe (address_pipe) < 0)
02421     {
02422       dbus_set_error (error, _dbus_error_from_errno (errno),
02423                       "Failed to create a pipe: %s",
02424                       _dbus_strerror (errno));
02425       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02426                      _dbus_strerror (errno));
02427       goto out;
02428     }
02429   if (pipe (errors_pipe) < 0)
02430     {
02431       dbus_set_error (error, _dbus_error_from_errno (errno),
02432                       "Failed to create a pipe: %s",
02433                       _dbus_strerror (errno));
02434       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02435                      _dbus_strerror (errno));
02436       goto out;
02437     }
02438 
02439   pid = fork ();
02440   if (pid < 0)
02441     {
02442       dbus_set_error (error, _dbus_error_from_errno (errno),
02443                       "Failed to fork(): %s",
02444                       _dbus_strerror (errno));
02445       _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02446                      _dbus_strerror (errno));
02447       goto out;
02448     }
02449 
02450   if (pid == 0)
02451     {
02452       /* child process */
02453       int fd = open ("/dev/null", O_RDWR);
02454       if (fd == -1)
02455         /* huh?! can't open /dev/null? */
02456         _exit (1);
02457 
02458       /* set-up stdXXX */
02459       close (address_pipe[READ_END]);
02460       close (errors_pipe[READ_END]);
02461       close (0);                /* close stdin */
02462       close (1);                /* close stdout */
02463       close (2);                /* close stderr */
02464 
02465       if (dup2 (fd, 0) == -1)
02466         _exit (1);
02467       if (dup2 (address_pipe[WRITE_END], 1) == -1)
02468         _exit (1);
02469       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02470         _exit (1);
02471 
02472       close (fd);
02473       close (address_pipe[WRITE_END]);
02474       close (errors_pipe[WRITE_END]);
02475 
02476       execv (DBUS_BINDIR "/dbus-launch", argv);
02477 
02478       /* failed, try searching PATH */
02479       execvp ("dbus-launch", argv);
02480 
02481       /* still nothing, we failed */
02482       _exit (1);
02483     }
02484 
02485   /* parent process */
02486   close (address_pipe[WRITE_END]);
02487   close (errors_pipe[WRITE_END]);
02488   address_pipe[WRITE_END] = -1;
02489   errors_pipe[WRITE_END] = -1;
02490 
02491   ret = 0;
02492   do 
02493     {
02494       ret = _dbus_read (address_pipe[READ_END], address, 1024);
02495     }
02496   while (ret > 0);
02497 
02498   /* reap the child process to avoid it lingering as zombie */
02499   do
02500     {
02501       ret = waitpid (pid, &status, 0);
02502     }
02503   while (ret == -1 && errno == EINTR);
02504 
02505   /* We succeeded if the process exited with status 0 and
02506      anything was read */
02507   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02508       _dbus_string_get_length (address) == orig_len)
02509     {
02510       /* The process ended with error */
02511       DBusString error_message;
02512       _dbus_string_init (&error_message);
02513       ret = 0;
02514       do
02515         {
02516           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
02517         }
02518       while (ret > 0);
02519 
02520       _dbus_string_set_length (address, orig_len);
02521       if (_dbus_string_get_length (&error_message) > 0)
02522         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02523                         "dbus-launch failed to autolaunch D-Bus session: %s",
02524                         _dbus_string_get_data (&error_message));
02525       else
02526       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02527                       "Failed to execute dbus-launch to autolaunch D-Bus session");
02528       goto out;
02529     }
02530 
02531   retval = TRUE;
02532   
02533  out:
02534   if (retval)
02535     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02536   else
02537     _DBUS_ASSERT_ERROR_IS_SET (error);
02538   
02539   if (address_pipe[0] != -1)
02540     close (address_pipe[0]);
02541   if (address_pipe[1] != -1)
02542     close (address_pipe[1]);
02543   if (errors_pipe[0] != -1)
02544     close (errors_pipe[0]);
02545   if (errors_pipe[1] != -1)
02546     close (errors_pipe[1]);
02547 
02548   _dbus_string_free (&uuid);
02549   return retval;
02550 }
02551 
02570 dbus_bool_t
02571 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
02572                                dbus_bool_t create_if_not_found,
02573                                DBusError  *error)
02574 {
02575   DBusString filename;
02576   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
02577   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
02578 }
02579 
02580 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
02581 
02582 static dbus_bool_t
02583 split_paths_and_append (DBusString *dirs, 
02584                         const char *suffix, 
02585                         DBusList **dir_list)
02586 {
02587   /* split on colon (:) */
02588    int start;
02589    int i;
02590    int len;
02591    char *cpath;
02592    const DBusString file_suffix;
02593 
02594    start = 0;
02595    i = 0;
02596 
02597    _dbus_string_init_const (&file_suffix, suffix);
02598 
02599    len = _dbus_string_get_length (dirs);
02600 
02601    while (_dbus_string_find (dirs, start, ":", &i))
02602      {
02603        DBusString path;
02604 
02605        if (!_dbus_string_init (&path))
02606           goto oom;
02607 
02608        if (!_dbus_string_copy_len (dirs,
02609                                    start,
02610                                    i - start,
02611                                    &path,
02612                                    0))
02613           {
02614             _dbus_string_free (&path);
02615             goto oom;
02616           }
02617 
02618         _dbus_string_chop_white (&path);
02619 
02620         /* check for an empty path */
02621         if (_dbus_string_get_length (&path) == 0)
02622           goto next;
02623 
02624         if (!_dbus_concat_dir_and_file (&path,
02625                                         &file_suffix))
02626           {
02627             _dbus_string_free (&path);
02628             goto oom;
02629           }
02630 
02631         if (!_dbus_string_copy_data(&path, &cpath))
02632           {
02633             _dbus_string_free (&path);
02634             goto oom;
02635           }
02636 
02637         if (!_dbus_list_append (dir_list, cpath))
02638           {
02639             _dbus_string_free (&path);              
02640             dbus_free (cpath);
02641             goto oom;
02642           }
02643 
02644        next:
02645         _dbus_string_free (&path);
02646         start = i + 1;
02647     } 
02648       
02649   if (start != len)
02650     { 
02651       DBusString path;
02652 
02653       if (!_dbus_string_init (&path))
02654         goto oom;
02655 
02656       if (!_dbus_string_copy_len (dirs,
02657                                   start,
02658                                   len - start,
02659                                   &path,
02660                                   0))
02661         {
02662           _dbus_string_free (&path);
02663           goto oom;
02664         }
02665 
02666       if (!_dbus_concat_dir_and_file (&path,
02667                                       &file_suffix))
02668         {
02669           _dbus_string_free (&path);
02670           goto oom;
02671         }
02672 
02673       if (!_dbus_string_copy_data(&path, &cpath))
02674         {
02675           _dbus_string_free (&path);
02676           goto oom;
02677         }
02678 
02679       if (!_dbus_list_append (dir_list, cpath))
02680         {
02681           _dbus_string_free (&path);              
02682           dbus_free (cpath);
02683           goto oom;
02684         }
02685 
02686       _dbus_string_free (&path); 
02687     }
02688 
02689   return TRUE;
02690 
02691  oom:
02692   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
02693   _dbus_list_clear (dir_list);
02694   return FALSE;
02695 }
02696 
02714 dbus_bool_t 
02715 _dbus_get_standard_session_servicedirs (DBusList **dirs)
02716 {
02717   const char *xdg_data_home;
02718   const char *xdg_data_dirs;
02719   DBusString servicedir_path;
02720 
02721   if (!_dbus_string_init (&servicedir_path))
02722     return FALSE;
02723 
02724   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
02725   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
02726 
02727   if (xdg_data_dirs != NULL)
02728     {
02729       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
02730         goto oom;
02731 
02732       if (!_dbus_string_append (&servicedir_path, ":"))
02733         goto oom;
02734     }
02735   else
02736     {
02737       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
02738         goto oom;
02739     }
02740 
02741   /* 
02742    * add configured datadir to defaults
02743    * this may be the same as an xdg dir
02744    * however the config parser should take 
02745    * care of duplicates 
02746    */
02747   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
02748         goto oom;
02749 
02750   if (xdg_data_home != NULL)
02751     {
02752       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
02753         goto oom;
02754     }
02755   else
02756     {
02757       const DBusString *homedir;
02758       const DBusString local_share;
02759 
02760       if (!_dbus_homedir_from_current_process (&homedir))
02761         goto oom;
02762        
02763       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
02764         goto oom;
02765 
02766       _dbus_string_init_const (&local_share, "/.local/share");
02767       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
02768         goto oom;
02769     }
02770 
02771   if (!split_paths_and_append (&servicedir_path, 
02772                                DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
02773                                dirs))
02774     goto oom;
02775 
02776   _dbus_string_free (&servicedir_path);  
02777   return TRUE;
02778 
02779  oom:
02780   _dbus_string_free (&servicedir_path);
02781   return FALSE;
02782 }
02783 
02784 /* tests in dbus-sysdeps-util.c */

Generated on Fri Apr 4 20:38:42 2008 for D-Bus by  doxygen 1.5.1