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