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