[gnome-builder] runner: add API to set a TTY for IdeRunner



commit 7ffcae780a31d2d9f2aa58e0bc8aa567087d98a4
Author: Christian Hergert <chergert redhat com>
Date:   Fri Nov 11 21:23:43 2016 -0800

    runner: add API to set a TTY for IdeRunner
    
    This allows plugins to set a TTY to be used on the IdeRunner. However,
    we may need future API for plugins to coordinate on who should be setting
    the TTY as the debugger may want to control the TTY in a different view
    than the editor.
    
    After you create the PTY slave, simply ide_runner_set_tty() using that
    fd to ensure the IdeRunner uses it.

 libide/runner/ide-runner.c |   79 ++++++++++++++++++++++++++++++++++++++++++-
 libide/runner/ide-runner.h |    4 ++
 2 files changed, 81 insertions(+), 2 deletions(-)
---
diff --git a/libide/runner/ide-runner.c b/libide/runner/ide-runner.c
index bcc0990..6e03c41 100644
--- a/libide/runner/ide-runner.c
+++ b/libide/runner/ide-runner.c
@@ -18,9 +18,11 @@
 
 #define G_LOG_DOMAIN "ide-runner"
 
+#include <errno.h>
 #include <glib/gi18n.h>
 #include <libpeas/peas.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include "ide-context.h"
 #include "ide-debug.h"
@@ -36,9 +38,14 @@
 typedef struct
 {
   PeasExtensionSet *addins;
-  GQueue argv;
   IdeEnvironment *env;
+
+  GQueue argv;
+
   GSubprocessFlags flags;
+
+  int tty_fd;
+
   guint clear_env : 1;
   guint run_on_host : 1;
 } IdeRunnerPrivate;
@@ -162,7 +169,6 @@ ide_runner_real_run_async (IdeRunner           *self,
   g_autoptr(GTask) task = NULL;
   g_autoptr(IdeSubprocessLauncher) launcher = NULL;
   g_autoptr(IdeSubprocess) subprocess = NULL;
-  g_auto(GStrv) environ = NULL;
   IdeConfigurationManager *config_manager;
   IdeConfiguration *config;
   const gchar *identifier;
@@ -193,6 +199,18 @@ ide_runner_real_run_async (IdeRunner           *self,
   ide_subprocess_launcher_set_flags (launcher, priv->flags);
 
   /*
+   * If we have a tty_fd set, then we want to override our stdin,
+   * stdout, and stderr fds with our TTY.
+   */
+  if (priv->tty_fd != -1)
+    {
+      IDE_TRACE_MSG ("Setting TTY fd to %d\n", priv->tty_fd);
+      ide_subprocess_launcher_take_stdin_fd (launcher, dup (priv->tty_fd));
+      ide_subprocess_launcher_take_stdout_fd (launcher, dup (priv->tty_fd));
+      ide_subprocess_launcher_take_stderr_fd (launcher, dup (priv->tty_fd));
+    }
+
+  /*
    * We want the runners to run on the host so that we aren't captive to
    * our containing system (flatpak, jhbuild, etc).
    */
@@ -258,6 +276,32 @@ ide_runner_real_run_finish (IdeRunner     *self,
 }
 
 static void
+ide_runner_real_set_tty (IdeRunner *self,
+                         int        tty_fd)
+{
+  IdeRunnerPrivate *priv = ide_runner_get_instance_private (self);
+
+  g_assert (IDE_IS_RUNNER (self));
+  g_assert (tty_fd >= -1);
+
+  if (tty_fd != priv->tty_fd)
+    {
+      if (priv->tty_fd != -1)
+        {
+          close (priv->tty_fd);
+          priv->tty_fd = -1;
+        }
+
+      if (tty_fd != -1)
+        {
+          priv->tty_fd = dup (tty_fd);
+          if (priv->tty_fd == -1)
+            g_warning ("Failed to dup() tty_fd: %s", g_strerror (errno));
+        }
+    }
+}
+
+static void
 ide_runner_extension_added (PeasExtensionSet *set,
                             PeasPluginInfo   *plugin_info,
                             PeasExtension    *exten,
@@ -328,6 +372,12 @@ ide_runner_finalize (GObject *object)
   g_queue_clear (&priv->argv);
   g_clear_object (&priv->env);
 
+  if (priv->tty_fd != -1)
+    {
+      close (priv->tty_fd);
+      priv->tty_fd = -1;
+    }
+
   G_OBJECT_CLASS (ide_runner_parent_class)->finalize (object);
 }
 
@@ -401,6 +451,7 @@ ide_runner_class_init (IdeRunnerClass *klass)
 
   klass->run_async = ide_runner_real_run_async;
   klass->run_finish = ide_runner_real_run_finish;
+  klass->set_tty = ide_runner_real_set_tty;
 
   properties [PROP_ARGV] =
     g_param_spec_boxed ("argv",
@@ -462,8 +513,11 @@ ide_runner_init (IdeRunner *self)
   IdeRunnerPrivate *priv = ide_runner_get_instance_private (self);
 
   g_queue_init (&priv->argv);
+
   priv->env = ide_environment_new ();
+
   priv->flags = 0;
+  priv->tty_fd = -1;
 }
 
 /**
@@ -869,3 +923,24 @@ ide_runner_set_clear_env (IdeRunner *self,
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CLEAR_ENV]);
     }
 }
+
+void
+ide_runner_set_tty (IdeRunner *self,
+                    int        tty_fd)
+{
+  IDE_ENTRY;
+
+  g_return_if_fail (IDE_IS_RUNNER (self));
+  g_return_if_fail (tty_fd >= -1);
+
+  if (IDE_RUNNER_GET_CLASS (self)->set_tty)
+    {
+      IDE_RUNNER_GET_CLASS (self)->set_tty (self, tty_fd);
+      return;
+    }
+
+  g_warning ("%s does not support setting a TTY fd",
+             G_OBJECT_TYPE_NAME (self));
+
+  IDE_EXIT;
+}
diff --git a/libide/runner/ide-runner.h b/libide/runner/ide-runner.h
index a6ab281..3d6bb5b 100644
--- a/libide/runner/ide-runner.h
+++ b/libide/runner/ide-runner.h
@@ -45,6 +45,8 @@ struct _IdeRunnerClass
   gboolean       (*run_finish) (IdeRunner            *self,
                                 GAsyncResult         *result,
                                 GError              **error);
+  void           (*set_tty)    (IdeRunner            *self,
+                                int                   tty_fd);
 };
 
 IdeRunner      *ide_runner_new             (IdeContext           *context);
@@ -75,6 +77,8 @@ GOutputStream  *ide_runner_get_stderr      (IdeRunner            *self);
 gboolean        ide_runner_get_run_on_host (IdeRunner            *self);
 void            ide_runner_set_run_on_host (IdeRunner            *self,
                                             gboolean              run_on_host);
+void            ide_runner_set_tty         (IdeRunner            *self,
+                                            int                   tty_fd);
 
 G_END_DECLS
 


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