Yes, processes inherit the file descriptors of their parent, when you do:
In
php -r 'passthru("nano");'
php
will inherit the stdin of the shell (a tty device if invoked at the prompt of an interactive shell) and nano
will inherit it as well (while stdout is a pipe used by php
to retrieve the output of nano
and pass it through, nano
seems to be happy with it, not all editors would, you may want to use system()
instead here).
In:
something | php -r 'passthru("nano");'
You're calling php
with it stdin now a pipe with something
's stdout at the other end. And nano
will inherit it.
If you want php
's stdin to be the pipe, while nano
stdin whatever the shell's stdin is, you'd need to somehow pass that resource to php
, and have php
(or the shell run by passthru
) make it the stdin of nano
. It could be done with for instance:
{ something 3<&- | php -r 'passthru("nano <&3 3<&-");'; } 3<&0
Where we make the resource on fd 0 (stdin) also available on fd 3 within a command group ({...;}
), close it for something
, which doesn't need it (3<&-
), and tell the shell run by php's passthru
to restore stdin from that fd 3.
Example:
$ php -r 'passthru("ls -l /proc/self/fd");'
total 0
lrwx------ 1 stephane stephane 64 Mar 19 15:12 0 -> /dev/pts/38
l-wx------ 1 stephane stephane 64 Mar 19 15:12 1 -> pipe:[22538485]
lrwx------ 1 stephane stephane 64 Mar 19 15:12 2 -> /dev/pts/38
fd 0 is a tty device for terminal interaction.
$ echo hello | php -r 'passthru("ls -l /proc/self/fd");'
total 0
lr-x------ 1 stephane stephane 64 Mar 19 15:12 0 -> pipe:[22539326]
l-wx------ 1 stephane stephane 64 Mar 19 15:12 1 -> pipe:[22530020]
lrwx------ 1 stephane stephane 64 Mar 19 15:12 2 -> /dev/pts/38
Now ls
's stdin is a pipe (the one echo
is feeding).
$ { echo hello 3<&- | php -r 'passthru("ls -l /proc/\$PPID/fd /proc/self/fd <&3 3<&-");';} 3<&0
/proc/9202/fd:
total 0
lr-x------ 1 stephane stephane 64 Mar 19 15:17 0 -> pipe:[22544619]
lrwx------ 1 stephane stephane 64 Mar 19 15:17 1 -> /dev/pts/38
lrwx------ 1 stephane stephane 64 Mar 19 15:17 2 -> /dev/pts/38
lrwx------ 1 stephane stephane 64 Mar 19 15:17 3 -> /dev/pts/38
lr-x------ 1 stephane stephane 64 Mar 19 15:17 4 -> pipe:[22544623]
/proc/self/fd:
total 0
lrwx------ 1 stephane stephane 64 Mar 19 15:17 0 -> /dev/pts/38
l-wx------ 1 stephane stephane 64 Mar 19 15:17 1 -> pipe:[22544623]
lrwx------ 1 stephane stephane 64 Mar 19 15:17 2 -> /dev/pts/38
ls
's stdin has been made the tty device again, while its parent (php) still has the pipe on stdin (see also the tty on fd 3 and another pipe on fd 4, probably the one it is reading the output of ls
with).
So here, you need to change your php script to:
<?php
foreach(file("php://stdin") as $name) {
echo "Hello $name";
passthru("nano <&3 3<&-");
}
?>
And call it as:
{ printf '%s\n' World Everybody | php script.php; } 3<&0
To pass both resources (the pipe from printf
and the original stdin) to php
.
If you expect that php
script to always be called from within a terminal and that nano
should then always interact with the terminal (but then again, note that php
makes its stdout not the terminal), you could change it instead to:
<?php
foreach(file("php://stdin") as $name) {
echo "Hello $name";
passthru("nano < /dev/tty");
}
?>
Where we hard-code nano
's stdin to be the controlling terminal.