diff --git a/ChangeLog b/ChangeLog index 1803cd247..da15a34bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2005-01-01 Tor Lillqvist + + * glib/glib.symbols + * glib/gutils.h + * glib/gutils.c: Make also g_getenv(), g_setenv(), g_unsetenv() + and g_find_program_in_path() take and return UTF-8 strings on + Win32. Implement DLL ABI backward compatility for them, too. Move + all the DLL ABI stability wrappers to the end of the file. Use + wide character API when available in inner_find_program_in_path(). + + * glib/gfileutils.c: With the UTF-8ness of g_getenv() above, just + use g_getenv() to get PATHEXT. (Yeah, it's probably overdoing it + to consider somebody actually having anything else than ASCII + in PATHEXT, but...) + 2004-12-31 Tor Lillqvist * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1803cd247..da15a34bb 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,18 @@ +2005-01-01 Tor Lillqvist + + * glib/glib.symbols + * glib/gutils.h + * glib/gutils.c: Make also g_getenv(), g_setenv(), g_unsetenv() + and g_find_program_in_path() take and return UTF-8 strings on + Win32. Implement DLL ABI backward compatility for them, too. Move + all the DLL ABI stability wrappers to the end of the file. Use + wide character API when available in inner_find_program_in_path(). + + * glib/gfileutils.c: With the UTF-8ness of g_getenv() above, just + use g_getenv() to get PATHEXT. (Yeah, it's probably overdoing it + to consider somebody actually having anything else than ASCII + in PATHEXT, but...) + 2004-12-31 Tor Lillqvist * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 1803cd247..da15a34bb 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,18 @@ +2005-01-01 Tor Lillqvist + + * glib/glib.symbols + * glib/gutils.h + * glib/gutils.c: Make also g_getenv(), g_setenv(), g_unsetenv() + and g_find_program_in_path() take and return UTF-8 strings on + Win32. Implement DLL ABI backward compatility for them, too. Move + all the DLL ABI stability wrappers to the end of the file. Use + wide character API when available in inner_find_program_in_path(). + + * glib/gfileutils.c: With the UTF-8ness of g_getenv() above, just + use g_getenv() to get PATHEXT. (Yeah, it's probably overdoing it + to consider somebody actually having anything else than ASCII + in PATHEXT, but...) + 2004-12-31 Tor Lillqvist * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 1803cd247..da15a34bb 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,18 @@ +2005-01-01 Tor Lillqvist + + * glib/glib.symbols + * glib/gutils.h + * glib/gutils.c: Make also g_getenv(), g_setenv(), g_unsetenv() + and g_find_program_in_path() take and return UTF-8 strings on + Win32. Implement DLL ABI backward compatility for them, too. Move + all the DLL ABI stability wrappers to the end of the file. Use + wide character API when available in inner_find_program_in_path(). + + * glib/gfileutils.c: With the UTF-8ness of g_getenv() above, just + use g_getenv() to get PATHEXT. (Yeah, it's probably overdoing it + to consider somebody actually having anything else than ASCII + in PATHEXT, but...) + 2004-12-31 Tor Lillqvist * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1803cd247..da15a34bb 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,18 @@ +2005-01-01 Tor Lillqvist + + * glib/glib.symbols + * glib/gutils.h + * glib/gutils.c: Make also g_getenv(), g_setenv(), g_unsetenv() + and g_find_program_in_path() take and return UTF-8 strings on + Win32. Implement DLL ABI backward compatility for them, too. Move + all the DLL ABI stability wrappers to the end of the file. Use + wide character API when available in inner_find_program_in_path(). + + * glib/gfileutils.c: With the UTF-8ness of g_getenv() above, just + use g_getenv() to get PATHEXT. (Yeah, it's probably overdoing it + to consider somebody actually having anything else than ASCII + in PATHEXT, but...) + 2004-12-31 Tor Lillqvist * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to diff --git a/glib/gfileutils.c b/glib/gfileutils.c index a9a14c538..8b9c4f7d8 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -146,7 +146,7 @@ g_file_test (const gchar *filename, if (test & G_FILE_TEST_IS_EXECUTABLE) { const gchar *lastdot = strrchr (filename, '.'); - gchar *pathext = NULL, *tem, *p; + const gchar *pathext = NULL, *p; int extlen; if (lastdot == NULL) @@ -160,53 +160,11 @@ g_file_test (const gchar *filename, /* Check if it is one of the types listed in %PATHEXT% */ - /* Perhaps unfortunately, g_getenv() doesn't return UTF-8, but - * system codepage. And _wgetenv() isn't useful either, as the C - * runtime just keeps system codepage versions of the - * environment variables in applications that aren't built - * specially. So use GetEnvironmentVariableW(). - */ - if (G_WIN32_HAVE_WIDECHAR_API ()) - { - wchar_t dummy[2], *wvar; - int len; - - len = GetEnvironmentVariableW (L"PATHEXT", dummy, 2); - - if (len == 0) - return FALSE; - - wvar = g_new (wchar_t, len); - - if (GetEnvironmentVariableW (L"PATHEXT", wvar, len) == len - 1) - pathext = g_utf16_to_utf8 (wvar, -1, NULL, NULL, NULL); - - g_free (wvar); - } - else - { - gchar dummy[2], *cpvar; - int len; - - len = GetEnvironmentVariableA ("PATHEXT", dummy, 2); - - if (len == 0) - return FALSE; - - cpvar = g_new (gchar, len); - - if (GetEnvironmentVariableA ("PATHEXT", cpvar, len) == len - 1) - pathext = g_locale_to_utf8 (cpvar, -1, NULL, NULL, NULL); - - g_free (cpvar); - } - + pathext = g_getenv ("PATHEXT"); if (pathext == NULL) return FALSE; - tem = pathext; pathext = g_utf8_casefold (pathext, -1); - g_free (tem); lastdot = g_utf8_casefold (lastdot, -1); extlen = strlen (lastdot); @@ -214,13 +172,13 @@ g_file_test (const gchar *filename, p = pathext; while (TRUE) { - gchar *q = strchr (p, ';'); + const gchar *q = strchr (p, ';'); if (q == NULL) q = p + strlen (p); if (extlen == q - p && memcmp (lastdot, p, extlen) == 0) { - g_free (pathext); + g_free ((gchar *) pathext); g_free ((gchar *) lastdot); return TRUE; } @@ -230,7 +188,7 @@ g_file_test (const gchar *filename, break; } - g_free (pathext); + g_free ((gchar *) pathext); g_free ((gchar *) lastdot); return FALSE; } diff --git a/glib/glib.symbols b/glib/glib.symbols index 2285395ca..ea4c785b7 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -195,7 +195,10 @@ g_file_test PRIVATE #ifdef G_OS_WIN32 g_file_test_utf8 #endif -g_find_program_in_path +g_find_program_in_path PRIVATE +#ifdef G_OS_WIN32 +g_find_program_in_path_utf8 +#endif g_fopen g_fprintf G_GNUC_PRINTF(2,3) g_free @@ -208,7 +211,10 @@ g_get_current_dir_utf8 #endif g_get_current_time g_get_filename_charsets -g_getenv +g_getenv PRIVATE +#ifdef G_OS_WIN32 +g_getenv_utf8 +#endif g_get_home_dir PRIVATE #ifdef G_OS_WIN32 g_get_home_dir_utf8 @@ -645,7 +651,10 @@ g_scanner_sync_file_offset g_scanner_unexp_token g_scanner_warn G_GNUC_PRINTF(2,3) g_set_application_name -g_setenv +g_setenv PRIVATE +#ifdef G_OS_WIN32 +g_setenv_utf8 +#endif g_set_error G_GNUC_PRINTF(4,5) g_set_prgname g_set_printerr_handler @@ -882,7 +891,10 @@ g_unichar_xdigit_value G_GNUC_CONST g_unicode_canonical_decomposition G_GNUC_MALLOC g_unicode_canonical_ordering g_unlink -g_unsetenv +g_unsetenv PRIVATE +#ifdef G_OS_WIN32 +g_unsetenv_utf8 +#endif g_uri_list_extract_uris G_GNUC_MALLOC g_usleep g_utf16_to_ucs4 G_GNUC_MALLOC diff --git a/glib/gutils.c b/glib/gutils.c index f9fb93127..5c92aba1b 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -236,46 +236,51 @@ g_find_program_in_path (const gchar *program) { const gchar *last_dot = strrchr (program, '.'); - if (last_dot == NULL || strchr (last_dot, '\\') != NULL) + if (last_dot == NULL || + strchr (last_dot, '\\') != NULL || + strchr (last_dot, '/') != NULL) { const gint program_length = strlen (program); - const gchar *pathext = getenv ("PATHEXT"); - const gchar *p; + gchar *pathext = g_build_path (";", + ".exe;.cmd;.bat;.com", + g_getenv ("PATHEXT"), + NULL); + gchar *p; gchar *decorated_program; gchar *retval; - if (pathext == NULL) - pathext = ".com;.exe;.bat"; - p = pathext; do { - pathext = p; - p = my_strchrnul (pathext, ';'); + gchar *q = my_strchrnul (p, ';'); - decorated_program = g_malloc (program_length + (p-pathext) + 1); + decorated_program = g_malloc (program_length + (q-p) + 1); memcpy (decorated_program, program, program_length); - memcpy (decorated_program+program_length, pathext, p-pathext); - decorated_program [program_length + (p-pathext)] = '\0'; + memcpy (decorated_program+program_length, p, q-p); + decorated_program [program_length + (q-p)] = '\0'; retval = inner_find_program_in_path (decorated_program); g_free (decorated_program); if (retval != NULL) - return retval; + { + g_free (pathext); + return retval; + } + p = q; } while (*p++ != '\0'); + g_free (pathext); return NULL; } else return inner_find_program_in_path (program); } -#define g_find_program_in_path inner_find_program_in_path #endif /** * g_find_program_in_path: - * @program: a program name + * @program: a program name in the GLib file name encoding * * Locates the first executable named @program in the user's path, in the * same way that execvp() would locate it. Returns an allocated string @@ -283,29 +288,34 @@ g_find_program_in_path (const gchar *program) * the path. If @program is already an absolute path, returns a copy of * @program if @program exists and is executable, and NULL otherwise. * - * On Windows, if @program does not have a file type suffix, tries to - * append the suffixes in the PATHEXT environment variable (if that - * doesn't exists, the suffixes .com, .exe, and .bat) in turn, and - * then look for the resulting file name in the same way as - * CreateProcess() would. This means first in the directory where the + * On Windows, if @program does not have a file type suffix, tries + * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in + * the PATHEXT environment variable. + * + * It looks for the file in the same way as CreateProcess() + * would. This means first in the directory where the executing * program was loaded from, then in the current directory, then in the * Windows 32-bit system directory, then in the Windows directory, and - * finally in the directories in the PATH environment variable. If - * the program is found, the return value contains the full name - * including the type suffix. + * finally in the directories in the PATH environment variable. If the + * program is found, the return value contains the full name including + * the type suffix. * * Return value: absolute path, or NULL **/ #ifdef G_OS_WIN32 -static -#endif +static gchar * +inner_find_program_in_path (const gchar *program) +#else gchar* g_find_program_in_path (const gchar *program) +#endif { const gchar *path, *p; gchar *name, *freeme; #ifdef G_OS_WIN32 - gchar *path_tmp; + const gchar *path_copy; + gchar *filename = NULL, *appdir = NULL; + gchar *sysdir = NULL, *windir = NULL; #endif size_t len; size_t pathlen; @@ -345,21 +355,82 @@ g_find_program_in_path (const gchar *program) path = "/bin:/usr/bin:."; } #else - { - gchar *tmp; - gchar moddir[MAXPATHLEN], sysdir[MAXPATHLEN], windir[MAXPATHLEN]; + if (G_WIN32_HAVE_WIDECHAR_API ()) + { + int n; + wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN], + wwindir[MAXPATHLEN]; + + n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN); + if (n > 0 && n < MAXPATHLEN) + filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL); + + n = GetSystemDirectoryW (wsysdir, MAXPATHLEN); + if (n > 0 && n < MAXPATHLEN) + sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL); + + n = GetWindowsDirectoryW (wwindir, MAXPATHLEN); + if (n > 0 && n < MAXPATHLEN) + windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL); + } + else + { + int n; + gchar cpfilename[MAXPATHLEN], cpsysdir[MAXPATHLEN], + cpwindir[MAXPATHLEN]; + + n = GetModuleFileNameA (NULL, cpfilename, MAXPATHLEN); + if (n > 0 && n < MAXPATHLEN) + filename = g_locale_to_utf8 (cpfilename, -1, NULL, NULL, NULL); + + n = GetSystemDirectoryA (cpsysdir, MAXPATHLEN); + if (n > 0 && n < MAXPATHLEN) + sysdir = g_locale_to_utf8 (cpsysdir, -1, NULL, NULL, NULL); + + n = GetWindowsDirectoryA (cpwindir, MAXPATHLEN); + if (n > 0 && n < MAXPATHLEN) + windir = g_locale_to_utf8 (cpwindir, -1, NULL, NULL, NULL); + } + + if (filename) + { + appdir = g_path_get_dirname (filename); + g_free (filename); + } + + path = g_strdup (path); - GetModuleFileName (NULL, moddir, sizeof (moddir)); - tmp = g_path_get_dirname (moddir); - GetSystemDirectory (sysdir, sizeof (sysdir)); - GetWindowsDirectory (windir, sizeof (windir)); - path_tmp = g_strconcat (tmp, ";.;", sysdir, ";", windir, - (path != NULL ? ";" : NULL), - (path != NULL ? path : NULL), - NULL); - g_free (tmp); - path = path_tmp; + if (windir) + { + const gchar *tem = path; + path = g_strconcat (windir, ";", path, NULL); + g_free ((gchar *) tem); + g_free (windir); + } + + if (sysdir) + { + const gchar *tem = path; + path = g_strconcat (sysdir, ";", path, NULL); + g_free ((gchar *) tem); + g_free (sysdir); + } + + { + const gchar *tem = path; + path = g_strconcat (".;", path, NULL); + g_free ((gchar *) tem); } + + if (appdir) + { + const gchar *tem = path; + path = g_strconcat (appdir, ";", path, NULL); + g_free ((gchar *) tem); + g_free (appdir); + } + + path_copy = path; #endif len = strlen (program) + 1; @@ -394,7 +465,7 @@ g_find_program_in_path (const gchar *program) ret = g_strdup (startp); g_free (freeme); #ifdef G_OS_WIN32 - g_free (path_tmp); + g_free ((gchar *) path_copy); #endif return ret; } @@ -403,7 +474,7 @@ g_find_program_in_path (const gchar *program) g_free (freeme); #ifdef G_OS_WIN32 - g_free (path_tmp); + g_free ((gchar *) path_copy); #endif return NULL; @@ -801,82 +872,156 @@ g_get_current_dir (void) #endif /* !Win32 */ } -#ifdef G_OS_WIN32 - -#undef g_get_current_dir - -/* Binary compatibility version. Not for newly compiled code. */ - -gchar* -g_get_current_dir (void) -{ - gchar *utf8_dir = g_get_current_dir_utf8 (); - gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL); - g_free (utf8_dir); - return dir; -} - -#endif - /** * g_getenv: - * @variable: the environment variable to get. + * @variable: the environment variable to get, in the GLib file name encoding. * - * Returns an environment variable. + * 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(). + * 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(). **/ G_CONST_RETURN gchar* g_getenv (const gchar *variable) { #ifndef G_OS_WIN32 + g_return_val_if_fail (variable != NULL, NULL); return getenv (variable); -#else + +#else /* G_OS_WIN32 */ + GQuark quark; - gchar *system_env; - gchar *expanded_env; - guint length; - gchar dummy[2]; + gchar *value; g_return_val_if_fail (variable != NULL, NULL); - - system_env = getenv (variable); - if (!system_env) - return 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(). (If all software was written - * in the best possible way, such environment variables would be - * stored in the Registry as REG_EXPAND_SZ type values, and would - * then get automatically expanded before the 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. + * 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.) */ - if (strchr (system_env, '%') == NULL) + if (G_WIN32_HAVE_WIDECHAR_API ()) { - /* No reference to other variable(s), return value as such. */ - return system_env; + wchar_t dummy[2], *wname, *wvalue; + int len; + + wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL); + + len = GetEnvironmentVariableW (wname, dummy, 2); + + if (len == 0) + { + g_free (wname); + return NULL; + } + + 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); + } + else + { + gchar dummy[3], *cpname, *cpvalue; + int len; + + cpname = g_locale_from_utf8 (variable, -1, NULL, NULL, NULL); + + g_return_val_if_fail (cpname != NULL, NULL); + + len = GetEnvironmentVariableA (cpname, dummy, 2); + + if (len == 0) + { + g_free (cpname); + return NULL; + } + + cpvalue = g_new (gchar, len); + + if (GetEnvironmentVariableA (cpname, cpvalue, len) != len - 1) + { + g_free (cpname); + g_free (cpvalue); + return NULL; + } + + if (strchr (cpvalue, '%') != NULL) + { + gchar *tem = cpvalue; + + len = ExpandEnvironmentStringsA (cpvalue, dummy, 3); + + if (len > 0) + { + cpvalue = g_new (gchar, len); + + if (ExpandEnvironmentStringsA (tem, cpvalue, len) != len) + { + g_free (cpvalue); + cpvalue = tem; + } + else + g_free (tem); + } + } + + value = g_locale_to_utf8 (cpvalue, -1, NULL, NULL, NULL); + + g_free (cpname); + g_free (cpvalue); } - /* First check how much space we need */ - length = ExpandEnvironmentStrings (system_env, dummy, 2); - - expanded_env = g_malloc (length); - - ExpandEnvironmentStrings (system_env, expanded_env, length); - - quark = g_quark_from_string (expanded_env); - g_free (expanded_env); + quark = g_quark_from_string (value); + g_free (value); return g_quark_to_string (quark); -#endif + +#endif /* G_OS_WIN32 */ } /** @@ -885,7 +1030,10 @@ g_getenv (const gchar *variable) * @value: the value for to set the variable to. * @overwrite: whether to change the variable if it already exists. * - * Sets an environment variable. + * 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 any sequence of bytes. On Windows, they should be in + * UTF-8. * * Note that on some systems, the memory used for the variable and its value * can't be reclaimed later. @@ -899,17 +1047,20 @@ 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 && g_getenv (variable) != NULL) + if (!overwrite && getenv (variable) != NULL) return TRUE; /* This results in a leak when you overwrite existing @@ -920,19 +1071,76 @@ g_setenv (const gchar *variable, result = putenv (string); #endif return result == 0; + +#else /* G_OS_WIN32 */ + + gboolean retval; + + 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. + */ + + if (G_WIN32_HAVE_WIDECHAR_API ()) + { + wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL); + wchar_t *wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL); + gchar *tem = g_strconcat (variable, "=", value, NULL); + wchar_t *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); + } + else + { + /* In the non-Unicode case (Win9x), just putenv() is good + * enough. + */ + gchar *tem = g_strconcat (variable, "=", value, NULL); + gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL); + + g_free (tem); + + retval = (putenv (cpassignment) == 0); + + g_free (cpassignment); + } + + return retval; + +#endif /* G_OS_WIN32 */ } +#ifndef G_OS_WIN32 #ifndef HAVE_UNSETENV /* According to the Single Unix Specification, environ is not in * any system header, although unistd.h often declares it. */ -# ifndef _MSC_VER -/* - * Win32 - at least msvc headers declare it so let's avoid - * warning C4273: '__p__environ' : inconsistent dll linkage. dllexport assumed. - */ extern char **environ; -# endif +#endif #endif /** @@ -950,14 +1158,18 @@ extern char **environ; 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 +#else /* !HAVE_UNSETENV */ int len; gchar **e, **f; + g_return_if_fail (variable != NULL); g_return_if_fail (strchr (variable, '=') == NULL); len = strlen (variable); @@ -979,7 +1191,44 @@ g_unsetenv (const gchar *variable) e++; } *f = NULL; -#endif +#endif /* !HAVE_UNSETENV */ + +#else /* G_OS_WIN32 */ + + g_return_if_fail (variable != NULL); + g_return_if_fail (strchr (variable, '=') == NULL); + g_return_if_fail (g_utf8_validate (variable, -1, NULL)); + + if (G_WIN32_HAVE_WIDECHAR_API ()) + { + wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL); + gchar *tem = g_strconcat (variable, "=", NULL); + wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL); + + g_free (tem); + _wputenv (wassignment); + g_free (wassignment); + + SetEnvironmentVariableW (wname, NULL); + + g_free (wname); + } + else + { + /* In the non-Unicode case (Win9x), just putenv() is good + * enough. + */ + gchar *tem = g_strconcat (variable, "=", NULL); + gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL); + + g_free (tem); + + putenv (cpassignment); + + g_free (cpassignment); + } + +#endif /* G_OS_WIN32 */ } G_LOCK_DEFINE_STATIC (g_utils_global); @@ -1047,13 +1296,6 @@ g_get_any_init (void) { if (!g_tmp_dir) { -#ifdef G_OS_WIN32 - /* g_tmp_dir is kept in the system codepage for most of this - * function, and converted at the end. home_dir, user_name and - * real_name are handled in UTF-8 all the way. - */ -#endif - g_tmp_dir = g_strdup (g_getenv ("TMPDIR")); if (!g_tmp_dir) g_tmp_dir = g_strdup (g_getenv ("TMP")); @@ -1076,7 +1318,7 @@ g_get_any_init (void) #ifndef G_OS_WIN32 g_tmp_dir = g_strdup ("/tmp"); #else /* G_OS_WIN32 */ - g_tmp_dir = g_strdup ("C:\\"); + g_tmp_dir = g_strdup ("\\"); #endif /* G_OS_WIN32 */ } @@ -1084,23 +1326,18 @@ g_get_any_init (void) /* We check $HOME first for Win32, though it is a last resort for Unix * where we prefer the results of getpwuid(). */ - { - const gchar *home = g_getenv ("HOME"); - gchar *home_utf8 = NULL; + g_home_dir = g_strdup (g_getenv ("HOME")); - if (home) - home_utf8 = g_locale_to_utf8 (home, -1, NULL, NULL, NULL); - - /* Only believe HOME if it is an absolute path and exists */ - if (home_utf8) - { - if (g_path_is_absolute (home_utf8) && - g_file_test (home_utf8, G_FILE_TEST_IS_DIR)) - g_home_dir = home_utf8; - else - g_free (home_utf8); - } - } + /* Only believe HOME if it is an absolute path and exists */ + if (g_home_dir) + { + if (!(g_path_is_absolute (g_home_dir) && + g_file_test (g_home_dir, G_FILE_TEST_IS_DIR))) + { + g_free (g_home_dir); + g_home_dir = NULL; + } + } /* In case HOME is Unix-style (it happens), convert it to * Windows style. @@ -1115,9 +1352,8 @@ g_get_any_init (void) if (!g_home_dir) { /* USERPROFILE is probably the closest equivalent to $HOME? */ - if (getenv ("USERPROFILE") != NULL) - g_home_dir = g_locale_to_utf8 (g_getenv ("USERPROFILE"), - -1, NULL, NULL, NULL); + if (g_getenv ("USERPROFILE") != NULL) + g_home_dir = g_strdup (g_getenv ("USERPROFILE")); } if (!g_home_dir) @@ -1130,18 +1366,10 @@ g_get_any_init (void) * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and * HOMEPATH is its root "\"? */ - if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL) - { - gchar *homedrive, *homepath; - - homedrive = g_strdup (g_getenv ("HOMEDRIVE")); - homepath = g_locale_to_utf8 (g_getenv ("HOMEPATH"), - -1, NULL, NULL, NULL); - - g_home_dir = g_strconcat (homedrive, homepath, NULL); - g_free (homedrive); - g_free (homepath); - } + if (g_getenv ("HOMEDRIVE") != NULL && g_getenv ("HOMEPATH") != NULL) + g_home_dir = g_strconcat (g_getenv ("HOMEDRIVE"), + g_getenv ("HOMEPATH"), + NULL); } #endif /* G_OS_WIN32 */ @@ -1286,13 +1514,17 @@ g_get_any_init (void) g_real_name = g_strdup ("Unknown"); #ifdef G_OS_WIN32 - g_tmp_dir_cp = g_tmp_dir; - g_tmp_dir = g_locale_to_utf8 (g_tmp_dir_cp, -1, NULL, NULL, NULL); - + g_tmp_dir_cp = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL); g_user_name_cp = g_locale_from_utf8 (g_user_name, -1, NULL, NULL, NULL); - g_real_name_cp = g_locale_from_utf8 (g_real_name, -1, NULL, NULL, NULL); + if (!g_tmp_dir_cp) + g_tmp_dir_cp = g_strdup ("\\"); + if (!g_user_name_cp) + g_user_name_cp = g_strdup ("somebody"); + if (!g_real_name_cp) + g_real_name_cp = g_strdup ("Unknown"); + /* home_dir might be NULL, unlike tmp_dir, user_name and * real_name. */ @@ -1315,25 +1547,6 @@ g_get_user_name (void) return g_user_name; } -#ifdef G_OS_WIN32 - -#undef g_get_user_name - -/* Binary compatibility version. Not for newly compiled code. */ - -G_CONST_RETURN gchar* -g_get_user_name (void) -{ - G_LOCK (g_utils_global); - if (!g_tmp_dir) - g_get_any_init (); - G_UNLOCK (g_utils_global); - - return g_user_name_cp; -} - -#endif - G_CONST_RETURN gchar* g_get_real_name (void) { @@ -1345,25 +1558,6 @@ g_get_real_name (void) return g_real_name; } -#ifdef G_OS_WIN32 - -#undef g_get_real_name - -/* Binary compatibility version. Not for newly compiled code. */ - -G_CONST_RETURN gchar* -g_get_real_name (void) -{ - G_LOCK (g_utils_global); - if (!g_tmp_dir) - g_get_any_init (); - G_UNLOCK (g_utils_global); - - return g_real_name_cp; -} - -#endif - G_CONST_RETURN gchar* g_get_home_dir (void) { @@ -1375,25 +1569,6 @@ g_get_home_dir (void) return g_home_dir; } -#ifdef G_OS_WIN32 - -#undef g_get_home_dir - -/* Binary compatibility version. Not for newly compiled code. */ - -G_CONST_RETURN gchar* -g_get_home_dir (void) -{ - G_LOCK (g_utils_global); - if (!g_tmp_dir) - g_get_any_init (); - G_UNLOCK (g_utils_global); - - return g_home_dir_cp; -} - -#endif - /* Return a directory to be used to store temporary files. This is the * value of the TMPDIR, TMP or TEMP environment variables (they are * checked in that order). If none of those exist, use P_tmpdir from @@ -1412,25 +1587,6 @@ g_get_tmp_dir (void) return g_tmp_dir; } -#ifdef G_OS_WIN32 - -#undef g_get_tmp_dir - -/* Binary compatibility version. Not for newly compiled code. */ - -G_CONST_RETURN gchar* -g_get_tmp_dir (void) -{ - G_LOCK (g_utils_global); - if (!g_tmp_dir) - g_get_any_init (); - G_UNLOCK (g_utils_global); - - return g_tmp_dir_cp; -} - -#endif - G_LOCK_DEFINE_STATIC (g_prgname); static gchar *g_prgname = NULL; @@ -2189,3 +2345,135 @@ _glib_gettext (const gchar *str) } #endif /* ENABLE_NLS */ + +#ifdef G_OS_WIN32 + +/* Binary compatibility versions. Not for newly compiled code. */ + +#undef g_find_program_in_path + +gchar* +g_find_program_in_path (const gchar *program) +{ + gchar *utf8_program = g_locale_to_utf8 (program, -1, NULL, NULL, NULL); + gchar *utf8_retval = g_find_program_in_path_utf8 (utf8_program); + gchar *retval; + + g_free (utf8_program); + if (utf8_retval == NULL) + return NULL; + retval = g_locale_from_utf8 (utf8_retval, -1, NULL, NULL, NULL); + g_free (utf8_retval); + + return retval; +} + +#undef g_get_current_dir + +gchar* +g_get_current_dir (void) +{ + gchar *utf8_dir = g_get_current_dir_utf8 (); + gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL); + g_free (utf8_dir); + return dir; +} + +#undef g_getenv + +G_CONST_RETURN gchar* +g_getenv (const gchar *variable) +{ + gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL); + const gchar *utf8_value = g_getenv_utf8 (utf8_variable); + gchar *value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL); + GQuark quark = g_quark_from_string (value); + + g_free (utf8_variable); + g_free (value); + + return g_quark_to_string (quark); +} + +#undef g_setenv + +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); + + g_free (utf8_variable); + g_free (utf8_value); + + return retval; +} + +#undef g_unsetenv + +void +g_unsetenv (const gchar *variable) +{ + gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL); + + g_unsetenv_utf8 (utf8_variable); + + g_free (utf8_variable); +} + +#undef g_get_user_name + +G_CONST_RETURN gchar* +g_get_user_name (void) +{ + G_LOCK (g_utils_global); + if (!g_tmp_dir) + g_get_any_init (); + G_UNLOCK (g_utils_global); + + return g_user_name_cp; +} + +#undef g_get_real_name + +G_CONST_RETURN gchar* +g_get_real_name (void) +{ + G_LOCK (g_utils_global); + if (!g_tmp_dir) + g_get_any_init (); + G_UNLOCK (g_utils_global); + + return g_real_name_cp; +} + +#undef g_get_home_dir + +G_CONST_RETURN gchar* +g_get_home_dir (void) +{ + G_LOCK (g_utils_global); + if (!g_tmp_dir) + g_get_any_init (); + G_UNLOCK (g_utils_global); + + return g_home_dir_cp; +} + +#undef g_get_tmp_dir + +G_CONST_RETURN gchar* +g_get_tmp_dir (void) +{ + G_LOCK (g_utils_global); + if (!g_tmp_dir) + g_get_any_init (); + G_UNLOCK (g_utils_global); + + return g_tmp_dir_cp; +} + +#endif diff --git a/glib/gutils.h b/glib/gutils.h index 6544c0f25..8e43cde01 100644 --- a/glib/gutils.h +++ b/glib/gutils.h @@ -192,6 +192,13 @@ void g_nullify_pointer (gpointer *nullify_location); /* return the environment string for the variable. The returned memory * must not be freed. */ +#ifdef G_OS_WIN32 +#define g_getenv g_getenv_utf8 +#define g_setenv g_setenv_utf8 +#define g_unsetenv g_unsetenv_utf8 +#define g_find_program_in_path g_find_program_in_path_utf8 +#endif + G_CONST_RETURN gchar* g_getenv (const gchar *variable); gboolean g_setenv (const gchar *variable, const gchar *value,