Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation)
      3  *
      4  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
      5  * Copyright (C) 2003 CodeFactory AB
      6  *
      7  * Licensed under the Academic Free License version 2.1
      8  *
      9  * This program is free software; you can redistribute it and/or modify
     10  * it under the terms of the GNU General Public License as published by
     11  * the Free Software Foundation; either version 2 of the License, or
     12  * (at your option) any later version.
     13  *
     14  * This program is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  * GNU General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU General Public License
     20  * along with this program; if not, write to the Free Software
     21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #include <config.h>
     26 #include "dbus-internals.h"
     27 #include "dbus-sysdeps.h"
     28 #include "dbus-threads.h"
     29 #include "dbus-protocol.h"
     30 #include "dbus-string.h"
     31 #include "dbus-list.h"
     32 
     33 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
     34  * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
     35  *
     36  * These are the standard ANSI C headers...
     37  */
     38 #if HAVE_LOCALE_H
     39 #include <locale.h>
     40 #endif
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <stdio.h>
     44 
     45 #ifdef HAVE_ERRNO_H
     46 #include <errno.h>
     47 #endif
     48 
     49 _DBUS_DEFINE_GLOBAL_LOCK (win_fds);
     50 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
     51 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
     52 
     53 #ifdef DBUS_WIN
     54   #include <stdlib.h>
     55 #elif (defined __APPLE__)
     56 # include <crt_externs.h>
     57 # define environ (*_NSGetEnviron())
     58 #else
     59 extern char **environ;
     60 #endif
     61 
     62 /**
     63  * @defgroup DBusSysdeps Internal system-dependent API
     64  * @ingroup DBusInternals
     65  * @brief Internal system-dependent API available on UNIX and Windows
     66  *
     67  * The system-dependent API has a dual purpose. First, it encapsulates
     68  * all usage of operating system APIs for ease of auditing and to
     69  * avoid cluttering the rest of the code with bizarre OS quirks and
     70  * headers. Second, it abstracts different operating system APIs for
     71  * portability.
     72  *
     73  * @{
     74  */
     75 
     76 /**
     77  * Aborts the program with SIGABRT (dumping core).
     78  */
     79 void
     80 _dbus_abort (void)
     81 {
     82   const char *s;
     83 
     84   _dbus_print_backtrace ();
     85 
     86   s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
     87   if (s && *s)
     88     {
     89       /* don't use _dbus_warn here since it can _dbus_abort() */
     90       fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
     91       _dbus_sleep_milliseconds (1000 * 180);
     92     }
     93 
     94   abort ();
     95   _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
     96 }
     97 
     98 /**
     99  * Wrapper for setenv(). If the value is #NULL, unsets
    100  * the environment variable.
    101  *
    102  * There is an unfixable memleak in that it is unsafe to
    103  * free memory malloced for use with setenv. This is because
    104  * we can not rely on internal implementation details of
    105  * the underlying libc library.
    106  *
    107  * @param varname name of environment variable
    108  * @param value value of environment variable
    109  * @returns #TRUE on success.
    110  */
    111 dbus_bool_t
    112 _dbus_setenv (const char *varname,
    113               const char *value)
    114 {
    115   _dbus_assert (varname != NULL);
    116 
    117   if (value == NULL)
    118     {
    119 #ifdef HAVE_UNSETENV
    120       unsetenv (varname);
    121       return TRUE;
    122 #else
    123       char *putenv_value;
    124       size_t len;
    125 
    126       len = strlen (varname);
    127 
    128       /* Use system malloc to avoid memleaks that dbus_malloc
    129        * will get upset about.
    130        */
    131 
    132       putenv_value = malloc (len + 2);
    133       if (putenv_value == NULL)
    134         return FALSE;
    135 
    136       strcpy (putenv_value, varname);
    137 #if defined(DBUS_WIN)
    138       strcat (putenv_value, "=");
    139 #endif
    140 
    141       return (putenv (putenv_value) == 0);
    142 #endif
    143     }
    144   else
    145     {
    146 #ifdef HAVE_SETENV
    147       return (setenv (varname, value, TRUE) == 0);
    148 #else
    149       char *putenv_value;
    150       size_t len;
    151       size_t varname_len;
    152       size_t value_len;
    153 
    154       varname_len = strlen (varname);
    155       value_len = strlen (value);
    156 
    157       len = varname_len + value_len + 1 /* '=' */ ;
    158 
    159       /* Use system malloc to avoid memleaks that dbus_malloc
    160        * will get upset about.
    161        */
    162 
    163       putenv_value = malloc (len + 1);
    164       if (putenv_value == NULL)
    165         return FALSE;
    166 
    167       strcpy (putenv_value, varname);
    168       strcpy (putenv_value + varname_len, "=");
    169       strcpy (putenv_value + varname_len + 1, value);
    170 
    171       return (putenv (putenv_value) == 0);
    172 #endif
    173     }
    174 }
    175 
    176 /**
    177  * Wrapper for getenv().
    178  *
    179  * @param varname name of environment variable
    180  * @returns value of environment variable or #NULL if unset
    181  */
    182 const char*
    183 _dbus_getenv (const char *varname)
    184 {
    185   return getenv (varname);
    186 }
    187 
    188 /**
    189  * Wrapper for clearenv().
    190  *
    191  * @returns #TRUE on success.
    192  */
    193 dbus_bool_t
    194 _dbus_clearenv (void)
    195 {
    196   dbus_bool_t rc = TRUE;
    197 
    198 #ifdef HAVE_CLEARENV
    199   if (clearenv () != 0)
    200      rc = FALSE;
    201 #else
    202 
    203   if (environ != NULL)
    204     environ[0] = NULL;
    205 #endif
    206 
    207   return rc;
    208 }
    209 
    210 /**
    211  * Gets a #NULL-terminated list of key=value pairs from the
    212  * environment. Use dbus_free_string_array to free it.
    213  *
    214  * @returns the environment or #NULL on OOM
    215  */
    216 char **
    217 _dbus_get_environment (void)
    218 {
    219   int i, length;
    220   char **environment;
    221 
    222   _dbus_assert (environ != NULL);
    223 
    224   for (length = 0; environ[length] != NULL; length++);
    225 
    226   /* Add one for NULL */
    227   length++;
    228 
    229   environment = dbus_new0 (char *, length);
    230 
    231   if (environment == NULL)
    232     return NULL;
    233 
    234   for (i = 0; environ[i] != NULL; i++)
    235     {
    236       environment[i] = _dbus_strdup (environ[i]);
    237 
    238       if (environment[i] == NULL)
    239         break;
    240     }
    241 
    242   if (environ[i] != NULL)
    243     {
    244       dbus_free_string_array (environment);
    245       environment = NULL;
    246     }
    247 
    248   return environment;
    249 }
    250 
    251 /**
    252  * Split paths into a list of char strings
    253  *
    254  * @param dirs string with pathes
    255  * @param suffix string concated to each path in dirs
    256  * @param dir_list contains a list of splitted pathes
    257  * return #TRUE is pathes could be splittes,#FALSE in oom case
    258  */
    259 dbus_bool_t
    260 _dbus_split_paths_and_append (DBusString *dirs,
    261                               const char *suffix,
    262                               DBusList  **dir_list)
    263 {
    264    int start;
    265    int i;
    266    int len;
    267    char *cpath;
    268    DBusString file_suffix;
    269 
    270    start = 0;
    271    i = 0;
    272 
    273    _dbus_string_init_const (&file_suffix, suffix);
    274 
    275    len = _dbus_string_get_length (dirs);
    276 
    277    while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
    278      {
    279        DBusString path;
    280 
    281        if (!_dbus_string_init (&path))
    282           goto oom;
    283 
    284        if (!_dbus_string_copy_len (dirs,
    285                                    start,
    286                                    i - start,
    287                                    &path,
    288                                    0))
    289           {
    290             _dbus_string_free (&path);
    291             goto oom;
    292           }
    293 
    294         _dbus_string_chop_white (&path);
    295 
    296         /* check for an empty path */
    297         if (_dbus_string_get_length (&path) == 0)
    298           goto next;
    299 
    300         if (!_dbus_concat_dir_and_file (&path,
    301                                         &file_suffix))
    302           {
    303             _dbus_string_free (&path);
    304             goto oom;
    305           }
    306 
    307         if (!_dbus_string_copy_data(&path, &cpath))
    308           {
    309             _dbus_string_free (&path);
    310             goto oom;
    311           }
    312 
    313         if (!_dbus_list_append (dir_list, cpath))
    314           {
    315             _dbus_string_free (&path);
    316             dbus_free (cpath);
    317             goto oom;
    318           }
    319 
    320        next:
    321         _dbus_string_free (&path);
    322         start = i + 1;
    323     }
    324 
    325   if (start != len)
    326     {
    327       DBusString path;
    328 
    329       if (!_dbus_string_init (&path))
    330         goto oom;
    331 
    332       if (!_dbus_string_copy_len (dirs,
    333                                   start,
    334                                   len - start,
    335                                   &path,
    336                                   0))
    337         {
    338           _dbus_string_free (&path);
    339           goto oom;
    340         }
    341 
    342       if (!_dbus_concat_dir_and_file (&path,
    343                                       &file_suffix))
    344         {
    345           _dbus_string_free (&path);
    346           goto oom;
    347         }
    348 
    349       if (!_dbus_string_copy_data(&path, &cpath))
    350         {
    351           _dbus_string_free (&path);
    352           goto oom;
    353         }
    354 
    355       if (!_dbus_list_append (dir_list, cpath))
    356         {
    357           _dbus_string_free (&path);
    358           dbus_free (cpath);
    359           goto oom;
    360         }
    361 
    362       _dbus_string_free (&path);
    363     }
    364 
    365   return TRUE;
    366 
    367  oom:
    368   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
    369   _dbus_list_clear (dir_list);
    370   return FALSE;
    371 }
    372 
    373 /** @} */
    374 
    375 /**
    376  * @addtogroup DBusString
    377  *
    378  * @{
    379  */
    380 /**
    381  * Appends an integer to a DBusString.
    382  *
    383  * @param str the string
    384  * @param value the integer value
    385  * @returns #FALSE if not enough memory or other failure.
    386  */
    387 dbus_bool_t
    388 _dbus_string_append_int (DBusString *str,
    389                          long        value)
    390 {
    391   /* this calculation is from comp.lang.c faq */
    392 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
    393   int orig_len;
    394   int i;
    395   char *buf;
    396 
    397   orig_len = _dbus_string_get_length (str);
    398 
    399   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
    400     return FALSE;
    401 
    402   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
    403 
    404   snprintf (buf, MAX_LONG_LEN, "%ld", value);
    405 
    406   i = 0;
    407   while (*buf)
    408     {
    409       ++buf;
    410       ++i;
    411     }
    412 
    413   _dbus_string_shorten (str, MAX_LONG_LEN - i);
    414 
    415   return TRUE;
    416 }
    417 
    418 /**
    419  * Appends an unsigned integer to a DBusString.
    420  *
    421  * @param str the string
    422  * @param value the integer value
    423  * @returns #FALSE if not enough memory or other failure.
    424  */
    425 dbus_bool_t
    426 _dbus_string_append_uint (DBusString    *str,
    427                           unsigned long  value)
    428 {
    429   /* this is wrong, but definitely on the high side. */
    430 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
    431   int orig_len;
    432   int i;
    433   char *buf;
    434 
    435   orig_len = _dbus_string_get_length (str);
    436 
    437   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
    438     return FALSE;
    439 
    440   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
    441 
    442   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
    443 
    444   i = 0;
    445   while (*buf)
    446     {
    447       ++buf;
    448       ++i;
    449     }
    450 
    451   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
    452 
    453   return TRUE;
    454 }
    455 
    456 #ifdef DBUS_BUILD_TESTS
    457 /**
    458  * Appends a double to a DBusString.
    459  *
    460  * @param str the string
    461  * @param value the floating point value
    462  * @returns #FALSE if not enough memory or other failure.
    463  */
    464 dbus_bool_t
    465 _dbus_string_append_double (DBusString *str,
    466                             double      value)
    467 {
    468 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
    469   int orig_len;
    470   char *buf;
    471   int i;
    472 
    473   orig_len = _dbus_string_get_length (str);
    474 
    475   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
    476     return FALSE;
    477 
    478   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
    479 
    480   snprintf (buf, MAX_LONG_LEN, "%g", value);
    481 
    482   i = 0;
    483   while (*buf)
    484     {
    485       ++buf;
    486       ++i;
    487     }
    488 
    489   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
    490 
    491   return TRUE;
    492 }
    493 #endif /* DBUS_BUILD_TESTS */
    494 
    495 /**
    496  * Parses an integer contained in a DBusString. Either return parameter
    497  * may be #NULL if you aren't interested in it. The integer is parsed
    498  * and stored in value_return. Return parameters are not initialized
    499  * if the function returns #FALSE.
    500  *
    501  * @param str the string
    502  * @param start the byte index of the start of the integer
    503  * @param value_return return location of the integer value or #NULL
    504  * @param end_return return location of the end of the integer, or #NULL
    505  * @returns #TRUE on success
    506  */
    507 dbus_bool_t
    508 _dbus_string_parse_int (const DBusString *str,
    509                         int               start,
    510                         long             *value_return,
    511                         int              *end_return)
    512 {
    513   long v;
    514   const char *p;
    515   char *end;
    516 
    517   p = _dbus_string_get_const_data_len (str, start,
    518                                        _dbus_string_get_length (str) - start);
    519 
    520   end = NULL;
    521   _dbus_set_errno_to_zero ();
    522   v = strtol (p, &end, 0);
    523   if (end == NULL || end == p || errno != 0)
    524     return FALSE;
    525 
    526   if (value_return)
    527     *value_return = v;
    528   if (end_return)
    529     *end_return = start + (end - p);
    530 
    531   return TRUE;
    532 }
    533 
    534 /**
    535  * Parses an unsigned integer contained in a DBusString. Either return
    536  * parameter may be #NULL if you aren't interested in it. The integer
    537  * is parsed and stored in value_return. Return parameters are not
    538  * initialized if the function returns #FALSE.
    539  *
    540  * @param str the string
    541  * @param start the byte index of the start of the integer
    542  * @param value_return return location of the integer value or #NULL
    543  * @param end_return return location of the end of the integer, or #NULL
    544  * @returns #TRUE on success
    545  */
    546 dbus_bool_t
    547 _dbus_string_parse_uint (const DBusString *str,
    548                          int               start,
    549                          unsigned long    *value_return,
    550                          int              *end_return)
    551 {
    552   unsigned long v;
    553   const char *p;
    554   char *end;
    555 
    556   p = _dbus_string_get_const_data_len (str, start,
    557                                        _dbus_string_get_length (str) - start);
    558 
    559   end = NULL;
    560   _dbus_set_errno_to_zero ();
    561   v = strtoul (p, &end, 0);
    562   if (end == NULL || end == p || errno != 0)
    563     return FALSE;
    564 
    565   if (value_return)
    566     *value_return = v;
    567   if (end_return)
    568     *end_return = start + (end - p);
    569 
    570   return TRUE;
    571 }
    572 
    573 #ifdef DBUS_BUILD_TESTS
    574 static dbus_bool_t
    575 ascii_isspace (char c)
    576 {
    577   return (c == ' ' ||
    578 	  c == '\f' ||
    579 	  c == '\n' ||
    580 	  c == '\r' ||
    581 	  c == '\t' ||
    582 	  c == '\v');
    583 }
    584 #endif /* DBUS_BUILD_TESTS */
    585 
    586 #ifdef DBUS_BUILD_TESTS
    587 static dbus_bool_t
    588 ascii_isdigit (char c)
    589 {
    590   return c >= '0' && c <= '9';
    591 }
    592 #endif /* DBUS_BUILD_TESTS */
    593 
    594 #ifdef DBUS_BUILD_TESTS
    595 static dbus_bool_t
    596 ascii_isxdigit (char c)
    597 {
    598   return (ascii_isdigit (c) ||
    599 	  (c >= 'a' && c <= 'f') ||
    600 	  (c >= 'A' && c <= 'F'));
    601 }
    602 #endif /* DBUS_BUILD_TESTS */
    603 
    604 #ifdef DBUS_BUILD_TESTS
    605 /* Calls strtod in a locale-independent fashion, by looking at
    606  * the locale data and patching the decimal comma to a point.
    607  *
    608  * Relicensed from glib.
    609  */
    610 static double
    611 ascii_strtod (const char *nptr,
    612 	      char      **endptr)
    613 {
    614   /* FIXME: The Win32 C library's strtod() doesn't handle hex.
    615    * Presumably many Unixes don't either.
    616    */
    617 
    618   char *fail_pos;
    619   double val;
    620   struct lconv *locale_data;
    621   const char *decimal_point;
    622   int decimal_point_len;
    623   const char *p, *decimal_point_pos;
    624   const char *end = NULL; /* Silence gcc */
    625 
    626   fail_pos = NULL;
    627 
    628 #if HAVE_LOCALECONV
    629   locale_data = localeconv ();
    630   decimal_point = locale_data->decimal_point;
    631 #else
    632   decimal_point = ".";
    633 #endif
    634 
    635   decimal_point_len = strlen (decimal_point);
    636   _dbus_assert (decimal_point_len != 0);
    637 
    638   decimal_point_pos = NULL;
    639   if (decimal_point[0] != '.' ||
    640       decimal_point[1] != 0)
    641     {
    642       p = nptr;
    643       /* Skip leading space */
    644       while (ascii_isspace (*p))
    645 	p++;
    646 
    647       /* Skip leading optional sign */
    648       if (*p == '+' || *p == '-')
    649 	p++;
    650 
    651       if (p[0] == '0' &&
    652 	  (p[1] == 'x' || p[1] == 'X'))
    653 	{
    654 	  p += 2;
    655 	  /* HEX - find the (optional) decimal point */
    656 
    657 	  while (ascii_isxdigit (*p))
    658 	    p++;
    659 
    660 	  if (*p == '.')
    661 	    {
    662 	      decimal_point_pos = p++;
    663 
    664 	      while (ascii_isxdigit (*p))
    665 		p++;
    666 
    667 	      if (*p == 'p' || *p == 'P')
    668 		p++;
    669 	      if (*p == '+' || *p == '-')
    670 		p++;
    671 	      while (ascii_isdigit (*p))
    672 		p++;
    673 	      end = p;
    674 	    }
    675 	}
    676       else
    677 	{
    678 	  while (ascii_isdigit (*p))
    679 	    p++;
    680 
    681 	  if (*p == '.')
    682 	    {
    683 	      decimal_point_pos = p++;
    684 
    685 	      while (ascii_isdigit (*p))
    686 		p++;
    687 
    688 	      if (*p == 'e' || *p == 'E')
    689 		p++;
    690 	      if (*p == '+' || *p == '-')
    691 		p++;
    692 	      while (ascii_isdigit (*p))
    693 		p++;
    694 	      end = p;
    695 	    }
    696 	}
    697       /* For the other cases, we need not convert the decimal point */
    698     }
    699 
    700   /* Set errno to zero, so that we can distinguish zero results
    701      and underflows */
    702   _dbus_set_errno_to_zero ();
    703 
    704   if (decimal_point_pos)
    705     {
    706       char *copy, *c;
    707 
    708       /* We need to convert the '.' to the locale specific decimal point */
    709       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
    710 
    711       c = copy;
    712       memcpy (c, nptr, decimal_point_pos - nptr);
    713       c += decimal_point_pos - nptr;
    714       memcpy (c, decimal_point, decimal_point_len);
    715       c += decimal_point_len;
    716       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
    717       c += end - (decimal_point_pos + 1);
    718       *c = 0;
    719 
    720       val = strtod (copy, &fail_pos);
    721 
    722       if (fail_pos)
    723 	{
    724 	  if (fail_pos > decimal_point_pos)
    725 	    fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
    726 	  else
    727 	    fail_pos = (char *)nptr + (fail_pos - copy);
    728 	}
    729 
    730       dbus_free (copy);
    731 
    732     }
    733   else
    734     val = strtod (nptr, &fail_pos);
    735 
    736   if (endptr)
    737     *endptr = fail_pos;
    738 
    739   return val;
    740 }
    741 #endif /* DBUS_BUILD_TESTS */
    742 
    743 #ifdef DBUS_BUILD_TESTS
    744 /**
    745  * Parses a floating point number contained in a DBusString. Either
    746  * return parameter may be #NULL if you aren't interested in it. The
    747  * integer is parsed and stored in value_return. Return parameters are
    748  * not initialized if the function returns #FALSE.
    749  *
    750  * @param str the string
    751  * @param start the byte index of the start of the float
    752  * @param value_return return location of the float value or #NULL
    753  * @param end_return return location of the end of the float, or #NULL
    754  * @returns #TRUE on success
    755  */
    756 dbus_bool_t
    757 _dbus_string_parse_double (const DBusString *str,
    758                            int               start,
    759                            double           *value_return,
    760                            int              *end_return)
    761 {
    762   double v;
    763   const char *p;
    764   char *end;
    765 
    766   p = _dbus_string_get_const_data_len (str, start,
    767                                        _dbus_string_get_length (str) - start);
    768 
    769   /* parsing hex works on linux but isn't portable, so intercept it
    770    * here to get uniform behavior.
    771    */
    772   if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
    773     return FALSE;
    774 
    775   end = NULL;
    776   _dbus_set_errno_to_zero ();
    777   v = ascii_strtod (p, &end);
    778   if (end == NULL || end == p || errno != 0)
    779     return FALSE;
    780 
    781   if (value_return)
    782     *value_return = v;
    783   if (end_return)
    784     *end_return = start + (end - p);
    785 
    786   return TRUE;
    787 }
    788 #endif /* DBUS_BUILD_TESTS */
    789 
    790 /** @} */ /* DBusString group */
    791 
    792 /**
    793  * @addtogroup DBusInternalsUtils
    794  * @{
    795  */
    796 
    797 void
    798 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
    799                                           int   n_bytes)
    800 {
    801   long tv_usec;
    802   int i;
    803 
    804   /* fall back to pseudorandom */
    805   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
    806                  n_bytes);
    807 
    808   _dbus_get_current_time (NULL, &tv_usec);
    809   srand (tv_usec);
    810 
    811   i = 0;
    812   while (i < n_bytes)
    813     {
    814       double r;
    815       unsigned int b;
    816 
    817       r = rand ();
    818       b = (r / (double) RAND_MAX) * 255.0;
    819 
    820       buffer[i] = b;
    821 
    822       ++i;
    823     }
    824 }
    825 
    826 /**
    827  * Fills n_bytes of the given buffer with random bytes.
    828  *
    829  * @param buffer an allocated buffer
    830  * @param n_bytes the number of bytes in buffer to write to
    831  */
    832 void
    833 _dbus_generate_random_bytes_buffer (char *buffer,
    834                                     int   n_bytes)
    835 {
    836   DBusString str;
    837 
    838   if (!_dbus_string_init (&str))
    839     {
    840       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
    841       return;
    842     }
    843 
    844   if (!_dbus_generate_random_bytes (&str, n_bytes))
    845     {
    846       _dbus_string_free (&str);
    847       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
    848       return;
    849     }
    850 
    851   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
    852 
    853   _dbus_string_free (&str);
    854 }
    855 
    856 /**
    857  * Generates the given number of random bytes, where the bytes are
    858  * chosen from the alphanumeric ASCII subset.
    859  *
    860  * @param str the string
    861  * @param n_bytes the number of random ASCII bytes to append to string
    862  * @returns #TRUE on success, #FALSE if no memory or other failure
    863  */
    864 dbus_bool_t
    865 _dbus_generate_random_ascii (DBusString *str,
    866                              int         n_bytes)
    867 {
    868   static const char letters[] =
    869     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
    870   int i;
    871   int len;
    872 
    873   if (!_dbus_generate_random_bytes (str, n_bytes))
    874     return FALSE;
    875 
    876   len = _dbus_string_get_length (str);
    877   i = len - n_bytes;
    878   while (i < len)
    879     {
    880       _dbus_string_set_byte (str, i,
    881                              letters[_dbus_string_get_byte (str, i) %
    882                                      (sizeof (letters) - 1)]);
    883 
    884       ++i;
    885     }
    886 
    887   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
    888                                              n_bytes));
    889 
    890   return TRUE;
    891 }
    892 
    893 /**
    894  * Converts a UNIX errno, or Windows errno or WinSock error value into
    895  * a #DBusError name.
    896  *
    897  * @todo should cover more errnos, specifically those
    898  * from open().
    899  *
    900  * @param error_number the errno.
    901  * @returns an error name
    902  */
    903 const char*
    904 _dbus_error_from_errno (int error_number)
    905 {
    906   switch (error_number)
    907     {
    908     case 0:
    909       return DBUS_ERROR_FAILED;
    910 
    911 #ifdef EPROTONOSUPPORT
    912     case EPROTONOSUPPORT:
    913       return DBUS_ERROR_NOT_SUPPORTED;
    914 #endif
    915 #ifdef WSAEPROTONOSUPPORT
    916     case WSAEPROTONOSUPPORT:
    917       return DBUS_ERROR_NOT_SUPPORTED;
    918 #endif
    919 #ifdef EAFNOSUPPORT
    920     case EAFNOSUPPORT:
    921       return DBUS_ERROR_NOT_SUPPORTED;
    922 #endif
    923 #ifdef WSAEAFNOSUPPORT
    924     case WSAEAFNOSUPPORT:
    925       return DBUS_ERROR_NOT_SUPPORTED;
    926 #endif
    927 #ifdef ENFILE
    928     case ENFILE:
    929       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
    930 #endif
    931 #ifdef EMFILE
    932     case EMFILE:
    933       return DBUS_ERROR_LIMITS_EXCEEDED;
    934 #endif
    935 #ifdef EACCES
    936     case EACCES:
    937       return DBUS_ERROR_ACCESS_DENIED;
    938 #endif
    939 #ifdef EPERM
    940     case EPERM:
    941       return DBUS_ERROR_ACCESS_DENIED;
    942 #endif
    943 #ifdef ENOBUFS
    944     case ENOBUFS:
    945       return DBUS_ERROR_NO_MEMORY;
    946 #endif
    947 #ifdef ENOMEM
    948     case ENOMEM:
    949       return DBUS_ERROR_NO_MEMORY;
    950 #endif
    951 #ifdef ECONNREFUSED
    952     case ECONNREFUSED:
    953       return DBUS_ERROR_NO_SERVER;
    954 #endif
    955 #ifdef WSAECONNREFUSED
    956     case WSAECONNREFUSED:
    957       return DBUS_ERROR_NO_SERVER;
    958 #endif
    959 #ifdef ETIMEDOUT
    960     case ETIMEDOUT:
    961       return DBUS_ERROR_TIMEOUT;
    962 #endif
    963 #ifdef WSAETIMEDOUT
    964     case WSAETIMEDOUT:
    965       return DBUS_ERROR_TIMEOUT;
    966 #endif
    967 #ifdef ENETUNREACH
    968     case ENETUNREACH:
    969       return DBUS_ERROR_NO_NETWORK;
    970 #endif
    971 #ifdef WSAENETUNREACH
    972     case WSAENETUNREACH:
    973       return DBUS_ERROR_NO_NETWORK;
    974 #endif
    975 #ifdef EADDRINUSE
    976     case EADDRINUSE:
    977       return DBUS_ERROR_ADDRESS_IN_USE;
    978 #endif
    979 #ifdef WSAEADDRINUSE
    980     case WSAEADDRINUSE:
    981       return DBUS_ERROR_ADDRESS_IN_USE;
    982 #endif
    983 #ifdef EEXIST
    984     case EEXIST:
    985       return DBUS_ERROR_FILE_EXISTS;
    986 #endif
    987 #ifdef ENOENT
    988     case ENOENT:
    989       return DBUS_ERROR_FILE_NOT_FOUND;
    990 #endif
    991     }
    992 
    993   return DBUS_ERROR_FAILED;
    994 }
    995 
    996 /**
    997  * Converts the current system errno value into a #DBusError name.
    998  *
    999  * @returns an error name
   1000  */
   1001 const char*
   1002 _dbus_error_from_system_errno (void)
   1003 {
   1004   return _dbus_error_from_errno (errno);
   1005 }
   1006 
   1007 /**
   1008  * Assign 0 to the global errno variable
   1009  */
   1010 void
   1011 _dbus_set_errno_to_zero (void)
   1012 {
   1013 #ifdef DBUS_WINCE
   1014   SetLastError (0);
   1015 #else
   1016   errno = 0;
   1017 #endif
   1018 }
   1019 
   1020 /**
   1021  * See if errno is set
   1022  * @returns #TRUE if errno is not 0
   1023  */
   1024 dbus_bool_t
   1025 _dbus_get_is_errno_nonzero (void)
   1026 {
   1027   return errno != 0;
   1028 }
   1029 
   1030 /**
   1031  * See if errno is ENOMEM
   1032  * @returns #TRUE if errno == ENOMEM
   1033  */
   1034 dbus_bool_t
   1035 _dbus_get_is_errno_enomem (void)
   1036 {
   1037   return errno == ENOMEM;
   1038 }
   1039 
   1040 /**
   1041  * See if errno is EINTR
   1042  * @returns #TRUE if errno == EINTR
   1043  */
   1044 dbus_bool_t
   1045 _dbus_get_is_errno_eintr (void)
   1046 {
   1047   return errno == EINTR;
   1048 }
   1049 
   1050 /**
   1051  * See if errno is EPIPE
   1052  * @returns #TRUE if errno == EPIPE
   1053  */
   1054 dbus_bool_t
   1055 _dbus_get_is_errno_epipe (void)
   1056 {
   1057   return errno == EPIPE;
   1058 }
   1059 
   1060 /**
   1061  * Get error message from errno
   1062  * @returns _dbus_strerror(errno)
   1063  */
   1064 const char*
   1065 _dbus_strerror_from_errno (void)
   1066 {
   1067   return _dbus_strerror (errno);
   1068 }
   1069 
   1070 /** @} end of sysdeps */
   1071 
   1072 /* tests in dbus-sysdeps-util.c */
   1073