8 * Sudo command, if the cmd needs escalated privileges
14 * Executable of the cmd
20 * Passthrough cmd output
32 * Return code of cmd run
38 * @param string $command
41 public function __construct($command, $verbose = false) {
42 $this->command
= $command;
43 $this->verbose
= $verbose;
45 /* interrupt output stream */
52 * (Re-)set sudo command
55 public function setSu($sudo = false) {
60 * Execute a program with escalated privileges handling interactive password prompt
61 * @param string $command
62 * @param string $output
65 private function suExec($command, &$output, &$status) {
66 if (!($proc = proc_open($command, [STDIN
,["pipe","w"],["pipe","w"]], $pipes))) {
68 throw new \
Exception("Failed to run {$command}");
72 while (!feof($stdout)) {
73 $R = [$stdout]; $W = []; $E = [];
74 if (!stream_select($R, $W, $E, null)) {
77 $data = fread($stdout, 0x1000);
78 /* only check a few times */
80 if (stristr($data, "password")) {
81 printf("\n%s", $data);
86 $status = proc_close($proc);
94 public function run(array $args = null) {
95 $exec = escapeshellcmd($this->command
);
97 $exec .= " ". implode(" ", array_map("escapeshellarg", (array) $args));
101 $this->suExec(sprintf($this->sudo
." 2>&1", $exec), $this->output
, $this->status
);
102 } elseif ($this->verbose
) {
103 ob_start(function($s) {
107 passthru($exec, $this->status
);
110 exec($exec ." 2>&1", $output, $this->status
);
111 $this->output
= implode("\n", $output);
115 throw new \
Exception("Command {$this->command} failed ({$this->status})");
120 * Retrieve exit code of cmd run
123 public function getStatus() {
128 * Retrieve output of cmd run
131 public function getOutput() {
132 return $this->output
;