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