From 75433a383afce30c07ab67ea1f2138212cc174a2 Mon Sep 17 00:00:00 2001 From: Harald Hope Date: Mon, 15 Mar 2021 18:44:00 -0700 Subject: [PATCH] Huge upgrade!! Bug Fixes!! Refactors!!! BSDs!!! More BSDs!!! raspberry pi!! New Features!!! Enhanced old features!!! Did I mention bluetooth?! USB? Audio? No? well, all hugely upgraded! ------------------------------------------------------------------------ BUGS: 1. Sadly, 3.3.01 went out with a bug, forgot to remove a debugger, resulted in hardcoded kernel compiler version always showing. Note that there is a new inxi-perl/docs/inxi-bugs.txt file to track such bugs, and matched to specific tagged releases so you know the line number and items to update to fix it. 2. Typo in manjaro system base match resulted in failing to report system base as expected. ------------------------------------------------------------------------ KNOWN ISSUES BUT CAN'T OR WON'T BE FIXED: 1. OpenBSD made fvwm -version output an error along with the version, and not in the normal format for standard fvwm, this is just too complicated to work around for now, though it could be in theory by creating a dedicated fvwm-oBSD item in program_values. But that kind of granularity gets too hard to track, and they are likely to change or fix this in the future anyway. Best is they just restore default -version output to what it is elsewhere, not nested in error outputs. 2. Discovered an oddity, don't know how widespread this is, but Intel SSDs take about 200 milliseconds to get the sys hwmon based drive temps, when it should take under a millisecond, this may be a similar cause as those drives having a noticeable SMART report delay, not sure. This is quite noticeable since 200 ms is about 15% of the total execution time on my test system. ------------------------------------------------------------------------ FIXES: 1. For --recommends, added different rpm SUSE xdpyinfo package name. 2. Distro Data: added double term filter for lsb-release due to sometimes generating repeated names in distro. 3. Packages: fix for appimage package counts. 4. Desktop: fixed ID for some wm when no xprop installed, fallback to using @ps_cmd detections, which usually work fine. 5a. When swap used was 0, showed N/A, fixed to correctly show 0 KiB. 5b. If no swap devices found, BSDs were not correctly showing no swap data found message. Corrected. 6a. Bluetooth: Removed hcidump from debugger, in some cases, that will just hang endlessly. Also wrapped bluetoothctl and bt-adapter debugger data collection with @ps_cmd bluetooth running test. Only run if bluetooth service is running. 6b. Bluetooth: running detections have to be very strict, only bluetoothd, not bluetooth, the latter can show true when bluetoothd is not running, and did in my tests. 7. USB: with Code Change 1, found a few places where fallback usb type detections were creating false matches, which resulted in say, bluetooth devices showing up as network devices due to the presence of the word 'wireless' in the device description. These matches are all updated and revised to be more accurate and less error prone. 8. Battery: an oversight, had forgotten to have percent used of available capacity, which made Battery data hard to decipher, now it shows the percent of available total, as well as the condition percent, so it's easier to understand the data now, and hopefully more clear. 9a. OpenBSD changed usbdevs output format sometime in the latest releases, which made the delicate matching patterns fail. Updated to handle both variants. They also changed pcidump -v formatting at some point, now inxi will try to handle either. Note that usbdevs updates also work fine on NetBSD. 9b. FreeBSD also changed their pciconf output in beta 13.0, which also broke the detections completely, now checks for old and new formats. Sigh. It should not take this much work to parse tools whose output should be consistent and reliable. Luckily I ran the beta prior to this release, or all pci device detections would simply have failed, without fallback. 9c. Dragonfly BSD also changed an output format, in vmstat, that made the RAM used report fail. Since it's clearly not predictable which BSD will change support for which vmstat options, now just running vmstat without options, and then using processing logic to determine what to do with the results. 10. It turns out NetBSD is using /proc/meminfo, who would have thought? for memory data, but they use it in a weird way that could result in either negative or near 0 ram used. Added in some filters to not allow such values to print, now it tries to make an educated guess about how much ram the system is really using based on some tests. 11. Something you'd only notice if testing a lot, uptime failed when the uptime was < 1 minute, it had failed to handle the seconds only option, now it does, seconds, minutes, hours:minutes, days hours:minutes, all work. 12. Missed linsysfs type to exclude in partitons, that was a partner to linprocfs type, both are BSD types. 13. Added -ww to ps arguments, that stops the cutting width to terminal size default behavior in BSDs, an easy fix, wish I'd known about that a long time ago. 15. gpart seems to show sizes in bytes, not the expected KiB, so that's now handled internally. Hopefully that odd behavior won't randomly change in the future, sigh. 16. Fixed slim dm detection, saw instance where it's got slim.pid like normal dms, not the slim.lock which inxi was looking for, so now inxi looks for both, and we're all happy! ------------------------------------------------------------------------ ENHANCEMENTS: 1. Added in something that should have been there all along, now inxi validates the man page download as well as the self, this avoids corrupted downloads breaking the man. 2. Init: added support for shepherd init system. 3. Distro Data: added support for guix distro ID; added support for NomadBSD, GhostBSD, HardenedBSD system base. GhostBSD also shows the main package version for the distro version ID, which isn't quite the same as the version you download, but it's close. Also added os-release support for BSDs, using similar tests as for linux distros, that results in nicer outputs for example for Dragonfly BSD. 4. Package Data: added guix/scratch [venom]/kiss/nix package managers. Update for slackware 15 package manager data directory relocation, now handles either legacy current or future one. 5. Repos: added scratch/kiss/nix-channels; Added GhostBSD, HardenedBSD pkg repos. 6. USB Data: added usbconfig. That's FreeBSD's, and related systems. 7. Device Data: Added pcictl support, that's NetBSD's, I thought inxi had supported that, but then I remembered last time I tried to run netBSD in a vm, I couldn't get it figured out. Now debugged and working reasonably well. 8. Raspberry Pi 3, 4: ethernet nic now detected; wifi device, which is on a special mmcnr type, now works, that stopped working in pi 3, due to the change, now it's handled cleanly. Also added support for pi bluetooth, which lives on a special serial bus, not usb. For Raspberry Pi OS, added system base detections, which are tricky. Also matched mmcnr devices to IF data, which was trickyy as well. Note that as far as I could discover, only pi puts wifi on mmcnr. 9. Bluetooth: due to deprecated nature of the fine hciconfig utility, added in support for bt-adapter, which also allows matching of bluetooth data to device data, but is very sparse in info supplied compared to hciconfig. bluetoothctl does not have enough data to show the hci device, so it's not used, since inxi can't match the bluetooth data to the device (no hci[x]). This should help the distros that are moving away from hciconfig, in particular, AUR is only way arch users can get hciconfig, which isn't ideal. 10. New tool and feature, ServiceData, this does two things, as cross platform as practical, show status of bluetooth service, this should help a lot in support people debugging bluetooth problems, since you have bluetooth enabled but down, or up, disabled, and you can also have the device itself down or up, so now it shows all that data together for when it's down, but when the device is up, it just shows the device status since the other stuff is redundant then. In -Sa, it now shows the OS service manager that inxi detected using a bunch of fallback tests, that's useful to admins who are on a machine they don't know, then you can see the service manager to use, like rc-service, systemctl, service, sv, etc. 11. Big update for -A: Sound Servers: had always been really just only ALSA, now it shows all detected sound servers, and whether they are running or not. Includes: ALSA, OSS, PipeWire, PulseAudio, sndio, JACK. Note that OSS version is a guess, might be wrong source for the version info. 12. Added USB device 'power:' item, that's in mA, not a terrible thing to have listed, -xxx. This new feature was launched cross platform, which is nice. Whether the BSD detections will break in the future of course depends on whether they change the output formats again or not. Also added in USB more chip IDs, which can be useful. For BSDs, also added in a synthetic USB rev, taken from the device/hub speeds. Yes, I know, USB 2 can have low speed, full speed, or high speed, and 1.1 can have low and full speeds, so you actually can't tell the USB revision version from the speeds, but it's close enough. 13. Made all USB/Device data the same syntax and order, more predictable, bus, chip, class IDs all the same now. 14. Added in support for hammer and null/nullfs file system types, which trigger 'logical:' type device in partitions, that's also more correct than the source: Err-102 that used to show, which was really just a flag to alert me visibly that the partition type detection had simply failed internally. Now for detected types, like zfs tank/name or null/nullfs, it knows they are logical structures. 15. Expanded BSD CPU data, where available, now can show L1/L2/ L3 cache, cpu arch, stepping, family/model ids, etc, which is kind of nifty, although, again, delicate fragile rules that will probably break in the future, but easier to fix now. 16. By an old request, added full native BSD doas support. That's a nice little tool, and it plugged in fairly seamlessly to existing sudo support. Both the internal doas/sudo stuff should work the same, and the detection of sudo/doas start should work the same too. 17a. Shell/Parent Data: Big refactor of the shell start/parent logic, into ShellData which helped resolve some issues with running-in showing shell name, not vt terminal or program name. Cause of that is lots of levels of parents before inxi could reach the actual program that was running inxi. Solution was to change to a longer loop, and let it iterate 8 times, until it finds something that is not a shell or sudo/doas/su type parent, this seems to work quite well, you can only make it fail now if you actually try to do it on purpose, which is fine. This was very old logic, and carried some mistakes and redundancies that made it very hard to understand, that's cleaned up now. Also restored the old (login) value, which shows when you use your normal login account on console, some system will also now show (sudo,login) if the login user sudos inxi, but that varies system to system. 17b. BSD running-in: Some of the BSDs now support the -f flag for ps, which made the parent logic for running-in possible for BSDs, which was nice. Some still don't support it, like OpenBSD and NetBSD, but that's fine, inxi tests, and if no support detected, just shows tty number. Adding in more robust support here cleaned up some redundant logic internally as well. 17c. Updated terminal and shell ID detections, there's quite a few new terminals this year, and a new shell or two. Those are needed for more reliable detections of when the parent is NOT a shell, which is how we find what it is. 18. Added ctwm wm support, that's the new default for NetBSD, based on twm, has version numbers. 19. Upgraded BSD support for gpart and glabel data, now should catch more more often. 20. For things like zfs raid, added component size, that doesn't always work due to how zfs refers to its components, but it often does, which is better than never before. 21. To make BSD support smoother, got rid of some OpenBSD only rules, which in fact often apply to NetBSD as well. That may lead to some glitches, but overall it's better to totally stay away from OpenBSD only tests, and all BSD variant tests, and just do dynamic testing that will work when it applies, and not when it doesn't. In this case, added ftp downloader support for netBSD by removing the openBSD only flag for that item. There's a bit of a risk there in a sense since if different ftp programs with different options were to be the fallback for something else, it might get used, but that's fine, it's a corner case, better to have them all work now than to worry about weird future things. But limiting it to only BSDs should get rid of most of the problem. vmstat and optical drive still use net/openbsd specifics because it is too tricky to figure out it out in any more dynamic way. 22. For -Sxxx, added if systemd, display, virtual terminal number. Could be useful to debug subtle issues, if the user is for example not running their desktop in vt 7, the default for most systems. ------------------------------------------------------------------------ CHANGES: 1. Moved battery voltage to -Bx output, the voltage is quite important to know since that is the key indicator of battery state. If voltage is within .5 volts of specified minimum, shows voltage for -B since that's a prefail condition, it's getting close to death. 2. In partitions and raid, when the device was linear raid logical type layout, it said, no-raid, when it should be 'linear', that's now cleaner and more correct. 3. When running-in is a tty value, it will now show the entire tty ID, minus the '/dev/tty', this will be more precise, and also may resolve cases where tty was fully alpha, no numbers, previously inxi filtered out everything that was not a number, but that can in some tty types remove critical tty data, so now it will show: running-in: tty 2 [not changed]; tty pts/2 [adds pts/]; tty E2 [adds the E]; tty rx [would have not shown at ll before] ------------------------------------------------------------------------ CODE CHANGES: NOTE: unlike the previous refactors, a lot of these changes were done to make inxi more maintainable, which means, slightly less optimized, which has been my preference in the past, but if the stuff can't be maintained, it doesn't matter how fast it runs! These changes have really enhanced the quality of the code and made it a lot easier to work with. It's also now a lot easier to add debuggers, force/fake data switches, etc, so it gets done, unlike before, when it was a pain, so it got skipped, and then caused bugs because of stray debuggers left in place, and so on. The bright side is while reading up on this, I learned that using very large subs is much more efficient than many small ones, which I've always felt was the case, and it is, so the style used internally in inxi proves to be the best one for optimizations. These refactors, ongoing, have now touched at least 1/3, almost 1/2, of the entire inxi codebase, so the stuff is getting more and more consistent and up to date, but given how old the logic is in places, there will be more refactors in the future, and maybe once the code is easier to maintain, some renewed optimizations!, if we can find anything that makes sense, like passing array/hash references back to the caller, already the first half is done, passing references to the sub/method always. The second part is started, using the Benchmark Perl module, which really speeds up testing and helps avoid pointless tweaks that do little re speed improvements. I could see with some care some areas where working on data directly via references could really speed things up, but it's hard to write and read that type of code, but it's already being done in the recursive data and output logics, and a few other places. 1. Large refactor of USBData, that was done in part to help make it work for BSDs better, but also to get it better organized. This refactor also made all the device items, like -A,-G,-N,-E use the same methods for creating USB output, previously they had used a hodgepodge of methods, some super old, it was not possible to add USB support more extensively for BSDs without this change. Also added in some fallback usb type detection tools using several large online collections of that info to see what possible matching patterns could catch more devices and correctly match them to their type, which is the primary way now that usb output per type is created. This really helps with BSDs, though BSD usb utilities suffer from less data than lsusb so they don't always get device name strings in a form where they can be readily ID'ed, but it's way better than it was before, so that's fine! Moved all previous methods of detecting if a card/device was USB into USBData itself so it would all be in one place, and easier to maintain. All USB tools now use bus_id_alpha for sorting, and all now sort as well, that was an oversight, previously the BSD usb tools were not sorted, but those have been enhanced a lot, so sorting on alpha synthetic bus ids became possible. Removed lsusb as a BSD option, it's really unreliable, and the data is different, and also varies a lot, it didn't really work at all in Dragonfly, or had strange output, so lsusb is now a linux only item. 2. Moved various booleans that were global to %force, %loaded, and some to the already present, but lightly used, %use hashes. It was getting too hard to add tests etc, which was causing bugs to happen. Yes, using hashes is slower than hardcoding in the boolean scalars, but this change was done to improve maintainability, which is starting to matter more. 3. Moved several sets of subs to new packages, again, to help with debugging and maintainability. MemoryData, redone in part to handle the oddities with NetBSD reporting of free, cached, and buffers, but really just to make it easier to work with overall. Also moved kernel parameter logic to KernelParameters, gpart logic to GpartData, glabel logic to GlabelData, ip data IpData, check_tools to CheckTools, which was also enhanced largely, and simplified, making it much easier to work with. 4. Wrapped more debugger logic in $fake{data} logic, that makes it harder to leave a debugger uncommented, now to run it, you have to trigger it with $fake{item} so the test runs, that way even if I forget to comment it out, it won't run for regular user. 5. Big update to docs in branch inxi-perl/docs, those are now much more usable for development. Updated in particular inxi-values.txt to be primary reference doc for $fake, $dbg, %force, %use, etc types and values. Also updated inxi-optimization.txt and inxi-resources.txt to bring them closer to the present. Created inxi-bugs.txt as well, which will help to know which known bugs belonged to which frozen pools. These bugs will only refer to bugs known to exist in tagged releases in frozen pool distros. 6. For sizes, moved most of the sizing to use main::translate_size, this is more predictable, though as noted, these types of changes make inxi a bit slower since it moved stuff out of inline to using quick expensive sub calls, but it's a lot easier to maintain, and that's getting to be more important to me now. 7. In order to catch live events, added in dmesg to dmesg.boot data in BSDs, that's the only way I could find to readily detect usb flash drives that were plugged in after boot. Another hack, these will all come back to bite me, but that's fine, the base is easier to work on and debug now, so if I want to spend time revisiting the next major version BSD releases, it will be easier to resolve the next sets of failures. 8. A big change, I learned about the non greedy operator for regex patterns, ?, as in, .*?(next match rule), it will now go up only to the next match rule. Not knowing this simple little thing made inxi use some really convoluted regex to avoid such greedy patterns. Still some gotchas with ?, like it ignores following rules that are zero or 1, ? type, and just treats it as zero instances. But that's easy to work with. 9. Not totally done, but now moved more to having set data tools set their $loaded{item} value in get data, not externally, that makes it easier to track the stuff. Only where it makes sense, but there's a lot of those set/get items, they should probably all become package/classes, with set/get I think. 10. Optimized reader() and grabber() and set_ps_aux_data(), all switched from using grep/map to using for loops, that means inxi doesn't have to go through each array 2x anymore, actually 4x in the case of set_ps_aux_data(). This saved a visible amount of execution time, I noticed this lag when running pinxi through NYTProf optimizer, there was a quite visible time difference between grabber/reader and the subshell time, these optimizations almost removed that difference, meaning only the subshell now really takes any time to run. Optimized url_cleaner and data_cleaner in RepoData, those now just work directy on the array references, no returns. Ran some more optimization tests, but will probably hold off on some of them, for example, using cleaner() by reference is about 50% faster than by copy, but redoing that requires adding in many copies from read only things like $1, so the change would lead to slightly less clean code, but may revisit this in the future, we'll see. But in theory, basically all the core internal tools that take a value and modify it should do that by reference purely since it's way faster, up to 10x. --- inxi | 5486 +++++++++++++++++++++++++++++------------------- inxi.1 | 189 +- inxi.changelog | 468 +++++ 3 files changed, 3958 insertions(+), 2185 deletions(-) diff --git a/inxi b/inxi index ce41381..593a5e0 100755 --- a/inxi +++ b/inxi @@ -36,77 +36,77 @@ use Getopt::Long qw(GetOptions); Getopt::Long::Configure ('bundling', 'no_ignore_case', 'no_getopt_compat', 'no_auto_abbrev','pass_through'); use POSIX qw(uname strftime ttyname); -# use feature qw(state); +# use Benchmark qw(:all); +# use Devel::Size qw(size total_size); +# use feature qw(say state); # 5.10 or newer Perl ## INXI INFO ## my $self_name='inxi'; -my $self_version='3.3.01'; -my $self_date='2021-02-08'; +my $self_version='3.3.02'; +my $self_date='2021-03-15'; my $self_patch='00'; ## END INXI INFO ## ### INITIALIZE VARIABLES ### -## Self data -my ($self_path, $user_config_dir, $user_config_file,$user_data_dir); +## Hashes +my (%alerts,%build_prop,%client,%colors,%dl,%files,%gpart, +%dmmapper,%force,%loaded,%mapper,%program_values,%rows,%sensors_raw, +%service_tool,%system_files); + +## System Arrays +my (@app,@dmesg_boot,@devices_audio,@devices_bluetooth,@devices_graphics, +@devices_network,@devices_hwraid,@devices_timer,@dmi,@gpudata,@ifs,@ifs_bsd, +@paths,@ps_aux,@ps_cmd,@ps_gui,@sensors_exclude,@sensors_use, +@sysctl,@sysctl_audio,@sysctl_battery,@sysctl_machine,@sysctl_sensors, +@uname,@usb,@usb_audio,@usb_bluetooth,@usb_graphics,@usb_network); + +## Disk/Partition arrays +my (@dm_boot_disk,@dm_boot_optical,@glabel,@labels,@lsblk,@lvm, +@lvm_raid,@md_raid,@partitions,@proc_partitions,@raw_logical, +@sysctl_disks,@swaps,@uuids,@zfs_raid); ## Debuggers -my $debug=0; -my (@t0,$end,$start,$fh_l,$log_file); # log file handle, file -my ($b_hires,$t1,$t2,$t3) = (0,0,0,0); +my %debugger = ('level' => 0); +my (@dbg,%fake,@t0); +my ($b_hires,$b_log,$b_log_colors,$b_log_full); +my ($end,$start,$fh_l,$log_file); # log file handle, file +my ($t1,$t2,$t3) = (0,0,0); # timers +## debug / temp tools +$debugger{'sys'} = 1; +$client{'test-konvi'} = 0; + # NOTE: redhat removed HiRes from Perl Core Modules. if (eval {require Time::HiRes}){ Time::HiRes->import('gettimeofday','tv_interval','usleep'); $b_hires = 1; } @t0 = eval 'Time::HiRes::gettimeofday()' if $b_hires; # let's start it right away -## Hashes -my (%alerts,%build_prop,%client,%colors,%debugger,%dl,%files, -%dmmapper,%mapper,%program_values,%rows,%sensors_raw,%system_files); -## Arrays -# ps_aux is full output, ps_cmd is only the last 10 columns to last -my (@app,@dmesg_boot,@devices_audio,@devices_bluetooth,@devices_graphics, -@devices_network,@devices_hwraid,@devices_timer,@dmi,@gpudata,@ifs,@ifs_bsd, -@paths,@proc_partitions,@ps_aux,@ps_cmd,@ps_gui,@sensors_exclude,@sensors_use, -@sysctl,@sysctl_battery,@sysctl_sensors,@sysctl_machine,@uname,@usb); -## Disk arrays -my (@dm_boot_disk,@dm_boot_optical,@glabel,@gpart,@labels,@lsblk,@lvm, -@lvm_raid,@md_raid,@partitions,@raw_logical,@sysctl_disks,@swaps,@uuids,@zfs_raid); -my @test = (0,0,0,0,0); +## Booleans [busybox_ps not used actively] +my ($b_admin,$b_android,$b_arm,$b_busybox_ps,$b_display,$b_irc, +$b_mips,$b_ppc,$b_root,$b_running_in_display,$b_sparc); -## Booleans -my ($b_active_general,$b_active_lvm, -$b_admin,$b_android,$b_arm,$b_bb_ps,$b_block_tool,$b_build_prop, -$b_display,$b_dmesg_boot_check,$b_dmi,$b_dmidecode_force, -$b_fake_bluetooth,$b_fake_bsd,$b_fake_cpu,$b_fake_dboot,$b_fake_dmidecode, -$b_fake_logical,$b_fake_pciconf,$b_fake_raid,$b_fake_sensors,$b_fake_sysctl, -$b_fake_usbdevs,$b_force_display, -$b_gpudata,$b_hddtemp_force,$b_irc,$b_log,$b_log_colors,$b_log_full,$b_lvm,$b_lvm_data, -$b_man,$b_mapper,$b_mdadm,$b_mem,$b_mips, -$b_no_html_wan,$b_no_sudo,$b_pci,$b_pci_tool,$b_pkg,$b_ppc,$b_proc_partitions, -$b_ps_gui,$b_root,$b_running_in_display,$b_sensors,$b_skip_dig, -$b_slot_tool,$b_soc_audio,$b_soc_bluetooth,$b_soc_gfx,$b_soc_net,$b_soc_timer,$b_sparc, -$b_swaps,$b_sysctl,$b_usb,$b_usb_check,$b_usb_sys,$b_usb_tool, -$b_wmctrl); -## Disk checks -my ($b_dm_boot_disk,$b_dm_boot_optical,$b_glabel,$b_hardware_raid, -$b_label_uuid,$b_lsblk,$b_partitions,$b_raid,$b_smartctl); # initialize basic use features my %use = ( 'sysctl_disk' => 1, # unused currently 'update' => 1, # switched off/on with maintainer config ALLOW_UPDATE 'weather' => 1, # switched off/on with maintainer config ALLOW_WEATHER ); + +## Self data +my ($self_path,$user_config_dir,$user_config_file,$user_data_dir); + ## System my ($bsd_type,$device_vm,$language,$os,$pci_tool,$wan_url) = ('','','','','',''); -my ($bits_sys,$cpu_arch); +my ($bits_sys,$cpu_arch,$ppid); my ($cpu_sleep,$dl_timeout,$limit,$ps_cols,$ps_count) = (0.35,4,10,0,5); my $sensors_cpu_nu = 0; my ($dl_ua,$weather_source,$weather_unit) = ('s-tools/' . $self_name . '-',100,'mi'); + ## Tools -my ($display,$ftp_alt,$tty_session); -my ($display_opt,$sudo) = ('',''); +my ($bt_tool,$display,$ftp_alt,$tty_session); +my ($display_opt,$sudoas) = ('',''); ## Output my $extra = 0;# supported values: 0-3 @@ -142,10 +142,6 @@ my %size = ( 'term-lines' => 100, ); -## debug / temp tools -$debugger{'sys'} = 1; -$client{'test-konvi'} = 0; - ######################################################################## #### STARTUP ######################################################################## @@ -159,16 +155,16 @@ sub main { eval $start if $b_log; initialize(); ## Uncomment these two values for start client debugging - # $debug = 3; # 3 prints timers / 10 prints to log file + # $debugger{'level'} = 3; # 3 prints timers / 10 prints to log file # set_debugger(); # for debugging of konvi and other start client issues ## legacy method #my $ob_start = StartClient->new(); #$ob_start->get_client_data(); - StartClient::get_client_data(); + StartClient::set(); # print_line( Dumper \%client); - get_options(); + OptionsHandler::get(); set_debugger(); # right after so it's set - check_tools(); + CheckTools::set(); set_colors(); set_sep(); # print download_file('stdout','https://') . "\n"; @@ -195,146 +191,195 @@ sub initialize { set_display_width('live'); } -sub check_tools { - my ($action,$program,$message,@data,%commands); - if ($b_dmi){ - $action = 'use'; - if ($program = check_program('dmidecode')) { - @data = grabber("$program -t chassis -t baseboard -t processor 2>&1"); - if (scalar @data < 15){ - if ($b_root) { - foreach (@data){ - if ($_ =~ /No SMBIOS/i){ - $action = 'smbios'; - last; - } - elsif ($_ =~ /^\/dev\/mem: Operation/i){ - $action = 'no-data'; - last; - } - else { - $action = 'unknown-error'; - last; - } - } - } - else { - if (grep { $_ =~ /^\/dev\/mem: Permission/i } @data){ - $action = 'permissions'; - } - else { - $action = 'unknown-error'; - } - } - } - } - else { - $action = 'missing'; - } - $alerts{'dmidecode'} = { - 'action' => $action, - 'missing' => row_defaults('tool-missing-required','dmidecode'), - 'permissions' => row_defaults('tool-permissions','dmidecode'), - 'path' => $program, - 'smbios' => row_defaults('dmidecode-smbios'), - 'no-data' => row_defaults('dmidecode-dev-mem'), - 'unknown-error' => row_defaults('tool-unknown-error','dmidecode'), - }; - } - # 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 - if ($b_lvm || $b_pci || $b_sysctl || $show{'bluetooth'}){ - if (!$bsd_type){ - if ($b_pci ){ - $commands{'lspci'} = '-n'; - } - if ($b_lvm){ - $commands{'lvs'} = ''; - } - } - else { - if ($b_pci ){ - $commands{'pciconf'} = '-l'; - $commands{'pcictl'} = 'list'; - $commands{'pcidump'} = ''; - } - if ($b_sysctl ){ - # note: there is a case of kernel.osrelease but it's a linux distro - $commands{'sysctl'} = 'kern.osrelease'; - } - } - foreach ( keys %commands ){ - $action = 'use'; - if ($program = check_program($_)) { - # > 0 means error in shell - #my $cmd = "$program $commands{$_} >/dev/null"; - #print "$cmd\n"; - $pci_tool = $_ if $_ =~ /pci/; - $action = 'permissions' if system("$program $commands{$_} >/dev/null 2>&1"); - } - else { - $action = 'missing'; - } - $alerts{$_} = { - 'action' => $action, - 'missing' => row_defaults('tool-missing-incomplete',"$_"), - 'path' => $program, - 'permissions' => row_defaults('tool-permissions',"$_"), - }; - } - } - %commands = (); - if ($show{'bluetooth'}){ - # hangs when bluetooth service is enabled - # $commands{'bt-adapter'} = '-l'; - # hangs endlessly - # $commands{'bluetoothctl'} = 'list'; - $commands{'hciconfig'} = 'linux'; - } - if ($show{'sensor'}){ - $commands{'sensors'} = 'linux'; - } - # note: lsusb ships in FreeBSD ports sysutils/usbutils - if ($b_usb){ - $commands{'lsusb'} = 'all'; - $commands{'usbdevs'} = 'bsd'; - } - if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})){ - $commands{'ip'} = 'linux'; - $commands{'ifconfig'} = 'all'; - } - # can't check permissions since we need to know the partition/disc - if ($b_block_tool){ - $commands{'blockdev'} = 'linux'; - $commands{'lsblk'} = 'linux'; - } - if ($b_mdadm){ - $commands{'mdadm'} = 'linux'; - } - if ($b_smartctl){ - $commands{'smartctl'} = 'all'; - } - foreach ( keys %commands ){ - $action = 'use'; - $program = ''; - $message = row_defaults('tool-present'); - if ( ($commands{$_} eq 'linux' && $os ne 'linux' ) || ($commands{$_} eq 'bsd' && $os eq 'linux' ) ){ - $message = row_defaults('tool-missing-os', ucfirst($os) . " $_"); +# CheckTools +{ +package CheckTools; +my (%commands); +sub set { + eval $start if $b_log; + set_commands(); + my ($action,$program,$message,@data); + foreach my $test ( keys %commands ){ + ($action,$program) = ('use',''); + $message = main::row_defaults('tool-present'); + if ($commands{$test}->[1] && ( + ($commands{$test}->[1] eq 'linux' && $os ne 'linux' ) || + ($commands{$test}->[1] eq 'bsd' && $os eq 'linux' ) ) ){ $action = 'platform'; } - elsif (!($program = check_program($_))){ - $message = row_defaults('tool-missing-recommends',"$_"); + elsif ($program = main::check_program($test)) { + # > 0 means error in shell + #my $cmd = "$program $commands{$test} >/dev/null"; + #print "$cmd\n"; + $pci_tool = $test if $test =~ /pci/; + if ($commands{$test}->[0] eq 'exec-sys'){ + $action = 'permissions' if system("$program $commands{$test}->[2] >/dev/null 2>&1"); + } + elsif ($commands{$test}->[0] eq 'exec-string'){ + @data = main::grabber("$program $commands{$test}->[2] 2>&1"); + # dmidecode errors are so specific it gets its own section + # also sets custom dmidecode error messages + if ($test eq 'dmidecode'){ + $action = set_dmidecode(\@data) if scalar @data < 15; + } + elsif (grep { $_ =~ /$commands{$test}->[3]/i } @data){ + $action = 'permissions'; + } + } + } + else { $action = 'missing'; } - $alerts{$_} = { - 'action' => $action, - 'missing' => $message, - 'path' => $program, - 'platform' => $message, + $alerts{$test}->{'action'} = $action; + $alerts{$test}->{'path'} = $program; + if ($action eq 'missing'){ + $alerts{$test}->{'message'} = main::row_defaults('tool-missing-recommends',"$test"); + } + elsif ($action eq 'permissions'){ + $alerts{$test}->{'message'} = main::row_defaults('tool-permissions',"$test"); + } + elsif ($action eq 'platform'){ + $alerts{$test}->{'message'} = main::row_defaults('tool-missing-os', ucfirst($os) . " $test"); + } + } + print Data::Dumper::Dumper \%alerts if $dbg[25]; + set_fake_bsd_tools() if $fake{'bsd'}; + set_forced_tools(); + eval $end if $b_log; +} +sub set_dmidecode { + my ($data) = @_; + my $action = 'use'; + if ($b_root) { + foreach (@$data){ + if ($_ =~ /No SMBIOS/i){ + $action = 'smbios'; + last; + } + elsif ($_ =~ /^\/dev\/mem: Operation/i){ + $action = 'no-data'; + last; + } + else { + $action = 'unknown-error'; + last; + } + } + } + else { + if (grep { $_ =~ /^\/dev\/mem: Permission/i } @$data){ + $action = 'permissions'; + } + else { + $action = 'unknown-error'; + } + } + if ($action ne 'use' && $action ne 'permissions'){ + if ($action eq 'smbios'){ + $alerts{'dmidecode'}->{'message'} = rmain::ow_defaults('dmidecode-smbios'); + } + elsif ($action eq 'no-data'){ + $alerts{'dmidecode'}->{'message'} = main::row_defaults('dmidecode-dev-mem'); + } + elsif ($action eq 'unknown-error'){ + $alerts{'dmidecode'}->{'message'} = main::row_defaults('tool-unknown-error','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 + if (!$bsd_type){ + if ($use{'pci'} ){ + $commands{'lspci'} = ['exec-sys','','-n']; + } + if ($use{'lvm'}){ + $commands{'lvs'} = ['exec-sys','','']; + } + } + else { + if ($use{'pci'}){ + $commands{'pciconf'} = ['exec-sys','','-l']; + $commands{'pcictl'} = ['exec-sys','',' pci0 list']; + $commands{'pcidump'} = ['exec-sys','','']; + } + if ($use{'sysctl'}){ + # note: there is a case of kernel.osrelease but it's a linux distro + $commands{'sysctl'} = ['exec-sys','','kern.osrelease']; + } + } + if ($use{'dmidecode'}){ + $commands{'dmidecode'} = ['exec-string','','-t chassis -t baseboard -t processor','']; + } + if ($use{'usb'}){ + # note: lsusb ships in FreeBSD ports sysutils/usbutils + $commands{'lsusb'} = ['missing','','','']; + # we want these set for various null bsd data tests + $commands{'usbconfig'} = ['exec-string','bsd','list','permissions']; + $commands{'usbdevs'} = ['missing','bsd','','']; + } + if ($show{'bluetooth'}){ + $commands{'bluetoothctl'} = ['missing','linux','','']; + # bt-adapter hangs when bluetooth service is disabled + $commands{'bt-adapter'} = ['missing','linux','','']; + $commands{'hciconfig'} = ['missing','linux','','']; + } + if ($show{'sensor'}){ + $commands{'sensors'} = ['missing','linux','','']; + } + + if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})){ + $commands{'ip'} = ['missing','linux','','']; + $commands{'ifconfig'} = ['missing','','','']; + } + # can't check permissions since we need to know the partition/disc + if ($use{'block-tool'}){ + $commands{'blockdev'} = ['missing','linux','','']; + $commands{'lsblk'} = ['missing','linux','','']; + } + if ($use{'mdadm'}){ + $commands{'mdadm'} = ['missing','linux','','']; + } + if ($use{'smartctl'}){ + $commands{'smartctl'} = ['missing','','','']; + } +} +sub set_forced_tools { + if ($bt_tool){ + if ($bt_tool ne 'bluetootctl' && $alerts{'bluetoothctl'}->{'action'} eq 'use'){ + $alerts{'bluetoothctl'}->{'action'} = 'missing'; + } + if ($bt_tool ne 'bt-adapter' && $alerts{'bt-adapter'}->{'action'} eq 'use'){ + $alerts{'bt-adapter'}->{'action'} = 'missing'; + } + if ($bt_tool ne 'hciconfig' && $alerts{'hciconfig'}->{'action'} eq 'use'){ + $alerts{'hciconfig'}->{'action'} = 'missing'; + } + } +} +# only for dev/debugging BSD +sub set_fake_bsd_tools { + $system_files{'dmesg-boot'} = '/var/run/dmesg.boot' if $fake{'dboot'}; + $alerts{'sysctl'}->{'action'} = 'use' if $fake{'sysctl'}; + if ($fake{'pciconf'} || $fake{'pcictl'} || $fake{'pcidump'}){ + $alerts{'pciconf'}->{'action'} = 'use' if $fake{'pciconf'}; + $alerts{'pcictl'}->{'action'} = 'use' if $fake{'pcictl'}; + $alerts{'pcidump'}->{'action'} = 'use' if $fake{'pcidump'}; + $alerts{'lspci'} = { + 'action' => 'missing', + 'message' => 'Required program lspci not available', }; } - # print Dumper \%alerts; - set_fake_bsd_tools() if $b_fake_bsd; + if ($fake{'usbconfig'} || $fake{'usbdevs'}){ + $alerts{'usbconfig'}->{'action'} = 'use' if $fake{'usbconfig'}; + $alerts{'usbdevs'}->{'action'} = 'use' if $fake{'usbdevs'}; + $alerts{'lsusb'} = { + 'action' => 'missing', + 'message' => 'Required program lsusb not available', + }; + } +} } # args: 1 - desktop/app command for --version; 2 - search string; # 3 - space print number; 4 - [optional] version arg: -v, version, etc @@ -347,9 +392,9 @@ sub set_basics { $ENV{'LC_ALL'}='C'; # remember, perl uses the opposite t/f return as shell!!! # some versions of busybox do not have tty, like openwrt - $b_irc = ( check_program('tty') && system('tty >/dev/null') ) ? 1 : 0; + $b_irc = (check_program('tty') && system('tty >/dev/null') ) ? 1 : 0; # print "birc: $b_irc\n"; - $b_display = ( $ENV{'DISPLAY'} ) ? 1 : 0; + $b_display = ($ENV{'DISPLAY'}) ? 1 : 0; $b_root = $< == 0; # root UID 0, all others > 0 $dl{'dl'} = 'curl'; $dl{'curl'} = 1; @@ -367,6 +412,7 @@ sub set_basics { $colors{'default'} = 2; $show{'partition-sort'} = 'id'; # sort order for partitions @raw_logical = (0,0,0); + $ppid = getppid(); } # args: $1 - default OR override default cols max integer count. $_[0] @@ -416,20 +462,6 @@ sub set_display_width { # print "tc: $size{'term'} cmc: $size{'console'} cm: $size{'max'}\n"; } -# only for dev/debugging BSD -sub set_fake_bsd_tools { - $system_files{'dmesg-boot'} = '/var/run/dmesg.boot' if $b_fake_dboot; - $alerts{'pciconf'}->{'action'} = 'use' if $b_fake_pciconf; - $alerts{'sysctl'}->{'action'} = 'use' if $b_fake_sysctl; - if ($b_fake_usbdevs){ - $alerts{'usbdevs'}->{'action'} = 'use'; - $alerts{'lsusb'} = { - 'action' => 'missing', - 'missing' => 'Required program lsusb not available', - }; - } -} - # NOTE: most tests internally are against !$bsd_type sub set_os { @uname = uname(); @@ -448,7 +480,7 @@ sub set_os { } $b_android = 1 if -e '/system/build.prop'; if ( $os =~ /(aix|bsd|cosix|dragonfly|darwin|hp-?ux|indiana|irix|sunos|solaris|ultrix|unix)/ ){ - if ( $os =~ /openbsd/ ){ + if ($os =~ /openbsd/){ $os = 'openbsd'; } elsif ($os =~ /darwin/){ @@ -501,16 +533,22 @@ sub set_sep { } # Important: -n makes it non interactive, no prompt for password -# only use sudo if not root, -n option requires sudo -V 1.7 or greater. +# only use doas/sudo if not root, -n option requires sudo -V 1.7 or greater. # for some reason sudo -n with < 1.7 in Perl does not print to stderr # sudo will just error out which is the safest course here for now, # otherwise that interactive sudo password thing is too annoying sub set_sudo { - if (!$b_root && !$b_no_sudo && (my $path = check_program('sudo'))) { - my @data = program_data('sudo'); - $data[1] =~ s/^([0-9]+\.[0-9]+).*/$1/; - #print "sudo v: $data[1]\n"; - $sudo = "$path -n " if is_numeric($data[1]) && $data[1] >= 1.7; + if (!$b_root){ + my ($path); + if (!$force{'no-doas'} && ($path = check_program('doas'))){ + $sudoas = "$path -n "; + } + elsif (!$force{'no-sudo'} && ($path = check_program('sudo'))) { + my @data = program_data('sudo'); + $data[1] =~ s/^([0-9]+\.[0-9]+).*/$1/; + #print "sudo v: $data[1]\n"; + $sudoas = "$path -n " if is_numeric($data[1]) && $data[1] >= 1.7; + } } } @@ -636,7 +674,7 @@ sub set_xorg_log { } } } - print "Xorg log file: $file_holder\nLast modified: $time_holder\n" if $test[14]; + print "Xorg log file: $file_holder\nLast modified: $time_holder\n" if $dbg[14]; log_data('data',"Xorg log file: $file_holder") if $b_log; $system_files{'xorg-log'} = $file_holder; eval $end if $b_log; @@ -1136,10 +1174,14 @@ sub get_config_item { elsif ($key eq 'LANGUAGE') {$language = $val if $val =~ /^(en)$/} elsif ($key eq 'LIMIT') {$limit = $val if is_int($val)} elsif ($key eq 'OUTPUT_TYPE') {$output_type = $val if $val =~ /^(json|screen|xml)$/} - elsif ($key eq 'NO_DIG') {$b_skip_dig = $val if is_int($val)} - elsif ($key eq 'NO_HTML_WAN') {$b_no_html_wan = $val if is_int($val)} - elsif ($key eq 'NO_SUDO') {$b_no_sudo = $val if is_int($val)} - elsif ($key eq 'PARTITION_SORT') {$show{'partition-sort'} = $val if ($val =~ /^(dev-base|fs|id|label|percent-used|size|uuid|used)$/) } + elsif ($key eq 'NO_DIG') {$force{'no-dig'} = $val if is_int($val)} + elsif ($key eq 'NO_DOAS') {$force{'no-doas'} = $val if is_int($val)} + elsif ($key eq 'NO_HTML_WAN') {$force{'no-html-wan'} = $val if is_int($val)} + elsif ($key eq 'NO_SUDO') {$force{'no-sudo'} = $val if is_int($val)} + elsif ($key eq 'PARTITION_SORT') { + if ($val =~ /^(dev-base|fs|id|label|percent-used|size|uuid|used)$/){ + $show{'partition-sort'} = $val; + }} elsif ($key eq 'PS_COUNT') {$ps_count = $val if is_int($val) } elsif ($key eq 'SENSORS_CPU_NO') {$sensors_cpu_nu = $val if is_int($val)} elsif ($key eq 'SENSORS_EXCLUDE') {@sensors_exclude = split(/\s*,\s*/, $val) if $val} @@ -1150,11 +1192,11 @@ sub get_config_item { $show{'no-host'} = 1 if !$show{'host'}; } } - elsif ($key eq 'USB_SYS') {$b_usb_sys = $val if is_int($val)} + elsif ($key eq 'USB_SYS') {$force{'usb-sys'} = $val if is_int($val)} elsif ($key eq 'WAN_IP_URL') { if ($val =~ /^(ht|f)tp[s]?:\//i){ $wan_url = $val; - $b_skip_dig = 1; + $force{'no-dig'} = 1; } } elsif ($key eq 'WEATHER_SOURCE') {$weather_source = $val if is_int($val)} @@ -1321,27 +1363,27 @@ sub log_data { sub set_debugger { user_debug_test_1() if $debugger{'test-1'}; - if ( $debug >= 20){ + if ( $debugger{'level'} >= 20){ error_handler('not-in-irc', 'debug data generator') if $b_irc; - my $option = ( $debug > 22 ) ? 'main-full' : 'main'; - $debugger{'gz'} = 1 if ($debug == 22 || $debug == 24); + my $option = ($debugger{'level'} > 22) ? 'main-full' : 'main'; + $debugger{'gz'} = 1 if ($debugger{'level'} == 22 || $debugger{'level'} == 24); my $ob_sys = SystemDebugger->new($option); $ob_sys->run_debugger(); - $ob_sys->upload_file($ftp_alt) if $debug > 20; + $ob_sys->upload_file($ftp_alt) if $debugger{'level'} > 20; exit 0; } - elsif ($debug >= 10 && $debug <= 12){ + elsif ($debugger{'level'} >= 10 && $debugger{'level'} <= 12){ $b_log = 1; - if ($debug == 11){ + if ($debugger{'level'} == 11){ $b_log_full = 1; } - elsif ($debug == 12){ + elsif ($debugger{'level'} == 12){ $b_log_colors = 1; } begin_logging(); } - elsif ($debug <= 3){ - if ($debug == 3){ + elsif ($debugger{'level'} <= 3){ + if ($debugger{'level'} == 3){ $b_log = 1; $debugger{'timers'} = 1; begin_logging(); @@ -1355,7 +1397,6 @@ sub set_debugger { ## SystemDebugger { package SystemDebugger; - my $option = 'main'; my ($data_dir,$debug_dir,$debug_gz,$parse_src,$upload) = ('','','','',''); my @content; @@ -1520,12 +1561,17 @@ sub bluetooth_data { print "Collecting bluetooth data...\n"; # no warnings 'uninitialized'; my @cmds = ( - # ['bluetoothctl','list'], # do not use, hangs!! - # ['bt-adapter','-l'], # hangs once bluetooth service is enabled ['hciconfig','-a'], - ['hcidump',''], + #['hcidump',''], # hangs sometimes ['hcitool','dev'], ); + # these hang if bluetoothd not enabled + if (@ps_cmd && (grep {m|/bluetoothd|} @ps_cmd)){ + push(@cmds,['bt-adapter','--list']); + push(@cmds,['bt-adapter','--info']); + push(@cmds,['bluetoothctl','-- list']); + push(@cmds,['bluetoothctl','-- show']); + } run_commands(\@cmds,'bluetooth'); } @@ -1834,6 +1880,7 @@ sub system_data { # bsd tools http://cb.vu/unixtoolbox.xhtml my @cmds = ( # general + ['sysctl', '-a'], ['sysctl', '-b kern.geom.conftxt'], ['sysctl', '-b kern.geom.confxml'], ['usbdevs','-v'], @@ -1841,13 +1888,15 @@ sub system_data { ['pciconf','-l -cv'], ['pciconf','-vl'], ['pciconf','-l'], + ['usbconfig','list'], # needs root, sigh... why? # openbsd ['pcidump',''], ['pcidump','-v'], # netbsd ['kldstat',''], - ['pcictl','list'], - ['pcictl','list -ns'], + ['pcictl','pci0 list'], + ['pcictl','pci0 list -N'], + ['pcictl','pci0 list -n'], ); run_commands(\@cmds,'system-bsd'); # diskinfo -v @@ -1915,7 +1964,7 @@ sub system_files { @files = RepoData::get($data_dir); copy_files(\@files, 'repo'); # chdir "/etc"; - @files = main::globber('/etc/*[-_s[rR]elease,[vV]ersion,issue}*'); + @files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); push(@files, '/etc/issue'); push(@files, '/etc/lsb-release'); push(@files, '/etc/os-release'); @@ -2299,6 +2348,11 @@ sub user_debug_test_1 { # print(join(', ', PerlIO::get_layers(STDOUT)), "\n"); # close $duped; } +# see docs/optimization.txt +sub ram_use { + my ($name, $ref) = @_; + printf "%-25s %5d %5d\n", $name, size($ref), total_size($ref); +} #### ------------------------------------------------------------------- #### DOWNLOADER @@ -2352,7 +2406,7 @@ sub download_file { $debug_data = $result; } } - print "-------\nDownloader Data:\n$cmd\nResult: $debug_data\n" if $test[1]; + print "-------\nDownloader Data:\n$cmd\nResult: $debug_data\n" if $dbg[1]; log_data('data',"$cmd\nResult: $result") if $b_log; return $result; } @@ -2375,11 +2429,11 @@ sub get_file { my $msg = "Failed to connect to server/file!\n"; $msg .= "Response: ${content}Downloader: HTTP::Tiny URL: $url\nFile: $file"; log_data('data',$msg) if $b_log; - print error_defaults('download-error',$msg) if $test[1]; + print error_defaults('download-error',$msg) if $dbg[1]; $return = 0; } else { - if ( $debug ){ + if ($debug){ print "$response->{success}\n"; print "$response->{status} $response->{reason}\n"; while (my ($key, $value) = each %{$response->{'headers'}}) { @@ -2430,7 +2484,7 @@ sub set_downloader { $dl{'timeout'} = ''; } elsif ( $dl{'curl'} && check_program('curl') ){ - $quiet = '-s ' if !$test[1]; + $quiet = '-s ' if !$dbg[1]; $dl{'dl'} = 'curl'; $dl{'file'} = " -L ${quiet}-o "; $dl{'no-ssl'} = ' --insecure'; @@ -2439,7 +2493,7 @@ sub set_downloader { $dl{'ua'} = ' -A ' . $dl_ua; } elsif ($dl{'wget'} && check_program('wget') ){ - $quiet = '-q ' if !$test[1]; + $quiet = '-q ' if !$dbg[1]; $dl{'dl'} = 'wget'; $dl{'file'} = " ${quiet}-O "; $dl{'no-ssl'} = ' --no-check-certificate'; @@ -2449,14 +2503,15 @@ sub set_downloader { $dl{'ua'} = ' -U ' . $dl_ua; } elsif ($dl{'fetch'} && check_program('fetch')){ - $quiet = '-q ' if !$test[1]; + $quiet = '-q ' if !$dbg[1]; $dl{'dl'} = 'fetch'; $dl{'file'} = " ${quiet}-o "; $dl{'no-ssl'} = ' --no-verify-peer'; $dl{'stdout'} = " ${quiet}-o -"; $dl{'timeout'} = ' -T '; } - elsif ( $bsd_type eq 'openbsd' && check_program('ftp') ){ + # at least openbsd/netbsd + elsif ($bsd_type && check_program('ftp') ){ $dl{'dl'} = 'ftp'; $dl{'file'} = ' -o '; $dl{'null'} = ' 2>/dev/null'; @@ -2664,13 +2719,13 @@ sub check_items { elsif ($type eq 'recommended system programs'){ if ($bsd_type){ @data = qw(camcontrol dig dmidecode fdisk file glabel gpart ifconfig ipmi-sensors - ipmitool lsusb sudo smartctl sysctl tree upower uptime usbdevs); + ipmitool lsusb sudo smartctl sysctl tree upower uptime usbconfig usbdevs); $info_os = 'info-bsd'; } else { - @data = qw(blockdev dig dmidecode fdisk file hciconfig hddtemp ifconfig ip ipmitool - ipmi-sensors lsblk lsusb lvs mdadm modinfo runlevel sensors smartctl strings - sudo tree upower uptime); + @data = qw(blockdev bt-adapter dig dmidecode fdisk file hciconfig hddtemp + ifconfig ip ipmitool ipmi-sensors lsblk lsusb lvs mdadm modinfo runlevel + sensors smartctl strings sudo tree upower uptime); } $b_program = 1; $item = 'Program'; @@ -2901,6 +2956,13 @@ sub item_data { 'pacman' => 'util-linux', 'rpm' => 'util-linux', }, + 'bt-adapter' => { + 'info' => '-E bluetooth data (if no hciconfig)', + 'info-bsd' => '', + 'apt' => 'bluez-tools', + 'pacman' => 'bluez-tools', + 'rpm' => 'bluez-tools', + }, 'curl' => { 'info' => '-i (if no dig); -w,-W; -U', 'info-bsd' => '-i (if no dig); -w,-W; -U', @@ -2972,10 +3034,10 @@ sub item_data { 'rpm' => '', }, 'hciconfig' => { - 'info' => '-E bluetooth HCI data', + 'info' => '-E bluetooth data (deprecated, good report)', 'info-bsd' => '', 'apt' => 'bluez', - 'pacman' => 'bluez-utils', + 'pacman' => 'bluez-utils-compat (frugalware: bluez-utils)', 'rpm' => 'bluez-utils', }, 'hddtemp' => { @@ -3111,9 +3173,16 @@ sub item_data { 'pacman' => 'procps', 'rpm' => 'procps', }, + 'usbconfig' => { + 'info' => '', + 'info-bsd' => '-A; -E; -G; -J; -N; (alternate: usbdevs)', + 'apt' => 'usbutils', + 'pacman' => 'usbutils', + 'rpm' => 'usbutils', + }, 'usbdevs' => { 'info' => '', - 'info-bsd' => '-A; -J; -N;', + 'info-bsd' => '-A; -E; -G; -J; -N; (alternate: usbconfig)', 'apt' => 'usbutils', 'pacman' => 'usbutils', 'rpm' => 'usbutils', @@ -3131,7 +3200,7 @@ sub item_data { 'info-bsd' => '-G glx info', 'apt' => 'mesa-utils', 'pacman' => 'mesa-demos', - 'rpm' => 'glx-utils (openSUSE 12.3 and later Mesa-demo-x)', + 'rpm' => 'glx-utils (SUSE: Mesa-demo-x)', }, 'wmctrl' => { 'info' => '-S active window manager (fallback)', @@ -3145,7 +3214,7 @@ sub item_data { 'info-bsd' => '-G multi screen resolution', 'apt' => 'X11-utils', 'pacman' => 'xorg-xdpyinfo', - 'rpm' => 'xorg-x11-utils', + 'rpm' => 'xorg-x11-utils (SUSE: xdpyinfo)', }, 'xprop' => { 'info' => '-S desktop data', @@ -3385,10 +3454,16 @@ sub grabber { eval $start if $b_log; my ($cmd,$split,$strip) = @_; $split ||= "\n"; - my @rows = split(/$split/, qx($cmd)); - if ($strip && @rows){ - @rows = grep {/^\s*[^#]/} @rows; - @rows = map {s/^\s+|\s+$//g; $_} @rows if @rows; + my @rows; + if ($strip){ + for (split(/$split/, qx($cmd))){ + next if /^\s*(#|$)/; + $_ =~ s/^\s+|\s+$//g; + push(@rows,$_); + } + } + else { + @rows = split(/$split/, qx($cmd)); } eval $end if $b_log; return @rows; @@ -3518,6 +3593,7 @@ sub set_program_values { 'clfswm' => ['^clsfwm',0,'0','clfswm',0,1,0,'',''], # no version 'compiz' => ['^compiz',2,'--version','Compiz',0,1,0,'',''], 'compton' => ['^\d',1,'--version','Compton',0,1,0,'',''], + 'ctwm' => ['^\S',1,'-version','ctwm',0,1,0,'',''], 'cwm' => ['^cwm',0,'0','CWM',0,1,0,'',''], # no version 'dcompmgr' => ['^dcompmgr',0,'0','dcompmgr',0,1,0,'',''], # unverified 'deepin' => ['^Version',2,'file','Deepin',0,100,'=','','/etc/deepin-version'], # special @@ -3533,10 +3609,11 @@ sub set_program_values { 'fireplace' => ['^fireplace',0,'0','fireplace',0,1,0,'',''], # unverified 'fluxbox' => ['^fluxbox',2,'-v','Fluxbox',0,1,0,'',''], 'flwm' => ['^flwm',0,'0','FLWM',0,0,1,'',''], # no version - 'fvwm' => ['^fvwm',2,'-version','FVWM',0,1,0,'',''], + #openbsd changed: version string: [FVWM[[main] Fvwm.. sigh, and outputs to stderr. Why? + 'fvwm' => ['^fvwm',2,'-version','FVWM',0,1,0,'',''], 'fvwm1' => ['^Fvwm',3,'-version','FVWM1',0,1,1,'',''], - 'fvwm2' => ['^fvwm',2,'--version','fVWM2',0,1,0,'',''], - 'fvwm3' => ['^fvwm',2,'--version','fVWM3',0,1,0,'',''], + 'fvwm2' => ['^fvwm',2,'--version','FVWM2',0,1,0,'',''], + 'fvwm3' => ['^fvwm',2,'--version','FVWM3',0,1,0,'',''], 'fvwm95' => ['^fvwm',2,'--version','FVWM95',0,1,1,'',''], 'fvwm-crystal' => ['^fvwm',2,'--version','FVWM-Crystal',0,0,0,'',''], # for print name fvwm 'gala' => ['^gala',0,'0','gala',0,1,0,'',''], # pantheon wm: super slow result, 2, '--version' works? @@ -3621,7 +3698,7 @@ sub set_program_values { 'unagi' => ['^\S',1,'--version','unagi',0,1,0,'',''], 'unity' => ['^unity',2,'--version','Unity',0,1,0,'',''], 'unity-system-compositor' => ['^unity-system-compositor',2,'--version', - 'unity-system-compositor (mir)',0,0,0,'',''], + 'unity-system-compositor (mir)',0,0,0,'',''], 'wavy' => ['^wavy',0,'0','wavy',0,1,0,'',''], # unverified 'waycooler' => ['^way',3,'--version','way-cooler',0,1,0,'',''], 'way-cooler' => ['^way',3,'--version','way-cooler',0,1,0,'',''], @@ -3668,7 +3745,7 @@ sub set_program_values { 'xdm' => ['^xdm',0,'0','XDM',0,1,0,'',''], 'xenodm' => ['^xenodm',0,'0','xenodm',0,1,0,'',''], ## Shells - not checked: ion, eshell ## - ## See test_shell() for unhandled but known shells + ## See ShellData::shell_test() for unhandled but known shells 'ash' => ['',3,'pkg','ash',1,0,0,'',''], # special; dash precursor 'bash' => ['^GNU[[:space:]]bash',4,'--version','Bash',1,1,0,'',''], 'busybox' => ['^busybox',0,'0','BusyBox',1,0,0,'',''], # unverified, hush/ash likely @@ -3870,8 +3947,13 @@ sub reader { chomp(my @rows = <$fh>); close $fh if $fh; if (@rows && $strip){ - @rows = grep {/^\s*[^#]/} @rows; - @rows = map {s/^\s+|\s+$//g; $_} @rows if @rows; + my @temp; + for (@rows){ + next if /^\s*(#|$)/; + $_ =~ s/^\s+|\s+$//g; + push(@temp,$_); + } + @rows = @temp; } eval $end if $b_log; # note: returns undef scalar value if $rows[index] does not exist @@ -3924,7 +4006,7 @@ sub writer { #### ------------------------------------------------------------------- #### UPDATER -##### ------------------------------------------------------------------- +#### ------------------------------------------------------------------- # arg 1: type to return sub get_defaults { @@ -3936,9 +4018,9 @@ sub get_defaults { 'inxi-dev' => 'https://smxi.org/in/', 'inxi-main' => 'https://github.com/smxi/inxi/raw/master/', 'inxi-pinxi' => 'https://github.com/smxi/inxi/raw/inxi-perl/', - 'inxi-man' => "https://smxi.org/in/$self_name.1.gz", + 'inxi-man' => "https://smxi.org/in/$self_name.1", 'inxi-man-gh' => "https://github.com/smxi/inxi/raw/master/$self_name.1", - 'pinxi-man' => "https://smxi.org/in/$self_name.1.gz", + 'pinxi-man' => "https://smxi.org/in/$self_name.1", 'pinxi-man-gh' => "https://github.com/smxi/inxi/raw/inxi-perl/$self_name.1", ); if ( exists $defaults{$type}){ @@ -3980,11 +4062,12 @@ sub update_me { $file_contents = download_file('stdout', $self_download); # then do the actual download - if ( $file_contents ){ + if ($file_contents){ # make sure the whole file got downloaded and is in the variable + print "Validating downloaded data...\n"; if ( $file_contents =~ /###\*\*EOF\*\*###/ ){ open(my $fh, '>', $full_self_path); - print $fh $file_contents or error_handler('write', "$full_self_path", "$!" ); + print $fh $file_contents or error_handler('write', $full_self_path, "$!" ); close $fh; qx( chmod +x '$self_path/$self_name' ); set_version_data(); @@ -3993,10 +4076,9 @@ sub update_me { $output .= "New $download_id version release date: $self_date\n"; $output .= "To run the new version, just start $self_name again.\n"; $output .= "$line3\n"; - $output .= "Starting download of man page file now.\n"; print $output; $output = ''; - if ($b_man){ + if ($use{'man'}){ update_man($download_id); } else { @@ -4016,12 +4098,12 @@ sub update_me { } sub update_man { + eval $start if $b_log; my ($download_id) = @_; - my $man_file_location=set_man_location(); - my $man_file_path="$man_file_location/$self_name.1" ; - my ($man_file_url,$output) = ('',''); - - my $b_downloaded = 0; + my $man_file_location = set_man_location(); + my $man_file_path = "$man_file_location/$self_name.1" ; + my ($file_contents,$man_file_url,$output,$program) = ('','','',''); + print "Starting download of man page file now.\n"; if ( ! -d $man_file_location ){ print "The required man directory was not detected on your system.\n"; print "Unable to continue: $man_file_location\n"; @@ -4039,39 +4121,51 @@ sub update_man { system( 'mandb' ); } } - # first choice is inxi.1/pinxi.1 from gh, second gz from smxi.org - if ( $download_id ne 'dev server' && (my $program = check_program('gzip'))){ - $man_file_url=get_defaults($self_name . '-man-gh'); - print "Downloading Man page file...\n"; - $b_downloaded = download_file('file', $man_file_url, $man_file_path); - if ($b_downloaded){ - print "Download successful. Compressing file...\n"; - system("$program -9 -f $man_file_path > $man_file_path.gz"); - my $err = $?; - if ($err > 0){ - print "Oh no! Something went wrong compressing the manfile:\n"; - print "Local path: $man_file_path Error: $err\n"; - } - else { - print "Download and install of man page successful.\nCheck to make sure it works: man $self_name\n"; - } - } + if (!($program = check_program('gzip'))){ + print "Required program gzip not found. Unable to install man page.\n"; + return 0; + } + # first choice is inxi.1/pinxi.1 from gh, second from smxi.org + if ($download_id ne 'dev server'){ + $man_file_url = get_defaults($self_name . '-man-gh'); } else { $man_file_url = get_defaults($self_name . '-man'); - # used to use spider tests, but only wget supports that, so no need - print "Downloading Man page file gz...\n"; - $man_file_path .= '.gz'; - # returns perl, 1 for true, 0 for false, even when using shell tool returns - $b_downloaded = download_file('file', $man_file_url, $man_file_path ); - if ($b_downloaded) { - print "Download and install of man page successful.\nCheck to make sure it works: man $self_name\n"; + } + print "Updating $self_name.1 in $man_file_location\n"; + print "using $download_id branch as download source\n"; + print "Downloading man page file...\n"; + print "Download URL: $man_file_url\n" if $dbg[1]; + $file_contents = download_file('stdout', $man_file_url); + if ($file_contents){ + # make sure the whole file got downloaded and is in the variable + print "Download successful. Validating downloaded man file data...\n"; + if ( $file_contents =~ m|\.\\" EOF|) { + print "Contents validated. Writing to man location...\n"; + open(my $fh, '>', $man_file_path); + print $fh $file_contents or error_handler('write', $man_file_path, "$!" ); + close $fh; + print "Writing successful. Compressing file...\n"; + system("$program -9 -f $man_file_path > $man_file_path.gz"); + my $err = $?; + if ($err > 0){ + print "Oh no! Something went wrong compressing the man file!\n"; + print "Error: $err\n"; + } + else { + print "Download, install, and compression of man page successful.\n"; + print "Check to make sure it works: man $self_name\n"; + } + } + else { + error_handler('file-corrupt', "$self_name.1"); } } - if ( !$b_downloaded ){ - print "Oh no! Something went wrong downloading the Man file at:\n$man_file_url\n"; - print "Try -U with --dbg 1 for more information on the failure.\n"; + # now run the error handlers on any downloader failure + else { + error_handler('download-error', $man_file_url, $download_id); } + eval $end if $b_log; } sub set_man_location { @@ -4132,12 +4226,15 @@ sub set_version_data { #### OPTIONS HANDLER / VERSION ######################################################################## -sub get_options { +# OptionsHandler +{ +package OptionsHandler; +my (%trigger); +my ($self_download,$download_id); +sub get { eval $start if $b_log; $show{'short'} = 1; - my ($b_downloader,$b_help,$b_no_man,$b_no_man_force,$b_sensors_default, - $b_recommends,$b_updater,$b_version,$b_use_man,$self_download, $download_id); - GetOptions ( + Getopt::Long::GetOptions ( 'a|admin' => sub { $b_admin = 1;}, 'A|audio' => sub { @@ -4161,14 +4258,14 @@ sub get_options { $show{'battery-forced'} = 1; }, 'c|color:i' => sub { my ($opt,$arg) = @_; - if ( $arg >= 0 && $arg < get_color_scheme('count') ){ - set_color_scheme($arg); + if ( $arg >= 0 && $arg < main::get_color_scheme('count') ){ + main::set_color_scheme($arg); } elsif ( $arg >= 94 && $arg <= 99 ){ $colors{'selector'} = $arg; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, 'C|cpu' => sub { $show{'short'} = 0; @@ -4211,13 +4308,13 @@ sub get_options { $show{'graphic'} = 1; $show{'graphic-basic'} = 1; }, 'h|help|?' => sub { - $b_help = 1; }, + $trigger{'help'} = 1; }, 'i|ip' => sub { $show{'short'} = 0; $show{'ip'} = 1; $show{'network'} = 1; $show{'network-advanced'} = 1; - $b_downloader = 1 if ! check_program('dig');}, + $trigger{'downloader'} = 1 if ! main::check_program('dig');}, 'I|info' => sub { $show{'short'} = 0; $show{'info'} = 1; }, @@ -4237,7 +4334,7 @@ sub get_options { $limit = $arg; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'L|logical|lvm' => sub { $show{'short'} = 0; @@ -4279,7 +4376,7 @@ sub get_options { $show{'partition-sort'} = $arg; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'r|repos|repo' => sub { $show{'short'} = 0; @@ -4298,7 +4395,7 @@ sub get_options { $cpu_sleep = $arg; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'slots|slot' => sub { $show{'short'} = 0; @@ -4323,7 +4420,7 @@ sub get_options { $ps_count = $num if $num; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'u|uuid' => sub { $show{'short'} = 0; @@ -4380,7 +4477,7 @@ sub get_options { $extra = 2; } if ($arg >= 7 ){ - $b_downloader = 1 if ! check_program('dig'); + $trigger{'downloader'} = 1 if !main::check_program('dig'); $show{'bluetooth-forced'} = 1; $show{'cpu-flag'} = 1; $show{'ip'} = 1; @@ -4389,7 +4486,7 @@ sub get_options { } if ($arg >= 8 ){ $b_admin = 1; - $b_downloader = 1; + $trigger{'downloader'} = 1; $show{'logical'} = 1; $show{'process'} = 1; $show{'ps-cpu'} = 1; @@ -4400,37 +4497,37 @@ sub get_options { } } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'V|version' => sub { - $b_version = 1 }, + $trigger{'version'} = 1 }, 'w|weather' => sub { my ($opt) = @_; $show{'short'} = 0; - $b_downloader = 1; + $trigger{'downloader'} = 1; if ( $use{'weather'} ){ $show{'weather'} = 1; } else { - error_handler('distro-block', $opt); + main::error_handler('distro-block', $opt); } }, 'W|weather-location:s' => sub { my ($opt,$arg) = @_; $arg ||= ''; $arg =~ s/\s//g; $show{'short'} = 0; - $b_downloader = 1; + $trigger{'downloader'} = 1; if ( $use{'weather'} ){ if ($arg){ $show{'weather'} = 1; $show{'weather-location'} = $arg; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } } else { - error_handler('distro-block', $opt); + main::error_handler('distro-block', $opt); } }, 'ws|weather-source:s' => sub { my ($opt,$arg) = @_; @@ -4440,7 +4537,7 @@ sub get_options { $weather_source = $arg; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'weather-unit:s' => sub { my ($opt,$arg) = @_; @@ -4453,7 +4550,7 @@ sub get_options { $weather_unit = $arg; } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); } }, 'x|extra:i' => sub { my ($opt,$arg) = @_; @@ -4473,10 +4570,10 @@ sub get_options { $arg = 80; } if ( $arg =~ /\d/ && ($arg == 1 || $arg >= 80) ){ - set_display_width($arg); + main::set_display_width($arg); } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, 'z|filter' => sub { $use{'filter'} = 1; }, @@ -4491,23 +4588,23 @@ sub get_options { my ($opt,$arg) = @_; if ($arg == 40) { $dl{'tiny'} = 0; - $b_downloader = 1;} + $trigger{'downloader'} = 1;} elsif ($arg == 41) { $dl{'curl'} = 0; - $b_downloader = 1;} + $trigger{'downloader'} = 1;} elsif ($arg == 42) { $dl{'fetch'} = 0; - $b_downloader = 1;} + $trigger{'downloader'} = 1;} elsif ($arg == 43) { $dl{'wget'} = 0; - $b_downloader = 1;} + $trigger{'downloader'} = 1;} elsif ($arg == 44) { $dl{'curl'} = 0; $dl{'fetch'} = 0; $dl{'wget'} = 0; - $b_downloader = 1;} + $trigger{'downloader'} = 1;} else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, 'arm' => sub { $b_arm = 1 }, @@ -4515,39 +4612,36 @@ sub get_options { my ($opt,$arg) = @_; if ($arg =~ /^(darwin|dragonfly|freebsd|openbsd|netbsd)$/i){ $bsd_type = lc($arg); - $b_fake_bsd = 1; + $fake{'bsd'} = 1; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, - 'bsd-data:s' => sub { + 'bt-tool:s' => sub { my ($opt,$arg) = @_; - if ($arg =~ /^(dboot|pciconf|sysctl|usbdevs)$/i){ - $b_fake_dboot = 1 if $arg eq 'dboot'; - $b_fake_pciconf = 1 if $arg eq 'pciconf'; - $b_fake_sysctl = 1 if $arg eq 'sysctl'; - $b_fake_usbdevs = 1 if $arg eq 'usbdevs'; + if ($arg =~ /^(bluetoothctl|bt-adapter|hciconfig)$/i){ + $bt_tool = lc($arg); } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, 'dbg:i' => sub { my ($opt,$arg) = @_; if ($arg > 0) { - $test[$arg] = 1; + $dbg[$arg] = 1; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, 'debug:i' => sub { my ($opt,$arg) = @_; if ($arg =~ /^[1-3]|1[0-3]|2[0-4]$/){ - $debug=$arg; + $debugger{'level'} = $arg; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, 'debug-filter|debug-z' => sub { $debugger{'filter'} = 1 }, @@ -4570,16 +4664,17 @@ sub get_options { $debugger{'sys-print'} = 1; }, 'debug-test-1' => sub { $debugger{'test-1'} = 1; }, - 'debug-width:i' => sub { + 'debug-width|debug-y:i' => sub { my ($opt,$arg) = @_; + $arg ||= 80; if ($arg =~ /^[0-9]+$/ && ($arg == 1 || $arg >= 80)){ $debugger{'width'} = $arg; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, 'dig' => sub { - $b_skip_dig = 0; }, + $force{'no-dig'} = 0; }, 'display:s' => sub { my ($opt,$arg) = @_; if ($arg =~ /^:?([0-9\.]+)?$/){ @@ -4587,45 +4682,71 @@ sub get_options { $display ||= ':0'; $display = ":$display" if $display !~ /^:/; $b_display = ($b_root) ? 0 : 1; - $b_force_display = 1; + $force{'display'} = 1; $display_opt = "-display $display"; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, - 'dmidecode' => sub { - $b_dmidecode_force = 1 }, + 'dmi|dmidecode' => sub { + $force{'dmidecode'} = 1 }, 'downloader:s' => sub { my ($opt,$arg) = @_; $arg = lc($arg); if ($arg =~ /^(curl|fetch|ftp|perl|wget)$/){ - if ($arg eq 'perl' && (!check_perl_module('HTTP::Tiny') || !check_perl_module('IO::Socket::SSL') )){ - error_handler('missing-perl-downloader', $opt, $arg); + if ($arg eq 'perl' && (!main::check_perl_module('HTTP::Tiny') || + !main::check_perl_module('IO::Socket::SSL') )){ + main::error_handler('missing-perl-downloader', $opt, $arg); } - elsif ( !check_program($arg)) { - error_handler('missing-downloader', $opt, $arg); + elsif ( !main::check_program($arg)) { + main::error_handler('missing-downloader', $opt, $arg); } else { # this dumps all the other data and resets %dl for only the # desired downloader. - $arg = set_perl_downloader($arg); + $arg = main::set_perl_downloader($arg); %dl = ('dl' => $arg, $arg => 1); - $b_downloader = 1; + $trigger{'downloader'} = 1; } } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); } }, - 'fake-cpu' => sub { - $b_fake_cpu = 1 }, - 'fake-dmi' => sub { - $b_fake_dmidecode = 1 }, - 'fake-logical' => sub { - $b_fake_logical = 1 }, - 'fake-raid' => sub { - $b_fake_raid = 1 }, - 'fake-sensors' => sub { - $b_fake_sensors = 1 }, + 'fake:s' => sub { + my ($opt,$arg) = @_; + if ($arg){ + my $wl = 'bluetooth|compiler|cpu|dboot|dmidecode|ipmi|logical|'; + $wl .= 'pciconf|pcictl|pcidump|raid-hw|raid-lvm|raid-md|raid-zfs|'; + $wl .= 'sensors|sysctl|uptime|usbconfig|usbdevs|vmstat|xorg-log'; + for (split(',',$arg)){ + if ($_ =~ /\b($wl)\b/){ + $fake{lc($1)} = 1; + } + else { + main::error_handler('bad-arg', $opt, $_); + } + } + } + else { + main::error_handler('bad-arg', $opt, $arg); + }}, + 'force:s' => sub { + my ($opt,$arg) = @_; + if ($arg){ + my $wl = 'display|dmidecode|hddtemp|lsusb|man|no-dig|no-doas|no-html-wan|'; + $wl .= 'no-sudo|usb-sys|vmstat|wmctrl'; + for (split(',',$arg)){ + if ($_ =~ /\b($wl)\b/){ + $force{lc($1)} = 1; + } + else { + main::error_handler('bad-arg', $opt, $_); + } + } + } + else { + main::error_handler('bad-arg', $opt, $arg); + }}, 'ftp:s' => sub { my ($opt,$arg) = @_; # pattern: ftp.x.x/x @@ -4633,73 +4754,70 @@ sub get_options { $ftp_alt = $arg; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, 'hddtemp' => sub { - $b_hddtemp_force = 1 }, + $force{'hddtemp'} = 1 }, 'host|hostname' => sub { $show{'host'} = 1; $show{'no-host'} = 0}, 'html-wan' => sub { - $b_no_html_wan = 0; }, + $force{'no-html-wan'} = 0; }, 'irc' => sub { $b_irc = 1; }, 'man' => sub { - $b_use_man = 1; }, + $trigger{'use-man'} = 1; }, 'mips' => sub { $b_mips = 1 }, 'output:s' => sub { my ($opt,$arg) = @_; if ($arg =~ /^(json|screen|xml)$/){ - if ($arg =~ /json|screen|xml/){ - $output_type = $arg; - } - else { - error_handler('option-feature-incomplete', $opt, $arg); - } + $output_type = $arg; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, 'no-dig' => sub { - $b_skip_dig = 1; }, + $force{'no-dig'} = 1; }, + 'no-doas' => sub { + $force{'no-doas'} = 1; }, 'no-host|no-hostname' => sub { $show{'host'} = 0 ; $show{'no-host'} = 1}, 'no-html-wan' => sub { - $b_no_html_wan= 1;}, + $force{'no-html-wan'}= 1;}, 'no-man' => sub { - $b_no_man_force = 0; }, + $trigger{'no-man-force'} = 0; }, 'no-ssl' => sub { $dl{'no-ssl-opt'}=1 }, 'no-sudo' => sub { - $b_no_sudo = 1; }, + $force{'no-sudo'} = 1; }, 'output-file:s' => sub { my ($opt,$arg) = @_; if ($arg){ - if ($arg eq 'print' || check_output_path($arg)){ + if ($arg eq 'print' || main::check_output_path($arg)){ $output_file = $arg; } else { - error_handler('output-file-bad', $opt, $arg); + main::error_handler('output-file-bad', $opt, $arg); } } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, 'ppc' => sub { $b_ppc = 1 }, 'recommends' => sub { - $b_recommends = 1; }, + $trigger{'recommends'} = 1; }, 'sensors-default' => sub { - $b_sensors_default = 1; }, + $trigger{'sensors-default'} = 1; }, 'sensors-exclude:s' => sub { my ($opt,$arg) = @_; if ($arg){ @sensors_exclude = split(/\s*,\s*/, $arg); } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); }}, 'sensors-use:s' => sub { my ($opt,$arg) = @_; @@ -4707,7 +4825,7 @@ sub get_options { @sensors_use = split(/\s*,\s*/, $arg); } else { - error_handler('bad-arg',$opt,$arg); + main::error_handler('bad-arg',$opt,$arg); }}, 'sparc' => sub { $b_sparc = 1; }, @@ -4717,112 +4835,81 @@ sub get_options { $b_irc = 0; }, 'U|update:s' => sub { # 1,2,3 OR http://myserver/path/inxi my ($opt,$arg) = @_; - $b_downloader = 1; - if ( $use{'update'} ){ - $b_updater = 1; - if (!$arg && $self_name eq 'pinxi'){ - $b_man = 1; - $download_id = 'inxi-perl branch'; - $self_download = get_defaults('inxi-pinxi'); - } - elsif ($arg && $arg eq '3'){ - $b_man = 1; - $download_id = 'dev server'; - $self_download = get_defaults('inxi-dev'); - } - else { - if (!$arg){ - $download_id = 'main branch'; - $self_download = get_defaults('inxi-main'); - $b_man = 1; - $b_use_man = 1; - } - elsif ( $arg =~ /^[12]$/){ - $download_id = "branch $arg"; - $self_download = get_defaults("inxi-branch-$arg"); - } - elsif ( $arg =~ /^http/){ - $download_id = 'alt server'; - $self_download = $arg; - } - } - if (!$self_download){ - error_handler('bad-arg', $opt, $arg); - } - } - else { - error_handler('distro-block', $opt); - } }, + process_updater($opt,$arg);}, 'usb-sys' => sub { - $b_usb_sys = 1 }, + $force{'usb-sys'} = 1 }, 'usb-tool' => sub { - $b_usb_tool = 1 }, + $force{'lsusb'} = 1 }, 'wan-ip-url:s' => sub { my ($opt,$arg) = @_; if ($arg && $arg =~ /^(f|ht)tp[s]?:\/\//){ $wan_url = $arg; - $b_skip_dig = 1 + $force{'no-dig'} = 1; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, 'wm' => sub { - $b_wmctrl = 1 }, + $force{'wmctrl'} = 1 }, 'wrap-max|indent-min:i' => sub { my ($opt,$arg) = @_; if ($arg =~ /^\d+$/){ $size{'wrap-max'} = $arg; } else { - error_handler('bad-arg', $opt, $arg); + main::error_handler('bad-arg', $opt, $arg); }}, '<>' => sub { my ($opt) = @_; - error_handler('unknown-option', "$opt", "" ); } + main::error_handler('unknown-option', "$opt", "" ); } ) ; #or error_handler('unknown-option', "@ARGV", ''); ## run all these after so that we can change widths, downloaders, etc + post_process(); eval $end if $b_log; - CheckRecommends::run() if $b_recommends; - set_downloader() if $b_downloader || $wan_url || ($b_skip_dig && $show{'ip'}); # sets for either config or arg here - set_xorg_log() if $show{'graphic'}; - show_version() if $b_version; - show_options() if $b_help; - $b_man = 0 if (!$b_use_man || $b_no_man_force); - update_me( $self_download, $download_id ) if $b_updater; +} +sub post_process { + CheckRecommends::run() if $trigger{'recommends'}; + # sets for either config or arg here + main::set_downloader() if $trigger{'downloader'} || $wan_url || ($force{'no-dig'} && $show{'ip'}); + main::set_xorg_log() if $show{'graphic'}; + main::show_version() if $trigger{'version'}; + main::show_options() if $trigger{'help'}; + $use{'man'} = 0 if (!$trigger{'use-man'} || $trigger{'no-man-force'}); + main::update_me($self_download, $download_id) if $trigger{'updater'}; if ($output_type){ if ($output_type ne 'screen' && ! $output_file){ - error_handler('bad-arg', '--output', '--output-file not provided'); + main::error_handler('bad-arg', '--output', '--output-file not provided'); } } $show{'graphic-basic'} = 0 if $b_admin; - if ($b_sensors_default){ + if ($trigger{'sensors-default'}){ @sensors_exclude = (); @sensors_use = (); } if ($show{'short'} || $show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'logical'} || $show{'partition'} || $show{'partition-full'} || $show{'raid'} || $show{'unmounted'}){ - $b_block_tool = 1; + $use{'block-tool'} = 1; } if ($show{'raid'} || $show{'disk'} || $show{'disk-total'} || $show{'disk-basic'} || $show{'unmounted'}){ - $b_mdadm = 1; + $use{'mdadm'} = 1; } if ($bsd_type && ($show{'short'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'disk'})){ - $b_dm_boot_disk = 1; + $use{'dm-boot-disk'} = 1; } if ($bsd_type && ($show{'optical-basic'} || $show{'optical'})){ - $b_dm_boot_optical = 1 + $use{'dm-boot-optical'} = 1 } if ($b_admin && $show{'disk'}){ - $b_smartctl = 1; + $use{'smartctl'} = 1; } # triggers may extend to -D, -pP if ($show{'short'} || $show{'logical'} || $show{'raid'} || $show{'disk'} || $show{'disk-total'} || $show{'disk-basic'} || $show{'unmounted'}){ - $b_lvm = 1; + $use{'lvm'} = 1; } - set_sudo() if ( $show{'unmounted'} || ($extra > 0 && $show{'disk'}) ); + main::set_sudo() if ( $show{'unmounted'} || ($extra > 0 && $show{'disk'}) ); $extra = 3 if $b_admin; $use{'filter'} = 0 if $use{'filter-override'}; # override for things like -b or -v2 to -v3 @@ -4835,21 +4922,62 @@ sub get_options { $show{'disk-basic'} = 0; $show{'disk-total'} = 0; } - if ( $show{'ram'} || $show{'slot'} || ($show{'cpu'} && $extra > 1) || - ( ( $bsd_type || $b_dmidecode_force ) && ($show{'machine'} || $show{'battery'}) ) ){ - $b_dmi = 1; + if ($show{'ram'} || $show{'slot'} || ($show{'cpu'} && ($extra > 1 || $bsd_type)) || + ( ( $bsd_type || $force{'dmidecode'} ) && ($show{'machine'} || $show{'battery'}) ) ){ + $use{'dmidecode'} = 1; } if ($show{'audio'} || $show{'graphic'} || $show{'network'} || $show{'raid'} ){ - $b_pci = 1; + $use{'pci'} = 1; } if ($show{'usb'} || $show{'audio'} || $show{'bluetooth'} || $show{'graphic'} || $show{'network'} ){ - $b_usb = 1; + $use{'usb'} = 1; } - if ($bsd_type && ($show{'short'} || $show{'system'} || $show{'battery'} || $show{'cpu'} || $show{'cpu-basic'} || - $show{'info'} || $show{'machine'} || $show{'process'} || $show{'ram'} || $show{'sensor'} ) ){ - $b_sysctl = 1; + if ($bsd_type && ($show{'short'} || $show{'system'} || $show{'audio'} || $show{'battery'} || + $show{'cpu'} || $show{'cpu-basic'} || $show{'info'} || $show{'machine'} || + $show{'process'} || $show{'ram'} || $show{'sensor'} ) ){ + $use{'sysctl'} = 1; } -} +} +sub process_updater { + my ($opt,$arg) = @_; + $trigger{'downloader'} = 1; + if ($use{'update'}){ + $trigger{'updater'} = 1; + if (!$arg && $self_name eq 'pinxi'){ + $use{'man'} = 1; + $download_id = 'inxi-perl branch'; + $self_download = main::get_defaults('inxi-pinxi'); + } + elsif ($arg && $arg eq '3'){ + $use{'man'} = 1; + $download_id = 'dev server'; + $self_download = main::get_defaults('inxi-dev'); + } + else { + if (!$arg){ + $download_id = 'main branch'; + $self_download = main::get_defaults('inxi-main'); + $use{'man'} = 1; + $trigger{'use-man'} = 1; + } + elsif ( $arg =~ /^[12]$/){ + $download_id = "branch $arg"; + $self_download = main::get_defaults("inxi-branch-$arg"); + } + elsif ( $arg =~ /^http/){ + $download_id = 'alt server'; + $self_download = $arg; + } + } + if (!$self_download){ + main::error_handler('bad-arg', $opt, $arg); + } + } + else { + main::error_handler('distro-block', $opt); + } +} +} sub show_options { error_handler('not-in-irc', 'help') if $b_irc; @@ -4882,10 +5010,10 @@ sub show_options { $self_name^-FzjJxy^80" ], ['0', '', '', $line ], ['0', '', '', "Output Control Options (see Extra Data Options to extend output):" ], - ['1', '-A', '--audio', "Audio/sound devices(s), driver, sound server." ], + ['1', '-A', '--audio', "Audio/sound devices(s), driver, running sound servers." ], ['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ], - ['1', '-B', '--battery', "System battery info, including charge and condition, plus - extra info (if battery present)." ], + ['1', '-B', '--battery', "System battery info, including charge, condition + voltage (if critical), plus extra info (if battery present)." ], ['1', '-c', '--color', "Set color scheme (0-42). For piped or redirected output, you must use an explicit color selector. Example:^$self_name^-c^11" ], ['1', '', '', "Color selectors let you set the config file value for the @@ -4942,7 +5070,7 @@ sub show_options { ['1', '-o', '--unmounted', "Unmounted $partition_string info (includes UUID and Label if available). Shows file system type if you have lsblk installed (Linux) or, for BSD/GNU Linux, if 'file' installed and you are root or if - you have added to /etc/sudoers (sudo v. 1.7 or newer)." ], + you have added to /etc/sudoers (sudo v. 1.7 or newer)(BSDs: see doas)." ], ['1', '', '', "Example: ^^ALL^=^NOPASSWD:^/usr/bin/file^" ], ['1', '-p', '--partitions-full', "Full $partition_string information (-P plus all other detected ${partition_string}s)." ], @@ -4951,8 +5079,8 @@ 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, PACMAN, PACMAN-G2, PISI, PORTAGE, PORTS (BSDs), SLACKPKG, - TCE, URPMQ, XBPS, YUM/ZYPP." ], + APT, CARDS, EOPKG, NIX, PACMAN, PACMAN-G2, PISI, PKG (BSDs), PORTAGE, PORTS + (BSDs), SCRATCHPKG, SLACKPKG, 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." ], ['1', '-s', '--sensors', "Sensors output (if sensors installed/configured): @@ -5027,7 +5155,7 @@ sub show_options { ['2', '-A', '', "If available: list of alternate kernel modules/drivers for device(s)." ], ['2', '-C', '', "If available: CPU socket type, base/boost speeds - (dmidecode+root/sudo required); CPU vulnerabilities (bugs); + (dmidecode+root/sudo/doas[BSDs] required); CPU vulnerabilities (bugs); family, model-id, stepping - format: hex (decimal) if greater than 9, otherwise hex; microcode - format: hex." ], ['2', '-d,-D', '', "If available: logical and physical block sizes; drive family; @@ -5039,7 +5167,8 @@ sub show_options { resolution; hz; dpi; size; diagonal; list of alternate kernel modules/drivers for device(s)." ], ['2', '-I', '', "As well as per package manager counts, also adds total - number of lib files found for each package manager if not -r." ], + number of lib files found for each package manager 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', '-L', '', "LV, Crypto, devices, components: add maj:min; show @@ -5056,9 +5185,10 @@ sub show_options { ['1', '-x', '--extra', "Adds the following extra data (only works with verbose or line output, not short form):" ], ['2', '-A', '', "Specific vendor/product information (if relevant); - PCI/USB ID of device; Version/port(s)/driver version (if available)." ], - ['2', '-B', '', "Vendor/model, status (if available); attached devices - (e.g. wireless mouse, keyboard, if present)." ], + PCI/USB ID of device; Version/port(s)/driver version (if available); + non-running sound servers." ], + ['2', '-B', '', "Current/minimum voltage, vendor/model, status (if available); + attached devices (e.g. wireless mouse, keyboard, if present)." ], ['2', '-C', '', "CPU $flags (short list, use -f to see full list); CPU boost (turbo) enabled/disabled, if present; Bogomips on CPU; CPU microarchitecture + revision (if found, or @@ -5068,7 +5198,7 @@ sub show_options { ['2', '-D', '', "HDD temp with disk data. Kernels >= 5.6: enable module drivetemp if not enabled. Older systems require hddtemp, run as as superuser, or as user if you have added hddtemp to /etc/sudoers - (sudo v. 1.7 or newer). + (sudo v. 1.7 or newer)(BSDs see doas). Example:^^ALL^=^NOPASSWD:^/usr/sbin/hddtemp" ], ['2', '-E', '', "PCI/USB Bus ID of device, driver version, LMP version." ], @@ -5091,7 +5221,7 @@ sub show_options { ['2', '-r', '', "Packages, see -Ix." ], ['2', '-R', '', "md-raid: second RAID Info line with extra data: blocks, chunk size, bitmap (if present). Resync line, shows blocks - synced/total blocks. Hardware RAID driver version, bus ID." ], + synced/total blocks. Hardware RAID driver version, bus-ID." ], ['2', '-s', '', "Basic voltages (ipmi, lm-sensors if present): 12v, 5v, 3.3v, vbat." ], ['2', '-S', '', "Kernel gcc version; system base of distro (if relevant and detected)" ], @@ -5108,7 +5238,7 @@ 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." ], - ['2', '-B', '', "Serial number, voltage now/minimum (if available)." ], + ['2', '-B', '', "Serial number." ], ['2', '-C', '', "L1/L3 cache (if root and dmidecode installed)." ], ['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number; LVM volume group free space (if available)." ], @@ -5123,7 +5253,7 @@ sub show_options { IRC. Adds Init version number, RC (if found). Adds per package manager package counts if not -r." ], ['2', '-j,-p,-P', '', "Swap priority." ], - ['2', '-J', '', "Vendor:chip ID." ], + ['2', '-J', '', "Vendor:chip-ID." ], ['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." ], @@ -5156,10 +5286,10 @@ sub show_options { rotation speed/SSD (if detected)." ], ['2', '-E', '', "Serial number, class ID, HCI version and revision." ], ['2', '-G', '', "Serial number, class ID." ], - ['2', '-I', '', "For 'Shell:' adds ([su|sudo|login]) to shell name if present; + ['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', '', "For Device: serial number (if present), interface count; USB speed." ], + ['2', '-J', '', "If present: Devices: serial number, interface count; USB speed; 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 voltage, if available; serial number." ], @@ -5169,7 +5299,7 @@ sub show_options { Hardware RAID rev, ports, specific vendor/product information." ], ['2', '-S', '', "Panel/tray/bar/dock info in desktop output, if in X (like lxpanel, xfce4-panel, mate-panel); (if available) dm version number, window manager - version number."], + version number, virtual terminal number."], ); if ( $use{'weather'} ){ push(@data, @@ -5210,11 +5340,14 @@ sub show_options { ['2', '43', '', "Bypass Wget as a downloader option." ], ['2', '44', '', "Bypass Curl, Fetch, and Wget as downloader options. Forces Perl if HTTP::Tiny present." ], + ['1', '', '--bt-tool', "[bt-adapter|hciconfig] Force use of given tool for bluetooth." ], ['1', '', '--dig', "Overrides configuration item NO_DIG (resets to default)." ], ['1', '', '--display', "[:[0-9]] Try to get display data out of X (default: display 0)." ], ['1', '', '--dmidecode', "Force use of dmidecode data instead of /sys where relevant (e.g. -M, -B)." ], ['1', '', '--downloader', "Force $self_name to use [curl|fetch|perl|wget] for downloads." ], + ['1', '', '--force', "[dmidecode|hddtemp|lsusb|usb-sys|vmstat|wmctl]. Force use of item, + see --hddtemp, --dmidecode, --wm, --usb-tool, --usb-sys." ], ['1', '', '--hddtemp', "Force use of hddtemp for disk temps." ], ['1', '', '--host', "Turn on hostname for -S." ], ['1', '', '--html-wan', "Overrides configuration item NO_HTML_WAN (resets to default)." ], @@ -5228,6 +5361,8 @@ sub show_options { } push(@data, ['1', '', '--no-dig', "Skip dig for WAN IP checks, use downloader program." ], + ['1', '', '--no-doas', "Skip internal program use of doas features (not related + to starting $self_name with doas)." ], ['1', '', '--no-host', "Turn off hostname for -S. Useful if showing output from servers etc. -z triggers --no-host." ], ['1', '', '--no-html-wan', "Skip HTML IP sources for WAN IP checks, use dig only, @@ -5261,8 +5396,9 @@ sub show_options { inside of another tool like Chef or MOTD and returns corrupted color codes. Please see man page or file an issue if you need to use this flag. Must use -y [width] option if you want a specific output width. Always put this option first in an option list."], - ['1', '', '--usb-sys', "Force USB data to use /sys as data source (Linux only)." ], - ['1', '', '--usb-tool', "Force USB data to use lsusb as data source (Linux only)." ], + ['1', '', '--usb-sys', "Force USB data to use only /sys as data source (Linux only)." ], + ['1', '', '--usb-tool', "Force USB data to use lsusb as data source [default] + (Linux only)." ], ['1', '', '--wan-ip-url', "[URL] Skips dig, uses supplied URL for WAN IP (-i). URL output must end in the IP address. See man. Example:^$self_name^-i^--wan-ip-url^https://yoursite.com/ip.php" ], @@ -5288,12 +5424,12 @@ sub show_options { ['2', '22', '', "Upload debugger dataset to $self_name debugger server automatically, removes debugger data directory and debugger tar.gz file." ], # ['1', '', '--debug-filter', "Add -z flag to debugger $self_name optiions." ], - ['1', '', '--debug-proc', "Force debugger parsing of /proc as sudo/root." ], + ['1', '', '--debug-proc', "Force debugger parsing of /proc as sudo/doas/root." ], ['1', '', '--debug-proc-print', "To locate file that /proc debugger hangs on." ], ['1', '', '--debug-no-exit', "Skip exit on error to allow completion." ], ['1', '', '--debug-no-proc', "Skip /proc debugging in case of a hang." ], ['1', '', '--debug-no-sys', "Skip /sys debugging in case of a hang." ], - ['1', '', '--debug-sys', "Force PowerPC debugger parsing of /sys as sudo/root." ], + ['1', '', '--debug-sys', "Force PowerPC debugger parsing of /sys as sudo/doas/root." ], ['1', '', '--debug-sys-print', "To locate file that /sys debugger hangs on." ], ['1', '', '--ftp', "Use with --debugger 21 to trigger an alternate FTP server for upload. Format:^[ftp.xx.xx/yy]. Must include a remote directory to upload to. @@ -5364,10 +5500,9 @@ sub show_version { package StartClient; # use warnings; # use strict; -my $ppid = ''; my $pppid = ''; -# NOTE: there's no reason to crete an object, we can just access +# NOTE: there's no reason to create an object, we can just access # the features statically. # args: none # sub new { @@ -5377,14 +5512,11 @@ my $pppid = ''; # # print "$type\n"; # return bless $self, $class; # } - -sub get_client_data { +sub set { eval $start if $b_log; - $ppid = getppid(); - main::set_ps_aux() if ! @ps_aux; + main::set_ps_aux() if !$loaded{'ps-aux'}; if (!$b_irc){ # we'll run get_shell_data for -I, but only then - $client{'ppid'} = $ppid; } else { $use{'filter'} = 1; @@ -5399,14 +5531,13 @@ sub get_client_data { sub get_client_name { eval $start if $b_log; my $client_name = ''; - # print "$ppid\n"; if ($ppid && -e "/proc/$ppid/exe" ){ $client_name = lc(readlink "/proc/$ppid/exe"); $client_name =~ s/^.*\///; if ($client_name =~ /^bash|dash|sh|python.*|perl.*$/){ - $pppid = (main::grabber("ps -p $ppid -o ppid"))[1]; - #my @temp = (main::grabber("ps -p $ppid -o ppid 2>/dev/null"))[1]; + $pppid = (main::grabber("ps -wwp $ppid -o ppid"))[1]; + #my @temp = (main::grabber("ps -wwp $ppid -o ppid 2>/dev/null"))[1]; $pppid =~ s/^\s+|\s+$//g; $client_name =~ s/[0-9\.]+$//; # clean things like python2.7 if ($pppid && -f "/proc/$pppid/exe" ){ @@ -5421,13 +5552,12 @@ sub get_client_name { #print "$client{'name-print'}\n"; } else { - if (! check_modern_konvi() ){ - $ppid = getppid(); - $client_name = (main::grabber("ps -p $ppid"))[1]; + if (!check_modern_konvi()){ + $client_name = (main::grabber("ps -wwp $ppid 2>/dev/null"))[1]; if ($client_name){ - my @data = split(/\s+/, $client_name) if $client_name; + my @data = split(/\s+/, $client_name); if ($bsd_type){ - $client_name = lc($data[5]); + $client_name = lc($data[4]); } # gnu/linux uses last value else { @@ -5500,7 +5630,7 @@ sub get_client_version { elsif ($client{'name'} eq 'konversation') { $client{'konvi'} = ( ! $client{'native'} ) ? 2 : 1; } - elsif ($client{'name'} =~ /quassel/) { + elsif ($client{'name'} =~ /quassel/i) { @data = main::grabber("$client{'name'} -v 2>/dev/null"); foreach (@data){ if ($_ =~ /^Quassel IRC:/){ @@ -5538,18 +5668,20 @@ sub get_client_version { elsif ($client{'name'} =~ /python/) { perl_python_client(); } + # NOTE: these must be empirically determined, not all events that + # show no tty are actually IRC. tmux is not a vt, but runs inside one if (!$client{'name-print'}) { - # NOTE: these must be empirically determined, not all events that - # show no tty are actually IRC. - my $wl_terms = 'alacritty|evilvte|germinal|guake|hyper|kate|kitty|kmscon|'; - $wl_terms .= 'konsole|minicom|putty|rxvt|sakura|shellinabox|^st$|sudo|term|tilda|'; - $wl_terms .= 'tilix|urvxt|yaft|yakuake'; + my $wl_terms = 'alacritty|altyo|black-screen|conhost|doas|evilvte|'; + $wl_terms .= 'germinal|guake|havoc|hyper|kate|kitty|kmscon|konsole|login|'; + $wl_terms .= 'macwise|minicom|putty|rxvt|sakura|securecrt|shellinabox|'; + $wl_terms .= '^st$|sudo|term|tilda|tilix|tmux|tym|wayst|xiki|'; + $wl_terms .= 'yaft|yakuake|\bzoc\b'; my $wl_clients = 'ansible|chef|run-parts|sshd'; my $whitelist = "$wl_terms|$wl_clients"; # print "$client{'name'}\n"; if ($client{'name'} =~ /($whitelist)/i){ if ($client{'name'} =~ /($wl_terms)/i){ - main::get_shell_data($ppid); + ShellData::set(); } else { $client{'name-print'} = $client{'name'}; @@ -5566,7 +5698,6 @@ sub get_cmdline { eval $start if $b_log; my @cmdline; my $i = 0; - $ppid = getppid(); if (! -e "/proc/$ppid/cmdline" ){ return 1; } @@ -5945,6 +6076,7 @@ sub row_defaults { 'battery-data' => 'No system Battery data found. Is one present?', 'battery-data-sys' => 'No /sys data found.', 'bluetooth-data' => 'No Bluetooth data was found.', + 'bluetooth-down' => "$id can't run.", 'cpu-bugs-null' => 'No CPU vulnerability/bugs data available.', 'cpu-model-null' => 'Model N/A', 'cpu-speeds' => "No speed data found for $id cores.", @@ -6009,6 +6141,8 @@ sub row_defaults { 'tool-permissions' => "Unable to run $id. Root privileges required.", 'tool-present' => 'Present and working', 'tool-unknown-error' => "Unknown $id error. Unable to generate data.", + 'tools-missing' => "This feature requires one of these tools: $id", + 'tools-missing-bsd' => "This feature requires one of these BSD tools: $id", 'unmounted-data' => 'No Unmounted partitions found.', 'unmounted-data-bsd' => 'No Unmounted partition data found for this BSD system.', 'unmounted-file' => 'No /proc/partitions file found.', @@ -6023,31 +6157,37 @@ sub row_defaults { } # convert string passed to KB, based on GB/MB/TB id -# NOTE: K 1024 KB 1000 +# NOTE: K 1024 KB 1000 KiB 1024 +# 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 = 0; + my ($size,$unit) = (0,''); #print ":$working:\n"; return if ! defined $working; - my $math = ( $working =~ /B$/) ? 1000: 1024; - if ( $working =~ /^([0-9\.]+)\s*M[B]?$/i){ + my $math = ($working =~ /B$/) ? 1000: 1024; + if ($working =~ /^([0-9\.]+)\s*([kKMGTPE])i?B?$/i){ + $size = $1; + $unit = uc($2); + } + if ($unit eq 'K'){ + $size = $1; + } + elsif ($unit eq 'M'){ $size = $1 * $math; } - elsif ( $working =~ /^([0-9\.]+)\s*G[B]?$/i){ + elsif ($unit eq 'G'){ $size = $1 * $math**2; } - elsif ( $working =~ /^([0-9\.]+)\s*T[B]?$/i){ + elsif ($unit eq 'T'){ $size = $1 * $math**3; } - elsif ( $working =~ /^([0-9\.]+)\s*P[B]?$/i){ + elsif ($unit eq 'P'){ $size = $1 * $math**4; } - elsif ( $working =~ /^([0-9\.]+)\s*E[B]?$/i){ + elsif ($unit eq 'E'){ $size = $1 * $math**5; } - elsif ( $working =~ /^([0-9\.]+)\s*[kK][B]?$/i){ - $size = $1; - } $size = int($size) if $size; return $size; } @@ -6290,6 +6430,7 @@ sub print_data { 'Monitor' => 1, 'Optical' => 1, 'Screen' => 1, + 'Sound Server' => 1, 'variant' => 1, # arm > 1 cpu type ); foreach my $val1 (@{$data->{$key1}}){ @@ -6482,7 +6623,7 @@ sub get { eval $start if $b_log; my (@rows); my $num = 0; - if (($b_arm || $b_mips) && !$b_soc_audio && !$b_pci_tool){ + if (($b_arm || $b_mips) && !$use{'soc-audio'} && !$use{'pci-tool'}){ my $type = ($b_arm) ? 'arm' : 'mips'; my $key = 'Message'; push(@rows,{ @@ -6492,7 +6633,7 @@ sub get { else { push(@rows,device_output()); } - if ( ( (($b_arm || $b_mips) && !$b_soc_audio && !$b_pci_tool) || !@rows ) && + if ( ( (($b_arm || $b_mips) && !$use{'soc-audio'} && !$use{'pci-tool'}) || !@rows ) && (my $file = main::system_files('asound-cards') ) ){ push(@rows,asound_output($file)); } @@ -6521,16 +6662,16 @@ sub device_output { $j = scalar @rows; my $driver = $row->[9]; $driver ||= 'N/A'; - my $card = $row->[4]; - $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; + my $device = $row->[4]; + $device = ($device) ? main::pci_cleaner($device,'output') : 'N/A'; # have seen absurdly verbose card descriptions, with non related data etc - if (length($card) > 85 || $size{'max'} < 110){ - $card = main::pci_long_filter($card); + if (length($device) > 85 || $size{'max'} < 110){ + $device = main::pci_long_filter($device); } push(@rows, { - main::key($num++,1,1,'Device') => $card, + main::key($num++,1,1,'Device') => $device, },); - if ($extra > 0 && $b_pci_tool && $row->[12]){ + if ($extra > 0 && $use{'pci-tool'} && $row->[12]){ my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]->{main::key($num++,0,2,'vendor')} = $item if $item; } @@ -6546,7 +6687,7 @@ sub device_output { $rows[$j]->{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10]; } if ($extra > 0){ - $rows[$j]->{main::key($num++,0,2,'bus ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; + $rows[$j]->{main::key($num++,0,2,'bus-ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; } if ($extra > 1){ my $chip_id = 'N/A'; @@ -6556,9 +6697,9 @@ sub device_output { elsif ($row->[6]){ $chip_id = $row->[6]; } - $rows[$j]->{main::key($num++,0,2,'chip ID')} = $chip_id; + $rows[$j]->{main::key($num++,0,2,'chip-ID')} = $chip_id; if ($extra > 2 && $row->[1]){ - $rows[$j]->{main::key($num++,0,2,'class ID')} = $row->[1]; + $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->[1]; } } #print "$row->[0]\n"; @@ -6573,7 +6714,7 @@ sub asound_output { eval $start if $b_log; my ($file) = @_; my (@asound,@rows); - my ($card,$driver,$j,$num) = ('','',0,1); + my ($device,$driver,$j,$num) = ('','',0,1); @asound = main::reader($file); foreach (@asound){ # filtering out modems and usb devices like webcams, this might get a @@ -6583,13 +6724,13 @@ sub asound_output { my @working = split(/:\s*/, $_); # now let's get 1 2 $working[1] =~ /(.*)\s+-\s+(.*)/; - $card = $2; + $device = $2; $driver = $1; - if ( $card ){ + if ($device){ $j = scalar @rows; $driver ||= 'N/A'; push(@rows, { - main::key($num++,1,1,'Device') => $card, + main::key($num++,1,1,'Device') => $device, main::key($num++,1,2,'driver') => $driver, },); if ($extra > 0){ @@ -6606,94 +6747,124 @@ sub asound_output { } sub usb_output { eval $start if $b_log; - my (@rows,@ids,$driver,$path_id,$product,@temp2); + my (@rows,@ids,$path_id,$product,@temp2); my ($j,$num) = (0,1); - if (-d '/proc/asound') { - # note: this will double the data, but it's easier this way. - # inxi tested for -L in the /proc/asound files, and used only those. - my @files = main::globber('/proc/asound/*/usbid'); - foreach (@files){ - my $id = main::reader($_,'',0); - push(@ids, $id) if ($id && ! grep {/$id/} @ids); + return if !@usb_audio; + foreach my $row (@usb_audio){ + # print Data::Dumper::Dumper $row; + $num = 1; + # make sure to reset, or second device trips last flag + ($path_id,$product) = ('',''); + $product = main::cleaner($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], + },); + if ($extra > 0){ + $rows[$j]->{main::key($num++,0,2,'bus-ID')} = "$path_id:$row->[1]"; } - # lsusb is a very expensive operation - if (@ids){ - if (!$bsd_type && !$b_usb_check){ - main::USBData::set(); - } + if ($extra > 1){ + $row->[7] ||= 'N/A'; + $rows[$j]->{main::key($num++,0,2,'chip-ID')} = $row->[7]; } - main::log_data('dump','@ids',\@ids) if $b_log; - return if !@usb; - foreach my $id (@ids){ - $j = scalar @rows; - foreach my $row (@usb){ - # a device will always be the second or > device on the bus - if ($row->[1] > 1 && $row->[7] eq $id){ - # print Data::Dumper::Dumper $row; - $num = 1; - # makre sure to reset, or second device trips last flag - ($driver,$path_id,$product) = ('','',''); - $product = main::cleaner($row->[13]) if $row->[13]; - $driver = $row->[15] if $row->[15]; - $path_id = $row->[2] if $row->[2]; - $product ||= 'N/A'; - $driver ||= 'snd-usb-audio'; - push(@rows, { - main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', - main::key($num++,0,2,'driver') => $driver, - },); - if ($extra > 0){ - $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::apply_filter($row->[16]); - } - } - } + 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::apply_filter($row->[16]); + } + $j = scalar @rows; } eval $end if $b_log; return @rows; } - sub sound_server_output { eval $start if $b_log; - my (@data,$server,$version); - my $num = 0; - if (my $file = main::system_files('asound-version') ){ - my $content = main::reader($file,'',0); - # some alsa strings have the build date in (...) - # remove trailing . and remove possible second line if compiled by user -# foreach (@content){ -# if (!/compile/i){ - #$_ =~ s/Advanced Linux Sound Architecture/ALSA/; - $version = (split(/\s+/, $content))[-1]; - $version =~ s/\.$//; # trim off period - $server = 'ALSA'; -# } -# } - } - elsif (my $program = main::check_program('oss')){ - $server = 'OSS'; - $version = main::program_version('oss','\S',2); - $version ||= 'N/A'; - } - if ($server){ - @data = ({ - main::key($num++,1,1,'Sound Server') => $server, - main::key($num++,0,2,'v') => $version, - },); + my (@rows,$program); + my ($j,$num) = (0,0); + my @servers = sound_server_data(); + for my $server (@servers){ + next if $extra < 1 && (!$server->[2] || $server->[2] ne 'yes'); + $j = scalar @rows; + $server->[1] ||= 'N/A'; + push(@rows, { + main::key($num++,1,1,'Sound Server') => $server->[0], + main::key($num++,0,2,'v') => $server->[1], + }); + $server->[2] ||= 'N/A'; + $rows[$j]->{main::key($num++,1,1,'running')} = $server->[2]; } eval $end if $b_log; - return @data; + return @rows; +} +sub sound_server_data { + eval $start if $b_log; + my (@servers,$program,$running,$server,$version); + if (my $file = main::system_files('asound-version') ){ + # avoid possible second line if compiled by user + my $content = main::reader($file,'',0); + # some alsa strings have the build date in (...) + $version = (split(/\s+/, $content))[-1]; + $version =~ s/\.$//; # trim off period + $server = 'ALSA'; + $running = 'yes'; + # not needed I think, if asound is there, it's running, but if that's + # not correct, can use one of the info/list/stat tests for aplay + #if (main::check_program('aplay') && main::grabber('aplay -l 2>/dev/null')){ + # $running = 'yes'; + #} + push(@servers, [$server,$version,$running]); + ($running,$server,$version) = ('','',''); + } + # sndstat file may be removed in linux oss + if (-e '/dev/sndstat' || ($program = main::check_program('ossinfo'))){ + $server = 'OSS'; + #$version = main::program_version('oss','\S',2); + $version = (grep {/^hw.snd.version:/} @sysctl_audio)[0] if @sysctl_audio; + $version = (split(/:\s*/,$version),1)[1] if $version; + $version =~ s|/.*$|| if $version; + # not a great test, but ok for now + $running = (-e '/dev/sndstat') ? 'yes' : 'no?'; + push(@servers, [$server,$version,$running]); + ($running,$server,$version) = ('','',''); + } + if ($program = main::check_program('sndiod')){ + $server = 'sndio'; + #$version = main::program_version('sndio','\S',2); + $running = (grep {/sndiod/} @ps_cmd) ? 'yes': 'no'; + push(@servers, [$server,$version,$running]); + ($running,$server,$version) = ('','',''); + } + if ($program = main::check_program('jackd')){ + $server = 'JACK'; + $version = main::program_version($program,'^jackd',3,'--version',1); + $running = (grep {/jackd/} @ps_cmd) ? 'yes':'no' ; + push(@servers, [$server,$version,$running]); + ($running,$server,$version) = ('','',''); + } + # note: pactl info/list/stat could be used + if ($program = main::check_program('pactl')){ + $server = 'PulseAudio'; + $version = main::program_version($program,'^pactl',2,'--version',1); + $running = (grep {m|/pulseaudiod?\b|} @ps_cmd) ? 'yes':'no' ; + push(@servers, [$server,$version,$running]); + ($running,$server,$version) = ('','',''); + } + if ($program = main::check_program('pipewire')){ + $server = 'PipeWire'; + $version = main::program_version($program,'^Compiled with libpipe',4,'--version',1); + $running = (grep {/pipewire/} @ps_cmd) ? 'yes':'no' ; + push(@servers, [$server,$version,$running]); + ($running,$server,$version) = ('','',''); + } + main::log_data('dump','sound servers: @servers',\@servers) if $b_log; + print Data::Dumper::Dumper \@servers if $dbg[26]; + return @servers; + eval $end if $b_log; } } @@ -6705,10 +6876,10 @@ sub get { eval $start if $b_log; my (@rows,%battery,$key1,$val1); my $num = 0; - if ($bsd_type || $b_dmidecode_force){ + if ($bsd_type || $force{'dmidecode'}){ if ($alerts{'dmidecode'}->{'action'} ne 'use'){ $key1 = $alerts{'dmidecode'}->{'action'}; - $val1 = $alerts{'dmidecode'}->{$key1}; + $val1 = $alerts{'dmidecode'}->{'message'}; $key1 = ucfirst($key1); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } @@ -6780,13 +6951,17 @@ sub battery_output { # print Data::Dumper::Dumper $battery; foreach $key (sort keys %$battery){ $num = 0; - my ($charge,$condition,$model,$serial,$status,$volts) = ('','','','','',''); + my ($charge,$condition,$model,$serial,$status) = ('','','','',''); my ($chemistry,$cycles,$location) = ('','',''); next if !$battery->{$key}{'purpose'} || $battery->{$key}{'purpose'} ne 'primary'; # $battery->{$key}{''}; # we need to handle cases where charge or energy full is 0 if (defined $battery->{$key}{'energy_now'} && $battery->{$key}{'energy_now'} ne ''){ $charge = "$battery->{$key}{'energy_now'} Wh"; + if ($battery->{$key}{'energy_full'} && main::is_numeric($battery->{$key}{'energy_full'})){ + my $percent = sprintf("%.1f", $battery->{$key}{'energy_now'}/$battery->{$key}{'energy_full'}*100); + $charge .= ' (' . $percent . '%)'; + } } # better than nothing, shows the charged percent elsif (defined $battery->{$key}{'capacity'} && $battery->{$key}{'capacity'} ne ''){ @@ -6810,16 +6985,16 @@ sub battery_output { main::key($num++,0,2,'charge') => $charge, main::key($num++,0,2,'condition') => $condition, },); - if ($extra > 0){ - if ($extra > 1){ - if ($battery->{$key}{'voltage_min_design'} || $battery->{$key}{'voltage_now'}){ - $battery->{$key}{'voltage_min_design'} ||= 'N/A'; - $battery->{$key}{'voltage_now'} ||= 'N/A'; - $volts = "$battery->{$key}{'voltage_now'}/$battery->{$key}{'voltage_min_design'}"; - } - $volts ||= 'N/A'; - $rows[$j]->{main::key($num++,0,2,'volts')} = $volts; + if ($extra > 0 || ($battery->{$key}{'voltage_now'} && $battery->{$key}{'voltage_min_design'} && + ($battery->{$key}{'voltage_now'} - $battery->{$key}{'voltage_min_design'}) < 0.5)){ + $battery->{$key}{'voltage_now'} ||= 'N/A'; + $rows[$j]->{main::key($num++,1,2,'volts')} = $battery->{$key}{'voltage_now'}; + if ($battery->{$key}{'voltage_now'} ne 'N/A' || $battery->{$key}{'voltage_min_design'}){ + $battery->{$key}{'voltage_min_design'} ||= 'N/A'; + $rows[$j]->{main::key($num++,0,3,'min')} = $battery->{$key}{'voltage_min_design'}; } + } + if ($extra > 0){ if ($battery->{$key}{'manufacturer'} || $battery->{$key}{'model_name'}) { if ($battery->{$key}{'manufacturer'} && $battery->{$key}{'model_name'}){ $model = "$battery->{$key}{'manufacturer'} $battery->{$key}{'model_name'}"; @@ -7018,7 +7193,7 @@ sub battery_data_sys { } if ( $battery{$id}->{'energy_full_design'} && $battery{$id}->{'energy_full'} ){ $battery{$id}->{'of_orig'} = 100 * $battery{$id}->{'energy_full'}/$battery{$id}->{'energy_full_design'}; - $battery{$id}->{'of_orig'} = sprintf("%.0f", $battery{$id}->{'of_orig'}); + $battery{$id}->{'of_orig'} = sprintf("%.1f", $battery{$id}->{'of_orig'}); } if ( $battery{$id}->{'energy_now'} ){ $battery{$id}->{'energy_now'} = sprintf("%.1f", $battery{$id}->{'energy_now'}); @@ -7116,12 +7291,16 @@ sub upower_data { ## BluetoothData { package BluetoothData; -my ($b_hci_error,$b_hci,%hci); +my ($b_bluetooth,$b_hci_error,$b_hci,$b_service); +my ($service); +my (%hci); sub get { eval $start if $b_log; my (@rows); my $num = 0; - if (($b_arm || $b_mips) && !$b_soc_bluetooth && !$b_pci_tool){ + $b_bluetooth = 1 if @ps_cmd && (grep {m|/bluetoothd\b|} @ps_cmd); + # note: rapi 4 has pci bus + if (($b_arm || $b_mips) && !$use{'soc-bluetooth'} && !$use{'pci-tool'}){ # do nothing, but keep the test conditions to force # the non arm case to always run #my $type = ($b_arm) ? 'arm' : 'mips'; @@ -7152,22 +7331,23 @@ sub get { sub device_output { eval $start if $b_log; - my (@rows); + my ($bus_id,@rows); my ($j,$num) = (0,1); foreach my $row (@devices_bluetooth){ $num = 1; + $bus_id = ''; $j = scalar @rows; my $driver = ($row->[9]) ? $row->[9] : 'N/A'; - my $card = $row->[4]; - $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; + my $device = $row->[4]; + $device = ($device) ? main::pci_cleaner($device,'output') : 'N/A'; # have seen absurdly verbose card descriptions, with non related data etc - if (length($card) > 85 || $size{'max'} < 110){ - $card = main::pci_long_filter($card); + if (length($device) > 85 || $size{'max'} < 110){ + $device = main::pci_long_filter($device); } push(@rows, { - main::key($num++,1,1,'Device') => $card, + main::key($num++,1,1,'Device') => $device, },); - if ($extra > 0 && $b_pci_tool && $row->[12]){ + if ($extra > 0 && $use{'pci-tool'} && $row->[12]){ my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]->{main::key($num++,0,2,'vendor')} = $item if $item; } @@ -7181,7 +7361,7 @@ sub device_output { $rows[$j]->{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10]; } if ($extra > 0){ - $rows[$j]->{main::key($num++,0,2,'bus ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; + $rows[$j]->{main::key($num++,0,2,'bus-ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; } if ($extra > 1){ my $chip_id = 'N/A'; @@ -7191,12 +7371,21 @@ sub device_output { elsif ($row->[6]){ $chip_id = $row->[6]; } - $rows[$j]->{main::key($num++,0,2,'chip ID')} = $chip_id; + $rows[$j]->{main::key($num++,0,2,'chip-ID')} = $chip_id; if ($extra > 2 && $row->[1]){ - $rows[$j]->{main::key($num++,0,2,'class ID')} = $row->[1]; + $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->[1]; } } - push(@rows,advanced_output('pci',"$row->[2].$row->[3]")) if defined $row->[2] && defined $row->[3]; + # weird serial rpi bt + if ($use{'soc-bluetooth'}){ + # /sys/devices/platform/soc/fe201000.serial/ + $bus_id = "$row->[6].$row->[1]" if defined $row->[1] && defined $row->[6]; + } + else { + # only theoretical, never seen one + $bus_id = "$row->[2].$row->[3]" if defined $row->[2] && defined $row->[3]; + } + push(@rows,advanced_output('pci',$bus_id)) if $bus_id; #print "$row->[0]\n"; } eval $end if $b_log; @@ -7204,45 +7393,42 @@ sub device_output { } sub usb_output { eval $start if $b_log; - return if !@usb; - my (@rows,$driver,$path_id,$product); + return if !@usb_bluetooth; + my (@rows,$path_id,$product); my ($j,$num) = (0,1); - foreach my $row (@usb){ + foreach my $row (@usb_bluetooth){ #print Data::Dumper::Dumper $row; - if ($row->[14] && $row->[14] eq 'Bluetooth'){ - #print Data::Dumper::Dumper $row; - $num = 1; - $j = scalar @rows; - # makre sure to reset, or second device trips last flag - ($driver,$path_id,$product) = ('','',''); - $product = main::cleaner($row->[13]) if $row->[13]; - $driver = ($row->[15]) ? $row->[15] : 'N/A'; - $path_id = $row->[2] if $row->[2]; -# $product ||= 'N/A'; - push(@rows, { - main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', - main::key($num++,1,2,'driver') => $driver, - },); - 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; - } - if ($extra > 0){ - $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::apply_filter($row->[16]); - } - push(@rows,advanced_output('usb',$path_id)) if $path_id; + $num = 1; + $j = scalar @rows; + # makre sure to reset, or second device trips last flag + ($path_id,$product) = ('',''); + $product = main::cleaner($row->[13]) if $row->[13]; + $product ||= 'N/A'; + $row->[15] ||= 'N/A'; + $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; } + if ($extra > 0){ + $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::apply_filter($row->[16]); + } + push(@rows,advanced_output('usb',$path_id)) if $path_id; } eval $end if $b_log; return @rows; @@ -7250,18 +7436,22 @@ sub usb_output { sub advanced_output { my ($type,$bus_id) = @_; eval $start if $b_log; - my ($path,@rows,@temp); + my (@rows,@temp); my ($j,$num,$k,$l,$m,$id,$id2) = (0,1,2,3,4,'',''); - hci_data() if !$b_hci && $alerts{'hciconfig'}->{'action'} eq 'use'; - if ($type eq 'usb'){ - $path = "/sys/bus/usb/devices/$bus_id:*/bluetooth"; + if (!$b_hci && $alerts{'hciconfig'}->{'action'} eq 'use'){ + hciconfig_data(); } - elsif ($type eq 'pci') { - $path = "/sys/bus/pci/devices/0000:$bus_id/bluetooth"; + elsif (!$b_hci && $alerts{'bt-adapter'}->{'action'} eq 'use'){ + bt_tool_data(); } + #print "bid: $bus_id\n"; if ($type ne 'check'){ - @temp = main::globber("$path/*") if $path; + @temp = main::globber('/sys/class/bluetooth/*'); + @temp = map {$_ = Cwd::abs_path($_);$_} @temp if @temp; + #print Data::Dumper::Dumper \@temp; + @temp = grep {/$bus_id/} @temp if @temp; @temp = map {$_ =~ s|^/.*/||;$_;} @temp if @temp; + #print Data::Dumper::Dumper \@temp; } elsif ($type eq 'check' && %hci){ @temp = keys %hci; @@ -7269,6 +7459,14 @@ sub advanced_output { ($k,$l,$m) = (1,2,3); } if (@temp && %hci){ + if ($hci{'alert'}){ + check_service(); # sets $service + $j = scalar @rows; + $rows[$j]->{main::key($num++,1,$k,'Report')} = ''; + $rows[$j]->{main::key($num++,0,$l,'bt-service')} = $service; + $rows[$j]->{main::key($num++,0,$l,'note')} = $hci{'alert'}; + delete $hci{'alert'}; + } foreach my $item (@temp){ if ($hci{$item}){ $id2 = $item if $id; @@ -7278,23 +7476,40 @@ sub advanced_output { },); $rows[$j]->{main::key($num++,0,$l,'ID')} = $item if !$id; $rows[$j]->{main::key($num++,0,$l,'state')} = $hci{$item}->{'state'}; - if (my $btv = bluetooth_version($hci{$item}->{'lmp-version'})){ + # this only appears for hciconfig, bt-adapter does not run without bt service + if (!$b_bluetooth || $hci{$item}->{'state'} eq 'down'){ + check_service(); # sets $service + $rows[$j]->{main::key($num++,0,$l,'bt-service')} = $service; + } + $rows[$j]->{main::key($num++,0,$l,'address')} = main::apply_filter($hci{$item}->{'address'}); + # lmp/hci version only hciconfig sadly + if (defined $hci{$item}->{'lmp-version'} && + (my $btv = bluetooth_version($hci{$item}->{'lmp-version'}))){ $rows[$j]->{main::key($num++,0,$l,'bt-v')} = $btv; } - if ($extra > 0 && $hci{$item}->{'lmp-version'}){ + if ($extra > 0 && defined $hci{$item}->{'lmp-version'}){ $rows[$j]->{main::key($num++,0,$l,'lmp-v')} = $hci{$item}->{'lmp-version'}; if ($extra > 1 && $hci{$item}->{'lmp-subversion'}){ $rows[$j]->{main::key($num++,0,$m,'sub-v')} = $hci{$item}->{'lmp-subversion'}; } } - if ($extra > 0 && $hci{$item}->{'hci-version'} && ($extra > 2 || !$hci{$item}->{'lmp-version'} || + if ($extra > 0 && defined $hci{$item}->{'hci-version'} && ($extra > 2 || !$hci{$item}->{'lmp-version'} || ($hci{$item}->{'lmp-version'} && $hci{$item}->{'lmp-version'} ne $hci{$item}->{'hci-version'}))){ $rows[$j]->{main::key($num++,0,$l,'hci-v')} = $hci{$item}->{'hci-version'}; if ($extra > 1 && $hci{$item}->{'hci-revision'}){ $rows[$j]->{main::key($num++,0,$m,'rev')} = $hci{$item}->{'hci-revision'}; } } - $rows[$j]->{main::key($num++,0,$l,'address')} = main::apply_filter($hci{$item}->{'address'}); +# if ($extra > 1 && $hci{$item}->{'discoverable'}){ +# $rows[$j]->{main::key($num++,1,$l,'discover')} = $hci{$item}->{'discoverable'}; +# if ($extra > 2 && $hci{$item}->{'discovering'}){ +# $rows[$j]->{main::key($num++,1,$m,'active')} = $hci{$item}->{'discovering'}; +# } +# } +# if ($extra > 1 && $hci{$item}->{'pairable'}){ +# $rows[$j]->{main::key($num++,0,$l,'pair')} = $hci{$item}->{'pairable'}; +# } + # this data only from hciconfig if ($b_admin && ($hci{$item}->{'acl-mtu'} || $hci{$item}->{'sco-mtu'} || $hci{$item}->{'link-policy'})){ $j = scalar @rows; @@ -7321,21 +7536,78 @@ sub advanced_output { } } } - if ($alerts{'hciconfig'}->{'action'} ne 'use' && !$b_hci_error){ - my $key = 'Message'; + if (!$b_hci_error && ($alerts{'hciconfig'}->{'action'} ne 'use' && + $alerts{'bt-adapter'}->{'action'} ne 'use')){ + my $key = 'Report'; + my $value = ''; + if ($alerts{'hciconfig'}->{'action'} eq 'platform' || + $alerts{'bt-adapter'}->{'action'} eq 'platform'){ + $value = main::row_defaults('tool-missing-os','bluetooth'); + } + else { + $value = main::row_defaults('tools-missing','hciconfig/bt-adapter'); + } push(@rows,{ - main::key($num++,0,1,$key) => $alerts{'hciconfig'}->{$alerts{'hciconfig'}->{'action'}}, + main::key($num++,0,1,$key) => $value, },); $b_hci_error = 1; } eval $end if $b_log; return @rows; } -sub hci_data { + +sub bt_tool_data { eval $start if $b_log; $b_hci = 1; my (@data,$id); - if ($b_fake_bluetooth){ + if ($fake{'bluetooth'}){ + my $file; + $file = ""; + @data = main::reader($file,'strip'); + } + else { + if ($b_bluetooth){ + my $cmd = "$alerts{'bt-adapter'}->{'path'} --info 2>/dev/null"; + @data = main::grabber($cmd,'', 'strip'); + } + } + # print Data::Dumper::Dumper \@data; + main::log_data('dump','@data', \@data) if $b_log; + foreach (@data){ + my @working = split(/:\s*/,$_); + # print Data::Dumper::Dumper \@working; + next if ! @working; + if ($working[0] =~ /^\[([^\]]+)\]/){ + $id = $1; + } + elsif ($working[0] eq 'Address'){ + $hci{$id}->{'address'} = join(':',@working[1 .. $#working]); + } + elsif ($working[0] eq 'Powered'){ + $hci{$id}->{'state'} = ($working[1] =~ /^(1|yes)\b/) ? 'up': 'down'; + } + elsif ($working[0] eq 'Discoverable'){ + $hci{$id}->{'discoverable'} = ($working[1] =~ /^(1|yes)\b/) ? 'yes': 'no'; + } + elsif ($working[0] eq 'Pairable'){ + $hci{$id}->{'pairable'} = ($working[1] =~ /^(1|yes)\b/) ? 'yes': 'no'; + } + elsif ($working[0] eq 'Discovering'){ + $hci{$id}->{'discovering'} = ($working[1] =~ /^(1|yes)\b/) ? 'yes': 'no'; + } + } + if (!@data && !$b_bluetooth){ + $hci{'alert'} = main::row_defaults('bluetooth-down','bt-adapter'); + } + print Data::Dumper::Dumper \%hci if $dbg[27]; + 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; + my (@data,$id); + if ($fake{'bluetooth'}){ my $file; $file = ""; @data = main::reader($file,'strip'); @@ -7359,7 +7631,7 @@ sub hci_data { $hci{$id}->{'acl-mtu'} = $2; $hci{$id}->{'sco-mtu'} = $3; } - elsif (/^(UP.*|DOWN.*)/){ + elsif (/^(UP|DOWN).*/){ $hci{$id}->{'state'} = lc($1); } elsif (/^HCI Version:\s+([0-9\.]+)\s+.*Revision:\s+0x([0-9a-f]+)/){ @@ -7380,14 +7652,23 @@ sub hci_data { $hci{$id}->{'service-classes'} = main::general_cleaner(lc($1)); } } - # print Data::Dumper::Dumper \%hci; + print Data::Dumper::Dumper \%hci if $dbg[27]; main::log_data('dump','%hci', \%hci) if $b_log; eval $end if $b_log; } +sub check_service { + eval $start if $b_log; + if (!$b_service){ + $service = ServiceData::get('status','bluetooth'); + $service ||= 'N/A'; + $b_service = 1; + } + eval $end if $b_log; +} sub bluetooth_version { eval $start if $b_log; my ($lmp) = @_; - return if !main::is_numeric($lmp); + return if !defined $lmp || !main::is_numeric($lmp); $lmp = int($lmp); # conveniently, LMP starts with 0, so perfect for array indexes my @bt = qw(1.0b 1.1 1.2 2.0 2.1 3.0 4.0 4.1 4.2 5.0 5.1 5.2); @@ -7500,15 +7781,18 @@ sub full_output { $rows[$j]->{main::key($num++,0,2,'microcode')} = $cpu{'microcode'}; } } - if ($extra > 1 && $properties{'l1-cache'}){ - $rows[$j]->{main::key($num++,0,2,'L1 cache')} = main::get_size($properties{'l1-cache'},'string'); - } - if (!$b_arm || ($b_arm && $properties{'l2-cache'})){ + if (($extra > 1 && ($properties{'l1-cache'} || $properties{'l3-cache'})) || + ((!$b_arm && !$b_mips && !$b_ppc) || $properties{'l2-cache'})){ + $rows[$j]->{main::key($num++,1,2,'cache')} = ''; + if ($extra > 1 && $properties{'l1-cache'}){ + $rows[$j]->{main::key($num++,0,3,'L1')} = main::get_size($properties{'l1-cache'},'string'); + } + # the arm + l2 will never be true since arm cpus don't have l2 cache $properties{'l2-cache'} = ($properties{'l2-cache'}) ? main::get_size($properties{'l2-cache'},'string') : 'N/A'; - $rows[$j]->{main::key($num++,0,2,'L2 cache')} = $properties{'l2-cache'}; - } - if ($extra > 1 && $properties{'l3-cache'}){ - $rows[$j]->{main::key($num++,0,2,'L3 cache')} = main::get_size($properties{'l3-cache'},'string'); + $rows[$j]->{main::key($num++,0,3,'L2')} = $properties{'l2-cache'}; + if ($extra > 1 && $properties{'l3-cache'}){ + $rows[$j]->{main::key($num++,0,3,'L3')} = main::get_size($properties{'l3-cache'},'string'); + } } if ($extra > 0 && !$show{'cpu-flag'}){ $j = scalar @rows; @@ -7720,8 +8004,7 @@ sub cpuinfo_data { my %cpu = set_cpu_data(); $cpu{'type'} = cpu_vendor($cpu_arch) if $cpu_arch =~ /e2k/; # already set to lower # use --arm flag when testing arm cpus, and --fake-cpu to trigger fake data - if ($b_fake_cpu){ - # $cpu{'type'} = 'elbrus'; # uncomment to test elbrus + if ($fake{'cpu'}){ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-4-core-pinebook-1.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv6-single-core-1.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv7-dual-core-1.txt"; @@ -7745,6 +8028,7 @@ sub cpuinfo_data { # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-6-core-xeon-no-mt-lathander.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/mips/mips-mainusg-cpuinfo.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/ppc/ppc-debian-ppc64-cpuinfo.txt"; + # $cpu{'type'} = 'elbrus'; # uncomment to test elbrus # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE1C-8.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2CDSP-4.txt"; # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2S4-3-monocub.txt"; @@ -7913,40 +8197,40 @@ sub cpuinfo_data { ## this is only for -C full cpu output if ( $type eq 'full' ){ if (!$cpu{'l2-cache'} && ($line[0] eq 'cache size' || $line[0] eq 'l2 cache size' )){ - if ($line[1] =~ /(\d+)\s(K|M)B$/){ - $cpu{'l2-cache'} = ($2 eq 'M') ? ($1*1024) : $1; + if ($line[1] =~ /(\d+\s*[KMG])i?B?$/){ + $cpu{'l2-cache'} = main::translate_size($1); } } elsif (!$cpu{'l1-cache'} && $line[0] eq 'l1 cache size'){ - if ($line[1] =~ /(\d+)\sKB$/){ - $cpu{'l1-cache'} = $1; + if ($line[1] =~ /(\d+\s*[KMG])i?B?$/){ + $cpu{'l1-cache'} = main::translate_size($1); } } elsif (!$cpu{'l3-cache'} && $line[0] eq 'l3 cache size'){ - if ($line[1] =~ /(\d+)\s(K|M)B$/){ - $cpu{'l2-cache'} = ($2 eq 'M') ? ($1*1024) : $1; + if ($line[1] =~ /(\d+\s*[KMG])i?B?$/){ + $cpu{'l2-cache'} = main::translate_size($1); } } if ($cpu{'type'} eq 'elbrus'){ # note: cache0 is L1i and cache1 L1d, but add both for L1 if (!$cpu{'l0-cache'} && $line[0] eq 'cache0'){ - if ($line[1] =~ /size=(\d+)K\s/){ + if ($line[1] =~ /size\s*=\s*(\d+)K\s/){ $cpu{'l0-cache'} = $1; } } elsif (!$cpu{'l1-cache'} && $line[0] eq 'cache1'){ - if ($line[1] =~ /size=(\d+)K\s/){ + if ($line[1] =~ /size\s*=\s*(\d+)K\s/){ $cpu{'l1-cache'} = $1; $cpu{'l1-cache'} += $cpu{'l0-cache'} if $cpu{'l0-cache'}; } } elsif (!$cpu{'l2-cache'} && $line[0] eq 'cache2'){ - if ($line[1] =~ /size=(\d+)(K|M)\s/){ + if ($line[1] =~ /size\s*=\s*(\d+)(K|M)\s/){ $cpu{'l2-cache'} = ($2 eq 'M') ? ($1*1024) : $1; } } elsif (!$cpu{'l3-cache'} && $line[0] eq 'cache3'){ - if ($line[1] =~ /size=(\d+)(K|M)\s/){ + if ($line[1] =~ /size\s*=\s*(\d+)(K|M)\s/){ $cpu{'l3-cache'} = ($2 eq 'M') ? ($1*1024) : $1; } } @@ -8010,7 +8294,7 @@ sub cpuinfo_data { $cpu{'max-freq'} = $speeds{'max-freq'}; } main::log_data('dump','%cpu',\%cpu) if $b_log; - print Data::Dumper::Dumper \%cpu if $test[8]; + print Data::Dumper::Dumper \%cpu if $dbg[8]; eval $end if $b_log; return %cpu; } @@ -8031,21 +8315,22 @@ sub sysctl_data { $line[0] eq 'machdep.cpu.brand_string' ){ # cut L2 cache/cpu max speed out of model string, if available # openbsd 5.6: AMD Sempron(tm) Processor 3400+ ("AuthenticAMD" 686-class, 256KB L2 cache) + # openbsd 6.x has Lx cache data in dmesg.boot # freebsd 10: hw.model: AMD Athlon(tm) II X2 245 Processor $line[1] = main::cleaner($line[1]); $line[1] = cpu_cleaner($line[1]); - if ( $line[1] =~ /([0-9]+)[-[:space:]]*([KM]B)\s+L2 cache/) { + if ( $line[1] =~ /([0-9]+)[\s-]*([KM]B)\s+L2 cache/i) { my $multiplier = ($2 eq 'MB') ? 1024: 1; $cpu{'l2-cache'} = $1 * $multiplier; } - if ( $line[1] =~ /([^0-9\.][0-9\.]+)[-[:space:]]*[MG]Hz/) { + if ( $line[1] =~ /([^0-9\.][0-9\.]+)[\s-]*[MG]Hz/) { $cpu{'max-freq'} = $1; if ($cpu{'max-freq'} =~ /MHz/i) { - $cpu{'max-freq'} =~ s/[-[:space:]]*MHz//; + $cpu{'max-freq'} =~ s/[\s-]*MHz//; $cpu{'max-freq'} = speed_cleaner($cpu{'max-freq'},'mhz'); } elsif ($cpu{'max-freq'} =~ /GHz/) { - $cpu{'max-freq'} =~ s/[-[:space:]]*GHz//i; + $cpu{'max-freq'} =~ s/[\s-]*GHz//i; $cpu{'max-freq'} = $cpu{'max-freq'} / 1000; $cpu{'max-freq'} = speed_cleaner($cpu{'max-freq'},'mhz'); } @@ -8056,7 +8341,7 @@ sub sysctl_data { $cpu{'model_name'} = $line[1]; $cpu{'type'} = cpu_vendor($line[1]); } - # NOTE: hw.l1icachesize: hw.l1dcachesize: + # NOTE: hw.l1icachesize: hw.l1dcachesize: ; in bytes, apparently elsif ($line[0] eq 'hw.l1icachesize') { $cpu{'l1-cache'} = $line[1]/1024; } @@ -8143,15 +8428,193 @@ sub sysctl_data { $cpu{'dies'} = $die_id; } } - if (!$cpu{'flags'}){ - $cpu{'flags'} = cpu_flags_bsd(); + if (!$cpu{'flags'} || !$cpu{'family'}){ + my %dmesg_boot = dmesg_boot_data(); + $cpu{'flags'} = $dmesg_boot{'flags'} if !$cpu{'flags'}; + $cpu{'family'} = $dmesg_boot{'family'} if !$cpu{'family'}; + $cpu{'l1-cache'} = $dmesg_boot{'l1-cache'} if !$cpu{'l1-cache'}; + $cpu{'l2-cache'} = $dmesg_boot{'l2-cache'} if !$cpu{'l2-cache'}; + $cpu{'l3-cache'} = $dmesg_boot{'l3-cache'} if !$cpu{'l3-cache'}; + $cpu{'microcode'} = $dmesg_boot{'microcode'} if !$cpu{'microcode'}; + $cpu{'model_id'} = $dmesg_boot{'model_id'} if !$cpu{'model_id'}; + $cpu{'stepping'} = $dmesg_boot{'stepping'} if !$cpu{'stepping'}; + $cpu{'type'} = $dmesg_boot{'type'} if !$cpu{'type'}; + } + if ( $extra > 0 && !$cpu{'arch'} && $type ne 'short' ){ + ($cpu{'arch'},$cpu{'arch-note'}) = cpu_arch($cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'stepping'}); + #print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n"; } main::log_data('dump','%cpu',\%cpu) if $b_log; - print Data::Dumper::Dumper \%cpu if $test[8]; + print Data::Dumper::Dumper \%cpu if $dbg[8]; eval $end if $b_log; return %cpu; } +sub dmesg_boot_data { + eval $start if $b_log; + my (%values); + my ($family,$flags,$microcode,$model,$sep,$stepping,$type) = ('','','','','','',''); + my ($l1,$l2,$l3) = (0,0,0); + # this will be null if it was not readable + my $file = main::system_files('dmesg-boot'); + if ( @dmesg_boot){ + foreach (@dmesg_boot){ + # can be ~Features/Features2/AMD Features + if ( /Features/ || ( $bsd_type eq "openbsd" && /^cpu0:\s*[a-z0-9]{2,3}(\s|,)[a-z0-9]{2,3}(\s|,)/i ) ) { + my @line = split(/:\s*/, lc($_)); + # free bsd has to have weird syntax: <....,> + # Features2=0x1e98220b + $line[1] =~ s/^[^<]*<|>[^>]*$//g; + # then get rid of stuff + $line[1] =~ s/<[^>]+>//g; + # and replace commas with spaces + $line[1] =~ s/,/ /g; + $flags .= $sep . $line[1]; + $sep = ' '; + } + elsif (/^cpu0:\s*([^,]+),\s+([0-9\.]+\s*MHz),\s+([0-9a-f]+)-([0-9a-f]+)-([0-9a-f]+)/){ + $type = cpu_vendor($1); + $family = uc($3); + $model = uc($4); + $stepping = uc($5); + $family =~ s/^0+//; + $model =~ s/^0+//; + $stepping =~ s/^0+//; + } + # note: cpu cache is in KiB MiB even though they call it KB and MB + elsif (/^cpu0:\s*[0-9\.]+[KMG]B\s/ && + /^cpu0:\s*(([0-9\.]+[KMG])i?B.*?\sI[\s-]?cache)?(,?\s*([0-9\.]+[KMG])i?B.*?\sD[\s-]?cache)?(,?\s*([0-9\s]+[KMG])i?B.*?\sL2[\s-]?cache)?(,?\s*([0-9\.]+[KMG])i?B.*?\sL3[\s-]?cache)?/){ + $l1 = main::translate_size($2) if $2; + $l2 = main::translate_size($6) if $6; + $l3 = main::translate_size($8) if $8; + } + elsif (/^~*Origin:\s*(.+?)[\s,]+(Id\s*=\s*(0x)?([0-9a-f]+)[\s,]*)?(Family\s*=\s*(0x)?([a-f0-9]+)[\s,]*)?(Model\s*=\s*(0x)([a-f0-9]+)[\s,]*)?(Stepping\s*=\s*(0x)?([0-9a-f]+))?/){ + $type = cpu_vendor($1) if $1; + $microcode = ($3) ? uc($4) : $4; + $family = ($6) ? uc($7) : $7; + $model = ($9) ? uc($10) : $10; + $stepping = ($12) ? uc($13) : $13; + } + elsif (/^(ioapic|pci)/){ + last; + } + } + if ($flags){ + $flags =~ s/\s+/ /g; + $flags =~ s/^\s+|\s+$//g; + } + } + else { + if ( $file && ! -r $file ){ + $flags = main::row_defaults('dmesg-boot-permissions'); + } + } + %values = ( + 'family' => $family, + 'flags' => $flags, + 'l1-cache' => $l1, + 'l2-cache' => $l2, + 'l3-cache' => $l3, + 'microcode' => $microcode, + 'model_id' => $model, + 'stepping' => $stepping, + 'type' => $type, + ); + print Data::Dumper::Dumper \%values if $dbg[27]; + eval $end if $b_log; + return %values; +} +sub cpu_dmi_data { + eval $start if $b_log; + return if !@dmi; + my %dmi_data = ('L1' => 0, 'L2' => 0,'L3' => 0, 'ext-clock' => undef, 'socket' => undef, + 'speed' => undef, 'max-speed' => undef, 'upgrade' => undef, 'volts' => undef); + my ($id,$amount,$socket,$upgrade); + foreach my $item (@dmi){ + next if ref $item ne 'ARRAY'; + next if ($item->[0] < 4 || $item->[0] == 5 || $item->[0] == 6); + last if $item->[0] > 7; + if ($item->[0] == 7){ + # skip first three rows, we don't need that data + ($id,$amount) = ('',0); + foreach my $value (@$item[3 .. $#$item]){ + next if $value =~ /~/; + # variants: L3 - Cache; L3 Cache; L3-cache; L2 CACHE; CPU Internal L1 + if ($value =~ /^Socket Designation:.*? (L[1-3])\b/){ + $id = $1; + } + # some cpus only show Socket Designation: Internal cache + elsif (!$id && $value =~ /^Configuration:.* Level.*?([1-3])\b/){ + $id = "L$1"; + } + # NOTE: cache is in KiB or MiB but they call it kB or MB + # so we send translate_size k or M which trips KiB/MiB mode + elsif ($id && $value =~ /^Installed Size:\s+(.*?[kKM])i?B$/){ + $amount = main::translate_size($1); + } + if ($id && $amount){ + $dmi_data{$id} += $amount; + last; + } + } + } + # note: for multi cpu systems, we're hoping that these values are + # the same for each cpu, which in most pc situations they will be, + # and ARM etc won't be using dmi data here anyway. + # Older dmidecode appear to have unreliable Upgrade outputs + elsif ($item->[0] == 4){ + # skip first three row,s we don't need that data + ($socket,$upgrade) = (undef); + foreach my $value (@$item[3 .. $#$item]){ + next if $value =~ /~/; + # note: on single cpu systems, Socket Designation shows socket type, + # but on multi, shows like, CPU1; CPU Socket #2; Socket 0; so check values a bit. + # Socket Designation: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz + # Sometimes shows as CPU Socket... + if ($value =~ /^Socket Designation:\s*(CPU\s*Socket|Socket)?[\s-]*(.*)$/i){ + $upgrade = main::dmi_cleaner($2) if $2 !~ /(cpu|[mg]hz|onboard|socket|@|^#?[0-9]$)/i; + #print "$socket_temp\n"; + } + # normally we prefer this value, but sometimes it's garbage + # older systems often show: Upgrade: ZIF Socket which is a generic term, legacy + elsif ($value =~ /^Upgrade:\s*(CPU\s*Socket|Socket)?[\s-]*(.*)$/i){ + #print "$2\n"; + $socket = main::dmi_cleaner($2) if $2 !~ /(ZIF|\bslot\b)/i; + } + # seen: Voltage: 5.0 V 2.9 V + elsif ($value =~ /^Voltage:\s*([0-9\.]+)\s*(V|Volts)?\b/i){ + $dmi_data{'volts'} = main::dmi_cleaner($1); + } + elsif ($value =~ /^Current Speed:\s*([0-9\.]+)\s*([MGK]Hz)?\b/i){ + $dmi_data{'speed'} = main::dmi_cleaner($1); + } + elsif ($value =~ /^Max Speed:\s*([0-9\.]+)\s*([MGK]Hz)?\b/i){ + $dmi_data{'max-speed'} = main::dmi_cleaner($1); + } + elsif ($value =~ /^External Clock:\s*([0-9\.]+\s*[MGK]Hz)\b/){ + $dmi_data{'ext-clock'} = main::dmi_cleaner($1); + } + } + } + } + # Seen older cases where Upgrade: Other value exists + if ($socket || $upgrade){ + if ($socket && $upgrade){ + $upgrade = undef if $socket eq $upgrade; + } + elsif ($upgrade){ + $socket = $upgrade; + $upgrade = undef; + } + $dmi_data{'socket'} = $socket; + $dmi_data{'upgrade'} = $upgrade; + } + main::log_data('dump','%dmi_data',\%dmi_data) if $b_log; + # print Data::Dumper::Dumper \%dmi_data; + eval $end if $b_log; + return %dmi_data; +} + sub cpu_properties { my ($cpu) = @_; my ($b_amd_zen,$b_epyc,$b_ht,$b_elbrus,$b_intel,$b_ryzen,$b_xeon); @@ -8207,11 +8670,13 @@ sub cpu_properties { # print 'model id: ' . $cpu->{'model_id'} . ' arch: ' . $cpu->{'arch'} . " cpc: $cpu_cores phyc: $phyical_count proc: $processors_count \n"; } $phyical_count ||= 1; # assume 1 if no id found, as with ARM - if ($extra > 1){ + if ($extra > 1 || ($bsd_type && !$cpu->{'l2-cache'})){ # note: dmidecode has one entry per cpu per cache type, so this already # has done the arithmetic on > 1 cpus for L1 and L3. my %cpu_dmi = cpu_dmi_data(); $l1_cache = $cpu_dmi{'L1'} if $cpu_dmi{'L1'}; + # note: bsds often won't have L2 catch data found yet + $l2_cache = $cpu_dmi{'L2'} if !$cpu->{'l2-cache'} && $cpu_dmi{'L2'}; $l3_cache = $cpu_dmi{'L3'} if $cpu_dmi{'L3'}; # bsd sysctl can have these values so let's check just in case $l1_cache = $cpu->{'l1-cache'} * $phyical_count if !$l1_cache && $cpu->{'l1-cache'}; @@ -8371,7 +8836,10 @@ sub cpu_properties { $cpu_layout .= count_alpha($cpu_cores) . 'Core'; $cpu_layout .= ' (' . $cpu->{'dies'}. '-Die)' if !$bsd_type && $cpu->{'dies'} > 1; # the only possible change for bsds is if we can get phys counts in the future - if ($bsd_type){ + if (!$cpu->{'l2-cache'} ){ + # do nothing + } + elsif ($bsd_type){ $l2_cache = $cpu->{'l2-cache'} * $phyical_count; } # AMD SOS chips appear to report full L2 cache per core @@ -8442,94 +8910,7 @@ sub cpu_properties { eval $end if $b_log; return %cpu_properties; } -sub cpu_dmi_data { - eval $start if $b_log; - return if !@dmi; - my %dmi_data = ('L1' => 0, 'L2' => 0,'L3' => 0, 'ext-clock' => undef, 'socket' => undef, - 'speed' => undef, 'max-speed' => undef, 'upgrade' => undef, 'volts' => undef); - my ($id,$amount,$socket,$upgrade); - foreach my $item (@dmi){ - next if ref $item ne 'ARRAY'; - next if ($item->[0] < 4 || $item->[0] == 5 || $item->[0] == 6); - last if $item->[0] > 7; - if ($item->[0] == 7){ - # skip first three row, we don't need that data - ($id,$amount) = ('',0); - foreach my $value (@$item[3 .. $#$item]){ - next if $value =~ /~/; - # variants: L3 - Cache; L3 Cache; L3-cache; CPU Internal L1 - if ($value =~ /^Socket Designation:.* (L[1-3])\b/){ - $id = $1; - } - # some cpus only show Socket Designation: Internal cache - elsif (!$id && $value =~ /^Configuration:.* Level.*([1-3])\b/){ - $id = "L$1"; - } - elsif ($id && $value =~ /^Installed Size:\s+(.*B)$/){ - $amount = main::translate_size($1); - } - if ($id && $amount){ - $dmi_data{$id} += $amount; - last; - } - } - } - # note: for multi cpu systems, we're hoping that these values are - # the same for each cpu, which in most pc situations they will be, - # and ARM etc won't be using dmi data here anyway. - # Older dmidecode appear to have unreliable Upgrade outputs - elsif ($item->[0] == 4){ - # skip first three row, we don't need that data - ($socket,$upgrade) = (undef); - foreach my $value (@$item[3 .. $#$item]){ - next if $value =~ /~/; - # note: on single cpu systems, Socket Designation shows socket type, - # but on multi, shows like, CPU1; CPU Socket #2; Socket 0; so check values a bit. - # Socket Designation: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz - # Sometimes shows as CPU Socket... - if ($value =~ /^Socket Designation:\s*(CPU\s*Socket|Socket)?[\s-]*(.*)$/i){ - $upgrade = main::dmi_cleaner($2) if $2 !~ /(cpu|[mg]hz|onboard|socket|@|^#?[0-9]$)/i; - #print "$socket_temp\n"; - } - # normally we prefer this value, but sometimes it's garbage - # older systems often show: Upgrade: ZIF Socket which is a generic term, legacy - elsif ($value =~ /^Upgrade:\s*(CPU\s*Socket|Socket)?[\s-]*(.*)$/i){ - #print "$2\n"; - $socket = main::dmi_cleaner($2) if $2 !~ /(ZIF|\bslot\b)/i; - } - # seen: Voltage: 5.0 V 2.9 V - elsif ($value =~ /^Voltage:\s*([0-9\.]+)\s*(V|Volts)?\b/i){ - $dmi_data{'volts'} = main::dmi_cleaner($1); - } - elsif ($value =~ /^Current Speed:\s*([0-9\.]+)\s*([MGK]Hz)?\b/i){ - $dmi_data{'speed'} = main::dmi_cleaner($1); - } - elsif ($value =~ /^Max Speed:\s*([0-9\.]+)\s*([MGK]Hz)?\b/i){ - $dmi_data{'max-speed'} = main::dmi_cleaner($1); - } - elsif ($value =~ /^External Clock:\s*([0-9\.]+\s*[MGK]Hz)\b/){ - $dmi_data{'ext-clock'} = main::dmi_cleaner($1); - } - } - } - } - # Seen older cases where Upgrade: Other value exists - if ($socket || $upgrade){ - if ($socket && $upgrade){ - $upgrade = undef if $socket eq $upgrade; - } - elsif ($upgrade){ - $socket = $upgrade; - $upgrade = undef; - } - $dmi_data{'socket'} = $socket; - $dmi_data{'upgrade'} = $upgrade; - } - main::log_data('dump','%dmi_data',\%dmi_data) if $b_log; - # print Data::Dumper::Dumper \%dmi_data; - eval $end if $b_log; - return %dmi_data; -} + sub cpu_bugs_sys { eval $start if $b_log; my (@bugs,$type,$value); @@ -8695,42 +9076,6 @@ sub elbrus_data { eval $end if $b_log; return @return; } -sub cpu_flags_bsd { - eval $start if $b_log; - my ($flags,$sep) = ('',''); - # this will be null if it was not readable - my $file = main::system_files('dmesg-boot'); - if ( @dmesg_boot){ - foreach (@dmesg_boot){ - if ( /Features/ || ( $bsd_type eq "openbsd" && /^cpu0:\s*[a-z0-9]{2,3}(\s|,)[a-z0-9]{2,3}(\s|,)/i ) ) { - my @line = split(/:\s*/, lc($_)); - # free bsd has to have weird syntax: <....,> - # Features2=0x1e98220b - $line[1] =~ s/^[^<]*<|>[^>]*$//g; - # then get rid of stuff - $line[1] =~ s/<[^>]+>//g; - # and replace commas with spaces - $line[1] =~ s/,/ /g; - $flags .= $sep . $line[1]; - $sep = ' '; - } - elsif (/real mem/){ - last; - } - } - if ($flags){ - $flags =~ s/\s+/ /g; - $flags =~ s/^\s+|\s+$//g; - } - } - else { - if ( $file && ! -r $file ){ - $flags = main::row_defaults('dmesg-boot-permissions'); - } - } - eval $end if $b_log; - return $flags; -} # only elbrus ID is actually used live sub cpu_vendor { @@ -8800,6 +9145,8 @@ sub cpu_arch { eval $start if $b_log; my ($type,$family,$model,$stepping) = @_; $stepping = 0 if !main::is_numeric($stepping); + $family ||= ''; + $model ||= ''; my ($arch,$note) = ('',''); my $check = main::row_defaults('note-check'); # See: docs/inxi-resources.txt @@ -9271,7 +9618,7 @@ sub drives_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++,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'; } @@ -9363,12 +9710,13 @@ sub disk_data { my (@rows,@data,@devs); my $num = 0; my ($used) = (0); - PartitionData::partition_data() if !$b_partitions; - RaidData::raid_data() if !$b_raid; + PartitionData::partition_data() if !$loaded{'partitions'}; + RaidData::raid_data() if !$loaded{'raid'}; foreach my $row (@partitions){ # don't count remote used, also, some cases mount # panfs is parallel NAS volume manager, need more data - next if ($row->{'fs'} && $row->{'fs'} =~ /cifs|iso9660|nfs|panfs|sshfs|smbfs|unionfs/); + # null is hammer fs slice + next if ($row->{'fs'} && $row->{'fs'} =~ /^(cifs|iso9660|nfs|null|overlay|panfs|sshfs|smbfs|unionfs)$/); # don't count zfs or file type swap next if ($row->{'swap-type'} && $row->{'swap-type'} ne 'partition'); # in some cases, like redhat, mounted cdrom/dvds show up in partition data @@ -9393,10 +9741,10 @@ sub disk_data { @data = smartctl_data(\@data); } else { - $smartctl_missing = $alerts{'smartctl'}->{'missing'}; + $smartctl_missing = $alerts{'smartctl'}->{'message'}; } } - print Data::Dumper::Dumper \@data if $test[13];; + print Data::Dumper::Dumper \@data if $dbg[13];; main::log_data('data',"used: $used") if $b_log; eval $end if $b_log; return @data; @@ -9406,7 +9754,7 @@ sub proc_data { my ($used) = @_; my (@data,@drives); my ($b_hdx,$logical_size,$size) = (0,0,0); - main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; + main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; foreach my $row (@proc_partitions){ if ( $row->[-1] =~ /^(fio[a-z]+|[hsv]d[a-z]+|(ada|mmcblk|n[b]?d|nvme[0-9]+n)[0-9]+)$/) { $b_hdx = 1 if $row->[-1] =~ /^hd[a-z]/; @@ -9464,7 +9812,7 @@ sub proc_data { @data = proc_data_advanced($b_hdx,\@drives); } main::log_data('dump','@data',\@data) if $b_log; - print Data::Dumper::Dumper \@data if $test[24]; + print Data::Dumper::Dumper \@data if $dbg[24]; eval $end if $b_log; return @data; } @@ -9621,10 +9969,11 @@ sub proc_data_advanced { $drives->[$i]{'rotation'} = "$data[2] rpm"; $drives->[$i]{'drive-type'} = 'HDD'; } - elsif (($drives->[$i]{'model'} && $drives->[$i]{'model'} =~ /(ssd|flash|nvme|mmc|\bm[\.-]?2\b)/i) || - ($block_type && ($block_type eq 'mmc' || $block_type eq 'nvme')) || - # note: this last case could conceivabley be wrong for a spun down HDD - (defined $data[2] && $data[2] eq '0') ){ + elsif (($block_type && $block_type ne 'sdx') || + # note: this case could conceivabley be wrong for a spun down HDD + (defined $data[2] && $data[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'; } } @@ -9659,45 +10008,52 @@ sub dmesg_boot_data { $drives[$i]->{'type'} = ''; $drives[$i]->{'vendor'} = ''; } - #print "$i\n"; - if ($bsd_type eq 'openbsd'){ - if ($row[1] =~ /(^|,\s*)([0-9\.]+[MGTPE][B]?),.*\ssectors$|^{'size'} = $working; - } - if ($row[2] && $row[2] =~ /<([^>]+)>/){ - $drives[$i]->{'model'} = $1 if $1; - $drives[$i]->{'type'} = 'removable' if $_ =~ /removable$/; - # - my $count = ($drives[$i]->{'model'} =~ tr/,//); - if ($count && $count > 1){ - @temp = split(/,\s*/, $drives[$i]->{'model'}); - $drives[$i]->{'model'} = $temp[1]; - } - } - # print "openbsd\n"; + #print "$_ i: $i\n"; + # openbsd/netbsd matches will often work + if ($row[1] =~ /(^|,\s*)([0-9\.]+\s*[MGTPE])i?B?[,.\s]+([0-9]+)\ssectors$|^{'block-physical'} = ($working/$3)*1024 if $3; + $size += $working if $working; + $drives[$i]->{'size'} = $working; } - else { - if ($row[1] =~ /^([0-9]+[KMGTPE][B]?)\s/){ - $working = main::translate_size($1); - $size += $working if $working; - $drives[$i]->{'size'} = $working; - } - if ($row[1] =~ /device$|^]*)>\s(.*)/; - $drives[$i]->{'model'} = $1 if $1; - $drives[$i]->{'spec'} = $2 if $2; - } - if ($row[1] =~ /^Serial\sNumber\s(.*)/){ - $drives[$i]->{'serial'} = $1; - } - if ($row[1] =~ /^([0-9\.]+[MG][B]?\/s)/){ - $drives[$i]->{'speed'} = $1; - $drives[$i]->{'speed'} =~ s/\.[0-9]+// if $drives[$i]->{'speed'}; + # don't set both, if smartctl installed, we want to use its data so having + # only one of logical/physical will trip use of smartctl values + if ($row[1] =~ /[\s,]+([0-9]+)\sbytes?[\s\/]sect/ ){ + #$drives[$i]->{'block-logical'} = $1; + $drives[$i]->{'block-physical'} = $1; + } + if ($row[2] && $row[2] =~ /<([^>]+)>/){ + $drives[$i]->{'model'} = $1 if $1; + $drives[$i]->{'type'} = 'removable' if $_ =~ /removable/; + # + my $count = ($drives[$i]->{'model'} =~ tr/,//); + if ($count && $count > 1){ + @temp = split(/,\s*/, $drives[$i]->{'model'}); + $drives[$i]->{'model'} = $temp[1]; } } + if ($row[2] && $row[2] =~ /\sserial\.(\S*)/){ + $drives[$i]->{'serial'} = $1; + } + if (!$drives[$i]->{'serial'} && $row[1] =~ /^Serial\sNumber\s(.*)/){ + $drives[$i]->{'serial'} = $1; + } + # these were mainly FreeBSD/Dragonfly matches + if (!$drives[$i]->{'size'} && $row[1] =~ /^([0-9]+\s*[KMGTPE])i?B?[\s,]/){ + $working = main::translate_size($1); + $size += $working if $working; + $drives[$i]->{'size'} = $working; + } + if ($row[1] =~ /(device$|^([0-9\.]+\s*[KMGT]B\s+)?<)/){ + $row[1] =~ s/\sdevice$//g; + $row[1] =~ /<([^>]*)>(\s(.*))?/; + $drives[$i]->{'model'} = $1 if $1; + $drives[$i]->{'spec'} = $3 if $3; + } + if ($row[1] =~ /^([0-9\.]+[MG][B]?\/s)/){ + $drives[$i]->{'speed'} = $1; + $drives[$i]->{'speed'} =~ s/\.[0-9]+// if $drives[$i]->{'speed'}; + } $drives[$i]->{'model'} = main::disk_cleaner($drives[$i]->{'model'}); my @device_data = device_vendor($drives[$i]->{'model'},''); $drives[$i]->{'vendor'} = $device_data[0] if $device_data[0]; @@ -9707,10 +10063,10 @@ sub dmesg_boot_data { $size = main::row_defaults('data-bsd'); } } - elsif ( $file && ! -r $file ){ + elsif ($file && ! -r $file){ $size = main::row_defaults('dmesg-boot-permissions'); } - elsif (!$file ){ + elsif (!$file){ $size = main::row_defaults('dmesg-boot-missing'); } @data = ({ @@ -9819,7 +10175,7 @@ sub smartctl_data { eval $start if $b_log; my ($data) = @_; my ($b_attributes,$b_intel,$b_kingston,$cmd,%holder,$id,@working,@result,@split); - my ($splitter,$num,$a,$f,$r,$t,$v,$w,$y) = (':\s*',0,0,8,1,5,3,4,6); # $y is type, $t threashold, etc + my ($splitter,$num,$a,$f,$r,$t,$v,$w,$y) = (':\s*',0,0,8,1,5,3,4,6); # $y is type, $t threshold, etc for (my $i = 0; $i < scalar @$data; $i++){ next if !$data->[$i]{'id'}; ($b_attributes,$b_intel,$b_kingston,$splitter,$num,$a,$r) = (0,0,0,':\s*',0,0,1); @@ -9832,7 +10188,7 @@ sub smartctl_data { @result = main::grabber("$cmd", '', 'strip'); main::log_data('dump','@result', \@result) if $b_log; # log before cleanup @result = grep {!/^(smartctl|Copyright|==)/} @result; - print 'Drive:/dev/' . $id . ":\n", Data::Dumper::Dumper\@result if $test[12]; + print 'Drive:/dev/' . $id . ":\n", Data::Dumper::Dumper\@result if $dbg[12]; if (scalar @result < 4 ){ if (grep {/failed: permission denied/i} @result){ $data->[$i]{'smart-permissions'} = main::row_defaults('tool-permissions','smartctl'); @@ -9914,9 +10270,9 @@ sub smartctl_data { $data->[$i]{'speed'} = $2 if !$data->[$i]{'speed'}; } } - # seen both Size and Sizes + # seen both Size and Sizes. Linux will usually have both, BSDs not physical elsif ($split[$a] =~ /^Sector Sizes?$/ ){ - if( $data->[$i]{'type'} || !$data->[$i]{'block-logical'} || !$data->[$i]{'block-physical'} ){ + if ($data->[$i]{'type'} || !$data->[$i]{'block-logical'} || !$data->[$i]{'block-physical'} ){ if ($split[$r] =~ m|^([0-9]+) bytes logical/physical| ){ $data->[$i]{'block-logical'} = $1; $data->[$i]{'block-physical'} = $1; @@ -10182,7 +10538,7 @@ sub smartctl_data { } } } - print Data::Dumper::Dumper $data if $test[19]; + print Data::Dumper::Dumper $data if $dbg[19]; eval $end if $b_log; return @$data; } @@ -10357,18 +10713,20 @@ sub set_vendors { ['(^MKN|Mushkin)','Mushkin','Mushkin',''], # MKNS # MU = Multiple_Flash_Reader too risky: |M[UZ][^L] HD103SI HD start risky # HM320II HM320II - ['(SAMSUNG|^MCG[0-9]+GC|^MCC|^MCBOE|\bEVO\b|^[GS]2 Portable|^DS20|^[DG]3 Station|^DUO\b|^P3|^[BC]GN|^[CD]JN|^BJ[NT]|^[BC]WB|^(HM|SP)[0-9]{2}|^MZMPC|^HD[0-9]{3}[A-Z]{2}$|SV[0-9]|E[A-Z][1-9]QT|YP\b)','SAMSUNG','Samsung',''], # maybe ^SM, ^HM + ['(SAMSUNG|^MCG[0-9]+GC|^MCC|^MCBOE|\bEVO\b|^[GS]2 Portable|^DS20|^[DG]3 Station|^DUO\b|^P3|^[BC]GN|^[CD]JN|^BJ[NT]|^[BC]WB|^(HM|SP)[0-9]{2}|^MZMPC|^HD[0-9]{3}[A-Z]{2}$|^G[CD][1-9][QS]|^M[AB]G[0-9][FG]|SV[0-9]|E[A-Z][1-9]QT|YP\b)','SAMSUNG','Samsung',''], # maybe ^SM, ^HM # Android UMS Composite? - ['(SanDisk|^SDS[S]?[DQ]|^D[AB]4|^SL([0-9]+)G|^AFGCE|^ABLCD|^SDW[1-9]|^SEM[1-9]|^U3\b|^SU[0-9]|^DX[1-9]|ULTRA\s(FIT|trek)|Clip Sport|Cruzer|^Extreme|iXpand)','SanDisk','SanDisk',''], + ['(SanDisk|^SDS[S]?[DQ]|^D[AB]4|^SL([0-9]+)G|^AFGCE|^ABLCD|^SDW[1-9]|^SEM[1-9]|^U3\b|^SU[0-9]|^DX[1-9]|^S[CD][0-9]{2}G|ULTRA\s(FIT|trek)|Clip Sport|Cruzer|^Extreme|iXpand)','SanDisk','SanDisk',''], # these are HP/Sandisk cobranded. DX110064A5xnNMRI ids as HP and Sandisc ['(^DX[1-9])','^(HP\b|SANDDISK)','Sandisk/HP',''], # ssd drive, must come before seagate ST test # real, SSEAGATE Backup+; XP1600HE30002 | 024 HN (spinpoint) ; possible usb: 24AS - ['(^ST[^T]|[S]?SEAGATE|^X[AFP]|^5AS|^BUP|Expansion Desk|^Expansion|FreeAgent|GoFlex|Backup(\+|\s?Plus)\s?(Hub)?|OneTouch|Slim\s? BK)','[S]?SEAGATE','Seagate',''], + # ST[numbers] excludes other ST starting devices + ['(^ST[0-9]{2}|[S]?SEAGATE|^X[AFP]|^5AS|^BUP|Expansion Desk|^Expansion|FreeAgent|GoFlex|Backup(\+|\s?Plus)\s?(Hub)?|OneTouch|Slim\s? BK)','[S]?SEAGATE','Seagate',''], ['^(WD|WL[0]9]|Western Digital|My (Book|Passport)|\d*LPCX|Elements|easystore|MD0|M000|EARX|EFRX|\d*EAVS|0JD|JP[CV]|[0-9]+(BEV|(00)?AAK|AAV|AZL|EA[CD]S)|3200[AB]|2500[BJ]|EA[A-Z]S|20G2|5000[AB]|6400[AB]|7500[AB]|i HTS|00[ABL][A-Z]{2})','(^WDC|Western\s?Digital)','Western Digital',''], # rare cases WDC is in middle of string ['(\bWDC\b)','','Western Digital',''], ## THEN BETTER KNOWN ONESs ## - ['^(A-?DATA|AX[MN]|CH11|HV[1-9]|IM2|HD[1-9]|HDD\s?CH|IUM)','^A-?DATA','A-Data',''], + # A-Data can be in middle of string + ['^(.*\bA-?DATA|ASP[0-9]|AX[MN]|CH11|HV[1-9]|IM2|HD[1-9]|HDD\s?CH|IUM)','A-?DATA','A-Data',''], ['^ASUS','^ASUS','ASUS',''], # ATCS05 can be hitachi travelstar but not sure ['^ATP','^ATP\b','ATP',''], @@ -10391,11 +10749,12 @@ sub set_vendors { ['^(PNY|Hook\s?Attache|SSD2SC|(SSD7?)?EP7)','^PNY\s','PNY','','^PNY'], # note: get rid of: M[DGK] becasue mushkin starts with MK # note: seen: KXG50ZNV512G NVMe TOSHIBA 512GB | THNSN51T02DUK NVMe TOSHIBA 1024GB - ['(^[S]?TOS|^THN|TOSHIBA|TransMemory|^M[GKQ][0-9]|KBG4)','[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_ + ['(^[S]?TOS|^THN|TOSHIBA|TransMemory|^M[GKQ][0-9]|KBG4|^SA[0-9]{2}G$)','[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_ ## LAST: THEY ARE SHORT AND COULD LEAD TO FALSE ID, OR ARE UNLIKELY ## # unknown: AL25744_12345678; ADP may be usb 2.5" adapter; udisk unknown: Z1E6FTKJ 00AAKS # SSD2SC240G726A10 MRS020A128GTS25C EHSAJM0016GB ['^5ACE','^5ACE','5ACE',''], # could be seagate: ST316021 5ACE + ['^(Aarvex|AX[0-9]{2})','^AARVEX','AARVEX',''], ['^(AbonMax|ASU[0-9])','^AbonMax','AbonMax',''], ['^Acasis','^Acasis','Acasis (hub)',''], ['^Acclamator','^Acclamator','Acclamator',''], @@ -10486,6 +10845,7 @@ sub set_vendors { ['^Fordisk','^Fordisk','Fordisk',''], # FK0032CAAZP/FB160C4081 FK or FV can be HP but can be other things ['^FORESEE','^FORESEE','ForeseSU04Ge',''], + ['^Founder','^Founder','Founder',''], ['^(FOXLINE|FLD)','^FOXLINE','Foxline',''], # russian vendor? ['^(GALAX\b|Gamer\s?L)','^GALAX','GALAX',''], ['^Galaxy\b','^Galaxy','Galaxy',''], @@ -10520,7 +10880,7 @@ sub set_vendors { ['^INDMEM','^INDMEM','INDMEM',''], ['^Inland','^Inland','Inland',''], ['^(InnoDisk|Innolite)','^InnoDisk( Corp.)?','InnoDisk',''], - ['^Innostor','^Innostor','Innostor',''], + ['Innostor','Innostor','Innostor',''], ['^Innovation','^Innovation(\s*IT)?','Innovation IT',''], ['^Innovera','^Innovera','Innovera',''], ['^Intaiel','^Intaiel','Intaiel',''], @@ -10556,14 +10916,14 @@ sub set_vendors { ['^(LEN|UMIS)','^Lenovo','Lenovo',''], ['^RPFT','','Lenovo O.E.M.',''], ['^LG\b','^LG','LG',''], - ['^(LITE[-\s]?ON[\s-]?IT)','^LITE[-]?ON[\s-]?IT','LITE-ON IT',''], # LITEONIT_LSS-24L6G - ['^(LITE[-\s]?ON|PH[1-9])','^LITE[-]?ON','LITE-ON',''], # PH6-CE240-L + ['(LITE[-\s]?ON[\s-]?IT)','LITE[-]?ON[\s-]?IT','LITE-ON IT',''], # LITEONIT_LSS-24L6G + ['(LITE[-\s]?ON|^PH[1-9])','LITE[-]?ON','LITE-ON',''], # PH6-CE240-L; CL1-3D256-Q11 NVMe LITEON 256GB ['^LONDISK','^LONDISK','LONDISK',''], ['^(LSI|MegaRAID)','^LSI\b','LSI',''], ['^(M-Systems|DiskOnKey)','^M-Systems','M-Systems',''], ['^(Mach\s*Xtreme|MXSSD|MXU)','^Mach\s*Xtreme','Mach Xtreme',''], ['^Maximus','^Maximus','Maximus',''], - ['^(MAXTOR|Atlas|TM[0-9]{4}|[KL]0[1-9]|Y[0-9]{3}[A-Z])','^MAXTOR','Maxtor',''], # note M2 M3 is usually maxtor, but can be samsung + ['^(MAXTOR|Atlas|TM[0-9]{4}|[KL]0[1-9]|Y[0-9]{3}[A-Z]|STM[0-9])','^MAXTOR','Maxtor',''], # note M2 M3 is usually maxtor, but can be samsung ['^(Memorex|TravelDrive|TD\s?Classic)','^Memorex','Memorex',''], # note: C300/400 can be either micron or crucial, but C400 is M4 from crucial ['(^MT|^M5|^Micron|00-MT|C[34]00)','^Micron','Micron',''],# C400-MTFDDAK128MAM @@ -10597,6 +10957,7 @@ sub set_vendors { ['^Netac','^Netac','Netac',''], # NGFF is a type, like msata, sata ['^Nik','^Nikimi','Nikimi',''], + ['^NOREL','^NOREL(SYS)?','NorelSys',''], ['^Orico','^Orico','Orico',''], ['^OSC','^OSC\b','OSC',''], ['^OWC','^OWC\b','OWC',''], @@ -10638,6 +10999,7 @@ sub set_vendors { ['^(SILICON\s?MOTION|SM[0-9])','^SILICON\s?MOTION','Silicon Motion',''], ['(Silicon[\s-]?Power|^SP[CP]C|^Silicon|^Diamond|^HasTopSunlightpeed)','Silicon[\s-]?Power','Silicon Power',''], ['^SINTECHI?','^SINTECHI?','SinTech (adapter)',''], + ['^SiS\b','^SiS','SiS',''], ['Smartbuy','\s?Smartbuy','Smartbuy',''], # SSD Smartbuy 60GB; mSata Smartbuy 3 # HFS128G39TND-N210A; seen nvme with name in middle ['(SK\s?HYNIX|^HF[MS]|^H[BC]G)','\s?SK\s?HYNIX','SK Hynix',''], @@ -10695,6 +11057,8 @@ sub set_vendors { ['^VMware','^VMware','VMware',''], ['^(Vseky|Vaseky)','^Vaseky','Vaseky',''], # ata-Vseky_V880_350G_ ['^(Walgreen|Infinitive)','^Walgreen','Walgreen',''], + ['^Walton','^Walton','Walton',''], + ['^(Wearable|Air-?Stash)','^Wearable','Wearable',''], ['^Wellcomm','^Wellcomm','Wellcomm',''], ['^Wilk','^Wilk','Wilk',''], ['^(Wortmann(\sAG)?|Terra\s?US)','^Wortmann(\sAG)?','Wortmann AG',''], @@ -10759,7 +11123,7 @@ sub hdd_temp { my ($device) = @_; my ($path) = (''); my (@data,$hdd_temp); - $hdd_temp = hdd_temp_sys($device) if !$b_hddtemp_force && -e "/sys/block/$device"; + $hdd_temp = hdd_temp_sys($device) if !$force{'hddtemp'} && -e "/sys/block/$device"; if (!$hdd_temp){ $device = "/dev/$device"; if ($device =~ /nvme/i){ @@ -10771,7 +11135,7 @@ sub hdd_temp { } if ($nvme){ $device =~ s/n[0-9]//; - @data = main::grabber("$sudo$nvme smart-log $device 2>/dev/null"); + @data = main::grabber("$sudoas$nvme smart-log $device 2>/dev/null"); foreach (@data){ my @row = split(/\s*:\s*/, $_); next if !$row[0]; @@ -10792,7 +11156,7 @@ sub hdd_temp { } } if ($hddtemp){ - $hdd_temp = (main::grabber("$sudo$hddtemp -nq -u C $device 2>/dev/null"))[0]; + $hdd_temp = (main::grabber("$sudoas$hddtemp -nq -u C $device 2>/dev/null"))[0]; } } $hdd_temp =~ s/\s?(Celsius|C)$// if $hdd_temp; @@ -10810,7 +11174,10 @@ sub hdd_temp_sys { # slice out the part of path that gives us hwmon $path =~ s%/(block|nvme)/.*$%%; return if ! -e "$path/hwmon/"; - my @data = main::globber("$path/hwmon/hwmon*/temp*"); + # we don't want these: crit|max|min|lowest|highest + # seeing long lag to read temp input files for some reason + # on some systems, just one one of them. + my @data = main::globber("$path/hwmon/hwmon*/temp*_{input,label}"); #print "device: $device\n"; foreach (sort @data){ #print "file: $_\n"; @@ -10847,7 +11214,7 @@ sub hdd_temp_sys { $hdd_temp = sprintf("%.1f", $hdd_temp/1000) if $hdd_temp; main::log_data('data',"device: $device temp: $hdd_temp") if $b_log; main::log_data('dump','%sensors',\%sensors) if $b_log; - print Data::Dumper::Dumper \%sensors if $test[21]; + print Data::Dumper::Dumper \%sensors if $dbg[21]; eval $end if $b_log; return $hdd_temp; } @@ -10936,38 +11303,6 @@ sub device_speed { eval $end if $b_log; return @data; } -# gptid/c5e940f1-5ce2-11e6-9eeb-d05099ac4dc2 N/A ada0p1 -sub match_glabel { - eval $start if $b_log; - my ($gptid) = @_; - return if !@glabel || ! $gptid; - #$gptid =~ s/s[0-9]+$//; - my ($dev_id) = (''); - foreach (@glabel){ - my @temp = split(/\s+/, $_); - my $gptid_trimmed = $gptid; - # slice off s[0-9] from end in case they use slice syntax - $gptid_trimmed =~ s/s[0-9]+$//; - if (defined $temp[0] && ($temp[0] eq $gptid || $temp[0] eq $gptid_trimmed ) ){ - $dev_id = $temp[2]; - last; - } - } - $dev_id ||= $gptid; # no match? return full string - eval $end if $b_log; - return $dev_id; -} -sub set_glabel { - eval $start if $b_log; - $b_glabel = 1; - if (my $path = main::check_program('glabel')){ - @glabel = main::grabber("$path status 2>/dev/null"); - } - main::log_data('dump','@glabel:with Headers',\@glabel) if $b_log; - # get rid of first header line - shift @glabel; - eval $end if $b_log; -} } ## GraphicData @@ -10979,7 +11314,7 @@ sub get { eval $start if $b_log; my (@rows); my $num = 0; - if (($b_arm || $b_mips) && !$b_soc_gfx && !$b_pci_tool){ + if (($b_arm || $b_mips) && !$use{'soc-gfx'} && !$use{'pci-tool'}){ my $type = ($b_arm) ? 'arm' : 'mips'; my $key = 'Message'; push(@rows, { @@ -11024,16 +11359,16 @@ sub device_output { $j = scalar @rows; $driver = $row->[9]; $driver ||= 'N/A'; - my $card = main::trimmer($row->[4]); - $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; + my $device = main::trimmer($row->[4]); + $device = ($device) ? main::pci_cleaner($device,'output') : 'N/A'; # have seen absurdly verbose card descriptions, with non related data etc - if (length($card) > 85 || $size{'max'} < 110){ - $card = main::pci_long_filter($card); + if (length($device) > 85 || $size{'max'} < 110){ + $device = main::pci_long_filter($device); } push(@rows, { - main::key($num++,1,1,'Device') => $card, + main::key($num++,1,1,'Device') => $device, },); - if ($extra > 0 && $b_pci_tool && $row->[12]){ + if ($extra > 0 && $use{'pci-tool'} && $row->[12]){ my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]->{main::key($num++,0,2,'vendor')} = $item if $item; } @@ -11048,13 +11383,13 @@ sub device_output { $rows[$j]->{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10]; } if ($extra > 0){ - $rows[$j]->{main::key($num++,0,2,'bus ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; + $rows[$j]->{main::key($num++,0,2,'bus-ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; } if ($extra > 1){ - $rows[$j]->{main::key($num++,0,2,'chip ID')} = ($row->[5]) ? "$row->[5]:$row->[6]" : $row->[6]; + $rows[$j]->{main::key($num++,0,2,'chip-ID')} = ($row->[5]) ? "$row->[5]:$row->[6]" : $row->[6]; } if ($extra > 2 && $row->[1]){ - $rows[$j]->{main::key($num++,0,2,'class ID')} = $row->[1]; + $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->[1]; } #print "$row->[0]\n"; } @@ -11065,46 +11400,44 @@ sub usb_output { eval $start if $b_log; my (@rows,@ids,$driver,$path_id,$product,@temp2); my ($j,$num) = (0,1); - return if !@usb; - foreach my $row (@usb){ + return if !@usb_graphics; + foreach my $row (@usb_graphics){ # these tests only work for /sys based usb data for now - if ($row->[14] && ($row->[14] eq 'Audio-Video' || $row->[14] eq 'Video' ) ){ - $num = 1; - $j = scalar @rows; - # makre sure to reset, or second device trips last flag - ($driver,$path_id,$product) = ('','',''); - $product = main::cleaner($row->[13]) if $row->[13]; - $driver = $row->[15] if $row->[15]; - $path_id = $row->[2] if $row->[2]; - $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'){ - $driver = 'N/A'; - } - else { - $driver = 'N/A'; - } + $num = 1; + $j = scalar @rows; + # makre sure to reset, or second device trips last flag + ($driver,$path_id,$product) = ('','',''); + $product = main::cleaner($row->[13]) if $row->[13]; + $driver = $row->[15] if $row->[15]; + $path_id = $row->[2] if $row->[2]; + $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'){ + $driver = 'N/A'; } - push(@rows, { - main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', - main::key($num++,0,2,'driver') => $driver, - },); - if ($extra > 0){ - $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::apply_filter($row->[16]); + else { + $driver = 'N/A'; } } + push(@rows, { + main::key($num++,1,1,'Device') => $product, + main::key($num++,0,2,'type') => 'USB', + main::key($num++,0,2,'driver') => $driver, + },); + if ($extra > 0){ + $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::apply_filter($row->[16]); + } } eval $end if $b_log; return @rows; @@ -11215,7 +11548,7 @@ sub display_output(){ } if ($b_admin ){ if (defined $graphics{'display-id'}){ - $row[0]->{main::key($num++,0,2,'display ID')} = $graphics{'display-id'}; + $row[0]->{main::key($num++,0,2,'display-ID')} = $graphics{'display-id'}; } if (defined $graphics{'display-screens'}){ $row[0]->{main::key($num++,0,2,'screens')} = $graphics{'display-screens'}; @@ -11498,7 +11831,7 @@ sub display_data_x { else { $graphics{'no-xdpyinfo'} = main::row_defaults('tool-missing-basic','xdpyinfo'); } - print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $test[17]; + print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17]; main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log; eval $end if $b_log; } @@ -11509,7 +11842,7 @@ sub display_data_wayland { # return as wayland-0 or 0? $graphics{'display-id'} =~ s/wayland-?//i; } - #print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $test[17]; + #print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17]; #main::log_data('dump','@graphics{screens}',$graphics{'screens'}) if $b_log; eval $end if $b_log; } @@ -11537,7 +11870,7 @@ sub get_protocol { $protocol = '' if $protocol eq 'tty'; # need to confirm that there's a point to this test, I believe no, fails out of x # loginctl also results in the session id - if (!$protocol && $b_display && $b_force_display){ + if (!$protocol && $b_display && $force{'display'}){ if (my $program = main::check_program('loginctl')){ my $id = ''; # $id = $ENV{'XDG_SESSION_ID'}; # returns tty session in console @@ -11723,11 +12056,13 @@ sub x_drivers { my ($driver,@driver_data,,%drivers); my ($alternate,$failed,$loaded,$sep,$unloaded) = ('','','','',''); if (my $log = main::system_files('xorg-log')){ - # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/Xorg.0-voyager-serena.log"; - # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/loading-unload-failed-all41-mint.txt"; - # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/loading-unload-failed-phd21-mint.txt"; - # $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"; + if ($fake{'xorg-log'}) { + # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/Xorg.0-voyager-serena.log"; + # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/loading-unload-failed-all41-mint.txt"; + # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/loading-unload-failed-phd21-mint.txt"; + # $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); # list is from sgfxi plus non-free drivers, plus ARM drivers my $list = join('|', qw(amdgpu apm ark armsoc atimisc ati @@ -11860,7 +12195,7 @@ sub display_compositor { eval $start if $b_log; my ($protocol) = @_; my ($compositor) = (''); - main::set_ps_gui() if !$b_ps_gui; + main::set_ps_gui() if !$loaded{'ps-gui'}; if (@ps_gui){ # 1 check program; 2 search; 3 unused version; 4 print my @compositors = ( @@ -11938,13 +12273,13 @@ sub get { @rows = ({main::key($num++,0,1,$key1) => $val1,}); } else { - main::set_lsblk() if !$b_lsblk; - if ($b_fake_logical || $alerts{'lvs'}->{'action'} eq 'use'){ - lvm_data() if !$b_lvm_data; + main::set_lsblk() if !$loaded{'lsblk'}; + if ($fake{'logical'} || $alerts{'lvs'}->{'action'} eq 'use'){ + lvm_data() if !$loaded{'lvm-data'}; if (!@lvm){ my $key = 'Message'; # note: arch linux has a bug where lvs returns 0 if non root start - my $message = ($b_active_lvm) ? $alerts{'lvs'}->{'permissions'} : main::row_defaults('lvm-data',''); + my $message = ($use{'logical-lvm'}) ? main::row_defaults('tool-permissions','lvs') : main::row_defaults('lvm-data',''); push(@rows, { main::key($num++,0,1,$key) => $message, },); @@ -11954,13 +12289,13 @@ sub get { @rows = lvm_output(\%processed); } } - elsif ($b_active_lvm && $alerts{'lvs'}->{'action'} eq 'permissions'){ + elsif ($use{'logical-lvm'} && $alerts{'lvs'}->{'action'} eq 'permissions'){ my $key = 'Message'; push(@rows, { - main::key($num++,0,1,$key) => $alerts{'lvs'}->{'permissions'}, + main::key($num++,0,1,$key) => $alerts{'lvs'}->{'message'}, },); } - elsif (@lsblk && !$b_active_lvm && ($alerts{'lvs'}->{'action'} eq 'permissions' || + elsif (@lsblk && !$use{'logical-lvm'} && ($alerts{'lvs'}->{'action'} eq 'permissions' || $alerts{'lvs'}->{'action'} eq 'missing')){ my $key = 'Message'; push(@rows, { @@ -11969,11 +12304,11 @@ sub get { } elsif ($alerts{'lvs'}->{'action'} ne 'use'){ $key1 = $alerts{'lvs'}->{'action'}; - $val1 = $alerts{'lvs'}->{$key1}; + $val1 = $alerts{'lvs'}->{'message'}; $key1 = ucfirst($key1); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } - if ($b_active_general){ + if ($use{'logical-general'}){ my @general_data = general_data(); push(@rows,general_output(\@general_data)) if @general_data; } @@ -12116,7 +12451,7 @@ sub components_recursive_output { sub general_data { eval $start if $b_log; my (@found,@general_data,%parent,$parent_fs); - main::set_mapper() if !$b_mapper; + main::set_mapper() if !$loaded{'mapper'}; foreach my $row (@lsblk){ # bcache doesn't have mapped name: !$mapper{$row->{'name'}} || next if !$row->{'parent'}; @@ -12165,7 +12500,7 @@ sub general_data { } } main::log_data('dump','luks @general_data', \@general_data); - print Data::Dumper::Dumper \@general_data if $test[23]; + print Data::Dumper::Dumper \@general_data if $dbg[23]; eval $end if $b_log; return @general_data; } @@ -12173,18 +12508,18 @@ sub general_data { # note: called for disk totals, raid, and logical sub lvm_data { eval $start if $b_log; - $b_lvm_data = 1; - main::set_proc_partitions() if !$b_proc_partitions; - main::set_mapper() if !$b_mapper; + $loaded{'lvm-data'} = 1; + main::set_proc_partitions() if !$loaded{'proc-partitions'}; + main::set_mapper() if !$loaded{'mapper'}; my (@args,@data,%totals); @args = qw(vg_name vg_fmt vg_size vg_free lv_name lv_layout lv_size lv_kernel_major lv_kernel_minor segtype seg_count seg_start_pe seg_size_pe stripes devices raid_mismatch_count raid_sync_action raid_write_behind copy_percent); my $num = 0; - if ($b_fake_logical){ - my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lvm/lvs-test-1.txt"; - @data = main::reader($file,'strip'); + if ($fake{'logical'}){ + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lvm/lvs-test-1.txt"; + #@data = main::reader($file,'strip'); } else { # lv_full_name: ar0-home; lv_dm_path: /dev/mapper/ar0-home @@ -12197,11 +12532,12 @@ sub lvm_data { $cmd .= ' 2>/dev/null'; @data = main::grabber("$cmd",'','strip'); main::log_data('dump','lvm @data', \@data) if $b_log; - print "command: $cmd\n" if $test[22]; + print "command: $cmd\n" if $dbg[22]; } my $j = 0; foreach (@data){ my @line = split(/\^:/, $_); + next if $_ =~ /^Partial mode/i; # sometimes 2>/dev/null doesn't catch this for (my $i = 0; $i < scalar @args; $i++){ $line[$i] =~ s/k$// if $args[$i] =~ /_(free|size|used)$/; $lvm[$j]->{$args[$i]} = $line[$i]; @@ -12214,7 +12550,7 @@ sub lvm_data { } # print Data::Dumper::Dumper \%totals, \@raw_logical; main::log_data('dump','lvm @lvm', \@lvm) if $b_log; - print Data::Dumper::Dumper \@lvm if $test[22]; + print Data::Dumper::Dumper \@lvm if $dbg[22]; eval $end if $b_log; } sub process_lvm_data { @@ -12250,7 +12586,7 @@ sub process_lvm_data { } } main::log_data('dump','lvm %processed', \%processed) if $b_log; - print Data::Dumper::Dumper \%processed if $test[23]; + print Data::Dumper::Dumper \%processed if $dbg[23]; eval $end if $b_log; return %processed; } @@ -12292,7 +12628,7 @@ sub get { eval $start if $b_log; my (%soc_machine,%data,@rows,$key1,$val1,$which); my $num = 0; - if ($bsd_type && @sysctl_machine && !$b_dmidecode_force ){ + if ($bsd_type && @sysctl_machine && !$force{'dmidecode'} ){ %data = machine_data_sysctl(); if (%data){ @rows = machine_output(\%data); @@ -12302,10 +12638,10 @@ sub get { $val1 = main::row_defaults('machine-data-force-dmidecode',''); } } - elsif ($bsd_type || $b_dmidecode_force){ - if ( !$b_fake_dmidecode && $alerts{'dmidecode'}->{'action'} ne 'use'){ + elsif ($bsd_type || $force{'dmidecode'}){ + if ( !$fake{'dmidecode'} && $alerts{'dmidecode'}->{'action'} ne 'use'){ $key1 = $alerts{'dmidecode'}->{'action'}; - $val1 = $alerts{'dmidecode'}->{$key1}; + $val1 = $alerts{'dmidecode'}->{'message'}; $key1 = ucfirst($key1); } else { @@ -12407,7 +12743,8 @@ sub machine_output { # no point in showing chassis if system isn't there, it's very unlikely that # would be correct if ($extra > 1){ - if ($data->{'board_version'} && $data->{'chassis_version'} eq $data->{'board_version'}){ + if ($data->{'board_version'} && $data->{'chassis_version'} && + $data->{'chassis_version'} eq $data->{'board_version'}){ $b_skip_chassis = 1; } if (!$b_skip_chassis && $data->{'chassis_vendor'} ){ @@ -12545,7 +12882,7 @@ sub machine_data_sys { $data{'firmware'} = 'UEFI'; } elsif ( glob('/sys/firmware/acpi/tables/UEFI*') ){ - $data{'firmware'} = 'UEFI [Legacy]'; + $data{'firmware'} = 'UEFI-[Legacy]'; } foreach (@sys_files){ $path = "$sys_dir$_"; @@ -12573,6 +12910,7 @@ sub machine_data_sys { # 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; @@ -12610,7 +12948,7 @@ sub machine_data_soc { } } if (!$data{'model'} && $b_android){ - main::set_build_prop() if !$b_build_prop; + main::set_build_prop() if !$loaded{'build-prop'}; if ($build_prop{'product-manufacturer'} && $build_prop{'product-model'}){ my $brand = ''; if ($build_prop{'product-brand'} && @@ -12645,8 +12983,8 @@ sub machine_data_soc { main::log_data('data',"device-tree-serial: $serial") if $b_log; $data{'serial'} = $serial if $serial; } - - #print Data::Dumper::Dumper \%data; + print Data::Dumper::Dumper \%data if $dbg[28]; + main::log_data('dump','%data',\%data) if $b_log; eval $end if $b_log; return %data; } @@ -12786,7 +13124,7 @@ sub machine_data_dmi { # foreach (keys %data){ # print "$_: $data{$_}\n"; # } - #print Data::Dumper::Dumper \%data; + print Data::Dumper::Dumper \%data if $dbg[28]; main::log_data('dump','%data',\%data) if $b_log; eval $end if $b_log; return %data; @@ -12801,39 +13139,72 @@ sub machine_data_sysctl { next if ! $_; my @item = split(':', $_); next if ! $item[1]; - if ($item[0] eq 'hw.vendor'){ + if ($item[0] eq 'hw.vendor' || $item[0] eq 'machdep.dmi.board-vendor'){ $data{'board_vendor'} = main::dmi_cleaner($item[1]); } - elsif ($item[0] eq 'hw.product'){ + elsif ($item[0] eq 'hw.product' || $item[0] eq 'machdep.dmi.board-product'){ $data{'board_name'} = main::dmi_cleaner($item[1]); } - elsif ($item[0] eq 'hw.version'){ - $data{'board_version'} = $item[1]; + elsif ($item[0] eq 'hw.version' || $item[0] eq 'machdep.dmi.board-version'){ + $data{'board_version'} = main::dmi_cleaner($item[1]); } - elsif ($item[0] eq 'hw.serialno'){ - $data{'board_serial'} = $item[1]; + elsif ($item[0] eq 'hw.serialno' || $item[0] eq 'machdep.dmi.board-serial'){ + $data{'board_serial'} = main::dmi_cleaner($item[1]); } elsif ($item[0] eq 'hw.serial'){ - $data{'board_serial'} = $item[1]; + $data{'board_serial'} = main::dmi_cleaner($item[1]); } elsif ($item[0] eq 'hw.uuid'){ - $data{'board_uuid'} = $item[1]; + $data{'board_uuid'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.system-vendor'){ + $data{'sys_vendor'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.system-product'){ + $data{'product_name'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.system-version'){ + $data{'product_version'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.system-serial'){ + $data{'product_serial'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.system-uuid'){ + $data{'sys_uuid'} = main::dmi_cleaner($item[1]); } # bios0:at mainbus0: AT/286+ BIOS, date 06/30/06, BIOS32 rev. 0 @ 0xf2030, SMBIOS rev. 2.4 @ 0xf0000 (47 entries) # bios0:vendor Phoenix Technologies, LTD version "3.00" date 06/30/2006 elsif ($item[0] =~ /^bios[0-9]/){ - if ($_ =~ /^^bios[0-9]:at\s.*\srev\.\s([\S]+)\s@.*/){ + if ($_ =~ /^^bios[0-9]:at\s.*?\srev\.\s([\S]+)\s@.*/){ $data{'bios_rev'} = $1; $data{'firmware'} = 'BIOS' if $_ =~ /BIOS/; } - elsif ($item[1] =~ /^vendor\s(.*)\sversion\s"?([\S]+)"?\sdate\s([\S]+)/ ){ + elsif ($item[1] =~ /^vendor\s(.*?)\sversion\s"?([\S]+)"?\sdate\s([\S]+)/ ){ $data{'bios_vendor'} = $1; $data{'bios_version'} = $2; $data{'bios_date'} = $3; $data{'bios_version'} =~ s/^v//i if $data{'bios_version'} && $data{'bios_version'} !~ /vi/i; } } + elsif ($item[0] eq 'machdep.dmi.bios-vendor'){ + $data{'bios_vendor'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.bios-version'){ + $data{'bios_version'} = main::dmi_cleaner($item[1]); + } + elsif ($item[0] eq 'machdep.dmi.bios-date'){ + $data{'bios_date'} = main::dmi_cleaner($item[1]); + } } + if ($data{'board_vendor'} || $data{'sys_vendor'} || $data{'board_name'} || $data{'product_name'}){ + my $vendor = $data{'sys_vendor'}; + $vendor = $data{'board_vendor'} if !$vendor; + my $product = $data{'product_name'}; + $product = $data{'board_name'} if !$product; + $data{'device'} = get_device_vm($vendor,$product); + } + print Data::Dumper::Dumper \%data if $dbg[28]; + main::log_data('dump','%data',\%data) if $b_log; eval $end if $b_log; return %data; } @@ -12890,6 +13261,8 @@ sub get_device_sys { sub get_device_vm { eval $start if $b_log; my ($manufacturer,$product_name) = @_; + $manufacturer ||= ''; + $product_name ||= ''; my $vm; if ( my $program = main::check_program('systemd-detect-virt') ){ my $vm_test = (main::grabber("$program 2>/dev/null"))[0]; @@ -12972,7 +13345,7 @@ sub get { eval $start if $b_log; my (@rows); my $num = 0; - if (($b_arm || $b_mips) && !$b_soc_net && !$b_pci_tool){ + if (($b_arm || $b_mips) && !$use{'soc-network'} && !$use{'pci-tool'}){ # do nothing, but keep the test conditions to force # the non arm case to always run } @@ -13026,14 +13399,14 @@ sub device_output { } # first check if it's a known wifi id'ed card, if so, no print of duplex/speed $b_wifi = check_wifi($row->[4]); - my $card = $row->[4]; - $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; - #$card ||= 'N/A'; + my $device = $row->[4]; + $device = ($device) ? main::pci_cleaner($device,'output') : 'N/A'; + #$device ||= 'N/A'; $driver ||= 'N/A'; push(@rows, { - main::key($num++,1,1,'Device') => $card, + main::key($num++,1,1,'Device') => $device, },); - if ($extra > 0 && $b_pci_tool && $row->[12]){ + if ($extra > 0 && $use{'pci-tool'} && $row->[12]){ my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]->{main::key($num++,0,2,'vendor')} = $item if $item; } @@ -13060,13 +13433,13 @@ sub device_output { $row->[8] ||= 'N/A'; # as far as I know, wifi has no port, but in case it does in future, use it $rows[$j]->{main::key($num++,0,2,'port')} = $row->[8] if (!$b_wifi || ( $b_wifi && $row->[8] ne 'N/A') ); - $rows[$j]->{main::key($num++,0,2,'bus ID')} = $bus_id; + $rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id; } if ($extra > 1){ - $rows[$j]->{main::key($num++,0,2,'chip ID')} = $chip_id; + $rows[$j]->{main::key($num++,0,2,'chip-ID')} = $chip_id; } if ($extra > 2 && $row->[1]){ - $rows[$j]->{main::key($num++,0,2,'class ID')} = $row->[1]; + $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->[1]; } if ($show{'network-advanced'}){ my @data; @@ -13097,61 +13470,54 @@ sub device_output { } sub usb_output { eval $start if $b_log; - my (@rows,@temp2,$b_wifi,$driver, - $path,$path_id,$product,$test,$type); + return if !@usb_network; + my (@rows,@temp2,$b_wifi,$driver,$path,$path_id,$product,$type); my ($j,$num) = (0,1); - return if !@usb; - foreach my $row (@usb){ - # a device will always be the second or > device on the bus, except for - # daisychained hubs - if ($row->[1] > 1 && $row->[4] ne '09'){ - $num = 1; - ($driver,$path,$path_id,$product,$test,$type) = ('','','','','',''); - $product = main::cleaner($row->[13]) if $row->[13]; - $driver = $row->[15] if $row->[15]; - $path = $row->[3] if $row->[3]; - $path_id = $row->[2] if $row->[2]; - $type = $row->[14] if $row->[14]; - $test = "$driver $product $type"; - if ($product && network_device($test)){ - $driver ||= 'usb-network'; - push(@rows, { - main::key($num++,1,1,'Device') => $product, - main::key($num++,0,2,'type') => 'USB', - main::key($num++,0,2,'driver') => $driver, - },); - $b_wifi = check_wifi($product); - if ($extra > 0){ - $rows[$j]->{main::key($num++,0,2,'bus ID')} = "$path_id:$row->[1]"; - } - if ($extra > 1){ - $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::apply_filter($row->[16]); - } - if ($show{'network-advanced'}){ - my @data; - if (!$bsd_type){ - my (@temp,$vendor,$chip); - @temp = split(':', $row->[7]) if $row->[7]; - ($vendor,$chip) = ($temp[0],$temp[1]) if @temp; - @data = advanced_data_sys($vendor,$chip,0,$b_wifi,$path,''); - } - # NOTE: we need the driver.number, like wlp0 to get a match, and - # we can't get that from usb data, so we have to let it fall back down - # to the check function for BSDs. - #else { - # @data = advanced_data_bsd($row->[2],$b_wifi); - #} - push(@rows,@data) if @data; - } - $j = scalar @rows; - } + foreach my $row (@usb_network){ + $num = 1; + ($driver,$path,$path_id,$product,$type) = ('','','','',''); + $product = main::cleaner($row->[13]) if $row->[13]; + $driver = $row->[15] if $row->[15]; + $path = $row->[3] if $row->[3]; + $path_id = $row->[2] if $row->[2]; + $type = $row->[14] if $row->[14]; + $driver ||= 'N/A'; + push(@rows, { + main::key($num++,1,1,'Device') => $product, + main::key($num++,0,2,'type') => 'USB', + main::key($num++,0,2,'driver') => $driver, + },); + $b_wifi = check_wifi($product); + if ($extra > 0){ + $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::apply_filter($row->[16]); + } + if ($show{'network-advanced'}){ + my @data; + if (!$bsd_type){ + my (@temp,$vendor,$chip); + @temp = split(':', $row->[7]) if $row->[7]; + ($vendor,$chip) = ($temp[0],$temp[1]) if @temp; + @data = advanced_data_sys($vendor,$chip,0,$b_wifi,$path,''); + } + # NOTE: we need the driver.number, like wlp0 to get a match, and + # we can't get that from usb data, so we have to let it fall back down + # to the check function for BSDs. + #else { + # @data = advanced_data_bsd($row->[2],$b_wifi); + #} + push(@rows,@data) if @data; + } + $j = scalar @rows; } eval $end if $b_log; return @rows; @@ -13187,7 +13553,8 @@ sub advanced_data_sys { my ($data1,$data2,$duplex,$mac,$speed,$state); # for usb, we already know where we are if (!$b_usb){ - if (( !$b_arm && !$b_ppc) || $b_pci_tool ){ + # pi mmcnr has pcitool and also these vendor/device paths. + if (( !$b_arm && !$b_ppc) || $use{'pci-tool'} ){ $path = "$_/device/vendor"; $data1 = main::reader($path,'',0) if -r $path; $data1 =~ s/^0x// if $data1; @@ -13197,13 +13564,12 @@ sub advanced_data_sys { # this is a fix for a redhat bug in virtio $data2 = (defined $data2 && $data2 eq '0001' && defined $chip && $chip eq '1000') ? '1000' : $data2; } - elsif ($b_arm || $b_ppc) { - $path = Cwd::abs_path($_); - $path =~ /($chip)/; - if ($1){ - $data1 = $vendor; - $data2 = $chip; - } + # there are cases where arm devices have a small pci bus + # or, with mmcnr devices, will show device/vendor info in data1/2 + # which won't match with the path IDs + if (($b_arm || $b_ppc || $b_mips || $b_sparc) && $chip && Cwd::abs_path($_) =~ /\b$chip\b/) { + $data1 = $vendor; + $data2 = $chip; } } # print "d1:$data1 v:$vendor d2:$data2 c:$chip bus_id: $bus_id\n"; @@ -13237,7 +13603,7 @@ sub advanced_data_sys { # no print out for wifi since it doesn't have duplex/speed data available # note that some cards show 'unknown' for state, so only testing explicitly # for 'down' string in that to skip showing speed/duplex - # /sys/class/net/$if/wireless : nont always there, but worth a try: wlan/wl/ww/wlp + # /sys/class/net/$if/wireless : not always there, but worth a try: wlan/wl/ww/wlp $b_wifi = 1 if !$b_wifi && ( -e "$_$if/wireless" || $if =~ /^(wl|ww)/); if (!$b_wifi && $state ne 'down' && $state ne 'no'){ # make sure the value is strictly numeric before appending Mbps @@ -13286,7 +13652,7 @@ sub advanced_data_bsd { else { @data = @$item; } - if ( $b_check || $working_if eq $if){ + if ($b_check || $working_if eq $if){ $if = $working_if if $b_check; # print "top: if: $if ifs: @ifs_found\n"; next if ($b_check && grep {/$if/} @ifs_found); @@ -13436,11 +13802,11 @@ sub wan_ip { # dig +short @ns1-1.akamaitech.net ANY whoami.akamai.net # this one can take forever, and sometimes requires explicit -4 or -6 # dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com - if (!$b_skip_dig && (my $program = main::check_program('dig') )){ + if (!$force{'no-dig'} && (my $program = main::check_program('dig') )){ $ip = (main::grabber("$program +short +time=1 +tries=1 \@ns1-1.akamaitech.net ANY whoami.akamai.net 2>/dev/null"))[0]; $b_dig = 1; } - if (!$ip && !$b_no_html_wan) { + if (!$ip && !$force{'no-html-wan'}) { # note: tests: akamai: 0.055 - 0.065 icanhazip.com: 0.177 0.164 # smxi: 0.525, so almost 10x slower. Dig is fast too # leaving smxi as last test because I know it will always be up. @@ -13484,46 +13850,6 @@ sub wan_ip { eval $end if $b_log; return @data; } - -### 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 - -# Wi-Fi.*Adapter Wireless.*Adapter Ethernet.*Adapter WLAN.*Adapter -# Network.*Adapter 802\.11 Atheros Atmel D-Link.*Adapter D-Link.*Wireless Linksys -# Netgea Ralink Realtek.*Network Realtek.*Wireless Realtek.*WLAN Belkin.*Wireless -# Belkin.*WLAN Belkin.*Network Actiontec.*Wireless Actiontec.*Network AirLink.*Wireless -# Asus.*Network Asus.*Wireless Buffalo.*Wireless Davicom DWA-.*RangeBooster DWA-.*Wireless -# ENUWI-.*Wireless LG.*Wi-Fi Rosewill.*Wireless RNX-.*Wireless Samsung.*LinkStick -# Samsung.*Wireless Sony.*Wireless TEW-.*Wireless TP-Link.*Wireless -# WG[0-9][0-9][0-9].*Wireless WNA[0-9][0-9][0-9] WNDA[0-9][0-9][0-9] -# Zonet.*ZEW.*Wireless -sub network_device { - eval $start if $b_log; - my ($device_string) = @_; - my ($b_network); - # belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda; - # Atmel makes other stuff. NOTE: exclude 'networks': IMC Networks - my @tests = qw(wifi Wi-Fi.*Adapter Ethernet \bLAN\b WLAN Network\b Networking\b - 802\.1[15] 802\.3 - Wireless.*Adapter 54\sMbps 100\/1000 NBase-T Mobile\sBroadband Atheros D-Link.*Adapter - Dell.*Wireless D-Link.*Wireless Linksys Netgea Ralink Realtek.*Network Realtek.*Wireless - Belkin.*Wireless Actiontec.*Wireless AirLink.*Wireless Asus.*Wireless - Buffalo.*Wireless Davicom DWA-.*RangeBooster DWA-.*Wireless - ENUWI-.*Wireless LG.*Wi-Fi Rosewill.*Wireless RNX-.*Wireless Samsung.*LinkStick - Samsung.*Wireless Sony.*Wireless TEW-.*Wireless TP-Link.*Wireless - WG[0-9][0-9][0-9].*Wireless WNA[0-9][0-9][0-9] WNDA[0-9][0-9][0-9] - Zonet.*ZEW.*Wireless 050d:935b 0bda:8189 0bda:8197 - ); - foreach (@tests){ - if ($device_string =~ /$_/i ){ - $b_network = 1; - last; - } - } - eval $end if $b_log; - return $b_network; -} sub check_bus_id { eval $start if $b_log; my ($path,$bus_id) = @_; @@ -13542,7 +13868,7 @@ sub check_bus_id { } sub check_wifi { my ($item) = @_; - my $b_wifi = ($item =~ /wireless|wifi|wi-fi|wlan|802\.11|centrino/i) ? 1 : 0; + my $b_wifi = ($item =~ /wireless|wi-?fi|wlan|802\.11|centrino/i) ? 1 : 0; return $b_wifi; } } @@ -13701,7 +14027,7 @@ sub optical_data_bsd { $devices{$working}->{'type'} = ($working =~ /^cd/) ? 'optical' : 'unknown'; } #print "$_\n"; - if ($bsd_type ne 'openbsd'){ + if ($bsd_type !~ /^(net|open)bsd$/){ if ($row[1] && $row[1] =~ /^<([^>]+)>/){ $devices{$working}->{'model'} = $1; $count = ($devices{$working}->{'model'} =~ tr/ //); @@ -13885,7 +14211,7 @@ sub get { eval $start if $b_log; my (@rows,$key1,$val1); my $num = 0; - partition_data() if !$b_partitions; + partition_data() if !$loaded{'partitions'}; if (!@partitions) { $key1 = 'Message'; #$val1 = ($bsd_type && $bsd_type eq 'darwin') ? @@ -13918,7 +14244,7 @@ sub partition_output { next if $row->{'swap-type'} && $row->{'swap-type'} ne 'partition'; if (!$row->{'hidden'}){ $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; - $used = ($row->{'used'}) ? main::get_size($row->{'used'},'string') : 'N/A'; + $used = main::get_size($row->{'used'},'string','N/A'); # used can be 0 $percent = (defined $row->{'percent-used'}) ? ' (' . $row->{'percent-used'} . '%)' : ''; } else { @@ -13938,7 +14264,7 @@ sub partition_output { if (($b_admin || $row->{'hidden'}) && $row->{'raw-size'} ){ # It's an error! permissions or missing tool $raw_size = ($row->{'raw-size'}) ? main::get_size($row->{'raw-size'},'string') : 'N/A'; - $rows[$j]->{main::key($num++,0,2,'raw size')} = $raw_size; + $rows[$j]->{main::key($num++,0,2,'raw-size')} = $raw_size; } if ($b_admin && $row->{'raw-available'} && $size ne 'N/A'){ $size .= ' (' . $row->{'raw-available'} . '%)'; @@ -13950,13 +14276,13 @@ sub partition_output { $rows[$j]->{main::key($num++,0,2,'swappiness')} = $row->{'swappiness'}; } if ($b_admin && $fs eq 'swap' && defined $row->{'cache-pressure'}){ - $rows[$j]->{main::key($num++,0,2,'cache pressure')} = $row->{'cache-pressure'}; + $rows[$j]->{main::key($num++,0,2,'cache-pressure')} = $row->{'cache-pressure'}; } if ($extra > 1 && $fs eq 'swap' && defined $row->{'priority'}){ $rows[$j]->{main::key($num++,0,2,'priority')} = $row->{'priority'}; } if ($b_admin && $row->{'block-size'}){ - $rows[$j]->{main::key($num++,0,2,'block size')} = $row->{'block-size'} . ' B';; + $rows[$j]->{main::key($num++,0,2,'block-size')} = $row->{'block-size'} . ' B';; #$rows[$j]->{main::key($num++,0,2,'physical')} = $row->{'block-size'} . ' B'; #$rows[$j]->{main::key($num++,0,2,'logical')} = $row->{'block-logical'} . ' B'; } @@ -13984,27 +14310,29 @@ sub partition_data { eval $start if $b_log; #return if $bsd_type && $bsd_type eq 'darwin'; # darwin has muated output, of course my (@data,@rows,@mount,@partitions_working,%part,@working); - my ($b_fake_map,$b_fs,$b_load,$b_space,$cols,$roots) = (0,1,0,0,6,0); - my ($back_size,$back_used) = (4,3); + my ($back_size,$back_used,$b_fs,$cols,$roots) = (4,3,1,6,0); + my ($b_fake_map,$b_load,$b_logical,$b_space,); my ($block_size,$blockdev,$dev_base,$dev_mapped,$dev_type,$fs,$id,$label, $maj_min,$percent_used,$raw_size,$replace,$size_available,$size,$test, $type,$uuid,$used); - $b_partitions = 1; + $loaded{'partitions'} = 1; if ($b_admin){ # for partition block size $blockdev = $alerts{'blockdev'}->{'path'} if $alerts{'blockdev'}->{'path'}; } # for raw partition sizes, maj_min - main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; - main::set_lsblk() if !$bsd_type && !$b_lsblk; - # set labels, uuid, gpart - set_label_uuid() if !$b_label_uuid; + main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; + main::set_lsblk() if !$bsd_type && !$loaded{'lsblk'}; + # set @labels, @uuid, %gpart + if (!$bsd_type){ + set_label_uuid() if !$loaded{'label-uuid'}; + } # most current OS support -T and -k, but -P means different things # in freebsd. However since most use is from linux, we make that default # android 7 no -T support if (!$bsd_type){ @partitions_working = main::grabber("df -P -T -k 2>/dev/null"); - main::set_mapper() if !$b_mapper; + main::set_mapper() if !$loaded{'mapper'}; } else { # this is missing the file system data @@ -14037,11 +14365,7 @@ sub partition_data { $roots++ if /\s\/$/; } @partitions_working = grep {!/^rootfs/} @partitions_working if $roots > 1; - # IMPORTANT: check the lsblk completer tool check_partition_data() for matching lsblck - # filters. - my $filters = 'aufs|cgroup.*|cgmfs|configfs|debugfs|\/dev|dev|\/dev\/loop[0-9]*|'; - $filters .= 'devfs|devtmpfs|fdescfs|iso9660|linprocfs|none|procfs|\/run(\/.*)?|'; - $filters .= 'run|shm|squashfs|sys|\/sys\/.*|sysfs|tmpfs|type|udev|unionfs|vartmp'; + my $filters = partition_filters(); #push @partitions_working, '//mafreebox.freebox.fr/Disque dur cifs 239216096 206434016 20607496 91% /freebox/Disque dur'; #push @partitions_working, '//mafreebox.freebox.fr/AllPG cifs 436616192 316339304 120276888 73% /freebox/AllPG'; foreach (@partitions_working){ @@ -14100,9 +14424,10 @@ sub partition_data { # this handles zfs type devices/partitions, which do not start with / but contain / # note: Main/jails/transmission_1 path can be > 1 deep # Main zfs 3678031340 8156 3678023184 0% /mnt/Main - if (!$dev_base && ($row[0] =~ /^([^\/]+\/)(.+)/ || ($row[0] =~ /^[^\/]+$/ && $row[1] =~ /^(btrfs|zfs)$/ ) ) ){ + if (!$dev_base && ($row[0] =~ /^([^\/]+\/)(.+)/ || + ($row[0] =~ /^[^\/]+$/ && $row[1] =~ /^(btrfs|hammer[2-9]?|zfs)$/ ) ) ){ $dev_base = $row[0]; - $dev_type = 'raid'; + $dev_type = 'logical'; } # this handles yet another fredforfaen special case where a mounted drive # has the search string in its name, includes / (| @@ -14131,7 +14456,7 @@ sub partition_data { if (%part && $part{'label'}) { $label = $part{'label'}; } - elsif ( @labels){ + elsif (@labels){ $label = get_label($row[0]); } } @@ -14146,14 +14471,15 @@ sub partition_data { } else { $fs = ($b_fs) ? $row[1]: get_mounts_fs($row[0],\@mount); - if (@gpart && ($show{'label'} || $show{'uuid'} ) ){ - my @extra = get_bsd_label_uuid("$dev_base"); - if (@extra){ - $label = $extra[0]; - $uuid = $extra[1]; - } + if ($bsd_type && ($b_admin || $show{'label'} || $show{'uuid'} ) ){ + my @temp = GpartData::get($dev_base); + $block_size = $temp[0] if $temp[0]; + $label = $temp[1] if $temp[1]; + $uuid =$temp[2] if $temp[2]; } } + # assuming that all null/nullfs are parts of a logical fs + $b_logical = 1 if $fs && $fs =~ /^(hammer|null|zfs)/; $id = join(' ', @row[$cols .. $#row]); $size = $row[$cols - $back_size]; if ($b_admin && -e "/sys/block/"){ @@ -14174,6 +14500,11 @@ sub partition_data { elsif ($dev_base =~ /^\/\/|:\//){ $dev_type = 'remote'; } + # a slice bsd system, zfs can't be detected this easily + elsif ($b_logical && $fs && $fs =~ /^(null(fs)?)$/){ + $dev_type = 'logical'; + $dev_base = $row[0] if !$dev_base; + } # an error has occurred almost for sure elsif (!$dev_base){ $dev_type = 'source'; @@ -14206,19 +14537,18 @@ sub partition_data { } @data = swap_data(); push(@partitions,@data); - # print Data::Dumper::Dumper \@partitions if $test[16]; + print Data::Dumper::Dumper \@partitions if $dbg[16]; if (!$bsd_type && @lsblk){ check_partition_data();# updates @partitions } main::log_data('dump','@partitions',\@partitions) if $b_log; - print Data::Dumper::Dumper \@partitions if $test[16]; + print Data::Dumper::Dumper \@partitions if $dbg[16]; eval $end if $b_log; } - sub swap_data { eval $start if $b_log; - return @swaps if $b_swaps; - $b_swaps = 1; + return @swaps if $loaded{'swaps'}; + $loaded{'swaps'} = 1; my (@data,@working); my ($cache_pressure,$dev_base,$dev_mapped,$dev_type,$label,$maj_min, $mount,$path,$pattern1,$pattern2,$percent_used,$priority,$size, @@ -14256,7 +14586,7 @@ sub swap_data { # data, it's the same exact output as swapon -s foreach (@working){ #next if ! /^\/dev/ || /^\/dev\/(ramzwap|zram)/; - next if /^(Device|Filename)/; + next if /^(Device|Filename|no swap)/; ($dev_base,$dev_mapped,$dev_type,$label,$maj_min,$mount,$priority, $swap_type,$uuid) = ('','','','','','',undef,'partition',''); @data = split(/\s+/, $_); @@ -14271,20 +14601,22 @@ sub swap_data { $swap_type = 'partition'; $dev_base = $data[0]; $dev_base =~ s|^/dev/||; - if (!$bsd_type && $dev_base =~ /^dm-/ && %dmmapper){ - $dev_mapped = $dmmapper{$dev_base}; + if (!$bsd_type){ + if ($dev_base =~ /^dm-/ && %dmmapper){ + $dev_mapped = $dmmapper{$dev_base}; + } + if ($show{'label'} && @labels){ + $label = get_label($data[0]); + } + if ($show{'uuid'} && @uuids){ + $uuid = get_uuid($data[0]); + } } - if ($show{'label'} && @labels){ - $label = get_label($data[0]); - } - if ($show{'uuid'} && @uuids){ - $uuid = get_uuid($data[0]); - } - if ($bsd_type && @gpart && ($show{'label'} || $show{'uuid'} ) ){ - my @extra = get_bsd_label_uuid("$dev_base"); - if (@extra){ - $label = $extra[0]; - $uuid = $extra[1]; + else { + if ($bsd_type && ($show{'label'} || $show{'uuid'} ) ){ + my @temp = GpartData::get($data[0]); + $label = $temp[1] if $temp[1]; + $uuid = $temp[2] if $temp[2]; } } $dev_type = 'dev'; @@ -14325,7 +14657,7 @@ sub swap_data { $s++; } main::log_data('dump','@swaps',\@swaps) if $b_log; - print Data::Dumper::Dumper \@swaps if $test[15];; + print Data::Dumper::Dumper \@swaps if $dbg[15];; eval $end if $b_log; return @swaps; } @@ -14347,94 +14679,16 @@ sub swap_advanced_data { eval $end if $b_log; return ($swappiness,$cache_pressure); } -sub get_mounts_fs { - eval $start if $b_log; - my ($item,$mount) = @_; - $item =~ s/map:\/(\S+)/map $1/ if $bsd_type && $bsd_type eq 'darwin'; - return 'N/A' if ! @$mount; - my ($fs) = (''); - # linux: /dev/sdb6 on /var/www/m type ext4 (rw,relatime,data=ordered) - # /dev/sda3 on /root.dev/ugw type ext3 (rw,relatime,errors=continue,user_xattr,acl,barrier=1,data=journal) - # bsd: /dev/ada0s1a on / (ufs, local, soft-updates) - foreach (@$mount){ - if ($bsd_type && $_ =~ /^$item\son.*\(([^,\s\)]+)[,\s]*.*\)/){ - $fs = $1; - last; - } - elsif (!$bsd_type && $_ =~ /^$item\son.*\stype\s([\S]+)\s\([^\)]+\)/){ - $fs = $1; - last; - } - } - eval $end if $b_log; - main::log_data('data',"fs: $fs") if $b_log; - return $fs; -} -# 1. Name: ada1p1 -# label: (null) -# label: ssd-root -# rawuuid: b710678b-f196-11e1-98fd-021fc614aca9 -sub get_bsd_label_uuid { - eval $start if $b_log; - my ($item) = @_; - my (@data,$b_found); - foreach (@gpart){ - my @working = split(/\s*:\s*/, $_); - if ($_ =~ /^[0-9]+\.\sName:/ && $working[1] eq $item){ - $b_found = 1; - } - elsif ($_ =~ /^[0-9]+\.\sName:/ && $working[1] ne $item){ - $b_found = 0; - } - if ($b_found){ - if ($working[0] eq 'label'){ - $data[0] = $working[1]; - $data[0] =~ s/\(|\)//g; # eg: label:(null) - we want to show null - } - if ($working[0] eq 'rawuuid'){ - $data[1] = $working[1]; - $data[0] =~ s/\(|\)//g; - } - } - } - main::log_data('dump','@data',\@data) if $b_log; - eval $end if $b_log; - return @data; -} -sub set_label_uuid { - eval $start if $b_log; - $b_label_uuid = 1; - if ( $show{'unmounted'} || $show{'label'} || $show{'uuid'} ){ - if (!$bsd_type){ - if (-d '/dev/disk/by-label'){ - @labels = main::globber('/dev/disk/by-label/*'); - } - if (-d '/dev/disk/by-uuid'){ - @uuids = main::globber('/dev/disk/by-uuid/*'); - } - } - else { - if ( my $path = main::check_program('gpart')){ - @gpart = main::grabber("$path list 2>/dev/null",'','strip'); - } - } - } - eval $end if $b_log; -} - # handle cases of hidden file systems sub check_partition_data { eval $start if $b_log; my ($b_found,$dev_mapped,$temp); - # NOTE: these filters must match the fs filters in sub partitiion_data!! - my $fs_filters = 'aufs|cgmfs|configfs|devfs|devtmpfs|'; - $fs_filters .= 'fdescfs|linprocfs|procfs|squashfs|swap|'; - $fs_filters .= 'sysfs|tmpfs|unionfs'; + my $filters = partition_filters(); foreach my $row (@lsblk){ $b_found = 0; $dev_mapped = ''; if (!$row->{'name'} || !$row->{'mount'} || !$row->{'type'} || - ($row->{'fs'} && $row->{'fs'} =~ /^($fs_filters)$/) || + ($row->{'fs'} && $row->{'fs'} =~ /^($filters)$/) || ($row->{'type'} =~ /^(disk|loop|rom)$/)){ next; } @@ -14475,6 +14729,59 @@ 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 +sub partition_filters { + my $filters = 'aufs|cgroup.*|cgmfs|configfs|debugfs|\/dev|dev|'; + $filters .= '\/dev\/loop[0-9]*|devfs|devtmpfs|fdescfs|iso9660|'; + $filters .= 'kernfs|linprocfs|linsysfs|none|overla(id|y)|procfs|ptyfs|'; + $filters .= '/run(\/.*)?|run|shm|squashfs|sys|\/sys\/.*|sysfs|'; + $filters .= 'tmpfs|type|udev|unionfs|vartmp'; + return $filters +} +sub get_mounts_fs { + eval $start if $b_log; + my ($item,$mount) = @_; + $item =~ s/map:\/(\S+)/map $1/ if $bsd_type && $bsd_type eq 'darwin'; + return 'N/A' if ! @$mount; + my ($fs) = (''); + # linux: /dev/sdb6 on /var/www/m type ext4 (rw,relatime,data=ordered) + # /dev/sda3 on /root.dev/ugw type ext3 (rw,relatime,errors=continue,user_xattr,acl,barrier=1,data=journal) + # bsd: /dev/ada0s1a on / (ufs, local, soft-updates) + # bsd 2: /dev/wd0g on /home type ffs (local, nodev, nosuid) + foreach (@$mount){ + if ($_ =~ /^$item\s+on.*?\s+type\s+([\S]+)\s+\([^\)]+\)/){ + $fs = $1; + last; + } + elsif ($_ =~ /^$item\s+on.*?\s+\(([^,\s\)]+?)[,\s]*.*\)/){ + $fs = $1; + last; + } + + } + eval $end if $b_log; + main::log_data('data',"fs: $fs") if $b_log; + return $fs; +} + +sub set_label_uuid { + eval $start if $b_log; + $loaded{'label-uuid'} = 1; + if ($show{'unmounted'} || $show{'label'} || $show{'swap'} || $show{'uuid'} ){ + if (-d '/dev/disk/by-label'){ + @labels = main::globber('/dev/disk/by-label/*'); + } + if (-d '/dev/disk/by-uuid'){ + @uuids = main::globber('/dev/disk/by-uuid/*'); + } + main::log_data('dump', '@lebels', \@labels) if $b_log; + main::log_data('dump', '@uuids', \@uuids) if $b_log; + } + eval $end if $b_log; +} + # args: 1: blockdev full path (part only); 2: block id; 3: size (part only) sub admin_data { eval $start if $b_log; @@ -14676,7 +14983,7 @@ sub mem_processes { } @rows = splice(@rows,0,$count); #print Data::Dumper::Dumper \@rows; - @processes = main::get_memory_data_full('process') if !$b_mem; + @processes = main::MemoryData::full('process') if !$loaded{'memory'}; $j = scalar @rows; my $throttled = throttled($ps_count,$count,$j); #$cpu_mem = ' - CPU: % used' if $extra > 0; @@ -14753,18 +15060,13 @@ sub throttled { ## RaidData { package RaidData; -# debugger switches -my $b_hw = 0; -my $b_lvm = 0; -my $b_md = 0; -my $b_zfs = 0; sub get { eval $start if $b_log; my (@hardware_raid,@rows,$key1,$val1); my $num = 0; - @hardware_raid = hw_data() if $b_hardware_raid || $b_hw; - raid_data() if !$b_raid; + @hardware_raid = hw_data() if $use{'hardware-raid'} || $fake{'raid-hw'}; + raid_data() if !$loaded{'raid'}; #print 'get: ', Data::Dumper::Dumper \@lvm_raid; #print 'get: ', Data::Dumper::Dumper \@md_raid; #print 'get: ', Data::Dumper::Dumper \@zfs_raid; @@ -14792,7 +15094,6 @@ sub get { @rows = ({main::key($num++,0,1,$key1) => $val1,}); } eval $end if $b_log; - ($b_md,$b_zfs) = undef; return @rows; } sub hw_output { @@ -14811,22 +15112,23 @@ sub hw_output { $rows[$j]->{main::key($num++,0,2,'vendor')} = $row->{'vendor'} if $row->{'vendor'}; $rows[$j]->{main::key($num++,1,2,'driver')} = $driver; if ($extra > 0){ - my $driver_version = ($row->{'driver-version'}) ? $row->{'driver-version'}: 'N/A' ; - $rows[$j]->{main::key($num++,0,3,'v')} = $driver_version; + $row->{'driver-version'} ||= 'N/A'; + $rows[$j]->{main::key($num++,0,3,'v')} = $row->{'driver-version'}; if ($extra > 2){ my $port= ($row->{'port'}) ? $row->{'port'}: 'N/A' ; $rows[$j]->{main::key($num++,0,2,'port')} = $port; } - my $bus_id = (defined $row->{'bus-id'} && defined $row->{'sub-id'}) ? "$row->{'bus-id'}.$row->{'sub-id'}": 'N/A' ; - $rows[$j]->{main::key($num++,0,2,'bus ID')} = $bus_id; + my $bus_id = (defined $row->{'bus-id'} && defined $row->{'sub-id'}) ? "$row->{'bus-id'}.$row->{'sub-id'}": 'N/A' ; + $rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id; } if ($extra > 1){ - my $chip_id = (defined $row->{'vendor-id'} && defined $row->{'chip-id'}) ? "$row->{'vendor-id'}.$row->{'chip-id'}": 'N/A' ; - $rows[$j]->{main::key($num++,0,2,'chip ID')} = $chip_id; + my $chip_id = (defined $row->{'vendor-id'} && defined $row->{'chip-id'}) ? "$row->{'vendor-id'}.$row->{'chip-id'}": 'N/A' ; + $rows[$j]->{main::key($num++,0,2,'chip-ID')} = $chip_id; } if ($extra > 2){ - my $rev= (defined $row->{'rev'} && $row->{'rev'}) ? $row->{'rev'}: 'N/A' ; - $rows[$j]->{main::key($num++,0,2,'rev')} = $rev; + $row->{'rev'} = 'N/A' if !defined $row->{'rev'}; # could be 0 + $rows[$j]->{main::key($num++,0,2,'rev')} = $row->{'rev'}; + $rows[$j]->{main::key($num++,0,2,'class-ID')} = $row->{'class-id'} if $row->{'class-id'}; } } eval $end if $b_log; @@ -14911,7 +15213,7 @@ sub md_output { $j = scalar @rows; next if !%$row; $num = 1; - $level = (defined $row->{'level'}) ? $row->{'level'} : 'no-raid'; + $level = (defined $row->{'level'}) ? $row->{'level'} : 'linear'; push(@rows, { main::key($num++,1,1,'Device') => $row->{'id'}, }); @@ -14947,13 +15249,13 @@ sub md_output { $blocks = ($row->{'blocks'}) ? $row->{'blocks'} : 'N/A'; $rows[$j]->{main::key($num++,0,3,'blocks')} = $blocks; $chunk = ($row->{'chunk-size'}) ? $row->{'chunk-size'} : 'N/A'; - $rows[$j]->{main::key($num++,0,3,'chunk size')} = $chunk; + $rows[$j]->{main::key($num++,0,3,'chunk-size')} = $chunk; if ($extra > 1){ if ($row->{'bitmap'}){ $rows[$j]->{main::key($num++,0,3,'bitmap')} = $row->{'bitmap'}; } if ($row->{'super-block'}){ - $rows[$j]->{main::key($num++,0,3,'super blocks')} = $row->{'super-block'}; + $rows[$j]->{main::key($num++,0,3,'super-blocks')} = $row->{'super-block'}; } if ($row->{'algorithm'}){ $rows[$j]->{main::key($num++,0,3,'algorithm')} = $row->{'algorithm'}; @@ -14997,7 +15299,7 @@ sub md_output { } $rows[$j]->{main::key($num++,1,2,'Recovering')} = $percent; my $finish = ($row->{'recovery-finish'})?$row->{'recovery-finish'} : 'N/A'; - $rows[$j]->{main::key($num++,0,3,'time remaining')} = $finish; + $rows[$j]->{main::key($num++,0,3,'time-remaining')} = $finish; if ($extra > 0){ if ($row->{'sectors-recovered'}){ $rows[$j]->{main::key($num++,0,3,'sectors')} = $row->{'sectors-recovered'}; @@ -15040,7 +15342,7 @@ sub zfs_output { @arrays_holder = @arrays; my $count = scalar @arrays; if (!defined $arrays[0]->{'level'} ){ - $level = 'no-raid'; + $level = 'linear'; $rows[$j]->{main::key($num++,0,2,'level')} = $level; } elsif ($count < 2 && $arrays[0]->{'level'}){ @@ -15067,7 +15369,7 @@ sub zfs_output { $num = 1; $size = ($row2->{'size'}) ? main::get_size($row2->{'size'},'string') : 'N/A'; $available = ($row2->{'free'}) ? main::get_size($row2->{'free'},'string') : 'N/A'; - $level = (defined $row2->{'level'}) ? $row2->{'level'}: 'no-raid'; + $level = (defined $row2->{'level'}) ? $row2->{'level'}: 'linear'; $status = ($row2->{'status'}) ? $row2->{'status'}: 'N/A'; push(@rows, { main::key($num++,1,2,'Array') => $level, @@ -15163,7 +15465,7 @@ sub components_output { $$rows_ref[$$j_ref]{main::key($$num_ref++,0,$l3,'maj-min')} = $device->[$f2]; } if ($b_admin && $device->[$f1]){ - my $size = ($device->[$f1]) ? main::get_size($device->[$f1],'string') : 'N/A'; + my $size = main::get_size($device->[$f1],'string'); $$rows_ref[$$j_ref]->{main::key($$num_ref++,0,$l3,'size')} = $size; } if ($b_admin && $device->[$f3]){ @@ -15181,19 +15483,19 @@ sub components_output { sub raid_data { eval $start if $b_log; - main::set_lsblk() if !$bsd_type && !$b_lsblk; - main::set_mapper() if !$bsd_type && !$b_mapper; - main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; + main::set_lsblk() if !$bsd_type && !$loaded{'lsblk'}; + main::set_mapper() if !$bsd_type && !$loaded{'mapper'}; + main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; my (@data); - $b_raid = 1; - if (($b_fake_raid && $b_lvm) || + $loaded{'raid'} = 1; + if ($fake{'raid-lvm'} || ($alerts{'lvs'}->{'action'} && $alerts{'lvs'}->{'action'} eq 'use')){ @lvm_raid = lvm_data(); } - if (($b_fake_raid && $b_md) || (my $file = main::system_files('mdstat') )){ + if ($fake{'raid-md'} || (my $file = main::system_files('mdstat') )){ @md_raid = md_data($file); } - if (($b_fake_raid && $b_zfs) || (my $path = main::check_program('zpool') )){ + if ($fake{'raid-zfs'} || (my $path = main::check_program('zpool') )){ @zfs_raid = zfs_data($path); } eval $end if $b_log; @@ -15216,10 +15518,11 @@ sub hw_data { $driver = ($working->[9]) ? lc($working->[9]): ''; $driver =~ s/-/_/g if $driver; my $driver_version = ($driver) ? main::get_module_version($driver): ''; - if ($extra > 2 && $b_pci_tool && $working->[11]){ + if ($extra > 2 && $use{'pci-tool'} && $working->[11]){ $vendor = main::get_pci_vendor($working->[4],$working->[11]); } push(@hardware_raid, { + 'class-id' => $working->[1], 'bus-id' => $working->[2], 'chip-id' => $working->[6], 'device' => $working->[4], @@ -15239,11 +15542,11 @@ sub hw_data { } sub lvm_data { eval $start if $b_log; - LogicalData::lvm_data() if !$b_lvm_data; + LogicalData::lvm_data() if !$loaded{'lvm-data'}; return if !@lvm; my (@lvraid,$maj_min,$vg_used,@working); foreach my $item (@lvm){ - next if $item->{'segtype'} !~ /^raid/; + next if $item->{'segtype'} && $item->{'segtype'} !~ /^raid/; my (@components,$dev,$maj_min,$vg_used); #print Data::Dumper::Dumper $item; if ($item->{'lv_kernel_major'} . ':' . $item->{'lv_kernel_minor'}){ @@ -15300,7 +15603,7 @@ sub md_data { eval $start if $b_log; my ($mdstat) = @_; my $j = 0; - if ($b_fake_raid) { + if ($fake{'raid-md'}) { #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-4-device-1.txt"; #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-rebuild-1.txt"; #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-mirror-fserver2-1.txt"; @@ -15523,7 +15826,7 @@ sub zfs_data { my ($allocated,$free,$size,$size_holder,$size_logical,$status,@working); my $b_v = 1; my ($i,$j,$k) = (0,0,0); - if ($b_fake_raid){ + if ($fake{'raid-zfs'}){ #my $file; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-1-mirror-main-solestar.txt"; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-2-mirror-main-solestar.txt"; @@ -15534,7 +15837,6 @@ sub zfs_data { else { @working = main::grabber("$zpool list -v 2>/dev/null"); } - DiskData::set_glabel() if $bsd_type && !$b_glabel; # bsd sed does not support inserting a true \n so use this trick # some zfs does not have -v if (!@working){ @@ -15608,8 +15910,8 @@ sub zfs_data { my $working = ($1) ? $1 : ''; # note: the negative case can never happen my $state = ($3) ? $3 : ''; my ($maj_min,$part_size); - if ($working =~ /[\S]+\// && @glabel){ - $working = DiskData::match_glabel($working); + if ($bsd_type && $working =~ /[\S]+\//){ + $working = GlabelData::get($working); } # kind of a hack, things like cache may not show size/free # data since they have no array row, but they might show it in @@ -15629,7 +15931,7 @@ sub zfs_data { $free = ($row[4])? main::translate_size($row[4]): ''; $zfs[$j]->{'arrays'}[$k]{'free'} = $free; } - if ((!$maj_min || !$part_size) && @lsblk){ + if ((!$maj_min || !$part_size) && @proc_partitions){ my @part = main::get_proc_partition($working); if (@part){ $maj_min = $part[0] . ':' . $part[1]; @@ -15641,6 +15943,10 @@ sub zfs_data { $maj_min = $data{'maj-min'}; $part_size = $data{'size'}; } + if (!$part_size && $bsd_type){ + my @temp = GpartData::get($working); + $part_size = $temp[3] if $temp[3]; + } $raw_logical[1] += $part_size if $part_size; $zfs[$j]->{'arrays'}[$k]{'components'}[$i] = [$working,$part_size,$maj_min,$state]; $i++; @@ -15669,7 +15975,7 @@ sub zfs_status { foreach my $row (@$zfs){ $i = 0; $k = 0; - if ($b_fake_raid){ + if ($fake{'raid-zfs'}){ my $file; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-1-mirror-main-solestar.txt"; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-2-mirror-main-solestar.txt"; @@ -15737,10 +16043,10 @@ package RamData; sub get { my (@data,@rows,$key1,@ram,$val1); my $num = 0; - @rows = main::get_memory_data_full('ram') if !$b_mem; - if ( !$b_fake_dmidecode && $alerts{'dmidecode'}->{'action'} ne 'use'){ + @rows = MemoryData::full('ram') if !$loaded{'memory'}; + if ( !$fake{'dmidecode'} && $alerts{'dmidecode'}->{'action'} ne 'use'){ $key1 = $alerts{'dmidecode'}->{'action'}; - $val1 = $alerts{'dmidecode'}->{$key1}; + $val1 = $alerts{'dmidecode'}->{'message'}; push(@rows, { main::key($num++,1,1,'RAM Report') => '', main::key($num++,0,2,$key1) => $val1, @@ -15794,7 +16100,7 @@ sub ram_output { $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 ) ) ){ - $rows[$j]->{main::key($num++,1,2,'max module size')} = process_size($item->{'max-module-size'}); + $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'}; } @@ -15862,7 +16168,7 @@ sub ram_output { } if ($extra > 2 ){ $mod->{'data-width'} ||= 'N/A'; - $rows[$j]->{main::key($num++,0,3,'bus width')} = $mod->{'data-width'}; + $rows[$j]->{main::key($num++,0,3,'bus-width')} = $mod->{'data-width'}; $mod->{'total-width'} ||= 'N/A'; $rows[$j]->{main::key($num++,0,3,'total')} = $mod->{'total-width'}; } @@ -16040,7 +16346,7 @@ sub dmidecode_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]B/ ) { + if ( $temp[1] =~ /^[0-9]+\s*[KkMTPG]i?B/ ) { $derived_module_size = calculate_size($temp[1],$derived_module_size); $working_size = calculate_size($temp[1],0); $device_size = $working_size; @@ -16318,12 +16624,12 @@ sub process_speed { my ($speed,$device_type,$check) = @_; my $speed_note; $speed = main::dmi_cleaner($speed) if $speed; - if ($device_type && $device_type =~ /ddr/i && $speed && $speed =~ /^([0-9]+) 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 - if ($speed && $speed =~ /^([0-9]+) M/){ + if ($speed && $speed =~ /^([0-9]+)\s*M/){ $speed_note = $check if $1 < 50 || $1 > 20000 ; } return ($speed,$speed_note); @@ -16338,57 +16644,37 @@ sub process_size { #return $size if $size =~ /\D/; return $size if !main::is_numeric($size); #print "size: $size\n"; - if ( $size < 1024 ){ - $unit='MiB'; - } - elsif ( $size < 1024000 ){ - $size = $size / 1024; - $unit='GiB'; - $b_trim = 1; - } - elsif ( $size < 1024000000 ){ - $size = $size / 1024000; - $unit='TiB'; - $b_trim = 1; - } # we only want a max 2 decimal places, and only when it's - # a unit > MB + # a unit > 1 GiB + $b_trim = 1 if $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 sub calculate_size { my ($data, $size) = @_; # technically k is KiB, K is KB but can't trust that - if ( $data =~ /^[0-9]+\s*[kKGMTP]B/) { - if ( $data =~ /([0-9]+)\s*GB/ ) { - $data = $1 * 1024; + if ( $data =~ /^([0-9]+\s*[kKGMTP])i?B/) { + my $working = $1; + # 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 + $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 ) { + $size = $working_size; } - elsif ( $data =~ /([0-9]+)\s*MB/ ) { - $data = $1; - } - elsif ( $data =~ /([0-9]+)\s*TB/ ) { - $data = $1 * 1024 * 1000; - } - elsif ( $data =~ /([0-9]+)\s*PB/ ) { - $data = $1 * 1024 * 1000 * 1000; - } - elsif ( $data =~ /([0-9]+)\s*[kK]B/ ) { - $data = $1/1024; - #print "d3:$data\n"; - } - #print "d1a: $data s1: $size\n"; - if (main::is_numeric($data) && $data > $size ) { - #if ($data =~ /^[0-9][0-9]+$/ && $data > $size ) { - $size = $data; - } - #print "d1b: $data s1: $size\n"; + #print "ws-b: $working_size s-2: $size\n"; } else { $size = 0; } - #print "d2: $data s2: $size\n"; + #print "d-2: $data s-3: $size\n"; return $size; } } @@ -16404,13 +16690,12 @@ sub get { eval $start if $b_log; ($debugger_dir) = @_; my (@data,@rows,@rows_p,@rows_r); - if ($extra > 0 && !$b_pkg){ + if ($extra > 0 && !$loaded{'packages'}){ my %packages = PackageData::get('main',\$num); my @data; for (keys %packages){ $rows_p[0]->{$_} = $packages{$_}; } - $b_pkg = 1; } $num = 0; if ($bsd_type){ @@ -16446,11 +16731,13 @@ sub get_repos_linux { $apt = $apt_termux if -e $apt_termux; # for android termux my $cards = '/etc/cards.conf'; my $eopkg_dir = '/var/lib/eopkg/'; + 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 $scratchpkg = '/etc/scratchpkg.repo'; my $slackpkg = '/etc/slackpkg/mirrors'; my $slackpkg_plus = '/etc/slackpkg/slackpkgplus.conf'; my $slapt_get = '/etc/slapt-get/'; @@ -16551,7 +16838,7 @@ sub get_repos_linux { } if (@apt_urls){ $key = repo_data('active','apt'); - @apt_urls = url_cleaner(\@apt_urls); + url_cleaner(\@apt_urls); } else { $key = repo_data('missing','apt'); @@ -16645,14 +16932,14 @@ sub get_repos_linux { $key = repo_data('missing','slackpkg+'); } else { - @content = url_cleaner(\@content); + url_cleaner(\@content); $key = repo_data('active','slackpkg+'); } @data = ( {main::key($num++,1,1,$key) => $slackpkg_plus}, [@content], ); - @data = url_cleaner(\@data); + url_cleaner(\@data); push(@rows,@data); @content = (); } @@ -16719,7 +17006,7 @@ sub get_repos_linux { $key = repo_data('missing',$repo); } else { - @content = url_cleaner(\@content); + url_cleaner(\@content); $key = repo_data('active',$repo); } push(@rows, @@ -16782,7 +17069,7 @@ sub get_repos_linux { $key = repo_data('missing','portage'); } else { - @content = url_cleaner(\@content); + url_cleaner(\@content); $key = repo_data('active','portage'); } push(@rows, @@ -16798,6 +17085,11 @@ sub get_repos_linux { @data = repo_builder($apk,'apk','^\s*[^#]+'); push(@rows,@data); } + # Venom + if (-f $scratchpkg){ + @data = repo_builder($scratchpkg,'scratchpkg','^[[:space:]]*[^#]+'); + push(@rows,@data); + } # cards/nutyx if (-f $cards){ @data3 = main::reader($cards,'clean'); @@ -16812,7 +17104,7 @@ sub get_repos_linux { $key = repo_data('missing','cards'); } else { - @content = url_cleaner(\@content); + url_cleaner(\@content); $key = repo_data('active','cards'); } push(@rows, @@ -16863,7 +17155,7 @@ sub get_repos_linux { if (/(.+)\s([\S]+:\/\/.+)/){ # pack the repo url push(@content, $1); - @content = url_cleaner(\@content); + url_cleaner(\@content); # get the repo $repo = $2; push(@rows, @@ -16909,7 +17201,7 @@ sub get_repos_linux { $repo = ($2 =~ /^activ/i) ? $repo : ''; } if ($repo && @content){ - @content = url_cleaner(\@content); + url_cleaner(\@content); $key = repo_data('active',$which); push(@rows, {main::key($num++,1,1,$key) => $repo}, @@ -16921,7 +17213,7 @@ sub get_repos_linux { } # last one if present if ($repo && @content){ - @content = url_cleaner(\@content); + url_cleaner(\@content); $key = repo_data('active',$which); push(@rows, {main::key($num++,1,1,$key) => $repo}, @@ -16929,6 +17221,24 @@ sub get_repos_linux { ); } } + 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; + if (!@content){ + $key = repo_data('missing','nix'); + } + else { + url_cleaner(\@content); + $key = repo_data('active','nix'); + } + my $user = ($ENV{'USER'}) ? $ENV{'USER'}: 'N/A'; + push(@rows, + {main::key($num++,1,1,$key) => $user}, + [@content], + ); + @content = (); + + } # print Dumper \@rows; eval $end if $b_log; return @rows; @@ -16940,11 +17250,14 @@ sub get_repos_bsd { my $bsd_pkg = '/usr/local/etc/pkg/repos/'; my $freebsd = '/etc/freebsd-update.conf'; my $freebsd_pkg = '/etc/pkg/FreeBSD.conf'; + my $ghostbsd_pkg = '/etc/pkg/GhostBSD.conf'; + my $hardenedbsd_pkg = '/etc/pkg/HardenedBSD.conf'; my $netbsd = '/usr/pkg/etc/pkgin/repositories.conf'; my $openbsd = '/etc/pkg.conf'; my $openbsd2 = '/etc/installurl'; my $portsnap = '/etc/portsnap.conf'; - if ( -f $portsnap || -f $freebsd || -d $bsd_pkg){ + if ( -f $portsnap || -f $freebsd || -d $bsd_pkg || + -f $ghostbsd_pkg || -f $hardenedbsd_pkg){ if ( -f $portsnap ) { @data = repo_builder($portsnap,'portsnap','^\s*SERVERNAME','\s*=\s*',1); push(@rows,@data); @@ -16953,13 +17266,11 @@ sub get_repos_bsd { @data = repo_builder($freebsd,'freebsd','^\s*ServerName','\s+',1); push(@rows,@data); } -# if ( -f $freebsd_pkg ){ -# @data = repo_builder($freebsd_pkg,'freebsd-pkg','^\s*url',':\s+',1); -# push(@rows,@data); -# } - if ( -d $bsd_pkg || -f $freebsd_pkg){ + if ( -d $bsd_pkg || -f $freebsd_pkg || -f $ghostbsd_pkg || -f $hardenedbsd_pkg){ @files = main::globber('/usr/local/etc/pkg/repos/*.conf'); push(@files, $freebsd_pkg) if -f $freebsd_pkg; + push(@files, $ghostbsd_pkg) if -f $ghostbsd_pkg; + push(@files, $hardenedbsd_pkg) if -f $hardenedbsd_pkg; if (@files){ my ($url); foreach (@files){ @@ -16988,11 +17299,11 @@ sub get_repos_bsd { } } } - if (! @data3){ + if (!@data3){ $key = repo_data('missing','bsd-package'); } else { - @data3 = url_cleaner(\@data3); + url_cleaner(\@data3); $key = repo_data('active','bsd-package'); } push(@rows, @@ -17050,8 +17361,8 @@ sub repo_data { 'apk-missing' => 'No active APK repos in', 'apt-active' => 'Active apt repos in', 'apt-missing' => 'No active apt repos in', - 'bsd-files-missing' => 'No BSD pkg server files found', - 'bsd-package-active' => 'BSD enabled pkg servers in', + 'bsd-files-missing' => 'No pkg server files found', + 'bsd-package-active' => 'Enabled pkg servers in', 'bsd-package-missing' => 'No enabled BSD pkg servers in', 'cards-active' => 'Active CARDS collections in', 'cards-missing' => 'No active CARDS collections in', @@ -17066,6 +17377,8 @@ sub repo_data { 'netbsd-active' => 'NetBSD pkg servers', 'netbsd-files-missing' => 'No NetBSD pkg server files found', 'netbsd-missing' => 'No NetBSD pkg servers in', + 'nix-active' => 'Active nix channels for user', + 'nix-missing' => 'No nix channels found for user', 'openbsd-active' => 'OpenBSD pkg mirror', 'openbsd-files-missing' => 'No OpenBSD pkg mirror files found', 'openbsd-missing' => 'No OpenBSD pkg mirrors in', @@ -17077,8 +17390,10 @@ sub repo_data { 'pisi-missing' => 'No active pisi repos found', 'portage-active' => 'Enabled portage sources in', 'portage-missing' => 'No enabled portage sources in', - 'portsnap-active' => 'BSD ports server', + 'portsnap-active' => 'Ports server', 'portsnap-missing' => 'No ports servers in', + 'scratchpkg-active' => 'scratchpkg repos in', + 'scratchpkg-missing' => 'No active scratchpkg repos in', 'slackpkg-active' => 'slackpkg repos in', 'slackpkg-missing' => 'No active slackpkg repos in', 'slackpkg+-active' => 'slackpkg+ repos in', @@ -17105,7 +17420,7 @@ sub repo_builder { if (-r $file){ @content = main::reader($file); @content = grep {/$search/i && !/^\s*$/} @content if @content; - @content = data_cleaner(\@content) if @content; + data_cleaner(\@content) if @content; } if ($split && @content){ @content = map { @@ -17118,7 +17433,7 @@ sub repo_builder { } else { $key = repo_data('active',$type); - @content = url_cleaner(\@content); + url_cleaner(\@content); } @data = ( {main::key($num++,1,1,$key) => $file}, @@ -17128,16 +17443,12 @@ sub repo_builder { return @data; } sub data_cleaner { - my ($content) = @_; # basics: trim white space, get rid of double spaces - @$content = map { $_ =~ s/^\s+|\s+$//g; $_ =~ s/\s\s+/ /g; $_} @$content; - return @$content; + @{$_[0]} = map {$_ =~ s/^\s+|\s+$//g; $_ =~ s/\s\s+/ /g; $_} @{$_[0]}; } # clean if irc sub url_cleaner { - my ($content) = @_; - @$content = map { $_ =~ s/:\//: \//; $_} @$content if $b_irc; - return @$content; + @{$_[0]} = map {$_ =~ s/:\//: \//; $_} @{$_[0]} if $b_irc; } sub file_path { my ($filename,$dir) = @_; @@ -17153,7 +17464,6 @@ sub file_path { ## SensorData { package SensorData; -my ($b_ipmi) = (0); sub get { eval $start if $b_log; my ($key1,$program,$val1,@data,@rows,%sensors); @@ -17161,11 +17471,10 @@ sub get { my $source = 'sensors'; # we're allowing 1 or 2 ipmi tools, first the gnu one, then the # almost certain to be present in BSDs - if ( $b_ipmi || - ( main::globber('/dev/ipmi**') && - ( ( $program = main::check_program('ipmi-sensors') ) || - ( $program = main::check_program('ipmitool') ) ) ) ){ - if ($b_ipmi || $b_root){ + if ($fake{'ipmi'} || (main::globber('/dev/ipmi**') && + ( ($program = main::check_program('ipmi-sensors')) || + ($program = main::check_program('ipmitool')) ) ) ){ + if ($fake{'ipmi'} || $b_root){ %sensors = ipmi_data($program); @data = sensors_output('ipmi',\%sensors); if (!@data) { @@ -17184,10 +17493,10 @@ sub get { push(@rows,@data); } } - if ( $alerts{'sensors'}->{'action'} ne 'use'){ + if (!$fake{'sensors'} && $alerts{'sensors'}->{'action'} ne 'use'){ #print "here 1\n"; $key1 = $alerts{'sensors'}->{'action'}; - $val1 = $alerts{'sensors'}->{$key1}; + $val1 = $alerts{'sensors'}->{'message'}; $key1 = ucfirst($key1); @data = ({main::key($num++,0,1,$key1) => $val1,}); push(@rows,@data); @@ -17367,26 +17676,34 @@ sub ipmi_data { my ($program) = @_; my ($b_cpu_0,$cmd,$file,@data,$fan_working,%sensors,@row,$sys_fan_nu, $temp_working,$working_unit); - $program ||= 'ipmi-sensors'; # only for debugging, will always exist if reaches here my ($b_ipmitool,$i_key,$i_value,$i_unit); - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-archerseven-1.txt";$program='ipmitool'; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-crazy-epyc-1.txt";$program='ipmitool'; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-RK016013.txt";$program='ipmitool'; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-crazy-epyc-1.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-lathander.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-zwerg.txt"; - #@data = main::reader($file); - if ($program =~ /ipmi-sensors$/){ - $cmd = $program; - ($b_ipmitool,$i_key,$i_value,$i_unit) = (0,1,3,4); + if ($fake{'ipmi'}){ + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-archerseven-1.txt";$program='ipmitool'; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-crazy-epyc-1.txt";$program='ipmitool'; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-RK016013.txt";$program='ipmitool'; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-freebsd-offsite-backup.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-crazy-epyc-1.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-lathander.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-zwerg.txt"; + #@data = main::reader($file); + #($b_ipmitool,$i_key,$i_value,$i_unit) = (0,1,3,4); # ipmi-sensors + #($b_ipmitool,$i_key,$i_value,$i_unit) = (1,0,1,2); # ipmitool sensors } else { - $cmd = "$program sensors"; - ($b_ipmitool,$i_key,$i_value,$i_unit) = (1,0,1,2); + if ($program =~ /ipmi-sensors$/){ + $cmd = $program; + ($b_ipmitool,$i_key,$i_value,$i_unit) = (0,1,3,4); + } + else { # ipmitool + $cmd = "$program sensors"; + ($b_ipmitool,$i_key,$i_value,$i_unit) = (1,0,1,2); + } + @data = main::grabber("$cmd 2>/dev/null"); } - @data = main::grabber("$cmd 2>/dev/null"); # print join("\n", @data), "\n"; - return if ! @data; + # shouldn't need to log, but saw a case with debugger ipmi data, but none here apparently + main::log_data('dump','ipmi @data',\@data) if $b_log; + return if !@data; foreach (@data){ next if /^\s*$/; # print "$_\n"; @@ -17394,13 +17711,13 @@ sub ipmi_data { #print "$row[$i_value]\n"; next if !main::is_numeric($row[$i_value]); # print "$row[$i_key] - $row[$i_value]\n"; - if (!$sensors{'mobo-temp'} && $row[$i_key] =~ /^(MB_TEMP[0-9]|System[\s_]Temp|System[\s_]?Board)$/i){ + if (!$sensors{'mobo-temp'} && $row[$i_key] =~ /^(MB_TEMP[0-9]|System[\s_]Temp|System[\s_]?Board([\s_]Temp)?)$/i){ $sensors{'mobo-temp'} = int($row[$i_value]); $working_unit = $row[$i_unit]; $working_unit =~ s/degrees\s// if $b_ipmitool; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; } - elsif ($row[$i_key] =~ /^(Ambient)$/i){ + elsif ($row[$i_key] =~ /^(Ambient)([\s_]Temp)?$/i){ $sensors{'ambient-temp'} = int($row[$i_value]); $working_unit = $row[$i_unit]; $working_unit =~ s/degrees\s// if $b_ipmitool; @@ -17514,16 +17831,16 @@ sub ipmi_data { elsif (!$sensors{'volts-soc-p1'} && $row[$i_key] =~ /^(P1_SOC_RUN$)/i) { $sensors{'volts-soc-p1'} = $row[$i_value]; } - elsif (! $sensors{'volts-soc-p2'} && $row[$i_key] =~ /^(P2_SOC_RUN$)/i) { + elsif (!$sensors{'volts-soc-p2'} && $row[$i_key] =~ /^(P2_SOC_RUN$)/i) { $sensors{'volts-soc-p2'} = $row[$i_value]; } } } - # print Data::Dumper::Dumper \%sensors; + print Data::Dumper::Dumper \%sensors if $dbg[31]; %sensors = process_data(%sensors) if %sensors; main::log_data('dump','ipmi: %sensors',\%sensors) if $b_log; eval $end if $b_log; - # print Data::Dumper::Dumper \%sensors; + print Data::Dumper::Dumper \%sensors if $dbg[31]; return %sensors; } sub lm_sensors_data { @@ -17531,7 +17848,7 @@ sub lm_sensors_data { my (%sensors); my ($sys_fan_nu) = (0); my ($adapter,$fan_working,$temp_working,$working_unit) = ('','','','',''); - process_lm_sensors() if !$b_sensors; + process_lm_sensors() if !$loaded{'lm-sensors'}; foreach $adapter (keys %{$sensors_raw{'main'}}){ next if !$adapter || ref $sensors_raw{'main'}->{$adapter} ne 'ARRAY'; # not sure why hwmon is excluded, forgot to add info in comments @@ -17696,10 +18013,10 @@ sub lm_sensors_data { } } } - # print Data::Dumper::Dumper \%sensors; + print Data::Dumper::Dumper \%sensors if $dbg[31]; %sensors = process_data(%sensors) if %sensors; main::log_data('dump','lm-sensors: %sensors',\%sensors) if $b_log; - # print Data::Dumper::Dumper \%sensors; + print Data::Dumper::Dumper \%sensors if $dbg[31]; eval $end if $b_log; return %sensors; } @@ -17707,7 +18024,7 @@ sub process_lm_sensors { eval $start if $b_log; my (@data,@sensors_data,@values); my ($adapter,$holder,$type) = ('','',''); - if ($b_fake_sensors){ + if ($fake{'sensors'}){ #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/amdgpu-w-fan-speed-stretch-k10.txt"; #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/peci-tin-geggo.txt"; #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-w-other-biker.txt"; @@ -17766,8 +18083,8 @@ sub process_lm_sensors { $holder = $_; } } - $b_sensors = 1; - if ($test[18]){ + $loaded{'lm-sensors'} = 1; + if ($dbg[18]){ print 'lm sensors: ' , Data::Dumper::Dumper \%sensors_raw; } if ($b_log){ @@ -18056,7 +18373,7 @@ sub process_data { } sub gpu_data { eval $start if $b_log; - return @gpudata if $b_gpudata; + return @gpudata if $loaded{'gpu-data'}; my ($cmd,@data,@data2,$path,@screens,$temp); my ($j) = (0); if ($path = main::check_program('nvidia-settings')){ @@ -18176,8 +18493,8 @@ sub gpu_data { } main::log_data('dump','sensors output: video: @gpudata',\@gpudata); # we'll probably use this data elsewhere so make it a one time call - $b_gpudata = 1; - print 'gpudata: ', Data::Dumper::Dumper \@gpudata if $test[18]; + $loaded{'gpu-data'} = 1; + print 'gpudata: ', Data::Dumper::Dumper \@gpudata if $dbg[18]; eval $end if $b_log; return @gpudata; } @@ -18191,17 +18508,18 @@ sub get { eval $start if $b_log; my (@rows,$key1,$val1); my $num = 0; - if ($b_fake_dmidecode || ( $alerts{'dmidecode'}->{'action'} eq 'use' && (!$b_arm || $b_slot_tool ) )){ + if ($fake{'dmidecode'} || ( $alerts{'dmidecode'}->{'action'} eq 'use' && + (!$b_arm || $use{'slot-tool'} ) )){ @rows = slot_output(); } - elsif ($b_arm && !$b_slot_tool){ + elsif ($b_arm && !$use{'slot-tool'}){ $key1 = 'ARM'; $val1 = main::row_defaults('arm-pci',''); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } elsif ( $alerts{'dmidecode'}->{'action'} ne 'use'){ $key1 = $alerts{'dmidecode'}->{'action'}; - $val1 = $alerts{'dmidecode'}->{$key1}; + $val1 = $alerts{'dmidecode'}->{'message'}; $key1 = ucfirst($key1); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } @@ -18291,8 +18609,8 @@ sub swap_output { my $num = 0; my $j = 0; my (%part,@rows,$dev,$percent,$raw_size,$size,$used); - main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; - main::set_mapper() if !$b_mapper; + main::set_proc_partitions() if !$bsd_type && !$loaded{'proc-partitions'}; + main::set_mapper() if !$loaded{'mapper'}; my @swap_data = PartitionData::swap_data(); foreach my $row (@swap_data){ $num = 1; @@ -18310,7 +18628,7 @@ sub swap_output { $rows[$j]->{main::key($num++,0,2,'swappiness')} = $row->{'swappiness'}; } if (defined $row->{'cache-pressure'}){ - $rows[$j]->{main::key($num++,0,2,'cache pressure')} = $row->{'cache-pressure'}; + $rows[$j]->{main::key($num++,0,2,'cache-pressure')} = $row->{'cache-pressure'}; } } else { @@ -18326,7 +18644,7 @@ sub swap_output { if ($b_admin && $row->{'raw-size'} ){ # It's an error! permissions or missing tool $raw_size = main::get_size($row->{'raw-size'},'string'); - $rows[$j]->{main::key($num++,0,2,'raw size')} = $raw_size; + $rows[$j]->{main::key($num++,0,2,'raw-size')} = $raw_size; } # not used for swap as far as I know if ($b_admin && $row->{'raw-available'} && $size ne 'N/A'){ @@ -18336,7 +18654,7 @@ sub swap_output { $rows[$j]->{main::key($num++,0,2,'used')} = $used . $percent; # not used for swap as far as I know if ($b_admin && $row->{'block-size'}){ - $rows[$j]->{main::key($num++,0,2,'block size')} = $row->{'block-size'} . ' B';; + $rows[$j]->{main::key($num++,0,2,'block-size')} = $row->{'block-size'} . ' B';; #$rows[$j]->{main::key($num++,0,2,'physical')} = $row->{'block-size'} . ' B'; #$rows[$j]->{main::key($num++,0,2,'logical')} = $row->{'block-logical'} . ' B'; } @@ -18448,8 +18766,8 @@ sub unmounted_data { 'dvd[0-9]*','dvdrw[0-9]*','fd[0-9]','ram[0-9]*'); my $num = 0; # set labels, uuid, gpart - PartitionData::partition_data() if !$b_partitions; - RaidData::raid_data() if !$b_raid; + PartitionData::partition_data() if !$loaded{'partitions'}; + RaidData::raid_data() if !$loaded{'raid'}; my @mounted = get_mounted(); #print join("\n",(@filters,@mounted)),"\n"; foreach my $row (@proc_partitions){ @@ -18489,9 +18807,16 @@ sub unmounted_data { # these components of lvm raid will show as partitions byt are reserved private lvm member # See man lvm for all current reserved private volume names next if $dev_mapped && $dev_mapped =~ /_([ctv]data|corig|[mr]image|mlog|[crt]meta|pmspare|pvmove|vorigin)(_[0-9]+)?$/; - $label = PartitionData::get_label("/dev/$row->[-1]") if !$label; + if (!$bsd_type){ + $label = PartitionData::get_label("/dev/$row->[-1]") if !$label; + $uuid = PartitionData::get_uuid("/dev/$row->[-1]") if !$uuid; + } + else { + my @temp = GpartnData::get($row->[-1]); + $label = $temp[1] if $temp[1]; + $uuid = $temp[2] if $temp[2]; + } $maj_min = "$row->[0]:$row->[1]" if !$maj_min; - $uuid = PartitionData::get_uuid("/dev/$row->[-1]") if !$uuid; push(@unmounted, { 'dev-base' => $row->[-1], 'dev-mapped' => $dev_mapped, @@ -18547,7 +18872,7 @@ sub unmounted_filesystem { # this will fail if regular user and no sudo present, but that's fine, it will just return null # note the hack that simply slices out the first line if > 1 items found in string # also, if grub/lilo is on partition boot sector, no file system data is available - $data = (main::grabber("$sudo$file -s /dev/$item 2>/dev/null"))[0]; + $data = (main::grabber("$sudoas$file -s /dev/$item 2>/dev/null"))[0]; if ($data){ foreach (@filesystems){ if ($data =~ /($_)[\s,]/i){ @@ -18572,14 +18897,29 @@ sub get { eval $start if $b_log; my (@rows,$key1,$val1); my $num = 0; - if ( !@usb && $alerts{'lsusb'}->{'action'} ne 'use' && $alerts{'usbdevs'}->{'action'} ne 'use'){ + if (!@usb && $alerts{'lsusb'}->{'action'} ne 'use' && + $alerts{'usbdevs'}->{'action'} ne 'use' && + $alerts{'usbconfig'}->{'action'} ne 'use' ){ if ($os eq 'linux' ){ $key1 = $alerts{'lsusb'}->{'action'}; - $val1 = $alerts{'lsusb'}->{$key1}; + $val1 = $alerts{'lsusb'}->{'message'}; } else { - $key1 = $alerts{'usbdevs'}->{'action'}; - $val1 = $alerts{'usbdevs'}->{$key1}; + # note: usbdevs only has 'missing', usbconfig has missing/permissions + # both have platform, but irrelevant since testing for linux here + if ($alerts{'usbdevs'}->{'action'} eq 'missing' && + $alerts{'usbconfig'}->{'action'} eq 'missing'){ + $key1 = $alerts{'usbdevs'}->{'action'}; + $val1 = main::row_defaults('tools-missing-bsd','usbdevs/usbconfig'); + } + elsif ($alerts{'usbconfig'}->{'action'} eq 'permissions'){ + $key1 = $alerts{'usbconfig'}->{'action'}; + $val1 = $alerts{'usbconfig'}->{'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,}); @@ -18603,12 +18943,11 @@ sub usb_output { my ($b_hub,$bus_id,$chip_id,$driver,$ind_sc,$path_id,$ports,$product,$serial,$speed,$type); my $num = 0; my $j = 0; - # note: the data has been presorted in set_lsusb_data by: - # bus id then device id, so we don't need to worry about the order + # 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){ $j = scalar @rows; ($b_hub,$ind_sc,$num) = (0,3,1); - $chip_id = $id->[7]; ($driver,$path_id,$ports,$product, $serial,$speed,$type) = ('','','','','','',''); $speed = ( main::is_numeric($id->[8]) ) ? sprintf("%1.1f",$id->[8]) : $id->[8] if $id->[8]; @@ -18657,12 +18996,17 @@ sub usb_output { 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++,0,$ind_sc,'chip ID')} = $chip_id; + $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; + $rows[$j]->{main::key($num++,0,$ind_sc,'class-ID')} = $id; } if (!$b_hub && $extra > 2){ if ($serial){ @@ -19322,30 +19666,31 @@ sub complete_location { } #### ------------------------------------------------------------------- -#### UTILITIES FOR DATA LINES +#### UTILITIES FOR DATA LINES - GET #### ------------------------------------------------------------------- -sub get_compiler_version { +# Get CompilerVersion +{ +package CompilerVersion; +sub get { eval $start if $b_log; my (@compiler); - if (my $file = system_files('version') ) { - @compiler = get_compiler_version_linux($file); + if (my $file = main::system_files('version') ) { + @compiler = version_proc($file); } elsif ($bsd_type) { - @compiler = get_compiler_version_bsd(); + @compiler = version_bsd(); } eval $end if $b_log; return @compiler; } -sub get_compiler_version_bsd { +sub version_bsd { eval $start if $b_log; my (@compiler,@working); if ($alerts{'sysctl'}->{'action'} && $alerts{'sysctl'}->{'action'} eq 'use'){ - # for dragonfly, we will use free mem, not used because free is 0 my @working; foreach (@sysctl){ - # freebsd seems to use bytes here # Not every line will have a : separator though the processor should make # most have it. This appears to be 10.x late feature add, I don't see it # on earlier BSDs @@ -19357,26 +19702,29 @@ sub get_compiler_version_bsd { } } } - log_data('dump','@compiler',\@compiler) if $b_log; + main::log_data('dump','@compiler',\@compiler) if $b_log; eval $end if $b_log; return @compiler; } - -sub get_compiler_version_linux { +sub version_proc { eval $start if $b_log; my ($file) = @_; my (@compiler,$version); - my @data = reader($file); + my @data = main::reader($file); my $result = $data[0] if @data; if ($result){ - # $result = $result =~ /\*(gcc|clang)\*eval\*/; - # $result='Linux version 5.4.0-rc1 (sourav@archlinux-pc) (clang version 9.0.0 (tags/RELEASE_900/final)) #1 SMP PREEMPT Sun Oct 6 18:02:41 IST 2019'; - #$result='Linux version 5.8.3-fw1 (fst@x86_64.frugalware.org) ( OpenMandriva 11.0.0-0.20200819.1 clang version 11.0.0 (/builddir/build/BUILD/llvm-project-release-11.x/clang 2a0076812cf106fcc34376d9d967dc5f2847693a), LLD 11.0.0)'; - #$result='Linux version 5.8.0-18-generic (buildd@lgw01-amd64-057) (gcc (Ubuntu 10.2.0-5ubuntu2) 10.2.0, GNU ld (GNU Binutils for Ubuntu) 2.35) #19-Ubuntu SMP Wed Aug 26 15:26:32 UTC 2020'; - # $result='Linux version 5.8.9-fw1 (fst@x86_64.frugalware.org) (gcc (Frugalware Linux) 9.2.1 20200215, GNU ld (GNU Binutils) 2.35) #1 SMP PREEMPT Tue Sep 15 16:38:57 CEST 2020'; - # $result='Linux version 5.8.0-2-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.0-9) 10.2.0, GNU ld (GNU Binutils for Debian) 2.35) #1 SMP Debian 5.8.10-1 (2020-09-19)'; - $result='Linux version 5.9.0-5-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-1) 10.2.1 20201207, GNU ld (GNU Binutils for Debian) 2.35.1) #1 SMP Debian 5.9.15-1 (2020-12-17)'; - if ($result =~ /(gcc|clang).*version\s([\S]+)/){ + if ($fake{'compiler'}){ + # $result = $result =~ /\*(gcc|clang)\*eval\*/; + # $result='Linux version 5.4.0-rc1 (sourav@archlinux-pc) (clang version 9.0.0 (tags/RELEASE_900/final)) #1 SMP PREEMPT Sun Oct 6 18:02:41 IST 2019'; + # $result='Linux version 5.8.3-fw1 (fst@x86_64.frugalware.org) ( OpenMandriva 11.0.0-0.20200819.1 clang version 11.0.0 (/builddir/build/BUILD/llvm-project-release-11.x/clang 2a0076812cf106fcc34376d9d967dc5f2847693a), LLD 11.0.0)'; + # $result='Linux version 5.8.0-18-generic (buildd@lgw01-amd64-057) (gcc (Ubuntu 10.2.0-5ubuntu2) 10.2.0, GNU ld (GNU Binutils for Ubuntu) 2.35) #19-Ubuntu SMP Wed Aug 26 15:26:32 UTC 2020'; + # $result='Linux version 5.8.9-fw1 (fst@x86_64.frugalware.org) (gcc (Frugalware Linux) 9.2.1 20200215, GNU ld (GNU Binutils) 2.35) #1 SMP PREEMPT Tue Sep 15 16:38:57 CEST 2020'; + # $result='Linux version 5.8.0-2-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.0-9) 10.2.0, GNU ld (GNU Binutils for Debian) 2.35) #1 SMP Debian 5.8.10-1 (2020-09-19)'; + # $result='Linux version 5.9.0-5-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-1) 10.2.1 20201207, GNU ld (GNU Binutils for Debian) 2.35.1) #1 SMP Debian 5.9.15-1 (2020-12-17)'; + # $result='Linux version 2.6.1 (GNU 0.9 GNU-Mach 1.8+git20201007-486/Hurd-0.9 i686-AT386)'; + # $result='NetBSD version 9.1 (netbsd@localhost) (gcc version 7.5.0) NetBSD 9.1 (GENERIC) #0: Sun Oct 18 19:24:30 UTC 2020'; + } + if ($result =~ /(gcc|clang).*version\s([^\s\)]+)/){ $version = $2; $version ||= 'N/A'; @compiler = ($1,$version); @@ -19387,10 +19735,11 @@ sub get_compiler_version_linux { @compiler = ($1,$version); } } - log_data('dump','@compiler',\@compiler) if $b_log; + main::log_data('dump','@compiler',\@compiler) if $b_log; eval $end if $b_log; return @compiler; } +} ## Get DesktopEnvironment ## returns array: @@ -19408,7 +19757,7 @@ $xdg_desktop,@desktop,@data,@xprop); sub get { eval $start if $b_log; set_desktop_values(); - main::set_ps_gui() if ! $b_ps_gui; + main::set_ps_gui() if ! $loaded{'ps-gui'}; get_kde_trinity_data(); if (!@desktop){ get_env_de_data(); @@ -19425,7 +19774,7 @@ sub get { if ($extra > 2 && @desktop){ set_info_data(); } - if ($b_display && !$b_force_display && $extra > 1){ + if ($b_display && !$force{'display'} && $extra > 1){ get_wm(); } set_gtk_data() if $b_gtk && $extra > 1; @@ -19766,10 +20115,14 @@ sub get_env_xprop_non_gnome_based_data { sub get_ps_de_data { eval $start if $b_log; my ($program,@version_data); - main::set_ps_gui() if !$b_ps_gui; + main::set_ps_gui() if !$loaded{'ps-gui'}; if (@ps_gui){ + # the sequence here matters, some desktops like icewm, razor, let you set different + # wm, so we want to get the main controlling desktop first # 1 check program; 2 ps_gui search; 3 data; 4: trigger alternate values/version my @desktops =( + ['icewm','icewm','icewm'], + ['WindowMaker','WindowMaker','wmaker',''], ['9wm','9wm','9wm',''], ['afterstep','afterstep','afterstep',''], ['aewm++','aewm\+\+','aewm++',''], @@ -19782,6 +20135,7 @@ sub get_ps_de_data { ['cagebreak','cagebreak','cagebreak',''], ['calmwm','calmwm','calmwm',''], ['clfswm','.*(sh|c?lisp)?.*clfswm','clfswm',''], + ['ctwm','ctwm','ctwm',''], ['cwm','(openbsd-)?cwm','cwm',''], ['dwm','dwm','dwm',''], ['echinus','echinus','echinus',''], @@ -19798,7 +20152,9 @@ sub get_ps_de_data { ['fvwm','fvwm','fvwm',''], ['glass','glass','glass',''], ['hackedbox','hackedbox','hackedbox',''], + ['herbstluftwm','herbstluftwm','herbstluftwm'], ['instantwm','instantwm','instantwm',''], + ['i3','i3','i3',''], ['ion3','ion3','ion3',''], ['jbwm','jbwm','jbwm',''], ['jwm','jwm','jwm',''], @@ -19828,7 +20184,6 @@ sub get_ps_de_data { ['twm','twm','twm',''], ['waycooler','waycooler','way-cooler',''], ['way-cooler','way-cooler','way-cooler',''], - ['WindowMaker','WindowMaker','wmaker',''], ['windowlab','windowlab','windowlab',''], # not in debian apt, current is wmii, version 3 ['wmii2','wmii2','wmii2',''], @@ -19896,11 +20251,11 @@ sub set_qt_data { sub get_wm { eval $start if $b_log; - if (!$b_wmctrl) { + if (!$force{'wmctrl'}) { get_wm_main(); } # note, some wm, like cinnamon muffin, do not appear in ps aux, but do in wmctrl - if ( (!$desktop[5] || $b_wmctrl) && (my $program = main::check_program('wmctrl'))){ + if ( (!$desktop[5] || $force{'wmctrl'}) && (my $program = main::check_program('wmctrl'))){ get_wm_wmctrl($program); } eval $end if $b_log; @@ -19922,11 +20277,11 @@ sub get_wm_main { } } if (!$desktop[5]){ - main::set_ps_gui() if ! $b_ps_gui; + main::set_ps_gui() if ! $loaded{'ps-gui'}; # order matters, see above logic # due to lisp/python starters, clfswm/stumpwm/qtile will not detect here $wms = '9wm|aewm\+\+|aewm|afterstep|amiwm|antiwm|awesome|blackbox|bspwm|budgie-wm|'; - $wms .= 'cagebreak|calmwm|clfswm|compiz|(openbsd-)?cwm|fluxbox|'; + $wms .= 'cagebreak|calmwm|clfswm|compiz|ctwm|(openbsd-)?cwm|fluxbox|'; $wms .= 'deepin-wm|dwm|echinus|evilwm|'; $wms .= 'fireplace|flwm|fvwm-crystal|fvwm1|fvwm2|fvwm3|fvwm95|fvwm|'; $wms .= 'gala|glass|gnome-shell|hackedbox|i3|instantwm|ion3|jbwm|jwm|'; @@ -19993,7 +20348,7 @@ sub get_wm_version { sub set_info_data { eval $start if $b_log; - main::set_ps_gui() if ! $b_ps_gui; + main::set_ps_gui() if ! $loaded{'ps-gui'}; my (@data,@info,$item); my $pattern = 'alltray|awn|bar|bmpanel|bmpanel2|budgie-panel|cairo-dock|'; $pattern .= 'dde-dock|dmenu|dockbarx|docker|docky|dzen|dzen2|'; @@ -20052,7 +20407,7 @@ sub get_display_manager { # explicitly, not -e. Guessing on cdm.pid my @dms = qw(cdm.pid entranced.pid gdm.pid gdm3.pid kdm.pid ldm.pid lightdm.pid lxdm.pid mdm.pid nodm.pid pcdm.pid sddm.pid slim.lock - tdm.pid udm.pid wdm.pid xdm.pid xenodm.pid); + slim.pid tdm.pid udm.pid wdm.pid xdm.pid xenodm.pid); # these are the only one I know of so far that have version info my @dms_version = qw(gdm gdm3 lightdm slim); $b_run = 1 if -d "/run"; @@ -20108,7 +20463,9 @@ sub get_display_manager { ## Get DistroData { package DistroData; -my (@distro_data,@osr); +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){ @@ -20118,33 +20475,48 @@ sub get { get_linux_distro(); } eval $end if $b_log; - return @distro_data; + return ($distro,$system_base); } sub get_bsd_os { eval $start if $b_log; - my ($distro) = (''); if ($bsd_type eq 'darwin'){ - my $file = '/System/Library/CoreServices/SystemVersion.plist'; - if (-f $file){ - my @data = main::reader($file); - @data = grep {/(ProductName|ProductVersion)/} @data if @data; - @data = grep {//} @data if @data; - @data = map {s/<[\/]?string>//g; } @data if @data; - $distro = join(' ', @data); + $distro_file = '/System/Library/CoreServices/SystemVersion.plist'; + if (-f $distro_file){ + @working = main::reader($distro_file); + @working = grep {/(ProductName|ProductVersion)/} @working if @working; + @working = grep {//} @working if @working; + @working = map {s/<[\/]?string>//g; } @working if @working; + $distro = join(' ', @working); } } - # seen a case without osx file, or was it permissions? - # this covers all the other bsds anyway, no problem. - $distro = "$uname[0] $uname[2]" if !$distro; - @distro_data = ($distro,''); + if (!$distro){ + my $bsd_type_osr = 'dragonfly'; + @osr = main::reader($os_release) if -r $os_release; + if (@osr && $bsd_type =~ /($bsd_type_osr)/ && (grep {/($bsd_type_osr)/i} @osr)){ + $distro = get_os_release(); + } + } + if (!$distro){ + # seen a case without osx file, or was it permissions? + # this covers all the other bsds anyway, no problem. + $distro = "$uname[0] $uname[2]"; + } + if ($distro && + (-e '/etc/pkg/GhostBSD.conf' || -e '/usr/local/etc/pkg/repos/GhostBSD.conf') && + $distro =~ /freebsd/i){ + my $version = (main::grabber("pkg query '%v' os-generic-userland-base 2>/dev/null"))[0]; + # only swap if we get result from the query + if ($version){ + $system_base = $distro; + $distro = "GhostBSD $version"; + } + } + system_base_bsd() if $extra > 0; eval $end if $b_log; } sub get_linux_distro { - eval $start if $b_log; - my ($distro,$distro_id,$distro_file,$system_base) = ('','','',''); - my ($b_issue,$b_osr,$b_use_issue,@working); # order matters! my @derived = qw(antix-version aptosid-version bodhibuilder.conf kanotix-version knoppix-version pclinuxos-release mandrake-release manjaro-release mx-version @@ -20158,42 +20530,50 @@ sub get_linux_distro { # note, pclinuxos has all these mandrake/mandriva files, careful! my $lsb_good_s = 'mandrake-release|mandriva-release|mandrakelinux-release|manjaro-release'; my $os_release_good_s = 'altlinux-release|arch-release|pclinuxos-release|rpi-issue|SuSE-release'; + my ($b_issue,$b_lsb,$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 + # 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: # /etc/lsb-release-crunchbang # wait to handle since crunchbang file is one of the few in the world that # uses this method - my @distro_files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); + @distro_files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); push(@distro_files, '/etc/bodhibuilder.conf') if -r '/etc/bodhibuilder.conf'; - my $lsb_release = '/etc/lsb-release'; - my $b_lsb = 1 if -f $lsb_release; - my ($etc_issue,$issue,$lc_issue) = ('','/etc/issue',''); - $b_issue = 1 if -f $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,'',0) if -r $issue; - $etc_issue = main::clean_characters($etc_issue); - my $os_release = '/etc/os-release'; @osr = main::reader($os_release) if -r $os_release; - # debian issue can end with weird escapes like \n \l - # antergos: Antergos Linux \r (\l) if ($etc_issue){ - $lc_issue = lc($etc_issue) if $etc_issue; + $lc_issue = lc($etc_issue); if ($lc_issue =~ /(antergos|grml|linux lite)/){ $distro_id = $1; - $b_use_issue = 1; + $b_skip_issue = 1; } + # this raspbian detection fails for rasberry 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 + # 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'))){ + $distro_id = 'raspios' ; + } } # Note that antergos changed this around # 2018-05, and now lists # antergos in os-release, sigh... We want these distros to use os-release # if it contains their names. Last check below - if ( @osr && ( grep {/(manjaro|antergos|chakra|pclinuxos|zorin)/i} @osr ) ){ + if ( @osr && ( grep {/(manjaro|antergos|chakra|guix|pclinuxos|raspberry pi os|zorin)/i} @osr ) ){ $distro_file = $os_release; } - $distro_id = 'armbian' if grep {/armbian/} @distro_files; + if (grep {/armbian/} @distro_files){ + $distro_id = 'armbian' ; + } main::log_data('dump','@distro_files',\@distro_files) if $b_log; main::log_data('data',"distro_file-1: $distro_file") if $b_log; if (!$distro_file){ @@ -20206,7 +20586,6 @@ sub get_linux_distro { # antergos should use /etc/issue. We've already checked os-release above if ($distro_id eq 'antergos' || (grep {/antergos|chakra|manjaro/} @distro_files )){ @distro_files = grep {!/arch-release/} @distro_files; - #$system_base = 'Arch Linux'; } my $distro_files_s = join('|', @distro_files); @working = (@derived,@primary); @@ -20246,7 +20625,7 @@ sub get_linux_distro { } elsif ($distro_file && $distro_file eq $os_release){ $distro = get_os_release(); - $b_osr = 1; + $b_skip_osr = 1; } # 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)$/){ @@ -20275,28 +20654,37 @@ sub get_linux_distro { } $distro = main::clean_characters($distro) if $distro; } - # otherwise try the default debian/ubuntu /etc/issue file + # otherwise try the default debian/ubuntu/distro /etc/issue file elsif ($b_issue){ - if ( !$distro_id && $etc_issue && $lc_issue =~ /(mint|lmde)/ ){ + if ( !$distro_id && $lc_issue && $lc_issue =~ /(mint|lmde)/){ $distro_id = $1; - $b_use_issue = 1; + $b_skip_issue = 1; } # os-release/lsb gives more manageable and accurate output than issue, # but mint should use issue for now. Antergos uses arch os-release, but issue shows them - if (!$b_use_issue && @osr){ + if (!$b_skip_issue && @osr){ $distro = get_os_release(); - $b_osr = 1; + $b_skip_osr = 1; } - elsif (!$b_use_issue && $b_lsb){ + elsif (!$b_skip_issue && $b_lsb){ $distro = get_lsb_release(); } elsif ($etc_issue) { - $distro = $etc_issue; - # this handles an arch bug where /etc/arch-release is empty and /etc/issue - # is corrupted only older arch installs that have not been updated should - # have this fallback required, new ones use os-release - if ( $distro =~ /arch linux/i){ - $distro = 'Arch Linux'; + 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 + 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 + # 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){ + $distro = 'Arch Linux'; + } } } } @@ -20304,18 +20692,18 @@ sub get_linux_distro { # 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 ){ - if (!$b_osr && @osr){ + if (!$b_skip_osr && @osr){ $distro = get_os_release(); - $b_osr = 1; + $b_skip_osr = 1; } } # 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){ - if (!$b_osr && @osr){ + if (!$b_skip_osr && @osr){ $distro = get_os_release(); - $b_osr = 1; + $b_skip_osr = 1; } elsif ($b_lsb){ $distro = get_lsb_release(); @@ -20331,114 +20719,142 @@ sub get_linux_distro { $distro = $distro_file; } } - if ($extra > 0){ - my $base_arch_distro = 'anarchy|antergos|archbang|archlabs|archman|archstrike|arco|artix'; - # note: arch linux derived distro page claims kaos as arch derived but it is NOT - $base_arch_distro .= '|blackarch|bluestar|chakra|ctios|endeavour|hyperbola|linhes'; - $base_arch_distro .= '|manjaor|mysys2|netrunner\s?rolling|ninja|obarun|parabola'; - $base_arch_distro .= '|puppyrus-?a|reborn|snal|talkingarch|ubos'; - my $base_debian_version_distro = 'sidux'; - my $base_debian_version_osr = '\belive|lmde|neptune|parrot|pureos|rescatux|septor|sparky|tails'; - my $base_default = 'antix-version|mx-version'; # osr has base ids - my $base_issue = 'bunsen'; # base only found in issue - my $base_manual = 'blankon|deepin|kali'; # synthesize, no direct data available - my $base_osr = 'aptosid|grml|q4os|siduction|bodhi'; # osr base, distro id in list of distro files - my $base_osr_issue = 'grml|linux lite'; # osr base, distro id in issue - # osr has distro name but has ubuntu ID_LIKE/UBUNTU_CODENAME - my $base_osr_ubuntu = 'mint|neon|nitrux|pop!_os|zorin'; - my $base_upstream_lsb = '/etc/upstream-release/lsb-release'; - my $base_upstream_osr = '/etc/upstream-release/os-release'; - # 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); - if ( @osr_working){ - my (@osr_temp); - @osr_temp = @osr; - @osr = @osr_working; - $system_base = get_os_release(); - @osr = @osr_temp if !$system_base; - (@osr_temp,@osr_working) = (undef,undef); - } - } - elsif ( -r $base_upstream_lsb){ - $system_base = get_lsb_release($base_upstream_lsb); - } - if (!$system_base && @osr){ - my ($base_type) = (''); - if ($etc_issue && (grep {/($base_issue)/i} @osr)){ - $system_base = $etc_issue; - } - # more tests added here for other ubuntu derived distros - elsif ( @distro_files && (grep {/($base_default)/} @distro_files) ){ - $base_type = 'default'; - } - # must go before base_osr_ubuntu test - elsif ( grep {/($base_debian_version_osr)/i} @osr ){ - $system_base = debian_id(); - } - elsif ( grep {/($base_osr_ubuntu)/i} @osr ){ - $base_type = 'ubuntu'; - } - elsif ( ( ($distro_id && $distro_id =~ /($base_osr_issue)/ ) || - (@distro_files && (grep {/($base_osr)/} @distro_files) ) ) && - !(grep {/($base_osr)/i} @osr)){ - $system_base = get_os_release(); - } - if (!$system_base && $base_type){ - $system_base = get_os_release($base_type); - } - } - if (!$system_base && @distro_files && ( grep {/($base_debian_version_distro)/i} @distro_files ) ){ - $system_base = debian_id(); - } - if (!$system_base && $lc_issue && $lc_issue =~ /($base_manual)/){ - my $id = $1; - my %manual = ( - 'blankon' => 'Debian unstable', - 'deepin' => 'Debian unstable', - 'kali' => 'Debian testing', - ); - $system_base = $manual{$id}; - } - if (!$system_base && $distro && $distro =~ /^($base_arch_distro)/i){ - $system_base = 'Arch Linux'; - } - if ($distro && -d '/etc/salixtools/' && $distro =~ /Slackware/i){ - $system_base = $distro; - } - } + system_base() if $extra > 0; + # 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: + if ($extra == 0){$distro =~ s/Debian\s*GNU\/Linux/Raspberry Pi OS/;} + else {$distro = 'Raspberry Pi OS';} + } elsif (-d '/etc/salixtools/' && $distro =~ /Slackware/i){ $distro =~ s/Slackware/Salix/; } } else { # android fallback, sometimes requires root, sometimes doesn't - if ($b_android) { - main::set_build_prop() if !$b_build_prop;; - $distro = 'Android'; - $distro .= ' ' . $build_prop{'build-version'} if $build_prop{'build-version'}; - $distro .= ' ' . $build_prop{'build-date'} if $build_prop{'build-date'}; - if (!$show{'machine'}){ - if ($build_prop{'product-manufacturer'} && $build_prop{'product-model'}){ - $distro .= ' (' . $build_prop{'product-manufacturer'} . ' ' . $build_prop{'product-model'} . ')'; - } - elsif ($build_prop{'product-device'}){ - $distro .= ' (' . $build_prop{'product-device'} . ')'; - } - elsif ($build_prop{'product-name'}){ - $distro .= ' (' . $build_prop{'product-name'} . ')'; - } - } - } + android_info() if $b_android; } ## finally, if all else has failed, give up $distro ||= 'unknown'; - @distro_data = ($distro,$system_base); + eval $end if $b_log; +} + +sub android_info { + eval $start if $b_log; + main::set_build_prop() if !$loaded{'build-prop'};; + $distro = 'Android'; + $distro .= ' ' . $build_prop{'build-version'} if $build_prop{'build-version'}; + $distro .= ' ' . $build_prop{'build-date'} if $build_prop{'build-date'}; + if (!$show{'machine'}){ + if ($build_prop{'product-manufacturer'} && $build_prop{'product-model'}){ + $distro .= ' (' . $build_prop{'product-manufacturer'} . ' ' . $build_prop{'product-model'} . ')'; + } + elsif ($build_prop{'product-device'}){ + $distro .= ' (' . $build_prop{'product-device'} . ')'; + } + elsif ($build_prop{'product-name'}){ + $distro .= ' (' . $build_prop{'product-name'} . ')'; + } + } + eval $end if $b_log; +} + +sub system_base_bsd { + eval $start if $b_log; + # ghostbsd is handled in main bsd section + if (lc($uname[1]) eq 'nomadbsd' && $distro =~ /^freebsd/i){ + $system_base = $distro; + $distro = $uname[1]; + } + if (-f '/etc/pkg/HardenedBSD.conf' && $distro =~ /^freebsd/i){ + $system_base = $distro; + $distro = 'HardenedBSD'; + } + eval $end if $b_log; +} + +sub system_base { + eval $start if $b_log; + my $base_arch_distro = 'anarchy|antergos|archbang|archlabs|archman|archstrike|arco|artix'; + # note: arch linux derived distro page claims kaos as arch derived but it is NOT + $base_arch_distro .= '|blackarch|bluestar|chakra|ctios|endeavour|garuda|hyperbola|linhes'; + $base_arch_distro .= '|manjaro|mysys2|netrunner\s?rolling|ninja|obarun|parabola'; + $base_arch_distro .= '|puppyrus-?a|reborn|snal|talkingarch|ubos'; + my $base_debian_version_distro = 'sidux'; + my $base_debian_version_osr = '\belive|lmde|neptune|parrot|pureos|rescatux|septor|sparky|tails'; + my $base_default = 'antix-version|mx-version'; # osr has base ids + my $base_issue = 'bunsen'; # base only found in issue + my $base_manual = 'blankon|deepin|kali'; # synthesize, no direct data available + my $base_osr = 'aptosid|grml|q4os|siduction|bodhi'; # osr base, distro id in list of distro files + my $base_osr_issue = 'grml|linux lite'; # osr base, distro id in issue + # osr has distro name but has ubuntu ID_LIKE/UBUNTU_CODENAME + my $base_osr_ubuntu = 'mint|neon|nitrux|pop!_os|zorin'; + my $base_upstream_lsb = '/etc/upstream-release/lsb-release'; + my $base_upstream_osr = '/etc/upstream-release/os-release'; + # 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); + if ( @osr_working){ + my (@osr_temp); + @osr_temp = @osr; + @osr = @osr_working; + $system_base = get_os_release(); + @osr = @osr_temp if !$system_base; + (@osr_temp,@osr_working) = (undef,undef); + } + } + elsif ( -r $base_upstream_lsb){ + $system_base = get_lsb_release($base_upstream_lsb); + } + if (!$system_base && @osr){ + my ($base_type) = (''); + if ($etc_issue && (grep {/($base_issue)/i} @osr)){ + $system_base = $etc_issue; + } + # more tests added here for other ubuntu derived distros + elsif ( @distro_files && (grep {/($base_default)/} @distro_files) ){ + $base_type = 'default'; + } + # must go before base_osr_ubuntu test + elsif ( grep {/($base_debian_version_osr)/i} @osr ){ + $system_base = debian_id(); + } + elsif ( grep {/($base_osr_ubuntu)/i} @osr ){ + $base_type = 'ubuntu'; + } + elsif ( ( ($distro_id && $distro_id =~ /($base_osr_issue)/ ) || + (@distro_files && (grep {/($base_osr)/} @distro_files) ) ) && + !(grep {/($base_osr)/i} @osr)){ + $system_base = get_os_release(); + } + if (!$system_base && $base_type){ + $system_base = get_os_release($base_type); + } + } + if (!$system_base && @distro_files && ( grep {/($base_debian_version_distro)/i} @distro_files ) ){ + $system_base = debian_id(); + } + if (!$system_base && $lc_issue && $lc_issue =~ /($base_manual)/){ + my $id = $1; + my %manual = ( + 'blankon' => 'Debian unstable', + 'deepin' => 'Debian unstable', + 'kali' => 'Debian testing', + ); + $system_base = $manual{$id}; + } + if (!$system_base && $distro && $distro =~ /^($base_arch_distro)/i){ + $system_base = 'Arch Linux'; + } + if ($distro && -d '/etc/salixtools/' && $distro =~ /Slackware/i){ + $system_base = $distro; + } eval $end if $b_log; } @@ -20482,7 +20898,10 @@ sub get_lsb_release { $distro = $description; } else { - $distro = "$id $release $codename"; + # avoid duplicates + $distro = $id; + $distro .= " $release" if $distro !~ /$release/; + $distro .= " $codename" if $distro !~ /$codename/; $distro =~ s/^\s+|\s\s+|\s+$//g; # get rid of double and trailing spaces } eval $end if $b_log; @@ -20599,7 +21018,7 @@ sub debian_id { '13' => 'trixie', ); if (main::is_numeric($debian_version)){ - $id .= " $debian_version $debians{int($debian_version)}"; + $id .= " $debian_version " . $debians{int($debian_version)}; } elsif ($codename) { my %by_value = reverse %debians; @@ -20695,30 +21114,104 @@ sub get_gcc_data { return @gccs; } -# rasberry pi only -sub get_gpu_ram_arm { +# Get GlabelData +{ +package GlabelData; +# gptid/c5e940f1-5ce2-11e6-9eeb-d05099ac4dc2 N/A ada0p1 +sub get { eval $start if $b_log; - my ($gpu_ram) = (0); - if (my $program = check_program('vcgencmd')){ - # gpu=128M - # "VCHI initialization failed" - you need to add video group to your user - my $working = (grabber("$program get_mem gpu 2>/dev/null"))[0]; - $working = (split(/\s*=\s*/, $working))[1] if $working; - $gpu_ram = translate_size($working) if $working; + my ($gptid) = @_; + set() if !$loaded{'glabel'}; + return if !@glabel || !$gptid; + my ($dev_id) = (''); + foreach (@glabel){ + my @temp = split(/\s+/, $_); + my $gptid_trimmed = $gptid; + # slice off s[0-9] from end in case they use slice syntax + $gptid_trimmed =~ s/s[0-9]+$//; + if (defined $temp[0] && ($temp[0] eq $gptid || $temp[0] eq $gptid_trimmed ) ){ + $dev_id = $temp[2]; + last; + } } - log_data('data',"gpu ram: $gpu_ram") if $b_log; + $dev_id ||= $gptid; # no match? return full string eval $end if $b_log; - return $gpu_ram; + return $dev_id; } - -# standard systems -sub get_gpu_ram { +sub set { eval $start if $b_log; - my ($gpu_ram) = (0); + $loaded{'glabel'} = 1; + if (my $path = main::check_program('glabel')){ + @glabel = main::grabber("$path status 2>/dev/null"); + } + main::log_data('dump','@glabel:with Headers',\@glabel) if $b_log; + # get rid of first header line + shift @glabel; eval $end if $b_log; - return $gpu_ram; +} } +# Get GpartData +{ +package GpartData; +# 1. Name: ada1p1 +# label: (null) +# label: ssd-root +# rawuuid: b710678b-f196-11e1-98fd-021fc614aca9 +sub get { + eval $start if $b_log; + my ($item) = @_; + my (@data) = ('','','',''); + set() if !$loaded{'gpart'}; + return @data if !$item || !%gpart; + if ($gpart{$item}){ + $data[0] = $gpart{$item}->{'block-size'} if $gpart{$item}->{'block-size'}; + $data[1] = $gpart{$item}->{'label'} if $gpart{$item}->{'label'}; + $data[2] = $gpart{$item}->{'uuid'} if $gpart{$item}->{'uuid'}; + $data[3] = $gpart{$item}->{'size'} if $gpart{$item}->{'size'}; + } + main::log_data('dump','@data',\@data) if $b_log; + eval $end if $b_log; + return @data; +} +# 2021-03: openbsd: n/a; dragonfly: no 'list'; freebsd: yes +sub set { + eval $start if $b_log; + $loaded{'gpart'} = 1; + if (my $path = main::check_program('gpart')){ + my @data = main::grabber("$path list 2>/dev/null",'','strip'); + main::log_data('dump', 'gpart: @data', \@data) if $b_log; + my ($id); + for (@data){ + my @working = split(/\s*:\s*/, $_); + if ($working[0] =~ /^[0-9]+\.\s*Name/){ + $id = $working[1]; + } + elsif ($id){ + # eg: label:(null) - we want to show null + if ($working[0] eq 'label'){ + $working[1] =~ s/\(|\)//g; + $gpart{$id}->{'label'} = $working[1]; + } + elsif ($working[0] eq 'Mediasize'){ + $working[1] =~ s/\s+\(.*$//; # trim off the (2.4G) + # gpart shows in bytes, not KiB. For the time being... + $gpart{$id}->{'size'} = $working[1]/1024 if $working[1]; + } + elsif ($working[0] eq 'rawuuid'){ + $working[1] =~ s/\(|\)//g; + $gpart{$id}->{'uuid'} = $working[1]; + } + elsif ($working[0] eq 'Sectorsize'){ + $gpart{$id}->{'block-size'} = $working[1]; + } + } + } + } + main::log_data('dump', '%gpart', \%gpart) if $b_log; + eval $end if $b_log; +} +} sub get_hostname { eval $start if $b_log; my $hostname = ''; @@ -20756,10 +21249,10 @@ sub get_init_data { if ( $comm =~ /systemd/ ){ $init = 'systemd'; if ( $program = check_program('systemd')){ - $init_version = program_version($program,'^systemd','2','--version'); + $init_version = program_version($program,'^systemd','2','--version',1); } if (!$init_version && ($program = check_program('systemctl') ) ){ - $init_version = program_version($program,'^systemd','2','--version'); + $init_version = program_version($program,'^systemd','2','--version',1); } } # epoch version == Epoch Init System 1.0.1 "Sage" @@ -20774,6 +21267,10 @@ sub get_init_data { elsif ($comm =~ /runit/){ $init = 'runit'; } + elsif ($comm =~ /shepherd/){ + $init = 'Shepherd'; + $init_version = program_version('shepherd', '^shepherd', '4','--version',1); + } elsif ($comm =~ /^s6/){ $init = 's6'; } @@ -20782,7 +21279,8 @@ sub get_init_data { # output: /sbin/init --version: init (upstart 1.1) # init (upstart 0.6.3) # openwrt /sbin/init hangs on --version command, I think - if ((!$b_mips && !$b_sparc && !$b_arm) && ($init_version = program_version('init', 'upstart', '3','--version') )){ + if ((!$b_mips && !$b_sparc && !$b_arm) && + ($init_version = program_version('init', 'upstart', '3','--version') )){ $init = 'Upstart'; } elsif (check_program('launchctl')){ @@ -20799,7 +21297,7 @@ sub get_init_data { $init = 'init (BSD)'; } } - if ( grep { /openrc/ } globber('/run/*openrc*') ){ + if ( (grep { /openrc/ } globber('/run/*openrc*')) || (grep {/openrc/} @ps_cmd) ){ $rc = 'OpenRC'; # /sbin/openrc --version == openrc (OpenRC) 0.13 if ($program = check_program('openrc')){ @@ -20869,33 +21367,36 @@ sub get_kernel_bits { return $bits; } -sub get_kernel_parameters { +# Get KernelParameters +{ +package KernelParameters; +sub get { eval $start if $b_log; my ($parameters); - if (my $file = system_files('cmdline') ) { - $parameters = get_kernel_parameters_linux($file); + if (my $file = main::system_files('cmdline') ) { + $parameters = parameters_linux($file); } elsif ($bsd_type) { - $parameters = get_kernel_parameters_bsd(); + $parameters = parameters_bsd(); } eval $end if $b_log; return $parameters; } -sub get_kernel_parameters_linux { +sub parameters_linux { eval $start if $b_log; my ($file) = @_; # unrooted android may have file only root readable - my $line = reader($file,'',0) if -r $file; + my $line = main::reader($file,'',0) if -r $file; eval $end if $b_log; return $line; } -sub get_kernel_parameters_bsd { +sub parameters_bsd { eval $start if $b_log; my ($parameters); eval $end if $b_log; return $parameters; } - +} # 1 - partition name sub get_lsblk { eval $start if $b_log; @@ -20912,70 +21413,92 @@ sub get_lsblk { return %device; } -sub get_memory_data_full { +# Get MemoryData +{ +package MemoryData; + +sub get { + eval $start if $b_log; + my ($type) = @_; + my ($memory); + # note: netbsd 8.0 has meminfo! + $loaded{'memory'} = 1; + if (!$force{'vmstat'} && (my $file = main::system_files('meminfo'))) { + $memory = meminfo_data($type,$file); + } + else { + $memory = bsd_data($type); + } + eval $end if $b_log; + return $memory; +} +sub full { eval $start if $b_log; my ($source) = @_; my $num = 0; my ($memory,@rows); my ($gpu_ram,$percent,$total,$used) = (0,'','',''); - if ($show{'ram'} || (!$show{'info'} && $show{'process'} )){ - $memory = get_memory_data('splits'); - if ($memory){ - my @temp = split(':', $memory); - $gpu_ram = $temp[3] if $temp[3]; - $total = ($temp[0]) ? get_size($temp[0],'string') : 'N/A'; - $used = ($temp[1]) ? get_size($temp[1],'string') : 'N/A'; - $used .= " ($temp[2]%)" if $temp[2]; - if ($gpu_ram){ - $gpu_ram = get_size($gpu_ram,'string'); - } + $loaded{'memory'} = 1; + $memory = 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]; + if ($gpu_ram){ + $gpu_ram = main::get_size($gpu_ram,'string'); } - my $key = ($source eq 'process') ? 'System RAM': 'RAM'; - $rows[0]->{main::key($num++,1,1,$key)} = ''; - $rows[0]->{main::key($num++,0,2,'total')} = $total; - $rows[0]->{main::key($num++,0,2,'used')} = $used; - $rows[0]->{main::key($num++,0,2,'gpu')} = $gpu_ram if $gpu_ram; - $b_mem = 1; } + my $key = ($source eq 'process') ? 'System RAM': 'RAM'; + $rows[0]->{main::key($num++,1,1,$key)} = ''; + $rows[0]->{main::key($num++,0,2,'total')} = $total; + $rows[0]->{main::key($num++,0,2,'used')} = $used; + $rows[0]->{main::key($num++,0,2,'gpu')} = $gpu_ram if $gpu_ram; eval $end if $b_log; return @rows; } - -sub get_memory_data { - eval $start if $b_log; - my ($type) = @_; - my ($memory); - if (my $file = system_files('meminfo') ) { - $memory = get_memory_data_linux($type,$file); - } - else { - $memory = get_memory_data_bsd($type); - } - eval $end if $b_log; - return $memory; -} - -sub get_memory_data_linux { +sub meminfo_data { eval $start if $b_log; my ($type,$file) = @_; - my ($available,$gpu,$memory,$not_used,$total) = (0,0,'',0,0); - my @data = reader($file); + my ($available,$buffers,$cached,$free,$gpu,$memory,$not_used,$total) = (0,0,0,0,0,'',0,0); + my @data = main::reader($file); foreach (@data){ if ($_ =~ /^MemTotal:/){ - $total = get_piece($_,2); + $total = main::get_piece($_,2); } - elsif ($_ =~ /^(MemFree|Buffers|Cached):/){ - $not_used += get_piece($_,2); + elsif ($_ =~ /^MemFree:/){ + $free = main::get_piece($_,2); + } + elsif ($_ =~ /^Buffers:/){ + $buffers = main::get_piece($_,2); + } + elsif ($_ =~ /^Cached:/){ + $cached = main::get_piece($_,2); } elsif ($_ =~ /^MemAvailable:/){ - $available = get_piece($_,2); + $available = main::get_piece($_,2); } } - $not_used = $available if $available; - $gpu = get_gpu_ram_arm() if $b_arm; - #$gpu = translate_size('128M'); + $gpu = gpu_ram_arm() if $b_arm; + #$gpu = main::translate_size('128M'); $total += $gpu; - my $used = $total - ($not_used); + 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 + elsif (($total - ($free + $buffers + $cached)) > 10000) { + $not_used = ($free + $buffers + $cached); + } + # netbsd goes < 0, but it's wrong, so dump the cache + elsif (($total - ($free + $buffers)) > 10000){ + $not_used = ($free + $buffers); + } + else { + $not_used = $free; + } + my $used = ($total - $not_used); my $percent = ($used && $total) ? sprintf("%.1f", ($used/$total)*100) : ''; if ($type eq 'string'){ $percent = " ($percent%)" if $percent; @@ -20984,7 +21507,7 @@ sub get_memory_data_linux { else { $memory = "$total:$used:$percent:$gpu"; } - log_data('data',"memory: $memory") if $b_log; + main::log_data('data',"memory: $memory") if $b_log; eval $end if $b_log; return $memory; } @@ -20993,7 +21516,7 @@ sub get_memory_data_linux { # procs memory page disks traps cpu # r b w avm fre flt re pi po fr sr wd0 wd1 int sys cs us sy id # 0 0 0 55256 1484092 171 0 0 0 0 0 2 0 12 460 39 3 1 96 -## openbsd 6.3? added in M, sigh... +## openbsd 6.3? added in M/G/T etc, sigh... # 2 57 55M 590M 789 0 0 0... ## freebsd: # procs memory page disks faults cpu @@ -21001,21 +21524,23 @@ sub get_memory_data_linux { # 0 0 0 21880M 6444M 924 32 11 0 822 827 0 0 853 832 463 8 3 88 # with -H # 2 0 0 14925812 936448 36 13 10 0 84 35 0 0 84 30 42 11 3 86 -## dragonfly +## dragonfly: V1, supported -H # procs memory page disks faults cpu # r b w avm fre flt re pi po fr sr ad0 ad1 in sy cs us sy id # 0 0 0 0 84060 30273993 2845 12742 1164 407498171 320960902 0 0 .... -sub get_memory_data_bsd { +## dragonfly: V2, no avm, no -H support +sub bsd_data { eval $start if $b_log; my ($type) = @_; my $memory = ''; - my ($avm,$av_pages,$cnt,$fre,$free_mem,$real_mem,$total) = (3,0,0,4,0,0,0); + my ($avm,$av_pages,$cnt,$fre,$free_mem,$mult,$real_mem,$total) = (0,0,0,0,0,0,0,0); my (@data,$message); - my $arg = ($bsd_type ne 'openbsd') ? '-H' : ''; - if (my $program = check_program('vmstat')){ + # 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 - # for K/M/G tests - my @vmstat = grabber("vmstat $arg 2>/dev/null",'\n','strip'); + # for K/M/G tests, note that -H not consistently supported, so don't use. + my @vmstat = main::grabber("vmstat 2>/dev/null",'\n','strip'); + main::log_data('dump','@vmstat',\@vmstat) if $b_log; my @header = split(/\s+/, $vmstat[1]); foreach ( @header){ if ($_ eq 'avm'){$avm = $cnt} @@ -21026,18 +21551,18 @@ sub get_memory_data_bsd { my $row = $vmstat[-1]; if ( $row ){ @data = split(/\s+/, $row); - # 6.3 introduced an M character, sigh. - if ($data[$avm] && $data[$avm] =~ /^([0-9]+)M$/){ - $data[$avm] = $1 * 1024; + # openbsd 6.3, dragonfly 5.x introduced an M / G character, sigh. + if ($avm > 0 && $data[$avm] && $data[$avm] =~ /^([0-9\.]+[KGMT])(iB|B)?$/){ + $data[$avm] = main::translate_size($1); } - if ($data[$fre] && $data[$fre] =~ /^([0-9]+)M$/){ - $data[$fre] = $1 * 1024; + if ($fre > 0 && $data[$fre] && $data[$fre] =~ /^([0-9\.]+[KGMT])(iB|B)?$/){ + $data[$fre] = main::translate_size($1);; } - # dragonfly can have 0 avg, but they may fix that so make test dynamic - if ($data[$avm] != 0){ - $av_pages = ($bsd_type ne 'openbsd') ? sprintf('%.1f',$data[$avm]/1024) : $data[$avm]; + # dragonfly can have 0 avg, or no avm, sigh, but they may fix that so make test dynamic + if ($avm > 0 && $data[$avm] != 0){ + $av_pages = ($bsd_type !~ /^(net|open)bsd$/) ? sprintf('%.1f',$data[$avm]/1024) : $data[$avm]; } - elsif ($data[$fre] != 0){ + elsif ($fre > 0 && $data[$fre] != 0){ $free_mem = sprintf('%.1f',$data[$fre]); } } @@ -21077,7 +21602,7 @@ sub get_memory_data_bsd { my $used = (!$free_mem) ? $av_pages : $real_mem - $free_mem; if ($type eq 'string'){ $used = sprintf("%.1f",$used/1024); - $memory = "$used/($error) MB"; + $memory = "$used/($error) MiB"; } else { $memory = "$error:$used:"; @@ -21088,10 +21613,8 @@ sub get_memory_data_bsd { 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'){ - $used = sprintf("%.1f",$used/1024); - $real_mem = sprintf("%.1f",$real_mem/1024); $percent = " ($percent)" if $percent; - $memory = "$used/$real_mem MB" . $percent; + $memory = sprintf("%.1f/%.1f MiB", $used/1024, $real_mem/1024) . $percent; } else { $memory = "$real_mem:$used:$percent:0"; @@ -21100,6 +21623,29 @@ sub get_memory_data_bsd { eval $end if $b_log; return $memory; } +# rasberry pi only +sub gpu_ram_arm { + eval $start if $b_log; + my ($gpu_ram) = (0); + if (my $program = main::check_program('vcgencmd')){ + # gpu=128M + # "VCHI initialization failed" - you need to add video group to your user + my $working = (main::grabber("$program get_mem gpu 2>/dev/null"))[0]; + $working = (split(/\s*=\s*/, $working))[1] if $working; + $gpu_ram = main::translate_size($working) if $working; + } + main::log_data('data',"gpu ram: $gpu_ram") if $b_log; + eval $end if $b_log; + return $gpu_ram; +} +# standard systems, not used currently, but maybe one day? +sub get_gpu_ram { + eval $start if $b_log; + my ($gpu_ram) = (0); + eval $end if $b_log; + return $gpu_ram; +} +} sub get_module_version { eval $start if $b_log; @@ -21134,7 +21680,8 @@ $counts{'total'} = 0; sub get { eval $start if $b_log; # $num passed by reference to maintain incrementing where requested - ($type,$num) = @_; + ($type,$num) = @_; + $loaded{'packages'} = 1; package_counts(); appimage_counts(); create_output(); @@ -21199,14 +21746,29 @@ sub package_counts { ['emerge','emerge','d','/var/db/pkg/*/*/',1,5,'\\/'], ['eopkg','eopkg','d','/var/lib/eopkg/package/*',1,5,'\\/'], ['guix-sys','guix','p','package -p "/run/current-system/profile" -I',1,0,''], - ['guix-usr','guix','p','package package -I',1,0,''], - ['pacman','pacman','p','-Qq --color never',1,0,''], + ['guix-usr','guix','p','package -I',1,0,''], + ['kiss','kiss','p','list',1,0,''], + ['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,'-'], + ['pacman','pacman','p','-Qq --color never',1,0,'', + '!main::check_program(\'pacman-g2\')'], # pacman-g2 has sym link to pacman ['pacman-g2','pacman-g2','p','-Q',1,0,''], ['pkg','pkg','d','/var/db/pkg/*',1,0,''], # 'pkg list' returns non programs ['pkg_info','pkg_info','p','',1,0,''], - ['pkgtool','pkgtool','d','/var/log/packages/*',1,4,'\\/'], + # like cards, avoid pkginfo directly due to python pm being so slow + # but pkgadd is also found in scratch + ['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','pkgtool','d','/var/lib/pkgtools/packages',1,4,'\\/', + '-d \'/var/lib/pkgtools/packages\''], + ['pkgtool','pkgtool','d','/var/log/packages/',1,5,'\\/', + '! -d \'/var/lib/pkgtools/packages\' && -d \'/var/log/packages/\''], # way too slow without nodigest/sig!! confirms packages exist ['rpm','rpm','p','-qa --nodigest --nosignature',1,0,''], + # scratch is a programming language too, with software called scratch + ['scratch','pkgbuild','d','/var/lib/scratchpkg/index/*/.pkginfo',1,5,'\\/', + '-d \'/var/lib/scratchpkg\''], # note',' slapt-get, spkg, and pkgtool all return the same count #['slapt-get','slapt-get','p','--installed',1,0,''], #['spkg','spkg','p','--installed',1,0,''], @@ -21214,6 +21776,7 @@ sub package_counts { # note: I believe mageia uses rpm internally but confirm # ['urpmi','urpmq','p','??',1,0,''], ['xbps','xbps-query','p','-l',1,1,''], + # ['xxx-brew','brew','p','--cellar',0,0,''], # verify how this works ['zzz-flatpak','flatpak','p','list',0,0,''], ['zzz-snap','snap','p','list',0,0,'','@ps_cmd && (grep {/\bsnapd\b/} @ps_cmd)'], ); @@ -21246,7 +21809,7 @@ sub appimage_counts { if (@ps_cmd && (grep {/\bappimaged\b/} @ps_cmd)){ @list = main::globber($ENV{'HOME'} . '/.local/bin/*.appimage'); $count = scalar @list; - $counts{'zzz-appimage'} = ([$$count,undef]) if $count; + $counts{'zzz-appimage'} = ([$count,undef]) if $count; $counts{'total'} += $count; } } @@ -21365,33 +21928,223 @@ sub get_self_version { eval $end if $b_log; return $self_version . $patch; } - -sub get_shell_data { +# Get ServiceData +{ +package ServiceData; +my ($key,$service,$type); +sub get { eval $start if $b_log; - my ($ppid) = @_; - my $cmd = "ps -p $ppid -o comm= 2>/dev/null"; - my $shell = qx($cmd); - log_data('cmd',$cmd) if $b_log; + ($type,$service) = @_; + my $value; + set() if !$loaded{'service-tool'}; + $key = (keys %service_tool)[0] if %service_tool; + if ($key){ + if ($type eq 'status'){ + $value = process_status(); + } + elsif ($type eq 'tool'){ + $value = $service_tool{$key}->[1]; + } + } + eval $end if $b_log; + return $value; +} +sub process_status { + eval $start if $b_log; + my ($cmd,$status,@data); + my ($result,$value) = ('',''); + my %translate = ( + 'active' => 'running', + 'down' => 'stopped', + 'fail' => 'not found', + 'failed' => 'not found', + 'inactive' => 'stopped', + 'ok' => 'running', + 'not running' => 'stopped', + 'run' => 'running', + 'started' => 'running', + ); + if ($key eq 'systemctl'){ + $cmd = "$service_tool{$key}->[0] status $service"; + } + # can be /etc/init.d or /etc/rc.d; ghostbsd/gentoo have this + elsif ($key eq 'rc-service'){ + $cmd = "$service_tool{$key}->[0] $service status"; + } + # dragonfly/netbsd/freebsd have this + elsif ($key eq 'service'){ + $cmd = "$service_tool{$key}->[0] $service status"; + } + # runit + elsif ($key eq 'sv'){ + $cmd = "$service_tool{$key}->[0] status $service"; + } + # check or status or onestatus (netbsd) + elsif ($key eq 'rc.d'){ + if (-e "$service_tool{$key}->[0]$service"){ + $status = ($bsd_type && $bsd_type =~ /(dragonfly)/) ? 'status' : 'check'; + $cmd = "$service_tool{$key}->[0]$service check"; + } + else { + $result = 'not found'; + } + } + elsif ($key eq 'init.d'){ + if (-e "$service_tool{$key}->[0]$service"){ + $cmd = "$service_tool{$key}->[0]$service status"; + } + else { + $result = 'not found'; + } + } + @data = main::grabber("$cmd 2>&1",'','strip') if $cmd; + #@data = ('bluetooth is running.'); + print "key: $key\n", Data::Dumper::Dumper \@data if $dbg[29]; + main::log_data('dump','service @data',\@data) if $b_log; + for my $row (@data){ + my @working = split(/\s*:\s*/,$row); + ($value) = (''); + # print "$working[0]::$working[1]\n"; + if ($working[0] eq 'Loaded'){ + # note: sshd shows ssh for ssh.service + $working[1] =~ /^(.+?)\s*\(.*?\.service;\s+(\S+?);.*/; + $result = lc($1) if $1; + $result = lc($2) if $2; # this will be enabled/disabled + } + elsif ($working[0] eq 'Active'){ + $working[1] =~ /^(.+?)\s*\((\S+?)\).*/; + $value = lc($1) if $1 && (!$result || $result ne 'disabled'); + $value = $translate{$value} if $value && $translate{$value}; + $result .= ", $value" if ($result && $value); + last; + } + # valid syntax, but service does not exist + # * rc-service: service 'ntp' does not exist :: + elsif ($row =~ /$service.*?(not (exist|(be )?found)|no such (directory|file)|unrecognized)/i){ + $result = 'not found'; + last; + } + # means command directive doesn't exist, we don't know if service exists or not + # * ntpd: unknown function 'disable' :: + elsif ($row =~ /unknown (directive|function)|Usage/i){ + last; + } + # rc-service: * status: started :: * status: stopped, fail handled in not exist test + elsif ($working[0] eq '* status' && $working[1]){ + $result = lc($working[1]); + $result = $translate{$result} if $translate{$result}; + last; + } + ## start exists status detections + elsif ($working[0] =~ /\b$service is ([a-z\s]+?)(\s+as\s.*|\s+\.\.\..*)?\.?$/){ + $result = lc($1); + $result = $translate{$result} if $translate{$result}; + last; + } + # runit sv: run/down/fail - fail means not found + # run: udevd: (pid 631) 641s :: down: sshd: 9s, normally up + elsif ($working[1] && $working[1] eq $service && $working[0] =~ /^([a-z]+)$/){ + $result = lc($1); + $result = $translate{$result} if $translate{$result}; + $result = "enabled,$result" if $working[2] && $working[2] =~ /normally up/i; + } + # OpenBSD: sshd(ok) + elsif ($working[0] =~ /\b$service\s*\(([^\)]+)\)/){ + $result = lc($1); + $result = $translate{$result} if $translate{$result}; + last; + } + } + print "service result: $result\n" if $dbg[29]; + main::log_data('data',"result: $result") if $b_log; + eval $end if $b_log; + return $result; +} +sub set { + eval $start if $b_log; + $loaded{'service-tool'} = 1; + my ($path); + if ($path = main::check_program('systemctl')){ + # systemctl status ssh :: Loaded: / Active: + %service_tool = ('systemctl' => [$path,'systemctl']); + } + elsif ($path = main::check_program('rc-service')){ + # rc-service ssh status :: * status: stopped + %service_tool = ('rc-service' => [$path,'rc-service']); + } + elsif ($path = main::check_program('service')){ + # service sshd status + %service_tool = ('service' => [$path,'service']); + } + elsif ($path = main::check_program('sv')){ + # service sshd status + %service_tool = ('sv' => [$path,'sv']); + } + # freebsd does not have 'check', netbsd does not have status + elsif (-d '/etc/rc.d/'){ + # /etc/rc.d/ssh check :: ssh(ok|failed) + %service_tool = ('rc.d' => ['/etc/rc.d/','/etc/rc.d']); + } + elsif (-d '/etc/init.d/'){ + # /etc/init.d/ssh status :: Loaded: loaded (...)/ Active: active (...) + %service_tool = ('init.d' => ['/etc/init.d/','/etc/init.d']); + } + eval $end if $b_log; +} +} +# $dbg[29] = 1; set_path(); print ServiceData::get('status','bluetooth'),"\n"; + +# Get ShellData +{ +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. +sub set { + eval $start if $b_log; + my ($cmd,$parent,$pppid,$shell); + $loaded{'shell-data'} = 1; + $cmd = "ps -wwp $ppid -o comm= 2>/dev/null"; + $shell = qx($cmd); + # we'll be using these $client pppid/parent values in shell_launcher() + $pppid = $client{'pppid'} = get_pppid($ppid); + $pppid ||= ''; + $client{'pppid'} ||= ''; + # print "sh: $shell\n"; + main::log_data('cmd',$cmd) if $b_log; chomp($shell); if ($shell){ - #print "shell pre: $shell\n"; + # print "shell pre: $shell\n"; # when run in debugger subshell, would return sh as shell, # and parent as perl, that is, pinxi itself, which is actually right. # trim leading /.../ off just in case. ps -p should return the name, not path # but at least one user dataset suggests otherwise so just do it for all. $shell =~ s/^.*\///; - my $working = $ENV{'SHELL'}; # NOTE: su -c "inxi -F" results in shell being su - if ($shell eq 'sudo' || $shell eq 'su' ){ - $client{'su-start'} = $shell; - $shell = get_shell_parent(get_start_parent($ppid)); + # but: su - results in $parent being su + my $i=0; + $parent = $client{'parent'} = parent_name($pppid) if $pppid; + $parent ||= ''; + print "1: shell: $shell $ppid parent: $parent $pppid\n" if $b_debug; + # this will fail in this case: sudo su -c 'inxi -Ia' + if ($shell =~ /^(doas|login|sudo|su)$/){ + $client{'su-start'} = $shell if $shell ne 'login'; + $shell = $parent if $parent; } + # eg: su to root, then sudo + elsif ($parent && $client{'parent'} =~ /^(doas|sudo|su)$/){ + $client{'su-start'} = $parent; + $parent = ''; + } + print "2: shell: $shell parent: $parent\n" if $b_debug; + my $working = $ENV{'SHELL'}; if ($working){ $working =~ s/^.*\///; -# if (($shell eq 'sh' || $shell eq 'sudo' || $shell eq 'su' ) && $shell ne $working){ -# $client{'su-start'} = $shell if ($shell eq 'sudo' || $shell eq 'su'); -# $shell = $working; -# } # a few manual changes for known # Note: parent when fizsh shows as zsh but SHELL is fizsh, but other times # SHELL is default shell, but in zsh, SHELL is default shell, not zfs @@ -21399,17 +22152,17 @@ sub get_shell_data { $shell = $working; } } - # print "shell post: $shell working: $working\n"; + #print "3: shell post: $shell working: $working\n"; # since there are endless shells, we'll keep a list of non program value # set shells since there is little point in adding those to program values - if (test_shell($shell)){ + if (shell_test($shell)){ # do nothing, just leave $shell as is } # note: not all programs return version data. This may miss unhandled shells! - elsif ((@app = program_data(lc($shell),lc($shell),1)) && $app[0]){ + elsif ((@app = main::program_data(lc($shell),lc($shell),1)) && $app[0]){ $shell = $app[0]; $client{'version'} = $app[1] if $app[1]; - #print "app test $shell v: $client{'version'}\n"; + print "3: app test $shell v: $client{'version'}\n" if $b_debug; } else { # NOTE: we used to guess here with position 2 --version but this cuold lead @@ -21420,34 +22173,34 @@ sub get_shell_data { # recognized as a known possible program #print "app not shell?: $shell\n"; if ($shell){ - # print 'shell: ' . $shell .' Start client version type: ', get_shell_parent(get_start_parent(getppid())), "\n"; - my $parent = get_shell_parent(get_start_parent($ppid)); + print "shell 4: $shell StartClientVersionType: $parent\n" if $b_debug; if ($parent){ - if (test_shell($parent)){ + if (shell_test($parent)){ $shell = $parent; } - elsif ((@app = program_data(lc($parent),lc($parent),0)) && $app[0]){ + elsif ((@app = main::program_data(lc($parent),lc($parent),0)) && $app[0]){ $shell = $app[0]; $client{'version'} = $app[1] if $app[1]; } - #print "shell3: $shell version: $client{'version'}\n"; + print "shell 5: $shell version: $client{'version'}\n" if $b_debug; } } else { - $client{'version'} = row_defaults('unknown-shell'); + $client{'version'} = main::row_defaults('unknown-shell'); } - #print "shell not app version: $client{'version'}\n"; + print "6: shell not app version: $client{'version'}\n" if $b_debug; } $client{'version'} ||= ''; $client{'version'} =~ s/(\(.*|-release|-version)// if $client{'version'}; + $shell =~ s/^[\s-]+|[\s-]+$//g if $shell; # sometimes will be like -sh $client{'name'} = lc($shell); $client{'name-print'} = $shell; - #print "shell4: $client{'name-print'} version: $client{'version'}\n"; + print "7: shell: $client{'name-print'} version: $client{'version'}\n" if $b_debug; if ($extra > 2 && $working && lc($shell) ne lc($working)){ - if (@app = program_data(lc($working))){ + if (@app = main::program_data(lc($working))){ $client{'default-shell'} = $app[0]; $client{'default-shell-v'} = $app[1]; - $client{'default-shell-v'} =~ s/(\(.*|-release|-version)// if $client{'default-shell-v'}; + $client{'default-shell-v'} =~ s/(\s*\(.*|-release|-version)// if $client{'default-shell-v'}; } else { $client{'default-shell'} = $working; @@ -21458,115 +22211,130 @@ sub get_shell_data { $client{'name'} = 'shell'; $client{'name-print'} = 'Unknown Shell'; } - $client{'su-start'} = 'sudo' if (!$client{'su-start'} && $ENV{'SUDO_USER'}); + if (!$client{'su-start'}){ + $client{'su-start'} = 'sudo' if $ENV{'SUDO_USER'}; + $client{'su-start'} = 'doas' if $ENV{'DOAS_USER'}; + } + if ($parent && $parent eq 'login'){ + $client{'su-start'} = ($client{'su-start'}) ? $client{'su-start'} . ',' . $parent: $parent; + } eval $end if $b_log; } +# 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; + my (@data); + my ($msg,$pppid,$shell_parent) = ('','',''); + $pppid = $client{'pppid'}; + if ($b_log){ + $msg = ($ppid) ? "pppid: $pppid ppid: $ppid": "ppid: undefined"; + main::log_data('data',$msg); + } + #print "self parent: $pppid ppid: $ppid\n"; + if ($pppid){ + $shell_parent = $client{'parent'}; + #print "shell parent 1: $shell_parent\n"; + if ($b_log){ + $msg = ($shell_parent) ? "shell parent 1: $shell_parent": "shell parent 1: undefined"; + main::log_data('data',$msg); + } + # in case sudo starts inxi, parent is shell (or perl inxi if run by debugger) + # so: perl (2) started pinxi with sudo (3) in sh (4) in terminal + my $shells = 'ash|bash|busybox|cicada|csh|dash|doas|elvish|fish|fizsh|ksh|ksh93|'; + $shells .= 'lksh|login|loksh|mksh|nash|oh|oil|osh|pdksh|perl|posh|'; + $shells .= 'su|sudo|tcsh|xonsh|yash|zsh'; + $shells .= shell_test('return'); + my $i = 0; + print "self::pppid-0: $pppid :: $shell_parent\n" if $b_debug; + # note that new shells not matched will keep this loop spinning until it ends. + # All we really can do about that is update with new shell name when we find them. + while ($i < 8 && $shell_parent && $shell_parent =~ /^($shells)$/){ + # bash > su > parent + $i++; + $pppid = get_pppid($pppid); + $shell_parent = parent_name($pppid); + print "self::pppid-${i}: $pppid :: $shell_parent\n" if $b_debug; + if ($b_log){ + $msg = ($shell_parent) ? "parent-$i: $shell_parent": "shell parent $i: undefined"; + main::log_data('data',$msg); + } + } + } + if ($b_log){ + $pppid ||= ''; + $shell_parent ||= ''; + main::log_data('data',"parents: pppid: $pppid parent-name: $shell_parent"); + } + eval $end if $b_log; + return $shell_parent; +} +# arg: 1 - parent id +# returns SID/start ID +sub get_pppid { + eval $start if $b_log; + my ($ppid) = @_; + return 0 if !$ppid; + # ps -j -fp : some bsds ps do not have -f for PPID, so we can't get the ppid + my $cmd = "ps -wwjfp $ppid 2>/dev/null"; + main::log_data('cmd',$cmd) if $b_log; + my @data = main::grabber($cmd); + #shift @data if @data; + my $pppid = main::awk(\@data,"$ppid",3,'\s+'); + eval $end if $b_log; + return $pppid; +} +# arg: 1 - parent id +# returns parent command name +sub parent_name { + eval $start if $b_log; + my ($ppid) = @_; + return '' if !$ppid; + my ($parent_name); + my $cmd = "ps -wwjp $ppid 2>/dev/null"; + main::log_data('cmd',$cmd) if $b_log; + my @data = main::grabber($cmd,'','strip'); + # dump the headers if they exist + $parent_name = (grep {/$ppid/} @data)[0] if @data; + if ($parent_name){ + # we don't want to worry about column position, just slice off all + # the first part before the command + $parent_name =~ s/^.*[0-9]+:[0-9\.]+\s+//; + # then get the command + $parent_name = (split(/\s+/,$parent_name))[0]; + # get rid of /../ path info if present + $parent_name =~ s|^.*/|| if $parent_name; + # to work around a ps -p or gnome-terminal bug, which returns + # gnome-terminal- trim -/_ off start/end; _su, etc, which breaks detections + $parent_name =~ s/^[_-]|[_-]$//g; + } + eval $end if $b_log; + return $parent_name; +} # 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 -sub test_shell { +# $1 - return|[shell name to test +# returns test list OR shell name/'' +sub shell_test { my ($test) = @_; - # not verified or tested - my $shells = 'apush|ccsh|ch|esh|eshell|heirloom|hush|'; + # these shells are not verified or tested + my $shells = 'apush|ccsh|ch|esh?|eshell|heirloom|hush|'; $shells .= 'ion|imrsh|larryshell|mrsh|msh(ell)?|murex|nsh|nu(shell)?|'; - $shells .= 'psh|pwsh|pysh(ell)?|rush|sash|'; - # tested shells with no version info discovered + $shells .= 'oksh|psh|pwsh|pysh(ell)?|rush|sash|xsh?|'; + # these shells are tested and have no version info $shells .= 'es|rc|scsh|sh'; return '|' . $shells if $test eq 'return'; return ($test =~ /^($shells)$/) ? $test : ''; } - -sub get_shell_source { - eval $start if $b_log; - my (@data); - my ($msg,$self_parent,$shell_parent) = ('','',''); - my $ppid = getppid(); - $self_parent = get_start_parent($ppid); - if ($b_log){ - $msg = ($ppid) ? "self parent: $self_parent ppid: $ppid": "self parent: undefined"; - log_data('data',$msg); - } - #print "self parent: $self_parent ppid: $ppid\n"; - if ($self_parent){ - $shell_parent = get_shell_parent($self_parent); - $client{'su-start'} = $shell_parent if ($shell_parent eq 'su' && !$client{'su-start'}); - #print "shell parent 1: $shell_parent\n"; - if ($b_log){ - $msg = ($shell_parent) ? "shell parent 1: $shell_parent": "shell parent 1: undefined"; - log_data('data',$msg); - } - # in case sudo starts inxi, parent is shell (or perl inxi if run by debugger) - # so: perl (2) started pinxi with sudo (3) in sh (4) in terminal - my $shells = 'ash|bash|busybox|cicada|csh|dash|elvish|fish|fizsh|ksh|ksh93|'; - $shells .= 'lksh|loksh|mksh|nash|oh|oil|osh|pdksh|perl|posh|'; - $shells .= 'su|sudo|tcsh|xonsh|yash|zsh'; - $shells .= test_shell('return'); - for my $i (2..4){ - if ( $shell_parent && $shell_parent =~ /^($shells)$/ ){ - # no idea why have to do script_parent action twice in su case, but you do. - $self_parent = get_start_parent($self_parent); - $shell_parent = get_shell_parent($self_parent); - #print "self::shell parent 2-${i}: $self_parent :: $shell_parent\n"; - if ($b_log){ - $msg = ($shell_parent) ? "shell parent $i: $shell_parent": "shell parent $i: undefined"; - log_data('data',$msg); - } - } - else { - last; - } - } - # to work around a ps -p or gnome-terminal bug, which returns - # gnome-terminal- trim - off end - $shell_parent =~ s/-$// if $shell_parent; - } - if ($b_log){ - $self_parent ||= ''; - $shell_parent ||= ''; - log_data('data',"parents: self: $self_parent shell: $shell_parent"); - } - eval $end if $b_log; - return $shell_parent; -} - -# utilities for get_shell_source -# arg: 1 - parent id -sub get_start_parent { - eval $start if $b_log; - my ($parent) = @_; - return 0 if !$parent; - # ps -j -fp : bsds ps do not have -f for PPID, so we can't get the ppid - my $cmd = "ps -j -fp $parent 2>/dev/null"; - log_data('cmd',$cmd) if $b_log; - my @data = grabber($cmd); - #shift @data if @data; - my $self_parent = awk(\@data,"$parent",3,'\s+'); - eval $end if $b_log; - return $self_parent; -} - -# arg: 1 - parent id -sub get_shell_parent { - eval $start if $b_log; - my ($parent) = @_; - return '' if !$parent; - my $cmd = "ps -j -p $parent 2>/dev/null"; - log_data('cmd',$cmd) if $b_log; - my @data = grabber($cmd,'','strip'); - #shift @data if @data; - my $shell_parent = awk(\@data, "$parent",-1,'\s+'); - eval $end if $b_log; - return $shell_parent; -} - # this will test against default IP like: (:0) vs full IP to determine # ssh status. Surprisingly easy test? Cross platform -sub get_ssh_status { +sub ssh_status { eval $start if $b_log; my ($b_ssh,$ssh); # fred pts/10 2018-03-24 16:20 (:0.0) # fred-remote pts/1 2018-03-27 17:13 (43.43.43.43) - if (my $program = check_program('who')){ - $ssh = (grabber("$program am i 2>/dev/null"))[0]; + if (my $program = main::check_program('who')){ + $ssh = (main::grabber("$program am i 2>/dev/null"))[0]; # crude IP validation if ($ssh && $ssh =~ /\(([:0-9a-f]{8,}|[1-9][\.0-9]{6,})\)$/){ $b_ssh = 1; @@ -21575,6 +22343,7 @@ sub get_ssh_status { eval $end if $b_log; return $b_ssh; } +} sub get_tty_console_irc { eval $start if $b_log; @@ -21584,7 +22353,6 @@ sub get_tty_console_irc { $tty_session = $ENV{'XDG_VTNR'}; } else { - my $ppid = getppid(); $tty_session = awk(\@ps_aux,".*$ppid.*$client{'name'}",7,'\s+'); $tty_session =~ s/^[^[0-9]+// if $tty_session; } @@ -21597,35 +22365,51 @@ sub get_tty_console_irc { sub get_tty_number { eval $start if $b_log; my ($tty); - if ( defined $ENV{'XDG_VTNR'} ){ - $tty = $ENV{'XDG_VTNR'}; + # note: ttyname returns undefined if pinxi is > redirected output + # variants: /dev/pts/1 /dev/tty1 /dev/ttyp2 /dev/ttyra [hex number a] + $tty = POSIX::ttyname(1); + # but tty direct works fine in that case + if (!defined $tty && (my $program = check_program('tty'))){ + chomp($tty = qx($program 2>/dev/null)); + } + if (defined $tty){ + $tty =~ s/^\/dev\/(tty)?//; } else { - $tty = POSIX::ttyname(1); - #variants: /dev/pts/1 /dev/tty1 /dev/ttyp2 /dev/ttyra [hex number a] - $tty =~ s/.*\/[^0-9]*//g if defined $tty; + $tty = ''; + } + # systemd only item, usually same as tty in console, not defined + # for root or non systemd systems. + if (defined $ENV{'XDG_VTNR'} && $tty ne '' && $ENV{'XDG_VTNR'} ne $tty){ + $tty = "$tty (vt $ENV{'XDG_VTNR'})"; + } + elsif ($tty eq '' && defined $ENV{'XDG_VTNR'}) { + $tty = $ENV{'XDG_VTNR'}; } - $tty = '' if ! defined $tty; log_data('data',"tty:$tty") if $b_log; eval $end if $b_log; return $tty; } -# 2:58PM up 437 days, 8:18, 3 users, load averages: 2.03, 1.72, 1.77 -# 04:29:08 up 3:18, 3 users, load average: 0,00, 0,00, 0,00 -# 10:23PM up 5 days, 16:17, 1 user, load averages: 0.85, 0.90, 1.00 -# 05:36:47 up 1 day, 3:28, 4 users, load average: 1,88, 0,98, 0,62 -# 05:36:47 up 1 day, 3 min, 4 users, load average: 1,88, 0,98, 0,62 -# 04:41:23 up 2:16, load average: 7.13, 6.06, 3.41 # root openwrt sub get_uptime { eval $start if $b_log; - my ($days,$hours,$minutes,$uptime) = ('','','',''); + my ($days,$hours,$minutes,$seconds,$uptime) = ('','','','',''); if (check_program('uptime')){ $uptime = qx(uptime); $uptime = trimmer($uptime); - #$uptime = '05:36:47 up 3 min, 4 users, load average: 1,88, 0,98, 0,62'; + if ($fake{'uptime'}){ + # $uptime = '2:58PM up 437 days, 8:18, 3 users, load averages: 2.03, 1.72, 1.77'; + # $uptime = '04:29:08 up 3:18, 3 users, load average: 0,00, 0,00, 0,00'; + # $uptime = '10:23PM up 5 days, 16:17, 1 user, load averages: 0.85, 0.90, 1.00'; + # $uptime = '05:36:47 up 1 day, 3:28, 4 users, load average: 1,88, 0,98, 0,62'; + # $uptime = '05:36:47 up 1 day, 3 min, 4 users, load average: 1,88, 0,98, 0,62'; + # $uptime = '04:41:23 up 2:16, load average: 7.13, 6.06, 3.41 # root openwrt'; + # $uptime = '9:51 PM up 2 mins, 1 user, load average: 0:58, 0.27, 0.11'; + # $uptime = '05:36:47 up 3 min, 4 users, load average: 1,88, 0,98, 0,62'; + # $uptime = '9:51 PM up 49 secs, 1 user, load average: 0:58, 0.27, 0.11'; + } if ($uptime && - $uptime =~ /[\S]+\s+up\s+(([0-9]+)\s+day[s]?,\s+)?(([0-9]{1,2}):([0-9]{1,2})|([0-9]+)\smin[s]?),\s+([0-9]+\s+user|load average)/){ + $uptime =~ /[\S]+\s+up\s+(([0-9]+)\s+day[s]?,\s+)?(([0-9]{1,2}):([0-9]{1,2})|([0-9]+)\smin[s]?|([0-9]+)\ssec[s]?),\s+([0-9]+\s+user|load average)/){ $days = $2 . 'd' if $2; $days .= ' ' if ($days && ($4 || $6)); if ($4 && $5){ @@ -21634,9 +22418,11 @@ sub get_uptime { } elsif ($6){ $minutes = $6 . 'm'; - } - $uptime = $days . $hours . $minutes; + elsif ($7){ + $seconds = $7 . 's'; + } + $uptime = $days . $hours . $minutes . $seconds; } } $uptime ||= 'N/A'; @@ -21655,14 +22441,14 @@ sub get_wakeups { } #### ------------------------------------------------------------------- -#### SET DATA VALUES +#### SET DATA VALUES - used to set data for program features #### ------------------------------------------------------------------- # android only, for distro / OS id and machine data sub set_build_prop { eval $start if $b_log; my $path = '/system/build.prop'; - $b_build_prop = 1; + $loaded{'build-prop'} = 1; return if ! -r $path; my @data = reader($path,'strip'); foreach (@data){ @@ -21705,7 +22491,7 @@ sub set_build_prop { } } log_data('dump','%build_prop',\%build_prop) if $b_log; - print Dumper \%build_prop if $test[20]; + print Dumper \%build_prop if $dbg[20]; eval $end if $b_log; } @@ -21729,15 +22515,15 @@ sub set_build_prop { ## DeviceData / PCI / SOC { package DeviceData; -my (@data,@devices,@files,@full_names,@pcis,@temp,@temp2,@temp3); - +my (@bluetooth,@devices,@files,@full_names,@pcis,@temp,@temp2,@temp3); +my ($b_bt_check); my ($busid,$busid_nu,$chip_id,$content,$device,$driver,$driver_nu,$file, $handle,$modules,$port,$rev,$temp,$type,$type_id,$vendor,$vendor_id); sub set { eval $start if $b_log; - $_[0] = 1; # check boolean passed by reference - if ( $b_pci ){ + ${$_[0]} = 1; # set check by reference + if ($use{'pci'}){ if (!$bsd_type){ if ($alerts{'lspci'}->{'action'} eq 'use' ){ lspci_data(); @@ -21757,9 +22543,13 @@ sub set { elsif ($alerts{'pcidump'}->{'action'} eq 'use'){ pcidump_data(); } + elsif ($alerts{'pcictl'}->{'action'} eq 'use'){ + pcictl_data(); + } } - if ($test[9]){ + if ($dbg[9]){ print Data::Dumper::Dumper \@devices_audio; + print Data::Dumper::Dumper \@devices_bluetooth; print Data::Dumper::Dumper \@devices_graphics; print Data::Dumper::Dumper \@devices_network; print Data::Dumper::Dumper \@devices_hwraid; @@ -21768,6 +22558,7 @@ sub set { } if ( $b_log){ main::log_data('dump','@devices_audio',\@devices_audio); + main::log_data('dump','@devices_bluetooth',\@devices_bluetooth); main::log_data('dump','@devices_graphics',\@devices_graphics); main::log_data('dump','@devices_hwraid',\@devices_hwraid); main::log_data('dump','@devices_network',\@devices_network); @@ -21781,7 +22572,7 @@ sub set { sub lspci_data { eval $start if $b_log; my ($subsystem,$subsystem_id); - @data = pci_grabber('lspci'); + my @data = pci_grabber('lspci'); #print Data::Dumper::Dumper \@data; foreach (@data){ #print "$_\n"; @@ -21827,7 +22618,7 @@ sub lspci_data { $device = main::cleaner($device); $temp[0] =~ /\[([^\]]+)\]$/; $type_id = $1; - $b_hardware_raid = 1 if $type_id eq '0104'; + $use{'hardware-raid'} = 1 if $type_id eq '0104'; $type = lc($type); $type = main::pci_cleaner($type,'pci'); $type =~ s/\s+$//; @@ -21835,7 +22626,7 @@ sub lspci_data { ($driver,$driver_nu,$modules,$subsystem,$subsystem_id) = ('','','','',''); } } - print Data::Dumper::Dumper \@devices if $test[4]; + print Data::Dumper::Dumper \@devices if $dbg[4]; main::log_data('dump','lspci @devices',\@devices) if $b_log; eval $end if $b_log; } @@ -21847,7 +22638,7 @@ sub lspci_data { # subclass = ethernet sub pciconf_data { eval $start if $b_log; - @data = pci_grabber('pciconf'); + my @data = pci_grabber('pciconf'); foreach (@data){ if ($driver){ if ($_ =~ /^~$/) { @@ -21881,31 +22672,46 @@ sub pciconf_data { $type = (split(/\s+=\s+/, $_))[1]; } } - elsif (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}).*class=([^\s]+)\scard=([^\s]+)\schip=([^\s]+)\srev=([^\s]+)/){ + # atapci0@pci0:0:1:1: class=0x01018a card=0x00000000 chip=0x71118086 rev=0x01 hdr=0x00 + # pre freebsd 13. + elsif (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}).*class=0x([\S]{4})\S*\scard=0x([\S]+)\schip=0x([\S]+)\srev=0x([\S]+)/){ + $driver = $1; + $busid = $2; + $busid_nu = $3; + $type_id = $4; # we don't use the sub sub class part of the id, just first 4 + #$vendor_id = $5; + $vendor_id = substr($6,4,4); + $chip_id = substr($6,0,4); + $rev = $7; + $driver =~ s/(^[a-z]+)([0-9]+$)//; + $driver = $1; + $driver_nu = $2; + ($device,$type,$vendor) = ('','',''); + } + # isab0@pci0:0:1:0: class=0x060100 rev=0x00 hdr=0x00 vendor=0x8086 device=0x7000 subvendor=0x0000 subdevice=0x0000 + # freebsd 13 changes. + elsif (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}).*class=0x([0-9a-f]{4})[\S]*\srev=0x([\S]+)\shdr=0x([^\s]+)\svendor=0x([\S]+)\sdevice=0x([\S]+)(\ssubvendor=0x([\S]+)\ssubdevice=0x([\S]+))?/){ $driver = $1; $busid = $2; $busid_nu = $3; $type_id = $4; - #$vendor_id = $5; - $vendor_id = substr($6,6,4); - $chip_id = substr($6,2,4); - $rev = $7; + $rev = $5; + $vendor_id = $7; + $chip_id = $8; $driver =~ /(^[a-z]+)([0-9]+$)/; $driver = $1; $driver_nu = $2; - # convert to 4 character, strip off 0x, and last trailing sub sub class. - $type_id =~ s/^(0x)?([0-9a-f]{4}).*/$2/ if $type_id; ($device,$type,$vendor) = ('','',''); } } - print Data::Dumper::Dumper \@devices if $test[4]; + print Data::Dumper::Dumper \@devices if $dbg[4]; main::log_data('dump','pciconf @devices',\@devices) if $b_log; eval $end if $b_log; } sub pcidump_data { eval $start if $b_log; - @data = pci_grabber('pcidump'); + my @data = pci_grabber('pcidump'); foreach (@data){ if ($_ =~ /^~$/ && $busid && $device) { @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, @@ -21920,19 +22726,61 @@ sub pcidump_data { $busid_nu = $2; $device = main::cleaner($3); } - elsif ($_ =~ /^0x[\S]{4}: Vendor ID: ([0-9a-f]{4}) Product ID: ([0-9a-f]{4})/ ){ + elsif ($_ =~ /^0x[\S]{4}:\s+Vendor ID:\s+([0-9a-f]{4}),?\s+Product ID:\s+([0-9a-f]{4})/ ){ $vendor_id = $1; $chip_id = $2; } - elsif ($_ =~ /^0x[\S]{4}: Class: ([0-9a-f]{2}) Subclass: ([0-9a-f]{2}) Interface: ([0-9a-f]+) Revision: ([0-9a-f]+)/){ + elsif ($_ =~ /^0x[\S]{4}:\s+Class:\s+([0-9a-f]{2})(\s[^,]+)?,?\s+Subclass:\s+([0-9a-f]{2})(\s+[^,]+)?,?(\s+Interface: ([0-9a-f]+),?\s+Revision: ([0-9a-f]+))?/){ $type = pci_class($1); - $type_id = "$1$2"; + $type_id = "$1$3"; } } - print Data::Dumper::Dumper \@devices if $test[4]; + print Data::Dumper::Dumper \@devices if $dbg[4]; main::log_data('dump','pcidump @devices',\@devices) if $b_log; eval $end if $b_log; } +sub pcictl_data { + eval $start if $b_log; + my @data = pci_grabber('pcictl'); + my @data2 = pci_grabber('pcictl-n'); + foreach (@data){ + if ($_ =~ /^~$/ && $busid && $device) { + @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu); + assign_data('pci',\@temp); + ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, + $rev,$port,$driver,$modules,$driver_nu) = undef; + next; + } + # it's too fragile to get these in one matching so match, trim, next match + if (/\s+\[([^\]0-9]+)([0-9]+)\]$/){ + $driver = $1; + $driver_nu = $2; + $_ =~ s/\s+\[[^\]]+\]$//; + } + if (/\s+\(.*?(revision 0x([^\)]+))?\)/){ + $rev = $2 if $2; + $_ =~ s/\s+\([^\)]+?\)$//; + } + if ($_ =~ /^([0-9a-f:]+):([0-9]+):\s+([^.]+?)$/i){ + $busid = $1; + $busid_nu = $2; + $device = main::cleaner($3); + my $working = (grep {/^${busid}:${busid_nu}:\s/} @data2)[0]; + if ($working && + $working =~ /^${busid}:${busid_nu}:\s+0x([0-9a-f]{4})([0-9a-f]{4})\s+\(0x([0-9a-f]{2})([0-9a-f]{2})[0-9a-f]+\)/){ + $vendor_id = $1; + $chip_id = $2; + $type = pci_class($3); + $type_id = "$3$4"; + } + } + } + print Data::Dumper::Dumper \@devices if $dbg[4]; + main::log_data('dump','pcidump @devices',\@devices) if $b_log; + eval $end if $b_log; +} + sub pci_grabber { eval $start if $b_log; my ($program) = @_; @@ -21952,14 +22800,27 @@ sub pci_grabber { $path = $alerts{'pcidump'}->{'path'}; $pattern = '^[0-9a-f]+:'; } - @data = main::grabber("$path $args 2>/dev/null",'','strip'); - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pciconf/pci-freebsd-8.2-2"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcidump/pci-openbsd-6.1-vm.txt"; - #my $file = "$ENV{HOME}/bin/scripts/inxi/data/lspci/racermach-1-knnv.txt"; - #my $file = "$ENV{HOME}/bin/scripts/inxi/data/lspci/rk016013-knnv.txt"; - #@data = main::reader($file,'strip'); + elsif ($program eq 'pcictl'){ + $args = ' pci0 list -N'; + $path = $alerts{'pcictl'}->{'path'}; + $pattern = '^[0-9a-f:]+:'; + } + elsif ($program eq 'pcictl-n'){ + $args = ' pci0 list -n'; + $path = $alerts{'pcictl'}->{'path'}; + $pattern = '^[0-9a-f:]+:'; + } + my @data = main::grabber("$path $args 2>/dev/null",'','strip'); + if ($fake{'pciconf'} || $fake{'pcictl'} || $fake{'pcidump'}){ + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pciconf/pci-freebsd-8.2-2"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcidump/pci-openbsd-6.1-vm.txt"; + my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcictl/pci-netbsd-9.1-vm.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/racermach-1-knnv.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/rk016013-knnv.txt"; + @data = main::reader($file,'strip'); + } if (@data){ - $b_pci_tool = 1 if scalar @data > 10; + $use{'pci-tool'} = 1 if scalar @data > 10; foreach (@data){ if ($_ =~ /$pattern/i){ push(@working, '~'); @@ -21968,7 +22829,7 @@ sub pci_grabber { } push(@working, '~'); } - #print Data::Dumper::Dumper \@working; + print Data::Dumper::Dumper \@working if $dbg[30]; eval $end if $b_log; return @working; } @@ -21978,7 +22839,7 @@ sub soc_data { soc_devices_files(); soc_devices(); soc_devicetree(); - print Data::Dumper::Dumper \@devices if $test[4]; + print Data::Dumper::Dumper \@devices if $dbg[4]; main::log_data('dump','soc @devices',\@devices) if $b_log; eval $end if $b_log; } @@ -22002,12 +22863,22 @@ sub soc_data { # 10: /sys/devices/vio/71000002/uevent:["DRIVER=ibmveth", "OF_NAME=l-lan" # 11: /sys/devices/platform/soc:/soc:i2c-hdmi:/i2c-2/2-0050/uevent:['OF_NAME=hdmiddc' # 12: /sys/devices/platform/soc:/soc:i2c-hdmi:/uevent:['DRIVER=i2c-gpio', 'OF_NAME=i2c-hdmi' +# 13: /sys/devices/platform/scb/fd580000.ethernet/uevent +# 14: /sys/devices/platform/soc/fe300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1/uevent (wifi, pi 3,4) +# 15: Pi BT: /sys/devices/platform/soc/fe201000.serial/uevent +# 16: Pi BT: /sys/devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0 sub soc_devices_files { eval $start if $b_log; if (-d '/sys/devices/platform/'){ @files = main::globber('/sys/devices/platform/soc*/*/uevent'); @temp2 = main::globber('/sys/devices/platform/soc*/*/*/uevent'); push(@files,@temp2) if @temp2; + if (-e '/sys/devices/platform/scb'){ + @temp2 = main::globber('/sys/devices/platform/scb/*/uevent'); + push(@files,@temp2) if @temp2; + @temp2 = main::globber('/sys/devices/platform/scb/*/*/uevent'); + push(@files,@temp2) if @temp2; + } @temp2 = main::globber('/sys/devices/platform/*/uevent'); push(@files,@temp2) if @temp2; } @@ -22027,9 +22898,11 @@ sub soc_devices_files { main::uniq(\@files); eval $end if $b_log; } + sub soc_devices { eval $start if $b_log; my (@working); + set_bluetooth() if !$b_bt_check; foreach $file (@files){ next if -z $file; $chip_id = $file; @@ -22065,6 +22938,11 @@ sub soc_devices { # it's worthless, we can't use it next if ! defined $type; $type_id = $type; + if (@bluetooth && $type eq 'serial'){ + my $file_temp = $file; + $file_temp =~ s/uevent$//; + $type = 'bluetooth' if grep {/$file_temp/} @bluetooth; + } $chip_id = '' if ! defined $chip_id; $vendor_id = '' if ! defined $vendor_id; $driver = '' if ! defined $driver; @@ -22075,6 +22953,7 @@ sub soc_devices { @temp3 = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,$rev, $port,$driver,$modules,'','','',$handle); assign_data('soc',\@temp3); + main::log_data('dump','soc devices: @devices @temp3',\@temp3) if $b_log; } eval $end if $b_log; } @@ -22084,6 +22963,7 @@ sub soc_devicetree { if (-d '/sys/firmware/devicetree/base/soc'){ @files = main::globber('/sys/firmware/devicetree/base/soc/*/compatible'); my $test = (@full_names) ? join('|', sort @full_names) : 'xxxxxx'; + set_bluetooth() if !$b_bt_check; foreach $file (@files){ if ( $file !~ m%$test%){ ($handle,$content,$device,$type,$type_id,$vendor_id) = ('','','','','',''); @@ -22093,6 +22973,11 @@ sub soc_devicetree { next if !$type || !$content; $handle = $2 if $2; $type_id = $type; + if (@bluetooth && $type eq 'serial'){ + my $file_temp = $file; + $file_temp =~ s/uevent$//; + $type = 'bluetooth' if grep {/$file_temp/} @bluetooth; + } if ($content){ @temp3 = split(',', $content); $vendor_id = $temp3[0]; @@ -22103,38 +22988,46 @@ sub soc_devicetree { $type = soc_type($type,$vendor_id,''); @temp3 = ($type,$type_id,0,0,$device,$vendor_id,'soc','','','','','','','',$handle); assign_data('soc',\@temp3); - main::log_data('dump','@devices @temp3',\@temp3) if $b_log; + main::log_data('dump','devicetree: @devices @temp3',\@temp3) if $b_log; } } } eval $end if $b_log; } +sub set_bluetooth { + # special case of pi bt on ttyAMA0 + $b_bt_check = 1; + @bluetooth = main::globber('/sys/class/bluetooth/*') if -e '/sys/class/bluetooth'; + @bluetooth = map {$_ = Cwd::abs_path($_);$_} @bluetooth if @bluetooth; + @bluetooth = grep {!/usb/} @bluetooth if @bluetooth; # we only want non usb bt + main::log_data('dump','soc bt: @bluetooth', \@bluetooth) if $b_log; +} sub assign_data { my ($tool,$data) = @_; if (check_graphics($data->[0],$data->[1])){ push(@devices_graphics,[@$data]); - $b_soc_gfx = 1 if $tool eq 'soc'; + $use{'soc-gfx'} = 1 if $tool eq 'soc'; } # for hdmi, we need gfx/audio both if (check_audio($data->[0],$data->[1])){ push(@devices_audio,[@$data]); - $b_soc_audio = 1 if $tool eq 'soc'; + $use{'soc-audio'} = 1 if $tool eq 'soc'; } if (check_bluetooth($data->[0],$data->[1])){ push(@devices_bluetooth,[@$data]); - $b_soc_bluetooth = 1 if $tool eq 'soc'; + $use{'soc-bluetooth'} = 1 if $tool eq 'soc'; } elsif (check_hwraid($data->[0],$data->[1])){ push(@devices_hwraid,[@$data]); - $b_soc_net = 1 if $tool eq 'soc'; + $use{'soc-hwraid'} = 1 if $tool eq 'soc'; } elsif (check_network($data->[0],$data->[1])){ push(@devices_network,[@$data]); - $b_soc_net = 1 if $tool eq 'soc'; + $use{'soc-network'} = 1 if $tool eq 'soc'; } elsif (check_timer($data->[0],$data->[1])){ push(@devices_timer,[@$data]); - $b_soc_timer = 1; + $use{'soc-timer'} = 1 if $tool eq 'soc'; } # not used at this point, -M comes before ANG # $device_vm = check_vm($data[4]) if ( (!$b_ppc && !$b_mips) && !$device_vm ); @@ -22203,6 +23096,7 @@ sub soc_type { ($driver && $driver =~ /(audio|snd|sound)/i) ){ $type = 'audio'; } + # no need for bluetooth since that's only found in pi, handled above elsif ($type =~ /^((meson-?)?fb|disp|display(-[^\s]+)?|gpu|.*mali|vpu)$/i){ $type = 'display'; } @@ -22210,7 +23104,7 @@ sub soc_type { elsif ($type =~ /^(([^\s]+-)?eth|ethernet(-[^\s]+)?|lan|l-lan)$/i){ $type = 'ethernet'; } - elsif ($type =~ /^(.*wlan.*|.*wifi.*)$/i){ + elsif ($type =~ /^(.*wlan.*|.*wifi.*|.*mmcnr.*)$/i){ $type = 'wifi'; } # needs to catch variants like hdmi-tx but not hdmi-connector @@ -22258,10 +23152,10 @@ sub pci_class { sub set_dmesg_boot_data { eval $start if $b_log; + ${$_[0]} = 1; # set check boolean by reference my ($file,@temp); my ($counter) = (0); - $b_dmesg_boot_check = 1; - if (!$b_fake_dboot){ + if (!$fake{'dboot'}){ $file = system_files('dmesg-boot'); } else { @@ -22271,11 +23165,16 @@ sub set_dmesg_boot_data { ## matches: toshiba: openbsd-5.6-sysctl-2.txt #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-5.6-dmesg.boot-1.txt"; ## matches: compaq: openbsd-5.6-sysctl-1.txt" - $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-dmesg.boot-1.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmesg-boot/openbsd-dmesg.boot-1.txt"; } if ($file){ return if ! -r $file; @dmesg_boot = reader($file); + my @dmesg = grabber('dmesg 2>/dev/null'); + # clear out for netbsd, only 1 space following or lines won't match + @dmesg = map {$_ =~ s/^\[[^\]]+\]\s//;$_} @dmesg; + push(@dmesg_boot,'~~~~~',@dmesg); + uniq(\@dmesg_boot); # get rid of duplicate lines # some dmesg repeats, so we need to dump the second and > iterations # replace all indented items with ~ so we can id them easily while # processing note that if user, may get error of read permissions @@ -22296,28 +23195,29 @@ sub set_dmesg_boot_data { } @dmesg_boot = @temp; # FreeBSD: 'da*' is a USB device 'ada*' is a SATA device 'mmcsd*' is an SD card - if ($b_dm_boot_disk && @dmesg_boot){ + # OpenBSD: 'sd' is usb device, 'wd' normal drive + if ($use{'dm-boot-disk'} && @dmesg_boot){ @dm_boot_disk = grep {/^(ad|ada|da|mmcblk|mmcsd|nvme[0-9]+n|sd|wd)[0-9]+(:|\sat\s)/} @dmesg_boot; log_data('dump','@dm_boot_disk',\@dm_boot_disk) if $b_log; - print Dumper \@dm_boot_disk if $test[11]; + print Dumper \@dm_boot_disk if $dbg[11]; } - if ($b_dm_boot_optical && @dmesg_boot){ + if ($use{'dm-boot-optical'} && @dmesg_boot){ @dm_boot_optical = grep {/^(cd)[0-9]+(\([^)]+\))?(:|\sat\s)/} @dmesg_boot; log_data('dump','@dm_boot_optical',\@dm_boot_optical) if $b_log; - print Dumper \@dm_boot_optical if $test[11]; + print Dumper \@dm_boot_optical if $dbg[11]; } } - log_data('dump','@dmesg_boot',\@dmesg_boot) if $b_log; - #print Dumper \@dmesg_boot if $test[11]; + log_data('dump','@dmesg_boot full',\@dmesg_boot) if $b_log; + print Dumper \@dmesg_boot if $dbg[11]; eval $end if $b_log; } # note, all actual tests have already been run in check_tools so if we # got here, we're good. -sub set_dmi_data { +sub set_dmicode_data { eval $start if $b_log; - $_[0] = 1; # check boolean passed by reference - if ($b_fake_dmidecode || $alerts{'dmidecode'}->{'action'} eq 'use' ){ + ${$_[0]} = 1; # set check boolean by reference + if ($fake{'dmidecode'} || $alerts{'dmidecode'}->{'action'} eq 'use' ){ set_dmidecode_data(); } eval $end if $b_log; @@ -22326,7 +23226,7 @@ sub set_dmi_data { sub set_dmidecode_data { eval $start if $b_log; my ($content,@data,@working,$type,$handle); - if ($b_fake_dmidecode){ + if ($fake{'dmidecode'}){ my $file; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/pci-freebsd-8.2-2"; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-loki-1.txt"; @@ -22335,9 +23235,9 @@ sub set_dmidecode_data { #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-vmware-ram-1.txt"; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-tyan-4408.txt"; #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-1.txt"; - $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-2.txt"; - open(my $fh, '<', $file) or die "can't open $file: $!"; - chomp(@data = <$fh>); + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-2.txt"; + #open(my $fh, '<', $file) or die "can't open $file: $!"; + #chomp(@data = <$fh>); } else { $content = qx($alerts{'dmidecode'}->{'path'} 2>/dev/null); @@ -22368,7 +23268,7 @@ sub set_dmidecode_data { $j = scalar @dmi; $handle = hex($1); $type = $2; - $b_slot_tool = 1 if $type && $type == 9; + $use{'slot-tool'} = 1 if $type && $type == 9; $b_skip = ( $type > 126 )? 1 : 0; next if $b_skip; # we don't need 32, system boot, or 127, end of table @@ -22391,11 +23291,14 @@ sub set_dmidecode_data { # by handle, as secondary sort. @dmi = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @dmi; log_data('dump','@dmi',\@dmi) if $b_log; - print Dumper \@dmi if $test[2]; + print Dumper \@dmi if $dbg[2]; eval $end if $b_log; } -sub set_ip_data { +# Set IpData +{ +package IpData; +sub set { eval $start if $b_log; if ($alerts{'ip'}->{'action'} eq 'use' ){ set_ip_addr(); @@ -22408,7 +23311,7 @@ sub set_ip_data { sub set_ip_addr { eval $start if $b_log; - my @data = grabber($alerts{'ip'}->{'path'} . " addr 2>/dev/null",'\n','strip'); + my @data = main::grabber($alerts{'ip'}->{'path'} . " addr 2>/dev/null",'\n','strip'); # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/if/scope-ipaddr-1.txt"; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/networking/ip-addr-blue-advance.txt"; #my @data = reader($file,'strip') or die $!; @@ -22447,22 +23350,22 @@ sub set_ip_addr { } @temp = ($type,$ip,$broadcast,$scope,$if_id); push(@ips,[@temp]); - #print Dumper \@ips; + #print Data::Dumper::Dumper \@ips; } } - #print Dumper \@ips if $test[4]; + #print Data::Dumper::Dumper \@ips if $dbg[4]; if (@ips){ @temp = ($if,[@ips]); push(@ifs,@temp); } - log_data('dump','@ifs',\@ifs) if $b_log; - print Dumper \@ifs if $test[3]; + main::log_data('dump','@ifs',\@ifs) if $b_log; + print Data::Dumper::Dumper \@ifs if $dbg[3]; eval $end if $b_log; } sub set_ifconfig { eval $start if $b_log; - my @data = grabber($alerts{'ifconfig'}->{'path'} . " 2>/dev/null",'\n',''); + my @data = main::grabber($alerts{'ifconfig'}->{'path'} . " 2>/dev/null",'\n',''); #my @data = reader("$ENV{'HOME'}/bin/scripts/inxi/data/if/vps-ifconfig-1.txt",'') or die $!; my ($b_skip,$broadcast,$if,@ips_bsd,$ip,@ips,$scope,$if_id,$type,@temp,@temp2); my ($state,$speed,$duplex,$mac); @@ -22492,27 +23395,27 @@ sub set_ifconfig { } $b_skip = 0; } - # lladdr openbsd - elsif (!$b_skip && $bsd_type && /^\s+(ether|media|status|lladdr)/){ + elsif (!$b_skip && $bsd_type && /^\s+(address|ether|media|status|lladdr)/){ $_ =~ s/^\s+//; - # media: Ethernet 100baseTX freebsd 7.3 - # media: Ethernet autoselect (1000baseT ) Freebsd 8.2 - # + # freebsd 7.3: media: Ethernet 100baseTX + # Freebsd 8.2/12.2: media: Ethernet autoselect (1000baseT ) + # Netbsd 9.1: media: Ethernet autoselect (1000baseT full-duplex) + # openbsd: media: Ethernet autoselect (1000baseT full-duplex) if (/^media/){ - # openbsd: media: Ethernet autoselect (1000baseT full-duplex) - if ($bsd_type && $bsd_type eq 'openbsd'){ - $_ =~ /\s\([\S]+\s([\S]+)\)/; - $duplex = $1; + if ($_ =~ /[\s\(]([1-9][^\(\s]+)?\s<([^>]+)>/){ + $speed = $1 if $1; + $duplex = $2; } - else { - $_ =~ /<([^>]+)>/; - $duplex = $1; + if (!$duplex && $_ =~ /\s\(([\S]+)\s([^\s<]+)\)/){ + $speed = $1; + $duplex = $2; + } + if (!$speed && $_ =~ /\s\(([1-9][\S]+)\s/){ + $speed = $1; } - $_ =~ /\s\(([1-9][\S]+\s)/; - $speed = $1; - $speed =~ s/\s+$// if $speed; } - elsif (!$mac && /^ether|lladdr/){ + # lladdr openbsd/address netbsd/ether freebsd + elsif (!$mac && /^(address|ether|lladdr)/){ $mac = (split(/\s+/, $_))[1]; } elsif (/^status/){ @@ -22541,7 +23444,7 @@ sub set_ifconfig { $scope = 'link' if $ip =~ /^fe80/; @temp = ($type,$ip,$broadcast,$scope,$if_id); push(@ips,[@temp]); - #print Dumper \@ips; + #print Data::Dumper::Dumper \@ips; } } if (@ips){ @@ -22553,16 +23456,17 @@ sub set_ifconfig { push(@ifs_bsd,@temp); ($state,$speed,$duplex,$mac) = ('','','',''); } - print Dumper \@ifs if $test[3]; - print Dumper \@ifs_bsd if $test[3]; - log_data('dump','@ifs',\@ifs) if $b_log; - log_data('dump','@ifs_bsd',\@ifs_bsd) if $b_log; + print Data::Dumper::Dumper \@ifs if $dbg[3]; + print Data::Dumper::Dumper \@ifs_bsd if $dbg[3]; + main::log_data('dump','@ifs',\@ifs) if $b_log; + main::log_data('dump','@ifs_bsd',\@ifs_bsd) if $b_log; eval $end if $b_log; } +} sub set_lsblk { eval $start if $b_log; - $b_lsblk = 1; + $loaded{'lsblk'} = 1; if ($alerts{'lsblk'} && $alerts{'lsblk'}->{'path'}){ my $cmd = $alerts{'lsblk'}->{'path'} . ' -bP --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,'; $cmd .= 'SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS,MAJ:MIN,PKNAME 2>/dev/null'; @@ -22595,11 +23499,11 @@ sub set_lsblk { # must be below assignments!! otherwise the result of the match replaces values # note: for bcache and luks, the device that has that fs is the parent!! if ($show{'logical'}){ - $b_active_lvm = 1 if !$b_active_lvm && $2 && $2 eq 'lvm'; - if (!$b_active_general && (($4 && ($4 eq 'crypto_LUKS' || $4 eq 'bcache')) + $use{'logical-lvm'} = 1 if !$use{'logical-lvm'} && $2 && $2 eq 'lvm'; + if (!$use{'logical-general'} && (($4 && ($4 eq 'crypto_LUKS' || $4 eq 'bcache')) || ($2 && ($2 eq 'dm' && $1 =~ /veracrypt/i) || $2 eq 'crypto' || $2 eq 'mpath' || $2 eq 'multipath'))){ - $b_active_general = 1; + $use{'logical-general'} = 1; } } } @@ -22612,7 +23516,7 @@ sub set_lsblk { sub set_mapper { eval $start if $b_log; - $b_mapper = 1; + $loaded{'mapper'} = 1; return if ! -d '/dev/mapper'; foreach ((globber('/dev/mapper/*'))){ my ($key,$value) = ($_,Cwd::abs_path("$_")); @@ -22627,58 +23531,60 @@ sub set_mapper { sub set_proc_partitions { eval $start if $b_log; - $b_proc_partitions = 1; + $loaded{'proc-partitions'} = 1; if (my $file = main::system_files('partitions')){ - @proc_partitions = main::reader($file,'strip'); - shift @proc_partitions; # get rid of headers - @proc_partitions = map { + my @parts = main::reader($file,'strip'); + #print Dumper \@parts; + shift @parts if @parts; # get rid of headers + for (@parts){ my @temp = split(/\s+/, $_); - next if ! defined $temp[2]; - [$temp[0],$temp[1],$temp[2],$temp[3]]; - } @proc_partitions; + next if !defined $temp[2]; + push (@proc_partitions,[$temp[0],$temp[1],$temp[2],$temp[3]]); + } } eval $end if $b_log; } sub set_ps_aux { eval $start if $b_log; - my ($header,@temp); - @ps_aux = grabber("ps aux 2>/dev/null",'','strip'); - if (@ps_aux){ - $header = shift @ps_aux; # get rid of header row + my ($header,@ps,@temp); + # note: some ps cut off output based on terminal width + # ww sets width unlimited + $loaded{'ps-aux'} = 1; + @ps = grabber("ps wwaux 2>/dev/null",'','strip'); + if (@ps){ + $header = shift @ps; # get rid of header row # handle busy box, which has 3 columns, regular ps aux has 11 # avoid deprecated implicit split error in older Perls @temp = split(/\s+/, $header); } - $ps_cols = $#temp; + $ps_cols = $#temp; # the indexes, not the scalar count if ($ps_cols < 10){ my $version = qx(ps --version 2>&1); - $b_bb_ps = 1 if $version =~ /busybox/i; + $b_busybox_ps = 1 if $version =~ /busybox/i; } - return if !@ps_aux; # note: mips/openwrt ps has no 'a' - $_=lc for @ps_aux; # this is a super fast way to set to lower - # note: regular perl /.../inxi but sudo /.../inxi is added for sudo start - # for pinxi, we want to see the useage data for cpu/ram - @ps_aux = grep {!/\/$self_name\b/} @ps_aux if $self_name eq 'inxi'; - # this is for testing for the presence of the command - @ps_cmd = grep {!/^\[/} map { + return if !@ps; # note: mips/openwrt ps has no 'a' + for (@ps){ + next if !$_; + next if $self_name eq 'inxi' && /\/$self_name\b/; + $_ = lc; + push (@ps_aux,$_); my @split = split(/\s+/, $_); # slice out 10th to last elements of ps aux rows my $final = $#split; # some stuff has a lot of data, chrome for example $final = ($final > ($ps_cols + 2) ) ? $ps_cols + 2 : $final; - @split = @split[$ps_cols .. $final]; - join(' ', @split); - } @ps_aux; - #@ps_cmd = grep {!/^\[/} @ps_cmd; + if ($split[$ps_cols] !~ /^\[/){ + push(@ps_cmd,join(' ', @split[$ps_cols .. $final])); + } + } # never, because ps loaded before option handler - print Dumper \@ps_cmd if $test[5]; + # print Dumper \@ps_cmd; # if $dbg[5]; eval $end if $b_log; } - sub set_ps_gui { eval $start if $b_log; - $b_ps_gui = 1; + $loaded{'ps-gui'} = 1; my ($working,@match,@temp); # desktops / wm (some wm also compositors) if ($show{'system'}){ @@ -22687,9 +23593,9 @@ sub set_ps_gui { push(@match,@temp); @temp=qw(3dwm 9wm afterstep aewm aewm\+\+ amiwm antiwm awesome blackbox bspwm - cagebreak calmwm (sh|c?lisp).*clfswm (openbsd-)?cwm dwm evilwm + cagebreak calmwm (sh|c?lisp).*clfswm ctwm (openbsd-)?cwm dwm evilwm fluxbox flwm flwm_topside fvwm.*-crystal fvwm1 fvwm2 fvwm3 fvwm95 fvwm - i3 instantwm ion3 jbwm jwm larswm lwm + herbstluftwm i3 icewm instantwm ion3 jbwm jwm larswm lwm matchbox-window-manager mini musca mwm nawm notion openbox orbital pekwm perceptia python.*qtile qtile qvwm ratpoison sawfish scrotwm spectrwm (sh|c?lisp).*stumpwm sway @@ -22742,26 +23648,27 @@ sub set_ps_gui { } } uniq(\@ps_gui) if @ps_gui; - print Dumper \@ps_gui if $test[5]; + print Dumper \@ps_gui if $dbg[5]; log_data('dump','@ps_gui',\@ps_gui) if $b_log; eval $end if $b_log; } + sub set_sysctl_data { eval $start if $b_log; return if !$alerts{'sysctl'} || $alerts{'sysctl'}->{'action'} ne 'use'; my (@temp); # darwin sysctl has BOTH = and : separators, and repeats data. Why? - if (!$b_fake_sysctl){ + if (!$fake{'sysctl'}){ @temp = grabber($alerts{'sysctl'}->{'path'} . " -a 2>/dev/null"); } else { #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1_sysctl_soekris6501_root.txt"; #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1sysctl_lenovot500_user.txt"; ## matches: compaq: openbsd-dmesg.boot-1.txt - my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-1.txt"; ## matches: toshiba: openbsd-5.6-dmesg.boot-1.txt #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/openbsd-5.6-sysctl-2.txt"; - @temp = reader($file); + # @temp = reader($file); } foreach (@temp){ $_ =~ s/\s*=\s*|:\s+/:/; @@ -22772,14 +23679,17 @@ sub set_sysctl_data { if (/^hw\.sensors/ && !/^hw\.sensors\.acpi(bat|cmb)/ && !/^hw.sensors.softraid/){ push(@sysctl_sensors, $_); } - elsif (/^hw\.(vendor|product|version|serialno|uuid)/){ + elsif (/^(hw\.|machdep\.dmi\.(bios|board|system)-)(date|product|serial(no)?|uuid|vendor|version)/){ push(@sysctl_machine, $_); } + elsif (/^hw\.snd\./){ + push(@sysctl_audio, $_); + } elsif (/^hw\.sensors\.acpi(bat|cmb)/){ push(@sysctl_battery, $_); } } - print Dumper \@sysctl if $test[7]; + print Dumper \@sysctl if $dbg[7]; # this thing can get really long. if ($b_log){ #main::log_data('dump','@sysctl',\@sysctl); @@ -22807,28 +23717,41 @@ sub set_sysctl_data { # 16 - serial # 17 - speed # 18 - configuration - not used -## USBData +# 19 - power mW bsd only, not used yet +# 20 - product rev number +## Set USBData { package USBData; my (@working); -my ($b_hub,$addr_id,$bus_id,$bus_id_alpha,$chip_id,$class_id, -$device_id,$driver,$ids,$interfaces,$name,$path,$path_id,$product, -$protocol_id,$serial,$speed,$subclass_id,$type,$version,$vendor,$vendor_id,); +my (@asound_ids,$b_asound,$b_hub,$addr_id,$bus_id,$bus_id_alpha, +$chip_id,$class_id,$device_id,$driver,$ids,$interfaces, +$name,$network_regex,$path,$path_id,$power,$product,$protocol_id,$rev, +$serial,$speed,$subclass_id,$type,$version,$vendor,$vendor_id); my $b_live = 1; # debugger file data - sub set { eval $start if $b_log; - $b_usb_check = 1; + ${$_[0]} = 1; # set checked boolean + # note: bsd package usbutils has lsusb in it, but we dont' want it for default + # usbdevs is best, has most data, and runs as user + if ($alerts{'usbdevs'}->{'action'} eq 'use'){ + usbdevs_data(); + } + # usbconfig has weak/poor output, and requires root, only fallback + elsif ($alerts{'usbconfig'}->{'action'} eq 'use'){ + usbconfig_data(); + } # if user config sets USB_SYS you can override with --usb-tool - if ((!$b_usb_sys || $b_usb_tool) && $alerts{'lsusb'}->{'action'} eq 'use' ){ + elsif ((!$force{'usb-sys'} || $force{'lsusb'}) && $alerts{'lsusb'}->{'action'} eq 'use' ){ lsusb_data(); } elsif (-d '/sys/bus/usb/devices'){ sys_data('main'); } - elsif ( $alerts{'usbdevs'}->{'action'} eq 'use'){ - usbdevs_data(); - } + @usb = sort {$a->[0] cmp $b->[0]} @usb if @usb; + main::log_data('dump','@usb_audio: ',\@usb_audio) if $b_log; + main::log_data('dump','@usb_bluetooth: ',\@usb_bluetooth) if $b_log; + main::log_data('dump','@usb_graphics: ',\@usb_graphics) if $b_log; + main::log_data('dump','@usb_network: ',\@usb_network) if $b_log; eval $end if $b_log; } @@ -22841,8 +23764,15 @@ sub lsusb_data { @working = split(/\s+/, $_); next unless defined $working[1] && defined $working[3]; $working[3] =~ s/:$//; - # Seen FreeBSD lsusb with: + # Don't use this fix, the data is garbage in general! Seen FreeBSD lsusb with: # Bus /dev/usb Device /dev/ugen0.3: ID 24ae:1003 Shenzhen Rapoo Technology Co., Ltd. + # hub, note incomplete data: Bus /dev/usb Device /dev/ugen0.1: ID 0000:0000 + # linux: + # Bus 005 Device 007: ID 0d8c:000c C-Media Electronics, Inc. Audio Adapter + #if ($working[3] =~ m|^/dev/ugen([0-9]+)\.([0-9]+)|){ + # $working[1] = $1; + # $working[3] = $2; + #} next unless main::is_numeric($working[1]) && main::is_numeric($working[3]); $addr_id = int($working[3]); $bus_id = int($working[1]); @@ -22851,6 +23781,9 @@ sub lsusb_data { @temp = @working[6..$#working]; $name = main::remove_duplicates(join(' ', @temp)); $name = $name; + # $type = check_type($name,'',''); + $type ||= ''; + # do NOT set bus_id_alpha here!! #print "$name\n"; $working[0] = $bus_id; $working[1] = $addr_id; @@ -22866,20 +23799,90 @@ sub lsusb_data { $working[11] = ''; $working[12] = ''; $working[13] = $name; - $working[14] = ''; + $working[14] = '';# $type; $working[15] = ''; $working[16] = ''; $working[17] = ''; $working[18] = ''; + $working[19] = ''; + $working[20] = ''; push(@usb,[@working]); #print join("\n",@working),"\n\n=====\n"; } - print Data::Dumper::Dumper \@usb if $test[6]; + print Data::Dumper::Dumper \@usb if $dbg[6]; sys_data('lsusb') if @usb; - print Data::Dumper::Dumper \@usb if $test[6]; + print Data::Dumper::Dumper \@usb if $dbg[6]; main::log_data('dump','@usb: plain',\@usb) 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) +sub usbconfig_data { + eval $start if $b_log; + my ($b_multi,$class,$config,$hub_id); + my ($ports,$j,$k) = (0,0,0); + my @data = data_grabber('usbconfig'); + push (@data,'END') if @data; + foreach (@data){ + # note that bsd spd=FULL has interest since we get that from the speed + if (/^([a-z_-]+)([0-9]+)\.([0-9]+):\s+<([^>]+)>\s+at usbus([0-9]+),\s+cfg=([0-9]+)\s+md=([^\s]+)\s+spd=([^\s]+)\s+\(([^\)]+)\)\s+pwr=([^\s]+)\s+\(([0-9]+mA)\)/){ + $hub_id = $2; + $addr_id = $3; + $bus_id = $5; + $driver = $1; + $name = main::remove_duplicates($4); + $type = check_type($name,'',''); + $config = $6; + $speed = prep_speed($9); + $power = $11; + ($product,$vendor) = ('',''); + # leave the ugly vendor/product ids unless chip-ID shows! + if ($extra > 1){ + if ($name =~ /vendor (0x)?[0-9a-f]{4}/){ + $name =~ s/vendor (0x)?([0-9a-f]{4})\s?//; + $vendor = ($2) ? $2 : ''; + } + if ($name =~ /product (0x)?[0-9a-f]{4}/){ + $name =~ s/product (0x)?([0-9a-f]{4})\s?//; + $product = ($2) ? $2 : ''; + } + } + $chip_id = ($vendor || $product) ? "$vendor:$product" : ''; + $class = ($type && $type eq 'Hub') ? '09': '01'; + process_power(\$power) if $power; + $j = scalar @usb; + $path_id = "$bus_id-$hub_id.$addr_id"; + $bus_id_alpha = bus_id_alpha($path_id); + $working[0] = $bus_id_alpha; + $working[1] = $addr_id; + $working[2] = $path_id; + $working[3] = ''; + $working[4] = $class; + $working[5] = ''; + $working[6] = ''; + $working[7] = $chip_id; + $working[8] = usb_rev($speed); + $working[9] = ''; + $working[10] = 0; + $working[11] = ''; + $working[12] = ''; + $working[13] = $name; + $working[14] = $type; + $working[15] = $driver; + $working[16] = ''; + $working[17] = $speed; + $working[18] = $config; + $working[19] = $power; + $working[20] = ''; + $usb[$j] = ([@working],); + assign_usb_type($usb[$j]); + @working = (); + } + } + main::log_data('dump','@usb: usbconfig',\@usb) if $b_log; + print Data::Dumper::Dumper \@usb 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 @@ -22887,59 +23890,76 @@ sub lsusb_data { # port 2 powered sub usbdevs_data { eval $start if $b_log; - my ($class,$hub_id,$port,$port_value); + my ($b_multi,$class,$config,$hub_id,$port,$port_value,$product_rev); my ($ports,$j,$k) = (0,0,0); my @data = data_grabber('usbdevs'); + push (@data,'END') if @data; foreach (@data){ if (/^Controller\s\/dev\/usb([0-9]+)/){ - # $j = scalar @usb; - ($j,$ports) = (0,0); - $port_value = ''; $bus_id = $1; + if (@working){ + $j = scalar @usb; + $usb[$j] = ([@working],); + assign_usb_type($usb[$j]); + } + ($j,$ports) = (0,0); + ($driver,$port_value) = ('',''); @working = (); } - elsif (/^addr\s([0-9]+):\s([^,]+),[^,]+,[^,]+,\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ + elsif (/^addr\s([0-9]+):\s([^,]+),[^,0-9]+([0-9]+ mA)?,\s+config\s+([0-9]+),\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ $j = scalar @usb; $k = $j; $hub_id = $1; $addr_id = $1; - $speed = $2; - $chip_id = "$4:$6"; - $name = main::remove_duplicates("$5 $3"); + $speed = prep_speed($2); + $power = $3; + $chip_id = "$6:$8"; + $config = $4; + $name = main::remove_duplicates("$7 $5"); #print "p1:$protocol\n"; $path_id = "$bus_id-$hub_id"; + $bus_id_alpha = bus_id_alpha($path_id); + process_power(\$power) if $power; $port_value = ''; - $working[0] = $bus_id; + $working[0] = $bus_id_alpha; $working[1] = $addr_id; - $working[2] = $path; + $working[2] = $path_id; $working[3] = ''; $working[4] = '09'; $working[5] = ''; $working[6] = ''; $working[7] = $chip_id; - $working[8] = $speed; + $working[8] = usb_rev($speed); $working[9] = ''; $working[10] = 0; $working[13] = $name; $working[14] = 'Hub'; $working[15] = ''; $working[16] = ''; - $working[17] = ''; - $working[18] = ''; + $working[17] = $speed; + $working[18] = $config; + $working[19] = $power; + $working[20] = ''; $usb[$j] = ([@working],); @working = (); } - elsif (/^\s+port\s([0-9]+)\saddr\s([0-9]+):\s([^,]+),[^,]+,[^,]+,\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ + elsif (/^\s+port\s([0-9]+)\saddr\s([0-9]+):\s([^,]+),[^,0-9]*([0-9]+\s?mA)?,\s+config\s+([0-9]+),\s?([^,]+)\(0x([0-9a-f]{4})\),\s?([^,]+)\s?\(0x([0-9a-f]{4})\)/){ $j = scalar @usb; $port = $1; $addr_id = "$2"; - $speed = "$3"; - $chip_id = "$5:$7"; - $name = main::remove_duplicates("$6 $4"); + $power = $4; + $config = $5; + $speed = prep_speed($3); + $chip_id = "$7:$9"; + $name = main::remove_duplicates("$8 $6"); + $type = check_type($name,'',''); + $type ||= ''; #print "p2:$protocol\n"; $ports++; $path_id = "$bus_id-$hub_id.$port"; - $working[0] = $bus_id; + $bus_id_alpha = bus_id_alpha($path_id); + process_power(\$power) if $power; + $working[0] = $bus_id_alpha; $working[1] = $addr_id; $working[2] = $path_id; $working[3] = ''; @@ -22947,18 +23967,21 @@ sub usbdevs_data { $working[5] = ''; $working[6] = ''; $working[7] = $chip_id; - $working[8] = $speed; + $working[8] = usb_rev($speed); $working[9] = ''; $working[10] = 0; $working[11] = ''; $working[12] = ''; $working[13] = $name; - $working[14] = ''; + $working[14] = $type; $working[15] = ''; $working[16] = ''; - $working[17] = ''; - $working[18] = ''; + $working[17] = $speed; + $working[18] = $config; + $working[19] = $power; + $working[20] = ''; $usb[$j] = ([@working],); + assign_usb_type($usb[$j]); $usb[$k]->[10] = $ports; @working = (); } @@ -22966,31 +23989,93 @@ sub usbdevs_data { $ports++; $usb[$k]->[10] = $ports; } - } - if (@working){ - $j = scalar @usb; - $usb[$j] = ( - [@working], - ); + # newer openbsd usbdevs totally changed their syntax and layout, sigh... + elsif (/^addr\s*([0-9a-f]+):\s+([a-f0-9]{4}:[a-f0-9]{4})\s*([^,]+)?,\s+([^,]+)$/){ + if (@working){ + $usb[$j] = ([@working],); + assign_usb_type($usb[$j]); + @working = (); + ($config,$driver,$power,$rev) = ('','','',''); + } + $j = scalar @usb; + $addr_id = $1; + $chip_id = $2; + $vendor = $3 if $3; + $vendor ||= ''; + $name = main::remove_duplicates("$vendor $4"); + $type = check_type($name,'',''); + $class_id = ($name =~ /hub/) ? '09': '01'; + $path_id = "$bus_id-$addr_id"; + $bus_id_alpha = bus_id_alpha($path_id); + $b_multi = 1; + $working[0] = $bus_id_alpha; + $working[1] = $addr_id; + $working[2] = $path_id; + $working[3] = ''; + $working[4] = $class_id; + $working[5] = ''; + $working[6] = ''; + $working[7] = $chip_id; + $working[8] = ''; + $working[9] = ''; + $working[10] = 0; + $working[11] = ''; + $working[12] = ''; + $working[13] = $name; + $working[14] = $type; + $working[15] = ''; + $working[16] = ''; + $working[17] = ''; + $working[18] = ''; + $working[19] = ''; + $working[20] = ''; + } + elsif ($b_multi && /^\s+([^,]+),\s+power\s+([0-9]+\s+mA),\s+config\s([0-9]+),\s+rev\s+([0-9\.]+)/){ + $speed = prep_speed($1); + $rev = usb_rev($speed); + $power = $2; + process_power(\$power) if $power; + $working[8] = $rev; + $working[17] = $speed; + $working[18] = $3; # config number + $working[19] = $power; + $working[20] = $4; # product rev + } + # 1 or more drivers supported + elsif ($b_multi && /^\s+driver:\s*([^,]+)$/){ + my $temp = $1; + $temp =~ s/[0-9]+$//; + $working[4] = '09' if $temp =~ /hub[0-9]/; + # drivers, note that when numbers trimmed off, drivers can have same name + $working[15] = ($working[15] && $working[15] !~ /\b$temp\b/) ? "$working[15],$temp" : $temp; + } + elsif ($_ eq 'END' && @working){ + $j = scalar @usb; + $usb[$j] = ([@working],); + assign_usb_type($usb[$j]); + } } main::log_data('dump','@usb: usbdevs',\@usb) if $b_log; - print Data::Dumper::Dumper \@usb if $test[6]; + print Data::Dumper::Dumper \@usb if $dbg[6]; eval $end if $b_log; } sub data_grabber { eval $start if $b_log; my ($program) = @_; - my %args = ('lsusb' => '', 'usbdevs' => '-v'); + my %args = ('lsusb' => '', 'usbconfig' => '', 'usbdevs' => '-v'); my (@data); - if ($b_live && !$b_fake_usbdevs){ + if ($b_live && !$fake{'usbdevs'} && !$fake{'usbconfig'}){ @data = main::grabber($alerts{$program}->{'path'} . " $args{$program} 2>/dev/null"); } else { my $file; - if ($b_fake_usbdevs){ + if ($fake{'usbdevs'}){ $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lsusb/bsd-usbdevs-v-1.txt"; } + elsif ($fake{'usbconfig'}){ + $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lsusb/bsd-usbconfig-list-v-1.txt"; + } else { $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lsusb/mdmarmer-lsusb.txt"; } @@ -23014,7 +24099,7 @@ sub sys_data { foreach (@files){ @uevent = main::reader("$_/uevent") if -r "$_/uevent"; $ids = main::awk(\@uevent,'^(DEVNAME|DEVICE\b)',2,'='); - if ( $ids){ + if ($ids){ @drivers = (); ($b_hub,$class_id,$protocol_id,$subclass_id) = (0,0,0,0); ($configuration,$driver,$interfaces,$name,$ports,$product,$serial,$speed, @@ -23035,6 +24120,8 @@ sub sys_data { $class_id = sys_item("$_/bDeviceClass"); # $subclass_id = sys_item("$_/bDeviceSubClass"); $class_id = hex($class_id) if $class_id; + $power = sys_item("$_/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; @@ -23048,6 +24135,8 @@ sub sys_data { $usb_version = sys_item("$_/version"); $speed = sys_item("$_/speed"); $configuration = sys_item("$_/configuration"); + $power = sys_item("$_/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 ''; if ($source eq 'lsusb'){ @@ -23074,6 +24163,9 @@ sub sys_data { $usb[$i]->[16] = $serial if $serial; $usb[$i]->[17] = $speed if $speed; $usb[$i]->[18] = $configuration; + $usb[$i]->[19] = $power; + $usb[$i]->[20] = ''; + assign_usb_type($usb[$i]); #print join("\n",@{$usb[$i]}),"\n\n";# if !$b_hub; last; } @@ -23130,13 +24222,15 @@ sub sys_data { $usb[$i]->[16] = $serial; $usb[$i]->[17] = $speed; $usb[$i]->[18] = $configuration; + $usb[$i]->[19] = $power; + $usb[$i]->[20] = ''; + assign_usb_type($usb[$i]); $i++; } - #print "$path_id ids: $bus_id:$device_id driver: $driver ports: $ports\n==========\n"; # if $test[6];; + #print "$path_id ids: $bus_id:$device_id driver: $driver ports: $ports\n==========\n"; # if $dbg[6];; } } - @usb = sort { $a->[0] cmp $b->[0] } @usb; - print Data::Dumper::Dumper \@usb if $source eq 'main' && $test[6]; + print Data::Dumper::Dumper \@usb if $source eq 'main' && $dbg[6]; main::log_data('dump','@usb: sys',\@usb) if $source eq 'main' && $b_log; eval $end if $b_log; } @@ -23197,7 +24291,49 @@ 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. + if (($row->[4] && $row->[4] eq '09') || + ($row->[14] && $row->[14] eq 'Hub') || + $row->[1] <= 1 || + (!$show{'audio'} && !$show{'bluetooth'} && !$show{'graphic'} && !$show{'network'})){ + return; + } + $row->[13] = '' if !defined $row->[13]; # product + $row->[14] = '' if !defined $row->[14]; # type + $row->[15] = '' if !defined $row->[15]; # driver + set_asound_ids() if $show{'audio'} && !$b_asound; + set_network_regex() if $show{'network'} && !$network_regex; + if ($show{'audio'} && ( + (@asound_ids && $row->[7] && (grep {$row->[7] eq $_} @asound_ids)) || + ($row->[14] =~ /Audio/) || + ($row->[15] && $row->[15] =~ /audio/) || + ($row->[13] && lc($row->[13]) =~ /(audio|\bdac[0-9]*\b|headphone|\bmic(rophone)?\b)/))){ + push(@usb_audio,$row); + } + elsif ($show{'bluetooth'} && ( + $row->[14] && $row->[14] =~ /Bluetooth/ || + ($row->[15] && $row->[15] =~ /btusb/))){ + push(@usb_bluetooth,$row); + } + elsif ($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{'network'} && ( + ($row->[14] && $row->[14] =~ /(Ethernet|Network|WiFi)/i) || + ($row->[15] && $row->[15] =~ /(^ipw|^iwl|wifi)/) || + ($row->[13] && $row->[13] =~ /($network_regex)/i))){ + #print "$1\n"; + push(@usb_network,$row); + } +} sub device_type { my ($data) = @_; my ($type); @@ -23254,23 +24390,114 @@ sub device_type { return $type; } # 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) = @_; $name = lc($name); - # ntoe used but if we want to add in bsd usb audio support could be good - if ($name =~ /(audio|hifi|sound)/){ + if ($name =~ /\b(hub)/i){ + $type = 'Hub'; + } + elsif ($name =~ /(audio|\bdac[0-9]*\b|(head|micro|tele)phone|hifi|\bmidi\b|\bmic\b|sound)/){ $type = 'Audio'; } # Broadcom HP Portable SoftSailing elsif (($driver && $driver =~ /btusb/) || $name =~ /(bluetooth)/){ - $type = 'Bluetooth'; + $type = 'Bluetooth' } - elsif (($driver && $driver =~ /uvcvideo/) || $name =~ /(display|video|camera)/){ + elsif (($driver && $driver =~ /video/) || + $name =~ /(camera|display|\bdvb-t|\b(pc)?tv\bvideo|webcam)/){ $type = 'Video'; } - # ethernet/wifi test not needed because NetworkData runs its own tests on the data + elsif ($name =~ /(wlan|wi-?fi|802\.1[15]|(11|54|108|240|300|450|1300)\s?mbps|(11|54|108|240)g\b|wireless[\s-][gn]\b|wireless.*adapter)/){ + $type = 'WiFi'; + } + elsif ($name =~ /(ethernet|\blan|802\.3|100?\/1000?|gigabit)/){ + $type = 'Ethernet'; + } + # note: audio devices show HID sometimes, not sure why + elsif ($name =~ /(joystick|keyboard|mouse|trackball)/){ + $type = 'HID'; + } return $type; } +# linux only, will create a positive match to sound devices +sub set_asound_ids { + $b_asound = 1; + if (-d '/proc/asound') { + # note: this will double the data, but it's easier this way. + # binxi tested for -L in the /proc/asound files, and used only those. + my @files = main::globber('/proc/asound/*/usbid'); + foreach (@files){ + my $id = main::reader($_,'',0); + push(@asound_ids, $id) if ($id && !(grep {/$id/} @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 +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 + # ralink has bluetooth as well as networking; (WG|WND?A)[0-9][0-9][0-9] netgear IDs + $network_regex = 'Ethernet|gigabit|\bISDN|\bLAN\b|Mobile\s?Broadband|'; + $network_regex .= '\bNIC\b|wi-?fi|Wireless[\s-][GN]\b|WLAN|'; + $network_regex .= '802\.(1[15]|3)|(10|11|54|108|240|300|450|1300)\s?Mbps|(11|54|108|240)g\b|100?\/1000?|'; + $network_regex .= '(100?|N)Base-?T\b|'; + $network_regex .= '(Actiontec|AirLink|Asus|Belkin|Buffalo|Dell|D-Link|DWA-|ENUWI-|'; + $network_regex .= 'Ralink|Realtek|Rosewill|RNX-|Samsung|Sony|TEW-|TP-Link'; + $network_regex .= 'Zonet.*ZEW.*).*Wireless|'; + $network_regex .= '(\bD-Link|Network(ing)?|Wireless).*(Adapter|Interface)|'; + $network_regex .= '(Linksys|Netgear|Davicom)|'; + $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; +} +sub prep_speed { + return if !$_[0]; + my $speed = $_[0]; + if ($_[0] =~ /^([0-9\.]+)\s*Mb/){ + $speed = $1; + } + elsif ($_[0] =~ /^([0-9\.]+)+\s*Gb/){ + $speed = $1 * 1000; + } + # 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 + } + elsif ($_[0] =~ /super[\s-]?speed/i){ + $speed = 5000;# 3.0; + } + elsif ($_[0] =~ /hi[\s-]?speed/i){ + $speed = 480; # 2.0, + } + elsif ($_[0] =~ /full[\s-]?speed/i){ + $speed = 12; # 1.1 - could be full speed 1.1/2.0 + } + elsif ($_[0] =~ /low[\s-]?speed/i){ + $speed = 1.5; # 1.5 - could be 1.0, or low speed 1.1/2.0 + } + return $speed; +} +sub process_power { + return if !${$_[0]}; + ${$_[0]} =~ s/\s//g; + # ${$_[0]} = '' if ${$_[0]} eq '0mA'; # better to handle on output +} # this is used to create an alpha sortable bus id for main $usb[0] sub bus_id_alpha { my ($id) = @_; @@ -23301,134 +24528,134 @@ sub assign_data { sub generate_lines { eval $start if $b_log; - my (%row,$b_pci_check,$b_dmi_check); - set_ps_aux() if ! @ps_aux; - set_sysctl_data() if $b_sysctl; + my (%row,%checks); + set_ps_aux() if !$loaded{'ps-aux'}; + set_sysctl_data() if $use{'sysctl'}; # note: ps aux loads before logging starts, so create debugger data here if ($b_log){ # I don't think we need to see this, it's long, but leave in case we do #main::log_data('dump','@ps_aux',\@ps_aux); log_data('dump','@ps_cmd',\@ps_cmd); } - if ( $show{'short'} ){ - set_dmesg_boot_data() if ($bsd_type && !$b_dmesg_boot_check); + if ($show{'short'}){ + set_dmesg_boot_data(\$checks{'dmesg-boot'}) if ($bsd_type && !$checks{'dmesg-boot'}); %row = generate_short_data(); assign_data(\%row); } else { - if ( $show{'system'} ){ + if ($show{'system'}){ %row = generate_system_data(); assign_data(\%row); } - if ( $show{'machine'} ){ - set_dmi_data($b_dmi_check) if $b_dmi && !$b_dmi_check; - set_dmesg_boot_data() if ($bsd_type && !$b_dmesg_boot_check); + if ($show{'machine'}){ + set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; + set_dmesg_boot_data() if ($bsd_type && !$checks{'dmesg-boot'}); %row = line_handler('Machine','machine'); assign_data(\%row); } - if ( $show{'battery'} ){ - set_dmi_data($b_dmi_check) if $b_dmi && !$b_dmi_check; + if ($show{'battery'}){ + set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; %row = line_handler('Battery','battery'); if (%row || $show{'battery-forced'}){ assign_data(\%row); } } - if ( $show{'ram'} ){ - set_dmi_data($b_dmi_check) if $b_dmi && !$b_dmi_check; + if ($show{'ram'}){ + set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; %row = line_handler('Memory','ram'); assign_data(\%row); } - if ( $show{'slot'} ){ - set_dmi_data($b_dmi_check) if $b_dmi && !$b_dmi_check; + if ($show{'slot'}){ + set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; %row = line_handler('PCI Slots','slot'); assign_data(\%row); } - if ( $show{'cpu'} || $show{'cpu-basic'} ){ - DeviceData::set($b_pci_check) if $b_arm && !$b_pci_check; - set_dmi_data($b_dmi_check) if $b_dmi && !$b_dmi_check; - set_dmesg_boot_data() if ($bsd_type && !$b_dmesg_boot_check); + if ($show{'cpu'} || $show{'cpu-basic'}){ + DeviceData::set(\$checks{'device'}) if $b_arm && !$checks{'device'}; + set_dmicode_data(\$checks{'dmi'}) if $use{'dmidecode'} && !$checks{'dmi'}; + set_dmesg_boot_data() if ($bsd_type && !$checks{'dmesg-boot'}); my $arg = ($show{'cpu-basic'}) ? 'basic' : 'full' ; %row = line_handler('CPU','cpu',$arg); assign_data(\%row); } - if ( $show{'graphic'} ){ - USBData::set() if !$b_usb_check; - DeviceData::set($b_pci_check) if !$b_pci_check; + if ($show{'graphic'}){ + USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + DeviceData::set(\$checks{'device'}) if !$checks{'device'}; %row = line_handler('Graphics','graphic'); assign_data(\%row); } - if ( $show{'audio'} ){ - # Note: USBData is set internally in AudioData because it's only run in one case - DeviceData::set($b_pci_check) if !$b_pci_check; + if ($show{'audio'}){ + USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + DeviceData::set(\$checks{'device'}) if !$checks{'device'}; %row = line_handler('Audio','audio'); assign_data(\%row); } - if ( $show{'network'} ){ - USBData::set() if !$b_usb_check; - DeviceData::set($b_pci_check) if !$b_pci_check; - set_ip_data() if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})); + if ($show{'network'}){ + USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + DeviceData::set(\$checks{'device'}) if !$checks{'device'}; + IpData::set() if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})); %row = line_handler('Network','network'); assign_data(\%row); } - if ( $show{'bluetooth'} ){ - USBData::set() if !$b_usb_check; - DeviceData::set($b_pci_check) if !$b_pci_check; + if ($show{'bluetooth'}){ + USBData::set(\$checks{'usb'}) if !$checks{'usb'}; + DeviceData::set(\$checks{'device'}) if !$checks{'device'}; %row = line_handler('Bluetooth','bluetooth'); assign_data(\%row); } - if ( $show{'logical'} ){ + if ($show{'logical'}){ %row = line_handler('Logical','logical'); assign_data(\%row); } - if ( $show{'raid'} ){ - DeviceData::set() if !$b_pci_check; + if ($show{'raid'}){ + DeviceData::set(\$checks{'device'}) if !$checks{'device'}; %row = line_handler('RAID','raid'); assign_data(\%row); } - if ( $show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'optical'} ){ - set_dmesg_boot_data() if ($bsd_type && !$b_dmesg_boot_check); + if ($show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'optical'}){ + set_dmesg_boot_data() if ($bsd_type && !$checks{'dmesg-boot'}); %row = line_handler('Drives','disk'); assign_data(\%row); } - if ( $show{'partition'} || $show{'partition-full'}){ + if ($show{'partition'} || $show{'partition-full'}){ %row = line_handler('Partition','partition'); assign_data(\%row); } - if ( $show{'swap'} ){ + if ($show{'swap'}){ %row = line_handler('Swap','swap'); assign_data(\%row); } - if ( $show{'unmounted'} ){ + if ($show{'unmounted'}){ %row = line_handler('Unmounted','unmounted'); assign_data(\%row); } - if ( $show{'usb'} ){ - USBData::set() if !$b_usb_check; + if ($show{'usb'}){ + USBData::set(\$checks{'usb'}) if !$checks{'usb'}; %row = line_handler('USB','usb'); assign_data(\%row); } - if ( $show{'sensor'} ){ + if ($show{'sensor'}){ %row = line_handler('Sensors','sensor'); assign_data(\%row); } - if ( $show{'repo'} ){ + if ($show{'repo'}){ %row = line_handler('Repos','repo'); assign_data(\%row); } - if ( $show{'process'} ){ + if ($show{'process'}){ %row = line_handler('Processes','process'); assign_data(\%row); } - if ( $show{'weather'} ){ + if ($show{'weather'}){ %row = line_handler('Weather','weather'); assign_data(\%row); } - if ( $show{'info'} ){ + if ($show{'info'}){ %row = generate_info_data(); assign_data(\%row); } } - if ( $output_type ne 'screen' ){ + if ($output_type ne 'screen'){ output_handler(\%rows); } eval $end if $b_log; @@ -23477,14 +24704,14 @@ sub generate_short_data { eval $start if $b_log; my $num = 0; my $kernel_os = ($bsd_type) ? 'OS' : 'Kernel'; - get_shell_data($client{'ppid'}) if $client{'ppid'}; + ShellData::set() if !$loaded{'shell-data'} && $ppid; my $client = $client{'name-print'}; my $client_shell = ($b_irc) ? 'Client' : 'Shell'; if ($client{'version'}){ $client .= ' ' . $client{'version'}; } my ($cpu_string,$speed,$speed_key,$type) = ('','','speed',''); - my $memory = get_memory_data('string'); + my $memory = MemoryData::get('string'); my @cpu = CpuData::get('short'); if (scalar @cpu > 1){ $type = ($cpu[2]) ? " (-$cpu[2]-)" : ''; @@ -23582,13 +24809,13 @@ sub generate_info_data { $b_gcc = 1; } $gcc ||= 'N/A'; - get_shell_data($client{'ppid'}) if $client{'ppid'}; + ShellData::set() if !$loaded{'shell-data'} && $ppid; my $client_shell = ($b_irc) ? 'Client' : 'Shell'; my $client = $client{'name-print'}; my %data = ( $data_name => [{ main::key($num++,0,1,'Processes') => scalar @ps_aux, - main::key($num++,1,1,'Uptime') => &get_uptime(), + main::key($num++,1,1,'Uptime') => get_uptime(), },], ); $index = scalar(@{ $data{$data_name} } ) - 1; @@ -23596,8 +24823,8 @@ sub generate_info_data { my $wakeups = get_wakeups(); $data{$data_name}->[$index]{main::key($num++,0,2,'wakeups')} = $wakeups if defined $wakeups; } - if (!$b_mem){ - my $memory = get_memory_data('splits'); + if (!$loaded{'memory'}){ + my $memory = MemoryData::get('splits'); if ($memory){ my @temp = split(':', $memory); $gpu_ram = $temp[3] if $temp[3]; @@ -23614,7 +24841,7 @@ sub generate_info_data { if ($gpu_ram){ $data{$data_name}->[$index]{main::key($num++,0,2,'gpu')} = $gpu_ram; } - if ( (!$b_display || $b_force_display) || $extra > 0 ){ + if ( (!$b_display || $force{'display'}) || $extra > 0 ){ my %init = get_init_data(); my $init_type = ($init{'init-type'}) ? $init{'init-type'}: 'N/A'; $data{$data_name}->[$index]{main::key($num++,1,1,'Init')} = $init_type; @@ -23636,6 +24863,10 @@ sub generate_info_data { my $default = ($init{'init-type'} eq 'systemd' && $init{'default'} =~ /[^0-9]$/ ) ? 'target' : 'default'; $data{$data_name}->[$index]{main::key($num++,0,2,$default)} = $init{'default'}; } + if ($b_admin && (my $tool = ServiceData::get('tool',''))){ + $data{$data_name}->[$index]{main::key($num++,0,2,'tool')} = $tool; + undef %service_tool; + } } } if ($extra > 0 ){ @@ -23658,29 +24889,25 @@ sub generate_info_data { $data{$data_name}->[$index]{main::key($num++,0,2,'clang')} = $clang_version; } } - if ($extra > 0 && !$b_pkg){ + if ($extra > 0 && !$loaded{'packages'}){ my %packages = PackageData::get('inner',\$num); for (keys %packages){ $data{$data_name}->[$index]{$_} = $packages{$_}; } - $b_pkg = 1; } - if (!$b_irc && $extra > 1 ){ - # bsds don't support -f option to get PPID - if (($b_display && !$b_force_display) && !$bsd_type){ - $parent = get_shell_source(); + if (!$b_irc && $extra > 1){ + # some bsds don't support -f option to get PPPID + # note: root/su - does not have $DISPLAY usually + if ($b_display && !$force{'display'} && $ppid && $client{'pppid'}){ + $parent = ShellData::shell_launcher(); } else { $parent = get_tty_number(); $parent = "tty $parent" if $parent ne ''; } - if ($parent eq 'login'){ - $client{'su-start'} = $parent if !$client{'su-start'}; - $parent = undef; - } # can be tty 0 so test for defined - $running_in = $parent if defined $parent; - if ($extra > 2 && $running_in && get_ssh_status() ){ + $running_in = $parent if $parent; + if ($extra > 2 && $running_in && ShellData::ssh_status() ){ $running_in .= ' (SSH)'; } } @@ -23695,8 +24922,8 @@ sub generate_info_data { $data{$data_name}->[$index]{main::key($num++,1,2,'default')} = $client{'default-shell'}; $data{$data_name}->[$index]{main::key($num++,0,3,'v')} = $client{'default-shell-v'} if $client{'default-shell-v'}; } - if ( $running_in ){ - $data{$data_name}->[$index]{main::key($num++,0,2,'running in')} = $running_in; + if ($running_in){ + $data{$data_name}->[$index]{main::key($num++,0,2,'running-in')} = $running_in; } $data{$data_name}->[$index]{main::key($num++,0,1,$self_name)} = &get_self_version(); @@ -23722,7 +24949,7 @@ sub generate_system_data { $data{$data_name}->[$index]{main::key($num++,1,1,'Kernel')} = get_kernel_data(); $data{$data_name}->[$index]{main::key($num++,0,2,'bits')} = get_kernel_bits(); if ($extra > 0){ - my @compiler = get_compiler_version(); # get compiler data + my @compiler = CompilerVersion::get(); # get compiler data if (scalar @compiler != 2){ @compiler = ('N/A', ''); } @@ -23733,7 +24960,7 @@ sub generate_system_data { $data{$data_name}->[$index]{main::key($num++,0,3,'v')} = $compiler[1]; } } - if ($b_admin && (my $params = get_kernel_parameters())){ + if ($b_admin && (my $params = KernelParameters::get())){ $index = scalar(@{ $data{$data_name} } ); #print "$params\n"; $params = apply_partition_filter('system', $params, 'label') if $use{'filter-label'}; @@ -23764,13 +24991,13 @@ sub generate_system_data { $wm .= ' ' . $desktop_data[6] if $extra > 2 && $desktop_data[6]; } } - if (!$b_display || ( !$desktop && $b_root)) { + if (!$b_display || (!$desktop && $b_root)) { my $tty = get_tty_number(); if (!$desktop){ $desktop_info = ''; } # it is defined, as '' - if ( $tty eq '' && $client{'console-irc'}){ + if ($tty eq '' && $client{'console-irc'}){ $tty = get_tty_console_irc('vtnr'); } $desktop = "tty $tty" if $tty ne ''; @@ -23791,6 +25018,9 @@ sub generate_system_data { } if ($extra > 1){ $data{$data_name}->[$index]{main::key($num++,0,2,'wm')} = $wm if $wm; + if ($extra > 2 && $b_display && defined $ENV{'XDG_VTNR'} ){ + $data{$data_name}->[$index]{main::key($num++,0,2,'vt')} = $ENV{'XDG_VTNR'}; + } my $dms = get_display_manager(); if ($dms || $desktop_key ne 'Console'){ $dms ||= 'N/A'; @@ -23819,5 +25049,5 @@ sub generate_system_data { main(); ## From the End comes the Beginning -## note: this EOF is needed for smxi handling, this is what triggers the full download ok +## note: this EOF is needed for self updater, triggers the full download ok ###**EOF**### diff --git a/inxi.1 b/inxi.1 index 586acf7..c4fd2b5 100644 --- a/inxi.1 +++ b/inxi.1 @@ -1,4 +1,4 @@ -.TH INXI 1 "2021\-02\-08" inxi "inxi manual" +.TH INXI 1 "2021\-03\-15" inxi "inxi manual" .SH NAME inxi \- Command line system information script for console and IRC @@ -64,7 +64,8 @@ keep things simple. .TP .B \-A\fR,\fB \-\-audio\fR -Show Audio/sound device(s) information, including device driver. +Show Audio/sound device(s) information, including device driver. Show running +sound server(s). See \fB\-xxA\fR to show all sound servers detected. .TP .B \-b\fR,\fB \-\-basic\fR @@ -78,18 +79,25 @@ Show system battery (\fBID\-x\fR) data, charge, condition, plus extra informatio about current battery state/charge/voltage. Supports multiple batteries when using \fB/sys\fR data. -Note that for \fBcharge\fR, the output shows the current charge, as well as its +Note that for \fBcharge:\fR, the output shows the current charge, as well as its value as a percentage of the available capacity, which can be less than the original design capacity. In the following example, the actual current available capacity of the battery is \fB22.2 Wh\fR. -\fBcharge: 20.1 Wh 95.4%\fR +\fBcharge: 20.1 Wh (95.4%)\fR -The \fBcondition\fR item shows the remaining available capacity / original design +The \fBcondition:\fR item shows the remaining available capacity / original design capacity, and then this figure as a percentage of original capacity available in the battery. \fBcondition: 22.2/36.4 Wh (61%)\fR +With \fB\-x\fR, or if voltage difference is critical, \fBvolts:\fR item shows the +current voltage, and the \fBmin:\fR voltage. Note +that if the current is below the minimum listed the battery is essentially dead +and will not charge. Test that to confirm, but that's technically how it's supposed to work. + +\fBvolts: 12.0 min: 11.4\fR + With \fB\-x\fR shows attached \fBDevice\-x\fR information (mouse, keyboard, etc.) if they are battery powered. @@ -198,14 +206,17 @@ model, and size. See \fBExtra Data Options\fR (\fB\-x\fR options) and .TP .B \-E\fR, \fB\-\-bluetooth\fR -Show bluetooth device(s), drivers. Show \fBReport:\fR with -(if available) bluetooth version (\fBbt\-v\fR), HCI ID, state, -address per device. See \fBExtra Data Options\fR for more. +Show bluetooth device(s), drivers. Show \fBReport:\fR (requires +\fBbt\-adapter\fR or \fBhciconfig\fR) with HCI ID, state, address per device, +and if available (hciconfig only) bluetooth version (\fBbt\-v\fR). +See \fBExtra Data Options\fR for more. + +If bluetooth service is down or disabled, will show message. Note that \fBReport\-ID:\fR indicates that the HCI item was not able to be linked to a specific device, similar to \fBIF\-ID:\fR in \fB\-n\fR. -Note that if your internal bluetooth device does not show, it's possible that +If your internal bluetooth device does not show, it's possible that it has been disabled, if you try enabling it using for example: \fBhciconfig hci0 up\fR @@ -216,7 +227,7 @@ and it returns a blocked by RF\-Kill error, you can do one of these: or -\fBrfkill list\fR +\fBrfkill list bluetooth\fR \fBrfkill unblock bluetooth\fR @@ -328,7 +339,8 @@ Show Logical volume information, for LVM, LUKS, bcache, etc. Shows size, free space (for LVM VG). For LVM, shows \fBDevice\-[xx]: VG:\fR (Volume Group) size/free, \fBLV\-[xx]\fR (Logical Volume). LV shows type, size, and components. Note that components are made up of either containers -(aka, logical devices), or physical devices. The full report requires sudo/root. +(aka, logical devices), or physical devices. The full report requires +doas[BSDs]/sudo/root. Logical block devices can be thought of as devices that are made up out of either other logical devices, or physical devices. inxi does its best @@ -406,9 +418,9 @@ information. Devices shows locator data (highly variable in syntax), size, speed type (eg: \fBtype: DDR3\fR). Note: \fB\-m\fR uses \fBdmidecode\fR, which must be run as root (or start -\fBinxi\fR with \fBsudo\fR), unless you figure out how to set up sudo to permit -dmidecode to read \fB/dev/mem\fR as user. \fBspeed\fR and \fBbus width\fR will not -show if \fBNo Module Installed\fR is found in \fBsize\fR. +\fBinxi\fR with \fBsudo\fR), unless you figure out how to set up doas[BSDs]/sudo +to permit dmidecode to read \fB/dev/mem\fR as user. \fBspeed\fR and \fBbus\-width\fR +will not show if \fBNo Module Installed\fR is found in \fBsize\fR. Note: If \fB\-m\fR is triggered RAM total/used report will appear in this section, not in \fB\-I\fR or \fB\-tm\fR items. @@ -497,6 +509,8 @@ if you have added to \fB/etc/sudoers\fR (sudo v. 1.7 or newer): .B ALL = NOPASSWD: /usr/bin/file (sample) +BSD users: see \fBman doas.conf\fR for setup. + Does not show components (partitions that create the md\-raid array) of md\-raid arrays. .TP @@ -528,16 +542,22 @@ APT distros like PCLinuxOS or Alt\-Linux) \fBEOPKG\fR (Solus) +\fBNIX\fR (NixOS + other distros as alternate package manager) + \fBPACMAN\fR (Arch Linux, KaOS + derived versions) \fBPACMAN\-G2\fR (Frugalware + derived versions) \fBPISI\fR (Pardus + derived versions) +\fBPKG\fR (OpenBSD, FreeBSD, NetBSD + derived OS types) + \fBPORTAGE\fR (Gentoo, Sabayon + derived versions) \fBPORTS\fR (OpenBSD, FreeBSD, NetBSD + derived OS types) +\fBSCRATCHPKG\fR (Venom + derived versions) + \fBSLACKPKG\fR (Slackware + derived versions) \fBTCE\fR (TinyCore) @@ -812,6 +832,8 @@ specific vendor [product] information. \- Adds PCI/USB ID of each device. +\- Adds non-running sound servers, if detected. + .TP .B \-x \-B\fR \- Adds vendor/model, battery status (if battery present). @@ -819,6 +841,10 @@ specific vendor [product] information. \- Adds attached battery powered peripherals (\fBDevice\-[number]:\fR) if detected (keyboard, mouse, etc.). +\- Adds battery \fBvolts:\fR, \fBmin:\fR voltages. Note that if difference +is critical, that is current voltage is too close to minimum voltage, shows +without \fB\-x\fR. + .TP .B \-x \-C\fR \- Adds bogomips on CPU (if available) @@ -860,8 +886,8 @@ Once enabled, add \fBdrivetemp\fR to \fB/etc/modules\fR or \fB/etc/modules\-load.d/***.conf\fR so it starts automatically. If you see drive temps running as regular user and you did not configure system -to use sudo hddtemp, then your system supports this feature. If no /sys data is -found, inxi will try to use hddtemp methods instead for that drive. +to use doas[BSDs]/sudo hddtemp, then your system supports this feature. If no /sys +data is found, inxi will try to use hddtemp methods instead for that drive. Hint: if temp is /sys sourced, the temp will be to 1 decimal, like 34.8, if hddtemp sourced, they will be integers. @@ -870,6 +896,8 @@ or if you have added to \fB/etc/sudoers\fR (sudo v. 1.7 or newer): .B ALL = NOPASSWD: /usr/sbin/hddtemp (sample) +BSD 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 @@ -885,8 +913,9 @@ specific vendor [product] information. \- Adds driver version (if available) for each device. -\- Adds LMP (HCI if no LMP data, and HCI if HCI/LMP versions are different) -version (if available) for each HCI ID. +\- Adds (if available, and \fBhciconfig\fR only) LMP (HCI if no LMP data, +and HCI if HCI/LMP versions are different) version (if available) +for each HCI ID. .TP .B \-x \-G\fR @@ -1023,13 +1052,12 @@ methods are found for each distribution system base detection. .TP .B \-xx \-B\fR -\- Adds serial number, voltage (if available). Note that \fBvolts\fR shows the -data (if available) as the voltage now / minimum design voltage. +\- Adds serial number. .TP .B \-xx \-C\fR -\- Adds \fBL1 cache:\fR and \fBL3 cache:\fR if either are available. Requires -dmidecode and sudo/root. +\- Adds \fBL1\-cache:\fR and \fBL3\-cache:\fR if either are available. Requires +dmidecode and doas[BSDs]/sudo/root. .TP .B \-xx \-D\fR @@ -1056,7 +1084,8 @@ For a PCIe 3 NVMe drive, with speed of \fB8 GT/s\fR and \fB4\fR lanes .B \-xx \-E\fR (\fB\-\-bluetooth\fR) \- Adds vendor:product ID of each device. -\- Adds LMP subversion (and/or HCI revision if applicable) for each device. +\- Adds (\fBhciconfig \fRonly) LMP subversion (and/or HCI revision +if applicable) for each device. .TP .B \-xx \-G\fR @@ -1198,7 +1227,7 @@ data is simply not available as of 2018\-04\-03), location (only available from .TP .B \-xxx \-C\fR \- Adds CPU voltage and external clock speed (this is the motherboard speed). -Requires sudo/root and \fBdmidecode\fR. +Requires doas[BSDs]/sudo/root and \fBdmidecode\fR. .TP .B \-xxx \-D\fR @@ -1216,7 +1245,7 @@ no data will show. .B \-xxx \-E\fR (\fB\-\-bluetooth\fR) \- Adds, if present, PCI/USB class ID. -\- Adds HCI version, revision. +\- Adds (\fBhciconfig \fRonly) HCI version, revision. .TP .B \-xxx \-G\fR @@ -1233,8 +1262,8 @@ Linux only). 0 value means the machine has not been suspended. \- For \fBShell:\fR adds \fBdefault:\fR shell if different from running shell, and default shell \fBv:\fR, if available. -\- For \fBrunning in:\fR adds \fB(SSH)\fR to parent, if present. SSH detection -uses the \fBwho am i\fR test. +\- For \fBrunning\-in:\fR adds \fB(SSH)\fR to parent, if present. SSH detection +uses the \fBwhoami\fR test. .TP .B \-xxx \-J\fR (\fB\-\-usb\fR) @@ -1246,6 +1275,8 @@ uses the \fBwho am i\fR test. \- Adds, if present, USB class ID. +\- Adds, if non 0, max power in mA. + .TP .B \-xxx \-m\fR, \fB\-\-memory\-modules\fR \- Adds memory bus width: primary bus width, and if present, total width. e.g. @@ -1285,6 +1316,9 @@ lxpanel, xfce4\-panel, lxqt\-panel, tint2, cairo-dock, trayer, and many others. \- Adds (if present), display manager (\fBdm\fR) version number. +\- Adds (if Linux, systemd, and in display), virtual terminal (\fBvt\fR) number. +These are the same as \fBctrl+alt+F[x]\fR numbers usually. + .TP .B \-xxx \-w\fR,\fB \-W\fR \- Adds location (city state country), observation altitude (if available), @@ -1314,19 +1348,19 @@ Format is \fBhexadecimal (decimal)\fR if greater than 9, otherwise \fBhexadecima \- Adds CPU microcode. Format is \fBhexadecimal\fR. \- Adds socket type (for motherboard CPU socket, if available). If results doubtful -will list two socket types and \fBnote: check\fR. Requires sudo/root and \fBdmidecode\fR. -The item in parentheses may simply be a different syntax for the same socket, -but in general, check this before trusting it. +will list two socket types and \fBnote: check\fR. Requires doas[BSDs]/sudo/root and +\fBdmidecode\fR. The item in parentheses may simply be a different syntax for the +same socket, but in general, check this before trusting it. .nf Sample: \fBsocket: 775 (478) note: check\fR Sample: \fBsocket: AM4\fR .fi -\- Adds DMI CPU base and boost/turbo speeds. Requires sudo/root and \fBdmidecode\fR. -In some cases, like with overclocking or 'turbo' or 'boost' modes, voltage and -external clock speeds may be increased, or short term limits raised on max CPU speeds. -These are often not reflected in /sys based CPU \fBmin/max:\fR speed results, -but often are using this source. +\- Adds DMI CPU base and boost/turbo speeds. Requires doas[BSDs]/sudo/root and +\fBdmidecode\fR. In some cases, like with overclocking or 'turbo' or 'boost' modes, +voltage and external clock speeds may be increased, or short term limits raised +on max CPU speeds. These are often not reflected in /sys based CPU \fBmin/max:\fR +speed results, but often are using this source. Samples: .nf @@ -1363,7 +1397,7 @@ values. The \fBbase/boost:\fR values are sometimes real, and sometimes not. .B \-a \-d\fR,\fB\-a \-D\fR \- Adds logical and physical block size in bytes. -Using \fBsmartctl\fR (requires sudo/root privileges). +Using \fBsmartctl\fR (requires doas[BSDs]/sudo/root privileges). \- Adds device model family, like \fBCaviar Black\fR, if available. @@ -1388,8 +1422,9 @@ and other useful data. .TP .B \-a \-E\fR (\fB\-\-bluetooth\fR) -\- Adds extra line to \fBReport:\fR, \fBInfo:\fR. Includes, if available, -ACL MTU, SCO MTU, Link policy, Link mode, and Service Classes. +\- Adds (\fBhciconfig\fR only) extra line to \fBReport:\fR, \fBInfo:\fR. +Includes, if available, ACL MTU, SCO MTU, Link policy, Link mode, +and Service Classes. .TP .B \-a \-G\fR @@ -1466,7 +1501,7 @@ instead. .TP .B \-a \-I\fR -Adds Packages, totals, per package manager totals, and number of lib +\- Adds Packages, totals, per package manager totals, and number of lib packages detected per package manager. Also adds detected package managers with 0 packages listed. Moves to \fBRepos\fR if \fB\-ra\fR. @@ -1476,9 +1511,13 @@ Info: .... Init: systemd v: 245 runlevel: 5 Compilers: gcc: 9.3.0 alt: 5/6/7/8/9 Packages: apt: 3681 lib: 2096 rpm: 0 Shell: ksh v: A_2020.0.0 default: Bash - v: 5.0.16 running in: kate inxi: 3.1.04 + v: 5.0.16 running\-in: kate inxi: 3.1.04 .fi +\- Adds service control tool, tested for in the following order: \fBsystemctl +rc-service service sv /etc/rc.d /etc/init.d\fR - useful to know which you need +when using an unfamiliar machine. + .TP .B \-a \-j\fR, \fB\-a \-P\fR [swap], \fB\-a \-P\fR [swap] \- Adds swappiness and vfs cache pressure, and a message to indicate @@ -1487,11 +1526,11 @@ If not the default value, shows default value as well, e.g. For \fB\-P\fR per swap physical partition: -\fBswappiness: 60 (default) cache pressure: 90 (default 100)\fR +\fBswappiness: 60 (default) cache\-pressure: 90 (default 100)\fR For \fB\-j\fR row 1 output: -\fBKernel: swappiness: 60 (default) cache pressure: 90 (default 100)\fR +\fBKernel: swappiness: 60 (default) cache\-pressure: 90 (default 100)\fR \- Adds device kernel major:minor number (Linux only). @@ -1518,7 +1557,7 @@ instead. .B \-a \-p\fR,\fB\-a \-P\fR \- Adds raw partition size, including file system overhead, partition table, e.g. -\fBraw size: 60.00 GiB\fR. +\fBraw\-size: 60.00 GiB\fR. \- Adds percent of raw size available to \fBsize:\fR item, e.g. @@ -1576,6 +1615,10 @@ basically forces the downloader selection to use \fBPerl 5.x\fR \fBHTTP::Tiny\fR which is generally slower than \fBCurl\fR or \fBWget\fR but it may help bypass issues with downloading. +.TP +.B \-\-bt\-tool [bt\-adapter|hciconfig]\fR +Force the use of the given tool for bluetooth report (\fB\-E\fR). + .TP .B \-\-dig\fR Temporary override of \fBNO_DIG\fR configuration item. Only use to test w/wo dig. @@ -1600,16 +1643,38 @@ If it hangs, \fB\-\-display\fR will not work. .TP .B \-\-dmidecode\fR -Force use of \fBdmidecode\fR. This will override \fB/sys\fR data in some lines, -e.g. \fB\-M\fR or \fB\-B\fR. +Shortcut, legacy. See \fB\-\-force dmidecode\fR. .TP .B \-\-downloader [curl|fetch|perl|wget]\fR Force inxi to use Curl, Fetch, Perl, or Wget for downloads. +.TP +.B \-\-force [dmidecode|hddtemp|lsusb|usb-sys|vmstat|wmctl]\fR +Various force options to allow users to override defaults. Values be given +as a comma separated list: + +\fBinxi \-MJ --force dmidecode,lsusb\fR + +\- \fBdmidecode\fR \- Force use of \fBdmidecode\fR. This will override \fB/sys\fR +data in some lines, e.g. \fB\-M\fR or \fB\-B\fR. + +\- \fBhddtemp\fR \- Force use of hddtemp instead of /sys temp data for disks. + +\- \fBlsusb\fR \- Forces the USB data generator to use \fBlsusb\fR as +data source (default). Overrides \fBUSB_SYS\fR in user configuration file(s). + +\- \fBusb-sys\fR \- Forces the USB data generator to use \fB/sys\fR as +data source instead of \fBlsusb\fR (Linux only). + +\- \fBvmstat\fR \- Forces use of vmstat for memory data. + +\- \fBwmctl\fR \- Force \fBSystem\fR item \fBwm\fR to use \fBwmctrl\fR +as data source, override default \fBps\fR source. + .TP .B \-\-hddtemp\fR -Force use of hddtemp instead of /sys temp data for disks. +Shortcut, legacy. See \fB\-\-force hddtemp\fR. .TP .B \-\-host\fR @@ -1641,6 +1706,15 @@ Overrides default use of \fBdig\fR to get WAN IP address. Allows use of normal downloader tool to get IP addresses. Only use if dig is failing, since dig is much faster and more reliable in general than other methods. +.TP +.B \-\-no\-doas\fR +Skips the use of doas to run certain internal features (like \fBhddtemp\fR, \fBfile\fR) +with doas. Not related to running inxi itself with doas/sudo or super user. +Some systems will register errors which will then trigger admin emails in such cases, so if +you want to disable regular user use of doas (which requires configuration to setup +anyway for these options) just use this option, or \fBNO_DOAS\fR configuration item. +See \fB\-\-no\-sudo\fR if you need to disable both types. + .TP .B \-\-no\-host\fR Turns off hostname in System line. This is default when using \fB\-z\fR, @@ -1678,10 +1752,10 @@ lists, or if you have problems making a connection for any reason. Works with .TP .B \-\-no\-sudo\fR Skips the use of sudo to run certain internal features (like \fBhddtemp\fR, \fBfile\fR) -with sudo. Not related to running inxi itself with sudo or super user. Some systems will -register errors which will then trigger admin emails in such cases, so if you want to disable -regular user use of sudo (which requires configuration to setup anyway for these options) -just use this option, or \fBNO_SUDO\fR configuration item. +with sudo. Not related to running inxi itself with sudo or super user. +Some systems will register errors which will then trigger admin emails in such cases, so if +you want to disable regular user use of sudo (which requires configuration to setup +anyway for these options) just use this option, or \fBNO_SUDO\fR configuration item. .TP .B \-\-output [json|screen|xml]\fR @@ -1790,13 +1864,11 @@ parent start program whitelist. .TP .B \-\-usb\-sys\fR -Forces the USB data generator to use \fB/sys\fR as data source -instead of \fBlsusb\fR. +Shortcut, legacy. See \fB\-\-force usb\-sys\fR .TP .B \-\-usb\-tool\fR -Forces the USB data generator to use \fBlsusb\fR as data source. Overrides -\fBUSB_SYS\fR in user configuration file(s). +Shortcut, legacy. See \fB\-\-force lsusb\fR .TP .B \-\-wan\-ip\-url [URL]\fR @@ -1812,8 +1884,7 @@ Same as configuration value (example): .TP .B \-\-wm\fR -Force \fBSystem\fR item \fBwm\fR to use \fBwmctrl\fR as data source, -override default \fBps\fR source. +Shortcut, legacy. See \fB\-\-force wmctl\fR. .TP .B \-\-wrap\-max [integer]\fR @@ -1914,7 +1985,7 @@ Skip /sys debugging in case of a hang. .TP .B \-\-debug\-sys\fR -Force PowerPC debugger parsing of /sys as sudo/root. +Force PowerPC debugger parsing of /sys as doas[BSDs]/sudo/root. .TP .B \-\-debug\-sys\-print\fR @@ -2020,6 +2091,8 @@ to sys admins running servers with many IP addresses. \fBNO_DIG\fR Set to \fB1\fR or \fBtrue\fR to disable WAN IP use of \fBdig\fR and force use of alternate downloaders. +\fBNO_DOAS\fR Set to \fB1\fR or \fBtrue\fR to disable internal use of \fBdoas\fR. + \fBNO_HTML_WAN\fR Set to \fB1\fR or \fBtrue\fR to disable WAN IP use of \fBHTML Downloaders\fR and force use of dig only, or nothing if dig disabled as well. Same as \fB\-\-no\-html\-wan\fR. Only use if dig is failing, and HTML downloaders are hanging. @@ -2174,3 +2247,5 @@ out to be. And of course, a big thanks to locsmif, who figured out a lot of the core methods, logic, and tricks originally used in inxi Gawk/Bash. + +.\" EOF diff --git a/inxi.changelog b/inxi.changelog index 03d2379..4d2af3d 100644 --- a/inxi.changelog +++ b/inxi.changelog @@ -1,3 +1,471 @@ +===================================================================================== +Version: 3.3.02 +Patch: 00 +Date: 2021-03-15 +----------------------------------- +Changes: +----------------------------------- + +Huge upgrade!! Bug Fixes!! Refactors!!! BSDs!!! More BSDs!!! +raspberry pi!! New Features!!! Enhanced old features!!! Did I +mention bluetooth?! USB? Audio? No? well, all hugely upgraded! + +------------------------------------------------------------------------ +BUGS: + +1. Sadly, 3.3.01 went out with a bug, forgot to remove a debugger, +resulted in hardcoded kernel compiler version always showing. + +Note that there is a new inxi-perl/docs/inxi-bugs.txt file to +track such bugs, and matched to specific tagged releases so you +know the line number and items to update to fix it. + +2. Typo in manjaro system base match resulted in failing to report +system base as expected. + +------------------------------------------------------------------------ +KNOWN ISSUES BUT CAN'T OR WON'T BE FIXED: + +1. OpenBSD made fvwm -version output an error along with the +version, and not in the normal format for standard fvwm, this +is just too complicated to work around for now, though it could +be in theory by creating a dedicated fvwm-oBSD item in +program_values. But that kind of granularity gets too hard to track, +and they are likely to change or fix this in the future anyway. +Best is they just restore default -version output to what it is +elsewhere, not nested in error outputs. + +2. Discovered an oddity, don't know how widespread this +is, but Intel SSDs take about 200 milliseconds to get the sys +hwmon based drive temps, when it should take under a +millisecond, this may be a similar cause as those drives having +a noticeable SMART report delay, not sure. This is quite +noticeable since 200 ms is about 15% of the total execution +time on my test system. + +------------------------------------------------------------------------ +FIXES: + +1. For --recommends, added different rpm SUSE xdpyinfo package name. + +2. Distro Data: added double term filter for lsb-release due to sometimes +generating repeated names in distro. + +3. Packages: fix for appimage package counts. + +4. Desktop: fixed ID for some wm when no xprop installed, fallback to +using @ps_cmd detections, which usually work fine. + +5a. When swap used was 0, showed N/A, fixed to correctly show 0 KiB. + +5b. If no swap devices found, BSDs were not correctly showing +no swap data found message. Corrected. + +6a. Bluetooth: Removed hcidump from debugger, in some cases, that will +just hang endlessly. Also wrapped bluetoothctl and bt-adapter debugger +data collection with @ps_cmd bluetooth running test. Only run if +bluetooth service is running. + +6b. Bluetooth: running detections have to be very strict, only +bluetoothd, not bluetooth, the latter can show true when bluetoothd +is not running, and did in my tests. + +7. USB: with Code Change 1, found a few places where fallback usb type +detections were creating false matches, which resulted in say, +bluetooth devices showing up as network devices due to the presence +of the word 'wireless' in the device description. These matches are +all updated and revised to be more accurate and less error prone. + +8. Battery: an oversight, had forgotten to have percent used of +available capacity, which made Battery data hard to decipher, now +it shows the percent of available total, as well as the condition +percent, so it's easier to understand the data now, and hopefully +more clear. + +9a. OpenBSD changed usbdevs output format sometime in the latest +releases, which made the delicate matching patterns fail. Updated +to handle both variants. They also changed pcidump -v formatting +at some point, now inxi will try to handle either. Note that +usbdevs updates also work fine on NetBSD. + +9b. FreeBSD also changed their pciconf output in beta 13.0, which +also broke the detections completely, now checks for old and new +formats. Sigh. It should not take this much work to parse tools +whose output should be consistent and reliable. Luckily I ran +the beta prior to this release, or all pci device detections +would simply have failed, without fallback. + +9c. Dragonfly BSD also changed an output format, in vmstat, that +made the RAM used report fail. Since it's clearly not predictable +which BSD will change support for which vmstat options, now just +running vmstat without options, and then using processing logic +to determine what to do with the results. + +10. It turns out NetBSD is using /proc/meminfo, who would have +thought? for memory data, but they use it in a weird way that +could result in either negative or near 0 ram used. Added in +some filters to not allow such values to print, now it tries +to make an educated guess about how much ram the system is +really using based on some tests. + +11. Something you'd only notice if testing a lot, uptime failed +when the uptime was < 1 minute, it had failed to handle the seconds +only option, now it does, seconds, minutes, hours:minutes, +days hours:minutes, all work. + +12. Missed linsysfs type to exclude in partitons, that was a partner +to linprocfs type, both are BSD types. + +13. Added -ww to ps arguments, that stops the cutting width to terminal +size default behavior in BSDs, an easy fix, wish I'd known about +that a long time ago. + +15. gpart seems to show sizes in bytes, not the expected KiB, so +that's now handled internally. Hopefully that odd behavior won't +randomly change in the future, sigh. + +16. Fixed slim dm detection, saw instance where it's got slim.pid +like normal dms, not the slim.lock which inxi was looking for, so +now inxi looks for both, and we're all happy! + +------------------------------------------------------------------------ +ENHANCEMENTS: + +1. Added in something that should have been there all along, now inxi +validates the man page download as well as the self, this avoids +corrupted downloads breaking the man. + +2. Init: added support for shepherd init system. + +3. Distro Data: added support for guix distro ID; added support for +NomadBSD, GhostBSD, HardenedBSD system base. GhostBSD also shows the main +package version for the distro version ID, which isn't quite the +same as the version you download, but it's close. Also added os-release +support for BSDs, using similar tests as for linux distros, that +results in nicer outputs for example for Dragonfly BSD. + +4. Package Data: added guix/scratch [venom]/kiss/nix package managers. +Update for slackware 15 package manager data directory relocation, +now handles either legacy current or future one. + +5. Repos: added scratch/kiss/nix-channels; Added GhostBSD, HardenedBSD +pkg repos. + +6. USB Data: added usbconfig. That's FreeBSD's, and related systems. + +7. Device Data: Added pcictl support, that's NetBSD's, I thought +inxi had supported that, but then I remembered last time I tried to +run netBSD in a vm, I couldn't get it figured out. Now debugged and +working reasonably well. + +8. Raspberry Pi 3, 4: ethernet nic now detected; wifi device, +which is on a special mmcnr type, now works, that stopped working in +pi 3, due to the change, now it's handled cleanly. Also added support +for pi bluetooth, which lives on a special serial bus, not usb. +For Raspberry Pi OS, added system base detections, which are tricky. +Also matched mmcnr devices to IF data, which was trickyy as well. +Note that as far as I could discover, only pi puts wifi on mmcnr. + +9. Bluetooth: due to deprecated nature of the fine hciconfig +utility, added in support for bt-adapter, which also allows matching +of bluetooth data to device data, but is very sparse in info +supplied compared to hciconfig. bluetoothctl does not have enough +data to show the hci device, so it's not used, since inxi can't +match the bluetooth data to the device (no hci[x]). This should help +the distros that are moving away from hciconfig, in particular, +AUR is only way arch users can get hciconfig, which isn't ideal. + +10. New tool and feature, ServiceData, this does two things, +as cross platform as practical, show status of bluetooth service, +this should help a lot in support people debugging bluetooth problems, +since you have bluetooth enabled but down, or up, disabled, and you +can also have the device itself down or up, so now it shows all that +data together for when it's down, but when the device is up, it just +shows the device status since the other stuff is redundant then. + +In -Sa, it now shows the OS service manager that inxi detected +using a bunch of fallback tests, that's useful to admins who +are on a machine they don't know, then you can see the service +manager to use, like rc-service, systemctl, service, sv, etc. + +11. Big update for -A: Sound Servers: had always been really +just only ALSA, now it shows all detected sound servers, and whether +they are running or not. Includes: ALSA, OSS, PipeWire, PulseAudio, +sndio, JACK. Note that OSS version is a guess, might be wrong source +for the version info. + +12. Added USB device 'power:' item, that's in mA, not a terrible +thing to have listed, -xxx. This new feature was launched cross +platform, which is nice. Whether the BSD detections will break +in the future of course depends on whether they change the output +formats again or not. Also added in USB more chip IDs, which can +be useful. For BSDs, also added in a synthetic USB rev, taken +from the device/hub speeds. Yes, I know, USB 2 can have low speed, +full speed, or high speed, and 1.1 can have low and full speeds, +so you actually can't tell the USB revision version from the speeds, +but it's close enough. + +13. Made all USB/Device data the same syntax and order, more +predictable, bus, chip, class IDs all the same now. + +14. Added in support for hammer and null/nullfs file system types, +which trigger 'logical:' type device in partitions, that's also +more correct than the source: Err-102 that used to show, which +was really just a flag to alert me visibly that the partition +type detection had simply failed internally. Now for detected +types, like zfs tank/name or null/nullfs, it knows they are +logical structures. + +15. Expanded BSD CPU data, where available, now can show L1/L2/ +L3 cache, cpu arch, stepping, family/model ids, etc, which is +kind of nifty, although, again, delicate fragile rules that +will probably break in the future, but easier to fix now. + +16. By an old request, added full native BSD doas support. +That's a nice little tool, and it plugged in fairly seamlessly +to existing sudo support. Both the internal doas/sudo stuff +should work the same, and the detection of sudo/doas start +should work the same too. + +17a. Shell/Parent Data: Big refactor of the shell start/parent logic, +into ShellData which helped resolve some issues with running-in +showing shell name, not vt terminal or program name. Cause of that +is lots of levels of parents before inxi could reach the actual +program that was running inxi. Solution was to change to a longer +loop, and let it iterate 8 times, until it finds something that is +not a shell or sudo/doas/su type parent, this seems to work quite +well, you can only make it fail now if you actually try to do it on +purpose, which is fine. + +This was very old logic, and carried some mistakes and +redundancies that made it very hard to understand, that's cleaned +up now. Also restored the old (login) value, which shows +when you use your normal login account on console, some system +will also now show (sudo,login) if the login user sudos inxi, +but that varies system to system. + +17b. BSD running-in: Some of the BSDs now support the -f flag +for ps, which made the parent logic for running-in possible for +BSDs, which was nice. Some still don't support it, like OpenBSD +and NetBSD, but that's fine, inxi tests, and if no support detected, +just shows tty number. Adding in more robust support here cleaned +up some redundant logic internally as well. + +17c. Updated terminal and shell ID detections, there's quite a few +new terminals this year, and a new shell or two. Those are needed +for more reliable detections of when the parent is NOT a shell, +which is how we find what it is. + +18. Added ctwm wm support, that's the new default for NetBSD, +based on twm, has version numbers. + +19. Upgraded BSD support for gpart and glabel data, now should +catch more more often. + +20. For things like zfs raid, added component size, that doesn't +always work due to how zfs refers to its components, but it often +does, which is better than never before. + +21. To make BSD support smoother, got rid of some OpenBSD only +rules, which in fact often apply to NetBSD as well. That may +lead to some glitches, but overall it's better to totally stay +away from OpenBSD only tests, and all BSD variant tests, and +just do dynamic testing that will work when it applies, and +not when it doesn't. In this case, added ftp downloader support +for netBSD by removing the openBSD only flag for that item. + +There's a bit of a risk there in a sense since if different ftp +programs with different options were to be the fallback for something +else, it might get used, but that's fine, it's a corner case, better +to have them all work now than to worry about weird future things. +But limiting it to only BSDs should get rid of most of the problem. + +vmstat and optical drive still use net/openbsd specifics because +it is too tricky to figure out it out in any more dynamic way. + +22. For -Sxxx, added if systemd, display, virtual terminal number. +Could be useful to debug subtle issues, if the user is for example +not running their desktop in vt 7, the default for most systems. + +------------------------------------------------------------------------ +CHANGES: + +1. Moved battery voltage to -Bx output, the voltage is quite +important to know since that is the key indicator of battery state. +If voltage is within .5 volts of specified minimum, shows voltage +for -B since that's a prefail condition, it's getting close to +death. + +2. In partitions and raid, when the device was linear raid logical +type layout, it said, no-raid, when it should be 'linear', that's +now cleaner and more correct. + +3. When running-in is a tty value, it will now show the entire +tty ID, minus the '/dev/tty', this will be more precise, and also +may resolve cases where tty was fully alpha, no numbers, previously +inxi filtered out everything that was not a number, but that can +in some tty types remove critical tty data, so now it will show: + +running-in: +tty 2 [not changed]; tty pts/2 [adds pts/]; tty E2 [adds the E]; +tty rx [would have not shown at ll before] + +------------------------------------------------------------------------ +CODE CHANGES: + +NOTE: unlike the previous refactors, a lot of these changes were +done to make inxi more maintainable, which means, slightly less +optimized, which has been my preference in the past, but if the +stuff can't be maintained, it doesn't matter how fast it runs! + +These changes have really enhanced the quality of the code and +made it a lot easier to work with. It's also now a lot easier to +add debuggers, force/fake data switches, etc, so it gets done, +unlike before, when it was a pain, so it got skipped, and then +caused bugs because of stray debuggers left in place, and so on. + +The bright side is while reading up on this, I learned that using +very large subs is much more efficient than many small ones, +which I've always felt was the case, and it is, so the style +used internally in inxi proves to be the best one for optimizations. + +These refactors, ongoing, have now touched at least 1/3, almost +1/2, of the entire inxi codebase, so the stuff is getting more +and more consistent and up to date, but given how old the logic +is in places, there will be more refactors in the future, and +maybe once the code is easier to maintain, some renewed +optimizations!, if we can find anything that makes sense, like +passing array/hash references back to the caller, already the +first half is done, passing references to the sub/method always. + +The second part is started, using the Benchmark Perl module, +which really speeds up testing and helps avoid pointless tweaks +that do little re speed improvements. + +I could see with some care some areas where working on data +directly via references could really speed things up, but it's +hard to write and read that type of code, but it's already being +done in the recursive data and output logics, and a few other +places. + +1. Large refactor of USBData, that was done in part to help make +it work for BSDs better, but also to get it better organized. + +This refactor also made all the device items, like -A,-G,-N,-E +use the same methods for creating USB output, previously they +had used a hodgepodge of methods, some super old, it was not +possible to add USB support more extensively for BSDs without +this change. + +Also added in some fallback usb type detection tools using +several large online collections of that info to see what possible +matching patterns could catch more devices and correctly match +them to their type, which is the primary way now that usb output +per type is created. This really helps with BSDs, though BSD +usb utilities suffer from less data than lsusb so they don't always +get device name strings in a form where they can be readily ID'ed, +but it's way better than it was before, so that's fine! + +Moved all previous methods of detecting if a card/device was USB +into USBData itself so it would all be in one place, and easier +to maintain. + +All USB tools now use bus_id_alpha for sorting, and all now +sort as well, that was an oversight, previously the BSD usb +tools were not sorted, but those have been enhanced a lot, so +sorting on alpha synthetic bus ids became possible. + +Removed lsusb as a BSD option, it's really unreliable, and the data +is different, and also varies a lot, it didn't really work at all +in Dragonfly, or had strange output, so lsusb is now a linux only +item. + +2. Moved various booleans that were global to %force, %loaded, and +some to the already present, but lightly used, %use hashes. It was +getting too hard to add tests etc, which was causing bugs to happen. +Yes, using hashes is slower than hardcoding in the boolean scalars, +but this change was done to improve maintainability, which is starting +to matter more. + +3. Moved several sets of subs to new packages, again, to help with +debugging and maintainability. MemoryData, redone in part to +handle the oddities with NetBSD reporting of free, cached, and +buffers, but really just to make it easier to work with overall. +Also moved kernel parameter logic to KernelParameters, gpart logic +to GpartData, glabel logic to GlabelData, ip data IpData, check_tools +to CheckTools, which was also enhanced largely, and simplified, +making it much easier to work with. + +4. Wrapped more debugger logic in $fake{data} logic, that makes +it harder to leave a debugger uncommented, now to run it, you have +to trigger it with $fake{item} so the test runs, that way even if +I forget to comment it out, it won't run for regular user. + +5. Big update to docs in branch inxi-perl/docs, those are now +much more usable for development. Updated in particular +inxi-values.txt to be primary reference doc for $fake, $dbg, +%force, %use, etc types and values. Also updated inxi-optimization.txt +and inxi-resources.txt to bring them closer to the present. + +Created inxi-bugs.txt as well, which will help to know which known +bugs belonged to which frozen pools. These bugs will only refer +to bugs known to exist in tagged releases in frozen pool distros. + +6. For sizes, moved most of the sizing to use main::translate_size, +this is more predictable, though as noted, these types of +changes make inxi a bit slower since it moved stuff out of inline +to using quick expensive sub calls, but it's a lot easier to +maintain, and that's getting to be more important to me now. + +7. In order to catch live events, added in dmesg to dmesg.boot data +in BSDs, that's the only way I could find to readily detect +usb flash drives that were plugged in after boot. Another hack, +these will all come back to bite me, but that's fine, the base +is easier to work on and debug now, so if I want to spend time +revisiting the next major version BSD releases, it will be easier +to resolve the next sets of failures. + +8. A big change, I learned about the non greedy operator for +regex patterns, ?, as in, .*?(next match rule), it will now +go up only to the next match rule. Not knowing this simple +little thing made inxi use some really convoluted regex to +avoid such greedy patterns. Still some gotchas with ?, like +it ignores following rules that are zero or 1, ? type, and +just treats it as zero instances. But that's easy to work with. + +9. Not totally done, but now moved more to having set data +tools set their $loaded{item} value in get data, not externally, +that makes it easier to track the stuff. Only where it makes +sense, but there's a lot of those set/get items, they should +probably all become package/classes, with set/get I think. + +10. Optimized reader() and grabber() and set_ps_aux_data(), all +switched from using grep/map to using for loops, that means +inxi doesn't have to go through each array 2x anymore, actually +4x in the case of set_ps_aux_data(). This saved a visible +amount of execution time, I noticed this lag when running +pinxi through NYTProf optimizer, there was a quite visible +time difference between grabber/reader and the subshell +time, these optimizations almost removed that difference, +meaning only the subshell now really takes any time to run. + +Optimized url_cleaner and data_cleaner in RepoData, those +now just work directy on the array references, no returns. + +Ran some more optimization tests, but will probably hold off +on some of them, for example, using cleaner() by reference is +about 50% faster than by copy, but redoing that requires +adding in many copies from read only things like $1, so +the change would lead to slightly less clean code, but may +revisit this in the future, we'll see. + +But in theory, basically all the core internal tools that +take a value and modify it should do that by reference +purely since it's way faster, up to 10x. + +----------------------------------- +-- Harald Hope - Mon, 15 Mar 2021 18:42:04 -0700 + ===================================================================================== Version: 3.3.01 Patch: 00