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