protected function executeProcess($command, $cwd, $stdin, &$stdout, &$stderr = NULL)
{
$descriptorSpec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
$process = proc_open($command, $descriptorSpec, $pipes, $cwd);
$txOff = 0;
$txLen = strlen($stdin);
$stdout = '';
$stderr = '';
$stdoutDone = FALSE;
$stderrDone = FALSE;
// Make stdin/stdout/stderr non-blocking
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
if ($txLen == 0) {
fclose($pipes[0]);
}
while (TRUE) {
// The program's stdout/stderr
$rx = array();
if (!$stdoutDone) {
$rx[] = $pipes[1];
}
if (!$stderrDone) {
$rx[] = $pipes[2];
}
// The program's stdin
$tx = array();
if ($txOff < $txLen) {
$tx[] = $pipes[0];
}
$ex = NULL;
// Block til r/w possible
stream_select($rx, $tx, $ex, NULL, NULL);
if (!empty($tx)) {
$txRet = fwrite($pipes[0], substr($stdin, $txOff, 8192));
if ($txRet !== FALSE) {
$txOff += $txRet;
}
if ($txOff >= $txLen) {
fclose($pipes[0]);
}
}
foreach ($rx as $r) {
if ($r == $pipes[1]) {
$stdout .= fread($pipes[1], 8192);
if (feof($pipes[1])) {
fclose($pipes[1]);
$stdoutDone = TRUE;
}
} elseif ($r == $pipes[2]) {
$stderr .= fread($pipes[2], 8192);
if (feof($pipes[2])) {
fclose($pipes[2]);
$stderrDone = TRUE;
}
}
}
if (!is_resource($process)) {
break;
}
if ($txOff >= $txLen && $stdoutDone && $stderrDone) {
break;
}
}
return proc_close($process);
}