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 1.2
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   abort ();
00080   _exit (1); /* in case someone manages to ignore SIGABRT */
00081 }
00082 
00094 dbus_bool_t
00095 _dbus_setenv (const char *varname,
00096               const char *value)
00097 {
00098   _dbus_assert (varname != NULL);
00099   
00100   if (value == NULL)
00101     {
00102 #ifdef HAVE_UNSETENV
00103       unsetenv (varname);
00104       return TRUE;
00105 #else
00106       char *putenv_value;
00107       size_t len;
00108 
00109       len = strlen (varname);
00110 
00111       /* Use system malloc to avoid memleaks that dbus_malloc
00112        * will get upset about.
00113        */
00114       
00115       putenv_value = malloc (len + 1);
00116       if (putenv_value == NULL)
00117         return FALSE;
00118 
00119       strcpy (putenv_value, varname);
00120       
00121       return (putenv (putenv_value) == 0);
00122 #endif
00123     }
00124   else
00125     {
00126 #ifdef HAVE_SETENV
00127       return (setenv (varname, value, TRUE) == 0);
00128 #else
00129       char *putenv_value;
00130       size_t len;
00131       size_t varname_len;
00132       size_t value_len;
00133 
00134       varname_len = strlen (varname);
00135       value_len = strlen (value);
00136       
00137       len = varname_len + value_len + 1 /* '=' */ ;
00138 
00139       /* Use system malloc to avoid memleaks that dbus_malloc
00140        * will get upset about.
00141        */
00142       
00143       putenv_value = malloc (len + 1);
00144       if (putenv_value == NULL)
00145         return FALSE;
00146 
00147       strcpy (putenv_value, varname);
00148       strcpy (putenv_value + varname_len, "=");
00149       strcpy (putenv_value + varname_len + 1, value);
00150       
00151       return (putenv (putenv_value) == 0);
00152 #endif
00153     }
00154 }
00155 
00162 const char*
00163 _dbus_getenv (const char *varname)
00164 {  
00165   return getenv (varname);
00166 }
00167 
00181 int
00182 _dbus_read (int               fd,
00183             DBusString       *buffer,
00184             int               count)
00185 {
00186   int bytes_read;
00187   int start;
00188   char *data;
00189 
00190   _dbus_assert (count >= 0);
00191   
00192   start = _dbus_string_get_length (buffer);
00193 
00194   if (!_dbus_string_lengthen (buffer, count))
00195     {
00196       errno = ENOMEM;
00197       return -1;
00198     }
00199 
00200   data = _dbus_string_get_data_len (buffer, start, count);
00201 
00202  again:
00203   
00204   bytes_read = read (fd, data, count);
00205 
00206   if (bytes_read < 0)
00207     {
00208       if (errno == EINTR)
00209         goto again;
00210       else
00211         {
00212           /* put length back (note that this doesn't actually realloc anything) */
00213           _dbus_string_set_length (buffer, start);
00214           return -1;
00215         }
00216     }
00217   else
00218     {
00219       /* put length back (doesn't actually realloc) */
00220       _dbus_string_set_length (buffer, start + bytes_read);
00221 
00222 #if 0
00223       if (bytes_read > 0)
00224         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00225 #endif
00226       
00227       return bytes_read;
00228     }
00229 }
00230 
00241 int
00242 _dbus_write (int               fd,
00243              const DBusString *buffer,
00244              int               start,
00245              int               len)
00246 {
00247   const char *data;
00248   int bytes_written;
00249   
00250   data = _dbus_string_get_const_data_len (buffer, start, len);
00251   
00252  again:
00253 
00254   bytes_written = write (fd, data, len);
00255 
00256   if (bytes_written < 0 && errno == EINTR)
00257     goto again;
00258 
00259 #if 0
00260   if (bytes_written > 0)
00261     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00262 #endif
00263   
00264   return bytes_written;
00265 }
00266 
00287 int
00288 _dbus_write_two (int               fd,
00289                  const DBusString *buffer1,
00290                  int               start1,
00291                  int               len1,
00292                  const DBusString *buffer2,
00293                  int               start2,
00294                  int               len2)
00295 {
00296   _dbus_assert (buffer1 != NULL);
00297   _dbus_assert (start1 >= 0);
00298   _dbus_assert (start2 >= 0);
00299   _dbus_assert (len1 >= 0);
00300   _dbus_assert (len2 >= 0);
00301   
00302 #ifdef HAVE_WRITEV
00303   {
00304     struct iovec vectors[2];
00305     const char *data1;
00306     const char *data2;
00307     int bytes_written;
00308 
00309     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00310 
00311     if (buffer2 != NULL)
00312       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00313     else
00314       {
00315         data2 = NULL;
00316         start2 = 0;
00317         len2 = 0;
00318       }
00319    
00320     vectors[0].iov_base = (char*) data1;
00321     vectors[0].iov_len = len1;
00322     vectors[1].iov_base = (char*) data2;
00323     vectors[1].iov_len = len2;
00324 
00325   again:
00326    
00327     bytes_written = writev (fd,
00328                             vectors,
00329                             data2 ? 2 : 1);
00330 
00331     if (bytes_written < 0 && errno == EINTR)
00332       goto again;
00333    
00334     return bytes_written;
00335   }
00336 #else /* HAVE_WRITEV */
00337   {
00338     int ret1;
00339     
00340     ret1 = _dbus_write (fd, buffer1, start1, len1);
00341     if (ret1 == len1 && buffer2 != NULL)
00342       {
00343         ret2 = _dbus_write (fd, buffer2, start2, len2);
00344         if (ret2 < 0)
00345           ret2 = 0; /* we can't report an error as the first write was OK */
00346        
00347         return ret1 + ret2;
00348       }
00349     else
00350       return ret1;
00351   }
00352 #endif /* !HAVE_WRITEV */   
00353 }
00354 
00355 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00356 
00384 int
00385 _dbus_connect_unix_socket (const char     *path,
00386                            dbus_bool_t     abstract,
00387                            DBusError      *error)
00388 {
00389   int fd;
00390   struct sockaddr_un addr;  
00391 
00392   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00393 
00394   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00395                  path, abstract);
00396   
00397   fd = socket (PF_UNIX, SOCK_STREAM, 0);
00398   
00399   if (fd < 0)
00400     {
00401       dbus_set_error (error,
00402                       _dbus_error_from_errno (errno),
00403                       "Failed to create socket: %s",
00404                       _dbus_strerror (errno)); 
00405       
00406       return -1;
00407     }
00408 
00409   _DBUS_ZERO (addr);
00410   addr.sun_family = AF_UNIX;
00411 
00412   if (abstract)
00413     {
00414 #ifdef HAVE_ABSTRACT_SOCKETS
00415       /* remember that abstract names aren't nul-terminated so we rely
00416        * on sun_path being filled in with zeroes above.
00417        */
00418       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00419       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00420       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00421 #else /* HAVE_ABSTRACT_SOCKETS */
00422       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00423                       "Operating system does not support abstract socket namespace\n");
00424       close (fd);
00425       return -1;
00426 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00427     }
00428   else
00429     {
00430       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00431     }
00432   
00433   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00434     {      
00435       dbus_set_error (error,
00436                       _dbus_error_from_errno (errno),
00437                       "Failed to connect to socket %s: %s",
00438                       path, _dbus_strerror (errno));
00439 
00440       close (fd);
00441       fd = -1;
00442       
00443       return -1;
00444     }
00445 
00446   if (!_dbus_set_fd_nonblocking (fd, error))
00447     {
00448       _DBUS_ASSERT_ERROR_IS_SET (error);
00449       
00450       close (fd);
00451       fd = -1;
00452 
00453       return -1;
00454     }
00455 
00456   return fd;
00457 }
00458 
00474 int
00475 _dbus_listen_unix_socket (const char     *path,
00476                           dbus_bool_t     abstract,
00477                           DBusError      *error)
00478 {
00479   int listen_fd;
00480   struct sockaddr_un addr;
00481 
00482   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00483 
00484   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00485                  path, abstract);
00486   
00487   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00488   
00489   if (listen_fd < 0)
00490     {
00491       dbus_set_error (error, _dbus_error_from_errno (errno),
00492                       "Failed to create socket \"%s\": %s",
00493                       path, _dbus_strerror (errno));
00494       return -1;
00495     }
00496 
00497   _DBUS_ZERO (addr);
00498   addr.sun_family = AF_UNIX;
00499   
00500   if (abstract)
00501     {
00502 #ifdef HAVE_ABSTRACT_SOCKETS
00503       /* remember that abstract names aren't nul-terminated so we rely
00504        * on sun_path being filled in with zeroes above.
00505        */
00506       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00507       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00508       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00509 #else /* HAVE_ABSTRACT_SOCKETS */
00510       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00511                       "Operating system does not support abstract socket namespace\n");
00512       close (listen_fd);
00513       return -1;
00514 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00515     }
00516   else
00517     {
00518       /* FIXME discussed security implications of this with Nalin,
00519        * and we couldn't think of where it would kick our ass, but
00520        * it still seems a bit sucky. It also has non-security suckage;
00521        * really we'd prefer to exit if the socket is already in use.
00522        * But there doesn't seem to be a good way to do this.
00523        *
00524        * Just to be extra careful, I threw in the stat() - clearly
00525        * the stat() can't *fix* any security issue, but it at least
00526        * avoids inadvertent/accidental data loss.
00527        */
00528       {
00529         struct stat sb;
00530 
00531         if (stat (path, &sb) == 0 &&
00532             S_ISSOCK (sb.st_mode))
00533           unlink (path);
00534       }
00535 
00536       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00537     }
00538   
00539   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00540     {
00541       dbus_set_error (error, _dbus_error_from_errno (errno),
00542                       "Failed to bind socket \"%s\": %s",
00543                       path, _dbus_strerror (errno));
00544       close (listen_fd);
00545       return -1;
00546     }
00547 
00548   if (listen (listen_fd, 30 /* backlog */) < 0)
00549     {
00550       dbus_set_error (error, _dbus_error_from_errno (errno),
00551                       "Failed to listen on socket \"%s\": %s",
00552                       path, _dbus_strerror (errno));
00553       close (listen_fd);
00554       return -1;
00555     }
00556 
00557   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00558     {
00559       _DBUS_ASSERT_ERROR_IS_SET (error);
00560       close (listen_fd);
00561       return -1;
00562     }
00563   
00564   /* Try opening up the permissions, but if we can't, just go ahead
00565    * and continue, maybe it will be good enough.
00566    */
00567   if (!abstract && chmod (path, 0777) < 0)
00568     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00569                 path);
00570   
00571   return listen_fd;
00572 }
00573 
00584 int
00585 _dbus_connect_tcp_socket (const char     *host,
00586                           dbus_uint32_t   port,
00587                           DBusError      *error)
00588 {
00589   int fd;
00590   struct sockaddr_in addr;
00591   struct hostent *he;
00592   struct in_addr *haddr;
00593 
00594   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00595   
00596   fd = socket (AF_INET, SOCK_STREAM, 0);
00597   
00598   if (fd < 0)
00599     {
00600       dbus_set_error (error,
00601                       _dbus_error_from_errno (errno),
00602                       "Failed to create socket: %s",
00603                       _dbus_strerror (errno)); 
00604       
00605       return -1;
00606     }
00607 
00608   if (host == NULL)
00609     host = "localhost";
00610 
00611   he = gethostbyname (host);
00612   if (he == NULL) 
00613     {
00614       dbus_set_error (error,
00615                       _dbus_error_from_errno (errno),
00616                       "Failed to lookup hostname: %s",
00617                       host);
00618       return -1;
00619     }
00620   
00621   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00622 
00623   _DBUS_ZERO (addr);
00624   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00625   addr.sin_family = AF_INET;
00626   addr.sin_port = htons (port);
00627   
00628   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00629     {      
00630       dbus_set_error (error,
00631                        _dbus_error_from_errno (errno),
00632                       "Failed to connect to socket %s: %s:%d",
00633                       host, _dbus_strerror (errno), port);
00634 
00635       close (fd);
00636       fd = -1;
00637       
00638       return -1;
00639     }
00640 
00641   if (!_dbus_set_fd_nonblocking (fd, error))
00642     {
00643       close (fd);
00644       fd = -1;
00645 
00646       return -1;
00647     }
00648 
00649   return fd;
00650 }
00651 
00662 int
00663 _dbus_listen_tcp_socket (const char     *host,
00664                          dbus_uint32_t   port,
00665                          DBusError      *error)
00666 {
00667   int listen_fd;
00668   struct sockaddr_in addr;
00669   struct hostent *he;
00670   struct in_addr *haddr;
00671 
00672   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00673   
00674   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00675   
00676   if (listen_fd < 0)
00677     {
00678       dbus_set_error (error, _dbus_error_from_errno (errno),
00679                       "Failed to create socket \"%s:%d\": %s",
00680                       host, port, _dbus_strerror (errno));
00681       return -1;
00682     }
00683 
00684   if (host == NULL)
00685     host = "localhost";
00686   
00687   he = gethostbyname (host);
00688   if (he == NULL) 
00689     {
00690       dbus_set_error (error,
00691                       _dbus_error_from_errno (errno),
00692                       "Failed to lookup hostname: %s",
00693                       host);
00694       return -1;
00695     }
00696   
00697   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00698 
00699   _DBUS_ZERO (addr);
00700   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00701   addr.sin_family = AF_INET;
00702   addr.sin_port = htons (port);
00703 
00704   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00705     {
00706       dbus_set_error (error, _dbus_error_from_errno (errno),
00707                       "Failed to bind socket \"%s:%d\": %s",
00708                       host, port, _dbus_strerror (errno));
00709       close (listen_fd);
00710       return -1;
00711     }
00712 
00713   if (listen (listen_fd, 30 /* backlog */) < 0)
00714     {
00715       dbus_set_error (error, _dbus_error_from_errno (errno),  
00716                       "Failed to listen on socket \"%s:%d\": %s",
00717                       host, port, _dbus_strerror (errno));
00718       close (listen_fd);
00719       return -1;
00720     }
00721 
00722   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00723     {
00724       close (listen_fd);
00725       return -1;
00726     }
00727   
00728   return listen_fd;
00729 }
00730 
00731 static dbus_bool_t
00732 write_credentials_byte (int             server_fd,
00733                         DBusError      *error)
00734 {
00735   int bytes_written;
00736   char buf[1] = { '\0' };
00737 
00738   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00739   
00740  again:
00741 
00742   bytes_written = write (server_fd, buf, 1);
00743 
00744   if (bytes_written < 0 && errno == EINTR)
00745     goto again;
00746 
00747   if (bytes_written < 0)
00748     {
00749       dbus_set_error (error, _dbus_error_from_errno (errno),
00750                       "Failed to write credentials byte: %s",
00751                      _dbus_strerror (errno));
00752       return FALSE;
00753     }
00754   else if (bytes_written == 0)
00755     {
00756       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00757                       "wrote zero bytes writing credentials byte");
00758       return FALSE;
00759     }
00760   else
00761     {
00762       _dbus_assert (bytes_written == 1);
00763       _dbus_verbose ("wrote credentials byte\n");
00764       return TRUE;
00765     }
00766 }
00767 
00786 dbus_bool_t
00787 _dbus_read_credentials_unix_socket  (int              client_fd,
00788                                      DBusCredentials *credentials,
00789                                      DBusError       *error)
00790 {
00791   struct msghdr msg;
00792   struct iovec iov;
00793   char buf;
00794 
00795 #ifdef HAVE_CMSGCRED 
00796   char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
00797   struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
00798 #endif
00799 
00800   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00801   
00802   /* The POSIX spec certainly doesn't promise this, but
00803    * we need these assertions to fail as soon as we're wrong about
00804    * it so we can do the porting fixups
00805    */
00806   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00807   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00808   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00809 
00810   _dbus_credentials_clear (credentials);
00811 
00812 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00813   /* Set the socket to receive credentials on the next message */
00814   {
00815     int on = 1;
00816     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00817       {
00818         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00819         return FALSE;
00820       }
00821   }
00822 #endif
00823 
00824   iov.iov_base = &buf;
00825   iov.iov_len = 1;
00826 
00827   memset (&msg, 0, sizeof (msg));
00828   msg.msg_iov = &iov;
00829   msg.msg_iovlen = 1;
00830 
00831 #ifdef HAVE_CMSGCRED
00832   memset (cmsgmem, 0, sizeof (cmsgmem));
00833   msg.msg_control = cmsgmem;
00834   msg.msg_controllen = sizeof (cmsgmem);
00835 #endif
00836 
00837  again:
00838   if (recvmsg (client_fd, &msg, 0) < 0)
00839     {
00840       if (errno == EINTR)
00841         goto again;
00842 
00843       dbus_set_error (error, _dbus_error_from_errno (errno),
00844                       "Failed to read credentials byte: %s",
00845                       _dbus_strerror (errno));
00846       return FALSE;
00847     }
00848 
00849   if (buf != '\0')
00850     {
00851       dbus_set_error (error, DBUS_ERROR_FAILED,
00852                       "Credentials byte was not nul");
00853       return FALSE;
00854     }
00855 
00856 #ifdef HAVE_CMSGCRED
00857   if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
00858     {
00859       dbus_set_error (error, DBUS_ERROR_FAILED);
00860       _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
00861       return FALSE;
00862     }
00863 #endif
00864 
00865   _dbus_verbose ("read credentials byte\n");
00866 
00867   {
00868 #ifdef SO_PEERCRED
00869     struct ucred cr;   
00870     int cr_len = sizeof (cr);
00871    
00872     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00873         cr_len == sizeof (cr))
00874       {
00875         credentials->pid = cr.pid;
00876         credentials->uid = cr.uid;
00877         credentials->gid = cr.gid;
00878       }
00879     else
00880       {
00881         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00882                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00883       }
00884 #elif defined(HAVE_CMSGCRED)
00885     struct cmsgcred *cred;
00886 
00887     cred = (struct cmsgcred *) CMSG_DATA (cmsg);
00888 
00889     credentials->pid = cred->cmcred_pid;
00890     credentials->uid = cred->cmcred_euid;
00891     credentials->gid = cred->cmcred_groups[0];
00892 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
00893     _dbus_verbose ("Socket credentials not supported on this OS\n");
00894 #endif
00895   }
00896 
00897   _dbus_verbose ("Credentials:"
00898                  "  pid "DBUS_PID_FORMAT
00899                  "  uid "DBUS_UID_FORMAT
00900                  "  gid "DBUS_GID_FORMAT"\n",
00901                  credentials->pid,
00902                  credentials->uid,
00903                  credentials->gid);
00904     
00905   return TRUE;
00906 }
00907 
00925 dbus_bool_t
00926 _dbus_send_credentials_unix_socket  (int              server_fd,
00927                                      DBusError       *error)
00928 {
00929   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00930   
00931   if (write_credentials_byte (server_fd, error))
00932     return TRUE;
00933   else
00934     return FALSE;
00935 }
00936 
00944 int
00945 _dbus_accept  (int listen_fd)
00946 {
00947   int client_fd;
00948   struct sockaddr addr;
00949   socklen_t addrlen;
00950 
00951   addrlen = sizeof (addr);
00952   
00953  retry:
00954   client_fd = accept (listen_fd, &addr, &addrlen);
00955   
00956   if (client_fd < 0)
00957     {
00958       if (errno == EINTR)
00959         goto retry;
00960     }
00961   
00962   return client_fd;
00963 }
00964 
00979 dbus_bool_t
00980 _dbus_string_append_int (DBusString *str,
00981                          long        value)
00982 {
00983   /* this calculation is from comp.lang.c faq */
00984 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
00985   int orig_len;
00986   int i;
00987   char *buf;
00988   
00989   orig_len = _dbus_string_get_length (str);
00990 
00991   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00992     return FALSE;
00993 
00994   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00995 
00996   snprintf (buf, MAX_LONG_LEN, "%ld", value);
00997 
00998   i = 0;
00999   while (*buf)
01000     {
01001       ++buf;
01002       ++i;
01003     }
01004   
01005   _dbus_string_shorten (str, MAX_LONG_LEN - i);
01006   
01007   return TRUE;
01008 }
01009 
01017 dbus_bool_t
01018 _dbus_string_append_uint (DBusString    *str,
01019                           unsigned long  value)
01020 {
01021   /* this is wrong, but definitely on the high side. */
01022 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01023   int orig_len;
01024   int i;
01025   char *buf;
01026   
01027   orig_len = _dbus_string_get_length (str);
01028 
01029   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01030     return FALSE;
01031 
01032   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01033 
01034   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01035 
01036   i = 0;
01037   while (*buf)
01038     {
01039       ++buf;
01040       ++i;
01041     }
01042   
01043   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01044   
01045   return TRUE;
01046 }
01047 
01055 dbus_bool_t
01056 _dbus_string_append_double (DBusString *str,
01057                             double      value)
01058 {
01059 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
01060   int orig_len;
01061   char *buf;
01062   int i;
01063   
01064   orig_len = _dbus_string_get_length (str);
01065 
01066   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01067     return FALSE;
01068 
01069   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01070 
01071   snprintf (buf, MAX_LONG_LEN, "%g", value);
01072 
01073   i = 0;
01074   while (*buf)
01075     {
01076       ++buf;
01077       ++i;
01078     }
01079   
01080   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01081   
01082   return TRUE;
01083 }
01084 
01097 dbus_bool_t
01098 _dbus_string_parse_int (const DBusString *str,
01099                         int               start,
01100                         long             *value_return,
01101                         int              *end_return)
01102 {
01103   long v;
01104   const char *p;
01105   char *end;
01106 
01107   p = _dbus_string_get_const_data_len (str, start,
01108                                        _dbus_string_get_length (str) - start);
01109 
01110   end = NULL;
01111   errno = 0;
01112   v = strtol (p, &end, 0);
01113   if (end == NULL || end == p || errno != 0)
01114     return FALSE;
01115 
01116   if (value_return)
01117     *value_return = v;
01118   if (end_return)
01119     *end_return = start + (end - p);
01120 
01121   return TRUE;
01122 }
01123 
01124 #ifdef DBUS_BUILD_TESTS
01125 /* Not currently used, so only built when tests are enabled */
01138 dbus_bool_t
01139 _dbus_string_parse_uint (const DBusString *str,
01140                          int               start,
01141                          unsigned long    *value_return,
01142                          int              *end_return)
01143 {
01144   unsigned long v;
01145   const char *p;
01146   char *end;
01147 
01148   p = _dbus_string_get_const_data_len (str, start,
01149                                        _dbus_string_get_length (str) - start);
01150 
01151   end = NULL;
01152   errno = 0;
01153   v = strtoul (p, &end, 0);
01154   if (end == NULL || end == p || errno != 0)
01155     return FALSE;
01156 
01157   if (value_return)
01158     *value_return = v;
01159   if (end_return)
01160     *end_return = start + (end - p);
01161 
01162   return TRUE;
01163 }
01164 #endif /* DBUS_BUILD_TESTS */
01165 
01166 static dbus_bool_t
01167 ascii_isspace (char c)
01168 {
01169   return (c == ' ' ||
01170           c == '\f' ||
01171           c == '\n' ||
01172           c == '\r' ||
01173           c == '\t' ||
01174           c == '\v');
01175 }
01176 
01177 static dbus_bool_t
01178 ascii_isdigit (char c)
01179 {
01180   return c >= '0' && c <= '9';
01181 }
01182 
01183 static dbus_bool_t
01184 ascii_isxdigit (char c)
01185 {
01186   return (ascii_isdigit (c) ||
01187           (c >= 'a' && c <= 'f') ||
01188           (c >= 'A' && c <= 'F'));
01189 }
01190 
01191 
01192 /* Calls strtod in a locale-independent fashion, by looking at
01193  * the locale data and patching the decimal comma to a point.
01194  *
01195  * Relicensed from glib.
01196  */
01197 static double
01198 ascii_strtod (const char *nptr,
01199               char      **endptr)
01200 {
01201   char *fail_pos;
01202   double val;
01203   struct lconv *locale_data;
01204   const char *decimal_point;
01205   int decimal_point_len;
01206   const char *p, *decimal_point_pos;
01207   const char *end = NULL; /* Silence gcc */
01208 
01209   fail_pos = NULL;
01210 
01211   locale_data = localeconv ();
01212   decimal_point = locale_data->decimal_point;
01213   decimal_point_len = strlen (decimal_point);
01214 
01215   _dbus_assert (decimal_point_len != 0);
01216   
01217   decimal_point_pos = NULL;
01218   if (decimal_point[0] != '.' ||
01219       decimal_point[1] != 0)
01220     {
01221       p = nptr;
01222       /* Skip leading space */
01223       while (ascii_isspace (*p))
01224         p++;
01225       
01226       /* Skip leading optional sign */
01227       if (*p == '+' || *p == '-')
01228         p++;
01229       
01230       if (p[0] == '0' &&
01231           (p[1] == 'x' || p[1] == 'X'))
01232         {
01233           p += 2;
01234           /* HEX - find the (optional) decimal point */
01235           
01236           while (ascii_isxdigit (*p))
01237             p++;
01238           
01239           if (*p == '.')
01240             {
01241               decimal_point_pos = p++;
01242               
01243               while (ascii_isxdigit (*p))
01244                 p++;
01245               
01246               if (*p == 'p' || *p == 'P')
01247                 p++;
01248               if (*p == '+' || *p == '-')
01249                 p++;
01250               while (ascii_isdigit (*p))
01251                 p++;
01252               end = p;
01253             }
01254         }
01255       else
01256         {
01257           while (ascii_isdigit (*p))
01258             p++;
01259           
01260           if (*p == '.')
01261             {
01262               decimal_point_pos = p++;
01263               
01264               while (ascii_isdigit (*p))
01265                 p++;
01266               
01267               if (*p == 'e' || *p == 'E')
01268                 p++;
01269               if (*p == '+' || *p == '-')
01270                 p++;
01271               while (ascii_isdigit (*p))
01272                 p++;
01273               end = p;
01274             }
01275         }
01276       /* For the other cases, we need not convert the decimal point */
01277     }
01278 
01279   /* Set errno to zero, so that we can distinguish zero results
01280      and underflows */
01281   errno = 0;
01282   
01283   if (decimal_point_pos)
01284     {
01285       char *copy, *c;
01286 
01287       /* We need to convert the '.' to the locale specific decimal point */
01288       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01289       
01290       c = copy;
01291       memcpy (c, nptr, decimal_point_pos - nptr);
01292       c += decimal_point_pos - nptr;
01293       memcpy (c, decimal_point, decimal_point_len);
01294       c += decimal_point_len;
01295       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01296       c += end - (decimal_point_pos + 1);
01297       *c = 0;
01298 
01299       val = strtod (copy, &fail_pos);
01300 
01301       if (fail_pos)
01302         {
01303           if (fail_pos > decimal_point_pos)
01304             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01305           else
01306             fail_pos = (char *)nptr + (fail_pos - copy);
01307         }
01308       
01309       dbus_free (copy);
01310           
01311     }
01312   else
01313     val = strtod (nptr, &fail_pos);
01314 
01315   if (endptr)
01316     *endptr = fail_pos;
01317   
01318   return val;
01319 }
01320 
01321 
01334 dbus_bool_t
01335 _dbus_string_parse_double (const DBusString *str,
01336                            int               start,
01337                            double           *value_return,
01338                            int              *end_return)
01339 {
01340   double v;
01341   const char *p;
01342   char *end;
01343 
01344   p = _dbus_string_get_const_data_len (str, start,
01345                                        _dbus_string_get_length (str) - start);
01346 
01347   end = NULL;
01348   errno = 0;
01349   v = ascii_strtod (p, &end);
01350   if (end == NULL || end == p || errno != 0)
01351     return FALSE;
01352 
01353   if (value_return)
01354     *value_return = v;
01355   if (end_return)
01356     *end_return = start + (end - p);
01357 
01358   return TRUE;
01359 }
01360  /* DBusString group */
01362 
01367 static dbus_bool_t
01368 fill_user_info_from_passwd (struct passwd *p,
01369                             DBusUserInfo  *info,
01370                             DBusError     *error)
01371 {
01372   _dbus_assert (p->pw_name != NULL);
01373   _dbus_assert (p->pw_dir != NULL);
01374   
01375   info->uid = p->pw_uid;
01376   info->primary_gid = p->pw_gid;
01377   info->username = _dbus_strdup (p->pw_name);
01378   info->homedir = _dbus_strdup (p->pw_dir);
01379   
01380   if (info->username == NULL ||
01381       info->homedir == NULL)
01382     {
01383       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01384       return FALSE;
01385     }
01386 
01387   return TRUE;
01388 }
01389 
01390 static dbus_bool_t
01391 fill_user_info (DBusUserInfo       *info,
01392                 dbus_uid_t          uid,
01393                 const DBusString   *username,
01394                 DBusError          *error)
01395 {
01396   const char *username_c;
01397   
01398   /* exactly one of username/uid provided */
01399   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01400   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01401 
01402   info->uid = DBUS_UID_UNSET;
01403   info->primary_gid = DBUS_GID_UNSET;
01404   info->group_ids = NULL;
01405   info->n_group_ids = 0;
01406   info->username = NULL;
01407   info->homedir = NULL;
01408   
01409   if (username != NULL)
01410     username_c = _dbus_string_get_const_data (username);
01411   else
01412     username_c = NULL;
01413 
01414   /* For now assuming that the getpwnam() and getpwuid() flavors
01415    * are always symmetrical, if not we have to add more configure
01416    * checks
01417    */
01418   
01419 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01420   {
01421     struct passwd *p;
01422     int result;
01423     char buf[1024];
01424     struct passwd p_str;
01425 
01426     p = NULL;
01427 #ifdef HAVE_POSIX_GETPWNAME_R
01428     if (uid >= 0)
01429       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01430                            &p);
01431     else
01432       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01433                            &p);
01434 #else
01435     if (uid != DBUS_UID_UNSET)
01436       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01437     else
01438       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01439     result = 0;
01440 #endif /* !HAVE_POSIX_GETPWNAME_R */
01441     if (result == 0 && p == &p_str)
01442       {
01443         if (!fill_user_info_from_passwd (p, info, error))
01444           return FALSE;
01445       }
01446     else
01447       {
01448         dbus_set_error (error, _dbus_error_from_errno (errno),
01449                         "User \"%s\" unknown or no memory to allocate password entry\n",
01450                         username_c ? username_c : "???");
01451         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01452         return FALSE;
01453       }
01454   }
01455 #else /* ! HAVE_GETPWNAM_R */
01456   {
01457     /* I guess we're screwed on thread safety here */
01458     struct passwd *p;
01459 
01460     if (uid != DBUS_UID_UNSET)
01461       p = getpwuid (uid);
01462     else
01463       p = getpwnam (username_c);
01464 
01465     if (p != NULL)
01466       {
01467         if (!fill_user_info_from_passwd (p, info, error))
01468           return FALSE;
01469       }
01470     else
01471       {
01472         dbus_set_error (error, _dbus_error_from_errno (errno),
01473                         "User \"%s\" unknown or no memory to allocate password entry\n",
01474                         username_c ? username_c : "???");
01475         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01476         return FALSE;
01477       }
01478   }
01479 #endif  /* ! HAVE_GETPWNAM_R */
01480 
01481   /* Fill this in so we can use it to get groups */
01482   username_c = info->username;
01483   
01484 #ifdef HAVE_GETGROUPLIST
01485   {
01486     gid_t *buf;
01487     int buf_count;
01488     int i;
01489     
01490     buf_count = 17;
01491     buf = dbus_new (gid_t, buf_count);
01492     if (buf == NULL)
01493       {
01494         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01495         goto failed;
01496       }
01497     
01498     if (getgrouplist (username_c,
01499                       info->primary_gid,
01500                       buf, &buf_count) < 0)
01501       {
01502         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01503         if (new == NULL)
01504           {
01505             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01506             dbus_free (buf);
01507             goto failed;
01508           }
01509         
01510         buf = new;
01511 
01512         errno = 0;
01513         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01514           {
01515             dbus_set_error (error,
01516                             _dbus_error_from_errno (errno),
01517                             "Failed to get groups for username \"%s\" primary GID "
01518                             DBUS_GID_FORMAT ": %s\n",
01519                             username_c, info->primary_gid,
01520                             _dbus_strerror (errno));
01521             dbus_free (buf);
01522             goto failed;
01523           }
01524       }
01525 
01526     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01527     if (info->group_ids == NULL)
01528       {
01529         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01530         dbus_free (buf);
01531         goto failed;
01532       }
01533     
01534     for (i = 0; i < buf_count; ++i)
01535       info->group_ids[i] = buf[i];
01536 
01537     info->n_group_ids = buf_count;
01538     
01539     dbus_free (buf);
01540   }
01541 #else  /* HAVE_GETGROUPLIST */
01542   {
01543     /* We just get the one group ID */
01544     info->group_ids = dbus_new (dbus_gid_t, 1);
01545     if (info->group_ids == NULL)
01546       {
01547         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01548         goto out;
01549       }
01550 
01551     info->n_group_ids = 1;
01552 
01553     (info->group_ids)[0] = info->primary_gid;
01554   }
01555 #endif /* HAVE_GETGROUPLIST */
01556 
01557   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01558   
01559   return TRUE;
01560   
01561  failed:
01562   _DBUS_ASSERT_ERROR_IS_SET (error);
01563   _dbus_user_info_free (info);
01564   return FALSE;
01565 }
01566 
01575 dbus_bool_t
01576 _dbus_user_info_fill (DBusUserInfo     *info,
01577                       const DBusString *username,
01578                       DBusError        *error)
01579 {
01580   return fill_user_info (info, DBUS_UID_UNSET,
01581                          username, error);
01582 }
01583 
01592 dbus_bool_t
01593 _dbus_user_info_fill_uid (DBusUserInfo *info,
01594                           dbus_uid_t    uid,
01595                           DBusError    *error)
01596 {
01597   return fill_user_info (info, uid,
01598                          NULL, error);
01599 }
01600 
01606 void
01607 _dbus_user_info_free (DBusUserInfo *info)
01608 {
01609   dbus_free (info->group_ids);
01610   dbus_free (info->username);
01611   dbus_free (info->homedir);
01612 }
01613 
01614 static dbus_bool_t
01615 fill_user_info_from_group (struct group  *g,
01616                            DBusGroupInfo *info,
01617                            DBusError     *error)
01618 {
01619   _dbus_assert (g->gr_name != NULL);
01620   
01621   info->gid = g->gr_gid;
01622   info->groupname = _dbus_strdup (g->gr_name);
01623 
01624   /* info->members = dbus_strdupv (g->gr_mem) */
01625   
01626   if (info->groupname == NULL)
01627     {
01628       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01629       return FALSE;
01630     }
01631 
01632   return TRUE;
01633 }
01634 
01635 static dbus_bool_t
01636 fill_group_info (DBusGroupInfo    *info,
01637                  dbus_gid_t        gid,
01638                  const DBusString *groupname,
01639                  DBusError        *error)
01640 {
01641   const char *group_c_str;
01642 
01643   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01644   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01645 
01646   if (groupname)
01647     group_c_str = _dbus_string_get_const_data (groupname);
01648   else
01649     group_c_str = NULL;
01650   
01651   /* For now assuming that the getgrnam() and getgrgid() flavors
01652    * always correspond to the pwnam flavors, if not we have
01653    * to add more configure checks.
01654    */
01655   
01656 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01657   {
01658     struct group *g;
01659     int result;
01660     char buf[1024];
01661     struct group g_str;
01662 
01663     g = NULL;
01664 #ifdef HAVE_POSIX_GETPWNAME_R
01665 
01666     if (group_c_str)
01667       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01668                            &g);
01669     else
01670       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01671                            &g);
01672 #else
01673     p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01674     result = 0;
01675 #endif /* !HAVE_POSIX_GETPWNAME_R */
01676     if (result == 0 && g == &g_str)
01677       {
01678         return fill_user_info_from_group (g, info, error);
01679       }
01680     else
01681       {
01682         dbus_set_error (error, _dbus_error_from_errno (errno),
01683                         "Group %s unknown or failed to look it up\n",
01684                         group_c_str ? group_c_str : "???");
01685         return FALSE;
01686       }
01687   }
01688 #else /* ! HAVE_GETPWNAM_R */
01689   {
01690     /* I guess we're screwed on thread safety here */
01691     struct group *g;
01692 
01693     g = getgrnam (group_c_str);
01694 
01695     if (g != NULL)
01696       {
01697         return fill_user_info_from_group (g, info, error);
01698       }
01699     else
01700       {
01701         dbus_set_error (error, _dbus_error_from_errno (errno),
01702                         "Group %s unknown or failed to look it up\n",
01703                         group_c_str ? group_c_str : "???");
01704         return FALSE;
01705       }
01706   }
01707 #endif  /* ! HAVE_GETPWNAM_R */
01708 }
01709 
01719 dbus_bool_t
01720 _dbus_group_info_fill (DBusGroupInfo    *info,
01721                        const DBusString *groupname,
01722                        DBusError        *error)
01723 {
01724   return fill_group_info (info, DBUS_GID_UNSET,
01725                           groupname, error);
01726 
01727 }
01728 
01738 dbus_bool_t
01739 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01740                            dbus_gid_t     gid,
01741                            DBusError     *error)
01742 {
01743   return fill_group_info (info, gid, NULL, error);
01744 }
01745 
01751 void
01752 _dbus_group_info_free (DBusGroupInfo    *info)
01753 {
01754   dbus_free (info->groupname);
01755 }
01756 
01763 void
01764 _dbus_credentials_clear (DBusCredentials *credentials)
01765 {
01766   credentials->pid = DBUS_PID_UNSET;
01767   credentials->uid = DBUS_UID_UNSET;
01768   credentials->gid = DBUS_GID_UNSET;
01769 }
01770 
01776 void
01777 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01778 {
01779   /* The POSIX spec certainly doesn't promise this, but
01780    * we need these assertions to fail as soon as we're wrong about
01781    * it so we can do the porting fixups
01782    */
01783   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01784   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01785   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01786   
01787   credentials->pid = getpid ();
01788   credentials->uid = getuid ();
01789   credentials->gid = getgid ();
01790 }
01791 
01800 dbus_bool_t
01801 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01802                          const DBusCredentials *provided_credentials)
01803 {
01804   if (provided_credentials->uid == DBUS_UID_UNSET)
01805     return FALSE;
01806   else if (expected_credentials->uid == DBUS_UID_UNSET)
01807     return FALSE;
01808   else if (provided_credentials->uid == 0)
01809     return TRUE;
01810   else if (provided_credentials->uid == expected_credentials->uid)
01811     return TRUE;
01812   else
01813     return FALSE;
01814 }
01815 
01820 unsigned long
01821 _dbus_getpid (void)
01822 {
01823   return getpid ();
01824 }
01825 
01829 dbus_uid_t
01830 _dbus_getuid (void)
01831 {
01832   return getuid ();
01833 }
01834 
01838 dbus_gid_t
01839 _dbus_getgid (void)
01840 {
01841   return getgid ();
01842 }
01843 
01844 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01845 
01846 #ifdef DBUS_USE_ATOMIC_INT_486
01847 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01848 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01849 static inline dbus_int32_t
01850 atomic_exchange_and_add (DBusAtomic            *atomic,
01851                          volatile dbus_int32_t  val)
01852 {
01853   register dbus_int32_t result;
01854 
01855   __asm__ __volatile__ ("lock; xaddl %0,%1"
01856                         : "=r" (result), "=m" (atomic->value)
01857                         : "0" (val), "m" (atomic->value));
01858   return result;
01859 }
01860 #endif
01861 
01870 dbus_int32_t
01871 _dbus_atomic_inc (DBusAtomic *atomic)
01872 {
01873 #ifdef DBUS_USE_ATOMIC_INT_486
01874   return atomic_exchange_and_add (atomic, 1);
01875 #else
01876   dbus_int32_t res;
01877   _DBUS_LOCK (atomic);
01878   res = atomic->value;
01879   atomic->value += 1;
01880   _DBUS_UNLOCK (atomic);
01881   return res;
01882 #endif
01883 }
01884 
01893 dbus_int32_t
01894 _dbus_atomic_dec (DBusAtomic *atomic)
01895 {
01896 #ifdef DBUS_USE_ATOMIC_INT_486
01897   return atomic_exchange_and_add (atomic, -1);
01898 #else
01899   dbus_int32_t res;
01900   
01901   _DBUS_LOCK (atomic);
01902   res = atomic->value;
01903   atomic->value -= 1;
01904   _DBUS_UNLOCK (atomic);
01905   return res;
01906 #endif
01907 }
01908 
01919 int
01920 _dbus_poll (DBusPollFD *fds,
01921             int         n_fds,
01922             int         timeout_milliseconds)
01923 {
01924 #ifdef HAVE_POLL
01925   /* This big thing is a constant expression and should get optimized
01926    * out of existence. So it's more robust than a configure check at
01927    * no cost.
01928    */
01929   if (_DBUS_POLLIN == POLLIN &&
01930       _DBUS_POLLPRI == POLLPRI &&
01931       _DBUS_POLLOUT == POLLOUT &&
01932       _DBUS_POLLERR == POLLERR &&
01933       _DBUS_POLLHUP == POLLHUP &&
01934       _DBUS_POLLNVAL == POLLNVAL &&
01935       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01936       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01937       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01938       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01939       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01940       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01941       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01942     {
01943       return poll ((struct pollfd*) fds,
01944                    n_fds, 
01945                    timeout_milliseconds);
01946     }
01947   else
01948     {
01949       /* We have to convert the DBusPollFD to an array of
01950        * struct pollfd, poll, and convert back.
01951        */
01952       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01953       return -1;
01954     }
01955 #else /* ! HAVE_POLL */
01956 
01957   fd_set read_set, write_set, err_set;
01958   int max_fd = 0;
01959   int i;
01960   struct timeval tv;
01961   int ready;
01962   
01963   FD_ZERO (&read_set);
01964   FD_ZERO (&write_set);
01965   FD_ZERO (&err_set);
01966 
01967   for (i = 0; i < n_fds; i++)
01968     {
01969       DBusPollFD f = fds[i];
01970 
01971       if (f.events & _DBUS_POLLIN)
01972         FD_SET (f.fd, &read_set);
01973 
01974       if (f.events & _DBUS_POLLOUT)
01975         FD_SET (f.fd, &write_set);
01976 
01977       FD_SET (f.fd, &err_set);
01978 
01979       max_fd = MAX (max_fd, f.fd);
01980     }
01981     
01982   tv.tv_sec = timeout_milliseconds / 1000;
01983   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01984 
01985   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01986 
01987   if (ready > 0)
01988     {
01989       for (i = 0; i < n_fds; i++)
01990         {
01991           DBusPollFD f = fds[i];
01992 
01993           f.revents = 0;
01994 
01995           if (FD_ISSET (f.fd, &read_set))
01996             f.revents |= _DBUS_POLLIN;
01997 
01998           if (FD_ISSET (f.fd, &write_set))
01999             f.revents |= _DBUS_POLLOUT;
02000 
02001           if (FD_ISSET (f.fd, &err_set))
02002             f.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                       filename_c, (unsigned long) sb.st_size);
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 
02461 dbus_bool_t
02462 _dbus_string_get_dirname  (const DBusString *filename,
02463                            DBusString       *dirname)
02464 {
02465   int sep;
02466   
02467   _dbus_assert (filename != dirname);
02468   _dbus_assert (filename != NULL);
02469   _dbus_assert (dirname != NULL);
02470 
02471   /* Ignore any separators on the end */
02472   sep = _dbus_string_get_length (filename);
02473   if (sep == 0)
02474     return _dbus_string_append (dirname, "."); /* empty string passed in */
02475     
02476   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02477     --sep;
02478 
02479   _dbus_assert (sep >= 0);
02480   
02481   if (sep == 0)
02482     return _dbus_string_append (dirname, "/");
02483   
02484   /* Now find the previous separator */
02485   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02486   if (sep < 0)
02487     return _dbus_string_append (dirname, ".");
02488   
02489   /* skip multiple separators */
02490   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02491     --sep;
02492 
02493   _dbus_assert (sep >= 0);
02494   
02495   if (sep == 0 &&
02496       _dbus_string_get_byte (filename, 0) == '/')
02497     return _dbus_string_append (dirname, "/");
02498   else
02499     return _dbus_string_copy_len (filename, 0, sep - 0,
02500                                   dirname, _dbus_string_get_length (dirname));
02501 }
02502 
02509 dbus_bool_t
02510 _dbus_path_is_absolute (const DBusString *filename)
02511 {
02512   if (_dbus_string_get_length (filename) > 0)
02513     return _dbus_string_get_byte (filename, 0) == '/';
02514   else
02515     return FALSE;
02516 }
02517 
02518 struct DBusDirIter
02519 {
02520   DIR *d;
02521   
02522 };
02523 
02531 DBusDirIter*
02532 _dbus_directory_open (const DBusString *filename,
02533                       DBusError        *error)
02534 {
02535   DIR *d;
02536   DBusDirIter *iter;
02537   const char *filename_c;
02538 
02539   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02540   
02541   filename_c = _dbus_string_get_const_data (filename);
02542 
02543   d = opendir (filename_c);
02544   if (d == NULL)
02545     {
02546       dbus_set_error (error, _dbus_error_from_errno (errno),
02547                       "Failed to read directory \"%s\": %s",
02548                       filename_c,
02549                       _dbus_strerror (errno));
02550       return NULL;
02551     }
02552   iter = dbus_new0 (DBusDirIter, 1);
02553   if (iter == NULL)
02554     {
02555       closedir (d);
02556       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02557                       "Could not allocate memory for directory iterator");
02558       return NULL;
02559     }
02560 
02561   iter->d = d;
02562 
02563   return iter;
02564 }
02565 
02579 dbus_bool_t
02580 _dbus_directory_get_next_file (DBusDirIter      *iter,
02581                                DBusString       *filename,
02582                                DBusError        *error)
02583 {
02584   struct dirent *ent;
02585 
02586   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02587   
02588  again:
02589   errno = 0;
02590   ent = readdir (iter->d);
02591   if (ent == NULL)
02592     {
02593       if (errno != 0)
02594         dbus_set_error (error,
02595                         _dbus_error_from_errno (errno),
02596                         "%s", _dbus_strerror (errno));
02597       return FALSE;
02598     }
02599   else if (ent->d_name[0] == '.' &&
02600            (ent->d_name[1] == '\0' ||
02601             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02602     goto again;
02603   else
02604     {
02605       _dbus_string_set_length (filename, 0);
02606       if (!_dbus_string_append (filename, ent->d_name))
02607         {
02608           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02609                           "No memory to read directory entry");
02610           return FALSE;
02611         }
02612       else
02613         return TRUE;
02614     }
02615 }
02616 
02620 void
02621 _dbus_directory_close (DBusDirIter *iter)
02622 {
02623   closedir (iter->d);
02624   dbus_free (iter);
02625 }
02626 
02627 static dbus_bool_t
02628 pseudorandom_generate_random_bytes (DBusString *str,
02629                                     int         n_bytes)
02630 {
02631   int old_len;
02632   unsigned long tv_usec;
02633   int i;
02634   
02635   old_len = _dbus_string_get_length (str);
02636 
02637   /* fall back to pseudorandom */
02638   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02639                  n_bytes);
02640   
02641   _dbus_get_current_time (NULL, &tv_usec);
02642   srand (tv_usec);
02643   
02644   i = 0;
02645   while (i < n_bytes)
02646     {
02647       double r;
02648       unsigned int b;
02649           
02650       r = rand ();
02651       b = (r / (double) RAND_MAX) * 255.0;
02652           
02653       if (!_dbus_string_append_byte (str, b))
02654         goto failed;
02655           
02656       ++i;
02657     }
02658 
02659   return TRUE;
02660 
02661  failed:
02662   _dbus_string_set_length (str, old_len);
02663   return FALSE;
02664 }
02665 
02674 dbus_bool_t
02675 _dbus_generate_random_bytes (DBusString *str,
02676                              int         n_bytes)
02677 {
02678   int old_len;
02679   int fd;
02680 
02681   /* FALSE return means "no memory", if it could
02682    * mean something else then we'd need to return
02683    * a DBusError. So we always fall back to pseudorandom
02684    * if the I/O fails.
02685    */
02686   
02687   old_len = _dbus_string_get_length (str);
02688   fd = -1;
02689 
02690   /* note, urandom on linux will fall back to pseudorandom */
02691   fd = open ("/dev/urandom", O_RDONLY);
02692   if (fd < 0)
02693     return pseudorandom_generate_random_bytes (str, n_bytes);
02694 
02695   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02696     {
02697       close (fd);
02698       _dbus_string_set_length (str, old_len);
02699       return pseudorandom_generate_random_bytes (str, n_bytes);
02700     }
02701 
02702   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02703                  n_bytes);
02704   
02705   close (fd);
02706   
02707   return TRUE;
02708 }
02709 
02718 dbus_bool_t
02719 _dbus_generate_random_ascii (DBusString *str,
02720                              int         n_bytes)
02721 {
02722   static const char letters[] =
02723     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02724   int i;
02725   int len;
02726   
02727   if (!_dbus_generate_random_bytes (str, n_bytes))
02728     return FALSE;
02729   
02730   len = _dbus_string_get_length (str);
02731   i = len - n_bytes;
02732   while (i < len)
02733     {
02734       _dbus_string_set_byte (str, i,
02735                              letters[_dbus_string_get_byte (str, i) %
02736                                      (sizeof (letters) - 1)]);
02737 
02738       ++i;
02739     }
02740 
02741   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02742                                              n_bytes));
02743 
02744   return TRUE;
02745 }
02746 
02754 const char*
02755 _dbus_strerror (int error_number)
02756 {
02757   const char *msg;
02758   
02759   msg = strerror (error_number);
02760   if (msg == NULL)
02761     msg = "unknown";
02762 
02763   return msg;
02764 }
02765 
02769 void
02770 _dbus_disable_sigpipe (void)
02771 {
02772   signal (SIGPIPE, SIG_IGN);
02773 }
02774 
02782 void
02783 _dbus_fd_set_close_on_exec (int fd)
02784 {
02785   int val;
02786   
02787   val = fcntl (fd, F_GETFD, 0);
02788   
02789   if (val < 0)
02790     return;
02791 
02792   val |= FD_CLOEXEC;
02793   
02794   fcntl (fd, F_SETFD, val);
02795 }
02796 
02806 const char*
02807 _dbus_error_from_errno (int error_number)
02808 {
02809   switch (error_number)
02810     {
02811     case 0:
02812       return DBUS_ERROR_FAILED;
02813       
02814 #ifdef EPROTONOSUPPORT
02815     case EPROTONOSUPPORT:
02816       return DBUS_ERROR_NOT_SUPPORTED;
02817 #endif
02818 #ifdef EAFNOSUPPORT
02819     case EAFNOSUPPORT:
02820       return DBUS_ERROR_NOT_SUPPORTED;
02821 #endif
02822 #ifdef ENFILE
02823     case ENFILE:
02824       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02825 #endif
02826 #ifdef EMFILE
02827     case EMFILE:
02828       return DBUS_ERROR_LIMITS_EXCEEDED;
02829 #endif
02830 #ifdef EACCES
02831     case EACCES:
02832       return DBUS_ERROR_ACCESS_DENIED;
02833 #endif
02834 #ifdef EPERM
02835     case EPERM:
02836       return DBUS_ERROR_ACCESS_DENIED;
02837 #endif
02838 #ifdef ENOBUFS
02839     case ENOBUFS:
02840       return DBUS_ERROR_NO_MEMORY;
02841 #endif
02842 #ifdef ENOMEM
02843     case ENOMEM:
02844       return DBUS_ERROR_NO_MEMORY;
02845 #endif
02846 #ifdef EINVAL
02847     case EINVAL:
02848       return DBUS_ERROR_FAILED;
02849 #endif
02850 #ifdef EBADF
02851     case EBADF:
02852       return DBUS_ERROR_FAILED;
02853 #endif
02854 #ifdef EFAULT
02855     case EFAULT:
02856       return DBUS_ERROR_FAILED;
02857 #endif
02858 #ifdef ENOTSOCK
02859     case ENOTSOCK:
02860       return DBUS_ERROR_FAILED;
02861 #endif
02862 #ifdef EISCONN
02863     case EISCONN:
02864       return DBUS_ERROR_FAILED;
02865 #endif
02866 #ifdef ECONNREFUSED
02867     case ECONNREFUSED:
02868       return DBUS_ERROR_NO_SERVER;
02869 #endif
02870 #ifdef ETIMEDOUT
02871     case ETIMEDOUT:
02872       return DBUS_ERROR_TIMEOUT;
02873 #endif
02874 #ifdef ENETUNREACH
02875     case ENETUNREACH:
02876       return DBUS_ERROR_NO_NETWORK;
02877 #endif
02878 #ifdef EADDRINUSE
02879     case EADDRINUSE:
02880       return DBUS_ERROR_ADDRESS_IN_USE;
02881 #endif
02882 #ifdef EEXIST
02883     case EEXIST:
02884       return DBUS_ERROR_FILE_NOT_FOUND;
02885 #endif
02886 #ifdef ENOENT
02887     case ENOENT:
02888       return DBUS_ERROR_FILE_NOT_FOUND;
02889 #endif
02890     }
02891 
02892   return DBUS_ERROR_FAILED;
02893 }
02894 
02900 void
02901 _dbus_exit (int code)
02902 {
02903   _exit (code);
02904 }
02905 
02914 dbus_bool_t
02915 _dbus_stat (const DBusString *filename,
02916             DBusStat         *statbuf,
02917             DBusError        *error)
02918 {
02919   const char *filename_c;
02920   struct stat sb;
02921 
02922   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02923   
02924   filename_c = _dbus_string_get_const_data (filename);
02925 
02926   if (stat (filename_c, &sb) < 0)
02927     {
02928       dbus_set_error (error, _dbus_error_from_errno (errno),
02929                       "%s", _dbus_strerror (errno));
02930       return FALSE;
02931     }
02932 
02933   statbuf->mode = sb.st_mode;
02934   statbuf->nlink = sb.st_nlink;
02935   statbuf->uid = sb.st_uid;
02936   statbuf->gid = sb.st_gid;
02937   statbuf->size = sb.st_size;
02938   statbuf->atime = sb.st_atime;
02939   statbuf->mtime = sb.st_mtime;
02940   statbuf->ctime = sb.st_ctime;
02941 
02942   return TRUE;
02943 }
02944 
02955 dbus_bool_t
02956 _dbus_full_duplex_pipe (int        *fd1,
02957                         int        *fd2,
02958                         dbus_bool_t blocking,
02959                         DBusError  *error)
02960 {
02961 #ifdef HAVE_SOCKETPAIR
02962   int fds[2];
02963 
02964   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02965   
02966   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02967     {
02968       dbus_set_error (error, _dbus_error_from_errno (errno),
02969                       "Could not create full-duplex pipe");
02970       return FALSE;
02971     }
02972 
02973   if (!blocking &&
02974       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02975        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02976     {
02977       dbus_set_error (error, _dbus_error_from_errno (errno),
02978                       "Could not set full-duplex pipe nonblocking");
02979       
02980       close (fds[0]);
02981       close (fds[1]);
02982       
02983       return FALSE;
02984     }
02985   
02986   *fd1 = fds[0];
02987   *fd2 = fds[1];
02988   
02989   return TRUE;  
02990 #else
02991   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02992   dbus_set_error (error, DBUS_ERROR_FAILED,
02993                   "_dbus_full_duplex_pipe() not implemented on this OS");
02994   return FALSE;
02995 #endif
02996 }
02997 
03005 dbus_bool_t
03006 _dbus_close (int        fd,
03007              DBusError *error)
03008 {
03009   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03010   
03011  again:
03012   if (close (fd) < 0)
03013     {
03014       if (errno == EINTR)
03015         goto again;
03016 
03017       dbus_set_error (error, _dbus_error_from_errno (errno),
03018                       "Could not close fd %d", fd);
03019       return FALSE;
03020     }
03021 
03022   return TRUE;
03023 }
03024 
03032 dbus_bool_t
03033 _dbus_set_fd_nonblocking (int             fd,
03034                           DBusError      *error)
03035 {
03036   int val;
03037 
03038   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03039   
03040   val = fcntl (fd, F_GETFL, 0);
03041   if (val < 0)
03042     {
03043       dbus_set_error (error, _dbus_error_from_errno (errno),
03044                       "Failed to get flags from file descriptor %d: %s",
03045                       fd, _dbus_strerror (errno));
03046       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03047                      _dbus_strerror (errno));
03048       return FALSE;
03049     }
03050 
03051   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03052     {
03053       dbus_set_error (error, _dbus_error_from_errno (errno),
03054                       "Failed to set nonblocking flag of file descriptor %d: %s",
03055                       fd, _dbus_strerror (errno));
03056       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03057                      fd, _dbus_strerror (errno));
03058 
03059       return FALSE;
03060     }
03061 
03062   return TRUE;
03063 }
03064 
03070 void
03071 _dbus_print_backtrace (void)
03072 {
03073 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03074   void *bt[500];
03075   int bt_size;
03076   int i;
03077   char **syms;
03078   
03079   bt_size = backtrace (bt, 500);
03080 
03081   syms = backtrace_symbols (bt, bt_size);
03082   
03083   i = 0;
03084   while (i < bt_size)
03085     {
03086       _dbus_verbose ("  %s\n", syms[i]);
03087       ++i;
03088     }
03089 
03090   free (syms);
03091 #else
03092   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
03093 #endif
03094 }
03095 
03103 dbus_bool_t
03104 _dbus_become_daemon (const DBusString *pidfile,
03105                      DBusError        *error)
03106 {
03107   const char *s;
03108   pid_t child_pid;
03109 
03110   if (chdir ("/") < 0)
03111     {
03112       dbus_set_error (error, DBUS_ERROR_FAILED,
03113                       "Could not chdir() to root directory");
03114       return FALSE;
03115     }
03116 
03117   switch ((child_pid = fork ()))
03118     {
03119     case -1:
03120       dbus_set_error (error, _dbus_error_from_errno (errno),
03121                       "Failed to fork daemon: %s", _dbus_strerror (errno));
03122       return FALSE;
03123       break;
03124 
03125     case 0:
03126 
03127 
03128       s = _dbus_getenv ("DBUS_DEBUG_DAEMONIZE");
03129       if (s != NULL)
03130               kill (_dbus_getpid (), SIGSTOP);
03131       
03132       s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03133       if (s == NULL || *s == '\0')
03134         {
03135           int dev_null_fd;
03136 
03137           /* silently ignore failures here, if someone
03138            * doesn't have /dev/null we may as well try
03139            * to continue anyhow
03140            */
03141 
03142           dev_null_fd = open ("/dev/null", O_RDWR);
03143           if (dev_null_fd >= 0)
03144             {
03145               dup2 (dev_null_fd, 0);
03146               dup2 (dev_null_fd, 1);
03147               dup2 (dev_null_fd, 2);
03148             }
03149         }
03150 
03151       /* Get a predictable umask */
03152       umask (022);
03153       break;
03154 
03155     default:
03156       if (pidfile)
03157         {
03158           if (!_dbus_write_pid_file (pidfile,
03159                                      child_pid,
03160                                      error))
03161             {
03162               kill (child_pid, SIGTERM);
03163               return FALSE;
03164             }
03165         }
03166       _exit (0);
03167       break;
03168     }
03169 
03170   if (setsid () == -1)
03171     _dbus_assert_not_reached ("setsid() failed");
03172   
03173   return TRUE;
03174 }
03175 
03184 dbus_bool_t
03185 _dbus_write_pid_file (const DBusString *filename,
03186                       unsigned long     pid,
03187                       DBusError        *error)
03188 {
03189   const char *cfilename;
03190   int fd;
03191   FILE *f;
03192 
03193   cfilename = _dbus_string_get_const_data (filename);
03194   
03195   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03196   
03197   if (fd < 0)
03198     {
03199       dbus_set_error (error, _dbus_error_from_errno (errno),
03200                       "Failed to open \"%s\": %s", cfilename,
03201                       _dbus_strerror (errno));
03202       return FALSE;
03203     }
03204 
03205   if ((f = fdopen (fd, "w")) == NULL)
03206     {
03207       dbus_set_error (error, _dbus_error_from_errno (errno),
03208                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03209       close (fd);
03210       return FALSE;
03211     }
03212   
03213   if (fprintf (f, "%lu\n", pid) < 0)
03214     {
03215       dbus_set_error (error, _dbus_error_from_errno (errno),
03216                       "Failed to write to \"%s\": %s", cfilename,
03217                       _dbus_strerror (errno));
03218       return FALSE;
03219     }
03220 
03221   if (fclose (f) == EOF)
03222     {
03223       dbus_set_error (error, _dbus_error_from_errno (errno),
03224                       "Failed to close \"%s\": %s", cfilename,
03225                       _dbus_strerror (errno));
03226       return FALSE;
03227     }
03228   
03229   return TRUE;
03230 }
03231 
03240 dbus_bool_t
03241 _dbus_change_identity  (dbus_uid_t     uid,
03242                         dbus_gid_t     gid,
03243                         DBusError     *error)
03244 {
03245   /* Set GID first, or the setuid may remove our permission
03246    * to change the GID
03247    */
03248   if (setgid (gid) < 0)
03249     {
03250       dbus_set_error (error, _dbus_error_from_errno (errno),
03251                       "Failed to set GID to %lu: %s", gid,
03252                       _dbus_strerror (errno));
03253       return FALSE;
03254     }
03255   
03256   if (setuid (uid) < 0)
03257     {
03258       dbus_set_error (error, _dbus_error_from_errno (errno),
03259                       "Failed to set UID to %lu: %s", uid,
03260                       _dbus_strerror (errno));
03261       return FALSE;
03262     }
03263   
03264   return TRUE;
03265 }
03266 
03272 void
03273 _dbus_set_signal_handler (int               sig,
03274                           DBusSignalHandler handler)
03275 {
03276   struct sigaction act;
03277   sigset_t empty_mask;
03278   
03279   sigemptyset (&empty_mask);
03280   act.sa_handler = handler;
03281   act.sa_mask    = empty_mask;
03282   act.sa_flags   = 0;
03283   sigaction (sig,  &act, 0);
03284 }
03285 
03286 
03287 #ifdef DBUS_BUILD_TESTS
03288 #include <stdlib.h>
03289 static void
03290 check_dirname (const char *filename,
03291                const char *dirname)
03292 {
03293   DBusString f, d;
03294   
03295   _dbus_string_init_const (&f, filename);
03296 
03297   if (!_dbus_string_init (&d))
03298     _dbus_assert_not_reached ("no memory");
03299 
03300   if (!_dbus_string_get_dirname (&f, &d))
03301     _dbus_assert_not_reached ("no memory");
03302 
03303   if (!_dbus_string_equal_c_str (&d, dirname))
03304     {
03305       _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03306                   filename,
03307                   _dbus_string_get_const_data (&d),
03308                   dirname);
03309       exit (1);
03310     }
03311 
03312   _dbus_string_free (&d);
03313 }
03314 
03315 static void
03316 check_path_absolute (const char *path,
03317                      dbus_bool_t expected)
03318 {
03319   DBusString p;
03320 
03321   _dbus_string_init_const (&p, path);
03322 
03323   if (_dbus_path_is_absolute (&p) != expected)
03324     {
03325       _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03326                   path, expected, _dbus_path_is_absolute (&p));
03327       exit (1);
03328     }
03329 }
03330 
03336 dbus_bool_t
03337 _dbus_sysdeps_test (void)
03338 {
03339   DBusString str;
03340   double val;
03341   int pos;
03342   
03343   check_dirname ("foo", ".");
03344   check_dirname ("foo/bar", "foo");
03345   check_dirname ("foo//bar", "foo");
03346   check_dirname ("foo///bar", "foo");
03347   check_dirname ("foo/bar/", "foo");
03348   check_dirname ("foo//bar/", "foo");
03349   check_dirname ("foo///bar/", "foo");
03350   check_dirname ("foo/bar//", "foo");
03351   check_dirname ("foo//bar////", "foo");
03352   check_dirname ("foo///bar///////", "foo");
03353   check_dirname ("/foo", "/");
03354   check_dirname ("
03355   check_dirname ("/foo/bar", "/foo");
03356   check_dirname ("/foo//bar", "/foo");
03357   check_dirname ("/foo///bar", "/foo");
03358   check_dirname ("/", "/");
03359   check_dirname ("
03360   check_dirname ("", ".");  
03361 
03362 
03363   _dbus_string_init_const (&str, "3.5");
03364   if (!_dbus_string_parse_double (&str,
03365                                   0, &val, &pos))
03366     {
03367       _dbus_warn ("Failed to parse double");
03368       exit (1);
03369     }
03370   if (val != 3.5)
03371     {
03372       _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03373       exit (1);
03374     }
03375   if (pos != 3)
03376     {
03377       _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03378       exit (1);
03379     }
03380 
03381   check_path_absolute ("/", TRUE);
03382   check_path_absolute ("/foo", TRUE);
03383   check_path_absolute ("", FALSE);
03384   check_path_absolute ("foo", FALSE);
03385   check_path_absolute ("foo/bar", FALSE);
03386   
03387   return TRUE;
03388 }
03389 #endif /* DBUS_BUILD_TESTS */
03390 

Generated on Wed Oct 22 14:05:05 2003 for D-BUS by doxygen1.3-rc3