Untitled

Run Settings
LanguagePHP
Language Version
Run Command
<?php /* * Copyright (C) 2014 Nethesis S.r.l. * * This script is part of NethServer. * * NethServer is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NethServer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NethServer. If not, see <http://www.gnu.org/licenses/>. */ use Symfony\Component\Process\Process; use Symfony\Component\Process\Exception\ProcessFailedException; class SystemTasks { const PTRACK_PATH_TEMPLATE = '/run/nethvoice/%s.sock'; const PTRACK_DUMP_PATH = '/run/nethvoice/%.16s.dump'; const TY_DECLARE = 0x01; const TY_DONE = 0x02; const TY_QUERY = 0x03; const TY_PROGRESS = 0x04; const TY_ERROR = 0x40; const TY_RESPONSE = 0x80; private $tasks = array(); public function startTask($command) { $taskId = md5(uniqid()); $socketPath = sprintf(self::PTRACK_PATH_TEMPLATE, $taskId); $dumpPath = sprintf(self::PTRACK_DUMP_PATH, md5($socketPath)); $cmd = strtr('/usr/libexec/nethserver/ptrack -D -s %socketPath -d %dumpPath -v -- ', array( '%dumpPath' => \escapeshellarg($dumpPath), '%socketPath' => \escapeshellarg($socketPath) )) . $command; $process = new Process($cmd); $process->taskId = $taskId; $process->run(); return $taskId; } /** * * @param string $taskId * @return array * @throws \RuntimeException */ public function getTaskStatus($taskId) { if ( ! isset($this->tasks[$taskId])) { $this->tasks[$taskId] = $this->fetchTaskStatus($taskId); } return $this->tasks[$taskId]; } private function fetchTaskStatus($taskId) { $socketPath = sprintf(self::PTRACK_PATH_TEMPLATE, $taskId); $dumpPath = sprintf(self::PTRACK_DUMP_PATH, md5($socketPath)); $taskStatus = FALSE; $errno = 0; $errstr = ""; $socket = @fsockopen('unix://' . $socketPath, -1, $errno, $errstr); if ($socket === FALSE) { $socketPathExists = $errno != 2; $taskStatus = $this->fetchDumpFile($dumpPath); } else { $this->sendMessage($socket, self::TY_QUERY); $taskStatus = $this->recvMessage($socket); fclose($socket); } return $taskStatus; } private function fetchDumpFile($dumpPath) { if ( ! file_exists($dumpPath)) { return NULL; } $tmp = json_decode(file_get_contents($dumpPath), TRUE); if ( ! is_array($tmp)) { return NULL; } return $tmp; } private function sendMessage($socket, $type, $args = array()) { $payload = json_encode($args); $data = pack('Cn', (int) $type, strlen($payload)) . $payload; $written = fwrite($socket, $data); if ($written !== strlen($data)) { throw new \RuntimeException(sprintf('%s: Socket write error', __CLASS__), 1405610071); } } private function recvMessage($socket) { $buf = $this->safeRead($socket, 3); if ($buf === FALSE) { throw new \RuntimeException(sprintf('%s: Socket read error', __CLASS__), 1405610072); } $header = unpack('Ctype/nsize', $buf); if ( ! is_array($header)) { throw new \RuntimeException(sprintf('%s: Socket read error', __CLASS__), 1405610073); } $message = NULL; if ($header['type'] & self::TY_RESPONSE) { $message = $this->safeRead($socket, $header['size']); if ($message === FALSE) { throw new \RuntimeException(sprintf('%s: Socket read error', __CLASS__), 1405610074); } } return json_decode($message, TRUE); } private function safeRead($socket, $size) { $buffer = ""; $count = 0; while ($count < $size) { if (feof($socket)) { return FALSE; } $chunk = fread($socket, $size - $count); $count += strlen($chunk); if ($chunk === FALSE) { return FALSE; } $buffer .= $chunk; } return $buffer; } }
Editor Settings
Theme
Key bindings
Full width
Lines