简体   繁体   中英

PHP Script hangs when passing a param to process

I have downloaded an open-source terminal emulator from github and modified it a little. The class for running a process looks like this:

<?php

class CProcess {
    const PROC_OK = true;
    const PROC_FAILED = false;

    private static $instance = null;

    public static function factory() {
        if (!isset(self::$instance)) {
            self::$instance = new CProcess();
        }
        return self::$instance;
    }

    private $pipes;
    private $process;
    private $stdinref;
    private $stdoutref;
    private $stderref;

    private function __construct() {

    }

    public function __destruct() {
        return $this->close();
    }

    public function open($command) {
        $spec = array(
            array("pty"), // STDIN
            array("pty"), // STDOUT
            array("pty")  // STDERR
        );

        if (!$this->process = proc_open($command, $spec, $this->pipes)) {
            return self::PROC_FAILED;
        }
        $this->stdinref = &$this->pipes[0];
        $this->stdoutref = &$this->pipes[1];
        $this->stderref = &$this->pipes[2];

        $this->setBlocking(0);
        return self::PROC_OK;
    }

    public function isResource() {
        return is_resource($this->process);
    }

    public function setBlocking($blocking = 1) {
        return stream_set_blocking($this->stdoutref, $blocking);
    }

    public function getStatus() {
        return proc_get_status($this->process);
    }

    public function get() {
        $out = stream_get_contents($this->stdoutref);
        return $out;
    }

    public function put($data) {
        fwrite($this->stdinref, $data . "\n");
        sleep(1);
        fflush($this->stdinref);
    }

    public function close() {
        if (is_resource($this->process)) {
            fclose($this->stdinref);
            fclose($this->stdoutref);
            fclose($this->stderref);
            return proc_close($this->process);
        }
    }

    public function metaData() {
        return stream_get_meta_data($this->stdoutref);
    }

}

Now I want to authenticate a login/password pair using the following method:

  public static function autenticate($login, $password) {
        if (true === DEBUG_MODE) {
            error_log("authenticate(): login={$login} password={$password}",0);
        }
        error_log("test");
        self::$username = $login;
        $process = CProcess::factory();
        $cmd = "su " . escapeshellarg($login);
        if (true === DEBUG_MODE) {
            error_log("authenticate(): cmd={$cmd}", 0);
        }

        $rc = $process->open($cmd);
        usleep(100000); // 500000
        if ($rc === CProcess::PROC_FAILED) {
            if (true === DEBUG_MODE) {
                error_log("authenticate(): process_open() returns {$rc}", 0);
            }

            return false;
        }
        if (true === DEBUG_MODE) {
            error_log("authenticate(): invoking process->put() with param={$password}");
        }

        $process->put($password);
        if (true === DEBUG_MODE) {
            error_log("authenticate(): process->put() returned its value");
        }

        usleep(100000);
        return (bool) !$process->close();
    }

The problem is that the script hangs when getting into $process->put($password); . My browser just shows 'Waiting for localhost' and it lasts forever. In the put(); method of the class CProcess I also tried PHP_EOL instead of \\n but the result was the same. What's wrong with this code?

The pipes your using should be more like, with read/write type options...

$spec = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("file", "/tmp/error-output.log", "a") );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM