moved out DBusPipe implementation from into separate files
[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  * Split paths into a list of char strings
247  * 
248  * @param dirs string with pathes 
249  * @param suffix string concated to each path in dirs
250  * @param dir_list contains a list of splitted pathes
251  * return #TRUE is pathes could be splittes,#FALSE in oom case 
252  */
253 dbus_bool_t
254 _dbus_split_paths_and_append (DBusString *dirs, 
255                               const char *suffix, 
256                               DBusList  **dir_list)
257 {
258    int start;
259    int i;
260    int len;
261    char *cpath;
262    DBusString file_suffix;
263
264    start = 0;
265    i = 0;
266
267    _dbus_string_init_const (&file_suffix, suffix);
268
269    len = _dbus_string_get_length (dirs);
270
271    while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
272      {
273        DBusString path;
274
275        if (!_dbus_string_init (&path))
276           goto oom;
277
278        if (!_dbus_string_copy_len (dirs,
279                                    start,
280                                    i - start,
281                                    &path,
282                                    0))
283           {
284             _dbus_string_free (&path);
285             goto oom;
286           }
287
288         _dbus_string_chop_white (&path);
289
290         /* check for an empty path */
291         if (_dbus_string_get_length (&path) == 0)
292           goto next;
293
294         if (!_dbus_concat_dir_and_file (&path,
295                                         &file_suffix))
296           {
297             _dbus_string_free (&path);
298             goto oom;
299           }
300
301         if (!_dbus_string_copy_data(&path, &cpath))
302           {
303             _dbus_string_free (&path);
304             goto oom;
305           }
306
307         if (!_dbus_list_append (dir_list, cpath))
308           {
309             _dbus_string_free (&path);              
310             dbus_free (cpath);
311             goto oom;
312           }
313
314        next:
315         _dbus_string_free (&path);
316         start = i + 1;
317     } 
318       
319   if (start != len)
320     { 
321       DBusString path;
322
323       if (!_dbus_string_init (&path))
324         goto oom;
325
326       if (!_dbus_string_copy_len (dirs,
327                                   start,
328                                   len - start,
329                                   &path,
330                                   0))
331         {
332           _dbus_string_free (&path);
333           goto oom;
334         }
335
336       if (!_dbus_concat_dir_and_file (&path,
337                                       &file_suffix))
338         {
339           _dbus_string_free (&path);
340           goto oom;
341         }
342
343       if (!_dbus_string_copy_data(&path, &cpath))
344         {
345           _dbus_string_free (&path);
346           goto oom;
347         }
348
349       if (!_dbus_list_append (dir_list, cpath))
350         {
351           _dbus_string_free (&path);              
352           dbus_free (cpath);
353           goto oom;
354         }
355
356       _dbus_string_free (&path); 
357     }
358
359   return TRUE;
360
361  oom:
362   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
363   _dbus_list_clear (dir_list);
364   return FALSE;
365 }
366
367 /** @} */
368
369 /**
370  * @addtogroup DBusString
371  *
372  * @{
373  */
374 /**
375  * Appends an integer to a DBusString.
376  * 
377  * @param str the string
378  * @param value the integer value
379  * @returns #FALSE if not enough memory or other failure.
380  */
381 dbus_bool_t
382 _dbus_string_append_int (DBusString *str,
383                          long        value)
384 {
385   /* this calculation is from comp.lang.c faq */
386 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
387   int orig_len;
388   int i;
389   char *buf;
390   
391   orig_len = _dbus_string_get_length (str);
392
393   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
394     return FALSE;
395
396   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
397
398   snprintf (buf, MAX_LONG_LEN, "%ld", value);
399
400   i = 0;
401   while (*buf)
402     {
403       ++buf;
404       ++i;
405     }
406   
407   _dbus_string_shorten (str, MAX_LONG_LEN - i);
408   
409   return TRUE;
410 }
411
412 /**
413  * Appends an unsigned integer to a DBusString.
414  * 
415  * @param str the string
416  * @param value the integer value
417  * @returns #FALSE if not enough memory or other failure.
418  */
419 dbus_bool_t
420 _dbus_string_append_uint (DBusString    *str,
421                           unsigned long  value)
422 {
423   /* this is wrong, but definitely on the high side. */
424 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
425   int orig_len;
426   int i;
427   char *buf;
428   
429   orig_len = _dbus_string_get_length (str);
430
431   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
432     return FALSE;
433
434   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
435
436   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
437
438   i = 0;
439   while (*buf)
440     {
441       ++buf;
442       ++i;
443     }
444   
445   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
446   
447   return TRUE;
448 }
449
450 #ifdef DBUS_BUILD_TESTS
451 /**
452  * Appends a double to a DBusString.
453  * 
454  * @param str the string
455  * @param value the floating point value
456  * @returns #FALSE if not enough memory or other failure.
457  */
458 dbus_bool_t
459 _dbus_string_append_double (DBusString *str,
460                             double      value)
461 {
462 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
463   int orig_len;
464   char *buf;
465   int i;
466   
467   orig_len = _dbus_string_get_length (str);
468
469   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
470     return FALSE;
471
472   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
473
474   snprintf (buf, MAX_LONG_LEN, "%g", value);
475
476   i = 0;
477   while (*buf)
478     {
479       ++buf;
480       ++i;
481     }
482   
483   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
484   
485   return TRUE;
486 }
487 #endif /* DBUS_BUILD_TESTS */
488
489 /**
490  * Parses an integer contained in a DBusString. Either return parameter
491  * may be #NULL if you aren't interested in it. The integer is parsed
492  * and stored in value_return. Return parameters are not initialized
493  * if the function returns #FALSE.
494  *
495  * @param str the string
496  * @param start the byte index of the start of the integer
497  * @param value_return return location of the integer value or #NULL
498  * @param end_return return location of the end of the integer, or #NULL
499  * @returns #TRUE on success
500  */
501 dbus_bool_t
502 _dbus_string_parse_int (const DBusString *str,
503                         int               start,
504                         long             *value_return,
505                         int              *end_return)
506 {
507   long v;
508   const char *p;
509   char *end;
510
511   p = _dbus_string_get_const_data_len (str, start,
512                                        _dbus_string_get_length (str) - start);
513
514   end = NULL;
515   errno = 0;
516   v = strtol (p, &end, 0);
517   if (end == NULL || end == p || errno != 0)
518     return FALSE;
519
520   if (value_return)
521     *value_return = v;
522   if (end_return)
523     *end_return = start + (end - p);
524
525   return TRUE;
526 }
527
528 /**
529  * Parses an unsigned integer contained in a DBusString. Either return
530  * parameter may be #NULL if you aren't interested in it. The integer
531  * is parsed and stored in value_return. Return parameters are not
532  * initialized if the function returns #FALSE.
533  *
534  * @param str the string
535  * @param start the byte index of the start of the integer
536  * @param value_return return location of the integer value or #NULL
537  * @param end_return return location of the end of the integer, or #NULL
538  * @returns #TRUE on success
539  */
540 dbus_bool_t
541 _dbus_string_parse_uint (const DBusString *str,
542                          int               start,
543                          unsigned long    *value_return,
544                          int              *end_return)
545 {
546   unsigned long v;
547   const char *p;
548   char *end;
549
550   p = _dbus_string_get_const_data_len (str, start,
551                                        _dbus_string_get_length (str) - start);
552
553   end = NULL;
554   errno = 0;
555   v = strtoul (p, &end, 0);
556   if (end == NULL || end == p || errno != 0)
557     return FALSE;
558
559   if (value_return)
560     *value_return = v;
561   if (end_return)
562     *end_return = start + (end - p);
563
564   return TRUE;
565 }
566
567 #ifdef DBUS_BUILD_TESTS
568 static dbus_bool_t
569 ascii_isspace (char c)
570 {
571   return (c == ' ' ||
572           c == '\f' ||
573           c == '\n' ||
574           c == '\r' ||
575           c == '\t' ||
576           c == '\v');
577 }
578 #endif /* DBUS_BUILD_TESTS */
579
580 #ifdef DBUS_BUILD_TESTS
581 static dbus_bool_t
582 ascii_isdigit (char c)
583 {
584   return c >= '0' && c <= '9';
585 }
586 #endif /* DBUS_BUILD_TESTS */
587
588 #ifdef DBUS_BUILD_TESTS
589 static dbus_bool_t
590 ascii_isxdigit (char c)
591 {
592   return (ascii_isdigit (c) ||
593           (c >= 'a' && c <= 'f') ||
594           (c >= 'A' && c <= 'F'));
595 }
596 #endif /* DBUS_BUILD_TESTS */
597
598 #ifdef DBUS_BUILD_TESTS
599 /* Calls strtod in a locale-independent fashion, by looking at
600  * the locale data and patching the decimal comma to a point.
601  *
602  * Relicensed from glib.
603  */
604 static double
605 ascii_strtod (const char *nptr,
606               char      **endptr)
607 {
608   /* FIXME: The Win32 C library's strtod() doesn't handle hex.
609    * Presumably many Unixes don't either.
610    */
611
612   char *fail_pos;
613   double val;
614   struct lconv *locale_data;
615   const char *decimal_point;
616   int decimal_point_len;
617   const char *p, *decimal_point_pos;
618   const char *end = NULL; /* Silence gcc */
619
620   fail_pos = NULL;
621
622   locale_data = localeconv ();
623   decimal_point = locale_data->decimal_point;
624   decimal_point_len = strlen (decimal_point);
625
626   _dbus_assert (decimal_point_len != 0);
627   
628   decimal_point_pos = NULL;
629   if (decimal_point[0] != '.' ||
630       decimal_point[1] != 0)
631     {
632       p = nptr;
633       /* Skip leading space */
634       while (ascii_isspace (*p))
635         p++;
636       
637       /* Skip leading optional sign */
638       if (*p == '+' || *p == '-')
639         p++;
640       
641       if (p[0] == '0' &&
642           (p[1] == 'x' || p[1] == 'X'))
643         {
644           p += 2;
645           /* HEX - find the (optional) decimal point */
646           
647           while (ascii_isxdigit (*p))
648             p++;
649           
650           if (*p == '.')
651             {
652               decimal_point_pos = p++;
653               
654               while (ascii_isxdigit (*p))
655                 p++;
656               
657               if (*p == 'p' || *p == 'P')
658                 p++;
659               if (*p == '+' || *p == '-')
660                 p++;
661               while (ascii_isdigit (*p))
662                 p++;
663               end = p;
664             }
665         }
666       else
667         {
668           while (ascii_isdigit (*p))
669             p++;
670           
671           if (*p == '.')
672             {
673               decimal_point_pos = p++;
674               
675               while (ascii_isdigit (*p))
676                 p++;
677               
678               if (*p == 'e' || *p == 'E')
679                 p++;
680               if (*p == '+' || *p == '-')
681                 p++;
682               while (ascii_isdigit (*p))
683                 p++;
684               end = p;
685             }
686         }
687       /* For the other cases, we need not convert the decimal point */
688     }
689
690   /* Set errno to zero, so that we can distinguish zero results
691      and underflows */
692   errno = 0;
693   
694   if (decimal_point_pos)
695     {
696       char *copy, *c;
697
698       /* We need to convert the '.' to the locale specific decimal point */
699       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
700       
701       c = copy;
702       memcpy (c, nptr, decimal_point_pos - nptr);
703       c += decimal_point_pos - nptr;
704       memcpy (c, decimal_point, decimal_point_len);
705       c += decimal_point_len;
706       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
707       c += end - (decimal_point_pos + 1);
708       *c = 0;
709
710       val = strtod (copy, &fail_pos);
711
712       if (fail_pos)
713         {
714           if (fail_pos > decimal_point_pos)
715             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
716           else
717             fail_pos = (char *)nptr + (fail_pos - copy);
718         }
719       
720       dbus_free (copy);
721           
722     }
723   else
724     val = strtod (nptr, &fail_pos);
725
726   if (endptr)
727     *endptr = fail_pos;
728   
729   return val;
730 }
731 #endif /* DBUS_BUILD_TESTS */
732
733 #ifdef DBUS_BUILD_TESTS
734 /**
735  * Parses a floating point number contained in a DBusString. Either
736  * return parameter may be #NULL if you aren't interested in it. The
737  * integer is parsed and stored in value_return. Return parameters are
738  * not initialized if the function returns #FALSE.
739  *
740  * @param str the string
741  * @param start the byte index of the start of the float
742  * @param value_return return location of the float value or #NULL
743  * @param end_return return location of the end of the float, or #NULL
744  * @returns #TRUE on success
745  */
746 dbus_bool_t
747 _dbus_string_parse_double (const DBusString *str,
748                            int               start,
749                            double           *value_return,
750                            int              *end_return)
751 {
752   double v;
753   const char *p;
754   char *end;
755
756   p = _dbus_string_get_const_data_len (str, start,
757                                        _dbus_string_get_length (str) - start);
758
759   /* parsing hex works on linux but isn't portable, so intercept it
760    * here to get uniform behavior.
761    */
762   if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
763     return FALSE;
764   
765   end = NULL;
766   errno = 0;
767   v = ascii_strtod (p, &end);
768   if (end == NULL || end == p || errno != 0)
769     return FALSE;
770
771   if (value_return)
772     *value_return = v;
773   if (end_return)
774     *end_return = start + (end - p);
775
776   return TRUE;
777 }
778 #endif /* DBUS_BUILD_TESTS */
779
780 /** @} */ /* DBusString group */
781
782 /**
783  * @addtogroup DBusInternalsUtils
784  * @{
785  */
786
787 void
788 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
789                                           int   n_bytes)
790 {
791   long tv_usec;
792   int i;
793   
794   /* fall back to pseudorandom */
795   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
796                  n_bytes);
797   
798   _dbus_get_current_time (NULL, &tv_usec);
799   srand (tv_usec);
800   
801   i = 0;
802   while (i < n_bytes)
803     {
804       double r;
805       unsigned int b;
806           
807       r = rand ();
808       b = (r / (double) RAND_MAX) * 255.0;
809
810       buffer[i] = b;
811
812       ++i;
813     }
814 }
815
816 /**
817  * Fills n_bytes of the given buffer with random bytes.
818  *
819  * @param buffer an allocated buffer
820  * @param n_bytes the number of bytes in buffer to write to
821  */
822 void
823 _dbus_generate_random_bytes_buffer (char *buffer,
824                                     int   n_bytes)
825 {
826   DBusString str;
827
828   if (!_dbus_string_init (&str))
829     {
830       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
831       return;
832     }
833
834   if (!_dbus_generate_random_bytes (&str, n_bytes))
835     {
836       _dbus_string_free (&str);
837       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
838       return;
839     }
840
841   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
842
843   _dbus_string_free (&str);
844 }
845
846 /**
847  * Generates the given number of random bytes, where the bytes are
848  * chosen from the alphanumeric ASCII subset.
849  *
850  * @param str the string
851  * @param n_bytes the number of random ASCII bytes to append to string
852  * @returns #TRUE on success, #FALSE if no memory or other failure
853  */
854 dbus_bool_t
855 _dbus_generate_random_ascii (DBusString *str,
856                              int         n_bytes)
857 {
858   static const char letters[] =
859     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
860   int i;
861   int len;
862   
863   if (!_dbus_generate_random_bytes (str, n_bytes))
864     return FALSE;
865   
866   len = _dbus_string_get_length (str);
867   i = len - n_bytes;
868   while (i < len)
869     {
870       _dbus_string_set_byte (str, i,
871                              letters[_dbus_string_get_byte (str, i) %
872                                      (sizeof (letters) - 1)]);
873
874       ++i;
875     }
876
877   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
878                                              n_bytes));
879
880   return TRUE;
881 }
882
883 /**
884  * Converts a UNIX errno, or Windows errno or WinSock error value into
885  * a #DBusError name.
886  *
887  * @todo should cover more errnos, specifically those
888  * from open().
889  * 
890  * @param error_number the errno.
891  * @returns an error name
892  */
893 const char*
894 _dbus_error_from_errno (int error_number)
895 {
896   switch (error_number)
897     {
898     case 0:
899       return DBUS_ERROR_FAILED;
900       
901 #ifdef EPROTONOSUPPORT
902     case EPROTONOSUPPORT:
903       return DBUS_ERROR_NOT_SUPPORTED;
904 #endif
905 #ifdef WSAEPROTONOSUPPORT
906     case WSAEPROTONOSUPPORT:
907       return DBUS_ERROR_NOT_SUPPORTED;
908 #endif
909 #ifdef EAFNOSUPPORT
910     case EAFNOSUPPORT:
911       return DBUS_ERROR_NOT_SUPPORTED;
912 #endif
913 #ifdef WSAEAFNOSUPPORT
914     case WSAEAFNOSUPPORT:
915       return DBUS_ERROR_NOT_SUPPORTED;
916 #endif
917 #ifdef ENFILE
918     case ENFILE:
919       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
920 #endif
921 #ifdef EMFILE
922     case EMFILE:
923       return DBUS_ERROR_LIMITS_EXCEEDED;
924 #endif
925 #ifdef EACCES
926     case EACCES:
927       return DBUS_ERROR_ACCESS_DENIED;
928 #endif
929 #ifdef EPERM
930     case EPERM:
931       return DBUS_ERROR_ACCESS_DENIED;
932 #endif
933 #ifdef ENOBUFS
934     case ENOBUFS:
935       return DBUS_ERROR_NO_MEMORY;
936 #endif
937 #ifdef ENOMEM
938     case ENOMEM:
939       return DBUS_ERROR_NO_MEMORY;
940 #endif
941 #ifdef ECONNREFUSED
942     case ECONNREFUSED:
943       return DBUS_ERROR_NO_SERVER;
944 #endif
945 #ifdef WSAECONNREFUSED
946     case WSAECONNREFUSED:
947       return DBUS_ERROR_NO_SERVER;
948 #endif
949 #ifdef ETIMEDOUT
950     case ETIMEDOUT:
951       return DBUS_ERROR_TIMEOUT;
952 #endif
953 #ifdef WSAETIMEDOUT
954     case WSAETIMEDOUT:
955       return DBUS_ERROR_TIMEOUT;
956 #endif
957 #ifdef ENETUNREACH
958     case ENETUNREACH:
959       return DBUS_ERROR_NO_NETWORK;
960 #endif
961 #ifdef WSAENETUNREACH
962     case WSAENETUNREACH:
963       return DBUS_ERROR_NO_NETWORK;
964 #endif
965 #ifdef EADDRINUSE
966     case EADDRINUSE:
967       return DBUS_ERROR_ADDRESS_IN_USE;
968 #endif
969 #ifdef WSAEADDRINUSE
970     case WSAEADDRINUSE:
971       return DBUS_ERROR_ADDRESS_IN_USE;
972 #endif
973 #ifdef EEXIST
974     case EEXIST:
975       return DBUS_ERROR_FILE_EXISTS;
976 #endif
977 #ifdef ENOENT
978     case ENOENT:
979       return DBUS_ERROR_FILE_NOT_FOUND;
980 #endif
981     }
982
983   return DBUS_ERROR_FAILED;
984 }
985
986 /**
987  * Assign 0 to the global errno variable
988  */
989 void
990 _dbus_set_errno_to_zero (void)
991 {
992   errno = 0;
993 }
994
995 /**
996  * See if errno is set
997  * @returns #TRUE if errno is not 0
998  */
999 dbus_bool_t
1000 _dbus_get_is_errno_nonzero (void)
1001 {
1002   return errno != 0;
1003 }
1004
1005 /**
1006  * See if errno is ENOMEM
1007  * @returns #TRUE if errno == ENOMEM
1008  */
1009 dbus_bool_t
1010 _dbus_get_is_errno_enomem (void)
1011 {
1012   return errno == ENOMEM;
1013 }
1014
1015 /**
1016  * See if errno is EINTR
1017  * @returns #TRUE if errno == EINTR
1018  */
1019 dbus_bool_t
1020 _dbus_get_is_errno_eintr (void)
1021 {
1022   return errno == EINTR;
1023 }
1024
1025 /**
1026  * See if errno is EPIPE
1027  * @returns #TRUE if errno == EPIPE
1028  */
1029 dbus_bool_t
1030 _dbus_get_is_errno_epipe (void)
1031 {
1032   return errno == EPIPE;
1033 }
1034
1035 /**
1036  * Get error message from errno
1037  * @returns _dbus_strerror(errno)
1038  */
1039 const char*
1040 _dbus_strerror_from_errno (void)
1041 {
1042   return _dbus_strerror (errno);
1043 }
1044
1045 /** @} end of sysdeps */
1046
1047 /* tests in dbus-sysdeps-util.c */