command = $command; $this->verbose = $verbose; } /** * (Re-)set sudo command * @param string $sudo */ public function setSu($sudo = false) { $this->sudo = $sudo; } /** * Execute a program with escalated privileges handling interactive password prompt * @param string $command * @param string $output * @param int $status */ private function suExec($command, &$output, &$status) { if (!($proc = proc_open($command, [STDIN,["pipe","w"],["pipe","w"]], $pipes))) { $status = -1; throw new Exception("Failed to run {$command}"); } $stdout = $pipes[1]; $passwd = 0; while (!feof($stdout)) { $R = [$stdout]; $W = []; $E = []; if (!stream_select($R, $W, $E, null)) { continue; } $data = fread($stdout, 0x1000); /* only check a few times */ if ($passwd++ < 10) { if (stristr($data, "password")) { printf("\n%s", $data); } } $output .= $data; } $status = proc_close($proc); } /** * Run the command * @param array $args * @return \pharext\ExecCmd self * @throws \pharext\Exception */ public function run(array $args = null) { $exec = escapeshellcmd($this->command); if ($args) { $exec .= " ". implode(" ", array_map("escapeshellarg", (array) $args)); } if ($this->sudo) { $this->suExec(sprintf($this->sudo." 2>&1", $exec), $this->output, $this->status); } elseif ($this->verbose) { ob_start(function($s) { $this->output .= $s; return $s; }, 1); passthru($exec, $this->status); ob_end_flush(); } else { exec($exec ." 2>&1", $output, $this->status); $this->output = implode("\n", $output); } if ($this->status) { throw new Exception("Command {$exec} failed ({$this->status})"); } return $this; } /** * Retrieve exit code of cmd run * @return int */ public function getStatus() { return $this->status; } /** * Retrieve output of cmd run * @return string */ public function getOutput() { return $this->output; } }