mirror of
https://github.com/YunoHost-Apps/z-push_ynh.git
synced 2024-09-03 18:05:58 +02:00
769 lines
No EOL
29 KiB
PHP
Executable file
769 lines
No EOL
29 KiB
PHP
Executable file
#!/usr/bin/php
|
|
<?php
|
|
/***********************************************
|
|
* File : z-push-top.php
|
|
* Project : Z-Push
|
|
* Descr : Shows realtime information about
|
|
* connected devices and active
|
|
* connections in a top-style format.
|
|
*
|
|
* Created : 07.09.2011
|
|
*
|
|
* Copyright 2007 - 2013 Zarafa Deutschland GmbH
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation with the following additional
|
|
* term according to sec. 7:
|
|
*
|
|
* According to sec. 7 of the GNU Affero General Public License, version 3,
|
|
* the terms of the AGPL are supplemented with the following terms:
|
|
*
|
|
* "Zarafa" is a registered trademark of Zarafa B.V.
|
|
* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
|
|
* The licensing of the Program under the AGPL does not imply a trademark license.
|
|
* Therefore any rights, title and interest in our trademarks remain entirely with us.
|
|
*
|
|
* However, if you propagate an unmodified version of the Program you are
|
|
* allowed to use the term "Z-Push" to indicate that you distribute the Program.
|
|
* Furthermore you may use our trademarks where it is necessary to indicate
|
|
* the intended purpose of a product or service provided you use it in accordance
|
|
* with honest practices in industrial or commercial matters.
|
|
* If you want to propagate modified versions of the Program under the name "Z-Push",
|
|
* you may only do so if you have a written permission by Zarafa Deutschland GmbH
|
|
* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
|
|
*
|
|
* This program 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 Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Consult LICENSE file for details
|
|
************************************************/
|
|
|
|
include('lib/exceptions/exceptions.php');
|
|
include('lib/core/zpushdefs.php');
|
|
include('lib/core/zpush.php');
|
|
include('lib/core/zlog.php');
|
|
include('lib/core/interprocessdata.php');
|
|
include('lib/core/topcollector.php');
|
|
include('lib/utils/utils.php');
|
|
include('lib/request/request.php');
|
|
include('lib/request/requestprocessor.php');
|
|
include('config.php');
|
|
include('version.php');
|
|
|
|
/************************************************
|
|
* MAIN
|
|
*/
|
|
declare(ticks = 1);
|
|
define('BASE_PATH_CLI', dirname(__FILE__) ."/");
|
|
|
|
try {
|
|
ZPush::CheckConfig();
|
|
if (!function_exists("pcntl_signal"))
|
|
throw new FatalException("Function pcntl_signal() is not available. Please install package 'php5-pcntl' (or similar) on your system.");
|
|
|
|
$zpt = new ZPushTop();
|
|
|
|
// check if help was requested from CLI
|
|
if (in_array('-h', $argv) || in_array('--help', $argv)) {
|
|
echo $zpt->UsageInstructions();
|
|
exit(1);
|
|
}
|
|
|
|
if ($zpt->IsAvailable()) {
|
|
pcntl_signal(SIGINT, array($zpt, "SignalHandler"));
|
|
$zpt->run();
|
|
$zpt->scrClear();
|
|
system("stty sane");
|
|
}
|
|
else
|
|
echo "Z-Push shared memory interprocess communication is not available.\n";
|
|
}
|
|
catch (ZPushException $zpe) {
|
|
die(get_class($zpe) . ": ". $zpe->getMessage() . "\n");
|
|
}
|
|
|
|
echo "terminated\n";
|
|
|
|
|
|
/************************************************
|
|
* Z-Push-Top
|
|
*/
|
|
class ZPushTop {
|
|
// show options
|
|
const SHOW_DEFAULT = 0;
|
|
const SHOW_ACTIVE_ONLY = 1;
|
|
const SHOW_UNKNOWN_ONLY = 2;
|
|
const SHOW_TERM_DEFAULT_TIME = 5; // 5 secs
|
|
|
|
private $topCollector;
|
|
private $starttime;
|
|
private $action;
|
|
private $filter;
|
|
private $status;
|
|
private $statusexpire;
|
|
private $wide;
|
|
private $wasEnabled;
|
|
private $terminate;
|
|
private $scrSize;
|
|
private $pingInterval;
|
|
private $showPush;
|
|
private $showTermSec;
|
|
|
|
private $linesActive = array();
|
|
private $linesOpen = array();
|
|
private $linesUnknown = array();
|
|
private $linesTerm = array();
|
|
private $pushConn = 0;
|
|
private $activeConn = array();
|
|
private $activeHosts = array();
|
|
private $activeUsers = array();
|
|
private $activeDevices = array();
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @access public
|
|
*/
|
|
public function ZPushTop() {
|
|
$this->starttime = time();
|
|
$this->currenttime = time();
|
|
$this->action = "";
|
|
$this->filter = false;
|
|
$this->status = false;
|
|
$this->statusexpire = 0;
|
|
$this->helpexpire = 0;
|
|
$this->doingTail = false;
|
|
$this->wide = false;
|
|
$this->terminate = false;
|
|
$this->showPush = true;
|
|
$this->showOption = self::SHOW_DEFAULT;
|
|
$this->showTermSec = self::SHOW_TERM_DEFAULT_TIME;
|
|
$this->scrSize = array('width' => 80, 'height' => 24);
|
|
$this->pingInterval = (defined('PING_INTERVAL') && PING_INTERVAL > 0) ? PING_INTERVAL : 12;
|
|
|
|
// get a TopCollector
|
|
$this->topCollector = new TopCollector();
|
|
}
|
|
|
|
/**
|
|
* Requests data from the running Z-Push processes
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
private function initialize() {
|
|
// request feedback from active processes
|
|
$this->wasEnabled = $this->topCollector->CollectData();
|
|
|
|
// remove obsolete data
|
|
$this->topCollector->ClearLatest(true);
|
|
|
|
// start with default colours
|
|
$this->scrDefaultColors();
|
|
}
|
|
|
|
/**
|
|
* Main loop of Z-Push-top
|
|
* Runs until termination is requested
|
|
*
|
|
* @access public
|
|
* @return
|
|
*/
|
|
public function run() {
|
|
$this->initialize();
|
|
|
|
do {
|
|
$this->currenttime = time();
|
|
|
|
// see if shared memory is active
|
|
if (!$this->IsAvailable())
|
|
$this->terminate = true;
|
|
|
|
// active processes should continue sending data
|
|
$this->topCollector->CollectData();
|
|
|
|
// get and process data from processes
|
|
$this->topCollector->ClearLatest();
|
|
$topdata = $this->topCollector->ReadLatest();
|
|
$this->processData($topdata);
|
|
|
|
// clear screen
|
|
$this->scrClear();
|
|
|
|
// check if screen size changed
|
|
$s = $this->scrGetSize();
|
|
if ($this->scrSize['width'] != $s['width']) {
|
|
if ($s['width'] > 180)
|
|
$this->wide = true;
|
|
else
|
|
$this->wide = false;
|
|
}
|
|
$this->scrSize = $s;
|
|
|
|
// print overview
|
|
$this->scrOverview();
|
|
|
|
// wait for user input
|
|
$this->readLineProcess();
|
|
}
|
|
while($this->terminate != true);
|
|
}
|
|
|
|
/**
|
|
* Indicates if TopCollector is available collecting data
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
public function IsAvailable() {
|
|
return $this->topCollector->IsActive();
|
|
}
|
|
|
|
/**
|
|
* Processes data written by the running processes
|
|
*
|
|
* @param array $data
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
private function processData($data) {
|
|
$this->linesActive = array();
|
|
$this->linesOpen = array();
|
|
$this->linesUnknown = array();
|
|
$this->linesTerm = array();
|
|
$this->pushConn = 0;
|
|
$this->activeConn = array();
|
|
$this->activeHosts = array();
|
|
$this->activeUsers = array();
|
|
$this->activeDevices = array();
|
|
|
|
if (!is_array($data))
|
|
return;
|
|
|
|
foreach ($data as $devid=>$users) {
|
|
foreach ($users as $user=>$pids) {
|
|
foreach ($pids as $pid=>$line) {
|
|
if (!is_array($line))
|
|
continue;
|
|
|
|
$line['command'] = Utils::GetCommandFromCode($line['command']);
|
|
|
|
if ($line["ended"] == 0) {
|
|
$this->activeDevices[$devid] = 1;
|
|
$this->activeUsers[$user] = 1;
|
|
$this->activeConn[$pid] = 1;
|
|
$this->activeHosts[$line['ip']] = 1;
|
|
|
|
$line["time"] = $this->currenttime - $line['start'];
|
|
if ($line['push'] === true) $this->pushConn += 1;
|
|
|
|
// ignore push connections
|
|
if ($line['push'] === true && ! $this->showPush)
|
|
continue;
|
|
|
|
if ($this->filter !== false) {
|
|
$f = $this->filter;
|
|
if (!($line["pid"] == $f || $line["ip"] == $f || strtolower($line['command']) == strtolower($f) || preg_match("/.*?$f.*?/i", $line['user']) ||
|
|
preg_match("/.*?$f.*?/i", $line['devagent']) || preg_match("/.*?$f.*?/i", $line['devid']) || preg_match("/.*?$f.*?/i", $line['addinfo']) ))
|
|
continue;
|
|
}
|
|
|
|
$lastUpdate = $this->currenttime - $line["update"];
|
|
if ($this->currenttime - $line["update"] < 2)
|
|
$this->linesActive[$line["update"].$line["pid"]] = $line;
|
|
else if (($line['push'] === true && $lastUpdate > ($this->pingInterval+2)) || ($line['push'] !== true && $lastUpdate > 4))
|
|
$this->linesUnknown[$line["update"].$line["pid"]] = $line;
|
|
else
|
|
$this->linesOpen[$line["update"].$line["pid"]] = $line;
|
|
}
|
|
else {
|
|
// do not show terminated + expired connections
|
|
if ($line['ended'] + $this->showTermSec < $this->currenttime)
|
|
continue;
|
|
|
|
if ($this->filter !== false) {
|
|
$f = $this->filter;
|
|
if (!($line['pid'] == $f || $line['ip'] == $f || strtolower($line['command']) == strtolower($f) || preg_match("/.*?$f.*?/i", $line['user']) ||
|
|
preg_match("/.*?$f.*?/i", $line['devagent']) || preg_match("/.*?$f.*?/i", $line['devid']) || preg_match("/.*?$f.*?/i", $line['addinfo']) ))
|
|
continue;
|
|
}
|
|
|
|
$line['time'] = $line['ended'] - $line['start'];
|
|
$this->linesTerm[$line['update'].$line['pid']] = $line;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// sort by execution time
|
|
krsort($this->linesActive);
|
|
krsort($this->linesOpen);
|
|
krsort($this->linesUnknown);
|
|
krsort($this->linesTerm);
|
|
}
|
|
|
|
/**
|
|
* Prints data to the terminal
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
private function scrOverview() {
|
|
$linesAvail = $this->scrSize['height'] - 8;
|
|
$lc = 1;
|
|
$this->scrPrintAt($lc,0, "\033[1mZ-Push top live statistics\033[0m\t\t\t\t\t". @strftime("%d/%m/%Y %T")."\n"); $lc++;
|
|
|
|
$this->scrPrintAt($lc,0, sprintf("Open connections: %d\t\t\t\tUsers:\t %d\tZ-Push: %s ",count($this->activeConn),count($this->activeUsers), $this->getVersion())); $lc++;
|
|
$this->scrPrintAt($lc,0, sprintf("Push connections: %d\t\t\t\tDevices: %d\tPHP-MAPI: %s", $this->pushConn, count($this->activeDevices),phpversion("mapi"))); $lc++;
|
|
$this->scrPrintAt($lc,0, sprintf(" Hosts:\t %d", $this->pushConn, count($this->activeHosts))); $lc++;
|
|
$lc++;
|
|
|
|
$this->scrPrintAt($lc,0, "\033[4m". $this->getLine(array('pid'=>'PID', 'ip'=>'IP', 'user'=>'USER', 'command'=>'COMMAND', 'time'=>'TIME', 'devagent'=>'AGENT', 'devid'=>'DEVID', 'addinfo'=>'Additional Information')). str_repeat(" ",20)."\033[0m"); $lc++;
|
|
|
|
// print help text if requested
|
|
$hl = 0;
|
|
if ($this->helpexpire > $this->currenttime) {
|
|
$help = $this->scrHelp();
|
|
$linesAvail -= count($help);
|
|
$hl = $this->scrSize['height'] - count($help) -1;
|
|
foreach ($help as $h) {
|
|
$this->scrPrintAt($hl,0, $h);
|
|
$hl++;
|
|
}
|
|
}
|
|
|
|
$toPrintActive = $linesAvail;
|
|
$toPrintOpen = $linesAvail;
|
|
$toPrintUnknown = $linesAvail;
|
|
$toPrintTerm = $linesAvail;
|
|
|
|
// default view: show all unknown, no terminated and half active+open
|
|
if (count($this->linesActive) + count($this->linesOpen) + count($this->linesUnknown) > $linesAvail) {
|
|
$toPrintUnknown = count($this->linesUnknown);
|
|
$toPrintActive = count($this->linesActive);
|
|
$toPrintOpen = $linesAvail-$toPrintUnknown-$toPrintActive;
|
|
$toPrintTerm = 0;
|
|
}
|
|
|
|
if ($this->showOption == self::SHOW_ACTIVE_ONLY) {
|
|
$toPrintActive = $linesAvail;
|
|
$toPrintOpen = 0;
|
|
$toPrintUnknown = 0;
|
|
$toPrintTerm = 0;
|
|
}
|
|
|
|
if ($this->showOption == self::SHOW_UNKNOWN_ONLY) {
|
|
$toPrintActive = 0;
|
|
$toPrintOpen = 0;
|
|
$toPrintUnknown = $linesAvail;
|
|
$toPrintTerm = 0;
|
|
}
|
|
|
|
$linesprinted = 0;
|
|
foreach ($this->linesActive as $time=>$l) {
|
|
if ($linesprinted >= $toPrintActive)
|
|
break;
|
|
|
|
$this->scrPrintAt($lc,0, "\033[01m" . $this->getLine($l) ."\033[0m");
|
|
$lc++;
|
|
$linesprinted++;
|
|
}
|
|
|
|
$linesprinted = 0;
|
|
foreach ($this->linesOpen as $time=>$l) {
|
|
if ($linesprinted >= $toPrintOpen)
|
|
break;
|
|
|
|
$this->scrPrintAt($lc,0, $this->getLine($l));
|
|
$lc++;
|
|
$linesprinted++;
|
|
}
|
|
|
|
$linesprinted = 0;
|
|
foreach ($this->linesUnknown as $time=>$l) {
|
|
if ($linesprinted >= $toPrintUnknown)
|
|
break;
|
|
|
|
$color = "0;31m";
|
|
if ($l['push'] == false && $time - $l["start"] > 30)
|
|
$color = "1;31m";
|
|
$this->scrPrintAt($lc,0, "\033[0". $color . $this->getLine($l) ."\033[0m");
|
|
$lc++;
|
|
$linesprinted++;
|
|
}
|
|
|
|
if ($toPrintTerm > 0)
|
|
$toPrintTerm = $linesAvail - $lc +6;
|
|
|
|
$linesprinted = 0;
|
|
foreach ($this->linesTerm as $time=>$l){
|
|
if ($linesprinted >= $toPrintTerm)
|
|
break;
|
|
|
|
$this->scrPrintAt($lc,0, "\033[01;30m" . $this->getLine($l) ."\033[0m");
|
|
$lc++;
|
|
$linesprinted++;
|
|
}
|
|
|
|
// add the lines used when displaying the help text
|
|
$lc += $hl;
|
|
$this->scrPrintAt($lc,0, "\033[K"); $lc++;
|
|
$this->scrPrintAt($lc,0, "Colorscheme: \033[01mActive \033[0mOpen \033[01;31mUnknown \033[01;30mTerminated\033[0m");
|
|
|
|
// remove old status
|
|
if ($this->statusexpire < $this->currenttime)
|
|
$this->status = false;
|
|
|
|
// show request information and help command
|
|
if ($this->starttime + 6 > $this->currenttime) {
|
|
$this->status = sprintf("Requesting information (takes up to %dsecs)", $this->pingInterval). str_repeat(".", ($this->currenttime-$this->starttime)) . " type \033[01;31mh\033[00;31m or \033[01;31mhelp\033[00;31m for usage instructions";
|
|
$this->statusexpire = $this->currenttime+1;
|
|
}
|
|
|
|
|
|
$str = "";
|
|
if (! $this->showPush)
|
|
$str .= "\033[00;32mPush: \033[01;32mNo\033[0m ";
|
|
|
|
if ($this->showOption == self::SHOW_ACTIVE_ONLY)
|
|
$str .= "\033[01;32mActive only\033[0m ";
|
|
|
|
if ($this->showOption == self::SHOW_UNKNOWN_ONLY)
|
|
$str .= "\033[01;32mUnknown only\033[0m ";
|
|
|
|
if ($this->showTermSec != self::SHOW_TERM_DEFAULT_TIME)
|
|
$str .= "\033[01;32mTerminated: ". $this->showTermSec. "s\033[0m ";
|
|
|
|
if ($this->filter !== false || ($this->status !== false && $this->statusexpire > $this->currenttime)) {
|
|
// print filter in green
|
|
if ($this->filter !== false)
|
|
$str .= "\033[00;32mFilter: \033[01;32m$this->filter\033[0m ";
|
|
// print status in red
|
|
if ($this->status !== false)
|
|
$str .= "\033[00;31m$this->status\033[0m";
|
|
}
|
|
$this->scrPrintAt(5,0, $str);
|
|
|
|
$this->scrPrintAt(4,0,"Action: \033[01m".$this->action . "\033[0m");
|
|
}
|
|
|
|
/**
|
|
* Waits for a keystroke and processes the requested command
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
private function readLineProcess() {
|
|
$ans = explode("^^", `bash -c "read -n 1 -t 1 ANS ; echo \\\$?^^\\\$ANS;"`);
|
|
|
|
if ($ans[0] < 128) {
|
|
if (isset($ans[1]) && bin2hex(trim($ans[1])) == "7f") {
|
|
$this->action = substr($this->action,0,-1);
|
|
}
|
|
|
|
if (isset($ans[1]) && $ans[1] != "" ){
|
|
$this->action .= trim(preg_replace("/[^A-Za-z0-9:]/","",$ans[1]));
|
|
}
|
|
|
|
if (bin2hex($ans[0]) == "30" && bin2hex($ans[1]) == "0a") {
|
|
$cmds = explode(':', $this->action);
|
|
if ($cmds[0] == "quit" || $cmds[0] == "q" || (isset($cmds[1]) && $cmds[0] == "" && $cmds[1] == "q")) {
|
|
$this->topCollector->CollectData(true);
|
|
$this->topCollector->ClearLatest(true);
|
|
|
|
$this->terminate = true;
|
|
}
|
|
else if ($cmds[0] == "clear" ) {
|
|
$this->topCollector->ClearLatest(true);
|
|
$this->topCollector->CollectData(true);
|
|
$this->topCollector->ReInitSharedMem();
|
|
}
|
|
else if ($cmds[0] == "filter" || $cmds[0] == "f") {
|
|
if (!isset($cmds[1]) || $cmds[1] == "") {
|
|
$this->filter = false;
|
|
$this->status = "No filter";
|
|
$this->statusexpire = $this->currenttime+5;
|
|
}
|
|
else {
|
|
$this->filter = $cmds[1];
|
|
$this->status = false;
|
|
}
|
|
}
|
|
else if ($cmds[0] == "option" || $cmds[0] == "o") {
|
|
if (!isset($cmds[1]) || $cmds[1] == "") {
|
|
$this->status = sprintf("Option value needs to be specified. See 'help' or 'h' for instructions", $cmds[1]);
|
|
$this->statusexpire = $this->currenttime+5;
|
|
}
|
|
else if ($cmds[1] == "p" || $cmds[1] == "push" || $cmds[1] == "ping")
|
|
$this->showPush = !$this->showPush;
|
|
else if ($cmds[1] == "a" || $cmds[1] == "active")
|
|
$this->showOption = self::SHOW_ACTIVE_ONLY;
|
|
else if ($cmds[1] == "u" || $cmds[1] == "unknown")
|
|
$this->showOption = self::SHOW_UNKNOWN_ONLY;
|
|
else if ($cmds[1] == "d" || $cmds[1] == "default") {
|
|
$this->showOption = self::SHOW_DEFAULT;
|
|
$this->showTermSec = self::SHOW_TERM_DEFAULT_TIME;
|
|
$this->showPush = true;
|
|
}
|
|
else if (is_numeric($cmds[1]))
|
|
$this->showTermSec = $cmds[1];
|
|
else {
|
|
$this->status = sprintf("Option '%s' unknown", $cmds[1]);
|
|
$this->statusexpire = $this->currenttime+5;
|
|
}
|
|
}
|
|
else if ($cmds[0] == "reset" || $cmds[0] == "r") {
|
|
$this->filter = false;
|
|
$this->wide = false;
|
|
$this->helpexpire = 0;
|
|
$this->status = "resetted";
|
|
$this->statusexpire = $this->currenttime+2;
|
|
}
|
|
else if ($cmds[0] == "wide" || $cmds[0] == "w") {
|
|
$this->wide = true;
|
|
$this->status = "w i d e view";
|
|
$this->statusexpire = $this->currenttime+2;
|
|
}
|
|
else if ($cmds[0] == "help" || $cmds[0] == "h") {
|
|
$this->helpexpire = $this->currenttime+20;
|
|
}
|
|
else if (($cmds[0] == "log" || $cmds[0] == "l") && isset($cmds[1]) ) {
|
|
if (!file_exists(LOGFILE)) {
|
|
$this->status = "Logfile can not be found: ". LOGFILE;
|
|
}
|
|
else {
|
|
system('bash -c "fgrep -a '.escapeshellarg($cmds[1]).' '. LOGFILE .' | less +G" > `tty`');
|
|
$this->status = "Returning from log, updating data";
|
|
}
|
|
$this->statusexpire = time()+5; // it might be much "later" now
|
|
}
|
|
else if (($cmds[0] == "tail" || $cmds[0] == "t")) {
|
|
if (!file_exists(LOGFILE)) {
|
|
$this->status = "Logfile can not be found: ". LOGFILE;
|
|
}
|
|
else {
|
|
$this->doingTail = true;
|
|
$this->scrClear();
|
|
$this->scrPrintAt(1,0,$this->scrAsBold("Press CTRL+C to return to Z-Push-Top\n\n"));
|
|
$secondary = "";
|
|
if (isset($cmds[1])) $secondary = " -n 200 | grep ".escapeshellarg($cmds[1]);
|
|
system('bash -c "tail -f '. LOGFILE . $secondary . '" > `tty`');
|
|
$this->doingTail = false;
|
|
$this->status = "Returning from tail, updating data";
|
|
}
|
|
$this->statusexpire = time()+5; // it might be much "later" now
|
|
}
|
|
|
|
else if ($cmds[0] != "") {
|
|
$this->status = sprintf("Command '%s' unknown", $cmds[0]);
|
|
$this->statusexpire = $this->currenttime+8;
|
|
}
|
|
$this->action = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Signal handler function
|
|
*
|
|
* @param int $signo signal number
|
|
*
|
|
* @access public
|
|
* @return
|
|
*/
|
|
public function SignalHandler($signo) {
|
|
// don't terminate if the signal was sent by terminating tail
|
|
if (!$this->doingTail) {
|
|
$this->topCollector->CollectData(true);
|
|
$this->topCollector->ClearLatest(true);
|
|
$this->terminate = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns usage instructions
|
|
*
|
|
* @return string
|
|
* @access public
|
|
*/
|
|
public function UsageInstructions() {
|
|
$help = "Usage:\n\tz-push-top.php\n\n" .
|
|
" Z-Push-Top is a live top-like overview of what Z-Push is doing. It does not have specific command line options.\n\n".
|
|
" When Z-Push-Top is running you can specify certain actions and options which can be executed (listed below).\n".
|
|
" This help information can also be shown inside Z-Push-Top by hitting 'help' or 'h'.\n\n";
|
|
$scrhelp = $this->scrHelp();
|
|
unset($scrhelp[0]);
|
|
|
|
$help .= implode("\n", $scrhelp);
|
|
$help .= "\n\n";
|
|
return $help;
|
|
}
|
|
|
|
|
|
/**
|
|
* Prints a 'help' text at the end of the page
|
|
*
|
|
* @access private
|
|
* @return array with help lines
|
|
*/
|
|
private function scrHelp() {
|
|
$h = array();
|
|
$secs = $this->helpexpire - $this->currenttime;
|
|
$h[] = "Actions supported by Z-Push-Top (help page still displayed for ".$secs."secs)";
|
|
$h[] = " ".$this->scrAsBold("Action")."\t\t".$this->scrAsBold("Comment");
|
|
$h[] = " ".$this->scrAsBold("h")." or ".$this->scrAsBold("help")."\t\tDisplays this information.";
|
|
$h[] = " ".$this->scrAsBold("q").", ".$this->scrAsBold("quit")." or ".$this->scrAsBold(":q")."\t\tExits Z-Push-Top.";
|
|
$h[] = " ".$this->scrAsBold("w")." or ".$this->scrAsBold("wide")."\t\tTries not to truncate data. Automatically done if more than 180 columns available.";
|
|
$h[] = " ".$this->scrAsBold("f:VAL")." or ".$this->scrAsBold("filter:VAL")."\tOnly display connections which contain VAL. This value is case-insensitive.";
|
|
$h[] = " ".$this->scrAsBold("f:")." or ".$this->scrAsBold("filter:")."\t\tWithout a search word: resets the filter.";
|
|
$h[] = " ".$this->scrAsBold("l:STR")." or ".$this->scrAsBold("log:STR")."\tIssues 'less +G' on the logfile, after grepping on the optional STR.";
|
|
$h[] = " ".$this->scrAsBold("t:STR")." or ".$this->scrAsBold("tail:STR")."\tIssues 'tail -f' on the logfile, grepping for optional STR.";
|
|
$h[] = " ".$this->scrAsBold("r")." or ".$this->scrAsBold("reset")."\t\tResets 'wide' or 'filter'.";
|
|
$h[] = " ".$this->scrAsBold("o:")." or ".$this->scrAsBold("option:")."\t\tSets display options. Valid options specified below";
|
|
$h[] = " ".$this->scrAsBold(" p")." or ".$this->scrAsBold("push")."\t\tLists/not lists active and open push connections.";
|
|
$h[] = " ".$this->scrAsBold(" a")." or ".$this->scrAsBold("action")."\t\tLists only active connections.";
|
|
$h[] = " ".$this->scrAsBold(" u")." or ".$this->scrAsBold("unknown")."\tLists only unknown connections.";
|
|
$h[] = " ".$this->scrAsBold(" 10")." or ".$this->scrAsBold("20")."\t\tLists terminated connections for 10 or 20 seconds. Any other number can be used.";
|
|
$h[] = " ".$this->scrAsBold(" d")." or ".$this->scrAsBold("default")."\tUses default options";
|
|
|
|
return $h;
|
|
}
|
|
|
|
/**
|
|
* Encapsulates string with different color escape characters
|
|
*
|
|
* @param string $text
|
|
*
|
|
* @access private
|
|
* @return string same text as bold
|
|
*/
|
|
private function scrAsBold($text) {
|
|
return "\033[01m" . $text ."\033[0m";
|
|
}
|
|
|
|
/**
|
|
* Prints one line of precessed data
|
|
*
|
|
* @param array $l line information
|
|
*
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function getLine($l) {
|
|
if ($this->wide === true)
|
|
return sprintf("%s%s%s%s%s%s%s%s", $this->ptStr($l['pid'],6), $this->ptStr($l['ip'],16), $this->ptStr($l['user'],24), $this->ptStr($l['command'],16), $this->ptStr($this->sec2min($l['time']),8), $this->ptStr($l['devagent'],28), $this->ptStr($l['devid'],30, true), $l['addinfo']);
|
|
else
|
|
return sprintf("%s%s%s%s%s%s%s%s", $this->ptStr($l['pid'],6), $this->ptStr($l['ip'],10), $this->ptStr($l['user'],8), $this->ptStr($l['command'],11), $this->ptStr($this->sec2min($l['time']),6), $this->ptStr($l['devagent'],20), $this->ptStr($l['devid'],12, true), $l['addinfo']);
|
|
}
|
|
|
|
/**
|
|
* Pads and trims string
|
|
*
|
|
* @param string $string to be trimmed/padded
|
|
* @param int $size characters to be considered
|
|
* @param boolean $cutmiddle (optional) indicates where to long information should
|
|
* be trimmed of, false means at the end
|
|
*
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function ptStr($str, $size, $cutmiddle = false) {
|
|
if (strlen($str) < $size)
|
|
return str_pad($str, $size);
|
|
else if ($cutmiddle == true) {
|
|
$cut = ($size-2)/2;
|
|
return $this->ptStr(substr($str,0,$cut) ."..". substr($str,(-1)*($cut-1)), $size);
|
|
}
|
|
else {
|
|
return substr($str,0,$size-3).".. ";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tries to discover the size of the current terminal
|
|
*
|
|
* @access private
|
|
* @return array 'width' and 'height' as keys
|
|
*/
|
|
private function scrGetSize() {
|
|
preg_match_all("/rows.([0-9]+);.columns.([0-9]+);/", strtolower(exec('stty -a | fgrep columns')), $output);
|
|
if(sizeof($output) == 3)
|
|
return array('width' => $output[2][0], 'height' => $output[1][0]);
|
|
|
|
return array('width' => 80, 'height' => 24);
|
|
}
|
|
|
|
/**
|
|
* Returns the version of the current Z-Push installation
|
|
*
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function getVersion() {
|
|
if (ZPUSH_VERSION == "SVN checkout" && file_exists(REAL_BASE_PATH.".svn/entries")) {
|
|
$svn = file(REAL_BASE_PATH.".svn/entries");
|
|
return "SVN " . substr(trim($svn[4]),stripos($svn[4],"z-push")+7) ." r".trim($svn[3]);
|
|
}
|
|
return ZPUSH_VERSION;
|
|
}
|
|
|
|
/**
|
|
* Converts seconds in MM:SS
|
|
*
|
|
* @param int $s seconds
|
|
*
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function sec2min($s) {
|
|
if (!is_int($s))
|
|
return $s;
|
|
return sprintf("%02.2d:%02.2d", floor($s/60), $s%60);
|
|
}
|
|
|
|
/**
|
|
* Resets the default colors of the terminal
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
private function scrDefaultColors() {
|
|
echo "\033[0m";
|
|
}
|
|
|
|
/**
|
|
* Clears screen of the terminal
|
|
*
|
|
* @param array $data
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
public function scrClear() {
|
|
echo "\033[2J";
|
|
}
|
|
|
|
/**
|
|
* Prints a text at a specific screen/terminal coordinates
|
|
*
|
|
* @param int $row row number
|
|
* @param int $col column number
|
|
* @param string $text to be printed
|
|
*
|
|
* @access private
|
|
* @return
|
|
*/
|
|
private function scrPrintAt($row, $col, $text="") {
|
|
echo "\033[".$row.";".$col."H".$text;
|
|
}
|
|
|
|
}
|
|
|
|
?>
|