X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgenviron.c;h=0a83ac941862fa0253d36340a794b1539fdbfeed;hb=49a5d0f6f2aed99cd78f25655f137f4448e47d92;hp=7e8a8c53f903d99cfde7c31364ade6c6d1b92dac;hpb=1b018a8bb2c4c508fe8e3996a31210d655b70d30;p=platform%2Fupstream%2Fglib.git diff --git a/glib/genviron.c b/glib/genviron.c index 7e8a8c5..0a83ac9 100644 --- a/glib/genviron.c +++ b/glib/genviron.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . */ /* @@ -30,17 +28,193 @@ #include #include -#ifdef HAVE_UNISTD_H -#include -#endif #ifdef HAVE_CRT_EXTERNS_H #include /* for _NSGetEnviron */ #endif +#ifdef G_OS_WIN32 +#include +#endif +#include "glib-private.h" #include "gmem.h" #include "gmessages.h" #include "gstrfuncs.h" +#include "gunicode.h" +#include "gconvert.h" +#include "gquark.h" + +/* Environ array functions {{{1 */ +static gint +g_environ_find (gchar **envp, + const gchar *variable) +{ + gint len, i; + + if (envp == NULL) + return -1; + + len = strlen (variable); + + for (i = 0; envp[i]; i++) + { + if (strncmp (envp[i], variable, len) == 0 && + envp[i][len] == '=') + return i; + } + + return -1; +} + +/** + * g_environ_getenv: + * @envp: (allow-none) (array zero-terminated=1) (transfer none): an environment + * list (eg, as returned from g_get_environ()), or %NULL + * for an empty environment list + * @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. + * + * Returns: 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) +{ + gint index; + + g_return_val_if_fail (variable != NULL, NULL); + + index = g_environ_find (envp, variable); + if (index != -1) + return envp[index] + strlen (variable) + 1; + else + return NULL; +} + +/** + * g_environ_setenv: + * @envp: (allow-none) (array zero-terminated=1) (transfer full): an + * environment list that can be freed using g_strfreev() (e.g., as + * returned from g_get_environ()), or %NULL for an empty + * environment list + * @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. + * + * Returns: (array zero-terminated=1) (transfer full): the + * updated environment list. Free it using g_strfreev(). + * + * Since: 2.32 + */ +gchar ** +g_environ_setenv (gchar **envp, + const gchar *variable, + const gchar *value, + gboolean overwrite) +{ + gint index; + + g_return_val_if_fail (variable != NULL, NULL); + g_return_val_if_fail (strchr (variable, '=') == NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + + 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; + + length = envp ? g_strv_length (envp) : 0; + envp = g_renew (gchar *, envp, length + 2); + envp[length] = g_strdup_printf ("%s=%s", variable, value); + envp[length + 1] = NULL; + } + + return envp; +} + +static gchar ** +g_environ_unsetenv_internal (gchar **envp, + const gchar *variable, + gboolean free_value) +{ + gint len; + gchar **e, **f; + + 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++; + } + else + { + if (free_value) + g_free (*e); + } + + e++; + } + *f = NULL; + + return envp; +} + + +/** + * g_environ_unsetenv: + * @envp: (allow-none) (array zero-terminated=1) (transfer full): an environment + * list that can be freed using g_strfreev() (e.g., as returned from g_get_environ()), + * or %NULL for an empty environment list + * @variable: the environment variable to remove, must not contain '=' + * + * Removes the environment variable @variable from the provided + * environment @envp. + * + * Returns: (array zero-terminated=1) (transfer full): the + * updated environment list. Free it using g_strfreev(). + * + * Since: 2.32 + */ +gchar ** +g_environ_unsetenv (gchar **envp, + const gchar *variable) +{ + g_return_val_if_fail (variable != NULL, NULL); + g_return_val_if_fail (strchr (variable, '=') == NULL, NULL); + + if (envp == NULL) + return NULL; + return g_environ_unsetenv_internal (envp, variable, TRUE); +} + +/* UNIX implemention {{{1 */ +#ifndef G_OS_WIN32 /** * g_getenv: @@ -55,7 +229,7 @@ * 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 + * Returns: 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(). @@ -63,14 +237,191 @@ const gchar * g_getenv (const gchar *variable) { -#ifndef G_OS_WIN32 - g_return_val_if_fail (variable != NULL, NULL); return getenv (variable); +} + +/** + * g_setenv: + * @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 an environment variable. 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. + * + * Note that on some systems, when variables are overwritten, the memory + * used for the previous variables and its value isn't reclaimed. + * + * You should be mindful of the fact that environment variable handling + * in UNIX is not thread-safe, and your program may crash if one thread + * calls g_setenv() while another thread is calling getenv(). (And note + * that many functions, such as gettext(), call getenv() internally.) + * This function is only safe to use at the very start of your program, + * before creating any other threads (or creating objects that create + * worker threads of their own). + * + * If you need to set up the environment for a child process, you can + * use g_get_environ() to get an environment array, modify that with + * g_environ_setenv() and g_environ_unsetenv(), and then pass that + * array directly to execvpe(), g_spawn_async(), or the like. + * + * Returns: %FALSE if the environment variable couldn't be set. + * + * Since: 2.4 + */ +gboolean +g_setenv (const gchar *variable, + const gchar *value, + gboolean overwrite) +{ + gint result; +#ifndef HAVE_SETENV + gchar *string; +#endif + + g_return_val_if_fail (variable != NULL, FALSE); + g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + +#ifdef HAVE_SETENV + result = setenv (variable, value, overwrite); +#else + if (!overwrite && getenv (variable) != NULL) + return TRUE; + + /* This results in a leak when you overwrite existing + * settings. It would be fairly easy to fix this by keeping + * our own parallel array or hash table. + */ + string = g_strconcat (variable, "=", value, NULL); + result = putenv (string); +#endif + return result == 0; +} + +#ifdef HAVE__NSGETENVIRON +#define environ (*_NSGetEnviron()) +#else +/* According to the Single Unix Specification, environ is not + * in any system header, although unistd.h often declares it. + */ +extern char **environ; +#endif + +/** + * g_unsetenv: + * @variable: the environment variable to remove, must not contain '=' + * + * Removes an environment variable from the environment. + * + * Note that on some systems, when variables are overwritten, the + * memory used for the previous variables and its value isn't reclaimed. + * + * You should be mindful of the fact that environment variable handling + * in UNIX is not thread-safe, and your program may crash if one thread + * calls g_unsetenv() while another thread is calling getenv(). (And note + * that many functions, such as gettext(), call getenv() internally.) This + * function is only safe to use at the very start of your program, before + * creating any other threads (or creating objects that create worker + * threads of their own). + * + * If you need to set up the environment for a child process, you can + * use g_get_environ() to get an environment array, modify that with + * g_environ_setenv() and g_environ_unsetenv(), and then pass that + * array directly to execvpe(), g_spawn_async(), or the like. + * + * Since: 2.4 + */ +void +g_unsetenv (const gchar *variable) +{ + g_return_if_fail (variable != NULL); + g_return_if_fail (strchr (variable, '=') == NULL); + +#ifdef HAVE_UNSETENV + unsetenv (variable); +#else /* !HAVE_UNSETENV */ + /* Mess directly with the environ array. + * This seems to be the only portable way to do this. + */ + g_environ_unsetenv_internal (environ, variable, FALSE); +#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; -#else /* G_OS_WIN32 */ + 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; @@ -96,7 +447,11 @@ g_getenv (const gchar *variable) if (len == 0) { g_free (wname); - return NULL; + if (GetLastError () == ERROR_ENVVAR_NOT_FOUND) + return NULL; + + quark = g_quark_from_static_string (""); + return g_quark_to_string (quark); } else if (len == 1) len = 2; @@ -135,85 +490,24 @@ g_getenv (const gchar *variable) g_free (wname); g_free (wvalue); - quark = g_quark_from_string (value); - g_free (value); - - return g_quark_to_string (quark); - -#endif /* G_OS_WIN32 */ -} - -/** - * g_setenv: - * @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 an environment variable. 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. - * - * Note that on some systems, when variables are overwritten, the memory - * used for the previous variables and its value isn't reclaimed. - * - * - * Environment variable handling in UNIX is not thread-safe, and your - * program may crash if one thread calls g_setenv() while another - * thread is calling getenv(). (And note that many functions, such as - * gettext(), call getenv() internally.) This function is only safe to - * use at the very start of your program, before creating any other - * threads (or creating objects that create worker threads of their - * own). - * - * If you need to set up the environment for a child process, you can - * use g_get_environ() to get an environment array, modify that with - * g_environ_setenv() and g_environ_unsetenv(), and then pass that - * array directly to execvpe(), g_spawn_async(), or the like. - * - * - * Returns: %FALSE if the environment variable couldn't be set. - * - * Since: 2.4 - */ -gboolean -g_setenv (const gchar *variable, - const gchar *value, - gboolean overwrite) -{ -#ifndef G_OS_WIN32 - - gint result; -#ifndef HAVE_SETENV - gchar *string; -#endif - - g_return_val_if_fail (variable != NULL, FALSE); - g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE); - -#ifdef HAVE_SETENV - result = setenv (variable, value, overwrite); -#else - if (!overwrite && getenv (variable) != NULL) - return TRUE; - - /* This results in a leak when you overwrite existing - * settings. It would be fairly easy to fix this by keeping - * our own parallel array or hash table. - */ - string = g_strconcat (variable, "=", value, NULL); - result = putenv (string); -#endif - return result == 0; + quark = g_quark_from_string (value); + g_free (value); -#else /* G_OS_WIN32 */ + 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 (value != 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); @@ -249,68 +543,11 @@ g_setenv (const gchar *variable, g_free (wvalue); return retval; - -#endif /* G_OS_WIN32 */ } -#ifdef HAVE__NSGETENVIRON -#define environ (*_NSGetEnviron()) -#elif !defined(G_OS_WIN32) - -/* According to the Single Unix Specification, environ is not - * in any system header, although unistd.h often declares it. - */ -extern char **environ; -#endif - -/** - * g_unsetenv: - * @variable: the environment variable to remove, must not contain '=' - * - * Removes an environment variable from the environment. - * - * Note that on some systems, when variables are overwritten, the - * memory used for the previous variables and its value isn't reclaimed. - * - * - * Environment variable handling in UNIX is not thread-safe, and your - * program may crash if one thread calls g_unsetenv() while another - * thread is calling getenv(). (And note that many functions, such as - * gettext(), call getenv() internally.) This function is only safe - * to use at the very start of your program, before creating any other - * threads (or creating objects that create worker threads of their - * own). - * - * If you need to set up the environment for a child process, you can - * use g_get_environ() to get an environment array, modify that with - * g_environ_setenv() and g_environ_unsetenv(), and then pass that - * array directly to execvpe(), g_spawn_async(), or the like. - * - * - * Since: 2.4 - */ 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 */ - -#else /* G_OS_WIN32 */ - wchar_t *wname, *wassignment; gchar *tem; @@ -329,49 +566,11 @@ g_unsetenv (const gchar *variable) 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; @@ -410,203 +609,86 @@ g_listenv (void) 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; strings = GetEnvironmentStringsW (); - for (n = 0; strings[n]; n += wcslen (strings + n) + 1); - result = g_new (char *, n + 1); - for (i = 0; strings[i]; i += wcslen (strings + i) + 1) - result[i] = g_utf16_to_utf8 (strings + i, -1, NULL, NULL, NULL); + for (n = 0, i = 0; strings[n]; i++) + n += wcslen (strings + n) + 1; + + result = g_new (char *, i + 1); + for (n = 0, i = 0; strings[n]; i++) + { + result[i] = g_utf16_to_utf8 (strings + n, -1, NULL, NULL, NULL); + n += wcslen (strings + n) + 1; + } FreeEnvironmentStringsW (strings); result[i] = NULL; return result; -#endif } -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; - } +/* Win32 binary compatibility versions {{{1 */ +#ifndef _WIN64 - 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: */