Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-sysdeps.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.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 
01168 dbus_bool_t
01169 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01170 {
01171   const char *directory;
01172   struct stat sb;
01173         
01174   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01175     
01176   directory = _dbus_string_get_const_data (dir);
01177         
01178   if (stat (directory, &sb) < 0)
01179     {
01180       dbus_set_error (error, _dbus_error_from_errno (errno),
01181                       "%s", _dbus_strerror (errno));
01182    
01183       return FALSE;
01184     }
01185     
01186   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01187       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01188     {
01189       dbus_set_error (error, DBUS_ERROR_FAILED,
01190                      "%s directory is not private to the user", directory);
01191       return FALSE;
01192     }
01193     
01194   return TRUE;
01195 }
01196 
01209 dbus_bool_t
01210 _dbus_string_parse_uint (const DBusString *str,
01211                          int               start,
01212                          unsigned long    *value_return,
01213                          int              *end_return)
01214 {
01215   unsigned long v;
01216   const char *p;
01217   char *end;
01218 
01219   p = _dbus_string_get_const_data_len (str, start,
01220                                        _dbus_string_get_length (str) - start);
01221 
01222   end = NULL;
01223   errno = 0;
01224   v = strtoul (p, &end, 0);
01225   if (end == NULL || end == p || errno != 0)
01226     return FALSE;
01227 
01228   if (value_return)
01229     *value_return = v;
01230   if (end_return)
01231     *end_return = start + (end - p);
01232 
01233   return TRUE;
01234 }
01235 
01236 #ifdef DBUS_BUILD_TESTS
01237 static dbus_bool_t
01238 ascii_isspace (char c)
01239 {
01240   return (c == ' ' ||
01241           c == '\f' ||
01242           c == '\n' ||
01243           c == '\r' ||
01244           c == '\t' ||
01245           c == '\v');
01246 }
01247 #endif /* DBUS_BUILD_TESTS */
01248 
01249 #ifdef DBUS_BUILD_TESTS
01250 static dbus_bool_t
01251 ascii_isdigit (char c)
01252 {
01253   return c >= '0' && c <= '9';
01254 }
01255 #endif /* DBUS_BUILD_TESTS */
01256 
01257 #ifdef DBUS_BUILD_TESTS
01258 static dbus_bool_t
01259 ascii_isxdigit (char c)
01260 {
01261   return (ascii_isdigit (c) ||
01262           (c >= 'a' && c <= 'f') ||
01263           (c >= 'A' && c <= 'F'));
01264 }
01265 #endif /* DBUS_BUILD_TESTS */
01266 
01267 #ifdef DBUS_BUILD_TESTS
01268 /* Calls strtod in a locale-independent fashion, by looking at
01269  * the locale data and patching the decimal comma to a point.
01270  *
01271  * Relicensed from glib.
01272  */
01273 static double
01274 ascii_strtod (const char *nptr,
01275               char      **endptr)
01276 {
01277   char *fail_pos;
01278   double val;
01279   struct lconv *locale_data;
01280   const char *decimal_point;
01281   int decimal_point_len;
01282   const char *p, *decimal_point_pos;
01283   const char *end = NULL; /* Silence gcc */
01284 
01285   fail_pos = NULL;
01286 
01287   locale_data = localeconv ();
01288   decimal_point = locale_data->decimal_point;
01289   decimal_point_len = strlen (decimal_point);
01290 
01291   _dbus_assert (decimal_point_len != 0);
01292   
01293   decimal_point_pos = NULL;
01294   if (decimal_point[0] != '.' ||
01295       decimal_point[1] != 0)
01296     {
01297       p = nptr;
01298       /* Skip leading space */
01299       while (ascii_isspace (*p))
01300         p++;
01301       
01302       /* Skip leading optional sign */
01303       if (*p == '+' || *p == '-')
01304         p++;
01305       
01306       if (p[0] == '0' &&
01307           (p[1] == 'x' || p[1] == 'X'))
01308         {
01309           p += 2;
01310           /* HEX - find the (optional) decimal point */
01311           
01312           while (ascii_isxdigit (*p))
01313             p++;
01314           
01315           if (*p == '.')
01316             {
01317               decimal_point_pos = p++;
01318               
01319               while (ascii_isxdigit (*p))
01320                 p++;
01321               
01322               if (*p == 'p' || *p == 'P')
01323                 p++;
01324               if (*p == '+' || *p == '-')
01325                 p++;
01326               while (ascii_isdigit (*p))
01327                 p++;
01328               end = p;
01329             }
01330         }
01331       else
01332         {
01333           while (ascii_isdigit (*p))
01334             p++;
01335           
01336           if (*p == '.')
01337             {
01338               decimal_point_pos = p++;
01339               
01340               while (ascii_isdigit (*p))
01341                 p++;
01342               
01343               if (*p == 'e' || *p == 'E')
01344                 p++;
01345               if (*p == '+' || *p == '-')
01346                 p++;
01347               while (ascii_isdigit (*p))
01348                 p++;
01349               end = p;
01350             }
01351         }
01352       /* For the other cases, we need not convert the decimal point */
01353     }
01354 
01355   /* Set errno to zero, so that we can distinguish zero results
01356      and underflows */
01357   errno = 0;
01358   
01359   if (decimal_point_pos)
01360     {
01361       char *copy, *c;
01362 
01363       /* We need to convert the '.' to the locale specific decimal point */
01364       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01365       
01366       c = copy;
01367       memcpy (c, nptr, decimal_point_pos - nptr);
01368       c += decimal_point_pos - nptr;
01369       memcpy (c, decimal_point, decimal_point_len);
01370       c += decimal_point_len;
01371       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01372       c += end - (decimal_point_pos + 1);
01373       *c = 0;
01374 
01375       val = strtod (copy, &fail_pos);
01376 
01377       if (fail_pos)
01378         {
01379           if (fail_pos > decimal_point_pos)
01380             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01381           else
01382             fail_pos = (char *)nptr + (fail_pos - copy);
01383         }
01384       
01385       dbus_free (copy);
01386           
01387     }
01388   else
01389     val = strtod (nptr, &fail_pos);
01390 
01391   if (endptr)
01392     *endptr = fail_pos;
01393   
01394   return val;
01395 }
01396 #endif /* DBUS_BUILD_TESTS */
01397 
01398 #ifdef DBUS_BUILD_TESTS
01399 
01411 dbus_bool_t
01412 _dbus_string_parse_double (const DBusString *str,
01413                            int               start,
01414                            double           *value_return,
01415                            int              *end_return)
01416 {
01417   double v;
01418   const char *p;
01419   char *end;
01420 
01421   p = _dbus_string_get_const_data_len (str, start,
01422                                        _dbus_string_get_length (str) - start);
01423 
01424   end = NULL;
01425   errno = 0;
01426   v = ascii_strtod (p, &end);
01427   if (end == NULL || end == p || errno != 0)
01428     return FALSE;
01429 
01430   if (value_return)
01431     *value_return = v;
01432   if (end_return)
01433     *end_return = start + (end - p);
01434 
01435   return TRUE;
01436 }
01437 #endif /* DBUS_BUILD_TESTS */
01438  /* DBusString group */
01440 
01445 static dbus_bool_t
01446 fill_user_info_from_passwd (struct passwd *p,
01447                             DBusUserInfo  *info,
01448                             DBusError     *error)
01449 {
01450   _dbus_assert (p->pw_name != NULL);
01451   _dbus_assert (p->pw_dir != NULL);
01452   
01453   info->uid = p->pw_uid;
01454   info->primary_gid = p->pw_gid;
01455   info->username = _dbus_strdup (p->pw_name);
01456   info->homedir = _dbus_strdup (p->pw_dir);
01457   
01458   if (info->username == NULL ||
01459       info->homedir == NULL)
01460     {
01461       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01462       return FALSE;
01463     }
01464 
01465   return TRUE;
01466 }
01467 
01468 static dbus_bool_t
01469 fill_user_info (DBusUserInfo       *info,
01470                 dbus_uid_t          uid,
01471                 const DBusString   *username,
01472                 DBusError          *error)
01473 {
01474   const char *username_c;
01475   
01476   /* exactly one of username/uid provided */
01477   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01478   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01479 
01480   info->uid = DBUS_UID_UNSET;
01481   info->primary_gid = DBUS_GID_UNSET;
01482   info->group_ids = NULL;
01483   info->n_group_ids = 0;
01484   info->username = NULL;
01485   info->homedir = NULL;
01486   
01487   if (username != NULL)
01488     username_c = _dbus_string_get_const_data (username);
01489   else
01490     username_c = NULL;
01491 
01492   /* For now assuming that the getpwnam() and getpwuid() flavors
01493    * are always symmetrical, if not we have to add more configure
01494    * checks
01495    */
01496   
01497 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01498   {
01499     struct passwd *p;
01500     int result;
01501     char buf[1024];
01502     struct passwd p_str;
01503 
01504     p = NULL;
01505 #ifdef HAVE_POSIX_GETPWNAM_R
01506     if (uid != DBUS_UID_UNSET)
01507       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01508                            &p);
01509     else
01510       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01511                            &p);
01512 #else
01513     if (uid != DBUS_UID_UNSET)
01514       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01515     else
01516       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01517     result = 0;
01518 #endif /* !HAVE_POSIX_GETPWNAM_R */
01519     if (result == 0 && p == &p_str)
01520       {
01521         if (!fill_user_info_from_passwd (p, info, error))
01522           return FALSE;
01523       }
01524     else
01525       {
01526         dbus_set_error (error, _dbus_error_from_errno (errno),
01527                         "User \"%s\" unknown or no memory to allocate password entry\n",
01528                         username_c ? username_c : "???");
01529         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01530         return FALSE;
01531       }
01532   }
01533 #else /* ! HAVE_GETPWNAM_R */
01534   {
01535     /* I guess we're screwed on thread safety here */
01536     struct passwd *p;
01537 
01538     if (uid != DBUS_UID_UNSET)
01539       p = getpwuid (uid);
01540     else
01541       p = getpwnam (username_c);
01542 
01543     if (p != NULL)
01544       {
01545         if (!fill_user_info_from_passwd (p, info, error))
01546           return FALSE;
01547       }
01548     else
01549       {
01550         dbus_set_error (error, _dbus_error_from_errno (errno),
01551                         "User \"%s\" unknown or no memory to allocate password entry\n",
01552                         username_c ? username_c : "???");
01553         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01554         return FALSE;
01555       }
01556   }
01557 #endif  /* ! HAVE_GETPWNAM_R */
01558 
01559   /* Fill this in so we can use it to get groups */
01560   username_c = info->username;
01561   
01562 #ifdef HAVE_GETGROUPLIST
01563   {
01564     gid_t *buf;
01565     int buf_count;
01566     int i;
01567     
01568     buf_count = 17;
01569     buf = dbus_new (gid_t, buf_count);
01570     if (buf == NULL)
01571       {
01572         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01573         goto failed;
01574       }
01575     
01576     if (getgrouplist (username_c,
01577                       info->primary_gid,
01578                       buf, &buf_count) < 0)
01579       {
01580         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01581         if (new == NULL)
01582           {
01583             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01584             dbus_free (buf);
01585             goto failed;
01586           }
01587         
01588         buf = new;
01589 
01590         errno = 0;
01591         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01592           {
01593             dbus_set_error (error,
01594                             _dbus_error_from_errno (errno),
01595                             "Failed to get groups for username \"%s\" primary GID "
01596                             DBUS_GID_FORMAT ": %s\n",
01597                             username_c, info->primary_gid,
01598                             _dbus_strerror (errno));
01599             dbus_free (buf);
01600             goto failed;
01601           }
01602       }
01603 
01604     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01605     if (info->group_ids == NULL)
01606       {
01607         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01608         dbus_free (buf);
01609         goto failed;
01610       }
01611     
01612     for (i = 0; i < buf_count; ++i)
01613       info->group_ids[i] = buf[i];
01614 
01615     info->n_group_ids = buf_count;
01616     
01617     dbus_free (buf);
01618   }
01619 #else  /* HAVE_GETGROUPLIST */
01620   {
01621     /* We just get the one group ID */
01622     info->group_ids = dbus_new (dbus_gid_t, 1);
01623     if (info->group_ids == NULL)
01624       {
01625         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01626         goto failed;
01627       }
01628 
01629     info->n_group_ids = 1;
01630 
01631     (info->group_ids)[0] = info->primary_gid;
01632   }
01633 #endif /* HAVE_GETGROUPLIST */
01634 
01635   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01636   
01637   return TRUE;
01638   
01639  failed:
01640   _DBUS_ASSERT_ERROR_IS_SET (error);
01641   return FALSE;
01642 }
01643 
01652 dbus_bool_t
01653 _dbus_user_info_fill (DBusUserInfo     *info,
01654                       const DBusString *username,
01655                       DBusError        *error)
01656 {
01657   return fill_user_info (info, DBUS_UID_UNSET,
01658                          username, error);
01659 }
01660 
01669 dbus_bool_t
01670 _dbus_user_info_fill_uid (DBusUserInfo *info,
01671                           dbus_uid_t    uid,
01672                           DBusError    *error)
01673 {
01674   return fill_user_info (info, uid,
01675                          NULL, error);
01676 }
01677 
01683 void
01684 _dbus_user_info_free (DBusUserInfo *info)
01685 {
01686   dbus_free (info->group_ids);
01687   dbus_free (info->username);
01688   dbus_free (info->homedir);
01689 }
01690 
01697 void
01698 _dbus_credentials_clear (DBusCredentials *credentials)
01699 {
01700   credentials->pid = DBUS_PID_UNSET;
01701   credentials->uid = DBUS_UID_UNSET;
01702   credentials->gid = DBUS_GID_UNSET;
01703 }
01704 
01710 void
01711 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01712 {
01713   /* The POSIX spec certainly doesn't promise this, but
01714    * we need these assertions to fail as soon as we're wrong about
01715    * it so we can do the porting fixups
01716    */
01717   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01718   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01719   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01720   
01721   credentials->pid = getpid ();
01722   credentials->uid = getuid ();
01723   credentials->gid = getgid ();
01724 }
01725 
01734 dbus_bool_t
01735 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01736                          const DBusCredentials *provided_credentials)
01737 {
01738   if (provided_credentials->uid == DBUS_UID_UNSET)
01739     return FALSE;
01740   else if (expected_credentials->uid == DBUS_UID_UNSET)
01741     return FALSE;
01742   else if (provided_credentials->uid == 0)
01743     return TRUE;
01744   else if (provided_credentials->uid == expected_credentials->uid)
01745     return TRUE;
01746   else
01747     return FALSE;
01748 }
01749 
01754 unsigned long
01755 _dbus_getpid (void)
01756 {
01757   return getpid ();
01758 }
01759 
01763 dbus_uid_t
01764 _dbus_getuid (void)
01765 {
01766   return getuid ();
01767 }
01768 
01769 #ifdef DBUS_BUILD_TESTS
01770 
01773 dbus_gid_t
01774 _dbus_getgid (void)
01775 {
01776   return getgid ();
01777 }
01778 #endif
01779 
01780 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01781 
01782 #ifdef DBUS_USE_ATOMIC_INT_486
01783 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01784 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01785 static inline dbus_int32_t
01786 atomic_exchange_and_add (DBusAtomic            *atomic,
01787                          volatile dbus_int32_t  val)
01788 {
01789   register dbus_int32_t result;
01790 
01791   __asm__ __volatile__ ("lock; xaddl %0,%1"
01792                         : "=r" (result), "=m" (atomic->value)
01793                         : "0" (val), "m" (atomic->value));
01794   return result;
01795 }
01796 #endif
01797 
01806 dbus_int32_t
01807 _dbus_atomic_inc (DBusAtomic *atomic)
01808 {
01809 #ifdef DBUS_USE_ATOMIC_INT_486
01810   return atomic_exchange_and_add (atomic, 1);
01811 #else
01812   dbus_int32_t res;
01813   _DBUS_LOCK (atomic);
01814   res = atomic->value;
01815   atomic->value += 1;
01816   _DBUS_UNLOCK (atomic);
01817   return res;
01818 #endif
01819 }
01820 
01829 dbus_int32_t
01830 _dbus_atomic_dec (DBusAtomic *atomic)
01831 {
01832 #ifdef DBUS_USE_ATOMIC_INT_486
01833   return atomic_exchange_and_add (atomic, -1);
01834 #else
01835   dbus_int32_t res;
01836   
01837   _DBUS_LOCK (atomic);
01838   res = atomic->value;
01839   atomic->value -= 1;
01840   _DBUS_UNLOCK (atomic);
01841   return res;
01842 #endif
01843 }
01844 
01853 int
01854 _dbus_poll (DBusPollFD *fds,
01855             int         n_fds,
01856             int         timeout_milliseconds)
01857 {
01858 #ifdef HAVE_POLL
01859   /* This big thing is a constant expression and should get optimized
01860    * out of existence. So it's more robust than a configure check at
01861    * no cost.
01862    */
01863   if (_DBUS_POLLIN == POLLIN &&
01864       _DBUS_POLLPRI == POLLPRI &&
01865       _DBUS_POLLOUT == POLLOUT &&
01866       _DBUS_POLLERR == POLLERR &&
01867       _DBUS_POLLHUP == POLLHUP &&
01868       _DBUS_POLLNVAL == POLLNVAL &&
01869       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01870       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01871       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01872       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01873       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01874       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01875       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01876     {
01877       return poll ((struct pollfd*) fds,
01878                    n_fds, 
01879                    timeout_milliseconds);
01880     }
01881   else
01882     {
01883       /* We have to convert the DBusPollFD to an array of
01884        * struct pollfd, poll, and convert back.
01885        */
01886       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01887       return -1;
01888     }
01889 #else /* ! HAVE_POLL */
01890 
01891   fd_set read_set, write_set, err_set;
01892   int max_fd = 0;
01893   int i;
01894   struct timeval tv;
01895   int ready;
01896   
01897   FD_ZERO (&read_set);
01898   FD_ZERO (&write_set);
01899   FD_ZERO (&err_set);
01900 
01901   for (i = 0; i < n_fds; i++)
01902     {
01903       DBusPollFD *fdp = &fds[i];
01904 
01905       if (fdp->events & _DBUS_POLLIN)
01906         FD_SET (fdp->fd, &read_set);
01907 
01908       if (fdp->events & _DBUS_POLLOUT)
01909         FD_SET (fdp->fd, &write_set);
01910 
01911       FD_SET (fdp->fd, &err_set);
01912 
01913       max_fd = MAX (max_fd, fdp->fd);
01914     }
01915     
01916   tv.tv_sec = timeout_milliseconds / 1000;
01917   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01918 
01919   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01920                   timeout_milliseconds < 0 ? NULL : &tv);
01921 
01922   if (ready > 0)
01923     {
01924       for (i = 0; i < n_fds; i++)
01925         {
01926           DBusPollFD *fdp = &fds[i];
01927 
01928           fdp->revents = 0;
01929 
01930           if (FD_ISSET (fdp->fd, &read_set))
01931             fdp->revents |= _DBUS_POLLIN;
01932 
01933           if (FD_ISSET (fdp->fd, &write_set))
01934             fdp->revents |= _DBUS_POLLOUT;
01935 
01936           if (FD_ISSET (fdp->fd, &err_set))
01937             fdp->revents |= _DBUS_POLLERR;
01938         }
01939     }
01940 
01941   return ready;
01942 #endif
01943 }
01944 
01946 #define NANOSECONDS_PER_SECOND       1000000000
01947 
01948 #define MICROSECONDS_PER_SECOND      1000000
01949 
01950 #define MILLISECONDS_PER_SECOND      1000
01951 
01952 #define NANOSECONDS_PER_MILLISECOND  1000000
01953 
01954 #define MICROSECONDS_PER_MILLISECOND 1000
01955 
01960 void
01961 _dbus_sleep_milliseconds (int milliseconds)
01962 {
01963 #ifdef HAVE_NANOSLEEP
01964   struct timespec req;
01965   struct timespec rem;
01966 
01967   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
01968   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
01969   rem.tv_sec = 0;
01970   rem.tv_nsec = 0;
01971 
01972   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
01973     req = rem;
01974 #elif defined (HAVE_USLEEP)
01975   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
01976 #else /* ! HAVE_USLEEP */
01977   sleep (MAX (milliseconds / 1000, 1));
01978 #endif
01979 }
01980 
01987 void
01988 _dbus_get_current_time (long *tv_sec,
01989                         long *tv_usec)
01990 {
01991   struct timeval t;
01992 
01993   gettimeofday (&t, NULL);
01994 
01995   if (tv_sec)
01996     *tv_sec = t.tv_sec;
01997   if (tv_usec)
01998     *tv_usec = t.tv_usec;
01999 }
02000 
02011 dbus_bool_t
02012 _dbus_file_get_contents (DBusString       *str,
02013                          const DBusString *filename,
02014                          DBusError        *error)
02015 {
02016   int fd;
02017   struct stat sb;
02018   int orig_len;
02019   int total;
02020   const char *filename_c;
02021 
02022   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02023   
02024   filename_c = _dbus_string_get_const_data (filename);
02025   
02026   /* O_BINARY useful on Cygwin */
02027   fd = open (filename_c, O_RDONLY | O_BINARY);
02028   if (fd < 0)
02029     {
02030       dbus_set_error (error, _dbus_error_from_errno (errno),
02031                       "Failed to open \"%s\": %s",
02032                       filename_c,
02033                       _dbus_strerror (errno));
02034       return FALSE;
02035     }
02036 
02037   if (fstat (fd, &sb) < 0)
02038     {
02039       dbus_set_error (error, _dbus_error_from_errno (errno),
02040                       "Failed to stat \"%s\": %s",
02041                       filename_c,
02042                       _dbus_strerror (errno));
02043 
02044       _dbus_verbose ("fstat() failed: %s",
02045                      _dbus_strerror (errno));
02046       
02047       close (fd);
02048       
02049       return FALSE;
02050     }
02051 
02052   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02053     {
02054       dbus_set_error (error, DBUS_ERROR_FAILED,
02055                       "File size %lu of \"%s\" is too large.",
02056                       (unsigned long) sb.st_size, filename_c);
02057       close (fd);
02058       return FALSE;
02059     }
02060   
02061   total = 0;
02062   orig_len = _dbus_string_get_length (str);
02063   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02064     {
02065       int bytes_read;
02066 
02067       while (total < (int) sb.st_size)
02068         {
02069           bytes_read = _dbus_read (fd, str,
02070                                    sb.st_size - total);
02071           if (bytes_read <= 0)
02072             {
02073               dbus_set_error (error, _dbus_error_from_errno (errno),
02074                               "Error reading \"%s\": %s",
02075                               filename_c,
02076                               _dbus_strerror (errno));
02077 
02078               _dbus_verbose ("read() failed: %s",
02079                              _dbus_strerror (errno));
02080               
02081               close (fd);
02082               _dbus_string_set_length (str, orig_len);
02083               return FALSE;
02084             }
02085           else
02086             total += bytes_read;
02087         }
02088 
02089       close (fd);
02090       return TRUE;
02091     }
02092   else if (sb.st_size != 0)
02093     {
02094       _dbus_verbose ("Can only open regular files at the moment.\n");
02095       dbus_set_error (error, DBUS_ERROR_FAILED,
02096                       "\"%s\" is not a regular file",
02097                       filename_c);
02098       close (fd);
02099       return FALSE;
02100     }
02101   else
02102     {
02103       close (fd);
02104       return TRUE;
02105     }
02106 }
02107 
02117 dbus_bool_t
02118 _dbus_string_save_to_file (const DBusString *str,
02119                            const DBusString *filename,
02120                            DBusError        *error)
02121 {
02122   int fd;
02123   int bytes_to_write;
02124   const char *filename_c;
02125   DBusString tmp_filename;
02126   const char *tmp_filename_c;
02127   int total;
02128   dbus_bool_t need_unlink;
02129   dbus_bool_t retval;
02130 
02131   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02132   
02133   fd = -1;
02134   retval = FALSE;
02135   need_unlink = FALSE;
02136   
02137   if (!_dbus_string_init (&tmp_filename))
02138     {
02139       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02140       return FALSE;
02141     }
02142 
02143   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02144     {
02145       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02146       _dbus_string_free (&tmp_filename);
02147       return FALSE;
02148     }
02149   
02150   if (!_dbus_string_append (&tmp_filename, "."))
02151     {
02152       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02153       _dbus_string_free (&tmp_filename);
02154       return FALSE;
02155     }
02156 
02157 #define N_TMP_FILENAME_RANDOM_BYTES 8
02158   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02159     {
02160       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02161       _dbus_string_free (&tmp_filename);
02162       return FALSE;
02163     }
02164     
02165   filename_c = _dbus_string_get_const_data (filename);
02166   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02167 
02168   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02169              0600);
02170   if (fd < 0)
02171     {
02172       dbus_set_error (error, _dbus_error_from_errno (errno),
02173                       "Could not create %s: %s", tmp_filename_c,
02174                       _dbus_strerror (errno));
02175       goto out;
02176     }
02177 
02178   need_unlink = TRUE;
02179   
02180   total = 0;
02181   bytes_to_write = _dbus_string_get_length (str);
02182 
02183   while (total < bytes_to_write)
02184     {
02185       int bytes_written;
02186 
02187       bytes_written = _dbus_write (fd, str, total,
02188                                    bytes_to_write - total);
02189 
02190       if (bytes_written <= 0)
02191         {
02192           dbus_set_error (error, _dbus_error_from_errno (errno),
02193                           "Could not write to %s: %s", tmp_filename_c,
02194                           _dbus_strerror (errno));
02195           
02196           goto out;
02197         }
02198 
02199       total += bytes_written;
02200     }
02201 
02202   if (close (fd) < 0)
02203     {
02204       dbus_set_error (error, _dbus_error_from_errno (errno),
02205                       "Could not close file %s: %s",
02206                       tmp_filename_c, _dbus_strerror (errno));
02207 
02208       goto out;
02209     }
02210 
02211   fd = -1;
02212   
02213   if (rename (tmp_filename_c, filename_c) < 0)
02214     {
02215       dbus_set_error (error, _dbus_error_from_errno (errno),
02216                       "Could not rename %s to %s: %s",
02217                       tmp_filename_c, filename_c,
02218                       _dbus_strerror (errno));
02219 
02220       goto out;
02221     }
02222 
02223   need_unlink = FALSE;
02224   
02225   retval = TRUE;
02226   
02227  out:
02228   /* close first, then unlink, to prevent ".nfs34234235" garbage
02229    * files
02230    */
02231 
02232   if (fd >= 0)
02233     close (fd);
02234         
02235   if (need_unlink && unlink (tmp_filename_c) < 0)
02236     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02237                    tmp_filename_c, _dbus_strerror (errno));
02238 
02239   _dbus_string_free (&tmp_filename);
02240 
02241   if (!retval)
02242     _DBUS_ASSERT_ERROR_IS_SET (error);
02243   
02244   return retval;
02245 }
02246 
02253 dbus_bool_t
02254 _dbus_create_file_exclusively (const DBusString *filename,
02255                                DBusError        *error)
02256 {
02257   int fd;
02258   const char *filename_c;
02259 
02260   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02261   
02262   filename_c = _dbus_string_get_const_data (filename);
02263   
02264   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02265              0600);
02266   if (fd < 0)
02267     {
02268       dbus_set_error (error,
02269                       DBUS_ERROR_FAILED,
02270                       "Could not create file %s: %s\n",
02271                       filename_c,
02272                       _dbus_strerror (errno));
02273       return FALSE;
02274     }
02275 
02276   if (close (fd) < 0)
02277     {
02278       dbus_set_error (error,
02279                       DBUS_ERROR_FAILED,
02280                       "Could not close file %s: %s\n",
02281                       filename_c,
02282                       _dbus_strerror (errno));
02283       return FALSE;
02284     }
02285   
02286   return TRUE;
02287 }
02288 
02297 dbus_bool_t
02298 _dbus_delete_file (const DBusString *filename,
02299                    DBusError        *error)
02300 {
02301   const char *filename_c;
02302 
02303   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02304   
02305   filename_c = _dbus_string_get_const_data (filename);
02306 
02307   if (unlink (filename_c) < 0)
02308     {
02309       dbus_set_error (error, DBUS_ERROR_FAILED,
02310                       "Failed to delete file %s: %s\n",
02311                       filename_c, _dbus_strerror (errno));
02312       return FALSE;
02313     }
02314   else
02315     return TRUE;
02316 }
02317 
02326 dbus_bool_t
02327 _dbus_create_directory (const DBusString *filename,
02328                         DBusError        *error)
02329 {
02330   const char *filename_c;
02331 
02332   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02333   
02334   filename_c = _dbus_string_get_const_data (filename);
02335 
02336   if (mkdir (filename_c, 0700) < 0)
02337     {
02338       if (errno == EEXIST)
02339         return TRUE;
02340       
02341       dbus_set_error (error, DBUS_ERROR_FAILED,
02342                       "Failed to create directory %s: %s\n",
02343                       filename_c, _dbus_strerror (errno));
02344       return FALSE;
02345     }
02346   else
02347     return TRUE;
02348 }
02349 
02360 dbus_bool_t
02361 _dbus_concat_dir_and_file (DBusString       *dir,
02362                            const DBusString *next_component)
02363 {
02364   dbus_bool_t dir_ends_in_slash;
02365   dbus_bool_t file_starts_with_slash;
02366 
02367   if (_dbus_string_get_length (dir) == 0 ||
02368       _dbus_string_get_length (next_component) == 0)
02369     return TRUE;
02370   
02371   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02372                                                     _dbus_string_get_length (dir) - 1);
02373 
02374   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02375 
02376   if (dir_ends_in_slash && file_starts_with_slash)
02377     {
02378       _dbus_string_shorten (dir, 1);
02379     }
02380   else if (!(dir_ends_in_slash || file_starts_with_slash))
02381     {
02382       if (!_dbus_string_append_byte (dir, '/'))
02383         return FALSE;
02384     }
02385 
02386   return _dbus_string_copy (next_component, 0, dir,
02387                             _dbus_string_get_length (dir));
02388 }
02389 
02390 static void
02391 pseudorandom_generate_random_bytes_buffer (char *buffer,
02392                                            int   n_bytes)
02393 {
02394   unsigned long tv_usec;
02395   int i;
02396   
02397   /* fall back to pseudorandom */
02398   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02399                  n_bytes);
02400   
02401   _dbus_get_current_time (NULL, &tv_usec);
02402   srand (tv_usec);
02403   
02404   i = 0;
02405   while (i < n_bytes)
02406     {
02407       double r;
02408       unsigned int b;
02409           
02410       r = rand ();
02411       b = (r / (double) RAND_MAX) * 255.0;
02412 
02413       buffer[i] = b;
02414 
02415       ++i;
02416     }
02417 }
02418 
02419 static dbus_bool_t
02420 pseudorandom_generate_random_bytes (DBusString *str,
02421                                     int         n_bytes)
02422 {
02423   int old_len;
02424   char *p;
02425   
02426   old_len = _dbus_string_get_length (str);
02427 
02428   if (!_dbus_string_lengthen (str, n_bytes))
02429     return FALSE;
02430 
02431   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02432 
02433   pseudorandom_generate_random_bytes_buffer (p, n_bytes);
02434 
02435   return TRUE;
02436 }
02437 
02444 void
02445 _dbus_generate_random_bytes_buffer (char *buffer,
02446                                     int   n_bytes)
02447 {
02448   DBusString str;
02449 
02450   if (!_dbus_string_init (&str))
02451     {
02452       pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02453       return;
02454     }
02455 
02456   if (!_dbus_generate_random_bytes (&str, n_bytes))
02457     {
02458       _dbus_string_free (&str);
02459       pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02460       return;
02461     }
02462 
02463   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
02464 
02465   _dbus_string_free (&str);
02466 }
02467 
02476 dbus_bool_t
02477 _dbus_generate_random_bytes (DBusString *str,
02478                              int         n_bytes)
02479 {
02480   int old_len;
02481   int fd;
02482 
02483   /* FALSE return means "no memory", if it could
02484    * mean something else then we'd need to return
02485    * a DBusError. So we always fall back to pseudorandom
02486    * if the I/O fails.
02487    */
02488   
02489   old_len = _dbus_string_get_length (str);
02490   fd = -1;
02491 
02492   /* note, urandom on linux will fall back to pseudorandom */
02493   fd = open ("/dev/urandom", O_RDONLY);
02494   if (fd < 0)
02495     return pseudorandom_generate_random_bytes (str, n_bytes);
02496 
02497   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02498     {
02499       close (fd);
02500       _dbus_string_set_length (str, old_len);
02501       return pseudorandom_generate_random_bytes (str, n_bytes);
02502     }
02503 
02504   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02505                  n_bytes);
02506   
02507   close (fd);
02508   
02509   return TRUE;
02510 }
02511 
02520 dbus_bool_t
02521 _dbus_generate_random_ascii (DBusString *str,
02522                              int         n_bytes)
02523 {
02524   static const char letters[] =
02525     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02526   int i;
02527   int len;
02528   
02529   if (!_dbus_generate_random_bytes (str, n_bytes))
02530     return FALSE;
02531   
02532   len = _dbus_string_get_length (str);
02533   i = len - n_bytes;
02534   while (i < len)
02535     {
02536       _dbus_string_set_byte (str, i,
02537                              letters[_dbus_string_get_byte (str, i) %
02538                                      (sizeof (letters) - 1)]);
02539 
02540       ++i;
02541     }
02542 
02543   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02544                                              n_bytes));
02545 
02546   return TRUE;
02547 }
02548 
02556 const char*
02557 _dbus_strerror (int error_number)
02558 {
02559   const char *msg;
02560   
02561   msg = strerror (error_number);
02562   if (msg == NULL)
02563     msg = "unknown";
02564 
02565   return msg;
02566 }
02567 
02571 void
02572 _dbus_disable_sigpipe (void)
02573 {
02574   signal (SIGPIPE, SIG_IGN);
02575 }
02576 
02584 void
02585 _dbus_fd_set_close_on_exec (int fd)
02586 {
02587   int val;
02588   
02589   val = fcntl (fd, F_GETFD, 0);
02590   
02591   if (val < 0)
02592     return;
02593 
02594   val |= FD_CLOEXEC;
02595   
02596   fcntl (fd, F_SETFD, val);
02597 }
02598 
02608 const char*
02609 _dbus_error_from_errno (int error_number)
02610 {
02611   switch (error_number)
02612     {
02613     case 0:
02614       return DBUS_ERROR_FAILED;
02615       
02616 #ifdef EPROTONOSUPPORT
02617     case EPROTONOSUPPORT:
02618       return DBUS_ERROR_NOT_SUPPORTED;
02619 #endif
02620 #ifdef EAFNOSUPPORT
02621     case EAFNOSUPPORT:
02622       return DBUS_ERROR_NOT_SUPPORTED;
02623 #endif
02624 #ifdef ENFILE
02625     case ENFILE:
02626       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02627 #endif
02628 #ifdef EMFILE
02629     case EMFILE:
02630       return DBUS_ERROR_LIMITS_EXCEEDED;
02631 #endif
02632 #ifdef EACCES
02633     case EACCES:
02634       return DBUS_ERROR_ACCESS_DENIED;
02635 #endif
02636 #ifdef EPERM
02637     case EPERM:
02638       return DBUS_ERROR_ACCESS_DENIED;
02639 #endif
02640 #ifdef ENOBUFS
02641     case ENOBUFS:
02642       return DBUS_ERROR_NO_MEMORY;
02643 #endif
02644 #ifdef ENOMEM
02645     case ENOMEM:
02646       return DBUS_ERROR_NO_MEMORY;
02647 #endif
02648 #ifdef EINVAL
02649     case EINVAL:
02650       return DBUS_ERROR_FAILED;
02651 #endif
02652 #ifdef EBADF
02653     case EBADF:
02654       return DBUS_ERROR_FAILED;
02655 #endif
02656 #ifdef EFAULT
02657     case EFAULT:
02658       return DBUS_ERROR_FAILED;
02659 #endif
02660 #ifdef ENOTSOCK
02661     case ENOTSOCK:
02662       return DBUS_ERROR_FAILED;
02663 #endif
02664 #ifdef EISCONN
02665     case EISCONN:
02666       return DBUS_ERROR_FAILED;
02667 #endif
02668 #ifdef ECONNREFUSED
02669     case ECONNREFUSED:
02670       return DBUS_ERROR_NO_SERVER;
02671 #endif
02672 #ifdef ETIMEDOUT
02673     case ETIMEDOUT:
02674       return DBUS_ERROR_TIMEOUT;
02675 #endif
02676 #ifdef ENETUNREACH
02677     case ENETUNREACH:
02678       return DBUS_ERROR_NO_NETWORK;
02679 #endif
02680 #ifdef EADDRINUSE
02681     case EADDRINUSE:
02682       return DBUS_ERROR_ADDRESS_IN_USE;
02683 #endif
02684 #ifdef EEXIST
02685     case EEXIST:
02686       return DBUS_ERROR_FILE_NOT_FOUND;
02687 #endif
02688 #ifdef ENOENT
02689     case ENOENT:
02690       return DBUS_ERROR_FILE_NOT_FOUND;
02691 #endif
02692     }
02693 
02694   return DBUS_ERROR_FAILED;
02695 }
02696 
02702 void
02703 _dbus_exit (int code)
02704 {
02705   _exit (code);
02706 }
02707 
02715 dbus_bool_t
02716 _dbus_close (int        fd,
02717              DBusError *error)
02718 {
02719   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02720   
02721  again:
02722   if (close (fd) < 0)
02723     {
02724       if (errno == EINTR)
02725         goto again;
02726 
02727       dbus_set_error (error, _dbus_error_from_errno (errno),
02728                       "Could not close fd %d", fd);
02729       return FALSE;
02730     }
02731 
02732   return TRUE;
02733 }
02734 
02742 dbus_bool_t
02743 _dbus_set_fd_nonblocking (int             fd,
02744                           DBusError      *error)
02745 {
02746   int val;
02747 
02748   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02749   
02750   val = fcntl (fd, F_GETFL, 0);
02751   if (val < 0)
02752     {
02753       dbus_set_error (error, _dbus_error_from_errno (errno),
02754                       "Failed to get flags from file descriptor %d: %s",
02755                       fd, _dbus_strerror (errno));
02756       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02757                      _dbus_strerror (errno));
02758       return FALSE;
02759     }
02760 
02761   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02762     {
02763       dbus_set_error (error, _dbus_error_from_errno (errno),
02764                       "Failed to set nonblocking flag of file descriptor %d: %s",
02765                       fd, _dbus_strerror (errno));
02766       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02767                      fd, _dbus_strerror (errno));
02768 
02769       return FALSE;
02770     }
02771 
02772   return TRUE;
02773 }
02774 
02775 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
02776 
02781 void
02782 _dbus_print_backtrace (void)
02783 {
02784 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
02785   void *bt[500];
02786   int bt_size;
02787   int i;
02788   char **syms;
02789   
02790   bt_size = backtrace (bt, 500);
02791 
02792   syms = backtrace_symbols (bt, bt_size);
02793   
02794   i = 0;
02795   while (i < bt_size)
02796     {
02797       _dbus_verbose ("  %s\n", syms[i]);
02798       ++i;
02799     }
02800 
02801   free (syms);
02802 #else
02803   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
02804 #endif
02805 }
02806 #endif /* asserts or tests enabled */
02807 
02808 
02816 dbus_bool_t
02817 _dbus_parse_uid (const DBusString      *uid_str,
02818                  dbus_uid_t            *uid)
02819 {
02820   int end;
02821   long val;
02822   
02823   if (_dbus_string_get_length (uid_str) == 0)
02824     {
02825       _dbus_verbose ("UID string was zero length\n");
02826       return FALSE;
02827     }
02828 
02829   val = -1;
02830   end = 0;
02831   if (!_dbus_string_parse_int (uid_str, 0, &val,
02832                                &end))
02833     {
02834       _dbus_verbose ("could not parse string as a UID\n");
02835       return FALSE;
02836     }
02837   
02838   if (end != _dbus_string_get_length (uid_str))
02839     {
02840       _dbus_verbose ("string contained trailing stuff after UID\n");
02841       return FALSE;
02842     }
02843 
02844   *uid = val;
02845 
02846   return TRUE;
02847 }
02848 
02864 dbus_bool_t
02865 _dbus_full_duplex_pipe (int        *fd1,
02866                         int        *fd2,
02867                         dbus_bool_t blocking,
02868                         DBusError  *error)
02869 {
02870 #ifdef HAVE_SOCKETPAIR
02871   int fds[2];
02872 
02873   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02874   
02875   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02876     {
02877       dbus_set_error (error, _dbus_error_from_errno (errno),
02878                       "Could not create full-duplex pipe");
02879       return FALSE;
02880     }
02881 
02882   if (!blocking &&
02883       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02884        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02885     {
02886       dbus_set_error (error, _dbus_error_from_errno (errno),
02887                       "Could not set full-duplex pipe nonblocking");
02888       
02889       close (fds[0]);
02890       close (fds[1]);
02891       
02892       return FALSE;
02893     }
02894   
02895   *fd1 = fds[0];
02896   *fd2 = fds[1];
02897 
02898   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02899                  *fd1, *fd2);
02900   
02901   return TRUE;  
02902 #else
02903   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02904   dbus_set_error (error, DBUS_ERROR_FAILED,
02905                   "_dbus_full_duplex_pipe() not implemented on this OS");
02906   return FALSE;
02907 #endif
02908 }
02909 
02912 /* tests in dbus-sysdeps-util.c */

Generated on Fri Sep 30 19:45:36 2005 for D-BUS by  doxygen 1.4.4