Branch: refs/heads/master
Author: Dimitar Zhekov <dimitar.zhekov(a)gmail.com>
Committer: Dimitar Zhekov <dimitar.zhekov(a)gmail.com>
Date: Wed, 01 Apr 2015 18:16:23 UTC
Commit: 8745ba58ae8e5582de7b3c828ac1eefa4e62e134
https://github.com/geany/geany/commit/8745ba58ae8e5582de7b3c828ac1eefa4e62e…
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).
Branch: refs/heads/master
Author: Dimitar Zhekov <dimitar.zhekov(a)gmail.com>
Committer: Dimitar Zhekov <dimitar.zhekov(a)gmail.com>
Date: Sun, 29 Mar 2015 10:51:07 UTC
Commit: 7bebf64f3da1fa3ae72e56c6ee4a9039701c8be5
https://github.com/geany/geany/commit/7bebf64f3da1fa3ae72e56c6ee4a9039701c8…
Log Message:
-----------
Fix SPAWN_UNBUFFERED description
Modified Paths:
--------------
src/spawn.h
Modified: src/spawn.h
4 lines changed, 1 insertions(+), 3 deletions(-)
===================================================================
@@ -44,7 +44,7 @@ typedef enum
SPAWN_LINE_BUFFERED = 0x00, /**< stdout/stderr are line buffered [default]. */
SPAWN_STDOUT_UNBUFFERED = 0x02, /**< stdout is not buffered. */
SPAWN_STDERR_UNBUFFERED = 0x04, /**< stderr is not buffered. */
- SPAWN_UNBUFFERED = 0x06, /**< stdout/stderr are line buffered. */
+ SPAWN_UNBUFFERED = 0x06, /**< stdout/stderr are not buffered. */
/* recursive modes */
SPAWN_STDIN_RECURSIVE = 0x08, /**< The stdin callback is recursive. */
SPAWN_STDOUT_RECURSIVE = 0x10, /**< The stdout callback is recursive. */
@@ -63,8 +63,6 @@ typedef enum
*
* If @c G_IO_IN or @c G_IO_PRI are set, the @a string will contain at least one character.
*
- * The callback function may modify the @a string, but must not free it.
- *
* @param string contains the child data if @c G_IO_IN or @c G_IO_PRI are set.
* @param condition the I/O condition which has been satisfied.
* @param data the passed to @c spawn_with_callbacks() with the callback.
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
Branch: refs/heads/master
Author: Dimitar Zhekov <dimitar.zhekov(a)gmail.com>
Committer: Dimitar Zhekov <dimitar.zhekov(a)gmail.com>
Date: Mon, 23 Mar 2015 18:02:43 UTC
Commit: a3af98cfc99884c8040f1de0b5fa8d3f57421ddb
https://github.com/geany/geany/commit/a3af98cfc99884c8040f1de0b5fa8d3f57421…
Log Message:
-----------
Altered keyfile.c to use the new spawning module
In particular, changed the default printcmd not to "single quote paths
on Win32 for g_spawn_command_line_async", but use the native double
quotes. Also fixed it not to g_strconcat(NULL, ...) if lpr is missing
under Unix. It works, but glib says the first string must not be NULL,
and the command becomes wrong anyway.
Modified Paths:
--------------
src/keyfile.c
Modified: src/keyfile.c
13 lines changed, 7 insertions(+), 6 deletions(-)
===================================================================
@@ -941,19 +941,20 @@ static void load_dialog_prefs(GKeyFile *config)
/* printing */
tmp_string2 = g_find_program_in_path(GEANY_DEFAULT_TOOLS_PRINTCMD);
-#ifdef G_OS_WIN32
+
if (!EMPTY(tmp_string2))
{
- /* single quote paths on Win32 for g_spawn_command_line_async */
- tmp_string = g_strconcat("'", tmp_string2, "' '%f'", NULL);
+ #ifdef G_OS_WIN32
+ tmp_string = g_strconcat(GEANY_DEFAULT_TOOLS_PRINTCMD, " \"%f\"", NULL);
+ #else
+ tmp_string = g_strconcat(GEANY_DEFAULT_TOOLS_PRINTCMD, " %f", NULL);
+ #endif
}
else
{
tmp_string = g_strdup("");
}
-#else
- tmp_string = g_strconcat(tmp_string2, " %f", NULL);
-#endif
+
printing_prefs.external_print_cmd = utils_get_setting_string(config, "printing", "print_cmd", tmp_string);
g_free(tmp_string);
g_free(tmp_string2);
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).