From 9bd47300086e549d7f3927d05311690a532e063c Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Wed, 17 Nov 2021 12:27:46 +0000 Subject: [PATCH] gsubprocess: Add G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP --- 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 47ca06bed..4c595803d 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -1983,6 +1983,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. (Since: 2.72) * * Flags to define the behaviour of a #GSubprocess. * @@ -2005,7 +2008,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 c0f4f8db6..523c80bfc 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 d6fe0d784..8bd1b2844 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 084b77df3..95ee3ac77 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);