• 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 #ifdef 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 #ifdef 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 #ifdef 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   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01315     {
01316       dbus_set_error (error,
01317                       _dbus_error_from_errno (errno),
01318                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01319                       host ? host : "*", port, gai_strerror(res), res);
01320       return -1;
01321     }
01322 
01323   tmp = ai;
01324   while (tmp)
01325     {
01326       int fd = -1, *newlisten_fd;
01327       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01328         {
01329           _DBUS_ASSERT_ERROR_IS_SET(error);
01330           goto failed;
01331         }
01332       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01333 
01334       reuseaddr = 1;
01335       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01336         {
01337           _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01338                       host ? host : "*", port, _dbus_strerror (errno));
01339         }
01340 
01341       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01342         {
01343           saved_errno = errno;
01344           _dbus_close(fd, NULL);
01345           if (saved_errno == EADDRINUSE)
01346             {
01347               /* Depending on kernel policy, it may or may not
01348                  be neccessary to bind to both IPv4 & 6 addresses
01349                  so ignore EADDRINUSE here */
01350               tmp = tmp->ai_next;
01351               continue;
01352             }
01353           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01354                           "Failed to bind socket \"%s:%s\": %s",
01355                           host ? host : "*", port, _dbus_strerror (saved_errno));
01356           goto failed;
01357         }
01358 
01359       if (listen (fd, 30 /* backlog */) < 0)
01360         {
01361           saved_errno = errno;
01362           _dbus_close (fd, NULL);
01363           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01364                           "Failed to listen on socket \"%s:%s\": %s",
01365                           host ? host : "*", port, _dbus_strerror (saved_errno));
01366           goto failed;
01367         }
01368 
01369       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
01370       if (!newlisten_fd)
01371         {
01372           saved_errno = errno;
01373           _dbus_close (fd, NULL);
01374           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01375                           "Failed to allocate file handle array: %s",
01376                           _dbus_strerror (saved_errno));
01377           goto failed;
01378         }
01379       listen_fd = newlisten_fd;
01380       listen_fd[nlisten_fd] = fd;
01381       nlisten_fd++;
01382 
01383       if (!_dbus_string_get_length(retport))
01384         {
01385           /* If the user didn't specify a port, or used 0, then
01386              the kernel chooses a port. After the first address
01387              is bound to, we need to force all remaining addresses
01388              to use the same port */
01389           if (!port || !strcmp(port, "0"))
01390             {
01391               struct sockaddr_storage addr;
01392               socklen_t addrlen;
01393               char portbuf[50];
01394 
01395               addrlen = sizeof(addr);
01396               getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01397 
01398               if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
01399                                      portbuf, sizeof(portbuf),
01400                                      NI_NUMERICHOST)) != 0)
01401                 {
01402                   dbus_set_error (error, _dbus_error_from_errno (errno),
01403                                   "Failed to resolve port \"%s:%s\": %s (%s)",
01404                                   host ? host : "*", port, gai_strerror(res), res);
01405                   goto failed;
01406                 }
01407               if (!_dbus_string_append(retport, portbuf))
01408                 {
01409                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01410                   goto failed;
01411                 }
01412 
01413               /* Release current address list & redo lookup */
01414               port = _dbus_string_get_const_data(retport);
01415               freeaddrinfo(ai);
01416               goto redo_lookup_with_port;
01417             }
01418           else
01419             {
01420               if (!_dbus_string_append(retport, port))
01421                 {
01422                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01423                     goto failed;
01424                 }
01425             }
01426         }
01427 
01428       tmp = tmp->ai_next;
01429     }
01430   freeaddrinfo(ai);
01431   ai = NULL;
01432 
01433   if (!nlisten_fd)
01434     {
01435       errno = EADDRINUSE;
01436       dbus_set_error (error, _dbus_error_from_errno (errno),
01437                       "Failed to bind socket \"%s:%s\": %s",
01438                       host ? host : "*", port, _dbus_strerror (errno));
01439       return -1;
01440     }
01441 
01442   for (i = 0 ; i < nlisten_fd ; i++)
01443     {
01444       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01445         {
01446           goto failed;
01447         }
01448     }
01449 
01450   *fds_p = listen_fd;
01451 
01452   return nlisten_fd;
01453 
01454  failed:
01455   if (ai)
01456     freeaddrinfo(ai);
01457   for (i = 0 ; i < nlisten_fd ; i++)
01458     _dbus_close(listen_fd[i], NULL);
01459   dbus_free(listen_fd);
01460   return -1;
01461 }
01462 
01463 static dbus_bool_t
01464 write_credentials_byte (int             server_fd,
01465                         DBusError      *error)
01466 {
01467   int bytes_written;
01468   char buf[1] = { '\0' };
01469 #if defined(HAVE_CMSGCRED)
01470   union {
01471           struct cmsghdr hdr;
01472           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01473   } cmsg;
01474   struct iovec iov;
01475   struct msghdr msg;
01476   iov.iov_base = buf;
01477   iov.iov_len = 1;
01478 
01479   _DBUS_ZERO(msg);
01480   msg.msg_iov = &iov;
01481   msg.msg_iovlen = 1;
01482 
01483   msg.msg_control = (caddr_t) &cmsg;
01484   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01485   _DBUS_ZERO(cmsg);
01486   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01487   cmsg.hdr.cmsg_level = SOL_SOCKET;
01488   cmsg.hdr.cmsg_type = SCM_CREDS;
01489 #endif
01490 
01491   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01492 
01493  again:
01494 
01495 #if defined(HAVE_CMSGCRED)
01496   bytes_written = sendmsg (server_fd, &msg, 0);
01497 #else
01498   bytes_written = write (server_fd, buf, 1);
01499 #endif
01500 
01501   if (bytes_written < 0 && errno == EINTR)
01502     goto again;
01503 
01504   if (bytes_written < 0)
01505     {
01506       dbus_set_error (error, _dbus_error_from_errno (errno),
01507                       "Failed to write credentials byte: %s",
01508                      _dbus_strerror (errno));
01509       return FALSE;
01510     }
01511   else if (bytes_written == 0)
01512     {
01513       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01514                       "wrote zero bytes writing credentials byte");
01515       return FALSE;
01516     }
01517   else
01518     {
01519       _dbus_assert (bytes_written == 1);
01520       _dbus_verbose ("wrote credentials byte\n");
01521       return TRUE;
01522     }
01523 }
01524 
01546 dbus_bool_t
01547 _dbus_read_credentials_socket  (int              client_fd,
01548                                 DBusCredentials *credentials,
01549                                 DBusError       *error)
01550 {
01551   struct msghdr msg;
01552   struct iovec iov;
01553   char buf;
01554   dbus_uid_t uid_read;
01555   dbus_pid_t pid_read;
01556   int bytes_read;
01557 
01558 #ifdef HAVE_CMSGCRED
01559   union {
01560     struct cmsghdr hdr;
01561     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01562   } cmsg;
01563 
01564 #elif defined(LOCAL_CREDS)
01565   struct {
01566     struct cmsghdr hdr;
01567     struct sockcred cred;
01568   } cmsg;
01569 #endif
01570 
01571   uid_read = DBUS_UID_UNSET;
01572   pid_read = DBUS_PID_UNSET;
01573 
01574   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01575 
01576   /* The POSIX spec certainly doesn't promise this, but
01577    * we need these assertions to fail as soon as we're wrong about
01578    * it so we can do the porting fixups
01579    */
01580   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01581   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01582   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01583 
01584   _dbus_credentials_clear (credentials);
01585 
01586   /* Systems supporting LOCAL_CREDS are configured to have this feature
01587    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01588    * the connection.  Therefore, the received message must carry the
01589    * credentials information without doing anything special.
01590    */
01591 
01592   iov.iov_base = &buf;
01593   iov.iov_len = 1;
01594 
01595   _DBUS_ZERO(msg);
01596   msg.msg_iov = &iov;
01597   msg.msg_iovlen = 1;
01598 
01599 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01600   _DBUS_ZERO(cmsg);
01601   msg.msg_control = (caddr_t) &cmsg;
01602   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01603 #endif
01604 
01605  again:
01606   bytes_read = recvmsg (client_fd, &msg, 0);
01607 
01608   if (bytes_read < 0)
01609     {
01610       if (errno == EINTR)
01611         goto again;
01612 
01613       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01614        * normally only call read_credentials if the socket was ready
01615        * for reading
01616        */
01617 
01618       dbus_set_error (error, _dbus_error_from_errno (errno),
01619                       "Failed to read credentials byte: %s",
01620                       _dbus_strerror (errno));
01621       return FALSE;
01622     }
01623   else if (bytes_read == 0)
01624     {
01625       /* this should not happen unless we are using recvmsg wrong,
01626        * so is essentially here for paranoia
01627        */
01628       dbus_set_error (error, DBUS_ERROR_FAILED,
01629                       "Failed to read credentials byte (zero-length read)");
01630       return FALSE;
01631     }
01632   else if (buf != '\0')
01633     {
01634       dbus_set_error (error, DBUS_ERROR_FAILED,
01635                       "Credentials byte was not nul");
01636       return FALSE;
01637     }
01638 
01639 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01640   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01641                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01642     {
01643       dbus_set_error (error, DBUS_ERROR_FAILED,
01644                       "Message from recvmsg() was not SCM_CREDS");
01645       return FALSE;
01646     }
01647 #endif
01648 
01649   _dbus_verbose ("read credentials byte\n");
01650 
01651   {
01652 #ifdef SO_PEERCRED
01653     struct ucred cr;
01654     int cr_len = sizeof (cr);
01655 
01656     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01657         cr_len == sizeof (cr))
01658       {
01659         pid_read = cr.pid;
01660         uid_read = cr.uid;
01661       }
01662     else
01663       {
01664         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01665                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01666       }
01667 #elif defined(HAVE_CMSGCRED)
01668     struct cmsgcred *cred;
01669 
01670     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01671     pid_read = cred->cmcred_pid;
01672     uid_read = cred->cmcred_euid;
01673 #elif defined(LOCAL_CREDS)
01674     pid_read = DBUS_PID_UNSET;
01675     uid_read = cmsg.cred.sc_uid;
01676     /* Since we have already got the credentials from this socket, we can
01677      * disable its LOCAL_CREDS flag if it was ever set. */
01678     _dbus_set_local_creds (client_fd, FALSE);
01679 #elif defined(HAVE_GETPEEREID)
01680     uid_t euid;
01681     gid_t egid;
01682     if (getpeereid (client_fd, &euid, &egid) == 0)
01683       {
01684         uid_read = euid;
01685       }
01686     else
01687       {
01688         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01689       }
01690 #elif defined(HAVE_GETPEERUCRED)
01691     ucred_t * ucred = NULL;
01692     if (getpeerucred (client_fd, &ucred) == 0)
01693       {
01694         pid_read = ucred_getpid (ucred);
01695         uid_read = ucred_geteuid (ucred);
01696 #ifdef HAVE_ADT
01697         /* generate audit session data based on socket ucred */
01698         adt_session_data_t *adth = NULL;
01699         adt_export_data_t *data = NULL;
01700         size_t size = 0;
01701         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01702           {
01703             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01704           }
01705         else
01706           {
01707             if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01708               {
01709                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01710               }
01711             else
01712               {
01713                 size = adt_export_session_data (adth, &data);
01714                 if (size <= 0)
01715                   {
01716                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01717                   }
01718                 else
01719                   {
01720                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01721                     free (data);
01722                   }
01723               }
01724             (void) adt_end_session (adth);
01725           }
01726 #endif /* HAVE_ADT */
01727       }
01728     else
01729       {
01730         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01731       }
01732     if (ucred != NULL)
01733       ucred_free (ucred);
01734 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01735     _dbus_verbose ("Socket credentials not supported on this OS\n");
01736 #endif
01737   }
01738 
01739   _dbus_verbose ("Credentials:"
01740                  "  pid "DBUS_PID_FORMAT
01741                  "  uid "DBUS_UID_FORMAT
01742                  "\n",
01743                  pid_read,
01744                  uid_read);
01745 
01746   if (pid_read != DBUS_PID_UNSET)
01747     {
01748       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01749         {
01750           _DBUS_SET_OOM (error);
01751           return FALSE;
01752         }
01753     }
01754 
01755   if (uid_read != DBUS_UID_UNSET)
01756     {
01757       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01758         {
01759           _DBUS_SET_OOM (error);
01760           return FALSE;
01761         }
01762     }
01763 
01764   return TRUE;
01765 }
01766 
01784 dbus_bool_t
01785 _dbus_send_credentials_socket  (int              server_fd,
01786                                 DBusError       *error)
01787 {
01788   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01789 
01790   if (write_credentials_byte (server_fd, error))
01791     return TRUE;
01792   else
01793     return FALSE;
01794 }
01795 
01805 int
01806 _dbus_accept  (int listen_fd)
01807 {
01808   int client_fd;
01809   struct sockaddr addr;
01810   socklen_t addrlen;
01811 #ifdef HAVE_ACCEPT4
01812   dbus_bool_t cloexec_done;
01813 #endif
01814 
01815   addrlen = sizeof (addr);
01816 
01817  retry:
01818 
01819 #ifdef HAVE_ACCEPT4
01820   /* We assume that if accept4 is available SOCK_CLOEXEC is too */
01821   client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
01822   cloexec_done = client_fd >= 0;
01823 
01824   if (client_fd < 0 && errno == ENOSYS)
01825 #endif
01826     {
01827       client_fd = accept (listen_fd, &addr, &addrlen);
01828     }
01829 
01830   if (client_fd < 0)
01831     {
01832       if (errno == EINTR)
01833         goto retry;
01834     }
01835 
01836   _dbus_verbose ("client fd %d accepted\n", client_fd);
01837 
01838 #ifdef HAVE_ACCEPT4
01839   if (!cloexec_done)
01840 #endif
01841     {
01842       _dbus_fd_set_close_on_exec(client_fd);
01843     }
01844 
01845   return client_fd;
01846 }
01847 
01856 dbus_bool_t
01857 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01858 {
01859   const char *directory;
01860   struct stat sb;
01861 
01862   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01863 
01864   directory = _dbus_string_get_const_data (dir);
01865 
01866   if (stat (directory, &sb) < 0)
01867     {
01868       dbus_set_error (error, _dbus_error_from_errno (errno),
01869                       "%s", _dbus_strerror (errno));
01870 
01871       return FALSE;
01872     }
01873 
01874   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01875       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01876     {
01877       dbus_set_error (error, DBUS_ERROR_FAILED,
01878                      "%s directory is not private to the user", directory);
01879       return FALSE;
01880     }
01881 
01882   return TRUE;
01883 }
01884 
01885 static dbus_bool_t
01886 fill_user_info_from_passwd (struct passwd *p,
01887                             DBusUserInfo  *info,
01888                             DBusError     *error)
01889 {
01890   _dbus_assert (p->pw_name != NULL);
01891   _dbus_assert (p->pw_dir != NULL);
01892 
01893   info->uid = p->pw_uid;
01894   info->primary_gid = p->pw_gid;
01895   info->username = _dbus_strdup (p->pw_name);
01896   info->homedir = _dbus_strdup (p->pw_dir);
01897 
01898   if (info->username == NULL ||
01899       info->homedir == NULL)
01900     {
01901       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01902       return FALSE;
01903     }
01904 
01905   return TRUE;
01906 }
01907 
01908 static dbus_bool_t
01909 fill_user_info (DBusUserInfo       *info,
01910                 dbus_uid_t          uid,
01911                 const DBusString   *username,
01912                 DBusError          *error)
01913 {
01914   const char *username_c;
01915 
01916   /* exactly one of username/uid provided */
01917   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01918   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01919 
01920   info->uid = DBUS_UID_UNSET;
01921   info->primary_gid = DBUS_GID_UNSET;
01922   info->group_ids = NULL;
01923   info->n_group_ids = 0;
01924   info->username = NULL;
01925   info->homedir = NULL;
01926 
01927   if (username != NULL)
01928     username_c = _dbus_string_get_const_data (username);
01929   else
01930     username_c = NULL;
01931 
01932   /* For now assuming that the getpwnam() and getpwuid() flavors
01933    * are always symmetrical, if not we have to add more configure
01934    * checks
01935    */
01936 
01937 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01938   {
01939     struct passwd *p;
01940     int result;
01941     size_t buflen;
01942     char *buf;
01943     struct passwd p_str;
01944 
01945     /* retrieve maximum needed size for buf */
01946     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01947 
01948     /* sysconf actually returns a long, but everything else expects size_t,
01949      * so just recast here.
01950      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
01951      */
01952     if ((long) buflen <= 0)
01953       buflen = 1024;
01954 
01955     result = -1;
01956     while (1)
01957       {
01958         buf = dbus_malloc (buflen);
01959         if (buf == NULL)
01960           {
01961             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01962             return FALSE;
01963           }
01964 
01965         p = NULL;
01966 #ifdef HAVE_POSIX_GETPWNAM_R
01967         if (uid != DBUS_UID_UNSET)
01968           result = getpwuid_r (uid, &p_str, buf, buflen,
01969                                &p);
01970         else
01971           result = getpwnam_r (username_c, &p_str, buf, buflen,
01972                                &p);
01973 #else
01974         if (uid != DBUS_UID_UNSET)
01975           p = getpwuid_r (uid, &p_str, buf, buflen);
01976         else
01977           p = getpwnam_r (username_c, &p_str, buf, buflen);
01978         result = 0;
01979 #endif /* !HAVE_POSIX_GETPWNAM_R */
01980         //Try a bigger buffer if ERANGE was returned
01981         if (result == ERANGE && buflen < 512 * 1024)
01982           {
01983             dbus_free (buf);
01984             buflen *= 2;
01985           }
01986         else
01987           {
01988             break;
01989           }
01990       }
01991     if (result == 0 && p == &p_str)
01992       {
01993         if (!fill_user_info_from_passwd (p, info, error))
01994           {
01995             dbus_free (buf);
01996             return FALSE;
01997           }
01998         dbus_free (buf);
01999       }
02000     else
02001       {
02002         dbus_set_error (error, _dbus_error_from_errno (errno),
02003                         "User \"%s\" unknown or no memory to allocate password entry\n",
02004                         username_c ? username_c : "???");
02005         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02006         dbus_free (buf);
02007         return FALSE;
02008       }
02009   }
02010 #else /* ! HAVE_GETPWNAM_R */
02011   {
02012     /* I guess we're screwed on thread safety here */
02013     struct passwd *p;
02014 
02015     if (uid != DBUS_UID_UNSET)
02016       p = getpwuid (uid);
02017     else
02018       p = getpwnam (username_c);
02019 
02020     if (p != NULL)
02021       {
02022         if (!fill_user_info_from_passwd (p, info, error))
02023           {
02024             return FALSE;
02025           }
02026       }
02027     else
02028       {
02029         dbus_set_error (error, _dbus_error_from_errno (errno),
02030                         "User \"%s\" unknown or no memory to allocate password entry\n",
02031                         username_c ? username_c : "???");
02032         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02033         return FALSE;
02034       }
02035   }
02036 #endif  /* ! HAVE_GETPWNAM_R */
02037 
02038   /* Fill this in so we can use it to get groups */
02039   username_c = info->username;
02040 
02041 #ifdef HAVE_GETGROUPLIST
02042   {
02043     gid_t *buf;
02044     int buf_count;
02045     int i;
02046     int initial_buf_count;
02047 
02048     initial_buf_count = 17;
02049     buf_count = initial_buf_count;
02050     buf = dbus_new (gid_t, buf_count);
02051     if (buf == NULL)
02052       {
02053         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02054         goto failed;
02055       }
02056 
02057     if (getgrouplist (username_c,
02058                       info->primary_gid,
02059                       buf, &buf_count) < 0)
02060       {
02061         gid_t *new;
02062         /* Presumed cause of negative return code: buf has insufficient
02063            entries to hold the entire group list. The Linux behavior in this
02064            case is to pass back the actual number of groups in buf_count, but
02065            on Mac OS X 10.5, buf_count is unhelpfully left alone.
02066            So as a hack, try to help out a bit by guessing a larger
02067            number of groups, within reason.. might still fail, of course,
02068            but we can at least print a more informative message.  I looked up
02069            the "right way" to do this by downloading Apple's own source code
02070            for the "id" command, and it turns out that they use an
02071            undocumented library function getgrouplist_2 (!) which is not
02072            declared in any header in /usr/include (!!). That did not seem
02073            like the way to go here.
02074         */
02075         if (buf_count == initial_buf_count)
02076           {
02077             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
02078           }
02079         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02080         if (new == NULL)
02081           {
02082             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02083             dbus_free (buf);
02084             goto failed;
02085           }
02086 
02087         buf = new;
02088 
02089         errno = 0;
02090         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02091           {
02092             if (errno == 0)
02093               {
02094                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02095                             username_c, buf_count, buf_count);
02096               }
02097             else
02098               {
02099                 dbus_set_error (error,
02100                                 _dbus_error_from_errno (errno),
02101                                 "Failed to get groups for username \"%s\" primary GID "
02102                                 DBUS_GID_FORMAT ": %s\n",
02103                                 username_c, info->primary_gid,
02104                                 _dbus_strerror (errno));
02105                 dbus_free (buf);
02106                 goto failed;
02107               }
02108           }
02109       }
02110 
02111     info->group_ids = dbus_new (dbus_gid_t, buf_count);
02112     if (info->group_ids == NULL)
02113       {
02114         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02115         dbus_free (buf);
02116         goto failed;
02117       }
02118 
02119     for (i = 0; i < buf_count; ++i)
02120       info->group_ids[i] = buf[i];
02121 
02122     info->n_group_ids = buf_count;
02123 
02124     dbus_free (buf);
02125   }
02126 #else  /* HAVE_GETGROUPLIST */
02127   {
02128     /* We just get the one group ID */
02129     info->group_ids = dbus_new (dbus_gid_t, 1);
02130     if (info->group_ids == NULL)
02131       {
02132         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02133         goto failed;
02134       }
02135 
02136     info->n_group_ids = 1;
02137 
02138     (info->group_ids)[0] = info->primary_gid;
02139   }
02140 #endif /* HAVE_GETGROUPLIST */
02141 
02142   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02143 
02144   return TRUE;
02145 
02146  failed:
02147   _DBUS_ASSERT_ERROR_IS_SET (error);
02148   return FALSE;
02149 }
02150 
02159 dbus_bool_t
02160 _dbus_user_info_fill (DBusUserInfo     *info,
02161                       const DBusString *username,
02162                       DBusError        *error)
02163 {
02164   return fill_user_info (info, DBUS_UID_UNSET,
02165                          username, error);
02166 }
02167 
02176 dbus_bool_t
02177 _dbus_user_info_fill_uid (DBusUserInfo *info,
02178                           dbus_uid_t    uid,
02179                           DBusError    *error)
02180 {
02181   return fill_user_info (info, uid,
02182                          NULL, error);
02183 }
02184 
02192 dbus_bool_t
02193 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02194 {
02195   /* The POSIX spec certainly doesn't promise this, but
02196    * we need these assertions to fail as soon as we're wrong about
02197    * it so we can do the porting fixups
02198    */
02199   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
02200   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
02201   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
02202 
02203   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
02204     return FALSE;
02205   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02206     return FALSE;
02207 
02208   return TRUE;
02209 }
02210 
02222 dbus_bool_t
02223 _dbus_append_user_from_current_process (DBusString *str)
02224 {
02225   return _dbus_string_append_uint (str,
02226                                    _dbus_geteuid ());
02227 }
02228 
02233 dbus_pid_t
02234 _dbus_getpid (void)
02235 {
02236   return getpid ();
02237 }
02238 
02242 dbus_uid_t
02243 _dbus_getuid (void)
02244 {
02245   return getuid ();
02246 }
02247 
02251 dbus_uid_t
02252 _dbus_geteuid (void)
02253 {
02254   return geteuid ();
02255 }
02256 
02263 unsigned long
02264 _dbus_pid_for_log (void)
02265 {
02266   return getpid ();
02267 }
02268 
02276 dbus_bool_t
02277 _dbus_parse_uid (const DBusString      *uid_str,
02278                  dbus_uid_t            *uid)
02279 {
02280   int end;
02281   long val;
02282 
02283   if (_dbus_string_get_length (uid_str) == 0)
02284     {
02285       _dbus_verbose ("UID string was zero length\n");
02286       return FALSE;
02287     }
02288 
02289   val = -1;
02290   end = 0;
02291   if (!_dbus_string_parse_int (uid_str, 0, &val,
02292                                &end))
02293     {
02294       _dbus_verbose ("could not parse string as a UID\n");
02295       return FALSE;
02296     }
02297 
02298   if (end != _dbus_string_get_length (uid_str))
02299     {
02300       _dbus_verbose ("string contained trailing stuff after UID\n");
02301       return FALSE;
02302     }
02303 
02304   *uid = val;
02305 
02306   return TRUE;
02307 }
02308 
02309 #if !DBUS_USE_SYNC
02310 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
02311 #endif
02312 
02319 dbus_int32_t
02320 _dbus_atomic_inc (DBusAtomic *atomic)
02321 {
02322 #if DBUS_USE_SYNC
02323   return __sync_add_and_fetch(&atomic->value, 1)-1;
02324 #else
02325   dbus_int32_t res;
02326   _DBUS_LOCK (atomic);
02327   res = atomic->value;
02328   atomic->value += 1;
02329   _DBUS_UNLOCK (atomic);
02330   return res;
02331 #endif
02332 }
02333 
02340 dbus_int32_t
02341 _dbus_atomic_dec (DBusAtomic *atomic)
02342 {
02343 #if DBUS_USE_SYNC
02344   return __sync_sub_and_fetch(&atomic->value, 1)+1;
02345 #else
02346   dbus_int32_t res;
02347 
02348   _DBUS_LOCK (atomic);
02349   res = atomic->value;
02350   atomic->value -= 1;
02351   _DBUS_UNLOCK (atomic);
02352   return res;
02353 #endif
02354 }
02355 
02356 #ifdef DBUS_BUILD_TESTS
02357 
02360 dbus_gid_t
02361 _dbus_getgid (void)
02362 {
02363   return getgid ();
02364 }
02365 #endif
02366 
02375 int
02376 _dbus_poll (DBusPollFD *fds,
02377             int         n_fds,
02378             int         timeout_milliseconds)
02379 {
02380 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02381   /* This big thing is a constant expression and should get optimized
02382    * out of existence. So it's more robust than a configure check at
02383    * no cost.
02384    */
02385   if (_DBUS_POLLIN == POLLIN &&
02386       _DBUS_POLLPRI == POLLPRI &&
02387       _DBUS_POLLOUT == POLLOUT &&
02388       _DBUS_POLLERR == POLLERR &&
02389       _DBUS_POLLHUP == POLLHUP &&
02390       _DBUS_POLLNVAL == POLLNVAL &&
02391       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
02392       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
02393       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
02394       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
02395       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
02396       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
02397       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
02398     {
02399       return poll ((struct pollfd*) fds,
02400                    n_fds,
02401                    timeout_milliseconds);
02402     }
02403   else
02404     {
02405       /* We have to convert the DBusPollFD to an array of
02406        * struct pollfd, poll, and convert back.
02407        */
02408       _dbus_warn ("didn't implement poll() properly for this system yet\n");
02409       return -1;
02410     }
02411 #else /* ! HAVE_POLL */
02412 
02413   fd_set read_set, write_set, err_set;
02414   int max_fd = 0;
02415   int i;
02416   struct timeval tv;
02417   int ready;
02418 
02419   FD_ZERO (&read_set);
02420   FD_ZERO (&write_set);
02421   FD_ZERO (&err_set);
02422 
02423   for (i = 0; i < n_fds; i++)
02424     {
02425       DBusPollFD *fdp = &fds[i];
02426 
02427       if (fdp->events & _DBUS_POLLIN)
02428         FD_SET (fdp->fd, &read_set);
02429 
02430       if (fdp->events & _DBUS_POLLOUT)
02431         FD_SET (fdp->fd, &write_set);
02432 
02433       FD_SET (fdp->fd, &err_set);
02434 
02435       max_fd = MAX (max_fd, fdp->fd);
02436     }
02437 
02438   tv.tv_sec = timeout_milliseconds / 1000;
02439   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02440 
02441   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02442                   timeout_milliseconds < 0 ? NULL : &tv);
02443 
02444   if (ready > 0)
02445     {
02446       for (i = 0; i < n_fds; i++)
02447         {
02448           DBusPollFD *fdp = &fds[i];
02449 
02450           fdp->revents = 0;
02451 
02452           if (FD_ISSET (fdp->fd, &read_set))
02453             fdp->revents |= _DBUS_POLLIN;
02454 
02455           if (FD_ISSET (fdp->fd, &write_set))
02456             fdp->revents |= _DBUS_POLLOUT;
02457 
02458           if (FD_ISSET (fdp->fd, &err_set))
02459             fdp->revents |= _DBUS_POLLERR;
02460         }
02461     }
02462 
02463   return ready;
02464 #endif
02465 }
02466 
02474 void
02475 _dbus_get_current_time (long *tv_sec,
02476                         long *tv_usec)
02477 {
02478   struct timeval t;
02479 
02480 #ifdef HAVE_MONOTONIC_CLOCK
02481   struct timespec ts;
02482   clock_gettime (CLOCK_MONOTONIC, &ts);
02483 
02484   if (tv_sec)
02485     *tv_sec = ts.tv_sec;
02486   if (tv_usec)
02487     *tv_usec = ts.tv_nsec / 1000;
02488 #else
02489   gettimeofday (&t, NULL);
02490 
02491   if (tv_sec)
02492     *tv_sec = t.tv_sec;
02493   if (tv_usec)
02494     *tv_usec = t.tv_usec;
02495 #endif
02496 }
02497 
02506 dbus_bool_t
02507 _dbus_create_directory (const DBusString *filename,
02508                         DBusError        *error)
02509 {
02510   const char *filename_c;
02511 
02512   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02513 
02514   filename_c = _dbus_string_get_const_data (filename);
02515 
02516   if (mkdir (filename_c, 0700) < 0)
02517     {
02518       if (errno == EEXIST)
02519         return TRUE;
02520 
02521       dbus_set_error (error, DBUS_ERROR_FAILED,
02522                       "Failed to create directory %s: %s\n",
02523                       filename_c, _dbus_strerror (errno));
02524       return FALSE;
02525     }
02526   else
02527     return TRUE;
02528 }
02529 
02540 dbus_bool_t
02541 _dbus_concat_dir_and_file (DBusString       *dir,
02542                            const DBusString *next_component)
02543 {
02544   dbus_bool_t dir_ends_in_slash;
02545   dbus_bool_t file_starts_with_slash;
02546 
02547   if (_dbus_string_get_length (dir) == 0 ||
02548       _dbus_string_get_length (next_component) == 0)
02549     return TRUE;
02550 
02551   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02552                                                     _dbus_string_get_length (dir) - 1);
02553 
02554   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02555 
02556   if (dir_ends_in_slash && file_starts_with_slash)
02557     {
02558       _dbus_string_shorten (dir, 1);
02559     }
02560   else if (!(dir_ends_in_slash || file_starts_with_slash))
02561     {
02562       if (!_dbus_string_append_byte (dir, '/'))
02563         return FALSE;
02564     }
02565 
02566   return _dbus_string_copy (next_component, 0, dir,
02567                             _dbus_string_get_length (dir));
02568 }
02569 
02571 #define NANOSECONDS_PER_SECOND       1000000000
02572 
02573 #define MICROSECONDS_PER_SECOND      1000000
02574 
02575 #define MILLISECONDS_PER_SECOND      1000
02576 
02577 #define NANOSECONDS_PER_MILLISECOND  1000000
02578 
02579 #define MICROSECONDS_PER_MILLISECOND 1000
02580 
02585 void
02586 _dbus_sleep_milliseconds (int milliseconds)
02587 {
02588 #ifdef HAVE_NANOSLEEP
02589   struct timespec req;
02590   struct timespec rem;
02591 
02592   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02593   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02594   rem.tv_sec = 0;
02595   rem.tv_nsec = 0;
02596 
02597   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02598     req = rem;
02599 #elif defined (HAVE_USLEEP)
02600   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02601 #else /* ! HAVE_USLEEP */
02602   sleep (MAX (milliseconds / 1000, 1));
02603 #endif
02604 }
02605 
02606 static dbus_bool_t
02607 _dbus_generate_pseudorandom_bytes (DBusString *str,
02608                                    int         n_bytes)
02609 {
02610   int old_len;
02611   char *p;
02612 
02613   old_len = _dbus_string_get_length (str);
02614 
02615   if (!_dbus_string_lengthen (str, n_bytes))
02616     return FALSE;
02617 
02618   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02619 
02620   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02621 
02622   return TRUE;
02623 }
02624 
02633 dbus_bool_t
02634 _dbus_generate_random_bytes (DBusString *str,
02635                              int         n_bytes)
02636 {
02637   int old_len;
02638   int fd;
02639 
02640   /* FALSE return means "no memory", if it could
02641    * mean something else then we'd need to return
02642    * a DBusError. So we always fall back to pseudorandom
02643    * if the I/O fails.
02644    */
02645 
02646   old_len = _dbus_string_get_length (str);
02647   fd = -1;
02648 
02649   /* note, urandom on linux will fall back to pseudorandom */
02650   fd = open ("/dev/urandom", O_RDONLY);
02651   if (fd < 0)
02652     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02653 
02654   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02655 
02656   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02657     {
02658       _dbus_close (fd, NULL);
02659       _dbus_string_set_length (str, old_len);
02660       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02661     }
02662 
02663   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02664                  n_bytes);
02665 
02666   _dbus_close (fd, NULL);
02667 
02668   return TRUE;
02669 }
02670 
02676 void
02677 _dbus_exit (int code)
02678 {
02679   _exit (code);
02680 }
02681 
02690 const char*
02691 _dbus_strerror (int error_number)
02692 {
02693   const char *msg;
02694 
02695   msg = strerror (error_number);
02696   if (msg == NULL)
02697     msg = "unknown";
02698 
02699   return msg;
02700 }
02701 
02705 void
02706 _dbus_disable_sigpipe (void)
02707 {
02708   signal (SIGPIPE, SIG_IGN);
02709 }
02710 
02718 void
02719 _dbus_fd_set_close_on_exec (intptr_t fd)
02720 {
02721   int val;
02722 
02723   val = fcntl (fd, F_GETFD, 0);
02724 
02725   if (val < 0)
02726     return;
02727 
02728   val |= FD_CLOEXEC;
02729 
02730   fcntl (fd, F_SETFD, val);
02731 }
02732 
02740 dbus_bool_t
02741 _dbus_close (int        fd,
02742              DBusError *error)
02743 {
02744   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02745 
02746  again:
02747   if (close (fd) < 0)
02748     {
02749       if (errno == EINTR)
02750         goto again;
02751 
02752       dbus_set_error (error, _dbus_error_from_errno (errno),
02753                       "Could not close fd %d", fd);
02754       return FALSE;
02755     }
02756 
02757   return TRUE;
02758 }
02759 
02767 int
02768 _dbus_dup(int        fd,
02769           DBusError *error)
02770 {
02771   int new_fd;
02772 
02773 #ifdef F_DUPFD_CLOEXEC
02774   dbus_bool_t cloexec_done;
02775 
02776   new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
02777   cloexec_done = new_fd >= 0;
02778 
02779   if (new_fd < 0 && errno == EINVAL)
02780 #endif
02781     {
02782       new_fd = fcntl(fd, F_DUPFD, 3);
02783     }
02784 
02785   if (new_fd < 0) {
02786 
02787     dbus_set_error (error, _dbus_error_from_errno (errno),
02788                     "Could not duplicate fd %d", fd);
02789     return -1;
02790   }
02791 
02792 #ifdef F_DUPFD_CLOEXEC
02793   if (!cloexec_done)
02794 #endif
02795     {
02796       _dbus_fd_set_close_on_exec(new_fd);
02797     }
02798 
02799   return new_fd;
02800 }
02801 
02809 dbus_bool_t
02810 _dbus_set_fd_nonblocking (int             fd,
02811                           DBusError      *error)
02812 {
02813   int val;
02814 
02815   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02816 
02817   val = fcntl (fd, F_GETFL, 0);
02818   if (val < 0)
02819     {
02820       dbus_set_error (error, _dbus_error_from_errno (errno),
02821                       "Failed to get flags from file descriptor %d: %s",
02822                       fd, _dbus_strerror (errno));
02823       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02824                      _dbus_strerror (errno));
02825       return FALSE;
02826     }
02827 
02828   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02829     {
02830       dbus_set_error (error, _dbus_error_from_errno (errno),
02831                       "Failed to set nonblocking flag of file descriptor %d: %s",
02832                       fd, _dbus_strerror (errno));
02833       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02834                      fd, _dbus_strerror (errno));
02835 
02836       return FALSE;
02837     }
02838 
02839   return TRUE;
02840 }
02841 
02847 void
02848 _dbus_print_backtrace (void)
02849 {
02850 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02851   void *bt[500];
02852   int bt_size;
02853   int i;
02854   char **syms;
02855 
02856   bt_size = backtrace (bt, 500);
02857 
02858   syms = backtrace_symbols (bt, bt_size);
02859 
02860   i = 0;
02861   while (i < bt_size)
02862     {
02863       /* don't use dbus_warn since it can _dbus_abort() */
02864       fprintf (stderr, "  %s\n", syms[i]);
02865       ++i;
02866     }
02867   fflush (stderr);
02868 
02869   free (syms);
02870 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02871   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02872 #else
02873   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02874 #endif
02875 }
02876 
02894 dbus_bool_t
02895 _dbus_full_duplex_pipe (int        *fd1,
02896                         int        *fd2,
02897                         dbus_bool_t blocking,
02898                         DBusError  *error)
02899 {
02900 #ifdef HAVE_SOCKETPAIR
02901   int fds[2];
02902   int retval;
02903 
02904 #ifdef SOCK_CLOEXEC
02905   dbus_bool_t cloexec_done;
02906 
02907   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
02908   cloexec_done = retval >= 0;
02909 
02910   if (retval < 0 && errno == EINVAL)
02911 #endif
02912     {
02913       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
02914     }
02915 
02916   if (retval < 0)
02917     {
02918       dbus_set_error (error, _dbus_error_from_errno (errno),
02919                       "Could not create full-duplex pipe");
02920       return FALSE;
02921     }
02922 
02923   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02924 
02925 #ifdef SOCK_CLOEXEC
02926   if (!cloexec_done)
02927 #endif
02928     {
02929       _dbus_fd_set_close_on_exec (fds[0]);
02930       _dbus_fd_set_close_on_exec (fds[1]);
02931     }
02932 
02933   if (!blocking &&
02934       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02935        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02936     {
02937       dbus_set_error (error, _dbus_error_from_errno (errno),
02938                       "Could not set full-duplex pipe nonblocking");
02939 
02940       _dbus_close (fds[0], NULL);
02941       _dbus_close (fds[1], NULL);
02942 
02943       return FALSE;
02944     }
02945 
02946   *fd1 = fds[0];
02947   *fd2 = fds[1];
02948 
02949   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02950                  *fd1, *fd2);
02951 
02952   return TRUE;
02953 #else
02954   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02955   dbus_set_error (error, DBUS_ERROR_FAILED,
02956                   "_dbus_full_duplex_pipe() not implemented on this OS");
02957   return FALSE;
02958 #endif
02959 }
02960 
02969 int
02970 _dbus_printf_string_upper_bound (const char *format,
02971                                  va_list     args)
02972 {
02973   char c;
02974   return vsnprintf (&c, 1, format, args);
02975 }
02976 
02983 const char*
02984 _dbus_get_tmpdir(void)
02985 {
02986   static const char* tmpdir = NULL;
02987 
02988   if (tmpdir == NULL)
02989     {
02990       /* TMPDIR is what glibc uses, then
02991        * glibc falls back to the P_tmpdir macro which
02992        * just expands to "/tmp"
02993        */
02994       if (tmpdir == NULL)
02995         tmpdir = getenv("TMPDIR");
02996 
02997       /* These two env variables are probably
02998        * broken, but maybe some OS uses them?
02999        */
03000       if (tmpdir == NULL)
03001         tmpdir = getenv("TMP");
03002       if (tmpdir == NULL)
03003         tmpdir = getenv("TEMP");
03004 
03005       /* And this is the sane fallback. */
03006       if (tmpdir == NULL)
03007         tmpdir = "/tmp";
03008     }
03009 
03010   _dbus_assert(tmpdir != NULL);
03011 
03012   return tmpdir;
03013 }
03014 
03034 static dbus_bool_t
03035 _read_subprocess_line_argv (const char *progpath,
03036                             dbus_bool_t path_fallback,
03037                             char       * const *argv,
03038                             DBusString *result,
03039                             DBusError  *error)
03040 {
03041   int result_pipe[2] = { -1, -1 };
03042   int errors_pipe[2] = { -1, -1 };
03043   pid_t pid;
03044   int ret;
03045   int status;
03046   int orig_len;
03047   int i;
03048 
03049   dbus_bool_t retval;
03050   sigset_t new_set, old_set;
03051 
03052   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03053   retval = FALSE;
03054 
03055   /* We need to block any existing handlers for SIGCHLD temporarily; they
03056    * will cause waitpid() below to fail.
03057    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
03058    */
03059   sigemptyset (&new_set);
03060   sigaddset (&new_set, SIGCHLD);
03061   sigprocmask (SIG_BLOCK, &new_set, &old_set);
03062 
03063   orig_len = _dbus_string_get_length (result);
03064 
03065 #define READ_END        0
03066 #define WRITE_END       1
03067   if (pipe (result_pipe) < 0)
03068     {
03069       dbus_set_error (error, _dbus_error_from_errno (errno),
03070                       "Failed to create a pipe to call %s: %s",
03071                       progpath, _dbus_strerror (errno));
03072       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03073                      progpath, _dbus_strerror (errno));
03074       goto out;
03075     }
03076   if (pipe (errors_pipe) < 0)
03077     {
03078       dbus_set_error (error, _dbus_error_from_errno (errno),
03079                       "Failed to create a pipe to call %s: %s",
03080                       progpath, _dbus_strerror (errno));
03081       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03082                      progpath, _dbus_strerror (errno));
03083       goto out;
03084     }
03085 
03086   pid = fork ();
03087   if (pid < 0)
03088     {
03089       dbus_set_error (error, _dbus_error_from_errno (errno),
03090                       "Failed to fork() to call %s: %s",
03091                       progpath, _dbus_strerror (errno));
03092       _dbus_verbose ("Failed to fork() to call %s: %s\n",
03093                      progpath, _dbus_strerror (errno));
03094       goto out;
03095     }
03096 
03097   if (pid == 0)
03098     {
03099       /* child process */
03100       int maxfds;
03101       int fd;
03102 
03103       fd = open ("/dev/null", O_RDWR);
03104       if (fd == -1)
03105         /* huh?! can't open /dev/null? */
03106         _exit (1);
03107 
03108       _dbus_verbose ("/dev/null fd %d opened\n", fd);
03109 
03110       /* set-up stdXXX */
03111       close (result_pipe[READ_END]);
03112       close (errors_pipe[READ_END]);
03113       close (0);                /* close stdin */
03114       close (1);                /* close stdout */
03115       close (2);                /* close stderr */
03116 
03117       if (dup2 (fd, 0) == -1)
03118         _exit (1);
03119       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03120         _exit (1);
03121       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03122         _exit (1);
03123 
03124       maxfds = sysconf (_SC_OPEN_MAX);
03125       /* Pick something reasonable if for some reason sysconf
03126        * says unlimited.
03127        */
03128       if (maxfds < 0)
03129         maxfds = 1024;
03130       /* close all inherited fds */
03131       for (i = 3; i < maxfds; i++)
03132         close (i);
03133 
03134       sigprocmask (SIG_SETMASK, &old_set, NULL);
03135 
03136       /* If it looks fully-qualified, try execv first */
03137       if (progpath[0] == '/')
03138         {
03139           execv (progpath, argv);
03140           /* Ok, that failed.  Now if path_fallback is given, let's
03141            * try unqualified.  This is mostly a hack to work
03142            * around systems which ship dbus-launch in /usr/bin
03143            * but everything else in /bin (because dbus-launch
03144            * depends on X11).
03145            */
03146           if (path_fallback)
03147             /* We must have a slash, because we checked above */
03148             execvp (strrchr (progpath, '/')+1, argv);
03149         }
03150       else
03151         execvp (progpath, argv);
03152 
03153       /* still nothing, we failed */
03154       _exit (1);
03155     }
03156 
03157   /* parent process */
03158   close (result_pipe[WRITE_END]);
03159   close (errors_pipe[WRITE_END]);
03160   result_pipe[WRITE_END] = -1;
03161   errors_pipe[WRITE_END] = -1;
03162 
03163   ret = 0;
03164   do
03165     {
03166       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03167     }
03168   while (ret > 0);
03169 
03170   /* reap the child process to avoid it lingering as zombie */
03171   do
03172     {
03173       ret = waitpid (pid, &status, 0);
03174     }
03175   while (ret == -1 && errno == EINTR);
03176 
03177   /* We succeeded if the process exited with status 0 and
03178      anything was read */
03179   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03180     {
03181       /* The process ended with error */
03182       DBusString error_message;
03183       _dbus_string_init (&error_message);
03184       ret = 0;
03185       do
03186         {
03187           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03188         }
03189       while (ret > 0);
03190 
03191       _dbus_string_set_length (result, orig_len);
03192       if (_dbus_string_get_length (&error_message) > 0)
03193         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03194                         "%s terminated abnormally with the following error: %s",
03195                         progpath, _dbus_string_get_data (&error_message));
03196       else
03197         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03198                         "%s terminated abnormally without any error message",
03199                         progpath);
03200       goto out;
03201     }
03202 
03203   retval = TRUE;
03204 
03205  out:
03206   sigprocmask (SIG_SETMASK, &old_set, NULL);
03207 
03208   if (retval)
03209     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03210   else
03211     _DBUS_ASSERT_ERROR_IS_SET (error);
03212 
03213   if (result_pipe[0] != -1)
03214     close (result_pipe[0]);
03215   if (result_pipe[1] != -1)
03216     close (result_pipe[1]);
03217   if (errors_pipe[0] != -1)
03218     close (errors_pipe[0]);
03219   if (errors_pipe[1] != -1)
03220     close (errors_pipe[1]);
03221 
03222   return retval;
03223 }
03224 
03236 dbus_bool_t
03237 _dbus_get_autolaunch_address (DBusString *address,
03238                               DBusError  *error)
03239 {
03240   static char *argv[6];
03241   int i;
03242   DBusString uuid;
03243   dbus_bool_t retval;
03244 
03245   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03246   retval = FALSE;
03247 
03248   if (!_dbus_string_init (&uuid))
03249     {
03250       _DBUS_SET_OOM (error);
03251       return FALSE;
03252     }
03253 
03254   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03255     {
03256       _DBUS_SET_OOM (error);
03257       goto out;
03258     }
03259 
03260   i = 0;
03261   argv[i] = "dbus-launch";
03262   ++i;
03263   argv[i] = "--autolaunch";
03264   ++i;
03265   argv[i] = _dbus_string_get_data (&uuid);
03266   ++i;
03267   argv[i] = "--binary-syntax";
03268   ++i;
03269   argv[i] = "--close-stderr";
03270   ++i;
03271   argv[i] = NULL;
03272   ++i;
03273 
03274   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03275 
03276   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03277                                        TRUE,
03278                                        argv, address, error);
03279 
03280  out:
03281   _dbus_string_free (&uuid);
03282   return retval;
03283 }
03284 
03303 dbus_bool_t
03304 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03305                                dbus_bool_t create_if_not_found,
03306                                DBusError  *error)
03307 {
03308   DBusString filename;
03309   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03310   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03311 }
03312 
03313 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03314 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03315 
03335 dbus_bool_t
03336 _dbus_lookup_session_address (dbus_bool_t *supported,
03337                               DBusString  *address,
03338                               DBusError   *error)
03339 {
03340   /* On non-Mac Unix platforms, if the session address isn't already
03341    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03342    * fall back to the autolaunch: global default; see
03343    * init_session_address in dbus/dbus-bus.c. */
03344   *supported = FALSE;
03345   return TRUE;
03346 }
03347 
03365 dbus_bool_t
03366 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03367 {
03368   const char *xdg_data_home;
03369   const char *xdg_data_dirs;
03370   DBusString servicedir_path;
03371 
03372   if (!_dbus_string_init (&servicedir_path))
03373     return FALSE;
03374 
03375   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03376   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03377 
03378   if (xdg_data_dirs != NULL)
03379     {
03380       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03381         goto oom;
03382 
03383       if (!_dbus_string_append (&servicedir_path, ":"))
03384         goto oom;
03385     }
03386   else
03387     {
03388       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03389         goto oom;
03390     }
03391 
03392   /*
03393    * add configured datadir to defaults
03394    * this may be the same as an xdg dir
03395    * however the config parser should take
03396    * care of duplicates
03397    */
03398   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03399         goto oom;
03400 
03401   if (xdg_data_home != NULL)
03402     {
03403       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03404         goto oom;
03405     }
03406   else
03407     {
03408       const DBusString *homedir;
03409       DBusString local_share;
03410 
03411       if (!_dbus_homedir_from_current_process (&homedir))
03412         goto oom;
03413 
03414       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03415         goto oom;
03416 
03417       _dbus_string_init_const (&local_share, "/.local/share");
03418       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03419         goto oom;
03420     }
03421 
03422   if (!_dbus_split_paths_and_append (&servicedir_path,
03423                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03424                                      dirs))
03425     goto oom;
03426 
03427   _dbus_string_free (&servicedir_path);
03428   return TRUE;
03429 
03430  oom:
03431   _dbus_string_free (&servicedir_path);
03432   return FALSE;
03433 }
03434 
03435 
03454 dbus_bool_t
03455 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03456 {
03457   const char *xdg_data_dirs;
03458   DBusString servicedir_path;
03459 
03460   if (!_dbus_string_init (&servicedir_path))
03461     return FALSE;
03462 
03463   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03464 
03465   if (xdg_data_dirs != NULL)
03466     {
03467       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03468         goto oom;
03469 
03470       if (!_dbus_string_append (&servicedir_path, ":"))
03471         goto oom;
03472     }
03473   else
03474     {
03475       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03476         goto oom;
03477     }
03478 
03479   /*
03480    * add configured datadir to defaults
03481    * this may be the same as an xdg dir
03482    * however the config parser should take
03483    * care of duplicates
03484    */
03485   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03486         goto oom;
03487 
03488   if (!_dbus_split_paths_and_append (&servicedir_path,
03489                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03490                                      dirs))
03491     goto oom;
03492 
03493   _dbus_string_free (&servicedir_path);
03494   return TRUE;
03495 
03496  oom:
03497   _dbus_string_free (&servicedir_path);
03498   return FALSE;
03499 }
03500 
03509 dbus_bool_t
03510 _dbus_append_system_config_file (DBusString *str)
03511 {
03512   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03513 }
03514 
03521 dbus_bool_t
03522 _dbus_append_session_config_file (DBusString *str)
03523 {
03524   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03525 }
03526 
03534 void
03535 _dbus_flush_caches (void)
03536 {
03537   _dbus_user_database_flush_system ();
03538 }
03539 
03553 dbus_bool_t
03554 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03555                                                 DBusCredentials *credentials)
03556 {
03557   DBusString homedir;
03558   DBusString dotdir;
03559   dbus_uid_t uid;
03560 
03561   _dbus_assert (credentials != NULL);
03562   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03563 
03564   if (!_dbus_string_init (&homedir))
03565     return FALSE;
03566 
03567   uid = _dbus_credentials_get_unix_uid (credentials);
03568   _dbus_assert (uid != DBUS_UID_UNSET);
03569 
03570   if (!_dbus_homedir_from_uid (uid, &homedir))
03571     goto failed;
03572 
03573 #ifdef DBUS_BUILD_TESTS
03574   {
03575     const char *override;
03576 
03577     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03578     if (override != NULL && *override != '\0')
03579       {
03580         _dbus_string_set_length (&homedir, 0);
03581         if (!_dbus_string_append (&homedir, override))
03582           goto failed;
03583 
03584         _dbus_verbose ("Using fake homedir for testing: %s\n",
03585                        _dbus_string_get_const_data (&homedir));
03586       }
03587     else
03588       {
03589         static dbus_bool_t already_warned = FALSE;
03590         if (!already_warned)
03591           {
03592             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03593             already_warned = TRUE;
03594           }
03595       }
03596   }
03597 #endif
03598 
03599   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03600   if (!_dbus_concat_dir_and_file (&homedir,
03601                                   &dotdir))
03602     goto failed;
03603 
03604   if (!_dbus_string_copy (&homedir, 0,
03605                           directory, _dbus_string_get_length (directory))) {
03606     goto failed;
03607   }
03608 
03609   _dbus_string_free (&homedir);
03610   return TRUE;
03611 
03612  failed:
03613   _dbus_string_free (&homedir);
03614   return FALSE;
03615 }
03616 
03617 //PENDING(kdab) docs
03618 void
03619 _dbus_daemon_publish_session_bus_address (const char* addr)
03620 {
03621 
03622 }
03623 
03624 //PENDING(kdab) docs
03625 void
03626 _dbus_daemon_unpublish_session_bus_address (void)
03627 {
03628 
03629 }
03630 
03637 dbus_bool_t
03638 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03639 {
03640   return errno == EAGAIN || errno == EWOULDBLOCK;
03641 }
03642 
03650 dbus_bool_t
03651 _dbus_delete_directory (const DBusString *filename,
03652                         DBusError        *error)
03653 {
03654   const char *filename_c;
03655 
03656   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03657 
03658   filename_c = _dbus_string_get_const_data (filename);
03659 
03660   if (rmdir (filename_c) != 0)
03661     {
03662       dbus_set_error (error, DBUS_ERROR_FAILED,
03663                       "Failed to remove directory %s: %s\n",
03664                       filename_c, _dbus_strerror (errno));
03665       return FALSE;
03666     }
03667 
03668   return TRUE;
03669 }
03670 
03678 dbus_bool_t
03679 _dbus_socket_can_pass_unix_fd(int fd) {
03680 
03681 #ifdef SCM_RIGHTS
03682   union {
03683     struct sockaddr sa;
03684     struct sockaddr_storage storage;
03685     struct sockaddr_un un;
03686   } sa_buf;
03687 
03688   socklen_t sa_len = sizeof(sa_buf);
03689 
03690   _DBUS_ZERO(sa_buf);
03691 
03692   if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
03693     return FALSE;
03694 
03695   return sa_buf.sa.sa_family == AF_UNIX;
03696 
03697 #else
03698   return FALSE;
03699 
03700 #endif
03701 }
03702 
03703 
03704 /*
03705  * replaces the term DBUS_PREFIX in configure_time_path by the
03706  * current dbus installation directory. On unix this function is a noop
03707  *
03708  * @param configure_time_path
03709  * @return real path
03710  */
03711 const char *
03712 _dbus_replace_install_prefix (const char *configure_time_path)
03713 {
03714   return configure_time_path;
03715 }
03716 
03717 /* tests in dbus-sysdeps-util.c */

Generated on Fri Jul 22 2011 16:59:34 for D-Bus by  doxygen 1.7.1