[gnome-terminal] client: legacy: Implement FD passing
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-terminal] client: legacy: Implement FD passing
- Date: Mon, 30 Oct 2017 21:41:45 +0000 (UTC)
commit 17681615a03d1952491ff9d424db2b2b1a84483d
Author: Christian Persch <chpe src gnome org>
Date: Mon Oct 30 22:41:06 2017 +0100
client: legacy: Implement FD passing
src/terminal-options.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
src/terminal-options.h | 4 ++
src/terminal.c | 11 +++--
3 files changed, 135 insertions(+), 4 deletions(-)
---
diff --git a/src/terminal-options.c b/src/terminal-options.c
index a48c437..ee9e1b4 100644
--- a/src/terminal-options.c
+++ b/src/terminal-options.c
@@ -30,6 +30,7 @@
#include <glib/gprintf.h>
#include "terminal-options.h"
+#include "terminal-client-utils.h"
#include "terminal-screen.h"
#include "terminal-app.h"
#include "terminal-util.h"
@@ -120,6 +121,8 @@ initial_tab_new (char *profile /* adopts */)
it->zoom = 1.0;
it->zoom_set = FALSE;
it->active = FALSE;
+ it->fd_list = NULL;
+ it->fd_array = NULL;
return it;
}
@@ -131,6 +134,9 @@ initial_tab_free (InitialTab *it)
g_strfreev (it->exec_argv);
g_free (it->title);
g_free (it->working_dir);
+ g_clear_object (&it->fd_list);
+ if (it->fd_array)
+ g_array_unref (it->fd_array);
g_slice_free (InitialTab, it);
}
@@ -722,6 +728,87 @@ option_working_directory_callback (const gchar *option_name,
}
static gboolean
+option_pass_std_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ g_assert (g_str_has_prefix (option_name, "--std"));
+ /* We may support this later */
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "FD passing of %s is not supported",
+ option_name + 2);
+ return FALSE;
+}
+
+static gboolean
+option_pass_fd_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ errno = 0;
+ char *end;
+ gint64 v = g_ascii_strtoll (value, &end, 10);
+ if (errno || end == value || v == -1 || v < G_MININT || v > G_MAXINT) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Failed to parse \"%s\" as file descriptor number",
+ value);
+ return FALSE;
+ }
+
+ int fd = v;
+ if (fd == STDIN_FILENO ||
+ fd == STDOUT_FILENO ||
+ fd == STDERR_FILENO) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "FD passing of %s is not supported",
+ fd == STDIN_FILENO ? "stdin" : fd == STDOUT_FILENO ? "stdout" : "stderr");
+ return FALSE;
+ }
+
+ InitialTab *it = ensure_top_tab (options);
+ if (it->fd_list == NULL)
+ it->fd_list = g_unix_fd_list_new ();
+ if (it->fd_array == NULL)
+ it->fd_array = g_array_sized_new (FALSE /* zero terminate */,
+ TRUE /* clear */,
+ sizeof (PassFdElement),
+ 8 /* that should be plenty */);
+
+
+ for (guint i = 0; i < it->fd_array->len; i++) {
+ PassFdElement *e = &g_array_index (it->fd_array, PassFdElement, i);
+ if (e->fd == fd) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ _("Cannot pass FD %d twice"), fd);
+ return FALSE;
+ }
+ }
+
+ int idx = g_unix_fd_list_append (it->fd_list, fd, error);
+ if (idx == -1) {
+ g_prefix_error (error, "%d: ", fd);
+ return FALSE;
+ }
+
+ PassFdElement e = { idx, fd };
+ g_array_append_val (it->fd_array, e);
+
+#if 0
+ if (fd == STDOUT_FILENO ||
+ fd == STDERR_FILENO)
+ verbosity = 0;
+ if (fd == STDIN_FILENO)
+ it->wait = TRUE;
+#endif
+
+ return TRUE;
+}
+
+static gboolean
option_active_callback (const gchar *option_name,
const gchar *value,
gpointer data,
@@ -1262,6 +1349,43 @@ get_goption_context (TerminalOptions *options)
N_("DIRNAME")
},
{
+ "stdin",
+ 0,
+ G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_pass_std_cb,
+ "Forward stdin",
+ NULL
+ },
+ {
+ "stdout",
+ 0,
+ G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_pass_std_cb,
+ "Forward stdout",
+ NULL
+ },
+ {
+ "stderr",
+ 0,
+ G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_pass_std_cb,
+ "Forward stderr",
+ NULL
+ },
+ {
+ "fd",
+ 0,
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_pass_fd_cb,
+ N_("Forward file descriptor"),
+ /* FD = file descriptor */
+ N_("FD")
+ },
+ {
"zoom",
0,
0,
diff --git a/src/terminal-options.h b/src/terminal-options.h
index 2285b14..1d120b5 100644
--- a/src/terminal-options.h
+++ b/src/terminal-options.h
@@ -25,6 +25,8 @@
#include <glib.h>
#include <stdio.h>
+#include <gio/gunixfdlist.h>
+
#include "terminal-profiles-list.h"
G_BEGIN_DECLS
@@ -100,6 +102,8 @@ typedef struct
char *title;
char *working_dir;
double zoom;
+ GUnixFDList *fd_list;
+ GArray *fd_array;
guint zoom_set : 1;
guint active : 1;
} InitialTab;
diff --git a/src/terminal.c b/src/terminal.c
index 30b8241..41e5341 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -318,18 +318,21 @@ handle_options (TerminalFactory *factory,
argv = it->exec_argv ? it->exec_argv : options->exec_argv,
argc = argv ? g_strv_length (argv) : 0;
+ PassFdElement *fd_array = it->fd_array ? (PassFdElement*)it->fd_array->data : NULL;
+ gsize fd_array_len = it->fd_array ? it->fd_array->len : 0;
+
terminal_client_append_exec_options (&builder,
it->working_dir ? it->working_dir
: options->default_working_dir,
- NULL, 0, /* FD array */
+ fd_array, fd_array_len,
argc == 0);
if (!terminal_receiver_call_exec_sync (receiver,
g_variant_builder_end (&builder),
g_variant_new_bytestring_array ((const char * const *)
argv, argc),
- NULL /* infdlist */, NULL /* outfdlist */,
- NULL /* cancellable */,
- &err)) {
+ it->fd_list, NULL /* outfdlist */,
+ NULL /* cancellable */,
+ &err)) {
if (handle_exec_error (err, service_name))
return FALSE;
else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]