#include "gmessages.h"
#include "gstrfuncs.h"
+/* Environ array functions {{{1 */
+static gint
+g_environ_find (gchar **envp,
+ const gchar *variable)
+{
+ gint len, i;
+
+ len = strlen (variable);
+
+ for (i = 0; envp[i]; i++)
+ {
+ if (strncmp (envp[i], variable, len) == 0 &&
+ envp[i][len] == '=')
+ return i;
+ }
+
+ return -1;
+}
/**
- * g_getenv:
+ * g_environ_getenv:
+ * @envp: (array zero-terminated=1) (transfer none): an environment
+ * list (eg, as returned from g_get_environ())
* @variable: the environment variable to get, in the GLib file name
* encoding
*
- * Returns the value of an environment variable.
+ * Returns the value of the environment variable @variable in the
+ * provided list @envp.
*
- * The name and value are in the GLib file name encoding. On UNIX,
- * this means the actual bytes which might or might not be in some
- * consistent character set and encoding. On Windows, it is in UTF-8.
- * On Windows, in case the environment variable's value contains
- * references to other environment variables, they are expanded.
+ * The name and value are in the GLib file name encoding.
+ * On UNIX, this means the actual bytes which might or might not
+ * be in some consistent character set and encoding. On Windows,
+ * it is in UTF-8. On Windows, in case the environment variable's
+ * value contains references to other environment variables, they
+ * are expanded.
*
* Return value: the value of the environment variable, or %NULL if
- * the environment variable is not found. The returned string
- * may be overwritten by the next call to g_getenv(), g_setenv()
- * or g_unsetenv().
+ * the environment variable is not set in @envp. The returned
+ * string is owned by @envp, and will be freed if @variable is
+ * set or unset again.
+ *
+ * Since: 2.32
*/
const gchar *
-g_getenv (const gchar *variable)
+g_environ_getenv (gchar **envp,
+ const gchar *variable)
{
-#ifndef G_OS_WIN32
+ gint index;
+ g_return_val_if_fail (envp != NULL, NULL);
g_return_val_if_fail (variable != NULL, NULL);
- return getenv (variable);
-
-#else /* G_OS_WIN32 */
+ index = g_environ_find (envp, variable);
+ if (index != -1)
+ return envp[index] + strlen (variable) + 1;
+ else
+ return NULL;
+}
- GQuark quark;
- gchar *value;
- wchar_t dummy[2], *wname, *wvalue;
- int len;
+/**
+ * g_environ_setenv:
+ * @envp: (array zero-terminated=1) (transfer full): an environment
+ * list (eg, as returned from g_get_environ())
+ * @variable: the environment variable to set, must not contain '='
+ * @value: the value for to set the variable to
+ * @overwrite: whether to change the variable if it already exists
+ *
+ * Sets the environment variable @variable in the provided list
+ * @envp to @value.
+ *
+ * Both the variable's name and value should be in the GLib
+ * file name encoding. On UNIX, this means that they can be
+ * arbitrary byte strings. On Windows, they should be in UTF-8.
+ *
+ * Return value: (array zero-terminated=1) (transfer full): the
+ * updated environment
+ *
+ * Since: 2.32
+ */
+gchar **
+g_environ_setenv (gchar **envp,
+ const gchar *variable,
+ const gchar *value,
+ gboolean overwrite)
+{
+ gint index;
+ g_return_val_if_fail (envp != NULL, NULL);
g_return_val_if_fail (variable != NULL, NULL);
- g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
-
- /* On Windows NT, it is relatively typical that environment
- * variables contain references to other environment variables. If
- * so, use ExpandEnvironmentStrings(). (In an ideal world, such
- * environment variables would be stored in the Registry as
- * REG_EXPAND_SZ type values, and would then get automatically
- * expanded before a program sees them. But there is broken software
- * that stores environment variables as REG_SZ values even if they
- * contain references to other environment variables.)
- */
-
- wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
-
- len = GetEnvironmentVariableW (wname, dummy, 2);
+ g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
- if (len == 0)
+ index = g_environ_find (envp, variable);
+ if (index != -1)
{
- g_free (wname);
- return NULL;
+ if (overwrite)
+ {
+ g_free (envp[index]);
+ envp[index] = g_strdup_printf ("%s=%s", variable, value);
+ }
}
- else if (len == 1)
- len = 2;
-
- wvalue = g_new (wchar_t, len);
-
- if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
+ else
{
- g_free (wname);
- g_free (wvalue);
- return NULL;
+ gint length;
+
+ length = g_strv_length (envp);
+ envp = g_renew (gchar *, envp, length + 2);
+ envp[length] = g_strdup_printf ("%s=%s", variable, value);
+ envp[length + 1] = NULL;
}
- if (wcschr (wvalue, L'%') != NULL)
- {
- wchar_t *tem = wvalue;
+ return envp;
+}
- len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
+/**
+ * g_environ_unsetenv:
+ * @envp: (array zero-terminated=1) (transfer full): an environment
+ * list (eg, as returned from g_get_environ())
+ * @variable: the environment variable to remove, must not contain '='
+ *
+ * Removes the environment variable @variable from the provided
+ * environment @envp.
+ *
+ * Return value: (array zero-terminated=1) (transfer full): the
+ * updated environment
+ *
+ * Since: 2.32
+ */
+gchar **
+g_environ_unsetenv (gchar **envp,
+ const gchar *variable)
+{
+ gint len;
+ gchar **e, **f;
- if (len > 0)
- {
- wvalue = g_new (wchar_t, len);
+ g_return_val_if_fail (envp != NULL, NULL);
+ g_return_val_if_fail (variable != NULL, NULL);
+ g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
- if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
- {
- g_free (wvalue);
- wvalue = tem;
- }
- else
- g_free (tem);
+ len = strlen (variable);
+
+ /* Note that we remove *all* environment entries for
+ * the variable name, not just the first.
+ */
+ e = f = envp;
+ while (*e != NULL)
+ {
+ if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=')
+ {
+ *f = *e;
+ f++;
}
+ e++;
}
+ *f = NULL;
- value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
-
- g_free (wname);
- g_free (wvalue);
+ return envp;
+}
- quark = g_quark_from_string (value);
- g_free (value);
+/* UNIX implemention {{{1 */
+#ifndef G_OS_WIN32
- return g_quark_to_string (quark);
+/**
+ * g_getenv:
+ * @variable: the environment variable to get, in the GLib file name
+ * encoding
+ *
+ * Returns the value of an environment variable.
+ *
+ * The name and value are in the GLib file name encoding. On UNIX,
+ * this means the actual bytes which might or might not be in some
+ * consistent character set and encoding. On Windows, it is in UTF-8.
+ * On Windows, in case the environment variable's value contains
+ * references to other environment variables, they are expanded.
+ *
+ * Return value: the value of the environment variable, or %NULL if
+ * the environment variable is not found. The returned string
+ * may be overwritten by the next call to g_getenv(), g_setenv()
+ * or g_unsetenv().
+ */
+const gchar *
+g_getenv (const gchar *variable)
+{
+ g_return_val_if_fail (variable != NULL, NULL);
-#endif /* G_OS_WIN32 */
+ return getenv (variable);
}
/**
const gchar *value,
gboolean overwrite)
{
-#ifndef G_OS_WIN32
-
gint result;
#ifndef HAVE_SETENV
gchar *string;
result = putenv (string);
#endif
return result == 0;
-
-#else /* G_OS_WIN32 */
-
- gboolean retval;
- wchar_t *wname, *wvalue, *wassignment;
- gchar *tem;
-
- g_return_val_if_fail (variable != NULL, FALSE);
- g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
- g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
- g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
-
- if (!overwrite && g_getenv (variable) != NULL)
- return TRUE;
-
- /* We want to (if possible) set both the environment variable copy
- * kept by the C runtime and the one kept by the system.
- *
- * We can't use only the C runtime's putenv or _wputenv() as that
- * won't work for arbitrary Unicode strings in a "non-Unicode" app
- * (with main() and not wmain()). In a "main()" app the C runtime
- * initializes the C runtime's environment table by converting the
- * real (wide char) environment variables to system codepage, thus
- * breaking those that aren't representable in the system codepage.
- *
- * As the C runtime's putenv() will also set the system copy, we do
- * the putenv() first, then call SetEnvironmentValueW ourselves.
- */
-
- wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
- wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
- tem = g_strconcat (variable, "=", value, NULL);
- wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
-
- g_free (tem);
- _wputenv (wassignment);
- g_free (wassignment);
-
- retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
-
- g_free (wname);
- g_free (wvalue);
-
- return retval;
-
-#endif /* G_OS_WIN32 */
}
#ifdef HAVE__NSGETENVIRON
#define environ (*_NSGetEnviron())
-#elif !defined(G_OS_WIN32)
-
+#else
/* According to the Single Unix Specification, environ is not
* in any system header, although unistd.h often declares it.
*/
void
g_unsetenv (const gchar *variable)
{
-#ifndef G_OS_WIN32
+#ifdef HAVE_UNSETENV
+ g_return_if_fail (variable != NULL);
+ g_return_if_fail (strchr (variable, '=') == NULL);
+
+ unsetenv (variable);
+#else /* !HAVE_UNSETENV */
+ g_return_if_fail (variable != NULL);
+ g_return_if_fail (strchr (variable, '=') == NULL);
+
+ /* Mess directly with the environ array.
+ * This seems to be the only portable way to do this.
+ */
+ g_environ_unsetenv (environ, variable);
+#endif /* !HAVE_UNSETENV */
+}
+
+/**
+ * g_listenv:
+ *
+ * Gets the names of all variables set in the environment.
+ *
+ * Programs that want to be portable to Windows should typically use
+ * this function and g_getenv() instead of using the environ array
+ * from the C library directly. On Windows, the strings in the environ
+ * array are in system codepage encoding, while in most of the typical
+ * use cases for environment variables in GLib-using programs you want
+ * the UTF-8 encoding that this function and g_getenv() provide.
+ *
+ * Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated
+ * list of strings which must be freed with g_strfreev().
+ *
+ * Since: 2.8
+ */
+gchar **
+g_listenv (void)
+{
+ gchar **result, *eq;
+ gint len, i, j;
+
+ len = g_strv_length (environ);
+ result = g_new0 (gchar *, len + 1);
+
+ j = 0;
+ for (i = 0; i < len; i++)
+ {
+ eq = strchr (environ[i], '=');
+ if (eq)
+ result[j++] = g_strndup (environ[i], eq - environ[i]);
+ }
+
+ result[j] = NULL;
+
+ return result;
+}
+
+/**
+ * g_get_environ:
+ *
+ * Gets the list of environment variables for the current process.
+ *
+ * The list is %NULL terminated and each item in the list is of the
+ * form 'NAME=VALUE'.
+ *
+ * This is equivalent to direct access to the 'environ' global variable,
+ * except portable.
+ *
+ * The return value is freshly allocated and it should be freed with
+ * g_strfreev() when it is no longer needed.
+ *
+ * Returns: (array zero-terminated=1) (transfer full): the list of
+ * environment variables
+ *
+ * Since: 2.28
+ */
+gchar **
+g_get_environ (void)
+{
+ return g_strdupv (environ);
+}
+
+/* Win32 implementation {{{1 */
+#else /* G_OS_WIN32 */
+
+const gchar *
+g_getenv (const gchar *variable)
+{
+ GQuark quark;
+ gchar *value;
+ wchar_t dummy[2], *wname, *wvalue;
+ int len;
+
+ g_return_val_if_fail (variable != NULL, NULL);
+ g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
+
+ /* On Windows NT, it is relatively typical that environment
+ * variables contain references to other environment variables. If
+ * so, use ExpandEnvironmentStrings(). (In an ideal world, such
+ * environment variables would be stored in the Registry as
+ * REG_EXPAND_SZ type values, and would then get automatically
+ * expanded before a program sees them. But there is broken software
+ * that stores environment variables as REG_SZ values even if they
+ * contain references to other environment variables.)
+ */
+
+ wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
+
+ len = GetEnvironmentVariableW (wname, dummy, 2);
+
+ if (len == 0)
+ {
+ g_free (wname);
+ return NULL;
+ }
+ else if (len == 1)
+ len = 2;
+
+ wvalue = g_new (wchar_t, len);
+
+ if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
+ {
+ g_free (wname);
+ g_free (wvalue);
+ return NULL;
+ }
+
+ if (wcschr (wvalue, L'%') != NULL)
+ {
+ wchar_t *tem = wvalue;
+
+ len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
+
+ if (len > 0)
+ {
+ wvalue = g_new (wchar_t, len);
+
+ if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
+ {
+ g_free (wvalue);
+ wvalue = tem;
+ }
+ else
+ g_free (tem);
+ }
+ }
+
+ value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
+
+ g_free (wname);
+ g_free (wvalue);
+
+ quark = g_quark_from_string (value);
+ g_free (value);
+
+ return g_quark_to_string (quark);
+}
+
+gboolean
+g_setenv (const gchar *variable,
+ const gchar *value,
+ gboolean overwrite)
+{
+ gboolean retval;
+ wchar_t *wname, *wvalue, *wassignment;
+ gchar *tem;
+
+ g_return_val_if_fail (variable != NULL, FALSE);
+ g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
+ g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
+ g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+
+ if (!overwrite && g_getenv (variable) != NULL)
+ return TRUE;
+
+ /* We want to (if possible) set both the environment variable copy
+ * kept by the C runtime and the one kept by the system.
+ *
+ * We can't use only the C runtime's putenv or _wputenv() as that
+ * won't work for arbitrary Unicode strings in a "non-Unicode" app
+ * (with main() and not wmain()). In a "main()" app the C runtime
+ * initializes the C runtime's environment table by converting the
+ * real (wide char) environment variables to system codepage, thus
+ * breaking those that aren't representable in the system codepage.
+ *
+ * As the C runtime's putenv() will also set the system copy, we do
+ * the putenv() first, then call SetEnvironmentValueW ourselves.
+ */
-#ifdef HAVE_UNSETENV
- g_return_if_fail (variable != NULL);
- g_return_if_fail (strchr (variable, '=') == NULL);
+ wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
+ wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
+ tem = g_strconcat (variable, "=", value, NULL);
+ wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
- unsetenv (variable);
-#else /* !HAVE_UNSETENV */
- g_return_if_fail (variable != NULL);
- g_return_if_fail (strchr (variable, '=') == NULL);
+ g_free (tem);
+ _wputenv (wassignment);
+ g_free (wassignment);
- /* Mess directly with the environ array.
- * This seems to be the only portable way to do this.
- */
- g_environ_unsetenv (environ, variable);
-#endif /* !HAVE_UNSETENV */
+ retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
-#else /* G_OS_WIN32 */
+ g_free (wname);
+ g_free (wvalue);
+
+ return retval;
+}
+void
+g_unsetenv (const gchar *variable)
+{
wchar_t *wname, *wassignment;
gchar *tem;
SetEnvironmentVariableW (wname, NULL);
g_free (wname);
-
-#endif /* G_OS_WIN32 */
}
-/**
- * g_listenv:
- *
- * Gets the names of all variables set in the environment.
- *
- * Programs that want to be portable to Windows should typically use
- * this function and g_getenv() instead of using the environ array
- * from the C library directly. On Windows, the strings in the environ
- * array are in system codepage encoding, while in most of the typical
- * use cases for environment variables in GLib-using programs you want
- * the UTF-8 encoding that this function and g_getenv() provide.
- *
- * Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated
- * list of strings which must be freed with g_strfreev().
- *
- * Since: 2.8
- */
gchar **
g_listenv (void)
{
-#ifndef G_OS_WIN32
- gchar **result, *eq;
- gint len, i, j;
-
- len = g_strv_length (environ);
- result = g_new0 (gchar *, len + 1);
-
- j = 0;
- for (i = 0; i < len; i++)
- {
- eq = strchr (environ[i], '=');
- if (eq)
- result[j++] = g_strndup (environ[i], eq - environ[i]);
- }
-
- result[j] = NULL;
-
- return result;
-#else
gchar **result, *eq;
gint len = 0, j;
wchar_t *p, *q;
FreeEnvironmentStringsW (p);
return result;
-#endif
}
-/**
- * g_get_environ:
- *
- * Gets the list of environment variables for the current process.
- *
- * The list is %NULL terminated and each item in the list is of the
- * form 'NAME=VALUE'.
- *
- * This is equivalent to direct access to the 'environ' global variable,
- * except portable.
- *
- * The return value is freshly allocated and it should be freed with
- * g_strfreev() when it is no longer needed.
- *
- * Returns: (array zero-terminated=1) (transfer full): the list of
- * environment variables
- *
- * Since: 2.28
- */
gchar **
g_get_environ (void)
{
-#ifndef G_OS_WIN32
- return g_strdupv (environ);
-#else
gunichar2 *strings;
gchar **result;
gint i, n;
result[i] = NULL;
return result;
-#endif
}
-static gint
-g_environ_find (gchar **envp,
- const gchar *variable)
-{
- gint len, i;
-
- len = strlen (variable);
+#ifndef _WIN64
- for (i = 0; envp[i]; i++)
- {
- if (strncmp (envp[i], variable, len) == 0 &&
- envp[i][len] == '=')
- return i;
- }
+/* Binary compatibility versions. Not for newly compiled code. */
- return -1;
-}
+#undef g_getenv
-/**
- * g_environ_getenv:
- * @envp: (array zero-terminated=1) (transfer none): an environment
- * list (eg, as returned from g_get_environ())
- * @variable: the environment variable to get, in the GLib file name
- * encoding
- *
- * Returns the value of the environment variable @variable in the
- * provided list @envp.
- *
- * The name and value are in the GLib file name encoding.
- * On UNIX, this means the actual bytes which might or might not
- * be in some consistent character set and encoding. On Windows,
- * it is in UTF-8. On Windows, in case the environment variable's
- * value contains references to other environment variables, they
- * are expanded.
- *
- * Return value: the value of the environment variable, or %NULL if
- * the environment variable is not set in @envp. The returned
- * string is owned by @envp, and will be freed if @variable is
- * set or unset again.
- *
- * Since: 2.32
- */
const gchar *
-g_environ_getenv (gchar **envp,
- const gchar *variable)
+g_getenv (const gchar *variable)
{
- gint index;
-
- g_return_val_if_fail (envp != NULL, NULL);
- g_return_val_if_fail (variable != NULL, NULL);
+ gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
+ const gchar *utf8_value = g_getenv_utf8 (utf8_variable);
+ gchar *value;
+ GQuark quark;
- index = g_environ_find (envp, variable);
- if (index != -1)
- return envp[index] + strlen (variable) + 1;
- else
+ g_free (utf8_variable);
+ if (!utf8_value)
return NULL;
-}
+ value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL);
+ quark = g_quark_from_string (value);
+ g_free (value);
-/**
- * g_environ_setenv:
- * @envp: (array zero-terminated=1) (transfer full): an environment
- * list (eg, as returned from g_get_environ())
- * @variable: the environment variable to set, must not contain '='
- * @value: the value for to set the variable to
- * @overwrite: whether to change the variable if it already exists
- *
- * Sets the environment variable @variable in the provided list
- * @envp to @value.
- *
- * Both the variable's name and value should be in the GLib
- * file name encoding. On UNIX, this means that they can be
- * arbitrary byte strings. On Windows, they should be in UTF-8.
- *
- * Return value: (array zero-terminated=1) (transfer full): the
- * updated environment
- *
- * Since: 2.32
- */
-gchar **
-g_environ_setenv (gchar **envp,
- const gchar *variable,
- const gchar *value,
- gboolean overwrite)
-{
- gint index;
+ return g_quark_to_string (quark);
+}
- g_return_val_if_fail (envp != NULL, NULL);
- g_return_val_if_fail (variable != NULL, NULL);
- g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
+#undef g_setenv
- index = g_environ_find (envp, variable);
- if (index != -1)
- {
- if (overwrite)
- {
- g_free (envp[index]);
- envp[index] = g_strdup_printf ("%s=%s", variable, value);
- }
- }
- else
- {
- gint length;
+gboolean
+g_setenv (const gchar *variable,
+ const gchar *value,
+ gboolean overwrite)
+{
+ gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
+ gchar *utf8_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
+ gboolean retval = g_setenv_utf8 (utf8_variable, utf8_value, overwrite);
- length = g_strv_length (envp);
- envp = g_renew (gchar *, envp, length + 2);
- envp[length] = g_strdup_printf ("%s=%s", variable, value);
- envp[length + 1] = NULL;
- }
+ g_free (utf8_variable);
+ g_free (utf8_value);
- return envp;
+ return retval;
}
-/**
- * g_environ_unsetenv:
- * @envp: (array zero-terminated=1) (transfer full): an environment
- * list (eg, as returned from g_get_environ())
- * @variable: the environment variable to remove, must not contain '='
- *
- * Removes the environment variable @variable from the provided
- * environment @envp.
- *
- * Return value: (array zero-terminated=1) (transfer full): the
- * updated environment
- *
- * Since: 2.32
- */
-gchar **
-g_environ_unsetenv (gchar **envp,
- const gchar *variable)
+#undef g_unsetenv
+
+void
+g_unsetenv (const gchar *variable)
{
- gint len;
- gchar **e, **f;
+ gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
- g_return_val_if_fail (envp != NULL, NULL);
- g_return_val_if_fail (variable != NULL, NULL);
- g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
+ g_unsetenv_utf8 (utf8_variable);
- len = strlen (variable);
+ g_free (utf8_variable);
+}
- /* Note that we remove *all* environment entries for
- * the variable name, not just the first.
- */
- e = f = envp;
- while (*e != NULL)
- {
- if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=')
- {
- *f = *e;
- f++;
- }
- e++;
- }
- *f = NULL;
+#endif /* _WIN64 */
- return envp;
-}
+#endif /* G_OS_WIN32 */
+
+/* Epilogue {{{1 */
+/* vim: set foldmethod=marker: */