diff --git a/inxi b/inxi index 31ed74f..d88963d 100755 --- a/inxi +++ b/inxi @@ -4,7 +4,7 @@ ## Additional features (C) Scott Rogers - kde, cpu info ## Further fixes (listed as known): Horst Tritremmel ## Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch -## Jarett.Stevens - dmidecode -M patch for older systems with the /sys +## Jarett.Stevens - dmidecode -M patch for older systems without /sys machine ## ## License: GNU GPL v3 or greater ## @@ -13,6 +13,8 @@ ## ## If you don't understand what Free Software is, please read (or reread) ## this page: http://www.gnu.org/philosophy/free-sw.html +## +## DEVS: NOTE: geany/scite folding is picky. Leave 1 space after # or it breaks! use strict; use warnings; @@ -20,51 +22,65 @@ use warnings; use 5.008; ## Perl 7 things for testing: depend on Perl 5.032 -#use 5.032; +# use 5.032; # use compat::perl5; # act like Perl 5's defaults -#no feature qw(indirect); -#no multidimensional; -#no bareword::filehandles; +# no feature qw(indirect); +# no multidimensional; +# no bareword::filehandles; use Cwd qw(abs_path); # #abs_path realpath getcwd use Data::Dumper qw(Dumper); # print_r # NOTE: load in SystemDebugger unless encounter issues with require/import -#use File::Find; +# use File::Find; use File::stat; # needed for Xorg.0.log file mtime comparisons use Getopt::Long qw(GetOptions); # Note: default auto_abbrev is enabled Getopt::Long::Configure ('bundling', 'no_ignore_case', 'no_getopt_compat', 'no_auto_abbrev','pass_through'); -use POSIX qw(uname strftime ttyname); +use POSIX qw(ceil uname strftime ttyname); # use Benchmark qw(:all); # use Devel::Size qw(size total_size); # use feature qw(say state); # 5.10 or newer Perl +### INITIALIZE VARIABLES ### + ## INXI INFO ## my $self_name='inxi'; -my $self_version='3.3.03'; -my $self_date='2021-03-17'; +my $self_version='3.3.04'; +my $self_date='2021-04-16'; my $self_patch='00'; ## END INXI INFO ## -### INITIALIZE VARIABLES ### +my ($b_pledge,@pledges); +if (eval {require OpenBSD::Pledge}){ + OpenBSD::Pledge->import(); + $b_pledge = 1; + # cpath/wpath: dir/files .inxi, --debug > 9, -c 9x, -w/W; + # dns/inet: ftp upload --debug > 20; exec/proc/rpath: critical; + # prot_exec: Perl import; getpw: perl getpwuid() -c 9x, Net::FTP --debug > 20; + # stdio: default; error: debugging pledge/perl + # tested. not required: mcast pf ps recvfd sendfd tmppath tty unix vminfo; + # Pledge removal: OptionsHandler::post_process() [dns,inet,cpath,getpw,wpath]; + # SelectColors::set_selection() [getpw] + @pledges = qw(cpath dns exec getpw inet proc prot_exec rpath wpath); + pledge(@pledges); +} + +## Self data +my ($self_path,$user_config_dir,$user_config_file,$user_data_dir); ## Hashes -my (%alerts,%build_prop,%client,%colors,%dl,%files,%gpart, +my (%alerts,%build_prop,%client,%colors,%disks_bsd,%dboot,%devices,%dl, %dmmapper,%force,%loaded,%mapper,%program_values,%rows,%sensors_raw, -%service_tool,%system_files); +%service_tool,%show,%sysctl,%system_files,%usb); ## System Arrays -my (@app,@dmesg_boot,@devices_audio,@devices_bluetooth,@devices_graphics, -@devices_network,@devices_hwraid,@devices_timer,@dmi,@gpudata,@ifs,@ifs_bsd, -@paths,@ps_aux,@ps_cmd,@ps_gui,@sensors_exclude,@sensors_use, -@sysctl,@sysctl_audio,@sysctl_battery,@sysctl_machine,@sysctl_sensors, -@uname,@usb,@usb_audio,@usb_bluetooth,@usb_graphics,@usb_network); +my (@app,@dmi,@gpudata,@ifs,@ifs_bsd,@paths,@ps_aux,@ps_cmd,@ps_gui, +@sensors_exclude,@sensors_use,@uname); -## Disk/Partition arrays -my (@dm_boot_disk,@dm_boot_optical,@glabel,@labels,@lsblk,@lvm, -@lvm_raid,@md_raid,@partitions,@proc_partitions,@raw_logical, -@sysctl_disks,@swaps,@uuids,@zfs_raid); +## Disk/Logical/Partition/RAID arrays +my (@glabel,@labels,@lsblk,@lvm,@lvm_raid,@md_raid,@partitions,@proc_partitions, +@raw_logical,@soft_raid,@swaps,@uuids,@zfs_raid); ## Debuggers my %debugger = ('level' => 0); @@ -87,16 +103,6 @@ if (eval {require Time::HiRes}){ my ($b_admin,$b_android,$b_arm,$b_busybox_ps,$b_display,$b_irc, $b_mips,$b_ppc,$b_root,$b_running_in_display,$b_sparc); -# initialize basic use features -my %use = ( -'sysctl_disk' => 1, # unused currently -'update' => 1, # switched off/on with maintainer config ALLOW_UPDATE -'weather' => 1, # switched off/on with maintainer config ALLOW_WEATHER -); - -## Self data -my ($self_path,$user_config_dir,$user_config_file,$user_data_dir); - ## System my ($bsd_type,$device_vm,$language,$os,$pci_tool,$wan_url) = ('','','','','',''); my ($bits_sys,$cpu_arch,$ppid); @@ -117,7 +123,8 @@ my $line3 = "----------------------------------------\n"; my ($output_file,$output_type) = ('','screen'); my $prefix = 0; # for the primiary row hash key prefix -# these will assign a separator to non irc states. Important! Using ':' can +## Initialize internal hashes +# these assign a separator to non irc states. Important! Using ':' can # trigger stupid emoticon. Note: SEP1/SEP2 from short form not used anymore. # behaviors in output on IRC, so do not use those. my %sep = ( @@ -126,7 +133,6 @@ my %sep = ( 's2-irc' => '', 's2-console' => ':', ); -my %show; #$show{'host'} = 1; my %size = ( 'console' => 115, @@ -141,6 +147,10 @@ my %size = ( 'term' => 80, 'term-lines' => 100, ); +my %use = ( +'update' => 1, # switched off/on with maintainer config ALLOW_UPDATE +'weather' => 1, # switched off/on with maintainer config ALLOW_WEATHER +); ######################################################################## #### STARTUP @@ -158,7 +168,7 @@ sub main { # $debugger{'level'} = 3; # 3 prints timers / 10 prints to log file # set_debugger(); # for debugging of konvi and other start client issues ## legacy method - #my $ob_start = StartClient->new(); + # my $ob_start = StartClient->new(); #$ob_start->get_client_data(); StartClient::set(); # print_line( Dumper \%client); @@ -168,7 +178,7 @@ sub main { set_colors(); set_sep(); # print download_file('stdout','https://') . "\n"; - generate_lines(); + OutputGenerator::generate(); eval $end if $b_log; cleanup(); # weechat's executor plugin forced me to do this, and rightfully so, @@ -185,13 +195,13 @@ sub initialize { set_path(); set_user_paths(); set_basics(); - system_files('set'); - get_configs(); + set_system_files(); + Configs::set(); # set_downloader(); set_display_width('live'); } -# CheckTools +## CheckTools { package CheckTools; my (%commands); @@ -209,8 +219,8 @@ sub set { } elsif ($program = main::check_program($test)) { # > 0 means error in shell - #my $cmd = "$program $commands{$test} >/dev/null"; - #print "$cmd\n"; + # my $cmd = "$program $commands{$test} >/dev/null"; + # print "$cmd\n"; $pci_tool = $test if $test =~ /pci/; if ($commands{$test}->[0] eq 'exec-sys'){ $action = 'permissions' if system("$program $commands{$test}->[2] >/dev/null 2>&1"); @@ -239,7 +249,7 @@ sub set { $alerts{$test}->{'message'} = main::row_defaults('tool-permissions',"$test"); } elsif ($action eq 'platform'){ - $alerts{$test}->{'message'} = main::row_defaults('tool-missing-os', ucfirst($os) . " $test"); + $alerts{$test}->{'message'} = main::row_defaults('tool-missing-os', $uname[0] . " $test"); } } print Data::Dumper::Dumper \%alerts if $dbg[25]; @@ -252,7 +262,11 @@ sub set_dmidecode { my $action = 'use'; if ($b_root) { foreach (@$data){ - if ($_ =~ /No SMBIOS/i){ + # don't need first line or scanning /dev/mem lines + if (/^(# dmi|Scanning)/){ + next; + } + elsif ($_ =~ /No SMBIOS/i){ $action = 'smbios'; last; } @@ -276,7 +290,7 @@ sub set_dmidecode { } if ($action ne 'use' && $action ne 'permissions'){ if ($action eq 'smbios'){ - $alerts{'dmidecode'}->{'message'} = rmain::ow_defaults('dmidecode-smbios'); + $alerts{'dmidecode'}->{'message'} = main::row_defaults('dmidecode-smbios'); } elsif ($action eq 'no-data'){ $alerts{'dmidecode'}->{'message'} = main::row_defaults('dmidecode-dev-mem'); @@ -294,7 +308,7 @@ sub set_commands { if ($use{'pci'} ){ $commands{'lspci'} = ['exec-sys','','-n']; } - if ($use{'lvm'}){ + if ($use{'logical'}){ $commands{'lvs'} = ['exec-sys','','']; } } @@ -308,6 +322,12 @@ sub set_commands { # note: there is a case of kernel.osrelease but it's a linux distro $commands{'sysctl'} = ['exec-sys','','kern.osrelease']; } + if ($use{'bsd-partition'}){ + $commands{'bioctl'} = ['missing','','']; + $commands{'disklabel'} = ['missing','','']; + $commands{'fdisk'} = ['missing','','']; + $commands{'gpart'} = ['missing','','']; + } } if ($use{'dmidecode'}){ $commands{'dmidecode'} = ['exec-string','','-t chassis -t baseboard -t processor','']; @@ -328,7 +348,6 @@ sub set_commands { if ($show{'sensor'}){ $commands{'sensors'} = ['missing','linux','','']; } - if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})){ $commands{'ip'} = ['missing','linux','','']; $commands{'ifconfig'} = ['missing','','','']; @@ -344,6 +363,9 @@ sub set_commands { if ($use{'smartctl'}){ $commands{'smartctl'} = ['missing','','','']; } + if ($show{'unmounted'}){ + $commands{'disklabel'} = ['missing','bsd','xx']; + } } sub set_forced_tools { if ($bt_tool){ @@ -379,8 +401,12 @@ sub set_fake_bsd_tools { 'message' => 'Required program lsusb not available', }; } + if ($fake{'disklabel'}){ + $alerts{'disklabel'}->{'action'} = 'use'; + } } } + # args: 1 - desktop/app command for --version; 2 - search string; # 3 - space print number; 4 - [optional] version arg: -v, version, etc # 5 - [optional] exit first find 0/1; 6 - [optional] 0/1 stderr output @@ -419,45 +445,47 @@ sub set_basics { # is the display width override. sub set_display_width { my ($width) = @_; - if ( $width eq 'live' ){ + if ($width eq 'live'){ ## sometimes tput will trigger an error (mageia) if irc client - if ( ! $b_irc ){ - if ( check_program('tput') ) { - # trips error if use qx()... - chomp($size{'term'}=qx{tput cols}); - chomp($size{'term-lines'}=qx{tput lines}); + if (!$b_irc){ + if (my $program = check_program('tput')) { + # Arch urxvt: 'tput: unknown terminal "rxvt-unicode-256color"' + # trips error if use qx(); in FreeBSD, if you use 2>/dev/null + # it makes default value 80x24, who knows why? + chomp($size{'term'} = qx{$program cols}); + chomp($size{'term-lines'} = qx{$program lines}); $size{'term-cols'} = $size{'term'}; } # print "tc: $size{'term'} cmc: $size{'console'}\n"; # double check, just in case it's missing functionality or whatever - if ( $size{'term'} == 0 || !is_int($size{'term'}) ){ + if (!is_int($size{'term'} || $size{'term'} == 0)){ $size{'term'}=80; # we'll be using this for terminal dimensions later so don't set default. # $size{'term-lines'}=100; } } # this lets you set different size for in or out of display server - if ( ! $b_running_in_display && $size{'no-display'} ){ - $size{'console'}=$size{'no-display'}; + if (!$b_running_in_display && $size{'no-display'}){ + $size{'console'} = $size{'no-display'}; } # term_cols is set in top globals, using tput cols # print "tc: $size{'term'} cmc: $size{'console'}\n"; - if ( $size{'term'} < $size{'console'} ){ - $size{'console'}=$size{'term'}; + if ($size{'term'} < $size{'console'}){ + $size{'console'} = $size{'term'}; } # adjust, some terminals will wrap if output cols == term cols - $size{'console'}=( $size{'console'} - 2 ); + $size{'console'} = ($size{'console'} - 2); # echo cmc: $size{'console'} # comes after source for user set stuff - if ( ! $b_irc ){ - $size{'max'}=$size{'console'}; + if (!$b_irc){ + $size{'max'} = $size{'console'}; } else { - $size{'max'}=$size{'irc'}; + $size{'max'} = $size{'irc'}; } } else { - $size{'max'}=$width; + $size{'max'} = $width; } # print "tc: $size{'term'} cmc: $size{'console'} cm: $size{'max'}\n"; } @@ -479,7 +507,7 @@ sub set_os { $bits_sys = 64; } $b_android = 1 if -e '/system/build.prop'; - if ( $os =~ /(aix|bsd|cosix|dragonfly|darwin|hp-?ux|indiana|irix|sunos|solaris|ultrix|unix)/ ){ + if ($os =~ /(aix|bsd|cosix|dragonfly|darwin|hp-?ux|indiana|irix|sunos|solaris|ultrix|unix)/){ if ($os =~ /openbsd/){ $os = 'openbsd'; } @@ -546,12 +574,34 @@ sub set_sudo { elsif (!$force{'no-sudo'} && ($path = check_program('sudo'))) { my @data = program_data('sudo'); $data[1] =~ s/^([0-9]+\.[0-9]+).*/$1/; - #print "sudo v: $data[1]\n"; + # print "sudo v: $data[1]\n"; $sudoas = "$path -n " if is_numeric($data[1]) && $data[1] >= 1.7; } } } +sub set_system_files { + my %files = ( + 'asound-cards' => '/proc/asound/cards', + 'asound-modules' => '/proc/asound/modules', + 'asound-version' => '/proc/asound/version', + 'dmesg-boot' => '/var/run/dmesg.boot', + 'proc-cmdline' => '/proc/cmdline', + 'proc-cpuinfo' => '/proc/cpuinfo', + 'proc-mdstat' => '/proc/mdstat', + 'proc-meminfo' => '/proc/meminfo', + 'proc-modules' => '/proc/modules', # not used + 'proc-mounts' => '/proc/mounts',# not used + 'proc-partitions' => '/proc/partitions', + 'proc-scsi' => '/proc/scsi/scsi', + 'proc-version' => '/proc/version', + # note: 'xorg-log' is set in set_xorg_log() only if -G is triggered + ); + foreach (keys %files){ + $system_files{$_} = (-e $files{$_}) ? $files{$_} : ''; + } +} + sub set_user_paths { my ( $b_conf, $b_data ); # this needs to be set here because various options call the parent @@ -560,85 +610,55 @@ sub set_user_paths { $self_path =~ s/[^\/]+$//; # print "0: $0 sp: $self_path\n"; - if ( defined $ENV{'XDG_CONFIG_HOME'} && $ENV{'XDG_CONFIG_HOME'} ){ + if (defined $ENV{'XDG_CONFIG_HOME'} && $ENV{'XDG_CONFIG_HOME'}){ $user_config_dir=$ENV{'XDG_CONFIG_HOME'}; $b_conf=1; } - elsif ( -d "$ENV{'HOME'}/.config" ){ + elsif (-d "$ENV{'HOME'}/.config"){ $user_config_dir="$ENV{'HOME'}/.config"; $b_conf=1; } else { $user_config_dir="$ENV{'HOME'}/.$self_name"; } - if ( defined $ENV{'XDG_DATA_HOME'} && $ENV{'XDG_DATA_HOME'} ){ + if (defined $ENV{'XDG_DATA_HOME'} && $ENV{'XDG_DATA_HOME'}){ $user_data_dir="$ENV{'XDG_DATA_HOME'}/$self_name"; $b_data=1; } - elsif ( -d "$ENV{'HOME'}/.local/share" ){ + elsif (-d "$ENV{'HOME'}/.local/share"){ $user_data_dir="$ENV{'HOME'}/.local/share/$self_name"; $b_data=1; } else { $user_data_dir="$ENV{'HOME'}/.$self_name"; } - # note, this used to be created/checked in specific instance, but we'll just do it - # universally so it's done at script start. - if ( ! -d $user_data_dir ){ + # note, this used to be created/checked in specific instance, but we'll just + # do it universally so it's done at script start. + if (! -d $user_data_dir){ mkdir $user_data_dir; # system "echo", "Made: $user_data_dir"; } - if ( $b_conf && -f "$ENV{'HOME'}/.$self_name/$self_name.conf" ){ - #system 'mv', "-f $ENV{'HOME'}/.$self_name/$self_name.conf", $user_config_dir; + if ($b_conf && -f "$ENV{'HOME'}/.$self_name/$self_name.conf"){ + # system 'mv', "-f $ENV{'HOME'}/.$self_name/$self_name.conf", $user_config_dir; # print "WOULD: Moved $self_name.conf from $ENV{'HOME'}/.$self_name to $user_config_dir\n"; } - if ( $b_data && -d "$ENV{'HOME'}/.$self_name" ){ - #system 'mv', '-f', "$ENV{'HOME'}/.$self_name/*", $user_data_dir; - #system 'rm', '-Rf', "$ENV{'HOME'}/.$self_name"; + if ($b_data && -d "$ENV{'HOME'}/.$self_name"){ + # system 'mv', '-f', "$ENV{'HOME'}/.$self_name/*", $user_data_dir; + # system 'rm', '-Rf', "$ENV{'HOME'}/.$self_name"; # print "WOULD: Moved data dir $ENV{'HOME'}/.$self_name to $user_data_dir\n"; } $log_file="$user_data_dir/$self_name.log"; - #system 'echo', "$ENV{'HOME'}/.$self_name/* $user_data_dir"; + # system 'echo', "$ENV{'HOME'}/.$self_name/* $user_data_dir"; # print "scd: $user_config_dir sdd: $user_data_dir \n"; } -# args: 1: set|hash key to return either null or path -sub system_files { - my ($file) = @_; - if ( $file eq 'set'){ - %files = ( - 'asound-cards' => '/proc/asound/cards', - 'asound-modules' => '/proc/asound/modules', - 'asound-version' => '/proc/asound/version', - 'cmdline' => '/proc/cmdline', - 'cpuinfo' => '/proc/cpuinfo', - 'dmesg-boot' => '/var/run/dmesg.boot', - 'lsb-release' => '/etc/lsb-release', - 'mdstat' => '/proc/mdstat', - 'meminfo' => '/proc/meminfo', - 'modules' => '/proc/modules', - 'mounts' => '/proc/mounts', - 'os-release' => '/etc/os-release', - 'partitions' => '/proc/partitions', - 'scsi' => '/proc/scsi/scsi', - 'version' => '/proc/version', - # note: 'xorg-log' is set only if -G is triggered - ); - foreach ( keys %files ){ - $system_files{$_} = ( -e $files{$_} ) ? $files{$_} : ''; - } - } - else { - return $system_files{$file}; - } -} sub set_xorg_log { eval $start if $b_log; my (@temp,@x_logs); my ($file_holder,$time_holder,$x_mtime) = ('',0,0); # NOTE: other variations may be /var/run/gdm3/... but not confirmed - # we are just going to get all the Xorg logs we can find, and not worry about - # which is 'right'. + # worry about we are just going to get all the Xorg logs we can find, + # and not which is 'right'. @temp = globber('/var/log/Xorg.*.log'); push(@x_logs, @temp) if @temp; @temp = globber('/var/lib/gdm/.local/share/xorg/Xorg.*.log'); @@ -654,7 +674,7 @@ sub set_xorg_log { foreach (@x_logs){ if (-r $_){ my $src_info = File::stat::stat("$_"); - #print "$_\n"; + # print "$_\n"; if ($src_info){ $x_mtime = $src_info->mtime; # print $_ . ": $x_time" . "\n"; @@ -797,9 +817,9 @@ sub set_colors { if (exists $colors{'c1'}){ return 1; } - # This let's user pick their color scheme. For IRC, only shows the color schemes, - # no interactive. The override value only will be placed in user config files. - # /etc/inxi.conf can also override + # This let's user pick their color scheme. For IRC, only shows the color + # schemes, no interactive. The override value only will be placed in user + # config files. /etc/inxi.conf can also override if (exists $colors{'selector'}){ my $ob_selector = SelectColors->new($colors{'selector'}); $ob_selector->select_schema(); @@ -843,17 +863,10 @@ sub set_colors { ## SelectColors { package SelectColors; - -# use warnings; -# use strict; -# use diagnostics; -# use 5.008; - my (@data,%configs,%status); my ($type,$w_fh); my $safe_color_count = 12; # null/normal + default color group my $count = 0; - # args: 1 - type sub new { my $class = shift; @@ -869,7 +882,7 @@ sub select_schema { start_selector(); create_color_selections(); if (! $b_irc ){ - main::check_config_file(); + Configs::check_file(); get_selection(); } else { @@ -945,8 +958,8 @@ sub start_selector { } sub create_color_selections { my $spacer = '^^'; # printer removes double spaces, but replaces ^ with ' ' - $count = ( main::get_color_scheme('count') - 1 ); - for my $i (0 .. $count){ + $count = (main::get_color_scheme('count') - 1); + foreach my $i (0 .. $count){ if ($i > 9){ $spacer = '^'; } @@ -1003,11 +1016,17 @@ sub get_selection { else { process_selection($response); } + if ($b_pledge){ + @pledges = grep {$_ ne 'getpw'} @pledges; + OpenBSD::Pledge::pledge(@pledges); + } } sub process_selection { my $response = shift; if ($response == ($count + 3) ){ - @data = ([0, '', '', "Ok, exiting $self_name now. You can set the colors later."],); + @data = ( + [0, '', '', "Ok, exiting $self_name now. You can set the colors later."], + ); main::print_basic(\@data); exit 0; } @@ -1113,14 +1132,11 @@ sub print_irc_message { #### CONFIGS #### ------------------------------------------------------------------- -sub check_config_file { - $user_config_file = "$user_config_dir/$self_name.conf"; - if ( ! -f $user_config_file ){ - open( my $fh, '>', $user_config_file ) or error_handler('create', $user_config_file, $!); - } -} - -sub get_configs { +## Configs +# public: set() check_file() +{ +package Configs; +sub set { my ($configs) = @_; my ($key, $val,@config_files); if (!$configs){ @@ -1147,59 +1163,76 @@ sub get_configs { next unless length; ($key, $val) = split(/\s*=\s*/, $_, 2); next unless length($val); - get_config_item($key,$val); + process_item($key,$val); # print "f: $file key: $key val: $val\n"; } close $fh; } } - -# note: someone managed to make a config file with corrupted values, so check int -# explicitly, don't assume it was done correctly. +# note: someone managed to make a config file with corrupted values, so check +# int explicitly, don't assume it was done correctly. # args: 0: key; 1: value -sub get_config_item { +sub process_item { my ($key,$val) = @_; - if ($key eq 'ALLOW_UPDATE' || $key eq 'B_ALLOW_UPDATE') {$use{'update'} = $val if is_int($val)} - elsif ($key eq 'ALLOW_WEATHER' || $key eq 'B_ALLOW_WEATHER') {$use{'weather'} = $val if is_int($val)} - elsif ($key eq 'CPU_SLEEP') {$cpu_sleep = $val if is_numeric($val)} - elsif ($key eq 'DL_TIMEOUT') {$dl_timeout = $val if is_int($val)} + if ($key eq 'ALLOW_UPDATE' || $key eq 'B_ALLOW_UPDATE') { + $use{'update'} = $val if main::is_int($val)} + elsif ($key eq 'ALLOW_WEATHER' || $key eq 'B_ALLOW_WEATHER') { + $use{'weather'} = $val if main::is_int($val)} + elsif ($key eq 'CPU_SLEEP') { + $cpu_sleep = $val if main::is_numeric($val)} + elsif ($key eq 'DL_TIMEOUT') { + $dl_timeout = $val if main::is_int($val)} elsif ($key eq 'DOWNLOADER') { if ($val =~ /^(curl|fetch|ftp|perl|wget)$/){ # this dumps all the other data and resets %dl for only the # desired downloader. - $val = set_perl_downloader($val); + $val = main::set_perl_downloader($val); %dl = ('dl' => $val, $val => 1); }} - elsif ($key eq 'FILTER_STRING') {$filter_string = $val} - elsif ($key eq 'LANGUAGE') {$language = $val if $val =~ /^(en)$/} - elsif ($key eq 'LIMIT') {$limit = $val if is_int($val)} - elsif ($key eq 'OUTPUT_TYPE') {$output_type = $val if $val =~ /^(json|screen|xml)$/} - elsif ($key eq 'NO_DIG') {$force{'no-dig'} = $val if is_int($val)} - elsif ($key eq 'NO_DOAS') {$force{'no-doas'} = $val if is_int($val)} - elsif ($key eq 'NO_HTML_WAN') {$force{'no-html-wan'} = $val if is_int($val)} - elsif ($key eq 'NO_SUDO') {$force{'no-sudo'} = $val if is_int($val)} + elsif ($key eq 'FILTER_STRING') { + $filter_string = $val} + elsif ($key eq 'LANGUAGE') { + $language = $val if $val =~ /^(en)$/} + elsif ($key eq 'LIMIT') { + $limit = $val if main::is_int($val)} + elsif ($key eq 'OUTPUT_TYPE') { + $output_type = $val if $val =~ /^(json|screen|xml)$/} + elsif ($key eq 'NO_DIG') { + $force{'no-dig'} = $val if main::is_int($val)} + elsif ($key eq 'NO_DOAS') { + $force{'no-doas'} = $val if main::is_int($val)} + elsif ($key eq 'NO_HTML_WAN') { + $force{'no-html-wan'} = $val if main::is_int($val)} + elsif ($key eq 'NO_SUDO') { + $force{'no-sudo'} = $val if main::is_int($val)} elsif ($key eq 'PARTITION_SORT') { if ($val =~ /^(dev-base|fs|id|label|percent-used|size|uuid|used)$/){ $show{'partition-sort'} = $val; }} - elsif ($key eq 'PS_COUNT') {$ps_count = $val if is_int($val) } - elsif ($key eq 'SENSORS_CPU_NO') {$sensors_cpu_nu = $val if is_int($val)} - elsif ($key eq 'SENSORS_EXCLUDE') {@sensors_exclude = split(/\s*,\s*/, $val) if $val} - elsif ($key eq 'SENSORS_USE') {@sensors_use = split(/\s*,\s*/, $val) if $val} + elsif ($key eq 'PS_COUNT') { + $ps_count = $val if main::is_int($val) } + elsif ($key eq 'SENSORS_CPU_NO') { + $sensors_cpu_nu = $val if main::is_int($val)} + elsif ($key eq 'SENSORS_EXCLUDE') { + @sensors_exclude = split(/\s*,\s*/, $val) if $val} + elsif ($key eq 'SENSORS_USE') { + @sensors_use = split(/\s*,\s*/, $val) if $val} elsif ($key eq 'SHOW_HOST' || $key eq 'B_SHOW_HOST') { - if (is_int($val)){ + if (main::is_int($val)){ $show{'host'} = $val; $show{'no-host'} = 1 if !$show{'host'}; } } - elsif ($key eq 'USB_SYS') {$force{'usb-sys'} = $val if is_int($val)} + elsif ($key eq 'USB_SYS') { + $force{'usb-sys'} = $val if main::is_int($val)} elsif ($key eq 'WAN_IP_URL') { if ($val =~ /^(ht|f)tp[s]?:\//i){ $wan_url = $val; $force{'no-dig'} = 1; } } - elsif ($key eq 'WEATHER_SOURCE') {$weather_source = $val if is_int($val)} + elsif ($key eq 'WEATHER_SOURCE') { + $weather_source = $val if main::is_int($val)} elsif ($key eq 'WEATHER_UNIT') { $val = lc($val) if $val; if ($val && $val =~ /^(c|f|cf|fc|i|m|im|mi)$/){ @@ -1209,26 +1242,49 @@ sub get_config_item { } } # layout - elsif ($key eq 'CONSOLE_COLOR_SCHEME') {$colors{'console'} = $val if is_int($val)} - elsif ($key eq 'GLOBAL_COLOR_SCHEME') {$colors{'global'} = $val if is_int($val)} - elsif ($key eq 'IRC_COLOR_SCHEME') {$colors{'irc-gui'} = $val if is_int($val)} - elsif ($key eq 'IRC_CONS_COLOR_SCHEME') {$colors{'irc-console'} = $val if is_int($val)} - elsif ($key eq 'IRC_X_TERM_COLOR_SCHEME') {$colors{'irc-virt-term'} = $val if is_int($val)} - elsif ($key eq 'VIRT_TERM_COLOR_SCHEME') {$colors{'virt-term'} = $val if is_int($val)} + elsif ($key eq 'CONSOLE_COLOR_SCHEME') { + $colors{'console'} = $val if main::is_int($val)} + elsif ($key eq 'GLOBAL_COLOR_SCHEME') { + $colors{'global'} = $val if main::is_int($val)} + elsif ($key eq 'IRC_COLOR_SCHEME') { + $colors{'irc-gui'} = $val if main::is_int($val)} + elsif ($key eq 'IRC_CONS_COLOR_SCHEME') { + $colors{'irc-console'} = $val if main::is_int($val)} + elsif ($key eq 'IRC_X_TERM_COLOR_SCHEME') { + $colors{'irc-virt-term'} = $val if main::is_int($val)} + elsif ($key eq 'VIRT_TERM_COLOR_SCHEME') { + $colors{'virt-term'} = $val if main::is_int($val)} # note: not using the old short SEP1/SEP2 - elsif ($key eq 'SEP1_IRC') {$sep{'s1-irc'} = $val} - elsif ($key eq 'SEP1_CONSOLE') {$sep{'s1-console'} = $val} - elsif ($key eq 'SEP2_IRC') {$sep{'s2-irc'} = $val} - elsif ($key eq 'SEP2_CONSOLE') {$sep{'s2-console'} = $val} + elsif ($key eq 'SEP1_IRC') { + $sep{'s1-irc'} = $val} + elsif ($key eq 'SEP1_CONSOLE') { + $sep{'s1-console'} = $val} + elsif ($key eq 'SEP2_IRC') { + $sep{'s2-irc'} = $val} + elsif ($key eq 'SEP2_CONSOLE') { + $sep{'s2-console'} = $val} # size - elsif ($key eq 'COLS_MAX_CONSOLE') {$size{'console'} = $val if is_int($val)} - elsif ($key eq 'COLS_MAX_IRC') {$size{'irc'} = $val if is_int($val)} - elsif ($key eq 'COLS_MAX_NO_DISPLAY') {$size{'no-display'} = $val if is_int($val)} - elsif ($key eq 'INDENT') {$size{'indent'} = $val if is_int($val)} - elsif ($key eq 'WRAP_MAX' || $key eq 'INDENT_MIN') {$size{'wrap-max'} = $val if is_int($val)} + elsif ($key eq 'COLS_MAX_CONSOLE') { + $size{'console'} = $val if main::is_int($val)} + elsif ($key eq 'COLS_MAX_IRC') { + $size{'irc'} = $val if main::is_int($val)} + elsif ($key eq 'COLS_MAX_NO_DISPLAY') { + $size{'no-display'} = $val if main::is_int($val)} + elsif ($key eq 'INDENT') { + $size{'indent'} = $val if main::is_int($val)} + elsif ($key eq 'WRAP_MAX' || $key eq 'INDENT_MIN') { + $size{'wrap-max'} = $val if main::is_int($val)} # print "mc: key: $key val: $val\n"; # print Dumper (keys %size) . "\n"; } +sub check_file { + $user_config_file = "$user_config_dir/$self_name.conf"; + if ( ! -f $user_config_file ){ + open( my $fh, '>', $user_config_file ) or + main::error_handler('create', $user_config_file, $!); + } +} +} #### ------------------------------------------------------------------- #### DEBUGGERS @@ -1246,7 +1302,7 @@ sub begin_logging { $start='main::log_data("fs", (caller(1))[3], \@_);'; #$t3 = tv_interval ($t0, [gettimeofday]); $t3 = eval 'Time::HiRes::tv_interval (\@t0, [Time::HiRes::gettimeofday()]);' if $b_hires; - #print Dumper $@; + # print Dumper $@; my $now = strftime "%Y-%m-%d %H:%M:%S", localtime; return if $debugger{'timers'}; # do the rotation if logfile exists @@ -1298,7 +1354,7 @@ sub log_data { # $t1 = [gettimeofday]; #$t3 = tv_interval ($t0, [gettimeofday]); $t3 = eval 'Time::HiRes::tv_interval(\@t0, [Time::HiRes::gettimeofday()])' if $b_hires; - #print Dumper $@; + # print Dumper $@; $data = "Start: Function: $two$args\n${spacer}Elapsed: $t3\n"; $spacer=''; $timer = $data if $debugger{'timers'}; @@ -1307,14 +1363,14 @@ sub log_data { # print 'timer:', Time::HiRes::tv_interval(\@t0, [Time::HiRes::gettimeofday()]),"\n"; #$t3 = tv_interval ($t0, [gettimeofday]); eval '$t3 = Time::HiRes::tv_interval(\@t0, [Time::HiRes::gettimeofday()])' if $b_hires; - #print Dumper $t3; + # print Dumper $t3; $data = "${spacer}Elapsed: $t3\nEnd: Function: $two\n"; $spacer=''; $timer = $data if $debugger{'timers'}; } elsif ( $one eq 'cat') { if ( $b_log_full ){ - for my $file ($two){ + foreach my $file ($two){ my $contents = do { local( @ARGV, $/ ) = $file; <> }; # or: qx(cat $file) $data = "$data${line3}Full file data: $file\n\n$contents\n$line3\n"; } @@ -1355,7 +1411,7 @@ sub log_data { if ($debugger{'timers'}){ print $timer if $timer; } - #print "d: $data"; + # print "d: $data"; elsif ($data){ print $fh_l "$spacer$data"; } @@ -1394,6 +1450,7 @@ sub set_debugger { } } } + ## SystemDebugger { package SystemDebugger; @@ -1417,9 +1474,9 @@ sub run_debugger { print "Starting $self_name debugging data collector...\n"; print "Loading required debugger Perl File:: modules... \n"; # Fedora/Redhat doesn't include File::Find File::Copy in - # core modules!! why? Or rather, they deliberately removed them!! + # core modules. why? Or rather, they deliberately removed them. if (main::check_perl_module('File::Find')){ - File::Find->import('find'); + File::Find->import; } else { main::error_handler('required-module', 'File', 'File::Find'); @@ -1436,6 +1493,14 @@ sub run_debugger { else { main::error_handler('required-module', 'File', 'File::Spec::Functions'); } + if ($debugger{'level'} > 20){ + if (main::check_perl_module('Net::FTP')){ + Net::FTP->import; + } + else { + main::error_handler('required-module', 'Net', 'Net::FTP'); + } + } create_debug_directory(); print "Note: for dmidecode, smartctl, lvm data you must be root.\n" if !$b_root; print $line3; @@ -1492,18 +1557,18 @@ sub create_debug_directory { if (length($hour) == 1) {$hour = "0$hour";} if (length($mon) == 1) {$mon = "0$mon";} if (length($mday) == 1) {$mday = "0$mday";} - my $today = "$year-$mon-${mday}_$hour$min$sec"; # my $date = strftime "-%Y-%m-%d_", localtime; if ($b_root){ $root_string = '-root'; } $bsd_string = "-BSD-$bsd_type" if $bsd_type; + my $id = ($debugger{'id'} ) ? '-' . $debugger{'id'}: ''; if ($b_arm ){$alt_string = '-ARM'} elsif ($b_mips) {$alt_string = '-MIPS'} elsif ($b_ppc) {$alt_string = '-PPC'} elsif ($b_sparc) {$alt_string = '-SPARC'} - $debug_dir = "$self_name$alt_string$bsd_string-$host-$today$root_string-$self_version-$self_patch"; + $debug_dir = "$self_name$alt_string$bsd_string-$host$id-$today$root_string-$self_version-$self_patch"; $debug_gz = "$debug_dir.tar.gz"; $data_dir = "$user_data_dir/$debug_dir"; if ( -d $data_dir ){ @@ -1564,13 +1629,16 @@ sub bluetooth_data { ['hciconfig','-a'], #['hcidump',''], # hangs sometimes ['hcitool','dev'], + ['rfkill','--output-all'], ); # these hang if bluetoothd not enabled if (@ps_cmd && (grep {m|/bluetoothd|} @ps_cmd)){ - push(@cmds,['bt-adapter','--list']); - push(@cmds,['bt-adapter','--info']); - push(@cmds,['bluetoothctl','-- list']); - push(@cmds,['bluetoothctl','-- show']); + push(@cmds, + ['bt-adapter','--list'], + ['bt-adapter','--info'], + ['bluetoothctl','-- list'], + ['bluetoothctl','-- show'] + ); } run_commands(\@cmds,'bluetooth'); } @@ -1700,9 +1768,15 @@ sub disk_data { @cmds = ( ['atacontrol', 'list'], ['camcontrol', 'devlist'], + ['camcontrol', 'devlist -v'], + ['geom', 'part list'], ['glabel', 'status'], + ['gpart', 'list'], # gpart in linux/bsd but do it here again + ['gpart', 'show'], + ['gpart', 'status'], ['swapctl', '-l -k'], ['swapctl', '-l -k'], + ['vmstat', ''], ['vmstat', '-H'], ); run_commands(\@cmds,'disk-bsd'); @@ -1885,11 +1959,15 @@ sub system_data { ['sysctl', '-b kern.geom.confxml'], ['usbdevs','-v'], # freebsd + ['ofwdump','-a'], # arm / soc + ['ofwdump','-ar'], # arm / soc ['pciconf','-l -cv'], ['pciconf','-vl'], ['pciconf','-l'], + ['usbconfig','dump_device_desc'], ['usbconfig','list'], # needs root, sigh... why? # openbsd + ['ofctl',''], # arm / soc, need to see data sample of this ['pcidump',''], ['pcidump','-v'], # netbsd @@ -1961,7 +2039,7 @@ sub system_data { sub system_files { print "Collecting system files data...\n"; my (%data,@files,@files2); - @files = RepoData::get($data_dir); + @files = RepoItem::get($data_dir); copy_files(\@files, 'repo'); # chdir "/etc"; @files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); @@ -2116,7 +2194,7 @@ sub build_tree { foreach (@files){ next if /^\./; $cmd = "tree -a -L 10 $dirname/$_ > $data_dir/sys-data-tree-$_-10.txt"; - #print "$cmd\n"; + # print "$cmd\n"; system($cmd); } } @@ -2251,22 +2329,40 @@ sub process_sys_traverse { } sub wanted { + # note: we want these directories pruned before the -d test so find + # doesn't try to read files inside of the directories + if ($parse_src eq 'proc'){ + if ($File::Find::name =~ m!^/proc/[0-9]+! || + $File::Find::name =~ m!^/proc/(irq|spl|sys)! || + # these choke on sudo/root: kmsg kcore kpage and we don't want keys or kallsyms + $File::Find::name =~ m!^/proc/k! || + $File::Find::name =~ m!^/proc/bus/pci! || + $File::Find::name =~ m!^/proc/(irq|spl|sys)!){ + # perl compiler complains on start if defined test not used + $File::Find::prune = 1 if defined $File::Find::prune; + return; + } + } + elsif ($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 + if ($File::Find::name =~ m!/(\.[a-z]|kernel/|trace/|parameters|debug)!){ + $File::Find::prune = 1 if defined $File::Find::prune; + } + } return if -d; # not directory return unless -e; # Must exist return unless -f; # Must be file 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\/ # picdec\/|, wait_for_fb_sleep/wake is an odroid thing caused hang # wakeup_count also fails for android, but works fine on regular systems - return if $b_arm && $File::Find::name =~ /^\/sys\/power\/(wait_for_fb_|wakeup_count$)/; - return if $File::Find::name =~ /\/(\.[a-z]|kernel\/|trace\/|parameters\/|debug\/)/; + return if $b_arm && $File::Find::name =~ m!^/sys/power/(wait_for_fb_|wakeup_count$)!; # pp_num_states: amdgpu driver bug; android: wakeup_count - return if $File::Find::name =~ /\/pp_num_states$/; + return if $File::Find::name =~ m!/pp_num_states$!; # 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 @@ -2276,12 +2372,7 @@ sub wanted { # 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|spl|sys)\//; - # these choke on sudo/root: kmsg kcore kpage and we don't want keys or kallsyms - return if $File::Find::name =~ /^\/proc\/k/; - return if $File::Find::name =~ /(\/mb_groups|debug)$/; + return if $File::Find::name =~ m!(/mb_groups|debug)$!; } # print $File::Find::name . "\n"; push(@content, $File::Find::name); @@ -2291,8 +2382,6 @@ sub wanted { # args: 2 - optional: alternate ftp upload url # NOTE: must be in format: ftp.site.com/incoming sub upload_file { - require Net::FTP; - Net::FTP->import; my ($self, $ftp_url) = @_; my ($ftp, $domain, $host, $user, $pass, $dir, $error); $ftp_url ||= main::get_defaults('ftp-upload'); @@ -2334,6 +2423,7 @@ sub upload_file { } } } + # random tests for various issues sub user_debug_test_1 { # open(my $duped, '>&', STDOUT); @@ -2348,6 +2438,7 @@ sub user_debug_test_1 { # print(join(', ', PerlIO::get_layers(STDOUT)), "\n"); # close $duped; } + # see docs/optimization.txt sub ram_use { my ($name, $ref) = @_; @@ -2476,7 +2567,7 @@ sub set_downloader { $dl{'tiny'} = 0; } } - #print $dl{'tiny'} . "\n"; + # print $dl{'tiny'} . "\n"; if ($dl{'tiny'}){ $dl{'dl'} = 'tiny'; $dl{'file'} = ''; @@ -2671,7 +2762,7 @@ sub run { ['0', '', '', " "], ); push(@rows, @data); - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; main::print_basic(\@rows); exit 0; # shell true } @@ -2718,14 +2809,15 @@ 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 upower uptime usbconfig usbdevs); + @data = qw(camcontrol dig disklabel dmidecode doas fdisk file glabel gpart + ifconfig ipmi-sensors ipmitool pciconfig pcidump pcictl smartctl sudo + sysctl tree upower uptime usbconfig usbdevs); $info_os = 'info-bsd'; } else { - @data = qw(blockdev bt-adapter dig dmidecode fdisk file hciconfig hddtemp - ifconfig ip ipmitool ipmi-sensors lsblk lsusb lvs mdadm modinfo runlevel - sensors smartctl strings sudo tree upower uptime); + @data = qw(blockdev bt-adapter dig dmidecode doas fdisk file hciconfig + hddtemp ifconfig ip ipmitool ipmi-sensors lsblk lsusb lvs mdadm modinfo + runlevel sensors smartctl strings sudo tree upower uptime); } $b_program = 1; $item = 'Program'; @@ -2764,6 +2856,7 @@ sub check_items { elsif ($type eq 'recommended Perl modules'){ @data = qw(File::Copy File::Find File::Spec::Functions HTTP::Tiny IO::Socket::SSL Time::HiRes Cpanel::JSON::XS JSON::XS XML::Dumper Net::FTP); + push(@data, qw(OpenBSD::Pledge OpenBSD::Unveil)) if $bsd_type && $bsd_type eq 'openbsd'; $b_perl_module = 1; $item = 'Perl Module'; $extra = ' (Optional)'; @@ -2816,12 +2909,12 @@ sub check_items { ['0', '', '', " " ], ); if ($extra2){ - $rows[scalar @rows] = (['0', '', '', $extra2]); - $rows[scalar @rows] = (['0', '', '', ' ']); + $rows[scalar @rows] = ['0', '', '', $extra2]; + $rows[scalar @rows] = ['0', '', '', ' ']; } if ($extra3){ - $rows[scalar @rows] = (['0', '', '', $extra3]); - $rows[scalar @rows] = (['0', '', '', ' ']); + $rows[scalar @rows] = ['0', '', '', $extra3]; + $rows[scalar @rows] = ['0', '', '', ' ']; } foreach my $item (@data){ $install = ''; @@ -2847,23 +2940,23 @@ sub check_items { push(@missing, "$item$install"); } $row = make_row($item,$about,$result); - $rows[scalar @rows] = (['0', '', '', $row]); + $rows[scalar @rows] = ['0', '', '', $row]; } - $rows[scalar @rows] = (['0', '', '', " "]); + $rows[scalar @rows] = ['0', '', '', " "]; if (@missing){ - $rows[scalar @rows] = (['0', '', '', "The following $type are missing$extra4:"]); + $rows[scalar @rows] = ['0', '', '', "The following $type are missing$extra4:"]; foreach (@missing) { - $rows[scalar @rows] = (['0', '', '', "$item: $_"]); + $rows[scalar @rows] = ['0', '', '', "$item: $_"]; } } if (@unreadable){ - $rows[scalar @rows] = (['0', '', '', "The following $type are not readable: "]); + $rows[scalar @rows] = ['0', '', '', "The following $type are not readable: "]; foreach (@unreadable) { - $rows[scalar @rows] = (['0', '', '', "$item: $_"]); + $rows[scalar @rows] = ['0', '', '', "$item: $_"]; } } if (!@missing && !@unreadable){ - $rows[scalar @rows] = (['0', '', '', "All $type are present"]); + $rows[scalar @rows] = ['0', '', '', "All $type are present"]; } return @rows; } @@ -2984,6 +3077,13 @@ sub item_data { 'pacman' => 'dnsutils', 'rpm' => 'bind-utils', }, + 'disklabel' => { + 'info' => '', + 'info-bsd' => '-j, -p, -P; -R; -o (Open/NetBSD+derived)', + 'apt' => '', + 'pacman' => '', + 'rpm' => '', + }, 'dmidecode' => { 'info' => '-M if no sys machine data; -m', 'info-bsd' => '-M if null sysctl; -m; -B if null sysctl', @@ -2991,6 +3091,13 @@ sub item_data { 'pacman' => 'dmidecode', 'rpm' => 'dmidecode', }, + 'doas' => { + 'info' => '-Dx hddtemp-user; -o file-user (alt for sudo)', + 'info-bsd' => '-Dx hddtemp-user; -o file-user', + 'apt' => 'doas', + 'pacman' => 'doas', + 'rpm' => 'doas', + }, 'fdisk' => { 'info' => '-D partition scheme (fallback)', 'info-bsd' => '-D partition scheme', @@ -3028,7 +3135,7 @@ sub item_data { }, 'gpart' => { 'info' => '', - 'info-bsd' => '-p,-P file system, size', + 'info-bsd' => '-p,-P; -R; -o (FreeBSD+derived)', 'apt' => '', 'pacman' => '', 'rpm' => '', @@ -3091,7 +3198,7 @@ sub item_data { }, 'lsusb' => { 'info' => '-A usb audio; -J (optional); -N usb networking', - 'info-bsd' => '-A; -J; -N. Alternate to usbdevs', + 'info-bsd' => '', 'apt' => 'usbutils', 'pacman' => 'usbutils', 'rpm' => 'usbutils', @@ -3110,6 +3217,27 @@ sub item_data { 'pacman' => 'module-init-tools', 'rpm' => 'module-init-tools', }, + 'pciconfig' => { + 'info' => '', + 'info-bsd' => '-A,-E,-G,-N pci devices (FreeBSD+derived)', + 'apt' => '', + 'pacman' => '', + 'rpm' => '', + }, + 'pcictl' => { + 'info' => '', + 'info-bsd' => '-A,-E,-G,-N pci devices (NetBSD+derived)', + 'apt' => '', + 'pacman' => '', + 'rpm' => '', + }, + 'pcidump' => { + 'info' => '', + 'info-bsd' => '-A,-E,-G,-N pci devices (OpenBSD+derived, doas/su)', + 'apt' => '', + 'pacman' => '', + 'rpm' => '', + }, 'runlevel' => { 'info' => '-I fallback to Perl', 'info-bsd' => '', @@ -3138,6 +3266,13 @@ sub item_data { 'pacman' => '?', 'rpm' => '?', }, + 'sudo' => { + 'info' => '-Dx hddtemp-user; -o file-user', + 'info-bsd' => '-Dx hddtemp-user; -o file-user (alt for doas)', + 'apt' => 'sudo', + 'pacman' => 'sudo', + 'rpm' => 'sudo', + }, 'sysctl' => { 'info' => '', 'info-bsd' => '-C; -I; -m; -tm', @@ -3145,13 +3280,6 @@ sub item_data { 'pacman' => '?', 'rpm' => '?', }, - 'sudo' => { - 'info' => '-Dx hddtemp-user; -o file-user', - 'info-bsd' => '-Dx hddtemp-user; -o file-user', - 'apt' => 'sudo', - 'pacman' => 'sudo', - 'rpm' => 'sudo', - }, 'tree' => { 'info' => '--debugger 20,21 /sys tree', 'info-bsd' => '--debugger 20,21 /sys tree', @@ -3175,14 +3303,14 @@ sub item_data { }, 'usbconfig' => { 'info' => '', - 'info-bsd' => '-A; -E; -G; -J; -N; (alternate: usbdevs)', + 'info-bsd' => '-A; -E; -G; -J; -N; (FreeBSD+derived, doas/su)', 'apt' => 'usbutils', 'pacman' => 'usbutils', 'rpm' => 'usbutils', }, 'usbdevs' => { 'info' => '', - 'info-bsd' => '-A; -E; -G; -J; -N; (alternate: usbconfig)', + 'info-bsd' => '-A; -E; -G; -J; -N; (Open/NetBSD+derived)', 'apt' => 'usbutils', 'pacman' => 'usbutils', 'rpm' => 'usbutils', @@ -3214,7 +3342,7 @@ sub item_data { 'info-bsd' => '-G multi screen resolution', 'apt' => 'X11-utils', 'pacman' => 'xorg-xdpyinfo', - 'rpm' => 'xorg-x11-utils (SUSE: xdpyinfo)', + 'rpm' => 'xorg-x11-utils (SUSE/Fedora?: xdpyinfo)', }, 'xprop' => { 'info' => '-S desktop data', @@ -3228,7 +3356,7 @@ sub item_data { 'info-bsd' => '-G single screen resolution', 'apt' => 'x11-xserver-utils', 'pacman' => 'xrandr', - 'rpm' => 'x11-server-utils', + 'rpm' => 'x11-server-utils (Fedora: xrandr)', }, # Perl Modules 'Cpanel::JSON::XS' => { @@ -3287,6 +3415,20 @@ sub item_data { 'pacman' => 'Core Modules', 'rpm' => 'Core Modules', }, + 'OpenBSD::Pledge' => { + 'info' => "$self_name Perl pledge support.", + 'info-bsd' => "$self_name Perl pledge support.", + 'apt' => '', + 'pacman' => '', + 'rpm' => '', + }, + 'OpenBSD::Unveil' => { + 'info' => "Experimental: $self_name Perl unveil support.", + 'info-bsd' => "Experimental: $self_name Perl unveil support.", + 'apt' => '', + 'pacman' => '', + 'rpm' => '', + }, 'Time::HiRes' => { 'info' => '-C cpu sleep (not required); --debug timers', 'info-bsd' => '-C cpu sleep (not required); --debug timers', @@ -3355,8 +3497,9 @@ sub awk { my ($ref,$search,$num,$sep) = @_; my ($result); # print "search: $search\n"; - return if ! @$ref || ! $search; + return if !@$ref || !$search; foreach (@$ref){ + next if !defined $_; if (/$search/i){ $result = $_; $result =~ s/^\s+|\s+$//g; @@ -3420,6 +3563,7 @@ sub compare_versions { sub convert_hex { return (defined $_[0] && $_[0] =~ /^0x/) ? hex($_[0]) : $_[0]; } + # returns count of files in directory, if 0, dir is empty sub count_dir_files { return unless -d $_[0]; @@ -3476,6 +3620,7 @@ sub globber { eval $end if $b_log; return @files; } + # arg MUST be quoted when inserted, otherwise perl takes it for a hex number sub is_hex { return (defined $_[0] && $_[0] =~ /^0x/) ? 1 : 0; @@ -3531,7 +3676,7 @@ sub program_data { my ($values_id,$version_id,$level) = @_; my (@data,$path,@program_data); $level = 0 if ! $level; - #print "val_id: $values_id ver_id:$version_id lev:$level ex:$extra\n"; + # print "val_id: $values_id ver_id:$version_id lev:$level ex:$extra\n"; $version_id = $values_id if ! $version_id; @data = program_values($values_id); if ($data[3]){ @@ -3548,7 +3693,7 @@ sub program_data { return @program_data; } -# it's almost 1000 times slower to load these each time program_values is called!! +# It's almost 1000 times slower to load these each time program_values is called!! sub set_program_values { %program_values = ( ## Clients ## @@ -3609,7 +3754,7 @@ sub set_program_values { 'fireplace' => ['^fireplace',0,'0','fireplace',0,1,0,'',''], # unverified 'fluxbox' => ['^fluxbox',2,'-v','Fluxbox',0,1,0,'',''], 'flwm' => ['^flwm',0,'0','FLWM',0,0,1,'',''], # no version - #openbsd changed: version string: [FVWM[[main] Fvwm.. sigh, and outputs to stderr. Why? + # openbsd changed: version string: [FVWM[[main] Fvwm.. sigh, and outputs to stderr. Why? 'fvwm' => ['^fvwm',2,'-version','FVWM',0,1,0,'',''], 'fvwm1' => ['^Fvwm',3,'-version','FVWM1',0,1,1,'',''], 'fvwm2' => ['^fvwm',2,'--version','FVWM2',0,1,0,'',''], @@ -3794,7 +3939,7 @@ sub program_values { if ( defined $program_values{$app} ){ @program_data = @{$program_values{$app}}; } - #my $debug = Dumper \@program_data; + # my $debug = Dumper \@program_data; log_data('dump',"Program Data",\@program_data) if $b_log; return @program_data; } @@ -3912,6 +4057,7 @@ sub program_version_cmd { eval $end if $b_log; return @data; } + # returns $cmd, $search sub program_version_pkg { eval $start if $b_log; @@ -3972,10 +4118,10 @@ sub toucher { # arg: 1 - string to be right left trimmed. Also slices off \n so no chomp needed # this thing is super fast, no need to log its times etc, 0.0001 seconds or less sub trimmer { - #eval $start if $b_log; + # eval $start if $b_log; my ($str) = @_; $str =~ s/^\s+|\s+$|\n$//g; - #eval $end if $b_log; + # eval $end if $b_log; return $str; } @@ -4226,10 +4372,11 @@ sub set_version_data { #### OPTIONS HANDLER / VERSION ######################################################################## -# OptionsHandler +## OptionsHandler { package OptionsHandler; -my (%trigger); +# note: had %trigger local but tripped odd perl 5.008 failures unless global +# so moved to %use and %show globals. my ($self_download,$download_id); sub get { eval $start if $b_log; @@ -4308,13 +4455,13 @@ sub get { $show{'graphic'} = 1; $show{'graphic-basic'} = 1; }, 'h|help|?' => sub { - $trigger{'help'} = 1; }, + $show{'help'} = 1; }, 'i|ip' => sub { $show{'short'} = 0; $show{'ip'} = 1; $show{'network'} = 1; $show{'network-advanced'} = 1; - $trigger{'downloader'} = 1 if ! main::check_program('dig');}, + $use{'downloader'} = 1 if ! main::check_program('dig');}, 'I|info' => sub { $show{'short'} = 0; $show{'info'} = 1; }, @@ -4477,7 +4624,8 @@ sub get { $extra = 2; } if ($arg >= 7 ){ - $trigger{'downloader'} = 1 if !main::check_program('dig'); + $use{'downloader'} = 1 if !main::check_program('dig'); + $show{'battery-forced'} = 1; $show{'bluetooth-forced'} = 1; $show{'cpu-flag'} = 1; $show{'ip'} = 1; @@ -4487,7 +4635,7 @@ sub get { } if ($arg >= 8 ){ $b_admin = 1; - $trigger{'downloader'} = 1; + $use{'downloader'} = 1; $show{'process'} = 1; $show{'ps-cpu'} = 1; $show{'ps-mem'} = 1; @@ -4500,11 +4648,11 @@ sub get { main::error_handler('bad-arg',$opt,$arg); } }, 'V|version' => sub { - $trigger{'version'} = 1 }, + $show{'version'} = 1 }, 'w|weather' => sub { my ($opt) = @_; $show{'short'} = 0; - $trigger{'downloader'} = 1; + $use{'downloader'} = 1; if ( $use{'weather'} ){ $show{'weather'} = 1; } @@ -4516,8 +4664,8 @@ sub get { $arg ||= ''; $arg =~ s/\s//g; $show{'short'} = 0; - $trigger{'downloader'} = 1; - if ( $use{'weather'} ){ + $use{'downloader'} = 1; + if ($use{'weather'}){ if ($arg){ $show{'weather'} = 1; $show{'weather-location'} = $arg; @@ -4588,21 +4736,21 @@ sub get { my ($opt,$arg) = @_; if ($arg == 40) { $dl{'tiny'} = 0; - $trigger{'downloader'} = 1;} + $use{'downloader'} = 1;} elsif ($arg == 41) { $dl{'curl'} = 0; - $trigger{'downloader'} = 1;} + $use{'downloader'} = 1;} elsif ($arg == 42) { $dl{'fetch'} = 0; - $trigger{'downloader'} = 1;} + $use{'downloader'} = 1;} elsif ($arg == 43) { $dl{'wget'} = 0; - $trigger{'downloader'} = 1;} + $use{'downloader'} = 1;} elsif ($arg == 44) { $dl{'curl'} = 0; $dl{'fetch'} = 0; $dl{'wget'} = 0; - $trigger{'downloader'} = 1;} + $use{'downloader'} = 1;} else { main::error_handler('bad-arg', $opt, $arg); }}, @@ -4620,7 +4768,7 @@ sub get { }, 'bt-tool:s' => sub { my ($opt,$arg) = @_; - if ($arg =~ /^(bluetoothctl|bt-adapter|hciconfig)$/i){ + if ($arg =~ /^(bluetoothctl|bt-adapter|hciconfig|rfkill)$/i){ $bt_tool = lc($arg); } else { @@ -4643,8 +4791,16 @@ sub get { else { main::error_handler('bad-arg', $opt, $arg); } }, - 'debug-filter|debug-z' => sub { + 'debug-filter|debug-z|debug-zy' => sub { $debugger{'filter'} = 1 }, + 'debug-id:s' => sub { + my ($opt,$arg) = @_; + if ($arg){ + $debugger{'id'} = $arg; + } + else { + main::error_handler('bad-arg', $opt, $arg); + } }, 'debug-no-eps' => sub { $debugger{'no-exit'} = 1; $debugger{'no-proc'} = 1; @@ -4664,7 +4820,7 @@ sub get { $debugger{'sys-print'} = 1; }, 'debug-test-1' => sub { $debugger{'test-1'} = 1; }, - 'debug-width|debug-y:i' => sub { + 'debug-width|debug-y|debug-zy:i' => sub { my ($opt,$arg) = @_; $arg ||= 80; if ($arg =~ /^[0-9]+$/ && ($arg == 1 || $arg >= 80)){ @@ -4706,7 +4862,7 @@ sub get { # desired downloader. $arg = main::set_perl_downloader($arg); %dl = ('dl' => $arg, $arg => 1); - $trigger{'downloader'} = 1; + $use{'downloader'} = 1; } } else { @@ -4715,8 +4871,8 @@ sub get { 'fake:s' => sub { my ($opt,$arg) = @_; if ($arg){ - my $wl = 'bluetooth|compiler|cpu|dboot|dmidecode|ipmi|logical|'; - $wl .= 'pciconf|pcictl|pcidump|raid-hw|raid-lvm|raid-md|raid-zfs|'; + my $wl = 'bluetooth|compiler|cpu|dboot|dmidecode|ipmi|logical|pciconf|'; + $wl .= 'pcictl|pcidump|raid-hw|raid-lvm|raid-md|raid-soft|raid-zfs|'; $wl .= 'sensors|sysctl|uptime|usbconfig|usbdevs|vmstat|xorg-log'; for (split(',',$arg)){ if ($_ =~ /\b($wl)\b/){ @@ -4766,7 +4922,7 @@ sub get { 'irc' => sub { $b_irc = 1; }, 'man' => sub { - $trigger{'use-man'} = 1; }, + $use{'yes-man'} = 1; }, 'mips' => sub { $b_mips = 1 }, 'output:s' => sub { @@ -4787,7 +4943,7 @@ sub get { 'no-html-wan' => sub { $force{'no-html-wan'}= 1;}, 'no-man' => sub { - $trigger{'no-man-force'} = 0; }, + $use{'no-man'} = 0; }, 'no-ssl' => sub { $dl{'no-ssl-opt'}=1 }, 'no-sudo' => sub { @@ -4808,9 +4964,9 @@ sub get { 'ppc' => sub { $b_ppc = 1 }, 'recommends' => sub { - $trigger{'recommends'} = 1; }, + $show{'recommends'} = 1;}, 'sensors-default' => sub { - $trigger{'sensors-default'} = 1; }, + $use{'sensors-default'} = 1; }, 'sensors-exclude:s' => sub { my ($opt,$arg) = @_; if ($arg){ @@ -4861,28 +5017,50 @@ sub get { }}, '<>' => sub { my ($opt) = @_; - main::error_handler('unknown-option', "$opt", "" ); } - ) ; #or error_handler('unknown-option', "@ARGV", ''); - ## run all these after so that we can change widths, downloaders, etc + main::error_handler('unknown-option', "$opt", "" );} + ); # or error_handler('unknown-option', "@ARGV", ''); + # run all these after so that we can change widths, downloaders, etc + # print Data::Dumper::Dumper \%trigger; post_process(); eval $end if $b_log; } sub post_process { - CheckRecommends::run() if $trigger{'recommends'}; + CheckRecommends::run() if $show{'recommends'}; # sets for either config or arg here - main::set_downloader() if $trigger{'downloader'} || $wan_url || ($force{'no-dig'} && $show{'ip'}); + if ($use{'downloader'} || $wan_url || ($force{'no-dig'} && $show{'ip'})){ + main::set_downloader(); + } main::set_xorg_log() if $show{'graphic'}; - main::show_version() if $trigger{'version'}; - main::show_options() if $trigger{'help'}; - $use{'man'} = 0 if (!$trigger{'use-man'} || $trigger{'no-man-force'}); - main::update_me($self_download, $download_id) if $trigger{'updater'}; + main::show_version() if $show{'version'}; + main::show_options() if $show{'help'}; + $use{'man'} = 0 if (!$use{'yes-man'} || $use{'no-man'}); + main::update_me($self_download, $download_id) if $use{'update-trigger'}; + if ($b_pledge){ + my $b_update; + # if -c 9x, remove in SelectColors::set_selection(), else remove here + if (!$colors{'selector'} && $debugger{'level'} < 21){ + @pledges = grep {$_ ne 'getpw'} @pledges; + $b_update = 1; + } + if ($debugger{'level'} < 21){ # remove ftp upload + @pledges = grep {!/(dns|inet)/} @pledges; + $b_update = 1; + } + # not writing/creating .inxi data dirs colors selector launches set_color() + if (!$show{'weather'} && !$colors{'selector'} && $debugger{'level'} < 10 && + $output_type eq 'screen'){ + @pledges = grep {!/(cpath|wpath)/} @pledges; + $b_update = 1; + } + OpenBSD::Pledge::pledge(@pledges) if $b_update; + } if ($output_type){ - if ($output_type ne 'screen' && ! $output_file){ + if ($output_type ne 'screen' && !$output_file){ main::error_handler('bad-arg', '--output', '--output-file not provided'); } } $show{'graphic-basic'} = 0 if $b_admin; - if ($trigger{'sensors-default'}){ + if ($use{'sensors-default'}){ @sensors_exclude = (); @sensors_use = (); } @@ -4895,21 +5073,15 @@ sub post_process { || $show{'unmounted'}){ $use{'mdadm'} = 1; } - if ($bsd_type && ($show{'short'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'disk'})){ - $use{'dm-boot-disk'} = 1; - } - if ($bsd_type && ($show{'optical-basic'} || $show{'optical'})){ - $use{'dm-boot-optical'} = 1 - } if ($b_admin && $show{'disk'}){ $use{'smartctl'} = 1; } # triggers may extend to -D, -pP if ($show{'short'} || $show{'logical'} || $show{'raid'} || $show{'disk'} || $show{'disk-total'} || $show{'disk-basic'} || $show{'unmounted'}){ - $use{'lvm'} = 1; + $use{'logical'} = 1; } - main::set_sudo() if ( $show{'unmounted'} || ($extra > 0 && $show{'disk'}) ); + main::set_sudo() if ($show{'unmounted'} || ($extra > 0 && $show{'disk'})); $extra = 3 if $b_admin; $use{'filter'} = 0 if $use{'filter-override'}; # override for things like -b or -v2 to -v3 @@ -4922,27 +5094,56 @@ sub post_process { $show{'disk-basic'} = 0; $show{'disk-total'} = 0; } - if ($show{'ram'} || $show{'slot'} || ($show{'cpu'} && ($extra > 1 || $bsd_type)) || - ( ( $bsd_type || $force{'dmidecode'} ) && ($show{'machine'} || $show{'battery'}) ) ){ + if ($show{'ram'} || $show{'slot'} || ($show{'cpu'} && ($extra > 1 || $bsd_type)) || + (( $bsd_type || $force{'dmidecode'}) && ($show{'machine'} || $show{'battery'}))){ $use{'dmidecode'} = 1; } - if ($show{'audio'} || $show{'graphic'} || $show{'network'} || $show{'raid'} ){ + if ($show{'audio'} || $show{'bluetooth'} || $show{'graphic'} || + $show{'network'} || $show{'raid'} ){ $use{'pci'} = 1; } - if ($show{'usb'} || $show{'audio'} || $show{'bluetooth'} || $show{'graphic'} || $show{'network'} ){ + if ($show{'usb'} || $show{'audio'} || $show{'bluetooth'} || + $show{'graphic'} || $show{'network'} ){ $use{'usb'} = 1; } - if ($bsd_type && ($show{'short'} || $show{'system'} || $show{'audio'} || $show{'battery'} || - $show{'cpu'} || $show{'cpu-basic'} || $show{'info'} || $show{'machine'} || - $show{'process'} || $show{'ram'} || $show{'sensor'} ) ){ + if ($bsd_type){ + if ($show{'audio'}){ + $use{'bsd-audio'} = 1;} + if ($show{'battery'}){ + $use{'bsd-battery'} = 1;} + if ($show{'short'} || $show{'cpu-basic'} || $show{'cpu'}){ + $use{'bsd-cpu'} = 1; + $use{'bsd-sleep'} = 1;} + if ($show{'short'} || $show{'disk-basic'} || $show{'disk-total'} || + $show{'disk'} || $show{'partition'} || $show{'partition-full'} || + $show{'raid'} || $show{'swap'} || $show{'unmounted'}){ + $use{'bsd-disk'} = 1; + $use{'bsd-partition'} = 1; + $use{'bsd-raid'} = 1;} + if ($show{'system'}){ + $use{'bsd-kernel'} = 1;} + if ($show{'machine'}){ + $use{'bsd-machine'} = 1;} + if ($show{'short'} || $show{'info'} || $show{'ps-mem'} || $show{'ram'}){ + $use{'bsd-memory'} = 1;} + if ($show{'optical-basic'} || $show{'optical'}){ + $use{'bsd-optical'} = 1;} + # strictly only used to fill in pci drivers if tool doesn't support that + if ($use{'pci'}){ + $use{'bsd-pci'} = 1;} + if ($show{'raid'}){ + $use{'bsd-ram'} = 1;} + if ($show{'sensor'}){ + $use{'bsd-sensor'} = 1;} + # always use this, it's too core $use{'sysctl'} = 1; } } sub process_updater { my ($opt,$arg) = @_; - $trigger{'downloader'} = 1; + $use{'downloader'} = 1; if ($use{'update'}){ - $trigger{'updater'} = 1; + $use{'update-trigger'} = 1; if (!$arg && $self_name eq 'pinxi'){ $use{'man'} = 1; $download_id = 'inxi-perl branch'; @@ -4958,7 +5159,7 @@ sub process_updater { $download_id = 'main branch'; $self_download = main::get_defaults('inxi-main'); $use{'man'} = 1; - $trigger{'use-man'} = 1; + $use{'yes-man'} = 1; } elsif ( $arg =~ /^[12]$/){ $download_id = "branch $arg"; @@ -5013,7 +5214,7 @@ sub show_options { ['1', '-A', '--audio', "Audio/sound devices(s), driver, running sound servers." ], ['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ], ['1', '-B', '--battery', "System battery info, including charge, condition - voltage (if critical), plus extra info (if battery present)." ], + voltage (if critical), plus extra info (if battery present/detected)." ], ['1', '-c', '--color', "Set color scheme (0-42). For piped or redirected output, you must use an explicit color selector. Example:^$self_name^-c^11" ], ['1', '', '', "Color selectors let you set the config file value for the @@ -5241,7 +5442,7 @@ sub show_options { ['2', '-B', '', "Serial number." ], ['2', '-C', '', "L1/L3 cache (if root and dmidecode installed)." ], ['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number; LVM - volume group free space (if available)." ], + volume group free space (if available); disk duid, some BSDs." ], ['2', '-E', '', "Chip vendor:product ID, LMP subversion." ], ['2', '-G', '', "Chip vendor:product ID for each video device; OpenGL compatibility version, if free drivers and available; Xorg compositor; @@ -5251,7 +5452,7 @@ sub show_options { ['2', '-I', '', "Other detected installed gcc versions (if present). System default runlevel. Adds parent program (or tty) for shell info if not in IRC. Adds Init version number, RC (if found). Adds per package manager - package counts if not -r." ], + installed package counts if not -r." ], ['2', '-j,-p,-P', '', "Swap priority." ], ['2', '-J', '', "Vendor:chip-ID." ], ['2', '-L', '', "Show internal LVM volumes, like raid image/meta volumes; @@ -5340,7 +5541,8 @@ sub show_options { ['2', '43', '', "Bypass Wget as a downloader option." ], ['2', '44', '', "Bypass Curl, Fetch, and Wget as downloader options. Forces Perl if HTTP::Tiny present." ], - ['1', '', '--bt-tool', "[bt-adapter|hciconfig] Force use of given tool for bluetooth." ], + ['1', '', '--bt-tool', "[bt-adapter|hciconfig|rfkill] Force use of given tool for + bluetooth report." ], ['1', '', '--dig', "Overrides configuration item NO_DIG (resets to default)." ], ['1', '', '--display', "[:[0-9]] Try to get display data out of X (default: display 0)." ], ['1', '', '--dmidecode', "Force use of dmidecode data instead of /sys where relevant @@ -5496,7 +5698,7 @@ sub show_version { #### STARTUP DATA ######################################################################## -# StartClient +## StartClient { package StartClient; # use warnings; @@ -5538,7 +5740,7 @@ sub get_client_name { $client_name =~ s/^.*\///; if ($client_name =~ /^(bash|csh|dash|fish|sh|python.*|perl.*|zsh)$/){ $pppid = (main::grabber("ps -wwp $ppid -o ppid"))[1]; - #my @temp = (main::grabber("ps -wwp $ppid -o ppid 2>/dev/null"))[1]; + # my @temp = (main::grabber("ps -wwp $ppid -o ppid 2>/dev/null"))[1]; $pppid =~ s/^\s+|\s+$//g; $client_name =~ s/[0-9\.]+$//; # clean things like python2.7 if ($pppid && -f "/proc/$pppid/exe" ){ @@ -5550,7 +5752,7 @@ sub get_client_name { $client{'name'} = $client_name; get_client_version(); # print "c:$client_name p:$pppid\n"; - #print "$client{'name-print'}\n"; + # print "$client{'name-print'}\n"; } else { if (!check_modern_konvi()){ @@ -5848,7 +6050,7 @@ sub set_konvi_data { # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf if ($config_tool){ my @data = main::grabber("$config_tool --path data 2>/dev/null",':'); - main::get_configs(\@data); + Configs::set(\@data); } eval $end if $b_log; } @@ -5872,6 +6074,7 @@ sub apply_filter { } return $string; } + # note, let the print logic handle N/A cases sub apply_partition_filter { my ($source,$string,$type) = @_; @@ -5885,6 +6088,7 @@ sub apply_partition_filter { } return $string; } + sub arm_cleaner { my ($item) = @_; $item =~ s/(\([^\(]*Device Tree[^\)]*\))//gi; @@ -5909,7 +6113,7 @@ sub cleaner { my ($item) = @_; return $item if !$item;# handle cases where it was 0 or '' # note: |nee trips engineering, but I don't know why nee was filtered - $item =~ s/chipset|company|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|incorporation|industrial|international|\bnee\b|revision|semiconductor|software|technologies|technology|ltd\.||\bltd\b|inc\.||\binc\b|intl\.|co\.||corp\.||\(tm\)|\(r\)|®|\(rev ..\)|\'|\"|\sinc\s*$|\?//gi; + $item =~ s/chipset|company|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|incorporation|industrial|international|\bnee\b|no\sstring|revision|semiconductor|software|technologies|technology|ltd\.||\bltd\b|inc\.||\binc\b|intl\.|co\.||corp\.||\(tm\)|\(r\)|®|\(rev ..\)|\'|\"|\sinc\s*$|\?//gi; $item =~ s/,|\*/ /g; $item =~ s/\s\s+/ /g; $item =~ s/^\s+|\s+$//g; @@ -5947,6 +6151,7 @@ sub general_cleaner { $string =~ s/$cleaner//i; return $string; } + # args: $1 - size in KB, return KB, MB, GB, TB, PB, EB; $2 - 'string'; # $3 - default value if null # returns string with units or array or size unmodified if not numeric @@ -6008,7 +6213,7 @@ sub increment_starters { sub pci_cleaner { my ($string,$type) = @_; - #print "st1 $type:$string\n"; + # print "st1 $type:$string\n"; my $filter = 'and\ssubsidiaries|compatible\scontroller|'; $filter .= '\b(device|controller|connection|multimedia)\b|\([^)]+\)'; # \[[^\]]+\]$| not trimming off ending [...] initial type filters removes end @@ -6016,10 +6221,11 @@ sub pci_cleaner { $string =~ s/($filter)//ig; $string =~ s/\s\s+/ /g; $string =~ s/^\s+|\s+$//g; - #print "st2 $type:$string\n"; + # print "st2 $type:$string\n"; $string = remove_duplicates($string) if $string; return $string; } + sub pci_cleaner_subsystem { my ($string) = @_; # we only need filters for features that might use vendor, -AGN @@ -6074,16 +6280,17 @@ sub row_defaults { my %unfound = ( 'arm-cpu-f' => 'Use -f option to see features', 'arm-pci' => 'No ARM data found for this feature.', - 'battery-data' => 'No system Battery data found. Is one present?', + 'battery-data' => 'No system battery data found. Is one present?', + 'battery-data-bsd' => 'No battery data found. Try with --dmidecode', 'battery-data-sys' => 'No /sys data found.', - 'bluetooth-data' => 'No Bluetooth data was found.', - 'bluetooth-down' => "$id can't run.", + 'bluetooth-data' => 'No bluetooth data found.', + 'bluetooth-down' => "tool can't run", 'cpu-bugs-null' => 'No CPU vulnerability/bugs data available.', 'cpu-model-null' => 'Model N/A', - 'cpu-speeds' => "No speed data found for $id cores.", + 'cpu-speeds' => 'No per core speed data found.', 'darwin-feature' => 'Feature not supported iu Darwin/OSX.', - 'disk-data' => 'No Disk data was found.', - 'disk-data-bsd' => 'No Disk data found for this BSD system.', + 'disk-data' => 'No disk data found.', + 'disk-data-bsd' => 'No disk data found.', 'disk-size-0' => 'Total N/A', 'display-console' => 'No advanced graphics data found on this system in console.', 'display-driver-na' => 'n/a (using device driver)', @@ -6102,38 +6309,46 @@ sub row_defaults { 'dmidecode-smbios' => 'No SMBIOS data for dmidecode to process', 'IP-dig' => "No $id found. Connected to web? SSL issues? Try --no-dig", 'IP-no-dig' => "No $id found. Connected to web? SSL issues? Try enabling dig", - 'lvm-data' => 'No LVM data was found.', - 'lvm-data-bsd' => 'No BSD support for LVM data.', - 'machine-data' => 'No Machine data: try newer kernel.', - 'machine-data-bsd' => 'No Machine data: Is dmidecode installed? Try -M --dmidecode.', - 'machine-data-dmidecode' => 'No Machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.', - 'machine-data-force-dmidecode' => 'No Machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.', + 'logical-data' => 'No logical block device data found.', + 'logical-data-bsd' => "Logical block device feature unsupported in $id.", + 'machine-data' => 'No machine data: try newer kernel.', + 'machine-data-bsd' => 'No machine data: Is dmidecode installed? Try -M --dmidecode.', + 'machine-data-dmidecode' => 'No machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.', + 'machine-data-force-dmidecode' => 'No machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.', 'mips-pci' => 'No MIPS data found for this feature.', 'note-check' => 'check', 'note-est' => 'est.', - 'optical-data' => 'No Optical or Floppy data was found.', - 'optical-data-bsd' => 'No Optical or Floppy data found for this BSD system.', + 'optical-data' => 'No optical or floppy data found.', + 'optical-data-bsd' => 'No optical or floppy data found.', 'output-limit' => "Output throttled. IPs: $id; Limit: $limit; Override: --limit [1-x;-1 all]", 'packages' => 'No packages detected. Unsupported package manager?', - 'partition-data' => 'No Partition data was found.', + 'partition-data' => 'No partition data found.', 'partition-hidden' => 'N/A (hidden?)', 'pci-advanced-data' => 'bus/chip ids unavailable', - 'pci-card-data' => 'No Device data found.', + 'pci-card-data' => 'No device data found.', 'pci-card-data-root' => 'Device data requires root.', 'pci-slot-data' => 'No PCI Slot data found.', - 'ps-data-null' => 'No Process data available.', - 'raid-data' => 'No RAID data was found.', - 'ram-data' => 'No RAM data was found.', + 'ps-data-null' => 'No process data available.', + 'raid-data' => 'No RAID data found.', + 'ram-data' => 'No RAM data found.', + 'ram-data-complete' => 'For complete report, try with --dmidecode', + 'ram-data-dmidecode' => 'No RAM data found. Try with --dmidecode', + 'recommends' => 'see --recommends', + 'root-feature' => 'Feature requires superuser permissions.', + 'root-item-incomplete' => "Full $id report requires superuser permissions.", 'root-required' => '', - 'root-suggested' => 'try sudo/root', - 'sensors-data-ipmi' => 'No ipmi sensors data was found.', - 'sensors-data-linux' => 'No sensors data was found. Is sensors configured?', + 'root-suggested' => 'try sudo/root',# gdm only + 'sensors-data-bsd' => "$id sensor data found but not usable.", + 'sensors-data-bsd-ok' => 'No sensor data found. Are sensors present?', + 'sensors-data-ipmi' => 'No ipmi sensor data found.', + 'sensors-data-linux' => 'No sensor data found. Is lm-sensors configured?', 'sensors-ipmi-root' => 'Unable to run ipmi sensors. Root privileges required.', - 'smartctl-command-failed' => 'A mandatory SMART command failed. Various possible causes.', + 'smartctl-command' => 'A mandatory SMART command failed. Various possible causes.', + 'smartctl-open' => 'Unable to open device. Wrong device ID given?', 'smartctl-udma-crc' => 'Bad cable/connection?', 'smartctl-usb' => 'Unknown USB bridge. Flash drive/Unsupported enclosure?', - 'swap-admin' => 'No admin Swap data available.', - 'swap-data' => 'No Swap data was found.', + 'swap-admin' => 'No admin swap data available.', + 'swap-data' => 'No swap data was found.', 'tool-missing-basic' => "", 'tool-missing-incomplete' => "Missing system tool: $id. Output will be incomplete", 'tool-missing-os' => "No OS support. Is a comparable $id tool available?", @@ -6143,11 +6358,11 @@ sub row_defaults { 'tool-present' => 'Present and working', 'tool-unknown-error' => "Unknown $id error. Unable to generate data.", 'tools-missing' => "This feature requires one of these tools: $id", - 'tools-missing-bsd' => "This feature requires one of these BSD tools: $id", - 'unmounted-data' => 'No Unmounted partitions found.', - 'unmounted-data-bsd' => 'No Unmounted partition data found for this BSD system.', + 'tools-missing-bsd' => "This feature requires one of these tools: $id", + 'unmounted-data' => 'No unmounted partitions found.', + 'unmounted-data-bsd' => "Unmounted partition feature unsupported in $id.", 'unmounted-file' => 'No /proc/partitions file found.', - 'usb-data' => 'No USB data was found. Server?', + 'usb-data' => 'No USB data found. Server?', 'unknown-desktop-version' => 'ERR-101', 'unknown-dev' => 'ERR-102', 'unknown-shell' => 'ERR-100', @@ -6164,7 +6379,7 @@ sub row_defaults { sub translate_size { my ($working) = @_; my ($size,$unit) = (0,''); - #print ":$working:\n"; + # print ":$working:\n"; return if ! defined $working; my $math = ($working =~ /B$/) ? 1000: 1024; if ($working =~ /^([0-9\.]+)\s*([kKMGTPE])i?B?$/i){ @@ -6207,6 +6422,7 @@ sub check_output_path { $b_good = 1 if (-d $dir && -w $dir && $dir =~ /^\// && $file); return $b_good; } + # passing along hash ref sub output_handler { my ($data) = @_; @@ -6221,6 +6437,7 @@ sub output_handler { generate_xml($data); } } + # passing along hash ref # NOTE: file has already been set and directory verified sub generate_json { @@ -6268,7 +6485,7 @@ sub generate_xml { my ($xml); my $b_debug = 0; error_handler('not-in-irc', 'help') if $b_irc; - #print Dumper $data if $b_debug; + # print Dumper $data if $b_debug; if (check_perl_module('XML::Dumper')){ XML::Dumper->import; $xml = XML::Dumper::pl2xml($data); @@ -6313,7 +6530,7 @@ sub print_basic { } # print $length . "\n"; for my $i (0 .. $#$data){ - #print "0: $data->[$i][0]\n"; + # print "0: $data->[$i][0]\n"; if ($data->[$i][0] == 0 ){ $indent = 0; $indent1 = 0; @@ -6339,13 +6556,13 @@ sub print_basic { $line = sprintf("%-${indent}s\n", "$start"); print_line($line); $start = ''; - #print "1-print.\n"; + # print "1-print.\n"; } if ( ( $indent + length($data->[$i][3]) ) < $size{'max'} ){ $data->[$i][3] =~ s/\^/ /g; $line = sprintf("%-${indent}s%s\n", "$start", $data->[$i][3]); print_line($line); - #print "2-print.\n"; + # print "2-print.\n"; } else { my $holder = ''; @@ -6353,11 +6570,11 @@ sub print_basic { # note: special case, split ' ' trims leading, trailing spaces, # then splits like awk, on one or more white spaces. foreach my $word (split(' ', $data->[$i][3])){ - #print "$word\n"; + # print "$word\n"; if ( ( $indent + length($holder) + length($word) ) < $size{'max'} ) { $word =~ s/\^/ /g; $holder .= $word . $sep; - #print "3-hold.\n"; + # print "3-hold.\n"; } #elsif ( ( $indent + length($holder) + length($word) ) >= $size{'max'}){ else { @@ -6366,13 +6583,13 @@ sub print_basic { $start = ''; $word =~ s/\^/ /g; $holder = $word . $sep; - #print "4-print-hold.\n"; + # print "4-print-hold.\n"; } } if ($holder !~ /^[ ]*$/){ $line = sprintf("%-${indent}s%s\n", "$start", $holder); print_line($line); - #print "5-print-last.\n"; + # print "5-print-last.\n"; } } } @@ -6396,9 +6613,9 @@ sub print_data { if ($size{'max'} < $size{'wrap-max'} || $size{'indent'} < 11 ){ $indent = 2; } - #foreach my $key1 (sort { (split('#', $a))[0] <=> (split('#', $b))[0] } keys %$data) { + # foreach my $key1 (sort { (split('#', $a))[0] <=> (split('#', $b))[0] } keys %$data) { foreach my $key1 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %$data) { - #foreach my $key1 (sort { $a cmp $b } keys %$data) { + # foreach my $key1 (sort { $a cmp $b } keys %$data) { $key = (split('#', $key1))[3]; if ($key ne 'SHORT' ) { $start = sprintf("$colors{'c1'}%-${indent}s$colors{'cn'}","$key$sep{'s1'}"); @@ -6439,9 +6656,9 @@ sub print_data { if (ref($val1) eq 'HASH'){ #%row = %$val1; ($counter,$split_count) = (0,0); - #foreach my $key2 (sor ({ (split('#', $a))[0] <=> (split('#', $b))[0] } keys %$val1){ + # foreach my $key2 (sor ({ (split('#', $a))[0] <=> (split('#', $b))[0] } keys %$val1){ foreach my $key2 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %$val1){ - #foreach my $key2 (sort { $a cmp $b } keys %$val1){ + # foreach my $key2 (sort { $a cmp $b } keys %$val1){ ($hash_id,$b_container,$indentx,$key) = (split('#', $key2)); if ($start_holder eq 'Graphics' && $key eq 'Screen'){ $ids{'Monitor'} = 1; @@ -6471,7 +6688,7 @@ sub print_data { @temp = split(/\s+/, $val2); $split_count = scalar @temp; if ( !$b_single && ( length( "$key$sep{'s2'} $val2" ) + $length ) < $size{'max'} ) { - #print "one\n"; + # print "one\n"; $length += length("$key$sep{'s2'} $val2"); $holder .= "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val2"; } @@ -6480,7 +6697,7 @@ sub print_data { # can have the last row have a lot of devices, or many raid types elsif ( !$b_single && ( length( "$key$sep{'s2'} $val2" ) + $indent ) > $size{'max'} && !defined $ids{$key} && $split_count > 2 ) { - #print "two\n"; + # print "two\n"; @values = split(/\s+/, $val2); $val3 = shift @values; # $length += length("$key$sep{'s2'} $val3 ") + $indent; @@ -6490,10 +6707,10 @@ sub print_data { # print scalar @values,"\n"; foreach (@values){ # my $l = (length("$_ ") + $length); - #print "$l\n"; + # print "$l\n"; if ( (length("$_ ") + $length) < $size{'max'} ){ - #print "three.1\n"; - #print "a\n"; + # print "three.1\n"; + # print "a\n"; if ($start2){ $holder2 .= "$start2$_ "; $start2 = ''; @@ -6506,19 +6723,19 @@ sub print_data { $length += length("$_ "); } else { - #print "three.2\n"; + # print "three.2\n"; if ($start2){ $holder2 = "$start2$holder2"; } else { $holder2 = "$colors{'c2'}$holder2"; } - #print "xx:$holder"; + # print "xx:$holder"; $line = sprintf("%-${indent}s%s$colors{'cn'}\n","$start","$holder$holder2"); print_line($line); $holder = ''; $holder2 = "$_ "; - #print "h2: $holder2\n"; + # print "h2: $holder2\n"; $length = length($holder2) + $indent; $start2 = ''; $start = ''; @@ -6526,7 +6743,7 @@ sub print_data { } } if ($holder2 !~ /^\s*$/){ - #print "four\n"; + # print "four\n"; $holder2 = "$colors{'c2'}$holder2"; $line = sprintf("%-${indent}s%s$colors{'cn'}\n","$start","$holder$holder2"); print_line($line); @@ -6540,16 +6757,16 @@ sub print_data { } # NOTE: only these and the last fallback are used for b_single output else { - #print "H: $counter " . scalar %$val1 . " $indent3 $indent2\n"; + # print "H: $counter " . scalar %$val1 . " $indent3 $indent2\n"; if ($holder){ - #print "five\n"; + # print "five\n"; $line = sprintf("%-${indent_use}s%s$colors{'cn'}\n",$start,"$holder"); $length = length("$key$sep{'s2'} $val2") + $indent_use; print_line($line); $start = ''; } else { - #print "six\n"; + # print "six\n"; $length = $indent_use; #$holder = ''; } @@ -6559,7 +6776,7 @@ sub print_data { $indent_use = ($indent * $indentx) if $b_single; } if ($holder !~ /^\s*$/){ - #print "seven\n"; + # print "seven\n"; $line = sprintf("%-${indent_use}s%s$colors{'cn'}\n",$start,"$start2$holder"); print_line($line); $holder = ''; @@ -6569,7 +6786,7 @@ sub print_data { } # only for repos currently elsif (ref($val1) eq 'ARRAY'){ - #print "eight\n"; + # print "eight\n"; $array=0; foreach my $item (@$val1){ $array++; @@ -6609,16 +6826,16 @@ sub print_line { } ######################################################################## -#### DATA PROCESSORS +#### ITEM PROCESSORS ######################################################################## #### ------------------------------------------------------------------- -#### PRIMARY DATA GENERATORS +#### ITEM GENERATORS #### ------------------------------------------------------------------- -## AudioData +## AudioItem { -package AudioData; +package AudioItem; sub get { eval $start if $b_log; @@ -6634,8 +6851,8 @@ sub get { else { push(@rows,device_output()); } - if ( ( (($b_arm || $b_mips) && !$use{'soc-audio'} && !$use{'pci-tool'}) || !@rows ) && - (my $file = main::system_files('asound-cards') ) ){ + if (((($b_arm || $b_mips) && !$use{'soc-audio'} && !$use{'pci-tool'}) || !@rows ) && + (my $file = $system_files{'asound-cards'})){ push(@rows,asound_output($file)); } push(@rows,usb_output()); @@ -6656,9 +6873,10 @@ sub get { sub device_output { eval $start if $b_log; + return if !$devices{'audio'}; my (@rows); my ($j,$num) = (0,1); - foreach my $row (@devices_audio){ + foreach my $row (@{$devices{'audio'}}){ $num = 1; $j = scalar @rows; my $driver = $row->[9]; @@ -6703,7 +6921,7 @@ sub device_output { $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->[1]; } } - #print "$row->[0]\n"; + # print "$row->[0]\n"; } eval $end if $b_log; return @rows; @@ -6720,7 +6938,7 @@ sub asound_output { foreach (@asound){ # filtering out modems and usb devices like webcams, this might get a # usb audio card as well, this will take some trial and error - if ( !/modem|usb/i && /^\s*[0-9]/ ) { + if (!/modem|usb/i && /^\s*[0-9]/) { $num = 1; my @working = split(/:\s*/, $_); # now let's get 1 2 @@ -6750,8 +6968,8 @@ sub usb_output { eval $start if $b_log; my (@rows,@ids,$path_id,$product,@temp2); my ($j,$num) = (0,1); - return if !@usb_audio; - foreach my $row (@usb_audio){ + return if !$usb{'audio'}; + foreach my $row (@{$usb{'audio'}}){ # print Data::Dumper::Dumper $row; $num = 1; # make sure to reset, or second device trips last flag @@ -6788,16 +7006,16 @@ sub sound_server_output { my (@rows,$program); my ($j,$num) = (0,0); my @servers = sound_server_data(); - for my $server (@servers){ + foreach my $server (@servers){ next if $extra < 1 && (!$server->[2] || $server->[2] ne 'yes'); $j = scalar @rows; $server->[1] ||= 'N/A'; + $server->[2] ||= 'N/A'; push(@rows, { main::key($num++,1,1,'Sound Server') => $server->[0], main::key($num++,0,2,'v') => $server->[1], + main::key($num++,0,2,'running') => $server->[2], }); - $server->[2] ||= 'N/A'; - $rows[$j]->{main::key($num++,1,1,'running')} = $server->[2]; } eval $end if $b_log; return @rows; @@ -6805,7 +7023,7 @@ sub sound_server_output { sub sound_server_data { eval $start if $b_log; my (@servers,$program,$running,$server,$version); - if (my $file = main::system_files('asound-version') ){ + if (my $file = $system_files{'asound-version'}){ # avoid possible second line if compiled by user my $content = main::reader($file,'',0); # some alsa strings have the build date in (...) @@ -6815,9 +7033,9 @@ sub sound_server_data { $running = 'yes'; # not needed I think, if asound is there, it's running, but if that's # not correct, can use one of the info/list/stat tests for aplay - #if (main::check_program('aplay') && main::grabber('aplay -l 2>/dev/null')){ - # $running = 'yes'; - #} + # if (main::check_program('aplay') && main::grabber('aplay -l 2>/dev/null')){ + # $running = 'yes'; + # } push(@servers, [$server,$version,$running]); ($running,$server,$version) = ('','',''); } @@ -6825,7 +7043,7 @@ sub sound_server_data { if (-e '/dev/sndstat' || ($program = main::check_program('ossinfo'))){ $server = 'OSS'; #$version = main::program_version('oss','\S',2); - $version = (grep {/^hw.snd.version:/} @sysctl_audio)[0] if @sysctl_audio; + $version = (grep {/^hw.snd.version:/} @{$sysctl{'audio'}})[0] if $sysctl{'audio'}; $version = (split(/:\s*/,$version),1)[1] if $version; $version =~ s|/.*$|| if $version; # not a great test, but ok for now @@ -6869,15 +7087,16 @@ sub sound_server_data { } } -## BatteryData +## BatteryItem { -package BatteryData; +package BatteryItem; + my (@upower_items,$b_upower,$upower); sub get { eval $start if $b_log; my (@rows,%battery,$key1,$val1); my $num = 0; - if ($bsd_type || $force{'dmidecode'}){ + if ($force{'dmidecode'}){ if ($alerts{'dmidecode'}->{'action'} ne 'use'){ $key1 = $alerts{'dmidecode'}->{'action'}; $val1 = $alerts{'dmidecode'}->{'message'}; @@ -6898,6 +7117,19 @@ sub get { } } } + elsif ($bsd_type && ($sysctl{'battery'} || $show{'battery-forced'})){ + %battery = battery_data_sysctl() if $sysctl{'battery'}; + if (!%battery){ + if ($show{'battery-forced'}){ + $key1 = 'Message'; + $val1 = main::row_defaults('battery-data-bsd',''); + @rows = ({main::key($num++,0,1,$key1) => $val1,}); + } + } + else { + @rows = battery_output(\%battery); + } + } elsif (-d '/sys/class/power_supply/'){ %battery = battery_data_sys(); if (!%battery){ @@ -6914,7 +7146,7 @@ sub get { else { if ($show{'battery-forced'}){ $key1 = 'Message'; - $val1 = main::row_defaults('battery-data-sys',''); + $val1 = (!$bsd_type) ? main::row_defaults('battery-data-sys'): main::row_defaults('battery-data-bsd'); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } } @@ -7094,8 +7326,8 @@ sub battery_data_sys { # note: there is no 'location' file, but dmidecode has it # '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 - constant_charge_current constant_charge_current_max cycle_count + my @items = qw(alarm capacity capacity_level charge_full charge_full_design + charge_now constant_charge_current constant_charge_current_max cycle_count energy_full energy_full_design energy_now location manufacturer model_name power_now present scope serial_number status technology type voltage_min_design voltage_now); foreach $item (@batteries){ @@ -7188,25 +7420,105 @@ sub battery_data_sys { $battery{$id}->{'energy_full_design'} = $battery{$id}->{'charge_full_design'} * $battery{$id}->{'voltage_min_design'}; } } - if ( $battery{$id}->{'energy_now'} && $battery{$id}->{'energy_full'} ){ + if ($battery{$id}->{'energy_now'} && $battery{$id}->{'energy_full'}){ $battery{$id}->{'capacity'} = 100 * $battery{$id}->{'energy_now'}/$battery{$id}->{'energy_full'}; $battery{$id}->{'capacity'} = sprintf("%.1f", $battery{$id}->{'capacity'}); } + if ($battery{$id}->{'energy_full_design'} && $battery{$id}->{'energy_full'}){ + $battery{$id}->{'of_orig'} = 100 * $battery{$id}->{'energy_full'}/$battery{$id}->{'energy_full_design'}; + $battery{$id}->{'of_orig'} = sprintf("%.1f", $battery{$id}->{'of_orig'}); + } + if ($battery{$id}->{'energy_now'}){ + $battery{$id}->{'energy_now'} = sprintf("%.1f", $battery{$id}->{'energy_now'}); + } + if ($battery{$id}->{'energy_full_design'}){ + $battery{$id}->{'energy_full_design'} = sprintf("%.1f",$battery{$id}->{'energy_full_design'}); + } + if ($battery{$id}->{'energy_full'}){ + $battery{$id}->{'energy_full'} = sprintf("%.1f", $battery{$id}->{'energy_full'}); + } + } + print Data::Dumper::Dumper \%battery if $dbg[33]; + main::log_data('dump','sys: %battery',\%battery) if $b_log; + eval $end if $b_log; + return %battery; +} +sub battery_data_sysctl { + eval $start if $b_log; + my (%battery,$id); + for (@{$sysctl{'battery'}}){ + if (/^(hw\.sensors\.)acpi([^\.]+)(\.|:)/){ + $id = uc($2); + } + if (/volt[^:]+:([0-9\.]+)\s+VDC\s+\(voltage\)/){ + $battery{$id}->{'voltage_min_design'} = $1; + } + elsif (/volt[^:]+:([0-9\.]+)\s+VDC\s+\(current voltage\)/){ + $battery{$id}->{'voltage_now'} = $1; + } + elsif (/watthour[^:]+:([0-9\.]+)\s+Wh\s+\(design capacity\)/){ + $battery{$id}->{'energy_full_design'} = $1; + } + elsif (/watthour[^:]+:([0-9\.]+)\s+Wh\s+\(last full capacity\)/){ + $battery{$id}->{'energy_full'} = $1; + } + elsif (/watthour[^:]+:([0-9\.]+)\s+Wh\s+\(remaining capacity\)/){ + $battery{$id}->{'energy_now'} = $1; + } + elsif (/amphour[^:]+:([0-9\.]+)\s+Ah\s+\(design capacity\)/){ + $battery{$id}->{'charge_full_design'} = $1; + } + elsif (/amphour[^:]+:([0-9\.]+)\s+Ah\s+\(last full capacity\)/){ + $battery{$id}->{'charge_full'} = $1; + } + elsif (/amphour[^:]+:([0-9\.]+)\s+Ah\s+\(remaining capacity\)/){ + $battery{$id}->{'charge_now'} = $1; + } + elsif (/raw[^:]+:[0-9\.]+\s+\((battery) ([^\)]+)\)/){ + $battery{$id}->{'status'} = $2; + } + elsif (/^acpi[\S]+:at [^:]+:\s*$id\s+model\s+(.*?)\s*serial\s+([\S]*?)\s*type\s+(.*?)\s*oem\s+(.*)/i){ + $battery{$id}->{'model_name'} = main::dmi_cleaner($1); + $battery{$id}->{'serial_number'} = $2; + $battery{$id}->{'technology'} = $3; + $battery{$id}->{'manufacturer'} = main::dmi_cleaner($4); + } + } + # then do the condition/charge percent math + for my $id (keys %battery){ + $battery{$id}->{'purpose'} = 'primary'; + # CHARGE is Ah, which are converted to Wh by: Ah x voltage. + if ($battery{$id}->{'voltage_min_design'}){ + if ($battery{$id}->{'charge_now'}){ + $battery{$id}->{'energy_now'} = $battery{$id}->{'charge_now'} * $battery{$id}->{'voltage_min_design'}; + } + if ($battery{$id}->{'charge_full'}){ + $battery{$id}->{'energy_full'} = $battery{$id}->{'charge_full'}*$battery{$id}->{'voltage_min_design'}; + } + if ($battery{$id}->{'charge_full_design'}){ + $battery{$id}->{'energy_full_design'} = $battery{$id}->{'charge_full_design'} * $battery{$id}->{'voltage_min_design'}; + } + } if ( $battery{$id}->{'energy_full_design'} && $battery{$id}->{'energy_full'} ){ $battery{$id}->{'of_orig'} = 100 * $battery{$id}->{'energy_full'}/$battery{$id}->{'energy_full_design'}; $battery{$id}->{'of_orig'} = sprintf("%.1f", $battery{$id}->{'of_orig'}); } - if ( $battery{$id}->{'energy_now'} ){ + if ($battery{$id}->{'energy_now'} && $battery{$id}->{'energy_full'}){ + $battery{$id}->{'capacity'} = 100 * $battery{$id}->{'energy_now'}/$battery{$id}->{'energy_full'}; + $battery{$id}->{'capacity'} = sprintf("%.1f", $battery{$id}->{'capacity'}); + } + if ($battery{$id}->{'energy_now'}){ $battery{$id}->{'energy_now'} = sprintf("%.1f", $battery{$id}->{'energy_now'}); } - if ( $battery{$id}->{'energy_full_design'} ){ - $battery{$id}->{'energy_full_design'} = sprintf("%.1f",$battery{$id}->{'energy_full_design'}); - } - if ( $battery{$id}->{'energy_full'} ){ + if ($battery{$id}->{'energy_full'}){ $battery{$id}->{'energy_full'} = sprintf("%.1f", $battery{$id}->{'energy_full'}); } + if ($battery{$id}->{'energy_full_design'}){ + $battery{$id}->{'energy_full_design'} = sprintf("%.1f", $battery{$id}->{'energy_full_design'}); + } } - main::log_data('dump','sys: %battery',\%battery) if $b_log; + print Data::Dumper::Dumper \%battery if $dbg[33]; + main::log_data('dump','dmi: %battery',\%battery) if $b_log; eval $end if $b_log; return %battery; } @@ -7252,7 +7564,7 @@ sub battery_data_dmi { last; } } - # print Data::Dumper::Dumper \%battery; + print Data::Dumper::Dumper \%battery if $dbg[33]; main::log_data('dump','dmi: %battery',\%battery) if $b_log; eval $end if $b_log; return %battery; @@ -7286,13 +7598,13 @@ sub upower_data { eval $end if $b_log; return %data; } - } -## BluetoothData +## BluetoothItem { -package BluetoothData; -my ($b_bluetooth,$b_hci_error,$b_hci,$b_service); +package BluetoothItem; + +my ($b_bluetooth,$b_hci_error,$b_hci,$b_rfk,$b_service); my ($service); my (%hci); sub get { @@ -7304,11 +7616,11 @@ sub get { if (($b_arm || $b_mips) && !$use{'soc-bluetooth'} && !$use{'pci-tool'}){ # do nothing, but keep the test conditions to force # the non arm case to always run - #my $type = ($b_arm) ? 'arm' : 'mips'; - #my $key = 'Message'; - #push(@rows,{ - #main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), - #},); + # my $type = ($b_arm) ? 'arm' : 'mips'; + # my $key = 'Message'; + # push(@rows,{ + # main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), + # },); } else { push(@rows,device_output()); @@ -7332,9 +7644,10 @@ sub get { sub device_output { eval $start if $b_log; + return if !$devices{'bluetooth'}; my ($bus_id,@rows); my ($j,$num) = (0,1); - foreach my $row (@devices_bluetooth){ + foreach my $row (@{$devices{'bluetooth'}}){ $num = 1; $bus_id = ''; $j = scalar @rows; @@ -7387,18 +7700,18 @@ sub device_output { $bus_id = "$row->[2].$row->[3]" if defined $row->[2] && defined $row->[3]; } push(@rows,advanced_output('pci',$bus_id)) if $bus_id; - #print "$row->[0]\n"; + # print "$row->[0]\n"; } eval $end if $b_log; return @rows; } sub usb_output { eval $start if $b_log; - return if !@usb_bluetooth; + return if !$usb{'bluetooth'}; my (@rows,$path_id,$product); my ($j,$num) = (0,1); - foreach my $row (@usb_bluetooth){ - #print Data::Dumper::Dumper $row; + foreach my $row (@{$usb{'bluetooth'}}){ + # print Data::Dumper::Dumper $row; $num = 1; $j = scalar @rows; # makre sure to reset, or second device trips last flag @@ -7438,51 +7751,85 @@ sub advanced_output { my ($type,$bus_id) = @_; eval $start if $b_log; my (@rows,@temp); - my ($j,$num,$k,$l,$m,$id,$id2) = (0,1,2,3,4,'',''); + my ($j,$num,$k,$l,$m,$n,$address,$id,$note,$tool) = (0,1,2,3,4,5,'','','',''); if (!$b_hci && $alerts{'hciconfig'}->{'action'} eq 'use'){ hciconfig_data(); + $tool = 'hciconfig'; } elsif (!$b_hci && $alerts{'bt-adapter'}->{'action'} eq 'use'){ bt_tool_data(); + $tool = 'bt-adapter'; } - #print "bid: $bus_id\n"; + if (!$b_rfk && -e '/sys/class/bluetooth/'){ + rfkill_data(); + $tool = 'rfkill' if !$tool; + } + # print "bid: $bus_id\n"; if ($type ne 'check'){ @temp = main::globber('/sys/class/bluetooth/*'); @temp = map {$_ = Cwd::abs_path($_);$_} @temp if @temp; - #print Data::Dumper::Dumper \@temp; + # print Data::Dumper::Dumper \@temp; @temp = grep {/$bus_id/} @temp if @temp; @temp = map {$_ =~ s|^/.*/||;$_;} @temp if @temp; - #print Data::Dumper::Dumper \@temp; + # print Data::Dumper::Dumper \@temp; } elsif ($type eq 'check' && %hci){ @temp = keys %hci; $id = '-ID'; - ($k,$l,$m) = (1,2,3); + ($k,$l,$m,$n) = (1,2,3,4); } if (@temp && %hci){ if ($hci{'alert'}){ - check_service(); # sets $service - $j = scalar @rows; - $rows[$j]->{main::key($num++,1,$k,'Report')} = ''; - $rows[$j]->{main::key($num++,0,$l,'bt-service')} = $service; - $rows[$j]->{main::key($num++,0,$l,'note')} = $hci{'alert'}; + if (keys %hci == 1) { + check_service(); # sets $service + $j = scalar @rows; + $rows[$j]->{main::key($num++,1,$k,'Report')} = $tool; + $rows[$j]->{main::key($num++,0,$l,'bt-service')} = $service; + $rows[$j]->{main::key($num++,0,$l,'note')} = $hci{'alert'}; + } + else { + $note = $hci{'alert'}; + } delete $hci{'alert'}; } foreach my $item (@temp){ if ($hci{$item}){ - $id2 = $item if $id; $j = scalar @rows; push(@rows,{ - main::key($num++,1,$k,'Report' . $id) => $id2, + main::key($num++,1,$k,'Report' . $id) => $tool, },); - $rows[$j]->{main::key($num++,0,$l,'ID')} = $item if !$id; - $rows[$j]->{main::key($num++,0,$l,'state')} = $hci{$item}->{'state'}; + if ($note){ + $rows[$j]->{main::key($num++,0,$l,'note')} = $note; + } + # synthesize for rfkill + if (!$hci{$item}->{'state'}){ + $hci{$item}->{'state'} = ($b_bluetooth) ? 'up' : 'down'; + } + $rows[$j]->{main::key($num++,0,$l,'ID')} = $item; + if (defined $hci{$item}->{'rf-index'} && + ($extra > 0 || $hci{$item}->{'state'} eq 'down')){ + $rows[$j]->{main::key($num++,0,$m,'rfk-id')} = $hci{$item}->{'rf-index'}; + } + $rows[$j]->{main::key($num++,1,$l,'state')} = $hci{$item}->{'state'}; # this only appears for hciconfig, bt-adapter does not run without bt service if (!$b_bluetooth || $hci{$item}->{'state'} eq 'down'){ - check_service(); # sets $service - $rows[$j]->{main::key($num++,0,$l,'bt-service')} = $service; + if (!$b_bluetooth || $hci{$item}->{'state'} eq 'down'){ + check_service(); # sets $service + $rows[$j]->{main::key($num++,0,$m,'bt-service')} = $service; + } + if ($hci{$item}->{'hard-blocked'}){ + $rows[$j]->{main::key($num++,1,$m,'rfk-block')} = ''; + $rows[$j]->{main::key($num++,0,$n,'hardware')} = $hci{$item}->{'hard-blocked'}; + $rows[$j]->{main::key($num++,0,$n,'software')} = $hci{$item}->{'soft-blocked'}; + } } - $rows[$j]->{main::key($num++,0,$l,'address')} = main::apply_filter($hci{$item}->{'address'}); + if (!$hci{$item}->{'address'} && $tool eq 'rfkill'){ + $address = main::row_defaults('recommends'); + } + else { + $address = main::apply_filter($hci{$item}->{'address'}); + } + $rows[$j]->{main::key($num++,0,$l,'address')} = $address; # lmp/hci version only hciconfig sadly if (defined $hci{$item}->{'lmp-version'} && (my $btv = bluetooth_version($hci{$item}->{'lmp-version'}))){ @@ -7501,15 +7848,15 @@ sub advanced_output { $rows[$j]->{main::key($num++,0,$m,'rev')} = $hci{$item}->{'hci-revision'}; } } -# if ($extra > 1 && $hci{$item}->{'discoverable'}){ -# $rows[$j]->{main::key($num++,1,$l,'discover')} = $hci{$item}->{'discoverable'}; -# if ($extra > 2 && $hci{$item}->{'discovering'}){ -# $rows[$j]->{main::key($num++,1,$m,'active')} = $hci{$item}->{'discovering'}; -# } -# } -# if ($extra > 1 && $hci{$item}->{'pairable'}){ -# $rows[$j]->{main::key($num++,0,$l,'pair')} = $hci{$item}->{'pairable'}; -# } + # if ($extra > 1 && $hci{$item}->{'discoverable'}){ + # $rows[$j]->{main::key($num++,1,$l,'discover')} = $hci{$item}->{'discoverable'}; + # if ($extra > 2 && $hci{$item}->{'discovering'}){ + # $rows[$j]->{main::key($num++,1,$m,'active')} = $hci{$item}->{'discovering'}; + # } + # } + # if ($extra > 1 && $hci{$item}->{'pairable'}){ + # $rows[$j]->{main::key($num++,0,$l,'pair')} = $hci{$item}->{'pairable'}; + # } # this data only from hciconfig if ($b_admin && ($hci{$item}->{'acl-mtu'} || $hci{$item}->{'sco-mtu'} || $hci{$item}->{'link-policy'})){ @@ -7537,7 +7884,7 @@ sub advanced_output { } } } - if (!$b_hci_error && ($alerts{'hciconfig'}->{'action'} ne 'use' && + if (!@rows && !$b_hci_error && ($alerts{'hciconfig'}->{'action'} ne 'use' && $alerts{'bt-adapter'}->{'action'} ne 'use')){ my $key = 'Report'; my $value = ''; @@ -7598,7 +7945,7 @@ sub bt_tool_data { } } if (!@data && !$b_bluetooth){ - $hci{'alert'} = main::row_defaults('bluetooth-down','bt-adapter'); + $hci{'alert'} = main::row_defaults('bluetooth-down'); } print Data::Dumper::Dumper \%hci if $dbg[27]; main::log_data('dump','%hci', \%hci) if $b_log; @@ -7657,6 +8004,42 @@ sub hciconfig_data { main::log_data('dump','%hci', \%hci) if $b_log; eval $end if $b_log; } +sub rfkill_data { + eval $start if $b_log; + $b_rfk = 1; + my (@data,$id,$value); + if ($fake{'bluetooth'}){ + my $file; + $file = ""; + @data = main::reader($file,'strip'); + } + else { + # /state is the state of rfkill, NOT bluetooth! + @data = main::globber('/sys/class/bluetooth/hci*/rfkill*/{hard,index,soft}'); + } + # print Data::Dumper::Dumper \@data; + main::log_data('dump','@data', \@data) if $b_log; + foreach (@data){ + $id = (split(/\//,$_))[4]; + if (m|/soft$|){ + $value = main::reader($_,'strip',0); + $hci{$id}->{'soft-blocked'} = ($value) ? 'yes': 'no'; + $hci{$id}->{'state'} = 'down' if $hci{$id}->{'soft-blocked'} eq 'yes'; + } + elsif (m|/hard$|){ + $value = main::reader($_,'strip',0); + $hci{$id}->{'hard-blocked'} = ($value) ? 'yes': 'no'; + $hci{$id}->{'state'} = 'down' if $hci{$id}->{'hard-blocked'} eq 'yes'; + } + elsif (m|/index$|){ + $value = main::reader($_,'strip',0); + $hci{$id}->{'rf-index'} = $value; + } + } + print Data::Dumper::Dumper \%hci if $dbg[27]; + main::log_data('dump','%hci', \%hci) if $b_log; + eval $end if $b_log; +} sub check_service { eval $start if $b_log; if (!$b_service){ @@ -7678,9 +8061,9 @@ sub bluetooth_version { } } -## CpuData +## CpuItem { -package CpuData; +package CpuItem; sub get { eval $start if $b_log; @@ -7704,13 +8087,14 @@ sub full_output { my $num = 0; my ($b_flags,$b_speeds,$core_speeds_value,$flag_key,@flags,%cpu,@rows); my $sleep = $cpu_sleep * 1000000; - if ($b_hires){ - eval 'Time::HiRes::usleep( $sleep )'; - } - else { - select(undef, undef, undef, $cpu_sleep); - } - if (my $file = main::system_files('cpuinfo')){ + if (my $file = $system_files{'proc-cpuinfo'}){ + # bsd sleep is set before sysctl runs, same idea + if ($b_hires){ + eval 'Time::HiRes::usleep( $sleep )'; + } + else { + select(undef, undef, undef, $cpu_sleep); + } %cpu = cpuinfo_data($file,'full'); } elsif ($bsd_type ){ @@ -7794,6 +8178,9 @@ sub full_output { if ($extra > 1 && $properties{'l3-cache'}){ $rows[$j]->{main::key($num++,0,3,'L3')} = main::get_size($properties{'l3-cache'},'string'); } + if ($properties{'cache-check'}){ + $rows[$j]->{main::key($num++,0,3,'note')} = $properties{'cache-check'}; + } } if ($extra > 0 && !$show{'cpu-flag'}){ $j = scalar @rows; @@ -7832,7 +8219,7 @@ sub full_output { $b_speeds = 1; } else { - $core_speeds_value = main::row_defaults('cpu-speeds',scalar @speeds); + $core_speeds_value = main::row_defaults('cpu-speeds'); } } else { @@ -7936,16 +8323,16 @@ sub short_data { my $num = 0; my (%cpu,@data,%speeds); my $sys = '/sys/devices/system/cpu/cpufreq/policy0'; - my $sleep = $cpu_sleep * 1000000; - if ($b_hires){ - eval 'Time::HiRes::usleep( $sleep )'; - } - else { - select(undef, undef, undef, $cpu_sleep); - } # NOTE: : Permission denied, ie, this is not always readable # /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq - if (my $file = main::system_files('cpuinfo')){ + if (my $file = $system_files{'proc-cpuinfo'}){ + my $sleep = $cpu_sleep * 1000000; + if ($b_hires){ + eval 'Time::HiRes::usleep( $sleep )'; + } + else { + select(undef, undef, undef, $cpu_sleep); + } %cpu = cpuinfo_data($file,$type); } elsif ($bsd_type ){ @@ -8030,6 +8417,7 @@ sub cpuinfo_data { # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/mips/mips-mainusg-cpuinfo.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/ppc/ppc-debian-ppc64-cpuinfo.txt"; # $cpu{'type'} = 'elbrus'; # uncomment to test elbrus + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/elbrus-2c3/cpuinfo.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE1C-8.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2CDSP-4.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2S4-3-monocub.txt"; @@ -8054,7 +8442,7 @@ sub cpuinfo_data { $starter = $line[0]; # preserve case for one specific ARM issue $line[0] = lc($line[0]); if ($b_arm && !$b_first && $starter eq 'Processor' && $line[1] !~ /^\d+$/){ - #print "l1:$line[1]\n"; + # print "l1:$line[1]\n"; $cpu{'model_name'} = main::cleaner($line[1]); $cpu{'model_name'} = cpu_cleaner($cpu{'model_name'}); $cpu{'type'} = 'arm'; @@ -8070,7 +8458,7 @@ sub cpuinfo_data { $cpu{'processors'}->[$proc_count] = 0; $b_proc_int = 0; $b_first = 1; - #print "p0:\n"; + # print "p0:\n"; } } elsif ($line[0] eq 'processor'){ @@ -8080,13 +8468,13 @@ sub cpuinfo_data { $b_first = 1; $cpu{'processors'}->[$proc_count] = 0; $proc_count++; - #print "p1: $proc_count\n"; + # print "p1: $proc_count\n"; } else { if (!$b_proc_int){ $cpu{'processors'}->[$proc_count] = 0; $proc_count++; - #print "p2a: $proc_count\n"; + # print "p2a: $proc_count\n"; } if (!$b_first ){ # note: alternate: @@ -8098,7 +8486,7 @@ sub cpuinfo_data { } $cpu{'model_name'} = main::cleaner($line[1]); $cpu{'model_name'} = cpu_cleaner($cpu{'model'}); - #print "p2b:\n"; + # print "p2b:\n"; } $b_first = 1; } @@ -8153,7 +8541,7 @@ sub cpuinfo_data { elsif ( $line[0] eq 'cpu mhz' || $line[0] eq 'clock' ){ $speed = speed_cleaner($line[1]); $cpu{'processors'}->[$proc_count-1] = $speed; - #$ids[$phys_id]->[$die_id] = ([($speed)]); + #$ids[$phys_id]->[$die_id] = [$speed]; } elsif (!$cpu{'siblings'} && $line[0] eq 'siblings' ){ $cpu{'siblings'} = $line[1]; @@ -8163,18 +8551,18 @@ sub cpuinfo_data { } # increment by 1 for every new physical id we see. These are in almost all cases # separate cpus, not separate dies within a single cpu body. - elsif ( $line[0] eq 'physical id' ){ - if ( !defined $phys_holder || $phys_holder != $line[1] ){ + elsif ($line[0] eq 'physical id'){ + if (!defined $phys_holder || $phys_holder != $line[1]){ # only increment if not in array counter push(@phys_cpus, $line[1]) if ! grep {/$line[1]/} @phys_cpus; $phys_holder = $line[1]; - #print "pid: $line[1] ph: $phys_holder did: $die_id\n"; + # print "pid: $line[1] ph: $phys_holder did: $die_id\n"; $die_id = 0; #$die_holder = 0; } } - elsif ( $line[0] eq 'core id' ){ - #print "ph: $phys_holder did: $die_id l1: $line[1] s: $speed\n"; + elsif ($line[0] eq 'core id'){ + # print "ph: $phys_holder did: $die_id l1: $line[1] s: $speed\n"; # https://www.pcworld.com/article/3214635/components-processors/ryzen-threadripper-review-we-test-amds-monster-cpu.html if ($line[1] > 0 ){ $die_holder = $line[1]; @@ -8190,7 +8578,7 @@ sub cpuinfo_data { } $phys_holder = 0 if ! defined $phys_holder; $ids[$phys_holder]->[$die_id][$line[1]] = $speed; - #print "ph: $phys_holder did: $die_id l1: $line[1] s: $speed\n"; + # print "ph: $phys_holder did: $die_id l1: $line[1] s: $speed\n"; } if (!$cpu{'type'} && $line[0] eq 'vendor_id' ){ $cpu{'type'} = cpu_vendor($line[1]); @@ -8209,7 +8597,7 @@ sub cpuinfo_data { } elsif (!$cpu{'l3-cache'} && $line[0] eq 'l3 cache size'){ if ($line[1] =~ /(\d+\s*[KMG])i?B?$/){ - $cpu{'l2-cache'} = main::translate_size($1); + $cpu{'l3-cache'} = main::translate_size($1); } } if ($cpu{'type'} eq 'elbrus'){ @@ -8239,20 +8627,18 @@ sub cpuinfo_data { if (!$cpu{'flags'} && ($line[0] eq 'flags' || $line[0] eq 'features' )){ $cpu{'flags'} = $line[1]; } - } - if ( $extra > 0 && $type eq 'full' ){ - if ($line[0] eq 'bogomips'){ + if ($extra > 0 && $line[0] eq 'bogomips'){ # new arm shows bad bogomip value, so don't use it $cpu{'bogomips'} += $line[1] if $line[1] > 50; } } if ($b_admin ){ # note: not used unless maybe /sys data missing? - if ( !$cpu{'bugs'} && $line[0] eq 'bugs'){ + 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 (!$cpu{'microcode'} && $line[0] eq 'microcode'){ if ($line[1] =~ /0x/){ $cpu{'microcode'} = uc($line[1]); $cpu{'microcode'} =~ s/^0X//; @@ -8278,11 +8664,11 @@ sub cpuinfo_data { } } $cpu{'ids'} = (\@ids); - if ( $extra > 0 && !$cpu{'arch'} && $type ne 'short' ){ + if ($extra > 0 && !$cpu{'arch'} && $type ne 'short'){ ($cpu{'arch'},$cpu{'arch-note'}) = cpu_arch($cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'stepping'}); # cpu_arch comes from set_os() $cpu{'arch'} = $cpu_arch if (!$cpu{'arch'} && $cpu_arch && ($b_mips || $b_arm || $b_ppc)); - #print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n"; + # print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n"; } if (!$speeds{'cur-freq'}){ $cpu{'cur-freq'} = $cpu{'processors'}->[0]; @@ -8307,12 +8693,13 @@ sub sysctl_data { my (@ids,@line,%speeds,@working); my ($sep) = (''); my ($die_holder,$die_id,$phys_holder,$phys_id,$proc_count,$speed) = (0,0,0,0,0,0,0); - foreach (@sysctl){ + @{$sysctl{'cpu'}} = () if !$sysctl{'cpu'}; # don't want error next! + foreach (@{$sysctl{'cpu'}}){ @line = split(/\s*:\s*/, $_); next if ! $line[0]; # darwin shows machine, like MacBook7,1, not cpu # machdep.cpu.brand_string: Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz - if ( ($bsd_type ne 'darwin' && $line[0] eq 'hw.model' ) || + if (($bsd_type ne 'darwin' && $line[0] eq 'hw.model' ) || $line[0] eq 'machdep.cpu.brand_string' ){ # cut L2 cache/cpu max speed out of model string, if available # openbsd 5.6: AMD Sempron(tm) Processor 3400+ ("AuthenticAMD" 686-class, 256KB L2 cache) @@ -8353,7 +8740,8 @@ sub sysctl_data { $cpu{'l3-cache'} = $line[1]/1024; } # this is in mghz in samples - elsif ($line[0] eq 'hw.clockrate' || $line[0] eq 'hw.cpuspeed') { + elsif (!$cpu{'cur-freq'} && + ($line[0] eq 'hw.clockrate' || $line[0] eq 'hw.cpuspeed')){ $cpu{'cur-freq'} = $line[1]; } # these are in hz: 2400000000 @@ -8366,6 +8754,18 @@ sub sysctl_data { elsif ($line[0] eq 'hw.busfrequency_max') { $cpu{'max-freq'} = $line[1]/1000000; } + # FB seems to call freq something other than clock speed, unreliable + # eg: 1500 Mhz real shows as 2400 freq, which is wrong + # elsif ($line[0] =~ /^dev\.cpu\.([0-9]+)\.freq$/){ + # $speed = speed_cleaner($line[1]); + # $cpu{'processors'}->[$1] = $speed; + # } + # weird FB thing, freq can be wrong, so just count the cores and call it + # done. + elsif ($line[0] =~ /^dev\.cpu\.([0-9]+)\./ && + (!$cpu{'processors'} || !defined $cpu{'processors'}->[$1])){ + $cpu{'processors'}->[$1] = undef; + } elsif ($line[0] eq 'machdep.cpu.vendor') { $cpu{'type'} = cpu_vendor($line[1]); } @@ -8376,18 +8776,23 @@ sub sysctl_data { elsif ($line[0] eq 'hw.ncpu' ) { $cpu{'cores'} = $line[1]; } - # Freebsd does some voltage hacking to actually run at lowest listed frequencies. - # The cpu does not actually support all the speeds output here but works in freebsd. - elsif ($line[0] eq 'dev.cpu.0.freq_levels') { + # Freebsd does some voltage hacking to actually run at lowest listed + # frequencies. The cpu does not actually support all the speeds output + # here but works in freebsd. Disabled this, the freq appear to refer to + # something else, not cpu clock. Remove XXX to enable + elsif ($line[0] eq 'dev.cpu.0.freq_levelsXXX') { $line[1] =~ s/^\s+|\/[0-9]+|\s+$//g; if ( $line[1] =~ /[0-9]+\s+[0-9]+/ ) { + # get rid of -1 in FB: 2400/-1 2200/-1 2000/-1 1800/-1 + $line[1] =~ s|/-1||g; my @temp = split(/\s+/, $line[1]); $cpu{'max-freq'} = $temp[0]; $cpu{'min-freq'} = $temp[-1]; $cpu{'scalings'} = \@temp; } } - elsif (!$cpu{'cur-freq'} && $line[0] eq 'dev.cpu.0.freq' ) { + # Disabled w/XXX. this is almost certainly bad data, should not be used + elsif (!$cpu{'cur-freq'} && $line[0] eq 'dev.cpu.0.freqXXX' ) { $cpu{'cur-freq'} = $line[1]; } # the following have only been seen in DragonflyBSD data but thumbs up! @@ -8412,8 +8817,8 @@ sub sysctl_data { if ($phys_holder != $line[1] ){ $phys_id++; $phys_holder = $line[1]; - $ids[$phys_id] = ([(0)]); - $ids[$phys_id]->[$die_id] = ([(0)]); + $ids[$phys_id] = [0]; + $ids[$phys_id]->[$die_id] = [0]; } } elsif ( $line[0] eq 'hw.cpu_topology.cpu0.core_id' ){ @@ -8430,7 +8835,9 @@ sub sysctl_data { } } if (!$cpu{'flags'} || !$cpu{'family'}){ - my %dmesg_boot = dmesg_boot_data(); + my %dmesg_boot = dboot_data(); + # this core count may fix failed MT detection. + $cpu{'cores'} = $dmesg_boot{'cores'} if $dmesg_boot{'cores'}; $cpu{'flags'} = $dmesg_boot{'flags'} if !$cpu{'flags'}; $cpu{'family'} = $dmesg_boot{'family'} if !$cpu{'family'}; $cpu{'l1-cache'} = $dmesg_boot{'l1-cache'} if !$cpu{'l1-cache'}; @@ -8438,12 +8845,16 @@ sub sysctl_data { $cpu{'l3-cache'} = $dmesg_boot{'l3-cache'} if !$cpu{'l3-cache'}; $cpu{'microcode'} = $dmesg_boot{'microcode'} if !$cpu{'microcode'}; $cpu{'model_id'} = $dmesg_boot{'model_id'} if !$cpu{'model_id'}; + $cpu{'max-freq'} = $dmesg_boot{'max-freq'} if !$cpu{'max-freq'}; + $cpu{'min-freq'} = $dmesg_boot{'min-freq'} if !$cpu{'min-freq'}; + $cpu{'scalings'} = $dmesg_boot{'scalings'} if !$cpu{'scalings'}; + $cpu{'siblings'} = $dmesg_boot{'siblings'} if !$cpu{'siblings'}; $cpu{'stepping'} = $dmesg_boot{'stepping'} if !$cpu{'stepping'}; $cpu{'type'} = $dmesg_boot{'type'} if !$cpu{'type'}; } if ( $extra > 0 && !$cpu{'arch'} && $type ne 'short' ){ ($cpu{'arch'},$cpu{'arch-note'}) = cpu_arch($cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'stepping'}); - #print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n"; + # print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n"; } main::log_data('dump','%cpu',\%cpu) if $b_log; print Data::Dumper::Dumper \%cpu if $dbg[8]; @@ -8451,53 +8862,91 @@ sub sysctl_data { return %cpu; } -sub dmesg_boot_data { +sub dboot_data { eval $start if $b_log; - my (%values); + my ($max_freq,$min_freq,@scalings,%values); my ($family,$flags,$microcode,$model,$sep,$stepping,$type) = ('','','','','','',''); + my ($cores,$siblings) = (0,0); my ($l1,$l2,$l3) = (0,0,0); # this will be null if it was not readable - my $file = main::system_files('dmesg-boot'); - if ( @dmesg_boot){ - foreach (@dmesg_boot){ + my $file = $system_files{'dmesg-boot'}; + if ($dboot{'cpu'}){ + foreach (@{$dboot{'cpu'}}){ # can be ~Features/Features2/AMD Features - if ( /Features/ || ( $bsd_type eq "openbsd" && /^cpu0:\s*[a-z0-9]{2,3}(\s|,)[a-z0-9]{2,3}(\s|,)/i ) ) { + if (/Features/ || ( $bsd_type eq "openbsd" && + /^cpu0:\s*[a-z0-9]{2,3}(\s|,)[a-z0-9]{2,3}(\s|,)/i )) { my @line = split(/:\s*/, lc($_)); # free bsd has to have weird syntax: <....,> # Features2=0x1e98220b $line[1] =~ s/^[^<]*<|>[^>]*$//g; # then get rid of stuff $line[1] =~ s/<[^>]+>//g; + # handle corner case like ,EL3 32, + $line[1] =~ s/ (32|64)/_$1/g; # and replace commas with spaces $line[1] =~ s/,/ /g; $flags .= $sep . $line[1]; $sep = ' '; } + # cpu0:AMD E1-1200 APU with Radeon(tm) HD Graphics, 1398.66 MHz, 14-02-00 elsif (/^cpu0:\s*([^,]+),\s+([0-9\.]+\s*MHz),\s+([0-9a-f]+)-([0-9a-f]+)-([0-9a-f]+)/){ $type = cpu_vendor($1); $family = uc($3); $model = uc($4); $stepping = uc($5); - $family =~ s/^0+//; - $model =~ s/^0+//; - $stepping =~ s/^0+//; + $family =~ s/^0//; + $model =~ s/^0//; + $stepping =~ s/^0//; # can be 00 } # note: cpu cache is in KiB MiB even though they call it KB and MB - elsif (/^cpu0:\s*[0-9\.]+[KMG]B\s/ && - /^cpu0:\s*(([0-9\.]+[KMG])i?B.*?\sI[\s-]?cache)?(,?\s*([0-9\.]+[KMG])i?B.*?\sD[\s-]?cache)?(,?\s*([0-9\s]+[KMG])i?B.*?\sL2[\s-]?cache)?(,?\s*([0-9\.]+[KMG])i?B.*?\sL3[\s-]?cache)?/){ - $l1 = main::translate_size($2) if $2; - $l2 = main::translate_size($6) if $6; - $l3 = main::translate_size($8) if $8; + # cpu31: 32KB 64b/line 8-way I-cache, 32KB 64b/line 8-way D-cache, 512KB 64b/line 8-way L2 cache + # 8-way means 1 per core, 16-way means 1/2 per core + elsif (/^cpu0:\s*[0-9\.]+[KMG]B\s/){ + # cpu0: 32KB 64b/line 4-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache + # cpu0:48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache + if (/\b([0-9\.]+[KMG])i?B\s\S+\s([0-9]+)-way\s(L1 \S+\s)?I[\s-]?cache/){ + $l1 = main::translate_size($1); + } + if (/\b([0-9\.]+[KMG])i?B\s\S+\s([0-9]+)-way\sD[\s-]?cache/){ + # do nothing, we aren't going to use the D cache + } + if (/\b([0-9\.]+[KMG])i?B\s\S+\s([0-9]+)-way\sL2[\s-]?cache/){ + $l2 = main::translate_size($1); + } + if (/\b([0-9\.]+[KMG])i?B\s\S+\s([0-9]+)-way\sL3[\s-]?cache/){ + $l3 = main::translate_size($1); + } } - elsif (/^~*Origin:\s*(.+?)[\s,]+(Id\s*=\s*(0x)?([0-9a-f]+)[\s,]*)?(Family\s*=\s*(0x)?([a-f0-9]+)[\s,]*)?(Model\s*=\s*(0x)([a-f0-9]+)[\s,]*)?(Stepping\s*=\s*(0x)?([0-9a-f]+))?/){ - $type = cpu_vendor($1) if $1; - $microcode = ($3) ? uc($4) : $4; - $family = ($6) ? uc($7) : $7; - $model = ($9) ? uc($10) : $10; - $stepping = ($12) ? uc($13) : $13; + elsif (/^~Origin:(.+?)[\s,]+(Id|Family|Model|Stepping)/){ + $type = cpu_vendor($1); + if (/\bId\s*=\s*(0x)?([0-9a-f]+)\b/){ + $microcode = ($1) ? uc($2) : $2; + } + if (/\bFamily\s*=\s*(0x)?([a-f0-9]+)\b/){ + $family = ($1) ? uc($2) : $2; + } + if (/\bModel\s*=\s*(0x)?([a-f0-9]+)\b/){ + $model = ($1) ? uc($2) : $2; + } + # they don't seem to use hex for steppings, so convert it + if (/\bStepping\s*=\s*(0x)?([0-9a-f]+)\b/){ + $stepping = (!$1) ? uc(sprintf("%X", $2)) : $2; + } } - elsif (/^(ioapic|pci)/){ - last; + elsif (/^cpu0:.*?[0-9\.]+\s?MHz:\sspeeds:\s(.*?)\s?MHz/){ + @scalings = split(/[,\s]+/,$1); + $min_freq = $scalings[-1]; + $max_freq = $scalings[0]; + } + # 2 core MT Intel Core/Rzyen similar, use smt 0 as trigger to count: + # cpu2:smt 0, core 1, package 0 + # cpu3:smt 1, core 1, package 0 + ## but: older AMD Athlon 2 core: + # cpu0:smt 0, core 0, package 0 + # cpu0:smt 0, core 0, package 1 + elsif (/cpu([0-9]+):smt\s([0-9]+),\score\s([0-9]+)(,\spackage\s([0-9]+))?/){ + $siblings = $1 + 1; + $cores += 1 if $2 == 0; } } if ($flags){ @@ -8506,18 +8955,23 @@ sub dmesg_boot_data { } } else { - if ( $file && ! -r $file ){ + if ($file && ! -r $file){ $flags = main::row_defaults('dmesg-boot-permissions'); } } %values = ( + 'cores' => $cores, 'family' => $family, 'flags' => $flags, 'l1-cache' => $l1, 'l2-cache' => $l2, 'l3-cache' => $l3, + 'max-freq' => $max_freq, 'microcode' => $microcode, + 'min-freq' => $min_freq, 'model_id' => $model, + 'scalings' => \@scalings, + 'siblings' => $siblings, 'stepping' => $stepping, 'type' => $type, ); @@ -8525,7 +8979,7 @@ sub dmesg_boot_data { eval $end if $b_log; return %values; } -sub cpu_dmi_data { +sub dmidecode_data { eval $start if $b_log; return if !@dmi; my %dmi_data = ('L1' => 0, 'L2' => 0,'L3' => 0, 'ext-clock' => undef, 'socket' => undef, @@ -8574,12 +9028,12 @@ sub cpu_dmi_data { # Sometimes shows as CPU Socket... if ($value =~ /^Socket Designation:\s*(CPU\s*Socket|Socket)?[\s-]*(.*)$/i){ $upgrade = main::dmi_cleaner($2) if $2 !~ /(cpu|[mg]hz|onboard|socket|@|^#?[0-9]$)/i; - #print "$socket_temp\n"; + # print "$socket_temp\n"; } # normally we prefer this value, but sometimes it's garbage # older systems often show: Upgrade: ZIF Socket which is a generic term, legacy elsif ($value =~ /^Upgrade:\s*(CPU\s*Socket|Socket)?[\s-]*(.*)$/i){ - #print "$2\n"; + # print "$2\n"; $socket = main::dmi_cleaner($2) if $2 !~ /(ZIF|\bslot\b)/i; } # seen: Voltage: 5.0 V 2.9 V @@ -8619,6 +9073,7 @@ sub cpu_dmi_data { sub cpu_properties { my ($cpu) = @_; my ($b_amd_zen,$b_epyc,$b_ht,$b_elbrus,$b_intel,$b_ryzen,$b_xeon); + my ($cores_x,$cache_check) = (1,''); if ($cpu->{'type'} ){ if ($cpu->{'type'} eq 'intel'){ $b_intel = 1; @@ -8641,55 +9096,37 @@ sub cpu_properties { $b_elbrus = 1; } } - #my @dies = $phys[0]->[0]; + # my @dies = $phys[0]->[0]; my @phys = @{$cpu->{'ids'}}; - my $phyical_count = 0; - #my $phyical_count = scalar @phys; + my $physical_count = 0; + # my $physical_count = scalar @phys; my @processors; my ($speed,$speed_key); # handle case where cpu reports say, phys id 0, 2, 4, 6 [yes, seen it] foreach (@phys) { - $phyical_count++ if $_; + $physical_count++ if $_; } # count unique processors ## # note, this fails for intel cpus at times @processors = @{$cpu->{'processors'}}; - #print ref $cpu->{'processors'}, "\n"; + # print ref $cpu->{'processors'}, "\n"; my $processors_count = scalar @processors; - #print "p count:$processors_count\n"; - #print Data::Dumper::Dumper \@processors; + # print "p count:$processors_count\n"; + # print Data::Dumper::Dumper \@processors; # $cpu_cores is per physical cpu my ($cpu_layout,$cpu_type,$min_max,$min_max_key) = ('','','',''); my ($dmi_max_speed,$dmi_speed,$ext_clock,$socket,$upgrade,$volts) = (undef); my ($l1_cache,$l2_cache,$l3_cache,$core_count,$cpu_cores,$die_count) = (0,0,0,0,0,0); # note: elbrus supports turning off cores, so we need to add one for cases where rounds to 0 or 1 less if ($b_elbrus && $processors_count){ - my @elbrus = elbrus_data($cpu->{'model_id'},$processors_count,$cpu->{'arch'}); + my @elbrus = elbrus_data($cpu->{'family'},$cpu->{'model_id'},$processors_count,$cpu->{'arch'}); $cpu_cores = $elbrus[0]; - $phyical_count = $elbrus[1]; + $physical_count = $elbrus[1]; $cpu->{'arch'} = $elbrus[2]; - # print 'model id: ' . $cpu->{'model_id'} . ' arch: ' . $cpu->{'arch'} . " cpc: $cpu_cores phyc: $phyical_count proc: $processors_count \n"; + # print 'model id: ' . $cpu->{'model_id'} . ' arch: ' . $cpu->{'arch'} . " cpc: $cpu_cores phyc: $physical_count proc: $processors_count \n"; } - $phyical_count ||= 1; # assume 1 if no id found, as with ARM - if ($extra > 1 || ($bsd_type && !$cpu->{'l2-cache'})){ - # note: dmidecode has one entry per cpu per cache type, so this already - # has done the arithmetic on > 1 cpus for L1 and L3. - my %cpu_dmi = cpu_dmi_data(); - $l1_cache = $cpu_dmi{'L1'} if $cpu_dmi{'L1'}; - # note: bsds often won't have L2 catch data found yet - $l2_cache = $cpu_dmi{'L2'} if !$cpu->{'l2-cache'} && $cpu_dmi{'L2'}; - $l3_cache = $cpu_dmi{'L3'} if $cpu_dmi{'L3'}; - # bsd sysctl can have these values so let's check just in case - $l1_cache = $cpu->{'l1-cache'} * $phyical_count if !$l1_cache && $cpu->{'l1-cache'}; - $l3_cache = $cpu->{'l3-cache'} * $phyical_count if !$l3_cache && $cpu->{'l3-cache'}; - $dmi_max_speed = $cpu_dmi{'max-speed'} if $cpu_dmi{'max-speed'}; - $socket = $cpu_dmi{'socket'} if $cpu_dmi{'socket'}; - $upgrade = $cpu_dmi{'upgrade'} if $cpu_dmi{'upgrade'}; - $dmi_speed = $cpu_dmi{'speed'} if $cpu_dmi{'speed'}; - $ext_clock = $cpu_dmi{'ext-clock'} if $cpu_dmi{'ext-clock'}; - $volts = $cpu_dmi{'volts'} if $cpu_dmi{'volts'}; - } - foreach my $die_ref ( @phys ){ + $physical_count ||= 1; # assume 1 if no id found, as with ARM + foreach my $die_ref (@phys){ next if ref $die_ref ne 'ARRAY'; $core_count = 0; $die_count = scalar @$die_ref; @@ -8703,7 +9140,7 @@ sub cpu_properties { foreach my $id (@$core_ref){ $core_count++ if defined $id && !$b_arm; } - #print 'cores: ' . $core_count, "\n"; + # print 'cores: ' . $core_count, "\n"; } } # this covers potentially cases where ARM cpus have > 1 die @@ -8712,22 +9149,22 @@ sub cpu_properties { # NOTE: amd A6-4400M APU 2 core reports: cores: 1 siblings: 2 # NOTE: AMD A10-5800K APU 4 core reports: cores: 2 siblings: 4 if (!$cpu_cores){ - if ($cpu->{'cores'} && ! $core_count || $cpu->{'cores'} >= $core_count){ + if ($cpu->{'cores'} && !$core_count || $cpu->{'cores'} >= $core_count){ $cpu_cores = $cpu->{'cores'}; } elsif ($core_count > $cpu->{'cores'}){ $cpu_cores = $core_count; } } - #print "cpu-c:$cpu_cores\n"; + # print "cpu-c:$cpu_cores\n"; #$cpu_cores = $cpu->{'cores'}; # like, intel core duo # NOTE: sadly, not all core intel are HT/MT, oh well... # xeon may show wrong core / physical id count, if it does, fix it. A xeon # may show a repeated core id : 0 which gives a fake num_of_cores=1 if ($b_intel){ - if ($cpu->{'siblings'} && $cpu->{'siblings'} > 1 && $cpu->{'cores'} && $cpu->{'cores'} > 1 ){ - if ( $cpu->{'siblings'}/$cpu->{'cores'} == 1 ){ + if ($cpu->{'siblings'} && $cpu->{'siblings'} > 1 && $cpu->{'cores'} && $cpu->{'cores'} > 1){ + if ($cpu->{'siblings'}/$cpu->{'cores'} == 1){ $b_intel = 0; $b_ht = 0; } @@ -8755,8 +9192,8 @@ sub cpu_properties { # } # final check, override the num of cores value if it clearly is wrong # and use the raw core count and synthesize the total instead of real count - if ( $cpu_cores == 0 && ($cpu->{'cores'} * $phyical_count > 1)){ - $cpu_cores = ($cpu->{'cores'} * $phyical_count); + if ( $cpu_cores == 0 && ($cpu->{'cores'} * $physical_count > 1)){ + $cpu_cores = ($cpu->{'cores'} * $physical_count); } # last check, seeing some intel cpus and vms with intel cpus that do not show any # core id data at all, or siblings. @@ -8779,11 +9216,25 @@ sub cpu_properties { $cpu->{'processors'}[$_] = 0; } } + # so far only OpenBSD has a way to detect MT cpus + if ($bsd_type){ + if ($cpu->{'siblings'}){ + $cores_x = $cpu_cores if $cpu_cores && $cpu_cores > 1; + } + # if no siblings we couldn't get MT status of cpu so can't trust cache + else { + $cache_check = main::row_defaults('note-check'); + } + } + # only elbrus shows L1 / L3 cache data in cpuinfo + else { + $cores_x = $cpu_cores if $cpu_cores && $cpu_cores > 1; + } # last test to catch some corner cases # seen a case where a xeon vm in a dual xeon system actually had 2 cores, no MT # so it reported 4 siblings, 2 cores, but actually only had 1 core per virtual cpu - #print "prc: $processors_count phc: $phyical_count coc: $core_count cpc: $cpu_cores\n"; - if (!$b_arm && $processors_count == $phyical_count*$core_count && $cpu_cores > $core_count){ + # print "prc: $processors_count phc: $physical_count coc: $core_count cpc: $cpu_cores\n"; + if (!$b_arm && $processors_count == $physical_count*$core_count && $cpu_cores > $core_count){ $b_ht = 0; #$b_xeon = 0; $b_intel = 0; @@ -8791,29 +9242,50 @@ sub cpu_properties { $core_count = 1; $cpu->{'siblings'} = 1; } - #print "pc: $processors_count s: $cpu->{'siblings'} cpuc: $cpu_cores corec: $core_count\n"; + if ($extra > 1 || ($bsd_type && !$cpu->{'l2-cache'})){ + # note: dmidecode has one entry per cpu per cache type, so this already + # has done the arithmetic on > 1 cpus for L1 and L3. + my %cpu_dmi = dmidecode_data(); + my $multi = ($bsd_type) ? $cpu_cores: 1; + $l1_cache = $cpu_dmi{'L1'} * $physical_count if $cpu_dmi{'L1'}; + # note: bsds often won't have L2 catch data found yet + $cpu->{'l2-cache'} = $cpu_dmi{'L2'} if !$cpu->{'l2-cache'} && $cpu_dmi{'L2'}; + $l3_cache = $cpu_dmi{'L3'} * $physical_count if $cpu_dmi{'L3'}; + # bsd sysctl can have these values so let's check just in case + $l1_cache = $cpu->{'l1-cache'} * $cores_x * $physical_count if !$l1_cache && $cpu->{'l1-cache'}; + # L3 is almost always per physical cpu, not per core + $l3_cache = $cpu->{'l3-cache'} * $physical_count if !$l3_cache && $cpu->{'l3-cache'}; + $cache_check = '' if !$l1_cache && !$cpu->{'l2-cache'} && !$l3_cache; # nothing to check! + $dmi_max_speed = $cpu_dmi{'max-speed'} if $cpu_dmi{'max-speed'}; + $socket = $cpu_dmi{'socket'} if $cpu_dmi{'socket'}; + $upgrade = $cpu_dmi{'upgrade'} if $cpu_dmi{'upgrade'}; + $dmi_speed = $cpu_dmi{'speed'} if $cpu_dmi{'speed'}; + $ext_clock = $cpu_dmi{'ext-clock'} if $cpu_dmi{'ext-clock'}; + $volts = $cpu_dmi{'volts'} if $cpu_dmi{'volts'}; + } + # print "pc: $processors_count s: $cpu->{'siblings'} cpuc: $cpu_cores corec: $core_count\n"; # Algorithm: # if > 1 processor && processor id (physical id) == core id then Multi threaded (MT) # if siblings > 1 && siblings == 2 * num_of_cores ($cpu->{'cores'}) then Multi threaded (MT) # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP) # if > 1 processor && processor ids (physical id) > 1 then Symmetric Multi Processing (SMP) # if = 1 processor then single core/processor Uni-Processor (UP) - if ( $processors_count > 1 || ( $b_intel && $cpu->{'siblings'} > 0 ) ) { + if ($processors_count > 1 || ($b_intel && $cpu->{'siblings'} > 0)) { # non-multicore MT - if ($processors_count == ($phyical_count * $cpu_cores * 2)){ - #print "mt:1\n"; + if ($processors_count == ($physical_count * $cpu_cores * 2)){ + # print "mt:1\n"; $cpu_type .= 'MT'; } # elsif ($b_xeon && $cpu->{'siblings'} > 1){ -# #print "mt:2\n"; +# # print "mt:2\n"; # $cpu_type .= 'MT'; # } elsif ($cpu->{'siblings'} > 1 && ($cpu->{'siblings'} == 2 * $cpu_cores )){ - #print "mt:3\n"; + # print "mt:3\n"; $cpu_type .= 'MT'; } # non-MT multi-core or MT multi-core - if ( ($processors_count == $cpu_cores ) || ($phyical_count < $cpu_cores)){ + if ( ($processors_count == $cpu_cores ) || ($physical_count < $cpu_cores)){ my $sep = ($cpu_type) ? ' ' : '' ; $cpu_type .= $sep . 'MCP'; } @@ -8823,7 +9295,7 @@ sub cpu_properties { $cpu_type .= $sep . 'MCM'; } # >1 cpu sockets active: Symetric Multi Processing - if ($phyical_count > 1){ + if ($physical_count > 1){ my $sep = ($cpu_type) ? ' ' : '' ; $cpu_type .= $sep . 'SMP'; } @@ -8831,29 +9303,31 @@ sub cpu_properties { else { $cpu_type = 'UP'; } - if ($phyical_count > 1){ - $cpu_layout = $phyical_count . 'x '; + if ($physical_count > 1){ + $cpu_layout = $physical_count . 'x '; } $cpu_layout .= count_alpha($cpu_cores) . 'Core'; $cpu_layout .= ' (' . $cpu->{'dies'}. '-Die)' if !$bsd_type && $cpu->{'dies'} > 1; - # the only possible change for bsds is if we can get phys counts in the future if (!$cpu->{'l2-cache'} ){ # do nothing } + # the only possible change for bsds is if we can get phys counts in the future + # Looks like Intel on bsd shows L2 per core, not total. Note: Pentium N3540 + # uses 2(not 4)xL2 cache size for 4 cores, sigh... you just can't win... elsif ($bsd_type){ - $l2_cache = $cpu->{'l2-cache'} * $phyical_count; + $l2_cache = $cpu->{'l2-cache'} * $cores_x * $physical_count; } # AMD SOS chips appear to report full L2 cache per core elsif ($cpu->{'type'} eq 'amd' && ($cpu->{'family'} eq '14' || $cpu->{'family'} eq '15' || $cpu->{'family'} eq '16')){ - $l2_cache = $cpu->{'l2-cache'} * $phyical_count; + $l2_cache = $cpu->{'l2-cache'} * $physical_count; } elsif ($cpu->{'type'} ne 'intel'){ - $l2_cache = $cpu->{'l2-cache'} * $cpu_cores * $phyical_count; + $l2_cache = $cpu->{'l2-cache'} * $cpu_cores * $physical_count; } ## note: this handles how intel reports L2, total instead of per core like AMD does # note that we need to multiply by number of actual cpus here to get true cache size else { - $l2_cache = $cpu->{'l2-cache'} * $phyical_count; + $l2_cache = $cpu->{'l2-cache'} * $physical_count; } if ($cpu->{'cur-freq'} && $cpu->{'min-freq'} && $cpu->{'max-freq'} ){ $min_max = "$cpu->{'min-freq'}/$cpu->{'max-freq'} MHz"; @@ -8887,6 +9361,7 @@ sub cpu_properties { } my %cpu_properties = ( 'bits-sys' => $bits_sys, + 'cache-check' => $cache_check, 'cpu-layout' => $cpu_layout, 'cpu-type' => $cpu_type, 'dmi-max-speed' => $dmi_max_speed, @@ -8904,10 +9379,10 @@ sub cpu_properties { 'l3-cache' => $l3_cache, ); main::log_data('dump','%cpu_properties',\%cpu_properties) if $b_log; - #print Data::Dumper::Dumper $cpu; - #print Data::Dumper::Dumper \%cpu_properties; - #my $dc = scalar @dies; - #print 'phys: ' . $pc . ' dies: ' . $dc, "\n"; + # print Data::Dumper::Dumper $cpu; + # print Data::Dumper::Dumper \%cpu_properties; + # my $dc = scalar @dies; + # print 'phys: ' . $pc . ' dies: ' . $dc, "\n"; eval $end if $b_log; return %cpu_properties; } @@ -8945,14 +9420,15 @@ sub cpu_speeds { } } if (!@speeds){ + # handle special case, FB, where we use undef for no processor speed found foreach (@$processors){ - if ($_ || $_ eq '0'){ + if ($_ || (defined $_ && $_ eq '0')){ $_ = sprintf("%.0f", $_); push(@speeds, $_); } } } - #print join('; ', @speeds), "\n"; + # print join('; ', @speeds), "\n"; eval $end if $b_log; return @speeds; } @@ -9053,24 +9529,28 @@ sub cpu_dies_sys { # returns: 0 - per cpu cores; 1 - phys cpu count; 2 - override model defaul names sub elbrus_data { eval $start if $b_log; - my ($model_id,$count,$arch) = @_; + my ($family_id,$model_id,$count,$arch) = @_; # 0: cores - my @cores; my @return = (0,1,$arch); - $cores[1] = 1; - $cores[2] = 1; - $cores[3] = 4; - $cores[4] = 2; - $cores[6] = 1; - $cores[7] = 8; - $cores[8] = 1; - $cores[9] = 8; - $cores[10] = 12; - $cores[11] = 16; - $cores[12] = 2; - if (main::is_numeric($model_id) && $cores[$model_id]){ - $return[0] = $cores[$model_id] ; - } + my %cores = ( + # key=family id + model id + '41' => 1, + '42' => 1, + '43' => 4, + '44' => 2, + '46' => 1, + '47' => 8, + '48' => 1, + '49' => 8, + '59' => 8, + '4A' => 12, + '4B' => 16, + '4C' => 2, + '6A' => 12, + '6B' => 16, + '6C' => 2, + ); + $return[0] = $cores{$family_id . $model_id} if $cores{$family_id . $model_id}; if ($return[0]){ $return[1] = ($count % $return[0]) ? int($count/$return[0]) + 1 : $count/$return[0]; } @@ -9129,8 +9609,8 @@ sub system_cpu_name { } # synthesize it, [4] will be like: cortex-a15-timer; sunxi-timer # so far all with this directory show soc name, not cpu name for timer - elsif (! -d '/sys/firmware/devicetree/base' && @devices_timer){ - foreach my $working (@devices_timer){ + elsif (! -d '/sys/firmware/devicetree/base' && $devices{'timer'}){ + foreach my $working (@{$devices{'timer'}}){ next if $working->[0] ne 'timer' || !$working->[4] || $working->[4] =~ /timer-mem$/; $working->[4] =~ s/(-system)?-timer$//; $compat = $working->[4]; @@ -9259,34 +9739,46 @@ sub cpu_arch { # note, to test uncoment $cpu{'type'} = Elbrus in proc/cpuinfo logic elsif ( $type eq 'elbrus'){ # E8CB - if ($family eq '4'){ - if ( $model eq '1' ) {$arch = 'Elbrus'} - elsif ( $model eq '2' ) {$arch = 'Elbrus-S'} - elsif ( $model eq '3' ) {$arch = 'Elbrus-4C'} - elsif ( $model eq '4' ) {$arch = 'Elbrus-2C+'} - elsif ( $model eq '6' ) {$arch = 'Elbrus-2CM'} - elsif ( $model eq '7' ) { - if ($stepping >= 2) {$arch = 'Elbrus-8C1';} - else {$arch = 'Elbrus-8C';} - } # note: stepping > 1 may be 8C1 - elsif ( $model eq '8' ) {$arch = 'Elbrus-1C+'} - # 8C2 morphed out of E8CV, but the two were the same die - elsif ( $model eq '9' ) { - $arch = 'Elbrus-8CV/8C2'; - $note = $check;} - elsif ( $model eq '10' ) {$arch = 'Elbrus-12C'} - elsif ( $model eq '11' ) {$arch = 'Elbrus-16C'} - elsif ( $model eq '12' ) {$arch = 'Elbrus-2C3'} + if ($family eq '4'){ + if ($model eq '1') {$arch = 'Elbrus'} + elsif ($model eq '2') {$arch = 'Elbrus-S'} + elsif ($model eq '3') {$arch = 'Elbrus-4C'} + elsif ($model eq '4') {$arch = 'Elbrus-2C+'} + elsif ($model eq '6') {$arch = 'Elbrus-2CM'} + elsif ($model eq '7') { + if ($stepping >= 2) {$arch = 'Elbrus-8C1';} + else {$arch = 'Elbrus-8C';} + } # note: stepping > 1 may be 8C1 + elsif ( $model eq '8' ) {$arch = 'Elbrus-1C+'} + # 8C2 morphed out of E8CV, but the two were the same die + elsif ( $model eq '9' ) { + $arch = 'Elbrus-8CV/8C2'; + $note = $check;} + elsif ($model eq 'A') {$arch = 'Elbrus-12C'} + elsif ($model eq 'B') {$arch = 'Elbrus-16C'} + elsif ($model eq 'C') {$arch = 'Elbrus-2C3'} + else { + $arch = 'Elbrus-??'; + $note = $check;} + } + elsif ($family eq '5'){ + if ($model eq '9') {$arch = 'Elbrus-8C2'} + else { + $arch = 'Elbrus-??'; + $note = $check;} + } + elsif ($family eq '6'){ + if ($model eq 'A') {$arch = 'Elbrus-12C'} + elsif ($model eq 'B') {$arch = 'Elbrus-16C'} + elsif ($model eq 'C') {$arch = 'Elbrus-2C3'} + else { + $arch = 'Elbrus-??'; + $note = $check;} + } else { $arch = 'Elbrus-??'; - $note = $check;} - } - elsif ($family eq '5'){ - if ($model eq '9') {$arch = 'Elbrus-8C2'} - else { - $arch = 'Elbrus-??'; - $note = $check;} - } + $note = $check; + } } elsif ( $type eq 'intel'){ if ($family eq '4'){ @@ -9402,7 +9894,7 @@ sub cpu_arch { sub count_alpha { my ($count) = @_; - #print "$count\n"; + # print "$count\n"; my @alpha = qw(Single Dual Triple Quad); if ($count > 4){ $count .= '-'; @@ -9459,9 +9951,9 @@ sub cpu_cleaner { } sub hex_and_decimal { my ($data) = @_; - $data ||= ''; + $data = '' if !defined $data; if ($data =~ /\S/){ - $data .= ' (' . hex($data) . ')' if hex($data) ne $data; + $data .= ' (' . hex($data) . ')' if hex($data) ne $data; } else { $data = 'N/A'; @@ -9470,9 +9962,9 @@ sub hex_and_decimal { } } -## DiskData +## DriveItem { -package DiskData; +package DriveItem; my ($b_hddtemp,$b_nvme,$smartctl_missing); my ($hddtemp,$nvme) = ('',''); my (@by_id,@by_path,@vendors); @@ -9484,15 +9976,15 @@ sub get { my ($type) = @_; $type ||= 'standard'; my $num = 0; - @data = disk_data($type); + @data = drive_data($type); # NOTE: if (@data){ if ($type eq 'standard'){ - push(@rows,totals_output(\@data)); - push(@rows,drives_output(\@data)) if $show{'disk'} && @data; - if ($bsd_type && !@dm_boot_disk && $type eq 'standard' && $show{'disk'} ){ + push(@rows,storage_output(\@data)); + push(@rows,drive_output(\@data)) if $show{'disk'} && @data; + if ($bsd_type && !$dboot{'disk'} && $type eq 'standard' && $show{'disk'} ){ $key1 = 'Drive Report'; - my $file = main::system_files('dmesg-boot'); + my $file = $system_files{'dmesg-boot'}; if ( $file && ! -r $file){ $val1 = main::row_defaults('dmesg-boot-permissions'); } @@ -9521,16 +10013,16 @@ sub get { $val1 = main::row_defaults('disk-data'); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } - #push(@rows,@data); + # push(@rows,@data); if ($show{'optical'} || $show{'optical-basic'}){ - push(@rows,OpticalData::get()); + push(@rows,OpticalItem::get()); } ($b_hddtemp,$b_nvme,$hddtemp,$nvme) = (undef,undef,undef,undef); (@by_id,@by_path) = (undef,undef); eval $end if $b_log; return @rows; } -sub totals_output { +sub storage_output { eval $start if $b_log; my ($disks) = @_; my (@rows); @@ -9539,14 +10031,14 @@ sub totals_output { push(@rows, { main::key($num++,1,1,'Local Storage') => '', }); - #print Data::Dumper::Dumper $disks; + # print Data::Dumper::Dumper $disks; $size = main::get_size($disks->[0]{'size'},'string','N/A'); if ($disks->[0]{'logical-size'}){ $rows[$j]->{main::key($num++,1,2,'total')} = ''; $rows[$j]->{main::key($num++,0,3,'raw')} = $size; $size = main::get_size($disks->[0]{'logical-size'},'string'); $size_value = $disks->[0]{'logical-size'}; - #print Data::Dumper::Dumper $disks; + # print Data::Dumper::Dumper $disks; $rows[$j]->{main::key($num++,1,3,'usable')} = $size; } else { @@ -9567,10 +10059,10 @@ sub totals_output { eval $end if $b_log; return @rows; } -sub drives_output { +sub drive_output { eval $start if $b_log; my ($disks) = @_; - #print Data::Dumper::Dumper $disks; + # print Data::Dumper::Dumper $disks; my ($b_smart_permissions,@rows,$smart_age,$smart_basic,$smart_fail); my ($num,$j) = (0,0); my ($id,$model,$size) = ('','',''); @@ -9588,7 +10080,7 @@ sub drives_output { $model = ($row->{'model'}) ? $row->{'model'}: 'N/A'; $id = ($row->{'id'}) ? "/dev/$row->{'id'}":'N/A'; $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; - #print Data::Dumper::Dumper $disks; + # print Data::Dumper::Dumper $disks; $j = scalar @rows; if (!$b_smart_permissions && $row->{'smart-permissions'}){ $b_smart_permissions = 1; @@ -9635,8 +10127,14 @@ sub drives_output { $rows[$j]->{main::key($num++,0,2,'rotation')} = $row->{'rotation'}; } if ($extra > 1){ - my $serial = main::apply_filter($row->{'serial'}); - $rows[$j]->{main::key($num++,0,2,'serial')} = $serial; + if (!$row->{'serial'} && $alerts{'bioctl'} && + $alerts{'bioctl'}->{'action'} eq 'permissions'){ + $row->{'serial'} = main::row_defaults('root-required'); + } + else { + $row->{'serial'} = main::apply_filter($row->{'serial'}); + } + $rows[$j]->{main::key($num++,0,2,'serial')} = $row->{'serial'}; if ($row->{'drive-serial'}){ $rows[$j]->{main::key($num++,0,2,'drive serial')} = main::apply_filter($row->{'drive-serial'}); } @@ -9650,10 +10148,19 @@ sub drives_output { if ($extra > 0 && $row->{'temp'}){ $rows[$j]->{main::key($num++,0,2,'temp')} = $row->{'temp'} . ' C'; } + if ($extra > 1 && $alerts{'bioctl'}){ + if (!$row->{'duid'} && $alerts{'bioctl'}->{'action'} eq 'permissions'){ + $rows[$j]->{main::key($num++,0,2,'duid')} = main::row_defaults('root-required'); + } + elsif ($row->{'duid'}) { + $rows[$j]->{main::key($num++,0,2,'duid')} = main::apply_filter($row->{'duid'}); + } + } # extra level tests already done if (defined $row->{'partition-table'}){ $rows[$j]->{main::key($num++,0,2,'scheme')} = $row->{'partition-table'}; } + if ($row->{'smart'} || $row->{'smart-error'}){ $j = scalar @rows; ## Basic SMART and drive info ## @@ -9705,14 +10212,14 @@ sub smart_output { eval $end if $b_log; } -sub disk_data { +sub drive_data { eval $start if $b_log; my ($type) = @_; my (@rows,@data,@devs); my $num = 0; my ($used) = (0); - PartitionData::partition_data() if !$loaded{'partitions'}; - RaidData::raid_data() if !$loaded{'raid'}; + PartitionItem::set_partitions() if !$loaded{'set-partitions'}; + RaidItem::raid_data() if !$loaded{'raid'}; foreach my $row (@partitions){ # don't count remote used, also, some cases mount # panfs is parallel NAS volume manager, need more data @@ -9735,7 +10242,7 @@ sub disk_data { @data = proc_data($used); } else { - @data = dmesg_boot_data($used); + @data = bsd_data($used); } if ($b_admin){ if ( $alerts{'smartctl'} && $alerts{'smartctl'}->{'action'} eq 'use'){ @@ -9755,7 +10262,7 @@ sub proc_data { my ($used) = @_; my (@data,@drives); my ($b_hdx,$logical_size,$size) = (0,0,0); - main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; + PartitionData::set() if !$bsd_type && !$loaded{'partition-data'}; foreach my $row (@proc_partitions){ if ( $row->[-1] =~ /^(fio[a-z]+|[hsv]d[a-z]+|(ada|mmcblk|n[b]?d|nvme[0-9]+n)[0-9]+)$/) { $b_hdx = 1 if $row->[-1] =~ /^hd[a-z]/; @@ -9806,7 +10313,7 @@ sub proc_data { 'size' => $size, 'used' => $used, }); - #print Data::Dumper::Dumper \@data; + # print Data::Dumper::Dumper \@data; if ($show{'disk'}){ unshift(@drives,@data); # print 'drives:', Data::Dumper::Dumper \@drives; @@ -9848,7 +10355,7 @@ sub proc_data_advanced { } } # scsi stuff - if ($file = main::system_files('scsi')){ + if ($file = $system_files{'proc-scsi'}){ @scsi = scsi_data($file); } # print 'drives:', Data::Dumper::Dumper $drives; @@ -9856,7 +10363,7 @@ sub proc_data_advanced { #next if $drives->[$i]{'id'} =~ /^hd[a-z]/; ($block_type,$firmware,$model,$partition_scheme, $serial,$vendor,$working_path) = ('','','','','','',''); - #print "$drives->[$i]{'id'}\n"; + # print "$drives->[$i]{'id'}\n"; @disk_data = disk_data_by_id("/dev/$drives->[$i]{'id'}"); main::log_data('dump','@disk_data', \@disk_data) if $b_log; if ($drives->[$i]{'id'} =~ /[sv]d[a-z]/){ @@ -9979,107 +10486,90 @@ sub proc_data_advanced { } } } - # print Data::Dumper::Dumper $drives; + main::log_data('dump','$drives',\$drives) if $b_log; + print Data::Dumper::Dumper $drives if $dbg[24]; eval $end if $b_log; return @$drives; } # camcontrol identify |grep ^serial (this might be (S)ATA specific) # smartcl -i |grep ^Serial # see smartctl; camcontrol devlist; gptid status; -sub dmesg_boot_data { +sub bsd_data { eval $start if $b_log; my ($used) = @_; - my (@data,@drives,@temp); - my ($id_holder,$i,$size,$working) = ('',0,0,0); - my $file = main::system_files('dmesg-boot'); - if (@dm_boot_disk){ - foreach (@dm_boot_disk){ - my @row = split(/:\s*/, $_); - next if ! defined $row[1]; - if ($id_holder ne $row[0]){ - $i++ if $id_holder; - # print "$i $id_holder $row[0]\n"; - $id_holder = $row[0]; - } - # no dots, note: ada2: 2861588MB BUT: ada2: 600.000MB/s - if (! exists $drives[$i]){ - $drives[$i]->{'id'} = $row[0]; - $drives[$i]->{'firmware'} = ''; - $drives[$i]->{'temp'} = ''; - $drives[$i]->{'type'} = ''; - $drives[$i]->{'vendor'} = ''; - } - #print "$_ i: $i\n"; - # openbsd/netbsd matches will often work - if ($row[1] =~ /(^|,\s*)([0-9\.]+\s*[MGTPE])i?B?[,.\s]+([0-9]+)\ssectors$|^{'block-physical'} = ($working/$3)*1024 if $3; - $size += $working if $working; - $drives[$i]->{'size'} = $working; - } - # don't set both, if smartctl installed, we want to use its data so having - # only one of logical/physical will trip use of smartctl values - if ($row[1] =~ /[\s,]+([0-9]+)\sbytes?[\s\/]sect/ ){ - #$drives[$i]->{'block-logical'} = $1; - $drives[$i]->{'block-physical'} = $1; - } - if ($row[2] && $row[2] =~ /<([^>]+)>/){ - $drives[$i]->{'model'} = $1 if $1; - $drives[$i]->{'type'} = 'removable' if $_ =~ /removable/; - # - my $count = ($drives[$i]->{'model'} =~ tr/,//); - if ($count && $count > 1){ - @temp = split(/,\s*/, $drives[$i]->{'model'}); - $drives[$i]->{'model'} = $temp[1]; - } - } - if ($row[2] && $row[2] =~ /\sserial\.(\S*)/){ - $drives[$i]->{'serial'} = $1; - } - if (!$drives[$i]->{'serial'} && $row[1] =~ /^Serial\sNumber\s(.*)/){ - $drives[$i]->{'serial'} = $1; - } - # these were mainly FreeBSD/Dragonfly matches - if (!$drives[$i]->{'size'} && $row[1] =~ /^([0-9]+\s*[KMGTPE])i?B?[\s,]/){ - $working = main::translate_size($1); - $size += $working if $working; - $drives[$i]->{'size'} = $working; - } - if ($row[1] =~ /(device$|^([0-9\.]+\s*[KMGT]B\s+)?<)/){ - $row[1] =~ s/\sdevice$//g; - $row[1] =~ /<([^>]*)>(\s(.*))?/; - $drives[$i]->{'model'} = $1 if $1; - $drives[$i]->{'spec'} = $3 if $3; - } - if ($row[1] =~ /^([0-9\.]+[MG][B]?\/s)/){ - $drives[$i]->{'speed'} = $1; - $drives[$i]->{'speed'} =~ s/\.[0-9]+// if $drives[$i]->{'speed'}; - } - $drives[$i]->{'model'} = main::disk_cleaner($drives[$i]->{'model'}); - my @device_data = device_vendor($drives[$i]->{'model'},''); - $drives[$i]->{'vendor'} = $device_data[0] if $device_data[0]; - $drives[$i]->{'model'} = $device_data[1] if $device_data[1]; - } - if (!$size){ - $size = main::row_defaults('data-bsd'); - } - } - elsif ($file && ! -r $file){ + my (@data,@drives,@softraid,@temp); + my ($i,$logical_size,$size,$working) = (0,0,0,0); + my $file = $system_files{'dmesg-boot'}; + DiskDataBSD::set() if !$loaded{'disk-data-bsd'}; + # we don't want non dboot disk data from gpart or disklabel + if ($file && ! -r $file){ $size = main::row_defaults('dmesg-boot-permissions'); } elsif (!$file){ $size = main::row_defaults('dmesg-boot-missing'); } + elsif (%disks_bsd){ + if ($sysctl{'softraid'}){ + @softraid = map {$_ =~ s/.*\(([^\)]+)\).*/$1/;$_} @{$sysctl{'softraid'}}; + } + foreach my $id (sort keys %disks_bsd){ + next if !$disks_bsd{$id} || !$disks_bsd{$id}->{'size'}; + $drives[$i]->{'id'} = $id; + $drives[$i]->{'firmware'} = ''; + $drives[$i]->{'temp'} = ''; + $drives[$i]->{'type'} = ''; + $drives[$i]->{'vendor'} = ''; + $drives[$i]->{'block-logical'} = $disks_bsd{$id}->{'block-logical'}; + $drives[$i]->{'block-physical'} = $disks_bsd{$id}->{'block-physical'}; + $drives[$i]->{'partition-table'} = $disks_bsd{$id}->{'scheme'}; + $drives[$i]->{'serial'} = $disks_bsd{$id}->{'serial'}; + $drives[$i]->{'size'} = $disks_bsd{$id}->{'size'}; + # don't count OpenBSD RAID/CRYPTO virtual disks! + if ($drives[$i]->{'size'} && (!@softraid || !(grep {$id eq $_} @softraid))){ + $size += $drives[$i]->{'size'} if $drives[$i]->{'size'}; + } + $drives[$i]->{'spec'} = $disks_bsd{$id}->{'spec'}; + $drives[$i]->{'speed'} = $disks_bsd{$id}->{'speed'}; + $drives[$i]->{'type'} = $disks_bsd{$id}->{'type'}; + # generate the synthetic model/vendor data + $drives[$i]->{'model'} = $disks_bsd{$id}->{'model'}; + if ($drives[$i]->{'model'}){ + my @device_data = device_vendor($drives[$i]->{'model'},''); + $drives[$i]->{'vendor'} = $device_data[0] if $device_data[0]; + $drives[$i]->{'model'} = $device_data[1] if $device_data[1]; + } + if ($disks_bsd{$id}->{'duid'}){ + $drives[$i]->{'duid'} = $disks_bsd{$id}->{'duid'}; + } + if ($disks_bsd{$id}->{'partition-table'}){ + $drives[$i]->{'partition-table'} = $disks_bsd{$id}->{'partition-table'}; + } + $i++; + } + # raw_logical[0] is total of all logical raid/lvm found + # raw_logical[1] is total of all components found. If this totally fails, + # and we end up with raw logical less than used, give up + if (@raw_logical && $size && $raw_logical[0] && + (!$used || $raw_logical[0] > $used)){ + $logical_size = ($size - $raw_logical[1] + $raw_logical[0]); + } + if (!$size){ + $size = main::row_defaults('data-bsd'); + } + } @data = ({ + 'logical-size' => $logical_size, + 'logical-free' => $raw_logical[2], 'size' => $size, 'used' => $used, }); - #main::log_data('dump','@data',\@data) if $b_log; + #main::log_data('dump','$data',\@data) if $b_log; if ( $show{'disk'} ){ push(@data,@drives); - # print 'drives:', Data::Dumper::Dumper \@drives; + # print 'data:', Data::Dumper::Dumper \@data; } - # print Data::Dumper::Dumper \@data; + main::log_data('dump','$data',\@data) if $b_log; + print Data::Dumper::Dumper \@data if $dbg[24]; eval $end if $b_log; return @data; } @@ -10088,7 +10578,8 @@ sub dmesg_boot_data { # make sure to update if fields added in smartctl_data() sub smartctl_fields { eval $start if $b_log; - my @data = ([ # age + my @data = ( + [ # age ['smart-gsense-error-rate-ar','g-sense error rate'], ['smart-media-wearout-a','media wearout'], ['smart-media-wearout-t','threshold'], @@ -10167,7 +10658,8 @@ sub smartctl_fields { ['smart-unknown-5-w','worst'], ['smart-unknown-5-t','threshold'], ['smart-unknown-5-f','alert'], - ]); + ] + ); eval $end if $b_log; return @data; } @@ -10181,24 +10673,30 @@ sub smartctl_data { next if !$data->[$i]{'id'}; ($b_attributes,$b_intel,$b_kingston,$splitter,$num,$a,$r) = (0,0,0,':\s*',0,0,1); %holder = (); - #print $data->[$i]{'id'},"\n"; + # print $data->[$i]{'id'},"\n"; # m2 nvme failed on nvme0n1 drive id: $id = $data->[$i]{'id'}; $id =~ s/n[0-9]+$// if $id =~ /^nvme/; + # openbsd needs the 'c' partition, which is the entire disk + $id .= 'c' if $bsd_type && $bsd_type eq 'openbsd'; $cmd = $alerts{'smartctl'}->{'path'} . " -AHi /dev/" . $id . ' 2>/dev/null'; @result = main::grabber("$cmd", '', 'strip'); main::log_data('dump','@result', \@result) if $b_log; # log before cleanup @result = grep {!/^(smartctl|Copyright|==)/} @result; print 'Drive:/dev/' . $id . ":\n", Data::Dumper::Dumper\@result if $dbg[12]; - if (scalar @result < 4 ){ + if (scalar @result < 5 ){ if (grep {/failed: permission denied/i} @result){ $data->[$i]{'smart-permissions'} = main::row_defaults('tool-permissions','smartctl'); } elsif (grep {/unknown usb bridge/i} @result){ $data->[$i]{'smart-error'} = main::row_defaults('smartctl-usb'); } + # can come later in output too elsif (grep {/A mandatory SMART command failed/i} @result){ - $data->[$i]{'smart-error'} = main::row_defaults('smartctl-command-failed'); + $data->[$i]{'smart-error'} = main::row_defaults('smartctl-command'); + } + elsif (grep {/open device.*Operation not supported by device/i} @result){ + $data->[$i]{'smart-error'} = main::row_defaults('smartctl-open'); } else { $data->[$i]{'smart-error'} = main::row_defaults('tool-unknown-error','smartctl'); @@ -10223,6 +10721,10 @@ sub smartctl_data { $split[$t] = (main::is_numeric($split[$t])) ? int($split[$t]) : 0; $split[$v] = (main::is_numeric($split[$v])) ? int($split[$v]) : 0; } + # can occur later in output so retest it here + if ($split[$a] =~ /A mandatory SMART command failed/i){ + $data->[$i]{'smart-error'} = main::row_defaults('smartctl-command'); + } ## DEVICE INFO ## if ($split[$a] eq 'Device Model'){ $b_intel = 1 if $split[$r] =~/\bintel\b/i; @@ -10553,7 +11055,7 @@ sub peripheral_data { if (@by_id){ foreach (@by_id) { if ("/dev/$id" eq Cwd::abs_path($_)){ - #print "$id here\n"; + # print "$id here\n"; if (/usb-/i){ $type = 'USB'; } @@ -10714,7 +11216,7 @@ sub set_vendors { ['(^MKN|Mushkin)','Mushkin','Mushkin',''], # MKNS # MU = Multiple_Flash_Reader too risky: |M[UZ][^L] HD103SI HD start risky # HM320II HM320II - ['(SAMSUNG|^MCG[0-9]+GC|^MCC|^MCBOE|\bEVO\b|^[GS]2 Portable|^DS20|^[DG]3 Station|^DUO\b|^P3|^[BC]GN|^[CD]JN|^BJ[NT]|^[BC]WB|^(HM|SP)[0-9]{2}|^MZMPC|^HD[0-9]{3}[A-Z]{2}$|^G[CD][1-9][QS]|^M[AB]G[0-9][FG]|SV[0-9]|E[A-Z][1-9]QT|YP\b)','SAMSUNG','Samsung',''], # maybe ^SM, ^HM + ['(SAMSUNG|^MCG[0-9]+GC|^MCC|^MCBOE|\bEVO\b|^[GS]2 Portable|^DS20|^[DG]3 Station|^DUO\b|^P3|^[BC]GN|^[CD]JN|^BJ[NT]|^[BC]WB|^(HM|SP)[0-9]{2}|^MZMPC|^HD[0-9]{3}[A-Z]{2}$|^G[CD][1-9][QS]|^M[AB]G[0-9][FG]|SV[0-9]|[BE][A-Z][1-9]QT|YP\b)','SAMSUNG','Samsung',''], # maybe ^SM, ^HM # Android UMS Composite? ['(SanDisk|^SDS[S]?[DQ]|^D[AB]4|^SL([0-9]+)G|^AFGCE|^ABLCD|^SDW[1-9]|^SEM[1-9]|^U3\b|^SU[0-9]|^DX[1-9]|^S[CD][0-9]{2}G|ULTRA\s(FIT|trek)|Clip Sport|Cruzer|^Extreme|iXpand)','SanDisk','SanDisk',''], # these are HP/Sandisk cobranded. DX110064A5xnNMRI ids as HP and Sandisc @@ -10738,7 +11240,7 @@ sub set_vendors { ['^(MAB[0-9])','^(HP\b|FUJITSU)','Fujitsu/HP',''], # note: 2012: wdc bought hgst ['^(HGST|Touro|54[15]0|7250)','^HGST','HGST (Hitachi)',''], # HGST HUA - ['^(Hitachi|HCS|HD[PST]|DK[0-9]|IC|HT|HU|HMS|HDE|0G[0-9])','^Hitachi','Hitachi',''], + ['^((ATA\s)?Hitachi|HCS|HD[PST]|DK[0-9]|IC|HT|HU|HMS|HDE|0G[0-9])','Hitachi','Hitachi',''], # vb: VB0250EAVER but clashes with vbox; HP_SSD_S700_120G ;GB0500EAFYL GB starter too generic? ['^(HP\b|[MV]B[0-6]|G[BJ][0-9]|DF[0-9]|F[BK]|0-9]|PSS|XR[0-9]{4}|c350|v[0-9]{3}[bgorw]$|x[0-9]{3}[w]$)','^HP','HP',''], ['^(Lexar|LSD|JumpDrive|JD\s?Firefly|WorkFlow)','^Lexar','Lexar',''], # mmc-LEXAR_0xb016546c; JD Firefly; @@ -10762,8 +11264,10 @@ sub set_vendors { ['^(Actions|HS USB Flash)','^Actions','Actions',''], ['^Addlink','^Addlink','Addlink',''], ['^(ADplus|SuperVer\b)','^ADplus','ADplus',''], - ['^ADTRON','^(ADTRON)','Adtron',''], + ['^ADTRON','^ADTRON','Adtron',''], ['^(Advantech|SQF)','^Advantech','Advantech',''], + ['^AEGO','^AEGO','AEGO',''], + ['^AFOX','^AFOX','AFOX',''], ['^(Agile|AGI)','^(AGI|Agile\s?Gear\s?Int[a-z]*)','AGI',''], ['^Aireye','^Aireye','Aireye',''], ['^Alcatel','^Alcatel','Alcatel',''], @@ -10821,7 +11325,7 @@ sub set_vendors { ['^DIGITAL\s?FILM','DIGITAL\s?FILM','Digital Film',''], ['^(Disney|PIX[\s]?JR)','^Disney','Disney',''], ['^(Doggo|DQ-|Sendisk|Shenchu)','^(doggo|Sendisk(.?Shenchu)?|Shenchu(.?Sendisk)?)','Doggo (SENDISK/Shenchu)',''], - ['^(Dogfish|Shark)','^Dogfish(\s*Technology)?','Dogfish Technolgy',''], + ['^(Dogfish|Shark)','^Dogfish(\s*Technology)?','Dogfish Technology',''], ['^DragonDiamond','^DragonDiamond','DragonDiamond',''], ['^DREVO\b','^DREVO','Drevo',''], # DX1100 is probably sandisk, but could be HP, or it could be hp branded sandisk @@ -10831,10 +11335,12 @@ sub set_vendors { ['^Eluktro','^Eluktronics','Eluktronics',''], ['^Emperor','^Emperor','Emperor',''], ['^Emtec','^Emtec','Emtec',''], + ['^ENE\b','^ENE','ENE',''], ['^Energy','^Energy','Energy',''], ['^eNova','^eNOVA','eNOVA',''], ['^Epson','^Epson','Epson',''], ['^(Etelcom|SSD051)','^Etelcom','Etelcom',''], + ['^EURS','^EURS','EURS',''], # NOTE: ESA3... may be IBM PCIe SAD card/drives ['^(EXCELSTOR|r technology)','^EXCELSTOR( TECHNO(LOGY)?)?','ExcelStor',''], ['^EZLINK','^EZLINK','EZLINK',''], @@ -10852,7 +11358,9 @@ sub set_vendors { ['^Galaxy\b','^Galaxy','Galaxy',''], ['^(Garmin|Fenix|Nuvi|Zumo)','^Garmin','Garmin',''], ['^Geil','^Geil','Geil',''], + ['^GelL','^GelL','GelL',''], # typo for Geil? GelL ZENITH R3 120GB ['^(Generic|UY[67])','^Generic','Generic',''], + ['^Getrich','^Getrich','Getrich',''], ['^Gigabyte','^Gigabyte','Gigabyte',''], # SSD ['^Gigastone','^Gigastone','Gigastone',''], ['^Gloway','^Gloway','Gloway',''], @@ -10886,7 +11394,7 @@ sub set_vendors { ['^Innovera','^Innovera','Innovera',''], ['^Intaiel','^Intaiel','Intaiel',''], ['^(INM|Integral|V\s?Series)','^Integral(\s?Memory)?','Integral Memory',''], - ['^(lntenso|Intenso|(Alu|Basic|Business|Micro|Mobile|Rainbow|Speed|Twister|Ultra) Line|Rainbow)','^Intenso','Intenso',''], + ['^(lntenso|Intenso|(Alu|Basic|Business|Micro|c?Mobile|Premium|Rainbow|Slim|Speed|Twister|Ultra) Line|Rainbow)','^Intenso','Intenso',''], ['^(Iomega|ZIP\b|Clik!)','^Iomega','Iomega',''], ['^JingX','^JingX','JingX',''], #JingX 120G SSD - not confirmed, but guessing ['^Jingyi','^Jingyi','Jingyi',''], @@ -10894,13 +11402,14 @@ sub set_vendors { ['^JMicron','^JMicron(\s?Tech(nology)?)?','JMicron Tech',''], #JMicron H/W raid ['^KimMIDI','^KimMIDI','KimMIDI',''], ['^Kimtigo','^Kimtigo','Kimtigo',''], + ['^Kingbank','^Kingbank','Kingbank',''], ['^Kingchux[\s-]?ing','^Kingchux[\s-]?ing','Kingchuxing',''], ['^(KingDian|NGF)','^KingDian','KingDian',''], ['^Kingfast','^Kingfast','Kingfast',''], ['^KingMAX','^KingMAX','KingMAX',''], ['^Kingrich','^Kingrich','KingrSU04Gich',''], - ['^KING\s?SHARE','^KING\s?SHARE','KingShare',''], - ['^(KingSpec|ACSC|KS[DQ]|NT-[0-9]|P4\b|PA18)','^KingSpec','KingSpec',''], + ['^KING\s?SHA\s?RE','^KING\s?SHA\s?RE','KingShare',''], + ['^(KingSpec|ACSC|KS[DQ]|N[ET]-[0-9]|P4\b|PA18)','^KingSpec','KingSpec',''], ['^KingSSD','^KingSSD','KingSSD',''], # kingwin docking, not actual drive ['^(EZD|EZ-Dock)','','Kingwin Docking Station',''], @@ -11013,6 +11522,7 @@ sub set_vendors { ['^STE[CK]','^STE[CK]','sTec',''], # wd bought this one ['^STmagic','^STmagic','STmagic',''], ['^STORFLY','^STORFLY','StorFly',''], + ['\dSUN\d','^SUN(\sMicrosystems)?','Sun Microsystems',''], ['^SUNEAST','^SUNEAST','SunEast',''], ['^SuperSSpeed','^SuperSSpeed','SuperSSpeed',''], # NOTE: F[MNETU] not reliable, g.skill starts with FM too: @@ -11033,6 +11543,7 @@ sub set_vendors { ['^Tele2','^Tele2','Tele2',''], ['^Teleplan','^Teleplan','Teleplan',''], ['^TEUTONS','^TEUTONS','TEUTONS',''], + ['^THU','^THU','THU',''], ['^Tigo','^Tigo','Tigo',''], ['^Timetec','^Timetec','Timetec',''], ['^TKD','^TKD','TKD',''], @@ -11050,7 +11561,7 @@ sub set_vendors { ['^(OOS[1-9]|Utania)','Utania','Utania',''], ['^U-TECH','U-TECH','U-Tech',''], ['^VBOX','','VirtualBox',''], - ['^(Verbatim|STORE N GO|Vi[1-9]|OTG\s?Tiny)','^Verbatim','Verbatim',''], + ['^(Verbatim|STORE\s?\'?N\'?\s?(FLIP|GO)|Vi[1-9]|OTG\s?Tiny)','^Verbatim','Verbatim',''], ['^V-GEN','^V-GEN','V-Gen',''], ['^(Victorinox|Swissflash)','^Victorinox','Victorinox',''], ['^(Visipro|SDVP)','^Visipro','Visipro',''], @@ -11092,7 +11603,7 @@ sub device_vendor { return if !$model; set_vendors() if !@vendors; # 0 - match pattern; 1 - replace pattern; 2 - vendor print; 3 - serial pattern - # Data URLs: inxi-resources.txt Section: DiskData device_vendor() + # Data URLs: inxi-resources.txt Section: DriveItem device_vendor() # $model = 'H10 HBRPEKNX0202A NVMe INTEL 512GB'; # $model = 'Patriot Memory'; foreach my $row (@vendors){ @@ -11179,10 +11690,10 @@ sub hdd_temp_sys { # seeing long lag to read temp input files for some reason # on some systems, just one one of them. my @data = main::globber("$path/hwmon/hwmon*/temp*_{input,label}"); - #print "device: $device\n"; + # print "device: $device\n"; foreach (sort @data){ - #print "file: $_\n"; - #print(main::reader($_,'',0),"\n"); + # print "file: $_\n"; + # print(main::reader($_,'',0),"\n"); $path = $_; # cleanup everything in front of temp, the path $path =~ s/^.*\///; @@ -11226,7 +11737,7 @@ sub block_data { # 0: logical block size 1: disk physical block size/partition block size; my @blocks = (0,0); my ($block_log,$block_size) = (0,0); - #my $path_size = "/sys/block/$id/size"; + # my $path_size = "/sys/block/$id/size"; my $path_log_block = "/sys/block/$id/queue/logical_block_size"; my $path_phy_block = "/sys/block/$id/queue/physical_block_size"; # legacy system path @@ -11246,7 +11757,7 @@ sub device_speed { my ($device) = @_; my ($b_nvme,$lanes,$speed,@data); my $working = Cwd::abs_path("/sys/class/block/$device"); - #print "$working\n"; + # print "$working\n"; if ($working){ my ($id); # slice out the ata id: @@ -11300,15 +11811,15 @@ sub device_speed { } } @data = ($speed,$lanes); - #print "$working $speed\n"; + # print "$working $speed\n"; eval $end if $b_log; return @data; } } -## GraphicData +## GraphicItem { -package GraphicData; +package GraphicItem; my $driver = ''; # we need this as a fallback in case no xorg log found my %graphics; sub get { @@ -11345,18 +11856,19 @@ sub get { sub device_output { eval $start if $b_log; + return if !$devices{'graphics'}; my (@rows); my ($j,$num) = (0,1); - foreach my $row (@devices_graphics){ + foreach my $row (@{$devices{'graphics'}}){ $num = 1; - #print "$row->[0] $row->[3]\n"; + # print "$row->[0] $row->[3]\n"; # not using 3D controller yet, needs research: |3D controller |display controller # note: this is strange, but all of these can be either a separate or the same # card. However, by comparing bus id, say: 00:02.0 we can determine that the # cards are either the same or different. We want only the .0 version as a valid # card. .1 would be for example: Display Adapter with bus id x:xx.1, not the right one next if $row->[3] != 0; - #print "$row->[0] $row->[3]\n"; + # print "$row->[0] $row->[3]\n"; $j = scalar @rows; $driver = $row->[9]; $driver ||= 'N/A'; @@ -11392,7 +11904,7 @@ sub device_output { if ($extra > 2 && $row->[1]){ $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->[1]; } - #print "$row->[0]\n"; + # print "$row->[0]\n"; } eval $end if $b_log; return @rows; @@ -11401,12 +11913,12 @@ sub usb_output { eval $start if $b_log; my (@rows,@ids,$driver,$path_id,$product,@temp2); my ($j,$num) = (0,1); - return if !@usb_graphics; - foreach my $row (@usb_graphics){ + return if !$usb{'graphics'}; + foreach my $row (@{$usb{'graphics'}}){ # these tests only work for /sys based usb data for now $num = 1; $j = scalar @rows; - # makre sure to reset, or second device trips last flag + # make sure to reset, or second device trips last flag ($driver,$path_id,$product) = ('','',''); $product = main::cleaner($row->[13]) if $row->[13]; $driver = $row->[15] if $row->[15]; @@ -11453,7 +11965,7 @@ sub display_output(){ if ($extra > 1 || $protocol eq 'wayland'){ set_compositor($protocol); } - if ( $b_display){ + if ($b_display){ display_data_x(); # currently barebones, wayland needs a lot more work if ($protocol && $protocol eq 'wayland' && !$graphics{'screens'}){ @@ -11470,15 +11982,15 @@ sub display_output(){ $graphics{'x-version'} = $graphics{'xorg-version'} if $graphics{'xorg-version'};; $graphics{'x-version'} = x_version() if !$graphics{'x-version'}; $graphics{'x-version'} = $graphics{'x-version-id'} if !$graphics{'x-version'}; - #print Data::Dumper::Dumper \%graphics; + # print Data::Dumper::Dumper \%graphics; if (%graphics){ my ($driver_missing,$resolution,$server_string) = ('','',''); # print "$graphics{'x-vendor'} $graphics{'x-version'} $graphics{'x-vendor-release'}","\n"; if ($graphics{'x-vendor'}){ my $version = ($graphics{'x-version'}) ? " $graphics{'x-version'}" : ''; - #$version = (!$version && $graphics{'x-vendor-release'}) ? " $graphics{'x-vendor-release'}" : ''; + # $version = (!$version && $graphics{'x-vendor-release'}) ? " $graphics{'x-vendor-release'}" : ''; $server_string = "$graphics{'x-vendor'}$version"; - #print "$server_string\n"; + # print "$server_string\n"; } elsif ($graphics{'x-version'}) { if ($graphics{'x-version'} =~ /^Xvesa/){ @@ -11516,7 +12028,7 @@ sub display_output(){ # located inside this directory, which is not readable unless you are root # Normally Arch gdm log is here: ~/.local/share/xorg/Xorg.1.log # $driver comes from the Device lines, and is just last fallback. - if ($driver){ + if ($driver && $driver ne 'N/A'){ if (-e '/var/lib/gdm' && !$b_root ){ $driver_missing = main::row_defaults('display-driver-na') . ' - ' . main::row_defaults('root-suggested'); } @@ -11604,7 +12116,7 @@ sub display_output(){ } } if ($main->{'monitors'}){ - #print $basic_count . '::' . $m_count, "\n"; + # print $basic_count . '::' . $m_count, "\n"; foreach my $monitor (@{$main->{'monitors'}}){ ($diag,$dpi,$hz,$resolution,$size) = (undef); if ($show{'graphic-basic'}){ @@ -11639,7 +12151,7 @@ sub display_output(){ $row[$row_key]->{main::key($num++,0,4,'hz')} = $hz if $hz; $dpi = ($monitor->{'dpi'}) ? $monitor->{'dpi'} : ''; $row[$row_key]->{main::key($num++,0,4,'dpi')} = $dpi if $dpi; - #print "$dpi :: $main->{'s-dpi'}\n"; + # print "$dpi :: $main->{'s-dpi'}\n"; if ($monitor->{'size-x'} && $monitor->{'size-y'}){ $size = $monitor->{'size-x'} . 'x' . $monitor->{'size-y'} . 'mm ('. $monitor->{'size-x-i'} . 'x' . $monitor->{'size-y-i'} . '")'; @@ -11676,12 +12188,12 @@ sub display_data_x { my ($screen_id,$screen,@working); my ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i); my @xdpyinfo = main::grabber("$program $display_opt 2>/dev/null","\n",'strip'); - #@xdpyinfo = map {s/^\s+//;$_} @xdpyinfo if @xdpyinfo; - #print join("\n",@xdpyinfo), "\n"; + # @xdpyinfo = map {s/^\s+//;$_} @xdpyinfo if @xdpyinfo; + # print join("\n",@xdpyinfo), "\n"; foreach (@xdpyinfo){ @working = split(/:\s+/, $_); next if ( ($graphics{'screens'} && $working[0] !~ /^(dimensions$|screen\s#)/ ) || !$working[0] ); - #print "$_\n"; + # print "$_\n"; if ($working[0] eq 'vendor string'){ $working[1] =~ s/The\s|\sFoundation//g; # some distros, like fedora, report themselves as the xorg vendor, @@ -11751,14 +12263,14 @@ sub display_data_x { push(@{$graphics{'screens'}}, $screen); } } - #print Data::Dumper::Dumper $graphics{'screens'}; + # print Data::Dumper::Dumper $graphics{'screens'}; if (my $program = main::check_program('xrandr')){ ($diagonal,$diagonal_m,$dpi) = (undef); ($screen_id,$screen,@working) = (undef); ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i) = (undef); my (@monitors,$monitor_id,$screen,$screen_id,@xrandr_screens); my @xrandr = main::grabber("$program $display_opt 2>/dev/null",'','strip'); - #$graphics{'dimensions'} = (\@dimensions); + # $graphics{'dimensions'} = (\@dimensions); # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle # multiple screens from different video cards foreach (@xrandr){ @@ -11810,11 +12322,11 @@ sub display_data_x { } } push(@xrandr_screens, \@monitors) if @monitors; - #print "xrand: " . Data::Dumper::Dumper \@xrandr_screens; + # print "xrand: " . Data::Dumper::Dumper \@xrandr_screens; my ($i) = (0); foreach my $main (@{$graphics{'screens'}}){ # print "h: " . Data::Dumper::Dumper $main; - #print $main->{'screen'}, "\n"; + # print $main->{'screen'}, "\n"; foreach my $screens (@xrandr_screens){ # print "d: " . Data::Dumper::Dumper $screens; if ($screens->[0]{'screen'} eq $main->{'screen'}){ @@ -11843,8 +12355,8 @@ sub display_data_wayland { # return as wayland-0 or 0? $graphics{'display-id'} =~ s/wayland-?//i; } - #print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17]; - #main::log_data('dump','@graphics{screens}',$graphics{'screens'}) if $b_log; + # print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17]; + # main::log_data('dump','@graphics{screens}',$graphics{'screens'}) if $b_log; eval $end if $b_log; } sub set_compositor { @@ -11896,13 +12408,13 @@ sub gl_output(){ eval $start if $b_log; my $num = 0; my (@row,$arg); - #print ("$b_display : $b_root\n"); + # print ("$b_display : $b_root\n"); if ( $b_display){ if (my $program = main::check_program('glxinfo')){ # NOTE: glxinfo -B is not always available, unfortunately my @glxinfo = main::grabber("$program $display_opt 2>/dev/null"); - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/graphics/glxinfo/glxinfo-ssh-centos.txt"; - #my @glxinfo = main::reader($file); + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/graphics/glxinfo/glxinfo-ssh-centos.txt"; + # my @glxinfo = main::reader($file); if (!@glxinfo){ my $type = 'display-console'; if ($b_root){ @@ -11916,7 +12428,7 @@ sub gl_output(){ }); return @row; } - #print join("\n", @glxinfo),"\n"; + # print join("\n", @glxinfo),"\n"; my $compat_version = ''; my ($b_compat,$b_nogl,@core_profile_version,@direct_render,@renderer, @opengl_version,@working); @@ -11927,9 +12439,9 @@ sub gl_output(){ if ($working[1]){ $working[1] = main::cleaner($working[1]); # Allow all mesas - #if ($working[1] =~ /mesa/i){ + # if ($working[1] =~ /mesa/i){ # - #} + # } } # note: there are cases where gl drivers are missing and empty # field value occurs. @@ -12045,9 +12557,7 @@ sub tty_data(){ if ($tty_working ne '' && (my $program = main::check_program('stty'))){ my $tty_arg = ($bsd_type) ? '-f' : '-F'; # handle vtnr integers, and tty ID with letters etc. - if (-e "/dev/tty$tty_working"){ - $tty_working = "tty$tty_working"; - } + $tty_working = "tty$tty_working" if -e "/dev/tty$tty_working"; $tty = (main::grabber("$program $tty_arg /dev/$tty_working size 2>/dev/null"))[0]; if ($tty){ my @temp = split(/\s+/, $tty); @@ -12062,7 +12572,7 @@ sub x_drivers { eval $start if $b_log; my ($driver,@driver_data,,%drivers); my ($alternate,$failed,$loaded,$sep,$unloaded) = ('','','','',''); - if (my $log = main::system_files('xorg-log')){ + if (my $log = $system_files{'xorg-log'}){ if ($fake{'xorg-log'}) { # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/Xorg.0-voyager-serena.log"; # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/loading-unload-failed-all41-mint.txt"; @@ -12074,16 +12584,16 @@ sub x_drivers { # list is from sgfxi plus non-free drivers, plus ARM drivers my $list = join('|', qw(amdgpu apm ark armsoc atimisc ati chips cirrus cyrix fbdev fbturbo fglrx geode glide glint - i128 i740 i810-dec100 i810e i810 i815 i830 i845 i855 i865 i915 i945 i965 - iftv imstt intel ivtv mach64 mesa mga modesetting - neomagic newport nouveau nsc nvidia nv openchrome r128 radeonhd radeon + i128 i740 i810-dec100 i810e i810 i815 i830 i845 i855 i865 i915 i945 + i965 iftv imstt intel ivtv mach64 mesa mga modesetting neomagic newport + nouveau nsc nvidia nv openchrome r128 radeonhd radeon rendition s3virge s3 savage siliconmotion sisimedia sisusb sis sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx tdfx tga trident tseng unichrome v4l vboxvideo vesa vga via vmware vmwgfx voodoo)); # it's much cheaper to grab the simple pattern match then do the expensive one # in the main loop. - #@xorg = grep {/Failed|Unload|Loading/} @xorg; + # @xorg = grep {/Failed|Unload|Loading/} @xorg; foreach (@xorg){ next if !/Failed|Unload|Loading/; # print "$_\n"; @@ -12107,10 +12617,10 @@ sub x_drivers { # which can occur. This is the driver that is actually driving the display. # note that xorg will often load several modules, like modesetting,fbdev,nouveau # NOTE: - #(II) UnloadModule: "nouveau" - #(II) Unloading nouveau - #(II) Failed to load module "nouveau" (already loaded, 0) - #(II) LoadModule: "modesetting" + # (II) UnloadModule: "nouveau" + # (II) Unloading nouveau + # (II) Failed to load module "nouveau" (already loaded, 0) + # (II) LoadModule: "modesetting" elsif (/Failed.*($list)\"?.*$/i ) { # Set driver to lower case because sometimes it will show as # RADEON or NVIDIA in the actual x start @@ -12173,8 +12683,8 @@ sub x_version { elsif ($program = main::check_program('Xvesa')){ @data = main::grabber("$program -version 2>&1"); } - #print join('^ ', @paths), " :: $program\n"; - #print Data::Dumper::Dumper \@data; + # print join('^ ', @paths), " :: $program\n"; + # print Data::Dumper::Dumper \@data; if (@data){ foreach (@data){ if (/^X.org X server/i){ @@ -12216,7 +12726,7 @@ sub display_compositor { ['gnome-shell','gnome-shell','','gnome-shell'], ['kwin_wayland','kwin_wayland','','kwin_wayland'], ['kwin_x11','kwin_x11','','kwin_x11'], - #['kwin','kwin','','kwin'], + # ['kwin','kwin','','kwin'], ['marco','marco','','marco'], ['muffin','muffin','','muffin'], ['mutter','mutter','','mutter'], @@ -12266,9 +12776,9 @@ sub display_compositor { } } -## LogicalData +## LogicalItem { -package LogicalData; +package LogicalItem; sub get { eval $start if $b_log; @@ -12276,17 +12786,17 @@ sub get { my $num = 0; if ($bsd_type){ $key1 = 'Message'; - $val1 = main::row_defaults('lvm-data-bsd'); + $val1 = main::row_defaults('logical-data-bsd',$uname[0]); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } else { - main::set_lsblk() if !$loaded{'lsblk'}; + LsblkData::set() if !$loaded{'lsblk'}; if ($fake{'logical'} || $alerts{'lvs'}->{'action'} eq 'use'){ - lvm_data() if !$loaded{'lvm-data'}; + lvm_data() if !$loaded{'logical-data'}; if (!@lvm){ my $key = 'Message'; # note: arch linux has a bug where lvs returns 0 if non root start - my $message = ($use{'logical-lvm'}) ? main::row_defaults('tool-permissions','lvs') : main::row_defaults('lvm-data',''); + my $message = ($use{'logical-lvm'}) ? main::row_defaults('tool-permissions','lvs') : main::row_defaults('logical-data',''); push(@rows, { main::key($num++,0,1,$key) => $message, },); @@ -12306,7 +12816,7 @@ sub get { $alerts{'lvs'}->{'action'} eq 'missing')){ my $key = 'Message'; push(@rows, { - main::key($num++,0,1,$key) => main::row_defaults('lvm-data',''), + main::key($num++,0,1,$key) => main::row_defaults('logical-data',''), },); } elsif ($alerts{'lvs'}->{'action'} ne 'use'){ @@ -12425,9 +12935,9 @@ sub components_recursive_output { elsif ($type eq 'lvm'){ ($l2,$l3) = (4+$indent,5+$indent); } - #print 'outside: ', scalar @$component, "\n", Data::Dumper::Dumper $component; + # print 'outside: ', scalar @$component, "\n", Data::Dumper::Dumper $component; foreach my $component (@$components){ - #print "inside: -n", Data::Dumper::Dumper $component->[$i]; + # print "inside: -n", Data::Dumper::Dumper $component->[$i]; $$j = scalar @$rows if $b_admin; my $id; if ($component->[0] =~ /^(bcache|dm-|md)[0-9]/){ @@ -12459,12 +12969,12 @@ sub components_recursive_output { sub general_data { eval $start if $b_log; my (@found,@general_data,%parent,$parent_fs); - main::set_proc_partitions() if !$loaded{'proc-partitions'}; + PartitionData::set('proc') if !$loaded{'partition-data'}; main::set_mapper() if !$loaded{'mapper'}; foreach my $row (@lsblk){ # bcache doesn't have mapped name: !$mapper{$row->{'name'}} || next if !$row->{'parent'}; - %parent = main::get_lsblk($row->{'parent'}); + %parent = LsblkData::get($row->{'parent'}); next if !$parent{'fs'}; if ($row->{'type'} && (($row->{'type'} eq 'crypt' || $row->{'type'} eq 'mpath' || $row->{'type'} eq 'multipath') || @@ -12495,7 +13005,7 @@ sub general_data { elsif ($row->{'type'} eq 'crypt'){ $type = 'Crypt'; } - #my $name = ($use{'filter-uuid'}) ? "luks-$filter_string" : $row->{'name'}; + # my $name = ($use{'filter-uuid'}) ? "luks-$filter_string" : $row->{'name'}; component_data($row->{'maj-min'},\@full_components); # print "$row->{'name'}\n", Data::Dumper::Dumper \@full_components; push(@general_data, { @@ -12517,18 +13027,18 @@ sub general_data { # note: called for disk totals, raid, and logical sub lvm_data { eval $start if $b_log; - $loaded{'lvm-data'} = 1; + $loaded{'logical-data'} = 1; my (@args,@data,%totals); @args = qw(vg_name vg_fmt vg_size vg_free lv_name lv_layout lv_size lv_kernel_major lv_kernel_minor segtype seg_count seg_start_pe seg_size_pe stripes devices raid_mismatch_count raid_sync_action raid_write_behind copy_percent); my $num = 0; - main::set_proc_partitions() if !$loaded{'proc-partitions'}; + PartitionData::set() if !$loaded{'partition-data'}; main::set_mapper() if !$loaded{'mapper'}; if ($fake{'logical'}){ - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lvm/lvs-test-1.txt"; - #@data = main::reader($file,'strip'); + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lvm/lvs-test-1.txt"; + # @data = main::reader($file,'strip'); } else { # lv_full_name: ar0-home; lv_dm_path: /dev/mapper/ar0-home @@ -12612,7 +13122,7 @@ sub component_recursive_data { # return @devices if !$b_admin; foreach my $device (@devices){ my ($mapped,$mm2,@part); - @part = main::get_proc_partition($device) if @proc_partitions; + @part = PartitionData::get($device) if @proc_partitions; $mm2 = $part[0] . ':' . $part[1] if @part; if ($device =~ /^(bcache|dm-|md)[0-9]+$/){ $mapped = $dmmapper{$device}; @@ -12628,15 +13138,15 @@ sub component_recursive_data { } } -## MachineData +## MachineItem { -package MachineData; +package MachineItem; sub get { eval $start if $b_log; my (%soc_machine,%data,@rows,$key1,$val1,$which); my $num = 0; - if ($bsd_type && @sysctl_machine && !$force{'dmidecode'} ){ + if ($bsd_type && $sysctl{'machine'} && !$force{'dmidecode'}){ %data = machine_data_sysctl(); if (%data){ @rows = machine_output(\%data); @@ -12647,7 +13157,7 @@ sub get { } } elsif ($bsd_type || $force{'dmidecode'}){ - if ( !$fake{'dmidecode'} && $alerts{'dmidecode'}->{'action'} ne 'use'){ + if (!$fake{'dmidecode'} && $alerts{'dmidecode'}->{'action'} ne 'use'){ $key1 = $alerts{'dmidecode'}->{'action'}; $val1 = $alerts{'dmidecode'}->{'message'}; $key1 = ucfirst($key1); @@ -12659,7 +13169,7 @@ sub get { } elsif (!$key1){ $key1 = 'Message'; - $val1 = main::row_defaults('machine-data',''); + $val1 = main::row_defaults('machine-data'); } } } @@ -12670,7 +13180,12 @@ sub get { } else { $key1 = 'Message'; - $val1 = main::row_defaults('machine-data-dmidecode',''); + if ($alerts{'dmidecode'}->{'action'} eq 'missing'){ + $val1 = main::row_defaults('machine-data-dmidecode'); + } + else { + $val1 = main::row_defaults('machine-data'); + } } } elsif (!$bsd_type) { @@ -12830,7 +13345,7 @@ sub machine_soc_output { my ($soc_machine) = @_; my ($key,@rows); my ($cont_sys,$ind_sys,$j,$num) = (1,1,0,0); - #print Data::Dumper::Dumper \%soc_machine; + # print Data::Dumper::Dumper \%soc_machine; # 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 ($soc_machine->{'device'} || $soc_machine->{'model'}){ @@ -12930,8 +13445,8 @@ sub machine_data_sys { sub machine_data_soc { eval $end if $b_log; my (%data,@temp); - if (my $file = main::system_files('cpuinfo')){ - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-shevaplug-1.2ghz.txt"; + if (my $file = $system_files{'proc-cpuinfo'}){ + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-shevaplug-1.2ghz.txt"; my @data = main::reader($file); foreach (@data){ if (/^(Hardware|machine)\s*:/i){ @@ -13141,9 +13656,9 @@ sub machine_data_dmi { # it uses hw. info from sysctl -a and bios info from dmesg.boot sub machine_data_sysctl { eval $start if $b_log; - my (%data,$vm); + my (%data,$product,$vendor,$vm); # ^hw\.(vendor|product|version|serialno|uuid) - foreach (@sysctl_machine){ + foreach (@{$sysctl{'machine'}}){ next if ! $_; my @item = split(':', $_); next if ! $item[1]; @@ -13187,7 +13702,7 @@ sub machine_data_sysctl { $data{'bios_rev'} = $1; $data{'firmware'} = 'BIOS' if $_ =~ /BIOS/; } - elsif ($item[1] =~ /^vendor\s(.*?)\sversion\s"?([\S]+)"?\sdate\s([\S]+)/ ){ + elsif ($item[1] =~ /^vendor\s(.*?)\sversion\s(.*?)\sdate\s([\S]+)/ ){ $data{'bios_vendor'} = $1; $data{'bios_version'} = $2; $data{'bios_date'} = $3; @@ -13205,12 +13720,13 @@ sub machine_data_sysctl { } } if ($data{'board_vendor'} || $data{'sys_vendor'} || $data{'board_name'} || $data{'product_name'}){ - my $vendor = $data{'sys_vendor'}; + $vendor = $data{'sys_vendor'}; $vendor = $data{'board_vendor'} if !$vendor; - my $product = $data{'product_name'}; + $product = $data{'product_name'}; $product = $data{'board_name'} if !$product; - $data{'device'} = get_device_vm($vendor,$product); } + # detections can be from other sources. + $data{'device'} = get_device_vm($vendor,$product); print Data::Dumper::Dumper \%data if $dbg[28]; main::log_data('dump','%data',\%data) if $b_log; eval $end if $b_log; @@ -13279,7 +13795,7 @@ sub get_device_vm { if (lc($vm_test) eq 'oracle'){ $vm = 'virtualbox'; } - elsif ( $vm_test ne 'none'){ + elsif ($vm_test ne 'none'){ $vm = $vm_test; } } @@ -13292,7 +13808,7 @@ sub get_device_vm { my @vm_data = main::grabber("$program 2>/dev/null"); if (@vm_data){ if (grep {/kqemu/i} @vm_data){$vm = 'kqemu'} - elsif (grep {/kvm/i} @vm_data){$vm = 'kvm'} + elsif (grep {/kvm|qumranet/i} @vm_data){$vm = 'kvm'} elsif (grep {/qemu/i} @vm_data){$vm = 'qemu'} } } @@ -13300,7 +13816,8 @@ sub get_device_vm { # this will catch many Linux systems and some BSDs if (!$vm || lc($vm) eq 'bochs' ) { # $device_vm is '' if nothing detected - my @vm_data = (@sysctl,@dmesg_boot,$device_vm); + my @vm_data = ($device_vm); + push(@vm_data,@{$dboot{'machine-vm'}}) if $dboot{'machine-vm'}; if (-e '/dev/disk/by-id'){ my @dev = glob('/dev/disk/by-id/*'); push(@vm_data,@dev); @@ -13311,18 +13828,33 @@ sub get_device_vm { elsif (grep {/vmware/i} @vm_data){ $vm = 'vmware'; } - elsif (grep {/Virtual HD/i} @vm_data){ + # needs to be first, because contains virtio;qumranet, grabber only gets + # first instance then stops, so make sure patterns are right. + elsif (grep {/(openbsd[\s-]vmm)/i} @vm_data){ + $vm = 'vmm'; + } + elsif (grep {/(\bhvm\b)/i} @vm_data){ + $vm = 'hvm'; + } + elsif (grep {/(qemu)/i} @vm_data){ + $vm = 'qemu'; + } + elsif (grep {/(\bkvm\b|qumranet|virtio)/i} @vm_data){ + $vm = 'kvm'; + } + elsif (grep {/Virtual HD|Microsoft.*Virtual Machine/i} @vm_data){ $vm = 'hyper-v'; } - if (!$vm && (my $file = main::system_files('cpuinfo'))){ + if (!$vm && (my $file = $system_files{'proc-cpuinfo'})){ my @info = main::reader($file); $vm = 'virtual-machine' if grep {/^flags.*hypervisor/} @info; } + # this may be wrong, confirm it if (!$vm && -e '/dev/vda' || -e '/dev/vdb' || -e '/dev/xvda' || -e '/dev/xvdb' ){ $vm = 'virtual-machine'; } } - if (!$vm && $product_name){ + if (!$vm && $product_name){ if ($product_name eq 'VMware'){ $vm = 'vmware'; } @@ -13345,9 +13877,9 @@ sub get_device_vm { } -## NetworkData +## NetworkItem { -package NetworkData; +package NetworkItem; my ($b_ip_run,@ifs_found); sub get { eval $start if $b_log; @@ -13362,12 +13894,24 @@ sub get { } push(@rows,usb_output()); # note: rasberry pi uses usb networking only - if (!@rows && ($b_arm || $b_mips)){ - my $type = ($b_arm) ? 'arm' : 'mips'; - my $key = 'Message'; - push(@rows, { - main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), - },); + if (!@rows){ + if ($b_arm || $b_mips){ + my $type = ($b_arm) ? 'arm' : 'mips'; + my $key = 'Message'; + push(@rows, { + main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), + },); + } + else { + my $key = 'Message'; + my $type = 'pci-card-data'; + if ($pci_tool && $alerts{$pci_tool}->{'action'} eq 'permissions'){ + $type = 'pci-card-data-root'; + } + push(@rows,{ + main::key($num++,0,1,$key) => main::row_defaults($type,''), + },); + } } if ($show{'network-advanced'}){ # @ifs_found = (); @@ -13389,12 +13933,13 @@ sub get { sub device_output { eval $start if $b_log; + return if !$devices{'network'}; my ($b_wifi,@rows,%holder); my ($j,$num) = (0,1); - foreach my $row (@devices_network){ + foreach my $row (@{$devices{'network'}}){ $num = 1; - #print "$row->[0] $row->[3]\n"; - #print "$row->[0] $row->[3]\n"; + # print "$row->[0] $row->[3]\n"; + # print "$row->[0] $row->[3]\n"; $j = scalar @rows; my $driver = $row->[9]; my $chip_id = "$row->[5]:$row->[6]"; @@ -13459,7 +14004,7 @@ sub device_output { } push(@rows,@data) if @data; } - #print "$row->[0]\n"; + # print "$row->[0]\n"; } # @rows = (); # we want to handle ARM errors in main get @@ -13478,10 +14023,10 @@ sub device_output { } sub usb_output { eval $start if $b_log; - return if !@usb_network; + return if !$usb{'network'}; my (@rows,@temp2,$b_wifi,$driver,$path,$path_id,$product,$type); my ($j,$num) = (0,1); - foreach my $row (@usb_network){ + foreach my $row (@{$usb{'network'}}){ $num = 1; ($driver,$path,$path_id,$product,$type) = ('','','','',''); $product = main::cleaner($row->[13]) if $row->[13]; @@ -13517,12 +14062,11 @@ sub usb_output { ($vendor,$chip) = ($temp[0],$temp[1]) if @temp; @data = advanced_data_sys($vendor,$chip,0,$b_wifi,$path,''); } - # NOTE: we need the driver.number, like wlp0 to get a match, and - # we can't get that from usb data, so we have to let it fall back down - # to the check function for BSDs. - #else { - # @data = advanced_data_bsd($row->[2],$b_wifi); - #} + # NOTE: we need the driver + driver nu, like wlp0 to get a match, + else { + $driver .= $row->[21] if defined $row->[21]; + @data = advanced_data_bsd($driver,$b_wifi); + } push(@rows,@data) if @data; } $j = scalar @rows; @@ -13556,7 +14100,7 @@ sub advanced_data_sys { $key = 'IF-ID'; ($cont_if,$ind_if) = (1,2); } - #print join('; ', @paths), $count, "\n"; + # print join('; ', @paths), $count, "\n"; foreach (@paths){ my ($data1,$data2,$duplex,$mac,$speed,$state); # for usb, we already know where we are @@ -13600,12 +14144,12 @@ sub advanced_data_sys { $path = "$_/operstate"; $state = main::reader($path,'',0) if -r $path; $state ||= 'N/A'; - #print "$speed \n"; + # print "$speed \n"; @row = ({ main::key($num++,1,$cont_if,$key) => $if, main::key($num++,0,$ind_if,'state') => $state, },); - #my $j = scalar @row - 1; + # my $j = scalar @row - 1; push(@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found)); # print "push: if: $if ifs: @ifs_found\n"; # no print out for wifi since it doesn't have duplex/speed data available @@ -13673,7 +14217,7 @@ sub advanced_data_bsd { $speed ||= 'N/A'; $state = $data[0]; $state ||= 'N/A'; - #print "$speed \n"; + # print "$speed \n"; @row = ({ main::key($num++,1,$cont_if,$key) => $if, main::key($num++,0,$ind_if,'state') => $state, @@ -13683,7 +14227,7 @@ sub advanced_data_bsd { # no print out for wifi since it doesn't have duplex/speed data available # note that some cards show 'unknown' for state, so only testing explicitly # for 'down' string in that to skip showing speed/duplex - if (!$b_wifi && $state ne 'down' && $state ne 'no'){ + if (!$b_wifi && $state ne 'down' && $state ne 'no network'){ # make sure the value is strictly numeric before appending Mbps $speed = ( main::is_int($speed) ) ? "$speed Mbps" : $speed; $row[0]->{main::key($num++,0,$ind_if,'speed')} = $speed; @@ -13739,7 +14283,7 @@ sub if_ip { },); last OUTER; } - #print "$data2->[0] $data2->[1]\n"; + # print "$data2->[0] $data2->[1]\n"; my ($ipv,$ip,$broadcast,$scope,$scope_id); $ipv = ($data2->[0])? $data2->[0]: 'N/A'; $ip = main::apply_filter($data2->[1]); @@ -13881,25 +14425,23 @@ sub check_wifi { } } -## OpticalData +## OpticalItem { -package OpticalData; - +package OpticalItem; sub get { eval $start if $b_log; my (%data,@rows,$key1,$val1); my $num = 0; if ($bsd_type){ - #%data = optical_data_bsd(); $key1 = 'Optical Report'; $val1 = main::row_defaults('optical-data-bsd'); @rows = ({main::key($num++,0,1,$key1) => $val1,}); - if ( @dm_boot_optical){ - %data = optical_data_bsd(); - @rows = optical_output(\%data) if %data; + if ($dboot{'optical'}){ + %data = drive_data_bsd(); + @rows = drive_output(\%data) if %data; } else{ - my $file = main::system_files('dmesg-boot'); + my $file = $system_files{'dmesg-boot'}; if ( $file && ! -r $file ){ $val1 = main::row_defaults('dmesg-boot-permissions'); } @@ -13914,8 +14456,8 @@ sub get { } } else { - %data = optical_data_linux(); - @rows = optical_output(\%data) if %data; + %data = drive_data_linux(); + @rows = drive_output(\%data) if %data; } if (!@rows){ $key1 = 'Message'; @@ -13925,71 +14467,71 @@ sub get { eval $end if $b_log; return @rows; } -sub optical_output { +sub drive_output { eval $start if $b_log; - my ($devices) = @_; + my ($drives) = @_; my (@rows); my $num = 0; my $j = 0; # build floppy if any - foreach my $key (sort keys %$devices){ - if ($devices->{$key}{'type'} eq 'floppy'){ + foreach my $key (sort keys %$drives){ + if ($drives->{$key}{'type'} eq 'floppy'){ push(@rows, { - main::key($num++,0,1,ucfirst($devices->{$key}{'type'})) => "/dev/$key", + main::key($num++,0,1,ucfirst($drives->{$key}{'type'})) => "/dev/$key", }); - delete $devices->{$key}; + delete $drives->{$key}; } } - foreach my $key (sort keys %$devices){ + foreach my $key (sort keys %$drives){ $j = scalar @rows; $num = 1; - my $vendor = $devices->{$key}{'vendor'}; + my $vendor = $drives->{$key}{'vendor'}; $vendor ||= 'N/A'; - my $model = $devices->{$key}{'model'}; + my $model = $drives->{$key}{'model'}; $model ||= 'N/A'; push(@rows, { - main::key($num++,1,1,ucfirst($devices->{$key}{'type'})) => "/dev/$key", + main::key($num++,1,1,ucfirst($drives->{$key}{'type'})) => "/dev/$key", main::key($num++,0,2,'vendor') => $vendor, main::key($num++,0,2,'model') => $model, }); if ($extra > 0){ - my $rev = $devices->{$key}{'rev'}; + my $rev = $drives->{$key}{'rev'}; $rev ||= 'N/A'; $rows[$j]->{ main::key($num++,0,2,'rev')} = $rev; } - if ($extra > 1 && $devices->{$key}{'serial'}){ - $rows[$j]->{ main::key($num++,0,2,'serial')} = main::apply_filter($devices->{$key}{'serial'}); + if ($extra > 1 && $drives->{$key}{'serial'}){ + $rows[$j]->{ main::key($num++,0,2,'serial')} = main::apply_filter($drives->{$key}{'serial'}); } - my $links = (@{$devices->{$key}{'links'}}) ? join(',', sort @{$devices->{$key}{'links'}}) : 'N/A' ; + my $links = (@{$drives->{$key}{'links'}}) ? join(',', sort @{$drives->{$key}{'links'}}) : 'N/A' ; $rows[$j]->{ main::key($num++,0,2,'dev-links')} = $links; if ($show{'optical'}){ $j = scalar @rows; - my $speed = $devices->{$key}{'speed'}; + my $speed = $drives->{$key}{'speed'}; $speed ||= 'N/A'; my ($audio,$multisession) = ('',''); - if (defined $devices->{$key}{'multisession'}){ - $multisession = ( $devices->{$key}{'multisession'} == 1 ) ? 'yes' : 'no' ; + if (defined $drives->{$key}{'multisession'}){ + $multisession = ( $drives->{$key}{'multisession'} == 1 ) ? 'yes' : 'no' ; } $multisession ||= 'N/A'; - if (defined $devices->{$key}{'audio'}){ - $audio = ( $devices->{$key}{'audio'} == 1 ) ? 'yes' : 'no' ; + if (defined $drives->{$key}{'audio'}){ + $audio = ( $drives->{$key}{'audio'} == 1 ) ? 'yes' : 'no' ; } $audio ||= 'N/A'; my $dvd = 'N/A'; my (@rw,$rws); - if (defined $devices->{$key}{'dvd'}){ - $dvd = ( $devices->{$key}{'dvd'} == 1 ) ? 'yes' : 'no' ; + if (defined $drives->{$key}{'dvd'}){ + $dvd = ( $drives->{$key}{'dvd'} == 1 ) ? 'yes' : 'no' ; } - if ($devices->{$key}{'cdr'}){ + if ($drives->{$key}{'cdr'}){ push(@rw, 'cd-r'); } - if ($devices->{$key}{'cdrw'}){ + if ($drives->{$key}{'cdrw'}){ push(@rw, 'cd-rw'); } - if ($devices->{$key}{'dvdr'}){ + if ($drives->{$key}{'dvdr'}){ push(@rw, 'dvd-r'); } - if ($devices->{$key}{'dvdram'}){ + if ($drives->{$key}{'dvdram'}){ push(@rw, 'dvd-ram'); } $rws = (@rw) ? join(',', @rw) : 'none' ; @@ -14002,21 +14544,21 @@ sub optical_output { main::key($num++,0,3,'rw') => $rws, }); if ($extra > 0 ){ - my $state = $devices->{$key}{'state'}; + my $state = $drives->{$key}{'state'}; $state ||= 'N/A'; $rows[$j]->{ main::key($num++,0,3,'state')} = $state; } } } - #print Data::Dumper::Dumper \%devices; + # print Data::Dumper::Dumper \%drives; eval $end if $b_log; return @rows; } -sub optical_data_bsd { +sub drive_data_bsd { eval $start if $b_log; - my (%devices,@rows,@temp); + my (%drives,@rows,@temp); my ($count,$i,$working) = (0,0,''); - foreach (@dm_boot_optical){ + foreach (@{$dboot{'optical'}}){ $_ =~ s/(cd[0-9]+)\(([^:]+):([0-9]+):([0-9]+)\):/$1:$2-$3.$4,/; my @row = split(/:\s*/, $_); next if ! defined $row[1]; @@ -14025,100 +14567,100 @@ sub optical_data_bsd { $working = $row[0]; } # no dots, note: ada2: 2861588MB BUT: ada2: 600.000MB/s - if (! exists $devices{$working}){ - $devices{$working}->{'links'} = ([]); - $devices{$working}->{'model'} = ''; - $devices{$working}->{'rev'} = ''; - $devices{$working}->{'state'} = ''; - $devices{$working}->{'vendor'} = ''; - $devices{$working}->{'temp'} = ''; - $devices{$working}->{'type'} = ($working =~ /^cd/) ? 'optical' : 'unknown'; + if (!exists $drives{$working}){ + $drives{$working}->{'links'} = []; + $drives{$working}->{'model'} = ''; + $drives{$working}->{'rev'} = ''; + $drives{$working}->{'state'} = ''; + $drives{$working}->{'vendor'} = ''; + $drives{$working}->{'temp'} = ''; + $drives{$working}->{'type'} = ($working =~ /^cd/) ? 'optical' : 'unknown'; } - #print "$_\n"; + # print "$_\n"; if ($bsd_type !~ /^(net|open)bsd$/){ if ($row[1] && $row[1] =~ /^<([^>]+)>/){ - $devices{$working}->{'model'} = $1; - $count = ($devices{$working}->{'model'} =~ tr/ //); + $drives{$working}->{'model'} = $1; + $count = ($drives{$working}->{'model'} =~ tr/ //); if ($count && $count > 1){ - @temp = split(/\s+/, $devices{$working}->{'model'}); - $devices{$working}->{'vendor'} = $temp[0]; + @temp = split(/\s+/, $drives{$working}->{'model'}); + $drives{$working}->{'vendor'} = $temp[0]; my $index = ($#temp > 2 ) ? ($#temp - 1): $#temp; - $devices{$working}->{'model'} = join(' ', @temp[1..$index]); - $devices{$working}->{'rev'} = $temp[-1] if $count > 2; + $drives{$working}->{'model'} = join(' ', @temp[1..$index]); + $drives{$working}->{'rev'} = $temp[-1] if $count > 2; } if ($show{'optical'}){ if (/\bDVD\b/){ - $devices{$working}->{'dvd'} = 1; + $drives{$working}->{'dvd'} = 1; } if (/\bRW\b/){ - $devices{$working}->{'cdrw'} = 1; - $devices{$working}->{'dvdr'} = 1 if $devices{$working}->{'dvd'}; + $drives{$working}->{'cdrw'} = 1; + $drives{$working}->{'dvdr'} = 1 if $drives{$working}->{'dvd'}; } } } if ($row[1] && $row[1] =~ /^Serial/){ @temp = split(/\s+/,$row[1]); - $devices{$working}->{'serial'} = $temp[-1]; + $drives{$working}->{'serial'} = $temp[-1]; } if ($show{'optical'}){ if ($row[1] =~ /^([0-9\.]+[MGTP][B]?\/s)/){ - $devices{$working}->{'speed'} = $1; - $devices{$working}->{'speed'} =~ s/\.[0-9]+//; + $drives{$working}->{'speed'} = $1; + $drives{$working}->{'speed'} =~ s/\.[0-9]+//; } if (/\bDVD[-]?RAM\b/){ - $devices{$working}->{'cdr'} = 1; - $devices{$working}->{'dvdram'} = 1; + $drives{$working}->{'cdr'} = 1; + $drives{$working}->{'dvdram'} = 1; } if ($row[2] && $row[2] =~ /,\s(.*)$/){ - $devices{$working}->{'state'} = $1; - $devices{$working}->{'state'} =~ s/\s+-\s+/, /; + $drives{$working}->{'state'} = $1; + $drives{$working}->{'state'} =~ s/\s+-\s+/, /; } } } else { if ($row[2] && $row[2] =~ /<([^>]+)>/){ - $devices{$working}->{'model'} = $1; - $count = ($devices{$working}->{'model'} =~ tr/,//); - #print "c: $count $row[2]\n"; + $drives{$working}->{'model'} = $1; + $count = ($drives{$working}->{'model'} =~ tr/,//); + # print "c: $count $row[2]\n"; if ($count && $count > 1){ - @temp = split(/,\s*/, $devices{$working}->{'model'}); - $devices{$working}->{'vendor'} = $temp[0]; - $devices{$working}->{'model'} = $temp[1]; - $devices{$working}->{'rev'} = $temp[2]; + @temp = split(/,\s*/, $drives{$working}->{'model'}); + $drives{$working}->{'vendor'} = $temp[0]; + $drives{$working}->{'model'} = $temp[1]; + $drives{$working}->{'rev'} = $temp[2]; } if ($show{'optical'}){ if (/\bDVD\b/){ - $devices{$working}->{'dvd'} = 1; + $drives{$working}->{'dvd'} = 1; } if (/\bRW\b/){ - $devices{$working}->{'cdrw'} = 1; - $devices{$working}->{'dvdr'} = 1 if $devices{$working}->{'dvd'}; + $drives{$working}->{'cdrw'} = 1; + $drives{$working}->{'dvdr'} = 1 if $drives{$working}->{'dvd'}; } if (/\bDVD[-]?RAM\b/){ - $devices{$working}->{'cdr'} = 1; - $devices{$working}->{'dvdram'} = 1; + $drives{$working}->{'cdr'} = 1; + $drives{$working}->{'dvdram'} = 1; } } } if ($show{'optical'}){ - #print "$row[1]\n"; + # print "$row[1]\n"; if (($row[1] =~ tr/,//) > 1){ @temp = split(/,\s*/, $row[1]); - $devices{$working}->{'speed'} = $temp[2]; + $drives{$working}->{'speed'} = $temp[2]; } } } } - main::log_data('dump','%devices',\%devices) if $b_log; - #print Data::Dumper::Dumper \%devices; + main::log_data('dump','%drives',\%drives) if $b_log; + # print Data::Dumper::Dumper \%drives; eval $end if $b_log; - return %devices; + return %drives; } -sub optical_data_linux { +sub drive_data_linux { eval $start if $b_log; - my (@data,%devices,@info,@rows); + my (@data,%drives,@info,@rows); @data = main::globber('/dev/dvd* /dev/cdr* /dev/scd* /dev/sr* /dev/fd[0-9]'); # Newer kernel is NOT linking all optical drives. Some, but not all. # Get the actual disk dev location, first try default which is easier to run, @@ -14130,36 +14672,36 @@ sub optical_data_linux { # possible fix: puppy has these in /mnt not /dev they say $working =~ s/\/(dev|media|mnt)\///; $_ =~ s/\/(dev|media|mnt)\///; - if (!defined $devices{$working}){ + if (!defined $drives{$working}){ my @temp = ($_ ne $working) ? ($_) : (); - $devices{$working}->{'links'} = \@temp; - $devices{$working}->{'type'} = ($working =~ /^fd/) ? 'floppy' : 'optical' ; + $drives{$working}->{'links'} = \@temp; + $drives{$working}->{'type'} = ($working =~ /^fd/) ? 'floppy' : 'optical' ; } else { - push(@{$devices{$working}->{'links'}}, $_) if $_ ne $working; + push(@{$drives{$working}->{'links'}}, $_) if $_ ne $working; } - #print "$working\n"; + # print "$working\n"; } if ($show{'optical'} && -e '/proc/sys/dev/cdrom/info'){ @info = main::reader('/proc/sys/dev/cdrom/info','strip'); } - #print join('; ', @data), "\n"; - foreach my $key (keys %devices){ - next if $devices{$key}->{'type'} eq 'floppy'; + # print join('; ', @data), "\n"; + foreach my $key (keys %drives){ + next if $drives{$key}->{'type'} eq 'floppy'; my $device = "/sys/block/$key/device"; if ( -d $device){ if (-r "$device/vendor"){ - $devices{$key}->{'vendor'} = main::reader("$device/vendor",'',0); - $devices{$key}->{'vendor'} = main::cleaner($devices{$key}->{'vendor'}); - $devices{$key}->{'state'} = main::reader("$device/state",'',0); - $devices{$key}->{'model'} = main::reader("$device/model",'',0); - $devices{$key}->{'model'} = main::cleaner($devices{$key}->{'model'}); - $devices{$key}->{'rev'} = main::reader("$device/rev",'',0); + $drives{$key}->{'vendor'} = main::reader("$device/vendor",'',0); + $drives{$key}->{'vendor'} = main::cleaner($drives{$key}->{'vendor'}); + $drives{$key}->{'state'} = main::reader("$device/state",'',0); + $drives{$key}->{'model'} = main::reader("$device/model",'',0); + $drives{$key}->{'model'} = main::cleaner($drives{$key}->{'model'}); + $drives{$key}->{'rev'} = main::reader("$device/rev",'',0); } } elsif ( -r "/proc/ide/$key/model"){ - $devices{$key}->{'vendor'} = main::reader("/proc/ide/$key/model",'',0); - $devices{$key}->{'vendor'} = main::cleaner($devices{$key}->{'vendor'}); + $drives{$key}->{'vendor'} = main::reader("/proc/ide/$key/model",'',0); + $drives{$key}->{'vendor'} = main::cleaner($drives{$key}->{'vendor'}); } if ($show{'optical'} && @info){ my $index = 0; @@ -14174,52 +14716,52 @@ sub optical_data_linux { last if ! $index; # index will be > 0 if it was found } elsif ($item =~/^drive speed:/) { - $devices{$key}->{'speed'} = $split[$index]; + $drives{$key}->{'speed'} = $split[$index]; } elsif ($item =~/^Can read multisession:/) { - $devices{$key}->{'multisession'}=$split[$index+1]; + $drives{$key}->{'multisession'}=$split[$index+1]; } elsif ($item =~/^Can read MCN:/) { - $devices{$key}->{'mcn'}=$split[$index+1]; + $drives{$key}->{'mcn'}=$split[$index+1]; } elsif ($item =~/^Can play audio:/) { - $devices{$key}->{'audio'}=$split[$index+1]; + $drives{$key}->{'audio'}=$split[$index+1]; } elsif ($item =~/^Can write CD-R:/) { - $devices{$key}->{'cdr'}=$split[$index+1]; + $drives{$key}->{'cdr'}=$split[$index+1]; } elsif ($item =~/^Can write CD-RW:/) { - $devices{$key}->{'cdrw'}=$split[$index+1]; + $drives{$key}->{'cdrw'}=$split[$index+1]; } elsif ($item =~/^Can read DVD:/) { - $devices{$key}->{'dvd'}=$split[$index+1]; + $drives{$key}->{'dvd'}=$split[$index+1]; } elsif ($item =~/^Can write DVD-R:/) { - $devices{$key}->{'dvdr'}=$split[$index+1]; + $drives{$key}->{'dvdr'}=$split[$index+1]; } elsif ($item =~/^Can write DVD-RAM:/) { - $devices{$key}->{'dvdram'}=$split[$index+1]; + $drives{$key}->{'dvdram'}=$split[$index+1]; } } } } - main::log_data('dump','%devices',\%devices) if $b_log; - #print Data::Dumper::Dumper \%devices; + main::log_data('dump','%drives',\%drives) if $b_log; + # print Data::Dumper::Dumper \%drives; eval $end if $b_log; - return %devices; + return %drives; } } -## PartitionData +## PartitionItem { -package PartitionData; +package PartitionItem; sub get { eval $start if $b_log; my (@rows,$key1,$val1); my $num = 0; - partition_data() if !$loaded{'partitions'}; + set_partitions() if !$loaded{'set-partitions'}; if (!@partitions) { $key1 = 'Message'; #$val1 = ($bsd_type && $bsd_type eq 'darwin') ? @@ -14228,16 +14770,16 @@ sub get { @rows = ({main::key($num++,0,1,$key1) => $val1,}); } else { - @rows = partition_output(); + @rows = create_output(); } eval $end if $b_log; return @rows; } -sub partition_output { +sub create_output { eval $start if $b_log; my $num = 0; my $j = 0; - my (%part,@rows,$dev,$dev_type,$fs,$percent,$raw_size,$size,$used); + my (@rows,$dev,$dev_type,$fs,$percent,$raw_size,$size,$used); # alpha sort for non numerics if ($show{'partition-sort'} !~ /^(percent-used|size|used)$/){ @partitions = sort { $a->{$show{'partition-sort'}} cmp $b->{$show{'partition-sort'}} } @partitions; @@ -14259,7 +14801,6 @@ sub partition_output { $percent = ''; $used = $size = (!$b_root) ? main::row_defaults('root-required') : main::row_defaults('partition-hidden'); } - %part = (); $fs = ($row->{'fs'}) ? lc($row->{'fs'}): 'N/A'; $dev_type = ($row->{'dev-type'}) ? $row->{'dev-type'} : 'dev'; $row->{'dev-base'} = '/dev/' . $row->{'dev-base'} if $dev_type eq 'dev' && $row->{'dev-base'}; @@ -14301,20 +14842,24 @@ sub partition_output { if ($extra > 0 && $row->{'dev-mapped'}){ $rows[$j]->{main::key($num++,0,3,'mapped')} = $row->{'dev-mapped'}; } - if ($show{'label'}){ - $row->{'label'} = main::apply_partition_filter('part', $row->{'label'}, '') if $use{'filter-label'}; - $rows[$j]->{main::key($num++,0,2,'label')} = ($row->{'label'}) ? $row->{'label'}: 'N/A'; - } - if ($show{'uuid'}){ - $row->{'uuid'} = main::apply_partition_filter('part', $row->{'uuid'}, '') if $use{'filter-uuid'}; - $rows[$j]->{main::key($num++,0,2,'uuid')} = ($row->{'uuid'}) ? $row->{'uuid'}: 'N/A'; + # add fs known to not use label/uuid here + if (($dev_type eq 'dev' && $fs !~ /^(ffs)$/) || + $row->{'label'} || $row->{'uuid'}){ + if ($show{'label'}){ + $row->{'label'} = main::apply_partition_filter('part', $row->{'label'}, '') if $use{'filter-label'}; + $rows[$j]->{main::key($num++,0,2,'label')} = ($row->{'label'}) ? $row->{'label'}: 'N/A'; + } + if ($show{'uuid'}){ + $row->{'uuid'} = main::apply_partition_filter('part', $row->{'uuid'}, '') if $use{'filter-uuid'}; + $rows[$j]->{main::key($num++,0,2,'uuid')} = ($row->{'uuid'}) ? $row->{'uuid'}: 'N/A'; + } } } eval $end if $b_log; return @rows; } -sub partition_data { +sub set_partitions { eval $start if $b_log; #return if $bsd_type && $bsd_type eq 'darwin'; # darwin has muated output, of course my (@data,@rows,@mount,@partitions_working,%part,@working); @@ -14323,15 +14868,16 @@ sub partition_data { my ($block_size,$blockdev,$dev_base,$dev_mapped,$dev_type,$fs,$id,$label, $maj_min,$percent_used,$raw_size,$replace,$size_available,$size,$test, $type,$uuid,$used); - $loaded{'partitions'} = 1; + $loaded{'set-partitions'} = 1; if ($b_admin){ # for partition block size $blockdev = $alerts{'blockdev'}->{'path'} if $alerts{'blockdev'}->{'path'}; } # for raw partition sizes, maj_min - main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; - main::set_lsblk() if !$bsd_type && !$loaded{'lsblk'}; - # set @labels, @uuid, %gpart + PartitionData::set() if !$bsd_type && !$loaded{'partition-data'}; + DiskDataBSD::set() if $bsd_type && !$loaded{'disk-data-bsd'}; + LsblkData::set() if !$bsd_type && !$loaded{'lsblk'}; + # set @labels, @uuid if (!$bsd_type){ set_label_uuid() if !$loaded{'label-uuid'}; } @@ -14374,8 +14920,8 @@ sub partition_data { } @partitions_working = grep {!/^rootfs/} @partitions_working if $roots > 1; my $filters = partition_filters(); - #push @partitions_working, '//mafreebox.freebox.fr/Disque dur cifs 239216096 206434016 20607496 91% /freebox/Disque dur'; - #push @partitions_working, '//mafreebox.freebox.fr/AllPG cifs 436616192 316339304 120276888 73% /freebox/AllPG'; + # push @partitions_working, '//mafreebox.freebox.fr/Disque dur cifs 239216096 206434016 20607496 91% /freebox/Disque dur'; + # push @partitions_working, '//mafreebox.freebox.fr/AllPG cifs 436616192 316339304 120276888 73% /freebox/AllPG'; foreach (@partitions_working){ # apple crap, maybe also freebsd? $_ =~ s/^map\s+([\S]+)/map:\/$1/ if $b_fake_map; @@ -14387,9 +14933,9 @@ sub partition_data { if ($test =~ /\s/){ $b_space = 1; $replace =~ s/\s/^^/g; - #print ":$replace:\n"; + # print ":$replace:\n"; $_ =~ s/^$test/$replace/; - #print "$_\n"; + # print "$_\n"; } } my @row = split(/\s+/, $_); @@ -14402,7 +14948,7 @@ sub partition_data { $maj_min,$type,$uuid) = ('','','','','','','','',''); ($b_load,$block_size,$percent_used,$raw_size,$size_available, $size,$used) = (0,0,0,0,0,0,0,0); - %part = (); + undef %part; # NOTE: using -P for linux fixes line wraps, and for bsds, assuming they don't use such long file names if ($row[0] =~ /^\/dev\/|:\/|\/\//){ # this could point to by-label or by-uuid so get that first. In theory, abs_path should @@ -14426,7 +14972,7 @@ sub partition_data { } $dev_base = $row[0]; $dev_base =~ s|^/.*/||; - %part = main::get_lsblk($dev_base) if @lsblk; + %part = LsblkData::get($dev_base) if @lsblk; $maj_min = get_maj_min($dev_base) if @proc_partitions; } # this handles zfs type devices/partitions, which do not start with / but contain / @@ -14455,13 +15001,13 @@ sub partition_data { if ($b_load){ if (!$bsd_type){ if ($b_fs){ - $fs = (%part && $part{'fs'}) ? $part{'fs'} : $row[1]; + $fs = ($part{'fs'}) ? $part{'fs'} : $row[1]; } else { $fs = get_mounts_fs($row[0],\@mount); } if ($show{'label'}) { - if (%part && $part{'label'}) { + if ($part{'label'}) { $label = $part{'label'}; } elsif (@labels){ @@ -14469,7 +15015,7 @@ sub partition_data { } } if ($show{'uuid'}) { - if (%part && $part{'uuid'}) { + if ($part{'uuid'}) { $uuid = $part{'uuid'}; } elsif ( @uuids){ @@ -14479,12 +15025,6 @@ sub partition_data { } else { $fs = ($b_fs) ? $row[1]: get_mounts_fs($row[0],\@mount); - if ($bsd_type && ($b_admin || $show{'label'} || $show{'uuid'} ) ){ - my @temp = GpartData::get($dev_base); - $block_size = $temp[0] if $temp[0]; - $label = $temp[1] if $temp[1]; - $uuid =$temp[2] if $temp[2]; - } } # assuming that all null/nullfs are parts of a logical fs $b_logical = 1 if $fs && $fs =~ /^(hammer|null|zfs)/; @@ -14522,6 +15062,13 @@ sub partition_data { $dev_type = 'dev'; } } + if ($bsd_type && $dev_type eq 'dev' && $row[0] && + ($b_admin || $show{'label'} || $show{'uuid'})){ + my %temp = DiskDataBSD::get($row[0]); + $block_size = $temp{'logical-block-size'}; + $label = $temp{'label'}; + $uuid = $temp{'uuid'}; + } $used = $row[$cols - $back_used]; $percent_used = sprintf("%.1f", ( $used/$size )*100) if ($size && main::is_numeric($size) ); push(@partitions,{ @@ -14543,8 +15090,8 @@ sub partition_data { }); } } - @data = swap_data(); - push(@partitions,@data); + swap_data() if !$loaded{'set-swap'}; + push(@partitions,@swaps); print Data::Dumper::Dumper \@partitions if $dbg[16]; if (!$bsd_type && @lsblk){ check_partition_data();# updates @partitions @@ -14555,12 +15102,11 @@ sub partition_data { } sub swap_data { eval $start if $b_log; - return @swaps if $loaded{'swaps'}; - $loaded{'swaps'} = 1; + $loaded{'set-swap'} = 1; my (@data,@working); - my ($cache_pressure,$dev_base,$dev_mapped,$dev_type,$label,$maj_min, - $mount,$path,$pattern1,$pattern2,$percent_used,$priority,$size, - $swap_type,$swappiness,$used,$uuid); + my ($block_size,$cache_pressure,$dev_base,$dev_mapped,$dev_type,$label, + $maj_min,$mount,$path,$pattern1,$pattern2,$percent_used,$priority, + $size,$swap_type,$swappiness,$used,$uuid); my ($s,$j,$size_id,$used_id) = (1,0,2,3); if (!$bsd_type){ # faster, avoid subshell, same as swapon -s @@ -14595,8 +15141,8 @@ sub swap_data { foreach (@working){ #next if ! /^\/dev/ || /^\/dev\/(ramzwap|zram)/; next if /^(Device|Filename|no swap)/; - ($dev_base,$dev_mapped,$dev_type,$label,$maj_min,$mount,$priority, - $swap_type,$uuid) = ('','','','','','',undef,'partition',''); + ($block_size,$dev_base,$dev_mapped,$dev_type,$label,$maj_min,$mount,$priority, + $swap_type,$uuid) = ('','','','','','','',undef,'partition',''); @data = split(/\s+/, $_); if (/^\/dev\/(block\/)?(compcache|ramzwap|zram)/i){ $swap_type = 'zram'; @@ -14621,10 +15167,11 @@ sub swap_data { } } else { - if ($bsd_type && ($show{'label'} || $show{'uuid'} ) ){ - my @temp = GpartData::get($data[0]); - $label = $temp[1] if $temp[1]; - $uuid = $temp[2] if $temp[2]; + if ($show{'label'} || $show{'uuid'}){ + my %temp = DiskDataBSD::get($data[0]); + $block_size = $temp{'logical-block-size'}; + $label = $temp{'label'}; + $uuid = $temp{'uuid'}; } } $dev_type = 'dev'; @@ -14644,6 +15191,7 @@ sub swap_data { $used = $data[$used_id]; $percent_used = sprintf("%.1f", ( $used/$size )*100); push(@swaps, { + 'block-size' => $block_size, 'cache-pressure' => $cache_pressure, 'dev-base' => $dev_base, 'dev-mapped' => $dev_mapped, @@ -14667,7 +15215,6 @@ sub swap_data { main::log_data('dump','@swaps',\@swaps) if $b_log; print Data::Dumper::Dumper \@swaps if $dbg[15];; eval $end if $b_log; - return @swaps; } sub swap_advanced_data { eval $start if $b_log; @@ -14700,23 +15247,26 @@ sub check_partition_data { ($row->{'type'} =~ /^(disk|loop|rom)$/)){ next; } - #print "$row->{'name'} $row->{'mount'}\n"; + # unmap so we can match name to dev-base + if (%mapper && $mapper{$row->{'name'}}){ + $dev_mapped = $row->{'name'}; + $row->{'name'} = $mapper{$row->{'name'}}; + } + # print "$row->{'name'} $row->{'mount'}\n"; foreach my $row2 (@partitions){ - # print "m:$row->{'mount'} id:$row2->{'id'}\n"; + # print "1: n:$row->{'name'} m:$row->{'mount'} db:$row2->{'dev-base'} id:$row2->{'id'}\n"; next if !$row2->{'id'}; - if ($row->{'mount'} eq $row2->{'id'}){ + # note: for swap mount point is [SWAP] in @lsblk, but swap-x in @partitions + if ($row->{'mount'} eq $row2->{'id'} || $row->{'name'} eq $row2->{'dev-base'}){ $b_found = 1; - if (%mapper && $mapper{$row->{'name'}}){ - $dev_mapped = $row->{'name'}; - $row->{'name'} = $mapper{$row->{'name'}}; - } last; } - #print "m:$row->{'mount'} id:$row2->{'id'}\n"; + # print "m:$row->{'mount'} id:$row2->{'id'}\n"; } if (!$b_found){ - #print "found: $row->{'name'} $row->{'mount'}\n"; + # print "found: n:$row->{'name'} m:$row->{'mount'}\n"; $temp = { + 'block-logical' => $row->{'block-logical'}, 'dev-base' => $row->{'name'}, 'dev-mapped' => $dev_mapped, 'fs' => $row->{'fs'}, @@ -14744,7 +15294,7 @@ sub partition_filters { my $filters = 'aufs|cgroup.*|cgmfs|configfs|debugfs|\/dev|dev|'; $filters .= '\/dev\/loop[0-9]*|devfs|devtmpfs|fdescfs|iso9660|'; $filters .= 'kernfs|linprocfs|linsysfs|none|overla(id|y)|procfs|ptyfs|'; - $filters .= '/run(\/.*)?|run|shm|squashfs|sys|\/sys\/.*|sysfs|'; + $filters .= '/run(\/.*)?|run|shm|squashfs|swap|sys|\/sys\/.*|sysfs|'; $filters .= 'tmpfs|type|udev|unionfs|vartmp'; return $filters } @@ -14773,7 +15323,6 @@ sub get_mounts_fs { main::log_data('data',"fs: $fs") if $b_log; return $fs; } - sub set_label_uuid { eval $start if $b_log; $loaded{'label-uuid'} = 1; @@ -14890,10 +15439,9 @@ sub get_uuid { } } -## ProcessData +## ProcessItem { -package ProcessData; - +package ProcessItem; sub get { eval $start if $b_log; my $num = 0; @@ -14937,8 +15485,8 @@ sub cpu_processes { $j = scalar @rows; # $cpu_mem = ' - Memory: MiB / % used' if $extra > 0; my $throttled = throttled($ps_count,$count,$j); - #my $header = "CPU % used - Command - pid$cpu_mem - top"; - #my $header = "Top $count by CPU"; + # my $header = "CPU % used - Command - pid$cpu_mem - top"; + # my $header = "Top $count by CPU"; my @data = ({ main::key($num++,1,1,'CPU top') => "$count$throttled" . ' of ' . scalar @ps_aux, },); @@ -14967,7 +15515,7 @@ sub cpu_processes { $mem .= ' (' . $row[3] . '%)'; $processes[$j]->{main::key($num++,0,3,'mem')} = $mem; } - #print Data::Dumper::Dumper \@processes, "i: $i; j: $j "; + # print Data::Dumper::Dumper \@processes, "i: $i; j: $j "; } eval $end if $b_log; return @processes; @@ -14990,13 +15538,13 @@ sub mem_processes { $pid_col = 0 if $ps_cols == 2; } @rows = splice(@rows,0,$count); - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; @processes = main::MemoryData::full('process') if !$loaded{'memory'}; $j = scalar @rows; my $throttled = throttled($ps_count,$count,$j); #$cpu_mem = ' - CPU: % used' if $extra > 0; - #my $header = "Memory MiB/% used - Command - pid$cpu_mem - top"; - #my $header = "Top $count by Memory"; + # my $header = "Memory MiB/% used - Command - pid$cpu_mem - top"; + # my $header = "Top $count by Memory"; @data = ({ main::key($num++,1,1,'Memory top') => "$count$throttled" . ' of ' . scalar @ps_aux, },); @@ -15030,7 +15578,7 @@ sub mem_processes { $cpu = $row[2] . '%'; $processes[$j]->{main::key($num++,0,3,'cpu')} = $cpu; } - #print Data::Dumper::Dumper \@processes, "i: $i; j: $j "; + # print Data::Dumper::Dumper \@processes, "i: $i; j: $j "; } eval $end if $b_log; return @processes; @@ -15065,9 +15613,9 @@ sub throttled { } } -## RaidData +## RaidItem { -package RaidData; +package RaidItem; sub get { eval $start if $b_log; @@ -15075,10 +15623,10 @@ sub get { my $num = 0; @hardware_raid = hw_data() if $use{'hardware-raid'} || $fake{'raid-hw'}; raid_data() if !$loaded{'raid'}; - #print 'get: ', Data::Dumper::Dumper \@lvm_raid; - #print 'get: ', Data::Dumper::Dumper \@md_raid; - #print 'get: ', Data::Dumper::Dumper \@zfs_raid; - if (!@lvm_raid && !@md_raid && !@zfs_raid && !@hardware_raid){ + # print 'get: ', Data::Dumper::Dumper \@lvm_raid; + # print 'get: ', Data::Dumper::Dumper \@md_raid; + # print 'get: ', Data::Dumper::Dumper \@zfs_raid; + if (!@lvm_raid && !@md_raid && !@zfs_raid && !@soft_raid && !@hardware_raid){ if ($show{'raid-forced'}){ $key1 = 'Message'; $val1 = main::row_defaults('raid-data'); @@ -15094,6 +15642,9 @@ sub get { if (@md_raid){ push(@rows,md_output()); } + if (@soft_raid){ + push(@rows,soft_output()); + } if (@zfs_raid){ push(@rows,zfs_output()); } @@ -15140,12 +15691,12 @@ sub hw_output { } } eval $end if $b_log; - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; return @rows; } sub lvm_output { eval $start if $b_log; - my (@components,@components_good,@components_meta,@rows); + my (@components,@good,@components_meta,@rows); my ($size); my ($j,$num) = (0,0); foreach my $row (sort {$a->{'id'} cmp $b->{'id'}} @lvm_raid){ @@ -15186,32 +15737,32 @@ sub lvm_output { $rows[$j]->{main::key($num++,0,4,'vg-free')} = $size; } @components = (ref $row->{'components'} eq 'ARRAY') ? @{$row->{'components'}} : (); - @components_good = (); + @good = (); @components_meta = (); foreach my $item (sort { $a->[0] cmp $b->[0]} @components){ if ($item->[4] =~ /_rmeta/){ push(@components_meta, $item); } else { - push(@components_good, $item); + push(@good, $item); } } $j = scalar @rows; $rows[$j]->{main::key($num++,1,2,'Components')} = ''; my $b_bump; - components_output('lvm','Online',\@rows,\@components_good,\$j,\$num,\$b_bump); + components_output('lvm','Online',\@rows,\@good,\$j,\$num,\$b_bump); components_output('lvm','Meta',\@rows,\@components_meta,\$j,\$num,\$b_bump); } eval $end if $b_log; - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; return @rows; } sub md_output { eval $start if $b_log; - my (@components,@components_good,@failed,@inactive,@rows,@spare,@temp); + my (@components,@good,@failed,@inactive,@rows,@spare,@temp); my ($blocks,$chunk,$level,$report,$size,$status); my ($j,$num) = (0,0); - #print Data::Dumper::Dumper \@md_raid; + # print Data::Dumper::Dumper \@md_raid; if ($extra > 2 && $md_raid[0]->{'supported-levels'}){ push(@rows, { main::key($num++,0,1,'Supported mdraid levels') => $md_raid[0]->{'supported-levels'}, @@ -15245,7 +15796,7 @@ sub md_output { $report .= " $row->{'u-data'}" if $report; $report ||= 'N/A'; if ($extra == 0){ - #print "here 0\n"; + # print "here 0\n"; $rows[$j]->{main::key($num++,0,2,'report')} = $report; } if ($extra > 0){ @@ -15271,7 +15822,7 @@ sub md_output { } } @components = (ref $row->{'components'} eq 'ARRAY') ? @{$row->{'components'}} : (); - @components_good = (); + @good = (); @failed = (); @inactive = (); @spare = (); @@ -15279,22 +15830,22 @@ sub md_output { # print Data::Dumper::Dumper \@components; foreach my $item (sort { $a->[1] <=> $b->[1]} @components){ if (defined $item->[2] && $item->[2] =~ /^(F)$/){ - push(@failed, $item); + push(@failed,$item); } elsif (defined $item->[2] && $item->[2] =~ /(S)$/){ - push(@spare, $item); + push(@spare,$item); } elsif ($row->{'status'} && $row->{'status'} eq 'inactive' ){ - push(@inactive, $item); + push(@inactive,$item); } else { - push(@components_good, $item); + push(@good,$item); } } $j = scalar @rows; $rows[$j]->{main::key($num++,1,2,'Components')} = ''; my $b_bump; - components_output('mdraid','Online',\@rows,\@components_good,\$j,\$num,\$b_bump); + components_output('mdraid','Online',\@rows,\@good,\$j,\$num,\$b_bump); components_output('mdraid','Failed',\@rows,\@failed,\$j,\$num,\$b_bump); components_output('mdraid','Inactive',\@rows,\@inactive,\$j,\$num,\$b_bump); components_output('mdraid','Spare',\@rows,\@spare,\$j,\$num,\$b_bump); @@ -15319,17 +15870,79 @@ sub md_output { } } eval $end if $b_log; - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; + return @rows; +} + +sub soft_output { + eval $start if $b_log; + my (@components,@good,@failed,@rows,@offline,@rebuild,@temp); + my ($size); + my ($j,$num) = (0,0); + if (@soft_raid && $alerts{'bioctl'}->{'action'} eq 'permissions'){ + push(@rows,{ + main::key($num++,1,1,'Message') => main::row_defaults('root-item-incomplete','softraid'), + }); + } + # print Data::Dumper::Dumper \@soft_raid; + foreach my $row (sort {$a->{'id'} cmp $b->{'id'}} @soft_raid){ + $j = scalar @rows; + next if !%$row; + $num = 1; + push(@rows, { + main::key($num++,1,1,'Device') => $row->{'id'}, + }); + $row->{'level'} ||= 'N/A'; + $rows[$j]->{main::key($num++,0,2,'type')} = $row->{'type'}; + $rows[$j]->{main::key($num++,0,2,'level')} = $row->{'level'}; + $rows[$j]->{main::key($num++,0,2,'status')} = $row->{'status'}; + if ($row->{'state'}){ + $rows[$j]->{main::key($num++,0,2,'state')} = $row->{'state'}; + } + if ($row->{'size'}){ + $size = main::get_size($row->{'size'},'string'); + } + $size ||= 'N/A'; + $rows[$j]->{main::key($num++,0,2,'size')} = $size; + @components = (ref $row->{'components'} eq 'ARRAY') ? @{$row->{'components'}} : (); + @good = (); + @failed = (); + @offline = (); + @rebuild = (); + foreach my $item (sort { $a->[1] <=> $b->[1]} @components){ + if (defined $item->[2] && $item->[2] eq 'failed'){ + push(@failed,$item); + } + elsif (defined $item->[2] && $item->[2] eq 'offline'){ + push(@offline,$item); + } + elsif (defined $item->[2] && $item->[2] eq 'rebuild'){ + push(@rebuild,$item); + } + else { + push(@good,$item); + } + } + $j = scalar @rows; + $rows[$j]->{main::key($num++,1,2,'Components')} = ''; + my $b_bump; + components_output('softraid','Online',\@rows,\@good,\$j,\$num,\$b_bump); + components_output('softraid','Failed',\@rows,\@failed,\$j,\$num,\$b_bump); + components_output('softraid','Rebuild',\@rows,\@rebuild,\$j,\$num,\$b_bump); + components_output('softraid','Offline',\@rows,\@offline,\$j,\$num,\$b_bump); + } + eval $end if $b_log; + # print Data::Dumper::Dumper \@rows; return @rows; } sub zfs_output { - eval $start if $b_log; - my (@arrays,@arrays_holder,@components,@components_good,@failed,@rows,@spare); + eval $start if $b_log; + my (@arrays,@arrays_holder,@components,@good,@failed,@rows,@spare); my ($allocated,$available,$level,$size,$status); my ($b_row_1_sizes); my ($j,$num) = (0,0); - #print Data::Dumper::Dumper \@zfs_raid; + # print Data::Dumper::Dumper \@zfs_raid; foreach my $row (sort {$a->{'id'} cmp $b->{'id'}} @zfs_raid){ $j = scalar @rows; $b_row_1_sizes = 0; @@ -15357,7 +15970,7 @@ sub zfs_output { $rows[$j]->{main::key($num++,0,2,'level')} = $arrays[0]->{'level'}; } if ($size){ - #print "here 0\n"; + # print "here 0\n"; $rows[$j]->{main::key($num++,0,2,'size')} = $size; $size = ''; $b_row_1_sizes = 1; @@ -15388,7 +16001,7 @@ sub zfs_output { } # items like cache may have one component, with a size on that component elsif (!$b_row_1_sizes){ - #print "here $count\n"; + # print "here $count\n"; $size = ($row2->{'size'}) ? main::get_size($row2->{'size'},'string') : 'N/A'; $available = ($row2->{'free'}) ? main::get_size($row2->{'free'},'string') : 'N/A'; $rows[$j]->{main::key($num++,0,2,'size')} = $size; @@ -15403,7 +16016,7 @@ sub zfs_output { @components = (ref $row2->{'components'} eq 'ARRAY') ? @{$row2->{'components'}} : (); @failed = (); @spare = (); - @components_good = (); + @good = (); # @spare = split(/\s+/, $row->{'unused'}) if $row->{'unused'}; foreach my $item (sort { $a->[0] cmp $b->[0]} @components){ if (defined $item->[3] && $item->[3] =~ /^(DEGRADED|FAULTED|UNAVAIL)$/){ @@ -15415,19 +16028,19 @@ sub zfs_output { # note: spares in use show: INUSE but technically it's still a spare, # but since it's in use, consider it online. else { - push(@components_good, $item); + push(@good, $item); } } $j = scalar @rows; $rows[$j]->{main::key($num++,1,3,'Components')} = ''; my $b_bump; - components_output('zfs','Online',\@rows,\@components_good,\$j,\$num,\$b_bump); + components_output('zfs','Online',\@rows,\@good,\$j,\$num,\$b_bump); components_output('zfs','Failed',\@rows,\@failed,\$j,\$num,\$b_bump); components_output('zfs','Available',\@rows,\@spare,\$j,\$num,\$b_bump); } } eval $end if $b_log; - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; return @rows; } @@ -15448,20 +16061,25 @@ sub components_output { $extra1 = 'mapped'; $k = 1 if $item eq 'Inactive'; } + elsif ($type eq 'softraid'){ + ($f1,$f2,$f3,$f4,$k1,$l1,$l2,$l3) = (1,10,10,3,5,3,4,5); + $extra1 = 'device'; + $k = 1; + } elsif ($type eq 'zfs'){ ($f1,$f2,$f3,$l1,$l2,$l3) = (1,2,3,4,5,6); $k = 1; } - #print "item: $item\n"; + # print "item: $item\n"; $$j_ref++ if $$b_bump_ref; $$b_bump_ref = 0; my $good = ($item eq 'Online' && !@$array_ref ) ? 'N/A' : ''; $$rows_ref[$$j_ref]->{main::key($$num_ref++,1,$l1,$item)} = $good; #$$j_ref++ if $b_admin; - #print Data::Dumper::Dumper $array_ref; + # print Data::Dumper::Dumper $array_ref; foreach my $device (@$array_ref){ next if ref $device ne 'ARRAY'; - #if ($b_admin && $device->[$f1] && $device->[$f2]){ + # if ($b_admin && $device->[$f1] && $device->[$f2]){ if ($b_admin){ $$j_ref++; $$b_bump_ref = 1; @@ -15491,19 +16109,24 @@ sub components_output { sub raid_data { eval $start if $b_log; - main::set_lsblk() if !$bsd_type && !$loaded{'lsblk'}; + LsblkData::set() if !$bsd_type && !$loaded{'lsblk'}; main::set_mapper() if !$bsd_type && !$loaded{'mapper'}; - main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; + PartitionData::set() if !$bsd_type && !$loaded{'partition-data'}; my (@data); $loaded{'raid'} = 1; if ($fake{'raid-lvm'} || ($alerts{'lvs'}->{'action'} && $alerts{'lvs'}->{'action'} eq 'use')){ @lvm_raid = lvm_data(); } - if ($fake{'raid-md'} || (my $file = main::system_files('mdstat') )){ + if ($fake{'raid-md'} || (my $file = $system_files{'proc-mdstat'})){ @md_raid = md_data($file); } + if ($fake{'raid-soft'} || $sysctl{'softraid'}){ + DiskDataBSD::set() if !$loaded{'disk-data-bsd'}; + @soft_raid = soft_data(); + } if ($fake{'raid-zfs'} || (my $path = main::check_program('zpool') )){ + DiskDataBSD::set() if $bsd_type && !$loaded{'disk-data-bsd'}; @zfs_raid = zfs_data($path); } eval $end if $b_log; @@ -15521,8 +16144,9 @@ sub raid_data { # 10 modules sub hw_data { eval $start if $b_log; + return if !$devices{'hwraid'}; my ($driver,$vendor,@hardware_raid); - foreach my $working (@devices_hwraid){ + foreach my $working (@{$devices{'hwraid'}}){ $driver = ($working->[9]) ? lc($working->[9]): ''; $driver =~ s/-/_/g if $driver; my $driver_version = ($driver) ? main::get_module_version($driver): ''; @@ -15550,13 +16174,13 @@ sub hw_data { } sub lvm_data { eval $start if $b_log; - LogicalData::lvm_data() if !$loaded{'lvm-data'}; + LogicalItem::lvm_data() if !$loaded{'logical-data'}; return if !@lvm; my (@lvraid,$maj_min,$vg_used,@working); foreach my $item (@lvm){ next if $item->{'segtype'} && $item->{'segtype'} !~ /^raid/; my (@components,$dev,$maj_min,$vg_used); - #print Data::Dumper::Dumper $item; + # print Data::Dumper::Dumper $item; if ($item->{'lv_kernel_major'} . ':' . $item->{'lv_kernel_minor'}){ $maj_min = $item->{'lv_kernel_major'} . ':' . $item->{'lv_kernel_minor'}; } @@ -15569,7 +16193,7 @@ sub lvm_data { foreach my $part (@working){ my (@data,$dev,$maj_min,$mapped,$size); if (@proc_partitions){ - @data = main::get_proc_partition($part); + @data = PartitionData::get($part); $maj_min = $data[0] . ':' . $data[1] if defined $data[1]; $size = $data[2]; $raw_logical[1] += $size if $part =~ /^dm-/ && $size; @@ -15601,7 +16225,6 @@ sub lvm_data { 'vg-used' => $vg_used, }); } - # print Data::Dumper::Dumper \@lvraid; main::log_data('dump','@lvraid',\@lvraid) if $b_log; eval $end if $b_log; @@ -15622,7 +16245,7 @@ sub md_data { #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-inactive-active-spare-syntax.txt"; } my @working = main::reader($mdstat,'strip'); - #print Data::Dumper::Dumper \@working; + # print Data::Dumper::Dumper \@working; my (@mdraid,@temp,$b_found,$system,$unused); # NOTE: a system with empty mdstat will not show these values if ($working[0] && $working[0] =~ /^Personalities/){ @@ -15662,14 +16285,14 @@ sub md_data { @temp = (); # cascade of tests, light to cpu intense if ((!$maj_min || !$size) && @proc_partitions){ - @part = main::get_proc_partition($id); + @part = PartitionData::get($id); if (@part){ $maj_min = $part[0] . ':' . $part[1]; $size = $part[2]; } } if ((!$maj_min || !$size) && @lsblk){ - %device = main::get_lsblk($id) if @lsblk; + %device = LsblkData::get($id) if @lsblk; $maj_min = $device{'maj-min'} if $device{'maj-min'}; $size = $device{'size'} if $device{'size'}; } @@ -15693,14 +16316,14 @@ sub md_data { $state = $details{'devices'}->{$name}{'state'}; } if ((!$maj_min || !$part_size) && @proc_partitions){ - @part = main::get_proc_partition($name); + @part = PartitionData::get($name); if (@part){ $maj_min = $part[0] . ':' . $part[1] if !$maj_min; $part_size = $part[2] if !$part_size; } } if ((!$maj_min || !$part_size) && @lsblk) { - %data= main::get_lsblk($name); + %data= LsblkData::get($name); $maj_min = $data{'maj-min'} if !$maj_min; $part_size = $data{'size'}if !$part_size; } @@ -15709,7 +16332,7 @@ sub md_data { $state = $info if !$state && $info; push(@components,[$name,$number,$info,$part_size,$maj_min,$state,$mapped]); } - #print "$component_string\n"; + # print "$component_string\n"; $j = scalar @mdraid; push(@mdraid, { 'chunk-size' => $details{'chunk-size'}, # if we got it, great, if not, further down @@ -15723,7 +16346,7 @@ sub md_data { 'type' => 'mdraid', }); } - #print "$_\n"; + # print "$_\n"; if ($_ =~ /^([0-9]+)\sblocks/){ $mdraid[$j]->{'blocks'} = $1; } @@ -15752,13 +16375,13 @@ sub md_data { $mdraid[$j]->{'recovery-finish'} = $1; $mdraid[$j]->{'recovery-speed'} = $2; } - #print 'mdraid loop: ', Data::Dumper::Dumper \@mdraid; + # print 'mdraid loop: ', Data::Dumper::Dumper \@mdraid; } if (@mdraid){ $mdraid[0]->{'supported-levels'} = $system if $system; $mdraid[0]->{'unused'} = $unused if $unused; } - #print Data::Dumper::Dumper \@mdraid; + # print Data::Dumper::Dumper \@mdraid; eval $end if $b_log; return @mdraid; } @@ -15821,12 +16444,77 @@ sub md_details { }; } } - #print Data::Dumper::Dumper \%details; + # print Data::Dumper::Dumper \%details; main::log_data('dump',"$id: %details",\%details) if $b_log; eval $end if $b_log; return %details; } +sub soft_data { + eval $start if $b_log; + my ($cmd,$id,$state,$status,@data,@softraid,@working); + # already been set in DiskDataBSD but we know the device exists + foreach my $device (@{$sysctl{'softraid'}}){ + if ($device =~ /\.drive[\d]+:([\S]+)\s\(([a-z0-9]+)\)[,\s]+(\S+)/){ + my ($level,$size,@components); + $id = $2; + $status = $1; + $state = $3; + if ($alerts{'bioctl'}->{'action'} eq 'use'){ + $cmd = $alerts{'bioctl'}->{'path'} . " $id 2>/dev/null"; + @data = main::grabber($cmd,'','strip'); + main::log_data('dump','softraid @data',\@data) if $b_log; + shift @data if @data; # get rid of headers + foreach my $row (@data){ + @working = split(/\s+/,$row); + next if !defined $working[0]; + if ($working[0] =~ /^softraid/){ + if ($working[3] && main::is_numeric($working[3])){ + $size = $working[3]/1024;# it's in bytes + $raw_logical[0] += $size; + } + $status = lc($working[2]) if $working[2]; + $state = lc(join(' ', @working[6..$#working])) if $working[6]; + $level = lc($working[5]) if $working[5]; + } + elsif ($working[0] =~ /^[\d]{1,2}$/){ + my ($c_id,$c_device,$c_size,$c_status); + if ($working[2] && main::is_numeric($working[2])){ + $c_size = $working[2]/1024;# it's in bytes + $raw_logical[1] += $c_size; + } + $c_status = lc($working[1]) if $working[1]; + if ($working[3] && $working[3] =~ /^([\d:\.]+)$/){ + $c_device = $1; + } + if ($working[5] && $working[5] =~ /<([^>]+)>/){ + $c_id = $1; + } + # when offline, there will be no $c_id, but we want to show device + if (!$c_id && $c_device){ + $c_id = $c_device; + } + push(@components,[$c_id,$c_size,$c_status,$c_device]) if $c_id; + } + } + } + push(@softraid, { + 'components' => \@components, + 'id' => $id, + 'level' => $level, + 'size' => $size, + 'state' => $state, + 'status' => $status, + 'type' => 'softraid', + }); + } + } + print Data::Dumper::Dumper \@softraid if $dbg[37]; + main::log_data('dump','@softraid',\@softraid) if $b_log; + eval $end if $b_log; + return @softraid; +} + sub zfs_data { eval $start if $b_log; my ($zpool) = @_; @@ -15835,11 +16523,11 @@ sub zfs_data { my $b_v = 1; my ($i,$j,$k) = (0,0,0); if ($fake{'raid-zfs'}){ - #my $file; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-1-mirror-main-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-2-mirror-main-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-tank-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-gojev-1.txt"; + # my $file; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-1-mirror-main-solestar.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-2-mirror-main-solestar.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-tank-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-gojev-1.txt"; #@working = main::reader($file);$zpool = ''; } else { @@ -15851,7 +16539,7 @@ sub zfs_data { @working = main::grabber("$zpool list 2>/dev/null"); $b_v = 0; } - #print Data::Dumper::Dumper \@working; + # print Data::Dumper::Dumper \@working; main::log_data('dump','@working',\@working) if $b_log; if (!@working){ main::log_data('data','no zpool list data') if $b_log; @@ -15888,7 +16576,7 @@ sub zfs_data { 'type' => 'zfs', }); } - #print Data::Dumper::Dumper \@zfs; + # print Data::Dumper::Dumper \@zfs; # raid level is the second item in the output, unless it is not, sometimes it is absent if ($row[1] =~ /raid|mirror/){ $row[1] =~ s/^raid1/mirror/; @@ -15940,20 +16628,20 @@ sub zfs_data { $zfs[$j]->{'arrays'}[$k]{'free'} = $free; } if ((!$maj_min || !$part_size) && @proc_partitions){ - my @part = main::get_proc_partition($working); + my @part = PartitionData::get($working); if (@part){ $maj_min = $part[0] . ':' . $part[1]; $part_size = $part[2]; } } if ((!$maj_min || !$part_size) && @lsblk){ - my %data= main::get_lsblk($working); + my %data= LsblkData::get($working); $maj_min = $data{'maj-min'}; $part_size = $data{'size'}; } if (!$part_size && $bsd_type){ - my @temp = GpartData::get($working); - $part_size = $temp[3] if $temp[3]; + my %temp = DiskDataBSD::get($working); + $part_size = $temp{'size'} if $temp{'size'}; } $raw_logical[1] += $part_size if $part_size; $zfs[$j]->{'arrays'}[$k]{'components'}[$i] = [$working,$part_size,$maj_min,$state]; @@ -15971,7 +16659,7 @@ sub zfs_data { $j++; } @zfs = zfs_status($zpool,\@zfs); - # print Data::Dumper::Dumper \@zfs; + print Data::Dumper::Dumper \@zfs if $dbg[37]; eval $end if $b_log; return @zfs; } @@ -15985,9 +16673,9 @@ sub zfs_status { $k = 0; if ($fake{'raid-zfs'}){ my $file; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-1-mirror-main-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-2-mirror-main-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-tank-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-1-mirror-main-solestar.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-2-mirror-main-solestar.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-tank-1.txt"; #@pool_status = main::reader($file,'strip'); } else { @@ -15996,14 +16684,14 @@ sub zfs_status { } main::log_data('cmd',$cmd) if $b_log; #@arrays = (ref $row->{'arrays'} eq 'ARRAY' ) ? @{$row->{'arrays'}} : (); - #print "$row->{'id'} rs:$row->{'status'}\n"; + # print "$row->{'id'} rs:$row->{'status'}\n"; $status = ($row->{'status'} && $row->{'status'} eq 'no-status') ? check_zfs_status($row->{'id'},\@pool_status): $row->{'status'}; $zfs->[$j]{'status'} = $status if $status; #@arrays = grep {defined $_} @arrays; - #print "$row->{id} $#arrays\n"; - #print Data::Dumper::Dumper \@arrays; + # print "$row->{id} $#arrays\n"; + # print Data::Dumper::Dumper \@arrays; foreach my $array (@{$row->{'arrays'}}){ - #print 'ref: ', ref $array, "\n"; + # print 'ref: ', ref $array, "\n"; #next if ref $array ne 'HASH'; my @components = (ref $array->{'components'} eq 'ARRAY') ? @{$array->{'components'}} : (); $l = 0; @@ -16011,7 +16699,7 @@ sub zfs_status { $level = ($array->{'level'}) ? "$array->{'level'}-$i": $array->{'level'}; $status = ($level) ? check_zfs_status($level,\@pool_status): ''; $zfs->[$j]{'arrays'}[$k]{'status'} = $status; - #print "$level i:$i j:$j k:$k $status\n"; + # print "$level i:$i j:$j k:$k $status\n"; foreach my $component (@components){ my @temp = split('~', $component); $status = ($temp[0]) ? check_zfs_status($temp[0],\@pool_status): ''; @@ -16044,26 +16732,32 @@ sub check_zfs_status { } } -## RamData +## RamItem { -package RamData; - +package RamItem; +my (@vendors); sub get { my (@data,@rows,$key1,@ram,$val1); my $num = 0; @rows = MemoryData::full('ram') if !$loaded{'memory'}; - if ( !$fake{'dmidecode'} && $alerts{'dmidecode'}->{'action'} ne 'use'){ - $key1 = $alerts{'dmidecode'}->{'action'}; - $val1 = $alerts{'dmidecode'}->{'message'}; - push(@rows, { - main::key($num++,1,1,'RAM Report') => '', - main::key($num++,0,2,$key1) => $val1, - }); + if ($bsd_type && !$force{'dmidecode'} && ($dboot{'ram'} || $fake{'dboot'})){ + @ram = dboot_data(); + if (@ram){ + @data = ram_output(\@ram,'dboot'); + } + else { + $key1 = 'message'; + $val1 = main::row_defaults('ram-data-dmidecode'); + @data = ({ + main::key($num++,1,1,'RAM Report') => '', + main::key($num++,0,2,$key1) => $val1, + }); + } } - else { + elsif ($fake{'dmidecode'} || $alerts{'dmidecode'}->{'action'} eq 'use'){ @ram = dmidecode_data(); if (@ram){ - @data = ram_output(\@ram); + @data = ram_output(\@ram,'dmidecode'); } else { $key1 = 'message'; @@ -16073,20 +16767,33 @@ sub get { main::key($num++,0,2,$key1) => $val1, }); } - push(@rows,@data); } + else { + $key1 = $alerts{'dmidecode'}->{'action'}; + $val1 = $alerts{'dmidecode'}->{'message'}; + push(@rows, { + main::key($num++,1,1,'RAM Report') => '', + main::key($num++,0,2,$key1) => $val1, + }); + } + push(@rows,@data); eval $end if $b_log; return @rows; } sub ram_output { eval $start if $b_log; - my ($ram) = @_; + my ($ram,$source) = @_; return if !@$ram; my $num = 0; my $j = 0; my (@rows,$b_non_system); my ($arrays,$modules,$slots,$type_holder) = (0,0,0,''); + if ($source eq 'dboot'){ + push(@rows, { + main::key($num++,0,1,'Message') => main::row_defaults('ram-data-complete'), + }); + } foreach my $item (@$ram){ $j = scalar @rows; if (!$show{'ram-short'}){ @@ -16158,11 +16865,9 @@ sub ram_output { $mod->{'speed'} = $mod->{'configured-clock-speed'}; $mod->{'speed-note'} = $mod->{'configured-note'} if $mod->{'configured-note'} ; } - # rare instances, dmi type 6, no speed - else { - $mod->{'speed'} = 'N/A'; - } } + # rare instances, dmi type 6, no speed, dboot also no speed + $mod->{'speed'} ||= 'N/A'; $rows[$j]->{main::key($num++,1,3,'speed')} = $mod->{'speed'}; $rows[$j]->{main::key($num++,0,4,'note')} = $mod->{'speed-note'} if $mod->{'speed-note'}; } @@ -16174,19 +16879,19 @@ sub ram_output { $rows[$j]->{main::key($num++,0,3,'detail')} = $mod->{'device-type-detail'}; } } - if ($extra > 2 ){ + if ($source ne 'dboot' && $extra > 2){ $mod->{'data-width'} ||= 'N/A'; $rows[$j]->{main::key($num++,0,3,'bus-width')} = $mod->{'data-width'}; $mod->{'total-width'} ||= 'N/A'; $rows[$j]->{main::key($num++,0,3,'total')} = $mod->{'total-width'}; } - if ($extra > 1 ){ + if ($source ne 'dboot' && $extra > 1){ $mod->{'manufacturer'} ||= 'N/A'; $rows[$j]->{main::key($num++,0,3,'manufacturer')} = $mod->{'manufacturer'}; $mod->{'part-number'} ||= 'N/A'; $rows[$j]->{main::key($num++,0,3,'part-no')} = $mod->{'part-number'}; } - if ($extra > 2 ){ + if ($source ne 'dboot' && $extra > 2){ $mod->{'serial'} = main::apply_filter($mod->{'serial'}); $rows[$j]->{main::key($num++,0,3,'serial')} = $mod->{'serial'}; } @@ -16214,7 +16919,7 @@ sub dmidecode_data { my ($derived_module_size,$max_cap_5,$max_cap_16,$max_module_size) = (0,0,0,0); my ($i,$j,$k) = (0,0,0); my $check = main::row_defaults('note-check'); - #print Data::Dumper::Dumper \@dmi; + # print Data::Dumper::Dumper \@dmi; foreach my $entry (@dmi){ ## NOTE: do NOT reset these values, that causes failures # ($derived_module_size,$max_cap_5,$max_cap_16,$max_module_size) = (0,0,0,0); @@ -16242,8 +16947,8 @@ sub dmidecode_data { $ram[$k]->{'eec'} = $temp[1]; } } - $ram[$k]->{'modules'} = ([],); - #print Data::Dumper::Dumper \@ram; + $ram[$k]->{'modules'} = []; + # print Data::Dumper::Dumper \@ram; $b_5 = 1; } elsif ($entry->[0] == 6){ @@ -16295,7 +17000,7 @@ sub dmidecode_data { 'speed' => $speed, 'type' => $type, }; - #print Data::Dumper::Dumper \@ram; + # print Data::Dumper::Dumper \@ram; $j++; } elsif ($entry->[0] == 16){ @@ -16310,7 +17015,7 @@ sub dmidecode_data { $max_cap_16 = calculate_size($temp[1],$max_cap_16); $ram[$handle]->{'max-capacity-16'} = $max_cap_16; } - # note: these 3 have cleaned data in set_dmidecode_data, so replace stuff manually + # note: these 3 have cleaned data in DmiData, so replace stuff manually elsif ($temp[0] eq 'Location'){ $temp[1] =~ s/\sOr\sMotherboard//; $temp[1] ||= 'System Board'; @@ -16327,17 +17032,20 @@ sub dmidecode_data { elsif ($temp[0] eq 'Number Of Devices'){ $ram[$handle]->{'slots-16'} = $temp[1]; } - #print "0: $temp[0]\n"; + # print "0: $temp[0]\n"; } $ram[$handle]->{'derived-module-size'} = 0; $ram[$handle]->{'device-count-found'} = 0; $ram[$handle]->{'used-capacity'} = 0; - #print "s16: $ram[$handle]->{'slots-16'}\n"; + # print "s16: $ram[$handle]->{'slots-16'}\n"; } elsif ($entry->[0] == 17){ - my ($bank_locator,$configured_speed,$configured_note,$data_width) = ('','','',''); - my ($device_type,$device_type_detail,$form_factor,$locator,$main_locator) = ('','','','',''); - my ($manufacturer,$part_number,$serial,$speed,$speed_note,$total_width) = ('','','','','',''); + my ($bank_locator,$configured_speed,$configured_note, + $data_width) = ('','','',''); + my ($device_type,$device_type_detail,$form_factor,$locator, + $main_locator) = ('','','','',''); + my ($manufacturer,$vendor_id,$part_number,$serial,$speed,$speed_note, + $total_width) = ('','','','','','',''); my ($device_size,$i_data,$i_total,$working_size) = (0,0,0,0); foreach my $item (@$entry){ @temp = split(/:\s*/, $item, 2); @@ -16427,6 +17135,11 @@ sub dmidecode_data { $data_width = $total_width; $total_width = $temp_width; } + if ((!$manufacturer || $manufacturer =~ /^([a-f0-9]{4})$/i) && $part_number){ + $vendor_id = lc($1) if $1; + ($manufacturer,$part_number) = ram_vendor($part_number); + $manufacturer = $vendor_id if !$manufacturer && $vendor_id; + } $ram[$handle]->{'derived-module-size'} = $derived_module_size; $ram[$handle]->{'modules'}[$i]{'configured-clock-speed'} = $configured_speed; $ram[$handle]->{'modules'}[$i]{'configured-note'} = $configured_note if $configured_note; @@ -16437,6 +17150,7 @@ sub dmidecode_data { $ram[$handle]->{'modules'}[$i]{'form-factor'} = $form_factor; $ram[$handle]->{'modules'}[$i]{'locator'} = $main_locator; $ram[$handle]->{'modules'}[$i]{'manufacturer'} = $manufacturer; + $ram[$handle]->{'modules'}[$i]{'vendor-id'} = $vendor_id; $ram[$handle]->{'modules'}[$i]{'part-number'} = $part_number; $ram[$handle]->{'modules'}[$i]{'serial'} = $serial; $ram[$handle]->{'modules'}[$i]{'speed'} = $speed; @@ -16451,9 +17165,95 @@ sub dmidecode_data { last; } } + print Data::Dumper::Dumper \@ram if $dbg[36]; + main::log_data('dump','@ram',\@ram) if $b_log; @ram = process_data(\@ram) if @ram; main::log_data('dump','@ram',\@ram) if $b_log; - # print Data::Dumper::Dumper \@ram; + print Data::Dumper::Dumper \@ram if $dbg[36]; + eval $end if $b_log; + return @ram; +} +sub dboot_data { + eval $start if $b_log; + my (@ram); + my $est = main::row_defaults('note-est'); + my ($arr,$derived_module_size,$subtract) = (0,0,0); + my ($holder); + foreach (@{$dboot{'ram'}}){ + my ($addr,$detail,$device_detail,$ecc,$iic,$locator,$size,$speed,$type); + # note: seen one netbsd with multiline spdmem0/1 etc but not consistent so don't use + if (/^(spdmem([\d]+)):at iic([\d]+)(\saddr 0x([0-9a-f]+))?/){ + $iic = $3; + $locator = $1; + $holder = $iic if !defined $holder; # prime for first use + # note: seen iic2 as only device + if ($iic != $holder){ + if ($ram[$arr] && $ram[$arr]->{'slots-16'}){ + $subtract += $ram[$arr]->{'slots-16'}; + } + $holder = $iic; + # then since we are on a new iic device, assume new ram array. + # this needs more data to confirm this guess. + $arr++; + } + if ($5){ + $addr = hex($5); + } + if (/(non?[\s-]parity)/i){ + $device_detail = $1; + $ecc = 'None'; + } + elsif (/EEC/i){ + $device_detail = 'EEC'; + $ecc = 'EEC'; + } + if (/\b(PC[0-9]+-\S+)\b/){ + $speed = $1; + my $temp = speed_mapper($speed); + if ($temp ne $speed){ + $detail = $speed; + $speed = $temp; + } + } + # we want to avoid netbsd trying to complete @ram without real data + if (/:(\d+[MGT])B?\s(DDR[0-9]*)\b/){ + $size = main::translate_size($1)/1024; + $type = $2; + if ($addr){ + $ram[$arr]->{'slots-16'} = $addr - 80 + 1 - $subtract; + $locator = 'Slot-' . $ram[$arr]->{'slots-16'}; + } + $ram[$arr]->{'device-count-found'}++; + # build up actual capacity found for override tests + $ram[$arr]->{'max-capacity-16'} += $size; + $ram[$arr]->{'max-cap-qualifier'} = $est; + $ram[$arr]->{'slots-16'}++ if !$addr; + $derived_module_size = $size if $size > $derived_module_size; + $ram[$arr]->{'slots-qualifier'} = $est; + $ram[$arr]->{'eec'} = $ecc; + $ram[$arr]->{'derived-module-size'} = $derived_module_size; + push(@{$ram[$arr]->{'modules'}},{ + 'device-type' => $type, + 'device-type-detail' => $detail, + 'locator' => $locator, + 'size' => $size, + 'speed' => $speed, + }); + } + } + } + for (my $i = 0; $i++ ;scalar @ram){ + next if ref $ram[$i] ne 'HASH'; + # 1 slot is possible, but 3 is very unlikely due to dual channel ddr + if ($ram[$i]->{'slots'} && $ram[$i]->{'slots'} > 2 && $ram[$i]->{'slots'} % 2 == 1){ + $ram[$i]->{'slots'}++; + } + } + print Data::Dumper::Dumper \@ram if $dbg[36]; + main::log_data('dump','@ram',\@ram) if $b_log; + @ram = process_data(\@ram) if @ram; + main::log_data('dump','@ram',\@ram) if $b_log; + print Data::Dumper::Dumper \@ram if $dbg[36]; eval $end if $b_log; return @ram; } @@ -16500,7 +17300,6 @@ sub process_data { if ($b_debug){ print "3: dcf: $item->{'device-count-found'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; } - # note: some cases memory capacity == max module size, so one stick will fill it # but I think only with cases of 2 slots does this happen, so if > 2, use the count of slots. if ($max_cap && ($item->{'device-count-found'} || $item->{'slots-16'}) ){ @@ -16611,6 +17410,11 @@ sub process_data { $item->{'slots-16'} = scalar @{$item->{'modules'}}; print "L\n" if $b_debug; } + # only bsds using dmesg data + elsif ($item->{'slots-qualifier'}){ + $est_slots = $item->{'slots-qualifier'}; + $est_cap = $est; + } push(@return, { 'capacity' => $max_cap, 'cap-qualifier' => $est_cap, @@ -16647,11 +17451,11 @@ sub process_speed { sub process_size { my ($size) = @_; my ($b_trim,$unit) = (0,''); - #print "size0: $size\n"; + # print "size0: $size\n"; return 'N/A' if !$size; #return $size if $size =~ /\D/; return $size if !main::is_numeric($size); - #print "size: $size\n"; + # print "size: $size\n"; # we only want a max 2 decimal places, and only when it's # a unit > 1 GiB $b_trim = 1 if $size > 1024; @@ -16673,23 +17477,126 @@ sub calculate_size { my $working_size = main::translate_size($working); # but we want it back in MiB for RAM, that should get fixed $working_size = $working_size/1024 if $working_size; - #print "ws-a: $working_size s-1: $size\n"; + # print "ws-a: $working_size s-1: $size\n"; if (main::is_numeric($working_size) && $working_size > $size ) { $size = $working_size; } - #print "ws-b: $working_size s-2: $size\n"; + # print "ws-b: $working_size s-2: $size\n"; } else { $size = 0; } - #print "d-2: $data s-3: $size\n"; + # print "d-2: $data s-3: $size\n"; return $size; } +sub speed_mapper { + my ($type) = @_; + my %speeds = ( + # DDR + 'PC-1600' => 200, + 'PC-2100' => 266, + 'PC-2400' => 300, + 'PC-2700' => 333, + 'PC-3200' => 400, + # DDR2 + 'PC2-3200' => 400, + 'PC2-4200' => 533, + 'PC2-5300' => 667, + 'PC2-6400' => 800, + 'PC2-8000' => 1000, + # DDR3 + 'PC3-6400' => 800, + 'PC3-8500' => 1066, + 'PC3-10600' => 1333, + 'PC3-12800' => 1600, + # DDR4 + 'PC4-19200' => 2400, + 'PC4-21300' => 2666, + 'PC4-23400' => 2933, + 'PC4-24000' => 3000, + 'PC4-25600' => 3200, + 'PC4-28800' => 3600, + 'PC4-32000' => 4000, + 'PC4-35200' => 4400, + # DDR5 + 'PC5-38400' => 4800, + 'PC5-51200' => 6400, + # DDR6, coming... + ); + return ($speeds{$type}) ? $speeds{$type} . ' MT/s' : $type; +} +sub set_vendors { + @vendors = ( + # A-Data xpg: AX4U; AX\d{4} for axiom + ['^(A[DX]\dU|AVD|A[\s-]?Data)','A[\s-]?Data','A-Data',''], + ['^(A[\s-]?Tech)','A[\s-]?Tech','A-Tech',''], # don't know part nu + ['^(AX[\d]{4}|Axiom)','Axiom','Axiom',''], + ['^(BD\d|Black[s-]?Diamond)','Black[s-]?Diamond','Black Diamond',''], + ['^(-BN$|Brute[s-]?Networks)','Brute[s-]?Networks','Brute Networks',''], + ['^(CM|Corsair)','Corsair','Corsair',''], + ['^(CT\d|BL|Crucial)','Crucial','Crucial',''], + ['^(CY|Cypress)','Cypress','Cypress',''], + ['^(SNP|Dell)','Dell','Dell',''], + ['^(PE[\d]{4}|Edge)','Edge','Edge',''], + ['^(GVT|Galvantech)','Galvantech','Galvantech',''], + # if we get more G starters, make rules tighter + ['^(G[A-Z]|Geil)','Geil','Geil',''], + # Note: FA- but make loose FA + ['^(F4|G[\s\.-]?Skill)','G[\s\.-]?Skill','G.Skill',''], + ['^(HP)','','HP',''], # no IDs found + ['^(HX|HyperX)','HyperX','HyperX',''], + ['^(HY|Infineon)','Infineon','Infineon',''],#HY[A-Z]\d + ['^(KSM|KVR|Kingston)','Kingston','Kingston',''], + ['^(MT|Micron)','Micron','Micron',''], + ['^(M[BLERS][A-Z][1-7]|Mushkin)','Mushkin','Mushkin',''], + ['^(OCZ)','^OCZ\b','OCZ',''], + ['^([MN]D\d|OLOy)','OLOy','OLOy',''], + ['^(M[ERS]\d|Nemix)','Nemix','Nemix',''], + # before patriot just in case + ['^(MN\d|PNY)','PNY\s','PNY',''], + ['^(P[A-Z]|Patriot)','Patriot','Patriot',''], + ['^(K[1-6][ABT]|K[1-6][\d]{3}|M[\d]{3}[A-Z]|Samsung)','Samsung','Samsung',''], + ['^(SP|Silicon[\s-]?Power)','Silicon[\s-]?Power','Silicon Power',''], + ['^(STK|Simtek)','Simtek','Simtek',''], + ['^(HM[ACT]|SK[\s-]?Hynix)','SK[\s-]?Hynix','SK-Hynix',''], + # TED TTZD TLRD TDZAD TF4D4 TPD4 TXKD4 seen: HMT but could by skh + #['^(T(ED|D[PZ]|F\d|LZ|P[DR]T[CZ]|XK)|Team[\s-]?Group)','Team[\s-]?Group','TeamGroup',''], + ['^(T[^\dR]|Team[\s-]?Group)','Team[\s-]?Group','TeamGroup',''], + ['^(TR\d|JM\d|Transcend)','Transcend','Transcend',''], + ['^(VK\d|Vaseky)','Vaseky','Vaseky',''], + ); +} +sub ram_vendor { + eval $end if $b_log; + my ($id) = $_[0]; + set_vendors() if !@vendors; + my ($vendor,@data); + foreach my $row (@vendors){ + if ($id =~ /$row->[0]/i){ + $vendor = $row->[2]; + # Usually we want to assign N/A at output phase, maybe do this logic there? + if ($row->[1]){ + if ($id !~ m/$row->[1]$/i){ + $id =~ s/$row->[1]//i; + } + else { + $id = 'N/A'; + } + } + $id =~ s/^[\/\[\s_-]+|[\/\s_-]+$//g; + $id =~ s/\s\s/ /g; + @data = ($vendor,$id); + last; + } + } + eval $end if $b_log; + return @data; +} } -## RepoData +## RepoItem { -package RepoData; +package RepoItem; # easier to keep these package global, but undef after done my (@dbg_files,$debugger_dir); @@ -16779,13 +17686,13 @@ sub get_repos_linux { # critical: whitespace is the separator, no logical ordering of # field names exists within each entry. @data2 = main::reader($file); - #print Data::Dumper::Dumper \@data2; + # print Data::Dumper::Dumper \@data2; if (@data2){ @data2 = map {s/^\s*$/~/;$_} @data2; push(@data2, '~'); } push(@dbg_files, $file) if $debugger_dir; - #print "$file\n"; + # print "$file\n"; @apt_urls = (); @apt_working = (); $b_apt_enabled = 1; @@ -16796,20 +17703,20 @@ sub get_repos_linux { next if $row =~ /^\s+/ && $row !~ /^\s+[^#]+:\//; # strip out line space starters now that it's safe $row =~ s/^\s+//; - #print "$row\n"; + # print "$row\n"; if ($row eq '~'){ if (@apt_working && $b_apt_enabled){ - #print "1: url builder\n"; + # print "1: url builder\n"; foreach $repo (@apt_working){ $string = $apt_types; $string .= ' [arch=' . $apt_arch . ']' if $apt_arch; $string .= ' ' . $repo; $string .= ' ' . $apt_suites if $apt_suites ; $string .= ' ' . $apt_comp if $apt_comp; - #print "s1:$string\n"; + # print "s1:$string\n"; push(@data3, $string); } - #print join("\n",@data3),"\n"; + # print join("\n",@data3),"\n"; push(@apt_urls,@data3); } @data3 = (); @@ -16820,9 +17727,9 @@ sub get_repos_linux { $apt_types = ''; $b_apt_enabled = 1; } - #print "row:$row\n"; + # print "row:$row\n"; elsif ($row =~ /^Types:\s*(.*)/i){ - #print "ath:$type_holder\n"; + # print "ath:$type_holder\n"; $apt_types = $1; } elsif ($row =~ /^Enabled:\s*(.*)/i){ @@ -16965,7 +17872,7 @@ sub get_repos_linux { $repo = 'zypp'; } #$repo = 'yum'; - #push(@files, "$ENV{'HOME'}/bin/scripts/inxi/data/repo/yum/rpmfusion-nonfree-1.repo"); + # push(@files, "$ENV{'HOME'}/bin/scripts/inxi/data/repo/yum/rpmfusion-nonfree-1.repo"); if (@files){ foreach (sort @files){ @data2 = main::reader($_); @@ -17180,8 +18087,8 @@ sub get_repos_linux { #$path = 'eopkg'; my $which = ($path =~ /pisi$/) ? 'pisi': 'eopkg'; my $cmd = ($which eq 'pisi') ? "$path list-repo": "$path lr"; - #my $file = "$ENV{HOME}/bin/scripts/inxi/data/repo/solus/eopkg-2.txt"; - #@data2 = main::reader($file,'strip'); + # my $file = "$ENV{HOME}/bin/scripts/inxi/data/repo/solus/eopkg-2.txt"; + # @data2 = main::reader($file,'strip'); @data2 = main::grabber("$cmd 2>/dev/null","\n",'strip'); main::writer("$debugger_dir/system-repo-data-$which.txt",\@data2) if $debugger_dir; # now we need to create the structure: repo info: repo path @@ -17299,7 +18206,7 @@ sub get_repos_bsd { $url = "$data2[1]:$data2[2]"; $url =~ s/"|,//g; } - #print "url:$url\n" if $url; + # print "url:$url\n" if $url; if ($data2[0] eq 'enabled'){ if ($url && $data2[1] =~ /^(1|true|yes)$/i){ push(@data3, "$url"); @@ -17498,9 +18405,9 @@ sub file_path { } } -## SensorData +## SensorItem { -package SensorData; +package SensorItem; sub get { eval $start if $b_log; my ($key1,$program,$val1,@data,@rows,%sensors); @@ -17517,7 +18424,7 @@ sub get { if (!@data) { $key1 = 'Message'; $val1 = main::row_defaults('sensors-data-ipmi'); - #$val1 = main::row_defaults('dev'); + # $val1 = main::row_defaults('dev'); @data = ({main::key($num++,0,1,$key1) => $val1,}); } push(@rows,@data); @@ -17530,25 +18437,43 @@ sub get { push(@rows,@data); } } - if (!$fake{'sensors'} && $alerts{'sensors'}->{'action'} ne 'use'){ - #print "here 1\n"; - $key1 = $alerts{'sensors'}->{'action'}; - $val1 = $alerts{'sensors'}->{'message'}; - $key1 = ucfirst($key1); - @data = ({main::key($num++,0,1,$key1) => $val1,}); - push(@rows,@data); - } - else { - %sensors = lm_sensors_data(); - @data = sensors_output($source,\%sensors); - #print "here 2\n"; - if (!@data) { + if ($sysctl{'sensor'}){ + %sensors = sysctl_data(); + @data = sensors_output('sysctl-sensors',\%sensors); + if (!@data){ $key1 = 'Message'; - $val1 = main::row_defaults('sensors-data-linux'); + $val1 = main::row_defaults('sensors-data-bsd',$uname[0]); @data = ({main::key($num++,0,1,$key1) => $val1,}); } push(@rows,@data); } + else { + if (!$fake{'sensors'} && $alerts{'sensors'}->{'action'} ne 'use'){ + # print "here 1\n"; + if ($bsd_type && $bsd_type =~ /^(free|open)bsd/){ + $key1 = 'Message'; + $val1 = main::row_defaults('sensors-data-bsd-ok'); + } + else { + $key1 = $alerts{'sensors'}->{'action'}; + $val1 = $alerts{'sensors'}->{'message'}; + $key1 = ucfirst($key1); + } + @data = ({main::key($num++,0,1,$key1) => $val1,}); + push(@rows,@data); + } + else { + %sensors = lm_sensors_data(); + @data = sensors_output($source,\%sensors); + # print "here 2\n"; + if (!@data) { + $key1 = 'Message'; + $val1 = main::row_defaults('sensors-data-linux'); + @data = ({main::key($num++,0,1,$key1) => $val1,}); + } + push(@rows,@data); + } + } eval $end if $b_log; return @rows; } @@ -17715,14 +18640,15 @@ sub ipmi_data { $temp_working,$working_unit); my ($b_ipmitool,$i_key,$i_value,$i_unit); if ($fake{'ipmi'}){ - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-archerseven-1.txt";$program='ipmitool'; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-crazy-epyc-1.txt";$program='ipmitool'; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-RK016013.txt";$program='ipmitool'; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-freebsd-offsite-backup.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-crazy-epyc-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-lathander.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-zwerg.txt"; - #@data = main::reader($file); + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-archerseven-1.txt";$program='ipmitool'; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-crazy-epyc-1.txt";$program='ipmitool'; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-RK016013.txt";$program='ipmitool'; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-freebsd-offsite-backup.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-crazy-epyc-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-lathander.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-zwerg.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-arm-server-1.txt"; + # @data = main::reader($file); #($b_ipmitool,$i_key,$i_value,$i_unit) = (0,1,3,4); # ipmi-sensors #($b_ipmitool,$i_key,$i_value,$i_unit) = (1,0,1,2); # ipmitool sensors } @@ -17745,7 +18671,7 @@ sub ipmi_data { next if /^\s*$/; # print "$_\n"; @row = split(/\s*\|\s*/, $_); - #print "$row[$i_value]\n"; + # print "$row[$i_value]\n"; next if !main::is_numeric($row[$i_value]); # print "$row[$i_key] - $row[$i_value]\n"; if (!$sensors{'mobo-temp'} && $row[$i_key] =~ /^(MB_TEMP[0-9]|System[\s_]Temp|System[\s_]?Board([\s_]Temp)?)$/i){ @@ -17763,7 +18689,7 @@ sub ipmi_data { # Platform Control Hub (PCH), it is the X370 chip on the Crosshair VI Hero. # VRM: voltage regulator module # NOTE: CPU0_TEMP CPU1_TEMP is possible, unfortunately; CPU Temp Interf - elsif ( !$sensors{'cpu-temp'} && $row[$i_key] =~ /^CPU([01])?([\s_]Temp)?$/i) { + elsif (!$sensors{'cpu-temp'} && $row[$i_key] =~ /^CPU([01])?([\s_]Temp)?$/i) { $b_cpu_0 = 1 if defined $1 && $1 == 0; $sensors{'cpu-temp'} = int($row[$i_value]); $working_unit = $row[$i_unit]; @@ -17824,10 +18750,10 @@ sub ipmi_data { $sys_fan_nu = hex($2); $fan_working = int($row[$i_value]); $sensors{'fan-default'} = () if !$sensors{'fan-default'}; - if ( $sys_fan_nu =~ /^([0-9]+)$/ ) { + if ($sys_fan_nu =~ /^([0-9]+)$/) { # add to array if array index does not exist OR if number is > existing number if ( defined $sensors{'fan-default'}->[$sys_fan_nu] ) { - if ( $fan_working >= $sensors{'fan-default'}->[$sys_fan_nu] ) { + if ($fan_working >= $sensors{'fan-default'}->[$sys_fan_nu]) { $sensors{'fan-default'}->[$sys_fan_nu] = $fan_working; } } @@ -17846,23 +18772,23 @@ sub ipmi_data { $sensors{'fan-psu-2'} = int($row[$i_value]); } if ($extra > 0){ - if ($row[$i_key] =~ /^(MAIN\s|P[_]?)?12V$/i) { + if ($row[$i_key] =~ /^((MAIN\s|P[_]?)?12V|PSU[12]_VOUT)$/i) { $sensors{'volts-12'} = $row[$i_value]; } - elsif ($row[$i_key] =~ /^(MAIN\s5V|P5V|5VCC|5V PG)$/i) { + elsif ($row[$i_key] =~ /^(MAIN\s5V|P5V|5VCC|5V PG|5V_SB)$/i) { $sensors{'volts-5'} = $row[$i_value]; } - elsif ($row[$i_key] =~ /^(MAIN\s3.3V|P3V3|3.3VCC|3.3V PG)$/i) { + elsif ($row[$i_key] =~ /^(MAIN\s3\.3V|P3V3|3\.3VCC|3\.3V PG|3V3_SB)$/i) { $sensors{'volts-3.3'} = $row[$i_value]; } elsif ($row[$i_key] =~ /^((P_)?VBAT|CMOS Battery|BATT 3.0V)$/i) { $sensors{'volts-vbat'} = $row[$i_value]; } # NOTE: VDimmP1ABC VDimmP1DEF - elsif (!$sensors{'volts-dimm-p1'} && $row[$i_key] =~ /^(P1_VMEM|VDimmP1|MEM RSR A PG)/i) { + elsif (!$sensors{'volts-dimm-p1'} && $row[$i_key] =~ /^(P1_VMEM|VDimmP1|MEM RSR A PG|DIMM_VR1_VOLT)/i) { $sensors{'volts-dimm-p1'} = $row[$i_value]; } - elsif (! $sensors{'volts-dimm-p2'} && $row[$i_key] =~ /^(P2_VMEM|VDimmP2|MEM RSR B PG)/i) { + elsif (!$sensors{'volts-dimm-p2'} && $row[$i_key] =~ /^(P2_VMEM|VDimmP2|MEM RSR B PG|DIMM_VR2_VOLT)/i) { $sensors{'volts-dimm-p2'} = $row[$i_value]; } elsif (!$sensors{'volts-soc-p1'} && $row[$i_key] =~ /^(P1_SOC_RUN$)/i) { @@ -17896,7 +18822,7 @@ sub lm_sensors_data { foreach (@{$sensors_raw{'main'}->{$adapter}}){ my @working = split(':', $_); next if !$working[0]; - #print "$working[0]:$working[1]\n"; + # print "$working[0]:$working[1]\n"; # There are some guesses here, but with more sensors samples it will get closer. # note: using arrays starting at 1 for all fan arrays to make it easier overall # we have to be sure we are working with the actual real string before assigning @@ -17924,7 +18850,7 @@ sub lm_sensors_data { elsif ($_ =~ /^(T?CPU.*|Tdie.*):([0-9\.]+)[\s°]*(C|F)/i) { $temp_working = $2; $working_unit = $3; - if ( !$sensors{'cpu-temp'} || + if (!$sensors{'cpu-temp'} || ( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'cpu-temp'} ) ) { $sensors{'cpu-temp'} = $temp_working; } @@ -18018,9 +18944,9 @@ sub lm_sensors_data { elsif ($_ =~ /^FAN([2-9]|1[0-9]).*:([0-9]+)[\s]RPM/i) { $fan_working = $2; $sys_fan_nu = $1; - if ( $sys_fan_nu =~ /^([0-9]+)$/ ) { + if ($sys_fan_nu =~ /^([0-9]+)$/) { # add to array if array index does not exist OR if number is > existing number - if ( defined $sensors{'fan-default'}->[$sys_fan_nu] ) { + if (defined $sensors{'fan-default'}->[$sys_fan_nu]) { if ( $fan_working >= $sensors{'fan-default'}->[$sys_fan_nu] ) { $sensors{'fan-default'}->[$sys_fan_nu] = $fan_working; } @@ -18062,13 +18988,13 @@ sub process_lm_sensors { my (@data,@sensors_data,@values); my ($adapter,$holder,$type) = ('','',''); if ($fake{'sensors'}){ - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/amdgpu-w-fan-speed-stretch-k10.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/peci-tin-geggo.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-w-other-biker.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-asus-chassis-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-devnull-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-jammin1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-mx-incorrect-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/amdgpu-w-fan-speed-stretch-k10.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/peci-tin-geggo.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-w-other-biker.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-asus-chassis-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-devnull-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-jammin1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-mx-incorrect-1.txt"; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-maximus-arch-1.txt"; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/kernel-58-sensors-ant-1.txt"; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-zenpower-nvme-2.txt"; @@ -18083,9 +19009,9 @@ sub process_lm_sensors { @sensors_data = map {$_ =~ s/\s*:\s*\+?/:/;$_} @sensors_data; push(@sensors_data, 'END'); } - #print Data::Dumper::Dumper \@sensors_data; + # print Data::Dumper::Dumper \@sensors_data; foreach (@sensors_data){ - #print 'st:', $_, "\n"; + # print 'st:', $_, "\n"; next if /^\s*$/; $_ = main::trimmer($_); if (@values && $adapter && (/^Adapter/ || $_ eq 'END')){ @@ -18131,29 +19057,82 @@ sub process_lm_sensors { return @data; } -# oddly, openbsd sysctl actually has hw.sensors data! +# bsds sysctl may have hw.sensors data sub sysctl_data { eval $start if $b_log; my (@data,%sensors); - foreach (@sysctl_sensors){ - if (/^hw.sensors\.([0-9a-z]+)\.(temp|fan|volt)([0-9])/){ - my $sensor = $1; - my $type = $2; - my $number = $3; - my @working = split(':', $_); + # assume always starts at 0, can't do dynamic because freebsd shows tz1 first + my $add = 1; + foreach (@{$sysctl{'sensor'}}){ + my ($sensor,$type,$number,$value); + if (/^hw\.sensors\.([a-z]+)([0-9]+)\.(cpu|temp|fan|volt)([0-9])/){ + $sensor = $1; + $type = $3; + $number = $4; + # hw.sensors.cpu0.temp0:47.00 degC + # hw.sensors.acpitz0.temp0:43.00 degC + $type = 'cpu' if $sensor eq 'cpu'; + } + elsif (/^hw\.sensors\.(acpi)\.(thermal)\.(tz)([0-9]+)\.(temperature)/){ + $sensor = $1 . $3; # eg acpitz + $type = ($5 eq 'temperature') ? 'temp': $5; + $number = $4; + } + elsif (/^dev\.(cpu)\.([0-9]+)\.(temperature)/){ + $sensor = $1; + $type = $3; + $number = $2; + $type = 'cpu' if $sensor eq 'cpu'; + } + if ($sensor && $type){ + if ($sensor && ((@sensors_use && !(grep {/$sensor/} @sensors_use)) || + (@sensors_exclude && (grep {/$sensor/} @sensors_exclude)))){ + next; + } + my $working = (split(':\s*', $_))[1]; + if (defined $working && $working =~ /^([0-9\.]+)\s?((deg)?([CF]))?\b/){ + $value = $1 ; + $sensors{'temp-unit'} = $4 if $4 && !$sensors{'temp-unit'}; + } + else { + next; + } + $number += $add; + if ($type eq 'cpu' && !defined $sensors{'cpu-temp'}){ + $sensors{'cpu-temp'} = $value; + } + elsif ($type eq 'temp' && !defined $sensors{'temp' . $number}){ + $sensors{'temp' . $number} = $value; + } + elsif ($type eq 'fan' && !defined $sensors{'fan-main'}->[$number]){ + $sensors{'fan-main'}->[$number] = $value; + } + elsif ($type eq 'volt'){ + if ($working =~ /\+3\.3V/i){ + $sensors{'volts-3.3'} = $value; + } + elsif ($working =~ /\+5V/i){ + $sensors{'volts-5'} = $value; + } + elsif ($working =~ /\+12V/i){ + $sensors{'volts-12'} = $value; + } + elsif ($working =~ /VBAT/i){ + $sensors{'volts-vbat'} = $value; + } + } } - last if /^(hw.cpuspeed|hw.vendor|hw.physmem)/; } %sensors = process_data(%sensors) if %sensors; main::log_data('dump','%sensors',\%sensors) if $b_log; - # print Data::Dumper::Dumper \%sensors; + print Data::Dumper::Dumper \%sensors if $dbg[31];; eval $end if $b_log; return %sensors; } sub set_temp_unit { my ($sensors,$working) = @_; my $return_unit = ''; - if ( !$sensors && $working ){ + if (!$sensors && $working){ $return_unit = $working; } elsif ($sensors){ @@ -18174,23 +19153,23 @@ sub process_data { # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment # this is wrong for systems with > 2 tempX readings, but the logic is too complex with 3 variables # so have to accept that it will be wrong in some cases, particularly for motherboard temp readings. - if ( $sensors{'temp1'} && $sensors{'temp2'} ){ - if ( $sensors_cpu_nu ) { + if ($sensors{'temp1'} && $sensors{'temp2'}){ + if ($sensors_cpu_nu) { $fan_type = $sensors_cpu_nu; } else { # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed # but only if other fan speed is 0. - if ( $sensors{'temp1'} >= $sensors{'temp2'} && - defined $fan_default[1] && defined $fan_default[2] && $fan_default[1] == 0 && $fan_default[2] > 0 ) { + if ($sensors{'temp1'} >= $sensors{'temp2'} && + defined $fan_default[1] && defined $fan_default[2] && $fan_default[1] == 0 && $fan_default[2] > 0) { $fan_type = 2; } - elsif ( $sensors{'temp2'} >= $sensors{'temp1'} && - defined $fan_default[1] && defined $fan_default[2] && $fan_default[2] == 0 && $fan_default[1] > 0 ) { + elsif ($sensors{'temp2'} >= $sensors{'temp1'} && + defined $fan_default[1] && defined $fan_default[2] && $fan_default[2] == 0 && $fan_default[1] > 0) { $fan_type = 1; } # then handle the standard case if these fringe cases are false - elsif ( $sensors{'temp1'} >= $sensors{'temp2'} ) { + elsif ($sensors{'temp1'} >= $sensors{'temp2'}) { $fan_type = 1; } else { @@ -18199,24 +19178,24 @@ sub process_data { } } # need a case for no temps at all reported, like with old intels - elsif ( !$sensors{'temp2'} && !$sensors{'cpu-temp'} ){ - if ( !$sensors{'temp1'} && !$sensors{'mobo-temp'} ){ + elsif (!$sensors{'temp2'} && !$sensors{'cpu-temp'}){ + if (!$sensors{'temp1'} && !$sensors{'mobo-temp'}){ $fan_type = 1; } - elsif ( $sensors{'temp1'} && !$sensors{'mobo-temp'} ){ + elsif ($sensors{'temp1'} && !$sensors{'mobo-temp'}){ $fan_type = 1; } - elsif ( $sensors{'temp1'} && $sensors{'mobo-temp'} ){ + elsif ($sensors{'temp1'} && $sensors{'mobo-temp'}){ $fan_type = 1; } } # convert the diff number for F, it needs to be bigger that is - if ( $sensors{'temp-unit'} && $sensors{'temp-unit'} eq "F" ) { + if ($sensors{'temp-unit'} && $sensors{'temp-unit'} eq "F") { $temp_diff = $temp_diff * 1.8 } - if ( $sensors{'cpu-temp'} ) { + if ($sensors{'cpu-temp'}) { # specific hack to handle broken CPUTIN temps with PECI - if ( $sensors{'cpu-peci-temp'} && ( $sensors{'cpu-temp'} - $sensors{'cpu-peci-temp'} ) > $temp_diff ){ + if ($sensors{'cpu-peci-temp'} && ($sensors{'cpu-temp'} - $sensors{'cpu-peci-temp'}) > $temp_diff){ $cpu_temp = $sensors{'cpu-peci-temp'}; } # then get the real cpu temp, best guess is hottest is real, though only within narrowed diff range @@ -18225,10 +19204,10 @@ sub process_data { } } else { - if ($fan_type ){ + if ($fan_type){ # there are some weird scenarios - if ( $fan_type == 1 ){ - if ( $sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp2'} > $sensors{'temp1'} ) { + if ($fan_type == 1){ + if ($sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp2'} > $sensors{'temp1'}) { $cpu_temp = $sensors{'temp2'}; } else { @@ -18236,7 +19215,7 @@ sub process_data { } } else { - if ( $sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp1'} > $sensors{'temp2'} ) { + if ($sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp1'} > $sensors{'temp2'}) { $cpu_temp = $sensors{'temp1'}; } else { @@ -18247,36 +19226,36 @@ sub process_data { else { $cpu_temp = $sensors{'temp1'}; # can be null, that is ok } - if ( $cpu_temp ) { + if ($cpu_temp) { # using $sensors{'temp3'} is just not reliable enough, more errors caused than fixed imo - #if ( $sensors{'temp3'} && $sensors{'temp3'} > $cpu_temp ) { + # if ( $sensors{'temp3'} && $sensors{'temp3'} > $cpu_temp ) { # $cpu_temp = $sensors{'temp3'}; - #} + # } # there are some absurdly wrong $sensors{'temp1'}: acpitz-virtual-0 $sensors{'temp1'}: +13.8°C - if ( $sensors{'core-0-temp'} && ($sensors{'core-0-temp'} - $cpu_temp) > $temp_diff ) { + if ($sensors{'core-0-temp'} && ($sensors{'core-0-temp'} - $cpu_temp) > $temp_diff) { $cpu_temp = $sensors{'core-0-temp'}; } } } # if all else fails, use core0/peci temp if present and cpu is null - if ( !$cpu_temp ) { - if ( $sensors{'core-0-temp'} ) { + if (!$cpu_temp) { + if ($sensors{'core-0-temp'}) { $cpu_temp = $sensors{'core-0-temp'}; } # note that peci temp is known to be colder than the actual system # sometimes so it is the last fallback we want to use even though in theory # it is more accurate, but fact suggests theory wrong. - elsif ( $sensors{'cpu-peci-temp'} ) { + elsif ($sensors{'cpu-peci-temp'}) { $cpu_temp = $sensors{'cpu-peci-temp'}; } } # then the real mobo temp - if ( $sensors{'mobo-temp'} ){ + if ($sensors{'mobo-temp'}){ $mobo_temp = $sensors{'mobo-temp'}; } - elsif ( $fan_type ){ - if ( $fan_type == 1 ) { - if ( $sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp2'} > $sensors{'temp1'} ) { + elsif ($fan_type){ + if ($fan_type == 1) { + if ($sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp2'} > $sensors{'temp1'}) { $mobo_temp = $sensors{'temp1'}; } else { @@ -18284,7 +19263,7 @@ sub process_data { } } else { - if ( $sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp1'} > $sensors{'temp2'} ) { + if ($sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp1'} > $sensors{'temp2'}) { $mobo_temp = $sensors{'temp2'}; } else { @@ -18292,35 +19271,42 @@ sub process_data { } } ## NOTE: not safe to assume $sensors{'temp3'} is the mobo temp, sad to say - #if ( $sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp3'} && $sensors{'temp3'} < $mobo_temp ) { - # $mobo_temp = $sensors{'temp3'}; - #} + # if ( $sensors{'temp1'} && $sensors{'temp2'} && $sensors{'temp3'} && $sensors{'temp3'} < $mobo_temp ) { + # $mobo_temp = $sensors{'temp3'}; + # } } + # in case with cpu-temp AND temp1 and not temp 2, or temp 2 only, fan type: 0 else { - $mobo_temp = $sensors{'temp2'}; + if ($sensors{'cpu-temp'} && $sensors{'temp1'} && + $sensors{'cpu-temp'} > $sensors{'temp1'}){ + $mobo_temp = $sensors{'temp1'}; + } + elsif ($sensors{'temp2'}) { + $mobo_temp = $sensors{'temp2'}; + } } @fan_main = @{$sensors{'fan-main'}} if $sensors{'fan-main'}; $index_count_fan_main = (@fan_main) ? scalar @fan_main : 0; @fan_default = @{$sensors{'fan-default'}} if $sensors{'fan-default'}; $index_count_fan_default = (@fan_default) ? scalar @fan_default : 0; # then set the cpu fan speed - if ( ! $fan_main[1] ) { + if (!$fan_main[1]) { # note, you cannot test for $fan_default[1] or [2] != "" # because that creates an array item in gawk just by the test itself - if ( $fan_type == 1 && defined $fan_default[1] ) { + if ($fan_type == 1 && defined $fan_default[1]) { $fan_main[1] = $fan_default[1]; $fan_default[1] = undef; } - elsif ( $fan_type == 2 && defined $fan_default[2] ) { + elsif ($fan_type == 2 && defined $fan_default[2]) { $fan_main[1] = $fan_default[2]; $fan_default[2] = undef; } } # clear out any duplicates. Primary fan real trumps fan working always if same speed for ($i = 1; $i <= $index_count_fan_main; $i++) { - if ( defined $fan_main[$i] && $fan_main[$i] ) { + if (defined $fan_main[$i] && $fan_main[$i]) { for ($j = 1; $j <= $index_count_fan_default; $j++) { - if ( defined $fan_default[$j] && $fan_main[$i] == $fan_default[$j] ) { + if (defined $fan_default[$j] && $fan_main[$i] == $fan_default[$j]) { $fan_default[$j] = undef; } } @@ -18335,17 +19321,17 @@ sub process_data { # Note: gensub is the culprit I think, assigning type string for range 501-1000 but # type integer for all others, this triggers true for > for ($j = 1; $j <= $index_count_fan_default; $j++) { - if ( defined $fan_default[$j] && $fan_default[$j] > 5000 && !$fan_main[2] ) { + if (defined $fan_default[$j] && $fan_default[$j] > 5000 && !$fan_main[2]) { $fan_main[2] = $fan_default[$j]; $fan_default[$j] = ''; # then add one if required for output - if ( $index_count_fan_main < 2 ) { + if ($index_count_fan_main < 2) { $index_count_fan_main = 2; } } } # if they are ALL null, print error message. psFan is not used in output currently - if ( !$cpu_temp && !$mobo_temp && !$fan_main[1] && !$fan_main[2] && !$fan_main[1] && !@fan_default ) { + if (!$cpu_temp && !$mobo_temp && !$fan_main[1] && !$fan_main[2] && !$fan_main[1] && !@fan_default) { %sensors = (); } else { @@ -18363,7 +19349,7 @@ sub process_data { $psu2_fan = $sensors{'fan-psu-2'} if $sensors{'fan-psu-2'}; # so far only for ipmi, sensors data is junk for volts if ($extra > 0 && - ($sensors{'volts-12'} || $sensors{'volts-5'} || $sensors{'volts-3.3'} || $sensors{'volts-vbat'}) ){ + ($sensors{'volts-12'} || $sensors{'volts-5'} || $sensors{'volts-3.3'} || $sensors{'volts-vbat'})){ $v_12 = $sensors{'volts-12'} if $sensors{'volts-12'}; $v_5 = $sensors{'volts-5'} if $sensors{'volts-5'}; $v_3_3 = $sensors{'volts-3.3'} if $sensors{'volts-3.3'}; @@ -18495,7 +19481,7 @@ sub gpu_data { } } if ($sensors_raw{'gpu'}){ - #my ($b_found,$holder) = (0,''); + # my ($b_found,$holder) = (0,''); foreach my $adapter (keys %{$sensors_raw{'gpu'}}){ $j = scalar @gpudata; $gpudata[$j]->{'type'} = $adapter; @@ -18537,10 +19523,9 @@ sub gpu_data { } } -## SlotData +## SlotItem { -package SlotData; - +package SlotItem; sub get { eval $start if $b_log; my (@rows,$key1,$val1); @@ -18624,15 +19609,15 @@ sub slot_output { } } -## SwapData +## SwapItem { -package SwapData; +package SwapItem; sub get { eval $start if $b_log; my (@rows); my $num = 0; - @rows = swap_output(); + @rows = create_output(); if (!@rows){ push(@rows, {main::key($num++,0,1,'Alert') => main::row_defaults('swap-data')}, @@ -18641,20 +19626,20 @@ sub get { eval $end if $b_log; return @rows; } -sub swap_output { +sub create_output { eval $start if $b_log; my $num = 0; my $j = 0; - my (%part,@rows,$dev,$percent,$raw_size,$size,$used); - main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; + my (@rows,$dev,$percent,$raw_size,$size,$used); + PartitionData::set() if !$bsd_type && !$loaded{'partition-data'}; + DiskDataBSD::set() if $bsd_type && !$loaded{'disk-data-bsd'}; main::set_mapper() if !$loaded{'mapper'}; - my @swap_data = PartitionData::swap_data(); - foreach my $row (@swap_data){ + PartitionItem::swap_data() if !$loaded{'set-swap'}; + foreach my $row (@swaps){ $num = 1; $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; $used = main::get_size($row->{'used'},'string','N/A'); # used can be 0 $percent = (defined $row->{'percent-used'}) ? ' (' . $row->{'percent-used'} . '%)' : ''; - %part = (); $dev = ($row->{'swap-type'} eq 'file') ? 'file' : 'dev'; $row->{'swap-type'} = ($row->{'swap-type'}) ? $row->{'swap-type'} : 'N/A'; if ($b_admin && !$bsd_type && $j == 0){ @@ -18721,27 +19706,47 @@ sub swap_output { } -## UnmountedData +## UnmountedItem { -package UnmountedData; +package UnmountedItem; sub get { eval $start if $b_log; my (@data,@rows,$key1,$val1); my $num = 0; if ($bsd_type){ - $key1 = 'Message'; - $val1 = main::row_defaults('unmounted-data-bsd'); - } - else { - if (main::system_files('partitions')){ - @data = unmounted_data(); + DiskDataBSD::set() if !$loaded{'disk-data-bsd'}; + if (%disks_bsd && ($alerts{'disklabel'}->{'action'} eq 'use' || + $alerts{'gpart'}->{'action'} eq 'use')){ + @data = bsd_data(); if (!@data){ $key1 = 'Message'; $val1 = main::row_defaults('unmounted-data'); } else { - @rows = unmounted_output(\@data); + @rows = create_output(\@data); + } + } + else { + if ($alerts{'disklabel'}->{'action'} eq 'permissions'){ + $key1 = 'Message'; + $val1 = $alerts{'disklabel'}->{'message'}; + } + else { + $key1 = 'Message'; + $val1 = main::row_defaults('unmounted-data-bsd',$uname[0]); + } + } + } + else { + if ($system_files{'proc-partitions'}){ + @data = proc_data(); + if (!@data){ + $key1 = 'Message'; + $val1 = main::row_defaults('unmounted-data'); + } + else { + @rows = create_output(\@data); } } else { @@ -18755,7 +19760,7 @@ sub get { eval $end if $b_log; return @rows; } -sub unmounted_output { +sub create_output { eval $start if $b_log; my ($unmounted) = @_; my (@rows,$fs); @@ -18768,7 +19773,10 @@ sub unmounted_output { $fs = lc($row->{'fs'}); } else { - if (main::check_program('file')){ + if ($bsd_type){ + $fs = 'N/A'; + } + elsif (main::check_program('file')){ $fs = ($b_root) ? 'N/A' : main::row_defaults('root-required'); } else { @@ -18787,15 +19795,20 @@ sub unmounted_output { if ($extra > 0 && $row->{'dev-mapped'}){ $rows[$j]->{main::key($num++,0,2,'mapped')} = $row->{'dev-mapped'}; } + $row->{'label'} ||= 'N/A'; + $row->{'uuid'} ||= 'N/A'; $rows[$j]->{main::key($num++,0,2,'size')} = $size; $rows[$j]->{main::key($num++,0,2,'fs')} = $fs; - $rows[$j]->{main::key($num++,0,2,'label')} = $row->{'label'}; - $rows[$j]->{main::key($num++,0,2,'uuid')} = $row->{'uuid'}; + # don't show for fs known to not have label/uuid + if ($fs !~ /^(ffs)$/){ + $rows[$j]->{main::key($num++,0,2,'label')} = $row->{'label'}; + $rows[$j]->{main::key($num++,0,2,'uuid')} = $row->{'uuid'}; + } } eval $end if $b_log; return @rows; } -sub unmounted_data { +sub proc_data { eval $start if $b_log; my ($dev_mapped,$fs,$label,$maj_min,$size,$uuid,%part,@unmounted); # last filters to make sure these are dumped @@ -18803,10 +19816,10 @@ sub unmounted_data { 'dvd[0-9]*','dvdrw[0-9]*','fd[0-9]','ram[0-9]*'); my $num = 0; # set labels, uuid, gpart - PartitionData::partition_data() if !$loaded{'partitions'}; - RaidData::raid_data() if !$loaded{'raid'}; + PartitionItem::set_partitions() if !$loaded{'set-partitions'}; + RaidItem::raid_data() if !$loaded{'raid'}; my @mounted = get_mounted(); - #print join("\n",(@filters,@mounted)),"\n"; + # print join("\n",(@filters,@mounted)),"\n"; foreach my $row (@proc_partitions){ ($dev_mapped,$fs,$label,$maj_min,$uuid,$size) = ('','','','','',''); # note that size 1 means it is a logical extended partition container @@ -18818,7 +19831,7 @@ sub unmounted_data { # the unmounted report because sdb was found in sdb1, but match of eg sdb1 and sdb12 # makes this a problem, so usinig zfs_member test instead to filter out zfs members. # in arm/android seen /dev/block/mmcblk0p12 - #print "mount: $row->[-1]\n"; + # print "mount: $row->[-1]\n"; if ( $row->[-1] !~ /^(nvme[0-9]+n|mmcblk|mtdblk|mtdblock)[0-9]+$/ && $row->[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && $row->[-1] !~ /\bloop/ && @@ -18827,7 +19840,7 @@ sub unmounted_data { $dev_mapped = $dmmapper{$row->[-1]} if $dmmapper{$row->[-1]}; if (@lsblk){ my $id = ($dev_mapped) ? $dev_mapped: $row->[-1]; - %part = main::get_lsblk($id); + %part = LsblkData::get($id); if (%part){ $fs = $part{'fs'}; $label = $part{'label'}; @@ -18845,8 +19858,8 @@ sub unmounted_data { # See man lvm for all current reserved private volume names next if $dev_mapped && $dev_mapped =~ /_([ctv]data|corig|[mr]image|mlog|[crt]meta|pmspare|pvmove|vorigin)(_[0-9]+)?$/; if (!$bsd_type){ - $label = PartitionData::get_label("/dev/$row->[-1]") if !$label; - $uuid = PartitionData::get_uuid("/dev/$row->[-1]") if !$uuid; + $label = PartitionItem::get_label("/dev/$row->[-1]") if !$label; + $uuid = PartitionItem::get_uuid("/dev/$row->[-1]") if !$uuid; } else { my @temp = GpartnData::get($row->[-1]); @@ -18865,33 +19878,78 @@ sub unmounted_data { }); } } - # print Data::Dumper::Dumper @unmounted; + print Data::Dumper::Dumper \@unmounted if $dbg[35]; + main::log_data('dump','@unmounted',\@unmounted) if $b_log; + eval $end if $b_log; + return @unmounted; +} +sub bsd_data { + eval $start if $b_log; + my ($fs,$label,$size,$uuid,%part,@unmounted); + PartitionItem::set_partitions() if !$loaded{'set-partitions'}; + RaidItem::raid_data() if !$loaded{'raid'}; + my @mounted = get_mounted(); + foreach my $id (sort keys %disks_bsd){ + next if !$disks_bsd{$id}->{'partitions'}; + foreach my $part (sort keys %{$disks_bsd{$id}->{'partitions'}}){ + if (!(grep {$_ =~ /$part$/} @mounted)){ + $fs = $disks_bsd{$id}->{'partitions'}{$part}{'fs'}; + next if $fs && $fs =~ /(raid|_member)$/i; + $label = $disks_bsd{$id}->{'partitions'}{$part}{'label'}; + $size = $disks_bsd{$id}->{'partitions'}{$part}{'size'}; + $uuid = $disks_bsd{$id}->{'partitions'}{$part}{'uuid'}; + # $fs = unmounted_filesystem($part) if !$fs; + push(@unmounted, { + 'dev-base' => $part, + 'dev-mapped' => '', + 'fs' => $fs, + 'label' => $label, + 'maj-min' => '', + 'size' => $size, + 'uuid' => $uuid, + }); + } + } + } + print Data::Dumper::Dumper \@unmounted if $dbg[35]; main::log_data('dump','@unmounted',\@unmounted) if $b_log; eval $end if $b_log; return @unmounted; } sub get_mounted { eval $start if $b_log; - my (@mounted); + my (@arrays,@mounted); foreach my $row (@partitions){ push(@mounted, $row->{'dev-base'}) if $row->{'dev-base'}; } - foreach my $row ((@lvm_raid,@md_raid,@zfs_raid)){ + # print Data::Dumper::Dumper \@zfs_raid; + foreach my $row ((@lvm_raid,@md_raid,@soft_raid,@zfs_raid)){ # we want to not show md0 etc in unmounted report push(@mounted, $row->{'id'}) if $row->{'id'}; - my @arrays = (ref $row->{'arrays'} eq 'ARRAY' ) ? @{$row->{'arrays'}} : (); + # print Data::Dumper::Dumper $row; + # row->arrays->components: zfs; row->components: lvm,mdraid,softraid + if ($row->{'arrays'} && ref $row->{'arrays'} eq 'ARRAY'){ + push(@arrays,@{$row->{'arrays'}}); + } + elsif ($row->{'components'} && ref $row->{'components'} eq 'ARRAY'){ + push(@arrays,$row); + } @arrays = grep {defined $_} @arrays; - foreach my $array (@arrays){ - my @components = (ref $array->{'components'} eq 'ARRAY') ? @{$array->{'components'}} : (); + # print Data::Dumper::Dumper \@arrays; + foreach my $item (@arrays){ + # print Data::Dumper::Dumper $item; + my @components = (ref $item->{'components'} eq 'ARRAY') ? @{$item->{'components'}} : (); foreach my $component (@components){ - my @temp = split('~', $component); - push(@mounted, $temp[0]); + # md has ~, not zfs,lvm,softraid + my $temp = (split('~', $component->[0]))[0]; + push(@mounted, $temp); } } } eval $end if $b_log; return @mounted; } +# bsds do not seem to return any useful data so only for linux sub unmounted_filesystem { eval $start if $b_log; my ($item) = @_; @@ -18926,15 +19984,14 @@ sub unmounted_filesystem { } } -## UsbData +## UsbItem { -package UsbData; - +package UsbItem; sub get { eval $start if $b_log; my (@rows,$key1,$val1); my $num = 0; - if (!@usb && $alerts{'lsusb'}->{'action'} ne 'use' && + if (!$usb{'main'} && $alerts{'lsusb'}->{'action'} ne 'use' && $alerts{'usbdevs'}->{'action'} ne 'use' && $alerts{'usbconfig'}->{'action'} ne 'use' ){ if ($os eq 'linux' ){ @@ -18975,14 +20032,14 @@ sub get { } sub usb_output { eval $start if $b_log; - return if ! @usb; + return if !$usb{'main'}; my (@rows); my ($b_hub,$bus_id,$chip_id,$driver,$ind_sc,$path_id,$ports,$product,$serial,$speed,$type); my $num = 0; my $j = 0; - # note: the data has been presorted in USBData: + # note: the data has been presorted in UsbData: # bus alpah id, so we don't need to worry about the order - foreach my $id (@usb){ + foreach my $id (@{$usb{'main'}}){ $j = scalar @rows; ($b_hub,$ind_sc,$num) = (0,3,1); ($driver,$path_id,$ports,$product, @@ -18998,7 +20055,7 @@ sub usb_output { if ($id->[4] eq '09'){ $ports = $id->[10] if $id->[10]; $ports ||= 'N/A'; - #print "pt0:$protocol\n"; + # print "pt0:$protocol\n"; push(@rows, { main::key($num++,1,1,'Hub') => $bus_id, main::key($num++,0,2,'info') => $product, @@ -19014,7 +20071,7 @@ sub usb_output { $driver = $id->[15] if $id->[15]; $type ||= 'N/A'; $driver ||= 'N/A'; - #print "pt3:$class:$product\n"; + # print "pt3:$class:$product\n"; $rows[$j]->{main::key($num++,1,2,'Device')} = $bus_id; $rows[$j]->{main::key($num++,0,3,'info')} = $product; $rows[$j]->{main::key($num++,0,3,'type')} = $type; @@ -19051,17 +20108,16 @@ sub usb_output { } } } - #print Data::Dumper::Dumper \@rows; + # print Data::Dumper::Dumper \@rows; eval $end if $b_log; return @rows; } } -## add metric / imperial (us) switch -## WeatherData +## WeatherItem +# add metric / imperial (us) switch { -package WeatherData; - +package WeatherItem; sub get { eval $start if $b_log; my (@rows); @@ -19323,12 +20379,12 @@ sub get_weather { if (-r $file_cached){ @weather_data = main::reader($file_cached); $freshness = (split(/\^\^/, $weather_data[0]))[1]; - #print "$now:$freshness\n"; + # print "$now:$freshness\n"; } if (!$freshness || $freshness < ($now - 60) ) { @weather_data = download_weather($now,$file_cached,$location); } - #print join("\n", @weather_data), "\n"; + # print join("\n", @weather_data), "\n"; # NOTE: because temps can be 0, we can't do if value tests foreach (@weather_data){ my @working = split(/\s*\^\^\s*/, $_); @@ -19567,7 +20623,7 @@ sub download_weather { $url = "https://smxi.org/opt/xr2.php?loc=$location->[0]&src=$weather_source"; $ua = 'weather'; # { -# #my $file2 = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/weather-1.xml"; +# # my $file2 = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/weather-1.xml"; # # my $file2 = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/feed-oslo-1.xml"; # local $/; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/weather-1.xml"; @@ -19578,7 +20634,7 @@ sub download_weather { @weather = split('\n', $temp) if $temp; unshift(@weather, "timestamp^^$now"); main::writer($file_cached,\@weather); - #print "$file_cached: download/cleaned\n"; + # print "$file_cached: download/cleaned\n"; eval $end if $b_log; return @weather; } @@ -19587,7 +20643,7 @@ sub download_weather { sub test_locale_date { my ($date_time,$location,$epoch) = @_; # $date_time .= 'дек'; - #print "1: $date_time\n"; + # print "1: $date_time\n"; if ($date_time =~ m/[^\x00-\x7f]/){ if (!$location && $epoch){ $date_time = POSIX::strftime "%Y-%m-%d %H:%M:%S", localtime($epoch); @@ -19597,7 +20653,7 @@ sub test_locale_date { } } $date_time =~ s/\s+$//; - #print "2: $date_time\n"; + # print "2: $date_time\n"; return $date_time; } sub get_location { @@ -19630,11 +20686,11 @@ sub get_location { @loc_data = split('\n', $loc_data[0]); unshift(@loc_data, "timestamp^^$now"); main::writer($file_cached,\@loc_data); - #print "$file_cached: download/cleaned\n"; + # print "$file_cached: download/cleaned\n"; } foreach (@loc_data){ my @working = split(/\s*\^\^\s*/, $_); - #print "$working[0]:$working[1]\n"; + # print "$working[0]:$working[1]\n"; if ($working[0] eq 'CountryCode3' ) { $loc{'country3'} = $working[1]; } @@ -19666,7 +20722,7 @@ sub get_location { $loc{'tz'} = $working[1]; } } - #print Data::Dumper::Dumper \%loc; + # print Data::Dumper::Dumper \%loc; # assign location, cascade from most accurate # latitude,longitude first if ($loc{'lat'} && $loc{'long'}){ @@ -19685,7 +20741,7 @@ sub get_location { $state = ($loc{'region-id'}) ? $loc{'region-id'} : 'Region N/A'; $loc_string = main::apply_filter("$city, $state, $country"); my @location = ($loc_arg,$loc_string,$loc{'tz'}); - #print ($loc_arg,"\n", join("\n", @loc_data), "\n",scalar @loc_data, "\n"); + # print ($loc_arg,"\n", join("\n", @loc_data), "\n",scalar @loc_data, "\n"); eval $end if $b_log; return @location; } @@ -19703,16 +20759,67 @@ sub complete_location { } #### ------------------------------------------------------------------- -#### UTILITIES FOR DATA LINES - GET +#### ITEM UTILITIES #### ------------------------------------------------------------------- -# Get CompilerVersion +# android only, for distro / OS id and machine data +sub set_build_prop { + eval $start if $b_log; + my $path = '/system/build.prop'; + $loaded{'build-prop'} = 1; + return if ! -r $path; + my @data = reader($path,'strip'); + foreach (@data){ + my @working = split('=', $_); + next if $working[0] !~ /^ro\.(build|product)/; + if ($working[0] eq 'ro.build.date.utc'){ + $build_prop{'build-date'} = strftime "%F", gmtime($working[1]); + } + # ldgacy, replaced by ro.product.device + elsif ($working[0] eq 'ro.build.product'){ + $build_prop{'build-product'} = $working[1]; + } + # this can be brand, company, android, it varies, but we don't want android value + elsif ($working[0] eq 'ro.build.user'){ + $build_prop{'build-user'} = $working[1] if $working[1] !~ /android/i; + } + elsif ($working[0] eq 'ro.build.version.release'){ + $build_prop{'build-version'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.board'){ + $build_prop{'product-board'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.brand'){ + $build_prop{'product-brand'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.device'){ + $build_prop{'product-device'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.manufacturer'){ + $build_prop{'product-manufacturer'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.model'){ + $build_prop{'product-model'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.name'){ + $build_prop{'product-name'} = $working[1]; + } + elsif ($working[0] eq 'ro.product.screensize'){ + $build_prop{'product-screensize'} = $working[1]; + } + } + log_data('dump','%build_prop',\%build_prop) if $b_log; + print Dumper \%build_prop if $dbg[20]; + eval $end if $b_log; +} + +## CompilerVersion { package CompilerVersion; sub get { eval $start if $b_log; my (@compiler); - if (my $file = main::system_files('version') ) { + if (my $file = $system_files{'proc-version'}) { @compiler = version_proc($file); } elsif ($bsd_type) { @@ -19726,16 +20833,26 @@ sub version_bsd { eval $start if $b_log; my (@compiler,@working); if ($alerts{'sysctl'}->{'action'} && $alerts{'sysctl'}->{'action'} eq 'use'){ - my @working; - foreach (@sysctl){ - # Not every line will have a : separator though the processor should make - # most have it. This appears to be 10.x late feature add, I don't see it - # on earlier BSDs - if (/^kern.compiler_version/){ - @working = split(/:\s*/, $_); - $working[1] =~ /.*(gcc|clang)\sversion\s([\S]+)\s.*/; - @compiler = ($1,$2); - last; + if ($sysctl{'kernel'}){ + my @working; + foreach (@{$sysctl{'kernel'}}){ + # Not every line will have a : separator though the processor should make + # most have it. This appears to be 10.x late feature add, I don't see it + # on earlier BSDs + if (/^kern.compiler_version/){ + @working = split(/:\s*/, $_); + $working[1] =~ /.*(gcc|clang)\sversion\s([\S]+)\s.*/; + @compiler = ($1,$2); + last; + } + } + } + # OpenBSD doesn't show compiler data in sysctl or dboot but it's going to + # be Clang until way into the future, and it will be the installed version. + if (!@compiler){ + if (my $path = main::check_program('clang')){ + $compiler[0] = 'clang'; + $compiler[1] = main::program_version($path,'clang',3,'--version'); } } } @@ -19778,8 +20895,187 @@ sub version_proc { } } -## Get DesktopEnvironment -## returns array: +sub set_dboot_data { + eval $start if $b_log; + $loaded{'dboot'} = 1; + my ($file,@db_data,@dm_data,@temp); + my ($counter) = (0); + if (!$fake{'dboot'}){ + $file = $system_files{'dmesg-boot'}; + } + else { + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/bsd-disks-diabolus.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/freebsd-disks-solestar.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/freebsd-enceladus-1.txt"; + ## matches: toshiba: openbsd-5.6-sysctl-2.txt + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-5.6-dmesg.boot-1.txt"; + ## matches: compaq: openbsd-5.6-sysctl-1.txt" + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-dmesg.boot-1.txt"; + $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-6.8-battery-sensors-1.txt"; + } + if ($file){ + return if ! -r $file; + @db_data = reader($file); + # sometimes > 1 sessions stored, dump old ones + for (@db_data){ + if (/^(Dragonfly|OpenBSD|NetBSD|FreeBSD is a registered trademark|Copyright.*Midnight)/){ + $counter++; + undef @temp if $counter > 1; + } + push(@temp,$_); + } + @db_data = @temp; + undef @temp; + my @dm_data = grabber('dmesg 2>/dev/null'); + # clear out for netbsd, only 1 space following or lines won't match + @dm_data = map {$_ =~ s/^\[[^\]]+\]\s//;$_} @dm_data; + $counter = 0; + # dump previous sessions, and also everything roughly before dmesg.boot + # ends, it does't need to be perfect, we just only want the actual post + # boot data + for (@dm_data){ + if (/^(Dragonfly|OpenBSD|NetBSD|FreeBSD is a registered trademark|Copyright.*Midnight)/ || + /^(smbus[0-9]:|Security policy loaded|root on)/){ + $counter++; + undef @temp if $counter > 1; + } + push(@temp,$_); + } + @dm_data = @temp; + undef @temp; + push(@db_data,'~~~~~',@dm_data); + # uniq(\@db_data); # get rid of duplicate lines + # some dmesg repeats, so we need to dump the second and > iterations + # replace all indented items with ~ so we can id them easily while + # processing note that if user, may get error of read permissions + # for some weird reason, real mem and avail mem are use a '=' separator, + # who knows why, the others are ':' + foreach (@db_data){ + $_ =~ s/\s*=\s*|:\s*/:/; + $_ =~ s/\"//g; + $_ =~ s/^\s+/~/; + $_ =~ s/\s\s/ /g; + $_ =~ s/^(\S+)\sat\s/$1:at /; # ada0 at ahcich0 + push(@{$dboot{'main'}}, $_); + if ($use{'bsd-battery'} && /^acpi(bat|cmb)/){ + push(@{$sysctl{'battery'}}, $_); + } + # ~Debug Features 0:<2 CTX BKPTs,4 Watchpoints,6 Breakpoints,PMUv3,Debugv8> + elsif ($use{'bsd-cpu'} && + (!/^~(Debug|Memory)/ && /(^cpu[0-9]+:|Features|^~*Origin:\s*)/)){ + push(@{$dboot{'cpu'}}, $_); + } + # FreeBSD: 'da*' is a USB device 'ada*' is a SATA device 'mmcsd*' is an SD card + # OpenBSD: 'sd' is usb device, 'wd' normal drive. OpenBSD uses sd for nvme drives + # but also has the nvme data: + # nvme1 at pci6 dev 0 function 0 vendor "Phison", unknown product 0x5012 rev 0x01: msix, NVMe 1.3 + # nvme1: OWC Aura P12 1.0TB, firmware ECFM22.6, serial 2003100010208 + # scsibus2 at nvme1: 2 targets, initiator 0 + # sd1 at scsibus2 targ 1 lun 0: + # sd1: 915715MB, 4096 bytes/sector, 234423126 sectors + elsif ($use{'bsd-disk'} && + /^(ad|ada|da|mmcblk|mmcsd|nvme([0-9]+n)?|sd|wd)[0-9]+(:|\sat\s|.*?\sdetached$)/){ + $_ =~ s/^\(//; + push (@{$dboot{'disk'}},$_); + } + if ($use{'bsd-machine'} && /^bios[0-9]:(at|vendor)/){ + push(@{$sysctl{'machine'}}, $_); + } + elsif ($use{'bsd-machine'} && !$dboot{'machine-vm'} && + /(\bhvm\b|innotek|\bkvm\b|microsoft.*virtual machine|openbsd[\s-]vmm|qemu|qumranet|vbox|virtio|virtualbox|vmware)/i){ + push(@{$dboot{'machine-vm'}}, $_); + } + elsif ($use{'bsd-optical'} && /^(cd)[0-9]+(\([^)]+\))?(:|\sat\s)/){ + push(@{$dboot{'optical'}},$_); + } + elsif ($use{'bsd-pci'} && /^(pci[0-9]+:at|\S+:at pci)/){ + push(@{$dboot{'pci'}},$_); + } + elsif ($use{'bsd-ram'} && /(^spdmem)/){ + push(@{$dboot{'ram'}}, $_); + } + } + log_data('dump','$dboot{main}',$dboot{'main'}) if $b_log; + print Dumper $dboot{'main'} if $dbg[11]; + + if ($dboot{'main'} && $b_log){ + log_data('dump','$dboot{cpu}',$dboot{'cpu'}); + log_data('dump','$dboot{disk}',$dboot{'disk'}); + log_data('dump','$dboot{machine-vm}',$dboot{'machine-vm'}); + log_data('dump','$dboot{optical}',$dboot{'optical'}); + log_data('dump','$dboot{ram}',$dboot{'ram'}); + log_data('dump','$dboot{usb}',$dboot{'usb'}); + log_data('dump','$sysctl{battery}',$sysctl{'battery'}); + log_data('dump','$sysctl{machine}',$sysctl{'machine'}); + } + if ($dboot{'main'} && $dbg[11]){ + print("cpu:\n", Dumper $dboot{'cpu'}); + print("disk:\n", Dumper $dboot{'disk'}); + print("machine vm:\n", Dumper $dboot{'machine-vm'}); + print("optical:\n", Dumper $dboot{'optical'}); + print("ram:\n", Dumper $dboot{'ram'}); + print("usb:\n", Dumper $dboot{'usb'}); + print("sys battery:\n", Dumper $sysctl{'battery'}); + print("sys machine:\n", Dumper $sysctl{'machine'}); + } + # this should help get rid of dmesg usb mounts not present + # note if you take out one, put in another, it will always show the first + # one, I think. Not great. Not using this means all drives attached + # current session are shown, using it, possibly wrong drive shown, which is bad + # not using this for now: && (my @disks = grep {/^hw\.disknames/} @{$dboot{'disk'}} + if ($dboot{'disk'}){ + # hw.disknames:sd0:,sd1:3242432,sd2: + #$disks[0] =~ s/(^hw\.disknames:|:[^,]*)//g; + #@disks = split(',',$disks[0]) if $disks[0]; + my ($id,$value,%dboot_disks,@disks_live,@temp); + # first, since openbsd has this, let's use it + foreach (@{$dboot{'disk'}}){ + if (!@disks_live && /^hw\.disknames/){ + $_ =~ s/(^hw\.disknames:|:[^,]*)//g; + @disks_live = split(/[,\s]/,$_) if $_; + } + else { + push(@temp,$_); + } + } + @{$dboot{'disk'}} = @temp if @temp; + foreach my $row (@temp){ + $row =~ /^([^:\s]+)[:\s]+(.+)/; + $id = $1; + $value = $2; + push(@{$dboot_disks{$id}},$value); + # get rid of detached or non present drives + if ((@disks_live && !(grep {$id =~ /^$_/} @disks_live)) || + $value =~ /\b(destroyed|detached)$/){ + delete $dboot_disks{$id}; + } + } + $dboot{'disk'} = \%dboot_disks; + log_data('dump','post: $dboot{disk}',$dboot{'disk'}) if $b_log; + print("post: disk:\n",Dumper $dboot{'disk'}) if $dbg[11]; + } + if ($use{'bsd-pci'} && $dboot{'pci'}){ + my $bus_id = 0; + foreach (@{$dboot{'pci'}}){ + if (/^pci[0-9]+:at.*?bus\s([0-9]+)/){ + $bus_id = $1; + next; + } + elsif (/:at pci[0-9]+\sdev/){ + $_ =~ s/^(\S+):at.*?dev\s([0-9]+)\sfunction\s([0-9]+)\s/$bus_id:$2:$3:$1:/; + push(@temp,$_); + } + } + $dboot{'pci'} = [@temp]; + log_data('dump','$dboot{pci}',$dboot{'pci'}) if $b_log; + print("pci:\n",Dumper $dboot{'pci'}) if $dbg[11]; + } + } + eval $end if $b_log; +} + +## DesktopEnvironment +# returns array: # 0 - desktop name # 1 - version # 2 - toolkit @@ -20060,7 +21356,7 @@ sub check_gnome { sub get_env_xprop_non_gnome_based_data { eval $start if $b_log; my ($program,@version_data,$version); - #print join("\n", @xprop), "\n"; + # print join("\n", @xprop), "\n"; # String: "This is xfdesktop version 4.2.12" # alternate: xfce4-about --version > xfce4-about 4.10.0 (Xfce 4.10) # note: some distros/wm (e.g. bunsen) set xdg to xfce to solve some other @@ -20436,6 +21732,993 @@ sub set_xprop { } +## DeviceData / PCI / SOC +# creates arrays: $devices{'audio'}; $devices{'graphics'}; $devices{'hwraid'}; +# $devices{'network'}; $devices{'timer'} and local @devices for logging/debugging +# 0 type +# 1 type_id +# 2 bus_id +# 3 sub_id +# 4 device +# 5 vendor_id +# 6 chip_id +# 7 rev +# 8 port +# 9 driver +# 10 modules +# 11 driver_nu [bsd, like: em0 - driver em; nu 0. Used to match IF in -n +# 12 subsystem/vendor +# 13 subsystem vendor_id:chip id +# 14 soc handle +# 15 serial number +{ +package DeviceData; +my (@bluetooth,@devices,@files,@full_names,@pcis,@temp,@temp2,@temp3); +my ($b_bt_check); +my ($busid,$busid_nu,$chip_id,$content,$device,$driver,$driver_nu,$file, +$handle,$modules,$port,$rev,$serial,$temp,$type,$type_id,$vendor,$vendor_id); + +sub set { + eval $start if $b_log; + ${$_[0]} = 1; # set check by reference + if ($use{'pci'}){ + if (!$bsd_type){ + if ($alerts{'lspci'}->{'action'} eq 'use' ){ + lspci_data(); + } + # ! -d '/proc/bus/pci' + # this is sketchy, a sbc won't have pci, but a non sbc arm may have it, so + # build up both and see what happens + if ($b_arm || $b_mips || $b_ppc || $b_sparc){ + soc_data(); + } + } + else { + # if (1 == 1){ + if ($alerts{'pciconf'}->{'action'} eq 'use'){ + pciconf_data(); + } + elsif ($alerts{'pcidump'}->{'action'} eq 'use'){ + pcidump_data(); + } + elsif ($alerts{'pcictl'}->{'action'} eq 'use'){ + pcictl_data(); + } + } + if ($dbg[9]){ + print Data::Dumper::Dumper $devices{'audio'}; + print Data::Dumper::Dumper $devices{'bluetooth'}; + print Data::Dumper::Dumper $devices{'graphics'}; + print Data::Dumper::Dumper $devices{'network'}; + print Data::Dumper::Dumper $devices{'hwraid'}; + print Data::Dumper::Dumper $devices{'timer'}; + print "vm: $device_vm\n"; + } + if ( $b_log){ + main::log_data('dump','$devices{audio}',$devices{'audio'}); + main::log_data('dump','$devices{bluetooth}',$devices{'bluetooth'}); + main::log_data('dump','$devices{graphics}',$devices{'graphics'}); + main::log_data('dump','$devices{hwraid}',$devices{'hwraid'}); + main::log_data('dump','$devices{network}',$devices{'network'}); + main::log_data('dump','$devices{timer}',$devices{'timer'}); + } + } + @devices = undef; + eval $end if $b_log; +} + +sub lspci_data { + eval $start if $b_log; + my ($subsystem,$subsystem_id); + my @data = pci_grabber('lspci'); + # print Data::Dumper::Dumper \@data; + foreach (@data){ + # print "$_\n"; + if ($device){ + if ($_ =~ /^~$/) { + @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu,$subsystem,$subsystem_id); + assign_data('pci',\@temp); + $device = ''; + # print "$busid $device_id r:$rev p: $port\n$type\n$device\n"; + } + elsif ($_ =~ /^Subsystem.*\[([a-f0-9]{4}:[a-f0-9]{4})\]/){ + $subsystem_id = $1; + $subsystem = (split(/^Subsystem:\s*/, $_))[1]; + $subsystem =~ s/(\s?\[[^\]]+\])+$//g; + $subsystem = main::cleaner($subsystem); + $subsystem = main::pci_cleaner($subsystem,'pci'); + $subsystem = main::pci_cleaner_subsystem($subsystem); + # print "ss:$subsystem\n"; + } + elsif ($_ =~ /^I\/O\sports/){ + $port = (split(/\s+/, $_))[3]; + # print "p:$port\n"; + } + elsif ($_ =~ /^Kernel\sdriver\sin\suse/){ + $driver = (split(/:\s*/, $_))[1]; + } + elsif ($_ =~ /^Kernel\smodules/i){ + $modules = (split(/:\s*/, $_))[1]; + } + } + # note: arm servers can have more complicated patterns + # 0002:01:02.0 Ethernet controller [0200]: Cavium, Inc. THUNDERX Network Interface Controller virtual function [177d:a034] (rev 08) + elsif ($_ =~ /^(([0-9a-f]{2,4}:)?[0-9a-f]{2}:[0-9a-f]{2})[.:]([0-9a-f]+)\s(.*)\s\[([0-9a-f]{4}):([0-9a-f]{4})\](\s\(rev\s([^\)]+)\))?/){ + $busid = $1; + $busid_nu = hex($3); + @temp = split(/:\s+/, $4); + $device = $temp[1]; + $type = $temp[0]; + $vendor_id = $5; + $chip_id = $6; + $rev = ($8)? $8 : ''; + $device = main::cleaner($device); + $temp[0] =~ /\[([^\]]+)\]$/; + $type_id = $1; + $use{'hardware-raid'} = 1 if $type_id eq '0104'; + $type = lc($type); + $type = main::pci_cleaner($type,'pci'); + $type =~ s/\s+$//; + # print "$type\n"; + ($driver,$driver_nu,$modules,$subsystem,$subsystem_id) = ('','','','',''); + } + } + print Data::Dumper::Dumper \@devices if $dbg[4]; + main::log_data('dump','lspci @devices',\@devices) if $b_log; + eval $end if $b_log; +} + +# em0@pci0:6:0:0: class=0x020000 card=0x10d315d9 chip=0x10d38086 rev=0x00 hdr=0x00 +# vendor = 'Intel Corporation' +# device = 'Intel 82574L Gigabit Ethernet Controller (82574L)' +# class = network +# subclass = ethernet +sub pciconf_data { + eval $start if $b_log; + my @data = pci_grabber('pciconf'); + foreach (@data){ + if ($driver){ + if ($_ =~ /^~$/) { + $vendor = main::cleaner($vendor); + $device = main::cleaner($device); + # handle possible regex in device name, like [ConnectX-3] + # and which could make matches fail + my $device_temp = main::regex_cleaner($device); + if ($vendor && $device){ + if (main::regex_cleaner($vendor) !~ /\Q$device_temp\E/i){ + $device = "$vendor $device"; + } + } + elsif (!$device){ + $device = $vendor; + } + @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu); + assign_data('pci',\@temp); + $driver = ''; + # print "$busid $device_id r:$rev p: $port\n$type\n$device\n"; + } + elsif ($_ =~ /^vendor/){ + $vendor = (split(/\s+=\s+/, $_))[1]; + # print "p:$port\n"; + } + elsif ($_ =~ /^device/){ + $device = (split(/\s+=\s+/, $_))[1]; + } + elsif ($_ =~ /^class/i){ + $type = (split(/\s+=\s+/, $_))[1]; + } + } + # pre freebsd 13, note chip is product+vendor + # atapci0@pci0:0:1:1: class=0x01018a card=0x00000000 chip=0x71118086 rev=0x01 hdr=0x00 + # freebsd 13 + # isab0@pci0:0:1:0: class=0x060100 rev=0x00 hdr=0x00 vendor=0x8086 device=0x7000 subvendor=0x0000 subdevice=0x0000 + if (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}):/){ + $driver = $1; + $busid = $2; + $busid_nu = $3; + $driver = $1; + $driver =~ s/([0-9]+)$//; + $driver_nu = $1; + # we don't use the sub sub class part of the class id, just first 4 + if (/\bclass=0x([\S]{4})\S*\b/){ + $type_id = $1; + } + if (/\brev=0x([\S]+)\b/){ + $rev = $1; + } + if (/\bvendor=0x([\S]+)\b/){ + $vendor_id = $1; + } + if (/\bdevice=0x([\S]+)\b/){ + $chip_id = $1; + } + # yes, they did it backwards, product+vendor id + if (/\bchip=0x([a-f0-9]{4})([a-f0-9]{4})\b/){ + $chip_id = $1; + $vendor_id = $2; + } + ($device,$type,$vendor) = ('','',''); + } + } + print Data::Dumper::Dumper \@devices if $dbg[4]; + main::log_data('dump','pciconf @devices',\@devices) if $b_log; + eval $end if $b_log; +} + +sub pcidump_data { + eval $start if $b_log; + my @data = pci_grabber('pcidump'); + main::set_dboot_data() if !$loaded{'dboot'}; + foreach (@data){ + if ($_ =~ /^~$/ && $busid && $device) { + @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu,'','','',$serial); + assign_data('pci',\@temp); + ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu,$serial) = undef; + next; + } + if ($_ =~ /^([0-9a-f:]+):([0-9]+):\s([^:]+)$/i){ + $busid = $1; + $busid_nu = $2; + ($driver,$driver_nu) = pcidump_driver("$busid:$busid_nu") if $dboot{'pci'}; + $device = main::cleaner($3); + } + elsif ($_ =~ /^0x[\S]{4}:\s+Vendor ID:\s+([0-9a-f]{4}),?\s+Product ID:\s+([0-9a-f]{4})/ ){ + $vendor_id = $1; + $chip_id = $2; + } + elsif ($_ =~ /^0x[\S]{4}:\s+Class:\s+([0-9a-f]{2})(\s[^,]+)?,?\s+Subclass:\s+([0-9a-f]{2})(\s+[^,]+)?,?(\s+Interface: ([0-9a-f]+),?\s+Revision: ([0-9a-f]+))?/){ + $type = pci_class($1); + $type_id = "$1$3"; + } + elsif (/^Serial Number:\s*(\S+)/){ + $serial = $1; + } + } + print Data::Dumper::Dumper \@devices if $dbg[4]; + main::log_data('dump','pcidump @devices',\@devices) if $b_log; + eval $end if $b_log; +} +sub pcidump_driver { + eval $start if $b_log; + my $bus_id = $_[0]; + my ($driver,$nu); + for (@{$dboot{'pci'}}) { + if (/^$bus_id:([^0-9]+)([0-9]+):/){ + $driver = $1; + $nu = $2; + last; + } + } + eval $end if $b_log; + return ($driver,$nu); +} +sub pcictl_data { + eval $start if $b_log; + my @data = pci_grabber('pcictl'); + my @data2 = pci_grabber('pcictl-n'); + foreach (@data){ + if ($_ =~ /^~$/ && $busid && $device) { + @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu); + assign_data('pci',\@temp); + ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu) = undef; + next; + } + # it's too fragile to get these in one matching so match, trim, next match + if (/\s+\[([^\]0-9]+)([0-9]+)\]$/){ + $driver = $1; + $driver_nu = $2; + $_ =~ s/\s+\[[^\]]+\]$//; + } + if (/\s+\(.*?(revision 0x([^\)]+))?\)/){ + $rev = $2 if $2; + $_ =~ s/\s+\([^\)]+?\)$//; + } + if ($_ =~ /^([0-9a-f:]+):([0-9]+):\s+([^.]+?)$/i){ + $busid = $1; + $busid_nu = $2; + $device = main::cleaner($3); + my $working = (grep {/^${busid}:${busid_nu}:\s/} @data2)[0]; + if ($working && + $working =~ /^${busid}:${busid_nu}:\s+0x([0-9a-f]{4})([0-9a-f]{4})\s+\(0x([0-9a-f]{2})([0-9a-f]{2})[0-9a-f]+\)/){ + $vendor_id = $1; + $chip_id = $2; + $type = pci_class($3); + $type_id = "$3$4"; + } + } + } + print Data::Dumper::Dumper \@devices if $dbg[4]; + main::log_data('dump','pcidump @devices',\@devices) if $b_log; + eval $end if $b_log; +} + +sub pci_grabber { + eval $start if $b_log; + my ($program) = @_; + my ($args,$path,$pattern,@data,@working); + if ($program eq 'lspci'){ + # 2.2.8 lspci did not support -k, added in 2.2.9, but -v turned on -k + $args = ' -nnv'; + $path = $alerts{'lspci'}->{'path'}; + $pattern = '^[0-9a-f]+:'; + } + elsif ($program eq 'pciconf'){ + $args = ' -lv'; + $path = $alerts{'pciconf'}->{'path'}; + $pattern = '^([^@]+)\@pci'; + } + elsif ($program eq 'pcidump'){ + $args = ' -v'; + $path = $alerts{'pcidump'}->{'path'}; + $pattern = '^[0-9a-f]+:'; + } + elsif ($program eq 'pcictl'){ + $args = ' pci0 list -N'; + $path = $alerts{'pcictl'}->{'path'}; + $pattern = '^[0-9a-f:]+:'; + } + elsif ($program eq 'pcictl-n'){ + $args = ' pci0 list -n'; + $path = $alerts{'pcictl'}->{'path'}; + $pattern = '^[0-9a-f:]+:'; + } + if ($fake{'pciconf'} || $fake{'pcictl'} || $fake{'pcidump'}){ + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pciconf/pci-freebsd-8.2-2"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcidump/pci-openbsd-6.1-vm.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcictl/pci-netbsd-9.1-vm.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/racermach-1-knnv.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/rk016013-knnv.txt"; + # @data = main::reader($file,'strip'); + } + else { + @data = main::grabber("$path $args 2>/dev/null",'','strip'); + } + if (@data){ + $use{'pci-tool'} = 1 if scalar @data > 10; + foreach (@data){ + # this is the group separator and assign trigger + if ($_ =~ /$pattern/i){ + push(@working, '~'); + } + push(@working, $_); + } + push(@working, '~'); + } + print Data::Dumper::Dumper \@working if $dbg[30]; + eval $end if $b_log; + return @working; +} + +sub soc_data { + eval $start if $b_log; + soc_devices_files(); + soc_devices(); + soc_devicetree(); + print Data::Dumper::Dumper \@devices if $dbg[4]; + main::log_data('dump','soc @devices',\@devices) if $b_log; + eval $end if $b_log; +} +# 1: /sys/devices/platform/soc/1c30000.ethernet/uevent:["DRIVER=dwmac-sun8i", "OF_NAME=ethernet", +# "OF_FULLNAME=/soc/ethernet@1c30000", "OF_COMPATIBLE_0=allwinner,sun8i-h3-emac", +# "OF_COMPATIBLE_N=1", "OF_ALIAS_0=ethernet0", # "MODALIAS=of:NethernetTCallwinner,sun8i-h3-emac"] +# 2: /sys/devices/platform/soc:audio/uevent:["DRIVER=bcm2835_audio", "OF_NAME=audio", "OF_FULLNAME=/soc/audio", +# "OF_COMPATIBLE_0=brcm,bcm2835-audio", "OF_COMPATIBLE_N=1", "MODALIAS=of:NaudioTCbrcm,bcm2835-audio"] +# 3: /sys/devices/platform/soc:fb/uevent:["DRIVER=bcm2708_fb", "OF_NAME=fb", "OF_FULLNAME=/soc/fb", +# "OF_COMPATIBLE_0=brcm,bcm2708-fb", "OF_COMPATIBLE_N=1", "MODALIAS=of:NfbTCbrcm,bcm2708-fb"] +# 4: /sys/devices/platform/soc/1c40000.gpu/uevent:["OF_NAME=gpu", "OF_FULLNAME=/soc/gpu@1c40000", +# "OF_COMPATIBLE_0=allwinner,sun8i-h3-mali", "OF_COMPATIBLE_1=allwinner,sun7i-a20-mali", +# "OF_COMPATIBLE_2=arm,mali-400", "OF_COMPATIBLE_N=3", +# "MODALIAS=of:NgpuTCallwinner,sun8i-h3-maliCallwinner,sun7i-a20-maliCarm,mali-400"] +# 5: /sys/devices/platform/soc/soc:internal-regs/d0018180.gpio/uevent +# 6: /sys/devices/soc.0/1180000001800.mdio/8001180000001800:05/uevent +# ["DRIVER=AR8035", "OF_NAME=ethernet-phy" +# 7: /sys/devices/soc.0/1c30000.eth/uevent +# 8: /sys/devices/wlan.26/uevent [from pine64] +# 9: /sys/devices/platform/audio/uevent:["DRIVER=bcm2835_AUD0", "OF_NAME=audio" +# 10: /sys/devices/vio/71000002/uevent:["DRIVER=ibmveth", "OF_NAME=l-lan" +# 11: /sys/devices/platform/soc:/soc:i2c-hdmi:/i2c-2/2-0050/uevent:['OF_NAME=hdmiddc' +# 12: /sys/devices/platform/soc:/soc:i2c-hdmi:/uevent:['DRIVER=i2c-gpio', 'OF_NAME=i2c-hdmi' +# 13: /sys/devices/platform/scb/fd580000.ethernet/uevent +# 14: /sys/devices/platform/soc/fe300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1/uevent (wifi, pi 3,4) +# 15: Pi BT: /sys/devices/platform/soc/fe201000.serial/uevent +# 16: Pi BT: /sys/devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0 +sub soc_devices_files { + eval $start if $b_log; + if (-d '/sys/devices/platform/'){ + @files = main::globber('/sys/devices/platform/soc*/*/uevent'); + @temp2 = main::globber('/sys/devices/platform/soc*/*/*/uevent'); + push(@files,@temp2) if @temp2; + if (-e '/sys/devices/platform/scb'){ + @temp2 = main::globber('/sys/devices/platform/scb/*/uevent'); + push(@files,@temp2) if @temp2; + @temp2 = main::globber('/sys/devices/platform/scb/*/*/uevent'); + push(@files,@temp2) if @temp2; + } + @temp2 = main::globber('/sys/devices/platform/*/uevent'); + push(@files,@temp2) if @temp2; + } + if (main::globber('/sys/devices/soc*')){ + @temp2 = main::globber('/sys/devices/soc*/*/uevent'); + push(@files,@temp2) if @temp2; + @temp2 = main::globber('/sys/devices/soc*/*/*/uevent'); + push(@files,@temp2) if @temp2; + } + @temp2 = main::globber('/sys/devices/*/uevent'); # see case 8 + push(@files,@temp2) if @temp2; + @temp2 = main::globber('/sys/devices/*/*/uevent'); # see case 10 + push(@files,@temp2) if @temp2; + @temp2 = undef; + # not sure why, but even as root/sudo, /subsystem|driver/uevent are unreadable with -r test true + @files = grep {!/\/(subsystem|driver)\//} @files if @files; + main::uniq(\@files); + eval $end if $b_log; +} + +sub soc_devices { + eval $start if $b_log; + my (@working); + set_bluetooth() if !$b_bt_check; + foreach $file (@files){ + next if -z $file; + $chip_id = $file; + # variants: /soc/20100000.ethernet/ /soc/soc:audio/ /soc:/ /soc@0/ /soc:/12cb0000.i2c:/ + # mips: /sys/devices/soc.0/1180000001800.mdio/8001180000001800:07/ + # ppc: /sys/devices/vio/71000002/ + $chip_id =~ /\/sys\/devices\/(platform\/)?(soc[^\/]*\/)?([^\/]+\/)?([^\/]+\/)?([^\/\.:]+)([\.:])?([^\/:]+)?:?\/uevent$/; + $chip_id = $5; + $temp = $7; + @working = main::reader($file, 'strip') if -r $file; + ($device,$driver,$handle,$type,$vendor_id) = (undef,undef,undef,undef,undef); + foreach my $data (@working){ + @temp2 = split('=', $data); + if ($temp2[0] eq 'DRIVER'){ + $driver = $temp2[1]; + $driver =~ s/-/_/g if $driver; # kernel uses _, not - in module names + } + elsif ($temp2[0] eq 'OF_NAME'){ + $type = $temp2[1]; + } + # we'll use these paths to test in device tree pci completer + elsif ($temp2[0] eq 'OF_FULLNAME' && $temp2[1]){ + # we don't want the short names like /soc, /led and so on + push(@full_names, $temp2[1]) if (() = $temp2[1] =~ /\//g) > 1; + $handle = (split('@', $temp2[1]))[-1] if $temp2[1] =~ /@/; + } + elsif ($temp2[0] eq 'OF_COMPATIBLE_0'){ + @temp3 = split(',', $temp2[1]); + $device = $temp3[-1]; + $vendor_id = $temp3[0]; + } + } + # it's worthless, we can't use it + next if ! defined $type; + $type_id = $type; + if (@bluetooth && $type eq 'serial'){ + my $file_temp = $file; + $file_temp =~ s/uevent$//; + $type = 'bluetooth' if grep {/$file_temp/} @bluetooth; + } + $chip_id = '' if ! defined $chip_id; + $vendor_id = '' if ! defined $vendor_id; + $driver = '' if ! defined $driver; + $handle = '' if ! defined $handle; + $busid = (defined $temp && main::is_int($temp)) ? $temp: 0; + $type = soc_type($type,$vendor_id,$driver); + ($busid_nu,$modules,$port,$rev) = (0,'','',''); + @temp3 = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,$rev, + $port,$driver,$modules,'','','',$handle); + assign_data('soc',\@temp3); + main::log_data('dump','soc devices: @devices @temp3',\@temp3) if $b_log; + } + eval $end if $b_log; +} +sub soc_devicetree { + eval $start if $b_log; + # now we want to fill in stuff that was not in /sys/devices/ + if (-d '/sys/firmware/devicetree/base/soc'){ + @files = main::globber('/sys/firmware/devicetree/base/soc/*/compatible'); + my $test = (@full_names) ? join('|', sort @full_names) : 'xxxxxx'; + set_bluetooth() if !$b_bt_check; + foreach $file (@files){ + if ( $file !~ m%$test%){ + ($handle,$content,$device,$type,$type_id,$vendor_id) = ('','','','','',''); + $content = main::reader($file, 'strip',0) if -r $file; + $file =~ m%soc/([^@]+)@([^/]+)/compatible$%; + $type = $1; + next if !$type || !$content; + $handle = $2 if $2; + $type_id = $type; + if (@bluetooth && $type eq 'serial'){ + my $file_temp = $file; + $file_temp =~ s/uevent$//; + $type = 'bluetooth' if grep {/$file_temp/} @bluetooth; + } + if ($content){ + @temp3 = split(',', $content); + $vendor_id = $temp3[0]; + $device = $temp3[-1]; + # strip off those weird device tree special characters + $device =~ s/\x01|\x02|\x03|\x00//g; + } + $type = soc_type($type,$vendor_id,''); + @temp3 = ($type,$type_id,0,0,$device,$vendor_id,'soc','','','','','','','',$handle); + assign_data('soc',\@temp3); + main::log_data('dump','devicetree: @devices @temp3',\@temp3) if $b_log; + } + } + } + eval $end if $b_log; +} +sub set_bluetooth { + # special case of pi bt on ttyAMA0 + $b_bt_check = 1; + @bluetooth = main::globber('/sys/class/bluetooth/*') if -e '/sys/class/bluetooth'; + @bluetooth = map {$_ = Cwd::abs_path($_);$_} @bluetooth if @bluetooth; + @bluetooth = grep {!/usb/} @bluetooth if @bluetooth; # we only want non usb bt + main::log_data('dump','soc bt: @bluetooth', \@bluetooth) if $b_log; +} +sub assign_data { + my ($tool,$data) = @_; + if (check_graphics($data->[0],$data->[1])){ + push(@{$devices{'graphics'}},[@$data]); + $use{'soc-gfx'} = 1 if $tool eq 'soc'; + } + # for hdmi, we need gfx/audio both + if (check_audio($data->[0],$data->[1])){ + push(@{$devices{'audio'}},[@$data]); + $use{'soc-audio'} = 1 if $tool eq 'soc'; + } + if (check_bluetooth($data->[0],$data->[1])){ + push(@{$devices{'bluetooth'}},[@$data]); + $use{'soc-bluetooth'} = 1 if $tool eq 'soc'; + } + elsif (check_hwraid($data->[0],$data->[1])){ + push(@{$devices{'hwraid'}},[@$data]); + $use{'soc-hwraid'} = 1 if $tool eq 'soc'; + } + elsif (check_network($data->[0],$data->[1])){ + push(@{$devices{'network'}},[@$data]); + $use{'soc-network'} = 1 if $tool eq 'soc'; + } + elsif (check_timer($data->[0],$data->[1])){ + push(@{$devices{'timer'}},[@$data]); + $use{'soc-timer'} = 1 if $tool eq 'soc'; + } + # not used at this point, -M comes before ANG + # $device_vm = check_vm($data[4]) if ( (!$b_ppc && !$b_mips) && !$device_vm ); + push(@devices,[@$data]); +} +# note: for soc, these have been converted in soc_type() +sub check_audio { + if ( ( $_[1] && length($_[1]) == 4 && $_[1] =~ /^04/ ) || + ( $_[0] && $_[0] =~ /^(audio|hdmi|multimedia|sound)$/i )){ + return 1; + } + else {return 0} +} +sub check_bluetooth { + if ( ( $_[1] && length($_[1]) == 4 && $_[1] eq '0d11' ) || + ( $_[0] && $_[0] =~ /^(bluetooth)$/i )){ + return 1; + } + else {return 0} +} +sub check_graphics { + # note: multimedia class 04 is viddeo if 0400. 'tv' is risky I think + if ( ( $_[1] && length($_[1]) == 4 && ($_[1] =~ /^03/ || $_[1] eq '0400' || + $_[1] eq '0d80' ) ) || + ( $_[0] && $_[0] =~ /^(vga|display|hdmi|3d|video|tv|television)$/i)){ + return 1; + } + else {return 0} +} +sub check_hwraid { + return 1 if ( $_[1] && $_[1] eq '0104' ); +} +# NOTE: class 06 subclass 80 +# https://www-s.acm.illinois.edu/sigops/2007/roll_your_own/7.c.1.html +# 0d20: 802.11a 0d21: 802.11b 0d80: other wireless +sub check_network { + if ( ( $_[1] && length($_[1]) == 4 && ($_[1] =~/^02/ || $_[1] =~ /^0d2/ || $_[1] eq '0680' ) ) || + ( $_[0] && $_[0] =~ /^(ethernet|network|wifi|wlan)$/i ) ){ + return 1; + } + else {return 0} +} +sub check_timer { + return 1 if ( $_[0] && $_[0] eq 'timer' ); +} +sub check_vm { + if ( $_[0] && $_[0] =~ /(innotek|vbox|virtualbox|vmware|qemu)/i ) { + return $1 + } + else {return ''} +} + +sub soc_type { + my ($type,$info,$driver) = @_; + # I2S or i2s. I2C is i2 controller |[iI]2[Ss]. note: odroid hdmi item is sound only + # snd_soc_dummy. simple-audio-amplifier driver: speaker_amp + if (($driver && $driver =~ /codec/) || ($info && $info =~ /codec/) || + ($type && $type =~ /codec/) ){ + $type = 'codec'; + } + elsif (($driver && $driver =~ /dummy/i) || ($info && $info =~ /dummy/i)){ + $type = 'dummy'; + } + elsif ($type =~ /^(daudio|.*hifi.*|.*sound[_-]card|.*dac[0-9]?)$/i || + ($info && $info !~ /amp/i && $info =~ /(sound|audio)/i) || + ($driver && $driver =~ /(audio|snd|sound)/i) ){ + $type = 'audio'; + } + # no need for bluetooth since that's only found in pi, handled above + elsif ($type =~ /^((meson-?)?fb|disp|display(-[^\s]+)?|gpu|.*mali|vpu)$/i){ + $type = 'display'; + } + # includes ethernet-phy, meson-eth + elsif ($type =~ /^(([^\s]+-)?eth|ethernet(-[^\s]+)?|lan|l-lan)$/i){ + $type = 'ethernet'; + } + elsif ($type =~ /^(.*wlan.*|.*wifi.*|.*mmcnr.*)$/i){ + $type = 'wifi'; + } + # needs to catch variants like hdmi-tx but not hdmi-connector + elsif ( $type =~ /^(.*hdmi(-?tx)?)$/i){ + $type = 'hdmi'; + } + elsif ($type =~ /^timer$/i){ + $type = 'timer'; + } + return $type; +} +sub pci_class { + eval $start if $b_log; + my ($id) = @_; + $id = lc($id); + my %classes = ( + '00' => 'unclassified', + '01' => 'mass-storage', + '02' => 'network', + '03' => 'display', + '04' => 'audio', + '05' => 'memory', + '06' => 'bridge', + '07' => 'communication', + '08' => 'peripheral', + '09' => 'input', + '0a' => 'docking', + '0b' => 'processor', + '0c' => 'serialbus', + '0d' => 'wireless', + '0e' => 'intelligent', + '0f' => 'satellite', + '10' => 'encryption', + '11' => 'signal-processing', + '12' => 'processing-accelerators', + '13' => 'non-essential-instrumentation', + '40' => 'coprocessor', + 'ff' => 'unassigned', + ); + my $type = (defined $classes{$id}) ? $classes{$id}: 'unhandled'; + eval $end if $b_log; + return $type; +} +} + +## DiskDataBSD +# handles disks and partition extra data for disks bsd, raid-zfs, +# partitions, swap, unmounted +# glabel: partID, logical/physical-block-size, uuid, label, size +# disklabel: partID, block-size, fs, size +{ +package DiskDataBSD; +# sets initial pure dboot data, and fills it in with +# disklabel/gpart partition and advanced data +sub set { + eval $start if $b_log; + $loaded{'disk-data-bsd'} = 1; + set_dboot_disks(); + if ($use{'bsd-partition'}){ + if ($alerts{'gpart'}->{'action'} eq 'use'){ + set_gpart_data(); + } + elsif ($alerts{'disklabel'}->{'action'} eq 'use'){ + set_disklabel_data(); + } + } + eval $end if $b_log; +} +sub get { + eval $start if $b_log; + my $id = $_[0]; + return if !$id || !%disks_bsd; + $id =~ s|^/dev/||; + my (%data); + # this handles mainly zfs, which can be either disk or part + if ($disks_bsd{$id}){ + %data = %{$disks_bsd{$id}}; + delete $data{'partitions'} if $data{'partitions'}; + } + else { + OUTER: foreach my $key (keys %disks_bsd){ + if ($disks_bsd{$key}->{'partitions'}){ + foreach my $part (keys %{$disks_bsd{$key}->{'partitions'}}){ + if ($part eq $id){ + %data = %{$disks_bsd{$key}->{'partitions'}{$part}}; + last OUTER; + } + } + } + } + } + eval $end if $b_log; + return %data; +} +sub set_dboot_disks { + eval $start if $b_log; + my ($working,@temp); + foreach my $id (sort keys %{$dboot{'disk'}}){ + next if !@{$dboot{'disk'}->{$id}}; + foreach (@{$dboot{'disk'}->{$id}}){ + my @row = split(/:\s*/, $_); + next if !$row[0]; + # no dots, note: ada2: 2861588MB BUT: ada2: 600.000MB/s + # print "$_ i: $i\n"; + # openbsd/netbsd matches will often work + if ($row[0] =~ /(^|,\s*)([0-9\.]+\s*[MGTPE])i?B?[,.\s]+([0-9]+)\ssectors$|^{'block-physical'} = POSIX::ceil(($working/$3)*1024) if $3; + $disks_bsd{$id}->{'size'} = $working; + } + # don't set both, if smartctl installed, we want to use its data so having + # only one of logical/physical will trip use of smartctl values + if ($row[0] =~ /[\s,]+([0-9]+)\sbytes?[\s\/]sect/ ){ + #$disks_bsd{$id}->{'block-logical'} = $1; + $disks_bsd{$id}->{'block-physical'} = $1; + } + if ($row[1]){ + if ($row[1] =~ /<([^>]+)>/){ + $disks_bsd{$id}->{'model'} = $1 if $1; + $disks_bsd{$id}->{'type'} = 'removable' if $_ =~ /removable/; + # + my $count = ($disks_bsd{$id}->{'model'} =~ tr/,//); + if ($count && $count > 1){ + @temp = split(/,\s*/, $disks_bsd{$id}->{'model'}); + $disks_bsd{$id}->{'model'} = $temp[1]; + } + } + if ($row[1] =~ /\bserial\.(\S*)/){ + $disks_bsd{$id}->{'serial'} = $1; + } + } + if (!$disks_bsd{$id}->{'serial'} && $row[0] =~ /^Serial\sNumber\s(.*)/){ + $disks_bsd{$id}->{'serial'} = $1; + } + # mmcsd0:32GB at mmc0 50.0MHz/4bit/65535-block + if (!$disks_bsd{$id}->{'serial'} && $row[0] =~ /(\s(SN|s\/n)\s(\S+))[>\s]/){ + $disks_bsd{$id}->{'serial'} = $3; + # strip out the SN/MFG so it won't show in model + $row[0] =~ s/$1//; + $row[0] =~ s/\sMFG\s[^>]+//; + } + # these were mainly FreeBSD/Dragonfly matches + if (!$disks_bsd{$id}->{'size'} && $row[0] =~ /^([0-9]+\s*[KMGTPE])i?B?[\s,]/){ + $working = main::translate_size($1); + $disks_bsd{$id}->{'size'} = $working; + } + if ($row[0] =~ /(device$|^([0-9\.]+\s*[KMGT]B\s+)?<)/){ + $row[0] =~ s/\bdevice$//g; + $row[0] =~ /<([^>]*)>(\s(.*))?/; + $disks_bsd{$id}->{'model'} = $1 if $1; + $disks_bsd{$id}->{'spec'} = $3 if $3; + } + if ($row[0] =~ /^([0-9\.]+[MG][B]?\/s)/){ + $disks_bsd{$id}->{'speed'} = $1; + $disks_bsd{$id}->{'speed'} =~ s/\.[0-9]+// if $disks_bsd{$id}->{'speed'}; + } + $disks_bsd{$id}->{'model'} = main::disk_cleaner($disks_bsd{$id}->{'model'}); + if (!$disks_bsd{$id}->{'serial'} && $show{'disk'} && $extra > 1 && + $alerts{'bioctl'}->{'action'} eq 'use'){ + $disks_bsd{$id}->{'serial'} = bioctl_data($id); + } + } + } + print Data::Dumper::Dumper \%disks_bsd if $dbg[34]; + main::log_data('dump','%disks_bsd',\%disks_bsd) if $b_log; + eval $end if $b_log; +} +sub bioctl_data { + eval $start if $b_log; + my $id = $_[0]; + my $serial; + my $working = (main::grabber($alerts{'bioctl'}->{'path'} . " $id 2>&1",'','strip'))[0]; + if ($working){ + if ($working =~ /permission/i){ + $alerts{'bioctl'}->{'action'} = 'permissions'; + } + elsif ($working =~ /serial[\s-]?(number|n[ou]\.?)?\s+(\S+)$/i) { + $serial = $2; + } + } + eval $end if $b_log; + return $serial; +} +sub set_disklabel_data { + eval $start if $b_log; + my ($cmd,@data,@working); + # see docs/inxi-data.txt for fs info + my %fs = ( + '4.2bsd' => 'ffs', + '4.4lfs' => 'lfs', + ); + foreach my $id (keys %disks_bsd){ + $cmd = "$alerts{'disklabel'}->{'path'} $id 2>&1"; + @data = main::grabber($cmd,'','strip'); + main::log_data('dump','disklabel @data', \@data) if $b_log; + if (scalar @data < 4 && (grep {/permission/i} @data)){ + $alerts{'disklabel'}->{'action'} = 'permissions'; + $alerts{'disklabel'}->{'message'} = main::row_defaults('root-feature'); + last; + } + else { + my ($b_part,$duid,$part_id,$bytes_sector) = undef; + if ($extra > 2 && $show{'disk'} && $alerts{'fdisk'}->{'action'} eq 'use'){ + $disks_bsd{$id}->{'partition-table'} = fdisk_data($id); + } + foreach my $row (@data){ + if ($row =~ /^\d+\spartitions:/){ + $b_part = 1; + next; + } + if (!$b_part){ + @working = split(/:\s*/, $row); + if ($working[0] eq 'bytes/sector'){ + $disks_bsd{$id}->{'block-physical'} = $working[1]; + $bytes_sector = $working[1]; + } + elsif ($working[0] eq 'duid'){ + $working[1] =~ s/^0+$//; # dump duid if all 0s + $disks_bsd{$id}->{'duid'} = $working[1]; + } + elsif ($working[0] eq 'label'){ + $disks_bsd{$id}->{'dlabel'} = $working[1]; + } + } + # part: size [bytes*sector] offset fstype [fsize bsize cpg]# mount + # d: 8388608 18838976 4.2BSD 2048 16384 12960 # /tmp + else { + @working = split(/:?\s+#?\s*/, $row); + # netbsd: disklabel: super block size 0 AFTER partitions started! + # note: 'unused' fs type is NOT unused space, it's often the entire disk!! + if (($working[0] && $working[0] eq 'disklabel') || + ($working[3] && $working[3] =~ /ISO9660|unused/i) || + (!$working[1] || !main::is_numeric($working[1]))){ + next; + } + $part_id = $id . $working[0]; + $working[1] = $working[1]*$bytes_sector/1024 if $working[1]; + $disks_bsd{$id}->{'partitions'}{$part_id}{'size'} = $working[1]; + if ($working[3]){ # fs + $working[3] = lc($working[3]); + $working[3] = $fs{$working[3]} if $fs{$working[3]}; #translate + } + $disks_bsd{$id}->{'partitions'}{$part_id}{'fs'} = $working[3]; + # OpenBSD: mount point; NetBSD: (Cyl. 0 - 45852*) + if ($working[7] && $working[7] =~ m|^/|){ + $disks_bsd{$id}->{'partitions'}{$part_id}{'mount'} = $working[7]; + } + $disks_bsd{$id}->{'partitions'}{$part_id}{'uuid'} = ''; + $disks_bsd{$id}->{'partitions'}{$part_id}{'label'} = ''; + } + } + } + } + print Data::Dumper::Dumper \%disks_bsd if $dbg[34]; + main::log_data('dump', '%disks_bsd', \%disks_bsd) if $b_log; + eval $end if $b_log; +} +sub fdisk_data { + eval $start if $b_log; + my $id = $_[0]; + my ($scheme); + my @data = main::grabber($alerts{'fdisk'}->{'path'} . " -v $id 2>&1",'','strip'); + foreach (@data){ + if (/permission/i){ + $alerts{'fdisk'}->{'action'} = 'permissions'; + last; + } + elsif (/^(GUID|MBR):/){ + $scheme = ($1 eq 'GUID') ? 'GPT' : $1; + last; + } + } + eval $start if $b_log; + return $scheme; +} +# 2021-03: openbsd: n/a; dragonfly: no 'list'; freebsd: yes +sub set_gpart_data { + eval $start if $b_log; + my @data = main::grabber($alerts{'gpart'}->{'path'} . " list 2>/dev/null",'','strip'); + main::log_data('dump', 'gpart: @data', \@data) if $b_log; + my ($b_cd,$id,$part_id,$type); + for (@data){ + my @working = split(/\s*:\s*/, $_); + if ($working[0] eq 'Geom name'){ + $id = $working[1]; + # [1. Name|Geom name]: iso9660/FVBE + $b_cd = ($id =~ /iso9660/i) ? 1: 0; + next; + } + elsif ($working[0] eq 'scheme'){ + $disks_bsd{$id}->{'scheme'} = $working[1]; + next; + } + elsif ($working[0] eq 'Consumers'){ + $type = 'disk'; + next; + } + elsif ($working[0] eq 'Providers'){ + $type = 'part'; + next; + } + if (!$b_cd && $type && $type eq 'part'){ + if ($working[0] =~ /^[0-9]+\.\s*Name/){ + $part_id = $working[1]; + } + # eg: label:(null) - we want to show null + elsif ($working[0] eq 'label'){ + $working[1] =~ s/\(|\)//g; + $disks_bsd{$id}->{'partitions'}{$part_id}{'label'} = $working[1]; + } + elsif ($working[0] eq 'Mediasize'){ + $working[1] =~ s/\s+\(.*$//; # trim off the (2.4G) + # gpart shows in bytes, not KiB. For the time being... + $disks_bsd{$id}->{'partitions'}{$part_id}{'size'} = $working[1]/1024 if $working[1]; + } + elsif ($working[0] eq 'rawuuid'){ + $working[1] =~ s/\(|\)//g; + $disks_bsd{$id}->{'partitions'}{$part_id}{'uuid'} = $working[1]; + } + elsif ($working[0] eq 'Sectorsize'){ + $disks_bsd{$id}->{'partitions'}{$part_id}{'physical-block-size'} = $working[1]; + } + elsif ($working[0] eq 'Stripesize'){ + $disks_bsd{$id}->{'partitions'}{$part_id}{'logical-block-size'} = $working[1]; + } + elsif ($working[0] eq 'type'){ + $working[1] =~ s/\(|\)//g; + $disks_bsd{$id}->{'partitions'}{$part_id}{'fs'} = $working[1]; + } + } + # really strange results happen if no dboot disks were found and it's zfs! + elsif (!$b_cd && $type && $type eq 'disk' && $disks_bsd{$id}->{'size'}) { + # need to see raid, may be > 1 Consumers + if ($working[0] =~ /^[0-9]+\.\s*Name/){ + $id = $working[1]; + } + elsif ($working[0] eq 'Mediasize'){ + $working[1] =~ s/\s+\(.*$//; # trim off the (2.4G) + # gpart shows in bytes, not KiB. For the time being... + $disks_bsd{$id}->{'size'} = $working[1]/1024 if $working[1]; + } + elsif ($working[0] eq 'Sectorsize'){ + $disks_bsd{$id}->{'block-physical'} = $working[1]; + } + } + } + print Data::Dumper::Dumper \%disks_bsd if $dbg[34]; + main::log_data('dump', '%disks_bsd', \%disks_bsd) if $b_log; + eval $end if $b_log; +} +} + sub get_display_manager { eval $start if $b_log; my (@data,@found,$path,$working,$b_run,$b_vrun,$b_vrunrc); @@ -20497,7 +22780,7 @@ sub get_display_manager { return join(', ', @found) if @found; } -## Get DistroData +## DistroData { package DistroData; my (@distro_files,@osr,@working); @@ -21118,6 +23401,94 @@ sub ubuntu_id { return $id; } } + +## DmidecodeData +{ +package DmidecodeData; +# note, all actual tests have already been run in check_tools so if we +# got here, we're good. +sub set { + eval $start if $b_log; + ${$_[0]} = 1; # set check boolean by reference + if ($fake{'dmidecode'} || $alerts{'dmidecode'}->{'action'} eq 'use' ){ + generate_data(); + } + eval $end if $b_log; +} + +sub generate_data { + eval $start if $b_log; + my ($content,@data,@working,$type,$handle); + if ($fake{'dmidecode'}){ + my $file; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/pci-freebsd-8.2-2"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-loki-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-t41-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-mint-20180106.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-vmware-ram-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-tyan-4408.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-2.txt"; + # open(my $fh, '<', $file) or die "can't open $file: $!"; + #chomp(@data = <$fh>); + } + else { + $content = qx($alerts{'dmidecode'}->{'path'} 2>/dev/null); + @data = split('\n', $content); + } + # we don't need the opener lines of dmidecode output + # but we do want to preserve the indentation. Empty lines + # won't matter, they will be skipped, so no need to handle them. + # some dmidecodes do not use empty line separators + splice(@data, 0, 5) if @data; + my $j = 0; + my $b_skip = 1; + foreach (@data){ + if (!/^Hand/){ + next if $b_skip; + if (/^[^\s]/){ + $_ = lc($_); + $_ =~ s/\s(information)//; + push(@working, $_); + } + elsif (/^\t/){ + $_ =~ s/^\t\t/~/; + $_ =~ s/^\t|\s+$//g; + push(@working, $_); + } + } + elsif (/^Handle\s(0x[0-9A-Fa-f]+).*DMI\stype\s([0-9]+),.*/){ + $j = scalar @dmi; + $handle = hex($1); + $type = $2; + $use{'slot-tool'} = 1 if $type && $type == 9; + $b_skip = ( $type > 126 )? 1 : 0; + next if $b_skip; + # we don't need 32, system boot, or 127, end of table + if (@working){ + if ($working[0] != 32 && $working[0] < 127){ + $dmi[$j] = ( + [@working], + ); + } + } + @working = ($type,$handle); + } + } + if (@working && $working[0] != 32 && $working[0] != 127){ + $j = scalar @dmi; + $dmi[$j] = \@working; + } + # last by not least, sort it by dmi type, now we don't have to worry + # about random dmi type ordering in the data, which happens. Also sort + # by handle, as secondary sort. + @dmi = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @dmi; + main::log_data('dump','@dmi',\@dmi) if $b_log; + print Data::Dumper::Dumper \@dmi if $dbg[2]; + eval $end if $b_log; +} +} + # return all device modules not including driver sub get_driver_modules { eval $start if $b_log; @@ -21132,6 +23503,7 @@ sub get_driver_modules { eval $end if $b_log; return $modules; } + # 1: driver; 2: modules, comma separated, return only modules # which do not equal the driver string itself. Sometimes the module # name is different from the driver name, even though it's the same thing. @@ -21165,7 +23537,8 @@ sub get_gcc_data { return @gccs; } -# Get GlabelData +## GlabelData - set/get +# used only to get RAID ZFS gptid path standard name, like ada0p1 { package GlabelData; # gptid/c5e940f1-5ce2-11e6-9eeb-d05099ac4dc2 N/A ada0p1 @@ -21202,67 +23575,6 @@ sub set { } } -# Get GpartData -{ -package GpartData; -# 1. Name: ada1p1 -# label: (null) -# label: ssd-root -# rawuuid: b710678b-f196-11e1-98fd-021fc614aca9 -sub get { - eval $start if $b_log; - my ($item) = @_; - my (@data) = ('','','',''); - set() if !$loaded{'gpart'}; - return @data if !$item || !%gpart; - if ($gpart{$item}){ - $data[0] = $gpart{$item}->{'block-size'} if $gpart{$item}->{'block-size'}; - $data[1] = $gpart{$item}->{'label'} if $gpart{$item}->{'label'}; - $data[2] = $gpart{$item}->{'uuid'} if $gpart{$item}->{'uuid'}; - $data[3] = $gpart{$item}->{'size'} if $gpart{$item}->{'size'}; - } - main::log_data('dump','@data',\@data) if $b_log; - eval $end if $b_log; - return @data; -} -# 2021-03: openbsd: n/a; dragonfly: no 'list'; freebsd: yes -sub set { - eval $start if $b_log; - $loaded{'gpart'} = 1; - if (my $path = main::check_program('gpart')){ - my @data = main::grabber("$path list 2>/dev/null",'','strip'); - main::log_data('dump', 'gpart: @data', \@data) if $b_log; - my ($id); - for (@data){ - my @working = split(/\s*:\s*/, $_); - if ($working[0] =~ /^[0-9]+\.\s*Name/){ - $id = $working[1]; - } - elsif ($id){ - # eg: label:(null) - we want to show null - if ($working[0] eq 'label'){ - $working[1] =~ s/\(|\)//g; - $gpart{$id}->{'label'} = $working[1]; - } - elsif ($working[0] eq 'Mediasize'){ - $working[1] =~ s/\s+\(.*$//; # trim off the (2.4G) - # gpart shows in bytes, not KiB. For the time being... - $gpart{$id}->{'size'} = $working[1]/1024 if $working[1]; - } - elsif ($working[0] eq 'rawuuid'){ - $working[1] =~ s/\(|\)//g; - $gpart{$id}->{'uuid'} = $working[1]; - } - elsif ($working[0] eq 'Sectorsize'){ - $gpart{$id}->{'block-size'} = $working[1]; - } - } - } - } - main::log_data('dump', '%gpart', \%gpart) if $b_log; - eval $end if $b_log; -} -} sub get_hostname { eval $start if $b_log; my $hostname = ''; @@ -21299,7 +23611,7 @@ sub get_init_data { if ( $comm ){ if ( $comm =~ /systemd/ ){ $init = 'systemd'; - if ( $program = check_program('systemd')){ + if ($program = check_program('systemd')){ $init_version = program_version($program,'^systemd','2','--version',1); } if (!$init_version && ($program = check_program('systemctl') ) ){ @@ -21380,6 +23692,175 @@ sub get_init_data { return %init; } +## IpData +{ +package IpData; +sub set { + eval $start if $b_log; + if ($alerts{'ip'}->{'action'} eq 'use' ){ + set_ip_addr(); + } + elsif ($alerts{'ifconfig'}->{'action'} eq 'use'){ + set_ifconfig(); + } + eval $end if $b_log; +} + +sub set_ip_addr { + eval $start if $b_log; + my @data = main::grabber($alerts{'ip'}->{'path'} . " addr 2>/dev/null",'\n','strip'); + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/if/scope-ipaddr-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/networking/ip-addr-blue-advance.txt"; + # my @data = reader($file,'strip') or die $!; + my ($b_skip,$broadcast,$if,$ip,@ips,$scope,$if_id,$type,@temp,@temp2); + foreach (@data){ + if (/^[0-9]/){ + # print "$_\n"; + if (@ips){ + # print "$if\n"; + @temp = ($if,[@ips]); + push(@ifs,@temp); + @ips = (); + } + @temp = split(/:\s+/, $_); + $if = $temp[1]; + if ($if eq 'lo'){ + $b_skip = 1; + $if = ''; + next; + } + $b_skip = 0; + @temp = (); + } + elsif (!$b_skip && /^inet/){ + # print "$_\n"; + @temp = split(/\s+/, $_); + ($broadcast,$ip,$scope,$if_id,$type) = ('','','','',''); + $ip = $temp[1]; + $type = ($temp[0] eq 'inet') ? 4 : 6 ; + if ($temp[2] eq 'brd'){ + $broadcast = $temp[3]; + } + if (/scope\s([^\s]+)(\s(.+))?/){ + $scope = $1; + $if_id = $3; + } + @temp = ($type,$ip,$broadcast,$scope,$if_id); + push(@ips,[@temp]); + # print Data::Dumper::Dumper \@ips; + } + } + # print Data::Dumper::Dumper \@ips if $dbg[4]; + if (@ips){ + @temp = ($if,[@ips]); + push(@ifs,@temp); + } + main::log_data('dump','@ifs',\@ifs) if $b_log; + print Data::Dumper::Dumper \@ifs if $dbg[3]; + eval $end if $b_log; +} + +sub set_ifconfig { + eval $start if $b_log; + my @data = main::grabber($alerts{'ifconfig'}->{'path'} . " 2>/dev/null",'\n',''); + # my @data = reader("$ENV{'HOME'}/bin/scripts/inxi/data/if/vps-ifconfig-1.txt",'') or die $!; + my ($b_skip,$broadcast,$if,@ips_bsd,$ip,@ips,$scope,$if_id,$type,@temp,@temp2); + my ($state,$speed,$duplex,$mac); + foreach (@data){ + if (/^[\S]/i){ + # print "$_\n"; + if (@ips){ + # print "here\n"; + @temp = ($if,[@ips]); + push(@ifs,@temp); + @ips = (); + } + if ($mac){ + @temp = ($if,[($state,$speed,$duplex,$mac)]); + push(@ifs_bsd,@temp); + ($state,$speed,$duplex,$mac,$if_id) = ('','','','',''); + } + $if = (split(/\s+/, $_))[0]; + $if =~ s/:$//; # em0: flags=8843 + $if_id = $if; + $if = (split(':', $if))[0] if $if; + if ($if =~ /^lo/){ + $b_skip = 1; + $if = ''; + $if_id = ''; + next; + } + $b_skip = 0; + } + elsif (!$b_skip && $bsd_type && /^\s+(address|ether|media|status|lladdr)/){ + $_ =~ s/^\s+//; + # freebsd 7.3: media: Ethernet 100baseTX + # Freebsd 8.2/12.2: media: Ethernet autoselect (1000baseT ) + # Netbsd 9.1: media: Ethernet autoselect (1000baseT full-duplex) + # openbsd: media: Ethernet autoselect (1000baseT full-duplex) + if (/^media/){ + if ($_ =~ /[\s\(]([1-9][^\(\s]+)?\s<([^>]+)>/){ + $speed = $1 if $1; + $duplex = $2; + } + if (!$duplex && $_ =~ /\s\(([\S]+)\s([^\s<]+)\)/){ + $speed = $1; + $duplex = $2; + } + if (!$speed && $_ =~ /\s\(([1-9][\S]+)\s/){ + $speed = $1; + } + } + # lladdr openbsd/address netbsd/ether freebsd + elsif (!$mac && /^(address|ether|lladdr)/){ + $mac = (split(/\s+/, $_))[1]; + } + elsif (/^status:\s*(.*)/){ + $state = $1; + } + } + elsif (!$b_skip && /^\s+inet/){ + # print "$_\n"; + $_ =~ s/^\s+//; + $_ =~ s/addr:\s/addr:/; + @temp = split(/\s+/, $_); + ($broadcast,$ip,$scope,$type) = ('','','',''); + $ip = $temp[1]; + # fe80::225:90ff:fe13:77ce%em0 +# $ip =~ s/^addr:|%([\S]+)//; + if ($1 && $1 ne $if_id){ + $if_id = $1; + } + $type = ($temp[0] eq 'inet') ? 4 : 6 ; + if (/(Bcast:|broadcast\s)([\S]+)/){ + $broadcast = $2; + } + if (/(scopeid\s[^<]+<|Scope:|scopeid\s)([^>]+)[>]?/){ + $scope = $2; + } + $scope = 'link' if $ip =~ /^fe80/; + @temp = ($type,$ip,$broadcast,$scope,$if_id); + push(@ips,[@temp]); + # print Data::Dumper::Dumper \@ips; + } + } + if (@ips){ + @temp = ($if,[@ips]); + push(@ifs,@temp); + } + if ($mac){ + @temp = ($if,[($state,$speed,$duplex,$mac)]); + push(@ifs_bsd,@temp); + ($state,$speed,$duplex,$mac) = ('','','',''); + } + print Data::Dumper::Dumper \@ifs if $dbg[3]; + print Data::Dumper::Dumper \@ifs_bsd if $dbg[3]; + main::log_data('dump','@ifs',\@ifs) if $b_log; + main::log_data('dump','@ifs_bsd',\@ifs_bsd) if $b_log; + eval $end if $b_log; +} +} + sub get_kernel_data { eval $start if $b_log; my ($kernel,$ksplice) = ('',''); @@ -21418,13 +23899,13 @@ sub get_kernel_bits { return $bits; } -# Get KernelParameters +## KernelParameters { package KernelParameters; sub get { eval $start if $b_log; my ($parameters); - if (my $file = main::system_files('cmdline') ) { + if (my $file = $system_files{'proc-cmdline'}) { $parameters = parameters_linux($file); } elsif ($bsd_type) { @@ -21448,8 +23929,12 @@ sub parameters_bsd { return $parameters; } } + +## LsblkData - set/get +{ +package LsblkData; # 1 - partition name -sub get_lsblk { +sub get { eval $start if $b_log; my $item = $_[0]; return if !@lsblk; @@ -21463,8 +23948,73 @@ sub get_lsblk { eval $start if $b_log; return %device; } +sub set { + eval $start if $b_log; + $loaded{'lsblk'} = 1; + if ($alerts{'lsblk'} && $alerts{'lsblk'}->{'path'}){ + my $cmd = $alerts{'lsblk'}->{'path'} . ' -bP --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,'; + $cmd .= 'SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS,MAJ:MIN,PKNAME 2>/dev/null'; + my $pattern = 'NAME="([^"]*)"\s+TYPE="([^"]*)"\s+RM="([^"]*)"\s+'; + $pattern .= 'FSTYPE="([^"]*)"\s+SIZE="([^"]*)"\s+LABEL="([^"]*)"\s+'; + $pattern .= 'UUID="([^"]*)"\s+SERIAL="([^"]*)"\s+MOUNTPOINT="([^"]*)"\s+'; + $pattern .= 'PHY-SEC="([^"]*)"\s+LOG-SEC="([^"]*)"\s+PARTFLAGS="([^"]*)"\s+'; + $pattern .= 'MAJ:MIN="([^"]*)"\s+PKNAME="([^"]*)"'; + my @working = main::grabber($cmd); + foreach (@working){ + if (/$pattern/){ + my $size = ($5) ? $5/1024: 0; + # some versions of lsblk do not return serial, fs, uuid, or label + push(@lsblk, { + 'name' => $1, + 'type' => $2, + 'rm' => $3, + 'fs' => $4, + 'size' => $size, + 'label' => $6, + 'uuid' => $7, + 'serial' => $8, + 'mount' => $9, + 'block-physical' => $10, + 'block-logical' => $11, + 'partition-flags' => $12, + 'maj-min' => $13, + 'parent' => $14, + }); + # must be below assignments!! otherwise the result of the match replaces values + # note: for bcache and luks, the device that has that fs is the parent!! + if ($show{'logical'}){ + $use{'logical-lvm'} = 1 if !$use{'logical-lvm'} && $2 && $2 eq 'lvm'; + if (!$use{'logical-general'} && (($4 && ($4 eq 'crypto_LUKS' || $4 eq 'bcache')) + || ($2 && ($2 eq 'dm' && $1 =~ /veracrypt/i) || + $2 eq 'crypto' || $2 eq 'mpath' || $2 eq 'multipath'))){ + $use{'logical-general'} = 1; + } + } + } + } + } + print Data::Dumper::Dumper \@lsblk if $dbg[32]; + main::log_data('dump','@lsblk',\@lsblk) if $b_log; + eval $end if $b_log; +} +} -# Get MemoryData +sub set_mapper { + eval $start if $b_log; + $loaded{'mapper'} = 1; + return if ! -d '/dev/mapper'; + foreach ((globber('/dev/mapper/*'))){ + my ($key,$value) = ($_,Cwd::abs_path("$_")); + next if !$value; + $key =~ s|^/.*/||; + $value =~ s|^/.*/||; + $mapper{$key} = $value; + } + %dmmapper = reverse %mapper if %mapper; + eval $end if $b_log; +} + +## MemoryData { package MemoryData; @@ -21476,7 +24026,7 @@ sub get { $loaded{'memory'} = 1; # netbsd uses meminfo, but it uses it in a weird way if (!$force{'vmstat'} && (!$bsd_type || ($force{'meminfo'} && $bsd_type)) && - (my $file = main::system_files('meminfo'))) { + (my $file = $system_files{'proc-meminfo'})) { $memory = meminfo_data($type,$file); } else { @@ -21595,27 +24145,27 @@ sub bsd_data { my @vmstat = main::grabber("vmstat 2>/dev/null",'\n','strip'); main::log_data('dump','@vmstat',\@vmstat) if $b_log; my @header = split(/\s+/, $vmstat[1]); - foreach ( @header){ + foreach (@header){ if ($_ eq 'avm'){$avm = $cnt} elsif ($_ eq 'fre'){$fre = $cnt} elsif ($_ eq 'flt'){last;} $cnt++; } my $row = $vmstat[-1]; - if ( $row ){ + if ($row){ @data = split(/\s+/, $row); # openbsd 6.3, dragonfly 5.x introduced an M / G character, sigh. if ($avm > 0 && $data[$avm] && $data[$avm] =~ /^([0-9\.]+[KGMT])(iB|B)?$/){ $data[$avm] = main::translate_size($1); } if ($fre > 0 && $data[$fre] && $data[$fre] =~ /^([0-9\.]+[KGMT])(iB|B)?$/){ - $data[$fre] = main::translate_size($1);; + $data[$fre] = main::translate_size($1); } # dragonfly can have 0 avg, or no avm, sigh, but they may fix that so make test dynamic if ($avm > 0 && $data[$avm] != 0){ $av_pages = ($bsd_type !~ /^(net|open)bsd$/) ? sprintf('%.1f',$data[$avm]/1024) : $data[$avm]; } - elsif ($fre > 0 && $data[$fre] != 0){ + if ($fre > 0 && $data[$fre] != 0){ $free_mem = sprintf('%.1f',$data[$fre]); } } @@ -21624,23 +24174,25 @@ sub bsd_data { if ($alerts{'sysctl'}->{'action'} eq 'use'){ # for dragonfly, we will use free mem, not used because free is 0 my @working; - foreach (@sysctl){ - # freebsd seems to use bytes here - if (!$real_mem && /^hw.physmem:/){ - @working = split(/:\s*/, $_); - #if ($working[1]){ - $working[1] =~ s/^[^0-9]+|[^0-9]+$//g; - $real_mem = sprintf("%.1f", $working[1]/1024); - #} - last if $free_mem; - } - # But, it uses K here. Openbsd/Dragonfly do not seem to have this item - # this can be either: Free Memory OR Free Memory Pages - elsif (/^Free Memory:/){ - @working = split(/:\s*/, $_); - $working[1] =~ s/[^0-9]+//g; - $free_mem = sprintf("%.1f", $working[1]); - last if $real_mem; + if ($sysctl{'memory'}){ + foreach (@{$sysctl{'memory'}}){ + # freebsd seems to use bytes here + if (!$real_mem && /^hw.physmem:/){ + @working = split(/:\s*/, $_); + # if ($working[1]){ + $working[1] =~ s/^[^0-9]+|[^0-9]+$//g; + $real_mem = sprintf("%.1f", $working[1]/1024); + # } + last if $free_mem; + } + # But, it uses K here. Openbsd/Dragonfly do not seem to have this item + # this can be either: Free Memory OR Free Memory Pages + elsif (/^Free Memory:/){ + @working = split(/:\s*/, $_); + $working[1] =~ s/[^0-9]+//g; + $free_mem = sprintf("%.1f", $working[1]); + last if $real_mem; + } } } } @@ -21712,7 +24264,7 @@ sub get_module_version { elsif (-f "/sys/module/$module/uevent"){ $version = 'kernel'; } - #print "version:$version\n"; + # print "version:$version\n"; if (!$version) { if (my $path = check_program('modinfo')){ my @data = grabber("$path $module 2>/dev/null"); @@ -21723,9 +24275,10 @@ sub get_module_version { eval $end if $b_log; return $version; } + +## PackageData # Note: this outputs the key/value pairs ready to go and is # called from either -r or -Ix, -r precedes. -## Get PackageData { package PackageData; my ($count,%counts,@list,$num,%output,$program,$type); @@ -21824,8 +24377,8 @@ sub package_counts { ['scratch','pkgbuild','d','/var/lib/scratchpkg/index/*/.pkginfo',1,5,'\\/', '-d \'/var/lib/scratchpkg\''], # note',' slapt-get, spkg, and pkgtool all return the same count - #['slapt-get','slapt-get','p','--installed',1,0,''], - #['spkg','spkg','p','--installed',1,0,''], + # ['slapt-get','slapt-get','p','--installed',1,0,''], + # ['spkg','spkg','p','--installed',1,0,''], ['tce','tce-status','p','-i',1,0,''], # note: I believe mageia uses rpm internally but confirm # ['urpmi','urpmq','p','??',1,0,''], @@ -21846,13 +24399,13 @@ sub package_counts { } $libs = undef; $count = scalar @list; - #print Data::Dumper::Dumper \@list; + # print Data::Dumper::Dumper \@list; if ($b_admin && $count && $_->[4]){ $libs = count_libs(\@list,$_->[5],$_->[6]); } - $counts{$_->[0]} = ([$count,$libs]); + $counts{$_->[0]} = [$count,$libs]; $counts{'total'} += $count; - #print Data::Dumper::Dumper \%counts; + # print Data::Dumper::Dumper \%counts; } } # print Data::Dumper::Dumper \%counts; @@ -21863,7 +24416,7 @@ sub appimage_counts { if (@ps_cmd && (grep {/\bappimaged\b/} @ps_cmd)){ @list = main::globber($ENV{'HOME'} . '/.local/bin/*.appimage'); $count = scalar @list; - $counts{'zzz-appimage'} = ([$count,undef]) if $count; + $counts{'zzz-appimage'} = [$count,undef] if $count; $counts{'total'} += $count; } } @@ -21872,16 +24425,58 @@ sub count_libs { my (@data); my $i = 0; $split ||= '\\s+'; - #print scalar @$items, '::', $split, '::', $pos, "\n"; + # print scalar @$items, '::', $split, '::', $pos, "\n"; foreach (@$items){ @data = split(/$split/, $_); - #print scalar @data, '::', $data[$pos], "\n"; + # print scalar @data, '::', $data[$pos], "\n"; $i++ if $data[$pos] && $data[$pos] =~ m%^lib%; } return $i; } } +## PartitionData - set/get +# for /proc/partitions only, see DiskDataBSD for BSD partition data. +{ +package PartitionData; +sub set { + my ($type) = @_; + $loaded{'partition-data'} = 1; + if (my $file = $system_files{'proc-partitions'}){ + proc_data($file); + } +} +# 1 - partition name, without /dev, like sda1, sde +sub get { + eval $start if $b_log; + my $item = $_[0]; + return if !@proc_partitions; + my (@device); + foreach my $device (@proc_partitions){ + if ($device->[3] eq $item){ + @device = @$device; + last; + } + } + eval $start if $b_log; + return @device; +} + +sub proc_data { + eval $start if $b_log; + my $file = $_[0]; + my @parts = main::reader($file,'strip'); + # print Dumper \@parts; + shift @parts if @parts; # get rid of headers + for (@parts){ + my @temp = split(/\s+/, $_); + next if !defined $temp[2]; + push (@proc_partitions,[$temp[0],$temp[1],$temp[2],$temp[3]]); + } + eval $end if $b_log; +} +} + # args: 1 - pci device string; 2 - pci cleaned subsystem string sub get_pci_vendor { eval $start if $b_log; @@ -21908,20 +24503,113 @@ sub get_pci_vendor { return $vendor; } -# 1 - partition name, without /dev, like sda1, sde -sub get_proc_partition { +sub set_ps_aux { eval $start if $b_log; - my $item = $_[0]; - return if !@proc_partitions; - my (@device); - foreach my $device (@proc_partitions){ - if ($device->[3] eq $item){ - @device = @$device; - last; + my ($header,@ps,@temp); + # note: some ps cut off output based on terminal width + # ww sets width unlimited + $loaded{'ps-aux'} = 1; + @ps = grabber("ps wwaux 2>/dev/null",'','strip'); + if (@ps){ + $header = shift @ps; # get rid of header row + # handle busy box, which has 3 columns, regular ps aux has 11 + # avoid deprecated implicit split error in older Perls + @temp = split(/\s+/, $header); + } + $ps_cols = $#temp; # the indexes, not the scalar count + if ($ps_cols < 10){ + my $version = qx(ps --version 2>&1); + $b_busybox_ps = 1 if $version =~ /busybox/i; + } + return if !@ps; # note: mips/openwrt ps has no 'a' + for (@ps){ + next if !$_; + next if $self_name eq 'inxi' && /\/$self_name\b/; + $_ = lc; + push (@ps_aux,$_); + my @split = split(/\s+/, $_); + # slice out 10th to last elements of ps aux rows + my $final = $#split; + # some stuff has a lot of data, chrome for example + $final = ($final > ($ps_cols + 2) ) ? $ps_cols + 2 : $final; + if ($split[$ps_cols] !~ /^\[/){ + push(@ps_cmd,join(' ', @split[$ps_cols .. $final])); } } + # never, because ps loaded before option handler + # print Dumper \@ps_cmd; # if $dbg[5]; + eval $end if $b_log; +} + +sub set_ps_gui { eval $start if $b_log; - return @device; + $loaded{'ps-gui'} = 1; + my ($working,@match,@temp); + # desktops / wm (some wm also compositors) + if ($show{'system'}){ + @temp=qw(razor-desktop razor-session lxsession lxqt-session + tdelauncher tdeinit_phase1); + push(@match,@temp); + @temp=qw(3dwm 9wm afterstep aewm aewm\+\+ amiwm antiwm awesome + blackbox bspwm + cagebreak calmwm (sh|c?lisp).*clfswm ctwm (openbsd-)?cwm dwm evilwm + fluxbox flwm flwm_topside fvwm.*-crystal fvwm1 fvwm2 fvwm3 fvwm95 fvwm + herbstluftwm i3 icewm instantwm ion3 jbwm jwm larswm lwm + matchbox-window-manager mini musca mwm nawm notion + openbox orbital pekwm perceptia python.*qtile qtile qvwm ratpoison + sawfish scrotwm spectrwm (sh|c?lisp).*stumpwm sway + tinywm tvtwm twm + waycooler way-cooler windowlab WindowMaker wm2 wmii2 wmii wmx + xfdesktop xmonad yeahwm); + push(@match,@temp); + } + # wm: + if ($show{'system'} && $extra > 1){ + @temp=qw(budgie-wm compiz deepin-wm gala gnome-shell + twin kwin_wayland kwin_x11 kwin marco + deepin-metacity metacity metisse mir muffin deepin-mutter mutter + ukwm xfwm4 xfwm5); + push(@match,@temp); + # startx: /bin/sh /usr/bin/startx + @temp=qw(ly .*startx xinit); # possible dm values + push(@match,@temp); + } + # info: NOTE: glx-dock is cairo-dock + if ($show{'system'} && $extra > 2){ + @temp=qw(alltray awn bar bmpanel bmpanel2 budgie-panel + cairo-dock dde-dock dmenu dockbarx docker docky dzen dzen2 + fbpanel fspanel glx-dock gnome-panel hpanel i3bar icewmtray + kdocker kicker latte latte-dock lemonbar ltpanel lxpanel lxqt-panel + matchbox-panel mate-panel ourico + perlpanel plank plasma-desktop plasma-netbook polybar pypanel + razor-panel razorqt-panel stalonetray swaybar taskbar tint2 trayer + ukui-panel vala-panel wbar wharf wingpanel witray + xfce4-panel xfce5-panel xmobar yabar); + push(@match,@temp); + } + # compositors (for wayland these are also the server, note. + # for wayland always show, so always load these + if ($show{'graphic'} && $extra > 0){ + @temp=qw(3dwm asc budgie-wm compiz compton deepin-wm dwc dcompmgr + enlightenment fireplace gnome-shell grefson kmscon kwin_wayland kwin_x11 + liri marco metisse mir moblin motorcar muffin mutter + orbital papyros perceptia picom rustland sommelier sway swc + ukwm unagi unity-system-compositor + wavy waycooler way-cooler wayfire wayhouse westford weston xcompmgr); + push(@match,@temp); + } + uniq(\@match); + my $matches = join('|', @match); + foreach (@ps_cmd){ + if (/^(|[\S]*\/)($matches)(\/|\s|$)/){ + $working = $2; + push(@ps_gui, $working); # deal with duplicates with uniq + } + } + uniq(\@ps_gui) if @ps_gui; + print Dumper \@ps_gui if $dbg[5]; + log_data('dump','@ps_gui',\@ps_gui) if $b_log; + eval $end if $b_log; } # # check? /var/run/nologin for bsds? @@ -21931,7 +24619,7 @@ sub get_runlevel_data { if ( my $program = check_program('runlevel')){ $runlevel = (grabber("$program 2>/dev/null"))[0]; $runlevel =~ s/[^\d]//g if $runlevel; - #print_line($runlevel . ";;"); + # print_line($runlevel . ";;"); } eval $end if $b_log; return $runlevel; @@ -21982,7 +24670,8 @@ sub get_self_version { eval $end if $b_log; return $self_version . $patch; } -# Get ServiceData + +## ServiceData { package ServiceData; my ($key,$service,$type); @@ -22025,6 +24714,9 @@ sub process_status { elsif ($key eq 'rc-service'){ $cmd = "$service_tool{$key}->[0] $service status"; } + elsif ($key eq 'rcctl'){ + $cmd = "$service_tool{$key}->[0] check $service"; + } # dragonfly/netbsd/freebsd have this elsif ($key eq 'service'){ $cmd = "$service_tool{$key}->[0] $service status"; @@ -22052,7 +24744,7 @@ sub process_status { } } @data = main::grabber("$cmd 2>&1",'','strip') if $cmd; - #@data = ('bluetooth is running.'); + # @data = ('bluetooth is running.'); print "key: $key\n", Data::Dumper::Dumper \@data if $dbg[29]; main::log_data('dump','service @data',\@data) if $b_log; for my $row (@data){ @@ -22069,7 +24761,7 @@ sub process_status { $working[1] =~ /^(.+?)\s*\((\S+?)\).*/; $value = lc($1) if $1 && (!$result || $result ne 'disabled'); $value = $translate{$value} if $value && $translate{$value}; - $result .= ", $value" if ($result && $value); + $result .= ",$value" if ($result && $value); last; } # valid syntax, but service does not exist @@ -22126,6 +24818,10 @@ sub set { # rc-service ssh status :: * status: stopped %service_tool = ('rc-service' => [$path,'rc-service']); } + elsif ($path = main::check_program('rcctl')){ + # rc-service ssh status :: * status: stopped + %service_tool = ('rcctl' => [$path,'rcctl']); + } elsif ($path = main::check_program('service')){ # service sshd status %service_tool = ('service' => [$path,'service']); @@ -22148,7 +24844,7 @@ sub set { } # $dbg[29] = 1; set_path(); print ServiceData::get('status','bluetooth'),"\n"; -# Get ShellData +## ShellData { package ShellData; my $b_debug = 0; # disable all debugger output in case forget to comment out! @@ -22206,7 +24902,7 @@ sub set { $shell = $working; } } - #print "3: shell post: $shell working: $working\n"; + # print "3: shell post: $shell working: $working\n"; # since there are endless shells, we'll keep a list of non program value # set shells since there is little point in adding those to program values if (shell_test($shell)){ @@ -22225,7 +24921,7 @@ sub set { # eg: shell -> infos -> inxi -> sh -> infos --version -> infos -> inxi... # Basically here we are hoping that the grandparent is a shell, or at least # recognized as a known possible program - #print "app not shell?: $shell\n"; + # print "app not shell?: $shell\n"; if ($shell){ print "shell 4: $shell StartClientVersionType: $parent\n" if $b_debug; if ($parent){ @@ -22285,10 +24981,10 @@ sub shell_launcher { $msg = ($ppid) ? "pppid: $pppid ppid: $ppid": "ppid: undefined"; main::log_data('data',$msg); } - #print "self parent: $pppid ppid: $ppid\n"; + # print "self parent: $pppid ppid: $ppid\n"; if ($pppid){ $shell_parent = $client{'parent'}; - #print "shell parent 1: $shell_parent\n"; + # print "shell parent 1: $shell_parent\n"; if ($b_log){ $msg = ($shell_parent) ? "shell parent 1: $shell_parent": "shell parent 1: undefined"; main::log_data('data',$msg); @@ -22333,7 +25029,7 @@ sub get_pppid { my $cmd = "ps -wwjfp $ppid 2>/dev/null"; main::log_data('cmd',$cmd) if $b_log; my @data = main::grabber($cmd); - #shift @data if @data; + # shift @data if @data; my $pppid = main::awk(\@data,"$ppid",3,'\s+'); eval $end if $b_log; return $pppid; @@ -22448,6 +25144,112 @@ sub tty_number { } } +sub set_sysctl_data { + eval $start if $b_log; + return if !$alerts{'sysctl'} || $alerts{'sysctl'}->{'action'} ne 'use'; + my (@temp); + # darwin sysctl has BOTH = and : separators, and repeats data. Why? + if (!$fake{'sysctl'}){ + # just on odd chance we hit a bsd with /proc/cpuinfo, don't want to + # sleep 2x + if ($use{'bsd-sleep'} && !$system_files{'proc-cpuinfo'}){ + if ($b_hires){ + eval 'Time::HiRes::usleep( $sleep )'; + } + else { + select(undef, undef, undef, $cpu_sleep); + } + } + @temp = grabber($alerts{'sysctl'}->{'path'} . " -a 2>/dev/null"); + } + else { + my $file; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1_sysctl_soekris6501_root.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1sysctl_lenovot500_user.txt"; + ## matches: compaq: openbsd-dmesg.boot-1.txt + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-1.txt"; + ## matches: toshiba: openbsd-5.6-dmesg.boot-1.txt + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-2.txt"; + $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd-6.8-sysctl-a-battery-sensor-1.txt"; + @temp = reader($file); + } + foreach (@temp){ + $_ =~ s/\s*=\s*|:\s+/:/; + $_ =~ s/\"//g; + push(@{$sysctl{'main'}}, $_); + # we're building these here so we can use these arrays per feature + if ($use{'bsd-audio'} && /^hw\.snd\./){ + push(@{$sysctl{'audio'}}, $_); # not used currently, just test data + } + # note: we could use ac0 to indicate plugged in but messes with battery output + elsif ($use{'bsd-battery'} && /^hw\.sensors\.acpi(bat|cmb)/){ + push(@{$sysctl{'battery'}}, $_); + } + # hw.cpufreq.temperature: 40780 :: dev.cpu0.temperature + # hw.acpi.thermal.tz2.temperature: 27.9C :: hw.acpi.thermal.tz1.temperature: 42.1C + # hw.acpi.thermal.tz0.temperature: 42.1C + elsif ($use{'bsd-sensor'} &&((/^hw\.sensors/ && !/^hw\.sensors\.acpi(ac|bat|cmb)/ && + !/^hw\.sensors\.softraid/) || /^hw\.acpi\.thermal/ || /^dev\.cpu\.[0-9]+\.temp/)){ + push(@{$sysctl{'sensor'}}, $_); + } + # Must go AFTER sensor because sometimes freebsd puts sensors in dev.cpu + # hw.l1dcachesize hw.l2cachesize + elsif ($use{'bsd-cpu'} && (/^hw\.(busfreq|clock|n?cpu|l[123].?cach|model)/ || + /^dev\.cpu/ || /^machdep\.cpu/)){ + push(@{$sysctl{'cpu'}}, $_); + } + # only activate if using the diskname feature in dboot!! + elsif ($use{'bsd-disk'} && /^hw\.disknames/){ + push(@{$dboot{'disk'}}, $_); + } + elsif ($use{'bsd-kernel'} && /^kern.compiler_version/){ + push(@{$dboot{'kernel'}}, $_); + } + elsif ($use{'bsd-machine'} && + /^(hw\.|machdep\.dmi\.(bios|board|system)-)(date|product|serial(no)?|uuid|vendor|version)/){ + push(@{$sysctl{'machine'}}, $_); + } + # let's rely on dboot, we really just want the hardware specs for solid ID + # elsif ($use{'bsd-machine'} && !$dboot{'machine-vm'} && + # /(\bhvm\b|innotek|\bkvm\b|microsoft.*virtual machine|openbsd[\s-]vmm|qemu|qumranet|vbox|virtio|virtualbox|vmware)/i){ + # push(@{$dboot{'machine-vm'}}, $_); + # } + elsif ($use{'bsd-memory'} && /^(hw\.(physmem|usermem)|Free Memory)/){ + push(@{$sysctl{'memory'}}, $_); + } + + elsif ($use{'bsd-raid'} && /^hw\.sensors\.softraid[0-9]\.drive[0-9]/){ + push(@{$sysctl{'softraid'}}, $_); + } + } + if ($dbg[7]){ + print("main\n", Dumper $sysctl{'main'}); + print("dboot-machine-vm\n", Dumper $dboot{'machine-vm'}); + print("audio\n", Dumper $sysctl{'audio'}); + print("battery\n", Dumper $sysctl{'battery'}); + print("cpu\n", Dumper $sysctl{'cpu'}); + print("kernel\n", Dumper $sysctl{'kernel'}); + print("machine\n", Dumper $sysctl{'machine'}); + print("memory\n", Dumper $sysctl{'memory'}); + print("sensors\n", Dumper $sysctl{'sensor'}); + print("softraid\n", Dumper $sysctl{'softraid'}); + } + # this thing can get really long. + if ($b_log){ + main::log_data('dump','$sysctl{main}',$sysctl{'main'}); + main::log_data('dump','$dboot{machine-vm}',$sysctl{'machine-vm'}); + main::log_data('dump','$sysctl{audio}',$sysctl{'audio'}); + main::log_data('dump','$sysctl{battery}',$sysctl{'battery'}); + main::log_data('dump','$sysctl{cpu}',$sysctl{'cpu'}); + main::log_data('dump','$sysctl{kernel}',$sysctl{'kernel'}); + main::log_data('dump','$sysctl{machine}',$sysctl{'machine'}); + main::log_data('dump','$sysctl{memory}',$sysctl{'memory'}); + main::log_data('dump','$sysctl{sensors}',$sysctl{'sensor'}); + main::log_data('dump','$sysctl{softraid}',$sysctl{'softraid'}); + } + eval $end if $b_log; +} + sub get_uptime { eval $start if $b_log; my ($days,$hours,$minutes,$seconds,$uptime) = ('','','','',''); @@ -22486,1275 +25288,9 @@ sub get_uptime { eval $end if $b_log; return $uptime; } -# note: seen instance in android where reading file hangs endlessly!!! -sub get_wakeups { - eval $start if $b_log; - return if $b_arm || $b_mips || $b_ppc; - my ($wakeups); - my $path = '/sys/power/wakeup_count'; - $wakeups = reader($path,'strip',0) if -r $path; - eval $end if $b_log; - return $wakeups; -} -#### ------------------------------------------------------------------- -#### SET DATA VALUES - used to set data for program features -#### ------------------------------------------------------------------- - -# android only, for distro / OS id and machine data -sub set_build_prop { - eval $start if $b_log; - my $path = '/system/build.prop'; - $loaded{'build-prop'} = 1; - return if ! -r $path; - my @data = reader($path,'strip'); - foreach (@data){ - my @working = split('=', $_); - next if $working[0] !~ /^ro\.(build|product)/; - if ($working[0] eq 'ro.build.date.utc'){ - $build_prop{'build-date'} = strftime "%F", gmtime($working[1]); - } - # ldgacy, replaced by ro.product.device - elsif ($working[0] eq 'ro.build.product'){ - $build_prop{'build-product'} = $working[1]; - } - # this can be brand, company, android, it varies, but we don't want android value - elsif ($working[0] eq 'ro.build.user'){ - $build_prop{'build-user'} = $working[1] if $working[1] !~ /android/i; - } - elsif ($working[0] eq 'ro.build.version.release'){ - $build_prop{'build-version'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.board'){ - $build_prop{'product-board'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.brand'){ - $build_prop{'product-brand'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.device'){ - $build_prop{'product-device'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.manufacturer'){ - $build_prop{'product-manufacturer'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.model'){ - $build_prop{'product-model'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.name'){ - $build_prop{'product-name'} = $working[1]; - } - elsif ($working[0] eq 'ro.product.screensize'){ - $build_prop{'product-screensize'} = $working[1]; - } - } - log_data('dump','%build_prop',\%build_prop) if $b_log; - print Dumper \%build_prop if $dbg[20]; - eval $end if $b_log; -} - -## creates arrays: @devices_audio; @devices_graphics; @devices_hwraid; -## @devices_network; @devices_timer plus @devices for logging/debugging -# 0 type -# 1 type_id -# 2 bus_id -# 3 sub_id -# 4 device -# 5 vendor_id -# 6 chip_id -# 7 rev -# 8 port -# 9 driver -# 10 modules -# 11 driver_nu [bsd, like: em0 - driver em; nu 0. Used to match IF in -n -# 12 subsystem/vendor -# 13 subsystem vendor_id:chip id -# 14 soc handle -## DeviceData / PCI / SOC -{ -package DeviceData; -my (@bluetooth,@devices,@files,@full_names,@pcis,@temp,@temp2,@temp3); -my ($b_bt_check); -my ($busid,$busid_nu,$chip_id,$content,$device,$driver,$driver_nu,$file, -$handle,$modules,$port,$rev,$temp,$type,$type_id,$vendor,$vendor_id); - -sub set { - eval $start if $b_log; - ${$_[0]} = 1; # set check by reference - if ($use{'pci'}){ - if (!$bsd_type){ - if ($alerts{'lspci'}->{'action'} eq 'use' ){ - lspci_data(); - } - # ! -d '/proc/bus/pci' - # this is sketchy, a sbc won't have pci, but a non sbc arm may have it, so - # build up both and see what happens - if ($b_arm || $b_mips || $b_ppc || $b_sparc){ - soc_data(); - } - } - else { - #if (1 == 1){ - if ($alerts{'pciconf'}->{'action'} eq 'use'){ - pciconf_data(); - } - elsif ($alerts{'pcidump'}->{'action'} eq 'use'){ - pcidump_data(); - } - elsif ($alerts{'pcictl'}->{'action'} eq 'use'){ - pcictl_data(); - } - } - if ($dbg[9]){ - print Data::Dumper::Dumper \@devices_audio; - print Data::Dumper::Dumper \@devices_bluetooth; - print Data::Dumper::Dumper \@devices_graphics; - print Data::Dumper::Dumper \@devices_network; - print Data::Dumper::Dumper \@devices_hwraid; - print Data::Dumper::Dumper \@devices_timer; - print "vm: $device_vm\n"; - } - if ( $b_log){ - main::log_data('dump','@devices_audio',\@devices_audio); - main::log_data('dump','@devices_bluetooth',\@devices_bluetooth); - main::log_data('dump','@devices_graphics',\@devices_graphics); - main::log_data('dump','@devices_hwraid',\@devices_hwraid); - main::log_data('dump','@devices_network',\@devices_network); - main::log_data('dump','@devices_timer',\@devices_timer); - } - } - @devices = undef; - eval $end if $b_log; -} - -sub lspci_data { - eval $start if $b_log; - my ($subsystem,$subsystem_id); - my @data = pci_grabber('lspci'); - #print Data::Dumper::Dumper \@data; - foreach (@data){ - #print "$_\n"; - if ($device){ - if ($_ =~ /^~$/) { - @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, - $rev,$port,$driver,$modules,$driver_nu,$subsystem,$subsystem_id); - assign_data('pci',\@temp); - $device = ''; - #print "$busid $device_id r:$rev p: $port\n$type\n$device\n"; - } - elsif ($_ =~ /^Subsystem.*\[([a-f0-9]{4}:[a-f0-9]{4})\]/){ - $subsystem_id = $1; - $subsystem = (split(/^Subsystem:\s*/, $_))[1]; - $subsystem =~ s/(\s?\[[^\]]+\])+$//g; - $subsystem = main::cleaner($subsystem); - $subsystem = main::pci_cleaner($subsystem,'pci'); - $subsystem = main::pci_cleaner_subsystem($subsystem); - #print "ss:$subsystem\n"; - } - elsif ($_ =~ /^I\/O\sports/){ - $port = (split(/\s+/, $_))[3]; - #print "p:$port\n"; - } - elsif ($_ =~ /^Kernel\sdriver\sin\suse/){ - $driver = (split(/:\s*/, $_))[1]; - } - elsif ($_ =~ /^Kernel\smodules/i){ - $modules = (split(/:\s*/, $_))[1]; - } - } - # note: arm servers can have more complicated patterns - # 0002:01:02.0 Ethernet controller [0200]: Cavium, Inc. THUNDERX Network Interface Controller virtual function [177d:a034] (rev 08) - elsif ($_ =~ /^(([0-9a-f]{2,4}:)?[0-9a-f]{2}:[0-9a-f]{2})[.:]([0-9a-f]+)\s(.*)\s\[([0-9a-f]{4}):([0-9a-f]{4})\](\s\(rev\s([^\)]+)\))?/){ - $busid = $1; - $busid_nu = hex($3); - @temp = split(/:\s+/, $4); - $device = $temp[1]; - $type = $temp[0]; - $vendor_id = $5; - $chip_id = $6; - $rev = ($8)? $8 : ''; - $device = main::cleaner($device); - $temp[0] =~ /\[([^\]]+)\]$/; - $type_id = $1; - $use{'hardware-raid'} = 1 if $type_id eq '0104'; - $type = lc($type); - $type = main::pci_cleaner($type,'pci'); - $type =~ s/\s+$//; - #print "$type\n"; - ($driver,$driver_nu,$modules,$subsystem,$subsystem_id) = ('','','','',''); - } - } - print Data::Dumper::Dumper \@devices if $dbg[4]; - main::log_data('dump','lspci @devices',\@devices) if $b_log; - eval $end if $b_log; -} - -# em0@pci0:6:0:0: class=0x020000 card=0x10d315d9 chip=0x10d38086 rev=0x00 hdr=0x00 -# vendor = 'Intel Corporation' -# device = 'Intel 82574L Gigabit Ethernet Controller (82574L)' -# class = network -# subclass = ethernet -sub pciconf_data { - eval $start if $b_log; - my @data = pci_grabber('pciconf'); - foreach (@data){ - if ($driver){ - if ($_ =~ /^~$/) { - $vendor = main::cleaner($vendor); - $device = main::cleaner($device); - # handle possible regex in device name, like [ConnectX-3] - # and which could make matches fail - my $device_temp = main::regex_cleaner($device); - if ($vendor && $device){ - if (main::regex_cleaner($vendor) !~ /\Q$device_temp\E/i){ - $device = "$vendor $device"; - } - } - elsif (!$device){ - $device = $vendor; - } - @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, - $rev,$port,$driver,$modules,$driver_nu); - assign_data('pci',\@temp); - $driver = ''; - #print "$busid $device_id r:$rev p: $port\n$type\n$device\n"; - } - elsif ($_ =~ /^vendor/){ - $vendor = (split(/\s+=\s+/, $_))[1]; - #print "p:$port\n"; - } - elsif ($_ =~ /^device/){ - $device = (split(/\s+=\s+/, $_))[1]; - } - elsif ($_ =~ /^class/i){ - $type = (split(/\s+=\s+/, $_))[1]; - } - } - # atapci0@pci0:0:1:1: class=0x01018a card=0x00000000 chip=0x71118086 rev=0x01 hdr=0x00 - # pre freebsd 13. - elsif (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}).*class=0x([\S]{4})\S*\scard=0x([\S]+)\schip=0x([\S]+)\srev=0x([\S]+)/){ - $driver = $1; - $busid = $2; - $busid_nu = $3; - $type_id = $4; # we don't use the sub sub class part of the id, just first 4 - #$vendor_id = $5; - $vendor_id = substr($6,4,4); - $chip_id = substr($6,0,4); - $rev = $7; - $driver =~ s/(^[a-z]+)([0-9]+$)//; - $driver = $1; - $driver_nu = $2; - ($device,$type,$vendor) = ('','',''); - } - # isab0@pci0:0:1:0: class=0x060100 rev=0x00 hdr=0x00 vendor=0x8086 device=0x7000 subvendor=0x0000 subdevice=0x0000 - # freebsd 13 changes. - elsif (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}).*class=0x([0-9a-f]{4})[\S]*\srev=0x([\S]+)\shdr=0x([^\s]+)\svendor=0x([\S]+)\sdevice=0x([\S]+)(\ssubvendor=0x([\S]+)\ssubdevice=0x([\S]+))?/){ - $driver = $1; - $busid = $2; - $busid_nu = $3; - $type_id = $4; - $rev = $5; - $vendor_id = $7; - $chip_id = $8; - $driver =~ /(^[a-z]+)([0-9]+$)/; - $driver = $1; - $driver_nu = $2; - ($device,$type,$vendor) = ('','',''); - } - } - print Data::Dumper::Dumper \@devices if $dbg[4]; - main::log_data('dump','pciconf @devices',\@devices) if $b_log; - eval $end if $b_log; -} - -sub pcidump_data { - eval $start if $b_log; - my @data = pci_grabber('pcidump'); - foreach (@data){ - if ($_ =~ /^~$/ && $busid && $device) { - @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, - $rev,$port,$driver,$modules,$driver_nu); - assign_data('pci',\@temp); - ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, - $rev,$port,$driver,$modules,$driver_nu) = undef; - next; - } - if ($_ =~ /^([0-9a-f:]+):([0-9]+):\s([^:]+)$/i){ - $busid = $1; - $busid_nu = $2; - $device = main::cleaner($3); - } - elsif ($_ =~ /^0x[\S]{4}:\s+Vendor ID:\s+([0-9a-f]{4}),?\s+Product ID:\s+([0-9a-f]{4})/ ){ - $vendor_id = $1; - $chip_id = $2; - } - elsif ($_ =~ /^0x[\S]{4}:\s+Class:\s+([0-9a-f]{2})(\s[^,]+)?,?\s+Subclass:\s+([0-9a-f]{2})(\s+[^,]+)?,?(\s+Interface: ([0-9a-f]+),?\s+Revision: ([0-9a-f]+))?/){ - $type = pci_class($1); - $type_id = "$1$3"; - } - } - print Data::Dumper::Dumper \@devices if $dbg[4]; - main::log_data('dump','pcidump @devices',\@devices) if $b_log; - eval $end if $b_log; -} -sub pcictl_data { - eval $start if $b_log; - my @data = pci_grabber('pcictl'); - my @data2 = pci_grabber('pcictl-n'); - foreach (@data){ - if ($_ =~ /^~$/ && $busid && $device) { - @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, - $rev,$port,$driver,$modules,$driver_nu); - assign_data('pci',\@temp); - ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, - $rev,$port,$driver,$modules,$driver_nu) = undef; - next; - } - # it's too fragile to get these in one matching so match, trim, next match - if (/\s+\[([^\]0-9]+)([0-9]+)\]$/){ - $driver = $1; - $driver_nu = $2; - $_ =~ s/\s+\[[^\]]+\]$//; - } - if (/\s+\(.*?(revision 0x([^\)]+))?\)/){ - $rev = $2 if $2; - $_ =~ s/\s+\([^\)]+?\)$//; - } - if ($_ =~ /^([0-9a-f:]+):([0-9]+):\s+([^.]+?)$/i){ - $busid = $1; - $busid_nu = $2; - $device = main::cleaner($3); - my $working = (grep {/^${busid}:${busid_nu}:\s/} @data2)[0]; - if ($working && - $working =~ /^${busid}:${busid_nu}:\s+0x([0-9a-f]{4})([0-9a-f]{4})\s+\(0x([0-9a-f]{2})([0-9a-f]{2})[0-9a-f]+\)/){ - $vendor_id = $1; - $chip_id = $2; - $type = pci_class($3); - $type_id = "$3$4"; - } - } - } - print Data::Dumper::Dumper \@devices if $dbg[4]; - main::log_data('dump','pcidump @devices',\@devices) if $b_log; - eval $end if $b_log; -} - -sub pci_grabber { - eval $start if $b_log; - my ($program) = @_; - my ($args,$path,$pattern,@working); - if ($program eq 'lspci'){ - $args = ' -knnv'; - $path = $alerts{'lspci'}->{'path'}; - $pattern = '^[0-9a-f]+:'; - } - elsif ($program eq 'pciconf'){ - $args = ' -lv'; - $path = $alerts{'pciconf'}->{'path'}; - $pattern = '^([^@]+)\@pci'; - } - elsif ($program eq 'pcidump'){ - $args = ' -v'; - $path = $alerts{'pcidump'}->{'path'}; - $pattern = '^[0-9a-f]+:'; - } - elsif ($program eq 'pcictl'){ - $args = ' pci0 list -N'; - $path = $alerts{'pcictl'}->{'path'}; - $pattern = '^[0-9a-f:]+:'; - } - elsif ($program eq 'pcictl-n'){ - $args = ' pci0 list -n'; - $path = $alerts{'pcictl'}->{'path'}; - $pattern = '^[0-9a-f:]+:'; - } - my @data = main::grabber("$path $args 2>/dev/null",'','strip'); - if ($fake{'pciconf'} || $fake{'pcictl'} || $fake{'pcidump'}){ - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pciconf/pci-freebsd-8.2-2"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcidump/pci-openbsd-6.1-vm.txt"; - my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcictl/pci-netbsd-9.1-vm.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/racermach-1-knnv.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/rk016013-knnv.txt"; - @data = main::reader($file,'strip'); - } - if (@data){ - $use{'pci-tool'} = 1 if scalar @data > 10; - foreach (@data){ - if ($_ =~ /$pattern/i){ - push(@working, '~'); - } - push(@working, $_); - } - push(@working, '~'); - } - print Data::Dumper::Dumper \@working if $dbg[30]; - eval $end if $b_log; - return @working; -} - -sub soc_data { - eval $start if $b_log; - soc_devices_files(); - soc_devices(); - soc_devicetree(); - print Data::Dumper::Dumper \@devices if $dbg[4]; - main::log_data('dump','soc @devices',\@devices) if $b_log; - eval $end if $b_log; -} -# 1: /sys/devices/platform/soc/1c30000.ethernet/uevent:["DRIVER=dwmac-sun8i", "OF_NAME=ethernet", -# "OF_FULLNAME=/soc/ethernet@1c30000", "OF_COMPATIBLE_0=allwinner,sun8i-h3-emac", -# "OF_COMPATIBLE_N=1", "OF_ALIAS_0=ethernet0", # "MODALIAS=of:NethernetTCallwinner,sun8i-h3-emac"] -# 2: /sys/devices/platform/soc:audio/uevent:["DRIVER=bcm2835_audio", "OF_NAME=audio", "OF_FULLNAME=/soc/audio", -# "OF_COMPATIBLE_0=brcm,bcm2835-audio", "OF_COMPATIBLE_N=1", "MODALIAS=of:NaudioTCbrcm,bcm2835-audio"] -# 3: /sys/devices/platform/soc:fb/uevent:["DRIVER=bcm2708_fb", "OF_NAME=fb", "OF_FULLNAME=/soc/fb", -# "OF_COMPATIBLE_0=brcm,bcm2708-fb", "OF_COMPATIBLE_N=1", "MODALIAS=of:NfbTCbrcm,bcm2708-fb"] -# 4: /sys/devices/platform/soc/1c40000.gpu/uevent:["OF_NAME=gpu", "OF_FULLNAME=/soc/gpu@1c40000", -# "OF_COMPATIBLE_0=allwinner,sun8i-h3-mali", "OF_COMPATIBLE_1=allwinner,sun7i-a20-mali", -# "OF_COMPATIBLE_2=arm,mali-400", "OF_COMPATIBLE_N=3", -# "MODALIAS=of:NgpuTCallwinner,sun8i-h3-maliCallwinner,sun7i-a20-maliCarm,mali-400"] -# 5: /sys/devices/platform/soc/soc:internal-regs/d0018180.gpio/uevent -# 6: /sys/devices/soc.0/1180000001800.mdio/8001180000001800:05/uevent -# ["DRIVER=AR8035", "OF_NAME=ethernet-phy" -# 7: /sys/devices/soc.0/1c30000.eth/uevent -# 8: /sys/devices/wlan.26/uevent [from pine64] -# 9: /sys/devices/platform/audio/uevent:["DRIVER=bcm2835_AUD0", "OF_NAME=audio" -# 10: /sys/devices/vio/71000002/uevent:["DRIVER=ibmveth", "OF_NAME=l-lan" -# 11: /sys/devices/platform/soc:/soc:i2c-hdmi:/i2c-2/2-0050/uevent:['OF_NAME=hdmiddc' -# 12: /sys/devices/platform/soc:/soc:i2c-hdmi:/uevent:['DRIVER=i2c-gpio', 'OF_NAME=i2c-hdmi' -# 13: /sys/devices/platform/scb/fd580000.ethernet/uevent -# 14: /sys/devices/platform/soc/fe300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1/uevent (wifi, pi 3,4) -# 15: Pi BT: /sys/devices/platform/soc/fe201000.serial/uevent -# 16: Pi BT: /sys/devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0 -sub soc_devices_files { - eval $start if $b_log; - if (-d '/sys/devices/platform/'){ - @files = main::globber('/sys/devices/platform/soc*/*/uevent'); - @temp2 = main::globber('/sys/devices/platform/soc*/*/*/uevent'); - push(@files,@temp2) if @temp2; - if (-e '/sys/devices/platform/scb'){ - @temp2 = main::globber('/sys/devices/platform/scb/*/uevent'); - push(@files,@temp2) if @temp2; - @temp2 = main::globber('/sys/devices/platform/scb/*/*/uevent'); - push(@files,@temp2) if @temp2; - } - @temp2 = main::globber('/sys/devices/platform/*/uevent'); - push(@files,@temp2) if @temp2; - } - if (main::globber('/sys/devices/soc*')){ - @temp2 = main::globber('/sys/devices/soc*/*/uevent'); - push(@files,@temp2) if @temp2; - @temp2 = main::globber('/sys/devices/soc*/*/*/uevent'); - push(@files,@temp2) if @temp2; - } - @temp2 = main::globber('/sys/devices/*/uevent'); # see case 8 - push(@files,@temp2) if @temp2; - @temp2 = main::globber('/sys/devices/*/*/uevent'); # see case 10 - push(@files,@temp2) if @temp2; - @temp2 = undef; - # not sure why, but even as root/sudo, /subsystem|driver/uevent are unreadable with -r test true - @files = grep {!/\/(subsystem|driver)\//} @files if @files; - main::uniq(\@files); - eval $end if $b_log; -} - -sub soc_devices { - eval $start if $b_log; - my (@working); - set_bluetooth() if !$b_bt_check; - foreach $file (@files){ - next if -z $file; - $chip_id = $file; - # variants: /soc/20100000.ethernet/ /soc/soc:audio/ /soc:/ /soc@0/ /soc:/12cb0000.i2c:/ - # mips: /sys/devices/soc.0/1180000001800.mdio/8001180000001800:07/ - # ppc: /sys/devices/vio/71000002/ - $chip_id =~ /\/sys\/devices\/(platform\/)?(soc[^\/]*\/)?([^\/]+\/)?([^\/]+\/)?([^\/\.:]+)([\.:])?([^\/:]+)?:?\/uevent$/; - $chip_id = $5; - $temp = $7; - @working = main::reader($file, 'strip') if -r $file; - ($device,$driver,$handle,$type,$vendor_id) = (undef,undef,undef,undef,undef); - foreach my $data (@working){ - @temp2 = split('=', $data); - if ($temp2[0] eq 'DRIVER'){ - $driver = $temp2[1]; - $driver =~ s/-/_/g if $driver; # kernel uses _, not - in module names - } - elsif ($temp2[0] eq 'OF_NAME'){ - $type = $temp2[1]; - } - # we'll use these paths to test in device tree pci completer - elsif ($temp2[0] eq 'OF_FULLNAME' && $temp2[1]){ - # we don't want the short names like /soc, /led and so on - push(@full_names, $temp2[1]) if (() = $temp2[1] =~ /\//g) > 1; - $handle = (split('@', $temp2[1]))[-1] if $temp2[1] =~ /@/; - } - elsif ($temp2[0] eq 'OF_COMPATIBLE_0'){ - @temp3 = split(',', $temp2[1]); - $device = $temp3[-1]; - $vendor_id = $temp3[0]; - } - } - # it's worthless, we can't use it - next if ! defined $type; - $type_id = $type; - if (@bluetooth && $type eq 'serial'){ - my $file_temp = $file; - $file_temp =~ s/uevent$//; - $type = 'bluetooth' if grep {/$file_temp/} @bluetooth; - } - $chip_id = '' if ! defined $chip_id; - $vendor_id = '' if ! defined $vendor_id; - $driver = '' if ! defined $driver; - $handle = '' if ! defined $handle; - $busid = (defined $temp && main::is_int($temp)) ? $temp: 0; - $type = soc_type($type,$vendor_id,$driver); - ($busid_nu,$modules,$port,$rev) = (0,'','',''); - @temp3 = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,$rev, - $port,$driver,$modules,'','','',$handle); - assign_data('soc',\@temp3); - main::log_data('dump','soc devices: @devices @temp3',\@temp3) if $b_log; - } - eval $end if $b_log; -} -sub soc_devicetree { - eval $start if $b_log; - # now we want to fill in stuff that was not in /sys/devices/ - if (-d '/sys/firmware/devicetree/base/soc'){ - @files = main::globber('/sys/firmware/devicetree/base/soc/*/compatible'); - my $test = (@full_names) ? join('|', sort @full_names) : 'xxxxxx'; - set_bluetooth() if !$b_bt_check; - foreach $file (@files){ - if ( $file !~ m%$test%){ - ($handle,$content,$device,$type,$type_id,$vendor_id) = ('','','','','',''); - $content = main::reader($file, 'strip',0) if -r $file; - $file =~ m%soc/([^@]+)@([^/]+)/compatible$%; - $type = $1; - next if !$type || !$content; - $handle = $2 if $2; - $type_id = $type; - if (@bluetooth && $type eq 'serial'){ - my $file_temp = $file; - $file_temp =~ s/uevent$//; - $type = 'bluetooth' if grep {/$file_temp/} @bluetooth; - } - if ($content){ - @temp3 = split(',', $content); - $vendor_id = $temp3[0]; - $device = $temp3[-1]; - # strip off those weird device tree special characters - $device =~ s/\x01|\x02|\x03|\x00//g; - } - $type = soc_type($type,$vendor_id,''); - @temp3 = ($type,$type_id,0,0,$device,$vendor_id,'soc','','','','','','','',$handle); - assign_data('soc',\@temp3); - main::log_data('dump','devicetree: @devices @temp3',\@temp3) if $b_log; - } - } - } - eval $end if $b_log; -} -sub set_bluetooth { - # special case of pi bt on ttyAMA0 - $b_bt_check = 1; - @bluetooth = main::globber('/sys/class/bluetooth/*') if -e '/sys/class/bluetooth'; - @bluetooth = map {$_ = Cwd::abs_path($_);$_} @bluetooth if @bluetooth; - @bluetooth = grep {!/usb/} @bluetooth if @bluetooth; # we only want non usb bt - main::log_data('dump','soc bt: @bluetooth', \@bluetooth) if $b_log; -} -sub assign_data { - my ($tool,$data) = @_; - if (check_graphics($data->[0],$data->[1])){ - push(@devices_graphics,[@$data]); - $use{'soc-gfx'} = 1 if $tool eq 'soc'; - } - # for hdmi, we need gfx/audio both - if (check_audio($data->[0],$data->[1])){ - push(@devices_audio,[@$data]); - $use{'soc-audio'} = 1 if $tool eq 'soc'; - } - if (check_bluetooth($data->[0],$data->[1])){ - push(@devices_bluetooth,[@$data]); - $use{'soc-bluetooth'} = 1 if $tool eq 'soc'; - } - elsif (check_hwraid($data->[0],$data->[1])){ - push(@devices_hwraid,[@$data]); - $use{'soc-hwraid'} = 1 if $tool eq 'soc'; - } - elsif (check_network($data->[0],$data->[1])){ - push(@devices_network,[@$data]); - $use{'soc-network'} = 1 if $tool eq 'soc'; - } - elsif (check_timer($data->[0],$data->[1])){ - push(@devices_timer,[@$data]); - $use{'soc-timer'} = 1 if $tool eq 'soc'; - } - # not used at this point, -M comes before ANG - # $device_vm = check_vm($data[4]) if ( (!$b_ppc && !$b_mips) && !$device_vm ); - push(@devices,[@$data]); -} -# note: for soc, these have been converted in soc_type() -sub check_audio { - if ( ( $_[1] && length($_[1]) == 4 && $_[1] =~ /^04/ ) || - ( $_[0] && $_[0] =~ /^(audio|hdmi|multimedia|sound)$/i )){ - return 1; - } - else {return 0} -} -sub check_bluetooth { - if ( ( $_[1] && length($_[1]) == 4 && $_[1] eq '0d11' ) || - ( $_[0] && $_[0] =~ /^(bluetooth)$/i )){ - return 1; - } - else {return 0} -} -sub check_graphics { - # note: multimedia class 04 is viddeo if 0400. 'tv' is risky I think - if ( ( $_[1] && length($_[1]) == 4 && ($_[1] =~ /^03/ || $_[1] eq '0400' || - $_[1] eq '0d80' ) ) || - ( $_[0] && $_[0] =~ /^(vga|display|hdmi|3d|video|tv|television)$/i)){ - return 1; - } - else {return 0} -} -sub check_hwraid { - return 1 if ( $_[1] && $_[1] eq '0104' ); -} -# NOTE: class 06 subclass 80 -# https://www-s.acm.illinois.edu/sigops/2007/roll_your_own/7.c.1.html -# 0d20: 802.11a 0d21: 802.11b 0d80: other wireless -sub check_network { - if ( ( $_[1] && length($_[1]) == 4 && ($_[1] =~/^02/ || $_[1] =~ /^0d2/ || $_[1] eq '0680' ) ) || - ( $_[0] && $_[0] =~ /^(ethernet|network|wifi|wlan)$/i ) ){ - return 1; - } - else {return 0} -} -sub check_timer { - return 1 if ( $_[0] && $_[0] eq 'timer' ); -} -sub check_vm { - if ( $_[0] && $_[0] =~ /(innotek|vbox|virtualbox|vmware|qemu)/i ) { - return $1 - } - else {return ''} -} - -sub soc_type { - my ($type,$info,$driver) = @_; - # I2S or i2s. I2C is i2 controller |[iI]2[Ss]. note: odroid hdmi item is sound only - # snd_soc_dummy. simple-audio-amplifier driver: speaker_amp - if (($driver && $driver =~ /codec/) || ($info && $info =~ /codec/) || - ($type && $type =~ /codec/) ){ - $type = 'codec'; - } - elsif (($driver && $driver =~ /dummy/i) || ($info && $info =~ /dummy/i)){ - $type = 'dummy'; - } - elsif ($type =~ /^(daudio|.*hifi.*|.*sound[_-]card|.*dac[0-9]?)$/i || - ($info && $info !~ /amp/i && $info =~ /(sound|audio)/i) || - ($driver && $driver =~ /(audio|snd|sound)/i) ){ - $type = 'audio'; - } - # no need for bluetooth since that's only found in pi, handled above - elsif ($type =~ /^((meson-?)?fb|disp|display(-[^\s]+)?|gpu|.*mali|vpu)$/i){ - $type = 'display'; - } - # includes ethernet-phy, meson-eth - elsif ($type =~ /^(([^\s]+-)?eth|ethernet(-[^\s]+)?|lan|l-lan)$/i){ - $type = 'ethernet'; - } - elsif ($type =~ /^(.*wlan.*|.*wifi.*|.*mmcnr.*)$/i){ - $type = 'wifi'; - } - # needs to catch variants like hdmi-tx but not hdmi-connector - elsif ( $type =~ /^(.*hdmi(-?tx)?)$/i){ - $type = 'hdmi'; - } - elsif ($type =~ /^timer$/i){ - $type = 'timer'; - } - return $type; -} -sub pci_class { - eval $start if $b_log; - my ($id) = @_; - $id = lc($id); - my %classes = ( - '00' => 'unclassified', - '01' => 'mass-storage', - '02' => 'network', - '03' => 'display', - '04' => 'audio', - '05' => 'memory', - '06' => 'bridge', - '07' => 'communication', - '08' => 'peripheral', - '09' => 'input', - '0a' => 'docking', - '0b' => 'processor', - '0c' => 'serialbus', - '0d' => 'wireless', - '0e' => 'intelligent', - '0f' => 'satellite', - '10' => 'encryption', - '11' => 'signal-processing', - '12' => 'processing-accelerators', - '13' => 'non-essential-instrumentation', - '40' => 'coprocessor', - 'ff' => 'unassigned', - ); - my $type = (defined $classes{$id}) ? $classes{$id}: 'unhandled'; - eval $end if $b_log; - return $type; -} -} - -sub set_dmesg_boot_data { - eval $start if $b_log; - ${$_[0]} = 1; # set check boolean by reference - my ($file,@temp); - my ($counter) = (0); - if (!$fake{'dboot'}){ - $file = system_files('dmesg-boot'); - } - else { - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/bsd-disks-diabolus.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/freebsd-disks-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/freebsd-enceladus-1.txt"; - ## matches: toshiba: openbsd-5.6-sysctl-2.txt - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-5.6-dmesg.boot-1.txt"; - ## matches: compaq: openbsd-5.6-sysctl-1.txt" - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-dmesg.boot-1.txt"; - } - if ($file){ - return if ! -r $file; - @dmesg_boot = reader($file); - my @dmesg = grabber('dmesg 2>/dev/null'); - # clear out for netbsd, only 1 space following or lines won't match - @dmesg = map {$_ =~ s/^\[[^\]]+\]\s//;$_} @dmesg; - push(@dmesg_boot,'~~~~~',@dmesg); - uniq(\@dmesg_boot); # get rid of duplicate lines - # some dmesg repeats, so we need to dump the second and > iterations - # replace all indented items with ~ so we can id them easily while - # processing note that if user, may get error of read permissions - # for some weird reason, real mem and avail mem are use a '=' separator, - # who knows why, the others are ':' - foreach (@dmesg_boot){ - $counter++ if /^(OpenBSD|DragonFly|FreeBSD is a registered trademark)/; - last if $counter > 1; - $_ =~ s/\s*=\s*|:\s*/:/; - $_ =~ s/\"//g; - $_ =~ s/^\s+/~/; - $_ =~ s/\s\s/ /g; - $_ =~ s/^(\S+)\sat\s/$1:at /; # ada0 at ahcich0 - push(@temp, $_); - if (/^bios[0-9]:(at|vendor)/){ - push(@sysctl_machine, $_); - } - } - @dmesg_boot = @temp; - # FreeBSD: 'da*' is a USB device 'ada*' is a SATA device 'mmcsd*' is an SD card - # OpenBSD: 'sd' is usb device, 'wd' normal drive - if ($use{'dm-boot-disk'} && @dmesg_boot){ - @dm_boot_disk = grep {/^(ad|ada|da|mmcblk|mmcsd|nvme[0-9]+n|sd|wd)[0-9]+(:|\sat\s)/} @dmesg_boot; - log_data('dump','@dm_boot_disk',\@dm_boot_disk) if $b_log; - print Dumper \@dm_boot_disk if $dbg[11]; - } - if ($use{'dm-boot-optical'} && @dmesg_boot){ - @dm_boot_optical = grep {/^(cd)[0-9]+(\([^)]+\))?(:|\sat\s)/} @dmesg_boot; - log_data('dump','@dm_boot_optical',\@dm_boot_optical) if $b_log; - print Dumper \@dm_boot_optical if $dbg[11]; - } - } - log_data('dump','@dmesg_boot full',\@dmesg_boot) if $b_log; - print Dumper \@dmesg_boot if $dbg[11]; - eval $end if $b_log; -} - -# note, all actual tests have already been run in check_tools so if we -# got here, we're good. -sub set_dmicode_data { - eval $start if $b_log; - ${$_[0]} = 1; # set check boolean by reference - if ($fake{'dmidecode'} || $alerts{'dmidecode'}->{'action'} eq 'use' ){ - set_dmidecode_data(); - } - eval $end if $b_log; -} - -sub set_dmidecode_data { - eval $start if $b_log; - my ($content,@data,@working,$type,$handle); - if ($fake{'dmidecode'}){ - my $file; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/pci-freebsd-8.2-2"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-loki-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-t41-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-mint-20180106.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-vmware-ram-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-tyan-4408.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-2.txt"; - #open(my $fh, '<', $file) or die "can't open $file: $!"; - #chomp(@data = <$fh>); - } - else { - $content = qx($alerts{'dmidecode'}->{'path'} 2>/dev/null); - @data = split('\n', $content); - } - # we don't need the opener lines of dmidecode output - # but we do want to preserve the indentation. Empty lines - # won't matter, they will be skipped, so no need to handle them. - # some dmidecodes do not use empty line separators - splice(@data, 0, 5) if @data; - my $j = 0; - my $b_skip = 1; - foreach (@data){ - if (!/^Hand/){ - next if $b_skip; - if (/^[^\s]/){ - $_ = lc($_); - $_ =~ s/\s(information)//; - push(@working, $_); - } - elsif (/^\t/){ - $_ =~ s/^\t\t/~/; - $_ =~ s/^\t|\s+$//g; - push(@working, $_); - } - } - elsif (/^Handle\s(0x[0-9A-Fa-f]+).*DMI\stype\s([0-9]+),.*/){ - $j = scalar @dmi; - $handle = hex($1); - $type = $2; - $use{'slot-tool'} = 1 if $type && $type == 9; - $b_skip = ( $type > 126 )? 1 : 0; - next if $b_skip; - # we don't need 32, system boot, or 127, end of table - if (@working){ - if ($working[0] != 32 && $working[0] < 127){ - $dmi[$j] = ( - [@working], - ); - } - } - @working = ($type,$handle); - } - } - if (@working && $working[0] != 32 && $working[0] != 127){ - $j = scalar @dmi; - $dmi[$j] = \@working; - } - # last by not least, sort it by dmi type, now we don't have to worry - # about random dmi type ordering in the data, which happens. Also sort - # by handle, as secondary sort. - @dmi = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @dmi; - log_data('dump','@dmi',\@dmi) if $b_log; - print Dumper \@dmi if $dbg[2]; - eval $end if $b_log; -} - -# Set IpData -{ -package IpData; -sub set { - eval $start if $b_log; - if ($alerts{'ip'}->{'action'} eq 'use' ){ - set_ip_addr(); - } - elsif ($alerts{'ifconfig'}->{'action'} eq 'use'){ - set_ifconfig(); - } - eval $end if $b_log; -} - -sub set_ip_addr { - eval $start if $b_log; - my @data = main::grabber($alerts{'ip'}->{'path'} . " addr 2>/dev/null",'\n','strip'); - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/if/scope-ipaddr-1.txt"; - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/networking/ip-addr-blue-advance.txt"; - #my @data = reader($file,'strip') or die $!; - my ($b_skip,$broadcast,$if,$ip,@ips,$scope,$if_id,$type,@temp,@temp2); - foreach (@data){ - if (/^[0-9]/){ - #print "$_\n"; - if (@ips){ - #print "$if\n"; - @temp = ($if,[@ips]); - push(@ifs,@temp); - @ips = (); - } - @temp = split(/:\s+/, $_); - $if = $temp[1]; - if ($if eq 'lo'){ - $b_skip = 1; - $if = ''; - next; - } - $b_skip = 0; - @temp = (); - } - elsif (!$b_skip && /^inet/){ - #print "$_\n"; - @temp = split(/\s+/, $_); - ($broadcast,$ip,$scope,$if_id,$type) = ('','','','',''); - $ip = $temp[1]; - $type = ($temp[0] eq 'inet') ? 4 : 6 ; - if ($temp[2] eq 'brd'){ - $broadcast = $temp[3]; - } - if (/scope\s([^\s]+)(\s(.+))?/){ - $scope = $1; - $if_id = $3; - } - @temp = ($type,$ip,$broadcast,$scope,$if_id); - push(@ips,[@temp]); - #print Data::Dumper::Dumper \@ips; - } - } - #print Data::Dumper::Dumper \@ips if $dbg[4]; - if (@ips){ - @temp = ($if,[@ips]); - push(@ifs,@temp); - } - main::log_data('dump','@ifs',\@ifs) if $b_log; - print Data::Dumper::Dumper \@ifs if $dbg[3]; - eval $end if $b_log; -} - -sub set_ifconfig { - eval $start if $b_log; - my @data = main::grabber($alerts{'ifconfig'}->{'path'} . " 2>/dev/null",'\n',''); - #my @data = reader("$ENV{'HOME'}/bin/scripts/inxi/data/if/vps-ifconfig-1.txt",'') or die $!; - my ($b_skip,$broadcast,$if,@ips_bsd,$ip,@ips,$scope,$if_id,$type,@temp,@temp2); - my ($state,$speed,$duplex,$mac); - foreach (@data){ - if (/^[\S]/i){ - #print "$_\n"; - if (@ips){ - #print "here\n"; - @temp = ($if,[@ips]); - push(@ifs,@temp); - @ips = (); - } - if ($mac){ - @temp = ($if,[($state,$speed,$duplex,$mac)]); - push(@ifs_bsd,@temp); - ($state,$speed,$duplex,$mac,$if_id) = ('','','','',''); - } - $if = (split(/\s+/, $_))[0]; - $if =~ s/:$//; # em0: flags=8843 - $if_id = $if; - $if = (split(':', $if))[0] if $if; - if ($if =~ /^lo/){ - $b_skip = 1; - $if = ''; - $if_id = ''; - next; - } - $b_skip = 0; - } - elsif (!$b_skip && $bsd_type && /^\s+(address|ether|media|status|lladdr)/){ - $_ =~ s/^\s+//; - # freebsd 7.3: media: Ethernet 100baseTX - # Freebsd 8.2/12.2: media: Ethernet autoselect (1000baseT ) - # Netbsd 9.1: media: Ethernet autoselect (1000baseT full-duplex) - # openbsd: media: Ethernet autoselect (1000baseT full-duplex) - if (/^media/){ - if ($_ =~ /[\s\(]([1-9][^\(\s]+)?\s<([^>]+)>/){ - $speed = $1 if $1; - $duplex = $2; - } - if (!$duplex && $_ =~ /\s\(([\S]+)\s([^\s<]+)\)/){ - $speed = $1; - $duplex = $2; - } - if (!$speed && $_ =~ /\s\(([1-9][\S]+)\s/){ - $speed = $1; - } - } - # lladdr openbsd/address netbsd/ether freebsd - elsif (!$mac && /^(address|ether|lladdr)/){ - $mac = (split(/\s+/, $_))[1]; - } - elsif (/^status/){ - $state = (split(/\s+/, $_))[1]; - } - } - elsif (!$b_skip && /^\s+inet/){ - #print "$_\n"; - $_ =~ s/^\s+//; - $_ =~ s/addr:\s/addr:/; - @temp = split(/\s+/, $_); - ($broadcast,$ip,$scope,$type) = ('','','',''); - $ip = $temp[1]; - # fe80::225:90ff:fe13:77ce%em0 -# $ip =~ s/^addr:|%([\S]+)//; - if ($1 && $1 ne $if_id){ - $if_id = $1; - } - $type = ($temp[0] eq 'inet') ? 4 : 6 ; - if (/(Bcast:|broadcast\s)([\S]+)/){ - $broadcast = $2; - } - if (/(scopeid\s[^<]+<|Scope:|scopeid\s)([^>]+)[>]?/){ - $scope = $2; - } - $scope = 'link' if $ip =~ /^fe80/; - @temp = ($type,$ip,$broadcast,$scope,$if_id); - push(@ips,[@temp]); - #print Data::Dumper::Dumper \@ips; - } - } - if (@ips){ - @temp = ($if,[@ips]); - push(@ifs,@temp); - } - if ($mac){ - @temp = ($if,[($state,$speed,$duplex,$mac)]); - push(@ifs_bsd,@temp); - ($state,$speed,$duplex,$mac) = ('','','',''); - } - print Data::Dumper::Dumper \@ifs if $dbg[3]; - print Data::Dumper::Dumper \@ifs_bsd if $dbg[3]; - main::log_data('dump','@ifs',\@ifs) if $b_log; - main::log_data('dump','@ifs_bsd',\@ifs_bsd) if $b_log; - eval $end if $b_log; -} -} - -sub set_lsblk { - eval $start if $b_log; - $loaded{'lsblk'} = 1; - if ($alerts{'lsblk'} && $alerts{'lsblk'}->{'path'}){ - my $cmd = $alerts{'lsblk'}->{'path'} . ' -bP --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,'; - $cmd .= 'SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS,MAJ:MIN,PKNAME 2>/dev/null'; - my $pattern = 'NAME="([^"]*)"\s+TYPE="([^"]*)"\s+RM="([^"]*)"\s+'; - $pattern .= 'FSTYPE="([^"]*)"\s+SIZE="([^"]*)"\s+LABEL="([^"]*)"\s+'; - $pattern .= 'UUID="([^"]*)"\s+SERIAL="([^"]*)"\s+MOUNTPOINT="([^"]*)"\s+'; - $pattern .= 'PHY-SEC="([^"]*)"\s+LOG-SEC="([^"]*)"\s+PARTFLAGS="([^"]*)"\s+'; - $pattern .= 'MAJ:MIN="([^"]*)"\s+PKNAME="([^"]*)"'; - my @working = main::grabber($cmd); - foreach (@working){ - if (/$pattern/){ - my $size = ($5) ? $5/1024: 0; - # some versions of lsblk do not return serial, fs, uuid, or label - push(@lsblk, { - 'name' => $1, - 'type' => $2, - 'rm' => $3, - 'fs' => $4, - 'size' => $size, - 'label' => $6, - 'uuid' => $7, - 'serial' => $8, - 'mount' => $9, - 'block-physical' => $10, - 'block-logical' => $11, - 'partition-flags' => $12, - 'maj-min' => $13, - 'parent' => $14, - }); - # must be below assignments!! otherwise the result of the match replaces values - # note: for bcache and luks, the device that has that fs is the parent!! - if ($show{'logical'}){ - $use{'logical-lvm'} = 1 if !$use{'logical-lvm'} && $2 && $2 eq 'lvm'; - if (!$use{'logical-general'} && (($4 && ($4 eq 'crypto_LUKS' || $4 eq 'bcache')) - || ($2 && ($2 eq 'dm' && $1 =~ /veracrypt/i) || - $2 eq 'crypto' || $2 eq 'mpath' || $2 eq 'multipath'))){ - $use{'logical-general'} = 1; - } - } - } - } - } - print Data::Dumper::Dumper \@lsblk if $dbg[32]; - main::log_data('dump','@lsblk',\@lsblk) if $b_log; - eval $end if $b_log; -} - -sub set_mapper { - eval $start if $b_log; - $loaded{'mapper'} = 1; - return if ! -d '/dev/mapper'; - foreach ((globber('/dev/mapper/*'))){ - my ($key,$value) = ($_,Cwd::abs_path("$_")); - next if !$value; - $key =~ s|^/.*/||; - $value =~ s|^/.*/||; - $mapper{$key} = $value; - } - %dmmapper = reverse %mapper if %mapper; - eval $end if $b_log; -} - -sub set_proc_partitions { - eval $start if $b_log; - $loaded{'proc-partitions'} = 1; - if (my $file = main::system_files('partitions')){ - my @parts = main::reader($file,'strip'); - #print Dumper \@parts; - shift @parts if @parts; # get rid of headers - for (@parts){ - my @temp = split(/\s+/, $_); - next if !defined $temp[2]; - push (@proc_partitions,[$temp[0],$temp[1],$temp[2],$temp[3]]); - } - } - eval $end if $b_log; -} - -sub set_ps_aux { - eval $start if $b_log; - my ($header,@ps,@temp); - # note: some ps cut off output based on terminal width - # ww sets width unlimited - $loaded{'ps-aux'} = 1; - @ps = grabber("ps wwaux 2>/dev/null",'','strip'); - if (@ps){ - $header = shift @ps; # get rid of header row - # handle busy box, which has 3 columns, regular ps aux has 11 - # avoid deprecated implicit split error in older Perls - @temp = split(/\s+/, $header); - } - $ps_cols = $#temp; # the indexes, not the scalar count - if ($ps_cols < 10){ - my $version = qx(ps --version 2>&1); - $b_busybox_ps = 1 if $version =~ /busybox/i; - } - return if !@ps; # note: mips/openwrt ps has no 'a' - for (@ps){ - next if !$_; - next if $self_name eq 'inxi' && /\/$self_name\b/; - $_ = lc; - push (@ps_aux,$_); - my @split = split(/\s+/, $_); - # slice out 10th to last elements of ps aux rows - my $final = $#split; - # some stuff has a lot of data, chrome for example - $final = ($final > ($ps_cols + 2) ) ? $ps_cols + 2 : $final; - if ($split[$ps_cols] !~ /^\[/){ - push(@ps_cmd,join(' ', @split[$ps_cols .. $final])); - } - } - # never, because ps loaded before option handler - # print Dumper \@ps_cmd; # if $dbg[5]; - eval $end if $b_log; -} -sub set_ps_gui { - eval $start if $b_log; - $loaded{'ps-gui'} = 1; - my ($working,@match,@temp); - # desktops / wm (some wm also compositors) - if ($show{'system'}){ - @temp=qw(razor-desktop razor-session lxsession lxqt-session - tdelauncher tdeinit_phase1); - push(@match,@temp); - @temp=qw(3dwm 9wm afterstep aewm aewm\+\+ amiwm antiwm awesome - blackbox bspwm - cagebreak calmwm (sh|c?lisp).*clfswm ctwm (openbsd-)?cwm dwm evilwm - fluxbox flwm flwm_topside fvwm.*-crystal fvwm1 fvwm2 fvwm3 fvwm95 fvwm - herbstluftwm i3 icewm instantwm ion3 jbwm jwm larswm lwm - matchbox-window-manager mini musca mwm nawm notion - openbox orbital pekwm perceptia python.*qtile qtile qvwm ratpoison - sawfish scrotwm spectrwm (sh|c?lisp).*stumpwm sway - tinywm tvtwm twm - waycooler way-cooler windowlab WindowMaker wm2 wmii2 wmii wmx - xfdesktop xmonad yeahwm); - push(@match,@temp); - } - # wm: - if ($show{'system'} && $extra > 1){ - @temp=qw(budgie-wm compiz deepin-wm gala gnome-shell - twin kwin_wayland kwin_x11 kwin marco - deepin-metacity metacity metisse mir muffin deepin-mutter mutter - ukwm xfwm4 xfwm5); - push(@match,@temp); - # startx: /bin/sh /usr/bin/startx - @temp=qw(ly .*startx xinit); # possible dm values - push(@match,@temp); - } - # info: NOTE: glx-dock is cairo-dock - if ($show{'system'} && $extra > 2){ - @temp=qw(alltray awn bar bmpanel bmpanel2 budgie-panel - cairo-dock dde-dock dmenu dockbarx docker docky dzen dzen2 - fbpanel fspanel glx-dock gnome-panel hpanel i3bar icewmtray - kdocker kicker latte latte-dock lemonbar ltpanel lxpanel lxqt-panel - matchbox-panel mate-panel ourico - perlpanel plank plasma-desktop plasma-netbook polybar pypanel - razor-panel razorqt-panel stalonetray swaybar taskbar tint2 trayer - ukui-panel vala-panel wbar wharf wingpanel witray - xfce4-panel xfce5-panel xmobar yabar); - push(@match,@temp); - } - # compositors (for wayland these are also the server, note. - # for wayland always show, so always load these - if ($show{'graphic'} && $extra > 0){ - @temp=qw(3dwm asc budgie-wm compiz compton deepin-wm dwc dcompmgr - enlightenment fireplace gnome-shell grefson kmscon kwin_wayland kwin_x11 - liri marco metisse mir moblin motorcar muffin mutter - orbital papyros perceptia picom rustland sommelier sway swc - ukwm unagi unity-system-compositor - wavy waycooler way-cooler wayfire wayhouse westford weston xcompmgr); - push(@match,@temp); - } - uniq(\@match); - my $matches = join('|', @match); - foreach (@ps_cmd){ - if (/^(|[\S]*\/)($matches)(\/|\s|$)/){ - $working = $2; - push(@ps_gui, $working); # deal with duplicates with uniq - } - } - uniq(\@ps_gui) if @ps_gui; - print Dumper \@ps_gui if $dbg[5]; - log_data('dump','@ps_gui',\@ps_gui) if $b_log; - eval $end if $b_log; -} - -sub set_sysctl_data { - eval $start if $b_log; - return if !$alerts{'sysctl'} || $alerts{'sysctl'}->{'action'} ne 'use'; - my (@temp); - # darwin sysctl has BOTH = and : separators, and repeats data. Why? - if (!$fake{'sysctl'}){ - @temp = grabber($alerts{'sysctl'}->{'path'} . " -a 2>/dev/null"); - } - else { - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1_sysctl_soekris6501_root.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1sysctl_lenovot500_user.txt"; - ## matches: compaq: openbsd-dmesg.boot-1.txt - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-1.txt"; - ## matches: toshiba: openbsd-5.6-dmesg.boot-1.txt - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-2.txt"; - # @temp = reader($file); - } - foreach (@temp){ - $_ =~ s/\s*=\s*|:\s+/:/; - $_ =~ s/\"//g; - push(@sysctl, $_); - # we're building these here so we can use these arrays to test - # in each feature if we will try to build the feature for bsds - if (/^hw\.sensors/ && !/^hw\.sensors\.acpi(bat|cmb)/ && !/^hw.sensors.softraid/){ - push(@sysctl_sensors, $_); - } - elsif (/^(hw\.|machdep\.dmi\.(bios|board|system)-)(date|product|serial(no)?|uuid|vendor|version)/){ - push(@sysctl_machine, $_); - } - elsif (/^hw\.snd\./){ - push(@sysctl_audio, $_); - } - elsif (/^hw\.sensors\.acpi(bat|cmb)/){ - push(@sysctl_battery, $_); - } - } - print Dumper \@sysctl if $dbg[7]; - # this thing can get really long. - if ($b_log){ - #main::log_data('dump','@sysctl',\@sysctl); - } - eval $end if $b_log; -} - -## @usb array indexes +## UsbData +# %usb array indexes # 0 - bus id / sort id # 1 - device id # 2 - path_id @@ -23776,14 +25312,15 @@ sub set_sysctl_data { # 18 - configuration - not used # 19 - power mW bsd only, not used yet # 20 - product rev number -## Set USBData +# 21 - driver_nu [bsd only] { -package USBData; +package UsbData; my (@working); my (@asound_ids,$b_asound,$b_hub,$addr_id,$bus_id,$bus_id_alpha, -$chip_id,$class_id,$device_id,$driver,$ids,$interfaces, -$name,$network_regex,$path,$path_id,$power,$product,$protocol_id,$rev, -$serial,$speed,$subclass_id,$type,$version,$vendor,$vendor_id); +$chip_id,$class_id,$device_id,$driver,$driver_nu,$ids,$interfaces, +$name,$network_regex,$path,$path_id,$power,$product,$product_id, +$protocol_id,$rev,$serial,$speed,$subclass_id,$type,$version,$vendor, +$vendor_id); my $b_live = 1; # debugger file data sub set { eval $start if $b_log; @@ -23804,20 +25341,20 @@ sub set { elsif (-d '/sys/bus/usb/devices'){ sys_data('main'); } - @usb = sort {$a->[0] cmp $b->[0]} @usb if @usb; - main::log_data('dump','@usb_audio: ',\@usb_audio) if $b_log; - main::log_data('dump','@usb_bluetooth: ',\@usb_bluetooth) if $b_log; - main::log_data('dump','@usb_graphics: ',\@usb_graphics) if $b_log; - main::log_data('dump','@usb_network: ',\@usb_network) if $b_log; + @{$usb{'main'}} = sort {$a->[0] cmp $b->[0]} @{$usb{'main'}} if $usb{'main'}; + main::log_data('dump','$usb{audio}: ',$usb{'audio'}) if $b_log; + main::log_data('dump','$usb{bluetooth}: ',$usb{'bluetooth'}) if $b_log; + main::log_data('dump','$usb{graphics}: ',$usb{'graphics'}) if $b_log; + main::log_data('dump','$usb{network}: ',$usb{'network'}) if $b_log; eval $end if $b_log; } sub lsusb_data { eval $start if $b_log; my (@temp); - my @data = data_grabber('lsusb'); + my @data = usb_grabber('lsusb'); foreach (@data){ - next if /^\s*$|^Couldn't/; # expensive second call: || /UNAVAIL/ + next if /^~$|^Couldn't/; # expensive second call: || /UNAVAIL/ @working = split(/\s+/, $_); next unless defined $working[1] && defined $working[3]; $working[3] =~ s/:$//; @@ -23826,10 +25363,10 @@ sub lsusb_data { # hub, note incomplete data: Bus /dev/usb Device /dev/ugen0.1: ID 0000:0000 # linux: # Bus 005 Device 007: ID 0d8c:000c C-Media Electronics, Inc. Audio Adapter - #if ($working[3] =~ m|^/dev/ugen([0-9]+)\.([0-9]+)|){ + # if ($working[3] =~ m|^/dev/ugen([0-9]+)\.([0-9]+)|){ # $working[1] = $1; # $working[3] = $2; - #} + # } next unless main::is_numeric($working[1]) && main::is_numeric($working[3]); $addr_id = int($working[3]); $bus_id = int($working[1]); @@ -23841,7 +25378,7 @@ sub lsusb_data { # $type = check_type($name,'',''); $type ||= ''; # do NOT set bus_id_alpha here!! - #print "$name\n"; + # print "$name\n"; $working[0] = $bus_id; $working[1] = $addr_id; $working[2] = $path_id; @@ -23863,84 +25400,118 @@ sub lsusb_data { $working[18] = ''; $working[19] = ''; $working[20] = ''; - push(@usb,[@working]); - #print join("\n",@working),"\n\n=====\n"; + push(@{$usb{'main'}},[@working]); + # print join("\n",@working),"\n\n=====\n"; } - print Data::Dumper::Dumper \@usb if $dbg[6]; - sys_data('lsusb') if @usb; - print Data::Dumper::Dumper \@usb if $dbg[6]; - main::log_data('dump','@usb: plain',\@usb) if $b_log; + print Data::Dumper::Dumper $usb{'main'} if $dbg[6]; + sys_data('lsusb') if $usb{'main'}; + print Data::Dumper::Dumper $usb{'main'} if $dbg[6]; + main::log_data('dump','$usb{main}: plain',$usb{'main'}) if $b_log; eval $end if $b_log; } -#ugen0.1: at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA) -#ugen0.2: at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (160mA) +# ugen0.1: at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=SAVE (0mA) +# ugen0.2: at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (160mA) +# note: tried getting driver/ports from dmesg, impossible, waste of time sub usbconfig_data { eval $start if $b_log; - my ($b_multi,$class,$config,$hub_id); - my ($ports,$j,$k) = (0,0,0); - my @data = data_grabber('usbconfig'); - push (@data,'END') if @data; + my ($cfg,$hub_id,$ports); + my @data = usb_grabber('usbconfig'); foreach (@data){ - # note that bsd spd=FULL has interest since we get that from the speed - if (/^([a-z_-]+)([0-9]+)\.([0-9]+):\s+<([^>]+)>\s+at usbus([0-9]+),\s+cfg=([0-9]+)\s+md=([^\s]+)\s+spd=([^\s]+)\s+\(([^\)]+)\)\s+pwr=([^\s]+)\s+\(([0-9]+mA)\)/){ + if ($_ eq '~' && @working){ + $chip_id = ($vendor_id || $product_id) ? "$vendor_id:$product_id" : ''; + $working[7] = $chip_id; + $product ||= ''; + $vendor ||= ''; + $working[13] = main::remove_duplicates("$vendor $product") if $product || $vendor; + # leave the ugly vendor/product ids unless chip-ID shows! + $working[13] = $chip_id if $extra < 2 && $chip_id && !$working[13]; + if (defined $class_id && defined $subclass_id && defined $protocol_id){ + $class_id = hex($class_id); + $subclass_id = hex($subclass_id); + $protocol_id = hex($protocol_id); + $type = device_type("$class_id/$subclass_id/$protocol_id"); + } + if ($working[13] && (!$type || $type eq '')){ + $type = check_type($working[13],'',''); + } + $working[14] = $type; + push(@{$usb{'main'}},[@working]); + assign_usb_type([@working]); + undef @working; + } + elsif (/^([a-z_-]+)([0-9]+)\.([0-9]+):\s+<[^>]+>\s+at usbus([0-9]+)\b/){ + ($class_id,$cfg,$power,$speed,$subclass_id,$type) = undef; + ($product,$product_id,$vendor,$vendor_id) = ('','','',''); $hub_id = $2; $addr_id = $3; - $bus_id = $5; - $driver = $1; - $name = main::remove_duplicates($4); - $type = check_type($name,'',''); - $config = $6; - $speed = prep_speed($9); - $power = $11; - ($product,$vendor) = ('',''); - # leave the ugly vendor/product ids unless chip-ID shows! - if ($extra > 1){ - if ($name =~ /vendor (0x)?[0-9a-f]{4}/){ - $name =~ s/vendor (0x)?([0-9a-f]{4})\s?//; - $vendor = ($2) ? $2 : ''; - } - if ($name =~ /product (0x)?[0-9a-f]{4}/){ - $name =~ s/product (0x)?([0-9a-f]{4})\s?//; - $product = ($2) ? $2 : ''; - } - } - $chip_id = ($vendor || $product) ? "$vendor:$product" : ''; - $class = ($type && $type eq 'Hub') ? '09': '01'; - process_power(\$power) if $power; - $j = scalar @usb; + $bus_id = $4; $path_id = "$bus_id-$hub_id.$addr_id"; $bus_id_alpha = bus_id_alpha($path_id); + if (/\bcfg\s*=\s*([0-9]+)/){ + $cfg = $1; + } + if (/\bmd\s*=\s*([\S]+)/){ + # nothing + } + # odd, using \b after ) doesn't work as expected + # note that bsd spd=FULL has no interest since we get that from the speed + if (/\b(speed|spd)\s*=\s*([\S]+)\s+\(([^\)]+)\)/){ + $speed = prep_speed($3); + } + if (/\b(power|pwr)\s*=\s*([\S]+)\s+\(([0-9]+mA)\)/){ + $power = $3; + process_power(\$power) if $power; + } $working[0] = $bus_id_alpha; $working[1] = $addr_id; $working[2] = $path_id; $working[3] = ''; - $working[4] = $class; - $working[5] = ''; - $working[6] = ''; - $working[7] = $chip_id; $working[8] = usb_rev($speed); $working[9] = ''; - $working[10] = 0; - $working[11] = ''; - $working[12] = ''; - $working[13] = $name; - $working[14] = $type; + $working[10] = $ports; $working[15] = $driver; - $working[16] = ''; $working[17] = $speed; - $working[18] = $config; + $working[18] = $cfg; $working[19] = $power; $working[20] = ''; - $usb[$j] = ([@working],); - assign_usb_type($usb[$j]); - @working = (); + $working[21] = $driver_nu; + } + elsif (/^bDeviceClass\s*=\s*0x00([a-f0-9]{2})\s*(<([^>]+)>)?/){ + $class_id = $1; + $working[4] = $class_id; + } + elsif (/^bDeviceSubClass\s*=\s*0x00([a-f0-9]{2})/){ + $subclass_id = $1; + $working[5] = $subclass_id; + } + elsif (/^bDeviceProtocol\s*=\s*0x00([a-f0-9]{2})/){ + $protocol_id = $1; + $working[6] = $protocol_id; + } + elsif (/^idVendor\s*=\s*0x([a-f0-9]{4})/){ + $vendor_id = $1; + } + elsif (/^idProduct\s*=\s*0x([a-f0-9]{4})/){ + $product_id = $1; + } + elsif (/^iManufacturer\s*=\s*0x([a-f0-9]{4})\s*(<([^>]+)>)?/){ + $vendor = main::cleaner($3); + $vendor =~ s/^0x.*//; # seen case where vendor string was ID + $working[11] = $vendor; + } + elsif (/^iProduct\s*=\s*0x([a-f0-9]{4})\s*(<([^>]+)>)?/){ + $product = main::cleaner($3); + $product =~ s/^0x.*//; # in case they put product ID in, sigh + $working[12] = $product; + } + elsif (/^iSerialNumber\s*=\s*0x([a-f0-9]{4})\s*(<([^>]+)>)?/){ + $working[16] = main::cleaner($3); } } - main::log_data('dump','@usb: usbconfig',\@usb) if $b_log; - print Data::Dumper::Dumper \@usb if $dbg[6]; + main::log_data('dump','$usb{main}: usbconfig',$usb{'main'}) if $b_log; + print Data::Dumper::Dumper $usb{'main'} if $dbg[6]; eval $end if $b_log; } - # Controller /dev/usb2: # addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Intel(0x8086), rev 1.00 # port 1 addr 2: full speed, power 98 mA, config 1, USB Receiver(0xc52b), Logitech(0x046d), rev 12.01 @@ -23948,24 +25519,20 @@ sub usbconfig_data { sub usbdevs_data { eval $start if $b_log; my ($b_multi,$class,$config,$hub_id,$port,$port_value,$product_rev); - my ($ports,$j,$k) = (0,0,0); - my @data = data_grabber('usbdevs'); - push (@data,'END') if @data; + my ($ports) = (0); + my @data = usb_grabber('usbdevs'); foreach (@data){ - if (/^Controller\s\/dev\/usb([0-9]+)/){ + if ($_ eq '~' && @working){ + $working[10] = $ports; + push(@{$usb{'main'}},[@working]); + assign_usb_type([@working]); + undef @working; + ($config,$driver,$power,$rev) = ('','','',''); + } + elsif (/^Controller\s\/dev\/usb([0-9]+)/){ $bus_id = $1; - if (@working){ - $j = scalar @usb; - $usb[$j] = ([@working],); - assign_usb_type($usb[$j]); - } - ($j,$ports) = (0,0); - ($driver,$port_value) = ('',''); - @working = (); } elsif (/^addr\s([0-9]+):\s([^,]+),[^,0-9]+([0-9]+ mA)?,\s+config\s+([0-9]+),\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ - $j = scalar @usb; - $k = $j; $hub_id = $1; $addr_id = $1; $speed = prep_speed($2); @@ -23973,9 +25540,10 @@ sub usbdevs_data { $chip_id = "$6:$8"; $config = $4; $name = main::remove_duplicates("$7 $5"); - #print "p1:$protocol\n"; + # print "p1:$protocol\n"; $path_id = "$bus_id-$hub_id"; $bus_id_alpha = bus_id_alpha($path_id); + $ports = 0; process_power(\$power) if $power; $port_value = ''; $working[0] = $bus_id_alpha; @@ -23988,7 +25556,7 @@ sub usbdevs_data { $working[7] = $chip_id; $working[8] = usb_rev($speed); $working[9] = ''; - $working[10] = 0; + $working[10] = $ports; $working[13] = $name; $working[14] = 'Hub'; $working[15] = ''; @@ -23997,11 +25565,8 @@ sub usbdevs_data { $working[18] = $config; $working[19] = $power; $working[20] = ''; - $usb[$j] = ([@working],); - @working = (); } - elsif (/^\s+port\s([0-9]+)\saddr\s([0-9]+):\s([^,]+),[^,0-9]*([0-9]+\s?mA)?,\s+config\s+([0-9]+),\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ - $j = scalar @usb; + elsif (/^port\s([0-9]+)\saddr\s([0-9]+):\s([^,]+),[^,0-9]*([0-9]+\s?mA)?,\s+config\s+([0-9]+),\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ $port = $1; $addr_id = "$2"; $power = $4; @@ -24011,7 +25576,7 @@ sub usbdevs_data { $name = main::remove_duplicates("$8 $6"); $type = check_type($name,'',''); $type ||= ''; - #print "p2:$protocol\n"; + # print "p2:$protocol\n"; $ports++; $path_id = "$bus_id-$hub_id.$port"; $bus_id_alpha = bus_id_alpha($path_id); @@ -24026,7 +25591,7 @@ sub usbdevs_data { $working[7] = $chip_id; $working[8] = usb_rev($speed); $working[9] = ''; - $working[10] = 0; + $working[10] = $ports; $working[11] = ''; $working[12] = ''; $working[13] = $name; @@ -24037,33 +25602,22 @@ sub usbdevs_data { $working[18] = $config; $working[19] = $power; $working[20] = ''; - $usb[$j] = ([@working],); - assign_usb_type($usb[$j]); - $usb[$k]->[10] = $ports; - @working = (); } - elsif (/^\s+port\s([0-9]+)\spowered/){ + elsif (/^port\s([0-9]+)\spowered/){ $ports++; - $usb[$k]->[10] = $ports; } - # newer openbsd usbdevs totally changed their syntax and layout, sigh... - elsif (/^addr\s*([0-9a-f]+):\s+([a-f0-9]{4}:[a-f0-9]{4})\s*([^,]+)?,\s+([^,]+)$/){ - if (@working){ - $usb[$j] = ([@working],); - assign_usb_type($usb[$j]); - @working = (); - ($config,$driver,$power,$rev) = ('','','',''); - } - $j = scalar @usb; + # newer openbsd usbdevs totally changed their syntax and layout, but it is better... + elsif (/^addr\s*([0-9a-f]+):\s+([a-f0-9]{4}:[a-f0-9]{4})\s*([^,]+)?(,\s[^,]+?)?,\s+([^,]+)$/){ $addr_id = $1; $chip_id = $2; - $vendor = $3 if $3; + $vendor = main::cleaner($3) if $3; $vendor ||= ''; - $name = main::remove_duplicates("$vendor $4"); + $name = main::remove_duplicates("$vendor $5"); $type = check_type($name,'',''); - $class_id = ($name =~ /hub/) ? '09': '01'; + $class_id = ($name =~ /hub/i) ? '09': '01'; $path_id = "$bus_id-$addr_id"; $bus_id_alpha = bus_id_alpha($path_id); + $ports = 0; $b_multi = 1; $working[0] = $bus_id_alpha; $working[1] = $addr_id; @@ -24075,7 +25629,7 @@ sub usbdevs_data { $working[7] = $chip_id; $working[8] = ''; $working[9] = ''; - $working[10] = 0; + $working[10] = $ports; $working[11] = ''; $working[12] = ''; $working[13] = $name; @@ -24087,43 +25641,63 @@ sub usbdevs_data { $working[19] = ''; $working[20] = ''; } - elsif ($b_multi && /^\s+([^,]+),\s+power\s+([0-9]+\s+mA),\s+config\s([0-9]+),\s+rev\s+([0-9\.]+)/){ + elsif ($b_multi && + /^([^,]+),\s+(self powered|power\s+([0-9]+\s+mA)),\s+config\s([0-9]+),\s+rev\s+([0-9\.]+)(,\s+i?Serial\s(\S*))?/i){ $speed = prep_speed($1); $rev = usb_rev($speed); - $power = $2; + $power = $3; process_power(\$power) if $power; $working[8] = $rev; + $working[16] = $7 if $7; $working[17] = $speed; - $working[18] = $3; # config number + $working[18] = $4; # config number $working[19] = $power; - $working[20] = $4; # product rev + $working[20] = $5; # product rev } # 1 or more drivers supported - elsif ($b_multi && /^\s+driver:\s*([^,]+)$/){ + elsif ($b_multi && /^driver:\s*([^,]+)$/){ my $temp = $1; - $temp =~ s/[0-9]+$//; $working[4] = '09' if $temp =~ /hub[0-9]/; + $temp =~ s/([0-9]+)$//; + $working[21] = $1; # driver nu # drivers, note that when numbers trimmed off, drivers can have same name $working[15] = ($working[15] && $working[15] !~ /\b$temp\b/) ? "$working[15],$temp" : $temp; + # now that we have the driver, let's recheck the type + if (!$type && $name && $working[15]){ + $type = check_type($name,$working[15],''); + $working[14] = $type if $type; + } } - elsif ($_ eq 'END' && @working){ - $j = scalar @usb; - $usb[$j] = ([@working],); - assign_usb_type($usb[$j]); + elsif ($b_multi && /^port\s[0-9]/){ + $ports++; } } - main::log_data('dump','@usb: usbdevs',\@usb) if $b_log; - print Data::Dumper::Dumper \@usb if $dbg[6]; + main::log_data('dump','$usb{main}: usbdevs',$usb{'main'}) if $b_log; + print Data::Dumper::Dumper $usb{'main'} if $dbg[6]; eval $end if $b_log; } -sub data_grabber { +sub usb_grabber { eval $start if $b_log; my ($program) = @_; - my %args = ('lsusb' => '', 'usbconfig' => '', 'usbdevs' => '-v'); - my (@data); + my ($args,$path,$pattern,@data,@working); + if ($program eq 'lsusb'){ + $args = ''; + $path = $alerts{'lsusb'}->{'path'}; + $pattern = '^Bus [0-9]'; + } + elsif ($program eq 'usbconfig'){ + $args = 'dump_device_desc'; + $path = $alerts{'usbconfig'}->{'path'}; + $pattern = '^[a-z_-]+[0-9]+\.[0-9]+:'; + } + elsif ($program eq 'usbdevs'){ + $args = '-vv'; + $path = $alerts{'usbdevs'}->{'path'}; + $pattern = '^(addr\s[0-9a-f]+:|port\s[0-9]+\saddr\s[0-9]+:)'; + } if ($b_live && !$fake{'usbdevs'} && !$fake{'usbconfig'}){ - @data = main::grabber($alerts{$program}->{'path'} . " $args{$program} 2>/dev/null"); + @data = main::grabber("$path $args 2>/dev/null",'','strip'); } else { my $file; @@ -24136,11 +25710,20 @@ sub data_grabber { else { $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lsusb/mdmarmer-lsusb.txt"; } - @data = main::reader($file); + @data = main::reader($file,'strip'); } - #print Data::Dumper::Dumper \@data; + if (@data){ + $use{'usb-tool'} = 1 if scalar @data > 2; + foreach (@data){ + # this is the group separator and assign trigger + push(@working, '~') if $_ =~ /$pattern/i; + push(@working, $_); + } + push(@working, '~'); + } + print Data::Dumper::Dumper \@working if $dbg[30]; eval $end if $b_log; - return @data; + return @working; } sub sys_data { @@ -24152,17 +25735,17 @@ sub sys_data { my @files = main::globber('/sys/bus/usb/devices/*'); # we want to get rid of the hubs with x-0: syntax, those are hubs found in /usbx @files = grep {!/\/[0-9]+-0:/} @files; - #print join("\n", @files); + # print join("\n", @files); foreach (@files){ - @uevent = main::reader("$_/uevent") if -r "$_/uevent"; - $ids = main::awk(\@uevent,'^(DEVNAME|DEVICE\b)',2,'='); - if ($ids){ + # be careful, sometimes uevent is not readable + @uevent = (-r "$_/uevent") ? main::reader("$_/uevent") : undef; + if (@uevent && ($ids = main::awk(\@uevent,'^(DEVNAME|DEVICE\b)',2,'='))){ @drivers = (); ($b_hub,$class_id,$protocol_id,$subclass_id) = (0,0,0,0); ($configuration,$driver,$interfaces,$name,$ports,$product,$serial,$speed, $type,$usb_version,$vendor) = ('','','','','','','','','','',''); - #print Cwd::abs_path($_),"\n"; - #print "f1: $_\n"; + # print Cwd::abs_path($_),"\n"; + # print "f1: $_\n"; $path_id = $_; $path_id =~ s/^.*\///; $path_id =~ s/^usb([0-9]+)/$1-0/; @@ -24197,33 +25780,33 @@ sub sys_data { $class_id = sprintf("%02x", $class_id) if defined $class_id && $class_id ne ''; $subclass_id = sprintf("%02x", $subclass_id) if defined $subclass_id && $subclass_id ne ''; if ($source eq 'lsusb'){ - for ($i = 0; $i < scalar @usb; $i++){ - if ($usb[$i]->[0] eq $bus_id && $usb[$i]->[1] == $device_id){ - if (!$b_hub && $usb[$i]->[13] && (!$type || $type eq '' )){ - $type = check_type($usb[$i]->[13],$driver,$type); + for ($i = 0; $i < scalar @{$usb{'main'}}; $i++){ + if ($usb{'main'}->[$i][0] eq $bus_id && $usb{'main'}->[$i][1] == $device_id){ + if (!$b_hub && $usb{'main'}->[$i][13] && (!$type || $type eq '' )){ + $type = check_type($usb{'main'}->[$i][13],$driver,$type); } - #print $type,"\n"; - $usb[$i]->[0] = $bus_id_alpha; - $usb[$i]->[2] = $path_id; - $usb[$i]->[3] = $_; - $usb[$i]->[4] = $class_id; - $usb[$i]->[5] = $subclass_id; - $usb[$i]->[6] = $protocol_id; - $usb[$i]->[8] = $usb_version; - $usb[$i]->[9] = $interfaces; - $usb[$i]->[10] = $ports if $ports; - if ($type && $b_hub && (!$usb[$i]->[13] || $usb[$i]->[13] =~ /^linux foundation/i )){ - $usb[$i]->[13] = "$type"; + # print $type,"\n"; + $usb{'main'}->[$i][0] = $bus_id_alpha; + $usb{'main'}->[$i][2] = $path_id; + $usb{'main'}->[$i][3] = $_; + $usb{'main'}->[$i][4] = $class_id; + $usb{'main'}->[$i][5] = $subclass_id; + $usb{'main'}->[$i][6] = $protocol_id; + $usb{'main'}->[$i][8] = $usb_version; + $usb{'main'}->[$i][9] = $interfaces; + $usb{'main'}->[$i][10] = $ports if $ports; + if ($type && $b_hub && (!$usb{'main'}->[$i][13] || $usb{'main'}->[$i][13] =~ /^linux foundation/i )){ + $usb{'main'}->[$i][13] = "$type"; } - $usb[$i]->[14] = $type if ($type && !$b_hub); - $usb[$i]->[15] = $driver if $driver; - $usb[$i]->[16] = $serial if $serial; - $usb[$i]->[17] = $speed if $speed; - $usb[$i]->[18] = $configuration; - $usb[$i]->[19] = $power; - $usb[$i]->[20] = ''; - assign_usb_type($usb[$i]); - #print join("\n",@{$usb[$i]}),"\n\n";# if !$b_hub; + $usb{'main'}->[$i][14] = $type if ($type && !$b_hub); + $usb{'main'}->[$i][15] = $driver if $driver; + $usb{'main'}->[$i][16] = $serial if $serial; + $usb{'main'}->[$i][17] = $speed if $speed; + $usb{'main'}->[$i][18] = $configuration; + $usb{'main'}->[$i][19] = $power; + $usb{'main'}->[$i][20] = ''; + assign_usb_type($usb{'main'}->[$i]); + # print join("\n",@{$usb{'main'}->[$i]}),"\n\n";# if !$b_hub; last; } } @@ -24256,39 +25839,39 @@ sub sys_data { $type = check_type($name,$driver,$type); } # this isn't that useful, but save in case something shows up - #if ($configuration){ + # if ($configuration){ # $name = ($name) ? "$name $configuration" : $configuration; - #} + # } $type = 'Hub' if $b_hub; - $usb[$i]->[0] = $bus_id_alpha; - $usb[$i]->[1] = $device_id; - $usb[$i]->[2] = $path_id; - $usb[$i]->[3] = $_; - $usb[$i]->[4] = $class_id; - $usb[$i]->[5] = $subclass_id; - $usb[$i]->[6] = $protocol_id; - $usb[$i]->[7] = "$vendor_id:$chip_id"; - $usb[$i]->[8] = $usb_version; - $usb[$i]->[9] = $interfaces; - $usb[$i]->[10] = $ports; - $usb[$i]->[11] = $vendor; - $usb[$i]->[12] = $product; - $usb[$i]->[13] = $name; - $usb[$i]->[14] = $type; - $usb[$i]->[15] = $driver; - $usb[$i]->[16] = $serial; - $usb[$i]->[17] = $speed; - $usb[$i]->[18] = $configuration; - $usb[$i]->[19] = $power; - $usb[$i]->[20] = ''; - assign_usb_type($usb[$i]); + $usb{'main'}->[$i][0] = $bus_id_alpha; + $usb{'main'}->[$i][1] = $device_id; + $usb{'main'}->[$i][2] = $path_id; + $usb{'main'}->[$i][3] = $_; + $usb{'main'}->[$i][4] = $class_id; + $usb{'main'}->[$i][5] = $subclass_id; + $usb{'main'}->[$i][6] = $protocol_id; + $usb{'main'}->[$i][7] = "$vendor_id:$chip_id"; + $usb{'main'}->[$i][8] = $usb_version; + $usb{'main'}->[$i][9] = $interfaces; + $usb{'main'}->[$i][10] = $ports; + $usb{'main'}->[$i][11] = $vendor; + $usb{'main'}->[$i][12] = $product; + $usb{'main'}->[$i][13] = $name; + $usb{'main'}->[$i][14] = $type; + $usb{'main'}->[$i][15] = $driver; + $usb{'main'}->[$i][16] = $serial; + $usb{'main'}->[$i][17] = $speed; + $usb{'main'}->[$i][18] = $configuration; + $usb{'main'}->[$i][19] = $power; + $usb{'main'}->[$i][20] = ''; + assign_usb_type($usb{'main'}->[$i]); $i++; } - #print "$path_id ids: $bus_id:$device_id driver: $driver ports: $ports\n==========\n"; # if $dbg[6];; + # print "$path_id ids: $bus_id:$device_id driver: $driver ports: $ports\n==========\n"; # if $dbg[6];; } } - print Data::Dumper::Dumper \@usb if $source eq 'main' && $dbg[6]; - main::log_data('dump','@usb: sys',\@usb) if $source eq 'main' && $b_log; + print Data::Dumper::Dumper $usb{'main'} if $source eq 'main' && $dbg[6]; + main::log_data('dump','$usb{main}: sys',$usb{'main'}) if $source eq 'main' && $b_log; eval $end if $b_log; } # get driver, interface [type:] data @@ -24302,7 +25885,7 @@ sub uevent_data { # print "f2: $_\n"; ($interface) = (''); @working = main::reader($_) if -r $_; - #print join("\n",@working), "\n"; + # print join("\n",@working), "\n"; if (@working){ $driver = main::awk(\@working,'^DRIVER',2,'='); $interface = main::awk(\@working,'^INTERFACE',2,'='); @@ -24324,7 +25907,7 @@ sub uevent_data { } } } - #print "driver:$driver\n"; + # print "driver:$driver\n"; $b_hub = 1 if $driver && $driver eq 'hub'; $driver = '' if $driver && ($driver eq 'usb' || $driver eq 'hub'); push(@drivers,$driver) if $driver; @@ -24365,30 +25948,31 @@ sub assign_usb_type { $row->[15] = '' if !defined $row->[15]; # driver set_asound_ids() if $show{'audio'} && !$b_asound; set_network_regex() if $show{'network'} && !$network_regex; + # NOTE: a device, like camera, can be audio+graphic if ($show{'audio'} && ( (@asound_ids && $row->[7] && (grep {$row->[7] eq $_} @asound_ids)) || ($row->[14] =~ /Audio/) || ($row->[15] && $row->[15] =~ /audio/) || ($row->[13] && lc($row->[13]) =~ /(audio|\bdac[0-9]*\b|headphone|\bmic(rophone)?\b)/))){ - push(@usb_audio,$row); + push(@{$usb{'audio'}},$row); } - elsif ($show{'bluetooth'} && ( - $row->[14] && $row->[14] =~ /Bluetooth/ || - ($row->[15] && $row->[15] =~ /btusb/))){ - push(@usb_bluetooth,$row); - } - elsif ($show{'graphic'} && ( + if ($show{'graphic'} && ( $row->[14] && ($row->[14] =~ /Video/ ) || ($row->[15] && $row->[15] =~ /video/) || ($row->[13] && lc($row->[13]) =~ /(camera|\bdvb-t|\b(pc)?tv\b|video|webcam)/))){ - push(@usb_graphics,$row); + push(@{$usb{'graphics'}},$row); + } + elsif ($show{'bluetooth'} && ( + $row->[14] && $row->[14] =~ /Bluetooth/ || + ($row->[15] && $row->[15] =~ /\b(btusb|ubt)\b/))){ + push(@{$usb{'bluetooth'}},$row); } elsif ($show{'network'} && ( ($row->[14] && $row->[14] =~ /(Ethernet|Network|WiFi)/i) || ($row->[15] && $row->[15] =~ /(^ipw|^iwl|wifi)/) || ($row->[13] && $row->[13] =~ /($network_regex)/i))){ - #print "$1\n"; - push(@usb_network,$row); + # print "$1\n"; + push(@{$usb{'network'}},$row); } } sub device_type { @@ -24396,7 +25980,7 @@ sub device_type { my ($type); # note: the 3/0/0 value passed will be decimal, not hex my @types = split('/', $data) if $data; - #print @types,"\n"; + # print @types,"\n"; if (!@types || $types[0] eq '0' || scalar @types != 3) {return '';} elsif ($types[0] eq '255') { return '';} if (scalar @types == 3){ @@ -24451,14 +26035,14 @@ sub device_type { sub check_type { my ($name,$driver,$type) = @_; $name = lc($name); - if ($name =~ /\b(hub)/i){ + if (($driver && $driver =~ /hub/) || $name =~ /\b(hub)/i){ $type = 'Hub'; } elsif ($name =~ /(audio|\bdac[0-9]*\b|(head|micro|tele)phone|hifi|\bmidi\b|\bmic\b|sound)/){ $type = 'Audio'; } # Broadcom HP Portable SoftSailing - elsif (($driver && $driver =~ /btusb/) || $name =~ /(bluetooth)/){ + elsif (($driver && $driver =~ /\b(btusb|ubt)\b/) || $name =~ /(bluetooth)/){ $type = 'Bluetooth' } elsif (($driver && $driver =~ /video/) || @@ -24468,13 +26052,19 @@ sub check_type { elsif ($name =~ /(wlan|wi-?fi|802\.1[15]|(11|54|108|240|300|450|1300)\s?mbps|(11|54|108|240)g\b|wireless[\s-][gn]\b|wireless.*adapter)/){ $type = 'WiFi'; } - elsif ($name =~ /(ethernet|\blan|802\.3|100?\/1000?|gigabit)/){ + # note, until freebsd match to actual drivers, these top level driver matches aren't interesting + elsif (($driver && $bsd_type && $driver =~ /\b(muge)\b/) || + $name =~ /(ethernet|\blan|802\.3|100?\/1000?|gigabit)/){ $type = 'Ethernet'; } # note: audio devices show HID sometimes, not sure why elsif ($name =~ /(joystick|keyboard|mouse|trackball)/){ $type = 'HID'; } + elsif (($driver && $driver =~ /^(umass)$/) || + $name =~ /\b(disk|drive|flash)\b/){ + $type = 'Mass Storage'; + } return $type; } # linux only, will create a positive match to sound devices @@ -24539,13 +26129,13 @@ sub prep_speed { elsif ($_[0] =~ /super[\s-]?speed/i){ $speed = 5000;# 3.0; } - elsif ($_[0] =~ /hi[\s-]?speed/i){ + elsif ($_[0] =~ /hi(gh)?[\s-]?speed/i){ $speed = 480; # 2.0, } elsif ($_[0] =~ /full[\s-]?speed/i){ $speed = 12; # 1.1 - could be full speed 1.1/2.0 } - elsif ($_[0] =~ /low[\s-]?speed/i){ + elsif ($_[0] =~ /low?[\s-]?speed/i){ $speed = 1.5; # 1.5 - could be 1.0, or low speed 1.1/2.0 } return $speed; @@ -24564,206 +26154,165 @@ sub bus_id_alpha { } } -######################################################################## -#### GENERATE LINES -######################################################################## - -#### ------------------------------------------------------------------- -#### LINE CONTROLLERS -#### ------------------------------------------------------------------- - -sub assign_data { - my ($row) = @_; - return if ! %$row; - if ($output_type eq 'screen'){ - print_data($row); - } - else { - %rows = (%rows,%$row); - } +# note: seen instance in android where reading file hangs endlessly!!! +sub get_wakeups { + eval $start if $b_log; + return if $b_arm || $b_mips || $b_ppc; + my ($wakeups); + my $path = '/sys/power/wakeup_count'; + $wakeups = reader($path,'strip',0) if -r $path; + eval $end if $b_log; + return $wakeups; } -sub generate_lines { +######################################################################## +#### GENERATE OUTPUT +######################################################################## + +## OutputGenerator +# Also creates Short, Info, and System items +{ +package OutputGenerator; + +sub generate { eval $start if $b_log; my (%row,%checks); - set_ps_aux() if !$loaded{'ps-aux'}; - set_sysctl_data() if $use{'sysctl'}; + main::set_ps_aux() if !$loaded{'ps-aux'}; + main::set_sysctl_data() if $use{'sysctl'}; + main::set_dboot_data() if $bsd_type && !$loaded{'dboot'}; # note: ps aux loads before logging starts, so create debugger data here if ($b_log){ # I don't think we need to see this, it's long, but leave in case we do - #main::log_data('dump','@ps_aux',\@ps_aux); - log_data('dump','@ps_cmd',\@ps_cmd); + # main::log_data('dump','@ps_aux',\@ps_aux); + main::log_data('dump','@ps_cmd',\@ps_cmd); } if ($show{'short'}){ - set_dmesg_boot_data(\$checks{'dmesg-boot'}) if ($bsd_type && !$checks{'dmesg-boot'}); - %row = generate_short_data(); + %row = short_output(); assign_data(\%row); } else { if ($show{'system'}){ - %row = generate_system_data(); + %row = system_item(); assign_data(\%row); } if ($show{'machine'}){ - set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; - set_dmesg_boot_data() if ($bsd_type && !$checks{'dmesg-boot'}); - %row = line_handler('Machine','machine'); + DmidecodeData::set(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; + %row = item_handler('Machine','machine'); assign_data(\%row); } if ($show{'battery'}){ - set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; - %row = line_handler('Battery','battery'); + DmidecodeData::set(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; + %row = item_handler('Battery','battery'); if (%row || $show{'battery-forced'}){ assign_data(\%row); } } if ($show{'ram'}){ - set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; - %row = line_handler('Memory','ram'); + DmidecodeData::set(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; + %row = item_handler('Memory','ram'); assign_data(\%row); } if ($show{'slot'}){ - set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; - %row = line_handler('PCI Slots','slot'); + DmidecodeData::set(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; + %row = item_handler('PCI Slots','slot'); assign_data(\%row); } if ($show{'cpu'} || $show{'cpu-basic'}){ DeviceData::set(\$checks{'device'}) if $b_arm && !$checks{'device'}; - set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; - set_dmesg_boot_data() if ($bsd_type && !$checks{'dmesg-boot'}); + DmidecodeData::set(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; my $arg = ($show{'cpu-basic'}) ? 'basic' : 'full' ; - %row = line_handler('CPU','cpu',$arg); + %row = item_handler('CPU','cpu',$arg); assign_data(\%row); } if ($show{'graphic'}){ - USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + UsbData::set(\$checks{'usb'}) if !$checks{'usb'}; DeviceData::set(\$checks{'device'}) if !$checks{'device'}; - %row = line_handler('Graphics','graphic'); + %row = item_handler('Graphics','graphic'); assign_data(\%row); } if ($show{'audio'}){ - USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + UsbData::set(\$checks{'usb'}) if !$checks{'usb'}; DeviceData::set(\$checks{'device'}) if !$checks{'device'}; - %row = line_handler('Audio','audio'); + %row = item_handler('Audio','audio'); assign_data(\%row); } if ($show{'network'}){ - USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + UsbData::set(\$checks{'usb'}) if !$checks{'usb'}; DeviceData::set(\$checks{'device'}) if !$checks{'device'}; IpData::set() if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})); - %row = line_handler('Network','network'); + %row = item_handler('Network','network'); assign_data(\%row); } if ($show{'bluetooth'}){ - USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + UsbData::set(\$checks{'usb'}) if !$checks{'usb'}; DeviceData::set(\$checks{'device'}) if !$checks{'device'}; - %row = line_handler('Bluetooth','bluetooth'); + %row = item_handler('Bluetooth','bluetooth'); assign_data(\%row); } if ($show{'logical'}){ - %row = line_handler('Logical','logical'); + %row = item_handler('Logical','logical'); assign_data(\%row); } if ($show{'raid'}){ DeviceData::set(\$checks{'device'}) if !$checks{'device'}; - %row = line_handler('RAID','raid'); + %row = item_handler('RAID','raid'); assign_data(\%row); } if ($show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'optical'}){ - set_dmesg_boot_data() if ($bsd_type && !$checks{'dmesg-boot'}); - %row = line_handler('Drives','disk'); + %row = item_handler('Drives','disk'); assign_data(\%row); } if ($show{'partition'} || $show{'partition-full'}){ - %row = line_handler('Partition','partition'); + %row = item_handler('Partition','partition'); assign_data(\%row); } if ($show{'swap'}){ - %row = line_handler('Swap','swap'); + %row = item_handler('Swap','swap'); assign_data(\%row); } if ($show{'unmounted'}){ - %row = line_handler('Unmounted','unmounted'); + %row = item_handler('Unmounted','unmounted'); assign_data(\%row); } if ($show{'usb'}){ - USBData::set(\$checks{'usb'}) if !$checks{'usb'}; - %row = line_handler('USB','usb'); + UsbData::set(\$checks{'usb'}) if !$checks{'usb'}; + %row = item_handler('USB','usb'); assign_data(\%row); } if ($show{'sensor'}){ - %row = line_handler('Sensors','sensor'); + %row = item_handler('Sensors','sensor'); assign_data(\%row); } if ($show{'repo'}){ - %row = line_handler('Repos','repo'); + %row = item_handler('Repos','repo'); assign_data(\%row); } if ($show{'process'}){ - %row = line_handler('Processes','process'); + %row = item_handler('Processes','process'); assign_data(\%row); } if ($show{'weather'}){ - %row = line_handler('Weather','weather'); + %row = item_handler('Weather','weather'); assign_data(\%row); } if ($show{'info'}){ - %row = generate_info_data(); + %row = info_item(); assign_data(\%row); } } if ($output_type ne 'screen'){ - output_handler(\%rows); + main::output_handler(\%rows); } eval $end if $b_log; } - -sub line_handler { - eval $start if $b_log; - my ($key,$sub,$arg) = @_; - my %subs = ( - 'audio' => \&AudioData::get, - 'battery' => \&BatteryData::get, - 'bluetooth' => \&BluetoothData::get, - 'cpu' => \&CpuData::get, - 'disk' => \&DiskData::get, - 'graphic' => \&GraphicData::get, - 'logical' => \&LogicalData::get, - 'machine' => \&MachineData::get, - 'network' => \&NetworkData::get, - 'partition' => \&PartitionData::get, - 'raid' => \&RaidData::get, - 'ram' => \&RamData::get, - 'repo' => \&RepoData::get, - 'process' => \&ProcessData::get, - 'sensor' => \&SensorData::get, - 'slot' => \&SlotData::get, - 'swap' => \&SwapData::get, - 'unmounted' => \&UnmountedData::get, - 'usb' => \&UsbData::get, - 'weather' => \&WeatherData::get, - ); - my (%data); - my $data_name = main::key($prefix++,1,0,$key); - my @rows = $subs{$sub}->($arg); - if (@rows){ - %data = ($data_name => \@rows,); - } - eval $end if $b_log; - return %data; -} - -#### ------------------------------------------------------------------- -#### SHORT, DEBUG -#### ------------------------------------------------------------------- - -sub generate_short_data { +## Short, Info, System Items ## +sub short_output { eval $start if $b_log; my $num = 0; my $kernel_os = ($bsd_type) ? 'OS' : 'Kernel'; my ($cpu_string,$speed,$speed_key,$type) = ('','','speed',''); my $memory = MemoryData::get('string'); - my @cpu = CpuData::get('short'); + my @cpu = CpuItem::get('short'); if (scalar @cpu > 1){ $type = ($cpu[2]) ? " (-$cpu[2]-)" : ''; ($speed,$speed_key) = ('',''); @@ -24776,7 +26325,7 @@ sub generate_short_data { $speed_key = $cpu[3]; $speed = $cpu[4]; } - $cpu[1] ||= row_defaults('cpu-model-null'); + $cpu[1] ||= main::row_defaults('cpu-model-null'); $cpu_string = $cpu[0] . ' ' . $cpu[1] . $type; } elsif ($bsd_type) { @@ -24791,7 +26340,7 @@ sub generate_short_data { } } } - my @disk = DiskData::get('short'); + my @disk = DriveItem::get('short'); # print Dumper \@disk; my $disk_string = 'N/A'; my ($size,$used) = ('',''); @@ -24799,14 +26348,14 @@ sub generate_short_data { if (@disk){ $size = ($disk[0]->{'logical-size'}) ? $disk[0]->{'logical-size'} : $disk[0]->{'size'}; # must be > 0 - if ($size && is_numeric($size) ){ + if ($size && main::is_numeric($size) ){ $size_holder = $size; - $size = get_size($size,'string'); + $size = main::get_size($size,'string'); } $used = $disk[0]->{'used'}; - if ($used && is_numeric($disk[0]->{'used'}) ){ + if ($used && main::is_numeric($disk[0]->{'used'}) ){ $used_holder = $disk[0]->{'used'}; - $used = get_size($used,'string'); + $used = main::get_size($used,'string'); } # in some fringe cases size can be 0 so only assign 'N/A' if no percents etc if ($size_holder && $used_holder){ @@ -24814,12 +26363,12 @@ sub generate_short_data { $disk_string = "$size$percent"; } else { - $size ||= row_defaults('disk-size-0'); + $size ||= main::row_defaults('disk-size-0'); $disk_string = "$used/$size"; } } $memory ||= 'N/A'; - #print join('; ', @cpu), " sleep: $cpu_sleep\n"; + # print join('; ', @cpu), " sleep: $cpu_sleep\n"; if (!$loaded{'shell-data'} && $ppid && (!$b_irc || !$client{'name-print'})){ ShellData::set(); } @@ -24831,14 +26380,14 @@ sub generate_short_data { my @data = ({ main::key($num++,0,0,'CPU') => $cpu_string, main::key($num++,0,0,$speed_key) => $speed, - main::key($num++,0,0,$kernel_os) => &get_kernel_data(), - main::key($num++,0,0,'Up') => &get_uptime(), + main::key($num++,0,0,$kernel_os) => main::get_kernel_data(), + main::key($num++,0,0,'Up') => main::get_uptime(), main::key($num++,0,0,'Mem') => $memory, main::key($num++,0,0,'Storage') => $disk_string, # could make -1 for ps aux itself, -2 for ps aux and self main::key($num++,0,0,'Procs') => scalar @ps_aux, main::key($num++,0,0,$client_shell) => $client, - main::key($num++,0,0,$self_name) => &get_self_version(), + main::key($num++,0,0,$self_name) => main::get_self_version(), },); my %row = ( main::key($prefix,1,0,'SHORT') => [(@data),], @@ -24846,12 +26395,7 @@ sub generate_short_data { eval $end if $b_log; return %row; } - -#### ------------------------------------------------------------------- -#### CONSTRUCTED LINES -#### ------------------------------------------------------------------- - -sub generate_info_data { +sub info_item{ eval $start if $b_log; my $num = 0; my $gcc_alt = ''; @@ -24859,7 +26403,7 @@ sub generate_info_data { my $data_name = main::key($prefix++,1,0,'Info'); my ($b_gcc,$gcc,$index); my ($gpu_ram,$parent,$percent,$total,$used) = (0,'','','',''); - my @gccs = get_gcc_data(); + my @gccs = main::get_gcc_data(); if (@gccs){ $gcc = shift @gccs; if ($extra > 1 && @gccs){ @@ -24871,12 +26415,12 @@ sub generate_info_data { my %data = ( $data_name => [{ main::key($num++,0,1,'Processes') => scalar @ps_aux, - main::key($num++,1,1,'Uptime') => get_uptime(), + main::key($num++,1,1,'Uptime') => main::get_uptime(), },], ); $index = scalar(@{ $data{$data_name} } ) - 1; if ($extra > 2){ - my $wakeups = get_wakeups(); + my $wakeups = main::get_wakeups(); $data{$data_name}->[$index]{main::key($num++,0,2,'wakeups')} = $wakeups if defined $wakeups; } if (!$loaded{'memory'}){ @@ -24884,11 +26428,11 @@ sub generate_info_data { if ($memory){ my @temp = split(':', $memory); $gpu_ram = $temp[3] if $temp[3]; - $total = ($temp[0]) ? get_size($temp[0],'string') : 'N/A'; - $used = ($temp[1]) ? get_size($temp[1],'string') : 'N/A'; + $total = ($temp[0]) ? main::get_size($temp[0],'string') : 'N/A'; + $used = ($temp[1]) ? main::get_size($temp[1],'string') : 'N/A'; $used .= " ($temp[2]%)" if $temp[2]; if ($gpu_ram){ - $gpu_ram = get_size($gpu_ram,'string'); + $gpu_ram = main::get_size($gpu_ram,'string'); } } $data{$data_name}->[$index]{main::key($num++,1,1,'Memory')} = $total; @@ -24898,7 +26442,7 @@ sub generate_info_data { $data{$data_name}->[$index]{main::key($num++,0,2,'gpu')} = $gpu_ram; } if ( (!$b_display || $force{'display'}) || $extra > 0 ){ - my %init = get_init_data(); + my %init = main::get_init_data(); my $init_type = ($init{'init-type'}) ? $init{'init-type'}: 'N/A'; $data{$data_name}->[$index]{main::key($num++,1,1,'Init')} = $init_type; if ($extra > 1 ){ @@ -24928,8 +26472,8 @@ sub generate_info_data { if ($extra > 0 ){ my $b_clang; my $clang_version = ''; - if (my $path = check_program('clang')){ - $clang_version = program_version($path,'clang',3,'--version'); + if (my $path = main::check_program('clang')){ + $clang_version = main::program_version($path,'clang',3,'--version'); $clang_version ||= 'N/A'; $b_clang = 1; } @@ -24988,12 +26532,11 @@ sub generate_info_data { $data{$data_name}->[$index]{main::key($num++,0,2,'running-in')} = $running_in; } } - $data{$data_name}->[$index]{main::key($num++,0,1,$self_name)} = get_self_version(); + $data{$data_name}->[$index]{main::key($num++,0,1,$self_name)} = main::get_self_version(); eval $end if $b_log; return %data; } - -sub generate_system_data { +sub system_item { eval $start if $b_log; my ($cont_desk,$ind_dm,$num) = (1,2,0); my ($index); @@ -25005,10 +26548,10 @@ sub generate_system_data { ); $index = scalar(@{ $data{$data_name} } ) - 1; if ($show{'host'}){ - $data{$data_name}->[$index]{main::key($num++,0,1,'Host')} = get_hostname(); + $data{$data_name}->[$index]{main::key($num++,0,1,'Host')} = main::get_hostname(); } - $data{$data_name}->[$index]{main::key($num++,1,1,'Kernel')} = get_kernel_data(); - $data{$data_name}->[$index]{main::key($num++,0,2,'bits')} = get_kernel_bits(); + $data{$data_name}->[$index]{main::key($num++,1,1,'Kernel')} = main::get_kernel_data(); + $data{$data_name}->[$index]{main::key($num++,0,2,'bits')} = main::get_kernel_bits(); if ($extra > 0){ my @compiler = CompilerVersion::get(); # get compiler data if (scalar @compiler != 2){ @@ -25023,9 +26566,9 @@ sub generate_system_data { } if ($b_admin && (my $params = KernelParameters::get())){ $index = scalar(@{ $data{$data_name} } ); - #print "$params\n"; - $params = apply_partition_filter('system', $params, 'label') if $use{'filter-label'}; - $params = apply_partition_filter('system', $params, 'uuid') if $use{'filter-uuid'}; + # print "$params\n"; + $params = main::apply_partition_filter('system', $params, 'label') if $use{'filter-label'}; + $params = main::apply_partition_filter('system', $params, 'uuid') if $use{'filter-uuid'}; $data{$data_name}->[$index]{main::key($num++,0,2,'parameters')} = $params; $index = scalar(@{ $data{$data_name} } ); } @@ -25037,8 +26580,8 @@ sub generate_system_data { $desktop_version = $desktop_data[1] if $desktop_data[1]; $desktop .= ' ' . $desktop_version if $desktop_version; if ($extra > 0 && $desktop_data[3]){ - #$desktop .= ' (' . $desktop_data[2]; - #$desktop .= ( $desktop_data[3] ) ? ' ' . $desktop_data[3] . ')' : ')'; + # $desktop .= ' (' . $desktop_data[2]; + # $desktop .= ( $desktop_data[3] ) ? ' ' . $desktop_data[3] . ')' : ')'; $toolkit = "$desktop_data[2] $desktop_data[3]"; } if ($extra > 2 && $desktop_data[4]){ @@ -25084,16 +26627,16 @@ sub generate_system_data { if ($extra > 2 && $b_display && defined $ENV{'XDG_VTNR'} ){ $data{$data_name}->[$index]{main::key($num++,0,2,'vt')} = $ENV{'XDG_VTNR'}; } - my $dms = get_display_manager(); + my $dms = main::get_display_manager(); if ($dms || $desktop_key ne 'Console'){ $dms ||= 'N/A'; $data{$data_name}->[$index]{main::key($num++,0,$ind_dm,$dm_key)} = $dms; } } - #if ($extra > 2 && $desktop_key ne 'Console'){ + # if ($extra > 2 && $desktop_key ne 'Console'){ # my $tty = ShellData::tty_number() if !$loaded{'tty-number'}; # $data{$data_name}->[$index]{main::key($num++,0,1,'vc')} = $tty if $tty ne ''; - #} + # } my $distro_key = ($bsd_type) ? 'OS': 'Distro'; my @distro_data = DistroData::get(); my $distro = $distro_data[0]; @@ -25105,6 +26648,52 @@ sub generate_system_data { eval $end if $b_log; return %data; } +## Item Processors ## +sub assign_data { + my ($row) = @_; + return if ! %$row; + if ($output_type eq 'screen'){ + main::print_data($row); + } + else { + %rows = (%rows,%$row); + } +} +sub item_handler { + eval $start if $b_log; + my ($key,$sub,$arg) = @_; + my %subs = ( + 'audio' => \&AudioItem::get, + 'battery' => \&BatteryItem::get, + 'bluetooth' => \&BluetoothItem::get, + 'cpu' => \&CpuItem::get, + 'disk' => \&DriveItem::get, + 'graphic' => \&GraphicItem::get, + 'logical' => \&LogicalItem::get, + 'machine' => \&MachineItem::get, + 'network' => \&NetworkItem::get, + 'partition' => \&PartitionItem::get, + 'raid' => \&RaidItem::get, + 'ram' => \&RamItem::get, + 'repo' => \&RepoItem::get, + 'process' => \&ProcessItem::get, + 'sensor' => \&SensorItem::get, + 'slot' => \&SlotItem::get, + 'swap' => \&SwapItem::get, + 'unmounted' => \&UnmountedItem::get, + 'usb' => \&UsbItem::get, + 'weather' => \&WeatherItem::get, + ); + my (%data); + my $data_name = main::key($prefix++,1,0,$key); + my @rows = $subs{$sub}->($arg); + if (@rows){ + %data = ($data_name => \@rows,); + } + eval $end if $b_log; + return %data; +} +} ####################################################################### #### LAUNCH diff --git a/inxi.1 b/inxi.1 index b978b2d..879715e 100644 --- a/inxi.1 +++ b/inxi.1 @@ -1,4 +1,4 @@ -.TH INXI 1 "2021\-03\-17" inxi "inxi manual" +.TH INXI 1 "2021\-04\-16" inxi "inxi manual" .SH NAME inxi \- Command line system information script for console and IRC @@ -19,14 +19,15 @@ inxi \- Command line system information script for console and IRC \fBinxi\fB [\fB\-x\fR|\fB\-xx\fR|\fB\-xxx\fR|\fB\-a\fR] \fB\-OPTION(s)\fR -All short form options have long form variants \- see below for these and more advanced options. +All short form options have long form variants \- see below for these and more +advanced options. .SH DESCRIPTION -\fBinxi\fR is a command line system information script built for console -and IRC. It is also used a debugging tool for forum technical support -to quickly ascertain users' system configurations and hardware. inxi shows -system hardware, CPU, drivers, Xorg, Desktop, Kernel, gcc version(s), Processes, -RAM usage, and a wide variety of other useful information. +\fBinxi\fR is a command line system information script built for console and +IRC. It is also used a debugging tool for forum technical support to quickly +ascertain users' system configurations and hardware. inxi shows system +hardware, CPU, drivers, Xorg, Desktop, Kernel, gcc version(s), Processes, RAM +usage, and a wide variety of other useful information. \fBinxi\fR output varies depending on whether it is being used on CLI or IRC, with some default filters and color options applied only for IRC use. @@ -40,12 +41,12 @@ username directory in partitions, and a few other items. Because inxi is often used on forums for support, you can also trigger this filtering with the \fB\-z\fR option (\fB\-Fz\fR, for example). To override -the IRC filter, you can use the \fB\-Z\fR option. This can be useful in debugging -network connection issues online in a private chat, for example. +the IRC filter, you can use the \fB\-Z\fR option. This can be useful in +debugging network connection issues online in a private chat, for example. .SH USING OPTIONS -Options can be combined if they do not conflict. You can either group the letters -together or separate them. +Options can be combined if they do not conflict. You can either group the +letters together or separate them. Letters with numbers can have no gap or a gap at your discretion, except when using \fB \-t\fR. Note that if you use an option that requires an additional @@ -73,33 +74,35 @@ Show basic output, short form. Same as: \fBinxi \-v 2\fR .TP .B \-B\fR,\fB \-\-battery\fR -Show system battery (\fBID\-x\fR) data, charge, condition, plus extra information -(if battery present). Uses \fB/sys\fR or, for BSDs without systctl battery data, -\fBdmidecode\fR. \fBdmidecode\fR does not have very much information, and none -about current battery state/charge/voltage. Supports multiple batteries when -using \fB/sys\fR data. +Show system battery (\fBID\-x\fR) data, charge, condition, plus extra +information (if battery present). Uses \fB/sys\fR or, for BSDs without systctl +battery data, use \fB\-\-dmidecode\fR to force its use. \fBdmidecode\fR does +not have very much information, and none about current battery +state/charge/voltage. Supports multiple batteries when using \fB/sys\fR or +\fBsysctl\fR data. -Note that for \fBcharge:\fR, the output shows the current charge, as well as its -value as a percentage of the available capacity, which can be less than the original design -capacity. In the following example, the actual current available capacity of the battery -is \fB22.2 Wh\fR. +Note that for \fBcharge:\fR, the output shows the current charge, as well as +its value as a percentage of the available capacity, which can be less than +the original design capacity. In the following example, the actual current +available capacity of the battery is \fB22.2 Wh\fR. \fBcharge: 20.1 Wh (95.4%)\fR -The \fBcondition:\fR item shows the remaining available capacity / original design -capacity, and then this figure as a percentage of original capacity available in the battery. +The \fBcondition:\fR item shows the remaining available capacity / original +design capacity, and then this figure as a percentage of original capacity +available in the battery. \fBcondition: 22.2/36.4 Wh (61%)\fR -With \fB\-x\fR, or if voltage difference is critical, \fBvolts:\fR item shows the -current voltage, and the \fBmin:\fR voltage. Note -that if the current is below the minimum listed the battery is essentially dead -and will not charge. Test that to confirm, but that's technically how it's supposed to work. +With \fB\-x\fR, or if voltage difference is critical, \fBvolts:\fR item shows +the current voltage, and the \fBmin:\fR voltage. Note that if the current is +below the minimum listed the battery is essentially dead and will not charge. +Test that to confirm, but that's technically how it's supposed to work. \fBvolts: 12.0 min: 11.4\fR -With \fB\-x\fR shows attached \fBDevice\-x\fR information (mouse, keyboard, etc.) -if they are battery powered. +With \fB\-x\fR shows attached \fBDevice\-x\fR information (mouse, keyboard, +etc.) if they are battery powered. .TP .B \-\-bluetooth\fR \- See \fB\-E\fR @@ -111,14 +114,15 @@ Set color scheme. If no scheme number is supplied, 0 is assumed. .TP .B \-c \fR[\fB94\fR\-\fB99\fR] -These color selectors run a color selector option prior to inxi starting which lets -you set the config file value for the selection. +These color selectors run a color selector option prior to inxi starting +which lets you set the config file value for the selection. NOTE: All configuration file set color values are removed when output is -piped or redirected. You must use the explicit runtime \fB\-c \fR option -if you want color codes to be present in the piped/redirected output. +piped or redirected. You must use the explicit runtime \fB\-c \fR +option if you want color codes to be present in the piped/redirected output. -Color selectors for each type display (NOTE: IRC and global only show safe color set): +Color selectors for each type display (NOTE: IRC and global only show safe +color set): .TP .B \-c 94\fR @@ -149,17 +153,19 @@ Setting a specific color type removes the global color selection. .TP .B \-C\fR,\fB \-\-cpu\fR -Show full CPU output, including per CPU clock speed and CPU max speed (if available). -If max speed data present, shows \fB(max)\fR in short output formats (\fBinxi\fR, -\fBinxi \-b\fR) if actual CPU speed matches max CPU speed. If max CPU speed does -not match actual CPU speed, shows both actual and max speed information. -See \fB\-x\fR for more options. +Show full CPU output, including per CPU clock speed and CPU max speed (if +available). If max speed data present, shows \fB(max)\fR in short output +formats (\fBinxi\fR, \fBinxi \-b\fR) if actual CPU speed matches max CPU +speed. If max CPU speed does not match actual CPU speed, shows both actual +and max speed information. See \fB\-x\fR for more options. For certain CPUs (some ARM, and AMD Zen family) shows CPU die count. -The details for each CPU include a technical description e.g. \fBtype: MT MCP\fR +The details for each CPU include a technical description e.g. \fBtype: MT +MCP\fR -* \fBMT\fR \- Multi/Hyper Threaded CPU, more than 1 thread per core (previously \fBHT\fR). +* \fBMT\fR \- Multi/Hyper Threaded CPU, more than 1 thread per core +(previously \fBHT\fR). * \fBMCM\fR \- Multi Chip Model (more than 1 die per CPU). @@ -169,52 +175,56 @@ The details for each CPU include a technical description e.g. \fBtype: MT MCP\fR * \fBUP\fR \- Uni (single core) Processor. -Note that \fBmin/max:\fR speeds are not necessarily true in cases of overclocked CPUs -or CPUs in turbo/boost mode. See \fB\-Ca\fR for alternate \fBbase/boost:\fR speed data. +Note that \fBmin/max:\fR speeds are not necessarily true in cases of +overclocked CPUs or CPUs in turbo/boost mode. See \fB\-Ca\fR for alternate +\fBbase/boost:\fR speed data. .TP .B \-d\fR,\fB \-\-disk\-full\fR,\fB\-\-optical\fR -Show optical drive data as well as \fB\-D\fR hard drive data. With \fB\-x\fR, adds a -feature line to the output. Also shows floppy disks if present. Note that there is -no current way to get any information about the floppy device that we are aware of, -so it will simply show the floppy ID without any extra data. \fB\-xx\fR adds a -few more features. +Show optical drive data as well as \fB\-D\fR hard drive data. With \fB\-x\fR, +adds a feature line to the output. Also shows floppy disks if present. Note +that there is no current way to get any information about the floppy device +that we are aware of, so it will simply show the floppy ID without any extra +data. \fB\-xx\fR adds a few more features. .TP .B \-D\fR,\fB \-\-disk\fR Show Hard Disk info. Shows total disk space and used percentage. The disk used percentage includes space used by swap partition(s), since those are not usable -for data storage. Also, unmounted partitions are not counted in disk use percentages -since inxi has no access to the used amount. +for data storage. Also, unmounted partitions are not counted in disk use +percentages since inxi has no access to the used amount. If the system has RAID or other logical storage, and if inxi can determine -the size of those vs their components, you will see the storage total raw and usable -sizes, plus the percent used of the usable size. The no argument short form -of inxi will show only the usable (or total if no usable) and used percent. -If there is no logical storage detected, only \fBtotal:\fR and \fBused:\fR will -show. Sample (with RAID logical size calculated): +the size of those vs their components, you will see the storage total raw and +usable sizes, plus the percent used of the usable size. The no argument short +form of inxi will show only the usable (or total if no usable) and used +percent. If there is no logical storage detected, only \fBtotal:\fR and +\fBused:\fR will show. Sample (with RAID logical size calculated): -\fBLocal Storage: total: raw: 5.49 TiB usable: 2.80 TiB used: 1.35 TiB (48.3%)\fR +\fBLocal Storage: total: raw: 5.49 TiB usable: 2.80 TiB used: 1.35 TiB +(48.3%)\fR Without logical storage detected: \fBLocal Storage: total: 2.89 TiB used: 1.51 TiB (52.3%)\fR -Also shows per disk information: Disk ID, type (if present), vendor (if detected), -model, and size. See \fBExtra Data Options\fR (\fB\-x\fR options) and -\fBAdmin Extra Data Options\fR (\fB\-\-admin\fR options) for many more features. +Also shows per disk information: Disk ID, type (if present), vendor (if +detected), model, and size. See \fBExtra Data Options\fR (\fB\-x\fR options) +and \fBAdmin Extra Data Options\fR (\fB\-\-admin\fR options) for many more +features. .TP .B \-E\fR, \fB\-\-bluetooth\fR -Show bluetooth device(s), drivers. Show \fBReport:\fR (requires -\fBbt\-adapter\fR or \fBhciconfig\fR) with HCI ID, state, address per device, +Show bluetooth device(s), drivers. Show \fBReport:\fR with HCI ID, state, +address per device (requires \fBbt\-adapter\fR or \fBhciconfig\fR), and if available (hciconfig only) bluetooth version (\fBbt\-v\fR). See \fBExtra Data Options\fR for more. -If bluetooth service is down or disabled, will show message. +If bluetooth shows as \fBstatus: down\fR, shows \fBbt-service:\fR\fB state +and rfkill\fR software and hardware blocked states, and rfkill ID. -Note that \fBReport\-ID:\fR indicates that the HCI item was not able to be linked to a -specific device, similar to \fBIF\-ID:\fR in \fB\-n\fR. +Note that \fBReport\-ID:\fR indicates that the HCI item was not able to be +linked to a specific device, similar to \fBIF\-ID:\fR in \fB\-n\fR. If your internal bluetooth device does not show, it's possible that it has been disabled, if you try enabling it using for example: @@ -248,20 +258,21 @@ very specialized cases. .TP .B \-f\fR,\fB \-\-flags\fR -Show all CPU flags used, not just the short list. Not shown with \fB\-F\fR in order -to avoid spamming. ARM CPUs: show \fBfeatures\fR items. +Show all CPU flags used, not just the short list. Not shown with \fB\-F\fR +in order to avoid spamming. ARM CPUs: show \fBfeatures\fR items. .TP .B \-F\fR,\fB \-\-full\fR -Show Full output for inxi. Includes all Upper Case line letters (except \fB\-J\fR -and \fB\-W\fR) plus \fB\-\-swap\fR, \fB\-s\fR and \fB\-n\fR. Does not show extra -verbose options such as \fB\-d \-f \-i -J \-l \-m \-o \-p \-r \-t \-u \-x\fR unless -you use those arguments in the command, e.g.: \fBinxi \-Frmxx\fR +Show Full output for inxi. Includes all Upper Case line letters (except +\fB\-J\fR and \fB\-W\fR) plus \fB\-\-swap\fR, \fB\-s\fR and \fB\-n\fR. Does +not show extra verbose options such as \fB\-d \-f \-i -J \-l \-m \-o \-p \-r +\-t \-u \-x\fR unless you use those arguments in the command, e.g.: +\fBinxi \-Frmxx\fR .TP .B \-G\fR,\fB \-\-graphics\fR -Show Graphic device(s) information, including details of device and display drivers -(\fBloaded:\fR, and, if applicable: \fBunloaded:\fR, \fBfailed:\fR), +Show Graphic device(s) information, including details of device and display +drivers (\fBloaded:\fR, and, if applicable: \fBunloaded:\fR, \fBfailed:\fR), display protocol (if available), display server (and/or Wayland compositor), vendor and version number, e.g.: @@ -281,7 +292,8 @@ or always if detected and Wayland. .B \-h\fR,\fB \-\-help\fR The help menu. Features dynamic sizing to fit into terminal window. Set script global \fBCOLS_MAX_CONSOLE\fR if you want a different default value, or -use \fB\-y \fR to temporarily override the defaults or actual window width. +use \fB\-y \fR to temporarily override the defaults or actual window +width. .TP .B \-i\fR,\fB \-\-ip\fR @@ -292,8 +304,8 @@ local/WAN IP. Shows both IPv4 and IPv6 link IP addresses. .TP .B \-I\fR,\fB \-\-info\fR -Show Information: processes, uptime, memory, IRC client (or shell type if run in -shell, not IRC), inxi version. See \fB\-Ix\fR, \fB\-Ixx\fR, and \fB\-Ia\fR +Show Information: processes, uptime, memory, IRC client (or shell type if run +in shell, not IRC), inxi version. See \fB\-Ix\fR, \fB\-Ixx\fR, and \fB\-Ia\fR for extra information (init type/version, runlevel, packages). Note: if \fB\-m\fR is used or triggered, the memory item will show in the main @@ -312,7 +324,8 @@ swap partition(s) will not show on the \fB\-P\fR line to avoid redundancy. .B \-J\fR,\fB \-\-usb\fR Show USB data for attached Hubs and Devices. Hubs also show number of ports. Be aware that a port is not always external, some may be internal, and either -used or unused (for example, a motherboard USB header connector that is not used). +used or unused (for example, a motherboard USB header connector that is not +used). Hubs and Devices are listed in order of BusID. @@ -330,8 +343,8 @@ The \fBrev: 2.0\fR item refers to the USB revision number, like \fB1.0\fR or .TP .B \-l\fR,\fB \-\-label\fR -Show partition labels. Default: main partitions \fB\-P\fR. For full \fB\-p\fR output, -use: \fB\-pl\fR. +Show partition labels. Default: main partitions \fB\-P\fR. For full \fB\-p\fR +output, use: \fB\-pl\fR. .TP .B \-L\fR, \fB\-\-logical\fR @@ -363,8 +376,8 @@ component belongs to which. Sample: -\fBDevice\-10: mybackup type: LUKS dm: dm\-28 size: 6.36 GiB Components: c\-1: md1 -cc\-1: dm\-26 ppp\-1: sdj2 cc\-2: dm\-27 ppp\-1: sdk2\fR +\fBDevice\-10: mybackup type: LUKS dm: dm\-28 size: 6.36 GiB Components: +c\-1: md1 cc\-1: dm\-26 ppp\-1: sdj2 cc\-2: dm\-27 ppp\-1: sdk2\fR .nf \fBLV\-5: lvm_raid1 type: raid1 dm: dm\-16 size: 4.88 GiB @@ -374,9 +387,9 @@ pp\-1: sde1 c\-4: dm\-15 pp\-1: sde1\fR .fi It is easier to follow the flow of components and devices using \fB\-y1\fR. In -this example, there is one primary component (c\-1), md1, which is made up of two -components (cc\-1,2), dm\-26 and dm\-27. These are respectively made from physical -devices (p\-1) sdj2 and sdk2. +this example, there is one primary component (c\-1), md1, which is made up of +two components (cc\-1,2), dm\-26 and dm\-27. These are respectively made from +physical devices (p\-1) sdj2 and sdk2. .nf \fBDevice\-10: mybackup @@ -410,38 +423,42 @@ Other types of logical block handling like LUKS, bcache show as: .TP .B \-m\fR,\fB \-\-memory\fR -Memory (RAM) data. Does not display with \fB\-b\fR or \fB\-F\fR unless you use \fB\-m\fR -explicitly. Ordered by system board physical system memory array(s) (\fBArray\-[number]\fR), -and individual memory devices (\fBDevice\-[number]\fR). Physical memory -array data shows array capacity, number of devices supported, and Error Correction -information. Devices shows locator data (highly variable in syntax), size, speed, -type (eg: \fBtype: DDR3\fR). +Memory (RAM) data. Does not display with \fB\-b\fR or \fB\-F\fR unless you +use \fB\-m\fR explicitly. Ordered by system board physical system memory +array(s) (\fBArray\-[number]\fR), and individual memory devices +(\fBDevice\-[number]\fR). Physical memory array data shows array capacity, +number of devices supported, and Error Correction information. Devices shows +locator data (highly variable in syntax), size, speed, type +(eg: \fBtype: DDR3\fR). Note: \fB\-m\fR uses \fBdmidecode\fR, which must be run as root (or start -\fBinxi\fR with \fBsudo\fR), unless you figure out how to set up doas[BSDs]/sudo -to permit dmidecode to read \fB/dev/mem\fR as user. \fBspeed\fR and \fBbus\-width\fR -will not show if \fBNo Module Installed\fR is found in \fBsize\fR. +\fBinxi\fR with \fBsudo\fR), unless you figure out how to set up +doas[BSDs]/sudo to permit dmidecode to read \fB/dev/mem\fR as user. +\fBspeed\fR and \fBbus\-width\fR will not show if \fBNo Module Installed\fR +is found in \fBsize\fR. -Note: If \fB\-m\fR is triggered RAM total/used report will appear in this section, -not in \fB\-I\fR or \fB\-tm\fR items. +Note: If \fB\-m\fR is triggered RAM total/used report will appear in this +section, not in \fB\-I\fR or \fB\-tm\fR items. -Because \fBdmidecode\fR data is extremely unreliable, inxi will try to make best guesses. -If you see \fB(check)\fR after the capacity number, you should check it with the -specifications. \fB(est)\fR is slightly more reliable, but you should still check -the real specifications before buying RAM. Unfortunately there is nothing \fBinxi\fR -can do to get truly reliable data about the system RAM; maybe one day the kernel devs -will put this data into \fB/sys\fR, and make it real data, taken from the actual system, -not dmi data. For most people, the data will be right, but a significant percentage of -users will have either a wrong max module size, if present, or max capacity. +Because \fBdmidecode\fR data is extremely unreliable, inxi will try to make +best guesses. If you see \fB(check)\fR after the capacity number, you should +check it with the specifications. \fB(est)\fR is slightly more reliable, but +you should still check the real specifications before buying RAM. Unfortunately +there is nothing \fBinxi\fR can do to get truly reliable data about the system +RAM; maybe one day the kernel devs will put this data into \fB/sys\fR, and make +it real data, taken from the actual system, not dmi data. For most people, the +data will be right, but a significant percentage of users will have either a +wrong max module size, if present, or max capacity. Under dmidecode, \fBSpeed:\fR is the expected speed of the memory (what is advertised on the memory spec sheet) and \fBConfigured Clock Speed:\fR -is what the actual speed is now. To handle this, if speed and configured speed values -are different, you will see this instead: +is what the actual speed is now. To handle this, if speed and configured speed +values are different, you will see this instead: \fBspeed: spec: [specified speed] MT/S actual: [actual] MT/S\fR -Also, if DDR, and speed in MHz, will change to: \fBspeed: [speed] MT/S ([speed] MHz)\fR +Also, if DDR, and speed in MHz, will change to: \fBspeed: [speed] MT/S +([speed] MHz)\fR If the detected speed is logically absurd, like 1 MT/s or 69910 MT/s, adds: \fBnote: check\fR. Sample: @@ -458,7 +475,8 @@ If the detected speed is logically absurd, like 1 MT/s or 69910 MT/s, adds: actual: 2 MT/s (1 MHz) note: check\fR .fi -See \fB\-\-memory\-modules\fR and \fB\-\-memory\-short\fR if you want a shorter report. +See \fB\-\-memory\-modules\fR and \fB\-\-memory\-short\fR if you want a +shorter report. .TP .B \-\-memory\-modules\fR @@ -473,58 +491,62 @@ Sample: \fBReport: arrays: 1 slots: 4 modules: 2 type: DDR4\fR .TP .B \-M\fR,\fB \-\-machine\fR -Show machine data. Device, Motherboard, BIOS, and if present, System Builder (Like Lenovo). -Older systems/kernels without the required \fB/sys\fR data can use \fBdmidecode\fR instead, run -as root. If using \fBdmidecode\fR, may also show BIOS/UEFI revision as well as version. -\fB\-\-dmidecode\fR forces use of \fBdmidecode\fR data instead of \fB/sys\fR. -Will also attempt to show if the system was booted by BIOS, UEFI, or UEFI [Legacy], the -latter being legacy BIOS boot mode in a system board using UEFI. +Show machine data. Device, Motherboard, BIOS, and if present, System Builder +(Like Lenovo). Older systems/kernels without the required \fB/sys\fR data can +use \fBdmidecode\fR instead, run as root. If using \fBdmidecode\fR, may also +show BIOS/UEFI revision as well as version. \fB\-\-dmidecode\fR forces use of +\fBdmidecode\fR data instead of \fB/sys\fR. Will also attempt to show if the +system was booted by BIOS, UEFI, or UEFI [Legacy], the latter being legacy +BIOS boot mode in a system board using UEFI. -Device information requires either \fB/sys\fR or \fBdmidecode\fR. Note that 'other\-vm?' -is a type that means it's usually a VM, but inxi failed to detect which type, or -positively confirm which VM it is. Primary VM identification is via systemd\-detect\-virt -but fallback tests that should also support some BSDs are used. Less commonly -used or harder to detect VMs may not be correctly detected. If you get an incorrect output, -post an issue and we'll get it fixed if possible. +Device information requires either \fB/sys\fR or \fBdmidecode\fR. Note that +\fBother\-vm?\fR is a type that means it's usually a VM, but inxi failed to +detect which type, or positively confirm which VM it is. Primary VM +identification is via systemd\-detect\-virt but fallback tests that should also +support some BSDs are used. Less commonly used or harder to detect VMs may not +be correctly detected. If you get an incorrect output, post an issue and we'll +get it fixed if possible. -Due to unreliable vendor data, device type will show: desktop, laptop, notebook, server, -blade, plus some obscure stuff that inxi is unlikely to ever run on. +Due to unreliable vendor data, device type will show: desktop, laptop, +notebook, server, blade, plus some obscure stuff that inxi is unlikely to +ever run on. .TP .B \-n\fR,\fB \-\-network\-advanced\fR -Show Advanced Network device information in addition to that produced by \fB\-N\fR. -Shows interface, speed, MAC ID, state, etc. +Show Advanced Network device information in addition to that produced by +\fB\-N\fR. Shows interface, speed, MAC ID, state, etc. .TP .B \-N\fR,\fB \-\-network\fR -Show Network device(s) information, including device driver. With \fB\-x\fR, shows Bus ID, -Port number. +Show Network device(s) information, including device driver. With \fB\-x\fR, +shows Bus ID, Port number. .TP .B \-o\fR,\fB \-\-unmounted\fR Show unmounted partition information (includes UUID and LABEL if available). -Shows file system type if you have \fBlsblk\fR installed (Linux only). For BSD/GNU Linux: -shows file system type if \fBfile\fR is installed, and if you are root or -if you have added to \fB/etc/sudoers\fR (sudo v. 1.7 or newer): +Shows file system type if you have \fBlsblk\fR installed (Linux only). For +BSD/GNU Linux: shows file system type if \fBfile\fR is installed, and if you +are root or if you have added to \fB/etc/sudoers\fR (sudo v. 1.7 or newer): .B ALL = NOPASSWD: /usr/bin/file (sample) BSD users: see \fBman doas.conf\fR for setup. -Does not show components (partitions that create the md\-raid array) of md\-raid arrays. +Does not show components (partitions that create the md\-raid array) of +md\-raid arrays. .TP .B \-p\fR,\fB \-\-partitions\-full\fR -Show full Partition information (\fB\-P\fR plus all other detected mounted partitions). +Show full Partition information (\fB\-P\fR plus all other detected mounted +partitions). .TP .B \-P\fR,\fB \-\-partitions\fR Show basic Partition information. -Shows, if detected: \fB/ /boot /boot/efi /home /opt /tmp /usr /usr/home /var /var/tmp -/var/log\fR (for android, shows \fB/cache /data /firmware /system\fR). -If \fB\-\-swap\fR is not used, shows active swap partitions (never shows file or -zram type swap). -Use \fB\-p\fR to see all mounted partitions. +Shows, if detected: \fB/ /boot /boot/efi /home /opt /tmp /usr /usr/home /var +/var/tmp /var/log\fR (for android, shows \fB/cache /data /firmware /system\fR). +If \fB\-\-swap\fR is not used, shows active swap partitions (never shows file +or zram type swap). Use \fB\-p\fR to see all mounted partitions. .TP .B \-\-processes\fR \- See \fB\-t\fR @@ -571,7 +593,8 @@ APT distros like PCLinuxOS or Alt\-Linux) More will be added as distro data is collected. If yours is missing please show us how to get this information and we'll try to add it. -See \fB\-rx\fR, \fB\-rxx\fR, and \fB\-ra\fR for installed package count information. +See \fB\-rx\fR, \fB\-rxx\fR, and \fB\-ra\fR for installed package count +information. .TP .B \-R\fR,\fB \-\-raid\fR @@ -580,13 +603,13 @@ and components. See extra data with \fB\-x\fR / \fB\-xx\fR. md\-raid: If device is resyncing, also shows resync progress line. -Note: Only md\-raid, ZFS and hardware RAID are currently supported. -Other software RAID types may be added, if the software -RAID actually can be made to give the required output. +Note: supported types: lvm raid, md\-raid, softraid, ZFS, and hardware RAID. +Other software RAID types may be added, if the software RAID can be made to +give the required output. -The component ID numbers work like this: mdraid: the numerator -is the actual mdraid component number; ZFS: the numerator is -auto\-incremented counter only. Eg. \fBOnline: 1: sdb1\fR +The component ID numbers work like this: mdraid: the numerator is the actual +mdraid component number; lvm/softraid/ZFS: the numerator is auto\-incremented +counter only. Eg. \fBOnline: 1: sdb1\fR If hardware RAID is detected, shows basic information. Due to complexity of adding hardware RAID device disk / RAID reports, those will only be added @@ -622,11 +645,12 @@ e.g. taskbar or panel. .TP .B \-t\fR,\fB \-\-processes\fR -[\fBc\fR|\fBm\fR|\fBcm\fR|\fBmc NUMBER\fR] Show processes. If no arguments, defaults to \fBcm\fR. -If followed by a number, shows that number of processes for each type -(default: \fB5\fR; if in IRC, max: \fB5\fR) +[\fBc\fR|\fBm\fR|\fBcm\fR|\fBmc NUMBER\fR] Show processes. If no arguments, +defaults to \fBcm\fR. If followed by a number, shows that number of processes +for each type (default: \fB5\fR; if in IRC, max: \fB5\fR) -Make sure that there is no space between letters and numbers (e.g. write as \fB\-t cm10\fR). +Make sure that there is no space between letters and numbers (e.g. write as +\fB\-t cm10\fR). .TP .B \-t c\fR @@ -687,13 +711,13 @@ speeds, if available) + \fB\-G\fR + basic Disk + \fB\-I\fR. .TP .B \-v 2 -\- Adds networking device (\fB\-N\fR), Machine (\fB\-M\fR) data, Battery (\fB\-B\fR) -(if available). Same as: \fBinxi \-b\fR +\- Adds networking device (\fB\-N\fR), Machine (\fB\-M\fR) data, Battery +(\fB\-B\fR) (if available). Same as: \fBinxi \-b\fR .TP .B \-v 3 -\- Adds advanced CPU (\fB\-C\fR) and network (\fB\-n\fR) data; triggers \fB\-x\fR -advanced data option. +\- Adds advanced CPU (\fB\-C\fR) and network (\fB\-n\fR) data; triggers +\fB\-x\fR advanced data option. .TP .B \-v 4 @@ -729,25 +753,27 @@ Useful for testing output and to see what data you can get from your system. .B \-w\fR,\fB \-\-weather\fR Adds weather line. To get weather for an alternate location, use \fB\-W [location]\fR. See also \fB\-x\fR, \fB\-xx\fR, \fB\-xxx\fR options. -Please note that your distribution's maintainer may chose to disable this feature. +Please note that your distribution's maintainer may chose to disable this +feature. DO NOT USE THIS FEATURE FOR AUTOMATED WEATHER UPDATES! You will be blocked -from any further access. This feature is not meant for widget type -weather monitoring, or Conky type use. It is meant to get weather when you need to +from any further access. This feature is not meant for widget type weather +monitoring, or Conky type use. It is meant to get weather when you need to see it, for example, on a remote server. .TP .B \-W\fR, \fB\-\-weather\-location \fR -Get weather/time for an alternate location. Accepts postal/zip code[, country], -city,state pair, or latitude,longitude. Note: city/country/state names must not -contain spaces. Replace spaces with '\fB+\fR' sign. Don't place spaces around -any commas. Postal code is not reliable except for North America and maybe the UK. -Try postal codes with and without country code added. Note that City,State applies -only to USA, otherwise it's City,Country. If country name (english) does not work, -try 2 character country code (e.g. Spain: es; Great Britain: gb). +Get weather/time for an alternate location. Accepts postal/zip code[, country], +city,state pair, or latitude,longitude. Note: city/country/state names must +not contain spaces. Replace spaces with '\fB+\fR' sign. Don't place spaces +around any commas. Postal code is not reliable except for North America and +maybe the UK. Try postal codes with and without country code added. Note that +City,State applies only to USA, otherwise it's City,Country. If country name +(english) does not work, try 2 character country code (e.g. Spain: es; +Great Britain: gb). -See \fIhttps://en.wikipedia.org/wiki/ISO_3166\-1_alpha\-2\fR for current 2 letter -country codes. +See \fIhttps://en.wikipedia.org/wiki/ISO_3166\-1_alpha\-2\fR for current 2 +letter country codes. Use only ASCII letters in city/state/country names. @@ -755,28 +781,28 @@ Examples: \fB\-W 95623,us\fR OR \fB\-W Boston,MA\fR OR \fB\-W 45.5234,\-122.6762\fR OR \fB\-W new+york,ny\fR OR \fB\-W bodo,norway\fR. DO NOT USE THIS FEATURE FOR AUTOMATED WEATHER UPDATES! Use of automated queries, -will result in your access being blocked. If you try to work around the ban, you -will be permanently banned from this service. +will result in your access being blocked. If you try to work around the ban, +you will be permanently banned from this service. .TP .B \-\-weather\-source\fR, \fB\-\-ws \fR -[\fB1\-9\fR] Switches weather data source. Possible values are \fB1\-9\fR. \fB1\-4\fR -will generally be active, and \fB5\-9\fR may or may not be active, so check. -\fB1\fR may not support city / country names with spaces (even if you use the \fB+\fR -sign instead of space). \fB2\fR offers pretty good data, but may not have all small -city names for \fB\-W\fR. +[\fB1\-9\fR] Switches weather data source. Possible values are \fB1\-9\fR. +\fB1\-4\fR will generally be active, and \fB5\-9\fR may or may not be active, +so check. \fB1\fR may not support city / country names with spaces (even if +you use the \fB+\fR sign instead of space). \fB2\fR offers pretty good data, +but may not have all small city names for \fB\-W\fR. -Please note that the data sources are not static per value, and can change any time, -or be removed, so always test to verify which source is being used for each value -if that is important to you. Data sources may be added or removed on occasions, so -try each one and see which you prefer. If you get unsupported source message, it means -that number has not been implemented. +Please note that the data sources are not static per value, and can change any +time, or be removed, so always test to verify which source is being used for +each value if that is important to you. Data sources may be added or removed +on occasions, so try each one and see which you prefer. If you get unsupported +source message, it means that number has not been implemented. .TP .B \-\-weather\-unit \fR -[\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR] Sets weather units to metric (\fBm\fR), imperial (\fBi\fR), -metric (imperial) (\fBmi\fR, default), imperial (metric) (\fBim\fR). If metric or imperial -not found,sets to default value, or \fBN/A\fR. +[\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR] Sets weather units to metric (\fBm\fR), +imperial (\fBi\fR), metric (imperial) (\fBmi\fR, default), imperial (metric) +(\fBim\fR). If metric or imperial not found,sets to default value, or \fBN/A\fR. .TP .B \-y\fR,\fB \-\-width [integer]\fR @@ -820,8 +846,8 @@ OR \fB\-\-extra 1\fR, \fB\-\-extra 2\fR, \fB\-\-extra 3\fR -The following details show which lines / items display extra information for each -extra data level. +The following details show which lines / items display extra information for +each extra data level. .TP .B \-x \-A\fR @@ -849,8 +875,8 @@ without \fB\-x\fR. .B \-x \-C\fR \- Adds bogomips on CPU (if available) -\- Adds \fBboost: [enabled|disabled]\fR if detected, aka \fBturbo\fR. Not all CPUs -have this feature. +\- Adds \fBboost: [enabled|disabled]\fR if detected, aka \fBturbo\fR. Not all +CPUs have this feature. \- Adds CPU Flags (short list). Use \fB\-f\fR to see full flag/feature list. @@ -873,10 +899,11 @@ dds rev version to optical drive. .B \-x \-D\fR \- Adds HDD temperature with disk data. -Method 1: Systems running Linux kernels ~5.6 and newer should have \fBdrivetemp\fR -module data available. If so, drive temps will come from /sys data for each drive, -and will not require root or hddtemp. This method is MUCH faster than using hddtemp. -Note that NVMe drives do not require \fBdrivetemp\fR. +Method 1: Systems running Linux kernels ~5.6 and newer should have +\fBdrivetemp\fR module data available. If so, drive temps will come from +/sys data for each drive, and will not require root or hddtemp. This method +is MUCH faster than using hddtemp. Note that NVMe drives do not require +\fBdrivetemp\fR. If your \fBdrivetemp\fR module is not enabled, enable it: @@ -885,11 +912,11 @@ If your \fBdrivetemp\fR module is not enabled, enable it: Once enabled, add \fBdrivetemp\fR to \fB/etc/modules\fR or \fB/etc/modules\-load.d/***.conf\fR so it starts automatically. -If you see drive temps running as regular user and you did not configure system -to use doas[BSDs]/sudo hddtemp, then your system supports this feature. If no /sys -data is found, inxi will try to use hddtemp methods instead for that drive. -Hint: if temp is /sys sourced, the temp will be to 1 decimal, like 34.8, if hddtemp -sourced, they will be integers. +If you see drive temps running as regular user and you did not configure +system to use doas[BSDs]/sudo hddtemp, then your system supports this feature. +If no /sys data is found, inxi will try to use hddtemp methods instead for +that drive. Hint: if temp is /sys sourced, the temp will be to 1 decimal, +like 34.8, if hddtemp sourced, they will be integers. Method 2: if you have hddtemp installed, if you are root or if you have added to \fB/etc/sudoers\fR (sudo v. 1.7 or newer): @@ -971,7 +998,8 @@ That requires the full output of the query or method to discover all installed packages on your system, as well of course as the command or method used to discover those. -\- If in shell (i.e. not in IRC client), adds shell version number, if available. +\- If in shell (i.e. not in IRC client), adds shell version number, if +available. .TP .B \-x \-j\fR, \fB\-x \-\-swap\fR @@ -983,8 +1011,8 @@ Add \fBmapper:\fR. See \fB\-x \-o\fR. .TP .B \-x \-L\fR, \fB\-x \-\-logical\fR -\- Adds \fBdm: dm-x\fR to VG > LV and other Device types. This can help tracking -down which device belongs to what. +\- Adds \fBdm: dm-x\fR to VG > LV and other Device types. This can help +tracking down which device belongs to what. .TP .B \-x \-m\fR, \fB\-\-memory\-modules\fR @@ -1023,17 +1051,19 @@ bitmap (if present). Resync line, shows blocks synced/total blocks. .TP .B \-x \-s\fR -\- Adds basic voltages: 12v, 5v, 3.3v, vbat (\fBipmi\fR, \fBlm-sensors\fR if present). +\- Adds basic voltages: 12v, 5v, 3.3v, vbat (\fBipmi\fR, \fBlm-sensors\fR if +present). .TP .B \-x \-S\fR \- Adds Kernel gcc version. -\- Adds to \fBDistro:\fR \fBbase:\fR if detected. System base will only be seen on -a subset of distributions. The distro must be both derived from a parent distro (e.g. Mint from -Ubuntu), and explicitly added to the supported distributions for this feature. Due to -the complexity of distribution identification, these will only be added as relatively solid -methods are found for each distribution system base detection. +\- Adds to \fBDistro:\fR \fBbase:\fR if detected. System base will only be +seen on a subset of distributions. The distro must be both derived from a +parent distro (e.g. Mint from Ubuntu), and explicitly added to the supported +distributions for this feature. Due to the complexity of distribution +identification, these will only be added as relatively solid methods are +found for each distribution system base detection. .TP .B \-x \-t\fR (\fB\-\-processes\fR) @@ -1056,17 +1086,17 @@ methods are found for each distribution system base detection. .TP .B \-xx \-C\fR -\- Adds \fBL1\-cache:\fR and \fBL3\-cache:\fR if either are available. Requires -dmidecode and doas[BSDs]/sudo/root. +\- Adds \fBL1\-cache:\fR and \fBL3\-cache:\fR if either are available. +Requires dmidecode and doas[BSDs]/sudo/root. .TP .B \-xx \-D\fR \- Adds disk serial number. \- Adds disk speed (if available). This is the theoretical top speed of the -device as reported. This speed may be restricted by system board limits, eg. -a SATA 3 drive on a SATA 2 board may report SATA 2 speeds, but this is not -completely consistent, sometimes a SATA 3 device on a SATA 2 board reports +device as reported. This speed may be restricted by system board limits, +eg. a SATA 3 drive on a SATA 2 board may report SATA 2 speeds, but this is +not completely consistent, sometimes a SATA 3 device on a SATA 2 board reports its design speed. NVMe drives: adds lanes, and (per direction) speed is calculated with @@ -1080,6 +1110,8 @@ For a PCIe 3 NVMe drive, with speed of \fB8 GT/s\fR and \fB4\fR lanes \fBspeed: 31.6 Gb/s lanes: 4\fR +\- Adds disk duid, if available. Some BSDs have it. + .TP .B \-xx \-E\fR (\fB\-\-bluetooth\fR) \- Adds vendor:product ID of each device. @@ -1101,12 +1133,12 @@ the same. Example: \- If available, shows \fBalternate:\fR Xorg drivers. This means a driver on the default list of drivers Xorg automatically checks for the device, but which -is not installed. For example, if you have \fBnouveau\fR driver, \fBnvidia\fR would -show as alternate if it was not installed. Note that \fBalternate:\fR does NOT mean you -should have it, it's just one of the drivers Xorg checks to see if is present -and loaded when checking the device. This can let you know there are other driver options. -Note that if you have explicitly set the driver in \fBxorg.conf\fR, Xorg will not -create this automatic check driver list. +is not installed. For example, if you have \fBnouveau\fR driver, \fBnvidia\fR +would show as alternate if it was not installed. Note that \fBalternate:\fR +does NOT mean you should have it, it's just one of the drivers Xorg checks to +see if is present and loaded when checking the device. This can let you know +there are other driver options. Note that if you have explicitly set the driver +in \fBxorg.conf\fR, Xorg will not create this automatic check driver list. \- If available, shows Xorg dpi (\fBs-dpi:\fR) for the active Xorg \fBScreen\fR (not physical monitor). Note that the physical monitor dpi and the Xorg @@ -1121,10 +1153,10 @@ dpi are not necessarily the same thing, and can vary widely. \- Adds system default runlevel, if detected. Supports Systemd/Upstart/SysVinit type defaults. -\- Shows \fBPackages:\fR counts by discovered package manager types. In cases where -only 1 type had results, does not show total after \fBPackages:\fR. Does not -show installed package managers wtih 0 packages. See \fB\-a\fR for full output. -Moves to \fBRepos\fR if \fB\-rxx\fR. +\- Shows \fBPackages:\fR counts by discovered package manager types. In cases +where only 1 type had results, does not show total after \fBPackages:\fR. Does +not show installed package managers wtih 0 packages. See \fB\-a\fR for full +output. Moves to \fBRepos\fR if \fB\-rxx\fR. \- Adds parent program (or tty) that started shell, if not IRC client. @@ -1150,14 +1182,14 @@ documentation to better understand their use of the term 'stripes'. .B \-xx \-m\fR, \fB\-\-memory\-modules\fR \- Adds memory device Manufacturer. -\- Adds memory device Part Number (\fBpart\-no:\fR). Useful for ordering new or -replacement memory sticks etc. Part numbers are unique, particularly -if you use the word \fBmemory\fR in the search as well. With \fB\-xxx\fR, -also shows serial number. +\- Adds memory device Part Number (\fBpart\-no:\fR). Useful for ordering new +or replacement memory sticks etc. Part numbers are unique, particularly if you +use the word \fBmemory\fR in the search as well. With \fB\-xxx\fR, also shows +serial number. -\- Adds single/double bank memory, if data is found. Note, this may not be 100% right -all of the time since it depends on the order that data is found in \fBdmidecode\fR -output for \fBtype 6\fR and \fBtype 17\fR. +\- Adds single/double bank memory, if data is found. Note, this may not be +100% right all of the time since it depends on the order that data is found +in \fBdmidecode\fR output for \fBtype 6\fR and \fBtype 17\fR. .TP .B \-xx \-M\fR @@ -1189,11 +1221,11 @@ shows progress bar. Supports most known display managers, including gdm, gdm3, idm, kdm, lightdm, lxdm, mdm, nodm, sddm, slim, tint, wdm, and xdm. -\- Adds, if run in X, window manager type (\fBwm\fR), if available. -Not all window managers are supported. Some desktops support using more than one -window manager, so this can be useful to see what window manager is actually running. -If none found, shows nothing. Uses a less accurate fallback tool \fBwmctrl\fR -if \fBps\fR tests fail to find data. +\- Adds, if run in X, window manager type (\fBwm\fR), if available. Not all +window managers are supported. Some desktops support using more than one +window manager, so this can be useful to see what window manager is actually +running. If none found, shows nothing. Uses a less accurate fallback tool +\fBwmctrl\fR if \fBps\fR tests fail to find data. \- Adds desktop toolkit (\fBtk\fR), if available (Xfce/KDE/Trinity). @@ -1233,13 +1265,14 @@ Requires doas[BSDs]/sudo/root and \fBdmidecode\fR. .B \-xxx \-D\fR \- Adds disk firmware revision number (if available). -\- Adds disk partition scheme (in most cases), e.g. \fBscheme: GPT\fR. Currently not -able to detect all schemes, but handles the most common, e.g. \fBGPT\fR or \fBMBR\fR. +\- Adds disk partition scheme (in most cases), e.g. \fBscheme: GPT\fR. +Currently not able to detect all schemes, but handles the most common, e.g. +\fBGPT\fR or \fBMBR\fR. -\- Adds disk rotation speed (in some but not all cases), e.g. \fBrotation: 7200 rpm\fR -or \fBrotation: SSD\fR if positive SSD identification was made. If no rotation or positive -SSD ID found, nothing shows. Not all disks report this speed, so even if they are spinnning, -no data will show. +\- Adds disk rotation speed (in some but not all cases), e.g. +\fBrotation: 7200 rpm\fR or \fBrotation: SSD\fR if positive SSD identification +was made. If no rotation or positive SSD ID found, nothing shows. Not all disks +report this speed, so even if they are spinnning, no data will show. .TP .B \-xxx \-E\fR (\fB\-\-bluetooth\fR) @@ -1280,9 +1313,10 @@ uses the \fBwhoami\fR test. .TP .B \-xxx \-m\fR, \fB\-\-memory\-modules\fR \- Adds memory bus width: primary bus width, and if present, total width. e.g. -\fBbus width: 64 bit (total: 72 bits)\fR. Note that total / data widths are mixed up -sometimes in dmidecode output, so inxi will take the larger value as the total if -present. If no total width data is found, then inxi will not show that item. +\fBbus width: 64 bit (total: 72 bits)\fR. Note that total / data widths are +mixed up sometimes in dmidecode output, so inxi will take the larger value as +the total if present. If no total width data is found, then inxi will not show +that item. \- Adds device Type Detail, e.g. \fBdetail: DDR3 (Synchronous)\fR. @@ -1299,7 +1333,8 @@ data available. .TP .B \-xxx \-R\fR -\- md\-raid: Adds system mdraid support types (kernel support, read ahead, RAID events) +\- md\-raid: Adds system mdraid support types (kernel support, read ahead, +RAID events) \- zfs\-raid: Adds portion allocated (used) by RAID array/device. @@ -1309,8 +1344,9 @@ data available. .TP .B \-xxx \-S\fR \- Adds, if in X, or with \fB--display\fR, bar/dock/panel/tray items -(\fBinfo\fR). If none found, shows nothing. Supports desktop items like gnome\-panel, -lxpanel, xfce4\-panel, lxqt\-panel, tint2, cairo-dock, trayer, and many others. +(\fBinfo\fR). If none found, shows nothing. Supports desktop items like +gnome\-panel, lxpanel, xfce4\-panel, lxqt\-panel, tint2, cairo-dock, trayer, +and many others. \- Adds (if present), window manager (\fBwm\fR) version number. @@ -1326,42 +1362,43 @@ have this, some don't, it varies. weather observation time (if available), sunset/sunrise (if available). .SH ADMIN EXTRA DATA OPTIONS -These options are triggered with \fB\-\-admin\fR or \fB\-a\fR. Admin options are -advanced output options, and are more technical, and mostly of interest to system -administrators or other machine admins. +These options are triggered with \fB\-\-admin\fR or \fB\-a\fR. Admin options +are advanced output options, and are more technical, and mostly of interest to +system administrators or other machine admins. The \fB\-\-admin\fR option sets \fB\-xxx\fR, and only has to be used once. It will trigger the following features: .TP .B \-a \-A\fR -\- Adds, if present, possible \fBalternate:\fR kernel modules capable of driving -each \fBDevice\-x\fR (not including the current \fBdriver:\fR). If no non\-driver -modules found, shows nothing. NOTE: just because it lists a module does NOT mean it is -available in the system, it's just something the kernel knows could possibly be used -instead. +\- Adds, if present, possible \fBalternate:\fR kernel modules capable of +driving each \fBDevice\-x\fR (not including the current \fBdriver:\fR). If no +non\-driver modules found, shows nothing. NOTE: just because it lists a module +does NOT mean it is available in the system, it's just something the kernel +knows could possibly be used instead. .TP .B \-a \-C\fR \- Adds CPU family, model\-id, and stepping (replaces \fBrev\fR of \fB\-Cx\fR). -Format is \fBhexadecimal (decimal)\fR if greater than 9, otherwise \fBhexadecimal\fR. - +Format is \fBhexadecimal (decimal)\fR if greater than 9, otherwise +\fBhexadecimal\fR. \- Adds CPU microcode. Format is \fBhexadecimal\fR. -\- Adds socket type (for motherboard CPU socket, if available). If results doubtful -will list two socket types and \fBnote: check\fR. Requires doas[BSDs]/sudo/root and -\fBdmidecode\fR. The item in parentheses may simply be a different syntax for the -same socket, but in general, check this before trusting it. +\- Adds socket type (for motherboard CPU socket, if available). If results +doubtful will list two socket types and \fBnote: check\fR. Requires +doas[BSDs]/sudo/root and \fBdmidecode\fR. The item in parentheses may simply +be a different syntax for the same socket, but in general, check this before +trusting it. .nf Sample: \fBsocket: 775 (478) note: check\fR Sample: \fBsocket: AM4\fR .fi \- Adds DMI CPU base and boost/turbo speeds. Requires doas[BSDs]/sudo/root and -\fBdmidecode\fR. In some cases, like with overclocking or 'turbo' or 'boost' modes, -voltage and external clock speeds may be increased, or short term limits raised -on max CPU speeds. These are often not reflected in /sys based CPU \fBmin/max:\fR -speed results, but often are using this source. +\fBdmidecode\fR. In some cases, like with overclocking or 'turbo' or 'boost' +modes, voltage and external clock speeds may be increased, or short term limits +raised on max CPU speeds. These are often not reflected in /sys based +CPU \fBmin/max:\fR speed results, but often are using this source. Samples: .nf @@ -1376,14 +1413,13 @@ Overclocked 3000 MHz CPU, with boosted max speed: .fi Note that these numbers can be confusing, but basically, the \fBbase\fR -number is the actual normal top speed the CPU runs at without boost mode, and the -\fBboost\fR number is the max speed the CPU reports itself able to run at. -The actual max speed may be higher than either value, or lower. -The \fBboost\fR number appears to be hard\-coded into the CPU DMI data, -and does not seem to reflect actual max speeds that overclocking or -other combinations of speed boosters can enable, as you can see from the -example where the CPU is running at a speed faster than -the min/max or base/boost values. +number is the actual normal top speed the CPU runs at without boost mode, and +the \fBboost\fR number is the max speed the CPU reports itself able to run at. +The actual max speed may be higher than either value, or lower. The \fBboost\fR +number appears to be hard\-coded into the CPU DMI data, and does not seem to +reflect actual max speeds that overclocking or other combinations of speed +boosters can enable, as you can see from the example where the CPU is running +at a speed faster than the min/max or base/boost values. Note that the normal \fBmin/max:\fR speeds do NOT show actual overclocked OR boost/turbo mode speeds, and appear to be hard\-coded values, not dynamic real @@ -1406,15 +1442,15 @@ Using \fBsmartctl\fR (requires doas[BSDs]/sudo/root privileges). \- Adds device kernel major:minor number (Linux only). -\- Adds SMART report line: status, enabled/disabled, health, powered on, -cycles, and some error cases if out of range values. Note that for Pre\-fail items, -it will show the VALUE and THRESHOLD numbers. It will also fall back for unknown -attributes that are or have been failing and print out the Attribute name, value, -threshold, and failing message. This way even for unhandled Attribute names, -you should get a solid report for full failure cases. Other cases may show -if inxi believes that the item may be approaching failure. This is a guess so -make sure to check the drive and smartctl full output to verify before -taking any further action. +\- Adds SMART report line: status, enabled/disabled, health, powered on, +cycles, and some error cases if out of range values. Note that for Pre\-fail +items, it will show the VALUE and THRESHOLD numbers. It will also fall back +for unknown attributes that are or have been failing and print out the +Attribute name, value, threshold, and failing message. This way even for +unhandled Attribute names, you should get a solid report for full failure +cases. Other cases may show if inxi believes that the item may be approaching +failure. This is a guess so make sure to check the drive and smartctl full +output to verify before taking any further action. \- Adds, for USB or other external drives, actual model name/serial if available, and different from enclosure model/serial, and corrects block @@ -1445,17 +1481,19 @@ and \fBMonitors\fR are referring to the \fBX\fR technical terms, not normal consumer usage. 1 \fBDisplay\fR runs 1 or more \fBScreens\fR, and a \fBScreen\fR runs 1 or more \fBMonitors\fR. -\- Adds \fBDisplay\fR ID, for the Display running the Screen that runs the Monitors. +\- Adds \fBDisplay\fR ID, for the Display running the Screen that runs the +Monitors. \- Adds total number of \fBScreens\fR listed for the current \fBDisplay\fR. -\- Adds default \fBScreen\fR ID if Screen (not monitor!) total is greater than 1. +\- Adds default \fBScreen\fR ID if Screen (not monitor!) total is greater than +1. -\- Adds \fBScreen\fR line, which includes the ID (\fBScreen: 0\fR) then \fBs-res\fR -(Screen resolution), \fBs\-dpi\fR, \fBs\-size\fR and \fBs\-diag\fR. Remember, this is an -Xorg \fBScreen\fR, NOT a monitor screen, and the information listed is about -the Xorg Screen! It may at times be the same as a single monitor system, -but usually it's different in some ways. +\- Adds \fBScreen\fR line, which includes the ID (\fBScreen: 0\fR) then +\fBs-res\fR (Screen resolution), \fBs\-dpi\fR, \fBs\-size\fR and \fBs\-diag\fR. +Remember, this is an Xorg \fBScreen\fR, NOT a monitor screen, and the +information listed is about the Xorg Screen! It may at times be the same as a +single monitor system, but usually it's different in some ways. \- Adds \fBMonitor\fR ID(s). Monitors are a subset of a Screen, each of which can have one or more monitors. Normally a dual monitor setup is 2 monitors @@ -1494,11 +1532,11 @@ Monitor\-2: VGA\-0 res: 1280x1024 hz: 60 dpi: 86 size: 376x301mm (14.8x11.9") diag: 482mm (19") ....\fR .fi -\- Adds, if present, possible \fBalternate:\fR kernel modules capable of driving -each \fBDevice\-x\fR (not including the current \fBloaded:\fR). If no non\-driver -modules found, shows nothing. NOTE: just because it lists a module does NOT mean it is -available in the system, it's just something the kernel knows could possibly be used -instead. +\- Adds, if present, possible \fBalternate:\fR kernel modules capable of +driving each \fBDevice\-x\fR (not including the current \fBloaded:\fR). If no +non\-driver modules found, shows nothing. NOTE: just because it lists a module +does NOT mean it is available in the system, it's just something the kernel +knows could possibly be used instead. .TP .B \-a \-I\fR @@ -1512,12 +1550,12 @@ Info: .... Init: systemd v: 245 runlevel: 5 Compilers: gcc: 9.3.0 alt: 5/6/7/8/9 Packages: apt: 3681 lib: 2096 rpm: 0 Shell: ksh v: A_2020.0.0 default: Bash - v: 5.0.16 running\-in: kate inxi: 3.1.04 + v: 5.0.16 running\-in: kate inxi: 3.1.04\fR .fi \- Adds service control tool, tested for in the following order: \fBsystemctl -rc-service service sv /etc/rc.d /etc/init.d\fR - useful to know which you need -when using an unfamiliar machine. +rc-service rcctl service sv /etc/rc.d /etc/init.d\fR - useful to know which +you need when using an unfamiliar machine. .TP .B \-a \-j\fR, \fB\-a \-P\fR [swap], \fB\-a \-P\fR [swap] @@ -1537,26 +1575,27 @@ For \fB\-j\fR row 1 output: .TP .B \-a \-L\fR -\- Expands Component report, shows size / maj-min of components and devices, and -mapped name for logical components. Puts each component/device on its own line. +\- Expands Component report, shows size / maj-min of components and devices, +and mapped name for logical components. Puts each component/device on its own +line. \- Adds maj-min to LV and other devices. .TP .B \-a \-n\fR, \fB\-a \-N\fR, \fB\-a \-i\fR -\- Adds, if present, possible \fBalternate:\fR kernel modules capable of driving -each \fBDevice\-x\fR (not including the current \fBdriver:\fR). If no non\-driver -modules found, shows nothing. NOTE: just because it lists a module does NOT mean it is -available in the system, it's just something the kernel knows could possibly be used -instead. - +\- Adds, if present, possible \fBalternate:\fR kernel modules capable of +driving each \fBDevice\-x\fR (not including the current \fBdriver:\fR). If no +non\-driver modules found, shows nothing. NOTE: just because it lists a module +does NOT mean it is available in the system, it's just something the kernel +knows could possibly be used instead. .TP .B \-a \-o\fR \- Adds device kernel major:minor number (Linux only). .TP .B \-a \-p\fR,\fB\-a \-P\fR -\- Adds raw partition size, including file system overhead, partition table, e.g. +\- Adds raw partition size, including file system overhead, partition table, +e.g. \fBraw\-size: 60.00 GiB\fR. @@ -1579,8 +1618,8 @@ not the raw size. .B \-a \-R\fR \- Adds device kernel major:minor number (mdraid, Linux only). -\- Adds, if available, component size, major:minor number, state (Linux only). -Turns Component report to 1 component per line if size and major:minor present. +\- Adds, if available, component size, major:minor number (Linux only). Turns +Component report to 1 component per line. .TP .B \-a \-S\fR @@ -1612,18 +1651,19 @@ Curl, Wget, Fetch, OpenBSD only: ftp .TP .B \-\-alt 44\fR Bypass \fBCurl\fR, \fBFetch\fR, and \fBWget\fR as downloader options. This -basically forces the downloader selection to use \fBPerl 5.x\fR \fBHTTP::Tiny\fR, -which is generally slower than \fBCurl\fR or \fBWget\fR but it may help bypass -issues with downloading. +basically forces the downloader selection to use \fBPerl 5.x\fR +\fBHTTP::Tiny\fR, which is generally slower than \fBCurl\fR or \fBWget\fR but +it may help bypass issues with downloading. .TP -.B \-\-bt\-tool [bt\-adapter|hciconfig]\fR +.B \-\-bt\-tool [bt\-adapter|hciconfig|rfkill]\fR Force the use of the given tool for bluetooth report (\fB\-E\fR). +\fBrfkill\fR does not support mac address data. .TP .B \-\-dig\fR -Temporary override of \fBNO_DIG\fR configuration item. Only use to test w/wo dig. -Restores default behavior for WAN IP, which is use dig if present. +Temporary override of \fBNO_DIG\fR configuration item. Only use to test w/wo +dig. Restores default behavior for WAN IP, which is use dig if present. .TP .B \-\-display [:]\fR @@ -1632,13 +1672,13 @@ Default gets display info from display \fB:0\fR. If you use the format \fB\-\-display :1\fR then it would get it from display \fB1\fR instead, or any display you specify. -Note that in some cases, \fB\-\-display\fR will cause inxi to hang endlessly when -running the option in console with Intel graphics. The situation regarding -other free drivers such as nouveau/ATI is currently unknown. It may be that +Note that in some cases, \fB\-\-display\fR will cause inxi to hang endlessly +when running the option in console with Intel graphics. The situation regarding +other free drivers such as nouveau/ATI is currently unknown. It may be that this is a bug with the Intel graphics driver \- more information is required. -You can test this easily by running the following command out of X/display server: -\fBglxinfo \-display :0\fR +You can test this easily by running the following command out of X/display +server: \fBglxinfo \-display :0\fR If it hangs, \fB\-\-display\fR will not work. @@ -1657,8 +1697,8 @@ as a comma separated list: \fBinxi \-MJ --force dmidecode,lsusb\fR -\- \fBdmidecode\fR \- Force use of \fBdmidecode\fR. This will override \fB/sys\fR -data in some lines, e.g. \fB\-M\fR or \fB\-B\fR. +\- \fBdmidecode\fR \- Force use of \fBdmidecode\fR. This will override +\fB/sys\fR data in some lines, e.g. \fB\-M\fR or \fB\-B\fR. \- \fBhddtemp\fR \- Force use of hddtemp instead of /sys temp data for disks. @@ -1688,33 +1728,34 @@ other switches you use. .TP .B \-\-html\-wan\fR -Temporary override of \fBNO_HTML_WAN\fR configuration item. Only use to test w/wo -HTML downloaders for WAN IP. Restores default behavior for WAN IP, which is use HTML -downloader if present and if dig failed. +Temporary override of \fBNO_HTML_WAN\fR configuration item. Only use to test +w/wo HTML downloaders for WAN IP. Restores default behavior for WAN IP, which +is use HTML downloader if present and if dig failed. .TP .B \-\-limit [\-1 \- x]\fR -Raise or lower max output limit of IP addresses for \fB\-i\fR. \fB\-1\fR removes limit. +Raise or lower max output limit of IP addresses for \fB\-i\fR. \fB\-1\fR +removes limit. .TP .B \-\-man\fR -Updates / installs man page with \fB\-U\fR if \fBpinxi\fR or using \fB\-U 3\fR dev branch. -(Only active if \fB\-U\fR is is not disabled by maintainers). +Updates / installs man page with \fB\-U\fR if \fBpinxi\fR or using \fB\-U 3\fR +dev branch. (Only active if \fB\-U\fR is is not disabled by maintainers). .TP .B \-\-no\-dig\fR Overrides default use of \fBdig\fR to get WAN IP address. Allows use of normal -downloader tool to get IP addresses. Only use if dig is failing, since dig is much -faster and more reliable in general than other methods. - +downloader tool to get IP addresses. Only use if dig is failing, since dig is +much faster and more reliable in general than other methods. .TP .B \-\-no\-doas\fR -Skips the use of doas to run certain internal features (like \fBhddtemp\fR, \fBfile\fR) -with doas. Not related to running inxi itself with doas/sudo or super user. -Some systems will register errors which will then trigger admin emails in such cases, so if -you want to disable regular user use of doas (which requires configuration to setup -anyway for these options) just use this option, or \fBNO_DOAS\fR configuration item. -See \fB\-\-no\-sudo\fR if you need to disable both types. +Skips the use of doas to run certain internal features (like \fBhddtemp\fR, +\fBfile\fR) with doas. Not related to running inxi itself with doas/sudo or +super user. Some systems will register errors which will then trigger admin +emails in such cases, so if you want to disable regular user use of doas +(which requires configuration to setup anyway for these options) just use +this option, or \fBNO_DOAS\fR configuration item. See \fB\-\-no\-sudo\fR if +you need to disable both types. .TP .B \-\-no\-host\fR @@ -1722,6 +1763,7 @@ Turns off hostname in System line. This is default when using \fB\-z\fR, for anonymizing inxi output for posting on forums or IRC. Overrides configuration value (if set): indent\-min + \fBSHOW_HOST='true'\fR \- Same as: \fBSHOW_HOST='false'\fR This is an absolute override, the host will not show no matter what other @@ -1729,19 +1771,21 @@ switches you use. .TP .B \-\-no\-html-wan\fR -Overrides use of HTML downloaders to get WAN IP address. Use either only dig, or -do not get wan IP. Only use if dig is failing, and the HTML downloaders are taking -too long, or are hanging or failing. +Overrides use of HTML downloaders to get WAN IP address. Use either only dig, +or do not get wan IP. Only use if dig is failing, and the HTML downloaders are +taking too long, or are hanging or failing. + Make permanent with \fBNO_HTML_WAN='true'\fR .TP .B \-\-no\-man\fR -Disables man page install with \fB\-U\fR for master and active development branches. -(Only active if \fB\-U\fR is is not disabled by maintainers). +Disables man page install with \fB\-U\fR for master and active development +branches. (Only active if \fB\-U\fR is is not disabled by maintainers). .TP .B \-\-no\-sensor\-force\fR -Overrides user set \fBSENSOR_FORCE\fR configuration value. Restores default behavior. +Overrides user set \fBSENSOR_FORCE\fR configuration value. Restores default +behavior. .TP .B \-\-no\-ssl\fR @@ -1752,11 +1796,12 @@ lists, or if you have problems making a connection for any reason. Works with .TP .B \-\-no\-sudo\fR -Skips the use of sudo to run certain internal features (like \fBhddtemp\fR, \fBfile\fR) -with sudo. Not related to running inxi itself with sudo or super user. -Some systems will register errors which will then trigger admin emails in such cases, so if -you want to disable regular user use of sudo (which requires configuration to setup -anyway for these options) just use this option, or \fBNO_SUDO\fR configuration item. +Skips the use of sudo to run certain internal features (like \fBhddtemp\fR, +\fBfile\fR) with sudo. Not related to running inxi itself with sudo or +superuser. Some systems will register errors which will then trigger admin +emails in such cases, so if you want to disable regular user use of sudo (which +requires configuration to setup anyway for these options) just use this option, +or \fBNO_SUDO\fR configuration item. .TP .B \-\-output [json|screen|xml]\fR @@ -1770,14 +1815,14 @@ Required for non\-screen \fB\-\-output\fR formats (json|xml). .TP .B \-\-partition\-sort [dev\-base|fs|id|label|percent\-used|size|uuid|used]\fR -Change default sort order of partition output. Corresponds to \fBPARTITION_SORT\fR -configuration item. These are the available sort options: +Change default sort order of partition output. Corresponds to +\fBPARTITION_SORT\fR configuration item. These are the available sort options: \fBdev\-base\fR - \fB/dev\fR partition identifier, like \fB/dev/sda1\fR. Note that it's an alphabetic sort, so \fBsda12\fR is before \fBsda2\fR. -\fBfs\fR \- Partition filesystem. Note that sorts will be somewhat random if all -filesystems are the same. +\fBfs\fR \- Partition filesystem. Note that sorts will be somewhat random if +all filesystems are the same. \fBid\fR \- Mount point of partition (default). @@ -1794,8 +1839,9 @@ sort will be random. .TP .B \-\-pm\-type [package manager name]\fR -For distro package maintainers only, and only for non apt, rpm, or pacman based systems. -To be used to test replacement package lists for recommends for that package manager. +For distro package maintainers only, and only for non apt, rpm, or pacman +based systems. To be used to test replacement package lists for recommends +for that package manager. .TP .B \-\-sensors\-default\fR @@ -1804,40 +1850,44 @@ on a one time basis. .TP .B \-\-sensors\-exclude\fR -Similar to \fB\-\-sensors\-use\fR except removes listed sensors from sensor data. -Make permanent with \fBSENSORS_EXCLUDE\fR configuration item. Note that gpu, network, -disk, and other specific device monitor chips are excluded by default. +Similar to \fB\-\-sensors\-use\fR except removes listed sensors from sensor +data. Make permanent with \fBSENSORS_EXCLUDE\fR configuration item. Note that +gpu, network, disk, and other specific device monitor chips are excluded by +default. Example: \fBinxi \-sxx \-\-sensors\-exclude k10temp-pci-00c3\fR .TP .B \-\-sensors\-use\fR -Use only the (comma separated) sensor arrays for \fB\-s\fR output. Make permanent -with \fBSENSORS_USE\fR configuration item. Sensor array ID value must be the exact -value shown in lm\-sensors sensors output (Linux/lm-sensors only). If you only want -to exclude one (or more) sensors from the output, use \fB\-\-sensors\-exlude\fR. +Use only the (comma separated) sensor arrays for \fB\-s\fR output. Make +permanent with \fBSENSORS_USE\fR configuration item. Sensor array ID value +must be the exact value shown in lm\-sensors sensors output (Linux/lm-sensors +only). If you only want to exclude one (or more) sensors from the output, +use \fB\-\-sensors\-exlude\fR. -Can be useful if the default sensor data used by inxi is not from the right sensor -array. Note that all other sensor data will be removed, which may lead to undesired -consequences. Please be aware that this can lead to many undesirable side\-effects, -since default behavior is to use all the sensors arrays and select which values -to use from them following a set sequence of rules. So if you force one to be used, -you may lose data that was used from another one. +Can be useful if the default sensor data used by inxi is not from the right +sensor array. Note that all other sensor data will be removed, which may lead +to undesired consequences. Please be aware that this can lead to many +undesirable side\-effects, since default behavior is to use all the sensors +arrays and select which values to use from them following a set sequence of +rules. So if you force one to be used, you may lose data that was used from +another one. -Most likely best use is when one (or two) of the sensor arrays has all the sensor data -you want, and you just want to make sure inxi doesn't use data from another array that -has inacurate or misleading data. +Most likely best use is when one (or two) of the sensor arrays has all the +sensor data you want, and you just want to make sure inxi doesn't use data +from another array that has inacurate or misleading data. -Note that gpu, network, disk, and other specific device monitor chips are excluded by -default, and should not be added since they do not provide cpu, board, system, etc, -sensor data. +Note that gpu, network, disk, and other specific device monitor chips are +excluded by default, and should not be added since they do not provide cpu, +board, system, etc, sensor data. Example: \fBinxi \-sxx \-\-sensors\-use nct6791-isa-0290,k10temp-pci-00c3\fR .TP .B \-\-sleep [0\-x.x]\fR Usually in decimals. Change CPU sleep time for \fB\-C\fR (current: \fB\0.35\fR). -Sleep is used to let the system catch up and show a more accurate CPU use. Example: +Sleep is used to let the system catch up and show a more accurate CPU use. +Example: \fBinxi \-Cxxx \-\-sleep 0.15\fR @@ -1847,21 +1897,21 @@ Overrides default internal value and user configuration value: .TP .B \-\-tty\fR -Forces internal IRC flag to off. Used in unhandled cases where the program running -inxi may not be seen as a shell/tty, but it is not an IRC client. Put \fB\-\-tty\fR -first in option list to avoid unexpected errors. If you want a specific -output width, use the \fB\-\-width\fR option. If you want normal color codes in -the output, use the \fB\-c [color ID]\fR flag. +Forces internal IRC flag to off. Used in unhandled cases where the program +running inxi may not be seen as a shell/tty, but it is not an IRC client. +Put \fB\-\-tty\fR first in option list to avoid unexpected errors. If you want +a specific output width, use the \fB\-\-width\fR option. If you want normal +color codes in the output, use the \fB\-c [color ID]\fR flag. -The sign you need to use this is extra numbers before the key/value pairs of the -output of your program. These are IRC, not TTY, color codes. Please post a github -issue if you find you need to use \fB\-\-tty\fR (including the full -\fB\-Ixxx\fR line) so we can figure out how to add your program to the list -of whitelisted programs. +The sign you need to use this is extra numbers before the key/value pairs of +the output of your program. These are IRC, not TTY, color codes. Please post a +github issue if you find you need to use \fB\-\-tty\fR (including the full +\fB\-Ixxx\fR line) so we can figure out how to add your program to the list of +whitelisted programs. -You can see what inxi believed started it in the \fB\-Ixxx\fR line, \fBShell:\fR or -\fBClient:\fR item. Please let us know what that result was so we can add it to the -parent start program whitelist. +You can see what inxi believed started it in the \fB\-Ixxx\fR line, +\fBShell:\fR or \fBClient:\fR item. Please let us know what that result was +so we can add it to the parent start program whitelist. .TP .B \-\-usb\-sys\fR @@ -1876,8 +1926,8 @@ Shortcut, legacy. See \fB\-\-force lsusb\fR Force \fB\-i\fR to use supplied URL as WAN IP source. Overrides dig or default IP source urls. URL must start with http[s] or ftp. -The IP address from the URL must be the last item on the last (non\-empty) line -of the page content source code. +The IP address from the URL must be the last item on the last (non\-empty) +line of the page content source code. Same as configuration value (example): @@ -1889,12 +1939,12 @@ Shortcut, legacy. See \fB\-\-force wmctl\fR. .TP .B \-\-wrap\-max [integer]\fR -Overrides default or configuration set line starter wrap width value. -Wrap max is the maximum width that inxi will wrap line starters (e.g. \fBInfo:\fR) -to their own lines, with data lines indented only 2 columns. If terminal/console -width or \fB\-\-width\fR is less than wrap width, wrapping of line starter occurs. -If \fB80\fR or less, no wrapping will occur. -Overrides internal default value (90) and user configuration value: +Overrides default or configuration set line starter wrap width value. Wrap +max is the maximum width that inxi will wrap line starters (e.g. \fBInfo:\fR) +to their own lines, with data lines indented only 2 columns. If +terminal/console width or \fB\-\-width\fR is less than wrap width, wrapping +of line starter occurs. If \fB80\fR or less, no wrapping will occur. Overrides +internal default value (90) and user configuration value: \fBWRAP_MAX=85\fR (previously \fBINDENT_MIN\fR) @@ -1910,14 +1960,12 @@ for Perl downloader. .TP .B \-\-dbg [2\-xx]\fR -\- See github \fBinxi-perl/docs/inxi-values.txt\fR for specific specialized debugging -options. These can vary but tend to not change much, though they are added as -needed. +\- See github \fBinxi-perl/docs/inxi-values.txt\fR for specific specialized +debugging options. .TP .B \-\-debug [1\-3]\fR -\- On screen debugger output. Output varies depending on current needs -Usually nothing changes. +\- On screen debugger output. .TP .B \-\-debug 10\fR @@ -1965,8 +2013,8 @@ use if you experienced a failure or hang, or were instructed to do so. .TP .B \-\-debug\-proc\fR -Force debugger to parse \fB/proc\fR directory data when run as root. Normally this is -disabled due to unpredictable data in /proc tree. +Force debugger to parse \fB/proc\fR directory data when run as root. Normally +this is disabled due to unpredictable data in /proc tree. .TP .B \-\-debug\-proc\-print\fR @@ -1993,9 +2041,9 @@ Force PowerPC debugger parsing of /sys as doas[BSDs]/sudo/root. Use this to locate file that /sys debugger hangs on. .SH SUPPORTED IRC CLIENTS -BitchX, Gaim/Pidgin, ircII, Irssi, Konversation, Kopete, KSirc, KVIrc, Weechat, -and Xchat. Plus any others that are capable of displaying either built\-in or external -script output. +BitchX, Gaim/Pidgin, ircII, Irssi, Konversation, Kopete, KSirc, KVIrc, +Weechat, and Xchat. Plus any others that are capable of displaying either +built\-in or external script output. .SH RUNNING IN IRC CLIENT To trigger inxi output in your IRC client, pick the appropriate method from the @@ -2011,8 +2059,8 @@ IRC client. .B /cmd inxi \fR[\fBoptions\fR] -To run inxi in Konversation as a native script if your distribution or inxi package -hasn't already done this for you, create this symbolic link: +To run inxi in Konversation as a native script if your distribution or inxi +package hasn't already done this for you, create this symbolic link: KDE 4: .B ln \-s /usr/local/bin/inxi /usr/share/kde4/apps/konversation/scripts/inxi @@ -2049,9 +2097,10 @@ have dropped the \fB\-curses\fR part of their program name, i.e.: inxi will read its configuration/initialization files in the following order: -\fB/etc/inxi.conf\fR contains the default configurations. These can be overridden -by user configurations found in one of the following locations (inxi will -store its config file using the following precedence: +\fB/etc/inxi.conf\fR contains the default configurations. These can be +overridden by user configurations found in one of the following locations +(inxi will store its config file using the following precedence: + if \fB$XDG_CONFIG_HOME\fR is not empty, it will go there, else if \fB$HOME/.conf/inxi.conf\fR exists, it will go there, and as a last default, the legacy location is used), i.e.: @@ -2074,44 +2123,49 @@ If terminal/console width or \fB\-\-width\fR is less than wrap width, wrapping of line starter occurs \fBCOLS_MAX_IRC\fR The max display column width on IRC clients. -\fBCOLS_MAX_NO_DISPLAY\fR The max display column width in console, out of GUI desktop. +\fBCOLS_MAX_NO_DISPLAY\fR The max display column width in console, out of GUI +desktop. -\fBCPU_SLEEP\fR Decimal value \fB0\fR or more. Default is usually around \fB0.35\fR -seconds. Time that inxi will 'sleep' before getting CPU speed data, so that it -reflects actual system state. +\fBCPU_SLEEP\fR Decimal value \fB0\fR or more. Default is usually around +\fB0.35\fR seconds. Time that inxi will 'sleep' before getting CPU speed data, +so that it reflects actual system state. \fBDOWNLOADER\fR Sets default inxi downloader: curl, fetch, ftp, perl, wget. -See \fB\-\-recommends\fR output for more information on downloaders and Perl downloaders. +See \fB\-\-recommends\fR output for more information on downloaders and Perl +downloaders. -\fBFILTER_STRING\fR Default \fB\fR. Any string you prefer to see instead -for filtered values. +\fBFILTER_STRING\fR Default \fB\fR. Any string you prefer to see +instead for filtered values. -\fBLIMIT\fR Overrides default of \fB10\fR IP addresses per IF. This is only of interest -to sys admins running servers with many IP addresses. +\fBLIMIT\fR Overrides default of \fB10\fR IP addresses per IF. This is only of +interest to sys admins running servers with many IP addresses. -\fBNO_DIG\fR Set to \fB1\fR or \fBtrue\fR to disable WAN IP use of \fBdig\fR and force -use of alternate downloaders. +\fBNO_DIG\fR Set to \fB1\fR or \fBtrue\fR to disable WAN IP use of \fBdig\fR +and force use of alternate downloaders. -\fBNO_DOAS\fR Set to \fB1\fR or \fBtrue\fR to disable internal use of \fBdoas\fR. +\fBNO_DOAS\fR Set to \fB1\fR or \fBtrue\fR to disable internal use of +\fBdoas\fR. -\fBNO_HTML_WAN\fR Set to \fB1\fR or \fBtrue\fR to disable WAN IP use of \fBHTML Downloaders\fR and force -use of dig only, or nothing if dig disabled as well. Same as \fB\-\-no\-html\-wan\fR. Only use if -dig is failing, and HTML downloaders are hanging. +\fBNO_HTML_WAN\fR Set to \fB1\fR or \fBtrue\fR to disable WAN IP use of +\fBHTML Downloaders\fR and force use of dig only, or nothing if dig disabled +as well. Same as \fB\-\-no\-html\-wan\fR. Only use if dig is failing, and +HTML downloaders are hanging. -\fBNO_SUDO\fR Set to \fB1\fR or \fBtrue\fR to disable internal use of \fBsudo\fR. +\fBNO_SUDO\fR Set to \fB1\fR or \fBtrue\fR to disable internal use of +\fBsudo\fR. \fBPARTITION_SORT\fR Overrides default partition output sort. See \fB\-\-partition\-sort\fR for options. -\fBPS_COUNT\fR The default number of items showing per \fB\-t\fR type, \fBm\fR or -\fBc\fR. Default is 5. +\fBPS_COUNT\fR The default number of items showing per \fB\-t\fR type, \fBm\fR +or \fBc\fR. Default is 5. -\fBSENSORS_CPU_NO\fR In cases of ambiguous temp1/temp2 (inxi can't figure out which -is the CPU), forces sensors to use either value 1 or 2 as CPU temperature. See the -above configuration page on smxi.org for full info. +\fBSENSORS_CPU_NO\fR In cases of ambiguous temp1/temp2 (inxi can't figure out +which is the CPU), forces sensors to use either value 1 or 2 as CPU +temperature. See the above configuration page on smxi.org for full info. -\fBSENSORS_EXCLUDE\fR Exclude supplied sensor array[s] from sensor output. Override with -\fB\-\-sensors\-default\fR. See \fB\-\-sensors\-exclude\fR. +\fBSENSORS_EXCLUDE\fR Exclude supplied sensor array[s] from sensor output. +Override with \fB\-\-sensors\-default\fR. See \fB\-\-sensors\-exclude\fR. \fBSENSORS_USE\fR Use only supplied sensor array[s]. Override with \fB\-\-sensors\-default\fR. See \fB\-\-sensors\-use\fR. @@ -2120,40 +2174,42 @@ above configuration page on smxi.org for full info. \fBUSB_SYS\fR Forces all USB data to use \fB/sys\fR instead of \fBlsusb\fR. -\fBWAN_IP_URL\fR Forces \fB\-i\fR to use supplied URL, and to not use dig (dig is -generally much faster). URL must begin with http or ftp. Note that if you use this, -the downloader set tests will run each time you start inxi whether a downloader feature -is going to be used or not. +\fBWAN_IP_URL\fR Forces \fB\-i\fR to use supplied URL, and to not use dig +(dig is generally much faster). URL must begin with http or ftp. Note that if +you use this, the downloader set tests will run each time you start inxi +whether a downloader feature is going to be used or not. -The IP address from the URL must be the last item on the last (non\-empty) line of -the URL's page content source code. +The IP address from the URL must be the last item on the last (non\-empty) +line of the URL's page content source code. Same as \fB\-\-wan\-ip\-url [URL]\fR -\fBWEATHER_SOURCE\fR Values: [\fB0-9\fR]. Same as \fB\-\-weather\-source\fR. Values -4\-9 are not currently supported, but this can change at any time. +\fBWEATHER_SOURCE\fR Values: [\fB0-9\fR]. Same as \fB\-\-weather\-source\fR. +Values 4\-9 are not currently supported, but this can change at any time. -\fBWEATHER_UNIT\fR Values: [\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR]. Same as \fB\-\-weather\-unit\fR. +\fBWEATHER_UNIT\fR Values: [\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR]. Same as +\fB\-\-weather\-unit\fR. -\fBWRAP_MAX\fR (previously \fBINDENT_MIN\fR) The maximum width where the line starter wraps -to its own line. If terminal/console width or \fB\-\-width\fR is less than wrap width, -wrapping of line starter occurs. Overrides default. See \fB\-\-wrap\-max\fR. -If \fB80\fR or less, wrap will never happen. +\fBWRAP_MAX\fR (previously \fBINDENT_MIN\fR) The maximum width where the line +starter wraps to its own line. If terminal/console width or \fB\-\-width\fR is +less than wrap width, wrapping of line starter occurs. Overrides default. +See \fB\-\-wrap\-max\fR. If \fB80\fR or less, wrap will never happen. .TP .B Color Options -It's best to use the \fB\-c [94\-99]\fR color selector tool to set the following values -because it will correctly update the configuration file and remove any invalid -or conflicting items, but if you prefer to create your own configuration files, -here are the options. All take the integer value from the options available in -\fB\-c 94\-99\fR. +It's best to use the \fB\-c [94\-99]\fR color selector tool to set the +following values because it will correctly update the configuration file and +remove any invalid or conflicting items, but if you prefer to create your own +configuration files, here are the options. All take the integer value from the +options available in \fB\-c 94\-99\fR. -NOTE: All default and configuration file set color values are removed when output is -piped or redirected. You must use the explicit \fB\-c \fR option -if you want colors to be present in the piped/redirected output (creating a PDF for -example). +NOTE: All default and configuration file set color values are removed when +output is piped or redirected. You must use the explicit +\fB\-c \fR option if you want colors to be present in the +piped/redirected output (creating a PDF for example). -\fBCONSOLE_COLOR_SCHEME\fR The color scheme for console output (not in X/Wayland). +\fBCONSOLE_COLOR_SCHEME\fR The color scheme for console output (not in +X/Wayland). \fBGLOBAL_COLOR_SCHEME\fR Overrides all other color schemes. @@ -2163,15 +2219,16 @@ example). \fBIRC_X_TERM_COLOR_SCHEME\fR In X/Wayland IRC client terminal color scheme. -\fBVIRT_TERM_COLOR_SCHEME\fR Color scheme for virtual terminal output (in X/Wayland). +\fBVIRT_TERM_COLOR_SCHEME\fR Color scheme for virtual terminal output (in +X/Wayland). .SH BUGS Please report bugs using the following resources. -You may be asked to run the inxi debugger tool (see \fB\-\-debug 21/22\fR), which will -upload a data dump of system files for use in debugging inxi. These data dumps are -very important since they provide us with all the real system data inxi uses to parse -out its report. +You may be asked to run the inxi debugger tool (see \fB\-\-debug 21/22\fR), +which will upload a data dump of system files for use in debugging inxi. These +data dumps are very important since they provide us with all the real system +data inxi uses to parse out its report. .TP .B Issue Report File an issue report: @@ -2206,7 +2263,8 @@ maintained by Harald Hope (aka h2 or TechAdmin). Initial CPU logic, konversation version logic, occasional maintenance fixes, and the initial xiin.py tool for /sys parsing (obsolete, but still very much -appreciated for all the valuable debugger data it helped generate): Scott Rogers +appreciated for all the valuable debugger data it helped generate): +Scott Rogers Further fixes (listed as known): @@ -2214,18 +2272,19 @@ Horst Tritremmel Steven Barrett (aka: damentz) \- USB audio patch; swap percent used patch. -Jarett.Stevens \- \fBdmidecode \-M\fR patch for older systems with no \fB/sys\fR. +Jarett.Stevens \- \fBdmidecode \-M\fR patch for older systems with no +\fB/sys\fR. .SH SPECIAL THANKS TO THE FOLLOWING The nice people at irc.oftc.net channels #linux\-smokers\-club and #smxi, who all really have to be considered to be co\-developers because of their -non\-stop enthusiasm and willingness to provide real\-time testing and debugging -of inxi development. +non\-stop enthusiasm and willingness to provide real\-time testing and +debugging of inxi development. -Siduction forum members, who have helped get some features working by providing -a large number of datasets that have revealed possible variations, particularly for the -RAM \fB\-m\fR option. +Siduction forum members, who have helped get some features working by providing +a large number of datasets that have revealed possible variations, particularly +for the RAM \fB\-m\fR option. AntiX users and admins, who have helped greatly with testing and debugging, particularly for the 3.0.0 release. @@ -2234,19 +2293,23 @@ ArcherSeven (Max), Brett Bohnenkamper (aka KittyKatt), and Iotaka, who always manage to find the weirdest or most extreme hardware and setups that help make inxi much more robust. -For the vastly underrated skill of output error/glitch catching, Pete Haddow. His -patience and focus in going through inxi repeatedly to find errors and inconsistencies -is much appreciated. +For the vastly underrated skill of output error/glitch catching, Pete Haddow. +His patience and focus in going through inxi repeatedly to find errors and +inconsistencies is much appreciated. + +For a huge boost to BSD support, Stan Vandiver, who did a lot of testing +and setup many remote access systems for testing and development. All the inxi package maintainers, distro support people, forum moderators, and in particular, sys admins with their particular issues, which almost always -help make inxi better, and any others who contribute ideas, suggestions, and patches. +help make inxi better, and any others who contribute ideas, suggestions, and +patches. -Without a wide range of diverse Linux kernel\-based Free Desktop systems to test -on, we could never have gotten inxi to be as reliable and solid as it's turning -out to be. +Without a wide range of diverse Linux kernel\-based Free Desktop systems to +test on, we could never have gotten inxi to be as reliable and solid as it's +turning out to be. -And of course, a big thanks to locsmif, who figured out a lot of the core methods, -logic, and tricks originally used in inxi Gawk/Bash. +And of course, a big thanks to locsmif, who figured out a lot of the core +ideas, logic, and tricks originally used in inxi Gawk/Bash. .\" EOF diff --git a/inxi.changelog b/inxi.changelog index 6925b0b..9916815 100644 --- a/inxi.changelog +++ b/inxi.changelog @@ -1,778 +1,1292 @@ -===================================================================================== +================================================================================ +Version: 3.3.04 +Patch: 00 +Date: 2021-04-16 +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- + +Enhanced features!! Huge BSD upgrades! Bug Fixes!! Elbrus Fixes!! More bluetooth +fixes!! What are you waiting for?!!? + +A special thanks for significant help, ongoing, leading to a huge boost to BSD +support, Stan Vandiver, who did a lot of BSD testing, and setup many remote +access systems for testing and development of the latest BSD upgrades. If you're +a BSD user, you can thank him for helping to expand BSD support! + +An ongoing thanks to Mr. Mazda, for continuous testing, suggestions, and helpful +ideas. + +Take special note of the code folding fixes in Fix 1, those open up possible +free software code editors that can be used to work with inxi to more than just +Kwrite/Kate, to include scite and geany, nice lightweight code editors. You +can't do real work in inxi without code folding, so getting this finally +resolved was I think worth it. + +Also, for the first time ever!! inxi is now using Pledge, well, if +OpenBSD::Pledge module is available, which is currently only in OpenBSD, since +that's the only system that supports Pledge security, except for Serenity, but +inxi doesn't support Serenity. Note that OpenBSD was smart and added +OpenBSD::Pledge and OpenBSD::Unveil to Perl Core modules, thus removing any hoop +that might stop a Perl program from implementing it. Nice going OpenBSD guys! + +The addition of OpenBSD softraid support for RAID and CRYPTO types highlights +the problem with --raid and --logical, where --raid is really just a subset of +Logical volume management. Note that while the hardware RAID feature only lists +the actual PCI RAID device, OpenBSD bioctl supports hardware RAID out of the +box, something I'd thought of doing in inxi for a few years, but it's too much +work, but bioctl has done the work, which is impressive. Can't do much without a +lot of debugger data there though, but it's worth being aware of. In this case, +since softraid is the primary device, I opted to call Crypto and RAID types all +RAID, same as with linear zfs. + +-------------------------------------------------------------------------------- +KNOWN ISSUES BUT CAN'T OR WON'T BE FIXED: + +1. FreeBSD: USB drivers. I really gave this a try, but could not get any logic +to be stable across systems and varying syntaxes used. Will wait for FreeBSD to +add drivers to usbconfig -vl. Note that this makes it not possible to correctly +match USB networking devices to their respective IF data, so USB networking IF +will fall back to the undetected IF-ID, which means it was found but not +connected to a specific hardware device. + +2. FreeBSD Battery Report: there are non-objective values for Battery state data +in sysctl output, as in minutes remaining, which has no meaning, and percent +charge (percent of what? original design capacity? current actual capacity?). If +data with voltages, design/current capacity in Ah or Wh, is made available, +support will be added. Note that there are 3rd party tools that do supply this +data in a usable format, but they are not in core so no point. + +3. BSDs All: have found no way to get physical CPU counts. this will lead to odd +outputs in some cases, like a 2 cpu system reporting itself as a 2x the actual +core counts single CPU, but the data just isn't there as far as I know. +Dragonfly in some cases appears to have that data. + +4. BSDs All: so far no way to get live per core cpu speeds using a file or fast +command query. Thought I'd found a way in FreeBSD but that was not the correct +clockrate values, or inconsistently right/wrong, so not using it. Also saw the +same issue with max/min frequencies in FreeBSD so removed that item, it's +better to show nothing than data that is not reliable or actually not even +referring to what it seems to be. + +5. BSD SOC Support: An issue poster asked why FreeBSD (but really BSD in +general) SOC ARM device, like RaPi, support, was so weak in inxi. The reason is +simple: to do SOC ARM device data in a meaningful way requires a complete path +based data structure, which the BSDs do not appear to have, at least from what +I've seen so far. See Linux's /sys data structures for examples of what is +required to add or expand inxi SOC device support in inxi. It's hard even with +that type of rich path based data, and without it I won't try. + +The bright side is inxi runs perfectly on such devices, no errors, which was +amazing to see, and spoke volumes of the recent work done to extend support for +the BSDs. + +6. Perl / inxi, when run as root, shows read error when trying to open a 200 / +--w------- permission /sys uevent file for reading. The test works as expected +as user, but not as root. Perl will try to read it when run as root even though +it has no read permissions, only write. This in reality only manifests on very +old /sys, from Debian Etch kernel 2.26 days. + +-------------------------------------------------------------------------------- +BUGS: + +1. tput + urxvt / FreeBSD: There appears to be a bug in Arch Linux urxvt that +leads to failed terminal/console size from tput. Also while trying to resolve +this bug, discovered that if you use "tput cols 2>/dev/null" in FreeBSD, for +some inexplicable reason tput puts out defaults 80 cols x 24 rows. Why? Who +knows. Added in non numeric tests of output to handle errors from tput instead. + +The bug appears to be what rxvt reports itself as vs what it is actually running +as. This issue isn't present in any other distro I tried, but could just be a +new bug in urxvt, don't know. + +2. Elbrus CPU: Ongoing issue #197 Elbrus poster gave sample of new 2C3 cpuinfo, +that exposed some bugs internally in inxi Elbrus handling, I was using integer +values instead of hex for model IDs in the Elbrus logic, which would fail after +model 9. + +3. BSD dmesg.boot: The logic used for dmesg.boot data processing had errors, and +had to be fully redone because of the need to detect in a reliable way the +current state of USB drives. This logic now is much more robust and reliable, +and no longer relies on using 'uniq' values per line, which would fail in all +kinds of situations. + +4. OpenBSD USB Speeds: bugs fixed for OpenBSD speeds, these were found during +the USB data refactor testing process. + +5. BSDs: in some cases, wrong memory used values were being generated, this +should be largely corrected now. Also pulled the weird NetBSD use of +/proc/meminfo which had wrong data in it, and now use vmstat for all BSDs, which +after the used bug fixes, is more reliable for BSDs. + +6. All systems: CPU stepping would report as N/A if stepping 0, luckily I came +across some systems with an actual stepping: 0, which are not common. + +7. FreeBSD: dmidecode sourced L2 cache data failed to show correct totals in +some cases. Due to no MT detection possible for FreeBSD currently, these totals +will still be wrong, but now it says note; check to let users know. + +8. dmidecode: some cases were getting the wrong failure error message, this bug +became exposed due to OpenBSD locking /dev/mem even to root, which then failed +to show the expected message. This was a bug, and is now corrected. + +9. FreeBSD: partition swap size didn't show in at least some cases, that's +corrected. + +10. Linux Partitions: partitions would let doubled swap items through in several +cases, and also failed to create in rare cases matches for hidden partition +mapped id's. Finally tracked down the actual cause, when moving the partition +filters I'd forgotten to add swap into the filter list, oops. But now it will +catch duplicates in several different ways, so that's fine. + +11. Unmounted: Failed to properly handle detecting RAID components in the case +of lvm, mdraid, it was only working for zfs. This was an accident, and should +now be corrected. + +-------------------------------------------------------------------------------- +FIXES: + +1. Code Folding: Note that this was NOT a bug or failure in inxi, it was a bug +in scintilla/scite geany code editors with folding, basically if you commented +out logic, without using a space or other marker after the comment #, folding +would break in weird ways. Obviously the core scintilla engine should IGNORE the +darned # commented out lines, but it doesn't, which is a real bug. But not in +inxi. + +This was however worth working around, because without folding, you can't work +on or learn how inxi works, and the only editor I know of in the free software +eco-system that can handle folding reasonably accurately was until now +Kwrite/Kate code editors, and those have some real, long standing, weaknesses, +and bugs around folding that have never been resolved, and yes, did notify them +about them, and no, they remain unfixed after years, or they were fixed briefly, +then broke again. + +So it was important to expand the base of possible code editors to more than +just the KDE stuff. Fixing this was tedious, but I think worth it. On the bright +side, geany/scite folding / unfolding is FAST, and once the code issues that +triggered folding failures were resolved, very accurate, much better than Kate's +to be honest, though Kate isn't as picky, but Kate's unfold top nodes has been +broken more often than it's worked. + +To avoid this issue, it's also important to configure geany/scite to use a space +after the comment when using keyboard shortcuts to comment out lines/blocks. +Same goes for Kate/Kwrite, by the way. + +2. Battery: Forgot to add battery-force to -v7, which means you would never see +the battery line in full output if there was no battery present, this is similar +to how raid-forced worked, it was just an oversight which I hadn't noticed until +testing the new BSD battery logic. + +3. Indentation: small indentation fixes on Sound Server data. Those are visible +with -y1, that is. + +4. OpenBSD PCI: enabled Device matching to PCI networking device, this required +an odd little hack, but seems to be pretty reliable, and allowed me to add +driver to PCI device reports as well. Not sure why driver isn't in pcidump -v +but it probably will be in the future. Note to self: add in support for that so +if they include it in a future release, it will suddenly 'just work', assume +they use the same basic syntax as usbdevs -vv output. + +5. BSDs: Added in some null data protections for BSDs, which do not always have +all the data types found in Linux, those would trigger Perl undefined value +errors, which are warnings that inxi failed internally to test for null data in +that, but it's hard to know when to do that when the data is basically always +there in Linux. + +6. Debugger: Added test for required Net::FTP module in debugger, had forgotten +to make that test explicit, which led to odd failures. + +7. BSDs: nvme detections should be better now. But I have seen no live test +system to confirm the fixes work as expected, plus, at least, OpenBSD swaps +nvme0 to sd0 internally, so I'm not actually sure how that data will even work, +we'll see how that goes. + +8. BSDs: oddly, despite using 0x hex numbers almost everywhere, for CPU +stepping, the stepping is in decimal, which is even odder because CPU makers +list their steppings as hex in many if not most cases. In case this is corrected +in the future, if 0x appears before stepping number, will not then try to +convert to hex since it already is. + +9a. CPU L3: Subtle, probably won't change behaviors, but L3 cache is per physical +CPU in every case I've found, so never multiply value by cores for L3. Like +everything, this may lead to corner cases being wrong, but that's life, it will +also lead to the data being right for most users. + +9b. CPU L1: Different L1 syntaxes found so inxi now uses more loose detections, +should cover most OpenBSD L1 variants at least. + +10. BSDs: inxi was using internal 'sleep' right before reading /proc/cpuinfo, +but that was silly for BSDs since cpu speeds there come from sysctl, so the BSD +sleeps are now running before sysctl if CPU data feature is required. + +11. Too many to remember, but lots of subtle message output changes to make more +clear, more accurate, shorter, whatever. + +12. USB: a very subtle fix, some devices can be both audio and video, like +cameras, but inxi would default to the first detected. Now it checks for both +before going to the list of checks, and correctly assigns a type that is both +audio and video to the audio and video hashes so both features will show the USB +device, not just Audio. + +13: BSD: fixes for BSD ifconfig IF status, it was slicing off the full status +string, like 'no network' to 'no', which is silly. Now shows full string. + +14. OpenBSD: restored USB Hub ports: xx item, I hadn't realized that the data +was still there with usbdevs but it required an extra -v, like: usbdevs -vv to +trigger, so now the OpenBSD USB ports works fine again. + +15. Fedora Xorg: updated --recommends to use the newer split apart xorg utils +package names, only xrandr I think needed updating. Thanks Mr. Mazda for keeping +up with that stuff! + +16. OpenBSD SMART: the actual device being queried turns out to the 'c' +partition, the one that represents the entire disk, NOT the main device ID, like +sd0, so now inxi tacks on 'c', sd0c, when smartctl runs, and it works fine. So +previously SMART report would never have worked in OpenBSD. + +17. Partion labels/uuids: in Partitions and Unmounted, does not show label/uuid +if fs type is ffs or if fs is a logical type one, like zfs, hammer, and remote +fs mounts etc. This cleans up output, since these file system types will never +have labels or uuids. + +18. Mr Mazda inxi was missing data and showing errors if run in Debian Etch with +Perl 5.008, and I realized I'd slipped up and had used the -k option without +testing lspci version, but -k was only available in 3.0 in Lenny. But -v turns +on -k automatically, so the easy solution was just to remove the -k and leave +the -nnv, which is the same thing, but does not cause errors in early lspci. + +There are also errors with reading as root some /sys uevent files, but upon +examination, those had only root write permission, so the perl -r test isn't +right. Don't think that can be fixed. See Can't/Won't fix for more. + +Another issue I noticed was that in some cases Perl seemed to lose track of some +hash values in local %trigger in OptionsHandler, and just lose them, thus +leading to things like --help --version --recommends not working. Moving +%trigger to globals %show and %use fixed that one, but that's weird, no idea +what happened, but it works now. + +Tested in Sarge 3.1, where core modules have to be explicitly installed, they +were not included in base Perl install. Kernel 2.4 had some key differences, +different lspci syntax, different /proc/partitions, so the block device output +and device output is flawed, but otherwise inxi worked fine in Sarge, from 2005! +But these issues will not be corrected, kernel 2.24 is just too old, lol. + +inxi should always run ok in very old systems, like Etch, back to when Perl 5.8 +was standard, so bugs like this are always welcome, it's easy to slip up and use +something that didn't work in those old systems, then forget to test. + +19. Corner case SMART errors, sometimes occur much later in output than inxi +expects, this is now corrected and errors should show in smart data no matter +where the main error type occured. + +-------------------------------------------------------------------------------- +ENHANCEMENTS: + +1. Elbrus: Going along with Bug 2, Updated Elbrus microarch to use family 6, +assuming models 10, 11, are the same, which they should be since 12 is the same +as in family 4. + +2. IPMI Sensors: More sensor syntax detections, sensors will never be stable... + +3. OpenBSD: Rolled out live battery state feature, they have very good data, +simple, but solid, that allows for a quality battery state report. Handles both +Wh/Ah, though I am slightly suspicious of the reality of the arithmetic for Ah > +Wh conversion, it seems to be too high. That's Ah * Design Voltage. But Linux +battery data has the same issue, though I think in most cases, the data is in +Wh, so this issue isn't BSD specific. My suspicion is that the voltages used to +determine Ah may actually be slightly lower than the listed design voltage, +which inxi calls min: but it's actually the design voltage. + +Unknown if NetBSD data is the same as OpenBSD for battery, was unable to locate +any samples, so can't say, if you have a NetBSD laptop that correctly reports +battery state in sysctl -a, please file an issue with some sample battery +charge/voltage syntax and values, ideally from > 1 system. If the data is +complete, it's easy to add support. + +4a. BSD USB rev: inxi now emulates USB rev versions for BSD USB speed/rev +version data. Note that this is not guaranteed to be right, because USB devices +can be different rev versions than the speed they run at, but as far as I could +find, the USB revision data is not available in any practical sense, unless I +create a complicated recursive tool to build up a snapshot of the usb system and +devices from dmesg data, but I already blew a day on that attempt, so will wait +for more complete data in the usb tools in future. The rev version is based on +the device/hub speed, using a standard USB rev speed mapping. But a 12 Mbps +device can be rev 2, not rev 1.1, for example, that is, it's actually a USB 2.0 +device, but a slow speed one. + +4b. USB Type: Expanded fallback USB device type tests, these are useful for +cases where it's either a vendor defined type, or for Open/NetBSD, which do not +yet show USB class/subclass data. But it's a good fallback tool, added Mass +Storage, expanded detections. + +5. BSD Sensors: Going along with Enhancement 3, rolled out live sensors data. +Confirmed working in OpenBSD and FreeBSD, not sure about NetBSD, no data, +problem with vm testing is no sensors, but don't have any NetBSD hardware +installs to verify. Stan gave it a good try, but could not get NetBSD running so +far, maybe later. + +This basically means the -B and -s features are largely feature complete for the +BSDs as far as practical, though due to difficulties in getting the data in a +consistent clear way, some more advanced features, like gpu temps, which are now +available in Linux kernel values and lm-sensors, do not yet appear to be present +in the BSDs, though if this changes, the structures are in place to make +updates to these logics very easy to implement now. + +Note that the --sensors-include and --sensors-exclude items, or config items, +work fine with this BSD logic, though you have to figure out what exact syntax +to use, but that's the same in Linux. + +6. OpenBSD Pledge: Yes, that's right, inxi is now Pledged!!! In OpenBSD, anyway, +they did a really good job, and the OpenBSD Perl packager made a very nice Perl +modules, OpenBSD::Pledge, which was very easy to implement. Now I know what inxi +needs to run its features!! + +So far OpenBSD only, but Pledge seems like a really good idea, so I figured, +let's give it a spin, even if it will only currently work on OpenBSD, but that's +fine, inxi is pledged as tightly as I could make it, including unpledging +features not required post options processing, once inxi knows what it's +actually going to be doing. + +Note that I'm aware of OpenBSD::Unveil, but that's a lot harder to implement due +to never really being sure about what files inxi will need to be looking at +until well into the logic. I may look at that in the future. + +7. Bluetooth Rfkill: Due to ongoing failures in current inxi to show consistent +Bluetooth hci report on Linux, added in one last fallback, rfkill state, which +allows inxi to always fallback to at least that basic data. Also added in which +tool is providing the report mostly, like: Report: bt-adapter ID: hci0 and so +on. + +Also integrated into -xxx data, or for down state, the full rfkill report, since +that can be quite useful. + +Note that bluetooth is a real pain for users to debug because you can have: + + * Bluetooth Service: enabled/disabled * Bluetooth Service: started/stopped * +bluetoothctl: start/stop * bt-adapter: start/stop * hciconfig: start/stop * +rfkill: software: block/unblock; hardware: block/unblock - however, for +hardware, that means a physical button has been pressed to disable it, on the +laptop that is. + +To make matters worse, one tool does not always even know when another tool has +changed something, for example, if I rfkill blocked hci0, then unblocked it, +hciconfig would keep seeing it as down until it was switched to on with +hciconfig explicitly. This is I suspect one reason hciconfig is being dropped, +it doesn't know how to listen to the newer tools like bluetoothctl, bt-adapter, +or rfkill. + +8. OpenBSD: Going along with Code Change 1, now has disk serial (doas/root), +more consistent physical block size data, more reliable disk data, and for +-Dxxx, duid, if available. Also added disk partition table scheme, aka MBR / +GPT. Some of these new items may also work with NetBSD. See also Fix 17, SMART +fix for OpenBSD. + +9. OpenBSD/NetBSD/FreeBSD: the DiskDataBSD refactor now allows Unmounted +partitions report. + +10. OpenBSD: added in CPU MT detections using siblings data, I think only +OpenBSD and Dragonfly support proper MT cpu core counts. Still no way to get +physical cpu counts in OpenBSD or FreeBSD or NetBSD that I am aware of. + +11. OpenBSD: added in cpu speed min/max data, that was available in most cases, +didn't realize that. + +12. BSDs: expanded and made more robust cpu L1/L2/L3 cache detections, now for +example, OpenBSD will report its L1/L2/L3 cache without root. FreeBSD requires +root since that data is coming from dmidecode. + +This logic update made BSD L-cache data much more reliable and consistent, and, +important, easy to work with. This was directly connected to Code Changes 2 and +3, which made dealing with those data sources a lot easier. + +Note that L1/L2 cache data if not from OpenBSD will show note: check because +it's not possible to determine if it's a multithreaded MT cpu or not, and thus +if L1/L2 * core count would so often be totally wrong that inxi won't try to +guess, it will just list the single value found, and tell the user to check it +themselves. + +13. OpenBSD: Added rcctl tool to init tools, I hadn't known about that one, that +replaces the fallback default used before, /etc/rc.d. + +14. RAM Vendor: Issue #245 raised the point that it would be good to try to show +RAM vendor data when the manufactorer field is empty, and since that logic is +already present in disk_vendor, it was just matter of researching the product +IDs to find the matching patterns for the RAM vendors, the initial list is +pretty good, but will need updates now and then to correct errors. Also will +override only vendor ID 4 character hex value and see if it can find a better +value. + +15. OpenBSD RAM: data quality is decent (no vendor/product no, unfortunately). +The data is often, but sadly not always, available. I'm not clear why sometimes +it isn't, but since OpenBSD also defaults to blocking /dev/mem to even root +user, which then blocks dmidecode, this is the only practical way to give basic +RAM data for OpenBSD, so that's running fine now, when the data is available, +with the added bonus of not needing doas/root. + +Note that due to the way that this data is present, I can have inxi deduce some +things like how many arrays there are, and then guess at overall capacity, max +stick size, and so on, but all Array-x: values are followed by note: est because +they are never based on hard data, just extrapolations. I debated if inxi should +even show the guesses, but I think by saying note: est after each Array-x: item, +it's pretty clear that it's not hard data, and it does give an idea roughly. I +made an initial guess at > 1 ram array but found no data samples to let me see +if my guess was right or not, so > 1 array remains roughly theoretical until +shown to work or not work empirically. + +While NetBSD sometimes has the system ram data in a similar way that OpenBSD +does in dmesg.boot, it varies too much, and is too inconsistent. There are not +enough data samples with good consistent data, and the samples I did see +suggested that it would take too much code and convoluted logic to handle the +variations, so I'm leaving this one alone. Also, NetBSD probably doesn't block +/dev/mem so dmidecode should work fine. + +16. Using system clang version info for OpenBSD kernel compiler, the assumption +being that a BSD is an OS, so the Clang version it shipped with would be the +clang version that compiled the kernel. Please correct if this is wrong. + +17. OpenBSD RAID: support added for softraid, including for drive storage +totals, unmounted raid component detections. Plugged in pretty smoothly, able to +generate a partial report for non root, and shows message if not root. + +18. VM detections upgraded, particularly for BSDs, now includes vmm, hvm, +hyper-v, kvm. Not all of these would have been detected before. Also cleaned up +vm logic, moved all vm detections into $dboot{'machine-vm'}, and only use the +first found item. + +19. Disk Vendors!!: Yes, last, but not least!! More disk vendors, vendor ID +matches!! Yep. What else can I say? Eternity? Man's quest for something that +cannot be found, yet these strivings never cease, here manifested by always new +vendors and ID matches! + +-------------------------------------------------------------------------------- +DOCUMENTATION: + +1. Very significant ongoing upgrades to the docs in inxi-perl/docs/, +particularly in inxi-values.txt, inxi-resources.txt, and inxi-data.txt. These +are now increasingly useful, and I am trying to keep in particular +inxi-values.txt up to date as a primary reference for various features, though +it will always lag, because that's how it is, lol. + +2. Cleaned up changelog, made 80 cols wide for text, bars, etc, made numbered +lists and headers consistent, but otherwise did not change any of the actual +content. + +-------------------------------------------------------------------------------- +CODE CHANGES: + +1. Complete rewrite of BSD disk/partition data tools, now there is one core +tool that generates a mega-disk/partition hash, which is then used for all +features that need partition/disk data. This worked out super well, and allowed +new features like BSD Unmounted disk data to be generated for the first time +ever, along with filling in various block device fields that were missing +before. + +2. Change 1 also went along with a refactor of dmesg data tool for BSDs, which +allowed for much more granular data generation, along with a complex %dboot hash +which stores all sub types as well as the main full dataset. This allowed inxi +to stop looping through all of dmesg data each time a feature needed it. Now all +the data types are assigned if required by a feature, and only then. This, along +with change 1, worked really well. + +See also Bug 3, which mandated completely changing how dmesg.boot and dmesg live +data were / are merged, the result is far more robust now, and far less prone to +error. + +3. Similar to dmesg changes, used same methods for sysctl data, now all the data +is assigned to %sysctl data structure based on if needed or not, so it only does +the assignments one time, in one location. Much cleaner code this way, and +allows for testing set/unset substructures, like $sysctl{'cpu'}. + +4. The %dboot and %sysctl refactors went so well that I switched the core USB +and Devices to also use %usb and %devices structures. These updates let me dump +a lot of global hashes and arrays, and leaned everything down a lot, and also +removed basically all the testing loops for these data types, now the Item +features just test to see if a reference to the specific type exists, if it +does, it has data, if not, it doesn't, this is a lot easier to manage. + +5. Ongoing: moving related subroutines to Packages, the goal is to have pretty +much all related subroutines (functions) contained in parent classes/packages, +makes it easier to maintain. + +6. Ongoing: making all internal package tools have similar sub names, getting +rid of the specific names for output and data generator functions. This makes +each Item Generator increasingly like all the others, as much as practical. + +7. A big one, renamed all the feature generators to be XxxxxItem, instead of +XxxxData, which was colliding as a package name with actual data generator +tools, now all the Feature generators are [Feature]Item, and all the Data +generators have Data type names where relevant. This avoided in particular the +silly case where I was relying on case to differentiate UsbData and USBData, +feature vs data generator. + +8. As part of the move to data hash global structures, also moved as many of the +top global scalars and hashes and arrays to these now much more heavily utilized +global hashes, like %alerts, %use, %fake, %force, and so on. There are now far +fewer globals running than before, and where it makes sense, I keep moving them +into global hashes, and giving the global hashes more work to do. + +9. Significantly expanded list of debuggers for specific data types always +available, see docs/inxi-values.txt for list of options there. Decided for rapid +development, it was too much of a pain to always be uncommenting the debuggers, +so now am uncommenting, adding to @dbg supported items, then documenting. I +guess this means the @dbg items are more or less stable and consistent now, give +or take. + +10. Refactored UsbData and DeviceData, for in particular the BSDs, to be much +more robust and to rely less on very fragile regex parsing patterns, takes more +lines of code, but better than having the detections break every other BSD +release. This was part of the %device and %usb refactors as well. + +11. Fixed system_files() too, which was really silly logic, it used a global +packed hash of system files, then would do a function call for the paths when +required, which was redundant since the values were already in a hash which +could be used directly. This was a throwback to inxi gawk/bash, where hashes +were not really used in this way, and the logic had been translated to Perl +without thinking about it, but once I thought about it, I realized how silly +that was. This must have knocked off a good 50 or more unnecessary, and always +expensive, function calls. + + +-------------------------------------------------------------------------------- +-- Harald Hope - Fri, 16 Apr 2021 20:37:35 -0700 + +================================================================================ Version: 3.3.03 Patch: 00 Date: 2021-03-17 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bugs!! Fixes! Spring cleaning! -Because these are either newly created, or newly discovered, bugs, -this release was pushed as early as possible to get them fixed asap. +Because these are either newly created, or newly discovered, bugs, this release +was pushed as early as possible to get them fixed asap. BUGS: -1. Desktop: Lumina detection had a syntax error which made it not work. -This has been broken for a while. +1. Desktop: Lumina detection had a syntax error which made it not work. This has +been broken for a while. 2. Logical: if not root, and if LUKS / bcache detected, failed to load -proc_partitions, which generates error on --logical --admin since the -required components data was not loaded. This was an oversight. +proc_partitions, which generates error on --logical --admin since the required +components data was not loaded. This was an oversight. -3. The 3.3.02 ShellData refactor created a bug for console IRC, showed -shell, not irc client, name, and set default shell data which also -showed. +3. The 3.3.02 ShellData refactor created a bug for console IRC, showed shell, +not irc client, name, and set default shell data which also showed. -4. Console IRC tty: there was also an older bug that made -S, -G -not work consistently, and there were errors that had been missed -for many years in that logic. These should all be corrected, console -irc out of display, or in display as root, should now show tty info, -tty size in -G. +4. Console IRC tty: there was also an older bug that made -S, -G not work +consistently, and there were errors that had been missed for many years in that +logic. These should all be corrected, console irc out of display, or in display +as root, should now show tty info, tty size in -G. FIXES: -1. Memory: restored $bsd_type block on /proc/meminfo and force NetBSD -to use a corrected vmstat. This leaves that block of logic to correct -the NetBSD oddities in meminfo, but it may fix future isses that popup. +1. Memory: restored $bsd_type block on /proc/meminfo and force NetBSD to use a +corrected vmstat. This leaves that block of logic to correct the NetBSD oddities +in meminfo, but it may fix future isses that popup. -2. -Sxxx man page item incorrectly said XDG_VTNR was systemd/linux, it's -not, it's various things, GhostBSD has it, for example. See what you get -for believing what people say! +2. -Sxxx man page item incorrectly said XDG_VTNR was systemd/linux, it's not, +it's various things, GhostBSD has it, for example. See what you get for +believing what people say! -3. Logical: added in N/A for null maj-min in --logical report. While -bug 2 triggered those errors, there could be future cases where maj-min -are null, like BSD lvm data etc. +3. Logical: added in N/A for null maj-min in --logical report. While bug 2 +triggered those errors, there could be future cases where maj-min are null, like +BSD lvm data etc. ENHANCEMENTS: 1. Going along with Fix 1, added '--force meminfo' in case you really want that. 2. Distro: System Base: Added TrueNAS detection. -3. Package Data: Added mport [MidnightBSD] type. That requires root to run -for some odd reason, so won't see the best output if not root. +3. Package Data: Added mport [MidnightBSD] type. That requires root to run for +some odd reason, so won't see the best output if not root. CHANGES: 1. Moved logical to -v7 from -v8, it's stable enough now. CODE CHANGES: -1. Moved get_tty_number and get_tty_console_irc to ShellData:tty_number -and ShellData::tty_console_irc. +1. Moved get_tty_number and get_tty_console_irc to ShellData:tty_number and +ShellData::tty_console_irc. ShellData::tty_number was being loaded several times, added $loaded{'tty-number'} test, and made client{'tty-number'} to store value. -tty_console_irc changed to console_irc_tty, which is what it gets, removed -hacks and made it load once and store result in client hash. +tty_console_irc changed to console_irc_tty, which is what it gets, removed hacks +and made it load once and store result in client hash. -2. Optimization: retested sub vs package::method and they run at exactly -the same time, give or take, so moving more stuff into packages to make -it easier to maintain. +2. Optimization: retested sub vs package::method and they run at exactly the +same time, give or take, so moving more stuff into packages to make it easier to +maintain. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Wed, 17 Mar 2021 19:36:39 -0700 -===================================================================================== +================================================================================ Version: 3.3.02 Patch: 00 Date: 2021-03-15 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- -Huge upgrade!! Bug Fixes!! Refactors!!! BSDs!!! More BSDs!!! -raspberry pi!! New Features!!! Enhanced old features!!! Did I -mention bluetooth?! USB? Audio? No? well, all hugely upgraded! +Huge upgrade!! Bug Fixes!! Refactors!!! BSDs!!! More BSDs!!! raspberry pi!! New +Features!!! Enhanced old features!!! Did I mention bluetooth?! USB? Audio? No? +well, all hugely upgraded! ------------------------------------------------------------------------- +-------------------------------------------------------------------------------- BUGS: -1. Sadly, 3.3.01 went out with a bug, forgot to remove a debugger, -resulted in hardcoded kernel compiler version always showing. +1. Sadly, 3.3.01 went out with a bug, forgot to remove a debugger, resulted in +hardcoded kernel compiler version always showing. -Note that there is a new inxi-perl/docs/inxi-bugs.txt file to -track such bugs, and matched to specific tagged releases so you -know the line number and items to update to fix it. +Note that there is a new inxi-perl/docs/inxi-bugs.txt file to track such bugs, +and matched to specific tagged releases so you know the line number and items to +update to fix it. -2. Typo in manjaro system base match resulted in failing to report -system base as expected. +2. Typo in manjaro system base match resulted in failing to report system base +as expected. ------------------------------------------------------------------------- +-------------------------------------------------------------------------------- KNOWN ISSUES BUT CAN'T OR WON'T BE FIXED: -1. OpenBSD made fvwm -version output an error along with the -version, and not in the normal format for standard fvwm, this -is just too complicated to work around for now, though it could -be in theory by creating a dedicated fvwm-oBSD item in -program_values. But that kind of granularity gets too hard to track, -and they are likely to change or fix this in the future anyway. -Best is they just restore default -version output to what it is -elsewhere, not nested in error outputs. +1. OpenBSD made fvwm -version output an error along with the version, and not in +the normal format for standard fvwm, this is just too complicated to work around +for now, though it could be in theory by creating a dedicated fvwm-oBSD item in +program_values. But that kind of granularity gets too hard to track, and they +are likely to change or fix this in the future anyway. Best is they just restore +default -version output to what it is elsewhere, not nested in error outputs. -2. Discovered an oddity, don't know how widespread this -is, but Intel SSDs take about 200 milliseconds to get the sys -hwmon based drive temps, when it should take under a -millisecond, this may be a similar cause as those drives having -a noticeable SMART report delay, not sure. This is quite -noticeable since 200 ms is about 15% of the total execution -time on my test system. +2. Discovered an oddity, don't know how widespread this is, but Intel SSDs take +about 200 milliseconds to get the sys hwmon based drive temps, when it should +take under a millisecond, this may be a similar cause as those drives having a +noticeable SMART report delay, not sure. This is quite noticeable since 200 ms +is about 15% of the total execution time on my test system. ------------------------------------------------------------------------- +-------------------------------------------------------------------------------- FIXES: 1. For --recommends, added different rpm SUSE xdpyinfo package name. -2. Distro Data: added double term filter for lsb-release due to sometimes +2. Distro Data: added double term filter for lsb-release due to sometimes generating repeated names in distro. 3. Packages: fix for appimage package counts. -4. Desktop: fixed ID for some wm when no xprop installed, fallback to -using @ps_cmd detections, which usually work fine. +4. Desktop: fixed ID for some wm when no xprop installed, fallback to using +@ps_cmd detections, which usually work fine. 5a. When swap used was 0, showed N/A, fixed to correctly show 0 KiB. -5b. If no swap devices found, BSDs were not correctly showing -no swap data found message. Corrected. +5b. If no swap devices found, BSDs were not correctly showing no swap data found +message. Corrected. -6a. Bluetooth: Removed hcidump from debugger, in some cases, that will -just hang endlessly. Also wrapped bluetoothctl and bt-adapter debugger -data collection with @ps_cmd bluetooth running test. Only run if -bluetooth service is running. +6a. Bluetooth: Removed hcidump from debugger, in some cases, that will just hang +endlessly. Also wrapped bluetoothctl and bt-adapter debugger data collection +with @ps_cmd bluetooth running test. Only run if bluetooth service is running. -6b. Bluetooth: running detections have to be very strict, only -bluetoothd, not bluetooth, the latter can show true when bluetoothd -is not running, and did in my tests. +6b. Bluetooth: running detections have to be very strict, only bluetoothd, not +bluetooth, the latter can show true when bluetoothd is not running, and did in +my tests. -7. USB: with Code Change 1, found a few places where fallback usb type -detections were creating false matches, which resulted in say, -bluetooth devices showing up as network devices due to the presence -of the word 'wireless' in the device description. These matches are -all updated and revised to be more accurate and less error prone. +7. USB: with Code Change 1, found a few places where fallback usb type +detections were creating false matches, which resulted in say, bluetooth devices +showing up as network devices due to the presence of the word 'wireless' in the +device description. These matches are all updated and revised to be more +accurate and less error prone. -8. Battery: an oversight, had forgotten to have percent used of -available capacity, which made Battery data hard to decipher, now -it shows the percent of available total, as well as the condition -percent, so it's easier to understand the data now, and hopefully -more clear. +8. Battery: an oversight, had forgotten to have percent used of available +capacity, which made Battery data hard to decipher, now it shows the percent of +available total, as well as the condition percent, so it's easier to understand +the data now, and hopefully more clear. -9a. OpenBSD changed usbdevs output format sometime in the latest -releases, which made the delicate matching patterns fail. Updated -to handle both variants. They also changed pcidump -v formatting -at some point, now inxi will try to handle either. Note that -usbdevs updates also work fine on NetBSD. +9a. OpenBSD changed usbdevs output format sometime in the latest releases, which +made the delicate matching patterns fail. Updated to handle both variants. They +also changed pcidump -v formatting at some point, now inxi will try to handle +either. Note that usbdevs updates also work fine on NetBSD. -9b. FreeBSD also changed their pciconf output in beta 13.0, which -also broke the detections completely, now checks for old and new -formats. Sigh. It should not take this much work to parse tools -whose output should be consistent and reliable. Luckily I ran -the beta prior to this release, or all pci device detections -would simply have failed, without fallback. +9b. FreeBSD also changed their pciconf output in beta 13.0, which also broke the +detections completely, now checks for old and new formats. Sigh. It should not +take this much work to parse tools whose output should be consistent and +reliable. Luckily I ran the beta prior to this release, or all pci device +detections would simply have failed, without fallback. -9c. Dragonfly BSD also changed an output format, in vmstat, that -made the RAM used report fail. Since it's clearly not predictable -which BSD will change support for which vmstat options, now just -running vmstat without options, and then using processing logic -to determine what to do with the results. +9c. Dragonfly BSD also changed an output format, in vmstat, that made the RAM +used report fail. Since it's clearly not predictable which BSD will change +support for which vmstat options, now just running vmstat without options, and +then using processing logic to determine what to do with the results. -10. It turns out NetBSD is using /proc/meminfo, who would have -thought? for memory data, but they use it in a weird way that -could result in either negative or near 0 ram used. Added in -some filters to not allow such values to print, now it tries -to make an educated guess about how much ram the system is -really using based on some tests. +10. It turns out NetBSD is using /proc/meminfo, who would have thought? for +memory data, but they use it in a weird way that could result in either negative +or near 0 ram used. Added in some filters to not allow such values to print, now +it tries to make an educated guess about how much ram the system is really using +based on some tests. -11. Something you'd only notice if testing a lot, uptime failed -when the uptime was < 1 minute, it had failed to handle the seconds -only option, now it does, seconds, minutes, hours:minutes, -days hours:minutes, all work. +11. Something you'd only notice if testing a lot, uptime failed when the uptime +was < 1 minute, it had failed to handle the seconds only option, now it does, +seconds, minutes, hours:minutes, days hours:minutes, all work. -12. Missed linsysfs type to exclude in partitons, that was a partner -to linprocfs type, both are BSD types. +12. Missed linsysfs type to exclude in partitons, that was a partner to +linprocfs type, both are BSD types. -13. Added -ww to ps arguments, that stops the cutting width to terminal -size default behavior in BSDs, an easy fix, wish I'd known about -that a long time ago. +13. Added -ww to ps arguments, that stops the cutting width to terminal size +default behavior in BSDs, an easy fix, wish I'd known about that a long time +ago. -15. gpart seems to show sizes in bytes, not the expected KiB, so -that's now handled internally. Hopefully that odd behavior won't -randomly change in the future, sigh. +15. gpart seems to show sizes in bytes, not the expected KiB, so that's now +handled internally. Hopefully that odd behavior won't randomly change in the +future, sigh. -16. Fixed slim dm detection, saw instance where it's got slim.pid -like normal dms, not the slim.lock which inxi was looking for, so -now inxi looks for both, and we're all happy! +16. Fixed slim dm detection, saw instance where it's got slim.pid like normal +dms, not the slim.lock which inxi was looking for, so now inxi looks for both, +and we're all happy! ------------------------------------------------------------------------- +-------------------------------------------------------------------------------- ENHANCEMENTS: -1. Added in something that should have been there all along, now inxi -validates the man page download as well as the self, this avoids -corrupted downloads breaking the man. +1. Added in something that should have been there all along, now inxi validates +the man page download as well as the self, this avoids corrupted downloads +breaking the man. 2. Init: added support for shepherd init system. -3. Distro Data: added support for guix distro ID; added support for -NomadBSD, GhostBSD, HardenedBSD system base. GhostBSD also shows the main -package version for the distro version ID, which isn't quite the -same as the version you download, but it's close. Also added os-release -support for BSDs, using similar tests as for linux distros, that -results in nicer outputs for example for Dragonfly BSD. +3. Distro Data: added support for guix distro ID; added support for NomadBSD, +GhostBSD, HardenedBSD system base. GhostBSD also shows the main package version +for the distro version ID, which isn't quite the same as the version you +download, but it's close. Also added os-release support for BSDs, using similar +tests as for linux distros, that results in nicer outputs for example for +Dragonfly BSD. -4. Package Data: added guix/scratch [venom]/kiss/nix package managers. -Update for slackware 15 package manager data directory relocation, -now handles either legacy current or future one. +4. Package Data: added guix/scratch [venom]/kiss/nix package managers. Update +for slackware 15 package manager data directory relocation, now handles either +legacy current or future one. -5. Repos: added scratch/kiss/nix-channels; Added GhostBSD, HardenedBSD -pkg repos. +5. Repos: added scratch/kiss/nix-channels; Added GhostBSD, HardenedBSD pkg +repos. 6. USB Data: added usbconfig. That's FreeBSD's, and related systems. -7. Device Data: Added pcictl support, that's NetBSD's, I thought -inxi had supported that, but then I remembered last time I tried to -run netBSD in a vm, I couldn't get it figured out. Now debugged and -working reasonably well. +7. Device Data: Added pcictl support, that's NetBSD's, I thought inxi had +supported that, but then I remembered last time I tried to run netBSD in a vm, I +couldn't get it figured out. Now debugged and working reasonably well. -8. Raspberry Pi 3, 4: ethernet nic now detected; wifi device, -which is on a special mmcnr type, now works, that stopped working in -pi 3, due to the change, now it's handled cleanly. Also added support -for pi bluetooth, which lives on a special serial bus, not usb. -For Raspberry Pi OS, added system base detections, which are tricky. -Also matched mmcnr devices to IF data, which was trickyy as well. -Note that as far as I could discover, only pi puts wifi on mmcnr. +8. Raspberry Pi 3, 4: ethernet nic now detected; wifi device, which is on a +special mmcnr type, now works, that stopped working in pi 3, due to the change, +now it's handled cleanly. Also added support for pi bluetooth, which lives on a +special serial bus, not usb. For Raspberry Pi OS, added system base detections, +which are tricky. Also matched mmcnr devices to IF data, which was trickyy as +well. Note that as far as I could discover, only pi puts wifi on mmcnr. -9. Bluetooth: due to deprecated nature of the fine hciconfig -utility, added in support for bt-adapter, which also allows matching -of bluetooth data to device data, but is very sparse in info -supplied compared to hciconfig. bluetoothctl does not have enough -data to show the hci device, so it's not used, since inxi can't -match the bluetooth data to the device (no hci[x]). This should help -the distros that are moving away from hciconfig, in particular, -AUR is only way arch users can get hciconfig, which isn't ideal. +9. Bluetooth: due to deprecated nature of the fine hciconfig utility, added in +support for bt-adapter, which also allows matching of bluetooth data to device +data, but is very sparse in info supplied compared to hciconfig. bluetoothctl +does not have enough data to show the hci device, so it's not used, since inxi +can't match the bluetooth data to the device (no hci[x]). This should help the +distros that are moving away from hciconfig, in particular, AUR is only way arch +users can get hciconfig, which isn't ideal. -10. New tool and feature, ServiceData, this does two things, -as cross platform as practical, show status of bluetooth service, -this should help a lot in support people debugging bluetooth problems, -since you have bluetooth enabled but down, or up, disabled, and you -can also have the device itself down or up, so now it shows all that -data together for when it's down, but when the device is up, it just -shows the device status since the other stuff is redundant then. +10. New tool and feature, ServiceData, this does two things, as cross platform +as practical, show status of bluetooth service, this should help a lot in +support people debugging bluetooth problems, since you have bluetooth enabled +but down, or up, disabled, and you can also have the device itself down or up, +so now it shows all that data together for when it's down, but when the device +is up, it just shows the device status since the other stuff is redundant then. -In -Sa, it now shows the OS service manager that inxi detected -using a bunch of fallback tests, that's useful to admins who -are on a machine they don't know, then you can see the service -manager to use, like rc-service, systemctl, service, sv, etc. +In -Sa, it now shows the OS service manager that inxi detected using a bunch of +fallback tests, that's useful to admins who are on a machine they don't know, +then you can see the service manager to use, like rc-service, systemctl, +service, sv, etc. -11. Big update for -A: Sound Servers: had always been really -just only ALSA, now it shows all detected sound servers, and whether -they are running or not. Includes: ALSA, OSS, PipeWire, PulseAudio, -sndio, JACK. Note that OSS version is a guess, might be wrong source -for the version info. +11. Big update for -A: Sound Servers: had always been really just only ALSA, now +it shows all detected sound servers, and whether they are running or not. +Includes: ALSA, OSS, PipeWire, PulseAudio, sndio, JACK. Note that OSS version is +a guess, might be wrong source for the version info. -12. Added USB device 'power:' item, that's in mA, not a terrible -thing to have listed, -xxx. This new feature was launched cross -platform, which is nice. Whether the BSD detections will break -in the future of course depends on whether they change the output -formats again or not. Also added in USB more chip IDs, which can -be useful. For BSDs, also added in a synthetic USB rev, taken -from the device/hub speeds. Yes, I know, USB 2 can have low speed, -full speed, or high speed, and 1.1 can have low and full speeds, -so you actually can't tell the USB revision version from the speeds, -but it's close enough. +12. Added USB device 'power:' item, that's in mA, not a terrible thing to have +listed, -xxx. This new feature was launched cross platform, which is nice. +Whether the BSD detections will break in the future of course depends on whether +they change the output formats again or not. Also added in USB more chip IDs, +which can be useful. For BSDs, also added in a synthetic USB rev, taken from the +device/hub speeds. Yes, I know, USB 2 can have low speed, full speed, or high +speed, and 1.1 can have low and full speeds, so you actually can't tell the USB +revision version from the speeds, but it's close enough. -13. Made all USB/Device data the same syntax and order, more -predictable, bus, chip, class IDs all the same now. +13. Made all USB/Device data the same syntax and order, more predictable, bus, +chip, class IDs all the same now. -14. Added in support for hammer and null/nullfs file system types, -which trigger 'logical:' type device in partitions, that's also -more correct than the source: Err-102 that used to show, which -was really just a flag to alert me visibly that the partition -type detection had simply failed internally. Now for detected -types, like zfs tank/name or null/nullfs, it knows they are -logical structures. +14. Added in support for hammer and null/nullfs file system types, which trigger +'logical:' type device in partitions, that's also more correct than the source: +Err-102 that used to show, which was really just a flag to alert me visibly that +the partition type detection had simply failed internally. Now for detected +types, like zfs tank/name or null/nullfs, it knows they are logical structures. -15. Expanded BSD CPU data, where available, now can show L1/L2/ -L3 cache, cpu arch, stepping, family/model ids, etc, which is -kind of nifty, although, again, delicate fragile rules that -will probably break in the future, but easier to fix now. +15. Expanded BSD CPU data, where available, now can show L1/L2/ L3 cache, cpu +arch, stepping, family/model ids, etc, which is kind of nifty, although, again, +delicate fragile rules that will probably break in the future, but easier to fix +now. -16. By an old request, added full native BSD doas support. -That's a nice little tool, and it plugged in fairly seamlessly -to existing sudo support. Both the internal doas/sudo stuff -should work the same, and the detection of sudo/doas start -should work the same too. +16. By an old request, added full native BSD doas support. That's a nice little +tool, and it plugged in fairly seamlessly to existing sudo support. Both the +internal doas/sudo stuff should work the same, and the detection of sudo/doas +start should work the same too. -17a. Shell/Parent Data: Big refactor of the shell start/parent logic, -into ShellData which helped resolve some issues with running-in -showing shell name, not vt terminal or program name. Cause of that -is lots of levels of parents before inxi could reach the actual -program that was running inxi. Solution was to change to a longer -loop, and let it iterate 8 times, until it finds something that is -not a shell or sudo/doas/su type parent, this seems to work quite -well, you can only make it fail now if you actually try to do it on -purpose, which is fine. +17a. Shell/Parent Data: Big refactor of the shell start/parent logic, into +ShellData which helped resolve some issues with running-in showing shell name, +not vt terminal or program name. Cause of that is lots of levels of parents +before inxi could reach the actual program that was running inxi. Solution was +to change to a longer loop, and let it iterate 8 times, until it finds something +that is not a shell or sudo/doas/su type parent, this seems to work quite well, +you can only make it fail now if you actually try to do it on purpose, which is +fine. -This was very old logic, and carried some mistakes and -redundancies that made it very hard to understand, that's cleaned -up now. Also restored the old (login) value, which shows -when you use your normal login account on console, some system -will also now show (sudo,login) if the login user sudos inxi, -but that varies system to system. +This was very old logic, and carried some mistakes and redundancies that made it +very hard to understand, that's cleaned up now. Also restored the old (login) +value, which shows when you use your normal login account on console, some +system will also now show (sudo,login) if the login user sudos inxi, but that +varies system to system. -17b. BSD running-in: Some of the BSDs now support the -f flag -for ps, which made the parent logic for running-in possible for -BSDs, which was nice. Some still don't support it, like OpenBSD -and NetBSD, but that's fine, inxi tests, and if no support detected, -just shows tty number. Adding in more robust support here cleaned -up some redundant logic internally as well. +17b. BSD running-in: Some of the BSDs now support the -f flag for ps, which made +the parent logic for running-in possible for BSDs, which was nice. Some still +don't support it, like OpenBSD and NetBSD, but that's fine, inxi tests, and if +no support detected, just shows tty number. Adding in more robust support here +cleaned up some redundant logic internally as well. -17c. Updated terminal and shell ID detections, there's quite a few -new terminals this year, and a new shell or two. Those are needed -for more reliable detections of when the parent is NOT a shell, -which is how we find what it is. +17c. Updated terminal and shell ID detections, there's quite a few new terminals +this year, and a new shell or two. Those are needed for more reliable detections +of when the parent is NOT a shell, which is how we find what it is. -18. Added ctwm wm support, that's the new default for NetBSD, -based on twm, has version numbers. +18. Added ctwm wm support, that's the new default for NetBSD, based on twm, has +version numbers. -19. Upgraded BSD support for gpart and glabel data, now should -catch more more often. +19. Upgraded BSD support for gpart and glabel data, now should catch more more +often. -20. For things like zfs raid, added component size, that doesn't -always work due to how zfs refers to its components, but it often -does, which is better than never before. +20. For things like zfs raid, added component size, that doesn't always work due +to how zfs refers to its components, but it often does, which is better than +never before. -21. To make BSD support smoother, got rid of some OpenBSD only -rules, which in fact often apply to NetBSD as well. That may -lead to some glitches, but overall it's better to totally stay -away from OpenBSD only tests, and all BSD variant tests, and -just do dynamic testing that will work when it applies, and -not when it doesn't. In this case, added ftp downloader support -for netBSD by removing the openBSD only flag for that item. +21. To make BSD support smoother, got rid of some OpenBSD only rules, which in +fact often apply to NetBSD as well. That may lead to some glitches, but overall +it's better to totally stay away from OpenBSD only tests, and all BSD variant +tests, and just do dynamic testing that will work when it applies, and not when +it doesn't. In this case, added ftp downloader support for netBSD by removing +the openBSD only flag for that item. -There's a bit of a risk there in a sense since if different ftp -programs with different options were to be the fallback for something -else, it might get used, but that's fine, it's a corner case, better -to have them all work now than to worry about weird future things. -But limiting it to only BSDs should get rid of most of the problem. +There's a bit of a risk there in a sense since if different ftp programs with +different options were to be the fallback for something else, it might get used, +but that's fine, it's a corner case, better to have them all work now than to +worry about weird future things. But limiting it to only BSDs should get rid of +most of the problem. -vmstat and optical drive still use net/openbsd specifics because -it is too tricky to figure out it out in any more dynamic way. +vmstat and optical drive still use net/openbsd specifics because it is too +tricky to figure out it out in any more dynamic way. -22. For -Sxxx, added if systemd, display, virtual terminal number. -Could be useful to debug subtle issues, if the user is for example -not running their desktop in vt 7, the default for most systems. +22. For -Sxxx, added if systemd, display, virtual terminal number. Could be +useful to debug subtle issues, if the user is for example not running their +desktop in vt 7, the default for most systems. -23. And, last but not least, yes, you guessed it!!! You've been -paying attention!!! More disk vendors, more vendor IDs!!! As -always, thanks linux-lite hardware database!! +23. And, last but not least, yes, you guessed it!!! You've been paying +attention!!! More disk vendors, more vendor IDs!!! As always, thanks linux-lite +hardware database!! ------------------------------------------------------------------------- +-------------------------------------------------------------------------------- CHANGES: -1. Moved battery voltage to -Bx output, the voltage is quite -important to know since that is the key indicator of battery state. -If voltage is within .5 volts of specified minimum, shows voltage -for -B since that's a prefail condition, it's getting close to -death. +1. Moved battery voltage to -Bx output, the voltage is quite important to know +since that is the key indicator of battery state. If voltage is within .5 volts +of specified minimum, shows voltage for -B since that's a prefail condition, +it's getting close to death. -2. In partitions and raid, when the device was linear raid logical -type layout, it said, no-raid, when it should be 'linear', that's -now cleaner and more correct. +2. In partitions and raid, when the device was linear raid logical type layout, +it said, no-raid, when it should be 'linear', that's now cleaner and more +correct. -3. When running-in is a tty value, it will now show the entire -tty ID, minus the '/dev/tty', this will be more precise, and also -may resolve cases where tty was fully alpha, no numbers, previously -inxi filtered out everything that was not a number, but that can -in some tty types remove critical tty data, so now it will show: +3. When running-in is a tty value, it will now show the entire tty ID, minus the +'/dev/tty', this will be more precise, and also may resolve cases where tty was +fully alpha, no numbers, previously inxi filtered out everything that was not a +number, but that can in some tty types remove critical tty data, so now it will +show: running-in: tty 2 [not changed]; tty pts/2 [adds pts/]; tty E2 [adds the E]; tty rx [would have not shown at ll before] ------------------------------------------------------------------------- +-------------------------------------------------------------------------------- CODE CHANGES: -NOTE: unlike the previous refactors, a lot of these changes were -done to make inxi more maintainable, which means, slightly less -optimized, which has been my preference in the past, but if the -stuff can't be maintained, it doesn't matter how fast it runs! +NOTE: unlike the previous refactors, a lot of these changes were done to make +inxi more maintainable, which means, slightly less optimized, which has been my +preference in the past, but if the stuff can't be maintained, it doesn't matter +how fast it runs! -These changes have really enhanced the quality of the code and -made it a lot easier to work with. It's also now a lot easier to -add debuggers, force/fake data switches, etc, so it gets done, -unlike before, when it was a pain, so it got skipped, and then -caused bugs because of stray debuggers left in place, and so on. +These changes have really enhanced the quality of the code and made it a lot +easier to work with. It's also now a lot easier to add debuggers, force/fake +data switches, etc, so it gets done, unlike before, when it was a pain, so it +got skipped, and then caused bugs because of stray debuggers left in place, and +so on. -The bright side is while reading up on this, I learned that using -very large subs is much more efficient than many small ones, -which I've always felt was the case, and it is, so the style -used internally in inxi proves to be the best one for optimizations. +The bright side is while reading up on this, I learned that using very large +subs is much more efficient than many small ones, which I've always felt was the +case, and it is, so the style used internally in inxi proves to be the best one +for optimizations. -These refactors, ongoing, have now touched at least 1/3, almost -1/2, of the entire inxi codebase, so the stuff is getting more -and more consistent and up to date, but given how old the logic -is in places, there will be more refactors in the future, and -maybe once the code is easier to maintain, some renewed -optimizations!, if we can find anything that makes sense, like -passing array/hash references back to the caller, already the -first half is done, passing references to the sub/method always. +These refactors, ongoing, have now touched at least 1/3, almost 1/2, of the +entire inxi codebase, so the stuff is getting more and more consistent and up to +date, but given how old the logic is in places, there will be more refactors in +the future, and maybe once the code is easier to maintain, some renewed +optimizations!, if we can find anything that makes sense, like passing +array/hash references back to the caller, already the first half is done, +passing references to the sub/method always. -The second part is started, using the Benchmark Perl module, -which really speeds up testing and helps avoid pointless tweaks -that do little re speed improvements. +The second part is started, using the Benchmark Perl module, which really speeds +up testing and helps avoid pointless tweaks that do little re speed +improvements. -I could see with some care some areas where working on data -directly via references could really speed things up, but it's -hard to write and read that type of code, but it's already being -done in the recursive data and output logics, and a few other -places. +I could see with some care some areas where working on data directly via +references could really speed things up, but it's hard to write and read that +type of code, but it's already being done in the recursive data and output +logics, and a few other places. -1. Large refactor of USBData, that was done in part to help make -it work for BSDs better, but also to get it better organized. +1. Large refactor of USBData, that was done in part to help make it work for +BSDs better, but also to get it better organized. -This refactor also made all the device items, like -A,-G,-N,-E -use the same methods for creating USB output, previously they -had used a hodgepodge of methods, some super old, it was not -possible to add USB support more extensively for BSDs without -this change. +This refactor also made all the device items, like -A,-G,-N,-E use the same +methods for creating USB output, previously they had used a hodgepodge of +methods, some super old, it was not possible to add USB support more extensively +for BSDs without this change. -Also added in some fallback usb type detection tools using -several large online collections of that info to see what possible -matching patterns could catch more devices and correctly match -them to their type, which is the primary way now that usb output -per type is created. This really helps with BSDs, though BSD -usb utilities suffer from less data than lsusb so they don't always -get device name strings in a form where they can be readily ID'ed, -but it's way better than it was before, so that's fine! +Also added in some fallback usb type detection tools using several large online +collections of that info to see what possible matching patterns could catch more +devices and correctly match them to their type, which is the primary way now +that usb output per type is created. This really helps with BSDs, though BSD usb +utilities suffer from less data than lsusb so they don't always get device name +strings in a form where they can be readily ID'ed, but it's way better than it +was before, so that's fine! -Moved all previous methods of detecting if a card/device was USB -into USBData itself so it would all be in one place, and easier -to maintain. +Moved all previous methods of detecting if a card/device was USB into USBData +itself so it would all be in one place, and easier to maintain. -All USB tools now use bus_id_alpha for sorting, and all now -sort as well, that was an oversight, previously the BSD usb -tools were not sorted, but those have been enhanced a lot, so -sorting on alpha synthetic bus ids became possible. +All USB tools now use bus_id_alpha for sorting, and all now sort as well, that +was an oversight, previously the BSD usb tools were not sorted, but those have +been enhanced a lot, so sorting on alpha synthetic bus ids became possible. -Removed lsusb as a BSD option, it's really unreliable, and the data -is different, and also varies a lot, it didn't really work at all -in Dragonfly, or had strange output, so lsusb is now a linux only -item. +Removed lsusb as a BSD option, it's really unreliable, and the data is +different, and also varies a lot, it didn't really work at all in Dragonfly, or +had strange output, so lsusb is now a linux only item. -2. Moved various booleans that were global to %force, %loaded, and -some to the already present, but lightly used, %use hashes. It was -getting too hard to add tests etc, which was causing bugs to happen. -Yes, using hashes is slower than hardcoding in the boolean scalars, -but this change was done to improve maintainability, which is starting -to matter more. +2. Moved various booleans that were global to %force, %loaded, and some to the +already present, but lightly used, %use hashes. It was getting too hard to add +tests etc, which was causing bugs to happen. Yes, using hashes is slower than +hardcoding in the boolean scalars, but this change was done to improve +maintainability, which is starting to matter more. -3. Moved several sets of subs to new packages, again, to help with -debugging and maintainability. MemoryData, redone in part to -handle the oddities with NetBSD reporting of free, cached, and -buffers, but really just to make it easier to work with overall. -Also moved kernel parameter logic to KernelParameters, gpart logic -to GpartData, glabel logic to GlabelData, ip data IpData, check_tools -to CheckTools, which was also enhanced largely, and simplified, -making it much easier to work with. +3. Moved several sets of subs to new packages, again, to help with debugging and +maintainability. MemoryData, redone in part to handle the oddities with NetBSD +reporting of free, cached, and buffers, but really just to make it easier to +work with overall. Also moved kernel parameter logic to KernelParameters, gpart +logic to GpartData, glabel logic to GlabelData, ip data IpData, check_tools to +CheckTools, which was also enhanced largely, and simplified, making it much +easier to work with. -4. Wrapped more debugger logic in $fake{data} logic, that makes -it harder to leave a debugger uncommented, now to run it, you have -to trigger it with $fake{item} so the test runs, that way even if -I forget to comment it out, it won't run for regular user. +4. Wrapped more debugger logic in $fake{data} logic, that makes it harder to +leave a debugger uncommented, now to run it, you have to trigger it with +$fake{item} so the test runs, that way even if I forget to comment it out, it +won't run for regular user. -5. Big update to docs in branch inxi-perl/docs, those are now -much more usable for development. Updated in particular -inxi-values.txt to be primary reference doc for $fake, $dbg, -%force, %use, etc types and values. Also updated inxi-optimization.txt -and inxi-resources.txt to bring them closer to the present. +5. Big update to docs in branch inxi-perl/docs, those are now much more usable +for development. Updated in particular inxi-values.txt to be primary reference +doc for $fake, $dbg, %force, %use, etc types and values. Also updated +inxi-optimization.txt and inxi-resources.txt to bring them closer to the +present. -Created inxi-bugs.txt as well, which will help to know which known -bugs belonged to which frozen pools. These bugs will only refer -to bugs known to exist in tagged releases in frozen pool distros. +Created inxi-bugs.txt as well, which will help to know which known bugs belonged +to which frozen pools. These bugs will only refer to bugs known to exist in +tagged releases in frozen pool distros. -6. For sizes, moved most of the sizing to use main::translate_size, -this is more predictable, though as noted, these types of -changes make inxi a bit slower since it moved stuff out of inline -to using quick expensive sub calls, but it's a lot easier to -maintain, and that's getting to be more important to me now. +6. For sizes, moved most of the sizing to use main::translate_size, this is more +predictable, though as noted, these types of changes make inxi a bit slower +since it moved stuff out of inline to using quick expensive sub calls, but it's +a lot easier to maintain, and that's getting to be more important to me now. -7. In order to catch live events, added in dmesg to dmesg.boot data -in BSDs, that's the only way I could find to readily detect -usb flash drives that were plugged in after boot. Another hack, -these will all come back to bite me, but that's fine, the base -is easier to work on and debug now, so if I want to spend time -revisiting the next major version BSD releases, it will be easier -to resolve the next sets of failures. +7. In order to catch live events, added in dmesg to dmesg.boot data in BSDs, +that's the only way I could find to readily detect usb flash drives that were +plugged in after boot. Another hack, these will all come back to bite me, but +that's fine, the base is easier to work on and debug now, so if I want to spend +time revisiting the next major version BSD releases, it will be easier to +resolve the next sets of failures. -8. A big change, I learned about the non greedy operator for -regex patterns, ?, as in, .*?(next match rule), it will now -go up only to the next match rule. Not knowing this simple -little thing made inxi use some really convoluted regex to -avoid such greedy patterns. Still some gotchas with ?, like -it ignores following rules that are zero or 1, ? type, and -just treats it as zero instances. But that's easy to work with. +8. A big change, I learned about the non greedy operator for regex patterns, ?, +as in, .*?(next match rule), it will now go up only to the next match rule. Not +knowing this simple little thing made inxi use some really convoluted regex to +avoid such greedy patterns. Still some gotchas with ?, like it ignores following +rules that are zero or 1, ? type, and just treats it as zero instances. But +that's easy to work with. -9. Not totally done, but now moved more to having set data -tools set their $loaded{item} value in get data, not externally, -that makes it easier to track the stuff. Only where it makes -sense, but there's a lot of those set/get items, they should -probably all become package/classes, with set/get I think. +9. Not totally done, but now moved more to having set data tools set their +$loaded{item} value in get data, not externally, that makes it easier to track +the stuff. Only where it makes sense, but there's a lot of those set/get items, +they should probably all become package/classes, with set/get I think. -10. Optimized reader() and grabber() and set_ps_aux_data(), all -switched from using grep/map to using for loops, that means -inxi doesn't have to go through each array 2x anymore, actually -4x in the case of set_ps_aux_data(). This saved a visible -amount of execution time, I noticed this lag when running -pinxi through NYTProf optimizer, there was a quite visible -time difference between grabber/reader and the subshell -time, these optimizations almost removed that difference, -meaning only the subshell now really takes any time to run. +10. Optimized reader() and grabber() and set_ps_aux_data(), all switched from +using grep/map to using for loops, that means inxi doesn't have to go through +each array 2x anymore, actually 4x in the case of set_ps_aux_data(). This saved +a visible amount of execution time, I noticed this lag when running pinxi +through NYTProf optimizer, there was a quite visible time difference between +grabber/reader and the subshell time, these optimizations almost removed that +difference, meaning only the subshell now really takes any time to run. -Optimized url_cleaner and data_cleaner in RepoData, those -now just work directy on the array references, no returns. +Optimized url_cleaner and data_cleaner in RepoData, those now just work directy +on the array references, no returns. -Ran some more optimization tests, but will probably hold off -on some of them, for example, using cleaner() by reference is -about 50% faster than by copy, but redoing that requires -adding in many copies from read only things like $1, so -the change would lead to slightly less clean code, but may -revisit this in the future, we'll see. +Ran some more optimization tests, but will probably hold off on some of them, +for example, using cleaner() by reference is about 50% faster than by copy, but +redoing that requires adding in many copies from read only things like $1, so +the change would lead to slightly less clean code, but may revisit this in the +future, we'll see. -But in theory, basically all the core internal tools that -take a value and modify it should do that by reference -purely since it's way faster, up to 10x. +But in theory, basically all the core internal tools that take a value and +modify it should do that by reference purely since it's way faster, up to 10x. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Mon, 15 Mar 2021 18:42:04 -0700 -===================================================================================== +================================================================================ Version: 3.3.01 Patch: 00 Date: 2021-02-08 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug fixes!! Fixes!!! Refactors!!! Edits!!! -Bugs: -1. Big bug, 3.2 appears to have introduced this bug, for disks, rotation and +BUGS: +1. Big bug, 3.2 appears to have introduced this bug, for disks, rotation and partition scheme would never show, oops. 2. Tiny bug kept one specific smart value from ever showing, typo. -Fixes: -1. Accidentally followed Arch linux derived distro page, which claims KaOS as -arch derived, when of course it's not, it's its own distro, own toolchain, etc. -I kind of knew this but had forgotten, then I believed the Arch derived distro -page, oh well. Resulted in KaOS being listed with arch linux as system base -with -Sx. Arch should fix this, it's not like it's hard, just remove the distro -from the page. +FIXES: +1. Accidentally followed Arch linux derived distro page, which claims KaOS as +arch derived, when of course it's not, it's its own distro, own toolchain, etc. +I kind of knew this but had forgotten, then I believed the Arch derived distro +page, oh well. Resulted in KaOS being listed with arch linux as system base with +-Sx. Arch should fix this, it's not like it's hard, just remove the distro from +the page. -2. Cleared up explanations for drivetemp vs hddtemp use, updated --recommends, -man, and help to hopefully make this clear. Debian will be dropping hddtemp, -which is not maintained, sometime in the coming years, sooner than later. -Note that users unfortunately have to manually enable drivetemp module unless -their distros enable it by default, but the man/recommands/help explain that. +2. Cleared up explanations for drivetemp vs hddtemp use, updated --recommends, +man, and help to hopefully make this clear. Debian will be dropping hddtemp, +which is not maintained, sometime in the coming years, sooner than later. Note +that users unfortunately have to manually enable drivetemp module unless their +distros enable it by default, but the man/recommands/help explain that. 3. Fixed smart indentation issues, that went along with code change 1, was -failing to indent one further level for failed/age values like it's supposed -to. +failing to indent one further level for failed/age values like it's supposed to. -Enhancements: -1. Added /proc/device to debugger, that will help track block device main numbers +ENHANCEMENTS: +1. Added /proc/device to debugger, that will help track block device main +numbers -2. More disk vendors, more disk vendor IDs!!! As noted, the enternal flow flows -eternally, thanks linux-lite hardware database users!! and other inxi users, +2. More disk vendors, more disk vendor IDs!!! As noted, the enternal flow flows +eternally, thanks linux-lite hardware database users!! and other inxi users, whose outputs sometimes reveal a failure or two. -3. Added loaded kernel module tests to --recommends, this was mostly to let users -know that drivetemp is needed if you want non superuser fast drive temps, and -that this came along with kernels 5.6 or newer. Hopefully word will start drifting -out. Note that if inxi is using drivetemp values, drive temps will appear as -regular user with -Dx, and will be to 1 decimal place. hddtemp temps are -integers, and requires sudo to display the temps. +3. Added loaded kernel module tests to --recommends, this was mostly to let +users know that drivetemp is needed if you want non superuser fast drive temps, +and that this came along with kernels 5.6 or newer. Hopefully word will start +drifting out. Note that if inxi is using drivetemp values, drive temps will +appear as regular user with -Dx, and will be to 1 decimal place. hddtemp temps +are integers, and requires sudo to display the temps. -4. To handle issue #239 which I'd thought of trying off and on, but never did, -added option to -Dxxx to show SSD if a positive SSD ID was made to rotation: -So rotation will show either nothing, if no rotation or ssd data is detected, -the disk speed in rpm, or SSD if an SSD device. There may be corner cases where -this is wrong, but I don't have data for that, for example, if a disk is parked -and has zero rotation but is a HDD, not as SSD. I don't know what the data -looksl ike in that case. Note that if sudo inxi -Da is used, and smartctl is -installed, it should be right almost all the time, and with regular -Dxxx, it's -going to be right almost always, with a few corner cases. That slight -uncertainty is why I never implemented this before. Legacy drives also sometimes -did not report rotation speeds even when HDD, so those may create issues, -but inxi will only call it an SSD if it's an nvme, mmcblk device, both are -easy to ID as SSD, or if it meets certain conditions. It will not call a drive -an SSD if it was unable to meet those conditions. +4. To handle issue #239 which I'd thought of trying off and on, but never did, +added option to -Dxxx to show SSD if a positive SSD ID was made to rotation: So +rotation will show either nothing, if no rotation or ssd data is detected, the +disk speed in rpm, or SSD if an SSD device. There may be corner cases where this +is wrong, but I don't have data for that, for example, if a disk is parked and +has zero rotation but is a HDD, not as SSD. I don't know what the data looksl +ike in that case. Note that if sudo inxi -Da is used, and smartctl is installed, +it should be right almost all the time, and with regular -Dxxx, it's going to be +right almost always, with a few corner cases. That slight uncertainty is why I +never implemented this before. Legacy drives also sometimes did not report +rotation speeds even when HDD, so those may create issues, but inxi will only +call it an SSD if it's an nvme, mmcblk device, both are easy to ID as SSD, or if +it meets certain conditions. It will not call a drive an SSD if it was unable to +meet those conditions. INTERNAL CODE CHANGES: 1. Refactored the output logic for DiskData, that was messy, split it into a few -subs, and also refactored the way smartctl data was loaded and used, that's -much cleaner and easier to use now. Split the previous 1 big sub into: +subs, and also refactored the way smartctl data was loaded and used, that's much +cleaner and easier to use now. Split the previous 1 big sub into: + totals_output(), drives_output(), and smart_output(). + Also split out the smart field arrays into a separate sub, which loads -references to avoid creating new arrays and copying them all over when outputting -smart data. References are weird to work with directly but they are MUCH faster -to use, so I'm moving as much of the internal logic to use array raferences -instead of dereferenced arrays/hashes assigned to a new array, or hash. +references to avoid creating new arrays and copying them all over when +outputting smart data. References are weird to work with directly but they are +MUCH faster to use, so I'm moving as much of the internal logic to use array +raferences instead of dereferenced arrays/hashes assigned to a new array, or +hash. 2. Redid all the output modules and renamed them to be more consistent and -predictable, and redid the logic here and there to make the get() items be fairly -similar on all the data builder packages. Now as with the data subs, which -generally end in _data, now most of the output subs end with _output. +predictable, and redid the logic here and there to make the get() items be +fairly similar on all the data builder packages. Now as with the data subs, +which generally end in _data, now most of the output subs end with _output. + +3. Roughly finished the process started in 3.2, got rid of redundant array +loads, changed: -3. Roughly finished the process started in 3.2, got rid of redundant array loads, -changed: @something = something_data(); push (@rows,@something); to: push (@rows,something_data()); -which avoids creating an extra array, this also let me remove many arrays overall. -4. Missed a few hashes in machine data that were being passed directly, not as +which avoids creating an extra array, this also let me remove many arrays +overall. + +4. Missed a few hashes in machine data that were being passed directly, not as references, to other subs, corrected that. I think I missed those because they were %, so the search I did for @ in sub arg lists didn't catch the % hashes. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Mon, 08 Feb 2021 16:16:27 -0800 -===================================================================================== +================================================================================ Version: 3.3.00 Patch: 00 Date: 2021-01-28 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug fixes!! New Feature!! Edits, cleanups!! -Bugs: -1. Small bug, wrong regex would make mdraid unused report never show. -Was looking for ^used, not ^unused. No idea how that happened, but it's fixed. +BUGS: +1. Small bug, wrong regex would make mdraid unused report never show. Was +looking for ^used, not ^unused. No idea how that happened, but it's fixed. 2. Big RAID bug. Due to never having seen an 'inactive' state mdraid dataset, -inxi had a bunch of bugs around that. I'd assumed active and inactive would have -roughly the same syntax, but they don't. This is now corrected. Thanks Solus user -for giving me the required data. This case when not corrected resulted in a +inxi had a bunch of bugs around that. I'd assumed active and inactive would have +roughly the same syntax, but they don't. This is now corrected. Thanks Solus +user for giving me the required data. This case when not corrected resulted in a spray of errors as RAID ran, and a fairly incomplete RAID report for mdraid. -3. A bug that probably never impacted anyone, but in SMART the matching rules +3. A bug that probably never impacted anyone, but in SMART the matching rules failed to match field name Size[s]? in the logical/physical block sizes. -However, those were already coming in from I believe pre-existing /sys data -for the drives but now it's fixed anyway. I had not realized that smartctl -made it plural when logical/physical were different, and singular when -they were the same. +However, those were already coming in from I believe pre-existing /sys data for +the drives but now it's fixed anyway. I had not realized that smartctl made it +plural when logical/physical were different, and singular when they were the +same. -4. Failed to use all possible sd block device major number matches, which -led to false disk total/used reports, that is, totals less than used. +4. Failed to use all possible sd block device major number matches, which led to +false disk total/used reports, that is, totals less than used. -5. Bug probably introduced in 3.2, zfs single array device did not show -raid level. +5. Bug probably introduced in 3.2, zfs single array device did not show raid +level. -Fixes: +FIXES: 1. Going along with bug 2, fixed some other admin/non admin report glitches. -Made patterns more aggressively matching, whitelist based to avoid the types -of syntax issues that caused bug 2. +Made patterns more aggressively matching, whitelist based to avoid the types of +syntax issues that caused bug 2. 2. Added 'faulty' type to mdraid matches, that had not been handled. -3. Found even more of those pesky 'card' references in help and man page, +3. Found even more of those pesky 'card' references in help and man page, replaced all of them with 'device[s]'. -4. Subtle fix, for debugger data collectors, added -y1 support, which can -be useful at times. +4. Subtle fix, for debugger data collectors, added -y1 support, which can be +useful at times. -Enhancements: -1. In USB data grabber, added fallback case for unspecified type cases, now -uses a simple name/driver string test to determine if it's graphics, audio, -or bluetooth. This was mainly to make sure bluetooth usb devices get caught. +ENHANCEMENTS: +1. In USB data grabber, added fallback case for unspecified type cases, now uses +a simple name/driver string test to determine if it's graphics, audio, or +bluetooth. This was mainly to make sure bluetooth usb devices get caught. -2. New feature! -E/--bluetooth. Gives an -n like bluetooth Device-x/Report. -Requires for the 'Report:' part hciconfig, which most all distros still have -in their repos. With -a, shows an additional Info: line that has more obscure +2. New feature! -E/--bluetooth. Gives an -n like bluetooth Device-x/Report. +Requires for the 'Report:' part hciconfig, which most all distros still have in +their repos. With -a, shows an additional Info: line that has more obscure bluetooth hci data: acl-mtu sco-mtu, link-policy, link-mode, service-classes. -This closes the ancient, venerable issue #79, filed by mikaela so many years -ago. Better late than never!! However, features like this were really difficult +This closes the ancient, venerable issue #79, filed by mikaela so many years +ago. Better late than never!! However, features like this were really difficult in legacy bash/gawk inxi 2.x, and became fairly easy with inxi 3.x, so I guess -we'll slowly whittle away at these things when the mood, and global pandemic +we'll slowly whittle away at these things when the mood, and global pandemic lockdowns, make that seem like a good idea... -Includes a small lookup table to match LMP number to Bluetooth version (bt-v:), -hopefully that's a correct way to determine bluetooth version, there was some +Includes a small lookup table to match LMP number to Bluetooth version (bt-v:), +hopefully that's a correct way to determine bluetooth version, there was some ambiguity about that. -x, -xx, and -xxx function pretty much the same way as with -A, -G, and -N -devices, adding Chip IDs, Bus IDs, version info, and so on. -Since this bluetooth report does not require root and is an upper case option, -it's been added to default -F, similar to -R, and -v 5, where raid/bluetooth -shows only if data is found. With -v7 or -R or -E, always shows, including -no data found message. +devices, adding Chip IDs, Bus IDs, version info, and so on. Since this bluetooth +report does not require root and is an upper case option, it's been added to +default -F, similar to -R, and -v 5, where raid/bluetooth shows only if data is +found. With -v7 or -R or -E, always shows, including no data found message. -Includes a fallback report Report-ID: case where for some reason, inxi could -not match the HCI ID with the device. That's similar to IF-ID in -n, which -does the same when some of the IFs could not be matched to a specific device. +Includes a fallback report Report-ID: case where for some reason, inxi could not +match the HCI ID with the device. That's similar to IF-ID in -n, which does the +same when some of the IFs could not be matched to a specific device. 3. For -A, -G, -N, and -E, new item for -xxx, classID, I realized this is -actually useful for many cases of trying to figure out what devices are, -though most users would not know what to do with that information, but that's -why it's an -xxx option! +actually useful for many cases of trying to figure out what devices are, though +most users would not know what to do with that information, but that's why it's +an -xxx option! -4. Yes! You've been paying attention!! More disk vendors, and new vendor IDs!! -The cornucopia flows its endless bounty over the grateful data collector, and, +4. Yes! You've been paying attention!! More disk vendors, and new vendor IDs!! +The cornucopia flows its endless bounty over the grateful data collector, and, hopefully, inxi users!! Thanks as always, linux-lite hardware database, and -linux-lite users who really seem set on the impossible project of obtaining -all the disks/vendors known to man. +linux-lite users who really seem set on the impossible project of obtaining all +the disks/vendors known to man. -Changes: +CHANGES: 1. Small change in wording for mdraid report: -'System supported mdraid' becomes 'Supported mdraid levels' which is cleaner -and much more precise. +'System supported mdraid' becomes 'Supported mdraid levels' which is cleaner and +much more precise. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Thu, 28 Jan 2021 19:34:17 -0800 -===================================================================================== +================================================================================ Version: 3.2.02 Patch: 00 Date: 2021-01-10 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- New version, man page, bug fixes, changes, adjustments and cleanups!!! -Special thanks to mr. mazda for his ongoing suggestions, ideas, and observations. +Special thanks to mr. mazda for his ongoing suggestions, ideas, and +observations. -Bugs: +BUGS: 1. In certain corner cases, it appears that lsusb has blank lines, which tripped -errors in inxi output when the usb parser was trying to access split keys that did -not exist. Added in check to make sure split actually resulted in expected data. +errors in inxi output when the usb parser was trying to access split keys that +did not exist. Added in check to make sure split actually resulted in expected +data. -2. A red face bug, I'd left the output debugger switched on with json output, so -it was printing out the json data structure with Dumper, that's now switched off. -Hope this doesn't mess anyone up, but it would have mattered only if the person -was using: +2. A red face bug, I'd left the output debugger switched on with json output, so +it was printing out the json data structure with Dumper, that's now switched +off. Hope this doesn't mess anyone up, but it would have mattered only if the +person was using: --output json --output-type print It did not effect xml output. -Fixes: -1. Got rid of extra level of -L data structure and output handler. Not visible -to users, but still irksome, so nice to get that fixed. Recursive structures are -confusing, lol, but this extra level was pointless, but to fix it required redoing -the logic a bit for both data generator and output feature. +FIXES: +1. Got rid of extra level of -L data structure and output handler. Not visible +to users, but still irksome, so nice to get that fixed. Recursive structures are +confusing, lol, but this extra level was pointless, but to fix it required +redoing the logic a bit for both data generator and output feature. -2. Added in support for --display :0.0, previously it did not support the -.0 addition, but why not, if it works for people, good, if not, makes no difference. +2. Added in support for --display :0.0, previously it did not support the .0 +addition, but why not, if it works for people, good, if not, makes no +difference. -3. There were some missing cases for LVM missing data messages, so the following -fixes were added: - * In cases where lsblk is installed and user is non root, or lvs is not installed, - but no lvm data is present, inxi now shows the expected 'Message: No LVM data found.' - instead of the permissions or missing program error that showed before. - If lsblk is not installed, and lvm is installed (or missing), with lvs not root - readable, the permissiosn message (or missing program) will show since at that - point, inxi has no way to know if there is lvm data or not. +3. There were some missing cases for LVM missing data messages, so the +following fixes were added: + * In cases where lsblk is installed and user is non root, or lvs is not + installed, but no lvm data is present, inxi now shows the expected 'Message: + No LVM data found.' instead of the permissions or missing program error that + showed before. If lsblk is not installed, and lvm is installed (or missing), + with lvs not root readable, the permissiosn message (or missing program) will + show since at that point, inxi has no way to know if there is lvm data or not. * Not an inxi, but rather an Arch Linux packaging bug, the maintainer of lvm has made lvs and vgs fail to return error number on non root start, which is @@ -780,381 +1294,390 @@ fixes were added: to be fixed, inxi will just test if lvs and lsblk lvm data, it will show permissions message, otherwse the no lvm data message as expected. -I think these cover the last unhandled LVM cases I came across, so ideally, the +I think these cover the last unhandled LVM cases I came across, so ideally, the lvm data messages will be reasonably correct. 4. Some man page lintian fixes. -5. Changed usb data parser to use 'unless' instead of 'if' in tests since -it's easier to read unless positive tests are true than if negative or -negative etc. +5. Changed usb data parser to use 'unless' instead of 'if' in tests since it's +easier to read unless positive tests are true than if negative or negative etc. -Enhancements: -1. Since I see too often things like -F --no-host -z which is redundant, the +ENHANCEMENTS: +1. Since I see too often things like -F --no-host -z which is redundant, the help and man now make it more clear that -z implies --no-host. -2. Even though it's not that pointful, I added in derived Arch Linux system -base like Ubuntu/Debian have. It's not that meaningful because unlike -Ubuntu/Debian, where you want to know what version the derived distro is -based on, Arch is rolling thus no versions, but I figured, why not, it's -easy to do, so might as well make the system base feature a bit more complete. +2. Even though it's not that pointful, I added in derived Arch Linux system base +like Ubuntu/Debian have. It's not that meaningful because unlike Ubuntu/Debian, +where you want to know what version the derived distro is based on, Arch is +rolling thus no versions, but I figured, why not, it's easy to do, so might as +well make the system base feature a bit more complete. -Note that the way I did this requires that the distro is ID'ed as its derived +Note that the way I did this requires that the distro is ID'ed as its derived distro nanme, not Arch Linux, that will vary depending on how they did their -os-release etc, or distro files, but that's not really an inxi issue, that's -up to them. From what I've been seeing, it looks like more of the derived -distros are being ID'ed in inxi as the derived name, so those should all work -fine. Note that seeing 'base:' requires -Sx. +os-release etc, or distro files, but that's not really an inxi issue, that's up +to them. From what I've been seeing, it looks like more of the derived distros +are being ID'ed in inxi as the derived name, so those should all work fine. Note +that seeing 'base:' requires -Sx. -3. More disk vendors!! More disk vendor IDs!!! I really dug into the stuff, -and refactored slightly the backend tools I use, so it's now a bit easier -to handle the data. Thanks linux-lite hardware database, as always, for -having users that really seemt to use every disk variant known to humanity. +3. More disk vendors!! More disk vendor IDs!!! I really dug into the stuff, and +refactored slightly the backend tools I use, so it's now a bit easier to handle +the data. Thanks linux-lite hardware database, as always, for having users that +really seemt to use every disk variant known to humanity. -Changes: -1. In -G, made FAILED: lower case, and also moved it to be after unloaded: -It was too easy to think that the loaded driver had failed. Also to make it -more explicit, made output like this, in other words, driver: is a container -for the possible children: loaded: unloaded: failed: alternate: which should be -easier to parse and read without mixing up what belongs to what. +CHANGES: +1. In -G, made FAILED: lower case, and also moved it to be after unloaded: It +was too easy to think that the loaded driver had failed. Also to make it more +explicit, made output like this, in other words, driver: is a container for the +possible children: loaded: unloaded: failed: alternate: which should be easier +to parse and read without mixing up what belongs to what. driver: loaded: modesetting unloaded: nouvean,vesa alternate: nv driver: loaded: amdgpu unloaded: vesa failed: ati -Note that if there is no unloaded: driver, failed: would still appear to come after -loaded:, but hopefully it's more clear now. +Note that if there is no unloaded: driver, failed: would still appear to come +after loaded:, but hopefully it's more clear now. -Basically what we found was that the presence of the uppercase FAILED: drew -the eye so much that it was sometimes not noted that it was a key: following -the driver: item, which itself because it did not list explicitly loaded: -was not as clear as it could have been. By making failed: the same as the -other key names visually, hopefully it will be less easy to think that the -loaded: driver failed: +Basically what we found was that the presence of the uppercase FAILED: drew the +eye so much that it was sometimes not noted that it was a key: following the +driver: item, which itself because it did not list explicitly loaded: was not as +clear as it could have been. By making failed: the same as the other key names +visually, hopefully it will be less easy to think that the loaded: driver +failed: -In a sense, this is a legacy issue, because the original use of FAILED: was for -non free video drivers, to see when xorg had failed to load them, but over -more recent years, the most frequent thing I have been seeing is odd things -like failed: ati, when xorg tries to load the legacy ati driver when amdgpu -is being used. +In a sense, this is a legacy issue, because the original use of FAILED: was for +non free video drivers, to see when xorg had failed to load them, but over more +recent years, the most frequent thing I have been seeing is odd things like +failed: ati, when xorg tries to load the legacy ati driver when amdgpu is being +used. -2. Likewise, for RAID mdraid and zfs changed FAILED: to Failed:, again, to make it -more consistent with the other types. +2. Likewise, for RAID mdraid and zfs changed FAILED: to Failed:, again, to make +it more consistent with the other types. -3. In help menu and man page, removed legacy 'card(s)' in -A, -G, -N, and replaced -that with 'device(s)', which is the more accurate term, since the days when these -things were only addon cards are long behind us. I had not noticed that, but it -caught me eye and I realized it was a very deprecated and obsolete syntax, which -did not match the way inxi describes devices today. +3. In help menu and man page, removed legacy 'card(s)' in -A, -G, -N, and +replaced that with 'device(s)', which is the more accurate term, since the days +when these things were only addon cards are long behind us. I had not noticed +that, but it caught me eye and I realized it was a very deprecated and obsolete +syntax, which did not match the way inxi describes devices today. -4. It was pointed out how incoherent the naming of the item for setting wrap width, ---indent-min and config item INDENT_MIN were super confusing, since it was neither -indent or minimum, it was in fact wrap maximum, so the new options and config items -are --wrap-max and WRAP_MAX. Note that the legacy values will keep working, but -it was almost impossible in words to explain this option because the option text -was almost the exact opposite of what the option actually does. Redid the man -and help explanations to make the function of this option/config item more clear. +4. It was pointed out how incoherent the naming of the item for setting wrap +width, --indent-min and config item INDENT_MIN were super confusing, since it +was neither indent or minimum, it was in fact wrap maximum, so the new options +and config items are --wrap-max and WRAP_MAX. Note that the legacy values will +keep working, but it was almost impossible in words to explain this option +because the option text was almost the exact opposite of what the option +actually does. Redid the man and help explanations to make the function of this +option/config item more clear. -5. Made -J/--usb Hub-xx: to fit with other repeating device types in inxi output, -before Hub: was not numbered, but it struck me, it should be, like all the other -auto-incremented counter line starters, like ID-xx:, Device-x:, and so on. +5. Made -J/--usb Hub-xx: to fit with other repeating device types in inxi +output, before Hub: was not numbered, but it struck me, it should be, like all +the other auto-incremented counter line starters, like ID-xx:, Device-x:, and so +on. -6. Reorganized the main help menu to hopefully be more logical, now it shows the +6. Reorganized the main help menu to hopefully be more logical, now it shows the primary output triggers, then after, the extra data items, -a, -x, -xx, -xxx, -separated by white space per type to make it easier to read. This also moved -the stuff that had been under the -x items back to where they should be, together -with the main output control options. For readability and usability, I think this -will help, the help menu is really long, so the more visual cues it has to make it -clear what each section is, the better I think. Previously -a was the first items, -then way further down was -x, -xx, and -xxx, then under those was -z, -Z, -y. +separated by white space per type to make it easier to read. This also moved the +stuff that had been under the -x items back to where they should be, together +with the main output control options. For readability and usability, I think +this will help, the help menu is really long, so the more visual cues it has to +make it clear what each section is, the better I think. Previously -a was the +first items, then way further down was -x, -xx, and -xxx, then under those was +-z, -Z, -y. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Sun, 10 Jan 2021 18:25:48 -0800 -===================================================================================== +================================================================================ Version: 3.2.01 Patch: 00 Date: 2020-12-17 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug Fixes!!! Continuing internal refactor!! -This bug report came in right after 3.2.00 went out live, but I would never have +This bug report came in right after 3.2.00 went out live, but I would never have found it myself in testing so better found than not found! -Bugs: +BUGS: -1. A bug was introduced to dmidecode data handlers in 3.2.00 resulted in the -dmidecode data array basically eating itself up until errors appear. Quite difficult -to trigger, but babydr from Slackware forums figured it out, using -F --dmidecode -to force dmidecode use for all features that support it triggered thee bug always. -This was a result of the refactor, previously inxi had worked on copies of referenced -arrays, but in this case, it was working on the original array of arrays, subtle, -but obvious. This method was only used on dmidecode arrays. +1. A bug was introduced to dmidecode data handlers in 3.2.00 resulted in the +dmidecode data array basically eating itself up until errors appear. Quite +difficult to trigger, but babydr from Slackware forums figured it out, using -F +--dmidecode to force dmidecode use for all features that support it triggered +thee bug always. This was a result of the refactor, previously inxi had worked +on copies of referenced arrays, but in this case, it was working on the original +array of arrays, subtle, but obvious. This method was only used on dmidecode +arrays. -2. A second bug was exposed almost by accident, for -M --dmidecode data, there was -a missing field and also a missing is set test on that field that led to an error -of using undefined value in string comparison. This was strictly speaking 2 bugs, -both very old, from 2.9 first rewrite, one failing to set/get the value, and the -other failing to test if the value was set before using it. +2. A second bug was exposed almost by accident, for -M --dmidecode data, there +was a missing field and also a missing is set test on that field that led to an +error of using undefined value in string comparison. This was strictly speaking +2 bugs, both very old, from 2.9 first rewrite, one failing to set/get the value, +and the other failing to test if the value was set before using it. -Fixes: +FIXES: -1. There were a few glitches in help menu and man page related to -L option, those -are corrected. +1. There were a few glitches in help menu and man page related to -L option, +those are corrected. INTERNAL CODE CHANGES: -1. removed bug inducing splice use in some cases, and added parens to splice to make -it fit the new way of with perl builtins, when taking 2 or more arguments, use parens. +1. removed bug inducing splice use in some cases, and added parens to splice to +make it fit the new way of with perl builtins, when taking 2 or more arguments, +use parens. -2. Found many more instances to add -> dereferencing operator. I have to say, not -doing that consistently made the code much harder to read, and created situations -where it's somewhat ambiguous what item belongs to what, with everything consistently --> operator run, the code is more clear and obvious, and some of the hacks I'd added -because of the lack of clarity were also removed. +2. Found many more instances to add -> dereferencing operator. I have to say, +not doing that consistently made the code much harder to read, and created +situations where it's somewhat ambiguous what item belongs to what, with +everything consistently -> operator run, the code is more clear and obvious, and +some of the hacks I'd added because of the lack of clarity were also removed. -3. Removed explicit setting of hash references with null value, that was done out -of failure to use -> operators which clearly indicate to Perl and coder what is -happening, so those crutches were removed. Also got rid of unnecessary array +3. Removed explicit setting of hash references with null value, that was done +out of failure to use -> operators which clearly indicate to Perl and coder what +is happening, so those crutches were removed. Also got rid of unnecessary array priming like: my @array = (); Some of these habits came from other languages, -but in Perl, declaring my @array means it's an array that is null, and you don't +but in Perl, declaring my @array means it's an array that is null, and you don't need to do a further (). @array = () is obviously fine for resetting arrays in loops or whatever, but not in the initial declaration. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Thu, 17 Dec 2020 14:27:13 -0800 -===================================================================================== +================================================================================ Version: 3.2.00 Patch: 00 Date: 2020-12-15 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Huge upgrade, major rewrite/refactor, new features, everything is polished!!! -Note that due to large number of internal changes to code, a separate -INTERNAL CODE CHANGES section is at the bottom. Those are changes which in -general do not impact what users see that much, but which definitely impact -working on and with inxi! They also make errors less likely, and removed many -possible bad data error situations. +Note that due to large number of internal changes to code, a separate INTERNAL +CODE CHANGES section is at the bottom. Those are changes which in general do not +impact what users see that much, but which definitely impact working on and with +inxi! They also make errors less likely, and removed many possible bad data +error situations. BUGS: -1. Obscure, but very old Tyan Mobo used a form of dmidecode data for RAM that I'd -never gotten a dataset for before, this tripped a series of errors in inxi, which -were actually caused by small errors and failures to check certain things, as -well as simply never assigning data in corner cases. This system used only dmi -handles 5 and 6, which is a very rare setup, from the very early days of dmi -data being settled, but it was valid data, and actually inxi was supposed to support -it, because I'd never gotten a dataset containing such legacy hardware data, the -support didn't work. There were actually several bugs discovered while tracking -this down, all were corrected. +1. Obscure, but very old Tyan Mobo used a form of dmidecode data for RAM that +I'd never gotten a dataset for before, this tripped a series of errors in inxi, +which were actually caused by small errors and failures to check certain things, +as well as simply never assigning data in corner cases. This system used only +dmi handles 5 and 6, which is a very rare setup, from the very early days of dmi +data being settled, but it was valid data, and actually inxi was supposed to +support it, because I'd never gotten a dataset containing such legacy hardware +data, the support didn't work. There were actually several bugs discovered while +tracking this down, all were corrected. -2. Going along with the cpu fixes below, there was a bug that if stepping was 0, -stepping would not show. I had not realized stepping could be 0, so did a true/false -test instead of a defined test, which makes 0 in perl always test as false. This is -corrected. +2. Going along with the cpu fixes below, there was a bug that if stepping was 0, +stepping would not show. I had not realized stepping could be 0, so did a +true/false test instead of a defined test, which makes 0 in perl always test as +false. This is corrected. -3. While going through code, discovered that missing second argument to main::grabber -would have made glabel tool (BSD I think mostly) always fail, without exception. -That explains why bsd systems were never getting glabel data, heh. +3. While going through code, discovered that missing second argument to +main::grabber would have made glabel tool (BSD I think mostly) always fail, +without exception. That explains why bsd systems were never getting glabel data, +heh. -4. Many null get_size tests would not have worked because they were testing -for null array but ('','') was actually being returned, which is not a null array. -The testing and results for get_size were quite random, now they are all the same -and consistent, and confirmed correct. +4. Many null get_size tests would not have worked because they were testing for +null array but ('','') was actually being returned, which is not a null array. +The testing and results for get_size were quite random, now they are all the +same and consistent, and confirmed correct. -5. In unmounted devices, the match sent to @lsblk to get extended device data -would never work with dm-xx type names, failed to translate them to their -mapped name, which is what is used in lsblk matches, this is corrected. -This could lead to failures to match fs of members of luks, raid, etc, -particularly noticeable with complex logical device structures. This means -the fallback filters against internal logic volume names, various file system -type matches, would always fail. +5. In unmounted devices, the match sent to @lsblk to get extended device data +would never work with dm-xx type names, failed to translate them to their mapped +name, which is what is used in lsblk matches, this is corrected. This could lead +to failures to match fs of members of luks, raid, etc, particularly noticeable +with complex logical device structures. This means the fallback filters against +internal logic volume names, various file system type matches, would always +fail. -6. A small host of further bugs found and fixed during the major refactor, but -not all of them were noted, they were just fixed, sorry, those will be lost -to history unless you compare with diffs the two versions, but that's thousands -of lines, but there were more bugs fixed than listed above, just can't remember +6. A small host of further bugs found and fixed during the major refactor, but +not all of them were noted, they were just fixed, sorry, those will be lost to +history unless you compare with diffs the two versions, but that's thousands of +lines, but there were more bugs fixed than listed above, just can't remember them all. FIXES: -1. There was some ambiguity about when inxi falls back to showing hardware graphics -driver instead of xorg gfx driver when it can't find an xorg driver. That can happen -for instance because of wayland, or because of obscure xorg drivers not yet supported. -Now the message is very clear, it says the gfx software driver is n/a, and that it's -showing the hardware gfx driver. +1. There was some ambiguity about when inxi falls back to showing hardware +graphics driver instead of xorg gfx driver when it can't find an xorg driver. +That can happen for instance because of wayland, or because of obscure xorg +drivers not yet supported. Now the message is very clear, it says the gfx +software driver is n/a, and that it's showing the hardware gfx driver. -2. Big redo of cpu microarch, finally handled cases where same stepping/model ID -has two micorarches listed, now that is shown clearly to users, like AMD Zen family -17, model 18, which can be either Zen or Zen+, so now it shows that ambiguity, and -a comment: note: check, like it shows for ram report when it's not sure. Shows -for instance: -arch: Zen/Zen+ note: check -in such cases, in other words, it tells users that the naming convention -basically changed during the same hardware/die cycle. +2. Big redo of cpu microarch, finally handled cases where same stepping/model ID +has two micorarches listed, now that is shown clearly to users, like AMD Zen +family 17, model 18, which can be either Zen or Zen+, so now it shows that +ambiguity, and a comment: note: check, like it shows for ram report when it's +not sure. Shows for instance: arch: Zen/Zen+ note: check in such cases, in other +words, it tells users that the naming convention basically changed during the +same hardware/die cycle. -3. There were some raid component errors in the unmounted tests which is supposed -to test the raid components and remove them from the mounted list. Note that inxi -now also tests better if something is a raid component, or an lvm component, or -various other things, so unmounted will be right more often now, though it's still -not perfect since there are still more unhandled logical storage components that -will show as unmounted when tney are parts of logical volumes. Bit by bit!! +3. There were some raid component errors in the unmounted tests which is +supposed to test the raid components and remove them from the mounted list. Note +that inxi now also tests better if something is a raid component, or an lvm +component, or various other things, so unmounted will be right more often now, +though it's still not perfect since there are still more unhandled logical +storage components that will show as unmounted when tney are parts of logical +volumes. Bit by bit!! -4. Part of a significant android fine tuning and fix series, for -P, android uses -different default names for partitions, so none showed, now a subset of standard -android partitions, like /System, /firmware, etc, shows. Android will never work -well though because google keeps locking down key file read/search permissions in -/sys and /proc. +4. Part of a significant android fine tuning and fix series, for -P, android +uses different default names for partitions, so none showed, now a subset of +standard android partitions, like /System, /firmware, etc, shows. Android will +never work well though because google keeps locking down key file read/search +permissions in /sys and /proc. 5. More ARM device detections, that got tuned quite a bit and cleaned up, for -instance, it was doing case sensitive checks, but found cases where the value -is all upper case, so it was missing it. Now it does case insensitive device type +instance, it was doing case sensitive checks, but found cases where the value is +all upper case, so it was missing it. Now it does case insensitive device type searches. -6. One of the oldest glitches in inxi was the failure to take the size of the raid -arrays versus the size totals of the raid array components led to Local Storage -results that were uselessly wrong, being based on what is now called 'raw' disk -totals, that's the raw physical total of all system disks. Now if raid is detected -the old total: used:... is expanded to: total: raw:... usable:....used:, the usable -being the actual disk space that can be used to store data. Also in the case of -LVM systems, a further item is added, lvm-free: to report the unused but available -volume group space, that is, space not currently taken by logical volumes. This -can provide a useful overview of your system storage, and is much improved over -the previous version, which was technically unable to solve that issue because -the internal structures did not support it, now they do. LVM data requires sudo/ -root unfortunately, so you will see different disk raw totals depending on -if it's root or not if there is LVM RAID running. +6. One of the oldest glitches in inxi was the failure to take the size of the +raid arrays versus the size totals of the raid array components led to Local +Storage results that were uselessly wrong, being based on what is now called +'raw' disk totals, that's the raw physical total of all system disks. Now if +raid is detected the old total: used:... is expanded to: total: raw:... +usable:....used:, the usable being the actual disk space that can be used to +store data. Also in the case of LVM systems, a further item is added, lvm-free: +to report the unused but available volume group space, that is, space not +currently taken by logical volumes. This can provide a useful overview of your +system storage, and is much improved over the previous version, which was +technically unable to solve that issue because the internal structures did not +support it, now they do. LVM data requires sudo/ root unfortunately, so you will +see different disk raw totals depending on if it's root or not if there is LVM +RAID running. Sample: inxi -D Drives: Local Storage: total: raw: 340.19 GiB usable: 276.38 GiB lvm-free: 84.61 GiB used: 8.49 GiB (3.1%) -lvm-free is non assigned volume group size, that is, size not assigned -to a logical volume in the volume group, but available in the volume group. -raw: is the total of all detected block devices, usable is how much of that -can be used in file systems, that is, raid is > 1 devices, but those devices -are not available for storage, only the total of the raid volume is. -Note that if you are not using LVM, you will never see lvm-free:. +lvm-free is non assigned volume group size, that is, size not assigned to a +logical volume in the volume group, but available in the volume group. raw: is +the total of all detected block devices, usable is how much of that can be used +in file systems, that is, raid is > 1 devices, but those devices are not +available for storage, only the total of the raid volume is. Note that if you +are not using LVM, you will never see lvm-free:. -7. An anonymous user sent a dataset that contained a reasonable alternate -syntax for sensors output, that made inxi fail to get the sensors data. That was -prepending 'T' to temp items, and 'F' to fan items, which made enough sense though -I'd never seen it before, so inxi now supports that alternate sensors temp/fan -syntax, so that should expand the systems it supports by default out of the box. +7. An anonymous user sent a dataset that contained a reasonable alternate +syntax for sensors output, that made inxi fail to get the sensors data. That was +prepending 'T' to temp items, and 'F' to fan items, which made enough sense +though I'd never seen it before, so inxi now supports that alternate sensors +temp/fan syntax, so that should expand the systems it supports by default out of +the box. -8. Finally was able to resolve a long standing issue of loading File::Find, which -is only used in --debug 20-22 debugger, from top of inxi to require load in the -debugger. I'd tried to fix this before, but failed, the problem is that redhat -/fedora have broken apart Perl core modules, and made some of them into external -modules, which made inxi fail to start due to missing use of required module that -was not really required. Thanks to mrmazda for pointing this out to me, I'd tried -to get this working before but failed, but this time I figured out how to recode -some of the uses of File::Find so it would work when loaded without the package -debugger, hard to figure it, turned out a specific sub routine call in that -specific case required the parentheses that had been left off, very subtle. +8. Finally was able to resolve a long standing issue of loading File::Find, +which is only used in --debug 20-22 debugger, from top of inxi to require load +in the debugger. I'd tried to fix this before, but failed, the problem is that +redhat /fedora have broken apart Perl core modules, and made some of them into +external modules, which made inxi fail to start due to missing use of required +module that was not really required. Thanks to mrmazda for pointing this out to +me, I'd tried to get this working before but failed, but this time I figured out +how to recode some of the uses of File::Find so it would work when loaded +without the package debugger, hard to figure it, turned out a specific sub +routine call in that specific case required the parentheses that had been left +off, very subtle. -9. Subtle issue, unlike most of the other device data processors, the USB -data parser did not use the remove duplicates tool, which led in some cases -to duplicated company names in the output for USB, which looks silly. +9. Subtle issue, unlike most of the other device data processors, the USB data +parser did not use the remove duplicates tool, which led in some cases to +duplicated company names in the output for USB, which looks silly. -10. Somehow devtmpfs was not being detected in all cases to remove that from -partitions report, that was added to the file systen filters to make sure it +10. Somehow devtmpfs was not being detected in all cases to remove that from +partitions report, that was added to the file systen filters to make sure it gets caught. -11. Removed LVM image/meta/data data slices from unmounted report, those are LVM +11. Removed LVM image/meta/data data slices from unmounted report, those are LVM items, but they are internal LVM volumes, not available or usable. I believe -there are other data/meta type variants for different LVM features but I have -added as many types as I could find.. Also explictly now remove any _member type -item, which is always part of some other logical structure, like RAID or -LVM, those were not explicitly handled before. +there are other data/meta type variants for different LVM features but I have +added as many types as I could find.. Also explictly now remove any _member type +item, which is always part of some other logical structure, like RAID or LVM, +those were not explicitly handled before. -12. Corrected the various terms ZFS can use for spare drives, and due to how -those describe slightly different situations than simply spare, changed the spare -section header to Available, which is more accureate for ZFS. +12. Corrected the various terms ZFS can use for spare drives, and due to how +those describe slightly different situations than simply spare, changed the +spare section header to Available, which is more accureate for ZFS. ENHANCEMENTS: -1. Going along with FIX 2 is updating and adding to intel, elbrus microarch family/ -model/stepping IDs (E8C2), so that is fairly up to date now. +1. Going along with FIX 2 is updating and adding to intel, elbrus microarch +family/ model/stepping IDs (E8C2), so that is fairly up to date now. -2. Added in a very crude and highly unreliable default fallback for intel: -/sys/devices/cpu/caps/pmu_name which will show the basic internal name used -which can be quite different from what the actual microarch name is, but the hope -is that for new intel cpus that come out after these last inxi updates, something -may show, instead of nothing. Note these names are often much more generic, like -using skylake for many different microarches. +2. Added in a very crude and highly unreliable default fallback for intel: +/sys/devices/cpu/caps/pmu_name which will show the basic internal name used +which can be quite different from what the actual microarch name is, but the +hope is that for new intel cpus that come out after these last inxi updates, +something may show, instead of nothing. Note these names are often much more +generic, like using skylake for many different microarches. -3. More android enhancements, for androids that allow reading of /system/build.prop, -which is a very useful informative system info file, more android data will show, -like the device name and variant, and a few other specialized items. You can see if -your android device lets inxi read build.prop if you see under -S Distro: -Android 7.1 (2016-07-23) or just Android. If it shows just android, that means -it can't read that file. Showing Android however is also new, since while inxi -can't always read build.prop, if that file is there, it's android, so inxi -finally can recognize it's in android, even though it can't give much info if -it's locked down. Inxi in fact did not previously know it was running in android, -which is quite different from ARM systems in some ways, but now it does. +3. More android enhancements, for androids that allow reading of +/system/build.prop, which is a very useful informative system info file, more +android data will show, like the device name and variant, and a few other +specialized items. You can see if your android device lets inxi read build.prop +if you see under -S Distro: Android 7.1 (2016-07-23) or just Android. If it +shows just android, that means it can't read that file. Showing Android however +is also new, since while inxi can't always read build.prop, if that file is +there, it's android, so inxi finally can recognize it's in android, even though +it can't give much info if it's locked down. Inxi in fact did not previously +know it was running in android, which is quite different from ARM systems in +some ways, but now it does. -If the data is available, it will be used in Distro: and in Machine: data to add +If the data is available, it will be used in Distro: and in Machine: data to add more information about the android version and device. -4. A big one, for -p/-P/-o/-j now shows with -x the mapped device name, not just -the /dev/dm-xx ID, which makes connecting the various new bits easier, for RAID, -Logical reports. Note that /dev/mapper/ is removed from the mapped name since +4. A big one, for -p/-P/-o/-j now shows with -x the mapped device name, not just +the /dev/dm-xx ID, which makes connecting the various new bits easier, for RAID, +Logical reports. Note that /dev/mapper/ is removed from the mapped name since that's redundant and verbose and makes the output harder to read. For mapped -devices, the new --logical / -L report lets you drill into the devices to find +devices, the new --logical / -L report lets you drill into the devices to find out what dm-xx is actually based on. 5. More big ones, for -a -p/-P/-o/-j/-R/-L shows kernel device major:minor number, which again lets you trace each device around the system and report. -6. Added mdadm if root for mdraid report, that let me add a few other -details for mdraid not previously available. This added item 'state;' -to the mdraid report with right -x options. +6. Added mdadm if root for mdraid report, that let me add a few other details +for mdraid not previously available. This added item 'state;' to the mdraid +report with right -x options. -7. Added vpu component type to ARM gfx device type detection, don't know -how video processing vpu had escaped my notice. +7. Added vpu component type to ARM gfx device type detection, don't know how +video processing vpu had escaped my notice. -8. Added fio[a-z] block device, I'd never heard of that before, but saw -use of it in dataset, so learned it's real, but was never handled as a -valid block device type before, like sda, hda, vda, nvme, mmcblk, -etc. fio works the same, it's fio + [a-z] + [0-9]+ partition number. +8. Added fio[a-z] block device, I'd never heard of that before, but saw use of +it in dataset, so learned it's real, but was never handled as a valid block +device type before, like sda, hda, vda, nvme, mmcblk, etc. fio works the same, +it's fio + [a-z] + [0-9]+ partition number. -9. Expanded to alternate syntax Elbrus cpu L1, L2, L3 reporting. Note -that in their nomenclature, L0 and L1 are actually both L1, so add those -together when detected. +9. Expanded to alternate syntax Elbrus cpu L1, L2, L3 reporting. Note that in +their nomenclature, L0 and L1 are actually both L1, so add those together when +detected. -10. RAM, thanks to a Mint user, antikythera, learned, and handled something -new, module 'speed:' vs module 'configured clock speed:'. -To quote from supermicro: +10. RAM, thanks to a Mint user, antikythera, learned, and handled something new, +module 'speed:' vs module 'configured clock speed:'. To quote from supermicro: <<< -Question: Under dmidecode, my 'Configured Clock Speed' is lower than my -'Speed'. What does each term mean and why are they not the same? -Answer: Under dmidecode, Speed is the expected speed of the memory -(what is advertised on the memory spec sheet) and Configured Clock Speed -is what the actual speed is now. The cause could be many things but the -main possibilities are mismatching memory and using a CPU that doesn't -support your expected memory clock speed. -Please use only one type of memory and make sure that your CPU supports -your memory. +Question: Under dmidecode, my 'Configured Clock Speed' is lower than my 'Speed'. +What does each term mean and why are they not the same? + +Answer: Under dmidecode, Speed is the expected speed of the memory (what is +advertised on the memory spec sheet) and Configured Clock Speed is what the +actual speed is now. The cause could be many things but the main possibilities +are mismatching memory and using a CPU that doesn't support your expected memory +clock speed. Please use only one type of memory and make sure that your CPU +supports your memory. >>> -11. Since RAM was gettng a look, also changed cases where ddr ram speed is reported -in MHz, now it will show the speeds as: [speed * 2] MT/S ([speed] MHz). This -will let users make apples to apples speed comparisons between different systems. -Since MT/S is largely standard now, there's no need to translate that to MHz. +11. Since RAM was gettng a look, also changed cases where ddr ram speed is +reported in MHz, now it will show the speeds as: [speed * 2] MT/S ([speed] MHz). +This will let users make apples to apples speed comparisons between different +systems. Since MT/S is largely standard now, there's no need to translate that +to MHz. -12. And, even more!! When RAM speeds are logically absurd, adds in note: check -This is from a real user's data by the way, as you can see, it triggers all -the new RAM per Device report features. +12. And, even more!! When RAM speeds are logically absurd, adds in note: check +This is from a real user's data by the way, as you can see, it triggers all the +new RAM per Device report features. Sample: Memory: @@ -1167,255 +1690,260 @@ Memory: Device-4: DIMM_B2 size: 8 GiB speed: spec: 1600 MT/s (800 MHz) actual: 2 MT/s (1 MHz) note: check -13. More disks vendor!!! More disk vendor IDs!!! Yes, that's right, eternity -exists, here, now, and manifests every day!! Thanks to linux-lite hardware -database for this eternally generating list. Never underestimate the -creativity of mankind to make more disk drive companies, and to release -new model IDs for existing companies. Yes, I feel that this is a metaphore -for something much larger, but what that is, I'm not entirely clear about. +13. More disks vendor!!! More disk vendor IDs!!! Yes, that's right, eternity +exists, here, now, and manifests every day!! Thanks to linux-lite hardware +database for this eternally generating list. Never underestimate the creativity +of mankind to make more disk drive companies, and to release new model IDs for +existing companies. Yes, I feel that this is a metaphore for something much +larger, but what that is, I'm not entirely clear about. CHANGES: -1. Recent kernel changes have added a lot more sensor data in /sys, although -this varies system to system, but now, if your system supports it, you can -get at least partial hdd temp reports without needing hddtemp or root. Early -results suggest that nvme may have better support than spinning disks, but it -really varies. inxi will now look for the /sys based temp first, then fall -back to the much slower and root / sudo only hddtemp. You can force hddtemp -always with --hddtemp option, which has a corresponding configuration item. +1. Recent kernel changes have added a lot more sensor data in /sys, although +this varies system to system, but now, if your system supports it, you can get +at least partial hdd temp reports without needing hddtemp or root. Early results +suggest that nvme may have better support than spinning disks, but it really +varies. inxi will now look for the /sys based temp first, then fall back to the +much slower and root / sudo only hddtemp. You can force hddtemp always with +--hddtemp option, which has a corresponding configuration item. -2. The long requested and awaited yet arcane and obscure feature -L/--logical, -which tries to give a reasonably good report on LVM, LUKS, VeraCrypt, as well -as handling LVM raid, both regular and thin, is now working. This took a lot -of testing, and is a very solid and good start in my view, going from nothing -to something is always a big improvement!! LVM reports require root/sudo. This +2. The long requested and awaited yet arcane and obscure feature -L/--logical, +which tries to give a reasonably good report on LVM, LUKS, VeraCrypt, as well as +handling LVM raid, both regular and thin, is now working. This took a lot of +testing, and is a very solid and good start in my view, going from nothing to +something is always a big improvement!! LVM reports require root/sudo. This will, finally, close issue #135. -3. Going along with -L, and serving as a model for the logic of -L, was the -complete refactor of -R, RAID, which was a real mess internally, definitely -one of the messiest and hardest to work with features of inxi before the -refactor. It's now completely cleaned up and modularized, and is easy to add -raid types, which was not possible before, now it cleanly supports zfs, mdraid, -and lvm raid, with in depth reports and added items like mdraid size, raid -component device sizes and maj:min numbers if the -a option is used. Note -that LVM RAID requires root/sudo. +3. Going along with -L, and serving as a model for the logic of -L, was the +complete refactor of -R, RAID, which was a real mess internally, definitely one +of the messiest and hardest to work with features of inxi before the refactor. +It's now completely cleaned up and modularized, and is easy to add raid types, +which was not possible before, now it cleanly supports zfs, mdraid, and lvm +raid, with in depth reports and added items like mdraid size, raid component +device sizes and maj:min numbers if the -a option is used. Note that LVM RAID +requires root/sudo. -4. Added some more sensors dimm, volts items, slight expansion. Note that the +4. Added some more sensors dimm, volts items, slight expansion. Note that the possible expansion of sensors made possible by the recently upgraded sensors -output logic, as well as the new inxi internal sensors data structure, -which is far more granular than the previous version, and allows for much -more fine grained control and output, though only gpu data currently takes -advantage of this new power under the covers, although as noted, the /sys based -hdd temps use the same source, only straight from /sys, since it was actually -easier using the data directly from sys than trying to map the drive locations to -specific drives in sensors output. Well, to be accurate, since now only -board type sensors are used for the temp/fan speed, voltage, etc, reports, -the removal of entire sensor groups means less chance of wrong results. +output logic, as well as the new inxi internal sensors data structure, which is +far more granular than the previous version, and allows for much more fine +grained control and output, though only gpu data currently takes advantage of +this new power under the covers, although as noted, the /sys based hdd temps use +the same source, only straight from /sys, since it was actually easier using the +data directly from sys than trying to map the drive locations to specific drives +in sensors output. Well, to be accurate, since now only board type sensors are +used for the temp/fan speed, voltage, etc, reports, the removal of entire sensor +groups means less chance of wrong results. -5. To bring the ancient RAID logic to fit the rest of inxi style, made -zfs, mdraid, and lvm raid components use incrementing numbers, like cpu -cores does. This got rid of the kind of ugly hacks used previously -which were not the same for zfs or mdraid, but now they are all the same, -except that the numbers for mdraid are the actual device numbers that -mdraid supplies, and the LVM and ZFS numbers are just autoincremented, -starting at 1. +5. To bring the ancient RAID logic to fit the rest of inxi style, made zfs, +mdraid, and lvm raid components use incrementing numbers, like cpu cores does. +This got rid of the kind of ugly hacks used previously which were not the same +for zfs or mdraid, but now they are all the same, except that the numbers for +mdraid are the actual device numbers that mdraid supplies, and the LVM and ZFS +numbers are just autoincremented, starting at 1. -6. Changed message to because +6. Changed message to because it's shorter and communicates the same thing. INTERNAL CODE CHANGES: -1. Small, transparent test, tested on Perl 5.032 for Perl 7 compatibility. All +1. Small, transparent test, tested on Perl 5.032 for Perl 7 compatibility. All tests passed, no legacy code issues in inxi as of now. -2. Although most users won't notice, a big chunk of inxi was refactored -internally, which is why the new -L, the revamped -R, and the fixed -disk totals finally all can work now. This may hopefully result in more -consistent output and fewer oddities and randomnesses, since more of the -methods all use the same tools now under the covers. Ths refactor also -significantly improved inxi's execution speed, by about 4-5%, but most -of those gains are not visible due to the added new features, but the -end result is new inxi runs roughly the same speed as pre 3.2.00 inxi, but -does more, and does it better, internally at least. If you have a very -good eye you may also note a few places where this manifests externally -as well. Last I checked about 10-12% of the lines of inxi had been changed, -but I think that number is higher now. Everything that could be optimized -was, everything could be made more efficient was. +2. Although most users won't notice, a big chunk of inxi was refactored +internally, which is why the new -L, the revamped -R, and the fixed disk totals +finally all can work now. This may hopefully result in more consistent output +and fewer oddities and randomnesses, since more of the methods all use the same +tools now under the covers. Ths refactor also significantly improved inxi's +execution speed, by about 4-5%, but most of those gains are not visible due to +the added new features, but the end result is new inxi runs roughly the same +speed as pre 3.2.00 inxi, but does more, and does it better, internally at +least. If you have a very good eye you may also note a few places where this +manifests externally as well. Last I checked about 10-12% of the lines of inxi +had been changed, but I think that number is higher now. Everything that could +be optimized was, everything could be made more efficient was. -3. Several core tools in inxi were expanded to work much more cleanly, -like reader(), which now supports returning just the index value you want, -that always happened on the caller end before, which led to extra code. -get_size likewise was expanded to do a string return, which let me -remove a lot of internal redundant code in creating the size unit output, -like 32 MiB. uniq() was also redone to work exclusively by reference. +3. Several core tools in inxi were expanded to work much more cleanly, like +reader(), which now supports returning just the index value you want, that +always happened on the caller end before, which led to extra code. get_size +likewise was expanded to do a string return, which let me remove a lot of +internal redundant code in creating the size unit output, like 32 MiB. uniq() +was also redone to work exclusively by reference. -4. Many bad reference and dereference practices that had slipped into inxi -from the start are mostly corrected now, array assignments use push now, -rather than assign to array, then add array to another array, and assign -those to the master array. Several unnecessary and cpu/ram intensive copying -steps, that is, were removed in many locations internally in inxi. Also -now inxi uses more direct anonymous array and hash refernce assignments, -which again removes redundant array/hash creation, copy, and assignment. +4. Many bad reference and dereference practices that had slipped into inxi from +the start are mostly corrected now, array assignments use push now, rather than +assign to array, then add array to another array, and assign those to the master +array. Several unnecessary and cpu/ram intensive copying steps, that is, were +removed in many locations internally in inxi. Also now inxi uses more direct +anonymous array and hash refernce assignments, which again removes redundant +array/hash creation, copy, and assignment. -5. Also added explicit -> dereferencing arrows to make the code more clear -and readable, and to make it easier for perl to know what is happening. -The lack of consistency actually created confusion, I was not aware of -what certain code was doing, and didn't realize it was doing the same -thing as other code because of using different methods and syntaxes for -referencing array/hash components. I probably missed some, but I got many -of them, most probably. +5. Also added explicit -> dereferencing arrows to make the code more clear and +readable, and to make it easier for perl to know what is happening. The lack of +consistency actually created confusion, I was not aware of what certain code was +doing, and didn't realize it was doing the same thing as other code because of +using different methods and syntaxes for referencing array/hash components. I +probably missed some, but I got many of them, most probably. -6. Instituted a new perl builtin sub routine rule which is: if the sub -takes 2 or more arguments, always put in parentheses, it makes the -code much easier to follow because you see the closing ), like: -push(@rows,@row); Most perl builtins that take only one arg do not -use parentheses, except length, which just looks weird when used in -math tests, that is: length($var) > 13 looks better than length $var > 13. -This resolved inconsistent uses that had grown over time, so now all the -main builtins follow these rules consistently internally. +6. Instituted a new perl builtin sub routine rule which is: if the sub takes 2 +or more arguments, always put in parentheses, it makes the code much easier to +follow because you see the closing ), like: push(@rows,@row); Most perl builtins +that take only one arg do not use parentheses, except length, which just looks +weird when used in math tests, that is: length($var) > 13 looks better than +length $var > 13. This resolved inconsistent uses that had grown over time, so +now all the main builtins follow these rules consistently internally. -Due to certain style elements, and the time required to carefully go through -all these rules, grep and map do not yet consistently use these rules, that's -because the tendency has been to use the grep {..test..} @array and -map {...actions...} @array +Due to certain style elements, and the time required to carefully go through all +these rules, grep and map do not yet consistently use these rules, that's +because the tendency has been to use the grep {..test..} @array and map +{...actions...} @array -7. Mainly to deal with android failures to read standard system files due to -google locking it down, moved most file queries to use -r, is readable, rather -than -e, exists, or -f, is file, unless it only needs to know if it exists, -of course. This fixed many null data errors in android even on locked androids. +7. Mainly to deal with android failures to read standard system files due to +google locking it down, moved most file queries to use -r, is readable, rather +than -e, exists, or -f, is file, unless it only needs to know if it exists, of +course. This fixed many null data errors in android even on locked androids. -8. Added in %mapper and %dmmapper hashes to allow for easy mapping and -unmapping of mapped block devices. Got rid of other ways of doing that, -and made it consistent throughout inxi. These are globals that load once. +8. Added in %mapper and %dmmapper hashes to allow for easy mapping and unmapping +of mapped block devices. Got rid of other ways of doing that, and made it +consistent throughout inxi. These are globals that load once. -9. Learned that perl builtin split() has a very strange and in my view originally -terrible decision that involves treating as regex rules string characters in split -string, like split('^^',$string), which should logically be a string value, not -a ^ start search followed by a ^, but that's how it is, so that was carefully checked -and made consistent as well. Also expanded split to take advantage of the number of -splits to do, which I had only used occasionally before, but only updated field/value -splits where I have a good idea of what the data is. This is very useful when the -data is in the form of field: value, but value can contain : as well. You have to -be very careful however, since some data we do want in fact the 2nd split, but not -the subsequent ones, so I only updated the ones I was very sure about. +9. Learned that perl builtin split() has a very strange and in my view +originally terrible decision that involves treating as regex rules string +characters in split string, like split('^^',$string), which should logically be +a string value, not a ^ start search followed by a ^, but that's how it is, so +that was carefully checked and made consistent as well. Also expanded split to +take advantage of the number of splits to do, which I had only used occasionally +before, but only updated field/value splits where I have a good idea of what the +data is. This is very useful when the data is in the form of field: value, but +value can contain : as well. You have to be very careful however, since some +data we do want in fact the 2nd split, but not the subsequent ones, so I only +updated the ones I was very sure about. -10. Going along with the cpu microarch fixes, updated and cleaned up all the lists -of model/stepping matches, now they are all in order and much easier to scan and -find, that had gotten sloppy over the years. +10. Going along with the cpu microarch fixes, updated and cleaned up all the +lists of model/stepping matches, now they are all in order and much easier to +scan and find, that had gotten sloppy over the years. -11. More ARM, moved dummy and codec device values into their own storage arrays, -that let me remove the filters against those in the other detections. Makes logic -easier to read and maintain as well. +11. More ARM, moved dummy and codec device values into their own storage arrays, +that let me remove the filters against those in the other detections. Makes +logic easier to read and maintain as well. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Tue, 15 Dec 2020 15:08:05 -0800 -===================================================================================== +================================================================================ Version: 3.1.09 Patch: 00 Date: 2020-11-11 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug fixes, new features!! Update now!! Or don't, it's up to you. -Bugs: -1. Let's call some of the android fixes and debugger failures bugs, why not? -Those are fixed. Note that many of these fixes will impact any system that is +BUGS: +1. Let's call some of the android fixes and debugger failures bugs, why not? +Those are fixed. Note that many of these fixes will impact any system that is ARM based, not just android. -Fixes: -1. Related to issue #226 which was a fine issue, fine tuned the debugger debuggers -to allow for smoother handling of /sys parse failures. Also added debugger filters -for common items that would make the /sys parser hang, oddly, most seem to be in -/sys/power for android devices. +FIXES: +1. Related to issue #226 which was a fine issue, fine tuned the debugger +debuggers to allow for smoother handling of /sys parse failures. Also added +debugger filters for common items that would make the /sys parser hang, oddly, +most seem to be in /sys/power for android devices. 2. Added some fine-tunings for possible mmcblk storage paths, in some cases, an -extra /block is added, which made inxi think mounted drives were unmounted. I've -never seen this extra /block except on mmcblk devices on android, but you never +extra /block is added, which made inxi think mounted drives were unmounted. I've +never seen this extra /block except on mmcblk devices on android, but you never know, it could be more widespread. -3. Also mainly related to android, but maybe other ARM devices, in some cases, -an errant 'timer' device was appearing as a cpu variant, which is wrong. That was -a corner case for sure, and part of the variant logic in fact uses timer values -to assign the actual cpu variants, but it was wrong in this case because it was -....-timer-mem, not ...-timer, which led to non-existent CPU variants showing. +3. Also mainly related to android, but maybe other ARM devices, in some cases, +an errant 'timer' device was appearing as a cpu variant, which is wrong. That +was a corner case for sure, and part of the variant logic in fact uses timer +values to assign the actual cpu variants, but it was wrong in this case because +it was ....-timer-mem, not ...-timer, which led to non-existent CPU variants +showing. 4. Issue #236 by ChrisCheney pointed out that inxi had never updated its default -/proc/meminfo value to use the newer MemAvailable as default if present, which led -to incorrect memory used values showing up. That's because back in the old days, -we had to construct a synthetic Memory used from MemFree, buffers, cache, etc, but that -wasn't always right, since sometimes the cache actually isn't available, often is, -but not always. +/proc/meminfo value to use the newer MemAvailable as default if present, which +led to incorrect memory used values showing up. That's because back in the old +days, we had to construct a synthetic Memory used from MemFree, buffers, cache, +etc, but that wasn't always right, since sometimes the cache actually isn't +available, often is, but not always. + https://github.com/torvalds/linux/commit/34e431b0ae398fc54ea69ff85ec700722c9da773 -This commit on the kernel explains it pretty clearly. -Thanks Chris for bringing this to our attention. -5. Kind of more future-proofing, got rid of a bunch of hard-coded strings internally -and switched those to use the row_defaults values, which is where string messages -are supposed to go. That was mostly in the initial program check messages on start-up, -but also a few other stray ones. Also consolidated them a bit to get rid of redundant -messages, and added more variable based messages, like for missing/permissions on -programs etc. The idea in general is that all the strings are contained in subs so -that in theory they could be swapped for other strings, eg, languages, but honestly, -I no longer see this as very likely to ever happen. But it's still nice to be -consistent internally and not get sloppy with english strings. +This commit on the kernel explains it pretty clearly. Thanks Chris for bringing +this to our attention. -This also got rid of some largely redundant items in row_defaults, and expanded the -list of handled events, and of variable based events, so it shouldn't be as necessary -to add new row_defaults items for similar events. +5. Kind of more future-proofing, got rid of a bunch of hard-coded strings +internally and switched those to use the row_defaults values, which is where +string messages are supposed to go. That was mostly in the initial program check +messages on start-up, but also a few other stray ones. Also consolidated them a +bit to get rid of redundant messages, and added more variable based messages, +like for missing/permissions on programs etc. The idea in general is that all +the strings are contained in subs so that in theory they could be swapped for +other strings, eg, languages, but honestly, I no longer see this as very likely +to ever happen. But it's still nice to be consistent internally and not get +sloppy with english strings. -Enhancements: -1. Debugger item to maybe try to find distro OEM, this was connected with issue #231 -but the issue poster vanished, and didn't do the work required, so this one won't -happen until someone who cares [not me, that is] does the required work. -It's always funny to see how quickly people vanish when they have to do the actual -boring research that they want me to do for them, lol. Or maybe, sigh is more -appropriate than lol. But it is pretty much par for the course, sad to say. -Or maybe this was an OEM hoping to have someone do their corporate work for them -for free, who knows. Anyway, there's a certain category of items that I'm reasonably -happy to implement, but NOT if I have to do all the boring research work, so such -features being added will depend on the poster actually doing the boring work. +This also got rid of some largely redundant items in row_defaults, and expanded +the list of handled events, and of variable based events, so it shouldn't be as +necessary to add new row_defaults items for similar events. -I've gotten burned on this a few times, cpu arch: for example, some guy said he'd -track that and provide updates, he never even made it to the first release, so I got -stuck doing that one forever after. But that one at least has some general value, so -that's ok more or less, but I definitely won't take on stuff that I really don't -personally care at all about unless the person requesting the feature does all the work -beforehand. The boring part, that is.... +ENHANCEMENTS: +1. Debugger item to maybe try to find distro OEM, this was connected with issue +#231 but the issue poster vanished, and didn't do the work required, so this one +won't happen until someone who cares [not me, that is] does the required work. +It's always funny to see how quickly people vanish when they have to do the +actual boring research that they want me to do for them, lol. Or maybe, sigh is +more appropriate than lol. But it is pretty much par for the course, sad to say. +Or maybe this was an OEM hoping to have someone do their corporate work for them +for free, who knows. Anyway, there's a certain category of items that I'm +reasonably happy to implement, but NOT if I have to do all the boring research +work, so such features being added will depend on the poster actually doing the +boring work. -2. Related to issue #226, much improved android ID and many small android fixes for -machine data etc. Now uses /system/build.prop for some data, which is a nice source, -sadly, most modern android devices seem to be locked down, with both build.prop and -/sys locked down, which makes inxi unable to actually get any of that data, but if -your device either does not have these root only readable, or if you have an android -rooted phone, the android support will be more informative. +I've gotten burned on this a few times, cpu arch: for example, some guy said +he'd track that and provide updates, he never even made it to the first release, +so I got stuck doing that one forever after. But that one at least has some +general value, so that's ok more or less, but I definitely won't take on stuff +that I really don't personally care at all about unless the person requesting +the feature does all the work beforehand. The boring part, that is.... + +2. Related to issue #226, much improved android ID and many small android fixes +for machine data etc. Now uses /system/build.prop for some data, which is a nice +source, sadly, most modern android devices seem to be locked down, with both +build.prop and /sys locked down, which makes inxi unable to actually get any of +that data, but if your device either does not have these root only readable, or +if you have an android rooted phone, the android support will be more +informative. Hint: if you run inxi in termux on your non rooted android device, and it shows -you what android version you are using in System:... Distro: line, then your android -is not locked down. I have one such phone, android 7.1, but I cannot say how usual -or non usual this is. The poster of issue #226 for instance had to root his android -7 phone to get this data to display. So it seems to vary quite a bit. +you what android version you are using in System:... Distro: line, then your +android is not locked down. I have one such phone, android 7.1, but I cannot say +how usual or non usual this is. The poster of issue #226 for instance had to +root his android 7 phone to get this data to display. So it seems to vary quite +a bit. -Note that due to these file system lockdowns, in general, trying to do android arm -support remains largely a waste of time, but on some devices sometimes, you can now -get quite nice system info. As I noted in the issue, if I can't get the features to -work on a non rooted phone in my possession, I'm probably not going to try to do the -work because it's too hard to try to work on android issues without having the device -in front of you for testing and debugging. In this case, one of my phones did work, so -I did the work just to see where android is at now. +Note that due to these file system lockdowns, in general, trying to do android +arm support remains largely a waste of time, but on some devices sometimes, you +can now get quite nice system info. As I noted in the issue, if I can't get the +features to work on a non rooted phone in my possession, I'm probably not going +to try to do the work because it's too hard to try to work on android issues +without having the device in front of you for testing and debugging. In this +case, one of my phones did work, so I did the work just to see where android is +at now. -Android showed some slightly odd syntaxes for some devices, but those are now handled -where I got a dataset for them that revealed the changes required. +Android showed some slightly odd syntaxes for some devices, but those are now +handled where I got a dataset for them that revealed the changes required. -3. Also related to issue #226 for termux in android, will show -r info. -That's an apt based package manager, but termux puts the apt files somewhere else so +3. Also related to issue #226 for termux in android, will show -r info. That's +an apt based package manager, but termux puts the apt files somewhere else so needed to change paths if those alternate paths existed for apt. -4. Added PARTFLAGS to debugger to see what knd of data that will yield, that's -a lsblk key/value pair. +4. Added PARTFLAGS to debugger to see what knd of data that will yield, that's a +lsblk key/value pair. 5. Just because it's easy to do, added new -Ixxx item, wakeups: which is a subset of Uptime, this will show how many times the system has been woken from @@ -1427,142 +1955,146 @@ metaphor for something, the endless spinning of maya, who knows? 7. Added newest known ubuntu release, hirsute, to buntu ID logic. Might as well catch them early, that will be 21.04. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Wed, 11 Nov 2020 14:57:38 -0800 -===================================================================================== +================================================================================ Version: 3.1.08 Patch: 00 Date: 2020-10-16 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug fixes, updates!!! Yes!! Why wait!!! Can't stay frozen forever! -Bugs: -1. Not an inxi bug, but a weird change in defaults for ubuntu GNOME ENV -variable values when running at least the gnome desktop, result to end -users appears to be a bug. This resolves issue #228 -Note that so much weird non desktop data was put into those environmental -variables that inxi simply could make no sense of it. The fix was to make -the detections more robust, using regex instead of string compare, as well as -to at least try to strip out such corrupted data values, though that can never -be fully predictable. -As far as I know, this issue only hits ubuntu gnome desktops, I've never seen these -value corruptions on any other distro, or on any other ubuntu desktop, though -they may be there, but I'm not going to test all the ubuntu spins to find out. +BUGS: +1. Not an inxi bug, but a weird change in defaults for ubuntu GNOME ENV variable +values when running at least the gnome desktop, result to end users appears to +be a bug. This resolves issue #228 -I'm hoping the combination of logic fixes and junk data cleaning will handle +Note that so much weird non desktop data was put into those environmental +variables that inxi simply could make no sense of it. The fix was to make the +detections more robust, using regex instead of string compare, as well as to at +least try to strip out such corrupted data values, though that can never be +fully predictable. + +As far as I know, this issue only hits ubuntu gnome desktops, I've never seen +these value corruptions on any other distro, or on any other ubuntu desktop, +though they may be there, but I'm not going to test all the ubuntu spins to find +out. + +I'm hoping the combination of logic fixes and junk data cleaning will handle most future instances of these types of corruptions automatically. Again, this only happens on relatively laste ubuntu gnomes as far as I know. -Fixes: +FIXES: 1. An oversight, added sshd to list of whitelisted start clients. This permits -expected output for: ssh inxi -bay -that is, running inxi as an ssh command string. Should have done that a while ago, -but better late than never. -This corrects issue #227, or at least, has a better default, it worked fine before, -but required using --tty to reset to default terminal behavior. The problem is -that if inxi can't determine what it's running in, it defaults to thinking it's -in an IRC client, and switches to IRC color codes, among other changes. -But it was nice to get sshd covered automatically so users don't have to know -the --tty option. +expected output for: ssh inxi -bay that is, running inxi as an ssh +command string. Should have done that a while ago, but better late than never. -Changes: +This corrects issue #227, or at least, has a better default, it worked fine +before, but required using --tty to reset to default terminal behavior. The +problem is that if inxi can't determine what it's running in, it defaults to +thinking it's in an IRC client, and switches to IRC color codes, among other +changes. But it was nice to get sshd covered automatically so users don't have +to know the --tty option. + +CHANGES: 1. More disk vendors and vendor IDs!!! Yes, that's right, the list never ends!! ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Fri, 16 Oct 2020 13:43:40 -0700 -===================================================================================== +================================================================================ Version: 3.1.07 Patch: 00 Date: 2020-09-29 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug fixes, feature updates, changes!! -Bugs: -1. There was a glitch in the pattern that made -D samsung / seagate not ID right, -fixed. +BUGS: +1. There was a glitch in the pattern that made -D samsung / seagate not ID +right, fixed. -2. I do not like calling this a bug, because it's not an inxi bug, it's an upstream -regression in the syntax used in /proc/version, they changed a fully predictable -gcc version .... to a random series of embedded/nested parentheses and other random -junk. inxi tries to deal with this regression, which will be perceived as a bug in -systems running kernel 5.8 or newer and inxi 3.1.06 or older, since it will fail to -show the kernel build compiler version since it can't find it in the string. +2. I do not like calling this a bug, because it's not an inxi bug, it's an +upstream regression in the syntax used in /proc/version, they changed a fully +predictable gcc version .... to a random series of embedded/nested parentheses +and other random junk. inxi tries to deal with this regression, which will be +perceived as a bug in systems running kernel 5.8 or newer and inxi 3.1.06 or +older, since it will fail to show the kernel build compiler version since it +can't find it in the string. I really dislike these types of regressions caused by bad ideas done badly and without any thought to the transmitted knowledge base, but that's how it goes, no discipline, I miss the graybeards, who cared about things like this. -Fixes: +FIXES: 1. more -D nvme id changes, intel in this case. 2. FreeBSD lsusb changed syntax, which triggered a series of errors when run. -[hint bsd users, do NOT file issues that you want fixed and then not provide -all the data required in a prompt and timely manner, otherwise, really, -why did you file the issue?]. +[hint bsd users, do NOT file issues that you want fixed and then not provide all +the data required in a prompt and timely manner, otherwise, really, why did you +file the issue?]. Note: the fix basically just rejects any row from lsusb that does not have the expected syntax/value in the expected place, which was I think the right solution given that the change was random, broke expected syntax for lsusb, and -wasn't really integrateable into existing inxi usb logic, so why fight it? -Given that at least 99.99% of all lsusb output in the world, including by the -way OpenBSD's [not sure about most recent version], shows the expected values in -the expected place, I could see no value in creating a convoluted work-around -for a non core bsd tool in the first place, so that's what I didn't do. +wasn't really integrateable into existing inxi usb logic, so why fight it? Given +that at least 99.99% of all lsusb output in the world, including by the way +OpenBSD's [not sure about most recent version], shows the expected values in the +expected place, I could see no value in creating a convoluted work-around for a +non core bsd tool in the first place, so that's what I didn't do. See the README.txt for what to do to get issues really handed in BSDs. -Changes: -1. -C 'boost' option changed from -xxx feature to -x feature. -Consider it a promotion! +CHANGES: +1. -C 'boost' option changed from -xxx feature to -x feature. Consider it a +promotion! 2. Added --dbg 19 switch to enable smart data debugging for -Da. -3. Some new tools to handle impossible data values for some -D situations for SMART -where the smart report contains gibberish values, that was issue #225 -- tools were -convert_hex and is_Hex. The utility for these is limited, but might be of use in -some cases, like handling the above gibberish data value. +3. Some new tools to handle impossible data values for some -D situations for +SMART where the smart report contains gibberish values, that was issue #225 -- +tools were convert_hex and is_Hex. The utility for these is limited, but might +be of use in some cases, like handling the above gibberish data value. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Tue, 29 Sep 2020 16:08:05 -0700 -===================================================================================== +================================================================================ Version: 3.1.06 Patch: 00 Date: 2020-08-16 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- New features, new changes, new bug fixes!!! Excitement!!! Thrills!!! -Bugs: -1. Forgot to set get Shell logic in inxi short form, oops, so Shell remained blank, -only inxi short, which I rarely use so I didn't notice. +BUGS: +1. Forgot to set get Shell logic in inxi short form, oops, so Shell remained +blank, only inxi short, which I rarely use so I didn't notice. -2. Failed to test pacman-g2 for packages, had wrong query argument, so it failed. -Also failed to test for null data, so showed errors for packages as well. Both -fixed. +2. Failed to test pacman-g2 for packages, had wrong query argument, so it +failed. Also failed to test for null data, so showed errors for packages as +well. Both fixed. -3. A big bug, subtle, and also at the same time, an enhancement, it turns out NVME -drives do NOT follow the age old /proc/partitions logic where if the minor number is -divisible by 16 or has remainder 8 when divided by 16, it's a primary drive, not -a partition. nvme drives use a random numbering when > 1 nvme drives are present, and -the old tests would fail for all nvme drivers more than the first one, which led -to wrong disk size totals. Thanks gardotd426 who took the time to help figure this -out in issue #223 - fix is to not do that test for nvme drives, or rather, to add -a last fail test for nvme primary nvme[0-9]n[0-9] drive detections, not the minor -number. +3. A big bug, subtle, and also at the same time, an enhancement, it turns out +NVME drives do NOT follow the age old /proc/partitions logic where if the minor +number is divisible by 16 or has remainder 8 when divided by 16, it's a primary +drive, not a partition. nvme drives use a random numbering when > 1 nvme drives +are present, and the old tests would fail for all nvme drivers more than the +first one, which led to wrong disk size totals. Thanks gardotd426 who took the +time to help figure this out in issue #223 - fix is to not do that test for nvme +drives, or rather, to add a last fail test for nvme primary nvme[0-9]n[0-9] +drive detections, not the minor number. -Fixes: +FIXES: 1. Corrected indentation for block sizes, children were not indented. 2. Updated some older inxi-perl/docs pages, why not, once in a while? @@ -1571,56 +2103,58 @@ Fixes: corrected, and the kernel gcc version now shows correctly for the previous syntax and the new one. Hopefully they do not change it again, sigh... -4. Removed string 'hwmon' sensors from gpu, those are not gpu sensors, and -are also usually not board/cpu sensors, but things like ath10, iwl, etc, -network, or disk sensors, etc. In some cases hwmon sensor data would appear +4. Removed string 'hwmon' sensors from gpu, those are not gpu sensors, and are +also usually not board/cpu sensors, but things like ath10, iwl, etc, network, or +disk sensors, etc. In some cases hwmon sensor data would appear -Enhancements: -1. Big sensors refactor, now inxi supports two new sensors options: ---sensors-exclude - which allows you to exclude any primary sensor type[s]. Note that -in the refactored logic, and in the old logic, gpu sensors were already excluded. -Now other hardware specific sensors like network are excluded as well. +ENHANCEMENTS: +1. Big sensors refactor, now inxi supports two new sensors options: +--sensors-exclude - which allows you to exclude any primary sensor type[s]. Note +that in the refactored logic, and in the old logic, gpu sensors were already +excluded. Now other hardware specific sensors like network are excluded as well. --sensors-use - use ONLY list of supplied sensor IDs, which have to match the syntax you see in lm-sensors sensors output. Both accept comma separated list of sensors, 1 or more, no spaces. -The refactor however is more far reaching, now inxi stores and structures data -not as a long line of sensors and data without differentiation, but by sensor array/chip -ID, which is how the exclude and use features can work, and how granular default -hardware sensor exclusions and uses can happen. This is now working in the gpu -sensors, and will in the future be extended to the newer 5.7/5.8 kernel disk -temperature sensors values, which will lead in some cases to being able to get -sensors data for disks without root or hddtemp. This is a complicated bit of logic, -and I don't have time to do it right now, but the data is now there and stored -and possible to use in the future. +The refactor however is more far reaching, now inxi stores and structures data +not as a long line of sensors and data without differentiation, but by sensor +array/chip ID, which is how the exclude and use features can work, and how +granular default hardware sensor exclusions and uses can happen. This is now +working in the gpu sensors, and will in the future be extended to the newer +5.7/5.8 kernel disk temperature sensors values, which will lead in some cases to +being able to get sensors data for disks without root or hddtemp. This is a +complicated bit of logic, and I don't have time to do it right now, but the data +is now there and stored and possible to use in the future. -To see sensors structures, use: inxi -s --dbg 18 and that will show the sensors data -and its structures, which makes debugger a lot easier for new features. +To see sensors structures, use: inxi -s --dbg 18 and that will show the sensors +data and its structures, which makes debugger a lot easier for new features. This issue was originally generated by what was in my view an invalid complaint -about some inxi sensors defaults, which led me to look more closely at sensors -logic, which is severely lacking. More work on sensors will happen in the future, -time, health, and energy permitting. +about some inxi sensors defaults, which led me to look more closely at sensors +logic, which is severely lacking. More work on sensors will happen in the +future, time, health, and energy permitting. -2. Added Watts, mem temp, for amdgpu sensors, as -sxxx option. More gpu sensor -data will be added as new data samples show what will be available for the -free modules like amdgpu, nouvean, and the intel graphics modules. +2. Added Watts, mem temp, for amdgpu sensors, as -sxxx option. More gpu sensor +data will be added as new data samples show what will be available for the free +modules like amdgpu, nouvean, and the intel graphics modules. -3. More disk vendors and IDs, as noted, the list never ends, and it hasn't ended, -so statement remains true. Thanks linux-lite hardware database. +3. More disk vendors and IDs, as noted, the list never ends, and it hasn't +ended, so statement remains true. Thanks linux-lite hardware database. -Changes: +CHANGES: + +1. This has always bugged me since it was introduced, the primary cpu line +starter Topology: which was only technically accurate for its direct value, not +its children, and also, in -b, cpu short form was using the value as the key, +which is a no-no, I'd been meaning to fix that too, but finally realized if I +just make the primary CPU line key be 'Info:', which is short, yet +non-ambiguous, it would solve both problems. -1. This has always bugged me since it was introduced, the primary cpu line starter -Topology: which was only technically accurate for its direct value, not its children, -and also, in -b, cpu short form was using the value as the key, which is a no-no, -I'd been meaning to fix that too, but finally realized if I just make the primary -CPU line key be 'Info:', which is short, yet non-ambiguous, it would solve both -problems. To keep the -b cpu line as short as before, I removed the 'type:' and integraged that value into the primary Info: string: + CPU: Info: 6-Core AMD Ryzen 5 2600 [MT MCP] speed: 2750 MHz min/max: 1550/3400 MHz @@ -1628,301 +2162,302 @@ CPU: CPU: 6-Core: AMD Ryzen 5 2600 type: MT MCP speed: 1515 MHz min/max: 1550/3400 MHz -These resolve something that has irked me for quite a while, 'Topology:' didn't -fit, it was too geeky, and worst, it only applied to the value directly following -it, NOT to the rest of the CPU information. It also could not be shortened or -abbreviated since then it would have made no actual sense, like topo:, and the -same issue with value being used for key in -b, and wrong word for line starter -in -C would have existed. Besides, someone might think I was trying to make a -subtle reference to the great Jodorowsky film 'El Topo', which would be silly, -because that's art, and this is just some system specs that are reasonably -readable... +These resolve something that has irked me for quite a while, 'Topology:' didn't +fit, it was too geeky, and worst, it only applied to the value directly +following it, NOT to the rest of the CPU information. It also could not be +shortened or abbreviated since then it would have made no actual sense, like +topo:, and the same issue with value being used for key in -b, and wrong word +for line starter in -C would have existed. Besides, someone might think I was +trying to make a subtle reference to the great Jodorowsky film 'El Topo', which +would be silly, because that's art, and this is just some system specs that are +reasonably readable... 2. Was using opendns for WAN dig IP address, but apparently cysco bought that -company, and now I've noticed the old opendns dig queries were failing more and -more, so replaced that with akamai dig requests. -Also made the WAN IP fallback to HTTP IP method if dig failed. New option: ---no-http-wan and config item NO_HTTP_WAN with override --http-wan added to -let you switch off http wan IP requests if you want. Note that if dig fails, -you will get no wan ip address. +company, and now I've noticed the old opendns dig queries were failing more and +more, so replaced that with akamai dig requests. Also made the WAN IP fallback +to HTTP IP method if dig failed. New option: --no-http-wan and config item +NO_HTTP_WAN with override --http-wan added to let you switch off http wan IP +requests if you want. Note that if dig fails, you will get no wan ip address. Updated/improved error messages to handle this more complex set of wan ip options, so hopefully the error alert message will in most cases be right. -3. To future proof inxi, switched debugger upload location to ftp.smxi.org/incoming -from the old techpatterns.com/incoming. Updated man/help to remove those urls too. +3. To future proof inxi, switched debugger upload location to +ftp.smxi.org/incoming from the old techpatterns.com/incoming. Updated man/help +to remove those urls too. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Sun, 16 Aug 2020 14:28:58 -0700 -===================================================================================== +================================================================================ Version: 3.1.05 Patch: 00 Date: 2020-07-26 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- Bug fixes!!! New Features!! Why wait!!! -Bugs: -1. Issue #220 on github: inxi misidentified XFCE as Gnome. This was a kind of core -issue, and pointed to some logic that needed updating, and some inadequate -assumptions made, and some too loose cascade of tests. Hopefully now xfce will -almost never get misidentified, and the other primary desktops ID'ed either from +BUGS: +1. Issue #220 on github: inxi misidentified XFCE as Gnome. This was a kind of +core issue, and pointed to some logic that needed updating, and some inadequate +assumptions made, and some too loose cascade of tests. Hopefully now xfce will +almost never get misidentified, and the other primary desktops ID'ed either from $ENV or from xrop -root will be slightly more accurately identified as well. -Note that this fix creates a possibility for obscure misconfigured desktops to -be ID'ed wrong, but in this case, that will be technically a bug for them, but -with the new fixes, that situation will be cleaner to handle internally in the +Note that this fix creates a possibility for obscure misconfigured desktops to +be ID'ed wrong, but in this case, that will be technically a bug for them, but +with the new fixes, that situation will be cleaner to handle internally in the desktop ID logic. -Also tightened the final Gnome fallback detection to not trigger a possible -false positive, it was testing for ^_GNOME but that is not adequate, because -some gnome programs will trigger these values in xprop -root even if GNOME -is not running. Should be safer now, hopefully no new bugs will be triggered -by these changes. +Also tightened the final Gnome fallback detection to not trigger a possible +false positive, it was testing for ^_GNOME but that is not adequate, because +some gnome programs will trigger these values in xprop -root even if GNOME is +not running. Should be safer now, hopefully no new bugs will be triggered by +these changes. -Fixes: -1. Missed an indentation level for -y1, gcc alt should have been indented in -one more level, now it is. +FIXES: +1. Missed an indentation level for -y1, gcc alt should have been indented in one +more level, now it is. -2. In disk vendors/family, didn't clean items starting with '/', this is -now corrected. Yes, some do, don't ask me why. Might be cases like: -Crucial/Micron maybe, where the first ID is grabbed, not sure. +2. In disk vendors/family, didn't clean items starting with '/', this is now +corrected. Yes, some do, don't ask me why. Might be cases like: Crucial/Micron +maybe, where the first ID is grabbed, not sure. -Enhancements: -1. New Disk vendors, vendor IDs!!! The list never ends!!! We've finally found -infinity, and it is the unceasing wave of tiny and not so tiny disks and their +ENHANCEMENTS: +1. New Disk vendors, vendor IDs!!! The list never ends!!! We've finally found +infinity, and it is the unceasing wave of tiny and not so tiny disks and their Ids. -2. New feature: for -Aa, -Na/-na/-ia, -Ga, now will add the modules the kernel -could support if they were available on the Device-x lines of those items. -This was made an -a option because it really makes no sense, if it's a regular -option, users might think that for example an nvidia card had a nouveua driver -when it didn't, when in fact, all the kernel is saying is that it knows those -listed modules 'couid' be used or present. This corresponds to the Display: -item in -Ga, that lists 'alternate:' drivers that Xorg knows about that could +2. New feature: for -Aa, -Na/-na/-ia, -Ga, now will add the modules the kernel +could support if they were available on the Device-x lines of those items. This +was made an -a option because it really makes no sense, if it's a regular +option, users might think that for example an nvidia card had a nouveua driver +when it didn't, when in fact, all the kernel is saying is that it knows those +listed modules 'couid' be used or present. This corresponds to the Display: item +in -Ga, that lists 'alternate:' drivers that Xorg knows about that could likewise be used, if they were on the system. -In other words these are --admin options because otherwise users might get confused, -so this is one where you want to know the man explanation before you ask for it. +In other words these are --admin options because otherwise users might get +confused, so this is one where you want to know the man explanation before you +ask for it. -It is useful however if you're not sure what your choices are for kernel modules. +It is useful however if you're not sure what your choices are for kernel +modules. -When the alternate driver is the same as the active driver, or if none is found, +When the alternate driver is the same as the active driver, or if none is found, it does not show the alternate: item to avoid spamming. ------------------------------------ +-------------------------------------------------------------------------------- -- Harald Hope - Sun, 26 Jul 2020 19:10:21 -0700 -===================================================================================== +================================================================================ Version: 3.1.04 Patch: 00 Date: 2020-06-28 ------------------------------------ -Changes: ------------------------------------ +-------------------------------------------------------------------------------- +CHANGES: +-------------------------------------------------------------------------------- New version, new man, huge update, bug fixes, cleanups, updates!! What started as a relatively minor issue report ended up with a refactor of big chunks of some of the oldest code and logic in inxi. -So many bugs and fixes, updates, and enhancements, that I will probably miss some -when I try to list them. +So many bugs and fixes, updates, and enhancements, that I will probably miss +some when I try to list them. -Bugs: -1. In the process of fixing an issue about sudo use triggering server admin -emails on failure, when --sudo/--no-sudo and their respective configuration -items were added, sudo was inadvertently disabled because the test ran before +BUGS: +1. In the process of fixing an issue about sudo use triggering server admin +emails on failure, when --sudo/--no-sudo and their respective configuration +items were added, sudo was inadvertently disabled because the test ran before the options were processed, which meant the condition to set sudo data was -always false, so sudo for internal use was never set. The solution was to -set a flag in the option handler and set sudo after options or configs run. +always false, so sudo for internal use was never set. The solution was to set a +flag in the option handler and set sudo after options or configs run. -2. Issue #219 reported gentoo and one other repo type would fail to show -enabled repos, and would show an error as well, this was due to forgetting -to make the match test case insensitive. If only all bugs were this easy -to fix!! +2. Issue #219 reported gentoo and one other repo type would fail to show enabled +repos, and would show an error as well, this was due to forgetting to make the +match test case insensitive. If only all bugs were this easy to fix!! -3. I'd seen this bug before, and couldn't figure out why it existed. -It turned out that the partition blacklist filters were running fine -in the main partition data tool, but I had forgotten to add in corresponding -lsblk partition data filters, lol, so when the logic went back and double -checked for missing partitions. This feature had been, if i remember right, -to be able to show hidden partitions, which the standard method didn't see, -but lsblk did, anyway, when the double check and add missing partitions -logic ran, inxi was putting back in the blacklisted partitions every time, -despite the original blacklists working well and as intended. -This was fixed by adding in all the required fs type blacklists, then -adding in comments above each black list reminding coders that if they -add or remove from one blacklist, they have to do the same on the other. +3. I'd seen this bug before, and couldn't figure out why it existed. It turned +out that the partition blacklist filters were running fine in the main partition +data tool, but I had forgotten to add in corresponding lsblk partition data +filters, lol, so when the logic went back and double checked for missing +partitions. This feature had been, if i remember right, to be able to show +hidden partitions, which the standard method didn't see, but lsblk did, anyway, +when the double check and add missing partitions logic ran, inxi was putting +back in the blacklisted partitions every time, despite the original blacklists +working well and as intended. This was fixed by adding in all the required fs +type blacklists, then adding in comments above each black list reminding coders +that if they add or remove from one blacklist, they have to do the same on the +other. -4. Found while testing something unrelated on older vm, the fallback -case for cpu bugs, which was supposed to show the basic /proc/cpuinfo -cpu bugs, was failing inexplicably because the data was simply being -put into the wrong variable name, sigh. +4. Found while testing something unrelated on older vm, the fallback case for +cpu bugs, which was supposed to show the basic /proc/cpuinfo cpu bugs, was +failing inexplicably because the data was simply being put into the wrong +variable name, sigh. -Fixes: +FIXES: 1. While not technically an inxi bug, it would certainly appear that way to -anyone who triggered it. We'd gotten issue reports before on this, but they -were never complete, so couldn't figure it out. Basically, if someone puts -inxi into a simple script that is in $PATH [this was the missing fact needed to -actually trigger this bug in order to fix it], the script [not inxi], will -then enter into an endless loop as inxi queries it for its version number using -