aboutsummaryrefslogtreecommitdiffstats
path: root/inxi
diff options
context:
space:
mode:
Diffstat (limited to 'inxi')
-rwxr-xr-xinxi696
1 files changed, 528 insertions, 168 deletions
diff --git a/inxi b/inxi
index dc46bb0..5c9e4c7 100755
--- a/inxi
+++ b/inxi
@@ -31,8 +31,8 @@ use POSIX qw(uname strftime ttyname);
## INXI INFO ##
my $self_name='inxi';
-my $self_version='3.0.09';
-my $self_date='2018-05-11';
+my $self_version='3.0.11';
+my $self_date='2018-06-04';
my $self_patch='00';
## END INXI INFO ##
@@ -64,8 +64,8 @@ my (@dm_boot_disk,@dm_boot_optical,@glabel,@gpart,@labels,@lsblk,@partitions,
my @test = (0,0,0,0,0);
## Booleans
-my ($b_arm,$b_console_irc,$b_debug_gz,$b_display,$b_dmesg_boot_check,$b_dmi,
-$b_dmidecode_force,$b_fake_bsd,$b_fake_dboot,$b_fake_pciconf,$b_fake_sysctl,
+my ($b_admin,$b_arm,$b_console_irc,$b_debug_gz,$b_display,$b_dmesg_boot_check,
+$b_dmi,$b_dmidecode_force,$b_fake_bsd,$b_fake_dboot,$b_fake_pciconf,$b_fake_sysctl,
$b_fake_usbdevs,$b_force_display,$b_gpudata,$b_irc,$b_log,$b_log_colors,
$b_log_full,$b_man,$b_mem,$b_pci,$b_root,$b_running_in_display,$b_sudo,
$b_sysctl,$b_usb_check);
@@ -79,7 +79,7 @@ my ($bsd_type,$language,$os) = ('','','');
my ($bits_sys);
my ($cpu_sleep,$dl_timeout,$limit,$ps_count,$usb_level) = (0.35,4,10,5,0);
my $sensors_cpu_nu = 0;
-my $weather_unit='cf';
+my $weather_unit='mi';
## Tools
my ($display,$ftp_alt,$tty_session);
@@ -176,17 +176,32 @@ sub check_tools {
if ( $b_dmi ){
$action = 'use';
if ($program = check_program('dmidecode')) {
- my $result = system("$program -t chassis >/dev/null 2>&1");
- if (!$result){
+ @data = grabber("$program -t chassis -t baseboard -t processor 2>&1");
+ if (scalar @data < 15){
if ($b_root) {
- @data = grabber("$program --type chassis");
- if ( grep { $_ =~ /No SMBIOS/i } @data ){
- $action = 'smbios';
+ foreach (@data){
+ if ($_ =~ /No SMBIOS/i){
+ $action = 'smbios';
+ last;
+ }
+ elsif ($_ =~ /^\/dev\/mem: Operation/i){
+ $action = 'no-data';
+ last;
+ }
+ else {
+ $action = 'unknown-error';
+ last;
+ }
+ }
+ }
+ else {
+ if (grep { $_ =~ /^\/dev\/mem: Permission/i } @data){
+ $action = 'permissions';
+ }
+ else {
+ $action = 'unknown-error';
}
}
- }
- elsif ($result){
- $action = 'permissions';
}
}
else {
@@ -198,6 +213,8 @@ sub check_tools {
'missing' => 'Required program dmidecode not available',
'permissions' => 'Unable to run dmidecode. Are you root?',
'smbios' => 'No SMBIOS data for dmidecode to process',
+ 'no-data' => 'dmidecode is not allowed to read /dev/mem',
+ 'unknown-error' => 'dmidecode was unable to generate data',
},
);
%alerts = (%alerts, %hash);
@@ -457,6 +474,7 @@ sub set_user_paths {
# initialize function directly.
$self_path = $0;
$self_path =~ s/[^\/]+$//;
+ # print "0: $0 sp: $self_path\n";
if ( defined $ENV{'XDG_CONFIG_HOME'} && $ENV{'XDG_CONFIG_HOME'} ){
$user_config_dir=$ENV{'XDG_CONFIG_HOME'};
@@ -852,7 +870,7 @@ sub get_selection {
@data = ();
my $response = <STDIN>;
chomp $response;
- if ($response =~ /[^0-9]/ || $response > ($count + 3)){
+ if ($response =~ /([^0-9]|^$)/ || ( $response =~ /^[0-9]+$/ && $response > ($count + 3) )){
@data = (
[0, '', '', "Error - Invalid Selection. You entered this: $response. Hit <ENTER> to continue."],
[0, '', '', "$line1"],
@@ -1024,7 +1042,14 @@ sub get_config_item {
elsif ($key eq 'PS_COUNT') {$ps_count = int($val) }
elsif ($key eq 'SENSORS_CPU_NO') {$sensors_cpu_nu = int($val)}
elsif ($key eq 'SHOW_HOST' || $key eq 'B_SHOW_HOST') { $show{'host'} = int($val)}
- elsif ($key eq 'WEATHER_UNIT') { $weather_unit = lc($val) if $val =~ /^(c|f|cf|fc)$/i}
+ elsif ($key eq 'WEATHER_UNIT') {
+ $val = lc($val) if $val;
+ if ($val && $val =~ /^(c|f|cf|fc|i|m|im|mi)$/){
+ my %units = ('c'=>'m','f'=>'i','cf'=>'mi','fc'=>'im');
+ $val = $units{$val} if defined $units{$val};
+ $weather_unit = $val;
+ }
+ }
# layout
elsif ($key eq 'CONSOLE_COLOR_SCHEME') {$colors{'console'} = int($val)}
elsif ($key eq 'GLOBAL_COLOR_SCHEME') {$colors{'global'} = int($val)}
@@ -1211,10 +1236,7 @@ package SystemDebugger;
#use POSIX qw(strftime);
my $option = 'main';
-my $upload = '';
-my $data_dir = '';
-my $debug_dir = '';
-my $debug_gz = '';
+my ($data_dir,$debug_dir,$debug_gz,$parse_src,$upload) = ('','','','','');
my @content = ();
my $b_debug = 0;
my $b_delete_dir = 1;
@@ -1258,6 +1280,13 @@ sub run_debugger {
print "Skipping /sys data collection. /sys not present, or empty.\n";
}
print $line3;
+ if ( -d '/proc' && main::count_dir_files('/proc') ){
+ proc_traverse_data();
+ }
+ else {
+ print "Skipping /proc data collection. /proc not present, or empty.\n";
+ }
+ print $line3;
}
run_self();
print $line3;
@@ -1267,11 +1296,10 @@ sub run_debugger {
sub create_debug_directory {
my $host = main::get_hostname();
$host =~ s/ /-/g;
- $host ||= 'no-host';
+ $host = 'no-host' if !$host || $host eq 'N/A';
my ($arm_string,$bsd_string,$root_string) = ('','','');
# note: Time::Piece was introduced in perl 5.9.5
my ($sec,$min,$hour,$mday,$mon,$year) = localtime;
- my $version = substr($self_version,0,3);
$year = $year+1900;
$mon += 1;
if (length($sec) == 1) {$sec = "0$sec";}
@@ -1287,7 +1315,7 @@ sub create_debug_directory {
}
$bsd_string = "-BSD-$bsd_type" if $bsd_type;
$arm_string = '-ARM' if $b_arm;
- $debug_dir = "$self_name$arm_string$bsd_string-$host-$today$root_string-$version";
+ $debug_dir = "$self_name$arm_string$bsd_string-$host-$today$root_string-$self_version";
$debug_gz = "$debug_dir.tar.gz";
$data_dir = "$user_data_dir/$debug_dir";
if ( -d $data_dir ){
@@ -1639,7 +1667,10 @@ sub system_data {
['systemctl','list-units'],
['systemctl','list-units --type=target'],
['systemd-detect-virt',''],
+ ['upower','-e'],
['uptime',''],
+ ['vcgencmd','get_mem arm'],
+ ['vcgencmd','get_mem gpu'],
);
run_commands(\@cmds,'system');
@files = main::globber('/dev/bus/usb/*/*');
@@ -1681,19 +1712,22 @@ sub system_files {
}
sub copy_files {
- my ($files_ref, $type) = @_;
+ my ($files_ref,$type,$alt_dir) = @_;
my ($absent,$error,$good,$name,$unreadable);
+ my $directory = ($alt_dir) ? $alt_dir : $data_dir;
+ my $working = ($type ne 'proc') ? "$type-file-": '';
foreach (@$files_ref) {
$name = $_;
$name =~ s/^\///;
- $name =~ s/\//-/g;
- $name = "$data_dir/$type-file-$name";
+ $name =~ s/\//~/g;
+ $name = "$directory/$working$name";
$good = $name . '.txt';
$absent = $name . '-absent';
$error = $name . '-error';
$unreadable = $name . '-unreadable';
- if (-e $_ ) {
- if (-r $_){
+ # proc have already been tested for readable/exists
+ if ($type eq 'proc' || -e $_ ) {
+ if ($type eq 'proc' || -r $_){
copy($_,"$good") or main::toucher($error);
}
else {
@@ -1846,30 +1880,50 @@ sub sys_traverse_data {
print "Parsing /sys files...\n";
# get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied
no warnings 'File::Find';
+ $parse_src = 'sys';
File::Find::find( \&wanted, "/sys");
- process_data();
+ process_sys_data();
+ @content = ();
+}
+sub proc_traverse_data {
+ print "Parsing /proc files...\n";
+ # get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied
+ no warnings 'File::Find';
+ $parse_src = 'proc';
+ File::Find::find( \&wanted, "/proc");
+ process_proc_data();
+ @content = ();
}
sub wanted {
return if -d; # not directory
return unless -e; # Must exist
- return unless -r; # Must be readable
return unless -f; # Must be file
- # note: a new file in 4.11 /sys can hang this, it is /parameter/ then
- # a few variables. Since inxi does not need to see that file, we will
- # not use it. Also do not need . files or __ starting files
- # print $File::Find::name . "\n";
- # block maybe: cfgroup\/
- return if $File::Find::name =~ /\/(\.[a-z]|kernel\/|parameters\/|debug\/)/;
- # comment this one out if you experience hangs or if
- # we discover syntax of foreign language characters
- # Must be ascii like. This is questionable and might require further
- # investigation, it is removing some characters that we might want
- return unless -T;
+ return unless -r; # Must be readable
+ if ($parse_src eq 'sys'){
+ # note: a new file in 4.11 /sys can hang this, it is /parameter/ then
+ # a few variables. Since inxi does not need to see that file, we will
+ # not use it. Also do not need . files or __ starting files
+ # print $File::Find::name . "\n";
+ # block maybe: cfgroup\/
+ return if $File::Find::name =~ /\/(\.[a-z]|kernel\/|parameters\/|debug\/)/;
+ # comment this one out if you experience hangs or if
+ # we discover syntax of foreign language characters
+ # Must be ascii like. This is questionable and might require further
+ # investigation, it is removing some characters that we might want
+ return unless -T;
+ }
+ elsif ($parse_src eq 'proc') {
+ return if $File::Find::name =~ /^\/proc\/[0-9]+\//;
+ return if $File::Find::name =~ /^\/proc\/bus\/pci\//;
+ return if $File::Find::name =~ /^\/proc\/irq\//;
+ return if $File::Find::name =~ /(\/mb_groups|debug)$/;
+ return if $File::Find::name eq '/proc/kallsyms' || $File::Find::name eq '/proc/keys';
+ }
# print $File::Find::name . "\n";
push (@content, $File::Find::name);
return;
}
-sub process_data {
+sub process_sys_data {
my ($data,$fh,$result,$row,$sep);
my $filename = "sys-data-parse.txt";
# no sorts, we want the order it comes in
@@ -1892,6 +1946,16 @@ sub process_data {
close $fh;
# print $fh "$result";
}
+sub process_proc_data {
+ my ($data,$fh,$result,$row,$sep);
+ my $proc_dir = "$data_dir/proc";
+ mkdir $proc_dir or main::error_handler('mkdir', "$proc_dir", "$!");
+ # @content = sort @content;
+ copy_files(\@content,'proc',$proc_dir);
+# foreach (@content){
+# print "$_\n";
+# }
+}
# args: 1 - path to file to be uploaded
# args: 2 - optional: alternate ftp upload url
# NOTE: must be in format: ftp.site.com/incoming
@@ -2111,8 +2175,10 @@ sub set_perl_downloader {
#### -------------------------------------------------------------------
sub error_handler {
+ eval $start if $b_log;
my ( $err, $one, $two) = @_;
- my ($b_recommends,$b_help,$errno) = (0,0,0);
+ my ($b_help,$b_recommends);
+ my ($b_exit,$errno) = (1,0);
my $message = do {
if ( $err eq 'empty' ) { 'empty value' }
## Basic rules
@@ -2146,7 +2212,7 @@ sub error_handler {
elsif ( $err eq 'mkdir' ) {
$errno=44; "Error creating directory: $one \nError: $two" }
elsif ( $err eq 'open' ) {
- $errno=45; "Error opening file: $one \nError: $two" }
+ $errno=45; $b_exit=0; "Error opening file: $one \nError: $two" }
elsif ( $err eq 'open-dir' ) {
$errno=46; "Error opening directory: $one \nError: $two" }
elsif ( $err eq 'output-file-bad' ) {
@@ -2187,7 +2253,8 @@ sub error_handler {
if ($b_recommends){
print_line("See --recommends for more information.\n");
}
- exit 0;
+ eval $end if $b_log;
+ exit 0 if $b_exit;
}
sub error_defaults {
@@ -2281,12 +2348,12 @@ sub check_items {
elsif ($type eq 'recommended system programs'){
if ($bsd_type){
@data = qw(camcontrol dig dmidecode fdisk file glabel gpart ifconfig ipmi-sensors
- ipmitool lsusb sudo smartctl sysctl tree uptime usbdevs);
+ ipmitool lsusb sudo smartctl sysctl tree upower uptime usbdevs);
$info_os = 'info-bsd';
}
else {
@data = qw(dig dmidecode fdisk file hddtemp ifconfig ip ipmitool ipmi-sensors
- lsblk lsusb modinfo runlevel sensors strings sudo tree uptime);
+ lsblk lsusb modinfo runlevel sensors strings sudo tree upower uptime);
}
$b_program = 1;
$item = 'Program';
@@ -2659,6 +2726,13 @@ sub item_data {
'pacman' => 'tree',
'rpm' => 'tree',
}),
+ 'upower' => ({
+ 'info' => '-sx attached device battery info',
+ 'info-bsd' => '-sx attached device battery info',
+ 'apt' => 'upower',
+ 'pacman' => 'upower',
+ 'rpm' => 'upower',
+ }),
'uptime' => ({
'info' => '-I uptime',
'info-bsd' => '-I uptime',
@@ -3397,6 +3471,8 @@ sub get_options{
my ($b_downloader,$b_help,$b_no_man,$b_no_man_force,$b_recommends,$b_updater,$b_version,
$b_use_man,$self_download, $download_id);
GetOptions (
+ 'admin' => sub {
+ $b_admin = 1;},
'A|audio' => sub {
$show{'short'} = 0;
$show{'audio'} = 1;},
@@ -3652,8 +3728,11 @@ sub get_options{
my ($opt,$arg) = @_;
$arg ||= '';
$arg =~ s/\s//g;
- if ($arg && $arg =~ /^(cf|fc|f|c)$/i){
- $weather_unit = lc($arg);
+ $arg = lc($arg) if $arg;
+ if ($arg && $arg =~ /^(c|f|cf|fc|i|m|im|mi)$/){
+ my %units = ('c'=>'m','f'=>'i','cf'=>'mi','fc'=>'im');
+ $arg = $units{$arg} if defined $units{$arg};
+ $weather_unit = $arg;
}
else {
error_handler('bad-arg',$opt,$arg);
@@ -3961,7 +4040,7 @@ sub show_options {
['0', '', '', "Output Control Options:" ],
['1', '-A', '--audio', "Audio/sound card(s), driver, sound server." ],
['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ],
- ['1', '-B', '--battery', "Battery info, including charge and condition, plus
+ ['1', '-B', '--battery', "System battery info, including charge and condition, plus
extra info (if battery present)." ],
['1', '-c', '--color', "Set color scheme (0-42). Example:^$self_name^-c^11" ],
['1', '', '', "Color selectors let you set the config file value for the
@@ -4064,22 +4143,23 @@ sub show_options {
Only use if you want the weather somewhere other than the machine running
$self_name. Use only ASCII characters, replace spaces in city/state/country names with '+'.
Example:^$self_name^-W^new+york,ny"],
- ['1', '', '--weather-unit', "Set weather units to metric (m), imperial (f),
- metric/imperial (cf), or imperial/metric (fc)."],
+ ['1', '', '--weather-unit', "Set weather units to metric (m), imperial (i),
+ metric/imperial (mi), or imperial/metric (im)."],
);
push @data, @rows;
}
@rows = (
- ['1', '-x', '-extra', "Adds the following extra data (only works with
+ ['1', '-x', '--extra', "Adds the following extra data (only works with
verbose or line output, not short form):" ],
- ['2', '-B', '', "Vendor/model, status (if available)." ],
+ ['2', '-B', '', "Vendor/model, status (if available); attached devices
+ (e.g. wireless mouse, keyboard, if present)." ],
['2', '-C', '', "CPU $flags, Bogomips on CPU; CPU microarchitecture +
- revision (if found)." ],
+ revision (if found, or unless --admin, then shows as 'stepping')." ],
['2', '-d', '', "Extra optical drive features data; adds rev version to
optical drive." ],
- ['2', '-D', '', "HDD temp with disk data if you have hddtemp installed, if
- you are root, or if you have added to /etc/sudoers (sudo v. 1.7 or newer).
- Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp" ],
+ ['2', '-D', '', "HDD temp with disk data if you have hddtemp installed,
+ if you are root, or if you have added to /etc/sudoers (sudo v. 1.7 or newer).
+ Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp" ],
['2', '-G', '', "Direct rendering status (in X); Screen number GPU is
running on (Nvidia only)." ],
['2', '-i', '', "For IPv6, show additional scope addresses: Global, Site,
@@ -4112,7 +4192,7 @@ sub show_options {
['2', '-A', '', "Chip vendor:product ID for each audio device." ],
['2', '-B', '', "Serial number, voltage now/minimum (if available)." ],
['2', '-C', '', "Minimum CPU speed, if available." ],
- ['2', '-D', '', "Disk serial number." ],
+ ['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number." ],
['2', '-G', '', "Chip vendor:product ID for each video card; OpenGL
compatibility version, if free drivers and available; compositor (experimental)." ],
['2', '-I', '', "Other detected installed gcc versions (if present). System
@@ -4138,7 +4218,8 @@ sub show_options {
['1', '-xxx', '--extra 3', "Show extra, extra, extra data (only works
with verbose or line output, not short form):" ],
['2', '-B', '', "Chemistry, cycles, location (if available)." ],
- ['2', '-D', '', "Firmware rev. if available; partition scheme, in some cases." ],
+ ['2', '-D', '', "Firmware rev. if available; partition scheme, in some cases; disk
+ rotation speed (if detected)." ],
['2', '-I', '', "For 'Shell:' adds ([su|sudo|login]) to shell name if present;
for 'running in:' adds (SSH) if SSH session." ],
['2', '-m', '', "Width of memory bus, data and total (if present and greater
@@ -4155,6 +4236,10 @@ sub show_options {
push @data, @rows;
}
@rows = (
+ ['1', '', '--admin', "Adds advanced sys admin data (only works with
+ verbose or line output, not short form):" ],
+ ['2', '-C', '', "If available: CPU errata (bugs); family, model-id, stepping - format:
+ hex (decimal) if greater than 9, otherwise hex; microcode - format: hex." ],
['1', '-y', '--width', "Output line width max (integer >= 80). Overrides IRC/Terminal
settings or actual widths. Example:^inxi^-y^130" ],
['1', '-z', '--filter', "Adds security filters for IP/MAC addresses, serial numbers,
@@ -4681,11 +4766,13 @@ sub clean_characters {
my ($data) = @_;
# newline, pipe, brackets, + sign, with space, then clear doubled
# spaces and then strip out trailing/leading spaces.
- $data =~ s/\n|\|\+|\[\s\]|\s\s+/ /g if $data;
- $data =~ s/^\s+|\s+$//g if $data;
+ # etc/issue often has junk stuff like (\l) \n \l
+ return if ! $data;
+ $data =~ s/[:\47]|\\[a-z]|\n|,|\"|\*|\||\+|\[\s\]|n\/a|\s\s+/ /g;
+ $data =~ s/\(\)//;
+ $data =~ s/^\s+|\s+$//g;
return $data;
}
-
sub cleaner {
my ($item) = @_;
return $item if !$item;# handle cases where it was 0 or ''
@@ -4700,6 +4787,7 @@ sub cleaner {
sub disk_cleaner {
my ($item) = @_;
return $item if !$item;
+ # <?unknown>?|
$item =~ s/vendor.*|product.*|O\.?E\.?M\.?//gi;
$item =~ s/\s\s+/ /g;
$item =~ s/^\s+|\s+$//g;
@@ -4839,7 +4927,7 @@ sub row_defaults {
my %unfound = (
'arm-cpu-f' => 'Use -f option to see features',
'arm-pci' => "PCI data type is not supported on ARM systems.",
- 'battery-data' => "No battery data found. Is one present?",
+ 'battery-data' => "No system battery data found. Is one present?",
'battery-data-sys' => "No /sys data found. Old system?",
'cpu-model-null' => "Model N/A",
'darwin-feature' => "Feature not supported iu Darwin/OSX.",
@@ -5597,10 +5685,10 @@ sub sound_server_data {
## BatteryData
{
package BatteryData;
-
+my (@upower_items,$b_upower,$upower);
sub get {
eval $start if $b_log;
- my (@rows,$key1,%battery,$val1);
+ my (@rows,%battery,$key1,$val1);
my $num = 0;
if ($bsd_type || $b_dmidecode_force){
my $ref = $alerts{'dmidecode'};
@@ -5644,6 +5732,7 @@ sub get {
@rows = ({main::key($num++,$key1) => $val1,});
}
}
+ (@upower_items,$b_upower,$upower) = undef;
eval $end if $b_log;
return @rows;
}
@@ -5670,20 +5759,22 @@ sub get {
# 17 location
sub create_output {
eval $start if $b_log;
- my (%battery,@data,@rows) = @_;
- my ($key);
+ my (%battery) = @_;
+ my ($key,@data,@rows);
my $num = 0;
my $j = 0;
+ # print Data::Dumper::Dumper \%battery;
foreach $key (sort keys %battery){
$num = 0;
my ($charge,$condition,$model,$serial,$status,$volts) = ('','','','','','');
my ($chemistry,$cycles,$location) = ('','','');
+ next if !$battery{$key}{'purpose'} || $battery{$key}{'purpose'} ne 'primary';
# $battery{$key}{''};
# we need to handle cases where charge or energy full is 0
- $charge = ($battery{$key}{'energy_now'} || $battery{$key}{'energy_now'} eq 0) ? "$battery{$key}{'energy_now'} Wh" : 'N/A';
+ $charge = (defined $battery{$key}{'energy_now'} && $battery{$key}{'energy_now'} ne '') ? "$battery{$key}{'energy_now'} Wh" : 'N/A';
if ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full_design'}){
$battery{$key}{'energy_full_design'} ||= 'N/A';
- $battery{$key}{'energy_full'}= ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full'} eq 0) ? $battery{$key}{'energy_full'} : 'N/A';
+ $battery{$key}{'energy_full'}= (defined $battery{$key}{'energy_full'} && $battery{$key}{'energy_full'} ne '') ? $battery{$key}{'energy_full'} : 'N/A';
$condition = "$battery{$key}{'energy_full'}/$battery{$key}{'energy_full_design'} Wh";
if ($battery{$key}{'of_orig'}){
$condition .= " ($battery{$key}{'of_orig'}%)";
@@ -5741,6 +5832,57 @@ sub create_output {
}
}
}
+ $battery{$key} = undef;
+ }
+ # print Data::Dumper::Dumper \%battery;
+ # now if there are any devices left, print them out, excluding Mains
+ if ($extra > 0){
+ $upower = main::check_program('upower');
+ foreach $key (sort keys %battery){
+ $num = 0;
+ next if !defined $battery{$key} || $battery{$key}{'purpose'} eq 'mains';
+ my ($charge,$model,$serial,$percent,$status,$vendor) = ('','','','','','');
+ my (%upower_data);
+ $j = scalar @rows;
+ %upower_data = upower_data($key) if $upower;
+ if ($upower_data{'percent'}){
+ $charge = $upower_data{'percent'};
+ }
+ elsif ($battery{$key}{'capacity_level'} && lc($battery{$key}{'capacity_level'}) ne 'unknown'){
+ $charge = $battery{$key}{'capacity_level'};
+ }
+ else {
+ $charge = 'N/A';
+ }
+ $model = $battery{$key}{'model_name'} if $battery{$key}{'model_name'};
+ $status = ($battery{$key}{'status'} && lc($battery{$key}{'status'}) ne 'unknown') ? $battery{$key}{'status'}: 'N/A' ;
+ $vendor = $battery{$key}{'manufacturer'} if $battery{$key}{'manufacturer'};
+ if ($vendor || $model){
+ if ($vendor && $model){
+ $model = "$vendor $model";
+ }
+ elsif ($vendor){
+ $model = $vendor;
+ }
+ }
+ else {
+ $model = 'N/A';
+ }
+ @data = ({
+ main::key($num++,'Device') => $key,
+ main::key($num++,'model') => $model,
+ },);
+ @rows = (@rows,@data);
+ if ($extra > 1){
+ $serial = main::apply_filter($battery{$key}{'serial_number'});
+ $rows[$j]{main::key($num++,'serial')} = $serial;
+ }
+ $rows[$j]{main::key($num++,'charge')} = $charge;
+ if ($extra > 2 && $upower_data{'rechargeable'}){
+ $rows[$j]{main::key($num++,'rechargeable')} = $upower_data{'rechargeable'};
+ }
+ $rows[$j]{main::key($num++,'status')} = $status;
+ }
}
eval $end if $b_log;
return @rows;
@@ -5751,10 +5893,9 @@ sub battery_data_sys {
eval $start if $b_log;
my ($b_ma,%battery,$file,$id,$item,$path,$value);
my $num = 0;
- # NOTE: known ids: BAT[0-9] CMB[0-9]
- my @batteries = main::globber("/sys/class/power_supply/[BC][AM][TB]*/");
+ my @batteries = main::globber("/sys/class/power_supply/*");
# note: there is no 'location' file, but dmidecode has it
- # 'type' is generic, like: Battery
+ # 'type' is generic, like: Battery, Mains
# capacity_level is a string, like: Normal
my @items = qw(alarm capacity capacity_level charge_full charge_full_design charge_now
cycle_count energy_full energy_full_design energy_now location manufacturer model_name
@@ -5762,11 +5903,20 @@ sub battery_data_sys {
foreach $item (@batteries){
$b_ma = 0;
$id = $item;
- $id =~ s%/sys/class/power_supply/|\/$%%g;
+ $id =~ s%/sys/class/power_supply/%%g;
+ my $purpose = ($id =~ /^(BAT|CMB).*$/) ? 'primary': 'device';
+ # don't create arrays of device data if it's not going to show
+ next if $extra == 0 && $purpose ne 'primary';
$battery{$id} = ({});
+ # NOTE: known ids: BAT[0-9] CMB[0-9]
+ $battery{$id}{'purpose'} = $purpose;
foreach $file (@items){
- $path = "$item$file";
+ $path = "$item/$file";
$value = (-f $path) ? (main::reader($path))[0]: '';
+ # mains
+ if ($file eq 'type' && $value && lc($value) ne 'battery' ){
+ $battery{$id}{'purpose'} = 'mains';
+ }
if ($value){
if ($file eq 'voltage_min_design'){
$value = sprintf("%.1f", $value/1000000);
@@ -5860,6 +6010,7 @@ sub battery_data_dmi {
$id = "BAT$i";
$i++;
$battery{$id} = ({});
+ $battery{$id}{'purpose'} = 'primary';
# skip first three row, we don't need that data
splice @ref, 0, 3 if @ref;
foreach my $item (@ref){
@@ -5873,7 +6024,6 @@ sub battery_data_dmi {
elsif ($value[0] eq 'Design Capacity') {
$value[1] =~ s/\s*mwh$//i;
$battery{$id}{'energy_full_design'} = sprintf( "%.1f", $value[1]/1000);
-
}
elsif ($value[0] eq 'Design Voltage') {
$value[1] =~ s/\s*mv$//i;
@@ -5897,6 +6047,35 @@ sub battery_data_dmi {
eval $end if $b_log;
return %battery;
}
+sub upower_data {
+ my ($id) = @_;
+ eval $start if $b_log;
+ my (%data);
+ if (!$b_upower && $upower){
+ @upower_items = main::grabber("$upower -e",'','strip');
+ $b_upower = 1;
+ }
+ if ($upower && @upower_items){
+ foreach (@upower_items){
+ if ($_ =~ /$id/){
+ my @working = main::grabber("$upower -i $_",'','strip');
+ foreach my $row (@working){
+ my @temp = split /\s*:\s*/, $row;
+ if ($temp[0] eq 'percentage'){
+ $data{'percent'} = $temp[1];
+ }
+ elsif ($temp[0] eq 'rechargeable'){
+ $data{'rechargeable'} = $temp[1];
+ }
+ }
+ last;
+ }
+ }
+ }
+ eval $end if $b_log;
+ return %data;
+}
+
}
## CpuData
@@ -5967,10 +6146,18 @@ sub create_output_full {
if ($extra > 0){
$cpu{'arch'} ||= 'N/A';
$rows[$j]{main::key($num++,'arch')} = $cpu{'arch'};
- if ( $cpu{'arch'} ne 'N/A' && $cpu{'rev'} ){
+ if ( !$b_admin && $cpu{'arch'} ne 'N/A' && $cpu{'rev'} ){
$rows[$j]{main::key($num++,'rev')} = $cpu{'rev'};
}
}
+ if ($b_admin){
+ $rows[$j]{main::key($num++,'family')} = hex_and_decimal($cpu{'family'});
+ $rows[$j]{main::key($num++,'model-id')} = hex_and_decimal($cpu{'model_id'});
+ $rows[$j]{main::key($num++,'stepping')} = hex_and_decimal($cpu{'rev'});
+ $cpu{'microcode'} ||= 'N/A';
+ $rows[$j]{main::key($num++,'microcode')} = $cpu{'microcode'};
+ }
+
$properties{'l2-cache'} ||= 'N/A';
$rows[$j]{main::key($num++,'L2 cache')} = $properties{'l2-cache'} if (!$b_arm || ($b_arm && $properties{'l2-cache'} ne 'N/A'));
if ($extra > 0 && !$show{'cpu-flag'}){
@@ -6030,6 +6217,15 @@ sub create_output_full {
},);
@rows = (@rows,@data);
}
+ if ($b_admin && $cpu{'bugs'}){
+ my @bugs = split /\s+/, $cpu{'bugs'};
+ @bugs = sort(@bugs);
+ my $bug = join ' ', @bugs;
+ @data = ({
+ main::key($num++,'Errata') => $bug,
+ },);
+ @rows = (@rows,@data);
+ }
eval $end if $b_log;
return @rows;
}
@@ -6230,7 +6426,7 @@ sub data_cpuinfo {
}
}
elsif (!$cpu{'rev'} && ($line[0] eq 'stepping' || $line[0] eq 'cpu revision' )){
- $cpu{'rev'} = $line[1];
+ $cpu{'rev'} = uc(sprintf("%x", $line[1]));
}
# this is hex so uc for cpu arch id
elsif (!$cpu{'model_id'} && $line[0] eq 'model' ){
@@ -6325,6 +6521,21 @@ sub data_cpuinfo {
$cpu{'bogomips'} += $line[1] if $line[1] > 50;
}
}
+ if ($b_admin ){
+ if ( !$cpu{'bugs'} && $line[0] eq 'bugs'){
+ $cpu{'bugs'} = $line[1];
+ }
+ # unlike family and model id, microcode appears to be hex already
+ if ( !$cpu{'microcode'} && $line[0] eq 'microcode'){
+ if ($line[1] =~ /0x/){
+ $cpu{'microcode'} = uc($line[1]);
+ $cpu{'microcode'} =~ s/^0X//;
+ }
+ else {
+ $cpu{'microcode'} = uc(sprintf("%x", $line[1]));
+ }
+ }
+ }
}
$cpu{'phys'} = scalar @phys_cpus;
$cpu{'dies'} = $die_id++; # count starts at 0, all cpus have 1 die at least
@@ -7093,6 +7304,16 @@ sub cpu_cleaner {
$cpu =~ s/^\s+|\s+$//g;
return $cpu;
}
+sub hex_and_decimal {
+ my ($data) = @_;
+ if ($data){
+ $data .= ' (' . hex($data) . ')' if hex($data) ne $data;
+ }
+ else {
+ $data = 'N/A';
+ }
+ return $data;
+}
}
## DiskData
@@ -7226,8 +7447,12 @@ sub create_output {
}
$rows[$j]{main::key($num++,'model')} = $model;
$rows[$j]{main::key($num++,'size')} = $size;
- if ($extra > 0 && $row{'speed'}){
+ if ($extra > 1 && $row{'speed'}){
$rows[$j]{main::key($num++,'speed')} = $row{'speed'};
+ $rows[$j]{main::key($num++,'lanes')} = $row{'lanes'} if $row{'lanes'};
+ }
+ if ($extra > 2 && $row{'rotation'}){
+ $rows[$j]{main::key($num++,'rotation')} = $row{'rotation'};
}
if ($extra > 1){
my $serial = main::apply_filter($row{'serial'});
@@ -7380,9 +7605,10 @@ sub proc_data_advanced {
($block_type,$firmware,$model,$partition_scheme,
$serial,$vendor,$working_path) = ('','','','','','','');
if ($extra > 2){
- @data = partition_scheme($pt_cmd,$drives[$i]{'id'});
+ @data = advanced_disk_data($pt_cmd,$drives[$i]{'id'});
$pt_cmd = $data[0];
$drives[$i]{'partition-table'} = uc($data[1]) if $data[1];
+ $drives[$i]{'rotation'} = "$data[2] rpm" if $data[2];
}
#print "$drives[$i]{'id'}\n";
@disk_data = disk_data_by_id("/dev/$drives[$i]{'id'}");
@@ -7465,6 +7691,9 @@ sub proc_data_advanced {
if ($extra > 0){
$drives[$i]{'temp'} = hdd_temp("/dev/$drives[$i]{'id'}");
if ($extra > 1){
+ my @speed_data = device_speed($drives[$i]{'id'});
+ $drives[$i]{'speed'} = $speed_data[0] if $speed_data[0];
+ $drives[$i]{'lanes'} = $speed_data[1] if $speed_data[1];
if (@disk_data && $disk_data[2]){
$drives[$i]{'serial'} = $disk_data[2];
}
@@ -7624,7 +7853,7 @@ sub peripheral_data {
eval $end if $b_log;
return $type;
}
-sub partition_scheme {
+sub advanced_disk_data {
eval $start if $b_log;
my ($set_cmd,$id) = @_;
my ($cmd,$pt,$program,@data,@return);
@@ -7635,15 +7864,13 @@ sub partition_scheme {
# runs as user, but is SLOW: udisksctl info -b /dev/sda
# line: org.freedesktop.UDisks2.PartitionTable:
# Type: dos
- if (!$b_root){
- if ($program = main::check_program('udevadm')){
- $return[0] = "$program info -q property -n ";
- }
+ if ($program = main::check_program('udevadm')){
+ $return[0] = "$program info -q property -n ";
}
- if (!$return[0] && $b_root && -e "/lib/udev/udisks-part-id") {
+ elsif ($b_root && -e "/lib/udev/udisks-part-id") {
$return[0] = "/lib/udev/udisks-part-id /dev/";
}
- elsif (!$return[0] && $b_root && ($program = main::check_program('fdisk'))) {
+ elsif ($b_root && ($program = main::check_program('fdisk'))) {
$return[0] = "$program -l /dev/";
}
if (!$return[0]) {
@@ -7670,9 +7897,19 @@ sub partition_scheme {
$return[1] = 'dos' if !$return[1];
}
else {
- $return[1] = main::awk(\@data,'^(UDISKS_PARTITION_TABLE_SCHEME|ID_PART_TABLE_TYPE)',2,'=');
+ foreach (@data){
+ if ( /^(UDISKS_PARTITION_TABLE_SCHEME|ID_PART_TABLE_TYPE)/ ){
+ my @working = split /=/, $_;
+ $return[1] = $working[1];
+ }
+ elsif (/^ID_ATA_ROTATION_RATE_RPM/){
+ my @working = split /=/, $_;
+ $return[2] = $working[1];
+ }
+ last if $return[1] && $return[2];
+ }
}
- $return[1] = 'mbr' if $return[1] && $return[1] eq 'dos';
+ $return[1] = 'mbr' if $return[1] && lc($return[1]) eq 'dos';
}
eval $end if $b_log;
return @return;
@@ -7777,7 +8014,8 @@ sub device_vendor {
['^PNY','^PNY\s','PNY','','^PNY'],
['^(SanDisk|SDS[S]?[DQ]|SL([0-9]+)G|AFGCE)','^SanDisk','SanDisk',''],
# note: get rid of: M[DGK] becasue mushkin starts with MK
- ['^([S]?TOS|THN)','^[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_
+ # note: seen: KXG50ZNV512G NVMe TOSHIBA 512GB | THNSN51T02DUK NVMe TOSHIBA 1024GB
+ ['(^[S]?TOS|^THN|TOSHIBA)','[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_
## These go last because they are short and could lead to false ID, or are unlikely ##
['^Android','^Android','Android',''],
# must come before AP|Apacer
@@ -7785,6 +8023,7 @@ sub device_vendor {
['^(AP|Apacer)','^Apacer','Apacer',''],
['^BUFFALO','^BUFFALO','Buffalo',''],
['^EXCELSTOR','^EXCELSTOR( TECHNOLOGY)?','Excelstor',''],
+ ['^GALAX\b','^GALAX','GALAX',''],
['^Generic','^Generic','Generic',''],
['^GOODRAM','^GOODRAM','GOODRAM',''],
# supertalent also has FM: |FM
@@ -7840,6 +8079,7 @@ sub device_vendor {
$vendor = $row[2];
$model =~ s/$row[1]//i if $row[1] && lc($model) ne lc($row[1]);
$model =~ s/^[\s\-_]+|[\s\-_]+$//g;
+ $model =~ s/\s\s/ /g;
@data = ($vendor,$model);
last;
}
@@ -7889,6 +8129,69 @@ sub hdd_temp {
eval $end if $b_log;
return $hdd_temp;
}
+sub device_speed {
+ eval $start if $b_log;
+ my ($device) = @_;
+ my ($b_nvme,$lanes,$speed,@data);
+ my $working = Cwd::abs_path("/sys/class/block/$device");
+ #print "$working\n";
+ if ($working){
+ my ($id);
+ # slice out the ata id:
+ # /sys/devices/pci0000:00:11.0/ata1/host0/target0:
+ if ($working =~ /^.*\/ata([0-9]+)\/.*/){
+ $id = $1;
+ }
+ # /sys/devices/pci0000:00/0000:00:05.0/virtio1/block/vda
+ elsif ($working =~ /^.*\/virtio([0-9]+)\/.*/){
+ $id = $1;
+ }
+ # /sys/devices/pci0000:10/0000:10:01.2/0000:13:00.0/nvme/nvme0/nvme0n1
+ elsif ($working =~ /^.*\/(nvme[0-9]+)\/.*/){
+ $id = $1;
+ $b_nvme = 1;
+ }
+ # do host last because the strings above might have host as well as their search item
+ # 0000:00:1f.2/host3/target3: increment by 1 sine ata starts at 1, but host at 0
+ elsif ($working =~ /^.*\/host([0-9]+)\/.*/){
+ $id = $1 + 1 if defined $1;
+ }
+ # print "$working $id\n";
+ if (defined $id){
+ if ($b_nvme){
+ $working = "/sys/class/nvme/$id/device/max_link_speed";
+ $speed = (main::reader($working))[0] if -f $working;
+ if ($speed =~ /([0-9\.]+)\sGT\/s/){
+ $speed = $1;
+ # pcie1: 2.5 GT/s; pcie2: 5.0 GT/s; pci3: 8 GT/s
+ # NOTE: PCIe 3 stopped using the 8b/10b encoding but a sample pcie3 nvme has
+ # rated speed of GT/s * .8 anyway. GT/s * (128b/130b)
+ $speed = ($speed <= 5 ) ? $speed * .8 : $speed * 128/130;
+ $speed = sprintf("%.1f",$speed) if $speed;
+ $working = "/sys/class/nvme/$id/device/max_link_width";
+ $lanes = (main::reader($working))[0] if -f $working;
+ $lanes = 1 if !$lanes;
+ # https://www.edn.com/electronics-news/4380071/What-does-GT-s-mean-anyway-
+ # https://www.anandtech.com/show/2412/2
+ # http://www.tested.com/tech/457440-theoretical-vs-actual-bandwidth-pci-express-and-thunderbolt/
+ # PCIe 1,2 use “8b/10b” encoding: eight bits are encoded into a 10-bit symbol
+ # PCIe 3,4,5 use "128b/130b" encoding: 128 bits are encoded into a 130 bit symbol
+ $speed = ($speed * $lanes) . " Gb/s";
+ }
+ }
+ else {
+ $working = "/sys/class/ata_link/link$id/sata_spd";
+ $speed = (main::reader($working))[0] if -f $working;
+ $speed = main::disk_cleaner($speed) if $speed;
+ $speed =~ s/Gbps/Gb\/s/ if $speed;
+ }
+ }
+ }
+ @data = ($speed,$lanes);
+ #print "$working $speed\n";
+ eval $end if $b_log;
+ return @data;
+}
# gptid/c5e940f1-5ce2-11e6-9eeb-d05099ac4dc2 N/A ada0p1
sub match_glabel {
eval $start if $b_log;
@@ -8035,7 +8338,7 @@ sub display_data(){
# $id = $ENV{'XDG_SESSION_ID'}; # returns tty session in console
my @data = main::grabber("$program --no-pager --no-legend 2>/dev/null",'','strip');
foreach (@data){
- next if /tty[0-6]$/;
+ next if /tty[v]?[0-6]$/; # freebsd: ttyv3
$id = (split /\s+/, $_)[0];
last; # multiuser? too bad, we'll go for the first one
}
@@ -8443,6 +8746,9 @@ sub display_compositor {
if (main::check_program('mutter') && (grep {/mutter/} @ps_cmd ) ) {
$compositor = 'mutter';
}
+ elsif (main::check_program('kwin_wayland') && (grep {/\bkwin_wayland\b/} @ps_cmd ) ) {
+ $compositor = 'kwin_wayland';
+ }
elsif (main::check_program('kwin') && (grep {/\bkwin\b/} @ps_cmd ) ) {
$compositor = 'kwin';
}
@@ -8632,7 +8938,8 @@ sub create_output {
if ($data{'chassis_vendor'} ne $data{'sys_vendor'} ){
$chassis_vendor = $data{'chassis_vendor'};
}
- if ($data{'chassis_type'} ){
+ # dmidecode can have these be the same
+ if ($data{'chassis_type'} && $data{'device'} ne $data{'chassis_type'} ){
$chassis_type = $data{'chassis_type'};
}
if ($data{'chassis_version'}){
@@ -8704,11 +9011,18 @@ sub create_output_arm {
my $num = 0;
my $j = 0;
#print Data::Dumper::Dumper \%arm_machine;
- if ($arm_machine{'device'}){
- my $device = main::cleaner( $arm_machine{'device'} );
- $device ||= 'N/A';
+ # this is sketchy, /proc/device-tree/model may be similar to Hardware value from /proc/cpuinfo
+ # raspi: Hardware : BCM2835 model: Raspberry Pi Model B Rev 2
+ if ($arm_machine{'device'} || $arm_machine{'model'}){
$rows[$j]{main::key($num++,'Type')} = 'ARM Device';
- $rows[$j]{main::key($num++,'System')} = $device;
+ my $system = 'System';
+ if (defined $arm_machine{'model'}){
+ $rows[$j]{main::key($num++,'System')} = $arm_machine{'model'};
+ $system = 'v';
+ }
+ my $device = $arm_machine{'device'};
+ $device ||= 'N/A';
+ $rows[$j]{main::key($num++,$system)} = $device;
}
# we're going to print N/A for 0000 values sine the item was there.
if ($arm_machine{'firmware'}){
@@ -8799,7 +9113,7 @@ sub machine_data_arm {
foreach (@data){
if (/^Hardware/i){
@temp = split /\s*:\s*/, $_;
- $arm_machine{'device'} = $temp[1];
+ $arm_machine{'device'} = main::cleaner($temp[1]);
}
elsif (/^Revision/i){
@temp = split /\s*:\s*/, $_;
@@ -8811,6 +9125,19 @@ sub machine_data_arm {
}
}
}
+ if (-f '/proc/device-tree/model'){
+ my $model = (main::reader('/proc/device-tree/model'))[0];
+ main::log_data('data',"device-tree-model: $model") if $b_log;
+ if ( $model ){
+ $model = main::dmi_cleaner($model);
+ my (@result) = ();
+ @result = split(/\s+/, $arm_machine{'device'}) if $arm_machine{'device'};
+ if ( !$arm_machine{'device'} ||
+ (scalar(@result) == 1 && $model !~ /$arm_machine{'device'}/) ){
+ $arm_machine{'model'} = $model;
+ }
+ }
+ }
#print Data::Dumper::Dumper \%arm_machine;
eval $end if $b_log;
return %arm_machine;
@@ -9165,8 +9492,10 @@ sub card_data {
foreach (@pci){
$num = 1;
my @row = @$_;
- #print "$row[0] $row[3]\n";
- if ($row[0] eq 'network' || $row[0] eq 'ethernet' ){
+ #print "$row[0] $row[3]\n";
+ # NOTE: class 06 subclass 80
+ # https://www-s.acm.illinois.edu/sigops/2007/roll_your_own/7.c.1.html
+ if ($row[0] eq 'network' || $row[0] eq 'ethernet' || $row[1] eq '0680' ){
#print "$row[0] $row[3]\n";
$j = scalar @rows;
my $driver = $row[9];
@@ -9184,12 +9513,10 @@ sub card_data {
$card = ($card) ? main::pci_cleaner($card,'output') : 'N/A';
#$card ||= 'N/A';
$driver ||= 'N/A';
- @data = (
- {
+ @data = ({
main::key($num++,'Card') => $card,
main::key($num++,'driver') => $driver,
- },
- );
+ },);
@rows = (@rows,@data);
if ($extra > 0){
if ($row[9] && !$bsd_type){
@@ -10123,14 +10450,14 @@ sub partition_data {
}
}
@partitions_working = grep {!/^rootfs/} @partitions_working if $roots > 1;
- my $filters = '^(aufs|cgroup.*|cgmfs|configfs|debugfs|\/dev|dev|\/dev/loop[0-9]*|devfs|devtmpfs|';
- $filters .= 'fdescfs|iso9660|linprocfs|none|procfs|\/run(\/.*)?|run|squashfs|sys|\/sys\/.*|sysfs|';
- $filters .= 'tmpfs|type|udev|unionfs|vartmp)$';
+ my $filters = '^(aufs|cgroup.*|cgmfs|configfs|debugfs|\/dev|dev|\/dev/loop[0-9]*|';
+ $filters .= 'devfs|devtmpfs|fdescfs|iso9660|linprocfs|none|procfs|\/run(\/.*)?|';
+ $filters .= 'run|shm|squashfs|sys|\/sys\/.*|sysfs|tmpfs|type|udev|unionfs|vartmp)$';
foreach (@partitions_working){
# stupid apple bullshit
$_ =~ s/^map\s+([\S]+)/map:\/$1/ if $b_fake_map;
my @row = split /\s+/, $_;
- if ($row[0] =~ /$filters/ || $row[0] =~ /^ROOT/i){
+ if ($row[0] =~ /$filters/ || $row[0] =~ /^ROOT/i || ($b_fs && $row[1] eq 'tmpfs')){
next;
}
$dev_base = '';
@@ -12778,9 +13105,14 @@ sub sensors_data {
# which is the maximum CPU temperature reported as critical temperature by coretemp"
# NOTE: I've seen an inexplicable case where: CPU:52.0°C fails to match with [\s°] but
# does match with: [\s°]*. I can't account for this, but that's why the * is there
- elsif (!$sensors{'cpu-temp'} && $_ =~ /^CPU.*:([0-9\.]+)[\s°]*(C|F)/i) {
- $sensors{'cpu-temp'} = $1;
- $working_unit = $2;
+ # Tdie is a new k10temp-pci syntax for cpu die temp
+ elsif ($_ =~ /^(CPU.*|Tdie.*):([0-9\.]+)[\s°]*(C|F)/i) {
+ $temp_working = $2;
+ $working_unit = $3;
+ if ( !$sensors{'cpu-temp'} ||
+ ( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'cpu-temp'} ) ) {
+ $sensors{'cpu-temp'} = $temp_working;
+ }
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
}
elsif ($_ =~ /^PECI\sAgent\s0.*:([0-9\.]+)[\s°]*(C|F)/i) {
@@ -12797,13 +13129,13 @@ sub sensors_data {
$sensors{'sodimm-temp'} = $1;
$working_unit = $2;
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
-
}
# for temp1/2 only use temp1/2 if they are null or greater than the last ones
elsif ($_ =~ /^temp1:([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $1;
$working_unit = $2;
- if ( !$sensors{'temp1'} || ( defined $temp_working && $temp_working > 0 ) ) {
+ if ( !$sensors{'temp1'} ||
+ ( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'temp1'} ) ) {
$sensors{'temp1'} = $temp_working;
}
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@@ -12811,7 +13143,8 @@ sub sensors_data {
elsif ($_ =~ /^temp2:([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $1;
$working_unit = $2;
- if ( !$sensors{'temp2'} || ( defined $temp_working && $temp_working > 0 ) ) {
+ if ( !$sensors{'temp2'} ||
+ ( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'temp2'} ) ) {
$sensors{'temp2'} = $temp_working;
}
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@@ -12820,7 +13153,8 @@ sub sensors_data {
elsif ($_ =~ /^temp3:([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $1;
$working_unit = $2;
- if ( !$sensors{'temp3'} || ( defined $temp_working && $temp_working > 0 ) ) {
+ if ( !$sensors{'temp3'} ||
+ ( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'temp3'} ) ) {
$sensors{'temp3'} = $temp_working;
}
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@@ -12830,7 +13164,8 @@ sub sensors_data {
elsif ($_ =~ /^(core0|core 0|Physical id 0)(.*):([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $3;
$working_unit = $4;
- if ( !$sensors{'core-0-temp'} || ( defined $temp_working && $temp_working > 0 ) ) {
+ if ( !$sensors{'core-0-temp'} ||
+ ( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'core-0-temp'} ) ) {
$sensors{'core-0-temp'} = $temp_working;
}
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@@ -13487,9 +13822,10 @@ sub unmounted_data {
# lvm might have dm-1 type syntax
# need to exclude loop type file systems, squashfs for example
# NOTE: nvme needs special treatment because the main device is: nvme0n1
- if ( $working[-1] !~ /^nvme[0-9]+n[0-9]+$/ &&
- $working[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && $working[2] != 1 &&
- $working[-1] !~ /loop/ && !(grep {$working[-1] =~ /$_/} @mounted)){
+ # note: $working[2] != 1 is wrong, it's not related
+ if ( $working[-1] !~ /^(nvme[0-9]+n|mmcblk)[0-9]+$/ &&
+ $working[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && $working[-1] !~ /loop/ &&
+ !(grep {$working[-1] =~ /$_/} @mounted)){
%part = PartitionData::check_lsblk($working[-1],0) if (@lsblk && $working[-1]);
if (%part){
$fs = $part{'fs'};
@@ -13846,16 +14182,16 @@ sub elevation_output {
$feet = sprintf("%.0f", 3.28 * $meters) if defined $meters && !$feet;
$meters = sprintf("%.1f", $feet / 3.28 ) if defined $feet && !$meters;
$meters = sprintf("%.0f", $meters) if $meters;
- if ( defined $meters && $weather_unit eq 'cf' ){
+ if ( defined $meters && $weather_unit eq 'mi' ){
$result = "$meters $m_unit ($feet $i_unit)";
}
- elsif (defined $meters && $weather_unit eq 'fc' ){
+ elsif (defined $meters && $weather_unit eq 'im' ){
$result = "$feet $i_unit ($meters $m_unit)";
}
- elsif (defined $meters && $weather_unit eq 'c' ){
+ elsif (defined $meters && $weather_unit eq 'm' ){
$result = "$meters $m_unit";
}
- elsif (defined $feet && $weather_unit eq 'f' ){
+ elsif (defined $feet && $weather_unit eq 'i' ){
$result = "$feet $i_unit";
}
else {
@@ -13868,16 +14204,16 @@ sub unit_output {
eval $start if $b_log;
my ($primary,$metric,$m_unit,$imperial,$i_unit) = @_;
my $result = '';
- if ($metric && $imperial && $weather_unit eq 'cf' ){
+ if ($metric && $imperial && $weather_unit eq 'mi' ){
$result = "$metric $m_unit ($imperial $i_unit)";
}
- elsif ($metric && $imperial && $weather_unit eq 'fc' ){
+ elsif ($metric && $imperial && $weather_unit eq 'im' ){
$result = "$imperial $i_unit ($metric $m_unit)";
}
- elsif ($metric && $weather_unit eq 'c' ){
+ elsif ($metric && $weather_unit eq 'm' ){
$result = "$metric $m_unit";
}
- elsif ($imperial && $weather_unit eq 'f' ){
+ elsif ($imperial && $weather_unit eq 'i' ){
$result = "$imperial $i_unit";
}
elsif ($primary){
@@ -13897,10 +14233,10 @@ sub wind_output {
$gust_mph = undef if $gust_mph && $mph && $mph eq $gust_mph;
$gust_ms = undef if $gust_ms && $ms && $ms eq $gust_ms;
# calculate and round, order matters so that rounding only happens after math done
- $ms = sprintf("%.1f", $ms ) if $ms; # very low mph speeds yield 0, which is wrong
+ $ms = 0.44704 * $mph if $mph && !$ms;
$mph = $ms * 2.23694 if $ms && !$mph;
$kmh = sprintf("%.0f", 18 * $ms / 5) if $ms;
- $ms = sprintf("%.0f", $ms ) if $ms;
+ $ms = sprintf("%.1f", $ms ) if $ms; # very low mph speeds yield 0, which is wrong
$mph = sprintf("%.0f", $mph) if $mph;
$gust_ms = 0.44704 * $gust_mph if $gust_mph && !$gust_ms;
$gust_kmh = 18 * $gust_ms / 5 if $gust_ms;
@@ -13912,29 +14248,29 @@ sub wind_output {
$result = $primary;
}
elsif ($mph && $direction ){
- if ( $weather_unit eq 'cf' ){
+ if ( $weather_unit eq 'mi' ){
$result = "from $direction at $ms $m_unit ($kmh $km_unit, $mph $i_unit)";
}
- elsif ( $weather_unit eq 'fc' ){
+ elsif ( $weather_unit eq 'im' ){
$result = "from $direction at $mph $i_unit ($ms $m_unit, $kmh $km_unit)";
}
- elsif ( $weather_unit eq 'c' ){
+ elsif ( $weather_unit eq 'm' ){
$result = "from $direction at $ms $m_unit ($kmh $km_unit)";
}
- elsif ( $weather_unit eq 'f' ){
+ elsif ( $weather_unit eq 'i' ){
$result = "from $direction at $mph $i_unit";
}
if ($gust_mph){
- if ( $weather_unit eq 'cf' ){
+ if ( $weather_unit eq 'mi' ){
$result .= ". Gusting to $ms $m_unit ($kmh $km_unit, $mph $i_unit)";
}
- elsif ( $weather_unit eq 'fc' ){
+ elsif ( $weather_unit eq 'im' ){
$result .= ". Gusting to $mph $i_unit ($ms $m_unit, $kmh $km_unit)";
}
- elsif ( $weather_unit eq 'c' ){
+ elsif ( $weather_unit eq 'm' ){
$result .= ". Gusting to $ms $m_unit ($kmh $km_unit)";
}
- elsif ( $weather_unit eq 'f' ){
+ elsif ( $weather_unit eq 'i' ){
$result .= ". Gusting to $mph $i_unit";
}
}
@@ -14809,28 +15145,38 @@ sub set_xprop {
sub get_display_manager {
eval $start if $b_log;
- my (@data,@found,$temp,$working);
+ my (@data,@found,$temp,$working,$b_run,$b_vrun,$b_vrunrc);
# ldm - LTSP display manager. Note that sddm does not appear to have a .pid
# extension in Arch note: to avoid positives with directories, test for -f
# explicitly, not -e
my @dms = qw(entranced.pid gdm.pid gdm3.pid kdm.pid ldm.pid
- lightdm.pid lxdm.pid mdm.pid nodm.pid sddm.pid sddm slim.lock
- tint2.pid wdm.pid xdm.pid xenodm.pid);
+ lightdm.pid lxdm.pid mdm.pid nodm.pid pcdm.pid
+ sddm.pid slim.lock tint2.pid wdm.pid xdm.pid xenodm.pid);
# this is the only one I know of so far that has --version
# lightdm outputs to stderr, so it has to be redirected
my @dms_version = qw(lightdm);
+ $b_run = 1 if -d "/run";
+ # in most linux, /var/run is a sym link to /run, so no need to check it twice
+ if ( -d "/var/run" ){
+ my $rdlink = readlink('/var/run');
+ $b_vrun = 1 if $rdlink && $rdlink ne '/run';
+ $b_vrunrc = 1 if -d "/var/run/rc.d";
+ }
foreach my $id (@dms){
- # note: ${dm_id%.*}/$dm_id will create a dir name out of the dm id, then
+ # note: $working will create a dir name out of the dm $id, then
# test if pid is in that note: sddm, in an effort to be unique and special,
# do not use a pid/lock file, but rather a random string inside a directory
# called /run/sddm/ so assuming the existence of the pid inside a directory named
# from the dm. Hopefully this change will not have negative results.
$working = $id;
$working =~ s/\.\S+$//;
- # note: there's always been an issue with duplicated dm's in inxi, this should now correct it
- if ( ( -f "/run/$id" || -d "/run/$working" || -f "/var/run/$id" ) && ! grep {/$working/} @found ){
- if ($extra > 2 && awk( \@dms_version, $working) ){
- @data = main::grabber("$working --version 2>&1");
+ # note: there were issues with duplicated dm's in inxi, checking @found corrects it
+ if ( ( ( $b_run && ( -f "/run/$id" || -d "/run/$working" ) ) ||
+ ( $b_vrun && ( -f "/var/run/$id" || -d "/var/run/$working" ) ) ||
+ ( $b_vrunrc && ( -f "/var/run/rc.d/$working" || -d "/var/run/rc.d/$id" ) ) ) &&
+ ! grep {/$working/} @found ){
+ if ($extra > 2 && awk( \@dms_version, $working) && (my $path = main::check_program($working)) ){
+ @data = main::grabber("$path --version 2>&1");
$temp = awk(\@data,'\S',2,'\s+');
$working .= ' ' . $temp if $temp;
}
@@ -14890,7 +15236,7 @@ sub get_bsd_os {
sub get_linux_distro {
eval $start if $b_log;
my ($distro_file) = ('');
- my ($b_osr,@working);
+ my ($b_antergos,$b_osr,@working);
my @derived = qw(antix-version aptosid-version kanotix-version knoppix-version
mandrake-release manjaro-release mx-version pardus-release porteus-version sabayon-release
siduction-version sidux-version slitaz-release solusos-release turbolinux-release
@@ -14908,18 +15254,29 @@ sub get_linux_distro {
# uses this method
my @distro_files = glob('/etc/*[-_]{[rR]elease,[vV]ersion}*');
my $lsb_release = '/etc/lsb-release';
- my $issue = '/etc/issue';
+ my ($etc_issue,$issue) = ('','/etc/issue');
my $os_release = '/etc/os-release';
- my $b_os_release = ( -f $os_release ) ? 1 : 0;
- my $b_lsb = ( -f $lsb_release ) ? 1 : 0;
+ my $b_issue = 1 if -f $issue;
+ my $b_os_release = 1 if -f $os_release;
+ my $b_lsb = 1 if -f $lsb_release;
+ # note: OpenSuse Tumbleweed 2018-05 has made /etc/issue created by sym link to /run/issue
+ # and then made that resulting file 700 permissions, which is obviously a mistake
+ $etc_issue = (main::reader($issue))[0] if $b_issue && -r $issue;
+ # debian issue can end with weird escapes like \n \l
+ # antergos: Antergos Linux \r (\l)
+ if ($etc_issue){
+ $etc_issue = main::clean_characters($etc_issue);
+ $b_antergos = 1 if $etc_issue =~ /antergos/i;
+ }
main::log_data('dump','@distro_files',\@distro_files) if $b_log;
if ( scalar @distro_files == 1 ){
$distro_file = $distro_files[0];
}
elsif (scalar @distro_files > 1) {
- # special case, to force manjaro which also has arch-release
+ # special case, to force manjaro/antergos which also have arch-release
# manjaro should use lsb, which has the full info, arch uses os release
- if (grep {/manjaro/} @distro_files){
+ # antergos should use /etc/issue
+ if ($b_antergos || grep {/manjaro/} @distro_files){
@distro_files = grep {!/arch-release/} @distro_files;
}
my $distro_files_s = join "|", @distro_files;
@@ -14973,29 +15330,26 @@ sub get_linux_distro {
# not use a variable type format
@working = main::reader($distro_file);
$distro = main::awk(\@working,'suse');
- $distro = main::clean_characters($distro) if $distro;
}
else {
$distro = (main::reader($distro_file))[0];
}
+ $distro = main::clean_characters($distro) if $distro;
}
# otherwise try the default debian/ubuntu /etc/issue file
- elsif (-f $issue){
- @working = main::reader($issue);
- my $b_mint = scalar (grep {/mint/i} @working);
+ elsif ($b_issue){
+ my $b_mint = ( $etc_issue && $etc_issue =~ /mint/i ) ? 1 : 0;
# os-release/lsb gives more manageable and accurate output than issue,
- # but mint should use issue for now.
- if ($b_os_release && !$b_mint){
+ # but mint should use issue for now. Antergos uses arch os-release, but issue shows them
+ if ($b_os_release && !$b_mint && !$b_antergos){
$distro = get_os_release();
$b_osr = 1;
}
- elsif ($b_lsb && !$b_mint){
+ elsif ($b_lsb && !$b_mint && !$b_antergos){
$distro = get_lsb_release();
}
- else {
- # debian issue can end with weird escapes like \n \l
- @working = main::reader($issue);
- $distro = (map {s/\\[a-z]|,|\*|\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @working)[0] if @working;
+ elsif ($etc_issue) {
+ $distro = $etc_issue;
# this handles an arch bug where /etc/arch-release is empty and /etc/issue
# is corrupted only older arch installs that have not been updated should
# have this fallback required, new ones use os-release
@@ -15006,8 +15360,8 @@ sub get_linux_distro {
}
# a final check. If a long value, before assigning the debugger output, if os-release
# exists then let's use that if it wasn't tried already. Maybe that will be better.
- # not handling the corrupt data, maybe later if needed
- if ($distro && length($distro) > 50 ){
+ # not handling the corrupt data, maybe later if needed. 10 + distro: (8) + string
+ if ($distro && length($distro) > 60 ){
if (!$b_osr && $b_os_release){
$distro = get_os_release();
}
@@ -15029,7 +15383,8 @@ sub get_linux_distro {
# the file name itself to set the distro value. Why say unknown if we have
# a pretty good idea, after all?
if ($distro_file){
- $distro_file =~ s/[-_]|release|version//g;
+ $distro_file =~ s/\/etc\/|[-_]|release|version//g;
+ $distro = $distro_file;
}
}
## finally, if all else has failed, give up
@@ -15037,6 +15392,7 @@ sub get_linux_distro {
eval $end if $b_log;
return $distro;
}
+
sub get_lsb_release {
eval $start if $b_log;
my ($distro,$id,$release,$codename,$description) = ('','','','','');
@@ -15083,8 +15439,8 @@ sub get_lsb_release {
}
sub get_os_release {
eval $start if $b_log;
- my ($pretty_name,$name,$version_name,$version_id,
- $distro_name,$distro) = ('','','','','','');
+ my ($pretty_name,$lc_name,$name,$version_name,$version_id,
+ $distro_name,$distro) = ('','','','','','','');
my @content = main::reader('/etc/os-release');
main::log_data('dump','@content',\@content) if $b_log;
@content = map {s/\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @content if @content;
@@ -15097,6 +15453,7 @@ sub get_os_release {
}
if ($working[0] eq 'NAME' && $working[1]){
$name = $working[1];
+ $lc_name = lc($name);
}
if ($working[0] eq 'VERSION' && $working[1]){
$version_name = $working[1];
@@ -15106,18 +15463,19 @@ sub get_os_release {
}
}
# NOTE: tumbleweed has pretty name but pretty name does not have version id
- if ($pretty_name && $pretty_name !~ /tumbleweed/i){
+ # arco shows only the release name, like kirk, in pretty name
+ if ($pretty_name && ($pretty_name !~ /tumbleweed/i && $lc_name ne 'arcolinux') ){
$distro = $pretty_name;
}
elsif ($name){
$distro = $name;
+ $distro = 'Arco Linux' if $lc_name eq 'arcolinux';
if ($version_name){
$distro .= ' ' . $version_name;
}
elsif ($version_id){
$distro .= ' ' . $version_id;
}
-
}
eval $end if $b_log;
return $distro;
@@ -15706,7 +16064,7 @@ sub get_uptime {
$uptime = trimmer($uptime);
#$uptime = '05:36:47 up 3 min, 4 users, load average: 1,88, 0,98, 0,62';
if ($uptime &&
- $uptime =~ /[\S]+\s+up\s+(([0-9]+)\s+day[s]?,\s+)?(([0-9]{1,2}):([0-9]{1,2})|([0-9]+)\smin),\s+[0-9]+\s+user/){
+ $uptime =~ /[\S]+\s+up\s+(([0-9]+)\s+day[s]?,\s+)?(([0-9]{1,2}):([0-9]{1,2})|([0-9]+)\smin[s]?),\s+[0-9]+\s+user/){
$days = $2 . 'd' if $2;
$days .= ' ' if ($days && ($4 || $6));
if ($4 && $5){
@@ -16136,6 +16494,8 @@ sub set_lspci_data {
my $path = check_program('lspci');
$content = qx($path -nnv 2>/dev/null) if $path;
@pcis = split /\n/, $content if $content;
+ #my $file = "$ENV{HOME}/bin/scripts/inxi/data/lspci/racermach-1-knnv.txt";
+ #@pcis = reader($file);
#print scalar @pcis;
@pcis = map {$_ =~ s/^\s+//; $_} @pcis if @pcis;
foreach (@pcis){