[X2Go-Commits] [libx2goclient] 11/44: src/x2goclient-network-ssh.{c, h}: split out OpenSSH client process spawning into a separate function called x2goclient_network_ssh_start_sshcmd ().

git-admin at x2go.org git-admin at x2go.org
Fri Sep 18 01:55:38 CEST 2020


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository libx2goclient.

commit d8ec4e0cc640252144d7c5444340374623d0e50f
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Thu Jul 30 14:39:48 2020 +0200

    src/x2goclient-network-ssh.{c,h}: split out OpenSSH client process spawning into a separate function called x2goclient_network_ssh_start_sshcmd ().
    
    This is in preparation of spawning other OpenSSH client processes (like
    control processes for the master connection), so it's not a straight
    copy, but something more sophisticated.
    
    Also, the code is being reworked to not use an instance variable for the
    process but to keep it local, since we're in the process of changing
    this as well.
---
 src/x2goclient-network-ssh.c | 187 +++++++++++++++++++++++++++++--------------
 src/x2goclient-network-ssh.h |   2 +
 2 files changed, 130 insertions(+), 59 deletions(-)

diff --git a/src/x2goclient-network-ssh.c b/src/x2goclient-network-ssh.c
index 7344546..48a75a4 100644
--- a/src/x2goclient-network-ssh.c
+++ b/src/x2goclient-network-ssh.c
@@ -137,6 +137,7 @@ static void x2goclient_network_ssh_log_std_str (const gchar * const str, const g
 static gboolean x2goclient_network_ssh_gptrarray_to_string (GPtrArray * const arr, const gchar * const prelude, gchar ** const ret_str);
 static void x2goclient_network_ssh_gptrarray_print_debug (GPtrArray * const arr, const gchar * const prelude, const gchar * const desc);
 static gboolean x2goclient_network_ssh_sshcmd_add_host_port (X2GoClientNetworkSSH * const self, GPtrArray * const ssh_cmd, GError ** const gerr);
+static gboolean x2goclient_network_ssh_start_sshcmd (X2GoClientNetworkSSH * const self, const GPtrArray * const ssh_cmd, GError ** const gerr, const gboolean master);
 
 
 static void x2goclient_network_ssh_class_init (X2GoClientNetworkSSHClass * const klass) {
@@ -874,65 +875,7 @@ static gboolean x2goclient_network_ssh_parent_connect (X2GoClientNetwork * const
     x2goclient_network_ssh_gptrarray_print_debug (ssh_cmd, "Would try to connect via:", "OpenSSH client command");
 
     g_log (NULL, G_LOG_LEVEL_DEBUG, "Launching!");
-    GError *ssh_err = NULL;
-    GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
-
-    if (self->openssh_bugs->backgrounding_keeps_stderr) {
-      flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE;
-    }
-    else {
-      flags |= G_SUBPROCESS_FLAGS_STDERR_PIPE;
-    }
-
-    self->master_conn = g_subprocess_newv ((const gchar* const*)(ssh_cmd->pdata), flags, &ssh_err);
-
-    ret = (self->master_conn != NULL);
-
-    if (ret) {
-      g_log (NULL, G_LOG_LEVEL_DEBUG, "Process started/executed successfully!");
-
-      if (ssh_err) {
-        g_log (NULL, G_LOG_LEVEL_WARNING, "Successful execution, but ssh_err set? Weird, here's the message: %s", ssh_err->message);
-      }
-
-      GCancellable *master_conn_comm_cancel = g_cancellable_new ();
-      g_clear_error (&ssh_err);
-      GBytes *ssh_stdout = NULL, *ssh_stderr = NULL;
-      if (!(g_subprocess_communicate (self->master_conn, NULL, master_conn_comm_cancel, &ssh_stdout, &ssh_stderr, &ssh_err))) {
-        g_log (NULL, G_LOG_LEVEL_CRITICAL, "Communication with master connection subprocess failed: %s", ssh_err->message);
-      }
-      else {
-        gsize ssh_stdout_size = 0, ssh_stderr_size = 0;
-
-        const gchar *ssh_stdout_str = NULL, *ssh_stderr_str = NULL;
-        if (ssh_stdout) {
-          ssh_stdout_str = g_bytes_get_data (ssh_stdout, &ssh_stdout_size);
-        }
-        else {
-          g_log (NULL, G_LOG_LEVEL_WARNING, "Master connection does not have stdout pipe attached, but we expect it to be available. Ignoring output on stdout.");
-        }
-
-        if (ssh_stderr) {
-          ssh_stderr_str = g_bytes_get_data (ssh_stderr, &ssh_stderr_size);
-        }
-        else if (!(self->openssh_bugs->backgrounding_keeps_stderr)) {
-          g_log (NULL, G_LOG_LEVEL_WARNING, "Master connection does not have stderr pipe attached, but we expect it to be available. Ignoring output on stderr.");
-        }
-
-        x2goclient_network_ssh_log_std_str (ssh_stdout_str, ssh_stdout_size, 0);
-        x2goclient_network_ssh_log_std_str (ssh_stderr_str, ssh_stderr_size, 1);
-
-        g_bytes_unref (ssh_stdout);
-        g_bytes_unref (ssh_stderr);
-      }
-
-      g_clear_error (&ssh_err);
-    }
-    else {
-      g_log (NULL, G_LOG_LEVEL_CRITICAL, "Process didn't execute/start successfully!\nError:\n>>>%s<<<", ssh_err->message);
-    }
-
-    g_clear_error (&ssh_err);
+    self->active_master_conn = ret = x2goclient_network_ssh_start_sshcmd (self, ssh_cmd, gerr, TRUE);
   }
 
   g_free (session_path);
@@ -1283,3 +1226,129 @@ static gboolean x2goclient_network_ssh_sshcmd_add_host_port (X2GoClientNetworkSS
 
   return (ret);
 }
+
+static gboolean x2goclient_network_ssh_start_sshcmd (X2GoClientNetworkSSH * const self, const GPtrArray * const ssh_cmd, GError ** const gerr, const gboolean master) {
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (X2GOCLIENT_IS_NETWORK_SSH (self), ret);
+  g_return_val_if_fail (ssh_cmd, ret);
+  g_return_val_if_fail (((NULL == gerr) || (NULL == *gerr)), ret);
+
+  ret = TRUE;
+
+  GError *proc_err = NULL;
+  GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
+
+  if ((master) && (self->openssh_bugs->backgrounding_keeps_stderr)) {
+    flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE;
+  }
+  else {
+    flags |= G_SUBPROCESS_FLAGS_STDERR_PIPE;
+  }
+
+  GSubprocess *proc = g_subprocess_newv ((const gchar* const*)(ssh_cmd->pdata), flags, &proc_err);
+
+  ret = (proc != NULL);
+
+  if (ret) {
+    g_log (NULL, G_LOG_LEVEL_DEBUG, "OpenSSH client process started/executed successfully!");
+
+    if (proc_err) {
+      g_log (NULL, G_LOG_LEVEL_WARNING, "Successful execution, but ssh_err set? Weird, here's the message: %s", proc_err->message);
+    }
+
+    GCancellable *proc_comm_cancel = g_cancellable_new ();
+    g_clear_error (&proc_err);
+    GBytes *proc_stdout = NULL, *proc_stderr = NULL;
+    if (!(g_subprocess_communicate (proc, NULL, proc_comm_cancel, &proc_stdout, &proc_stderr, &proc_err))) {
+      const gchar *desc = "master connection";
+
+      if (!(master)) {
+        desc = "control command";
+      }
+
+      g_propagate_prefixed_error (gerr, proc_err, "Communication with %s subprocess failed: ", desc);
+
+      if (!(gerr)) {
+        g_log (NULL, G_LOG_LEVEL_WARNING, "Communication with %s subprocess failed: %s", desc, proc_err->message);
+      }
+
+      ret = FALSE;
+    }
+    else {
+      /* Okay, everything seems to have worked out correctly, read the data. */
+      gsize proc_stdout_size = 0, proc_stderr_size = 0;
+      const gchar *proc_stdout_str = NULL, *proc_stderr_str = NULL;
+
+      const gchar *desc = "Master connection";
+
+      if (!(master)) {
+        desc = "Control command";
+      }
+
+      if (proc_stdout) {
+        proc_stdout_str = g_bytes_get_data (proc_stdout, &proc_stdout_size);
+      }
+      else {
+        g_log (NULL, G_LOG_LEVEL_WARNING, "%s does not have stdout pipe attached, but we expect it to be available. Ignoring output on stdout.", desc);
+      }
+
+      if (proc_stderr) {
+        proc_stderr_str = g_bytes_get_data (proc_stderr, &proc_stderr_size);
+      }
+      else if ((!(master)) || (!(self->openssh_bugs->backgrounding_keeps_stderr))) {
+        g_log (NULL, G_LOG_LEVEL_WARNING, "%s does not have stderr pipe attached, but we expect it to be available. Ignoring output on stderr.", desc);
+      }
+
+      x2goclient_network_ssh_log_std_str (proc_stdout_str, proc_stdout_size, 0);
+      x2goclient_network_ssh_log_std_str (proc_stderr_str, proc_stderr_size, 1);
+
+      g_bytes_unref (proc_stdout);
+      g_bytes_unref (proc_stderr);
+
+      /* This should be true, but I guess it doesn't hurt to check.
+       *
+       * Also, this should really be something like gassert (), but that
+       * doesn't exist and the existing warning and assertion
+       * functions/macros are not up to the task (since they return from
+       * the calling function, leaving objects around).
+       *
+       * assert () itself likewise is not useful in this case because such
+       * assertions can be turned off.
+       */
+      if (!(g_subprocess_get_if_exited (proc))) {
+        g_set_error (gerr, X2GOCLIENT_NETWORK_SSH_ERROR, X2GOCLIENT_NETWORK_SSH_ERROR_PROC_COMMUNICATE_TRUE_RETVAL_UNAVAILABLE, "%s spawned successfully, but exit status not available.", desc);
+
+        if (!(gerr)) {
+          g_log (NULL, G_LOG_LEVEL_WARNING, "%s spawned successfully, but exit status not available.", desc);
+        }
+
+        ret = FALSE;
+      }
+      else {
+        /* Check process return value. */
+        const gint exit_status = g_subprocess_get_exit_status (proc);
+
+        ret = (!(exit_status));
+
+        if (!(ret)) {
+          g_set_error (gerr, X2GOCLIENT_NETWORK_SSH_ERROR, X2GOCLIENT_NETWORK_SSH_ERROR_PROC_RETVAL_NONZERO, "%s failed to execute successfully, return value: %d.", desc, exit_status);
+
+          if (!(gerr)) {
+            g_log (NULL, G_LOG_LEVEL_WARNING, "%s failed to execute successfully, return value: %d.", desc, exit_status);
+          }
+        }
+      }
+    }
+  }
+  else {
+    g_log (NULL, G_LOG_LEVEL_CRITICAL, "Process didn't execute/start successfully!\nError:\n>>>%s<<<", proc_err->message);
+  }
+
+  g_object_unref (proc);
+  proc = NULL;
+
+  g_clear_error (&proc_err);
+
+  return (ret);
+}
diff --git a/src/x2goclient-network-ssh.h b/src/x2goclient-network-ssh.h
index 5fa346d..690d550 100644
--- a/src/x2goclient-network-ssh.h
+++ b/src/x2goclient-network-ssh.h
@@ -67,6 +67,8 @@ enum {
   X2GOCLIENT_NETWORK_SSH_ERROR_CONNECT_NATIVE_FETCH,
   X2GOCLIENT_NETWORK_SSH_ERROR_CONNECT_SOCK_ADDR_UNKNOWN,
   X2GOCLIENT_NETWORK_SSH_ERROR_CONNECT_OPTIONS_INVALID,
+  X2GOCLIENT_NETWORK_SSH_ERROR_PROC_COMMUNICATE_TRUE_RETVAL_UNAVAILABLE,
+  X2GOCLIENT_NETWORK_SSH_ERROR_PROC_RETVAL_NONZERO,
 };
 
 

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git


More information about the x2go-commits mailing list