mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
Make also the g_spawn*() functions take parameters in the GLib file name
2005-08-25 Tor Lillqvist <tml@novell.com> Make also the g_spawn*() functions take parameters in the GLib file name encoding, i.e. UTF-8, on Windows. Has no impact on Unix API or ABI. Like the other GLib API that was earlier changed to use UTF-8 on Windows, the names of the functions that take UTF-8 have _utf8 suffixes added by using preprocessor macros in the header file. The old names are kept for functions with the old behaviour, taking parameters in the system codepage, for DLL ABI stability. * glib/gspawn.h: On Win32 add the suffix _utf8 to the names of the g_spawn*() functions. * glib/gspawn-win32.c: Use wide-char API on NT-based Windows. Convert parameters from UTF-8 to wide chars (NT) or system codepage (Win9x) and call the C library _wspawn*() or spawn*() functions respectvely. Add DLL ABI stability versions that take parameters in the system codepage. * glib/gspawn-win32-helper.c: On NT-based Windows use the wide-char versions of argv and envp, and use wide-char API to change directory and spawn the program to run. Remove the verbose debugging output, it was too complex to modify for the wide-char features. (Just add temporary debugging printouts if needed, no need to have them permanently in the source.) * glib/gspawn.c: Corresponding documentation updates. * glib/glib.symbols: Corresponding changes: Mark the ABI stability symbols as PRIVATE, add the new _utf8-suffixed ones.
This commit is contained in:
parent
2982892d98
commit
41e833ae4c
32
ChangeLog
32
ChangeLog
@ -1,3 +1,35 @@
|
|||||||
|
2005-08-25 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Make also the g_spawn*() functions take parameters in the GLib
|
||||||
|
file name encoding, i.e. UTF-8, on Windows. Has no impact on Unix
|
||||||
|
API or ABI. Like the other GLib API that was earlier changed to
|
||||||
|
use UTF-8 on Windows, the names of the functions that take UTF-8
|
||||||
|
have _utf8 suffixes added by using preprocessor macros in the
|
||||||
|
header file. The old names are kept for functions with the old
|
||||||
|
behaviour, taking parameters in the system codepage, for DLL ABI
|
||||||
|
stability.
|
||||||
|
|
||||||
|
* glib/gspawn.h: On Win32 add the suffix _utf8 to the names of the
|
||||||
|
g_spawn*() functions.
|
||||||
|
|
||||||
|
* glib/gspawn-win32.c: Use wide-char API on NT-based
|
||||||
|
Windows. Convert parameters from UTF-8 to wide chars (NT) or
|
||||||
|
system codepage (Win9x) and call the C library _wspawn*() or
|
||||||
|
spawn*() functions respectvely. Add DLL ABI stability versions
|
||||||
|
that take parameters in the system codepage.
|
||||||
|
|
||||||
|
* glib/gspawn-win32-helper.c: On NT-based Windows use the
|
||||||
|
wide-char versions of argv and envp, and use wide-char API to
|
||||||
|
change directory and spawn the program to run. Remove the verbose
|
||||||
|
debugging output, it was too complex to modify for the wide-char
|
||||||
|
features. (Just add temporary debugging printouts if needed, no
|
||||||
|
need to have them permanently in the source.)
|
||||||
|
|
||||||
|
* glib/gspawn.c: Corresponding documentation updates.
|
||||||
|
|
||||||
|
* glib/glib.symbols: Corresponding changes: Mark the ABI stability
|
||||||
|
symbols as PRIVATE, add the new _utf8-suffixed ones.
|
||||||
|
|
||||||
2005-08-24 Stepan Kasal <kasal@ucw.cz>
|
2005-08-24 Stepan Kasal <kasal@ucw.cz>
|
||||||
|
|
||||||
* glib/gtypes.h (G_MININT64): Cast the constant to gint64; it is
|
* glib/gtypes.h (G_MININT64): Cast the constant to gint64; it is
|
||||||
|
@ -1,3 +1,35 @@
|
|||||||
|
2005-08-25 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Make also the g_spawn*() functions take parameters in the GLib
|
||||||
|
file name encoding, i.e. UTF-8, on Windows. Has no impact on Unix
|
||||||
|
API or ABI. Like the other GLib API that was earlier changed to
|
||||||
|
use UTF-8 on Windows, the names of the functions that take UTF-8
|
||||||
|
have _utf8 suffixes added by using preprocessor macros in the
|
||||||
|
header file. The old names are kept for functions with the old
|
||||||
|
behaviour, taking parameters in the system codepage, for DLL ABI
|
||||||
|
stability.
|
||||||
|
|
||||||
|
* glib/gspawn.h: On Win32 add the suffix _utf8 to the names of the
|
||||||
|
g_spawn*() functions.
|
||||||
|
|
||||||
|
* glib/gspawn-win32.c: Use wide-char API on NT-based
|
||||||
|
Windows. Convert parameters from UTF-8 to wide chars (NT) or
|
||||||
|
system codepage (Win9x) and call the C library _wspawn*() or
|
||||||
|
spawn*() functions respectvely. Add DLL ABI stability versions
|
||||||
|
that take parameters in the system codepage.
|
||||||
|
|
||||||
|
* glib/gspawn-win32-helper.c: On NT-based Windows use the
|
||||||
|
wide-char versions of argv and envp, and use wide-char API to
|
||||||
|
change directory and spawn the program to run. Remove the verbose
|
||||||
|
debugging output, it was too complex to modify for the wide-char
|
||||||
|
features. (Just add temporary debugging printouts if needed, no
|
||||||
|
need to have them permanently in the source.)
|
||||||
|
|
||||||
|
* glib/gspawn.c: Corresponding documentation updates.
|
||||||
|
|
||||||
|
* glib/glib.symbols: Corresponding changes: Mark the ABI stability
|
||||||
|
symbols as PRIVATE, add the new _utf8-suffixed ones.
|
||||||
|
|
||||||
2005-08-24 Stepan Kasal <kasal@ucw.cz>
|
2005-08-24 Stepan Kasal <kasal@ucw.cz>
|
||||||
|
|
||||||
* glib/gtypes.h (G_MININT64): Cast the constant to gint64; it is
|
* glib/gtypes.h (G_MININT64): Cast the constant to gint64; it is
|
||||||
|
@ -1,3 +1,35 @@
|
|||||||
|
2005-08-25 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Make also the g_spawn*() functions take parameters in the GLib
|
||||||
|
file name encoding, i.e. UTF-8, on Windows. Has no impact on Unix
|
||||||
|
API or ABI. Like the other GLib API that was earlier changed to
|
||||||
|
use UTF-8 on Windows, the names of the functions that take UTF-8
|
||||||
|
have _utf8 suffixes added by using preprocessor macros in the
|
||||||
|
header file. The old names are kept for functions with the old
|
||||||
|
behaviour, taking parameters in the system codepage, for DLL ABI
|
||||||
|
stability.
|
||||||
|
|
||||||
|
* glib/gspawn.h: On Win32 add the suffix _utf8 to the names of the
|
||||||
|
g_spawn*() functions.
|
||||||
|
|
||||||
|
* glib/gspawn-win32.c: Use wide-char API on NT-based
|
||||||
|
Windows. Convert parameters from UTF-8 to wide chars (NT) or
|
||||||
|
system codepage (Win9x) and call the C library _wspawn*() or
|
||||||
|
spawn*() functions respectvely. Add DLL ABI stability versions
|
||||||
|
that take parameters in the system codepage.
|
||||||
|
|
||||||
|
* glib/gspawn-win32-helper.c: On NT-based Windows use the
|
||||||
|
wide-char versions of argv and envp, and use wide-char API to
|
||||||
|
change directory and spawn the program to run. Remove the verbose
|
||||||
|
debugging output, it was too complex to modify for the wide-char
|
||||||
|
features. (Just add temporary debugging printouts if needed, no
|
||||||
|
need to have them permanently in the source.)
|
||||||
|
|
||||||
|
* glib/gspawn.c: Corresponding documentation updates.
|
||||||
|
|
||||||
|
* glib/glib.symbols: Corresponding changes: Mark the ABI stability
|
||||||
|
symbols as PRIVATE, add the new _utf8-suffixed ones.
|
||||||
|
|
||||||
2005-08-24 Stepan Kasal <kasal@ucw.cz>
|
2005-08-24 Stepan Kasal <kasal@ucw.cz>
|
||||||
|
|
||||||
* glib/gtypes.h (G_MININT64): Cast the constant to gint64; it is
|
* glib/gtypes.h (G_MININT64): Cast the constant to gint64; it is
|
||||||
|
@ -851,13 +851,20 @@ g_slist_sort_with_data
|
|||||||
|
|
||||||
#if IN_HEADER(__G_SPAWN_H__)
|
#if IN_HEADER(__G_SPAWN_H__)
|
||||||
#if IN_FILE(__G_SPAWN_C__)
|
#if IN_FILE(__G_SPAWN_C__)
|
||||||
g_spawn_async
|
g_spawn_async PRIVATE
|
||||||
g_spawn_async_with_pipes
|
g_spawn_async_with_pipes PRIVATE
|
||||||
g_spawn_close_pid
|
g_spawn_close_pid
|
||||||
g_spawn_command_line_async
|
g_spawn_command_line_async PRIVATE
|
||||||
g_spawn_command_line_sync
|
g_spawn_command_line_sync PRIVATE
|
||||||
g_spawn_error_quark
|
g_spawn_error_quark
|
||||||
g_spawn_sync
|
g_spawn_sync PRIVATE
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
g_spawn_async_utf8
|
||||||
|
g_spawn_async_with_pipes_utf8
|
||||||
|
g_spawn_command_line_async_utf8
|
||||||
|
g_spawn_command_line_sync_utf8
|
||||||
|
g_spawn_sync_utf8
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -27,23 +27,12 @@
|
|||||||
#include "gspawn-win32.c" /* For shared definitions */
|
#include "gspawn-win32.c" /* For shared definitions */
|
||||||
|
|
||||||
|
|
||||||
static GString *debugstring;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_err_and_exit (gint fd,
|
write_err_and_exit (gint fd,
|
||||||
gint msg)
|
gint msg)
|
||||||
{
|
{
|
||||||
gint en = errno;
|
gint en = errno;
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
debugstring = g_string_new (NULL);
|
|
||||||
g_string_append (debugstring,
|
|
||||||
g_strdup_printf ("writing error code %d and errno %d",
|
|
||||||
msg, en));
|
|
||||||
MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
write (fd, &msg, sizeof(msg));
|
write (fd, &msg, sizeof(msg));
|
||||||
write (fd, &en, sizeof(en));
|
write (fd, &en, sizeof(en));
|
||||||
|
|
||||||
@ -63,6 +52,99 @@ write_err_and_exit (gint fd,
|
|||||||
* away in the global __argc and __argv by the C runtime startup code.
|
* away in the global __argc and __argv by the C runtime startup code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Info peeked from mingw runtime's source code. __wgetmainargs() is a
|
||||||
|
* function to get the program's argv in wide char format.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int newmode;
|
||||||
|
} _startupinfo;
|
||||||
|
|
||||||
|
extern void __wgetmainargs(int *argc,
|
||||||
|
wchar_t ***wargv,
|
||||||
|
wchar_t ***wenviron,
|
||||||
|
int expand_wildcards,
|
||||||
|
_startupinfo *startupinfo);
|
||||||
|
|
||||||
|
/* Copy of protect_argv that handles wchar_t strings */
|
||||||
|
|
||||||
|
static gint
|
||||||
|
protect_wargv (wchar_t **wargv,
|
||||||
|
wchar_t ***new_wargv)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gint argc = 0;
|
||||||
|
|
||||||
|
while (wargv[argc])
|
||||||
|
++argc;
|
||||||
|
*new_wargv = g_new (wchar_t *, 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_wargv[0] constructed by this function should
|
||||||
|
* *not* be passed as the filename argument to a _wspawn* or _wexec*
|
||||||
|
* family function. That argument should be the real file name
|
||||||
|
* without any quoting.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
wchar_t *p = wargv[i];
|
||||||
|
wchar_t *q;
|
||||||
|
gint len = 0;
|
||||||
|
gboolean need_dblquotes = FALSE;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
if (*p == ' ' || *p == '\t')
|
||||||
|
need_dblquotes = TRUE;
|
||||||
|
else if (*p == '"')
|
||||||
|
len++;
|
||||||
|
else if (*p == '\\')
|
||||||
|
{
|
||||||
|
wchar_t *pp = p;
|
||||||
|
while (*pp && *pp == '\\')
|
||||||
|
pp++;
|
||||||
|
if (*pp == '"')
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = (*new_wargv)[i] = g_new (wchar_t, len + need_dblquotes*2 + 1);
|
||||||
|
p = wargv[i];
|
||||||
|
|
||||||
|
if (need_dblquotes)
|
||||||
|
*q++ = '"';
|
||||||
|
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
if (*p == '"')
|
||||||
|
*q++ = '\\';
|
||||||
|
else if (*p == '\\')
|
||||||
|
{
|
||||||
|
wchar_t *pp = p;
|
||||||
|
while (*pp && *pp == '\\')
|
||||||
|
pp++;
|
||||||
|
if (*pp == '"')
|
||||||
|
*q++ = '\\';
|
||||||
|
}
|
||||||
|
*q++ = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_dblquotes)
|
||||||
|
*q++ = '"';
|
||||||
|
*q++ = '\0';
|
||||||
|
}
|
||||||
|
(*new_wargv)[argc] = NULL;
|
||||||
|
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
int _stdcall
|
int _stdcall
|
||||||
WinMain (struct HINSTANCE__ *hInstance,
|
WinMain (struct HINSTANCE__ *hInstance,
|
||||||
struct HINSTANCE__ *hPrevInstance,
|
struct HINSTANCE__ *hPrevInstance,
|
||||||
@ -77,44 +159,43 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|||||||
int saved_errno;
|
int saved_errno;
|
||||||
int no_error = CHILD_NO_ERROR;
|
int no_error = CHILD_NO_ERROR;
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
gint file_and_argv_zero = 0;
|
gint argv_zero_offset = ARG_PROGRAM;
|
||||||
gchar **new_argv;
|
gchar **new_argv;
|
||||||
|
wchar_t **new_wargv;
|
||||||
SETUP_DEBUG();
|
int argc;
|
||||||
|
wchar_t **wargv, **wenvp;
|
||||||
if (debug)
|
_startupinfo si = { 0 };
|
||||||
{
|
|
||||||
debugstring = g_string_new (NULL);
|
|
||||||
|
|
||||||
g_string_append (debugstring,
|
|
||||||
g_strdup_printf ("g-spawn-win32-helper: "
|
|
||||||
"argc = %d, argv: ",
|
|
||||||
__argc));
|
|
||||||
for (i = 0; i < __argc; i++)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
g_string_append (debugstring, " ");
|
|
||||||
g_string_append (debugstring, __argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert (__argc >= ARG_COUNT);
|
g_assert (__argc >= ARG_COUNT);
|
||||||
|
|
||||||
/* argv[ARG_CHILD_ERR_REPORT] is the file descriptor onto which
|
if (G_WIN32_HAVE_WIDECHAR_API ())
|
||||||
* write error messages.
|
{
|
||||||
|
/* Fetch the wide-char argument vector */
|
||||||
|
__wgetmainargs (&argc, &wargv, &wenvp, 0, &si);
|
||||||
|
|
||||||
|
/* We still have the system codepage args in __argv. We can look
|
||||||
|
* at the first args in which gspawn-win32.c passes us flags and
|
||||||
|
* fd numbers in __argv, as we know those are just ASCII anyway.
|
||||||
|
*/
|
||||||
|
g_assert (argc == __argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* argv[ARG_CHILD_ERR_REPORT] is the file descriptor number onto
|
||||||
|
* which write error messages.
|
||||||
*/
|
*/
|
||||||
child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
|
child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
|
||||||
|
|
||||||
/* Hack to implement G_SPAWN_FILE_AND_ARGV_ZERO */
|
/* Hack to implement G_SPAWN_FILE_AND_ARGV_ZERO. If
|
||||||
|
* argv[ARG_CHILD_ERR_REPORT] is suffixed with a '#' it means we get
|
||||||
|
* the program to run and its argv[0] separately.
|
||||||
|
*/
|
||||||
if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
|
if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
|
||||||
file_and_argv_zero = 1;
|
argv_zero_offset++;
|
||||||
|
|
||||||
/* argv[ARG_STDIN..ARG_STDERR] are the file descriptors that should
|
/* argv[ARG_STDIN..ARG_STDERR] are the file descriptor numbers that
|
||||||
* be dup2'd to stdin, stdout and stderr, '-' if the corresponding
|
* should be dup2'd to 0, 1 and 2. '-' if the corresponding fd
|
||||||
* std* should be let alone, and 'z' if it should be connected to
|
* should be left alone, and 'z' if it should be connected to the
|
||||||
* the bit bucket NUL:.
|
* bit bucket NUL:.
|
||||||
*/
|
*/
|
||||||
if (__argv[ARG_STDIN][0] == '-')
|
if (__argv[ARG_STDIN][0] == '-')
|
||||||
; /* Nothing */
|
; /* Nothing */
|
||||||
@ -185,21 +266,21 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|||||||
if (__argv[ARG_WORKING_DIRECTORY][0] == '-' &&
|
if (__argv[ARG_WORKING_DIRECTORY][0] == '-' &&
|
||||||
__argv[ARG_WORKING_DIRECTORY][1] == 0)
|
__argv[ARG_WORKING_DIRECTORY][1] == 0)
|
||||||
; /* Nothing */
|
; /* Nothing */
|
||||||
else if (chdir (__argv[ARG_WORKING_DIRECTORY]) < 0)
|
else if ((G_WIN32_HAVE_WIDECHAR_API () &&
|
||||||
write_err_and_exit (child_err_report_fd,
|
_wchdir (wargv[ARG_WORKING_DIRECTORY]) < 0) ||
|
||||||
CHILD_CHDIR_FAILED);
|
(!G_WIN32_HAVE_WIDECHAR_API () &&
|
||||||
|
chdir (__argv[ARG_WORKING_DIRECTORY]) < 0))
|
||||||
|
write_err_and_exit (child_err_report_fd, CHILD_CHDIR_FAILED);
|
||||||
|
|
||||||
/* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
|
/* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
|
||||||
* upwards should be closed
|
* upwards should be closed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
|
if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
|
||||||
for (i = 3; i < 1000; i++) /* FIXME real limit? */
|
for (i = 3; i < 1000; i++) /* FIXME real limit? */
|
||||||
if (i != child_err_report_fd)
|
if (i != child_err_report_fd)
|
||||||
close (i);
|
close (i);
|
||||||
|
|
||||||
/* __argv[ARG_WAIT] is "w" to wait for the program to exit */
|
/* __argv[ARG_WAIT] is "w" to wait for the program to exit */
|
||||||
|
|
||||||
if (__argv[ARG_WAIT][0] == 'w')
|
if (__argv[ARG_WAIT][0] == 'w')
|
||||||
mode = P_WAIT;
|
mode = P_WAIT;
|
||||||
else
|
else
|
||||||
@ -207,53 +288,36 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|||||||
|
|
||||||
/* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
|
/* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
|
||||||
|
|
||||||
/* __argv[ARG_PROGRAM] is program file to run,
|
/* __argv[ARG_PROGRAM] is executable file to run,
|
||||||
* __argv[ARG_PROGRAM+1]... is its __argv.
|
* __argv[argv_zero_offset]... is its argv. argv_zero_offset equals
|
||||||
|
* ARG_PROGRAM unless G_SPAWN_FILE_AND_ARGV_ZERO was used, in which
|
||||||
|
* case we have a separate executable name and argv[0].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protect_argv (__argv, &new_argv);
|
|
||||||
|
|
||||||
/* For the program name passed to spawnv(), don't use the quoted
|
/* For the program name passed to spawnv(), don't use the quoted
|
||||||
* version. */
|
* version.
|
||||||
|
*/
|
||||||
if (debug)
|
if (G_WIN32_HAVE_WIDECHAR_API ())
|
||||||
{
|
{
|
||||||
debugstring = g_string_new (NULL);
|
protect_wargv (wargv + argv_zero_offset, &new_wargv);
|
||||||
g_string_append (debugstring,
|
|
||||||
g_strdup_printf ("calling %s %s mode=%s argv: ",
|
|
||||||
(__argv[ARG_USE_PATH][0] == 'y' ?
|
|
||||||
"spawnvp" : "spawnv"),
|
|
||||||
__argv[ARG_PROGRAM],
|
|
||||||
(mode == P_WAIT ?
|
|
||||||
"P_WAIT" : "P_NOWAIT")));
|
|
||||||
i = ARG_PROGRAM + 1 + file_and_argv_zero;
|
|
||||||
while (new_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 (new_argv[ARG_USE_PATH][0] == 'y')
|
if (__argv[ARG_USE_PATH][0] == 'y')
|
||||||
handle = spawnvp (mode, __argv[ARG_PROGRAM], new_argv + ARG_PROGRAM + file_and_argv_zero);
|
handle = _wspawnvp (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv);
|
||||||
|
else
|
||||||
|
handle = _wspawnv (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
handle = spawnv (mode, __argv[ARG_PROGRAM], new_argv + ARG_PROGRAM + file_and_argv_zero);
|
{
|
||||||
|
protect_argv (__argv + argv_zero_offset, &new_argv);
|
||||||
|
|
||||||
|
if (__argv[ARG_USE_PATH][0] == 'y')
|
||||||
|
handle = spawnvp (mode, __argv[ARG_PROGRAM], (const char **) new_argv);
|
||||||
|
else
|
||||||
|
handle = spawnv (mode, __argv[ARG_PROGRAM], (const char **) new_argv);
|
||||||
|
}
|
||||||
|
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
debugstring = g_string_new (NULL);
|
|
||||||
g_string_append (debugstring,
|
|
||||||
g_strdup_printf ("%s returned %#x",
|
|
||||||
(__argv[ARG_USE_PATH][0] == 'y' ?
|
|
||||||
"spawnvp" : "spawnv"),
|
|
||||||
handle));
|
|
||||||
MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle == -1 && saved_errno != 0)
|
if (handle == -1 && saved_errno != 0)
|
||||||
write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
|
write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
|
||||||
|
|
||||||
@ -264,4 +328,3 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|||||||
write (child_err_report_fd, &zero, sizeof (zero));
|
write (child_err_report_fd, &zero, sizeof (zero));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,14 @@
|
|||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
/* Mingw doesn't have prototypes for these */
|
||||||
|
int _wspawnvpe (int, const wchar_t *, const wchar_t **, const wchar_t **);
|
||||||
|
int _wspawnvp (int, const wchar_t *, const wchar_t **);
|
||||||
|
int _wspawnve (int, const wchar_t *, const wchar_t **, const wchar_t **);
|
||||||
|
int _wspawnv (int, const wchar_t *, const wchar_t **);
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
#ifdef G_SPAWN_WIN32_DEBUG
|
#ifdef G_SPAWN_WIN32_DEBUG
|
||||||
@ -171,7 +179,6 @@ protect_argv (gchar **argv,
|
|||||||
if (need_dblquotes)
|
if (need_dblquotes)
|
||||||
*q++ = '"';
|
*q++ = '"';
|
||||||
*q++ = '\0';
|
*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;
|
(*new_argv)[argc] = NULL;
|
||||||
|
|
||||||
@ -192,25 +199,25 @@ g_spawn_error_quark (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
g_spawn_async (const gchar *working_directory,
|
g_spawn_async_utf8 (const gchar *working_directory,
|
||||||
gchar **argv,
|
gchar **argv,
|
||||||
gchar **envp,
|
gchar **envp,
|
||||||
GSpawnFlags flags,
|
GSpawnFlags flags,
|
||||||
GSpawnChildSetupFunc child_setup,
|
GSpawnChildSetupFunc child_setup,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GPid *child_handle,
|
GPid *child_handle,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (argv != NULL, FALSE);
|
g_return_val_if_fail (argv != NULL, FALSE);
|
||||||
|
|
||||||
return g_spawn_async_with_pipes (working_directory,
|
return g_spawn_async_with_pipes_utf8 (working_directory,
|
||||||
argv, envp,
|
argv, envp,
|
||||||
flags,
|
flags,
|
||||||
child_setup,
|
child_setup,
|
||||||
user_data,
|
user_data,
|
||||||
child_handle,
|
child_handle,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avoids a danger in threaded situations (calling close()
|
/* Avoids a danger in threaded situations (calling close()
|
||||||
@ -362,6 +369,46 @@ set_child_error (gint report[2],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wchar_t **
|
||||||
|
utf8_charv_to_wcharv (gchar **utf8_charv)
|
||||||
|
{
|
||||||
|
wchar_t **retval = NULL;
|
||||||
|
|
||||||
|
if (utf8_charv != NULL)
|
||||||
|
{
|
||||||
|
int n = 0, i;
|
||||||
|
|
||||||
|
while (utf8_charv[n])
|
||||||
|
n++;
|
||||||
|
retval = g_new (wchar_t *, n + 1);
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, NULL);
|
||||||
|
retval[n] = NULL;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **
|
||||||
|
utf8_charv_to_cp_charv (gchar **utf8_charv)
|
||||||
|
{
|
||||||
|
char **retval = NULL;
|
||||||
|
|
||||||
|
if (utf8_charv != NULL)
|
||||||
|
{
|
||||||
|
int n = 0, i;
|
||||||
|
|
||||||
|
while (utf8_charv[n])
|
||||||
|
n++;
|
||||||
|
retval = g_new (char *, n + 1);
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
retval[i] = g_locale_from_utf8 (utf8_charv[i], -1, NULL, NULL, NULL);
|
||||||
|
retval[n] = NULL;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
do_spawn_with_pipes (gboolean dont_wait,
|
do_spawn_with_pipes (gboolean dont_wait,
|
||||||
gboolean dont_return_handle,
|
gboolean dont_return_handle,
|
||||||
@ -414,25 +461,63 @@ do_spawn_with_pipes (gboolean dont_wait,
|
|||||||
* Unix probably isn't of much use as such on Win32, anyhow.
|
* Unix probably isn't of much use as such on Win32, anyhow.
|
||||||
*/
|
*/
|
||||||
if (child_setup)
|
if (child_setup)
|
||||||
(* child_setup) (user_data);
|
{
|
||||||
|
static gboolean warned = FALSE;
|
||||||
|
if (!warned)
|
||||||
|
{
|
||||||
|
warned = TRUE;
|
||||||
|
g_warning ("passing a child setup function to the g_spawn functions is pointless and dangerous on Win32");
|
||||||
|
}
|
||||||
|
(* child_setup) (user_data);
|
||||||
|
}
|
||||||
|
|
||||||
new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
|
new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
|
||||||
if (flags & G_SPAWN_SEARCH_PATH)
|
if (G_WIN32_HAVE_WIDECHAR_API ())
|
||||||
if (envp != NULL)
|
{
|
||||||
rc = spawnvpe (mode, argv[0], (const char **) new_argv, (const char **) envp);
|
wchar_t *wargv0 = g_utf8_to_utf16 (argv[0], -1, NULL, NULL, NULL);
|
||||||
else
|
wchar_t **wargv = utf8_charv_to_wcharv (new_argv);
|
||||||
rc = spawnvp (mode, argv[0], (const char **) new_argv);
|
wchar_t **wenvp = utf8_charv_to_wcharv (envp);
|
||||||
|
|
||||||
|
if (flags & G_SPAWN_SEARCH_PATH)
|
||||||
|
if (wenvp != NULL)
|
||||||
|
rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
|
||||||
|
else
|
||||||
|
rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
|
||||||
|
else
|
||||||
|
if (wenvp != NULL)
|
||||||
|
rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
|
||||||
|
else
|
||||||
|
rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
|
||||||
|
|
||||||
|
g_free (wargv0);
|
||||||
|
g_strfreev ((gchar **) wargv);
|
||||||
|
g_strfreev ((gchar **) wenvp);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (envp != NULL)
|
{
|
||||||
rc = spawnve (mode, argv[0], (const char **) new_argv, (const char **) envp);
|
char *cpargv0 = g_locale_from_utf8 (argv[0], -1, NULL, NULL, NULL);
|
||||||
else
|
char **cpargv = utf8_charv_to_cp_charv (new_argv);
|
||||||
rc = spawnv (mode, argv[0], (const char **) new_argv);
|
char **cpenvp = utf8_charv_to_cp_charv (envp);
|
||||||
|
|
||||||
|
if (flags & G_SPAWN_SEARCH_PATH)
|
||||||
|
if (cpenvp != NULL)
|
||||||
|
rc = spawnvpe (mode, cpargv0, (const char **) cpargv, (const char **) cpenvp);
|
||||||
|
else
|
||||||
|
rc = spawnvp (mode, cpargv0, (const char **) cpargv);
|
||||||
|
else
|
||||||
|
if (envp != NULL)
|
||||||
|
rc = spawnve (mode, cpargv0, (const char **) cpargv, (const char **) cpenvp);
|
||||||
|
else
|
||||||
|
rc = spawnv (mode, cpargv0, (const char **) cpargv);
|
||||||
|
|
||||||
|
g_free (cpargv0);
|
||||||
|
g_strfreev (cpargv);
|
||||||
|
g_strfreev (cpenvp);
|
||||||
|
}
|
||||||
|
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
g_strfreev (protected_argv);
|
||||||
g_free (protected_argv[i]);
|
|
||||||
g_free (protected_argv);
|
|
||||||
|
|
||||||
if (rc == -1 && saved_errno != 0)
|
if (rc == -1 && saved_errno != 0)
|
||||||
{
|
{
|
||||||
@ -565,27 +650,51 @@ do_spawn_with_pipes (gboolean dont_wait,
|
|||||||
if (child_setup)
|
if (child_setup)
|
||||||
(* child_setup) (user_data);
|
(* child_setup) (user_data);
|
||||||
|
|
||||||
if (envp != NULL)
|
if (G_WIN32_HAVE_WIDECHAR_API ())
|
||||||
/* Let's hope envp hasn't mucked with PATH so that
|
{
|
||||||
* gspawn-win32-helper.exe isn't found.
|
wchar_t *whelper = g_utf8_to_utf16 (HELPER_PROCESS, -1, NULL, NULL, NULL);
|
||||||
*/
|
wchar_t **wargv = utf8_charv_to_wcharv (new_argv);
|
||||||
rc = spawnvpe (P_NOWAIT, HELPER_PROCESS, (const char **) new_argv, (const char **) envp);
|
wchar_t **wenvp = utf8_charv_to_wcharv (envp);
|
||||||
|
|
||||||
|
if (wenvp != NULL)
|
||||||
|
/* Let's hope envp hasn't mucked with PATH so that
|
||||||
|
* gspawn-win32-helper.exe isn't found.
|
||||||
|
*/
|
||||||
|
rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
|
||||||
|
else
|
||||||
|
rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
g_free (whelper);
|
||||||
|
g_strfreev ((gchar **) wargv);
|
||||||
|
g_strfreev ((gchar **) wenvp);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
rc = spawnvp (P_NOWAIT, HELPER_PROCESS, (const char **) new_argv);
|
{
|
||||||
|
char **cpargv = utf8_charv_to_cp_charv (new_argv);
|
||||||
|
char **cpenvp = utf8_charv_to_cp_charv (envp);
|
||||||
|
|
||||||
saved_errno = errno;
|
if (cpenvp != NULL)
|
||||||
|
rc = spawnvpe (P_NOWAIT, HELPER_PROCESS, (const char **) cpargv, (const char **) cpenvp);
|
||||||
|
else
|
||||||
|
rc = spawnvp (P_NOWAIT, HELPER_PROCESS, (const char **) cpargv);
|
||||||
|
|
||||||
/* Close thed the other process's ends of the pipes in this
|
saved_errno = errno;
|
||||||
* process, otherwise the reader will never get EOF.
|
|
||||||
|
g_strfreev (cpargv);
|
||||||
|
g_strfreev (cpenvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the other process's ends of the pipes in this process,
|
||||||
|
* otherwise the reader will never get EOF.
|
||||||
*/
|
*/
|
||||||
close_and_invalidate (&child_err_report_pipe[1]);
|
close_and_invalidate (&child_err_report_pipe[1]);
|
||||||
close_and_invalidate (&stdin_pipe[0]);
|
close_and_invalidate (&stdin_pipe[0]);
|
||||||
close_and_invalidate (&stdout_pipe[1]);
|
close_and_invalidate (&stdout_pipe[1]);
|
||||||
close_and_invalidate (&stderr_pipe[1]);
|
close_and_invalidate (&stderr_pipe[1]);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
g_strfreev (protected_argv);
|
||||||
g_free (protected_argv[i]);
|
|
||||||
g_free (protected_argv);
|
|
||||||
|
|
||||||
g_free (new_argv[ARG_WORKING_DIRECTORY]);
|
g_free (new_argv[ARG_WORKING_DIRECTORY]);
|
||||||
g_free (new_argv);
|
g_free (new_argv);
|
||||||
@ -680,16 +789,16 @@ do_spawn_with_pipes (gboolean dont_wait,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
g_spawn_sync (const gchar *working_directory,
|
g_spawn_sync_utf8 (const gchar *working_directory,
|
||||||
gchar **argv,
|
gchar **argv,
|
||||||
gchar **envp,
|
gchar **envp,
|
||||||
GSpawnFlags flags,
|
GSpawnFlags flags,
|
||||||
GSpawnChildSetupFunc child_setup,
|
GSpawnChildSetupFunc child_setup,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
gchar **standard_output,
|
gchar **standard_output,
|
||||||
gchar **standard_error,
|
gchar **standard_error,
|
||||||
gint *exit_status,
|
gint *exit_status,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gint outpipe = -1;
|
gint outpipe = -1;
|
||||||
gint errpipe = -1;
|
gint errpipe = -1;
|
||||||
@ -920,17 +1029,17 @@ g_spawn_sync (const gchar *working_directory,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
g_spawn_async_with_pipes (const gchar *working_directory,
|
g_spawn_async_with_pipes_utf8 (const gchar *working_directory,
|
||||||
gchar **argv,
|
gchar **argv,
|
||||||
gchar **envp,
|
gchar **envp,
|
||||||
GSpawnFlags flags,
|
GSpawnFlags flags,
|
||||||
GSpawnChildSetupFunc child_setup,
|
GSpawnChildSetupFunc child_setup,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GPid *child_handle,
|
GPid *child_handle,
|
||||||
gint *standard_input,
|
gint *standard_input,
|
||||||
gint *standard_output,
|
gint *standard_output,
|
||||||
gint *standard_error,
|
gint *standard_error,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (argv != NULL, FALSE);
|
g_return_val_if_fail (argv != NULL, FALSE);
|
||||||
g_return_val_if_fail (standard_output == NULL ||
|
g_return_val_if_fail (standard_output == NULL ||
|
||||||
@ -958,12 +1067,269 @@ g_spawn_async_with_pipes (const gchar *working_directory,
|
|||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
g_spawn_command_line_sync_utf8 (const gchar *command_line,
|
||||||
|
gchar **standard_output,
|
||||||
|
gchar **standard_error,
|
||||||
|
gint *exit_status,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean retval;
|
||||||
|
gchar **argv = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (command_line != NULL, FALSE);
|
||||||
|
|
||||||
|
if (!g_shell_parse_argv (command_line,
|
||||||
|
NULL, &argv,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
retval = g_spawn_sync_utf8 (NULL,
|
||||||
|
argv,
|
||||||
|
NULL,
|
||||||
|
G_SPAWN_SEARCH_PATH,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
standard_output,
|
||||||
|
standard_error,
|
||||||
|
exit_status,
|
||||||
|
error);
|
||||||
|
g_strfreev (argv);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
g_spawn_command_line_async_utf8 (const gchar *command_line,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean retval;
|
||||||
|
gchar **argv = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (command_line != NULL, FALSE);
|
||||||
|
|
||||||
|
if (!g_shell_parse_argv (command_line,
|
||||||
|
NULL, &argv,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
retval = g_spawn_async_utf8 (NULL,
|
||||||
|
argv,
|
||||||
|
NULL,
|
||||||
|
G_SPAWN_SEARCH_PATH,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
g_strfreev (argv);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
g_spawn_close_pid (GPid pid)
|
||||||
|
{
|
||||||
|
CloseHandle (pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Binary compatibility versions that take system codepage pathnames,
|
||||||
|
* argument vectors and environments. These get used only by code
|
||||||
|
* built against 2.8.1 or earlier. Code built against 2.8.2 or later
|
||||||
|
* will use the _utf8 versions above (see the #defines in gspawn.h).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef g_spawn_async
|
||||||
|
#undef g_spawn_async_with_pipes
|
||||||
|
#undef g_spawn_sync
|
||||||
|
#undef g_spawn_command_line_sync
|
||||||
|
#undef g_spawn_command_line_async
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
setup_utf8_copies (const gchar *working_directory,
|
||||||
|
gchar **utf8_working_directory,
|
||||||
|
gchar **argv,
|
||||||
|
gchar ***utf8_argv,
|
||||||
|
gchar **envp,
|
||||||
|
gchar ***utf8_envp,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gint i, argc, envc;
|
||||||
|
|
||||||
|
if (working_directory == NULL)
|
||||||
|
*utf8_working_directory = NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*utf8_working_directory = g_locale_to_utf8 (working_directory, -1, NULL, NULL, NULL);
|
||||||
|
if (*utf8_working_directory == NULL)
|
||||||
|
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
||||||
|
"Invalid characters in working directory");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc = 0;
|
||||||
|
while (argv[argc])
|
||||||
|
++argc;
|
||||||
|
*utf8_argv = g_new (gchar *, argc + 1);
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
(*utf8_argv)[i] = g_locale_to_utf8 (argv[i], -1, NULL, NULL, NULL);
|
||||||
|
if ((*utf8_argv)[i] == NULL)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
||||||
|
"Invalid characters in argument vector");
|
||||||
|
|
||||||
|
g_strfreev (*utf8_argv);
|
||||||
|
*utf8_argv = NULL;
|
||||||
|
|
||||||
|
g_free (*utf8_working_directory);
|
||||||
|
*utf8_working_directory = NULL;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*utf8_argv)[argc] = NULL;
|
||||||
|
|
||||||
|
if (envp == NULL)
|
||||||
|
{
|
||||||
|
*utf8_envp = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
envc = 0;
|
||||||
|
while (envp[envc])
|
||||||
|
++envc;
|
||||||
|
*utf8_envp = g_new (gchar *, envc + 1);
|
||||||
|
for (i = 0; i < envc; i++)
|
||||||
|
{
|
||||||
|
(*utf8_envp)[i] = g_locale_to_utf8 (envp[i], -1, NULL, NULL, NULL);
|
||||||
|
if ((*utf8_envp)[i] == NULL)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
||||||
|
"Invalid characters in environment");
|
||||||
|
|
||||||
|
g_strfreev (*utf8_envp);
|
||||||
|
*utf8_envp = NULL;
|
||||||
|
|
||||||
|
g_strfreev (*utf8_argv);
|
||||||
|
*utf8_argv = NULL;
|
||||||
|
|
||||||
|
g_free (*utf8_working_directory);
|
||||||
|
*utf8_working_directory = NULL;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*utf8_envp)[envc] = NULL;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_utf8_copies (gchar *utf8_working_directory,
|
||||||
|
gchar **utf8_argv,
|
||||||
|
gchar **utf8_envp)
|
||||||
|
{
|
||||||
|
g_free (utf8_working_directory);
|
||||||
|
g_strfreev (utf8_argv);
|
||||||
|
g_strfreev (utf8_envp);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
g_spawn_async_with_pipes (const gchar *working_directory,
|
||||||
|
gchar **argv,
|
||||||
|
gchar **envp,
|
||||||
|
GSpawnFlags flags,
|
||||||
|
GSpawnChildSetupFunc child_setup,
|
||||||
|
gpointer user_data,
|
||||||
|
GPid *child_handle,
|
||||||
|
gint *standard_input,
|
||||||
|
gint *standard_output,
|
||||||
|
gint *standard_error,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gchar *utf8_working_directory;
|
||||||
|
gchar **utf8_argv;
|
||||||
|
gchar **utf8_envp;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
if (!setup_utf8_copies (working_directory, &utf8_working_directory,
|
||||||
|
argv, &utf8_argv,
|
||||||
|
envp, &utf8_envp,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
retval = g_spawn_async_with_pipes_utf8 (utf8_working_directory,
|
||||||
|
utf8_argv, utf8_envp,
|
||||||
|
flags, child_setup, user_data,
|
||||||
|
child_handle,
|
||||||
|
standard_input, standard_output, standard_error,
|
||||||
|
error);
|
||||||
|
|
||||||
|
free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
g_spawn_async (const gchar *working_directory,
|
||||||
|
gchar **argv,
|
||||||
|
gchar **envp,
|
||||||
|
GSpawnFlags flags,
|
||||||
|
GSpawnChildSetupFunc child_setup,
|
||||||
|
gpointer user_data,
|
||||||
|
GPid *child_handle,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return g_spawn_async_with_pipes (working_directory,
|
||||||
|
argv, envp,
|
||||||
|
flags,
|
||||||
|
child_setup,
|
||||||
|
user_data,
|
||||||
|
child_handle,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
g_spawn_sync (const gchar *working_directory,
|
||||||
|
gchar **argv,
|
||||||
|
gchar **envp,
|
||||||
|
GSpawnFlags flags,
|
||||||
|
GSpawnChildSetupFunc child_setup,
|
||||||
|
gpointer user_data,
|
||||||
|
gchar **standard_output,
|
||||||
|
gchar **standard_error,
|
||||||
|
gint *exit_status,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gchar *utf8_working_directory;
|
||||||
|
gchar **utf8_argv;
|
||||||
|
gchar **utf8_envp;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
if (!setup_utf8_copies (working_directory, &utf8_working_directory,
|
||||||
|
argv, &utf8_argv,
|
||||||
|
envp, &utf8_envp,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
retval = g_spawn_sync_utf8 (utf8_working_directory,
|
||||||
|
utf8_argv, utf8_envp,
|
||||||
|
flags, child_setup, user_data,
|
||||||
|
standard_output, standard_error, exit_status,
|
||||||
|
error);
|
||||||
|
|
||||||
|
free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
g_spawn_command_line_sync (const gchar *command_line,
|
g_spawn_command_line_sync (const gchar *command_line,
|
||||||
gchar **standard_output,
|
gchar **standard_output,
|
||||||
gchar **standard_error,
|
gchar **standard_error,
|
||||||
gint *exit_status,
|
gint *exit_status,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
gchar **argv = 0;
|
gchar **argv = 0;
|
||||||
@ -992,7 +1358,7 @@ g_spawn_command_line_sync (const gchar *command_line,
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
g_spawn_command_line_async (const gchar *command_line,
|
g_spawn_command_line_async (const gchar *command_line,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
gchar **argv = 0;
|
gchar **argv = 0;
|
||||||
@ -1019,11 +1385,5 @@ g_spawn_command_line_async (const gchar *command_line,
|
|||||||
|
|
||||||
#endif /* !GSPAWN_HELPER */
|
#endif /* !GSPAWN_HELPER */
|
||||||
|
|
||||||
void
|
|
||||||
g_spawn_close_pid (GPid pid)
|
|
||||||
{
|
|
||||||
CloseHandle (pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __G_SPAWN_C__
|
#define __G_SPAWN_C__
|
||||||
#include "galiasdef.c"
|
#include "galiasdef.c"
|
||||||
|
@ -206,8 +206,9 @@ read_data (GString *str,
|
|||||||
* must be used to evaluate the exit status. If an error occurs, no data is
|
* must be used to evaluate the exit status. If an error occurs, no data is
|
||||||
* returned in @standard_output, @standard_error, or @exit_status.
|
* returned in @standard_output, @standard_error, or @exit_status.
|
||||||
*
|
*
|
||||||
* This function calls g_spawn_async_with_pipes() internally; see that function
|
* This function calls g_spawn_async_with_pipes() internally; see that
|
||||||
* for full details on the other parameters.
|
* function for full details on the other parameters and details on
|
||||||
|
* how these functions work on Windows.
|
||||||
*
|
*
|
||||||
* Return value: %TRUE on success, %FALSE if an error was set.
|
* Return value: %TRUE on success, %FALSE if an error was set.
|
||||||
**/
|
**/
|
||||||
@ -422,9 +423,9 @@ g_spawn_sync (const gchar *working_directory,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* g_spawn_async_with_pipes:
|
* g_spawn_async_with_pipes:
|
||||||
* @working_directory: child's current working directory, or %NULL to inherit parent's
|
* @working_directory: child's current working directory, or %NULL to inherit parent's, in the GLib file name encoding
|
||||||
* @argv: child's argument vector
|
* @argv: child's argument vector, in the GLib file name encoding
|
||||||
* @envp: child's environment, or %NULL to inherit parent's
|
* @envp: child's environment, or %NULL to inherit parent's, in the GLib file name encoding
|
||||||
* @flags: flags from #GSpawnFlags
|
* @flags: flags from #GSpawnFlags
|
||||||
* @child_setup: function to run in the child just before exec()
|
* @child_setup: function to run in the child just before exec()
|
||||||
* @user_data: user data for @child_setup
|
* @user_data: user data for @child_setup
|
||||||
@ -443,12 +444,30 @@ g_spawn_sync (const gchar *working_directory,
|
|||||||
* the program must be a full path; the <envar>PATH</envar> shell variable
|
* 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.
|
* will only be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
|
||||||
*
|
*
|
||||||
* On Windows, the low-level child process creation API
|
* On Windows, note that all the string or string vector arguments to
|
||||||
* (CreateProcess())doesn't use argument vectors,
|
* this function and the other g_spawn*() functions are in UTF-8, the
|
||||||
|
* GLib file name encoding. Unicode characters that are not part of
|
||||||
|
* the system codepage passed in argument vectors will be correctly
|
||||||
|
* available in the spawned program only if it uses wide character API
|
||||||
|
* to retrieve its command line. For C programs built with Microsoft's
|
||||||
|
* tools it is enough to make the program have a wmain() instead of
|
||||||
|
* main(). wmain() has a wide character argument vector as parameter.
|
||||||
|
*
|
||||||
|
* At least currently, mingw doesn't support wmain(), so if you use
|
||||||
|
* mingw to develop the spawned program, it will have to call the
|
||||||
|
* undocumented function __wgetmainargs() to get the wide character
|
||||||
|
* argument vector and environment. See gspawn-win32-helper.c in the
|
||||||
|
* GLib sources or init.c in the mingw runtime sources for a prototype
|
||||||
|
* for that function. Alternatively, you can retrieve the Win32 system
|
||||||
|
* level wide character command line passed to the spawned program
|
||||||
|
* using the GetCommandLineW() function.
|
||||||
|
*
|
||||||
|
* 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
|
* but a command line. The C runtime library's
|
||||||
* <function>spawn*()</function> family of functions (which
|
* <function>spawn*()</function> family of functions (which
|
||||||
* g_spawn_async_with_pipes() eventually calls) paste the argument
|
* g_spawn_async_with_pipes() eventually calls) paste the argument
|
||||||
* vector elements into a command line, and the C runtime startup code
|
* vector elements together into a command line, and the C runtime startup code
|
||||||
* does a corresponding reconstruction of an argument vector from the
|
* does a corresponding reconstruction of an argument vector from the
|
||||||
* command line, to be passed to main(). Complications arise when you have
|
* command line, to be passed to main(). Complications arise when you have
|
||||||
* argument vector elements that contain spaces of double quotes. The
|
* argument vector elements that contain spaces of double quotes. The
|
||||||
@ -506,8 +525,8 @@ g_spawn_sync (const gchar *working_directory,
|
|||||||
* before calling exec() in the child. Obviously
|
* before calling exec() in the child. Obviously
|
||||||
* actions taken in this function will only affect the child, not the
|
* actions taken in this function will only affect the child, not the
|
||||||
* parent. On Windows, there is no separate fork() and exec()
|
* parent. On Windows, there is no separate fork() and exec()
|
||||||
* functionality. Child processes are created and run right away with
|
* functionality. Child processes are created and run with
|
||||||
* one API call, CreateProcess(). @child_setup is
|
* a single API call, CreateProcess(). @child_setup is
|
||||||
* called in the parent process just before creating the child
|
* called in the parent process just before creating the child
|
||||||
* process. You should carefully consider what you do in @child_setup
|
* process. You should carefully consider what you do in @child_setup
|
||||||
* if you intend your software to be portable to Windows.
|
* if you intend your software to be portable to Windows.
|
||||||
@ -521,7 +540,7 @@ g_spawn_sync (const gchar *working_directory,
|
|||||||
* process using the Win32 API, for example wait for its termination
|
* process using the Win32 API, for example wait for its termination
|
||||||
* with the <function>WaitFor*()</function> functions, or examine its
|
* with the <function>WaitFor*()</function> functions, or examine its
|
||||||
* exit code with GetExitCodeProcess(). You should close the handle
|
* exit code with GetExitCodeProcess(). You should close the handle
|
||||||
* with CloseHandle() when you no longer need it.
|
* with CloseHandle() or g_spawn_close_pid() when you no longer need it.
|
||||||
*
|
*
|
||||||
* If non-%NULL, the @standard_input, @standard_output, @standard_error
|
* If non-%NULL, the @standard_input, @standard_output, @standard_error
|
||||||
* locations will be filled with file descriptors for writing to the child's
|
* locations will be filled with file descriptors for writing to the child's
|
||||||
@ -617,7 +636,9 @@ g_spawn_async_with_pipes (const gchar *working_directory,
|
|||||||
* and WEXITSTATUS() must be used to evaluate the exit status.
|
* and WEXITSTATUS() must be used to evaluate the exit status.
|
||||||
*
|
*
|
||||||
* On Windows, please note the implications of g_shell_parse_argv()
|
* On Windows, please note the implications of g_shell_parse_argv()
|
||||||
* parsing @command_line. Space is a separator, and backslashes are
|
* parsing @command_line. Parsing is done according to Unix shell rules, not
|
||||||
|
* Windows command interpreter rules.
|
||||||
|
* Space is a separator, and backslashes are
|
||||||
* special. Thus you cannot simply pass a @command_line containing
|
* special. Thus you cannot simply pass a @command_line containing
|
||||||
* canonical Windows paths, like "c:\\program files\\app\\app.exe", as
|
* canonical Windows paths, like "c:\\program files\\app\\app.exe", as
|
||||||
* the backslashes will be eaten, and the space will act as a
|
* the backslashes will be eaten, and the space will act as a
|
||||||
|
@ -71,6 +71,14 @@ typedef enum
|
|||||||
|
|
||||||
GQuark g_spawn_error_quark (void);
|
GQuark g_spawn_error_quark (void);
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
#define g_spawn_async g_spawn_async_utf8
|
||||||
|
#define g_spawn_async_with_pipes g_spawn_async_with_pipes_utf8
|
||||||
|
#define g_spawn_sync g_spawn_sync_utf8
|
||||||
|
#define g_spawn_command_line_sync g_spawn_command_line_sync_utf8
|
||||||
|
#define g_spawn_command_line_async g_spawn_command_line_async_utf8
|
||||||
|
#endif
|
||||||
|
|
||||||
gboolean g_spawn_async (const gchar *working_directory,
|
gboolean g_spawn_async (const gchar *working_directory,
|
||||||
gchar **argv,
|
gchar **argv,
|
||||||
gchar **envp,
|
gchar **envp,
|
||||||
|
Loading…
Reference in New Issue
Block a user