Merge branch 'dbus-1.6'
[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 <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-sysdeps.h"
28 #include "dbus-threads.h"
29 #include "dbus-protocol.h"
30 #include "dbus-string.h"
31 #include "dbus-list.h"
32
33 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
34  * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
35  *
36  * These are the standard ANSI C headers...
37  */
38 #if HAVE_LOCALE_H
39 #include <locale.h>
40 #endif
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdio.h>
44
45 #ifdef HAVE_ERRNO_H
46 #include <errno.h>
47 #endif
48
49 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
50
51 #ifdef DBUS_WIN
52   #include <stdlib.h>
53 #elif (defined __APPLE__)
54 # include <crt_externs.h>
55 # define environ (*_NSGetEnviron())
56 #else
57 extern char **environ;
58 #endif
59
60 /**
61  * @defgroup DBusSysdeps Internal system-dependent API
62  * @ingroup DBusInternals
63  * @brief Internal system-dependent API available on UNIX and Windows
64  *
65  * The system-dependent API has a dual purpose. First, it encapsulates
66  * all usage of operating system APIs for ease of auditing and to
67  * avoid cluttering the rest of the code with bizarre OS quirks and
68  * headers. Second, it abstracts different operating system APIs for
69  * portability.
70  * 
71  * @{
72  */
73
74 /**
75  * Aborts the program with SIGABRT (dumping core).
76  */
77 void
78 _dbus_abort (void)
79 {
80   const char *s;
81   
82   _dbus_print_backtrace ();
83   
84   s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
85   if (s && *s)
86     {
87       /* don't use _dbus_warn here since it can _dbus_abort() */
88       fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
89       _dbus_sleep_milliseconds (1000 * 180);
90     }
91   
92   abort ();
93   _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
94 }
95
96 /**
97  * Wrapper for setenv(). If the value is #NULL, unsets
98  * the environment variable.
99  *
100  * There is an unfixable memleak in that it is unsafe to
101  * free memory malloced for use with setenv. This is because
102  * we can not rely on internal implementation details of
103  * the underlying libc library.
104  *
105  * @param varname name of environment variable
106  * @param value value of environment variable
107  * @returns #TRUE on success.
108  */
109 dbus_bool_t
110 _dbus_setenv (const char *varname,
111               const char *value)
112 {
113   _dbus_assert (varname != NULL);
114   
115   if (value == NULL)
116     {
117 #ifdef HAVE_UNSETENV
118       unsetenv (varname);
119       return TRUE;
120 #else
121       char *putenv_value;
122       size_t len;
123
124       len = strlen (varname);
125
126       /* Use system malloc to avoid memleaks that dbus_malloc
127        * will get upset about.
128        */
129       
130       putenv_value = malloc (len + 2);
131       if (putenv_value == NULL)
132         return FALSE;
133
134       strcpy (putenv_value, varname);
135 #if defined(DBUS_WIN)
136       strcat (putenv_value, "=");
137 #endif
138       
139       return (putenv (putenv_value) == 0);
140 #endif
141     }
142   else
143     {
144 #ifdef HAVE_SETENV
145       return (setenv (varname, value, TRUE) == 0);
146 #else
147       char *putenv_value;
148       size_t len;
149       size_t varname_len;
150       size_t value_len;
151
152       varname_len = strlen (varname);
153       value_len = strlen (value);
154       
155       len = varname_len + value_len + 1 /* '=' */ ;
156
157       /* Use system malloc to avoid memleaks that dbus_malloc
158        * will get upset about.
159        */
160       
161       putenv_value = malloc (len + 1);
162       if (putenv_value == NULL)
163         return FALSE;
164
165       strcpy (putenv_value, varname);
166       strcpy (putenv_value + varname_len, "=");
167       strcpy (putenv_value + varname_len + 1, value);
168       
169       return (putenv (putenv_value) == 0);
170 #endif
171     }
172 }
173
174 /**
175  * Wrapper for getenv().
176  *
177  * @param varname name of environment variable
178  * @returns value of environment variable or #NULL if unset
179  */
180 const char*
181 _dbus_getenv (const char *varname)
182 {  
183   /* Don't respect any environment variables if the current process is
184    * setuid.  This is the equivalent of glibc's __secure_getenv().
185    */
186   if (_dbus_check_setuid ())
187     return NULL;
188   return getenv (varname);
189 }
190
191 /**
192  * Wrapper for clearenv().
193  *
194  * @returns #TRUE on success.
195  */
196 dbus_bool_t
197 _dbus_clearenv (void)
198 {
199   dbus_bool_t rc = TRUE;
200
201 #ifdef HAVE_CLEARENV
202   if (clearenv () != 0)
203      rc = FALSE;
204 #else
205
206   if (environ != NULL)
207     environ[0] = NULL;
208 #endif
209
210   return rc;
211 }
212
213 /**
214  * Split paths into a list of char strings
215  * 
216  * @param dirs string with pathes 
217  * @param suffix string concated to each path in dirs
218  * @param dir_list contains a list of splitted pathes
219  * return #TRUE is pathes could be splittes,#FALSE in oom case 
220  */
221 dbus_bool_t
222 _dbus_split_paths_and_append (DBusString *dirs, 
223                               const char *suffix, 
224                               DBusList  **dir_list)
225 {
226    int start;
227    int i;
228    int len;
229    char *cpath;
230    DBusString file_suffix;
231
232    start = 0;
233    i = 0;
234
235    _dbus_string_init_const (&file_suffix, suffix);
236
237    len = _dbus_string_get_length (dirs);
238
239    while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
240      {
241        DBusString path;
242
243        if (!_dbus_string_init (&path))
244           goto oom;
245
246        if (!_dbus_string_copy_len (dirs,
247                                    start,
248                                    i - start,
249                                    &path,
250                                    0))
251           {
252             _dbus_string_free (&path);
253             goto oom;
254           }
255
256         _dbus_string_chop_white (&path);
257
258         /* check for an empty path */
259         if (_dbus_string_get_length (&path) == 0)
260           goto next;
261
262         if (!_dbus_concat_dir_and_file (&path,
263                                         &file_suffix))
264           {
265             _dbus_string_free (&path);
266             goto oom;
267           }
268
269         if (!_dbus_string_copy_data(&path, &cpath))
270           {
271             _dbus_string_free (&path);
272             goto oom;
273           }
274
275         if (!_dbus_list_append (dir_list, cpath))
276           {
277             _dbus_string_free (&path);              
278             dbus_free (cpath);
279             goto oom;
280           }
281
282        next:
283         _dbus_string_free (&path);
284         start = i + 1;
285     } 
286       
287   if (start != len)
288     { 
289       DBusString path;
290
291       if (!_dbus_string_init (&path))
292         goto oom;
293
294       if (!_dbus_string_copy_len (dirs,
295                                   start,
296                                   len - start,
297                                   &path,
298                                   0))
299         {
300           _dbus_string_free (&path);
301           goto oom;
302         }
303
304       if (!_dbus_concat_dir_and_file (&path,
305                                       &file_suffix))
306         {
307           _dbus_string_free (&path);
308           goto oom;
309         }
310
311       if (!_dbus_string_copy_data(&path, &cpath))
312         {
313           _dbus_string_free (&path);
314           goto oom;
315         }
316
317       if (!_dbus_list_append (dir_list, cpath))
318         {
319           _dbus_string_free (&path);              
320           dbus_free (cpath);
321           goto oom;
322         }
323
324       _dbus_string_free (&path); 
325     }
326
327   return TRUE;
328
329  oom:
330   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
331   _dbus_list_clear (dir_list);
332   return FALSE;
333 }
334
335 /** @} */
336
337 /**
338  * @addtogroup DBusString
339  *
340  * @{
341  */
342 /**
343  * Appends an integer to a DBusString.
344  * 
345  * @param str the string
346  * @param value the integer value
347  * @returns #FALSE if not enough memory or other failure.
348  */
349 dbus_bool_t
350 _dbus_string_append_int (DBusString *str,
351                          long        value)
352 {
353   /* this calculation is from comp.lang.c faq */
354 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
355   int orig_len;
356   int i;
357   char *buf;
358   
359   orig_len = _dbus_string_get_length (str);
360
361   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
362     return FALSE;
363
364   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
365
366   snprintf (buf, MAX_LONG_LEN, "%ld", value);
367
368   i = 0;
369   while (*buf)
370     {
371       ++buf;
372       ++i;
373     }
374   
375   _dbus_string_shorten (str, MAX_LONG_LEN - i);
376   
377   return TRUE;
378 }
379
380 /**
381  * Appends an unsigned integer to a DBusString.
382  * 
383  * @param str the string
384  * @param value the integer value
385  * @returns #FALSE if not enough memory or other failure.
386  */
387 dbus_bool_t
388 _dbus_string_append_uint (DBusString    *str,
389                           unsigned long  value)
390 {
391   /* this is wrong, but definitely on the high side. */
392 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
393   int orig_len;
394   int i;
395   char *buf;
396   
397   orig_len = _dbus_string_get_length (str);
398
399   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
400     return FALSE;
401
402   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
403
404   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
405
406   i = 0;
407   while (*buf)
408     {
409       ++buf;
410       ++i;
411     }
412   
413   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
414   
415   return TRUE;
416 }
417
418 /**
419  * Parses an integer contained in a DBusString. Either return parameter
420  * may be #NULL if you aren't interested in it. The integer is parsed
421  * and stored in value_return. Return parameters are not initialized
422  * if the function returns #FALSE.
423  *
424  * @param str the string
425  * @param start the byte index of the start of the integer
426  * @param value_return return location of the integer value or #NULL
427  * @param end_return return location of the end of the integer, or #NULL
428  * @returns #TRUE on success
429  */
430 dbus_bool_t
431 _dbus_string_parse_int (const DBusString *str,
432                         int               start,
433                         long             *value_return,
434                         int              *end_return)
435 {
436   long v;
437   const char *p;
438   char *end;
439
440   p = _dbus_string_get_const_data_len (str, start,
441                                        _dbus_string_get_length (str) - start);
442
443   end = NULL;
444   _dbus_set_errno_to_zero ();
445   v = strtol (p, &end, 0);
446   if (end == NULL || end == p || errno != 0)
447     return FALSE;
448
449   if (value_return)
450     *value_return = v;
451   if (end_return)
452     *end_return = start + (end - p);
453
454   return TRUE;
455 }
456
457 /**
458  * Parses an unsigned integer contained in a DBusString. Either return
459  * parameter may be #NULL if you aren't interested in it. The integer
460  * is parsed and stored in value_return. Return parameters are not
461  * initialized if the function returns #FALSE.
462  *
463  * @param str the string
464  * @param start the byte index of the start of the integer
465  * @param value_return return location of the integer value or #NULL
466  * @param end_return return location of the end of the integer, or #NULL
467  * @returns #TRUE on success
468  */
469 dbus_bool_t
470 _dbus_string_parse_uint (const DBusString *str,
471                          int               start,
472                          unsigned long    *value_return,
473                          int              *end_return)
474 {
475   unsigned long v;
476   const char *p;
477   char *end;
478
479   p = _dbus_string_get_const_data_len (str, start,
480                                        _dbus_string_get_length (str) - start);
481
482   end = NULL;
483   _dbus_set_errno_to_zero ();
484   v = strtoul (p, &end, 0);
485   if (end == NULL || end == p || errno != 0)
486     return FALSE;
487
488   if (value_return)
489     *value_return = v;
490   if (end_return)
491     *end_return = start + (end - p);
492
493   return TRUE;
494 }
495
496 /** @} */ /* DBusString group */
497
498 /**
499  * @addtogroup DBusInternalsUtils
500  * @{
501  */
502
503 void
504 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
505                                           int   n_bytes)
506 {
507   long tv_usec;
508   int i;
509   
510   /* fall back to pseudorandom */
511   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
512                  n_bytes);
513   
514   _dbus_get_real_time (NULL, &tv_usec);
515   srand (tv_usec);
516   
517   i = 0;
518   while (i < n_bytes)
519     {
520       double r;
521       unsigned int b;
522           
523       r = rand ();
524       b = (r / (double) RAND_MAX) * 255.0;
525
526       buffer[i] = b;
527
528       ++i;
529     }
530 }
531
532 /**
533  * Fills n_bytes of the given buffer with random bytes.
534  *
535  * @param buffer an allocated buffer
536  * @param n_bytes the number of bytes in buffer to write to
537  */
538 void
539 _dbus_generate_random_bytes_buffer (char *buffer,
540                                     int   n_bytes)
541 {
542   DBusString str;
543
544   if (!_dbus_string_init (&str))
545     {
546       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
547       return;
548     }
549
550   if (!_dbus_generate_random_bytes (&str, n_bytes))
551     {
552       _dbus_string_free (&str);
553       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
554       return;
555     }
556
557   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
558
559   _dbus_string_free (&str);
560 }
561
562 /**
563  * Generates the given number of random bytes, where the bytes are
564  * chosen from the alphanumeric ASCII subset.
565  *
566  * @param str the string
567  * @param n_bytes the number of random ASCII bytes to append to string
568  * @returns #TRUE on success, #FALSE if no memory or other failure
569  */
570 dbus_bool_t
571 _dbus_generate_random_ascii (DBusString *str,
572                              int         n_bytes)
573 {
574   static const char letters[] =
575     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
576   int i;
577   int len;
578   
579   if (!_dbus_generate_random_bytes (str, n_bytes))
580     return FALSE;
581   
582   len = _dbus_string_get_length (str);
583   i = len - n_bytes;
584   while (i < len)
585     {
586       _dbus_string_set_byte (str, i,
587                              letters[_dbus_string_get_byte (str, i) %
588                                      (sizeof (letters) - 1)]);
589
590       ++i;
591     }
592
593   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
594                                              n_bytes));
595
596   return TRUE;
597 }
598
599 /**
600  * Converts a UNIX errno, or Windows errno or WinSock error value into
601  * a #DBusError name.
602  *
603  * @todo should cover more errnos, specifically those
604  * from open().
605  * 
606  * @param error_number the errno.
607  * @returns an error name
608  */
609 const char*
610 _dbus_error_from_errno (int error_number)
611 {
612   switch (error_number)
613     {
614     case 0:
615       return DBUS_ERROR_FAILED;
616       
617 #ifdef EPROTONOSUPPORT
618     case EPROTONOSUPPORT:
619       return DBUS_ERROR_NOT_SUPPORTED;
620 #elif defined(WSAEPROTONOSUPPORT)
621     case WSAEPROTONOSUPPORT:
622       return DBUS_ERROR_NOT_SUPPORTED;
623 #endif
624 #ifdef EAFNOSUPPORT
625     case EAFNOSUPPORT:
626       return DBUS_ERROR_NOT_SUPPORTED;
627 #elif defined(WSAEAFNOSUPPORT)
628     case WSAEAFNOSUPPORT:
629       return DBUS_ERROR_NOT_SUPPORTED;
630 #endif
631 #ifdef ENFILE
632     case ENFILE:
633       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
634 #endif
635 #ifdef EMFILE
636     case EMFILE:
637       return DBUS_ERROR_LIMITS_EXCEEDED;
638 #endif
639 #ifdef EACCES
640     case EACCES:
641       return DBUS_ERROR_ACCESS_DENIED;
642 #endif
643 #ifdef EPERM
644     case EPERM:
645       return DBUS_ERROR_ACCESS_DENIED;
646 #endif
647 #ifdef ENOBUFS
648     case ENOBUFS:
649       return DBUS_ERROR_NO_MEMORY;
650 #endif
651 #ifdef ENOMEM
652     case ENOMEM:
653       return DBUS_ERROR_NO_MEMORY;
654 #endif
655 #ifdef ECONNREFUSED
656     case ECONNREFUSED:
657       return DBUS_ERROR_NO_SERVER;
658 #elif defined(WSAECONNREFUSED)
659     case WSAECONNREFUSED:
660       return DBUS_ERROR_NO_SERVER;
661 #endif
662 #ifdef ETIMEDOUT
663     case ETIMEDOUT:
664       return DBUS_ERROR_TIMEOUT;
665 #elif defined(WSAETIMEDOUT)
666     case WSAETIMEDOUT:
667       return DBUS_ERROR_TIMEOUT;
668 #endif
669 #ifdef ENETUNREACH
670     case ENETUNREACH:
671       return DBUS_ERROR_NO_NETWORK;
672 #elif defined(WSAENETUNREACH)
673     case WSAENETUNREACH:
674       return DBUS_ERROR_NO_NETWORK;
675 #endif
676 #ifdef EADDRINUSE
677     case EADDRINUSE:
678       return DBUS_ERROR_ADDRESS_IN_USE;
679 #elif defined(WSAEADDRINUSE)
680     case WSAEADDRINUSE:
681       return DBUS_ERROR_ADDRESS_IN_USE;
682 #endif
683 #ifdef EEXIST
684     case EEXIST:
685       return DBUS_ERROR_FILE_EXISTS;
686 #endif
687 #ifdef ENOENT
688     case ENOENT:
689       return DBUS_ERROR_FILE_NOT_FOUND;
690 #endif
691     }
692
693   return DBUS_ERROR_FAILED;
694 }
695
696 /**
697  * Converts the current system errno value into a #DBusError name.
698  *
699  * @returns an error name
700  */
701 const char*
702 _dbus_error_from_system_errno (void)
703 {
704   return _dbus_error_from_errno (errno);
705 }
706
707 /**
708  * Assign 0 to the global errno variable
709  */
710 void
711 _dbus_set_errno_to_zero (void)
712 {
713 #ifdef DBUS_WINCE
714   SetLastError (0);
715 #else
716   errno = 0;
717 #endif
718 }
719
720 /**
721  * See if errno is set
722  * @returns #TRUE if errno is not 0
723  */
724 dbus_bool_t
725 _dbus_get_is_errno_nonzero (void)
726 {
727   return errno != 0;
728 }
729
730 /**
731  * See if errno is ENOMEM
732  * @returns #TRUE if errno == ENOMEM
733  */
734 dbus_bool_t
735 _dbus_get_is_errno_enomem (void)
736 {
737   return errno == ENOMEM;
738 }
739
740 /**
741  * See if errno is EINTR
742  * @returns #TRUE if errno == EINTR
743  */
744 dbus_bool_t
745 _dbus_get_is_errno_eintr (void)
746 {
747   return errno == EINTR;
748 }
749
750 /**
751  * See if errno is EPIPE
752  * @returns #TRUE if errno == EPIPE
753  */
754 dbus_bool_t
755 _dbus_get_is_errno_epipe (void)
756 {
757   return errno == EPIPE;
758 }
759
760 /**
761  * Get error message from errno
762  * @returns _dbus_strerror(errno)
763  */
764 const char*
765 _dbus_strerror_from_errno (void)
766 {
767   return _dbus_strerror (errno);
768 }
769
770 /** @} end of sysdeps */
771
772 /* tests in dbus-sysdeps-util.c */