diff --git a/src/Ssh/Exec.php b/src/Ssh/Exec.php index f951d37..4d3c0d7 100644 --- a/src/Ssh/Exec.php +++ b/src/Ssh/Exec.php @@ -13,6 +13,9 @@ */ class Exec extends Subsystem { + protected $cwd; + protected $storeCwd = false; + protected function createResource() { $this->resource = $this->getSessionResource(); @@ -20,18 +23,32 @@ protected function createResource() public function run($cmd, $pty = null, array $env = array(), $width = 80, $height = 25, $width_height_type = SSH2_TERM_UNIT_CHARS) { - $cmd .= ';echo -ne "[return_code:$?]"'; + if ($this->cwd && $this->storeCwd) { + $cmd = 'cd '.escapeshellarg($this->cwd).';'.$cmd; + } + + $cmd .= ';echo -ne "\\0" "$?" "\\0";pwd'; $stdout = ssh2_exec($this->getResource(), $cmd, $pty, $env, $width, $height, $width_height_type); $stderr = ssh2_fetch_stream($stdout, SSH2_STREAM_STDERR); stream_set_blocking($stderr, true); stream_set_blocking($stdout, true); $output = stream_get_contents($stdout); - preg_match('/\[return_code:(.*?)\]/', $output, $match); - if ((int) $match[1] !== 0) { - throw new RuntimeException(stream_get_contents($stderr), (int) $match[1]); + preg_match('/^(.*)\\0 (\d+) \\0([^\\0]+)$/s', $output, $match); + + list($_, $output, $retcode, $cwd) = $match; + + $this->cwd = rtrim($cwd, "\r\n"); + + if ((int) $retcode !== 0) { + throw new RuntimeException(stream_get_contents($stderr), (int) $retcode); } - return preg_replace('/\[return_code:(.*?)\]/', '', $output); + return $output; + } + + public function setStoreCwd($store) + { + $this->storeCwd = $store; } } diff --git a/tests/Ssh/FunctionalTests/ExecTest.php b/tests/Ssh/FunctionalTests/ExecTest.php index 3d5bd2d..30af351 100644 --- a/tests/Ssh/FunctionalTests/ExecTest.php +++ b/tests/Ssh/FunctionalTests/ExecTest.php @@ -58,5 +58,28 @@ public function testExecuteErrorOutput() $this->assertEquals('', trim($output)); } + + public function testExecuteWithStoreCwd() + { + $configuration = new Configuration('localhost'); + $authentication = new Password(TEST_USER, TEST_PASSWORD); + $session = new Session($configuration, $authentication); + + $exec = $session->getExec(); + $exec->setStoreCwd(true); + + $output = $exec->run('pwd'); + $this->assertEquals(getenv('HOME'), trim($output)); + + $exec->run('cd /'); + + $output = $exec->run('pwd'); + $this->assertEquals('/', trim($output)); + + $exec->run('cd ~'); + + $output = $exec->run('pwd'); + $this->assertEquals(getenv('HOME'), trim($output)); + } } - +