D-Bus  1.6.18
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  again:
00319 
00320   bytes_read = recvmsg(fd, &m, 0
00321 #ifdef MSG_CMSG_CLOEXEC
00322                        |MSG_CMSG_CLOEXEC
00323 #endif
00324                        );
00325 
00326   if (bytes_read < 0)
00327     {
00328       if (errno == EINTR)
00329         goto again;
00330       else
00331         {
00332           /* put length back (note that this doesn't actually realloc anything) */
00333           _dbus_string_set_length (buffer, start);
00334           return -1;
00335         }
00336     }
00337   else
00338     {
00339       struct cmsghdr *cm;
00340       dbus_bool_t found = FALSE;
00341 
00342       if (m.msg_flags & MSG_CTRUNC)
00343         {
00344           /* Hmm, apparently the control data was truncated. The bad
00345              thing is that we might have completely lost a couple of fds
00346              without chance to recover them. Hence let's treat this as a
00347              serious error. */
00348 
00349           errno = ENOSPC;
00350           _dbus_string_set_length (buffer, start);
00351           return -1;
00352         }
00353 
00354       for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
00355         if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
00356           {
00357             unsigned i;
00358 
00359             _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
00360             *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
00361 
00362             memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
00363             found = TRUE;
00364 
00365             /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
00366                worked, hence we need to go through this list and set
00367                CLOEXEC everywhere in any case */
00368             for (i = 0; i < *n_fds; i++)
00369               _dbus_fd_set_close_on_exec(fds[i]);
00370 
00371             break;
00372           }
00373 
00374       if (!found)
00375         *n_fds = 0;
00376 
00377       /* put length back (doesn't actually realloc) */
00378       _dbus_string_set_length (buffer, start + bytes_read);
00379 
00380 #if 0
00381       if (bytes_read > 0)
00382         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00383 #endif
00384 
00385       return bytes_read;
00386     }
00387 #endif
00388 }
00389 
00390 int
00391 _dbus_write_socket_with_unix_fds(int               fd,
00392                                  const DBusString *buffer,
00393                                  int               start,
00394                                  int               len,
00395                                  const int        *fds,
00396                                  int               n_fds) {
00397 
00398 #ifndef HAVE_UNIX_FD_PASSING
00399 
00400   if (n_fds > 0) {
00401     errno = ENOTSUP;
00402     return -1;
00403   }
00404 
00405   return _dbus_write_socket(fd, buffer, start, len);
00406 #else
00407   return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
00408 #endif
00409 }
00410 
00411 int
00412 _dbus_write_socket_with_unix_fds_two(int               fd,
00413                                      const DBusString *buffer1,
00414                                      int               start1,
00415                                      int               len1,
00416                                      const DBusString *buffer2,
00417                                      int               start2,
00418                                      int               len2,
00419                                      const int        *fds,
00420                                      int               n_fds) {
00421 
00422 #ifndef HAVE_UNIX_FD_PASSING
00423 
00424   if (n_fds > 0) {
00425     errno = ENOTSUP;
00426     return -1;
00427   }
00428 
00429   return _dbus_write_socket_two(fd,
00430                                 buffer1, start1, len1,
00431                                 buffer2, start2, len2);
00432 #else
00433 
00434   struct msghdr m;
00435   struct cmsghdr *cm;
00436   struct iovec iov[2];
00437   int bytes_written;
00438 
00439   _dbus_assert (len1 >= 0);
00440   _dbus_assert (len2 >= 0);
00441   _dbus_assert (n_fds >= 0);
00442 
00443   _DBUS_ZERO(iov);
00444   iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
00445   iov[0].iov_len = len1;
00446 
00447   if (buffer2)
00448     {
00449       iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
00450       iov[1].iov_len = len2;
00451     }
00452 
00453   _DBUS_ZERO(m);
00454   m.msg_iov = iov;
00455   m.msg_iovlen = buffer2 ? 2 : 1;
00456 
00457   if (n_fds > 0)
00458     {
00459       m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
00460       m.msg_control = alloca(m.msg_controllen);
00461       memset(m.msg_control, 0, m.msg_controllen);
00462 
00463       cm = CMSG_FIRSTHDR(&m);
00464       cm->cmsg_level = SOL_SOCKET;
00465       cm->cmsg_type = SCM_RIGHTS;
00466       cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
00467       memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
00468     }
00469 
00470  again:
00471 
00472   bytes_written = sendmsg (fd, &m, 0
00473 #if HAVE_DECL_MSG_NOSIGNAL
00474                            |MSG_NOSIGNAL
00475 #endif
00476                            );
00477 
00478   if (bytes_written < 0 && errno == EINTR)
00479     goto again;
00480 
00481 #if 0
00482   if (bytes_written > 0)
00483     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00484 #endif
00485 
00486   return bytes_written;
00487 #endif
00488 }
00489 
00503 int
00504 _dbus_write_socket_two (int               fd,
00505                         const DBusString *buffer1,
00506                         int               start1,
00507                         int               len1,
00508                         const DBusString *buffer2,
00509                         int               start2,
00510                         int               len2)
00511 {
00512 #if HAVE_DECL_MSG_NOSIGNAL
00513   struct iovec vectors[2];
00514   const char *data1;
00515   const char *data2;
00516   int bytes_written;
00517   struct msghdr m;
00518 
00519   _dbus_assert (buffer1 != NULL);
00520   _dbus_assert (start1 >= 0);
00521   _dbus_assert (start2 >= 0);
00522   _dbus_assert (len1 >= 0);
00523   _dbus_assert (len2 >= 0);
00524 
00525   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00526 
00527   if (buffer2 != NULL)
00528     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00529   else
00530     {
00531       data2 = NULL;
00532       start2 = 0;
00533       len2 = 0;
00534     }
00535 
00536   vectors[0].iov_base = (char*) data1;
00537   vectors[0].iov_len = len1;
00538   vectors[1].iov_base = (char*) data2;
00539   vectors[1].iov_len = len2;
00540 
00541   _DBUS_ZERO(m);
00542   m.msg_iov = vectors;
00543   m.msg_iovlen = data2 ? 2 : 1;
00544 
00545  again:
00546 
00547   bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
00548 
00549   if (bytes_written < 0 && errno == EINTR)
00550     goto again;
00551 
00552   return bytes_written;
00553 
00554 #else
00555   return _dbus_write_two (fd, buffer1, start1, len1,
00556                           buffer2, start2, len2);
00557 #endif
00558 }
00559 
00560 dbus_bool_t
00561 _dbus_socket_is_invalid (int fd)
00562 {
00563     return fd < 0 ? TRUE : FALSE;
00564 }
00565 
00582 int
00583 _dbus_read (int               fd,
00584             DBusString       *buffer,
00585             int               count)
00586 {
00587   int bytes_read;
00588   int start;
00589   char *data;
00590 
00591   _dbus_assert (count >= 0);
00592 
00593   start = _dbus_string_get_length (buffer);
00594 
00595   if (!_dbus_string_lengthen (buffer, count))
00596     {
00597       errno = ENOMEM;
00598       return -1;
00599     }
00600 
00601   data = _dbus_string_get_data_len (buffer, start, count);
00602 
00603  again:
00604 
00605   bytes_read = read (fd, data, count);
00606 
00607   if (bytes_read < 0)
00608     {
00609       if (errno == EINTR)
00610         goto again;
00611       else
00612         {
00613           /* put length back (note that this doesn't actually realloc anything) */
00614           _dbus_string_set_length (buffer, start);
00615           return -1;
00616         }
00617     }
00618   else
00619     {
00620       /* put length back (doesn't actually realloc) */
00621       _dbus_string_set_length (buffer, start + bytes_read);
00622 
00623 #if 0
00624       if (bytes_read > 0)
00625         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00626 #endif
00627 
00628       return bytes_read;
00629     }
00630 }
00631 
00642 int
00643 _dbus_write (int               fd,
00644              const DBusString *buffer,
00645              int               start,
00646              int               len)
00647 {
00648   const char *data;
00649   int bytes_written;
00650 
00651   data = _dbus_string_get_const_data_len (buffer, start, len);
00652 
00653  again:
00654 
00655   bytes_written = write (fd, data, len);
00656 
00657   if (bytes_written < 0 && errno == EINTR)
00658     goto again;
00659 
00660 #if 0
00661   if (bytes_written > 0)
00662     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00663 #endif
00664 
00665   return bytes_written;
00666 }
00667 
00688 int
00689 _dbus_write_two (int               fd,
00690                  const DBusString *buffer1,
00691                  int               start1,
00692                  int               len1,
00693                  const DBusString *buffer2,
00694                  int               start2,
00695                  int               len2)
00696 {
00697   _dbus_assert (buffer1 != NULL);
00698   _dbus_assert (start1 >= 0);
00699   _dbus_assert (start2 >= 0);
00700   _dbus_assert (len1 >= 0);
00701   _dbus_assert (len2 >= 0);
00702 
00703 #ifdef HAVE_WRITEV
00704   {
00705     struct iovec vectors[2];
00706     const char *data1;
00707     const char *data2;
00708     int bytes_written;
00709 
00710     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00711 
00712     if (buffer2 != NULL)
00713       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00714     else
00715       {
00716         data2 = NULL;
00717         start2 = 0;
00718         len2 = 0;
00719       }
00720 
00721     vectors[0].iov_base = (char*) data1;
00722     vectors[0].iov_len = len1;
00723     vectors[1].iov_base = (char*) data2;
00724     vectors[1].iov_len = len2;
00725 
00726   again:
00727 
00728     bytes_written = writev (fd,
00729                             vectors,
00730                             data2 ? 2 : 1);
00731 
00732     if (bytes_written < 0 && errno == EINTR)
00733       goto again;
00734 
00735     return bytes_written;
00736   }
00737 #else /* HAVE_WRITEV */
00738   {
00739     int ret1, ret2;
00740 
00741     ret1 = _dbus_write (fd, buffer1, start1, len1);
00742     if (ret1 == len1 && buffer2 != NULL)
00743       {
00744         ret2 = _dbus_write (fd, buffer2, start2, len2);
00745         if (ret2 < 0)
00746           ret2 = 0; /* we can't report an error as the first write was OK */
00747 
00748         return ret1 + ret2;
00749       }
00750     else
00751       return ret1;
00752   }
00753 #endif /* !HAVE_WRITEV */
00754 }
00755 
00756 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00757 
00787 int
00788 _dbus_connect_unix_socket (const char     *path,
00789                            dbus_bool_t     abstract,
00790                            DBusError      *error)
00791 {
00792   int fd;
00793   size_t path_len;
00794   struct sockaddr_un addr;
00795 
00796   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00797 
00798   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00799                  path, abstract);
00800 
00801 
00802   if (!_dbus_open_unix_socket (&fd, error))
00803     {
00804       _DBUS_ASSERT_ERROR_IS_SET(error);
00805       return -1;
00806     }
00807   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00808 
00809   _DBUS_ZERO (addr);
00810   addr.sun_family = AF_UNIX;
00811   path_len = strlen (path);
00812 
00813   if (abstract)
00814     {
00815 #ifdef HAVE_ABSTRACT_SOCKETS
00816       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00817       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00818 
00819       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00820         {
00821           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00822                       "Abstract socket name too long\n");
00823           _dbus_close (fd, NULL);
00824           return -1;
00825         }
00826 
00827       strncpy (&addr.sun_path[1], path, path_len);
00828       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00829 #else /* HAVE_ABSTRACT_SOCKETS */
00830       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00831                       "Operating system does not support abstract socket namespace\n");
00832       _dbus_close (fd, NULL);
00833       return -1;
00834 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00835     }
00836   else
00837     {
00838       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00839         {
00840           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00841                       "Socket name too long\n");
00842           _dbus_close (fd, NULL);
00843           return -1;
00844         }
00845 
00846       strncpy (addr.sun_path, path, path_len);
00847     }
00848 
00849   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00850     {
00851       dbus_set_error (error,
00852                       _dbus_error_from_errno (errno),
00853                       "Failed to connect to socket %s: %s",
00854                       path, _dbus_strerror (errno));
00855 
00856       _dbus_close (fd, NULL);
00857       return -1;
00858     }
00859 
00860   if (!_dbus_set_fd_nonblocking (fd, error))
00861     {
00862       _DBUS_ASSERT_ERROR_IS_SET (error);
00863 
00864       _dbus_close (fd, NULL);
00865       return -1;
00866     }
00867 
00868   return fd;
00869 }
00870 
00883 int
00884 _dbus_connect_exec (const char     *path,
00885                     char *const    argv[],
00886                     DBusError      *error)
00887 {
00888   int fds[2];
00889   pid_t pid;
00890   int retval;
00891   dbus_bool_t cloexec_done = 0;
00892 
00893   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00894 
00895   _dbus_verbose ("connecting to process %s\n", path);
00896 
00897 #ifdef SOCK_CLOEXEC
00898   retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
00899   cloexec_done = (retval >= 0);
00900 
00901   if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
00902 #endif
00903     {
00904       retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
00905     }
00906 
00907   if (retval < 0)
00908     {
00909       dbus_set_error (error,
00910                       _dbus_error_from_errno (errno),
00911                       "Failed to create socket pair: %s",
00912                       _dbus_strerror (errno));
00913       return -1;
00914     }
00915 
00916   if (!cloexec_done)
00917     {
00918       _dbus_fd_set_close_on_exec (fds[0]);
00919       _dbus_fd_set_close_on_exec (fds[1]);
00920     }
00921 
00922   pid = fork ();
00923   if (pid < 0)
00924     {
00925       dbus_set_error (error,
00926                       _dbus_error_from_errno (errno),
00927                       "Failed to fork() to call %s: %s",
00928                       path, _dbus_strerror (errno));
00929       close (fds[0]);
00930       close (fds[1]);
00931       return -1;
00932     }
00933 
00934   if (pid == 0)
00935     {
00936       /* child */
00937       close (fds[0]);
00938 
00939       dup2 (fds[1], STDIN_FILENO);
00940       dup2 (fds[1], STDOUT_FILENO);
00941 
00942       if (fds[1] != STDIN_FILENO &&
00943           fds[1] != STDOUT_FILENO)
00944         close (fds[1]);
00945 
00946       /* Inherit STDERR and the controlling terminal from the
00947          parent */
00948 
00949       _dbus_close_all ();
00950 
00951       execvp (path, argv);
00952 
00953       fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
00954 
00955       _exit(1);
00956     }
00957 
00958   /* parent */
00959   close (fds[1]);
00960 
00961   if (!_dbus_set_fd_nonblocking (fds[0], error))
00962     {
00963       _DBUS_ASSERT_ERROR_IS_SET (error);
00964 
00965       close (fds[0]);
00966       return -1;
00967     }
00968 
00969   return fds[0];
00970 }
00971 
00981 static dbus_bool_t
00982 _dbus_set_local_creds (int fd, dbus_bool_t on)
00983 {
00984   dbus_bool_t retval = TRUE;
00985 
00986 #if defined(HAVE_CMSGCRED)
00987   /* NOOP just to make sure only one codepath is used
00988    *      and to prefer CMSGCRED
00989    */
00990 #elif defined(LOCAL_CREDS)
00991   int val = on ? 1 : 0;
00992   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00993     {
00994       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00995       retval = FALSE;
00996     }
00997   else
00998     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00999                    on ? "enabled" : "disabled", fd);
01000 #endif
01001 
01002   return retval;
01003 }
01004 
01022 int
01023 _dbus_listen_unix_socket (const char     *path,
01024                           dbus_bool_t     abstract,
01025                           DBusError      *error)
01026 {
01027   int listen_fd;
01028   struct sockaddr_un addr;
01029   size_t path_len;
01030   unsigned int reuseaddr;
01031 
01032   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01033 
01034   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
01035                  path, abstract);
01036 
01037   if (!_dbus_open_unix_socket (&listen_fd, error))
01038     {
01039       _DBUS_ASSERT_ERROR_IS_SET(error);
01040       return -1;
01041     }
01042   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01043 
01044   _DBUS_ZERO (addr);
01045   addr.sun_family = AF_UNIX;
01046   path_len = strlen (path);
01047 
01048   if (abstract)
01049     {
01050 #ifdef HAVE_ABSTRACT_SOCKETS
01051       /* remember that abstract names aren't nul-terminated so we rely
01052        * on sun_path being filled in with zeroes above.
01053        */
01054       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
01055       path_len++; /* Account for the extra nul byte added to the start of sun_path */
01056 
01057       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01058         {
01059           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01060                       "Abstract socket name too long\n");
01061           _dbus_close (listen_fd, NULL);
01062           return -1;
01063         }
01064 
01065       strncpy (&addr.sun_path[1], path, path_len);
01066       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
01067 #else /* HAVE_ABSTRACT_SOCKETS */
01068       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
01069                       "Operating system does not support abstract socket namespace\n");
01070       _dbus_close (listen_fd, NULL);
01071       return -1;
01072 #endif /* ! HAVE_ABSTRACT_SOCKETS */
01073     }
01074   else
01075     {
01076       /* Discussed security implications of this with Nalin,
01077        * and we couldn't think of where it would kick our ass, but
01078        * it still seems a bit sucky. It also has non-security suckage;
01079        * really we'd prefer to exit if the socket is already in use.
01080        * But there doesn't seem to be a good way to do this.
01081        *
01082        * Just to be extra careful, I threw in the stat() - clearly
01083        * the stat() can't *fix* any security issue, but it at least
01084        * avoids inadvertent/accidental data loss.
01085        */
01086       {
01087         struct stat sb;
01088 
01089         if (stat (path, &sb) == 0 &&
01090             S_ISSOCK (sb.st_mode))
01091           unlink (path);
01092       }
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, path, path_len);
01103     }
01104 
01105   reuseaddr = 1;
01106   if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01107     {
01108       _dbus_warn ("Failed to set socket option\"%s\": %s",
01109                   path, _dbus_strerror (errno));
01110     }
01111 
01112   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
01113     {
01114       dbus_set_error (error, _dbus_error_from_errno (errno),
01115                       "Failed to bind socket \"%s\": %s",
01116                       path, _dbus_strerror (errno));
01117       _dbus_close (listen_fd, NULL);
01118       return -1;
01119     }
01120 
01121   if (listen (listen_fd, 30 /* backlog */) < 0)
01122     {
01123       dbus_set_error (error, _dbus_error_from_errno (errno),
01124                       "Failed to listen on socket \"%s\": %s",
01125                       path, _dbus_strerror (errno));
01126       _dbus_close (listen_fd, NULL);
01127       return -1;
01128     }
01129 
01130   if (!_dbus_set_local_creds (listen_fd, TRUE))
01131     {
01132       dbus_set_error (error, _dbus_error_from_errno (errno),
01133                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
01134                       path, _dbus_strerror (errno));
01135       close (listen_fd);
01136       return -1;
01137     }
01138 
01139   if (!_dbus_set_fd_nonblocking (listen_fd, error))
01140     {
01141       _DBUS_ASSERT_ERROR_IS_SET (error);
01142       _dbus_close (listen_fd, NULL);
01143       return -1;
01144     }
01145 
01146   /* Try opening up the permissions, but if we can't, just go ahead
01147    * and continue, maybe it will be good enough.
01148    */
01149   if (!abstract && chmod (path, 0777) < 0)
01150     _dbus_warn ("Could not set mode 0777 on socket %s\n",
01151                 path);
01152 
01153   return listen_fd;
01154 }
01155 
01166 int
01167 _dbus_listen_systemd_sockets (int       **fds,
01168                               DBusError *error)
01169 {
01170   int r, n;
01171   unsigned fd;
01172   int *new_fds;
01173 
01174   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01175 
01176   n = sd_listen_fds (TRUE);
01177   if (n < 0)
01178     {
01179       dbus_set_error (error, _dbus_error_from_errno (-n),
01180                       "Failed to acquire systemd socket: %s",
01181                       _dbus_strerror (-n));
01182       return -1;
01183     }
01184 
01185   if (n <= 0)
01186     {
01187       dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01188                       "No socket received.");
01189       return -1;
01190     }
01191 
01192   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01193     {
01194       r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
01195       if (r < 0)
01196         {
01197           dbus_set_error (error, _dbus_error_from_errno (-r),
01198                           "Failed to verify systemd socket type: %s",
01199                           _dbus_strerror (-r));
01200           return -1;
01201         }
01202 
01203       if (!r)
01204         {
01205           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01206                           "Passed socket has wrong type.");
01207           return -1;
01208         }
01209     }
01210 
01211   /* OK, the file descriptors are all good, so let's take posession of
01212      them then. */
01213 
01214   new_fds = dbus_new (int, n);
01215   if (!new_fds)
01216     {
01217       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
01218                       "Failed to allocate file handle array.");
01219       goto fail;
01220     }
01221 
01222   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01223     {
01224       if (!_dbus_set_local_creds (fd, TRUE))
01225         {
01226           dbus_set_error (error, _dbus_error_from_errno (errno),
01227                           "Failed to enable LOCAL_CREDS on systemd socket: %s",
01228                           _dbus_strerror (errno));
01229           goto fail;
01230         }
01231 
01232       if (!_dbus_set_fd_nonblocking (fd, error))
01233         {
01234           _DBUS_ASSERT_ERROR_IS_SET (error);
01235           goto fail;
01236         }
01237 
01238       new_fds[fd - SD_LISTEN_FDS_START] = fd;
01239     }
01240 
01241   *fds = new_fds;
01242   return n;
01243 
01244  fail:
01245 
01246   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01247     {
01248       _dbus_close (fd, NULL);
01249     }
01250 
01251   dbus_free (new_fds);
01252   return -1;
01253 }
01254 
01268 int
01269 _dbus_connect_tcp_socket (const char     *host,
01270                           const char     *port,
01271                           const char     *family,
01272                           DBusError      *error)
01273 {
01274     return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
01275 }
01276 
01277 int
01278 _dbus_connect_tcp_socket_with_nonce (const char     *host,
01279                                      const char     *port,
01280                                      const char     *family,
01281                                      const char     *noncefile,
01282                                      DBusError      *error)
01283 {
01284   int saved_errno = 0;
01285   int fd = -1, res;
01286   struct addrinfo hints;
01287   struct addrinfo *ai, *tmp;
01288 
01289   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01290 
01291   _DBUS_ZERO (hints);
01292 
01293   if (!family)
01294     hints.ai_family = AF_UNSPEC;
01295   else if (!strcmp(family, "ipv4"))
01296     hints.ai_family = AF_INET;
01297   else if (!strcmp(family, "ipv6"))
01298     hints.ai_family = AF_INET6;
01299   else
01300     {
01301       dbus_set_error (error,
01302                       DBUS_ERROR_BAD_ADDRESS,
01303                       "Unknown address family %s", family);
01304       return -1;
01305     }
01306   hints.ai_protocol = IPPROTO_TCP;
01307   hints.ai_socktype = SOCK_STREAM;
01308   hints.ai_flags = AI_ADDRCONFIG;
01309 
01310   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
01311     {
01312       dbus_set_error (error,
01313                       _dbus_error_from_errno (errno),
01314                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01315                       host, port, gai_strerror(res), res);
01316       return -1;
01317     }
01318 
01319   tmp = ai;
01320   while (tmp)
01321     {
01322       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01323         {
01324           freeaddrinfo(ai);
01325           _DBUS_ASSERT_ERROR_IS_SET(error);
01326           return -1;
01327         }
01328       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01329 
01330       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01331         {
01332           saved_errno = errno;
01333           _dbus_close(fd, NULL);
01334           fd = -1;
01335           tmp = tmp->ai_next;
01336           continue;
01337         }
01338 
01339       break;
01340     }
01341   freeaddrinfo(ai);
01342 
01343   if (fd == -1)
01344     {
01345       dbus_set_error (error,
01346                       _dbus_error_from_errno (saved_errno),
01347                       "Failed to connect to socket \"%s:%s\" %s",
01348                       host, port, _dbus_strerror(saved_errno));
01349       return -1;
01350     }
01351 
01352   if (noncefile != NULL)
01353     {
01354       DBusString noncefileStr;
01355       dbus_bool_t ret;
01356       _dbus_string_init_const (&noncefileStr, noncefile);
01357       ret = _dbus_send_nonce (fd, &noncefileStr, error);
01358       _dbus_string_free (&noncefileStr);
01359 
01360       if (!ret)
01361     {
01362       _dbus_close (fd, NULL);
01363           return -1;
01364         }
01365     }
01366 
01367   if (!_dbus_set_fd_nonblocking (fd, error))
01368     {
01369       _dbus_close (fd, NULL);
01370       return -1;
01371     }
01372 
01373   return fd;
01374 }
01375 
01392 int
01393 _dbus_listen_tcp_socket (const char     *host,
01394                          const char     *port,
01395                          const char     *family,
01396                          DBusString     *retport,
01397                          int           **fds_p,
01398                          DBusError      *error)
01399 {
01400   int saved_errno;
01401   int nlisten_fd = 0, *listen_fd = NULL, res, i;
01402   struct addrinfo hints;
01403   struct addrinfo *ai, *tmp;
01404   unsigned int reuseaddr;
01405 
01406   *fds_p = NULL;
01407   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01408 
01409   _DBUS_ZERO (hints);
01410 
01411   if (!family)
01412     hints.ai_family = AF_UNSPEC;
01413   else if (!strcmp(family, "ipv4"))
01414     hints.ai_family = AF_INET;
01415   else if (!strcmp(family, "ipv6"))
01416     hints.ai_family = AF_INET6;
01417   else
01418     {
01419       dbus_set_error (error,
01420                       DBUS_ERROR_BAD_ADDRESS,
01421                       "Unknown address family %s", family);
01422       return -1;
01423     }
01424 
01425   hints.ai_protocol = IPPROTO_TCP;
01426   hints.ai_socktype = SOCK_STREAM;
01427   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
01428 
01429  redo_lookup_with_port:
01430   ai = NULL;
01431   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01432     {
01433       dbus_set_error (error,
01434                       _dbus_error_from_errno (errno),
01435                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01436                       host ? host : "*", port, gai_strerror(res), res);
01437       goto failed;
01438     }
01439 
01440   tmp = ai;
01441   while (tmp)
01442     {
01443       int fd = -1, *newlisten_fd;
01444       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01445         {
01446           _DBUS_ASSERT_ERROR_IS_SET(error);
01447           goto failed;
01448         }
01449       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01450 
01451       reuseaddr = 1;
01452       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01453         {
01454           _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01455                       host ? host : "*", port, _dbus_strerror (errno));
01456         }
01457 
01458       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01459         {
01460           saved_errno = errno;
01461           _dbus_close(fd, NULL);
01462           if (saved_errno == EADDRINUSE)
01463             {
01464               /* Depending on kernel policy, it may or may not
01465                  be neccessary to bind to both IPv4 & 6 addresses
01466                  so ignore EADDRINUSE here */
01467               tmp = tmp->ai_next;
01468               continue;
01469             }
01470           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01471                           "Failed to bind socket \"%s:%s\": %s",
01472                           host ? host : "*", port, _dbus_strerror (saved_errno));
01473           goto failed;
01474         }
01475 
01476       if (listen (fd, 30 /* backlog */) < 0)
01477         {
01478           saved_errno = errno;
01479           _dbus_close (fd, NULL);
01480           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01481                           "Failed to listen on socket \"%s:%s\": %s",
01482                           host ? host : "*", port, _dbus_strerror (saved_errno));
01483           goto failed;
01484         }
01485 
01486       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
01487       if (!newlisten_fd)
01488         {
01489           saved_errno = errno;
01490           _dbus_close (fd, NULL);
01491           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01492                           "Failed to allocate file handle array: %s",
01493                           _dbus_strerror (saved_errno));
01494           goto failed;
01495         }
01496       listen_fd = newlisten_fd;
01497       listen_fd[nlisten_fd] = fd;
01498       nlisten_fd++;
01499 
01500       if (!_dbus_string_get_length(retport))
01501         {
01502           /* If the user didn't specify a port, or used 0, then
01503              the kernel chooses a port. After the first address
01504              is bound to, we need to force all remaining addresses
01505              to use the same port */
01506           if (!port || !strcmp(port, "0"))
01507             {
01508               int result;
01509               struct sockaddr_storage addr;
01510               socklen_t addrlen;
01511               char portbuf[50];
01512 
01513               addrlen = sizeof(addr);
01514               result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01515 
01516               if (result == -1 ||
01517                   (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
01518                                       portbuf, sizeof(portbuf),
01519                                       NI_NUMERICHOST)) != 0)
01520                 {
01521                   dbus_set_error (error, _dbus_error_from_errno (errno),
01522                                   "Failed to resolve port \"%s:%s\": %s (%s)",
01523                                   host ? host : "*", port, gai_strerror(res), res);
01524                   goto failed;
01525                 }
01526               if (!_dbus_string_append(retport, portbuf))
01527                 {
01528                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01529                   goto failed;
01530                 }
01531 
01532               /* Release current address list & redo lookup */
01533               port = _dbus_string_get_const_data(retport);
01534               freeaddrinfo(ai);
01535               goto redo_lookup_with_port;
01536             }
01537           else
01538             {
01539               if (!_dbus_string_append(retport, port))
01540                 {
01541                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01542                     goto failed;
01543                 }
01544             }
01545         }
01546 
01547       tmp = tmp->ai_next;
01548     }
01549   freeaddrinfo(ai);
01550   ai = NULL;
01551 
01552   if (!nlisten_fd)
01553     {
01554       errno = EADDRINUSE;
01555       dbus_set_error (error, _dbus_error_from_errno (errno),
01556                       "Failed to bind socket \"%s:%s\": %s",
01557                       host ? host : "*", port, _dbus_strerror (errno));
01558       goto failed;
01559     }
01560 
01561   for (i = 0 ; i < nlisten_fd ; i++)
01562     {
01563       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01564         {
01565           goto failed;
01566         }
01567     }
01568 
01569   *fds_p = listen_fd;
01570 
01571   return nlisten_fd;
01572 
01573  failed:
01574   if (ai)
01575     freeaddrinfo(ai);
01576   for (i = 0 ; i < nlisten_fd ; i++)
01577     _dbus_close(listen_fd[i], NULL);
01578   dbus_free(listen_fd);
01579   return -1;
01580 }
01581 
01582 static dbus_bool_t
01583 write_credentials_byte (int             server_fd,
01584                         DBusError      *error)
01585 {
01586   int bytes_written;
01587   char buf[1] = { '\0' };
01588 #if defined(HAVE_CMSGCRED)
01589   union {
01590           struct cmsghdr hdr;
01591           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01592   } cmsg;
01593   struct iovec iov;
01594   struct msghdr msg;
01595   iov.iov_base = buf;
01596   iov.iov_len = 1;
01597 
01598   _DBUS_ZERO(msg);
01599   msg.msg_iov = &iov;
01600   msg.msg_iovlen = 1;
01601 
01602   msg.msg_control = (caddr_t) &cmsg;
01603   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01604   _DBUS_ZERO(cmsg);
01605   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01606   cmsg.hdr.cmsg_level = SOL_SOCKET;
01607   cmsg.hdr.cmsg_type = SCM_CREDS;
01608 #endif
01609 
01610   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01611 
01612  again:
01613 
01614 #if defined(HAVE_CMSGCRED)
01615   bytes_written = sendmsg (server_fd, &msg, 0
01616 #if HAVE_DECL_MSG_NOSIGNAL
01617                            |MSG_NOSIGNAL
01618 #endif
01619                            );
01620 #else
01621   bytes_written = send (server_fd, buf, 1, 0
01622 #if HAVE_DECL_MSG_NOSIGNAL
01623                         |MSG_NOSIGNAL
01624 #endif
01625                         );
01626 #endif
01627 
01628   if (bytes_written < 0 && errno == EINTR)
01629     goto again;
01630 
01631   if (bytes_written < 0)
01632     {
01633       dbus_set_error (error, _dbus_error_from_errno (errno),
01634                       "Failed to write credentials byte: %s",
01635                      _dbus_strerror (errno));
01636       return FALSE;
01637     }
01638   else if (bytes_written == 0)
01639     {
01640       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01641                       "wrote zero bytes writing credentials byte");
01642       return FALSE;
01643     }
01644   else
01645     {
01646       _dbus_assert (bytes_written == 1);
01647       _dbus_verbose ("wrote credentials byte\n");
01648       return TRUE;
01649     }
01650 }
01651 
01673 dbus_bool_t
01674 _dbus_read_credentials_socket  (int              client_fd,
01675                                 DBusCredentials *credentials,
01676                                 DBusError       *error)
01677 {
01678   struct msghdr msg;
01679   struct iovec iov;
01680   char buf;
01681   dbus_uid_t uid_read;
01682   dbus_pid_t pid_read;
01683   int bytes_read;
01684 
01685 #ifdef HAVE_CMSGCRED
01686   union {
01687     struct cmsghdr hdr;
01688     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01689   } cmsg;
01690 
01691 #elif defined(LOCAL_CREDS)
01692   struct {
01693     struct cmsghdr hdr;
01694     struct sockcred cred;
01695   } cmsg;
01696 #endif
01697 
01698   uid_read = DBUS_UID_UNSET;
01699   pid_read = DBUS_PID_UNSET;
01700 
01701   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01702 
01703   /* The POSIX spec certainly doesn't promise this, but
01704    * we need these assertions to fail as soon as we're wrong about
01705    * it so we can do the porting fixups
01706    */
01707   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01708   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01709   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01710 
01711   _dbus_credentials_clear (credentials);
01712 
01713   /* Systems supporting LOCAL_CREDS are configured to have this feature
01714    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01715    * the connection.  Therefore, the received message must carry the
01716    * credentials information without doing anything special.
01717    */
01718 
01719   iov.iov_base = &buf;
01720   iov.iov_len = 1;
01721 
01722   _DBUS_ZERO(msg);
01723   msg.msg_iov = &iov;
01724   msg.msg_iovlen = 1;
01725 
01726 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01727   _DBUS_ZERO(cmsg);
01728   msg.msg_control = (caddr_t) &cmsg;
01729   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01730 #endif
01731 
01732  again:
01733   bytes_read = recvmsg (client_fd, &msg, 0);
01734 
01735   if (bytes_read < 0)
01736     {
01737       if (errno == EINTR)
01738         goto again;
01739 
01740       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01741        * normally only call read_credentials if the socket was ready
01742        * for reading
01743        */
01744 
01745       dbus_set_error (error, _dbus_error_from_errno (errno),
01746                       "Failed to read credentials byte: %s",
01747                       _dbus_strerror (errno));
01748       return FALSE;
01749     }
01750   else if (bytes_read == 0)
01751     {
01752       /* this should not happen unless we are using recvmsg wrong,
01753        * so is essentially here for paranoia
01754        */
01755       dbus_set_error (error, DBUS_ERROR_FAILED,
01756                       "Failed to read credentials byte (zero-length read)");
01757       return FALSE;
01758     }
01759   else if (buf != '\0')
01760     {
01761       dbus_set_error (error, DBUS_ERROR_FAILED,
01762                       "Credentials byte was not nul");
01763       return FALSE;
01764     }
01765 
01766 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01767   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01768                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01769     {
01770       dbus_set_error (error, DBUS_ERROR_FAILED,
01771                       "Message from recvmsg() was not SCM_CREDS");
01772       return FALSE;
01773     }
01774 #endif
01775 
01776   _dbus_verbose ("read credentials byte\n");
01777 
01778   {
01779 #ifdef SO_PEERCRED
01780 #ifdef __OpenBSD__
01781     struct sockpeercred cr;
01782 #else
01783     struct ucred cr;
01784 #endif
01785     int cr_len = sizeof (cr);
01786 
01787     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01788         cr_len == sizeof (cr))
01789       {
01790         pid_read = cr.pid;
01791         uid_read = cr.uid;
01792       }
01793     else
01794       {
01795         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01796                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01797       }
01798 #elif defined(HAVE_CMSGCRED)
01799     struct cmsgcred *cred;
01800 
01801     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01802     pid_read = cred->cmcred_pid;
01803     uid_read = cred->cmcred_euid;
01804 #elif defined(LOCAL_CREDS)
01805     pid_read = DBUS_PID_UNSET;
01806     uid_read = cmsg.cred.sc_uid;
01807     /* Since we have already got the credentials from this socket, we can
01808      * disable its LOCAL_CREDS flag if it was ever set. */
01809     _dbus_set_local_creds (client_fd, FALSE);
01810 #elif defined(HAVE_GETPEEREID)
01811     uid_t euid;
01812     gid_t egid;
01813     if (getpeereid (client_fd, &euid, &egid) == 0)
01814       {
01815         uid_read = euid;
01816       }
01817     else
01818       {
01819         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01820       }
01821 #elif defined(HAVE_GETPEERUCRED)
01822     ucred_t * ucred = NULL;
01823     if (getpeerucred (client_fd, &ucred) == 0)
01824       {
01825         pid_read = ucred_getpid (ucred);
01826         uid_read = ucred_geteuid (ucred);
01827 #ifdef HAVE_ADT
01828         /* generate audit session data based on socket ucred */
01829         adt_session_data_t *adth = NULL;
01830         adt_export_data_t *data = NULL;
01831         size_t size = 0;
01832         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01833           {
01834             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01835           }
01836         else
01837           {
01838             if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01839               {
01840                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01841               }
01842             else
01843               {
01844                 size = adt_export_session_data (adth, &data);
01845                 if (size <= 0)
01846                   {
01847                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01848                   }
01849                 else
01850                   {
01851                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01852                     free (data);
01853                   }
01854               }
01855             (void) adt_end_session (adth);
01856           }
01857 #endif /* HAVE_ADT */
01858       }
01859     else
01860       {
01861         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01862       }
01863     if (ucred != NULL)
01864       ucred_free (ucred);
01865 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01866     _dbus_verbose ("Socket credentials not supported on this OS\n");
01867 #endif
01868   }
01869 
01870   _dbus_verbose ("Credentials:"
01871                  "  pid "DBUS_PID_FORMAT
01872                  "  uid "DBUS_UID_FORMAT
01873                  "\n",
01874                  pid_read,
01875                  uid_read);
01876 
01877   if (pid_read != DBUS_PID_UNSET)
01878     {
01879       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01880         {
01881           _DBUS_SET_OOM (error);
01882           return FALSE;
01883         }
01884     }
01885 
01886   if (uid_read != DBUS_UID_UNSET)
01887     {
01888       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01889         {
01890           _DBUS_SET_OOM (error);
01891           return FALSE;
01892         }
01893     }
01894 
01895   return TRUE;
01896 }
01897 
01915 dbus_bool_t
01916 _dbus_send_credentials_socket  (int              server_fd,
01917                                 DBusError       *error)
01918 {
01919   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01920 
01921   if (write_credentials_byte (server_fd, error))
01922     return TRUE;
01923   else
01924     return FALSE;
01925 }
01926 
01936 int
01937 _dbus_accept  (int listen_fd)
01938 {
01939   int client_fd;
01940   struct sockaddr addr;
01941   socklen_t addrlen;
01942 #ifdef HAVE_ACCEPT4
01943   dbus_bool_t cloexec_done;
01944 #endif
01945 
01946   addrlen = sizeof (addr);
01947 
01948  retry:
01949 
01950 #ifdef HAVE_ACCEPT4
01951   /*
01952    * At compile-time, we assume that if accept4() is available in
01953    * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
01954    * not necessarily true that either is supported by the running kernel.
01955    */
01956   client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
01957   cloexec_done = client_fd >= 0;
01958 
01959   if (client_fd < 0 && (errno == ENOSYS || errno == EINVAL))
01960 #endif
01961     {
01962       client_fd = accept (listen_fd, &addr, &addrlen);
01963     }
01964 
01965   if (client_fd < 0)
01966     {
01967       if (errno == EINTR)
01968         goto retry;
01969     }
01970 
01971   _dbus_verbose ("client fd %d accepted\n", client_fd);
01972 
01973 #ifdef HAVE_ACCEPT4
01974   if (!cloexec_done)
01975 #endif
01976     {
01977       _dbus_fd_set_close_on_exec(client_fd);
01978     }
01979 
01980   return client_fd;
01981 }
01982 
01991 dbus_bool_t
01992 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01993 {
01994   const char *directory;
01995   struct stat sb;
01996 
01997   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01998 
01999   directory = _dbus_string_get_const_data (dir);
02000 
02001   if (stat (directory, &sb) < 0)
02002     {
02003       dbus_set_error (error, _dbus_error_from_errno (errno),
02004                       "%s", _dbus_strerror (errno));
02005 
02006       return FALSE;
02007     }
02008 
02009   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
02010       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
02011     {
02012       dbus_set_error (error, DBUS_ERROR_FAILED,
02013                      "%s directory is not private to the user", directory);
02014       return FALSE;
02015     }
02016 
02017   return TRUE;
02018 }
02019 
02020 static dbus_bool_t
02021 fill_user_info_from_passwd (struct passwd *p,
02022                             DBusUserInfo  *info,
02023                             DBusError     *error)
02024 {
02025   _dbus_assert (p->pw_name != NULL);
02026   _dbus_assert (p->pw_dir != NULL);
02027 
02028   info->uid = p->pw_uid;
02029   info->primary_gid = p->pw_gid;
02030   info->username = _dbus_strdup (p->pw_name);
02031   info->homedir = _dbus_strdup (p->pw_dir);
02032 
02033   if (info->username == NULL ||
02034       info->homedir == NULL)
02035     {
02036       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02037       return FALSE;
02038     }
02039 
02040   return TRUE;
02041 }
02042 
02043 static dbus_bool_t
02044 fill_user_info (DBusUserInfo       *info,
02045                 dbus_uid_t          uid,
02046                 const DBusString   *username,
02047                 DBusError          *error)
02048 {
02049   const char *username_c;
02050 
02051   /* exactly one of username/uid provided */
02052   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
02053   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
02054 
02055   info->uid = DBUS_UID_UNSET;
02056   info->primary_gid = DBUS_GID_UNSET;
02057   info->group_ids = NULL;
02058   info->n_group_ids = 0;
02059   info->username = NULL;
02060   info->homedir = NULL;
02061 
02062   if (username != NULL)
02063     username_c = _dbus_string_get_const_data (username);
02064   else
02065     username_c = NULL;
02066 
02067   /* For now assuming that the getpwnam() and getpwuid() flavors
02068    * are always symmetrical, if not we have to add more configure
02069    * checks
02070    */
02071 
02072 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
02073   {
02074     struct passwd *p;
02075     int result;
02076     size_t buflen;
02077     char *buf;
02078     struct passwd p_str;
02079 
02080     /* retrieve maximum needed size for buf */
02081     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
02082 
02083     /* sysconf actually returns a long, but everything else expects size_t,
02084      * so just recast here.
02085      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
02086      */
02087     if ((long) buflen <= 0)
02088       buflen = 1024;
02089 
02090     result = -1;
02091     while (1)
02092       {
02093         buf = dbus_malloc (buflen);
02094         if (buf == NULL)
02095           {
02096             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02097             return FALSE;
02098           }
02099 
02100         p = NULL;
02101 #ifdef HAVE_POSIX_GETPWNAM_R
02102         if (uid != DBUS_UID_UNSET)
02103           result = getpwuid_r (uid, &p_str, buf, buflen,
02104                                &p);
02105         else
02106           result = getpwnam_r (username_c, &p_str, buf, buflen,
02107                                &p);
02108 #else
02109         if (uid != DBUS_UID_UNSET)
02110           p = getpwuid_r (uid, &p_str, buf, buflen);
02111         else
02112           p = getpwnam_r (username_c, &p_str, buf, buflen);
02113         result = 0;
02114 #endif /* !HAVE_POSIX_GETPWNAM_R */
02115         //Try a bigger buffer if ERANGE was returned
02116         if (result == ERANGE && buflen < 512 * 1024)
02117           {
02118             dbus_free (buf);
02119             buflen *= 2;
02120           }
02121         else
02122           {
02123             break;
02124           }
02125       }
02126     if (result == 0 && p == &p_str)
02127       {
02128         if (!fill_user_info_from_passwd (p, info, error))
02129           {
02130             dbus_free (buf);
02131             return FALSE;
02132           }
02133         dbus_free (buf);
02134       }
02135     else
02136       {
02137         dbus_set_error (error, _dbus_error_from_errno (errno),
02138                         "User \"%s\" unknown or no memory to allocate password entry\n",
02139                         username_c ? username_c : "???");
02140         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02141         dbus_free (buf);
02142         return FALSE;
02143       }
02144   }
02145 #else /* ! HAVE_GETPWNAM_R */
02146   {
02147     /* I guess we're screwed on thread safety here */
02148     struct passwd *p;
02149 
02150     if (uid != DBUS_UID_UNSET)
02151       p = getpwuid (uid);
02152     else
02153       p = getpwnam (username_c);
02154 
02155     if (p != NULL)
02156       {
02157         if (!fill_user_info_from_passwd (p, info, error))
02158           {
02159             return FALSE;
02160           }
02161       }
02162     else
02163       {
02164         dbus_set_error (error, _dbus_error_from_errno (errno),
02165                         "User \"%s\" unknown or no memory to allocate password entry\n",
02166                         username_c ? username_c : "???");
02167         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02168         return FALSE;
02169       }
02170   }
02171 #endif  /* ! HAVE_GETPWNAM_R */
02172 
02173   /* Fill this in so we can use it to get groups */
02174   username_c = info->username;
02175 
02176 #ifdef HAVE_GETGROUPLIST
02177   {
02178     gid_t *buf;
02179     int buf_count;
02180     int i;
02181     int initial_buf_count;
02182 
02183     initial_buf_count = 17;
02184     buf_count = initial_buf_count;
02185     buf = dbus_new (gid_t, buf_count);
02186     if (buf == NULL)
02187       {
02188         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02189         goto failed;
02190       }
02191 
02192     if (getgrouplist (username_c,
02193                       info->primary_gid,
02194                       buf, &buf_count) < 0)
02195       {
02196         gid_t *new;
02197         /* Presumed cause of negative return code: buf has insufficient
02198            entries to hold the entire group list. The Linux behavior in this
02199            case is to pass back the actual number of groups in buf_count, but
02200            on Mac OS X 10.5, buf_count is unhelpfully left alone.
02201            So as a hack, try to help out a bit by guessing a larger
02202            number of groups, within reason.. might still fail, of course,
02203            but we can at least print a more informative message.  I looked up
02204            the "right way" to do this by downloading Apple's own source code
02205            for the "id" command, and it turns out that they use an
02206            undocumented library function getgrouplist_2 (!) which is not
02207            declared in any header in /usr/include (!!). That did not seem
02208            like the way to go here.
02209         */
02210         if (buf_count == initial_buf_count)
02211           {
02212             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
02213           }
02214         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02215         if (new == NULL)
02216           {
02217             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02218             dbus_free (buf);
02219             goto failed;
02220           }
02221 
02222         buf = new;
02223 
02224         errno = 0;
02225         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02226           {
02227             if (errno == 0)
02228               {
02229                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02230                             username_c, buf_count, buf_count);
02231               }
02232             else
02233               {
02234                 dbus_set_error (error,
02235                                 _dbus_error_from_errno (errno),
02236                                 "Failed to get groups for username \"%s\" primary GID "
02237                                 DBUS_GID_FORMAT ": %s\n",
02238                                 username_c, info->primary_gid,
02239                                 _dbus_strerror (errno));
02240                 dbus_free (buf);
02241                 goto failed;
02242               }
02243           }
02244       }
02245 
02246     info->group_ids = dbus_new (dbus_gid_t, buf_count);
02247     if (info->group_ids == NULL)
02248       {
02249         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02250         dbus_free (buf);
02251         goto failed;
02252       }
02253 
02254     for (i = 0; i < buf_count; ++i)
02255       info->group_ids[i] = buf[i];
02256 
02257     info->n_group_ids = buf_count;
02258 
02259     dbus_free (buf);
02260   }
02261 #else  /* HAVE_GETGROUPLIST */
02262   {
02263     /* We just get the one group ID */
02264     info->group_ids = dbus_new (dbus_gid_t, 1);
02265     if (info->group_ids == NULL)
02266       {
02267         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02268         goto failed;
02269       }
02270 
02271     info->n_group_ids = 1;
02272 
02273     (info->group_ids)[0] = info->primary_gid;
02274   }
02275 #endif /* HAVE_GETGROUPLIST */
02276 
02277   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02278 
02279   return TRUE;
02280 
02281  failed:
02282   _DBUS_ASSERT_ERROR_IS_SET (error);
02283   return FALSE;
02284 }
02285 
02294 dbus_bool_t
02295 _dbus_user_info_fill (DBusUserInfo     *info,
02296                       const DBusString *username,
02297                       DBusError        *error)
02298 {
02299   return fill_user_info (info, DBUS_UID_UNSET,
02300                          username, error);
02301 }
02302 
02311 dbus_bool_t
02312 _dbus_user_info_fill_uid (DBusUserInfo *info,
02313                           dbus_uid_t    uid,
02314                           DBusError    *error)
02315 {
02316   return fill_user_info (info, uid,
02317                          NULL, error);
02318 }
02319 
02327 dbus_bool_t
02328 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02329 {
02330   /* The POSIX spec certainly doesn't promise this, but
02331    * we need these assertions to fail as soon as we're wrong about
02332    * it so we can do the porting fixups
02333    */
02334   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
02335   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
02336   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
02337 
02338   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
02339     return FALSE;
02340   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02341     return FALSE;
02342 
02343   return TRUE;
02344 }
02345 
02357 dbus_bool_t
02358 _dbus_append_user_from_current_process (DBusString *str)
02359 {
02360   return _dbus_string_append_uint (str,
02361                                    _dbus_geteuid ());
02362 }
02363 
02368 dbus_pid_t
02369 _dbus_getpid (void)
02370 {
02371   return getpid ();
02372 }
02373 
02377 dbus_uid_t
02378 _dbus_getuid (void)
02379 {
02380   return getuid ();
02381 }
02382 
02386 dbus_uid_t
02387 _dbus_geteuid (void)
02388 {
02389   return geteuid ();
02390 }
02391 
02398 unsigned long
02399 _dbus_pid_for_log (void)
02400 {
02401   return getpid ();
02402 }
02403 
02411 dbus_bool_t
02412 _dbus_parse_uid (const DBusString      *uid_str,
02413                  dbus_uid_t            *uid)
02414 {
02415   int end;
02416   long val;
02417 
02418   if (_dbus_string_get_length (uid_str) == 0)
02419     {
02420       _dbus_verbose ("UID string was zero length\n");
02421       return FALSE;
02422     }
02423 
02424   val = -1;
02425   end = 0;
02426   if (!_dbus_string_parse_int (uid_str, 0, &val,
02427                                &end))
02428     {
02429       _dbus_verbose ("could not parse string as a UID\n");
02430       return FALSE;
02431     }
02432 
02433   if (end != _dbus_string_get_length (uid_str))
02434     {
02435       _dbus_verbose ("string contained trailing stuff after UID\n");
02436       return FALSE;
02437     }
02438 
02439   *uid = val;
02440 
02441   return TRUE;
02442 }
02443 
02444 #if !DBUS_USE_SYNC
02445 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
02446 #endif
02447 
02454 dbus_int32_t
02455 _dbus_atomic_inc (DBusAtomic *atomic)
02456 {
02457 #if DBUS_USE_SYNC
02458   return __sync_add_and_fetch(&atomic->value, 1)-1;
02459 #else
02460   dbus_int32_t res;
02461   _DBUS_LOCK (atomic);
02462   res = atomic->value;
02463   atomic->value += 1;
02464   _DBUS_UNLOCK (atomic);
02465   return res;
02466 #endif
02467 }
02468 
02475 dbus_int32_t
02476 _dbus_atomic_dec (DBusAtomic *atomic)
02477 {
02478 #if DBUS_USE_SYNC
02479   return __sync_sub_and_fetch(&atomic->value, 1)+1;
02480 #else
02481   dbus_int32_t res;
02482 
02483   _DBUS_LOCK (atomic);
02484   res = atomic->value;
02485   atomic->value -= 1;
02486   _DBUS_UNLOCK (atomic);
02487   return res;
02488 #endif
02489 }
02490 
02498 dbus_int32_t
02499 _dbus_atomic_get (DBusAtomic *atomic)
02500 {
02501 #if DBUS_USE_SYNC
02502   __sync_synchronize ();
02503   return atomic->value;
02504 #else
02505   dbus_int32_t res;
02506 
02507   _DBUS_LOCK (atomic);
02508   res = atomic->value;
02509   _DBUS_UNLOCK (atomic);
02510   return res;
02511 #endif
02512 }
02513 
02522 int
02523 _dbus_poll (DBusPollFD *fds,
02524             int         n_fds,
02525             int         timeout_milliseconds)
02526 {
02527 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02528   /* This big thing is a constant expression and should get optimized
02529    * out of existence. So it's more robust than a configure check at
02530    * no cost.
02531    */
02532   if (_DBUS_POLLIN == POLLIN &&
02533       _DBUS_POLLPRI == POLLPRI &&
02534       _DBUS_POLLOUT == POLLOUT &&
02535       _DBUS_POLLERR == POLLERR &&
02536       _DBUS_POLLHUP == POLLHUP &&
02537       _DBUS_POLLNVAL == POLLNVAL &&
02538       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
02539       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
02540       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
02541       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
02542       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
02543       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
02544       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
02545     {
02546       return poll ((struct pollfd*) fds,
02547                    n_fds,
02548                    timeout_milliseconds);
02549     }
02550   else
02551     {
02552       /* We have to convert the DBusPollFD to an array of
02553        * struct pollfd, poll, and convert back.
02554        */
02555       _dbus_warn ("didn't implement poll() properly for this system yet\n");
02556       return -1;
02557     }
02558 #else /* ! HAVE_POLL */
02559 
02560   fd_set read_set, write_set, err_set;
02561   int max_fd = 0;
02562   int i;
02563   struct timeval tv;
02564   int ready;
02565 
02566   FD_ZERO (&read_set);
02567   FD_ZERO (&write_set);
02568   FD_ZERO (&err_set);
02569 
02570   for (i = 0; i < n_fds; i++)
02571     {
02572       DBusPollFD *fdp = &fds[i];
02573 
02574       if (fdp->events & _DBUS_POLLIN)
02575         FD_SET (fdp->fd, &read_set);
02576 
02577       if (fdp->events & _DBUS_POLLOUT)
02578         FD_SET (fdp->fd, &write_set);
02579 
02580       FD_SET (fdp->fd, &err_set);
02581 
02582       max_fd = MAX (max_fd, fdp->fd);
02583     }
02584 
02585   tv.tv_sec = timeout_milliseconds / 1000;
02586   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02587 
02588   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02589                   timeout_milliseconds < 0 ? NULL : &tv);
02590 
02591   if (ready > 0)
02592     {
02593       for (i = 0; i < n_fds; i++)
02594         {
02595           DBusPollFD *fdp = &fds[i];
02596 
02597           fdp->revents = 0;
02598 
02599           if (FD_ISSET (fdp->fd, &read_set))
02600             fdp->revents |= _DBUS_POLLIN;
02601 
02602           if (FD_ISSET (fdp->fd, &write_set))
02603             fdp->revents |= _DBUS_POLLOUT;
02604 
02605           if (FD_ISSET (fdp->fd, &err_set))
02606             fdp->revents |= _DBUS_POLLERR;
02607         }
02608     }
02609 
02610   return ready;
02611 #endif
02612 }
02613 
02621 void
02622 _dbus_get_monotonic_time (long *tv_sec,
02623                           long *tv_usec)
02624 {
02625 #ifdef HAVE_MONOTONIC_CLOCK
02626   struct timespec ts;
02627   clock_gettime (CLOCK_MONOTONIC, &ts);
02628 
02629   if (tv_sec)
02630     *tv_sec = ts.tv_sec;
02631   if (tv_usec)
02632     *tv_usec = ts.tv_nsec / 1000;
02633 #else
02634   struct timeval t;
02635 
02636   gettimeofday (&t, NULL);
02637 
02638   if (tv_sec)
02639     *tv_sec = t.tv_sec;
02640   if (tv_usec)
02641     *tv_usec = t.tv_usec;
02642 #endif
02643 }
02644 
02652 void
02653 _dbus_get_real_time (long *tv_sec,
02654                      long *tv_usec)
02655 {
02656   struct timeval t;
02657 
02658   gettimeofday (&t, NULL);
02659 
02660   if (tv_sec)
02661     *tv_sec = t.tv_sec;
02662   if (tv_usec)
02663     *tv_usec = t.tv_usec;
02664 }
02665 
02674 dbus_bool_t
02675 _dbus_create_directory (const DBusString *filename,
02676                         DBusError        *error)
02677 {
02678   const char *filename_c;
02679 
02680   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02681 
02682   filename_c = _dbus_string_get_const_data (filename);
02683 
02684   if (mkdir (filename_c, 0700) < 0)
02685     {
02686       if (errno == EEXIST)
02687         return TRUE;
02688 
02689       dbus_set_error (error, DBUS_ERROR_FAILED,
02690                       "Failed to create directory %s: %s\n",
02691                       filename_c, _dbus_strerror (errno));
02692       return FALSE;
02693     }
02694   else
02695     return TRUE;
02696 }
02697 
02708 dbus_bool_t
02709 _dbus_concat_dir_and_file (DBusString       *dir,
02710                            const DBusString *next_component)
02711 {
02712   dbus_bool_t dir_ends_in_slash;
02713   dbus_bool_t file_starts_with_slash;
02714 
02715   if (_dbus_string_get_length (dir) == 0 ||
02716       _dbus_string_get_length (next_component) == 0)
02717     return TRUE;
02718 
02719   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02720                                                     _dbus_string_get_length (dir) - 1);
02721 
02722   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02723 
02724   if (dir_ends_in_slash && file_starts_with_slash)
02725     {
02726       _dbus_string_shorten (dir, 1);
02727     }
02728   else if (!(dir_ends_in_slash || file_starts_with_slash))
02729     {
02730       if (!_dbus_string_append_byte (dir, '/'))
02731         return FALSE;
02732     }
02733 
02734   return _dbus_string_copy (next_component, 0, dir,
02735                             _dbus_string_get_length (dir));
02736 }
02737 
02739 #define NANOSECONDS_PER_SECOND       1000000000
02740 
02741 #define MICROSECONDS_PER_SECOND      1000000
02742 
02743 #define MILLISECONDS_PER_SECOND      1000
02744 
02745 #define NANOSECONDS_PER_MILLISECOND  1000000
02746 
02747 #define MICROSECONDS_PER_MILLISECOND 1000
02748 
02753 void
02754 _dbus_sleep_milliseconds (int milliseconds)
02755 {
02756 #ifdef HAVE_NANOSLEEP
02757   struct timespec req;
02758   struct timespec rem;
02759 
02760   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02761   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02762   rem.tv_sec = 0;
02763   rem.tv_nsec = 0;
02764 
02765   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02766     req = rem;
02767 #elif defined (HAVE_USLEEP)
02768   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02769 #else /* ! HAVE_USLEEP */
02770   sleep (MAX (milliseconds / 1000, 1));
02771 #endif
02772 }
02773 
02774 static dbus_bool_t
02775 _dbus_generate_pseudorandom_bytes (DBusString *str,
02776                                    int         n_bytes)
02777 {
02778   int old_len;
02779   char *p;
02780 
02781   old_len = _dbus_string_get_length (str);
02782 
02783   if (!_dbus_string_lengthen (str, n_bytes))
02784     return FALSE;
02785 
02786   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02787 
02788   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02789 
02790   return TRUE;
02791 }
02792 
02801 dbus_bool_t
02802 _dbus_generate_random_bytes (DBusString *str,
02803                              int         n_bytes)
02804 {
02805   int old_len;
02806   int fd;
02807 
02808   /* FALSE return means "no memory", if it could
02809    * mean something else then we'd need to return
02810    * a DBusError. So we always fall back to pseudorandom
02811    * if the I/O fails.
02812    */
02813 
02814   old_len = _dbus_string_get_length (str);
02815   fd = -1;
02816 
02817   /* note, urandom on linux will fall back to pseudorandom */
02818   fd = open ("/dev/urandom", O_RDONLY);
02819   if (fd < 0)
02820     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02821 
02822   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02823 
02824   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02825     {
02826       _dbus_close (fd, NULL);
02827       _dbus_string_set_length (str, old_len);
02828       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02829     }
02830 
02831   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02832                  n_bytes);
02833 
02834   _dbus_close (fd, NULL);
02835 
02836   return TRUE;
02837 }
02838 
02844 void
02845 _dbus_exit (int code)
02846 {
02847   _exit (code);
02848 }
02849 
02858 const char*
02859 _dbus_strerror (int error_number)
02860 {
02861   const char *msg;
02862 
02863   msg = strerror (error_number);
02864   if (msg == NULL)
02865     msg = "unknown";
02866 
02867   return msg;
02868 }
02869 
02873 void
02874 _dbus_disable_sigpipe (void)
02875 {
02876   signal (SIGPIPE, SIG_IGN);
02877 }
02878 
02886 void
02887 _dbus_fd_set_close_on_exec (intptr_t fd)
02888 {
02889   int val;
02890 
02891   val = fcntl (fd, F_GETFD, 0);
02892 
02893   if (val < 0)
02894     return;
02895 
02896   val |= FD_CLOEXEC;
02897 
02898   fcntl (fd, F_SETFD, val);
02899 }
02900 
02908 dbus_bool_t
02909 _dbus_close (int        fd,
02910              DBusError *error)
02911 {
02912   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02913 
02914  again:
02915   if (close (fd) < 0)
02916     {
02917       if (errno == EINTR)
02918         goto again;
02919 
02920       dbus_set_error (error, _dbus_error_from_errno (errno),
02921                       "Could not close fd %d", fd);
02922       return FALSE;
02923     }
02924 
02925   return TRUE;
02926 }
02927 
02935 int
02936 _dbus_dup(int        fd,
02937           DBusError *error)
02938 {
02939   int new_fd;
02940 
02941 #ifdef F_DUPFD_CLOEXEC
02942   dbus_bool_t cloexec_done;
02943 
02944   new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
02945   cloexec_done = new_fd >= 0;
02946 
02947   if (new_fd < 0 && errno == EINVAL)
02948 #endif
02949     {
02950       new_fd = fcntl(fd, F_DUPFD, 3);
02951     }
02952 
02953   if (new_fd < 0) {
02954 
02955     dbus_set_error (error, _dbus_error_from_errno (errno),
02956                     "Could not duplicate fd %d", fd);
02957     return -1;
02958   }
02959 
02960 #ifdef F_DUPFD_CLOEXEC
02961   if (!cloexec_done)
02962 #endif
02963     {
02964       _dbus_fd_set_close_on_exec(new_fd);
02965     }
02966 
02967   return new_fd;
02968 }
02969 
02977 dbus_bool_t
02978 _dbus_set_fd_nonblocking (int             fd,
02979                           DBusError      *error)
02980 {
02981   int val;
02982 
02983   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02984 
02985   val = fcntl (fd, F_GETFL, 0);
02986   if (val < 0)
02987     {
02988       dbus_set_error (error, _dbus_error_from_errno (errno),
02989                       "Failed to get flags from file descriptor %d: %s",
02990                       fd, _dbus_strerror (errno));
02991       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02992                      _dbus_strerror (errno));
02993       return FALSE;
02994     }
02995 
02996   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02997     {
02998       dbus_set_error (error, _dbus_error_from_errno (errno),
02999                       "Failed to set nonblocking flag of file descriptor %d: %s",
03000                       fd, _dbus_strerror (errno));
03001       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03002                      fd, _dbus_strerror (errno));
03003 
03004       return FALSE;
03005     }
03006 
03007   return TRUE;
03008 }
03009 
03015 void
03016 _dbus_print_backtrace (void)
03017 {
03018 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
03019   void *bt[500];
03020   int bt_size;
03021   int i;
03022   char **syms;
03023 
03024   bt_size = backtrace (bt, 500);
03025 
03026   syms = backtrace_symbols (bt, bt_size);
03027 
03028   i = 0;
03029   while (i < bt_size)
03030     {
03031       /* don't use dbus_warn since it can _dbus_abort() */
03032       fprintf (stderr, "  %s\n", syms[i]);
03033       ++i;
03034     }
03035   fflush (stderr);
03036 
03037   free (syms);
03038 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
03039   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
03040 #else
03041   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
03042 #endif
03043 }
03044 
03057 dbus_bool_t
03058 _dbus_full_duplex_pipe (int        *fd1,
03059                         int        *fd2,
03060                         dbus_bool_t blocking,
03061                         DBusError  *error)
03062 {
03063 #ifdef HAVE_SOCKETPAIR
03064   int fds[2];
03065   int retval;
03066 
03067 #ifdef SOCK_CLOEXEC
03068   dbus_bool_t cloexec_done;
03069 
03070   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
03071   cloexec_done = retval >= 0;
03072 
03073   if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
03074 #endif
03075     {
03076       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
03077     }
03078 
03079   if (retval < 0)
03080     {
03081       dbus_set_error (error, _dbus_error_from_errno (errno),
03082                       "Could not create full-duplex pipe");
03083       return FALSE;
03084     }
03085 
03086   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03087 
03088 #ifdef SOCK_CLOEXEC
03089   if (!cloexec_done)
03090 #endif
03091     {
03092       _dbus_fd_set_close_on_exec (fds[0]);
03093       _dbus_fd_set_close_on_exec (fds[1]);
03094     }
03095 
03096   if (!blocking &&
03097       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03098        !_dbus_set_fd_nonblocking (fds[1], NULL)))
03099     {
03100       dbus_set_error (error, _dbus_error_from_errno (errno),
03101                       "Could not set full-duplex pipe nonblocking");
03102 
03103       _dbus_close (fds[0], NULL);
03104       _dbus_close (fds[1], NULL);
03105 
03106       return FALSE;
03107     }
03108 
03109   *fd1 = fds[0];
03110   *fd2 = fds[1];
03111 
03112   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03113                  *fd1, *fd2);
03114 
03115   return TRUE;
03116 #else
03117   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03118   dbus_set_error (error, DBUS_ERROR_FAILED,
03119                   "_dbus_full_duplex_pipe() not implemented on this OS");
03120   return FALSE;
03121 #endif
03122 }
03123 
03132 int
03133 _dbus_printf_string_upper_bound (const char *format,
03134                                  va_list     args)
03135 {
03136   char static_buf[1024];
03137   int bufsize = sizeof (static_buf);
03138   int len;
03139   va_list args_copy;
03140 
03141   DBUS_VA_COPY (args_copy, args);
03142   len = vsnprintf (static_buf, bufsize, format, args_copy);
03143   va_end (args_copy);
03144 
03145   /* If vsnprintf() returned non-negative, then either the string fits in
03146    * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
03147    * returns the number of characters that were needed, or this OS returns the
03148    * truncated length.
03149    *
03150    * We ignore the possibility that snprintf might just ignore the length and
03151    * overrun the buffer (64-bit Solaris 7), because that's pathological.
03152    * If your libc is really that bad, come back when you have a better one. */
03153   if (len == bufsize)
03154     {
03155       /* This could be the truncated length (Tru64 and IRIX have this bug),
03156        * or the real length could be coincidentally the same. Which is it?
03157        * If vsnprintf returns the truncated length, we'll go to the slow
03158        * path. */
03159       DBUS_VA_COPY (args_copy, args);
03160 
03161       if (vsnprintf (static_buf, 1, format, args_copy) == 1)
03162         len = -1;
03163 
03164       va_end (args_copy);
03165     }
03166 
03167   /* If vsnprintf() returned negative, we have to do more work.
03168    * HP-UX returns negative. */
03169   while (len < 0)
03170     {
03171       char *buf;
03172 
03173       bufsize *= 2;
03174 
03175       buf = dbus_malloc (bufsize);
03176 
03177       if (buf == NULL)
03178         return -1;
03179 
03180       DBUS_VA_COPY (args_copy, args);
03181       len = vsnprintf (buf, bufsize, format, args_copy);
03182       va_end (args_copy);
03183 
03184       dbus_free (buf);
03185 
03186       /* If the reported length is exactly the buffer size, round up to the
03187        * next size, in case vsnprintf has been returning the truncated
03188        * length */
03189       if (len == bufsize)
03190         len = -1;
03191     }
03192 
03193   return len;
03194 }
03195 
03202 const char*
03203 _dbus_get_tmpdir(void)
03204 {
03205   static const char* tmpdir = NULL;
03206 
03207   if (tmpdir == NULL)
03208     {
03209       /* TMPDIR is what glibc uses, then
03210        * glibc falls back to the P_tmpdir macro which
03211        * just expands to "/tmp"
03212        */
03213       if (tmpdir == NULL)
03214         tmpdir = getenv("TMPDIR");
03215 
03216       /* These two env variables are probably
03217        * broken, but maybe some OS uses them?
03218        */
03219       if (tmpdir == NULL)
03220         tmpdir = getenv("TMP");
03221       if (tmpdir == NULL)
03222         tmpdir = getenv("TEMP");
03223 
03224       /* And this is the sane fallback. */
03225       if (tmpdir == NULL)
03226         tmpdir = "/tmp";
03227     }
03228 
03229   _dbus_assert(tmpdir != NULL);
03230 
03231   return tmpdir;
03232 }
03233 
03253 static dbus_bool_t
03254 _read_subprocess_line_argv (const char *progpath,
03255                             dbus_bool_t path_fallback,
03256                             char       * const *argv,
03257                             DBusString *result,
03258                             DBusError  *error)
03259 {
03260   int result_pipe[2] = { -1, -1 };
03261   int errors_pipe[2] = { -1, -1 };
03262   pid_t pid;
03263   int ret;
03264   int status;
03265   int orig_len;
03266 
03267   dbus_bool_t retval;
03268   sigset_t new_set, old_set;
03269 
03270   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03271   retval = FALSE;
03272 
03273   /* We need to block any existing handlers for SIGCHLD temporarily; they
03274    * will cause waitpid() below to fail.
03275    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
03276    */
03277   sigemptyset (&new_set);
03278   sigaddset (&new_set, SIGCHLD);
03279   sigprocmask (SIG_BLOCK, &new_set, &old_set);
03280 
03281   orig_len = _dbus_string_get_length (result);
03282 
03283 #define READ_END        0
03284 #define WRITE_END       1
03285   if (pipe (result_pipe) < 0)
03286     {
03287       dbus_set_error (error, _dbus_error_from_errno (errno),
03288                       "Failed to create a pipe to call %s: %s",
03289                       progpath, _dbus_strerror (errno));
03290       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03291                      progpath, _dbus_strerror (errno));
03292       goto out;
03293     }
03294   if (pipe (errors_pipe) < 0)
03295     {
03296       dbus_set_error (error, _dbus_error_from_errno (errno),
03297                       "Failed to create a pipe to call %s: %s",
03298                       progpath, _dbus_strerror (errno));
03299       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03300                      progpath, _dbus_strerror (errno));
03301       goto out;
03302     }
03303 
03304   pid = fork ();
03305   if (pid < 0)
03306     {
03307       dbus_set_error (error, _dbus_error_from_errno (errno),
03308                       "Failed to fork() to call %s: %s",
03309                       progpath, _dbus_strerror (errno));
03310       _dbus_verbose ("Failed to fork() to call %s: %s\n",
03311                      progpath, _dbus_strerror (errno));
03312       goto out;
03313     }
03314 
03315   if (pid == 0)
03316     {
03317       /* child process */
03318       int fd;
03319 
03320       fd = open ("/dev/null", O_RDWR);
03321       if (fd == -1)
03322         /* huh?! can't open /dev/null? */
03323         _exit (1);
03324 
03325       _dbus_verbose ("/dev/null fd %d opened\n", fd);
03326 
03327       /* set-up stdXXX */
03328       close (result_pipe[READ_END]);
03329       close (errors_pipe[READ_END]);
03330       close (0);                /* close stdin */
03331       close (1);                /* close stdout */
03332       close (2);                /* close stderr */
03333 
03334       if (dup2 (fd, 0) == -1)
03335         _exit (1);
03336       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03337         _exit (1);
03338       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03339         _exit (1);
03340 
03341       _dbus_close_all ();
03342 
03343       sigprocmask (SIG_SETMASK, &old_set, NULL);
03344 
03345       /* If it looks fully-qualified, try execv first */
03346       if (progpath[0] == '/')
03347         {
03348           execv (progpath, argv);
03349           /* Ok, that failed.  Now if path_fallback is given, let's
03350            * try unqualified.  This is mostly a hack to work
03351            * around systems which ship dbus-launch in /usr/bin
03352            * but everything else in /bin (because dbus-launch
03353            * depends on X11).
03354            */
03355           if (path_fallback)
03356             /* We must have a slash, because we checked above */
03357             execvp (strrchr (progpath, '/')+1, argv);
03358         }
03359       else
03360         execvp (progpath, argv);
03361 
03362       /* still nothing, we failed */
03363       _exit (1);
03364     }
03365 
03366   /* parent process */
03367   close (result_pipe[WRITE_END]);
03368   close (errors_pipe[WRITE_END]);
03369   result_pipe[WRITE_END] = -1;
03370   errors_pipe[WRITE_END] = -1;
03371 
03372   ret = 0;
03373   do
03374     {
03375       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03376     }
03377   while (ret > 0);
03378 
03379   /* reap the child process to avoid it lingering as zombie */
03380   do
03381     {
03382       ret = waitpid (pid, &status, 0);
03383     }
03384   while (ret == -1 && errno == EINTR);
03385 
03386   /* We succeeded if the process exited with status 0 and
03387      anything was read */
03388   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03389     {
03390       /* The process ended with error */
03391       DBusString error_message;
03392       if (!_dbus_string_init (&error_message))
03393         {
03394           _DBUS_SET_OOM (error);
03395           goto out;
03396         }
03397 
03398       ret = 0;
03399       do
03400         {
03401           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03402         }
03403       while (ret > 0);
03404 
03405       _dbus_string_set_length (result, orig_len);
03406       if (_dbus_string_get_length (&error_message) > 0)
03407         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03408                         "%s terminated abnormally with the following error: %s",
03409                         progpath, _dbus_string_get_data (&error_message));
03410       else
03411         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03412                         "%s terminated abnormally without any error message",
03413                         progpath);
03414       goto out;
03415     }
03416 
03417   retval = TRUE;
03418 
03419  out:
03420   sigprocmask (SIG_SETMASK, &old_set, NULL);
03421 
03422   if (retval)
03423     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03424   else
03425     _DBUS_ASSERT_ERROR_IS_SET (error);
03426 
03427   if (result_pipe[0] != -1)
03428     close (result_pipe[0]);
03429   if (result_pipe[1] != -1)
03430     close (result_pipe[1]);
03431   if (errors_pipe[0] != -1)
03432     close (errors_pipe[0]);
03433   if (errors_pipe[1] != -1)
03434     close (errors_pipe[1]);
03435 
03436   return retval;
03437 }
03438 
03450 dbus_bool_t
03451 _dbus_get_autolaunch_address (const char *scope,
03452                               DBusString *address,
03453                               DBusError  *error)
03454 {
03455 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
03456   /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
03457    * but that's done elsewhere, and if it worked, this function wouldn't
03458    * be called.) */
03459   const char *display;
03460   static char *argv[6];
03461   int i;
03462   DBusString uuid;
03463   dbus_bool_t retval;
03464 
03465   if (_dbus_check_setuid ())
03466     {
03467       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03468                             "Unable to autolaunch when setuid");
03469       return FALSE;
03470     }
03471 
03472   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03473   retval = FALSE;
03474 
03475   /* fd.o #19997: if $DISPLAY isn't set to something useful, then
03476    * dbus-launch-x11 is just going to fail. Rather than trying to
03477    * run it, we might as well bail out early with a nice error. */
03478   display = _dbus_getenv ("DISPLAY");
03479 
03480   if (display == NULL || display[0] == '\0')
03481     {
03482       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03483           "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
03484       return FALSE;
03485     }
03486 
03487   if (!_dbus_string_init (&uuid))
03488     {
03489       _DBUS_SET_OOM (error);
03490       return FALSE;
03491     }
03492 
03493   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03494     {
03495       _DBUS_SET_OOM (error);
03496       goto out;
03497     }
03498 
03499   i = 0;
03500   argv[i] = "dbus-launch";
03501   ++i;
03502   argv[i] = "--autolaunch";
03503   ++i;
03504   argv[i] = _dbus_string_get_data (&uuid);
03505   ++i;
03506   argv[i] = "--binary-syntax";
03507   ++i;
03508   argv[i] = "--close-stderr";
03509   ++i;
03510   argv[i] = NULL;
03511   ++i;
03512 
03513   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03514 
03515   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03516                                        TRUE,
03517                                        argv, address, error);
03518 
03519  out:
03520   _dbus_string_free (&uuid);
03521   return retval;
03522 #else
03523   dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03524       "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
03525       "set your DBUS_SESSION_BUS_ADDRESS instead");
03526   return FALSE;
03527 #endif
03528 }
03529 
03548 dbus_bool_t
03549 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03550                                dbus_bool_t create_if_not_found,
03551                                DBusError  *error)
03552 {
03553   DBusString filename;
03554   dbus_bool_t b;
03555 
03556   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03557 
03558   b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03559   if (b)
03560     return TRUE;
03561 
03562   dbus_error_free (error);
03563 
03564   /* Fallback to the system machine ID */
03565   _dbus_string_init_const (&filename, "/etc/machine-id");
03566   return _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
03567 }
03568 
03569 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03570 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03571 
03578 dbus_bool_t
03579 _dbus_lookup_launchd_socket (DBusString *socket_path,
03580                              const char *launchd_env_var,
03581                              DBusError  *error)
03582 {
03583 #ifdef DBUS_ENABLE_LAUNCHD
03584   char *argv[4];
03585   int i;
03586 
03587   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03588 
03589   if (_dbus_check_setuid ())
03590     {
03591       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03592                             "Unable to find launchd socket when setuid");
03593       return FALSE;
03594     }
03595 
03596   i = 0;
03597   argv[i] = "launchctl";
03598   ++i;
03599   argv[i] = "getenv";
03600   ++i;
03601   argv[i] = (char*)launchd_env_var;
03602   ++i;
03603   argv[i] = NULL;
03604   ++i;
03605 
03606   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03607 
03608   if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
03609     {
03610       return FALSE;
03611     }
03612 
03613   /* no error, but no result either */
03614   if (_dbus_string_get_length(socket_path) == 0)
03615     {
03616       return FALSE;
03617     }
03618 
03619   /* strip the carriage-return */
03620   _dbus_string_shorten(socket_path, 1);
03621   return TRUE;
03622 #else /* DBUS_ENABLE_LAUNCHD */
03623   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03624                 "can't lookup socket from launchd; launchd support not compiled in");
03625   return FALSE;
03626 #endif
03627 }
03628 
03629 #ifdef DBUS_ENABLE_LAUNCHD
03630 static dbus_bool_t
03631 _dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
03632 {
03633   dbus_bool_t valid_socket;
03634   DBusString socket_path;
03635 
03636   if (_dbus_check_setuid ())
03637     {
03638       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03639                             "Unable to find launchd socket when setuid");
03640       return FALSE;
03641     }
03642 
03643   if (!_dbus_string_init (&socket_path))
03644     {
03645       _DBUS_SET_OOM (error);
03646       return FALSE;
03647     }
03648 
03649   valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
03650 
03651   if (dbus_error_is_set(error))
03652     {
03653       _dbus_string_free(&socket_path);
03654       return FALSE;
03655     }
03656 
03657   if (!valid_socket)
03658     {
03659       dbus_set_error(error, "no socket path",
03660                 "launchd did not provide a socket path, "
03661                 "verify that org.freedesktop.dbus-session.plist is loaded!");
03662       _dbus_string_free(&socket_path);
03663       return FALSE;
03664     }
03665   if (!_dbus_string_append (address, "unix:path="))
03666     {
03667       _DBUS_SET_OOM (error);
03668       _dbus_string_free(&socket_path);
03669       return FALSE;
03670     }
03671   if (!_dbus_string_copy (&socket_path, 0, address,
03672                           _dbus_string_get_length (address)))
03673     {
03674       _DBUS_SET_OOM (error);
03675       _dbus_string_free(&socket_path);
03676       return FALSE;
03677     }
03678 
03679   _dbus_string_free(&socket_path);
03680   return TRUE;
03681 }
03682 #endif
03683 
03703 dbus_bool_t
03704 _dbus_lookup_session_address (dbus_bool_t *supported,
03705                               DBusString  *address,
03706                               DBusError   *error)
03707 {
03708 #ifdef DBUS_ENABLE_LAUNCHD
03709   *supported = TRUE;
03710   return _dbus_lookup_session_address_launchd (address, error);
03711 #else
03712   /* On non-Mac Unix platforms, if the session address isn't already
03713    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03714    * fall back to the autolaunch: global default; see
03715    * init_session_address in dbus/dbus-bus.c. */
03716   *supported = FALSE;
03717   return TRUE;
03718 #endif
03719 }
03720 
03738 dbus_bool_t
03739 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03740 {
03741   const char *xdg_data_home;
03742   const char *xdg_data_dirs;
03743   DBusString servicedir_path;
03744 
03745   if (!_dbus_string_init (&servicedir_path))
03746     return FALSE;
03747 
03748   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03749   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03750 
03751   if (xdg_data_home != NULL)
03752     {
03753       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03754         goto oom;
03755     }
03756   else
03757     {
03758       const DBusString *homedir;
03759       DBusString local_share;
03760 
03761       if (!_dbus_homedir_from_current_process (&homedir))
03762         goto oom;
03763 
03764       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03765         goto oom;
03766 
03767       _dbus_string_init_const (&local_share, "/.local/share");
03768       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03769         goto oom;
03770     }
03771 
03772   if (!_dbus_string_append (&servicedir_path, ":"))
03773     goto oom;
03774 
03775   if (xdg_data_dirs != NULL)
03776     {
03777       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03778         goto oom;
03779 
03780       if (!_dbus_string_append (&servicedir_path, ":"))
03781         goto oom;
03782     }
03783   else
03784     {
03785       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03786         goto oom;
03787     }
03788 
03789   /*
03790    * add configured datadir to defaults
03791    * this may be the same as an xdg dir
03792    * however the config parser should take
03793    * care of duplicates
03794    */
03795   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
03796     goto oom;
03797 
03798   if (!_dbus_split_paths_and_append (&servicedir_path,
03799                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03800                                      dirs))
03801     goto oom;
03802 
03803   _dbus_string_free (&servicedir_path);
03804   return TRUE;
03805 
03806  oom:
03807   _dbus_string_free (&servicedir_path);
03808   return FALSE;
03809 }
03810 
03811 
03830 dbus_bool_t
03831 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03832 {
03833   /*
03834    * DBUS_DATADIR may be the same as one of the standard directories. However,
03835    * the config parser should take care of the duplicates.
03836    *
03837    * Also, append /lib as counterpart of /usr/share on the root
03838    * directory (the root directory does not know /share), in order to
03839    * facilitate early boot system bus activation where /usr might not
03840    * be available.
03841    */
03842   static const char standard_search_path[] =
03843     "/usr/local/share:"
03844     "/usr/share:"
03845     DBUS_DATADIR ":"
03846     "/lib";
03847   DBusString servicedir_path;
03848 
03849   _dbus_string_init_const (&servicedir_path, standard_search_path);
03850 
03851   return _dbus_split_paths_and_append (&servicedir_path,
03852                                        DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03853                                        dirs);
03854 }
03855 
03864 dbus_bool_t
03865 _dbus_append_system_config_file (DBusString *str)
03866 {
03867   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03868 }
03869 
03876 dbus_bool_t
03877 _dbus_append_session_config_file (DBusString *str)
03878 {
03879   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03880 }
03881 
03889 void
03890 _dbus_flush_caches (void)
03891 {
03892   _dbus_user_database_flush_system ();
03893 }
03894 
03908 dbus_bool_t
03909 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03910                                                 DBusCredentials *credentials)
03911 {
03912   DBusString homedir;
03913   DBusString dotdir;
03914   dbus_uid_t uid;
03915 
03916   _dbus_assert (credentials != NULL);
03917   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03918 
03919   if (!_dbus_string_init (&homedir))
03920     return FALSE;
03921 
03922   uid = _dbus_credentials_get_unix_uid (credentials);
03923   _dbus_assert (uid != DBUS_UID_UNSET);
03924 
03925   if (!_dbus_homedir_from_uid (uid, &homedir))
03926     goto failed;
03927 
03928 #ifdef DBUS_BUILD_TESTS
03929   {
03930     const char *override;
03931 
03932     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03933     if (override != NULL && *override != '\0')
03934       {
03935         _dbus_string_set_length (&homedir, 0);
03936         if (!_dbus_string_append (&homedir, override))
03937           goto failed;
03938 
03939         _dbus_verbose ("Using fake homedir for testing: %s\n",
03940                        _dbus_string_get_const_data (&homedir));
03941       }
03942     else
03943       {
03944         static dbus_bool_t already_warned = FALSE;
03945         if (!already_warned)
03946           {
03947             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03948             already_warned = TRUE;
03949           }
03950       }
03951   }
03952 #endif
03953 
03954   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03955   if (!_dbus_concat_dir_and_file (&homedir,
03956                                   &dotdir))
03957     goto failed;
03958 
03959   if (!_dbus_string_copy (&homedir, 0,
03960                           directory, _dbus_string_get_length (directory))) {
03961     goto failed;
03962   }
03963 
03964   _dbus_string_free (&homedir);
03965   return TRUE;
03966 
03967  failed:
03968   _dbus_string_free (&homedir);
03969   return FALSE;
03970 }
03971 
03972 //PENDING(kdab) docs
03973 dbus_bool_t
03974 _dbus_daemon_publish_session_bus_address (const char* addr,
03975                                           const char *scope)
03976 {
03977   return TRUE;
03978 }
03979 
03980 //PENDING(kdab) docs
03981 void
03982 _dbus_daemon_unpublish_session_bus_address (void)
03983 {
03984 
03985 }
03986 
03993 dbus_bool_t
03994 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03995 {
03996   return errno == EAGAIN || errno == EWOULDBLOCK;
03997 }
03998 
04006 dbus_bool_t
04007 _dbus_delete_directory (const DBusString *filename,
04008                         DBusError        *error)
04009 {
04010   const char *filename_c;
04011 
04012   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
04013 
04014   filename_c = _dbus_string_get_const_data (filename);
04015 
04016   if (rmdir (filename_c) != 0)
04017     {
04018       dbus_set_error (error, DBUS_ERROR_FAILED,
04019                       "Failed to remove directory %s: %s\n",
04020                       filename_c, _dbus_strerror (errno));
04021       return FALSE;
04022     }
04023 
04024   return TRUE;
04025 }
04026 
04034 dbus_bool_t
04035 _dbus_socket_can_pass_unix_fd(int fd) {
04036 
04037 #ifdef SCM_RIGHTS
04038   union {
04039     struct sockaddr sa;
04040     struct sockaddr_storage storage;
04041     struct sockaddr_un un;
04042   } sa_buf;
04043 
04044   socklen_t sa_len = sizeof(sa_buf);
04045 
04046   _DBUS_ZERO(sa_buf);
04047 
04048   if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
04049     return FALSE;
04050 
04051   return sa_buf.sa.sa_family == AF_UNIX;
04052 
04053 #else
04054   return FALSE;
04055 
04056 #endif
04057 }
04058 
04059 
04060 /*
04061  * replaces the term DBUS_PREFIX in configure_time_path by the
04062  * current dbus installation directory. On unix this function is a noop
04063  *
04064  * @param configure_time_path
04065  * @return real path
04066  */
04067 const char *
04068 _dbus_replace_install_prefix (const char *configure_time_path)
04069 {
04070   return configure_time_path;
04071 }
04072 
04077 void
04078 _dbus_close_all (void)
04079 {
04080   int maxfds, i;
04081 
04082 #ifdef __linux__
04083   DIR *d;
04084 
04085   /* On Linux we can optimize this a bit if /proc is available. If it
04086      isn't available, fall back to the brute force way. */
04087 
04088   d = opendir ("/proc/self/fd");
04089   if (d)
04090     {
04091       for (;;)
04092         {
04093           struct dirent buf, *de;
04094           int k, fd;
04095           long l;
04096           char *e = NULL;
04097 
04098           k = readdir_r (d, &buf, &de);
04099           if (k != 0 || !de)
04100             break;
04101 
04102           if (de->d_name[0] == '.')
04103             continue;
04104 
04105           errno = 0;
04106           l = strtol (de->d_name, &e, 10);
04107           if (errno != 0 || e == NULL || *e != '\0')
04108             continue;
04109 
04110           fd = (int) l;
04111           if (fd < 3)
04112             continue;
04113 
04114           if (fd == dirfd (d))
04115             continue;
04116 
04117           close (fd);
04118         }
04119 
04120       closedir (d);
04121       return;
04122     }
04123 #endif
04124 
04125   maxfds = sysconf (_SC_OPEN_MAX);
04126 
04127   /* Pick something reasonable if for some reason sysconf says
04128    * unlimited.
04129    */
04130   if (maxfds < 0)
04131     maxfds = 1024;
04132 
04133   /* close all inherited fds */
04134   for (i = 3; i < maxfds; i++)
04135     close (i);
04136 }
04137 
04147 dbus_bool_t
04148 _dbus_check_setuid (void)
04149 {
04150   /* TODO: get __libc_enable_secure exported from glibc.
04151    * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
04152    */
04153 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
04154   {
04155     /* See glibc/include/unistd.h */
04156     extern int __libc_enable_secure;
04157     return __libc_enable_secure;
04158   }
04159 #elif defined(HAVE_ISSETUGID)
04160   /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
04161   return issetugid ();
04162 #else
04163   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
04164   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
04165 
04166   static dbus_bool_t check_setuid_initialised;
04167   static dbus_bool_t is_setuid;
04168 
04169   if (_DBUS_UNLIKELY (!check_setuid_initialised))
04170     {
04171 #ifdef HAVE_GETRESUID
04172       if (getresuid (&ruid, &euid, &suid) != 0 ||
04173           getresgid (&rgid, &egid, &sgid) != 0)
04174 #endif /* HAVE_GETRESUID */
04175         {
04176           suid = ruid = getuid ();
04177           sgid = rgid = getgid ();
04178           euid = geteuid ();
04179           egid = getegid ();
04180         }
04181 
04182       check_setuid_initialised = TRUE;
04183       is_setuid = (ruid != euid || ruid != suid ||
04184                    rgid != egid || rgid != sgid);
04185 
04186     }
04187   return is_setuid;
04188 #endif
04189 }
04190 
04191 /* tests in dbus-sysdeps-util.c */