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