diff --git a/gio/gsubprocesslauncher.c b/gio/gsubprocesslauncher.c index 6a7e26547..5cdec4d4e 100644 --- a/gio/gsubprocesslauncher.c +++ b/gio/gsubprocesslauncher.c @@ -240,8 +240,12 @@ g_subprocess_launcher_new (GSubprocessFlags flags) * As an alternative, you can use g_subprocess_launcher_setenv(), * g_subprocess_launcher_unsetenv(), etc. * - * Pass %NULL to inherit the parent process' environment. Pass an - * empty array to set an empty environment. + * Pass an empty array to set an empty environment. Pass %NULL to inherit the + * parent process’ environment. As of GLib 2.54, the parent process’ environment + * will be copied when g_subprocess_launcher_set_environ() is called. + * Previously, it was copied when the subprocess was executed. This means the + * copied environment may now be modified (using g_subprocess_launcher_setenv(), + * etc.) before launching the subprocess. * * On UNIX, all strings in this array can be arbitrary byte strings. * On Windows, they should be in UTF-8. @@ -254,6 +258,9 @@ g_subprocess_launcher_set_environ (GSubprocessLauncher *self, { g_strfreev (self->envp); self->envp = g_strdupv (env); + + if (self->envp == NULL) + self->envp = g_get_environ (); } /** diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c index e1270b1bd..7200226ba 100644 --- a/gio/tests/gsubprocess.c +++ b/gio/tests/gsubprocess.c @@ -948,6 +948,51 @@ test_env (void) g_object_unref (proc); } +/* Test that explicitly inheriting and modifying the parent process’ + * environment works. */ +static void +test_env_inherit (void) +{ + GError *local_error = NULL; + GError **error = &local_error; + GSubprocessLauncher *launcher; + GSubprocess *proc; + GPtrArray *args; + GInputStream *stdout; + gchar *result; + gchar **split; + + g_setenv ("TEST_ENV_INHERIT1", "1", TRUE); + g_setenv ("TEST_ENV_INHERIT2", "2", TRUE); + + args = get_test_subprocess_args ("env", NULL); + launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); + g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE); + g_subprocess_launcher_set_environ (launcher, NULL); + g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE); + g_subprocess_launcher_unsetenv (launcher, "TEST_ENV_INHERIT1"); + + g_assert_null (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT1")); + g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT2"), ==, "2"); + g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TWO"), ==, "2"); + + proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL); + g_ptr_array_free (args, TRUE); + g_assert_no_error (local_error); + + stdout = g_subprocess_get_stdout_pipe (proc); + + result = splice_to_string (stdout, error); + split = g_strsplit (result, "\n", -1); + g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1")); + g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2"); + g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2"); + + g_strfreev (split); + g_free (result); + g_object_unref (proc); +} + static void test_cwd (void) { @@ -1265,6 +1310,7 @@ main (int argc, char **argv) g_test_add_func ("/gsubprocess/communicate-nothing", test_communicate_nothing); g_test_add_func ("/gsubprocess/terminate", test_terminate); g_test_add_func ("/gsubprocess/env", test_env); + g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit); g_test_add_func ("/gsubprocess/cwd", test_cwd); #ifdef G_OS_UNIX g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);