+2003-02-04 Tor Lillqvist <tml@iki.fi>
+
+ * 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 <otaylor@redhat.com>
* Makefile.am: Remove references to glib.spec.
+2003-02-04 Tor Lillqvist <tml@iki.fi>
+
+ * 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 <otaylor@redhat.com>
* Makefile.am: Remove references to glib.spec.
+2003-02-04 Tor Lillqvist <tml@iki.fi>
+
+ * 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 <otaylor@redhat.com>
* Makefile.am: Remove references to glib.spec.
+2003-02-04 Tor Lillqvist <tml@iki.fi>
+
+ * 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 <otaylor@redhat.com>
* Makefile.am: Remove references to glib.spec.
+2003-02-04 Tor Lillqvist <tml@iki.fi>
+
+ * 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 <otaylor@redhat.com>
* Makefile.am: Remove references to glib.spec.
+2003-02-04 Tor Lillqvist <tml@iki.fi>
+
+ * 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 <otaylor@redhat.com>
* Makefile.am: Remove references to glib.spec.
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);
int handle;
int no_error = CHILD_NO_ERROR;
int zero = 0;
+ gchar **new_argv;
SETUP_DEBUG();
* __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 ("");
(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)
{
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],
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;
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,
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)
{
* the program must be a full path; the <envar>PATH</envar> shell variable
* will only be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
*
+ * On Windows, the low-level child process creation API
+ * (<function>CreateProcess()</function>)doesn't use argument vectors,
+ * but a command line. The C runtime library's
+ * <function>spawn*()</function> 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
+ * <function>main()</function>. Complications arise when you have
+ * argument vector elements that contain spaces of double quotes. The
+ * <function>spawn()</function> 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
+ * <function>spawn()</function> function.
+ *
* @envp is a %NULL-terminated array of strings, where each string
* has the form <literal>KEY=VALUE</literal>. This will become
* the child's environment. If @envp is %NULL, the child inherits its
*
* 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
**/