Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

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.0
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-test.h"
00029 #include <sys/types.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <signal.h>
00033 #include <unistd.h>
00034 #include <stdio.h>
00035 #include <errno.h>
00036 #include <fcntl.h>
00037 #include <sys/socket.h>
00038 #include <dirent.h>
00039 #include <sys/un.h>
00040 #include <pwd.h>
00041 #include <time.h>
00042 #include <locale.h>
00043 #include <sys/time.h>
00044 #include <sys/stat.h>
00045 #include <sys/wait.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include <grp.h>
00049 
00050 #ifdef HAVE_WRITEV
00051 #include <sys/uio.h>
00052 #endif
00053 #ifdef HAVE_POLL
00054 #include <sys/poll.h>
00055 #endif
00056 #ifdef HAVE_BACKTRACE
00057 #include <execinfo.h>
00058 #endif
00059 
00060 
00061 #ifndef O_BINARY
00062 #define O_BINARY 0
00063 #endif
00064 
00065 #ifndef HAVE_SOCKLEN_T
00066 #define socklen_t int
00067 #endif
00068 
00076 void
00077 _dbus_abort (void)
00078 {
00079 #ifdef DBUS_ENABLE_VERBOSE_MODE
00080   const char *s;
00081   s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00082   if (s && *s)
00083     _dbus_print_backtrace ();
00084 #endif
00085   abort ();
00086   _exit (1); /* in case someone manages to ignore SIGABRT */
00087 }
00088 
00100 dbus_bool_t
00101 _dbus_setenv (const char *varname,
00102               const char *value)
00103 {
00104   _dbus_assert (varname != NULL);
00105   
00106   if (value == NULL)
00107     {
00108 #ifdef HAVE_UNSETENV
00109       unsetenv (varname);
00110       return TRUE;
00111 #else
00112       char *putenv_value;
00113       size_t len;
00114 
00115       len = strlen (varname);
00116 
00117       /* Use system malloc to avoid memleaks that dbus_malloc
00118        * will get upset about.
00119        */
00120       
00121       putenv_value = malloc (len + 1);
00122       if (putenv_value == NULL)
00123         return FALSE;
00124 
00125       strcpy (putenv_value, varname);
00126       
00127       return (putenv (putenv_value) == 0);
00128 #endif
00129     }
00130   else
00131     {
00132 #ifdef HAVE_SETENV
00133       return (setenv (varname, value, TRUE) == 0);
00134 #else
00135       char *putenv_value;
00136       size_t len;
00137       size_t varname_len;
00138       size_t value_len;
00139 
00140       varname_len = strlen (varname);
00141       value_len = strlen (value);
00142       
00143       len = varname_len + value_len + 1 /* '=' */ ;
00144 
00145       /* Use system malloc to avoid memleaks that dbus_malloc
00146        * will get upset about.
00147        */
00148       
00149       putenv_value = malloc (len + 1);
00150       if (putenv_value == NULL)
00151         return FALSE;
00152 
00153       strcpy (putenv_value, varname);
00154       strcpy (putenv_value + varname_len, "=");
00155       strcpy (putenv_value + varname_len + 1, value);
00156       
00157       return (putenv (putenv_value) == 0);
00158 #endif
00159     }
00160 }
00161 
00168 const char*
00169 _dbus_getenv (const char *varname)
00170 {  
00171   return getenv (varname);
00172 }
00173 
00187 int
00188 _dbus_read (int               fd,
00189             DBusString       *buffer,
00190             int               count)
00191 {
00192   int bytes_read;
00193   int start;
00194   char *data;
00195 
00196   _dbus_assert (count >= 0);
00197   
00198   start = _dbus_string_get_length (buffer);
00199 
00200   if (!_dbus_string_lengthen (buffer, count))
00201     {
00202       errno = ENOMEM;
00203       return -1;
00204     }
00205 
00206   data = _dbus_string_get_data_len (buffer, start, count);
00207 
00208  again:
00209   
00210   bytes_read = read (fd, data, count);
00211 
00212   if (bytes_read < 0)
00213     {
00214       if (errno == EINTR)
00215         goto again;
00216       else
00217         {
00218           /* put length back (note that this doesn't actually realloc anything) */
00219           _dbus_string_set_length (buffer, start);
00220           return -1;
00221         }
00222     }
00223   else
00224     {
00225       /* put length back (doesn't actually realloc) */
00226       _dbus_string_set_length (buffer, start + bytes_read);
00227 
00228 #if 0
00229       if (bytes_read > 0)
00230         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00231 #endif
00232       
00233       return bytes_read;
00234     }
00235 }
00236 
00247 int
00248 _dbus_write (int               fd,
00249              const DBusString *buffer,
00250              int               start,
00251              int               len)
00252 {
00253   const char *data;
00254   int bytes_written;
00255   
00256   data = _dbus_string_get_const_data_len (buffer, start, len);
00257   
00258  again:
00259 
00260   bytes_written = write (fd, data, len);
00261 
00262   if (bytes_written < 0 && errno == EINTR)
00263     goto again;
00264 
00265 #if 0
00266   if (bytes_written > 0)
00267     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00268 #endif
00269   
00270   return bytes_written;
00271 }
00272 
00293 int
00294 _dbus_write_two (int               fd,
00295                  const DBusString *buffer1,
00296                  int               start1,
00297                  int               len1,
00298                  const DBusString *buffer2,
00299                  int               start2,
00300                  int               len2)
00301 {
00302   _dbus_assert (buffer1 != NULL);
00303   _dbus_assert (start1 >= 0);
00304   _dbus_assert (start2 >= 0);
00305   _dbus_assert (len1 >= 0);
00306   _dbus_assert (len2 >= 0);
00307   
00308 #ifdef HAVE_WRITEV
00309   {
00310     struct iovec vectors[2];
00311     const char *data1;
00312     const char *data2;
00313     int bytes_written;
00314 
00315     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00316 
00317     if (buffer2 != NULL)
00318       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00319     else
00320       {
00321         data2 = NULL;
00322         start2 = 0;
00323         len2 = 0;
00324       }
00325    
00326     vectors[0].iov_base = (char*) data1;
00327     vectors[0].iov_len = len1;
00328     vectors[1].iov_base = (char*) data2;
00329     vectors[1].iov_len = len2;
00330 
00331   again:
00332    
00333     bytes_written = writev (fd,
00334                             vectors,
00335                             data2 ? 2 : 1);
00336 
00337     if (bytes_written < 0 && errno == EINTR)
00338       goto again;
00339    
00340     return bytes_written;
00341   }
00342 #else /* HAVE_WRITEV */
00343   {
00344     int ret1;
00345     
00346     ret1 = _dbus_write (fd, buffer1, start1, len1);
00347     if (ret1 == len1 && buffer2 != NULL)
00348       {
00349         ret2 = _dbus_write (fd, buffer2, start2, len2);
00350         if (ret2 < 0)
00351           ret2 = 0; /* we can't report an error as the first write was OK */
00352        
00353         return ret1 + ret2;
00354       }
00355     else
00356       return ret1;
00357   }
00358 #endif /* !HAVE_WRITEV */   
00359 }
00360 
00361 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00362 
00390 int
00391 _dbus_connect_unix_socket (const char     *path,
00392                            dbus_bool_t     abstract,
00393                            DBusError      *error)
00394 {
00395   int fd;
00396   struct sockaddr_un addr;  
00397 
00398   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00399 
00400   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00401                  path, abstract);
00402   
00403   fd = socket (PF_UNIX, SOCK_STREAM, 0);
00404   
00405   if (fd < 0)
00406     {
00407       dbus_set_error (error,
00408                       _dbus_error_from_errno (errno),
00409                       "Failed to create socket: %s",
00410                       _dbus_strerror (errno)); 
00411       
00412       return -1;
00413     }
00414 
00415   _DBUS_ZERO (addr);
00416   addr.sun_family = AF_UNIX;
00417 
00418   if (abstract)
00419     {
00420 #ifdef HAVE_ABSTRACT_SOCKETS
00421       /* remember that abstract names aren't nul-terminated so we rely
00422        * on sun_path being filled in with zeroes above.
00423        */
00424       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00425       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00426       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00427 #else /* HAVE_ABSTRACT_SOCKETS */
00428       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00429                       "Operating system does not support abstract socket namespace\n");
00430       close (fd);
00431       return -1;
00432 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00433     }
00434   else
00435     {
00436       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00437     }
00438   
00439   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00440     {      
00441       dbus_set_error (error,
00442                       _dbus_error_from_errno (errno),
00443                       "Failed to connect to socket %s: %s",
00444                       path, _dbus_strerror (errno));
00445 
00446       close (fd);
00447       fd = -1;
00448       
00449       return -1;
00450     }
00451 
00452   if (!_dbus_set_fd_nonblocking (fd, error))
00453     {
00454       _DBUS_ASSERT_ERROR_IS_SET (error);
00455       
00456       close (fd);
00457       fd = -1;
00458 
00459       return -1;
00460     }
00461 
00462   return fd;
00463 }
00464 
00480 int
00481 _dbus_listen_unix_socket (const char     *path,
00482                           dbus_bool_t     abstract,
00483                           DBusError      *error)
00484 {
00485   int listen_fd;
00486   struct sockaddr_un addr;
00487 
00488   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00489 
00490   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00491                  path, abstract);
00492   
00493   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00494   
00495   if (listen_fd < 0)
00496     {
00497       dbus_set_error (error, _dbus_error_from_errno (errno),
00498                       "Failed to create socket \"%s\": %s",
00499                       path, _dbus_strerror (errno));
00500       return -1;
00501     }
00502 
00503   _DBUS_ZERO (addr);
00504   addr.sun_family = AF_UNIX;
00505   
00506   if (abstract)
00507     {
00508 #ifdef HAVE_ABSTRACT_SOCKETS
00509       /* remember that abstract names aren't nul-terminated so we rely
00510        * on sun_path being filled in with zeroes above.
00511        */
00512       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00513       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00514       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00515 #else /* HAVE_ABSTRACT_SOCKETS */
00516       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00517                       "Operating system does not support abstract socket namespace\n");
00518       close (listen_fd);
00519       return -1;
00520 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00521     }
00522   else
00523     {
00524       /* FIXME discussed security implications of this with Nalin,
00525        * and we couldn't think of where it would kick our ass, but
00526        * it still seems a bit sucky. It also has non-security suckage;
00527        * really we'd prefer to exit if the socket is already in use.
00528        * But there doesn't seem to be a good way to do this.
00529        *
00530        * Just to be extra careful, I threw in the stat() - clearly
00531        * the stat() can't *fix* any security issue, but it at least
00532        * avoids inadvertent/accidental data loss.
00533        */
00534       {
00535         struct stat sb;
00536 
00537         if (stat (path, &sb) == 0 &&
00538             S_ISSOCK (sb.st_mode))
00539           unlink (path);
00540       }
00541 
00542       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00543     }
00544   
00545   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00546     {
00547       dbus_set_error (error, _dbus_error_from_errno (errno),
00548                       "Failed to bind socket \"%s\": %s",
00549                       path, _dbus_strerror (errno));
00550       close (listen_fd);
00551       return -1;
00552     }
00553 
00554   if (listen (listen_fd, 30 /* backlog */) < 0)
00555     {
00556       dbus_set_error (error, _dbus_error_from_errno (errno),
00557                       "Failed to listen on socket \"%s\": %s",
00558                       path, _dbus_strerror (errno));
00559       close (listen_fd);
00560       return -1;
00561     }
00562 
00563   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00564     {
00565       _DBUS_ASSERT_ERROR_IS_SET (error);
00566       close (listen_fd);
00567       return -1;
00568     }
00569   
00570   /* Try opening up the permissions, but if we can't, just go ahead
00571    * and continue, maybe it will be good enough.
00572    */
00573   if (!abstract && chmod (path, 0777) < 0)
00574     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00575                 path);
00576   
00577   return listen_fd;
00578 }
00579 
00590 int
00591 _dbus_connect_tcp_socket (const char     *host,
00592                           dbus_uint32_t   port,
00593                           DBusError      *error)
00594 {
00595   int fd;
00596   struct sockaddr_in addr;
00597   struct hostent *he;
00598   struct in_addr *haddr;
00599 
00600   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00601   
00602   fd = socket (AF_INET, SOCK_STREAM, 0);
00603   
00604   if (fd < 0)
00605     {
00606       dbus_set_error (error,
00607                       _dbus_error_from_errno (errno),
00608                       "Failed to create socket: %s",
00609                       _dbus_strerror (errno)); 
00610       
00611       return -1;
00612     }
00613 
00614   if (host == NULL)
00615     host = "localhost";
00616 
00617   he = gethostbyname (host);
00618   if (he == NULL) 
00619     {
00620       dbus_set_error (error,
00621                       _dbus_error_from_errno (errno),
00622                       "Failed to lookup hostname: %s",
00623                       host);
00624       return -1;
00625     }
00626   
00627   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00628 
00629   _DBUS_ZERO (addr);
00630   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00631   addr.sin_family = AF_INET;
00632   addr.sin_port = htons (port);
00633   
00634   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00635     {      
00636       dbus_set_error (error,
00637                        _dbus_error_from_errno (errno),
00638                       "Failed to connect to socket %s: %s:%d",
00639                       host, _dbus_strerror (errno), port);
00640 
00641       close (fd);
00642       fd = -1;
00643       
00644       return -1;
00645     }
00646 
00647   if (!_dbus_set_fd_nonblocking (fd, error))
00648     {
00649       close (fd);
00650       fd = -1;
00651 
00652       return -1;
00653     }
00654 
00655   return fd;
00656 }
00657 
00668 int
00669 _dbus_listen_tcp_socket (const char     *host,
00670                          dbus_uint32_t   port,
00671                          DBusError      *error)
00672 {
00673   int listen_fd;
00674   struct sockaddr_in addr;
00675   struct hostent *he;
00676   struct in_addr *haddr;
00677 
00678   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00679   
00680   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00681   
00682   if (listen_fd < 0)
00683     {
00684       dbus_set_error (error, _dbus_error_from_errno (errno),
00685                       "Failed to create socket \"%s:%d\": %s",
00686                       host, port, _dbus_strerror (errno));
00687       return -1;
00688     }
00689 
00690   he = gethostbyname (host);
00691   if (he == NULL) 
00692     {
00693       dbus_set_error (error,
00694                       _dbus_error_from_errno (errno),
00695                       "Failed to lookup hostname: %s",
00696                       host);
00697       return -1;
00698     }
00699   
00700   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00701 
00702   _DBUS_ZERO (addr);
00703   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00704   addr.sin_family = AF_INET;
00705   addr.sin_port = htons (port);
00706 
00707   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00708     {
00709       dbus_set_error (error, _dbus_error_from_errno (errno),
00710                       "Failed to bind socket \"%s:%d\": %s",
00711                       host, port, _dbus_strerror (errno));
00712       close (listen_fd);
00713       return -1;
00714     }
00715 
00716   if (listen (listen_fd, 30 /* backlog */) < 0)
00717     {
00718       dbus_set_error (error, _dbus_error_from_errno (errno),  
00719                       "Failed to listen on socket \"%s:%d\": %s",
00720                       host, port, _dbus_strerror (errno));
00721       close (listen_fd);
00722       return -1;
00723     }
00724 
00725   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00726     {
00727       close (listen_fd);
00728       return -1;
00729     }
00730   
00731   return listen_fd;
00732 }
00733 
00734 static dbus_bool_t
00735 write_credentials_byte (int             server_fd,
00736                         DBusError      *error)
00737 {
00738   int bytes_written;
00739   char buf[1] = { '\0' };
00740 
00741   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00742   
00743  again:
00744 
00745   bytes_written = write (server_fd, buf, 1);
00746 
00747   if (bytes_written < 0 && errno == EINTR)
00748     goto again;
00749 
00750   if (bytes_written < 0)
00751     {
00752       dbus_set_error (error, _dbus_error_from_errno (errno),
00753                       "Failed to write credentials byte: %s",
00754                      _dbus_strerror (errno));
00755       return FALSE;
00756     }
00757   else if (bytes_written == 0)
00758     {
00759       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00760                       "wrote zero bytes writing credentials byte");
00761       return FALSE;
00762     }
00763   else
00764     {
00765       _dbus_assert (bytes_written == 1);
00766       _dbus_verbose ("wrote credentials byte\n");
00767       return TRUE;
00768     }
00769 }
00770 
00789 dbus_bool_t
00790 _dbus_read_credentials_unix_socket  (int              client_fd,
00791                                      DBusCredentials *credentials,
00792                                      DBusError       *error)
00793 {
00794   struct msghdr msg;
00795   struct iovec iov;
00796   char buf;
00797 
00798 #ifdef HAVE_CMSGCRED 
00799   char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
00800   struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
00801 #endif
00802 
00803   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00804   
00805   /* The POSIX spec certainly doesn't promise this, but
00806    * we need these assertions to fail as soon as we're wrong about
00807    * it so we can do the porting fixups
00808    */
00809   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00810   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00811   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00812 
00813   _dbus_credentials_clear (credentials);
00814 
00815 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00816   /* Set the socket to receive credentials on the next message */
00817   {
00818     int on = 1;
00819     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00820       {
00821         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00822         return FALSE;
00823       }
00824   }
00825 #endif
00826 
00827   iov.iov_base = &buf;
00828   iov.iov_len = 1;
00829 
00830   memset (&msg, 0, sizeof (msg));
00831   msg.msg_iov = &iov;
00832   msg.msg_iovlen = 1;
00833 
00834 #ifdef HAVE_CMSGCRED
00835   memset (cmsgmem, 0, sizeof (cmsgmem));
00836   msg.msg_control = cmsgmem;
00837   msg.msg_controllen = sizeof (cmsgmem);
00838 #endif
00839 
00840  again:
00841   if (recvmsg (client_fd, &msg, 0) < 0)
00842     {
00843       if (errno == EINTR)
00844         goto again;
00845 
00846       dbus_set_error (error, _dbus_error_from_errno (errno),
00847                       "Failed to read credentials byte: %s",
00848                       _dbus_strerror (errno));
00849       return FALSE;
00850     }
00851 
00852   if (buf != '\0')
00853     {
00854       dbus_set_error (error, DBUS_ERROR_FAILED,
00855                       "Credentials byte was not nul");
00856       return FALSE;
00857     }
00858 
00859 #ifdef HAVE_CMSGCRED
00860   if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
00861     {
00862       dbus_set_error (error, DBUS_ERROR_FAILED);
00863       _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
00864       return FALSE;
00865     }
00866 #endif
00867 
00868   _dbus_verbose ("read credentials byte\n");
00869 
00870   {
00871 #ifdef SO_PEERCRED
00872     struct ucred cr;   
00873     int cr_len = sizeof (cr);
00874    
00875     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00876         cr_len == sizeof (cr))
00877       {
00878         credentials->pid = cr.pid;
00879         credentials->uid = cr.uid;
00880         credentials->gid = cr.gid;
00881       }
00882     else
00883       {
00884         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00885                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00886       }
00887 #elif defined(HAVE_CMSGCRED)
00888     struct cmsgcred *cred;
00889 
00890     cred = (struct cmsgcred *) CMSG_DATA (cmsg);
00891 
00892     credentials->pid = cred->cmcred_pid;
00893     credentials->uid = cred->cmcred_euid;
00894     credentials->gid = cred->cmcred_groups[0];
00895 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
00896     _dbus_verbose ("Socket credentials not supported on this OS\n");
00897 #endif
00898   }
00899 
00900   _dbus_verbose ("Credentials:"
00901                  "  pid "DBUS_PID_FORMAT
00902                  "  uid "DBUS_UID_FORMAT
00903                  "  gid "DBUS_GID_FORMAT"\n",
00904                  credentials->pid,
00905                  credentials->uid,
00906                  credentials->gid);
00907     
00908   return TRUE;
00909 }
00910 
00928 dbus_bool_t
00929 _dbus_send_credentials_unix_socket  (int              server_fd,
00930                                      DBusError       *error)
00931 {
00932   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00933   
00934   if (write_credentials_byte (server_fd, error))
00935     return TRUE;
00936   else
00937     return FALSE;
00938 }
00939 
00947 int
00948 _dbus_accept  (int listen_fd)
00949 {
00950   int client_fd;
00951   struct sockaddr addr;
00952   socklen_t addrlen;
00953 
00954   addrlen = sizeof (addr);
00955   
00956  retry:
00957   client_fd = accept (listen_fd, &addr, &addrlen);
00958   
00959   if (client_fd < 0)
00960     {
00961       if (errno == EINTR)
00962         goto retry;
00963     }
00964   
00965   return client_fd;
00966 }
00967 
00982 dbus_bool_t
00983 _dbus_string_append_int (DBusString *str,
00984                          long        value)
00985 {
00986   /* this calculation is from comp.lang.c faq */
00987 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
00988   int orig_len;
00989   int i;
00990   char *buf;
00991   
00992   orig_len = _dbus_string_get_length (str);
00993 
00994   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00995     return FALSE;
00996 
00997   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00998 
00999   snprintf (buf, MAX_LONG_LEN, "%ld", value);
01000 
01001   i = 0;
01002   while (*buf)
01003     {
01004       ++buf;
01005       ++i;
01006     }
01007   
01008   _dbus_string_shorten (str, MAX_LONG_LEN - i);
01009   
01010   return TRUE;
01011 }
01012 
01020 dbus_bool_t
01021 _dbus_string_append_uint (DBusString    *str,
01022                           unsigned long  value)
01023 {
01024   /* this is wrong, but definitely on the high side. */
01025 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01026   int orig_len;
01027   int i;
01028   char *buf;
01029   
01030   orig_len = _dbus_string_get_length (str);
01031 
01032   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01033     return FALSE;
01034 
01035   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01036 
01037   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01038 
01039   i = 0;
01040   while (*buf)
01041     {
01042       ++buf;
01043       ++i;
01044     }
01045   
01046   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01047   
01048   return TRUE;
01049 }
01050 
01058 dbus_bool_t
01059 _dbus_string_append_double (DBusString *str,
01060                             double      value)
01061 {
01062 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
01063   int orig_len;
01064   char *buf;
01065   int i;
01066   
01067   orig_len = _dbus_string_get_length (str);
01068 
01069   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01070     return FALSE;
01071 
01072   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01073 
01074   snprintf (buf, MAX_LONG_LEN, "%g", value);
01075 
01076   i = 0;
01077   while (*buf)
01078     {
01079       ++buf;
01080       ++i;
01081     }
01082   
01083   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01084   
01085   return TRUE;
01086 }
01087 
01100 dbus_bool_t
01101 _dbus_string_parse_int (const DBusString *str,
01102                         int               start,
01103                         long             *value_return,
01104                         int              *end_return)
01105 {
01106   long v;
01107   const char *p;
01108   char *end;
01109 
01110   p = _dbus_string_get_const_data_len (str, start,
01111                                        _dbus_string_get_length (str) - start);
01112 
01113   end = NULL;
01114   errno = 0;
01115   v = strtol (p, &end, 0);
01116   if (end == NULL || end == p || errno != 0)
01117     return FALSE;
01118 
01119   if (value_return)
01120     *value_return = v;
01121   if (end_return)
01122     *end_return = start + (end - p);
01123 
01124   return TRUE;
01125 }
01126 
01127 #ifdef DBUS_BUILD_TESTS
01128 /* Not currently used, so only built when tests are enabled */
01141 dbus_bool_t
01142 _dbus_string_parse_uint (const DBusString *str,
01143                          int               start,
01144                          unsigned long    *value_return,
01145                          int              *end_return)
01146 {
01147   unsigned long v;
01148   const char *p;
01149   char *end;
01150 
01151   p = _dbus_string_get_const_data_len (str, start,
01152                                        _dbus_string_get_length (str) - start);
01153 
01154   end = NULL;
01155   errno = 0;
01156   v = strtoul (p, &end, 0);
01157   if (end == NULL || end == p || errno != 0)
01158     return FALSE;
01159 
01160   if (value_return)
01161     *value_return = v;
01162   if (end_return)
01163     *end_return = start + (end - p);
01164 
01165   return TRUE;
01166 }
01167 #endif /* DBUS_BUILD_TESTS */
01168 
01169 static dbus_bool_t
01170 ascii_isspace (char c)
01171 {
01172   return (c == ' ' ||
01173           c == '\f' ||
01174           c == '\n' ||
01175           c == '\r' ||
01176           c == '\t' ||
01177           c == '\v');
01178 }
01179 
01180 static dbus_bool_t
01181 ascii_isdigit (char c)
01182 {
01183   return c >= '0' && c <= '9';
01184 }
01185 
01186 static dbus_bool_t
01187 ascii_isxdigit (char c)
01188 {
01189   return (ascii_isdigit (c) ||
01190           (c >= 'a' && c <= 'f') ||
01191           (c >= 'A' && c <= 'F'));
01192 }
01193 
01194 
01195 /* Calls strtod in a locale-independent fashion, by looking at
01196  * the locale data and patching the decimal comma to a point.
01197  *
01198  * Relicensed from glib.
01199  */
01200 static double
01201 ascii_strtod (const char *nptr,
01202               char      **endptr)
01203 {
01204   char *fail_pos;
01205   double val;
01206   struct lconv *locale_data;
01207   const char *decimal_point;
01208   int decimal_point_len;
01209   const char *p, *decimal_point_pos;
01210   const char *end = NULL; /* Silence gcc */
01211 
01212   fail_pos = NULL;
01213 
01214   locale_data = localeconv ();
01215   decimal_point = locale_data->decimal_point;
01216   decimal_point_len = strlen (decimal_point);
01217 
01218   _dbus_assert (decimal_point_len != 0);
01219   
01220   decimal_point_pos = NULL;
01221   if (decimal_point[0] != '.' ||
01222       decimal_point[1] != 0)
01223     {
01224       p = nptr;
01225       /* Skip leading space */
01226       while (ascii_isspace (*p))
01227         p++;
01228       
01229       /* Skip leading optional sign */
01230       if (*p == '+' || *p == '-')
01231         p++;
01232       
01233       if (p[0] == '0' &&
01234           (p[1] == 'x' || p[1] == 'X'))
01235         {
01236           p += 2;
01237           /* HEX - find the (optional) decimal point */
01238           
01239           while (ascii_isxdigit (*p))
01240             p++;
01241           
01242           if (*p == '.')
01243             {
01244               decimal_point_pos = p++;
01245               
01246               while (ascii_isxdigit (*p))
01247                 p++;
01248               
01249               if (*p == 'p' || *p == 'P')
01250                 p++;
01251               if (*p == '+' || *p == '-')
01252                 p++;
01253               while (ascii_isdigit (*p))
01254                 p++;
01255               end = p;
01256             }
01257         }
01258       else
01259         {
01260           while (ascii_isdigit (*p))
01261             p++;
01262           
01263           if (*p == '.')
01264             {
01265               decimal_point_pos = p++;
01266               
01267               while (ascii_isdigit (*p))
01268                 p++;
01269               
01270               if (*p == 'e' || *p == 'E')
01271                 p++;
01272               if (*p == '+' || *p == '-')
01273                 p++;
01274               while (ascii_isdigit (*p))
01275                 p++;
01276               end = p;
01277             }
01278         }
01279       /* For the other cases, we need not convert the decimal point */
01280     }
01281 
01282   /* Set errno to zero, so that we can distinguish zero results
01283      and underflows */
01284   errno = 0;
01285   
01286   if (decimal_point_pos)
01287     {
01288       char *copy, *c;
01289 
01290       /* We need to convert the '.' to the locale specific decimal point */
01291       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01292       
01293       c = copy;
01294       memcpy (c, nptr, decimal_point_pos - nptr);
01295       c += decimal_point_pos - nptr;
01296       memcpy (c, decimal_point, decimal_point_len);
01297       c += decimal_point_len;
01298       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01299       c += end - (decimal_point_pos + 1);
01300       *c = 0;
01301 
01302       val = strtod (copy, &fail_pos);
01303 
01304       if (fail_pos)
01305         {
01306           if (fail_pos > decimal_point_pos)
01307             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01308           else
01309             fail_pos = (char *)nptr + (fail_pos - copy);
01310         }
01311       
01312       dbus_free (copy);
01313           
01314     }
01315   else
01316     val = strtod (nptr, &fail_pos);
01317 
01318   if (endptr)
01319     *endptr = fail_pos;
01320   
01321   return val;
01322 }
01323 
01324 
01337 dbus_bool_t
01338 _dbus_string_parse_double (const DBusString *str,
01339                            int               start,
01340                            double           *value_return,
01341                            int              *end_return)
01342 {
01343   double v;
01344   const char *p;
01345   char *end;
01346 
01347   p = _dbus_string_get_const_data_len (str, start,
01348                                        _dbus_string_get_length (str) - start);
01349 
01350   end = NULL;
01351   errno = 0;
01352   v = ascii_strtod (p, &end);
01353   if (end == NULL || end == p || errno != 0)
01354     return FALSE;
01355 
01356   if (value_return)
01357     *value_return = v;
01358   if (end_return)
01359     *end_return = start + (end - p);
01360 
01361   return TRUE;
01362 }
01363  /* DBusString group */
01365 
01370 static dbus_bool_t
01371 fill_user_info_from_passwd (struct passwd *p,
01372                             DBusUserInfo  *info,
01373                             DBusError     *error)
01374 {
01375   _dbus_assert (p->pw_name != NULL);
01376   _dbus_assert (p->pw_dir != NULL);
01377   
01378   info->uid = p->pw_uid;
01379   info->primary_gid = p->pw_gid;
01380   info->username = _dbus_strdup (p->pw_name);
01381   info->homedir = _dbus_strdup (p->pw_dir);
01382   
01383   if (info->username == NULL ||
01384       info->homedir == NULL)
01385     {
01386       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01387       return FALSE;
01388     }
01389 
01390   return TRUE;
01391 }
01392 
01393 static dbus_bool_t
01394 fill_user_info (DBusUserInfo       *info,
01395                 dbus_uid_t          uid,
01396                 const DBusString   *username,
01397                 DBusError          *error)
01398 {
01399   const char *username_c;
01400   
01401   /* exactly one of username/uid provided */
01402   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01403   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01404 
01405   info->uid = DBUS_UID_UNSET;
01406   info->primary_gid = DBUS_GID_UNSET;
01407   info->group_ids = NULL;
01408   info->n_group_ids = 0;
01409   info->username = NULL;
01410   info->homedir = NULL;
01411   
01412   if (username != NULL)
01413     username_c = _dbus_string_get_const_data (username);
01414   else
01415     username_c = NULL;
01416 
01417   /* For now assuming that the getpwnam() and getpwuid() flavors
01418    * are always symmetrical, if not we have to add more configure
01419    * checks
01420    */
01421   
01422 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01423   {
01424     struct passwd *p;
01425     int result;
01426     char buf[1024];
01427     struct passwd p_str;
01428 
01429     p = NULL;
01430 #ifdef HAVE_POSIX_GETPWNAME_R
01431     if (uid >= 0)
01432       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01433                            &p);
01434     else
01435       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01436                            &p);
01437 #else
01438     if (uid != DBUS_UID_UNSET)
01439       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01440     else
01441       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01442     result = 0;
01443 #endif /* !HAVE_POSIX_GETPWNAME_R */
01444     if (result == 0 && p == &p_str)
01445       {
01446         if (!fill_user_info_from_passwd (p, info, error))
01447           return FALSE;
01448       }
01449     else
01450       {
01451         dbus_set_error (error, _dbus_error_from_errno (errno),
01452                         "User \"%s\" unknown or no memory to allocate password entry\n",
01453                         username_c ? username_c : "???");
01454         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01455         return FALSE;
01456       }
01457   }
01458 #else /* ! HAVE_GETPWNAM_R */
01459   {
01460     /* I guess we're screwed on thread safety here */
01461     struct passwd *p;
01462 
01463     if (uid != DBUS_UID_UNSET)
01464       p = getpwuid (uid);
01465     else
01466       p = getpwnam (username_c);
01467 
01468     if (p != NULL)
01469       {
01470         if (!fill_user_info_from_passwd (p, info, error))
01471           return FALSE;
01472       }
01473     else
01474       {
01475         dbus_set_error (error, _dbus_error_from_errno (errno),
01476                         "User \"%s\" unknown or no memory to allocate password entry\n",
01477                         username_c ? username_c : "???");
01478         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01479         return FALSE;
01480       }
01481   }
01482 #endif  /* ! HAVE_GETPWNAM_R */
01483 
01484   /* Fill this in so we can use it to get groups */
01485   username_c = info->username;
01486   
01487 #ifdef HAVE_GETGROUPLIST
01488   {
01489     gid_t *buf;
01490     int buf_count;
01491     int i;
01492     
01493     buf_count = 17;
01494     buf = dbus_new (gid_t, buf_count);
01495     if (buf == NULL)
01496       {
01497         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01498         goto failed;
01499       }
01500     
01501     if (getgrouplist (username_c,
01502                       info->primary_gid,
01503                       buf, &buf_count) < 0)
01504       {
01505         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01506         if (new == NULL)
01507           {
01508             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01509             dbus_free (buf);
01510             goto failed;
01511           }
01512         
01513         buf = new;
01514 
01515         errno = 0;
01516         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01517           {
01518             dbus_set_error (error,
01519                             _dbus_error_from_errno (errno),
01520                             "Failed to get groups for username \"%s\" primary GID "
01521                             DBUS_GID_FORMAT ": %s\n",
01522                             username_c, info->primary_gid,
01523                             _dbus_strerror (errno));
01524             dbus_free (buf);
01525             goto failed;
01526           }
01527       }
01528 
01529     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01530     if (info->group_ids == NULL)
01531       {
01532         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01533         dbus_free (buf);
01534         goto failed;
01535       }
01536     
01537     for (i = 0; i < buf_count; ++i)
01538       info->group_ids[i] = buf[i];
01539 
01540     info->n_group_ids = buf_count;
01541     
01542     dbus_free (buf);
01543   }
01544 #else  /* HAVE_GETGROUPLIST */
01545   {
01546     /* We just get the one group ID */
01547     info->group_ids = dbus_new (dbus_gid_t, 1);
01548     if (info->group_ids == NULL)
01549       {
01550         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01551         goto out;
01552       }
01553 
01554     info->n_group_ids = 1;
01555 
01556     (info->group_ids)[0] = info->primary_gid;
01557   }
01558 #endif /* HAVE_GETGROUPLIST */
01559 
01560   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01561   
01562   return TRUE;
01563   
01564  failed:
01565   _DBUS_ASSERT_ERROR_IS_SET (error);
01566   _dbus_user_info_free (info);
01567   return FALSE;
01568 }
01569 
01578 dbus_bool_t
01579 _dbus_user_info_fill (DBusUserInfo     *info,
01580                       const DBusString *username,
01581                       DBusError        *error)
01582 {
01583   return fill_user_info (info, DBUS_UID_UNSET,
01584                          username, error);
01585 }
01586 
01595 dbus_bool_t
01596 _dbus_user_info_fill_uid (DBusUserInfo *info,
01597                           dbus_uid_t    uid,
01598                           DBusError    *error)
01599 {
01600   return fill_user_info (info, uid,
01601                          NULL, error);
01602 }
01603 
01609 void
01610 _dbus_user_info_free (DBusUserInfo *info)
01611 {
01612   dbus_free (info->group_ids);
01613   dbus_free (info->username);
01614   dbus_free (info->homedir);
01615 }
01616 
01617 static dbus_bool_t
01618 fill_user_info_from_group (struct group  *g,
01619                            DBusGroupInfo *info,
01620                            DBusError     *error)
01621 {
01622   _dbus_assert (g->gr_name != NULL);
01623   
01624   info->gid = g->gr_gid;
01625   info->groupname = _dbus_strdup (g->gr_name);
01626 
01627   /* info->members = dbus_strdupv (g->gr_mem) */
01628   
01629   if (info->groupname == NULL)
01630     {
01631       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01632       return FALSE;
01633     }
01634 
01635   return TRUE;
01636 }
01637 
01638 static dbus_bool_t
01639 fill_group_info (DBusGroupInfo    *info,
01640                  dbus_gid_t        gid,
01641                  const DBusString *groupname,
01642                  DBusError        *error)
01643 {
01644   const char *group_c_str;
01645 
01646   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01647   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01648 
01649   if (groupname)
01650     group_c_str = _dbus_string_get_const_data (groupname);
01651   else
01652     group_c_str = NULL;
01653   
01654   /* For now assuming that the getgrnam() and getgrgid() flavors
01655    * always correspond to the pwnam flavors, if not we have
01656    * to add more configure checks.
01657    */
01658   
01659 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01660   {
01661     struct group *g;
01662     int result;
01663     char buf[1024];
01664     struct group g_str;
01665 
01666     g = NULL;
01667 #ifdef HAVE_POSIX_GETPWNAME_R
01668 
01669     if (group_c_str)
01670       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01671                            &g);
01672     else
01673       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01674                            &g);
01675 #else
01676     p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01677     result = 0;
01678 #endif /* !HAVE_POSIX_GETPWNAME_R */
01679     if (result == 0 && g == &g_str)
01680       {
01681         return fill_user_info_from_group (g, info, error);
01682       }
01683     else
01684       {
01685         dbus_set_error (error, _dbus_error_from_errno (errno),
01686                         "Group %s unknown or failed to look it up\n",
01687                         group_c_str ? group_c_str : "???");
01688         return FALSE;
01689       }
01690   }
01691 #else /* ! HAVE_GETPWNAM_R */
01692   {
01693     /* I guess we're screwed on thread safety here */
01694     struct group *g;
01695 
01696     g = getgrnam (group_c_str);
01697 
01698     if (g != NULL)
01699       {
01700         return fill_user_info_from_group (g, info, error);
01701       }
01702     else
01703       {
01704         dbus_set_error (error, _dbus_error_from_errno (errno),
01705                         "Group %s unknown or failed to look it up\n",
01706                         group_c_str ? group_c_str : "???");
01707         return FALSE;
01708       }
01709   }
01710 #endif  /* ! HAVE_GETPWNAM_R */
01711 }
01712 
01722 dbus_bool_t
01723 _dbus_group_info_fill (DBusGroupInfo    *info,
01724                        const DBusString *groupname,
01725                        DBusError        *error)
01726 {
01727   return fill_group_info (info, DBUS_GID_UNSET,
01728                           groupname, error);
01729 
01730 }
01731 
01741 dbus_bool_t
01742 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01743                            dbus_gid_t     gid,
01744                            DBusError     *error)
01745 {
01746   return fill_group_info (info, gid, NULL, error);
01747 }
01748 
01754 void
01755 _dbus_group_info_free (DBusGroupInfo    *info)
01756 {
01757   dbus_free (info->groupname);
01758 }
01759 
01766 void
01767 _dbus_credentials_clear (DBusCredentials *credentials)
01768 {
01769   credentials->pid = DBUS_PID_UNSET;
01770   credentials->uid = DBUS_UID_UNSET;
01771   credentials->gid = DBUS_GID_UNSET;
01772 }
01773 
01779 void
01780 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01781 {
01782   /* The POSIX spec certainly doesn't promise this, but
01783    * we need these assertions to fail as soon as we're wrong about
01784    * it so we can do the porting fixups
01785    */
01786   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01787   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01788   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01789   
01790   credentials->pid = getpid ();
01791   credentials->uid = getuid ();
01792   credentials->gid = getgid ();
01793 }
01794 
01803 dbus_bool_t
01804 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01805                          const DBusCredentials *provided_credentials)
01806 {
01807   if (provided_credentials->uid == DBUS_UID_UNSET)
01808     return FALSE;
01809   else if (expected_credentials->uid == DBUS_UID_UNSET)
01810     return FALSE;
01811   else if (provided_credentials->uid == 0)
01812     return TRUE;
01813   else if (provided_credentials->uid == expected_credentials->uid)
01814     return TRUE;
01815   else
01816     return FALSE;
01817 }
01818 
01823 unsigned long
01824 _dbus_getpid (void)
01825 {
01826   return getpid ();
01827 }
01828 
01832 dbus_uid_t
01833 _dbus_getuid (void)
01834 {
01835   return getuid ();
01836 }
01837 
01841 dbus_gid_t
01842 _dbus_getgid (void)
01843 {
01844   return getgid ();
01845 }
01846 
01847 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01848 
01849 #ifdef DBUS_USE_ATOMIC_INT_486
01850 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01851 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01852 static inline dbus_int32_t
01853 atomic_exchange_and_add (DBusAtomic            *atomic,
01854                          volatile dbus_int32_t  val)
01855 {
01856   register dbus_int32_t result;
01857 
01858   __asm__ __volatile__ ("lock; xaddl %0,%1"
01859                         : "=r" (result), "=m" (atomic->value)
01860                         : "0" (val), "m" (atomic->value));
01861   return result;
01862 }
01863 #endif
01864 
01873 dbus_int32_t
01874 _dbus_atomic_inc (DBusAtomic *atomic)
01875 {
01876 #ifdef DBUS_USE_ATOMIC_INT_486
01877   return atomic_exchange_and_add (atomic, 1);
01878 #else
01879   dbus_int32_t res;
01880   _DBUS_LOCK (atomic);
01881   res = atomic->value;
01882   atomic->value += 1;
01883   _DBUS_UNLOCK (atomic);
01884   return res;
01885 #endif
01886 }
01887 
01896 dbus_int32_t
01897 _dbus_atomic_dec (DBusAtomic *atomic)
01898 {
01899 #ifdef DBUS_USE_ATOMIC_INT_486
01900   return atomic_exchange_and_add (atomic, -1);
01901 #else
01902   dbus_int32_t res;
01903   
01904   _DBUS_LOCK (atomic);
01905   res = atomic->value;
01906   atomic->value -= 1;
01907   _DBUS_UNLOCK (atomic);
01908   return res;
01909 #endif
01910 }
01911 
01920 int
01921 _dbus_poll (DBusPollFD *fds,
01922             int         n_fds,
01923             int         timeout_milliseconds)
01924 {
01925 #ifdef HAVE_POLL
01926   /* This big thing is a constant expression and should get optimized
01927    * out of existence. So it's more robust than a configure check at
01928    * no cost.
01929    */
01930   if (_DBUS_POLLIN == POLLIN &&
01931       _DBUS_POLLPRI == POLLPRI &&
01932       _DBUS_POLLOUT == POLLOUT &&
01933       _DBUS_POLLERR == POLLERR &&
01934       _DBUS_POLLHUP == POLLHUP &&
01935       _DBUS_POLLNVAL == POLLNVAL &&
01936       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01937       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01938       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01939       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01940       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01941       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01942       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01943     {
01944       return poll ((struct pollfd*) fds,
01945                    n_fds, 
01946                    timeout_milliseconds);
01947     }
01948   else
01949     {
01950       /* We have to convert the DBusPollFD to an array of
01951        * struct pollfd, poll, and convert back.
01952        */
01953       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01954       return -1;
01955     }
01956 #else /* ! HAVE_POLL */
01957 
01958   fd_set read_set, write_set, err_set;
01959   int max_fd = 0;
01960   int i;
01961   struct timeval tv;
01962   int ready;
01963   
01964   FD_ZERO (&read_set);
01965   FD_ZERO (&write_set);
01966   FD_ZERO (&err_set);
01967 
01968   for (i = 0; i < n_fds; i++)
01969     {
01970       DBusPollFD f = fds[i];
01971 
01972       if (f.events & _DBUS_POLLIN)
01973         FD_SET (f.fd, &read_set);
01974 
01975       if (f.events & _DBUS_POLLOUT)
01976         FD_SET (f.fd, &write_set);
01977 
01978       FD_SET (f.fd, &err_set);
01979 
01980       max_fd = MAX (max_fd, f.fd);
01981     }
01982     
01983   tv.tv_sec = timeout_milliseconds / 1000;
01984   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01985 
01986   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01987 
01988   if (ready > 0)
01989     {
01990       for (i = 0; i < n_fds; i++)
01991         {
01992           DBusPollFD f = fds[i];
01993 
01994           f.revents = 0;
01995 
01996           if (FD_ISSET (f.fd, &read_set))
01997             f.revents |= _DBUS_POLLIN;
01998 
01999           if (FD_ISSET (f.fd, &write_set))
02000             f.revents |= _DBUS_POLLOUT;
02001 
02002           if (FD_ISSET (f.fd, &err_set))
02003             f.revents |= _DBUS_POLLERR;
02004         }
02005     }
02006 
02007   return ready;
02008 #endif
02009 }
02010 
02012 #define NANOSECONDS_PER_SECOND       1000000000
02013 
02014 #define MICROSECONDS_PER_SECOND      1000000
02015 
02016 #define MILLISECONDS_PER_SECOND      1000
02017 
02018 #define NANOSECONDS_PER_MILLISECOND  1000000
02019 
02020 #define MICROSECONDS_PER_MILLISECOND 1000
02021 
02026 void
02027 _dbus_sleep_milliseconds (int milliseconds)
02028 {
02029 #ifdef HAVE_NANOSLEEP
02030   struct timespec req;
02031   struct timespec rem;
02032 
02033   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02034   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02035   rem.tv_sec = 0;
02036   rem.tv_nsec = 0;
02037 
02038   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02039     req = rem;
02040 #elif defined (HAVE_USLEEP)
02041   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02042 #else /* ! HAVE_USLEEP */
02043   sleep (MAX (milliseconds / 1000, 1));
02044 #endif
02045 }
02046 
02053 void
02054 _dbus_get_current_time (long *tv_sec,
02055                         long *tv_usec)
02056 {
02057   struct timeval t;
02058 
02059   gettimeofday (&t, NULL);
02060 
02061   if (tv_sec)
02062     *tv_sec = t.tv_sec;
02063   if (tv_usec)
02064     *tv_usec = t.tv_usec;
02065 }
02066 
02077 dbus_bool_t
02078 _dbus_file_get_contents (DBusString       *str,
02079                          const DBusString *filename,
02080                          DBusError        *error)
02081 {
02082   int fd;
02083   struct stat sb;
02084   int orig_len;
02085   int total;
02086   const char *filename_c;
02087 
02088   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02089   
02090   filename_c = _dbus_string_get_const_data (filename);
02091   
02092   /* O_BINARY useful on Cygwin */
02093   fd = open (filename_c, O_RDONLY | O_BINARY);
02094   if (fd < 0)
02095     {
02096       dbus_set_error (error, _dbus_error_from_errno (errno),
02097                       "Failed to open \"%s\": %s",
02098                       filename_c,
02099                       _dbus_strerror (errno));
02100       return FALSE;
02101     }
02102 
02103   if (fstat (fd, &sb) < 0)
02104     {
02105       dbus_set_error (error, _dbus_error_from_errno (errno),
02106                       "Failed to stat \"%s\": %s",
02107                       filename_c,
02108                       _dbus_strerror (errno));
02109 
02110       _dbus_verbose ("fstat() failed: %s",
02111                      _dbus_strerror (errno));
02112       
02113       close (fd);
02114       
02115       return FALSE;
02116     }
02117 
02118   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02119     {
02120       dbus_set_error (error, DBUS_ERROR_FAILED,
02121                       "File size %lu of \"%s\" is too large.",
02122                       filename_c, (unsigned long) sb.st_size);
02123       close (fd);
02124       return FALSE;
02125     }
02126   
02127   total = 0;
02128   orig_len = _dbus_string_get_length (str);
02129   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02130     {
02131       int bytes_read;
02132 
02133       while (total < (int) sb.st_size)
02134         {
02135           bytes_read = _dbus_read (fd, str,
02136                                    sb.st_size - total);
02137           if (bytes_read <= 0)
02138             {
02139               dbus_set_error (error, _dbus_error_from_errno (errno),
02140                               "Error reading \"%s\": %s",
02141                               filename_c,
02142                               _dbus_strerror (errno));
02143 
02144               _dbus_verbose ("read() failed: %s",
02145                              _dbus_strerror (errno));
02146               
02147               close (fd);
02148               _dbus_string_set_length (str, orig_len);
02149               return FALSE;
02150             }
02151           else
02152             total += bytes_read;
02153         }
02154 
02155       close (fd);
02156       return TRUE;
02157     }
02158   else if (sb.st_size != 0)
02159     {
02160       _dbus_verbose ("Can only open regular files at the moment.\n");
02161       dbus_set_error (error, DBUS_ERROR_FAILED,
02162                       "\"%s\" is not a regular file",
02163                       filename_c);
02164       close (fd);
02165       return FALSE;
02166     }
02167   else
02168     {
02169       close (fd);
02170       return TRUE;
02171     }
02172 }
02173 
02183 dbus_bool_t
02184 _dbus_string_save_to_file (const DBusString *str,
02185                            const DBusString *filename,
02186                            DBusError        *error)
02187 {
02188   int fd;
02189   int bytes_to_write;
02190   const char *filename_c;
02191   DBusString tmp_filename;
02192   const char *tmp_filename_c;
02193   int total;
02194   dbus_bool_t need_unlink;
02195   dbus_bool_t retval;
02196 
02197   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02198   
02199   fd = -1;
02200   retval = FALSE;
02201   need_unlink = FALSE;
02202   
02203   if (!_dbus_string_init (&tmp_filename))
02204     {
02205       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02206       return FALSE;
02207     }
02208 
02209   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02210     {
02211       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02212       _dbus_string_free (&tmp_filename);
02213       return FALSE;
02214     }
02215   
02216   if (!_dbus_string_append (&tmp_filename, "."))
02217     {
02218       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02219       _dbus_string_free (&tmp_filename);
02220       return FALSE;
02221     }
02222 
02223 #define N_TMP_FILENAME_RANDOM_BYTES 8
02224   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02225     {
02226       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02227       _dbus_string_free (&tmp_filename);
02228       return FALSE;
02229     }
02230     
02231   filename_c = _dbus_string_get_const_data (filename);
02232   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02233 
02234   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02235              0600);
02236   if (fd < 0)
02237     {
02238       dbus_set_error (error, _dbus_error_from_errno (errno),
02239                       "Could not create %s: %s", tmp_filename_c,
02240                       _dbus_strerror (errno));
02241       goto out;
02242     }
02243 
02244   need_unlink = TRUE;
02245   
02246   total = 0;
02247   bytes_to_write = _dbus_string_get_length (str);
02248 
02249   while (total < bytes_to_write)
02250     {
02251       int bytes_written;
02252 
02253       bytes_written = _dbus_write (fd, str, total,
02254                                    bytes_to_write - total);
02255 
02256       if (bytes_written <= 0)
02257         {
02258           dbus_set_error (error, _dbus_error_from_errno (errno),
02259                           "Could not write to %s: %s", tmp_filename_c,
02260                           _dbus_strerror (errno));
02261           
02262           goto out;
02263         }
02264 
02265       total += bytes_written;
02266     }
02267 
02268   if (close (fd) < 0)
02269     {
02270       dbus_set_error (error, _dbus_error_from_errno (errno),
02271                       "Could not close file %s: %s",
02272                       tmp_filename_c, _dbus_strerror (errno));
02273 
02274       goto out;
02275     }
02276 
02277   fd = -1;
02278   
02279   if (rename (tmp_filename_c, filename_c) < 0)
02280     {
02281       dbus_set_error (error, _dbus_error_from_errno (errno),
02282                       "Could not rename %s to %s: %s",
02283                       tmp_filename_c, filename_c,
02284                       _dbus_strerror (errno));
02285 
02286       goto out;
02287     }
02288 
02289   need_unlink = FALSE;
02290   
02291   retval = TRUE;
02292   
02293  out:
02294   /* close first, then unlink, to prevent ".nfs34234235" garbage
02295    * files
02296    */
02297 
02298   if (fd >= 0)
02299     close (fd);
02300         
02301   if (need_unlink && unlink (tmp_filename_c) < 0)
02302     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02303                    tmp_filename_c, _dbus_strerror (errno));
02304 
02305   _dbus_string_free (&tmp_filename);
02306 
02307   if (!retval)
02308     _DBUS_ASSERT_ERROR_IS_SET (error);
02309   
02310   return retval;
02311 }
02312 
02319 dbus_bool_t
02320 _dbus_create_file_exclusively (const DBusString *filename,
02321                                DBusError        *error)
02322 {
02323   int fd;
02324   const char *filename_c;
02325 
02326   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02327   
02328   filename_c = _dbus_string_get_const_data (filename);
02329   
02330   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02331              0600);
02332   if (fd < 0)
02333     {
02334       dbus_set_error (error,
02335                       DBUS_ERROR_FAILED,
02336                       "Could not create file %s: %s\n",
02337                       filename_c,
02338                       _dbus_strerror (errno));
02339       return FALSE;
02340     }
02341 
02342   if (close (fd) < 0)
02343     {
02344       dbus_set_error (error,
02345                       DBUS_ERROR_FAILED,
02346                       "Could not close file %s: %s\n",
02347                       filename_c,
02348                       _dbus_strerror (errno));
02349       return FALSE;
02350     }
02351   
02352   return TRUE;
02353 }
02354 
02363 dbus_bool_t
02364 _dbus_delete_file (const DBusString *filename,
02365                    DBusError        *error)
02366 {
02367   const char *filename_c;
02368 
02369   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02370   
02371   filename_c = _dbus_string_get_const_data (filename);
02372 
02373   if (unlink (filename_c) < 0)
02374     {
02375       dbus_set_error (error, DBUS_ERROR_FAILED,
02376                       "Failed to delete file %s: %s\n",
02377                       filename_c, _dbus_strerror (errno));
02378       return FALSE;
02379     }
02380   else
02381     return TRUE;
02382 }
02383 
02392 dbus_bool_t
02393 _dbus_create_directory (const DBusString *filename,
02394                         DBusError        *error)
02395 {
02396   const char *filename_c;
02397 
02398   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02399   
02400   filename_c = _dbus_string_get_const_data (filename);
02401 
02402   if (mkdir (filename_c, 0700) < 0)
02403     {
02404       if (errno == EEXIST)
02405         return TRUE;
02406       
02407       dbus_set_error (error, DBUS_ERROR_FAILED,
02408                       "Failed to create directory %s: %s\n",
02409                       filename_c, _dbus_strerror (errno));
02410       return FALSE;
02411     }
02412   else
02413     return TRUE;
02414 }
02415 
02423 dbus_bool_t
02424 _dbus_delete_directory (const DBusString *filename,
02425                         DBusError        *error)
02426 {
02427   const char *filename_c;
02428   
02429   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02430 
02431   filename_c = _dbus_string_get_const_data (filename);
02432 
02433   if (rmdir (filename_c) != 0)
02434     {
02435       dbus_set_error (error, DBUS_ERROR_FAILED,
02436                       "Failed to remove directory %s: %s\n",
02437                       filename_c, _dbus_strerror (errno));
02438       return FALSE;
02439     }
02440   
02441   return TRUE;
02442 }
02443 
02454 dbus_bool_t
02455 _dbus_concat_dir_and_file (DBusString       *dir,
02456                            const DBusString *next_component)
02457 {
02458   dbus_bool_t dir_ends_in_slash;
02459   dbus_bool_t file_starts_with_slash;
02460 
02461   if (_dbus_string_get_length (dir) == 0 ||
02462       _dbus_string_get_length (next_component) == 0)
02463     return TRUE;
02464   
02465   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02466                                                     _dbus_string_get_length (dir) - 1);
02467 
02468   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02469 
02470   if (dir_ends_in_slash && file_starts_with_slash)
02471     {
02472       _dbus_string_shorten (dir, 1);
02473     }
02474   else if (!(dir_ends_in_slash || file_starts_with_slash))
02475     {
02476       if (!_dbus_string_append_byte (dir, '/'))
02477         return FALSE;
02478     }
02479 
02480   return _dbus_string_copy (next_component, 0, dir,
02481                             _dbus_string_get_length (dir));
02482 }
02483 
02490 dbus_bool_t
02491 _dbus_string_get_dirname  (const DBusString *filename,
02492                            DBusString       *dirname)
02493 {
02494   int sep;
02495   
02496   _dbus_assert (filename != dirname);
02497   _dbus_assert (filename != NULL);
02498   _dbus_assert (dirname != NULL);
02499 
02500   /* Ignore any separators on the end */
02501   sep = _dbus_string_get_length (filename);
02502   if (sep == 0)
02503     return _dbus_string_append (dirname, "."); /* empty string passed in */
02504     
02505   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02506     --sep;
02507 
02508   _dbus_assert (sep >= 0);
02509   
02510   if (sep == 0)
02511     return _dbus_string_append (dirname, "/");
02512   
02513   /* Now find the previous separator */
02514   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02515   if (sep < 0)
02516     return _dbus_string_append (dirname, ".");
02517   
02518   /* skip multiple separators */
02519   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02520     --sep;
02521 
02522   _dbus_assert (sep >= 0);
02523   
02524   if (sep == 0 &&
02525       _dbus_string_get_byte (filename, 0) == '/')
02526     return _dbus_string_append (dirname, "/");
02527   else
02528     return _dbus_string_copy_len (filename, 0, sep - 0,
02529                                   dirname, _dbus_string_get_length (dirname));
02530 }
02531 
02538 dbus_bool_t
02539 _dbus_path_is_absolute (const DBusString *filename)
02540 {
02541   if (_dbus_string_get_length (filename) > 0)
02542     return _dbus_string_get_byte (filename, 0) == '/';
02543   else
02544     return FALSE;
02545 }
02546 
02550 struct DBusDirIter
02551 {
02552   DIR *d; 
02554 };
02555 
02563 DBusDirIter*
02564 _dbus_directory_open (const DBusString *filename,
02565                       DBusError        *error)
02566 {
02567   DIR *d;
02568   DBusDirIter *iter;
02569   const char *filename_c;
02570 
02571   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02572   
02573   filename_c = _dbus_string_get_const_data (filename);
02574 
02575   d = opendir (filename_c);
02576   if (d == NULL)
02577     {
02578       dbus_set_error (error, _dbus_error_from_errno (errno),
02579                       "Failed to read directory \"%s\": %s",
02580                       filename_c,
02581                       _dbus_strerror (errno));
02582       return NULL;
02583     }
02584   iter = dbus_new0 (DBusDirIter, 1);
02585   if (iter == NULL)
02586     {
02587       closedir (d);
02588       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02589                       "Could not allocate memory for directory iterator");
02590       return NULL;
02591     }
02592 
02593   iter->d = d;
02594 
02595   return iter;
02596 }
02597 
02611 dbus_bool_t
02612 _dbus_directory_get_next_file (DBusDirIter      *iter,
02613                                DBusString       *filename,
02614                                DBusError        *error)
02615 {
02616   struct dirent *ent;
02617 
02618   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02619   
02620  again:
02621   errno = 0;
02622   ent = readdir (iter->d);
02623   if (ent == NULL)
02624     {
02625       if (errno != 0)
02626         dbus_set_error (error,
02627                         _dbus_error_from_errno (errno),
02628                         "%s", _dbus_strerror (errno));
02629       return FALSE;
02630     }
02631   else if (ent->d_name[0] == '.' &&
02632            (ent->d_name[1] == '\0' ||
02633             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02634     goto again;
02635   else
02636     {
02637       _dbus_string_set_length (filename, 0);
02638       if (!_dbus_string_append (filename, ent->d_name))
02639         {
02640           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02641                           "No memory to read directory entry");
02642           return FALSE;
02643         }
02644       else
02645         return TRUE;
02646     }
02647 }
02648 
02652 void
02653 _dbus_directory_close (DBusDirIter *iter)
02654 {
02655   closedir (iter->d);
02656   dbus_free (iter);
02657 }
02658 
02659 static dbus_bool_t
02660 pseudorandom_generate_random_bytes (DBusString *str,
02661                                     int         n_bytes)
02662 {
02663   int old_len;
02664   unsigned long tv_usec;
02665   int i;
02666   
02667   old_len = _dbus_string_get_length (str);
02668 
02669   /* fall back to pseudorandom */
02670   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02671                  n_bytes);
02672   
02673   _dbus_get_current_time (NULL, &tv_usec);
02674   srand (tv_usec);
02675   
02676   i = 0;
02677   while (i < n_bytes)
02678     {
02679       double r;
02680       unsigned int b;
02681           
02682       r = rand ();
02683       b = (r / (double) RAND_MAX) * 255.0;
02684           
02685       if (!_dbus_string_append_byte (str, b))
02686         goto failed;
02687           
02688       ++i;
02689     }
02690 
02691   return TRUE;
02692 
02693  failed:
02694   _dbus_string_set_length (str, old_len);
02695   return FALSE;
02696 }
02697 
02706 dbus_bool_t
02707 _dbus_generate_random_bytes (DBusString *str,
02708                              int         n_bytes)
02709 {
02710   int old_len;
02711   int fd;
02712 
02713   /* FALSE return means "no memory", if it could
02714    * mean something else then we'd need to return
02715    * a DBusError. So we always fall back to pseudorandom
02716    * if the I/O fails.
02717    */
02718   
02719   old_len = _dbus_string_get_length (str);
02720   fd = -1;
02721 
02722   /* note, urandom on linux will fall back to pseudorandom */
02723   fd = open ("/dev/urandom", O_RDONLY);
02724   if (fd < 0)
02725     return pseudorandom_generate_random_bytes (str, n_bytes);
02726 
02727   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02728     {
02729       close (fd);
02730       _dbus_string_set_length (str, old_len);
02731       return pseudorandom_generate_random_bytes (str, n_bytes);
02732     }
02733 
02734   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02735                  n_bytes);
02736   
02737   close (fd);
02738   
02739   return TRUE;
02740 }
02741 
02750 dbus_bool_t
02751 _dbus_generate_random_ascii (DBusString *str,
02752                              int         n_bytes)
02753 {
02754   static const char letters[] =
02755     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02756   int i;
02757   int len;
02758   
02759   if (!_dbus_generate_random_bytes (str, n_bytes))
02760     return FALSE;
02761   
02762   len = _dbus_string_get_length (str);
02763   i = len - n_bytes;
02764   while (i < len)
02765     {
02766       _dbus_string_set_byte (str, i,
02767                              letters[_dbus_string_get_byte (str, i) %
02768                                      (sizeof (letters) - 1)]);
02769 
02770       ++i;
02771     }
02772 
02773   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02774                                              n_bytes));
02775 
02776   return TRUE;
02777 }
02778 
02786 const char*
02787 _dbus_strerror (int error_number)
02788 {
02789   const char *msg;
02790   
02791   msg = strerror (error_number);
02792   if (msg == NULL)
02793     msg = "unknown";
02794 
02795   return msg;
02796 }
02797 
02801 void
02802 _dbus_disable_sigpipe (void)
02803 {
02804   signal (SIGPIPE, SIG_IGN);
02805 }
02806 
02814 void
02815 _dbus_fd_set_close_on_exec (int fd)
02816 {
02817   int val;
02818   
02819   val = fcntl (fd, F_GETFD, 0);
02820   
02821   if (val < 0)
02822     return;
02823 
02824   val |= FD_CLOEXEC;
02825   
02826   fcntl (fd, F_SETFD, val);
02827 }
02828 
02838 const char*
02839 _dbus_error_from_errno (int error_number)
02840 {
02841   switch (error_number)
02842     {
02843     case 0:
02844       return DBUS_ERROR_FAILED;
02845       
02846 #ifdef EPROTONOSUPPORT
02847     case EPROTONOSUPPORT:
02848       return DBUS_ERROR_NOT_SUPPORTED;
02849 #endif
02850 #ifdef EAFNOSUPPORT
02851     case EAFNOSUPPORT:
02852       return DBUS_ERROR_NOT_SUPPORTED;
02853 #endif
02854 #ifdef ENFILE
02855     case ENFILE:
02856       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02857 #endif
02858 #ifdef EMFILE
02859     case EMFILE:
02860       return DBUS_ERROR_LIMITS_EXCEEDED;
02861 #endif
02862 #ifdef EACCES
02863     case EACCES:
02864       return DBUS_ERROR_ACCESS_DENIED;
02865 #endif
02866 #ifdef EPERM
02867     case EPERM:
02868       return DBUS_ERROR_ACCESS_DENIED;
02869 #endif
02870 #ifdef ENOBUFS
02871     case ENOBUFS:
02872       return DBUS_ERROR_NO_MEMORY;
02873 #endif
02874 #ifdef ENOMEM
02875     case ENOMEM:
02876       return DBUS_ERROR_NO_MEMORY;
02877 #endif
02878 #ifdef EINVAL
02879     case EINVAL:
02880       return DBUS_ERROR_FAILED;
02881 #endif
02882 #ifdef EBADF
02883     case EBADF:
02884       return DBUS_ERROR_FAILED;
02885 #endif
02886 #ifdef EFAULT
02887     case EFAULT:
02888       return DBUS_ERROR_FAILED;
02889 #endif
02890 #ifdef ENOTSOCK
02891     case ENOTSOCK:
02892       return DBUS_ERROR_FAILED;
02893 #endif
02894 #ifdef EISCONN
02895     case EISCONN:
02896       return DBUS_ERROR_FAILED;
02897 #endif
02898 #ifdef ECONNREFUSED
02899     case ECONNREFUSED:
02900       return DBUS_ERROR_NO_SERVER;
02901 #endif
02902 #ifdef ETIMEDOUT
02903     case ETIMEDOUT:
02904       return DBUS_ERROR_TIMEOUT;
02905 #endif
02906 #ifdef ENETUNREACH
02907     case ENETUNREACH:
02908       return DBUS_ERROR_NO_NETWORK;
02909 #endif
02910 #ifdef EADDRINUSE
02911     case EADDRINUSE:
02912       return DBUS_ERROR_ADDRESS_IN_USE;
02913 #endif
02914 #ifdef EEXIST
02915     case EEXIST:
02916       return DBUS_ERROR_FILE_NOT_FOUND;
02917 #endif
02918 #ifdef ENOENT
02919     case ENOENT:
02920       return DBUS_ERROR_FILE_NOT_FOUND;
02921 #endif
02922     }
02923 
02924   return DBUS_ERROR_FAILED;
02925 }
02926 
02932 void
02933 _dbus_exit (int code)
02934 {
02935   _exit (code);
02936 }
02937 
02946 dbus_bool_t
02947 _dbus_stat (const DBusString *filename,
02948             DBusStat         *statbuf,
02949             DBusError        *error)
02950 {
02951   const char *filename_c;
02952   struct stat sb;
02953 
02954   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02955   
02956   filename_c = _dbus_string_get_const_data (filename);
02957 
02958   if (stat (filename_c, &sb) < 0)
02959     {
02960       dbus_set_error (error, _dbus_error_from_errno (errno),
02961                       "%s", _dbus_strerror (errno));
02962       return FALSE;
02963     }
02964 
02965   statbuf->mode = sb.st_mode;
02966   statbuf->nlink = sb.st_nlink;
02967   statbuf->uid = sb.st_uid;
02968   statbuf->gid = sb.st_gid;
02969   statbuf->size = sb.st_size;
02970   statbuf->atime = sb.st_atime;
02971   statbuf->mtime = sb.st_mtime;
02972   statbuf->ctime = sb.st_ctime;
02973 
02974   return TRUE;
02975 }
02976 
02987 dbus_bool_t
02988 _dbus_full_duplex_pipe (int        *fd1,
02989                         int        *fd2,
02990                         dbus_bool_t blocking,
02991                         DBusError  *error)
02992 {
02993 #ifdef HAVE_SOCKETPAIR
02994   int fds[2];
02995 
02996   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02997   
02998   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02999     {
03000       dbus_set_error (error, _dbus_error_from_errno (errno),
03001                       "Could not create full-duplex pipe");
03002       return FALSE;
03003     }
03004 
03005   if (!blocking &&
03006       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03007        !_dbus_set_fd_nonblocking (fds[1], NULL)))
03008     {
03009       dbus_set_error (error, _dbus_error_from_errno (errno),
03010                       "Could not set full-duplex pipe nonblocking");
03011       
03012       close (fds[0]);
03013       close (fds[1]);
03014       
03015       return FALSE;
03016     }
03017   
03018   *fd1 = fds[0];
03019   *fd2 = fds[1];
03020   
03021   return TRUE;  
03022 #else
03023   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03024   dbus_set_error (error, DBUS_ERROR_FAILED,
03025                   "_dbus_full_duplex_pipe() not implemented on this OS");
03026   return FALSE;
03027 #endif
03028 }
03029 
03037 dbus_bool_t
03038 _dbus_close (int        fd,
03039              DBusError *error)
03040 {
03041   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03042   
03043  again:
03044   if (close (fd) < 0)
03045     {
03046       if (errno == EINTR)
03047         goto again;
03048 
03049       dbus_set_error (error, _dbus_error_from_errno (errno),
03050                       "Could not close fd %d", fd);
03051       return FALSE;
03052     }
03053 
03054   return TRUE;
03055 }
03056 
03064 dbus_bool_t
03065 _dbus_set_fd_nonblocking (int             fd,
03066                           DBusError      *error)
03067 {
03068   int val;
03069 
03070   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03071   
03072   val = fcntl (fd, F_GETFL, 0);
03073   if (val < 0)
03074     {
03075       dbus_set_error (error, _dbus_error_from_errno (errno),
03076                       "Failed to get flags from file descriptor %d: %s",
03077                       fd, _dbus_strerror (errno));
03078       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03079                      _dbus_strerror (errno));
03080       return FALSE;
03081     }
03082 
03083   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03084     {
03085       dbus_set_error (error, _dbus_error_from_errno (errno),
03086                       "Failed to set nonblocking flag of file descriptor %d: %s",
03087                       fd, _dbus_strerror (errno));
03088       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03089                      fd, _dbus_strerror (errno));
03090 
03091       return FALSE;
03092     }
03093 
03094   return TRUE;
03095 }
03096 
03102 void
03103 _dbus_print_backtrace (void)
03104 {
03105 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03106   void *bt[500];
03107   int bt_size;
03108   int i;
03109   char **syms;
03110   
03111   bt_size = backtrace (bt, 500);
03112 
03113   syms = backtrace_symbols (bt, bt_size);
03114   
03115   i = 0;
03116   while (i < bt_size)
03117     {
03118       _dbus_verbose ("  %s\n", syms[i]);
03119       ++i;
03120     }
03121 
03122   free (syms);
03123 #else
03124   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
03125 #endif
03126 }
03127 
03135 dbus_bool_t
03136 _dbus_become_daemon (const DBusString *pidfile,
03137                      DBusError        *error)
03138 {
03139   const char *s;
03140   pid_t child_pid;
03141   int dev_null_fd;
03142 
03143   _dbus_verbose ("Becoming a daemon...\n");
03144 
03145   _dbus_verbose ("chdir to /\n");
03146   if (chdir ("/") < 0)
03147     {
03148       dbus_set_error (error, DBUS_ERROR_FAILED,
03149                       "Could not chdir() to root directory");
03150       return FALSE;
03151     }
03152 
03153   _dbus_verbose ("forking...\n");
03154   switch ((child_pid = fork ()))
03155     {
03156     case -1:
03157       _dbus_verbose ("fork failed\n");
03158       dbus_set_error (error, _dbus_error_from_errno (errno),
03159                       "Failed to fork daemon: %s", _dbus_strerror (errno));
03160       return FALSE;
03161       break;
03162 
03163     case 0:
03164       _dbus_verbose ("in child, closing std file descriptors\n");
03165 
03166       /* silently ignore failures here, if someone
03167        * doesn't have /dev/null we may as well try
03168        * to continue anyhow
03169        */
03170       
03171       dev_null_fd = open ("/dev/null", O_RDWR);
03172       if (dev_null_fd >= 0)
03173         {
03174           dup2 (dev_null_fd, 0);
03175           dup2 (dev_null_fd, 1);
03176           
03177           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03178           if (s == NULL || *s == '\0')
03179             dup2 (dev_null_fd, 2);
03180           else
03181             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
03182         }
03183 
03184       /* Get a predictable umask */
03185       _dbus_verbose ("setting umask\n");
03186       umask (022);
03187       break;
03188 
03189     default:
03190       if (pidfile)
03191         {
03192           _dbus_verbose ("parent writing pid file\n");
03193           if (!_dbus_write_pid_file (pidfile,
03194                                      child_pid,
03195                                      error))
03196             {
03197               _dbus_verbose ("pid file write failed, killing child\n");
03198               kill (child_pid, SIGTERM);
03199               return FALSE;
03200             }
03201         }
03202       _dbus_verbose ("parent exiting\n");
03203       _exit (0);
03204       break;
03205     }
03206 
03207   _dbus_verbose ("calling setsid()\n");
03208   if (setsid () == -1)
03209     _dbus_assert_not_reached ("setsid() failed");
03210   
03211   return TRUE;
03212 }
03213 
03222 dbus_bool_t
03223 _dbus_write_pid_file (const DBusString *filename,
03224                       unsigned long     pid,
03225                       DBusError        *error)
03226 {
03227   const char *cfilename;
03228   int fd;
03229   FILE *f;
03230 
03231   cfilename = _dbus_string_get_const_data (filename);
03232   
03233   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03234   
03235   if (fd < 0)
03236     {
03237       dbus_set_error (error, _dbus_error_from_errno (errno),
03238                       "Failed to open \"%s\": %s", cfilename,
03239                       _dbus_strerror (errno));
03240       return FALSE;
03241     }
03242 
03243   if ((f = fdopen (fd, "w")) == NULL)
03244     {
03245       dbus_set_error (error, _dbus_error_from_errno (errno),
03246                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03247       close (fd);
03248       return FALSE;
03249     }
03250   
03251   if (fprintf (f, "%lu\n", pid) < 0)
03252     {
03253       dbus_set_error (error, _dbus_error_from_errno (errno),
03254                       "Failed to write to \"%s\": %s", cfilename,
03255                       _dbus_strerror (errno));
03256       return FALSE;
03257     }
03258 
03259   if (fclose (f) == EOF)
03260     {
03261       dbus_set_error (error, _dbus_error_from_errno (errno),
03262                       "Failed to close \"%s\": %s", cfilename,
03263                       _dbus_strerror (errno));
03264       return FALSE;
03265     }
03266   
03267   return TRUE;
03268 }
03269 
03278 dbus_bool_t
03279 _dbus_change_identity  (dbus_uid_t     uid,
03280                         dbus_gid_t     gid,
03281                         DBusError     *error)
03282 {
03283   /* Set GID first, or the setuid may remove our permission
03284    * to change the GID
03285    */
03286   if (setgid (gid) < 0)
03287     {
03288       dbus_set_error (error, _dbus_error_from_errno (errno),
03289                       "Failed to set GID to %lu: %s", gid,
03290                       _dbus_strerror (errno));
03291       return FALSE;
03292     }
03293   
03294   if (setuid (uid) < 0)
03295     {
03296       dbus_set_error (error, _dbus_error_from_errno (errno),
03297                       "Failed to set UID to %lu: %s", uid,
03298                       _dbus_strerror (errno));
03299       return FALSE;
03300     }
03301   
03302   return TRUE;
03303 }
03304 
03310 void
03311 _dbus_set_signal_handler (int               sig,
03312                           DBusSignalHandler handler)
03313 {
03314   struct sigaction act;
03315   sigset_t empty_mask;
03316   
03317   sigemptyset (&empty_mask);
03318   act.sa_handler = handler;
03319   act.sa_mask    = empty_mask;
03320   act.sa_flags   = 0;
03321   sigaction (sig,  &act, 0);
03322 }
03323 
03324 
03325 #ifdef DBUS_BUILD_TESTS
03326 #include <stdlib.h>
03327 static void
03328 check_dirname (const char *filename,
03329                const char *dirname)
03330 {
03331   DBusString f, d;
03332   
03333   _dbus_string_init_const (&f, filename);
03334 
03335   if (!_dbus_string_init (&d))
03336     _dbus_assert_not_reached ("no memory");
03337 
03338   if (!_dbus_string_get_dirname (&f, &d))
03339     _dbus_assert_not_reached ("no memory");
03340 
03341   if (!_dbus_string_equal_c_str (&d, dirname))
03342     {
03343       _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03344                   filename,
03345                   _dbus_string_get_const_data (&d),
03346                   dirname);
03347       exit (1);
03348     }
03349 
03350   _dbus_string_free (&d);
03351 }
03352 
03353 static void
03354 check_path_absolute (const char *path,
03355                      dbus_bool_t expected)
03356 {
03357   DBusString p;
03358 
03359   _dbus_string_init_const (&p, path);
03360 
03361   if (_dbus_path_is_absolute (&p) != expected)
03362     {
03363       _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03364                   path, expected, _dbus_path_is_absolute (&p));
03365       exit (1);
03366     }
03367 }
03368 
03374 dbus_bool_t
03375 _dbus_sysdeps_test (void)
03376 {
03377   DBusString str;
03378   double val;
03379   int pos;
03380   
03381   check_dirname ("foo", ".");
03382   check_dirname ("foo/bar", "foo");
03383   check_dirname ("foo//bar", "foo");
03384   check_dirname ("foo///bar", "foo");
03385   check_dirname ("foo/bar/", "foo");
03386   check_dirname ("foo//bar/", "foo");
03387   check_dirname ("foo///bar/", "foo");
03388   check_dirname ("foo/bar//", "foo");
03389   check_dirname ("foo//bar////", "foo");
03390   check_dirname ("foo///bar///////", "foo");
03391   check_dirname ("/foo", "/");
03392   check_dirname ("
03393   check_dirname ("/foo/bar", "/foo");
03394   check_dirname ("/foo//bar", "/foo");
03395   check_dirname ("/foo///bar", "/foo");
03396   check_dirname ("/", "/");
03397   check_dirname ("
03398   check_dirname ("", ".");  
03399 
03400 
03401   _dbus_string_init_const (&str, "3.5");
03402   if (!_dbus_string_parse_double (&str,
03403                                   0, &val, &pos))
03404     {
03405       _dbus_warn ("Failed to parse double");
03406       exit (1);
03407     }
03408   if (val != 3.5)
03409     {
03410       _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03411       exit (1);
03412     }
03413   if (pos != 3)
03414     {
03415       _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03416       exit (1);
03417     }
03418 
03419   _dbus_string_init_const (&str, "0xff");
03420   if (!_dbus_string_parse_double (&str,
03421                                   0, &val, &pos))
03422     {
03423       _dbus_warn ("Failed to parse double");
03424       exit (1);
03425     }
03426   if (val != 0xff)
03427     {
03428       _dbus_warn ("Failed to parse 0xff correctly, got: %f", val);
03429       exit (1);
03430     }
03431   if (pos != 4)
03432     {
03433       _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
03434       exit (1);
03435     }
03436   
03437   check_path_absolute ("/", TRUE);
03438   check_path_absolute ("/foo", TRUE);
03439   check_path_absolute ("", FALSE);
03440   check_path_absolute ("foo", FALSE);
03441   check_path_absolute ("foo/bar", FALSE);
03442   
03443   return TRUE;
03444 }
03445 #endif /* DBUS_BUILD_TESTS */
03446 

Generated on Wed Jun 9 05:01:27 2004 for D-BUS by doxygen1.2.15