dbus-sysdeps.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-protocol.h"
00029 #include "dbus-string.h"
00030 #include <sys/types.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <signal.h>
00034 #include <unistd.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <fcntl.h>
00038 #include <sys/socket.h>
00039 #include <dirent.h>
00040 #include <sys/un.h>
00041 #include <pwd.h>
00042 #include <time.h>
00043 #include <locale.h>
00044 #include <sys/time.h>
00045 #include <sys/stat.h>
00046 #include <sys/wait.h>
00047 #include <netinet/in.h>
00048 #include <netdb.h>
00049 #include <grp.h>
00050 
00051 #ifdef HAVE_WRITEV
00052 #include <sys/uio.h>
00053 #endif
00054 #ifdef HAVE_POLL
00055 #include <sys/poll.h>
00056 #endif
00057 #ifdef HAVE_BACKTRACE
00058 #include <execinfo.h>
00059 #endif
00060 #ifdef HAVE_GETPEERUCRED
00061 #include <ucred.h>
00062 #endif
00063 
00064 #ifndef O_BINARY
00065 #define O_BINARY 0
00066 #endif
00067 
00068 #ifndef HAVE_SOCKLEN_T
00069 #define socklen_t int
00070 #endif
00071 
00076 #ifndef DBUS_DISABLE_ASSERT
00077 
00080 void
00081 _dbus_abort (void)
00082 {
00083 #ifdef DBUS_ENABLE_VERBOSE_MODE
00084   const char *s;
00085   s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00086   if (s && *s)
00087     _dbus_print_backtrace ();
00088 #endif
00089   abort ();
00090   _exit (1); /* in case someone manages to ignore SIGABRT */
00091 }
00092 #endif
00093 
00105 dbus_bool_t
00106 _dbus_setenv (const char *varname,
00107               const char *value)
00108 {
00109   _dbus_assert (varname != NULL);
00110   
00111   if (value == NULL)
00112     {
00113 #ifdef HAVE_UNSETENV
00114       unsetenv (varname);
00115       return TRUE;
00116 #else
00117       char *putenv_value;
00118       size_t len;
00119 
00120       len = strlen (varname);
00121 
00122       /* Use system malloc to avoid memleaks that dbus_malloc
00123        * will get upset about.
00124        */
00125       
00126       putenv_value = malloc (len + 1);
00127       if (putenv_value == NULL)
00128         return FALSE;
00129 
00130       strcpy (putenv_value, varname);
00131       
00132       return (putenv (putenv_value) == 0);
00133 #endif
00134     }
00135   else
00136     {
00137 #ifdef HAVE_SETENV
00138       return (setenv (varname, value, TRUE) == 0);
00139 #else
00140       char *putenv_value;
00141       size_t len;
00142       size_t varname_len;
00143       size_t value_len;
00144 
00145       varname_len = strlen (varname);
00146       value_len = strlen (value);
00147       
00148       len = varname_len + value_len + 1 /* '=' */ ;
00149 
00150       /* Use system malloc to avoid memleaks that dbus_malloc
00151        * will get upset about.
00152        */
00153       
00154       putenv_value = malloc (len + 1);
00155       if (putenv_value == NULL)
00156         return FALSE;
00157 
00158       strcpy (putenv_value, varname);
00159       strcpy (putenv_value + varname_len, "=");
00160       strcpy (putenv_value + varname_len + 1, value);
00161       
00162       return (putenv (putenv_value) == 0);
00163 #endif
00164     }
00165 }
00166 
00173 const char*
00174 _dbus_getenv (const char *varname)
00175 {  
00176   return getenv (varname);
00177 }
00178 
00192 int
00193 _dbus_read (int               fd,
00194             DBusString       *buffer,
00195             int               count)
00196 {
00197   int bytes_read;
00198   int start;
00199   char *data;
00200 
00201   _dbus_assert (count >= 0);
00202   
00203   start = _dbus_string_get_length (buffer);
00204 
00205   if (!_dbus_string_lengthen (buffer, count))
00206     {
00207       errno = ENOMEM;
00208       return -1;
00209     }
00210 
00211   data = _dbus_string_get_data_len (buffer, start, count);
00212 
00213  again:
00214   
00215   bytes_read = read (fd, data, count);
00216 
00217   if (bytes_read < 0)
00218     {
00219       if (errno == EINTR)
00220         goto again;
00221       else
00222         {
00223           /* put length back (note that this doesn't actually realloc anything) */
00224           _dbus_string_set_length (buffer, start);
00225           return -1;
00226         }
00227     }
00228   else
00229     {
00230       /* put length back (doesn't actually realloc) */
00231       _dbus_string_set_length (buffer, start + bytes_read);
00232 
00233 #if 0
00234       if (bytes_read > 0)
00235         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00236 #endif
00237       
00238       return bytes_read;
00239     }
00240 }
00241 
00252 int
00253 _dbus_write (int               fd,
00254              const DBusString *buffer,
00255              int               start,
00256              int               len)
00257 {
00258   const char *data;
00259   int bytes_written;
00260   
00261   data = _dbus_string_get_const_data_len (buffer, start, len);
00262   
00263  again:
00264 
00265   bytes_written = write (fd, data, len);
00266 
00267   if (bytes_written < 0 && errno == EINTR)
00268     goto again;
00269 
00270 #if 0
00271   if (bytes_written > 0)
00272     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00273 #endif
00274   
00275   return bytes_written;
00276 }
00277 
00298 int
00299 _dbus_write_two (int               fd,
00300                  const DBusString *buffer1,
00301                  int               start1,
00302                  int               len1,
00303                  const DBusString *buffer2,
00304                  int               start2,
00305                  int               len2)
00306 {
00307   _dbus_assert (buffer1 != NULL);
00308   _dbus_assert (start1 >= 0);
00309   _dbus_assert (start2 >= 0);
00310   _dbus_assert (len1 >= 0);
00311   _dbus_assert (len2 >= 0);
00312   
00313 #ifdef HAVE_WRITEV
00314   {
00315     struct iovec vectors[2];
00316     const char *data1;
00317     const char *data2;
00318     int bytes_written;
00319 
00320     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00321 
00322     if (buffer2 != NULL)
00323       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00324     else
00325       {
00326         data2 = NULL;
00327         start2 = 0;
00328         len2 = 0;
00329       }
00330    
00331     vectors[0].iov_base = (char*) data1;
00332     vectors[0].iov_len = len1;
00333     vectors[1].iov_base = (char*) data2;
00334     vectors[1].iov_len = len2;
00335 
00336   again:
00337    
00338     bytes_written = writev (fd,
00339                             vectors,
00340                             data2 ? 2 : 1);
00341 
00342     if (bytes_written < 0 && errno == EINTR)
00343       goto again;
00344    
00345     return bytes_written;
00346   }
00347 #else /* HAVE_WRITEV */
00348   {
00349     int ret1;
00350     
00351     ret1 = _dbus_write (fd, buffer1, start1, len1);
00352     if (ret1 == len1 && buffer2 != NULL)
00353       {
00354         ret2 = _dbus_write (fd, buffer2, start2, len2);
00355         if (ret2 < 0)
00356           ret2 = 0; /* we can't report an error as the first write was OK */
00357        
00358         return ret1 + ret2;
00359       }
00360     else
00361       return ret1;
00362   }
00363 #endif /* !HAVE_WRITEV */   
00364 }
00365 
00366 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00367 
00395 int
00396 _dbus_connect_unix_socket (const char     *path,
00397                            dbus_bool_t     abstract,
00398                            DBusError      *error)
00399 {
00400   int fd;
00401   size_t path_len;
00402   struct sockaddr_un addr;  
00403 
00404   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00405 
00406   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00407                  path, abstract);
00408   
00409   fd = socket (PF_UNIX, SOCK_STREAM, 0);
00410   
00411   if (fd < 0)
00412     {
00413       dbus_set_error (error,
00414                       _dbus_error_from_errno (errno),
00415                       "Failed to create socket: %s",
00416                       _dbus_strerror (errno)); 
00417       
00418       return -1;
00419     }
00420 
00421   _DBUS_ZERO (addr);
00422   addr.sun_family = AF_UNIX;
00423   path_len = strlen (path);
00424 
00425   if (abstract)
00426     {
00427 #ifdef HAVE_ABSTRACT_SOCKETS
00428       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00429       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00430 
00431       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00432         {
00433           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00434                       "Abstract socket name too long\n");
00435           close (fd);
00436           return -1;
00437         }
00438         
00439       strncpy (&addr.sun_path[1], path, path_len);
00440       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00441 #else /* HAVE_ABSTRACT_SOCKETS */
00442       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00443                       "Operating system does not support abstract socket namespace\n");
00444       close (fd);
00445       return -1;
00446 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00447     }
00448   else
00449     {
00450       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00451         {
00452           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00453                       "Socket name too long\n");
00454           close (fd);
00455           return -1;
00456         }
00457 
00458       strncpy (addr.sun_path, path, path_len);
00459     }
00460   
00461   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00462     {      
00463       dbus_set_error (error,
00464                       _dbus_error_from_errno (errno),
00465                       "Failed to connect to socket %s: %s",
00466                       path, _dbus_strerror (errno));
00467 
00468       close (fd);
00469       fd = -1;
00470       
00471       return -1;
00472     }
00473 
00474   if (!_dbus_set_fd_nonblocking (fd, error))
00475     {
00476       _DBUS_ASSERT_ERROR_IS_SET (error);
00477       
00478       close (fd);
00479       fd = -1;
00480 
00481       return -1;
00482     }
00483 
00484   return fd;
00485 }
00486 
00502 int
00503 _dbus_listen_unix_socket (const char     *path,
00504                           dbus_bool_t     abstract,
00505                           DBusError      *error)
00506 {
00507   int listen_fd;
00508   struct sockaddr_un addr;
00509   size_t path_len;
00510 
00511   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00512 
00513   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00514                  path, abstract);
00515   
00516   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00517   
00518   if (listen_fd < 0)
00519     {
00520       dbus_set_error (error, _dbus_error_from_errno (errno),
00521                       "Failed to create socket \"%s\": %s",
00522                       path, _dbus_strerror (errno));
00523       return -1;
00524     }
00525 
00526   _DBUS_ZERO (addr);
00527   addr.sun_family = AF_UNIX;
00528   path_len = strlen (path);
00529   
00530   if (abstract)
00531     {
00532 #ifdef HAVE_ABSTRACT_SOCKETS
00533       /* remember that abstract names aren't nul-terminated so we rely
00534        * on sun_path being filled in with zeroes above.
00535        */
00536       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00537       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00538 
00539       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00540         {
00541           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00542                       "Abstract socket name too long\n");
00543           close (listen_fd);
00544           return -1;
00545         }
00546       
00547       strncpy (&addr.sun_path[1], path, path_len);
00548       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00549 #else /* HAVE_ABSTRACT_SOCKETS */
00550       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00551                       "Operating system does not support abstract socket namespace\n");
00552       close (listen_fd);
00553       return -1;
00554 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00555     }
00556   else
00557     {
00558       /* FIXME discussed security implications of this with Nalin,
00559        * and we couldn't think of where it would kick our ass, but
00560        * it still seems a bit sucky. It also has non-security suckage;
00561        * really we'd prefer to exit if the socket is already in use.
00562        * But there doesn't seem to be a good way to do this.
00563        *
00564        * Just to be extra careful, I threw in the stat() - clearly
00565        * the stat() can't *fix* any security issue, but it at least
00566        * avoids inadvertent/accidental data loss.
00567        */
00568       {
00569         struct stat sb;
00570 
00571         if (stat (path, &sb) == 0 &&
00572             S_ISSOCK (sb.st_mode))
00573           unlink (path);
00574       }
00575 
00576       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00577         {
00578           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00579                       "Abstract socket name too long\n");
00580           close (listen_fd);
00581           return -1;
00582         }
00583         
00584       strncpy (addr.sun_path, path, path_len);
00585     }
00586   
00587   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00588     {
00589       dbus_set_error (error, _dbus_error_from_errno (errno),
00590                       "Failed to bind socket \"%s\": %s",
00591                       path, _dbus_strerror (errno));
00592       close (listen_fd);
00593       return -1;
00594     }
00595 
00596   if (listen (listen_fd, 30 /* backlog */) < 0)
00597     {
00598       dbus_set_error (error, _dbus_error_from_errno (errno),
00599                       "Failed to listen on socket \"%s\": %s",
00600                       path, _dbus_strerror (errno));
00601       close (listen_fd);
00602       return -1;
00603     }
00604 
00605   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00606     {
00607       _DBUS_ASSERT_ERROR_IS_SET (error);
00608       close (listen_fd);
00609       return -1;
00610     }
00611   
00612   /* Try opening up the permissions, but if we can't, just go ahead
00613    * and continue, maybe it will be good enough.
00614    */
00615   if (!abstract && chmod (path, 0777) < 0)
00616     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00617                 path);
00618   
00619   return listen_fd;
00620 }
00621 
00632 int
00633 _dbus_connect_tcp_socket (const char     *host,
00634                           dbus_uint32_t   port,
00635                           DBusError      *error)
00636 {
00637   int fd;
00638   struct sockaddr_in addr;
00639   struct hostent *he;
00640   struct in_addr *haddr;
00641 
00642   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00643   
00644   fd = socket (AF_INET, SOCK_STREAM, 0);
00645   
00646   if (fd < 0)
00647     {
00648       dbus_set_error (error,
00649                       _dbus_error_from_errno (errno),
00650                       "Failed to create socket: %s",
00651                       _dbus_strerror (errno)); 
00652       
00653       return -1;
00654     }
00655 
00656   if (host == NULL)
00657     host = "localhost";
00658 
00659   he = gethostbyname (host);
00660   if (he == NULL) 
00661     {
00662       dbus_set_error (error,
00663                       _dbus_error_from_errno (errno),
00664                       "Failed to lookup hostname: %s",
00665                       host);
00666       close (fd);
00667       return -1;
00668     }
00669   
00670   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00671 
00672   _DBUS_ZERO (addr);
00673   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00674   addr.sin_family = AF_INET;
00675   addr.sin_port = htons (port);
00676   
00677   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00678     {      
00679       dbus_set_error (error,
00680                        _dbus_error_from_errno (errno),
00681                       "Failed to connect to socket %s: %s:%d",
00682                       host, _dbus_strerror (errno), port);
00683 
00684       close (fd);
00685       fd = -1;
00686       
00687       return -1;
00688     }
00689 
00690   if (!_dbus_set_fd_nonblocking (fd, error))
00691     {
00692       close (fd);
00693       fd = -1;
00694 
00695       return -1;
00696     }
00697 
00698   return fd;
00699 }
00700 
00711 int
00712 _dbus_listen_tcp_socket (const char     *host,
00713                          dbus_uint32_t   port,
00714                          DBusError      *error)
00715 {
00716   int listen_fd;
00717   struct sockaddr_in addr;
00718   struct hostent *he;
00719   struct in_addr *haddr;
00720 
00721   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00722   
00723   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00724   
00725   if (listen_fd < 0)
00726     {
00727       dbus_set_error (error, _dbus_error_from_errno (errno),
00728                       "Failed to create socket \"%s:%d\": %s",
00729                       host, port, _dbus_strerror (errno));
00730       return -1;
00731     }
00732 
00733   he = gethostbyname (host);
00734   if (he == NULL) 
00735     {
00736       dbus_set_error (error,
00737                       _dbus_error_from_errno (errno),
00738                       "Failed to lookup hostname: %s",
00739                       host);
00740       close (listen_fd);
00741       return -1;
00742     }
00743   
00744   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00745 
00746   _DBUS_ZERO (addr);
00747   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00748   addr.sin_family = AF_INET;
00749   addr.sin_port = htons (port);
00750 
00751   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00752     {
00753       dbus_set_error (error, _dbus_error_from_errno (errno),
00754                       "Failed to bind socket \"%s:%d\": %s",
00755                       host, port, _dbus_strerror (errno));
00756       close (listen_fd);
00757       return -1;
00758     }
00759 
00760   if (listen (listen_fd, 30 /* backlog */) < 0)
00761     {
00762       dbus_set_error (error, _dbus_error_from_errno (errno),  
00763                       "Failed to listen on socket \"%s:%d\": %s",
00764                       host, port, _dbus_strerror (errno));
00765       close (listen_fd);
00766       return -1;
00767     }
00768 
00769   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00770     {
00771       close (listen_fd);
00772       return -1;
00773     }
00774   
00775   return listen_fd;
00776 }
00777 
00778 static dbus_bool_t
00779 write_credentials_byte (int             server_fd,
00780                         DBusError      *error)
00781 {
00782   int bytes_written;
00783   char buf[1] = { '\0' };
00784 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00785   struct {
00786           struct cmsghdr hdr;
00787           struct cmsgcred cred;
00788   } cmsg;
00789   struct iovec iov;
00790   struct msghdr msg;
00791 #endif
00792 
00793 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00794   iov.iov_base = buf;
00795   iov.iov_len = 1;
00796 
00797   memset (&msg, 0, sizeof (msg));
00798   msg.msg_iov = &iov;
00799   msg.msg_iovlen = 1;
00800 
00801   msg.msg_control = &cmsg;
00802   msg.msg_controllen = sizeof (cmsg);
00803   memset (&cmsg, 0, sizeof (cmsg));
00804   cmsg.hdr.cmsg_len = sizeof (cmsg);
00805   cmsg.hdr.cmsg_level = SOL_SOCKET;
00806   cmsg.hdr.cmsg_type = SCM_CREDS;
00807 #endif
00808 
00809   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00810   
00811  again:
00812 
00813 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00814   bytes_written = sendmsg (server_fd, &msg, 0);
00815 #else
00816   bytes_written = write (server_fd, buf, 1);
00817 #endif
00818 
00819   if (bytes_written < 0 && errno == EINTR)
00820     goto again;
00821 
00822   if (bytes_written < 0)
00823     {
00824       dbus_set_error (error, _dbus_error_from_errno (errno),
00825                       "Failed to write credentials byte: %s",
00826                      _dbus_strerror (errno));
00827       return FALSE;
00828     }
00829   else if (bytes_written == 0)
00830     {
00831       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00832                       "wrote zero bytes writing credentials byte");
00833       return FALSE;
00834     }
00835   else
00836     {
00837       _dbus_assert (bytes_written == 1);
00838       _dbus_verbose ("wrote credentials byte\n");
00839       return TRUE;
00840     }
00841 }
00842 
00861 dbus_bool_t
00862 _dbus_read_credentials_unix_socket  (int              client_fd,
00863                                      DBusCredentials *credentials,
00864                                      DBusError       *error)
00865 {
00866   struct msghdr msg;
00867   struct iovec iov;
00868   char buf;
00869 
00870 #ifdef HAVE_CMSGCRED 
00871   struct {
00872           struct cmsghdr hdr;
00873           struct cmsgcred cred;
00874   } cmsg;
00875 #endif
00876 
00877   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00878   
00879   /* The POSIX spec certainly doesn't promise this, but
00880    * we need these assertions to fail as soon as we're wrong about
00881    * it so we can do the porting fixups
00882    */
00883   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00884   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00885   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00886 
00887   _dbus_credentials_clear (credentials);
00888 
00889 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00890   /* Set the socket to receive credentials on the next message */
00891   {
00892     int on = 1;
00893     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00894       {
00895         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00896         return FALSE;
00897       }
00898   }
00899 #endif
00900 
00901   iov.iov_base = &buf;
00902   iov.iov_len = 1;
00903 
00904   memset (&msg, 0, sizeof (msg));
00905   msg.msg_iov = &iov;
00906   msg.msg_iovlen = 1;
00907 
00908 #ifdef HAVE_CMSGCRED
00909   memset (&cmsg, 0, sizeof (cmsg));
00910   msg.msg_control = &cmsg;
00911   msg.msg_controllen = sizeof (cmsg);
00912 #endif
00913 
00914  again:
00915   if (recvmsg (client_fd, &msg, 0) < 0)
00916     {
00917       if (errno == EINTR)
00918         goto again;
00919 
00920       dbus_set_error (error, _dbus_error_from_errno (errno),
00921                       "Failed to read credentials byte: %s",
00922                       _dbus_strerror (errno));
00923       return FALSE;
00924     }
00925 
00926   if (buf != '\0')
00927     {
00928       dbus_set_error (error, DBUS_ERROR_FAILED,
00929                       "Credentials byte was not nul");
00930       return FALSE;
00931     }
00932 
00933 #ifdef HAVE_CMSGCRED
00934   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00935     {
00936       dbus_set_error (error, DBUS_ERROR_FAILED,
00937                       "Message from recvmsg() was not SCM_CREDS");
00938       return FALSE;
00939     }
00940 #endif
00941 
00942   _dbus_verbose ("read credentials byte\n");
00943 
00944   {
00945 #ifdef SO_PEERCRED
00946     struct ucred cr;   
00947     int cr_len = sizeof (cr);
00948    
00949     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00950         cr_len == sizeof (cr))
00951       {
00952         credentials->pid = cr.pid;
00953         credentials->uid = cr.uid;
00954         credentials->gid = cr.gid;
00955       }
00956     else
00957       {
00958         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00959                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00960       }
00961 #elif defined(HAVE_CMSGCRED)
00962     credentials->pid = cmsg.cred.cmcred_pid;
00963     credentials->uid = cmsg.cred.cmcred_euid;
00964     credentials->gid = cmsg.cred.cmcred_groups[0];
00965 #elif defined(HAVE_GETPEEREID)
00966     uid_t euid;
00967     gid_t egid;
00968     if (getpeereid (client_fd, &euid, &egid) == 0)
00969       {
00970         credentials->uid = euid;
00971         credentials->gid = egid;
00972       }
00973     else
00974       {
00975         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
00976       }
00977 #elif defined(HAVE_GETPEERUCRED)
00978     ucred_t * ucred = NULL;
00979     if (getpeerucred (client_fd, &ucred) == 0)
00980       {
00981         credentials->pid = ucred_getpid (ucred);
00982         credentials->uid = ucred_geteuid (ucred);
00983         credentials->gid = ucred_getegid (ucred);
00984       }
00985     else
00986       {
00987         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
00988       }
00989     if (ucred != NULL)
00990       ucred_free (ucred);
00991 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
00992     _dbus_verbose ("Socket credentials not supported on this OS\n");
00993 #endif
00994   }
00995 
00996   _dbus_verbose ("Credentials:"
00997                  "  pid "DBUS_PID_FORMAT
00998                  "  uid "DBUS_UID_FORMAT
00999                  "  gid "DBUS_GID_FORMAT"\n",
01000                  credentials->pid,
01001                  credentials->uid,
01002                  credentials->gid);
01003     
01004   return TRUE;
01005 }
01006 
01024 dbus_bool_t
01025 _dbus_send_credentials_unix_socket  (int              server_fd,
01026                                      DBusError       *error)
01027 {
01028   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01029   
01030   if (write_credentials_byte (server_fd, error))
01031     return TRUE;
01032   else
01033     return FALSE;
01034 }
01035 
01043 int
01044 _dbus_accept  (int listen_fd)
01045 {
01046   int client_fd;
01047   struct sockaddr addr;
01048   socklen_t addrlen;
01049 
01050   addrlen = sizeof (addr);
01051   
01052  retry:
01053   client_fd = accept (listen_fd, &addr, &addrlen);
01054   
01055   if (client_fd < 0)
01056     {
01057       if (errno == EINTR)
01058         goto retry;
01059     }
01060   
01061   return client_fd;
01062 }
01063 
01078 dbus_bool_t
01079 _dbus_string_append_int (DBusString *str,
01080                          long        value)
01081 {
01082   /* this calculation is from comp.lang.c faq */
01083 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
01084   int orig_len;
01085   int i;
01086   char *buf;
01087   
01088   orig_len = _dbus_string_get_length (str);
01089 
01090   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
01091     return FALSE;
01092 
01093   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01094 
01095   snprintf (buf, MAX_LONG_LEN, "%ld", value);
01096 
01097   i = 0;
01098   while (*buf)
01099     {
01100       ++buf;
01101       ++i;
01102     }
01103   
01104   _dbus_string_shorten (str, MAX_LONG_LEN - i);
01105   
01106   return TRUE;
01107 }
01108 
01116 dbus_bool_t
01117 _dbus_string_append_uint (DBusString    *str,
01118                           unsigned long  value)
01119 {
01120   /* this is wrong, but definitely on the high side. */
01121 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01122   int orig_len;
01123   int i;
01124   char *buf;
01125   
01126   orig_len = _dbus_string_get_length (str);
01127 
01128   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01129     return FALSE;
01130 
01131   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01132 
01133   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01134 
01135   i = 0;
01136   while (*buf)
01137     {
01138       ++buf;
01139       ++i;
01140     }
01141   
01142   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01143   
01144   return TRUE;
01145 }
01146 
01147 #ifdef DBUS_BUILD_TESTS
01148 
01155 dbus_bool_t
01156 _dbus_string_append_double (DBusString *str,
01157                             double      value)
01158 {
01159 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
01160   int orig_len;
01161   char *buf;
01162   int i;
01163   
01164   orig_len = _dbus_string_get_length (str);
01165 
01166   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01167     return FALSE;
01168 
01169   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01170 
01171   snprintf (buf, MAX_LONG_LEN, "%g", value);
01172 
01173   i = 0;
01174   while (*buf)
01175     {
01176       ++buf;
01177       ++i;
01178     }
01179   
01180   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01181   
01182   return TRUE;
01183 }
01184 #endif /* DBUS_BUILD_TESTS */
01185 
01198 dbus_bool_t
01199 _dbus_string_parse_int (const DBusString *str,
01200                         int               start,
01201                         long             *value_return,
01202                         int              *end_return)
01203 {
01204   long v;
01205   const char *p;
01206   char *end;
01207 
01208   p = _dbus_string_get_const_data_len (str, start,
01209                                        _dbus_string_get_length (str) - start);
01210 
01211   end = NULL;
01212   errno = 0;
01213   v = strtol (p, &end, 0);
01214   if (end == NULL || end == p || errno != 0)
01215     return FALSE;
01216 
01217   if (value_return)
01218     *value_return = v;
01219   if (end_return)
01220     *end_return = start + (end - p);
01221 
01222   return TRUE;
01223 }
01224 
01233 dbus_bool_t
01234 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01235 {
01236   const char *directory;
01237   struct stat sb;
01238         
01239   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01240     
01241   directory = _dbus_string_get_const_data (dir);
01242         
01243   if (stat (directory, &sb) < 0)
01244     {
01245       dbus_set_error (error, _dbus_error_from_errno (errno),
01246                       "%s", _dbus_strerror (errno));
01247    
01248       return FALSE;
01249     }
01250     
01251   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01252       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01253     {
01254       dbus_set_error (error, DBUS_ERROR_FAILED,
01255                      "%s directory is not private to the user", directory);
01256       return FALSE;
01257     }
01258     
01259   return TRUE;
01260 }
01261 
01274 dbus_bool_t
01275 _dbus_string_parse_uint (const DBusString *str,
01276                          int               start,
01277                          unsigned long    *value_return,
01278                          int              *end_return)
01279 {
01280   unsigned long v;
01281   const char *p;
01282   char *end;
01283 
01284   p = _dbus_string_get_const_data_len (str, start,
01285                                        _dbus_string_get_length (str) - start);
01286 
01287   end = NULL;
01288   errno = 0;
01289   v = strtoul (p, &end, 0);
01290   if (end == NULL || end == p || errno != 0)
01291     return FALSE;
01292 
01293   if (value_return)
01294     *value_return = v;
01295   if (end_return)
01296     *end_return = start + (end - p);
01297 
01298   return TRUE;
01299 }
01300 
01301 #ifdef DBUS_BUILD_TESTS
01302 static dbus_bool_t
01303 ascii_isspace (char c)
01304 {
01305   return (c == ' ' ||
01306           c == '\f' ||
01307           c == '\n' ||
01308           c == '\r' ||
01309           c == '\t' ||
01310           c == '\v');
01311 }
01312 #endif /* DBUS_BUILD_TESTS */
01313 
01314 #ifdef DBUS_BUILD_TESTS
01315 static dbus_bool_t
01316 ascii_isdigit (char c)
01317 {
01318   return c >= '0' && c <= '9';
01319 }
01320 #endif /* DBUS_BUILD_TESTS */
01321 
01322 #ifdef DBUS_BUILD_TESTS
01323 static dbus_bool_t
01324 ascii_isxdigit (char c)
01325 {
01326   return (ascii_isdigit (c) ||
01327           (c >= 'a' && c <= 'f') ||
01328           (c >= 'A' && c <= 'F'));
01329 }
01330 #endif /* DBUS_BUILD_TESTS */
01331 
01332 #ifdef DBUS_BUILD_TESTS
01333 /* Calls strtod in a locale-independent fashion, by looking at
01334  * the locale data and patching the decimal comma to a point.
01335  *
01336  * Relicensed from glib.
01337  */
01338 static double
01339 ascii_strtod (const char *nptr,
01340               char      **endptr)
01341 {
01342   char *fail_pos;
01343   double val;
01344   struct lconv *locale_data;
01345   const char *decimal_point;
01346   int decimal_point_len;
01347   const char *p, *decimal_point_pos;
01348   const char *end = NULL; /* Silence gcc */
01349 
01350   fail_pos = NULL;
01351 
01352   locale_data = localeconv ();
01353   decimal_point = locale_data->decimal_point;
01354   decimal_point_len = strlen (decimal_point);
01355 
01356   _dbus_assert (decimal_point_len != 0);
01357   
01358   decimal_point_pos = NULL;
01359   if (decimal_point[0] != '.' ||
01360       decimal_point[1] != 0)
01361     {
01362       p = nptr;
01363       /* Skip leading space */
01364       while (ascii_isspace (*p))
01365         p++;
01366       
01367       /* Skip leading optional sign */
01368       if (*p == '+' || *p == '-')
01369         p++;
01370       
01371       if (p[0] == '0' &&
01372           (p[1] == 'x' || p[1] == 'X'))
01373         {
01374           p += 2;
01375           /* HEX - find the (optional) decimal point */
01376           
01377           while (ascii_isxdigit (*p))
01378             p++;
01379           
01380           if (*p == '.')
01381             {
01382               decimal_point_pos = p++;
01383               
01384               while (ascii_isxdigit (*p))
01385                 p++;
01386               
01387               if (*p == 'p' || *p == 'P')
01388                 p++;
01389               if (*p == '+' || *p == '-')
01390                 p++;
01391               while (ascii_isdigit (*p))
01392                 p++;
01393               end = p;
01394             }
01395         }
01396       else
01397         {
01398           while (ascii_isdigit (*p))
01399             p++;
01400           
01401           if (*p == '.')
01402             {
01403               decimal_point_pos = p++;
01404               
01405               while (ascii_isdigit (*p))
01406                 p++;
01407               
01408               if (*p == 'e' || *p == 'E')
01409                 p++;
01410               if (*p == '+' || *p == '-')
01411                 p++;
01412               while (ascii_isdigit (*p))
01413                 p++;
01414               end = p;
01415             }
01416         }
01417       /* For the other cases, we need not convert the decimal point */
01418     }
01419 
01420   /* Set errno to zero, so that we can distinguish zero results
01421      and underflows */
01422   errno = 0;
01423   
01424   if (decimal_point_pos)
01425     {
01426       char *copy, *c;
01427 
01428       /* We need to convert the '.' to the locale specific decimal point */
01429       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01430       
01431       c = copy;
01432       memcpy (c, nptr, decimal_point_pos - nptr);
01433       c += decimal_point_pos - nptr;
01434       memcpy (c, decimal_point, decimal_point_len);
01435       c += decimal_point_len;
01436       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01437       c += end - (decimal_point_pos + 1);
01438       *c = 0;
01439 
01440       val = strtod (copy, &fail_pos);
01441 
01442       if (fail_pos)
01443         {
01444           if (fail_pos > decimal_point_pos)
01445             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01446           else
01447             fail_pos = (char *)nptr + (fail_pos - copy);
01448         }
01449       
01450       dbus_free (copy);
01451           
01452     }
01453   else
01454     val = strtod (nptr, &fail_pos);
01455 
01456   if (endptr)
01457     *endptr = fail_pos;
01458   
01459   return val;
01460 }
01461 #endif /* DBUS_BUILD_TESTS */
01462 
01463 #ifdef DBUS_BUILD_TESTS
01464 
01476 dbus_bool_t
01477 _dbus_string_parse_double (const DBusString *str,
01478                            int               start,
01479                            double           *value_return,
01480                            int              *end_return)
01481 {
01482   double v;
01483   const char *p;
01484   char *end;
01485 
01486   p = _dbus_string_get_const_data_len (str, start,
01487                                        _dbus_string_get_length (str) - start);
01488 
01489   end = NULL;
01490   errno = 0;
01491   v = ascii_strtod (p, &end);
01492   if (end == NULL || end == p || errno != 0)
01493     return FALSE;
01494 
01495   if (value_return)
01496     *value_return = v;
01497   if (end_return)
01498     *end_return = start + (end - p);
01499 
01500   return TRUE;
01501 }
01502 #endif /* DBUS_BUILD_TESTS */
01503  /* DBusString group */
01505 
01510 static dbus_bool_t
01511 fill_user_info_from_passwd (struct passwd *p,
01512                             DBusUserInfo  *info,
01513                             DBusError     *error)
01514 {
01515   _dbus_assert (p->pw_name != NULL);
01516   _dbus_assert (p->pw_dir != NULL);
01517   
01518   info->uid = p->pw_uid;
01519   info->primary_gid = p->pw_gid;
01520   info->username = _dbus_strdup (p->pw_name);
01521   info->homedir = _dbus_strdup (p->pw_dir);
01522   
01523   if (info->username == NULL ||
01524       info->homedir == NULL)
01525     {
01526       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01527       return FALSE;
01528     }
01529 
01530   return TRUE;
01531 }
01532 
01533 static dbus_bool_t
01534 fill_user_info (DBusUserInfo       *info,
01535                 dbus_uid_t          uid,
01536                 const DBusString   *username,
01537                 DBusError          *error)
01538 {
01539   const char *username_c;
01540   
01541   /* exactly one of username/uid provided */
01542   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01543   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01544 
01545   info->uid = DBUS_UID_UNSET;
01546   info->primary_gid = DBUS_GID_UNSET;
01547   info->group_ids = NULL;
01548   info->n_group_ids = 0;
01549   info->username = NULL;
01550   info->homedir = NULL;
01551   
01552   if (username != NULL)
01553     username_c = _dbus_string_get_const_data (username);
01554   else
01555     username_c = NULL;
01556 
01557   /* For now assuming that the getpwnam() and getpwuid() flavors
01558    * are always symmetrical, if not we have to add more configure
01559    * checks
01560    */
01561   
01562 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01563   {
01564     struct passwd *p;
01565     int result;
01566     char buf[1024];
01567     struct passwd p_str;
01568 
01569     p = NULL;
01570 #ifdef HAVE_POSIX_GETPWNAM_R
01571     if (uid != DBUS_UID_UNSET)
01572       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01573                            &p);
01574     else
01575       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01576                            &p);
01577 #else
01578     if (uid != DBUS_UID_UNSET)
01579       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01580     else
01581       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01582     result = 0;
01583 #endif /* !HAVE_POSIX_GETPWNAM_R */
01584     if (result == 0 && p == &p_str)
01585       {
01586         if (!fill_user_info_from_passwd (p, info, error))
01587           return FALSE;
01588       }
01589     else
01590       {
01591         dbus_set_error (error, _dbus_error_from_errno (errno),
01592                         "User \"%s\" unknown or no memory to allocate password entry\n",
01593                         username_c ? username_c : "???");
01594         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01595         return FALSE;
01596       }
01597   }
01598 #else /* ! HAVE_GETPWNAM_R */
01599   {
01600     /* I guess we're screwed on thread safety here */
01601     struct passwd *p;
01602 
01603     if (uid != DBUS_UID_UNSET)
01604       p = getpwuid (uid);
01605     else
01606       p = getpwnam (username_c);
01607 
01608     if (p != NULL)
01609       {
01610         if (!fill_user_info_from_passwd (p, info, error))
01611           return FALSE;
01612       }
01613     else
01614       {
01615         dbus_set_error (error, _dbus_error_from_errno (errno),
01616                         "User \"%s\" unknown or no memory to allocate password entry\n",
01617                         username_c ? username_c : "???");
01618         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01619         return FALSE;
01620       }
01621   }
01622 #endif  /* ! HAVE_GETPWNAM_R */
01623 
01624   /* Fill this in so we can use it to get groups */
01625   username_c = info->username;
01626   
01627 #ifdef HAVE_GETGROUPLIST
01628   {
01629     gid_t *buf;
01630     int buf_count;
01631     int i;
01632     
01633     buf_count = 17;
01634     buf = dbus_new (gid_t, buf_count);
01635     if (buf == NULL)
01636       {
01637         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01638         goto failed;
01639       }
01640     
01641     if (getgrouplist (username_c,
01642                       info->primary_gid,
01643                       buf, &buf_count) < 0)
01644       {
01645         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01646         if (new == NULL)
01647           {
01648             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01649             dbus_free (buf);
01650             goto failed;
01651           }
01652         
01653         buf = new;
01654 
01655         errno = 0;
01656         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01657           {
01658             dbus_set_error (error,
01659                             _dbus_error_from_errno (errno),
01660                             "Failed to get groups for username \"%s\" primary GID "
01661                             DBUS_GID_FORMAT ": %s\n",
01662                             username_c, info->primary_gid,
01663                             _dbus_strerror (errno));
01664             dbus_free (buf);
01665             goto failed;
01666           }
01667       }
01668 
01669     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01670     if (info->group_ids == NULL)
01671       {
01672         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01673         dbus_free (buf);
01674         goto failed;
01675       }
01676     
01677     for (i = 0; i < buf_count; ++i)
01678       info->group_ids[i] = buf[i];
01679 
01680     info->n_group_ids = buf_count;
01681     
01682     dbus_free (buf);
01683   }
01684 #else  /* HAVE_GETGROUPLIST */
01685   {
01686     /* We just get the one group ID */
01687     info->group_ids = dbus_new (dbus_gid_t, 1);
01688     if (info->group_ids == NULL)
01689       {
01690         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01691         goto failed;
01692       }
01693 
01694     info->n_group_ids = 1;
01695 
01696     (info->group_ids)[0] = info->primary_gid;
01697   }
01698 #endif /* HAVE_GETGROUPLIST */
01699 
01700   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01701   
01702   return TRUE;
01703   
01704  failed:
01705   _DBUS_ASSERT_ERROR_IS_SET (error);
01706   return FALSE;
01707 }
01708 
01717 dbus_bool_t
01718 _dbus_user_info_fill (DBusUserInfo     *info,
01719                       const DBusString *username,
01720                       DBusError        *error)
01721 {
01722   return fill_user_info (info, DBUS_UID_UNSET,
01723                          username, error);
01724 }
01725 
01734 dbus_bool_t
01735 _dbus_user_info_fill_uid (DBusUserInfo *info,
01736                           dbus_uid_t    uid,
01737                           DBusError    *error)
01738 {
01739   return fill_user_info (info, uid,
01740                          NULL, error);
01741 }
01742 
01748 void
01749 _dbus_user_info_free (DBusUserInfo *info)
01750 {
01751   dbus_free (info->group_ids);
01752   dbus_free (info->username);
01753   dbus_free (info->homedir);
01754 }
01755 
01762 void
01763 _dbus_credentials_clear (DBusCredentials *credentials)
01764 {
01765   credentials->pid = DBUS_PID_UNSET;
01766   credentials->uid = DBUS_UID_UNSET;
01767   credentials->gid = DBUS_GID_UNSET;
01768 }
01769 
01775 void
01776 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01777 {
01778   /* The POSIX spec certainly doesn't promise this, but
01779    * we need these assertions to fail as soon as we're wrong about
01780    * it so we can do the porting fixups
01781    */
01782   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01783   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01784   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01785   
01786   credentials->pid = getpid ();
01787   credentials->uid = getuid ();
01788   credentials->gid = getgid ();
01789 }
01790 
01799 dbus_bool_t
01800 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01801                          const DBusCredentials *provided_credentials)
01802 {
01803   if (provided_credentials->uid == DBUS_UID_UNSET)
01804     return FALSE;
01805   else if (expected_credentials->uid == DBUS_UID_UNSET)
01806     return FALSE;
01807   else if (provided_credentials->uid == 0)
01808     return TRUE;
01809   else if (provided_credentials->uid == expected_credentials->uid)
01810     return TRUE;
01811   else
01812     return FALSE;
01813 }
01814 
01819 unsigned long
01820 _dbus_getpid (void)
01821 {
01822   return getpid ();
01823 }
01824 
01828 dbus_uid_t
01829 _dbus_getuid (void)
01830 {
01831   return getuid ();
01832 }
01833 
01834 #ifdef DBUS_BUILD_TESTS
01835 
01838 dbus_gid_t
01839 _dbus_getgid (void)
01840 {
01841   return getgid ();
01842 }
01843 #endif
01844 
01845 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01846 
01847 #ifdef DBUS_USE_ATOMIC_INT_486
01848 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01849 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01850 static inline dbus_int32_t
01851 atomic_exchange_and_add (DBusAtomic            *atomic,
01852                          volatile dbus_int32_t  val)
01853 {
01854   register dbus_int32_t result;
01855 
01856   __asm__ __volatile__ ("lock; xaddl %0,%1"
01857                         : "=r" (result), "=m" (atomic->value)
01858                         : "0" (val), "m" (atomic->value));
01859   return result;
01860 }
01861 #endif
01862 
01871 dbus_int32_t
01872 _dbus_atomic_inc (DBusAtomic *atomic)
01873 {
01874 #ifdef DBUS_USE_ATOMIC_INT_486
01875   return atomic_exchange_and_add (atomic, 1);
01876 #else
01877   dbus_int32_t res;
01878   _DBUS_LOCK (atomic);
01879   res = atomic->value;
01880   atomic->value += 1;
01881   _DBUS_UNLOCK (atomic);
01882   return res;
01883 #endif
01884 }
01885 
01894 dbus_int32_t
01895 _dbus_atomic_dec (DBusAtomic *atomic)
01896 {
01897 #ifdef DBUS_USE_ATOMIC_INT_486
01898   return atomic_exchange_and_add (atomic, -1);
01899 #else
01900   dbus_int32_t res;
01901   
01902   _DBUS_LOCK (atomic);
01903   res = atomic->value;
01904   atomic->value -= 1;
01905   _DBUS_UNLOCK (atomic);
01906   return res;
01907 #endif
01908 }
01909 
01918 int
01919 _dbus_poll (DBusPollFD *fds,
01920             int         n_fds,
01921             int         timeout_milliseconds)
01922 {
01923 #ifdef HAVE_POLL
01924   /* This big thing is a constant expression and should get optimized
01925    * out of existence. So it's more robust than a configure check at
01926    * no cost.
01927    */
01928   if (_DBUS_POLLIN == POLLIN &&
01929       _DBUS_POLLPRI == POLLPRI &&
01930       _DBUS_POLLOUT == POLLOUT &&
01931       _DBUS_POLLERR == POLLERR &&
01932       _DBUS_POLLHUP == POLLHUP &&
01933       _DBUS_POLLNVAL == POLLNVAL &&
01934       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01935       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01936       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01937       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01938       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01939       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01940       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01941     {
01942       return poll ((struct pollfd*) fds,
01943                    n_fds, 
01944                    timeout_milliseconds);
01945     }
01946   else
01947     {
01948       /* We have to convert the DBusPollFD to an array of
01949        * struct pollfd, poll, and convert back.
01950        */
01951       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01952       return -1;
01953     }
01954 #else /* ! HAVE_POLL */
01955 
01956   fd_set read_set, write_set, err_set;
01957   int max_fd = 0;
01958   int i;
01959   struct timeval tv;
01960   int ready;
01961   
01962   FD_ZERO (&read_set);
01963   FD_ZERO (&write_set);
01964   FD_ZERO (&err_set);
01965 
01966   for (i = 0; i < n_fds; i++)
01967     {
01968       DBusPollFD *fdp = &fds[i];
01969 
01970       if (fdp->events & _DBUS_POLLIN)
01971         FD_SET (fdp->fd, &read_set);
01972 
01973       if (fdp->events & _DBUS_POLLOUT)
01974         FD_SET (fdp->fd, &write_set);
01975 
01976       FD_SET (fdp->fd, &err_set);
01977 
01978       max_fd = MAX (max_fd, fdp->fd);
01979     }
01980     
01981   tv.tv_sec = timeout_milliseconds / 1000;
01982   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01983 
01984   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01985                   timeout_milliseconds < 0 ? NULL : &tv);
01986 
01987   if (ready > 0)
01988     {
01989       for (i = 0; i < n_fds; i++)
01990         {
01991           DBusPollFD *fdp = &fds[i];
01992 
01993           fdp->revents = 0;
01994 
01995           if (FD_ISSET (fdp->fd, &read_set))
01996             fdp->revents |= _DBUS_POLLIN;
01997 
01998           if (FD_ISSET (fdp->fd, &write_set))
01999             fdp->revents |= _DBUS_POLLOUT;
02000 
02001           if (FD_ISSET (fdp->fd, &err_set))
02002             fdp->revents |= _DBUS_POLLERR;
02003         }
02004     }
02005 
02006   return ready;
02007 #endif
02008 }
02009 
02011 #define NANOSECONDS_PER_SECOND       1000000000
02012 
02013 #define MICROSECONDS_PER_SECOND      1000000
02014 
02015 #define MILLISECONDS_PER_SECOND      1000
02016 
02017 #define NANOSECONDS_PER_MILLISECOND  1000000
02018 
02019 #define MICROSECONDS_PER_MILLISECOND 1000
02020 
02025 void
02026 _dbus_sleep_milliseconds (int milliseconds)
02027 {
02028 #ifdef HAVE_NANOSLEEP
02029   struct timespec req;
02030   struct timespec rem;
02031 
02032   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02033   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02034   rem.tv_sec = 0;
02035   rem.tv_nsec = 0;
02036 
02037   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02038     req = rem;
02039 #elif defined (HAVE_USLEEP)
02040   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02041 #else /* ! HAVE_USLEEP */
02042   sleep (MAX (milliseconds / 1000, 1));
02043 #endif
02044 }
02045 
02052 void
02053 _dbus_get_current_time (long *tv_sec,
02054                         long *tv_usec)
02055 {
02056   struct timeval t;
02057 
02058   gettimeofday (&t, NULL);
02059 
02060   if (tv_sec)
02061     *tv_sec = t.tv_sec;
02062   if (tv_usec)
02063     *tv_usec = t.tv_usec;
02064 }
02065 
02076 dbus_bool_t
02077 _dbus_file_get_contents (DBusString       *str,
02078                          const DBusString *filename,
02079                          DBusError        *error)
02080 {
02081   int fd;
02082   struct stat sb;
02083   int orig_len;
02084   int total;
02085   const char *filename_c;
02086 
02087   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02088   
02089   filename_c = _dbus_string_get_const_data (filename);
02090   
02091   /* O_BINARY useful on Cygwin */
02092   fd = open (filename_c, O_RDONLY | O_BINARY);
02093   if (fd < 0)
02094     {
02095       dbus_set_error (error, _dbus_error_from_errno (errno),
02096                       "Failed to open \"%s\": %s",
02097                       filename_c,
02098                       _dbus_strerror (errno));
02099       return FALSE;
02100     }
02101 
02102   if (fstat (fd, &sb) < 0)
02103     {
02104       dbus_set_error (error, _dbus_error_from_errno (errno),
02105                       "Failed to stat \"%s\": %s",
02106                       filename_c,
02107                       _dbus_strerror (errno));
02108 
02109       _dbus_verbose ("fstat() failed: %s",
02110                      _dbus_strerror (errno));
02111       
02112       close (fd);
02113       
02114       return FALSE;
02115     }
02116 
02117   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02118     {
02119       dbus_set_error (error, DBUS_ERROR_FAILED,
02120                       "File size %lu of \"%s\" is too large.",
02121                       (unsigned long) sb.st_size, filename_c);
02122       close (fd);
02123       return FALSE;
02124     }
02125   
02126   total = 0;
02127   orig_len = _dbus_string_get_length (str);
02128   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02129     {
02130       int bytes_read;
02131 
02132       while (total < (int) sb.st_size)
02133         {
02134           bytes_read = _dbus_read (fd, str,
02135                                    sb.st_size - total);
02136           if (bytes_read <= 0)
02137             {
02138               dbus_set_error (error, _dbus_error_from_errno (errno),
02139                               "Error reading \"%s\": %s",
02140                               filename_c,
02141                               _dbus_strerror (errno));
02142 
02143               _dbus_verbose ("read() failed: %s",
02144                              _dbus_strerror (errno));
02145               
02146               close (fd);
02147               _dbus_string_set_length (str, orig_len);
02148               return FALSE;
02149             }
02150           else
02151             total += bytes_read;
02152         }
02153 
02154       close (fd);
02155       return TRUE;
02156     }
02157   else if (sb.st_size != 0)
02158     {
02159       _dbus_verbose ("Can only open regular files at the moment.\n");
02160       dbus_set_error (error, DBUS_ERROR_FAILED,
02161                       "\"%s\" is not a regular file",
02162                       filename_c);
02163       close (fd);
02164       return FALSE;
02165     }
02166   else
02167     {
02168       close (fd);
02169       return TRUE;
02170     }
02171 }
02172 
02182 dbus_bool_t
02183 _dbus_string_save_to_file (const DBusString *str,
02184                            const DBusString *filename,
02185                            DBusError        *error)
02186 {
02187   int fd;
02188   int bytes_to_write;
02189   const char *filename_c;
02190   DBusString tmp_filename;
02191   const char *tmp_filename_c;
02192   int total;
02193   dbus_bool_t need_unlink;
02194   dbus_bool_t retval;
02195 
02196   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02197   
02198   fd = -1;
02199   retval = FALSE;
02200   need_unlink = FALSE;
02201   
02202   if (!_dbus_string_init (&tmp_filename))
02203     {
02204       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02205       return FALSE;
02206     }
02207 
02208   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02209     {
02210       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02211       _dbus_string_free (&tmp_filename);
02212       return FALSE;
02213     }
02214   
02215   if (!_dbus_string_append (&tmp_filename, "."))
02216     {
02217       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02218       _dbus_string_free (&tmp_filename);
02219       return FALSE;
02220     }
02221 
02222 #define N_TMP_FILENAME_RANDOM_BYTES 8
02223   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02224     {
02225       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02226       _dbus_string_free (&tmp_filename);
02227       return FALSE;
02228     }
02229     
02230   filename_c = _dbus_string_get_const_data (filename);
02231   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02232 
02233   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02234              0600);
02235   if (fd < 0)
02236     {
02237       dbus_set_error (error, _dbus_error_from_errno (errno),
02238                       "Could not create %s: %s", tmp_filename_c,
02239                       _dbus_strerror (errno));
02240       goto out;
02241     }
02242 
02243   need_unlink = TRUE;
02244   
02245   total = 0;
02246   bytes_to_write = _dbus_string_get_length (str);
02247 
02248   while (total < bytes_to_write)
02249     {
02250       int bytes_written;
02251 
02252       bytes_written = _dbus_write (fd, str, total,
02253                                    bytes_to_write - total);
02254 
02255       if (bytes_written <= 0)
02256         {
02257           dbus_set_error (error, _dbus_error_from_errno (errno),
02258                           "Could not write to %s: %s", tmp_filename_c,
02259                           _dbus_strerror (errno));
02260           
02261           goto out;
02262         }
02263 
02264       total += bytes_written;
02265     }
02266 
02267   if (close (fd) < 0)
02268     {
02269       dbus_set_error (error, _dbus_error_from_errno (errno),
02270                       "Could not close file %s: %s",
02271                       tmp_filename_c, _dbus_strerror (errno));
02272 
02273       goto out;
02274     }
02275 
02276   fd = -1;
02277   
02278   if (rename (tmp_filename_c, filename_c) < 0)
02279     {
02280       dbus_set_error (error, _dbus_error_from_errno (errno),
02281                       "Could not rename %s to %s: %s",
02282                       tmp_filename_c, filename_c,
02283                       _dbus_strerror (errno));
02284 
02285       goto out;
02286     }
02287 
02288   need_unlink = FALSE;
02289   
02290   retval = TRUE;
02291   
02292  out:
02293   /* close first, then unlink, to prevent ".nfs34234235" garbage
02294    * files
02295    */
02296 
02297   if (fd >= 0)
02298     close (fd);
02299         
02300   if (need_unlink && unlink (tmp_filename_c) < 0)
02301     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02302                    tmp_filename_c, _dbus_strerror (errno));
02303 
02304   _dbus_string_free (&tmp_filename);
02305 
02306   if (!retval)
02307     _DBUS_ASSERT_ERROR_IS_SET (error);
02308   
02309   return retval;
02310 }
02311 
02318 dbus_bool_t
02319 _dbus_create_file_exclusively (const DBusString *filename,
02320                                DBusError        *error)
02321 {
02322   int fd;
02323   const char *filename_c;
02324 
02325   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02326   
02327   filename_c = _dbus_string_get_const_data (filename);
02328   
02329   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02330              0600);
02331   if (fd < 0)
02332     {
02333       dbus_set_error (error,
02334                       DBUS_ERROR_FAILED,
02335                       "Could not create file %s: %s\n",
02336                       filename_c,
02337                       _dbus_strerror (errno));
02338       return FALSE;
02339     }
02340 
02341   if (close (fd) < 0)
02342     {
02343       dbus_set_error (error,
02344                       DBUS_ERROR_FAILED,
02345                       "Could not close file %s: %s\n",
02346                       filename_c,
02347                       _dbus_strerror (errno));
02348       return FALSE;
02349     }
02350   
02351   return TRUE;
02352 }
02353 
02362 dbus_bool_t
02363 _dbus_delete_file (const DBusString *filename,
02364                    DBusError        *error)
02365 {
02366   const char *filename_c;
02367 
02368   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02369   
02370   filename_c = _dbus_string_get_const_data (filename);
02371 
02372   if (unlink (filename_c) < 0)
02373     {
02374       dbus_set_error (error, DBUS_ERROR_FAILED,
02375                       "Failed to delete file %s: %s\n",
02376                       filename_c, _dbus_strerror (errno));
02377       return FALSE;
02378     }
02379   else
02380     return TRUE;
02381 }
02382 
02391 dbus_bool_t
02392 _dbus_create_directory (const DBusString *filename,
02393                         DBusError        *error)
02394 {
02395   const char *filename_c;
02396 
02397   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02398   
02399   filename_c = _dbus_string_get_const_data (filename);
02400 
02401   if (mkdir (filename_c, 0700) < 0)
02402     {
02403       if (errno == EEXIST)
02404         return TRUE;
02405       
02406       dbus_set_error (error, DBUS_ERROR_FAILED,
02407                       "Failed to create directory %s: %s\n",
02408                       filename_c, _dbus_strerror (errno));
02409       return FALSE;
02410     }
02411   else
02412     return TRUE;
02413 }
02414 
02425 dbus_bool_t
02426 _dbus_concat_dir_and_file (DBusString       *dir,
02427                            const DBusString *next_component)
02428 {
02429   dbus_bool_t dir_ends_in_slash;
02430   dbus_bool_t file_starts_with_slash;
02431 
02432   if (_dbus_string_get_length (dir) == 0 ||
02433       _dbus_string_get_length (next_component) == 0)
02434     return TRUE;
02435   
02436   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02437                                                     _dbus_string_get_length (dir) - 1);
02438 
02439   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02440 
02441   if (dir_ends_in_slash && file_starts_with_slash)
02442     {
02443       _dbus_string_shorten (dir, 1);
02444     }
02445   else if (!(dir_ends_in_slash || file_starts_with_slash))
02446     {
02447       if (!_dbus_string_append_byte (dir, '/'))
02448         return FALSE;
02449     }
02450 
02451   return _dbus_string_copy (next_component, 0, dir,
02452                             _dbus_string_get_length (dir));
02453 }
02454 
02455 static void
02456 pseudorandom_generate_random_bytes_buffer (char *buffer,
02457                                            int   n_bytes)
02458 {
02459   unsigned long tv_usec;
02460   int i;
02461   
02462   /* fall back to pseudorandom */
02463   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02464                  n_bytes);
02465   
02466   _dbus_get_current_time (NULL, &tv_usec);
02467   srand (tv_usec);
02468   
02469   i = 0;
02470   while (i < n_bytes)
02471     {
02472       double r;
02473       unsigned int b;
02474           
02475       r = rand ();
02476       b = (r / (double) RAND_MAX) * 255.0;
02477 
02478       buffer[i] = b;
02479 
02480       ++i;
02481     }
02482 }
02483 
02484 static dbus_bool_t
02485 pseudorandom_generate_random_bytes (DBusString *str,
02486                                     int         n_bytes)
02487 {
02488   int old_len;
02489   char *p;
02490   
02491   old_len = _dbus_string_get_length (str);
02492 
02493   if (!_dbus_string_lengthen (str, n_bytes))
02494     return FALSE;
02495 
02496   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02497 
02498   pseudorandom_generate_random_bytes_buffer (p, n_bytes);
02499 
02500   return TRUE;
02501 }
02502 
02509 void
02510 _dbus_generate_random_bytes_buffer (char *buffer,
02511                                     int   n_bytes)
02512 {
02513   DBusString str;
02514 
02515   if (!_dbus_string_init (&str))
02516     {
02517       pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02518       return;
02519     }
02520 
02521   if (!_dbus_generate_random_bytes (&str, n_bytes))
02522     {
02523       _dbus_string_free (&str);
02524       pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02525       return;
02526     }
02527 
02528   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
02529 
02530   _dbus_string_free (&str);
02531 }
02532 
02541 dbus_bool_t
02542 _dbus_generate_random_bytes (DBusString *str,
02543                              int         n_bytes)
02544 {
02545   int old_len;
02546   int fd;
02547 
02548   /* FALSE return means "no memory", if it could
02549    * mean something else then we'd need to return
02550    * a DBusError. So we always fall back to pseudorandom
02551    * if the I/O fails.
02552    */
02553   
02554   old_len = _dbus_string_get_length (str);
02555   fd = -1;
02556 
02557   /* note, urandom on linux will fall back to pseudorandom */
02558   fd = open ("/dev/urandom", O_RDONLY);
02559   if (fd < 0)
02560     return pseudorandom_generate_random_bytes (str, n_bytes);
02561 
02562   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02563     {
02564       close (fd);
02565       _dbus_string_set_length (str, old_len);
02566       return pseudorandom_generate_random_bytes (str, n_bytes);
02567     }
02568 
02569   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02570                  n_bytes);
02571   
02572   close (fd);
02573   
02574   return TRUE;
02575 }
02576 
02585 dbus_bool_t
02586 _dbus_generate_random_ascii (DBusString *str,
02587                              int         n_bytes)
02588 {
02589   static const char letters[] =
02590     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02591   int i;
02592   int len;
02593   
02594   if (!_dbus_generate_random_bytes (str, n_bytes))
02595     return FALSE;
02596   
02597   len = _dbus_string_get_length (str);
02598   i = len - n_bytes;
02599   while (i < len)
02600     {
02601       _dbus_string_set_byte (str, i,
02602                              letters[_dbus_string_get_byte (str, i) %
02603                                      (sizeof (letters) - 1)]);
02604 
02605       ++i;
02606     }
02607 
02608   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02609                                              n_bytes));
02610 
02611   return TRUE;
02612 }
02613 
02621 const char*
02622 _dbus_strerror (int error_number)
02623 {
02624   const char *msg;
02625   
02626   msg = strerror (error_number);
02627   if (msg == NULL)
02628     msg = "unknown";
02629 
02630   return msg;
02631 }
02632 
02636 void
02637 _dbus_disable_sigpipe (void)
02638 {
02639   signal (SIGPIPE, SIG_IGN);
02640 }
02641 
02649 void
02650 _dbus_fd_set_close_on_exec (int fd)
02651 {
02652   int val;
02653   
02654   val = fcntl (fd, F_GETFD, 0);
02655   
02656   if (val < 0)
02657     return;
02658 
02659   val |= FD_CLOEXEC;
02660   
02661   fcntl (fd, F_SETFD, val);
02662 }
02663 
02673 const char*
02674 _dbus_error_from_errno (int error_number)
02675 {
02676   switch (error_number)
02677     {
02678     case 0:
02679       return DBUS_ERROR_FAILED;
02680       
02681 #ifdef EPROTONOSUPPORT
02682     case EPROTONOSUPPORT:
02683       return DBUS_ERROR_NOT_SUPPORTED;
02684 #endif
02685 #ifdef EAFNOSUPPORT
02686     case EAFNOSUPPORT:
02687       return DBUS_ERROR_NOT_SUPPORTED;
02688 #endif
02689 #ifdef ENFILE
02690     case ENFILE:
02691       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02692 #endif
02693 #ifdef EMFILE
02694     case EMFILE:
02695       return DBUS_ERROR_LIMITS_EXCEEDED;
02696 #endif
02697 #ifdef EACCES
02698     case EACCES:
02699       return DBUS_ERROR_ACCESS_DENIED;
02700 #endif
02701 #ifdef EPERM
02702     case EPERM:
02703       return DBUS_ERROR_ACCESS_DENIED;
02704 #endif
02705 #ifdef ENOBUFS
02706     case ENOBUFS:
02707       return DBUS_ERROR_NO_MEMORY;
02708 #endif
02709 #ifdef ENOMEM
02710     case ENOMEM:
02711       return DBUS_ERROR_NO_MEMORY;
02712 #endif
02713 #ifdef EINVAL
02714     case EINVAL:
02715       return DBUS_ERROR_FAILED;
02716 #endif
02717 #ifdef EBADF
02718     case EBADF:
02719       return DBUS_ERROR_FAILED;
02720 #endif
02721 #ifdef EFAULT
02722     case EFAULT:
02723       return DBUS_ERROR_FAILED;
02724 #endif
02725 #ifdef ENOTSOCK
02726     case ENOTSOCK:
02727       return DBUS_ERROR_FAILED;
02728 #endif
02729 #ifdef EISCONN
02730     case EISCONN:
02731       return DBUS_ERROR_FAILED;
02732 #endif
02733 #ifdef ECONNREFUSED
02734     case ECONNREFUSED:
02735       return DBUS_ERROR_NO_SERVER;
02736 #endif
02737 #ifdef ETIMEDOUT
02738     case ETIMEDOUT:
02739       return DBUS_ERROR_TIMEOUT;
02740 #endif
02741 #ifdef ENETUNREACH
02742     case ENETUNREACH:
02743       return DBUS_ERROR_NO_NETWORK;
02744 #endif
02745 #ifdef EADDRINUSE
02746     case EADDRINUSE:
02747       return DBUS_ERROR_ADDRESS_IN_USE;
02748 #endif
02749 #ifdef EEXIST
02750     case EEXIST:
02751       return DBUS_ERROR_FILE_NOT_FOUND;
02752 #endif
02753 #ifdef ENOENT
02754     case ENOENT:
02755       return DBUS_ERROR_FILE_NOT_FOUND;
02756 #endif
02757     }
02758 
02759   return DBUS_ERROR_FAILED;
02760 }
02761 
02767 void
02768 _dbus_exit (int code)
02769 {
02770   _exit (code);
02771 }
02772 
02780 dbus_bool_t
02781 _dbus_close (int        fd,
02782              DBusError *error)
02783 {
02784   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02785   
02786  again:
02787   if (close (fd) < 0)
02788     {
02789       if (errno == EINTR)
02790         goto again;
02791 
02792       dbus_set_error (error, _dbus_error_from_errno (errno),
02793                       "Could not close fd %d", fd);
02794       return FALSE;
02795     }
02796 
02797   return TRUE;
02798 }
02799 
02807 dbus_bool_t
02808 _dbus_set_fd_nonblocking (int             fd,
02809                           DBusError      *error)
02810 {
02811   int val;
02812 
02813   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02814   
02815   val = fcntl (fd, F_GETFL, 0);
02816   if (val < 0)
02817     {
02818       dbus_set_error (error, _dbus_error_from_errno (errno),
02819                       "Failed to get flags from file descriptor %d: %s",
02820                       fd, _dbus_strerror (errno));
02821       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02822                      _dbus_strerror (errno));
02823       return FALSE;
02824     }
02825 
02826   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02827     {
02828       dbus_set_error (error, _dbus_error_from_errno (errno),
02829                       "Failed to set nonblocking flag of file descriptor %d: %s",
02830                       fd, _dbus_strerror (errno));
02831       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02832                      fd, _dbus_strerror (errno));
02833 
02834       return FALSE;
02835     }
02836 
02837   return TRUE;
02838 }
02839 
02840 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
02841 
02846 void
02847 _dbus_print_backtrace (void)
02848 {
02849 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
02850   void *bt[500];
02851   int bt_size;
02852   int i;
02853   char **syms;
02854   
02855   bt_size = backtrace (bt, 500);
02856 
02857   syms = backtrace_symbols (bt, bt_size);
02858   
02859   i = 0;
02860   while (i < bt_size)
02861     {
02862       _dbus_verbose ("  %s\n", syms[i]);
02863       ++i;
02864     }
02865 
02866   free (syms);
02867 #else
02868   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
02869 #endif
02870 }
02871 #endif /* asserts or tests enabled */
02872 
02873 
02881 dbus_bool_t
02882 _dbus_parse_uid (const DBusString      *uid_str,
02883                  dbus_uid_t            *uid)
02884 {
02885   int end;
02886   long val;
02887   
02888   if (_dbus_string_get_length (uid_str) == 0)
02889     {
02890       _dbus_verbose ("UID string was zero length\n");
02891       return FALSE;
02892     }
02893 
02894   val = -1;
02895   end = 0;
02896   if (!_dbus_string_parse_int (uid_str, 0, &val,
02897                                &end))
02898     {
02899       _dbus_verbose ("could not parse string as a UID\n");
02900       return FALSE;
02901     }
02902   
02903   if (end != _dbus_string_get_length (uid_str))
02904     {
02905       _dbus_verbose ("string contained trailing stuff after UID\n");
02906       return FALSE;
02907     }
02908 
02909   *uid = val;
02910 
02911   return TRUE;
02912 }
02913 
02929 dbus_bool_t
02930 _dbus_full_duplex_pipe (int        *fd1,
02931                         int        *fd2,
02932                         dbus_bool_t blocking,
02933                         DBusError  *error)
02934 {
02935 #ifdef HAVE_SOCKETPAIR
02936   int fds[2];
02937 
02938   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02939   
02940   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02941     {
02942       dbus_set_error (error, _dbus_error_from_errno (errno),
02943                       "Could not create full-duplex pipe");
02944       return FALSE;
02945     }
02946 
02947   if (!blocking &&
02948       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02949        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02950     {
02951       dbus_set_error (error, _dbus_error_from_errno (errno),
02952                       "Could not set full-duplex pipe nonblocking");
02953       
02954       close (fds[0]);
02955       close (fds[1]);
02956       
02957       return FALSE;
02958     }
02959   
02960   *fd1 = fds[0];
02961   *fd2 = fds[1];
02962 
02963   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02964                  *fd1, *fd2);
02965   
02966   return TRUE;  
02967 #else
02968   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02969   dbus_set_error (error, DBUS_ERROR_FAILED,
02970                   "_dbus_full_duplex_pipe() not implemented on this OS");
02971   return FALSE;
02972 #endif
02973 }
02974 
02977 /* tests in dbus-sysdeps-util.c */

Generated on Tue Jul 7 15:14:00 2009 for D-BUS by  doxygen 1.4.6