Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | 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.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-protocol.h"
00029 #include "dbus-string.h"
00030 #include <sys/types.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <signal.h>
00034 #include <unistd.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <fcntl.h>
00038 #include <sys/socket.h>
00039 #include <dirent.h>
00040 #include <sys/un.h>
00041 #include <pwd.h>
00042 #include <time.h>
00043 #include <locale.h>
00044 #include <sys/time.h>
00045 #include <sys/stat.h>
00046 #include <sys/wait.h>
00047 #include <netinet/in.h>
00048 #include <netdb.h>
00049 #include <grp.h>
00050 
00051 #ifdef HAVE_WRITEV
00052 #include <sys/uio.h>
00053 #endif
00054 #ifdef HAVE_POLL
00055 #include <sys/poll.h>
00056 #endif
00057 #ifdef HAVE_BACKTRACE
00058 #include <execinfo.h>
00059 #endif
00060 
00061 
00062 #ifndef O_BINARY
00063 #define O_BINARY 0
00064 #endif
00065 
00066 #ifndef HAVE_SOCKLEN_T
00067 #define socklen_t int
00068 #endif
00069 
00074 #ifndef DBUS_DISABLE_ASSERT
00075 
00078 void
00079 _dbus_abort (void)
00080 {
00081 #ifdef DBUS_ENABLE_VERBOSE_MODE
00082   const char *s;
00083   s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00084   if (s && *s)
00085     _dbus_print_backtrace ();
00086 #endif
00087   abort ();
00088   _exit (1); /* in case someone manages to ignore SIGABRT */
00089 }
00090 #endif
00091 
00103 dbus_bool_t
00104 _dbus_setenv (const char *varname,
00105               const char *value)
00106 {
00107   _dbus_assert (varname != NULL);
00108   
00109   if (value == NULL)
00110     {
00111 #ifdef HAVE_UNSETENV
00112       unsetenv (varname);
00113       return TRUE;
00114 #else
00115       char *putenv_value;
00116       size_t len;
00117 
00118       len = strlen (varname);
00119 
00120       /* Use system malloc to avoid memleaks that dbus_malloc
00121        * will get upset about.
00122        */
00123       
00124       putenv_value = malloc (len + 1);
00125       if (putenv_value == NULL)
00126         return FALSE;
00127 
00128       strcpy (putenv_value, varname);
00129       
00130       return (putenv (putenv_value) == 0);
00131 #endif
00132     }
00133   else
00134     {
00135 #ifdef HAVE_SETENV
00136       return (setenv (varname, value, TRUE) == 0);
00137 #else
00138       char *putenv_value;
00139       size_t len;
00140       size_t varname_len;
00141       size_t value_len;
00142 
00143       varname_len = strlen (varname);
00144       value_len = strlen (value);
00145       
00146       len = varname_len + value_len + 1 /* '=' */ ;
00147 
00148       /* Use system malloc to avoid memleaks that dbus_malloc
00149        * will get upset about.
00150        */
00151       
00152       putenv_value = malloc (len + 1);
00153       if (putenv_value == NULL)
00154         return FALSE;
00155 
00156       strcpy (putenv_value, varname);
00157       strcpy (putenv_value + varname_len, "=");
00158       strcpy (putenv_value + varname_len + 1, value);
00159       
00160       return (putenv (putenv_value) == 0);
00161 #endif
00162     }
00163 }
00164 
00171 const char*
00172 _dbus_getenv (const char *varname)
00173 {  
00174   return getenv (varname);
00175 }
00176 
00190 int
00191 _dbus_read (int               fd,
00192             DBusString       *buffer,
00193             int               count)
00194 {
00195   int bytes_read;
00196   int start;
00197   char *data;
00198 
00199   _dbus_assert (count >= 0);
00200   
00201   start = _dbus_string_get_length (buffer);
00202 
00203   if (!_dbus_string_lengthen (buffer, count))
00204     {
00205       errno = ENOMEM;
00206       return -1;
00207     }
00208 
00209   data = _dbus_string_get_data_len (buffer, start, count);
00210 
00211  again:
00212   
00213   bytes_read = read (fd, data, count);
00214 
00215   if (bytes_read < 0)
00216     {
00217       if (errno == EINTR)
00218         goto again;
00219       else
00220         {
00221           /* put length back (note that this doesn't actually realloc anything) */
00222           _dbus_string_set_length (buffer, start);
00223           return -1;
00224         }
00225     }
00226   else
00227     {
00228       /* put length back (doesn't actually realloc) */
00229       _dbus_string_set_length (buffer, start + bytes_read);
00230 
00231 #if 0
00232       if (bytes_read > 0)
00233         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00234 #endif
00235       
00236       return bytes_read;
00237     }
00238 }
00239 
00250 int
00251 _dbus_write (int               fd,
00252              const DBusString *buffer,
00253              int               start,
00254              int               len)
00255 {
00256   const char *data;
00257   int bytes_written;
00258   
00259   data = _dbus_string_get_const_data_len (buffer, start, len);
00260   
00261  again:
00262 
00263   bytes_written = write (fd, data, len);
00264 
00265   if (bytes_written < 0 && errno == EINTR)
00266     goto again;
00267 
00268 #if 0
00269   if (bytes_written > 0)
00270     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00271 #endif
00272   
00273   return bytes_written;
00274 }
00275 
00296 int
00297 _dbus_write_two (int               fd,
00298                  const DBusString *buffer1,
00299                  int               start1,
00300                  int               len1,
00301                  const DBusString *buffer2,
00302                  int               start2,
00303                  int               len2)
00304 {
00305   _dbus_assert (buffer1 != NULL);
00306   _dbus_assert (start1 >= 0);
00307   _dbus_assert (start2 >= 0);
00308   _dbus_assert (len1 >= 0);
00309   _dbus_assert (len2 >= 0);
00310   
00311 #ifdef HAVE_WRITEV
00312   {
00313     struct iovec vectors[2];
00314     const char *data1;
00315     const char *data2;
00316     int bytes_written;
00317 
00318     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00319 
00320     if (buffer2 != NULL)
00321       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00322     else
00323       {
00324         data2 = NULL;
00325         start2 = 0;
00326         len2 = 0;
00327       }
00328    
00329     vectors[0].iov_base = (char*) data1;
00330     vectors[0].iov_len = len1;
00331     vectors[1].iov_base = (char*) data2;
00332     vectors[1].iov_len = len2;
00333 
00334   again:
00335    
00336     bytes_written = writev (fd,
00337                             vectors,
00338                             data2 ? 2 : 1);
00339 
00340     if (bytes_written < 0 && errno == EINTR)
00341       goto again;
00342    
00343     return bytes_written;
00344   }
00345 #else /* HAVE_WRITEV */
00346   {
00347     int ret1;
00348     
00349     ret1 = _dbus_write (fd, buffer1, start1, len1);
00350     if (ret1 == len1 && buffer2 != NULL)
00351       {
00352         ret2 = _dbus_write (fd, buffer2, start2, len2);
00353         if (ret2 < 0)
00354           ret2 = 0; /* we can't report an error as the first write was OK */
00355        
00356         return ret1 + ret2;
00357       }
00358     else
00359       return ret1;
00360   }
00361 #endif /* !HAVE_WRITEV */   
00362 }
00363 
00364 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00365 
00393 int
00394 _dbus_connect_unix_socket (const char     *path,
00395                            dbus_bool_t     abstract,
00396                            DBusError      *error)
00397 {
00398   int fd;
00399   struct sockaddr_un addr;  
00400 
00401   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00402 
00403   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00404                  path, abstract);
00405   
00406   fd = socket (PF_UNIX, SOCK_STREAM, 0);
00407   
00408   if (fd < 0)
00409     {
00410       dbus_set_error (error,
00411                       _dbus_error_from_errno (errno),
00412                       "Failed to create socket: %s",
00413                       _dbus_strerror (errno)); 
00414       
00415       return -1;
00416     }
00417 
00418   _DBUS_ZERO (addr);
00419   addr.sun_family = AF_UNIX;
00420 
00421   if (abstract)
00422     {
00423 #ifdef HAVE_ABSTRACT_SOCKETS
00424       /* remember that abstract names aren't nul-terminated so we rely
00425        * on sun_path being filled in with zeroes above.
00426        */
00427       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00428       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00429       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00430 #else /* HAVE_ABSTRACT_SOCKETS */
00431       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00432                       "Operating system does not support abstract socket namespace\n");
00433       close (fd);
00434       return -1;
00435 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00436     }
00437   else
00438     {
00439       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00440     }
00441   
00442   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00443     {      
00444       dbus_set_error (error,
00445                       _dbus_error_from_errno (errno),
00446                       "Failed to connect to socket %s: %s",
00447                       path, _dbus_strerror (errno));
00448 
00449       close (fd);
00450       fd = -1;
00451       
00452       return -1;
00453     }
00454 
00455   if (!_dbus_set_fd_nonblocking (fd, error))
00456     {
00457       _DBUS_ASSERT_ERROR_IS_SET (error);
00458       
00459       close (fd);
00460       fd = -1;
00461 
00462       return -1;
00463     }
00464 
00465   return fd;
00466 }
00467 
00483 int
00484 _dbus_listen_unix_socket (const char     *path,
00485                           dbus_bool_t     abstract,
00486                           DBusError      *error)
00487 {
00488   int listen_fd;
00489   struct sockaddr_un addr;
00490 
00491   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00492 
00493   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00494                  path, abstract);
00495   
00496   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00497   
00498   if (listen_fd < 0)
00499     {
00500       dbus_set_error (error, _dbus_error_from_errno (errno),
00501                       "Failed to create socket \"%s\": %s",
00502                       path, _dbus_strerror (errno));
00503       return -1;
00504     }
00505 
00506   _DBUS_ZERO (addr);
00507   addr.sun_family = AF_UNIX;
00508   
00509   if (abstract)
00510     {
00511 #ifdef HAVE_ABSTRACT_SOCKETS
00512       /* remember that abstract names aren't nul-terminated so we rely
00513        * on sun_path being filled in with zeroes above.
00514        */
00515       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00516       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00517       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00518 #else /* HAVE_ABSTRACT_SOCKETS */
00519       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00520                       "Operating system does not support abstract socket namespace\n");
00521       close (listen_fd);
00522       return -1;
00523 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00524     }
00525   else
00526     {
00527       /* FIXME discussed security implications of this with Nalin,
00528        * and we couldn't think of where it would kick our ass, but
00529        * it still seems a bit sucky. It also has non-security suckage;
00530        * really we'd prefer to exit if the socket is already in use.
00531        * But there doesn't seem to be a good way to do this.
00532        *
00533        * Just to be extra careful, I threw in the stat() - clearly
00534        * the stat() can't *fix* any security issue, but it at least
00535        * avoids inadvertent/accidental data loss.
00536        */
00537       {
00538         struct stat sb;
00539 
00540         if (stat (path, &sb) == 0 &&
00541             S_ISSOCK (sb.st_mode))
00542           unlink (path);
00543       }
00544 
00545       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00546     }
00547   
00548   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00549     {
00550       dbus_set_error (error, _dbus_error_from_errno (errno),
00551                       "Failed to bind socket \"%s\": %s",
00552                       path, _dbus_strerror (errno));
00553       close (listen_fd);
00554       return -1;
00555     }
00556 
00557   if (listen (listen_fd, 30 /* backlog */) < 0)
00558     {
00559       dbus_set_error (error, _dbus_error_from_errno (errno),
00560                       "Failed to listen on socket \"%s\": %s",
00561                       path, _dbus_strerror (errno));
00562       close (listen_fd);
00563       return -1;
00564     }
00565 
00566   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00567     {
00568       _DBUS_ASSERT_ERROR_IS_SET (error);
00569       close (listen_fd);
00570       return -1;
00571     }
00572   
00573   /* Try opening up the permissions, but if we can't, just go ahead
00574    * and continue, maybe it will be good enough.
00575    */
00576   if (!abstract && chmod (path, 0777) < 0)
00577     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00578                 path);
00579   
00580   return listen_fd;
00581 }
00582 
00593 int
00594 _dbus_connect_tcp_socket (const char     *host,
00595                           dbus_uint32_t   port,
00596                           DBusError      *error)
00597 {
00598   int fd;
00599   struct sockaddr_in addr;
00600   struct hostent *he;
00601   struct in_addr *haddr;
00602 
00603   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00604   
00605   fd = socket (AF_INET, SOCK_STREAM, 0);
00606   
00607   if (fd < 0)
00608     {
00609       dbus_set_error (error,
00610                       _dbus_error_from_errno (errno),
00611                       "Failed to create socket: %s",
00612                       _dbus_strerror (errno)); 
00613       
00614       return -1;
00615     }
00616 
00617   if (host == NULL)
00618     host = "localhost";
00619 
00620   he = gethostbyname (host);
00621   if (he == NULL) 
00622     {
00623       dbus_set_error (error,
00624                       _dbus_error_from_errno (errno),
00625                       "Failed to lookup hostname: %s",
00626                       host);
00627       close (fd);
00628       return -1;
00629     }
00630   
00631   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00632 
00633   _DBUS_ZERO (addr);
00634   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00635   addr.sin_family = AF_INET;
00636   addr.sin_port = htons (port);
00637   
00638   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00639     {      
00640       dbus_set_error (error,
00641                        _dbus_error_from_errno (errno),
00642                       "Failed to connect to socket %s: %s:%d",
00643                       host, _dbus_strerror (errno), port);
00644 
00645       close (fd);
00646       fd = -1;
00647       
00648       return -1;
00649     }
00650 
00651   if (!_dbus_set_fd_nonblocking (fd, error))
00652     {
00653       close (fd);
00654       fd = -1;
00655 
00656       return -1;
00657     }
00658 
00659   return fd;
00660 }
00661 
00672 int
00673 _dbus_listen_tcp_socket (const char     *host,
00674                          dbus_uint32_t   port,
00675                          DBusError      *error)
00676 {
00677   int listen_fd;
00678   struct sockaddr_in addr;
00679   struct hostent *he;
00680   struct in_addr *haddr;
00681 
00682   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00683   
00684   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00685   
00686   if (listen_fd < 0)
00687     {
00688       dbus_set_error (error, _dbus_error_from_errno (errno),
00689                       "Failed to create socket \"%s:%d\": %s",
00690                       host, port, _dbus_strerror (errno));
00691       return -1;
00692     }
00693 
00694   he = gethostbyname (host);
00695   if (he == NULL) 
00696     {
00697       dbus_set_error (error,
00698                       _dbus_error_from_errno (errno),
00699                       "Failed to lookup hostname: %s",
00700                       host);
00701       close (listen_fd);
00702       return -1;
00703     }
00704   
00705   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00706 
00707   _DBUS_ZERO (addr);
00708   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00709   addr.sin_family = AF_INET;
00710   addr.sin_port = htons (port);
00711 
00712   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00713     {
00714       dbus_set_error (error, _dbus_error_from_errno (errno),
00715                       "Failed to bind socket \"%s:%d\": %s",
00716                       host, port, _dbus_strerror (errno));
00717       close (listen_fd);
00718       return -1;
00719     }
00720 
00721   if (listen (listen_fd, 30 /* backlog */) < 0)
00722     {
00723       dbus_set_error (error, _dbus_error_from_errno (errno),  
00724                       "Failed to listen on socket \"%s:%d\": %s",
00725                       host, port, _dbus_strerror (errno));
00726       close (listen_fd);
00727       return -1;
00728     }
00729 
00730   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00731     {
00732       close (listen_fd);
00733       return -1;
00734     }
00735   
00736   return listen_fd;
00737 }
00738 
00739 static dbus_bool_t
00740 write_credentials_byte (int             server_fd,
00741                         DBusError      *error)
00742 {
00743   int bytes_written;
00744   char buf[1] = { '\0' };
00745 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00746   struct {
00747           struct cmsghdr hdr;
00748           struct cmsgcred cred;
00749   } cmsg;
00750   struct iovec iov;
00751   struct msghdr msg;
00752 #endif
00753 
00754 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00755   iov.iov_base = buf;
00756   iov.iov_len = 1;
00757 
00758   memset (&msg, 0, sizeof (msg));
00759   msg.msg_iov = &iov;
00760   msg.msg_iovlen = 1;
00761 
00762   msg.msg_control = &cmsg;
00763   msg.msg_controllen = sizeof (cmsg);
00764   memset (&cmsg, 0, sizeof (cmsg));
00765   cmsg.hdr.cmsg_len = sizeof (cmsg);
00766   cmsg.hdr.cmsg_level = SOL_SOCKET;
00767   cmsg.hdr.cmsg_type = SCM_CREDS;
00768 #endif
00769 
00770   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00771   
00772  again:
00773 
00774 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00775   bytes_written = sendmsg (server_fd, &msg, 0);
00776 #else
00777   bytes_written = write (server_fd, buf, 1);
00778 #endif
00779 
00780   if (bytes_written < 0 && errno == EINTR)
00781     goto again;
00782 
00783   if (bytes_written < 0)
00784     {
00785       dbus_set_error (error, _dbus_error_from_errno (errno),
00786                       "Failed to write credentials byte: %s",
00787                      _dbus_strerror (errno));
00788       return FALSE;
00789     }
00790   else if (bytes_written == 0)
00791     {
00792       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00793                       "wrote zero bytes writing credentials byte");
00794       return FALSE;
00795     }
00796   else
00797     {
00798       _dbus_assert (bytes_written == 1);
00799       _dbus_verbose ("wrote credentials byte\n");
00800       return TRUE;
00801     }
00802 }
00803 
00822 dbus_bool_t
00823 _dbus_read_credentials_unix_socket  (int              client_fd,
00824                                      DBusCredentials *credentials,
00825                                      DBusError       *error)
00826 {
00827   struct msghdr msg;
00828   struct iovec iov;
00829   char buf;
00830 
00831 #ifdef HAVE_CMSGCRED 
00832   struct {
00833           struct cmsghdr hdr;
00834           struct cmsgcred cred;
00835   } cmsg;
00836 #endif
00837 
00838   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00839   
00840   /* The POSIX spec certainly doesn't promise this, but
00841    * we need these assertions to fail as soon as we're wrong about
00842    * it so we can do the porting fixups
00843    */
00844   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00845   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00846   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00847 
00848   _dbus_credentials_clear (credentials);
00849 
00850 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00851   /* Set the socket to receive credentials on the next message */
00852   {
00853     int on = 1;
00854     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00855       {
00856         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00857         return FALSE;
00858       }
00859   }
00860 #endif
00861 
00862   iov.iov_base = &buf;
00863   iov.iov_len = 1;
00864 
00865   memset (&msg, 0, sizeof (msg));
00866   msg.msg_iov = &iov;
00867   msg.msg_iovlen = 1;
00868 
00869 #ifdef HAVE_CMSGCRED
00870   memset (&cmsg, 0, sizeof (cmsg));
00871   msg.msg_control = &cmsg;
00872   msg.msg_controllen = sizeof (cmsg);
00873 #endif
00874 
00875  again:
00876   if (recvmsg (client_fd, &msg, 0) < 0)
00877     {
00878       if (errno == EINTR)
00879         goto again;
00880 
00881       dbus_set_error (error, _dbus_error_from_errno (errno),
00882                       "Failed to read credentials byte: %s",
00883                       _dbus_strerror (errno));
00884       return FALSE;
00885     }
00886 
00887   if (buf != '\0')
00888     {
00889       dbus_set_error (error, DBUS_ERROR_FAILED,
00890                       "Credentials byte was not nul");
00891       return FALSE;
00892     }
00893 
00894 #ifdef HAVE_CMSGCRED
00895   if (cmsg->hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00896     {
00897       dbus_set_error (error, DBUS_ERROR_FAILED,
00898                       "Message from recvmsg() was not SCM_CREDS");
00899       return FALSE;
00900     }
00901 #endif
00902 
00903   _dbus_verbose ("read credentials byte\n");
00904 
00905   {
00906 #ifdef SO_PEERCRED
00907     struct ucred cr;   
00908     int cr_len = sizeof (cr);
00909    
00910     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00911         cr_len == sizeof (cr))
00912       {
00913         credentials->pid = cr.pid;
00914         credentials->uid = cr.uid;
00915         credentials->gid = cr.gid;
00916       }
00917     else
00918       {
00919         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00920                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00921       }
00922 #elif defined(HAVE_CMSGCRED)
00923     credentials->pid = cmsg.cred.cmcred_pid;
00924     credentials->uid = cmsg.cred.cmcred_euid;
00925     credentials->gid = cmsg.cred.cmcred_groups[0];
00926 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
00927     _dbus_verbose ("Socket credentials not supported on this OS\n");
00928 #endif
00929   }
00930 
00931   _dbus_verbose ("Credentials:"
00932                  "  pid "DBUS_PID_FORMAT
00933                  "  uid "DBUS_UID_FORMAT
00934                  "  gid "DBUS_GID_FORMAT"\n",
00935                  credentials->pid,
00936                  credentials->uid,
00937                  credentials->gid);
00938     
00939   return TRUE;
00940 }
00941 
00959 dbus_bool_t
00960 _dbus_send_credentials_unix_socket  (int              server_fd,
00961                                      DBusError       *error)
00962 {
00963   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00964   
00965   if (write_credentials_byte (server_fd, error))
00966     return TRUE;
00967   else
00968     return FALSE;
00969 }
00970 
00978 int
00979 _dbus_accept  (int listen_fd)
00980 {
00981   int client_fd;
00982   struct sockaddr addr;
00983   socklen_t addrlen;
00984 
00985   addrlen = sizeof (addr);
00986   
00987  retry:
00988   client_fd = accept (listen_fd, &addr, &addrlen);
00989   
00990   if (client_fd < 0)
00991     {
00992       if (errno == EINTR)
00993         goto retry;
00994     }
00995   
00996   return client_fd;
00997 }
00998 
01013 dbus_bool_t
01014 _dbus_string_append_int (DBusString *str,
01015                          long        value)
01016 {
01017   /* this calculation is from comp.lang.c faq */
01018 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
01019   int orig_len;
01020   int i;
01021   char *buf;
01022   
01023   orig_len = _dbus_string_get_length (str);
01024 
01025   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
01026     return FALSE;
01027 
01028   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01029 
01030   snprintf (buf, MAX_LONG_LEN, "%ld", value);
01031 
01032   i = 0;
01033   while (*buf)
01034     {
01035       ++buf;
01036       ++i;
01037     }
01038   
01039   _dbus_string_shorten (str, MAX_LONG_LEN - i);
01040   
01041   return TRUE;
01042 }
01043 
01051 dbus_bool_t
01052 _dbus_string_append_uint (DBusString    *str,
01053                           unsigned long  value)
01054 {
01055   /* this is wrong, but definitely on the high side. */
01056 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01057   int orig_len;
01058   int i;
01059   char *buf;
01060   
01061   orig_len = _dbus_string_get_length (str);
01062 
01063   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01064     return FALSE;
01065 
01066   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01067 
01068   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01069 
01070   i = 0;
01071   while (*buf)
01072     {
01073       ++buf;
01074       ++i;
01075     }
01076   
01077   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01078   
01079   return TRUE;
01080 }
01081 
01082 #ifdef DBUS_BUILD_TESTS
01083 
01090 dbus_bool_t
01091 _dbus_string_append_double (DBusString *str,
01092                             double      value)
01093 {
01094 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
01095   int orig_len;
01096   char *buf;
01097   int i;
01098   
01099   orig_len = _dbus_string_get_length (str);
01100 
01101   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01102     return FALSE;
01103 
01104   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01105 
01106   snprintf (buf, MAX_LONG_LEN, "%g", value);
01107 
01108   i = 0;
01109   while (*buf)
01110     {
01111       ++buf;
01112       ++i;
01113     }
01114   
01115   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01116   
01117   return TRUE;
01118 }
01119 #endif /* DBUS_BUILD_TESTS */
01120 
01133 dbus_bool_t
01134 _dbus_string_parse_int (const DBusString *str,
01135                         int               start,
01136                         long             *value_return,
01137                         int              *end_return)
01138 {
01139   long v;
01140   const char *p;
01141   char *end;
01142 
01143   p = _dbus_string_get_const_data_len (str, start,
01144                                        _dbus_string_get_length (str) - start);
01145 
01146   end = NULL;
01147   errno = 0;
01148   v = strtol (p, &end, 0);
01149   if (end == NULL || end == p || errno != 0)
01150     return FALSE;
01151 
01152   if (value_return)
01153     *value_return = v;
01154   if (end_return)
01155     *end_return = start + (end - p);
01156 
01157   return TRUE;
01158 }
01159 
01167 dbus_bool_t
01168 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01169 {
01170   const char *directory;
01171   struct stat sb;
01172         
01173   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01174     
01175   directory = _dbus_string_get_const_data (dir);
01176         
01177   if (stat (directory, &sb) < 0)
01178     {
01179       dbus_set_error (error, _dbus_error_from_errno (errno),
01180                       "%s", _dbus_strerror (errno));
01181    
01182       return FALSE;
01183     }
01184     
01185   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01186       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01187     {
01188       dbus_set_error (error, DBUS_ERROR_FAILED,
01189                      "%s directory is not private to the user", directory);
01190       return FALSE;
01191     }
01192     
01193   return TRUE;
01194 }
01195 
01196 #ifdef DBUS_BUILD_TESTS
01197 /* Not currently used, so only built when tests are enabled */
01210 dbus_bool_t
01211 _dbus_string_parse_uint (const DBusString *str,
01212                          int               start,
01213                          unsigned long    *value_return,
01214                          int              *end_return)
01215 {
01216   unsigned long v;
01217   const char *p;
01218   char *end;
01219 
01220   p = _dbus_string_get_const_data_len (str, start,
01221                                        _dbus_string_get_length (str) - start);
01222 
01223   end = NULL;
01224   errno = 0;
01225   v = strtoul (p, &end, 0);
01226   if (end == NULL || end == p || errno != 0)
01227     return FALSE;
01228 
01229   if (value_return)
01230     *value_return = v;
01231   if (end_return)
01232     *end_return = start + (end - p);
01233 
01234   return TRUE;
01235 }
01236 #endif /* DBUS_BUILD_TESTS */
01237 
01238 #ifdef DBUS_BUILD_TESTS
01239 static dbus_bool_t
01240 ascii_isspace (char c)
01241 {
01242   return (c == ' ' ||
01243           c == '\f' ||
01244           c == '\n' ||
01245           c == '\r' ||
01246           c == '\t' ||
01247           c == '\v');
01248 }
01249 #endif /* DBUS_BUILD_TESTS */
01250 
01251 #ifdef DBUS_BUILD_TESTS
01252 static dbus_bool_t
01253 ascii_isdigit (char c)
01254 {
01255   return c >= '0' && c <= '9';
01256 }
01257 #endif /* DBUS_BUILD_TESTS */
01258 
01259 #ifdef DBUS_BUILD_TESTS
01260 static dbus_bool_t
01261 ascii_isxdigit (char c)
01262 {
01263   return (ascii_isdigit (c) ||
01264           (c >= 'a' && c <= 'f') ||
01265           (c >= 'A' && c <= 'F'));
01266 }
01267 #endif /* DBUS_BUILD_TESTS */
01268 
01269 #ifdef DBUS_BUILD_TESTS
01270 /* Calls strtod in a locale-independent fashion, by looking at
01271  * the locale data and patching the decimal comma to a point.
01272  *
01273  * Relicensed from glib.
01274  */
01275 static double
01276 ascii_strtod (const char *nptr,
01277               char      **endptr)
01278 {
01279   char *fail_pos;
01280   double val;
01281   struct lconv *locale_data;
01282   const char *decimal_point;
01283   int decimal_point_len;
01284   const char *p, *decimal_point_pos;
01285   const char *end = NULL; /* Silence gcc */
01286 
01287   fail_pos = NULL;
01288 
01289   locale_data = localeconv ();
01290   decimal_point = locale_data->decimal_point;
01291   decimal_point_len = strlen (decimal_point);
01292 
01293   _dbus_assert (decimal_point_len != 0);
01294   
01295   decimal_point_pos = NULL;
01296   if (decimal_point[0] != '.' ||
01297       decimal_point[1] != 0)
01298     {
01299       p = nptr;
01300       /* Skip leading space */
01301       while (ascii_isspace (*p))
01302         p++;
01303       
01304       /* Skip leading optional sign */
01305       if (*p == '+' || *p == '-')
01306         p++;
01307       
01308       if (p[0] == '0' &&
01309           (p[1] == 'x' || p[1] == 'X'))
01310         {
01311           p += 2;
01312           /* HEX - find the (optional) decimal point */
01313           
01314           while (ascii_isxdigit (*p))
01315             p++;
01316           
01317           if (*p == '.')
01318             {
01319               decimal_point_pos = p++;
01320               
01321               while (ascii_isxdigit (*p))
01322                 p++;
01323               
01324               if (*p == 'p' || *p == 'P')
01325                 p++;
01326               if (*p == '+' || *p == '-')
01327                 p++;
01328               while (ascii_isdigit (*p))
01329                 p++;
01330               end = p;
01331             }
01332         }
01333       else
01334         {
01335           while (ascii_isdigit (*p))
01336             p++;
01337           
01338           if (*p == '.')
01339             {
01340               decimal_point_pos = p++;
01341               
01342               while (ascii_isdigit (*p))
01343                 p++;
01344               
01345               if (*p == 'e' || *p == 'E')
01346                 p++;
01347               if (*p == '+' || *p == '-')
01348                 p++;
01349               while (ascii_isdigit (*p))
01350                 p++;
01351               end = p;
01352             }
01353         }
01354       /* For the other cases, we need not convert the decimal point */
01355     }
01356 
01357   /* Set errno to zero, so that we can distinguish zero results
01358      and underflows */
01359   errno = 0;
01360   
01361   if (decimal_point_pos)
01362     {
01363       char *copy, *c;
01364 
01365       /* We need to convert the '.' to the locale specific decimal point */
01366       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01367       
01368       c = copy;
01369       memcpy (c, nptr, decimal_point_pos - nptr);
01370       c += decimal_point_pos - nptr;
01371       memcpy (c, decimal_point, decimal_point_len);
01372       c += decimal_point_len;
01373       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01374       c += end - (decimal_point_pos + 1);
01375       *c = 0;
01376 
01377       val = strtod (copy, &fail_pos);
01378 
01379       if (fail_pos)
01380         {
01381           if (fail_pos > decimal_point_pos)
01382             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01383           else
01384             fail_pos = (char *)nptr + (fail_pos - copy);
01385         }
01386       
01387       dbus_free (copy);
01388           
01389     }
01390   else
01391     val = strtod (nptr, &fail_pos);
01392 
01393   if (endptr)
01394     *endptr = fail_pos;
01395   
01396   return val;
01397 }
01398 #endif /* DBUS_BUILD_TESTS */
01399 
01400 #ifdef DBUS_BUILD_TESTS
01401 
01413 dbus_bool_t
01414 _dbus_string_parse_double (const DBusString *str,
01415                            int               start,
01416                            double           *value_return,
01417                            int              *end_return)
01418 {
01419   double v;
01420   const char *p;
01421   char *end;
01422 
01423   p = _dbus_string_get_const_data_len (str, start,
01424                                        _dbus_string_get_length (str) - start);
01425 
01426   end = NULL;
01427   errno = 0;
01428   v = ascii_strtod (p, &end);
01429   if (end == NULL || end == p || errno != 0)
01430     return FALSE;
01431 
01432   if (value_return)
01433     *value_return = v;
01434   if (end_return)
01435     *end_return = start + (end - p);
01436 
01437   return TRUE;
01438 }
01439 #endif /* DBUS_BUILD_TESTS */
01440  /* DBusString group */
01442 
01447 static dbus_bool_t
01448 fill_user_info_from_passwd (struct passwd *p,
01449                             DBusUserInfo  *info,
01450                             DBusError     *error)
01451 {
01452   _dbus_assert (p->pw_name != NULL);
01453   _dbus_assert (p->pw_dir != NULL);
01454   
01455   info->uid = p->pw_uid;
01456   info->primary_gid = p->pw_gid;
01457   info->username = _dbus_strdup (p->pw_name);
01458   info->homedir = _dbus_strdup (p->pw_dir);
01459   
01460   if (info->username == NULL ||
01461       info->homedir == NULL)
01462     {
01463       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01464       return FALSE;
01465     }
01466 
01467   return TRUE;
01468 }
01469 
01470 static dbus_bool_t
01471 fill_user_info (DBusUserInfo       *info,
01472                 dbus_uid_t          uid,
01473                 const DBusString   *username,
01474                 DBusError          *error)
01475 {
01476   const char *username_c;
01477   
01478   /* exactly one of username/uid provided */
01479   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01480   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01481 
01482   info->uid = DBUS_UID_UNSET;
01483   info->primary_gid = DBUS_GID_UNSET;
01484   info->group_ids = NULL;
01485   info->n_group_ids = 0;
01486   info->username = NULL;
01487   info->homedir = NULL;
01488   
01489   if (username != NULL)
01490     username_c = _dbus_string_get_const_data (username);
01491   else
01492     username_c = NULL;
01493 
01494   /* For now assuming that the getpwnam() and getpwuid() flavors
01495    * are always symmetrical, if not we have to add more configure
01496    * checks
01497    */
01498   
01499 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01500   {
01501     struct passwd *p;
01502     int result;
01503     char buf[1024];
01504     struct passwd p_str;
01505 
01506     p = NULL;
01507 #ifdef HAVE_POSIX_GETPWNAM_R
01508     if (uid != DBUS_UID_UNSET)
01509       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01510                            &p);
01511     else
01512       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01513                            &p);
01514 #else
01515     if (uid != DBUS_UID_UNSET)
01516       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01517     else
01518       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01519     result = 0;
01520 #endif /* !HAVE_POSIX_GETPWNAM_R */
01521     if (result == 0 && p == &p_str)
01522       {
01523         if (!fill_user_info_from_passwd (p, info, error))
01524           return FALSE;
01525       }
01526     else
01527       {
01528         dbus_set_error (error, _dbus_error_from_errno (errno),
01529                         "User \"%s\" unknown or no memory to allocate password entry\n",
01530                         username_c ? username_c : "???");
01531         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01532         return FALSE;
01533       }
01534   }
01535 #else /* ! HAVE_GETPWNAM_R */
01536   {
01537     /* I guess we're screwed on thread safety here */
01538     struct passwd *p;
01539 
01540     if (uid != DBUS_UID_UNSET)
01541       p = getpwuid (uid);
01542     else
01543       p = getpwnam (username_c);
01544 
01545     if (p != NULL)
01546       {
01547         if (!fill_user_info_from_passwd (p, info, error))
01548           return FALSE;
01549       }
01550     else
01551       {
01552         dbus_set_error (error, _dbus_error_from_errno (errno),
01553                         "User \"%s\" unknown or no memory to allocate password entry\n",
01554                         username_c ? username_c : "???");
01555         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01556         return FALSE;
01557       }
01558   }
01559 #endif  /* ! HAVE_GETPWNAM_R */
01560 
01561   /* Fill this in so we can use it to get groups */
01562   username_c = info->username;
01563   
01564 #ifdef HAVE_GETGROUPLIST
01565   {
01566     gid_t *buf;
01567     int buf_count;
01568     int i;
01569     
01570     buf_count = 17;
01571     buf = dbus_new (gid_t, buf_count);
01572     if (buf == NULL)
01573       {
01574         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01575         goto failed;
01576       }
01577     
01578     if (getgrouplist (username_c,
01579                       info->primary_gid,
01580                       buf, &buf_count) < 0)
01581       {
01582         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01583         if (new == NULL)
01584           {
01585             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01586             dbus_free (buf);
01587             goto failed;
01588           }
01589         
01590         buf = new;
01591 
01592         errno = 0;
01593         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01594           {
01595             dbus_set_error (error,
01596                             _dbus_error_from_errno (errno),
01597                             "Failed to get groups for username \"%s\" primary GID "
01598                             DBUS_GID_FORMAT ": %s\n",
01599                             username_c, info->primary_gid,
01600                             _dbus_strerror (errno));
01601             dbus_free (buf);
01602             goto failed;
01603           }
01604       }
01605 
01606     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01607     if (info->group_ids == NULL)
01608       {
01609         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01610         dbus_free (buf);
01611         goto failed;
01612       }
01613     
01614     for (i = 0; i < buf_count; ++i)
01615       info->group_ids[i] = buf[i];
01616 
01617     info->n_group_ids = buf_count;
01618     
01619     dbus_free (buf);
01620   }
01621 #else  /* HAVE_GETGROUPLIST */
01622   {
01623     /* We just get the one group ID */
01624     info->group_ids = dbus_new (dbus_gid_t, 1);
01625     if (info->group_ids == NULL)
01626       {
01627         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01628         goto failed;
01629       }
01630 
01631     info->n_group_ids = 1;
01632 
01633     (info->group_ids)[0] = info->primary_gid;
01634   }
01635 #endif /* HAVE_GETGROUPLIST */
01636 
01637   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01638   
01639   return TRUE;
01640   
01641  failed:
01642   _DBUS_ASSERT_ERROR_IS_SET (error);
01643   return FALSE;
01644 }
01645 
01654 dbus_bool_t
01655 _dbus_user_info_fill (DBusUserInfo     *info,
01656                       const DBusString *username,
01657                       DBusError        *error)
01658 {
01659   return fill_user_info (info, DBUS_UID_UNSET,
01660                          username, error);
01661 }
01662 
01671 dbus_bool_t
01672 _dbus_user_info_fill_uid (DBusUserInfo *info,
01673                           dbus_uid_t    uid,
01674                           DBusError    *error)
01675 {
01676   return fill_user_info (info, uid,
01677                          NULL, error);
01678 }
01679 
01685 void
01686 _dbus_user_info_free (DBusUserInfo *info)
01687 {
01688   dbus_free (info->group_ids);
01689   dbus_free (info->username);
01690   dbus_free (info->homedir);
01691 }
01692 
01699 void
01700 _dbus_credentials_clear (DBusCredentials *credentials)
01701 {
01702   credentials->pid = DBUS_PID_UNSET;
01703   credentials->uid = DBUS_UID_UNSET;
01704   credentials->gid = DBUS_GID_UNSET;
01705 }
01706 
01712 void
01713 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01714 {
01715   /* The POSIX spec certainly doesn't promise this, but
01716    * we need these assertions to fail as soon as we're wrong about
01717    * it so we can do the porting fixups
01718    */
01719   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01720   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01721   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01722   
01723   credentials->pid = getpid ();
01724   credentials->uid = getuid ();
01725   credentials->gid = getgid ();
01726 }
01727 
01736 dbus_bool_t
01737 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01738                          const DBusCredentials *provided_credentials)
01739 {
01740   if (provided_credentials->uid == DBUS_UID_UNSET)
01741     return FALSE;
01742   else if (expected_credentials->uid == DBUS_UID_UNSET)
01743     return FALSE;
01744   else if (provided_credentials->uid == 0)
01745     return TRUE;
01746   else if (provided_credentials->uid == expected_credentials->uid)
01747     return TRUE;
01748   else
01749     return FALSE;
01750 }
01751 
01756 unsigned long
01757 _dbus_getpid (void)
01758 {
01759   return getpid ();
01760 }
01761 
01765 dbus_uid_t
01766 _dbus_getuid (void)
01767 {
01768   return getuid ();
01769 }
01770 
01771 #ifdef DBUS_BUILD_TESTS
01772 
01775 dbus_gid_t
01776 _dbus_getgid (void)
01777 {
01778   return getgid ();
01779 }
01780 #endif
01781 
01782 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01783 
01784 #ifdef DBUS_USE_ATOMIC_INT_486
01785 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01786 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01787 static inline dbus_int32_t
01788 atomic_exchange_and_add (DBusAtomic            *atomic,
01789                          volatile dbus_int32_t  val)
01790 {
01791   register dbus_int32_t result;
01792 
01793   __asm__ __volatile__ ("lock; xaddl %0,%1"
01794                         : "=r" (result), "=m" (atomic->value)
01795                         : "0" (val), "m" (atomic->value));
01796   return result;
01797 }
01798 #endif
01799 
01808 dbus_int32_t
01809 _dbus_atomic_inc (DBusAtomic *atomic)
01810 {
01811 #ifdef DBUS_USE_ATOMIC_INT_486
01812   return atomic_exchange_and_add (atomic, 1);
01813 #else
01814   dbus_int32_t res;
01815   _DBUS_LOCK (atomic);
01816   res = atomic->value;
01817   atomic->value += 1;
01818   _DBUS_UNLOCK (atomic);
01819   return res;
01820 #endif
01821 }
01822 
01831 dbus_int32_t
01832 _dbus_atomic_dec (DBusAtomic *atomic)
01833 {
01834 #ifdef DBUS_USE_ATOMIC_INT_486
01835   return atomic_exchange_and_add (atomic, -1);
01836 #else
01837   dbus_int32_t res;
01838   
01839   _DBUS_LOCK (atomic);
01840   res = atomic->value;
01841   atomic->value -= 1;
01842   _DBUS_UNLOCK (atomic);
01843   return res;
01844 #endif
01845 }
01846 
01855 int
01856 _dbus_poll (DBusPollFD *fds,
01857             int         n_fds,
01858             int         timeout_milliseconds)
01859 {
01860 #ifdef HAVE_POLL
01861   /* This big thing is a constant expression and should get optimized
01862    * out of existence. So it's more robust than a configure check at
01863    * no cost.
01864    */
01865   if (_DBUS_POLLIN == POLLIN &&
01866       _DBUS_POLLPRI == POLLPRI &&
01867       _DBUS_POLLOUT == POLLOUT &&
01868       _DBUS_POLLERR == POLLERR &&
01869       _DBUS_POLLHUP == POLLHUP &&
01870       _DBUS_POLLNVAL == POLLNVAL &&
01871       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01872       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01873       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01874       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01875       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01876       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01877       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01878     {
01879       return poll ((struct pollfd*) fds,
01880                    n_fds, 
01881                    timeout_milliseconds);
01882     }
01883   else
01884     {
01885       /* We have to convert the DBusPollFD to an array of
01886        * struct pollfd, poll, and convert back.
01887        */
01888       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01889       return -1;
01890     }
01891 #else /* ! HAVE_POLL */
01892 
01893   fd_set read_set, write_set, err_set;
01894   int max_fd = 0;
01895   int i;
01896   struct timeval tv;
01897   int ready;
01898   
01899   FD_ZERO (&read_set);
01900   FD_ZERO (&write_set);
01901   FD_ZERO (&err_set);
01902 
01903   for (i = 0; i < n_fds; i++)
01904     {
01905       DBusPollFD *fdp = &fds[i];
01906 
01907       if (fdp->events & _DBUS_POLLIN)
01908         FD_SET (fdp->fd, &read_set);
01909 
01910       if (fdp->events & _DBUS_POLLOUT)
01911         FD_SET (fdp->fd, &write_set);
01912 
01913       FD_SET (fdp->fd, &err_set);
01914 
01915       max_fd = MAX (max_fd, fdp->fd);
01916     }
01917     
01918   tv.tv_sec = timeout_milliseconds / 1000;
01919   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01920 
01921   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01922                   timeout_milliseconds < 0 ? NULL : &tv);
01923 
01924   if (ready > 0)
01925     {
01926       for (i = 0; i < n_fds; i++)
01927         {
01928           DBusPollFD *fdp = &fds[i];
01929 
01930           fdp->revents = 0;
01931 
01932           if (FD_ISSET (fdp->fd, &read_set))
01933             fdp->revents |= _DBUS_POLLIN;
01934 
01935           if (FD_ISSET (fdp->fd, &write_set))
01936             fdp->revents |= _DBUS_POLLOUT;
01937 
01938           if (FD_ISSET (fdp->fd, &err_set))
01939             fdp->revents |= _DBUS_POLLERR;
01940         }
01941     }
01942 
01943   return ready;
01944 #endif
01945 }
01946 
01948 #define NANOSECONDS_PER_SECOND       1000000000
01949 
01950 #define MICROSECONDS_PER_SECOND      1000000
01951 
01952 #define MILLISECONDS_PER_SECOND      1000
01953 
01954 #define NANOSECONDS_PER_MILLISECOND  1000000
01955 
01956 #define MICROSECONDS_PER_MILLISECOND 1000
01957 
01962 void
01963 _dbus_sleep_milliseconds (int milliseconds)
01964 {
01965 #ifdef HAVE_NANOSLEEP
01966   struct timespec req;
01967   struct timespec rem;
01968 
01969   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
01970   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
01971   rem.tv_sec = 0;
01972   rem.tv_nsec = 0;
01973 
01974   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
01975     req = rem;
01976 #elif defined (HAVE_USLEEP)
01977   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
01978 #else /* ! HAVE_USLEEP */
01979   sleep (MAX (milliseconds / 1000, 1));
01980 #endif
01981 }
01982 
01989 void
01990 _dbus_get_current_time (long *tv_sec,
01991                         long *tv_usec)
01992 {
01993   struct timeval t;
01994 
01995   gettimeofday (&t, NULL);
01996 
01997   if (tv_sec)
01998     *tv_sec = t.tv_sec;
01999   if (tv_usec)
02000     *tv_usec = t.tv_usec;
02001 }
02002 
02013 dbus_bool_t
02014 _dbus_file_get_contents (DBusString       *str,
02015                          const DBusString *filename,
02016                          DBusError        *error)
02017 {
02018   int fd;
02019   struct stat sb;
02020   int orig_len;
02021   int total;
02022   const char *filename_c;
02023 
02024   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02025   
02026   filename_c = _dbus_string_get_const_data (filename);
02027   
02028   /* O_BINARY useful on Cygwin */
02029   fd = open (filename_c, O_RDONLY | O_BINARY);
02030   if (fd < 0)
02031     {
02032       dbus_set_error (error, _dbus_error_from_errno (errno),
02033                       "Failed to open \"%s\": %s",
02034                       filename_c,
02035                       _dbus_strerror (errno));
02036       return FALSE;
02037     }
02038 
02039   if (fstat (fd, &sb) < 0)
02040     {
02041       dbus_set_error (error, _dbus_error_from_errno (errno),
02042                       "Failed to stat \"%s\": %s",
02043                       filename_c,
02044                       _dbus_strerror (errno));
02045 
02046       _dbus_verbose ("fstat() failed: %s",
02047                      _dbus_strerror (errno));
02048       
02049       close (fd);
02050       
02051       return FALSE;
02052     }
02053 
02054   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02055     {
02056       dbus_set_error (error, DBUS_ERROR_FAILED,
02057                       "File size %lu of \"%s\" is too large.",
02058                       (unsigned long) sb.st_size, filename_c);
02059       close (fd);
02060       return FALSE;
02061     }
02062   
02063   total = 0;
02064   orig_len = _dbus_string_get_length (str);
02065   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02066     {
02067       int bytes_read;
02068 
02069       while (total < (int) sb.st_size)
02070         {
02071           bytes_read = _dbus_read (fd, str,
02072                                    sb.st_size - total);
02073           if (bytes_read <= 0)
02074             {
02075               dbus_set_error (error, _dbus_error_from_errno (errno),
02076                               "Error reading \"%s\": %s",
02077                               filename_c,
02078                               _dbus_strerror (errno));
02079 
02080               _dbus_verbose ("read() failed: %s",
02081                              _dbus_strerror (errno));
02082               
02083               close (fd);
02084               _dbus_string_set_length (str, orig_len);
02085               return FALSE;
02086             }
02087           else
02088             total += bytes_read;
02089         }
02090 
02091       close (fd);
02092       return TRUE;
02093     }
02094   else if (sb.st_size != 0)
02095     {
02096       _dbus_verbose ("Can only open regular files at the moment.\n");
02097       dbus_set_error (error, DBUS_ERROR_FAILED,
02098                       "\"%s\" is not a regular file",
02099                       filename_c);
02100       close (fd);
02101       return FALSE;
02102     }
02103   else
02104     {
02105       close (fd);
02106       return TRUE;
02107     }
02108 }
02109 
02119 dbus_bool_t
02120 _dbus_string_save_to_file (const DBusString *str,
02121                            const DBusString *filename,
02122                            DBusError        *error)
02123 {
02124   int fd;
02125   int bytes_to_write;
02126   const char *filename_c;
02127   DBusString tmp_filename;
02128   const char *tmp_filename_c;
02129   int total;
02130   dbus_bool_t need_unlink;
02131   dbus_bool_t retval;
02132 
02133   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02134   
02135   fd = -1;
02136   retval = FALSE;
02137   need_unlink = FALSE;
02138   
02139   if (!_dbus_string_init (&tmp_filename))
02140     {
02141       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02142       return FALSE;
02143     }
02144 
02145   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02146     {
02147       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02148       _dbus_string_free (&tmp_filename);
02149       return FALSE;
02150     }
02151   
02152   if (!_dbus_string_append (&tmp_filename, "."))
02153     {
02154       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02155       _dbus_string_free (&tmp_filename);
02156       return FALSE;
02157     }
02158 
02159 #define N_TMP_FILENAME_RANDOM_BYTES 8
02160   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02161     {
02162       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02163       _dbus_string_free (&tmp_filename);
02164       return FALSE;
02165     }
02166     
02167   filename_c = _dbus_string_get_const_data (filename);
02168   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02169 
02170   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02171              0600);
02172   if (fd < 0)
02173     {
02174       dbus_set_error (error, _dbus_error_from_errno (errno),
02175                       "Could not create %s: %s", tmp_filename_c,
02176                       _dbus_strerror (errno));
02177       goto out;
02178     }
02179 
02180   need_unlink = TRUE;
02181   
02182   total = 0;
02183   bytes_to_write = _dbus_string_get_length (str);
02184 
02185   while (total < bytes_to_write)
02186     {
02187       int bytes_written;
02188 
02189       bytes_written = _dbus_write (fd, str, total,
02190                                    bytes_to_write - total);
02191 
02192       if (bytes_written <= 0)
02193         {
02194           dbus_set_error (error, _dbus_error_from_errno (errno),
02195                           "Could not write to %s: %s", tmp_filename_c,
02196                           _dbus_strerror (errno));
02197           
02198           goto out;
02199         }
02200 
02201       total += bytes_written;
02202     }
02203 
02204   if (close (fd) < 0)
02205     {
02206       dbus_set_error (error, _dbus_error_from_errno (errno),
02207                       "Could not close file %s: %s",
02208                       tmp_filename_c, _dbus_strerror (errno));
02209 
02210       goto out;
02211     }
02212 
02213   fd = -1;
02214   
02215   if (rename (tmp_filename_c, filename_c) < 0)
02216     {
02217       dbus_set_error (error, _dbus_error_from_errno (errno),
02218                       "Could not rename %s to %s: %s",
02219                       tmp_filename_c, filename_c,
02220                       _dbus_strerror (errno));
02221 
02222       goto out;
02223     }
02224 
02225   need_unlink = FALSE;
02226   
02227   retval = TRUE;
02228   
02229  out:
02230   /* close first, then unlink, to prevent ".nfs34234235" garbage
02231    * files
02232    */
02233 
02234   if (fd >= 0)
02235     close (fd);
02236         
02237   if (need_unlink && unlink (tmp_filename_c) < 0)
02238     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02239                    tmp_filename_c, _dbus_strerror (errno));
02240 
02241   _dbus_string_free (&tmp_filename);
02242 
02243   if (!retval)
02244     _DBUS_ASSERT_ERROR_IS_SET (error);
02245   
02246   return retval;
02247 }
02248 
02255 dbus_bool_t
02256 _dbus_create_file_exclusively (const DBusString *filename,
02257                                DBusError        *error)
02258 {
02259   int fd;
02260   const char *filename_c;
02261 
02262   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02263   
02264   filename_c = _dbus_string_get_const_data (filename);
02265   
02266   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02267              0600);
02268   if (fd < 0)
02269     {
02270       dbus_set_error (error,
02271                       DBUS_ERROR_FAILED,
02272                       "Could not create file %s: %s\n",
02273                       filename_c,
02274                       _dbus_strerror (errno));
02275       return FALSE;
02276     }
02277 
02278   if (close (fd) < 0)
02279     {
02280       dbus_set_error (error,
02281                       DBUS_ERROR_FAILED,
02282                       "Could not close file %s: %s\n",
02283                       filename_c,
02284                       _dbus_strerror (errno));
02285       return FALSE;
02286     }
02287   
02288   return TRUE;
02289 }
02290 
02299 dbus_bool_t
02300 _dbus_delete_file (const DBusString *filename,
02301                    DBusError        *error)
02302 {
02303   const char *filename_c;
02304 
02305   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02306   
02307   filename_c = _dbus_string_get_const_data (filename);
02308 
02309   if (unlink (filename_c) < 0)
02310     {
02311       dbus_set_error (error, DBUS_ERROR_FAILED,
02312                       "Failed to delete file %s: %s\n",
02313                       filename_c, _dbus_strerror (errno));
02314       return FALSE;
02315     }
02316   else
02317     return TRUE;
02318 }
02319 
02328 dbus_bool_t
02329 _dbus_create_directory (const DBusString *filename,
02330                         DBusError        *error)
02331 {
02332   const char *filename_c;
02333 
02334   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02335   
02336   filename_c = _dbus_string_get_const_data (filename);
02337 
02338   if (mkdir (filename_c, 0700) < 0)
02339     {
02340       if (errno == EEXIST)
02341         return TRUE;
02342       
02343       dbus_set_error (error, DBUS_ERROR_FAILED,
02344                       "Failed to create directory %s: %s\n",
02345                       filename_c, _dbus_strerror (errno));
02346       return FALSE;
02347     }
02348   else
02349     return TRUE;
02350 }
02351 
02362 dbus_bool_t
02363 _dbus_concat_dir_and_file (DBusString       *dir,
02364                            const DBusString *next_component)
02365 {
02366   dbus_bool_t dir_ends_in_slash;
02367   dbus_bool_t file_starts_with_slash;
02368 
02369   if (_dbus_string_get_length (dir) == 0 ||
02370       _dbus_string_get_length (next_component) == 0)
02371     return TRUE;
02372   
02373   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02374                                                     _dbus_string_get_length (dir) - 1);
02375 
02376   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02377 
02378   if (dir_ends_in_slash && file_starts_with_slash)
02379     {
02380       _dbus_string_shorten (dir, 1);
02381     }
02382   else if (!(dir_ends_in_slash || file_starts_with_slash))
02383     {
02384       if (!_dbus_string_append_byte (dir, '/'))
02385         return FALSE;
02386     }
02387 
02388   return _dbus_string_copy (next_component, 0, dir,
02389                             _dbus_string_get_length (dir));
02390 }
02391 
02392 static void
02393 pseudorandom_generate_random_bytes_buffer (char *buffer,
02394                                            int   n_bytes)
02395 {
02396   unsigned long tv_usec;
02397   int i;
02398   
02399   /* fall back to pseudorandom */
02400   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02401                  n_bytes);
02402   
02403   _dbus_get_current_time (NULL, &tv_usec);
02404   srand (tv_usec);
02405   
02406   i = 0;
02407   while (i < n_bytes)
02408     {
02409       double r;
02410       unsigned int b;
02411           
02412       r = rand ();
02413       b = (r / (double) RAND_MAX) * 255.0;
02414 
02415       buffer[i] = b;
02416 
02417       ++i;
02418     }
02419 }
02420 
02421 static dbus_bool_t
02422 pseudorandom_generate_random_bytes (DBusString *str,
02423                                     int         n_bytes)
02424 {
02425   int old_len;
02426   char *p;
02427   
02428   old_len = _dbus_string_get_length (str);
02429 
02430   if (!_dbus_string_lengthen (str, n_bytes))
02431     return FALSE;
02432 
02433   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02434 
02435   pseudorandom_generate_random_bytes_buffer (p, n_bytes);
02436 
02437   return TRUE;
02438 }
02439 
02446 void
02447 _dbus_generate_random_bytes_buffer (char *buffer,
02448                                     int   n_bytes)
02449 {
02450   DBusString str;
02451 
02452   if (!_dbus_string_init (&str))
02453     {
02454       pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02455       return;
02456     }
02457 
02458   if (!_dbus_generate_random_bytes (&str, n_bytes))
02459     {
02460       _dbus_string_free (&str);
02461       pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02462       return;
02463     }
02464 
02465   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
02466 
02467   _dbus_string_free (&str);
02468 }
02469 
02478 dbus_bool_t
02479 _dbus_generate_random_bytes (DBusString *str,
02480                              int         n_bytes)
02481 {
02482   int old_len;
02483   int fd;
02484 
02485   /* FALSE return means "no memory", if it could
02486    * mean something else then we'd need to return
02487    * a DBusError. So we always fall back to pseudorandom
02488    * if the I/O fails.
02489    */
02490   
02491   old_len = _dbus_string_get_length (str);
02492   fd = -1;
02493 
02494   /* note, urandom on linux will fall back to pseudorandom */
02495   fd = open ("/dev/urandom", O_RDONLY);
02496   if (fd < 0)
02497     return pseudorandom_generate_random_bytes (str, n_bytes);
02498 
02499   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02500     {
02501       close (fd);
02502       _dbus_string_set_length (str, old_len);
02503       return pseudorandom_generate_random_bytes (str, n_bytes);
02504     }
02505 
02506   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02507                  n_bytes);
02508   
02509   close (fd);
02510   
02511   return TRUE;
02512 }
02513 
02522 dbus_bool_t
02523 _dbus_generate_random_ascii (DBusString *str,
02524                              int         n_bytes)
02525 {
02526   static const char letters[] =
02527     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02528   int i;
02529   int len;
02530   
02531   if (!_dbus_generate_random_bytes (str, n_bytes))
02532     return FALSE;
02533   
02534   len = _dbus_string_get_length (str);
02535   i = len - n_bytes;
02536   while (i < len)
02537     {
02538       _dbus_string_set_byte (str, i,
02539                              letters[_dbus_string_get_byte (str, i) %
02540                                      (sizeof (letters) - 1)]);
02541 
02542       ++i;
02543     }
02544 
02545   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02546                                              n_bytes));
02547 
02548   return TRUE;
02549 }
02550 
02558 const char*
02559 _dbus_strerror (int error_number)
02560 {
02561   const char *msg;
02562   
02563   msg = strerror (error_number);
02564   if (msg == NULL)
02565     msg = "unknown";
02566 
02567   return msg;
02568 }
02569 
02573 void
02574 _dbus_disable_sigpipe (void)
02575 {
02576   signal (SIGPIPE, SIG_IGN);
02577 }
02578 
02586 void
02587 _dbus_fd_set_close_on_exec (int fd)
02588 {
02589   int val;
02590   
02591   val = fcntl (fd, F_GETFD, 0);
02592   
02593   if (val < 0)
02594     return;
02595 
02596   val |= FD_CLOEXEC;
02597   
02598   fcntl (fd, F_SETFD, val);
02599 }
02600 
02610 const char*
02611 _dbus_error_from_errno (int error_number)
02612 {
02613   switch (error_number)
02614     {
02615     case 0:
02616       return DBUS_ERROR_FAILED;
02617       
02618 #ifdef EPROTONOSUPPORT
02619     case EPROTONOSUPPORT:
02620       return DBUS_ERROR_NOT_SUPPORTED;
02621 #endif
02622 #ifdef EAFNOSUPPORT
02623     case EAFNOSUPPORT:
02624       return DBUS_ERROR_NOT_SUPPORTED;
02625 #endif
02626 #ifdef ENFILE
02627     case ENFILE:
02628       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02629 #endif
02630 #ifdef EMFILE
02631     case EMFILE:
02632       return DBUS_ERROR_LIMITS_EXCEEDED;
02633 #endif
02634 #ifdef EACCES
02635     case EACCES:
02636       return DBUS_ERROR_ACCESS_DENIED;
02637 #endif
02638 #ifdef EPERM
02639     case EPERM:
02640       return DBUS_ERROR_ACCESS_DENIED;
02641 #endif
02642 #ifdef ENOBUFS
02643     case ENOBUFS:
02644       return DBUS_ERROR_NO_MEMORY;
02645 #endif
02646 #ifdef ENOMEM
02647     case ENOMEM:
02648       return DBUS_ERROR_NO_MEMORY;
02649 #endif
02650 #ifdef EINVAL
02651     case EINVAL:
02652       return DBUS_ERROR_FAILED;
02653 #endif
02654 #ifdef EBADF
02655     case EBADF:
02656       return DBUS_ERROR_FAILED;
02657 #endif
02658 #ifdef EFAULT
02659     case EFAULT:
02660       return DBUS_ERROR_FAILED;
02661 #endif
02662 #ifdef ENOTSOCK
02663     case ENOTSOCK:
02664       return DBUS_ERROR_FAILED;
02665 #endif
02666 #ifdef EISCONN
02667     case EISCONN:
02668       return DBUS_ERROR_FAILED;
02669 #endif
02670 #ifdef ECONNREFUSED
02671     case ECONNREFUSED:
02672       return DBUS_ERROR_NO_SERVER;
02673 #endif
02674 #ifdef ETIMEDOUT
02675     case ETIMEDOUT:
02676       return DBUS_ERROR_TIMEOUT;
02677 #endif
02678 #ifdef ENETUNREACH
02679     case ENETUNREACH:
02680       return DBUS_ERROR_NO_NETWORK;
02681 #endif
02682 #ifdef EADDRINUSE
02683     case EADDRINUSE:
02684       return DBUS_ERROR_ADDRESS_IN_USE;
02685 #endif
02686 #ifdef EEXIST
02687     case EEXIST:
02688       return DBUS_ERROR_FILE_NOT_FOUND;
02689 #endif
02690 #ifdef ENOENT
02691     case ENOENT:
02692       return DBUS_ERROR_FILE_NOT_FOUND;
02693 #endif
02694     }
02695 
02696   return DBUS_ERROR_FAILED;
02697 }
02698 
02704 void
02705 _dbus_exit (int code)
02706 {
02707   _exit (code);
02708 }
02709 
02717 dbus_bool_t
02718 _dbus_close (int        fd,
02719              DBusError *error)
02720 {
02721   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02722   
02723  again:
02724   if (close (fd) < 0)
02725     {
02726       if (errno == EINTR)
02727         goto again;
02728 
02729       dbus_set_error (error, _dbus_error_from_errno (errno),
02730                       "Could not close fd %d", fd);
02731       return FALSE;
02732     }
02733 
02734   return TRUE;
02735 }
02736 
02744 dbus_bool_t
02745 _dbus_set_fd_nonblocking (int             fd,
02746                           DBusError      *error)
02747 {
02748   int val;
02749 
02750   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02751   
02752   val = fcntl (fd, F_GETFL, 0);
02753   if (val < 0)
02754     {
02755       dbus_set_error (error, _dbus_error_from_errno (errno),
02756                       "Failed to get flags from file descriptor %d: %s",
02757                       fd, _dbus_strerror (errno));
02758       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02759                      _dbus_strerror (errno));
02760       return FALSE;
02761     }
02762 
02763   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02764     {
02765       dbus_set_error (error, _dbus_error_from_errno (errno),
02766                       "Failed to set nonblocking flag of file descriptor %d: %s",
02767                       fd, _dbus_strerror (errno));
02768       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02769                      fd, _dbus_strerror (errno));
02770 
02771       return FALSE;
02772     }
02773 
02774   return TRUE;
02775 }
02776 
02777 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
02778 
02783 void
02784 _dbus_print_backtrace (void)
02785 {
02786 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
02787   void *bt[500];
02788   int bt_size;
02789   int i;
02790   char **syms;
02791   
02792   bt_size = backtrace (bt, 500);
02793 
02794   syms = backtrace_symbols (bt, bt_size);
02795   
02796   i = 0;
02797   while (i < bt_size)
02798     {
02799       _dbus_verbose ("  %s\n", syms[i]);
02800       ++i;
02801     }
02802 
02803   free (syms);
02804 #else
02805   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
02806 #endif
02807 }
02808 #endif /* asserts or tests enabled */
02809 
02810 
02818 dbus_bool_t
02819 _dbus_parse_uid (const DBusString      *uid_str,
02820                  dbus_uid_t            *uid)
02821 {
02822   int end;
02823   long val;
02824   
02825   if (_dbus_string_get_length (uid_str) == 0)
02826     {
02827       _dbus_verbose ("UID string was zero length\n");
02828       return FALSE;
02829     }
02830 
02831   val = -1;
02832   end = 0;
02833   if (!_dbus_string_parse_int (uid_str, 0, &val,
02834                                &end))
02835     {
02836       _dbus_verbose ("could not parse string as a UID\n");
02837       return FALSE;
02838     }
02839   
02840   if (end != _dbus_string_get_length (uid_str))
02841     {
02842       _dbus_verbose ("string contained trailing stuff after UID\n");
02843       return FALSE;
02844     }
02845 
02846   *uid = val;
02847 
02848   return TRUE;
02849 }
02850 
02866 dbus_bool_t
02867 _dbus_full_duplex_pipe (int        *fd1,
02868                         int        *fd2,
02869                         dbus_bool_t blocking,
02870                         DBusError  *error)
02871 {
02872 #ifdef HAVE_SOCKETPAIR
02873   int fds[2];
02874 
02875   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02876   
02877   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02878     {
02879       dbus_set_error (error, _dbus_error_from_errno (errno),
02880                       "Could not create full-duplex pipe");
02881       return FALSE;
02882     }
02883 
02884   if (!blocking &&
02885       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02886        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02887     {
02888       dbus_set_error (error, _dbus_error_from_errno (errno),
02889                       "Could not set full-duplex pipe nonblocking");
02890       
02891       close (fds[0]);
02892       close (fds[1]);
02893       
02894       return FALSE;
02895     }
02896   
02897   *fd1 = fds[0];
02898   *fd2 = fds[1];
02899 
02900   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02901                  *fd1, *fd2);
02902   
02903   return TRUE;  
02904 #else
02905   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02906   dbus_set_error (error, DBUS_ERROR_FAILED,
02907                   "_dbus_full_duplex_pipe() not implemented on this OS");
02908   return FALSE;
02909 #endif
02910 }
02911 
02914 /* tests in dbus-sysdeps-util.c */

Generated on Tue Sep 13 01:28:07 2005 for D-BUS by  doxygen 1.4.4