[gnome-builder/wip/gtk4-port] libide/io: guess user $PATH at startup



commit 7d96ff51d10e098e5c6b7132bc8ea0b52e4946e3
Author: Christian Hergert <chergert redhat com>
Date:   Thu May 5 14:47:39 2022 -0700

    libide/io: guess user $PATH at startup
    
    We can use this instead of "SAFE_PATH" when running from within Builder
    so that we get the user's default login path on the host system.

 src/libide/io/ide-shell-private.h |  3 +-
 src/libide/io/ide-shell.c         | 75 +++++++++++++++++++++++++++++++++++----
 src/libide/io/ide-shell.h         |  2 ++
 src/main.c                        |  3 +-
 4 files changed, 74 insertions(+), 9 deletions(-)
---
diff --git a/src/libide/io/ide-shell-private.h b/src/libide/io/ide-shell-private.h
index 39b511ffd..a10695804 100644
--- a/src/libide/io/ide-shell-private.h
+++ b/src/libide/io/ide-shell-private.h
@@ -24,6 +24,7 @@
 
 G_BEGIN_DECLS
 
-void _ide_guess_shell (void);
+void _ide_guess_shell     (void);
+void _ide_guess_user_path (void);
 
 G_END_DECLS
diff --git a/src/libide/io/ide-shell.c b/src/libide/io/ide-shell.c
index 8e69d5ec3..b188167cd 100644
--- a/src/libide/io/ide-shell.c
+++ b/src/libide/io/ide-shell.c
@@ -27,6 +27,7 @@
 #include "ide-shell-private.h"
 
 static const char *user_shell = "/bin/sh";
+static const char *user_default_path = SAFE_PATH;
 
 gboolean
 ide_shell_supports_dash_c (const char *shell)
@@ -60,26 +61,33 @@ ide_guess_shell_communicate_cb (GObject      *object,
   IdeSubprocess *subprocess = (IdeSubprocess *)object;
   g_autoptr(GError) error = NULL;
   g_autofree gchar *stdout_buf = NULL;
+  const char *key = user_data;
 
   g_assert (IDE_IS_SUBPROCESS (subprocess));
   g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (user_data == NULL);
+  g_assert (key != NULL);
 
   if (!ide_subprocess_communicate_utf8_finish (subprocess, result, &stdout_buf, NULL, &error))
     {
-      g_warning ("Failed to parse result from getent: %s", error->message);
+      g_warning ("Failure to parse host information: %s", error->message);
       return;
     }
 
   if (stdout_buf != NULL)
-    {
-      g_strstrip (stdout_buf);
+    g_strstrip (stdout_buf);
+
+  g_debug ("Guessed %s as \"%s\"", key, stdout_buf);
 
+  if (ide_str_equal0 (key, "SHELL"))
+    {
       if (stdout_buf[0] == '/')
         user_shell = g_steal_pointer (&stdout_buf);
     }
-
-  g_debug ("Guessed user shell as \"%s\"", user_shell);
+  else if (ide_str_equal0 (key, "PATH"))
+    {
+      if (!ide_str_empty0 (stdout_buf))
+        user_default_path = g_steal_pointer (&stdout_buf);
+    }
 }
 
 void
@@ -127,7 +135,44 @@ _ide_guess_shell (void)
                                          NULL,
                                          NULL,
                                          ide_guess_shell_communicate_cb,
-                                         NULL);
+                                         (gpointer)"SHELL");
+}
+
+void
+_ide_guess_user_path (void)
+{
+  g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+  g_autoptr(IdeSubprocess) subprocess = NULL;
+  g_autofree gchar *command = NULL;
+  g_autoptr(GError) error = NULL;
+  g_auto(GStrv) argv = NULL;
+
+  command = g_strdup_printf ("sh --login -c 'echo $PATH'");
+
+  if (!g_shell_parse_argv (command, NULL, &argv, &error))
+    {
+      g_warning ("Failed to parse command into argv: %s",
+                 error ? error->message : "unknown error");
+      return;
+    }
+
+  launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
+  ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
+  ide_subprocess_launcher_set_clear_env (launcher, FALSE);
+  ide_subprocess_launcher_set_cwd (launcher, g_get_home_dir ());
+  ide_subprocess_launcher_push_args (launcher, (const gchar * const *)argv);
+
+  if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error)))
+    {
+      g_warning ("Failed to spawn getent: %s", error->message);
+      return;
+    }
+
+  ide_subprocess_communicate_utf8_async (subprocess,
+                                         NULL,
+                                         NULL,
+                                         ide_guess_shell_communicate_cb,
+                                         (gpointer)"PATH");
 }
 
 /**
@@ -146,3 +191,19 @@ ide_get_user_shell (void)
 {
   return user_shell;
 }
+
+/**
+ * ide_get_user_default_path:
+ *
+ * Gets the default `$PATH` on the system for the user on the host.
+ *
+ * This value is sniffed during startup and will default to `SAFE_PATH`
+ * configured when building Builder until that value has been discovered.
+ *
+ * Returns: (not nullable): a string such as "/bin:/usr/bin"
+ */
+const char *
+ide_get_user_default_path (void)
+{
+  return user_default_path;
+}
diff --git a/src/libide/io/ide-shell.h b/src/libide/io/ide-shell.h
index b47d49d6a..d2124f3e8 100644
--- a/src/libide/io/ide-shell.h
+++ b/src/libide/io/ide-shell.h
@@ -30,5 +30,7 @@ IDE_AVAILABLE_IN_ALL
 gboolean    ide_shell_supports_dash_login (const char *shell);
 IDE_AVAILABLE_IN_ALL
 const char *ide_get_user_shell            (void);
+IDE_AVAILABLE_IN_ALL
+const char *ide_get_user_default_path     (void);
 
 G_END_DECLS
diff --git a/src/main.c b/src/main.c
index e722e21a2..7627cc3be 100644
--- a/src/main.c
+++ b/src/main.c
@@ -283,8 +283,9 @@ main (gint   argc,
   /* Initialize thread pools */
   _ide_thread_pool_init (FALSE);
 
-  /* Guess the user shell early */
+  /* Guess the user $SHELL and $PATH early */
   _ide_guess_shell ();
+  _ide_guess_user_path ();
 
   /* Ensure availability of some symbols possibly dropped in link */
   _ide_gtk_init ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]