glib/glib.symbols glib/gutils.h Make also g_getenv(), g_setenv(),

2005-01-01  Tor Lillqvist  <tml@iki.fi>

	* 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...)
This commit is contained in:
Tor Lillqvist 2005-01-01 02:09:51 +00:00 committed by Tor Lillqvist
parent 7e6be89c62
commit 714887d0fa
9 changed files with 611 additions and 271 deletions

View File

@ -1,3 +1,18 @@
2005-01-01 Tor Lillqvist <tml@iki.fi>
* 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 <tml@iki.fi> 2004-12-31 Tor Lillqvist <tml@iki.fi>
* glib/gfileutils.c (g_file_test): Rewrite the Win32 version to * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to

View File

@ -1,3 +1,18 @@
2005-01-01 Tor Lillqvist <tml@iki.fi>
* 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 <tml@iki.fi> 2004-12-31 Tor Lillqvist <tml@iki.fi>
* glib/gfileutils.c (g_file_test): Rewrite the Win32 version to * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to

View File

@ -1,3 +1,18 @@
2005-01-01 Tor Lillqvist <tml@iki.fi>
* 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 <tml@iki.fi> 2004-12-31 Tor Lillqvist <tml@iki.fi>
* glib/gfileutils.c (g_file_test): Rewrite the Win32 version to * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to

View File

@ -1,3 +1,18 @@
2005-01-01 Tor Lillqvist <tml@iki.fi>
* 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 <tml@iki.fi> 2004-12-31 Tor Lillqvist <tml@iki.fi>
* glib/gfileutils.c (g_file_test): Rewrite the Win32 version to * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to

View File

@ -1,3 +1,18 @@
2005-01-01 Tor Lillqvist <tml@iki.fi>
* 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 <tml@iki.fi> 2004-12-31 Tor Lillqvist <tml@iki.fi>
* glib/gfileutils.c (g_file_test): Rewrite the Win32 version to * glib/gfileutils.c (g_file_test): Rewrite the Win32 version to

View File

