1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeau/* 4*04fd306cSNickeau * This file is part of the Symfony package. 5*04fd306cSNickeau * 6*04fd306cSNickeau * (c) Fabien Potencier <fabien@symfony.com> 7*04fd306cSNickeau * 8*04fd306cSNickeau * For the full copyright and license information, please view the LICENSE 9*04fd306cSNickeau * file that was distributed with this source code. 10*04fd306cSNickeau */ 11*04fd306cSNickeau 12*04fd306cSNickeaunamespace Symfony\Component\Process\Pipes; 13*04fd306cSNickeau 14*04fd306cSNickeauuse Symfony\Component\Process\Process; 15*04fd306cSNickeau 16*04fd306cSNickeau/** 17*04fd306cSNickeau * UnixPipes implementation uses unix pipes as handles. 18*04fd306cSNickeau * 19*04fd306cSNickeau * @author Romain Neutron <imprec@gmail.com> 20*04fd306cSNickeau * 21*04fd306cSNickeau * @internal 22*04fd306cSNickeau */ 23*04fd306cSNickeauclass UnixPipes extends AbstractPipes 24*04fd306cSNickeau{ 25*04fd306cSNickeau private $ttyMode; 26*04fd306cSNickeau private $ptyMode; 27*04fd306cSNickeau private $haveReadSupport; 28*04fd306cSNickeau 29*04fd306cSNickeau public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport) 30*04fd306cSNickeau { 31*04fd306cSNickeau $this->ttyMode = $ttyMode; 32*04fd306cSNickeau $this->ptyMode = $ptyMode; 33*04fd306cSNickeau $this->haveReadSupport = $haveReadSupport; 34*04fd306cSNickeau 35*04fd306cSNickeau parent::__construct($input); 36*04fd306cSNickeau } 37*04fd306cSNickeau 38*04fd306cSNickeau public function __sleep(): array 39*04fd306cSNickeau { 40*04fd306cSNickeau throw new \BadMethodCallException('Cannot serialize '.__CLASS__); 41*04fd306cSNickeau } 42*04fd306cSNickeau 43*04fd306cSNickeau public function __wakeup() 44*04fd306cSNickeau { 45*04fd306cSNickeau throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); 46*04fd306cSNickeau } 47*04fd306cSNickeau 48*04fd306cSNickeau public function __destruct() 49*04fd306cSNickeau { 50*04fd306cSNickeau $this->close(); 51*04fd306cSNickeau } 52*04fd306cSNickeau 53*04fd306cSNickeau /** 54*04fd306cSNickeau * {@inheritdoc} 55*04fd306cSNickeau */ 56*04fd306cSNickeau public function getDescriptors(): array 57*04fd306cSNickeau { 58*04fd306cSNickeau if (!$this->haveReadSupport) { 59*04fd306cSNickeau $nullstream = fopen('/dev/null', 'c'); 60*04fd306cSNickeau 61*04fd306cSNickeau return [ 62*04fd306cSNickeau ['pipe', 'r'], 63*04fd306cSNickeau $nullstream, 64*04fd306cSNickeau $nullstream, 65*04fd306cSNickeau ]; 66*04fd306cSNickeau } 67*04fd306cSNickeau 68*04fd306cSNickeau if ($this->ttyMode) { 69*04fd306cSNickeau return [ 70*04fd306cSNickeau ['file', '/dev/tty', 'r'], 71*04fd306cSNickeau ['file', '/dev/tty', 'w'], 72*04fd306cSNickeau ['file', '/dev/tty', 'w'], 73*04fd306cSNickeau ]; 74*04fd306cSNickeau } 75*04fd306cSNickeau 76*04fd306cSNickeau if ($this->ptyMode && Process::isPtySupported()) { 77*04fd306cSNickeau return [ 78*04fd306cSNickeau ['pty'], 79*04fd306cSNickeau ['pty'], 80*04fd306cSNickeau ['pty'], 81*04fd306cSNickeau ]; 82*04fd306cSNickeau } 83*04fd306cSNickeau 84*04fd306cSNickeau return [ 85*04fd306cSNickeau ['pipe', 'r'], 86*04fd306cSNickeau ['pipe', 'w'], // stdout 87*04fd306cSNickeau ['pipe', 'w'], // stderr 88*04fd306cSNickeau ]; 89*04fd306cSNickeau } 90*04fd306cSNickeau 91*04fd306cSNickeau /** 92*04fd306cSNickeau * {@inheritdoc} 93*04fd306cSNickeau */ 94*04fd306cSNickeau public function getFiles(): array 95*04fd306cSNickeau { 96*04fd306cSNickeau return []; 97*04fd306cSNickeau } 98*04fd306cSNickeau 99*04fd306cSNickeau /** 100*04fd306cSNickeau * {@inheritdoc} 101*04fd306cSNickeau */ 102*04fd306cSNickeau public function readAndWrite(bool $blocking, bool $close = false): array 103*04fd306cSNickeau { 104*04fd306cSNickeau $this->unblock(); 105*04fd306cSNickeau $w = $this->write(); 106*04fd306cSNickeau 107*04fd306cSNickeau $read = $e = []; 108*04fd306cSNickeau $r = $this->pipes; 109*04fd306cSNickeau unset($r[0]); 110*04fd306cSNickeau 111*04fd306cSNickeau // let's have a look if something changed in streams 112*04fd306cSNickeau set_error_handler([$this, 'handleError']); 113*04fd306cSNickeau if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { 114*04fd306cSNickeau restore_error_handler(); 115*04fd306cSNickeau // if a system call has been interrupted, forget about it, let's try again 116*04fd306cSNickeau // otherwise, an error occurred, let's reset pipes 117*04fd306cSNickeau if (!$this->hasSystemCallBeenInterrupted()) { 118*04fd306cSNickeau $this->pipes = []; 119*04fd306cSNickeau } 120*04fd306cSNickeau 121*04fd306cSNickeau return $read; 122*04fd306cSNickeau } 123*04fd306cSNickeau restore_error_handler(); 124*04fd306cSNickeau 125*04fd306cSNickeau foreach ($r as $pipe) { 126*04fd306cSNickeau // prior PHP 5.4 the array passed to stream_select is modified and 127*04fd306cSNickeau // lose key association, we have to find back the key 128*04fd306cSNickeau $read[$type = array_search($pipe, $this->pipes, true)] = ''; 129*04fd306cSNickeau 130*04fd306cSNickeau do { 131*04fd306cSNickeau $data = @fread($pipe, self::CHUNK_SIZE); 132*04fd306cSNickeau $read[$type] .= $data; 133*04fd306cSNickeau } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1]))); 134*04fd306cSNickeau 135*04fd306cSNickeau if (!isset($read[$type][0])) { 136*04fd306cSNickeau unset($read[$type]); 137*04fd306cSNickeau } 138*04fd306cSNickeau 139*04fd306cSNickeau if ($close && feof($pipe)) { 140*04fd306cSNickeau fclose($pipe); 141*04fd306cSNickeau unset($this->pipes[$type]); 142*04fd306cSNickeau } 143*04fd306cSNickeau } 144*04fd306cSNickeau 145*04fd306cSNickeau return $read; 146*04fd306cSNickeau } 147*04fd306cSNickeau 148*04fd306cSNickeau /** 149*04fd306cSNickeau * {@inheritdoc} 150*04fd306cSNickeau */ 151*04fd306cSNickeau public function haveReadSupport(): bool 152*04fd306cSNickeau { 153*04fd306cSNickeau return $this->haveReadSupport; 154*04fd306cSNickeau } 155*04fd306cSNickeau 156*04fd306cSNickeau /** 157*04fd306cSNickeau * {@inheritdoc} 158*04fd306cSNickeau */ 159*04fd306cSNickeau public function areOpen(): bool 160*04fd306cSNickeau { 161*04fd306cSNickeau return (bool) $this->pipes; 162*04fd306cSNickeau } 163*04fd306cSNickeau} 164