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

dbus-sysdeps.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 1.2
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-test.h"
00029 #include <sys/types.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <signal.h>
00033 #include <unistd.h>
00034 #include <stdio.h>
00035 #include <errno.h>
00036 #include <fcntl.h>
00037 #include <sys/socket.h>
00038 #include <dirent.h>
00039 #include <sys/un.h>
00040 #include <pwd.h>
00041 #include <time.h>
00042 #include <locale.h>
00043 #include <sys/time.h>
00044 #include <sys/stat.h>
00045 #include <sys/wait.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include <grp.h>
00049 
00050 #ifdef HAVE_WRITEV
00051 #include <sys/uio.h>
00052 #endif
00053 #ifdef HAVE_POLL
00054 #include <sys/poll.h>
00055 #endif
00056 #ifdef HAVE_BACKTRACE
00057 #include <execinfo.h>
00058 #endif
00059 
00060 
00061 #ifndef O_BINARY
00062 #define O_BINARY 0
00063 #endif
00064 
00065 #ifndef HAVE_SOCKLEN_T
00066 #define socklen_t int
00067 #endif
00068 
00076 void
00077 _dbus_abort (void)
00078 {
00079 #ifdef DBUS_ENABLE_VERBOSE_MODE
00080   const char *s;
00081   s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00082   if (s && *s)
00083     _dbus_print_backtrace ();
00084 #endif
00085   abort ();
00086   _exit (1); /* in case someone manages to ignore SIGABRT */
00087 }
00088 
00100 dbus_bool_t
00101 _dbus_setenv (const char *varname,
00102               const char *value)
00103 {
00104   _dbus_assert (varname != NULL);
00105   
00106   if (value == NULL)
00107     {
00108 #ifdef HAVE_UNSETENV
00109       unsetenv (varname);
00110       return TRUE;
00111 #else
00112       char *putenv_value;
00113       size_t len;
00114 
00115       len = strlen (varname);
00116 
00117       /* Use system malloc to avoid memleaks that dbus_malloc
00118        * will get upset about.
00119        */
00120       
00121       putenv_value = malloc (len + 1);
00122       if (putenv_value == NULL)
00123         return FALSE;
00124 
00125       strcpy (putenv_value, varname);
00126       
00127       return (putenv (putenv_value) == 0);
00128 #endif
00129     }
00130   else
00131     {
00132 #ifdef HAVE_SETENV
00133       return (setenv (varname, value, TRUE) == 0);
00134 #else
00135       char *putenv_value;
00136       size_t len;
00137       size_t varname_len;
00138       size_t value_len;
00139 
00140       varname_len = strlen (varname);
00141       value_len = strlen (value);
00142       
00143       len = varname_len + value_len + 1 /* '=' */ ;
00144 
00145       /* Use system malloc to avoid memleaks that dbus_malloc
00146        * will get upset about.
00147        */
00148       
00149       putenv_value = malloc (len + 1);
00150       if (putenv_value == NULL)
00151         return FALSE;
00152 
00153       strcpy (putenv_value, varname);
00154       strcpy (putenv_value + varname_len, "=");
00155       strcpy (putenv_value + varname_len + 1, value);
00156       
00157       return (putenv (putenv_value) == 0);
00158 #endif
00159     }
00160 }
00161 
00168 const char*
00169 _dbus_getenv (const char *varname)
00170 {  
00171   return getenv (varname);
00172 }
00173 
00187 int
00188 _dbus_read (int               fd,
00189             DBusString       *buffer,
00190             int               count)
00191 {
00192   int bytes_read;
00193   int start;
00194   char *data;
00195 
00196   _dbus_assert (count >= 0);
00197   
00198   start = _dbus_string_get_length (buffer);
00199 
00200   if (!_dbus_string_lengthen (buffer, count))
00201     {
00202       errno = ENOMEM;
00203       return -1;
00204     }
00205 
00206   data = _dbus_string_get_data_len (buffer, start, count);
00207 
00208  again:
00209   
00210   bytes_read = read (fd, data, count);
00211 
00212   if (bytes_read < 0)
00213     {
00214       if (errno == EINTR)
00215         goto again;
00216       else
00217         {
00218           /* put length back (note that this doesn't actually realloc anything) */
00219           _dbus_string_set_length (buffer, start);
00220           return -1;
00221         }
00222     }
00223   else
00224     {
00225       /* put length back (doesn't actually realloc) */
00226       _dbus_string_set_length (buffer, start + bytes_read);
00227 
00228 #if 0
00229       if (bytes_read > 0)
00230         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00231 #endif
00232       
00233       return bytes_read;
00234     }
00235 }
00236 
00247 int
00248 _dbus_write (int               fd,
00249              const DBusString *buffer,
00250              int               start,
00251              int               len)
00252 {
00253   const char *data;
00254   int bytes_written;
00255   
00256   data = _dbus_string_get_const_data_len (buffer, start, len);
00257   
00258  again:
00259 
00260   bytes_written = write (fd, data, len);
00261 
00262   if (bytes_written < 0 && errno == EINTR)
00263     goto again;
00264 
00265 #if 0
00266   if (bytes_written > 0)
00267     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00268 #endif
00269   
00270   return bytes_written;
00271 }
00272 
00293 int
00294 _dbus_write_two (int               fd,
00295                  const DBusString *buffer1,
00296                  int               start1,
00297                  int               len1,
00298                  const DBusString *buffer2,
00299                  int               start2,
00300                  int               len2)
00301 {
00302   _dbus_assert (buffer1 != NULL);
00303   _dbus_assert (start1 >= 0);
00304   _dbus_assert (start2 >= 0);
00305   _dbus_assert (len1 >= 0);
00306   _dbus_assert (len2 >= 0);
00307   
00308 #ifdef HAVE_WRITEV
00309   {
00310     struct iovec vectors[2];
00311     const char *data1;
00312     const char *data2;
00313     int bytes_written;
00314 
00315     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00316 
00317     if (buffer2 != NULL)
00318       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00319     else
00320       {
00321         data2 = NULL;
00322         start2 = 0;
00323         len2 = 0;
00324       }
00325    
00326     vectors[0].iov_base = (char*) data1;
00327     vectors[0].iov_len = len1;
00328     vectors[1].iov_base = (char*) data2;
00329     vectors[1].iov_len = len2;
00330 
00331   again:
00332    
00333     bytes_written = writev (fd,
00334                             vectors,
00335                             data2 ? 2 : 1);
00336 
00337     if (bytes_written < 0 && errno == EINTR)
00338       goto again;
00339    
00340     return bytes_written;
00341   }
00342 #else /* HAVE_WRITEV */
00343   {
00344     int ret1;
00345     
00346     ret1 = _dbus_write (fd, buffer1, start1, len1);
00347     if (ret1 == len1 && buffer2 != NULL)
00348       {
00349         ret2 = _dbus_write (fd, buffer2, start2, len2);
00350         if (ret2 < 0)
00351           ret2 = 0; /* we can't report an error as the first write was OK */
00352        
00353         return ret1 + ret2;
00354       }
00355     else
00356       return ret1;
00357   }
00358 #endif /* !HAVE_WRITEV */   
00359 }
00360 
00361 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00362 
00390 int
00391 _dbus_connect_unix_socket (const char     *path,
00392                            dbus_bool_t     abstract,
00393                            DBusError      *error)
00394 {
00395   int fd;
00396   struct sockaddr_un addr;  
00397 
00398   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00399 
00400   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00401                  path, abstract);
00402   
00403   fd = socket (PF_UNIX, SOCK_STREAM, 0);
00404   
00405   if (fd < 0)
00406     {
00407       dbus_set_error (error,
00408                       _dbus_error_from_errno (errno),
00409                       "Failed to create socket: %s",
00410                       _dbus_strerror (errno)); 
00411       
00412       return -1;
00413     }
00414 
00415   _DBUS_ZERO (addr);
00416   addr.sun_family = AF_UNIX;
00417 
00418   if (abstract)
00419     {
00420 #ifdef HAVE_ABSTRACT_SOCKETS
00421       /* remember that abstract names aren't nul-terminated so we rely
00422        * on sun_path being filled in with zeroes above.
00423        */
00424       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00425       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00426       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00427 #else /* HAVE_ABSTRACT_SOCKETS */
00428       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00429                       "Operating system does not support abstract socket namespace\n");
00430       close (fd);
00431       return -1;
00432 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00433     }
00434   else
00435     {
00436       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00437     }
00438   
00439   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00440     {      
00441       dbus_set_error (error,
00442                       _dbus_error_from_errno (errno),
00443                       "Failed to connect to socket %s: %s",
00444                       path, _dbus_strerror (errno));
00445 
00446       close (fd);
00447       fd = -1;
00448       
00449       return -1;
00450     }
00451 
00452   if (!_dbus_set_fd_nonblocking (fd, error))
00453     {
00454       _DBUS_ASSERT_ERROR_IS_SET (error);
00455       
00456       close (fd);
00457       fd = -1;
00458 
00459       return -1;
00460     }
00461 
00462   return fd;
00463 }
00464 
00480 int
00481 _dbus_listen_unix_socket (const char     *path,
00482                           dbus_bool_t     abstract,
00483                           DBusError      *error)
00484 {
00485   int listen_fd;
00486   struct sockaddr_un addr;
00487 
00488   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00489 
00490   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00491                  path, abstract);
00492   
00493   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00494   
00495   if (listen_fd < 0)
00496     {
00497       dbus_set_error (error, _dbus_error_from_errno (errno),
00498                       "Failed to create socket \"%s\": %s",
00499                       path, _dbus_strerror (errno));
00500       return -1;
00501     }
00502 
00503   _DBUS_ZERO (addr);
00504   addr.sun_family = AF_UNIX;
00505   
00506   if (abstract)
00507     {
00508 #ifdef HAVE_ABSTRACT_SOCKETS
00509       /* remember that abstract names aren't nul-terminated so we rely
00510        * on sun_path being filled in with zeroes above.
00511        */
00512       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00513       strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00514       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00515 #else /* HAVE_ABSTRACT_SOCKETS */
00516       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00517                       "Operating system does not support abstract socket namespace\n");
00518       close (listen_fd);
00519       return -1;
00520 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00521     }
00522   else
00523     {
00524       /* FIXME discussed security implications of this with Nalin,
00525        * and we couldn't think of where it would kick our ass, but
00526        * it still seems a bit sucky. It also has non-security suckage;
00527        * really we'd prefer to exit if the socket is already in use.
00528        * But there doesn't seem to be a good way to do this.
00529        *
00530        * Just to be extra careful, I threw in the stat() - clearly
00531        * the stat() can't *fix* any security issue, but it at least
00532        * avoids inadvertent/accidental data loss.
00533        */
00534       {
00535         struct stat sb;
00536 
00537         if (stat (path, &sb) == 0 &&
00538             S_ISSOCK (sb.st_mode))
00539           unlink (path);
00540       }
00541 
00542       strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00543     }
00544   
00545   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00546     {
00547       dbus_set_error (error, _dbus_error_from_errno (errno),
00548                       "Failed to bind socket \"%s\": %s",
00549                       path, _dbus_strerror (errno));
00550       close (listen_fd);
00551       return -1;
00552     }
00553 
00554   if (listen (listen_fd, 30 /* backlog */) < 0)
00555     {
00556       dbus_set_error (error, _dbus_error_from_errno (errno),
00557                       "Failed to listen on socket \"%s\": %s",
00558                       path, _dbus_strerror (errno));
00559       close (listen_fd);
00560       return -1;
00561     }
00562 
00563   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00564     {
00565       _DBUS_ASSERT_ERROR_IS_SET (error);
00566       close (listen_fd);
00567       return -1;
00568     }
00569   
00570   /* Try opening up the permissions, but if we can't, just go ahead
00571    * and continue, maybe it will be good enough.
00572    */
00573   if (!abstract && chmod (path, 0777) < 0)
00574     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00575                 path);
00576   
00577   return listen_fd;
00578 }
00579 
00590 int
00591 _dbus_connect_tcp_socket (const char     *host,
00592                           dbus_uint32_t   port,
00593                           DBusError      *error)
00594 {
00595   int fd;
00596   struct sockaddr_in addr;
00597   struct hostent *he;
00598   struct in_addr *haddr;
00599 
00600   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00601   
00602   fd = socket (AF_INET, SOCK_STREAM, 0);
00603   
00604   if (fd < 0)
00605     {
00606       dbus_set_error (error,
00607                       _dbus_error_from_errno (errno),
00608                       "Failed to create socket: %s",
00609                       _dbus_strerror (errno)); 
00610       
00611       return -1;
00612     }
00613 
00614   if (host == NULL)
00615     host = "localhost";
00616 
00617   he = gethostbyname (host);
00618   if (he == NULL) 
00619     {
00620       dbus_set_error (error,
00621                       _dbus_error_from_errno (errno),
00622                       "Failed to lookup hostname: %s",
00623                       host);
00624       return -1;
00625     }
00626   
00627   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00628 
00629   _DBUS_ZERO (addr);
00630   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00631   addr.sin_family = AF_INET;
00632   addr.sin_port = htons (port);
00633   
00634   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00635     {      
00636       dbus_set_error (error,
00637                        _dbus_error_from_errno (errno),
00638                       "Failed to connect to socket %s: %s:%d",
00639                       host, _dbus_strerror (errno), port);
00640 
00641       close (fd);
00642       fd = -1;
00643       
00644       return -1;
00645     }
00646 
00647   if (!_dbus_set_fd_nonblocking (fd, error))
00648     {
00649       close (fd);
00650       fd = -1;
00651 
00652       return -1;
00653     }
00654 
00655   return fd;
00656 }
00657 
00668 int
00669 _dbus_listen_tcp_socket (const char     *host,
00670                          dbus_uint32_t   port,
00671                          DBusError      *error)
00672 {
00673   int listen_fd;
00674   struct sockaddr_in addr;
00675   struct hostent *he;
00676   struct in_addr *haddr;
00677 
00678   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00679   
00680   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00681   
00682   if (listen_fd < 0)
00683     {
00684       dbus_set_error (error, _dbus_error_from_errno (errno),
00685                       "Failed to create socket \"%s:%d\": %s",
00686                       host, port, _dbus_strerror (errno));
00687       return -1;
00688     }
00689 
00690   if (host == NULL)
00691     host = "localhost";
00692   
00693   he = gethostbyname (host);
00694   if (he == NULL) 
00695     {
00696       dbus_set_error (error,
00697                       _dbus_error_from_errno (errno),
00698                       "Failed to lookup hostname: %s",
00699                       host);
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 out;
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   _dbus_user_info_free (info);
01570   return FALSE;
01571 }
01572 
01581 dbus_bool_t
01582 _dbus_user_info_fill (DBusUserInfo     *info,
01583                       const DBusString *username,
01584                       DBusError        *error)
01585 {
01586   return fill_user_info (info, DBUS_UID_UNSET,
01587                          username, error);
01588 }
01589 
01598 dbus_bool_t
01599 _dbus_user_info_fill_uid (DBusUserInfo *info,
01600                           dbus_uid_t    uid,
01601                           DBusError    *error)
01602 {
01603   return fill_user_info (info, uid,
01604                          NULL, error);
01605 }
01606 
01612 void
01613 _dbus_user_info_free (DBusUserInfo *info)
01614 {
01615   dbus_free (info->group_ids);
01616   dbus_free (info->username);
01617   dbus_free (info->homedir);
01618 }
01619 
01620 static dbus_bool_t
01621 fill_user_info_from_group (struct group  *g,
01622                            DBusGroupInfo *info,
01623                            DBusError     *error)
01624 {
01625   _dbus_assert (g->gr_name != NULL);
01626   
01627   info->gid = g->gr_gid;
01628   info->groupname = _dbus_strdup (g->gr_name);
01629 
01630   /* info->members = dbus_strdupv (g->gr_mem) */
01631   
01632   if (info->groupname == NULL)
01633     {
01634       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01635       return FALSE;
01636     }
01637 
01638   return TRUE;
01639 }
01640 
01641 static dbus_bool_t
01642 fill_group_info (DBusGroupInfo    *info,
01643                  dbus_gid_t        gid,
01644                  const DBusString *groupname,
01645                  DBusError        *error)
01646 {
01647   const char *group_c_str;
01648 
01649   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01650   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01651 
01652   if (groupname)
01653     group_c_str = _dbus_string_get_const_data (groupname);
01654   else
01655     group_c_str = NULL;
01656   
01657   /* For now assuming that the getgrnam() and getgrgid() flavors
01658    * always correspond to the pwnam flavors, if not we have
01659    * to add more configure checks.
01660    */
01661   
01662 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01663   {
01664     struct group *g;
01665     int result;
01666     char buf[1024];
01667     struct group g_str;
01668 
01669     g = NULL;
01670 #ifdef HAVE_POSIX_GETPWNAME_R
01671 
01672     if (group_c_str)
01673       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01674                            &g);
01675     else
01676       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01677                            &g);
01678 #else
01679     p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01680     result = 0;
01681 #endif /* !HAVE_POSIX_GETPWNAME_R */
01682     if (result == 0 && g == &g_str)
01683       {
01684         return fill_user_info_from_group (g, info, error);
01685       }
01686     else
01687       {
01688         dbus_set_error (error, _dbus_error_from_errno (errno),
01689                         "Group %s unknown or failed to look it up\n",
01690                         group_c_str ? group_c_str : "???");
01691         return FALSE;
01692       }
01693   }
01694 #else /* ! HAVE_GETPWNAM_R */
01695   {
01696     /* I guess we're screwed on thread safety here */
01697     struct group *g;
01698 
01699     g = getgrnam (group_c_str);
01700 
01701     if (g != NULL)
01702       {
01703         return fill_user_info_from_group (g, info, error);
01704       }
01705     else
01706       {
01707         dbus_set_error (error, _dbus_error_from_errno (errno),
01708                         "Group %s unknown or failed to look it up\n",
01709                         group_c_str ? group_c_str : "???");
01710         return FALSE;
01711       }
01712   }
01713 #endif  /* ! HAVE_GETPWNAM_R */
01714 }
01715 
01725 dbus_bool_t
01726 _dbus_group_info_fill (DBusGroupInfo    *info,
01727                        const DBusString *groupname,
01728                        DBusError        *error)
01729 {
01730   return fill_group_info (info, DBUS_GID_UNSET,
01731                           groupname, error);
01732 
01733 }
01734 
01744 dbus_bool_t
01745 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01746                            dbus_gid_t     gid,
01747                            DBusError     *error)
01748 {
01749   return fill_group_info (info, gid, NULL, error);
01750 }
01751 
01757 void
01758 _dbus_group_info_free (DBusGroupInfo    *info)
01759 {
01760   dbus_free (info->groupname);
01761 }
01762 
01769 void
01770 _dbus_credentials_clear (DBusCredentials *credentials)
01771 {
01772   credentials->pid = DBUS_PID_UNSET;
01773   credentials->uid = DBUS_UID_UNSET;
01774   credentials->gid = DBUS_GID_UNSET;
01775 }
01776 
01782 void
01783 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01784 {
01785   /* The POSIX spec certainly doesn't promise this, but
01786    * we need these assertions to fail as soon as we're wrong about
01787    * it so we can do the porting fixups
01788    */
01789   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01790   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01791   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01792   
01793   credentials->pid = getpid ();
01794   credentials->uid = getuid ();
01795   credentials->gid = getgid ();
01796 }
01797 
01806 dbus_bool_t
01807 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01808                          const DBusCredentials *provided_credentials)
01809 {
01810   if (provided_credentials->uid == DBUS_UID_UNSET)
01811     return FALSE;
01812   else if (expected_credentials->uid == DBUS_UID_UNSET)
01813     return FALSE;
01814   else if (provided_credentials->uid == 0)
01815     return TRUE;
01816   else if (provided_credentials->uid == expected_credentials->uid)
01817     return TRUE;
01818   else
01819     return FALSE;
01820 }
01821 
01826 unsigned long
01827 _dbus_getpid (void)
01828 {
01829   return getpid ();
01830 }
01831 
01835 dbus_uid_t
01836 _dbus_getuid (void)
01837 {
01838   return getuid ();
01839 }
01840 
01844 dbus_gid_t
01845 _dbus_getgid (void)
01846 {
01847   return getgid ();
01848 }
01849 
01850 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01851 
01852 #ifdef DBUS_USE_ATOMIC_INT_486
01853 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
01854 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
01855 static inline dbus_int32_t
01856 atomic_exchange_and_add (DBusAtomic            *atomic,
01857                          volatile dbus_int32_t  val)
01858 {
01859   register dbus_int32_t result;
01860 
01861   __asm__ __volatile__ ("lock; xaddl %0,%1"
01862                         : "=r" (result), "=m" (atomic->value)
01863                         : "0" (val), "m" (atomic->value));
01864   return result;
01865 }
01866 #endif
01867 
01876 dbus_int32_t
01877 _dbus_atomic_inc (DBusAtomic *atomic)
01878 {
01879 #ifdef DBUS_USE_ATOMIC_INT_486
01880   return atomic_exchange_and_add (atomic, 1);
01881 #else
01882   dbus_int32_t res;
01883   _DBUS_LOCK (atomic);
01884   res = atomic->value;
01885   atomic->value += 1;
01886   _DBUS_UNLOCK (atomic);
01887   return res;
01888 #endif
01889 }
01890 
01899 dbus_int32_t
01900 _dbus_atomic_dec (DBusAtomic *atomic)
01901 {
01902 #ifdef DBUS_USE_ATOMIC_INT_486
01903   return atomic_exchange_and_add (atomic, -1);
01904 #else
01905   dbus_int32_t res;
01906   
01907   _DBUS_LOCK (atomic);
01908   res = atomic->value;
01909   atomic->value -= 1;
01910   _DBUS_UNLOCK (atomic);
01911   return res;
01912 #endif
01913 }
01914 
01925 int
01926 _dbus_poll (DBusPollFD *fds,
01927             int         n_fds,
01928             int         timeout_milliseconds)
01929 {
01930 #ifdef HAVE_POLL
01931   /* This big thing is a constant expression and should get optimized
01932    * out of existence. So it's more robust than a configure check at
01933    * no cost.
01934    */
01935   if (_DBUS_POLLIN == POLLIN &&
01936       _DBUS_POLLPRI == POLLPRI &&
01937       _DBUS_POLLOUT == POLLOUT &&
01938       _DBUS_POLLERR == POLLERR &&
01939       _DBUS_POLLHUP == POLLHUP &&
01940       _DBUS_POLLNVAL == POLLNVAL &&
01941       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01942       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01943       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01944       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01945       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01946       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01947       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01948     {
01949       return poll ((struct pollfd*) fds,
01950                    n_fds, 
01951                    timeout_milliseconds);
01952     }
01953   else
01954     {
01955       /* We have to convert the DBusPollFD to an array of
01956        * struct pollfd, poll, and convert back.
01957        */
01958       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01959       return -1;
01960     }
01961 #else /* ! HAVE_POLL */
01962 
01963   fd_set read_set, write_set, err_set;
01964   int max_fd = 0;
01965   int i;
01966   struct timeval tv;
01967   int ready;
01968   
01969   FD_ZERO (&read_set);
01970   FD_ZERO (&write_set);
01971   FD_ZERO (&err_set);
01972 
01973   for (i = 0; i < n_fds; i++)
01974     {
01975       DBusPollFD f = fds[i];
01976 
01977       if (f.events & _DBUS_POLLIN)
01978         FD_SET (f.fd, &read_set);
01979 
01980       if (f.events & _DBUS_POLLOUT)
01981         FD_SET (f.fd, &write_set);
01982 
01983       FD_SET (f.fd, &err_set);
01984 
01985       max_fd = MAX (max_fd, f.fd);
01986     }
01987     
01988   tv.tv_sec = timeout_milliseconds / 1000;
01989   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01990 
01991   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01992 
01993   if (ready > 0)
01994     {
01995       for (i = 0; i < n_fds; i++)
01996         {
01997           DBusPollFD f = fds[i];
01998 
01999           f.revents = 0;
02000 
02001           if (FD_ISSET (f.fd, &read_set))
02002             f.revents |= _DBUS_POLLIN;
02003 
02004           if (FD_ISSET (f.fd, &write_set))
02005             f.revents |= _DBUS_POLLOUT;
02006 
02007           if (FD_ISSET (f.fd, &err_set))
02008             f.revents |= _DBUS_POLLERR;
02009         }
02010     }
02011 
02012   return ready;
02013 #endif
02014 }
02015 
02017 #define NANOSECONDS_PER_SECOND       1000000000
02018 
02019 #define MICROSECONDS_PER_SECOND      1000000
02020 
02021 #define MILLISECONDS_PER_SECOND      1000
02022 
02023 #define NANOSECONDS_PER_MILLISECOND  1000000
02024 
02025 #define MICROSECONDS_PER_MILLISECOND 1000
02026 
02031 void
02032 _dbus_sleep_milliseconds (int milliseconds)
02033 {
02034 #ifdef HAVE_NANOSLEEP
02035   struct timespec req;
02036   struct timespec rem;
02037 
02038   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02039   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02040   rem.tv_sec = 0;
02041   rem.tv_nsec = 0;
02042 
02043   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02044     req = rem;
02045 #elif defined (HAVE_USLEEP)
02046   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02047 #else /* ! HAVE_USLEEP */
02048   sleep (MAX (milliseconds / 1000, 1));
02049 #endif
02050 }
02051 
02058 void
02059 _dbus_get_current_time (long *tv_sec,
02060                         long *tv_usec)
02061 {
02062   struct timeval t;
02063 
02064   gettimeofday (&t, NULL);
02065 
02066   if (tv_sec)
02067     *tv_sec = t.tv_sec;
02068   if (tv_usec)
02069     *tv_usec = t.tv_usec;
02070 }
02071 
02082 dbus_bool_t
02083 _dbus_file_get_contents (DBusString       *str,
02084                          const DBusString *filename,
02085                          DBusError        *error)
02086 {
02087   int fd;
02088   struct stat sb;
02089   int orig_len;
02090   int total;
02091   const char *filename_c;
02092 
02093   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02094   
02095   filename_c = _dbus_string_get_const_data (filename);
02096   
02097   /* O_BINARY useful on Cygwin */
02098   fd = open (filename_c, O_RDONLY | O_BINARY);
02099   if (fd < 0)
02100     {
02101       dbus_set_error (error, _dbus_error_from_errno (errno),
02102                       "Failed to open \"%s\": %s",
02103                       filename_c,
02104                       _dbus_strerror (errno));
02105       return FALSE;
02106     }
02107 
02108   if (fstat (fd, &sb) < 0)
02109     {
02110       dbus_set_error (error, _dbus_error_from_errno (errno),
02111                       "Failed to stat \"%s\": %s",
02112                       filename_c,
02113                       _dbus_strerror (errno));
02114 
02115       _dbus_verbose ("fstat() failed: %s",
02116                      _dbus_strerror (errno));
02117       
02118       close (fd);
02119       
02120       return FALSE;
02121     }
02122 
02123   if (sb.st_size > _DBUS_ONE_MEGABYTE)
02124     {
02125       dbus_set_error (error, DBUS_ERROR_FAILED,
02126                       "File size %lu of \"%s\" is too large.",
02127                       filename_c, (unsigned long) sb.st_size);
02128       close (fd);
02129       return FALSE;
02130     }
02131   
02132   total = 0;
02133   orig_len = _dbus_string_get_length (str);
02134   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02135     {
02136       int bytes_read;
02137 
02138       while (total < (int) sb.st_size)
02139         {
02140           bytes_read = _dbus_read (fd, str,
02141                                    sb.st_size - total);
02142           if (bytes_read <= 0)
02143             {
02144               dbus_set_error (error, _dbus_error_from_errno (errno),
02145                               "Error reading \"%s\": %s",
02146                               filename_c,
02147                               _dbus_strerror (errno));
02148 
02149               _dbus_verbose ("read() failed: %s",
02150                              _dbus_strerror (errno));
02151               
02152               close (fd);
02153               _dbus_string_set_length (str, orig_len);
02154               return FALSE;
02155             }
02156           else
02157             total += bytes_read;
02158         }
02159 
02160       close (fd);
02161       return TRUE;
02162     }
02163   else if (sb.st_size != 0)
02164     {
02165       _dbus_verbose ("Can only open regular files at the moment.\n");
02166       dbus_set_error (error, DBUS_ERROR_FAILED,
02167                       "\"%s\" is not a regular file",
02168                       filename_c);
02169       close (fd);
02170       return FALSE;
02171     }
02172   else
02173     {
02174       close (fd);
02175       return TRUE;
02176     }
02177 }
02178 
02188 dbus_bool_t
02189 _dbus_string_save_to_file (const DBusString *str,
02190                            const DBusString *filename,
02191                            DBusError        *error)
02192 {
02193   int fd;
02194   int bytes_to_write;
02195   const char *filename_c;
02196   DBusString tmp_filename;
02197   const char *tmp_filename_c;
02198   int total;
02199   dbus_bool_t need_unlink;
02200   dbus_bool_t retval;
02201 
02202   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02203   
02204   fd = -1;
02205   retval = FALSE;
02206   need_unlink = FALSE;
02207   
02208   if (!_dbus_string_init (&tmp_filename))
02209     {
02210       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02211       return FALSE;
02212     }
02213 
02214   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02215     {
02216       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02217       _dbus_string_free (&tmp_filename);
02218       return FALSE;
02219     }
02220   
02221   if (!_dbus_string_append (&tmp_filename, "."))
02222     {
02223       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02224       _dbus_string_free (&tmp_filename);
02225       return FALSE;
02226     }
02227 
02228 #define N_TMP_FILENAME_RANDOM_BYTES 8
02229   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02230     {
02231       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02232       _dbus_string_free (&tmp_filename);
02233       return FALSE;
02234     }
02235     
02236   filename_c = _dbus_string_get_const_data (filename);
02237   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02238 
02239   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02240              0600);
02241   if (fd < 0)
02242     {
02243       dbus_set_error (error, _dbus_error_from_errno (errno),
02244                       "Could not create %s: %s", tmp_filename_c,
02245                       _dbus_strerror (errno));
02246       goto out;
02247     }
02248 
02249   need_unlink = TRUE;
02250   
02251   total = 0;
02252   bytes_to_write = _dbus_string_get_length (str);
02253 
02254   while (total < bytes_to_write)
02255     {
02256       int bytes_written;
02257 
02258       bytes_written = _dbus_write (fd, str, total,
02259                                    bytes_to_write - total);
02260 
02261       if (bytes_written <= 0)
02262         {
02263           dbus_set_error (error, _dbus_error_from_errno (errno),
02264                           "Could not write to %s: %s", tmp_filename_c,
02265                           _dbus_strerror (errno));
02266           
02267           goto out;
02268         }
02269 
02270       total += bytes_written;
02271     }
02272 
02273   if (close (fd) < 0)
02274     {
02275       dbus_set_error (error, _dbus_error_from_errno (errno),
02276                       "Could not close file %s: %s",
02277                       tmp_filename_c, _dbus_strerror (errno));
02278 
02279       goto out;
02280     }
02281 
02282   fd = -1;
02283   
02284   if (rename (tmp_filename_c, filename_c) < 0)
02285     {
02286       dbus_set_error (error, _dbus_error_from_errno (errno),
02287                       "Could not rename %s to %s: %s",
02288                       tmp_filename_c, filename_c,
02289                       _dbus_strerror (errno));
02290 
02291       goto out;
02292     }
02293 
02294   need_unlink = FALSE;
02295   
02296   retval = TRUE;
02297   
02298  out:
02299   /* close first, then unlink, to prevent ".nfs34234235" garbage
02300    * files
02301    */
02302 
02303   if (fd >= 0)
02304     close (fd);
02305         
02306   if (need_unlink && unlink (tmp_filename_c) < 0)
02307     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02308                    tmp_filename_c, _dbus_strerror (errno));
02309 
02310   _dbus_string_free (&tmp_filename);
02311 
02312   if (!retval)
02313     _DBUS_ASSERT_ERROR_IS_SET (error);
02314   
02315   return retval;
02316 }
02317 
02324 dbus_bool_t
02325 _dbus_create_file_exclusively (const DBusString *filename,
02326                                DBusError        *error)
02327 {
02328   int fd;
02329   const char *filename_c;
02330 
02331   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02332   
02333   filename_c = _dbus_string_get_const_data (filename);
02334   
02335   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02336              0600);
02337   if (fd < 0)
02338     {
02339       dbus_set_error (error,
02340                       DBUS_ERROR_FAILED,
02341                       "Could not create file %s: %s\n",
02342                       filename_c,
02343                       _dbus_strerror (errno));
02344       return FALSE;
02345     }
02346 
02347   if (close (fd) < 0)
02348     {
02349       dbus_set_error (error,
02350                       DBUS_ERROR_FAILED,
02351                       "Could not close file %s: %s\n",
02352                       filename_c,
02353                       _dbus_strerror (errno));
02354       return FALSE;
02355     }
02356   
02357   return TRUE;
02358 }
02359 
02368 dbus_bool_t
02369 _dbus_delete_file (const DBusString *filename,
02370                    DBusError        *error)
02371 {
02372   const char *filename_c;
02373 
02374   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02375   
02376   filename_c = _dbus_string_get_const_data (filename);
02377 
02378   if (unlink (filename_c) < 0)
02379     {
02380       dbus_set_error (error, DBUS_ERROR_FAILED,
02381                       "Failed to delete file %s: %s\n",
02382                       filename_c, _dbus_strerror (errno));
02383       return FALSE;
02384     }
02385   else
02386     return TRUE;
02387 }
02388 
02397 dbus_bool_t
02398 _dbus_create_directory (const DBusString *filename,
02399                         DBusError        *error)
02400 {
02401   const char *filename_c;
02402 
02403   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02404   
02405   filename_c = _dbus_string_get_const_data (filename);
02406 
02407   if (mkdir (filename_c, 0700) < 0)
02408     {
02409       if (errno == EEXIST)
02410         return TRUE;
02411       
02412       dbus_set_error (error, DBUS_ERROR_FAILED,
02413                       "Failed to create directory %s: %s\n",
02414                       filename_c, _dbus_strerror (errno));
02415       return FALSE;
02416     }
02417   else
02418     return TRUE;
02419 }
02420 
02431 dbus_bool_t
02432 _dbus_concat_dir_and_file (DBusString       *dir,
02433                            const DBusString *next_component)
02434 {
02435   dbus_bool_t dir_ends_in_slash;
02436   dbus_bool_t file_starts_with_slash;
02437 
02438   if (_dbus_string_get_length (dir) == 0 ||
02439       _dbus_string_get_length (next_component) == 0)
02440     return TRUE;
02441   
02442   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02443                                                     _dbus_string_get_length (dir) - 1);
02444 
02445   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02446 
02447   if (dir_ends_in_slash && file_starts_with_slash)
02448     {
02449       _dbus_string_shorten (dir, 1);
02450     }
02451   else if (!(dir_ends_in_slash || file_starts_with_slash))
02452     {
02453       if (!_dbus_string_append_byte (dir, '/'))
02454         return FALSE;
02455     }
02456 
02457   return _dbus_string_copy (next_component, 0, dir,
02458                             _dbus_string_get_length (dir));
02459 }
02460 
02467 dbus_bool_t
02468 _dbus_string_get_dirname  (const DBusString *filename,
02469                            DBusString       *dirname)
02470 {
02471   int sep;
02472   
02473   _dbus_assert (filename != dirname);
02474   _dbus_assert (filename != NULL);
02475   _dbus_assert (dirname != NULL);
02476 
02477   /* Ignore any separators on the end */
02478   sep = _dbus_string_get_length (filename);
02479   if (sep == 0)
02480     return _dbus_string_append (dirname, "."); /* empty string passed in */
02481     
02482   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02483     --sep;
02484 
02485   _dbus_assert (sep >= 0);
02486   
02487   if (sep == 0)
02488     return _dbus_string_append (dirname, "/");
02489   
02490   /* Now find the previous separator */
02491   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02492   if (sep < 0)
02493     return _dbus_string_append (dirname, ".");
02494   
02495   /* skip multiple separators */
02496   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02497     --sep;
02498 
02499   _dbus_assert (sep >= 0);
02500   
02501   if (sep == 0 &&
02502       _dbus_string_get_byte (filename, 0) == '/')
02503     return _dbus_string_append (dirname, "/");
02504   else
02505     return _dbus_string_copy_len (filename, 0, sep - 0,
02506                                   dirname, _dbus_string_get_length (dirname));
02507 }
02508 
02515 dbus_bool_t
02516 _dbus_path_is_absolute (const DBusString *filename)
02517 {
02518   if (_dbus_string_get_length (filename) > 0)
02519     return _dbus_string_get_byte (filename, 0) == '/';
02520   else
02521     return FALSE;
02522 }
02523 
02527 struct DBusDirIter
02528 {
02529   DIR *d; 
02531 };
02532 
02540 DBusDirIter*
02541 _dbus_directory_open (const DBusString *filename,
02542                       DBusError        *error)
02543 {
02544   DIR *d;
02545   DBusDirIter *iter;
02546   const char *filename_c;
02547 
02548   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02549   
02550   filename_c = _dbus_string_get_const_data (filename);
02551 
02552   d = opendir (filename_c);
02553   if (d == NULL)
02554     {
02555       dbus_set_error (error, _dbus_error_from_errno (errno),
02556                       "Failed to read directory \"%s\": %s",
02557                       filename_c,
02558                       _dbus_strerror (errno));
02559       return NULL;
02560     }
02561   iter = dbus_new0 (DBusDirIter, 1);
02562   if (iter == NULL)
02563     {
02564       closedir (d);
02565       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02566                       "Could not allocate memory for directory iterator");
02567       return NULL;
02568     }
02569 
02570   iter->d = d;
02571 
02572   return iter;
02573 }
02574 
02588 dbus_bool_t
02589 _dbus_directory_get_next_file (DBusDirIter      *iter,
02590                                DBusString       *filename,
02591                                DBusError        *error)
02592 {
02593   struct dirent *ent;
02594 
02595   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02596   
02597  again:
02598   errno = 0;
02599   ent = readdir (iter->d);
02600   if (ent == NULL)
02601     {
02602       if (errno != 0)
02603         dbus_set_error (error,
02604                         _dbus_error_from_errno (errno),
02605                         "%s", _dbus_strerror (errno));
02606       return FALSE;
02607     }
02608   else if (ent->d_name[0] == '.' &&
02609            (ent->d_name[1] == '\0' ||
02610             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02611     goto again;
02612   else
02613     {
02614       _dbus_string_set_length (filename, 0);
02615       if (!_dbus_string_append (filename, ent->d_name))
02616         {
02617           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02618                           "No memory to read directory entry");
02619           return FALSE;
02620         }
02621       else
02622         return TRUE;
02623     }
02624 }
02625 
02629 void
02630 _dbus_directory_close (DBusDirIter *iter)
02631 {
02632   closedir (iter->d);
02633   dbus_free (iter);
02634 }
02635 
02636 static dbus_bool_t
02637 pseudorandom_generate_random_bytes (DBusString *str,
02638                                     int         n_bytes)
02639 {
02640   int old_len;
02641   unsigned long tv_usec;
02642   int i;
02643   
02644   old_len = _dbus_string_get_length (str);
02645 
02646   /* fall back to pseudorandom */
02647   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02648                  n_bytes);
02649   
02650   _dbus_get_current_time (NULL, &tv_usec);
02651   srand (tv_usec);
02652   
02653   i = 0;
02654   while (i < n_bytes)
02655     {
02656       double r;
02657       unsigned int b;
02658           
02659       r = rand ();
02660       b = (r / (double) RAND_MAX) * 255.0;
02661           
02662       if (!_dbus_string_append_byte (str, b))
02663         goto failed;
02664           
02665       ++i;
02666     }
02667 
02668   return TRUE;
02669 
02670  failed:
02671   _dbus_string_set_length (str, old_len);
02672   return FALSE;
02673 }
02674 
02683 dbus_bool_t
02684 _dbus_generate_random_bytes (DBusString *str,
02685                              int         n_bytes)
02686 {
02687   int old_len;
02688   int fd;
02689 
02690   /* FALSE return means "no memory", if it could
02691    * mean something else then we'd need to return
02692    * a DBusError. So we always fall back to pseudorandom
02693    * if the I/O fails.
02694    */
02695   
02696   old_len = _dbus_string_get_length (str);
02697   fd = -1;
02698 
02699   /* note, urandom on linux will fall back to pseudorandom */
02700   fd = open ("/dev/urandom", O_RDONLY);
02701   if (fd < 0)
02702     return pseudorandom_generate_random_bytes (str, n_bytes);
02703 
02704   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02705     {
02706       close (fd);
02707       _dbus_string_set_length (str, old_len);
02708       return pseudorandom_generate_random_bytes (str, n_bytes);
02709     }
02710 
02711   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02712                  n_bytes);
02713   
02714   close (fd);
02715   
02716   return TRUE;
02717 }
02718 
02727 dbus_bool_t
02728 _dbus_generate_random_ascii (DBusString *str,
02729                              int         n_bytes)
02730 {
02731   static const char letters[] =
02732     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02733   int i;
02734   int len;
02735   
02736   if (!_dbus_generate_random_bytes (str, n_bytes))
02737     return FALSE;
02738   
02739   len = _dbus_string_get_length (str);
02740   i = len - n_bytes;
02741   while (i < len)
02742     {
02743       _dbus_string_set_byte (str, i,
02744                              letters[_dbus_string_get_byte (str, i) %
02745                                      (sizeof (letters) - 1)]);
02746 
02747       ++i;
02748     }
02749 
02750   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02751                                              n_bytes));
02752 
02753   return TRUE;
02754 }
02755 
02763 const char*
02764 _dbus_strerror (int error_number)
02765 {
02766   const char *msg;
02767   
02768   msg = strerror (error_number);
02769   if (msg == NULL)
02770     msg = "unknown";
02771 
02772   return msg;
02773 }
02774 
02778 void
02779 _dbus_disable_sigpipe (void)
02780 {
02781   signal (SIGPIPE, SIG_IGN);
02782 }
02783 
02791 void
02792 _dbus_fd_set_close_on_exec (int fd)
02793 {
02794   int val;
02795   
02796   val = fcntl (fd, F_GETFD, 0);
02797   
02798   if (val < 0)
02799     return;
02800 
02801   val |= FD_CLOEXEC;
02802   
02803   fcntl (fd, F_SETFD, val);
02804 }
02805 
02815 const char*
02816 _dbus_error_from_errno (int error_number)
02817 {
02818   switch (error_number)
02819     {
02820     case 0:
02821       return DBUS_ERROR_FAILED;
02822       
02823 #ifdef EPROTONOSUPPORT
02824     case EPROTONOSUPPORT:
02825       return DBUS_ERROR_NOT_SUPPORTED;
02826 #endif
02827 #ifdef EAFNOSUPPORT
02828     case EAFNOSUPPORT:
02829       return DBUS_ERROR_NOT_SUPPORTED;
02830 #endif
02831 #ifdef ENFILE
02832     case ENFILE:
02833       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
02834 #endif
02835 #ifdef EMFILE
02836     case EMFILE:
02837       return DBUS_ERROR_LIMITS_EXCEEDED;
02838 #endif
02839 #ifdef EACCES
02840     case EACCES:
02841       return DBUS_ERROR_ACCESS_DENIED;
02842 #endif
02843 #ifdef EPERM
02844     case EPERM:
02845       return DBUS_ERROR_ACCESS_DENIED;
02846 #endif
02847 #ifdef ENOBUFS
02848     case ENOBUFS:
02849       return DBUS_ERROR_NO_MEMORY;
02850 #endif
02851 #ifdef ENOMEM
02852     case ENOMEM:
02853       return DBUS_ERROR_NO_MEMORY;
02854 #endif
02855 #ifdef EINVAL
02856     case EINVAL:
02857       return DBUS_ERROR_FAILED;
02858 #endif
02859 #ifdef EBADF
02860     case EBADF:
02861       return DBUS_ERROR_FAILED;
02862 #endif
02863 #ifdef EFAULT
02864     case EFAULT:
02865       return DBUS_ERROR_FAILED;
02866 #endif
02867 #ifdef ENOTSOCK
02868     case ENOTSOCK:
02869       return DBUS_ERROR_FAILED;
02870 #endif
02871 #ifdef EISCONN
02872     case EISCONN:
02873       return DBUS_ERROR_FAILED;
02874 #endif
02875 #ifdef ECONNREFUSED
02876     case ECONNREFUSED:
02877       return DBUS_ERROR_NO_SERVER;
02878 #endif
02879 #ifdef ETIMEDOUT
02880     case ETIMEDOUT:
02881       return DBUS_ERROR_TIMEOUT;
02882 #endif
02883 #ifdef ENETUNREACH
02884     case ENETUNREACH:
02885       return DBUS_ERROR_NO_NETWORK;
02886 #endif
02887 #ifdef EADDRINUSE
02888     case EADDRINUSE:
02889       return DBUS_ERROR_ADDRESS_IN_USE;
02890 #endif
02891 #ifdef EEXIST
02892     case EEXIST:
02893       return DBUS_ERROR_FILE_NOT_FOUND;
02894 #endif
02895 #ifdef ENOENT
02896     case ENOENT:
02897       return DBUS_ERROR_FILE_NOT_FOUND;
02898 #endif
02899     }
02900 
02901   return DBUS_ERROR_FAILED;
02902 }
02903 
02909 void
02910 _dbus_exit (int code)
02911 {
02912   _exit (code);
02913 }
02914 
02923 dbus_bool_t
02924 _dbus_stat (const DBusString *filename,
02925             DBusStat         *statbuf,
02926             DBusError        *error)
02927 {
02928   const char *filename_c;
02929   struct stat sb;
02930 
02931   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02932   
02933   filename_c = _dbus_string_get_const_data (filename);
02934 
02935   if (stat (filename_c, &sb) < 0)
02936     {
02937       dbus_set_error (error, _dbus_error_from_errno (errno),
02938                       "%s", _dbus_strerror (errno));
02939       return FALSE;
02940     }
02941 
02942   statbuf->mode = sb.st_mode;
02943   statbuf->nlink = sb.st_nlink;
02944   statbuf->uid = sb.st_uid;
02945   statbuf->gid = sb.st_gid;
02946   statbuf->size = sb.st_size;
02947   statbuf->atime = sb.st_atime;
02948   statbuf->mtime = sb.st_mtime;
02949   statbuf->ctime = sb.st_ctime;
02950 
02951   return TRUE;
02952 }
02953 
02964 dbus_bool_t
02965 _dbus_full_duplex_pipe (int        *fd1,
02966                         int        *fd2,
02967                         dbus_bool_t blocking,
02968                         DBusError  *error)
02969 {
02970 #ifdef HAVE_SOCKETPAIR
02971   int fds[2];
02972 
02973   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02974   
02975   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02976     {
02977       dbus_set_error (error, _dbus_error_from_errno (errno),
02978                       "Could not create full-duplex pipe");
02979       return FALSE;
02980     }
02981 
02982   if (!blocking &&
02983       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02984        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02985     {
02986       dbus_set_error (error, _dbus_error_from_errno (errno),
02987                       "Could not set full-duplex pipe nonblocking");
02988       
02989       close (fds[0]);
02990       close (fds[1]);
02991       
02992       return FALSE;
02993     }
02994   
02995   *fd1 = fds[0];
02996   *fd2 = fds[1];
02997   
02998   return TRUE;  
02999 #else
03000   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03001   dbus_set_error (error, DBUS_ERROR_FAILED,
03002                   "_dbus_full_duplex_pipe() not implemented on this OS");
03003   return FALSE;
03004 #endif
03005 }
03006 
03014 dbus_bool_t
03015 _dbus_close (int        fd,
03016              DBusError *error)
03017 {
03018   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03019   
03020  again:
03021   if (close (fd) < 0)
03022     {
03023       if (errno == EINTR)
03024         goto again;
03025 
03026       dbus_set_error (error, _dbus_error_from_errno (errno),
03027                       "Could not close fd %d", fd);
03028       return FALSE;
03029     }
03030 
03031   return TRUE;
03032 }
03033 
03041 dbus_bool_t
03042 _dbus_set_fd_nonblocking (int             fd,
03043                           DBusError      *error)
03044 {
03045   int val;
03046 
03047   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03048   
03049   val = fcntl (fd, F_GETFL, 0);
03050   if (val < 0)
03051     {
03052       dbus_set_error (error, _dbus_error_from_errno (errno),
03053                       "Failed to get flags from file descriptor %d: %s",
03054                       fd, _dbus_strerror (errno));
03055       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03056                      _dbus_strerror (errno));
03057       return FALSE;
03058     }
03059 
03060   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03061     {
03062       dbus_set_error (error, _dbus_error_from_errno (errno),
03063                       "Failed to set nonblocking flag of file descriptor %d: %s",
03064                       fd, _dbus_strerror (errno));
03065       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03066                      fd, _dbus_strerror (errno));
03067 
03068       return FALSE;
03069     }
03070 
03071   return TRUE;
03072 }
03073 
03079 void
03080 _dbus_print_backtrace (void)
03081 {
03082 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03083   void *bt[500];
03084   int bt_size;
03085   int i;
03086   char **syms;
03087   
03088   bt_size = backtrace (bt, 500);
03089 
03090   syms = backtrace_symbols (bt, bt_size);
03091   
03092   i = 0;
03093   while (i < bt_size)
03094     {
03095       _dbus_verbose ("  %s\n", syms[i]);
03096       ++i;
03097     }
03098 
03099   free (syms);
03100 #else
03101   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
03102 #endif
03103 }
03104 
03112 dbus_bool_t
03113 _dbus_become_daemon (const DBusString *pidfile,
03114                      DBusError        *error)
03115 {
03116   const char *s;
03117   pid_t child_pid;
03118   int dev_null_fd;
03119 
03120   _dbus_verbose ("Becoming a daemon...\n");
03121 
03122   _dbus_verbose ("chdir to /\n");
03123   if (chdir ("/") < 0)
03124     {
03125       dbus_set_error (error, DBUS_ERROR_FAILED,
03126                       "Could not chdir() to root directory");
03127       return FALSE;
03128     }
03129 
03130   _dbus_verbose ("forking...\n");
03131   switch ((child_pid = fork ()))
03132     {
03133     case -1:
03134       _dbus_verbose ("fork failed\n");
03135       dbus_set_error (error, _dbus_error_from_errno (errno),
03136                       "Failed to fork daemon: %s", _dbus_strerror (errno));
03137       return FALSE;
03138       break;
03139 
03140     case 0:
03141       _dbus_verbose ("in child, closing std file descriptors\n");
03142 
03143       /* silently ignore failures here, if someone
03144        * doesn't have /dev/null we may as well try
03145        * to continue anyhow
03146        */
03147       
03148       dev_null_fd = open ("/dev/null", O_RDWR);
03149       if (dev_null_fd >= 0)
03150         {
03151           dup2 (dev_null_fd, 0);
03152           dup2 (dev_null_fd, 1);
03153           
03154           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03155           if (s == NULL || *s == '\0')
03156             dup2 (dev_null_fd, 2);
03157           else
03158             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
03159         }
03160 
03161       /* Get a predictable umask */
03162       _dbus_verbose ("setting umask\n");
03163       umask (022);
03164       break;
03165 
03166     default:
03167       if (pidfile)
03168         {
03169           _dbus_verbose ("parent writing pid file\n");
03170           if (!_dbus_write_pid_file (pidfile,
03171                                      child_pid,
03172                                      error))
03173             {
03174               _dbus_verbose ("pid file write failed, killing child\n");
03175               kill (child_pid, SIGTERM);
03176               return FALSE;
03177             }
03178         }
03179       _dbus_verbose ("parent exiting\n");
03180       _exit (0);
03181       break;
03182     }
03183 
03184   _dbus_verbose ("calling setsid()\n");
03185   if (setsid () == -1)
03186     _dbus_assert_not_reached ("setsid() failed");
03187   
03188   return TRUE;
03189 }
03190 
03199 dbus_bool_t
03200 _dbus_write_pid_file (const DBusString *filename,
03201                       unsigned long     pid,
03202                       DBusError        *error)
03203 {
03204   const char *cfilename;
03205   int fd;
03206   FILE *f;
03207 
03208   cfilename = _dbus_string_get_const_data (filename);
03209   
03210   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03211   
03212   if (fd < 0)
03213     {
03214       dbus_set_error (error, _dbus_error_from_errno (errno),
03215                       "Failed to open \"%s\": %s", cfilename,
03216                       _dbus_strerror (errno));
03217       return FALSE;
03218     }
03219 
03220   if ((f = fdopen (fd, "w")) == NULL)
03221     {
03222       dbus_set_error (error, _dbus_error_from_errno (errno),
03223                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03224       close (fd);
03225       return FALSE;
03226     }
03227   
03228   if (fprintf (f, "%lu\n", pid) < 0)
03229     {
03230       dbus_set_error (error, _dbus_error_from_errno (errno),
03231                       "Failed to write to \"%s\": %s", cfilename,
03232                       _dbus_strerror (errno));
03233       return FALSE;
03234     }
03235 
03236   if (fclose (f) == EOF)
03237     {
03238       dbus_set_error (error, _dbus_error_from_errno (errno),
03239                       "Failed to close \"%s\": %s", cfilename,
03240                       _dbus_strerror (errno));
03241       return FALSE;
03242     }
03243   
03244   return TRUE;
03245 }
03246 
03255 dbus_bool_t
03256 _dbus_change_identity  (dbus_uid_t     uid,
03257                         dbus_gid_t     gid,
03258                         DBusError     *error)
03259 {
03260   /* Set GID first, or the setuid may remove our permission
03261    * to change the GID
03262    */
03263   if (setgid (gid) < 0)
03264     {
03265       dbus_set_error (error, _dbus_error_from_errno (errno),
03266                       "Failed to set GID to %lu: %s", gid,
03267                       _dbus_strerror (errno));
03268       return FALSE;
03269     }
03270   
03271   if (setuid (uid) < 0)
03272     {
03273       dbus_set_error (error, _dbus_error_from_errno (errno),
03274                       "Failed to set UID to %lu: %s", uid,
03275                       _dbus_strerror (errno));
03276       return FALSE;
03277     }
03278   
03279   return TRUE;
03280 }
03281 
03287 void
03288 _dbus_set_signal_handler (int               sig,
03289                           DBusSignalHandler handler)
03290 {
03291   struct sigaction act;
03292   sigset_t empty_mask;
03293   
03294   sigemptyset (&empty_mask);
03295   act.sa_handler = handler;
03296   act.sa_mask    = empty_mask;
03297   act.sa_flags   = 0;
03298   sigaction (sig,  &act, 0);
03299 }
03300 
03301 
03302 #ifdef DBUS_BUILD_TESTS
03303 #include <stdlib.h>
03304 static void
03305 check_dirname (const char *filename,
03306                const char *dirname)
03307 {
03308   DBusString f, d;
03309   
03310   _dbus_string_init_const (&f, filename);
03311 
03312   if (!_dbus_string_init (&d))
03313     _dbus_assert_not_reached ("no memory");
03314 
03315   if (!_dbus_string_get_dirname (&f, &d))
03316     _dbus_assert_not_reached ("no memory");
03317 
03318   if (!_dbus_string_equal_c_str (&d, dirname))
03319     {
03320       _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03321                   filename,
03322                   _dbus_string_get_const_data (&d),
03323                   dirname);
03324       exit (1);
03325     }
03326 
03327   _dbus_string_free (&d);
03328 }
03329 
03330 static void
03331 check_path_absolute (const char *path,
03332                      dbus_bool_t expected)
03333 {
03334   DBusString p;
03335 
03336   _dbus_string_init_const (&p, path);
03337 
03338   if (_dbus_path_is_absolute (&p) != expected)
03339     {
03340       _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03341                   path, expected, _dbus_path_is_absolute (&p));
03342       exit (1);
03343     }
03344 }
03345 
03351 dbus_bool_t
03352 _dbus_sysdeps_test (void)
03353 {
03354   DBusString str;
03355   double val;
03356   int pos;
03357   
03358   check_dirname ("foo", ".");
03359   check_dirname ("foo/bar", "foo");
03360   check_dirname ("foo//bar", "foo");
03361   check_dirname ("foo///bar", "foo");
03362   check_dirname ("foo/bar/", "foo");
03363   check_dirname ("foo//bar/", "foo");
03364   check_dirname ("foo///bar/", "foo");
03365   check_dirname ("foo/bar//", "foo");
03366   check_dirname ("foo//bar////", "foo");
03367   check_dirname ("foo///bar///////", "foo");
03368   check_dirname ("/foo", "/");
03369   check_dirname ("
03370   check_dirname ("/foo/bar", "/foo");
03371   check_dirname ("/foo//bar", "/foo");
03372   check_dirname ("/foo///bar", "/foo");
03373   check_dirname ("/", "/");
03374   check_dirname ("
03375   check_dirname ("", ".");  
03376 
03377 
03378   _dbus_string_init_const (&str, "3.5");
03379   if (!_dbus_string_parse_double (&str,
03380                                   0, &val, &pos))
03381     {
03382       _dbus_warn ("Failed to parse double");
03383       exit (1);
03384     }
03385   if (val != 3.5)
03386     {
03387       _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03388       exit (1);
03389     }
03390   if (pos != 3)
03391     {
03392       _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03393       exit (1);
03394     }
03395 
03396   _dbus_string_init_const (&str, "0xff");
03397   if (!_dbus_string_parse_double (&str,
03398                                   0, &val, &pos))
03399     {
03400       _dbus_warn ("Failed to parse double");
03401       exit (1);
03402     }
03403   if (val != 0xff)
03404     {
03405       _dbus_warn ("Failed to parse 0xff correctly, got: %f", val);
03406       exit (1);
03407     }
03408   if (pos != 4)
03409     {
03410       _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
03411       exit (1);
03412     }
03413   
03414   check_path_absolute ("/", TRUE);
03415   check_path_absolute ("/foo", TRUE);
03416   check_path_absolute ("", FALSE);
03417   check_path_absolute ("foo", FALSE);
03418   check_path_absolute ("foo/bar", FALSE);
03419   
03420   return TRUE;
03421 }
03422 #endif /* DBUS_BUILD_TESTS */
03423 

Generated on Tue Feb 10 18:14:09 2004 for D-BUS by doxygen 1.3.5