@ -146,7 +146,7 @@ g_file_test (const gchar *filename,
if (test & G_FILE_TEST_IS_EXECUTABLE) if (test & G_FILE_TEST_IS_EXECUTABLE)
{ {
const gchar *lastdot = strrchr (filename, '.'); const gchar *lastdot = strrchr (filename, '.');
gchar *pathext = NULL, *tem, *p; const gchar *pathext = NULL, *p;
int extlen; int extlen;
if (lastdot == NULL) if (lastdot == NULL)
@ -160,53 +160,11 @@ g_file_test (const gchar *filename,
/* Check if it is one of the types listed in %PATHEXT% */ /* Check if it is one of the types listed in %PATHEXT% */
/* Perhaps unfortunately, g_getenv() doesn't return UTF-8, but pathext = g_getenv ("PATHEXT");
* 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);
}
if (pathext == NULL) if (pathext == NULL)
return FALSE; return FALSE;
tem = pathext;
pathext = g_utf8_casefold (pathext, -1); pathext = g_utf8_casefold (pathext, -1);
g_free (tem);
lastdot = g_utf8_casefold (lastdot, -1); lastdot = g_utf8_casefold (lastdot, -1);
extlen = strlen (lastdot); extlen = strlen (lastdot);
@ -214,13 +172,13 @@ g_file_test (const gchar *filename,
p = pathext; p = pathext;
while (TRUE) while (TRUE)
{ {
gchar *q = strchr (p, ';'); const gchar *q = strchr (p, ';');
if (q == NULL) if (q == NULL)
q = p + strlen (p); q = p + strlen (p);
if (extlen == q - p && if (extlen == q - p &&
memcmp (lastdot, p, extlen) == 0) memcmp (lastdot, p, extlen) == 0)
{ {
g_free (pathext); g_free ((gchar *) pathext);
g_free ((gchar *) lastdot); g_free ((gchar *) lastdot);
return TRUE; return TRUE;
} }
@ -230,7 +188,7 @@ g_file_test (const gchar *filename,
break; break;
} }
g_free (pathext); g_free ((gchar *) pathext);
g_free ((gchar *) lastdot); g_free ((gchar *) lastdot);
return FALSE; return FALSE;
} }

View File

@ -195,7 +195,10 @@ g_file_test PRIVATE
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_file_test_utf8 g_file_test_utf8
#endif #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_fopen
g_fprintf G_GNUC_PRINTF(2,3) g_fprintf G_GNUC_PRINTF(2,3)
g_free g_free
@ -208,7 +211,10 @@ g_get_current_dir_utf8
#endif #endif
g_get_current_time g_get_current_time
g_get_filename_charsets g_get_filename_charsets
g_getenv g_getenv PRIVATE
#ifdef G_OS_WIN32
g_getenv_utf8
#endif
g_get_home_dir PRIVATE g_get_home_dir PRIVATE
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_get_home_dir_utf8 g_get_home_dir_utf8
@ -645,7 +651,10 @@ g_scanner_sync_file_offset
g_scanner_unexp_token g_scanner_unexp_token
g_scanner_warn G_GNUC_PRINTF(2,3) g_scanner_warn G_GNUC_PRINTF(2,3)
g_set_application_name 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_error G_GNUC_PRINTF(4,5)
g_set_prgname g_set_prgname
g_set_printerr_handler 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_decomposition G_GNUC_MALLOC
g_unicode_canonical_ordering g_unicode_canonical_ordering
g_unlink g_unlink
g_unsetenv g_unsetenv PRIVATE
#ifdef G_OS_WIN32
g_unsetenv_utf8
#endif
g_uri_list_extract_uris G_GNUC_MALLOC g_uri_list_extract_uris G_GNUC_MALLOC
g_usleep g_usleep
g_utf16_to_ucs4 G_GNUC_MALLOC g_utf16_to_ucs4 G_GNUC_MALLOC

View File

@ -236,46 +236,51 @@ g_find_program_in_path (const gchar *program)
{ {
const gchar *last_dot = strrchr (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 gint program_length = strlen (program);
const gchar *pathext = getenv ("PATHEXT"); gchar *pathext = g_build_path (";",
const gchar *p; ".exe;.cmd;.bat;.com",
g_getenv ("PATHEXT"),
NULL);
gchar *p;
gchar *decorated_program; gchar *decorated_program;
gchar *retval; gchar *retval;
if (pathext == NULL)
pathext = ".com;.exe;.bat";
p = pathext; p = pathext;
do do
{ {
pathext = p; gchar *q = my_strchrnul (p, ';');
p = my_strchrnul (pathext, ';');
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, program_length);
memcpy (decorated_program+program_length, pathext, p-pathext); memcpy (decorated_program+program_length, p, q-p);
decorated_program [program_length + (p-pathext)] = '\0'; decorated_program [program_length + (q-p)] = '\0';
retval = inner_find_program_in_path (decorated_program); retval = inner_find_program_in_path (decorated_program);
g_free (decorated_program); g_free (decorated_program);
if (retval != NULL) if (retval != NULL)
return retval; {
g_free (pathext);
return retval;
}
p = q;
} while (*p++ != '\0'); } while (*p++ != '\0');
g_free (pathext);
return NULL; return NULL;
} }
else else
return inner_find_program_in_path (program); return inner_find_program_in_path (program);
} }
#define g_find_program_in_path inner_find_program_in_path
#endif #endif
/** /**
* g_find_program_in_path: * 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 * Locates the first executable named @program in the user's path, in the
* same way that execvp() would locate it. Returns an allocated string * 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 * the path. If @program is already an absolute path, returns a copy of
* @program if @program exists and is executable, and NULL otherwise. * @program if @program exists and is executable, and NULL otherwise.
* *
* On Windows, if @program does not have a file type suffix, tries to * On Windows, if @program does not have a file type suffix, tries
* append the suffixes in the PATHEXT environment variable (if that * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
* doesn't exists, the suffixes .com, .exe, and .bat) in turn, and * the PATHEXT environment variable.
* then look for the resulting file name in the same way as *
* CreateProcess() would. This means first in the directory where the * 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 * program was loaded from, then in the current directory, then in the
* Windows 32-bit system directory, then in the Windows directory, and * Windows 32-bit system directory, then in the Windows directory, and
* finally in the directories in the PATH environment variable. If * finally in the directories in the PATH environment variable. If the
* the program is found, the return value contains the full name * program is found, the return value contains the full name including
* including the type suffix. * the type suffix.
* *
* Return value: absolute path, or NULL * Return value: absolute path, or NULL
**/ **/
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
static static gchar *
#endif inner_find_program_in_path (const gchar *program)
#else
gchar* gchar*
g_find_program_in_path (const gchar *program) g_find_program_in_path (const gchar *program)
#endif
{ {
const gchar *path, *p; const gchar *path, *p;
gchar *name, *freeme; gchar *name, *freeme;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
gchar *path_tmp; const gchar *path_copy;
gchar *filename = NULL, *appdir = NULL;
gchar *sysdir = NULL, *windir = NULL;
#endif #endif
size_t len; size_t len;
size_t pathlen; size_t pathlen;
@ -345,21 +355,82 @@ g_find_program_in_path (const gchar *program)
path = "/bin:/usr/bin:."; path = "/bin:/usr/bin:.";
} }
#else #else
{ if (G_WIN32_HAVE_WIDECHAR_API ())
gchar *tmp; {
gchar moddir[MAXPATHLEN], sysdir[MAXPATHLEN], windir[MAXPATHLEN]; int n;
wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
wwindir[MAXPATHLEN];
GetModuleFileName (NULL, moddir, sizeof (moddir)); n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
tmp = g_path_get_dirname (moddir); if (n > 0 && n < MAXPATHLEN)
GetSystemDirectory (sysdir, sizeof (sysdir)); filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
GetWindowsDirectory (windir, sizeof (windir));
path_tmp = g_strconcat (tmp, ";.;", sysdir, ";", windir, n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
(path != NULL ? ";" : NULL), if (n > 0 && n < MAXPATHLEN)
(path != NULL ? path : NULL), sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
NULL);
g_free (tmp); n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
path = path_tmp; 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);
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 #endif
len = strlen (program) + 1; len = strlen (program) + 1;
@ -394,7 +465,7 @@ g_find_program_in_path (const gchar *program)
ret = g_strdup (startp); ret = g_strdup (startp);
g_free (freeme); g_free (freeme);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_free (path_tmp); g_free ((gchar *) path_copy);
#endif #endif
return ret; return ret;
} }
@ -403,7 +474,7 @@ g_find_program_in_path (const gchar *program)
g_free (freeme); g_free (freeme);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_free (path_tmp); g_free ((gchar *) path_copy);
#endif #endif
return NULL; return NULL;
@ -801,82 +872,156 @@ g_get_current_dir (void)
#endif /* !Win32 */ #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: * 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 * Return value: the value of the environment variable, or %NULL if
* variable is not found. The returned string may be overwritten by the next call to g_getenv(), * the environment variable is not found. The returned string may be
* g_setenv() or g_unsetenv(). * overwritten by the next call to g_getenv(), g_setenv() or
* g_unsetenv().
**/ **/
G_CONST_RETURN gchar* G_CONST_RETURN gchar*
g_getenv (const gchar *variable) g_getenv (const gchar *variable)
{ {
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
g_return_val_if_fail (variable != NULL, NULL); g_return_val_if_fail (variable != NULL, NULL);
return getenv (variable); return getenv (variable);
#else
#else /* G_OS_WIN32 */
GQuark quark; GQuark quark;
gchar *system_env; gchar *value;
gchar *expanded_env;
guint length;
gchar dummy[2];
g_return_val_if_fail (variable != NULL, NULL); g_return_val_if_fail (variable != NULL, NULL);
g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
system_env = getenv (variable);
if (!system_env)
return NULL;
/* On Windows NT, it is relatively typical that environment /* On Windows NT, it is relatively typical that environment
* variables contain references to other environment variables. If * variables contain references to other environment variables. If
* so, use ExpandEnvironmentStrings(). (If all software was written * so, use ExpandEnvironmentStrings(). (In an ideal world, such
* in the best possible way, such environment variables would be * environment variables would be stored in the Registry as
* stored in the Registry as REG_EXPAND_SZ type values, and would * REG_EXPAND_SZ type values, and would then get automatically
* then get automatically expanded before the program sees them. But * expanded before a program sees them. But there is broken software
* there is broken software that stores environment variables as * that stores environment variables as REG_SZ values even if they
* REG_SZ values even if they contain references to other * contain references to other environment variables.)
* environment variables.
*/ */
if (strchr (system_env, '%') == NULL) if (G_WIN32_HAVE_WIDECHAR_API ())
{ {
/* No reference to other variable(s), return value as such. */ wchar_t dummy[2], *wname, *wvalue;
return system_env; 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 */ quark = g_quark_from_string (value);
length = ExpandEnvironmentStrings (system_env, dummy, 2); g_free (value);
expanded_env = g_malloc (length);
ExpandEnvironmentStrings (system_env, expanded_env, length);
quark = g_quark_from_string (expanded_env);
g_free (expanded_env);
return g_quark_to_string (quark); 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. * @value: the value for to set the variable to.
* @overwrite: whether to change the variable if it already exists. * @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 * Note that on some systems, the memory used for the variable and its value
* can't be reclaimed later. * can't be reclaimed later.
@ -899,17 +1047,20 @@ g_setenv (const gchar *variable,
const gchar *value, const gchar *value,
gboolean overwrite) gboolean overwrite)
{ {
#ifndef G_OS_WIN32
gint result; gint result;
#ifndef HAVE_SETENV #ifndef HAVE_SETENV
gchar *string; gchar *string;
#endif #endif
g_return_val_if_fail (variable != NULL, FALSE);
g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE); g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
#ifdef HAVE_SETENV #ifdef HAVE_SETENV
result = setenv (variable, value, overwrite); result = setenv (variable, value, overwrite);
#else #else
if (!overwrite && g_getenv (variable) != NULL) if (!overwrite && getenv (variable) != NULL)
return TRUE; return TRUE;
/* This results in a leak when you overwrite existing /* This results in a leak when you overwrite existing
@ -920,19 +1071,76 @@ g_setenv (const gchar *variable,
result = putenv (string); result = putenv (string);
#endif #endif
return result == 0; 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 #ifndef HAVE_UNSETENV
/* According to the Single Unix Specification, environ is not in /* According to the Single Unix Specification, environ is not in
* any system header, although unistd.h often declares it. * 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; extern char **environ;
# endif #endif
#endif #endif
/** /**
@ -950,14 +1158,18 @@ extern char **environ;
void void
g_unsetenv (const gchar *variable) g_unsetenv (const gchar *variable)
{ {
#ifndef G_OS_WIN32
#ifdef HAVE_UNSETENV #ifdef HAVE_UNSETENV
g_return_if_fail (variable != NULL);
g_return_if_fail (strchr (variable, '=') == NULL); g_return_if_fail (strchr (variable, '=') == NULL);
unsetenv (variable); unsetenv (variable);
#else #else /* !HAVE_UNSETENV */
int len; int len;
gchar **e, **f; gchar **e, **f;
g_return_if_fail (variable != NULL);
g_return_if_fail (strchr (variable, '=') == NULL); g_return_if_fail (strchr (variable, '=') == NULL);
len = strlen (variable); len = strlen (variable);
@ -979,7 +1191,44 @@ g_unsetenv (const gchar *variable)
e++; e++;
} }
*f = NULL; *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); G_LOCK_DEFINE_STATIC (g_utils_global);
@ -1047,13 +1296,6 @@ g_get_any_init (void)
{ {
if (!g_tmp_dir) 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")); g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
if (!g_tmp_dir) if (!g_tmp_dir)
g_tmp_dir = g_strdup (g_getenv ("TMP")); g_tmp_dir = g_strdup (g_getenv ("TMP"));
@ -1076,7 +1318,7 @@ g_get_any_init (void)
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
g_tmp_dir = g_strdup ("/tmp"); g_tmp_dir = g_strdup ("/tmp");
#else /* G_OS_WIN32 */ #else /* G_OS_WIN32 */
g_tmp_dir = g_strdup ("C:\\"); g_tmp_dir = g_strdup ("\\");
#endif /* G_OS_WIN32 */ #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 /* We check $HOME first for Win32, though it is a last resort for Unix
* where we prefer the results of getpwuid(). * where we prefer the results of getpwuid().
*/ */
{ g_home_dir = g_strdup (g_getenv ("HOME"));
const gchar *home = g_getenv ("HOME");
gchar *home_utf8 = NULL;
if (home) /* Only believe HOME if it is an absolute path and exists */
home_utf8 = g_locale_to_utf8 (home, -1, NULL, NULL, NULL); if (g_home_dir)
{
/* Only believe HOME if it is an absolute path and exists */ if (!(g_path_is_absolute (g_home_dir) &&
if (home_utf8) g_file_test (g_home_dir, G_FILE_TEST_IS_DIR)))
{ {
if (g_path_is_absolute (home_utf8) && g_free (g_home_dir);
g_file_test (home_utf8, G_FILE_TEST_IS_DIR)) g_home_dir = NULL;
g_home_dir = home_utf8; }
else }
g_free (home_utf8);
}
}
/* In case HOME is Unix-style (it happens), convert it to /* In case HOME is Unix-style (it happens), convert it to
* Windows style. * Windows style.
@ -1115,9 +1352,8 @@ g_get_any_init (void)
if (!g_home_dir) if (!g_home_dir)
{ {
/* USERPROFILE is probably the closest equivalent to $HOME? */ /* USERPROFILE is probably the closest equivalent to $HOME? */
if (getenv ("USERPROFILE") != NULL) if (g_getenv ("USERPROFILE") != NULL)
g_home_dir = g_locale_to_utf8 (g_getenv ("USERPROFILE"), g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
-1, NULL, NULL, NULL);
} }
if (!g_home_dir) if (!g_home_dir)
@ -1130,18 +1366,10 @@ g_get_any_init (void)
* 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
* HOMEPATH is its root "\"? * HOMEPATH is its root "\"?
*/ */
if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL) if (g_getenv ("HOMEDRIVE") != NULL && g_getenv ("HOMEPATH") != NULL)
{ g_home_dir = g_strconcat (g_getenv ("HOMEDRIVE"),
gchar *homedrive, *homepath; g_getenv ("HOMEPATH"),
NULL);
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);
}
} }
#endif /* G_OS_WIN32 */ #endif /* G_OS_WIN32 */
@ -1286,13 +1514,17 @@ g_get_any_init (void)
g_real_name = g_strdup ("Unknown"); g_real_name = g_strdup ("Unknown");
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_tmp_dir_cp = g_tmp_dir; g_tmp_dir_cp = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL);
g_tmp_dir = g_locale_to_utf8 (g_tmp_dir_cp, -1, NULL, NULL, NULL);
g_user_name_cp = g_locale_from_utf8 (g_user_name, -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); 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 /* home_dir might be NULL, unlike tmp_dir, user_name and
* real_name. * real_name.
*/ */
@ -1315,25 +1547,6 @@ g_get_user_name (void)
return g_user_name; 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_CONST_RETURN gchar*
g_get_real_name (void) g_get_real_name (void)
{ {
@ -1345,25 +1558,6 @@ g_get_real_name (void)
return g_real_name; 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_CONST_RETURN gchar*
g_get_home_dir (void) g_get_home_dir (void)
{ {
@ -1375,25 +1569,6 @@ g_get_home_dir (void)
return g_home_dir; 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 /* Return a directory to be used to store temporary files. This is the
* value of the TMPDIR, TMP or TEMP environment variables (they are * value of the TMPDIR, TMP or TEMP environment variables (they are
* checked in that order). If none of those exist, use P_tmpdir from * 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; 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); G_LOCK_DEFINE_STATIC (g_prgname);
static gchar *g_prgname = NULL; static gchar *g_prgname = NULL;
@ -2189,3 +2345,135 @@ _glib_gettext (const gchar *str)
} }
#endif /* ENABLE_NLS */ #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

View File

@ -192,6 +192,13 @@ void g_nullify_pointer (gpointer *nullify_location);
/* return the environment string for the variable. The returned memory /* return the environment string for the variable. The returned memory
* must not be freed. */ * 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); G_CONST_RETURN gchar* g_getenv (const gchar *variable);
gboolean g_setenv (const gchar *variable, gboolean g_setenv (const gchar *variable,
const gchar *value, const gchar *value,