}
static gint
-protect_argv (gchar **argv,
- gchar ***new_argv)
+protect_argv (const gchar * const *argv,
+ gchar ***new_argv)
{
gint i;
gint argc = 0;
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
- GPid *child_handle,
+ GPid *child_pid,
GError **error)
{
g_return_val_if_fail (argv != NULL, FALSE);
flags,
child_setup,
user_data,
- child_handle,
+ child_pid,
NULL, NULL, NULL,
error);
}
}
static gboolean
-utf8_charv_to_wcharv (char **utf8_charv,
- wchar_t ***wcharv,
- int *error_index,
- GError **error)
+utf8_charv_to_wcharv (const gchar * const *utf8_charv,
+ wchar_t ***wcharv,
+ int *error_index,
+ GError **error)
{
wchar_t **retval = NULL;
static gboolean
do_spawn_directly (gint *exit_status,
- gboolean do_return_handle,
- GSpawnFlags flags,
- gchar **argv,
- char **envp,
- char **protected_argv,
- GPid *child_handle,
- GError **error)
+ gboolean do_return_handle,
+ GSpawnFlags flags,
+ const gchar * const *argv,
+ const gchar * const *envp,
+ const gchar * const *protected_argv,
+ GPid *child_pid,
+ GError **error)
{
const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
- char **new_argv;
+ const gchar * const *new_argv;
gintptr rc = -1;
int errsv;
GError *conv_error = NULL;
if (exit_status == NULL)
{
- if (child_handle && do_return_handle)
- *child_handle = (GPid) rc;
+ if (child_pid && do_return_handle)
+ *child_pid = (GPid) rc;
else
{
CloseHandle ((HANDLE) rc);
- if (child_handle)
- *child_handle = 0;
+ if (child_pid)
+ *child_pid = 0;
}
}
else
}
static gboolean
-do_spawn_with_fds (gint *exit_status,
- gboolean do_return_handle,
- const gchar *working_directory,
- gchar **argv,
- char **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- GPid *child_handle,
- gint stdin_fd,
- gint stdout_fd,
- gint stderr_fd,
- gint *err_report,
- GError **error)
+fork_exec (gint *exit_status,
+ gboolean do_return_handle,
+ const gchar *working_directory,
+ const gchar * const *argv,
+ const gchar * const *envp,
+ GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup,
+ gpointer user_data,
+ GPid *child_pid,
+ gint *stdin_pipe_out,
+ gint *stdout_pipe_out,
+ gint *stderr_pipe_out,
+ gint stdin_fd,
+ gint stdout_fd,
+ gint stderr_fd,
+ gint *err_report,
+ GError **error)
{
char **protected_argv;
char args[ARG_COUNT][10];
gchar *helper_process;
wchar_t *whelper, **wargv, **wenvp;
gchar *glib_dll_directory;
+ int stdin_pipe[2] = { -1, -1 };
+ int stdout_pipe[2] = { -1, -1 };
+ int stderr_pipe[2] = { -1, -1 };
+
+ g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
+ g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
+ g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
if (child_setup && !warned_about_child_setup)
{
g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
}
+ if (stdin_pipe_out != NULL)
+ {
+ if (!make_pipe (stdin_pipe, error))
+ goto cleanup_and_fail;
+ stdin_fd = stdin_pipe[0];
+ }
+
+ if (stdout_pipe_out != NULL)
+ {
+ if (!make_pipe (stdout_pipe, error))
+ goto cleanup_and_fail;
+ stdout_fd = stdout_pipe[1];
+ }
+
+ if (stderr_pipe_out != NULL)
+ {
+ if (!make_pipe (stderr_pipe, error))
+ goto cleanup_and_fail;
+ stderr_fd = stderr_pipe[1];
+ }
+
argc = protect_argv (argv, &protected_argv);
if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 &&
/* We can do without the helper process */
gboolean retval =
do_spawn_directly (exit_status, do_return_handle, flags,
- argv, envp, protected_argv,
- child_handle, error);
+ argv, envp, (const gchar * const *) protected_argv,
+ child_pid, error);
g_strfreev (protected_argv);
return retval;
}
g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
}
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
+ if (!utf8_charv_to_wcharv ((const gchar * const *) new_argv, &wargv, &conv_error_index, &conv_error))
{
if (conv_error_index == ARG_WORKING_DIRECTORY)
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
switch (helper_report[0])
{
case CHILD_NO_ERROR:
- if (child_handle && do_return_handle)
+ if (child_pid && do_return_handle)
{
/* rc is our HANDLE for gspawn-win32-helper. It has
* told us the HANDLE of its child. Duplicate that into
* a HANDLE valid in this process.
*/
if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
- GetCurrentProcess (), (LPHANDLE) child_handle,
+ GetCurrentProcess (), (LPHANDLE) child_pid,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
char *emsg = g_win32_error_message (GetLastError ());
g_print("%s\n", emsg);
- *child_handle = 0;
+ *child_pid = 0;
}
}
- else if (child_handle)
- *child_handle = 0;
+ else if (child_pid)
+ *child_pid = 0;
write (helper_sync_pipe[1], " ", 1);
close_and_invalidate (&helper_sync_pipe[1]);
break;
if (rc != -1)
CloseHandle ((HANDLE) rc);
-
+
+ /* Close the other process's ends of the pipes in this process,
+ * otherwise the reader will never get EOF.
+ */
+ close_and_invalidate (&stdin_pipe[0]);
+ close_and_invalidate (&stdout_pipe[1]);
+ close_and_invalidate (&stderr_pipe[1]);
+
+ if (stdin_pipe_out != NULL)
+ *stdin_pipe_out = stdin_pipe[1];
+ if (stdout_pipe_out != NULL)
+ *stdout_pipe_out = stdout_pipe[0];
+ if (stderr_pipe_out != NULL)
+ *stderr_pipe_out = stderr_pipe[0];
+
return TRUE;
cleanup_and_fail:
if (helper_sync_pipe[1] != -1)
close (helper_sync_pipe[1]);
- return FALSE;
-}
-
-static gboolean
-do_spawn_with_pipes (gint *exit_status,
- gboolean do_return_handle,
- const gchar *working_directory,
- gchar **argv,
- char **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- gint *err_report,
- GError **error)
-{
- int stdin_pipe[2] = { -1, -1 };
- int stdout_pipe[2] = { -1, -1 };
- int stderr_pipe[2] = { -1, -1 };
-
- if (standard_input && !make_pipe (stdin_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_output && !make_pipe (stdout_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_error && !make_pipe (stderr_pipe, error))
- goto cleanup_and_fail;
-
- if (!do_spawn_with_fds (exit_status,
- do_return_handle,
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- child_handle,
- stdin_pipe[0],
- stdout_pipe[1],
- stderr_pipe[1],
- err_report,
- error))
- goto cleanup_and_fail;
-
- /* Close the other process's ends of the pipes in this process,
- * otherwise the reader will never get EOF.
- */
- close_and_invalidate (&stdin_pipe[0]);
- close_and_invalidate (&stdout_pipe[1]);
- close_and_invalidate (&stderr_pipe[1]);
-
- if (standard_input)
- *standard_input = stdin_pipe[1];
- if (standard_output)
- *standard_output = stdout_pipe[0];
- if (standard_error)
- *standard_error = stderr_pipe[0];
-
- return TRUE;
-
- cleanup_and_fail:
-
if (stdin_pipe[0] != -1)
close (stdin_pipe[0]);
if (stdin_pipe[1] != -1)
if (standard_error)
*standard_error = NULL;
-
- if (!do_spawn_with_pipes (&status,
- FALSE,
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- NULL,
- NULL,
- standard_output ? &outpipe : NULL,
- standard_error ? &errpipe : NULL,
- &reportpipe,
- error))
+
+ if (!fork_exec (&status,
+ FALSE,
+ working_directory,
+ (const gchar * const *) argv,
+ (const gchar * const *) envp,
+ flags,
+ child_setup,
+ user_data,
+ NULL,
+ NULL,
+ standard_output ? &outpipe : NULL,
+ standard_error ? &errpipe : NULL,
+ -1,
+ -1,
+ -1,
+ &reportpipe,
+ error))
return FALSE;
/* Read data from child. */
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
- GPid *child_handle,
+ GPid *child_pid,
gint *standard_input,
gint *standard_output,
gint *standard_error,
/* can't inherit stdin if we have an input pipe. */
g_return_val_if_fail (standard_input == NULL ||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
-
- return do_spawn_with_pipes (NULL,
- (flags & G_SPAWN_DO_NOT_REAP_CHILD),
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- child_handle,
- standard_input,
- standard_output,
- standard_error,
- NULL,
- error);
+
+ return fork_exec (NULL,
+ (flags & G_SPAWN_DO_NOT_REAP_CHILD),
+ working_directory,
+ (const gchar * const *) argv,
+ (const gchar * const *) envp,
+ flags,
+ child_setup,
+ user_data,
+ child_pid,
+ standard_input,
+ standard_output,
+ standard_error,
+ -1,
+ -1,
+ -1,
+ NULL,
+ error);
}
gboolean
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
- GPid *child_handle,
+ GPid *child_pid,
gint stdin_fd,
gint stdout_fd,
gint stderr_fd,
g_return_val_if_fail (stdin_fd == -1 ||
!(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
- return do_spawn_with_fds (NULL,
- (flags & G_SPAWN_DO_NOT_REAP_CHILD),
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- child_handle,
- stdin_fd,
- stdout_fd,
- stderr_fd,
- NULL,
- error);
+ return fork_exec (NULL,
+ (flags & G_SPAWN_DO_NOT_REAP_CHILD),
+ working_directory,
+ (const gchar * const *) argv,
+ (const gchar * const *) envp,
+ flags,
+ child_setup,
+ user_data,
+ child_pid,
+ NULL,
+ NULL,
+ NULL,
+ stdin_fd,
+ stdout_fd,
+ stderr_fd,
+ NULL,
+ error);
+
+}
+
+gboolean
+g_spawn_async_with_pipes_and_fds (const gchar *working_directory,
+ const gchar * const *argv,
+ const gchar * const *envp,
+ GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup,
+ gpointer user_data,
+ gint stdin_fd,
+ gint stdout_fd,
+ gint stderr_fd,
+ const gint *source_fds,
+ const gint *target_fds,
+ gsize n_fds,
+ GPid *child_pid_out,
+ gint *stdin_pipe_out,
+ gint *stdout_pipe_out,
+ gint *stderr_pipe_out,
+ GError **error)
+{
+ g_return_val_if_fail (argv != NULL, FALSE);
+ g_return_val_if_fail (stdout_pipe_out == NULL ||
+ !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
+ g_return_val_if_fail (stderr_pipe_out == NULL ||
+ !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
+ /* can't inherit stdin if we have an input pipe. */
+ g_return_val_if_fail (stdin_pipe_out == NULL ||
+ !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
+ /* can’t use pipes and stdin/stdout/stderr FDs */
+ g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
+ g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
+ g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
+
+ /* source_fds/target_fds isn’t supported on Windows at the moment. */
+ if (n_fds != 0)
+ {
+ g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_INVAL,
+ "FD redirection is not supported on Windows at the moment");
+ return FALSE;
+ }
+
+ return fork_exec (NULL,
+ (flags & G_SPAWN_DO_NOT_REAP_CHILD),
+ working_directory,
+ argv,
+ envp,
+ flags,
+ child_setup,
+ user_data,
+ child_pid_out,
+ stdin_pipe_out,
+ stdout_pipe_out,
+ stderr_pipe_out,
+ stdin_fd,
+ stdout_fd,
+ stderr_fd,
+ NULL,
+ error);
}
gboolean
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
- GPid *child_handle,
+ GPid *child_pid,
GError **error)
{
return g_spawn_async (working_directory,
flags,
child_setup,
user_data,
- child_handle,
+ child_pid,
error);
}
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
- GPid *child_handle,
+ GPid *child_pid,
gint *standard_input,
gint *standard_output,
gint *standard_error,
flags,
child_setup,
user_data,
- child_handle,
+ child_pid,
standard_input,
standard_output,
standard_error,