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