1 2<?php 3 4/* 5 Phoronix Test Suite 6 URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ 7 Copyright (C) 2008 - 2021, Phoronix Media 8 Copyright (C) 2008 - 2021, Michael Larabel 9 phodevi_system.php: The PTS Device Interface object for the system software 10 11 This program is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 3 of the License, or 14 (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program. If not, see <http://www.gnu.org/licenses/>. 23*/ 24 25class phodevi_system extends phodevi_device_interface 26{ 27 public static $report_wine_override = false; 28 29 public static function properties() 30 { 31 return array( 32 'username' => new phodevi_device_property('sw_username', phodevi::std_caching), 33 'hostname' => new phodevi_device_property('sw_hostname', phodevi::smart_caching), 34 'vendor-identifier' => new phodevi_device_property('sw_vendor_identifier', phodevi::smart_caching), 35 'filesystem' => new phodevi_device_property('sw_filesystem', phodevi::no_caching), 36 'virtualized-mode' => new phodevi_device_property('sw_virtualized_mode', phodevi::smart_caching), 37 'java-version' => new phodevi_device_property('sw_java_version', phodevi::std_caching), 38 'python-version' => new phodevi_device_property('sw_python_version', phodevi::std_caching), 39 'wine-version' => new phodevi_device_property('sw_wine_version', phodevi::std_caching), 40 'display-server' => new phodevi_device_property('sw_display_server', phodevi::smart_caching), 41 'display-driver' => new phodevi_device_property(array('sw_display_driver', false), phodevi::smart_caching), 42 'display-driver-string' => new phodevi_device_property(array('sw_display_driver', true), phodevi::smart_caching), 43 'dri-display-driver' => new phodevi_device_property('sw_dri_display_driver', phodevi::smart_caching), 44 'opengl-driver' => new phodevi_device_property('sw_opengl_driver', phodevi::std_caching), 45 'vulkan-driver' => new phodevi_device_property('sw_vulkan_driver', phodevi::std_caching), 46 'opencl-driver' => new phodevi_device_property('sw_opencl_driver', phodevi::std_caching), 47 'opengl-vendor' => new phodevi_device_property('sw_opengl_vendor', phodevi::smart_caching), 48 'desktop-environment' => new phodevi_device_property('sw_desktop_environment', phodevi::smart_caching), 49 'operating-system' => new phodevi_device_property('sw_operating_system', phodevi::smart_caching), 50 'os-version' => new phodevi_device_property('sw_os_version', phodevi::smart_caching), 51 'kernel' => new phodevi_device_property('sw_kernel', phodevi::smart_caching), 52 'kernel-architecture' => new phodevi_device_property('sw_kernel_architecture', phodevi::smart_caching), 53 'kernel-date' => new phodevi_device_property('sw_kernel_date', phodevi::smart_caching), 54 'kernel-string' => new phodevi_device_property('sw_kernel_string', phodevi::smart_caching), 55 'kernel-parameters' => new phodevi_device_property('sw_kernel_parameters', phodevi::std_caching), 56 'compiler' => new phodevi_device_property('sw_compiler', phodevi::no_caching), 57 'system-layer' => new phodevi_device_property('sw_system_layer', phodevi::no_caching), 58 'environment-variables' => new phodevi_device_property('sw_environment_variables', phodevi::std_caching), 59 'security-features' => new phodevi_device_property('sw_security_features', phodevi::std_caching), 60 'kernel-extra-details' => new phodevi_device_property('sw_kernel_extra_details', phodevi::std_caching), 61 'battery' => new phodevi_device_property('battery', phodevi::smart_caching), 62 'platform-profile' => new phodevi_device_property('sw_platform_profile', phodevi::std_caching), 63 ); 64 } 65 public static function sw_username() 66 { 67 // Gets the system user's name 68 if(function_exists('posix_getpwuid') && function_exists('posix_getuid')) 69 { 70 $userinfo = posix_getpwuid(posix_getuid()); 71 $username = $userinfo['name']; 72 } 73 else 74 { 75 $username = trim(getenv('USERNAME')); 76 } 77 78 return $username; 79 } 80 public static function sw_platform_profile() 81 { 82 $platform_profile = ''; 83 84 if(phodevi::is_linux()) 85 { 86 if(is_file('/sys/firmware/acpi/platform_profile')) 87 { 88 $platform_profile = pts_file_io::file_get_contents('/sys/firmware/acpi/platform_profile'); 89 } 90 } 91 92 return $platform_profile; 93 } 94 public static function sw_kernel_extra_details() 95 { 96 $extra = array(); 97 98 if(phodevi::is_linux()) 99 { 100 if(is_file('/sys/kernel/mm/transparent_hugepage/enabled')) 101 { 102 $thp_enabled = file_get_contents('/sys/kernel/mm/transparent_hugepage/enabled'); 103 if(($x = strpos($thp_enabled, '[')) !== false) 104 { 105 $thp_enabled = substr($thp_enabled, $x + 1); 106 if(($x = strpos($thp_enabled, ']')) !== false) 107 { 108 $thp_enabled = trim(substr($thp_enabled, 0, $x)); 109 if(!empty($thp_enabled)) 110 { 111 $extra[] = 'Transparent Huge Pages: ' . $thp_enabled; 112 } 113 } 114 } 115 116 } 117 } 118 119 return implode(' - ', $extra); 120 } 121 public static function sw_system_layer() 122 { 123 $layer = null; 124 125 if(phodevi::is_windows() && pts_client::executable_in_path('winecfg.exe') && ($wine = phodevi::read_property('system', 'wine-version'))) 126 { 127 $layer = $wine; 128 } 129 else if((getenv('USE_WINE') || getenv('WINE_VERSION') || self::$report_wine_override) && ($wine = phodevi::read_property('system', 'wine-version'))) 130 { 131 $layer = $wine; 132 } 133 else 134 { 135 // Report virtualization 136 $layer = phodevi::read_property('system', 'virtualized-mode'); 137 } 138 139 if(empty($layer) && is_file('/proc/version')) 140 { 141 if(stripos(file_get_contents('/proc/version'), 'Microsoft') !== false && stripos(file_get_contents('/proc/mounts'), 'lxfs') !== false) 142 { 143 // Microsoft Windows Subsystem for Linux 144 $layer = 'WSL'; 145 } 146 } 147 148 return $layer; 149 } 150 public static function sw_hostname() 151 { 152 $hostname = 'Unknown'; 153 154 if(($bin = pts_client::executable_in_path('hostname'))) 155 { 156 $hostname = trim(shell_exec($bin . ' 2>&1')); 157 } 158 else if(phodevi::is_windows()) 159 { 160 $hostname = getenv('USERDOMAIN'); 161 } 162 163 return $hostname; 164 } 165 public static function sw_vendor_identifier() 166 { 167 // Returns the vendor identifier used with the External Dependencies and other distro-specific features 168 $vendor = phodevi::is_linux() ? phodevi_linux_parser::read_lsb_distributor_id() : false; 169 170 if(!$vendor) 171 { 172 $vendor = phodevi::read_property('system', 'operating-system'); 173 174 if(($spos = strpos($vendor, ' ')) > 1) 175 { 176 $vendor = substr($vendor, 0, $spos); 177 } 178 } 179 180 return str_replace(array(' ', '/'), '', strtolower($vendor)); 181 } 182 public static function sw_filesystem() 183 { 184 // Determine file-system type 185 $fs = null; 186 187 if(phodevi::is_macos()) 188 { 189 $fs = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'FileSystem', false, array('MS-DOS FAT32')); 190 191 if($fs == null && pts_client::executable_in_path('mount')) 192 { 193 $mount = shell_exec('mount 2>&1'); 194 if(stripos($mount, ' on / (hfs, local, journaled)') !== false) 195 { 196 $fs = 'Journaled HFS+'; 197 } 198 else if(stripos($mount, ' on / (hfs') !== false) 199 { 200 $fs = 'HFS+'; 201 } 202 else if(stripos($mount, ' on / (apfs') !== false) 203 { 204 $fs = 'APFS'; 205 } 206 } 207 } 208 else if(phodevi::is_bsd()) 209 { 210 if(pts_client::executable_in_path('mount')) 211 { 212 $mount = shell_exec('mount 2>&1'); 213 214 if(($start = strpos($mount, 'on / (')) != false) 215 { 216 // FreeBSD, DragonflyBSD mount formatting 217 /* 218 -bash-4.0$ mount 219 ROOT on / (hammer, local) 220 /dev/da0s1a on /boot (ufs, local) 221 /pfs/@@-1:00001 on /var (null, local) 222 /pfs/@@-1:00002 on /tmp (null, local) 223 /pfs/@@-1:00003 on /usr (null, local) 224 /pfs/@@-1:00004 on /home (null, local) 225 /pfs/@@-1:00005 on /usr/obj (null, local) 226 /pfs/@@-1:00006 on /var/crash (null, local) 227 /pfs/@@-1:00007 on /var/tmp (null, local) 228 procfs on /proc (procfs, local) 229 */ 230 231 // TODO: improve this in case there are other partitions, etc 232 $fs = substr($mount, $start + 6); 233 $fs = substr($fs, 0, strpos($fs, ',')); 234 } 235 else if(($start = strpos($mount, 'on / type')) != false) 236 { 237 // OpenBSD 5.0 formatting is slightly different from above FreeBSD example 238 // TODO: improve this in case there are other partitions, etc 239 $fs = substr($mount, $start + 10); 240 $fs = substr($fs, 0, strpos($fs, ' ')); 241 } 242 } 243 } 244 else if(phodevi::is_hurd()) 245 { 246 // Very rudimentary Hurd filesystem detection support but works for at least a clean Debian GNU/Hurd EXT2 install 247 if(pts_client::executable_in_path('mount')) 248 { 249 $mount = shell_exec('mount 2>&1'); 250 251 if(($start = strpos($mount, 'on / type')) != false) 252 { 253 $fs = substr($mount, $start + 10); 254 $fs = substr($fs, 0, strpos($fs, ' ')); 255 256 if(substr($fs, -2) == 'fs') 257 { 258 $fs = substr($fs, 0, -2); 259 } 260 } 261 } 262 } 263 else if(phodevi::is_linux() || phodevi::is_solaris()) 264 { 265 $fs = trim(shell_exec('stat ' . pts_client::test_install_root_path() . ' -L -f -c %T 2> /dev/null')); 266 267 switch($fs) 268 { 269 case 'ext2/ext3': 270 if(isset(phodevi::$vfs->mounts)) 271 { 272 $fstab = phodevi::$vfs->mounts; 273 $fstab = str_replace('/boot ', 'IGNORE', $fstab); 274 275 $using_ext2 = strpos($fstab, ' ext2') !== false; 276 $using_ext3 = strpos($fstab, ' ext3') !== false; 277 $using_ext4 = strpos($fstab, ' ext4') !== false; 278 279 if(!$using_ext2 && !$using_ext3 && $using_ext4) 280 { 281 $fs = 'ext4'; 282 } 283 else if(!$using_ext2 && !$using_ext4 && $using_ext3) 284 { 285 $fs = 'ext3'; 286 } 287 else if(!$using_ext3 && !$using_ext4 && $using_ext2) 288 { 289 $fs = 'ext2'; 290 } 291 else if(is_dir('/proc/fs/ext4/')) 292 { 293 $fs = 'ext4'; 294 } 295 else if(is_dir('/proc/fs/ext3/')) 296 { 297 $fs = 'ext3'; 298 } 299 } 300 break; 301 case 'Case-sensitive Journaled HFS+': 302 $fs = 'HFS+'; 303 break; 304 case 'MS-DOS FAT32': 305 $fs = 'FAT32'; 306 break; 307 case 'UFSD_NTFS_COMPR': 308 $fs = 'NTFS'; 309 break; 310 case 'ecryptfs': 311 if(isset(phodevi::$vfs->mounts)) 312 { 313 // An easy attempt to determine what file-system is underneath ecryptfs if being compared 314 // For now just attempt to figure out the root file-system. 315 if(($s = strrpos(phodevi::$vfs->mounts, ' / ')) !== false) 316 { 317 $s = substr(phodevi::$vfs->mounts, ($s + 3)); 318 $s = substr($s, 0, strpos($s, ' ')); 319 320 321 if($s != null && !isset($s[18]) && $s != 'rootfs'&& pts_strings::string_only_contains($s, pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC)) 322 { 323 $fs = $s . ' (ecryptfs)'; 324 } 325 } 326 } 327 break; 328 default: 329 if(substr($fs, 0, 9) == 'UNKNOWN (') 330 { 331 $magic_block = substr($fs, 9, -1); 332 $known_magic_blocks = array( 333 '0x9123683e' => 'Btrfs', 334 '0x2fc12fc1' => 'zfs', // KQ Infotech ZFS 335 '0x482b' => 'HFS+', 336 '0x65735546' => 'FUSE', 337 '0x565a4653' => 'ReiserFS', 338 '0x52345362' => 'Reiser4', 339 '0x3434' => 'NILFS2', 340 '0x5346414f' => 'OpenAFS', 341 '0x47504653' => 'GPFS', 342 '0x5941ff53' => 'YAFFS', 343 '0xff534d42' => 'CIFS', 344 '0x24051905' => 'UBIFS', 345 '0x1021994' => 'TMPFS', 346 '0x73717368' => 'SquashFS', 347 '0xc97e8168' => 'LogFS', 348 '0x5346544E' => 'NTFS', 349 '0xf15f' => 'eCryptfs', 350 '0x61756673' => 'AuFS', 351 '0xbd00bd0' => 'Lustre', 352 '0xaad7aaea' => 'PanFS', // Panasas FS 353 '0xf2f52010' => 'F2FS', 354 '0xc36400' => 'CephFS', 355 '0x53464846' => 'WSLFS', 356 '0xca451a4e' => 'BcacheFS' 357 ); 358 359 foreach($known_magic_blocks as $hex => $name) 360 { 361 if($magic_block == $hex) 362 { 363 $fs = $name; 364 break; 365 } 366 } 367 } 368 break; 369 } 370 371 if(strpos($fs, 'UNKNOWN') !== false && isset(phodevi::$vfs->mounts)) 372 { 373 $mounts = phodevi::$vfs->mounts; 374 $fs_r = array(); 375 376 $fs_checks = array( 377 'squashfs' => 'SquashFS', 378 'aufs' => 'AuFS', 379 'unionfs' => 'UnionFS', 380 'overlay' => 'overlayfs', 381 ); 382 383 foreach($fs_checks as $fs_module => $fs_name) 384 { 385 if(strpos($mounts, $fs_module) != false) 386 { 387 array_push($fs_r, $fs_name); 388 } 389 } 390 391 if(count($fs_r) > 0) 392 { 393 $fs = implode(' + ', $fs_r); 394 } 395 } 396 } 397 else if(phodevi::is_windows()) 398 { 399 // TODO could use better detection to verify if C: or the desired disk under test... but most of the time will be NTFS anyways 400 $fs = filter_var(trim(shell_exec('powershell "(Get-WMIObject -Class Win32_Volume | Select DriveLetter,FreeSpace,Capacity,DeviceID,Label,@{Name=\"FileSystemType\";Expression={$_.\"FileSystem\"}})[1].FileSystemType"')), FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH); 401 if(empty($fs) || $fs == 'Unknown' || $fs == 'FAT32') 402 { 403 $fs = filter_var(trim(shell_exec('powershell "(Get-WMIObject -Class Win32_Volume | Select DriveLetter,FreeSpace,Capacity,DeviceID,Label,@{Name=\"FileSystemType\";Expression={$_.\"FileSystem\"}})[0].FileSystemType"')),FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH); 404 } 405 406 // Fallback for Windows 8 407 if(empty($fs) || $fs == 'Unknown' || $fs == 'FAT32' || stripos($fs, 'not')) 408 { 409 if(strpos(shell_exec('fsutil fsinfo volumeinfo C:'), 'NTFS') !== false) 410 { 411 $fs = 'NTFS'; 412 } 413 } 414 } 415 416 if(empty($fs)) 417 { 418 $fs = 'Unknown'; 419 } 420 421 return $fs; 422 } 423 public static function sw_virtualized_mode() 424 { 425 // Reports if system is running virtualized 426 $virtualized = null; 427 $mobo = phodevi::read_name('motherboard'); 428 $gpu = phodevi::read_name('gpu'); 429 $cpu = phodevi::read_property('cpu', 'model'); 430 431 if(strpos($cpu, 'QEMU') !== false || (is_readable('/sys/class/dmi/id/bios_vendor') && pts_file_io::file_get_contents('/sys/class/dmi/id/bios_vendor') == 'QEMU')) 432 { 433 $virtualized = 'QEMU'; 434 435 if(strpos($cpu, 'QEMU Virtual') !== false) 436 { 437 $qemu_version = substr($cpu, (strrpos($cpu, ' ') + 1)); 438 439 if(pts_strings::is_version($qemu_version)) 440 { 441 $virtualized .= ' ' . $qemu_version; 442 } 443 } 444 } 445 else if(stripos($gpu, 'VMware') !== false || (is_readable('/sys/class/dmi/id/product_name') && stripos(pts_file_io::file_get_contents('/sys/class/dmi/id/product_name'), 'VMware') !== false)) 446 { 447 $virtualized = 'VMware'; 448 } 449 else if(stripos($gpu, 'VirtualBox') !== false || stripos(phodevi::read_name('motherboard'), 'VirtualBox') !== false) 450 { 451 $virtualized = 'VirtualBox'; 452 453 if($vbox_manage = pts_client::executable_in_path('VBoxManage')) 454 { 455 $vbox_manage = trim(shell_exec($vbox_manage . ' --version 2> /dev/null')); 456 457 if(is_numeric(substr($vbox_manage, 0, 1))) 458 { 459 $virtualized .= ' ' . $vbox_manage; 460 } 461 } 462 else if($modinfo = pts_client::executable_in_path('modinfo')) 463 { 464 $modinfo = trim(shell_exec('modinfo -F version vboxguest 2> /dev/null')); 465 466 if($modinfo != null && pts_strings::is_version(str_ireplace(array('_', 'RC', 'beta'), '', $modinfo))) 467 { 468 $virtualized .= ' ' . $modinfo; 469 } 470 } 471 472 } 473 else if(is_file('/sys/class/dmi/id/sys_vendor') && pts_file_io::file_get_contents('/sys/class/dmi/id/sys_vendor') == 'Xen') 474 { 475 $virtualized = pts_file_io::file_get_contents('/sys/class/dmi/id/product_name'); 476 477 if(strpos($virtualized, 'Xen') === false) 478 { 479 $virtualized = 'Xen ' . $virtualized; 480 } 481 482 // version string 483 $virtualized .= ' ' . pts_file_io::file_get_contents('/sys/class/dmi/id/product_version'); 484 485 // $virtualized should be then e.g. 'Xen HVM domU 4.1.1' 486 } 487 else if(stripos($gpu, 'Microsoft Hyper-V') !== false) 488 { 489 $virtualized = 'Microsoft Hyper-V Server'; 490 } 491 else if(stripos($mobo, 'Parallels Software') !== false) 492 { 493 $virtualized = 'Parallels Virtualization'; 494 } 495 else if(is_file('/sys/hypervisor/type')) 496 { 497 $type = pts_file_io::file_get_contents('/sys/hypervisor/type'); 498 $version = array(); 499 500 foreach(array('major', 'minor', 'extra') as $v) 501 { 502 if(is_file('/sys/hypervisor/version/' . $v)) 503 { 504 $v = pts_file_io::file_get_contents('/sys/hypervisor/version/' . $v); 505 } 506 else 507 { 508 continue; 509 } 510 511 if($v != null) 512 { 513 if(!empty($version) && substr($v, 0, 1) != '.') 514 { 515 $v = '.' . $v; 516 } 517 array_push($version, $v); 518 } 519 } 520 521 $virtualized = ucwords($type) . ' ' . implode('', $version) . ' Hypervisor'; 522 } 523 524 if($systemd_virt = pts_client::executable_in_path('systemd-detect-virt')) 525 { 526 $systemd_virt = trim(shell_exec($systemd_virt . ' 2> /dev/null')); 527 528 if($systemd_virt != null && $systemd_virt != 'none') 529 { 530 switch($systemd_virt) 531 { 532 case 'kvm': 533 $systemd_virt = 'KVM'; 534 break; 535 case 'oracle': 536 $systemd_virt = 'Oracle'; 537 break; 538 } 539 540 if($virtualized != null && stripos($virtualized, $systemd_virt) === false && stripos($systemd_virt, $virtualized) === false) 541 { 542 $virtualized = $systemd_virt . ' ' . $virtualized; 543 } 544 else if($virtualized == null) 545 { 546 $virtualized = $systemd_virt; 547 } 548 } 549 } 550 551 if(empty($virtualized)) 552 { 553 if(is_file('/.dockerenv')) 554 { 555 $virtualized = 'Docker'; 556 } 557 else if(is_file('/dev/lxc/console')) 558 { 559 $virtualized = 'lxc'; 560 } 561 } 562 563 return $virtualized; 564 } 565 public static function sw_environment_variables() 566 { 567 $check_variables = array('LIBGL', '__GL', 'DRI_', 'DEBUG', 'FLAGS', 'PERF_', 'PERFTEST'); 568 $to_report = array(); 569 570 if(stripos(phodevi::read_property('system', 'opengl-driver'), 'Mesa')) 571 { 572 array_push($check_variables, 'MESA', 'GALLIUM'); 573 } 574 575 if(isset($_SERVER)) 576 { 577 foreach($_SERVER as $name => &$value) 578 { 579 foreach($check_variables as $var) 580 { 581 if(stripos($name, $var) !== false && $name != '__GL_SYNC_TO_VBLANK' && strpos($name, 'GJS') === false) 582 { 583 $value = trim($value); 584 if(strpos($value, ' ') !== false) 585 { 586 $value = '"' . $value . '"'; 587 } 588 array_push($to_report, $name . '=' . $value); 589 break; 590 } 591 } 592 593 } 594 } 595 596 return implode(' ', array_unique($to_report)); 597 } 598 public static function sw_security_features() 599 { 600 $security = array(); 601 if(pts_client::executable_in_path('getenforce')) 602 { 603 $selinux = shell_exec('getenforce 2>&1'); 604 if(strpos($selinux, 'Enforcing') !== false) 605 { 606 $security[] = 'SELinux'; 607 } 608 } 609 610 // Meltdown / KPTI check 611 if(phodevi::is_linux()) 612 { 613 /* if(strpos(phodevi::$vfs->dmesg, 'page tables isolation: enabled') !== false) 614 { 615 // Kernel Page Table Isolation 616 $security[] = 'KPTI'; 617 } 618*/ 619 // Spectre 620 foreach(pts_file_io::glob('/sys/devices/system/cpu/vulnerabilities/*') as $vuln) 621 { 622 $fc = file_get_contents($vuln); 623 $fc = str_replace('Mitigation: ', 'Mitigation of ', $fc); 624 $fc = str_replace('Speculative Store Bypass', 'SSB', $fc); 625 if(!empty($fc)) 626 { 627 $security[] = basename($vuln) . ': ' . $fc; 628 } 629 } 630 } 631 else if(phodevi::is_bsd()) 632 { 633 // FreeBSD 634 if(phodevi_bsd_parser::read_sysctl('vm.pmap.pti') == '1') 635 { 636 $security[] = 'KPTI'; 637 } 638 if(phodevi_bsd_parser::read_sysctl('hw.ibrs_active') == '1') 639 { 640 $security[] = 'IBRS'; 641 } 642 643 // DragonFlyBSD 644 if(($spectre = phodevi_bsd_parser::read_sysctl('machdep.spectre_mitigation')) != '0' && $spectre != 'NONE' && !empty($spectre)) 645 { 646 $security[] = 'Spectre ' . $spectre . ' Mitigation'; 647 } 648 if(phodevi_bsd_parser::read_sysctl('machdep.meltdown_mitigation') == '1') 649 { 650 $security[] = 'Meltdown Mitigation'; 651 } 652 } 653 else if(phodevi::is_windows()) 654 { 655 $mds_tool = getenv('USERPROFILE') . '\Downloads\mdstool-cli.exe'; 656 if(is_file($mds_tool)) 657 { 658 $mds_output = preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', shell_exec($mds_tool)); 659 //echo PHP_EOL; 660 foreach(array('__user pointer sanitization: Disabled', 'Retpoline: Full', 'IBPB: Always', 'IBRS: Enabled', 'STIBP: Enabled', 'KPTI Enabled: Yes', 'PTE Inversion: Yes') as $check) 661 { 662 if(stripos($mds_output, $check) !== false) 663 { 664 $security[] = $check; 665 } 666 } 667 } 668 } 669 670 return !empty($security) ? implode(' + ', $security) : null; 671 } 672 public static function sw_compiler() 673 { 674 // Returns version of the compiler (if present) 675 $compilers = array(); 676 677 if($gcc = pts_client::executable_in_path('gcc')) 678 { 679 if(!is_link($gcc) || strpos(readlink($gcc), 'gcc') !== false) 680 { 681 // GCC 682 // If it's a link, ensure that it's not linking to llvm/clang or something 683 $version = trim(shell_exec('gcc -dumpversion 2>&1')); 684 $v = shell_exec('gcc -v 2>&1'); 685 if(pts_strings::is_version($version)) 686 { 687 688 if(($t = strrpos($v, $version . ' ')) !== false) 689 { 690 $v = substr($v, ($t + strlen($version) + 1)); 691 $v = substr($v, 0, strpos($v, ' ')); 692 693 if($v != null && is_numeric($v)) 694 { 695 // On development versions the release date is expressed 696 // e.g. gcc version 4.7.0 20120314 (prerelease) (GCC) 697 $version .= ' ' . $v; 698 } 699 else 700 { 701 $v = shell_exec('gcc --version 2>&1'); 702 if(($t = strrpos($v, $version)) !== false) 703 { 704 $v = substr($v, $t); 705 $v = substr($v, 0, strpos(str_replace(PHP_EOL, ' ', $v), ' ')); 706 if(($t = strpos($v, ')')) !== false) 707 { 708 $v = substr($v, 0, $t); 709 } 710 711 if(pts_strings::is_version($v)) 712 { 713 $version = $v; 714 } 715 } 716 } 717 } 718 719 $compilers['gcc'] = 'GCC ' . $version; 720 } 721 else if(($t = strpos($v, ' version ')) !== false) 722 { 723 $v = substr($v, ($t + strlen(' version '))); 724 if(($t = strpos($v, ' (')) !== false) 725 { 726 $v = substr($v, 0, $t); 727 $compilers['gcc'] = 'GCC ' . $v; 728 } 729 } 730 } 731 // sometimes "copyright" slips into version string 732 if(isset($compilers['gcc'])) 733 { 734 $compilers['gcc'] = str_replace('Copyright', '', $compilers['gcc']); 735 } 736 } 737 738 if(pts_client::executable_in_path('pgcc')) 739 { 740 // NVIDIA PGI Compiler 741 $compilers['pgcc'] = 'PGI Compiler'; 742 $v = trim(shell_exec('pgcc --version 2>&1')); 743 $v = substr($v, strpos($v, 'pgcc ') + 5); 744 $v = substr($v, 0, strpos($v, ' ')); 745 if(pts_strings::is_version(str_replace('-', '', $v))) 746 { 747 $compilers['pgcc'] .= ' ' . $v; 748 } 749 } 750 751 if(pts_client::executable_in_path('pcc')) 752 { 753 // PCC - Portable C Compiler 754 $pcc = explode(' ', trim(shell_exec('pcc -version 2>&1'))); 755 756 if($pcc[0] == 'pcc') 757 { 758 $compilers['pcc'] = 'PCC ' . $pcc[1] . (is_numeric($pcc[2]) ? ' ' . $pcc[2] : null); 759 } 760 } 761 762 if(pts_client::executable_in_path('pgcpp') || pts_client::executable_in_path('pgCC')) 763 { 764 // The Portland Group Compilers 765 $compilers['pgcpp'] = 'PGI C-C++ Workstation'; 766 } 767 768 if(($clang = pts_client::executable_in_path('clang'))) 769 { 770 // Clang 771 $compiler_info = shell_exec(escapeshellarg($clang) . ' --version'); 772 if(($cv_pos = stripos($compiler_info, 'clang version')) !== false) 773 { 774 // With Clang 3.0 and prior, the --version produces output where the first line is: 775 // e.g. clang version 3.0 (branches/release_30 142590) 776 777 $compiler_info = substr($compiler_info, ($cv_pos + 14)); 778 $compiler_info = str_replace(PHP_EOL, ' ', $compiler_info); 779 $clang_version = substr($compiler_info, 0, strpos($compiler_info, ' ')); 780 781 // XXX: the below check bypass now because e.g. Ubuntu appends '-ubuntuX', etc that breaks check 782 if(pts_strings::is_version($clang_version) || true) 783 { 784 // Also see if there is a Clang SVN tag to fetch 785 $compiler_info = substr($compiler_info, 0, strpos($compiler_info, PHP_EOL)); 786 if(($cv_pos = strpos($compiler_info, ')')) !== false) 787 { 788 $compiler_info = substr($compiler_info, 0, $cv_pos); 789 $compiler_info = substr($compiler_info, (strrpos($compiler_info, ' ') + 1)); 790 791 if(is_numeric($compiler_info)) 792 { 793 // Right now Clang/LLVM uses SVN system and their revisions are only numeric 794 $clang_version .= ' (SVN ' . $compiler_info . ')'; 795 } 796 } 797 798 $compiler_info = 'Clang ' . $clang_version; 799 } 800 else 801 { 802 $compiler_info = null; 803 } 804 } 805 else 806 { 807 $compiler_info = substr($compiler_info, 0, strpos($compiler_info, PHP_EOL)); 808 } 809 810 // Clang 811 if(empty($compiler_info) && stripos($compiler_info, 'not found')) 812 { 813 // At least with Clang ~3.0 the -dumpversion is reporting '4.2.1' ratherthan the useful information... 814 // This is likely just for GCC command compatibility, so only use this as a fallback 815 $compiler_info = 'Clang ' . trim(shell_exec('clang -dumpversion 2> /dev/null')); 816 } 817 818 $compilers['clang'] = $compiler_info; 819 } 820 821 // For now at least Intel oneAPI has symlink from clang to icpx so this below code isn't needed in such case 822 if(!pts_client::executable_in_path('clang') && ($icpx = pts_client::executable_in_path('icpx'))) 823 { 824 // Intel oneAPI DPC++/C++ Compiler 825 $icpx = shell_exec(escapeshellarg($icpx) . ' --version'); 826 $icpx = substr($icpx, 0, strpos($icpx, PHP_EOL)); 827 if(stripos($icpx, 'oneAPI') !== false) 828 { 829 $icpx = str_ireplace(array('(R)'), '', $icpx); 830 if(($x = strpos($icpx, ' (')) !== false) 831 { 832 $icpx = substr($icpx, 0, $x); 833 } 834 } 835 836 $compilers['icpx'] = $icpx; 837 } 838 839 if(($llvm_ld = pts_client::executable_in_path('llvm-link')) || ($llvm_ld = pts_client::executable_in_path('llvm-ld'))) 840 { 841 // LLVM - Low Level Virtual Machine 842 // Reading the version from llvm-ld (the LLVM linker) should be safe as well for finding out version of LLVM in use 843 // As of LLVM 3.2svn, llvm-ld seems to be llvm-link 844 845 $info = trim(shell_exec($llvm_ld . ' -version 2> /dev/null')); 846 847 if(($s = strpos($info, 'version')) != false) 848 { 849 $info = substr($info, 0, strpos($info, PHP_EOL, $s)); 850 $info = substr($info, (strrpos($info, ' ') + 1)); 851 852 if(pts_strings::is_version(str_replace('svn', '', $info))) 853 { 854 $compilers['llvmc'] = 'LLVM ' . $info; 855 } 856 } 857 } 858 else if(pts_client::executable_in_path('llvm-config')) 859 { 860 // LLVM - Low Level Virtual Machine config 861 $info = trim(shell_exec('llvm-config --version 2> /dev/null')); 862 if(pts_strings::is_version(str_replace('svn', '', $info))) 863 { 864 $compilers['llvmc'] = 'LLVM ' . $info; 865 } 866 } 867 else if(pts_client::executable_in_path('llvmc')) 868 { 869 // LLVM - Low Level Virtual Machine (llvmc) 870 $info = trim(shell_exec('llvmc -version 2>&1')); 871 872 if(($s = strpos($info, 'version')) != false) 873 { 874 $info = substr($info, 0, strpos($info, "\n", $s)); 875 $info = substr($info, strrpos($info, "\n")); 876 877 $compilers['llvmc'] = trim($info); 878 } 879 } 880 881 if(pts_client::executable_in_path('suncc')) 882 { 883 // Sun Studio / SunCC 884 $info = trim(shell_exec('suncc -V 2>&1')); 885 886 if(($s = strpos($info, 'Sun C')) != false) 887 { 888 $info = substr($info, $s); 889 $info = substr($info, 0, strpos($info, "\n")); 890 891 $compilers['suncc'] = $info; 892 } 893 } 894 895 if(pts_client::executable_in_path('ioc')) 896 { 897 // Intel Offline Compiler (IOC) SDK for OpenCL 898 // -v e.g. : Intel(R) SDK for OpenCL* - Offline Compiler 2012 Command-Line Client, version 1.0.2 899 $info = trim(shell_exec('ioc -version 2>&1')) . ' '; 900 901 if(($s = strpos($info, 'Offline Compiler ')) != false) 902 { 903 $compilers['ioc'] = 'Intel IOC SDK'; 904 $sv = substr($info, ($s + 17)); 905 $sv = substr($sv, 0, strpos($sv, ' ')); 906 907 if(is_numeric($sv)) 908 { 909 $compilers['ioc'] .= ' ' . $sv; 910 } 911 912 if(($s = strpos($info, 'version ')) != false) 913 { 914 $sv = substr($info, ($s + 8)); 915 $sv = substr($sv, 0, strpos($sv, ' ')); 916 917 if(pts_strings::is_version($sv)) 918 { 919 $compilers['ioc'] .= ' v' . $sv; 920 } 921 } 922 } 923 } 924 925 if(($icc = pts_client::executable_in_path('icc')) || ($icc = pts_client::executable_in_path('icpc'))) 926 { 927 // Intel oneAPI DPC++/C++ Compiler 928 $icc = shell_exec(escapeshellarg($icc) . ' --version'); 929 $icc = substr($icc, 0, strpos($icc, PHP_EOL)); 930 if(stripos($icc, 'icc') !== false) 931 { 932 $icc = str_ireplace(array('(R)', '(ICC)', '(C)'), '', $icc); 933 if(($x = strpos($icpx, ' (')) !== false) 934 { 935 $icpx = substr($icc, 0, $x); 936 } 937 } 938 939 $icc = str_replace('icc', 'ICC', $icc); 940 $compilers['icc'] = $icc; 941 } 942 943 if(phodevi::is_macos() && pts_client::executable_in_path('xcodebuild')) 944 { 945 $xcode = phodevi_osx_parser::read_osx_system_profiler('SPDeveloperToolsDataType', 'Xcode'); 946 $xcode = substr($xcode, 0, strpos($xcode, ' ')); 947 948 if($xcode) 949 { 950 $compilers['Xcode'] = 'Xcode ' . $xcode; 951 } 952 } 953 954 if(($nvcc = pts_client::executable_in_path('nvcc')) || is_executable(($nvcc = '/usr/local/cuda/bin/nvcc'))) 955 { 956 // Check outside of PATH too since by default the CUDA Toolkit goes to '/usr/local/cuda/' and relies upon user to update system 957 // NVIDIA CUDA Compiler Driver 958 $nvcc = shell_exec($nvcc . ' --version 2>&1'); 959 if(($s = strpos($nvcc, 'release ')) !== false) 960 { 961 $nvcc = str_replace(array(','), '', substr($nvcc, ($s + 8))); 962 $nvcc = substr($nvcc, 0, strpos($nvcc, ' ')); 963 964 if(pts_strings::is_version($nvcc)) 965 { 966 $compilers['CUDA'] = 'CUDA ' . $nvcc; 967 } 968 } 969 } 970 971 // Try to make the compiler that's used by default to appear first 972 if(pts_client::read_env('CC') && isset($compilers[basename(pts_strings::first_in_string(pts_client::read_env('CC'), ' '))])) 973 { 974 $cc_env = basename(pts_strings::first_in_string(pts_client::read_env('CC'), ' ')); 975 $default_compiler = $compilers[$cc_env]; 976 unset($compilers[$cc_env]); 977 array_unshift($compilers, $default_compiler); 978 } 979 else if(pts_client::executable_in_path('cc') && is_link(pts_client::executable_in_path('cc'))) 980 { 981 $cc_link = basename(readlink(pts_client::executable_in_path('cc'))); 982 983 if(isset($compilers[$cc_link])) 984 { 985 $default_compiler = $compilers[$cc_link]; 986 unset($compilers[pts_client::read_env('CC')]); 987 array_unshift($compilers, $default_compiler); 988 } 989 } 990 991 return implode(' + ', array_unique($compilers)); 992 } 993 public static function sw_kernel_string() 994 { 995 return trim(phodevi::read_property('system', 'kernel') . ' (' . phodevi::read_property('system', 'kernel-architecture') . ') ' . phodevi::read_property('system', 'kernel-date')); 996 } 997 public static function sw_kernel_date() 998 { 999 $date = null; 1000 $k = phodevi::read_property('system', 'kernel'); 1001 1002 if(strpos($k, '99') !== false || stripos($k, 'rc') !== false) 1003 { 1004 // For now at least only report kernel build date when it looks like it's a devel kernel 1005 $v = php_uname('v'); 1006 if(($x = stripos($v, 'SMP ')) !== false) 1007 { 1008 $v = substr($v, ($x + 4)); 1009 $date = strtotime($v); 1010 if($date != false) 1011 { 1012 $date = date('Ymd', $date); 1013 } 1014 } 1015 } 1016 1017 return $date; 1018 } 1019 public static function sw_kernel() 1020 { 1021 return php_uname('r'); 1022 } 1023 public static function sw_kernel_parameters() 1024 { 1025 $parameters = null; 1026 1027 if(is_file('/proc/cmdline') && is_file('/proc/modules')) 1028 { 1029 $modules = array(); 1030 1031 foreach(explode(PHP_EOL, pts_file_io::file_get_contents('/proc/modules')) as $module_line) 1032 { 1033 $module_line = explode(' ', $module_line); 1034 1035 if(isset($module_line[0]) && !empty($module_line[0])) 1036 { 1037 array_push($modules, $module_line[0]); 1038 } 1039 } 1040 1041 if(!empty($modules)) 1042 { 1043 $to_report = array(); 1044 $cmdline = explode(' ', pts_file_io::file_get_contents('/proc/cmdline')); 1045 foreach($cmdline as $option) 1046 { 1047 if(($t = strpos($option, '.')) !== false) 1048 { 1049 if(in_array(substr($option, 0, $t), $modules)) 1050 { 1051 array_push($to_report, $option); 1052 } 1053 } 1054 } 1055 1056 if(!empty($to_report)) 1057 { 1058 $parameters = implode(' ', $to_report); 1059 } 1060 } 1061 } 1062 1063 return $parameters; 1064 } 1065 public static function sw_kernel_architecture() 1066 { 1067 // Find out the kernel archiecture 1068 if(phodevi::is_windows()) 1069 { 1070 //$kernel_arch = strpos($_SERVER['PROCESSOR_ARCHITECTURE'], 64) !== false || strpos($_SERVER['PROCESSOR_ARCHITEW6432'], 64 != false) ? 'x86_64' : 'i686'; 1071 if(isset($_SERVER['PROCESSOR_ARCHITEW6432'])) 1072 { 1073 $kernel_arch = $_SERVER['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 'x86_64' : 'i686'; 1074 } 1075 else 1076 { 1077 $kernel_arch = 'x86_64'; 1078 } 1079 } 1080 else 1081 { 1082 $kernel_arch = php_uname('m'); 1083 1084 switch($kernel_arch) 1085 { 1086 case 'X86-64': 1087 case 'amd64': 1088 $kernel_arch = 'x86_64'; 1089 break; 1090 case 'i86pc': 1091 case 'i586': 1092 case 'i686-AT386': 1093 $kernel_arch = 'i686'; 1094 break; 1095 } 1096 } 1097 1098 return $kernel_arch; 1099 } 1100 public static function sw_os_version() 1101 { 1102 // Returns OS version 1103 if(phodevi::is_macos()) 1104 { 1105 $os = phodevi_osx_parser::read_osx_system_profiler('SPSoftwareDataType', 'SystemVersion'); 1106 1107 $start_pos = strpos($os, '.'); 1108 $end_pos = strrpos($os, '.'); 1109 $start_pos = strrpos(substr($os, 0, $start_pos), ' '); 1110 $end_pos = strpos($os, ' ', $end_pos); 1111 1112 $os_version = substr($os, $start_pos + 1, $end_pos - $start_pos); 1113 } 1114 else if(phodevi::is_linux()) 1115 { 1116 $os_version = phodevi_linux_parser::read_lsb('Release'); 1117 1118 if($os_version == null) 1119 { 1120 if(is_readable('/etc/os-release')) 1121 $os_release = parse_ini_file('/etc/os-release'); 1122 else if(is_readable('/usr/lib/os-release')) 1123 $os_release = parse_ini_file('/usr/lib/os-release'); 1124 else 1125 $os_release = null; 1126 1127 if(isset($os_release['VERSION_ID']) && !empty($os_release['VERSION_ID'])) 1128 { 1129 $os_version = $os_release['VERSION_ID']; 1130 } 1131 else if(isset($os_release['VERSION']) && !empty($os_release['VERSION'])) 1132 { 1133 $os_version = $os_release['VERSION']; 1134 } 1135 $os_version = pts_strings::keep_in_string($os_version, pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_SPACE | pts_strings::CHAR_DASH | pts_strings::CHAR_UNDERSCORE); 1136 } 1137 } 1138 else if(phodevi::is_windows()) 1139 { 1140 $os_version = phodevi_windows_parser::get_wmi_object('win32_operatingsystem', 'BuildNumber'); 1141 } 1142 else 1143 { 1144 $os_version = php_uname('r'); 1145 } 1146 1147 return $os_version; 1148 } 1149 public static function sw_operating_system() 1150 { 1151 if(!PTS_IS_CLIENT) 1152 { 1153 // TODO: Figure out why this function is sometimes called from OpenBenchmarking.org.... 1154 return false; 1155 } 1156 1157 // Determine the operating system release 1158 if(phodevi::is_linux()) 1159 { 1160 $vendor = phodevi_linux_parser::read_lsb_distributor_id(); 1161 1162 if($vendor == null) 1163 { 1164 if(is_readable('/etc/os-release')) 1165 $os_release = parse_ini_file('/etc/os-release'); 1166 else if(is_readable('/usr/lib/os-release')) 1167 $os_release = parse_ini_file('/usr/lib/os-release'); 1168 else 1169 $os_release = null; 1170 1171 if(isset($os_release['PRETTY_NAME']) && !empty($os_release['PRETTY_NAME'])) 1172 { 1173 $vendor = $os_release['PRETTY_NAME']; 1174 } 1175 else if(isset($os_release['NAME']) && !empty($os_release['NAME'])) 1176 { 1177 $vendor = $os_release['NAME']; 1178 } 1179 1180 $vendor = str_replace('é', 'e', $vendor); 1181 } 1182 1183 if(($x = stripos($vendor, ' for ')) !== false) 1184 { 1185 $vendor = substr($vendor, 0, $x); 1186 } 1187 1188 $vendor = str_replace(array(' Software'), '', $vendor); 1189 } 1190 else if(phodevi::is_hurd()) 1191 { 1192 $vendor = php_uname('v'); 1193 } 1194 else 1195 { 1196 $vendor = null; 1197 } 1198 1199 $version = phodevi::read_property('system', 'os-version'); 1200 1201 if(!$vendor) 1202 { 1203 $os = null; 1204 1205 // Try to detect distro for those not supplying lsb_release 1206 $files = pts_file_io::glob('/etc/*-version'); 1207 for($i = 0; $i < count($files) && $os == null; $i++) 1208 { 1209 $file = file_get_contents($files[$i]); 1210 1211 if(trim($file) != null) 1212 { 1213 $os = substr($file, 0, strpos($file, "\n")); 1214 } 1215 } 1216 1217 if($os == null) 1218 { 1219 $files = pts_file_io::glob('/etc/*-release'); 1220 for($i = 0; $i < count($files) && $os == null; $i++) 1221 { 1222 $file = file_get_contents($files[$i]); 1223 1224 if(trim($file) != null) 1225 { 1226 $proposed_os = substr($file, 0, strpos($file, PHP_EOL)); 1227 1228 if(strpos($proposed_os, '=') == false) 1229 { 1230 $os = $proposed_os; 1231 } 1232 } 1233 else if($i == (count($files) - 1)) 1234 { 1235 $os = ucwords(substr(($n = basename($files[$i])), 0, strpos($n, '-'))); 1236 } 1237 } 1238 } 1239 1240 if($os == null && is_file('/etc/release')) 1241 { 1242 $file = file_get_contents('/etc/release'); 1243 $os = substr($file, 0, strpos($file, "\n")); 1244 } 1245 1246 if($os == null && is_file('/etc/palm-build-info')) 1247 { 1248 // Palm / webOS Support 1249 $os = phodevi_parser::parse_equal_delimited_file('/etc/palm-build-info', 'PRODUCT_VERSION_STRING'); 1250 } 1251 1252 if($os == null) 1253 { 1254 if(is_file('/etc/debian_version')) 1255 { 1256 $os = 'Debian ' . php_uname('s') . ' ' . ucwords(pts_file_io::file_get_contents('/etc/debian_version')); 1257 } 1258 else 1259 { 1260 $os = php_uname('s'); 1261 } 1262 } 1263 else if(strpos($os, ' ') === false) 1264 { 1265 // The OS string is only one word, likely a problem... 1266 if(is_file('/etc/arch-release') && stripos($os, 'Arch') === false) 1267 { 1268 // On at least some Arch installs (ARM) the file is empty so would have missed above check 1269 $os = trim('Arch Linux ' . $os); 1270 } 1271 } 1272 } 1273 else if($version != null && stripos($vendor, $version) === false) 1274 { 1275 $os = $vendor . ' ' . $version; 1276 } 1277 else 1278 { 1279 $os = $vendor; 1280 } 1281 1282 if(($break_point = strpos($os, ':')) > 0) 1283 { 1284 $os = substr($os, $break_point + 1); 1285 } 1286 1287 if(phodevi::is_macos()) 1288 { 1289 $os = phodevi_osx_parser::read_osx_system_profiler('SPSoftwareDataType', 'SystemVersion'); 1290 } 1291 else if(phodevi::is_windows()) 1292 { 1293 $os = $info = phodevi_windows_parser::get_wmi_object('win32_operatingsystem', 'caption') . ' Build ' . phodevi::read_property('system', 'os-version'); 1294 if(strpos($os, 'Windows') === false) 1295 { 1296 $os = trim(exec('ver')); 1297 } 1298 } 1299 if(($break_point = strpos($os, '(')) > 0) 1300 { 1301 $os = substr($os, 0, $break_point); 1302 } 1303 1304 $os = trim($os); 1305 1306 return $os; 1307 } 1308 public static function sw_desktop_environment() 1309 { 1310 $desktop = null; 1311 $desktop_environment = null; 1312 $desktop_version = null; 1313 $desktop_session = pts_client::read_env('DESKTOP_SESSION'); 1314 1315 if(pts_client::is_process_running('gnome-shell')) 1316 { 1317 // GNOME 3.0 / GNOME Shell 1318 $desktop_environment = 'GNOME Shell'; 1319 1320 if(pts_client::executable_in_path('gnome-shell')) 1321 { 1322 $desktop_version = pts_strings::last_in_string(trim(shell_exec('gnome-shell --version 2> /dev/null'))); 1323 } 1324 } 1325 else if(pts_client::is_process_running('gnome-panel') || $desktop_session == 'gnome') 1326 { 1327 // GNOME 1328 $desktop_environment = 'GNOME'; 1329 1330 if(pts_client::executable_in_path('gnome-about')) 1331 { 1332 $desktop_version = pts_strings::last_in_string(trim(shell_exec('gnome-about --version 2> /dev/null'))); 1333 } 1334 else if(pts_client::executable_in_path('gnome-session')) 1335 { 1336 $desktop_version = pts_strings::last_in_string(trim(shell_exec('gnome-session --version 2> /dev/null'))); 1337 } 1338 } 1339 else if(pts_client::is_process_running('unity-2d-panel') || $desktop_session == 'ubuntu-2d') 1340 { 1341 // Canonical / Ubuntu Unity 2D Desktop 1342 $desktop_environment = 'Unity 2D'; 1343 1344 if(pts_client::executable_in_path('unity')) 1345 { 1346 $desktop_version = pts_strings::last_in_string(trim(shell_exec('unity --version 2> /dev/null'))); 1347 } 1348 } 1349 else if(pts_client::is_process_running('unity-panel-service') || $desktop_session == 'ubuntu') 1350 { 1351 // Canonical / Ubuntu Unity Desktop 1352 $desktop_environment = 'Unity'; 1353 1354 if(pts_client::executable_in_path('unity')) 1355 { 1356 $desktop_version = pts_strings::last_in_string(trim(shell_exec('unity --version 2> /dev/null'))); 1357 } 1358 } 1359 else if($desktop_session == 'mate') 1360 { 1361 $desktop_environment = 'MATE'; 1362 if(pts_client::executable_in_path('mate-about')) 1363 { 1364 $desktop_version = pts_strings::last_in_string(trim(shell_exec('mate-about --version 2> /dev/null'))); 1365 } 1366 } 1367 else if(($kde5 = pts_client::is_process_running('plasmashell'))) 1368 { 1369 // KDE 5.x 1370 $desktop_environment = 'KDE Plasma'; 1371 $desktop_version = pts_strings::last_in_string(trim(shell_exec('plasmashell --version 2> /dev/null'))); 1372 } 1373 else if(($kde5 = pts_client::is_process_running('kded5'))) 1374 { 1375 // KDE 5.x 1376 $desktop_environment = 'KDE Frameworks'; 1377 if(pts_client::executable_in_path('kdeinit5')) 1378 { 1379 $desktop_version = pts_strings::last_in_string(trim(shell_exec('kdeinit5 --version 2> /dev/null'))); 1380 } 1381 } 1382 else if(($dde = pts_client::is_process_running('dde-desktop'))) 1383 { 1384 // KDE 5.x 1385 $desktop_environment = 'Deepin Desktop Environment'; 1386 $desktop_version = null; // TODO XXX 1387 } 1388 else if(($kde4 = pts_client::is_process_running('kded4')) || pts_client::is_process_running('kded')) 1389 { 1390 // KDE 4.x 1391 $desktop_environment = 'KDE'; 1392 $kde_output = trim(shell_exec(($kde4 ? 'kde4-config' : 'kde-config') . ' --version 2>&1')); 1393 $kde_lines = explode("\n", $kde_output); 1394 1395 for($i = 0; $i < count($kde_lines) && empty($desktop_version); $i++) 1396 { 1397 $line_segments = pts_strings::colon_explode($kde_lines[$i]); 1398 1399 if(in_array($line_segments[0], array('KDE', 'KDE Development Platform')) && isset($line_segments[1])) 1400 { 1401 $v = trim($line_segments[1]); 1402 1403 if(($cut = strpos($v, ' ')) > 0) 1404 { 1405 $v = substr($v, 0, $cut); 1406 } 1407 1408 $desktop_version = $v; 1409 } 1410 } 1411 } 1412 else if(pts_client::is_process_running('chromeos-wm')) 1413 { 1414 $chrome_output = trim(shell_exec('chromeos-wm -version')); 1415 1416 if($chrome_output == 'chromeos-wm') 1417 { 1418 // No version actually reported 1419 $chrome_output = 'Chrome OS'; 1420 } 1421 1422 $desktop_environment = $chrome_output; 1423 } 1424 else if(pts_client::is_process_running('lxqt-panel') || $desktop_session == 'lxqt') 1425 { 1426 //$lx_output = trim(shell_exec('lxqt-panel --version')); 1427 //$version = substr($lx_output, strpos($lx_output, ' ') + 1); 1428 1429 $desktop_environment = 'LXQt'; 1430 if(pts_client::executable_in_path('lxqt-about')) 1431 { 1432 $desktop_version = pts_strings::last_in_string(trim(shell_exec('lxqt-about --version | grep liblxqt 2> /dev/null'))); 1433 } 1434 } 1435 else if(pts_client::is_process_running('lxsession') || $desktop_session == 'lxde') 1436 { 1437 $lx_output = trim(shell_exec('lxpanel --version 2>&1')); 1438 $version = substr($lx_output, strpos($lx_output, ' ') + 1); 1439 1440 $desktop_environment = 'LXDE'; 1441 $desktop_version = $version; 1442 } 1443 else if(pts_client::is_process_running('lumina-desktop')) 1444 { 1445 // Lumina Desktop Environment 1446 $desktop_environment = 'Lumina'; 1447 $desktop_version = str_replace('"', '', trim(shell_exec('lumina-desktop --version 2>&1'))); 1448 } 1449 else if(pts_client::is_process_running('xfce4-session') || pts_client::is_process_running('xfce-mcs-manager') || $desktop_session == 'xfce') 1450 { 1451 // Xfce 4.x 1452 $desktop_environment = 'Xfce'; 1453 $xfce_output = trim(shell_exec('xfce4-session-settings --version 2>&1')); 1454 1455 if(($open = strpos($xfce_output, '(Xfce')) > 0) 1456 { 1457 $xfce_output = substr($xfce_output, strpos($xfce_output, ' ', $open) + 1); 1458 $desktop_version = substr($xfce_output, 0, strpos($xfce_output, ')')); 1459 } 1460 } 1461 else if(pts_client::is_process_running('sugar-session')) 1462 { 1463 // Sugar Desktop Environment (namely for OLPC) 1464 $desktop_environment = 'Sugar'; 1465 $desktop_version = null; // TODO: where can the Sugar version be figured out? 1466 } 1467 else if(pts_client::is_process_running('openbox')) 1468 { 1469 $desktop_environment = 'Openbox'; 1470 $openbox_output = trim(shell_exec('openbox --version 2>&1')); 1471 1472 if(($openbox_d = stripos($openbox_output, 'Openbox ')) !== false) 1473 { 1474 $openbox_output = substr($openbox_output, ($openbox_d + 8)); 1475 $desktop_version = substr($openbox_output, 0, strpos($openbox_output, PHP_EOL)); 1476 } 1477 } 1478 else if(pts_client::is_process_running('cinnamon')) 1479 { 1480 $desktop_environment = 'Cinnamon'; 1481 $desktop_version = pts_strings::last_in_string(trim(shell_exec('cinnamon --version 2> /dev/null'))); 1482 } 1483 else if(pts_client::is_process_running('sway')) 1484 { 1485 $desktop_environment = 'Sway'; 1486 $desktop_version = pts_strings::last_in_string(trim(shell_exec('sway --version 2> /dev/null'))); 1487 } 1488 else if(pts_client::is_process_running('enlightenment')) 1489 { 1490 $desktop_environment = 'Enlightenment'; 1491 $desktop_version = null; // No known -v / --version command on any Enlightenment component 1492 } 1493 else if(pts_client::is_process_running('consort-panel')) 1494 { 1495 $desktop_environment = 'Consort'; 1496 $desktop_version = null; // TODO: Haven't tested Consort Desktop yet 1497 } 1498 else if(pts_client::is_process_running('razor-desktop')) 1499 { 1500 $desktop_environment = 'Razor-qt'; 1501 $desktop_version = null; // TODO: Figure out how to determine razor version 1502 } 1503 else if(pts_client::is_process_running('icewm')) 1504 { 1505 $desktop_environment = 'IceWM'; 1506 $desktop_version = null; 1507 } 1508 else if(pts_client::is_process_running('budgie-panel') || $desktop_session == 'budgie-desktop') 1509 { 1510 // Budgie 1511 $desktop_environment = 'Budgie'; 1512 } 1513 1514 if(!empty($desktop_environment)) 1515 { 1516 $desktop = $desktop_environment; 1517 1518 if(!empty($desktop_version) && pts_strings::is_version($desktop_version)) 1519 { 1520 $desktop .= ' ' . $desktop_version; 1521 } 1522 } 1523 1524 return $desktop; 1525 } 1526 public static function sw_display_server() 1527 { 1528 $display_servers = array(); 1529 1530 if(phodevi::is_windows()) 1531 { 1532 // TODO: determine what to do for Windows support 1533 } 1534 else 1535 { 1536 if(pts_client::is_process_running('weston')) 1537 { 1538 $info = 'Wayland Weston'; 1539 $vinfo = trim(shell_exec('weston --version 2>&1')); 1540 1541 if(pts_strings::last_in_string($vinfo) && pts_strings::is_version(pts_strings::last_in_string($vinfo))) 1542 { 1543 $info .= ' ' . pts_strings::last_in_string($vinfo); 1544 } 1545 array_push($display_servers, $info); 1546 } 1547 if(pts_client::is_process_running('unity-system-compositor')) 1548 { 1549 $unity_system_comp = trim(str_replace('unity-system-compositor', '', shell_exec('unity-system-compositor --version 2>&1'))); 1550 1551 if(pts_strings::is_version($unity_system_comp)) 1552 { 1553 array_push($display_servers, 'Unity-System-Compositor ' . $unity_system_comp); 1554 } 1555 1556 } 1557 $xorg_log = isset(phodevi::$vfs->xorg_log) ? phodevi::$vfs->xorg_log : false; 1558 if($xorg_log && ($x = strpos($xorg_log, 'X.Org X Server ')) !== false) 1559 { 1560 $xorg_log = substr($xorg_log, ($x + strlen('X.Org X Server '))); 1561 $xorg_log = substr($xorg_log, 0, strpos($xorg_log, PHP_EOL)); 1562 1563 if(pts_strings::is_version($xorg_log)) 1564 { 1565 array_push($display_servers, 'X Server ' . $xorg_log); 1566 } 1567 } 1568 else if(($x_bin = (is_executable('/usr/libexec/Xorg.bin') ? '/usr/libexec/Xorg.bin' : false)) || ($x_bin = pts_client::executable_in_path('Xorg')) || ($x_bin = pts_client::executable_in_path('X'))) 1569 { 1570 // Find graphics subsystem version 1571 $info = shell_exec($x_bin . ' ' . (phodevi::is_solaris() ? ':0' : '') . ' -version 2>&1'); 1572 $pos = (($p = strrpos($info, 'Release Date')) !== false ? $p : strrpos($info, 'Build Date')); 1573 $info = trim(substr($info, 0, $pos)); 1574 1575 if($pos === false || getenv('DISPLAY') == false) 1576 { 1577 $version = null; 1578 } 1579 else if(($pos = strrpos($info, '(')) === false && strrpos($info, 'Server') === false) 1580 { 1581 $version = trim(substr($info, strrpos($info, ' '))); 1582 } 1583 else 1584 { 1585 $version = trim(substr($info, strrpos($info, 'Server') + 6)); 1586 1587 if(!pts_strings::is_version($version)) 1588 { 1589 $version = null; 1590 } 1591 } 1592 1593 array_push($display_servers, trim('X Server ' . $version)); 1594 } 1595 if(pts_client::is_process_running('surfaceflinger')) 1596 { 1597 array_push($display_servers, 'SurfaceFlinger'); 1598 } 1599 1600 if(pts_client::is_process_running('gnome-shell-wayland')) 1601 { 1602 array_push($display_servers, 'GNOME Shell Wayland'); 1603 } 1604 1605 if(getenv('WAYLAND_DISPLAY') != false) 1606 { 1607 array_push($display_servers, 'Wayland'); 1608 } 1609 } 1610 1611 return implode(' + ', $display_servers); 1612 } 1613 public static function sw_display_driver($with_version = true) 1614 { 1615 if(phodevi::is_windows()) 1616 { 1617 $windows_driver = phodevi_windows_parser::get_wmi_object('Win32_VideoController', 'DriverVersion'); 1618 1619 if(($nvidia_smi = pts_client::executable_in_path('nvidia-smi'))) 1620 { 1621 $smi_output = shell_exec(escapeshellarg($nvidia_smi) . ' -q -d CLOCK'); 1622 if(($v = stripos($smi_output, 'Driver Version')) !== false) 1623 { 1624 $nv_version = substr($smi_output, strpos($smi_output, ':', $v) + 1); 1625 $nv_version = trim(substr($nv_version, 0, strpos($nv_version, "\n"))); 1626 if(pts_strings::is_version($nv_version)) 1627 { 1628 $windows_driver = $nv_version . ' (' . $windows_driver . ')'; 1629 } 1630 } 1631 } 1632 return $windows_driver; 1633 } 1634 1635 $display_driver = phodevi::read_property('system', 'dri-display-driver'); 1636 $driver_version = null; 1637 1638 if(empty($display_driver) || $display_driver == 'NVIDIA') 1639 { 1640 if(phodevi::is_nvidia_graphics() || is_file('/proc/driver/nvidia/version')) 1641 { 1642 $display_driver = 'NVIDIA'; 1643 if(($nvs_value = phodevi_parser::read_nvidia_extension('NvidiaDriverVersion'))) 1644 { 1645 $driver_version = $nvs_value; 1646 } 1647 else 1648 { 1649 // NVIDIA's binary driver appends their driver version on the end of the OpenGL version string 1650 $glxinfo = phodevi_parser::software_glxinfo_version(); 1651 if(($pos = strpos($glxinfo, 'NVIDIA ')) != false) 1652 { 1653 $driver_version = substr($glxinfo, ($pos + 7)); 1654 } 1655 } 1656 } 1657 else if((phodevi::is_mesa_graphics() || phodevi::is_bsd()) && stripos(phodevi::read_property('gpu', 'model'), 'NVIDIA') !== false) 1658 { 1659 if(is_file('/sys/class/drm/version')) 1660 { 1661 // If there's DRM loaded and NVIDIA, it should be Nouveau 1662 $display_driver = 'nouveau'; 1663 } 1664 } 1665 } 1666 1667 // XXX: As of PTS 10.2.1, commented out due to xorg logs growing too big on recent Ubuntu/bug causing slow perf 1668 if(false && !empty($display_driver)) 1669 { 1670 $driver_version = phodevi_parser::read_xorg_module_version($display_driver . '_drv'); 1671 1672 if($driver_version == false || $driver_version == '1.0.0') 1673 { 1674 switch($display_driver) 1675 { 1676 case 'amd': 1677 // See if it's radeon driver 1678 $driver_version = phodevi_parser::read_xorg_module_version('radeon_drv'); 1679 1680 if($driver_version != false) 1681 { 1682 $display_driver = 'radeon'; 1683 } 1684 // See if it's the newer AMDGPU driver 1685 $driver_version = phodevi_parser::read_xorg_module_version('amdgpu_drv'); 1686 1687 if($driver_version != false) 1688 { 1689 $display_driver = 'amdgpu'; 1690 } 1691 break; 1692 case 'vmwgfx': 1693 // See if it's VMware driver 1694 $driver_version = phodevi_parser::read_xorg_module_version('vmware_drv'); 1695 1696 if($driver_version != false) 1697 { 1698 $display_driver = 'vmware'; 1699 } 1700 break; 1701 case 'radeon': 1702 // RadeonHD driver also reports DRI driver as 'radeon', so try reading that instead 1703 $driver_version = phodevi_parser::read_xorg_module_version('radeonhd_drv'); 1704 1705 if($driver_version != false) 1706 { 1707 $display_driver = 'radeonhd'; 1708 } 1709 $driver_version = phodevi_parser::read_xorg_module_version('amdgpu_drv'); 1710 1711 if($driver_version != false) 1712 { 1713 $display_driver = 'amdgpu'; 1714 } 1715 break; 1716 case 'nvidia': 1717 case 'NVIDIA': 1718 case 'nouveau': 1719 // NVIDIA's binary driver usually ends up reporting 1.0.0 1720 if(($nvs_value = phodevi_parser::read_nvidia_extension('NvidiaDriverVersion'))) 1721 { 1722 $display_driver = 'NVIDIA'; 1723 $driver_version = $nvs_value; 1724 } 1725 else 1726 { 1727 // NVIDIA's binary driver appends their driver version on the end of the OpenGL version string 1728 $glxinfo = phodevi_parser::software_glxinfo_version(); 1729 1730 if(($pos = strpos($glxinfo, 'NVIDIA ')) != false) 1731 { 1732 $display_driver = 'NVIDIA'; 1733 $driver_version = substr($glxinfo, ($pos + 7)); 1734 } 1735 } 1736 break; 1737 default: 1738 if(is_readable('/sys/class/graphics/fb0/name')) 1739 { 1740 // This path works for at least finding NVIDIA Tegra 2 DDX (via tegra_fb) 1741 $display_driver = file_get_contents('/sys/class/graphics/fb0/name'); 1742 $display_driver = str_replace(array('drm', '_fb'), '', $display_driver); 1743 $driver_version = phodevi_parser::read_xorg_module_version($display_driver . '_drv'); 1744 } 1745 break; 1746 } 1747 } 1748 1749 if($driver_version == false) 1750 { 1751 // If the version is empty, chances are the DDX driver string is incorrect 1752 $display_driver = null; 1753 1754 // See if the VESA or fbdev driver is in use 1755 foreach(array('modesetting', 'fbdev', 'vesa') as $drv) 1756 { 1757 $drv_version = phodevi_parser::read_xorg_module_version($drv . '_drv'); 1758 1759 if($drv_version) 1760 { 1761 $display_driver = $drv; 1762 $driver_version = $drv_version; 1763 break; 1764 } 1765 } 1766 } 1767 } 1768 if(!empty($driver_version) && $with_version && $driver_version != '0.0.0') 1769 { 1770 $display_driver .= ' ' . $driver_version; 1771 } 1772 1773 return $display_driver; 1774 } 1775 public static function sw_opengl_driver() 1776 { 1777 // OpenGL version 1778 $info = null; 1779 1780 if(phodevi::is_windows()) 1781 { 1782 $info = null; // TODO: Windows support 1783 } 1784 else if(pts_client::executable_in_path('nvidia-settings')) 1785 { 1786 $info = phodevi_parser::read_nvidia_extension('OpenGLVersion'); 1787 } 1788 1789 if($info == null) 1790 { 1791 $info = phodevi_parser::software_glxinfo_version(); 1792 1793 if($info && ($pos = strpos($info, ' ')) != false && strpos($info, 'Mesa') === false) 1794 { 1795 $info = substr($info, 0, $pos); 1796 } 1797 1798 $renderer = phodevi_parser::read_glx_renderer(); 1799 1800 if($renderer && ($s = strpos($renderer, 'Gallium')) !== false) 1801 { 1802 $gallium = substr($renderer, $s); 1803 $gallium = substr($gallium, 0, strpos($gallium, ' ', strpos($gallium, '.'))); 1804 $info .= ' ' . $gallium . ''; 1805 } 1806 1807 if($renderer && ($s = strpos($renderer, 'LLVM ')) !== false) 1808 { 1809 $llvm = substr($renderer, $s); 1810 $llvm = substr($llvm, 0, strpos($llvm, ')')); 1811 $info .= ' (' . $llvm . ')'; 1812 } 1813 } 1814 1815 return $info; 1816 } 1817 public static function sw_vulkan_driver() 1818 { 1819 // Vulkan driver/version 1820 $info = null; 1821 1822 if(isset(phodevi::$vfs->vulkaninfo)) 1823 { 1824 if(($pos = strpos(phodevi::$vfs->vulkaninfo, 'Vulkan API Version:')) !== false) 1825 { 1826 $info = substr(phodevi::$vfs->vulkaninfo, $pos + 20); 1827 $info = trim(substr($info, 0, strpos($info, "\n"))); 1828 } 1829 else if(($pos = strpos(phodevi::$vfs->vulkaninfo, 'apiVersion')) !== false) 1830 { 1831 $apiv = substr(phodevi::$vfs->vulkaninfo, $pos); 1832 $apiv = trim(substr($apiv, 0, strpos($apiv, ")\n"))); 1833 $apiv = trim(substr($apiv, strpos($apiv, '(') + 1)); 1834 if(pts_strings::is_version($apiv)) 1835 { 1836 $info = $apiv; 1837 } 1838 } 1839 } 1840 /* 1841 if($info == null) 1842 { 1843 // A less than ideal fallback for some detection now 1844 foreach(array_merge(pts_file_io::glob('/etc/vulkan/icd.d/*.json'), pts_file_io::glob('/usr/share/vulkan/icd.d/*.json')) as $icd_json) 1845 { 1846 $icd_json = json_decode(file_get_contents($icd_json), true); 1847 1848 if(isset($icd_json['ICD']['api_version']) && !empty($icd_json['ICD']['api_version'])) 1849 { 1850 $info = trim($icd_json['ICD']['api_version']); 1851 break; 1852 } 1853 } 1854 } 1855 */ 1856 1857 return $info; 1858 } 1859 public static function sw_opencl_driver() 1860 { 1861 // OpenCL driver/version 1862 $info = array(); 1863 1864 if(isset(phodevi::$vfs->clinfo)) 1865 { 1866 $sea = phodevi::$vfs->clinfo; 1867 while(($pos = strpos($sea, 'Platform Version')) != false) 1868 { 1869 $sea = substr($sea, $pos + 18); 1870 $info[] = trim(substr($sea, 0, strpos($sea, "\n"))); 1871 } 1872 } 1873 1874 return implode(' + ', $info); 1875 } 1876 public static function sw_opengl_vendor() 1877 { 1878 // OpenGL version 1879 $info = null; 1880 1881 if(pts_client::executable_in_path('glxinfo')) 1882 { 1883 $info = shell_exec('glxinfo 2>&1 | grep vendor'); 1884 1885 if($info && ($pos = strpos($info, 'OpenGL vendor string:')) !== false) 1886 { 1887 $info = substr($info, $pos + 22); 1888 $info = trim(substr($info, 0, strpos($info, "\n"))); 1889 } 1890 } 1891 else if(is_readable('/dev/nvidia0')) 1892 { 1893 $info = 'NVIDIA'; 1894 } 1895 else if(is_readable('/sys/module/fglrx/initstate') && pts_file_io::file_get_contents('/sys/module/fglrx/initstate') == 'live') 1896 { 1897 $info = 'ATI'; 1898 } 1899 else if(is_readable('/dev/dri/card0')) 1900 { 1901 $info = 'Mesa'; 1902 } 1903 else if(phodevi::is_bsd() && phodevi_bsd_parser::read_sysctl('dev.nvidia.0.%driver')) 1904 { 1905 $info = 'NVIDIA'; 1906 } 1907 1908 return $info; 1909 } 1910 public static function sw_compiler_build_configuration($compiler) 1911 { 1912 $cc = shell_exec($compiler . ' -v 2>&1'); 1913 1914 if(($t = stripos($cc, 'Configured with: ')) !== false) 1915 { 1916 $cc = substr($cc, ($t + 18)); 1917 $cc = substr($cc, 0, strpos($cc, PHP_EOL)); 1918 $cc = explode(' ', $cc); 1919 array_shift($cc); // this should just be the configure call (i.e. ../src/configure) 1920 1921 $drop_arguments = array( 1922 '--with-pkgversion=', 1923 '--with-bugurl=', 1924 '--prefix=', 1925 '--program-suffix=', 1926 '--libexecdir=', 1927 '--infodir=', 1928 '--libdir=', 1929 '--with-cloog=', 1930 '--with-isl=', 1931 '--with-java-home=', 1932 '--manddir=', 1933 '--with-ecj-jar=', 1934 '--with-jvm-jar-dir=', 1935 '--with-jvm-root-dir=', 1936 '--with-sysroot=', 1937 '--with-gxx-include-dir=', 1938 '--with-system-zlib', 1939 '--enable-linker-build-id', 1940 '--without-included-gettext' 1941 ); 1942 1943 foreach($cc as $i => $argument) 1944 { 1945 $arg_length = strlen($argument); 1946 if($argument[0] != '-') 1947 { 1948 unset($cc[$i]); 1949 } 1950 else 1951 { 1952 foreach($drop_arguments as $check_to_drop) 1953 { 1954 $len = strlen($check_to_drop); 1955 1956 if($len <= $arg_length && substr($argument, 0, $len) == $check_to_drop) 1957 { 1958 unset($cc[$i]); 1959 } 1960 } 1961 } 1962 } 1963 1964 sort($cc); 1965 $cc = implode(' ', $cc); 1966 } 1967 else if(($t = stripos($cc, 'clang')) !== false) 1968 { 1969 $cc = null; 1970 1971 // Clang doesn't report "configured with" but has other useful tid-bits... 1972 if(($c = pts_client::executable_in_path('llvm-ld')) || ($c = pts_client::executable_in_path('llvm-link'))) 1973 { 1974 $llvm_ld = shell_exec($c . ' -version 2>&1'); 1975 /* 1976 EXAMPLE OUTPUT: 1977 LLVM (http://llvm.org/): 1978 LLVM version 3.1svn 1979 Optimized build. 1980 Built Mar 23 2012 (08:53:34). 1981 Default target: x86_64-unknown-linux-gnu 1982 Host CPU: corei7-avx 1983 */ 1984 1985 if(stripos($llvm_ld, 'build') && (stripos($llvm_ld, 'host') || stripos($llvm_ld, 'target'))) 1986 { 1987 $llvm_ld = explode(PHP_EOL, $llvm_ld); 1988 1989 if(stripos($llvm_ld[0], 'http://')) 1990 { 1991 array_shift($llvm_ld); 1992 } 1993 if(stripos($llvm_ld[0], 'version')) 1994 { 1995 array_shift($llvm_ld); 1996 } 1997 1998 foreach($llvm_ld as $i => &$line) 1999 { 2000 $line = trim($line); 2001 if(substr($line, -1) == '.') 2002 { 2003 $line = substr($line, 0, -1); 2004 } 2005 2006 if($line == null) 2007 { 2008 unset($llvm_ld[$i]); 2009 } 2010 } 2011 2012 $cc = implode('; ', $llvm_ld); 2013 } 2014 } 2015 2016 } 2017 else 2018 { 2019 $cc = null; 2020 } 2021 2022 return $cc; 2023 } 2024 public static function sw_dri_display_driver() 2025 { 2026 $dri_driver = false; 2027 2028 if(is_file('/proc/driver/nvidia/version')) 2029 { 2030 $dri_driver = 'nvidia'; 2031 } 2032 else if(is_file('/sys/class/drm/card0/device/vendor')) 2033 { 2034 $vendor_id = pts_file_io::file_get_contents('/sys/class/drm/card0/device/vendor'); 2035 2036 switch($vendor_id) 2037 { 2038 case 0x1002: 2039 $dri_driver = 'radeon'; 2040 break; 2041 case 0x8086: 2042 $dri_driver = 'intel'; 2043 break; 2044 case 0x10de: 2045 // NVIDIA 2046 $dri_driver = 'nouveau'; 2047 break; 2048 } 2049 } 2050 2051 return $dri_driver; 2052 } 2053 public static function sw_java_version() 2054 { 2055 $java_version = trim(shell_exec('java -version 2>&1')); 2056 2057 if(strpos($java_version, 'not found') == false && (stripos($java_version, 'Java') !== false || stripos($java_version, 'jdk') !== false)) 2058 { 2059 $java_version = explode("\n", $java_version); 2060 2061 if(($cut = count($java_version) - 2) > 0) 2062 { 2063 $v = $java_version[$cut]; 2064 } 2065 else 2066 { 2067 $v = array_pop($java_version); 2068 } 2069 2070 $java_version = trim($v); 2071 } 2072 else 2073 { 2074 $java_version = null; 2075 } 2076 2077 return $java_version; 2078 } 2079 public static function sw_python_version() 2080 { 2081 $python_version = null; 2082 2083 if(($p = pts_client::executable_in_path('python')) != false) 2084 { 2085 $python_version = trim(shell_exec(escapeshellarg($p) . ' -V 2>&1')); 2086 } 2087 if(($p = pts_client::executable_in_path('python3')) != false) 2088 { 2089 $python3_version = trim(shell_exec(escapeshellarg($p) . ' -V 2>&1')); 2090 if($python3_version != $python_version) 2091 { 2092 $python_version .= ($python_version != null ? ' + ' : null) . $python3_version; 2093 } 2094 } 2095 2096 return $python_version; 2097 } 2098 public static function sw_wine_version() 2099 { 2100 $wine_version = null; 2101 2102 if((($use_wine = getenv('USE_WINE')) !== false || ($use_wine = getenv('WINE_VERSION')) !== false) && (is_executable($use_wine) || ($use_wine = pts_client::executable_in_path($use_wine)) !== false)) 2103 { 2104 $wine_version = trim(shell_exec($use_wine . ' --version 2>&1')); 2105 } 2106 else if(pts_client::executable_in_path('wine') != false) 2107 { 2108 $wine_version = trim(shell_exec('wine --version 2>&1')); 2109 } 2110 else if(pts_client::executable_in_path('winecfg.exe') != false && pts_client::read_env('WINE_VERSION')) 2111 { 2112 $wine_version = trim(pts_client::read_env('WINE_VERSION')); 2113 2114 if(stripos($wine_version, 'wine') === false) 2115 { 2116 $wine_version = 'wine-' . $wine_version; 2117 } 2118 } 2119 2120 return $wine_version; 2121 } 2122 public static function battery() 2123 { 2124 $batteries = array(); 2125 if(phodevi::is_linux()) 2126 { 2127 foreach(pts_file_io::glob('/sys/class/power_supply/BAT*/model_name') as $bat_path) 2128 { 2129 $bat_model = pts_file_io::file_get_contents($bat_path); 2130 $bat_dir = dirname($bat_path); 2131 $bat_manufacturer = is_file($bat_dir . '/manufacturer') ? pts_file_io::file_get_contents($bat_dir . '/manufacturer') : null; 2132 if(!empty($bat_model)) 2133 { 2134 $batteries[] = trim($bat_manufacturer . ' ' . $bat_model); 2135 } 2136 } 2137 } 2138 2139 return implode(' + ', $batteries); 2140 } 2141} 2142 2143?> 2144