1a94755bd71c1c74d6481acb087abb60f18fc20a
[yaffs-website] / vendor / symfony / process / Pipes / AbstractPipes.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Process\Pipes;
13
14 /**
15  * @author Romain Neutron <imprec@gmail.com>
16  *
17  * @internal
18  */
19 abstract class AbstractPipes implements PipesInterface
20 {
21     /** @var array */
22     public $pipes = array();
23
24     /** @var string */
25     private $inputBuffer = '';
26     /** @var resource|null */
27     private $input;
28     /** @var bool */
29     private $blocked = true;
30
31     public function __construct($input)
32     {
33         if (is_resource($input)) {
34             $this->input = $input;
35         } elseif (is_string($input)) {
36             $this->inputBuffer = $input;
37         } else {
38             $this->inputBuffer = (string) $input;
39         }
40     }
41
42     /**
43      * {@inheritdoc}
44      */
45     public function close()
46     {
47         foreach ($this->pipes as $pipe) {
48             fclose($pipe);
49         }
50         $this->pipes = array();
51     }
52
53     /**
54      * Returns true if a system call has been interrupted.
55      *
56      * @return bool
57      */
58     protected function hasSystemCallBeenInterrupted()
59     {
60         $lastError = error_get_last();
61
62         // stream_select returns false when the `select` system call is interrupted by an incoming signal
63         return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
64     }
65
66     /**
67      * Unblocks streams.
68      */
69     protected function unblock()
70     {
71         if (!$this->blocked) {
72             return;
73         }
74
75         foreach ($this->pipes as $pipe) {
76             stream_set_blocking($pipe, 0);
77         }
78         if (null !== $this->input) {
79             stream_set_blocking($this->input, 0);
80         }
81
82         $this->blocked = false;
83     }
84
85     /**
86      * Writes input to stdin.
87      */
88     protected function write()
89     {
90         if (!isset($this->pipes[0])) {
91             return;
92         }
93         $input = $this->input;
94         $r = $e = array();
95         $w = array($this->pipes[0]);
96
97         // let's have a look if something changed in streams
98         if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
99             return;
100         }
101
102         foreach ($w as $stdin) {
103             if (isset($this->inputBuffer[0])) {
104                 $written = fwrite($stdin, $this->inputBuffer);
105                 $this->inputBuffer = substr($this->inputBuffer, $written);
106                 if (isset($this->inputBuffer[0])) {
107                     return array($this->pipes[0]);
108                 }
109             }
110
111             if ($input) {
112                 for (;;) {
113                     $data = fread($input, self::CHUNK_SIZE);
114                     if (!isset($data[0])) {
115                         break;
116                     }
117                     $written = fwrite($stdin, $data);
118                     $data = substr($data, $written);
119                     if (isset($data[0])) {
120                         $this->inputBuffer = $data;
121
122                         return array($this->pipes[0]);
123                     }
124                 }
125                 if (feof($input)) {
126                     // no more data to read on input resource
127                     // use an empty buffer in the next reads
128                     $this->input = null;
129                 }
130             }
131         }
132
133         // no input to read on resource, buffer is empty
134         if (null === $this->input && !isset($this->inputBuffer[0])) {
135             fclose($this->pipes[0]);
136             unset($this->pipes[0]);
137         } elseif (!$w) {
138             return array($this->pipes[0]);
139         }
140     }
141 }