From 5d48d565e3fc10a29091e66991b6bed85577f0e7 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Tue, 4 Feb 2003 23:37:04 +0000 Subject: [PATCH] Fix typo: Should be SOCKET_ERROR, not SO_ERROR. Noticed by Daniel 2003-02-04 Tor Lillqvist * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. Merge from stable branch: Fix for bug #104014, reported by Alex Shaduri: * glib/gspawn-win32.c (protect_argv): New function. Add double-quotes around argv elements that need it, and escape embedded double-quotes with backslash. (do_spawn_with_pipes) Call protect_argv(). * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). * glib/gspawn.c (g_spawn_async_with_pipes): Document argument vector vs. command line details on Win32. (g_spawn_command_line_sync): Improve documentation about backslashes in the command line on Windows. --- ChangeLog | 21 +++++++++++ ChangeLog.pre-2-10 | 21 +++++++++++ ChangeLog.pre-2-12 | 21 +++++++++++ ChangeLog.pre-2-4 | 21 +++++++++++ ChangeLog.pre-2-6 | 21 +++++++++++ ChangeLog.pre-2-8 | 21 +++++++++++ glib/giowin32.c | 2 +- glib/gspawn-win32-helper.c | 18 ++++++---- glib/gspawn-win32.c | 89 +++++++++++++++++++++++++++++++++++++++++++++- glib/gspawn.c | 28 ++++++++++++--- 10 files changed, 250 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bb5f78..62f9bd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2003-02-04 Tor Lillqvist + + * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be + SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. + + Merge from stable branch: + + Fix for bug #104014, reported by Alex Shaduri: + + * glib/gspawn-win32.c (protect_argv): New function. Add + double-quotes around argv elements that need it, and escape + embedded double-quotes with backslash. + (do_spawn_with_pipes) Call protect_argv(). + + * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). + + * glib/gspawn.c (g_spawn_async_with_pipes): Document argument + vector vs. command line details on Win32. + (g_spawn_command_line_sync): Improve documentation about + backslashes in the command line on Windows. + Thu Jan 30 16:45:13 2003 Owen Taylor * Makefile.am: Remove references to glib.spec. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 4bb5f78..62f9bd0 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,24 @@ +2003-02-04 Tor Lillqvist + + * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be + SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. + + Merge from stable branch: + + Fix for bug #104014, reported by Alex Shaduri: + + * glib/gspawn-win32.c (protect_argv): New function. Add + double-quotes around argv elements that need it, and escape + embedded double-quotes with backslash. + (do_spawn_with_pipes) Call protect_argv(). + + * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). + + * glib/gspawn.c (g_spawn_async_with_pipes): Document argument + vector vs. command line details on Win32. + (g_spawn_command_line_sync): Improve documentation about + backslashes in the command line on Windows. + Thu Jan 30 16:45:13 2003 Owen Taylor * Makefile.am: Remove references to glib.spec. diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 4bb5f78..62f9bd0 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,24 @@ +2003-02-04 Tor Lillqvist + + * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be + SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. + + Merge from stable branch: + + Fix for bug #104014, reported by Alex Shaduri: + + * glib/gspawn-win32.c (protect_argv): New function. Add + double-quotes around argv elements that need it, and escape + embedded double-quotes with backslash. + (do_spawn_with_pipes) Call protect_argv(). + + * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). + + * glib/gspawn.c (g_spawn_async_with_pipes): Document argument + vector vs. command line details on Win32. + (g_spawn_command_line_sync): Improve documentation about + backslashes in the command line on Windows. + Thu Jan 30 16:45:13 2003 Owen Taylor * Makefile.am: Remove references to glib.spec. diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 4bb5f78..62f9bd0 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,24 @@ +2003-02-04 Tor Lillqvist + + * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be + SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. + + Merge from stable branch: + + Fix for bug #104014, reported by Alex Shaduri: + + * glib/gspawn-win32.c (protect_argv): New function. Add + double-quotes around argv elements that need it, and escape + embedded double-quotes with backslash. + (do_spawn_with_pipes) Call protect_argv(). + + * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). + + * glib/gspawn.c (g_spawn_async_with_pipes): Document argument + vector vs. command line details on Win32. + (g_spawn_command_line_sync): Improve documentation about + backslashes in the command line on Windows. + Thu Jan 30 16:45:13 2003 Owen Taylor * Makefile.am: Remove references to glib.spec. diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 4bb5f78..62f9bd0 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,24 @@ +2003-02-04 Tor Lillqvist + + * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be + SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. + + Merge from stable branch: + + Fix for bug #104014, reported by Alex Shaduri: + + * glib/gspawn-win32.c (protect_argv): New function. Add + double-quotes around argv elements that need it, and escape + embedded double-quotes with backslash. + (do_spawn_with_pipes) Call protect_argv(). + + * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). + + * glib/gspawn.c (g_spawn_async_with_pipes): Document argument + vector vs. command line details on Win32. + (g_spawn_command_line_sync): Improve documentation about + backslashes in the command line on Windows. + Thu Jan 30 16:45:13 2003 Owen Taylor * Makefile.am: Remove references to glib.spec. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 4bb5f78..62f9bd0 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,24 @@ +2003-02-04 Tor Lillqvist + + * glib/giowin32.c (g_io_channel_unix_new): Fix typo: Should be + SOCKET_ERROR, not SO_ERROR. Noticed by Daniel Kaufmann. + + Merge from stable branch: + + Fix for bug #104014, reported by Alex Shaduri: + + * glib/gspawn-win32.c (protect_argv): New function. Add + double-quotes around argv elements that need it, and escape + embedded double-quotes with backslash. + (do_spawn_with_pipes) Call protect_argv(). + + * glib/gspawn-win32-helper.c (WinMain): Call protect_argv(). + + * glib/gspawn.c (g_spawn_async_with_pipes): Document argument + vector vs. command line details on Win32. + (g_spawn_command_line_sync): Improve documentation about + backslashes in the command line on Windows. + Thu Jan 30 16:45:13 2003 Owen Taylor * Makefile.am: Remove references to glib.spec. diff --git a/glib/giowin32.c b/glib/giowin32.c index fdf5be5..a7277b7 100644 --- a/glib/giowin32.c +++ b/glib/giowin32.c @@ -1494,7 +1494,7 @@ g_io_channel_unix_new (gint fd) if (fstat (fd, &st) == 0) return g_io_channel_win32_new_fd_internal (fd, &st); - if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR) + if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SOCKET_ERROR) return g_io_channel_win32_new_socket(fd); g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd); diff --git a/glib/gspawn-win32-helper.c b/glib/gspawn-win32-helper.c index 18a398e..9f9af68 100644 --- a/glib/gspawn-win32-helper.c +++ b/glib/gspawn-win32-helper.c @@ -76,6 +76,7 @@ WinMain (struct HINSTANCE__ *hInstance, int handle; int no_error = CHILD_NO_ERROR; int zero = 0; + gchar **new_argv; SETUP_DEBUG(); @@ -204,6 +205,11 @@ WinMain (struct HINSTANCE__ *hInstance, * __argv[ARG_PROGRAM+1]... is its __argv. */ + protect_argv (__argv, &new_argv); + + /* For the program name passed to spawnv(), don't use the quoted + * version. */ + if (debug) { debugstring = g_string_new (""); @@ -215,19 +221,19 @@ WinMain (struct HINSTANCE__ *hInstance, (mode == P_WAIT ? "P_WAIT" : "P_NOWAIT"))); i = ARG_PROGRAM+1; - while (__argv[i]) + while (new_argv[i]) { - g_string_append (debugstring, __argv[i++]); - if (__argv[i]) + g_string_append (debugstring, new_argv[i++]); + if (new_argv[i]) g_string_append (debugstring, " "); } MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0); } - if (__argv[ARG_USE_PATH][0] == 'y') - handle = spawnvp (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM); + if (new_argv[ARG_USE_PATH][0] == 'y') + handle = spawnvp (mode, __argv[ARG_PROGRAM], new_argv+ARG_PROGRAM); else - handle = spawnv (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM); + handle = spawnv (mode, __argv[ARG_PROGRAM], new_argv+ARG_PROGRAM); if (debug) { diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c index fc5cb43..66cfe53 100644 --- a/glib/gspawn-win32.c +++ b/glib/gspawn-win32.c @@ -97,6 +97,84 @@ enum { ARG_COUNT = ARG_PROGRAM }; +static gint +protect_argv (gchar **argv, + gchar ***new_argv) +{ + gint i; + gint argc = 0; + + while (argv[argc]) + ++argc; + *new_argv = g_new (gchar *, argc+1); + + /* Quote each argv element if necessary, so that it will get + * reconstructed correctly in the C runtime startup code. Note that + * the unquoting algorithm in the C runtime is really weird, and + * rather different than what Unix shells do. See stdargv.c in the C + * runtime sources (in the Platform SDK, in src/crt). + * + * Note that an new_argv[0] constructed by this function should + * *not* be passed as the filename argument to a spawn* or exec* + * family function. That argument should be the real file name + * without any quoting. + */ + for (i = 0; i < argc; i++) + { + gchar *p = argv[i]; + gchar *q; + gint len = 0; + gboolean need_dblquotes = FALSE; + while (*p) + { + if (*p == ' ' || *p == '\t') + need_dblquotes = TRUE; + else if (*p == '"') + len++; + else if (*p == '\\') + { + gchar *pp = p; + while (*pp && *pp == '\\') + pp++; + if (*pp == '"') + len++; + } + len++; + p++; + } + + q = (*new_argv)[i] = g_malloc (len + need_dblquotes*2 + 1); + p = argv[i]; + + if (need_dblquotes) + *q++ = '"'; + + while (*p) + { + if (*p == '"') + *q++ = '\\'; + else if (*p == '\\') + { + gchar *pp = p; + while (*pp && *pp == '\\') + pp++; + if (*pp == '"') + *q++ = '\\'; + } + *q++ = *p; + p++; + } + + if (need_dblquotes) + *q++ = '"'; + *q++ = '\0'; + /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */ + } + (*new_argv)[argc] = NULL; + + return argc; +} + #ifndef GSPAWN_HELPER static gboolean make_pipe (gint p[2], @@ -746,6 +824,9 @@ do_spawn_with_pipes (gboolean dont_wait, gint helper = -1; gint buf[2]; gint n_ints = 0; + gint i; + gint argc; + gchar **new_argv; if (!make_pipe (child_err_report_pipe, error)) return FALSE; @@ -759,13 +840,15 @@ do_spawn_with_pipes (gboolean dont_wait, if (standard_error && !make_pipe (stderr_pipe, error)) goto cleanup_and_fail; + argc = protect_argv (argv, &new_argv); + helper = do_spawn (dont_wait, child_err_report_pipe[1], stdin_pipe[0], stdout_pipe[1], stderr_pipe[1], working_directory, - argv, + new_argv, envp, close_descriptors, search_path, @@ -775,6 +858,10 @@ do_spawn_with_pipes (gboolean dont_wait, child_setup, user_data); + for (i = 0; i < argc; i++) + g_free (new_argv[i]); + g_free (new_argv); + /* do_spawn() returns -1 if gspawn-win32-helper couldn't be run */ if (helper == -1) { diff --git a/glib/gspawn.c b/glib/gspawn.c index 165d995..be31eed 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -432,6 +432,24 @@ g_spawn_sync (const gchar *working_directory, * the program must be a full path; the PATH shell variable * will only be searched if you pass the %G_SPAWN_SEARCH_PATH flag. * + * On Windows, the low-level child process creation API + * (CreateProcess())doesn't use argument vectors, + * but a command line. The C runtime library's + * spawn*() family of functions (which + * g_spawn_async_with_pipes() eventually calls) paste the argument + * vector elements into a command line, and the C runtime startup code + * does a corresponding recostruction of an argument vector from the + * command line, to be passed to + * main(). Complications arise when you have + * argument vector elements that contain spaces of double quotes. The + * spawn() functions don't do any quoting or + * escaping, but on the other hand the startup code does do unquoting + * and unescaping in order to enable receiving arguments with embedded + * spaces or double quotes. To work around this asymmetry, + * g_spawn_async_with_pipes() will do quoting and escaping on argument + * vector elements that need it before calling the C runtime + * spawn() function. + * * @envp is a %NULL-terminated array of strings, where each string * has the form KEY=VALUE. This will become * the child's environment. If @envp is %NULL, the child inherits its @@ -584,11 +602,11 @@ g_spawn_async_with_pipes (const gchar *working_directory, * * On Windows, please note the implications of g_shell_parse_argv() * parsing @command_line. Space is a separator, and backslashes are - * special. Thus you cannot simply pass a @command_line consisting of - * a canonical Windows path, like "c:\\program files\\app\\app.exe", - * as the backslashes will be eaten, and the space will act as a - * separator. You need to enclose the path with single quotes, like - * "'c:\\program files\\app\\app.exe'". + * special. Thus you cannot simply pass a @command_line containing + * canonical Windows paths, like "c:\\program files\\app\\app.exe", as + * the backslashes will be eaten, and the space will act as a + * separator. You need to enclose such paths with single quotes, like + * "'c:\\program files\\app\\app.exe' 'e:\\folder\\argument.txt'". * * Return value: %TRUE on success, %FALSE if an error was set **/ -- 2.7.4