diff --git a/cmpUtil.php b/cmpUtil.php index 77be9bd..2203e85 100644 --- a/cmpUtil.php +++ b/cmpUtil.php @@ -264,8 +264,25 @@ "?" => "\\?" , "!" => "\\!" ); - if(@$str[0] == "asis") - return @$str[1]; + do { + if(!is_array($str)) + break; + + if(!isset($str[0])) + return null; + + if($str[0] != "asis") { + $this->d("Unknown modifier '".$str[0]."'"); + return null; + } + + if(!isset($str[1]) || !$str[1]) { + $this->d("Invalid string '".$str[1]."'"); + return null; + } + + return $str[1]; + } while(0); return strtr($str, $ttr); } @@ -274,7 +291,13 @@ $cmaEsc = array(); for($i = 0; $i < count($cmaRaw); $i++) { - $cmaEsc[] = $this->cmpShellEscStr($cmaRaw[$i]); + $str = $this->cmpShellEscStr($cmaRaw[$i]); + + if(!$str) { + return null; + } + + $cmaEsc[] = $str; } return $cmaEsc; @@ -289,8 +312,170 @@ return $this->cmpShellEscStr($cmaRaw); } + function cmpSysExecEventString(&$prs, &$buf, &$opt) { + $fs = "/\n/"; + + if(isset($opt["eventStringDelimer"]) && $opt["eventStringDelimer"]) + $fs = $opt["eventStringDelimer"]; + + $a = preg_split($fs, $buf); + + if(!$a) { + $this->d("Can't split buffer"); + return false; + } + + $c = count($a) - 1; + + if($c < 1) + return true; + + for($i = 0; $i < $c; $i++) { + $this->d($prs["streamCurrent"] . ": " . $a[$i]); + + if($prs["streamCurrent"] == "stdout") { + if(isset($opt["eventStringStdOut"]) && $opt["eventStringStdOut"]) { + ($opt["eventStringStdOut"]["call"])($a[$i], $prs); + } + } + else if($prs["streamCurrent"] == "stderr") { + if(isset($opt["eventStringStdErr"]) && $opt["eventStringStdErr"]) { + ($opt["eventStringStdErr"]["call"])($a[$i], $prs); + } + } + } + + // $this->d("Stream tail: " . $a[$c]); + $buf = $a[$c]; + + return true; + } + + function cmpSysExecEventListenner(&$ppsAll, &$opt) { + $prs = array(); + + while(!feof($ppsAll[1])) { + $read = [ $ppsAll[1], $ppsAll[2] ]; + $write = null; + $except = null; + + // $this->d("Add stream event listenner"); + $cnt = stream_select( + $read, + $write, + $except, + 1, // seconds + 0 // microseconds + ); + + if(false === $cnt) { + $this->d("stream_select err"); + return false; + } + + // $this->d("Streams event count : " . $sel); + + if(!$cnt) { + continue; + } + + $out = stream_get_contents($ppsAll[1]); + if($out) { + $prs["streamCurrent"] = "stdout"; + + if(!$this->cmpSysExecEventString($prs, $out, $opt)) + return false; + } + + $err = stream_get_contents($ppsAll[2]); + if($err) { + $prs["streamCurrent"] = "stderr"; + + if(!$this->cmpSysExecEventString($prs, $err, $opt)) + return false; + } + + // while + } + + return true; + } + + function cmpSysExecEventSwo(&$ppsAll, &$opt) { + do { + if(!@$opt["stdInEventAdd"]) + break; + + if(!is_callable(@$opt["stdInEventAdd"]["call"])) { + $this->d("Invalid callable stdInEventAdd"); + break; + } + + if(!@$opt["silent"]) + $this->d("Call stdInEventAdd"); + + ($opt["stdInEventAdd"]["call"]) ( + $ppsAll[0], + $opt["stdInEventAdd"] + ); + } while(0); + + do { + if(!@$opt["stdOutEventAdd"]) + break; + + if(!is_callable(@$opt["stdOutEventAdd"]["call"])) { + $this->d("Invalid callable stdOutEventAdd"); + break; + } + + if(!@$opt["silent"]) + $this->d("Call stdOutEventAdd"); + + ($opt["stdOutEventAdd" ]["call"]) ( + $ppsAll[1], + $opt["stdOutEventAdd"] + ); + } while(0); + + do { + if(!@$opt["stdErrEventAdd"]) + break; + + if(!is_callable(@$opt["stdErrEventAdd"]["call"])) { + $this->d("Invalid callable stdErrEventAdd"); + break; + } + + if(!@$opt["silent"]) + $this->d("Call stdErrEventAdd"); + + ($opt["stdErrEventAdd"]["call"]) ( + $ppsAll[2], + $opt["stdErrEventAdd"] + ); + } while(0); + + do { + if(!@$opt["eventWait"]) + break; + + if(!@$opt["silent"]) + $this->d("Call eventWait"); + + if(!is_callable(@$opt["eventWait"]["call"])) { + $this->d("Invalid callable eventWait"); + break; + } + + ($opt["eventWait"]["call"])(); + } while(0); + + return true; + } + function cmpSysExec($cmaRaw, $opt = []) { - $cmdStr = $this->cmpShellEscStr($cmaRaw); + $cmdStr = $this->cmpShellEsc($cmaRaw); if(!@$opt["silent"]) { $this->d("cmpSysExec: " . $cmdStr); @@ -324,113 +509,47 @@ $blk = $opt["blocking"]; } - stream_set_blocking($ppsAll[1], $blk); - stream_set_blocking($ppsAll[2], $blk); - $retVal = 255; $out = ""; $err = ""; - if($blk) { + if(isset($opt["eventString"]) && $opt["eventString"]) { + stream_set_blocking($ppsAll[1], 0); + stream_set_blocking($ppsAll[2], 0); + if(@$opt["stdin"]) { fwrite($ppsAll[0], $opt["stdin"]); fclose($ppsAll[0]); } - if(@$opt["stdOutRead"]) { - $this->d("Read loop"); + $this->cmpSysExecEventListenner($ppsAll, $opt); + } + else if($blk) { + stream_set_blocking($ppsAll[1], $blk); + stream_set_blocking($ppsAll[2], $blk); - while(!feof($ppsAll[1])) { - $out = stream_get_contents($ppsAll[1], 1048576); -// $err = stream_get_contents($ppsAll[2], 1048576); - - ($opt["stdOutRead" ]["call"]) ( - $out, - $opt["stdOutRead"] - ); - } - } - else { - $out = stream_get_contents($ppsAll[1], 1048576); - $err = stream_get_contents($ppsAll[2], 1048576); + if(@$opt["stdin"]) { + fwrite($ppsAll[0], $opt["stdin"]); + fclose($ppsAll[0]); } - fclose($ppsAll[1]); - fclose($ppsAll[2]); + $out = stream_get_contents($ppsAll[1], 1048576); + $err = stream_get_contents($ppsAll[2], 1048576); } else { + stream_set_blocking($ppsAll[1], $blk); + stream_set_blocking($ppsAll[2], $blk); + // $this->d("Nonblock"); - do { - if(!@$opt["stdInEventAdd"]) - break; + $this->cmpSysExecEventSwo($ppsAll, $opt); - if(!is_callable(@$opt["stdInEventAdd"]["call"])) { - $this->d("Invalid callable stdInEventAdd"); - break; - } - - if(!@$opt["silent"]) - $this->d("Call stdInEventAdd"); - - ($opt["stdInEventAdd"]["call"]) ( - $ppsAll[0], - $opt["stdInEventAdd"] - ); - } while(0); - - do { - if(!@$opt["stdOutEventAdd"]) - break; - - if(!is_callable(@$opt["stdOutEventAdd"]["call"])) { - $this->d("Invalid callable stdOutEventAdd"); - break; - } - - if(!@$opt["silent"]) - $this->d("Call stdOutEventAdd"); - - ($opt["stdOutEventAdd" ]["call"]) ( - $ppsAll[1], - $opt["stdOutEventAdd"] - ); - } while(0); - - do { - if(!@$opt["stdErrEventAdd"]) - break; - - if(!is_callable(@$opt["stdErrEventAdd"]["call"])) { - $this->d("Invalid callable stdErrEventAdd"); - break; - } - - if(!@$opt["silent"]) - $this->d("Call stdErrEventAdd"); - - ($opt["stdErrEventAdd"]["call"]) ( - $ppsAll[2], - $opt["stdErrEventAdd"] - ); - } while(0); - - do { - if(!@$opt["eventWait"]) - break; - - if(!@$opt["silent"]) - $this->d("Call eventWait"); - - if(!is_callable(@$opt["eventWait"]["call"])) { - $this->d("Invalid callable eventWait"); - break; - } - - ($opt["eventWait"]["call"])(); - } while(0); } + // $this->d("Close all pipe"); + + fclose($ppsAll[1]); + fclose($ppsAll[2]); $retVal = proc_close($prcRes);