xref: /plugin/combo/vendor/symfony/process/Pipes/UnixPipes.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
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