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