196 lines
5.0 KiB
PHP
196 lines
5.0 KiB
PHP
<?php
|
|
namespace nur\b\proc;
|
|
|
|
use nur\A;
|
|
use nur\base;
|
|
use nur\shell;
|
|
|
|
abstract class AbstractCmd implements ICmd {
|
|
/** @var bool */
|
|
private $needsStdin;
|
|
/** @var bool */
|
|
private $needsTty;
|
|
/** @var array */
|
|
protected $vars;
|
|
/** @var array */
|
|
protected $cmds;
|
|
|
|
function __construct() {
|
|
$this->needsStdin = true;
|
|
$this->needsTty = true;
|
|
$this->cmds = [];
|
|
}
|
|
|
|
function then($cmd, ?string $input=null, ?string $output=null): Cmd {
|
|
if ($this instanceof Cmd) {
|
|
$this->add($cmd, $input, $output);
|
|
return $this;
|
|
} else {
|
|
return (new Cmd($this))->add($cmd, $input, $output);
|
|
}
|
|
}
|
|
|
|
function or($cmd, ?string $input=null, ?string $output=null): CmdOr {
|
|
if ($this instanceof CmdOr) {
|
|
$this->add($cmd, $input, $output);
|
|
return $this;
|
|
} else {
|
|
return (new CmdOr($this))->add($cmd, $input, $output);
|
|
}
|
|
}
|
|
|
|
function and($cmd, ?string $input=null, ?string $output=null): CmdAnd {
|
|
if ($this instanceof CmdAnd) {
|
|
$this->add($cmd, $input, $output);
|
|
return $this;
|
|
} else {
|
|
return (new CmdAnd($this))->add($cmd, $input, $output);
|
|
}
|
|
}
|
|
|
|
function pipe($cmd): CmdPipe {
|
|
if ($this instanceof CmdPipe) {
|
|
$this->add($cmd);
|
|
return $this;
|
|
} else {
|
|
return new CmdPipe([$this, $cmd]);
|
|
}
|
|
}
|
|
|
|
function isNeedsStdin(): bool {
|
|
return $this->needsStdin;
|
|
}
|
|
|
|
function setNeedsStdin(bool $needsStdin): void {
|
|
$this->needsStdin = $needsStdin;
|
|
}
|
|
|
|
function isNeedsTty(): bool {
|
|
return $this->needsTty;
|
|
}
|
|
|
|
function setNeedsTty(bool $needsTty): void {
|
|
$this->needsTty = $needsTty;
|
|
}
|
|
|
|
function addLiteralVars($vars, ?string $sep=null): void {
|
|
if (base::z($vars)) return;
|
|
if (is_array($vars)) {
|
|
if ($sep === null) $sep = "\n";
|
|
$vars = implode($sep, $vars);
|
|
}
|
|
A::append($this->vars, strval($vars));
|
|
}
|
|
|
|
function addVars(?array $vars): void {
|
|
if ($vars === null) return;
|
|
foreach ($vars as $name => $value) {
|
|
$var = [];
|
|
if (!is_array($value)) $var[] = "export ";
|
|
A::merge($var, [$name, "=", shell::quote($value)]);
|
|
A::append($this->vars, implode("", $var));
|
|
}
|
|
}
|
|
|
|
function getVars(?string $sep=null): ?string {
|
|
if ($this->vars === null) return null;
|
|
if ($sep === null) $sep = "\n";
|
|
return implode($sep, $this->vars);
|
|
}
|
|
|
|
function addPrefix($prefix): void {
|
|
$count = count($this->cmds);
|
|
if ($count == 0) return;
|
|
$cmd =& $this->cmds[$count - 1];
|
|
if ($cmd instanceof ICmd) {
|
|
$cmd->addPrefix($prefix);
|
|
} elseif (is_array($prefix)) {
|
|
$prefix = shell::join($prefix);
|
|
$cmd = "$prefix $cmd";
|
|
} else {
|
|
$cmd = "$prefix $cmd";
|
|
}
|
|
}
|
|
|
|
function addRedir(?string $redir, $output=null, bool $append=false, $input=null): void {
|
|
$count = count($this->cmds);
|
|
if ($count == 0) return;
|
|
|
|
if ($output !== null) $output = escapeshellarg($output);
|
|
if ($input !== null) $input = escapeshellarg($input);
|
|
if ($redir === "default") $redir = null;
|
|
$gt = $append? ">>": ">";
|
|
if ($redir === null) {
|
|
$redirs = [];
|
|
if ($input !== null) $redirs[] = "<$input";
|
|
if ($output !== null) $redirs[] = "$gt$output";
|
|
if ($redirs) $redir = implode(" ", $redir);
|
|
} else {
|
|
switch ($redir) {
|
|
case "outonly":
|
|
case "noerr":
|
|
if ($output !== null) $redir = "$gt$output 2>/dev/null";
|
|
else $redir = "2>/dev/null";
|
|
break;
|
|
case "erronly":
|
|
case "noout":
|
|
if ($output !== null) $redir = "2$gt$output >/dev/null";
|
|
else $redir = "2>&1 >/dev/null";
|
|
break;
|
|
case "both":
|
|
case "err2out":
|
|
if ($output !== null) $redir = "$gt$output 2>&1";
|
|
else $redir = "2>&1";
|
|
break;
|
|
case "none":
|
|
case "null":
|
|
$redir = ">/dev/null 2>&1";
|
|
break;
|
|
}
|
|
}
|
|
if ($redir !== null) {
|
|
$cmd =& $this->cmds[$count - 1];
|
|
if ($cmd instanceof ICmd) {
|
|
$cmd->addRedir($redir);
|
|
} else {
|
|
$cmd = "$cmd $redir";
|
|
}
|
|
}
|
|
}
|
|
|
|
abstract function getCmd(?string $sep=null): string;
|
|
|
|
function passthru(int &$retcode=null): bool {
|
|
passthru($this->getCmd(), $retcode);
|
|
return $retcode == 0;
|
|
}
|
|
|
|
function system(string &$output=null, int &$retcode=null): bool {
|
|
$last_line = system($this->getCmd(), $retcode);
|
|
if ($last_line !== false) $output = $last_line;
|
|
return $retcode == 0;
|
|
}
|
|
|
|
function exec(array &$output=null, int &$retcode=null): bool {
|
|
exec($this->getCmd(), $output, $retcode);
|
|
return $retcode == 0;
|
|
}
|
|
|
|
/**
|
|
* retourner true s'il faut utiliser `exec` avec {@link fork_exec()}
|
|
*
|
|
* ne pas utiliser `exec` si des variables sont définies ou si c'est une
|
|
* composition de plusieurs commandes
|
|
*/
|
|
protected function useExec(): bool {
|
|
return $this->vars === null && count($this->cmds) == 1;
|
|
}
|
|
|
|
function fork_exec(int &$retcode=null): bool {
|
|
$cmd = $this->getCmd();
|
|
if ($this->useExec()) $cmd = "exec $cmd";
|
|
shell::_fork_exec($cmd, $retcode);
|
|
return $retcode == 0;
|
|
}
|
|
}
|