mirror of
https://github.com/danog/process.git
synced 2024-12-02 09:37:55 +01:00
Pass command via STDIN on Windows
This commit is contained in:
parent
1ccc4837d4
commit
0e57b8d379
Binary file not shown.
Binary file not shown.
@ -6,7 +6,10 @@ use Amp\ByteStream\Message;
|
||||
use Amp\Process\Process;
|
||||
|
||||
Amp\Loop::run(function () {
|
||||
$process = new Process("echo 'Hello, world!'");
|
||||
// "echo" is a shell internal command on Windows and doesn't work.
|
||||
$command = DIRECTORY_SEPARATOR === "\\" ? "cmd /c echo Hello World!" : "echo 'Hello, world!'";
|
||||
|
||||
$process = new Process($command);
|
||||
$process->start();
|
||||
|
||||
echo yield new Message($process->getStdout());
|
||||
|
@ -9,6 +9,7 @@ use function Amp\Promise\all;
|
||||
function show_process_output(Process $process): \Generator
|
||||
{
|
||||
$stream = $process->getStdout();
|
||||
|
||||
while (null !== $chunk = yield $stream->read()) {
|
||||
echo $chunk;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ Amp\Loop::run(function () {
|
||||
$process->start();
|
||||
|
||||
$stream = $process->getStdout();
|
||||
|
||||
while (null !== $chunk = yield $stream->read()) {
|
||||
echo $chunk;
|
||||
}
|
||||
|
@ -6,7 +6,12 @@ use Amp\ByteStream\Message;
|
||||
use Amp\Process\Process;
|
||||
|
||||
Amp\Loop::run(function () {
|
||||
$process = new Process('read ; echo "$REPLY"');
|
||||
if (DIRECTORY_SEPARATOR === "\\") {
|
||||
echo "This example doesn't work on Windows." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$process = new Process('read; echo "$REPLY"');
|
||||
$process->start();
|
||||
|
||||
/* send to stdin */
|
||||
|
@ -27,7 +27,7 @@ final class Runner implements ProcessRunner {
|
||||
|
||||
private $socketConnector;
|
||||
|
||||
private function makeCommand(string $command, string $workingDirectory): string {
|
||||
private function makeCommand(string $workingDirectory): string {
|
||||
$result = sprintf(
|
||||
'%s --address=%s --port=%d --token-size=%d',
|
||||
\escapeshellarg(self::WRAPPER_EXE_PATH),
|
||||
@ -40,8 +40,6 @@ final class Runner implements ProcessRunner {
|
||||
$result .= ' ' . \escapeshellarg('--cwd=' . \rtrim($workingDirectory, '\\'));
|
||||
}
|
||||
|
||||
$result .= ' ' . $command;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -51,12 +49,14 @@ final class Runner implements ProcessRunner {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function start(string $command, string $cwd = null, array $env = [], array $options = []): ProcessHandle {
|
||||
$command = $this->makeCommand($command, $cwd ?? '');
|
||||
if (strpos($command, "\0") !== false) {
|
||||
throw new ProcessException("Can't execute commands that contain null bytes.");
|
||||
}
|
||||
|
||||
$options['bypass_shell'] = true;
|
||||
|
||||
$handle = new Handle;
|
||||
$handle->proc = @\proc_open($command, self::FD_SPEC, $pipes, $cwd ?: null, $env ?: null, $options);
|
||||
$handle->proc = @\proc_open($this->makeCommand($cwd ?? ''), self::FD_SPEC, $pipes, $cwd ?: null, $env ?: null, $options);
|
||||
|
||||
if (!\is_resource($handle->proc)) {
|
||||
$message = "Could not start process";
|
||||
@ -74,16 +74,16 @@ final class Runner implements ProcessRunner {
|
||||
}
|
||||
|
||||
$securityTokens = \random_bytes(SocketConnector::SECURITY_TOKEN_SIZE * 6);
|
||||
$written = \fwrite($pipes[0], $securityTokens);
|
||||
$written = \fwrite($pipes[0], $securityTokens . "\0" . $command . "\0");
|
||||
|
||||
\fclose($pipes[0]);
|
||||
\fclose($pipes[1]);
|
||||
|
||||
if ($written !== SocketConnector::SECURITY_TOKEN_SIZE * 6) {
|
||||
if ($written !== SocketConnector::SECURITY_TOKEN_SIZE * 6 + \strlen($command) + 2) {
|
||||
\fclose($pipes[2]);
|
||||
\proc_close($handle->proc);
|
||||
|
||||
throw new ProcessException("Could not send security tokens to process wrapper");
|
||||
throw new ProcessException("Could not send security tokens / command to process wrapper");
|
||||
}
|
||||
|
||||
$handle->securityTokens = \str_split($securityTokens, SocketConnector::SECURITY_TOKEN_SIZE);
|
||||
|
@ -46,7 +46,7 @@ final class SocketConnector {
|
||||
Loop::unreference(Loop::onReadable($this->server, [$this, 'onServerSocketReadable']));
|
||||
}
|
||||
|
||||
private function failClientHandshake($socket, int $code): void {
|
||||
private function failClientHandshake($socket, int $code) {
|
||||
\fwrite($socket, \chr(SignalCode::HANDSHAKE_ACK) . \chr($code));
|
||||
\fclose($socket);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user