Implement on Win32. Append the executable file name suffixes from PATHEXT

2001-03-01  Tor Lillqvist  <tml@iki.fi>

	* gutils.c(g_find_program_in_path): Implement on Win32. Append the
	executable file name suffixes from PATHEXT in turn while
	looking	for the program.
	(g_find_program_in_path): If the program we are looking for is a
	relative path in a subdirectory, don't do any path search.
This commit is contained in:
Tor Lillqvist 2001-03-01 10:25:12 +00:00 committed by Tor Lillqvist
parent b6ba941b50
commit 00988d0d76
12 changed files with 174 additions and 28 deletions

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -3,12 +3,16 @@
* gutils.c (g_path_is_absolute): (Win32) Remove test for initial * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
double backslash (UNC path), this will of course be matched by the double backslash (UNC path), this will of course be matched by the
test for an initial G_DIR_SEPARATOR right up front. Silly me. test for an initial G_DIR_SEPARATOR right up front. Silly me.
(g_find_program_in_path): Implement on Win32. (g_find_program_in_path): Implement on Win32. Append the
executable file name suffixes from PATHEXT in turn while looking
for the program.
(g_find_program_in_path): If the program we are looking for is a
relative path in a subdirectory, don't do any path search.
(g_get_any_init): (Win32) Also look for the USERPROFILE env var (g_get_any_init): (Win32) Also look for the USERPROFILE env var
indicating the home directory equivalent. indicating the home directory equivalent.
* testglib.c (main): Test g_find_program_in_path() on Win32 by * testglib.c (main): Test g_find_program_in_path() on Win32 by
looking for more.com and regedit.exe. looking for more.com and regedit.
* glib.def: Add g_find_program_in_path. * glib.def: Add g_find_program_in_path.

View File

@ -157,6 +157,52 @@ my_strchrnul (const gchar *str, gchar c)
return p; return p;
} }
#ifdef G_OS_WIN32
gchar *inner_find_program_in_path (const gchar *program);
gchar*
g_find_program_in_path (const gchar *program)
{
const gchar *last_dot = strrchr (program, '.');
if (last_dot == NULL || strchr (last_dot, '\\') != NULL)
{
const gint program_length = strlen (program);
const gchar *pathext = getenv ("PATHEXT");
const gchar *p;
gchar *decorated_program;
gchar *retval;
if (pathext == NULL)
pathext = ".com;.exe;.bat";
p = pathext;
do
{
pathext = p;
p = my_strchrnul (pathext, ';');
decorated_program = g_malloc (program_length + (p-pathext) + 1);
memcpy (decorated_program, program, program_length);
memcpy (decorated_program+program_length, pathext, p-pathext);
decorated_program [program_length + (p-pathext)] = '\0';
retval = inner_find_program_in_path (decorated_program);
g_free (decorated_program);
if (retval != NULL)
return retval;
} while (*p++ != '\0');
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: * g_find_program_in_path:
* @program: a program name * @program: a program name
@ -167,6 +213,17 @@ my_strchrnul (const gchar *str, gchar c)
* 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
* 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
* 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.
*
* Return value: absolute path, or NULL * Return value: absolute path, or NULL
**/ **/
gchar* gchar*
@ -180,13 +237,13 @@ g_find_program_in_path (const gchar *program)
size_t len; size_t len;
size_t pathlen; size_t pathlen;
/* On Win32, should we try appending .exe, .com, and the other
* components of %PATHEXT% ?
*/
g_return_val_if_fail (program != NULL, NULL); g_return_val_if_fail (program != NULL, NULL);
if (g_path_is_absolute (program)) /* If it is an absolute path, or a relative path including subdirectories,
* don't look in PATH.
*/
if (g_path_is_absolute (program)
|| strchr (program, G_DIR_SEPARATOR) != NULL)
{ {
if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE)) if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
return g_strdup (program); return g_strdup (program);

View File

@ -157,6 +157,52 @@ my_strchrnul (const gchar *str, gchar c)
return p; return p;
} }
#ifdef G_OS_WIN32
gchar *inner_find_program_in_path (const gchar *program);
gchar*
g_find_program_in_path (const gchar *program)
{
const gchar *last_dot = strrchr (program, '.');
if (last_dot == NULL || strchr (last_dot, '\\') != NULL)
{
const gint program_length = strlen (program);
const gchar *pathext = getenv ("PATHEXT");
const gchar *p;
gchar *decorated_program;
gchar *retval;
if (pathext == NULL)
pathext = ".com;.exe;.bat";
p = pathext;
do
{
pathext = p;
p = my_strchrnul (pathext, ';');
decorated_program = g_malloc (program_length + (p-pathext) + 1);
memcpy (decorated_program, program, program_length);
memcpy (decorated_program+program_length, pathext, p-pathext);
decorated_program [program_length + (p-pathext)] = '\0';
retval = inner_find_program_in_path (decorated_program);
g_free (decorated_program);
if (retval != NULL)
return retval;
} while (*p++ != '\0');
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: * g_find_program_in_path:
* @program: a program name * @program: a program name
@ -167,6 +213,17 @@ my_strchrnul (const gchar *str, gchar c)
* 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
* 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
* 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.
*
* Return value: absolute path, or NULL * Return value: absolute path, or NULL
**/ **/
gchar* gchar*
@ -180,13 +237,13 @@ g_find_program_in_path (const gchar *program)
size_t len; size_t len;
size_t pathlen; size_t pathlen;
/* On Win32, should we try appending .exe, .com, and the other
* components of %PATHEXT% ?
*/
g_return_val_if_fail (program != NULL, NULL); g_return_val_if_fail (program != NULL, NULL);
if (g_path_is_absolute (program)) /* If it is an absolute path, or a relative path including subdirectories,
* don't look in PATH.
*/
if (g_path_is_absolute (program)
|| strchr (program, G_DIR_SEPARATOR) != NULL)
{ {
if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE)) if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
return g_strdup (program); return g_strdup (program);

View File

@ -1167,7 +1167,7 @@ main (int argc,
g_win32_get_package_installation_directory ("gtk20", NULL)); g_win32_get_package_installation_directory ("gtk20", NULL));
g_print ("found more.com as %s\n", g_find_program_in_path ("more.com")); g_print ("found more.com as %s\n", g_find_program_in_path ("more.com"));
g_print ("found regedit.exe as %s\n", g_find_program_in_path ("regedit.exe")); g_print ("found regedit as %s\n", g_find_program_in_path ("regedit"));
#endif #endif

View File

@ -1167,7 +1167,7 @@ main (int argc,
g_win32_get_package_installation_directory ("gtk20", NULL)); g_win32_get_package_installation_directory ("gtk20", NULL));
g_print ("found more.com as %s\n", g_find_program_in_path ("more.com")); g_print ("found more.com as %s\n", g_find_program_in_path ("more.com"));
g_print ("found regedit.exe as %s\n", g_find_program_in_path ("regedit.exe")); g_print ("found regedit as %s\n", g_find_program_in_path ("regedit"));
#endif #endif