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

Generated on Sun May 18 18:21:01 2008 for D-Bus by  doxygen 1.5.2