diff --git a/Makefile.in b/Makefile.in
index cbe29f51..53ede982 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -50,8 +50,8 @@ $(info Building against PostgreSQL $(MAJORVERSION))
REPMGR_CLIENT_OBJS = repmgr-client.o \
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-witness.o \
repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o repmgr-action-daemon.o \
- configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o
-REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o compat.o
+ configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o sysutils.o
+REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o compat.o sysutils.o
DATE=$(shell date "+%Y-%m-%d")
repmgr_version.h: repmgr_version.h.in
diff --git a/repmgr-action-cluster.c b/repmgr-action-cluster.c
index 2c2e6026..cbe02f74 100644
--- a/repmgr-action-cluster.c
+++ b/repmgr-action-cluster.c
@@ -1161,6 +1161,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
(void) remote_command(host,
runtime_options.remote_user,
command.data,
+ config_file_options.ssh_options,
&command_output);
p = command_output.data;
@@ -1373,6 +1374,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, Item
(void) remote_command(host,
runtime_options.remote_user,
quoted_command.data,
+ config_file_options.ssh_options,
&command_output);
free_conninfo_params(&remote_conninfo);
diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c
index ebe75ec9..55850bb1 100644
--- a/repmgr-action-standby.c
+++ b/repmgr-action-standby.c
@@ -3402,6 +3402,7 @@ do_standby_switchover(void)
command_success = remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -3465,6 +3466,7 @@ do_standby_switchover(void)
command_success = remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -3692,6 +3694,7 @@ do_standby_switchover(void)
command_success = remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -3744,6 +3747,7 @@ do_standby_switchover(void)
command_success = remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -4173,6 +4177,7 @@ do_standby_switchover(void)
(void) remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -4241,6 +4246,7 @@ do_standby_switchover(void)
command_success = remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -4461,6 +4467,7 @@ do_standby_switchover(void)
command_success = remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
@@ -4569,6 +4576,7 @@ do_standby_switchover(void)
success = remote_command(host,
runtime_options.remote_user,
remote_command_str.data,
+ config_file_options.ssh_options,
&command_output);
termPQExpBuffer(&remote_command_str);
diff --git a/repmgr-client-global.h b/repmgr-client-global.h
index ded775b0..e7c70b37 100644
--- a/repmgr-client-global.h
+++ b/repmgr-client-global.h
@@ -224,8 +224,6 @@ extern int check_server_version(PGconn *conn, char *server_type, bool exit_on_er
extern void check_93_config(void);
extern bool create_repmgr_extension(PGconn *conn);
extern int test_ssh_connection(char *host, char *remote_user);
-extern bool local_command(const char *command, PQExpBufferData *outputbuf);
-extern bool local_command_simple(const char *command, PQExpBufferData *outputbuf);
extern standy_clone_mode get_standby_clone_mode(void);
@@ -238,8 +236,6 @@ extern char *make_pg_path(const char *file);
extern void get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privileged_conn);
-extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
-
extern void make_remote_repmgr_path(PQExpBufferData *outputbuf, t_node_info *remote_node_record);
extern void make_repmgrd_path(PQExpBufferData *output_buf);
diff --git a/repmgr-client.c b/repmgr-client.c
index 8b610b62..0df6f420 100644
--- a/repmgr-client.c
+++ b/repmgr-client.c
@@ -97,8 +97,6 @@ t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
static ItemList cli_errors = {NULL, NULL};
static ItemList cli_warnings = {NULL, NULL};
-static bool _local_command(const char *command, PQExpBufferData *outputbuf, bool simple);
-
int
main(int argc, char **argv)
{
@@ -2399,75 +2397,6 @@ test_ssh_connection(char *host, char *remote_user)
-/*
- * Execute a command locally. "outputbuf" should either be an
- * initialised PQexpbuffer, or NULL
- */
-bool
-local_command(const char *command, PQExpBufferData *outputbuf)
-{
- return _local_command(command, outputbuf, false);
-}
-
-
-bool
-local_command_simple(const char *command, PQExpBufferData *outputbuf)
-{
- return _local_command(command, outputbuf, true);
-}
-
-
-static bool
-_local_command(const char *command, PQExpBufferData *outputbuf, bool simple)
-{
- FILE *fp = NULL;
- char output[MAXLEN];
- int retval = 0;
- bool success;
-
- log_verbose(LOG_DEBUG, "executing:\n %s", command);
-
- if (outputbuf == NULL)
- {
- retval = system(command);
- return (retval == 0) ? true : false;
- }
-
- fp = popen(command, "r");
-
- if (fp == NULL)
- {
- log_error(_("unable to execute local command:\n%s"), command);
- return false;
- }
-
-
- while (fgets(output, MAXLEN, fp) != NULL)
- {
- appendPQExpBuffer(outputbuf, "%s", output);
-
- if (!feof(fp) && simple == false)
- {
- break;
- }
- }
-
- retval = pclose(fp);
-
- /* */
- success = (WEXITSTATUS(retval) == 0 || WEXITSTATUS(retval) == 141) ? true : false;
-
- log_verbose(LOG_DEBUG, "result of command was %i (%i)", WEXITSTATUS(retval), retval);
-
- if (outputbuf->data != NULL && outputbuf->data[0] != '\0')
- log_verbose(LOG_DEBUG, "local_command(): output returned was:\n%s", outputbuf->data);
- else
- log_verbose(LOG_DEBUG, "local_command(): no output returned");
-
- return success;
-}
-
-
/*
* get_superuser_connection()
*
@@ -2674,78 +2603,6 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
}
-/*
- * Execute a command via ssh on the remote host.
- *
- * TODO: implement SSH calls using libssh2.
- */
-bool
-remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf)
-{
- FILE *fp;
- char ssh_command[MAXLEN] = "";
- PQExpBufferData ssh_host;
-
- char output[MAXLEN] = "";
-
- initPQExpBuffer(&ssh_host);
-
- if (*user != '\0')
- {
- appendPQExpBuffer(&ssh_host, "%s@", user);
- }
-
- appendPQExpBuffer(&ssh_host, "%s", host);
-
- maxlen_snprintf(ssh_command,
- "ssh -o Batchmode=yes %s %s %s",
- config_file_options.ssh_options,
- ssh_host.data,
- command);
-
- termPQExpBuffer(&ssh_host);
-
- log_debug("remote_command():\n %s", ssh_command);
-
- fp = popen(ssh_command, "r");
-
- if (fp == NULL)
- {
- log_error(_("unable to execute remote command:\n %s"), ssh_command);
- return false;
- }
-
- if (outputbuf != NULL)
- {
- /* TODO: better error handling */
- while (fgets(output, MAXLEN, fp) != NULL)
- {
- appendPQExpBuffer(outputbuf, "%s", output);
- }
- }
- else
- {
- while (fgets(output, MAXLEN, fp) != NULL)
- {
- if (!feof(fp))
- {
- break;
- }
- }
- }
-
- pclose(fp);
-
- if (outputbuf != NULL)
- {
- if (outputbuf->data != NULL && outputbuf->data[0] != '\0')
- log_verbose(LOG_DEBUG, "remote_command(): output returned was:\n%s", outputbuf->data);
- else
- log_verbose(LOG_DEBUG, "remote_command(): no output returned");
- }
-
- return true;
-}
void
diff --git a/repmgr.h b/repmgr.h
index deb8c488..25586020 100644
--- a/repmgr.h
+++ b/repmgr.h
@@ -41,6 +41,7 @@
#include "configfile.h"
#include "dbutils.h"
#include "log.h"
+#include "sysutils.h"
#define MIN_SUPPORTED_VERSION "9.3"
#define MIN_SUPPORTED_VERSION_NUM 90300
diff --git a/sysutils.c b/sysutils.c
new file mode 100644
index 00000000..69613957
--- /dev/null
+++ b/sysutils.c
@@ -0,0 +1,178 @@
+/*
+ * sysutils.c
+ *
+ * Copyright (c) 2ndQuadrant, 2010-2019
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "repmgr.h"
+
+static bool _local_command(const char *command, PQExpBufferData *outputbuf, bool simple, int *return_value);
+
+
+/*
+ * Execute a command locally. "outputbuf" should either be an
+ * initialised PQexpbuffer, or NULL
+ */
+bool
+local_command(const char *command, PQExpBufferData *outputbuf)
+{
+ return _local_command(command, outputbuf, false, NULL);
+}
+
+bool
+local_command_return_value(const char *command, PQExpBufferData *outputbuf, int *return_value)
+{
+ return _local_command(command, outputbuf, false, return_value);
+}
+
+
+bool
+local_command_simple(const char *command, PQExpBufferData *outputbuf)
+{
+ return _local_command(command, outputbuf, true, NULL);
+}
+
+
+static bool
+_local_command(const char *command, PQExpBufferData *outputbuf, bool simple, int *return_value)
+{
+ FILE *fp = NULL;
+ char output[MAXLEN];
+ int retval = 0;
+ bool success;
+
+ log_verbose(LOG_DEBUG, "executing:\n %s", command);
+
+ if (outputbuf == NULL)
+ {
+ retval = system(command);
+
+ if (return_value != NULL)
+ *return_value = WEXITSTATUS(retval);
+
+ return (retval == 0) ? true : false;
+ }
+
+ fp = popen(command, "r");
+
+ if (fp == NULL)
+ {
+ log_error(_("unable to execute local command:\n%s"), command);
+ return false;
+ }
+
+
+ while (fgets(output, MAXLEN, fp) != NULL)
+ {
+ appendPQExpBuffer(outputbuf, "%s", output);
+
+ if (!feof(fp) && simple == false)
+ {
+ break;
+ }
+ }
+
+ retval = pclose(fp);
+
+ /* */
+ success = (WEXITSTATUS(retval) == 0 || WEXITSTATUS(retval) == 141) ? true : false;
+
+ log_verbose(LOG_DEBUG, "result of command was %i (%i)", WEXITSTATUS(retval), retval);
+
+ if (return_value != NULL)
+ *return_value = WEXITSTATUS(retval);
+
+ if (outputbuf->data != NULL && outputbuf->data[0] != '\0')
+ log_verbose(LOG_DEBUG, "local_command(): output returned was:\n%s", outputbuf->data);
+ else
+ log_verbose(LOG_DEBUG, "local_command(): no output returned");
+
+ return success;
+}
+
+
+/*
+ * Execute a command via ssh on the remote host.
+ *
+ * TODO: implement SSH calls using libssh2.
+ */
+bool
+remote_command(const char *host, const char *user, const char *command, const char *ssh_options, PQExpBufferData *outputbuf)
+{
+ FILE *fp;
+ char ssh_command[MAXLEN] = "";
+ PQExpBufferData ssh_host;
+
+ char output[MAXLEN] = "";
+
+ initPQExpBuffer(&ssh_host);
+
+ if (*user != '\0')
+ {
+ appendPQExpBuffer(&ssh_host, "%s@", user);
+ }
+
+ appendPQExpBuffer(&ssh_host, "%s", host);
+
+ maxlen_snprintf(ssh_command,
+ "ssh -o Batchmode=yes %s %s %s",
+ ssh_options,
+ ssh_host.data,
+ command);
+
+ termPQExpBuffer(&ssh_host);
+
+ log_debug("remote_command():\n %s", ssh_command);
+
+ fp = popen(ssh_command, "r");
+
+ if (fp == NULL)
+ {
+ log_error(_("unable to execute remote command:\n %s"), ssh_command);
+ return false;
+ }
+
+ if (outputbuf != NULL)
+ {
+ /* TODO: better error handling */
+ while (fgets(output, MAXLEN, fp) != NULL)
+ {
+ appendPQExpBuffer(outputbuf, "%s", output);
+ }
+ }
+ else
+ {
+ while (fgets(output, MAXLEN, fp) != NULL)
+ {
+ if (!feof(fp))
+ {
+ break;
+ }
+ }
+ }
+
+ pclose(fp);
+
+ if (outputbuf != NULL)
+ {
+ if (outputbuf->data != NULL && outputbuf->data[0] != '\0')
+ log_verbose(LOG_DEBUG, "remote_command(): output returned was:\n%s", outputbuf->data);
+ else
+ log_verbose(LOG_DEBUG, "remote_command(): no output returned");
+ }
+
+ return true;
+}
diff --git a/sysutils.h b/sysutils.h
new file mode 100644
index 00000000..92d114e6
--- /dev/null
+++ b/sysutils.h
@@ -0,0 +1,28 @@
+/*
+ * sysutils.h
+ * Copyright (c) 2ndQuadrant, 2010-2019
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _SYSUTILS_H_
+#define _SYSUTILS_H_
+
+extern bool local_command(const char *command, PQExpBufferData *outputbuf);
+extern bool local_command_return_value(const char *command, PQExpBufferData *outputbuf, int *return_value);
+extern bool local_command_simple(const char *command, PQExpBufferData *outputbuf);
+
+extern bool remote_command(const char *host, const char *user, const char *command, const char *ssh_options, PQExpBufferData *outputbuf);
+
+#endif /* _SYSUTILS_H_ */