Commit d8ec4e0c authored by Mihai Moldovan's avatar Mihai Moldovan
Browse files

src/x2goclient-network-ssh.{c,h}: split out OpenSSH client process spawning...

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.
parent b98389b0
......@@ -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);
}
......@@ -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,
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment