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

Generated on Sat Jun 14 22:43:04 2008 for D-Bus by  doxygen 1.4.6