D-Bus  1.8.20
dbus-sysdeps.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2006  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-sysdeps.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-protocol.h"
00030 #include "dbus-string.h"
00031 #include "dbus-list.h"
00032 #include "dbus-misc.h"
00033 
00034 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
00035  * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
00036  *
00037  * These are the standard ANSI C headers...
00038  */
00039 #if HAVE_LOCALE_H
00040 #include <locale.h>
00041 #endif
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include <stdio.h>
00045 
00046 #ifdef HAVE_ERRNO_H
00047 #include <errno.h>
00048 #endif
00049 
00050 #ifdef DBUS_WIN
00051   #include <stdlib.h>
00052 #elif (defined __APPLE__)
00053 # include <crt_externs.h>
00054 # define environ (*_NSGetEnviron())
00055 #else
00056 extern char **environ;
00057 #endif
00058 
00076 void
00077 _dbus_abort (void)
00078 {
00079   const char *s;
00080   
00081   _dbus_print_backtrace ();
00082   
00083   s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00084   if (s && *s)
00085     {
00086       /* don't use _dbus_warn here since it can _dbus_abort() */
00087       fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
00088       _dbus_sleep_milliseconds (1000 * 180);
00089     }
00090   
00091   abort ();
00092   _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
00093 }
00094 
00113 dbus_bool_t
00114 dbus_setenv (const char *varname,
00115              const char *value)
00116 {
00117   _dbus_assert (varname != NULL);
00118   
00119   if (value == NULL)
00120     {
00121 #ifdef HAVE_UNSETENV
00122       unsetenv (varname);
00123       return TRUE;
00124 #else
00125       char *putenv_value;
00126       size_t len;
00127 
00128       len = strlen (varname);
00129 
00130       /* Use system malloc to avoid memleaks that dbus_malloc
00131        * will get upset about.
00132        */
00133       
00134       putenv_value = malloc (len + 2);
00135       if (putenv_value == NULL)
00136         return FALSE;
00137 
00138       strcpy (putenv_value, varname);
00139 #if defined(DBUS_WIN)
00140       strcat (putenv_value, "=");
00141 #endif
00142       
00143       return (putenv (putenv_value) == 0);
00144 #endif
00145     }
00146   else
00147     {
00148 #ifdef HAVE_SETENV
00149       return (setenv (varname, value, TRUE) == 0);
00150 #else
00151       char *putenv_value;
00152       size_t len;
00153       size_t varname_len;
00154       size_t value_len;
00155 
00156       varname_len = strlen (varname);
00157       value_len = strlen (value);
00158       
00159       len = varname_len + value_len + 1 /* '=' */ ;
00160 
00161       /* Use system malloc to avoid memleaks that dbus_malloc
00162        * will get upset about.
00163        */
00164       
00165       putenv_value = malloc (len + 1);
00166       if (putenv_value == NULL)
00167         return FALSE;
00168 
00169       strcpy (putenv_value, varname);
00170       strcpy (putenv_value + varname_len, "=");
00171       strcpy (putenv_value + varname_len + 1, value);
00172       
00173       return (putenv (putenv_value) == 0);
00174 #endif
00175     }
00176 }
00177 
00184 const char*
00185 _dbus_getenv (const char *varname)
00186 {  
00187   return getenv (varname);
00188 }
00189 
00195 dbus_bool_t
00196 _dbus_clearenv (void)
00197 {
00198   dbus_bool_t rc = TRUE;
00199 
00200 #ifdef HAVE_CLEARENV
00201   if (clearenv () != 0)
00202      rc = FALSE;
00203 #else
00204 
00205   if (environ != NULL)
00206     environ[0] = NULL;
00207 #endif
00208 
00209   return rc;
00210 }
00211 
00220 dbus_bool_t
00221 _dbus_split_paths_and_append (DBusString *dirs, 
00222                               const char *suffix, 
00223                               DBusList  **dir_list)
00224 {
00225    int start;
00226    int i;
00227    int len;
00228    char *cpath;
00229    DBusString file_suffix;
00230 
00231    start = 0;
00232    i = 0;
00233 
00234    _dbus_string_init_const (&file_suffix, suffix);
00235 
00236    len = _dbus_string_get_length (dirs);
00237 
00238    while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00239      {
00240        DBusString path;
00241 
00242        if (!_dbus_string_init (&path))
00243           goto oom;
00244 
00245        if (!_dbus_string_copy_len (dirs,
00246                                    start,
00247                                    i - start,
00248                                    &path,
00249                                    0))
00250           {
00251             _dbus_string_free (&path);
00252             goto oom;
00253           }
00254 
00255         _dbus_string_chop_white (&path);
00256 
00257         /* check for an empty path */
00258         if (_dbus_string_get_length (&path) == 0)
00259           goto next;
00260 
00261         if (!_dbus_concat_dir_and_file (&path,
00262                                         &file_suffix))
00263           {
00264             _dbus_string_free (&path);
00265             goto oom;
00266           }
00267 
00268         if (!_dbus_string_copy_data(&path, &cpath))
00269           {
00270             _dbus_string_free (&path);
00271             goto oom;
00272           }
00273 
00274         if (!_dbus_list_append (dir_list, cpath))
00275           {
00276             _dbus_string_free (&path);              
00277             dbus_free (cpath);
00278             goto oom;
00279           }
00280 
00281        next:
00282         _dbus_string_free (&path);
00283         start = i + 1;
00284     } 
00285       
00286   if (start != len)
00287     { 
00288       DBusString path;
00289 
00290       if (!_dbus_string_init (&path))
00291         goto oom;
00292 
00293       if (!_dbus_string_copy_len (dirs,
00294                                   start,
00295                                   len - start,
00296                                   &path,
00297                                   0))
00298         {
00299           _dbus_string_free (&path);
00300           goto oom;
00301         }
00302 
00303       if (!_dbus_concat_dir_and_file (&path,
00304                                       &file_suffix))
00305         {
00306           _dbus_string_free (&path);
00307           goto oom;
00308         }
00309 
00310       if (!_dbus_string_copy_data(&path, &cpath))
00311         {
00312           _dbus_string_free (&path);
00313           goto oom;
00314         }
00315 
00316       if (!_dbus_list_append (dir_list, cpath))
00317         {
00318           _dbus_string_free (&path);              
00319           dbus_free (cpath);
00320           goto oom;
00321         }
00322 
00323       _dbus_string_free (&path); 
00324     }
00325 
00326   return TRUE;
00327 
00328  oom:
00329   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
00330   _dbus_list_clear (dir_list);
00331   return FALSE;
00332 }
00333 
00348 dbus_bool_t
00349 _dbus_string_append_int (DBusString *str,
00350                          long        value)
00351 {
00352   /* this calculation is from comp.lang.c faq */
00353 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
00354   int orig_len;
00355   int i;
00356   char *buf;
00357   
00358   orig_len = _dbus_string_get_length (str);
00359 
00360   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00361     return FALSE;
00362 
00363   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00364 
00365   snprintf (buf, MAX_LONG_LEN, "%ld", value);
00366 
00367   i = 0;
00368   while (*buf)
00369     {
00370       ++buf;
00371       ++i;
00372     }
00373   
00374   _dbus_string_shorten (str, MAX_LONG_LEN - i);
00375   
00376   return TRUE;
00377 }
00378 
00386 dbus_bool_t
00387 _dbus_string_append_uint (DBusString    *str,
00388                           unsigned long  value)
00389 {
00390   /* this is wrong, but definitely on the high side. */
00391 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00392   int orig_len;
00393   int i;
00394   char *buf;
00395   
00396   orig_len = _dbus_string_get_length (str);
00397 
00398   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00399     return FALSE;
00400 
00401   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00402 
00403   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00404 
00405   i = 0;
00406   while (*buf)
00407     {
00408       ++buf;
00409       ++i;
00410     }
00411   
00412   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00413   
00414   return TRUE;
00415 }
00416 
00429 dbus_bool_t
00430 _dbus_string_parse_int (const DBusString *str,
00431                         int               start,
00432                         long             *value_return,
00433                         int              *end_return)
00434 {
00435   long v;
00436   const char *p;
00437   char *end;
00438 
00439   p = _dbus_string_get_const_data_len (str, start,
00440                                        _dbus_string_get_length (str) - start);
00441 
00442   end = NULL;
00443   _dbus_set_errno_to_zero ();
00444   v = strtol (p, &end, 0);
00445   if (end == NULL || end == p || errno != 0)
00446     return FALSE;
00447 
00448   if (value_return)
00449     *value_return = v;
00450   if (end_return)
00451     *end_return = start + (end - p);
00452 
00453   return TRUE;
00454 }
00455 
00468 dbus_bool_t
00469 _dbus_string_parse_uint (const DBusString *str,
00470                          int               start,
00471                          unsigned long    *value_return,
00472                          int              *end_return)
00473 {
00474   unsigned long v;
00475   const char *p;
00476   char *end;
00477 
00478   p = _dbus_string_get_const_data_len (str, start,
00479                                        _dbus_string_get_length (str) - start);
00480 
00481   end = NULL;
00482   _dbus_set_errno_to_zero ();
00483   v = strtoul (p, &end, 0);
00484   if (end == NULL || end == p || errno != 0)
00485     return FALSE;
00486 
00487   if (value_return)
00488     *value_return = v;
00489   if (end_return)
00490     *end_return = start + (end - p);
00491 
00492   return TRUE;
00493 }
00494  /* DBusString group */
00496 
00502 void
00503 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00504                                           int   n_bytes)
00505 {
00506   long tv_usec;
00507   int i;
00508   
00509   /* fall back to pseudorandom */
00510   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00511                  n_bytes);
00512   
00513   _dbus_get_real_time (NULL, &tv_usec);
00514   srand (tv_usec);
00515   
00516   i = 0;
00517   while (i < n_bytes)
00518     {
00519       double r;
00520       unsigned int b;
00521           
00522       r = rand ();
00523       b = (r / (double) RAND_MAX) * 255.0;
00524 
00525       buffer[i] = b;
00526 
00527       ++i;
00528     }
00529 }
00530 
00537 void
00538 _dbus_generate_random_bytes_buffer (char *buffer,
00539                                     int   n_bytes)
00540 {
00541   DBusString str;
00542 
00543   if (!_dbus_string_init (&str))
00544     {
00545       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00546       return;
00547     }
00548 
00549   if (!_dbus_generate_random_bytes (&str, n_bytes))
00550     {
00551       _dbus_string_free (&str);
00552       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00553       return;
00554     }
00555 
00556   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00557 
00558   _dbus_string_free (&str);
00559 }
00560 
00569 dbus_bool_t
00570 _dbus_generate_random_ascii (DBusString *str,
00571                              int         n_bytes)
00572 {
00573   static const char letters[] =
00574     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00575   int i;
00576   int len;
00577   
00578   if (!_dbus_generate_random_bytes (str, n_bytes))
00579     return FALSE;
00580   
00581   len = _dbus_string_get_length (str);
00582   i = len - n_bytes;
00583   while (i < len)
00584     {
00585       _dbus_string_set_byte (str, i,
00586                              letters[_dbus_string_get_byte (str, i) %
00587                                      (sizeof (letters) - 1)]);
00588 
00589       ++i;
00590     }
00591 
00592   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00593                                              n_bytes));
00594 
00595   return TRUE;
00596 }
00597 
00608 const char*
00609 _dbus_error_from_errno (int error_number)
00610 {
00611   switch (error_number)
00612     {
00613     case 0:
00614       return DBUS_ERROR_FAILED;
00615       
00616 #ifdef EPROTONOSUPPORT
00617     case EPROTONOSUPPORT:
00618       return DBUS_ERROR_NOT_SUPPORTED;
00619 #elif defined(WSAEPROTONOSUPPORT)
00620     case WSAEPROTONOSUPPORT:
00621       return DBUS_ERROR_NOT_SUPPORTED;
00622 #endif
00623 #ifdef EAFNOSUPPORT
00624     case EAFNOSUPPORT:
00625       return DBUS_ERROR_NOT_SUPPORTED;
00626 #elif defined(WSAEAFNOSUPPORT)
00627     case WSAEAFNOSUPPORT:
00628       return DBUS_ERROR_NOT_SUPPORTED;
00629 #endif
00630 #ifdef ENFILE
00631     case ENFILE:
00632       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
00633 #endif
00634 #ifdef EMFILE
00635     case EMFILE:
00636       return DBUS_ERROR_LIMITS_EXCEEDED;
00637 #endif
00638 #ifdef EACCES
00639     case EACCES:
00640       return DBUS_ERROR_ACCESS_DENIED;
00641 #endif
00642 #ifdef EPERM
00643     case EPERM:
00644       return DBUS_ERROR_ACCESS_DENIED;
00645 #endif
00646 #ifdef ENOBUFS
00647     case ENOBUFS:
00648       return DBUS_ERROR_NO_MEMORY;
00649 #endif
00650 #ifdef ENOMEM
00651     case ENOMEM:
00652       return DBUS_ERROR_NO_MEMORY;
00653 #endif
00654 #ifdef ECONNREFUSED
00655     case ECONNREFUSED:
00656       return DBUS_ERROR_NO_SERVER;
00657 #elif defined(WSAECONNREFUSED)
00658     case WSAECONNREFUSED:
00659       return DBUS_ERROR_NO_SERVER;
00660 #endif
00661 #ifdef ETIMEDOUT
00662     case ETIMEDOUT:
00663       return DBUS_ERROR_TIMEOUT;
00664 #elif defined(WSAETIMEDOUT)
00665     case WSAETIMEDOUT:
00666       return DBUS_ERROR_TIMEOUT;
00667 #endif
00668 #ifdef ENETUNREACH
00669     case ENETUNREACH:
00670       return DBUS_ERROR_NO_NETWORK;
00671 #elif defined(WSAENETUNREACH)
00672     case WSAENETUNREACH:
00673       return DBUS_ERROR_NO_NETWORK;
00674 #endif
00675 #ifdef EADDRINUSE
00676     case EADDRINUSE:
00677       return DBUS_ERROR_ADDRESS_IN_USE;
00678 #elif defined(WSAEADDRINUSE)
00679     case WSAEADDRINUSE:
00680       return DBUS_ERROR_ADDRESS_IN_USE;
00681 #endif
00682 #ifdef EEXIST
00683     case EEXIST:
00684       return DBUS_ERROR_FILE_EXISTS;
00685 #endif
00686 #ifdef ENOENT
00687     case ENOENT:
00688       return DBUS_ERROR_FILE_NOT_FOUND;
00689 #endif
00690     }
00691 
00692   return DBUS_ERROR_FAILED;
00693 }
00694 
00700 const char*
00701 _dbus_error_from_system_errno (void)
00702 {
00703   return _dbus_error_from_errno (errno);
00704 }
00705 
00709 void
00710 _dbus_set_errno_to_zero (void)
00711 {
00712 #ifdef DBUS_WINCE
00713   SetLastError (0);
00714 #else
00715   errno = 0;
00716 #endif
00717 }
00718 
00723 dbus_bool_t
00724 _dbus_get_is_errno_nonzero (void)
00725 {
00726   return errno != 0;
00727 }
00728 
00733 dbus_bool_t
00734 _dbus_get_is_errno_enomem (void)
00735 {
00736   return errno == ENOMEM;
00737 }
00738 
00743 dbus_bool_t
00744 _dbus_get_is_errno_eintr (void)
00745 {
00746   return errno == EINTR;
00747 }
00748 
00753 dbus_bool_t
00754 _dbus_get_is_errno_epipe (void)
00755 {
00756   return errno == EPIPE;
00757 }
00758 
00763 dbus_bool_t
00764 _dbus_get_is_errno_etoomanyrefs (void)
00765 {
00766 #ifdef ETOOMANYREFS
00767   return errno == ETOOMANYREFS;
00768 #else
00769   return FALSE;
00770 #endif
00771 }
00772 
00777 const char*
00778 _dbus_strerror_from_errno (void)
00779 {
00780   return _dbus_strerror (errno);
00781 }
00782 
00785 /* tests in dbus-sysdeps-util.c */