• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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 static dbus_bool_t
00094 _dbus_open_socket (int              *fd_p,
00095                    int               domain,
00096                    int               type,
00097                    int               protocol,
00098                    DBusError        *error)
00099 {
00100 #ifdef SOCK_CLOEXEC
00101   dbus_bool_t cloexec_done;
00102 
00103   *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
00104   cloexec_done = *fd_p >= 0;
00105 
00106   /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
00107   if (*fd_p < 0 && errno == EINVAL)
00108 #endif
00109     {
00110       *fd_p = socket (domain, type, protocol);
00111     }
00112 
00113   if (*fd_p >= 0)
00114     {
00115 #ifdef SOCK_CLOEXEC
00116       if (!cloexec_done)
00117 #endif
00118         {
00119           _dbus_fd_set_close_on_exec(*fd_p);
00120         }
00121 
00122       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00123       return TRUE;
00124     }
00125   else
00126     {
00127       dbus_set_error(error,
00128                      _dbus_error_from_errno (errno),
00129                      "Failed to open socket: %s",
00130                      _dbus_strerror (errno));
00131       return FALSE;
00132     }
00133 }
00134 
00135 dbus_bool_t
00136 _dbus_open_tcp_socket (int              *fd,
00137                        DBusError        *error)
00138 {
00139   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00140 }
00141 
00152 dbus_bool_t
00153 _dbus_open_unix_socket (int              *fd,
00154                         DBusError        *error)
00155 {
00156   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00157 }
00158 
00167 dbus_bool_t
00168 _dbus_close_socket (int               fd,
00169                     DBusError        *error)
00170 {
00171   return _dbus_close (fd, error);
00172 }
00173 
00183 int
00184 _dbus_read_socket (int               fd,
00185                    DBusString       *buffer,
00186                    int               count)
00187 {
00188   return _dbus_read (fd, buffer, count);
00189 }
00190 
00201 int
00202 _dbus_write_socket (int               fd,
00203                     const DBusString *buffer,
00204                     int               start,
00205                     int               len)
00206 {
00207 #if HAVE_DECL_MSG_NOSIGNAL
00208   const char *data;
00209   int bytes_written;
00210 
00211   data = _dbus_string_get_const_data_len (buffer, start, len);
00212 
00213  again:
00214 
00215   bytes_written = send (fd, data, len, MSG_NOSIGNAL);
00216 
00217   if (bytes_written < 0 && errno == EINTR)
00218     goto again;
00219 
00220   return bytes_written;
00221 
00222 #else
00223   return _dbus_write (fd, buffer, start, len);
00224 #endif
00225 }
00226 
00239 int
00240 _dbus_read_socket_with_unix_fds (int               fd,
00241                                  DBusString       *buffer,
00242                                  int               count,
00243                                  int              *fds,
00244                                  int              *n_fds) {
00245 #ifndef HAVE_UNIX_FD_PASSING
00246   int r;
00247 
00248   if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
00249     return r;
00250 
00251   *n_fds = 0;
00252   return r;
00253 
00254 #else
00255   int bytes_read;
00256   int start;
00257   struct msghdr m;
00258   struct iovec iov;
00259 
00260   _dbus_assert (count >= 0);
00261   _dbus_assert (*n_fds >= 0);
00262 
00263   start = _dbus_string_get_length (buffer);
00264 
00265   if (!_dbus_string_lengthen (buffer, count))
00266     {
00267       errno = ENOMEM;
00268       return -1;
00269     }
00270 
00271   _DBUS_ZERO(iov);
00272   iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
00273   iov.iov_len = count;
00274 
00275   _DBUS_ZERO(m);
00276   m.msg_iov = &iov;
00277   m.msg_iovlen = 1;
00278 
00279   /* Hmm, we have no clue how long the control data will actually be
00280      that is queued for us. The least we can do is assume that the
00281      caller knows. Hence let's make space for the number of fds that
00282      we shall read at max plus the cmsg header. */
00283   m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
00284 
00285   /* It's probably safe to assume that systems with SCM_RIGHTS also
00286      know alloca() */
00287   m.msg_control = alloca(m.msg_controllen);
00288   memset(m.msg_control, 0, m.msg_controllen);
00289 
00290  again:
00291 
00292   bytes_read = recvmsg(fd, &m, 0
00293 #ifdef MSG_CMSG_CLOEXEC
00294                        |MSG_CMSG_CLOEXEC
00295 #endif
00296                        );
00297 
00298   if (bytes_read < 0)
00299     {
00300       if (errno == EINTR)
00301         goto again;
00302       else
00303         {
00304           /* put length back (note that this doesn't actually realloc anything) */
00305           _dbus_string_set_length (buffer, start);
00306           return -1;
00307         }
00308     }
00309   else
00310     {
00311       struct cmsghdr *cm;
00312       dbus_bool_t found = FALSE;
00313 
00314       if (m.msg_flags & MSG_CTRUNC)
00315         {
00316           /* Hmm, apparently the control data was truncated. The bad
00317              thing is that we might have completely lost a couple of fds
00318              without chance to recover them. Hence let's treat this as a
00319              serious error. */
00320 
00321           errno = ENOSPC;
00322           _dbus_string_set_length (buffer, start);
00323           return -1;
00324         }
00325 
00326       for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
00327         if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
00328           {
00329             unsigned i;
00330 
00331             _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
00332             *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
00333 
00334             memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
00335             found = TRUE;
00336 
00337             /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
00338                worked, hence we need to go through this list and set
00339                CLOEXEC everywhere in any case */
00340             for (i = 0; i < *n_fds; i++)
00341               _dbus_fd_set_close_on_exec(fds[i]);
00342 
00343             break;
00344           }
00345 
00346       if (!found)
00347         *n_fds = 0;
00348 
00349       /* put length back (doesn't actually realloc) */
00350       _dbus_string_set_length (buffer, start + bytes_read);
00351 
00352 #if 0
00353       if (bytes_read > 0)
00354         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00355 #endif
00356 
00357       return bytes_read;
00358     }
00359 #endif
00360 }
00361 
00362 int
00363 _dbus_write_socket_with_unix_fds(int               fd,
00364                                  const DBusString *buffer,
00365                                  int               start,
00366                                  int               len,
00367                                  const int        *fds,
00368                                  int               n_fds) {
00369 
00370 #ifndef HAVE_UNIX_FD_PASSING
00371 
00372   if (n_fds > 0) {
00373     errno = ENOTSUP;
00374     return -1;
00375   }
00376 
00377   return _dbus_write_socket(fd, buffer, start, len);
00378 #else
00379   return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
00380 #endif
00381 }
00382 
00383 int
00384 _dbus_write_socket_with_unix_fds_two(int               fd,
00385                                      const DBusString *buffer1,
00386                                      int               start1,
00387                                      int               len1,
00388                                      const DBusString *buffer2,
00389                                      int               start2,
00390                                      int               len2,
00391                                      const int        *fds,
00392                                      int               n_fds) {
00393 
00394 #ifndef HAVE_UNIX_FD_PASSING
00395 
00396   if (n_fds > 0) {
00397     errno = ENOTSUP;
00398     return -1;
00399   }
00400 
00401   return _dbus_write_socket_two(fd,
00402                                 buffer1, start1, len1,
00403                                 buffer2, start2, len2);
00404 #else
00405 
00406   struct msghdr m;
00407   struct cmsghdr *cm;
00408   struct iovec iov[2];
00409   int bytes_written;
00410 
00411   _dbus_assert (len1 >= 0);
00412   _dbus_assert (len2 >= 0);
00413   _dbus_assert (n_fds >= 0);
00414 
00415   _DBUS_ZERO(iov);
00416   iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
00417   iov[0].iov_len = len1;
00418 
00419   if (buffer2)
00420     {
00421       iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
00422       iov[1].iov_len = len2;
00423     }
00424 
00425   _DBUS_ZERO(m);
00426   m.msg_iov = iov;
00427   m.msg_iovlen = buffer2 ? 2 : 1;
00428 
00429   if (n_fds > 0)
00430     {
00431       m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
00432       m.msg_control = alloca(m.msg_controllen);
00433       memset(m.msg_control, 0, m.msg_controllen);
00434 
00435       cm = CMSG_FIRSTHDR(&m);
00436       cm->cmsg_level = SOL_SOCKET;
00437       cm->cmsg_type = SCM_RIGHTS;
00438       cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
00439       memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
00440     }
00441 
00442  again:
00443 
00444   bytes_written = sendmsg (fd, &m, 0
00445 #if HAVE_DECL_MSG_NOSIGNAL
00446                            |MSG_NOSIGNAL
00447 #endif
00448                            );
00449 
00450   if (bytes_written < 0 && errno == EINTR)
00451     goto again;
00452 
00453 #if 0
00454   if (bytes_written > 0)
00455     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00456 #endif
00457 
00458   return bytes_written;
00459 #endif
00460 }
00461 
00475 int
00476 _dbus_write_socket_two (int               fd,
00477                         const DBusString *buffer1,
00478                         int               start1,
00479                         int               len1,
00480                         const DBusString *buffer2,
00481                         int               start2,
00482                         int               len2)
00483 {
00484 #if HAVE_DECL_MSG_NOSIGNAL
00485   struct iovec vectors[2];
00486   const char *data1;
00487   const char *data2;
00488   int bytes_written;
00489   struct msghdr m;
00490 
00491   _dbus_assert (buffer1 != NULL);
00492   _dbus_assert (start1 >= 0);
00493   _dbus_assert (start2 >= 0);
00494   _dbus_assert (len1 >= 0);
00495   _dbus_assert (len2 >= 0);
00496 
00497   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00498 
00499   if (buffer2 != NULL)
00500     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00501   else
00502     {
00503       data2 = NULL;
00504       start2 = 0;
00505       len2 = 0;
00506     }
00507 
00508   vectors[0].iov_base = (char*) data1;
00509   vectors[0].iov_len = len1;
00510   vectors[1].iov_base = (char*) data2;
00511   vectors[1].iov_len = len2;
00512 
00513   _DBUS_ZERO(m);
00514   m.msg_iov = vectors;
00515   m.msg_iovlen = data2 ? 2 : 1;
00516 
00517  again:
00518 
00519   bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
00520 
00521   if (bytes_written < 0 && errno == EINTR)
00522     goto again;
00523 
00524   return bytes_written;
00525 
00526 #else
00527   return _dbus_write_two (fd, buffer1, start1, len1,
00528                           buffer2, start2, len2);
00529 #endif
00530 }
00531 
00532 dbus_bool_t
00533 _dbus_socket_is_invalid (int fd)
00534 {
00535     return fd < 0 ? TRUE : FALSE;
00536 }
00537 
00554 int
00555 _dbus_read (int               fd,
00556             DBusString       *buffer,
00557             int               count)
00558 {
00559   int bytes_read;
00560   int start;
00561   char *data;
00562 
00563   _dbus_assert (count >= 0);
00564 
00565   start = _dbus_string_get_length (buffer);
00566 
00567   if (!_dbus_string_lengthen (buffer, count))
00568     {
00569       errno = ENOMEM;
00570       return -1;
00571     }
00572 
00573   data = _dbus_string_get_data_len (buffer, start, count);
00574 
00575  again:
00576 
00577   bytes_read = read (fd, data, count);
00578 
00579   if (bytes_read < 0)
00580     {
00581       if (errno == EINTR)
00582         goto again;
00583       else
00584         {
00585           /* put length back (note that this doesn't actually realloc anything) */
00586           _dbus_string_set_length (buffer, start);
00587           return -1;
00588         }
00589     }
00590   else
00591     {
00592       /* put length back (doesn't actually realloc) */
00593       _dbus_string_set_length (buffer, start + bytes_read);
00594 
00595 #if 0
00596       if (bytes_read > 0)
00597         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00598 #endif
00599 
00600       return bytes_read;
00601     }
00602 }
00603 
00614 int
00615 _dbus_write (int               fd,
00616              const DBusString *buffer,
00617              int               start,
00618              int               len)
00619 {
00620   const char *data;
00621   int bytes_written;
00622 
00623   data = _dbus_string_get_const_data_len (buffer, start, len);
00624 
00625  again:
00626 
00627   bytes_written = write (fd, data, len);
00628 
00629   if (bytes_written < 0 && errno == EINTR)
00630     goto again;
00631 
00632 #if 0
00633   if (bytes_written > 0)
00634     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00635 #endif
00636 
00637   return bytes_written;
00638 }
00639 
00660 int
00661 _dbus_write_two (int               fd,
00662                  const DBusString *buffer1,
00663                  int               start1,
00664                  int               len1,
00665                  const DBusString *buffer2,
00666                  int               start2,
00667                  int               len2)
00668 {
00669   _dbus_assert (buffer1 != NULL);
00670   _dbus_assert (start1 >= 0);
00671   _dbus_assert (start2 >= 0);
00672   _dbus_assert (len1 >= 0);
00673   _dbus_assert (len2 >= 0);
00674 
00675 #ifdef HAVE_WRITEV
00676   {
00677     struct iovec vectors[2];
00678     const char *data1;
00679     const char *data2;
00680     int bytes_written;
00681 
00682     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00683 
00684     if (buffer2 != NULL)
00685       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00686     else
00687       {
00688         data2 = NULL;
00689         start2 = 0;
00690         len2 = 0;
00691       }
00692 
00693     vectors[0].iov_base = (char*) data1;
00694     vectors[0].iov_len = len1;
00695     vectors[1].iov_base = (char*) data2;
00696     vectors[1].iov_len = len2;
00697 
00698   again:
00699 
00700     bytes_written = writev (fd,
00701                             vectors,
00702                             data2 ? 2 : 1);
00703 
00704     if (bytes_written < 0 && errno == EINTR)
00705       goto again;
00706 
00707     return bytes_written;
00708   }
00709 #else /* HAVE_WRITEV */
00710   {
00711     int ret1;
00712 
00713     ret1 = _dbus_write (fd, buffer1, start1, len1);
00714     if (ret1 == len1 && buffer2 != NULL)
00715       {
00716         ret2 = _dbus_write (fd, buffer2, start2, len2);
00717         if (ret2 < 0)
00718           ret2 = 0; /* we can't report an error as the first write was OK */
00719 
00720         return ret1 + ret2;
00721       }
00722     else
00723       return ret1;
00724   }
00725 #endif /* !HAVE_WRITEV */
00726 }
00727 
00728 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00729 
00759 int
00760 _dbus_connect_unix_socket (const char     *path,
00761                            dbus_bool_t     abstract,
00762                            DBusError      *error)
00763 {
00764   int fd;
00765   size_t path_len;
00766   struct sockaddr_un addr;
00767 
00768   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00769 
00770   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00771                  path, abstract);
00772 
00773 
00774   if (!_dbus_open_unix_socket (&fd, error))
00775     {
00776       _DBUS_ASSERT_ERROR_IS_SET(error);
00777       return -1;
00778     }
00779   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00780 
00781   _DBUS_ZERO (addr);
00782   addr.sun_family = AF_UNIX;
00783   path_len = strlen (path);
00784 
00785   if (abstract)
00786     {
00787 #ifdef HAVE_ABSTRACT_SOCKETS
00788       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00789       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00790 
00791       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00792         {
00793           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00794                       "Abstract socket name too long\n");
00795           _dbus_close (fd, NULL);
00796           return -1;
00797         }
00798 
00799       strncpy (&addr.sun_path[1], path, path_len);
00800       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00801 #else /* HAVE_ABSTRACT_SOCKETS */
00802       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00803                       "Operating system does not support abstract socket namespace\n");
00804       _dbus_close (fd, NULL);
00805       return -1;
00806 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00807     }
00808   else
00809     {
00810       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00811         {
00812           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00813                       "Socket name too long\n");
00814           _dbus_close (fd, NULL);
00815           return -1;
00816         }
00817 
00818       strncpy (addr.sun_path, path, path_len);
00819     }
00820 
00821   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00822     {
00823       dbus_set_error (error,
00824                       _dbus_error_from_errno (errno),
00825                       "Failed to connect to socket %s: %s",
00826                       path, _dbus_strerror (errno));
00827 
00828       _dbus_close (fd, NULL);
00829       fd = -1;
00830 
00831       return -1;
00832     }
00833 
00834   if (!_dbus_set_fd_nonblocking (fd, error))
00835     {
00836       _DBUS_ASSERT_ERROR_IS_SET (error);
00837 
00838       _dbus_close (fd, NULL);
00839       fd = -1;
00840 
00841       return -1;
00842     }
00843 
00844   return fd;
00845 }
00846 
00856 static dbus_bool_t
00857 _dbus_set_local_creds (int fd, dbus_bool_t on)
00858 {
00859   dbus_bool_t retval = TRUE;
00860 
00861 #if defined(HAVE_CMSGCRED)
00862   /* NOOP just to make sure only one codepath is used
00863    *      and to prefer CMSGCRED
00864    */
00865 #elif defined(LOCAL_CREDS)
00866   int val = on ? 1 : 0;
00867   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00868     {
00869       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00870       retval = FALSE;
00871     }
00872   else
00873     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00874                    on ? "enabled" : "disabled", fd);
00875 #endif
00876 
00877   return retval;
00878 }
00879 
00897 int
00898 _dbus_listen_unix_socket (const char     *path,
00899                           dbus_bool_t     abstract,
00900                           DBusError      *error)
00901 {
00902   int listen_fd;
00903   struct sockaddr_un addr;
00904   size_t path_len;
00905   unsigned int reuseaddr;
00906 
00907   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00908 
00909   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00910                  path, abstract);
00911 
00912   if (!_dbus_open_unix_socket (&listen_fd, error))
00913     {
00914       _DBUS_ASSERT_ERROR_IS_SET(error);
00915       return -1;
00916     }
00917   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00918 
00919   _DBUS_ZERO (addr);
00920   addr.sun_family = AF_UNIX;
00921   path_len = strlen (path);
00922 
00923   if (abstract)
00924     {
00925 #ifdef HAVE_ABSTRACT_SOCKETS
00926       /* remember that abstract names aren't nul-terminated so we rely
00927        * on sun_path being filled in with zeroes above.
00928        */
00929       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00930       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00931 
00932       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00933         {
00934           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00935                       "Abstract socket name too long\n");
00936           _dbus_close (listen_fd, NULL);
00937           return -1;
00938         }
00939 
00940       strncpy (&addr.sun_path[1], path, path_len);
00941       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00942 #else /* HAVE_ABSTRACT_SOCKETS */
00943       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00944                       "Operating system does not support abstract socket namespace\n");
00945       _dbus_close (listen_fd, NULL);
00946       return -1;
00947 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00948     }
00949   else
00950     {
00951       /* Discussed security implications of this with Nalin,
00952        * and we couldn't think of where it would kick our ass, but
00953        * it still seems a bit sucky. It also has non-security suckage;
00954        * really we'd prefer to exit if the socket is already in use.
00955        * But there doesn't seem to be a good way to do this.
00956        *
00957        * Just to be extra careful, I threw in the stat() - clearly
00958        * the stat() can't *fix* any security issue, but it at least
00959        * avoids inadvertent/accidental data loss.
00960        */
00961       {
00962         struct stat sb;
00963 
00964         if (stat (path, &sb) == 0 &&
00965             S_ISSOCK (sb.st_mode))
00966           unlink (path);
00967       }
00968 
00969       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00970         {
00971           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00972                       "Abstract socket name too long\n");
00973           _dbus_close (listen_fd, NULL);
00974           return -1;
00975         }
00976 
00977       strncpy (addr.sun_path, path, path_len);
00978     }
00979 
00980   reuseaddr = 1;
00981   if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
00982     {
00983       _dbus_warn ("Failed to set socket option\"%s\": %s",
00984                   path, _dbus_strerror (errno));
00985     }
00986 
00987   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00988     {
00989       dbus_set_error (error, _dbus_error_from_errno (errno),
00990                       "Failed to bind socket \"%s\": %s",
00991                       path, _dbus_strerror (errno));
00992       _dbus_close (listen_fd, NULL);
00993       return -1;
00994     }
00995 
00996   if (listen (listen_fd, 30 /* backlog */) < 0)
00997     {
00998       dbus_set_error (error, _dbus_error_from_errno (errno),
00999                       "Failed to listen on socket \"%s\": %s",
01000                       path, _dbus_strerror (errno));
01001       _dbus_close (listen_fd, NULL);
01002       return -1;
01003     }
01004 
01005   if (!_dbus_set_local_creds (listen_fd, TRUE))
01006     {
01007       dbus_set_error (error, _dbus_error_from_errno (errno),
01008                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
01009                       path, _dbus_strerror (errno));
01010       close (listen_fd);
01011       return -1;
01012     }
01013 
01014   if (!_dbus_set_fd_nonblocking (listen_fd, error))
01015     {
01016       _DBUS_ASSERT_ERROR_IS_SET (error);
01017       _dbus_close (listen_fd, NULL);
01018       return -1;
01019     }
01020 
01021   /* Try opening up the permissions, but if we can't, just go ahead
01022    * and continue, maybe it will be good enough.
01023    */
01024   if (!abstract && chmod (path, 0777) < 0)
01025     _dbus_warn ("Could not set mode 0777 on socket %s\n",
01026                 path);
01027 
01028   return listen_fd;
01029 }
01030 
01041 int
01042 _dbus_listen_systemd_sockets (int       **fds,
01043                               DBusError *error)
01044 {
01045   int r, n;
01046   unsigned fd;
01047   int *new_fds;
01048 
01049   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01050 
01051   n = sd_listen_fds (TRUE);
01052   if (n < 0)
01053     {
01054       dbus_set_error (error, _dbus_error_from_errno (-n),
01055                       "Failed to acquire systemd socket: %s",
01056                       _dbus_strerror (-n));
01057       return -1;
01058     }
01059 
01060   if (n <= 0)
01061     {
01062       dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01063                       "No socket received.");
01064       return -1;
01065     }
01066 
01067   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01068     {
01069       r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
01070       if (r < 0)
01071         {
01072           dbus_set_error (error, _dbus_error_from_errno (-r),
01073                           "Failed to verify systemd socket type: %s",
01074                           _dbus_strerror (-r));
01075           return -1;
01076         }
01077 
01078       if (!r)
01079         {
01080           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01081                           "Passed socket has wrong type.");
01082           return -1;
01083         }
01084     }
01085 
01086   /* OK, the file descriptors are all good, so let's take posession of
01087      them then. */
01088 
01089   new_fds = dbus_new (int, n);
01090   if (!new_fds)
01091     {
01092       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
01093                       "Failed to allocate file handle array.");
01094       goto fail;
01095     }
01096 
01097   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01098     {
01099       if (!_dbus_set_local_creds (fd, TRUE))
01100         {
01101           dbus_set_error (error, _dbus_error_from_errno (errno),
01102                           "Failed to enable LOCAL_CREDS on systemd socket: %s",
01103                           _dbus_strerror (errno));
01104           goto fail;
01105         }
01106 
01107       if (!_dbus_set_fd_nonblocking (fd, error))
01108         {
01109           _DBUS_ASSERT_ERROR_IS_SET (error);
01110           goto fail;
01111         }
01112 
01113       new_fds[fd - SD_LISTEN_FDS_START] = fd;
01114     }
01115 
01116   *fds = new_fds;
01117   return n;
01118 
01119  fail:
01120 
01121   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01122     {
01123       _dbus_close (fd, NULL);
01124     }
01125 
01126   dbus_free (new_fds);
01127   return -1;
01128 }
01129 
01143 int
01144 _dbus_connect_tcp_socket (const char     *host,
01145                           const char     *port,
01146                           const char     *family,
01147                           DBusError      *error)
01148 {
01149     return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
01150 }
01151 
01152 int
01153 _dbus_connect_tcp_socket_with_nonce (const char     *host,
01154                                      const char     *port,
01155                                      const char     *family,
01156                                      const char     *noncefile,
01157                                      DBusError      *error)
01158 {
01159   int saved_errno = 0;
01160   int fd = -1, res;
01161   struct addrinfo hints;
01162   struct addrinfo *ai, *tmp;
01163 
01164   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01165 
01166   if (!_dbus_open_tcp_socket (&fd, error))
01167     {
01168       _DBUS_ASSERT_ERROR_IS_SET(error);
01169       return -1;
01170     }
01171 
01172   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01173 
01174   _DBUS_ZERO (hints);
01175 
01176   if (!family)
01177     hints.ai_family = AF_UNSPEC;
01178   else if (!strcmp(family, "ipv4"))
01179     hints.ai_family = AF_INET;
01180   else if (!strcmp(family, "ipv6"))
01181     hints.ai_family = AF_INET6;
01182   else
01183     {
01184       dbus_set_error (error,
01185                       DBUS_ERROR_BAD_ADDRESS,
01186                       "Unknown address family %s", family);
01187       return -1;
01188     }
01189   hints.ai_protocol = IPPROTO_TCP;
01190   hints.ai_socktype = SOCK_STREAM;
01191   hints.ai_flags = AI_ADDRCONFIG;
01192 
01193   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
01194     {
01195       dbus_set_error (error,
01196                       _dbus_error_from_errno (errno),
01197                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01198                       host, port, gai_strerror(res), res);
01199       _dbus_close (fd, NULL);
01200       return -1;
01201     }
01202 
01203   tmp = ai;
01204   while (tmp)
01205     {
01206       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01207         {
01208           freeaddrinfo(ai);
01209           _DBUS_ASSERT_ERROR_IS_SET(error);
01210           return -1;
01211         }
01212       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01213 
01214       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01215         {
01216           saved_errno = errno;
01217           _dbus_close(fd, NULL);
01218           fd = -1;
01219           tmp = tmp->ai_next;
01220           continue;
01221         }
01222 
01223       break;
01224     }
01225   freeaddrinfo(ai);
01226 
01227   if (fd == -1)
01228     {
01229       dbus_set_error (error,
01230                       _dbus_error_from_errno (saved_errno),
01231                       "Failed to connect to socket \"%s:%s\" %s",
01232                       host, port, _dbus_strerror(saved_errno));
01233       return -1;
01234     }
01235 
01236   if (noncefile != NULL)
01237     {
01238       DBusString noncefileStr;
01239       dbus_bool_t ret;
01240       _dbus_string_init_const (&noncefileStr, noncefile);
01241       ret = _dbus_send_nonce (fd, &noncefileStr, error);
01242       _dbus_string_free (&noncefileStr);
01243 
01244       if (!ret)
01245     {
01246       _dbus_close (fd, NULL);
01247           return -1;
01248         }
01249     }
01250 
01251   if (!_dbus_set_fd_nonblocking (fd, error))
01252     {
01253       _dbus_close (fd, NULL);
01254       return -1;
01255     }
01256 
01257   return fd;
01258 }
01259 
01276 int
01277 _dbus_listen_tcp_socket (const char     *host,
01278                          const char     *port,
01279                          const char     *family,
01280                          DBusString     *retport,
01281                          int           **fds_p,
01282                          DBusError      *error)
01283 {
01284   int saved_errno;
01285   int nlisten_fd = 0, *listen_fd = NULL, res, i;
01286   struct addrinfo hints;
01287   struct addrinfo *ai, *tmp;
01288   unsigned int reuseaddr;
01289 
01290   *fds_p = NULL;
01291   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01292 
01293   _DBUS_ZERO (hints);
01294 
01295   if (!family)
01296     hints.ai_family = AF_UNSPEC;
01297   else if (!strcmp(family, "ipv4"))
01298     hints.ai_family = AF_INET;
01299   else if (!strcmp(family, "ipv6"))
01300     hints.ai_family = AF_INET6;
01301   else
01302     {
01303       dbus_set_error (error,
01304                       DBUS_ERROR_BAD_ADDRESS,
01305                       "Unknown address family %s", family);
01306       return -1;
01307     }
01308 
01309   hints.ai_protocol = IPPROTO_TCP;
01310   hints.ai_socktype = SOCK_STREAM;
01311   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
01312 
01313  redo_lookup_with_port:
01314   ai = NULL;
01315   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01316     {
01317       dbus_set_error (error,
01318                       _dbus_error_from_errno (errno),
01319                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01320                       host ? host : "*", port, gai_strerror(res), res);
01321       goto failed;
01322     }
01323 
01324   tmp = ai;
01325   while (tmp)
01326     {
01327       int fd = -1, *newlisten_fd;
01328       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01329         {
01330           _DBUS_ASSERT_ERROR_IS_SET(error);
01331           goto failed;
01332         }
01333       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01334 
01335       reuseaddr = 1;
01336       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01337         {
01338           _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01339                       host ? host : "*", port, _dbus_strerror (errno));
01340         }
01341 
01342       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01343         {
01344           saved_errno = errno;
01345           _dbus_close(fd, NULL);
01346           if (saved_errno == EADDRINUSE)
01347             {
01348               /* Depending on kernel policy, it may or may not
01349                  be neccessary to bind to both IPv4 & 6 addresses
01350                  so ignore EADDRINUSE here */
01351               tmp = tmp->ai_next;
01352               continue;
01353             }
01354           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01355                           "Failed to bind socket \"%s:%s\": %s",
01356                           host ? host : "*", port, _dbus_strerror (saved_errno));
01357           goto failed;
01358         }
01359 
01360       if (listen (fd, 30 /* backlog */) < 0)
01361         {
01362           saved_errno = errno;
01363           _dbus_close (fd, NULL);
01364           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01365                           "Failed to listen on socket \"%s:%s\": %s",
01366                           host ? host : "*", port, _dbus_strerror (saved_errno));
01367           goto failed;
01368         }
01369 
01370       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
01371       if (!newlisten_fd)
01372         {
01373           saved_errno = errno;
01374           _dbus_close (fd, NULL);
01375           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01376                           "Failed to allocate file handle array: %s",
01377                           _dbus_strerror (saved_errno));
01378           goto failed;
01379         }
01380       listen_fd = newlisten_fd;
01381       listen_fd[nlisten_fd] = fd;
01382       nlisten_fd++;
01383 
01384       if (!_dbus_string_get_length(retport))
01385         {
01386           /* If the user didn't specify a port, or used 0, then
01387              the kernel chooses a port. After the first address
01388              is bound to, we need to force all remaining addresses
01389              to use the same port */
01390           if (!port || !strcmp(port, "0"))
01391             {
01392               int result;
01393               struct sockaddr_storage addr;
01394               socklen_t addrlen;
01395               char portbuf[50];
01396 
01397               addrlen = sizeof(addr);
01398               result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01399 
01400               if (result == -1 ||
01401                   (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
01402                                       portbuf, sizeof(portbuf),
01403                                       NI_NUMERICHOST)) != 0)
01404                 {
01405                   dbus_set_error (error, _dbus_error_from_errno (errno),
01406                                   "Failed to resolve port \"%s:%s\": %s (%s)",
01407                                   host ? host : "*", port, gai_strerror(res), res);
01408                   goto failed;
01409                 }
01410               if (!_dbus_string_append(retport, portbuf))
01411                 {
01412                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01413                   goto failed;
01414                 }
01415 
01416               /* Release current address list & redo lookup */
01417               port = _dbus_string_get_const_data(retport);
01418               freeaddrinfo(ai);
01419               goto redo_lookup_with_port;
01420             }
01421           else
01422             {
01423               if (!_dbus_string_append(retport, port))
01424                 {
01425                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01426                     goto failed;
01427                 }
01428             }
01429         }
01430 
01431       tmp = tmp->ai_next;
01432     }
01433   freeaddrinfo(ai);
01434   ai = NULL;
01435 
01436   if (!nlisten_fd)
01437     {
01438       errno = EADDRINUSE;
01439       dbus_set_error (error, _dbus_error_from_errno (errno),
01440                       "Failed to bind socket \"%s:%s\": %s",
01441                       host ? host : "*", port, _dbus_strerror (errno));
01442       goto failed;
01443     }
01444 
01445   for (i = 0 ; i < nlisten_fd ; i++)
01446     {
01447       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01448         {
01449           goto failed;
01450         }
01451     }
01452 
01453   *fds_p = listen_fd;
01454 
01455   return nlisten_fd;
01456 
01457  failed:
01458   if (ai)
01459     freeaddrinfo(ai);
01460   for (i = 0 ; i < nlisten_fd ; i++)
01461     _dbus_close(listen_fd[i], NULL);
01462   dbus_free(listen_fd);
01463   return -1;
01464 }
01465 
01466 static dbus_bool_t
01467 write_credentials_byte (int             server_fd,
01468                         DBusError      *error)
01469 {
01470   int bytes_written;
01471   char buf[1] = { '\0' };
01472 #if defined(HAVE_CMSGCRED)
01473   union {
01474           struct cmsghdr hdr;
01475           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01476   } cmsg;
01477   struct iovec iov;
01478   struct msghdr msg;
01479   iov.iov_base = buf;
01480   iov.iov_len = 1;
01481 
01482   _DBUS_ZERO(msg);
01483   msg.msg_iov = &iov;
01484   msg.msg_iovlen = 1;
01485 
01486   msg.msg_control = (caddr_t) &cmsg;
01487   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01488   _DBUS_ZERO(cmsg);
01489   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01490   cmsg.hdr.cmsg_level = SOL_SOCKET;
01491   cmsg.hdr.cmsg_type = SCM_CREDS;
01492 #endif
01493 
01494   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01495 
01496  again:
01497 
01498 #if defined(HAVE_CMSGCRED)
01499   bytes_written = sendmsg (server_fd, &msg, 0
01500 #if HAVE_DECL_MSG_NOSIGNAL
01501                            |MSG_NOSIGNAL
01502 #endif
01503                            );
01504 #else
01505   bytes_written = send (server_fd, buf, 1, 0
01506 #if HAVE_DECL_MSG_NOSIGNAL
01507                         |MSG_NOSIGNAL
01508 #endif
01509                         );
01510 #endif
01511 
01512   if (bytes_written < 0 && errno == EINTR)
01513     goto again;
01514 
01515   if (bytes_written < 0)
01516     {
01517       dbus_set_error (error, _dbus_error_from_errno (errno),
01518                       "Failed to write credentials byte: %s",
01519                      _dbus_strerror (errno));
01520       return FALSE;
01521     }
01522   else if (bytes_written == 0)
01523     {
01524       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01525                       "wrote zero bytes writing credentials byte");
01526       return FALSE;
01527     }
01528   else
01529     {
01530       _dbus_assert (bytes_written == 1);
01531       _dbus_verbose ("wrote credentials byte\n");
01532       return TRUE;
01533     }
01534 }
01535 
01557 dbus_bool_t
01558 _dbus_read_credentials_socket  (int              client_fd,
01559                                 DBusCredentials *credentials,
01560                                 DBusError       *error)
01561 {
01562   struct msghdr msg;
01563   struct iovec iov;
01564   char buf;
01565   dbus_uid_t uid_read;
01566   dbus_pid_t pid_read;
01567   int bytes_read;
01568 
01569 #ifdef HAVE_CMSGCRED
01570   union {
01571     struct cmsghdr hdr;
01572     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01573   } cmsg;
01574 
01575 #elif defined(LOCAL_CREDS)
01576   struct {
01577     struct cmsghdr hdr;
01578     struct sockcred cred;
01579   } cmsg;
01580 #endif
01581 
01582   uid_read = DBUS_UID_UNSET;
01583   pid_read = DBUS_PID_UNSET;
01584 
01585   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01586 
01587   /* The POSIX spec certainly doesn't promise this, but
01588    * we need these assertions to fail as soon as we're wrong about
01589    * it so we can do the porting fixups
01590    */
01591   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01592   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01593   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01594 
01595   _dbus_credentials_clear (credentials);
01596 
01597   /* Systems supporting LOCAL_CREDS are configured to have this feature
01598    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01599    * the connection.  Therefore, the received message must carry the
01600    * credentials information without doing anything special.
01601    */
01602 
01603   iov.iov_base = &buf;
01604   iov.iov_len = 1;
01605 
01606   _DBUS_ZERO(msg);
01607   msg.msg_iov = &iov;
01608   msg.msg_iovlen = 1;
01609 
01610 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01611   _DBUS_ZERO(cmsg);
01612   msg.msg_control = (caddr_t) &cmsg;
01613   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01614 #endif
01615 
01616  again:
01617   bytes_read = recvmsg (client_fd, &msg, 0);
01618 
01619   if (bytes_read < 0)
01620     {
01621       if (errno == EINTR)
01622         goto again;
01623 
01624       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01625        * normally only call read_credentials if the socket was ready
01626        * for reading
01627        */
01628 
01629       dbus_set_error (error, _dbus_error_from_errno (errno),
01630                       "Failed to read credentials byte: %s",
01631                       _dbus_strerror (errno));
01632       return FALSE;
01633     }
01634   else if (bytes_read == 0)
01635     {
01636       /* this should not happen unless we are using recvmsg wrong,
01637        * so is essentially here for paranoia
01638        */
01639       dbus_set_error (error, DBUS_ERROR_FAILED,
01640                       "Failed to read credentials byte (zero-length read)");
01641       return FALSE;
01642     }
01643   else if (buf != '\0')
01644     {
01645       dbus_set_error (error, DBUS_ERROR_FAILED,
01646                       "Credentials byte was not nul");
01647       return FALSE;
01648     }
01649 
01650 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01651   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01652                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01653     {
01654       dbus_set_error (error, DBUS_ERROR_FAILED,
01655                       "Message from recvmsg() was not SCM_CREDS");
01656       return FALSE;
01657     }
01658 #endif
01659 
01660   _dbus_verbose ("read credentials byte\n");
01661 
01662   {
01663 #ifdef SO_PEERCRED
01664 #ifdef __OpenBSD__
01665     struct sockpeercred cr;
01666 #else
01667     struct ucred cr;
01668 #endif
01669     int cr_len = sizeof (cr);
01670 
01671     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01672         cr_len == sizeof (cr))
01673       {
01674         pid_read = cr.pid;
01675         uid_read = cr.uid;
01676       }
01677     else
01678       {
01679         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01680                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01681       }
01682 #elif defined(HAVE_CMSGCRED)
01683     struct cmsgcred *cred;
01684 
01685     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01686     pid_read = cred->cmcred_pid;
01687     uid_read = cred->cmcred_euid;
01688 #elif defined(LOCAL_CREDS)
01689     pid_read = DBUS_PID_UNSET;
01690     uid_read = cmsg.cred.sc_uid;
01691     /* Since we have already got the credentials from this socket, we can
01692      * disable its LOCAL_CREDS flag if it was ever set. */
01693     _dbus_set_local_creds (client_fd, FALSE);
01694 #elif defined(HAVE_GETPEEREID)
01695     uid_t euid;
01696     gid_t egid;
01697     if (getpeereid (client_fd, &euid, &egid) == 0)
01698       {
01699         uid_read = euid;
01700       }
01701     else
01702       {
01703         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01704       }
01705 #elif defined(HAVE_GETPEERUCRED)
01706     ucred_t * ucred = NULL;
01707     if (getpeerucred (client_fd, &ucred) == 0)
01708       {
01709         pid_read = ucred_getpid (ucred);
01710         uid_read = ucred_geteuid (ucred);
01711 #ifdef HAVE_ADT
01712         /* generate audit session data based on socket ucred */
01713         adt_session_data_t *adth = NULL;
01714         adt_export_data_t *data = NULL;
01715         size_t size = 0;
01716         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01717           {
01718             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01719           }
01720         else
01721           {
01722             if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01723               {
01724                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01725               }
01726             else
01727               {
01728                 size = adt_export_session_data (adth, &data);
01729                 if (size <= 0)
01730                   {
01731                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01732                   }
01733                 else
01734                   {
01735                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01736                     free (data);
01737                   }
01738               }
01739             (void) adt_end_session (adth);
01740           }
01741 #endif /* HAVE_ADT */
01742       }
01743     else
01744       {
01745         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01746       }
01747     if (ucred != NULL)
01748       ucred_free (ucred);
01749 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01750     _dbus_verbose ("Socket credentials not supported on this OS\n");
01751 #endif
01752   }
01753 
01754   _dbus_verbose ("Credentials:"
01755                  "  pid "DBUS_PID_FORMAT
01756                  "  uid "DBUS_UID_FORMAT
01757                  "\n",
01758                  pid_read,
01759                  uid_read);
01760 
01761   if (pid_read != DBUS_PID_UNSET)
01762     {
01763       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01764         {
01765           _DBUS_SET_OOM (error);
01766           return FALSE;
01767         }
01768     }
01769 
01770   if (uid_read != DBUS_UID_UNSET)
01771     {
01772       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01773         {
01774           _DBUS_SET_OOM (error);
01775           return FALSE;
01776         }
01777     }
01778 
01779   return TRUE;
01780 }
01781 
01799 dbus_bool_t
01800 _dbus_send_credentials_socket  (int              server_fd,
01801                                 DBusError       *error)
01802 {
01803   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01804 
01805   if (write_credentials_byte (server_fd, error))
01806     return TRUE;
01807   else
01808     return FALSE;
01809 }
01810 
01820 int
01821 _dbus_accept  (int listen_fd)
01822 {
01823   int client_fd;
01824   struct sockaddr addr;
01825   socklen_t addrlen;
01826 #ifdef HAVE_ACCEPT4
01827   dbus_bool_t cloexec_done;
01828 #endif
01829 
01830   addrlen = sizeof (addr);
01831 
01832  retry:
01833 
01834 #ifdef HAVE_ACCEPT4
01835   /* We assume that if accept4 is available SOCK_CLOEXEC is too */
01836   client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
01837   cloexec_done = client_fd >= 0;
01838 
01839   if (client_fd < 0 && errno == ENOSYS)
01840 #endif
01841     {
01842       client_fd = accept (listen_fd, &addr, &addrlen);
01843     }
01844 
01845   if (client_fd < 0)
01846     {
01847       if (errno == EINTR)
01848         goto retry;
01849     }
01850 
01851   _dbus_verbose ("client fd %d accepted\n", client_fd);
01852 
01853 #ifdef HAVE_ACCEPT4
01854   if (!cloexec_done)
01855 #endif
01856     {
01857       _dbus_fd_set_close_on_exec(client_fd);
01858     }
01859 
01860   return client_fd;
01861 }
01862 
01871 dbus_bool_t
01872 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01873 {
01874   const char *directory;
01875   struct stat sb;
01876 
01877   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01878 
01879   directory = _dbus_string_get_const_data (dir);
01880 
01881   if (stat (directory, &sb) < 0)
01882     {
01883       dbus_set_error (error, _dbus_error_from_errno (errno),
01884                       "%s", _dbus_strerror (errno));
01885 
01886       return FALSE;
01887     }
01888 
01889   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01890       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01891     {
01892       dbus_set_error (error, DBUS_ERROR_FAILED,
01893                      "%s directory is not private to the user", directory);
01894       return FALSE;
01895     }
01896 
01897   return TRUE;
01898 }
01899 
01900 static dbus_bool_t
01901 fill_user_info_from_passwd (struct passwd *p,
01902                             DBusUserInfo  *info,
01903                             DBusError     *error)
01904 {
01905   _dbus_assert (p->pw_name != NULL);
01906   _dbus_assert (p->pw_dir != NULL);
01907 
01908   info->uid = p->pw_uid;
01909   info->primary_gid = p->pw_gid;
01910   info->username = _dbus_strdup (p->pw_name);
01911   info->homedir = _dbus_strdup (p->pw_dir);
01912 
01913   if (info->username == NULL ||
01914       info->homedir == NULL)
01915     {
01916       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01917       return FALSE;
01918     }
01919 
01920   return TRUE;
01921 }
01922 
01923 static dbus_bool_t
01924 fill_user_info (DBusUserInfo       *info,
01925                 dbus_uid_t          uid,
01926                 const DBusString   *username,
01927                 DBusError          *error)
01928 {
01929   const char *username_c;
01930 
01931   /* exactly one of username/uid provided */
01932   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01933   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01934 
01935   info->uid = DBUS_UID_UNSET;
01936   info->primary_gid = DBUS_GID_UNSET;
01937   info->group_ids = NULL;
01938   info->n_group_ids = 0;
01939   info->username = NULL;
01940   info->homedir = NULL;
01941 
01942   if (username != NULL)
01943     username_c = _dbus_string_get_const_data (username);
01944   else
01945     username_c = NULL;
01946 
01947   /* For now assuming that the getpwnam() and getpwuid() flavors
01948    * are always symmetrical, if not we have to add more configure
01949    * checks
01950    */
01951 
01952 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01953   {
01954     struct passwd *p;
01955     int result;
01956     size_t buflen;
01957     char *buf;
01958     struct passwd p_str;
01959 
01960     /* retrieve maximum needed size for buf */
01961     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01962 
01963     /* sysconf actually returns a long, but everything else expects size_t,
01964      * so just recast here.
01965      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
01966      */
01967     if ((long) buflen <= 0)
01968       buflen = 1024;
01969 
01970     result = -1;
01971     while (1)
01972       {
01973         buf = dbus_malloc (buflen);
01974         if (buf == NULL)
01975           {
01976             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01977             return FALSE;
01978           }
01979 
01980         p = NULL;
01981 #ifdef HAVE_POSIX_GETPWNAM_R
01982         if (uid != DBUS_UID_UNSET)
01983           result = getpwuid_r (uid, &p_str, buf, buflen,
01984                                &p);
01985         else
01986           result = getpwnam_r (username_c, &p_str, buf, buflen,
01987                                &p);
01988 #else
01989         if (uid != DBUS_UID_UNSET)
01990           p = getpwuid_r (uid, &p_str, buf, buflen);
01991         else
01992           p = getpwnam_r (username_c, &p_str, buf, buflen);
01993         result = 0;
01994 #endif /* !HAVE_POSIX_GETPWNAM_R */
01995         //Try a bigger buffer if ERANGE was returned
01996         if (result == ERANGE && buflen < 512 * 1024)
01997           {
01998             dbus_free (buf);
01999             buflen *= 2;
02000           }
02001         else
02002           {
02003             break;
02004           }
02005       }
02006     if (result == 0 && p == &p_str)
02007       {
02008         if (!fill_user_info_from_passwd (p, info, error))
02009           {
02010             dbus_free (buf);
02011             return FALSE;
02012           }
02013         dbus_free (buf);
02014       }
02015     else
02016       {
02017         dbus_set_error (error, _dbus_error_from_errno (errno),
02018                         "User \"%s\" unknown or no memory to allocate password entry\n",
02019                         username_c ? username_c : "???");
02020         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02021         dbus_free (buf);
02022         return FALSE;
02023       }
02024   }
02025 #else /* ! HAVE_GETPWNAM_R */
02026   {
02027     /* I guess we're screwed on thread safety here */
02028     struct passwd *p;
02029 
02030     if (uid != DBUS_UID_UNSET)
02031       p = getpwuid (uid);
02032     else
02033       p = getpwnam (username_c);
02034 
02035     if (p != NULL)
02036       {
02037         if (!fill_user_info_from_passwd (p, info, error))
02038           {
02039             return FALSE;
02040           }
02041       }
02042     else
02043       {
02044         dbus_set_error (error, _dbus_error_from_errno (errno),
02045                         "User \"%s\" unknown or no memory to allocate password entry\n",
02046                         username_c ? username_c : "???");
02047         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02048         return FALSE;
02049       }
02050   }
02051 #endif  /* ! HAVE_GETPWNAM_R */
02052 
02053   /* Fill this in so we can use it to get groups */
02054   username_c = info->username;
02055 
02056 #ifdef HAVE_GETGROUPLIST
02057   {
02058     gid_t *buf;
02059     int buf_count;
02060     int i;
02061     int initial_buf_count;
02062 
02063     initial_buf_count = 17;
02064     buf_count = initial_buf_count;
02065     buf = dbus_new (gid_t, buf_count);
02066     if (buf == NULL)
02067       {
02068         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02069         goto failed;
02070       }
02071 
02072     if (getgrouplist (username_c,
02073                       info->primary_gid,
02074                       buf, &buf_count) < 0)
02075       {
02076         gid_t *new;
02077         /* Presumed cause of negative return code: buf has insufficient
02078            entries to hold the entire group list. The Linux behavior in this
02079            case is to pass back the actual number of groups in buf_count, but
02080            on Mac OS X 10.5, buf_count is unhelpfully left alone.
02081            So as a hack, try to help out a bit by guessing a larger
02082            number of groups, within reason.. might still fail, of course,
02083            but we can at least print a more informative message.  I looked up
02084            the "right way" to do this by downloading Apple's own source code
02085            for the "id" command, and it turns out that they use an
02086            undocumented library function getgrouplist_2 (!) which is not
02087            declared in any header in /usr/include (!!). That did not seem
02088            like the way to go here.
02089         */
02090         if (buf_count == initial_buf_count)
02091           {
02092             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
02093           }
02094         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02095         if (new == NULL)
02096           {
02097             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02098             dbus_free (buf);
02099             goto failed;
02100           }
02101 
02102         buf = new;
02103 
02104         errno = 0;
02105         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02106           {
02107             if (errno == 0)
02108               {
02109                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02110                             username_c, buf_count, buf_count);
02111               }
02112             else
02113               {
02114                 dbus_set_error (error,
02115                                 _dbus_error_from_errno (errno),
02116                                 "Failed to get groups for username \"%s\" primary GID "
02117                                 DBUS_GID_FORMAT ": %s\n",
02118                                 username_c, info->primary_gid,
02119                                 _dbus_strerror (errno));
02120                 dbus_free (buf);
02121                 goto failed;
02122               }
02123           }
02124       }
02125 
02126     info->group_ids = dbus_new (dbus_gid_t, buf_count);
02127     if (info->group_ids == NULL)
02128       {
02129         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02130         dbus_free (buf);
02131         goto failed;
02132       }
02133 
02134     for (i = 0; i < buf_count; ++i)
02135       info->group_ids[i] = buf[i];
02136 
02137     info->n_group_ids = buf_count;
02138 
02139     dbus_free (buf);
02140   }
02141 #else  /* HAVE_GETGROUPLIST */
02142   {
02143     /* We just get the one group ID */
02144     info->group_ids = dbus_new (dbus_gid_t, 1);
02145     if (info->group_ids == NULL)
02146       {
02147         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02148         goto failed;
02149       }
02150 
02151     info->n_group_ids = 1;
02152 
02153     (info->group_ids)[0] = info->primary_gid;
02154   }
02155 #endif /* HAVE_GETGROUPLIST */
02156 
02157   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02158 
02159   return TRUE;
02160 
02161  failed:
02162   _DBUS_ASSERT_ERROR_IS_SET (error);
02163   return FALSE;
02164 }
02165 
02174 dbus_bool_t
02175 _dbus_user_info_fill (DBusUserInfo     *info,
02176                       const DBusString *username,
02177                       DBusError        *error)
02178 {
02179   return fill_user_info (info, DBUS_UID_UNSET,
02180                          username, error);
02181 }
02182 
02191 dbus_bool_t
02192 _dbus_user_info_fill_uid (DBusUserInfo *info,
02193                           dbus_uid_t    uid,
02194                           DBusError    *error)
02195 {
02196   return fill_user_info (info, uid,
02197                          NULL, error);
02198 }
02199 
02207 dbus_bool_t
02208 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02209 {
02210   /* The POSIX spec certainly doesn't promise this, but
02211    * we need these assertions to fail as soon as we're wrong about
02212    * it so we can do the porting fixups
02213    */
02214   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
02215   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
02216   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
02217 
02218   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
02219     return FALSE;
02220   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02221     return FALSE;
02222 
02223   return TRUE;
02224 }
02225 
02237 dbus_bool_t
02238 _dbus_append_user_from_current_process (DBusString *str)
02239 {
02240   return _dbus_string_append_uint (str,
02241                                    _dbus_geteuid ());
02242 }
02243 
02248 dbus_pid_t
02249 _dbus_getpid (void)
02250 {
02251   return getpid ();
02252 }
02253 
02257 dbus_uid_t
02258 _dbus_getuid (void)
02259 {
02260   return getuid ();
02261 }
02262 
02266 dbus_uid_t
02267 _dbus_geteuid (void)
02268 {
02269   return geteuid ();
02270 }
02271 
02278 unsigned long
02279 _dbus_pid_for_log (void)
02280 {
02281   return getpid ();
02282 }
02283 
02291 dbus_bool_t
02292 _dbus_parse_uid (const DBusString      *uid_str,
02293                  dbus_uid_t            *uid)
02294 {
02295   int end;
02296   long val;
02297 
02298   if (_dbus_string_get_length (uid_str) == 0)
02299     {
02300       _dbus_verbose ("UID string was zero length\n");
02301       return FALSE;
02302     }
02303 
02304   val = -1;
02305   end = 0;
02306   if (!_dbus_string_parse_int (uid_str, 0, &val,
02307                                &end))
02308     {
02309       _dbus_verbose ("could not parse string as a UID\n");
02310       return FALSE;
02311     }
02312 
02313   if (end != _dbus_string_get_length (uid_str))
02314     {
02315       _dbus_verbose ("string contained trailing stuff after UID\n");
02316       return FALSE;
02317     }
02318 
02319   *uid = val;
02320 
02321   return TRUE;
02322 }
02323 
02324 #if !DBUS_USE_SYNC
02325 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
02326 #endif
02327 
02334 dbus_int32_t
02335 _dbus_atomic_inc (DBusAtomic *atomic)
02336 {
02337 #if DBUS_USE_SYNC
02338   return __sync_add_and_fetch(&atomic->value, 1)-1;
02339 #else
02340   dbus_int32_t res;
02341   _DBUS_LOCK (atomic);
02342   res = atomic->value;
02343   atomic->value += 1;
02344   _DBUS_UNLOCK (atomic);
02345   return res;
02346 #endif
02347 }
02348 
02355 dbus_int32_t
02356 _dbus_atomic_dec (DBusAtomic *atomic)
02357 {
02358 #if DBUS_USE_SYNC
02359   return __sync_sub_and_fetch(&atomic->value, 1)+1;
02360 #else
02361   dbus_int32_t res;
02362 
02363   _DBUS_LOCK (atomic);
02364   res = atomic->value;
02365   atomic->value -= 1;
02366   _DBUS_UNLOCK (atomic);
02367   return res;
02368 #endif
02369 }
02370 
02378 dbus_int32_t
02379 _dbus_atomic_get (DBusAtomic *atomic)
02380 {
02381 #if DBUS_USE_SYNC
02382   __sync_synchronize ();
02383   return atomic->value;
02384 #else
02385   dbus_int32_t res;
02386 
02387   _DBUS_LOCK (atomic);
02388   res = atomic->value;
02389   _DBUS_UNLOCK (atomic);
02390   return res;
02391 #endif
02392 }
02393 
02394 #ifdef DBUS_BUILD_TESTS
02395 
02398 dbus_gid_t
02399 _dbus_getgid (void)
02400 {
02401   return getgid ();
02402 }
02403 #endif
02404 
02413 int
02414 _dbus_poll (DBusPollFD *fds,
02415             int         n_fds,
02416             int         timeout_milliseconds)
02417 {
02418 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02419   /* This big thing is a constant expression and should get optimized
02420    * out of existence. So it's more robust than a configure check at
02421    * no cost.
02422    */
02423   if (_DBUS_POLLIN == POLLIN &&
02424       _DBUS_POLLPRI == POLLPRI &&
02425       _DBUS_POLLOUT == POLLOUT &&
02426       _DBUS_POLLERR == POLLERR &&
02427       _DBUS_POLLHUP == POLLHUP &&
02428       _DBUS_POLLNVAL == POLLNVAL &&
02429       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
02430       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
02431       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
02432       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
02433       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
02434       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
02435       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
02436     {
02437       return poll ((struct pollfd*) fds,
02438                    n_fds,
02439                    timeout_milliseconds);
02440     }
02441   else
02442     {
02443       /* We have to convert the DBusPollFD to an array of
02444        * struct pollfd, poll, and convert back.
02445        */
02446       _dbus_warn ("didn't implement poll() properly for this system yet\n");
02447       return -1;
02448     }
02449 #else /* ! HAVE_POLL */
02450 
02451   fd_set read_set, write_set, err_set;
02452   int max_fd = 0;
02453   int i;
02454   struct timeval tv;
02455   int ready;
02456 
02457   FD_ZERO (&read_set);
02458   FD_ZERO (&write_set);
02459   FD_ZERO (&err_set);
02460 
02461   for (i = 0; i < n_fds; i++)
02462     {
02463       DBusPollFD *fdp = &fds[i];
02464 
02465       if (fdp->events & _DBUS_POLLIN)
02466         FD_SET (fdp->fd, &read_set);
02467 
02468       if (fdp->events & _DBUS_POLLOUT)
02469         FD_SET (fdp->fd, &write_set);
02470 
02471       FD_SET (fdp->fd, &err_set);
02472 
02473       max_fd = MAX (max_fd, fdp->fd);
02474     }
02475 
02476   tv.tv_sec = timeout_milliseconds / 1000;
02477   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02478 
02479   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02480                   timeout_milliseconds < 0 ? NULL : &tv);
02481 
02482   if (ready > 0)
02483     {
02484       for (i = 0; i < n_fds; i++)
02485         {
02486           DBusPollFD *fdp = &fds[i];
02487 
02488           fdp->revents = 0;
02489 
02490           if (FD_ISSET (fdp->fd, &read_set))
02491             fdp->revents |= _DBUS_POLLIN;
02492 
02493           if (FD_ISSET (fdp->fd, &write_set))
02494             fdp->revents |= _DBUS_POLLOUT;
02495 
02496           if (FD_ISSET (fdp->fd, &err_set))
02497             fdp->revents |= _DBUS_POLLERR;
02498         }
02499     }
02500 
02501   return ready;
02502 #endif
02503 }
02504 
02512 void
02513 _dbus_get_current_time (long *tv_sec,
02514                         long *tv_usec)
02515 {
02516   struct timeval t;
02517 
02518 #ifdef HAVE_MONOTONIC_CLOCK
02519   struct timespec ts;
02520   clock_gettime (CLOCK_MONOTONIC, &ts);
02521 
02522   if (tv_sec)
02523     *tv_sec = ts.tv_sec;
02524   if (tv_usec)
02525     *tv_usec = ts.tv_nsec / 1000;
02526 #else
02527   gettimeofday (&t, NULL);
02528 
02529   if (tv_sec)
02530     *tv_sec = t.tv_sec;
02531   if (tv_usec)
02532     *tv_usec = t.tv_usec;
02533 #endif
02534 }
02535 
02544 dbus_bool_t
02545 _dbus_create_directory (const DBusString *filename,
02546                         DBusError        *error)
02547 {
02548   const char *filename_c;
02549 
02550   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02551 
02552   filename_c = _dbus_string_get_const_data (filename);
02553 
02554   if (mkdir (filename_c, 0700) < 0)
02555     {
02556       if (errno == EEXIST)
02557         return TRUE;
02558 
02559       dbus_set_error (error, DBUS_ERROR_FAILED,
02560                       "Failed to create directory %s: %s\n",
02561                       filename_c, _dbus_strerror (errno));
02562       return FALSE;
02563     }
02564   else
02565     return TRUE;
02566 }
02567 
02578 dbus_bool_t
02579 _dbus_concat_dir_and_file (DBusString       *dir,
02580                            const DBusString *next_component)
02581 {
02582   dbus_bool_t dir_ends_in_slash;
02583   dbus_bool_t file_starts_with_slash;
02584 
02585   if (_dbus_string_get_length (dir) == 0 ||
02586       _dbus_string_get_length (next_component) == 0)
02587     return TRUE;
02588 
02589   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02590                                                     _dbus_string_get_length (dir) - 1);
02591 
02592   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02593 
02594   if (dir_ends_in_slash && file_starts_with_slash)
02595     {
02596       _dbus_string_shorten (dir, 1);
02597     }
02598   else if (!(dir_ends_in_slash || file_starts_with_slash))
02599     {
02600       if (!_dbus_string_append_byte (dir, '/'))
02601         return FALSE;
02602     }
02603 
02604   return _dbus_string_copy (next_component, 0, dir,
02605                             _dbus_string_get_length (dir));
02606 }
02607 
02609 #define NANOSECONDS_PER_SECOND       1000000000
02610 
02611 #define MICROSECONDS_PER_SECOND      1000000
02612 
02613 #define MILLISECONDS_PER_SECOND      1000
02614 
02615 #define NANOSECONDS_PER_MILLISECOND  1000000
02616 
02617 #define MICROSECONDS_PER_MILLISECOND 1000
02618 
02623 void
02624 _dbus_sleep_milliseconds (int milliseconds)
02625 {
02626 #ifdef HAVE_NANOSLEEP
02627   struct timespec req;
02628   struct timespec rem;
02629 
02630   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02631   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02632   rem.tv_sec = 0;
02633   rem.tv_nsec = 0;
02634 
02635   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02636     req = rem;
02637 #elif defined (HAVE_USLEEP)
02638   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02639 #else /* ! HAVE_USLEEP */
02640   sleep (MAX (milliseconds / 1000, 1));
02641 #endif
02642 }
02643 
02644 static dbus_bool_t
02645 _dbus_generate_pseudorandom_bytes (DBusString *str,
02646                                    int         n_bytes)
02647 {
02648   int old_len;
02649   char *p;
02650 
02651   old_len = _dbus_string_get_length (str);
02652 
02653   if (!_dbus_string_lengthen (str, n_bytes))
02654     return FALSE;
02655 
02656   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02657 
02658   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02659 
02660   return TRUE;
02661 }
02662 
02671 dbus_bool_t
02672 _dbus_generate_random_bytes (DBusString *str,
02673                              int         n_bytes)
02674 {
02675   int old_len;
02676   int fd;
02677 
02678   /* FALSE return means "no memory", if it could
02679    * mean something else then we'd need to return
02680    * a DBusError. So we always fall back to pseudorandom
02681    * if the I/O fails.
02682    */
02683 
02684   old_len = _dbus_string_get_length (str);
02685   fd = -1;
02686 
02687   /* note, urandom on linux will fall back to pseudorandom */
02688   fd = open ("/dev/urandom", O_RDONLY);
02689   if (fd < 0)
02690     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02691 
02692   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02693 
02694   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02695     {
02696       _dbus_close (fd, NULL);
02697       _dbus_string_set_length (str, old_len);
02698       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02699     }
02700 
02701   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02702                  n_bytes);
02703 
02704   _dbus_close (fd, NULL);
02705 
02706   return TRUE;
02707 }
02708 
02714 void
02715 _dbus_exit (int code)
02716 {
02717   _exit (code);
02718 }
02719 
02728 const char*
02729 _dbus_strerror (int error_number)
02730 {
02731   const char *msg;
02732 
02733   msg = strerror (error_number);
02734   if (msg == NULL)
02735     msg = "unknown";
02736 
02737   return msg;
02738 }
02739 
02743 void
02744 _dbus_disable_sigpipe (void)
02745 {
02746   signal (SIGPIPE, SIG_IGN);
02747 }
02748 
02756 void
02757 _dbus_fd_set_close_on_exec (intptr_t fd)
02758 {
02759   int val;
02760 
02761   val = fcntl (fd, F_GETFD, 0);
02762 
02763   if (val < 0)
02764     return;
02765 
02766   val |= FD_CLOEXEC;
02767 
02768   fcntl (fd, F_SETFD, val);
02769 }
02770 
02778 dbus_bool_t
02779 _dbus_close (int        fd,
02780              DBusError *error)
02781 {
02782   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02783 
02784  again:
02785   if (close (fd) < 0)
02786     {
02787       if (errno == EINTR)
02788         goto again;
02789 
02790       dbus_set_error (error, _dbus_error_from_errno (errno),
02791                       "Could not close fd %d", fd);
02792       return FALSE;
02793     }
02794 
02795   return TRUE;
02796 }
02797 
02805 int
02806 _dbus_dup(int        fd,
02807           DBusError *error)
02808 {
02809   int new_fd;
02810 
02811 #ifdef F_DUPFD_CLOEXEC
02812   dbus_bool_t cloexec_done;
02813 
02814   new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
02815   cloexec_done = new_fd >= 0;
02816 
02817   if (new_fd < 0 && errno == EINVAL)
02818 #endif
02819     {
02820       new_fd = fcntl(fd, F_DUPFD, 3);
02821     }
02822 
02823   if (new_fd < 0) {
02824 
02825     dbus_set_error (error, _dbus_error_from_errno (errno),
02826                     "Could not duplicate fd %d", fd);
02827     return -1;
02828   }
02829 
02830 #ifdef F_DUPFD_CLOEXEC
02831   if (!cloexec_done)
02832 #endif
02833     {
02834       _dbus_fd_set_close_on_exec(new_fd);
02835     }
02836 
02837   return new_fd;
02838 }
02839 
02847 dbus_bool_t
02848 _dbus_set_fd_nonblocking (int             fd,
02849                           DBusError      *error)
02850 {
02851   int val;
02852 
02853   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02854 
02855   val = fcntl (fd, F_GETFL, 0);
02856   if (val < 0)
02857     {
02858       dbus_set_error (error, _dbus_error_from_errno (errno),
02859                       "Failed to get flags from file descriptor %d: %s",
02860                       fd, _dbus_strerror (errno));
02861       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02862                      _dbus_strerror (errno));
02863       return FALSE;
02864     }
02865 
02866   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02867     {
02868       dbus_set_error (error, _dbus_error_from_errno (errno),
02869                       "Failed to set nonblocking flag of file descriptor %d: %s",
02870                       fd, _dbus_strerror (errno));
02871       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02872                      fd, _dbus_strerror (errno));
02873 
02874       return FALSE;
02875     }
02876 
02877   return TRUE;
02878 }
02879 
02885 void
02886 _dbus_print_backtrace (void)
02887 {
02888 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02889   void *bt[500];
02890   int bt_size;
02891   int i;
02892   char **syms;
02893 
02894   bt_size = backtrace (bt, 500);
02895 
02896   syms = backtrace_symbols (bt, bt_size);
02897 
02898   i = 0;
02899   while (i < bt_size)
02900     {
02901       /* don't use dbus_warn since it can _dbus_abort() */
02902       fprintf (stderr, "  %s\n", syms[i]);
02903       ++i;
02904     }
02905   fflush (stderr);
02906 
02907   free (syms);
02908 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02909   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02910 #else
02911   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02912 #endif
02913 }
02914 
02932 dbus_bool_t
02933 _dbus_full_duplex_pipe (int        *fd1,
02934                         int        *fd2,
02935                         dbus_bool_t blocking,
02936                         DBusError  *error)
02937 {
02938 #ifdef HAVE_SOCKETPAIR
02939   int fds[2];
02940   int retval;
02941 
02942 #ifdef SOCK_CLOEXEC
02943   dbus_bool_t cloexec_done;
02944 
02945   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
02946   cloexec_done = retval >= 0;
02947 
02948   if (retval < 0 && errno == EINVAL)
02949 #endif
02950     {
02951       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
02952     }
02953 
02954   if (retval < 0)
02955     {
02956       dbus_set_error (error, _dbus_error_from_errno (errno),
02957                       "Could not create full-duplex pipe");
02958       return FALSE;
02959     }
02960 
02961   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02962 
02963 #ifdef SOCK_CLOEXEC
02964   if (!cloexec_done)
02965 #endif
02966     {
02967       _dbus_fd_set_close_on_exec (fds[0]);
02968       _dbus_fd_set_close_on_exec (fds[1]);
02969     }
02970 
02971   if (!blocking &&
02972       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02973        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02974     {
02975       dbus_set_error (error, _dbus_error_from_errno (errno),
02976                       "Could not set full-duplex pipe nonblocking");
02977 
02978       _dbus_close (fds[0], NULL);
02979       _dbus_close (fds[1], NULL);
02980 
02981       return FALSE;
02982     }
02983 
02984   *fd1 = fds[0];
02985   *fd2 = fds[1];
02986 
02987   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02988                  *fd1, *fd2);
02989 
02990   return TRUE;
02991 #else
02992   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02993   dbus_set_error (error, DBUS_ERROR_FAILED,
02994                   "_dbus_full_duplex_pipe() not implemented on this OS");
02995   return FALSE;
02996 #endif
02997 }
02998 
03007 int
03008 _dbus_printf_string_upper_bound (const char *format,
03009                                  va_list     args)
03010 {
03011   char c;
03012   return vsnprintf (&c, 1, format, args);
03013 }
03014 
03021 const char*
03022 _dbus_get_tmpdir(void)
03023 {
03024   static const char* tmpdir = NULL;
03025 
03026   if (tmpdir == NULL)
03027     {
03028       /* TMPDIR is what glibc uses, then
03029        * glibc falls back to the P_tmpdir macro which
03030        * just expands to "/tmp"
03031        */
03032       if (tmpdir == NULL)
03033         tmpdir = getenv("TMPDIR");
03034 
03035       /* These two env variables are probably
03036        * broken, but maybe some OS uses them?
03037        */
03038       if (tmpdir == NULL)
03039         tmpdir = getenv("TMP");
03040       if (tmpdir == NULL)
03041         tmpdir = getenv("TEMP");
03042 
03043       /* And this is the sane fallback. */
03044       if (tmpdir == NULL)
03045         tmpdir = "/tmp";
03046     }
03047 
03048   _dbus_assert(tmpdir != NULL);
03049 
03050   return tmpdir;
03051 }
03052 
03072 static dbus_bool_t
03073 _read_subprocess_line_argv (const char *progpath,
03074                             dbus_bool_t path_fallback,
03075                             char       * const *argv,
03076                             DBusString *result,
03077                             DBusError  *error)
03078 {
03079   int result_pipe[2] = { -1, -1 };
03080   int errors_pipe[2] = { -1, -1 };
03081   pid_t pid;
03082   int ret;
03083   int status;
03084   int orig_len;
03085   int i;
03086 
03087   dbus_bool_t retval;
03088   sigset_t new_set, old_set;
03089 
03090   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03091   retval = FALSE;
03092 
03093   /* We need to block any existing handlers for SIGCHLD temporarily; they
03094    * will cause waitpid() below to fail.
03095    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
03096    */
03097   sigemptyset (&new_set);
03098   sigaddset (&new_set, SIGCHLD);
03099   sigprocmask (SIG_BLOCK, &new_set, &old_set);
03100 
03101   orig_len = _dbus_string_get_length (result);
03102 
03103 #define READ_END        0
03104 #define WRITE_END       1
03105   if (pipe (result_pipe) < 0)
03106     {
03107       dbus_set_error (error, _dbus_error_from_errno (errno),
03108                       "Failed to create a pipe to call %s: %s",
03109                       progpath, _dbus_strerror (errno));
03110       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03111                      progpath, _dbus_strerror (errno));
03112       goto out;
03113     }
03114   if (pipe (errors_pipe) < 0)
03115     {
03116       dbus_set_error (error, _dbus_error_from_errno (errno),
03117                       "Failed to create a pipe to call %s: %s",
03118                       progpath, _dbus_strerror (errno));
03119       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03120                      progpath, _dbus_strerror (errno));
03121       goto out;
03122     }
03123 
03124   pid = fork ();
03125   if (pid < 0)
03126     {
03127       dbus_set_error (error, _dbus_error_from_errno (errno),
03128                       "Failed to fork() to call %s: %s",
03129                       progpath, _dbus_strerror (errno));
03130       _dbus_verbose ("Failed to fork() to call %s: %s\n",
03131                      progpath, _dbus_strerror (errno));
03132       goto out;
03133     }
03134 
03135   if (pid == 0)
03136     {
03137       /* child process */
03138       int maxfds;
03139       int fd;
03140 
03141       fd = open ("/dev/null", O_RDWR);
03142       if (fd == -1)
03143         /* huh?! can't open /dev/null? */
03144         _exit (1);
03145 
03146       _dbus_verbose ("/dev/null fd %d opened\n", fd);
03147 
03148       /* set-up stdXXX */
03149       close (result_pipe[READ_END]);
03150       close (errors_pipe[READ_END]);
03151       close (0);                /* close stdin */
03152       close (1);                /* close stdout */
03153       close (2);                /* close stderr */
03154 
03155       if (dup2 (fd, 0) == -1)
03156         _exit (1);
03157       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03158         _exit (1);
03159       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03160         _exit (1);
03161 
03162       maxfds = sysconf (_SC_OPEN_MAX);
03163       /* Pick something reasonable if for some reason sysconf
03164        * says unlimited.
03165        */
03166       if (maxfds < 0)
03167         maxfds = 1024;
03168       /* close all inherited fds */
03169       for (i = 3; i < maxfds; i++)
03170         close (i);
03171 
03172       sigprocmask (SIG_SETMASK, &old_set, NULL);
03173 
03174       /* If it looks fully-qualified, try execv first */
03175       if (progpath[0] == '/')
03176         {
03177           execv (progpath, argv);
03178           /* Ok, that failed.  Now if path_fallback is given, let's
03179            * try unqualified.  This is mostly a hack to work
03180            * around systems which ship dbus-launch in /usr/bin
03181            * but everything else in /bin (because dbus-launch
03182            * depends on X11).
03183            */
03184           if (path_fallback)
03185             /* We must have a slash, because we checked above */
03186             execvp (strrchr (progpath, '/')+1, argv);
03187         }
03188       else
03189         execvp (progpath, argv);
03190 
03191       /* still nothing, we failed */
03192       _exit (1);
03193     }
03194 
03195   /* parent process */
03196   close (result_pipe[WRITE_END]);
03197   close (errors_pipe[WRITE_END]);
03198   result_pipe[WRITE_END] = -1;
03199   errors_pipe[WRITE_END] = -1;
03200 
03201   ret = 0;
03202   do
03203     {
03204       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03205     }
03206   while (ret > 0);
03207 
03208   /* reap the child process to avoid it lingering as zombie */
03209   do
03210     {
03211       ret = waitpid (pid, &status, 0);
03212     }
03213   while (ret == -1 && errno == EINTR);
03214 
03215   /* We succeeded if the process exited with status 0 and
03216      anything was read */
03217   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03218     {
03219       /* The process ended with error */
03220       DBusString error_message;
03221       if (!_dbus_string_init (&error_message))
03222         {
03223           _DBUS_SET_OOM (error);
03224           goto out;
03225         }
03226 
03227       ret = 0;
03228       do
03229         {
03230           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03231         }
03232       while (ret > 0);
03233 
03234       _dbus_string_set_length (result, orig_len);
03235       if (_dbus_string_get_length (&error_message) > 0)
03236         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03237                         "%s terminated abnormally with the following error: %s",
03238                         progpath, _dbus_string_get_data (&error_message));
03239       else
03240         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03241                         "%s terminated abnormally without any error message",
03242                         progpath);
03243       goto out;
03244     }
03245 
03246   retval = TRUE;
03247 
03248  out:
03249   sigprocmask (SIG_SETMASK, &old_set, NULL);
03250 
03251   if (retval)
03252     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03253   else
03254     _DBUS_ASSERT_ERROR_IS_SET (error);
03255 
03256   if (result_pipe[0] != -1)
03257     close (result_pipe[0]);
03258   if (result_pipe[1] != -1)
03259     close (result_pipe[1]);
03260   if (errors_pipe[0] != -1)
03261     close (errors_pipe[0]);
03262   if (errors_pipe[1] != -1)
03263     close (errors_pipe[1]);
03264 
03265   return retval;
03266 }
03267 
03279 dbus_bool_t
03280 _dbus_get_autolaunch_address (const char *scope,
03281                               DBusString *address,
03282                               DBusError  *error)
03283 {
03284 #ifdef DBUS_BUILD_X11
03285   /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
03286    * but that's done elsewhere, and if it worked, this function wouldn't
03287    * be called.) */
03288   const char *display;
03289   static char *argv[6];
03290   int i;
03291   DBusString uuid;
03292   dbus_bool_t retval;
03293 
03294   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03295   retval = FALSE;
03296 
03297   /* fd.o #19997: if $DISPLAY isn't set to something useful, then
03298    * dbus-launch-x11 is just going to fail. Rather than trying to
03299    * run it, we might as well bail out early with a nice error. */
03300   display = _dbus_getenv ("DISPLAY");
03301 
03302   if (display == NULL || display[0] == '\0')
03303     {
03304       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03305           "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
03306       return FALSE;
03307     }
03308 
03309   if (!_dbus_string_init (&uuid))
03310     {
03311       _DBUS_SET_OOM (error);
03312       return FALSE;
03313     }
03314 
03315   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03316     {
03317       _DBUS_SET_OOM (error);
03318       goto out;
03319     }
03320 
03321   i = 0;
03322   argv[i] = "dbus-launch";
03323   ++i;
03324   argv[i] = "--autolaunch";
03325   ++i;
03326   argv[i] = _dbus_string_get_data (&uuid);
03327   ++i;
03328   argv[i] = "--binary-syntax";
03329   ++i;
03330   argv[i] = "--close-stderr";
03331   ++i;
03332   argv[i] = NULL;
03333   ++i;
03334 
03335   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03336 
03337   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03338                                        TRUE,
03339                                        argv, address, error);
03340 
03341  out:
03342   _dbus_string_free (&uuid);
03343   return retval;
03344 #else
03345   dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03346       "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
03347       "set your DBUS_SESSION_BUS_ADDRESS instead");
03348   return FALSE;
03349 #endif
03350 }
03351 
03370 dbus_bool_t
03371 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03372                                dbus_bool_t create_if_not_found,
03373                                DBusError  *error)
03374 {
03375   DBusString filename;
03376   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03377   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03378 }
03379 
03380 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03381 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03382 
03389 dbus_bool_t
03390 _dbus_lookup_launchd_socket (DBusString *socket_path,
03391                              const char *launchd_env_var,
03392                              DBusError  *error)
03393 {
03394 #ifdef DBUS_ENABLE_LAUNCHD
03395   char *argv[4];
03396   int i;
03397 
03398   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03399 
03400   i = 0;
03401   argv[i] = "launchctl";
03402   ++i;
03403   argv[i] = "getenv";
03404   ++i;
03405   argv[i] = (char*)launchd_env_var;
03406   ++i;
03407   argv[i] = NULL;
03408   ++i;
03409 
03410   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03411 
03412   if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
03413     {
03414       return FALSE;
03415     }
03416 
03417   /* no error, but no result either */
03418   if (_dbus_string_get_length(socket_path) == 0)
03419     {
03420       return FALSE;
03421     }
03422 
03423   /* strip the carriage-return */
03424   _dbus_string_shorten(socket_path, 1);
03425   return TRUE;
03426 #else /* DBUS_ENABLE_LAUNCHD */
03427   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03428                 "can't lookup socket from launchd; launchd support not compiled in");
03429   return FALSE;
03430 #endif
03431 }
03432 
03433 static dbus_bool_t
03434 _dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
03435 {
03436 #ifdef DBUS_ENABLE_LAUNCHD
03437   dbus_bool_t valid_socket;
03438   DBusString socket_path;
03439 
03440   if (!_dbus_string_init (&socket_path))
03441     {
03442       _DBUS_SET_OOM (error);
03443       return FALSE;
03444     }
03445 
03446   valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
03447 
03448   if (dbus_error_is_set(error))
03449     {
03450       _dbus_string_free(&socket_path);
03451       return FALSE;
03452     }
03453 
03454   if (!valid_socket)
03455     {
03456       dbus_set_error(error, "no socket path",
03457                 "launchd did not provide a socket path, "
03458                 "verify that org.freedesktop.dbus-session.plist is loaded!");
03459       _dbus_string_free(&socket_path);
03460       return FALSE;
03461     }
03462   if (!_dbus_string_append (address, "unix:path="))
03463     {
03464       _DBUS_SET_OOM (error);
03465       _dbus_string_free(&socket_path);
03466       return FALSE;
03467     }
03468   if (!_dbus_string_copy (&socket_path, 0, address,
03469                           _dbus_string_get_length (address)))
03470     {
03471       _DBUS_SET_OOM (error);
03472       _dbus_string_free(&socket_path);
03473       return FALSE;
03474     }
03475 
03476   _dbus_string_free(&socket_path);
03477   return TRUE;
03478 #else
03479   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03480                 "can't lookup session address from launchd; launchd support not compiled in");
03481   return FALSE;
03482 #endif
03483 }
03484 
03504 dbus_bool_t
03505 _dbus_lookup_session_address (dbus_bool_t *supported,
03506                               DBusString  *address,
03507                               DBusError   *error)
03508 {
03509 #ifdef DBUS_ENABLE_LAUNCHD
03510   *supported = TRUE;
03511   return _dbus_lookup_session_address_launchd (address, error);
03512 #else
03513   /* On non-Mac Unix platforms, if the session address isn't already
03514    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03515    * fall back to the autolaunch: global default; see
03516    * init_session_address in dbus/dbus-bus.c. */
03517   *supported = FALSE;
03518   return TRUE;
03519 #endif
03520 }
03521 
03539 dbus_bool_t
03540 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03541 {
03542   const char *xdg_data_home;
03543   const char *xdg_data_dirs;
03544   DBusString servicedir_path;
03545 
03546   if (!_dbus_string_init (&servicedir_path))
03547     return FALSE;
03548 
03549   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03550   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03551 
03552   if (xdg_data_dirs != NULL)
03553     {
03554       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03555         goto oom;
03556 
03557       if (!_dbus_string_append (&servicedir_path, ":"))
03558         goto oom;
03559     }
03560   else
03561     {
03562       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03563         goto oom;
03564     }
03565 
03566   /*
03567    * add configured datadir to defaults
03568    * this may be the same as an xdg dir
03569    * however the config parser should take
03570    * care of duplicates
03571    */
03572   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03573         goto oom;
03574 
03575   if (xdg_data_home != NULL)
03576     {
03577       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03578         goto oom;
03579     }
03580   else
03581     {
03582       const DBusString *homedir;
03583       DBusString local_share;
03584 
03585       if (!_dbus_homedir_from_current_process (&homedir))
03586         goto oom;
03587 
03588       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03589         goto oom;
03590 
03591       _dbus_string_init_const (&local_share, "/.local/share");
03592       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03593         goto oom;
03594     }
03595 
03596   if (!_dbus_split_paths_and_append (&servicedir_path,
03597                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03598                                      dirs))
03599     goto oom;
03600 
03601   _dbus_string_free (&servicedir_path);
03602   return TRUE;
03603 
03604  oom:
03605   _dbus_string_free (&servicedir_path);
03606   return FALSE;
03607 }
03608 
03609 
03628 dbus_bool_t
03629 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03630 {
03631   const char *xdg_data_dirs;
03632   DBusString servicedir_path;
03633 
03634   if (!_dbus_string_init (&servicedir_path))
03635     return FALSE;
03636 
03637   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03638 
03639   if (xdg_data_dirs != NULL)
03640     {
03641       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03642         goto oom;
03643 
03644       if (!_dbus_string_append (&servicedir_path, ":"))
03645         goto oom;
03646     }
03647   else
03648     {
03649       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03650         goto oom;
03651     }
03652 
03653   /*
03654    * add configured datadir to defaults
03655    * this may be the same as an xdg dir
03656    * however the config parser should take
03657    * care of duplicates
03658    */
03659   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03660         goto oom;
03661 
03662   if (!_dbus_split_paths_and_append (&servicedir_path,
03663                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03664                                      dirs))
03665     goto oom;
03666 
03667   _dbus_string_free (&servicedir_path);
03668   return TRUE;
03669 
03670  oom:
03671   _dbus_string_free (&servicedir_path);
03672   return FALSE;
03673 }
03674 
03683 dbus_bool_t
03684 _dbus_append_system_config_file (DBusString *str)
03685 {
03686   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03687 }
03688 
03695 dbus_bool_t
03696 _dbus_append_session_config_file (DBusString *str)
03697 {
03698   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03699 }
03700 
03708 void
03709 _dbus_flush_caches (void)
03710 {
03711   _dbus_user_database_flush_system ();
03712 }
03713 
03727 dbus_bool_t
03728 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03729                                                 DBusCredentials *credentials)
03730 {
03731   DBusString homedir;
03732   DBusString dotdir;
03733   dbus_uid_t uid;
03734 
03735   _dbus_assert (credentials != NULL);
03736   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03737 
03738   if (!_dbus_string_init (&homedir))
03739     return FALSE;
03740 
03741   uid = _dbus_credentials_get_unix_uid (credentials);
03742   _dbus_assert (uid != DBUS_UID_UNSET);
03743 
03744   if (!_dbus_homedir_from_uid (uid, &homedir))
03745     goto failed;
03746 
03747 #ifdef DBUS_BUILD_TESTS
03748   {
03749     const char *override;
03750 
03751     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03752     if (override != NULL && *override != '\0')
03753       {
03754         _dbus_string_set_length (&homedir, 0);
03755         if (!_dbus_string_append (&homedir, override))
03756           goto failed;
03757 
03758         _dbus_verbose ("Using fake homedir for testing: %s\n",
03759                        _dbus_string_get_const_data (&homedir));
03760       }
03761     else
03762       {
03763         static dbus_bool_t already_warned = FALSE;
03764         if (!already_warned)
03765           {
03766             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03767             already_warned = TRUE;
03768           }
03769       }
03770   }
03771 #endif
03772 
03773   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03774   if (!_dbus_concat_dir_and_file (&homedir,
03775                                   &dotdir))
03776     goto failed;
03777 
03778   if (!_dbus_string_copy (&homedir, 0,
03779                           directory, _dbus_string_get_length (directory))) {
03780     goto failed;
03781   }
03782 
03783   _dbus_string_free (&homedir);
03784   return TRUE;
03785 
03786  failed:
03787   _dbus_string_free (&homedir);
03788   return FALSE;
03789 }
03790 
03791 //PENDING(kdab) docs
03792 dbus_bool_t
03793 _dbus_daemon_publish_session_bus_address (const char* addr,
03794                                           const char *scope)
03795 {
03796   return TRUE;
03797 }
03798 
03799 //PENDING(kdab) docs
03800 void
03801 _dbus_daemon_unpublish_session_bus_address (void)
03802 {
03803 
03804 }
03805 
03812 dbus_bool_t
03813 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03814 {
03815   return errno == EAGAIN || errno == EWOULDBLOCK;
03816 }
03817 
03825 dbus_bool_t
03826 _dbus_delete_directory (const DBusString *filename,
03827                         DBusError        *error)
03828 {
03829   const char *filename_c;
03830 
03831   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03832 
03833   filename_c = _dbus_string_get_const_data (filename);
03834 
03835   if (rmdir (filename_c) != 0)
03836     {
03837       dbus_set_error (error, DBUS_ERROR_FAILED,
03838                       "Failed to remove directory %s: %s\n",
03839                       filename_c, _dbus_strerror (errno));
03840       return FALSE;
03841     }
03842 
03843   return TRUE;
03844 }
03845 
03853 dbus_bool_t
03854 _dbus_socket_can_pass_unix_fd(int fd) {
03855 
03856 #ifdef SCM_RIGHTS
03857   union {
03858     struct sockaddr sa;
03859     struct sockaddr_storage storage;
03860     struct sockaddr_un un;
03861   } sa_buf;
03862 
03863   socklen_t sa_len = sizeof(sa_buf);
03864 
03865   _DBUS_ZERO(sa_buf);
03866 
03867   if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
03868     return FALSE;
03869 
03870   return sa_buf.sa.sa_family == AF_UNIX;
03871 
03872 #else
03873   return FALSE;
03874 
03875 #endif
03876 }
03877 
03878 
03879 /*
03880  * replaces the term DBUS_PREFIX in configure_time_path by the
03881  * current dbus installation directory. On unix this function is a noop
03882  *
03883  * @param configure_time_path
03884  * @return real path
03885  */
03886 const char *
03887 _dbus_replace_install_prefix (const char *configure_time_path)
03888 {
03889   return configure_time_path;
03890 }
03891 
03892 /* tests in dbus-sysdeps-util.c */

Generated on Fri Jul 11 2014 20:41:56 for D-Bus by  doxygen 1.7.1