phpproc-open

output problems with proc_open()


I have a small PHP-written CLI script which works as a front-end to CLI-based calc from Linux. The script gets mathematical expressions from user and passes them to calc. Then when user wants to quit he simply enters stop. In this case the script sends exit to calc. The problem with this script is that it displays output only in the end when user sends stop. But I need to have the output of each user's mathematical expression. The script is below:

 <?php

    define('BUFSIZ', 1024);
    define('EXIT_CMD', 'stop');

    function printOutput(&$fd) {
         while (!feof($fd)) {
            echo fgets($fd, BUFSIZ);
        }   
    }

    function &getDescriptorSpec()
    {
        $spec = array(
            0 => array("pty"), // stdin
            1 => array("pty"), // stdout
            2 => array("pty") // stderr
        );
        return $spec;
    }

    function readInputLine(&$fd)
    {
        echo "Enter your input\n";
        $line = trim(fgets($fd)); 
        return $line;
    }

    function sendCmd(&$fd, $cmd)
    {
        fwrite($fd, "${cmd}\n");
    }

    function main() {

        $spec = getDescriptorSpec();
        $process = proc_open("calc", $spec, $pipes);
        if (is_resource($process)) {
            $procstdin = &$pipes[0];
            $procstdout = &$pipes[1];
            $fp = fopen('php://stdin', 'r');
            while (TRUE) {
                $line = readInputLine($fp);
                if (0 === strcmp($line, EXIT_CMD)) {
                    break;
                }
                sendCmd($procstdin, $line);

            }    
            sendCmd($procstdin, "exit");
            fclose($procstdin);
            printOutput($procstdout);
            fclose($procstdout);
            $retval = proc_close($process);
            echo "retval = $retval\n";
            fclose($fp);
        }
    }

    main();

Solution

  • When using the CLI version of PHP, the output is still buffered - so the usual time that a page is sent to the user is at the end of the script.

    As with any version of PHP - using flush() will force the output to be sent to the user.

    Also - you should use PHP_EOL, it outputs the correct new lines for whatever platform your on (linux and Windows use different chars - \r\n or \n). PHP_EOL is a safe way of creating a new line.