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