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

dbus-sysdeps.c

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

Generated on Sat Sep 25 19:17:13 2004 for D-BUS by  doxygen 1.3.8-20040913