dbus-sysdeps-unix.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #define _GNU_SOURCE 
00026 
00027 #include "dbus-internals.h"
00028 #include "dbus-sysdeps.h"
00029 #include "dbus-sysdeps-unix.h"
00030 #include "dbus-threads.h"
00031 #include "dbus-protocol.h"
00032 #include "dbus-transport.h"
00033 #include "dbus-string.h"
00034 #include "dbus-userdb.h"
00035 #include "dbus-list.h"
00036 #include "dbus-credentials.h"
00037 
00038 #include <sys/types.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <signal.h>
00042 #include <unistd.h>
00043 #include <stdio.h>
00044 #include <fcntl.h>
00045 #include <sys/socket.h>
00046 #include <dirent.h>
00047 #include <sys/un.h>
00048 #include <pwd.h>
00049 #include <time.h>
00050 #include <locale.h>
00051 #include <sys/time.h>
00052 #include <sys/stat.h>
00053 #include <sys/wait.h>
00054 #include <netinet/in.h>
00055 #include <netdb.h>
00056 #include <grp.h>
00057 
00058 #ifdef HAVE_ERRNO_H
00059 #include <errno.h>
00060 #endif
00061 #ifdef HAVE_WRITEV
00062 #include <sys/uio.h>
00063 #endif
00064 #ifdef HAVE_POLL
00065 #include <sys/poll.h>
00066 #endif
00067 #ifdef HAVE_BACKTRACE
00068 #include <execinfo.h>
00069 #endif
00070 #ifdef HAVE_GETPEERUCRED
00071 #include <ucred.h>
00072 #endif
00073 
00074 #ifdef HAVE_ADT
00075 #include <bsm/adt.h>
00076 #endif
00077 
00078 #ifndef O_BINARY
00079 #define O_BINARY 0
00080 #endif
00081 
00082 #ifndef AI_ADDRCONFIG
00083 #define AI_ADDRCONFIG 0
00084 #endif
00085 
00086 #ifndef HAVE_SOCKLEN_T
00087 #define socklen_t int
00088 #endif
00089 
00090 static dbus_bool_t
00091 _dbus_open_socket (int              *fd_p,
00092                    int               domain,
00093                    int               type,
00094                    int               protocol,
00095                    DBusError        *error)
00096 {
00097   *fd_p = socket (domain, type, protocol);
00098   if (*fd_p >= 0)
00099     {
00100       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00101       return TRUE;
00102     }
00103   else
00104     {
00105       dbus_set_error(error,
00106                      _dbus_error_from_errno (errno),
00107                      "Failed to open socket: %s",
00108                      _dbus_strerror (errno));
00109       return FALSE;
00110     }
00111 }
00112 
00113 dbus_bool_t
00114 _dbus_open_tcp_socket (int              *fd,
00115                        DBusError        *error)
00116 {
00117   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00118 }
00119 
00127 dbus_bool_t
00128 _dbus_open_unix_socket (int              *fd,
00129                         DBusError        *error)
00130 {
00131   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00132 }
00133 
00142 dbus_bool_t 
00143 _dbus_close_socket (int               fd,
00144                     DBusError        *error)
00145 {
00146   return _dbus_close (fd, error);
00147 }
00148 
00158 int
00159 _dbus_read_socket (int               fd,
00160                    DBusString       *buffer,
00161                    int               count)
00162 {
00163   return _dbus_read (fd, buffer, count);
00164 }
00165 
00176 int
00177 _dbus_write_socket (int               fd,
00178                     const DBusString *buffer,
00179                     int               start,
00180                     int               len)
00181 {
00182   return _dbus_write (fd, buffer, start, len);
00183 }
00184 
00195 int
00196 _dbus_pipe_write (DBusPipe         *pipe,
00197                   const DBusString *buffer,
00198                   int               start,
00199                   int               len,
00200                   DBusError        *error)
00201 {
00202   int written;
00203   
00204   written = _dbus_write (pipe->fd_or_handle, buffer, start, len);
00205   if (written < 0)
00206     {
00207       dbus_set_error (error, DBUS_ERROR_FAILED,
00208                       "Writing to pipe: %s\n",
00209                       _dbus_strerror (errno));
00210     }
00211   return written;
00212 }
00213 
00221 int
00222 _dbus_pipe_close  (DBusPipe         *pipe,
00223                    DBusError        *error)
00224 {
00225   if (_dbus_close (pipe->fd_or_handle, error) < 0)
00226     {
00227       return -1;
00228     }
00229   else
00230     {
00231       _dbus_pipe_invalidate (pipe);
00232       return 0;
00233     }
00234 }
00235 
00249 int
00250 _dbus_write_socket_two (int               fd,
00251                         const DBusString *buffer1,
00252                         int               start1,
00253                         int               len1,
00254                         const DBusString *buffer2,
00255                         int               start2,
00256                         int               len2)
00257 {
00258   return _dbus_write_two (fd, buffer1, start1, len1,
00259                           buffer2, start2, len2);
00260 }
00261 
00262 
00279 int
00280 _dbus_read (int               fd,
00281             DBusString       *buffer,
00282             int               count)
00283 {
00284   int bytes_read;
00285   int start;
00286   char *data;
00287 
00288   _dbus_assert (count >= 0);
00289   
00290   start = _dbus_string_get_length (buffer);
00291 
00292   if (!_dbus_string_lengthen (buffer, count))
00293     {
00294       errno = ENOMEM;
00295       return -1;
00296     }
00297 
00298   data = _dbus_string_get_data_len (buffer, start, count);
00299 
00300  again:
00301   
00302   bytes_read = read (fd, data, count);
00303 
00304   if (bytes_read < 0)
00305     {
00306       if (errno == EINTR)
00307         goto again;
00308       else
00309         {
00310           /* put length back (note that this doesn't actually realloc anything) */
00311           _dbus_string_set_length (buffer, start);
00312           return -1;
00313         }
00314     }
00315   else
00316     {
00317       /* put length back (doesn't actually realloc) */
00318       _dbus_string_set_length (buffer, start + bytes_read);
00319 
00320 #if 0
00321       if (bytes_read > 0)
00322         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00323 #endif
00324       
00325       return bytes_read;
00326     }
00327 }
00328 
00339 int
00340 _dbus_write (int               fd,
00341              const DBusString *buffer,
00342              int               start,
00343              int               len)
00344 {
00345   const char *data;
00346   int bytes_written;
00347   
00348   data = _dbus_string_get_const_data_len (buffer, start, len);
00349   
00350  again:
00351 
00352   bytes_written = write (fd, data, len);
00353 
00354   if (bytes_written < 0 && errno == EINTR)
00355     goto again;
00356 
00357 #if 0
00358   if (bytes_written > 0)
00359     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00360 #endif
00361   
00362   return bytes_written;
00363 }
00364 
00385 int
00386 _dbus_write_two (int               fd,
00387                  const DBusString *buffer1,
00388                  int               start1,
00389                  int               len1,
00390                  const DBusString *buffer2,
00391                  int               start2,
00392                  int               len2)
00393 {
00394   _dbus_assert (buffer1 != NULL);
00395   _dbus_assert (start1 >= 0);
00396   _dbus_assert (start2 >= 0);
00397   _dbus_assert (len1 >= 0);
00398   _dbus_assert (len2 >= 0);
00399   
00400 #ifdef HAVE_WRITEV
00401   {
00402     struct iovec vectors[2];
00403     const char *data1;
00404     const char *data2;
00405     int bytes_written;
00406 
00407     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00408 
00409     if (buffer2 != NULL)
00410       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00411     else
00412       {
00413         data2 = NULL;
00414         start2 = 0;
00415         len2 = 0;
00416       }
00417    
00418     vectors[0].iov_base = (char*) data1;
00419     vectors[0].iov_len = len1;
00420     vectors[1].iov_base = (char*) data2;
00421     vectors[1].iov_len = len2;
00422 
00423   again:
00424    
00425     bytes_written = writev (fd,
00426                             vectors,
00427                             data2 ? 2 : 1);
00428 
00429     if (bytes_written < 0 && errno == EINTR)
00430       goto again;
00431    
00432     return bytes_written;
00433   }
00434 #else /* HAVE_WRITEV */
00435   {
00436     int ret1;
00437     
00438     ret1 = _dbus_write (fd, buffer1, start1, len1);
00439     if (ret1 == len1 && buffer2 != NULL)
00440       {
00441         ret2 = _dbus_write (fd, buffer2, start2, len2);
00442         if (ret2 < 0)
00443           ret2 = 0; /* we can't report an error as the first write was OK */
00444        
00445         return ret1 + ret2;
00446       }
00447     else
00448       return ret1;
00449   }
00450 #endif /* !HAVE_WRITEV */   
00451 }
00452 
00453 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00454 
00482 int
00483 _dbus_connect_unix_socket (const char     *path,
00484                            dbus_bool_t     abstract,
00485                            DBusError      *error)
00486 {
00487   int fd;
00488   size_t path_len;
00489   struct sockaddr_un addr;  
00490 
00491   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00492 
00493   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00494                  path, abstract);
00495   
00496   
00497   if (!_dbus_open_unix_socket (&fd, error))
00498     {
00499       _DBUS_ASSERT_ERROR_IS_SET(error);
00500       return -1;
00501     }
00502   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00503 
00504   _DBUS_ZERO (addr);
00505   addr.sun_family = AF_UNIX;
00506   path_len = strlen (path);
00507 
00508   if (abstract)
00509     {
00510 #ifdef HAVE_ABSTRACT_SOCKETS
00511       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00512       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00513 
00514       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00515         {
00516           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00517                       "Abstract socket name too long\n");
00518           _dbus_close (fd, NULL);
00519           return -1;
00520         }
00521         
00522       strncpy (&addr.sun_path[1], path, path_len);
00523       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00524 #else /* HAVE_ABSTRACT_SOCKETS */
00525       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00526                       "Operating system does not support abstract socket namespace\n");
00527       _dbus_close (fd, NULL);
00528       return -1;
00529 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00530     }
00531   else
00532     {
00533       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00534         {
00535           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00536                       "Socket name too long\n");
00537           _dbus_close (fd, NULL);
00538           return -1;
00539         }
00540 
00541       strncpy (addr.sun_path, path, path_len);
00542     }
00543   
00544   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00545     {      
00546       dbus_set_error (error,
00547                       _dbus_error_from_errno (errno),
00548                       "Failed to connect to socket %s: %s",
00549                       path, _dbus_strerror (errno));
00550 
00551       _dbus_close (fd, NULL);
00552       fd = -1;
00553       
00554       return -1;
00555     }
00556 
00557   if (!_dbus_set_fd_nonblocking (fd, error))
00558     {
00559       _DBUS_ASSERT_ERROR_IS_SET (error);
00560       
00561       _dbus_close (fd, NULL);
00562       fd = -1;
00563 
00564       return -1;
00565     }
00566 
00567   return fd;
00568 }
00569 
00579 static dbus_bool_t
00580 _dbus_set_local_creds (int fd, dbus_bool_t on)
00581 {
00582   dbus_bool_t retval = TRUE;
00583 
00584 #if defined(HAVE_CMSGCRED)
00585   /* NOOP just to make sure only one codepath is used 
00586    *      and to prefer CMSGCRED
00587    */
00588 #elif defined(LOCAL_CREDS) 
00589   int val = on ? 1 : 0;
00590   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00591     {
00592       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00593       retval = FALSE;
00594     }
00595   else
00596     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00597                    on ? "enabled" : "disabled", fd);
00598 #endif
00599 
00600   return retval;
00601 }
00602 
00618 int
00619 _dbus_listen_unix_socket (const char     *path,
00620                           dbus_bool_t     abstract,
00621                           DBusError      *error)
00622 {
00623   int listen_fd;
00624   struct sockaddr_un addr;
00625   size_t path_len;
00626 
00627   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00628 
00629   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00630                  path, abstract);
00631   
00632   if (!_dbus_open_unix_socket (&listen_fd, error))
00633     {
00634       _DBUS_ASSERT_ERROR_IS_SET(error);
00635       return -1;
00636     }
00637   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00638 
00639   _DBUS_ZERO (addr);
00640   addr.sun_family = AF_UNIX;
00641   path_len = strlen (path);
00642   
00643   if (abstract)
00644     {
00645 #ifdef HAVE_ABSTRACT_SOCKETS
00646       /* remember that abstract names aren't nul-terminated so we rely
00647        * on sun_path being filled in with zeroes above.
00648        */
00649       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00650       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00651 
00652       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00653         {
00654           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00655                       "Abstract socket name too long\n");
00656           _dbus_close (listen_fd, NULL);
00657           return -1;
00658         }
00659       
00660       strncpy (&addr.sun_path[1], path, path_len);
00661       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00662 #else /* HAVE_ABSTRACT_SOCKETS */
00663       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00664                       "Operating system does not support abstract socket namespace\n");
00665       _dbus_close (listen_fd, NULL);
00666       return -1;
00667 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00668     }
00669   else
00670     {
00671       /* Discussed security implications of this with Nalin,
00672        * and we couldn't think of where it would kick our ass, but
00673        * it still seems a bit sucky. It also has non-security suckage;
00674        * really we'd prefer to exit if the socket is already in use.
00675        * But there doesn't seem to be a good way to do this.
00676        *
00677        * Just to be extra careful, I threw in the stat() - clearly
00678        * the stat() can't *fix* any security issue, but it at least
00679        * avoids inadvertent/accidental data loss.
00680        */
00681       {
00682         struct stat sb;
00683 
00684         if (stat (path, &sb) == 0 &&
00685             S_ISSOCK (sb.st_mode))
00686           unlink (path);
00687       }
00688 
00689       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00690         {
00691           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00692                       "Abstract socket name too long\n");
00693           _dbus_close (listen_fd, NULL);
00694           return -1;
00695         }
00696         
00697       strncpy (addr.sun_path, path, path_len);
00698     }
00699   
00700   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00701     {
00702       dbus_set_error (error, _dbus_error_from_errno (errno),
00703                       "Failed to bind socket \"%s\": %s",
00704                       path, _dbus_strerror (errno));
00705       _dbus_close (listen_fd, NULL);
00706       return -1;
00707     }
00708 
00709   if (listen (listen_fd, 30 /* backlog */) < 0)
00710     {
00711       dbus_set_error (error, _dbus_error_from_errno (errno),
00712                       "Failed to listen on socket \"%s\": %s",
00713                       path, _dbus_strerror (errno));
00714       _dbus_close (listen_fd, NULL);
00715       return -1;
00716     }
00717 
00718   if (!_dbus_set_local_creds (listen_fd, TRUE))
00719     {
00720       dbus_set_error (error, _dbus_error_from_errno (errno),
00721                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00722                       path, _dbus_strerror (errno));
00723       close (listen_fd);
00724       return -1;
00725     }
00726 
00727   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00728     {
00729       _DBUS_ASSERT_ERROR_IS_SET (error);
00730       _dbus_close (listen_fd, NULL);
00731       return -1;
00732     }
00733   
00734   /* Try opening up the permissions, but if we can't, just go ahead
00735    * and continue, maybe it will be good enough.
00736    */
00737   if (!abstract && chmod (path, 0777) < 0)
00738     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00739                 path);
00740   
00741   return listen_fd;
00742 }
00743 
00755 int
00756 _dbus_connect_tcp_socket (const char     *host,
00757                           const char     *port,
00758                           const char     *family,
00759                           DBusError      *error)
00760 {
00761   int fd = -1, res;
00762   struct addrinfo hints;
00763   struct addrinfo *ai, *tmp;
00764 
00765   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00766 
00767   if (!_dbus_open_tcp_socket (&fd, error))
00768     {
00769       _DBUS_ASSERT_ERROR_IS_SET(error);
00770       return -1;
00771     }
00772 
00773   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00774 
00775   _DBUS_ZERO (hints);
00776 
00777   if (!family)
00778     hints.ai_family = AF_UNSPEC;
00779   else if (!strcmp(family, "ipv4"))
00780     hints.ai_family = AF_INET;
00781   else if (!strcmp(family, "ipv6"))
00782     hints.ai_family = AF_INET6;
00783   else
00784     {
00785       dbus_set_error (error,
00786                       _dbus_error_from_errno (errno),
00787                       "Unknown address family %s", family);
00788       return -1;
00789     }
00790   hints.ai_protocol = IPPROTO_TCP;
00791   hints.ai_socktype = SOCK_STREAM;
00792   hints.ai_flags = AI_ADDRCONFIG;
00793 
00794   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00795     {
00796       dbus_set_error (error,
00797                       _dbus_error_from_errno (errno),
00798                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00799                       host, port, gai_strerror(res), res);
00800       _dbus_close (fd, NULL);
00801       return -1;
00802     }
00803 
00804   tmp = ai;
00805   while (tmp)
00806     {
00807       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00808         {
00809           freeaddrinfo(ai);
00810           _DBUS_ASSERT_ERROR_IS_SET(error);
00811           return -1;
00812         }
00813       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00814 
00815       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00816         {
00817           _dbus_close(fd, NULL);
00818           fd = -1;
00819           tmp = tmp->ai_next;
00820           continue;
00821         }
00822 
00823       break;
00824     }
00825   freeaddrinfo(ai);
00826 
00827   if (fd == -1)
00828     {
00829       dbus_set_error (error,
00830                       _dbus_error_from_errno (errno),
00831                       "Failed to connect to socket \"%s:%s\" %s",
00832                       host, port, _dbus_strerror(errno));
00833       return -1;
00834     }
00835 
00836 
00837   if (!_dbus_set_fd_nonblocking (fd, error))
00838     {
00839       _dbus_close (fd, NULL);
00840       fd = -1;
00841 
00842       return -1;
00843     }
00844 
00845   return fd;
00846 }
00847 
00862 int
00863 _dbus_listen_tcp_socket (const char     *host,
00864                          const char     *port,
00865                          const char     *family,
00866                          DBusString     *retport,
00867                          int           **fds_p,
00868                          DBusError      *error)
00869 {
00870   int nlisten_fd = 0, *listen_fd = NULL, res, i;
00871   struct addrinfo hints;
00872   struct addrinfo *ai, *tmp;
00873 
00874   *fds_p = NULL;
00875   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00876 
00877   _DBUS_ZERO (hints);
00878 
00879   if (!family)
00880     hints.ai_family = AF_UNSPEC;
00881   else if (!strcmp(family, "ipv4"))
00882     hints.ai_family = AF_INET;
00883   else if (!strcmp(family, "ipv6"))
00884     hints.ai_family = AF_INET6;
00885   else
00886     {
00887       dbus_set_error (error,
00888                       _dbus_error_from_errno (errno),
00889                       "Unknown address family %s", family);
00890       return -1;
00891     }
00892 
00893   hints.ai_protocol = IPPROTO_TCP;
00894   hints.ai_socktype = SOCK_STREAM;
00895   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00896 
00897  redo_lookup_with_port:
00898   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00899     {
00900       dbus_set_error (error,
00901                       _dbus_error_from_errno (errno),
00902                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00903                       host ? host : "*", port, gai_strerror(res), res);
00904       return -1;
00905     }
00906 
00907   tmp = ai;
00908   while (tmp)
00909     {
00910       int fd = -1, *newlisten_fd;
00911       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00912         {
00913           _DBUS_ASSERT_ERROR_IS_SET(error);
00914           goto failed;
00915         }
00916       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00917 
00918       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00919         {
00920           _dbus_close(fd, NULL);
00921           if (errno == EADDRINUSE)
00922             {
00923               /* Depending on kernel policy, it may or may not
00924                  be neccessary to bind to both IPv4 & 6 addresses
00925                  so ignore EADDRINUSE here */
00926               tmp = tmp->ai_next;
00927               continue;
00928             }
00929           dbus_set_error (error, _dbus_error_from_errno (errno),
00930                           "Failed to bind socket \"%s:%s\": %s",
00931                           host ? host : "*", port, _dbus_strerror (errno));
00932           goto failed;
00933         }
00934 
00935       if (listen (fd, 30 /* backlog */) < 0)
00936         {
00937           _dbus_close (fd, NULL);
00938           dbus_set_error (error, _dbus_error_from_errno (errno),
00939                           "Failed to listen on socket \"%s:%s\": %s",
00940                           host ? host : "*", port, _dbus_strerror (errno));
00941           goto failed;
00942         }
00943 
00944       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00945       if (!newlisten_fd)
00946         {
00947           _dbus_close (fd, NULL);
00948           dbus_set_error (error, _dbus_error_from_errno (errno),
00949                           "Failed to allocate file handle array: %s",
00950                           _dbus_strerror (errno));
00951           goto failed;
00952         }
00953       listen_fd = newlisten_fd;
00954       listen_fd[nlisten_fd] = fd;
00955       nlisten_fd++;
00956 
00957       if (!_dbus_string_get_length(retport))
00958         {
00959           /* If the user didn't specify a port, or used 0, then
00960              the kernel chooses a port. After the first address
00961              is bound to, we need to force all remaining addresses
00962              to use the same port */
00963           if (!port || !strcmp(port, "0"))
00964             {
00965               struct sockaddr_storage addr;
00966               socklen_t addrlen;
00967               char portbuf[50];
00968 
00969               addrlen = sizeof(addr);
00970               getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00971 
00972               if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00973                                      portbuf, sizeof(portbuf),
00974                                      NI_NUMERICHOST)) != 0)
00975                 {
00976                   dbus_set_error (error, _dbus_error_from_errno (errno),
00977                                   "Failed to resolve port \"%s:%s\": %s (%s)",
00978                                   host ? host : "*", port, gai_strerror(res), res);
00979                   goto failed;
00980                 }
00981               if (!_dbus_string_append(retport, portbuf))
00982                 {
00983                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00984                   goto failed;
00985                 }
00986 
00987               /* Release current address list & redo lookup */
00988               port = _dbus_string_get_const_data(retport);
00989               freeaddrinfo(ai);
00990               goto redo_lookup_with_port;
00991             }
00992           else
00993             {
00994               if (!_dbus_string_append(retport, port))
00995                 {
00996                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00997                     goto failed;
00998                 }
00999             }
01000         }
01001 
01002       tmp = tmp->ai_next;
01003     }
01004   freeaddrinfo(ai);
01005   ai = NULL;
01006 
01007   if (!nlisten_fd)
01008     {
01009       errno = EADDRINUSE;
01010       dbus_set_error (error, _dbus_error_from_errno (errno),
01011                       "Failed to bind socket \"%s:%s\": %s",
01012                       host ? host : "*", port, _dbus_strerror (errno));
01013       return -1;
01014     }
01015 
01016   for (i = 0 ; i < nlisten_fd ; i++)
01017     {
01018       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01019         {
01020           goto failed;
01021         }
01022     }
01023 
01024   *fds_p = listen_fd;
01025 
01026   return nlisten_fd;
01027 
01028  failed:
01029   if (ai)
01030     freeaddrinfo(ai);
01031   for (i = 0 ; i < nlisten_fd ; i++)
01032     _dbus_close(listen_fd[i], NULL);
01033   dbus_free(listen_fd);
01034   return -1;
01035 }
01036 
01037 static dbus_bool_t
01038 write_credentials_byte (int             server_fd,
01039                         DBusError      *error)
01040 {
01041   int bytes_written;
01042   char buf[1] = { '\0' };
01043 #if defined(HAVE_CMSGCRED) 
01044   struct {
01045           struct cmsghdr hdr;
01046           struct cmsgcred cred;
01047   } cmsg;
01048   struct iovec iov;
01049   struct msghdr msg;
01050   iov.iov_base = buf;
01051   iov.iov_len = 1;
01052 
01053   memset (&msg, 0, sizeof (msg));
01054   msg.msg_iov = &iov;
01055   msg.msg_iovlen = 1;
01056 
01057   msg.msg_control = &cmsg;
01058   msg.msg_controllen = sizeof (cmsg);
01059   memset (&cmsg, 0, sizeof (cmsg));
01060   cmsg.hdr.cmsg_len = sizeof (cmsg);
01061   cmsg.hdr.cmsg_level = SOL_SOCKET;
01062   cmsg.hdr.cmsg_type = SCM_CREDS;
01063 #endif
01064 
01065   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01066   
01067  again:
01068 
01069 #if defined(HAVE_CMSGCRED) 
01070   bytes_written = sendmsg (server_fd, &msg, 0);
01071 #else
01072   bytes_written = write (server_fd, buf, 1);
01073 #endif
01074 
01075   if (bytes_written < 0 && errno == EINTR)
01076     goto again;
01077 
01078   if (bytes_written < 0)
01079     {
01080       dbus_set_error (error, _dbus_error_from_errno (errno),
01081                       "Failed to write credentials byte: %s",
01082                      _dbus_strerror (errno));
01083       return FALSE;
01084     }
01085   else if (bytes_written == 0)
01086     {
01087       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01088                       "wrote zero bytes writing credentials byte");
01089       return FALSE;
01090     }
01091   else
01092     {
01093       _dbus_assert (bytes_written == 1);
01094       _dbus_verbose ("wrote credentials byte\n");
01095       return TRUE;
01096     }
01097 }
01098 
01120 dbus_bool_t
01121 _dbus_read_credentials_socket  (int              client_fd,
01122                                 DBusCredentials *credentials,
01123                                 DBusError       *error)
01124 {
01125   struct msghdr msg;
01126   struct iovec iov;
01127   char buf;
01128   dbus_uid_t uid_read;
01129   dbus_pid_t pid_read;
01130   int bytes_read;
01131   
01132   uid_read = DBUS_UID_UNSET;
01133   pid_read = DBUS_PID_UNSET;
01134   
01135 #ifdef HAVE_CMSGCRED 
01136   struct {
01137     struct cmsghdr hdr;
01138     struct cmsgcred cred;
01139   } cmsg;
01140 
01141 #elif defined(LOCAL_CREDS)
01142   struct {
01143     struct cmsghdr hdr;
01144     struct sockcred cred;
01145   } cmsg;
01146 #endif
01147 
01148   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01149   
01150   /* The POSIX spec certainly doesn't promise this, but
01151    * we need these assertions to fail as soon as we're wrong about
01152    * it so we can do the porting fixups
01153    */
01154   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01155   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01156   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01157 
01158   _dbus_credentials_clear (credentials);
01159 
01160   /* Systems supporting LOCAL_CREDS are configured to have this feature
01161    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01162    * the connection.  Therefore, the received message must carry the
01163    * credentials information without doing anything special.
01164    */
01165 
01166   iov.iov_base = &buf;
01167   iov.iov_len = 1;
01168 
01169   memset (&msg, 0, sizeof (msg));
01170   msg.msg_iov = &iov;
01171   msg.msg_iovlen = 1;
01172 
01173 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01174   memset (&cmsg, 0, sizeof (cmsg));
01175   msg.msg_control = &cmsg;
01176   msg.msg_controllen = sizeof (cmsg);
01177 #endif
01178 
01179  again:
01180   bytes_read = recvmsg (client_fd, &msg, 0);
01181 
01182   if (bytes_read < 0)
01183     {
01184       if (errno == EINTR)
01185         goto again;
01186 
01187       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01188        * normally only call read_credentials if the socket was ready
01189        * for reading
01190        */
01191       
01192       dbus_set_error (error, _dbus_error_from_errno (errno),
01193                       "Failed to read credentials byte: %s",
01194                       _dbus_strerror (errno));
01195       return FALSE;
01196     }
01197   else if (bytes_read == 0)
01198     {
01199       /* this should not happen unless we are using recvmsg wrong,
01200        * so is essentially here for paranoia
01201        */
01202       dbus_set_error (error, DBUS_ERROR_FAILED,
01203                       "Failed to read credentials byte (zero-length read)");
01204       return FALSE;
01205     }
01206   else if (buf != '\0')
01207     {
01208       dbus_set_error (error, DBUS_ERROR_FAILED,
01209                       "Credentials byte was not nul");
01210       return FALSE;
01211     }
01212 
01213 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01214   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
01215     {
01216       dbus_set_error (error, DBUS_ERROR_FAILED,
01217                       "Message from recvmsg() was not SCM_CREDS");
01218       return FALSE;
01219     }
01220 #endif
01221 
01222   _dbus_verbose ("read credentials byte\n");
01223 
01224   {
01225 #ifdef SO_PEERCRED
01226     struct ucred cr;   
01227     int cr_len = sizeof (cr);
01228     
01229     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01230         cr_len == sizeof (cr))
01231       {
01232         pid_read = cr.pid;
01233         uid_read = cr.uid;
01234       }
01235     else
01236       {
01237         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01238                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01239       }
01240 #elif defined(HAVE_CMSGCRED)
01241     pid_read = cmsg.cred.cmcred_pid;
01242     uid_read = cmsg.cred.cmcred_euid;
01243 #elif defined(LOCAL_CREDS)
01244     pid_read = DBUS_PID_UNSET;
01245     uid_read = cmsg.cred.sc_uid;
01246     /* Since we have already got the credentials from this socket, we can
01247      * disable its LOCAL_CREDS flag if it was ever set. */
01248     _dbus_set_local_creds (client_fd, FALSE);
01249 #elif defined(HAVE_GETPEEREID)
01250     uid_t euid;
01251     gid_t egid;
01252     if (getpeereid (client_fd, &euid, &egid) == 0)
01253       {
01254         uid_read = euid;
01255       }
01256     else
01257       {
01258         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01259       }
01260 #elif defined(HAVE_GETPEERUCRED)
01261     ucred_t * ucred = NULL;
01262     if (getpeerucred (client_fd, &ucred) == 0)
01263       {
01264         pid_read = ucred_getpid (ucred);
01265         uid_read = ucred_geteuid (ucred);
01266 #ifdef HAVE_ADT
01267         /* generate audit session data based on socket ucred */
01268         adt_session_data_t *adth = NULL;
01269         adt_export_data_t *data = NULL;
01270         size_t size = 0;
01271         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01272           {
01273             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01274           }
01275         else 
01276           {
01277             if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 
01278               {
01279                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01280               }
01281             else
01282               {
01283                 size = adt_export_session_data (adth, &data);
01284                 if (size <= 0)
01285                   {
01286                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01287                   }
01288                 else
01289                   {
01290                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01291                     free (data);
01292                   }
01293               }
01294             (void) adt_end_session (adth);
01295           }
01296 #endif /* HAVE_ADT */
01297       }
01298     else
01299       {
01300         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01301       }
01302     if (ucred != NULL)
01303       ucred_free (ucred);
01304 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01305     _dbus_verbose ("Socket credentials not supported on this OS\n");
01306 #endif
01307   }
01308 
01309   _dbus_verbose ("Credentials:"
01310                  "  pid "DBUS_PID_FORMAT
01311                  "  uid "DBUS_UID_FORMAT
01312                  "\n",
01313                  pid_read,
01314                  uid_read);
01315 
01316   if (pid_read != DBUS_PID_UNSET)
01317     {
01318       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01319         {
01320           _DBUS_SET_OOM (error);
01321           return FALSE;
01322         }
01323     }
01324 
01325   if (uid_read != DBUS_UID_UNSET)
01326     {
01327       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01328         {
01329           _DBUS_SET_OOM (error);
01330           return FALSE;
01331         }
01332     }
01333   
01334   return TRUE;
01335 }
01336 
01354 dbus_bool_t
01355 _dbus_send_credentials_socket  (int              server_fd,
01356                                 DBusError       *error)
01357 {
01358   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01359   
01360   if (write_credentials_byte (server_fd, error))
01361     return TRUE;
01362   else
01363     return FALSE;
01364 }
01365 
01373 int
01374 _dbus_accept  (int listen_fd)
01375 {
01376   int client_fd;
01377   struct sockaddr addr;
01378   socklen_t addrlen;
01379 
01380   addrlen = sizeof (addr);
01381   
01382  retry:
01383   client_fd = accept (listen_fd, &addr, &addrlen);
01384   
01385   if (client_fd < 0)
01386     {
01387       if (errno == EINTR)
01388         goto retry;
01389     }
01390 
01391   _dbus_verbose ("client fd %d accepted\n", client_fd);
01392   
01393   return client_fd;
01394 }
01395 
01404 dbus_bool_t
01405 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01406 {
01407   const char *directory;
01408   struct stat sb;
01409         
01410   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01411     
01412   directory = _dbus_string_get_const_data (dir);
01413         
01414   if (stat (directory, &sb) < 0)
01415     {
01416       dbus_set_error (error, _dbus_error_from_errno (errno),
01417                       "%s", _dbus_strerror (errno));
01418    
01419       return FALSE;
01420     }
01421     
01422   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01423       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01424     {
01425       dbus_set_error (error, DBUS_ERROR_FAILED,
01426                      "%s directory is not private to the user", directory);
01427       return FALSE;
01428     }
01429     
01430   return TRUE;
01431 }
01432 
01433 static dbus_bool_t
01434 fill_user_info_from_passwd (struct passwd *p,
01435                             DBusUserInfo  *info,
01436                             DBusError     *error)
01437 {
01438   _dbus_assert (p->pw_name != NULL);
01439   _dbus_assert (p->pw_dir != NULL);
01440   
01441   info->uid = p->pw_uid;
01442   info->primary_gid = p->pw_gid;
01443   info->username = _dbus_strdup (p->pw_name);
01444   info->homedir = _dbus_strdup (p->pw_dir);
01445   
01446   if (info->username == NULL ||
01447       info->homedir == NULL)
01448     {
01449       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01450       return FALSE;
01451     }
01452 
01453   return TRUE;
01454 }
01455 
01456 static dbus_bool_t
01457 fill_user_info (DBusUserInfo       *info,
01458                 dbus_uid_t          uid,
01459                 const DBusString   *username,
01460                 DBusError          *error)
01461 {
01462   const char *username_c;
01463   
01464   /* exactly one of username/uid provided */
01465   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01466   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01467 
01468   info->uid = DBUS_UID_UNSET;
01469   info->primary_gid = DBUS_GID_UNSET;
01470   info->group_ids = NULL;
01471   info->n_group_ids = 0;
01472   info->username = NULL;
01473   info->homedir = NULL;
01474   
01475   if (username != NULL)
01476     username_c = _dbus_string_get_const_data (username);
01477   else
01478     username_c = NULL;
01479 
01480   /* For now assuming that the getpwnam() and getpwuid() flavors
01481    * are always symmetrical, if not we have to add more configure
01482    * checks
01483    */
01484   
01485 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01486   {
01487     struct passwd *p;
01488     int result;
01489     size_t buflen;
01490     char *buf;
01491     struct passwd p_str;
01492 
01493     /* retrieve maximum needed size for buf */
01494     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01495 
01496     /* sysconf actually returns a long, but everything else expects size_t,
01497      * so just recast here.
01498      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
01499      */
01500     if ((long) buflen <= 0)
01501       buflen = 1024;
01502 
01503     result = -1;
01504     while (1)
01505       {
01506         buf = dbus_malloc (buflen);
01507         if (buf == NULL)
01508           {
01509             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01510             return FALSE;
01511           }
01512 
01513         p = NULL;
01514 #ifdef HAVE_POSIX_GETPWNAM_R
01515         if (uid != DBUS_UID_UNSET)
01516           result = getpwuid_r (uid, &p_str, buf, buflen,
01517                                &p);
01518         else
01519           result = getpwnam_r (username_c, &p_str, buf, buflen,
01520                                &p);
01521 #else
01522         if (uid != DBUS_UID_UNSET)
01523           p = getpwuid_r (uid, &p_str, buf, buflen);
01524         else
01525           p = getpwnam_r (username_c, &p_str, buf, buflen);
01526         result = 0;
01527 #endif /* !HAVE_POSIX_GETPWNAM_R */
01528         //Try a bigger buffer if ERANGE was returned
01529         if (result == ERANGE && buflen < 512 * 1024)
01530           {
01531             dbus_free (buf);
01532             buflen *= 2;
01533           }
01534         else
01535           {
01536             break;
01537           }
01538       }
01539     if (result == 0 && p == &p_str)
01540       {
01541         if (!fill_user_info_from_passwd (p, info, error))
01542           {
01543             dbus_free (buf);
01544             return FALSE;
01545           }
01546         dbus_free (buf);
01547       }
01548     else
01549       {
01550         dbus_set_error (error, _dbus_error_from_errno (errno),
01551                         "User \"%s\" unknown or no memory to allocate password entry\n",
01552                         username_c ? username_c : "???");
01553         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01554         dbus_free (buf);
01555         return FALSE;
01556       }
01557   }
01558 #else /* ! HAVE_GETPWNAM_R */
01559   {
01560     /* I guess we're screwed on thread safety here */
01561     struct passwd *p;
01562 
01563     if (uid != DBUS_UID_UNSET)
01564       p = getpwuid (uid);
01565     else
01566       p = getpwnam (username_c);
01567 
01568     if (p != NULL)
01569       {
01570         if (!fill_user_info_from_passwd (p, info, error))
01571           {
01572             return FALSE;
01573           }
01574       }
01575     else
01576       {
01577         dbus_set_error (error, _dbus_error_from_errno (errno),
01578                         "User \"%s\" unknown or no memory to allocate password entry\n",
01579                         username_c ? username_c : "???");
01580         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01581         return FALSE;
01582       }
01583   }
01584 #endif  /* ! HAVE_GETPWNAM_R */
01585 
01586   /* Fill this in so we can use it to get groups */
01587   username_c = info->username;
01588   
01589 #ifdef HAVE_GETGROUPLIST
01590   {
01591     gid_t *buf;
01592     int buf_count;
01593     int i;
01594     
01595     buf_count = 17;
01596     buf = dbus_new (gid_t, buf_count);
01597     if (buf == NULL)
01598       {
01599         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01600         goto failed;
01601       }
01602     
01603     if (getgrouplist (username_c,
01604                       info->primary_gid,
01605                       buf, &buf_count) < 0)
01606       {
01607         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01608         if (new == NULL)
01609           {
01610             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01611             dbus_free (buf);
01612             goto failed;
01613           }
01614         
01615         buf = new;
01616 
01617         errno = 0;
01618         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01619           {
01620             dbus_set_error (error,
01621                             _dbus_error_from_errno (errno),
01622                             "Failed to get groups for username \"%s\" primary GID "
01623                             DBUS_GID_FORMAT ": %s\n",
01624                             username_c, info->primary_gid,
01625                             _dbus_strerror (errno));
01626             dbus_free (buf);
01627             goto failed;
01628           }
01629       }
01630 
01631     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01632     if (info->group_ids == NULL)
01633       {
01634         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01635         dbus_free (buf);
01636         goto failed;
01637       }
01638     
01639     for (i = 0; i < buf_count; ++i)
01640       info->group_ids[i] = buf[i];
01641 
01642     info->n_group_ids = buf_count;
01643     
01644     dbus_free (buf);
01645   }
01646 #else  /* HAVE_GETGROUPLIST */
01647   {
01648     /* We just get the one group ID */
01649     info->group_ids = dbus_new (dbus_gid_t, 1);
01650     if (info->group_ids == NULL)
01651       {
01652         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01653         goto failed;
01654       }
01655 
01656     info->n_group_ids = 1;
01657 
01658     (info->group_ids)[0] = info->primary_gid;
01659   }
01660 #endif /* HAVE_GETGROUPLIST */
01661 
01662   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01663   
01664   return TRUE;
01665   
01666  failed:
01667   _DBUS_ASSERT_ERROR_IS_SET (error);
01668   return FALSE;
01669 }
01670 
01679 dbus_bool_t
01680 _dbus_user_info_fill (DBusUserInfo     *info,
01681                       const DBusString *username,
01682                       DBusError        *error)
01683 {
01684   return fill_user_info (info, DBUS_UID_UNSET,
01685                          username, error);
01686 }
01687 
01696 dbus_bool_t
01697 _dbus_user_info_fill_uid (DBusUserInfo *info,
01698                           dbus_uid_t    uid,
01699                           DBusError    *error)
01700 {
01701   return fill_user_info (info, uid,
01702                          NULL, error);
01703 }
01704 
01712 dbus_bool_t
01713 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01714 {
01715   /* The POSIX spec certainly doesn't promise this, but
01716    * we need these assertions to fail as soon as we're wrong about
01717    * it so we can do the porting fixups
01718    */
01719   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01720   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01721   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01722 
01723   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01724     return FALSE;
01725   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01726     return FALSE;
01727 
01728   return TRUE;
01729 }
01730 
01742 dbus_bool_t
01743 _dbus_append_user_from_current_process (DBusString *str)
01744 {
01745   return _dbus_string_append_uint (str,
01746                                    _dbus_geteuid ());
01747 }
01748 
01753 dbus_pid_t
01754 _dbus_getpid (void)
01755 {
01756   return getpid ();
01757 }
01758 
01762 dbus_uid_t
01763 _dbus_getuid (void)
01764 {
01765   return getuid ();
01766 }
01767 
01771 dbus_uid_t
01772 _dbus_geteuid (void)
01773 {
01774   return geteuid ();
01775 }
01776 
01783 unsigned long
01784 _dbus_pid_for_log (void)
01785 {
01786   return getpid ();
01787 }
01788 
01796 dbus_bool_t
01797 _dbus_parse_uid (const DBusString      *uid_str,
01798                  dbus_uid_t            *uid)
01799 {
01800   int end;
01801   long val;
01802   
01803   if (_dbus_string_get_length (uid_str) == 0)
01804     {
01805       _dbus_verbose ("UID string was zero length\n");
01806       return FALSE;
01807     }
01808 
01809   val = -1;
01810   end = 0;
01811   if (!_dbus_string_parse_int (uid_str, 0, &val,
01812                                &end))
01813     {
01814       _dbus_verbose ("could not parse string as a UID\n");
01815       return FALSE;
01816     }
01817   
01818   if (end != _dbus_string_get_length (uid_str))
01819     {
01820       _dbus_verbose ("string contained trailing stuff after UID\n");
01821       return FALSE;
01822     }
01823 
01824   *uid = val;
01825 
01826   return TRUE;
01827 }
01828 
01829 
01830 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01831 
01832 #if DBUS_USE_ATOMIC_INT_486_COND
01833 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01834 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01835 static inline dbus_int32_t
01836 atomic_exchange_and_add (DBusAtomic            *atomic,
01837                          volatile dbus_int32_t  val)
01838 {
01839   register dbus_int32_t result;
01840 
01841   __asm__ __volatile__ ("lock; xaddl %0,%1"
01842                         : "=r" (result), "=m" (atomic->value)
01843                         : "0" (val), "m" (atomic->value));
01844   return result;
01845 }
01846 #endif
01847 
01856 dbus_int32_t
01857 _dbus_atomic_inc (DBusAtomic *atomic)
01858 {
01859 #if DBUS_USE_ATOMIC_INT_486_COND
01860   return atomic_exchange_and_add (atomic, 1);
01861 #else
01862   dbus_int32_t res;
01863   _DBUS_LOCK (atomic);
01864   res = atomic->value;
01865   atomic->value += 1;
01866   _DBUS_UNLOCK (atomic);
01867   return res;
01868 #endif
01869 }
01870 
01879 dbus_int32_t
01880 _dbus_atomic_dec (DBusAtomic *atomic)
01881 {
01882 #if DBUS_USE_ATOMIC_INT_486_COND
01883   return atomic_exchange_and_add (atomic, -1);
01884 #else
01885   dbus_int32_t res;
01886   
01887   _DBUS_LOCK (atomic);
01888   res = atomic->value;
01889   atomic->value -= 1;
01890   _DBUS_UNLOCK (atomic);
01891   return res;
01892 #endif
01893 }
01894 
01895 #ifdef DBUS_BUILD_TESTS
01896 
01899 dbus_gid_t
01900 _dbus_getgid (void)
01901 {
01902   return getgid ();
01903 }
01904 #endif
01905 
01914 int
01915 _dbus_poll (DBusPollFD *fds,
01916             int         n_fds,
01917             int         timeout_milliseconds)
01918 {
01919 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01920   /* This big thing is a constant expression and should get optimized
01921    * out of existence. So it's more robust than a configure check at
01922    * no cost.
01923    */
01924   if (_DBUS_POLLIN == POLLIN &&
01925       _DBUS_POLLPRI == POLLPRI &&
01926       _DBUS_POLLOUT == POLLOUT &&
01927       _DBUS_POLLERR == POLLERR &&
01928       _DBUS_POLLHUP == POLLHUP &&
01929       _DBUS_POLLNVAL == POLLNVAL &&
01930       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01931       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01932       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01933       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01934       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01935       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01936       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01937     {
01938       return poll ((struct pollfd*) fds,
01939                    n_fds, 
01940                    timeout_milliseconds);
01941     }
01942   else
01943     {
01944       /* We have to convert the DBusPollFD to an array of
01945        * struct pollfd, poll, and convert back.
01946        */
01947       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01948       return -1;
01949     }
01950 #else /* ! HAVE_POLL */
01951 
01952   fd_set read_set, write_set, err_set;
01953   int max_fd = 0;
01954   int i;
01955   struct timeval tv;
01956   int ready;
01957   
01958   FD_ZERO (&read_set);
01959   FD_ZERO (&write_set);
01960   FD_ZERO (&err_set);
01961 
01962   for (i = 0; i < n_fds; i++)
01963     {
01964       DBusPollFD *fdp = &fds[i];
01965 
01966       if (fdp->events & _DBUS_POLLIN)
01967         FD_SET (fdp->fd, &read_set);
01968 
01969       if (fdp->events & _DBUS_POLLOUT)
01970         FD_SET (fdp->fd, &write_set);
01971 
01972       FD_SET (fdp->fd, &err_set);
01973 
01974       max_fd = MAX (max_fd, fdp->fd);
01975     }
01976     
01977   tv.tv_sec = timeout_milliseconds / 1000;
01978   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01979 
01980   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01981                   timeout_milliseconds < 0 ? NULL : &tv);
01982 
01983   if (ready > 0)
01984     {
01985       for (i = 0; i < n_fds; i++)
01986         {
01987           DBusPollFD *fdp = &fds[i];
01988 
01989           fdp->revents = 0;
01990 
01991           if (FD_ISSET (fdp->fd, &read_set))
01992             fdp->revents |= _DBUS_POLLIN;
01993 
01994           if (FD_ISSET (fdp->fd, &write_set))
01995             fdp->revents |= _DBUS_POLLOUT;
01996 
01997           if (FD_ISSET (fdp->fd, &err_set))
01998             fdp->revents |= _DBUS_POLLERR;
01999         }
02000     }
02001 
02002   return ready;
02003 #endif
02004 }
02005 
02012 void
02013 _dbus_get_current_time (long *tv_sec,
02014                         long *tv_usec)
02015 {
02016   struct timeval t;
02017 
02018   gettimeofday (&t, NULL);
02019 
02020   if (tv_sec)
02021     *tv_sec = t.tv_sec;
02022   if (tv_usec)
02023     *tv_usec = t.tv_usec;
02024 }
02025 
02036 dbus_bool_t
02037 _dbus_file_get_contents (DBusString       *str,
02038                          const DBusString *filename,
02039                          DBusError        *error)
02040 {
02041   int fd;
02042   struct stat sb;
02043   int orig_len;
02044   int total;
02045   const char *filename_c;
02046 
02047   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02048   
02049   filename_c = _dbus_string_get_const_data (filename);
02050   
02051   /* O_BINARY useful on Cygwin */
02052   fd = open (filename_c, O_RDONLY | O_BINARY);
02053   if (fd < 0)
02054     {
02055       dbus_set_error (error, _dbus_error_from_errno (errno),
02056                       "Failed to open \"%s\": %s",
02057                       filename_c,
02058                       _dbus_strerror (errno));
02059       return FALSE;
02060     }
02061 
02062   _dbus_verbose ("file fd %d opened\n", fd);
02063   
02064   if (fstat (fd, &sb) < 0)
02065     {
02066       dbus_set_error (error, _dbus_error_from_errno (errno),
02067                       "Failed to stat \"%s\": %s",
02068                       filename_c,
02069                       _dbus_strerror (errno));
02070 
02071       _dbus_verbose ("fstat() failed: %s",
02072                      _dbus_strerror (errno));
02073       
02074       _dbus_close (fd, NULL);
02075       
02076       return FALSE;
02077     }
02078 
02079   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02080     {
02081       dbus_set_error (error, DBUS_ERROR_FAILED,
02082                       "File size %lu of \"%s\" is too large.",
02083                       (unsigned long) sb.st_size, filename_c);
02084       _dbus_close (fd, NULL);
02085       return FALSE;
02086     }
02087   
02088   total = 0;
02089   orig_len = _dbus_string_get_length (str);
02090   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02091     {
02092       int bytes_read;
02093 
02094       while (total < (int) sb.st_size)
02095         {
02096           bytes_read = _dbus_read (fd, str,
02097                                    sb.st_size - total);
02098           if (bytes_read <= 0)
02099             {
02100               dbus_set_error (error, _dbus_error_from_errno (errno),
02101                               "Error reading \"%s\": %s",
02102                               filename_c,
02103                               _dbus_strerror (errno));
02104 
02105               _dbus_verbose ("read() failed: %s",
02106                              _dbus_strerror (errno));
02107               
02108               _dbus_close (fd, NULL);
02109               _dbus_string_set_length (str, orig_len);
02110               return FALSE;
02111             }
02112           else
02113             total += bytes_read;
02114         }
02115 
02116       _dbus_close (fd, NULL);
02117       return TRUE;
02118     }
02119   else if (sb.st_size != 0)
02120     {
02121       _dbus_verbose ("Can only open regular files at the moment.\n");
02122       dbus_set_error (error, DBUS_ERROR_FAILED,
02123                       "\"%s\" is not a regular file",
02124                       filename_c);
02125       _dbus_close (fd, NULL);
02126       return FALSE;
02127     }
02128   else
02129     {
02130       _dbus_close (fd, NULL);
02131       return TRUE;
02132     }
02133 }
02134 
02144 dbus_bool_t
02145 _dbus_string_save_to_file (const DBusString *str,
02146                            const DBusString *filename,
02147                            DBusError        *error)
02148 {
02149   int fd;
02150   int bytes_to_write;
02151   const char *filename_c;
02152   DBusString tmp_filename;
02153   const char *tmp_filename_c;
02154   int total;
02155   dbus_bool_t need_unlink;
02156   dbus_bool_t retval;
02157 
02158   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02159   
02160   fd = -1;
02161   retval = FALSE;
02162   need_unlink = FALSE;
02163   
02164   if (!_dbus_string_init (&tmp_filename))
02165     {
02166       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02167       return FALSE;
02168     }
02169 
02170   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02171     {
02172       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02173       _dbus_string_free (&tmp_filename);
02174       return FALSE;
02175     }
02176   
02177   if (!_dbus_string_append (&tmp_filename, "."))
02178     {
02179       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02180       _dbus_string_free (&tmp_filename);
02181       return FALSE;
02182     }
02183 
02184 #define N_TMP_FILENAME_RANDOM_BYTES 8
02185   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02186     {
02187       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02188       _dbus_string_free (&tmp_filename);
02189       return FALSE;
02190     }
02191     
02192   filename_c = _dbus_string_get_const_data (filename);
02193   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02194 
02195   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02196              0600);
02197   if (fd < 0)
02198     {
02199       dbus_set_error (error, _dbus_error_from_errno (errno),
02200                       "Could not create %s: %s", tmp_filename_c,
02201                       _dbus_strerror (errno));
02202       goto out;
02203     }
02204 
02205   _dbus_verbose ("tmp file fd %d opened\n", fd);
02206   
02207   need_unlink = TRUE;
02208   
02209   total = 0;
02210   bytes_to_write = _dbus_string_get_length (str);
02211 
02212   while (total < bytes_to_write)
02213     {
02214       int bytes_written;
02215 
02216       bytes_written = _dbus_write (fd, str, total,
02217                                    bytes_to_write - total);
02218 
02219       if (bytes_written <= 0)
02220         {
02221           dbus_set_error (error, _dbus_error_from_errno (errno),
02222                           "Could not write to %s: %s", tmp_filename_c,
02223                           _dbus_strerror (errno));
02224           
02225           goto out;
02226         }
02227 
02228       total += bytes_written;
02229     }
02230 
02231   if (fsync(fd))
02232     {
02233       dbus_set_error (error, _dbus_error_from_errno (errno),
02234                       "Could not synchronize file %s: %s",
02235                       tmp_filename_c, _dbus_strerror (errno));
02236 
02237       goto out;
02238   }
02239 
02240   if (!_dbus_close (fd, NULL))
02241     {
02242       dbus_set_error (error, _dbus_error_from_errno (errno),
02243                       "Could not close file %s: %s",
02244                       tmp_filename_c, _dbus_strerror (errno));
02245 
02246       goto out;
02247     }
02248 
02249   fd = -1;
02250   
02251   if (rename (tmp_filename_c, filename_c) < 0)
02252     {
02253       dbus_set_error (error, _dbus_error_from_errno (errno),
02254                       "Could not rename %s to %s: %s",
02255                       tmp_filename_c, filename_c,
02256                       _dbus_strerror (errno));
02257 
02258       goto out;
02259     }
02260 
02261   need_unlink = FALSE;
02262   
02263   retval = TRUE;
02264   
02265  out:
02266   /* close first, then unlink, to prevent ".nfs34234235" garbage
02267    * files
02268    */
02269 
02270   if (fd >= 0)
02271     _dbus_close (fd, NULL);
02272         
02273   if (need_unlink && unlink (tmp_filename_c) < 0)
02274     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02275                    tmp_filename_c, _dbus_strerror (errno));
02276 
02277   _dbus_string_free (&tmp_filename);
02278 
02279   if (!retval)
02280     _DBUS_ASSERT_ERROR_IS_SET (error);
02281   
02282   return retval;
02283 }
02284 
02291 dbus_bool_t
02292 _dbus_make_file_world_readable(const DBusString *filename,
02293                                DBusError *error)
02294 {
02295   const char *filename_c;
02296 
02297   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02298 
02299   filename_c = _dbus_string_get_const_data (filename);
02300   if (chmod (filename_c, 0644) == -1)
02301     {
02302       dbus_set_error (error,
02303                       DBUS_ERROR_FAILED,
02304                       "Could not change permissions of file %s: %s\n",
02305                       filename_c,
02306                       _dbus_strerror (errno));
02307       return FALSE;
02308     }
02309   return TRUE;
02310 }
02311 
02318 dbus_bool_t
02319 _dbus_create_file_exclusively (const DBusString *filename,
02320                                DBusError        *error)
02321 {
02322   int fd;
02323   const char *filename_c;
02324 
02325   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02326   
02327   filename_c = _dbus_string_get_const_data (filename);
02328   
02329   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02330              0600);
02331   if (fd < 0)
02332     {
02333       dbus_set_error (error,
02334                       DBUS_ERROR_FAILED,
02335                       "Could not create file %s: %s\n",
02336                       filename_c,
02337                       _dbus_strerror (errno));
02338       return FALSE;
02339     }
02340 
02341   _dbus_verbose ("exclusive file fd %d opened\n", fd);
02342   
02343   if (!_dbus_close (fd, NULL))
02344     {
02345       dbus_set_error (error,
02346                       DBUS_ERROR_FAILED,
02347                       "Could not close file %s: %s\n",
02348                       filename_c,
02349                       _dbus_strerror (errno));
02350       return FALSE;
02351     }
02352   
02353   return TRUE;
02354 }
02355 
02364 dbus_bool_t
02365 _dbus_delete_file (const DBusString *filename,
02366                    DBusError        *error)
02367 {
02368   const char *filename_c;
02369 
02370   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02371   
02372   filename_c = _dbus_string_get_const_data (filename);
02373 
02374   if (unlink (filename_c) < 0)
02375     {
02376       dbus_set_error (error, DBUS_ERROR_FAILED,
02377                       "Failed to delete file %s: %s\n",
02378                       filename_c, _dbus_strerror (errno));
02379       return FALSE;
02380     }
02381   else
02382     return TRUE;
02383 }
02384 
02393 dbus_bool_t
02394 _dbus_create_directory (const DBusString *filename,
02395                         DBusError        *error)
02396 {
02397   const char *filename_c;
02398 
02399   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02400   
02401   filename_c = _dbus_string_get_const_data (filename);
02402 
02403   if (mkdir (filename_c, 0700) < 0)
02404     {
02405       if (errno == EEXIST)
02406         return TRUE;
02407       
02408       dbus_set_error (error, DBUS_ERROR_FAILED,
02409                       "Failed to create directory %s: %s\n",
02410                       filename_c, _dbus_strerror (errno));
02411       return FALSE;
02412     }
02413   else
02414     return TRUE;
02415 }
02416 
02427 dbus_bool_t
02428 _dbus_concat_dir_and_file (DBusString       *dir,
02429                            const DBusString *next_component)
02430 {
02431   dbus_bool_t dir_ends_in_slash;
02432   dbus_bool_t file_starts_with_slash;
02433 
02434   if (_dbus_string_get_length (dir) == 0 ||
02435       _dbus_string_get_length (next_component) == 0)
02436     return TRUE;
02437   
02438   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02439                                                     _dbus_string_get_length (dir) - 1);
02440 
02441   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02442 
02443   if (dir_ends_in_slash && file_starts_with_slash)
02444     {
02445       _dbus_string_shorten (dir, 1);
02446     }
02447   else if (!(dir_ends_in_slash || file_starts_with_slash))
02448     {
02449       if (!_dbus_string_append_byte (dir, '/'))
02450         return FALSE;
02451     }
02452 
02453   return _dbus_string_copy (next_component, 0, dir,
02454                             _dbus_string_get_length (dir));
02455 }
02456 
02458 #define NANOSECONDS_PER_SECOND       1000000000
02459 
02460 #define MICROSECONDS_PER_SECOND      1000000
02461 
02462 #define MILLISECONDS_PER_SECOND      1000
02463 
02464 #define NANOSECONDS_PER_MILLISECOND  1000000
02465 
02466 #define MICROSECONDS_PER_MILLISECOND 1000
02467 
02472 void
02473 _dbus_sleep_milliseconds (int milliseconds)
02474 {
02475 #ifdef HAVE_NANOSLEEP
02476   struct timespec req;
02477   struct timespec rem;
02478 
02479   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02480   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02481   rem.tv_sec = 0;
02482   rem.tv_nsec = 0;
02483 
02484   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02485     req = rem;
02486 #elif defined (HAVE_USLEEP)
02487   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02488 #else /* ! HAVE_USLEEP */
02489   sleep (MAX (milliseconds / 1000, 1));
02490 #endif
02491 }
02492 
02493 static dbus_bool_t
02494 _dbus_generate_pseudorandom_bytes (DBusString *str,
02495                                    int         n_bytes)
02496 {
02497   int old_len;
02498   char *p;
02499   
02500   old_len = _dbus_string_get_length (str);
02501 
02502   if (!_dbus_string_lengthen (str, n_bytes))
02503     return FALSE;
02504 
02505   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02506 
02507   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02508 
02509   return TRUE;
02510 }
02511 
02520 dbus_bool_t
02521 _dbus_generate_random_bytes (DBusString *str,
02522                              int         n_bytes)
02523 {
02524   int old_len;
02525   int fd;
02526 
02527   /* FALSE return means "no memory", if it could
02528    * mean something else then we'd need to return
02529    * a DBusError. So we always fall back to pseudorandom
02530    * if the I/O fails.
02531    */
02532   
02533   old_len = _dbus_string_get_length (str);
02534   fd = -1;
02535 
02536   /* note, urandom on linux will fall back to pseudorandom */
02537   fd = open ("/dev/urandom", O_RDONLY);
02538   if (fd < 0)
02539     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02540 
02541   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02542   
02543   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02544     {
02545       _dbus_close (fd, NULL);
02546       _dbus_string_set_length (str, old_len);
02547       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02548     }
02549 
02550   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02551                  n_bytes);
02552   
02553   _dbus_close (fd, NULL);
02554   
02555   return TRUE;
02556 }
02557 
02563 void
02564 _dbus_exit (int code)
02565 {
02566   _exit (code);
02567 }
02568 
02577 const char*
02578 _dbus_strerror (int error_number)
02579 {
02580   const char *msg;
02581   
02582   msg = strerror (error_number);
02583   if (msg == NULL)
02584     msg = "unknown";
02585 
02586   return msg;
02587 }
02588 
02592 void
02593 _dbus_disable_sigpipe (void)
02594 {
02595   signal (SIGPIPE, SIG_IGN);
02596 }
02597 
02605 void
02606 _dbus_fd_set_close_on_exec (int fd)
02607 {
02608   int val;
02609   
02610   val = fcntl (fd, F_GETFD, 0);
02611   
02612   if (val < 0)
02613     return;
02614 
02615   val |= FD_CLOEXEC;
02616   
02617   fcntl (fd, F_SETFD, val);
02618 }
02619 
02627 dbus_bool_t
02628 _dbus_close (int        fd,
02629              DBusError *error)
02630 {
02631   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02632   
02633  again:
02634   if (close (fd) < 0)
02635     {
02636       if (errno == EINTR)
02637         goto again;
02638 
02639       dbus_set_error (error, _dbus_error_from_errno (errno),
02640                       "Could not close fd %d", fd);
02641       return FALSE;
02642     }
02643 
02644   return TRUE;
02645 }
02646 
02654 dbus_bool_t
02655 _dbus_set_fd_nonblocking (int             fd,
02656                           DBusError      *error)
02657 {
02658   int val;
02659 
02660   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02661   
02662   val = fcntl (fd, F_GETFL, 0);
02663   if (val < 0)
02664     {
02665       dbus_set_error (error, _dbus_error_from_errno (errno),
02666                       "Failed to get flags from file descriptor %d: %s",
02667                       fd, _dbus_strerror (errno));
02668       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02669                      _dbus_strerror (errno));
02670       return FALSE;
02671     }
02672 
02673   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02674     {
02675       dbus_set_error (error, _dbus_error_from_errno (errno),
02676                       "Failed to set nonblocking flag of file descriptor %d: %s",
02677                       fd, _dbus_strerror (errno));
02678       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02679                      fd, _dbus_strerror (errno));
02680 
02681       return FALSE;
02682     }
02683 
02684   return TRUE;
02685 }
02686 
02692 void
02693 _dbus_print_backtrace (void)
02694 {  
02695 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02696   void *bt[500];
02697   int bt_size;
02698   int i;
02699   char **syms;
02700   
02701   bt_size = backtrace (bt, 500);
02702 
02703   syms = backtrace_symbols (bt, bt_size);
02704   
02705   i = 0;
02706   while (i < bt_size)
02707     {
02708       /* don't use dbus_warn since it can _dbus_abort() */
02709       fprintf (stderr, "  %s\n", syms[i]);
02710       ++i;
02711     }
02712   fflush (stderr);
02713 
02714   free (syms);
02715 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02716   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02717 #else
02718   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02719 #endif
02720 }
02721 
02737 dbus_bool_t
02738 _dbus_full_duplex_pipe (int        *fd1,
02739                         int        *fd2,
02740                         dbus_bool_t blocking,
02741                         DBusError  *error)
02742 {
02743 #ifdef HAVE_SOCKETPAIR
02744   int fds[2];
02745 
02746   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02747   
02748   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02749     {
02750       dbus_set_error (error, _dbus_error_from_errno (errno),
02751                       "Could not create full-duplex pipe");
02752       return FALSE;
02753     }
02754 
02755   if (!blocking &&
02756       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02757        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02758     {
02759       dbus_set_error (error, _dbus_error_from_errno (errno),
02760                       "Could not set full-duplex pipe nonblocking");
02761       
02762       _dbus_close (fds[0], NULL);
02763       _dbus_close (fds[1], NULL);
02764       
02765       return FALSE;
02766     }
02767   
02768   *fd1 = fds[0];
02769   *fd2 = fds[1];
02770 
02771   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02772                  *fd1, *fd2);
02773   
02774   return TRUE;  
02775 #else
02776   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02777   dbus_set_error (error, DBUS_ERROR_FAILED,
02778                   "_dbus_full_duplex_pipe() not implemented on this OS");
02779   return FALSE;
02780 #endif
02781 }
02782 
02791 int
02792 _dbus_printf_string_upper_bound (const char *format,
02793                                  va_list     args)
02794 {
02795   char c;
02796   return vsnprintf (&c, 1, format, args);
02797 }
02798 
02805 const char*
02806 _dbus_get_tmpdir(void)
02807 {
02808   static const char* tmpdir = NULL;
02809 
02810   if (tmpdir == NULL)
02811     {
02812       /* TMPDIR is what glibc uses, then
02813        * glibc falls back to the P_tmpdir macro which
02814        * just expands to "/tmp"
02815        */
02816       if (tmpdir == NULL)
02817         tmpdir = getenv("TMPDIR");
02818 
02819       /* These two env variables are probably
02820        * broken, but maybe some OS uses them?
02821        */
02822       if (tmpdir == NULL)
02823         tmpdir = getenv("TMP");
02824       if (tmpdir == NULL)
02825         tmpdir = getenv("TEMP");
02826 
02827       /* And this is the sane fallback. */
02828       if (tmpdir == NULL)
02829         tmpdir = "/tmp";
02830     }
02831   
02832   _dbus_assert(tmpdir != NULL);
02833   
02834   return tmpdir;
02835 }
02836 
02849 dbus_bool_t
02850 _dbus_get_autolaunch_address (DBusString *address,
02851                               DBusError  *error)
02852 {
02853   static char *argv[6];
02854   int address_pipe[2] = { -1, -1 };
02855   int errors_pipe[2] = { -1, -1 };
02856   pid_t pid;
02857   int ret;
02858   int status;
02859   int orig_len;
02860   int i;
02861   DBusString uuid;
02862   dbus_bool_t retval;
02863   
02864   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02865   retval = FALSE;
02866 
02867   if (!_dbus_string_init (&uuid))
02868     {
02869       _DBUS_SET_OOM (error);
02870       return FALSE;
02871     }
02872   
02873   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02874     {
02875       _DBUS_SET_OOM (error);
02876       goto out;
02877     }
02878   
02879   i = 0;
02880   argv[i] = "dbus-launch";
02881   ++i;
02882   argv[i] = "--autolaunch";
02883   ++i;
02884   argv[i] = _dbus_string_get_data (&uuid);
02885   ++i;
02886   argv[i] = "--binary-syntax";
02887   ++i;
02888   argv[i] = "--close-stderr";
02889   ++i;
02890   argv[i] = NULL;
02891   ++i;
02892 
02893   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02894   
02895   orig_len = _dbus_string_get_length (address);
02896   
02897 #define READ_END        0
02898 #define WRITE_END       1
02899   if (pipe (address_pipe) < 0)
02900     {
02901       dbus_set_error (error, _dbus_error_from_errno (errno),
02902                       "Failed to create a pipe: %s",
02903                       _dbus_strerror (errno));
02904       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02905                      _dbus_strerror (errno));
02906       goto out;
02907     }
02908   if (pipe (errors_pipe) < 0)
02909     {
02910       dbus_set_error (error, _dbus_error_from_errno (errno),
02911                       "Failed to create a pipe: %s",
02912                       _dbus_strerror (errno));
02913       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02914                      _dbus_strerror (errno));
02915       goto out;
02916     }
02917 
02918   pid = fork ();
02919   if (pid < 0)
02920     {
02921       dbus_set_error (error, _dbus_error_from_errno (errno),
02922                       "Failed to fork(): %s",
02923                       _dbus_strerror (errno));
02924       _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02925                      _dbus_strerror (errno));
02926       goto out;
02927     }
02928 
02929   if (pid == 0)
02930     {
02931       /* child process */
02932       int maxfds;
02933       int fd;
02934 
02935       fd = open ("/dev/null", O_RDWR);
02936       if (fd == -1)
02937         /* huh?! can't open /dev/null? */
02938         _exit (1);
02939 
02940       _dbus_verbose ("/dev/null fd %d opened\n", fd);
02941       
02942       /* set-up stdXXX */
02943       close (address_pipe[READ_END]);
02944       close (errors_pipe[READ_END]);
02945       close (0);                /* close stdin */
02946       close (1);                /* close stdout */
02947       close (2);                /* close stderr */
02948 
02949       if (dup2 (fd, 0) == -1)
02950         _exit (1);
02951       if (dup2 (address_pipe[WRITE_END], 1) == -1)
02952         _exit (1);
02953       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02954         _exit (1);
02955 
02956       maxfds = sysconf (_SC_OPEN_MAX);
02957       /* Pick something reasonable if for some reason sysconf
02958        * says unlimited.
02959        */
02960       if (maxfds < 0)
02961         maxfds = 1024;
02962       /* close all inherited fds */
02963       for (i = 3; i < maxfds; i++)
02964         close (i);
02965 
02966       execv (DBUS_BINDIR "/dbus-launch", argv);
02967 
02968       /* failed, try searching PATH */
02969       execvp ("dbus-launch", argv);
02970 
02971       /* still nothing, we failed */
02972       _exit (1);
02973     }
02974 
02975   /* parent process */
02976   close (address_pipe[WRITE_END]);
02977   close (errors_pipe[WRITE_END]);
02978   address_pipe[WRITE_END] = -1;
02979   errors_pipe[WRITE_END] = -1;
02980 
02981   ret = 0;
02982   do 
02983     {
02984       ret = _dbus_read (address_pipe[READ_END], address, 1024);
02985     }
02986   while (ret > 0);
02987 
02988   /* reap the child process to avoid it lingering as zombie */
02989   do
02990     {
02991       ret = waitpid (pid, &status, 0);
02992     }
02993   while (ret == -1 && errno == EINTR);
02994 
02995   /* We succeeded if the process exited with status 0 and
02996      anything was read */
02997   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02998       _dbus_string_get_length (address) == orig_len)
02999     {
03000       /* The process ended with error */
03001       DBusString error_message;
03002       _dbus_string_init (&error_message);
03003       ret = 0;
03004       do
03005         {
03006           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03007         }
03008       while (ret > 0);
03009 
03010       _dbus_string_set_length (address, orig_len);
03011       if (_dbus_string_get_length (&error_message) > 0)
03012         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03013                         "dbus-launch failed to autolaunch D-Bus session: %s",
03014                         _dbus_string_get_data (&error_message));
03015       else
03016         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03017                         "Failed to execute dbus-launch to autolaunch D-Bus session");
03018       goto out;
03019     }
03020 
03021   retval = TRUE;
03022   
03023  out:
03024   if (retval)
03025     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03026   else
03027     _DBUS_ASSERT_ERROR_IS_SET (error);
03028 
03029   if (address_pipe[0] != -1)
03030     close (address_pipe[0]);
03031   if (address_pipe[1] != -1)
03032     close (address_pipe[1]);
03033   if (errors_pipe[0] != -1)
03034     close (errors_pipe[0]);
03035   if (errors_pipe[1] != -1)
03036     close (errors_pipe[1]);
03037 
03038   _dbus_string_free (&uuid);
03039   return retval;
03040 }
03041 
03060 dbus_bool_t
03061 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03062                                dbus_bool_t create_if_not_found,
03063                                DBusError  *error)
03064 {
03065   DBusString filename;
03066   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03067   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03068 }
03069 
03070 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03071 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03072 
03073 
03091 dbus_bool_t 
03092 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03093 {
03094   const char *xdg_data_home;
03095   const char *xdg_data_dirs;
03096   DBusString servicedir_path;
03097 
03098   if (!_dbus_string_init (&servicedir_path))
03099     return FALSE;
03100 
03101   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03102   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03103 
03104   if (xdg_data_dirs != NULL)
03105     {
03106       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03107         goto oom;
03108 
03109       if (!_dbus_string_append (&servicedir_path, ":"))
03110         goto oom;
03111     }
03112   else
03113     {
03114       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03115         goto oom;
03116     }
03117 
03118   /* 
03119    * add configured datadir to defaults
03120    * this may be the same as an xdg dir
03121    * however the config parser should take 
03122    * care of duplicates 
03123    */
03124   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03125         goto oom;
03126 
03127   if (xdg_data_home != NULL)
03128     {
03129       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03130         goto oom;
03131     }
03132   else
03133     {
03134       const DBusString *homedir;
03135       DBusString local_share;
03136 
03137       if (!_dbus_homedir_from_current_process (&homedir))
03138         goto oom;
03139        
03140       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03141         goto oom;
03142 
03143       _dbus_string_init_const (&local_share, "/.local/share");
03144       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03145         goto oom;
03146     }
03147 
03148   if (!_dbus_split_paths_and_append (&servicedir_path, 
03149                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
03150                                      dirs))
03151     goto oom;
03152 
03153   _dbus_string_free (&servicedir_path);  
03154   return TRUE;
03155 
03156  oom:
03157   _dbus_string_free (&servicedir_path);
03158   return FALSE;
03159 }
03160 
03161 
03180 dbus_bool_t 
03181 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03182 {
03183   const char *xdg_data_dirs;
03184   DBusString servicedir_path;
03185 
03186   if (!_dbus_string_init (&servicedir_path))
03187     return FALSE;
03188 
03189   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03190 
03191   if (xdg_data_dirs != NULL)
03192     {
03193       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03194         goto oom;
03195 
03196       if (!_dbus_string_append (&servicedir_path, ":"))
03197         goto oom;
03198     }
03199   else
03200     {
03201       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03202         goto oom;
03203     }
03204 
03205   /* 
03206    * add configured datadir to defaults
03207    * this may be the same as an xdg dir
03208    * however the config parser should take 
03209    * care of duplicates 
03210    */
03211   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03212         goto oom;
03213 
03214   if (!_dbus_split_paths_and_append (&servicedir_path, 
03215                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 
03216                                      dirs))
03217     goto oom;
03218 
03219   _dbus_string_free (&servicedir_path);  
03220   return TRUE;
03221 
03222  oom:
03223   _dbus_string_free (&servicedir_path);
03224   return FALSE;
03225 }
03226 
03235 dbus_bool_t
03236 _dbus_append_system_config_file (DBusString *str)
03237 {
03238   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03239 }
03240 
03247 dbus_bool_t
03248 _dbus_append_session_config_file (DBusString *str)
03249 {
03250   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03251 }
03252 
03260 void
03261 _dbus_flush_caches (void)
03262 {
03263   _dbus_user_database_flush_system ();
03264 }
03265 
03279 dbus_bool_t
03280 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03281                                                 DBusCredentials *credentials)
03282 {
03283   DBusString homedir;
03284   DBusString dotdir;
03285   dbus_uid_t uid;
03286   
03287   _dbus_assert (credentials != NULL);
03288   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03289   
03290   if (!_dbus_string_init (&homedir))
03291     return FALSE;
03292 
03293   uid = _dbus_credentials_get_unix_uid (credentials);
03294   _dbus_assert (uid != DBUS_UID_UNSET);
03295 
03296   if (!_dbus_homedir_from_uid (uid, &homedir))
03297     goto failed;
03298   
03299 #ifdef DBUS_BUILD_TESTS
03300   {
03301     const char *override;
03302     
03303     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03304     if (override != NULL && *override != '\0')
03305       {
03306         _dbus_string_set_length (&homedir, 0);
03307         if (!_dbus_string_append (&homedir, override))
03308           goto failed;
03309 
03310         _dbus_verbose ("Using fake homedir for testing: %s\n",
03311                        _dbus_string_get_const_data (&homedir));
03312       }
03313     else
03314       {
03315         static dbus_bool_t already_warned = FALSE;
03316         if (!already_warned)
03317           {
03318             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03319             already_warned = TRUE;
03320           }
03321       }
03322   }
03323 #endif
03324 
03325   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03326   if (!_dbus_concat_dir_and_file (&homedir,
03327                                   &dotdir))
03328     goto failed;
03329   
03330   if (!_dbus_string_copy (&homedir, 0,
03331                           directory, _dbus_string_get_length (directory))) {
03332     goto failed;
03333   }
03334 
03335   _dbus_string_free (&homedir);
03336   return TRUE;
03337   
03338  failed: 
03339   _dbus_string_free (&homedir);
03340   return FALSE;
03341 }
03342 
03343 
03350 dbus_bool_t
03351 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03352 {
03353   return errno == EAGAIN || errno == EWOULDBLOCK;
03354 }
03355 
03356 /* tests in dbus-sysdeps-util.c */

Generated on Tue Feb 24 16:40:40 2009 for D-Bus by  doxygen 1.5.1