2007-06-15 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   end = NULL;
754   errno = 0;
755   v = ascii_strtod (p, &end);
756   if (end == NULL || end == p || errno != 0)
757     return FALSE;
758
759   if (value_return)
760     *value_return = v;
761   if (end_return)
762     *end_return = start + (end - p);
763
764   return TRUE;
765 }
766 #endif /* DBUS_BUILD_TESTS */
767
768 /** @} */ /* DBusString group */
769
770 /**
771  * @addtogroup DBusInternalsUtils
772  * @{
773  */
774
775 void
776 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
777                                           int   n_bytes)
778 {
779   long tv_usec;
780   int i;
781   
782   /* fall back to pseudorandom */
783   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
784                  n_bytes);
785   
786   _dbus_get_current_time (NULL, &tv_usec);
787   srand (tv_usec);
788   
789   i = 0;
790   while (i < n_bytes)
791     {
792       double r;
793       unsigned int b;
794           
795       r = rand ();
796       b = (r / (double) RAND_MAX) * 255.0;
797
798       buffer[i] = b;
799
800       ++i;
801     }
802 }
803
804 /**
805  * Fills n_bytes of the given buffer with random bytes.
806  *
807  * @param buffer an allocated buffer
808  * @param n_bytes the number of bytes in buffer to write to
809  */
810 void
811 _dbus_generate_random_bytes_buffer (char *buffer,
812                                     int   n_bytes)
813 {
814   DBusString str;
815
816   if (!_dbus_string_init (&str))
817     {
818       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
819       return;
820     }
821
822   if (!_dbus_generate_random_bytes (&str, n_bytes))
823     {
824       _dbus_string_free (&str);
825       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
826       return;
827     }
828
829   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
830
831   _dbus_string_free (&str);
832 }
833
834 /**
835  * Generates the given number of random bytes, where the bytes are
836  * chosen from the alphanumeric ASCII subset.
837  *
838  * @param str the string
839  * @param n_bytes the number of random ASCII bytes to append to string
840  * @returns #TRUE on success, #FALSE if no memory or other failure
841  */
842 dbus_bool_t
843 _dbus_generate_random_ascii (DBusString *str,
844                              int         n_bytes)
845 {
846   static const char letters[] =
847     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
848   int i;
849   int len;
850   
851   if (!_dbus_generate_random_bytes (str, n_bytes))
852     return FALSE;
853   
854   len = _dbus_string_get_length (str);
855   i = len - n_bytes;
856   while (i < len)
857     {
858       _dbus_string_set_byte (str, i,
859                              letters[_dbus_string_get_byte (str, i) %
860                                      (sizeof (letters) - 1)]);
861
862       ++i;
863     }
864
865   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
866                                              n_bytes));
867
868   return TRUE;
869 }
870
871 /**
872  * Converts a UNIX or Windows errno
873  * into a #DBusError name.
874  *
875  * @todo should cover more errnos, specifically those
876  * from open().
877  * 
878  * @param error_number the errno.
879  * @returns an error name
880  */
881 const char*
882 _dbus_error_from_errno (int error_number)
883 {
884   switch (error_number)
885     {
886     case 0:
887       return DBUS_ERROR_FAILED;
888       
889 #ifdef EPROTONOSUPPORT
890     case EPROTONOSUPPORT:
891       return DBUS_ERROR_NOT_SUPPORTED;
892 #endif
893 #ifdef EAFNOSUPPORT
894     case EAFNOSUPPORT:
895       return DBUS_ERROR_NOT_SUPPORTED;
896 #endif
897 #ifdef ENFILE
898     case ENFILE:
899       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
900 #endif
901 #ifdef EMFILE
902     case EMFILE:
903       return DBUS_ERROR_LIMITS_EXCEEDED;
904 #endif
905 #ifdef EACCES
906     case EACCES:
907       return DBUS_ERROR_ACCESS_DENIED;
908 #endif
909 #ifdef EPERM
910     case EPERM:
911       return DBUS_ERROR_ACCESS_DENIED;
912 #endif
913 #ifdef ENOBUFS
914     case ENOBUFS:
915       return DBUS_ERROR_NO_MEMORY;
916 #endif
917 #ifdef ENOMEM
918     case ENOMEM:
919       return DBUS_ERROR_NO_MEMORY;
920 #endif
921 #ifdef EINVAL
922     case EINVAL:
923       return DBUS_ERROR_FAILED;
924 #endif
925 #ifdef EBADF
926     case EBADF:
927       return DBUS_ERROR_FAILED;
928 #endif
929 #ifdef EFAULT
930     case EFAULT:
931       return DBUS_ERROR_FAILED;
932 #endif
933 #ifdef ENOTSOCK
934     case ENOTSOCK:
935       return DBUS_ERROR_FAILED;
936 #endif
937 #ifdef EISCONN
938     case EISCONN:
939       return DBUS_ERROR_FAILED;
940 #endif
941 #ifdef ECONNREFUSED
942     case ECONNREFUSED:
943       return DBUS_ERROR_NO_SERVER;
944 #endif
945 #ifdef ETIMEDOUT
946     case ETIMEDOUT:
947       return DBUS_ERROR_TIMEOUT;
948 #endif
949 #ifdef ENETUNREACH
950     case ENETUNREACH:
951       return DBUS_ERROR_NO_NETWORK;
952 #endif
953 #ifdef EADDRINUSE
954     case EADDRINUSE:
955       return DBUS_ERROR_ADDRESS_IN_USE;
956 #endif
957 #ifdef EEXIST
958     case EEXIST:
959       return DBUS_ERROR_FILE_EXISTS;
960 #endif
961 #ifdef ENOENT
962     case ENOENT:
963       return DBUS_ERROR_FILE_NOT_FOUND;
964 #endif
965     }
966
967   return DBUS_ERROR_FAILED;
968 }
969
970 /**
971  * Assign 0 to the global errno variable
972  */
973 void
974 _dbus_set_errno_to_zero (void)
975 {
976   errno = 0;
977 }
978
979 /**
980  * See if errno is set
981  * @returns #TRUE if errno is not 0
982  */
983 dbus_bool_t
984 _dbus_get_is_errno_nonzero (void)
985 {
986   return errno != 0;
987 }
988
989 /**
990  * See if errno is ENOMEM
991  * @returns #TRUE if errno == ENOMEM
992  */
993 dbus_bool_t
994 _dbus_get_is_errno_enomem (void)
995 {
996   return errno == ENOMEM;
997 }
998
999 /**
1000  * See if errno is EINTR
1001  * @returns #TRUE if errno == EINTR
1002  */
1003 dbus_bool_t
1004 _dbus_get_is_errno_eintr (void)
1005 {
1006   return errno == EINTR;
1007 }
1008
1009 /**
1010  * Get error message from errno
1011  * @returns _dbus_strerror(errno)
1012  */
1013 const char*
1014 _dbus_strerror_from_errno (void)
1015 {
1016   return _dbus_strerror (errno);
1017 }
1018
1019 /** @} end of sysdeps */
1020
1021 /* tests in dbus-sysdeps-util.c */