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-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       close (fd);
00626       return -1;
00627     }
00628   
00629   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00630 
00631   _DBUS_ZERO (addr);
00632   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00633   addr.sin_family = AF_INET;
00634   addr.sin_port = htons (port);
00635   
00636   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00637     {      
00638       dbus_set_error (error,
00639                        _dbus_error_from_errno (errno),
00640                       "Failed to connect to socket %s: %s:%d",
00641                       host, _dbus_strerror (errno), port);
00642 
00643       close (fd);
00644       fd = -1;
00645       
00646       return -1;
00647     }
00648 
00649   if (!_dbus_set_fd_nonblocking (fd, error))
00650     {
00651       close (fd);
00652       fd = -1;
00653 
00654       return -1;
00655     }
00656 
00657   return fd;
00658 }
00659 
00670 int
00671 _dbus_listen_tcp_socket (const char     *host,
00672                          dbus_uint32_t   port,
00673                          DBusError      *error)
00674 {
00675   int listen_fd;
00676   struct sockaddr_in addr;
00677   struct hostent *he;
00678   struct in_addr *haddr;
00679 
00680   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00681   
00682   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00683   
00684   if (listen_fd < 0)
00685     {
00686       dbus_set_error (error, _dbus_error_from_errno (errno),
00687                       "Failed to create socket \"%s:%d\": %s",
00688                       host, port, _dbus_strerror (errno));
00689       return -1;
00690     }
00691 
00692   he = gethostbyname (host);
00693   if (he == NULL) 
00694     {
00695       dbus_set_error (error,
00696                       _dbus_error_from_errno (errno),
00697                       "Failed to lookup hostname: %s",
00698                       host);
00699       close (listen_fd);
00700       return -1;
00701     }
00702   
00703   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00704 
00705   _DBUS_ZERO (addr);
00706   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00707   addr.sin_family = AF_INET;
00708   addr.sin_port = htons (port);
00709 
00710   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00711     {
00712       dbus_set_error (error, _dbus_error_from_errno (errno),
00713                       "Failed to bind socket \"%s:%d\": %s",
00714                       host, port, _dbus_strerror (errno));
00715       close (listen_fd);
00716       return -1;
00717     }
00718 
00719   if (listen (listen_fd, 30 /* backlog */) < 0)
00720     {
00721       dbus_set_error (error, _dbus_error_from_errno (errno),  
00722                       "Failed to listen on socket \"%s:%d\": %s",
00723                       host, port, _dbus_strerror (errno));
00724       close (listen_fd);
00725       return -1;
00726     }
00727 
00728   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00729     {
00730       close (listen_fd);
00731       return -1;
00732     }
00733   
00734   return listen_fd;
00735 }
00736 
00737 static dbus_bool_t
00738 write_credentials_byte (int             server_fd,
00739                         DBusError      *error)
00740 {
00741   int bytes_written;
00742   char buf[1] = { '\0' };
00743 
00744   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00745   
00746  again:
00747 
00748   bytes_written = write (server_fd, buf, 1);
00749 
00750   if (bytes_written < 0 && errno == EINTR)
00751     goto again;
00752 
00753   if (bytes_written < 0)
00754     {
00755       dbus_set_error (error, _dbus_error_from_errno (errno),
00756                       "Failed to write credentials byte: %s",
00757                      _dbus_strerror (errno));
00758       return FALSE;
00759     }
00760   else if (bytes_written == 0)
00761     {
00762       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00763                       "wrote zero bytes writing credentials byte");
00764       return FALSE;
00765     }
00766   else
00767     {
00768       _dbus_assert (bytes_written == 1);
00769       _dbus_verbose ("wrote credentials byte\n");
00770       return TRUE;
00771     }
00772 }
00773 
00792 dbus_bool_t
00793 _dbus_read_credentials_unix_socket  (int              client_fd,
00794                                      DBusCredentials *credentials,
00795                                      DBusError       *error)
00796 {
00797   struct msghdr msg;
00798   struct iovec iov;
00799   char buf;
00800 
00801 #ifdef HAVE_CMSGCRED 
00802   char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
00803   struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
00804 #endif
00805 
00806   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00807   
00808   /* The POSIX spec certainly doesn't promise this, but
00809    * we need these assertions to fail as soon as we're wrong about
00810    * it so we can do the porting fixups
00811    */
00812   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00813   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00814   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00815 
00816   _dbus_credentials_clear (credentials);
00817 
00818 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00819   /* Set the socket to receive credentials on the next message */
00820   {
00821     int on = 1;
00822     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00823       {
00824         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00825         return FALSE;
00826       }
00827   }
00828 #endif
00829 
00830   iov.iov_base = &buf;
00831   iov.iov_len = 1;
00832 
00833   memset (&msg, 0, sizeof (msg));
00834   msg.msg_iov = &iov;
00835   msg.msg_iovlen = 1;
00836 
00837 #ifdef HAVE_CMSGCRED
00838   memset (cmsgmem, 0, sizeof (cmsgmem));
00839   msg.msg_control = cmsgmem;
00840   msg.msg_controllen = sizeof (cmsgmem);
00841 #endif
00842 
00843  again:
00844   if (recvmsg (client_fd, &msg, 0) < 0)
00845     {
00846       if (errno == EINTR)
00847         goto again;
00848 
00849       dbus_set_error (error, _dbus_error_from_errno (errno),
00850                       "Failed to read credentials byte: %s",
00851                       _dbus_strerror (errno));
00852       return FALSE;
00853     }
00854 
00855   if (buf != '\0')
00856     {
00857       dbus_set_error (error, DBUS_ERROR_FAILED,
00858                       "Credentials byte was not nul");
00859       return FALSE;
00860     }
00861 
00862 #ifdef HAVE_CMSGCRED
00863   if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
00864     {
00865       dbus_set_error (error, DBUS_ERROR_FAILED);
00866       _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
00867       return FALSE;
00868     }
00869 #endif
00870 
00871   _dbus_verbose ("read credentials byte\n");
00872 
00873   {
00874 #ifdef SO_PEERCRED
00875     struct ucred cr;   
00876     int cr_len = sizeof (cr);
00877    
00878     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00879         cr_len == sizeof (cr))
00880       {
00881         credentials->pid = cr.pid;
00882         credentials->uid = cr.uid;
00883         credentials->gid = cr.gid;
00884       }
00885     else
00886       {
00887         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00888                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00889       }
00890 #elif defined(HAVE_CMSGCRED)
00891     struct cmsgcred *cred;
00892 
00893     cred = (struct cmsgcred *) CMSG_DATA (cmsg);
00894 
00895     credentials->pid = cred->cmcred_pid;
00896     credentials->uid = cred->cmcred_euid;
00897     credentials->gid = cred->cmcred_groups[0];
00898 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
00899     _dbus_verbose ("Socket credentials not supported on this OS\n");
00900 #endif
00901   }
00902 
00903   _dbus_verbose ("Credentials:"
00904                  "  pid "DBUS_PID_FORMAT
00905                  "  uid "DBUS_UID_FORMAT
00906                  "  gid "DBUS_GID_FORMAT"\n",
00907                  credentials->pid,
00908                  credentials->uid,
00909                  credentials->gid);
00910     
00911   return TRUE;
00912 }
00913 
00931 dbus_bool_t
00932 _dbus_send_credentials_unix_socket  (int              server_fd,
00933                                      DBusError       *error)
00934 {
00935   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00936   
00937   if (write_credentials_byte (server_fd, error))
00938     return TRUE;
00939   else
00940     return FALSE;
00941 }
00942 
00950 int
00951 _dbus_accept  (int listen_fd)
00952 {
00953   int client_fd;
00954   struct sockaddr addr;
00955   socklen_t addrlen;
00956 
00957   addrlen = sizeof (addr);
00958   
00959  retry:
00960   client_fd = accept (listen_fd, &addr, &addrlen);
00961   
00962   if (client_fd < 0)
00963     {
00964       if (errno == EINTR)
00965         goto retry;
00966     }
00967   
00968   return client_fd;
00969 }
00970 
00985 dbus_bool_t
00986 _dbus_string_append_int (DBusString *str,
00987                          long        value)
00988 {
00989   /* this calculation is from comp.lang.c faq */
00990 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
00991   int orig_len;
00992   int i;
00993   char *buf;
00994   
00995   orig_len = _dbus_string_get_length (str);
00996 
00997   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00998     return FALSE;
00999 
01000   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01001 
01002   snprintf (buf, MAX_LONG_LEN, "%ld", value);
01003 
01004   i = 0;
01005   while (*buf)
01006     {
01007       ++buf;
01008       ++i;
01009     }
01010   
01011   _dbus_string_shorten (str, MAX_LONG_LEN - i);
01012   
01013   return TRUE;
01014 }
01015 
01023 dbus_bool_t
01024 _dbus_string_append_uint (DBusString    *str,
01025                           unsigned long  value)
01026 {
01027   /* this is wrong, but definitely on the high side. */
01028 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01029   int orig_len;
01030   int i;
01031   char *buf;
01032   
01033   orig_len = _dbus_string_get_length (str);
01034 
01035   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01036     return FALSE;
01037 
01038   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01039 
01040   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01041 
01042   i = 0;
01043   while (*buf)
01044     {
01045       ++buf;
01046       ++i;
01047     }
01048   
01049   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01050   
01051   return TRUE;
01052 }
01053 
01061 dbus_bool_t
01062 _dbus_string_append_double (DBusString *str,
01063                             double      value)
01064 {
01065 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
01066   int orig_len;
01067   char *buf;
01068   int i;
01069   
01070   orig_len = _dbus_string_get_length (str);
01071 
01072   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01073     return FALSE;
01074 
01075   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01076 
01077   snprintf (buf, MAX_LONG_LEN, "%g", value);
01078 
01079   i = 0;
01080   while (*buf)
01081     {
01082       ++buf;
01083       ++i;
01084     }
01085   
01086   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01087   
01088   return TRUE;
01089 }
01090 
01103 dbus_bool_t
01104 _dbus_string_parse_int (const DBusString *str,
01105                         int               start,
01106                         long             *value_return,
01107                         int              *end_return)
01108 {
01109   long v;
01110   const char *p;
01111   char *end;
01112 
01113   p = _dbus_string_get_const_data_len (str, start,
01114                                        _dbus_string_get_length (str) - start);
01115 
01116   end = NULL;
01117   errno = 0;
01118   v = strtol (p, &end, 0);
01119   if (end == NULL || end == p || errno != 0)
01120     return FALSE;
01121 
01122   if (value_return)
01123     *value_return = v;
01124   if (end_return)
01125     *end_return = start + (end - p);
01126 
01127   return TRUE;
01128 }
01129 
01130 #ifdef DBUS_BUILD_TESTS
01131 /* Not currently used, so only built when tests are enabled */
01144 dbus_bool_t
01145 _dbus_string_parse_uint (const DBusString *str,
01146                          int               start,
01147                          unsigned long    *value_return,
01148                          int              *end_return)
01149 {
01150   unsigned long v;
01151   const char *p;
01152   char *end;
01153 
01154   p = _dbus_string_get_const_data_len (str, start,
01155                                        _dbus_string_get_length (str) - start);
01156 
01157   end = NULL;
01158   errno = 0;
01159   v = strtoul (p, &end, 0);
01160   if (end == NULL || end == p || errno != 0)
01161     return FALSE;
01162 
01163   if (value_return)
01164     *value_return = v;
01165   if (end_return)
01166     *end_return = start + (end - p);
01167 
01168   return TRUE;
01169 }
01170 #endif /* DBUS_BUILD_TESTS */
01171 
01172 static dbus_bool_t
01173 ascii_isspace (char c)
01174 {
01175   return (c == ' ' ||
01176           c == '\f' ||
01177           c == '\n' ||
01178           c == '\r' ||
01179           c == '\t' ||
01180           c == '\v');
01181 }
01182 
01183 static dbus_bool_t
01184 ascii_isdigit (char c)
01185 {
01186   return c >= '0' && c <= '9';
01187 }
01188 
01189 static dbus_bool_t
01190 ascii_isxdigit (char c)
01191 {
01192   return (ascii_isdigit (c) ||
01193           (c >= 'a' && c <= 'f') ||
01194           (c >= 'A' && c <= 'F'));
01195 }
01196 
01197 
01198 /* Calls strtod in a locale-independent fashion, by looking at
01199  * the locale data and patching the decimal comma to a point.
01200  *
01201  * Relicensed from glib.
01202  */
01203 static double
01204 ascii_strtod (const char *nptr,
01205               char      **endptr)
01206 {
01207   char *fail_pos;
01208   double val;
01209   struct lconv *locale_data;
01210   const char *decimal_point;
01211   int decimal_point_len;
01212   const char *p, *decimal_point_pos;
01213   const char *end = NULL; /* Silence gcc */
01214 
01215   fail_pos = NULL;
01216 
01217   locale_data = localeconv ();
01218   decimal_point = locale_data->decimal_point;
01219   decimal_point_len = strlen (decimal_point);
01220 
01221   _dbus_assert (decimal_point_len != 0);
01222   
01223   decimal_point_pos = NULL;
01224   if (decimal_point[0] != '.' ||
01225       decimal_point[1] != 0)
01226     {
01227       p = nptr;
01228       /* Skip leading space */
01229       while (ascii_isspace (*p))
01230         p++;
01231       
01232       /* Skip leading optional sign */
01233       if (*p == '+' || *p == '-')
01234         p++;
01235       
01236       if (p[0] == '0' &&
01237           (p[1] == 'x' || p[1] == 'X'))
01238         {
01239           p += 2;
01240           /* HEX - find the (optional) decimal point */
01241           
01242           while (ascii_isxdigit (*p))
01243             p++;
01244           
01245           if (*p == '.')
01246             {
01247               decimal_point_pos = p++;
01248               
01249               while (ascii_isxdigit (*p))
01250                 p++;
01251               
01252               if (*p == 'p' || *p == 'P')
01253                 p++;
01254               if (*p == '+' || *p == '-')
01255                 p++;
01256               while (ascii_isdigit (*p))
01257                 p++;
01258               end = p;
01259             }
01260         }
01261       else
01262         {
01263           while (ascii_isdigit (*p))
01264             p++;
01265           
01266           if (*p == '.')
01267             {
01268               decimal_point_pos = p++;
01269               
01270               while (ascii_isdigit (*p))
01271                 p++;
01272               
01273               if (*p == 'e' || *p == 'E')
01274                 p++;
01275               if (*p == '+' || *p == '-')
01276                 p++;
01277               while (ascii_isdigit (*p))
01278                 p++;
01279               end = p;
01280             }
01281         }
01282       /* For the other cases, we need not convert the decimal point */
01283     }
01284 
01285   /* Set errno to zero, so that we can distinguish zero results
01286      and underflows */
01287   errno = 0;
01288   
01289   if (decimal_point_pos)
01290     {
01291       char *copy, *c;
01292 
01293       /* We need to convert the '.' to the locale specific decimal point */
01294       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01295       
01296       c = copy;
01297       memcpy (c, nptr, decimal_point_pos - nptr);
01298       c += decimal_point_pos - nptr;
01299       memcpy (c, decimal_point, decimal_point_len);
01300       c += decimal_point_len;
01301       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01302       c += end - (decimal_point_pos + 1);
01303       *c = 0;
01304 
01305       val = strtod (copy, &fail_pos);
01306 
01307       if (fail_pos)
01308         {
01309           if (fail_pos > decimal_point_pos)
01310             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01311           else
01312             fail_pos = (char *)nptr + (fail_pos - copy);
01313         }
01314       
01315       dbus_free (copy);
01316           
01317     }
01318   else
01319     val = strtod (nptr, &fail_pos);
01320 
01321   if (endptr)
01322     *endptr = fail_pos;
01323   
01324   return val;
01325 }
01326 
01327 
01340 dbus_bool_t
01341 _dbus_string_parse_double (const DBusString *str,
01342                            int               start,
01343                            double           *value_return,
01344                            int              *end_return)
01345 {
01346   double v;
01347   const char *p;
01348   char *end;
01349 
01350   p = _dbus_string_get_const_data_len (str, start,
01351                                        _dbus_string_get_length (str) - start);
01352 
01353   end = NULL;
01354   errno = 0;
01355   v = ascii_strtod (p, &end);
01356   if (end == NULL || end == p || errno != 0)
01357     return FALSE;
01358 
01359   if (value_return)
01360     *value_return = v;
01361   if (end_return)
01362     *end_return = start + (end - p);
01363 
01364   return TRUE;
01365 }
01366  /* DBusString group */
01368 
01373 static dbus_bool_t
01374 fill_user_info_from_passwd (struct passwd *p,
01375                             DBusUserInfo  *info,
01376                             DBusError     *error)
01377 {
01378   _dbus_assert (p->pw_name != NULL);
01379   _dbus_assert (p->pw_dir != NULL);
01380   
01381   info->uid = p->pw_uid;
01382   info->primary_gid = p->pw_gid;
01383   info->username = _dbus_strdup (p->pw_name);
01384   info->homedir = _dbus_strdup (p->pw_dir);
01385   
01386   if (info->username == NULL ||
01387       info->homedir == NULL)
01388     {
01389       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01390       return FALSE;
01391     }
01392 
01393   return TRUE;
01394 }
01395 
01396 static dbus_bool_t
01397 fill_user_info (DBusUserInfo       *info,
01398                 dbus_uid_t          uid,
01399                 const DBusString   *username,
01400                 DBusError          *error)
01401 {
01402   const char *username_c;
01403   
01404   /* exactly one of username/uid provided */
01405   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01406   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01407 
01408   info->uid = DBUS_UID_UNSET;
01409   info->primary_gid = DBUS_GID_UNSET;
01410   info->group_ids = NULL;
01411   info->n_group_ids = 0;
01412   info->username = NULL;
01413   info->homedir = NULL;
01414   
01415   if (username != NULL)
01416     username_c = _dbus_string_get_const_data (username);
01417   else
01418     username_c = NULL;
01419 
01420   /* For now assuming that the getpwnam() and getpwuid() flavors
01421    * are always symmetrical, if not we have to add more configure
01422    * checks
01423    */
01424   
01425 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01426   {
01427     struct passwd *p;
01428     int result;
01429     char buf[1024];
01430     struct passwd p_str;
01431 
01432     p = NULL;
01433 #ifdef HAVE_POSIX_GETPWNAME_R
01434     if (uid >= 0)
01435       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01436                            &p);
01437     else
01438       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01439                            &p);
01440 #else
01441     if (uid != DBUS_UID_UNSET)
01442       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01443     else
01444       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01445     result = 0;
01446 #endif /* !HAVE_POSIX_GETPWNAME_R */
01447     if (result == 0 && p == &p_str)
01448       {
01449         if (!fill_user_info_from_passwd (p, info, error))
01450           return FALSE;
01451       }
01452     else
01453       {
01454         dbus_set_error (error, _dbus_error_from_errno (errno),
01455                         "User \"%s\" unknown or no memory to allocate password entry\n",
01456                         username_c ? username_c : "???");
01457         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01458         return FALSE;
01459       }
01460   }
01461 #else /* ! HAVE_GETPWNAM_R */
01462   {
01463     /* I guess we're screwed on thread safety here */
01464     struct passwd *p;
01465 
01466     if (uid != DBUS_UID_UNSET)
01467       p = getpwuid (uid);
01468     else
01469       p = getpwnam (username_c);
01470 
01471     if (p != NULL)
01472       {
01473         if (!fill_user_info_from_passwd (p, info, error))
01474           return FALSE;
01475       }
01476     else
01477       {
01478         dbus_set_error (error, _dbus_error_from_errno (errno),
01479                         "User \"%s\" unknown or no memory to allocate password entry\n",
01480                         username_c ? username_c : "???");
01481         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01482         return FALSE;
01483       }
01484   }
01485 #endif  /* ! HAVE_GETPWNAM_R */
01486 
01487   /* Fill this in so we can use it to get groups */
01488   username_c = info->username;
01489   
01490 #ifdef HAVE_GETGROUPLIST
01491   {
01492     gid_t *buf;
01493     int buf_count;
01494     int i;
01495     
01496     buf_count = 17;
01497     buf = dbus_new (gid_t, buf_count);
01498     if (buf == NULL)
01499       {
01500         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01501         goto failed;
01502       }
01503     
01504     if (getgrouplist (username_c,
01505                       info->primary_gid,
01506                       buf, &buf_count) < 0)
01507       {
01508         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01509         if (new == NULL)
01510           {
01511             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01512             dbus_free (buf);
01513             goto failed;
01514           }
01515         
01516         buf = new;
01517 
01518         errno = 0;
01519         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01520           {
01521             dbus_set_error (error,
01522                             _dbus_error_from_errno (errno),
01523                             "Failed to get groups for username \"%s\" primary GID "
01524                             DBUS_GID_FORMAT ": %s\n",
01525                             username_c, info->primary_gid,
01526                             _dbus_strerror (errno));
01527             dbus_free (buf);
01528             goto failed;
01529           }
01530       }
01531 
01532     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01533     if (info->group_ids == NULL)
01534       {
01535         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01536         dbus_free (buf);
01537         goto failed;
01538       }
01539     
01540     for (i = 0; i < buf_count; ++i)
01541       info->group_ids[i] = buf[i];
01542 
01543     info->n_group_ids = buf_count;
01544     
01545     dbus_free (buf);
01546   }
01547 #else  /* HAVE_GETGROUPLIST */
01548   {
01549     /* We just get the one group ID */
01550     info->group_ids = dbus_new (dbus_gid_t, 1);
01551     if (info->group_ids == NULL)
01552       {
01553         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01554         goto failed;
01555       }
01556 
01557     info->n_group_ids = 1;
01558 
01559     (info->group_ids)[0] = info->primary_gid;
01560   }
01561 #endif /* HAVE_GETGROUPLIST */
01562 
01563   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01564   
01565   return TRUE;
01566   
01567  failed:
01568   _DBUS_ASSERT_ERROR_IS_SET (error);
01569   return FALSE;
01570 }
01571 
01580 dbus_bool_t
01581 _dbus_user_info_fill (DBusUserInfo     *info,
01582                       const DBusString *username,
01583                       DBusError        *error)
01584 {
01585   return fill_user_info (info, DBUS_UID_UNSET,
01586                          username, error);
01587 }
01588 
01597 dbus_bool_t
01598 _dbus_user_info_fill_uid (DBusUserInfo *info,
01599                           dbus_uid_t    uid,
01600                           DBusError    *error)
01601 {
01602   return fill_user_info (info, uid,
01603                          NULL, error);
01604 }
01605 
01611 void
01612 _dbus_user_info_free (DBusUserInfo *info)
01613 {
01614   dbus_free (info->group_ids);
01615   dbus_free (info->username);
01616   dbus_free (info->homedir);
01617 }
01618 
01619 static dbus_bool_t
01620 fill_user_info_from_group (struct group  *g,
01621                            DBusGroupInfo *info,
01622                            DBusError     *error)
01623 {
01624   _dbus_assert (g->gr_name != NULL);
01625   
01626   info->gid = g->gr_gid;
01627   info->groupname = _dbus_strdup (g->gr_name);
01628 
01629   /* info->members = dbus_strdupv (g->gr_mem) */
01630   
01631   if (info->groupname == NULL)
01632     {
01633       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01634       return FALSE;
01635     }
01636 
01637   return TRUE;
01638 }
01639 
01640 static dbus_bool_t
01641 fill_group_info (DBusGroupInfo    *info,
01642                  dbus_gid_t        gid,
01643                  const DBusString *groupname,
01644                  DBusError        *error)
01645 {
01646   const char *group_c_str;
01647 
01648   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01649   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01650 
01651   if (groupname)
01652     group_c_str = _dbus_string_get_const_data (groupname);
01653   else
01654     group_c_str = NULL;
01655   
01656   /* For now assuming that the getgrnam() and getgrgid() flavors
01657    * always correspond to the pwnam flavors, if not we have
01658    * to add more configure checks.
01659    */
01660   
01661 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01662   {
01663     struct group *g;
01664     int result;
01665     char buf[1024];
01666     struct group g_str;
01667 
01668     g = NULL;
01669 #ifdef HAVE_POSIX_GETPWNAME_R
01670 
01671     if (group_c_str)
01672       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01673                            &g);
01674     else
01675       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01676                            &g);
01677 #else
01678     p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01679     result = 0;
01680 #endif /* !HAVE_POSIX_GETPWNAME_R */
01681     if (result == 0 && g == &g_str)
01682       {
01683         return fill_user_info_from_group (g, info, error);
01684       }
01685     else
01686       {
01687         dbus_set_error (error, _dbus_error_from_errno (errno),
01688                         "Group %s unknown or failed to look it up\n",
01689                         group_c_str ? group_c_str : "???");
01690         return FALSE;
01691       }
01692   }
01693 #else /* ! HAVE_GETPWNAM_R */
01694   {
01695     /* I guess we're screwed on thread safety here */
01696     struct group *g;
01697 
01698     g = getgrnam (group_c_str);
01699 
01700     if (g != NULL)
01701       {
01702         return fill_user_info_from_group (g, info, error);
01703       }
01704     else
01705       {
01706         dbus_set_error (error, _dbus_error_from_errno (errno),
01707                         "Group %s unknown or failed to look it up\n",
01708                         group_c_str ? group_c_str : "???");
01709         return FALSE;
01710       }
01711   }
01712 #endif  /* ! HAVE_GETPWNAM_R */
01713 }
01714 
01724 dbus_bool_t
01725 _dbus_group_info_fill (DBusGroupInfo    *info,
01726                        const DBusString *groupname,
01727                        DBusError        *error)
01728 {
01729   return fill_group_info (info, DBUS_GID_UNSET,
01730                           groupname, error);
01731 
01732 }
01733 
01743 dbus_bool_t
01744 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01745                            dbus_gid_t     gid,
01746                            DBusError     *error)
01747 {
01748   return fill_group_info (info, gid, NULL, error);
01749 }
01750 
01756 void
01757 _dbus_group_info_free (DBusGroupInfo    *info)
01758 {
01759   dbus_free (info->groupname);
01760 }
01761 
01768 void
01769 _dbus_credentials_clear (DBusCredentials *credentials)
01770 {
01771   credentials->pid = DBUS_PID_UNSET;
01772   credentials->uid = DBUS_UID_UNSET;
01773   credentials->gid = DBUS_GID_UNSET;
01774 }
01775 
01781 void
01782 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01783 {
01784   /* The POSIX spec certainly doesn't promise this, but
01785    * we need these assertions to fail as soon as we're wrong about
01786    * it so we can do the porting fixups
01787    */
01788   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01789   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01790   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01791   
01792   credentials->pid = getpid ();
01793   credentials->uid = getuid ();
01794   credentials->gid = getgid ();
01795 }
01796 
01805 dbus_bool_t
01806 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01807                          const DBusCredentials *provided_credentials)
01808 {
01809   if (provided_credentials->uid == DBUS_UID_UNSET)
01810     return FALSE;
01811   else if (expected_credentials->uid == DBUS_UID_UNSET)
01812     return FALSE;
01813   else if (provided_credentials->uid == 0)
01814     return TRUE;
01815   else if (provided_credentials->uid == expected_credentials->uid)
01816     return TRUE;
01817   else
01818     return FALSE;
01819 }
01820 
01825 unsigned long
01826 _dbus_getpid (void)
01827 {
01828   return getpid ();
01829 }
01830 
01834 dbus_uid_t
01835 _dbus_getuid (void)
01836 {
01837   return getuid ();
01838 }
01839 
01843 dbus_gid_t
01844 _dbus_getgid (void)
01845 {
01846   return getgid ();
01847 }
01848 
01849 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01850 
01851 #ifdef DBUS_USE_ATOMIC_INT_486
01852 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01853 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01854 static inline dbus_int32_t
01855 atomic_exchange_and_add (DBusAtomic            *atomic,
01856                          volatile dbus_int32_t  val)
01857 {
01858   register dbus_int32_t result;
01859 
01860   __asm__ __volatile__ ("lock; xaddl %0,%1"
01861                         : "=r" (result), "=m" (atomic->value)
01862                         : "0" (val), "m" (atomic->value));
01863   return result;
01864 }
01865 #endif
01866 
01875 dbus_int32_t
01876 _dbus_atomic_inc (DBusAtomic *atomic)
01877 {
01878 #ifdef DBUS_USE_ATOMIC_INT_486
01879   return atomic_exchange_and_add (atomic, 1);
01880 #else
01881   dbus_int32_t res;
01882   _DBUS_LOCK (atomic);
01883   res = atomic->value;
01884   atomic->value += 1;
01885   _DBUS_UNLOCK (atomic);
01886   return res;
01887 #endif
01888 }
01889 
01898 dbus_int32_t
01899 _dbus_atomic_dec (DBusAtomic *atomic)
01900 {
01901 #ifdef DBUS_USE_ATOMIC_INT_486
01902   return atomic_exchange_and_add (atomic, -1);
01903 #else
01904   dbus_int32_t res;
01905   
01906   _DBUS_LOCK (atomic);
01907   res = atomic->value;
01908   atomic->value -= 1;
01909   _DBUS_UNLOCK (atomic);
01910   return res;
01911 #endif
01912 }
01913 
01922 int
01923 _dbus_poll (DBusPollFD *fds,
01924             int         n_fds,
01925             int         timeout_milliseconds)
01926 {
01927 #ifdef HAVE_POLL
01928   /* This big thing is a constant expression and should get optimized
01929    * out of existence. So it's more robust than a configure check at
01930    * no cost.
01931    */
01932   if (_DBUS_POLLIN == POLLIN &&
01933       _DBUS_POLLPRI == POLLPRI &&
01934       _DBUS_POLLOUT == POLLOUT &&
01935       _DBUS_POLLERR == POLLERR &&
01936       _DBUS_POLLHUP == POLLHUP &&
01937       _DBUS_POLLNVAL == POLLNVAL &&
01938       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01939       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01940       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01941       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01942       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01943       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01944       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01945     {
01946       return poll ((struct pollfd*) fds,
01947                    n_fds, 
01948                    timeout_milliseconds);
01949     }
01950   else
01951     {
01952       /* We have to convert the DBusPollFD to an array of
01953        * struct pollfd, poll, and convert back.
01954        */
01955       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01956       return -1;
01957     }
01958 #else /* ! HAVE_POLL */
01959 
01960   fd_set read_set, write_set, err_set;
01961   int max_fd = 0;
01962   int i;
01963   struct timeval tv;
01964   int ready;
01965   
01966   FD_ZERO (&read_set);
01967   FD_ZERO (&write_set);
01968   FD_ZERO (&err_set);
01969 
01970   for (i = 0; i < n_fds; i++)
01971     {
01972       DBusPollFD f = fds[i];
01973 
01974       if (f.events & _DBUS_POLLIN)
01975         FD_SET (f.fd, &read_set);
01976 
01977       if (f.events & _DBUS_POLLOUT)
01978         FD_SET (f.fd, &write_set);
01979 
01980       FD_SET (f.fd, &err_set);
01981 
01982       max_fd = MAX (max_fd, f.fd);
01983     }
01984     
01985   tv.tv_sec = timeout_milliseconds / 1000;
01986   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01987 
01988   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01989 
01990   if (ready > 0)
01991     {
01992       for (i = 0; i < n_fds; i++)
01993         {
01994           DBusPollFD f = fds[i];
01995 
01996           f.revents = 0;
01997 
01998           if (FD_ISSET (f.fd, &read_set))
01999             f.revents |= _DBUS_POLLIN;
02000 
02001           if (FD_ISSET (f.fd, &write_set))
02002             f.revents |= _DBUS_POLLOUT;
02003 
02004           if (FD_ISSET (f.fd, &err_set))
02005             f.revents |= _DBUS_POLLERR;
02006         }
02007     }
02008 
02009   return ready;
02010 #endif
02011 }
02012 
02014 #define NANOSECONDS_PER_SECOND       1000000000
02015 
02016 #define MICROSECONDS_PER_SECOND      1000000
02017 
02018 #define MILLISECONDS_PER_SECOND      1000
02019 
02020 #define NANOSECONDS_PER_MILLISECOND  1000000
02021 
02022 #define MICROSECONDS_PER_MILLISECOND 1000
02023 
02028 void
02029 _dbus_sleep_milliseconds (int milliseconds)
02030 {
02031 #ifdef HAVE_NANOSLEEP
02032   struct timespec req;
02033   struct timespec rem;
02034 
02035   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02036   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02037   rem.tv_sec = 0;
02038   rem.tv_nsec = 0;
02039 
02040   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02041     req = rem;
02042 #elif defined (HAVE_USLEEP)
02043   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02044 #else /* ! HAVE_USLEEP */
02045   sleep (MAX (milliseconds / 1000, 1));
02046 #endif
02047 }
02048 
02055 void
02056 _dbus_get_current_time (long *tv_sec,
02057                         long *tv_usec)
02058 {
02059   struct timeval t;
02060 
02061   gettimeofday (&t, NULL);
02062 
02063   if (tv_sec)
02064     *tv_sec = t.tv_sec;
02065   if (tv_usec)
02066     *tv_usec = t.tv_usec;
02067 }
02068 
02079 dbus_bool_t
02080 _dbus_file_get_contents (DBusString       *str,
02081                          const DBusString *filename,
02082                          DBusError        *error)
02083 {
02084   int fd;
02085   struct stat sb;
02086   int orig_len;
02087   int total;
02088   const char *filename_c;
02089 
02090   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02091   
02092   filename_c = _dbus_string_get_const_data (filename);
02093   
02094   /* O_BINARY useful on Cygwin */
02095   fd = open (filename_c, O_RDONLY | O_BINARY);
02096   if (fd < 0)
02097     {
02098       dbus_set_error (error, _dbus_error_from_errno (errno),
02099                       "Failed to open \"%s\": %s",
02100                       filename_c,
02101                       _dbus_strerror (errno));
02102       return FALSE;
02103     }
02104 
02105   if (fstat (fd, &sb) < 0)
02106     {
02107       dbus_set_error (error, _dbus_error_from_errno (errno),
02108                       "Failed to stat \"%s\": %s",
02109                       filename_c,
02110                       _dbus_strerror (errno));
02111 
02112       _dbus_verbose ("fstat() failed: %s",
02113                      _dbus_strerror (errno));
02114       
02115       close (fd);
02116       
02117       return FALSE;
02118     }
02119 
02120   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02121     {
02122       dbus_set_error (error, DBUS_ERROR_FAILED,
02123                       "File size %lu of \"%s\" is too large.",
02124                       (unsigned long) sb.st_size, filename_c);
02125       close (fd);
02126       return FALSE;
02127     }
02128   
02129   total = 0;
02130   orig_len = _dbus_string_get_length (str);
02131   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02132     {
02133       int bytes_read;
02134 
02135       while (total < (int) sb.st_size)
02136         {
02137           bytes_read = _dbus_read (fd, str,
02138                                    sb.st_size - total);
02139           if (bytes_read <= 0)
02140             {
02141               dbus_set_error (error, _dbus_error_from_errno (errno),
02142                               "Error reading \"%s\": %s",
02143                               filename_c,
02144                               _dbus_strerror (errno));
02145 
02146               _dbus_verbose ("read() failed: %s",
02147                              _dbus_strerror (errno));
02148               
02149               close (fd);
02150               _dbus_string_set_length (str, orig_len);
02151               return FALSE;
02152             }
02153           else
02154             total += bytes_read;
02155         }
02156 
02157       close (fd);
02158       return TRUE;
02159     }
02160   else if (sb.st_size != 0)
02161     {
02162       _dbus_verbose ("Can only open regular files at the moment.\n");
02163       dbus_set_error (error, DBUS_ERROR_FAILED,
02164                       "\"%s\" is not a regular file",
02165                       filename_c);
02166       close (fd);
02167       return FALSE;
02168     }
02169   else
02170     {
02171       close (fd);
02172       return TRUE;
02173     }
02174 }
02175 
02185 dbus_bool_t
02186 _dbus_string_save_to_file (const DBusString *str,
02187                            const DBusString *filename,
02188                            DBusError        *error)
02189 {
02190   int fd;
02191   int bytes_to_write;
02192   const char *filename_c;
02193   DBusString tmp_filename;
02194   const char *tmp_filename_c;
02195   int total;
02196   dbus_bool_t need_unlink;
02197   dbus_bool_t retval;
02198 
02199   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02200   
02201   fd = -1;
02202   retval = FALSE;
02203   need_unlink = FALSE;
02204   
02205   if (!_dbus_string_init (&tmp_filename))
02206     {
02207       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02208       return FALSE;
02209     }
02210 
02211   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02212     {
02213       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02214       _dbus_string_free (&tmp_filename);
02215       return FALSE;
02216     }
02217   
02218   if (!_dbus_string_append (&tmp_filename, "."))
02219     {
02220       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02221       _dbus_string_free (&tmp_filename);
02222       return FALSE;
02223     }
02224 
02225 #define N_TMP_FILENAME_RANDOM_BYTES 8
02226   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02227     {
02228       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02229       _dbus_string_free (&tmp_filename);
02230       return FALSE;
02231     }
02232     
02233   filename_c = _dbus_string_get_const_data (filename);
02234   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02235 
02236   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02237              0600);
02238   if (fd < 0)
02239     {
02240       dbus_set_error (error, _dbus_error_from_errno (errno),
02241                       "Could not create %s: %s", tmp_filename_c,
02242                       _dbus_strerror (errno));
02243       goto out;
02244     }
02245 
02246   need_unlink = TRUE;
02247   
02248   total = 0;
02249   bytes_to_write = _dbus_string_get_length (str);
02250 
02251   while (total < bytes_to_write)
02252     {
02253       int bytes_written;
02254 
02255       bytes_written = _dbus_write (fd, str, total,
02256                                    bytes_to_write - total);
02257 
02258       if (bytes_written <= 0)
02259         {
02260           dbus_set_error (error, _dbus_error_from_errno (errno),
02261                           "Could not write to %s: %s", tmp_filename_c,
02262                           _dbus_strerror (errno));
02263           
02264           goto out;
02265         }
02266 
02267       total += bytes_written;
02268     }
02269 
02270   if (close (fd) < 0)
02271     {
02272       dbus_set_error (error, _dbus_error_from_errno (errno),
02273                       "Could not close file %s: %s",
02274                       tmp_filename_c, _dbus_strerror (errno));
02275 
02276       goto out;
02277     }
02278 
02279   fd = -1;
02280   
02281   if (rename (tmp_filename_c, filename_c) < 0)
02282     {
02283       dbus_set_error (error, _dbus_error_from_errno (errno),
02284                       "Could not rename %s to %s: %s",
02285                       tmp_filename_c, filename_c,
02286                       _dbus_strerror (errno));
02287 
02288       goto out;
02289     }
02290 
02291   need_unlink = FALSE;
02292   
02293   retval = TRUE;
02294   
02295  out:
02296   /* close first, then unlink, to prevent ".nfs34234235" garbage
02297    * files
02298    */
02299 
02300   if (fd >= 0)
02301     close (fd);
02302         
02303   if (need_unlink && unlink (tmp_filename_c) < 0)
02304     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02305                    tmp_filename_c, _dbus_strerror (errno));
02306 
02307   _dbus_string_free (&tmp_filename);
02308 
02309   if (!retval)
02310     _DBUS_ASSERT_ERROR_IS_SET (error);
02311   
02312   return retval;
02313 }
02314 
02321 dbus_bool_t
02322 _dbus_create_file_exclusively (const DBusString *filename,
02323                                DBusError        *error)
02324 {
02325   int fd;
02326   const char *filename_c;
02327 
02328   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02329   
02330   filename_c = _dbus_string_get_const_data (filename);
02331   
02332   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02333              0600);
02334   if (fd < 0)
02335     {
02336       dbus_set_error (error,
02337                       DBUS_ERROR_FAILED,
02338                       "Could not create file %s: %s\n",
02339                       filename_c,
02340                       _dbus_strerror (errno));
02341       return FALSE;
02342     }
02343 
02344   if (close (fd) < 0)
02345     {
02346       dbus_set_error (error,
02347                       DBUS_ERROR_FAILED,
02348                       "Could not close file %s: %s\n",
02349                       filename_c,
02350                       _dbus_strerror (errno));
02351       return FALSE;
02352     }
02353   
02354   return TRUE;
02355 }
02356 
02365 dbus_bool_t
02366 _dbus_delete_file (const DBusString *filename,
02367                    DBusError        *error)
02368 {
02369   const char *filename_c;
02370 
02371   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02372   
02373   filename_c = _dbus_string_get_const_data (filename);
02374 
02375   if (unlink (filename_c) < 0)
02376     {
02377       dbus_set_error (error, DBUS_ERROR_FAILED,
02378                       "Failed to delete file %s: %s\n",
02379                       filename_c, _dbus_strerror (errno));
02380       return FALSE;
02381     }
02382   else
02383     return TRUE;
02384 }
02385 
02394 dbus_bool_t
02395 _dbus_create_directory (const DBusString *filename,
02396                         DBusError        *error)
02397 {
02398   const char *filename_c;
02399 
02400   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02401   
02402   filename_c = _dbus_string_get_const_data (filename);
02403 
02404   if (mkdir (filename_c, 0700) < 0)
02405     {
02406       if (errno == EEXIST)
02407         return TRUE;
02408       
02409       dbus_set_error (error, DBUS_ERROR_FAILED,
02410                       "Failed to create directory %s: %s\n",
02411                       filename_c, _dbus_strerror (errno));
02412       return FALSE;
02413     }
02414   else
02415     return TRUE;
02416 }
02417 
02425 dbus_bool_t
02426 _dbus_delete_directory (const DBusString *filename,
02427                         DBusError        *error)
02428 {
02429   const char *filename_c;
02430   
02431   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02432 
02433   filename_c = _dbus_string_get_const_data (filename);
02434 
02435   if (rmdir (filename_c) != 0)
02436     {
02437       dbus_set_error (error, DBUS_ERROR_FAILED,
02438                       "Failed to remove directory %s: %s\n",
02439                       filename_c, _dbus_strerror (errno));
02440       return FALSE;
02441     }
02442   
02443   return TRUE;
02444 }
02445 
02456 dbus_bool_t
02457 _dbus_concat_dir_and_file (DBusString       *dir,
02458                            const DBusString *next_component)
02459 {
02460   dbus_bool_t dir_ends_in_slash;
02461   dbus_bool_t file_starts_with_slash;
02462 
02463   if (_dbus_string_get_length (dir) == 0 ||
02464       _dbus_string_get_length (next_component) == 0)
02465     return TRUE;
02466   
02467   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02468                                                     _dbus_string_get_length (dir) - 1);
02469 
02470   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02471 
02472   if (dir_ends_in_slash && file_starts_with_slash)
02473     {
02474       _dbus_string_shorten (dir, 1);
02475     }
02476   else if (!(dir_ends_in_slash || file_starts_with_slash))
02477     {
02478       if (!_dbus_string_append_byte (dir, '/'))
02479         return FALSE;
02480     }
02481 
02482   return _dbus_string_copy (next_component, 0, dir,
02483                             _dbus_string_get_length (dir));
02484 }
02485 
02492 dbus_bool_t
02493 _dbus_string_get_dirname  (const DBusString *filename,
02494                            DBusString       *dirname)
02495 {
02496   int sep;
02497   
02498   _dbus_assert (filename != dirname);
02499   _dbus_assert (filename != NULL);
02500   _dbus_assert (dirname != NULL);
02501 
02502   /* Ignore any separators on the end */
02503   sep = _dbus_string_get_length (filename);
02504   if (sep == 0)
02505     return _dbus_string_append (dirname, "."); /* empty string passed in */
02506     
02507   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02508     --sep;
02509 
02510   _dbus_assert (sep >= 0);
02511   
02512   if (sep == 0)
02513     return _dbus_string_append (dirname, "/");
02514   
02515   /* Now find the previous separator */
02516   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02517   if (sep < 0)
02518     return _dbus_string_append (dirname, ".");
02519   
02520   /* skip multiple separators */
02521   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02522     --sep;
02523 
02524   _dbus_assert (sep >= 0);
02525   
02526   if (sep == 0 &&
02527       _dbus_string_get_byte (filename, 0) == '/')
02528     return _dbus_string_append (dirname, "/");
02529   else
02530     return _dbus_string_copy_len (filename, 0, sep - 0,
02531                                   dirname, _dbus_string_get_length (dirname));
02532 }
02533 
02540 dbus_bool_t
02541 _dbus_path_is_absolute (const DBusString *filename)
02542 {
02543   if (_dbus_string_get_length (filename) > 0)
02544     return _dbus_string_get_byte (filename, 0) == '/';
02545   else
02546     return FALSE;
02547 }
02548 
02552 struct DBusDirIter
02553 {
02554   DIR *d; 
02556 };
02557 
02565 DBusDirIter*
02566 _dbus_directory_open (const DBusString *filename,
02567                       DBusError        *error)
02568 {
02569   DIR *d;
02570   DBusDirIter *iter;
02571   const char *filename_c;
02572 
02573   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02574   
02575   filename_c = _dbus_string_get_const_data (filename);
02576 
02577   d = opendir (filename_c);
02578   if (d == NULL)
02579     {
02580       dbus_set_error (error, _dbus_error_from_errno (errno),
02581                       "Failed to read directory \"%s\": %s",
02582                       filename_c,
02583                       _dbus_strerror (errno));
02584       return NULL;
02585     }
02586   iter = dbus_new0 (DBusDirIter, 1);
02587   if (iter == NULL)
02588     {
02589       closedir (d);
02590       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02591                       "Could not allocate memory for directory iterator");
02592       return NULL;
02593     }
02594 
02595   iter->d = d;
02596 
02597   return iter;
02598 }
02599 
02613 dbus_bool_t
02614 _dbus_directory_get_next_file (DBusDirIter      *iter,
02615                                DBusString       *filename,
02616                                DBusError        *error)
02617 {
02618   struct dirent *ent;
02619 
02620   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02621   
02622  again:
02623   errno = 0;
02624   ent = readdir (iter->d);
02625   if (ent == NULL)
02626     {
02627       if (errno != 0)
02628         dbus_set_error (error,
02629                         _dbus_error_from_errno (errno),
02630                         "%s", _dbus_strerror (errno));
02631       return FALSE;
02632     }
02633   else if (ent->d_name[0] == '.' &&
02634            (ent->d_name[1] == '\0' ||
02635             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02636     goto again;
02637   else
02638     {
02639       _dbus_string_set_length (filename, 0);
02640       if (!_dbus_string_append (filename, ent->d_name))
02641         {
02642           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02643                           "No memory to read directory entry");
02644           return FALSE;
02645         }
02646       else
02647         return TRUE;
02648     }
02649 }
02650 
02654 void
02655 _dbus_directory_close (DBusDirIter *iter)
02656 {
02657   closedir (iter->d);
02658   dbus_free (iter);
02659 }
02660 
02661 static dbus_bool_t
02662 pseudorandom_generate_random_bytes (DBusString *str,
02663                                     int         n_bytes)
02664 {
02665   int old_len;
02666   unsigned long tv_usec;
02667   int i;
02668   
02669   old_len = _dbus_string_get_length (str);
02670 
02671   /* fall back to pseudorandom */
02672   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02673                  n_bytes);
02674   
02675   _dbus_get_current_time (NULL, &tv_usec);
02676   srand (tv_usec);
02677   
02678   i = 0;
02679   while (i < n_bytes)
02680     {
02681       double r;
02682       unsigned int b;
02683           
02684       r = rand ();
02685       b = (r / (double) RAND_MAX) * 255.0;
02686           
02687       if (!_dbus_string_append_byte (str, b))
02688         goto failed;
02689           
02690       ++i;
02691     }
02692 
02693   return TRUE;
02694 
02695  failed:
02696   _dbus_string_set_length (str, old_len);
02697   return FALSE;
02698 }
02699 
02708 dbus_bool_t
02709 _dbus_generate_random_bytes (DBusString *str,
02710                              int         n_bytes)
02711 {
02712   int old_len;
02713   int fd;
02714 
02715   /* FALSE return means "no memory", if it could
02716    * mean something else then we'd need to return
02717    * a DBusError. So we always fall back to pseudorandom
02718    * if the I/O fails.
02719    */
02720   
02721   old_len = _dbus_string_get_length (str);
02722   fd = -1;
02723 
02724   /* note, urandom on linux will fall back to pseudorandom */
02725   fd = open ("/dev/urandom", O_RDONLY);
02726   if (fd < 0)
02727     return pseudorandom_generate_random_bytes (str, n_bytes);
02728 
02729   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02730     {
02731       close (fd);
02732       _dbus_string_set_length (str, old_len);
02733       return pseudorandom_generate_random_bytes (str, n_bytes);
02734     }
02735 
02736   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02737                  n_bytes);
02738   
02739   close (fd);
02740   
02741   return TRUE;
02742 }
02743 
02752 dbus_bool_t
02753 _dbus_generate_random_ascii (DBusString *str,
02754                              int         n_bytes)
02755 {
02756   static const char letters[] =
02757     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02758   int i;
02759   int len;
02760   
02761   if (!_dbus_generate_random_bytes (str, n_bytes))
02762     return FALSE;
02763   
02764   len = _dbus_string_get_length (str);
02765   i = len - n_bytes;
02766   while (i < len)
02767     {
02768       _dbus_string_set_byte (str, i,
02769                              letters[_dbus_string_get_byte (str, i) %
02770                                      (sizeof (letters) - 1)]);
02771 
02772       ++i;
02773     }
02774 
02775   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02776                                              n_bytes));
02777 
02778   return TRUE;
02779 }
02780 
02788 const char*
02789 _dbus_strerror (int error_number)
02790 {
02791   const char *msg;
02792   
02793   msg = strerror (error_number);
02794   if (msg == NULL)
02795     msg = "unknown";
02796 
02797   return msg;
02798 }
02799 
02803 void
02804 _dbus_disable_sigpipe (void)
02805 {
02806   signal (SIGPIPE, SIG_IGN);
02807 }
02808 
02816 void
02817 _dbus_fd_set_close_on_exec (int fd)
02818 {
02819   int val;
02820   
02821   val = fcntl (fd, F_GETFD, 0);
02822   
02823   if (val < 0)
02824     return;
02825 
02826   val |= FD_CLOEXEC;
02827   
02828   fcntl (fd, F_SETFD, val);
02829 }
02830 
02840 const char*
02841 _dbus_error_from_errno (int error_number)
02842 {
02843   switch (error_number)
02844     {
02845     case 0:
02846       return DBUS_ERROR_FAILED;
02847       
02848 #ifdef EPROTONOSUPPORT
02849     case EPROTONOSUPPORT:
02850       return DBUS_ERROR_NOT_SUPPORTED;
02851 #endif
02852 #ifdef EAFNOSUPPORT
02853     case EAFNOSUPPORT:
02854       return DBUS_ERROR_NOT_SUPPORTED;
02855 #endif
02856 #ifdef ENFILE
02857     case ENFILE:
02858       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02859 #endif
02860 #ifdef EMFILE
02861     case EMFILE:
02862       return DBUS_ERROR_LIMITS_EXCEEDED;
02863 #endif
02864 #ifdef EACCES
02865     case EACCES:
02866       return DBUS_ERROR_ACCESS_DENIED;
02867 #endif
02868 #ifdef EPERM
02869     case EPERM:
02870       return DBUS_ERROR_ACCESS_DENIED;
02871 #endif
02872 #ifdef ENOBUFS
02873     case ENOBUFS:
02874       return DBUS_ERROR_NO_MEMORY;
02875 #endif
02876 #ifdef ENOMEM
02877     case ENOMEM:
02878       return DBUS_ERROR_NO_MEMORY;
02879 #endif
02880 #ifdef EINVAL
02881     case EINVAL:
02882       return DBUS_ERROR_FAILED;
02883 #endif
02884 #ifdef EBADF
02885     case EBADF:
02886       return DBUS_ERROR_FAILED;
02887 #endif
02888 #ifdef EFAULT
02889     case EFAULT:
02890       return DBUS_ERROR_FAILED;
02891 #endif
02892 #ifdef ENOTSOCK
02893     case ENOTSOCK:
02894       return DBUS_ERROR_FAILED;
02895 #endif
02896 #ifdef EISCONN
02897     case EISCONN:
02898       return DBUS_ERROR_FAILED;
02899 #endif
02900 #ifdef ECONNREFUSED
02901     case ECONNREFUSED:
02902       return DBUS_ERROR_NO_SERVER;
02903 #endif
02904 #ifdef ETIMEDOUT
02905     case ETIMEDOUT:
02906       return DBUS_ERROR_TIMEOUT;
02907 #endif
02908 #ifdef ENETUNREACH
02909     case ENETUNREACH:
02910       return DBUS_ERROR_NO_NETWORK;
02911 #endif
02912 #ifdef EADDRINUSE
02913     case EADDRINUSE:
02914       return DBUS_ERROR_ADDRESS_IN_USE;
02915 #endif
02916 #ifdef EEXIST
02917     case EEXIST:
02918       return DBUS_ERROR_FILE_NOT_FOUND;
02919 #endif
02920 #ifdef ENOENT
02921     case ENOENT:
02922       return DBUS_ERROR_FILE_NOT_FOUND;
02923 #endif
02924     }
02925 
02926   return DBUS_ERROR_FAILED;
02927 }
02928 
02934 void
02935 _dbus_exit (int code)
02936 {
02937   _exit (code);
02938 }
02939 
02948 dbus_bool_t
02949 _dbus_stat (const DBusString *filename,
02950             DBusStat         *statbuf,
02951             DBusError        *error)
02952 {
02953   const char *filename_c;
02954   struct stat sb;
02955 
02956   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02957   
02958   filename_c = _dbus_string_get_const_data (filename);
02959 
02960   if (stat (filename_c, &sb) < 0)
02961     {
02962       dbus_set_error (error, _dbus_error_from_errno (errno),
02963                       "%s", _dbus_strerror (errno));
02964       return FALSE;
02965     }
02966 
02967   statbuf->mode = sb.st_mode;
02968   statbuf->nlink = sb.st_nlink;
02969   statbuf->uid = sb.st_uid;
02970   statbuf->gid = sb.st_gid;
02971   statbuf->size = sb.st_size;
02972   statbuf->atime = sb.st_atime;
02973   statbuf->mtime = sb.st_mtime;
02974   statbuf->ctime = sb.st_ctime;
02975 
02976   return TRUE;
02977 }
02978 
02989 dbus_bool_t
02990 _dbus_full_duplex_pipe (int        *fd1,
02991                         int        *fd2,
02992                         dbus_bool_t blocking,
02993                         DBusError  *error)
02994 {
02995 #ifdef HAVE_SOCKETPAIR
02996   int fds[2];
02997 
02998   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02999   
03000   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
03001     {
03002       dbus_set_error (error, _dbus_error_from_errno (errno),
03003                       "Could not create full-duplex pipe");
03004       return FALSE;
03005     }
03006 
03007   if (!blocking &&
03008       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03009        !_dbus_set_fd_nonblocking (fds[1], NULL)))
03010     {
03011       dbus_set_error (error, _dbus_error_from_errno (errno),
03012                       "Could not set full-duplex pipe nonblocking");
03013       
03014       close (fds[0]);
03015       close (fds[1]);
03016       
03017       return FALSE;
03018     }
03019   
03020   *fd1 = fds[0];
03021   *fd2 = fds[1];
03022 
03023   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03024                  *fd1, *fd2);
03025   
03026   return TRUE;  
03027 #else
03028   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03029   dbus_set_error (error, DBUS_ERROR_FAILED,
03030                   "_dbus_full_duplex_pipe() not implemented on this OS");
03031   return FALSE;
03032 #endif
03033 }
03034 
03042 dbus_bool_t
03043 _dbus_close (int        fd,
03044              DBusError *error)
03045 {
03046   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03047   
03048  again:
03049   if (close (fd) < 0)
03050     {
03051       if (errno == EINTR)
03052         goto again;
03053 
03054       dbus_set_error (error, _dbus_error_from_errno (errno),
03055                       "Could not close fd %d", fd);
03056       return FALSE;
03057     }
03058 
03059   return TRUE;
03060 }
03061 
03069 dbus_bool_t
03070 _dbus_set_fd_nonblocking (int             fd,
03071                           DBusError      *error)
03072 {
03073   int val;
03074 
03075   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03076   
03077   val = fcntl (fd, F_GETFL, 0);
03078   if (val < 0)
03079     {
03080       dbus_set_error (error, _dbus_error_from_errno (errno),
03081                       "Failed to get flags from file descriptor %d: %s",
03082                       fd, _dbus_strerror (errno));
03083       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03084                      _dbus_strerror (errno));
03085       return FALSE;
03086     }
03087 
03088   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03089     {
03090       dbus_set_error (error, _dbus_error_from_errno (errno),
03091                       "Failed to set nonblocking flag of file descriptor %d: %s",
03092                       fd, _dbus_strerror (errno));
03093       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03094                      fd, _dbus_strerror (errno));
03095 
03096       return FALSE;
03097     }
03098 
03099   return TRUE;
03100 }
03101 
03107 void
03108 _dbus_print_backtrace (void)
03109 {
03110 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03111   void *bt[500];
03112   int bt_size;
03113   int i;
03114   char **syms;
03115   
03116   bt_size = backtrace (bt, 500);
03117 
03118   syms = backtrace_symbols (bt, bt_size);
03119   
03120   i = 0;
03121   while (i < bt_size)
03122     {
03123       _dbus_verbose ("  %s\n", syms[i]);
03124       ++i;
03125     }
03126 
03127   free (syms);
03128 #else
03129   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
03130 #endif
03131 }
03132 
03141 dbus_bool_t
03142 _dbus_become_daemon (const DBusString *pidfile,
03143                      int               print_pid_fd,
03144                      DBusError        *error)
03145 {
03146   const char *s;
03147   pid_t child_pid;
03148   int dev_null_fd;
03149 
03150   _dbus_verbose ("Becoming a daemon...\n");
03151 
03152   _dbus_verbose ("chdir to /\n");
03153   if (chdir ("/") < 0)
03154     {
03155       dbus_set_error (error, DBUS_ERROR_FAILED,
03156                       "Could not chdir() to root directory");
03157       return FALSE;
03158     }
03159 
03160   _dbus_verbose ("forking...\n");
03161   switch ((child_pid = fork ()))
03162     {
03163     case -1:
03164       _dbus_verbose ("fork failed\n");
03165       dbus_set_error (error, _dbus_error_from_errno (errno),
03166                       "Failed to fork daemon: %s", _dbus_strerror (errno));
03167       return FALSE;
03168       break;
03169 
03170     case 0:
03171       _dbus_verbose ("in child, closing std file descriptors\n");
03172 
03173       /* silently ignore failures here, if someone
03174        * doesn't have /dev/null we may as well try
03175        * to continue anyhow
03176        */
03177       
03178       dev_null_fd = open ("/dev/null", O_RDWR);
03179       if (dev_null_fd >= 0)
03180         {
03181           dup2 (dev_null_fd, 0);
03182           dup2 (dev_null_fd, 1);
03183           
03184           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03185           if (s == NULL || *s == '\0')
03186             dup2 (dev_null_fd, 2);
03187           else
03188             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
03189         }
03190 
03191       /* Get a predictable umask */
03192       _dbus_verbose ("setting umask\n");
03193       umask (022);
03194       break;
03195 
03196     default:
03197       if (pidfile)
03198         {
03199           _dbus_verbose ("parent writing pid file\n");
03200           if (!_dbus_write_pid_file (pidfile,
03201                                      child_pid,
03202                                      error))
03203             {
03204               _dbus_verbose ("pid file write failed, killing child\n");
03205               kill (child_pid, SIGTERM);
03206               return FALSE;
03207             }
03208         }
03209 
03210       /* Write PID if requested */
03211       if (print_pid_fd >= 0)
03212         {
03213           DBusString pid;
03214           int bytes;
03215           
03216           if (!_dbus_string_init (&pid))
03217             {
03218               _DBUS_SET_OOM (error);
03219               kill (child_pid, SIGTERM);
03220               return FALSE;
03221             }
03222           
03223           if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
03224               !_dbus_string_append (&pid, "\n"))
03225             {
03226               _dbus_string_free (&pid);
03227               _DBUS_SET_OOM (error);
03228               kill (child_pid, SIGTERM);
03229               return FALSE;
03230             }
03231           
03232           bytes = _dbus_string_get_length (&pid);
03233           if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
03234             {
03235               dbus_set_error (error, DBUS_ERROR_FAILED,
03236                               "Printing message bus PID: %s\n",
03237                               _dbus_strerror (errno));
03238               _dbus_string_free (&pid);
03239               kill (child_pid, SIGTERM);
03240               return FALSE;
03241             }
03242           
03243           _dbus_string_free (&pid);
03244         }
03245       _dbus_verbose ("parent exiting\n");
03246       _exit (0);
03247       break;
03248     }
03249 
03250   _dbus_verbose ("calling setsid()\n");
03251   if (setsid () == -1)
03252     _dbus_assert_not_reached ("setsid() failed");
03253   
03254   return TRUE;
03255 }
03256 
03265 dbus_bool_t
03266 _dbus_write_pid_file (const DBusString *filename,
03267                       unsigned long     pid,
03268                       DBusError        *error)
03269 {
03270   const char *cfilename;
03271   int fd;
03272   FILE *f;
03273 
03274   cfilename = _dbus_string_get_const_data (filename);
03275   
03276   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03277   
03278   if (fd < 0)
03279     {
03280       dbus_set_error (error, _dbus_error_from_errno (errno),
03281                       "Failed to open \"%s\": %s", cfilename,
03282                       _dbus_strerror (errno));
03283       return FALSE;
03284     }
03285 
03286   if ((f = fdopen (fd, "w")) == NULL)
03287     {
03288       dbus_set_error (error, _dbus_error_from_errno (errno),
03289                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03290       close (fd);
03291       return FALSE;
03292     }
03293   
03294   if (fprintf (f, "%lu\n", pid) < 0)
03295     {
03296       dbus_set_error (error, _dbus_error_from_errno (errno),
03297                       "Failed to write to \"%s\": %s", cfilename,
03298                       _dbus_strerror (errno));
03299       return FALSE;
03300     }
03301 
03302   if (fclose (f) == EOF)
03303     {
03304       dbus_set_error (error, _dbus_error_from_errno (errno),
03305                       "Failed to close \"%s\": %s", cfilename,
03306                       _dbus_strerror (errno));
03307       return FALSE;
03308     }
03309   
03310   return TRUE;
03311 }
03312 
03321 dbus_bool_t
03322 _dbus_change_identity  (dbus_uid_t     uid,
03323                         dbus_gid_t     gid,
03324                         DBusError     *error)
03325 {
03326   /* setgroups() only works if we are a privileged process,
03327    * so we don't return error on failure; the only possible
03328    * failure is that we don't have perms to do it.
03329    * FIXME not sure this is right, maybe if setuid()
03330    * is going to work then setgroups() should also work.
03331    */
03332   if (setgroups (0, NULL) < 0)
03333     _dbus_warn ("Failed to drop supplementary groups: %s\n",
03334                 _dbus_strerror (errno));
03335   
03336   /* Set GID first, or the setuid may remove our permission
03337    * to change the GID
03338    */
03339   if (setgid (gid) < 0)
03340     {
03341       dbus_set_error (error, _dbus_error_from_errno (errno),
03342                       "Failed to set GID to %lu: %s", gid,
03343                       _dbus_strerror (errno));
03344       return FALSE;
03345     }
03346   
03347   if (setuid (uid) < 0)
03348     {
03349       dbus_set_error (error, _dbus_error_from_errno (errno),
03350                       "Failed to set UID to %lu: %s", uid,
03351                       _dbus_strerror (errno));
03352       return FALSE;
03353     }
03354   
03355   return TRUE;
03356 }
03357 
03363 void
03364 _dbus_set_signal_handler (int               sig,
03365                           DBusSignalHandler handler)
03366 {
03367   struct sigaction act;
03368   sigset_t empty_mask;
03369   
03370   sigemptyset (&empty_mask);
03371   act.sa_handler = handler;
03372   act.sa_mask    = empty_mask;
03373   act.sa_flags   = 0;
03374   sigaction (sig,  &act, 0);
03375 }
03376 
03382 dbus_bool_t 
03383 _dbus_file_exists (const char *file)
03384 {
03385   return (access (file, F_OK) == 0);
03386 }
03387 
03394 dbus_bool_t 
03395 _dbus_user_at_console (const char *username,
03396                        DBusError  *error)
03397 {
03398 
03399   DBusString f;
03400   dbus_bool_t result;
03401 
03402   result = FALSE;
03403   if (!_dbus_string_init (&f))
03404     {
03405       _DBUS_SET_OOM (error);
03406       return FALSE;
03407     }
03408 
03409   if (!_dbus_string_append (&f, DBUS_CONSOLE_DIR))
03410     {
03411       _DBUS_SET_OOM (error);
03412       goto out;
03413     }
03414 
03415 
03416   if (!_dbus_string_append (&f, username))
03417     {
03418       _DBUS_SET_OOM (error);
03419       goto out;
03420     }
03421 
03422   result = _dbus_file_exists (_dbus_string_get_const_data (&f));
03423 
03424  out:
03425   _dbus_string_free (&f);
03426 
03427   return result;
03428 }
03429 
03430 #ifdef DBUS_BUILD_TESTS
03431 #include <stdlib.h>
03432 static void
03433 check_dirname (const char *filename,
03434                const char *dirname)
03435 {
03436   DBusString f, d;
03437   
03438   _dbus_string_init_const (&f, filename);
03439 
03440   if (!_dbus_string_init (&d))
03441     _dbus_assert_not_reached ("no memory");
03442 
03443   if (!_dbus_string_get_dirname (&f, &d))
03444     _dbus_assert_not_reached ("no memory");
03445 
03446   if (!_dbus_string_equal_c_str (&d, dirname))
03447     {
03448       _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03449                   filename,
03450                   _dbus_string_get_const_data (&d),
03451                   dirname);
03452       exit (1);
03453     }
03454 
03455   _dbus_string_free (&d);
03456 }
03457 
03458 static void
03459 check_path_absolute (const char *path,
03460                      dbus_bool_t expected)
03461 {
03462   DBusString p;
03463 
03464   _dbus_string_init_const (&p, path);
03465 
03466   if (_dbus_path_is_absolute (&p) != expected)
03467     {
03468       _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03469                   path, expected, _dbus_path_is_absolute (&p));
03470       exit (1);
03471     }
03472 }
03473 
03479 dbus_bool_t
03480 _dbus_sysdeps_test (void)
03481 {
03482   DBusString str;
03483   double val;
03484   int pos;
03485   
03486   check_dirname ("foo", ".");
03487   check_dirname ("foo/bar", "foo");
03488   check_dirname ("foo//bar", "foo");
03489   check_dirname ("foo///bar", "foo");
03490   check_dirname ("foo/bar/", "foo");
03491   check_dirname ("foo//bar/", "foo");
03492   check_dirname ("foo///bar/", "foo");
03493   check_dirname ("foo/bar//", "foo");
03494   check_dirname ("foo//bar////", "foo");
03495   check_dirname ("foo///bar///////", "foo");
03496   check_dirname ("/foo", "/");
03497   check_dirname ("
03498   check_dirname ("/foo/bar", "/foo");
03499   check_dirname ("/foo//bar", "/foo");
03500   check_dirname ("/foo///bar", "/foo");
03501   check_dirname ("/", "/");
03502   check_dirname ("
03503   check_dirname ("", ".");  
03504 
03505 
03506   _dbus_string_init_const (&str, "3.5");
03507   if (!_dbus_string_parse_double (&str,
03508                                   0, &val, &pos))
03509     {
03510       _dbus_warn ("Failed to parse double");
03511       exit (1);
03512     }
03513   if (ABS(3.5 - val) > 1e-6)
03514     {
03515       _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03516       exit (1);
03517     }
03518   if (pos != 3)
03519     {
03520       _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03521       exit (1);
03522     }
03523 
03524   _dbus_string_init_const (&str, "0xff");
03525   if (!_dbus_string_parse_double (&str,
03526                                   0, &val, &pos))
03527     {
03528       _dbus_warn ("Failed to parse double");
03529       exit (1);
03530     }
03531   if (ABS (0xff - val) > 1e-6)
03532     {
03533       _dbus_warn ("Failed to parse 0xff correctly, got: %f\n", val);
03534       exit (1);
03535     }
03536   if (pos != 4)
03537     {
03538       _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
03539       exit (1);
03540     }
03541   
03542   check_path_absolute ("/", TRUE);
03543   check_path_absolute ("/foo", TRUE);
03544   check_path_absolute ("", FALSE);
03545   check_path_absolute ("foo", FALSE);
03546   check_path_absolute ("foo/bar", FALSE);
03547   
03548   return TRUE;
03549 }
03550 #endif /* DBUS_BUILD_TESTS */
03551 

Generated on Mon Apr 4 04:40:47 2005 for D-BUS by  doxygen 1.4.0