Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP using shell_exec(bash read) works on tty but not when input is piped and has no newline

TL;DR -- echo -n abc | bash -c 'read -s x && echo -n \$x' doesn't output abc.

I have a PHP CLI script which needs to read a password from stdin.

<?php

function quiet_read_stdin ()
{
    return shell_exec ("bash -c 'read -s x && echo -n \$x'");
}

print "got: ###".quiet_read_stdin ()."###\n";
?>

If I run this in a terminal and input, say, 'xyz':

$> php /tmp/foo.php
got: ###xyz###

As expected, also this works

$> echo xyz | php /tmp/foo.php
got: ###xyz###

But this doesn't.

$> echo -n xyz | php /tmp/foo.php
got: ######

This is causing problems in my script in the case that the secret key is stored in a file without a newline, equivalent to php /tmp/foo.php < keyfile.

This doesn't work (Inappropriate ioctl for device):

system ('stty -echo');
$password = trim (fgets (STDIN));
system ('stty echo');

I don't want to fudge it by inserting a newline at any stage. How can I modify quiet_read_stdin so that it works whether or not the input has a trailing newline? A Linux-only solution is fine.

like image 674
spraff Avatar asked Jan 17 '26 05:01

spraff


1 Answers

For me, this works:

$ cat test.php
<?php
// ignore error message
// stty: standard input: Inappropriate ioctl for device    
shell_exec('stty -echo 2>/dev/null'); 

$io = fopen("php://stdin", "r");
$password = fgets($io);
echo "foo: $password\n";

shell_exec('stty echo 2>/dev/null');

$ echo -n "xyz" | php test.php
foo: xyz

$ php test.php          # typing: abc[ENTER]
foo: abc
like image 117
Kaii Avatar answered Jan 19 '26 18:01

Kaii



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!