skyprog Posted May 7, 2014 Share Posted May 7, 2014 (edited) This is a server client web socket program, when client send "exe" command the server executes a C application. The output of the c application is read from STDOUT by server and displayed on the client browser. Now there is a C application that requires a user input(scanf), we saved the input in a txt file. We read the input and write it to the stdin of the c program. The problem is that it seems that the C program is not accepting the input that we are writting on the stdin. When i tried this code without any stream select it was working and displaying the sum of two numbers read from input file, but when i place it in stream select command its creating problem. My complete server code is at the end. a part of server code that is creating child process on a client request if(strcmp($user_message, "exe") == 0 ) { echo "Executing a process\n"; $cwd = '/var/www/html/test/websockets' ; $process = proc_open($exe_command, $descriptorspec, $pipes, $cwd);//creating child process sleep(1); if (is_resource($process)) { echo "Process Created"; $read_socks[] = $pipes[1];//add a descriptor $stdout = array($pipes[1]);//save stdout in a variable defined above $stdin = array($pipes[0]); print_r ($stdout); print_r ($stdin); } } else { echo "Passing value to the C program".$user_message; //Read input.txt by line and store it in an array $input = array(); $input = file('/var/www/html/test/websockets/input.txt'); echo "INPUT"; print_r($input); echo "\n"; //Feed the input (hardcoded) $bytes = fwrite($stdin[0], "$input[0] $input[1]"); echo "Bytes written:".$bytes; sleep(1); } } } add.c #include <stdio.h> int main(void) { int first, second; printf("Enter two integers > \n"); scanf("%d", &first); scanf("%d", &second); printf("The two numbers are: %d %d\n", first, second); printf("Output: %d\n", first+second); } input.txt 2 4 output Passing value to the C program3Array ( [0] => Resource id #11 ) INPUTArray ( [0] => 2 [1] => 4 ) Bytes written:5 By doing ps I get root 1173 1164 0 12:08 pts/6 00:00:00 tclsh /usr/bin/unbuffer /var/www/html/test/websockets/./add root 1174 1173 0 12:08 pts/8 00:00:00 /var/www/html/test/websockets/./add After bytes written the server is hanging there is no response from the C application i.e the addition result of 4+2. Why there are two process of add i started 1 with proc open. **complete server code** <?php execute_prog('unbuffer /var/www/html/test/websockets/./add');//unbuffer stdout function execute_prog($exe) { echo "[+execute_prog]"; $host = 'localhost'; //host $port = '9000'; //port $null = NULL; //null var $read_socks; $new_client; $server = stream_socket_server("tcp://0.0.0.0:9000", $errno, $errorMessage); if ($server === false) { throw new UnexpectedValueException("Could not bind to socket: $errorMessage"); } set_time_limit(1800); $exe_command = escapeshellcmd($exe); $descriptorspec = array( 0 => array("pipe", "r"), // stdin -> for execution 1 => array("pipe", "w"), // stdout -> for execution 2 => array("pipe", "w") // stderr ); // $process = proc_open($exe_command, $descriptorspec, $pipes);//creating child process // if (is_resource($process)) { $client_socks = array(); $read_socks = array($server); $changed = array(); $stdout = NULL; $stdin = NULL; while(1) { //prepare readable sockets $write = NULL; $err = NULL; $except = NULL; $changed = $read_socks;//by refrence /* echo "stdout:"; print_r ($stdout); echo "\n"; echo "changed:"; print_r ($changed); echo "\n"; echo "read sock:"; print_r ($read_socks); echo "\n"; */ if (false === ($num_changed_streams = stream_select($changed, $write, $except, 0))) { /* Error handling */ echo "Errors\n"; } else if ($num_changed_streams > 0) { /* At least on one of the streams something interesting happened */ echo "Data on ".$num_changed_streams." descriptor\n"; if(in_array($stdout[0], $changed)) { echo "Data on child process STDOUT\n"; $s = fgets($stdout[0]); if( $s === false ) { // Hello program has finished. echo 'Finished', PHP_EOL; $s = NULL; //ob_flush(); flush(); // Close all descriptors and return... // break; } else { echo $s."</br>"; //prepare data to be sent to client $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$s, 'color'=>$user_color))); foreach ($read_socks as $sock) { if(($sock != $server) && ($sock != $stdout)) fwrite($sock, $response_text, strlen($response_text)); } $s = NULL; //ob_flush(); flush(); } } else if(in_array($server, $changed)) { //new client echo "New Connection\n"; $new_client = stream_socket_accept($server); if ($new_client) { //print remote client information, ip and port number echo 'Connection accepted from ' . stream_socket_get_name($new_client, true) . "n"; $read_socks[] = $new_client; echo "Now there are total ". count($read_socks) . " clients.n"; } $header = fread($new_client, 1024);//read data sent by the socket perform_handshaking($header, $new_client, $host, $port); //perform websocket handshake $ip = stream_socket_get_name($new_client, true); $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data fwrite($new_client,$response,strlen($response)); //delete the server socket from the read sockets unset($changed[ array_search($server, $changed) ]); } else if($write) { echo "Data on child process STDIN\n"; } else if($err) { echo "Data on child process STDERR\n"; } else { echo "Message from the client \n"; //message from existing client foreach($changed as $sock) { $data = fread($sock, 128); //echo "Data read:".$data." From sock:".$sock."\n"; if(!$data) { unset($client_socks[ array_search($sock, $client_socks) ]); @fclose($sock); echo "A client disconnected. Now there are total ". count($client_socks) . " clients.n"; continue; } else { $received_text = unmask($data); //unmask data $tst_msg = json_decode($received_text); //json decode $user_name = $tst_msg->name; //sender name $user_message = $tst_msg->message; //message text $user_color = $tst_msg->color; //color //echo "name:".$user_name." user mesg:".$user_message."\n"; //prepare data to be sent to client $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color))); fwrite($sock, $response_text, strlen($response_text)); //.................................................................................................................. if(strcmp($user_message, "exe") == 0 ) { echo "Executing a process\n"; $cwd = '/var/www/html/test/websockets' ; $process = proc_open($exe_command, $descriptorspec, $pipes, $cwd);//creating child process sleep(1); if (is_resource($process)) { echo "Process Created"; $read_socks[] = $pipes[1];//add a descriptor $stdout = array($pipes[1]);//save stdout in a variable defined above $stdin = array($pipes[0]); print_r ($stdout); print_r ($stdin); } } else { echo "Passing value to the C program".$user_message; print_r ($stdin); echo "\n"; //$input = array($user_message); // fwrite($stdin[0],"$input[0]");//,strlen($user_message)); //Read input.txt by line and store it in an array $input = array(); $input = file('/var/www/html/test/websockets/input.txt'); echo "INPUT"; print_r($input); echo "\n"; //Feed the input (hardcoded) $bytes = fwrite($stdin[0], "$input[0] $input[1]");// $input[1]"); echo "Bytes written:".$bytes; } } } } $num_changed_streams = 0; } } // close the listening socket fclose($server); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); echo "exitcode: ".proc_close($process)."\n"; } echo "[-execute_prog]"; // return $ret; } ?>Any ideas how to solve this?Thank you! EDIT The following code writes to the stdin of a C application but when i tried to integrate in the above client server its not working. <?php //descriptors to be handled by parent $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("file", "/var/www/html/websockets/error.txt", "a") ); // define current working directory where files would be stored $cwd = '/var/www/html' ; $child_proc = escapeshellcmd("unbuffer /var/www/html/test/websockets/./add"); // $process = proc_open('/var/www/html/websockets/add', $descriptorspec, $pipes);//creating child process $process = proc_open($child_proc, $descriptorspec, $pipes, $cwd);//creating child process sleep(1); if (is_resource($process)) { //Read input.txt by line and store it in an array $input = file('/var/www/html/test/websockets/input.txt'); //Feed the input (hardcoded) fwrite($pipes[0], "$input[0] $input[1]"); fclose($pipes[0]); while ($s = fgets($pipes[1])) { print $s."</br>"; flush(); } ?>Any guess why the code in the edit part is working where as when integrated in the client server application its output is not as expected. Edited May 7, 2014 by requinix please use [code] tags when posting code Quote Link to comment https://forums.phpfreaks.com/topic/288303-unable-to-write-to-stdin-of-c-application-using-pipes-created-in-php/ Share on other sites More sharing options...
kicken Posted May 7, 2014 Share Posted May 7, 2014 Add a new line to the end of your input. The C program is probably waiting for a new line before processing the input, as that is the normal behavior. $bytes = fwrite($stdin[0], "$input[0] $input[1]".PHP_EOL); As for why the stand-alone code works without the new line, that is likely because you are closing the stream in that code which tells the child process there is no more input so it will process what it got. Quote Link to comment https://forums.phpfreaks.com/topic/288303-unable-to-write-to-stdin-of-c-application-using-pipes-created-in-php/#findComment-1478586 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.