#include "SSH.h" #include "Launcher.h" #include "Utilities.h" #include #include #include #include #include #include namespace po = boost::program_options; using std::string; using std::vector; class SSHLauncher : public Launcher { public: SSHLauncher(po::variables_map& options); virtual ~SSHLauncher(); virtual bool Go(int timeout = 0); }; SSHLauncher::SSHLauncher(po::variables_map &options) : Launcher(options, ResourceFile::Format::percent_appledouble) { } SSHLauncher::~SSHLauncher() { } static void insertArgs(vector& args, po::variables_map& options, string name) { if(options.count(name)) { auto extraArgs = SplitArguments(options[name].as>()); args.insert(args.end(), extraArgs.begin(), extraArgs.end()); } } bool SSHLauncher::Go(int timeout) { std::vector args; args.push_back(options["ssh-host"].as()); insertArgs(args, options, "ssh-args"); args.push_back("--"); args.push_back(options["ssh-remote-path"].as()); insertArgs(args, options, "ssh-remote-args"); if(timeout) { args.push_back("--timeout"); args.push_back(boost::lexical_cast(timeout)); } args.push_back("-"); std::string program = options["ssh-path"].as(); std::vector argv; argv.push_back(program.c_str()); for(std::string& s : args) argv.push_back(s.c_str()); argv.push_back(NULL); int fd[2]; pipe(fd); const int READ_END = 0; const int WRITE_END = 1; pid_t pid = fork(); if(pid < 0) { perror("unable to fork"); return 1; } else if(pid == 0) { dup2(fd[READ_END], STDIN_FILENO); close(fd[WRITE_END]); close(fd[READ_END]); execvp(argv[0], const_cast (argv.data())); perror("exec failed"); std::cerr << "Tried to execute: " << program; for(auto a : args) std::cerr << " " << a; std::cerr << std::endl; _exit(1); } else { close(fd[READ_END]); std::ostringstream tmp; app.write(tmp, ResourceFile::Format::macbin); const std::string data = tmp.str(); write(fd[WRITE_END], data.data(), data.size()); close(fd[WRITE_END]); int wstatus; int result = 0; do { result = waitpid(pid, &wstatus, 0); } while(result == -1 && errno == EINTR); if(!WIFEXITED(wstatus)) { return false; } else { //int exitcode = WEXITSTATUS(wstatus); return true; } } } void SSH::GetOptions(options_description &desc) { desc.add_options() ("ssh-path", po::value()->default_value("ssh"),"ssh command to use") ("ssh-host", po::value(), "[username@]address of remote host") ("ssh-args", po::value>(), "additional arguments for ssh") ("ssh-remote-path", po::value()->default_value("LaunchAPPL"), "path to LaunchAPPL on remote host") ("ssh-remote-args", po::value>(), "additional arguments for LaunchAPPL on remote host") ; } bool SSH::CheckOptions(variables_map &options) { return options.count("ssh-host") != 0; } std::unique_ptr SSH::MakeLauncher(variables_map &options) { return std::unique_ptr(new SSHLauncher(options)); }