[glib] Add g_application_command_line_get_stdin()



commit 89d48d7800a21db1b94c09644bc68b84cda1940b
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Jan 18 14:37:37 2012 -0500

    Add g_application_command_line_get_stdin()
    
    This returns a GInputStream corresponding to the stdin on the
    commandline that caused this invocation.
    
    The local case works on both UNIX (GUnixInputStream on stdin) and
    Windows (GWin32InputStream on GetStdHandle(STD_INPUT_HANDLE)).  The
    remote case works only on UNIX (by fd passing over D-Bus).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=668210

 gio/gapplicationcommandline.c |   46 ++++++++++++++++++++++++++
 gio/gapplicationcommandline.h |   13 ++++---
 gio/gapplicationimpl-dbus.c   |   73 ++++++++++++++++++++++++++++++++++++-----
 gio/gio.symbols               |    1 +
 4 files changed, 119 insertions(+), 14 deletions(-)
---
diff --git a/gio/gapplicationcommandline.c b/gio/gapplicationcommandline.c
index 9b84854..b2da4b1 100644
--- a/gio/gapplicationcommandline.c
+++ b/gio/gapplicationcommandline.c
@@ -29,6 +29,16 @@
 #include <string.h>
 #include <stdio.h>
 
+#ifdef G_OS_UNIX
+#include "gunixinputstream.h"
+#endif
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#undef environ
+#include "gwin32inputstream.h"
+#endif
+
 G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT)
 
 /**
@@ -188,6 +198,16 @@ g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdli
   g_printerr ("%s", message);
 }
 
+static GInputStream *
+g_application_command_line_real_get_stdin (GApplicationCommandLine *cmdline)
+{
+#ifdef G_OS_UNIX
+  return g_unix_input_stream_new (0, FALSE);
+#else
+  return g_win32_input_stream_new (GetStdHandle (STD_INPUT_HANDLE), FALSE);
+#endif
+}
+
 static void
 g_application_command_line_get_property (GObject    *object,
                                          guint       prop_id,
@@ -296,6 +316,7 @@ g_application_command_line_class_init (GApplicationCommandLineClass *class)
 
   class->printerr_literal = g_application_command_line_real_printerr_literal;
   class->print_literal = g_application_command_line_real_print_literal;
+  class->get_stdin = g_application_command_line_real_get_stdin;
 
   g_object_class_install_property (object_class, PROP_ARGUMENTS,
     g_param_spec_variant ("arguments",
@@ -359,6 +380,31 @@ g_application_command_line_get_arguments (GApplicationCommandLine *cmdline,
 }
 
 /**
+ * g_application_command_line_get_stdin_data:
+ * @cmdline: a #GApplicationCommandLine
+ *
+ * Gets the stdin of the invoking process.
+ *
+ * The #GInputStream can be used to read data passed to the standard
+ * input of the invoking process.
+ * This doesn't work on all platforms.  Presently, it is only available
+ * on UNIX when using a DBus daemon capable of passing file descriptors.
+ * If stdin is not available then %NULL will be returned.  In the
+ * future, support may be expanded to other platforms.
+ *
+ * You must only call this function once per commandline invocation.
+ *
+ * Returns: (transfer full): a #GInputStream for stdin
+ *
+ * Since: 2.34
+ **/
+GInputStream *
+g_application_command_line_get_stdin (GApplicationCommandLine *cmdline)
+{
+  return G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->get_stdin (cmdline);
+}
+
+/**
  * g_application_command_line_get_cwd:
  * @cmdline: a #GApplicationCommandLine
  *
diff --git a/gio/gapplicationcommandline.h b/gio/gapplicationcommandline.h
index 8b6b094..cf5e5e0 100644
--- a/gio/gapplicationcommandline.h
+++ b/gio/gapplicationcommandline.h
@@ -62,12 +62,13 @@ struct _GApplicationCommandLineClass
   /*< private >*/
   GObjectClass parent_class;
 
-  void (* print_literal)    (GApplicationCommandLine *cmdline,
-                             const gchar             *message);
-  void (* printerr_literal) (GApplicationCommandLine *cmdline,
-                             const gchar             *message);
+  void                  (* print_literal)       (GApplicationCommandLine *cmdline,
+                                                 const gchar             *message);
+  void                  (* printerr_literal)    (GApplicationCommandLine *cmdline,
+                                                 const gchar             *message);
+  GInputStream *        (* get_stdin)           (GApplicationCommandLine *cmdline);
 
-  gpointer padding[12];
+  gpointer padding[11];
 };
 
 GType                   g_application_command_line_get_type             (void) G_GNUC_CONST;
@@ -75,6 +76,8 @@ GType                   g_application_command_line_get_type             (void) G
 gchar **                g_application_command_line_get_arguments        (GApplicationCommandLine   *cmdline,
                                                                          int                       *argc);
 
