From c64fd5a43e694d9851381226380b29bc5e9918e7 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Tue, 27 Nov 2018 11:19:49 +0300 Subject: [PATCH] Add -ssh-options option --- src/pg_probackup.c | 6 ++++-- src/pg_probackup.h | 1 + src/utils/remote.c | 51 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/pg_probackup.c b/src/pg_probackup.c index ba2fb5e9..40573d2a 100644 --- a/src/pg_probackup.c +++ b/src/pg_probackup.c @@ -78,6 +78,7 @@ char *remote_host; char *remote_port; char *remote_proto = (char*)"ssh"; char *ssh_config; +char *ssh_options; bool is_remote_agent; bool is_remote_backup; @@ -178,8 +179,9 @@ static pgut_option options[] = { 's', 20, "remote-port", &remote_port, SOURCE_CMDLINE, }, { 's', 21, "remote-proto", &remote_proto, SOURCE_CMDLINE, }, { 's', 22, "ssh-config", &ssh_config, SOURCE_CMDLINE, }, - { 'b', 23, "agent", &is_remote_agent, SOURCE_CMDLINE, }, - { 'b', 24, "remote", &is_remote_backup, SOURCE_CMDLINE, }, + { 's', 23, "ssh-options", &ssh_options, SOURCE_CMDLINE, }, + { 'b', 24, "agent", &is_remote_agent, SOURCE_CMDLINE, }, + { 'b', 25, "remote", &is_remote_backup, SOURCE_CMDLINE, }, /* restore options */ { 's', 30, "time", &target_time, SOURCE_CMDLINE }, { 's', 31, "xid", &target_xid, SOURCE_CMDLINE }, diff --git a/src/pg_probackup.h b/src/pg_probackup.h index 59f6f6cd..9714785f 100644 --- a/src/pg_probackup.h +++ b/src/pg_probackup.h @@ -357,6 +357,7 @@ extern char *remote_port; extern char *remote_host; extern char *remote_proto; extern char *ssh_config; +extern char *ssh_options; extern const char *master_db; extern const char *master_host; extern const char *master_port; diff --git a/src/utils/remote.c b/src/utils/remote.c index b66332fb..e3272714 100644 --- a/src/utils/remote.c +++ b/src/utils/remote.c @@ -7,7 +7,8 @@ #include "pg_probackup.h" #include "file.h" -#define MAX_CMDLINE_LENGTH 4096 +#define MAX_CMDLINE_LENGTH 4096 +#define MAX_CMDLINE_OPTIONS 256 static int append_option(char* buf, size_t buf_size, size_t dst, char const* src) { @@ -21,11 +22,50 @@ static int append_option(char* buf, size_t buf_size, size_t dst, char const* src return dst + len + 1; } +static int split_options(int argc, char* argv[], int max_options, char* options) +{ + char* opt = options; + char in_quote = '\0'; + while (true) { + switch (*opt) { + case '\'': + case '\"': + if (!in_quote) { + in_quote = *opt++; + continue; + } + if (*opt == in_quote && *++opt != in_quote) { + in_quote = '\0'; + continue; + } + break; + case '\0': + if (opt != options) { + argv[argc++] = options; + if (argc >= max_options) + elog(ERROR, "Too much options"); + } + return argc; + case ' ': + argv[argc++] = options; + if (argc >= max_options) + elog(ERROR, "Too much options"); + *opt++ = '\0'; + options = opt; + continue; + default: + break; + } + opt += 1; + } + return argc; +} + int remote_execute(int argc, char* argv[], bool listen) { char cmd[MAX_CMDLINE_LENGTH]; size_t dst = 0; - char* ssh_argv[8]; + char* ssh_argv[MAX_CMDLINE_OPTIONS]; int ssh_argc; int i; int outfd[2]; @@ -34,14 +74,17 @@ int remote_execute(int argc, char* argv[], bool listen) ssh_argc = 0; ssh_argv[ssh_argc++] = remote_proto; - if (remote_port != 0) { + if (remote_port != NULL) { ssh_argv[ssh_argc++] = (char*)"-p"; ssh_argv[ssh_argc++] = remote_port; } - if (ssh_config != 0) { + if (ssh_config != NULL) { ssh_argv[ssh_argc++] = (char*)"-F"; ssh_argv[ssh_argc++] = ssh_config; } + if (ssh_options != NULL) { + ssh_argc = split_options(ssh_argc, ssh_argv, MAX_CMDLINE_OPTIONS, ssh_options); + } ssh_argv[ssh_argc++] = remote_host; ssh_argv[ssh_argc++] = cmd+1; ssh_argv[ssh_argc] = NULL;