From 14b660d2c3ee6b528b9da70374d4358c8cdf10ac Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Sat, 13 Nov 2021 16:00:31 +0200 Subject: [PATCH 1/2] gsubprocess: Add G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP If the launcher flag `G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP` is set and path lookup is performed (`argv[0]` does not contain a `/`), we use the `PATH` of the child instead of the parent. `_GSubprocessLauncher::path_from_envp` is removed because it is never written to. --- gio/gioenums.h | 6 ++++- gio/gsubprocess.c | 7 +++-- gio/gsubprocesslauncher-private.h | 1 - gio/tests/gsubprocess.c | 43 +++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/gio/gioenums.h b/gio/gioenums.h index 2b6b5eb130..e12d2c8f39 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -1977,6 +1977,9 @@ typedef enum /*< flags >*/ { * file descriptors of their parent, unless those descriptors have * been explicitly marked as close-on-exec. This flag has no effect * over the "standard" file descriptors (stdin, stdout, stderr). + * @G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP: if path searching is + * needed when spawning the subprocess, use the PATH in the launcher + * environment. * * Flags to define the behaviour of a #GSubprocess. * @@ -1999,7 +2002,8 @@ typedef enum { G_SUBPROCESS_FLAGS_STDERR_PIPE = (1u << 4), G_SUBPROCESS_FLAGS_STDERR_SILENCE = (1u << 5), G_SUBPROCESS_FLAGS_STDERR_MERGE = (1u << 6), - G_SUBPROCESS_FLAGS_INHERIT_FDS = (1u << 7) + G_SUBPROCESS_FLAGS_INHERIT_FDS = (1u << 7), + G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP = (1u << 8), } GSubprocessFlags; /** diff --git a/gio/gsubprocess.c b/gio/gsubprocess.c index c0f4f8db6e..4f261d3e57 100644 --- a/gio/gsubprocess.c +++ b/gio/gsubprocess.c @@ -61,7 +61,10 @@ * As a matter of principle, #GSubprocess has no API that accepts * shell-style space-separated strings. It will, however, match the * typical shell behaviour of searching the PATH for executables that do - * not contain a directory separator in their name. + * not contain a directory separator in their name. By default, the PATH + * of the current process is used. You can specify + * %G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP to use the PATH of the + * launcher environment instead. * * #GSubprocess attempts to have a very simple API for most uses (ie: * spawning a subprocess with arguments and support for most typical @@ -380,7 +383,7 @@ initable_init (GInitable *initable, /* argv0 has no '/' in it? We better do a PATH lookup. */ if (strchr (self->argv[0], G_DIR_SEPARATOR) == NULL) { - if (self->launcher && self->launcher->path_from_envp) + if (self->launcher && self->launcher->flags & G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP) spawn_flags |= G_SPAWN_SEARCH_PATH_FROM_ENVP; else spawn_flags |= G_SPAWN_SEARCH_PATH; diff --git a/gio/gsubprocesslauncher-private.h b/gio/gsubprocesslauncher-private.h index d6fe0d784a..8bd1b28443 100644 --- a/gio/gsubprocesslauncher-private.h +++ b/gio/gsubprocesslauncher-private.h @@ -28,7 +28,6 @@ struct _GSubprocessLauncher GObject parent; GSubprocessFlags flags; - gboolean path_from_envp; char **envp; char *cwd; diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c index 084b77df3f..95ee3ac77c 100644 --- a/gio/tests/gsubprocess.c +++ b/gio/tests/gsubprocess.c @@ -26,6 +26,14 @@ #define SPLICELEN (TOTAL_HELLOS * strlen (HELLO_WORLD)) #endif + + +#ifdef G_OS_WIN32 +#define TESTPROG "gsubprocess-testprog.exe" +#else +#define TESTPROG "gsubprocess-testprog" +#endif + static GPtrArray * get_test_subprocess_args (const char *mode, ...) G_GNUC_NULL_TERMINATED; @@ -36,19 +44,12 @@ get_test_subprocess_args (const char *mode, { GPtrArray *ret; char *path; - const char *binname; va_list args; gpointer arg; ret = g_ptr_array_new_with_free_func (g_free); -#ifdef G_OS_WIN32 - binname = "gsubprocess-testprog.exe"; -#else - binname = "gsubprocess-testprog"; -#endif - - path = g_test_build_filename (G_TEST_BUILT, binname, NULL); + path = g_test_build_filename (G_TEST_BUILT, TESTPROG, NULL); g_ptr_array_add (ret, path); g_ptr_array_add (ret, g_strdup (mode)); @@ -167,6 +168,31 @@ test_search_path (void) g_object_unref (proc); } + +static void +test_search_path_from_envp (void) +{ + GError *local_error = NULL; + GError **error = &local_error; + GSubprocessLauncher *launcher; + GSubprocess *proc; + const char *path; + + path = g_test_get_dir (G_TEST_BUILT); + + launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP); + g_subprocess_launcher_setenv (launcher, "PATH", path, TRUE); + + proc = g_subprocess_launcher_spawn (launcher, error, TESTPROG, "exit1", NULL); + g_assert_no_error (local_error); + g_object_unref (launcher); + + g_subprocess_wait_check (proc, NULL, error); + g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1); + g_clear_error (error); + + g_object_unref (proc); +} #endif static void @@ -1819,6 +1845,7 @@ main (int argc, char **argv) g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit); #ifdef G_OS_UNIX g_test_add_func ("/gsubprocess/search-path", test_search_path); + g_test_add_func ("/gsubprocess/search-path-from-envp", test_search_path_from_envp); g_test_add_func ("/gsubprocess/signal", test_signal); #endif g_test_add_func ("/gsubprocess/exit1", test_exit1); -- GitLab From 5a81f486276d72b3335a63d1616f5219e138e8dc Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 17 Nov 2021 12:03:05 +0000 Subject: [PATCH 2/2] Apply 5 suggestion(s) to 2 file(s) --- gio/gioenums.h | 6 +++--- gio/gsubprocess.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gio/gioenums.h b/gio/gioenums.h index e12d2c8f39..50d8c8cfa8 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -1978,8 +1978,8 @@ typedef enum /*< flags >*/ { * been explicitly marked as close-on-exec. This flag has no effect * over the "standard" file descriptors (stdin, stdout, stderr). * @G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP: if path searching is - * needed when spawning the subprocess, use the PATH in the launcher - * environment. + * needed when spawning the subprocess, use the `PATH` in the launcher + * environment. (Since: 2.72) * * Flags to define the behaviour of a #GSubprocess. * @@ -2003,7 +2003,7 @@ typedef enum { G_SUBPROCESS_FLAGS_STDERR_SILENCE = (1u << 5), G_SUBPROCESS_FLAGS_STDERR_MERGE = (1u << 6), G_SUBPROCESS_FLAGS_INHERIT_FDS = (1u << 7), - G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP = (1u << 8), + G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP = (1u << 8) } GSubprocessFlags; /** diff --git a/gio/gsubprocess.c b/gio/gsubprocess.c index 4f261d3e57..523c80bfc5 100644 --- a/gio/gsubprocess.c +++ b/gio/gsubprocess.c @@ -61,9 +61,9 @@ * As a matter of principle, #GSubprocess has no API that accepts * shell-style space-separated strings. It will, however, match the * typical shell behaviour of searching the PATH for executables that do - * not contain a directory separator in their name. By default, the PATH + * not contain a directory separator in their name. By default, the `PATH` * of the current process is used. You can specify - * %G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP to use the PATH of the + * %G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP to use the `PATH` of the * launcher environment instead. * * #GSubprocess attempts to have a very simple API for most uses (ie: -- GitLab