+GInputStream *          g_application_command_line_get_stdin            (GApplicationCommandLine   *cmdline);
+
 const gchar * const *   g_application_command_line_get_environ          (GApplicationCommandLine   *cmdline);
 
 const gchar *           g_application_command_line_getenv               (GApplicationCommandLine   *cmdline,
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
index e1ed356..4239640 100644
--- a/gio/gapplicationimpl-dbus.c
+++ b/gio/gapplicationimpl-dbus.c
@@ -39,6 +39,11 @@
 #include "gapplicationcommandline.h"
 #include "gdbusmethodinvocation.h"
 
+#ifdef G_OS_UNIX
+#include "gunixinputstream.h"
+#include "gunixfdlist.h"
+#endif
+
 /* DBus Interface definition {{{1 */
 
 /* For documentation of these interfaces, see
@@ -524,8 +529,12 @@ g_application_impl_cmdline_done (GObject      *source,
   GError *error = NULL;
   GVariant *reply;
 
-  reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
-                                         result, &error);
+#ifdef G_OS_UNIX
+  reply = g_dbus_connection_call_with_unix_fd_list_finish (G_DBUS_CONNECTION (source), NULL, result, &error);
+#else
+  reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+#endif
+
 
   if (reply != NULL)
     {
@@ -580,15 +589,31 @@ g_application_impl_command_line (GApplicationImpl  *impl,
   /* In theory we should try other paths... */
   g_assert (object_id != 0);
 
-  g_dbus_connection_call (impl->session_bus,
-                          impl->bus_name,
-                          impl->object_path,
-                          "org.gtk.Application",
-                          "CommandLine",
-                          g_variant_new ("(o^aay a{sv})", object_path,
-                                         arguments, platform_data),
+#ifdef G_OS_UNIX
+  {
+    GError *error = NULL;
+    GUnixFDList *fd_list;
+
+    /* send along the stdin in case
+     * g_application_command_line_get_stdin_data() is called
+     */
+    fd_list = g_unix_fd_list_new ();
+    g_unix_fd_list_append (fd_list, 0, &error);
+    g_assert_no_error (error);
+
+    g_dbus_connection_call_with_unix_fd_list (impl->session_bus, impl->bus_name, impl->object_path,
+                                              "org.gtk.Application", "CommandLine",
+                                              g_variant_new ("(o^aay a{sv})", object_path, arguments, platform_data),
+                                              G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, fd_list, NULL,
+                                              g_application_impl_cmdline_done, &data);
+  }
+#else
+  g_dbus_connection_call (impl->session_bus, impl->bus_name, impl->object_path,
+                          "org.gtk.Application", "CommandLine",
+                          g_variant_new ("(o^aay a{sv})", object_path, arguments, platform_data),
                           G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, NULL,
                           g_application_impl_cmdline_done, &data);
+#endif
 
   g_main_loop_run (data.loop);
 
@@ -665,6 +690,35 @@ g_dbus_command_line_printerr_literal (GApplicationCommandLine *cmdline,
                           NULL, 0, -1, NULL, NULL, NULL);
 }
 
+static GInputStream *
+g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline)
+{
+#ifdef G_OS_UNIX
+  GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline;
+  GInputStream *result = NULL;
+  GDBusMessage *message;
+  GUnixFDList *fd_list;
+
+  message = g_dbus_method_invocation_get_message (gdbcl->invocation);
+  fd_list = g_dbus_message_get_unix_fd_list (message);
+
+  if (fd_list && g_unix_fd_list_get_length (fd_list))
+    {
+      gint *fds, n_fds, i;
+
+      fds = g_unix_fd_list_steal_fds (fd_list, &n_fds);
+      result = g_unix_input_stream_new (fds[0], TRUE);
+      for (i = 1; i < n_fds; i++)
+        close (fds[i]);
+      g_free (fds);
+    }
+
+  return result;
+#else
+  return NULL;
+#endif
+}
+
 static void
 g_dbus_command_line_finalize (GObject *object)
 {
@@ -695,6 +749,7 @@ g_dbus_command_line_class_init (GApplicationCommandLineClass *class)
   object_class->finalize = g_dbus_command_line_finalize;
   class->printerr_literal = g_dbus_command_line_printerr_literal;
   class->print_literal = g_dbus_command_line_print_literal;
+  class->get_stdin = g_dbus_command_line_get_stdin;
 }
 
 static GApplicationCommandLine *
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 1950347..3ae21bd 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -34,6 +34,7 @@ g_application_set_default
 g_application_set_flags
 g_application_set_inactivity_timeout
 g_application_quit
+g_application_command_line_get_stdin
 g_application_command_line_create_file_for_arg
 g_application_command_line_get_arguments
 g_application_command_line_get_cwd



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