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 
00766 int
00767 _dbus_listen_tcp_socket (const char     *host,
00768                          dbus_uint32_t   port,
00769                          DBusError      *error)
00770 {
00771   int listen_fd;
00772   struct sockaddr_in addr;
00773   struct hostent *he;
00774   struct in_addr *haddr;
00775 
00776   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00777   
00778   
00779   if (!_dbus_open_tcp_socket (&listen_fd, error))
00780     {
00781       _DBUS_ASSERT_ERROR_IS_SET(error);
00782       return -1;
00783     }
00784   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00785 
00786   he = gethostbyname (host);
00787   if (he == NULL) 
00788     {
00789       dbus_set_error (error,
00790                       _dbus_error_from_errno (errno),
00791                       "Failed to lookup hostname: %s",
00792                       host);
00793       _dbus_close (listen_fd, NULL);
00794       return -1;
00795     }
00796   
00797   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00798 
00799   _DBUS_ZERO (addr);
00800   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00801   addr.sin_family = AF_INET;
00802   addr.sin_port = htons (port);
00803 
00804   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00805     {
00806       dbus_set_error (error, _dbus_error_from_errno (errno),
00807                       "Failed to bind socket \"%s:%d\": %s",
00808                       host, port, _dbus_strerror (errno));
00809       _dbus_close (listen_fd, NULL);
00810       return -1;
00811     }
00812 
00813   if (listen (listen_fd, 30 /* backlog */) < 0)
00814     {
00815       dbus_set_error (error, _dbus_error_from_errno (errno),  
00816                       "Failed to listen on socket \"%s:%d\": %s",
00817                       host, port, _dbus_strerror (errno));
00818       _dbus_close (listen_fd, NULL);
00819       return -1;
00820     }
00821 
00822   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00823     {
00824       _dbus_close (listen_fd, NULL);
00825       return -1;
00826     }
00827   
00828   return listen_fd;
00829 }
00830 
00831 static dbus_bool_t
00832 write_credentials_byte (int             server_fd,
00833                         DBusError      *error)
00834 {
00835   int bytes_written;
00836   char buf[1] = { '\0' };
00837 #if defined(HAVE_CMSGCRED) 
00838   struct {
00839           struct cmsghdr hdr;
00840           struct cmsgcred cred;
00841   } cmsg;
00842   struct iovec iov;
00843   struct msghdr msg;
00844   iov.iov_base = buf;
00845   iov.iov_len = 1;
00846 
00847   memset (&msg, 0, sizeof (msg));
00848   msg.msg_iov = &iov;
00849   msg.msg_iovlen = 1;
00850 
00851   msg.msg_control = &cmsg;
00852   msg.msg_controllen = sizeof (cmsg);
00853   memset (&cmsg, 0, sizeof (cmsg));
00854   cmsg.hdr.cmsg_len = sizeof (cmsg);
00855   cmsg.hdr.cmsg_level = SOL_SOCKET;
00856   cmsg.hdr.cmsg_type = SCM_CREDS;
00857 #endif
00858 
00859   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00860   
00861  again:
00862 
00863 #if defined(HAVE_CMSGCRED) 
00864   bytes_written = sendmsg (server_fd, &msg, 0);
00865 #else
00866   bytes_written = write (server_fd, buf, 1);
00867 #endif
00868 
00869   if (bytes_written < 0 && errno == EINTR)
00870     goto again;
00871 
00872   if (bytes_written < 0)
00873     {
00874       dbus_set_error (error, _dbus_error_from_errno (errno),
00875                       "Failed to write credentials byte: %s",
00876                      _dbus_strerror (errno));
00877       return FALSE;
00878     }
00879   else if (bytes_written == 0)
00880     {
00881       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00882                       "wrote zero bytes writing credentials byte");
00883       return FALSE;
00884     }
00885   else
00886     {
00887       _dbus_assert (bytes_written == 1);
00888       _dbus_verbose ("wrote credentials byte\n");
00889       return TRUE;
00890     }
00891 }
00892 
00911 dbus_bool_t
00912 _dbus_read_credentials_unix_socket  (int              client_fd,
00913                                      DBusCredentials *credentials,
00914                                      DBusError       *error)
00915 {
00916   struct msghdr msg;
00917   struct iovec iov;
00918   char buf;
00919 
00920 #ifdef HAVE_CMSGCRED 
00921   struct {
00922           struct cmsghdr hdr;
00923           struct cmsgcred cred;
00924   } cmsg;
00925 
00926 #elif defined(LOCAL_CREDS)
00927   struct {
00928           struct cmsghdr hdr;
00929           struct sockcred cred;
00930   } cmsg;
00931 #endif
00932 
00933   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00934   
00935   /* The POSIX spec certainly doesn't promise this, but
00936    * we need these assertions to fail as soon as we're wrong about
00937    * it so we can do the porting fixups
00938    */
00939   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00940   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00941   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00942 
00943   _dbus_credentials_clear (credentials);
00944 
00945   /* Systems supporting LOCAL_CREDS are configured to have this feature
00946    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
00947    * the connection.  Therefore, the received message must carry the
00948    * credentials information without doing anything special.
00949    */
00950 
00951   iov.iov_base = &buf;
00952   iov.iov_len = 1;
00953 
00954   memset (&msg, 0, sizeof (msg));
00955   msg.msg_iov = &iov;
00956   msg.msg_iovlen = 1;
00957 
00958 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00959   memset (&cmsg, 0, sizeof (cmsg));
00960   msg.msg_control = &cmsg;
00961   msg.msg_controllen = sizeof (cmsg);
00962 #endif
00963 
00964  again:
00965   if (recvmsg (client_fd, &msg, 0) < 0)
00966     {
00967       if (errno == EINTR)
00968         goto again;
00969 
00970       dbus_set_error (error, _dbus_error_from_errno (errno),
00971                       "Failed to read credentials byte: %s",
00972                       _dbus_strerror (errno));
00973       return FALSE;
00974     }
00975 
00976   if (buf != '\0')
00977     {
00978       dbus_set_error (error, DBUS_ERROR_FAILED,
00979                       "Credentials byte was not nul");
00980       return FALSE;
00981     }
00982 
00983 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00984   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00985     {
00986       dbus_set_error (error, DBUS_ERROR_FAILED,
00987                       "Message from recvmsg() was not SCM_CREDS");
00988       return FALSE;
00989     }
00990 #endif
00991 
00992   _dbus_verbose ("read credentials byte\n");
00993 
00994   {
00995 #ifdef SO_PEERCRED
00996     struct ucred cr;   
00997     int cr_len = sizeof (cr);
00998    
00999     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01000         cr_len == sizeof (cr))
01001       {
01002         credentials->pid = cr.pid;
01003         credentials->uid = cr.uid;
01004         credentials->gid = cr.gid;
01005       }
01006     else
01007       {
01008         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01009                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01010       }
01011 #elif defined(HAVE_CMSGCRED)
01012     credentials->pid = cmsg.cred.cmcred_pid;
01013     credentials->uid = cmsg.cred.cmcred_euid;
01014     credentials->gid = cmsg.cred.cmcred_groups[0];
01015 #elif defined(LOCAL_CREDS)
01016     credentials->pid = DBUS_PID_UNSET;
01017     credentials->uid = cmsg.cred.sc_uid;
01018     credentials->gid = cmsg.cred.sc_gid;
01019     /* Since we have already got the credentials from this socket, we can
01020      * disable its LOCAL_CREDS flag if it was ever set. */
01021     _dbus_set_local_creds (client_fd, FALSE);
01022 #elif defined(HAVE_GETPEEREID)
01023     uid_t euid;
01024     gid_t egid;
01025     if (getpeereid (client_fd, &euid, &egid) == 0)
01026       {
01027         credentials->uid = euid;
01028         credentials->gid = egid;
01029       }
01030     else
01031       {
01032         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01033       }
01034 #elif defined(HAVE_GETPEERUCRED)
01035     ucred_t * ucred = NULL;
01036     if (getpeerucred (client_fd, &ucred) == 0)
01037       {
01038         credentials->pid = ucred_getpid (ucred);
01039         credentials->uid = ucred_geteuid (ucred);
01040         credentials->gid = ucred_getegid (ucred);
01041       }
01042     else
01043       {
01044         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01045       }
01046     if (ucred != NULL)
01047       ucred_free (ucred);
01048 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01049     _dbus_verbose ("Socket credentials not supported on this OS\n");
01050 #endif
01051   }
01052 
01053   _dbus_verbose ("Credentials:"
01054                  "  pid "DBUS_PID_FORMAT
01055                  "  uid "DBUS_UID_FORMAT
01056                  "  gid "DBUS_GID_FORMAT"\n",
01057                  credentials->pid,
01058                  credentials->uid,
01059                  credentials->gid);
01060     
01061   return TRUE;
01062 }
01063 
01081 dbus_bool_t
01082 _dbus_send_credentials_unix_socket  (int              server_fd,
01083                                      DBusError       *error)
01084 {
01085   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01086   
01087   if (write_credentials_byte (server_fd, error))
01088     return TRUE;
01089   else
01090     return FALSE;
01091 }
01092 
01100 int
01101 _dbus_accept  (int listen_fd)
01102 {
01103   int client_fd;
01104   struct sockaddr addr;
01105   socklen_t addrlen;
01106 
01107   addrlen = sizeof (addr);
01108   
01109  retry:
01110   client_fd = accept (listen_fd, &addr, &addrlen);
01111   
01112   if (client_fd < 0)
01113     {
01114       if (errno == EINTR)
01115         goto retry;
01116     }
01117   
01118   return client_fd;
01119 }
01120 
01129 dbus_bool_t
01130 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01131 {
01132   const char *directory;
01133   struct stat sb;
01134         
01135   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01136     
01137   directory = _dbus_string_get_const_data (dir);
01138         
01139   if (stat (directory, &sb) < 0)
01140     {
01141       dbus_set_error (error, _dbus_error_from_errno (errno),
01142                       "%s", _dbus_strerror (errno));
01143    
01144       return FALSE;
01145     }
01146     
01147   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01148       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01149     {
01150       dbus_set_error (error, DBUS_ERROR_FAILED,
01151                      "%s directory is not private to the user", directory);
01152       return FALSE;
01153     }
01154     
01155   return TRUE;
01156 }
01157 
01158 static dbus_bool_t
01159 fill_user_info_from_passwd (struct passwd *p,
01160                             DBusUserInfo  *info,
01161                             DBusError     *error)
01162 {
01163   _dbus_assert (p->pw_name != NULL);
01164   _dbus_assert (p->pw_dir != NULL);
01165   
01166   info->uid = p->pw_uid;
01167   info->primary_gid = p->pw_gid;
01168   info->username = _dbus_strdup (p->pw_name);
01169   info->homedir = _dbus_strdup (p->pw_dir);
01170   
01171   if (info->username == NULL ||
01172       info->homedir == NULL)
01173     {
01174       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01175       return FALSE;
01176     }
01177 
01178   return TRUE;
01179 }
01180 
01181 static dbus_bool_t
01182 fill_user_info (DBusUserInfo       *info,
01183                 dbus_uid_t          uid,
01184                 const DBusString   *username,
01185                 DBusError          *error)
01186 {
01187   const char *username_c;
01188   
01189   /* exactly one of username/uid provided */
01190   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01191   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01192 
01193   info->uid = DBUS_UID_UNSET;
01194   info->primary_gid = DBUS_GID_UNSET;
01195   info->group_ids = NULL;
01196   info->n_group_ids = 0;
01197   info->username = NULL;
01198   info->homedir = NULL;
01199   
01200   if (username != NULL)
01201     username_c = _dbus_string_get_const_data (username);
01202   else
01203     username_c = NULL;
01204 
01205   /* For now assuming that the getpwnam() and getpwuid() flavors
01206    * are always symmetrical, if not we have to add more configure
01207    * checks
01208    */
01209   
01210 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01211   {
01212     struct passwd *p;
01213     int result;
01214     char buf[1024];
01215     struct passwd p_str;
01216 
01217     p = NULL;
01218 #ifdef HAVE_POSIX_GETPWNAM_R
01219     if (uid != DBUS_UID_UNSET)
01220       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01221                            &p);
01222     else
01223       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01224                            &p);
01225 #else
01226     if (uid != DBUS_UID_UNSET)
01227       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01228     else
01229       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01230     result = 0;
01231 #endif /* !HAVE_POSIX_GETPWNAM_R */
01232     if (result == 0 && p == &p_str)
01233       {
01234         if (!fill_user_info_from_passwd (p, info, error))
01235           return FALSE;
01236       }
01237     else
01238       {
01239         dbus_set_error (error, _dbus_error_from_errno (errno),
01240                         "User \"%s\" unknown or no memory to allocate password entry\n",
01241                         username_c ? username_c : "???");
01242         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01243         return FALSE;
01244       }
01245   }
01246 #else /* ! HAVE_GETPWNAM_R */
01247   {
01248     /* I guess we're screwed on thread safety here */
01249     struct passwd *p;
01250 
01251     if (uid != DBUS_UID_UNSET)
01252       p = getpwuid (uid);
01253     else
01254       p = getpwnam (username_c);
01255 
01256     if (p != NULL)
01257       {
01258         if (!fill_user_info_from_passwd (p, info, error))
01259           return FALSE;
01260       }
01261     else
01262       {
01263         dbus_set_error (error, _dbus_error_from_errno (errno),
01264                         "User \"%s\" unknown or no memory to allocate password entry\n",
01265                         username_c ? username_c : "???");
01266         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01267         return FALSE;
01268       }
01269   }
01270 #endif  /* ! HAVE_GETPWNAM_R */
01271 
01272   /* Fill this in so we can use it to get groups */
01273   username_c = info->username;
01274   
01275 #ifdef HAVE_GETGROUPLIST
01276   {
01277     gid_t *buf;
01278     int buf_count;
01279     int i;
01280     
01281     buf_count = 17;
01282     buf = dbus_new (gid_t, buf_count);
01283     if (buf == NULL)
01284       {
01285         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01286         goto failed;
01287       }
01288     
01289     if (getgrouplist (username_c,
01290                       info->primary_gid,
01291                       buf, &buf_count) < 0)
01292       {
01293         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01294         if (new == NULL)
01295           {
01296             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01297             dbus_free (buf);
01298             goto failed;
01299           }
01300         
01301         buf = new;
01302 
01303         errno = 0;
01304         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01305           {
01306             dbus_set_error (error,
01307                             _dbus_error_from_errno (errno),
01308                             "Failed to get groups for username \"%s\" primary GID "
01309                             DBUS_GID_FORMAT ": %s\n",
01310                             username_c, info->primary_gid,
01311                             _dbus_strerror (errno));
01312             dbus_free (buf);
01313             goto failed;
01314           }
01315       }
01316 
01317     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01318     if (info->group_ids == NULL)
01319       {
01320         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01321         dbus_free (buf);
01322         goto failed;
01323       }
01324     
01325     for (i = 0; i < buf_count; ++i)
01326       info->group_ids[i] = buf[i];
01327 
01328     info->n_group_ids = buf_count;
01329     
01330     dbus_free (buf);
01331   }
01332 #else  /* HAVE_GETGROUPLIST */
01333   {
01334     /* We just get the one group ID */
01335     info->group_ids = dbus_new (dbus_gid_t, 1);
01336     if (info->group_ids == NULL)
01337       {
01338         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01339         goto failed;
01340       }
01341 
01342     info->n_group_ids = 1;
01343 
01344     (info->group_ids)[0] = info->primary_gid;
01345   }
01346 #endif /* HAVE_GETGROUPLIST */
01347 
01348   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01349   
01350   return TRUE;
01351   
01352  failed:
01353   _DBUS_ASSERT_ERROR_IS_SET (error);
01354   return FALSE;
01355 }
01356 
01365 dbus_bool_t
01366 _dbus_user_info_fill (DBusUserInfo     *info,
01367                       const DBusString *username,
01368                       DBusError        *error)
01369 {
01370   return fill_user_info (info, DBUS_UID_UNSET,
01371                          username, error);
01372 }
01373 
01382 dbus_bool_t
01383 _dbus_user_info_fill_uid (DBusUserInfo *info,
01384                           dbus_uid_t    uid,
01385                           DBusError    *error)
01386 {
01387   return fill_user_info (info, uid,
01388                          NULL, error);
01389 }
01390 
01396 void
01397 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01398 {
01399   /* The POSIX spec certainly doesn't promise this, but
01400    * we need these assertions to fail as soon as we're wrong about
01401    * it so we can do the porting fixups
01402    */
01403   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01404   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01405   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01406   
01407   credentials->pid = getpid ();
01408   credentials->uid = getuid ();
01409   credentials->gid = getgid ();
01410 }
01411 
01416 unsigned long
01417 _dbus_getpid (void)
01418 {
01419   return getpid ();
01420 }
01421 
01425 dbus_uid_t
01426 _dbus_getuid (void)
01427 {
01428   return getuid ();
01429 }
01430 
01431 #ifdef DBUS_BUILD_TESTS
01432 
01435 dbus_gid_t
01436 _dbus_getgid (void)
01437 {
01438   return getgid ();
01439 }
01440 #endif
01441 
01450 int
01451 _dbus_poll (DBusPollFD *fds,
01452             int         n_fds,
01453             int         timeout_milliseconds)
01454 {
01455 #ifdef HAVE_POLL
01456   /* This big thing is a constant expression and should get optimized
01457    * out of existence. So it's more robust than a configure check at
01458    * no cost.
01459    */
01460   if (_DBUS_POLLIN == POLLIN &&
01461       _DBUS_POLLPRI == POLLPRI &&
01462       _DBUS_POLLOUT == POLLOUT &&
01463       _DBUS_POLLERR == POLLERR &&
01464       _DBUS_POLLHUP == POLLHUP &&
01465       _DBUS_POLLNVAL == POLLNVAL &&
01466       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01467       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01468       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01469       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01470       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01471       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01472       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01473     {
01474       return poll ((struct pollfd*) fds,
01475                    n_fds, 
01476                    timeout_milliseconds);
01477     }
01478   else
01479     {
01480       /* We have to convert the DBusPollFD to an array of
01481        * struct pollfd, poll, and convert back.
01482        */
01483       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01484       return -1;
01485     }
01486 #else /* ! HAVE_POLL */
01487 
01488   fd_set read_set, write_set, err_set;
01489   int max_fd = 0;
01490   int i;
01491   struct timeval tv;
01492   int ready;
01493   
01494   FD_ZERO (&read_set);
01495   FD_ZERO (&write_set);
01496   FD_ZERO (&err_set);
01497 
01498   for (i = 0; i < n_fds; i++)
01499     {
01500       DBusPollFD *fdp = &fds[i];
01501 
01502       if (fdp->events & _DBUS_POLLIN)
01503         FD_SET (fdp->fd, &read_set);
01504 
01505       if (fdp->events & _DBUS_POLLOUT)
01506         FD_SET (fdp->fd, &write_set);
01507 
01508       FD_SET (fdp->fd, &err_set);
01509 
01510       max_fd = MAX (max_fd, fdp->fd);
01511     }
01512     
01513   tv.tv_sec = timeout_milliseconds / 1000;
01514   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01515 
01516   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01517                   timeout_milliseconds < 0 ? NULL : &tv);
01518 
01519   if (ready > 0)
01520     {
01521       for (i = 0; i < n_fds; i++)
01522         {
01523           DBusPollFD *fdp = &fds[i];
01524 
01525           fdp->revents = 0;
01526 
01527           if (FD_ISSET (fdp->fd, &read_set))
01528             fdp->revents |= _DBUS_POLLIN;
01529 
01530           if (FD_ISSET (fdp->fd, &write_set))
01531             fdp->revents |= _DBUS_POLLOUT;
01532 
01533           if (FD_ISSET (fdp->fd, &err_set))
01534             fdp->revents |= _DBUS_POLLERR;
01535         }
01536     }
01537 
01538   return ready;
01539 #endif
01540 }
01541 
01548 void
01549 _dbus_get_current_time (long *tv_sec,
01550                         long *tv_usec)
01551 {
01552   struct timeval t;
01553 
01554   gettimeofday (&t, NULL);
01555 
01556   if (tv_sec)
01557     *tv_sec = t.tv_sec;
01558   if (tv_usec)
01559     *tv_usec = t.tv_usec;
01560 }
01561 
01572 dbus_bool_t
01573 _dbus_file_get_contents (DBusString       *str,
01574                          const DBusString *filename,
01575                          DBusError        *error)
01576 {
01577   int fd;
01578   struct stat sb;
01579   int orig_len;
01580   int total;
01581   const char *filename_c;
01582 
01583   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01584   
01585   filename_c = _dbus_string_get_const_data (filename);
01586   
01587   /* O_BINARY useful on Cygwin */
01588   fd = open (filename_c, O_RDONLY | O_BINARY);
01589   if (fd < 0)
01590     {
01591       dbus_set_error (error, _dbus_error_from_errno (errno),
01592                       "Failed to open \"%s\": %s",
01593                       filename_c,
01594                       _dbus_strerror (errno));
01595       return FALSE;
01596     }
01597 
01598   if (fstat (fd, &sb) < 0)
01599     {
01600       dbus_set_error (error, _dbus_error_from_errno (errno),
01601                       "Failed to stat \"%s\": %s",
01602                       filename_c,
01603                       _dbus_strerror (errno));
01604 
01605       _dbus_verbose ("fstat() failed: %s",
01606                      _dbus_strerror (errno));
01607       
01608       _dbus_close (fd, NULL);
01609       
01610       return FALSE;
01611     }
01612 
01613   if (sb.st_size > _DBUS_ONE_MEGABYTE)
01614     {
01615       dbus_set_error (error, DBUS_ERROR_FAILED,
01616                       "File size %lu of \"%s\" is too large.",
01617                       (unsigned long) sb.st_size, filename_c);
01618       _dbus_close (fd, NULL);
01619       return FALSE;
01620     }
01621   
01622   total = 0;
01623   orig_len = _dbus_string_get_length (str);
01624   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
01625     {
01626       int bytes_read;
01627 
01628       while (total < (int) sb.st_size)
01629         {
01630           bytes_read = _dbus_read (fd, str,
01631                                    sb.st_size - total);
01632           if (bytes_read <= 0)
01633             {
01634               dbus_set_error (error, _dbus_error_from_errno (errno),
01635                               "Error reading \"%s\": %s",
01636                               filename_c,
01637                               _dbus_strerror (errno));
01638 
01639               _dbus_verbose ("read() failed: %s",
01640                              _dbus_strerror (errno));
01641               
01642               _dbus_close (fd, NULL);
01643               _dbus_string_set_length (str, orig_len);
01644               return FALSE;
01645             }
01646           else
01647             total += bytes_read;
01648         }
01649 
01650       _dbus_close (fd, NULL);
01651       return TRUE;
01652     }
01653   else if (sb.st_size != 0)
01654     {
01655       _dbus_verbose ("Can only open regular files at the moment.\n");
01656       dbus_set_error (error, DBUS_ERROR_FAILED,
01657                       "\"%s\" is not a regular file",
01658                       filename_c);
01659       _dbus_close (fd, NULL);
01660       return FALSE;
01661     }
01662   else
01663     {
01664       _dbus_close (fd, NULL);
01665       return TRUE;
01666     }
01667 }
01668 
01678 dbus_bool_t
01679 _dbus_string_save_to_file (const DBusString *str,
01680                            const DBusString *filename,
01681                            DBusError        *error)
01682 {
01683   int fd;
01684   int bytes_to_write;
01685   const char *filename_c;
01686   DBusString tmp_filename;
01687   const char *tmp_filename_c;
01688   int total;
01689   dbus_bool_t need_unlink;
01690   dbus_bool_t retval;
01691 
01692   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01693   
01694   fd = -1;
01695   retval = FALSE;
01696   need_unlink = FALSE;
01697   
01698   if (!_dbus_string_init (&tmp_filename))
01699     {
01700       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01701       return FALSE;
01702     }
01703 
01704   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
01705     {
01706       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01707       _dbus_string_free (&tmp_filename);
01708       return FALSE;
01709     }
01710   
01711   if (!_dbus_string_append (&tmp_filename, "."))
01712     {
01713       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01714       _dbus_string_free (&tmp_filename);
01715       return FALSE;
01716     }
01717 
01718 #define N_TMP_FILENAME_RANDOM_BYTES 8
01719   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
01720     {
01721       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01722       _dbus_string_free (&tmp_filename);
01723       return FALSE;
01724     }
01725     
01726   filename_c = _dbus_string_get_const_data (filename);
01727   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
01728 
01729   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01730              0600);
01731   if (fd < 0)
01732     {
01733       dbus_set_error (error, _dbus_error_from_errno (errno),
01734                       "Could not create %s: %s", tmp_filename_c,
01735                       _dbus_strerror (errno));
01736       goto out;
01737     }
01738 
01739   need_unlink = TRUE;
01740   
01741   total = 0;
01742   bytes_to_write = _dbus_string_get_length (str);
01743 
01744   while (total < bytes_to_write)
01745     {
01746       int bytes_written;
01747 
01748       bytes_written = _dbus_write (fd, str, total,
01749                                    bytes_to_write - total);
01750 
01751       if (bytes_written <= 0)
01752         {
01753           dbus_set_error (error, _dbus_error_from_errno (errno),
01754                           "Could not write to %s: %s", tmp_filename_c,
01755                           _dbus_strerror (errno));
01756           
01757           goto out;
01758         }
01759 
01760       total += bytes_written;
01761     }
01762 
01763   if (!_dbus_close (fd, NULL))
01764     {
01765       dbus_set_error (error, _dbus_error_from_errno (errno),
01766                       "Could not close file %s: %s",
01767                       tmp_filename_c, _dbus_strerror (errno));
01768 
01769       goto out;
01770     }
01771 
01772   fd = -1;
01773   
01774   if (rename (tmp_filename_c, filename_c) < 0)
01775     {
01776       dbus_set_error (error, _dbus_error_from_errno (errno),
01777                       "Could not rename %s to %s: %s",
01778                       tmp_filename_c, filename_c,
01779                       _dbus_strerror (errno));
01780 
01781       goto out;
01782     }
01783 
01784   need_unlink = FALSE;
01785   
01786   retval = TRUE;
01787   
01788  out:
01789   /* close first, then unlink, to prevent ".nfs34234235" garbage
01790    * files
01791    */
01792 
01793   if (fd >= 0)
01794     _dbus_close (fd, NULL);
01795         
01796   if (need_unlink && unlink (tmp_filename_c) < 0)
01797     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
01798                    tmp_filename_c, _dbus_strerror (errno));
01799 
01800   _dbus_string_free (&tmp_filename);
01801 
01802   if (!retval)
01803     _DBUS_ASSERT_ERROR_IS_SET (error);
01804   
01805   return retval;
01806 }
01807 
01814 dbus_bool_t
01815 _dbus_make_file_world_readable(const DBusString *filename,
01816                                DBusError *error)
01817 {
01818   const char *filename_c;
01819 
01820   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01821 
01822   filename_c = _dbus_string_get_const_data (filename);
01823   if (chmod (filename_c, 0644) == -1)
01824     {
01825       dbus_set_error (error,
01826                       DBUS_ERROR_FAILED,
01827                       "Could not change permissions of file %s: %s\n",
01828                       filename_c,
01829                       _dbus_strerror (errno));
01830       return FALSE;
01831     }
01832   return TRUE;
01833 }
01834 
01841 dbus_bool_t
01842 _dbus_create_file_exclusively (const DBusString *filename,
01843                                DBusError        *error)
01844 {
01845   int fd;
01846   const char *filename_c;
01847 
01848   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01849   
01850   filename_c = _dbus_string_get_const_data (filename);
01851   
01852   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01853              0600);
01854   if (fd < 0)
01855     {
01856       dbus_set_error (error,
01857                       DBUS_ERROR_FAILED,
01858                       "Could not create file %s: %s\n",
01859                       filename_c,
01860                       _dbus_strerror (errno));
01861       return FALSE;
01862     }
01863 
01864   if (!_dbus_close (fd, NULL))
01865     {
01866       dbus_set_error (error,
01867                       DBUS_ERROR_FAILED,
01868                       "Could not close file %s: %s\n",
01869                       filename_c,
01870                       _dbus_strerror (errno));
01871       return FALSE;
01872     }
01873   
01874   return TRUE;
01875 }
01876 
01885 dbus_bool_t
01886 _dbus_delete_file (const DBusString *filename,
01887                    DBusError        *error)
01888 {
01889   const char *filename_c;
01890 
01891   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01892   
01893   filename_c = _dbus_string_get_const_data (filename);
01894 
01895   if (unlink (filename_c) < 0)
01896     {
01897       dbus_set_error (error, DBUS_ERROR_FAILED,
01898                       "Failed to delete file %s: %s\n",
01899                       filename_c, _dbus_strerror (errno));
01900       return FALSE;
01901     }
01902   else
01903     return TRUE;
01904 }
01905 
01914 dbus_bool_t
01915 _dbus_create_directory (const DBusString *filename,
01916                         DBusError        *error)
01917 {
01918   const char *filename_c;
01919 
01920   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01921   
01922   filename_c = _dbus_string_get_const_data (filename);
01923 
01924   if (mkdir (filename_c, 0700) < 0)
01925     {
01926       if (errno == EEXIST)
01927         return TRUE;
01928       
01929       dbus_set_error (error, DBUS_ERROR_FAILED,
01930                       "Failed to create directory %s: %s\n",
01931                       filename_c, _dbus_strerror (errno));
01932       return FALSE;
01933     }
01934   else
01935     return TRUE;
01936 }
01937 
01948 dbus_bool_t
01949 _dbus_concat_dir_and_file (DBusString       *dir,
01950                            const DBusString *next_component)
01951 {
01952   dbus_bool_t dir_ends_in_slash;
01953   dbus_bool_t file_starts_with_slash;
01954 
01955   if (_dbus_string_get_length (dir) == 0 ||
01956       _dbus_string_get_length (next_component) == 0)
01957     return TRUE;
01958   
01959   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
01960                                                     _dbus_string_get_length (dir) - 1);
01961 
01962   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
01963 
01964   if (dir_ends_in_slash && file_starts_with_slash)
01965     {
01966       _dbus_string_shorten (dir, 1);
01967     }
01968   else if (!(dir_ends_in_slash || file_starts_with_slash))
01969     {
01970       if (!_dbus_string_append_byte (dir, '/'))
01971         return FALSE;
01972     }
01973 
01974   return _dbus_string_copy (next_component, 0, dir,
01975                             _dbus_string_get_length (dir));
01976 }
01977 
01979 #define NANOSECONDS_PER_SECOND       1000000000
01980 
01981 #define MICROSECONDS_PER_SECOND      1000000
01982 
01983 #define MILLISECONDS_PER_SECOND      1000
01984 
01985 #define NANOSECONDS_PER_MILLISECOND  1000000
01986 
01987 #define MICROSECONDS_PER_MILLISECOND 1000
01988 
01993 void
01994 _dbus_sleep_milliseconds (int milliseconds)
01995 {
01996 #ifdef HAVE_NANOSLEEP
01997   struct timespec req;
01998   struct timespec rem;
01999 
02000   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02001   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02002   rem.tv_sec = 0;
02003   rem.tv_nsec = 0;
02004 
02005   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02006     req = rem;
02007 #elif defined (HAVE_USLEEP)
02008   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02009 #else /* ! HAVE_USLEEP */
02010   sleep (MAX (milliseconds / 1000, 1));
02011 #endif
02012 }
02013 
02014 static dbus_bool_t
02015 _dbus_generate_pseudorandom_bytes (DBusString *str,
02016                                    int         n_bytes)
02017 {
02018   int old_len;
02019   char *p;
02020   
02021   old_len = _dbus_string_get_length (str);
02022 
02023   if (!_dbus_string_lengthen (str, n_bytes))
02024     return FALSE;
02025 
02026   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02027 
02028   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02029 
02030   return TRUE;
02031 }
02032 
02041 dbus_bool_t
02042 _dbus_generate_random_bytes (DBusString *str,
02043                              int         n_bytes)
02044 {
02045   int old_len;
02046   int fd;
02047 
02048   /* FALSE return means "no memory", if it could
02049    * mean something else then we'd need to return
02050    * a DBusError. So we always fall back to pseudorandom
02051    * if the I/O fails.
02052    */
02053   
02054   old_len = _dbus_string_get_length (str);
02055   fd = -1;
02056 
02057   /* note, urandom on linux will fall back to pseudorandom */
02058   fd = open ("/dev/urandom", O_RDONLY);
02059   if (fd < 0)
02060     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02061 
02062   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02063     {
02064       _dbus_close (fd, NULL);
02065       _dbus_string_set_length (str, old_len);
02066       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02067     }
02068 
02069   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02070                  n_bytes);
02071   
02072   _dbus_close (fd, NULL);
02073   
02074   return TRUE;
02075 }
02076 
02082 void
02083 _dbus_exit (int code)
02084 {
02085   _exit (code);
02086 }
02087 
02095 const char*
02096 _dbus_strerror (int error_number)
02097 {
02098   const char *msg;
02099   
02100   msg = strerror (error_number);
02101   if (msg == NULL)
02102     msg = "unknown";
02103 
02104   return msg;
02105 }
02106 
02110 void
02111 _dbus_disable_sigpipe (void)
02112 {
02113   signal (SIGPIPE, SIG_IGN);
02114 }
02115 
02123 void
02124 _dbus_fd_set_close_on_exec (int fd)
02125 {
02126   int val;
02127   
02128   val = fcntl (fd, F_GETFD, 0);
02129   
02130   if (val < 0)
02131     return;
02132 
02133   val |= FD_CLOEXEC;
02134   
02135   fcntl (fd, F_SETFD, val);
02136 }
02137 
02145 dbus_bool_t
02146 _dbus_close (int        fd,
02147              DBusError *error)
02148 {
02149   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02150   
02151  again:
02152   if (close (fd) < 0)
02153     {
02154       if (errno == EINTR)
02155         goto again;
02156 
02157       dbus_set_error (error, _dbus_error_from_errno (errno),
02158                       "Could not close fd %d", fd);
02159       return FALSE;
02160     }
02161 
02162   return TRUE;
02163 }
02164 
02172 dbus_bool_t
02173 _dbus_set_fd_nonblocking (int             fd,
02174                           DBusError      *error)
02175 {
02176   int val;
02177 
02178   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02179   
02180   val = fcntl (fd, F_GETFL, 0);
02181   if (val < 0)
02182     {
02183       dbus_set_error (error, _dbus_error_from_errno (errno),
02184                       "Failed to get flags from file descriptor %d: %s",
02185                       fd, _dbus_strerror (errno));
02186       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02187                      _dbus_strerror (errno));
02188       return FALSE;
02189     }
02190 
02191   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02192     {
02193       dbus_set_error (error, _dbus_error_from_errno (errno),
02194                       "Failed to set nonblocking flag of file descriptor %d: %s",
02195                       fd, _dbus_strerror (errno));
02196       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02197                      fd, _dbus_strerror (errno));
02198 
02199       return FALSE;
02200     }
02201 
02202   return TRUE;
02203 }
02204 
02210 void
02211 _dbus_print_backtrace (void)
02212 {  
02213 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02214   void *bt[500];
02215   int bt_size;
02216   int i;
02217   char **syms;
02218   
02219   bt_size = backtrace (bt, 500);
02220 
02221   syms = backtrace_symbols (bt, bt_size);
02222   
02223   i = 0;
02224   while (i < bt_size)
02225     {
02226       /* don't use dbus_warn since it can _dbus_abort() */
02227       fprintf (stderr, "  %s\n", syms[i]);
02228       ++i;
02229     }
02230   fflush (stderr);
02231 
02232   free (syms);
02233 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02234   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02235 #else
02236   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02237 #endif
02238 }
02239 
02255 dbus_bool_t
02256 _dbus_full_duplex_pipe (int        *fd1,
02257                         int        *fd2,
02258                         dbus_bool_t blocking,
02259                         DBusError  *error)
02260 {
02261 #ifdef HAVE_SOCKETPAIR
02262   int fds[2];
02263 
02264   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02265   
02266   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02267     {
02268       dbus_set_error (error, _dbus_error_from_errno (errno),
02269                       "Could not create full-duplex pipe");
02270       return FALSE;
02271     }
02272 
02273   if (!blocking &&
02274       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02275        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02276     {
02277       dbus_set_error (error, _dbus_error_from_errno (errno),
02278                       "Could not set full-duplex pipe nonblocking");
02279       
02280       _dbus_close (fds[0], NULL);
02281       _dbus_close (fds[1], NULL);
02282       
02283       return FALSE;
02284     }
02285   
02286   *fd1 = fds[0];
02287   *fd2 = fds[1];
02288 
02289   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02290                  *fd1, *fd2);
02291   
02292   return TRUE;  
02293 #else
02294   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02295   dbus_set_error (error, DBUS_ERROR_FAILED,
02296                   "_dbus_full_duplex_pipe() not implemented on this OS");
02297   return FALSE;
02298 #endif
02299 }
02300 
02301 
02310 int
02311 _dbus_printf_string_upper_bound (const char *format,
02312                                  va_list     args)
02313 {
02314   char c;
02315   return vsnprintf (&c, 1, format, args);
02316 }
02317 
02324 const char*
02325 _dbus_get_tmpdir(void)
02326 {
02327   static const char* tmpdir = NULL;
02328 
02329   if (tmpdir == NULL)
02330     {
02331       /* TMPDIR is what glibc uses, then
02332        * glibc falls back to the P_tmpdir macro which
02333        * just expands to "/tmp"
02334        */
02335       if (tmpdir == NULL)
02336         tmpdir = getenv("TMPDIR");
02337 
02338       /* These two env variables are probably
02339        * broken, but maybe some OS uses them?
02340        */
02341       if (tmpdir == NULL)
02342         tmpdir = getenv("TMP");
02343       if (tmpdir == NULL)
02344         tmpdir = getenv("TEMP");
02345 
02346       /* And this is the sane fallback. */
02347       if (tmpdir == NULL)
02348         tmpdir = "/tmp";
02349     }
02350   
02351   _dbus_assert(tmpdir != NULL);
02352   
02353   return tmpdir;
02354 }
02355 
02368 dbus_bool_t
02369 _dbus_get_autolaunch_address (DBusString *address,
02370                               DBusError  *error)
02371 {
02372   static char *argv[5];
02373   int address_pipe[2];
02374   pid_t pid;
02375   int ret;
02376   int status;
02377   int orig_len;
02378   int i;
02379   DBusString uuid;
02380   dbus_bool_t retval;
02381   
02382   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02383   retval = FALSE;
02384 
02385   _dbus_string_init (&uuid);
02386   
02387   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02388     {
02389       _DBUS_SET_OOM (error);
02390       goto out;
02391     }
02392   
02393   i = 0;
02394   argv[i] = "dbus-launch";
02395   ++i;
02396   argv[i] = "--autolaunch";
02397   ++i;
02398   argv[i] = _dbus_string_get_data (&uuid);
02399   ++i;
02400   argv[i] = "--binary-syntax";
02401   ++i;
02402   argv[i] = NULL;
02403   ++i;
02404 
02405   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02406   
02407   orig_len = _dbus_string_get_length (address);
02408   
02409 #define READ_END        0
02410 #define WRITE_END       1
02411   if (pipe (address_pipe) < 0)
02412     {
02413       dbus_set_error (error, _dbus_error_from_errno (errno),
02414                       "Failed to create a pipe: %s",
02415                       _dbus_strerror (errno));
02416       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02417                      _dbus_strerror (errno));
02418       goto out;
02419     }
02420 
02421   pid = fork ();
02422   if (pid < 0)
02423     {
02424       dbus_set_error (error, _dbus_error_from_errno (errno),
02425                       "Failed to fork(): %s",
02426                       _dbus_strerror (errno));
02427       _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02428                      _dbus_strerror (errno));
02429       goto out;
02430     }
02431 
02432   if (pid == 0)
02433     {
02434       /* child process */
02435       int fd = open ("/dev/null", O_RDWR);
02436       if (fd == -1)
02437         /* huh?! can't open /dev/null? */
02438         _exit (1);
02439 
02440       /* set-up stdXXX */
02441       close (address_pipe[READ_END]);
02442       close (0);                /* close stdin */
02443       close (1);                /* close stdout */
02444       close (2);                /* close stderr */
02445 
02446       if (dup2 (fd, 0) == -1)
02447         _exit (1);
02448       if (dup2 (address_pipe[WRITE_END], 1) == -1)
02449         _exit (1);
02450       if (dup2 (fd, 2) == -1)
02451         _exit (1);
02452 
02453       close (fd);
02454       close (address_pipe[WRITE_END]);
02455 
02456       execv (DBUS_BINDIR "/dbus-launch", argv);
02457 
02458       /* failed, try searching PATH */
02459       execvp ("dbus-launch", argv);
02460 
02461       /* still nothing, we failed */
02462       _exit (1);
02463     }
02464 
02465   /* parent process */
02466   close (address_pipe[WRITE_END]);
02467   ret = 0;
02468   do 
02469     {
02470       ret = _dbus_read (address_pipe[READ_END], address, 1024);
02471     }
02472   while (ret > 0);
02473 
02474   /* reap the child process to avoid it lingering as zombie */
02475   do
02476     {
02477       ret = waitpid (pid, &status, 0);
02478     }
02479   while (ret == -1 && errno == EINTR);
02480 
02481   /* We succeeded if the process exited with status 0 and
02482      anything was read */
02483   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02484       _dbus_string_get_length (address) == orig_len)
02485     {
02486       /* The process ended with error */
02487       _dbus_string_set_length (address, orig_len);
02488       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02489                       "Failed to execute dbus-launch to autolaunch D-Bus session");
02490       goto out;
02491     }
02492 
02493   retval = TRUE;
02494   
02495  out:
02496   if (retval)
02497     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02498   else
02499     _DBUS_ASSERT_ERROR_IS_SET (error);
02500   
02501   _dbus_string_free (&uuid);
02502   return retval;
02503 }
02504 
02523 dbus_bool_t
02524 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
02525                                dbus_bool_t create_if_not_found,
02526                                DBusError  *error)
02527 {
02528   DBusString filename;
02529   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
02530   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
02531 }
02532 
02533 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
02534 
02535 static dbus_bool_t
02536 split_paths_and_append (DBusString *dirs, 
02537                         const char *suffix, 
02538                         DBusList **dir_list)
02539 {
02540   /* split on colon (:) */
02541    int start;
02542    int i;
02543    int len;
02544    char *cpath;
02545    const DBusString file_suffix;
02546 
02547    start = 0;
02548    i = 0;
02549 
02550    _dbus_string_init_const (&file_suffix, suffix);
02551 
02552    len = _dbus_string_get_length (dirs);
02553 
02554    while (_dbus_string_find (dirs, start, ":", &i))
02555      {
02556        DBusString path;
02557 
02558        if (!_dbus_string_init (&path))
02559           goto oom;
02560 
02561        if (!_dbus_string_copy_len (dirs,
02562                                    start,
02563                                    i - start,
02564                                    &path,
02565                                    0))
02566           {
02567             _dbus_string_free (&path);
02568             goto oom;
02569           }
02570 
02571         _dbus_string_chop_white (&path);
02572 
02573         /* check for an empty path */
02574         if (_dbus_string_get_length (&path) == 0)
02575           goto next;
02576 
02577         if (!_dbus_concat_dir_and_file (&path,
02578                                         &file_suffix))
02579           {
02580             _dbus_string_free (&path);
02581             goto oom;
02582           }
02583 
02584         if (!_dbus_string_copy_data(&path, &cpath))
02585           {
02586             _dbus_string_free (&path);
02587             goto oom;
02588           }
02589 
02590         if (!_dbus_list_append (dir_list, cpath))
02591           {
02592             _dbus_string_free (&path);              
02593             dbus_free (cpath);
02594             goto oom;
02595           }
02596 
02597        next:
02598         _dbus_string_free (&path);
02599         start = i + 1;
02600     } 
02601       
02602   if (start != len)
02603     { 
02604       DBusString path;
02605 
02606       if (!_dbus_string_init (&path))
02607         goto oom;
02608 
02609       if (!_dbus_string_copy_len (dirs,
02610                                   start,
02611                                   len - start,
02612                                   &path,
02613                                   0))
02614         {
02615           _dbus_string_free (&path);
02616           goto oom;
02617         }
02618 
02619       if (!_dbus_concat_dir_and_file (&path,
02620                                       &file_suffix))
02621         {
02622           _dbus_string_free (&path);
02623           goto oom;
02624         }
02625 
02626       if (!_dbus_string_copy_data(&path, &cpath))
02627         {
02628           _dbus_string_free (&path);
02629           goto oom;
02630         }
02631 
02632       if (!_dbus_list_append (dir_list, cpath))
02633         {
02634           _dbus_string_free (&path);              
02635           dbus_free (cpath);
02636           goto oom;
02637         }
02638 
02639       _dbus_string_free (&path); 
02640     }
02641 
02642   return TRUE;
02643 
02644  oom:
02645   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
02646   _dbus_list_clear (dir_list);
02647   return FALSE;
02648 }
02649 
02667 dbus_bool_t 
02668 _dbus_get_standard_session_servicedirs (DBusList **dirs)
02669 {
02670   const char *xdg_data_home;
02671   const char *xdg_data_dirs;
02672   DBusString servicedir_path;
02673 
02674   if (!_dbus_string_init (&servicedir_path))
02675     return FALSE;
02676 
02677   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
02678   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
02679 
02680   if (xdg_data_dirs != NULL)
02681     {
02682       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
02683         goto oom;
02684 
02685       if (!_dbus_string_append (&servicedir_path, ":"))
02686         goto oom;
02687     }
02688   else
02689     {
02690       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
02691         goto oom;
02692     }
02693 
02694   /* 
02695    * add configured datadir to defaults
02696    * this may be the same as an xdg dir
02697    * however the config parser should take 
02698    * care of duplicates 
02699    */
02700   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
02701         goto oom;
02702 
02703   if (xdg_data_home != NULL)
02704     {
02705       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
02706         goto oom;
02707     }
02708   else
02709     {
02710       const DBusString *homedir;
02711       const DBusString local_share;
02712 
02713       if (!_dbus_homedir_from_current_process (&homedir))
02714         goto oom;
02715        
02716       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
02717         goto oom;
02718 
02719       _dbus_string_init_const (&local_share, "/.local/share");
02720       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
02721         goto oom;
02722     }
02723 
02724   if (!split_paths_and_append (&servicedir_path, 
02725                                DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
02726                                dirs))
02727     goto oom;
02728 
02729   _dbus_string_free (&servicedir_path);  
02730   return TRUE;
02731 
02732  oom:
02733   _dbus_string_free (&servicedir_path);
02734   return FALSE;
02735 }
02736 
02737 /* tests in dbus-sysdeps-util.c */

Generated on Fri Sep 21 18:12:13 2007 for D-Bus by  doxygen 1.5.1