PageRenderTime 1388ms CodeModel.GetById 707ms app.highlight 396ms RepoModel.GetById 268ms app.codeStats 1ms

/phoronix-test-suite/pts-core/objects/client/pts_client.php

#
PHP | 1689 lines | 1356 code | 221 blank | 112 comment | 321 complexity | 4df1a9dc02052e6aaf65e347502ca279 MD5 | raw file
   1<?php
   2
   3/*
   4	Phoronix Test Suite
   5	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
   6	Copyright (C) 2008 - 2012, Phoronix Media
   7	Copyright (C) 2008 - 2012, Michael Larabel
   8
   9	This program is free software; you can redistribute it and/or modify
  10	it under the terms of the GNU General Public License as published by
  11	the Free Software Foundation; either version 3 of the License, or
  12	(at your option) any later version.
  13
  14	This program is distributed in the hope that it will be useful,
  15	but WITHOUT ANY WARRANTY; without even the implied warranty of
  16	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17	GNU General Public License for more details.
  18
  19	You should have received a copy of the GNU General Public License
  20	along with this program. If not, see <http://www.gnu.org/licenses/>.
  21*/
  22
  23class pts_client
  24{
  25	public static $display;
  26	protected static $lock_pointers = null;
  27
  28	public static function create_lock($lock_file)
  29	{
  30		if(isset(self::$lock_pointers[$lock_file]) || is_writable(dirname($lock_file)) == false || disk_free_space(dirname($lock_file)) < 1024)
  31		{
  32			return false;
  33		}
  34
  35		self::$lock_pointers[$lock_file] = fopen($lock_file, 'w');
  36		chmod($lock_file, 0644);
  37		return self::$lock_pointers[$lock_file] != false && flock(self::$lock_pointers[$lock_file], LOCK_EX | LOCK_NB);
  38	}
  39	public static function init()
  40	{
  41		pts_define_directories(); // Define directories
  42
  43		if(QUICK_START)
  44		{
  45			return true;
  46		}
  47
  48		self::basic_init_process(); // Initalize common / needed PTS start-up work
  49		pts_network::client_startup();
  50		self::core_storage_init_process();
  51
  52		if(!is_file(PTS_TEMP_STORAGE))
  53		{
  54			self::build_temp_cache();
  55		}
  56
  57		pts_config::init_files();
  58		define('PTS_TEST_INSTALL_DEFAULT_PATH', pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/EnvironmentDirectory', '~/.phoronix-test-suite/installed-tests/')));
  59		define('PTS_SAVE_RESULTS_PATH', pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Testing/ResultsDirectory', '~/.phoronix-test-suite/test-results/')));
  60		self::extended_init_process();
  61
  62		$openbenchmarking = pts_storage_object::read_from_file(PTS_CORE_STORAGE, 'openbenchmarking');
  63		if($openbenchmarking != null)
  64		{
  65			// OpenBenchmarking.org Account
  66			pts_openbenchmarking_client::init_account($openbenchmarking);
  67		}
  68
  69		return true;
  70	}
  71	public static function module_framework_init()
  72	{
  73		// Process initially called when PTS starts up
  74		// Check for modules to auto-load from the configuration file
  75		$load_modules = pts_config::read_user_config('PhoronixTestSuite/Options/Modules/LoadModules', null);
  76
  77		if(!empty($load_modules))
  78		{
  79			foreach(pts_strings::comma_explode($load_modules) as $module)
  80			{
  81				$module_r = pts_strings::trim_explode('=', $module);
  82
  83				if(count($module_r) == 2)
  84				{
  85					// TODO: end up hooking this into pts_module::read_variable() rather than using the real env
  86					pts_client::set_environmental_variable($module_r[0], $module_r[1]);
  87				}
  88				else
  89				{
  90					pts_module_manager::attach_module($module);
  91				}
  92			}
  93		}
  94
  95		// Check for modules to load manually in PTS_MODULES
  96		if(($load_modules = pts_client::read_env('PTS_MODULES')) !== false)
  97		{
  98			foreach(pts_strings::comma_explode($load_modules) as $module)
  99			{
 100				if(!pts_module_manager::is_module_attached($module))
 101				{
 102					pts_module_manager::attach_module($module);
 103				}
 104			}
 105		}
 106
 107		// Detect modules to load automatically
 108		pts_module_manager::detect_modules_to_load();
 109
 110		// Clean-up modules list
 111		pts_module_manager::clean_module_list();
 112
 113		// Reset counter
 114		pts_module_manager::set_current_module(null);
 115
 116		// Load the modules
 117		$module_store_list = array();
 118		foreach(pts_module_manager::attached_modules() as $module)
 119		{
 120			$class_vars = get_class_vars($module);
 121			$module_store_vars = isset($class_vars['module_store_vars']) ? $class_vars['module_store_vars'] : null;
 122
 123			if(is_array($module_store_vars))
 124			{
 125				foreach($module_store_vars as $store_var)
 126				{
 127					if(!in_array($store_var, $module_store_list))
 128					{
 129						array_push($module_store_list, $store_var);
 130					}
 131				}
 132			}
 133		}
 134
 135		// Should any of the module options be saved to the results?
 136		foreach($module_store_list as $var)
 137		{
 138			$var_value = pts_client::read_env($var);
 139
 140			if(!empty($var_value))
 141			{
 142				pts_module_manager::var_store_add($var, $var_value);
 143			}
 144		}
 145
 146		pts_module_manager::module_process('__startup');
 147		define('PTS_STARTUP_TASK_PERFORMED', true);
 148		register_shutdown_function(array('pts_module_manager', 'module_process'), '__shutdown');
 149	}
 150	public static function open_basedir_check()
 151	{
 152		$passes = true;
 153		$open_basedir = ini_get('open_basedir');
 154
 155		if($open_basedir != false)
 156		{
 157			$is_in_allowed_dir = false;
 158			foreach(explode(':', $open_basedir) as $allowed_dir)
 159			{
 160				if(strpos(PTS_PATH, $allowed_dir) === 0)
 161				{
 162					$is_in_allowed_dir = true;
 163					break;
 164				}
 165			}
 166
 167			if($is_in_allowed_dir == false)
 168			{
 169				$passes = false;
 170			}
 171		}
 172
 173		return $passes;
 174	}
 175	public static function environmental_variables()
 176	{
 177		// The PTS environmental variables passed during the testing process, etc
 178		static $env_variables = null;
 179
 180		if($env_variables == null)
 181		{
 182			$env_variables = array(
 183			'PTS_VERSION' => PTS_VERSION,
 184			'PTS_CODENAME' => PTS_CODENAME,
 185			'PTS_DIR' => PTS_PATH,
 186			'PHP_BIN' => PHP_BIN,
 187			'NUM_CPU_CORES' => phodevi::read_property('cpu', 'core-count'),
 188			'NUM_CPU_JOBS' => (phodevi::read_property('cpu', 'core-count') * 2),
 189			'SYS_MEMORY' => phodevi::read_property('memory', 'capacity'),
 190			'VIDEO_MEMORY' => phodevi::read_property('gpu', 'memory-capacity'),
 191			'VIDEO_WIDTH' => pts_arrays::first_element(phodevi::read_property('gpu', 'screen-resolution')),
 192			'VIDEO_HEIGHT' => pts_arrays::last_element(phodevi::read_property('gpu', 'screen-resolution')),
 193			'VIDEO_MONITOR_COUNT' => phodevi::read_property('monitor', 'count'),
 194			'VIDEO_MONITOR_LAYOUT' => phodevi::read_property('monitor', 'layout'),
 195			'VIDEO_MONITOR_SIZES' => phodevi::read_property('monitor', 'modes'),
 196			'OPERATING_SYSTEM' => phodevi::read_property('system', 'vendor-identifier'),
 197			'OS_VERSION' => phodevi::read_property('system', 'os-version'),
 198			'OS_ARCH' => phodevi::read_property('system', 'kernel-architecture'),
 199			'OS_TYPE' => phodevi::operating_system(),
 200			'THIS_RUN_TIME' => PTS_INIT_TIME,
 201			'DEBUG_REAL_HOME' => pts_client::user_home_directory()
 202			);
 203
 204			if(!pts_client::executable_in_path('cc') && pts_client::executable_in_path('gcc'))
 205			{
 206				// This helps some test profiles build correctly if they don't do a cc check internally
 207				$env_variables['CC'] = 'gcc';
 208			}
 209		}
 210
 211		return $env_variables;
 212	}
 213	public static function test_install_root_path()
 214	{
 215		if(getenv('PTS_TEST_INSTALL_ROOT_PATH') != false && is_dir(getenv('PTS_TEST_INSTALL_ROOT_PATH')) && is_writable(getenv('PTS_TEST_INSTALL_ROOT_PATH')))
 216		{
 217			return getenv('PTS_TEST_INSTALL_ROOT_PATH');
 218		}
 219		else
 220		{
 221			return PTS_TEST_INSTALL_DEFAULT_PATH;
 222		}
 223	}
 224	public static function user_run_save_variables()
 225	{
 226		static $runtime_variables = null;
 227
 228		if($runtime_variables == null)
 229		{
 230			$runtime_variables = array(
 231			'VIDEO_RESOLUTION' => phodevi::read_property('gpu', 'screen-resolution-string'),
 232			'VIDEO_CARD' => phodevi::read_name('gpu'),
 233			'VIDEO_DRIVER' => phodevi::read_property('system', 'display-driver-string'),
 234			'OPERATING_SYSTEM' => phodevi::read_property('system', 'operating-system'),
 235			'PROCESSOR' => phodevi::read_name('cpu'),
 236			'MOTHERBOARD' => phodevi::read_name('motherboard'),
 237			'CHIPSET' => phodevi::read_name('chipset'),
 238			'KERNEL_VERSION' => phodevi::read_property('system', 'kernel'),
 239			'COMPILER' => phodevi::read_property('system', 'compiler'),
 240			'HOSTNAME' => phodevi::read_property('system', 'hostname')
 241			);
 242		}
 243
 244		return $runtime_variables;
 245	}
 246	public static function save_test_result($save_to = null, $save_results = null, $render_graphs = true, $result_identifier = null)
 247	{
 248		// Saves PTS result file
 249		if(substr($save_to, -4) != '.xml')
 250		{
 251			$save_to .= '.xml';
 252		}
 253
 254		$save_to_dir = pts_client::setup_test_result_directory($save_to);
 255
 256		if($save_to == null || $save_results == null)
 257		{
 258			$bool = false;
 259		}
 260		else
 261		{
 262			$save_name = basename($save_to, '.xml');
 263
 264			if($save_name == 'composite' && $render_graphs)
 265			{
 266				pts_client::generate_result_file_graphs($save_results, $save_to_dir);
 267			}
 268
 269			$bool = file_put_contents(PTS_SAVE_RESULTS_PATH . $save_to, $save_results);
 270
 271			if($result_identifier != null && (pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/SaveSystemLogs', 'TRUE') || (pts_c::$test_flags & pts_c::batch_mode) || (pts_c::$test_flags & pts_c::auto_mode)))
 272			{
 273				// Save verbose system information here
 274				$system_log_dir = $save_to_dir . '/system-logs/' . $result_identifier . '/';
 275				pts_file_io::mkdir($system_log_dir, 0777, true);
 276
 277				// Backup system files
 278				// TODO: move out these files/commands to log out to respective Phodevi components so only what's relevant will be logged
 279				$system_log_files = array(
 280					'/var/log/Xorg.0.log',
 281					'/proc/cpuinfo',
 282					'/proc/meminfo',
 283					'/proc/modules',
 284					'/proc/mounts',
 285					'/proc/cmdline',
 286					'/proc/version',
 287					'/etc/X11/xorg.conf',
 288					'/sys/kernel/debug/dri/0/radeon_pm_info',
 289					'/sys/kernel/debug/dri/0/i915_capabilities',
 290					'/sys/kernel/debug/dri/0/i915_cur_delayinfo',
 291					'/sys/kernel/debug/dri/0/i915_drpc_info',
 292					'/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies',
 293					);
 294
 295				/*
 296				if(phodevi::is_linux())
 297				{
 298					// the kernel config file might just be too large to upload for now
 299					array_push($system_log_files, '/boot/config-' . php_uname('r'));
 300				}
 301				*/
 302
 303				foreach($system_log_files as $file)
 304				{
 305					if(is_file($file) && is_readable($file))
 306					{
 307						// copy() can't be used in this case since it will result in a blank file for /proc/ file-system
 308						$file_contents = file_get_contents($file);
 309						$file_contents = pts_strings::remove_line_timestamps($file_contents);
 310						file_put_contents($system_log_dir . basename($file), $file_contents);
 311					}
 312				}
 313
 314				// Generate logs from system commands to backup
 315				$system_log_commands = array(
 316					'lspci -vvnn',
 317					'lscpu',
 318					'cc -v',
 319					'lsusb',
 320					'lsmod',
 321					'sensors',
 322					'dmesg',
 323					'cpufreq-info',
 324					'glxinfo',
 325					'clinfo',
 326					'uname -a',
 327					// 'udisks --dump',
 328					'upower --dump',
 329					);
 330
 331				if(phodevi::is_bsd())
 332				{
 333					array_push($system_log_commands, 'sysctl -a');
 334					array_push($system_log_commands, 'kenv');
 335				}
 336				if(is_readable('/dev/mem'))
 337				{
 338					array_push($system_log_commands, 'dmidecode');
 339				}
 340
 341				foreach($system_log_commands as $command_string)
 342				{
 343					$command = explode(' ', $command_string);
 344
 345					if(($command_bin = pts_client::executable_in_path($command[0])))
 346					{
 347						$cmd_output = shell_exec('cd ' . dirname($command_bin) . ' && ./' . $command_string . ' 2>&1');
 348
 349						// Try to filter out any serial numbers, etc.
 350						$cmd_output = pts_strings::remove_lines_containing($cmd_output, array('Serial N', 'S/N', 'Serial #', 'serial:', 'serial='));
 351						$cmd_output = pts_strings::remove_line_timestamps($cmd_output);
 352
 353						file_put_contents($system_log_dir . $command[0], $cmd_output);
 354					}
 355				}
 356
 357				// Dump some common / important environmental variables
 358				$environment_variables = array(
 359					'PATH' => null,
 360					'CFLAGS' => null,
 361					'CXXFLAGS' => null,
 362					'LD_LIBRARY_PATH' => null,
 363					'CC' => null,
 364					'CXX' => null,
 365					'LIBGL_DRIVERS_PATH' => null
 366					);
 367
 368				foreach($environment_variables as $variable => &$value)
 369				{
 370					$v = getenv($variable);
 371
 372					if($v != null)
 373					{
 374						$value = $v;
 375					}
 376					else
 377					{
 378						unset($environment_variables[$variable]);
 379					}
 380				}
 381
 382				if(!empty($environment_variables))
 383				{
 384					$variable_dump = null;
 385					foreach($environment_variables as $variable => $value)
 386					{
 387						$variable_dump .= $variable . '=' . $value . PHP_EOL;
 388					}
 389					file_put_contents($system_log_dir . 'environment-variables', $variable_dump);
 390				}
 391			}
 392		}
 393
 394		return $bool;
 395	}
 396	public static function save_result_file(&$result_file_writer, $save_name)
 397	{
 398		// Save the test file
 399		// TODO: clean this up with pts_client::save_test_result
 400		$j = 1;
 401		while(is_file(PTS_SAVE_RESULTS_PATH . $save_name . '/test-' . $j . '.xml'))
 402		{
 403			$j++;
 404		}
 405
 406		$real_name = $save_name . '/test-' . $j . '.xml';
 407
 408		pts_client::save_test_result($real_name, $result_file_writer->get_xml());
 409
 410		if(!is_file(PTS_SAVE_RESULTS_PATH . $save_name . '/composite.xml'))
 411		{
 412			pts_client::save_test_result($save_name . '/composite.xml', file_get_contents(PTS_SAVE_RESULTS_PATH . $real_name), true, $result_file_writer->get_result_identifier());
 413		}
 414		else
 415		{
 416			// Merge Results
 417			$merged_results = pts_merge::merge_test_results(file_get_contents(PTS_SAVE_RESULTS_PATH . $save_name . '/composite.xml'), file_get_contents(PTS_SAVE_RESULTS_PATH . $real_name));
 418			pts_client::save_test_result($save_name . '/composite.xml', $merged_results, true, $result_file_writer->get_result_identifier());
 419		}
 420
 421		return $real_name;
 422	}
 423	private static function basic_init_process()
 424	{
 425		// Initialize The Phoronix Test Suite
 426
 427		// PTS Defines
 428		define('PHP_BIN', pts_client::read_env('PHP_BIN'));
 429		define('PTS_INIT_TIME', time());
 430
 431		if(!defined('PHP_VERSION_ID'))
 432		{
 433			// PHP_VERSION_ID is only available in PHP 5.2.6 and later
 434			$php_version = explode('.', PHP_VERSION);
 435			define('PHP_VERSION_ID', ($php_version[0] * 10000 + $php_version[1] * 100 + $php_version[2]));
 436		}
 437
 438		$dir_init = array(PTS_USER_PATH);
 439		foreach($dir_init as $dir)
 440		{
 441			pts_file_io::mkdir($dir);
 442		}
 443	}
 444	public static function init_display_mode($flags = 0)
 445	{
 446		$env_mode = ($flags & pts_c::debug_mode) ? 'BASIC' : false;
 447
 448		switch(($env_mode != false || ($env_mode = pts_client::read_env('PTS_DISPLAY_MODE')) != false ? $env_mode : pts_config::read_user_config('PhoronixTestSuite/Options/General/DefaultDisplayMode', 'DEFAULT')))
 449		{
 450			case 'BASIC':
 451				self::$display = new pts_basic_display_mode();
 452				break;
 453			case 'BATCH':
 454			case 'CONCISE':
 455				self::$display = new pts_concise_display_mode();
 456				break;
 457			case 'DEFAULT':
 458			default:
 459				self::$display = new pts_concise_display_mode();
 460				break;
 461		}
 462	}
 463	private static function extended_init_process()
 464	{
 465		// Extended Initalization Process
 466		$directory_check = array(
 467			PTS_TEST_INSTALL_DEFAULT_PATH,
 468			PTS_SAVE_RESULTS_PATH,
 469			PTS_MODULE_LOCAL_PATH,
 470			PTS_MODULE_DATA_PATH,
 471			PTS_DOWNLOAD_CACHE_PATH,
 472			PTS_OPENBENCHMARKING_SCRATCH_PATH,
 473			PTS_TEST_PROFILE_PATH,
 474			PTS_TEST_SUITE_PATH,
 475			PTS_TEST_PROFILE_PATH . 'local/',
 476			PTS_TEST_SUITE_PATH . 'local/'
 477			);
 478
 479		foreach($directory_check as $dir)
 480		{
 481			pts_file_io::mkdir($dir);
 482		}
 483
 484		// Setup PTS Results Viewer
 485		pts_file_io::mkdir(PTS_SAVE_RESULTS_PATH . 'pts-results-viewer');
 486
 487		foreach(pts_file_io::glob(PTS_RESULTS_VIEWER_PATH . '*') as $result_viewer_file)
 488		{
 489			copy($result_viewer_file, PTS_SAVE_RESULTS_PATH . 'pts-results-viewer/' . basename($result_viewer_file));
 490		}
 491
 492		copy(PTS_CORE_STATIC_PATH . 'images/pts-106x55.png', PTS_SAVE_RESULTS_PATH . 'pts-results-viewer/pts-106x55.png');
 493
 494		// Setup ~/.phoronix-test-suite/xsl/
 495		pts_file_io::mkdir(PTS_USER_PATH . 'xsl/');
 496		copy(PTS_CORE_STATIC_PATH . 'xsl/pts-test-installation-viewer.xsl', PTS_USER_PATH . 'xsl/' . 'pts-test-installation-viewer.xsl');
 497		copy(PTS_CORE_STATIC_PATH . 'xsl/pts-user-config-viewer.xsl', PTS_USER_PATH . 'xsl/' . 'pts-user-config-viewer.xsl');
 498		copy(PTS_CORE_STATIC_PATH . 'images/pts-308x160.png', PTS_USER_PATH . 'xsl/' . 'pts-logo.png');
 499
 500		// pts_compatibility ops here
 501
 502		pts_client::init_display_mode();
 503	}
 504	public static function program_requirement_checks($only_show_required = false)
 505	{
 506		$extension_checks = pts_needed_extensions();
 507
 508		$printed_required_header = false;
 509		$printed_optional_header = false;
 510		foreach($extension_checks as $extension)
 511		{
 512			if($extension[1] == false)
 513			{
 514				if($extension[0] == 1)
 515				{
 516					// Oops, this extension is required
 517					if($printed_required_header == false)
 518					{
 519						echo PHP_EOL . 'The following PHP extensions are REQUIRED by the Phoronix Test Suite:' . PHP_EOL . PHP_EOL;
 520						$printed_required_header = true;
 521					}
 522				}
 523				else
 524				{
 525					if($only_show_required && $printed_required_header == false)
 526					{
 527						continue;
 528					}
 529
 530					// This extension is missing but optional
 531					if($printed_optional_header == false)
 532					{
 533						echo PHP_EOL . ($printed_required_header ? null : 'NOTICE: ') . 'The following PHP extensions are OPTIONAL but recommended:' . PHP_EOL . PHP_EOL;
 534						$printed_optional_header = true;
 535					}
 536				}
 537
 538				echo sprintf('%-8ls %-30ls' . PHP_EOL, $extension[2], $extension[3]);
 539			}
 540		}
 541
 542		if($printed_required_header || $printed_optional_header)
 543		{
 544			echo PHP_EOL;
 545
 546			if($printed_required_header)
 547			{
 548				exit;
 549			}
 550		}
 551	}
 552	private static function build_temp_cache()
 553	{
 554		$pso = pts_storage_object::recover_from_file(PTS_TEMP_STORAGE);
 555
 556		if($pso == false)
 557		{
 558			$pso = new pts_storage_object();
 559		}
 560
 561		$pso->add_object('environmental_variables_for_modules', pts_module_manager::modules_environmental_variables());
 562		$pso->add_object('vendor_alias_list', pts_external_dependencies::vendor_alias_list());
 563		$pso->add_object('command_alias_list', pts_documentation::client_commands_aliases());
 564
 565		$pso->save_to_file(PTS_TEMP_STORAGE);
 566	}
 567	private static function core_storage_init_process()
 568	{
 569		$pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE);
 570
 571		if($pso == false)
 572		{
 573			$pso = new pts_storage_object(true, true);
 574		}
 575
 576		// OpenBenchmarking.org - GSID
 577		$global_gsid = $pso->read_object('global_system_id');
 578		$global_gsid_e = $pso->read_object('global_system_id_e');
 579		$global_gsid_p = $pso->read_object('global_system_id_p');
 580
 581		if(empty($global_gsid) || pts_openbenchmarking::is_valid_gsid_format($global_gsid) == false)
 582		{
 583			// Global System ID for anonymous uploads, etc
 584			$requested_gsid = true;
 585			$global_gsid = pts_openbenchmarking_client::request_gsid();
 586
 587			if(is_array($global_gsid))
 588			{
 589				$pso->add_object('global_system_id', $global_gsid['gsid']); // GSID
 590				$pso->add_object('global_system_id_p', $global_gsid['gsid_p']); // GSID_P
 591				$pso->add_object('global_system_id_e', $global_gsid['gsid_e']); // GSID_E
 592				define('PTS_GSID', $global_gsid['gsid']);
 593				define('PTS_GSID_E', $global_gsid['gsid_e']);
 594			}
 595		}
 596		else if(pts_openbenchmarking::is_valid_gsid_e_format($global_gsid_e) == false || pts_openbenchmarking::is_valid_gsid_e_format($global_gsid_p) == false)
 597		{
 598			define('PTS_GSID', $global_gsid);
 599			$requested_gsid = false;
 600			$global_gsid = pts_openbenchmarking_client::retrieve_gsid();
 601
 602			if(is_array($global_gsid))
 603			{
 604				$pso->add_object('global_system_id_p', $global_gsid['gsid_p']); // GSID_P
 605				$pso->add_object('global_system_id_e', $global_gsid['gsid_e']); // GSID_E
 606				define('PTS_GSID_E', $global_gsid['gsid_e']);
 607			}
 608		}
 609		else
 610		{
 611			define('PTS_GSID', $global_gsid);
 612			define('PTS_GSID_E', $global_gsid_e);
 613			$requested_gsid = false;
 614		}
 615
 616		// Last Run Processing
 617		$last_core_version = $pso->read_object('last_core_version');
 618		define('FIRST_RUN_ON_PTS_UPGRADE', ($last_core_version != PTS_CORE_VERSION));
 619
 620		if(FIRST_RUN_ON_PTS_UPGRADE || ($pso->read_object('last_php_version') != phpversion()))
 621		{
 622			// Report any missing/recommended extensions
 623			self::program_requirement_checks();
 624		}
 625
 626		if(FIRST_RUN_ON_PTS_UPGRADE)
 627		{
 628			if($requested_gsid == false)
 629			{
 630				pts_openbenchmarking_client::update_gsid();
 631			}
 632
 633			pts_client::build_temp_cache();
 634		}
 635		$pso->add_object('last_core_version', PTS_CORE_VERSION); // PTS version last run
 636		$pso->add_object('last_php_version', phpversion()); // PHP version last run
 637
 638		//$last_pts_version = $pso->read_object('last_pts_version');
 639		// do something here with $last_pts_version if you want that information
 640		$pso->add_object('last_pts_version', PTS_VERSION); // PTS version last run
 641
 642		// Last Run Processing
 643		$last_run = $pso->read_object('last_run_time');
 644		define('IS_FIRST_RUN_TODAY', (substr($last_run, 0, 10) != date('Y-m-d')));
 645		$pso->add_object('last_run_time', date('Y-m-d H:i:s')); // Time PTS was last run
 646
 647
 648		// User Agreement Checking
 649		$agreement_cs = $pso->read_object('user_agreement_cs');
 650
 651		$pso->add_object('user_agreement_cs', $agreement_cs); // User agreement check-sum
 652
 653		// Phodevi Cache Handling
 654		$phodevi_cache = $pso->read_object('phodevi_smart_cache');
 655
 656		if($phodevi_cache instanceof phodevi_cache && pts_flags::no_phodevi_cache() == false)
 657		{
 658			$phodevi_cache = $phodevi_cache->restore_cache(PTS_USER_PATH, PTS_CORE_VERSION);
 659			phodevi::set_device_cache($phodevi_cache);
 660
 661			if(($external_phodevi_cache = pts_client::read_env('EXTERNAL_PHODEVI_CACHE')))
 662			{
 663				if(is_dir($external_phodevi_cache) && is_file($external_phodevi_cache . '/core.pt2so'))
 664				{
 665					$external_phodevi_cache .= '/core.pt2so';
 666				}
 667
 668				if(is_file($external_phodevi_cache))
 669				{
 670					$external_phodevi_cache = pts_storage_object::force_recover_from_file($external_phodevi_cache);
 671
 672					if($external_phodevi_cache != false)
 673					{
 674						$external_phodevi_cache = $external_phodevi_cache->read_object('phodevi_smart_cache');
 675						$external_phodevi_cache = $external_phodevi_cache->restore_cache(null, PTS_CORE_VERSION);
 676
 677						if($external_phodevi_cache != false)
 678						{
 679							//unset($external_phodevi_cache['system']['operating-system']);
 680							//unset($external_phodevi_cache['system']['vendor-identifier']);
 681							phodevi::set_device_cache($external_phodevi_cache);
 682						}
 683					}
 684				}
 685			}
 686		}
 687
 688		// Archive to disk
 689		$pso->save_to_file(PTS_CORE_STORAGE);
 690	}
 691	public static function user_agreement_check($command)
 692	{
 693		$pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE);
 694
 695		if($pso == false)
 696		{
 697			return false;
 698		}
 699
 700		$config_md5 = $pso->read_object('user_agreement_cs');
 701		$current_md5 = md5_file(PTS_PATH . 'pts-core/user-agreement.txt');
 702
 703		if($config_md5 != $current_md5 || pts_config::read_user_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', 'UNKNOWN') == 'UNKNOWN')
 704		{
 705			$prompt_in_method = pts_client::check_command_for_function($command, 'pts_user_agreement_prompt');
 706			$user_agreement = file_get_contents(PTS_PATH . 'pts-core/user-agreement.txt');
 707
 708			if($prompt_in_method)
 709			{
 710				$user_agreement_return = call_user_func(array($command, 'pts_user_agreement_prompt'), $user_agreement);
 711
 712				if(is_array($user_agreement_return))
 713				{
 714					if(count($user_agreement_return) == 3)
 715					{
 716						list($agree, $usage_reporting, $hwsw_reporting) = $user_agreement_return;
 717					}
 718					else
 719					{
 720						$agree = array_shift($user_agreement_return);
 721						$usage_reporting = -1;
 722						$hwsw_reporting = -1;
 723					}
 724				}
 725				else
 726				{
 727					$agree = $user_agreement_return;
 728					$usage_reporting = -1;
 729					$hwsw_reporting = -1;
 730				}
 731			}
 732
 733			if($prompt_in_method == false || $usage_reporting == -1 || $hwsw_reporting == -1)
 734			{
 735				pts_client::$display->generic_heading('User Agreement');
 736				echo wordwrap($user_agreement, 65);
 737				$agree = pts_flags::user_agreement_skip() || pts_user_io::prompt_bool_input('Do you agree to these terms and wish to proceed', true);
 738
 739				if(pts_flags::no_openbenchmarking_reporting())
 740				{
 741					$usage_reporting = false;
 742					$hwsw_reporting = false;
 743				}
 744				else
 745				{
 746					$usage_reporting = $agree ? pts_user_io::prompt_bool_input('Enable anonymous usage / statistics reporting', true) : -1;
 747					$hwsw_reporting = $agree ? pts_user_io::prompt_bool_input('Enable anonymous statistical reporting of installed software / hardware', true) : -1;
 748				}
 749			}
 750
 751			if($agree)
 752			{
 753				echo PHP_EOL;
 754				$pso->add_object('user_agreement_cs', $current_md5);
 755				$pso->save_to_file(PTS_CORE_STORAGE);
 756			}
 757			else
 758			{
 759				pts_client::exit_client('In order to run the Phoronix Test Suite, you must agree to the listed terms.');
 760			}
 761
 762			pts_config::user_config_generate(array(
 763				'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting' => pts_config::bool_to_string($usage_reporting),
 764				'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting' => pts_config::bool_to_string($hwsw_reporting),
 765				'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting' => pts_config::bool_to_string($hwsw_reporting)
 766				));
 767		}
 768	}
 769	public static function swap_variables($user_str, $replace_call)
 770	{
 771		if(is_array($replace_call))
 772		{
 773			if(count($replace_call) != 2 || method_exists($replace_call[0], $replace_call[1]) == false)
 774			{
 775				echo PHP_EOL . 'Var Swap With Method Failed.' . PHP_EOL;
 776				return $user_str;
 777			}
 778		}
 779		else if(!function_exists($replace_call))
 780		{
 781			echo PHP_EOL . 'Var Swap With Function Failed.' . PHP_EOL;
 782			return $user_str;
 783		}
 784
 785		$offset = 0;
 786		$replace_call_return = false;
 787
 788		while($offset < strlen($user_str) && ($s = strpos($user_str, '$', $offset)) !== false)
 789		{
 790			$s++;
 791			$var_name = substr($user_str, $s, (($e = strpos($user_str, ' ', $s)) == false ? strlen($user_str) : $e) - $s);
 792
 793			if($replace_call_return === false)
 794			{
 795				$replace_call_return = call_user_func($replace_call);
 796			}
 797
 798			$var_replacement = isset($replace_call_return[$var_name]) ? $replace_call_return[$var_name] : null;
 799
 800			if($var_replacement != null)
 801			{
 802				$user_str = str_replace('$' . $var_name, $var_replacement, $user_str);
 803			}
 804			else
 805			{
 806				// echo "\nVariable Swap For $var_name Failed.\n";
 807			}
 808
 809			$offset = $s + strlen($var_replacement);
 810		}
 811
 812		return $user_str;
 813	}
 814	public static function setup_test_result_directory($save_to)
 815	{
 816		$save_to_dir = PTS_SAVE_RESULTS_PATH . $save_to;
 817
 818		if(strpos(basename($save_to_dir), '.'))
 819		{
 820			$save_to_dir = dirname($save_to_dir);
 821		}
 822
 823		if($save_to_dir != '.')
 824		{
 825			pts_file_io::mkdir($save_to_dir);
 826		}
 827
 828		file_put_contents($save_to_dir . '/index.html', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><title>Phoronix Test Suite</title><meta http-equiv="REFRESH" content="0;url=composite.xml"></HEAD><BODY></BODY></HTML>');
 829
 830		return $save_to_dir;
 831	}
 832	public static function remove_installed_test(&$test_profile)
 833	{
 834		pts_file_io::delete($test_profile->get_install_dir(), null, true);
 835	}
 836	public static function exit_client($string = null, $exit_status = 0)
 837	{
 838		// Exit the Phoronix Test Suite client
 839		define('PTS_EXIT', 1);
 840
 841		if($string != null)
 842		{
 843			echo PHP_EOL . $string . PHP_EOL;
 844		}
 845
 846		exit($exit_status);
 847	}
 848	public static function current_user()
 849	{
 850		// Current system user
 851		return ($pts_user = pts_openbenchmarking_client::user_name()) != null ? $pts_user : phodevi::read_property('system', 'username');
 852	}
 853	public static function user_home_directory()
 854	{
 855		// Gets the system user's home directory
 856		static $userhome = null;
 857
 858		if($userhome == null)
 859		{
 860			if(function_exists('posix_getpwuid') && function_exists('posix_getuid'))
 861			{
 862				$userinfo = posix_getpwuid(posix_getuid());
 863				$userhome = $userinfo['dir'];
 864			}
 865			else if(($home = pts_client::read_env('HOME')))
 866			{
 867				$userhome = $home;
 868			}
 869			else if(($home = pts_client::read_env('HOMEPATH')))
 870			{
 871				$userhome = pts_client::read_env('HOMEDRIVE') . $home;
 872			}
 873			else
 874			{
 875				echo PHP_EOL . 'ERROR: Cannot find home directory.' . PHP_EOL;
 876				$userhome = null;
 877			}
 878
 879			$userhome = pts_strings::add_trailing_slash($userhome);
 880		}
 881
 882		return $userhome;
 883	}
 884	public static function test_profile_debug_message($message)
 885	{
 886		$reported = false;
 887
 888		if((pts_c::$test_flags & pts_c::debug_mode))
 889		{
 890			pts_client::$display->test_run_instance_error($message);
 891			$reported = true;
 892		}
 893
 894		return $reported;
 895	}
 896	public static function parse_home_directory($path)
 897	{
 898		// Find home directory if needed
 899		if(strpos($path, '~/') !== false)
 900		{
 901			$path = str_replace('~/', pts_client::user_home_directory(), $path);
 902		}
 903
 904		return pts_strings::add_trailing_slash($path);
 905	}
 906	public static function xsl_results_viewer_graph_template()
 907	{
 908		$raw_xsl = file_get_contents(PTS_RESULTS_VIEWER_PATH . 'pts-results-viewer.xsl');
 909
 910		// System Tables
 911		$conversions = array('systems', 'radar', 'overview', 'visualize');
 912		foreach($conversions as $convert)
 913		{
 914			$graph_string = pts_svg_dom::html_embed_code('result-graphs/' . $convert . '.BILDE_EXTENSION', 'SVG', array('width' => 'auto', 'height' => 'auto'), true);
 915			$raw_xsl = str_replace('<!-- ' . strtoupper($convert) . ' TAG -->', $graph_string, $raw_xsl);
 916		}
 917
 918		// Result Graphs
 919		$graph_string = pts_svg_dom::html_embed_code('result-graphs/<xsl:number value="position()" />.BILDE_EXTENSION', 'SVG', array('width' => 'auto', 'height' => 'auto'), true);
 920		$raw_xsl = str_replace('<!-- GRAPH TAG -->', $graph_string, $raw_xsl);
 921
 922		return $raw_xsl;
 923	}
 924	public static function generate_result_file_graphs($test_results_identifier, $save_to_dir = false)
 925	{
 926		if($save_to_dir)
 927		{
 928			if(pts_file_io::mkdir($save_to_dir . '/result-graphs') == false)
 929			{
 930				// Directory must exist, so remove any old graph files first
 931				foreach(pts_file_io::glob($save_to_dir . '/result-graphs/*') as $old_file)
 932				{
 933					unlink($old_file);
 934				}
 935			}
 936		}
 937
 938		$result_file = new pts_result_file($test_results_identifier);
 939
 940		$generated_graphs = array();
 941		$generated_graph_tables = false;
 942
 943		// Render overview chart
 944		if($save_to_dir)
 945		{
 946			$chart = new pts_ResultFileTable($result_file);
 947			$chart->renderChart($save_to_dir . '/result-graphs/overview.BILDE_EXTENSION');
 948
 949			$intent = -1;
 950			if($result_file->get_system_count() == 1 || ($intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true)))
 951			{
 952				$chart = new pts_ResultFileCompactSystemsTable($result_file, $intent);
 953			}
 954			else
 955			{
 956				$chart = new pts_ResultFileSystemsTable($result_file);
 957			}
 958			$chart->renderChart($save_to_dir . '/result-graphs/systems.BILDE_EXTENSION');
 959			unset($chart);
 960		}
 961
 962		foreach($result_file->get_result_objects() as $key => $result_object)
 963		{
 964			$save_to = $save_to_dir;
 965
 966			if($save_to_dir && is_dir($save_to_dir))
 967			{
 968				$save_to .= '/result-graphs/' . ($key + 1) . '.BILDE_EXTENSION';
 969
 970				if(PTS_IS_CLIENT)
 971				{
 972					if($result_file->is_multi_way_comparison() || pts_client::read_env('GRAPH_GROUP_SIMILAR'))
 973					{
 974						$table_keys = array();
 975						$titles = $result_file->get_test_titles();
 976
 977						foreach($titles as $this_title_index => $this_title)
 978						{
 979							if($this_title == $titles[$key])
 980							{
 981								array_push($table_keys, $this_title_index);
 982							}
 983						}
 984					}
 985					else
 986					{
 987						$table_keys = $key;
 988					}
 989
 990					$chart = new pts_ResultFileTable($result_file, null, $table_keys);
 991					$chart->renderChart($save_to_dir . '/result-graphs/' . ($key + 1) . '_table.BILDE_EXTENSION');
 992					unset($chart);
 993					$generated_graph_tables = true;
 994				}
 995			}
 996
 997			$graph = pts_render::render_graph($result_object, $result_file, $save_to);
 998			array_push($generated_graphs, $graph);
 999		}
1000
1001		// Generate mini / overview graphs
1002		if($save_to_dir)
1003		{
1004			$graph = new pts_OverviewGraph($result_file);
1005
1006			if($graph->doSkipGraph() == false)
1007			{
1008				$graph->renderGraph();
1009
1010				// Check to see if skip_graph was realized during the rendering process
1011				if($graph->doSkipGraph() == false)
1012				{
1013					$graph->svg_dom->output($save_to_dir . '/result-graphs/visualize.BILDE_EXTENSION');
1014				}
1015			}
1016			unset($graph);
1017
1018			$graph = new pts_RadarOverviewGraph($result_file);
1019
1020			if($graph->doSkipGraph() == false)
1021			{
1022				$graph->renderGraph();
1023
1024				// Check to see if skip_graph was realized during the rendering process
1025				if($graph->doSkipGraph() == false)
1026				{
1027					$graph->svg_dom->output($save_to_dir . '/result-graphs/radar.BILDE_EXTENSION');
1028				}
1029			}
1030			unset($graph);
1031		}
1032
1033		// Save XSL
1034		if(count($generated_graphs) > 0 && $save_to_dir)
1035		{
1036			file_put_contents($save_to_dir . '/pts-results-viewer.xsl', pts_client::xsl_results_viewer_graph_template($generated_graph_tables));
1037		}
1038
1039		return $generated_graphs;
1040	}
1041	public static function process_shutdown_tasks()
1042	{
1043		// TODO: possibly do something like posix_getpid() != pts_client::$startup_pid in case shutdown function is called from a child process
1044
1045		// Generate Phodevi Smart Cache
1046		if(pts_flags::no_phodevi_cache() == false && pts_client::read_env('EXTERNAL_PHODEVI_CACHE') == false)
1047		{
1048			if(pts_config::read_bool_config('PhoronixTestSuite/Options/General/UsePhodeviCache', 'TRUE'))
1049			{
1050				pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'phodevi_smart_cache', phodevi::get_phodevi_cache_object(PTS_USER_PATH, PTS_CORE_VERSION));
1051			}
1052			else
1053			{
1054				pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'phodevi_smart_cache', null);
1055			}
1056		}
1057
1058		if(is_array(self::$lock_pointers))
1059		{
1060			foreach(array_keys(self::$lock_pointers) as $lock_file)
1061			{
1062				self::release_lock($lock_file);
1063			}
1064		}
1065	}
1066	public static function do_anonymous_usage_reporting()
1067	{
1068		return pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', 0);
1069	}
1070	public static function release_lock($lock_file)
1071	{
1072		// Remove lock
1073		if(isset(self::$lock_pointers[$lock_file]) == false)
1074		{
1075			return false;
1076		}
1077
1078		if(is_resource(self::$lock_pointers[$lock_file]))
1079		{
1080			fclose(self::$lock_pointers[$lock_file]);
1081		}
1082
1083		pts_file_io::unlink($lock_file);
1084		unset(self::$lock_pointers[$lock_file]);
1085	}
1086	public static function check_command_for_function($option, $check_function)
1087	{
1088		$in_option = false;
1089
1090		if(is_file(PTS_COMMAND_PATH . $option . '.php'))
1091		{
1092			if(!class_exists($option, false) && is_file(PTS_COMMAND_PATH . $option . '.php'))
1093			{
1094				include(PTS_COMMAND_PATH . $option . '.php');
1095			}
1096
1097			if(method_exists($option, $check_function))
1098			{
1099				$in_option = true;
1100			}
1101		}
1102
1103		return $in_option;
1104	}
1105	public static function regenerate_graphs($result_file_identifier, $full_process_string = false, $extra_graph_attributes = null)
1106	{
1107		$save_to_dir = pts_client::setup_test_result_directory($result_file_identifier);
1108		$generated_graphs = pts_client::generate_result_file_graphs($result_file_identifier, $save_to_dir, false, $extra_graph_attributes);
1109		$generated = count($generated_graphs) > 0;
1110
1111		if($generated && $full_process_string)
1112		{
1113			echo PHP_EOL . $full_process_string . PHP_EOL;
1114			pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $result_file_identifier . '/index.html');
1115		}
1116
1117		return $generated;
1118	}
1119	public static function set_test_flags($test_flags = 0)
1120	{
1121		pts_c::$test_flags = $test_flags;
1122	}
1123	public static function execute_command($command, $pass_args = null)
1124	{
1125		if(!class_exists($command, false) && is_file(PTS_COMMAND_PATH . $command . '.php'))
1126		{
1127			include(PTS_COMMAND_PATH . $command . '.php');
1128		}
1129
1130		if(is_file(PTS_COMMAND_PATH . $command . '.php') && method_exists($command, 'argument_checks'))
1131		{
1132			$argument_checks = call_user_func(array($command, 'argument_checks'));
1133
1134			foreach($argument_checks as &$argument_check)
1135			{
1136				$function_check = $argument_check->get_function_check();
1137				$method_check = false;
1138
1139				if(is_array($function_check) && count($function_check) == 2)
1140				{
1141					$method_check = $function_check[0];
1142					$function_check = $function_check[1];
1143				}
1144
1145				if(substr($function_check, 0, 1) == '!')
1146				{
1147					$function_check = substr($function_check, 1);
1148					$return_fails_on = true;
1149				}
1150				else
1151				{
1152					$return_fails_on = false;
1153				}
1154
1155				
1156				if($method_check != false)
1157				{
1158					if(!method_exists($method_check, $function_check))
1159					{
1160						echo PHP_EOL . 'Method check fails.' . PHP_EOL;
1161						continue;
1162					}
1163
1164					$function_check = array($method_check, $function_check);
1165				}
1166				else if(!function_exists($function_check))
1167				{
1168					continue;
1169				}
1170
1171				if($argument_check->get_argument_index() == 'VARIABLE_LENGTH')
1172				{
1173					$return_value = null;
1174
1175					foreach($pass_args as $arg)
1176					{
1177						$return_value = call_user_func_array($function_check, array($arg));
1178
1179						if($return_value == true)
1180						{
1181							break;
1182						}
1183					}
1184
1185				}
1186				else
1187				{
1188					$return_value = call_user_func_array($function_check, array((isset($pass_args[$argument_check->get_argument_index()]) ? $pass_args[$argument_check->get_argument_index()] : null)));
1189				}
1190
1191				if($return_value == $return_fails_on)
1192				{
1193					$command_alias = defined($command . '::doc_use_alias') ? constant($command . '::doc_use_alias') : $command;
1194
1195					if((isset($pass_args[$argument_check->get_argument_index()]) && !empty($pass_args[$argument_check->get_argument_index()])) || ($argument_check->get_argument_index() == 'VARIABLE_LENGTH' && !empty($pass_args)))
1196					{
1197						pts_client::$display->generic_error('Invalid Argument: ' . implode(' ', $pass_args));
1198					}
1199					else
1200					{
1201						pts_client::$display->generic_error('Argument Missing.');
1202					}
1203
1204					echo 'CORRECT SYNTAX' . PHP_EOL . 'phoronix-test-suite ' . str_replace('_', '-', $command_alias) . ' ' . implode(' ', $argument_checks) . PHP_EOL . PHP_EOL;
1205
1206					if(method_exists($command, 'invalid_command'))
1207					{
1208						call_user_func_array(array($command, 'invalid_command'), $pass_args);
1209						echo PHP_EOL;
1210					}
1211
1212					return false;
1213				}
1214				else
1215				{
1216					if($argument_check->get_function_return_key() != null && !isset($pass_args[$argument_check->get_function_return_key()]))
1217					{
1218						$pass_args[$argument_check->get_function_return_key()] = $return_value;
1219					}
1220				}
1221			}
1222		}
1223
1224		pts_module_manager::module_process('__pre_option_process', $command);
1225
1226		if(is_file(PTS_COMMAND_PATH . $command . '.php'))
1227		{
1228			if(method_exists($command, 'run'))
1229			{
1230				call_user_func(array($command, 'run'), $pass_args);
1231			}
1232			else
1233			{
1234				echo PHP_EOL . 'There is an error in the requested command: ' . $command . PHP_EOL . PHP_EOL;
1235			}
1236		}
1237		else if(($t = pts_module::valid_run_command($command)) != false)
1238		{
1239			list($module, $module_command) = $t;
1240			pts_module_manager::set_current_module($module);
1241			pts_module_manager::run_command($module, $module_command, $pass_args);
1242			pts_module_manager::set_current_module(null);
1243		}
1244		echo PHP_EOL;
1245
1246		pts_module_manager::module_process('__post_option_process', $command);
1247	}
1248	public static function terminal_width()
1249	{
1250		static $terminal_width = null;
1251
1252		if($terminal_width == null)
1253		{
1254			$chars = -1;
1255
1256			if(pts_client::executable_in_path('tput'))
1257			{
1258				$terminal_width = trim(shell_exec('tput cols 2>&1'));
1259
1260				if(is_numeric($terminal_width) && $terminal_width > 1)
1261				{
1262					$chars = $terminal_width;
1263				}
1264			}
1265			else if(phodevi::is_windows())
1266			{
1267				// Need a better way to handle this
1268				$chars = 80;
1269			}
1270
1271			$terminal_width = $chars;
1272		}
1273
1274		return $terminal_width;
1275	}
1276	public static function user_hardware_software_reporting()
1277	{
1278		$hw_reporting = pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting', 'FALSE');
1279		$sw_reporting = pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting', 'FALSE');
1280
1281		if($hw_reporting == false && $sw_reporting == false)
1282		{
1283			return;
1284		}
1285
1286		$hw = array();
1287		$sw = array();
1288		$pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE);
1289
1290		if($hw_reporting)
1291		{
1292			$hw = array();
1293			foreach(pts_openbenchmarking::stats_hardware_list() as $key => $value)
1294			{
1295				if(count($value) == 2)
1296				{
1297					$hw[$key] = phodevi::read_property($value[0], $value[1]);
1298				}
1299				else
1300				{
1301					$hw[$key] = phodevi::read_name($value[0]);
1302				}
1303			}
1304
1305			$hw_prev = $pso->read_object('global_reported_hw');
1306			$pso->add_object('global_reported_hw', $hw);
1307
1308			if(is_array($hw_prev))
1309			{
1310				$hw = array_diff_assoc($hw, $hw_prev);
1311			}
1312
1313			// Check the PCI devices
1314			$pci = phodevi::read_property('motherboard', 'pci-devices');
1315			$pci_prev = $pso->read_object('global_reported_pci');
1316			$pso->add_object('global_reported_pci', $pci);
1317
1318			if(!empty($pci_prev) && is_array($pci_prev) && is_array($pci))
1319			{
1320				$pci = array_diff($pci, $pci_prev);
1321			}
1322
1323			if(!empty($pci))
1324			{
1325				pts_openbenchmarking_client::upload_pci_data($pci);
1326			}
1327
1328			// Check the USB devices
1329			$usb = phodevi::read_property('motherboard', 'usb-devices');
1330			$usb_prev = $pso->read_object('global_reported_usb');
1331			$pso->add_object('global_reported_usb', $usb);
1332
1333			if(!empty($usb_prev) && is_array($usb_prev) && is_array($usb))
1334			{
1335				$usb = array_diff($usb, $usb_prev);
1336			}
1337
1338			if(!empty($usb))
1339			{
1340				pts_openbenchmarking_client::upload_usb_data($usb);
1341			}
1342		}
1343		if($sw_reporting)
1344		{
1345			$sw = array();
1346			foreach(pts_openbenchmarking::stats_software_list() as $key => $value)
1347			{
1348				if(count($value) == 2)
1349				{
1350					$sw[$key] = phodevi::read_property($value[0], $value[1]);
1351				}
1352				else
1353				{
1354					$sw[$key] = phodevi::read_name($value[0]);
1355				}
1356			}
1357			$sw_prev = $pso->read_object('global_reported_sw');
1358			$pso->add_object('global_reported_sw', $sw);
1359
1360			if(is_array($sw_prev))
1361			{
1362				$sw = array_diff_assoc($sw, $sw_prev);
1363			}
1364		}
1365
1366		$to_report = array_merge($hw, $sw);
1367		$pso->save_to_file(PTS_CORE_STORAGE);
1368
1369		if(!empty($to_report))
1370		{
1371			pts_openbenchmarking_client::upload_hwsw_data($to_report);
1372		}				
1373	}
1374	public static function is_process_running($process)
1375	{
1376		if(phodevi::is_linux())
1377		{
1378			// Checks if process is running on the system
1379			$running = shell_exec('ps -C ' . strtolower($process) . ' 2>&1');
1380			$running = trim(str_replace(array('PID', 'TTY', 'TIME', 'CMD'), '', $running));
1381		}
1382		else if(phodevi::is_solaris())
1383		{
1384			// Checks if process is running on the system
1385			$ps = shell_exec('ps -ef 2>&1');
1386			$running = strpos($ps, ' ' . strtolower($process)) != false ? 'TRUE' : null;
1387		}
1388		else if(pts_client::executable_in_path('ps') != false)
1389		{
1390			// Checks if process is running on the system
1391			$ps = shell_exec('ps -ax 2>&1');
1392			$running = strpos($ps, ' ' . strtolower($process)) != false ? 'TRUE' : null;
1393		}
1394		else
1395		{
1396			$running = null;
1397		}
1398
1399		return !empty($running);
1400	}
1401	public static function parse_value_string_double_identifier($value_string)
1402	{
1403		// i.e. with PRESET_OPTIONS='stream.run-type=Add'
1404		$values = array();
1405
1406		foreach(explode(';', $value_string) as $preset)
1407		{
1408			if(count($preset = pts_strings::trim_explode('=', $preset)) == 2)
1409			{
1410				if(count($preset[0] = pts_strings::trim_explode('.', $preset[0])) == 2)
1411				{
1412					$values[$preset[0][0]][$preset[0][1]] = $preset[1];
1413				}
1414			}
1415		}
1416
1417		return $values;
1418	}
1419	public static function create_temporary_file()
1420	{
1421		return tempnam(pts_client::temporary_directory(), 'PTS');
1422	}
1423	public static function temporary_directory()
1424	{
1425		if(PHP_VERSION_ID >= 50210)
1426		{
1427			$dir = sys_get_temp_dir();
1428		}
1429		else
1430		{
1431			$dir = '/tmp'; // Assume /tmp
1432		}
1433
1434		return $dir;
1435	}
1436	public static function read_env($var)
1437	{
1438		return getenv($var);
1439	}
1440	public static function pts_set_environmental_variable($name, $value)
1441	{
1442		// Sets an environmental variable
1443		return getenv($name) == false && putenv($name . '=' . $value);
1444	}
1445	public static function shell_exec($exec, $extra_vars = null)
1446	{
1447		// Same as shell_exec() but with the PTS env variables added in
1448		// Convert pts_client::environmental_variables() into shell export variable syntax
1449
1450		$var_string = '';
1451		$extra_vars = ($extra_vars == null ? pts_client::environmental_variables() : array_merge(pts_client::environmental_variables(), $extra_vars));
1452
1453		foreach(array_keys($extra_vars) as $key)
1454		{
1455			$var_string .= 'export ' . $key . '=' . $extra_vars[$key] . ';';
1456		}
1457
1458		$var_string .= ' ';
1459
1460		return shell_exec($var_string . $exec);
1461	}
1462	public static function executable_in_path($executable)
1463	{
1464		static $cache = null;
1465
1466		if(!isset($cache[$executable]))
1467		{
1468			$paths = pts_strings::trim_explode((phodevi::is_windows() ? ';' : ':'), (($path = pts_client::read_env('PATH')) == false ? '/usr/bin:/usr/local/bin' : $path));
1469			$executable_path = false;
1470
1471			foreach($paths as $path)
1472			{
1473				$path = pts_strings::add_trailing_slash($path);
1474
1475				if(is_executable($path . $executable))
1476				{
1477					$executable_path = $path . $executable;
1478					break;
1479				}
1480			}
1481
1482			$cache[$executable] = $executable_path;
1483		}
1484
1485		return $cache[$executable];
1486	}
1487	public static function display_web_page($URL, $alt_text = null, $default_open = false, $auto_open = false)
1488	{
1489		if(((pts_c::$test_flags & pts_c::auto_mode) && $auto_open == false && $default_open == false) || (pts_client::read_env('DISPLAY') == false && phodevi::is_windows() == false && phodevi::is_macosx() == false))
1490		{
1491			return;
1492		}
1493
1494		// Launch the web browser
1495		$text = $alt_text == null ? 'Do you want to view the results in your web browser' : $alt_text;
1496
1497		if($auto_open == false)
1498		{
1499			if((pts_c::$test_flags & pts_c::batch_mode))
1500			{
1501				$view_results = pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/OpenBrowser', 'FALSE');
1502			}
1503			else
1504			{
1505				$view_results = pts_user_io::prompt_bool_input($text, $default_open);
1506			}
1507		}
1508		else
1509		{
1510			$view_results = true;
1511		}
1512
1513		if($view_results)
1514		{
1515			static $browser = null;
1516
1517			if($browser == null)
1518			{
1519				$config_browser = pts_config::read_user_config('PhoronixTestSuite/Options/General/DefaultBrowser', null);
1520
1521				if($config_browser != null && (is_executable($config_browser) || ($config_browser = pts_client::executable_in_path($config_browser))))
1522				{
1523					$browser = $config_browser;
1524				}
1525				else if(phodevi::is_windows())
1526				{
1527					$windows_browsers = array(
1528						'C:\Program Files (x86)\Mozilla Firefox\firefox.exe',
1529						'C:\Program Files\Internet Explorer\iexplore.exe'
1530						);
1531
1532					foreach($windows_browsers as $browser_test)
1533					{
1534						if(is_executable($browser_test))
1535						{
1536							$browser = $browser_test;
1537							break;
1538						}
1539					}
1540
1541					if(substr($URL, 0, 1) == '\\')
1542					{
1543						$URL = 'file:///C:' . str_replace('/', '\\', $URL);
1544					}
1545				}
1546				else
1547				{
1548					$possible_browsers = array('epiphany', 'firefox', 'mozilla', 'x-www-browser', 'open', 'xdg-open', 'iceweasel', 'konqueror');
1549
1550					foreach($possible_browsers as &$b)
1551					{
1552						if(($b = pts_client::executable_in_path($b)))
1553						{
1554							$browser = $b;
1555							break;
1556						}
1557					}
1558				}
1559			}
1560
1561			if($browser != null)
1562			{
1563				shell_exec($browser . ' "' . $URL . '" 2> /dev/null &');
1564			}
1565			else
1566			{
1567				echo PHP_EOL . 'No Web Browser Found.' . PHP_EOL;
1568			}
1569		}
1570	}
1571	public static function cache_hardware_calls()
1572	{
1573		phodevi::system_hardware(true);
1574		phodevi::supported_sensors();
1575		phodevi::unsupported_sensors();
1576	}
1577	public static function cache_software_calls()
1578	{
1579		phodevi::system_software(true);
1580	}
1581	public static function remove_saved_result_file($identifier)
1582	{
1583		pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $identifier, null, true);
1584	}
1585	public static function saved_test_results()
1586	{
1587		$results = array();
1588		$ignore_ids = array();
1589
1590		foreach(pts_file_io::glob(PTS_SAVE_RESULTS_PATH . '*/composite.xml') as $result_file)
1591		{
1592			$identifier = basename(dirname($result_file));
1593
1594			if(!in_array($identifier, $ignore_ids))
1595			{
1596				array_push($results, $identifier);
1597			}
1598		}
1599
1600		return $results;
1601	}
1602	public static function code_error_handler($error_code, $error_string, $error_file, $error_line)
1603	{
1604		if(($error_code & (E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)))
1605		{
1606			// It's a self-generated error by pts-core code intentionally
1607			return self::user_error_handler($error_code, $error_string, $error_file, $error_line);
1608		}
1609
1610		/*if(!(error_reporting() & $error_code))
1611		{
1612			return;
1613		}*/
1614
1615		switch($error_code)
1616		{
1617			case E_ERROR:
1618			case E_PARSE:
1619				$error_type = 'ERROR';
1620				break;
1621			case E_WARNING:
1622			case E_NOTICE:
1623				if(($s = strpos($error_string, 'Undefined ')) !== false && ($x = strpos($error_string, ': ', $s)) !== false)
1624				{
1625					$error_string = 'Undefined: ' . substr($error_string, ($x + 2));
1626				}
1627				else if(strpos($error_string, 'Name or service not known') !== false || strpos($error_string, 'HTTP request failed') !== false || strpos($error_string, 'fopen') !== false || strpos($error_string, 'file_get_contents') !== false)
1628				{
1629					// Don't report network errors
1630					return;
1631				}
1632				$error_type = 'NOTICE';
1633				break;
1634			default:
1635				$error_type = $error_code;
1636				break;
1637		}
1638
1639		echo PHP_EOL . '[' . $error_type . '] ' . $error_string . ' in ' . basename($error_file) . ':' . $error_line . PHP_EOL;
1640
1641		if($error_type == 'ERROR')
1642		{
1643			exit(1);
1644		}
1645	}
1646	public static function user_error_handler($error_code, $error_string, $error_file, $error_line)
1647	{
1648/*
1649
1650		trigger_error('Scheisse', E_USER_WARNING);
1651		trigger_error('Okay', E_USER_NOTICE);
1652		trigger_error('F', E_USER_ERROR);
1653*/
1654		switch($error_code)
1655		{
1656			case E_USER_ERROR:
1657				$error_type = 'ERROR';
1658				break;
1659			case E_USER_NOTICE:
1660				if(pts_client::is_client_debug_mode() == false)
1661				{
1662					return;
1663				}
1664				$error_type = 'NOTICE';
1665				break;
1666			case E_USER_WARNING:
1667				$error_type = 'NOTICE'; // Yes, report warnings as a notice label
1668				break;
1669		}
1670
1671		echo PHP_EOL . '[' . $error_type . '] ' . $error_string . (pts_client::is_client_debug_mode() ? ' in ' . basename($error_file) . ':' . $error_line : null) . PHP_EOL;
1672		return;
1673	}
1674	public static function is_client_debug_mode()
1675	{
1676		return false; // TODO
1677	}
1678}
1679
1680// Some extra magic
1681set_error_handler(array('pts_client', 'code_error_handler'));
1682
1683if(PTS_IS_CLIENT && (PTS_IS_DEV_BUILD || pts_client::is_client_debug_mode()))
1684{
1685	// Enable more verbose error reporting only when PTS is in development with milestone (alpha/beta) releases but no release candidate (r) or gold versions
1686	error_reporting(E_ALL | E_NOTICE | E_STRICT);
1687}
1688
1689?>