[geany/geany] 8745ba: Fix Windows attempts to run 2+ unquoted tokens as a program
Dimitar Zhekov
git-noreply at xxxxx
Fri May 15 17:07:39 UTC 2015
Branch: refs/heads/master
Author: Dimitar Zhekov <dimitar.zhekov at gmail.com>
Committer: Dimitar Zhekov <dimitar.zhekov at gmail.com>
Date: Wed, 01 Apr 2015 18:16:23 UTC
Commit: 8745ba58ae8e5582de7b3c828ac1eefa4e62e134
https://github.com/geany/geany/commit/8745ba58ae8e5582de7b3c828ac1eefa4e62e134
Log Message:
-----------
Fix Windows attempts to run 2+ unquoted tokens as a program
When passed Foo Bar Qux as a command line, Windows will try to run
Foo.exe Bar Qux, then "Foo Bar.exe" Qux, and last "Foo Bar Qux.exe",
for maximum flexibility. Quoting Foo supresses this behaviour.
Modified Paths:
--------------
src/spawn.c
src/spawn.h
Modified: src/spawn.c
79 lines changed, 62 insertions(+), 17 deletions(-)
===================================================================
@@ -75,7 +75,7 @@
/**
- * Checks whether a command line is valid.
+ * Checks whether a command line is syntactically valid and extracts the program name from it.
*
* All OS:
* - any leading spaces and tabs are ignored
@@ -84,20 +84,20 @@
* - the standard shell quoting and escaping rules are used, see @c g_shell_parse_argv()
* - as a consequence, an unqouted # at the start of an argument comments to the end of line
* Windows:
- * - a quoted program name must be entirely inside the quotes. It's hard to believe, but
- * "C:\Foo\Bar".pdf is actually executed as "C:\Foo\Bar.exe", and .pdf is completely
- * ignored, not even passed as an argument
- * - the standard Windows quoting rules are used: double quote is escaped with slash, and
- * any literal slashes before a double quote must be duplicated.
+ * - a quoted program name must be entirely inside the quotes. No "C:\Foo\Bar".pdf or
+ * "C:\Foo\Bar".bat, which would be executed by Windows as C:\Foo\Bar.exe
+ * - an unquoted program name may not contain spaces. Foo Bar Qux will not be considered
+ * "Foo Bar.exe" Qux or "Foo Bar Qux.exe", depending on what executables exist, as
+ * Windows normally does.
+ * - the standard Windows quoting and escaping rules are used: double quote is escaped with
+ * backslash, and any literal backslashes before a double quote must be duplicated.
*
- * @param command_line the command line to check.
- * @param execute whether to check, using @c g_find_program_in_path(), if the program specified
- * in the command line exists and is executable.
+ * @param command_line the command line to check and get the program name from.
* @param error return location for error.
*
- * @return @c TRUE on success, @c FALSE if an error was set.
+ * @return allocated string with the program name on success, @c NULL on error.
**/
-gboolean spawn_check_command(const gchar *command_line, gboolean execute, GError **error)
+gchar *spawn_get_program_name(const gchar *command_line, GError **error)
{
gchar *program;
@@ -189,6 +189,31 @@ gboolean spawn_check_command(const gchar *command_line, gboolean execute, GError
g_strfreev(argv);
#endif /* G_OS_WIN32 */
+ return program;
+}
+
+
+/**
+ * Checks whether a command line is valid.
+ *
+ * Checks if @a command_line is syntactically valid using @c spawn_get_program_name().
+ *
+ * If @a execute is TRUE, also checks, using @c g_find_program_in_path(), if the program
+ * specified in @a command_line exists and is executable.
+ *
+ * @param command_line the command line to check.
+ * @param execute whether to check if the command line is really executable.
+ * @param error return location for error.
+ *
+ * @return @c TRUE on success, @c FALSE on error.
+ */
+gboolean spawn_check_command(const gchar *command_line, gboolean execute, GError **error)
+{
+ gchar *program = spawn_get_program_name(command_line, error);
+
+ if (!program)
+ return FALSE;
+
if (execute)
{
gchar *executable = g_find_program_in_path(program);
@@ -445,20 +470,40 @@ gboolean spawn_async_with_pipes(const gchar *working_directory, const gchar *com
#ifdef G_OS_WIN32
GString *command;
- GArray *environment = g_array_new(TRUE, FALSE, sizeof(char));
+ GArray *environment;
GPid pid;
gchar *failure;
if (command_line)
{
- if (!spawn_check_command(command_line, FALSE, error))
+ gchar *program = spawn_get_program_name(command_line, error);
+ const gchar *arguments;
+
+ if (!program)
return FALSE;
- /* checked command line contains at least 1 non-blank */
- while (strchr(CL_BLANKS, *command_line))
- command_line++;
+
+ command = g_string_new(NULL);
+ arguments = strstr(command_line, program) + strlen(program);
+
+ if (*arguments == '"')
+ {
+ g_string_append(command, program);
+ arguments++;
+ }
+ else
+ {
+ /* quote the first token, to avoid Windows attemps to run two or more
+ unquoted tokens as a program until an existing file name is found */
+ g_string_printf(command, "\"%s\"", program);
+ }
+
+ g_string_append(command, arguments);
+ g_free(program);
}
+ else
+ command = g_string_new(NULL);
- command = g_string_new(command_line);
+ environment = g_array_new(TRUE, FALSE, sizeof(char));
while (argv && *argv)
spawn_append_argument(command, *argv++);
Modified: src/spawn.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -24,6 +24,8 @@
#include <glib.h>
+gchar *spawn_get_program_name(const gchar *command_line, GError **error);
+
gboolean spawn_check_command(const gchar *command_line, gboolean execute, GError **error);
gboolean spawn_kill_process(GPid pid, GError **error);
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list