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; } }