D-Bus 1.4.20

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 
00075 #ifdef HAVE_ADT
00076 #include <bsm/adt.h>
00077 #endif
00078 
00079 #include "sd-daemon.h"
00080 
00081 #ifndef O_BINARY
00082 #define O_BINARY 0
00083 #endif
00084 
00085 #ifndef AI_ADDRCONFIG
00086 #define AI_ADDRCONFIG 0
00087 #endif
00088 
00089 #ifndef HAVE_SOCKLEN_T
00090 #define socklen_t int
00091 #endif
00092 
00093 #if defined (__sun) || defined (__sun__)
00094 /*
00095  * CMS_SPACE etc. definitions for Solaris < 10, based on
00096  *   http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
00097  * via
00098  *   http://wiki.opencsw.org/porting-faq#toc10
00099  *
00100  * These are only redefined for Solaris, for now: if your OS needs these too,
00101  * please file a bug. (Or preferably, improve your OS so they're not needed.)
00102  */
00103 
00104 # ifndef CMSG_ALIGN
00105 #   ifdef __sun__
00106 #     define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
00107 #   else
00108       /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
00109 #     define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
00110                               ~(sizeof (long) - 1))
00111 #   endif
00112 # endif
00113 
00114 # ifndef CMSG_SPACE
00115 #   define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
00116                             CMSG_ALIGN (len))
00117 # endif
00118 
00119 # ifndef CMSG_LEN
00120 #   define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
00121 # endif
00122 
00123 #endif /* Solaris */
00124 
00125 static dbus_bool_t
00126 _dbus_open_socket (int              *fd_p,
00127                    int               domain,
00128                    int               type,
00129                    int               protocol,
00130                    DBusError        *error)
00131 {
00132 #ifdef SOCK_CLOEXEC
00133   dbus_bool_t cloexec_done;
00134 
00135   *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
00136   cloexec_done = *fd_p >= 0;
00137 
00138   /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
00139   if (*fd_p < 0 && errno == EINVAL)
00140 #endif
00141     {
00142       *fd_p = socket (domain, type, protocol);
00143     }
00144 
00145   if (*fd_p >= 0)
00146     {
00147 #ifdef SOCK_CLOEXEC
00148       if (!cloexec_done)
00149 #endif
00150         {
00151           _dbus_fd_set_close_on_exec(*fd_p);
00152         }
00153 
00154       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00155       return TRUE;
00156     }
00157   else
00158     {
00159       dbus_set_error(error,
00160                      _dbus_error_from_errno (errno),
00161                      "Failed to open socket: %s",
00162                      _dbus_strerror (errno));
00163       return FALSE;
00164     }
00165 }
00166 
00167 dbus_bool_t
00168 _dbus_open_tcp_socket (int              *fd,
00169                        DBusError        *error)
00170 {
00171   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00172 }
00173 
00184 dbus_bool_t
00185 _dbus_open_unix_socket (int              *fd,
00186                         DBusError        *error)
00187 {
00188   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00189 }
00190 
00199 dbus_bool_t
00200 _dbus_close_socket (int               fd,
00201                     DBusError        *error)
00202 {
00203   return _dbus_close (fd, error);
00204 }
00205 
00215 int
00216 _dbus_read_socket (int               fd,
00217                    DBusString       *buffer,
00218                    int               count)
00219 {
00220   return _dbus_read (fd, buffer, count);
00221 }
00222 
00233 int
00234 _dbus_write_socket (int               fd,
00235                     const DBusString *buffer,
00236                     int               start,
00237                     int               len)
00238 {
00239 #if HAVE_DECL_MSG_NOSIGNAL
00240   const char *data;
00241   int bytes_written;
00242 
00243   data = _dbus_string_get_const_data_len (buffer, start, len);
00244 
00245  again:
00246 
00247   bytes_written = send (fd, data, len, MSG_NOSIGNAL);
00248 
00249   if (bytes_written < 0 && errno == EINTR)
00250     goto again;
00251 
00252   return bytes_written;
00253 
00254 #else
00255   return _dbus_write (fd, buffer, start, len);
00256 #endif
00257 }
00258 
00271 int
00272 _dbus_read_socket_with_unix_fds (int               fd,
00273                                  DBusString       *buffer,
00274                                  int               count,
00275                                  int              *fds,
00276                                  int              *n_fds) {
00277 #ifndef HAVE_UNIX_FD_PASSING
00278   int r;
00279 
00280   if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
00281     return r;
00282 
00283   *n_fds = 0;
00284   return r;
00285 
00286 #else
00287   int bytes_read;
00288   int start;
00289   struct msghdr m;
00290   struct iovec iov;
00291 
00292   _dbus_assert (count >= 0);
00293   _dbus_assert (*n_fds >= 0);
00294 
00295   start = _dbus_string_get_length (buffer);
00296 
00297   if (!_dbus_string_lengthen (buffer, count))
00298     {
00299       errno = ENOMEM;
00300       return -1;
00301     }
00302 
00303   _DBUS_ZERO(iov);
00304   iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
00305   iov.iov_len = count;
00306 
00307   _DBUS_ZERO(m);
00308   m.msg_iov = &iov;
00309   m.msg_iovlen = 1;
00310 
00311   /* Hmm, we have no clue how long the control data will actually be
00312      that is queued for us. The least we can do is assume that the
00313      caller knows. Hence let's make space for the number of fds that
00314      we shall read at max plus the cmsg header. */
00315   m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
00316 
00317   /* It's probably safe to assume that systems with SCM_RIGHTS also
00318      know alloca() */
00319   m.msg_control = alloca(m.msg_controllen);
00320   memset(m.msg_control, 0, m.msg_controllen);
00321 
00322  again:
00323 
00324   bytes_read = recvmsg(fd, &m, 0
00325 #ifdef MSG_CMSG_CLOEXEC
00326                        |MSG_CMSG_CLOEXEC
00327 #endif
00328                        );
00329 
00330   if (bytes_read < 0)
00331     {
00332       if (errno == EINTR)
00333         goto again;
00334       else
00335         {
00336           /* put length back (note that this doesn't actually realloc anything) */
00337           _dbus_string_set_length (buffer, start);
00338           return -1;
00339         }
00340     }
00341   else
00342     {
00343       struct cmsghdr *cm;
00344       dbus_bool_t found = FALSE;
00345 
00346       if (m.msg_flags & MSG_CTRUNC)
00347         {
00348           /* Hmm, apparently the control data was truncated. The bad
00349              thing is that we might have completely lost a couple of fds
00350              without chance to recover them. Hence let's treat this as a
00351              serious error. */
00352 
00353           errno = ENOSPC;
00354           _dbus_string_set_length (buffer, start);
00355           return -1;
00356         }
00357 
00358       for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
00359         if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
00360           {
00361             unsigned i;
00362 
00363             _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
00364             *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
00365 
00366             memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
00367             found = TRUE;
00368 
00369             /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
00370                worked, hence we need to go through this list and set
00371                CLOEXEC everywhere in any case */
00372             for (i = 0; i < *n_fds; i++)
00373               _dbus_fd_set_close_on_exec(fds[i]);
00374 
00375             break;
00376           }
00377 
00378       if (!found)
00379         *n_fds = 0;
00380 
00381       /* put length back (doesn't actually realloc) */
00382       _dbus_string_set_length (buffer, start + bytes_read);
00383 
00384 #if 0
00385       if (bytes_read > 0)
00386         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00387 #endif
00388 
00389       return bytes_read;
00390     }
00391 #endif
00392 }
00393 
00394 int
00395 _dbus_write_socket_with_unix_fds(int               fd,
00396                                  const DBusString *buffer,
00397                                  int               start,
00398                                  int               len,
00399                                  const int        *fds,
00400                                  int               n_fds) {
00401 
00402 #ifndef HAVE_UNIX_FD_PASSING
00403 
00404   if (n_fds > 0) {
00405     errno = ENOTSUP;
00406     return -1;
00407   }
00408 
00409   return _dbus_write_socket(fd, buffer, start, len);
00410 #else
00411   return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
00412 #endif
00413 }
00414 
00415 int
00416 _dbus_write_socket_with_unix_fds_two(int               fd,
00417                                      const DBusString *buffer1,
00418                                      int               start1,
00419                                      int               len1,
00420                                      const DBusString *buffer2,
00421                                      int               start2,
00422                                      int               len2,
00423                                      const int        *fds,
00424                                      int               n_fds) {
00425 
00426 #ifndef HAVE_UNIX_FD_PASSING
00427 
00428   if (n_fds > 0) {
00429     errno = ENOTSUP;
00430     return -1;
00431   }
00432 
00433   return _dbus_write_socket_two(fd,
00434                                 buffer1, start1, len1,
00435                                 buffer2, start2, len2);
00436 #else
00437 
00438   struct msghdr m;
00439   struct cmsghdr *cm;
00440   struct iovec iov[2];
00441   int bytes_written;
00442 
00443   _dbus_assert (len1 >= 0);
00444   _dbus_assert (len2 >= 0);
00445   _dbus_assert (n_fds >= 0);
00446 
00447   _DBUS_ZERO(iov);
00448   iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
00449   iov[0].iov_len = len1;
00450 
00451   if (buffer2)
00452     {
00453       iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
00454       iov[1].iov_len = len2;
00455     }
00456 
00457   _DBUS_ZERO(m);
00458   m.msg_iov = iov;
00459   m.msg_iovlen = buffer2 ? 2 : 1;
00460 
00461   if (n_fds > 0)
00462     {
00463       m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
00464       m.msg_control = alloca(m.msg_controllen);
00465       memset(m.msg_control, 0, m.msg_controllen);
00466 
00467       cm = CMSG_FIRSTHDR(&m);
00468       cm->cmsg_level = SOL_SOCKET;
00469       cm->cmsg_type = SCM_RIGHTS;
00470       cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
00471       memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
00472     }
00473 
00474  again:
00475 
00476   bytes_written = sendmsg (fd, &m, 0
00477 #if HAVE_DECL_MSG_NOSIGNAL
00478                            |MSG_NOSIGNAL
00479 #endif
00480                            );
00481 
00482   if (bytes_written < 0 && errno == EINTR)
00483     goto again;
00484 
00485 #if 0
00486   if (bytes_written > 0)
00487     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00488 #endif
00489 
00490   return bytes_written;
00491 #endif
00492 }
00493 
00507 int
00508 _dbus_write_socket_two (int               fd,
00509                         const DBusString *buffer1,
00510                         int               start1,
00511                         int               len1,
00512                         const DBusString *buffer2,
00513                         int               start2,
00514                         int               len2)
00515 {
00516 #if HAVE_DECL_MSG_NOSIGNAL
00517   struct iovec vectors[2];
00518   const char *data1;
00519   const char *data2;
00520   int bytes_written;
00521   struct msghdr m;
00522 
00523   _dbus_assert (buffer1 != NULL);
00524   _dbus_assert (start1 >= 0);
00525   _dbus_assert (start2 >= 0);
00526   _dbus_assert (len1 >= 0);
00527   _dbus_assert (len2 >= 0);
00528 
00529   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00530 
00531   if (buffer2 != NULL)
00532     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00533   else
00534     {
00535       data2 = NULL;
00536       start2 = 0;
00537       len2 = 0;
00538     }
00539 
00540   vectors[0].iov_base = (char*) data1;
00541   vectors[0].iov_len = len1;
00542   vectors[1].iov_base = (char*) data2;
00543   vectors[1].iov_len = len2;
00544 
00545   _DBUS_ZERO(m);
00546   m.msg_iov = vectors;
00547   m.msg_iovlen = data2 ? 2 : 1;
00548 
00549  again:
00550 
00551   bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
00552 
00553   if (bytes_written < 0 && errno == EINTR)
00554     goto again;
00555 
00556   return bytes_written;
00557 
00558 #else
00559   return _dbus_write_two (fd, buffer1, start1, len1,
00560                           buffer2, start2, len2);
00561 #endif
00562 }
00563 
00564 dbus_bool_t
00565 _dbus_socket_is_invalid (int fd)
00566 {
00567     return fd < 0 ? TRUE : FALSE;
00568 }
00569 
00586 int
00587 _dbus_read (int               fd,
00588             DBusString       *buffer,
00589             int               count)
00590 {
00591   int bytes_read;
00592   int start;
00593   char *data;
00594 
00595   _dbus_assert (count >= 0);
00596 
00597   start = _dbus_string_get_length (buffer);
00598 
00599   if (!_dbus_string_lengthen (buffer, count))
00600     {
00601       errno = ENOMEM;
00602       return -1;
00603     }
00604 
00605   data = _dbus_string_get_data_len (buffer, start, count);
00606 
00607  again:
00608 
00609   bytes_read = read (fd, data, count);
00610 
00611   if (bytes_read < 0)
00612     {
00613       if (errno == EINTR)
00614         goto again;
00615       else
00616         {
00617           /* put length back (note that this doesn't actually realloc anything) */
00618           _dbus_string_set_length (buffer, start);
00619           return -1;
00620         }
00621     }
00622   else
00623     {
00624       /* put length back (doesn't actually realloc) */
00625       _dbus_string_set_length (buffer, start + bytes_read);
00626 
00627 #if 0
00628       if (bytes_read > 0)
00629         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00630 #endif
00631 
00632       return bytes_read;
00633     }
00634 }
00635 
00646 int
00647 _dbus_write (int               fd,
00648              const DBusString *buffer,
00649              int               start,
00650              int               len)
00651 {
00652   const char *data;
00653   int bytes_written;
00654 
00655   data = _dbus_string_get_const_data_len (buffer, start, len);
00656 
00657  again:
00658 
00659   bytes_written = write (fd, data, len);
00660 
00661   if (bytes_written < 0 && errno == EINTR)
00662     goto again;
00663 
00664 #if 0
00665   if (bytes_written > 0)
00666     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00667 #endif
00668 
00669   return bytes_written;
00670 }
00671 
00692 int
00693 _dbus_write_two (int               fd,
00694                  const DBusString *buffer1,
00695                  int               start1,
00696                  int               len1,
00697                  const DBusString *buffer2,
00698                  int               start2,
00699                  int               len2)
00700 {
00701   _dbus_assert (buffer1 != NULL);
00702   _dbus_assert (start1 >= 0);
00703   _dbus_assert (start2 >= 0);
00704   _dbus_assert (len1 >= 0);
00705   _dbus_assert (len2 >= 0);
00706 
00707 #ifdef HAVE_WRITEV
00708   {
00709     struct iovec vectors[2];
00710     const char *data1;
00711     const char *data2;
00712     int bytes_written;
00713 
00714     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00715 
00716     if (buffer2 != NULL)
00717       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00718     else
00719       {
00720         data2 = NULL;
00721         start2 = 0;
00722         len2 = 0;
00723       }
00724 
00725     vectors[0].iov_base = (char*) data1;
00726     vectors[0].iov_len = len1;
00727     vectors[1].iov_base = (char*) data2;
00728     vectors[1].iov_len = len2;
00729 
00730   again:
00731 
00732     bytes_written = writev (fd,
00733                             vectors,
00734                             data2 ? 2 : 1);
00735 
00736     if (bytes_written < 0 && errno == EINTR)
00737       goto again;
00738 
00739     return bytes_written;
00740   }
00741 #else /* HAVE_WRITEV */
00742   {
00743     int ret1;
00744 
00745     ret1 = _dbus_write (fd, buffer1, start1, len1);
00746     if (ret1 == len1 && buffer2 != NULL)
00747       {
00748         ret2 = _dbus_write (fd, buffer2, start2, len2);
00749         if (ret2 < 0)
00750           ret2 = 0; /* we can't report an error as the first write was OK */
00751 
00752         return ret1 + ret2;
00753       }
00754     else
00755       return ret1;
00756   }
00757 #endif /* !HAVE_WRITEV */
00758 }
00759 
00760 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00761 
00791 int
00792 _dbus_connect_unix_socket (const char     *path,
00793                            dbus_bool_t     abstract,
00794                            DBusError      *error)
00795 {
00796   int fd;
00797   size_t path_len;
00798   struct sockaddr_un addr;
00799 
00800   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00801 
00802   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00803                  path, abstract);
00804 
00805 
00806   if (!_dbus_open_unix_socket (&fd, error))
00807     {
00808       _DBUS_ASSERT_ERROR_IS_SET(error);
00809       return -1;
00810     }
00811   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00812 
00813   _DBUS_ZERO (addr);
00814   addr.sun_family = AF_UNIX;
00815   path_len = strlen (path);
00816 
00817   if (abstract)
00818     {
00819 #ifdef HAVE_ABSTRACT_SOCKETS
00820       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00821       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00822 
00823       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00824         {
00825           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00826                       "Abstract socket name too long\n");
00827           _dbus_close (fd, NULL);
00828           return -1;
00829         }
00830 
00831       strncpy (&addr.sun_path[1], path, path_len);
00832       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00833 #else /* HAVE_ABSTRACT_SOCKETS */
00834       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00835                       "Operating system does not support abstract socket namespace\n");
00836       _dbus_close (fd, NULL);
00837       return -1;
00838 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00839     }
00840   else
00841     {
00842       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00843         {
00844           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00845                       "Socket name too long\n");
00846           _dbus_close (fd, NULL);
00847           return -1;
00848         }
00849 
00850       strncpy (addr.sun_path, path, path_len);
00851     }
00852 
00853   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00854     {
00855       dbus_set_error (error,
00856                       _dbus_error_from_errno (errno),
00857                       "Failed to connect to socket %s: %s",
00858                       path, _dbus_strerror (errno));
00859 
00860       _dbus_close (fd, NULL);
00861       return -1;
00862     }
00863 
00864   if (!_dbus_set_fd_nonblocking (fd, error))
00865     {
00866       _DBUS_ASSERT_ERROR_IS_SET (error);
00867 
00868       _dbus_close (fd, NULL);
00869       return -1;
00870     }
00871 
00872   return fd;
00873 }
00874 
00884 static dbus_bool_t
00885 _dbus_set_local_creds (int fd, dbus_bool_t on)
00886 {
00887   dbus_bool_t retval = TRUE;
00888 
00889 #if defined(HAVE_CMSGCRED)
00890   /* NOOP just to make sure only one codepath is used
00891    *      and to prefer CMSGCRED
00892    */
00893 #elif defined(LOCAL_CREDS)
00894   int val = on ? 1 : 0;
00895   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00896     {
00897       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00898       retval = FALSE;
00899     }
00900   else
00901     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00902                    on ? "enabled" : "disabled", fd);
00903 #endif
00904 
00905   return retval;
00906 }
00907 
00925 int
00926 _dbus_listen_unix_socket (const char     *path,
00927                           dbus_bool_t     abstract,
00928                           DBusError      *error)
00929 {
00930   int listen_fd;
00931   struct sockaddr_un addr;
00932   size_t path_len;
00933   unsigned int reuseaddr;
00934 
00935   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00936 
00937   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00938                  path, abstract);
00939 
00940   if (!_dbus_open_unix_socket (&listen_fd, error))
00941     {
00942       _DBUS_ASSERT_ERROR_IS_SET(error);
00943       return -1;
00944     }
00945   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00946 
00947   _DBUS_ZERO (addr);
00948   addr.sun_family = AF_UNIX;
00949   path_len = strlen (path);
00950 
00951   if (abstract)
00952     {
00953 #ifdef HAVE_ABSTRACT_SOCKETS
00954       /* remember that abstract names aren't nul-terminated so we rely
00955        * on sun_path being filled in with zeroes above.
00956        */
00957       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00958       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00959 
00960       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00961         {
00962           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00963                       "Abstract socket name too long\n");
00964           _dbus_close (listen_fd, NULL);
00965           return -1;
00966         }
00967 
00968       strncpy (&addr.sun_path[1], path, path_len);
00969       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00970 #else /* HAVE_ABSTRACT_SOCKETS */
00971       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00972                       "Operating system does not support abstract socket namespace\n");
00973       _dbus_close (listen_fd, NULL);
00974       return -1;
00975 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00976     }
00977   else
00978     {
00979       /* Discussed security implications of this with Nalin,
00980        * and we couldn't think of where it would kick our ass, but
00981        * it still seems a bit sucky. It also has non-security suckage;
00982        * really we'd prefer to exit if the socket is already in use.
00983        * But there doesn't seem to be a good way to do this.
00984        *
00985        * Just to be extra careful, I threw in the stat() - clearly
00986        * the stat() can't *fix* any security issue, but it at least
00987        * avoids inadvertent/accidental data loss.
00988        */
00989       {
00990         struct stat sb;
00991 
00992         if (stat (path, &sb) == 0 &&
00993             S_ISSOCK (sb.st_mode))
00994           unlink (path);
00995       }
00996 
00997       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00998         {
00999           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01000                       "Abstract socket name too long\n");
01001           _dbus_close (listen_fd, NULL);
01002           return -1;
01003         }
01004 
01005       strncpy (addr.sun_path, path, path_len);
01006     }
01007 
01008   reuseaddr = 1;
01009   if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01010     {
01011       _dbus_warn ("Failed to set socket option\"%s\": %s",
01012                   path, _dbus_strerror (errno));
01013     }
01014 
01015   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
01016     {
01017       dbus_set_error (error, _dbus_error_from_errno (errno),
01018                       "Failed to bind socket \"%s\": %s",
01019                       path, _dbus_strerror (errno));
01020       _dbus_close (listen_fd, NULL);
01021       return -1;
01022     }
01023 
01024   if (listen (listen_fd, 30 /* backlog */) < 0)
01025     {
01026       dbus_set_error (error, _dbus_error_from_errno (errno),
01027                       "Failed to listen on socket \"%s\": %s",
01028                       path, _dbus_strerror (errno));
01029       _dbus_close (listen_fd, NULL);
01030       return -1;
01031     }
01032 
01033   if (!_dbus_set_local_creds (listen_fd, TRUE))
01034     {
01035       dbus_set_error (error, _dbus_error_from_errno (errno),
01036                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
01037                       path, _dbus_strerror (errno));
01038       close (listen_fd);
01039       return -1;
01040     }
01041 
01042   if (!_dbus_set_fd_nonblocking (listen_fd, error))
01043     {
01044       _DBUS_ASSERT_ERROR_IS_SET (error);
01045       _dbus_close (listen_fd, NULL);
01046       return -1;
01047     }
01048 
01049   /* Try opening up the permissions, but if we can't, just go ahead
01050    * and continue, maybe it will be good enough.
01051    */
01052   if (!abstract && chmod (path, 0777) < 0)
01053     _dbus_warn ("Could not set mode 0777 on socket %s\n",
01054                 path);
01055 
01056   return listen_fd;
01057 }
01058 
01069 int
01070 _dbus_listen_systemd_sockets (int       **fds,
01071                               DBusError *error)
01072 {
01073   int r, n;
01074   unsigned fd;
01075   int *new_fds;
01076 
01077   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01078 
01079   n = sd_listen_fds (TRUE);
01080   if (n < 0)
01081     {
01082       dbus_set_error (error, _dbus_error_from_errno (-n),
01083                       "Failed to acquire systemd socket: %s",
01084                       _dbus_strerror (-n));
01085       return -1;
01086     }
01087 
01088   if (n <= 0)
01089     {
01090       dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01091                       "No socket received.");
01092       return -1;
01093     }
01094 
01095   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01096     {
01097       r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
01098       if (r < 0)
01099         {
01100           dbus_set_error (error, _dbus_error_from_errno (-r),
01101                           "Failed to verify systemd socket type: %s",
01102                           _dbus_strerror (-r));
01103           return -1;
01104         }
01105 
01106       if (!r)
01107         {
01108           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01109                           "Passed socket has wrong type.");
01110           return -1;
01111         }
01112     }
01113 
01114   /* OK, the file descriptors are all good, so let's take posession of
01115      them then. */
01116 
01117   new_fds = dbus_new (int, n);
01118   if (!new_fds)
01119     {
01120       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
01121                       "Failed to allocate file handle array.");
01122       goto fail;
01123     }
01124 
01125   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01126     {
01127       if (!_dbus_set_local_creds (fd, TRUE))
01128         {
01129           dbus_set_error (error, _dbus_error_from_errno (errno),
01130                           "Failed to enable LOCAL_CREDS on systemd socket: %s",
01131                           _dbus_strerror (errno));
01132           goto fail;
01133         }
01134 
01135       if (!_dbus_set_fd_nonblocking (fd, error))
01136         {
01137           _DBUS_ASSERT_ERROR_IS_SET (error);
01138           goto fail;
01139         }
01140 
01141       new_fds[fd - SD_LISTEN_FDS_START] = fd;
01142     }
01143 
01144   *fds = new_fds;
01145   return n;
01146 
01147  fail:
01148 
01149   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01150     {
01151       _dbus_close (fd, NULL);
01152     }
01153 
01154   dbus_free (new_fds);
01155   return -1;
01156 }
01157 
01171 int
01172 _dbus_connect_tcp_socket (const char     *host,
01173                           const char     *port,
01174                           const char     *family,
01175                           DBusError      *error)
01176 {
01177     return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
01178 }
01179 
01180 int
01181 _dbus_connect_tcp_socket_with_nonce (const char     *host,
01182                                      const char     *port,
01183                                      const char     *family,
01184                                      const char     *noncefile,
01185                                      DBusError      *error)
01186 {
01187   int saved_errno = 0;
01188   int fd = -1, res;
01189   struct addrinfo hints;
01190   struct addrinfo *ai, *tmp;
01191 
01192   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01193 
01194   _DBUS_ZERO (hints);
01195 
01196   if (!family)
01197     hints.ai_family = AF_UNSPEC;
01198   else if (!strcmp(family, "ipv4"))
01199     hints.ai_family = AF_INET;
01200   else if (!strcmp(family, "ipv6"))
01201     hints.ai_family = AF_INET6;
01202   else
01203     {
01204       dbus_set_error (error,
01205                       DBUS_ERROR_BAD_ADDRESS,
01206                       "Unknown address family %s", family);
01207       return -1;
01208     }
01209   hints.ai_protocol = IPPROTO_TCP;
01210   hints.ai_socktype = SOCK_STREAM;
01211   hints.ai_flags = AI_ADDRCONFIG;
01212 
01213   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
01214     {
01215       dbus_set_error (error,
01216                       _dbus_error_from_errno (errno),
01217                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01218                       host, port, gai_strerror(res), res);
01219       return -1;
01220     }
01221 
01222   tmp = ai;
01223   while (tmp)
01224     {
01225       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01226         {
01227           freeaddrinfo(ai);
01228           _DBUS_ASSERT_ERROR_IS_SET(error);
01229           return -1;
01230         }
01231       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01232 
01233       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01234         {
01235           saved_errno = errno;
01236           _dbus_close(fd, NULL);
01237           fd = -1;
01238           tmp = tmp->ai_next;
01239           continue;
01240         }
01241 
01242       break;
01243     }
01244   freeaddrinfo(ai);
01245 
01246   if (fd == -1)
01247     {
01248       dbus_set_error (error,
01249                       _dbus_error_from_errno (saved_errno),
01250                       "Failed to connect to socket \"%s:%s\" %s",
01251                       host, port, _dbus_strerror(saved_errno));
01252       return -1;
01253     }
01254 
01255   if (noncefile != NULL)
01256     {
01257       DBusString noncefileStr;
01258       dbus_bool_t ret;
01259       _dbus_string_init_const (&noncefileStr, noncefile);
01260       ret = _dbus_send_nonce (fd, &noncefileStr, error);
01261       _dbus_string_free (&noncefileStr);
01262 
01263       if (!ret)
01264     {
01265       _dbus_close (fd, NULL);
01266           return -1;
01267         }
01268     }
01269 
01270   if (!_dbus_set_fd_nonblocking (fd, error))
01271     {
01272       _dbus_close (fd, NULL);
01273       return -1;
01274     }
01275 
01276   return fd;
01277 }
01278 
01295 int
01296 _dbus_listen_tcp_socket (const char     *host,
01297                          const char     *port,
01298                          const char     *family,
01299                          DBusString     *retport,
01300                          int           **fds_p,
01301                          DBusError      *error)
01302 {
01303   int saved_errno;
01304   int nlisten_fd = 0, *listen_fd = NULL, res, i;
01305   struct addrinfo hints;
01306   struct addrinfo *ai, *tmp;
01307   unsigned int reuseaddr;
01308 
01309   *fds_p = NULL;
01310   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01311 
01312   _DBUS_ZERO (hints);
01313 
01314   if (!family)
01315     hints.ai_family = AF_UNSPEC;
01316   else if (!strcmp(family, "ipv4"))
01317     hints.ai_family = AF_INET;
01318   else if (!strcmp(family, "ipv6"))
01319     hints.ai_family = AF_INET6;
01320   else
01321     {
01322       dbus_set_error (error,
01323                       DBUS_ERROR_BAD_ADDRESS,
01324                       "Unknown address family %s", family);
01325       return -1;
01326     }
01327 
01328   hints.ai_protocol = IPPROTO_TCP;
01329   hints.ai_socktype = SOCK_STREAM;
01330   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
01331 
01332  redo_lookup_with_port:
01333   ai = NULL;
01334   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01335     {
01336       dbus_set_error (error,
01337                       _dbus_error_from_errno (errno),
01338                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01339                       host ? host : "*", port, gai_strerror(res), res);
01340       goto failed;
01341     }
01342 
01343   tmp = ai;
01344   while (tmp)
01345     {
01346       int fd = -1, *newlisten_fd;
01347       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01348         {
01349           _DBUS_ASSERT_ERROR_IS_SET(error);
01350           goto failed;
01351         }
01352       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01353 
01354       reuseaddr = 1;
01355       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01356         {
01357           _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01358                       host ? host : "*", port, _dbus_strerror (errno));
01359         }
01360 
01361       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01362         {
01363           saved_errno = errno;
01364           _dbus_close(fd, NULL);
01365           if (saved_errno == EADDRINUSE)
01366             {
01367               /* Depending on kernel policy, it may or may not
01368                  be neccessary to bind to both IPv4 & 6 addresses
01369                  so ignore EADDRINUSE here */
01370               tmp = tmp->ai_next;
01371               continue;
01372             }
01373           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01374                           "Failed to bind socket \"%s:%s\": %s",
01375                           host ? host : "*", port, _dbus_strerror (saved_errno));
01376           goto failed;
01377         }
01378 
01379       if (listen (fd, 30 /* backlog */) < 0)
01380         {
01381           saved_errno = errno;
01382           _dbus_close (fd, NULL);
01383           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01384                           "Failed to listen on socket \"%s:%s\": %s",
01385                           host ? host : "*", port, _dbus_strerror (saved_errno));
01386           goto failed;
01387         }
01388 
01389       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
01390       if (!newlisten_fd)
01391         {
01392           saved_errno = errno;
01393           _dbus_close (fd, NULL);
01394           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01395                           "Failed to allocate file handle array: %s",
01396                           _dbus_strerror (saved_errno));
01397           goto failed;
01398         }
01399       listen_fd = newlisten_fd;
01400       listen_fd[nlisten_fd] = fd;
01401       nlisten_fd++;
01402 
01403       if (!_dbus_string_get_length(retport))
01404         {
01405           /* If the user didn't specify a port, or used 0, then
01406              the kernel chooses a port. After the first address
01407              is bound to, we need to force all remaining addresses
01408              to use the same port */
01409           if (!port || !strcmp(port, "0"))
01410             {
01411               int result;
01412               struct sockaddr_storage addr;
01413               socklen_t addrlen;
01414               char portbuf[50];
01415 
01416               addrlen = sizeof(addr);
01417               result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01418 
01419               if (result == -1 ||
01420                   (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
01421                                       portbuf, sizeof(portbuf),
01422                                       NI_NUMERICHOST)) != 0)
01423                 {
01424                   dbus_set_error (error, _dbus_error_from_errno (errno),
01425                                   "Failed to resolve port \"%s:%s\": %s (%s)",
01426                                   host ? host : "*", port, gai_strerror(res), res);
01427                   goto failed;
01428                 }
01429               if (!_dbus_string_append(retport, portbuf))
01430                 {
01431                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01432                   goto failed;
01433                 }
01434 
01435               /* Release current address list & redo lookup */
01436               port = _dbus_string_get_const_data(retport);
01437               freeaddrinfo(ai);
01438               goto redo_lookup_with_port;
01439             }
01440           else
01441             {
01442               if (!_dbus_string_append(retport, port))
01443                 {
01444                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01445                     goto failed;
01446                 }
01447             }
01448         }
01449 
01450       tmp = tmp->ai_next;
01451     }
01452   freeaddrinfo(ai);
01453   ai = NULL;
01454 
01455   if (!nlisten_fd)
01456     {
01457       errno = EADDRINUSE;
01458       dbus_set_error (error, _dbus_error_from_errno (errno),
01459                       "Failed to bind socket \"%s:%s\": %s",
01460                       host ? host : "*", port, _dbus_strerror (errno));
01461       goto failed;
01462     }
01463 
01464   for (i = 0 ; i < nlisten_fd ; i++)
01465     {
01466       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01467         {
01468           goto failed;
01469         }
01470     }
01471 
01472   *fds_p = listen_fd;
01473 
01474   return nlisten_fd;
01475 
01476  failed:
01477   if (ai)
01478     freeaddrinfo(ai);
01479   for (i = 0 ; i < nlisten_fd ; i++)
01480     _dbus_close(listen_fd[i], NULL);
01481   dbus_free(listen_fd);
01482   return -1;
01483 }
01484 
01485 static dbus_bool_t
01486 write_credentials_byte (int             server_fd,
01487                         DBusError      *error)
01488 {
01489   int bytes_written;
01490   char buf[1] = { '\0' };
01491 #if defined(HAVE_CMSGCRED)
01492   union {
01493           struct cmsghdr hdr;
01494           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01495   } cmsg;
01496   struct iovec iov;
01497   struct msghdr msg;
01498   iov.iov_base = buf;
01499   iov.iov_len = 1;
01500 
01501   _DBUS_ZERO(msg);
01502   msg.msg_iov = &iov;
01503   msg.msg_iovlen = 1;
01504 
01505   msg.msg_control = (caddr_t) &cmsg;
01506   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01507   _DBUS_ZERO(cmsg);
01508   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01509   cmsg.hdr.cmsg_level = SOL_SOCKET;
01510   cmsg.hdr.cmsg_type = SCM_CREDS;
01511 #endif
01512 
01513   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01514 
01515  again:
01516 
01517 #if defined(HAVE_CMSGCRED)
01518   bytes_written = sendmsg (server_fd, &msg, 0
01519 #if HAVE_DECL_MSG_NOSIGNAL
01520                            |MSG_NOSIGNAL
01521 #endif
01522                            );
01523 #else
01524   bytes_written = send (server_fd, buf, 1, 0
01525 #if HAVE_DECL_MSG_NOSIGNAL
01526                         |MSG_NOSIGNAL
01527 #endif
01528                         );
01529 #endif
01530 
01531   if (bytes_written < 0 && errno == EINTR)
01532     goto again;
01533 
01534   if (bytes_written < 0)
01535     {
01536       dbus_set_error (error, _dbus_error_from_errno (errno),
01537                       "Failed to write credentials byte: %s",
01538                      _dbus_strerror (errno));
01539       return FALSE;
01540     }
01541   else if (bytes_written == 0)
01542     {
01543       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01544                       "wrote zero bytes writing credentials byte");
01545       return FALSE;
01546     }
01547   else
01548     {
01549       _dbus_assert (bytes_written == 1);
01550       _dbus_verbose ("wrote credentials byte\n");
01551       return TRUE;
01552     }
01553 }
01554 
01576 dbus_bool_t
01577 _dbus_read_credentials_socket  (int              client_fd,
01578                                 DBusCredentials *credentials,
01579                                 DBusError       *error)
01580 {
01581   struct msghdr msg;
01582   struct iovec iov;
01583   char buf;
01584   dbus_uid_t uid_read;
01585   dbus_pid_t pid_read;
01586   int bytes_read;
01587 
01588 #ifdef HAVE_CMSGCRED
01589   union {
01590     struct cmsghdr hdr;
01591     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01592   } cmsg;
01593 
01594 #elif defined(LOCAL_CREDS)
01595   struct {
01596     struct cmsghdr hdr;
01597     struct sockcred cred;
01598   } cmsg;
01599 #endif
01600 
01601   uid_read = DBUS_UID_UNSET;
01602   pid_read = DBUS_PID_UNSET;
01603 
01604   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01605 
01606   /* The POSIX spec certainly doesn't promise this, but
01607    * we need these assertions to fail as soon as we're wrong about
01608    * it so we can do the porting fixups
01609    */
01610   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01611   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01612   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01613 
01614   _dbus_credentials_clear (credentials);
01615 
01616   /* Systems supporting LOCAL_CREDS are configured to have this feature
01617    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01618    * the connection.  Therefore, the received message must carry the
01619    * credentials information without doing anything special.
01620    */
01621 
01622   iov.iov_base = &buf;
01623   iov.iov_len = 1;
01624 
01625   _DBUS_ZERO(msg);
01626   msg.msg_iov = &iov;
01627   msg.msg_iovlen = 1;
01628 
01629 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01630   _DBUS_ZERO(cmsg);
01631   msg.msg_control = (caddr_t) &cmsg;
01632   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01633 #endif
01634 
01635  again:
01636   bytes_read = recvmsg (client_fd, &msg, 0);
01637 
01638   if (bytes_read < 0)
01639     {
01640       if (errno == EINTR)
01641         goto again;
01642 
01643       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01644        * normally only call read_credentials if the socket was ready
01645        * for reading
01646        */
01647 
01648       dbus_set_error (error, _dbus_error_from_errno (errno),
01649                       "Failed to read credentials byte: %s",
01650                       _dbus_strerror (errno));
01651       return FALSE;
01652     }
01653   else if (bytes_read == 0)
01654     {
01655       /* this should not happen unless we are using recvmsg wrong,
01656        * so is essentially here for paranoia
01657        */
01658       dbus_set_error (error, DBUS_ERROR_FAILED,
01659                       "Failed to read credentials byte (zero-length read)");
01660       return FALSE;
01661     }
01662   else if (buf != '\0')
01663     {
01664       dbus_set_error (error, DBUS_ERROR_FAILED,
01665                       "Credentials byte was not nul");
01666       return FALSE;
01667     }
01668 
01669 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01670   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01671                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01672     {
01673       dbus_set_error (error, DBUS_ERROR_FAILED,
01674                       "Message from recvmsg() was not SCM_CREDS");
01675       return FALSE;
01676     }
01677 #endif
01678 
01679   _dbus_verbose ("read credentials byte\n");
01680 
01681   {
01682 #ifdef SO_PEERCRED
01683 #ifdef __OpenBSD__
01684     struct sockpeercred cr;
01685 #else
01686     struct ucred cr;
01687 #endif
01688     int cr_len = sizeof (cr);
01689 
01690     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01691         cr_len == sizeof (cr))
01692       {
01693         pid_read = cr.pid;
01694         uid_read = cr.uid;
01695       }
01696     else
01697       {
01698         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01699                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01700       }
01701 #elif defined(HAVE_CMSGCRED)
01702     struct cmsgcred *cred;
01703 
01704     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01705     pid_read = cred->cmcred_pid;
01706     uid_read = cred->cmcred_euid;
01707 #elif defined(LOCAL_CREDS)
01708     pid_read = DBUS_PID_UNSET;
01709     uid_read = cmsg.cred.sc_uid;
01710     /* Since we have already got the credentials from this socket, we can
01711      * disable its LOCAL_CREDS flag if it was ever set. */
01712     _dbus_set_local_creds (client_fd, FALSE);
01713 #elif defined(HAVE_GETPEEREID)
01714     uid_t euid;
01715     gid_t egid;
01716     if (getpeereid (client_fd, &euid, &egid) == 0)
01717       {
01718         uid_read = euid;
01719       }
01720     else
01721       {
01722         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01723       }
01724 #elif defined(HAVE_GETPEERUCRED)
01725     ucred_t * ucred = NULL;
01726     if (getpeerucred (client_fd, &ucred) == 0)
01727       {
01728         pid_read = ucred_getpid (ucred);
01729         uid_read = ucred_geteuid (ucred);
01730 #ifdef HAVE_ADT
01731         /* generate audit session data based on socket ucred */
01732         adt_session_data_t *adth = NULL;
01733         adt_export_data_t *data = NULL;
01734         size_t size = 0;
01735         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01736           {
01737             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01738           }
01739         else
01740           {
01741             if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01742               {
01743                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01744               }
01745             else
01746               {
01747                 size = adt_export_session_data (adth, &data);
01748                 if (size <= 0)
01749                   {
01750                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01751                   }
01752                 else
01753                   {
01754                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01755                     free (data);
01756                   }
01757               }
01758             (void) adt_end_session (adth);
01759           }
01760 #endif /* HAVE_ADT */
01761       }
01762     else
01763       {
01764         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01765       }
01766     if (ucred != NULL)
01767       ucred_free (ucred);
01768 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01769     _dbus_verbose ("Socket credentials not supported on this OS\n");
01770 #endif
01771   }
01772 
01773   _dbus_verbose ("Credentials:"
01774                  "  pid "DBUS_PID_FORMAT
01775                  "  uid "DBUS_UID_FORMAT
01776                  "\n",
01777                  pid_read,
01778                  uid_read);
01779 
01780   if (pid_read != DBUS_PID_UNSET)
01781     {
01782       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01783         {
01784           _DBUS_SET_OOM (error);
01785           return FALSE;
01786         }
01787     }
01788 
01789   if (uid_read != DBUS_UID_UNSET)
01790     {
01791       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01792         {
01793           _DBUS_SET_OOM (error);
01794           return FALSE;
01795         }
01796     }
01797 
01798   return TRUE;
01799 }
01800 
01818 dbus_bool_t
01819 _dbus_send_credentials_socket  (int              server_fd,
01820                                 DBusError       *error)
01821 {
01822   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01823 
01824   if (write_credentials_byte (server_fd, error))
01825     return TRUE;
01826   else
01827     return FALSE;
01828 }
01829 
01839 int
01840 _dbus_accept  (int listen_fd)
01841 {
01842   int client_fd;
01843   struct sockaddr addr;
01844   socklen_t addrlen;
01845 #ifdef HAVE_ACCEPT4
01846   dbus_bool_t cloexec_done;
01847 #endif
01848 
01849   addrlen = sizeof (addr);
01850 
01851  retry:
01852 
01853 #ifdef HAVE_ACCEPT4
01854   /* We assume that if accept4 is available SOCK_CLOEXEC is too */
01855   client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
01856   cloexec_done = client_fd >= 0;
01857 
01858   if (client_fd < 0 && errno == ENOSYS)
01859 #endif
01860     {
01861       client_fd = accept (listen_fd, &addr, &addrlen);
01862     }
01863 
01864   if (client_fd < 0)
01865     {
01866       if (errno == EINTR)
01867         goto retry;
01868     }
01869 
01870   _dbus_verbose ("client fd %d accepted\n", client_fd);
01871 
01872 #ifdef HAVE_ACCEPT4
01873   if (!cloexec_done)
01874 #endif
01875     {
01876       _dbus_fd_set_close_on_exec(client_fd);
01877     }
01878 
01879   return client_fd;
01880 }
01881 
01890 dbus_bool_t
01891 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01892 {
01893   const char *directory;
01894   struct stat sb;
01895 
01896   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01897 
01898   directory = _dbus_string_get_const_data (dir);
01899 
01900   if (stat (directory, &sb) < 0)
01901     {
01902       dbus_set_error (error, _dbus_error_from_errno (errno),
01903                       "%s", _dbus_strerror (errno));
01904 
01905       return FALSE;
01906     }
01907 
01908   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01909       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01910     {
01911       dbus_set_error (error, DBUS_ERROR_FAILED,
01912                      "%s directory is not private to the user", directory);
01913       return FALSE;
01914     }
01915 
01916   return TRUE;
01917 }
01918 
01919 static dbus_bool_t
01920 fill_user_info_from_passwd (struct passwd *p,
01921                             DBusUserInfo  *info,
01922                             DBusError     *error)
01923 {
01924   _dbus_assert (p->pw_name != NULL);
01925   _dbus_assert (p->pw_dir != NULL);
01926 
01927   info->uid = p->pw_uid;
01928   info->primary_gid = p->pw_gid;
01929   info->username = _dbus_strdup (p->pw_name);
01930   info->homedir = _dbus_strdup (p->pw_dir);
01931 
01932   if (info->username == NULL ||
01933       info->homedir == NULL)
01934     {
01935       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01936       return FALSE;
01937     }
01938 
01939   return TRUE;
01940 }
01941 
01942 static dbus_bool_t
01943 fill_user_info (DBusUserInfo       *info,
01944                 dbus_uid_t          uid,
01945                 const DBusString   *username,
01946                 DBusError          *error)
01947 {
01948   const char *username_c;
01949 
01950   /* exactly one of username/uid provided */
01951   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01952   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01953 
01954   info->uid = DBUS_UID_UNSET;
01955   info->primary_gid = DBUS_GID_UNSET;
01956   info->group_ids = NULL;
01957   info->n_group_ids = 0;
01958   info->username = NULL;
01959   info->homedir = NULL;
01960 
01961   if (username != NULL)
01962     username_c = _dbus_string_get_const_data (username);
01963   else
01964     username_c = NULL;
01965 
01966   /* For now assuming that the getpwnam() and getpwuid() flavors
01967    * are always symmetrical, if not we have to add more configure
01968    * checks
01969    */
01970 
01971 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01972   {
01973     struct passwd *p;
01974     int result;
01975     size_t buflen;
01976     char *buf;
01977     struct passwd p_str;
01978 
01979     /* retrieve maximum needed size for buf */
01980     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01981 
01982     /* sysconf actually returns a long, but everything else expects size_t,
01983      * so just recast here.
01984      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
01985      */
01986     if ((long) buflen <= 0)
01987       buflen = 1024;
01988 
01989     result = -1;
01990     while (1)
01991       {
01992         buf = dbus_malloc (buflen);
01993         if (buf == NULL)
01994           {
01995             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01996             return FALSE;
01997           }
01998 
01999         p = NULL;
02000 #ifdef HAVE_POSIX_GETPWNAM_R
02001         if (uid != DBUS_UID_UNSET)
02002           result = getpwuid_r (uid, &p_str, buf, buflen,
02003                                &p);
02004         else
02005           result = getpwnam_r (username_c, &p_str, buf, buflen,
02006                                &p);
02007 #else
02008         if (uid != DBUS_UID_UNSET)
02009           p = getpwuid_r (uid, &p_str, buf, buflen);
02010         else
02011           p = getpwnam_r (username_c, &p_str, buf, buflen);
02012         result = 0;
02013 #endif /* !HAVE_POSIX_GETPWNAM_R */
02014         //Try a bigger buffer if ERANGE was returned
02015         if (result == ERANGE && buflen < 512 * 1024)
02016           {
02017             dbus_free (buf);
02018             buflen *= 2;
02019           }
02020         else
02021           {
02022             break;
02023           }
02024       }
02025     if (result == 0 && p == &p_str)
02026       {
02027         if (!fill_user_info_from_passwd (p, info, error))
02028           {
02029             dbus_free (buf);
02030             return FALSE;
02031           }
02032         dbus_free (buf);
02033       }
02034     else
02035       {
02036         dbus_set_error (error, _dbus_error_from_errno (errno),
02037                         "User \"%s\" unknown or no memory to allocate password entry\n",
02038                         username_c ? username_c : "???");
02039         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02040         dbus_free (buf);
02041         return FALSE;
02042       }
02043   }
02044 #else /* ! HAVE_GETPWNAM_R */
02045   {
02046     /* I guess we're screwed on thread safety here */
02047     struct passwd *p;
02048 
02049     if (uid != DBUS_UID_UNSET)
02050       p = getpwuid (uid);
02051     else
02052       p = getpwnam (username_c);
02053 
02054     if (p != NULL)
02055       {
02056         if (!fill_user_info_from_passwd (p, info, error))
02057           {
02058             return FALSE;
02059           }
02060       }
02061     else
02062       {
02063         dbus_set_error (error, _dbus_error_from_errno (errno),
02064                         "User \"%s\" unknown or no memory to allocate password entry\n",
02065                         username_c ? username_c : "???");
02066         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02067         return FALSE;
02068       }
02069   }
02070 #endif  /* ! HAVE_GETPWNAM_R */
02071 
02072   /* Fill this in so we can use it to get groups */
02073   username_c = info->username;
02074 
02075 #ifdef HAVE_GETGROUPLIST
02076   {
02077     gid_t *buf;
02078     int buf_count;
02079     int i;
02080     int initial_buf_count;
02081 
02082     initial_buf_count = 17;
02083     buf_count = initial_buf_count;
02084     buf = dbus_new (gid_t, buf_count);
02085     if (buf == NULL)
02086       {
02087         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02088         goto failed;
02089       }
02090 
02091     if (getgrouplist (username_c,
02092                       info->primary_gid,
02093                       buf, &buf_count) < 0)
02094       {
02095         gid_t *new;
02096         /* Presumed cause of negative return code: buf has insufficient
02097            entries to hold the entire group list. The Linux behavior in this
02098            case is to pass back the actual number of groups in buf_count, but
02099            on Mac OS X 10.5, buf_count is unhelpfully left alone.
02100            So as a hack, try to help out a bit by guessing a larger
02101            number of groups, within reason.. might still fail, of course,
02102            but we can at least print a more informative message.  I looked up
02103            the "right way" to do this by downloading Apple's own source code
02104            for the "id" command, and it turns out that they use an
02105            undocumented library function getgrouplist_2 (!) which is not
02106            declared in any header in /usr/include (!!). That did not seem
02107            like the way to go here.
02108         */
02109         if (buf_count == initial_buf_count)
02110           {
02111             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
02112           }
02113         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02114         if (new == NULL)
02115           {
02116             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02117             dbus_free (buf);
02118             goto failed;
02119           }
02120 
02121         buf = new;
02122 
02123         errno = 0;
02124         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02125           {
02126             if (errno == 0)
02127               {
02128                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02129                             username_c, buf_count, buf_count);
02130               }
02131             else
02132               {
02133                 dbus_set_error (error,
02134                                 _dbus_error_from_errno (errno),
02135                                 "Failed to get groups for username \"%s\" primary GID "
02136                                 DBUS_GID_FORMAT ": %s\n",
02137                                 username_c, info->primary_gid,
02138                                 _dbus_strerror (errno));
02139                 dbus_free (buf);
02140                 goto failed;
02141               }
02142           }
02143       }
02144 
02145     info->group_ids = dbus_new (dbus_gid_t, buf_count);
02146     if (info->group_ids == NULL)
02147       {
02148         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02149         dbus_free (buf);
02150         goto failed;
02151       }
02152 
02153     for (i = 0; i < buf_count; ++i)
02154       info->group_ids[i] = buf[i];
02155 
02156     info->n_group_ids = buf_count;
02157 
02158     dbus_free (buf);
02159   }
02160 #else  /* HAVE_GETGROUPLIST */
02161   {
02162     /* We just get the one group ID */
02163     info->group_ids = dbus_new (dbus_gid_t, 1);
02164     if (info->group_ids == NULL)
02165       {
02166         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02167         goto failed;
02168       }
02169 
02170     info->n_group_ids = 1;
02171 
02172     (info->group_ids)[0] = info->primary_gid;
02173   }
02174 #endif /* HAVE_GETGROUPLIST */
02175 
02176   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02177 
02178   return TRUE;
02179 
02180  failed:
02181   _DBUS_ASSERT_ERROR_IS_SET (error);
02182   return FALSE;
02183 }
02184 
02193 dbus_bool_t
02194 _dbus_user_info_fill (DBusUserInfo     *info,
02195                       const DBusString *username,
02196                       DBusError        *error)
02197 {
02198   return fill_user_info (info, DBUS_UID_UNSET,
02199                          username, error);
02200 }
02201 
02210 dbus_bool_t
02211 _dbus_user_info_fill_uid (DBusUserInfo *info,
02212                           dbus_uid_t    uid,
02213                           DBusError    *error)
02214 {
02215   return fill_user_info (info, uid,
02216                          NULL, error);
02217 }
02218 
02226 dbus_bool_t
02227 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02228 {
02229   /* The POSIX spec certainly doesn't promise this, but
02230    * we need these assertions to fail as soon as we're wrong about
02231    * it so we can do the porting fixups
02232    */
02233   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
02234   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
02235   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
02236 
02237   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
02238     return FALSE;
02239   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02240     return FALSE;
02241 
02242   return TRUE;
02243 }
02244 
02256 dbus_bool_t
02257 _dbus_append_user_from_current_process (DBusString *str)
02258 {
02259   return _dbus_string_append_uint (str,
02260                                    _dbus_geteuid ());
02261 }
02262 
02267 dbus_pid_t
02268 _dbus_getpid (void)
02269 {
02270   return getpid ();
02271 }
02272 
02276 dbus_uid_t
02277 _dbus_getuid (void)
02278 {
02279   return getuid ();
02280 }
02281 
02285 dbus_uid_t
02286 _dbus_geteuid (void)
02287 {
02288   return geteuid ();
02289 }
02290 
02297 unsigned long
02298 _dbus_pid_for_log (void)
02299 {
02300   return getpid ();
02301 }
02302 
02310 dbus_bool_t
02311 _dbus_parse_uid (const DBusString      *uid_str,
02312                  dbus_uid_t            *uid)
02313 {
02314   int end;
02315   long val;
02316 
02317   if (_dbus_string_get_length (uid_str) == 0)
02318     {
02319       _dbus_verbose ("UID string was zero length\n");
02320       return FALSE;
02321     }
02322 
02323   val = -1;
02324   end = 0;
02325   if (!_dbus_string_parse_int (uid_str, 0, &val,
02326                                &end))
02327     {
02328       _dbus_verbose ("could not parse string as a UID\n");
02329       return FALSE;
02330     }
02331 
02332   if (end != _dbus_string_get_length (uid_str))
02333     {
02334       _dbus_verbose ("string contained trailing stuff after UID\n");
02335       return FALSE;
02336     }
02337 
02338   *uid = val;
02339 
02340   return TRUE;
02341 }
02342 
02343 #if !DBUS_USE_SYNC
02344 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
02345 #endif
02346 
02353 dbus_int32_t
02354 _dbus_atomic_inc (DBusAtomic *atomic)
02355 {
02356 #if DBUS_USE_SYNC
02357   return __sync_add_and_fetch(&atomic->value, 1)-1;
02358 #else
02359   dbus_int32_t res;
02360   _DBUS_LOCK (atomic);
02361   res = atomic->value;
02362   atomic->value += 1;
02363   _DBUS_UNLOCK (atomic);
02364   return res;
02365 #endif
02366 }
02367 
02374 dbus_int32_t
02375 _dbus_atomic_dec (DBusAtomic *atomic)
02376 {
02377 #if DBUS_USE_SYNC
02378   return __sync_sub_and_fetch(&atomic->value, 1)+1;
02379 #else
02380   dbus_int32_t res;
02381 
02382   _DBUS_LOCK (atomic);
02383   res = atomic->value;
02384   atomic->value -= 1;
02385   _DBUS_UNLOCK (atomic);
02386   return res;
02387 #endif
02388 }
02389 
02397 dbus_int32_t
02398 _dbus_atomic_get (DBusAtomic *atomic)
02399 {
02400 #if DBUS_USE_SYNC
02401   __sync_synchronize ();
02402   return atomic->value;
02403 #else
02404   dbus_int32_t res;
02405 
02406   _DBUS_LOCK (atomic);
02407   res = atomic->value;
02408   _DBUS_UNLOCK (atomic);
02409   return res;
02410 #endif
02411 }
02412 
02413 #ifdef DBUS_BUILD_TESTS
02414 
02417 dbus_gid_t
02418 _dbus_getgid (void)
02419 {
02420   return getgid ();
02421 }
02422 #endif
02423 
02432 int
02433 _dbus_poll (DBusPollFD *fds,
02434             int         n_fds,
02435             int         timeout_milliseconds)
02436 {
02437 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02438   /* This big thing is a constant expression and should get optimized
02439    * out of existence. So it's more robust than a configure check at
02440    * no cost.
02441    */
02442   if (_DBUS_POLLIN == POLLIN &&
02443       _DBUS_POLLPRI == POLLPRI &&
02444       _DBUS_POLLOUT == POLLOUT &&
02445       _DBUS_POLLERR == POLLERR &&
02446       _DBUS_POLLHUP == POLLHUP &&
02447       _DBUS_POLLNVAL == POLLNVAL &&
02448       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
02449       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
02450       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
02451       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
02452       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
02453       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
02454       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
02455     {
02456       return poll ((struct pollfd*) fds,
02457                    n_fds,
02458                    timeout_milliseconds);
02459     }
02460   else
02461     {
02462       /* We have to convert the DBusPollFD to an array of
02463        * struct pollfd, poll, and convert back.
02464        */
02465       _dbus_warn ("didn't implement poll() properly for this system yet\n");
02466       return -1;
02467     }
02468 #else /* ! HAVE_POLL */
02469 
02470   fd_set read_set, write_set, err_set;
02471   int max_fd = 0;
02472   int i;
02473   struct timeval tv;
02474   int ready;
02475 
02476   FD_ZERO (&read_set);
02477   FD_ZERO (&write_set);
02478   FD_ZERO (&err_set);
02479 
02480   for (i = 0; i < n_fds; i++)
02481     {
02482       DBusPollFD *fdp = &fds[i];
02483 
02484       if (fdp->events & _DBUS_POLLIN)
02485         FD_SET (fdp->fd, &read_set);
02486 
02487       if (fdp->events & _DBUS_POLLOUT)
02488         FD_SET (fdp->fd, &write_set);
02489 
02490       FD_SET (fdp->fd, &err_set);
02491 
02492       max_fd = MAX (max_fd, fdp->fd);
02493     }
02494 
02495   tv.tv_sec = timeout_milliseconds / 1000;
02496   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02497 
02498   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02499                   timeout_milliseconds < 0 ? NULL : &tv);
02500 
02501   if (ready > 0)
02502     {
02503       for (i = 0; i < n_fds; i++)
02504         {
02505           DBusPollFD *fdp = &fds[i];
02506 
02507           fdp->revents = 0;
02508 
02509           if (FD_ISSET (fdp->fd, &read_set))
02510             fdp->revents |= _DBUS_POLLIN;
02511 
02512           if (FD_ISSET (fdp->fd, &write_set))
02513             fdp->revents |= _DBUS_POLLOUT;
02514 
02515           if (FD_ISSET (fdp->fd, &err_set))
02516             fdp->revents |= _DBUS_POLLERR;
02517         }
02518     }
02519 
02520   return ready;
02521 #endif
02522 }
02523 
02531 void
02532 _dbus_get_current_time (long *tv_sec,
02533                         long *tv_usec)
02534 {
02535   struct timeval t;
02536 
02537 #ifdef HAVE_MONOTONIC_CLOCK
02538   struct timespec ts;
02539   clock_gettime (CLOCK_MONOTONIC, &ts);
02540 
02541   if (tv_sec)
02542     *tv_sec = ts.tv_sec;
02543   if (tv_usec)
02544     *tv_usec = ts.tv_nsec / 1000;
02545 #else
02546   gettimeofday (&t, NULL);
02547 
02548   if (tv_sec)
02549     *tv_sec = t.tv_sec;
02550   if (tv_usec)
02551     *tv_usec = t.tv_usec;
02552 #endif
02553 }
02554 
02563 dbus_bool_t
02564 _dbus_create_directory (const DBusString *filename,
02565                         DBusError        *error)
02566 {
02567   const char *filename_c;
02568 
02569   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02570 
02571   filename_c = _dbus_string_get_const_data (filename);
02572 
02573   if (mkdir (filename_c, 0700) < 0)
02574     {
02575       if (errno == EEXIST)
02576         return TRUE;
02577 
02578       dbus_set_error (error, DBUS_ERROR_FAILED,
02579                       "Failed to create directory %s: %s\n",
02580                       filename_c, _dbus_strerror (errno));
02581       return FALSE;
02582     }
02583   else
02584     return TRUE;
02585 }
02586 
02597 dbus_bool_t
02598 _dbus_concat_dir_and_file (DBusString       *dir,
02599                            const DBusString *next_component)
02600 {
02601   dbus_bool_t dir_ends_in_slash;
02602   dbus_bool_t file_starts_with_slash;
02603 
02604   if (_dbus_string_get_length (dir) == 0 ||
02605       _dbus_string_get_length (next_component) == 0)
02606     return TRUE;
02607 
02608   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02609                                                     _dbus_string_get_length (dir) - 1);
02610 
02611   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02612 
02613   if (dir_ends_in_slash && file_starts_with_slash)
02614     {
02615       _dbus_string_shorten (dir, 1);
02616     }
02617   else if (!(dir_ends_in_slash || file_starts_with_slash))
02618     {
02619       if (!_dbus_string_append_byte (dir, '/'))
02620         return FALSE;
02621     }
02622 
02623   return _dbus_string_copy (next_component, 0, dir,
02624                             _dbus_string_get_length (dir));
02625 }
02626 
02628 #define NANOSECONDS_PER_SECOND       1000000000
02629 
02630 #define MICROSECONDS_PER_SECOND      1000000
02631 
02632 #define MILLISECONDS_PER_SECOND      1000
02633 
02634 #define NANOSECONDS_PER_MILLISECOND  1000000
02635 
02636 #define MICROSECONDS_PER_MILLISECOND 1000
02637 
02642 void
02643 _dbus_sleep_milliseconds (int milliseconds)
02644 {
02645 #ifdef HAVE_NANOSLEEP
02646   struct timespec req;
02647   struct timespec rem;
02648 
02649   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02650   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02651   rem.tv_sec = 0;
02652   rem.tv_nsec = 0;
02653 
02654   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02655     req = rem;
02656 #elif defined (HAVE_USLEEP)
02657   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02658 #else /* ! HAVE_USLEEP */
02659   sleep (MAX (milliseconds / 1000, 1));
02660 #endif
02661 }
02662 
02663 static dbus_bool_t
02664 _dbus_generate_pseudorandom_bytes (DBusString *str,
02665                                    int         n_bytes)
02666 {
02667   int old_len;
02668   char *p;
02669 
02670   old_len = _dbus_string_get_length (str);
02671 
02672   if (!_dbus_string_lengthen (str, n_bytes))
02673     return FALSE;
02674 
02675   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02676 
02677   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02678 
02679   return TRUE;
02680 }
02681 
02690 dbus_bool_t
02691 _dbus_generate_random_bytes (DBusString *str,
02692                              int         n_bytes)
02693 {
02694   int old_len;
02695   int fd;
02696 
02697   /* FALSE return means "no memory", if it could
02698    * mean something else then we'd need to return
02699    * a DBusError. So we always fall back to pseudorandom
02700    * if the I/O fails.
02701    */
02702 
02703   old_len = _dbus_string_get_length (str);
02704   fd = -1;
02705 
02706   /* note, urandom on linux will fall back to pseudorandom */
02707   fd = open ("/dev/urandom", O_RDONLY);
02708   if (fd < 0)
02709     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02710 
02711   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02712 
02713   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02714     {
02715       _dbus_close (fd, NULL);
02716       _dbus_string_set_length (str, old_len);
02717       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02718     }
02719 
02720   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02721                  n_bytes);
02722 
02723   _dbus_close (fd, NULL);
02724 
02725   return TRUE;
02726 }
02727 
02733 void
02734 _dbus_exit (int code)
02735 {
02736   _exit (code);
02737 }
02738 
02747 const char*
02748 _dbus_strerror (int error_number)
02749 {
02750   const char *msg;
02751 
02752   msg = strerror (error_number);
02753   if (msg == NULL)
02754     msg = "unknown";
02755 
02756   return msg;
02757 }
02758 
02762 void
02763 _dbus_disable_sigpipe (void)
02764 {
02765   signal (SIGPIPE, SIG_IGN);
02766 }
02767 
02775 void
02776 _dbus_fd_set_close_on_exec (intptr_t fd)
02777 {
02778   int val;
02779 
02780   val = fcntl (fd, F_GETFD, 0);
02781 
02782   if (val < 0)
02783     return;
02784 
02785   val |= FD_CLOEXEC;
02786 
02787   fcntl (fd, F_SETFD, val);
02788 }
02789 
02797 dbus_bool_t
02798 _dbus_close (int        fd,
02799              DBusError *error)
02800 {
02801   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02802 
02803  again:
02804   if (close (fd) < 0)
02805     {
02806       if (errno == EINTR)
02807         goto again;
02808 
02809       dbus_set_error (error, _dbus_error_from_errno (errno),
02810                       "Could not close fd %d", fd);
02811       return FALSE;
02812     }
02813 
02814   return TRUE;
02815 }
02816 
02824 int
02825 _dbus_dup(int        fd,
02826           DBusError *error)
02827 {
02828   int new_fd;
02829 
02830 #ifdef F_DUPFD_CLOEXEC
02831   dbus_bool_t cloexec_done;
02832 
02833   new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
02834   cloexec_done = new_fd >= 0;
02835 
02836   if (new_fd < 0 && errno == EINVAL)
02837 #endif
02838     {
02839       new_fd = fcntl(fd, F_DUPFD, 3);
02840     }
02841 
02842   if (new_fd < 0) {
02843 
02844     dbus_set_error (error, _dbus_error_from_errno (errno),
02845                     "Could not duplicate fd %d", fd);
02846     return -1;
02847   }
02848 
02849 #ifdef F_DUPFD_CLOEXEC
02850   if (!cloexec_done)
02851 #endif
02852     {
02853       _dbus_fd_set_close_on_exec(new_fd);
02854     }
02855 
02856   return new_fd;
02857 }
02858 
02866 dbus_bool_t
02867 _dbus_set_fd_nonblocking (int             fd,
02868                           DBusError      *error)
02869 {
02870   int val;
02871 
02872   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02873 
02874   val = fcntl (fd, F_GETFL, 0);
02875   if (val < 0)
02876     {
02877       dbus_set_error (error, _dbus_error_from_errno (errno),
02878                       "Failed to get flags from file descriptor %d: %s",
02879                       fd, _dbus_strerror (errno));
02880       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02881                      _dbus_strerror (errno));
02882       return FALSE;
02883     }
02884 
02885   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02886     {
02887       dbus_set_error (error, _dbus_error_from_errno (errno),
02888                       "Failed to set nonblocking flag of file descriptor %d: %s",
02889                       fd, _dbus_strerror (errno));
02890       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02891                      fd, _dbus_strerror (errno));
02892 
02893       return FALSE;
02894     }
02895 
02896   return TRUE;
02897 }
02898 
02904 void
02905 _dbus_print_backtrace (void)
02906 {
02907 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02908   void *bt[500];
02909   int bt_size;
02910   int i;
02911   char **syms;
02912 
02913   bt_size = backtrace (bt, 500);
02914 
02915   syms = backtrace_symbols (bt, bt_size);
02916 
02917   i = 0;
02918   while (i < bt_size)
02919     {
02920       /* don't use dbus_warn since it can _dbus_abort() */
02921       fprintf (stderr, "  %s\n", syms[i]);
02922       ++i;
02923     }
02924   fflush (stderr);
02925 
02926   free (syms);
02927 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02928   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02929 #else
02930   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02931 #endif
02932 }
02933 
02951 dbus_bool_t
02952 _dbus_full_duplex_pipe (int        *fd1,
02953                         int        *fd2,
02954                         dbus_bool_t blocking,
02955                         DBusError  *error)
02956 {
02957 #ifdef HAVE_SOCKETPAIR
02958   int fds[2];
02959   int retval;
02960 
02961 #ifdef SOCK_CLOEXEC
02962   dbus_bool_t cloexec_done;
02963 
02964   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
02965   cloexec_done = retval >= 0;
02966 
02967   if (retval < 0 && errno == EINVAL)
02968 #endif
02969     {
02970       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
02971     }
02972 
02973   if (retval < 0)
02974     {
02975       dbus_set_error (error, _dbus_error_from_errno (errno),
02976                       "Could not create full-duplex pipe");
02977       return FALSE;
02978     }
02979 
02980   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02981 
02982 #ifdef SOCK_CLOEXEC
02983   if (!cloexec_done)
02984 #endif
02985     {
02986       _dbus_fd_set_close_on_exec (fds[0]);
02987       _dbus_fd_set_close_on_exec (fds[1]);
02988     }
02989 
02990   if (!blocking &&
02991       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02992        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02993     {
02994       dbus_set_error (error, _dbus_error_from_errno (errno),
02995                       "Could not set full-duplex pipe nonblocking");
02996 
02997       _dbus_close (fds[0], NULL);
02998       _dbus_close (fds[1], NULL);
02999 
03000       return FALSE;
03001     }
03002 
03003   *fd1 = fds[0];
03004   *fd2 = fds[1];
03005 
03006   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03007                  *fd1, *fd2);
03008 
03009   return TRUE;
03010 #else
03011   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03012   dbus_set_error (error, DBUS_ERROR_FAILED,
03013                   "_dbus_full_duplex_pipe() not implemented on this OS");
03014   return FALSE;
03015 #endif
03016 }
03017 
03026 int
03027 _dbus_printf_string_upper_bound (const char *format,
03028                                  va_list     args)
03029 {
03030   char static_buf[1024];
03031   int bufsize = sizeof (static_buf);
03032   int len;
03033 
03034   len = vsnprintf (static_buf, bufsize, format, args);
03035 
03036   /* If vsnprintf() returned non-negative, then either the string fits in
03037    * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
03038    * returns the number of characters that were needed, or this OS returns the
03039    * truncated length.
03040    *
03041    * We ignore the possibility that snprintf might just ignore the length and
03042    * overrun the buffer (64-bit Solaris 7), because that's pathological.
03043    * If your libc is really that bad, come back when you have a better one. */
03044   if (len == bufsize)
03045     {
03046       /* This could be the truncated length (Tru64 and IRIX have this bug),
03047        * or the real length could be coincidentally the same. Which is it?
03048        * If vsnprintf returns the truncated length, we'll go to the slow
03049        * path. */
03050       if (vsnprintf (static_buf, 1, format, args) == 1)
03051         len = -1;
03052     }
03053 
03054   /* If vsnprintf() returned negative, we have to do more work.
03055    * HP-UX returns negative. */
03056   while (len < 0)
03057     {
03058       char *buf;
03059 
03060       bufsize *= 2;
03061 
03062       buf = dbus_malloc (bufsize);
03063 
03064       if (buf == NULL)
03065         return -1;
03066 
03067       len = vsnprintf (buf, bufsize, format, args);
03068       dbus_free (buf);
03069 
03070       /* If the reported length is exactly the buffer size, round up to the
03071        * next size, in case vsnprintf has been returning the truncated
03072        * length */
03073       if (len == bufsize)
03074         len = -1;
03075     }
03076 
03077   return len;
03078 }
03079 
03086 const char*
03087 _dbus_get_tmpdir(void)
03088 {
03089   static const char* tmpdir = NULL;
03090 
03091   if (tmpdir == NULL)
03092     {
03093       /* TMPDIR is what glibc uses, then
03094        * glibc falls back to the P_tmpdir macro which
03095        * just expands to "/tmp"
03096        */
03097       if (tmpdir == NULL)
03098         tmpdir = getenv("TMPDIR");
03099 
03100       /* These two env variables are probably
03101        * broken, but maybe some OS uses them?
03102        */
03103       if (tmpdir == NULL)
03104         tmpdir = getenv("TMP");
03105       if (tmpdir == NULL)
03106         tmpdir = getenv("TEMP");
03107 
03108       /* And this is the sane fallback. */
03109       if (tmpdir == NULL)
03110         tmpdir = "/tmp";
03111     }
03112 
03113   _dbus_assert(tmpdir != NULL);
03114 
03115   return tmpdir;
03116 }
03117 
03137 static dbus_bool_t
03138 _read_subprocess_line_argv (const char *progpath,
03139                             dbus_bool_t path_fallback,
03140                             char       * const *argv,
03141                             DBusString *result,
03142                             DBusError  *error)
03143 {
03144   int result_pipe[2] = { -1, -1 };
03145   int errors_pipe[2] = { -1, -1 };
03146   pid_t pid;
03147   int ret;
03148   int status;
03149   int orig_len;
03150   int i;
03151 
03152   dbus_bool_t retval;
03153   sigset_t new_set, old_set;
03154 
03155   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03156   retval = FALSE;
03157 
03158   /* We need to block any existing handlers for SIGCHLD temporarily; they
03159    * will cause waitpid() below to fail.
03160    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
03161    */
03162   sigemptyset (&new_set);
03163   sigaddset (&new_set, SIGCHLD);
03164   sigprocmask (SIG_BLOCK, &new_set, &old_set);
03165 
03166   orig_len = _dbus_string_get_length (result);
03167 
03168 #define READ_END        0
03169 #define WRITE_END       1
03170   if (pipe (result_pipe) < 0)
03171     {
03172       dbus_set_error (error, _dbus_error_from_errno (errno),
03173                       "Failed to create a pipe to call %s: %s",
03174                       progpath, _dbus_strerror (errno));
03175       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03176                      progpath, _dbus_strerror (errno));
03177       goto out;
03178     }
03179   if (pipe (errors_pipe) < 0)
03180     {
03181       dbus_set_error (error, _dbus_error_from_errno (errno),
03182                       "Failed to create a pipe to call %s: %s",
03183                       progpath, _dbus_strerror (errno));
03184       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03185                      progpath, _dbus_strerror (errno));
03186       goto out;
03187     }
03188 
03189   pid = fork ();
03190   if (pid < 0)
03191     {
03192       dbus_set_error (error, _dbus_error_from_errno (errno),
03193                       "Failed to fork() to call %s: %s",
03194                       progpath, _dbus_strerror (errno));
03195       _dbus_verbose ("Failed to fork() to call %s: %s\n",
03196                      progpath, _dbus_strerror (errno));
03197       goto out;
03198     }
03199 
03200   if (pid == 0)
03201     {
03202       /* child process */
03203       int maxfds;
03204       int fd;
03205 
03206       fd = open ("/dev/null", O_RDWR);
03207       if (fd == -1)
03208         /* huh?! can't open /dev/null? */
03209         _exit (1);
03210 
03211       _dbus_verbose ("/dev/null fd %d opened\n", fd);
03212 
03213       /* set-up stdXXX */
03214       close (result_pipe[READ_END]);
03215       close (errors_pipe[READ_END]);
03216       close (0);                /* close stdin */
03217       close (1);                /* close stdout */
03218       close (2);                /* close stderr */
03219 
03220       if (dup2 (fd, 0) == -1)
03221         _exit (1);
03222       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03223         _exit (1);
03224       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03225         _exit (1);
03226 
03227       maxfds = sysconf (_SC_OPEN_MAX);
03228       /* Pick something reasonable if for some reason sysconf
03229        * says unlimited.
03230        */
03231       if (maxfds < 0)
03232         maxfds = 1024;
03233       /* close all inherited fds */
03234       for (i = 3; i < maxfds; i++)
03235         close (i);
03236 
03237       sigprocmask (SIG_SETMASK, &old_set, NULL);
03238 
03239       /* If it looks fully-qualified, try execv first */
03240       if (progpath[0] == '/')
03241         {
03242           execv (progpath, argv);
03243           /* Ok, that failed.  Now if path_fallback is given, let's
03244            * try unqualified.  This is mostly a hack to work
03245            * around systems which ship dbus-launch in /usr/bin
03246            * but everything else in /bin (because dbus-launch
03247            * depends on X11).
03248            */
03249           if (path_fallback)
03250             /* We must have a slash, because we checked above */
03251             execvp (strrchr (progpath, '/')+1, argv);
03252         }
03253       else
03254         execvp (progpath, argv);
03255 
03256       /* still nothing, we failed */
03257       _exit (1);
03258     }
03259 
03260   /* parent process */
03261   close (result_pipe[WRITE_END]);
03262   close (errors_pipe[WRITE_END]);
03263   result_pipe[WRITE_END] = -1;
03264   errors_pipe[WRITE_END] = -1;
03265 
03266   ret = 0;
03267   do
03268     {
03269       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03270     }
03271   while (ret > 0);
03272 
03273   /* reap the child process to avoid it lingering as zombie */
03274   do
03275     {
03276       ret = waitpid (pid, &status, 0);
03277     }
03278   while (ret == -1 && errno == EINTR);
03279 
03280   /* We succeeded if the process exited with status 0 and
03281      anything was read */
03282   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03283     {
03284       /* The process ended with error */
03285       DBusString error_message;
03286       if (!_dbus_string_init (&error_message))
03287         {
03288           _DBUS_SET_OOM (error);
03289           goto out;
03290         }
03291 
03292       ret = 0;
03293       do
03294         {
03295           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03296         }
03297       while (ret > 0);
03298 
03299       _dbus_string_set_length (result, orig_len);
03300       if (_dbus_string_get_length (&error_message) > 0)
03301         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03302                         "%s terminated abnormally with the following error: %s",
03303                         progpath, _dbus_string_get_data (&error_message));
03304       else
03305         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03306                         "%s terminated abnormally without any error message",
03307                         progpath);
03308       goto out;
03309     }
03310 
03311   retval = TRUE;
03312 
03313  out:
03314   sigprocmask (SIG_SETMASK, &old_set, NULL);
03315 
03316   if (retval)
03317     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03318   else
03319     _DBUS_ASSERT_ERROR_IS_SET (error);
03320 
03321   if (result_pipe[0] != -1)
03322     close (result_pipe[0]);
03323   if (result_pipe[1] != -1)
03324     close (result_pipe[1]);
03325   if (errors_pipe[0] != -1)
03326     close (errors_pipe[0]);
03327   if (errors_pipe[1] != -1)
03328     close (errors_pipe[1]);
03329 
03330   return retval;
03331 }
03332 
03344 dbus_bool_t
03345 _dbus_get_autolaunch_address (const char *scope,
03346                               DBusString *address,
03347                               DBusError  *error)
03348 {
03349 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
03350   /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
03351    * but that's done elsewhere, and if it worked, this function wouldn't
03352    * be called.) */
03353   const char *display;
03354   static char *argv[6];
03355   int i;
03356   DBusString uuid;
03357   dbus_bool_t retval;
03358 
03359   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03360   retval = FALSE;
03361 
03362   /* fd.o #19997: if $DISPLAY isn't set to something useful, then
03363    * dbus-launch-x11 is just going to fail. Rather than trying to
03364    * run it, we might as well bail out early with a nice error. */
03365   display = _dbus_getenv ("DISPLAY");
03366 
03367   if (display == NULL || display[0] == '\0')
03368     {
03369       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03370           "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
03371       return FALSE;
03372     }
03373 
03374   if (!_dbus_string_init (&uuid))
03375     {
03376       _DBUS_SET_OOM (error);
03377       return FALSE;
03378     }
03379 
03380   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03381     {
03382       _DBUS_SET_OOM (error);
03383       goto out;
03384     }
03385 
03386   i = 0;
03387   argv[i] = "dbus-launch";
03388   ++i;
03389   argv[i] = "--autolaunch";
03390   ++i;
03391   argv[i] = _dbus_string_get_data (&uuid);
03392   ++i;
03393   argv[i] = "--binary-syntax";
03394   ++i;
03395   argv[i] = "--close-stderr";
03396   ++i;
03397   argv[i] = NULL;
03398   ++i;
03399 
03400   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03401 
03402   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03403                                        TRUE,
03404                                        argv, address, error);
03405 
03406  out:
03407   _dbus_string_free (&uuid);
03408   return retval;
03409 #else
03410   dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03411       "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
03412       "set your DBUS_SESSION_BUS_ADDRESS instead");
03413   return FALSE;
03414 #endif
03415 }
03416 
03435 dbus_bool_t
03436 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03437                                dbus_bool_t create_if_not_found,
03438                                DBusError  *error)
03439 {
03440   DBusString filename;
03441   dbus_bool_t b;
03442 
03443   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03444 
03445   b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03446   if (b)
03447     return TRUE;
03448 
03449   dbus_error_free (error);
03450 
03451   /* Fallback to the system machine ID */
03452   _dbus_string_init_const (&filename, "/etc/machine-id");
03453   return _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
03454 }
03455 
03456 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03457 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03458 
03465 dbus_bool_t
03466 _dbus_lookup_launchd_socket (DBusString *socket_path,
03467                              const char *launchd_env_var,
03468                              DBusError  *error)
03469 {
03470 #ifdef DBUS_ENABLE_LAUNCHD
03471   char *argv[4];
03472   int i;
03473 
03474   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03475 
03476   i = 0;
03477   argv[i] = "launchctl";
03478   ++i;
03479   argv[i] = "getenv";
03480   ++i;
03481   argv[i] = (char*)launchd_env_var;
03482   ++i;
03483   argv[i] = NULL;
03484   ++i;
03485 
03486   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03487 
03488   if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
03489     {
03490       return FALSE;
03491     }
03492 
03493   /* no error, but no result either */
03494   if (_dbus_string_get_length(socket_path) == 0)
03495     {
03496       return FALSE;
03497     }
03498 
03499   /* strip the carriage-return */
03500   _dbus_string_shorten(socket_path, 1);
03501   return TRUE;
03502 #else /* DBUS_ENABLE_LAUNCHD */
03503   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03504                 "can't lookup socket from launchd; launchd support not compiled in");
03505   return FALSE;
03506 #endif
03507 }
03508 
03509 static dbus_bool_t
03510 _dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
03511 {
03512 #ifdef DBUS_ENABLE_LAUNCHD
03513   dbus_bool_t valid_socket;
03514   DBusString socket_path;
03515 
03516   if (!_dbus_string_init (&socket_path))
03517     {
03518       _DBUS_SET_OOM (error);
03519       return FALSE;
03520     }
03521 
03522   valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
03523 
03524   if (dbus_error_is_set(error))
03525     {
03526       _dbus_string_free(&socket_path);
03527       return FALSE;
03528     }
03529 
03530   if (!valid_socket)
03531     {
03532       dbus_set_error(error, "no socket path",
03533                 "launchd did not provide a socket path, "
03534                 "verify that org.freedesktop.dbus-session.plist is loaded!");
03535       _dbus_string_free(&socket_path);
03536       return FALSE;
03537     }
03538   if (!_dbus_string_append (address, "unix:path="))
03539     {
03540       _DBUS_SET_OOM (error);
03541       _dbus_string_free(&socket_path);
03542       return FALSE;
03543     }
03544   if (!_dbus_string_copy (&socket_path, 0, address,
03545                           _dbus_string_get_length (address)))
03546     {
03547       _DBUS_SET_OOM (error);
03548       _dbus_string_free(&socket_path);
03549       return FALSE;
03550     }
03551 
03552   _dbus_string_free(&socket_path);
03553   return TRUE;
03554 #else
03555   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03556                 "can't lookup session address from launchd; launchd support not compiled in");
03557   return FALSE;
03558 #endif
03559 }
03560 
03580 dbus_bool_t
03581 _dbus_lookup_session_address (dbus_bool_t *supported,
03582                               DBusString  *address,
03583                               DBusError   *error)
03584 {
03585 #ifdef DBUS_ENABLE_LAUNCHD
03586   *supported = TRUE;
03587   return _dbus_lookup_session_address_launchd (address, error);
03588 #else
03589   /* On non-Mac Unix platforms, if the session address isn't already
03590    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03591    * fall back to the autolaunch: global default; see
03592    * init_session_address in dbus/dbus-bus.c. */
03593   *supported = FALSE;
03594   return TRUE;
03595 #endif
03596 }
03597 
03615 dbus_bool_t
03616 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03617 {
03618   const char *xdg_data_home;
03619   const char *xdg_data_dirs;
03620   DBusString servicedir_path;
03621 
03622   if (!_dbus_string_init (&servicedir_path))
03623     return FALSE;
03624 
03625   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03626   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03627 
03628   if (xdg_data_home != NULL)
03629     {
03630       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03631         goto oom;
03632     }
03633   else
03634     {
03635       const DBusString *homedir;
03636       DBusString local_share;
03637 
03638       if (!_dbus_homedir_from_current_process (&homedir))
03639         goto oom;
03640 
03641       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03642         goto oom;
03643 
03644       _dbus_string_init_const (&local_share, "/.local/share");
03645       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03646         goto oom;
03647     }
03648 
03649   if (!_dbus_string_append (&servicedir_path, ":"))
03650     goto oom;
03651 
03652   if (xdg_data_dirs != NULL)
03653     {
03654       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03655         goto oom;
03656 
03657       if (!_dbus_string_append (&servicedir_path, ":"))
03658         goto oom;
03659     }
03660   else
03661     {
03662       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03663         goto oom;
03664     }
03665 
03666   /*
03667    * add configured datadir to defaults
03668    * this may be the same as an xdg dir
03669    * however the config parser should take
03670    * care of duplicates
03671    */
03672   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
03673     goto oom;
03674 
03675   if (!_dbus_split_paths_and_append (&servicedir_path,
03676                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03677                                      dirs))
03678     goto oom;
03679 
03680   _dbus_string_free (&servicedir_path);
03681   return TRUE;
03682 
03683  oom:
03684   _dbus_string_free (&servicedir_path);
03685   return FALSE;
03686 }
03687 
03688 
03707 dbus_bool_t
03708 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03709 {
03710   const char *xdg_data_dirs;
03711   DBusString servicedir_path;
03712 
03713   if (!_dbus_string_init (&servicedir_path))
03714     return FALSE;
03715 
03716   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03717 
03718   if (xdg_data_dirs != NULL)
03719     {
03720       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03721         goto oom;
03722 
03723       if (!_dbus_string_append (&servicedir_path, ":"))
03724         goto oom;
03725     }
03726   else
03727     {
03728       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03729         goto oom;
03730     }
03731 
03732   /*
03733    * Add configured datadir to defaults. This may be the same as one
03734    * of the XDG directories. However, the config parser should take
03735    * care of the duplicates.
03736    *
03737    * Also, append /lib as counterpart of /usr/share on the root
03738    * directory (the root directory does not know /share), in order to
03739    * facilitate early boot system bus activation where /usr might not
03740    * be available.
03741    */
03742   if (!_dbus_string_append (&servicedir_path,
03743                             DBUS_DATADIR":"
03744                             "/lib:"))
03745         goto oom;
03746 
03747   if (!_dbus_split_paths_and_append (&servicedir_path,
03748                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03749                                      dirs))
03750     goto oom;
03751 
03752   _dbus_string_free (&servicedir_path);
03753   return TRUE;
03754 
03755  oom:
03756   _dbus_string_free (&servicedir_path);
03757   return FALSE;
03758 }
03759 
03768 dbus_bool_t
03769 _dbus_append_system_config_file (DBusString *str)
03770 {
03771   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03772 }
03773 
03780 dbus_bool_t
03781 _dbus_append_session_config_file (DBusString *str)
03782 {
03783   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03784 }
03785 
03793 void
03794 _dbus_flush_caches (void)
03795 {
03796   _dbus_user_database_flush_system ();
03797 }
03798 
03812 dbus_bool_t
03813 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03814                                                 DBusCredentials *credentials)
03815 {
03816   DBusString homedir;
03817   DBusString dotdir;
03818   dbus_uid_t uid;
03819 
03820   _dbus_assert (credentials != NULL);
03821   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03822 
03823   if (!_dbus_string_init (&homedir))
03824     return FALSE;
03825 
03826   uid = _dbus_credentials_get_unix_uid (credentials);
03827   _dbus_assert (uid != DBUS_UID_UNSET);
03828 
03829   if (!_dbus_homedir_from_uid (uid, &homedir))
03830     goto failed;
03831 
03832 #ifdef DBUS_BUILD_TESTS
03833   {
03834     const char *override;
03835 
03836     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03837     if (override != NULL && *override != '\0')
03838       {
03839         _dbus_string_set_length (&homedir, 0);
03840         if (!_dbus_string_append (&homedir, override))
03841           goto failed;
03842 
03843         _dbus_verbose ("Using fake homedir for testing: %s\n",
03844                        _dbus_string_get_const_data (&homedir));
03845       }
03846     else
03847       {
03848         static dbus_bool_t already_warned = FALSE;
03849         if (!already_warned)
03850           {
03851             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03852             already_warned = TRUE;
03853           }
03854       }
03855   }
03856 #endif
03857 
03858   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03859   if (!_dbus_concat_dir_and_file (&homedir,
03860                                   &dotdir))
03861     goto failed;
03862 
03863   if (!_dbus_string_copy (&homedir, 0,
03864                           directory, _dbus_string_get_length (directory))) {
03865     goto failed;
03866   }
03867 
03868   _dbus_string_free (&homedir);
03869   return TRUE;
03870 
03871  failed:
03872   _dbus_string_free (&homedir);
03873   return FALSE;
03874 }
03875 
03876 //PENDING(kdab) docs
03877 dbus_bool_t
03878 _dbus_daemon_publish_session_bus_address (const char* addr,
03879                                           const char *scope)
03880 {
03881   return TRUE;
03882 }
03883 
03884 //PENDING(kdab) docs
03885 void
03886 _dbus_daemon_unpublish_session_bus_address (void)
03887 {
03888 
03889 }
03890 
03897 dbus_bool_t
03898 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03899 {
03900   return errno == EAGAIN || errno == EWOULDBLOCK;
03901 }
03902 
03910 dbus_bool_t
03911 _dbus_delete_directory (const DBusString *filename,
03912                         DBusError        *error)
03913 {
03914   const char *filename_c;
03915 
03916   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03917 
03918   filename_c = _dbus_string_get_const_data (filename);
03919 
03920   if (rmdir (filename_c) != 0)
03921     {
03922       dbus_set_error (error, DBUS_ERROR_FAILED,
03923                       "Failed to remove directory %s: %s\n",
03924                       filename_c, _dbus_strerror (errno));
03925       return FALSE;
03926     }
03927 
03928   return TRUE;
03929 }
03930 
03938 dbus_bool_t
03939 _dbus_socket_can_pass_unix_fd(int fd) {
03940 
03941 #ifdef SCM_RIGHTS
03942   union {
03943     struct sockaddr sa;
03944     struct sockaddr_storage storage;
03945     struct sockaddr_un un;
03946   } sa_buf;
03947 
03948   socklen_t sa_len = sizeof(sa_buf);
03949 
03950   _DBUS_ZERO(sa_buf);
03951 
03952   if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
03953     return FALSE;
03954 
03955   return sa_buf.sa.sa_family == AF_UNIX;
03956 
03957 #else
03958   return FALSE;
03959 
03960 #endif
03961 }
03962 
03963 
03964 /*
03965  * replaces the term DBUS_PREFIX in configure_time_path by the
03966  * current dbus installation directory. On unix this function is a noop
03967  *
03968  * @param configure_time_path
03969  * @return real path
03970  */
03971 const char *
03972 _dbus_replace_install_prefix (const char *configure_time_path)
03973 {
03974   return configure_time_path;
03975 }
03976 
03977 /* tests in dbus-sysdeps-util.c */