#include "dbus-protocol.h"
#include "dbus-string.h"
#include "dbus-list.h"
+#include "dbus-misc.h"
/* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
* wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
#include <errno.h>
#endif
-_DBUS_DEFINE_GLOBAL_LOCK (win_fds);
-_DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
-_DBUS_DEFINE_GLOBAL_LOCK (system_users);
-
#ifdef DBUS_WIN
#include <stdlib.h>
#elif (defined __APPLE__)
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
+#elif HAVE_DECL_ENVIRON && defined(HAVE_UNISTD_H)
+# include <unistd.h>
#else
extern char **environ;
#endif
}
/**
+ * @ingroup DBusMisc
+ *
* Wrapper for setenv(). If the value is #NULL, unsets
* the environment variable.
*
* we can not rely on internal implementation details of
* the underlying libc library.
*
+ * This function is not thread-safe, because altering the environment
+ * in Unix is not thread-safe in general.
+ *
* @param varname name of environment variable
- * @param value value of environment variable
- * @returns #TRUE on success.
+ * @param value value of environment variable, or #NULL to unset
+ * @returns #TRUE on success, #FALSE if not enough memory.
*/
dbus_bool_t
-_dbus_setenv (const char *varname,
- const char *value)
+dbus_setenv (const char *varname,
+ const char *value)
{
_dbus_assert (varname != NULL);
const char*
_dbus_getenv (const char *varname)
{
+ /* Don't respect any environment variables if the current process is
+ * setuid. This is the equivalent of glibc's __secure_getenv().
+ */
+ if (_dbus_check_setuid ())
+ return NULL;
return getenv (varname);
}
}
/**
- * Gets a #NULL-terminated list of key=value pairs from the
- * environment. Use dbus_free_string_array to free it.
- *
- * @returns the environment or #NULL on OOM
- */
-char **
-_dbus_get_environment (void)
-{
- int i, length;
- char **environment;
-
- _dbus_assert (environ != NULL);
-
- for (length = 0; environ[length] != NULL; length++);
-
- /* Add one for NULL */
- length++;
-
- environment = dbus_new0 (char *, length);
-
- if (environment == NULL)
- return NULL;
-
- for (i = 0; environ[i] != NULL; i++)
- {
- environment[i] = _dbus_strdup (environ[i]);
-
- if (environment[i] == NULL)
- break;
- }
-
- if (environ[i] != NULL)
- {
- dbus_free_string_array (environment);
- environment = NULL;
- }
-
- return environment;
-}
-
-/**
* Split paths into a list of char strings
*
* @param dirs string with pathes
return TRUE;
}
-#ifdef DBUS_BUILD_TESTS
-/**
- * Appends a double to a DBusString.
- *
- * @param str the string
- * @param value the floating point value
- * @returns #FALSE if not enough memory or other failure.
- */
-dbus_bool_t
-_dbus_string_append_double (DBusString *str,
- double value)
-{
-#define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
- int orig_len;
- char *buf;
- int i;
-
- orig_len = _dbus_string_get_length (str);
-
- if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
- return FALSE;
-
- buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
-
- snprintf (buf, MAX_LONG_LEN, "%g", value);
-
- i = 0;
- while (*buf)
- {
- ++buf;
- ++i;
- }
-
- _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
-
- return TRUE;
-}
-#endif /* DBUS_BUILD_TESTS */
-
/**
* Parses an integer contained in a DBusString. Either return parameter
* may be #NULL if you aren't interested in it. The integer is parsed
return TRUE;
}
-#ifdef DBUS_BUILD_TESTS
-static dbus_bool_t
-ascii_isspace (char c)
-{
- return (c == ' ' ||
- c == '\f' ||
- c == '\n' ||
- c == '\r' ||
- c == '\t' ||
- c == '\v');
-}
-#endif /* DBUS_BUILD_TESTS */
-
-#ifdef DBUS_BUILD_TESTS
-static dbus_bool_t
-ascii_isdigit (char c)
-{
- return c >= '0' && c <= '9';
-}
-#endif /* DBUS_BUILD_TESTS */
-
-#ifdef DBUS_BUILD_TESTS
-static dbus_bool_t
-ascii_isxdigit (char c)
-{
- return (ascii_isdigit (c) ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F'));
-}
-#endif /* DBUS_BUILD_TESTS */
-
-#ifdef DBUS_BUILD_TESTS
-/* Calls strtod in a locale-independent fashion, by looking at
- * the locale data and patching the decimal comma to a point.
- *
- * Relicensed from glib.
- */
-static double
-ascii_strtod (const char *nptr,
- char **endptr)
-{
- /* FIXME: The Win32 C library's strtod() doesn't handle hex.
- * Presumably many Unixes don't either.
- */
-
- char *fail_pos;
- double val;
- struct lconv *locale_data;
- const char *decimal_point;
- int decimal_point_len;
- const char *p, *decimal_point_pos;
- const char *end = NULL; /* Silence gcc */
-
- fail_pos = NULL;
-
-#if HAVE_LOCALE_H
- locale_data = localeconv ();
- decimal_point = locale_data->decimal_point;
-#else
- decimal_point = ".";
-#endif
-
- decimal_point_len = strlen (decimal_point);
- _dbus_assert (decimal_point_len != 0);
-
- decimal_point_pos = NULL;
- if (decimal_point[0] != '.' ||
- decimal_point[1] != 0)
- {
- p = nptr;
- /* Skip leading space */
- while (ascii_isspace (*p))
- p++;
-
- /* Skip leading optional sign */
- if (*p == '+' || *p == '-')
- p++;
-
- if (p[0] == '0' &&
- (p[1] == 'x' || p[1] == 'X'))
- {
- p += 2;
- /* HEX - find the (optional) decimal point */
-
- while (ascii_isxdigit (*p))
- p++;
-
- if (*p == '.')
- {
- decimal_point_pos = p++;
-
- while (ascii_isxdigit (*p))
- p++;
-
- if (*p == 'p' || *p == 'P')
- p++;
- if (*p == '+' || *p == '-')
- p++;
- while (ascii_isdigit (*p))
- p++;
- end = p;
- }
- }
- else
- {
- while (ascii_isdigit (*p))
- p++;
-
- if (*p == '.')
- {
- decimal_point_pos = p++;
-
- while (ascii_isdigit (*p))
- p++;
-
- if (*p == 'e' || *p == 'E')
- p++;
- if (*p == '+' || *p == '-')
- p++;
- while (ascii_isdigit (*p))
- p++;
- end = p;
- }
- }
- /* For the other cases, we need not convert the decimal point */
- }
-
- /* Set errno to zero, so that we can distinguish zero results
- and underflows */
- _dbus_set_errno_to_zero ();
-
- if (decimal_point_pos)
- {
- char *copy, *c;
-
- /* We need to convert the '.' to the locale specific decimal point */
- copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
-
- c = copy;
- memcpy (c, nptr, decimal_point_pos - nptr);
- c += decimal_point_pos - nptr;
- memcpy (c, decimal_point, decimal_point_len);
- c += decimal_point_len;
- memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
- c += end - (decimal_point_pos + 1);
- *c = 0;
-
- val = strtod (copy, &fail_pos);
-
- if (fail_pos)
- {
- if (fail_pos > decimal_point_pos)
- fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
- else
- fail_pos = (char *)nptr + (fail_pos - copy);
- }
-
- dbus_free (copy);
-
- }
- else
- val = strtod (nptr, &fail_pos);
-
- if (endptr)
- *endptr = fail_pos;
-
- return val;
-}
-#endif /* DBUS_BUILD_TESTS */
-
-#ifdef DBUS_BUILD_TESTS
-/**
- * Parses a floating point number contained in a DBusString. Either
- * return parameter may be #NULL if you aren't interested in it. The
- * integer is parsed and stored in value_return. Return parameters are
- * not initialized if the function returns #FALSE.
- *
- * @param str the string
- * @param start the byte index of the start of the float
- * @param value_return return location of the float value or #NULL
- * @param end_return return location of the end of the float, or #NULL
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_string_parse_double (const DBusString *str,
- int start,
- double *value_return,
- int *end_return)
-{
- double v;
- const char *p;
- char *end;
-
- p = _dbus_string_get_const_data_len (str, start,
- _dbus_string_get_length (str) - start);
-
- /* parsing hex works on linux but isn't portable, so intercept it
- * here to get uniform behavior.
- */
- if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
- return FALSE;
-
- end = NULL;
- _dbus_set_errno_to_zero ();
- v = ascii_strtod (p, &end);
- if (end == NULL || end == p || errno != 0)
- return FALSE;
-
- if (value_return)
- *value_return = v;
- if (end_return)
- *end_return = start + (end - p);
-
- return TRUE;
-}
-#endif /* DBUS_BUILD_TESTS */
-
/** @} */ /* DBusString group */
/**
* @{
*/
-void
-_dbus_generate_pseudorandom_bytes_buffer (char *buffer,
- int n_bytes)
-{
- long tv_usec;
- int i;
-
- /* fall back to pseudorandom */
- _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
- n_bytes);
-
- _dbus_get_current_time (NULL, &tv_usec);
- srand (tv_usec);
-
- i = 0;
- while (i < n_bytes)
- {
- double r;
- unsigned int b;
-
- r = rand ();
- b = (r / (double) RAND_MAX) * 255.0;
-
- buffer[i] = b;
-
- ++i;
- }
-}
-
/**
* Fills n_bytes of the given buffer with random bytes.
*
* @param buffer an allocated buffer
* @param n_bytes the number of bytes in buffer to write to
+ * @param error location to store reason for failure
+ * @returns #TRUE on success
*/
-void
-_dbus_generate_random_bytes_buffer (char *buffer,
- int n_bytes)
+dbus_bool_t
+_dbus_generate_random_bytes_buffer (char *buffer,
+ int n_bytes,
+ DBusError *error)
{
DBusString str;
if (!_dbus_string_init (&str))
{
- _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
- return;
+ _DBUS_SET_OOM (error);
+ return FALSE;
}
- if (!_dbus_generate_random_bytes (&str, n_bytes))
+ if (!_dbus_generate_random_bytes (&str, n_bytes, error))
{
_dbus_string_free (&str);
- _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
- return;
+ return FALSE;
}
_dbus_string_copy_to_buffer (&str, buffer, n_bytes);
_dbus_string_free (&str);
+ return TRUE;
}
/**
*
* @param str the string
* @param n_bytes the number of random ASCII bytes to append to string
+ * @param error location to store reason for failure
* @returns #TRUE on success, #FALSE if no memory or other failure
*/
dbus_bool_t
_dbus_generate_random_ascii (DBusString *str,
- int n_bytes)
+ int n_bytes,
+ DBusError *error)
{
static const char letters[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
int i;
int len;
- if (!_dbus_generate_random_bytes (str, n_bytes))
+ if (!_dbus_generate_random_bytes (str, n_bytes, error))
return FALSE;
len = _dbus_string_get_length (str);
#ifdef EPROTONOSUPPORT
case EPROTONOSUPPORT:
return DBUS_ERROR_NOT_SUPPORTED;
-#endif
-#ifdef WSAEPROTONOSUPPORT
+#elif defined(WSAEPROTONOSUPPORT)
case WSAEPROTONOSUPPORT:
return DBUS_ERROR_NOT_SUPPORTED;
#endif
#ifdef EAFNOSUPPORT
case EAFNOSUPPORT:
return DBUS_ERROR_NOT_SUPPORTED;
-#endif
-#ifdef WSAEAFNOSUPPORT
+#elif defined(WSAEAFNOSUPPORT)
case WSAEAFNOSUPPORT:
return DBUS_ERROR_NOT_SUPPORTED;
#endif
#ifdef ECONNREFUSED
case ECONNREFUSED:
return DBUS_ERROR_NO_SERVER;
-#endif
-#ifdef WSAECONNREFUSED
+#elif defined(WSAECONNREFUSED)
case WSAECONNREFUSED:
return DBUS_ERROR_NO_SERVER;
#endif
#ifdef ETIMEDOUT
case ETIMEDOUT:
return DBUS_ERROR_TIMEOUT;
-#endif
-#ifdef WSAETIMEDOUT
+#elif defined(WSAETIMEDOUT)
case WSAETIMEDOUT:
return DBUS_ERROR_TIMEOUT;
#endif
#ifdef ENETUNREACH
case ENETUNREACH:
return DBUS_ERROR_NO_NETWORK;
-#endif
-#ifdef WSAENETUNREACH
+#elif defined(WSAENETUNREACH)
case WSAENETUNREACH:
return DBUS_ERROR_NO_NETWORK;
#endif
#ifdef EADDRINUSE
case EADDRINUSE:
return DBUS_ERROR_ADDRESS_IN_USE;
-#endif
-#ifdef WSAEADDRINUSE
+#elif defined(WSAEADDRINUSE)
case WSAEADDRINUSE:
return DBUS_ERROR_ADDRESS_IN_USE;
#endif
case ENOENT:
return DBUS_ERROR_FILE_NOT_FOUND;
#endif
+ default:
+ return DBUS_ERROR_FAILED;
}
-
- return DBUS_ERROR_FAILED;
}
/**
void
_dbus_set_errno_to_zero (void)
{
+#ifdef DBUS_WINCE
+ SetLastError (0);
+#else
errno = 0;
+#endif
}
/**
- * See if errno is set
- * @returns #TRUE if errno is not 0
+ * See if errno is ENOMEM
+ * @returns #TRUE if e == ENOMEM
*/
dbus_bool_t
-_dbus_get_is_errno_nonzero (void)
+_dbus_get_is_errno_enomem (int e)
{
- return errno != 0;
+ return e == ENOMEM;
}
/**
- * See if errno is ENOMEM
- * @returns #TRUE if errno == ENOMEM
+ * See if errno is EINTR
+ * @returns #TRUE if e == EINTR
*/
dbus_bool_t
-_dbus_get_is_errno_enomem (void)
+_dbus_get_is_errno_eintr (int e)
{
- return errno == ENOMEM;
+ return e == EINTR;
}
/**
- * See if errno is EINTR
- * @returns #TRUE if errno == EINTR
+ * See if errno is EPIPE
+ * @returns #TRUE if errno == EPIPE
*/
dbus_bool_t
-_dbus_get_is_errno_eintr (void)
+_dbus_get_is_errno_epipe (int e)
{
- return errno == EINTR;
+ return e == EPIPE;
}
/**
- * See if errno is EPIPE
- * @returns #TRUE if errno == EPIPE
+ * See if errno is ETOOMANYREFS
+ * @returns #TRUE if errno == ETOOMANYREFS
*/
dbus_bool_t
-_dbus_get_is_errno_epipe (void)
+_dbus_get_is_errno_etoomanyrefs (int e)
{
- return errno == EPIPE;
+#ifdef ETOOMANYREFS
+ return e == ETOOMANYREFS;
+#else
+ return FALSE;
+#endif
}
/**
return _dbus_strerror (errno);
}
+/**
+ * Log a message to the system log file (e.g. syslog on Unix) and/or stderr.
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ */
+void
+_dbus_log (DBusSystemLogSeverity severity,
+ const char *msg,
+ ...)
+{
+ va_list args;
+
+ va_start (args, msg);
+
+ _dbus_logv (severity, msg, args);
+
+ va_end (args);
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */