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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-sysdeps-unix.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-protocol.h"
00030 #include "dbus-transport.h"
00031 #include "dbus-string.h"
00032 #include "dbus-userdb.h"
00033 #include "dbus-list.h"
00034 #include "dbus-credentials.h"
00035 
00036 #include <sys/types.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <signal.h>
00040 #include <unistd.h>
00041 #include <stdio.h>
00042 #include <fcntl.h>
00043 #include <sys/socket.h>
00044 #include <dirent.h>
00045 #include <sys/un.h>
00046 #include <pwd.h>
00047 #include <time.h>
00048 #include <locale.h>
00049 #include <sys/time.h>
00050 #include <sys/stat.h>
00051 #include <sys/wait.h>
00052 #include <netinet/in.h>
00053 #include <netdb.h>
00054 #include <grp.h>
00055 
00056 #ifdef HAVE_ERRNO_H
00057 #include <errno.h>
00058 #endif
00059 #ifdef HAVE_WRITEV
00060 #include <sys/uio.h>
00061 #endif
00062 #ifdef HAVE_POLL
00063 #include <sys/poll.h>
00064 #endif
00065 #ifdef HAVE_BACKTRACE
00066 #include <execinfo.h>
00067 #endif
00068 #ifdef HAVE_GETPEERUCRED
00069 #include <ucred.h>
00070 #endif
00071 
00072 #ifndef O_BINARY
00073 #define O_BINARY 0
00074 #endif
00075 
00076 #ifndef HAVE_SOCKLEN_T
00077 #define socklen_t int
00078 #endif
00079 
00080 static dbus_bool_t
00081 _dbus_open_socket (int              *fd_p,
00082                    int               domain,
00083                    int               type,
00084                    int               protocol,
00085                    DBusError        *error)
00086 {
00087   *fd_p = socket (domain, type, protocol);
00088   if (*fd_p >= 0)
00089     {
00090       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00091       return TRUE;
00092     }
00093   else
00094     {
00095       dbus_set_error(error,
00096                      _dbus_error_from_errno (errno),
00097                      "Failed to open socket: %s",
00098                      _dbus_strerror (errno));
00099       return FALSE;
00100     }
00101 }
00102 
00103 dbus_bool_t
00104 _dbus_open_tcp_socket (int              *fd,
00105                        DBusError        *error)
00106 {
00107   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00108 }
00109 
00117 dbus_bool_t
00118 _dbus_open_unix_socket (int              *fd,
00119                         DBusError        *error)
00120 {
00121   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00122 }
00123 
00132 dbus_bool_t 
00133 _dbus_close_socket (int               fd,
00134                     DBusError        *error)
00135 {
00136   return _dbus_close (fd, error);
00137 }
00138 
00148 int
00149 _dbus_read_socket (int               fd,
00150                    DBusString       *buffer,
00151                    int               count)
00152 {
00153   return _dbus_read (fd, buffer, count);
00154 }
00155 
00166 int
00167 _dbus_write_socket (int               fd,
00168                     const DBusString *buffer,
00169                     int               start,
00170                     int               len)
00171 {
00172   return _dbus_write (fd, buffer, start, len);
00173 }
00174 
00185 int
00186 _dbus_pipe_write (DBusPipe         *pipe,
00187                   const DBusString *buffer,
00188                   int               start,
00189                   int               len,
00190                   DBusError        *error)
00191 {
00192   int written;
00193   
00194   written = _dbus_write (pipe->fd_or_handle, buffer, start, len);
00195   if (written < 0)
00196     {
00197       dbus_set_error (error, DBUS_ERROR_FAILED,
00198                       "Writing to pipe: %s\n",
00199                       _dbus_strerror (errno));
00200     }
00201   return written;
00202 }
00203 
00211 int
00212 _dbus_pipe_close  (DBusPipe         *pipe,
00213                    DBusError        *error)
00214 {
00215   if (_dbus_close (pipe->fd_or_handle, error) < 0)
00216     {
00217       return -1;
00218     }
00219   else
00220     {
00221       _dbus_pipe_invalidate (pipe);
00222       return 0;
00223     }
00224 }
00225 
00239 int
00240 _dbus_write_socket_two (int               fd,
00241                         const DBusString *buffer1,
00242                         int               start1,
00243                         int               len1,
00244                         const DBusString *buffer2,
00245                         int               start2,
00246                         int               len2)
00247 {
00248   return _dbus_write_two (fd, buffer1, start1, len1,
00249                           buffer2, start2, len2);
00250 }
00251 
00252 
00269 int
00270 _dbus_read (int               fd,
00271             DBusString       *buffer,
00272             int               count)
00273 {
00274   int bytes_read;
00275   int start;
00276   char *data;
00277 
00278   _dbus_assert (count >= 0);
00279   
00280   start = _dbus_string_get_length (buffer);
00281 
00282   if (!_dbus_string_lengthen (buffer, count))
00283     {
00284       errno = ENOMEM;
00285       return -1;
00286     }
00287 
00288   data = _dbus_string_get_data_len (buffer, start, count);
00289 
00290  again:
00291   
00292   bytes_read = read (fd, data, count);
00293 
00294   if (bytes_read < 0)
00295     {
00296       if (errno == EINTR)
00297         goto again;
00298       else
00299         {
00300           /* put length back (note that this doesn't actually realloc anything) */
00301           _dbus_string_set_length (buffer, start);
00302           return -1;
00303         }
00304     }
00305   else
00306     {
00307       /* put length back (doesn't actually realloc) */
00308       _dbus_string_set_length (buffer, start + bytes_read);
00309 
00310 #if 0
00311       if (bytes_read > 0)
00312         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00313 #endif
00314       
00315       return bytes_read;
00316     }
00317 }
00318 
00329 int
00330 _dbus_write (int               fd,
00331              const DBusString *buffer,
00332              int               start,
00333              int               len)
00334 {
00335   const char *data;
00336   int bytes_written;
00337   
00338   data = _dbus_string_get_const_data_len (buffer, start, len);
00339   
00340  again:
00341 
00342   bytes_written = write (fd, data, len);
00343 
00344   if (bytes_written < 0 && errno == EINTR)
00345     goto again;
00346 
00347 #if 0
00348   if (bytes_written > 0)
00349     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00350 #endif
00351   
00352   return bytes_written;
00353 }
00354 
00375 int
00376 _dbus_write_two (int               fd,
00377                  const DBusString *buffer1,
00378                  int               start1,
00379                  int               len1,
00380                  const DBusString *buffer2,
00381                  int               start2,
00382                  int               len2)
00383 {
00384   _dbus_assert (buffer1 != NULL);
00385   _dbus_assert (start1 >= 0);
00386   _dbus_assert (start2 >= 0);
00387   _dbus_assert (len1 >= 0);
00388   _dbus_assert (len2 >= 0);
00389   
00390 #ifdef HAVE_WRITEV
00391   {
00392     struct iovec vectors[2];
00393     const char *data1;
00394     const char *data2;
00395     int bytes_written;
00396 
00397     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00398 
00399     if (buffer2 != NULL)
00400       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00401     else
00402       {
00403         data2 = NULL;
00404         start2 = 0;
00405         len2 = 0;
00406       }
00407    
00408     vectors[0].iov_base = (char*) data1;
00409     vectors[0].iov_len = len1;
00410     vectors[1].iov_base = (char*) data2;
00411     vectors[1].iov_len = len2;
00412 
00413   again:
00414    
00415     bytes_written = writev (fd,
00416                             vectors,
00417                             data2 ? 2 : 1);
00418 
00419     if (bytes_written < 0 && errno == EINTR)
00420       goto again;
00421    
00422     return bytes_written;
00423   }
00424 #else /* HAVE_WRITEV */
00425   {
00426     int ret1;
00427     
00428     ret1 = _dbus_write (fd, buffer1, start1, len1);
00429     if (ret1 == len1 && buffer2 != NULL)
00430       {
00431         ret2 = _dbus_write (fd, buffer2, start2, len2);
00432         if (ret2 < 0)
00433           ret2 = 0; /* we can't report an error as the first write was OK */
00434        
00435         return ret1 + ret2;
00436       }
00437     else
00438       return ret1;
00439   }
00440 #endif /* !HAVE_WRITEV */   
00441 }
00442 
00443 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00444 
00472 int
00473 _dbus_connect_unix_socket (const char     *path,
00474                            dbus_bool_t     abstract,
00475                            DBusError      *error)
00476 {
00477   int fd;
00478   size_t path_len;
00479   struct sockaddr_un addr;  
00480 
00481   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00482 
00483   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00484                  path, abstract);
00485   
00486   
00487   if (!_dbus_open_unix_socket (&fd, error))
00488     {
00489       _DBUS_ASSERT_ERROR_IS_SET(error);
00490       return -1;
00491     }
00492   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00493 
00494   _DBUS_ZERO (addr);
00495   addr.sun_family = AF_UNIX;
00496   path_len = strlen (path);
00497 
00498   if (abstract)
00499     {
00500 #ifdef HAVE_ABSTRACT_SOCKETS
00501       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00502       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00503 
00504       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00505         {
00506           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00507                       "Abstract socket name too long\n");
00508           _dbus_close (fd, NULL);
00509           return -1;
00510         }
00511         
00512       strncpy (&addr.sun_path[1], path, path_len);
00513       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00514 #else /* HAVE_ABSTRACT_SOCKETS */
00515       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00516                       "Operating system does not support abstract socket namespace\n");
00517       _dbus_close (fd, NULL);
00518       return -1;
00519 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00520     }
00521   else
00522     {
00523       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00524         {
00525           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00526                       "Socket name too long\n");
00527           _dbus_close (fd, NULL);
00528           return -1;
00529         }
00530 
00531       strncpy (addr.sun_path, path, path_len);
00532     }
00533   
00534   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00535     {      
00536       dbus_set_error (error,
00537                       _dbus_error_from_errno (errno),
00538                       "Failed to connect to socket %s: %s",
00539                       path, _dbus_strerror (errno));
00540 
00541       _dbus_close (fd, NULL);
00542       fd = -1;
00543       
00544       return -1;
00545     }
00546 
00547   if (!_dbus_set_fd_nonblocking (fd, error))
00548     {
00549       _DBUS_ASSERT_ERROR_IS_SET (error);
00550       
00551       _dbus_close (fd, NULL);
00552       fd = -1;
00553 
00554       return -1;
00555     }
00556 
00557   return fd;
00558 }
00559 
00569 static dbus_bool_t
00570 _dbus_set_local_creds (int fd, dbus_bool_t on)
00571 {
00572   dbus_bool_t retval = TRUE;
00573 
00574 #if defined(HAVE_CMSGCRED)
00575   /* NOOP just to make sure only one codepath is used 
00576    *      and to prefer CMSGCRED
00577    */
00578 #elif defined(LOCAL_CREDS) 
00579   int val = on ? 1 : 0;
00580   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00581     {
00582       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00583       retval = FALSE;
00584     }
00585   else
00586     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00587                    on ? "enabled" : "disabled", fd);
00588 #endif
00589 
00590   return retval;
00591 }
00592 
00608 int
00609 _dbus_listen_unix_socket (const char     *path,
00610                           dbus_bool_t     abstract,
00611                           DBusError      *error)
00612 {
00613   int listen_fd;
00614   struct sockaddr_un addr;
00615   size_t path_len;
00616 
00617   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00618 
00619   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00620                  path, abstract);
00621   
00622   if (!_dbus_open_unix_socket (&listen_fd, error))
00623     {
00624       _DBUS_ASSERT_ERROR_IS_SET(error);
00625       return -1;
00626     }
00627   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00628 
00629   _DBUS_ZERO (addr);
00630   addr.sun_family = AF_UNIX;
00631   path_len = strlen (path);
00632   
00633   if (abstract)
00634     {
00635 #ifdef HAVE_ABSTRACT_SOCKETS
00636       /* remember that abstract names aren't nul-terminated so we rely
00637        * on sun_path being filled in with zeroes above.
00638        */
00639       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00640       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00641 
00642       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00643         {
00644           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00645                       "Abstract socket name too long\n");
00646           _dbus_close (listen_fd, NULL);
00647           return -1;
00648         }
00649       
00650       strncpy (&addr.sun_path[1], path, path_len);
00651       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00652 #else /* HAVE_ABSTRACT_SOCKETS */
00653       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00654                       "Operating system does not support abstract socket namespace\n");
00655       _dbus_close (listen_fd, NULL);
00656       return -1;
00657 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00658     }
00659   else
00660     {
00661       /* Discussed security implications of this with Nalin,
00662        * and we couldn't think of where it would kick our ass, but
00663        * it still seems a bit sucky. It also has non-security suckage;
00664        * really we'd prefer to exit if the socket is already in use.
00665        * But there doesn't seem to be a good way to do this.
00666        *
00667        * Just to be extra careful, I threw in the stat() - clearly
00668        * the stat() can't *fix* any security issue, but it at least
00669        * avoids inadvertent/accidental data loss.
00670        */
00671       {
00672         struct stat sb;
00673 
00674         if (stat (path, &sb) == 0 &&
00675             S_ISSOCK (sb.st_mode))
00676           unlink (path);
00677       }
00678 
00679       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00680         {
00681           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00682                       "Abstract socket name too long\n");
00683           _dbus_close (listen_fd, NULL);
00684           return -1;
00685         }
00686         
00687       strncpy (addr.sun_path, path, path_len);
00688     }
00689   
00690   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00691     {
00692       dbus_set_error (error, _dbus_error_from_errno (errno),
00693                       "Failed to bind socket \"%s\": %s",
00694                       path, _dbus_strerror (errno));
00695       _dbus_close (listen_fd, NULL);
00696       return -1;
00697     }
00698 
00699   if (listen (listen_fd, 30 /* backlog */) < 0)
00700     {
00701       dbus_set_error (error, _dbus_error_from_errno (errno),
00702                       "Failed to listen on socket \"%s\": %s",
00703                       path, _dbus_strerror (errno));
00704       _dbus_close (listen_fd, NULL);
00705       return -1;
00706     }
00707 
00708   if (!_dbus_set_local_creds (listen_fd, TRUE))
00709     {
00710       dbus_set_error (error, _dbus_error_from_errno (errno),
00711                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00712                       path, _dbus_strerror (errno));
00713       close (listen_fd);
00714       return -1;
00715     }
00716 
00717   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00718     {
00719       _DBUS_ASSERT_ERROR_IS_SET (error);
00720       _dbus_close (listen_fd, NULL);
00721       return -1;
00722     }
00723   
00724   /* Try opening up the permissions, but if we can't, just go ahead
00725    * and continue, maybe it will be good enough.
00726    */
00727   if (!abstract && chmod (path, 0777) < 0)
00728     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00729                 path);
00730   
00731   return listen_fd;
00732 }
00733 
00745 int
00746 _dbus_connect_tcp_socket (const char     *host,
00747                           const char     *port,
00748                           const char     *family,
00749                           DBusError      *error)
00750 {
00751   int fd = -1, res;
00752   struct addrinfo hints;
00753   struct addrinfo *ai, *tmp;
00754 
00755   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00756 
00757   if (!_dbus_open_tcp_socket (&fd, error))
00758     {
00759       _DBUS_ASSERT_ERROR_IS_SET(error);
00760       return -1;
00761     }
00762 
00763   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00764 
00765   _DBUS_ZERO (hints);
00766 
00767   if (!family)
00768     hints.ai_family = AF_UNSPEC;
00769   else if (!strcmp(family, "ipv4"))
00770     hints.ai_family = AF_INET;
00771   else if (!strcmp(family, "ipv6"))
00772     hints.ai_family = AF_INET6;
00773   else
00774     {
00775       dbus_set_error (error,
00776                       _dbus_error_from_errno (errno),
00777                       "Unknown address family %s", family);
00778       return -1;
00779     }
00780   fprintf(stderr, "Family %s\n", family ? family : "none");
00781   hints.ai_protocol = IPPROTO_TCP;
00782   hints.ai_socktype = SOCK_STREAM;
00783   hints.ai_flags = AI_ADDRCONFIG;
00784 
00785   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00786     {
00787       dbus_set_error (error,
00788                       _dbus_error_from_errno (errno),
00789                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00790                       host, port, gai_strerror(res), res);
00791       _dbus_close (fd, NULL);
00792       return -1;
00793     }
00794 
00795   tmp = ai;
00796   while (tmp)
00797     {
00798       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00799         {
00800           freeaddrinfo(ai);
00801           _DBUS_ASSERT_ERROR_IS_SET(error);
00802           return -1;
00803         }
00804       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00805 
00806       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00807         {
00808           _dbus_close(fd, NULL);
00809           fd = -1;
00810           tmp = tmp->ai_next;
00811           continue;
00812         }
00813 
00814       break;
00815     }
00816   freeaddrinfo(ai);
00817 
00818   if (fd == -1)
00819     {
00820       dbus_set_error (error,
00821                       _dbus_error_from_errno (errno),
00822                       "Failed to connect to socket \"%s:%s\" %s",
00823                       host, port, _dbus_strerror(errno));
00824       return -1;
00825     }
00826 
00827 
00828   if (!_dbus_set_fd_nonblocking (fd, error))
00829     {
00830       _dbus_close (fd, NULL);
00831       fd = -1;
00832 
00833       return -1;
00834     }
00835 
00836   return fd;
00837 }
00838 
00853 int
00854 _dbus_listen_tcp_socket (const char     *host,
00855                          const char     *port,
00856                          const char     *family,
00857                          DBusString     *retport,
00858                          int           **fds_p,
00859                          DBusError      *error)
00860 {
00861   int nlisten_fd = 0, *listen_fd = NULL, res, i;
00862   struct addrinfo hints;
00863   struct addrinfo *ai, *tmp;
00864 
00865   *fds_p = NULL;
00866   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00867 
00868   _DBUS_ZERO (hints);
00869 
00870   if (!family)
00871     hints.ai_family = AF_UNSPEC;
00872   else if (!strcmp(family, "ipv4"))
00873     hints.ai_family = AF_INET;
00874   else if (!strcmp(family, "ipv6"))
00875     hints.ai_family = AF_INET6;
00876   else
00877     {
00878       dbus_set_error (error,
00879                       _dbus_error_from_errno (errno),
00880                       "Unknown address family %s", family);
00881       return -1;
00882     }
00883 
00884   hints.ai_protocol = IPPROTO_TCP;
00885   hints.ai_socktype = SOCK_STREAM;
00886   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00887 
00888  redo_lookup_with_port:
00889   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00890     {
00891       dbus_set_error (error,
00892                       _dbus_error_from_errno (errno),
00893                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00894                       host ? host : "*", port, gai_strerror(res), res);
00895       return -1;
00896     }
00897 
00898   tmp = ai;
00899   while (tmp)
00900     {
00901       int fd = -1, *newlisten_fd;
00902       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00903         {
00904           _DBUS_ASSERT_ERROR_IS_SET(error);
00905           goto failed;
00906         }
00907       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00908 
00909       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00910         {
00911           _dbus_close(fd, NULL);
00912           if (errno == EADDRINUSE)
00913             {
00914               /* Depending on kernel policy, it may or may not
00915                  be neccessary to bind to both IPv4 & 6 addresses
00916                  so ignore EADDRINUSE here */
00917               tmp = tmp->ai_next;
00918               continue;
00919             }
00920           dbus_set_error (error, _dbus_error_from_errno (errno),
00921                           "Failed to bind socket \"%s:%s\": %s",
00922                           host ? host : "*", port, _dbus_strerror (errno));
00923           goto failed;
00924         }
00925 
00926       if (listen (fd, 30 /* backlog */) < 0)
00927         {
00928           _dbus_close (fd, NULL);
00929           dbus_set_error (error, _dbus_error_from_errno (errno),
00930                           "Failed to listen on socket \"%s:%s\": %s",
00931                           host ? host : "*", port, _dbus_strerror (errno));
00932           goto failed;
00933         }
00934 
00935       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00936       if (!newlisten_fd)
00937         {
00938           _dbus_close (fd, NULL);
00939           dbus_set_error (error, _dbus_error_from_errno (errno),
00940                           "Failed to allocate file handle array: %s",
00941                           _dbus_strerror (errno));
00942           goto failed;
00943         }
00944       listen_fd = newlisten_fd;
00945       listen_fd[nlisten_fd] = fd;
00946       nlisten_fd++;
00947 
00948       if (!_dbus_string_get_length(retport))
00949         {
00950           /* If the user didn't specify a port, or used 0, then
00951              the kernel chooses a port. After the first address
00952              is bound to, we need to force all remaining addresses
00953              to use the same port */
00954           if (!port || !strcmp(port, "0"))
00955             {
00956               struct sockaddr_storage addr;
00957               socklen_t addrlen;
00958               char portbuf[50];
00959 
00960               addrlen = sizeof(addr);
00961               getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00962 
00963               if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00964                                      portbuf, sizeof(portbuf),
00965                                      NI_NUMERICHOST)) != 0)
00966                 {
00967                   dbus_set_error (error, _dbus_error_from_errno (errno),
00968                                   "Failed to resolve port \"%s:%s\": %s (%s)",
00969                                   host ? host : "*", port, gai_strerror(res), res);
00970                   goto failed;
00971                 }
00972               if (!_dbus_string_append(retport, portbuf))
00973                 {
00974                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00975                   goto failed;
00976                 }
00977 
00978               /* Release current address list & redo lookup */
00979               port = _dbus_string_get_const_data(retport);
00980               freeaddrinfo(ai);
00981               goto redo_lookup_with_port;
00982             }
00983           else
00984             {
00985               if (!_dbus_string_append(retport, port))
00986                 {
00987                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00988                     goto failed;
00989                 }
00990             }
00991         }
00992 
00993       tmp = tmp->ai_next;
00994     }
00995   freeaddrinfo(ai);
00996   ai = NULL;
00997 
00998   if (!nlisten_fd)
00999     {
01000       errno = EADDRINUSE;
01001       dbus_set_error (error, _dbus_error_from_errno (errno),
01002                       "Failed to bind socket \"%s:%s\": %s",
01003                       host ? host : "*", port, _dbus_strerror (errno));
01004       return -1;
01005     }
01006 
01007   for (i = 0 ; i < nlisten_fd ; i++)
01008     {
01009       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01010         {
01011           goto failed;
01012         }
01013     }
01014 
01015   *fds_p = listen_fd;
01016 
01017   return nlisten_fd;
01018 
01019  failed:
01020   if (ai)
01021     freeaddrinfo(ai);
01022   for (i = 0 ; i < nlisten_fd ; i++)
01023     _dbus_close(listen_fd[i], NULL);
01024   dbus_free(listen_fd);
01025   return -1;
01026 }
01027 
01028 static dbus_bool_t
01029 write_credentials_byte (int             server_fd,
01030                         DBusError      *error)
01031 {
01032   int bytes_written;
01033   char buf[1] = { '\0' };
01034 #if defined(HAVE_CMSGCRED) 
01035   struct {
01036           struct cmsghdr hdr;
01037           struct cmsgcred cred;
01038   } cmsg;
01039   struct iovec iov;
01040   struct msghdr msg;
01041   iov.iov_base = buf;
01042   iov.iov_len = 1;
01043 
01044   memset (&msg, 0, sizeof (msg));
01045   msg.msg_iov = &iov;
01046   msg.msg_iovlen = 1;
01047 
01048   msg.msg_control = &cmsg;
01049   msg.msg_controllen = sizeof (cmsg);
01050   memset (&cmsg, 0, sizeof (cmsg));
01051   cmsg.hdr.cmsg_len = sizeof (cmsg);
01052   cmsg.hdr.cmsg_level = SOL_SOCKET;
01053   cmsg.hdr.cmsg_type = SCM_CREDS;
01054 #endif
01055 
01056   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01057   
01058  again:
01059 
01060 #if defined(HAVE_CMSGCRED) 
01061   bytes_written = sendmsg (server_fd, &msg, 0);
01062 #else
01063   bytes_written = write (server_fd, buf, 1);
01064 #endif
01065 
01066   if (bytes_written < 0 && errno == EINTR)
01067     goto again;
01068 
01069   if (bytes_written < 0)
01070     {
01071       dbus_set_error (error, _dbus_error_from_errno (errno),
01072                       "Failed to write credentials byte: %s",
01073                      _dbus_strerror (errno));
01074       return FALSE;
01075     }
01076   else if (bytes_written == 0)
01077     {
01078       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01079                       "wrote zero bytes writing credentials byte");
01080       return FALSE;
01081     }
01082   else
01083     {
01084       _dbus_assert (bytes_written == 1);
01085       _dbus_verbose ("wrote credentials byte\n");
01086       return TRUE;
01087     }
01088 }
01089 
01111 dbus_bool_t
01112 _dbus_read_credentials_socket  (int              client_fd,
01113                                 DBusCredentials *credentials,
01114                                 DBusError       *error)
01115 {
01116   struct msghdr msg;
01117   struct iovec iov;
01118   char buf;
01119   dbus_uid_t uid_read;
01120   dbus_pid_t pid_read;
01121   int bytes_read;
01122   
01123   uid_read = DBUS_UID_UNSET;
01124   pid_read = DBUS_PID_UNSET;
01125   
01126 #ifdef HAVE_CMSGCRED 
01127   struct {
01128     struct cmsghdr hdr;
01129     struct cmsgcred cred;
01130   } cmsg;
01131 
01132 #elif defined(LOCAL_CREDS)
01133   struct {
01134     struct cmsghdr hdr;
01135     struct sockcred cred;
01136   } cmsg;
01137 #endif
01138 
01139   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01140   
01141   /* The POSIX spec certainly doesn't promise this, but
01142    * we need these assertions to fail as soon as we're wrong about
01143    * it so we can do the porting fixups
01144    */
01145   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01146   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01147   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01148 
01149   _dbus_credentials_clear (credentials);
01150 
01151   /* Systems supporting LOCAL_CREDS are configured to have this feature
01152    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01153    * the connection.  Therefore, the received message must carry the
01154    * credentials information without doing anything special.
01155    */
01156 
01157   iov.iov_base = &buf;
01158   iov.iov_len = 1;
01159 
01160   memset (&msg, 0, sizeof (msg));
01161   msg.msg_iov = &iov;
01162   msg.msg_iovlen = 1;
01163 
01164 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01165   memset (&cmsg, 0, sizeof (cmsg));
01166   msg.msg_control = &cmsg;
01167   msg.msg_controllen = sizeof (cmsg);
01168 #endif
01169 
01170  again:
01171   bytes_read = recvmsg (client_fd, &msg, 0);
01172 
01173   if (bytes_read < 0)
01174     {
01175       if (errno == EINTR)
01176         goto again;
01177 
01178       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01179        * normally only call read_credentials if the socket was ready
01180        * for reading
01181        */
01182       
01183       dbus_set_error (error, _dbus_error_from_errno (errno),
01184                       "Failed to read credentials byte: %s",
01185                       _dbus_strerror (errno));
01186       return FALSE;
01187     }
01188   else if (bytes_read == 0)
01189     {
01190       /* this should not happen unless we are using recvmsg wrong,
01191        * so is essentially here for paranoia
01192        */
01193       dbus_set_error (error, DBUS_ERROR_FAILED,
01194                       "Failed to read credentials byte (zero-length read)");
01195       return FALSE;
01196     }
01197   else if (buf != '\0')
01198     {
01199       dbus_set_error (error, DBUS_ERROR_FAILED,
01200                       "Credentials byte was not nul");
01201       return FALSE;
01202     }
01203 
01204 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01205   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
01206     {
01207       dbus_set_error (error, DBUS_ERROR_FAILED,
01208                       "Message from recvmsg() was not SCM_CREDS");
01209       return FALSE;
01210     }
01211 #endif
01212 
01213   _dbus_verbose ("read credentials byte\n");
01214 
01215   {
01216 #ifdef SO_PEERCRED
01217     struct ucred cr;   
01218     int cr_len = sizeof (cr);
01219     
01220     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01221         cr_len == sizeof (cr))
01222       {
01223         pid_read = cr.pid;
01224         uid_read = cr.uid;
01225       }
01226     else
01227       {
01228         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01229                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01230       }
01231 #elif defined(HAVE_CMSGCRED)
01232     pid_read = cmsg.cred.cmcred_pid;
01233     uid_read = cmsg.cred.cmcred_euid;
01234 #elif defined(LOCAL_CREDS)
01235     pid_read = DBUS_PID_UNSET;
01236     uid_read = cmsg.cred.sc_uid;
01237     /* Since we have already got the credentials from this socket, we can
01238      * disable its LOCAL_CREDS flag if it was ever set. */
01239     _dbus_set_local_creds (client_fd, FALSE);
01240 #elif defined(HAVE_GETPEEREID)
01241     uid_t euid;
01242     gid_t egid;
01243     if (getpeereid (client_fd, &euid, &egid) == 0)
01244       {
01245         uid_read = euid;
01246       }
01247     else
01248       {
01249         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01250       }
01251 #elif defined(HAVE_GETPEERUCRED)
01252     ucred_t * ucred = NULL;
01253     if (getpeerucred (client_fd, &ucred) == 0)
01254       {
01255         pid_read = ucred_getpid (ucred);
01256         uid_read = ucred_geteuid (ucred);
01257       }
01258     else
01259       {
01260         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01261       }
01262     if (ucred != NULL)
01263       ucred_free (ucred);
01264 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01265     _dbus_verbose ("Socket credentials not supported on this OS\n");
01266 #endif
01267   }
01268 
01269   _dbus_verbose ("Credentials:"
01270                  "  pid "DBUS_PID_FORMAT
01271                  "  uid "DBUS_UID_FORMAT
01272                  "\n",
01273                  pid_read,
01274                  uid_read);
01275 
01276   if (pid_read != DBUS_PID_UNSET)
01277     {
01278       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01279         {
01280           _DBUS_SET_OOM (error);
01281           return FALSE;
01282         }
01283     }
01284 
01285   if (uid_read != DBUS_UID_UNSET)
01286     {
01287       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01288         {
01289           _DBUS_SET_OOM (error);
01290           return FALSE;
01291         }
01292     }
01293   
01294   return TRUE;
01295 }
01296 
01314 dbus_bool_t
01315 _dbus_send_credentials_socket  (int              server_fd,
01316                                 DBusError       *error)
01317 {
01318   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01319   
01320   if (write_credentials_byte (server_fd, error))
01321     return TRUE;
01322   else
01323     return FALSE;
01324 }
01325 
01333 int
01334 _dbus_accept  (int listen_fd)
01335 {
01336   int client_fd;
01337   struct sockaddr addr;
01338   socklen_t addrlen;
01339 
01340   addrlen = sizeof (addr);
01341   
01342  retry:
01343   client_fd = accept (listen_fd, &addr, &addrlen);
01344   
01345   if (client_fd < 0)
01346     {
01347       if (errno == EINTR)
01348         goto retry;
01349     }
01350 
01351   _dbus_verbose ("client fd %d accepted\n", client_fd);
01352   
01353   return client_fd;
01354 }
01355 
01364 dbus_bool_t
01365 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01366 {
01367   const char *directory;
01368   struct stat sb;
01369         
01370   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01371     
01372   directory = _dbus_string_get_const_data (dir);
01373         
01374   if (stat (directory, &sb) < 0)
01375     {
01376       dbus_set_error (error, _dbus_error_from_errno (errno),
01377                       "%s", _dbus_strerror (errno));
01378    
01379       return FALSE;
01380     }
01381     
01382   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01383       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01384     {
01385       dbus_set_error (error, DBUS_ERROR_FAILED,
01386                      "%s directory is not private to the user", directory);
01387       return FALSE;
01388     }
01389     
01390   return TRUE;
01391 }
01392 
01393 static dbus_bool_t
01394 fill_user_info_from_passwd (struct passwd *p,
01395                             DBusUserInfo  *info,
01396                             DBusError     *error)
01397 {
01398   _dbus_assert (p->pw_name != NULL);
01399   _dbus_assert (p->pw_dir != NULL);
01400   
01401   info->uid = p->pw_uid;
01402   info->primary_gid = p->pw_gid;
01403   info->username = _dbus_strdup (p->pw_name);
01404   info->homedir = _dbus_strdup (p->pw_dir);
01405   
01406   if (info->username == NULL ||
01407       info->homedir == NULL)
01408     {
01409       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01410       return FALSE;
01411     }
01412 
01413   return TRUE;
01414 }
01415 
01416 static dbus_bool_t
01417 fill_user_info (DBusUserInfo       *info,
01418                 dbus_uid_t          uid,
01419                 const DBusString   *username,
01420                 DBusError          *error)
01421 {
01422   const char *username_c;
01423   
01424   /* exactly one of username/uid provided */
01425   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01426   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01427 
01428   info->uid = DBUS_UID_UNSET;
01429   info->primary_gid = DBUS_GID_UNSET;
01430   info->group_ids = NULL;
01431   info->n_group_ids = 0;
01432   info->username = NULL;
01433   info->homedir = NULL;
01434   
01435   if (username != NULL)
01436     username_c = _dbus_string_get_const_data (username);
01437   else
01438     username_c = NULL;
01439 
01440   /* For now assuming that the getpwnam() and getpwuid() flavors
01441    * are always symmetrical, if not we have to add more configure
01442    * checks
01443    */
01444   
01445 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01446   {
01447     struct passwd *p;
01448     int result;
01449     char buf[1024];
01450     struct passwd p_str;
01451 
01452     p = NULL;
01453 #ifdef HAVE_POSIX_GETPWNAM_R
01454     if (uid != DBUS_UID_UNSET)
01455       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01456                            &p);
01457     else
01458       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01459                            &p);
01460 #else
01461     if (uid != DBUS_UID_UNSET)
01462       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01463     else
01464       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01465     result = 0;
01466 #endif /* !HAVE_POSIX_GETPWNAM_R */
01467     if (result == 0 && p == &p_str)
01468       {
01469         if (!fill_user_info_from_passwd (p, info, error))
01470           return FALSE;
01471       }
01472     else
01473       {
01474         dbus_set_error (error, _dbus_error_from_errno (errno),
01475                         "User \"%s\" unknown or no memory to allocate password entry\n",
01476                         username_c ? username_c : "???");
01477         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01478         return FALSE;
01479       }
01480   }
01481 #else /* ! HAVE_GETPWNAM_R */
01482   {
01483     /* I guess we're screwed on thread safety here */
01484     struct passwd *p;
01485 
01486     if (uid != DBUS_UID_UNSET)
01487       p = getpwuid (uid);
01488     else
01489       p = getpwnam (username_c);
01490 
01491     if (p != NULL)
01492       {
01493         if (!fill_user_info_from_passwd (p, info, error))
01494           return FALSE;
01495       }
01496     else
01497       {
01498         dbus_set_error (error, _dbus_error_from_errno (errno),
01499                         "User \"%s\" unknown or no memory to allocate password entry\n",
01500                         username_c ? username_c : "???");
01501         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01502         return FALSE;
01503       }
01504   }
01505 #endif  /* ! HAVE_GETPWNAM_R */
01506 
01507   /* Fill this in so we can use it to get groups */
01508   username_c = info->username;
01509   
01510 #ifdef HAVE_GETGROUPLIST
01511   {
01512     gid_t *buf;
01513     int buf_count;
01514     int i;
01515     
01516     buf_count = 17;
01517     buf = dbus_new (gid_t, buf_count);
01518     if (buf == NULL)
01519       {
01520         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01521         goto failed;
01522       }
01523     
01524     if (getgrouplist (username_c,
01525                       info->primary_gid,
01526                       buf, &buf_count) < 0)
01527       {
01528         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01529         if (new == NULL)
01530           {
01531             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01532             dbus_free (buf);
01533             goto failed;
01534           }
01535         
01536         buf = new;
01537 
01538         errno = 0;
01539         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01540           {
01541             dbus_set_error (error,
01542                             _dbus_error_from_errno (errno),
01543                             "Failed to get groups for username \"%s\" primary GID "
01544                             DBUS_GID_FORMAT ": %s\n",
01545                             username_c, info->primary_gid,
01546                             _dbus_strerror (errno));
01547             dbus_free (buf);
01548             goto failed;
01549           }
01550       }
01551 
01552     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01553     if (info->group_ids == NULL)
01554       {
01555         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01556         dbus_free (buf);
01557         goto failed;
01558       }
01559     
01560     for (i = 0; i < buf_count; ++i)
01561       info->group_ids[i] = buf[i];
01562 
01563     info->n_group_ids = buf_count;
01564     
01565     dbus_free (buf);
01566   }
01567 #else  /* HAVE_GETGROUPLIST */
01568   {
01569     /* We just get the one group ID */
01570     info->group_ids = dbus_new (dbus_gid_t, 1);
01571     if (info->group_ids == NULL)
01572       {
01573         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01574         goto failed;
01575       }
01576 
01577     info->n_group_ids = 1;
01578 
01579     (info->group_ids)[0] = info->primary_gid;
01580   }
01581 #endif /* HAVE_GETGROUPLIST */
01582 
01583   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01584   
01585   return TRUE;
01586   
01587  failed:
01588   _DBUS_ASSERT_ERROR_IS_SET (error);
01589   return FALSE;
01590 }
01591 
01600 dbus_bool_t
01601 _dbus_user_info_fill (DBusUserInfo     *info,
01602                       const DBusString *username,
01603                       DBusError        *error)
01604 {
01605   return fill_user_info (info, DBUS_UID_UNSET,
01606                          username, error);
01607 }
01608 
01617 dbus_bool_t
01618 _dbus_user_info_fill_uid (DBusUserInfo *info,
01619                           dbus_uid_t    uid,
01620                           DBusError    *error)
01621 {
01622   return fill_user_info (info, uid,
01623                          NULL, error);
01624 }
01625 
01633 dbus_bool_t
01634 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01635 {
01636   /* The POSIX spec certainly doesn't promise this, but
01637    * we need these assertions to fail as soon as we're wrong about
01638    * it so we can do the porting fixups
01639    */
01640   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01641   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01642   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01643 
01644   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01645     return FALSE;
01646   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_getuid()))
01647     return FALSE;
01648 
01649   return TRUE;
01650 }
01651 
01663 dbus_bool_t
01664 _dbus_append_user_from_current_process (DBusString *str)
01665 {
01666   return _dbus_string_append_uint (str,
01667                                    _dbus_getuid ());
01668 }
01669 
01674 dbus_pid_t
01675 _dbus_getpid (void)
01676 {
01677   return getpid ();
01678 }
01679 
01683 dbus_uid_t
01684 _dbus_getuid (void)
01685 {
01686   return getuid ();
01687 }
01688 
01695 unsigned long
01696 _dbus_pid_for_log (void)
01697 {
01698   return getpid ();
01699 }
01700 
01708 dbus_bool_t
01709 _dbus_parse_uid (const DBusString      *uid_str,
01710                  dbus_uid_t            *uid)
01711 {
01712   int end;
01713   long val;
01714   
01715   if (_dbus_string_get_length (uid_str) == 0)
01716     {
01717       _dbus_verbose ("UID string was zero length\n");
01718       return FALSE;
01719     }
01720 
01721   val = -1;
01722   end = 0;
01723   if (!_dbus_string_parse_int (uid_str, 0, &val,
01724                                &end))
01725     {
01726       _dbus_verbose ("could not parse string as a UID\n");
01727       return FALSE;
01728     }
01729   
01730   if (end != _dbus_string_get_length (uid_str))
01731     {
01732       _dbus_verbose ("string contained trailing stuff after UID\n");
01733       return FALSE;
01734     }
01735 
01736   *uid = val;
01737 
01738   return TRUE;
01739 }
01740 
01741 
01742 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01743 
01744 #ifdef DBUS_USE_ATOMIC_INT_486
01745 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01746 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01747 static inline dbus_int32_t
01748 atomic_exchange_and_add (DBusAtomic            *atomic,
01749                          volatile dbus_int32_t  val)
01750 {
01751   register dbus_int32_t result;
01752 
01753   __asm__ __volatile__ ("lock; xaddl %0,%1"
01754                         : "=r" (result), "=m" (atomic->value)
01755                         : "0" (val), "m" (atomic->value));
01756   return result;
01757 }
01758 #endif
01759 
01768 dbus_int32_t
01769 _dbus_atomic_inc (DBusAtomic *atomic)
01770 {
01771 #ifdef DBUS_USE_ATOMIC_INT_486
01772   return atomic_exchange_and_add (atomic, 1);
01773 #else
01774   dbus_int32_t res;
01775   _DBUS_LOCK (atomic);
01776   res = atomic->value;
01777   atomic->value += 1;
01778   _DBUS_UNLOCK (atomic);
01779   return res;
01780 #endif
01781 }
01782 
01791 dbus_int32_t
01792 _dbus_atomic_dec (DBusAtomic *atomic)
01793 {
01794 #ifdef DBUS_USE_ATOMIC_INT_486
01795   return atomic_exchange_and_add (atomic, -1);
01796 #else
01797   dbus_int32_t res;
01798   
01799   _DBUS_LOCK (atomic);
01800   res = atomic->value;
01801   atomic->value -= 1;
01802   _DBUS_UNLOCK (atomic);
01803   return res;
01804 #endif
01805 }
01806 
01807 #ifdef DBUS_BUILD_TESTS
01808 
01811 dbus_gid_t
01812 _dbus_getgid (void)
01813 {
01814   return getgid ();
01815 }
01816 #endif
01817 
01826 int
01827 _dbus_poll (DBusPollFD *fds,
01828             int         n_fds,
01829             int         timeout_milliseconds)
01830 {
01831 #ifdef HAVE_POLL
01832   /* This big thing is a constant expression and should get optimized
01833    * out of existence. So it's more robust than a configure check at
01834    * no cost.
01835    */
01836   if (_DBUS_POLLIN == POLLIN &&
01837       _DBUS_POLLPRI == POLLPRI &&
01838       _DBUS_POLLOUT == POLLOUT &&
01839       _DBUS_POLLERR == POLLERR &&
01840       _DBUS_POLLHUP == POLLHUP &&
01841       _DBUS_POLLNVAL == POLLNVAL &&
01842       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01843       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01844       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01845       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01846       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01847       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01848       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01849     {
01850       return poll ((struct pollfd*) fds,
01851                    n_fds, 
01852                    timeout_milliseconds);
01853     }
01854   else
01855     {
01856       /* We have to convert the DBusPollFD to an array of
01857        * struct pollfd, poll, and convert back.
01858        */
01859       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01860       return -1;
01861     }
01862 #else /* ! HAVE_POLL */
01863 
01864   fd_set read_set, write_set, err_set;
01865   int max_fd = 0;
01866   int i;
01867   struct timeval tv;
01868   int ready;
01869   
01870   FD_ZERO (&read_set);
01871   FD_ZERO (&write_set);
01872   FD_ZERO (&err_set);
01873 
01874   for (i = 0; i < n_fds; i++)
01875     {
01876       DBusPollFD *fdp = &fds[i];
01877 
01878       if (fdp->events & _DBUS_POLLIN)
01879         FD_SET (fdp->fd, &read_set);
01880 
01881       if (fdp->events & _DBUS_POLLOUT)
01882         FD_SET (fdp->fd, &write_set);
01883 
01884       FD_SET (fdp->fd, &err_set);
01885 
01886       max_fd = MAX (max_fd, fdp->fd);
01887     }
01888     
01889   tv.tv_sec = timeout_milliseconds / 1000;
01890   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01891 
01892   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01893                   timeout_milliseconds < 0 ? NULL : &tv);
01894 
01895   if (ready > 0)
01896     {
01897       for (i = 0; i < n_fds; i++)
01898         {
01899           DBusPollFD *fdp = &fds[i];
01900 
01901           fdp->revents = 0;
01902 
01903           if (FD_ISSET (fdp->fd, &read_set))
01904             fdp->revents |= _DBUS_POLLIN;
01905 
01906           if (FD_ISSET (fdp->fd, &write_set))
01907             fdp->revents |= _DBUS_POLLOUT;
01908 
01909           if (FD_ISSET (fdp->fd, &err_set))
01910             fdp->revents |= _DBUS_POLLERR;
01911         }
01912     }
01913 
01914   return ready;
01915 #endif
01916 }
01917 
01924 void
01925 _dbus_get_current_time (long *tv_sec,
01926                         long *tv_usec)
01927 {
01928   struct timeval t;
01929 
01930   gettimeofday (&t, NULL);
01931 
01932   if (tv_sec)
01933     *tv_sec = t.tv_sec;
01934   if (tv_usec)
01935     *tv_usec = t.tv_usec;
01936 }
01937 
01948 dbus_bool_t
01949 _dbus_file_get_contents (DBusString       *str,
01950                          const DBusString *filename,
01951                          DBusError        *error)
01952 {
01953   int fd;
01954   struct stat sb;
01955   int orig_len;
01956   int total;
01957   const char *filename_c;
01958 
01959   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01960   
01961   filename_c = _dbus_string_get_const_data (filename);
01962   
01963   /* O_BINARY useful on Cygwin */
01964   fd = open (filename_c, O_RDONLY | O_BINARY);
01965   if (fd < 0)
01966     {
01967       dbus_set_error (error, _dbus_error_from_errno (errno),
01968                       "Failed to open \"%s\": %s",
01969                       filename_c,
01970                       _dbus_strerror (errno));
01971       return FALSE;
01972     }
01973 
01974   _dbus_verbose ("file fd %d opened\n", fd);
01975   
01976   if (fstat (fd, &sb) < 0)
01977     {
01978       dbus_set_error (error, _dbus_error_from_errno (errno),
01979                       "Failed to stat \"%s\": %s",
01980                       filename_c,
01981                       _dbus_strerror (errno));
01982 
01983       _dbus_verbose ("fstat() failed: %s",
01984                      _dbus_strerror (errno));
01985       
01986       _dbus_close (fd, NULL);
01987       
01988       return FALSE;
01989     }
01990 
01991   if (sb.st_size > _DBUS_ONE_MEGABYTE)
01992     {
01993       dbus_set_error (error, DBUS_ERROR_FAILED,
01994                       "File size %lu of \"%s\" is too large.",
01995                       (unsigned long) sb.st_size, filename_c);
01996       _dbus_close (fd, NULL);
01997       return FALSE;
01998     }
01999   
02000   total = 0;
02001   orig_len = _dbus_string_get_length (str);
02002   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02003     {
02004       int bytes_read;
02005 
02006       while (total < (int) sb.st_size)
02007         {
02008           bytes_read = _dbus_read (fd, str,
02009                                    sb.st_size - total);
02010           if (bytes_read <= 0)
02011             {
02012               dbus_set_error (error, _dbus_error_from_errno (errno),
02013                               "Error reading \"%s\": %s",
02014                               filename_c,
02015                               _dbus_strerror (errno));
02016 
02017               _dbus_verbose ("read() failed: %s",
02018                              _dbus_strerror (errno));
02019               
02020               _dbus_close (fd, NULL);
02021               _dbus_string_set_length (str, orig_len);
02022               return FALSE;
02023             }
02024           else
02025             total += bytes_read;
02026         }
02027 
02028       _dbus_close (fd, NULL);
02029       return TRUE;
02030     }
02031   else if (sb.st_size != 0)
02032     {
02033       _dbus_verbose ("Can only open regular files at the moment.\n");
02034       dbus_set_error (error, DBUS_ERROR_FAILED,
02035                       "\"%s\" is not a regular file",
02036                       filename_c);
02037       _dbus_close (fd, NULL);
02038       return FALSE;
02039     }
02040   else
02041     {
02042       _dbus_close (fd, NULL);
02043       return TRUE;
02044     }
02045 }
02046 
02056 dbus_bool_t
02057 _dbus_string_save_to_file (const DBusString *str,
02058                            const DBusString *filename,
02059                            DBusError        *error)
02060 {
02061   int fd;
02062   int bytes_to_write;
02063   const char *filename_c;
02064   DBusString tmp_filename;
02065   const char *tmp_filename_c;
02066   int total;
02067   dbus_bool_t need_unlink;
02068   dbus_bool_t retval;
02069 
02070   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02071   
02072   fd = -1;
02073   retval = FALSE;
02074   need_unlink = FALSE;
02075   
02076   if (!_dbus_string_init (&tmp_filename))
02077     {
02078       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02079       return FALSE;
02080     }
02081 
02082   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02083     {
02084       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02085       _dbus_string_free (&tmp_filename);
02086       return FALSE;
02087     }
02088   
02089   if (!_dbus_string_append (&tmp_filename, "."))
02090     {
02091       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02092       _dbus_string_free (&tmp_filename);
02093       return FALSE;
02094     }
02095 
02096 #define N_TMP_FILENAME_RANDOM_BYTES 8
02097   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02098     {
02099       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02100       _dbus_string_free (&tmp_filename);
02101       return FALSE;
02102     }
02103     
02104   filename_c = _dbus_string_get_const_data (filename);
02105   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02106 
02107   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02108              0600);
02109   if (fd < 0)
02110     {
02111       dbus_set_error (error, _dbus_error_from_errno (errno),
02112                       "Could not create %s: %s", tmp_filename_c,
02113                       _dbus_strerror (errno));
02114       goto out;
02115     }
02116 
02117   _dbus_verbose ("tmp file fd %d opened\n", fd);
02118   
02119   need_unlink = TRUE;
02120   
02121   total = 0;
02122   bytes_to_write = _dbus_string_get_length (str);
02123 
02124   while (total < bytes_to_write)
02125     {
02126       int bytes_written;
02127 
02128       bytes_written = _dbus_write (fd, str, total,
02129                                    bytes_to_write - total);
02130 
02131       if (bytes_written <= 0)
02132         {
02133           dbus_set_error (error, _dbus_error_from_errno (errno),
02134                           "Could not write to %s: %s", tmp_filename_c,
02135                           _dbus_strerror (errno));
02136           
02137           goto out;
02138         }
02139 
02140       total += bytes_written;
02141     }
02142 
02143   if (!_dbus_close (fd, NULL))
02144     {
02145       dbus_set_error (error, _dbus_error_from_errno (errno),
02146                       "Could not close file %s: %s",
02147                       tmp_filename_c, _dbus_strerror (errno));
02148 
02149       goto out;
02150     }
02151 
02152   fd = -1;
02153   
02154   if (rename (tmp_filename_c, filename_c) < 0)
02155     {
02156       dbus_set_error (error, _dbus_error_from_errno (errno),
02157                       "Could not rename %s to %s: %s",
02158                       tmp_filename_c, filename_c,
02159                       _dbus_strerror (errno));
02160 
02161       goto out;
02162     }
02163 
02164   need_unlink = FALSE;
02165   
02166   retval = TRUE;
02167   
02168  out:
02169   /* close first, then unlink, to prevent ".nfs34234235" garbage
02170    * files
02171    */
02172 
02173   if (fd >= 0)
02174     _dbus_close (fd, NULL);
02175         
02176   if (need_unlink && unlink (tmp_filename_c) < 0)
02177     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02178                    tmp_filename_c, _dbus_strerror (errno));
02179 
02180   _dbus_string_free (&tmp_filename);
02181 
02182   if (!retval)
02183     _DBUS_ASSERT_ERROR_IS_SET (error);
02184   
02185   return retval;
02186 }
02187 
02194 dbus_bool_t
02195 _dbus_make_file_world_readable(const DBusString *filename,
02196                                DBusError *error)
02197 {
02198   const char *filename_c;
02199 
02200   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02201 
02202   filename_c = _dbus_string_get_const_data (filename);
02203   if (chmod (filename_c, 0644) == -1)
02204     {
02205       dbus_set_error (error,
02206                       DBUS_ERROR_FAILED,
02207                       "Could not change permissions of file %s: %s\n",
02208                       filename_c,
02209                       _dbus_strerror (errno));
02210       return FALSE;
02211     }
02212   return TRUE;
02213 }
02214 
02221 dbus_bool_t
02222 _dbus_create_file_exclusively (const DBusString *filename,
02223                                DBusError        *error)
02224 {
02225   int fd;
02226   const char *filename_c;
02227 
02228   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02229   
02230   filename_c = _dbus_string_get_const_data (filename);
02231   
02232   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02233              0600);
02234   if (fd < 0)
02235     {
02236       dbus_set_error (error,
02237                       DBUS_ERROR_FAILED,
02238                       "Could not create file %s: %s\n",
02239                       filename_c,
02240                       _dbus_strerror (errno));
02241       return FALSE;
02242     }
02243 
02244   _dbus_verbose ("exclusive file fd %d opened\n", fd);
02245   
02246   if (!_dbus_close (fd, NULL))
02247     {
02248       dbus_set_error (error,
02249                       DBUS_ERROR_FAILED,
02250                       "Could not close file %s: %s\n",
02251                       filename_c,
02252                       _dbus_strerror (errno));
02253       return FALSE;
02254     }
02255   
02256   return TRUE;
02257 }
02258 
02267 dbus_bool_t
02268 _dbus_delete_file (const DBusString *filename,
02269                    DBusError        *error)
02270 {
02271   const char *filename_c;
02272 
02273   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02274   
02275   filename_c = _dbus_string_get_const_data (filename);
02276 
02277   if (unlink (filename_c) < 0)
02278     {
02279       dbus_set_error (error, DBUS_ERROR_FAILED,
02280                       "Failed to delete file %s: %s\n",
02281                       filename_c, _dbus_strerror (errno));
02282       return FALSE;
02283     }
02284   else
02285     return TRUE;
02286 }
02287 
02296 dbus_bool_t
02297 _dbus_create_directory (const DBusString *filename,
02298                         DBusError        *error)
02299 {
02300   const char *filename_c;
02301 
02302   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02303   
02304   filename_c = _dbus_string_get_const_data (filename);
02305 
02306   if (mkdir (filename_c, 0700) < 0)
02307     {
02308       if (errno == EEXIST)
02309         return TRUE;
02310       
02311       dbus_set_error (error, DBUS_ERROR_FAILED,
02312                       "Failed to create directory %s: %s\n",
02313                       filename_c, _dbus_strerror (errno));
02314       return FALSE;
02315     }
02316   else
02317     return TRUE;
02318 }
02319 
02330 dbus_bool_t
02331 _dbus_concat_dir_and_file (DBusString       *dir,
02332                            const DBusString *next_component)
02333 {
02334   dbus_bool_t dir_ends_in_slash;
02335   dbus_bool_t file_starts_with_slash;
02336 
02337   if (_dbus_string_get_length (dir) == 0 ||
02338       _dbus_string_get_length (next_component) == 0)
02339     return TRUE;
02340   
02341   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02342                                                     _dbus_string_get_length (dir) - 1);
02343 
02344   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02345 
02346   if (dir_ends_in_slash && file_starts_with_slash)
02347     {
02348       _dbus_string_shorten (dir, 1);
02349     }
02350   else if (!(dir_ends_in_slash || file_starts_with_slash))
02351     {
02352       if (!_dbus_string_append_byte (dir, '/'))
02353         return FALSE;
02354     }
02355 
02356   return _dbus_string_copy (next_component, 0, dir,
02357                             _dbus_string_get_length (dir));
02358 }
02359 
02361 #define NANOSECONDS_PER_SECOND       1000000000
02362 
02363 #define MICROSECONDS_PER_SECOND      1000000
02364 
02365 #define MILLISECONDS_PER_SECOND      1000
02366 
02367 #define NANOSECONDS_PER_MILLISECOND  1000000
02368 
02369 #define MICROSECONDS_PER_MILLISECOND 1000
02370 
02375 void
02376 _dbus_sleep_milliseconds (int milliseconds)
02377 {
02378 #ifdef HAVE_NANOSLEEP
02379   struct timespec req;
02380   struct timespec rem;
02381 
02382   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02383   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02384   rem.tv_sec = 0;
02385   rem.tv_nsec = 0;
02386 
02387   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02388     req = rem;
02389 #elif defined (HAVE_USLEEP)
02390   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02391 #else /* ! HAVE_USLEEP */
02392   sleep (MAX (milliseconds / 1000, 1));
02393 #endif
02394 }
02395 
02396 static dbus_bool_t
02397 _dbus_generate_pseudorandom_bytes (DBusString *str,
02398                                    int         n_bytes)
02399 {
02400   int old_len;
02401   char *p;
02402   
02403   old_len = _dbus_string_get_length (str);
02404 
02405   if (!_dbus_string_lengthen (str, n_bytes))
02406     return FALSE;
02407 
02408   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02409 
02410   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02411 
02412   return TRUE;
02413 }
02414 
02423 dbus_bool_t
02424 _dbus_generate_random_bytes (DBusString *str,
02425                              int         n_bytes)
02426 {
02427   int old_len;
02428   int fd;
02429 
02430   /* FALSE return means "no memory", if it could
02431    * mean something else then we'd need to return
02432    * a DBusError. So we always fall back to pseudorandom
02433    * if the I/O fails.
02434    */
02435   
02436   old_len = _dbus_string_get_length (str);
02437   fd = -1;
02438 
02439   /* note, urandom on linux will fall back to pseudorandom */
02440   fd = open ("/dev/urandom", O_RDONLY);
02441   if (fd < 0)
02442     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02443 
02444   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02445   
02446   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02447     {
02448       _dbus_close (fd, NULL);
02449       _dbus_string_set_length (str, old_len);
02450       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02451     }
02452 
02453   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02454                  n_bytes);
02455   
02456   _dbus_close (fd, NULL);
02457   
02458   return TRUE;
02459 }
02460 
02466 void
02467 _dbus_exit (int code)
02468 {
02469   _exit (code);
02470 }
02471 
02480 const char*
02481 _dbus_strerror (int error_number)
02482 {
02483   const char *msg;
02484   
02485   msg = strerror (error_number);
02486   if (msg == NULL)
02487     msg = "unknown";
02488 
02489   return msg;
02490 }
02491 
02495 void
02496 _dbus_disable_sigpipe (void)
02497 {
02498   signal (SIGPIPE, SIG_IGN);
02499 }
02500 
02508 void
02509 _dbus_fd_set_close_on_exec (int fd)
02510 {
02511   int val;
02512   
02513   val = fcntl (fd, F_GETFD, 0);
02514   
02515   if (val < 0)
02516     return;
02517 
02518   val |= FD_CLOEXEC;
02519   
02520   fcntl (fd, F_SETFD, val);
02521 }
02522 
02530 dbus_bool_t
02531 _dbus_close (int        fd,
02532              DBusError *error)
02533 {
02534   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02535   
02536  again:
02537   if (close (fd) < 0)
02538     {
02539       if (errno == EINTR)
02540         goto again;
02541 
02542       dbus_set_error (error, _dbus_error_from_errno (errno),
02543                       "Could not close fd %d", fd);
02544       return FALSE;
02545     }
02546 
02547   return TRUE;
02548 }
02549 
02557 dbus_bool_t
02558 _dbus_set_fd_nonblocking (int             fd,
02559                           DBusError      *error)
02560 {
02561   int val;
02562 
02563   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02564   
02565   val = fcntl (fd, F_GETFL, 0);
02566   if (val < 0)
02567     {
02568       dbus_set_error (error, _dbus_error_from_errno (errno),
02569                       "Failed to get flags from file descriptor %d: %s",
02570                       fd, _dbus_strerror (errno));
02571       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02572                      _dbus_strerror (errno));
02573       return FALSE;
02574     }
02575 
02576   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02577     {
02578       dbus_set_error (error, _dbus_error_from_errno (errno),
02579                       "Failed to set nonblocking flag of file descriptor %d: %s",
02580                       fd, _dbus_strerror (errno));
02581       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02582                      fd, _dbus_strerror (errno));
02583 
02584       return FALSE;
02585     }
02586 
02587   return TRUE;
02588 }
02589 
02595 void
02596 _dbus_print_backtrace (void)
02597 {  
02598 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02599   void *bt[500];
02600   int bt_size;
02601   int i;
02602   char **syms;
02603   
02604   bt_size = backtrace (bt, 500);
02605 
02606   syms = backtrace_symbols (bt, bt_size);
02607   
02608   i = 0;
02609   while (i < bt_size)
02610     {
02611       /* don't use dbus_warn since it can _dbus_abort() */
02612       fprintf (stderr, "  %s\n", syms[i]);
02613       ++i;
02614     }
02615   fflush (stderr);
02616 
02617   free (syms);
02618 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02619   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02620 #else
02621   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02622 #endif
02623 }
02624 
02640 dbus_bool_t
02641 _dbus_full_duplex_pipe (int        *fd1,
02642                         int        *fd2,
02643                         dbus_bool_t blocking,
02644                         DBusError  *error)
02645 {
02646 #ifdef HAVE_SOCKETPAIR
02647   int fds[2];
02648 
02649   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02650   
02651   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02652     {
02653       dbus_set_error (error, _dbus_error_from_errno (errno),
02654                       "Could not create full-duplex pipe");
02655       return FALSE;
02656     }
02657 
02658   if (!blocking &&
02659       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02660        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02661     {
02662       dbus_set_error (error, _dbus_error_from_errno (errno),
02663                       "Could not set full-duplex pipe nonblocking");
02664       
02665       _dbus_close (fds[0], NULL);
02666       _dbus_close (fds[1], NULL);
02667       
02668       return FALSE;
02669     }
02670   
02671   *fd1 = fds[0];
02672   *fd2 = fds[1];
02673 
02674   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02675                  *fd1, *fd2);
02676   
02677   return TRUE;  
02678 #else
02679   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02680   dbus_set_error (error, DBUS_ERROR_FAILED,
02681                   "_dbus_full_duplex_pipe() not implemented on this OS");
02682   return FALSE;
02683 #endif
02684 }
02685 
02686 
02695 int
02696 _dbus_printf_string_upper_bound (const char *format,
02697                                  va_list     args)
02698 {
02699   char c;
02700   return vsnprintf (&c, 1, format, args);
02701 }
02702 
02709 const char*
02710 _dbus_get_tmpdir(void)
02711 {
02712   static const char* tmpdir = NULL;
02713 
02714   if (tmpdir == NULL)
02715     {
02716       /* TMPDIR is what glibc uses, then
02717        * glibc falls back to the P_tmpdir macro which
02718        * just expands to "/tmp"
02719        */
02720       if (tmpdir == NULL)
02721         tmpdir = getenv("TMPDIR");
02722 
02723       /* These two env variables are probably
02724        * broken, but maybe some OS uses them?
02725        */
02726       if (tmpdir == NULL)
02727         tmpdir = getenv("TMP");
02728       if (tmpdir == NULL)
02729         tmpdir = getenv("TEMP");
02730 
02731       /* And this is the sane fallback. */
02732       if (tmpdir == NULL)
02733         tmpdir = "/tmp";
02734     }
02735   
02736   _dbus_assert(tmpdir != NULL);
02737   
02738   return tmpdir;
02739 }
02740 
02753 dbus_bool_t
02754 _dbus_get_autolaunch_address (DBusString *address,
02755                               DBusError  *error)
02756 {
02757   static char *argv[6];
02758   int address_pipe[2] = { -1, -1 };
02759   int errors_pipe[2] = { -1, -1 };
02760   pid_t pid;
02761   int ret;
02762   int status;
02763   int orig_len;
02764   int i;
02765   DBusString uuid;
02766   dbus_bool_t retval;
02767   
02768   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02769   retval = FALSE;
02770 
02771   _dbus_string_init (&uuid);
02772   
02773   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02774     {
02775       _DBUS_SET_OOM (error);
02776       goto out;
02777     }
02778   
02779   i = 0;
02780   argv[i] = "dbus-launch";
02781   ++i;
02782   argv[i] = "--autolaunch";
02783   ++i;
02784   argv[i] = _dbus_string_get_data (&uuid);
02785   ++i;
02786   argv[i] = "--binary-syntax";
02787   ++i;
02788   argv[i] = "--close-stderr";
02789   ++i;
02790   argv[i] = NULL;
02791   ++i;
02792 
02793   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02794   
02795   orig_len = _dbus_string_get_length (address);
02796   
02797 #define READ_END        0
02798 #define WRITE_END       1
02799   if (pipe (address_pipe) < 0)
02800     {
02801       dbus_set_error (error, _dbus_error_from_errno (errno),
02802                       "Failed to create a pipe: %s",
02803                       _dbus_strerror (errno));
02804       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02805                      _dbus_strerror (errno));
02806       goto out;
02807     }
02808   if (pipe (errors_pipe) < 0)
02809     {
02810       dbus_set_error (error, _dbus_error_from_errno (errno),
02811                       "Failed to create a pipe: %s",
02812                       _dbus_strerror (errno));
02813       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02814                      _dbus_strerror (errno));
02815       goto out;
02816     }
02817 
02818   pid = fork ();
02819   if (pid < 0)
02820     {
02821       dbus_set_error (error, _dbus_error_from_errno (errno),
02822                       "Failed to fork(): %s",
02823                       _dbus_strerror (errno));
02824       _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02825                      _dbus_strerror (errno));
02826       goto out;
02827     }
02828 
02829   if (pid == 0)
02830     {
02831       /* child process */
02832       int fd = open ("/dev/null", O_RDWR);
02833       if (fd == -1)
02834         /* huh?! can't open /dev/null? */
02835         _exit (1);
02836 
02837       _dbus_verbose ("/dev/null fd %d opened\n", fd);
02838       
02839       /* set-up stdXXX */
02840       close (address_pipe[READ_END]);
02841       close (errors_pipe[READ_END]);
02842       close (0);                /* close stdin */
02843       close (1);                /* close stdout */
02844       close (2);                /* close stderr */
02845 
02846       if (dup2 (fd, 0) == -1)
02847         _exit (1);
02848       if (dup2 (address_pipe[WRITE_END], 1) == -1)
02849         _exit (1);
02850       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02851         _exit (1);
02852 
02853       close (fd);
02854       close (address_pipe[WRITE_END]);
02855       close (errors_pipe[WRITE_END]);
02856 
02857       execv (DBUS_BINDIR "/dbus-launch", argv);
02858 
02859       /* failed, try searching PATH */
02860       execvp ("dbus-launch", argv);
02861 
02862       /* still nothing, we failed */
02863       _exit (1);
02864     }
02865 
02866   /* parent process */
02867   close (address_pipe[WRITE_END]);
02868   close (errors_pipe[WRITE_END]);
02869   address_pipe[WRITE_END] = -1;
02870   errors_pipe[WRITE_END] = -1;
02871 
02872   ret = 0;
02873   do 
02874     {
02875       ret = _dbus_read (address_pipe[READ_END], address, 1024);
02876     }
02877   while (ret > 0);
02878 
02879   /* reap the child process to avoid it lingering as zombie */
02880   do
02881     {
02882       ret = waitpid (pid, &status, 0);
02883     }
02884   while (ret == -1 && errno == EINTR);
02885 
02886   /* We succeeded if the process exited with status 0 and
02887      anything was read */
02888   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02889       _dbus_string_get_length (address) == orig_len)
02890     {
02891       /* The process ended with error */
02892       DBusString error_message;
02893       _dbus_string_init (&error_message);
02894       ret = 0;
02895       do
02896         {
02897           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
02898         }
02899       while (ret > 0);
02900 
02901       _dbus_string_set_length (address, orig_len);
02902       if (_dbus_string_get_length (&error_message) > 0)
02903         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02904                         "dbus-launch failed to autolaunch D-Bus session: %s",
02905                         _dbus_string_get_data (&error_message));
02906       else
02907         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02908                         "Failed to execute dbus-launch to autolaunch D-Bus session");
02909       goto out;
02910     }
02911 
02912   retval = TRUE;
02913   
02914  out:
02915   if (retval)
02916     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02917   else
02918     _DBUS_ASSERT_ERROR_IS_SET (error);
02919 
02920   if (address_pipe[0] != -1)
02921     close (address_pipe[0]);
02922   if (address_pipe[1] != -1)
02923     close (address_pipe[1]);
02924   if (errors_pipe[0] != -1)
02925     close (errors_pipe[0]);
02926   if (errors_pipe[1] != -1)
02927     close (errors_pipe[1]);
02928 
02929   _dbus_string_free (&uuid);
02930   return retval;
02931 }
02932 
02951 dbus_bool_t
02952 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
02953                                dbus_bool_t create_if_not_found,
02954                                DBusError  *error)
02955 {
02956   DBusString filename;
02957   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
02958   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
02959 }
02960 
02961 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
02962 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
02963 
02964 
02982 dbus_bool_t 
02983 _dbus_get_standard_session_servicedirs (DBusList **dirs)
02984 {
02985   const char *xdg_data_home;
02986   const char *xdg_data_dirs;
02987   DBusString servicedir_path;
02988 
02989   if (!_dbus_string_init (&servicedir_path))
02990     return FALSE;
02991 
02992   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
02993   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
02994 
02995   if (xdg_data_dirs != NULL)
02996     {
02997       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
02998         goto oom;
02999 
03000       if (!_dbus_string_append (&servicedir_path, ":"))
03001         goto oom;
03002     }
03003   else
03004     {
03005       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03006         goto oom;
03007     }
03008 
03009   /* 
03010    * add configured datadir to defaults
03011    * this may be the same as an xdg dir
03012    * however the config parser should take 
03013    * care of duplicates 
03014    */
03015   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03016         goto oom;
03017 
03018   if (xdg_data_home != NULL)
03019     {
03020       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03021         goto oom;
03022     }
03023   else
03024     {
03025       const DBusString *homedir;
03026       DBusString local_share;
03027 
03028       if (!_dbus_homedir_from_current_process (&homedir))
03029         goto oom;
03030        
03031       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03032         goto oom;
03033 
03034       _dbus_string_init_const (&local_share, "/.local/share");
03035       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03036         goto oom;
03037     }
03038 
03039   if (!_dbus_split_paths_and_append (&servicedir_path, 
03040                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 
03041                                      dirs))
03042     goto oom;
03043 
03044   _dbus_string_free (&servicedir_path);  
03045   return TRUE;
03046 
03047  oom:
03048   _dbus_string_free (&servicedir_path);
03049   return FALSE;
03050 }
03051 
03052 
03071 dbus_bool_t 
03072 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03073 {
03074   const char *xdg_data_dirs;
03075   DBusString servicedir_path;
03076 
03077   if (!_dbus_string_init (&servicedir_path))
03078     return FALSE;
03079 
03080   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03081 
03082   if (xdg_data_dirs != NULL)
03083     {
03084       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03085         goto oom;
03086 
03087       if (!_dbus_string_append (&servicedir_path, ":"))
03088         goto oom;
03089     }
03090   else
03091     {
03092       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03093         goto oom;
03094     }
03095 
03096   /* 
03097    * add configured datadir to defaults
03098    * this may be the same as an xdg dir
03099    * however the config parser should take 
03100    * care of duplicates 
03101    */
03102   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03103         goto oom;
03104 
03105   if (!_dbus_split_paths_and_append (&servicedir_path, 
03106                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 
03107                                      dirs))
03108     goto oom;
03109 
03110   _dbus_string_free (&servicedir_path);  
03111   return TRUE;
03112 
03113  oom:
03114   _dbus_string_free (&servicedir_path);
03115   return FALSE;
03116 }
03117 
03126 dbus_bool_t
03127 _dbus_append_system_config_file (DBusString *str)
03128 {
03129   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03130 }
03131 
03138 dbus_bool_t
03139 _dbus_append_session_config_file (DBusString *str)
03140 {
03141   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03142 }
03143 
03151 void
03152 _dbus_flush_caches (void)
03153 {
03154   _dbus_user_database_flush_system ();
03155 }
03156 
03170 dbus_bool_t
03171 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03172                                                 DBusCredentials *credentials)
03173 {
03174   DBusString homedir;
03175   DBusString dotdir;
03176   dbus_uid_t uid;
03177   
03178   _dbus_assert (credentials != NULL);
03179   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03180   
03181   if (!_dbus_string_init (&homedir))
03182     return FALSE;
03183 
03184   uid = _dbus_credentials_get_unix_uid (credentials);
03185   _dbus_assert (uid != DBUS_UID_UNSET);
03186 
03187   if (!_dbus_homedir_from_uid (uid, &homedir))
03188     goto failed;
03189   
03190 #ifdef DBUS_BUILD_TESTS
03191   {
03192     const char *override;
03193     
03194     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03195     if (override != NULL && *override != '\0')
03196       {
03197         _dbus_string_set_length (&homedir, 0);
03198         if (!_dbus_string_append (&homedir, override))
03199           goto failed;
03200 
03201         _dbus_verbose ("Using fake homedir for testing: %s\n",
03202                        _dbus_string_get_const_data (&homedir));
03203       }
03204     else
03205       {
03206         static dbus_bool_t already_warned = FALSE;
03207         if (!already_warned)
03208           {
03209             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03210             already_warned = TRUE;
03211           }
03212       }
03213   }
03214 #endif
03215 
03216   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03217   if (!_dbus_concat_dir_and_file (&homedir,
03218                                   &dotdir))
03219     goto failed;
03220   
03221   if (!_dbus_string_copy (&homedir, 0,
03222                           directory, _dbus_string_get_length (directory))) {
03223     goto failed;
03224   }
03225 
03226   _dbus_string_free (&homedir);
03227   return TRUE;
03228   
03229  failed: 
03230   _dbus_string_free (&homedir);
03231   return FALSE;
03232 }
03233 
03234 
03241 dbus_bool_t
03242 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03243 {
03244   return errno == EAGAIN || errno == EWOULDBLOCK;
03245 }
03246 
03247 /* tests in dbus-sysdeps-util.c */

Generated on Mon Dec 14 22:26:12 2009 for D-Bus by  doxygen 1.4.7