diff --git a/src/Transport.cpp b/src/Transport.cpp index eda61d200..6af97159b 100644 --- a/src/Transport.cpp +++ b/src/Transport.cpp @@ -27,8 +27,7 @@ #include #include -#include -#include +#include "util.h" #include "Transport.h" #include "TransportSSH.h" #include "TransportRSYNC.h" @@ -70,49 +69,7 @@ Transport* Transport::getTransport(const Uri& uri) //////////////////////////////////////////////////////////////////////////////// int Transport::execute() { - if (executable == "") - return -1; - - pid_t child_pid = fork(); - - if (child_pid == 0) - { - // this is done by the child process - char shell[] = "bash"; - char opt[] = "-c"; - - std::string cmdline = executable; - - std::vector ::iterator it; - for (it = arguments.begin(); it != arguments.end(); ++it) - { - std::string tmp = *it; - cmdline += " " + tmp; - } - - char** argv = new char*[4]; - argv[0] = shell; // sh - argv[1] = opt; // -c - argv[2] = (char*)cmdline.c_str(); // e.g. scp undo.data user@host:.task/ - argv[3] = NULL; // required by execv - - int ret = execvp(shell, argv); - delete[] argv; - - exit(ret); - } - else - { - // this is done by the parent process - int child_status; - - pid_t pid = waitpid(child_pid, &child_status, 0); - - if (pid == -1) - return -1; - else - return child_status; - } + return ::execute(executable, arguments); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index dbed968a3..647eebdf7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -380,3 +381,53 @@ std::string compressIds (const std::vector & ids) } //////////////////////////////////////////////////////////////////////////////// +// Run an external executable with execvp. This means stdio goes to +// the child process, so that it can receive user input (e.g. passwords). +// +int execute(const std::string& executable, std::vector arguments) +{ + if (executable == "") + return -1; + + pid_t child_pid = fork(); + + if (child_pid == 0) + { + // this is done by the child process + char shell[] = "bash"; + char opt[] = "-c"; + + std::string cmdline = executable; + + std::vector ::iterator it; + for (it = arguments.begin(); it != arguments.end(); ++it) + { + cmdline += " " + (std::string)*it; + } + + char** argv = new char*[4]; + argv[0] = shell; // bash + argv[1] = opt; // -c + argv[2] = (char*)cmdline.c_str(); // e.g. scp undo.data user@host:.task/ + argv[3] = NULL; // required by execv + + int ret = execvp(shell, argv); + delete[] argv; + + exit(ret); + } + else + { + // this is done by the parent process + int child_status; + + pid_t pid = waitpid(child_pid, &child_status, 0); + + if (pid == -1) + return -1; + else + return child_status; + } +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index 275d85bd7..0f61f4885 100644 --- a/src/util.h +++ b/src/util.h @@ -58,6 +58,7 @@ void delay (float); std::string formatBytes (size_t); int autoComplete (const std::string&, const std::vector&, std::vector&); const std::string uuid (); +int execute (const std::string&, std::vector); #ifdef SOLARIS #define LOCK_SH 1