D-Bus  1.6.30
dbus-sysdeps-unix.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
00003  *
00004  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
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 #include "dbus-nonce.h"
00038 
00039 #include <sys/types.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <signal.h>
00043 #include <unistd.h>
00044 #include <stdio.h>
00045 #include <fcntl.h>
00046 #include <sys/socket.h>
00047 #include <dirent.h>
00048 #include <sys/un.h>
00049 #include <pwd.h>
00050 #include <time.h>
00051 #include <locale.h>
00052 #include <sys/time.h>
00053 #include <sys/stat.h>
00054 #include <sys/wait.h>
00055 #include <netinet/in.h>
00056 #include <netdb.h>
00057 #include <grp.h>
00058 
00059 #ifdef HAVE_ERRNO_H
00060 #include <errno.h>
00061 #endif
00062 #ifdef HAVE_WRITEV
00063 #include <sys/uio.h>
00064 #endif
00065 #ifdef HAVE_POLL
00066 #include <sys/poll.h>
00067 #endif
00068 #ifdef HAVE_BACKTRACE
00069 #include <execinfo.h>
00070 #endif
00071 #ifdef HAVE_GETPEERUCRED
00072 #include <ucred.h>
00073 #endif
00074 #ifdef HAVE_ALLOCA_H
00075 #include <alloca.h>
00076 #endif
00077 
00078 #ifdef HAVE_ADT
00079 #include <bsm/adt.h>
00080 #endif
00081 
00082 #include "sd-daemon.h"
00083 
00084 #ifndef O_BINARY
00085 #define O_BINARY 0
00086 #endif
00087 
00088 #ifndef AI_ADDRCONFIG
00089 #define AI_ADDRCONFIG 0
00090 #endif
00091 
00092 #ifndef HAVE_SOCKLEN_T
00093 #define socklen_t int
00094 #endif
00095 
00096 #if defined (__sun) || defined (__sun__)
00097 /*
00098  * CMS_SPACE etc. definitions for Solaris < 10, based on
00099  *   http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
00100  * via
00101  *   http://wiki.opencsw.org/porting-faq#toc10
00102  *
00103  * These are only redefined for Solaris, for now: if your OS needs these too,
00104  * please file a bug. (Or preferably, improve your OS so they're not needed.)
00105  */
00106 
00107 # ifndef CMSG_ALIGN
00108 #   ifdef __sun__
00109 #     define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
00110 #   else
00111       /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
00112 #     define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
00113                               ~(sizeof (long) - 1))
00114 #   endif
00115 # endif
00116 
00117 # ifndef CMSG_SPACE
00118 #   define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
00119                             CMSG_ALIGN (len))
00120 # endif
00121 
00122 # ifndef CMSG_LEN
00123 #   define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
00124 # endif
00125 
00126 #endif /* Solaris */
00127 
00128 static dbus_bool_t
00129 _dbus_open_socket (int              *fd_p,
00130                    int               domain,
00131                    int               type,
00132                    int               protocol,
00133                    DBusError        *error)
00134 {
00135 #ifdef SOCK_CLOEXEC
00136   dbus_bool_t cloexec_done;
00137 
00138   *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
00139   cloexec_done = *fd_p >= 0;
00140 
00141   /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
00142   if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
00143 #endif
00144     {
00145       *fd_p = socket (domain, type, protocol);
00146     }
00147 
00148   if (*fd_p >= 0)
00149     {
00150 #ifdef SOCK_CLOEXEC
00151       if (!cloexec_done)
00152 #endif
00153         {
00154           _dbus_fd_set_close_on_exec(*fd_p);
00155         }
00156 
00157       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00158       return TRUE;
00159     }
00160   else
00161     {
00162       dbus_set_error(error,
00163                      _dbus_error_from_errno (errno),
00164                      "Failed to open socket: %s",
00165                      _dbus_strerror (errno));
00166       return FALSE;
00167     }
00168 }
00169 
00180 static dbus_bool_t
00181 _dbus_open_unix_socket (int              *fd,
00182                         DBusError        *error)
00183 {
00184   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00185 }
00186 
00195 dbus_bool_t
00196 _dbus_close_socket (int               fd,
00197                     DBusError        *error)
00198 {
00199   return _dbus_close (fd, error);
00200 }
00201 
00211 int
00212 _dbus_read_socket (int               fd,
00213                    DBusString       *buffer,
00214                    int               count)
00215 {
00216   return _dbus_read (fd, buffer, count);
00217 }
00218 
00229 int
00230 _dbus_write_socket (int               fd,
00231                     const DBusString *buffer,
00232                     int               start,
00233                     int               len)
00234 {
00235 #if HAVE_DECL_MSG_NOSIGNAL
00236   const char *data;
00237   int bytes_written;
00238 
00239   data = _dbus_string_get_const_data_len (buffer, start, len);
00240 
00241  again:
00242 
00243   bytes_written = send (fd, data, len, MSG_NOSIGNAL);
00244 
00245   if (bytes_written < 0 && errno == EINTR)
00246     goto again;
00247 
00248   return bytes_written;
00249 
00250 #else
00251   return _dbus_write (fd, buffer, start, len);
00252 #endif
00253 }
00254 
00267 int
00268 _dbus_read_socket_with_unix_fds (int               fd,
00269                                  DBusString       *buffer,
00270                                  int               count,
00271                                  int              *fds,
00272                                  int              *n_fds) {
00273 #ifndef HAVE_UNIX_FD_PASSING
00274   int r;
00275 
00276   if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
00277     return r;
00278 
00279   *n_fds = 0;
00280   return r;
00281 
00282 #else
00283   int bytes_read;
00284   int start;
00285   struct msghdr m;
00286   struct iovec iov;
00287 
00288   _dbus_assert (count >= 0);
00289   _dbus_assert (*n_fds >= 0);
00290 
00291   start = _dbus_string_get_length (buffer);
00292 
00293   if (!_dbus_string_lengthen (buffer, count))
00294     {
00295       errno = ENOMEM;
00296       return -1;
00297     }
00298 
00299   _DBUS_ZERO(iov);
00300   iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
00301   iov.iov_len = count;
00302 
00303   _DBUS_ZERO(m);
00304   m.msg_iov = &iov;
00305   m.msg_iovlen = 1;
00306 
00307   /* Hmm, we have no clue how long the control data will actually be
00308      that is queued for us. The least we can do is assume that the
00309      caller knows. Hence let's make space for the number of fds that
00310      we shall read at max plus the cmsg header. */
00311   m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
00312 
00313   /* It's probably safe to assume that systems with SCM_RIGHTS also
00314      know alloca() */
00315   m.msg_control = alloca(m.msg_controllen);
00316   memset(m.msg_control, 0, m.msg_controllen);
00317 
00318   /* Do not include the padding at the end when we tell the kernel
00319    * how much we're willing to receive. This avoids getting
00320    * the padding filled with additional fds that we weren't expecting,
00321    * if a (potentially malicious) sender included them. (fd.o #83622) */
00322   m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
00323 
00324  again:
00325 
00326   bytes_read = recvmsg(fd, &m, 0
00327 #ifdef MSG_CMSG_CLOEXEC
00328                        |MSG_CMSG_CLOEXEC
00329 #endif
00330                        );
00331 
00332   if (bytes_read < 0)
00333     {
00334       if (errno == EINTR)
00335         goto again;
00336       else
00337         {
00338           /* put length back (note that this doesn't actually realloc anything) */
00339           _dbus_string_set_length (buffer, start);
00340           return -1;
00341         }
00342     }
00343   else
00344     {
00345       struct cmsghdr *cm;
00346       dbus_bool_t found = FALSE;
00347 
00348       if (m.msg_flags & MSG_CTRUNC)
00349         {
00350           /* Hmm, apparently the control data was truncated. The bad
00351              thing is that we might have completely lost a couple of fds
00352              without chance to recover them. Hence let's treat this as a
00353              serious error. */
00354 
00355           errno = ENOSPC;
00356           _dbus_string_set_length (buffer, start);
00357           return -1;
00358         }
00359 
00360       for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
00361         if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
00362           {
00363             size_t i;
00364             int *payload = (int *) CMSG_DATA (cm);
00365             size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
00366             size_t payload_len_fds = payload_len_bytes / sizeof (int);
00367             size_t fds_to_use;
00368 
00369             /* Every non-negative int fits in a size_t without truncation,
00370              * and we already know that *n_fds is non-negative, so
00371              * casting (size_t) *n_fds is OK */
00372             _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
00373 
00374             if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
00375               {
00376                 /* The fds in the payload will fit in our buffer */
00377                 fds_to_use = payload_len_fds;
00378               }
00379             else
00380               {
00381                 /* Too many fds in the payload. This shouldn't happen
00382                  * any more because we're setting m.msg_controllen to
00383                  * the exact number we can accept, but be safe and
00384                  * truncate. */
00385                 fds_to_use = (size_t) *n_fds;
00386 
00387                 /* Close the excess fds to avoid DoS: if they stayed open,
00388                  * someone could send us an extra fd per message
00389                  * and we'd eventually run out. */
00390                 for (i = fds_to_use; i < payload_len_fds; i++)
00391                   {
00392                     close (payload[i]);
00393                   }
00394               }
00395 
00396             memcpy (fds, payload, fds_to_use * sizeof (int));
00397             found = TRUE;
00398             /* This cannot overflow because we have chosen fds_to_use
00399              * to be <= *n_fds */
00400             *n_fds = (int) fds_to_use;
00401 
00402             /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
00403                worked, hence we need to go through this list and set
00404                CLOEXEC everywhere in any case */
00405             for (i = 0; i < fds_to_use; i++)
00406               _dbus_fd_set_close_on_exec(fds[i]);
00407 
00408             break;
00409           }
00410 
00411       if (!found)
00412         *n_fds = 0;
00413 
00414       /* put length back (doesn't actually realloc) */
00415       _dbus_string_set_length (buffer, start + bytes_read);
00416 
00417 #if 0
00418       if (bytes_read > 0)
00419         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00420 #endif
00421 
00422       return bytes_read;
00423     }
00424 #endif
00425 }
00426 
00427 int
00428 _dbus_write_socket_with_unix_fds(int               fd,
00429                                  const DBusString *buffer,
00430                                  int               start,
00431                                  int               len,
00432                                  const int        *fds,
00433                                  int               n_fds) {
00434 
00435 #ifndef HAVE_UNIX_FD_PASSING
00436 
00437   if (n_fds > 0) {
00438     errno = ENOTSUP;
00439     return -1;
00440   }
00441 
00442   return _dbus_write_socket(fd, buffer, start, len);
00443 #else
00444   return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
00445 #endif
00446 }
00447 
00448 int
00449 _dbus_write_socket_with_unix_fds_two(int               fd,
00450                                      const DBusString *buffer1,
00451                                      int               start1,
00452                                      int               len1,
00453                                      const DBusString *buffer2,
00454                                      int               start2,
00455                                      int               len2,
00456                                      const int        *fds,
00457                                      int               n_fds) {
00458 
00459 #ifndef HAVE_UNIX_FD_PASSING
00460 
00461   if (n_fds > 0) {
00462     errno = ENOTSUP;
00463     return -1;
00464   }
00465 
00466   return _dbus_write_socket_two(fd,
00467                                 buffer1, start1, len1,
00468                                 buffer2, start2, len2);
00469 #else
00470 
00471   struct msghdr m;
00472   struct cmsghdr *cm;
00473   struct iovec iov[2];
00474   int bytes_written;
00475 
00476   _dbus_assert (len1 >= 0);
00477   _dbus_assert (len2 >= 0);
00478   _dbus_assert (n_fds >= 0);
00479 
00480   _DBUS_ZERO(iov);
00481   iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
00482   iov[0].iov_len = len1;
00483 
00484   if (buffer2)
00485     {
00486       iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
00487       iov[1].iov_len = len2;
00488     }
00489 
00490   _DBUS_ZERO(m);
00491   m.msg_iov = iov;
00492   m.msg_iovlen = buffer2 ? 2 : 1;
00493 
00494   if (n_fds > 0)
00495     {
00496       m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
00497       m.msg_control = alloca(m.msg_controllen);
00498       memset(m.msg_control, 0, m.msg_controllen);
00499 
00500       cm = CMSG_FIRSTHDR(&m);
00501       cm->cmsg_level = SOL_SOCKET;
00502       cm->cmsg_type = SCM_RIGHTS;
00503       cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
00504       memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
00505     }
00506 
00507  again:
00508 
00509   bytes_written = sendmsg (fd, &m, 0
00510 #if HAVE_DECL_MSG_NOSIGNAL
00511                            |MSG_NOSIGNAL
00512 #endif
00513                            );
00514 
00515   if (bytes_written < 0 && errno == EINTR)
00516     goto again;
00517 
00518 #if 0
00519   if (bytes_written > 0)
00520     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00521 #endif
00522 
00523   return bytes_written;
00524 #endif
00525 }
00526 
00540 int
00541 _dbus_write_socket_two (int               fd,
00542                         const DBusString *buffer1,
00543                         int               start1,
00544                         int               len1,
00545                         const DBusString *buffer2,
00546                         int               start2,
00547                         int               len2)
00548 {
00549 #if HAVE_DECL_MSG_NOSIGNAL
00550   struct iovec vectors[2];
00551   const char *data1;
00552   const char *data2;
00553   int bytes_written;
00554   struct msghdr m;
00555 
00556   _dbus_assert (buffer1 != NULL);
00557   _dbus_assert (start1 >= 0);
00558   _dbus_assert (start2 >= 0);
00559   _dbus_assert (len1 >= 0);
00560   _dbus_assert (len2 >= 0);
00561 
00562   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00563 
00564   if (buffer2 != NULL)
00565     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00566   else
00567     {
00568       data2 = NULL;
00569       start2 = 0;
00570       len2 = 0;
00571     }
00572 
00573   vectors[0].iov_base = (char*) data1;
00574   vectors[0].iov_len = len1;
00575   vectors[1].iov_base = (char*) data2;
00576   vectors[1].iov_len = len2;
00577 
00578   _DBUS_ZERO(m);
00579   m.msg_iov = vectors;
00580   m.msg_iovlen = data2 ? 2 : 1;
00581 
00582  again:
00583 
00584   bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
00585 
00586   if (bytes_written < 0 && errno == EINTR)
00587     goto again;
00588 
00589   return bytes_written;
00590 
00591 #else
00592   return _dbus_write_two (fd, buffer1, start1, len1,
00593                           buffer2, start2, len2);
00594 #endif
00595 }
00596 
00597 dbus_bool_t
00598 _dbus_socket_is_invalid (int fd)
00599 {
00600     return fd < 0 ? TRUE : FALSE;
00601 }
00602 
00619 int
00620 _dbus_read (int               fd,
00621             DBusString       *buffer,
00622             int               count)
00623 {
00624   int bytes_read;
00625   int start;
00626   char *data;
00627 
00628   _dbus_assert (count >= 0);
00629 
00630   start = _dbus_string_get_length (buffer);
00631 
00632   if (!_dbus_string_lengthen (buffer, count))
00633     {
00634       errno = ENOMEM;
00635       return -1;
00636     }
00637 
00638   data = _dbus_string_get_data_len (buffer, start, count);
00639 
00640  again:
00641 
00642   bytes_read = read (fd, data, count);
00643 
00644   if (bytes_read < 0)
00645     {
00646       if (errno == EINTR)
00647         goto again;
00648       else
00649         {
00650           /* put length back (note that this doesn't actually realloc anything) */
00651           _dbus_string_set_length (buffer, start);
00652           return -1;
00653         }
00654     }
00655   else
00656     {
00657       /* put length back (doesn't actually realloc) */
00658       _dbus_string_set_length (buffer, start + bytes_read);
00659 
00660 #if 0
00661       if (bytes_read > 0)
00662         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00663 #endif
00664 
00665       return bytes_read;
00666     }
00667 }
00668 
00679 int
00680 _dbus_write (int               fd,
00681              const DBusString *buffer,
00682              int               start,
00683              int               len)
00684 {
00685   const char *data;
00686   int bytes_written;
00687 
00688   data = _dbus_string_get_const_data_len (buffer, start, len);
00689 
00690  again:
00691 
00692   bytes_written = write (fd, data, len);
00693 
00694   if (bytes_written < 0 && errno == EINTR)
00695     goto again;
00696 
00697 #if 0
00698   if (bytes_written > 0)
00699     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00700 #endif
00701 
00702   return bytes_written;
00703 }
00704 
00725 int
00726 _dbus_write_two (int               fd,
00727                  const DBusString *buffer1,
00728                  int               start1,
00729                  int               len1,
00730                  const DBusString *buffer2,
00731                  int               start2,
00732                  int               len2)
00733 {
00734   _dbus_assert (buffer1 != NULL);
00735   _dbus_assert (start1 >= 0);
00736   _dbus_assert (start2 >= 0);
00737   _dbus_assert (len1 >= 0);
00738   _dbus_assert (len2 >= 0);
00739 
00740 #ifdef HAVE_WRITEV
00741   {
00742     struct iovec vectors[2];
00743     const char *data1;
00744     const char *data2;
00745     int bytes_written;
00746 
00747     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00748 
00749     if (buffer2 != NULL)
00750       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00751     else
00752       {
00753         data2 = NULL;
00754         start2 = 0;
00755         len2 = 0;
00756       }
00757 
00758     vectors[0].iov_base = (char*) data1;
00759     vectors[0].iov_len = len1;
00760     vectors[1].iov_base = (char*) data2;
00761     vectors[1].iov_len = len2;
00762 
00763   again:
00764 
00765     bytes_written = writev (fd,
00766                             vectors,
00767                             data2 ? 2 : 1);
00768 
00769     if (bytes_written < 0 && errno == EINTR)
00770       goto again;
00771 
00772     return bytes_written;
00773   }
00774 #else /* HAVE_WRITEV */
00775   {
00776     int ret1, ret2;
00777 
00778     ret1 = _dbus_write (fd, buffer1, start1, len1);
00779     if (ret1 == len1 && buffer2 != NULL)
00780       {
00781         ret2 = _dbus_write (fd, buffer2, start2, len2);
00782         if (ret2 < 0)
00783           ret2 = 0; /* we can't report an error as the first write was OK */
00784 
00785         return ret1 + ret2;
00786       }
00787     else
00788       return ret1;
00789   }
00790 #endif /* !HAVE_WRITEV */
00791 }
00792 
00793 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00794 
00824 int
00825 _dbus_connect_unix_socket (const char     *path,
00826                            dbus_bool_t     abstract,
00827                            DBusError      *error)
00828 {
00829   int fd;
00830   size_t path_len;
00831   struct sockaddr_un addr;
00832 
00833   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00834 
00835   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00836                  path, abstract);
00837 
00838 
00839   if (!_dbus_open_unix_socket (&fd, error))
00840     {
00841       _DBUS_ASSERT_ERROR_IS_SET(error);
00842       return -1;
00843     }
00844   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00845 
00846   _DBUS_ZERO (addr);
00847   addr.sun_family = AF_UNIX;
00848   path_len = strlen (path);
00849 
00850   if (abstract)
00851     {
00852 #ifdef HAVE_ABSTRACT_SOCKETS
00853       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00854       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00855 
00856       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00857         {
00858           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00859                       "Abstract socket name too long\n");
00860           _dbus_close (fd, NULL);
00861           return -1;
00862         }
00863 
00864       strncpy (&addr.sun_path[1], path, path_len);
00865       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00866 #else /* HAVE_ABSTRACT_SOCKETS */
00867       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00868                       "Operating system does not support abstract socket namespace\n");
00869       _dbus_close (fd, NULL);
00870       return -1;
00871 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00872     }
00873   else
00874     {
00875       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00876         {
00877           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00878                       "Socket name too long\n");
00879           _dbus_close (fd, NULL);
00880           return -1;
00881         }
00882 
00883       strncpy (addr.sun_path, path, path_len);
00884     }
00885 
00886   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00887     {
00888       dbus_set_error (error,
00889                       _dbus_error_from_errno (errno),
00890                       "Failed to connect to socket %s: %s",
00891                       path, _dbus_strerror (errno));
00892 
00893       _dbus_close (fd, NULL);
00894       return -1;
00895     }
00896 
00897   if (!_dbus_set_fd_nonblocking (fd, error))
00898     {
00899       _DBUS_ASSERT_ERROR_IS_SET (error);
00900 
00901       _dbus_close (fd, NULL);
00902       return -1;
00903     }
00904 
00905   return fd;
00906 }
00907 
00920 int
00921 _dbus_connect_exec (const char     *path,
00922                     char *const    argv[],
00923                     DBusError      *error)
00924 {
00925   int fds[2];
00926   pid_t pid;
00927   int retval;
00928   dbus_bool_t cloexec_done = 0;
00929 
00930   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00931 
00932   _dbus_verbose ("connecting to process %s\n", path);
00933 
00934 #ifdef SOCK_CLOEXEC
00935   retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
00936   cloexec_done = (retval >= 0);
00937 
00938   if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
00939 #endif
00940     {
00941       retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
00942     }
00943 
00944   if (retval < 0)
00945     {
00946       dbus_set_error (error,
00947                       _dbus_error_from_errno (errno),
00948                       "Failed to create socket pair: %s",
00949                       _dbus_strerror (errno));
00950       return -1;
00951     }
00952 
00953   if (!cloexec_done)
00954     {
00955       _dbus_fd_set_close_on_exec (fds[0]);
00956       _dbus_fd_set_close_on_exec (fds[1]);
00957     }
00958 
00959   pid = fork ();
00960   if (pid < 0)
00961     {
00962       dbus_set_error (error,
00963                       _dbus_error_from_errno (errno),
00964                       "Failed to fork() to call %s: %s",
00965                       path, _dbus_strerror (errno));
00966       close (fds[0]);
00967       close (fds[1]);
00968       return -1;
00969     }
00970 
00971   if (pid == 0)
00972     {
00973       /* child */
00974       close (fds[0]);
00975 
00976       dup2 (fds[1], STDIN_FILENO);
00977       dup2 (fds[1], STDOUT_FILENO);
00978 
00979       if (fds[1] != STDIN_FILENO &&
00980           fds[1] != STDOUT_FILENO)
00981         close (fds[1]);
00982 
00983       /* Inherit STDERR and the controlling terminal from the
00984          parent */
00985 
00986       _dbus_close_all ();
00987 
00988       execvp (path, argv);
00989 
00990       fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
00991 
00992       _exit(1);
00993     }
00994 
00995   /* parent */
00996   close (fds[1]);
00997 
00998   if (!_dbus_set_fd_nonblocking (fds[0], error))
00999     {
01000       _DBUS_ASSERT_ERROR_IS_SET (error);
01001 
01002       close (fds[0]);
01003       return -1;
01004     }
01005 
01006   return fds[0];
01007 }
01008 
01018 static dbus_bool_t
01019 _dbus_set_local_creds (int fd, dbus_bool_t on)
01020 {
01021   dbus_bool_t retval = TRUE;
01022 
01023 #if defined(HAVE_CMSGCRED)
01024   /* NOOP just to make sure only one codepath is used
01025    *      and to prefer CMSGCRED
01026    */
01027 #elif defined(LOCAL_CREDS)
01028   int val = on ? 1 : 0;
01029   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
01030     {
01031       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
01032       retval = FALSE;
01033     }
01034   else
01035     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
01036                    on ? "enabled" : "disabled", fd);
01037 #endif
01038 
01039   return retval;
01040 }
01041 
01059 int
01060 _dbus_listen_unix_socket (const char     *path,
01061                           dbus_bool_t     abstract,
01062                           DBusError      *error)
01063 {
01064   int listen_fd;
01065   struct sockaddr_un addr;
01066   size_t path_len;
01067   unsigned int reuseaddr;
01068 
01069   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01070 
01071   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
01072                  path, abstract);
01073 
01074   if (!_dbus_open_unix_socket (&listen_fd, error))
01075     {
01076       _DBUS_ASSERT_ERROR_IS_SET(error);
01077       return -1;
01078     }
01079   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01080 
01081   _DBUS_ZERO (addr);
01082   addr.sun_family = AF_UNIX;
01083   path_len = strlen (path);
01084 
01085   if (abstract)
01086     {
01087 #ifdef HAVE_ABSTRACT_SOCKETS
01088       /* remember that abstract names aren't nul-terminated so we rely
01089        * on sun_path being filled in with zeroes above.
01090        */
01091       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
01092       path_len++; /* Account for the extra nul byte added to the start of sun_path */
01093 
01094       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01095         {
01096           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01097                       "Abstract socket name too long\n");
01098           _dbus_close (listen_fd, NULL);
01099           return -1;
01100         }
01101 
01102       strncpy (&addr.sun_path[1], path, path_len);
01103       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
01104 #else /* HAVE_ABSTRACT_SOCKETS */
01105       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
01106                       "Operating system does not support abstract socket namespace\n");
01107       _dbus_close (listen_fd, NULL);
01108       return -1;
01109 #endif /* ! HAVE_ABSTRACT_SOCKETS */
01110     }
01111   else
01112     {
01113       /* Discussed security implications of this with Nalin,
01114        * and we couldn't think of where it would kick our ass, but
01115        * it still seems a bit sucky. It also has non-security suckage;
01116        * really we'd prefer to exit if the socket is already in use.
01117        * But there doesn't seem to be a good way to do this.
01118        *
01119        * Just to be extra careful, I threw in the stat() - clearly
01120        * the stat() can't *fix* any security issue, but it at least
01121        * avoids inadvertent/accidental data loss.
01122        */
01123       {
01124         struct stat sb;
01125 
01126         if (stat (path, &sb) == 0 &&
01127             S_ISSOCK (sb.st_mode))
01128           unlink (path);
01129       }
01130 
01131       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01132         {
01133           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01134                       "Abstract socket name too long\n");
01135           _dbus_close (listen_fd, NULL);
01136           return -1;
01137         }
01138 
01139       strncpy (addr.sun_path, path, path_len);
01140     }
01141 
01142   reuseaddr = 1;
01143   if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01144     {
01145       _dbus_warn ("Failed to set socket option\"%s\": %s",
01146                   path, _dbus_strerror (errno));
01147     }
01148 
01149   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
01150     {
01151       dbus_set_error (error, _dbus_error_from_errno (errno),
01152                       "Failed to bind socket \"%s\": %s",
01153                       path, _dbus_strerror (errno));
01154       _dbus_close (listen_fd, NULL);
01155       return -1;
01156     }
01157 
01158   if (listen (listen_fd, 30 /* backlog */) < 0)
01159     {
01160       dbus_set_error (error, _dbus_error_from_errno (errno),
01161                       "Failed to listen on socket \"%s\": %s",
01162                       path, _dbus_strerror (errno));
01163       _dbus_close (listen_fd, NULL);
01164       return -1;
01165     }
01166 
01167   if (!_dbus_set_local_creds (listen_fd, TRUE))
01168     {
01169       dbus_set_error (error, _dbus_error_from_errno (errno),
01170                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
01171                       path, _dbus_strerror (errno));
01172       close (listen_fd);
01173       return -1;
01174     }
01175 
01176   if (!_dbus_set_fd_nonblocking (listen_fd, error))
01177     {
01178       _DBUS_ASSERT_ERROR_IS_SET (error);
01179       _dbus_close (listen_fd, NULL);
01180       return -1;
01181     }
01182 
01183   /* Try opening up the permissions, but if we can't, just go ahead
01184    * and continue, maybe it will be good enough.
01185    */
01186   if (!abstract && chmod (path, 0777) < 0)
01187     _dbus_warn ("Could not set mode 0777 on socket %s\n",
01188                 path);
01189 
01190   return listen_fd;
01191 }
01192 
01203 int
01204 _dbus_listen_systemd_sockets (int       **fds,
01205                               DBusError *error)
01206 {
01207   int r, n;
01208   unsigned fd;
01209   int *new_fds;
01210 
01211   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01212 
01213   n = sd_listen_fds (TRUE);
01214   if (n < 0)
01215     {
01216       dbus_set_error (error, _dbus_error_from_errno (-n),
01217                       "Failed to acquire systemd socket: %s",
01218                       _dbus_strerror (-n));
01219       return -1;
01220     }
01221 
01222   if (n <= 0)
01223     {
01224       dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01225                       "No socket received.");
01226       return -1;
01227     }
01228 
01229   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01230     {
01231       r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
01232       if (r < 0)
01233         {
01234           dbus_set_error (error, _dbus_error_from_errno (-r),
01235                           "Failed to verify systemd socket type: %s",
01236                           _dbus_strerror (-r));
01237           return -1;
01238         }
01239 
01240       if (!r)
01241         {
01242           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01243                           "Passed socket has wrong type.");
01244           return -1;
01245         }
01246     }
01247 
01248   /* OK, the file descriptors are all good, so let's take posession of
01249      them then. */
01250 
01251   new_fds = dbus_new (int, n);
01252   if (!new_fds)
01253     {
01254       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
01255                       "Failed to allocate file handle array.");
01256       goto fail;
01257     }
01258 
01259   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01260     {
01261       if (!_dbus_set_local_creds (fd, TRUE))
01262         {
01263           dbus_set_error (error, _dbus_error_from_errno (errno),
01264                           "Failed to enable LOCAL_CREDS on systemd socket: %s",
01265                           _dbus_strerror (errno));
01266           goto fail;
01267         }
01268 
01269       if (!_dbus_set_fd_nonblocking (fd, error))
01270         {
01271           _DBUS_ASSERT_ERROR_IS_SET (error);
01272           goto fail;
01273         }
01274 
01275       new_fds[fd - SD_LISTEN_FDS_START] = fd;
01276     }
01277 
01278   *fds = new_fds;
01279   return n;
01280 
01281  fail:
01282 
01283   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01284     {
01285       _dbus_close (fd, NULL);
01286     }
01287 
01288   dbus_free (new_fds);
01289   return -1;
01290 }
01291 
01305 int
01306 _dbus_connect_tcp_socket (const char     *host,
01307                           const char     *port,
01308                           const char     *family,
01309                           DBusError      *error)
01310 {
01311     return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
01312 }
01313 
01314 int
01315 _dbus_connect_tcp_socket_with_nonce (const char     *host,
01316                                      const char     *port,
01317                                      const char     *family,
01318                                      const char     *noncefile,
01319                                      DBusError      *error)
01320 {
01321   int saved_errno = 0;
01322   int fd = -1, res;
01323   struct addrinfo hints;
01324   struct addrinfo *ai, *tmp;
01325 
01326   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01327 
01328   _DBUS_ZERO (hints);
01329 
01330   if (!family)
01331     hints.ai_family = AF_UNSPEC;
01332   else if (!strcmp(family, "ipv4"))
01333     hints.ai_family = AF_INET;
01334   else if (!strcmp(family, "ipv6"))
01335     hints.ai_family = AF_INET6;
01336   else
01337     {
01338       dbus_set_error (error,
01339                       DBUS_ERROR_BAD_ADDRESS,
01340                       "Unknown address family %s", family);
01341       return -1;
01342     }
01343   hints.ai_protocol = IPPROTO_TCP;
01344   hints.ai_socktype = SOCK_STREAM;
01345   hints.ai_flags = AI_ADDRCONFIG;
01346 
01347   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
01348     {
01349       dbus_set_error (error,
01350                       _dbus_error_from_errno (errno),
01351                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01352                       host, port, gai_strerror(res), res);
01353       return -1;
01354     }
01355 
01356   tmp = ai;
01357   while (tmp)
01358     {
01359       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01360         {
01361           freeaddrinfo(ai);
01362           _DBUS_ASSERT_ERROR_IS_SET(error);
01363           return -1;
01364         }
01365       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01366 
01367       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01368         {
01369           saved_errno = errno;
01370           _dbus_close(fd, NULL);
01371           fd = -1;
01372           tmp = tmp->ai_next;
01373           continue;
01374         }
01375 
01376       break;
01377     }
01378   freeaddrinfo(ai);
01379 
01380   if (fd == -1)
01381     {
01382       dbus_set_error (error,
01383                       _dbus_error_from_errno (saved_errno),
01384                       "Failed to connect to socket \"%s:%s\" %s",
01385                       host, port, _dbus_strerror(saved_errno));
01386       return -1;
01387     }
01388 
01389   if (noncefile != NULL)
01390     {
01391       DBusString noncefileStr;
01392       dbus_bool_t ret;
01393       _dbus_string_init_const (&noncefileStr, noncefile);
01394       ret = _dbus_send_nonce (fd, &noncefileStr, error);
01395       _dbus_string_free (&noncefileStr);
01396 
01397       if (!ret)
01398     {
01399       _dbus_close (fd, NULL);
01400           return -1;
01401         }
01402     }
01403 
01404   if (!_dbus_set_fd_nonblocking (fd, error))
01405     {
01406       _dbus_close (fd, NULL);
01407       return -1;
01408     }
01409 
01410   return fd;
01411 }
01412 
01429 int
01430 _dbus_listen_tcp_socket (const char     *host,
01431                          const char     *port,
01432                          const char     *family,
01433                          DBusString     *retport,
01434                          int           **fds_p,
01435                          DBusError      *error)
01436 {
01437   int saved_errno;
01438   int nlisten_fd = 0, *listen_fd = NULL, res, i;
01439   struct addrinfo hints;
01440   struct addrinfo *ai, *tmp;
01441   unsigned int reuseaddr;
01442 
01443   *fds_p = NULL;
01444   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01445 
01446   _DBUS_ZERO (hints);
01447 
01448   if (!family)
01449     hints.ai_family = AF_UNSPEC;
01450   else if (!strcmp(family, "ipv4"))
01451     hints.ai_family = AF_INET;
01452   else if (!strcmp(family, "ipv6"))
01453     hints.ai_family = AF_INET6;
01454   else
01455     {
01456       dbus_set_error (error,
01457                       DBUS_ERROR_BAD_ADDRESS,
01458                       "Unknown address family %s", family);
01459       return -1;
01460     }
01461 
01462   hints.ai_protocol = IPPROTO_TCP;
01463   hints.ai_socktype = SOCK_STREAM;
01464   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
01465 
01466  redo_lookup_with_port:
01467   ai = NULL;
01468   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01469     {
01470       dbus_set_error (error,
01471                       _dbus_error_from_errno (errno),
01472                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01473                       host ? host : "*", port, gai_strerror(res), res);
01474       goto failed;
01475     }
01476 
01477   tmp = ai;
01478   while (tmp)
01479     {
01480       int fd = -1, *newlisten_fd;
01481       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01482         {
01483           _DBUS_ASSERT_ERROR_IS_SET(error);
01484           goto failed;
01485         }
01486       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01487 
01488       reuseaddr = 1;
01489       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01490         {
01491           _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01492                       host ? host : "*", port, _dbus_strerror (errno));
01493         }
01494 
01495       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01496         {
01497           saved_errno = errno;
01498           _dbus_close(fd, NULL);
01499           if (saved_errno == EADDRINUSE)
01500             {
01501               /* Depending on kernel policy, it may or may not
01502                  be neccessary to bind to both IPv4 & 6 addresses
01503                  so ignore EADDRINUSE here */
01504               tmp = tmp->ai_next;
01505               continue;
01506             }
01507           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01508                           "Failed to bind socket \"%s:%s\": %s",
01509                           host ? host : "*", port, _dbus_strerror (saved_errno));
01510           goto failed;
01511         }
01512 
01513       if (listen (fd, 30 /* backlog */) < 0)
01514         {
01515           saved_errno = errno;
01516           _dbus_close (fd, NULL);
01517           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01518                           "Failed to listen on socket \"%s:%s\": %s",
01519                           host ? host : "*", port, _dbus_strerror (saved_errno));
01520           goto failed;
01521         }
01522 
01523       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
01524       if (!newlisten_fd)
01525         {
01526           saved_errno = errno;
01527           _dbus_close (fd, NULL);
01528           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01529                           "Failed to allocate file handle array: %s",
01530                           _dbus_strerror (saved_errno));
01531           goto failed;
01532         }
01533       listen_fd = newlisten_fd;
01534       listen_fd[nlisten_fd] = fd;
01535       nlisten_fd++;
01536 
01537       if (!_dbus_string_get_length(retport))
01538         {
01539           /* If the user didn't specify a port, or used 0, then
01540              the kernel chooses a port. After the first address
01541              is bound to, we need to force all remaining addresses
01542              to use the same port */
01543           if (!port || !strcmp(port, "0"))
01544             {
01545               int result;
01546               struct sockaddr_storage addr;
01547               socklen_t addrlen;
01548               char portbuf[50];
01549 
01550               addrlen = sizeof(addr);
01551               result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01552 
01553               if (result == -1 ||
01554                   (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
01555                                       portbuf, sizeof(portbuf),
01556                                       NI_NUMERICHOST)) != 0)
01557                 {
01558                   dbus_set_error (error, _dbus_error_from_errno (errno),
01559                                   "Failed to resolve port \"%s:%s\": %s (%s)",
01560                                   host ? host : "*", port, gai_strerror(res), res);
01561                   goto failed;
01562                 }
01563               if (!_dbus_string_append(retport, portbuf))
01564                 {
01565                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01566                   goto failed;
01567                 }
01568 
01569               /* Release current address list & redo lookup */
01570               port = _dbus_string_get_const_data(retport);
01571               freeaddrinfo(ai);
01572               goto redo_lookup_with_port;
01573             }
01574           else
01575             {
01576               if (!_dbus_string_append(retport, port))
01577                 {
01578                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01579                     goto failed;
01580                 }
01581             }
01582         }
01583 
01584       tmp = tmp->ai_next;
01585     }
01586   freeaddrinfo(ai);
01587   ai = NULL;
01588 
01589   if (!nlisten_fd)
01590     {
01591       errno = EADDRINUSE;
01592       dbus_set_error (error, _dbus_error_from_errno (errno),
01593                       "Failed to bind socket \"%s:%s\": %s",
01594                       host ? host : "*", port, _dbus_strerror (errno));
01595       goto failed;
01596     }
01597 
01598   for (i = 0 ; i < nlisten_fd ; i++)
01599     {
01600       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01601         {
01602           goto failed;
01603         }
01604     }
01605 
01606   *fds_p = listen_fd;
01607 
01608   return nlisten_fd;
01609 
01610  failed:
01611   if (ai)
01612     freeaddrinfo(ai);
01613   for (i = 0 ; i < nlisten_fd ; i++)
01614     _dbus_close(listen_fd[i], NULL);
01615   dbus_free(listen_fd);
01616   return -1;
01617 }
01618 
01619 static dbus_bool_t
01620 write_credentials_byte (int             server_fd,
01621                         DBusError      *error)
01622 {
01623   int bytes_written;
01624   char buf[1] = { '\0' };
01625 #if defined(HAVE_CMSGCRED)
01626   union {
01627           struct cmsghdr hdr;
01628           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01629   } cmsg;
01630   struct iovec iov;
01631   struct msghdr msg;
01632   iov.iov_base = buf;
01633   iov.iov_len = 1;
01634 
01635   _DBUS_ZERO(msg);
01636   msg.msg_iov = &iov;
01637   msg.msg_iovlen = 1;
01638 
01639   msg.msg_control = (caddr_t) &cmsg;
01640   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01641   _DBUS_ZERO(cmsg);
01642   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01643   cmsg.hdr.cmsg_level = SOL_SOCKET;
01644   cmsg.hdr.cmsg_type = SCM_CREDS;
01645 #endif
01646 
01647   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01648 
01649  again:
01650 
01651 #if defined(HAVE_CMSGCRED)
01652   bytes_written = sendmsg (server_fd, &msg, 0
01653 #if HAVE_DECL_MSG_NOSIGNAL
01654                            |MSG_NOSIGNAL
01655 #endif
01656                            );
01657 #else
01658   bytes_written = send (server_fd, buf, 1, 0
01659 #if HAVE_DECL_MSG_NOSIGNAL
01660                         |MSG_NOSIGNAL
01661 #endif
01662                         );
01663 #endif
01664 
01665   if (bytes_written < 0 && errno == EINTR)
01666     goto again;
01667 
01668   if (bytes_written < 0)
01669     {
01670       dbus_set_error (error, _dbus_error_from_errno (errno),
01671                       "Failed to write credentials byte: %s",
01672                      _dbus_strerror (errno));
01673       return FALSE;
01674     }
01675   else if (bytes_written == 0)
01676     {
01677       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01678                       "wrote zero bytes writing credentials byte");
01679       return FALSE;
01680     }
01681   else
01682     {
01683       _dbus_assert (bytes_written == 1);
01684       _dbus_verbose ("wrote credentials byte\n");
01685       return TRUE;
01686     }
01687 }
01688 
01710 dbus_bool_t
01711 _dbus_read_credentials_socket  (int              client_fd,
01712                                 DBusCredentials *credentials,
01713                                 DBusError       *error)
01714 {
01715   struct msghdr msg;
01716   struct iovec iov;
01717   char buf;
01718   dbus_uid_t uid_read;
01719   dbus_pid_t pid_read;
01720   int bytes_read;
01721 
01722 #ifdef HAVE_CMSGCRED
01723   union {
01724     struct cmsghdr hdr;
01725     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01726   } cmsg;
01727 
01728 #elif defined(LOCAL_CREDS)
01729   struct {
01730     struct cmsghdr hdr;
01731     struct sockcred cred;
01732   } cmsg;
01733 #endif
01734 
01735   uid_read = DBUS_UID_UNSET;
01736   pid_read = DBUS_PID_UNSET;
01737 
01738   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01739 
01740   /* The POSIX spec certainly doesn't promise this, but
01741    * we need these assertions to fail as soon as we're wrong about
01742    * it so we can do the porting fixups
01743    */
01744   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01745   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01746   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01747 
01748   _dbus_credentials_clear (credentials);
01749 
01750   /* Systems supporting LOCAL_CREDS are configured to have this feature
01751    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01752    * the connection.  Therefore, the received message must carry the
01753    * credentials information without doing anything special.
01754    */
01755 
01756   iov.iov_base = &buf;
01757   iov.iov_len = 1;
01758 
01759   _DBUS_ZERO(msg);
01760   msg.msg_iov = &iov;
01761   msg.msg_iovlen = 1;
01762 
01763 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01764   _DBUS_ZERO(cmsg);
01765   msg.msg_control = (caddr_t) &cmsg;
01766   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01767 #endif
01768 
01769  again:
01770   bytes_read = recvmsg (client_fd, &msg, 0);
01771 
01772   if (bytes_read < 0)
01773     {
01774       if (errno == EINTR)
01775         goto again;
01776 
01777       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01778        * normally only call read_credentials if the socket was ready
01779        * for reading
01780        */
01781 
01782       dbus_set_error (error, _dbus_error_from_errno (errno),
01783                       "Failed to read credentials byte: %s",
01784                       _dbus_strerror (errno));
01785       return FALSE;
01786     }
01787   else if (bytes_read == 0)
01788     {
01789       /* this should not happen unless we are using recvmsg wrong,
01790        * so is essentially here for paranoia
01791        */
01792       dbus_set_error (error, DBUS_ERROR_FAILED,
01793                       "Failed to read credentials byte (zero-length read)");
01794       return FALSE;
01795     }
01796   else if (buf != '\0')
01797     {
01798       dbus_set_error (error, DBUS_ERROR_FAILED,
01799                       "Credentials byte was not nul");
01800       return FALSE;
01801     }
01802 
01803 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01804   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01805                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01806     {
01807       dbus_set_error (error, DBUS_ERROR_FAILED,
01808                       "Message from recvmsg() was not SCM_CREDS");
01809       return FALSE;
01810     }
01811 #endif
01812 
01813   _dbus_verbose ("read credentials byte\n");
01814 
01815   {
01816 #ifdef SO_PEERCRED
01817 #ifdef __OpenBSD__
01818     struct sockpeercred cr;
01819 #else
01820     struct ucred cr;
01821 #endif
01822     int cr_len = sizeof (cr);
01823 
01824     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01825         cr_len == sizeof (cr))
01826       {
01827         pid_read = cr.pid;
01828         uid_read = cr.uid;
01829       }
01830     else
01831       {
01832         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01833                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01834       }
01835 #elif defined(HAVE_CMSGCRED)
01836     struct cmsgcred *cred;
01837 
01838     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01839     pid_read = cred->cmcred_pid;
01840     uid_read = cred->cmcred_euid;
01841 #elif defined(LOCAL_CREDS)
01842     pid_read = DBUS_PID_UNSET;
01843     uid_read = cmsg.cred.sc_uid;
01844     /* Since we have already got the credentials from this socket, we can
01845      * disable its LOCAL_CREDS flag if it was ever set. */
01846     _dbus_set_local_creds (client_fd, FALSE);
01847 #elif defined(HAVE_GETPEEREID)
01848     uid_t euid;
01849     gid_t egid;
01850     if (getpeereid (client_fd, &euid, &egid) == 0)
01851       {
01852         uid_read = euid;
01853       }
01854     else
01855       {
01856         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01857       }
01858 #elif defined(HAVE_GETPEERUCRED)
01859     ucred_t * ucred = NULL;
01860     if (getpeerucred (client_fd, &ucred) == 0)
01861       {
01862         pid_read = ucred_getpid (ucred);
01863         uid_read = ucred_geteuid (ucred);
01864 #ifdef HAVE_ADT
01865         /* generate audit session data based on socket ucred */
01866         adt_session_data_t *adth = NULL;
01867         adt_export_data_t *data = NULL;
01868         size_t size = 0;
01869         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01870           {
01871             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01872           }
01873         else
01874           {
01875             if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01876               {
01877                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01878               }
01879             else
01880               {
01881                 size = adt_export_session_data (adth, &data);
01882                 if (size <= 0)
01883                   {
01884                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01885                   }
01886                 else
01887                   {
01888                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01889                     free (data);
01890                   }
01891               }
01892             (void) adt_end_session (adth);
01893           }
01894 #endif /* HAVE_ADT */
01895       }
01896     else
01897       {
01898         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01899       }
01900     if (ucred != NULL)
01901       ucred_free (ucred);
01902 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01903     _dbus_verbose ("Socket credentials not supported on this OS\n");
01904 #endif
01905   }
01906 
01907   _dbus_verbose ("Credentials:"
01908                  "  pid "DBUS_PID_FORMAT
01909                  "  uid "DBUS_UID_FORMAT
01910                  "\n",
01911                  pid_read,
01912                  uid_read);
01913 
01914   if (pid_read != DBUS_PID_UNSET)
01915     {
01916       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01917         {
01918           _DBUS_SET_OOM (error);
01919           return FALSE;
01920         }
01921     }
01922 
01923   if (uid_read != DBUS_UID_UNSET)
01924     {
01925       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01926         {
01927           _DBUS_SET_OOM (error);
01928           return FALSE;
01929         }
01930     }
01931 
01932   return TRUE;
01933 }
01934 
01952 dbus_bool_t
01953 _dbus_send_credentials_socket  (int              server_fd,
01954                                 DBusError       *error)
01955 {
01956   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01957 
01958   if (write_credentials_byte (server_fd, error))
01959     return TRUE;
01960   else
01961     return FALSE;
01962 }
01963 
01973 int
01974 _dbus_accept  (int listen_fd)
01975 {
01976   int client_fd;
01977   struct sockaddr addr;
01978   socklen_t addrlen;
01979 #ifdef HAVE_ACCEPT4
01980   dbus_bool_t cloexec_done;
01981 #endif
01982 
01983   addrlen = sizeof (addr);
01984 
01985  retry:
01986 
01987 #ifdef HAVE_ACCEPT4
01988   /*
01989    * At compile-time, we assume that if accept4() is available in
01990    * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
01991    * not necessarily true that either is supported by the running kernel.
01992    */
01993   client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
01994   cloexec_done = client_fd >= 0;
01995 
01996   if (client_fd < 0 && (errno == ENOSYS || errno == EINVAL))
01997 #endif
01998     {
01999       client_fd = accept (listen_fd, &addr, &addrlen);
02000     }
02001 
02002   if (client_fd < 0)
02003     {
02004       if (errno == EINTR)
02005         goto retry;
02006     }
02007 
02008   _dbus_verbose ("client fd %d accepted\n", client_fd);
02009 
02010 #ifdef HAVE_ACCEPT4
02011   if (!cloexec_done)
02012 #endif
02013     {
02014       _dbus_fd_set_close_on_exec(client_fd);
02015     }
02016 
02017   return client_fd;
02018 }
02019 
02028 dbus_bool_t
02029 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
02030 {
02031   const char *directory;
02032   struct stat sb;
02033 
02034   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02035 
02036   directory = _dbus_string_get_const_data (dir);
02037 
02038   if (stat (directory, &sb) < 0)
02039     {
02040       dbus_set_error (error, _dbus_error_from_errno (errno),
02041                       "%s", _dbus_strerror (errno));
02042 
02043       return FALSE;
02044     }
02045 
02046   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
02047       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
02048     {
02049       dbus_set_error (error, DBUS_ERROR_FAILED,
02050                      "%s directory is not private to the user", directory);
02051       return FALSE;
02052     }
02053 
02054   return TRUE;
02055 }
02056 
02057 static dbus_bool_t
02058 fill_user_info_from_passwd (struct passwd *p,
02059                             DBusUserInfo  *info,
02060                             DBusError     *error)
02061 {
02062   _dbus_assert (p->pw_name != NULL);
02063   _dbus_assert (p->pw_dir != NULL);
02064 
02065   info->uid = p->pw_uid;
02066   info->primary_gid = p->pw_gid;
02067   info->username = _dbus_strdup (p->pw_name);
02068   info->homedir = _dbus_strdup (p->pw_dir);
02069 
02070   if (info->username == NULL ||
02071       info->homedir == NULL)
02072     {
02073       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02074       return FALSE;
02075     }
02076 
02077   return TRUE;
02078 }
02079 
02080 static dbus_bool_t
02081 fill_user_info (DBusUserInfo       *info,
02082                 dbus_uid_t          uid,
02083                 const DBusString   *username,
02084                 DBusError          *error)
02085 {
02086   const char *username_c;
02087 
02088   /* exactly one of username/uid provided */
02089   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
02090   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
02091 
02092   info->uid = DBUS_UID_UNSET;
02093   info->primary_gid = DBUS_GID_UNSET;
02094   info->group_ids = NULL;
02095   info->n_group_ids = 0;
02096   info->username = NULL;
02097   info->homedir = NULL;
02098 
02099   if (username != NULL)
02100     username_c = _dbus_string_get_const_data (username);
02101   else
02102     username_c = NULL;
02103 
02104   /* For now assuming that the getpwnam() and getpwuid() flavors
02105    * are always symmetrical, if not we have to add more configure
02106    * checks
02107    */
02108 
02109 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
02110   {
02111     struct passwd *p;
02112     int result;
02113     size_t buflen;
02114     char *buf;
02115     struct passwd p_str;
02116 
02117     /* retrieve maximum needed size for buf */
02118     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
02119 
02120     /* sysconf actually returns a long, but everything else expects size_t,
02121      * so just recast here.
02122      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
02123      */
02124     if ((long) buflen <= 0)
02125       buflen = 1024;
02126 
02127     result = -1;
02128     while (1)
02129       {
02130         buf = dbus_malloc (buflen);
02131         if (buf == NULL)
02132           {
02133             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02134             return FALSE;
02135           }
02136 
02137         p = NULL;
02138 #ifdef HAVE_POSIX_GETPWNAM_R
02139         if (uid != DBUS_UID_UNSET)
02140           result = getpwuid_r (uid, &p_str, buf, buflen,
02141                                &p);
02142         else
02143           result = getpwnam_r (username_c, &p_str, buf, buflen,
02144                                &p);
02145 #else
02146         if (uid != DBUS_UID_UNSET)
02147           p = getpwuid_r (uid, &p_str, buf, buflen);
02148         else
02149           p = getpwnam_r (username_c, &p_str, buf, buflen);
02150         result = 0;
02151 #endif /* !HAVE_POSIX_GETPWNAM_R */
02152         //Try a bigger buffer if ERANGE was returned
02153         if (result == ERANGE && buflen < 512 * 1024)
02154           {
02155             dbus_free (buf);
02156             buflen *= 2;
02157           }
02158         else
02159           {
02160             break;
02161           }
02162       }
02163     if (result == 0 && p == &p_str)
02164       {
02165         if (!fill_user_info_from_passwd (p, info, error))
02166           {
02167             dbus_free (buf);
02168             return FALSE;
02169           }
02170         dbus_free (buf);
02171       }
02172     else
02173       {
02174         dbus_set_error (error, _dbus_error_from_errno (errno),
02175                         "User \"%s\" unknown or no memory to allocate password entry\n",
02176                         username_c ? username_c : "???");
02177         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02178         dbus_free (buf);
02179         return FALSE;
02180       }
02181   }
02182 #else /* ! HAVE_GETPWNAM_R */
02183   {
02184     /* I guess we're screwed on thread safety here */
02185     struct passwd *p;
02186 
02187     if (uid != DBUS_UID_UNSET)
02188       p = getpwuid (uid);
02189     else
02190       p = getpwnam (username_c);
02191 
02192     if (p != NULL)
02193       {
02194         if (!fill_user_info_from_passwd (p, info, error))
02195           {
02196             return FALSE;
02197           }
02198       }
02199     else
02200       {
02201         dbus_set_error (error, _dbus_error_from_errno (errno),
02202                         "User \"%s\" unknown or no memory to allocate password entry\n",
02203                         username_c ? username_c : "???");
02204         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02205         return FALSE;
02206       }
02207   }
02208 #endif  /* ! HAVE_GETPWNAM_R */
02209 
02210   /* Fill this in so we can use it to get groups */
02211   username_c = info->username;
02212 
02213 #ifdef HAVE_GETGROUPLIST
02214   {
02215     gid_t *buf;
02216     int buf_count;
02217     int i;
02218     int initial_buf_count;
02219 
02220     initial_buf_count = 17;
02221     buf_count = initial_buf_count;
02222     buf = dbus_new (gid_t, buf_count);
02223     if (buf == NULL)
02224       {
02225         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02226         goto failed;
02227       }
02228 
02229     if (getgrouplist (username_c,
02230                       info->primary_gid,
02231                       buf, &buf_count) < 0)
02232       {
02233         gid_t *new;
02234         /* Presumed cause of negative return code: buf has insufficient
02235            entries to hold the entire group list. The Linux behavior in this
02236            case is to pass back the actual number of groups in buf_count, but
02237            on Mac OS X 10.5, buf_count is unhelpfully left alone.
02238            So as a hack, try to help out a bit by guessing a larger
02239            number of groups, within reason.. might still fail, of course,
02240            but we can at least print a more informative message.  I looked up
02241            the "right way" to do this by downloading Apple's own source code
02242            for the "id" command, and it turns out that they use an
02243            undocumented library function getgrouplist_2 (!) which is not
02244            declared in any header in /usr/include (!!). That did not seem
02245            like the way to go here.
02246         */
02247         if (buf_count == initial_buf_count)
02248           {
02249             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
02250           }
02251         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02252         if (new == NULL)
02253           {
02254             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02255             dbus_free (buf);
02256             goto failed;
02257           }
02258 
02259         buf = new;
02260 
02261         errno = 0;
02262         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02263           {
02264             if (errno == 0)
02265               {
02266                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02267                             username_c, buf_count, buf_count);
02268               }
02269             else
02270               {
02271                 dbus_set_error (error,
02272                                 _dbus_error_from_errno (errno),
02273                                 "Failed to get groups for username \"%s\" primary GID "
02274                                 DBUS_GID_FORMAT ": %s\n",
02275                                 username_c, info->primary_gid,
02276                                 _dbus_strerror (errno));
02277                 dbus_free (buf);
02278                 goto failed;
02279               }
02280           }
02281       }
02282 
02283     info->group_ids = dbus_new (dbus_gid_t, buf_count);
02284     if (info->group_ids == NULL)
02285       {
02286         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02287         dbus_free (buf);
02288         goto failed;
02289       }
02290 
02291     for (i = 0; i < buf_count; ++i)
02292       info->group_ids[i] = buf[i];
02293 
02294     info->n_group_ids = buf_count;
02295 
02296     dbus_free (buf);
02297   }
02298 #else  /* HAVE_GETGROUPLIST */
02299   {
02300     /* We just get the one group ID */
02301     info->group_ids = dbus_new (dbus_gid_t, 1);
02302     if (info->group_ids == NULL)
02303       {
02304         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02305         goto failed;
02306       }
02307 
02308     info->n_group_ids = 1;
02309 
02310     (info->group_ids)[0] = info->primary_gid;
02311   }
02312 #endif /* HAVE_GETGROUPLIST */
02313 
02314   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02315 
02316   return TRUE;
02317 
02318  failed:
02319   _DBUS_ASSERT_ERROR_IS_SET (error);
02320   return FALSE;
02321 }
02322 
02331 dbus_bool_t
02332 _dbus_user_info_fill (DBusUserInfo     *info,
02333                       const DBusString *username,
02334                       DBusError        *error)
02335 {
02336   return fill_user_info (info, DBUS_UID_UNSET,
02337                          username, error);
02338 }
02339 
02348 dbus_bool_t
02349 _dbus_user_info_fill_uid (DBusUserInfo *info,
02350                           dbus_uid_t    uid,
02351                           DBusError    *error)
02352 {
02353   return fill_user_info (info, uid,
02354                          NULL, error);
02355 }
02356 
02364 dbus_bool_t
02365 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02366 {
02367   /* The POSIX spec certainly doesn't promise this, but
02368    * we need these assertions to fail as soon as we're wrong about
02369    * it so we can do the porting fixups
02370    */
02371   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
02372   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
02373   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
02374 
02375   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
02376     return FALSE;
02377   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02378     return FALSE;
02379 
02380   return TRUE;
02381 }
02382 
02394 dbus_bool_t
02395 _dbus_append_user_from_current_process (DBusString *str)
02396 {
02397   return _dbus_string_append_uint (str,
02398                                    _dbus_geteuid ());
02399 }
02400 
02405 dbus_pid_t
02406 _dbus_getpid (void)
02407 {
02408   return getpid ();
02409 }
02410 
02414 dbus_uid_t
02415 _dbus_getuid (void)
02416 {
02417   return getuid ();
02418 }
02419 
02423 dbus_uid_t
02424 _dbus_geteuid (void)
02425 {
02426   return geteuid ();
02427 }
02428 
02435 unsigned long
02436 _dbus_pid_for_log (void)
02437 {
02438   return getpid ();
02439 }
02440 
02448 dbus_bool_t
02449 _dbus_parse_uid (const DBusString      *uid_str,
02450                  dbus_uid_t            *uid)
02451 {
02452   int end;
02453   long val;
02454 
02455   if (_dbus_string_get_length (uid_str) == 0)
02456     {
02457       _dbus_verbose ("UID string was zero length\n");
02458       return FALSE;
02459     }
02460 
02461   val = -1;
02462   end = 0;
02463   if (!_dbus_string_parse_int (uid_str, 0, &val,
02464                                &end))
02465     {
02466       _dbus_verbose ("could not parse string as a UID\n");
02467       return FALSE;
02468     }
02469 
02470   if (end != _dbus_string_get_length (uid_str))
02471     {
02472       _dbus_verbose ("string contained trailing stuff after UID\n");
02473       return FALSE;
02474     }
02475 
02476   *uid = val;
02477 
02478   return TRUE;
02479 }
02480 
02481 #if !DBUS_USE_SYNC
02482 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
02483 #endif
02484 
02491 dbus_int32_t
02492 _dbus_atomic_inc (DBusAtomic *atomic)
02493 {
02494 #if DBUS_USE_SYNC
02495   return __sync_add_and_fetch(&atomic->value, 1)-1;
02496 #else
02497   dbus_int32_t res;
02498   _DBUS_LOCK (atomic);
02499   res = atomic->value;
02500   atomic->value += 1;
02501   _DBUS_UNLOCK (atomic);
02502   return res;
02503 #endif
02504 }
02505 
02512 dbus_int32_t
02513 _dbus_atomic_dec (DBusAtomic *atomic)
02514 {
02515 #if DBUS_USE_SYNC
02516   return __sync_sub_and_fetch(&atomic->value, 1)+1;
02517 #else
02518   dbus_int32_t res;
02519 
02520   _DBUS_LOCK (atomic);
02521   res = atomic->value;
02522   atomic->value -= 1;
02523   _DBUS_UNLOCK (atomic);
02524   return res;
02525 #endif
02526 }
02527 
02535 dbus_int32_t
02536 _dbus_atomic_get (DBusAtomic *atomic)
02537 {
02538 #if DBUS_USE_SYNC
02539   __sync_synchronize ();
02540   return atomic->value;
02541 #else
02542   dbus_int32_t res;
02543 
02544   _DBUS_LOCK (atomic);
02545   res = atomic->value;
02546   _DBUS_UNLOCK (atomic);
02547   return res;
02548 #endif
02549 }
02550 
02559 int
02560 _dbus_poll (DBusPollFD *fds,
02561             int         n_fds,
02562             int         timeout_milliseconds)
02563 {
02564 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02565   /* This big thing is a constant expression and should get optimized
02566    * out of existence. So it's more robust than a configure check at
02567    * no cost.
02568    */
02569   if (_DBUS_POLLIN == POLLIN &&
02570       _DBUS_POLLPRI == POLLPRI &&
02571       _DBUS_POLLOUT == POLLOUT &&
02572       _DBUS_POLLERR == POLLERR &&
02573       _DBUS_POLLHUP == POLLHUP &&
02574       _DBUS_POLLNVAL == POLLNVAL &&
02575       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
02576       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
02577       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
02578       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
02579       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
02580       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
02581       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
02582     {
02583       return poll ((struct pollfd*) fds,
02584                    n_fds,
02585                    timeout_milliseconds);
02586     }
02587   else
02588     {
02589       /* We have to convert the DBusPollFD to an array of
02590        * struct pollfd, poll, and convert back.
02591        */
02592       _dbus_warn ("didn't implement poll() properly for this system yet\n");
02593       return -1;
02594     }
02595 #else /* ! HAVE_POLL */
02596 
02597   fd_set read_set, write_set, err_set;
02598   int max_fd = 0;
02599   int i;
02600   struct timeval tv;
02601   int ready;
02602 
02603   FD_ZERO (&read_set);
02604   FD_ZERO (&write_set);
02605   FD_ZERO (&err_set);
02606 
02607   for (i = 0; i < n_fds; i++)
02608     {
02609       DBusPollFD *fdp = &fds[i];
02610 
02611       if (fdp->events & _DBUS_POLLIN)
02612         FD_SET (fdp->fd, &read_set);
02613 
02614       if (fdp->events & _DBUS_POLLOUT)
02615         FD_SET (fdp->fd, &write_set);
02616 
02617       FD_SET (fdp->fd, &err_set);
02618 
02619       max_fd = MAX (max_fd, fdp->fd);
02620     }
02621 
02622   tv.tv_sec = timeout_milliseconds / 1000;
02623   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02624 
02625   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02626                   timeout_milliseconds < 0 ? NULL : &tv);
02627 
02628   if (ready > 0)
02629     {
02630       for (i = 0; i < n_fds; i++)
02631         {
02632           DBusPollFD *fdp = &fds[i];
02633 
02634           fdp->revents = 0;
02635 
02636           if (FD_ISSET (fdp->fd, &read_set))
02637             fdp->revents |= _DBUS_POLLIN;
02638 
02639           if (FD_ISSET (fdp->fd, &write_set))
02640             fdp->revents |= _DBUS_POLLOUT;
02641 
02642           if (FD_ISSET (fdp->fd, &err_set))
02643             fdp->revents |= _DBUS_POLLERR;
02644         }
02645     }
02646 
02647   return ready;
02648 #endif
02649 }
02650 
02658 void
02659 _dbus_get_monotonic_time (long *tv_sec,
02660                           long *tv_usec)
02661 {
02662 #ifdef HAVE_MONOTONIC_CLOCK
02663   struct timespec ts;
02664   clock_gettime (CLOCK_MONOTONIC, &ts);
02665 
02666   if (tv_sec)
02667     *tv_sec = ts.tv_sec;
02668   if (tv_usec)
02669     *tv_usec = ts.tv_nsec / 1000;
02670 #else
02671   struct timeval t;
02672 
02673   gettimeofday (&t, NULL);
02674 
02675   if (tv_sec)
02676     *tv_sec = t.tv_sec;
02677   if (tv_usec)
02678     *tv_usec = t.tv_usec;
02679 #endif
02680 }
02681 
02689 void
02690 _dbus_get_real_time (long *tv_sec,
02691                      long *tv_usec)
02692 {
02693   struct timeval t;
02694 
02695   gettimeofday (&t, NULL);
02696 
02697   if (tv_sec)
02698     *tv_sec = t.tv_sec;
02699   if (tv_usec)
02700     *tv_usec = t.tv_usec;
02701 }
02702 
02711 dbus_bool_t
02712 _dbus_create_directory (const DBusString *filename,
02713                         DBusError        *error)
02714 {
02715   const char *filename_c;
02716 
02717   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02718 
02719   filename_c = _dbus_string_get_const_data (filename);
02720 
02721   if (mkdir (filename_c, 0700) < 0)
02722     {
02723       if (errno == EEXIST)
02724         return TRUE;
02725 
02726       dbus_set_error (error, DBUS_ERROR_FAILED,
02727                       "Failed to create directory %s: %s\n",
02728                       filename_c, _dbus_strerror (errno));
02729       return FALSE;
02730     }
02731   else
02732     return TRUE;
02733 }
02734 
02745 dbus_bool_t
02746 _dbus_concat_dir_and_file (DBusString       *dir,
02747                            const DBusString *next_component)
02748 {
02749   dbus_bool_t dir_ends_in_slash;
02750   dbus_bool_t file_starts_with_slash;
02751 
02752   if (_dbus_string_get_length (dir) == 0 ||
02753       _dbus_string_get_length (next_component) == 0)
02754     return TRUE;
02755 
02756   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02757                                                     _dbus_string_get_length (dir) - 1);
02758 
02759   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02760 
02761   if (dir_ends_in_slash && file_starts_with_slash)
02762     {
02763       _dbus_string_shorten (dir, 1);
02764     }
02765   else if (!(dir_ends_in_slash || file_starts_with_slash))
02766     {
02767       if (!_dbus_string_append_byte (dir, '/'))
02768         return FALSE;
02769     }
02770 
02771   return _dbus_string_copy (next_component, 0, dir,
02772                             _dbus_string_get_length (dir));
02773 }
02774 
02776 #define NANOSECONDS_PER_SECOND       1000000000
02777 
02778 #define MICROSECONDS_PER_SECOND      1000000
02779 
02780 #define MILLISECONDS_PER_SECOND      1000
02781 
02782 #define NANOSECONDS_PER_MILLISECOND  1000000
02783 
02784 #define MICROSECONDS_PER_MILLISECOND 1000
02785 
02790 void
02791 _dbus_sleep_milliseconds (int milliseconds)
02792 {
02793 #ifdef HAVE_NANOSLEEP
02794   struct timespec req;
02795   struct timespec rem;
02796 
02797   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02798   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02799   rem.tv_sec = 0;
02800   rem.tv_nsec = 0;
02801 
02802   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02803     req = rem;
02804 #elif defined (HAVE_USLEEP)
02805   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02806 #else /* ! HAVE_USLEEP */
02807   sleep (MAX (milliseconds / 1000, 1));
02808 #endif
02809 }
02810 
02811 static dbus_bool_t
02812 _dbus_generate_pseudorandom_bytes (DBusString *str,
02813                                    int         n_bytes)
02814 {
02815   int old_len;
02816   char *p;
02817 
02818   old_len = _dbus_string_get_length (str);
02819 
02820   if (!_dbus_string_lengthen (str, n_bytes))
02821     return FALSE;
02822 
02823   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02824 
02825   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02826 
02827   return TRUE;
02828 }
02829 
02838 dbus_bool_t
02839 _dbus_generate_random_bytes (DBusString *str,
02840                              int         n_bytes)
02841 {
02842   int old_len;
02843   int fd;
02844 
02845   /* FALSE return means "no memory", if it could
02846    * mean something else then we'd need to return
02847    * a DBusError. So we always fall back to pseudorandom
02848    * if the I/O fails.
02849    */
02850 
02851   old_len = _dbus_string_get_length (str);
02852   fd = -1;
02853 
02854   /* note, urandom on linux will fall back to pseudorandom */
02855   fd = open ("/dev/urandom", O_RDONLY);
02856   if (fd < 0)
02857     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02858 
02859   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02860 
02861   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02862     {
02863       _dbus_close (fd, NULL);
02864       _dbus_string_set_length (str, old_len);
02865       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02866     }
02867 
02868   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02869                  n_bytes);
02870 
02871   _dbus_close (fd, NULL);
02872 
02873   return TRUE;
02874 }
02875 
02881 void
02882 _dbus_exit (int code)
02883 {
02884   _exit (code);
02885 }
02886 
02895 const char*
02896 _dbus_strerror (int error_number)
02897 {
02898   const char *msg;
02899 
02900   msg = strerror (error_number);
02901   if (msg == NULL)
02902     msg = "unknown";
02903 
02904   return msg;
02905 }
02906 
02910 void
02911 _dbus_disable_sigpipe (void)
02912 {
02913   signal (SIGPIPE, SIG_IGN);
02914 }
02915 
02923 void
02924 _dbus_fd_set_close_on_exec (intptr_t fd)
02925 {
02926   int val;
02927 
02928   val = fcntl (fd, F_GETFD, 0);
02929 
02930   if (val < 0)
02931     return;
02932 
02933   val |= FD_CLOEXEC;
02934 
02935   fcntl (fd, F_SETFD, val);
02936 }
02937 
02945 dbus_bool_t
02946 _dbus_close (int        fd,
02947              DBusError *error)
02948 {
02949   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02950 
02951  again:
02952   if (close (fd) < 0)
02953     {
02954       if (errno == EINTR)
02955         goto again;
02956 
02957       dbus_set_error (error, _dbus_error_from_errno (errno),
02958                       "Could not close fd %d", fd);
02959       return FALSE;
02960     }
02961 
02962   return TRUE;
02963 }
02964 
02972 int
02973 _dbus_dup(int        fd,
02974           DBusError *error)
02975 {
02976   int new_fd;
02977 
02978 #ifdef F_DUPFD_CLOEXEC
02979   dbus_bool_t cloexec_done;
02980 
02981   new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
02982   cloexec_done = new_fd >= 0;
02983 
02984   if (new_fd < 0 && errno == EINVAL)
02985 #endif
02986     {
02987       new_fd = fcntl(fd, F_DUPFD, 3);
02988     }
02989 
02990   if (new_fd < 0) {
02991 
02992     dbus_set_error (error, _dbus_error_from_errno (errno),
02993                     "Could not duplicate fd %d", fd);
02994     return -1;
02995   }
02996 
02997 #ifdef F_DUPFD_CLOEXEC
02998   if (!cloexec_done)
02999 #endif
03000     {
03001       _dbus_fd_set_close_on_exec(new_fd);
03002     }
03003 
03004   return new_fd;
03005 }
03006 
03014 dbus_bool_t
03015 _dbus_set_fd_nonblocking (int             fd,
03016                           DBusError      *error)
03017 {
03018   int val;
03019 
03020   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03021 
03022   val = fcntl (fd, F_GETFL, 0);
03023   if (val < 0)
03024     {
03025       dbus_set_error (error, _dbus_error_from_errno (errno),
03026                       "Failed to get flags from file descriptor %d: %s",
03027                       fd, _dbus_strerror (errno));
03028       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03029                      _dbus_strerror (errno));
03030       return FALSE;
03031     }
03032 
03033   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03034     {
03035       dbus_set_error (error, _dbus_error_from_errno (errno),
03036                       "Failed to set nonblocking flag of file descriptor %d: %s",
03037                       fd, _dbus_strerror (errno));
03038       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03039                      fd, _dbus_strerror (errno));
03040 
03041       return FALSE;
03042     }
03043 
03044   return TRUE;
03045 }
03046 
03052 void
03053 _dbus_print_backtrace (void)
03054 {
03055 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
03056   void *bt[500];
03057   int bt_size;
03058   int i;
03059   char **syms;
03060 
03061   bt_size = backtrace (bt, 500);
03062 
03063   syms = backtrace_symbols (bt, bt_size);
03064 
03065   i = 0;
03066   while (i < bt_size)
03067     {
03068       /* don't use dbus_warn since it can _dbus_abort() */
03069       fprintf (stderr, "  %s\n", syms[i]);
03070       ++i;
03071     }
03072   fflush (stderr);
03073 
03074   free (syms);
03075 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
03076   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
03077 #else
03078   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
03079 #endif
03080 }
03081 
03094 dbus_bool_t
03095 _dbus_full_duplex_pipe (int        *fd1,
03096                         int        *fd2,
03097                         dbus_bool_t blocking,
03098                         DBusError  *error)
03099 {
03100 #ifdef HAVE_SOCKETPAIR
03101   int fds[2];
03102   int retval;
03103 
03104 #ifdef SOCK_CLOEXEC
03105   dbus_bool_t cloexec_done;
03106 
03107   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
03108   cloexec_done = retval >= 0;
03109 
03110   if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
03111 #endif
03112     {
03113       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
03114     }
03115 
03116   if (retval < 0)
03117     {
03118       dbus_set_error (error, _dbus_error_from_errno (errno),
03119                       "Could not create full-duplex pipe");
03120       return FALSE;
03121     }
03122 
03123   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03124 
03125 #ifdef SOCK_CLOEXEC
03126   if (!cloexec_done)
03127 #endif
03128     {
03129       _dbus_fd_set_close_on_exec (fds[0]);
03130       _dbus_fd_set_close_on_exec (fds[1]);
03131     }
03132 
03133   if (!blocking &&
03134       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03135        !_dbus_set_fd_nonblocking (fds[1], NULL)))
03136     {
03137       dbus_set_error (error, _dbus_error_from_errno (errno),
03138                       "Could not set full-duplex pipe nonblocking");
03139 
03140       _dbus_close (fds[0], NULL);
03141       _dbus_close (fds[1], NULL);
03142 
03143       return FALSE;
03144     }
03145 
03146   *fd1 = fds[0];
03147   *fd2 = fds[1];
03148 
03149   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03150                  *fd1, *fd2);
03151 
03152   return TRUE;
03153 #else
03154   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03155   dbus_set_error (error, DBUS_ERROR_FAILED,
03156                   "_dbus_full_duplex_pipe() not implemented on this OS");
03157   return FALSE;
03158 #endif
03159 }
03160 
03169 int
03170 _dbus_printf_string_upper_bound (const char *format,
03171                                  va_list     args)
03172 {
03173   char static_buf[1024];
03174   int bufsize = sizeof (static_buf);
03175   int len;
03176   va_list args_copy;
03177 
03178   DBUS_VA_COPY (args_copy, args);
03179   len = vsnprintf (static_buf, bufsize, format, args_copy);
03180   va_end (args_copy);
03181 
03182   /* If vsnprintf() returned non-negative, then either the string fits in
03183    * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
03184    * returns the number of characters that were needed, or this OS returns the
03185    * truncated length.
03186    *
03187    * We ignore the possibility that snprintf might just ignore the length and
03188    * overrun the buffer (64-bit Solaris 7), because that's pathological.
03189    * If your libc is really that bad, come back when you have a better one. */
03190   if (len == bufsize)
03191     {
03192       /* This could be the truncated length (Tru64 and IRIX have this bug),
03193        * or the real length could be coincidentally the same. Which is it?
03194        * If vsnprintf returns the truncated length, we'll go to the slow
03195        * path. */
03196       DBUS_VA_COPY (args_copy, args);
03197 
03198       if (vsnprintf (static_buf, 1, format, args_copy) == 1)
03199         len = -1;
03200 
03201       va_end (args_copy);
03202     }
03203 
03204   /* If vsnprintf() returned negative, we have to do more work.
03205    * HP-UX returns negative. */
03206   while (len < 0)
03207     {
03208       char *buf;
03209 
03210       bufsize *= 2;
03211 
03212       buf = dbus_malloc (bufsize);
03213 
03214       if (buf == NULL)
03215         return -1;
03216 
03217       DBUS_VA_COPY (args_copy, args);
03218       len = vsnprintf (buf, bufsize, format, args_copy);
03219       va_end (args_copy);
03220 
03221       dbus_free (buf);
03222 
03223       /* If the reported length is exactly the buffer size, round up to the
03224        * next size, in case vsnprintf has been returning the truncated
03225        * length */
03226       if (len == bufsize)
03227         len = -1;
03228     }
03229 
03230   return len;
03231 }
03232 
03239 const char*
03240 _dbus_get_tmpdir(void)
03241 {
03242   static const char* tmpdir = NULL;
03243 
03244   if (tmpdir == NULL)
03245     {
03246       /* TMPDIR is what glibc uses, then
03247        * glibc falls back to the P_tmpdir macro which
03248        * just expands to "/tmp"
03249        */
03250       if (tmpdir == NULL)
03251         tmpdir = getenv("TMPDIR");
03252 
03253       /* These two env variables are probably
03254        * broken, but maybe some OS uses them?
03255        */
03256       if (tmpdir == NULL)
03257         tmpdir = getenv("TMP");
03258       if (tmpdir == NULL)
03259         tmpdir = getenv("TEMP");
03260 
03261       /* And this is the sane fallback. */
03262       if (tmpdir == NULL)
03263         tmpdir = "/tmp";
03264     }
03265 
03266   _dbus_assert(tmpdir != NULL);
03267 
03268   return tmpdir;
03269 }
03270 
03290 static dbus_bool_t
03291 _read_subprocess_line_argv (const char *progpath,
03292                             dbus_bool_t path_fallback,
03293                             char       * const *argv,
03294                             DBusString *result,
03295                             DBusError  *error)
03296 {
03297   int result_pipe[2] = { -1, -1 };
03298   int errors_pipe[2] = { -1, -1 };
03299   pid_t pid;
03300   int ret;
03301   int status;
03302   int orig_len;
03303 
03304   dbus_bool_t retval;
03305   sigset_t new_set, old_set;
03306 
03307   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03308   retval = FALSE;
03309 
03310   /* We need to block any existing handlers for SIGCHLD temporarily; they
03311    * will cause waitpid() below to fail.
03312    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
03313    */
03314   sigemptyset (&new_set);
03315   sigaddset (&new_set, SIGCHLD);
03316   sigprocmask (SIG_BLOCK, &new_set, &old_set);
03317 
03318   orig_len = _dbus_string_get_length (result);
03319 
03320 #define READ_END        0
03321 #define WRITE_END       1
03322   if (pipe (result_pipe) < 0)
03323     {
03324       dbus_set_error (error, _dbus_error_from_errno (errno),
03325                       "Failed to create a pipe to call %s: %s",
03326                       progpath, _dbus_strerror (errno));
03327       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03328                      progpath, _dbus_strerror (errno));
03329       goto out;
03330     }
03331   if (pipe (errors_pipe) < 0)
03332     {
03333       dbus_set_error (error, _dbus_error_from_errno (errno),
03334                       "Failed to create a pipe to call %s: %s",
03335                       progpath, _dbus_strerror (errno));
03336       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03337                      progpath, _dbus_strerror (errno));
03338       goto out;
03339     }
03340 
03341   pid = fork ();
03342   if (pid < 0)
03343     {
03344       dbus_set_error (error, _dbus_error_from_errno (errno),
03345                       "Failed to fork() to call %s: %s",
03346                       progpath, _dbus_strerror (errno));
03347       _dbus_verbose ("Failed to fork() to call %s: %s\n",
03348                      progpath, _dbus_strerror (errno));
03349       goto out;
03350     }
03351 
03352   if (pid == 0)
03353     {
03354       /* child process */
03355       int fd;
03356 
03357       fd = open ("/dev/null", O_RDWR);
03358       if (fd == -1)
03359         /* huh?! can't open /dev/null? */
03360         _exit (1);
03361 
03362       _dbus_verbose ("/dev/null fd %d opened\n", fd);
03363 
03364       /* set-up stdXXX */
03365       close (result_pipe[READ_END]);
03366       close (errors_pipe[READ_END]);
03367       close (0);                /* close stdin */
03368       close (1);                /* close stdout */
03369       close (2);                /* close stderr */
03370 
03371       if (dup2 (fd, 0) == -1)
03372         _exit (1);
03373       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03374         _exit (1);
03375       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03376         _exit (1);
03377 
03378       _dbus_close_all ();
03379 
03380       sigprocmask (SIG_SETMASK, &old_set, NULL);
03381 
03382       /* If it looks fully-qualified, try execv first */
03383       if (progpath[0] == '/')
03384         {
03385           execv (progpath, argv);
03386           /* Ok, that failed.  Now if path_fallback is given, let's
03387            * try unqualified.  This is mostly a hack to work
03388            * around systems which ship dbus-launch in /usr/bin
03389            * but everything else in /bin (because dbus-launch
03390            * depends on X11).
03391            */
03392           if (path_fallback)
03393             /* We must have a slash, because we checked above */
03394             execvp (strrchr (progpath, '/')+1, argv);
03395         }
03396       else
03397         execvp (progpath, argv);
03398 
03399       /* still nothing, we failed */
03400       _exit (1);
03401     }
03402 
03403   /* parent process */
03404   close (result_pipe[WRITE_END]);
03405   close (errors_pipe[WRITE_END]);
03406   result_pipe[WRITE_END] = -1;
03407   errors_pipe[WRITE_END] = -1;
03408 
03409   ret = 0;
03410   do
03411     {
03412       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03413     }
03414   while (ret > 0);
03415 
03416   /* reap the child process to avoid it lingering as zombie */
03417   do
03418     {
03419       ret = waitpid (pid, &status, 0);
03420     }
03421   while (ret == -1 && errno == EINTR);
03422 
03423   /* We succeeded if the process exited with status 0 and
03424      anything was read */
03425   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03426     {
03427       /* The process ended with error */
03428       DBusString error_message;
03429       if (!_dbus_string_init (&error_message))
03430         {
03431           _DBUS_SET_OOM (error);
03432           goto out;
03433         }
03434 
03435       ret = 0;
03436       do
03437         {
03438           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03439         }
03440       while (ret > 0);
03441 
03442       _dbus_string_set_length (result, orig_len);
03443       if (_dbus_string_get_length (&error_message) > 0)
03444         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03445                         "%s terminated abnormally with the following error: %s",
03446                         progpath, _dbus_string_get_data (&error_message));
03447       else
03448         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03449                         "%s terminated abnormally without any error message",
03450                         progpath);
03451       goto out;
03452     }
03453 
03454   retval = TRUE;
03455 
03456  out:
03457   sigprocmask (SIG_SETMASK, &old_set, NULL);
03458 
03459   if (retval)
03460     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03461   else
03462     _DBUS_ASSERT_ERROR_IS_SET (error);
03463 
03464   if (result_pipe[0] != -1)
03465     close (result_pipe[0]);
03466   if (result_pipe[1] != -1)
03467     close (result_pipe[1]);
03468   if (errors_pipe[0] != -1)
03469     close (errors_pipe[0]);
03470   if (errors_pipe[1] != -1)
03471     close (errors_pipe[1]);
03472 
03473   return retval;
03474 }
03475 
03487 dbus_bool_t
03488 _dbus_get_autolaunch_address (const char *scope,
03489                               DBusString *address,
03490                               DBusError  *error)
03491 {
03492 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
03493   /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
03494    * but that's done elsewhere, and if it worked, this function wouldn't
03495    * be called.) */
03496   const char *display;
03497   static char *argv[6];
03498   int i;
03499   DBusString uuid;
03500   dbus_bool_t retval;
03501 
03502   if (_dbus_check_setuid ())
03503     {
03504       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03505                             "Unable to autolaunch when setuid");
03506       return FALSE;
03507     }
03508 
03509   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03510   retval = FALSE;
03511 
03512   /* fd.o #19997: if $DISPLAY isn't set to something useful, then
03513    * dbus-launch-x11 is just going to fail. Rather than trying to
03514    * run it, we might as well bail out early with a nice error. */
03515   display = _dbus_getenv ("DISPLAY");
03516 
03517   if (display == NULL || display[0] == '\0')
03518     {
03519       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03520           "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
03521       return FALSE;
03522     }
03523 
03524   if (!_dbus_string_init (&uuid))
03525     {
03526       _DBUS_SET_OOM (error);
03527       return FALSE;
03528     }
03529 
03530   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03531     {
03532       _DBUS_SET_OOM (error);
03533       goto out;
03534     }
03535 
03536   i = 0;
03537   argv[i] = "dbus-launch";
03538   ++i;
03539   argv[i] = "--autolaunch";
03540   ++i;
03541   argv[i] = _dbus_string_get_data (&uuid);
03542   ++i;
03543   argv[i] = "--binary-syntax";
03544   ++i;
03545   argv[i] = "--close-stderr";
03546   ++i;
03547   argv[i] = NULL;
03548   ++i;
03549 
03550   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03551 
03552   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03553                                        TRUE,
03554                                        argv, address, error);
03555 
03556  out:
03557   _dbus_string_free (&uuid);
03558   return retval;
03559 #else
03560   dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03561       "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
03562       "set your DBUS_SESSION_BUS_ADDRESS instead");
03563   return FALSE;
03564 #endif
03565 }
03566 
03585 dbus_bool_t
03586 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03587                                dbus_bool_t create_if_not_found,
03588                                DBusError  *error)
03589 {
03590   DBusString filename;
03591   dbus_bool_t b;
03592 
03593   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03594 
03595   b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03596   if (b)
03597     return TRUE;
03598 
03599   dbus_error_free (error);
03600 
03601   /* Fallback to the system machine ID */
03602   _dbus_string_init_const (&filename, "/etc/machine-id");
03603   return _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
03604 }
03605 
03606 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03607 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03608 
03615 dbus_bool_t
03616 _dbus_lookup_launchd_socket (DBusString *socket_path,
03617                              const char *launchd_env_var,
03618                              DBusError  *error)
03619 {
03620 #ifdef DBUS_ENABLE_LAUNCHD
03621   char *argv[4];
03622   int i;
03623 
03624   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03625 
03626   if (_dbus_check_setuid ())
03627     {
03628       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03629                             "Unable to find launchd socket when setuid");
03630       return FALSE;
03631     }
03632 
03633   i = 0;
03634   argv[i] = "launchctl";
03635   ++i;
03636   argv[i] = "getenv";
03637   ++i;
03638   argv[i] = (char*)launchd_env_var;
03639   ++i;
03640   argv[i] = NULL;
03641   ++i;
03642 
03643   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03644 
03645   if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
03646     {
03647       return FALSE;
03648     }
03649 
03650   /* no error, but no result either */
03651   if (_dbus_string_get_length(socket_path) == 0)
03652     {
03653       return FALSE;
03654     }
03655 
03656   /* strip the carriage-return */
03657   _dbus_string_shorten(socket_path, 1);
03658   return TRUE;
03659 #else /* DBUS_ENABLE_LAUNCHD */
03660   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03661                 "can't lookup socket from launchd; launchd support not compiled in");
03662   return FALSE;
03663 #endif
03664 }
03665 
03666 #ifdef DBUS_ENABLE_LAUNCHD
03667 static dbus_bool_t
03668 _dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
03669 {
03670   dbus_bool_t valid_socket;
03671   DBusString socket_path;
03672 
03673   if (_dbus_check_setuid ())
03674     {
03675       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03676                             "Unable to find launchd socket when setuid");
03677       return FALSE;
03678     }
03679 
03680   if (!_dbus_string_init (&socket_path))
03681     {
03682       _DBUS_SET_OOM (error);
03683       return FALSE;
03684     }
03685 
03686   valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
03687 
03688   if (dbus_error_is_set(error))
03689     {
03690       _dbus_string_free(&socket_path);
03691       return FALSE;
03692     }
03693 
03694   if (!valid_socket)
03695     {
03696       dbus_set_error(error, "no socket path",
03697                 "launchd did not provide a socket path, "
03698                 "verify that org.freedesktop.dbus-session.plist is loaded!");
03699       _dbus_string_free(&socket_path);
03700       return FALSE;
03701     }
03702   if (!_dbus_string_append (address, "unix:path="))
03703     {
03704       _DBUS_SET_OOM (error);
03705       _dbus_string_free(&socket_path);
03706       return FALSE;
03707     }
03708   if (!_dbus_string_copy (&socket_path, 0, address,
03709                           _dbus_string_get_length (address)))
03710     {
03711       _DBUS_SET_OOM (error);
03712       _dbus_string_free(&socket_path);
03713       return FALSE;
03714     }
03715 
03716   _dbus_string_free(&socket_path);
03717   return TRUE;
03718 }
03719 #endif
03720 
03740 dbus_bool_t
03741 _dbus_lookup_session_address (dbus_bool_t *supported,
03742                               DBusString  *address,
03743                               DBusError   *error)
03744 {
03745 #ifdef DBUS_ENABLE_LAUNCHD
03746   *supported = TRUE;
03747   return _dbus_lookup_session_address_launchd (address, error);
03748 #else
03749   /* On non-Mac Unix platforms, if the session address isn't already
03750    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03751    * fall back to the autolaunch: global default; see
03752    * init_session_address in dbus/dbus-bus.c. */
03753   *supported = FALSE;
03754   return TRUE;
03755 #endif
03756 }
03757 
03775 dbus_bool_t
03776 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03777 {
03778   const char *xdg_data_home;
03779   const char *xdg_data_dirs;
03780   DBusString servicedir_path;
03781 
03782   if (!_dbus_string_init (&servicedir_path))
03783     return FALSE;
03784 
03785   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03786   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03787 
03788   if (xdg_data_home != NULL)
03789     {
03790       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03791         goto oom;
03792     }
03793   else
03794     {
03795       const DBusString *homedir;
03796       DBusString local_share;
03797 
03798       if (!_dbus_homedir_from_current_process (&homedir))
03799         goto oom;
03800 
03801       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03802         goto oom;
03803 
03804       _dbus_string_init_const (&local_share, "/.local/share");
03805       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03806         goto oom;
03807     }
03808 
03809   if (!_dbus_string_append (&servicedir_path, ":"))
03810     goto oom;
03811 
03812   if (xdg_data_dirs != NULL)
03813     {
03814       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03815         goto oom;
03816 
03817       if (!_dbus_string_append (&servicedir_path, ":"))
03818         goto oom;
03819     }
03820   else
03821     {
03822       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03823         goto oom;
03824     }
03825 
03826   /*
03827    * add configured datadir to defaults
03828    * this may be the same as an xdg dir
03829    * however the config parser should take
03830    * care of duplicates
03831    */
03832   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
03833     goto oom;
03834 
03835   if (!_dbus_split_paths_and_append (&servicedir_path,
03836                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03837                                      dirs))
03838     goto oom;
03839 
03840   _dbus_string_free (&servicedir_path);
03841   return TRUE;
03842 
03843  oom:
03844   _dbus_string_free (&servicedir_path);
03845   return FALSE;
03846 }
03847 
03848 
03867 dbus_bool_t
03868 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03869 {
03870   /*
03871    * DBUS_DATADIR may be the same as one of the standard directories. However,
03872    * the config parser should take care of the duplicates.
03873    *
03874    * Also, append /lib as counterpart of /usr/share on the root
03875    * directory (the root directory does not know /share), in order to
03876    * facilitate early boot system bus activation where /usr might not
03877    * be available.
03878    */
03879   static const char standard_search_path[] =
03880     "/usr/local/share:"
03881     "/usr/share:"
03882     DBUS_DATADIR ":"
03883     "/lib";
03884   DBusString servicedir_path;
03885 
03886   _dbus_string_init_const (&servicedir_path, standard_search_path);
03887 
03888   return _dbus_split_paths_and_append (&servicedir_path,
03889                                        DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03890                                        dirs);
03891 }
03892 
03901 dbus_bool_t
03902 _dbus_append_system_config_file (DBusString *str)
03903 {
03904   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03905 }
03906 
03913 dbus_bool_t
03914 _dbus_append_session_config_file (DBusString *str)
03915 {
03916   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03917 }
03918 
03926 void
03927 _dbus_flush_caches (void)
03928 {
03929   _dbus_user_database_flush_system ();
03930 }
03931 
03945 dbus_bool_t
03946 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03947                                                 DBusCredentials *credentials)
03948 {
03949   DBusString homedir;
03950   DBusString dotdir;
03951   dbus_uid_t uid;
03952 
03953   _dbus_assert (credentials != NULL);
03954   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03955 
03956   if (!_dbus_string_init (&homedir))
03957     return FALSE;
03958 
03959   uid = _dbus_credentials_get_unix_uid (credentials);
03960   _dbus_assert (uid != DBUS_UID_UNSET);
03961 
03962   if (!_dbus_homedir_from_uid (uid, &homedir))
03963     goto failed;
03964 
03965 #ifdef DBUS_BUILD_TESTS
03966   {
03967     const char *override;
03968 
03969     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03970     if (override != NULL && *override != '\0')
03971       {
03972         _dbus_string_set_length (&homedir, 0);
03973         if (!_dbus_string_append (&homedir, override))
03974           goto failed;
03975 
03976         _dbus_verbose ("Using fake homedir for testing: %s\n",
03977                        _dbus_string_get_const_data (&homedir));
03978       }
03979     else
03980       {
03981         static dbus_bool_t already_warned = FALSE;
03982         if (!already_warned)
03983           {
03984             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03985             already_warned = TRUE;
03986           }
03987       }
03988   }
03989 #endif
03990 
03991   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03992   if (!_dbus_concat_dir_and_file (&homedir,
03993                                   &dotdir))
03994     goto failed;
03995 
03996   if (!_dbus_string_copy (&homedir, 0,
03997                           directory, _dbus_string_get_length (directory))) {
03998     goto failed;
03999   }
04000 
04001   _dbus_string_free (&homedir);
04002   return TRUE;
04003 
04004  failed:
04005   _dbus_string_free (&homedir);
04006   return FALSE;
04007 }
04008 
04009 //PENDING(kdab) docs
04010 dbus_bool_t
04011 _dbus_daemon_publish_session_bus_address (const char* addr,
04012                                           const char *scope)
04013 {
04014   return TRUE;
04015 }
04016 
04017 //PENDING(kdab) docs
04018 void
04019 _dbus_daemon_unpublish_session_bus_address (void)
04020 {
04021 
04022 }
04023 
04030 dbus_bool_t
04031 _dbus_get_is_errno_eagain_or_ewouldblock (void)
04032 {
04033   return errno == EAGAIN || errno == EWOULDBLOCK;
04034 }
04035 
04043 dbus_bool_t
04044 _dbus_delete_directory (const DBusString *filename,
04045                         DBusError        *error)
04046 {
04047   const char *filename_c;
04048 
04049   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
04050 
04051   filename_c = _dbus_string_get_const_data (filename);
04052 
04053   if (rmdir (filename_c) != 0)
04054     {
04055       dbus_set_error (error, DBUS_ERROR_FAILED,
04056                       "Failed to remove directory %s: %s\n",
04057                       filename_c, _dbus_strerror (errno));
04058       return FALSE;
04059     }
04060 
04061   return TRUE;
04062 }
04063 
04071 dbus_bool_t
04072 _dbus_socket_can_pass_unix_fd(int fd) {
04073 
04074 #ifdef SCM_RIGHTS
04075   union {
04076     struct sockaddr sa;
04077     struct sockaddr_storage storage;
04078     struct sockaddr_un un;
04079   } sa_buf;
04080 
04081   socklen_t sa_len = sizeof(sa_buf);
04082 
04083   _DBUS_ZERO(sa_buf);
04084 
04085   if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
04086     return FALSE;
04087 
04088   return sa_buf.sa.sa_family == AF_UNIX;
04089 
04090 #else
04091   return FALSE;
04092 
04093 #endif
04094 }
04095 
04096 
04097 /*
04098  * replaces the term DBUS_PREFIX in configure_time_path by the
04099  * current dbus installation directory. On unix this function is a noop
04100  *
04101  * @param configure_time_path
04102  * @return real path
04103  */
04104 const char *
04105 _dbus_replace_install_prefix (const char *configure_time_path)
04106 {
04107   return configure_time_path;
04108 }
04109 
04114 void
04115 _dbus_close_all (void)
04116 {
04117   int maxfds, i;
04118 
04119 #ifdef __linux__
04120   DIR *d;
04121 
04122   /* On Linux we can optimize this a bit if /proc is available. If it
04123      isn't available, fall back to the brute force way. */
04124 
04125   d = opendir ("/proc/self/fd");
04126   if (d)
04127     {
04128       for (;;)
04129         {
04130           struct dirent buf, *de;
04131           int k, fd;
04132           long l;
04133           char *e = NULL;
04134 
04135           k = readdir_r (d, &buf, &de);
04136           if (k != 0 || !de)
04137             break;
04138 
04139           if (de->d_name[0] == '.')
04140             continue;
04141 
04142           errno = 0;
04143           l = strtol (de->d_name, &e, 10);
04144           if (errno != 0 || e == NULL || *e != '\0')
04145             continue;
04146 
04147           fd = (int) l;
04148           if (fd < 3)
04149             continue;
04150 
04151           if (fd == dirfd (d))
04152             continue;
04153 
04154           close (fd);
04155         }
04156 
04157       closedir (d);
04158       return;
04159     }
04160 #endif
04161 
04162   maxfds = sysconf (_SC_OPEN_MAX);
04163 
04164   /* Pick something reasonable if for some reason sysconf says
04165    * unlimited.
04166    */
04167   if (maxfds < 0)
04168     maxfds = 1024;
04169 
04170   /* close all inherited fds */
04171   for (i = 3; i < maxfds; i++)
04172     close (i);
04173 }
04174 
04184 dbus_bool_t
04185 _dbus_check_setuid (void)
04186 {
04187   /* TODO: get __libc_enable_secure exported from glibc.
04188    * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
04189    */
04190 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
04191   {
04192     /* See glibc/include/unistd.h */
04193     extern int __libc_enable_secure;
04194     return __libc_enable_secure;
04195   }
04196 #elif defined(HAVE_ISSETUGID)
04197   /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
04198   return issetugid ();
04199 #else
04200   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
04201   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
04202 
04203   static dbus_bool_t check_setuid_initialised;
04204   static dbus_bool_t is_setuid;
04205 
04206   if (_DBUS_UNLIKELY (!check_setuid_initialised))
04207     {
04208 #ifdef HAVE_GETRESUID
04209       if (getresuid (&ruid, &euid, &suid) != 0 ||
04210           getresgid (&rgid, &egid, &sgid) != 0)
04211 #endif /* HAVE_GETRESUID */
04212         {
04213           suid = ruid = getuid ();
04214           sgid = rgid = getgid ();
04215           euid = geteuid ();
04216           egid = getegid ();
04217         }
04218 
04219       check_setuid_initialised = TRUE;
04220       is_setuid = (ruid != euid || ruid != suid ||
04221                    rgid != egid || rgid != sgid);
04222 
04223     }
04224   return is_setuid;
04225 #endif
04226 }
04227 
04228 /* tests in dbus-sysdeps-util.c */