php - Reading from STDIN pipe when using proc_open -


i trying make website people can compile , run code online, need find interactive way users send instructions.

actually, first comes mind exec() or system(), when users want input sth, way won't work. have use proc_open().

for instance, following code

int main() {     int a;     printf("please input integer\n");     scanf("%d", &a);     printf("hello world %d!\n", a);     return 0; } 

when used proc_open(), this

$descriptorspec = array(       0 => array( 'pipe' , 'r' ) ,       1 => array( 'pipe' , 'w' ) ,       2 => array( 'file' , 'errors' , 'w' )  );   $run_string = "cd ".$addr_base."; ./a.out 2>&1"; $process = proc_open($run_string, $descriptorspec, $pipes); if (is_resource($process)) {     //echo fgets($pipes[1])."<br/>";     fwrite($pipes[0], '12');     fclose($pipes[0]);     while (!feof($pipes[1]))         echo fgets($pipes[1])."<br/>";     fclose($pipes[1]);     proc_close($process); } 

when running c code, want first stdout stream, , input number, second stdout stream. if have commented line uncommented, page blocked.

is there way solve problem? how can read pipe while not data has been put there? or there better way write kind of interactive program?

it more c or glibc problem. you'll have use fflush(stdout).

why? , what's difference between running a.out in terminal , calling php?

answer: if run a.out in terminal (being stdin tty) glibc use line buffered io. if run program (php in case) , it's stdin pipe (or whatever not tty) glibc use internal io buffering. that's why first fgets() blocks if uncommented. more info check article.

good news: can control buffering using stdbuf command. change $run_string to:

$run_string = "cd ".$addr_base.";stdbuf -o0 ./a.out 2>&1"; 

here comes working example. working if c code don't cares fflush() using stdbuf command:

starting subprocess

$cmd = 'stdbuf -o0 ./a.out 2>&1';  // pipes should used stdin, stdout , stderr of child $descriptorspec = array (     0 => array("pipe", "r"),     1 => array("pipe", "w"),     2 => array("pipe", "w")  );  // open child $proc = proc_open (     $cmd, $descriptorspec, $pipes, getcwd() ); 

set streams non blocking mode

// set streams non blockin mode stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking(stdin, 0);  // check if opening has succeed if($proc === false){     throw new exception('cannot execute child process'); } 

get child pid. need later

// pid via get_status call $status = proc_get_status($proc); if($status === false) {     throw new exception (sprintf(         'failed obtain status information '     )); } $pid = $status['pid']; 

poll until child terminates

// now, poll childs termination while(true) {     // detect if child has terminated - php way     $status = proc_get_status($proc);     // check retval     if($status === false) {         throw new exception ("failed obtain status information $pid");     }     if($status['running'] === false) {         $exitcode = $status['exitcode'];         $pid = -1;         echo "child exited code: $exitcode\n";         exit($exitcode);     }      // read childs stdout , stderr     // avoid *forever* blocking through using time out (50000usec)     foreach(array(1, 2) $desc) {         // check stdout data         $read = array($pipes[$desc]);         $write = null;         $except = null;         $tv = 0;         $utv = 50000;          $n = stream_select($read, $write, $except, $tv, $utv);         if($n > 0) {             {                 $data = fread($pipes[$desc], 8092);                 fwrite(stdout, $data);             } while (strlen($data) > 0);         }     }       $read = array(stdin);     $n = stream_select($read, $write, $except, $tv, $utv);     if($n > 0) {         $input = fread(stdin, 8092);         // inpput program         fwrite($pipes[0], $input);     } } 

Comments

Popular posts from this blog

linux - Does gcc have any options to add version info in ELF binary file? -

android - send complex objects as post php java -

charts - What graph/dashboard product is facebook using in Dashboard: PUE & WUE -