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)
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
7 * Licensed under the Academic Free License version 2.1
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.
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.
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
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"
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.
36 * These are the standard ANSI C headers...
49 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
53 #elif (defined __APPLE__)
54 # include <crt_externs.h>
55 # define environ (*_NSGetEnviron())
57 extern char **environ;
61 * @defgroup DBusSysdeps Internal system-dependent API
62 * @ingroup DBusInternals
63 * @brief Internal system-dependent API available on UNIX and Windows
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
75 * Aborts the program with SIGABRT (dumping core).
82 _dbus_print_backtrace ();
84 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
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);
93 _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
97 * Wrapper for setenv(). If the value is #NULL, unsets
98 * the environment variable.
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.
105 * @param varname name of environment variable
106 * @param value value of environment variable
107 * @returns #TRUE on success.
110 _dbus_setenv (const char *varname,
113 _dbus_assert (varname != NULL);
124 len = strlen (varname);
126 /* Use system malloc to avoid memleaks that dbus_malloc
127 * will get upset about.
130 putenv_value = malloc (len + 2);
131 if (putenv_value == NULL)
134 strcpy (putenv_value, varname);
135 #if defined(DBUS_WIN)
136 strcat (putenv_value, "=");
139 return (putenv (putenv_value) == 0);
145 return (setenv (varname, value, TRUE) == 0);
152 varname_len = strlen (varname);
153 value_len = strlen (value);
155 len = varname_len + value_len + 1 /* '=' */ ;
157 /* Use system malloc to avoid memleaks that dbus_malloc
158 * will get upset about.
161 putenv_value = malloc (len + 1);
162 if (putenv_value == NULL)
165 strcpy (putenv_value, varname);
166 strcpy (putenv_value + varname_len, "=");
167 strcpy (putenv_value + varname_len + 1, value);
169 return (putenv (putenv_value) == 0);
175 * Wrapper for getenv().
177 * @param varname name of environment variable
178 * @returns value of environment variable or #NULL if unset
181 _dbus_getenv (const char *varname)
183 /* Don't respect any environment variables if the current process is
184 * setuid. This is the equivalent of glibc's __secure_getenv().
186 if (_dbus_check_setuid ())
188 return getenv (varname);
192 * Wrapper for clearenv().
194 * @returns #TRUE on success.
197 _dbus_clearenv (void)
199 dbus_bool_t rc = TRUE;
202 if (clearenv () != 0)
214 * Split paths into a list of char strings
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
222 _dbus_split_paths_and_append (DBusString *dirs,
230 DBusString file_suffix;
235 _dbus_string_init_const (&file_suffix, suffix);
237 len = _dbus_string_get_length (dirs);
239 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
243 if (!_dbus_string_init (&path))
246 if (!_dbus_string_copy_len (dirs,
252 _dbus_string_free (&path);
256 _dbus_string_chop_white (&path);
258 /* check for an empty path */
259 if (_dbus_string_get_length (&path) == 0)
262 if (!_dbus_concat_dir_and_file (&path,
265 _dbus_string_free (&path);
269 if (!_dbus_string_copy_data(&path, &cpath))
271 _dbus_string_free (&path);
275 if (!_dbus_list_append (dir_list, cpath))
277 _dbus_string_free (&path);
283 _dbus_string_free (&path);
291 if (!_dbus_string_init (&path))
294 if (!_dbus_string_copy_len (dirs,
300 _dbus_string_free (&path);
304 if (!_dbus_concat_dir_and_file (&path,
307 _dbus_string_free (&path);
311 if (!_dbus_string_copy_data(&path, &cpath))
313 _dbus_string_free (&path);
317 if (!_dbus_list_append (dir_list, cpath))
319 _dbus_string_free (&path);
324 _dbus_string_free (&path);
330 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
331 _dbus_list_clear (dir_list);
338 * @addtogroup DBusString
343 * Appends an integer to a DBusString.
345 * @param str the string
346 * @param value the integer value
347 * @returns #FALSE if not enough memory or other failure.
350 _dbus_string_append_int (DBusString *str,
353 /* this calculation is from comp.lang.c faq */
354 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
359 orig_len = _dbus_string_get_length (str);
361 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
364 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
366 snprintf (buf, MAX_LONG_LEN, "%ld", value);
375 _dbus_string_shorten (str, MAX_LONG_LEN - i);
381 * Appends an unsigned integer to a DBusString.
383 * @param str the string
384 * @param value the integer value
385 * @returns #FALSE if not enough memory or other failure.
388 _dbus_string_append_uint (DBusString *str,
391 /* this is wrong, but definitely on the high side. */
392 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
397 orig_len = _dbus_string_get_length (str);
399 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
402 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
404 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
413 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
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.
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
431 _dbus_string_parse_int (const DBusString *str,
440 p = _dbus_string_get_const_data_len (str, start,
441 _dbus_string_get_length (str) - start);
444 _dbus_set_errno_to_zero ();
445 v = strtol (p, &end, 0);
446 if (end == NULL || end == p || errno != 0)
452 *end_return = start + (end - p);
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.
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
470 _dbus_string_parse_uint (const DBusString *str,
472 unsigned long *value_return,
479 p = _dbus_string_get_const_data_len (str, start,
480 _dbus_string_get_length (str) - start);
483 _dbus_set_errno_to_zero ();
484 v = strtoul (p, &end, 0);
485 if (end == NULL || end == p || errno != 0)
491 *end_return = start + (end - p);
496 /** @} */ /* DBusString group */
499 * @addtogroup DBusInternalsUtils
504 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
510 /* fall back to pseudorandom */
511 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
514 _dbus_get_real_time (NULL, &tv_usec);
524 b = (r / (double) RAND_MAX) * 255.0;
533 * Fills n_bytes of the given buffer with random bytes.
535 * @param buffer an allocated buffer
536 * @param n_bytes the number of bytes in buffer to write to
539 _dbus_generate_random_bytes_buffer (char *buffer,
544 if (!_dbus_string_init (&str))
546 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
550 if (!_dbus_generate_random_bytes (&str, n_bytes))
552 _dbus_string_free (&str);
553 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
557 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
559 _dbus_string_free (&str);
563 * Generates the given number of random bytes, where the bytes are
564 * chosen from the alphanumeric ASCII subset.
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
571 _dbus_generate_random_ascii (DBusString *str,
574 static const char letters[] =
575 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
579 if (!_dbus_generate_random_bytes (str, n_bytes))
582 len = _dbus_string_get_length (str);
586 _dbus_string_set_byte (str, i,
587 letters[_dbus_string_get_byte (str, i) %
588 (sizeof (letters) - 1)]);
593 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
600 * Converts a UNIX errno, or Windows errno or WinSock error value into
603 * @todo should cover more errnos, specifically those
606 * @param error_number the errno.
607 * @returns an error name
610 _dbus_error_from_errno (int error_number)
612 switch (error_number)
615 return DBUS_ERROR_FAILED;
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;
626 return DBUS_ERROR_NOT_SUPPORTED;
627 #elif defined(WSAEAFNOSUPPORT)
628 case WSAEAFNOSUPPORT:
629 return DBUS_ERROR_NOT_SUPPORTED;
633 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
637 return DBUS_ERROR_LIMITS_EXCEEDED;
641 return DBUS_ERROR_ACCESS_DENIED;
645 return DBUS_ERROR_ACCESS_DENIED;
649 return DBUS_ERROR_NO_MEMORY;
653 return DBUS_ERROR_NO_MEMORY;
657 return DBUS_ERROR_NO_SERVER;
658 #elif defined(WSAECONNREFUSED)
659 case WSAECONNREFUSED:
660 return DBUS_ERROR_NO_SERVER;
664 return DBUS_ERROR_TIMEOUT;
665 #elif defined(WSAETIMEDOUT)
667 return DBUS_ERROR_TIMEOUT;
671 return DBUS_ERROR_NO_NETWORK;
672 #elif defined(WSAENETUNREACH)
674 return DBUS_ERROR_NO_NETWORK;
678 return DBUS_ERROR_ADDRESS_IN_USE;
679 #elif defined(WSAEADDRINUSE)
681 return DBUS_ERROR_ADDRESS_IN_USE;
685 return DBUS_ERROR_FILE_EXISTS;
689 return DBUS_ERROR_FILE_NOT_FOUND;
693 return DBUS_ERROR_FAILED;
697 * Converts the current system errno value into a #DBusError name.
699 * @returns an error name
702 _dbus_error_from_system_errno (void)
704 return _dbus_error_from_errno (errno);
708 * Assign 0 to the global errno variable
711 _dbus_set_errno_to_zero (void)
721 * See if errno is set
722 * @returns #TRUE if errno is not 0
725 _dbus_get_is_errno_nonzero (void)
731 * See if errno is ENOMEM
732 * @returns #TRUE if errno == ENOMEM
735 _dbus_get_is_errno_enomem (void)
737 return errno == ENOMEM;
741 * See if errno is EINTR
742 * @returns #TRUE if errno == EINTR
745 _dbus_get_is_errno_eintr (void)
747 return errno == EINTR;
751 * See if errno is EPIPE
752 * @returns #TRUE if errno == EPIPE
755 _dbus_get_is_errno_epipe (void)
757 return errno == EPIPE;
761 * Get error message from errno
762 * @returns _dbus_strerror(errno)
765 _dbus_strerror_from_errno (void)
767 return _dbus_strerror (errno);
770 /** @} end of sysdeps */
772 /* tests in dbus-sysdeps-util.c */