shell_exec command in php not working properly - php

I am trying to execute a C program using the shell_exec command, which needs arguments to be passed. It is working for one input, but not working for others. I tried to run the C program through terminal, it is working for all the inputs.
This is my execprog.php file. I have to give 2 inputs as command line arguments to file. /var/www/project is the path.
$query = "/var/www/project/./a.out /var/www/project/constraints.txt /var/www/project/constraints_keyword.txt /var/www/project/FIB.txt /var/www/project/ANS.txt";
echo $query;
$var = shell_exec($query);
echo $var;

<?php
$query = "/var/www/project/./a.out";
$arguments = array
(
'/var/www/project/constraints.txt',
'/var/www/project/constraints_keyword.txt',
'/var/www/project/FIB.txt',
'/var/www/project/ANS.txt'
);
$string = '';
for($i=0;$i<count($arguments);$i++)
$string.= ' %s';
$command = vsprintf("{$query}{$string}", $arguments);
$var = shell_exec($command);
echo $var;

As you it works on the terminal and not on apache then apache's php.ini file may be disabling the use of shell_exec().
See http://www.php.net/manual/en/ini.core.php#ini.disable-functions
Your apache's php.ini file may look something like
disable_functions=exec,passthru,shell_exec,system,proc_open,popen
Remove shell_exec from this list and restart the web server, although this is a security risk and I don't recommend it.
In general functions such as exec,shell_exec and system are always used to execute the external programs. Even a shell command can also be executed. If these two functions are enabled then a user can enter any command as input and execute into your server. So usually people disable in apache config as disable_functions to secure their site.
It works for me - Here is test run
Sample test c code
[akshay#gold tmp]$ cat test.c
#include<stdio.h>
int main(int args, char *argv[]) {
int i = 0;
for (i = 0; i < args; i++)
printf("Arg[%d] = %s\n",i, argv[i]);
return 0;
}
Compile
[akshay#gold tmp]$ gcc test.c
Sample php script
[akshay#gold tmp]$ cat test.php
<?php
$query = "/tmp/./a.out /var/www/project/constraints.txt /var/www/project/constraints_keyword.txt /var/www/project/FIB.txt /var/www/project/ANS.txt";
$var = shell_exec($query);
echo $var;
?>
Execution and output
[akshay#gold tmp]$ php test.php
Arg[0] = /tmp/./a.out
Arg[1] = /var/www/project/constraints.txt
Arg[2] = /var/www/project/constraints_keyword.txt
Arg[3] = /var/www/project/FIB.txt
Arg[4] = /var/www/project/ANS.txt

Related

Why my PHP code cannot exec r script. when i tried to run it from PHP exec function

My R Script :
mydb = dbConnect(MySQL(), user='root', password='root', dbname='skripsi',host='127.0.0.1')
user=dbReadTable(mydb,"users")
user[1,]$id=10
user[1,]$name="gelaaa"
user[1,]$email="Gelaaang#rocketmail.com"
newuser=user[1,]
dbSendQuery(mydb, "SET GLOBAL local_infile = true;")
dbWriteTable(mydb,"users",newuser,append = TRUE,row.names=FALSE)
My PHP Code :
public function forecastCal()
{
$output = exec("D:\R-4.1.0\bin\Rscript.exe D:\applications\coba-laravel\public\js\cicip.R");
dd('berhasil');
return $output;
}
i tried to change database data from my R script. when im using R GUI the script get executed well. but when i tried exec at php. my code did not run. how i can run R script at My PHP code?

Rscript not found in mac

If I execute an R program through macOS Terminal it works fine, but if I execute that program through PHP exec() I get an error which says "Rscript not found".
submit.php:
<?php
// print "hello";
$a = $_POST['a'];
$b = $_POST['b'];
// echo shell_exec("calc");
$output = exec("Rscript /xampp/htdocs/demo/1.R ".$a." ".$b);
print $output
?>
1.R:
setwd("C:/xampp/htdocs/demo")
print("hello")
args=commandArgs(trailingOnly = TRUE)
a = args[1]
b = args[2]
c = as.numeric(a)+as.numeric(b)
cat(c)
You need to tell the command interpreter where Rscript is located. In a normal login, you'd have a long PATH variable to search through, but when running from PHP you have a much more limited path. To figure out where the executable is located, type which Rscript from Terminal. Use the resulting path in your PHP script.
Also note that dumping raw user input into shell commands is a very bad idea. You should always use escapeshellarg() to make sure the input is sanitized. I would also suggest capturing the full output in the event that R outputs more than one line.
<?php
$a = escapeshellarg($_POST["a"]);
$b = escapeshellarg($_POST["b"]);
$r = "/xampp/htdocs/demo/1.R";
$lastline = exec("/usr/local/bin/Rscript $r $a $b", $output, $return);
// you could check the value of $return for non-zero values as well
// full output is returned as an array
echo implode("\n", $output);
Finally, you'll want to check your setwd() command in the R script. Might have some trouble with C: on a Mac! ;)

Pass BASH associative arrays to PHP script

Is it possible to pass BASH associative arrays as argv to PHP scripts?
I have a bash script, that collects some variables to a bash associative array like this. After that, I need to send it to PHP script:
typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)
php script.php --data ${DATA[#]}
From PHP script, i need to access the array in following manner:
<?php
$vars = getopt("",array(
"data:"
));
$data = $vars['data'];
foreach ($data as $k=>$v) {
echo "$k is $v";
}
?>
What I've tried
Weird syntax around the --data parameter follows advice from a great post about bash arrays from Norbert Kéri how to force passed parameter as an array:
You have no way of signaling to the function that you are passing an array. You get N positional parameters, with no information about the datatypes of each.
However this sollution still does not work for associative arrays - only values are passed to the function. Norbert Kéri made a follow up article about that, however its eval based solution does not work for me, as I need to pass the actual array as a parameter.
Is the thing I'm trying to achieve impossible or is there some way? Thank you!
Update: What I am trying to accomplish
I have a few PHP configuration files of following structure:
<?php
return array(
'option1' => 'foo',
'option2' => 'bar'
)
My bash script collects data from user input (through bash read function) and stores them into bash associative array. This array should be later passed as an argument to PHP script.
php script.php --file "config/config.php" --data $BASH_ASSOC_ARRAY
So instead of complicated seds functions etc. I can do simple:
<?php
$bash_input = getopt('',array('file:,data:'));
$data = $bash_input['data'];
$config = require($config_file);
$config['option1'] = $data['option1'];
$config['option2'] = $data['option2'];
// or
foreach ($data as $k=>$v) {
$config[$k] = $v;
}
// print to config file
file_put_contents($file, "<?php \n \n return ".var_export($config,true).";");
?>
This is used for configuring Laravel config files
Different Approach to #will's
Your bash script:
typeset -A DATA
foo=$(some_bash_function "param1" "param2")
bar=$(some_other_bash_function)
php script.php "{'data': '$foo', 'data2': '$bar'}"
PHP Script
<?php
$vars = json_decode($argv[1]);
$data = $vars['data'];
foreach ($data as $k=>$v) {
echo "$k is $v";
}
?>
EDIT (better approach) Credit to #will
typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)
php script.php echo -n "{"; for key in ${!DATA[#]}; do echo - "'$key'":"'${DATA[$key]}'", | sed 's/ /,/g' ; done; echo -n "}"
this does what you want (i think) all in one bash script. You can obviously move the php file out though.
declare -A assoc_array=([key1]=value1 [key2]=value2 [key3]=value3 [key4]=value4)
#These don't come out necesarily ordered
echo ${assoc_array[#]} #echos values
echo ${!assoc_array[#]} #echos keys
echo "" > tmp
for key in ${!assoc_array[#]}
do
echo $key:${assoc_array[$key]} >> tmp # Use some delimeter here to split the keys from the values
done
cat > file.php << EOF
<?php
\$fileArray = explode("\n", file_get_contents("tmp"));
\$data = array();
foreach(\$fileArray as \$line){
\$entry = explode(":", \$line);
\$data[\$entry[0]] = \$entry[1];
}
var_dump(\$data);
?>
EOF
php file.php
the escaping is necessary in the cat block annoyingly.

how can i assign values to my c program with php

I'm trying to run a C program of adding two numbers with PHP in a web browser. But when I run the command
exec"gcc name.c -o a & a" it
returns some garbage result like sum is : 8000542.00. It doesn't ask for any input.
I want to give inputs to scanf from the browser. Please suggest to me how can I resolve my problem.
I have tried this but couldn't handle it successfully.
$desc = array(0=> array ('pipe','w'), 1=> array ('pipe','r'));
$cmd = "C:\xampp\htdocs\add.exe";
$pipes=array();
$p = proc_open($cmd,$desc,$pipes);
if(is_resource($p))
{
echo stream_get_contents($pipes[0]);
fclose($pipes[0]);
$return_value=proc_close($p);
echo $return_value;

How to provide default value for user input in PHP?

Is there a PHP functionallity same as read -i in BASH so that a script can prompt the user and provide a default answer like this:
Are you doing ok? (yes/no): yes
Where "yes" is the default answer provided by the script, which the user can erase and input another.
The readline function does not seem to have what it takes. Is there any other way to do this?
Using a stream does not seem to work either:
<?php
echo "Are you doing ok? (yes/no): ";
$in = fopen('php://stdin', 'rw+');
fputs($in, 'yes'); // should be the default?
$answer = fgets($in);
fclose($in);
echo "\nYou entered: {$answer}\n";
Whatever is in written by the fputs($in, 'yes'); line is ignored:
Are you doing ok? (yes/no): yes
You entered:
Am I using the stream incorrectly? Or maybe there is some other way to achive the default value?
EDIT:
Maybe I simlified the example to much. The real issue is not a simple yes/no prompt - this is just an example. Let me emphasize again: I'm aiming for providing exactly the same functionallity as the read -i BASH command. The $answer in my specific case holds an URL, so I would like for the user to be provided with the first part of the url (scheme, host, port), so he can add/edit the rest (path, query), fragment. Like this:
Enter url: http://www.example.com/foo/
now the user complement the path with bar/baz and we get:
You entered: http://www.example.com/foo/bar/baz
But on the other hand the user also should have the option to erase the first part of the url and provide completely different string:
Enter url: ftp://www.my-super-specific-domain.com/foo/bar
There's no built in way of doing this because writing some code that does it is quite straight forward:
function writeQuestion($question, $answers)
{
echo $question . ' (' . implode('/', $answers) . '): ' . PHP_EOL;
}
function readAnswer($possibleAnswers, $defaultAnswer)
{
$in = fopen('php://stdin', 'rw+');
$answer = trim(fgets($in));
if(!in_array($answer, $possibleAnswers))
{
return $defaultAnswer;
}
return $answer;
}
$question = 'Are you doing ok?';
$answers = array('yes', 'no');
$defaultAnswer = 'yes';
writeQuestion($question, $answers);
$answer = readAnswer($answers, $defaultAnswer);
You can wrap standard bash read for prefilled/populated edit and call it from you main php cli script
bash script named xreadline:
#! /bin/bash
IFS="";read -r -p "$1" -i "$2" -e STRING;echo "$STRING"
main php cli script:
#!/usr/bin/php
<?php
function xreadline ($prompt,$prefill)
{
$on = exec ('./xreadline "'.$prompt.'" "'.$prefill.'"');
return $on;
}
$answer = xreadline ('Your answer: ', 'xyz');
echo $answer;
.....
This approach fully supports UTF8 instead of native PHP readline.
Comment messed my code so here is standalone php cli file with function call to "read" command.
Little bit tricky, but hopefully will work as supposed to. :-)
#!/usr/bin/php
<?php
function xreadline ($prompt,$prefill)
{
return exec ('/bin/bash -c \'read -r -p "'.$prompt.'" -i "'.$prefill.'" -e STRING;echo "$STRING";\'');
}
echo "Prompt test :\n";
$output = xreadline ("edit this prefilled prompt: ","prefilled stuff");
echo "\n";
echo $output;

Categories