From ed7049fcc14fd5a1bb7e01b9674ad4c64e90cefa Mon Sep 17 00:00:00 2001 From: Harald Hope Date: Sun, 7 May 2023 11:59:56 -0700 Subject: [PATCH] Completion of the audio fixes and improvements of 3.3.26. Added less common sound servers like EsounD and aRts, and made state reports more accurate for ALSA. Major USB code and data upgrades/refactors. The USB changes prepare inxi for USB 4, and adds lanes and Si/IEC speeds to the report. It is important to determine what USB mode you are running in with 3.x and 4. These changes conform more closely to how the USB consortium wants USB speeds refered to. With more robust USB data, this data now appears in a similar form as pcie: data for Devices, -A, -E, -G, -N, and for -D drives, as usb: plus rev, speed, lanes, mode, with the -xx/-a options, like pcie. This has been a long standing oversight and weakness of inxi USB and Device data, but now the two are fully integrated, including for drives, which was quite tricky to get working. Added netpkg and Zenwalk support to packages and repos. Also added repos support for sbopkg and slpkg, and updated package tools for Slackware. And more distros added to system base feature, and a few more for main ID. Improved --recommends report quite a bit, now it's more granular for missing packages and package manager reports, and also fixed a long standing missing current shell + version issue. Added the final package manager type, pkgtool (Slackware), that will be supported, which makes for 4, which is enough. Note that other package managers can be added following the documentation instructions for packagers, but this is enough for out of the box pm handling. Fixed a long standing oddity with how free / /proc/meminfo report MemTotal vs the actual physical RAM. I believe this issue also showed with GPU assigned RAM, but now for all but short form, shows Memory/RAM: available: ... used: ... -------------------------------------------------------------------------------- SPECIAL THANKS: 1. To the Slackware people at linuxquestions.org forums, who helped, again, on this audio feature, even finding current or not too old systems that use some of the new / old audio servers (EsoundD) running in the wild, which I never expected to see. And also for exposing some weak spots in the USB advanced logic, and helping with the sbopkg and slpkg repo logic and tools reports. 2. To the Manjaro forum users, for providing cases that show where inxi can be improved. The audio server/api issue, the current USB 3/4 upgrade, were initiated by threads pointing to things that could be improved in inxi. So I guess the real thanks are for using inxi enough to trigger cases that show where it's weak or can be better. Note that this requires that I follow roughly their forums, however I only look at threads that seem like they might be of general interest, or which suggest a possible weak spot in inxi, and I don't follow them consistently. More reliable is to file github issues, since I will always see those. -------------------------------------------------------------------------------- KNOWN ISSUES: 1. DesktopData: at one point, BunsenLabs Debian OpenBox had XDG_CURRENT_DESKTOP set to XFCE, which it isn't, but inxi can't work around such hacks, plus I don't even know if Bunsen is around anymore anyway. 2. DesktopData: CODE 1 reminds us that the time to depend on x tools like xprop for anything re desktop/wm detections is fast drawing to a close, true Wayland will not have xprop, unless it's running on xwayland, which is not something that should be relied on. Maybe recheck Moksha/Enlightenment which depend on xprop for version detection. The list of xprop detected wm/desktops in get_env_xprop_misc_data() is almost all X only wm/desktops, so those should be safe unless one of them decides to work on a wayland comositor. 3. BSD: ongoing weaknesses in BSD data sources make maintaining feature parity impossible, but I am trying to get the BSD data as clean and consistent as possible. I wish this were not the case, but the fact is, /sys is expanding and creating excellent and reliable data sources with every major Linux kernel update, and so far nothing comparable has appeared in the BSDs. This is just reality, it's not a condemnation, but something like the /proc then /sys file systems are an excellent idea, well worth emulating. 4. For the RAM available/total clarification, there's a slight issue because free/meminfo show MemAvailable as Free for use RAM, but dmesg shows available meaning what was available to the system during boot, minus the reserved percentage. Since we needed one term, available to System offers the closest in terms of technical precision without being too verbose. Technically available in this context means: total physical minus 'kernel code' minus 'reserved'. -------------------------------------------------------------------------------- BUGS: 1. CheckRecommends: See Fix 6b, more or less a bug, but really just a fix. 2. AUDIO: for USB devices, put extra data into row 0, no matter which row the USB device is. This led to the extra data for USB being assigned to the wrong row. Sigh. 3. OptionsHandler: When show{'ram'} was set, for bsd, set use{'bsd-raid'}, which makes both show raid and ram fail for BSD. Oops. User mode RAM data only seen in OpenBSD so far. This made loading $dboot{'ram'} fail, and any raid as well, sigh, unless -m was also tripped. -------------------------------------------------------------------------------- FIXES: 1. DistroData: typo for Arch base: was ctios, was supposed to be ctlos. 2a. DesktopData: found case where xprop -root not present (Void Linux), so xfce test failed. Split to new function dedicated to xfce detection that doesn't use xprop data. Also, XFCE is working on their Wayland version, which would in theory not even have xprop by default. Also, the base version number test for xfce depended on xprop, but xprop doesn't even have that xfce version data anymore, so just checking if xfce(4|5|)-panel exist and assigning primary version based on that test. 2b. DesktopData: Also see See CODE 1a,1b for further xprop and test fixes that could have led to false positive or negative test conditions for the items that used xprop tests. These tests are all xprop agnostic now, if it's there, they will use it, if not, do the best they can. 3. PackageData: fixed legacy dpkg-query, old version did not support -f shortcut for --showformat. This made dpkg package listing fail. 4a. GRAPHICS: Added legacy XFree86.0.log to X log path detection, that was an oversight. Also added legacy module syntax _drv.o (not _drv.so). This gets X driver data now for very old systems. 4b. GRAPHICS: fixed corner case where no x driver data, running as root, was not supposed to show 'note: X driver n/a' message, that was a holdover from before driver output was cleaned up and driver: N/A shows when no drivers at all found. Just forgot to remove it when doing recent updates in the driver section, maybe? 5. REPOS/PackageData: For netpkg Zenwalk Slackware systems, showed only slackpkg repo data, empty, and showed the Slackware pm, not netpkg for pm. See Enhancements 5, 6. 6. REPOS: removed slapt_get file /etc/slapt-get/pubring.kbx, that's not a repo file. Thanks chrisreturn for pointing that out. 7a. CheckRecommends: See also CODE 6. Fixed case where > 1 package manager is detected on system, now lists them one by one for detected, and shows package install options as well. Before only picked first detected, which could lead to wrong results for Missing Package lists. 7b. CheckRecommends: Fixed glitch, forgot to update the current shell/version when ShellData was refactored, this led to no current shell + version showing up in recommends core tools report. 8. RAM: fixed speed_mapper string match to allow for older syntaxes. This is as far as known OpenBSD only, from dboot data. Matches then converts PC2700 to PC-2700 which then allows for mapping. 9. RAM/PROCESSES/INFO/SHORT: Finally tracked down a long time oddity, where for example: RAM: total: 31.28 GiB does not match 32 GiB physical installed. This is because that is the total available after kernel and system reserved RAM is deducted, and in some cases, GPU allocated RAM. There are also corner cases where the listed amount can be less due to physical RAM damage, but that's uncommon. Added explanation of why it's different, and what available is referring to in man -m/--memory. Changed -m, -tm to show: System RAM: available: 31.28 GiB used 26.23 GiB (83.9%) and -I to show: Memory: available: 31.28 GiB used 26.23 GiB (83.9%) You can get the 'reserved' and 'kernel code' data from dmesg, but since Debian made that root/sudo tool, can't count on being able to parse that out of dmesg, plus you can never count no dmesg anyway since it can get overwritten by kernel oops or wonky device etc. inxi doesn't use dmesg data for Linux for this reason. ... [ 0.000000] Memory: 32784756K/33435864K available (10252K kernel code, 1243K rwdata, 3324K rodata, 1584K init, 2280K bss, 651108K reserved, 0K cma-reserved) Also removed Raspberry Pi video RAM added back in to total now that it's clear it's what is available. This may also make systems with GPU using system RAM more correct. 9. SENSORS: sensors /sys tried to create concatenated string with $unit $value but these are not necessarily defined, that needed to be protected with defined tests. -------------------------------------------------------------------------------- ENHANCEMENTS: 1a. AUDIO: JACK: added helper nsmd (new session manager), and its recommended gui agordejo. That's the drop in replacement for non-session-manager, the dev of which apparently lost interest in that project. But the ID method will work fine for for either, since both ran as nsmd. 1b. AUDIO: PULSE: added pulseaudio-alsa plugin support for helpers. This is like pipewire-alsa plugin, just alsa config file. Only seen in Arch Linux so far, but if others use similar paths for the glob pattern, they will also work fine. Also added pulseaudio-esound-compat plugin, which is easier to detect with /usr/bin/esdcompat. Also added paman, pulseaudio manager. 1c. AUDIO: ESOUND,ARTS: added legacy esd (EsounD aka: Enlightened Sound Daemon) and aRts sound server support, with basic help/tools. These are quite old, but are still occasionally seen in the wild on newer systems, surprisingly enough. 1d. AUDIO: ALSA: added alsactl to alsa tools. Missed that one, it's an /sbin type utility. 1e. AUDIO: ALSA: First try at ALSA compiled in but inactive report, previously depended on active only state of the API. Now uses compiled in SND_ kernel switch using the /boot/config-[kernel] file, which is a big expensive parse but only will activate on Linux kernels with no /proc/asound present. This fallback fails if kernel config file not present: /boot/config-$(uname -r). 1f. AUDIO: OSS: added tool ossctl. 1g. AUDIO: NAS: added helper: audiooss which is an OSS compat layer. 2a. DistroData: added Arch base distros: ArchEX, Bridge Linux, Condres OS, Feliz, LiriOS, Magpie, Namib, Porteus, RevengeOS, SalientOS, VeltOS. None of these are verified. Some don't exist anymore. Source: https://www.slant.co/topics/7603/~arch-linux-based-distributions 2b. DistroData: added ubuntu lunar 23-4 release id. 2c. DistroData: added porteux, added porteux, zenwalk to slackware systembase 3. DesktopData/GRAPHICS: added Smithay Wayland compositor. Not verified. 4a. UsbData/UsbItem: added USB lanes (-Jxx) and mode (-Ja), to add more useful data about USB revision and mode names the USB group has created. Otherwise it's too difficult to try to explain it. Note that -Jxx lanes follows other inxi items that show PCIe lanes as an -xx item to try to keep it consistent. This also consolidates the bsd and linux data sources, see CODE 5. Note modes and lanes are Linux only because the revision number, lanes, and speed used to determine mode are only natively available in Linux as actual internal data values. If this changes BSD support will be added in the future. The BSD rev and speed data is synthesized completely by inxi using some string values, and thus is not reliable, which means that pretending inxi can get this granular with data that is not coming directly from the system itself is probably not a good idea. Following wikipedia mode names: https://en.wikipedia.org/wiki/USB4 These are the known possible combinations: rev: 1.0 mode: 1.0 lanes: 1 speed: 1.5 Mbps rev: 1.1 mode: 1.0 lanes: 1 speed: 1.5 Mbps rev: 1.1 mode: 1.1 lanes: 1 speed: 12 Mbps rev: 2.0 mode: 1.0 lanes: 1 speed: 1.5 Mbps rev: 2.0 mode: 1.1 lanes: 1 speed: 12 Mbps rev: 2.0 mode: 2.0 lanes: 1 speed: 480 Mbps rev: 2.1 mode: 2.0 lanes: 1 speed: 480 Mbps rev: 3.0 mode: 3.2 gen-1x1 lanes: 1 speed: 5 Gbps rev: 3.0 mode: 3.2 gen-1x2 lanes: 2 speed: 10 Gbps rev: 3.1 mode: 3.2 gen-1x1 lanes: 1 speed: 5 Gbps rev: 3.1 mode: 3.2 gen-1x2 lanes: 2 speed: 10 Gbps rev: 3.1 mode: 3.2 gen-2x2 lanes: 2 speed: 20 Gbps [seen this case] rev: 3.2 mode: 3.2 gen-1x1 lanes: 1 speed: 5 Gbps [wrong rev: seen this case] rev: 3.2 mode: 3.2 gen-1x2 lanes: 2 speed: 10 Gbps [wrong rev: possible case] rev: 3.2 mode: 3.2 gen-2x1 lanes: 1 speed: 10 Gbps rev: 3.2 mode: 3.2 gen-2x2 lanes: 2 speed: 20 Gbps rev: 3.2 mode: 4-v1 gen-3x2 lanes: 2 speed: 40 Gbps [not seen, but possible] rev: 4 mode: 4-v1 gen-2x1 lanes; 1 speed: 10 Gbps rev: 4 mode: 4-v1 gen-2x2 lanes: 2 speed: 20 Gbps rev: 4 mode: 4-v1 gen-3x1 lanes: 1 speed: 20 Gbps rev: 4 mode: 4-v2 gen-3x2 lanes: 2 speed: 40 Gbps rev: 4 mode: 4-v2 gen-4x1 lanes: 1 speed: 40 Gbps rev: 4 mode: 4-v2 gen-4x2 lanes: 2 speed: 80 Gbps rev: 4 mode: 4-v2 gen-4x3-asymmetric lanes: 3 up, 1 down speed:120 Gbps I believe 120Gbps takes the 2 lanes of tx/rx and converts 2 rx lanes to tx so the entire lane is dedicated to transmit. and the third lane is dedicated to rx. Includes error message for unknown usb 3/4 rev/speed match combos. These can be bad hardware self reporting or unknown other issues. 4b. USB: Added Si/IEC speeds (base 2, base 10). -Ja triggers extra IEC, base 2 Bytes (xxx [MG]iB/s). -Jx triggers basic standard Si xxx [MG]b/s base 10 bits. 5a. PackageData: added netpkg as package tool. This stores data in same location as slackpkg, but assume if exists directory /var/netpkg, then the system is using netpkg as pm, not slackpkg. 5b. PackageData: added Slackware sbopkg, sboui as tools for pkgtool and netpkg. 6a. REPOS: added netpkg (Zenwalk Slackware based pm) repo report. 6b. REPOS: added sbopkg basic repo report. This handles both value syntax types, as well as the ability of /root config file to overwrite /etc config repo. 6c. REPOS: added slpkg repo report. This handles their old and newer syntax. 7a. CheckRecommends: For Slackware users, added pkgtool missing package name, also will use netpkg so hopefully Zenwalk uses same package names. 7b. CheckRecommends: Added radeon to kernel modules checks. 8. AUDIO/BLUETOOTH/DRIVES/GRAPHICS/NETWORK: For USB, -[ADEGN]xx adds rev, speed, lanes. -[ADEGN]a adds mode. 9. RAM: Updated RAM PC DDR in speed_mapper(), which is as far as I know only used by OpenBSD, which allows for MT/s speeds as non-root user, which is nice. That list hadn't been updated in a long time, so filled out DDR 1-5 PCx-yyyy ids. -------------------------------------------------------------------------------- CHANGES: 1a. USB: For -Jxy1, speed is now a child of rev: parent. This goes along with mode: and lanes: being children of rev:. This follows how USB consortium wants to refer to USB revisions now: by speed, lanes, and modes, the latter being the technical term, the speed being the marketing term. 1b. USB: If no speed data found, show N/A. This should almost never happen except for very old Linux and rarely with BSD. 1c. USB: Device type is lower cased except for abbreviations (type-C, HID). This makes it more consistent as a value. 1d. USB: Show basic Si speed with -Jx, and adds new IEC speed with -Ja. 2. CheckRecommends: See ENHANCEMENT, CODE 6. Now showing row by row package managers and missing packages, by package manager(s). 3. DRIVES: Changed long standing redundant use of 'type': type: USB ... type: HDD to: type: USB ... tech: HDD 'tech:' means the technology used, HDD, SDD, and if we can ever figure out how to detect it, Hybrid Hard Drive (HHD), 4. AUDIO/BLUETOOTH/DRIVES/GRAPHIC/NETWORK: moved 'type: USB' pair to after driver for -A/-E/-G/-N, which allows it to be the parent of the new USB data block. Negative is it moves it a bit further back in the line. For Drives, it moves it from after /dev.. maj-min to after block-size, However, with -D/-Dx, it's last in the line, which is nice. This is the only way I could find to make it more consistent across all possible USB device/drive type reports. 5. INFO/RAM/PROCESSES: Changed -I: Memory: [total] used: to: Memory: available: [total] used: Changed -tm/-m to be consistent: Memory: RAM: total: .. used.. to: Memory: System RAM: available: ... used:.. This corrects a long standing inaccuracy where MemTotal is not actually the full system RAM, but is the RAM minus reserved stuff for system and kernel, and GPU memory in some cases. -------------------------------------------------------------------------------- DOCUMENTATION: 1a. DOCS: docs/inxi-audio.txt: ongoing updates, adding more information, more on helpers, detection methods, etc. 1b. DOCS: New: docs/inxi-usb.txt: USB info, update, added more, a work in progress. 1c. DOCS: docs/inxi-custom-recommends.txt: name in inxi comment did not match, and updated to new comment cleaned up syntax in example. Fixed inxi comment file name. 1d. DOCS: New: docs/inxi-unit-handling.txt: To document how inxi handles size/speed data internally, and ideally, to help integrate all those methods into one big tool one day, not spread across many area. 1e. DOCS: New: docs/inxi-repo-package-manager.txt: To start to document arcana and methods and commands and outputs for package managers. Since this is a late start, will take time to complete, but better late than never. 2a. MAN/OPTIONS: updated for USB -Jx, -Jxx, -Ja, adding lanes, mode, iec speed items. 2b. MAN/OPTIONS: fixed error which had USB speed as -Jxxx instead of -Jxx. Also then changed speed to be -Jx. 2c. MAN/OPTIONS: updated for repos for SBOPKG, SBOUI, SLPKG, and added SLAPT_GET, I'd forgotten that one. 2d. MAN/OPTIONS: updated for -xx[ADEGN] USB rev, speed, lanes; for -a[ADEGN] updated for USB mode. 2e. MAN/OPTIONS: updated for memory available/used changed. 3. MAN: fixed some inconsistent use of short/long form display in extra data options. -------------------------------------------------------------------------------- CODE: 1a. DesktopData: New function for xfce only detections, turns out xprop is not necessarily installed, Void Linux for example had failed ID. Old version required xprop to do the tests, which was not robust and failed in this case. Function: get_env_xfce_data(). Also made xprop data optional for all the xxx_xprop_data desktop tests, not just some of them. This will forward proof the desktops 1b. DesktopData: Fixed bad parens in test cases, was not correctly organized. if (a || b || (c || d) && e) was supposed to be: if (a || b || ((c || d) && e)) Odd how those types of glitches creep in, one fix is also to just make the lines break more reasonably so the conditions are easier to parse visually. 2a. DEBUGGER: Added /etc/X11/XF86Config-4 xorg conf file to debugger. 2b. DEBUGGER: audio_data(): added audio server versions to cover all known ones. 3. MemoryData: changed all $memory to array references, got rid of split : separators, which were clearly legacy items leftover from bash/gawk days. Also changed MemoryData::get('splits') to get('full') to reflect this change. This change should be transparent though it may introduce corner case undefined value situation but that should not happen since array values are defined first. 4. UsbData: Refactor of usb speed, rev, added lanes, mode. Refactored most of the bsd/linux rev/speed logic, merged some of bsd speed/rev into the new version_data() function, which loads all the data based on what is calling it. This helps consolidate the logic across usb data sources. 5a. GLOBAL: made functions/methods use same comment syntax for args: args: 0:...; 1:... always starting with 0, to match array index. Same syntax for return array index values. In some cases simply note a variable is passed by ref: args: $value passed by reference. 5b. GLOBAL: made all sub/functions/methods follow the same spacing syntax. This seems to be a good compromise for space/readability. Note that adding in these new lines added about 400 lines to the total length, plus the line breaks that were already there. Yes, inxi has a lot of sub routines! aka functions and sometimes aka methods. [empty line] [comments] sub [name] { Packages/classes now also all follow the same spacing rules: [empty line] [comments] { package [name]; [empty line] [comments] sub [name] { ... } } Internally, subs generally do not use any empty lines unless it makes sense to do so for some specific reason. 5c: GLOBAL: made start of sub comments be upper case, I have a bad habit of typing comments in lower case, easier to read if it's reads like a normal sentence. 6. CheckRecommends: refactored entire items logic, set global hash for test items. Made support > 1 detected package manager. 7. REPOS: cleaned up comments for package manager/repo blocks. 8. SENSORS: sensors_sys failed to reset to undefined $unit and $value, and also failed to test if they were defined before using them in concatenation. --- inxi | 3116 ++++++++++++++++++++++++++++++++---------------- inxi.1 | 158 ++- inxi.changelog | 486 ++++++++ 3 files changed, 2686 insertions(+), 1074 deletions(-) diff --git a/inxi b/inxi index f135510..9da545d 100755 --- a/inxi +++ b/inxi @@ -48,8 +48,8 @@ use POSIX qw(ceil uname strftime ttyname); ## INXI INFO ## my $self_name='inxi'; -my $self_version='3.3.26'; -my $self_date='2023-03-28'; +my $self_version='3.3.27'; +my $self_date='2023-05-07'; my $self_patch='00'; ## END INXI INFO ## @@ -210,6 +210,7 @@ sub initialize { { package CheckTools; my (%commands); + sub set { eval $start if $b_log; set_commands(); @@ -264,6 +265,7 @@ sub set { set_forced_tools(); eval $end if $b_log; } + sub set_dmidecode { my ($data) = @_; my $action = 'use'; @@ -308,6 +310,7 @@ sub set_dmidecode { } return $action; } + sub set_commands { # note: gnu/linux has sysctl so it may be used that for something if present # there is lspci for bsds so doesn't hurt to check it @@ -377,6 +380,7 @@ sub set_commands { $commands{'disklabel'} = ['missing','bsd','xx']; } } + sub set_forced_tools { if ($bt_tool){ if ($bt_tool ne 'bluetootctl' && $alerts{'bluetoothctl'}->{'action'} eq 'use'){ @@ -390,6 +394,7 @@ sub set_forced_tools { } } } + # only for dev/debugging BSD sub set_fake_bsd_tools { $system_files{'dmesg-boot'} = '/var/run/dmesg.boot' if $fake{'dboot'}; @@ -417,9 +422,6 @@ sub set_fake_bsd_tools { } } -# 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 sub set_basics { ### LOCALIZATION - DO NOT CHANGE! ### # set to default LANG to avoid locales errors with , or . @@ -689,8 +691,8 @@ sub set_xorg_log { my ($file_holder,$time_holder,$x_mtime) = ('',0,0); # NOTE: other variations may be /var/run/gdm3/... but not confirmed # 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'); + # and not which is 'right'. Xorg was XFree86 earlier, only in /var/log. + @temp = globber('/var/log/{Xorg,XFree86}.*.log'); push(@x_logs, @temp) if @temp; @temp = globber('/var/lib/gdm/.local/share/xorg/Xorg.*.log'); push(@x_logs, @temp) if @temp; @@ -739,7 +741,7 @@ sub set_xorg_log { #### COLORS #### ------------------------------------------------------------------- -## arg: 1 - the type of action, either integer, count, or full +## args: 0: the type of action, either integer, count, or full sub get_color_scheme { eval $start if $b_log; my ($type) = @_; @@ -897,13 +899,15 @@ my (@data,%configs,%status); my ($type,$w_fh); my $safe_color_count = 12; # null/normal + default color group my $count = 0; -# args: 1 - type + +# args: 0: type sub new { my $class = shift; ($type) = @_; my $self = {}; return bless $self, $class; } + sub select_schema { eval $start if $b_log; assign_selectors(); @@ -956,6 +960,7 @@ sub assign_selectors { $configs{'selection'} = 'global'; } } + sub start_selector { my $whoami = getpwuid($<) || "unknown???"; if (!$b_irc){ @@ -986,6 +991,7 @@ sub start_selector { main::print_basic(\@data); @data = (); } + sub create_color_selections { my $spacer = '^^'; # printer removes double spaces, but replaces ^ with ' ' $count = (main::get_color_scheme('count') - 1); @@ -1006,6 +1012,7 @@ sub create_color_selections { @data = (); main::set_color_scheme(0); } + sub get_selection { my $number = $count + 1; @data = ( @@ -1050,6 +1057,7 @@ sub get_selection { OpenBSD::Pledge::pledge(@pledges); } } + sub process_selection { my $response = shift; if ($response == ($count + 3)){ @@ -1100,6 +1108,7 @@ sub process_selection { set_config_color_scheme($response); } } + sub delete_all_colors { my @file_lines = main::reader($user_config_file); open($w_fh, '>', $user_config_file) or main::error_handler('open', $user_config_file, $!); @@ -1110,6 +1119,7 @@ sub delete_all_colors { } close $w_fh; } + sub delete_global_color { my @file_lines = main::reader($user_config_file); open($w_fh, '>', $user_config_file) or main::error_handler('open', $user_config_file, $!); @@ -1120,6 +1130,7 @@ sub delete_global_color { } close $w_fh; } + sub set_config_color_scheme { my $value = shift; my @file_lines = main::reader($user_config_file); @@ -1154,7 +1165,6 @@ sub print_irc_message { main::print_basic(\@data); exit 0; } - } #### ------------------------------------------------------------------- @@ -1165,6 +1175,7 @@ sub print_irc_message { # public: set() check_file() { package Configs; + sub set { my ($b_show) = @_; my ($b_files,$key, $val,@config_files); @@ -1209,6 +1220,7 @@ sub set { } return $b_files if $b_show; } + sub show { print "Showing current active/set configurations, by file. Last overrides previous.\n"; my $b_files = set(1); @@ -1221,11 +1233,13 @@ sub show { } exit 0; } + # 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 process_item { my ($key,$val) = @_; + ## UTILITIES ## if ($key eq 'ALLOW_UPDATE' || $key eq 'B_ALLOW_UPDATE'){ $use{'update'} = $val if main::is_int($val)} @@ -1296,6 +1310,7 @@ sub process_item { $weather_unit = $val; } } + ## COLORS/SEP ## elsif ($key eq 'CONSOLE_COLOR_SCHEME'){ $colors{'console'} = $val if main::is_int($val)} @@ -1318,6 +1333,7 @@ sub process_item { $sep{'s2-irc'} = $val} elsif ($key eq 'SEP2_CONSOLE'){ $sep{'s2-console'} = $val} + ## SIZES ## elsif ($key eq 'COLS_MAX_CONSOLE'){ $size{'console'} = $val if main::is_int($val)} @@ -1343,6 +1359,7 @@ sub process_item { # 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){ @@ -1399,10 +1416,8 @@ sub begin_logging { # NOTE: no logging available until get_parameters is run, since that's what # sets logging # in order to trigger earlier logging manually set $b_log # to true in top variables. -# args: $1 - type [fs|fe|cat|dump|raw] OR data to log -# arg: $2 - -# arg: $one type (fs/fe/cat/dump/raw) or logged data; -# [$two is function name; [$three - function args]] +# args: 0: type [fs|fe|cat|dump|raw]; 1: function name OR data to log; +# [2: function args OR hash/array ref] sub log_data { return if !$b_log; my ($one, $two, $three) = @_; @@ -1525,8 +1540,8 @@ my ($data_dir,$debug_dir,$debug_gz,$parse_src,$upload) = ('','','','',''); my @content; my $b_debug = 0; my $b_delete_dir = 1; -# args: 1 - type -# args: 2 - upload + +# args: 0: type; 1: upload sub new { my $class = shift; ($option) = @_; @@ -1582,6 +1597,7 @@ sub run_debugger { print $line3; compress_dir(); } + sub check_required_items { print "Loading required debugger Perl File:: modules... \n"; # Fedora/Redhat doesn't include File::Find File::Copy in @@ -1620,6 +1636,7 @@ sub check_required_items { } } } + sub create_debug_directory { my $host = main::get_hostname(); $host =~ s/ /-/g; @@ -1658,6 +1675,7 @@ sub create_debug_directory { } print "Debugger data going into:\n$data_dir\n"; } + sub compress_dir { print "Creating tar.gz compressed file of this material...\n"; print "File: $debug_gz\n"; @@ -1672,6 +1690,7 @@ sub compress_dir { print "Directory removed.\n"; } } + # NOTE: incomplete, don't know how to ever find out # what sound server is actually running, and is in control sub audio_data { @@ -1681,12 +1700,17 @@ sub audio_data { ['aplay', '--version'], # alsa ['aplay', '-l'], # alsa devices ['aplay', '-L'], # alsa list of features, can detect active sound server + ['artsd', '-v'], # aRts + ['esd', '-v'], # EsounD, to stderr + ['nasd', '-V'], # NAS + ['jackd', '--version'], # JACK ['pactl', '--version'], # pulseaudio ['pactl', 'info'], # pulseaudio, check if running as server: Server Name: ['pactl', 'list'], # pulseaudio ['pipewire', '--version'], # pipewire ['pipewire-alsa', '--version'], # pipewire-alsa - just config files ['pipewire-pulse', '--version'], # pipewire-pulse + ['pulseaudio', '--version'], # PulseAudio ['pw-jack', '--version'], # pipewire-jack ['pw-cli', 'ls'], # pipewire, check if running as server ['pw-cli', 'info all'], @@ -1709,9 +1733,10 @@ sub audio_data { push(@files,@files2) if @files2; copy_files(\@files,'audio'); } + sub bluetooth_data { print "Collecting bluetooth data...\n"; -# no warnings 'uninitialized'; + # no warnings 'uninitialized'; my @cmds = ( ['hciconfig','-a'], # no version #['hcidump',''], # hangs sometimes @@ -1880,6 +1905,7 @@ sub disk_data { ); run_commands(\@cmds,'disk-bsd'); } + sub display_data { my (%data,@files,@files2); my $working = ''; @@ -1905,6 +1931,7 @@ sub display_data { push(@files, '/var/lib/gdm/.local/share/xorg/Xorg.0.log'); push(@files, $ENV{'HOME'} . '/.local/share/xorg/Xorg.0.log'); push(@files, $system_files{'xorg-log'}) if $system_files{'xorg-log'}; + push(@files, '/etc/X11/XFCconfig-4'); # very old format for xorg.conf push(@files, '/etc/X11/xorg.conf'); copy_files(\@files,'display-xorg'); print "Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, Wayland info...\n"; @@ -1987,9 +2014,10 @@ sub display_data { ); run_commands(\@cmds,'display'); } + sub network_data { print "Collecting networking data...\n"; -# no warnings 'uninitialized'; + # no warnings 'uninitialized'; my @cmds = ( ['ifconfig',''], # no version maybe in bsd, --version in linux ['ip','-Version'], @@ -1998,6 +2026,7 @@ sub network_data { ); run_commands(\@cmds,'network'); } + sub perl_modules { print "Collecting Perl module data (this can take a while)...\n"; my @modules; @@ -2040,6 +2069,7 @@ sub perl_modules { print $fh $mods; close $fh; } + sub system_data { print "Collecting system data...\n"; # has to run here because if null, error, list constructor throws fatal error @@ -2218,6 +2248,7 @@ sub system_files { @files = main::globber('/sys/devices/system/cpu/vulnerabilities/*'); copy_files(\@files,'security'); } + ## SELF EXECUTE FOR LOG/OUTPUT sub run_self { print "Creating $self_name output file now. This can take a few seconds...\n"; @@ -2270,6 +2301,7 @@ sub copy_files { } } } + sub run_commands { my ($cmds,$type) = @_; my $holder = ''; @@ -2300,6 +2332,7 @@ sub run_commands { } } } + sub get_glob { my ($type,$id,$glob) = @_; my @files = main::globber($glob); @@ -2319,6 +2352,7 @@ sub get_glob { # print Data::Dumper::Dumper \@result; main::writer("$data_dir/$type-data-$id-glob.txt",\@result); } + sub write_data { my ($data_ref, $type) = @_; my ($empty,$error,$fh,$good,$name,$undefined,$value); @@ -2343,6 +2377,7 @@ sub write_data { } } } + ## TOOLS FOR DIRECTORY TREE/LS/TRAVERSE; UPLOADER sub build_tree { my ($which) = @_; @@ -2431,6 +2466,7 @@ sub directory_ls { close $fh; # print "$output\n"; } + sub proc_traverse_data { print "Building /proc file list...\n"; # get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied @@ -2441,6 +2477,7 @@ sub proc_traverse_data { process_proc_traverse(); @content = (); } + sub process_proc_traverse { my ($data,$fh,$result,$row,$sep); my $proc_dir = "$data_dir/proc"; @@ -2448,7 +2485,7 @@ sub process_proc_traverse { mkdir $proc_dir or main::error_handler('mkdir', "$proc_dir", "$!"); # @content = sort @content; copy_files(\@content,'proc',$proc_dir); -# foreach (@content){print "$_\n";} + # foreach (@content){print "$_\n";} } sub sys_traverse_data { @@ -2461,6 +2498,7 @@ sub sys_traverse_data { process_sys_traverse(); @content = (); } + sub process_sys_traverse { my ($data,$fh,$result,$row,$sep); my $filename = "sys-data-parse.txt"; @@ -2493,6 +2531,7 @@ sub process_sys_traverse { close $fh; # print $fh "$result"; } + # perl compiler complains on start if prune = 1 used only once, so either # do $File::Find::prune = 1 if !$File::Find::prune; OR use no warnings 'once' sub wanted { @@ -2546,8 +2585,8 @@ sub wanted { push(@content, $File::Find::name); return; } -# args: 1 - path to file to be uploaded -# args: 2 - optional: alternate ftp upload url + +# args: 0: path to file to be uploaded; 1: optional: alternate ftp upload url # NOTE: must be in format: ftp.site.com/incoming sub upload_file { my ($self, $ftp_url) = @_; @@ -2562,12 +2601,10 @@ sub upload_file { $domain =~ s/^ftp\.//; $user = "anonymous"; $pass = "anonymous\@$domain"; - print $line3; print "Uploading to: $ftp_url\n"; # print "$host $domain $dir $user $pass\n"; print "File to be uploaded:\n$file_path\n"; - if ($host && ($file_path && -e $file_path)){ # NOTE: important: must explicitly set to passive true/1 $ftp = Net::FTP->new($host, Debug => 0, Passive => 1) || main::error_handler('ftp-connect', $ftp->message); @@ -2901,30 +2938,32 @@ sub error_defaults { ## CheckRecommends { package CheckRecommends; -my (@modules); +my ($item_data,@modules,@pms); + sub run { main::error_handler('not-in-irc', 'recommends') if $b_irc; my (@data,@rows); my $rows = []; my $line = main::make_line(); - my $pm = get_pm(); - basic_data($rows,$line,$pm); + @pms = get_pms(); + set_item_data(); + basic_data($rows,$line); if (!$bsd_type){ - check_items($rows,'required system directories',$line,$pm); + check_items($rows,'required system directories',$line); } - check_items($rows,'recommended system programs',$line,$pm); - check_items($rows,'recommended display information programs',$line,$pm); - check_items($rows,'recommended downloader programs',$line,$pm); + check_items($rows,'recommended system programs',$line); + check_items($rows,'recommended display information programs',$line); + check_items($rows,'recommended downloader programs',$line); if (!$bsd_type){ - check_items($rows,'recommended kernel modules',$line,$pm); + check_items($rows,'recommended kernel modules',$line); } - check_items($rows,'recommended Perl modules',$line,$pm); - check_items($rows,'recommended directories',$line,''); - check_items($rows,'recommended files',$line,''); + check_items($rows,'recommended Perl modules',$line); + check_items($rows,'recommended directories',$line); + check_items($rows,'recommended files',$line); push(@$rows, ['0', '', '', "$line"], ['0', '', '', "Ok, all done with the checks. Have a nice day."], - ['0', '', '', " "], + ['0', '', '', ''], ); # print Data::Dumper::Dumper $rows; main::print_basic($rows); @@ -2932,10 +2971,11 @@ sub run { } sub basic_data { - my ($rows,$line,$pm_local) = @_; + my ($rows,$line) = @_; my (@data,@rows); + $extra = 1; # needed for shell version + ShellData::set(); my $client = $client{'name-print'}; - $pm_local ||= 'N/A'; $client .= ' ' . $client{'version'} if $client{'version'}; my $default_shell = 'N/A'; if ($ENV{'SHELL'}){ @@ -2947,24 +2987,36 @@ sub basic_data { push(@$rows, ['0', '', '', "$self_name will now begin checking for the programs it needs to operate."], - ['0', '', '', "" ], + ['0', '', '', ""], ['0', '', '', "Check $self_name --help or the man page (man $self_name) - to see what options are available." ], - ['0', '', '', "$line" ], - ['0', '', '', "Test: core tools:" ], - ['0', '', '', "" ], - ['0', '', '', "Perl version: ^$]" ], - ['0', '', '', "Current shell: " . $client ], - ['0', '', '', "Default shell: " . $default_shell ], - ['0', '', '', "sh links to: $sh_real" ], - ['0', '', '', "Package manager: $pm_local" ], + to see what options are available."], + ['0', '', '', "$line"], + ['0', '', '', "Test: core tools:"], + ['0', '', '', ""], + ['0', '', '', "Perl version: ^$]"], + ['0', '', '', "Current shell: " . $client], + ['0', '', '', "Default shell: " . $default_shell], + ['0', '', '', "sh links to: $sh_real"], ); + if (scalar @pms == 0){ + push(@$rows,['0', '', '', "Package manager(s): No supported PM(s) detected"]); + } + elsif (scalar @pms == 1){ + push(@$rows,['0', '', '', "Package manager: $pms[0]"]); + } + else { + push(@$rows,['0', '', '', "Package managers detected:"]); + foreach my $pm (@pms){ + push(@$rows,['0', '', '', " pm: $pm"]); + } + } } + sub check_items { - my ($rows,$type,$line,$pm) = @_; + my ($rows,$type,$line) = @_; my (@data,@missing,$row,$result,@unreadable); my ($b_dir,$b_file,$b_kernel_module,$b_perl_module,$b_program,$item); - my ($about,$extra,$extra2,$extra3,$extra4,$info_os,$install) = ('','','','','','info',''); + my ($about,$extra,$extra2,$extra3,$extra4,$info_os) = ('','','','','','info'); if ($type eq 'required system directories'){ @data = qw(/proc /sys); $b_dir = 1; @@ -3035,7 +3087,7 @@ sub check_items { "; } elsif ($type eq 'recommended kernel modules'){ - @data = qw(amdgpu drivetemp nouveau); + @data = qw(amdgpu drivetemp nouveau radeon); @modules = main::lister('/sys/module/'); $b_kernel_module = 1; $extra2 = "GPU modules are only needed if applicable. NVMe drives do not need drivetemp @@ -3073,22 +3125,21 @@ sub check_items { push(@$rows, ['0', '', '', "$line" ], ['0', '', '', "Test: $type$extra:" ], - ['0', '', '', " " ], + ['0', '', '', ''], ); if ($extra2){ push(@$rows, ['0', '', '', $extra2], - ['0', '', '', ' ']); + ['0', '', '', '']); } if ($extra3){ push(@$rows, ['0', '', '', $extra3], - ['0', '', '', ' ']); + ['0', '', '', '']); } foreach my $item (@data){ - $install = ''; - $about = ''; - my $info = item_data($item); + undef $about; + my $info = $item_data->{$item}; $about = $info->{$info_os}; if (($b_dir && -d $item) || ($b_file && -r $item) || ($b_program && main::check_program($item)) || @@ -3102,20 +3153,24 @@ sub check_items { } else { $result = 'Missing'; - if (($b_program || $b_perl_module) && $pm){ - $info->{$pm} ||= 'N/A'; - $install = " ~ Install package: $info->{$pm}"; + push(@missing,"$item"); + if (($b_program || $b_perl_module) && @pms){ + my @install; + foreach my $pm (@pms){ + $info->{$pm} ||= 'N/A'; + push(@install," $pm: $info->{$pm}"); + } + push(@missing,@install); } - push(@missing, "$item$install"); } $row = make_row($item,$about,$result); push(@$rows, ['0', '', '', $row]); } - push(@$rows, ['0', '', '', " "]); + push(@$rows, ['0', '', '', '']); if (@missing){ push(@$rows, ['0', '', '', "The following $type are missing$extra4:"]); foreach (@missing){ - push(@$rows, ['0', '', '', "$item: $_"]); + push(@$rows, ['0', '', '', $_]); } } if (@unreadable){ @@ -3129,10 +3184,9 @@ sub check_items { } } -sub item_data { - my ($type) = @_; - my $data = { - # Directory Data +sub set_item_data { + $item_data = { + ## Directory Data ## '/dev' => { 'info' => '-l,-u,-o,-p,-P,-D disk partition data', }, @@ -3160,7 +3214,7 @@ sub item_data { '/sys/class/hwmon' => { 'info' => '-s sensor data (fallback if no lm-sensors)', }, - # File Data + ## File Data ## '/etc/lsb-release' => { 'info' => '-S distro version data (older version)', }, @@ -3197,9 +3251,9 @@ sub item_data { '/var/run/dmesg.boot' => { 'info' => '-D,-d disk data', }, - ## Kernel Module Data + ## Kernel Module Data ## 'amdgpu' => { - 'info' => '-s AMD GPU sensor data (newer AMD GPUs)', + 'info' => '-s, -G AMD GPU sensor data (newer GPUs)', 'info-bsd' => '', }, 'drivetemp' => { @@ -3207,17 +3261,24 @@ sub item_data { 'info-bsd' => '', }, 'nouveau' => { - 'info' => '-s Nvidia GPU sensor data (if using free driver)', + 'info' => '-s, -G Nvidia GPU sensor data (if using free driver)', + 'info-bsd' => '', + }, + 'radeon' => { + 'info' => '-s, -G AMD GPU sensor data (older GPUs)', 'info-bsd' => '', }, ## START PACKAGE MANAGER BLOCK ## - # Note: see inxi-perl branch for details: docs/recommends-package-manager.txt + # BSD only tools do not list package manager install names + ## Programs-System ## + # Note: see inxi-perl branch for details: docs/inxi-custom-recommends.txt # System Tools 'blockdev' => { 'info' => '--admin -p/-P (filesystem blocksize)', 'info-bsd' => '', 'apt' => 'util-linux', 'pacman' => 'util-linux', + 'pkgtool' => 'util-linux', 'rpm' => 'util-linux', }, 'bt-adapter' => { @@ -3225,6 +3286,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'bluez-tools', 'pacman' => 'bluez-tools', + 'pkgtool' => '', # needs to be built by user 'rpm' => 'bluez-tools', }, 'curl' => { @@ -3232,34 +3294,31 @@ sub item_data { 'info-bsd' => '-i (if no dig); -w,-W; -U', 'apt' => 'curl', 'pacman' => 'curl', + 'pkgtool' => 'curl', 'rpm' => 'curl', }, 'camcontrol' => { 'info' => '', 'info-bsd' => '-R; -D; -P. Get actual gptid /dev path', - 'apt' => '', - 'pacman' => '', - 'rpm' => '', }, 'dig' => { 'info' => '-i wlan IP', 'info-bsd' => '-i wlan IP', 'apt' => 'dnsutils', 'pacman' => 'dnsutils', + 'pkgtool' => 'bind', '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', 'apt' => 'dmidecode', 'pacman' => 'dmidecode', + 'pkgtool' => 'dmidecode', 'rpm' => 'dmidecode', }, 'doas' => { @@ -3267,6 +3326,7 @@ sub item_data { 'info-bsd' => '-Dx hddtemp-user; -o file-user', 'apt' => 'doas', 'pacman' => 'doas', + 'pkgtool' => ' opendoas', 'rpm' => 'doas', }, 'fdisk' => { @@ -3274,55 +3334,47 @@ sub item_data { 'info-bsd' => '-D partition scheme', 'apt' => 'fdisk', 'pacman' => 'util-linux', + 'pkgtool' => 'util-linux', 'rpm' => 'util-linux', }, 'fetch' => { 'info' => '', 'info-bsd' => '-i (if no dig); -w,-W; -U', - 'apt' => '', - 'pacman' => '', - 'rpm' => '', }, 'file' => { 'info' => '-o unmounted file system (if no lsblk)', 'info-bsd' => '-o unmounted file system', 'apt' => 'file', 'pacman' => 'file', + 'pkgtool' => 'file', 'rpm' => 'file', }, 'ftp' => { 'info' => '', 'info-bsd' => '-i (if no dig); -w,-W; -U', - 'apt' => '', - 'pacman' => '', - 'rpm' => '', }, 'fruid_print' => { 'info' => '-M machine data, Elbrus only', 'info-bsd' => '', 'apt' => '', 'pacman' => '', + 'pkgtool' => '', 'rpm' => '', }, 'glabel' => { 'info' => '', 'info-bsd' => '-R; -D; -P. Get actual gptid /dev path', - 'apt' => '', - 'pacman' => '', - 'rpm' => '', }, 'gpart' => { 'info' => '', 'info-bsd' => '-p,-P; -R; -o (FreeBSD+derived)', - 'apt' => '', - 'pacman' => '', - 'rpm' => '', }, 'hciconfig' => { 'info' => '-E bluetooth data (deprecated, good report)', 'info-bsd' => '', 'apt' => 'bluez', 'pacman' => 'bluez-utils-compat (frugalware: bluez-utils)', + 'pkgtool' => 'bluez', 'rpm' => 'bluez-utils', }, 'hddtemp' => { @@ -3330,6 +3382,7 @@ sub item_data { 'info-bsd' => '-Dx show hdd temp', 'apt' => 'hddtemp', 'pacman' => 'hddtemp', + 'pkgtool' => 'hddtemp', 'rpm' => 'hddtemp', }, 'ifconfig' => { @@ -3337,6 +3390,7 @@ sub item_data { 'info-bsd' => '-i ip LAN', 'apt' => 'net-tools', 'pacman' => 'net-tools', + 'pkgtool' => 'net-tools', 'rpm' => 'net-tools', }, 'ip' => { @@ -3344,6 +3398,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'iproute', 'pacman' => 'iproute2', + 'pkgtool' => 'iproute2', 'rpm' => 'iproute', }, 'ipmi-sensors' => { @@ -3351,6 +3406,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'freeipmi-tools', 'pacman' => 'freeipmi', + 'pkgtool' => 'freeipmi', 'rpm' => 'freeipmi', }, 'ipmitool' => { @@ -3358,6 +3414,7 @@ sub item_data { 'info-bsd' => '-s IPMI sensors (servers)', 'apt' => 'ipmitool', 'pacman' => 'ipmitool', + 'pkgtool' => 'ipmitool', 'rpm' => 'ipmitool', }, 'lsblk' => { @@ -3365,6 +3422,7 @@ sub item_data { 'info-bsd' => '-o unmounted file system', 'apt' => 'util-linux', 'pacman' => 'util-linux', + 'pkgtool' => 'util-linux', 'rpm' => 'util-linux-ng', }, 'lvs' => { @@ -3372,6 +3430,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'lvm2', 'pacman' => 'lvm2', + 'pkgtool' => 'lvm2', 'rpm' => 'lvm2', }, 'lsusb' => { @@ -3379,6 +3438,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'usbutils', 'pacman' => 'usbutils', + 'pkgtool' => 'usbutils', 'rpm' => 'usbutils', }, 'mdadm' => { @@ -3386,6 +3446,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'mdadm', 'pacman' => 'mdadm', + 'pkgtool' => 'mdadm', 'rpm' => 'mdadm', }, 'modinfo' => { @@ -3393,34 +3454,27 @@ sub item_data { 'info-bsd' => '', 'apt' => 'module-init-tools', 'pacman' => 'module-init-tools', + 'pkgtool' => 'kmod (earlier: 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' => '', 'apt' => 'systemd or sysvinit', 'pacman' => 'systemd', + 'pkgtool' => 'sysvinit', 'rpm' => 'systemd or sysvinit', }, 'sensors' => { @@ -3428,6 +3482,7 @@ sub item_data { 'info-bsd' => '', 'apt' => 'lm-sensors', 'pacman' => 'lm-sensors', + 'pkgtool' => 'lm_sensors', 'rpm' => 'lm-sensors', }, 'smartctl' => { @@ -3435,34 +3490,35 @@ sub item_data { 'info-bsd' => '-Da advanced data', 'apt' => 'smartmontools', 'pacman' => 'smartmontools', + 'pkgtool' => 'smartmontools', 'rpm' => 'smartmontools', }, 'strings' => { 'info' => '-I sysvinit version', 'info-bsd' => '', 'apt' => 'binutils', - 'pacman' => '?', - 'rpm' => '?', + 'pacman' => 'binutils', + 'pkgtool' => 'binutils', + 'rpm' => 'binutils', }, 'sudo' => { 'info' => '-Dx hddtemp-user; -o file-user (try doas!)', 'info-bsd' => '-Dx hddtemp-user; -o file-user (alt for doas)', 'apt' => 'sudo', 'pacman' => 'sudo', + 'pkgtool' => 'sudo', 'rpm' => 'sudo', }, 'sysctl' => { 'info' => '', 'info-bsd' => '-C; -I; -m; -tm', - 'apt' => '?', - 'pacman' => '?', - 'rpm' => '?', }, 'tree' => { 'info' => '--debugger 20,21 /sys tree', 'info-bsd' => '--debugger 20,21 /sys tree', 'apt' => 'tree', 'pacman' => 'tree', + 'pkgtool' => 'tree', 'rpm' => 'tree', }, 'upower' => { @@ -3470,6 +3526,7 @@ sub item_data { 'info-bsd' => '-sx attached device battery info', 'apt' => 'upower', 'pacman' => 'upower', + 'pkgtool' => 'upower', 'rpm' => 'upower', }, 'uptime' => { @@ -3477,35 +3534,32 @@ sub item_data { 'info-bsd' => '-I uptime', 'apt' => 'procps', 'pacman' => 'procps', + 'pkgtool' => 'procps', 'rpm' => 'procps', }, 'usbconfig' => { 'info' => '', '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; (Open/NetBSD+derived)', - 'apt' => 'usbutils', - 'pacman' => 'usbutils', - 'rpm' => 'usbutils', }, 'wget' => { 'info' => '-i (if no dig); -w,-W; -U', 'info-bsd' => '-i (if no dig); -w,-W; -U', 'apt' => 'wget', 'pacman' => 'wget', + 'pkgtool' => 'wget', 'rpm' => 'wget', }, - # Display Tools + ## Programs-Display ## 'glxinfo' => { 'info' => '-G (X) glx info', 'info-bsd' => '-G (X) glx info', 'apt' => 'mesa-utils', 'pacman' => 'mesa-demos', + 'pkgtool' => 'mesa', 'rpm' => 'glx-utils (SUSE: Mesa-demo-x)', }, 'wmctrl' => { @@ -3513,6 +3567,7 @@ sub item_data { 'info-bsd' => '-S active window managerr (fallback)', 'apt' => 'wmctrl', 'pacman' => 'wmctrl', + 'pkgtool' => 'wmctrl', 'rpm' => 'wmctrl', }, 'xdpyinfo' => { @@ -3520,6 +3575,7 @@ sub item_data { 'info-bsd' => '-G (X) Screen resolution, dpi; -Ga Screen size', 'apt' => 'X11-utils', 'pacman' => 'xorg-xdpyinfo', + 'pkgtool' => 'xdpyinfo', 'rpm' => 'xorg-x11-utils (SUSE/Fedora?: xdpyinfo)', }, 'xdriinfo' => { @@ -3527,6 +3583,7 @@ sub item_data { 'info-bsd' => '-G (X) DRI driver (if missing, fallback to Xorg log', 'apt' => 'X11-utils', 'pacman' => 'xorg-xdriinfo', + 'pkgtool' => 'xdriinfo', 'rpm' => 'xorg-x11-utils (SUSE/Fedora?: xdriinfo)', }, 'xprop' => { @@ -3534,6 +3591,7 @@ sub item_data { 'info-bsd' => '-S (X) desktop data', 'apt' => 'X11-utils', 'pacman' => 'xorg-xprop', + 'pkgtool' => 'xprop', 'rpm' => 'x11-utils', }, 'xrandr' => { @@ -3541,42 +3599,48 @@ sub item_data { 'info-bsd' => '-G (X) monitors(s) resolution; -Ga monitor data', 'apt' => 'x11-xserver-utils', 'pacman' => 'xrandr', + 'pkgtool' => 'xrandr', 'rpm' => 'x11-server-utils (Fedora: xrandr)', }, - # Perl Modules + ## Perl Modules ## 'Cpanel::JSON::XS' => { - 'info' => '--output json (faster than JSON::PP).', - 'info-bsd' => '--output json (faster than JSON::PP).', + 'info' => '-G wayland, --output json (faster).', + 'info-bsd' => '-G wayland, --output json (faster).', 'apt' => 'libcpanel-json-xs-perl', 'pacman' => 'perl-cpanel-json-xs', + 'pkgtool' => 'perl-Cpanel-JSON-XS', 'rpm' => 'perl-Cpanel-JSON-XS', }, 'File::Copy' => { - 'info' => '--debug 20-22 - required to run debugger.', - 'info-bsd' => '--debug 20-22 - required to run debugger.', + 'info' => '--debug 20-22 - required for debugger.', + 'info-bsd' => '--debug 20-22 - required for debugger.', 'apt' => 'Core Modules', 'pacman' => 'Core Modules', + 'pkgtool' => 'Core Modules', 'rpm' => 'perl-File-Copy', }, 'File::Find' => { - 'info' => '--debug 20-22 - required to run debugger.', - 'info-bsd' => '--debug 20-22 - required to run debugger.', + 'info' => '--debug 20-22 - required for debugger.', + 'info-bsd' => '--debug 20-22 - required for debugger.', 'apt' => 'Core Modules', 'pacman' => 'Core Modules', + 'pkgtool' => 'Core Modules', 'rpm' => 'perl-File-Find', }, 'File::Spec::Functions' => { - 'info' => '--debug 20-22 - required to run debugger.', - 'info-bsd' => '--debug 20-22 - required to run debugger.', + 'info' => '--debug 20-22 - required for debugger.', + 'info-bsd' => '--debug 20-22 - required for debugger.', 'apt' => 'Core Modules', 'pacman' => 'Core Modules', + 'pkgtool' => 'Core Modules', 'rpm' => 'Core Modules', }, 'HTTP::Tiny' => { 'info' => '-U; -w,-W; -i (if dig not installed).', 'info-bsd' => '-U; -w,-W; -i (if dig not installed)', - 'apt' => 'libhttp-tiny-perl', + 'apt' => 'libhttp-tiny-perl (Core Modules >= 5.014)', 'pacman' => 'Core Modules', + 'pkgtool' => 'perl-http-tiny (Core Modules >= 5.014)', 'rpm' => 'Perl-http-tiny', }, 'IO::Socket::SSL' => { @@ -3584,20 +3648,23 @@ sub item_data { 'info-bsd' => '-U; -w,-W; -i (if dig not installed)', 'apt' => 'libio-socket-ssl-perl', 'pacman' => 'perl-io-socket-ssl', + 'pkgtool' => 'perl-IO-Socket-SSL', # maybe in core modules 'rpm' => 'perl-IO-Socket-SSL', }, 'JSON::PP' => { - 'info' => '--output json (in CoreModules, but slower).', - 'info-bsd' => '--output json (in CoreModules, but slower).', - 'apt' => 'libjson-pp-perl', - 'pacman' => 'perl-json-pp', + 'info' => '-G wayland, --output json (in CoreModules, slower).', + 'info-bsd' => '-G wayland, --output json (in CoreModules, slower).', + 'apt' => 'libjson-pp-perl (Core Modules >= 5.014)', + 'pacman' => 'perl-json-pp (Core Modules >= 5.014)', + 'pkgtool' => 'Core Modules >= 5.014', 'rpm' => 'perl-JSON-PP', }, 'JSON::XS' => { - 'info' => '--output json (legacy).', - 'info-bsd' => '--output json (legacy).', + 'info' => '-G wayland, --output json (legacy).', + 'info-bsd' => '-G wayland, --output json (legacy).', 'apt' => 'libjson-xs-perl', 'pacman' => 'perl-json-xs', + 'pkgtool' => 'perl-JSON-XS', 'rpm' => 'perl-JSON-XS', }, 'Net::FTP' => { @@ -3605,27 +3672,23 @@ sub item_data { 'info-bsd' => '--debug 21,22', 'apt' => 'Core Modules', 'pacman' => 'Core Modules', + 'pkgtool' => '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', 'apt' => 'Core Modules', 'pacman' => 'Core Modules', + 'pkgtool' => 'Core Modules', 'rpm' => 'perl-Time-HiRes', }, 'XML::Dumper' => { @@ -3633,26 +3696,33 @@ sub item_data { 'info-bsd' => '--output xml - Crude and raw.', 'apt' => 'libxml-dumper-perl', 'pacman' => 'perl-xml-dumper', + 'pkgtool' => '', # package does not appear to exist 'rpm' => 'perl-XML-Dumper', }, ## END PACKAGE MANAGER BLOCK ## }; - return $data->{$type}; } -sub get_pm { - my ($pm) = (''); + +sub get_pms { + my @pms = (); # support maintainers of other pm types using custom lists if (main::check_program('dpkg')){ - $pm = 'apt'; + push(@pms,'apt'); } - elsif (main::check_program('pacman')){ - $pm = 'pacman'; + if (main::check_program('pacman')){ + push(@pms,'pacman'); } - elsif (main::check_program('rpm')){ - $pm = 'rpm'; + # assuming netpkg uses installpkg as backend + if (main::check_program('installpkg')){ + push(@pms,'pkgtool'); } - return $pm; + # rpm needs to go last because it's sometimes available on other pm systems + if (main::check_program('rpm')){ + push(@pms,'rpm'); + } + return @pms; } + # note: end will vary, but should always be treated as longest value possible. # expected values: Present/Missing sub make_row { @@ -3672,7 +3742,7 @@ sub make_row { # Duplicates the functionality of awk to allow for one liner # type data parsing. note: -1 corresponds to awk NF -# args 1: array of data; 2: search term; 3: field result; 4: separator +# args: 0: array of data; 1: search term; 2: field result; 3: separator # correpsonds to: awk -F='separator' '/search/ {print $2}' <<< @data # array is sent by reference so it must be dereferenced # NOTE: if you just want the first row, pass it \S as search string @@ -3701,7 +3771,7 @@ sub awk { return $result; } -# $1 - Perl module to check +# 0: Perl module to check sub check_perl_module { my ($module) = @_; my $b_present = 0; @@ -3710,7 +3780,7 @@ sub check_perl_module { return $b_present; } -# arg: 1 - string or path to search gneerated @paths data for. +# args: 0: string or path to search gneerated @paths data for. # note: a few nano seconds are saved by using raw $_[0] for program sub check_program { (grep { return "$_/$_[0]" if -e "$_/$_[0]"} @paths)[0]; @@ -3725,7 +3795,7 @@ sub cleanup { } } -# args: $1, $2, version numbers to compare by turning them to strings +# args: 0,1: version numbers to compare by turning them to strings # note that the structure of the two numbers is expected to be fairly # similar, otherwise it may not work perfectly. sub compare_versions { @@ -3758,9 +3828,9 @@ sub count_dir_files { return $count; } -# args: 1 - the string to get piece of -# 2 - the position in string, starting at 1 for 0 index. -# 3 - the separator, default is ' ' +# args: 0: the string to get piece of +# 1: the position in string, starting at 1 for 0 index. +# 2: the separator, default is ' ' sub get_piece { eval $start if $b_log; my ($string, $num, $sep) = @_; @@ -3775,8 +3845,8 @@ sub get_piece { } } -# arg: 1 - command to turn into an array; 2 - optional: splitter -# 3 - optionsl, strip and clean data +# args: 0: command to turn into an array; 1: optional: splitter; +# 2: optionsl, strip and clean data # similar to reader() except this creates an array of data # by lines from the command arg sub grabber { @@ -3799,7 +3869,7 @@ sub grabber { return ($type eq 'arr') ? @rows : \@rows; } -# args: 1 - string value to glob +# args: 0: string value to glob sub globber { eval $start if $b_log; my @files = <$_[0]>; @@ -3828,7 +3898,7 @@ sub is_numeric { # gets array ref, which may be undefined, plus join string # this helps avoid debugger print errors when we are printing arrays # which we don't know are defined or not null. -# args: 1 - array ref; 2 - join string; 3 - default value, optional +# args: 0: array ref; 1: join string; 2: default value, optional sub joiner { my ($arr,$join,$default) = @_; $default ||= ''; @@ -3886,8 +3956,8 @@ sub load_json { } # returns array of: 0: program print name 1: program version -# args: 1: program values id 2: program version string -# 3: $extra level. Note that StartClient runs BEFORE -x levels are set! +# args: 0: program values id; 1: program version string; +# 2: $extra level. Note that StartClient runs BEFORE -x levels are set! # Only use this function when you only need the name/version data returned sub program_data { eval $start if $b_log; @@ -4089,6 +4159,7 @@ sub set_program_values { 'scrotwm' => ['^scrotwm.*welcome.*',5,'-v','scrotwm',0,1,1,'',''], 'simulavr' => ['simulavr^',0,'0','SimulaVR',0,1,0,'',''], # unverified 'skylight' => ['^skylight',0,'0','Skylight',0,1,0,'',''], # unverified + 'smithay' => ['^smithay',0,'0','Smithay',0,1,0,'',''], # unverified 'sommelier' => ['^sommelier',0,'0','sommelier',0,1,0,'',''], # unverified 'snapwm' => ['^snapwm',0,'0','snapwm',0,1,0,'',''], # unverified 'spectrwm' => ['^spectrwm.*welcome.*wm',5,'-v','spectrwm',0,1,1,'',''], @@ -4140,6 +4211,7 @@ sub set_program_values { 'wxrc' => ['^wx',0,'0','',0,1,0,'WXRC',''], # unverified 'wxrd' => ['^wx',0,'0','',0,1,0,'WXRD',''], # unverified 'xcompmgr' => ['^xcompmgr',0,'0','xcompmgr',0,1,0,'',''], # no version + 'xfce-panel' => ['^xfce-panel',2,'--version','Xfce',0,1,0,'',''], 'xfce4-panel' => ['^xfce4-panel',2,'--version','Xfce',0,1,0,'',''], 'xfce5-panel' => ['^xfce5-panel',2,'--version','Xfce',0,1,0,'',''], 'xfdesktop' => ['xfdesktop[[:space:]]version',5,'--version','Xfce',0,1,0,'',''], @@ -4225,13 +4297,13 @@ sub set_program_values { } # returns array of: -# 0 - match string; 1 - search number; 2 - version string [alt: file]; -# 3 - Print name; 4 - console 0/1; -# 5 - 0/1 exit version loop at 1 [alt: if version=file replace value with \s]; -# 6 - 0/1 write to stderr [alt: if version=file, path for file] -# 7 - replace regex for further cleanup; 8 - extra data +# 0: match string; 1: search number; 2: version string [alt: file]; +# 3: Print name; 4: console 0/1; +# 5: 0/1 exit version loop at 1 [alt: if version=file replace value with \s]; +# 6: 0/1 write to stderr [alt: if version=file, path for file]; +# 7: replace regex for further cleanup; 8: extra data # note: setting index 1 or 2 to 0 will trip flags to not do version -# arg: 1 - program lower case name +# args: 0: program lower case name sub program_values { my ($app) = @_; my (@program_data); @@ -4244,10 +4316,10 @@ sub program_values { return @program_data; } -# 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 -# 7 - replace regex; 8 - extra data +# args: 0: desktop/app command for --version; 1: search string; +# 2: space print number; 3: [optional] version arg: -v, version, etc; +# 4: [optional] exit first find 0/1; 5: [optional] 0/1 stderr output; +# 6: replace regex; 7: extra data sub program_version { eval $start if $b_log; my ($app,$search,$num,$version,$exit,$stderr,$replace,$extra) = @_; @@ -4381,9 +4453,9 @@ sub program_version_pkg { return @data; } -# arg: 1 - full file path, returns array of file lines. -# 2 - optionsl, strip and clean data -# 3 - optional: undef|arr|ref|index return specific index, if it exists, else undef +# args: 0: full file path, returns array of file lines; +# 1: optionsl, strip and clean data; +# 2: optional: undef|arr|ref|index return specific index, if it exists, else undef # note: chomp has to chomp the entire action, not just <$fh> sub reader { eval $start if $b_log; @@ -4415,7 +4487,7 @@ sub reader { return $rows[$type]; } -# args: 1 - the file to create if not exists +# args: 0: the file to create if not exists sub toucher { my $file = shift; if (! -e $file){ @@ -4424,7 +4496,7 @@ sub toucher { } # calling it trimmer to avoid conflicts with existing trim stuff -# arg: 1 - string to be right left trimmed. Also slices off \n so no chomp needed +# args: 0: 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; @@ -4434,14 +4506,14 @@ sub trimmer { return $str; } -# args: 1 - array, by ref, modifying by ref +# args: 0: array, by ref, modifying by ref # send array, assign to hash, changed array by reference, uniq values only. sub uniq { my %seen; @{$_[0]} = grep !$seen{$_}++, @{$_[0]}; } -# arg: 1 file full path to write to; 2 - array ref or scalar of data to write. +# args: 0: file full path to write to; 1: array ref or scalar of data to write. # note: turning off strict refs so we can pass it a scalar or an array reference. sub writer { my ($path, $content) = @_; @@ -4463,7 +4535,7 @@ sub writer { #### UPDATER #### ------------------------------------------------------------------- -# arg 1: type to return +# args: 0: type to return sub get_defaults { my ($type) = @_; my %defaults = ( @@ -4486,9 +4558,9 @@ sub get_defaults { } } -# args: 1 - download url, not including file name; 2 - string to print out -# 3 - update type option -# note that 1 must end in / to properly construct the url path +# args: 0: download url, not including file name; 1: string to print out +# 2: update type option +# note that 0 must end in / to properly construct the url path sub update_me { eval $start if $b_log; my ($self_download,$download_id) = @_; @@ -4687,6 +4759,7 @@ package OptionsHandler; # 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; $show{'short'} = 1; @@ -5467,6 +5540,7 @@ sub get { post_process(); eval $end if $b_log; } + sub post_process { # first run all the stuff that exits after running CheckRecommends::run() if $show{'recommends'}; @@ -5561,7 +5635,7 @@ sub post_process { $show{'network'} || $show{'raid'}){ $use{'pci'} = 1; } - if ($show{'usb'} || $show{'audio'} || $show{'bluetooth'} || + if ($show{'usb'} || $show{'audio'} || $show{'bluetooth'} || $show{'disk'} || $show{'graphic'} || $show{'network'}){ $use{'usb'} = 1; } @@ -5591,6 +5665,8 @@ sub post_process { if ($use{'pci'}){ $use{'bsd-pci'} = 1;} if ($show{'raid'}){ + $use{'bsd-raid'} = 1;} + if ($show{'ram'}){ $use{'bsd-ram'} = 1;} if ($show{'sensor'}){ $use{'bsd-sensor'} = 1;} @@ -5598,6 +5674,7 @@ sub post_process { $use{'sysctl'} = 1; } } + sub process_updater { my ($opt,$arg) = @_; $use{'downloader'} = 1; @@ -5700,8 +5777,8 @@ sub show_options { ['1', '-i', '--ip', "WAN IP address and local interfaces (requires ifconfig or ip network tool). Triggers -n. Not shown with -F for user security reasons. You shouldn't paste your local/WAN IP."], - ['1', '-I', '--info', "General info, including processes, uptime, memory, - IRC client or shell type, $self_name version."], + ['1', '-I', '--info', "General info, including processes, uptime, memory (if + -m/-tm not used), IRC client or shell type, $self_name version."], ['1', '-j', '--swap', "Swap in use. Includes ${partition_string}s, zram, file."], ['1', '-J', '--usb', "Show USB data: Hubs and Devices."], @@ -5710,13 +5787,13 @@ sub show_options { LUKS, Crypto, bcache, etc. Shows components/devices, sizes, etc."], ['1', '-m', '--memory', "Memory (RAM) data. Requires root. Numbers of devices (slots) supported and individual memory devices (sticks of memory etc). - For devices, shows device locator, type (e.g. DDR3), size, speed. If neither - -I nor -tm are selected, also shows RAM used/total."], + For devices, shows device locator, type (e.g. DDR3), size, speed. Also shows + System RAM available/used, and removes Memory report from -I or -tm."], ['1', '', '--memory-modules,--mm', "Memory (RAM) data. Exclude empty module slots."], ['1', '', '--memory-short,--ms', "Memory (RAM) data. Show only short Memory RAM report, number of arrays, slots, modules, and RAM type."], ['1', '-M', '--machine', "Machine data. Device type (desktop, server, laptop, - VM etc.), motherboard, BIOS and, if present, system builder (e.g. Lenovo). + VM etc.), motherboard, BIOS and, if present, system builder (e.g. Lenovo). Shows UEFI/BIOS/UEFI [Legacy]. Older systems/kernels without the required /sys data can use dmidecode instead, run as root. Dmidecode can be forced with --dmidecode"], @@ -5735,8 +5812,9 @@ sub show_options { ${partition_string}s show if --swap is not used. Use -p to see all mounted ${partition_string}s."], ['1', '-r', '--repos', "Distro repository data. Supported repo types: APK, - APT, CARDS, EOPKG, NIX, PACMAN, PACMAN-G2, PISI, PKG (BSDs), PORTAGE, PORTS - (BSDs), SCRATCHPKG, SLACKPKG, TCE, URPMQ, XBPS, YUM/ZYPP."], + APT, CARDS, EOPKG, NETPKG, NIX, PACMAN, PACMAN-G2, PISI, PKG (BSDs), PORTAGE, + PORTS (BSDs), SBOPKG, SBOUI, SCRATCHPKG, SLACKPKG, SLAPT_GET, SLPKG, TCE, + URPMQ, XBPS, YUM/ZYPP."], ['1', '-R', '--raid', "RAID data. Shows RAID devices, states, levels, array sizes, and components. md-raid: If device is resyncing, also shows resync progress line."], @@ -5883,7 +5961,7 @@ sub show_options { number, if detected. Init/RC type and runlevel/target (if available). Total count of all packages discovered in system (if not -r)."], ['2', '-j', '', "Add mapped: name if partition mapped."], - ['2', '-J', '', "For Device: driver."], + ['2', '-J', '', "For Device: driver; Si speed (base 10, bits/s)."], ['2', '-L', '', "For VG > LV, and other Devices, dm:"], ['2', '-m,--memory-modules', '', "Max memory module size (if available)."], ['2', '-N', '', "Specific vendor/product information (if relevant); @@ -5912,25 +5990,27 @@ sub show_options { ['1', '-xx', '--extra 2', "Show extra, extra data (only works with verbose or line output, not short form):"], ['2', '-A', '', "Chip vendor:product ID for each audio device; PCIe speed, - lanes (if found); sound server/api helper daemons/plugins."], + lanes (if found); USB rev, speed, lanes (if found); sound server/api helper + daemons/plugins."], ['2', '-B', '', "Serial number."], - ['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number; LVM - volume group free space (if available); disk duid (some BSDs)."], + ['2', '-D', '', "Disk transfer speed; NVMe lanes; USB rev, speed, lanes (if + found); Disk serial number; LVM volume group free space (if available); disk + duid (some BSDs)."], ['2', '-E', '', "Chip vendor:product ID, LMP subversion; PCIe speed, lanes - (if found)."], + (if found); USB rev, speed, lanes (if found)."], ['2', '-G', '', "Chip vendor:product ID for each video device; Output ports, - used and empty; PCIe speed, lanes (if found); Xorg: OpenGL compatibility - version, if free drivers and available; Xorg compositor; - alternate Xorg drivers (if available. Alternate means driver is on automatic - driver check list of Xorg for the device vendor, but is not installed on - system); Xorg Screen data: ID, s-res, dpi; Monitors: ID, position (if > 1), - resolution, dpi, model, diagonal."], + used and empty; PCIe speed, lanes (if found); USB rev, speed, lanes (if + found); Xorg: OpenGL compatibility version, if free drivers and available; + Xorg compositor; alternate Xorg drivers (if available. Alternate means driver + is on automatic driver check list of Xorg for the device vendor, but is not + installed on system); Xorg Screen data: ID, s-res, dpi; Monitors: ID, + position (if > 1), resolution, dpi, model, diagonal."], ['2', '-I', '', "Other detected installed gcc versions (if present). System default target/runlevel. Adds parent program (or pty/tty) for shell info if not in IRC. Adds Init version number, RC (if found). Adds per package manager installed package counts (if not -r)."], ['2', '-j,-p,-P', '', "Swap priority."], - ['2', '-J', '', "Vendor:chip-ID."], + ['2', '-J', '', "Vendor:chip-ID; lanes (Linux only)."], ['2', '-L', '', "Show internal LVM volumes, like raid image/meta volumes; for LVM RAID, adds RAID report line (if not -R); show all components > devices, number of 'c' or 'p' indicate depth of device."], @@ -5938,7 +6018,8 @@ sub show_options { bank (if found); memory array voltage (legacy, rare); module voltage (if available)."], ['2', '-M', '', "Chassis info, BIOS ROM size (dmidecode only), if available."], - ['2', '-N', '', "Chip vendor:product ID; PCIe speed, lanes (if found)."], + ['2', '-N', '', "Chip vendor:product ID; PCIe speed, lanes (if found); USB + rev, speed, lanes (if found)."], ['2', '-r', '', "Packages, see -Ixx."], ['2', '-R', '', "md-raid: Superblock (if present), algorithm. If resync, shows progress bar. Hardware RAID Chip vendor:product ID."], @@ -5970,8 +6051,8 @@ sub show_options { ['2', '-I', '', "For 'Shell:' adds ([doas|su|sudo|login]) to shell name if present; adds default shell+version if different; for 'running in:' adds (SSH) if SSH session; adds wakeups: (from suspend) to Uptime."], - ['2', '-J', '', "If present: Devices: serial number, interface count; USB - speed; max power."], + ['2', '-J', '', "If present: Devices: serial number, interface count, max + power."], ['2', '-m,--memory-modules', '', "Width of memory bus, data and total (if present and greater than data); Detail for Type, if present; module current, min, max voltages (if present and different from each other); serial number."], @@ -5995,8 +6076,8 @@ sub show_options { verbose or line output, not short form); check man page for explanations!; also sets --extra=3:"], ['2', '-A', '', "If available: list of alternate kernel modules/drivers - for device(s); PCIe lanes-max: gen, speed, lanes (if relevant); list of - installed tools for servers."], + for device(s); PCIe lanes-max: gen, speed, lanes (if relevant); USB mode (if + found); list of installed tools for servers."], ['2', '-C', '', "If available: microarchitecture level (64 bit AMD/Intel only).CPU generation, process node, built years; CPU socket type, base/boost speeds (dmidecode+root/sudo/doas required); Full topology line, with cores, @@ -6004,23 +6085,27 @@ sub show_options { vulnerabilities (bugs); family, model-id, stepping - format: hex (decimal) if greater than 9; microcode format: hex."], ['2', '-d,-D', '', "If available: logical and physical block sizes; drive - family; maj:min, USB drive specifics; SMART report."], - ['2', '-E', '', "If available: in Report:, adds Info: line: acl-mtu, - sco-mtu, link-policy, link-mode, service-classes."], + family; maj:min; USB mode (if found); USB drive specifics; SMART report."], + ['2', '-E', '', "PCIe lanes-max: gen, speed, lanes (if relevant); USB mode + (if found); If available: in Report:, adds Info: line: acl-mtu, sco-mtu, + link-policy, link-mode, service-classes."], ['2', '-G', '', "GPU process node, built year (AMD/Intel/Nvidia only); non-free driver info (Nvidia only); PCIe lanes-max: gen, speed, lanes (if - relevant); list of alternate kernel modules/drivers for device(s) (if - available); Monitor built year, gamma, screen ratio (if available)."], + relevant); USB mode (if found); list of alternate kernel modules/drivers for + device(s) (if available); Monitor built year, gamma, screen ratio (if + available)."], ['2', '-I', '', "Adds to Packages total number of lib files found for each package manager and pm tools (if not -r); adds init service tool."], ['2', '-j,-p,-P', '', "For swap (if available): swappiness and vfs cache pressure, and if values are default or not."], + ['2', '-J', '', "Adds USB mode (Linux only); IEC speed (base 2, Bytes/s)."], ['2', '-L', '', "LV, Crypto, devices, components: add maj:min; show full device/components report (speed, mapped names)."], ['2', '-m', '', "Show full volts report, current, min, max, even if identical."], ['2', '-n,-N', '', "If available: list of alternate kernel modules/drivers - for device(s); PCIe lanes-max: gen, speed, lanes (if relevant)."], + for device(s); PCIe lanes-max: gen, speed, lanes (if relevant); USB mode (if + found)."], ['2', '-o', '', "If available: maj:min of device."], ['2', '-p,-P', '', "If available: raw size of ${partition_string}s, maj:min, percent available for user, block size of file system (root required)."], @@ -6244,6 +6329,7 @@ my $pppid = ''; # # print "$type\n"; # return bless $self, $class; # } + sub set { eval $start if $b_log; main::set_ps_aux() if !$loaded{'ps-aux'}; @@ -6313,6 +6399,7 @@ sub get_client_name { } eval $end if $b_log; } + sub get_client_version { eval $start if $b_log; @app = main::program_values($client{'name'}); @@ -6428,6 +6515,7 @@ sub get_client_version { } eval $end if $b_log; } + sub get_cmdline { eval $start if $b_log; my @cmdline; @@ -6453,6 +6541,7 @@ sub get_cmdline { eval $end if $b_log; return [@cmdline]; } + sub perl_python_client { eval $start if $b_log; return 1 if $client{'version'}; @@ -6504,9 +6593,10 @@ sub perl_python_client { } eval $end if $b_log; } -## try to infer the use of Konversation >= 1.2, which shows $PPID improperly -## no known method of finding Konvi >= 1.2 as parent process, so we look to see if it is running, -## and all other irc clients are not running. As of 2014-03-25 this isn't used in my cases + +# Try to infer the use of Konversation >= 1.2, which shows $PPID improperly +# no known method of finding Konvi >= 1.2 as parent process, so we look to see if it is running, +# and all other irc clients are not running. As of 2014-03-25 this isn't used in my cases sub check_modern_konvi { eval $start if $b_log; return 0 if !$client{'qdbus'}; @@ -6556,6 +6646,7 @@ sub check_modern_konvi { eval $end if $b_log; return $b_modern_konvi; } + sub set_konvi_data { eval $start if $b_log; # https://userbase.kde.org/Konversation/Scripts/Scripting_guide @@ -6678,7 +6769,7 @@ sub clean_regex { return $string; } -# $extra optional, if you want to add custom filter to defaults +# args: 0: string; 1: optional, if you want to add custom filter to defaults sub clean_unset { my ($string,$extra) = @_; my $cleaner = '^(\.)+$|Bad Index|default string|\[?empty\]?|\bnone\b|N\/A|^not |'; @@ -6701,7 +6792,7 @@ sub filter { return $string; } -# note, let the print logic handle N/A cases +# Note, let the print logic handle N/A cases sub filter_partition { my ($source,$string,$type) = @_; return $string if !$string || $string eq 'N/A'; @@ -6723,7 +6814,7 @@ sub filter_pci_long { return $string; } -# args: list of values, return the first one that is defined +# args: 0: list of values. Return the first one that is defined. sub get_defined { for (@_){ return $_ if defined $_; @@ -6731,8 +6822,8 @@ sub get_defined { return; # don't return undef explicitly, only implicitly! } -# args: $1 - vendor id; $2 - product id -# returns print ready vendor:chip id string, or na variants +# args: 0: vendor id; 1: product id. +# Returns print ready vendor:chip id string, or na variants sub get_chip_id { my ($vendor,$product)= @_; my $id = 'N/A'; @@ -6747,9 +6838,10 @@ sub get_chip_id { } return $id; } -# 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 + +# args: 0: size in KiB, return KiB, MiB, GiB, TiB, PiB, EiB; 1: 'string'; +# 2: default value if null. Assumes KiB input. +# Returns string with units or array or size unmodified if not numeric sub get_size { my ($size,$type,$empty) = @_; my (@data); @@ -6838,7 +6930,8 @@ sub message { 'disk-data' => 'No disk data found.', 'disk-data-bsd' => 'No disk data found.', 'disk-size-0' => 'Total N/A', - 'display-driver-na' => 'X driver n/a', + 'display-driver-na' => 'X driver n/a', # legacy, leave for now + 'display-driver-na-try-root' => 'X driver n/a, try sudo/root', 'display-server' => 'No display server data found. Headless machine?', 'dmesg-boot-permissions' => 'dmesg.boot permissions', 'dmesg-boot-missing' => 'dmesg.boot not found', @@ -6849,6 +6942,7 @@ sub message { 'edid-version' => "invalid EDID version: $id", 'egl-wayland' => 'No known Wayland EGL/GBM data sources.', 'egl-wayland-console' => 'No known Wayland EGL/GBM data sources.', + 'file-unreadable' => 'File not readable (permissions?)', 'gfx-api' => 'No display API data. No known data sources.', 'gfx-api-console' => 'No display API data available in console. Headless machine?', 'gfx-api-xvesa' => 'No Xvesa VBE/GOP data found.', @@ -6939,6 +7033,7 @@ sub message { 'unmounted-file' => 'No /proc/partitions file found.', 'unsupported' => '', 'usb-data' => 'No USB data found. Server?', + 'usb-mode-mismatch' => '', 'unknown-cpu-topology' => 'ERR-103', 'unknown-desktop-version' => 'ERR-101', 'unknown-dev' => 'ERR-102', @@ -6950,7 +7045,8 @@ sub message { return $message{$type}; } -# string of range types (2-5; 3 4; 3,4,2-12) to generate single regex string for +# args: 0: string of range types (2-5; 3 4; 3,4,2-12) to generate single regex +# string for sub regex_range { return if ! defined $_[0]; my @processed; @@ -6978,15 +7074,16 @@ sub remove_duplicates { return $string; } -# convert string passed to KB, based on GB/MB/TB id -# NOTE: K 1024 KB 1000 KiB 1024 +# args: 0: string to turn to KiB integer value. +# Convert string passed to KB, based on GB/MB/TB id +# NOTE: 1 [K 1000; kB: 1000; KB 1024; KiB 1024] bytes # The logic will turn false MB to M for this tool # Hopefully one day sizes will all be in KiB type units sub translate_size { my ($working) = @_; my ($size,$unit) = (0,''); # print ":$working:\n"; - return if ! defined $working; + return if !defined $working; my $math = ($working =~ /B$/) ? 1000: 1024; if ($working =~ /^([0-9\.]+)\s*([kKMGTPE])i?B?$/i){ $size = $1; @@ -7029,7 +7126,7 @@ sub check_output_path { return $b_good; } -# passing along hash ref +# Passing along hash ref sub output_handler { my ($data) = @_; # print Dumper \%data; @@ -7044,7 +7141,7 @@ sub output_handler { } } -# passing along hash ref +# Passing along hash ref # NOTE: file has already been set and directory verified sub generate_json { eval $start if $b_log; @@ -7214,9 +7311,8 @@ sub print_basic { } } -# this has to get a hash of hashes, at least for now. -# because perl does not retain insertion order, I use a prefix for each -# hash key to force sorts. +# This has to get a hash of hashes, at least for now. Because perl does not +# retain insertion order, I use a prefix for each hash key to force sorts. sub print_data { my ($data) = @_; my ($counter,$length,$split_count) = (0,0,0); @@ -7309,7 +7405,7 @@ sub print_data { if (!$b_single && $val2 || $val2 eq '0'){ $val2 .= " "; } - # see: Use of implicit split to @_ is deprecated. Only get this + # See: Use of implicit split to @_ is deprecated. Only get this # warning in Perl 5.08 oddly enough. ie, no: scalar (split(...)); my @values = split(/\s+/, $val2); $split_count = scalar @values; @@ -7320,7 +7416,7 @@ sub print_data { $length += length("$key$sep{'s2'} $val2"); $holder .= "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val2"; } - # handle case where the key/value pair is > max, and where there are + # Handle case where the key/value pair is > max, and where there are # a lot of terms, like cpu flags, raid types supported. Raid can have # the last row have a lot of devices, or many raid types. But we don't # want to wrap things like: 3.45 MiB (6.3%) @@ -7330,7 +7426,7 @@ sub print_data { # print "m-2 r1: $b_row1 iu: $indent_use\n"; $val3 = shift @values; $start2 = "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val3 "; - # case where not first item in line, but when key+first word added, + # Case where not first item in line, but when key+first word added, # is wider than max width. if ($holder && ($length + length("$key$sep{'s2'} $val3")) > $size{'max-cols'}){ @@ -7384,7 +7480,7 @@ sub print_data { $start = ''; } } - # we don't want to start a new line, continue until full length. + # We don't want to start a new line, continue until full length. if ($holder2 !~ /^\s*$/){ # print "p-2: r1: $b_row1 iu: $indent_use\n"; $holder2 = "$colors{'c2'}$holder2"; @@ -7432,28 +7528,31 @@ sub print_data { $start = ''; } } - # only for repos currently + # Only for repos currently elsif (ref($val1) eq 'ARRAY'){ # print "p-5: r1: $b_row1 iu: $indent_use\n"; - my $array=0; + my $num = 0; + my ($l1,$l2); $indent_use = $indent_2; foreach my $item (@$val1){ - $array++; + $num++; if ($size{'max-lines'}){ - my $l1 = length("$array$sep{'s2'} $item") + $indent_use; + $l1 = length("$num$sep{'s2'} $item") + $indent_use; + # Cut down the line string until it's short enough to fit in term if ($l1 > $size{'term-cols'}){ - my $l2 = length("$array$sep{'s2'} ") + $indent_use + 6; - # print "$l1 $size{'term-cols'} $l2 $array $indent_use\n"; + $l2 = length("$num$sep{'s2'} ") + $indent_use + 6; + # print "$l1 $size{'term-cols'} $l2 $num $indent_use\n"; $item = substr($item,0,$size{'term-cols'} - $l2) . '[...]'; } } - $line = "$colors{'c1'}$array$sep{'s2'} $colors{'c2'}$item$colors{'cn'}"; + $line = "$colors{'c1'}$num$sep{'s2'} $colors{'c2'}$item$colors{'cn'}"; $line = sprintf("%-${indent_use}s%s\n","","$line"); print_line($line); } + } } - # we want a space between data blocks for single + # We want a space between data blocks for single print_line("\n") if $b_single; } } @@ -7482,9 +7581,9 @@ sub print_line { # -y1 + -Y can result in start of output scrolling off screen if terminal # wrapped lines happen. if ((($size{'max-lines'} >= $size{'term-lines'}) && - $size{'max-lines'} == $size{'lines'}) || - ($size{'max-lines'} < $size{'term-lines'} && - $size{'max-lines'} + 1 == $size{'lines'})){ + $size{'max-lines'} == $size{'lines'}) || + ($size{'max-lines'} < $size{'term-lines'} && + $size{'max-lines'} + 1 == $size{'lines'})){ output_control(); } } @@ -7504,6 +7603,7 @@ sub print_line { ## AudioItem { package AudioItem; + sub get { eval $start if $b_log; my $rows = []; @@ -7535,6 +7635,7 @@ sub get { eval $end if $b_log; return $rows; } + sub device_output { eval $start if $b_log; return if !$devices{'audio'}; @@ -7587,6 +7688,7 @@ sub device_output { } eval $end if $b_log; } + # this handles fringe cases where there is no card on pcibus, # but there is a card present. I don't know the exact architecture # involved but I know this situation exists on at least one old machine. @@ -7623,6 +7725,7 @@ sub asound_output { # print Data::Dumper:Dumper $rows; eval $end if $b_log; } + sub usb_output { eval $start if $b_log; my $rows = $_[0]; @@ -7630,36 +7733,52 @@ sub usb_output { my ($j,$num) = (0,1); return if !$usb{'audio'}; foreach my $row (@{$usb{'audio'}}){ - # print Data::Dumper::Dumper $row; $num = 1; + $j = scalar @$rows; # make sure to reset, or second device trips last flag ($path_id,$product) = ('',''); $product = main::clean($row->[13]) if $row->[13]; - $path_id = $row->[2] if $row->[2]; $product ||= 'N/A'; $row->[15] ||= 'N/A'; push(@$rows, { main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', main::key($num++,0,2,'driver') => $row->[15], + main::key($num++,1,2,'type') => 'USB', }); if ($extra > 0){ + # print "$j \n"; + if ($extra > 1){ + $row->[8] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,3,'rev')} = $row->[8]; + if ($row->[17]){ + $rows->[$j]{main::key($num++,0,3,'speed')} = $row->[17]; + } + if ($row->[24]){ + $rows->[$j]{main::key($num++,0,3,'lanes')} = $row->[24]; + } + if ($b_admin && $row->[22]){ + $rows->[$j]{main::key($num++,0,3,'mode')} = $row->[22]; + } + } + $path_id = $row->[2] if $row->[2]; $rows->[$j]{main::key($num++,0,2,'bus-ID')} = "$path_id:$row->[1]"; + if ($extra > 1){ + $row->[7] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; + } + if ($extra > 2){ + if (defined $row->[5] && $row->[5] ne ''){ + $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; + } + if ($row->[16]){ + $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + } + } } - if ($extra > 1){ - $row->[7] ||= 'N/A'; - $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; - } - if ($extra > 2 && defined $row->[5] && $row->[5] ne ''){ - $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; - } - if ($extra > 2 && $row->[16]){ - $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); - } - $j = scalar @$rows; } eval $end if $b_log; } + sub sound_output { eval $start if $b_log; my $rows = $_[0]; @@ -7710,23 +7829,40 @@ sub sound_output { } eval $end if $b_log; } + # see docs/inxi-audio.txt for unused or alternate helpers/tools sub sound_data { eval $start if $b_log; - my ($helpers,$name,$program,$status,$test,$tools,$type,$version); + my ($config,$helpers,$name,$program,$status,$test,$tools,$type,$version); my $data = []; ## API Types ## - if (my $file = $system_files{'asound-version'}){ + # not yet, user lib: || main::globber('/usr/lib*{,/*}/libasound.so*') + # the config test is expensive but will only trigger on servers with no audio + # devices. Checks if kernel was compiled with SND_ items, even if no devices. + if (!$bsd_type && -r "/boot/config-$uname[2]"){ + $config = "/boot/config-$uname[2]"; + } + if ($system_files{'asound-version'} || + ($config && (grep {/^CONFIG_SND_/} @{main::reader($config,'','ref')}))){ $name = 'ALSA'; - $status = 'kernel-api'; $type = 'API'; - # avoid possible second line if compiled by user - my $content = main::reader($file,'',0); - # we want the string after driver version for old and new ALSA - # some alsa strings have the build date in (...) after Version - if ($content =~ /Driver Version (\S+)(\s|\.|$)/){ - $version = $1; - $version =~ s/\.$//; # trim off period + # always true until find better test for inactive API test + if ($system_files{'asound-version'}){ + # avoid possible second line if compiled by user + my $content = main::reader($system_files{'asound-version'},'',0); + # we want the string after driver version for old and new ALSA + # some alsa strings have the build date in (...) after Version + if ($content =~ /Driver Version (\S+)(\s|\.?$)/){ + $version = $1; + $version =~ s/\.$//; # trim off period + } + $status = 'kernel-api'; + } + else { + $status = 'inactive'; + $version = $uname[2]; + $version =~ s/^k//; # avoid double kk possible result + $version = 'k' . $version; } if ($extra > 1){ $test = [['osspd','daemon'],['aoss','oss-emulator'], @@ -7734,26 +7870,22 @@ sub sound_data { $helpers = sound_helpers($test); } if ($b_admin){ - $test = [qw(alsamixer alsamixergui amixer)]; + $test = [qw(alsactl alsamixer alsamixergui amixer)]; $tools = sound_tools($test); } - # 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')){ - # $status = 'running'; - # } push(@$data,[$type,$name,$version,$status,$helpers,$tools]); ($status,$version,$helpers,$tools) = ('','',undef,undef); } # sndstat file may be removed in linux oss, but ossinfo part of oss4-base # alsa oss compat driver will create /dev/sndstat in linux however + # Note: kernel compile: SOUND_OSS if ((-e '/dev/sndstat' && !$system_files{'asound-version'}) || main::check_program('ossinfo')){ $name = 'OSS'; # not a great test, but ok for now, check on current Linux, seems unlikely # to find OSS on OpenBSD in general. if ($bsd_type){ - $status = (-e '/dev/sndstat') ? 'kernel-api' : 'kernel-api (inactive)'; + $status = (-e '/dev/sndstat') ? 'kernel-api' : 'inactive'; } else { $status = (-e '/dev/sndstat') ? 'active' : 'off?'; @@ -7775,7 +7907,7 @@ sub sound_data { } if ($b_admin){ # *mixer are FreeBSD tools - $test = [qw(dsbmixer mixer ossinfo ossmix ossxmix vmixctl)]; + $test = [qw(dsbmixer mixer ossctl ossinfo ossmix ossxmix vmixctl)]; $tools = sound_tools($test); } push(@$data,[$type,$name,$version,$status,$helpers,$tools]); @@ -7798,17 +7930,51 @@ sub sound_data { ($status,$version,$helpers,$tools) = ('','',undef,undef); } ## Servers ## + if ($program = main::check_program('artsd')){ + $name = 'aRts'; + $status = (grep {/artsd/} @ps_cmd) ? 'active': 'off'; + $type = 'Server'; + $version = main::program_version($program,'^artsd',2,'-v',1); + if ($extra > 1){ + $test = [['artswrapper','daemon'],]; + $helpers = sound_helpers($test); + } + if ($b_admin){ + $test = [qw(artsbuilder artsdsp)]; + $tools = sound_tools($test); + } + push(@$data,[$type,$name,$version,$status,$helpers,$tools]); + ($status,$version,$helpers,$tools) = ('','',undef,undef); + } + # pulseaudio-esound-compat has esd pointing to esdcompat + if (($program = main::check_program('esd')) && + !main::check_program('esdcompat')){ + $name = 'EsounD'; + $status = (grep {/\besd\b/} @ps_cmd) ? 'active': 'off'; + $type = 'Server'; + $version = main::program_version($program,'^Esound',3,'--version',1,1); + # if ($extra > 1){ + # $test = [['','daemon'],]; + # $helpers = sound_helpers($test); + # } + if ($b_admin){ + $test = [qw(esdcat esdctl esddsp)]; + $tools = sound_tools($test); + } + push(@$data,[$type,$name,$version,$status,$helpers,$tools]); + ($status,$version,$helpers,$tools) = ('','',undef,undef); + } if ($program = main::check_program('jackd')){ $name = 'JACK'; $status = jack_status(); $type = 'Server'; $version = main::program_version($program,'^jackd',3,'--version',1); if ($extra > 1){ - $test = [['a2jmidid','daemon']]; + $test = [['a2jmidid','daemon'],['nsmd','daemon']]; $helpers = sound_helpers($test); } if ($b_admin){ - $test = [qw(cadence jack_control jack_mixer qjackctl)]; + $test = [qw(agordejo cadence jack_control jack_mixer qjackctl)]; $tools = sound_tools($test); } push(@$data,[$type,$name,$version,$status,$helpers,$tools]); @@ -7819,6 +7985,10 @@ sub sound_data { $status = (grep {/(^|\/)nasd/} @ps_cmd) ? 'active': 'off'; $type = 'Server'; $version = main::program_version($program,'^Network Audio',5,'-V',1); + if ($extra > 1){ + $test = [['audiooss','oss-compat'],]; + $helpers = sound_helpers($test); + } if ($b_admin){ $test = [qw(auctl auinfo)]; $tools = sound_tools($test); @@ -7851,7 +8021,7 @@ sub sound_data { push(@$data,[$type,$name,$version,$status,$helpers,$tools]); ($status,$version,$helpers,$tools) = ('','',undef,undef); } - # note: pactl info/list/stat could be used + # note: pactl info/list/stat could be used if ($program = main::check_program('pulseaudio')){ $name = 'PulseAudio'; $status = pulse_status($program); @@ -7859,11 +8029,13 @@ sub sound_data { $version = main::program_version($program,'^pulseaudio',2,'--version',1); if ($extra > 1){ $test = [['pulseaudio-dlna','daemon'], + ['pulseaudio-alsa','plugin','/etc/alsa/conf.d/*-pulseaudio-default.conf'], + ['esdcompat','plugin'], ['pulseaudio-jack','module','/usr/lib/pulse*/modules/module-jack-sink.so']]; $helpers = sound_helpers($test); } if ($b_admin){ - $test = [qw(pacat pactl pamix pamixer pavucontrol pulsemixer)]; + $test = [qw(pacat pactl paman pamix pamixer pavucontrol pulsemixer)]; $tools = sound_tools($test); } push(@$data,[$type,$name,$version,$status,$helpers,$tools]); @@ -7890,6 +8062,7 @@ sub sound_data { eval $end if $b_log; return $data; } + # assume if jackd running we have active jack, update if required sub jack_status { eval $start if $b_log; @@ -7913,6 +8086,7 @@ sub jack_status { eval $end if $b_log; return $status; } + # pipewire is complicated, it can be there and running without being active server # This is NOT verified as valid true/yes case!! sub pipewire_status { @@ -7940,6 +8114,7 @@ sub pipewire_status { eval $end if $b_log; return $status; } + # pulse might be running through pipewire sub pulse_status { eval $start if $b_log; @@ -7969,6 +8144,7 @@ sub pulse_status { eval $end if $b_log; return $status; } + sub sound_helpers { eval $start if $b_log; my $test = $_[0]; @@ -7994,6 +8170,7 @@ sub sound_helpers { # print Data::Dumper::Dumper $helpers; return $helpers; } + sub sound_tools { eval $start if $b_log; my $test = $_[0]; @@ -8012,8 +8189,8 @@ sub sound_tools { ## BatteryItem { package BatteryItem; - my (@upower_items,$b_upower,$upower); + sub get { eval $start if $b_log; my ($key1,$val1); @@ -8078,27 +8255,28 @@ sub get { eval $end if $b_log; return $rows; } + # alarm capacity capacity_level charge_full charge_full_design charge_now -# cycle_count energy_full energy_full_design energy_now location manufacturer model_name -# power_now present serial_number status technology type voltage_min_design voltage_now -# 0 name - battery id, not used -# 1 status -# 2 present -# 3 technology -# 4 cycle_count -# 5 voltage_min_design -# 6 voltage_now -# 7 power_now -# 8 energy_full_design -# 9 energy_full -# 10 energy_now -# 11 capacity -# 12 capacity_level -# 13 of_orig -# 14 model_name -# 15 manufacturer -# 16 serial_number -# 17 location +# cycle_count energy_full energy_full_design energy_now location manufacturer model_name +# power_now present serial_number status technology type voltage_min_design voltage_now +# 0: name - battery id, not used +# 1: status +# 2: present +# 3: technology +# 4: cycle_count +# 5: voltage_min_design +# 6: voltage_now +# 7: power_now +# 8: energy_full_design +# 9: energy_full +# 10: energy_now +# 11: capacity +# 12: capacity_level +# 13: of_orig +# 14: model_name +# 15: manufacturer +# 16: serial_number +# 17: location sub battery_output { eval $start if $b_log; my ($rows,$battery) = @_; @@ -8377,6 +8555,7 @@ sub battery_data_sys { main::log_data('dump','sys: %$battery',$battery) if $b_log; eval $end if $b_log; } + sub battery_data_sysctl { eval $start if $b_log; my $battery = $_[0]; @@ -8464,6 +8643,7 @@ sub battery_data_sysctl { main::log_data('dump','dmi: %$battery',$battery) if $b_log; eval $end if $b_log; } + # note, dmidecode does not have charge_now or charge_full sub battery_data_dmi { eval $start if $b_log; @@ -8516,6 +8696,7 @@ sub battery_data_dmi { main::log_data('dump','dmi: %$battery',$battery) if $b_log; eval $end if $b_log; } + sub upower_data { my ($id) = @_; eval $start if $b_log; @@ -8550,10 +8731,10 @@ sub upower_data { ## BluetoothItem { package BluetoothItem; - my ($b_bluetooth,$b_hci_error,$b_hci,$b_rfk,$b_service); my ($service); my (%hci); + sub get { eval $start if $b_log; my $rows = []; @@ -8647,6 +8828,7 @@ sub device_output { } eval $end if $b_log; } + sub usb_output { eval $start if $b_log; return if !$usb{'bluetooth'}; @@ -8665,30 +8847,46 @@ sub usb_output { $path_id = $row->[2] if $row->[2]; push(@$rows, { main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', main::key($num++,1,2,'driver') => $row->[15], },); if ($extra > 0 && $row->[15] && !$bsd_type){ my $version = main::get_module_version($row->[15]); $rows->[$j]{main::key($num++,0,3,'v')} = $version if $version; } + $rows->[$j]{main::key($num++,1,2,'type')} = 'USB'; if ($extra > 0){ + if ($extra > 1){ + $row->[8] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,3,'rev')} = $row->[8]; + if ($row->[17]){ + $rows->[$j]{main::key($num++,0,3,'speed')} = $row->[17]; + } + if ($row->[24]){ + $rows->[$j]{main::key($num++,0,3,'lanes')} = $row->[24]; + } + if ($b_admin && $row->[22]){ + $rows->[$j]{main::key($num++,0,3,'mode')} = $row->[22]; + } + } $rows->[$j]{main::key($num++,0,2,'bus-ID')} = "$path_id:$row->[1]"; - } - if ($extra > 1){ - $row->[7] ||= 'N/A'; - $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; - } - if ($extra > 2 && defined $row->[5] && $row->[5] ne ''){ - $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; - } - if ($extra > 2 && $row->[16]){ - $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + if ($extra > 1){ + $row->[7] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; + } + if ($extra > 2){ + if (defined $row->[5] && $row->[5] ne ''){ + $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; + } + if ($row->[16]){ + $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + } + } } advanced_output($rows,'usb',$path_id) if $path_id; } eval $end if $b_log; } + sub advanced_output { eval $start if $b_log; my ($rows,$type,$bus_id) = @_; @@ -8893,6 +9091,7 @@ sub bt_tool_data { main::log_data('dump','%hci', \%hci) if $b_log; eval $end if $b_log; } + sub hciconfig_data { eval $start if $b_log; $b_hci = 1; @@ -8946,6 +9145,7 @@ 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; @@ -8982,6 +9182,7 @@ sub rfkill_data { 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){ @@ -8991,6 +9192,7 @@ sub check_service { } eval $end if $b_log; } + sub bluetooth_version { eval $start if $b_log; my ($lmp) = @_; @@ -9007,6 +9209,7 @@ sub bluetooth_version { { package CpuItem; my ($type); + sub get { eval $start if $b_log; ($type) = @_; @@ -9319,6 +9522,7 @@ sub full_output { } eval $end if $b_log; } + # $num, $rows passed by reference sub full_output_caches { eval $start if $b_log; @@ -9362,6 +9566,7 @@ sub full_output_caches { } eval $end if $b_log; } + sub short_output { eval $start if $b_log; my ($rows,$cpu) = @_; @@ -9421,6 +9626,7 @@ sub short_data { eval $end if $b_log; return $data; } + sub prep_short_data { eval $start if $b_log; my ($cpu_data) = @_; @@ -9700,6 +9906,7 @@ sub cpuinfo_data { eval $end if $b_log; return $cpu; } + sub cpuinfo_data_grabber { eval $start if $b_log; my ($file,$cpu_type) = @_; # type by ref @@ -9800,6 +10007,7 @@ sub cpuinfo_data_grabber { } eval $end if $b_log; } + sub cpu_sys_data { eval $start if $b_log; my $sys_freq = $_[0]; @@ -9970,6 +10178,7 @@ sub cpu_sys_data { eval $end if $b_log; return $cpu_sys; } + sub sys_data_grabber { eval $start if $b_log; my (@files); @@ -10117,6 +10326,7 @@ sub sys_data_grabber { eval $end if $b_log; return $working; } + sub sysctl_data { eval $start if $b_log; my ($cpu,@line,%speeds,@working); @@ -10410,6 +10620,7 @@ sub dboot_data { eval $end if $b_log; return $values; } + sub dmidecode_data { eval $start if $b_log; my $dmi_data = {'L1' => 0, 'L2' => 0,'L3' => 0, 'phys-cnt' => 0, @@ -10750,6 +10961,7 @@ sub cp_data_dmi { $dmi_data->{'volts'} = $cpu_dmi->{'volts'} if $cpu_dmi->{'volts'}; eval $end if $b_log; } + sub cp_data_fallback { eval $start if $b_log; my ($cpu,$caches,$cache_check,$counts,$tests) = @_; @@ -10914,6 +11126,7 @@ sub cp_data_fallback { } eval $end if $b_log; } + # all values passed by reference so no need for returns sub cp_data_sys { eval $start if $b_log; @@ -11023,6 +11236,7 @@ sub cp_data_sys { # print Data::Dumper::Dumper $counts; eval $end if $b_log; } + sub cp_sys_caches { eval $start if $b_log; my ($sys_caches,$caches,$id,$id_di) = @_; @@ -11053,7 +11267,8 @@ sub cp_cache_desc { undef $cache_desc; return $desc; } -# $caches passed by reference + +# args: 0: $caches passed by reference sub cp_cache_processor { my ($cache,$count) = @_; my $output; @@ -11067,6 +11282,7 @@ sub cp_cache_processor { # print "$cache :: $count :: $output\n"; return $output; } + sub cp_caches_fallback { eval $start if $b_log; my ($counts,$cpu,$caches,$cache_check) = @_; @@ -11123,6 +11339,7 @@ sub cp_caches_fallback { } eval $end if $b_log; } + ## START CPU ARCH ## sub cp_cpu_arch { eval $start if $b_log; @@ -12023,6 +12240,7 @@ sub cp_cpu_level { eval $end if $b_log; return $level; } + sub cp_cpu_topology { my ($counts,$topology) = @_; my @alpha = qw(Single Dual Triple Quad); @@ -12110,6 +12328,7 @@ sub cp_cpu_topology { } $topology->{'string'} ||= ''; } + sub cp_cpu_alpha { my $cores = $_[0]; my $string = ''; @@ -12125,6 +12344,7 @@ sub cp_cpu_alpha { } return $string; } + # Logic: # 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) @@ -12193,8 +12413,10 @@ sub cp_cpu_type { eval $end if $b_log; return $cpu_type; } -# needed because no physical_id in cpuinfo, but > 1 cpu systems exist -# returns: 0 - per cpu cores; 1 - phys cpu count; 2 - override model defaul names + +# Legacy: this data should be comfing from the /sys tool now. +# Was needed because no physical_id in cpuinfo, but > 1 cpu systems exist +# returns: 0: per cpu cores; 1: phys cpu count; 2: override model defaul names sub cp_elbrus_data { eval $start if $b_log; my ($family_id,$model_id,$count,$arch) = @_; @@ -12225,6 +12447,7 @@ sub cp_elbrus_data { eval $end if $b_log; return $return; } + sub cp_speed_data { eval $start if $b_log; my ($cpu,$cpu_sys) = @_; @@ -12315,6 +12538,7 @@ sub cp_speed_data { eval $end if $b_log; return $info; } + sub cp_speed_min_max { my ($min,$max,$type) = @_; my ($min_max,$key); @@ -12333,7 +12557,8 @@ sub cp_speed_min_max { $key = $type . '-' . $key if $type && $key; return ($min_max,$key); } -# update $tests by reference + +# args: 0: cpu, by ref; 1: update $tests by reference sub cp_test_types { my ($cpu,$tests) = @_; if ($cpu->{'type'} eq 'intel'){ @@ -12381,6 +12606,7 @@ sub cpu_vendor { eval $end if $b_log; return $vendor; } + # do not define model-id, stepping, or revision, those can be 0 valid value sub set_cpu_data { ${$_[0]} = { @@ -12405,6 +12631,7 @@ sub set_cpu_data { 'type' => '', }; } + sub system_cpu_name { eval $start if $b_log; my ($compat,@working); @@ -12446,6 +12673,7 @@ sub clean_speed { $speed = sprintf("%.0f", $speed); return $speed; } + sub clean_cpu { my ($cpu) = @_; return if !$cpu; @@ -12457,6 +12685,7 @@ sub clean_cpu { $cpu =~ s/^\s+|\s+$//g; return $cpu; } + sub hex_and_decimal { my ($data) = @_; $data = '' if !defined $data; @@ -12482,6 +12711,7 @@ my ($hddtemp,$nvme) = ('',''); my (@by_id,@by_path); my ($debugger_dir); # main::writer("$debugger_dir/system-repo-data-urpmq.txt",\@data2) if $debugger_dir; + sub get { eval $start if $b_log; my ($type) = @_; @@ -12535,6 +12765,7 @@ sub get { eval $end if $b_log; return $rows; } + sub storage_output { eval $start if $b_log; my ($rows,$disks) = @_; @@ -12570,11 +12801,12 @@ sub storage_output { shift @$disks; eval $end if $b_log; } + sub drive_output { eval $start if $b_log; my ($rows,$disks) = @_; # print Data::Dumper::Dumper $disks; - my ($b_smart_permissions,$smart_age,$smart_basic,$smart_fail); + my ($b_smart_permissions,$block,$smart_age,$smart_basic,$smart_fail); my ($num,$j) = (0,0); my ($id,$model,$size) = ('','',''); # note: specific smartctl non-missing errors handled inside loop @@ -12605,9 +12837,7 @@ sub drive_output { if ($b_admin && $row->{'maj-min'}){ $rows->[$j]{main::key($num++,0,2,'maj-min')} = $row->{'maj-min'}; } - if ($row->{'type'}){ - $rows->[$j]{main::key($num++,0,2,'type')} = $row->{'type'}; - } + if ($row->{'vendor'}){ $rows->[$j]{main::key($num++,0,2,'vendor')} = $row->{'vendor'}; } @@ -12624,8 +12854,31 @@ sub drive_output { $rows->[$j]{main::key($num++,0,2,'size')} = $size; if ($b_admin && $row->{'block-physical'}){ $rows->[$j]{main::key($num++,1,2,'block-size')} = ''; - $rows->[$j]{main::key($num++,0,3,'physical')} = $row->{'block-physical'} . ' B'; - $rows->[$j]{main::key($num++,0,3,'logical')} = ($row->{'block-logical'}) ? $row->{'block-logical'} . ' B' : 'N/A'; + $rows->[$j]{main::key($num++,0,3,'physical')} = "$row->{'block-physical'} B"; + $block = ($row->{'block-logical'}) ? "$row->{'block-logical'} B" : 'N/A'; + $rows->[$j]{main::key($num++,0,3,'logical')} = $block; + } + if ($row->{'type'}){ + $rows->[$j]{main::key($num++,1,2,'type')} = $row->{'type'}; + if ($extra > 1 && $row->{'type'} eq 'USB' && $row->{'abs-path'} && + $usb{'disk'}){ + foreach my $device (@{$usb{'disk'}}){ + if ($device->[8] && $device->[26] && + $row->{'abs-path'} =~ /^$device->[26]/){ + $rows->[$j]{main::key($num++,0,3,'rev')} = $device->[8]; + if ($device->[17]){ + $rows->[$j]{main::key($num++,0,3,'spd')} = $device->[17]; + } + if ($device->[24]){ + $rows->[$j]{main::key($num++,0,3,'lanes')} = $device->[24]; + } + if ($b_admin && $device->[22]){ + $rows->[$j]{main::key($num++,0,3,'mode')} = $device->[22]; + } + last; + } + } + } } if ($extra > 1 && $row->{'speed'}){ if ($row->{'sata'}){ @@ -12635,8 +12888,8 @@ sub drive_output { $rows->[$j]{main::key($num++,0,2,'lanes')} = $row->{'lanes'} if $row->{'lanes'}; } if ($extra > 2){ - $row->{'drive-type'} ||= 'N/A'; - $rows->[$j]{main::key($num++,0,2,'type')} = $row->{'drive-type'}; + $row->{'tech'} ||= 'N/A'; + $rows->[$j]{main::key($num++,1,2,'tech')} = $row->{'tech'}; if ($row->{'rotation'}){ $rows->[$j]{main::key($num++,0,2,'rpm')} = $row->{'rotation'}; } @@ -12654,10 +12907,10 @@ sub drive_output { $rows->[$j]{main::key($num++,0,2,'drive serial')} = main::filter($row->{'drive-serial'}); } if ($row->{'firmware'}){ - $rows->[$j]{main::key($num++,0,2,'rev')} = $row->{'firmware'}; + $rows->[$j]{main::key($num++,0,2,'fw-rev')} = $row->{'firmware'}; } if ($row->{'drive-firmware'}){ - $rows->[$j]{main::key($num++,0,2,'drive rev')} = $row->{'drive-firmware'}; + $rows->[$j]{main::key($num++,0,2,'drive-rev')} = $row->{'drive-firmware'}; } } if ($extra > 0 && $row->{'temp'}){ @@ -12671,11 +12924,10 @@ sub drive_output { $rows->[$j]{main::key($num++,0,2,'duid')} = main::filter($row->{'duid'}); } } - # extra level tests already done + # 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 ## @@ -12688,7 +12940,8 @@ sub drive_output { } eval $end if $b_log; } -# $num and $rows passed by reference + +# args: $num and $rows passed by reference sub smart_output { eval $start if $b_log; my ($type,$smart_data,$row,$j,$num,$rows) = @_; @@ -12771,6 +13024,7 @@ sub drive_data { eval $end if $b_log; return $data; } + sub proc_data { eval $start if $b_log; my ($used) = @_; @@ -12896,6 +13150,9 @@ sub proc_data_advanced { $working_path = Cwd::abs_path("/sys/block/$drives->[$i]{'id'}"); $working_path =~ s/nvme[^\/]*$//; } + if ($working_path){ + $drives->[$i]{'abs-path'} = Cwd::abs_path($working_path); + } main::log_data('data',"working path: $working_path") if $b_log; if ($b_admin && -e "/sys/block/"){ ($drives->[$i]{'block-logical'},$drives->[$i]{'block-physical'}) = @{block_data($drives->[$i]{'id'})}; @@ -12948,7 +13205,9 @@ sub proc_data_advanced { } if ($working_path){ $path = "${working_path}removable"; - $drives->[$i]{'type'} = 'Removable' if -r $path && main::reader($path,'strip',0); # 0/1 value + if (-r $path && main::reader($path,'strip',0)){ + $drives->[$i]{'type'} = 'Removable' ; # 0/1 value + } } my $peripheral = peripheral_data($drives->[$i]{'id'}); # note: we only want to update type if we found a peripheral, otherwise preserve value @@ -12989,14 +13248,14 @@ sub proc_data_advanced { $drives->[$i]{'partition-table'} = uc($result->[1]) if $result->[1]; if ($result->[2]){ $drives->[$i]{'rotation'} = $result->[2]; - $drives->[$i]{'drive-type'} = 'HDD'; + $drives->[$i]{'tech'} = 'HDD'; } elsif (($block_type && $block_type ne 'sdx') || # note: this case could conceivabley be wrong for a spun down HDD (defined $result->[2] && $result->[2] eq '0') || ($drives->[$i]{'model'} && $drives->[$i]{'model'} =~ /(flash|mmc|msata|\bm[\.-]?2\b|nvme|ssd|solid\s?state)/i)){ - $drives->[$i]{'drive-type'} = 'SSD'; + $drives->[$i]{'tech'} = 'SSD'; } } } @@ -13005,6 +13264,7 @@ sub proc_data_advanced { 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; @@ -13278,10 +13538,10 @@ sub smartctl_data { if ($split[$r] !~ /^Solid/){ $data->[$i]{'rotation'} = $split[$r]; $data->[$i]{'rotation'} =~ s/\s*rpm$//i; - $data->[$i]{'drive-type'} = 'HDD'; + $data->[$i]{'tech'} = 'HDD'; } else { - $data->[$i]{'drive-type'} = 'SSD'; + $data->[$i]{'tech'} = 'SSD'; } } elsif ($split[$a] eq 'Serial Number'){ @@ -13437,7 +13697,7 @@ sub smartctl_data { } elsif ($split[$a] eq 'Media_Wearout_Indicator'){ # $data->[$i]{'smart-media-wearout'} = $split[$r]; - # seen case where they used hex numbers becaause values + # seen case where they used hex numbers because values # were in 47 billion range in hex. You can't hand perl an unquoted # hex number that is > 2^32 without tripping a perl warning if ($b_attributes && $split[$r] && !main::is_hex("$split[$r]") && $split[$r] > 0){ @@ -13613,6 +13873,7 @@ sub peripheral_data { eval $end if $b_log; return $type; } + sub disk_data_advanced { eval $start if $b_log; my ($set_cmd,$id) = @_; @@ -13675,6 +13936,7 @@ sub disk_data_advanced { eval $end if $b_log; return $advanced; } + sub scsi_data { eval $start if $b_log; my ($file) = @_; @@ -13704,6 +13966,7 @@ sub scsi_data { eval $end if $b_log; return $scsi; } + # @b_id has already been cleaned of partitions, wwn-, nvme-eui sub disk_data_by_id { eval $start if $b_log; @@ -13732,8 +13995,9 @@ sub disk_data_by_id { eval $end if $b_log; return $disk_data; } + ## START DISK VENDOR BLOCK ## -# 0 - match pattern; 1 - replace pattern; 2 - vendor print; 3 - serial pattern +# 0: match pattern; 1: replace pattern; 2: vendor print; 3: serial pattern sub set_disk_vendors { eval $start if $b_log; $vendors = [ @@ -14281,6 +14545,7 @@ sub set_disk_vendors { eval $end if $b_log; } ## END DISK VENDOR BLOCK ## + # receives space separated string that may or may not contain vendor data sub disk_vendor { eval $start if $b_log; @@ -14316,7 +14581,7 @@ sub disk_vendor { } # Normally hddtemp requires root, but you can set user rights in /etc/sudoers. -# args: $1 - /dev/ to be tested for +# args: 0: /dev/ to be tested for sub hdd_temp { eval $start if $b_log; my ($device) = @_; @@ -14363,6 +14628,7 @@ sub hdd_temp { eval $end if $b_log; return $hdd_temp; } + sub hdd_temp_sys { eval $start if $b_log; my ($device) = @_; @@ -14434,7 +14700,8 @@ sub hdd_temp_sys { eval $end if $b_log; return $hdd_temp; } -# args: 1: block id + +# args: 0: block id sub block_data { eval $start if $b_log; my ($id) = @_; @@ -14455,6 +14722,7 @@ sub block_data { eval $end if $b_log; return $blocks; } + sub drive_speed { eval $start if $b_log; my ($device) = @_; @@ -14524,6 +14792,7 @@ sub drive_speed { package GraphicItem; my ($b_primary,$b_wayland_data,%graphics,$monitor_ids,$monitor_map); my ($gpu_amd,$gpu_intel,$gpu_nv); + sub get { eval $start if $b_log; my $rows = []; @@ -14674,6 +14943,7 @@ sub device_output { } eval $end if $b_log; } + sub usb_output { eval $start if $b_log; my $rows = $_[0]; @@ -14692,7 +14962,7 @@ sub usb_output { $product ||= 'N/A'; # note: for real usb video out, no generic drivers? webcams may have one though if (!$driver){ - if ($row->[14] eq 'Audio-Video'){ + if ($row->[14] eq 'audio-video'){ $driver = 'N/A'; } else { @@ -14701,30 +14971,46 @@ sub usb_output { } push(@$rows, { main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', main::key($num++,0,2,'driver') => $driver, + main::key($num++,1,2,'type') => 'USB', },); if ($extra > 0){ + if ($extra > 1){ + $row->[8] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,3,'rev')} = $row->[8]; + if ($row->[17]){ + $rows->[$j]{main::key($num++,0,3,'speed')} = $row->[17]; + } + if ($row->[24]){ + $rows->[$j]{main::key($num++,0,3,'lanes')} = $row->[24]; + } + if ($b_admin && $row->[22]){ + $rows->[$j]{main::key($num++,0,3,'mode')} = $row->[22]; + } + } my $bus_id = "$path_id:$row->[1]"; - if ($extra > 1 && $monitor_ids){ + if ($monitor_ids){ port_output($bus_id,$j,$rows,\$num); } $rows->[$j]{main::key($num++,0,2,'bus-ID')} = $bus_id; - } - if ($extra > 1){ - $row->[7] ||= 'N/A'; - $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; - } - if ($extra > 2 && defined $row->[5] && $row->[5] ne ''){ - $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; - } - if ($extra > 2 && $row->[16]){ - $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + if ($extra > 1){ + $row->[7] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; + } + if ($extra > 2){ + if (defined $row->[5] && $row->[5] ne ''){ + $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; + } + if ($row->[16]){ + $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + } + } } } eval $end if $b_log; } -# $rows, $num by ref + +# args: $rows, $num by ref sub port_output { my ($bus_id,$j,$rows,$num) = @_; my (@connected,@disabled,@empty); @@ -14851,26 +15137,22 @@ sub display_output(){ } } # note: if no xorg log, and if wayland, there will be no xorg drivers, - # obviously, so we use the last driver found on the card section in that case. - # those come from lscpi kernel drivers so there should be no xorg/wayland issues. + # obviously, so we use the driver(s) found in the card section. + # Those come from lspci kernel drivers so should be no xorg/wayland issues. if (!@$x_drivers || !$x_drivers->[0]){ - # Fallback: specific case: in Arch/Manjaro gdm run systems, their Xorg.0.log is + # Fallback: specific case: in Arch/Manjaro gdm run systems, Xorg.0.log is # 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 (!$graphics{'protocol'} || $graphics{'protocol'} ne 'wayland'){ - if ($graphics{'gpu-drivers'}){ - if (-e '/var/lib/gdm' && !$b_root){ - $driver_note = main::message('display-driver-na'); - $driver_note .= ' - ' . main::message('root-suggested'); + # Problem: as root, wayland has no info anyway, including wayland detection. + if (-e '/var/lib/gdm' && !$b_root){ + if ($graphics{'gpu-drivers'}){ + $driver_note = main::message('display-driver-na-try-root'); } else { - $driver_note = main::message('display-driver-na'); + $driver_note = main::message('root-suggested'); } } - elsif (-e '/var/lib/gdm' && !$b_root) { - $driver_note = main::message('root-suggested'); - } } } # if xvesa, will always have display-driver set @@ -15020,6 +15302,7 @@ sub display_output(){ } eval $end if $b_log; } + sub monitors_output_basic { eval $start if $b_log; my ($type,$monitors,$s_dpi,$j,$row,$num) = @_; @@ -15056,7 +15339,8 @@ sub monitors_output_basic { } eval $end if $b_log; } -# $j, $row, $num passed by ref + +# args: $j, $row, $num passed by ref sub monitors_output_full { eval $start if $b_log; my ($type,$monitors,$j,$rows,$num) = @_; @@ -15265,6 +15549,7 @@ sub display_api_output { } eval $end if $b_log; } + sub egl_output { eval $start if $b_log; my ($rows,$num) = @_; @@ -15274,6 +15559,7 @@ sub egl_output { }); eval $end if $b_log; } + sub opengl_output { eval $start if $b_log; my ($program,$rows,$num) = @_; @@ -15382,6 +15668,7 @@ sub opengl_output { } eval $end if $b_log; } + sub xvesa_output { eval $start if $b_log; my ($rows,$num) = @_; @@ -15455,7 +15742,8 @@ sub display_data_wayland { main::log_data('dump','$monitor_ids',$monitor_ids) if $b_log; eval $end if $b_log; } -# if we didn't get explicit tool for wayland data, check to see if we got most + +# If we didn't get explicit tool for wayland data, check to see if we got most # of the data from /sys/class/drm edid and then skip xrandr to avoid gunking up # the data, in that case, all we get from xrandr would be the position, which is # nice but not a must-have. We've already cleared out all disabled ports. @@ -15478,6 +15766,7 @@ sub check_wayland_data { eval $end if $b_log; return $b_skip_pos; } + # Set Display rect size for > 1 monitors, monitor positions, size-i, diag sub wayland_data_advanced { eval $start if $b_log; @@ -15538,7 +15827,6 @@ sub wayland_data_advanced { } ## WAYLAND COMPOSITOR DATA TOOLS ## - # NOTE: These patterns are VERY fragile, and depend on no changes at all to # the data structure, and more important, the order. Something I would put # almost no money on being able to count on. @@ -15663,7 +15951,8 @@ sub wlinfo_data { print 'wayland/weston-info: monitor_ids: ', Data::Dumper::Dumper $monitor_ids if $dbg[46]; eval $end if $b_log; } -# note; since not all systems will have /sys data, we'll repack it if it's + +# Note; since not all systems will have /sys data, we'll repack it if it's # missing here. sub swaymsg_data { eval $start if $b_log; @@ -15787,7 +16076,8 @@ sub swaymsg_data { print 'swaymsg: ', Data::Dumper::Dumper $monitor_ids if $dbg[46]; eval $end if $b_log; } -# like a basic stripped down swaymsg -t get_outputs -p, less data though + +# Like a basic stripped down swaymsg -t get_outputs -p, less data though # This is EXTREMELY LIKELY TO FAIL! Any tiny syntax change will break this. sub wlrrandr_data { eval $start if $b_log; @@ -15851,7 +16141,8 @@ sub wlrrandr_data { print 'wlr-randr: ', Data::Dumper::Dumper $monitor_ids if $dbg[46]; eval $end if $b_log; } -# return model/serial for those horrible string type values we have to process + +# Return model/serial for those horrible string type values we have to process # in swaymsg -t get_outputs -p and wlr-randr default output sub get_model_serial { eval $start if $b_log; @@ -15906,6 +16197,7 @@ sub display_data_x { main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log; eval $end if $b_log; } + sub xdriinfo_data { eval $start if $b_log; my $program = $_[0]; @@ -15940,6 +16232,7 @@ sub xdriinfo_data { main::log_data('dump','%dri_drivers',\%dri_drivers) if $b_log; eval $end if $b_log; } + sub xdpyinfo_data { eval $start if $b_log; my ($program) = @_; @@ -16039,6 +16332,7 @@ sub xdpyinfo_data { main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log; eval $end if $b_log; } + sub xrandr_data { eval $end if $b_log; my ($program) = @_; @@ -16202,7 +16496,8 @@ sub xrandr_data { main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log; eval $end if $b_log; } -# handle some strange corner cases with more robust testing + +# Handle some strange corner cases with more robust testing sub check_screens { my ($id) = @_; my $b_use; @@ -16225,7 +16520,8 @@ sub check_screens { } return $b_use; } -# case where no xpdyinfo display server/version data exists, or to set Wayland + +# Case where no xpdyinfo display server/version data exists, or to set Wayland # Xwayland version, or Xvesa data. sub display_server_data { eval $start if $b_log; @@ -16290,6 +16586,7 @@ sub display_server_data { @paths = grep { !/^\/usr\/lib|xorg|libexec/ } @paths; eval $end if $b_log; } + sub display_protocol { eval $start if $b_log; $graphics{'protocol'} = ''; @@ -16365,9 +16662,11 @@ sub gpu_drivers_sys { eval $end if $b_log; return $drivers; } + sub display_drivers_x { eval $start if $b_log; my $driver_data = []; + # print 'x-log: ' . $system_files{'xorg-log'} . "\n"; 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"; @@ -16376,7 +16675,7 @@ sub display_drivers_x { # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/Xorg.0-gm10.log"; # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/xorg-multi-driver-1.log"; } - my $xorg = main::reader($log,'','ref'); + my $x_log = main::reader($log,'','ref'); # list is from sgfxi plus non-free drivers, plus ARM drivers. # Don't use ati. It's just a wrapper for: r128, mach64, radeon my $list = join('|', qw(amdgpu apm ark armsoc atimisc @@ -16399,19 +16698,19 @@ sub display_drivers_x { # $pattern = qr/$pattern/i; # qr/../i only added perl 5.14, fails on older perls # 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; - foreach my $line (@$xorg){ + # @$x_log = grep {/Failed|Unload|Loading/} @$x_log; + foreach my $line (@$x_log){ next if $line !~ /$pattern/i; - # print "$_\n"; - # note that in file names, driver is always lower case - if ($line =~ /\sLoading.*($list)_drv\.so$/i){ + # print "$line\n"; + # note that in file names, driver is always lower case. Legacy _drv.o + if ($line =~ /\sLoading.*($list)_drv\.s?o$/i){ $driver=lc($1); # we get all the actually loaded drivers first, we will use this to compare the # failed/unloaded, which have not always actually been truly loaded $drivers{$driver}='loaded'; } # openbsd uses UnloadModule: - elsif ($line =~ /(Unloading\s|UnloadModule).*\"?($list)(_drv\.so)?\"?$/i){ + elsif ($line =~ /(Unloading\s|UnloadModule).*\"?($list)(_drv\.s?o)?\"?$/i){ $driver=lc($2); # we get all the actually loaded drivers first, we will use this to compare the # failed/unloaded, which have not always actually been truly loaded @@ -16454,6 +16753,7 @@ sub display_drivers_x { } } } + # print 'drivers: ', Data::Dumper::Dumper \%drivers; foreach (sort keys %drivers){ if ($drivers{$_} eq 'loaded'){ push(@$loaded,$_); @@ -16476,6 +16776,7 @@ sub display_drivers_x { # print 'source: ', Data::Dumper::Dumper $driver_data; return $driver_data; } + ## GPU DATA ## sub set_amd_data { $gpu_amd = [ @@ -16708,6 +17009,7 @@ sub set_amd_data { }, ]; } + sub set_intel_data { $gpu_intel = [ {'arch' => 'Gen-1', @@ -16823,7 +17125,7 @@ sub set_intel_data { {'arch' => 'Gen-9', 'ids' => '0a84|1902|1906|190a|190b|190e|1912|1913|1915|1916|1917|191a|191b|' . '191d|191e|1921|1923|1926|1927|192a|192b|192d|1932|193a|193b|193d|1a84|1a85|' . - '3184|3185|5a84|5a85', + '5a84|5a85', 'code' => '', 'process' => 'Intel 14n', 'years' => '2015-16', @@ -16879,6 +17181,7 @@ sub set_intel_data { }, ]; } + sub set_nv_data { # this is vendor id: 12d2, nv1/riva/tnt type cards # 0008|0009|0010|0018|0019 @@ -17186,6 +17489,7 @@ sub set_nv_data { }, ], } + sub gpu_data { eval $start if $b_log; my ($v_id,$p_id,$name) = @_; @@ -17207,6 +17511,7 @@ sub gpu_data { eval $end if $b_log; return ($gpu_data,$b_nv); } + sub get_gpu_data { eval $start if $b_log; my ($gpu,$p_id,$name) = @_; @@ -17298,6 +17603,7 @@ sub set_monitors_sys { print 'monitor_sys_data(): ', Data::Dumper::Dumper $monitor_ids if $dbg[44]; eval $end if $b_log; } + sub monitor_edid_data { eval $start if $b_log; my ($file,$port) = @_; @@ -17380,6 +17686,7 @@ sub monitor_edid_data { } eval $end if $b_log; } + sub advanced_monitor_data { eval $start if $b_log; my ($monitors,$layouts) = @_; @@ -17474,7 +17781,8 @@ sub advanced_monitor_data { print Data::Dumper::Dumper $monitors if $dbg[45]; eval $end if $b_log; } -# clear out all disabled or not connected monitor ports + +# Clear out all disabled or not connected monitor ports sub set_active_monitors { eval $start if $b_log; foreach my $key (keys %$monitor_ids){ @@ -17486,6 +17794,7 @@ sub set_active_monitors { # print 'active monitors: ', Data::Dumper::Dumper $monitor_ids; eval $end if $b_log; } + sub get_monitor_position { eval $start if $b_log; my ($monitor,$horiz,$vert) = @_; @@ -17509,6 +17818,7 @@ sub get_monitor_position { eval $end if $b_log; return $position; } + sub set_monitor_layouts { my ($layouts) = @_; $layouts->[1][2] = {'1-1' => 'left','1-2' => 'right'}; @@ -17528,7 +17838,8 @@ sub set_monitor_layouts { '2-1' => 'middle-l','2-2' => 'middle-c','2-3' => 'middle-r', '3-1' => 'bottom-l','3-2' => 'bottom-c','3-3' => 'bottom-r'}; } -# this is required to resolve the situation where some xorg drivers change + +# This is required to resolve the situation where some xorg drivers change # the kernel ID for the port to something slightly different, amdgpu in particular. sub map_monitor_ids { eval $start if $b_log; @@ -17608,7 +17919,7 @@ sub map_monitor_ids { eval $end if $b_log; } -# handle case of monitor on left or right edge, vertical that is. +# Handle case of monitor on left or right edge, vertical that is. # mm dimensiions are based on the default position of monitor as sold. # very old systems may not have non 0 value for size x or y # size, res x,y by reference @@ -17621,6 +17932,7 @@ sub flip_size_x_y { } eval $end if $b_log; } + ## COMPOSITOR DATA ## sub set_compositor_data { eval $start if $b_log; @@ -17642,6 +17954,7 @@ sub set_compositor_data { } eval $end if $b_log; } + sub get_compositors { eval $start if $b_log; my $found = []; @@ -17669,7 +17982,7 @@ sub get_compositors { } ## UTILITIES ## -sub tty_data(){ +sub tty_data { eval $start if $b_log; my ($tty); if ($size{'term-cols'}){ @@ -17752,6 +18065,7 @@ sub get { eval $end if $b_log; return $rows; } + sub general_output { eval $start if $b_log; my ($rows,$general_data) = @_; @@ -17778,6 +18092,7 @@ sub general_output { } eval $end if $b_log; } + sub lvm_output { eval $start if $b_log; my ($rows,$lvm_data) = @_; @@ -17841,6 +18156,7 @@ sub components_output { $rows->[$$j]{main::key($$num++,1,$l1,'Components')} = $status; components_recursive_output($type,$j,$num,$rows,$components,0,'c','p'); } + sub components_recursive_output { my ($type,$j,$num,$rows,$components,$indent,$c,$p) = @_; my ($l,$m,$size) = (1,1,0); @@ -17881,7 +18197,7 @@ sub components_recursive_output { } } -# note: type dm is seen in only one dataset, but it's a start +# Note: type dm is seen in only one dataset, but it's a start sub general_data { eval $start if $b_log; my (@found,$parent,$parent_fs); @@ -17941,7 +18257,7 @@ sub general_data { return $general_data; } -# note: called for disk totals, raid, and logical +# Note: called for disk totals, raid, and logical sub lvm_data { eval $start if $b_log; $loaded{'logical-data'} = 1; @@ -17989,6 +18305,7 @@ sub lvm_data { print Data::Dumper::Dumper \@lvm if $dbg[22]; eval $end if $b_log; } + sub process_lvm_data { eval $start if $b_log; my $processed = {}; @@ -18026,10 +18343,12 @@ sub process_lvm_data { eval $end if $b_log; return $processed; } + sub component_data { my ($maj_min,$full_components) = @_; push(@$full_components, component_recursive_data($maj_min)); } + sub component_recursive_data { eval $start if $b_log; my ($maj_min) = @_; @@ -18136,13 +18455,14 @@ sub get { eval $end if $b_log; return $rows; } + ## keys for machine data are: -# 0-sys_vendor 1-product_name 2-product_version 3-product_serial 4-product_uuid -# 5-board_vendor 6-board_name 7-board_version 8-board_serial -# 9-bios_vendor 10-bios_version 11-bios_date +# 0: sys_vendor; 1: product_name; 2: product_version; 3: product_serial; +# 4: product_uuid; 5: board_vendor; 6: board_name; 7: board_version; +# 8: board_serial; 9: bios_vendor; 10: bios_version; 11: bios_date; ## with extra data: -# 12-chassis_vendor 13-chassis_type 14-chassis_version 15-chassis_serial -## unused: 16-bios_rev 17-bios_romsize 18 - firmware type +# 12: chassis_vendor; 13: chassis_type; 14: chassis_version; 15: chassis_serial; +## unused: 16: bios_rev; 17: bios_romsize; 18: firmware type sub machine_output { eval $start if $b_log; my ($rows,$data) = @_; @@ -18153,9 +18473,9 @@ sub machine_output { my ($bios_date,$bios_rev,$bios_romsize,$bios_vendor,$bios_version,$chassis_serial, $chassis_type,$chassis_vendor,$chassis_version,$mobo_model,$mobo_serial,$mobo_vendor, $mobo_version,$product_name,$product_serial,$product_version,$system_vendor); -# foreach my $key (keys %data){ -# print "$key: $data->{$key}\n"; -# } + # foreach my $key (keys %data){ + # print "$key: $data->{$key}\n"; + # } if (!$data->{'sys_vendor'} || ($data->{'board_vendor'} && $data->{'sys_vendor'} eq $data->{'board_vendor'} && !$data->{'product_name'} && !$data->{'product_version'} && @@ -18273,6 +18593,7 @@ sub machine_output { } eval $end if $b_log; } + sub machine_soc_output { my ($rows,$soc_machine) = @_; my ($key); @@ -18309,6 +18630,7 @@ sub machine_soc_output { } eval $end if $b_log; } + sub machine_data_fruid { eval $start if $b_log; my ($program) = @_; @@ -18352,6 +18674,7 @@ sub machine_data_fruid { main::log_data('dump','%data',$data) if $b_log; return $data; } + sub machine_data_sys { eval $start if $b_log; my ($path,$vm); @@ -18412,7 +18735,8 @@ sub machine_data_sys { eval $end if $b_log; return $data; } -# this will create an alternate machine data source + +# This will create an alternate machine data source # which will be used for alt ARM machine data in cases # where no dmi data present, or by cpu data to guess at # certain actions for arm only. @@ -18621,15 +18945,16 @@ sub machine_data_dmi { $data->{'device'} = get_device_vm($data->{'sys_vendor'},$data->{'product_name'}); $data->{'device'} ||= 'other-vm?'; } -# print "dmi:\n"; -# foreach (keys %data){ -# print "$_: $data->{$_}\n"; -# } + # print "dmi:\n"; + # foreach (keys %data){ + # print "$_: $data->{$_}\n"; + # } print Data::Dumper::Dumper $data if $dbg[28]; main::log_data('dump','%data',$data) if $b_log; eval $end if $b_log; return $data; } + # As far as I know, only OpenBSD supports this method. # it uses hw. info from sysctl -a and bios info from dmesg.boot sub machine_data_sysctl { @@ -18853,13 +19178,13 @@ sub get_device_vm { eval $end if $b_log; return $vm; } - } ## NetworkItem { package NetworkItem; my ($b_ip_run,@ifs_found); + sub get { eval $start if $b_log; my $rows = []; @@ -19011,6 +19336,7 @@ sub device_output { # @rows = (); eval $end if $b_log; } + sub usb_output { eval $start if $b_log; return if !$usb{'network'}; @@ -19029,22 +19355,37 @@ sub usb_output { $j = scalar @$rows; push(@$rows, { main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', main::key($num++,0,2,'driver') => $driver, + main::key($num++,1,2,'type') => 'USB', },); $b_wifi = check_wifi($product); if ($extra > 0){ + if ($extra > 1){ + $row->[8] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,3,'rev')} = $row->[8]; + if ($row->[17]){ + $rows->[$j]{main::key($num++,0,3,'speed')} = $row->[17]; + } + if ($row->[24]){ + $rows->[$j]{main::key($num++,0,3,'lanes')} = $row->[24]; + } + if ($b_admin && $row->[22]){ + $rows->[$j]{main::key($num++,0,3,'mode')} = $row->[22]; + } + } $rows->[$j]{main::key($num++,0,2,'bus-ID')} = "$path_id:$row->[1]"; - } - if ($extra > 1){ - $row->[7] ||= 'N/A'; - $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; - } - if ($extra > 2 && defined $row->[5] && $row->[5] ne ''){ - $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; - } - if ($extra > 2 && $row->[16]){ - $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + if ($extra > 1){ + $row->[7] ||= 'N/A'; + $rows->[$j]{main::key($num++,0,2,'chip-ID')} = $row->[7]; + } + if ($extra > 2){ + if (defined $row->[5] && $row->[5] ne ''){ + $rows->[$j]{main::key($num++,0,2,'class-ID')} = "$row->[4]$row->[5]"; + } + if ($row->[16]){ + $rows->[$j]{main::key($num++,0,2,'serial')} = main::filter($row->[16]); + } + } } if ($show{'network-advanced'}){ if (!$bsd_type){ @@ -19062,6 +19403,7 @@ sub usb_output { } eval $end if $b_log; } + sub advanced_data_sys { eval $start if $b_log; return if ! -d '/sys/class/net'; @@ -19182,7 +19524,6 @@ sub advanced_data_bsd { ($cont_if,$ind_if) = (1,2); } foreach my $item (@ifs_bsd){ - if (ref $item ne 'ARRAY'){ $working_if = $item; # print "$working_if\n"; @@ -19230,12 +19571,13 @@ sub advanced_data_bsd { } eval $end if $b_log; } -## values: -# 0 - ipv -# 1 - ip -# 2 - broadcast, if found -# 3 - scope, if found -# 4 - scope if, if different from if + +## Result values: +# 0: ipv +# 1: ip +# 2: broadcast, if found +# 3: scope, if found +# 4: scope IF, if different from IF sub if_ip { eval $start if $b_log; my ($rows,$type,$if) = @_; @@ -19314,7 +19656,8 @@ sub if_ip { } eval $end if $b_log; } -# get ip using downloader to stdout. This is a clean, text only IP output url, + +# Get ip using downloader to stdout. This is a clean, text only IP output url, # single line only, ending in the ip address. May have to modify this in the future # to handle ipv4 and ipv6 addresses but should not be necessary. # ip=$(echo 2001:0db8:85a3:0000:0000:8a2e:0370:7334 | gawk --re-interval ' @@ -19387,6 +19730,7 @@ sub wan_ip { }); eval $end if $b_log; } + sub check_bus_id { eval $start if $b_log; my ($path,$bus_id) = @_; @@ -19403,6 +19747,7 @@ sub check_bus_id { eval $end if $b_log; return $b_valid; } + sub check_wifi { my ($item) = @_; my $b_wifi = ($item =~ /wireless|wi-?fi|wlan|802\.11|centrino/i) ? 1 : 0; @@ -19413,6 +19758,7 @@ sub check_wifi { ## OpticalItem { package OpticalItem; + sub get { eval $start if $b_log; my $rows = $_[0]; @@ -19447,6 +19793,7 @@ sub get { eval $end if $b_log; return $rows; } + sub drive_output { eval $start if $b_log; my ($rows,$drives) = @_; @@ -19532,6 +19879,7 @@ sub drive_output { # print Data::Dumper::Dumper $drives; eval $end if $b_log; } + sub drive_data_bsd { eval $start if $b_log; my (@rows,@temp); @@ -19635,6 +19983,7 @@ sub drive_data_bsd { eval $end if $b_log; return $drives; } + sub drive_data_linux { eval $start if $b_log; my (@data,@info,@rows); @@ -19754,6 +20103,7 @@ sub get { eval $end if $b_log; return $rows; } + sub create_output { eval $start if $b_log; my $rows = $_[0]; @@ -20148,6 +20498,7 @@ sub set_partitions { print Data::Dumper::Dumper \@partitions if $dbg[16]; eval $end if $b_log; } + sub swap_data { eval $start if $b_log; $loaded{'set-swap'} = 1; @@ -20267,6 +20618,7 @@ sub swap_data { print Data::Dumper::Dumper \@swaps if $dbg[15];; eval $end if $b_log; } + sub swap_advanced_data { eval $start if $b_log; my ($swappiness,$cache_pressure) = (); @@ -20285,7 +20637,8 @@ sub swap_advanced_data { eval $end if $b_log; return ($swappiness,$cache_pressure); } -# handle cases of hidden file systems + +# Handle cases of hidden file systems sub check_partition_data { eval $start if $b_log; my ($b_found,$dev_mapped,$temp); @@ -20338,6 +20691,7 @@ sub check_partition_data { } eval $end if $b_log; } + # NOTE: Was forgetting to update one or the other so put them # all here for: subs partitiion_data(), check_partition_data() # note: p_d filters 'filesystem', and c_p_d filters against fs @@ -20352,7 +20706,8 @@ sub partition_filters { $filters .= 'sys|\/sys\/.*|sysfs|tmpfs|tracefs|type|udev|unionfs|vartmp'; return $filters } -# used to exclude disk used, partition/unmounted/swap label/uuid, unmounted label/uuid + +# Used to exclude disk used, partition/unmounted/swap label/uuid, unmounted label/uuid # see docs/inxi-data.txt PARTITION DATA for more on remote/fuse fs sub fs_excludes { my ($source) = @_; @@ -20370,6 +20725,7 @@ sub fs_excludes { $excludes .= ')(fs)?(\d{0,2})?'; return $excludes; } + sub get_mounts_fs { eval $start if $b_log; my ($item,$mount) = @_; @@ -20394,6 +20750,7 @@ 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; @@ -20410,7 +20767,7 @@ sub set_label_uuid { eval $end if $b_log; } -# args: 1: blockdev full path (part only); 2: block id; 3: size (part only) +# args: 0: blockdev full path (part only); 1: block id; 2: size (part only) sub admin_data { eval $start if $b_log; my ($blockdev,$id,$size) = @_; @@ -20437,6 +20794,7 @@ sub admin_data { eval $end if $b_log; return @sizes; } + sub get_maj_min { eval $start if $b_log; my ($id) = @_; @@ -20450,6 +20808,7 @@ sub get_maj_min { eval $end if $b_log; return $maj_min; } + sub get_label { eval $start if $b_log; my ($item) = @_; @@ -20467,6 +20826,7 @@ sub get_label { eval $end if $b_log; return $label; } + sub get_root { eval $start if $b_log; my ($path) = ('/dev/root'); @@ -20513,6 +20873,7 @@ sub get_uuid { ## ProcessItem { package ProcessItem; + sub get { eval $start if $b_log; my $num = 0; @@ -20534,6 +20895,7 @@ sub get { eval $end if $b_log; return $rows; } + sub cpu_processes { eval $start if $b_log; my $rows = $_[0]; @@ -20588,6 +20950,7 @@ sub cpu_processes { } eval $end if $b_log; } + sub mem_processes { eval $start if $b_log; my $rows = $_[0]; @@ -20608,7 +20971,7 @@ sub mem_processes { } @ps_rows = splice(@ps_rows,0,$count); # print Data::Dumper::Dumper \@rows; - push(@$rows,main::MemoryData::full('process')) if !$loaded{'memory'}; + push(@$rows,main::MemoryData::row('process')) if !$loaded{'memory'}; $j = scalar @$rows; my $throttled = throttled($ps_count,$count,$j); #$cpu_mem = ' - CPU: % used' if $extra > 0; @@ -20649,6 +21012,7 @@ sub mem_processes { } eval $end if $b_log; } + sub process_starter { my ($count, $row10, $row11) = @_; my $return = []; @@ -20666,6 +21030,7 @@ sub process_starter { } return $return; } + sub throttled { my ($ps_count,$count,$j) = @_; my $throttled = ''; @@ -20727,6 +21092,7 @@ sub get { eval $end if $b_log; return $rows; } + sub hw_output { eval $start if $b_log; my ($rows,$hardware_raid) = @_; @@ -20764,6 +21130,7 @@ sub hw_output { eval $end if $b_log; # print Data::Dumper::Dumper $rows; } + sub btrfs_output { eval $start if $b_log; my $rows = $_[0]; @@ -20780,6 +21147,7 @@ sub btrfs_output { eval $end if $b_log; # print Data::Dumper::Dumper $rows; } + sub lvm_output { eval $start if $b_log; my $rows = $_[0]; @@ -20801,7 +21169,6 @@ sub lvm_output { if ($row->{'raid-sync'}){ $rows->[$j]{main::key($num++,0,2,'sync')} = $row->{'raid-sync'}; } - if ($extra > 0){ $j = scalar @$rows; $num = 1; @@ -20843,6 +21210,7 @@ sub lvm_output { eval $end if $b_log; # print Data::Dumper::Dumper $rows; } + sub md_output { eval $start if $b_log; my $rows = $_[0]; @@ -21140,7 +21508,7 @@ sub zfs_output { # print Data::Dumper::Dumper $rows; } -## Most key stuff passed by ref, and is changed on the fly +# Most key stuff passed by ref, and is changed on the fly sub components_output { eval $start if $b_log; my ($type,$item,$rows,$array,$j,$num,$b_bump) = @_; @@ -21234,17 +21602,18 @@ sub raid_data { } eval $end if $b_log; } -# 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 + +# 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 sub hw_data { eval $start if $b_log; return if !$devices{'hwraid'}; @@ -21275,6 +21644,8 @@ sub hw_data { eval $end if $b_log; return $hardware_raid; } + +# Placeholder, if they ever get useful tools sub btrfs_data { eval $start if $b_log; my (@btraid,@working); @@ -21290,6 +21661,7 @@ sub btrfs_data { eval $end if $b_log; return @btraid; } + sub lvm_data { eval $start if $b_log; LogicalItem::lvm_data() if !$loaded{'logical-data'}; @@ -21348,6 +21720,7 @@ sub lvm_data { eval $end if $b_log; return @lvraid; } + sub md_data { eval $start if $b_log; my ($mdstat) = @_; @@ -21503,6 +21876,7 @@ sub md_data { eval $end if $b_log; return @mdraid; } + sub md_details { eval $start if $b_log; my ($id) = @_; @@ -21824,6 +22198,7 @@ sub zfs_data { eval $end if $b_log; return @zfs; } + sub zfs_fs_sizes { my ($path,$id) = @_; eval $start if $b_log; @@ -21845,6 +22220,7 @@ sub zfs_fs_sizes { eval $end if $b_log; return @data; } + sub zfs_status { eval $start if $b_log; my ($zpool,$zfs) = @_; @@ -21897,6 +22273,7 @@ sub zfs_status { eval $end if $b_log; return @$zfs; } + sub check_zfs_status { eval $start if $b_log; my ($item,$pool_status) = @_; @@ -21918,11 +22295,12 @@ sub check_zfs_status { { package RamItem; my ($vendors,$vendor_ids); + sub get { my ($key1,$ram,$val1); my $rows = []; my $num = 0; - push(@$rows, MemoryData::full('ram')) if !$loaded{'memory'}; + push(@$rows, MemoryData::row('ram')) if !$loaded{'memory'}; if ($bsd_type && !$force{'dmidecode'} && ($dboot{'ram'} || $fake{'dboot'})){ $ram = dboot_data(); if (@$ram){ @@ -21980,7 +22358,7 @@ sub ram_output { foreach my $item (@$ram){ $j = scalar @$rows; if (!$show{'ram-short'}){ - $b_non_system = ($item->{'use'} && lc($item->{'use'}) ne 'system memory') ? 1:0 ; + $b_non_system = ($item->{'use'} && lc($item->{'use'}) ne 'system memory') ? 1:0; $num = 1; push(@$rows, { main::key($num++,1,1,'Array') => '', @@ -21997,7 +22375,8 @@ sub ram_output { $item->{'eec'} ||= 'N/A'; $rows->[$j]{main::key($num++,0,2,'EC')} = $item->{'eec'}; if ($extra > 0 && (!$b_non_system || - (main::is_numeric($item->{'max-module-size'}) && $item->{'max-module-size'} > 10))){ + (main::is_numeric($item->{'max-module-size'}) && + $item->{'max-module-size'} > 10))){ $rows->[$j]{main::key($num++,1,2,'max-module-size')} = process_size($item->{'max-module-size'}); if ($item->{'mod-qualifier'}){ $rows->[$j]{main::key($num++,0,3,'note')} = $item->{'mod-qualifier'}; @@ -22017,7 +22396,7 @@ sub ram_output { foreach my $mod (@$entry){ $num = 1; $j = scalar @$rows; - # multi array setups will start index at next from previous array + # Multi array setups will start index at next from previous array next if ref $mod ne 'HASH'; if ($show{'ram-short'}){ $modules++ if ($mod->{'size'} =~ /^\d/); @@ -22029,7 +22408,7 @@ sub ram_output { push(@$rows, { main::key($num++,1,2,'Device') => $mod->{'locator'}, }); - # this will contain the no module string + # This will contain the no module string if ($mod->{'size'} =~ /\D/){ $rows->[$j]{main::key($num++,0,3,'type')} = lc($mod->{'size'}); next; @@ -22048,27 +22427,35 @@ sub ram_output { $mod->{'speed'} ne $mod->{'configured-clock-speed'}){ $rows->[$j]{main::key($num++,1,3,'speed')} = ''; $rows->[$j]{main::key($num++,0,4,'spec')} = $mod->{'speed'}; - $rows->[$j]{main::key($num++,0,4,'note')} = $mod->{'speed-note'} if $mod->{'speed-note'}; + if ($mod->{'speed-note'}){ + $rows->[$j]{main::key($num++,0,4,'note')} = $mod->{'speed-note'}; + } $rows->[$j]{main::key($num++,0,4,'actual')} = $mod->{'configured-clock-speed'}; - $rows->[$j]{main::key($num++,0,5,'note')} = $mod->{'configured-note'} if $mod->{'configured-note'}; + if ($mod->{'configured-note'}){ + $rows->[$j]{main::key($num++,0,5,'note')} = $mod->{'configured-note'}; + } } else { if (!$mod->{'speed'} && $mod->{'configured-clock-speed'}){ if ($mod->{'configured-clock-speed'}){ $mod->{'speed'} = $mod->{'configured-clock-speed'}; - $mod->{'speed-note'} = $mod->{'configured-note'} if $mod->{'configured-note'} ; + if ($mod->{'configured-note'}){ + $mod->{'speed-note'} = $mod->{'configured-note'}; + } } } - # rare instances, dmi type 6, no speed, dboot also no speed + # 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'}; + if ($mod->{'speed-note'}){ + $rows->[$j]{main::key($num++,0,4,'note')} = $mod->{'speed-note'}; + } } - # handle cases where -xx or -xxx and no voltage data (common) or voltages + # Handle cases where -xx or -xxx and no voltage data (common) or voltages # are all the same. if ($extra > 1){ - if (($mod->{'voltage-config'} || $mod->{'voltage-max'} || $mod->{'voltage-min'}) && - ($b_admin || ( + if (($mod->{'voltage-config'} || $mod->{'voltage-max'} || + $mod->{'voltage-min'}) && ($b_admin || ( ($mod->{'voltage-config'} && $mod->{'voltage-max'} && $mod->{'voltage-config'} ne $mod->{'voltage-max'}) || ($mod->{'voltage-config'} && $mod->{'voltage-min'} && @@ -22140,7 +22527,7 @@ sub dmidecode_data { my $check = main::message('note-check'); # print Data::Dumper::Dumper \@dmi; foreach my $entry (@dmi){ - ## NOTE: do NOT reset these values, that causes failures + ## 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); if ($entry->[0] == 5){ foreach my $item (@$entry){ @@ -22177,14 +22564,14 @@ sub dmidecode_data { @temp = split(/:\s*/, $item, 2); next if !$temp[1]; if ($temp[0] eq 'Installed Size'){ - # get module size + # Get module size $size = calculate_size($temp[1],0); - # using this causes issues, really only works for 16 -# if ($size =~ /^[0-9][0-9]+$/){ -# $ram->[$k]{'device-count-found'}++; -# $ram->[$k]{'used-capacity'} += $size; -# } - # get data after module size + # Using this causes issues, really only works for 16 + # if ($size =~ /^[0-9][0-9]+$/){ + # $ram->[$k]{'device-count-found'}++; + # $ram->[$k]{'used-capacity'} += $size; + # } + # Get data after module size $temp[1] =~ s/ Connection\)?//; $temp[1] =~ s/^[0-9]+\s*[KkMGTP]B\s*\(?//; $type = lc($temp[1]); @@ -22203,9 +22590,10 @@ sub dmidecode_data { $device_type = main::clean_dmi($temp[1]); } } - # because of the wide range of bank/slot type data, we will just use - # the one that seems most likely to be right. Some have: Bank: SO DIMM 0 slot: J6A - # so we dump the useless data and use the one most likely to be visibly correct + # Because of the wide range of bank/slot type data, we will just use + # the one that seems most likely to be right. Some have: + # 'Bank: SO DIMM 0 slot: J6A' so we dump the useless data and use the + # one most likely to be visibly correct if ($bank_locator =~ /DIMM/){ $main_locator = $bank_locator; } @@ -22234,7 +22622,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 DmiData, 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'; @@ -22273,7 +22661,7 @@ sub dmidecode_data { if ($temp[0] eq 'Array Handle'){ $handle = hex($temp[1]); } - # these two can have 'none' or 'unknown' value + # These two can have 'none' or 'unknown' value elsif ($temp[0] eq 'Data Width'){ $data_width = main::clean_dmi($temp[1]); $data_width =~ s/[\s_-]?bits// if $data_width; @@ -22282,7 +22670,8 @@ sub dmidecode_data { $total_width = main::clean_dmi($temp[1]); $total_width =~ s/[\s_-]?bits// if $total_width; } - # do not try to guess from installed modules, only use this to correct type 5 data + # Do not try to guess from installed modules, only use this to correct + # type 5 data elsif ($temp[0] eq 'Size'){ # we want any non real size data to be preserved if ($temp[1] =~ /^[0-9]+\s*[KkMTPG]i?B/){ @@ -22315,9 +22704,10 @@ sub dmidecode_data { my $result = process_speed($temp[1],$device_type,$check); ($speed,$speed_note) = @$result; } - # this is the actual speed the system booted at, speed is hardcoded + # This is the actual speed the system booted at, speed is hardcoded # clock speed means MHz, memory speed MT/S - elsif ($temp[0] eq 'Configured Clock Speed' || $temp[0] eq 'Configured Memory Speed'){ + elsif ($temp[0] eq 'Configured Clock Speed' || + $temp[0] eq 'Configured Memory Speed'){ my $result = process_speed($temp[1],$device_type,$check); ($configured_speed,$configured_note) = @$result; } @@ -22347,9 +22737,10 @@ sub dmidecode_data { } } } - # because of the wide range of bank/slot type data, we will just use - # the one that seems most likely to be right. Some have: Bank: SO DIMM 0 slot: J6A - # so we dump the useless data and use the one most likely to be visibly correct + # Because of the wide range of bank/slot type data, we will just use the + # one that seems most likely to be right. Some have: + # 'Bank: SO DIMM 0 slot: J6A' so we dump the useless data and use the one + # most likely to be visibly correct. if ($bank_locator =~ /DIMM/){ $main_locator = $bank_locator; } @@ -22361,10 +22752,11 @@ sub dmidecode_data { # build up actual capacity found for override tests $ram->[$handle]{'used-capacity'} += $working_size; } - # sometimes the data is just wrong, they reverse total/data. data I believe is - # used for the actual memory bus width, total is some synthetic thing, sometimes missing. - # note that we do not want a regular string comparison, because 128 bit memory buses are - # in our future, and 128 bits < 64 bits with string compare + # Sometimes the data is just wrong, they reverse total/data. data I + # believe is used for the actual memory bus width, total is some synthetic + # thing, sometimes missing. Note that we do not want a regular string + # comparison, because 128 bit memory buses are in our future, and + # 128 bits < 64 bits with string compare. $data_width =~ /(^[0-9]+).*/; $i_data = $1; $total_width =~ /(^[0-9]+).*/; @@ -22424,6 +22816,7 @@ sub dmidecode_data { eval $end if $b_log; return $ram; } + sub dboot_data { eval $start if $b_log; my $ram = []; @@ -22432,19 +22825,19 @@ sub dboot_data { 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 + # Note: seen a netbsd with multiline spdmem0/1 etc but not consistent, 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 + # 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. + # Then since we are on a new iic device, assume new ram array. + # This needs more data to confirm this guess. $arr++; } if ($5){ @@ -22458,15 +22851,17 @@ sub dboot_data { $device_detail = 'EEC'; $ecc = 'EEC'; } - if (/\b(PC[0-9]+-\S+)\b/){ + # Possible: PC2700CL2.5 PC3-10600 + if (/\b(PC([2-9]?-|)\d{4,})[^\d]/){ $speed = $1; + $speed =~ s/PC/PC-/ if $speed =~ /^PC\d{4}/; 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 + # 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; @@ -22475,7 +22870,7 @@ sub dboot_data { $locator = 'Slot-' . $ram->[$arr]{'slots-16'}; } $ram->[$arr]{'device-count-found'}++; - # build up actual capacity found for override tests + # 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; @@ -22508,6 +22903,7 @@ sub dboot_data { eval $end if $b_log; return $ram; } + sub process_data { eval $start if $b_log; my $ram = $_[0]; @@ -22516,22 +22912,22 @@ sub process_data { my $check = main::message('note-check'); my $est = main::message('note-est'); foreach my $item (@$ram){ - # because we use the actual array handle as the index, - # there will be many undefined keys + # Because we use the actual array handle as the index, there will be many + # undefined keys. next if ! defined $item; my ($max_cap,$max_mod_size) = (0,0); my ($alt_cap,$est_cap,$est_mod,$est_slots,$unit) = (0,'','','',''); $max_cap = $item->{'max-capacity-16'}; $max_cap ||= 0; - # make sure they are integers not string if empty + # Make sure they are integers not string if empty. $item->{'slots-5'} ||= 0; $item->{'slots-16'} ||= 0; $item->{'device-count-found'} ||= 0; $item->{'max-capacity-5'} ||= 0; $item->{'max-module-size'} ||= 0; $item->{'used-capacity'} ||= 0; - #$item->{'max-module-size'} = 0;# debugger - # 1: if max cap 1 is null, and max cap 2 not null, use 2 + # $item->{'max-module-size'} = 0;# debugger + # 1: If max cap 1 is null, and max cap 2 not null, use 2 if ($b_debug){ print "1: mms: $item->{'max-module-size'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; print "1a: s5: $item->{'slots-5'} s16: $item->{'slots-16'}\n"; @@ -22542,7 +22938,8 @@ sub process_data { if ($b_debug){ print "2: mms: $item->{'max-module-size'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; } - # 2: now check to see if actually found module sizes are > than listed max module, replace if > + # 2: Now check to see if actually found module sizes are > than listed + # max module, replace if > if ($item->{'max-module-size'} && $item->{'derived-module-size'} && $item->{'derived-module-size'} > $item->{'max-module-size'}){ $item->{'max-module-size'} = $item->{'derived-module-size'}; @@ -22551,11 +22948,12 @@ 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. + # 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'})){ - # first check that actual memory found is not greater than listed max cap, or - # checking to see module count * max mod size is not > used capacity + # First check that actual memory found is not greater than listed max cap, + # or checking to see module count * max mod size is not > used capacity if ($item->{'used-capacity'} && $item->{'max-capacity-16'}){ if ($item->{'used-capacity'} > $max_cap){ if ($item->{'max-module-size'} && @@ -22577,23 +22975,26 @@ sub process_data { } } } - # note that second case will never really activate except on virtual machines and maybe - # mobile devices + # Note that second case will never really activate except on virtual + # machines and maybe mobile devices. if (!$est_cap){ - # do not do this for only single modules found, max mod size can be equal to the array size + # Do not do this for only single modules found, max mod size can be + # equal to the array size. if ($item->{'slots-16'} > 1 && $item->{'device-count-found'} > 1 && $max_cap < ($item->{'derived-module-size'} * $item->{'slots-16'})){ $max_cap = $item->{'derived-module-size'} * $item->{'slots-16'}; $est_cap = $est; print "D\n" if $b_debug; } - elsif ($item->{'device-count-found'} > 0 && $max_cap < ($item->{'derived-module-size'} * $item->{'device-count-found'})){ + elsif ($item->{'device-count-found'} > 0 && + $max_cap < ($item->{'derived-module-size'} * $item->{'device-count-found'})){ $max_cap = $item->{'derived-module-size'} * $item->{'device-count-found'}; $est_cap = $est; print "E\n" if $b_debug; } - ## handle cases where we have type 5 data: mms x device count equals type 5 max cap - # however do not use it if cap / devices equals the derived module size + # Handle cases where we have type 5 data: mms x device count equals + # type 5 max caphowever do not use it if cap / devices equals the + # derived module size. elsif ($item->{'max-module-size'} > 0 && ($item->{'max-module-size'} * $item->{'slots-16'}) == $item->{'max-capacity-5'} && $item->{'max-capacity-5'} != $item->{'max-capacity-16'} && @@ -22607,18 +23008,20 @@ sub process_data { if ($b_debug){ print "4: mms: $item->{'max-module-size'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; } - # some cases of type 5 have too big module max size, just dump the data then since - # we cannot know if it is valid or not, and a guess can be wrong easily + # Some cases of type 5 have too big module max size, just dump the data + # then since we cannot know if it is valid or not, and a guess can be + # wrong easily. if ($item->{'max-module-size'} && $max_cap && $item->{'max-module-size'} > $max_cap){ $item->{'max-module-size'} = 0; } if ($b_debug){ print "5: dms: $item->{'derived-module-size'} :s16: $item->{'slots-16'} :mc: $max_cap\n"; } - # now prep for rebuilding the ram array data + # Now prep for rebuilding the ram array data. if (!$item->{'max-module-size'}){ # ie: 2x4gB - if (!$est_cap && $item->{'derived-module-size'} > 0 && $max_cap > ($item->{'derived-module-size'} * $item->{'slots-16'} * 4)){ + if (!$est_cap && $item->{'derived-module-size'} > 0 && + $max_cap > ($item->{'derived-module-size'} * $item->{'slots-16'} * 4)){ $est_cap = $check; print "G\n" if $b_debug; } @@ -22642,7 +23045,7 @@ sub process_data { $est_mod = $est; } } - # case where listed max cap is too big for actual slots x max cap, eg: + # Case where listed max cap is too big for actual slots x max cap, eg: # listed max cap, 8gb, max mod 2gb, slots 2 else { if (!$est_cap && $item->{'max-module-size'} > 0){ @@ -22653,7 +23056,7 @@ sub process_data { } } } - # no slots found due to legacy dmi probably. Note, too many logic errors + # No slots found due to legacy dmi probably. Note, too many logic errors # happen if we just set a general slots above, so safest to do it here $item->{'slots-16'} = $item->{'slots-5'} if $item->{'slots-5'} && !$item->{'slots-16'}; if (!$item->{'slots-16'} && $item->{'modules'} && ref $item->{'modules'} eq 'ARRAY'){ @@ -22661,7 +23064,7 @@ sub process_data { $item->{'slots-16'} = scalar @{$item->{'modules'}}; print "L\n" if $b_debug; } - # only bsds using dmesg data + # Only bsds using dmesg data elsif ($item->{'slots-qualifier'}){ $est_slots = $item->{'slots-qualifier'}; $est_cap = $est; @@ -22685,22 +23088,26 @@ sub process_data { @$ram = @result; eval $end if $b_log; } + sub process_speed { my ($speed,$device_type,$check) = @_; my $speed_note; $speed = main::clean_dmi($speed) if $speed; - if ($device_type && $device_type =~ /ddr/i && $speed && $speed =~ /^([0-9]+)\s*MHz/){ + if ($device_type && $device_type =~ /ddr/i && $speed && + $speed =~ /^([0-9]+)\s*MHz/){ $speed = ($1 * 2) . " MT/s ($speed)"; } - # seen cases of 1 MT/s, 61690 MT/s, not sure why, bug - # crucial is shipping 5100 MT/s now, and 6666 has been hit, so speeds can hit 10k + # Seen cases of 1 MT/s, 61690 MT/s, not sure why, bug. Crucial is shipping + # 5100 MT/s now, and 6666 has been hit, so speeds can hit 10k. if ($speed && $speed =~ /^([0-9]+)\s*M/){ $speed_note = $check if $1 < 50 || $1 > 20000 ; } return [$speed,$speed_note]; } -# this should be fixed, but for now, size in RAM is in MiB, not + +# This should be fixed, but for now, size in RAM is in MiB, not # KiB like the rest of inxi. +# args: 0: size in MiB sub process_size { my ($size) = @_; my ($b_trim,$unit) = (0,''); @@ -22709,26 +23116,27 @@ sub process_size { #return $size if $size =~ /\D/; return $size if !main::is_numeric($size); # print "size: $size\n"; - # we only want a max 2 decimal places, and only when it's - # a unit > 1 GiB + # We only want a max 2 decimal places, and only when it's + # a unit > 1 GiB. $b_trim = 1 if $size > 1024; - # switch it back to KiB for tool - ($size,$unit) = main::get_size($size * 1024); + # Switch it back to KiB for tool + ($size,$unit) = main::get_size($size*1024); $size = sprintf("%.2f",$size) if $b_trim; $size =~ s/\.[0]+$//; $size = "$size $unit"; return $size; } -# note that even though MB should be 1000^x it's actually -# MiB etc. As with process_size, this uses MiB not KiB + +# Note that even though MB should be 1000^x it's actually MiB etc. As with +# process_size, this uses MiB not KiB. sub calculate_size { my ($data, $size) = @_; - # technically k is KiB, K is KB but can't trust that + # Technically k is KiB, K is KB but can't trust that. if ($data =~ /^([0-9]+\s*[kKGMTP])i?B/){ my $working = $1; - # this converts it to KiB + # This converts it to KiB my $working_size = main::translate_size($working); - # but we want it back in MiB for RAM, that should get fixed + # 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"; if (main::is_numeric($working_size) && $working_size > $size){ @@ -22742,10 +23150,12 @@ sub calculate_size { # print "d-2: $data s-3: $size\n"; return $size; } + +# BSD: Map string to speed, in MT/s sub speed_mapper { my ($type) = @_; my %speeds = ( - # DDR + # DDR1 'PC-1600' => 200, 'PC-2100' => 266, 'PC-2400' => 300, @@ -22757,33 +23167,50 @@ sub speed_mapper { 'PC2-5300' => 667, 'PC2-6400' => 800, 'PC2-8000' => 1000, + 'PC2-8500' => 1066, # DDR3 'PC3-6400' => 800, 'PC3-8500' => 1066, 'PC3-10600' => 1333, 'PC3-12800' => 1600, + 'PC3-14900 ' => 1866, + 'PC3-17000' => 2133, # DDR4 + 'PC4-12800' => 1600, + 'PC4-14900' => 1866, + 'PC4-17000' => 2133, 'PC4-19200' => 2400, - 'PC4-21300' => 2666, - 'PC4-23400' => 2933, + 'PC4-21333' => 2666, + 'PC4-23466' => 2933, 'PC4-24000' => 3000, 'PC4-25600' => 3200, 'PC4-28800' => 3600, 'PC4-32000' => 4000, 'PC4-35200' => 4400, # DDR5 + 'PC5-32000' => 4000, + 'PC5-35200' => 4400, 'PC5-38400' => 4800, + 'PC5-41600' => 5200, + 'PC5-44800' => 5600, + 'PC5-48000' => 6000, + 'PC5-49600' => 6200, 'PC5-51200' => 6400, + 'PC5-54400' => 6800, + 'PC5-57600' => 7200, + 'PC5-60800' => 7600, + 'PC5-64000' => 8000, # DDR6, coming... ); return ($speeds{$type}) ? $speeds{$type} . ' MT/s' : $type; } + ## START RAM VENDOR ## sub set_ram_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 + ['^(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',''], @@ -22794,24 +23221,24 @@ sub set_ram_vendors { ['^(PE[\d]{4}|Edge)','Edge','Edge',''], ['^(Elpida|EB)','^Elpida','Elpida',''], ['^(GVT|Galvantech)','Galvantech','Galvantech',''], - # if we get more G starters, make rules tighter + # 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',''], - # qimonda spun out of infineon, same ids + # Qimonda spun out of Infineon, same ids # ['^(HYS]|Qimonda)','Qimonda','Qimonda',''], ['^(HY|Infineon)','Infineon','Infineon',''],#HY[A-Z]\d ['^(KSM|KVR|Kingston)','Kingston','Kingston',''], ['^(LuminouTek)','LuminouTek','LuminouTek',''], ['^(MT|Micron)','Micron','Micron',''], - # seen: 992069 991434 997110S + # Seen: 992069 991434 997110S ['^(M[BLERS][A-Z][1-7]|99[0-9]{3}|Mushkin)','Mushkin','Mushkin',''], ['^(OCZ)','^OCZ\b','OCZ',''], ['^([MN]D\d|OLOy)','OLOy','OLOy',''], ['^(M[ERS]\d|Nemix)','Nemix','Nemix',''], - # before patriot just in case + # Before patriot just in case ['^(MN\d|PNY)','PNY\s','PNY',''], ['^(P[A-Z]|Patriot)','Patriot','Patriot',''], ['^(K[1-6][ABLT]|K\d|M[\d]{3}[A-Z]|Samsung)','Samsung','Samsung',''], @@ -22826,7 +23253,8 @@ sub set_ram_vendors { ['^(Yangtze|Zhitai|YMTC)','(Yangtze(\s*Memory)?|YMTC)','YMTC',''], ]; } -# note: many of these are pci ids, not confirmed valid for ram + +# Note: many of these are pci ids, not confirmed valid for ram sub set_ram_vendor_ids { $vendor_ids = { '01f4' => 'Transcend',# confirmed @@ -22863,6 +23291,7 @@ sub set_ram_vendor_ids { } } ## END RAM VENDOR ## + sub ram_vendor { eval $end if $b_log; my ($id) = $_[0]; @@ -22896,6 +23325,7 @@ package RepoItem; # easier to keep these package global, but undef after done my (@dbg_files,$debugger_dir,%repo_keys); my $num = 0; + sub get { eval $start if $b_log; ($debugger_dir) = @_; @@ -22935,6 +23365,7 @@ sub get { eval $end if $b_log; return $rows; } + sub get_repos_linux { eval $start if $b_log; my $rows = $_[0]; @@ -22948,16 +23379,21 @@ sub get_repos_linux { my $dnf_conf = '/etc/dnf/dnf.conf'; my $dnf_repo_dir = '/etc/dnf.repos.d/'; my $eopkg_dir = '/var/lib/eopkg/'; + my $netpkg = '/etc/netpkg.conf'; + my $netpkg_dir = '/etc/netpkg.d'; my $nix = '/etc/nix/nix.conf'; my $pacman = '/etc/pacman.conf'; my $pacman_g2 = '/etc/pacman-g2.conf'; my $pisi_dir = '/etc/pisi/'; my $portage_dir = '/etc/portage/repos.conf/'; my $portage_gentoo_dir = '/etc/portage-gentoo/repos.conf/'; + my $sbopkg = '/etc/sbopkg/sbopkg.conf'; + my $sboui_backend = '/etc/sboui/sboui-backend.conf'; my $scratchpkg = '/etc/scratchpkg.repo'; my $slackpkg = '/etc/slackpkg/mirrors'; my $slackpkg_plus = '/etc/slackpkg/slackpkgplus.conf'; my $slapt_get = '/etc/slapt-get/'; + my $slpkg = '/etc/slpkg/repositories.toml'; my $tce_app = '/usr/bin/tce'; my $tce_file = '/opt/tcemirror'; my $tce_file2 = '/opt/localmirrors'; @@ -22967,8 +23403,8 @@ sub get_repos_linux { my $xbps_dir_2 = '/usr/share/xbps.d/'; my $zypp_repo_dir = '/etc/zypp/repos.d/'; my $b_test = 0; - # apt - debian, buntus, also sometimes some yum/rpm repos may create - # apt repos here as well + ## apt: Debian, *buntus + derived (deb files);AltLinux, PCLinuxOS (rpm files) + # Sometimes some yum/rpm repos may create apt repos here as well if (-f $apt || -d "$apt.d"){ my ($apt_arch,$apt_comp,$apt_suites,$apt_types,@apt_urls,@apt_working, $b_apt_enabled,$file,$string); @@ -23073,7 +23509,7 @@ sub get_repos_linux { } @files = (); } - # pacman: Arch and derived + ## pacman, pacman-g2: Arch + derived, Frugalware if (-f $pacman || -f $pacman_g2){ $repo = 'pacman'; if (-f $pacman_g2){ @@ -23114,15 +23550,98 @@ sub get_repos_linux { ); } } - # slackware - if (-f $slackpkg || -f $slackpkg_plus || -d $slapt_get){ - #$slackpkg = "$ENV{HOME}/bin/scripts/inxi/data/repo/slackware/slackpkg-2.conf"; + ## netpkg: Zenwalk, Slackware + if (-f $netpkg){ + my @data2 = ($netpkg); + if (-d $netpkg_dir){ + @data3 = main::globber("$netpkg_dir/*"); + @data3 = grep {!/\/local$/} @data3 if @data3; # package directory + push(@data2,@data3) if @data3; + } + foreach my $file (@data2){ + $data = repo_builder($file,'netpkg','^URL\s*=','\s*=\s*',1); + push(@$rows,@$data); + } + } + ## sbopkg, sboui, slackpkg, slackpkg+, slapt_get, slpkg: Slackware + derived + # $slpkg = "$ENV{'HOME'}/bin/scripts/inxi/data/repo/slackware/slpkg-2.toml"; + # $sbopkg = "$ENV{HOME}/bin/scripts/inxi/data/repo/slackware/sbopkg-2.conf"; + # $sboui_backend = "$ENV{HOME}/bin/scripts/inxi/data/repo/slackware/sboui-backend-1.conf"; + if (-f $slackpkg || -f $slackpkg_plus || -d $slapt_get || -f $slpkg || + -f $sbopkg || -f $sboui_backend){ + if (-f $sbopkg){ + my $sbo_root = '/root/.sbopkg.conf'; + # $sbo_root = "$ENV{HOME}/bin/scripts/inxi/data/repo/slackware/sbopkg-root-1.conf"; + @files = ($sbopkg); + # /root not readable as user, unless it is, so just check if readable + push(@files,$sbo_root) if -r $sbo_root; + my ($branch,$name); + # SRC_REPO repo URL not used, not what we think + foreach my $file (@files){ + foreach my $row (main::reader($file,'strip')){ + if ($row =~ /^REPO_NAME=(\S\{REPO_NAME:-)?(.*?)\}?$/){ + $name = $2; + } + elsif ($row =~ /^REPO_BRANCH=(\S\{REPO_BRANCH:-)?(.*?)\}?$/){ + $branch = $2; + } + } + } + # First found overridden by next, so we don't care where the value came + # from. We do care if 1 file and not root however, since might be wrong. + if ($branch && $name){ + if ($b_root || scalar @files == 2){ + $key = repo_data('active','sbopkg'); + } + else { + $key = repo_data('active-permissions','sbopkg'); + } + @content = ("$name ~ $branch"); + } + else { + $key = repo_data('missing','sbopkg'); + } + my @data = ( + {main::key($num++,1,1,$key) => join(', ',@files)}, + [@content], + ); + push(@$rows,@data); + (@content,@files) = (); + } + if (-f $sboui_backend){ + my ($branch,$repo); + # Note: sboui also has a sboui.conf file, with the package_manager string + # but that is too hard to handle clearly in output so leaving aside. + foreach my $row (main::reader($sboui_backend,'strip')){ + if ($row =~ /^REPO\s*=\s*["']?(\S+?)["']?\s*$/){ + $repo = $1; + } + elsif ($row =~ /^BRANCH\s*=\s*["']?(\S+?)["']?\s*$/){ + $branch = $1; + } + } + if ($repo){ + $key = repo_data('active','sboui'); + $branch = 'current' if !$branch || $repo =~ /ponce/i; + @content = ("SBo $branch ~ $repo"); # we want SBo name to show + } + else { + $key = repo_data('missing','sboui'); + } + my @data = ( + {main::key($num++,1,1,$key) => $sboui_backend}, + [@content], + ); + push(@$rows,@data); + @content = (); + } if (-f $slackpkg){ $data = repo_builder($slackpkg,'slackpkg','^[[:space:]]*[^#]+'); push(@$rows,@$data); } if (-d $slapt_get){ @data2 = main::globber("${slapt_get}*"); + @data2 = grep {!/pubring/} @data2 if @data2; foreach my $file (@data2){ $data = repo_builder($file,'slaptget','^\s*SOURCE','\s*=\s*',1); push(@$rows,@$data); @@ -23150,23 +23669,76 @@ sub get_repos_linux { } } } - if (! @content){ + if (!@content){ $key = repo_data('missing','slackpkg+'); } else { clean_url(\@content); $key = repo_data('active','slackpkg+'); } - my @data = ( + my @data = ( {main::key($num++,1,1,$key) => $slackpkg_plus}, [@content], ); - clean_url(\@data); push(@$rows,@data); @content = (); } + if (-f $slpkg){ + my ($active,$name,$repo); + my $holder = ''; + @data2 = main::reader($slpkg); + # We can't rely on the presence of empty lines as block separator. + push(@data2,'-eof-') if @data2; + # print Data::Dumper::Dumper \@data2; + # old: "https://download.salixos.org/x86_64/slackware-15.0/" + # new: ["https://slac...nl/people/alien/sbrepos/", "15.0/", "x86_64/"] + foreach (@data2){ + next if /^\s*([#\[]|$)/; + $_ = lc($_); + if (/^\s*(\S+?)_(repo(|_name|_mirror))\s*=\s*[\['"]{0,2}(.*?)[\]'"]{0,2}\s*$/ || + $_ eq '-eof-'){ + my ($key,$value) = ($2,$4); + if (($1 && $holder ne $1) || $_ eq '-eof-'){ + $holder = $1; + if ($name && $repo){ + if (!$active || $active =~ /^(true|1|yes)$/i){ + push(@content,"$name ~ $repo"); + } + ($active,$name,$repo) = (); + } + } + if ($key){ + if ($key eq 'repo'){ + $active = $value;} + elsif ($key eq 'repo_name'){ + $name = $value;} + elsif ($key eq 'repo_mirror'){ + # map new form to a real url + $value =~ s/['"],\s*['"]//g; + $repo = $value;} + } + } + } + if (!@content){ + $key = repo_data('missing','slpkg'); + } + else { + # Special case, sbo and ponce true, dump sbo, they conflict. + # slpkg does this internally so no other way to handle. + if (grep {/^ponce ~/} @content){ + @content = grep {!/sbo ~/} @content; + } + clean_url(\@content); + $key = repo_data('active','slpkg'); + } + push(@$rows, + {main::key($num++,1,1,$key) => $slpkg}, + [@content], + ); + (@content,@data2,@data3) = (); + } } - # redhat/suse + ## dnf, yum, zypp: Redhat, Suse + derived (rpm based) if (-f $dnf_conf ||-d $dnf_repo_dir|| -d $yum_repo_dir || -f $yum_conf || -d $zypp_repo_dir){ @files = (); @@ -23232,8 +23804,7 @@ sub get_repos_linux { if ($url && $title && $enabled){ push(@content, "$title ~ $url"); } - - if (! @content){ + if (!@content){ $key = repo_data('missing',$repo); } else { @@ -23249,7 +23820,7 @@ sub get_repos_linux { } # print Data::Dumper::Dumper \@$rows; } - # gentoo + # emerge, portage: Gentoo + derived if ((-d $portage_dir || -d $portage_gentoo_dir) && main::check_program('emerge')){ @files = (main::globber("$portage_dir*.conf"),main::globber("$portage_gentoo_dir*.conf")); $repo = 'portage'; @@ -23311,7 +23882,7 @@ sub get_repos_linux { } } } - # Alpine linux/Chimera + ## apk: Alpine, Chimera if (-f $apk || -d "$apk.d"){ @files = main::globber("$apk.d/*.list"); push(@files, $apk); @@ -23326,12 +23897,12 @@ sub get_repos_linux { } } } - # Venom + ## scratchpkg: Venom if (-f $scratchpkg){ $data = repo_builder($scratchpkg,'scratchpkg','^[[:space:]]*[^#]+'); push(@$rows,@$data); } - # cards/nutyx + # cards: Nutyx if (-f $cards){ @data3 = main::reader($cards,'clean'); push(@dbg_files, $cards) if $debugger_dir; @@ -23354,7 +23925,7 @@ sub get_repos_linux { ); @content = (); } - # TinyCore + ## tce: TinyCore if (-e $tce_app || -f $tce_file || -f $tce_file2){ if (-f $tce_file){ $data = repo_builder($tce_file,'tce','^\s*[^#]+'); @@ -23365,7 +23936,7 @@ sub get_repos_linux { push(@$rows,@$data); } } - # Void + ## xbps: Void if (-d $xbps_dir_1 || -d $xbps_dir_2){ @files = main::globber("$xbps_dir_1*.conf"); push(@files,main::globber("$xbps_dir_2*.conf")) if -d $xbps_dir_2; @@ -23377,22 +23948,22 @@ sub get_repos_linux { } } } - # Mandriva/Mageia using: urpmq + ## urpmq: Mandriva, Mageia if ($path = main::check_program('urpmq')){ @data2 = main::grabber("$path --list-media active --list-url","\n",'strip'); main::writer("$debugger_dir/system-repo-data-urpmq.txt",\@data2) if $debugger_dir; - # now we need to create the structure: repo info: repo path - # we do that by looping through the lines of the output and then - # putting it back into the : format print repos expects to see - # note this structure in the data, so store first line and make start of line - # then when it's an http line, add it, and create the full line collection. + # Now we need to create the structure: repo info: repo path. We do that by + # looping through the lines of the output and then putting it back into the + # : format print repos expects to see. Note this structure in the + # data, so store first line and make start of line then when it's an http + # line, add it, and create the full line collection. # Contrib ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/release # Contrib Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/updates # Non-free ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/release # Non-free Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/updates # Nonfree Updates (Local19) /mnt/data/mirrors/mageia/distrib/cauldron/x86_64/media/nonfree/updates foreach (@data2){ - # need to dump leading/trailing spaces and clear out color codes for irc output + # Need to dump leading/trailing spaces and clear out color codes for irc output $_ =~ s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g; $_ =~ s/\e\[([0-9];)?[0-9]+m//g; # urpmq output is the same each line, repo name space repo url, can be: @@ -23411,7 +23982,7 @@ sub get_repos_linux { } } } - # Pardus/Solus + # pisi: Pardus, Solus if ((-d $pisi_dir && ($path = main::check_program('pisi'))) || (-d $eopkg_dir && ($path = main::check_program('eopkg')))){ #$path = 'eopkg'; @@ -23421,11 +23992,11 @@ sub get_repos_linux { # @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 - # we do that by looping through the lines of the output and then - # putting it back into the : format print repos expects to see - # note this structure in the data, so store first line and make start of line - # then when it's an http line, add it, and create the full line collection. + # Now we need to create the structure: repo info: repo path + # We do that by looping through the lines of the output and then putting it + # back into the : format print repos expects to see. Note this + # structure in the data, so store first line and make start of line then + # when it's an http line, add it, and create the full line collection. # Pardus-2009.1 [Aktiv] # http://packages.pardus.org.tr/pardus-2009.1/pisi-index.xml.bz2 # Contrib [Aktiv] @@ -23466,6 +24037,7 @@ sub get_repos_linux { ); } } + ## nix: General pm for Linux/Unix if (-f $nix && ($path = main::check_program('nix-channel'))){ @content = main::grabber("$path --list 2>/dev/null","\n",'strip'); main::writer("$debugger_dir/system-repo-data-nix.txt",\@content) if $debugger_dir; @@ -23487,6 +24059,7 @@ sub get_repos_linux { # print Dumper $rows; eval $end if $b_log; } + sub get_repos_bsd { eval $start if $b_log; my $rows = $_[0]; @@ -23577,31 +24150,31 @@ sub get_repos_bsd { push(@$rows,@$data); } # I don't think this is right, have to find out, for midnightbsd -# if (-f $mports){ -# @data = main::reader($mports,'strip'); -# main::writer("$debugger_dir/system-repo-data-mports.txt",\@data) if $debugger_dir; -# for (@data){ -# if (!/^MASTER_SITE_INDEX/){ -# next; -# } -# else { -# push(@data3,(split(/=\s*/,$_))[1]); -# } -# last if /^INDEX/; -# } -# if (!@data3){ -# $key = repo_data('missing','mports'); -# } -# else { -# clean_url(\@data3); -# $key = repo_data('active','mports'); -# } -# push(@$rows, -# {main::key($num++,1,1,$key) => $mports}, -# [@data3], -# ); -# @data3 = (); -# } + # if (-f $mports){ + # @data = main::reader($mports,'strip'); + # main::writer("$debugger_dir/system-repo-data-mports.txt",\@data) if $debugger_dir; + # for (@data){ + # if (!/^MASTER_SITE_INDEX/){ + # next; + # } + # else { + # push(@data3,(split(/=\s*/,$_))[1]); + # } + # last if /^INDEX/; + # } + # if (!@data3){ + # $key = repo_data('missing','mports'); + # } + # else { + # clean_url(\@data3); + # $key = repo_data('active','mports'); + # } + # push(@$rows, + # {main::key($num++,1,1,$key) => $mports}, + # [@data3], + # ); + # @data3 = (); + # } # BSDs do not default always to having repo files, so show correct error # mesage in that case if (!@$rows){ @@ -23624,6 +24197,7 @@ sub get_repos_bsd { } eval $start if $b_log; } + sub set_repo_keys { eval $start if $b_log; %repo_keys = ( @@ -23651,6 +24225,8 @@ sub set_repo_keys { 'netbsd-active' => 'NetBSD pkg servers', 'netbsd-files-missing' => 'No NetBSD pkg server files found', 'netbsd-missing' => 'No NetBSD pkg servers in', + 'netpkg-active' => 'Active netpkg repos in', + 'netpkg-missing' => 'No active netpkg repos in', 'nix-active' => 'Active nix channels for user', 'nix-missing' => 'No nix channels found for user', 'openbsd-active' => 'OpenBSD pkg mirror', @@ -23666,6 +24242,11 @@ sub set_repo_keys { 'portage-missing' => 'No enabled portage sources in', 'portsnap-active' => 'Ports server', 'portsnap-missing' => 'No ports servers in', + 'sbopkg-active' => 'Active sbopkg repo', + 'sbopkg-active-permissions' => 'Active sbopkg repo (confirm with root)', + 'sbopkg-missing' => 'No sbopkg repo', + 'sboui-active' => 'Active sboui repo', + 'sboui-missing' => 'No sboui repo', 'scratchpkg-active' => 'scratchpkg repos in', 'scratchpkg-missing' => 'No active scratchpkg repos in', 'slackpkg-active' => 'slackpkg mirror in', @@ -23674,6 +24255,8 @@ sub set_repo_keys { 'slackpkg+-missing' => 'No active slackpkg+ repos in', 'slaptget-active' => 'slapt-get repos in', 'slaptget-missing' => 'No active slapt-get repos in', + 'slpkg-active' => 'Active slpkg repos in', + 'slpkg-missing' => 'No active slpkg repos in', 'tce-active' => 'tce mirrors in', 'tce-missing' => 'No tce mirrors in', 'xbps-active' => 'Active xbps repos in', @@ -23685,6 +24268,7 @@ sub set_repo_keys { ); eval $end if $b_log; } + sub repo_data { eval $start if $b_log; my ($status,$type) = @_; @@ -23692,6 +24276,7 @@ sub repo_data { eval $end if $b_log; return $repo_keys{$type . '-' . $status}; } + sub repo_builder { eval $start if $b_log; my ($file,$type,$search,$split,$count) = @_; @@ -23721,21 +24306,26 @@ sub repo_builder { [@content], ]; } + sub clean_data { # basics: trim white space, get rid of double spaces; trim comments at # ends of repo values @{$_[0]} = map { $_ =~ s/\s\s+/ /g; $_ =~ s/^\s+|\s+$//g; + $_ =~ s/\[\s+/[/g; # [ signed-by + $_ =~ s/\s+\]/]/g; $_ =~ s/^(.*\/.*) #.*/$1/; $_;} @{$_[0]}; } -# clean if irc + +# Clean if irc sub clean_url { @{$_[0]} = map {$_ =~ s/:\//: \//; $_} @{$_[0]} if $b_irc; # trim comments at ends of repo values @{$_[0]} = map {$_ =~ s/^(.*\/.*) #.*/$1/; $_} @{$_[0]}; } + sub file_path { my ($filename,$dir) = @_; my ($working); @@ -23753,6 +24343,7 @@ package SensorItem; my $gpu_data = []; my $sensors_raw = {}; my $max_fan = 15000; + sub get { eval $start if $b_log; my ($b_data,$b_ipmi,$b_no_lm,$b_no_sys); @@ -23864,6 +24455,7 @@ sub get { eval $end if $b_log; return $rows; } + sub sensors_output { eval $start if $b_log; my ($rows,$source,$sensors) = @_; @@ -24040,6 +24632,7 @@ sub sensors_output { eval $end if $b_log; return $b_result; } + sub ipmi_data { eval $start if $b_log; my ($program) = @_; @@ -24228,6 +24821,7 @@ sub ipmi_data { print Data::Dumper::Dumper $sensors if $dbg[31]; return $sensors; } + sub linux_sensors_data { eval $start if $b_log; my $sensors = {}; @@ -24430,7 +25024,6 @@ sub linux_sensors_data { } } } - print Data::Dumper::Dumper $sensors if $dbg[31]; process_data($sensors) if %$sensors; main::log_data('dump','lm-sensors: %sensors',$sensors) if $b_log; @@ -24438,6 +25031,7 @@ sub linux_sensors_data { eval $end if $b_log; return $sensors; } + sub load_lm_sensors { eval $start if $b_log; my (@sensors_data,@values); @@ -24521,6 +25115,7 @@ sub load_lm_sensors { main::log_data('dump','lm-sensors data: %$sensors_raw',$sensors_raw) if $b_log; eval $end if $b_log; } + sub load_sys_data { eval $start if $b_log; my ($device,$mon,$name,$label,$unit,$value,@values,%hwmons); @@ -24620,7 +25215,7 @@ sub load_sys_data { my $adapter = $hwmons{$hwmon}->{'name'}; $hwmons{$hwmon}->{'device'} =~ s/^0000://; $adapter .= '-' . $hwmons{$hwmon}->{'device'}; - @values = (); + ($unit,$value,@values) = (); foreach my $item (@{$hwmons{$hwmon}->{'sensors'}}){ my $name = ($item->{'label'}) ? $item->{'label'}: $item->{'id'}; if ($item->{'id'} =~ /^temp/){ @@ -24657,15 +25252,17 @@ sub load_sys_data { $unit = 'W'; $value = sprintf('%0.1f',$item->{'value'}/1000); } - my $string = $name . ':' . $value . " $unit"; - push(@values,$string); + if (defined $value && defined $unit){ + my $string = $name . ':' . $value . " $unit"; + push(@values,$string); + } } -# if ($hwmons{$hwmon}->{'type'} eq 'acpitz' && $hwmons{$hwmon}->{'device'}){ -# my $tz ='/sys/class/thermal/' . $hwmons{$hwmon}->{'device'} . '/type'; -# if (-e $tz){ -# my $tz_type = main::reader($tz,'strip',0),"\n"; -# } -# } + # if ($hwmons{$hwmon}->{'type'} eq 'acpitz' && $hwmons{$hwmon}->{'device'}){ + # my $tz ='/sys/class/thermal/' . $hwmons{$hwmon}->{'device'} . '/type'; + # if (-e $tz){ + # my $tz_type = main::reader($tz,'strip',0),"\n"; + # } + # } if (@values){ $sensors_raw->{$hwmons{$hwmon}->{'type'}}{$adapter} = [@values]; } @@ -24749,6 +25346,7 @@ sub sysctl_data { eval $end if $b_log; return $sensors; } + sub set_temp_unit { my ($sensors,$working) = @_; my $return_unit = ''; @@ -25019,6 +25617,7 @@ sub process_data { } eval $end if $b_log; } + sub gpu_sensor_data { eval $start if $b_log; my ($cmd,@data,@data2,$path,@screens,$temp); @@ -25149,6 +25748,7 @@ sub gpu_sensor_data { { package SlotItem; my ($sys_slots); + sub get { eval $start if $b_log; my ($data,$key1,$val1); @@ -25182,6 +25782,7 @@ sub get { eval $end if $b_log; return $rows; } + sub slot_output { eval $start if $b_log; my ($rows,$data) = @_; @@ -25261,6 +25862,7 @@ sub children_output { } } } + sub slot_data_dmi { eval $start if $b_log; my $i = 0; @@ -25372,6 +25974,7 @@ sub slot_data_dmi { eval $end if $b_log; return $slots; } + sub slot_data_sys { eval $start if $b_log; my $path = '/sys/devices/pci0000:*/00*'; @@ -25386,6 +25989,7 @@ sub slot_data_sys { main::log_data('dump','$sys_slots',$sys_slots) if $b_log; eval $end if $b_log; } + sub slot_data_recursive { eval $start if $b_log; my $path = shift @_; @@ -25421,6 +26025,7 @@ sub slot_data_recursive { eval $end if $b_log; return $info; } + sub slot_children { eval $start if $b_log; my ($bus_id,$slots) = @_; @@ -25432,6 +26037,7 @@ sub slot_children { eval $end if $b_log; return $children; } + sub slot_children_recursive { my ($bus_id,$slots) = @_; my $children; @@ -25463,6 +26069,7 @@ sub get { eval $end if $b_log; return $rows; } + sub create_output { eval $start if $b_log; my $rows = $_[0]; @@ -25546,7 +26153,6 @@ sub create_output { } eval $end if $b_log; } - } ## UnmountedItem @@ -25604,6 +26210,7 @@ sub get { eval $end if $b_log; return $rows; } + sub create_output { eval $start if $b_log; my ($rows,$unmounted) = @_; @@ -25662,6 +26269,7 @@ sub create_output { } eval $end if $b_log; } + sub proc_data { eval $start if $b_log; my ($dev_mapped,$fs,$label,$maj_min,$size,$uuid,$part); @@ -25743,6 +26351,7 @@ sub proc_data { eval $end if $b_log; return $unmounted; } + sub bsd_data { eval $start if $b_log; my ($fs,$label,$size,$uuid,%part); @@ -25777,6 +26386,7 @@ sub bsd_data { eval $end if $b_log; return $unmounted; } + sub get_mounted { eval $start if $b_log; my (@arrays); @@ -25811,6 +26421,7 @@ sub get_mounted { 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; @@ -25849,6 +26460,7 @@ sub unmounted_filesystem { ## UsbItem { package UsbItem; + sub get { eval $start if $b_log; my ($key1,$val1); @@ -25873,10 +26485,10 @@ sub get { $key1 = $alerts{'usbconfig'}->{'action'}; $val1 = $alerts{'usbconfig'}->{'message'}; } -# elsif ($alerts{'lsusb'}->{'action'} eq 'missing'){ -# $key1 = $alerts{'lsusb'}->{'action'}; -# $val1 = $alerts{'lsusb'}->{'message'}; -# } + # elsif ($alerts{'lsusb'}->{'action'} eq 'missing'){ + # $key1 = $alerts{'lsusb'}->{'action'}; + # $val1 = $alerts{'lsusb'}->{'message'}; + # } } $key1 = ucfirst($key1); @$rows = ({main::key($num++,0,1,$key1) => $val1}); @@ -25893,26 +26505,27 @@ sub get { eval $end if $b_log; return $rows; } + sub usb_output { eval $start if $b_log; return if !$usb{'main'}; my $rows = $_[0]; - my ($b_hub,$bus_id,$chip_id,$driver,$ind_sc,$path_id,$ports,$product,$serial, - $speed,$type); + my ($b_hub,$bus_id,$chip_id,$driver,$ind_rc,$ind_sc,$path_id,$ports,$product, + $rev,$serial,$speed_si,$type); my $num = 0; my $j = 0; # 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{'main'}}){ $j = scalar @$rows; - ($b_hub,$ind_sc,$num) = (0,3,1); - ($driver,$path_id,$ports,$product, - $serial,$speed,$type) = ('','','','','','',''); - $speed = (main::is_numeric($id->[8])) ? sprintf("%1.1f",$id->[8]) : $id->[8] if $id->[8]; + ($b_hub,$ind_rc,$ind_sc,$num) = (0,4,3,1); + ($driver,$path_id,$ports,$product,$rev,$serial,$speed_si, + $type) = ('','','','','','','','',''); + $rev = $id->[8] if $id->[8]; $product = main::clean($id->[13]) if $id->[13]; $serial = main::filter($id->[16]) if $id->[16]; $product ||= 'N/A'; - $speed ||= 'N/A'; + $rev ||= 'N/A'; $path_id = $id->[2] if $id->[2]; $bus_id = "$path_id:$id->[1]"; # it's a hub @@ -25924,9 +26537,9 @@ sub usb_output { main::key($num++,1,1,'Hub') => $bus_id, main::key($num++,0,2,'info') => $product, main::key($num++,0,2,'ports') => $ports, - main::key($num++,0,2,'rev') => $speed, },); $b_hub = 1; + $ind_rc =3; $ind_sc =2; } # it's a device @@ -25945,30 +26558,43 @@ sub usb_output { if ($extra > 2 && $id->[9]){ $rows->[$j]{main::key($num++,0,3,'interfaces')} = $id->[9]; } - $rows->[$j]{main::key($num++,0,3,'rev')} = $speed; } # for either hub or device - if ($extra > 1 && main::is_numeric($id->[17])){ - my $speed = $id->[17]; - if ($speed >= 1000){$speed = ($id->[17]/1000) . " Gb/s"} - else {$speed = $id->[17] . " Mb/s"} - $rows->[$j]{main::key($num++,0,$ind_sc,'speed')} = $speed; - } - if ($extra > 2 && $id->[19] && $id->[19] ne '0mA'){ - $rows->[$j]{main::key($num++,0,$ind_sc,'power')} = $id->[19]; - } - if ($extra > 1){ + $rows->[$j]{main::key($num++,1,$ind_sc,'rev')} = $rev; + if ($extra > 0){ + $speed_si = ($id->[17]) ? $id->[17] : 'N/A'; + $speed_si .= " ($id->[25])" if ($b_admin && $id->[25]); + $rows->[$j]{main::key($num++,0,$ind_rc,'speed')} = $speed_si; + if ($extra > 1){ + if ($id->[24]){ + if ($id->[23] == $id->[24]){ + $rows->[$j]{main::key($num++,0,$ind_rc,'lanes')} = $id->[24]; + } + else { + $rows->[$j]{main::key($num++,1,$ind_rc,'lanes')} = ''; + $rows->[$j]{main::key($num++,0,($ind_rc+1),'rx')} = $id->[23]; + $rows->[$j]{main::key($num++,0,($ind_rc+1),'tx')} = $id->[24]; + } + } + } + # 22 is only available if 23 and 24 are present as well + if ($b_admin && $id->[22]){ + $rows->[$j]{main::key($num++,0,$ind_rc,'mode')} = $id->[22]; + } + if ($extra > 2 && $id->[19] && $id->[19] ne '0mA'){ + $rows->[$j]{main::key($num++,0,$ind_sc,'power')} = $id->[19]; + } $chip_id = $id->[7]; $chip_id ||= 'N/A'; $rows->[$j]{main::key($num++,0,$ind_sc,'chip-ID')} = $chip_id; - } - if ($extra > 2 && defined $id->[5] && $id->[5] ne ''){ - my $id = sprintf("%02s",$id->[4]) . sprintf("%02s", $id->[5]); - $rows->[$j]{main::key($num++,0,$ind_sc,'class-ID')} = $id; - } - if (!$b_hub && $extra > 2){ - if ($serial){ - $rows->[$j]{main::key($num++,0,$ind_sc,'serial')} = main::filter($serial); + if ($extra > 2 && defined $id->[5] && $id->[5] ne ''){ + my $id = sprintf("%02s",$id->[4]) . sprintf("%02s", $id->[5]); + $rows->[$j]{main::key($num++,0,$ind_sc,'class-ID')} = $id; + } + if (!$b_hub && $extra > 2){ + if ($serial){ + $rows->[$j]{main::key($num++,0,$ind_sc,'serial')} = main::filter($serial); + } } } } @@ -25981,6 +26607,7 @@ sub usb_output { # add metric / imperial (us) switch { package WeatherItem; + sub get { eval $start if $b_log; my $rows = []; @@ -26017,6 +26644,7 @@ sub get { eval $end if $b_log; return $rows; } + sub weather_output { eval $start if $b_log; my ($rows,$location,$weather) = @_; @@ -26146,6 +26774,7 @@ sub weather_output { } eval $end if $b_log; } + sub process_elevation { eval $start if $b_log; my ($meters,$feet) = @_; @@ -26171,6 +26800,7 @@ sub process_elevation { eval $end if $b_log; return $result; } + sub process_unit { eval $start if $b_log; my ($primary,$metric,$m_unit,$imperial,$i_unit) = @_; @@ -26196,6 +26826,7 @@ sub process_unit { eval $end if $b_log; return $result; } + sub process_wind { eval $start if $b_log; my ($primary,$direction,$mph,$ms,$gust_mph,$gust_ms) = @_; @@ -26255,6 +26886,7 @@ sub process_wind { eval $end if $b_log; return $result; } + sub get_weather { eval $start if $b_log; my ($location) = @_; @@ -26409,9 +27041,9 @@ sub get_weather { $working[1] =~ /^([0-9\.]+)\sF\s\(([0-9\.]+)\sC\)/; $weather->{'temp-c'} = $2;; $weather->{'temp-f'} = $1; -# $weather->{'temp'} =~ s/\sF/\xB0 F/; # B0 -# $weather->{'temp'} =~ s/\sF/\x{2109}/; -# $weather->{'temp'} =~ s/\sC/\x{2103}/; + # $weather->{'temp'} =~ s/\sF/\xB0 F/; # B0 + # $weather->{'temp'} =~ s/\sF/\x{2109}/; + # $weather->{'temp'} =~ s/\sC/\x{2103}/; } elsif ($working[0] eq 'temp_f'){ $weather->{'temp-f'} = $working[1]; @@ -26505,6 +27137,7 @@ sub get_weather { eval $end if $b_log; return $weather; } + sub download_weather { eval $start if $b_log; my ($now,$file_cached,$location) = @_; @@ -26530,7 +27163,8 @@ sub download_weather { eval $end if $b_log; return $weather; } -# resolve wide character issue, if detected, switch to iso + +# Rsolve wide character issue, if detected, switch to iso # date format, we won't try to be too clever here. sub test_locale_date { my ($date_time,$location,$epoch) = @_; @@ -26576,6 +27210,7 @@ sub location_data { } eval $end if $b_log; } + sub get_location { eval $start if $b_log; my $location = $_[0]; @@ -26665,6 +27300,7 @@ sub get_location { # print ($loc_arg,"\n", join("\n", @loc_data), "\n",scalar @loc_data, "\n"); eval $end if $b_log; } + sub complete_location { eval $start if $b_log; my ($location,$city,$state,$country) = @_; @@ -26735,6 +27371,7 @@ sub set_build_prop { ## CompilerVersion { package CompilerVersion; + sub get { eval $start if $b_log; my $compiler = []; @@ -26779,6 +27416,7 @@ sub version_bsd { main::log_data('dump','@$compiler',$compiler) if $b_log; eval $end if $b_log; } + sub version_proc { eval $start if $b_log; my ($compiler,$file) = @_; @@ -26995,18 +27633,19 @@ sub set_dboot_data { ## DesktopEnvironment # returns array: -# 0 - desktop name -# 1 - version -# 2 - toolkit -# 3 - toolkit version -# 4 - info extra desktop data -# 5 - wm -# 6 - wm version +# 0: desktop name +# 1: version +# 2: toolkit +# 3: toolkit version +# 4: info extra desktop data +# 5: wm +# 6: wm version { package DesktopEnvironment; my ($b_gtk,$b_qt,$b_xprop,$desktop_session,$gdmsession,$kde_session_version, $xdg_desktop,@data,@xprop); my $desktop = []; + sub get { eval $start if $b_log; set_desktop_values(); @@ -27018,8 +27657,11 @@ sub get { if (!@$desktop){ get_env_xprop_gnome_based_data(); } - if (!@$desktop && $b_xprop){ - get_env_xprop_non_gnome_based_data(); + if (!@$desktop){ + get_env_xfce_data(); + } + if (!@$desktop){ + get_env_xprop_misc_data(); } if (!@$desktop){ get_ps_de_data(); @@ -27037,6 +27679,7 @@ sub get { eval $end if $b_log; return $desktop; } + sub set_desktop_values { # NOTE $XDG_CURRENT_DESKTOP envvar is not reliable, but it shows certain desktops better. # most desktops are not using it as of 2014-01-13 (KDE, UNITY, LXDE. Not Gnome) @@ -27046,14 +27689,16 @@ sub set_desktop_values { # for fallback to fallback protections re false gnome id $gdmsession = ($ENV{'GDMSESSION'}) ? prep_desktop_value($ENV{'GDMSESSION'}) : ''; } -# note: an ubuntu regresssion replaces or adds 'ubuntu' string to + +# Note: an ubuntu regresssion replaces or adds 'ubuntu' string to # real value. Since ubuntu is the only distro I know that does this, # will add more distro type filters as/if we come across them sub prep_desktop_value { $_[0] = lc(main::trimmer($_[0])); - $_[0] =~ s/\b(arch|debian|fedora|manjaro|mint|opensuse|ubuntu):?\s*//; + $_[0] =~ s/\b(arch|debian|fedora|manjaro|mint|opensuse|ubuntu):?\s*//i; return $_[0]; } + sub get_kde_trinity_data { eval $start if $b_log; my ($kded,$kded_name,$program,@version_data,@version_data2); @@ -27155,6 +27800,7 @@ sub get_kde_trinity_data { } eval $end if $b_log; } + sub get_env_de_data { eval $start if $b_log; my ($program,@version_data); @@ -27197,6 +27843,7 @@ sub get_env_de_data { } eval $end if $b_log; } + sub get_env_xprop_gnome_based_data { eval $start if $b_log; my ($program,$value,@version_data); @@ -27209,15 +27856,15 @@ sub get_env_xprop_gnome_based_data { # before gnome test eventually this needs to be better organized so all the # xprop tests are in the same section, but this is good enough for now. # NOTE: was checking for 'muffin' but that's not part of cinnamon - if ($xdg_desktop eq 'cinnamon' || $gdmsession eq 'cinnamon' || - (main::check_program('muffin') || main::check_program('cinnamon-session')) && - ($b_xprop && main::awk(\@xprop,'_muffin'))){ + if ($xdg_desktop eq 'cinnamon' || $gdmsession eq 'cinnamon' || ($b_xprop && + (main::check_program('muffin') || main::check_program('cinnamon-session')) && + main::awk(\@xprop,'_muffin'))){ ($desktop->[0],$desktop->[1]) = main::program_data('cinnamon','cinnamon',0); $b_gtk = 1; $desktop->[0] ||= 'Cinnamon'; } elsif ($xdg_desktop eq 'mate' || $gdmsession eq 'mate' || - ($b_xprop && main::awk(\@xprop,'_marco'))){ + ($b_xprop && main::awk(\@xprop,'_marco'))){ # NOTE: mate-about and mate-sesssion vary which has the higher number, neither # consistently corresponds to the actual MATE version, so check both. my %versions = ('mate-about' => '','mate-session' => ''); @@ -27246,7 +27893,8 @@ sub get_env_xprop_gnome_based_data { } eval $end if $b_log; } -# note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out + +# Note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out # https://bugzilla.gnome.org/show_bug.cgi?id=542880. # NOTE: manjaro is leaving XDG data null, which forces the manual check for gnome, sigh... # some gnome programs can trigger a false xprop gnome ID @@ -27282,7 +27930,8 @@ sub check_gnome { $b_gnome = 1; } # maybe use ^_gnome_session instead? try it for a while - elsif ($b_xprop && main::check_program('gnome-shell') && main::awk(\@xprop,'^_gnome_session')){ + elsif ($b_xprop && main::check_program('gnome-shell') && + main::awk(\@xprop,'^_gnome_session')){ $detection = 'xprop-root'; $b_gnome = 1; } @@ -27290,27 +27939,21 @@ sub check_gnome { eval $end if $b_log; return $b_gnome; } -sub get_env_xprop_non_gnome_based_data { + +# Not strictly dependent on xprop data, which is not necessarily always present +sub get_env_xfce_data { eval $start if $b_log; - my ($program,@version_data,$version); + my (@version_data); # 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 - # issues so don't test for that. $xdg_desktop eq 'xfce' + # note: some distros/wm (e.g. bunsen) set $xdg_desktop to xfce to solve some + # other issues so but are OpenBox. Not inxi issue. + # $xdg_desktop can be /usr/bin/startxfce4 + # print "xdg_d: $xdg_desktop gdms: $gdmsession\n"; if ($xdg_desktop eq 'xfce' || $gdmsession eq 'xfce' || - (main::check_program('xfdesktop')) && main::awk(\@xprop,'^(xfdesktop|xfce)')){ - # this is a very expensive test that doesn't usually result in a find - # talk to xfce to see what id they will be using for xfce 5 -# if (main::awk(\@xprop, 'xfce4')){ -# $version = '4'; -# } - if (main::awk(\@xprop, 'xfce5')){ - $version = '5'; - } - else { - $version = '4'; - } + ($b_xprop && main::check_program('xfdesktop')) && + main::awk(\@xprop,'^(xfdesktop|xfce)')){ @data = main::program_values('xfdesktop'); $desktop->[0] = $data[3]; # xfdesktop --version out of x fails to get display, so no data @@ -27319,6 +27962,18 @@ sub get_env_xprop_non_gnome_based_data { $desktop->[1] = main::awk(\@version_data,$data[0],$data[1],'\s+'); #$desktop->[1] = main::program_version('xfdesktop',$data[0],$data[1],$data[2],$data[5],$data[6]); if (!$desktop->[1]){ + my $version = '4'; # just assume it's 4, we tried + if (main::check_program('xfce4-panel')){ + $version = '4'; + } + # talk to xfce to see what id they will be using for xfce 5 + elsif (main::check_program('xfce5-panel')){ + $version = '5'; + } + # they might get rid of number, we'll see + elsif (main::check_program('xfce-panel')){ + $version = ''; + } @data = main::program_values("xfce${version}-panel"); # print Data::Dumper::Dumper \@data; # this returns an error message to stdout in x, which breaks the version @@ -27336,26 +27991,40 @@ sub get_env_xprop_non_gnome_based_data { $desktop->[2] = $data[3]; } } - elsif ($xdg_desktop eq 'moksha' || $gdmsession eq 'moksha' || - (main::check_program('enlightenment') || main::check_program('moksha')) && main::awk(\@xprop,'moksha')){ + eval $end if $b_log; +} + +# These require data from xprop, at least partially +sub get_env_xprop_misc_data { + eval $start if $b_log; + # print join("\n", @xprop), "\n"; + if ($xdg_desktop eq 'moksha' || $gdmsession eq 'moksha' || ($b_xprop && + (main::check_program('enlightenment') || main::check_program('moksha')) && + main::awk(\@xprop,'moksha'))){ # no -v or --version but version is in xprop -root # ENLIGHTENMENT_VERSION(STRING) = "Moksha 0.2.0.15989" $desktop->[0] = 'Moksha'; - $desktop->[1] = main::awk(\@xprop,'(enlightenment|moksha)_version',2,'\s+=\s+'); - $desktop->[1] =~ s/"?(Moksha|Enlightenment)\s([^"]+)"?/$2/i if $desktop->[1]; + if ($b_xprop){ + $desktop->[1] = main::awk(\@xprop,'(enlightenment|moksha)_version',2,'\s+=\s+'); + $desktop->[1] =~ s/"?(Moksha|Enlightenment)\s([^"]+)"?/$2/i if $desktop->[1]; + } } elsif ($xdg_desktop eq 'enlightenment' || $gdmsession eq 'enlightenment' || - (main::check_program('enlightenment') && main::awk(\@xprop,'enlightenment'))){ + ($b_xprop && main::check_program('enlightenment') && + main::awk(\@xprop,'enlightenment'))){ # no -v or --version but version is in xprop -root # ENLIGHTENMENT_VERSION(STRING) = "Enlightenment 0.16.999.49898" $desktop->[0] = 'Enlightenment'; - $desktop->[1] = main::awk(\@xprop,'(enlightenment|moksha)_version',2,'\s+=\s+'); - $desktop->[1] =~ s/"?(Moksha|Enlightenment)\s([^"]+)"?/$2/i if $desktop->[1]; + if ($b_xprop){ + $desktop->[1] = main::awk(\@xprop,'(enlightenment|moksha)_version',2,'\s+=\s+'); + $desktop->[1] =~ s/"?(Moksha|Enlightenment)\s([^"]+)"?/$2/i if $desktop->[1]; + } } # the sequence here matters, some desktops like icewm, razor, let you set different # wm, so we want to get the main controlling desktop first, then fall back to the wm # detections. get_ps_de_data() and get_wm() will handle alternate wm detections. - if (!$desktop->[0]){ + # I believe all these will be X only wm, so xprop tests fine here. + if ($b_xprop && !$desktop->[0]){ # 0 check program; 1 xprop search; 2: data; 3 - optional: ps_gui search my @desktops =( ['icewm','icewm','icewm'], @@ -27382,6 +28051,7 @@ sub get_env_xprop_non_gnome_based_data { # need to check starts line because it's so short eval $end if $b_log; } + sub get_ps_de_data { eval $start if $b_log; my ($program,@version_data); @@ -27444,6 +28114,7 @@ sub get_ps_de_data { } eval $end if $b_log; } + # NOTE: used to use a super slow method here, but gtk-launch returns # the gtk version I believe sub set_gtk_data { @@ -27453,6 +28124,7 @@ sub set_gtk_data { } eval $end if $b_log; } + sub set_qt_data { eval $start if $b_log; my ($program,@data,@version_data); @@ -27497,6 +28169,7 @@ sub get_wm { } eval $end if $b_log; } + sub get_wm_main { eval $start if $b_log; my ($wms,$working); @@ -27538,6 +28211,7 @@ sub get_wm_main { $desktop->[5] = $working if !$desktop->[5] && $working; eval $end if $b_log; } + sub get_wm_wmctrl { eval $start if $b_log; my ($program) = @_; @@ -27560,6 +28234,7 @@ sub get_wm_wmctrl { } eval $end if $b_log; } + sub get_wm_version { eval $start if $b_log; my ($type,$wm) = @_; @@ -27632,28 +28307,27 @@ sub set_xprop { # print "@xprop\n"; eval $end if $b_log; } - } ## DeviceData # 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 +# 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,%lspci_n); @@ -27808,7 +28482,8 @@ sub lspci_data { main::log_data('dump','lspci @devices',\@devices) if $b_log; eval $end if $b_log; } -# arg: $1 - busID + +# args: 0: busID # returns if valid busID: (classID,vendorID,productID,revNu) # almost never used, only in case of lspci -nnv line truncation bug sub lspci_n_data { @@ -27954,6 +28629,7 @@ sub pcidump_data { 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]; @@ -27968,6 +28644,7 @@ sub pcidump_driver { eval $end if $b_log; return ($driver,$nu); } + sub pcictl_data { eval $start if $b_log; my $data = pci_grabber('pcictl'); @@ -28081,6 +28758,7 @@ sub soc_data { 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"] @@ -28195,6 +28873,7 @@ sub soc_devices { } 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/ @@ -28232,6 +28911,7 @@ sub soc_devicetree { } eval $end if $b_log; } + sub set_bluetooth { # special case of pi bt on ttyAMA0 $b_bt_check = 1; @@ -28240,6 +28920,7 @@ sub set_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])){ @@ -28271,7 +28952,8 @@ sub assign_data { # $device_vm = check_vm($data[4]) if ((!$risc{'ppc'} && !$risc{'mips'}) && !$device_vm); push(@devices,[@$data]); } -# note: for soc, these have been converted in soc_type() + +# 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)){ @@ -28279,6 +28961,7 @@ sub check_audio { } else {return 0} } + sub check_bluetooth { if (($_[1] && length($_[1]) == 4 && $_[1] eq '0d11') || ($_[0] && $_[0] =~ /^(bluetooth)$/i)){ @@ -28286,6 +28969,7 @@ sub check_bluetooth { } else {return 0} } + sub check_graphics { # note: multimedia class 04 is video if 0400. 'tv' is risky I think if (($_[1] && length($_[1]) == 4 && ($_[1] =~ /^03/ || $_[1] eq '0400' || @@ -28295,9 +28979,11 @@ sub check_graphics { } 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 @@ -28308,9 +28994,11 @@ sub check_network { } 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 @@ -28359,6 +29047,7 @@ sub soc_type { } return $type; } + sub pci_class { eval $start if $b_log; my ($id) = @_; @@ -28419,7 +29108,8 @@ sub get_device_temp { # disklabel: partID, block-size, fs, size { package DiskDataBSD; -# sets initial pure dboot data, and fills it in with + +# Sets initial pure dboot data, and fills it in with # disklabel/gpart partition and advanced data sub set { eval $start if $b_log; @@ -28435,6 +29125,7 @@ sub set { } eval $end if $b_log; } + sub get { eval $start if $b_log; my $id = $_[0]; @@ -28461,6 +29152,7 @@ sub get { eval $end if $b_log; return $data; } + sub set_dboot_disks { eval $start if $b_log; my ($working,@temp); @@ -28535,6 +29227,7 @@ sub set_dboot_disks { 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]; @@ -28551,6 +29244,7 @@ sub bioctl_data { eval $end if $b_log; return $serial; } + sub set_disklabel_data { eval $start if $b_log; my ($cmd,@data,@working); @@ -28625,6 +29319,7 @@ sub set_disklabel_data { 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]; @@ -28643,6 +29338,7 @@ sub fdisk_data { 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; @@ -28820,6 +29516,7 @@ package DistroData; my (@distro_files,@osr,@working); my ($distro,$distro_file,$distro_id,$system_base) = ('','','',''); my ($etc_issue,$lc_issue,$os_release) = ('','','/etc/os-release'); + sub get { eval $start if $b_log; if ($bsd_type){ @@ -28877,9 +29574,9 @@ sub get_linux_distro { # order matters! my @derived = qw(antix-version aptosid-version bodhibuilder.conf kanotix-version knoppix-version pclinuxos-release mandrake-release manjaro-release mx-version - pardus-release porteus-version q4os_version sabayon-release siduction-version - sidux-version slax-version slint-version slitaz-release solusos-release - turbolinux-release zenwalk-version); + pardus-release porteus-version q4os_version sabayon-release + siduction-version sidux-version slax-version slint-version slitaz-release + solusos-release turbolinux-release zenwalk-version); my $derived_s = join('|', @derived); my @primary = qw(altlinux-release arch-release gentoo-release redhat-release slackware-version SuSE-release); @@ -28890,25 +29587,25 @@ sub get_linux_distro { $lsb_good_s .= 'manjaro-release'; my $os_release_good_s = 'altlinux-release|arch-release|mageia-release|'; $os_release_good_s .= 'pclinuxos-release|rpi-issue|SuSE-release'; - # we need these empirically verified one by one as they appear, but always remember + # We need these empirically verified one by one as they appear, but always remember # that stuff changes, legacy, deprecated, but these ideally are going to be right - my $osr_good = 'manjaro|antergos|chakra|guix|mageia|pclinuxos|raspberry pi os|'; - $osr_good .= 'slint|zorin'; - # force use of pretty name because that's only location of derived distro name + my $osr_good = 'manjaro|antergos|chakra|guix|mageia|pclinuxos|porteux|'; + $osr_good .= 'raspberry pi os|slint|zorin'; + # Force use of pretty name because that's only location of derived distro name my $osr_pretty = 'zinc'; my ($b_issue,$b_lsb,$b_osr_pretty,$b_skip_issue,$b_skip_osr); my ($issue,$lsb_release) = ('/etc/issue','/etc/lsb-release'); $b_issue = 1 if -f $issue; $b_lsb = 1 if -f $lsb_release; - # note: OpenSuse Tumbleweed 2018-05 has made /etc/issue created by sym link to /run/issue + # Note: OpenSuse Tumbleweed 2018-05 has made /etc/issue created by sym link to /run/issue # and then made that resulting file 700 permissions, which is obviously a mistake $etc_issue = main::reader($issue,'strip',0) if -r $issue; # debian issue can end with weird escapes like \n \l # antergos: Antergos Linux \r (\l) $etc_issue = main::clean_characters($etc_issue) if $etc_issue; - # note: always exceptions, so wild card after release/version: + # Note: always exceptions, so wild card after release/version: # /etc/lsb-release-crunchbang - # wait to handle since crunchbang file is one of the few in the world that + # Wait to handle since crunchbang file is one of the few in the world that # uses this method @distro_files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); push(@distro_files, '/etc/bodhibuilder.conf') if -r '/etc/bodhibuilder.conf'; @@ -28919,12 +29616,12 @@ sub get_linux_distro { $distro_id = $1; $b_skip_issue = 1; } - # this raspbian detection fails for raspberry pi os + # This raspbian detection fails for raspberry pi os elsif ($lc_issue =~ /(raspbian|peppermint)/){ $distro_id = $1; $distro_file = $os_release if @osr; } - # note: wrong fix, applies to both raspbian and raspberry pi os + # Note: wrong fix, applies to both raspbian and raspberry pi os # assumption here is that r pi os fixes this before stable release elsif ($lc_issue =~ /^debian/ && -e '/etc/apt/sources.list.d/raspi.list' && (grep {/[^#]+raspberrypi\.org/} main::reader('/etc/apt/sources.list.d/raspi.list'))){ @@ -28952,7 +29649,7 @@ sub get_linux_distro { $distro_file = $distro_files[0]; } elsif (scalar @distro_files > 1){ - # special case, to force manjaro/antergos which also have arch-release + # Special case, to force manjaro/antergos which also have arch-release # manjaro should use lsb, which has the full info, arch uses os release # antergos should use /etc/issue. We've already checked os-release above if ($distro_id eq 'antergos' || (grep {/antergos|chakra|manjaro/} @distro_files)){ @@ -28989,26 +29686,27 @@ sub get_linux_distro { $distro = main::awk(\@working,'antix.*\.iso') if @working; $distro = main::clean_characters($distro) if $distro; } - # this handles case where only one release/version file was found, and it's lsb-release. + # This handles case where only one release/version file was found, and it's lsb-release. # This would never apply for ubuntu or debian, which will filter down to the following # conditions. In general if there's a specific distro release file available, that's to # be preferred, but this is a good backup. - elsif ($distro_file && $b_lsb && ($distro_file =~ /\/etc\/($lsb_good_s)$/ || $distro_file eq $lsb_release)){ + elsif ($distro_file && $b_lsb && + ($distro_file =~ /\/etc\/($lsb_good_s)$/ || $distro_file eq $lsb_release)){ $distro = get_lsb_release(); } elsif ($distro_file && $distro_file eq $os_release){ $distro = get_os_release($b_osr_pretty); $b_skip_osr = 1; } - # if distro id file was found and it's not in the exluded primary distro file list, read it + # If distro id file was found and it's not in the exluded primary distro file list, read it elsif ($distro_file && -s $distro_file && $distro_file !~ /\/etc\/($exclude_s)$/){ - # new opensuse uses os-release, but older ones may have a similar syntax, so just use + # New opensuse uses os-release, but older ones may have a similar syntax, so just use # the first line if ($distro_file eq '/etc/SuSE-release'){ - # leaving off extra data since all new suse have it, in os-release, this file has + # Leaving off extra data since all new suse have it, in os-release, this file has # line breaks, like os-release but in case we want it, it's: # CODENAME = Mantis | VERSION = 12.2 - # for now, just take first occurrence, which should be the first line, which does + # For now, just take first occurrence, which should be the first line, which does # not use a variable type format @working = main::reader($distro_file); $distro = main::awk(\@working,'suse'); @@ -29027,7 +29725,7 @@ sub get_linux_distro { } $distro = main::clean_characters($distro) if $distro; } - # otherwise try the default debian/ubuntu/distro /etc/issue file + # Otherwise try the default debian/ubuntu/distro /etc/issue file elsif ($b_issue){ if (!$distro_id && $lc_issue && $lc_issue =~ /(mint|lmde)/){ $distro_id = $1; @@ -29045,14 +29743,14 @@ sub get_linux_distro { elsif ($etc_issue){ if (-d '/etc/guix' && $lc_issue =~ /^this is the gnu system\./){ $distro = 'Guix'; - # they didn't use any standard paths or files for os data, sigh, use pm version + # They didn't use any standard paths or files for os data, sigh, use pm version my $version = main::program_version('guix', '^guix', '4','--version',1); $distro .= " $version" if $version; $b_skip_issue = 1; } else { $distro = $etc_issue; - # this handles an arch bug where /etc/arch-release is empty and /etc/issue + # This handles an arch bug where /etc/arch-release is empty and /etc/issue # is corrupted only older arch installs that have not been updated should # have this fallback required, new ones use os-release if ($distro =~ /arch linux/i){ @@ -29061,7 +29759,7 @@ sub get_linux_distro { } } } - # a final check. If a long value, before assigning the debugger output, if os-release + # A final check. If a long value, before assigning the debugger output, if os-release # exists then let's use that if it wasn't tried already. Maybe that will be better. # not handling the corrupt data, maybe later if needed. 10 + distro: (8) + string if ($distro && length($distro) > 60){ @@ -29070,7 +29768,7 @@ sub get_linux_distro { $b_skip_osr = 1; } } - # test for /etc/lsb-release as a backup in case of failure, in cases + # Test for /etc/lsb-release as a backup in case of failure, in cases # where > one version/release file were found but the above resulted # in null distro value. if (!$distro && $windows{'cygwin'}){ @@ -29086,9 +29784,9 @@ sub get_linux_distro { $distro = get_lsb_release(); } } - # now some final null tries + # Now some final null tries if (!$distro){ - # if the file was null but present, which can happen in some cases, then use + # If the file was null but present, which can happen in some cases, then use # the file name itself to set the distro value. Why say unknown if we have # a pretty good idea, after all? if ($distro_file){ @@ -29097,14 +29795,14 @@ sub get_linux_distro { } } system_base() if $extra > 0; - # some last customized changes, double check if possible to verify still valid + # Some last customized changes, double check if possible to verify still valid if ($distro){ if ($distro_id eq 'armbian'){ $distro =~ s/Debian/Armbian/; } elsif ($distro_id eq 'raspios'){ $system_base = $distro; - # no need to repeat the debian version info if base: + # No need to repeat the debian version info if base: if ($extra == 0){$distro =~ s/Debian\s*GNU\/Linux/Raspberry Pi OS/;} else {$distro = 'Raspberry Pi OS';} } @@ -29116,7 +29814,7 @@ sub get_linux_distro { # android fallback, sometimes requires root, sometimes doesn't android_info() if $b_android; } - ## finally, if all else has failed, give up + ## Finally, if all else has failed, give up $distro ||= 'unknown'; eval $end if $b_log; } @@ -29160,14 +29858,16 @@ sub system_base_bsd { sub system_base { eval $start if $b_log; - # Need data on these Arch derived: CachyOS - my $base_distro_arch = 'anarchy|antergos|arch(bang|craft|labs|man|strike)|arco|artix'; + # Need data on these Arch derived: CachyOS; can be ArchLab/Labs + my $base_distro_arch = 'anarchy|antergos|apricity'; + $base_distro_arch .= '|arch(bang|craft|ex|lab|man|strike)|arco|artix'; + $base_distro_arch .= '|blackarch|bluestar|bridge|cachyos|chakra|condres|ctlos'; # note: arch linux derived distro page claims kaos as arch derived but it is NOT - $base_distro_arch .= '|blackarch|bluestar|cachyos|chakra|ctios'; - $base_distro_arch .= '|endeavour|garuda|hyperbola|linhes'; - $base_distro_arch .= '|mabox|manjaro|mysys2|netrunner\s?rolling|ninja|obarun'; - $base_distro_arch .= '|parabola|puppyrus-?a|reborn|snal|steamos|talkingarch'; - $base_distro_arch .= '|ubos|xero'; + $base_distro_arch .= '|endeavour|feliz|garuda|hyperbola|linhes|liri'; + $base_distro_arch .= '|mabox|magpie|manjaro|mysys2|namib|netrunner\s?rolling|ninja'; + $base_distro_arch .= '|obarun|parabola|porteus|puppyrus-?a'; + $base_distro_arch .= '|reborn|revenge|salient|snal|steamos'; + $base_distro_arch .= '|talkingarch|theshell|ubos|velt|xero'; my $base_file_debian_version = 'sidux'; # detect debian steamos before arch steamos my $base_osr_debian_version = '\belive|lmde|neptune|parrot|pureos|rescatux|'; @@ -29179,7 +29879,7 @@ sub system_base { # synthesize, no direct data available my $base_manual = 'blankon|deepin|kali'; # osr base, distro id in list of distro files - my $base_osr = 'aptosid|bodhi|grml|q4os|siduction|slax'; + my $base_osr = 'aptosid|bodhi|grml|q4os|siduction|slax|zenwalk'; # osr base, distro id in issue my $base_osr_issue = 'grml|linux lite|openmediavault'; # osr has distro name but has fedora centos redhat ID_LIKE and VERSION_ID same @@ -29188,11 +29888,11 @@ sub system_base { my $base_osr_ubuntu = 'feren|mint|neon|nitrux|pop!?_os|tuxedo|zinc|zorin'; my $base_upstream_lsb = '/etc/upstream-release/lsb-release'; my $base_upstream_osr = '/etc/upstream-release/os-release'; - # these id as themselves, but system base is version file + # These id as themselves, but system base is version file. Slackware mostly. my %base_version = ( - 'salix|slint' => '/etc/slackware-version', + 'porteux|salix|slint' => '/etc/slackware-version', ); - # first: try, some distros have upstream-release, elementary, new mint + # First: try, some distros have upstream-release, elementary, new mint # and anyone else who uses this method for fallback ID if (-r $base_upstream_osr){ my @osr_working = main::reader($base_upstream_osr); @@ -29285,9 +29985,9 @@ sub get_lsb_release { $id = 'Manjaro Linux'; } # in the old days, arch used lsb_release -# elsif ($working[1] =~ /^Arch$/i){ -# $id = 'Arch Linux'; -# } + # elsif ($working[1] =~ /^Arch$/i){ + # $id = 'Arch Linux'; + # } else { $id = $working[1]; } @@ -29321,6 +30021,7 @@ sub get_lsb_release { eval $end if $b_log; return $distro_lsb; } + sub get_os_release { eval $start if $b_log; my ($b_osr_pretty,$base_type) = @_; @@ -29439,12 +30140,15 @@ sub get_os_release { eval $end if $b_log; return $distro_osr; } -# arg: 1 - optional: debian codename + +# args: 0: optional: debian codename sub debian_id { eval $start if $b_log; my ($codename) = @_; my ($debian_version,$id); - $debian_version = main::reader('/etc/debian_version','strip',0) if -r '/etc/debian_version'; + if (-r '/etc/debian_version'){ + $debian_version = main::reader('/etc/debian_version','strip',0); + } $id = 'Debian'; return if !$debian_version && !$codename; # note, 3.0, woody, 3.1, sarge, but after it's integer per version @@ -29476,7 +30180,7 @@ sub debian_id { return $id; } -# note, these are only for matching distro/mint derived names. +# Note, these are only for matching distro/mint derived names. # Update list as new names become available. While first Mint was 2006-08, # this method depends on /etc/os-release which was introduced 2012-02. # Mint is using UBUNTU_CODENAME without ID data. @@ -29487,17 +30191,31 @@ sub ubuntu_id { my ($id) = (''); # xx.04, xx.10 my %codenames = ( - 'jammy' => '22.04 LTS','kinetic' => '22.10', - 'hirsute' => '21.04','impish' => '21.10', - 'focal' => '20.04 LTS','groovy' => '20.10', - 'disco' => '19.04','eoan' => '19.10', - 'bionic' => '18.04 LTS','cosmic' => '18.10', - 'zesty' => '17.04','artful' => '17.10', - 'xenial' => '16.04 LTS','yakkety' => '16.10', - 'vivid' => '15.04','wily' => '15.10', - 'trusty' => '14.04 LTS ','utopic' => '14.10', - 'raring' => '13.04','saucy' => '13.10', - 'precise' => '12.04 LTS ','quantal' => '12.10', + # '??' => '24.04 LTS', + # '??' => '23.10', + 'lunar' => '23.04', + 'kinetic' => '22.10', + 'jammy' => '22.04 LTS', + 'impish' => '21.10', + 'hirsute' => '21.04', + 'groovy' => '20.10', + 'focal' => '20.04 LTS', + 'eoan' => '19.10', + 'disco' => '19.04', + 'cosmic' => '18.10', + 'bionic' => '18.04 LTS', + 'artful' => '17.10', + 'zesty' => '17.04', + 'yakkety' => '16.10', + 'xenial' => '16.04 LTS', + 'wily' => '15.10', + 'vivid' => '15.04', + 'utopic' => '14.10', + 'trusty' => '14.04 LTS ', + 'saucy' => '13.10', + 'raring' => '13.04', + 'quantal' => '12.10', + 'precise' => '12.04 LTS ', # 'natty' => '11.04','oneiric' => '11.10', # 'lucid' => '10.04','maverick' => '10.10', # 'jaunty' => '9.04','karmic' => '9.10', @@ -29516,7 +30234,8 @@ sub ubuntu_id { ## DmidecodeData { package DmidecodeData; -# note, all actual tests have already been run in check_tools so if we + +# 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; @@ -29619,7 +30338,7 @@ sub get_driver_modules { return $modules; } -# 1: driver; 2: modules, comma separated, return only modules +# args: 0: driver; 1: 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. sub get_gcc_data { @@ -29654,9 +30373,10 @@ sub get_gcc_data { } ## GlabelData - set/get -# used only to get RAID ZFS gptid path standard name, like ada0p1 +# Used only to get RAID ZFS gptid path standard name, like ada0p1 { package GlabelData; + # gptid/c5e940f1-5ce2-11e6-9eeb-d05099ac4dc2 N/A ada0p1 sub get { eval $start if $b_log; @@ -29678,6 +30398,7 @@ sub get { eval $end if $b_log; return $dev_id; } + sub set { eval $start if $b_log; $loaded{'glabel'} = 1; @@ -29718,6 +30439,7 @@ sub get_hostname { { package InitData; my ($init,$init_version,$program) = ('','',''); + sub get { eval $start if $b_log; my $runlevel = get_runlevel(); @@ -29851,6 +30573,7 @@ sub get { 'default' => $default, }; } + sub dinit_data { eval $start if $b_log; $init = 'dinit'; @@ -29861,6 +30584,7 @@ sub dinit_data { } eval $end if $b_log; } + sub openrc_data { eval $start if $b_log; my $version; @@ -29875,7 +30599,8 @@ sub openrc_data { eval $end if $b_log; return ('OpenRC',$version); } -# # check? /var/run/nologin for bsds? + +# Check? /var/run/nologin for bsds? sub get_runlevel { eval $start if $b_log; my $runlevel = ''; @@ -29889,7 +30614,8 @@ sub get_runlevel { eval $end if $b_log; return $runlevel; } -# note: it appears that at least as of 2014-01-13, /etc/inittab is going + +# Note: it appears that at least as of 2014-01-13, /etc/inittab is going # to be used for default runlevel in upstart/sysvinit. systemd default is # not always set so check to see if it's linked. sub get_runlevel_default { @@ -29934,6 +30660,7 @@ sub get_runlevel_default { ## IpData { package IpData; + sub set { eval $start if $b_log; if ($alerts{'ip'}->{'action'} eq 'use'){ @@ -30151,6 +30878,7 @@ sub get_kernel_data { ## KernelParameters { package KernelParameters; + sub get { eval $start if $b_log; my ($parameters); @@ -30163,6 +30891,7 @@ sub get { eval $end if $b_log; return $parameters; } + sub parameters_linux { eval $start if $b_log; my ($file) = @_; @@ -30172,6 +30901,7 @@ sub parameters_linux { eval $end if $b_log; return $line; } + sub parameters_bsd { eval $start if $b_log; my ($parameters); @@ -30183,7 +30913,8 @@ sub parameters_bsd { ## LsblkData - set/get { package LsblkData; -# 1 - partition name + +# args: 0: partition name sub get { eval $start if $b_log; my $item = $_[0]; @@ -30198,6 +30929,7 @@ sub get { eval $start if $b_log; return ($result) ? $result : {}; } + sub set { eval $start if $b_log; $loaded{'lsblk'} = 1; @@ -30277,12 +31009,11 @@ package MemoryData; sub get { eval $start if $b_log; my ($type) = @_; - my ($memory); - # note: netbsd 8.0 has meminfo! $loaded{'memory'} = 1; - # netbsd uses meminfo, but it uses it in a weird way + my ($memory); + # netbsd 8.0 uses meminfo, but it uses it in a weird way if (!$force{'vmstat'} && (!$bsd_type || ($force{'meminfo'} && $bsd_type)) && - (my $file = $system_files{'proc-meminfo'})){ + (my $file = $system_files{'proc-meminfo'})){ $memory = meminfo_data($type,$file); } else { @@ -30291,39 +31022,41 @@ sub get { eval $end if $b_log; return $memory; } -sub full { + +sub row { eval $start if $b_log; my ($source) = @_; - my $num = 0; - my ($memory); - my $row = {}; - my ($gpu_ram,$percent,$total,$used) = (0,'','',''); $loaded{'memory'} = 1; - $memory = get('splits'); + my $num = 0; + my $row = {}; + my ($gpu_ram,$percent,$available,$used) = (0,'','N/A','N/A'); + my $memory = get('full'); if ($memory){ - my @temp = split(':', $memory); - $gpu_ram = $temp[3] if $temp[3]; - $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]; + $gpu_ram = $memory->[3] if $memory->[3]; + $available = main::get_size($memory->[0],'string') if $memory->[0]; + $used = main::get_size($memory->[1],'string') if $memory->[1]; + $used .= " ($memory->[2]%)" if $memory->[2]; if ($gpu_ram){ $gpu_ram = main::get_size($gpu_ram,'string'); } } - my $key = ($source eq 'process') ? 'System RAM': 'RAM'; - $row->{main::key($num++,1,1,$key)} = ''; - $row->{main::key($num++,0,2,'total')} = $total; + $row->{main::key($num++,1,1,'System RAM')} = ''; + $row->{main::key($num++,0,2,'available')} = $available; $row->{main::key($num++,0,2,'used')} = $used; $row->{main::key($num++,0,2,'gpu')} = $gpu_ram if $gpu_ram; eval $end if $b_log; return $row; } + sub meminfo_data { eval $start if $b_log; my ($type,$file) = @_; - my ($available,$buffers,$cached,$free,$gpu,$memory,$not_used,$total) = (0,0,0,0,0,'',0,0); + my ($available,$buffers,$cached,$free,$gpu,$not_used,$total) = (0,0,0,0,0,0,0); + my $memory; my @data = main::reader($file); + # Note: units kB should mean 1000x8 bits, but actually means KiB! Confusing foreach (@data){ + # Not actual total, it's total physical minus reserved/kernel/system. if ($_ =~ /^MemTotal:/){ $total = main::get_piece($_,2); } @@ -30341,17 +31074,17 @@ sub meminfo_data { } } $gpu = gpu_ram_arm() if $risc{'arm'}; - #$gpu = main::translate_size('128M'); - $total += $gpu; + # $gpu = main::translate_size('128M'); + # $total += $gpu; # not using because this ram is not available to system if ($available){ $not_used = $available; } - # seen fringe cases, where total - free+buff+cach < 0 - # the idea is that the OS must be using 10MiB of ram or more + # Seen fringe cases, where total - free+buff+cach < 0 + # The idea is that the OS must be using 10MiB of ram or more elsif (($total - ($free + $buffers + $cached)) > 10000){ $not_used = ($free + $buffers + $cached); } - # netbsd goes < 0, but it's wrong, so dump the cache + # Netbsd goes < 0, but it's wrong, so dump the cache elsif (($total - ($free + $buffers)) > 10000){ $not_used = ($free + $buffers); } @@ -30360,14 +31093,16 @@ sub meminfo_data { } my $used = ($total - $not_used); my $percent = ($used && $total) ? sprintf("%.1f", ($used/$total)*100) : ''; - if ($type eq 'string'){ + if ($type eq 'short'){ $percent = " ($percent%)" if $percent; - $memory = sprintf("%.1f/%.1f MiB", $used/1024, $total/1024) . $percent; + $memory = [sprintf("%.1f/%.1f MiB", $used/1024, $total/1024) . $percent]; } else { - $memory = "$total:$used:$percent:$gpu"; + # raw return in KiB + $memory = [$total,$used,$percent,$gpu]; } - main::log_data('data',"memory: $memory") if $b_log; + # print "$total, $used, $percent, $gpu\n"; + main::log_data('data',"memory ref: $memory") if $b_log; eval $end if $b_log; return $memory; } @@ -30392,9 +31127,8 @@ sub meminfo_data { sub bsd_data { eval $start if $b_log; my ($type) = @_; - my $memory = ''; my ($avm,$av_pages,$cnt,$fre,$free_mem,$mult,$real_mem,$total) = (0,0,0,0,0,0,0,0); - my (@data,$message); + my (@data,$memory,$message); # my $arg = ($bsd_type ne 'openbsd' && $bsd_type ne 'dragonfly') ? '-H' : ''; if (my $program = main::check_program('vmstat')){ # see above, it's the last line. -H makes it hopefully all in kB so no need @@ -30462,29 +31196,30 @@ sub bsd_data { if (($av_pages || $free_mem) && !$real_mem){ my $error = ($message) ? $message: 'total N/A'; my $used = (!$free_mem) ? $av_pages : $real_mem - $free_mem; - if ($type eq 'string'){ + if ($type eq 'short'){ $used = sprintf("%.1f",$used/1024); - $memory = "$used/($error) MiB"; + $memory = ["$used/($error) MiB"]; } else { - $memory = "$error:$used:"; + $memory = [$error,$used,undef]; } } # use openbsd/dragonfly avail mem data if available elsif (($av_pages || $free_mem) && $real_mem){ my $used = (!$free_mem) ? $av_pages : $real_mem - $free_mem; my $percent = ($used && $real_mem) ? sprintf("%.1f", ($used/$real_mem)*100) : ''; - if ($type eq 'string'){ + if ($type eq 'short'){ $percent = " ($percent)" if $percent; - $memory = sprintf("%.1f/%.1f MiB", $used/1024, $real_mem/1024) . $percent; + $memory = [sprintf("%.1f/%.1f MiB", $used/1024, $real_mem/1024) . $percent]; } else { - $memory = "$real_mem:$used:$percent:0"; + $memory = [$real_mem,$used,$percent,0]; } } eval $end if $b_log; return $memory; } + # raspberry pi only sub gpu_ram_arm { eval $start if $b_log; @@ -30540,6 +31275,7 @@ sub get_module_version { package PackageData; my ($count,$num,%pms,$type); $pms{'total'} = 0; + sub get { eval $start if $b_log; # $num passed by reference to maintain incrementing where requested @@ -30552,6 +31288,7 @@ sub get { eval $end if $b_log; return $output; } + sub create_output { eval $start if $b_log; my $output = $_[0]; @@ -30613,6 +31350,7 @@ sub create_output { # print Data::Dumper::Dumper \%output; eval $end if $b_log; } + sub package_counts { eval $start if $b_log; my ($type) = @_; @@ -30631,7 +31369,7 @@ sub package_counts { # mutyx. do cards test because there is a very slow pkginfo python pkg mgr ['cards','pkginfo','p','-i',1,1,'','main::check_program(\'cards\')'], # older dpkg-query do not support -f values consistently: eg ${binary:Package} - ['dpkg','dpkg-query','p','-W -f=\'${Package}\n\'',1,0,'','', + ['dpkg','dpkg-query','p','-W --showformat=\'${Package}\n\'',1,0,'','', ['apt','apt-get','aptitude','deb-get','nala','synaptic']], ['emerge','emerge','d','/var/db/pkg/*/*/',1,5,'\\/'], ['eopkg','eopkg','d','/var/lib/eopkg/package/*',1,5,'\\/'], @@ -30639,6 +31377,10 @@ sub package_counts { ['guix-usr','guix','p','package -I',1,0,''], ['kiss','kiss','p','list',1,0,''], ['mport','mport','p','list',1,0,''], + # netpkg puts packages in same place as slackpkg, only way to tell apart + ['netpkg','netpkg','d','/var/lib/pkgtools/packages/*',1,5,'\\/', + '-d \'/var/netpkg\' && -d \'/var/lib/pkgtools/packages\'', + ['netpkg','sbopkg','sboui','slackpkg','slapt-get','slpkg','swaret']], ['nix-sys','nix-store','p','-qR /run/current-system/sw',1,1,'-'], ['nix-usr','nix-store','p','-qR ~/.nix-profile',1,1,'-'], ['nix-default','nix-store','p','-qR /nix/var/nix/profiles/default',1,2,'-'], @@ -30656,11 +31398,11 @@ sub package_counts { ['pkgutils','pkginfo','p','-i',1,0,'','main::check_program(\'pkgadd\')'], # slack 15 moves packages to /var/lib/pkgtools/packages but links to /var/log/packages ['pkgtool','installpkg','d','/var/lib/pkgtools/packages/*',1,5,'\\/', - '-d \'/var/lib/pkgtools/packages\'', - ['slackpkg','slapt-get','slpkg','swaret']], + '!-d \'/var/netpkg\' && -d \'/var/lib/pkgtools/packages\'', + ['sbopkg','sboui','slackpkg','slapt-get','slpkg','swaret']], ['pkgtool','installpkg','d','/var/log/packages/*',1,4,'\\/', '! -d \'/var/lib/pkgtools/packages\' && -d \'/var/log/packages/\'', - ['slackpkg','slapt-get','slpkg','swaret']], + ['sbopkg','sboui','slackpkg','slapt-get','slpkg','swaret']], # rpm way too slow without nodigest/sig!! confirms packages exist # but even with, MASSIVELY slow in some cases, > 20, 30 seconds!!!! # find another way to get rpm package counts or don't show this feature for rpm!! @@ -30737,6 +31479,7 @@ sub package_counts { main::log_data('dump','Package managers: %pms',\%pms) if $b_log; eval $end if $b_log; } + sub appimage_counts { if (@ps_cmd && (grep {/\bappimage(d|launcher)\b/} @ps_cmd)){ my @list = main::globber($ENV{'HOME'} . '/.{appimage/,local/bin/}*.[aA]pp[iI]mage'); @@ -30748,6 +31491,7 @@ sub appimage_counts { $pms{'total'} += $count; } } + sub check_run { if ($force{'pkg'}){ return 1; @@ -30765,6 +31509,7 @@ sub check_run { } } } + sub count_libs { my ($items,$pos,$split) = @_; my (@data); @@ -30785,10 +31530,11 @@ sub count_libs { package ParseEDID; # CVT_ratios: my @known_ratios = qw(5/4 4/3 3/2 16/10 15/9 16/9); + +# Set values my @edid_info = ( ['a8', '_header'], ['a2', 'manufacturer_name'], - ['v', 'product_code'], ['V', 'serial_number'], ['C', 'week'], @@ -30796,7 +31542,6 @@ my @edid_info = ( ['C', 'edid_version'], ['C', 'edid_revision'], ['a', 'video_input_definition'], - ['C', 'max_size_horizontal'], # in cm, 0 on projectors ['C', 'max_size_vertical'], # in cm, 0 on projectors ['C', 'gamma'], @@ -30805,7 +31550,6 @@ my @edid_info = ( ['a3' , 'established_timings'], ['a16', 'standard_timings'], ['a72', 'monitor_details'], - ['C', 'extension_flag'], ['C', 'checksum'], ); @@ -30829,7 +31573,6 @@ my %subfields = ( [1, 'DPMS_suspend'], [1, 'DPMS_active_off'], [1, 'rgb'], - [1, ''], [1, 'sRGB_compliance'], [1, 'has_preferred_timing'], @@ -30882,7 +31625,6 @@ my %subfields = ( [4, 'vertical_image_size_hi'], [8, 'horizontal_border'], [8, 'vertical_border'], - [1, 'interlaced'], [2, 'stereo'], [2, 'digital_composite'], @@ -31078,6 +31820,7 @@ my %vendors = ( 'VIT' => 'Visitech', 'VLV' => 'Valve', 'VSC' => 'ViewSonic', 'VTK' => 'Viewteck', 'VTS' => 'VTech', 'WTC' => 'Wen Technology', 'XLX' => 'Xilinx', 'YMH' => 'Yamaha', 'ZCM' => 'Zenith', ); + sub _within_limit { my ($value, $type, $limit) = @_; $type eq 'min' ? $value >= $limit : $value <= $limit; @@ -31100,6 +31843,7 @@ sub _get_many_bits { } \%h; } + sub _build_detailed_timing { my ($pixel_clock, $vv) = @_; my $h = _get_many_bits($vv, 'detailed_timing'); @@ -31112,6 +31856,7 @@ sub _build_detailed_timing { } $h; } + sub _add_standard_timing_modes { my ($edid, $v) = @_; my @aspect2ratio = ( @@ -31121,17 +31866,19 @@ sub _add_standard_timing_modes { $v = [ map { my $h = _get_many_bits($_, 'standard_timing'); $h->{X} = ($h->{X} + 31) * 8; - if ($_ ne "\x20\x20" && $h->{X} > 256) { # cf VALID_TIMING in Xorg edid.h + if ($_ ne "\x20\x20" && $h->{X} > 256){ # cf VALID_TIMING in Xorg edid.h $h->{vfreq} += 60; - if ($h->{ratio} = $aspect2ratio[$h->{aspect}]) { + if ($h->{ratio} = $aspect2ratio[$h->{aspect}]){ delete $h->{aspect}; $h->{Y} = $h->{X} / eval($h->{ratio}); } $h; - } else { () } + } + else { () } } unpack('a2' x (length($v) / 2), $v) ]; $v; } + sub parse_edid { eval $start if $b_log; my ($raw_edid, $verbose) = @_; @@ -31141,52 +31888,62 @@ sub parse_edid { my $i = 0; foreach (@edid_info) { my ($field, $v) = ($_->[1], $vals[$i++]); - if ($field eq 'year') { + if ($field eq 'year'){ $v += 1990; - } elsif ($field eq 'manufacturer_name') { + } + elsif ($field eq 'manufacturer_name'){ my $h = _get_many_bits($v, 'manufacturer_name'); $v = join('', map { chr(ord('A') + $h->{$_} - 1) } 1 .. 3); $v = "" if $v eq "@@@"; $edid{'manufacturer_name_nice'} = ($v && $vendors{$v}) ? $vendors{$v} : ''; - } elsif ($field eq 'video_input_definition') { + } + elsif ($field eq 'video_input_definition'){ $v = _get_many_bits($v, 'video_input_definition'); - } elsif ($field eq 'feature_support') { + } + elsif ($field eq 'feature_support'){ $v = _get_many_bits($v, 'feature_support'); - } elsif ($field eq 'color_characteristics') { + } + elsif ($field eq 'color_characteristics'){ $v = _get_many_bits($v, 'color_characteristics'); - } elsif ($field eq 'established_timings') { + } + elsif ($field eq 'established_timings'){ my $h = _get_many_bits($v, 'established_timings'); $v = [ sort { $a->{X} <=> $b->{X} || $a->{vfreq} <=> $b->{vfreq} } map { /(\d+)x(\d+)_(\d+)(i?)/ ? { X => $1, Y => $2, vfreq => $3, $4 ? (interlace => 1) : () } : () } grep { $h->{$_} } keys %$h ]; - } elsif ($field eq 'standard_timings') { + } + elsif ($field eq 'standard_timings'){ $v = _add_standard_timing_modes(\%edid, $v); - } elsif ($field eq 'monitor_details') { - while ($v) { + } + elsif ($field eq 'monitor_details'){ + while ($v){ (my $pixel_clock, my $vv, $v) = unpack("v a16 a*", $v); - if ($pixel_clock) { + if ($pixel_clock){ # detailed timing my $h = _build_detailed_timing($pixel_clock, $vv); push @{$edid{detailed_timings}}, $h if $h->{horizontal_active} > 1 && $h->{vertical_active} > 1; - } else { + } + else { (my $flag, $vv) = unpack("n x a*", $vv); - if ($flag == 0xfd) { + if ($flag == 0xfd){ # range $edid{monitor_range} = _get_many_bits($vv, 'monitor_range'); - if ($edid{monitor_range}{pixel_clock_max} == 0xff) { + if ($edid{monitor_range}{pixel_clock_max} == 0xff){ delete $edid{monitor_range}{pixel_clock_max}; - } else { + } + else { $edid{monitor_range}{pixel_clock_max} *= 10; #- to have it in MHz } - } elsif ($flag == 0xf) { + } + elsif ($flag == 0xf){ my $range = _get_many_bits($vv, 'manufacturer_specified_range_timing'); my $e = $edid{detailed_timings}[0]; my $valid = 1; foreach my $m ('min', 'max') { my %total; - foreach my $dir ('horizontal', 'vertical') { + foreach my $dir ('horizontal', 'vertical'){ $range->{$dir . '_sync_pulse_width_' . $m} *= 2; $range->{$dir . '_back_porch_' . $m} *= 2; $range->{$dir . '_blanking_' . $m} *= 2; @@ -31194,30 +31951,36 @@ sub parse_edid { && _within_limit($e->{$dir . '_blanking'}, $m, $range->{$dir . '_blanking_' . $m}) && _within_limit($e->{$dir . '_sync_pulse_width'}, $m, $range->{$dir . '_sync_pulse_width_' . $m}) && _within_limit($e->{$dir . '_blanking'} - $e->{$dir . '_sync_offset'} - $e->{$dir . '_sync_pulse_width'}, - $m, $range->{$dir . '_back_porch_' . $m})) { + $m, $range->{$dir . '_back_porch_' . $m})){ $total{$dir} = $e->{$dir . '_active'} + $range->{$dir . '_blanking_' . $m}; } } - if ($total{horizontal} && $total{vertical}) { + if ($total{horizontal} && $total{vertical}){ my $hfreq = $e->{pixel_clock} * 1000 / $total{horizontal}; my $vfreq = $hfreq * 1000 / $total{vertical}; $range->{'horizontal_' . ($m eq 'min' ? 'max' : 'min')} = _round($hfreq); $range->{'vertical_' . ($m eq 'min' ? 'max' : 'min')} = _round($vfreq); - } else { + } + else { $valid = 0; } } $edid{$valid ? 'monitor_range' : 'manufacturer_specified_range_timing'} = $range; - } elsif ($flag == 0xfa) { + } + elsif ($flag == 0xfa){ push @{$edid{standard_timings}}, _add_standard_timing_modes(\%edid, unpack('a12', $vv)); - } elsif ($flag == 0xfc) { + } + elsif ($flag == 0xfc){ my $prev = $edid{monitor_name}; $edid{monitor_name} = ($prev ? "$prev " : '') . unpack('A13', $vv); - } elsif ($flag == 0xfe) { + } + elsif ($flag == 0xfe){ push @{$edid{monitor_text}}, unpack('A13', $vv); - } elsif ($flag == 0xff) { + } + elsif ($flag == 0xff){ push @{$edid{serial_number2}}, unpack('A13', $vv); - } elsif ($vv ne "\0" x 13 && $vv ne " " x 13) { + } + elsif ($vv ne "\0" x 13 && $vv ne " " x 13){ push(@warnings, "parse_edid: unknown flag $flag"); warn "$warnings[-1]\n" if $verbose; } @@ -31226,15 +31989,15 @@ sub parse_edid { } $edid{$field} = $v if $field && $field !~ /^_/; } - foreach (@eedid_blocks) { + foreach (@eedid_blocks){ my ($tag, $v) = unpack("C a*", $_); - if ($tag == 0x02) { # CEA EDID + if ($tag == 0x02){ # CEA EDID my $dtd_offset; ($dtd_offset, $v) = unpack("x C x a*", $v); next if $dtd_offset < 4; $dtd_offset -= 4; - while ($dtd_offset > 0) { - if (!$v) { + while ($dtd_offset > 0){ + if (!$v){ push(@warnings, "parse_edid: DTD offset outside of available data"); warn "$warnings[-1]\n" if $verbose; last; @@ -31243,12 +32006,12 @@ sub parse_edid { $dtd_offset -= $h->{size} + 1; my $vv; ($vv, $v) = unpack("x a$h->{size} a*", $v); - if ($h->{type} == 0x02) { # Video Data Block + if ($h->{type} == 0x02){ # Video Data Block my @vmodes = unpack("a" x $h->{size}, $vv); - foreach my $vmode (@vmodes) { + foreach my $vmode (@vmodes){ $h = _get_many_bits($vmode, 'cea_video_data_block'); my $cea_mode = $cea_video_modes[$h->{mode} - 1]; - if (!$cea_mode) { + if (!$cea_mode){ push(@warnings, "parse_edid: unhandled CEA mode $h->{mode}"); warn "$warnings[-1]\n" if $verbose; next; @@ -31259,14 +32022,15 @@ sub parse_edid { } } } - while (length($v) >= 18) { + while (length($v) >= 18){ (my $pixel_clock, my $vv, $v) = unpack("v a16 a*", $v); last if !$pixel_clock; my $h = _build_detailed_timing($pixel_clock, $vv); push @{$edid{detailed_timings}}, $h if $h->{horizontal_active} > 1 && $h->{vertical_active} > 1; } - } else { + } + else { push(@warnings, "parse_edid: unknown tag $tag"); warn "$warnings[-1]\n" if $verbose; } @@ -31279,24 +32043,24 @@ sub parse_edid { } $edid{product_code_h} = '0x'. $edid{product_code_h}; } - if ($edid{monitor_range}) { + if ($edid{monitor_range}){ $edid{HorizSync} = $edid{monitor_range}{horizontal_min} . '-' . $edid{monitor_range}{horizontal_max}; $edid{VertRefresh} = $edid{monitor_range}{vertical_min} . '-' . $edid{monitor_range}{vertical_max}; } - if ($edid{max_size_vertical}) { + if ($edid{max_size_vertical}){ $edid{ratio} = $edid{max_size_horizontal} / $edid{max_size_vertical}; $edid{ratio_name} = _ratio_name($edid{max_size_horizontal}, $edid{max_size_vertical}, 'cm'); $edid{ratio_precision} = 'cm'; } - if ($edid{feature_support}{has_preferred_timing} && $edid{detailed_timings}[0]) { + if ($edid{feature_support}{has_preferred_timing} && $edid{detailed_timings}[0]){ $edid{detailed_timings}[0]{preferred} = 1; } - foreach my $h (@{$edid{detailed_timings}}) { + foreach my $h (@{$edid{detailed_timings}}){ # EDID standard is ambiguous on how interlaced modes should be # specified; workaround clearly broken modes: - if ($h->{interlaced}) { - foreach ("720x480", "1440x480", "2880x480", "720x576", "1440x576", "2880x576", "1920x1080") { - if ($_ eq $h->{horizontal_active} . 'x' . $h->{vertical_active} * 2) { + if ($h->{interlaced}){ + foreach ("720x480", "1440x480", "2880x480", "720x576", "1440x576", "2880x576", "1920x1080"){ + if ($_ eq $h->{horizontal_active} . 'x' . $h->{vertical_active} * 2){ $h->{vertical_active} *= 2; $h->{vertical_blanking} *= 2; $h->{vertical_sync_offset} *= 2; @@ -31312,39 +32076,39 @@ sub parse_edid { vertical => _define($h->{vertical_image_size}) / 10, ); my ($error) = sort { $b <=> $a } map { abs($edid{'max_size_' . $_} - $in_cm{$_}) } keys %in_cm; - if ($error <= 0.5) { + if ($error <= 0.5){ $edid{'max_size_' . $_} = $in_cm{$_} foreach keys %in_cm; $edid{max_size_precision} = 'mm'; } - if ($error < 1 && $in_cm{vertical}) { + if ($error < 1 && $in_cm{vertical}){ # using it for the ratio $edid{ratio} = $in_cm{horizontal} / $in_cm{vertical}; $edid{ratio_name} = _ratio_name($in_cm{horizontal}, $in_cm{vertical}, 'mm'); $edid{ratio_precision} = 'mm'; } if ($edid{ratio_precision} && - abs($edid{ratio} - $h->{horizontal_active} / $h->{vertical_active}) > ($edid{ratio_precision} eq 'mm' ? 0.02 : 0.2)) { + abs($edid{ratio} - $h->{horizontal_active} / $h->{vertical_active}) > ($edid{ratio_precision} eq 'mm' ? 0.02 : 0.2)){ $h->{bad_ratio} = 1; } - if ($edid{ratio_name}) { + if ($edid{ratio_name}){ $edid{ratios} = $edid{ratio_name}; $edid{ratios} =~ s|/|:|g; $edid{ratios} = [split(/ or /, $edid{ratios})]; # "3/2 or 16/10" } - if ($edid{max_size_vertical}) { + if ($edid{max_size_vertical}){ $h->{vertical_dpi} = $h->{vertical_active} / $edid{max_size_vertical} * 2.54; } - if ($edid{max_size_horizontal}) { + if ($edid{max_size_horizontal}){ $h->{horizontal_dpi} = $h->{horizontal_active} / $edid{max_size_horizontal} * 2.54; } - if ($h->{horizontal_image_size}) { + if ($h->{horizontal_image_size}){ $h->{horizontal_image_size_i} = sprintf('%.2f',($h->{horizontal_image_size}/25.4)) + 0; } - if ($h->{vertical_image_size}) { + if ($h->{vertical_image_size}){ $h->{vertical_image_size_i} = sprintf('%.2f',($h->{vertical_image_size}/25.4)) + 0; } my $dpi_string = ''; - if ($h->{vertical_dpi} && $h->{horizontal_dpi}) { + if ($h->{vertical_dpi} && $h->{horizontal_dpi}){ $dpi_string = abs($h->{vertical_dpi} / $h->{horizontal_dpi} - 1) < 0.05 ? sprintf("%d dpi", $h->{horizontal_dpi}) : @@ -31364,17 +32128,14 @@ sub parse_edid { $h->{ModeLine} = sprintf(qq("%dx%d" $h->{pixel_clock} %d %d %d %d %d %d %d %d %shsync %svsync%s), $h->{horizontal_active}, $h->{vertical_active}, - $h->{horizontal_active}, $h->{horizontal_active} + $h->{horizontal_sync_offset}, $h->{horizontal_active} + $h->{horizontal_sync_offset} + $h->{horizontal_sync_pulse_width}, $horizontal_total, - $h->{vertical_active}, $h->{vertical_active} + $h->{vertical_sync_offset}, $h->{vertical_active} + $h->{vertical_sync_offset} + $h->{vertical_sync_pulse_width}, $vertical_total, - $h->{horizontal_sync_positive} ? '+' : '-', $h->{vertical_sync_positive} ? '+' : '-', $h->{interlaced} ? ' Interlace' : ''); @@ -31389,6 +32150,7 @@ sub parse_edid { eval $end if $b_log; \%edid; } + sub _edid_errors { my $edid = shift @_; if (!defined $edid->{edid_version}){ @@ -31420,11 +32182,13 @@ sub _edid_errors { } } } + sub _edid_error { my ($edid,$error,$data) = @_; $edid->{edid_errors} = [] if !$edid->{edid_errors}; push(@{$edid->{edid_errors}},main::message($error,$data)); } + sub _nearest_ratio { my ($ratio, $max_error) = @_; my @sorted = @@ -31435,32 +32199,45 @@ sub _nearest_ratio { } @known_ratios; $sorted[0][0]; } + sub _ratio_name { my ($horizontal, $vertical, $precision) = @_; - if ($precision eq 'mm') { + if ($precision eq 'mm'){ _nearest_ratio($horizontal / $vertical, 0.1); - } else { + } + else { my $error = 0.5; my $ratio1 = _nearest_ratio(($horizontal + $error) / ($vertical - $error), 0.2); my $ratio2 = _nearest_ratio(($horizontal - $error) / ($vertical + $error), 0.2); $ratio1 && $ratio2 or return; - if ($ratio1 eq $ratio2) { + if ($ratio1 eq $ratio2){ $ratio1; - } else { + } + else { my $ratio = _nearest_ratio($horizontal / $vertical, 0.2); join(' or ', $ratio, $ratio eq $ratio1 ? $ratio2 : $ratio1); } } } -sub _define { defined $_[0] ? $_[0] : 0 } -sub _sqr { $_[0] * $_[0] } -sub _round { int($_[0] + 0.5) } + +sub _define { + defined $_[0] ? $_[0] : 0; +} + +sub _sqr { + $_[0] * $_[0]; +} + +sub _round { + int($_[0] + 0.5); +} } ## PartitionData - set/get # for /proc/partitions only, see DiskDataBSD for BSD partition data. { package PartitionData; + sub set { my ($type) = @_; $loaded{'partition-data'} = 1; @@ -31468,7 +32245,8 @@ sub set { proc_data($file); } } -# 1 - partition name, without /dev, like sda1, sde + +# args: 0: partition name, without /dev, like sda1, sde sub get { eval $start if $b_log; my $item = $_[0]; @@ -31502,7 +32280,7 @@ sub proc_data { } } -# args: 1 - pci device string; 2 - pci cleaned subsystem string +# args: 0: pci device string; 1: pci cleaned subsystem string sub get_pci_vendor { eval $start if $b_log; my ($device, $subsystem) = @_; @@ -31711,7 +32489,7 @@ sub set_ps_gui { dwc dwl epd-wm fireplace feathers fenestra glass gamescope greenfield grefson hikari hopalong hyprland inaban japokwm kiwmi labwc laikawm lipstick liri mahogany marina maze motorcar newm nucleus orbital perceptia phoc pywm qtile - river rootston rustland simulavr skylight sommelier sway swc swvkc + river rootston rustland simulavr skylight smithay sommelier sway swc swvkc tabby taiwins tinybox tinywl trinkster velox vimway vivarium wavy waybox way-?cooler wayfire wayhouse waymonad westeros westford weston wio\+? wxr[cd] xuake)); @@ -31746,6 +32524,7 @@ sub get_self_version { { package ServiceData; my ($key,$service,$type); + sub get { eval $start if $b_log; ($type,$service) = @_; @@ -31763,6 +32542,7 @@ sub get { eval $end if $b_log; return $value; } + sub process_status { eval $start if $b_log; my ($cmd,$status,@data); @@ -31897,6 +32677,7 @@ sub process_status { eval $end if $b_log; return $result; } + sub set { eval $start if $b_log; $loaded{'service-tool'} = 1; @@ -31950,12 +32731,12 @@ sub set { package ShellData; my $b_debug = 0; # disable all debugger output in case forget to comment out! -# public. This does not depend on using ps -jfp, open/netbsd do not -# at this point support it, so we only want to use -jp to get parent -# $ppid set in initialize(). shell_launcher will use -f so it only -# runs in case we got $pppid. $client{'pppid'} will be used to trigger -# launcher tests. If started with sshd via ssh user@address 'pinxi -Ia' -# will show sshd as shell, which is fine, that's what it is. +# Public. This does not depend on using ps -jfp, open/netbsd do not at this +# point support it, so we only want to use -jp to get parent $ppid set in +# initialize(). shell_launcher will use -f so it only runs in case we got +# $pppid. $client{'pppid'} will be used to trigger launcher tests. If started +# with sshd via ssh user@address 'pinxi -Ia' will show sshd as shell, which is +# fine, that's what it is. sub set { eval $start if $b_log; my ($cmd,$parent,$pppid,$shell); @@ -32082,7 +32863,8 @@ sub set { } eval $end if $b_log; } -# public, returns shell launcher, terminal, program, whatever + +# Public: returns shell launcher, terminal, program, whatever # depends on $pppid so only runs if that is set. sub shell_launcher { eval $start if $b_log; @@ -32131,7 +32913,8 @@ sub shell_launcher { eval $end if $b_log; return $shell_parent; } -# arg: 1 - parent id + +# args: 0: parent id # returns SID/start ID sub get_pppid { eval $start if $b_log; @@ -32146,7 +32929,8 @@ sub get_pppid { eval $end if $b_log; return $pppid; } -# arg: 1 - parent id + +# args: 0: parent id # returns parent command name sub parent_name { eval $start if $b_log; @@ -32173,9 +32957,10 @@ sub parent_name { eval $end if $b_log; return $parent_name; } -# list of program_values non-handled shells, or known to have no version + +# List of program_values non-handled shells, or known to have no version # Move shell to set_program_values for print name, or version if available -# $1 - return|[shell name to test +# args: 0: return|[shell name to test # returns test list OR shell name/'' sub shell_test { my ($test) = @_; @@ -32188,7 +32973,8 @@ sub shell_test { return '|' . $shells if $test eq 'return'; return ($test =~ /^($shells)$/) ? $test : ''; } -# this will test against default IP like: (:0) vs full IP to determine + +# This will test against default IP like: (:0) vs full IP to determine # ssh status. Surprisingly easy test? Cross platform sub ssh_status { eval $start if $b_log; @@ -32197,7 +32983,7 @@ sub ssh_status { # fred-remote pts/1 2018-03-27 17:13 (43.43.43.43) if (my $program = main::check_program('who')){ $ssh = (main::grabber("$program am i 2>/dev/null"))[0]; - # crude IP validation + # crude IP validation, v6 ::::::::, v4 x.x.x.x if ($ssh && $ssh =~ /\(([:0-9a-f]{8,}|[1-9][\.0-9]{6,})\)$/){ $b_ssh = 1; } @@ -32205,6 +32991,7 @@ sub ssh_status { eval $end if $b_log; return $b_ssh; } + # If IRC: called if root for -S, -G, or if not in display for user. sub console_irc_tty { eval $start if $b_log; @@ -32223,6 +33010,7 @@ sub console_irc_tty { main::log_data('data',"console-irc-tty:$client{'con-irc-tty'}") if $b_log; eval $end if $b_log; } + sub tty_number { eval $start if $b_log; $loaded{'tty-number'} = 1; @@ -32417,37 +33205,43 @@ sub get_uptime { ## UsbData # %usb array indexes -# 0 - bus id / sort id -# 1 - device id -# 2 - path_id -# 3 - path -# 4 - class id -# 5 - subclass id -# 6 - protocol id -# 7 - vendor:chip id -# 8 - usb version -# 9 - interfaces -# 10 - ports -# 11 - vendor -# 12 - product -# 13 - device-name -# 14 - type string -# 15 - driver -# 16 - serial -# 17 - speed -# 18 - configuration - not used -# 19 - power mW bsd only, not used yet -# 20 - product rev number -# 21 - driver_nu [bsd only] +# 0: bus id / sort id +# 1: device id +# 2: path_id +# 3: path +# 4: class id +# 5: subclass id +# 6: protocol id +# 7: vendor:chip id +# 8: usb version +# 9: interfaces +# 10: ports +# 11: vendor +# 12: product +# 13: device-name +# 14: type string +# 15: driver +# 16: serial +# 17: speed (bits, Si base 10, [MG]bps) +# 18: configuration - not used +# 19: power mW bsd only, not used yet +# 20: product rev number +# 21: driver_nu [bsd only] +# 22: admin usb rev info +# 23: rx lanes +# 24: tx lanes +# 25: speed (Bytes, IEC base 2, [MG]iBs +# 26: absolute path { 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,$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); +$name,$network_regex,$path,$path_id,$power,$product,$product_id,$protocol_id, +$mode,$rev,$serial,$speed_si,$speed_iec,$subclass_id,$type,$version, +$vendor,$vendor_id); my $b_live = 1; # debugger file data + sub set { eval $start if $b_log; ${$_[0]} = 1; # set checked boolean @@ -32468,10 +33262,13 @@ sub set { sys_data('main'); } @{$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; + if ($b_log){ + main::log_data('dump','$usb{audio}: ',$usb{'audio'}); + main::log_data('dump','$usb{bluetooth}: ',$usb{'bluetooth'}); + main::log_data('dump','$usb{disk}: ',$usb{'disk'}); + main::log_data('dump','$usb{graphics}: ',$usb{'graphics'}); + main::log_data('dump','$usb{network}: ',$usb{'network'}); + } eval $end if $b_log; } @@ -32535,6 +33332,7 @@ sub lsusb_data { 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) # note: tried getting driver/ports from dmesg, impossible, waste of time @@ -32566,7 +33364,8 @@ sub usbconfig_data { undef @working; } elsif (/^([a-z_-]+)([0-9]+)\.([0-9]+):\s+<[^>]+>\s+at usbus([0-9]+)\b/){ - ($class_id,$cfg,$power,$speed,$subclass_id,$type) = (); + ($class_id,$cfg,$power,$rev,$mode,$speed_si,$speed_iec,$subclass_id, + $type) = (); ($product,$product_id,$vendor,$vendor_id) = ('','','',''); $hub_id = $2; $addr_id = $3; @@ -32582,25 +33381,28 @@ sub usbconfig_data { # 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); + $speed_si = $3; } if (/\b(power|pwr)\s*=\s*([\S]+)\s+\(([0-9]+mA)\)/){ $power = $3; process_power(\$power) if $power; } + version_data('bsd',\$speed_si,\$speed_iec,\$rev,\$mode); $working[0] = $bus_id_alpha; $working[1] = $addr_id; $working[2] = $path_id; $working[3] = ''; - $working[8] = usb_rev($speed); + $working[8] = $rev; $working[9] = ''; $working[10] = $ports; $working[15] = $driver; - $working[17] = $speed; + $working[17] = $speed_si; $working[18] = $cfg; $working[19] = $power; $working[20] = ''; $working[21] = $driver_nu; + $working[22] = $mode; + $working[25] = $speed_iec; } elsif (/^bDeviceClass\s*=\s*0x00([a-f0-9]{2})\s*(<([^>]+)>)?/){ $class_id = $1; @@ -32638,6 +33440,7 @@ sub usbconfig_data { 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 @@ -32659,9 +33462,10 @@ sub usbdevs_data { $bus_id = $1; } 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})\)/){ + ($mode,$rev,$speed_si,$speed_iec) = (); $hub_id = $1; $addr_id = $1; - $speed = prep_speed($2); + $speed_si = $2; # requires prep $power = $3; $chip_id = "$6:$8"; $config = $4; @@ -32672,6 +33476,7 @@ sub usbdevs_data { $ports = 0; process_power(\$power) if $power; $port_value = ''; + version_data('bsd',\$speed_si,\$speed_iec,\$rev,\$mode); $working[0] = $bus_id_alpha; $working[1] = $addr_id; $working[2] = $path_id; @@ -32680,24 +33485,27 @@ sub usbdevs_data { $working[5] = ''; $working[6] = ''; $working[7] = $chip_id; - $working[8] = usb_rev($speed); + $working[8] = $rev; $working[9] = ''; $working[10] = $ports; $working[13] = $name; $working[14] = 'Hub'; $working[15] = ''; $working[16] = ''; - $working[17] = $speed; + $working[17] = $speed_si; $working[18] = $config; $working[19] = $power; $working[20] = ''; + $working[22] = $mode; + $working[25] = $speed_iec; } 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})\)/){ + ($rev,$mode,$speed_iec,$speed_si) = (); $port = $1; - $addr_id = "$2"; + $addr_id = $2; + $speed_si = $3; $power = $4; $config = $5; - $speed = prep_speed($3); $chip_id = "$7:$9"; $name = main::remove_duplicates("$8 $6"); $type = check_type($name,'',''); @@ -32707,6 +33515,7 @@ sub usbdevs_data { $path_id = "$bus_id-$hub_id.$port"; $bus_id_alpha = bus_id_alpha($path_id); process_power(\$power) if $power; + version_data('bsd',\$speed_si,\$speed_iec,\$rev,\$mode); $working[0] = $bus_id_alpha; $working[1] = $addr_id; $working[2] = $path_id; @@ -32715,7 +33524,7 @@ sub usbdevs_data { $working[5] = ''; $working[6] = ''; $working[7] = $chip_id; - $working[8] = usb_rev($speed); + $working[8] = $rev; $working[9] = ''; $working[10] = $ports; $working[11] = ''; @@ -32724,10 +33533,12 @@ sub usbdevs_data { $working[14] = $type; $working[15] = ''; $working[16] = ''; - $working[17] = $speed; + $working[17] = $speed_si; $working[18] = $config; $working[19] = $power; $working[20] = ''; + $working[22] = $mode; + $working[25] = $speed_iec; } elsif (/^port\s([0-9]+)\spowered/){ $ports++; @@ -32768,17 +33579,20 @@ sub usbdevs_data { $working[20] = ''; } 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); + /^([^,]+),\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){ + ($mode,$rev,$speed_iec,$speed_si) = (); + $speed_si = $1; $power = $3; process_power(\$power) if $power; + version_data('bsd',\$speed_si,\$speed_iec,\$rev,\$mode); $working[8] = $rev; $working[16] = $7 if $7; - $working[17] = $speed; + $working[17] = $speed_si; $working[18] = $4; # config number $working[19] = $power; $working[20] = $5; # product rev + $working[22] = $mode; + $working[25] = $speed_iec; } # 1 or more drivers supported elsif ($b_multi && /^driver:\s*([^,]+)$/){ @@ -32855,24 +33669,24 @@ sub usb_grabber { sub sys_data { eval $start if $b_log; my ($source) = @_; - my ($configuration,$ports,$usb_version); + my ($configuration,$lanes_rx,$lanes_tx,$ports,$mode,$rev); my (@drivers,@uevent); my $i = 0; 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); - foreach (@files){ + foreach my $file (@files){ # be careful, sometimes uevent is not readable - @uevent = (-r "$_/uevent") ? main::reader("$_/uevent") : undef; + @uevent = (-r "$file/uevent") ? main::reader("$file/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"; - $path_id = $_; + (@drivers,$lanes_rx,$lanes_tx,$mode,$rev,$speed_iec,$speed_si) = (); + ($configuration,$driver,$interfaces,$name,$ports,$product,$serial, + $type,$vendor) = ('','','','','','','','',''); + # print Cwd::abs_path($file),"\n"; + # print "f1: $file\n"; + $path_id = $file; $path_id =~ s/^.*\///; $path_id =~ s/^usb([0-9]+)/$1-0/; # if DEVICE= then path = /proc/bus/usb/001/001 else: bus/usb/006/001 @@ -32883,29 +33697,32 @@ sub sys_data { $bus_id_alpha = bus_id_alpha($path_id); $device_id = int($working[3]); # this will be a hex number - $class_id = sys_item("$_/bDeviceClass"); - # $subclass_id = sys_item("$_/bDeviceSubClass"); - # $protocol_id = sys_item("$_/bDeviceProtocol"); + $class_id = sys_item("$file/bDeviceClass"); + # $subclass_id = sys_item("$file/bDeviceSubClass"); + # $protocol_id = sys_item("$file/bDeviceProtocol"); $class_id = hex($class_id) if $class_id; # $subclass_id = hex($subclass_id) if $subclass_id; # $protocol_id = hex($protocol_id) if $protocol_id; # print "$path_id $class_id/$subclass_id/$protocol_id\n"; - $power = sys_item("$_/bMaxPower"); + $power = sys_item("$file/bMaxPower"); process_power(\$power) if $power; # this populates class, subclass, and protocol id with decimal numbers - @drivers = uevent_data("$_/[0-9]*/uevent"); - push(@drivers, uevent_data("$_/[0-9]*/*/uevent")) if !$b_hub; - $ports = sys_item("$_/maxchild") if $b_hub; + @drivers = uevent_data("$file/[0-9]*/uevent"); + push(@drivers, uevent_data("$file/[0-9]*/*/uevent")) if !$b_hub; + $ports = sys_item("$file/maxchild") if $b_hub; if (@drivers){ main::uniq(\@drivers); $driver = join(',', sort @drivers); } - $interfaces = sys_item("$_/bNumInterfaces"); - $serial = sys_item("$_/serial"); - $usb_version = sys_item("$_/version"); - $speed = sys_item("$_/speed"); - $configuration = sys_item("$_/configuration"); - $power = sys_item("$_/bMaxPower"); + $interfaces = sys_item("$file/bNumInterfaces"); + $lanes_rx = sys_item("$file/rx_lanes"); + $lanes_tx = sys_item("$file/tx_lanes"); + $serial = sys_item("$file/serial"); + $rev = sys_item("$file/version"); + $speed_si = sys_item("$file/speed"); + version_data('sys',\$speed_si,\$speed_iec,\$rev,\$mode,$lanes_rx,$lanes_tx); + $configuration = sys_item("$file/configuration"); + $power = sys_item("$file/bMaxPower"); process_power(\$power) if $power; $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 ''; @@ -32918,24 +33735,29 @@ sub sys_data { # print $type,"\n"; $usb{'main'}->[$i][0] = $bus_id_alpha; $usb{'main'}->[$i][2] = $path_id; - $usb{'main'}->[$i][3] = $_; + $usb{'main'}->[$i][3] = $file; $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][8] = $rev; $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] =~ /^linux foundation/i)){ $usb{'main'}->[$i][13] = "$type"; } $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][17] = $speed_si if $speed_si; $usb{'main'}->[$i][18] = $configuration; $usb{'main'}->[$i][19] = $power; $usb{'main'}->[$i][20] = ''; + $usb{'main'}->[$i][22] = $mode; + $usb{'main'}->[$i][23] = $lanes_rx; + $usb{'main'}->[$i][24] = $lanes_tx; + $usb{'main'}->[$i][25] = $speed_iec if $speed_iec; + $usb{'main'}->[$i][26] = Cwd::abs_path($file); assign_usb_type($usb{'main'}->[$i]); # print join("\n",@{$usb{'main'}->[$i]}),"\n\n";# if !$b_hub; last; @@ -32943,13 +33765,13 @@ sub sys_data { } } else { - $chip_id = sys_item("$_/idProduct"); - $vendor_id = sys_item("$_/idVendor"); + $chip_id = sys_item("$file/idProduct"); + $vendor_id = sys_item("$file/idVendor"); # we don't want the device, it's probably a bad path in /sys/bus/usb/devices next if !$vendor_id && !$chip_id; - $product = sys_item("$_/product"); + $product = sys_item("$file/product"); $product = main::clean($product) if $product; - $vendor = sys_item("$_/manufacturer"); + $vendor = sys_item("$file/manufacturer"); $vendor = main::clean($vendor) if $vendor; if (!$b_hub && ($product || $vendor)){ if ($vendor && $product && $product !~ /$vendor/){ @@ -32977,12 +33799,12 @@ sub sys_data { $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][3] = $file; $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][8] = $rev; $usb{'main'}->[$i][9] = $interfaces; $usb{'main'}->[$i][10] = $ports; $usb{'main'}->[$i][11] = $vendor; @@ -32991,10 +33813,15 @@ sub sys_data { $usb{'main'}->[$i][14] = $type; $usb{'main'}->[$i][15] = $driver; $usb{'main'}->[$i][16] = $serial; - $usb{'main'}->[$i][17] = $speed; + $usb{'main'}->[$i][17] = $speed_si; $usb{'main'}->[$i][18] = $configuration; $usb{'main'}->[$i][19] = $power; $usb{'main'}->[$i][20] = ''; + $usb{'main'}->[$i][22] = $mode; + $usb{'main'}->[$i][23] = $lanes_rx; + $usb{'main'}->[$i][24] = $lanes_tx; + $usb{'main'}->[$i][25] = $speed_iec; + $usb{'main'}->[$i][26] = Cwd::abs_path($file); assign_usb_type($usb{'main'}->[$i]); $i++; } @@ -33005,7 +33832,8 @@ sub sys_data { 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 + +# Get driver, interface [type:] data sub uevent_data { my ($path) = @_; my ($interface,$interfaces,$temp,@interfaces,@drivers); @@ -33060,6 +33888,7 @@ sub uevent_data { } return @drivers; } + sub sys_item { my ($path) = @_; my ($item); @@ -33068,15 +33897,16 @@ sub sys_item { $item = main::trimmer($item) if $item; return $item; } + sub assign_usb_type { my ($row) = @_; - # it's a hub - # a device will always be the second or > device on the bus, although - # nested hubs of course can be > 1 too. No need to build these if none of - # lines are showing. + # It's a hub. A device will always be the second or > device on the bus, + # although nested hubs of course can be > 1 too. No need to build these if + # none of lines are showing. if (($row->[4] && $row->[4] eq '09') || - ($row->[14] && $row->[14] eq 'Hub') || $row->[1] <= 1 || - (!$show{'audio'} && !$show{'bluetooth'} && !$show{'graphic'} && !$show{'network'})){ + ($row->[14] && $row->[14] eq 'hub') || $row->[1] <= 1 || + (!$show{'audio'} && !$show{'bluetooth'} && !$show{'disk'} && + !$show{'graphic'} && !$show{'network'})){ return; } $row->[13] = '' if !defined $row->[13]; # product @@ -33087,27 +33917,32 @@ sub assign_usb_type { # 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->[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); } - if ($show{'graphic'} && ($row->[14] && ($row->[14] =~ /Video/) || + 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); } - elsif ($show{'bluetooth'} && ($row->[14] && $row->[14] =~ /Bluetooth/ || + elsif ($show{'bluetooth'} && ($row->[14] && $row->[14] =~ /bluetooth/ || ($row->[15] && $row->[15] =~ /\b(btusb|ubt)\b/))){ push(@{$usb{'bluetooth'}},$row); } + elsif ($show{'disk'} && ($row->[14] && $row->[14] =~ /mass storage/ || + ($row->[15] && $row->[15] =~ /storage/))){ + push(@{$usb{'disk'}},$row); + } elsif ($show{'network'} && ( - ($row->[14] && $row->[14] =~ /(Ethernet|Network|WiFi)/i) || + ($row->[14] && $row->[14] =~ /(ethernet|network|wifi)/) || ($row->[15] && $row->[15] =~ /(^ipw|^iwl|wifi)/) || ($row->[13] && $row->[13] =~ /($network_regex)/i))){ # print "$1\n"; push(@{$usb{'network'}},$row); } } + sub device_type { my ($data) = @_; my ($type); @@ -33121,54 +33956,86 @@ sub device_type { $subclass_id = $types[1]; $protocol_id = $types[2]; } - if ($types[0] eq '1'){$type = 'Audio';} + if ($types[0] eq '1'){ + $type = 'audio';} elsif ($types[0] eq '2'){ - if ($types[1] eq '2'){$type = 'Abstract (modem)';} - elsif ($types[1] eq '6'){$type = 'Ethernet Network';} - elsif ($types[1] eq '10'){$type = 'Mobile Direct Line';} - elsif ($types[1] eq '12'){$type = 'Ethernet Emulation';} - else {$type = 'Communication';} + if ($types[1] eq '2'){ + $type = 'abstract (modem)';} + elsif ($types[1] eq '6'){ + $type = 'ethernet network';} + elsif ($types[1] eq '10'){ + $type = 'mobile direct line';} + elsif ($types[1] eq '12'){ + $type = 'ethernet emulation';} + else { + $type = 'communication';} } elsif ($types[0] eq '3'){ - if ($types[2] eq '0'){$type = 'HID';} # actual value: None - elsif ($types[2] eq '1'){$type = 'Keyboard';} - elsif ($types[2] eq '2'){$type = 'Mouse';} + if ($types[2] eq '0'){ + $type = 'HID';} # actual value: None + elsif ($types[2] eq '1'){ + $type = 'keyboard';} + elsif ($types[2] eq '2'){ + $type = 'mouse';} } - elsif ($types[0] eq '6'){$type = 'Still Imaging';} - elsif ($types[0] eq '7'){$type = 'Printer';} - elsif ($types[0] eq '8'){$type = 'Mass Storage';} + elsif ($types[0] eq '6'){ + $type = 'still imaging';} + elsif ($types[0] eq '7'){ + $type = 'printer';} + elsif ($types[0] eq '8'){ + $type = 'mass storage';} # note: there is a bug in linux kernel that always makes hubs 9/0/0 elsif ($types[0] eq '9'){ - if ($types[2] eq '0'){$type = 'Full speed or root hub';} - elsif ($types[2] eq '1'){$type = 'Hi-speed hub with single TT';} - elsif ($types[2] eq '2'){$type = 'Hi-speed hub with multiple TTs';} + if ($types[2] eq '0'){ + $type = 'full speed or root hub';} + elsif ($types[2] eq '1'){ + $type = 'hi-speed hub with single TT';} + elsif ($types[2] eq '2'){ + $type = 'hi-speed hub with multiple TTs';} # seen protocol 3, usb3 type hub, but not documented on usb.org - elsif ($types[2] eq '3'){$type = 'Super-speed hub';} + elsif ($types[2] eq '3'){ + $type = 'super-speed hub';} # this is a guess, never seen it - elsif ($types[2] eq '4'){$type = 'Super-speed+ hub';} + elsif ($types[2] eq '4'){ + $type = 'super-speed+ hub';} } - elsif ($types[0] eq '10'){$type = 'CDC-Data';} - elsif ($types[0] eq '11'){$type = 'Smart Card';} - elsif ($types[0] eq '13'){$type = 'Content Security';} - elsif ($types[0] eq '14'){$type = 'Video';} - elsif ($types[0] eq '15'){$type = 'Personal Healthcare';} - elsif ($types[0] eq '16'){$type = 'Audio-Video';} - elsif ($types[0] eq '17'){$type = 'Billboard';} - elsif ($types[0] eq '18'){$type = 'Type-C Bridge';} - elsif ($types[0] eq '88'){$type = 'Xbox';} - elsif ($types[0] eq '220'){$type = 'Diagnostic';} + elsif ($types[0] eq '10'){ + $type = 'CDC-data';} + elsif ($types[0] eq '11'){ + $type = 'smart card';} + elsif ($types[0] eq '13'){ + $type = 'content security';} + elsif ($types[0] eq '14'){ + $type = 'video';} + elsif ($types[0] eq '15'){ + $type = 'personal healthcare';} + elsif ($types[0] eq '16'){ + $type = 'audio-video';} + elsif ($types[0] eq '17'){ + $type = 'billboard';} + elsif ($types[0] eq '18'){ + $type = 'type-C bridge';} + elsif ($types[0] eq '88'){ + $type = 'Xbox';} + elsif ($types[0] eq '220'){ + $type = 'diagnostic';} elsif ($types[0] eq '224'){ - if ($types[1] eq '1'){$type = 'Bluetooth';} + if ($types[1] eq '1'){ + $type = 'bluetooth';} elsif ($types[1] eq '2'){ - if ($types[2] eq '1'){$type = 'Host Wire Adapter';} - elsif ($types[2] eq '2'){$type = 'Device Wire Adapter';} - elsif ($types[2] eq '3'){$type = 'Device Wire Adapter';} + if ($types[2] eq '1'){ + $type = 'host wire adapter';} + elsif ($types[2] eq '2'){ + $type = 'device wire adapter';} + elsif ($types[2] eq '3'){ + $type = 'device wire adapter';} } } # print "$data: $type\n"; return $type; } -# device name/driver string based test, return if not detected + +# Device name/driver string based test, return if not detected # for linux based tests, and empty for bsd tests sub check_type { my ($name,$driver,$type) = @_; @@ -33205,6 +34072,7 @@ sub check_type { } return $type; } + # linux only, will create a positive match to sound devices sub set_asound_ids { $b_asound = 1; @@ -33219,9 +34087,10 @@ sub set_asound_ids { } main::log_data('dump','@asound_ids',\@asound_ids) if $b_log; } -### USB networking search string data, because some brands can have other products than -### wifi/nic cards, they need further identifiers, with wildcards. -### putting the most common and likely first, then the less common, then some specifics + +# USB networking search string data, because some brands can have other products +# than wifi/nic cards, they need further identifiers, with wildcards. Putting +# the most common and likely first, then the less common, then some specifics sub set_network_regex { # belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda; # Atmel, Atheros make other stuff. NOTE: exclude 'networks': IMC Networks @@ -33238,64 +34107,229 @@ sub set_network_regex { $network_regex .= 'Range(Booster|Max)|Samsung.*LinkStick|\b(WG|WND?A)[0-9][0-9][0-9]|'; $network_regex .= '\b(050d:935b|0bda:8189|0bda:8197)\b'; } -# try to guess at usb rev version from speeds -sub usb_rev { - return if !$_[0] || ! main::is_numeric($_[0]); - my $rev; - if ($_[0] < 2){$rev = '1.0';} - elsif ($_[0] < 13){$rev = '1.1';} - elsif ($_[0] < 481){$rev = '2.0';} - elsif ($_[0] < 5001){$rev = '3.0';} - elsif ($_[0] < 10001){$rev = '3.1';} - elsif ($_[0] < 20001){$rev = '3.2';} - elsif ($_[0] < 40001){$rev = '4.0';} - return $rev; + +# For linux, process rev, get mode. For bsds, get rev, speed. +# args: 0: sys/bsd; 1: speed_si; 2: speed_iec; 3: rev; 4: rev_info; 5: rx lanes; +# 6: tx lanes +# 1,2,3,4 passed by reference. +sub version_data { + return if !${$_[1]}; + if ($_[0] eq 'sys'){ + if (${$_[3]} && main::is_numeric(${$_[3]})){ + # as far as we know, 4 will not have subversions, but this may change, + # check how /sys reports this in coming year(s) + if (${$_[3]} =~ /^4/){ + ${$_[3]} = ${$_[3]} + 0; + } + else { + ${$_[3]} = sprintf('%.1f',${$_[3]}); + } + } + # BSD rev is synthetic, it's a hack. And no lane data, so not trying. + if ($b_admin && ${$_[1]} && ${$_[3]} && $_[5] && $_[6] && + ${$_[3]} =~ /^[1234]/){ + if (${$_[3]} =~ /^[12]/){ + if (${$_[1]} == 1.5){ + ${$_[4]} = '1.0';} + elsif (${$_[1]} == 12){ + ${$_[4]} = '1.1';} + elsif (${$_[1]} == 480){ + ${$_[4]} = '2.0';} + } + # Note: unless otherwise indicated, 1 lane is 1rx+1tx. + elsif (${$_[3]} =~ /^3/){ + if (${$_[1]} == 5000){ + ${$_[4]} = '3.2 gen-1x1';} # 1 lane + elsif (${$_[1]} == 10000){ + if ($_[6] == 1){ + ${$_[4]} = '3.2 gen-2x1';} # 1 lane + elsif ($_[6] == 2){ + ${$_[4]} = '3.2 gen-1x2';} # 2 lane + } + elsif (${$_[1]} == 20000){ + if ($_[6] == 1){ + ${$_[4]} = '3.2 gen-3x1';} # 1 lane + elsif ($_[6] == 2){ + ${$_[4]} = '3.2 gen-2x2';} # 2 lane + } + # just in case rev: 3.x shows these speeds + elsif (${$_[1]} == 40000){ + if ($_[6] == 1){ + ${$_[4]} = '4-v1 gen-4x1';} # 1 lane + elsif ($_[6] == 2){ + ${$_[4]} = '4-v1 gen-3x2';} # 2 lane + } + elsif (${$_[1]} == 80000){ + ${$_[4]} = '4-v2 gen-4x2'; # 2 lanes + } + ${$_[4]} = main::message('usb-mode-mismatch') if !${$_[4]}; + } + # NOTE: no realworld usb4 data, unclear if these gen are reliable. + # possible /sys will expose v1/v2/v3. Check future data. + elsif (${$_[3]} =~ /^4/){ + # gen 2: 10gb x 1 ln + if (${$_[1]} < 10001){ + ${$_[4]} = '4-v1 gen-2x1';} # 1 lane + # gen2: 10gb x 2 ln; gen3: 20gb x 1 ln. Confirm + elsif (${$_[1]} < 20001){ + if ($_[6] == 2){ + ${$_[4]} = '4-v1 gen-2x2';} # 2 lanes + elsif ($_[6] == 1){ + ${$_[4]} = '4-v1 gen-3x1';} # 1 lane + } + # gen3: 20gb x 2 ln; gen4 40gb x 1 ln. Confirm + elsif (${$_[1]} < 40001){ + if ($_[6] == 2){ + ${$_[4]} = '4-v1 gen-3x2';} # 2 lanes + elsif ($_[6] == 1){ + ${$_[4]} = '4-v2 gen-4x1';} # 1 lane + } + # 40gb x 2 ln + elsif (${$_[1]} < 80001){ + ${$_[4]} = '4-v2 gen-4x2';} # 2 lanes + # 3 lanes: 2 tx+tx @ 60gb, 1 rx+rx @ 40gb, wait for data + elsif (${$_[1]} < 120001){ + ${$_[4]} = '4-v2 gen-4x3-asym'; # 3 lanes, asymmetric + } + ${$_[4]} = main::message('usb-mode-mismatch') if !${$_[4]}; + } + } + } + else { + (${$_[1]},${$_[3]}) = prep_speed(${$_[1]}); + # bsd rev hardcoded. We want this set to undef if bad data + ${$_[3]} = usb_rev(${$_[1]}) if !${$_[3]}; + } + # Add Si/IEC units + if ($extra > 0 && ${$_[1]}){ + # 1 == 1000000 bits + my $si = ${$_[1]}; + if (${$_[1]} >= 1000){ + ${$_[1]} = (${$_[1]}/1000) . ' Gb/s'; + } + else { + ${$_[1]} = ${$_[1]} . ' Mb/s'; + } + if ($b_admin){ + $si = (($si*1000**2)/8); + if ($si < 1000000){ + ${$_[2]} = sprintf('%0.0f KiB/s',($si/1024)); + } + elsif ($si < 1000000000){ + ${$_[2]} = sprintf('%0.1f MiB/s',$si/1024**2); + } + else { + ${$_[2]} = sprintf('%0.2f GiB/s',($si/1024**3)); + } + } + } + # print Data::Dumper::Dumper \@_; } + +## BSD SPEED/REV ## +# Mapping of speed string to known speeds. Unreliable, very inaccurate, and some +# unconfirmed. Without real data source can never be better than a decent guess. +# args: 0: speed string sub prep_speed { return if !$_[0]; - my $speed = $_[0]; + my $speed_si = $_[0]; + my $rev; if ($_[0] =~ /^([0-9\.]+)\s*Mb/){ - $speed = $1; + $speed_si = $1; } elsif ($_[0] =~ /^([0-9\.]+)+\s*Gb/){ - $speed = $1 * 1000; + $speed_si = $1 * 1000; } - elsif ($_[0] =~ /usb\s?40/i){ - $speed = 40000;# 4 40gbps + elsif ($_[0] =~ /usb4?\s?120/i){ + $speed_si = 120000;# 4 120Gbps + $rev = '4'; } - elsif ($_[0] =~ /usb\s?20/i){ - $speed = 20000;# 4 20gbps + elsif ($_[0] =~ /usb4?\s?80/i){ + $speed_si = 80000;# 4 80Gbps + $rev = '4'; + } + elsif ($_[0] =~ /usb4?\s?40/i){ + $speed_si = 40000;# 4 40Gbps + $rev = '4'; + } + elsif ($_[0] =~ /usb4?\s?20/i){ + $speed_si = 20000;# 4 20Gbps + $rev = '4'; + } + elsif ($_[0] =~ /usb\s?20|super[\s-]?speed\s?(\+|plus) gen[\s-]?2x2/i){ + $speed_si = 20000;# 3.2 20Gbps + $rev = '3.2'; } # could be 3.2, 20000 too, also superspeed+ elsif ($_[0] =~ /super[\s-]?speed\s?(\+|plus)/i){ - $speed = 10000;# 3.1; # can't trust bsds to use superspeed+ but we'll hope + $speed_si = 10000;# 3.1; # can't trust bsds to use superspeed+ but we'll hope + $rev = '3.1'; } elsif ($_[0] =~ /super[\s-]?speed/i){ - $speed = 5000;# 3.0; + $speed_si = 5000;# 3.0; + $rev = '3.0'; } elsif ($_[0] =~ /hi(gh)?[\s-]?speed/i){ - $speed = 480; # 2.0, + $speed_si = 480; # 2.0, + $rev = '2.0'; } elsif ($_[0] =~ /full[\s-]?speed/i){ - $speed = 12; # 1.1 - could be full speed 1.1/2.0 + $speed_si = 12; # 1.1 - could be full speed 1.1/2.0 + $rev = '1.1'; } elsif ($_[0] =~ /low?[\s-]?speed/i){ - $speed = 1.5; # 1.5 - could be 1.0, or low speed 1.1/2.0 + $speed_si = 1.5; # 1.5 - could be 1.0, or low speed 1.1/2.0 + $rev = '1.0'; } - return $speed; + else { + undef $speed_si; # we don't know what the syntax was + } + return ($speed_si,$rev); } -sub process_power { - return if !${$_[0]}; - ${$_[0]} =~ s/\s//g; - # ${$_[0]} = '' if ${$_[0]} eq '0mA'; # better to handle on output + +# Try to guess at usb rev version from speed. Unreliable, very inaccurate. +# Note: this will probably be so inaccurate with USB 3.2/4 that it might be best +# to remove this feature at some point, unless better data sources found. +# args: 0: speed +sub usb_rev { + return if !$_[0] || !main::is_numeric($_[0]); + my $rev; + if ($_[0] < 2){ + $rev = '1.0';} + elsif ($_[0] < 13) + {$rev = '1.1';} + elsif ($_[0] < 481){ + $rev = '2.0';} + # 5 Gbps + elsif ($_[0] < 5001) + {$rev = '3.0';} + # 10 Gbps, this can be 3.1, 3.2 or 4 + elsif ($_[0] < 10001){ + $rev = '3.1';} + # SuperSpeed 'USB 20Gbps', this can be 3.2 or 4 + elsif ($_[0] < 20001){ + $rev = '3.2';} + # 4 does not use 4.x syntax, and real lanes/rev/speed data source required. + # 4: 10-120 Gbps. Update once data available for USB 3.2/4 speed strings + elsif ($_[0] < 120001){ + $rev = '4';} + return $rev; } -# this is used to create an alpha sortable bus id for main $usb[0] + +## UTILITIES ## +# This is used to create an alpha sortable bus id for main $usb[0] sub bus_id_alpha { my ($id) = @_; $id =~ s/^([1-9])-/0$1-/; $id =~ s/([-\.:])([0-9])\b/${1}0$2/g; return $id; } + +sub process_power { + return if !${$_[0]}; + ${$_[0]} =~ s/\s//g; + # ${$_[0]} = '' if ${$_[0]} eq '0mA'; # better to handle on output +} } # note: seen instance in android where reading file hangs endlessly!!! @@ -33318,6 +34352,7 @@ sub get_wakeups { { package OutputGenerator; my ($items,$subs); + sub generate { eval $start if $b_log; my ($item,%checks); @@ -33403,6 +34438,7 @@ sub generate { assign_data($item); } if ($show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'optical'}){ + UsbData::set(\$checks{'usb'}) if !$checks{'usb'}; $item = item_handler('Drives','disk'); assign_data($item); } @@ -33449,13 +34485,13 @@ sub generate { } eval $end if $b_log; } + ## 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 = CpuItem::get('short'); if (ref $cpu eq 'ARRAY' && scalar @$cpu > 1){ $type = ($cpu->[2]) ? " (-$cpu->[2]-)" : ''; @@ -33511,7 +34547,8 @@ sub short_output { $disk_string = "$used/$size"; } } - $memory ||= 'N/A'; + my $memory = MemoryData::get('short'); + @$memory = ('N/A') if !$memory || !@$memory || !$memory->[0]; # print join('; ', @cpu), " sleep: $cpu_sleep\n"; if (!$loaded{'shell-data'} && $ppid && (!$b_irc || !$client{'name-print'})){ ShellData::set(); @@ -33526,7 +34563,7 @@ sub short_output { main::key($num++,0,0,$speed_key) => $speed, main::key($num++,0,0,$kernel_os) => join(' ', @{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,'Mem') => $memory->[0], 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, @@ -33538,6 +34575,7 @@ sub short_output { main::key($prefix,1,0,'SHORT') => $data, }; } + sub info_item { eval $start if $b_log; my $num = 0; @@ -33567,18 +34605,18 @@ sub info_item { $data->{$data_name}[$index]{main::key($num++,0,2,'wakeups')} = $wakeups if defined $wakeups; } if (!$loaded{'memory'}){ - my $memory = MemoryData::get('splits'); - if ($memory){ - my @temp = split(':', $memory); - $gpu_ram = $temp[3] if $temp[3]; - $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]; + my $memory = MemoryData::get('full'); + if ($memory && @$memory){ + $gpu_ram = $memory->[3] if $memory->[3]; + $total = ($memory->[0]) ? main::get_size($memory->[0],'string') : 'N/A'; + $used = ($memory->[1]) ? main::get_size($memory->[1],'string') : 'N/A'; + $used .= " ($memory->[2]%)" if $memory->[2]; if ($gpu_ram){ $gpu_ram = main::get_size($gpu_ram,'string'); } } - $data->{$data_name}[$index]{main::key($num++,1,1,'Memory')} = $total; + $data->{$data_name}[$index]{main::key($num++,1,1,'Memory')} = ''; + $data->{$data_name}[$index]{main::key($num++,0,2,'available')} = $total; $data->{$data_name}[$index]{main::key($num++,0,2,'used')} = $used; } if ($gpu_ram){ @@ -33688,6 +34726,7 @@ sub info_item { eval $end if $b_log; return $data; } + sub system_item { eval $start if $b_log; my ($cont_desk,$ind_dm,$num) = (1,2,0); @@ -33845,6 +34884,7 @@ sub system_item { eval $end if $b_log; return $data; } + ## Item Processors ## sub assign_data { return if !$_[0] || ref $_[0] ne 'HASH'; @@ -33855,6 +34895,7 @@ sub assign_data { push(@$items,$_[0]); } } + sub item_handler { eval $start if $b_log; my ($key,$item,$arg) = @_; @@ -33865,6 +34906,7 @@ sub item_handler { return {main::key($prefix++,1,0,$key) => $rows}; } } + sub set_subs { $subs = { 'audio' => \&AudioItem::get, diff --git a/inxi.1 b/inxi.1 index 6bb9157..a5edc13 100644 --- a/inxi.1 +++ b/inxi.1 @@ -15,7 +15,7 @@ .\" with this program; if not, write to the Free Software Foundation, Inc., .\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" -.TH INXI 1 "2023\-03\-28" "inxi" "inxi manual" +.TH INXI 1 "2023\-05\-07" "inxi" "inxi manual" .SH NAME inxi \- Command line system information script for console and IRC @@ -131,8 +131,9 @@ keep things simple. Show Audio/sound device(s) information, including device driver. Shows active sound API(s) and sound server(s). -Supported servers/APIs: ALSA, JACK, OSS, NAS, PipeWire, PulseAudio, RoarAudio, -sndio. +Supported APIs: ALSA, OSS, sndio. Supported servers: aRts (artsd), Enlightened +Sound Daemon (esound, esd), JACK, NAS (Network Audio System, nasd), PipeWire, +PulseAudio, RoarAudio, sndiod. Use \fB\-Ax\fR to show all sound APIs/servers detected, including inactive, \fB\-Axx\fR to see API/Server helper daemons/plugin/modules, and \fB\-Aa\fR to @@ -242,7 +243,7 @@ Sample: .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, +Show optical drive data as well as \fB\-D\fR HDD/SSD 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 @@ -250,9 +251,9 @@ 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 +Show HDD/SSD drive info. Shows total drive space and used percentage. The drive +used percentage includes space used by swap partition(s), since those are not +usable for data storage. Also, unmounted partitions are not counted in drive 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 @@ -269,10 +270,10 @@ 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 drive information: Disk ID, type (FireWire, Removable, USB 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 @@ -386,8 +387,10 @@ 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/target, packages). -Note: if \fB\-m\fR is used or triggered, the memory item will show in the main -Memory: report of \fB\-m\fR, not in \fB\Info:\fR. +Note: if \fB\-m\fR or \fB\-tm\fR are active, the memory item will show in the +main Memory: report of \fB\-m\fR/\fB\-tm\fR/, not in \fB\Info:\fR. + +See \fB\-m\fR for explanation of \fBMemory: available:\fR. Raspberry Pi only: uses \fBvcgencmd get_mem gpu\fR to get gpu RAM amount, if user is in video group and \fBvcgencmd\fR is installed. Uses this result to @@ -418,7 +421,10 @@ generally shows BusID / DeviceID (except for tree view, which shows ports). Examples: \fBDevice\-3: 4\-3.2.1:2\fR or \fBHub: 4\-0:1\fR The \fBrev: 2.0\fR item refers to the USB revision number, like \fB1.0\fR or -\fB3.1\fR. +\fB3.1\fR. + +Use \fB\-Jx\fR for basic Si base 10 bits/s speed, \fB\-Jxx\fR for Si and IEC +base 2 Bytes/s speeds. \fB\-Ja\fR adds USB mode. .TP .B \-l \fR, \fB\-\-label\fR @@ -514,7 +520,7 @@ 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 +Note: If \fB\-m\fR is triggered RAM available/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 @@ -532,9 +538,9 @@ Under dmidecode, \fBSpeed:\fR is the expected speed of the memory 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 +\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 +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: @@ -542,7 +548,7 @@ If the detected speed is logically absurd, like 1 MT/s or 69910 MT/s, adds: .nf \fBMemory: - RAM: total: 31.38 GiB used: 20.65 GiB (65.8%) + System RAM: available: 31.38 GiB used: 20.65 GiB (65.8%) Array\-1: capacity: N/A slots: 4 note: check EC: N/A Device\-1: DIMM_A1 type: DDR3 size: 8 GiB speed: 1600 MT/s (800 MHz) Device\-2: DIMM_A2 type: DDR3 size: 8 GiB speed: spec: 1600 MT/s (800 MHz) @@ -555,6 +561,11 @@ If the detected speed is logically absurd, like 1 MT/s or 69910 MT/s, adds: See \fB\-\-memory\-modules\fR and \fB\-\-memory\-short\fR if you want a shorter report. +Note: the \fBSystem Ram: available:\fR is actually the total installed RAM minus +some reserved and kernel code RAM (and in some cases GPU assigned main system +RAM) that is allocated on system boot, and thus is generally less than the +actual physical RAM installed. + .TP .B \-\-memory\-modules\fR, \fB\-\-mm\fR Memory (RAM) data. Show only RAM arrays and modules in Memory report. @@ -657,6 +668,8 @@ APT distros like PCLinuxOS or Alt\-Linux) \fBEOPKG\fR (Solus) +\fBNETPKG\fR (Zenwalk/Slackware) + \fBNIX\fR (NixOS + other distros as alternate package manager) \fBPACMAN\fR (Arch Linux, KaOS + derived versions) @@ -671,10 +684,18 @@ APT distros like PCLinuxOS or Alt\-Linux) \fBPORTS\fR (OpenBSD, FreeBSD, NetBSD + derived OS types) +\fBSBOPKG\fR (Slackware + derived versions) + +\fBSBOUI\fR (Slackware + derived versions) + \fBSCRATCHPKG\fR (Venom + derived versions) \fBSLACKPKG\fR (Slackware + derived versions) +\fBSLAPT_GET\fR (Slackware + derived versions) + +\fBSLPKG\fR (Slackware + derived versions) + \fBTCE\fR (TinyCore) \fBURPMI\fR (Mandriva, Mageia + derived versions) @@ -763,6 +784,8 @@ Make sure that there is no space between letters and numbers (e.g. write as If the \fB\-I\fR or \fB\-m\fR lines are not triggered, will also show the system RAM used/total information. +See \fB\-m\fR for explanation of \fBRAM: total\-available:\fR. + .TP .B \-t cm\fR \- CPU+memory. With \fB\-x\fR, shows also CPU or memory for that process on @@ -833,7 +856,7 @@ min/max speeds, if available) + \fB\-G\fR + basic Disk + \fB\-I\fR. .TP .B \-v 4 \- Adds partition size/used data (\fB\-P\fR) for (if present): \fB/ /home /var/ -/boot\fR. Shows full disk data (\fB\-D\fR) +/boot\fR. Shows full drive data (\fB\-D\fR) .TP .B \-v 5 @@ -1286,7 +1309,7 @@ doas users: see \fBman doas.conf\fR for setup. You can force use of \fBhddtemp\fR for all drives using \fB\-\-hddtemp\fR. -\- If free LVM volume group size detected (root required), show \fBlvm-free:\fR +\- If free LVM volume group size detected (root required), show \fBlvm\-free:\fR on Local Storage line. This is how much unused space the VGs contain, that is, space not assigned to LVs. @@ -1366,15 +1389,21 @@ discover those. available. .TP -.B \-x \-j\fR, \fB\-x \-\-swap\fR +.B \-x \-j\fR (\fB\-\-swap\fR) Add \fBmapper:\fR. See \fB\-x \-o\fR. .TP .B \-x \-J\fR (\fB\-\-usb\fR) \- For Devices, adds driver(s). +\- Adds, if available, USB speed in base 10 bits/s (Si) units \fBMb/s\fR or +\fBGb/s\fR (may be incorrect on BSDs due to non reliable data source). These are +base 10 bits per second. This unit corresponds to the standard units the USB +consortium uses to indicate speeds, but not to how most of the rest of your +system reports sizes. Use \fB\-Jxx\fR to add base 2 IEC Byte/second speeds. + .TP -.B \-x \-L\fR, \fB\-x \-\-logical\fR +.B \-x \-L\fR (\fB\-\-logical\fR) \- Adds \fBdm: dm-x\fR to VG > LV and other Device types. This can help tracking down which device belongs to what. @@ -1450,6 +1479,8 @@ found for each distribution system base detection. \- Adds PCIe speed and lanes item (Linux only, if detected). +\- Adds for USB devices USB rev, speed, lanes (lanes Linux only). + \- Adds \fBwith: [item] \fBstatus: [state/plugin]\fR helper daemons/plugins for the sound API/server. @@ -1459,9 +1490,9 @@ the sound API/server. .TP .B \-xx \-D\fR -\- Adds disk serial number. +\- Adds HDD/SSD drive serial number. -\- Adds disk speed (if available). This is the theoretical top speed of the +\- Adds drive 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 @@ -1478,7 +1509,9 @@ 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. +\- Adds HDD/SSD drive duid, if available. Some BSDs have it. + +\- Adds for USB drives USB rev, speed, lanes (lanes Linux only). .TP .B \-xx \-E\fR (\fB\-\-bluetooth\fR) @@ -1490,6 +1523,8 @@ if applicable) for each device. \- Adds PCIe speed and lanes item (Linux only, and if PCIe bluetooth, which is rare). +\- Adds for USB devices USB rev, speed, lanes (lanes Linux only). + .TP .B \-xx \-G\fR Triggers much more complete Screen/Monitor output. @@ -1517,6 +1552,8 @@ or more \fBMonitors\fR. \- Adds PCIe speed and lanes item (Linux only, and if PCIe device and detected). +\- Adds for USB devices USB rev, speed, lanes (lanes Linux only). + \- Adds output port IDs, active, off (connected but disabled, like a closed laptop lid) and empty. Example: @@ -1609,8 +1646,12 @@ swap types (for \fB\-j\fR). .B \-xx \-J\fR (\fB\-\-usb\fR) \- Adds vendor:chip id. +\- Adds USB lanes. Uses tx (transmit) lane count for total unless rx and tx +counts are different (eg: \fBlanes: rx: 2 tx: 4\fR). Linux only. +See \fB\-Ja\fR for sample output. + .TP -.B \-xx \-L\fR, \fB\-xx \-\-logical\fR +.B \-xx \-L\fR (\fB\-\-logical\fR) \- Adds internal LVM Logical volumes, like raid image and meta data volumes. \- Adds full list of Components, sub\-components, and their physical devices. @@ -1647,6 +1688,8 @@ ROM size if using \fBdmidecode\fR. \- Adds PCIe speed and lanes item (Linux only, and if PCIe device and detected). +\- Adds for USB devices USB rev, speed, lanes (lanes Linux only). + .TP .B \-xx \-r\fR \- Adds to \fBPackages:\fR info. See \fB\-Ixx\fR @@ -1721,16 +1764,16 @@ CPU does not support SMT. .TP .B \-xxx \-D\fR -\- Adds disk firmware revision number (if available). +\- Adds HDD/SSD drive firmware revision number (if available). -\- Adds disk partition scheme (in most cases), e.g. \fBscheme: GPT\fR. +\- Adds drive 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 type (\fBHDD\fR/\fBSSD\fR), rotation speed (in some but not all -cases), e.g. \fBtype: HDD rpm: 7200\fR, or \fBtype: SSD\fR if positive SSD +\- Adds drive tech (\fBHDD\fR/\fBSSD\fR), rotation speed (in some but not all +cases), e.g. \fBtech: HDD rpm: 7200\fR, or \fBtech: SSD\fR if positive SSD identification was made. If no HDD, rotation, or positive SSD ID found, shows -\fBtype: N/A\fR. Not all HDD spinning disks report their speed, so even if they +\fBtech: N/A\fR. Not all HDD spinning disks report their speed, so even if they are spinning, no rpm data will show. .TP @@ -1784,8 +1827,6 @@ uses the \fBwhoami\fR test. \- Adds \fBinterfaces:\fR for non hub devices. -\- Adds, if available, USB speed in \fBMbits/s\fR or \fBGbits/s\fR. - \- Adds, if present, USB class ID. \- Adds, if non 0, max power in mA. @@ -1870,6 +1911,8 @@ shown). \- Adds list of detected audio server tools (\fBtools: [tools]\fR) to API/Server lines, like alsamixer, jack_control, pactl, pavuctl, pw-cli, sndioctl, etc. +\- Adds for USB devices USB mode (Linux only). + .TP .B \-a \-C\fR .br @@ -2042,8 +2085,11 @@ 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 sizes -if necessary. Adds in drive temperature for some drives as well, and other -useful data. +if necessary. + +\- Adds for USB drives USB mode (Linux only). + +\- Adds in drive temperature for some drives as well, and other useful data. .TP .B \-a \-E\fR (\fB\-\-bluetooth\fR) @@ -2055,6 +2101,8 @@ and Service Classes. or lanes, \fBlink\-max: gen: speed: lanes:\fR (only items different from primary shown. Bluetooth PCIe rare). +\- Adds for USB devices USB mode (Linux only). + .TP .B \-a \-G\fR \- Adds, if present, possible \fBalternate:\fR kernel modules capable of driving @@ -2077,6 +2125,8 @@ Includes extended non free Nvidia legacy informatin (Linux and Nvidia only), and issues, shows extra data that can help diagnose/debug. Adds \fBcode:\fR item if found and not the same as \fBarch:\fR. +\- Adds for USB devices USB mode (Linux only). + .nf \fBinxi \-Gaz Graphics: @@ -2172,6 +2222,7 @@ Graphics: API: GBM/EGL Message: Wayland GBM/EGL data currently not available. .fi + .TP .B \-a \-I\fR \- Adds to Packages number of lib packages detected per package manager. Also @@ -2193,7 +2244,7 @@ rc\-service rcctl service sv /etc/rc.d /etc/init.d\fR. Can be 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] +.B \-a \-j\fR (\fB\-\-swap\fR), \fB\-a \-P\fR [swap], \fB\-a \-P\fR [swap] \- Adds swappiness and vfs cache pressure, and a message to indicate if the value is the default value or not (Linux only, and only if available). If not the default value, shows default value as well, e.g. @@ -2209,7 +2260,38 @@ For \fB\-j\fR row 1 output: \- Adds device kernel major:minor number (Linux only). .TP -.B \-a \-L\fR +.B \-a \-J\fR (\fB\-\-usb)\fR +\- Adds, if available, USB speed in IEC units \fBMiB/s\fR or \fBGiB/s\fR (may +be incorrect on BSDs due to non reliable data source). These are base 2 Bytes +per second. + +\- Adds USB mode (Linux only), which is the technical terms the USB group uses +to describe USB revisions. In cases where speed and rev are an unknown +combination, (and probably at least one is wrong) shows message. + +There are no granular data sources in BSDs for accurate revision/lane/speed +information, so mode cannot be determined. + +Sample: +.nf +\fB +Hub\-1: 1\-0:1 info: hi\-speed hub with single TT ports: 14 rev: 2.0 + speed: 480 Mb/s (57.2 MiB/s) lanes: 1 mode: 2.0 chip\-ID: 1d6b:0002 + class\-ID: 0900 +Device\-1: 1-4:2 info: Wacom ET\-0405A [Graphire2 (4x5)] type: mouse + driver: usbhid,wacom interfaces: 1 rev: 1.1 speed: 1.5 Mb/s (183 KiB/s) + lanes: 1 mode: 1.0 power: 40mA chip\-ID: 056a:0011 class\-ID: 0301 +Hub\-2: 2\-0:1 info: Super\-speed hub ports: 8 rev: 3.1 + speed: 10 Gb/s (1.16 GiB/s) lanes: 1 mode: 3.2 gen\-2x1 chip\-ID: 1d6b:0003 + class\-ID: 0900 +Device\-1: 2\-8:5 info: SanDisk Ultra type: mass storage driver: usb\-storage + interfaces: 1 rev: 3.0 speed: 5 Gb/s (596.0 MiB/s) lanes: 1 mode: 3.2 gen\-1x1 + power: 896mA chip\-ID: 0781:5581 class\-ID: 0806 + serial: \fR +.fi + +.TP +.B \-a \-L\fR (\fB\-\-logical) \- 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. @@ -2231,6 +2313,8 @@ knows could possibly be used instead. or lanes, \fBlink\-max: gen: speed: lanes:\fR (only items different from primary shown). +\- Adds for USB devices USB mode (Linux only). + .TP .B \-a \-o\fR \- Adds device kernel major:minor number (Linux only). diff --git a/inxi.changelog b/inxi.changelog index c189752..321ecaf 100644 --- a/inxi.changelog +++ b/inxi.changelog @@ -1,3 +1,489 @@ +================================================================================ +Version: 3.3.27 +Patch: 00 +Date: 2023-05-07 +-------------------------------------------------------------------------------- +RELEASE NOTES: +-------------------------------------------------------------------------------- + +Completion of the audio fixes and improvements of 3.3.26. Added less common +sound servers like EsounD and aRts, and made state reports more accurate for +ALSA. + +Major USB code and data upgrades/refactors. The USB changes prepare inxi for USB +4, and adds lanes and Si/IEC speeds to the report. It is important to determine +what USB mode you are running in with 3.x and 4. These changes conform more +closely to how the USB consortium wants USB speeds refered to. + +With more robust USB data, this data now appears in a similar form as pcie: data +for Devices, -A, -E, -G, -N, and for -D drives, as usb: plus rev, speed, lanes, +mode, with the -xx/-a options, like pcie. This has been a long standing +oversight and weakness of inxi USB and Device data, but now the two are fully +integrated, including for drives, which was quite tricky to get working. + +Added netpkg and Zenwalk support to packages and repos. Also added repos support +for sbopkg and slpkg, and updated package tools for Slackware. + +And more distros added to system base feature, and a few more for main ID. + +Improved --recommends report quite a bit, now it's more granular for missing +packages and package manager reports, and also fixed a long standing missing +current shell + version issue. Added the final package manager type, pkgtool +(Slackware), that will be supported, which makes for 4, which is enough. Note +that other package managers can be added following the documentation +instructions for packagers, but this is enough for out of the box pm handling. + +Fixed a long standing oddity with how free / /proc/meminfo report MemTotal vs +the actual physical RAM. I believe this issue also showed with GPU assigned RAM, +but now for all but short form, shows Memory/RAM: available: ... used: ... + +-------------------------------------------------------------------------------- +SPECIAL THANKS: + +1. To the Slackware people at linuxquestions.org forums, who helped, again, on +this audio feature, even finding current or not too old systems that use some of +the new / old audio servers (EsoundD) running in the wild, which I never +expected to see. And also for exposing some weak spots in the USB advanced +logic, and helping with the sbopkg and slpkg repo logic and tools reports. + +2. To the Manjaro forum users, for providing cases that show where inxi can be +improved. The audio server/api issue, the current USB 3/4 upgrade, were +initiated by threads pointing to things that could be improved in inxi. So I +guess the real thanks are for using inxi enough to trigger cases that show where +it's weak or can be better. Note that this requires that I follow roughly their +forums, however I only look at threads that seem like they might be of general +interest, or which suggest a possible weak spot in inxi, and I don't follow them +consistently. More reliable is to file github issues, since I will always see +those. + +-------------------------------------------------------------------------------- +KNOWN ISSUES: + +1. DesktopData: at one point, BunsenLabs Debian OpenBox had XDG_CURRENT_DESKTOP +set to XFCE, which it isn't, but inxi can't work around such hacks, plus I don't +even know if Bunsen is around anymore anyway. + +2. DesktopData: CODE 1 reminds us that the time to depend on x tools like xprop +for anything re desktop/wm detections is fast drawing to a close, true Wayland +will not have xprop, unless it's running on xwayland, which is not something +that should be relied on. Maybe recheck Moksha/Enlightenment which depend on +xprop for version detection. + +The list of xprop detected wm/desktops in get_env_xprop_misc_data() is almost +all X only wm/desktops, so those should be safe unless one of them decides to +work on a wayland comositor. + +3. BSD: ongoing weaknesses in BSD data sources make maintaining feature parity +impossible, but I am trying to get the BSD data as clean and consistent as +possible. I wish this were not the case, but the fact is, /sys is expanding and +creating excellent and reliable data sources with every major Linux kernel +update, and so far nothing comparable has appeared in the BSDs. This is just +reality, it's not a condemnation, but something like the /proc then /sys file +systems are an excellent idea, well worth emulating. + +4. For the RAM available/total clarification, there's a slight issue because +free/meminfo show MemAvailable as Free for use RAM, but dmesg shows available +meaning what was available to the system during boot, minus the reserved +percentage. Since we needed one term, available to System offers the closest +in terms of technical precision without being too verbose. Technically available +in this context means: total physical minus 'kernel code' minus 'reserved'. + +-------------------------------------------------------------------------------- +BUGS: + +1. CheckRecommends: See Fix 6b, more or less a bug, but really just a fix. + +2. AUDIO: for USB devices, put extra data into row 0, no matter which row the +USB device is. This led to the extra data for USB being assigned to the wrong +row. Sigh. + +3. OptionsHandler: When show{'ram'} was set, for bsd, set use{'bsd-raid'}, which +makes both show raid and ram fail for BSD. Oops. User mode RAM data only seen in +OpenBSD so far. This made loading $dboot{'ram'} fail, and any raid as well, +sigh, unless -m was also tripped. + +-------------------------------------------------------------------------------- +FIXES: + +1. DistroData: typo for Arch base: was ctios, was supposed to be ctlos. + +2a. DesktopData: found case where xprop -root not present (Void Linux), so xfce +test failed. Split to new function dedicated to xfce detection that doesn't use +xprop data. Also, XFCE is working on their Wayland version, which would in +theory not even have xprop by default. + +Also, the base version number test for xfce depended on xprop, but +xprop doesn't even have that xfce version data anymore, so just checking if +xfce(4|5|)-panel exist and assigning primary version based on that test. + +2b. DesktopData: Also see See CODE 1a,1b for further xprop and test fixes that +could have led to false positive or negative test conditions for the items that +used xprop tests. These tests are all xprop agnostic now, if it's there, they +will use it, if not, do the best they can. + +3. PackageData: fixed legacy dpkg-query, old version did not support -f shortcut +for --showformat. This made dpkg package listing fail. + +4a. GRAPHICS: Added legacy XFree86.0.log to X log path detection, that was an +oversight. Also added legacy module syntax _drv.o (not _drv.so). This gets X +driver data now for very old systems. + +4b. GRAPHICS: fixed corner case where no x driver data, running as root, was not +supposed to show 'note: X driver n/a' message, that was a holdover from before +driver output was cleaned up and driver: N/A shows when no drivers at all found. +Just forgot to remove it when doing recent updates in the driver section, maybe? + +5. REPOS/PackageData: For netpkg Zenwalk Slackware systems, showed only slackpkg +repo data, empty, and showed the Slackware pm, not netpkg for pm. See +Enhancements 5, 6. + +6. REPOS: removed slapt_get file /etc/slapt-get/pubring.kbx, that's not a repo +file. Thanks chrisreturn for pointing that out. + +7a. CheckRecommends: See also CODE 6. Fixed case where > 1 package manager is +detected on system, now lists them one by one for detected, and shows package +install options as well. Before only picked first detected, which could lead +to wrong results for Missing Package lists. + +7b. CheckRecommends: Fixed glitch, forgot to update the current shell/version +when ShellData was refactored, this led to no current shell + version showing +up in recommends core tools report. + +8. RAM: fixed speed_mapper string match to allow for older syntaxes. This is as +far as known OpenBSD only, from dboot data. Matches then converts PC2700 to +PC-2700 which then allows for mapping. + +9. RAM/PROCESSES/INFO/SHORT: Finally tracked down a long time oddity, where for +example: + RAM: total: 31.28 GiB +does not match 32 GiB physical installed. This is because that is the total +available after kernel and system reserved RAM is deducted, and in some cases, +GPU allocated RAM. There are also corner cases where the listed amount can be +less due to physical RAM damage, but that's uncommon. + +Added explanation of why it's different, and what available is referring to in +man -m/--memory. + +Changed -m, -tm to show: + +System RAM: available: 31.28 GiB used 26.23 GiB (83.9%) + +and -I to show: + +Memory: available: 31.28 GiB used 26.23 GiB (83.9%) + +You can get the 'reserved' and 'kernel code' data from dmesg, but since Debian +made that root/sudo tool, can't count on being able to parse that out of dmesg, +plus you can never count no dmesg anyway since it can get overwritten by kernel +oops or wonky device etc. inxi doesn't use dmesg data for Linux for this reason. + +... [ 0.000000] Memory: 32784756K/33435864K available (10252K kernel code, +1243K rwdata, 3324K rodata, 1584K init, 2280K bss, 651108K reserved, 0K +cma-reserved) + +Also removed Raspberry Pi video RAM added back in to total now that it's clear +it's what is available. This may also make systems with GPU using system RAM +more correct. + +9. SENSORS: sensors /sys tried to create concatenated string with $unit $value +but these are not necessarily defined, that needed to be protected with defined +tests. + +-------------------------------------------------------------------------------- +ENHANCEMENTS: + +1a. AUDIO: JACK: added helper nsmd (new session manager), and its recommended +gui agordejo. That's the drop in replacement for non-session-manager, the dev of +which apparently lost interest in that project. But the ID method will work fine +for for either, since both ran as nsmd. + +1b. AUDIO: PULSE: added pulseaudio-alsa plugin support for helpers. This is like +pipewire-alsa plugin, just alsa config file. Only seen in Arch Linux so far, but +if others use similar paths for the glob pattern, they will also work fine. + +Also added pulseaudio-esound-compat plugin, which is easier to detect with +/usr/bin/esdcompat. + +Also added paman, pulseaudio manager. + +1c. AUDIO: ESOUND,ARTS: added legacy esd (EsounD aka: Enlightened Sound Daemon) +and aRts sound server support, with basic help/tools. These are quite old, but +are still occasionally seen in the wild on newer systems, surprisingly enough. + +1d. AUDIO: ALSA: added alsactl to alsa tools. Missed that one, it's an /sbin +type utility. + +1e. AUDIO: ALSA: First try at ALSA compiled in but inactive report, previously +depended on active only state of the API. Now uses compiled in SND_ kernel +switch using the /boot/config-[kernel] file, which is a big expensive parse but +only will activate on Linux kernels with no /proc/asound present. This fallback +fails if kernel config file not present: /boot/config-$(uname -r). + +1f. AUDIO: OSS: added tool ossctl. + +1g. AUDIO: NAS: added helper: audiooss which is an OSS compat layer. + +2a. DistroData: added Arch base distros: ArchEX, Bridge Linux, Condres OS, +Feliz, LiriOS, Magpie, Namib, Porteus, RevengeOS, SalientOS, VeltOS. + +None of these are verified. Some don't exist anymore. +Source: https://www.slant.co/topics/7603/~arch-linux-based-distributions + +2b. DistroData: added ubuntu lunar 23-4 release id. + +2c. DistroData: added porteux, added porteux, zenwalk to slackware systembase + +3. DesktopData/GRAPHICS: added Smithay Wayland compositor. Not verified. + +4a. UsbData/UsbItem: added USB lanes (-Jxx) and mode (-Ja), to add more useful +data about USB revision and mode names the USB group has created. Otherwise it's +too difficult to try to explain it. Note that -Jxx lanes follows other inxi +items that show PCIe lanes as an -xx item to try to keep it consistent. + +This also consolidates the bsd and linux data sources, see CODE 5. + +Note modes and lanes are Linux only because the revision number, lanes, and +speed used to determine mode are only natively available in Linux as actual +internal data values. If this changes BSD support will be added in the future. + +The BSD rev and speed data is synthesized completely by inxi using some string +values, and thus is not reliable, which means that pretending inxi can get this +granular with data that is not coming directly from the system itself is +probably not a good idea. + +Following wikipedia mode names: https://en.wikipedia.org/wiki/USB4 + +These are the known possible combinations: +rev: 1.0 mode: 1.0 lanes: 1 speed: 1.5 Mbps +rev: 1.1 mode: 1.0 lanes: 1 speed: 1.5 Mbps +rev: 1.1 mode: 1.1 lanes: 1 speed: 12 Mbps +rev: 2.0 mode: 1.0 lanes: 1 speed: 1.5 Mbps +rev: 2.0 mode: 1.1 lanes: 1 speed: 12 Mbps +rev: 2.0 mode: 2.0 lanes: 1 speed: 480 Mbps +rev: 2.1 mode: 2.0 lanes: 1 speed: 480 Mbps +rev: 3.0 mode: 3.2 gen-1x1 lanes: 1 speed: 5 Gbps +rev: 3.0 mode: 3.2 gen-1x2 lanes: 2 speed: 10 Gbps +rev: 3.1 mode: 3.2 gen-1x1 lanes: 1 speed: 5 Gbps +rev: 3.1 mode: 3.2 gen-1x2 lanes: 2 speed: 10 Gbps +rev: 3.1 mode: 3.2 gen-2x2 lanes: 2 speed: 20 Gbps [seen this case] +rev: 3.2 mode: 3.2 gen-1x1 lanes: 1 speed: 5 Gbps [wrong rev: seen this case] +rev: 3.2 mode: 3.2 gen-1x2 lanes: 2 speed: 10 Gbps [wrong rev: possible case] +rev: 3.2 mode: 3.2 gen-2x1 lanes: 1 speed: 10 Gbps +rev: 3.2 mode: 3.2 gen-2x2 lanes: 2 speed: 20 Gbps +rev: 3.2 mode: 4-v1 gen-3x2 lanes: 2 speed: 40 Gbps [not seen, but possible] +rev: 4 mode: 4-v1 gen-2x1 lanes; 1 speed: 10 Gbps +rev: 4 mode: 4-v1 gen-2x2 lanes: 2 speed: 20 Gbps +rev: 4 mode: 4-v1 gen-3x1 lanes: 1 speed: 20 Gbps +rev: 4 mode: 4-v2 gen-3x2 lanes: 2 speed: 40 Gbps +rev: 4 mode: 4-v2 gen-4x1 lanes: 1 speed: 40 Gbps +rev: 4 mode: 4-v2 gen-4x2 lanes: 2 speed: 80 Gbps +rev: 4 mode: 4-v2 gen-4x3-asymmetric lanes: 3 up, 1 down speed:120 Gbps + +I believe 120Gbps takes the 2 lanes of tx/rx and converts 2 rx lanes to tx so +the entire lane is dedicated to transmit. and the third lane is dedicated to rx. + +Includes error message for unknown usb 3/4 rev/speed match combos. These can be +bad hardware self reporting or unknown other issues. + +4b. USB: Added Si/IEC speeds (base 2, base 10). -Ja triggers extra IEC, base 2 +Bytes (xxx [MG]iB/s). -Jx triggers basic standard Si xxx [MG]b/s base 10 bits. + +5a. PackageData: added netpkg as package tool. This stores data in same location +as slackpkg, but assume if exists directory /var/netpkg, then the system is +using netpkg as pm, not slackpkg. + +5b. PackageData: added Slackware sbopkg, sboui as tools for pkgtool and netpkg. + +6a. REPOS: added netpkg (Zenwalk Slackware based pm) repo report. + +6b. REPOS: added sbopkg basic repo report. This handles both value syntax types, +as well as the ability of /root config file to overwrite /etc config repo. + +6c. REPOS: added slpkg repo report. This handles their old and newer syntax. + +7a. CheckRecommends: For Slackware users, added pkgtool missing package name, +also will use netpkg so hopefully Zenwalk uses same package names. + +7b. CheckRecommends: Added radeon to kernel modules checks. + +8. AUDIO/BLUETOOTH/DRIVES/GRAPHICS/NETWORK: For USB, -[ADEGN]xx adds rev, speed, +lanes. -[ADEGN]a adds mode. + +9. RAM: Updated RAM PC DDR in speed_mapper(), which is as far as I know only +used by OpenBSD, which allows for MT/s speeds as non-root user, which is nice. +That list hadn't been updated in a long time, so filled out DDR 1-5 PCx-yyyy +ids. + +-------------------------------------------------------------------------------- +CHANGES: + +1a. USB: For -Jxy1, speed is now a child of rev: parent. This goes along with +mode: and lanes: being children of rev:. This follows how USB consortium wants +to refer to USB revisions now: by speed, lanes, and modes, the latter being the +technical term, the speed being the marketing term. + +1b. USB: If no speed data found, show N/A. This should almost never happen +except for very old Linux and rarely with BSD. + +1c. USB: Device type is lower cased except for abbreviations (type-C, HID). This +makes it more consistent as a value. + +1d. USB: Show basic Si speed with -Jx, and adds new IEC speed with -Ja. + +2. CheckRecommends: See ENHANCEMENT, CODE 6. Now showing row by row package +managers and missing packages, by package manager(s). + +3. DRIVES: Changed long standing redundant use of 'type': +type: USB ... type: HDD +to: +type: USB ... tech: HDD +'tech:' means the technology used, HDD, SDD, and if we can ever figure out how +to detect it, Hybrid Hard Drive (HHD), + +4. AUDIO/BLUETOOTH/DRIVES/GRAPHIC/NETWORK: moved 'type: USB' pair to after +driver for -A/-E/-G/-N, which allows it to be the parent of the new USB data +block. Negative is it moves it a bit further back in the line. + +For Drives, it moves it from after /dev.. maj-min to after block-size, However, +with -D/-Dx, it's last in the line, which is nice. This is the only way I could +find to make it more consistent across all possible USB device/drive type +reports. + +5. INFO/RAM/PROCESSES: Changed -I: + +Memory: [total] used: +to: +Memory: available: [total] used: + +Changed -tm/-m to be consistent: + +Memory: RAM: total: .. used.. +to: +Memory: System RAM: available: ... used:.. + +This corrects a long standing inaccuracy where MemTotal is not actually the full +system RAM, but is the RAM minus reserved stuff for system and kernel, and GPU +memory in some cases. + +-------------------------------------------------------------------------------- +DOCUMENTATION: + +1a. DOCS: docs/inxi-audio.txt: ongoing updates, adding more information, more +on helpers, detection methods, etc. + +1b. DOCS: New: docs/inxi-usb.txt: USB info, update, added more, a work in +progress. + +1c. DOCS: docs/inxi-custom-recommends.txt: name in inxi comment did not match, +and updated to new comment cleaned up syntax in example. Fixed inxi comment file +name. + +1d. DOCS: New: docs/inxi-unit-handling.txt: To document how inxi handles +size/speed data internally, and ideally, to help integrate all those methods +into one big tool one day, not spread across many area. + +1e. DOCS: New: docs/inxi-repo-package-manager.txt: To start to document arcana +and methods and commands and outputs for package managers. Since this is a late +start, will take time to complete, but better late than never. + +2a. MAN/OPTIONS: updated for USB -Jx, -Jxx, -Ja, adding lanes, mode, iec speed +items. + +2b. MAN/OPTIONS: fixed error which had USB speed as -Jxxx instead of -Jxx. Also +then changed speed to be -Jx. + +2c. MAN/OPTIONS: updated for repos for SBOPKG, SBOUI, SLPKG, and added +SLAPT_GET, I'd forgotten that one. + +2d. MAN/OPTIONS: updated for -xx[ADEGN] USB rev, speed, lanes; for -a[ADEGN] +updated for USB mode. + +2e. MAN/OPTIONS: updated for memory available/used changed. + +3. MAN: fixed some inconsistent use of short/long form display in extra data +options. + +-------------------------------------------------------------------------------- +CODE: + +1a. DesktopData: New function for xfce only detections, turns out xprop is not +necessarily installed, Void Linux for example had failed ID. Old version +required xprop to do the tests, which was not robust and failed in this case. +Function: get_env_xfce_data(). Also made xprop data optional for all the +xxx_xprop_data desktop tests, not just some of them. This will forward proof +the desktops + +1b. DesktopData: Fixed bad parens in test cases, was not correctly organized. +if (a || b || (c || d) && e) +was supposed to be: +if (a || b || ((c || d) && e)) +Odd how those types of glitches creep in, one fix is also to just make the lines +break more reasonably so the conditions are easier to parse visually. + +2a. DEBUGGER: Added /etc/X11/XF86Config-4 xorg conf file to debugger. + +2b. DEBUGGER: audio_data(): added audio server versions to cover all known ones. + +3. MemoryData: changed all $memory to array references, got rid of split : +separators, which were clearly legacy items leftover from bash/gawk days. Also +changed MemoryData::get('splits') to get('full') to reflect this change. + +This change should be transparent though it may introduce corner case undefined +value situation but that should not happen since array values are defined first. + +4. UsbData: Refactor of usb speed, rev, added lanes, mode. Refactored most of +the bsd/linux rev/speed logic, merged some of bsd speed/rev into the new +version_data() function, which loads all the data based on what is calling it. +This helps consolidate the logic across usb data sources. + +5a. GLOBAL: made functions/methods use same comment syntax for args: + args: 0:...; 1:... +always starting with 0, to match array index. Same syntax for return array index +values. In some cases simply note a variable is passed by ref: + args: $value passed by reference. + +5b. GLOBAL: made all sub/functions/methods follow the same spacing syntax. This +seems to be a good compromise for space/readability. Note that adding in these +new lines added about 400 lines to the total length, plus the line breaks that +were already there. Yes, inxi has a lot of sub routines! aka functions and +sometimes aka methods. + +[empty line] +[comments] +sub [name] { + +Packages/classes now also all follow the same spacing rules: + +[empty line] +[comments] +# Package Name +{ +package [name]; +[empty line] +[comments] +sub [name] { +... +} +} + +Internally, subs generally do not use any empty lines unless it makes sense to +do so for some specific reason. + +5c: GLOBAL: made start of sub comments be upper case, I have a bad habit of +typing comments in lower case, easier to read if it's reads like a normal +sentence. + +6. CheckRecommends: refactored entire items logic, set global hash for test +items. Made support > 1 detected package manager. + +7. REPOS: cleaned up comments for package manager/repo blocks. + +8. SENSORS: sensors_sys failed to reset to undefined $unit and $value, and also +failed to test if they were defined before using them in concatenation. + +-------------------------------------------------------------------------------- +-- Harald Hope - Sun, 7 May 2023 14:00:00 -0700 + ================================================================================ Version: 3.3.26 Patch: 00