Implement on Win32. Append the executable file name suffixes from PATHEXT
authorTor Lillqvist <tml@iki.fi>
Thu, 1 Mar 2001 10:25:12 +0000 (10:25 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Thu, 1 Mar 2001 10:25:12 +0000 (10:25 +0000)
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.

12 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gutils.c
gutils.c
testglib.c
tests/testglib.c

index b3dc4cb..66f914d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index b3dc4cb..66f914d 100644 (file)
@@ -3,12 +3,16 @@
        * gutils.c (g_path_is_absolute): (Win32) Remove test for initial
        double backslash (UNC path), this will of course be matched by the
        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
        indicating the home directory equivalent.
 
        * 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.
 
index 1c89877..be7feb6 100644 (file)
@@ -157,6 +157,52 @@ my_strchrnul (const gchar *str, gchar c)
   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:
  * @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
  * @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
  **/
 gchar*
@@ -180,13 +237,13 @@ g_find_program_in_path (const gchar *program)
   size_t len;
   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);
 
-  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))
         return g_strdup (program);
index 1c89877..be7feb6 100644 (file)
--- a/gutils.c
+++ b/gutils.c
@@ -157,6 +157,52 @@ my_strchrnul (const gchar *str, gchar c)
   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:
  * @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
  * @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
  **/
 gchar*
@@ -180,13 +237,13 @@ g_find_program_in_path (const gchar *program)
   size_t len;
   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);
 
-  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))
         return g_strdup (program);
index bdb7b09..1e1adf3 100644 (file)
@@ -1167,7 +1167,7 @@ main (int   argc,
           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 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
 
index bdb7b09..1e1adf3 100644 (file)
@@ -1167,7 +1167,7 @@ main (int   argc,
           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 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