aboutsummaryrefslogtreecommitdiffstats
path: root/inxi
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2018-04-22 15:17:42 -0400
committerLibravatarUnit 193 <unit193@ubuntu.com>2018-04-22 15:17:42 -0400
commit2f191c302fed4463b1192d2595184a65411adf25 (patch)
treebb9c1db12554ac8724f3b5850d0e780ab4309216 /inxi
parente318468b98989bebe33f48b101115f9b7500b10a (diff)
downloadinxi-2f191c302fed4463b1192d2595184a65411adf25.tar.bz2
inxi-2f191c302fed4463b1192d2595184a65411adf25.tar.xz
inxi-2f191c302fed4463b1192d2595184a65411adf25.tar.zst
New upstream version 3.0.07-1upstream/3.0.07-1
Diffstat (limited to 'inxi')
-rwxr-xr-xinxi31508
1 files changed, 15818 insertions, 15690 deletions
diff --git a/inxi b/inxi
index f36c6dc..92926b5 100755
--- a/inxi
+++ b/inxi
@@ -1,697 +1,124 @@
-#!/usr/bin/env bash
-########################################################################
-SELF_NAME='inxi'
-# don't quote the following, parsers grab these too
-SELF_VERSION=2.3.56
-SELF_DATE=2018-01-17
-SELF_PATCH=00
-########################################################################
-#### SPECIAL THANKS
-########################################################################
-#### Special thanks to all those in #lsc and #smxi for their tireless
-#### dedication helping test inxi modules.
-########################################################################
-#### ABOUT INXI
-########################################################################
-#### inxi is a fork of infobash 3.02, the original bash sys info tool by locsmif
-#### As time permits functionality improvements and recoding will occur.
-####
-#### inxi, the universal, portable, system information tool for irc.
-#### Tested with Irssi, Xchat, Konversation, BitchX, KSirc, ircII,
-#### Gaim/Pidgin, Weechat, KVIrc and Kopete.
-#### Original infobash author and copyright holder:
-#### Copyright (C) 2005-2007 Michiel de Boer a.k.a. locsmif
-#### inxi version: Copyright (C) 2008-2018 Harald Hope
-#### Additional features (C) Scott Rogers - kde, cpu info
-#### Further fixes (listed as known): Horst Tritremmel <hjt at sidux.com>
-#### Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch
-#### Jarett.Stevens - dmidecde -M patch for older systems with the /sys
-####
-#### Current project home page/wiki/git: https://github.com/smxi/inxi
-#### Documentation/wiki pages can be found at https://smxi.org/docs/inxi.htm
-#### Project forums: http://techpatterns.com/forums/forum-33.html
-#### IRC support: irc.oftc.net channel #smxi
-#### Version control:
-#### * https://github.com/smxi/inxi
-#### * git: git pull https://github.com/smxi/inxi master
-#### * For basic version, no gz files, much smaller, do:
-#### git clone https://github.com/smxi/inxi --branch master-plain --single-branch
-#### * source repository url: https://github.com/smxi/inxi
-####
-#### This program is free software; you can redistribute it and/or modify
-#### it under the terms of the GNU General Public License as published by
-#### the Free Software Foundation; either version 3 of the License, or
-#### (at your option) any later version.
-####
-#### This program is distributed in the hope that it will be useful,
-#### but WITHOUT ANY WARRANTY; without even the implied warranty of
-#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#### GNU General Public License for more details.
-####
-#### You should have received a copy of the GNU General Public License
-#### along with this program. If not, see <http://www.gnu.org/licenses/>.
-####
-#### If you don't understand what Free Software is, please read (or reread)
-#### this page: http://www.gnu.org/philosophy/free-sw.html
-####
-#### But the main thing about Free Software is that its' about the freedom
-#### of the individual user, not the corporations that try to coopt it. This
-#### grows easy to forget when people confuse freedom with open source.
-########################################################################
-####
-#### PACKAGE NAME NOTES
-#### * Package names in (...) are the Debian Squeeze package name. Check your
-#### distro for proper package name by doing this: which <application>
-#### then find what package owns that application file. Or run --recommends
-#### which shows package names for Debian/Ubuntu, Arch, and Fedora/Redhat/Suse
-####
-#### DEPENDENCIES
-#### * bash >=3.0 (bash); df, readlink, stty, tr, uname, wc (coreutils);
-#### gawk (gawk); grep (grep); lspci (pciutils); ps; find (findutils);
-#### perl (Modules: [HTTP::Tiny IF NO wget/curl/fetch/ftp]; Net::FTP; File::Find);
-#### * Also the proc filesystem should be present and mounted for Linux
-#### * Some features, like -M and -d will not work, or will work incompletely,
-#### if /sys is missing
-####
-#### Apparently unpatched bash 3.0 has arrays broken; bug reports:
-#### http://ftp.gnu.org/gnu/bash/bash-3.0-patches/bash30-008
-#### http://lists.gnu.org/archive/html/bug-bash/2004-08/msg00144.html
-#### Bash 3.1 for proper array use
-####
-#### Arrays work in bash 2.05b, but "grep -Em" does not
-####
-#### RECOMMENDS (Needed to run certain features, listed by option)
-#### -A - for output of usb audio information: lsusb (usbutils)
-#### -Ax -Nx - for audio/network module version: modinfo (module-init-tools)
-#### -Dx - for hdd temp output (root only default): hddtemp (hddtemp)
-#### For user level hdd temp output: sudo (sudo)
-#### Note: requires user action for this feature to run as user (edit /etc/sudoers file)
-#### -G - full graphics output requires: glxinfo (mesa-utils); xdpyinfo (X11-utils);
-#### xrandr (x11-xserver-utils)
-#### -i - IP information, local/wan - ip (iproute) legacy, not used if ip present: ifconfig (net-tools)
-#### -I - uptime (procps, check Debian if changed)
-#### -Ix - view current runlevel while not in X window system (or with -x): runlevel (sysvinit)
-#### -m - all systems, dmidecode, unless someone can find a better way.
-#### -M - for older systems whose kernel does not have /sys data for machine, dmidecode (dmidecode)
-#### -o - for unmounted file system information in unmounted drives (root only default): file (file)
-#### Note: requires user action for this feature to run as user (edit /etc/sudoers file)
-#### For user level unmounted file system type output: sudo (sudo)
-#### -s For any sensors output, fan, temp, etc: sensors (lm-sensors)
-#### Note: requires setup of lm-sensors (sensors-detect and adding modules/modprobe/reboot,
-#### and ideally, pwmconfig) prior to full output being available.
-#### -S For desktop environment, user must be in X and have xprop installed (in X11-utils)
-#### -xx@14 - it really helps to have 'tree' installed on Linux systems with /sys for
-#### debugger data collection, that creates a very useful map of /sys.
-########################################################################
-#### BSD Adjustments
-#### * sed -i '' form supported by using SED_I="-i ''".
-#### * Note: New BSD sed supports using -r instead of -E for compatibility with gnu sed
-#### However, older, like FreeBSD 7.x, does not have -r so using SED_RX='-E' for this.
-#### * Gnu grep options can be used if the function component is only run in linux
-#### These are the options that bsd grep does not support that inxi uses: -m <number> -o
-#### so make sure if you use those to have them in gnu/linux only sections.
-#### It appears that freebsd uses gnu grep but openbsd uses bsd grep, however.
-#### * BSD ps does not support --without-headers option, and also does not support --sort <option>
-#### Tests show that -m fails to sort memory as expected, but -r does sort cpu percentage.
-#### * BSD_TYPE is set with values null, debian-bsd (debian gnu/kfreebsd), bsd (all other bsds)
-#### * Subshell and array closing ) must not be on their own line unless you use an explicit \
-#### to indicate that logic continues to next line where closing ) or )) are located.
-########################################################################
-#### CONVENTIONS:
-#### * Character Encoding: UTF-8 - this file contains special characters that must be opened and saved as UTF8
-#### * Indentation: TABS
-#### * Do not use `....` (back quotes), those are totally non-reabable, use $(....).
-#### * Do not use one liner flow controls.
-#### The ONLY time you should use ';' (semi-colon) is in this single case: if [[ condition ]];then.
-#### Never use compound 'if': ie, if [[ condition ]] && statement.
-#### * Note: [[ -n $something ]] - double brackets does not require quotes for variables: ie, "$something".
-#### * Always use quotes, double or single, for all string values. Really. It won't kill you.
-#### * All new code/methods must be in a function.
-
-#### * For all boolean tests, use 'true' / 'false'.
-#### !! Do NOT use 0 or 1 unless it's a function return.
-#### * Avoid complicated tests in the if condition itself.
-#### * To 'return' a value in a function, use 'echo <var>'.
-#### * For gawk: use always if ( num_of_cores > 1 ) { hanging { starter for all blocks
-#### This lets us use one method for all gawk structures, including BEGIN/END, if, for, etc
-#### * Using ${VAR} is about 30% slower than $VAR because bash has to check the stuff for actions
-#### SUBSHELLS ARE EXPENSIVE! - run these two if you do not believe me.
-#### time for (( i=0; i<1000; i++ )) do ff='/usr/local/bin/foo.pid';ff=${ff##*/};ff=${ff%.*};done;echo $ff
-#### time for (( i=0; i<1000; i++ )) do ff='/usr/local/bin/foo.pid';ff=$( basename $ff | cut -d '.' -f 1 );done;echo $ff
-####
-#### VARIABLE/FUNCTION NAMING:
-#### * All functions should follow standard naming--verb adjective noun.
-#### ie, get_cpu_data
-#### * All variables MUST be initialized / declared explicitly, either top of file, for Globals, or using local
-#### * All variables should clearly explain what they are, except counters like i, j.
-#### * Each word of Bash variable must be separated by '_' (underscore) (camel form), like: cpu_data
-#### * Each word of Gawk variable must be like this (first word lower, following start with upper): cpuData
-#### * Global variables are 'UPPER CASE', at top of this file.
-#### ie, SOME_VARIABLE=''
-#### * Local variables are 'lower case' and declared at the top of the function using local, always.
-#### ie: local some_variable=''
-#### * Locals that will be inherited by child functions have first char capitalized (so you know they are inherited).
-#### ie, Some_Variable
-#### * Booleans should start with b_ (local) or B_ (global) and state clearly what is being tested.
-#### * Arrays should start with a_ (local) or A_ (global).
-####
-#### SPECIAL NOTES:
-#### * The color variable ${C2} must always be followed by a space unless you know what
-#### character is going to be next for certain. Otherwise irc color codes can be accidentally
-#### activated or altered.
-#### * For native script konversation support (check distro for correct konvi scripts path):
-#### ln -s <path to inxi> /usr/share/apps/konversation/scripts/inxi
-#### DCOP doesn't like \n, so avoid using it for most output unless required, as in error messages.
-#### * print_screen_output " " # requires space, not null, to avoid error in for example in irssi
-#### * For logging of array data, array must be placed into the a_temp, otherwise only the first key logs
-#### * In gawk search patterns, . is a wildcard EXCEPT in [0-9.] type containers, then it's a literal
-#### So outside of bracketed items, it must be escaped, \. but inside, no need. Outside of gawk it should
-#### be escaped in search patterns if you are using it as a literal.
-####
-#### PACKAGE MANAGER DATA (note, while inxi tries to avoid using package managers to get data, sometimes
-#### it's the only way to get some data):
-#### * dpkg options: http://www.cyberciti.biz/howto/question/linux/dpkg-cheat-sheet.php
-#### * pacman options: https://wiki.archlinux.org/index.php/Pacman_Rosetta
-####
-#### As with all 'rules' there are acceptions, these are noted where used.
-###################################################################################
-#### KDE Konversation information. Moving from dcop(qt3/KDE3) to dbus(qt4/KDE4)
-###################################################################################
-#### * dcop and dbus -- these talk back to Konversation from this program
-#### * Scripting info -- http://konversation.berlios.de/docs/scripting.html
-#### -- http://www.kde.org.uk/apps/konversation/
-#### * dbus info -- http://dbus.freedesktop.org/doc/dbus-tutorial.html
-#### view dbus info -- https://fedorahosted.org/d-feet/
-#### -- or run qdbus
-#### * Konvi dbus/usage-- qdbus org.kde.konversation /irc say <server> <target-channel> <output>
-#### * Python usage -- http://wiki.python.org/moin/DbusExamples (just in case)
-####
-#### Because webpages come and go, the above information needs to be moved to inxi's wiki
-########################################################################
-#### Valuable Resources
-#### CPU flags: http://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean
-#### Advanced Bash: http://wiki.bash-hackers.org/syntax/pe
-#### gawk arrays: http://www.math.utah.edu/docs/info/gawk_12.html
-#### raid mdstat: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
-#### http://www.howtoforge.com/replacing_hard_disks_in_a_raid1_array
-#### https://raid.wiki.kernel.org/index.php/Mdstat
-#### dmi data: http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.0.pdf
-########################################################################
-#### TESTING FLAGS
-#### inxi supports advanced testing triggers to do various things, using -! <arg>
-#### -! 1 - triggers default B_TESTING_1='true' to trigger some test or other
-#### -! 2 - triggers default B_TESTING_2='true' to trigger some test or other
-#### -! 3 - triggers B_TESTING_1='true' and B_TESTING_2='true'
-#### -! 10 - triggers an update from the primary dev download server instead of source
-#### -! 11 - triggers an update from source branch one - if present, of course
-#### -! 12 - triggers an update from source branch two - if present, of course
-#### -! 13 - triggers an update from source branch three - if present, of course
-#### -! 14 - triggers an update from source branch four - if present, of course
-#### -! <http://......> - Triggers an update from whatever server you list.
-#### LOG FLAGS (logs to $HOME/.inxi/inxi.log with rotate 3 total)
-#### -@ 8 - Basic data logging of generated data / array values
-#### -@ 9 - Full logging of all data used, including cat of files and system data
-#### -@ 10 - Basic data logging plus color code logging
-########################################################################
-#### VARIABLES
-########################################################################
-
-## NOTE: we can use hwinfo if it's available in all systems, or most, to get
-## a lot more data and verbosity levels going
-
-### DISTRO MAINTAINER FLAGS ###
-# flag to allow distro maintainers to turn off update features. If false, turns off
-# -U and -! testing/advanced update options, as well as removing the -U help menu item
-# NOTE: Usually you want to create these in /etc/inxi.conf to avoid having to update each time
-B_ALLOW_UPDATE='true'
-B_ALLOW_WEATHER='true'
-
-### USER CONFIGS: SET IN inxi.conf file see wiki for directions ###
-# http://code.google.com/p/inxi/wiki/script_configuration_files
-# override in user config if desired, seems like less than .3 doesn't work as reliably
-CPU_SLEEP='0.3'
-FILTER_STRING='<filter>'
-
-# for features like help/version will fit to terminal / console screen width. Console
-# widths will be dynamically set in main() based on cols in term/console
-COLS_MAX_CONSOLE='115'
-COLS_MAX_IRC='105'
-# note, this is console out of x/display server, will also be set dynamically
-# not used currently, but maybe in future
-COLS_MAX_NO_DISPLAY='140'
-PS_COUNT=5
-# change to less, or more if you have very slow connection
-DL_TIMEOUT=8
-### END USER CONFIGS ###
-
-### LOCALIZATION - DO NOT CHANGE! ###
-# set to default LANG to avoid locales errors with , or .
-LANG=C
-# Make sure every program speaks English.
-LC_ALL="C"
-export LC_ALL
-
-### ARRAYS ###
-## Prep
-# Clear nullglob, because it creates unpredictable situations with IFS=$'\n' ARR=($VAR) IFS="$ORIGINAL_IFS"
-# type constructs. Stuff like [rev a1] is now seen as a glob expansion pattern, and fails, and
-# therefore results in nothing.
-shopt -u nullglob
-## info on bash built in: $IFS - http://tldp.org/LDP/abs/html/internalvariables.html
-# Backup the current Internal Field Separator
-ORIGINAL_IFS="$IFS"
-
-## Initialize
-A_ALSA_DATA=''
-A_AUDIO_DATA=''
-A_BATTERY_DATA=''
-A_CMDL=''
-A_CPU_CORE_DATA=''
-A_CPU_DATA=''
-A_CPU_TYPE_PCNT_CCNT=''
-A_DEBUG_BUFFER=''
-
-A_GCC_VERSIONS=''
-A_GLX_DATA=''
-A_GRAPHICS_CARD_DATA=''
-A_GRAPHIC_DRIVERS=''
-A_HDD_DATA=''
-A_INIT_DATA=''
-A_INTERFACES_DATA=''
-A_MACHINE_DATA=''
-A_MEMORY_DATA=''
-A_NETWORK_DATA=''
-A_OPTICAL_DRIVE_DATA=''
-A_PARTITION_DATA=''
-A_PCICONF_DATA=''
-A_PS_DATA=''
-A_RAID_DATA=()
-A_SENSORS_DATA=''
-A_UNMOUNTED_PARTITION_DATA=''
-A_WEATHER_DATA=''
-A_DISPLAY_SERVER_DATA=''
-
-### BOOLEANS ###
-## standard boolean flags ##
-B_BSD_DISK_SET='false'
-B_COLOR_SCHEME_SET='false'
-B_CONSOLE_IRC='false'
-# triggers full display of cpu flags
-B_CPU_FLAGS_FULL='false'
-B_CURL='true'
-# test for dbus irc client
-B_DBUS_CLIENT='false'
-# kde dcop
-B_DCOP='false'
-# Debug flood override: make 'true' to allow long debug output
-B_DEBUG_FLOOD='false'
-# for special -i debugging cases
-B_DEBUG_I='false'
-B_DMIDECODE_SET='false'
-# show extra output data
-B_EXTRA_DATA='false'
-# triggered by -xx
-B_EXTRA_EXTRA_DATA='false'
-B_FETCH='true'
-B_FORCE_DMIDECODE='false'
-B_ID_SET='false'
-# override certain errors due to currupted data
-B_HANDLE_CORRUPT_DATA='false'
-B_LABEL_SET='false'
-B_LSPCI='false'
-B_LOG_COLORS='false'
-B_LOG_FULL_DATA='false'
-B_MAN='true'
-B_MAPPER_SET='false'
-B_OUTPUT_FILTER='false'
-B_OVERRIDE_FILTER='false'
-B_PCICONF='false'
-B_PCICONF_SET='false'
-# kde qdbus
-B_QDBUS='false'
-B_POSSIBLE_PORTABLE='false'
-B_RAID_SET='false'
-B_ROOT='false'
-B_RUN_COLOR_SELECTOR='false'
-B_RUNNING_IN_DISPLAY='false' # in x type display server
-if tty >/dev/null;then
- B_IRC='false'
-else
- B_IRC='true'
-fi
-# this sets the debug buffer
-B_SCRIPT_UP='false'
-B_SHOW_ADVANCED_NETWORK='false'
-# Show sound card data
-B_SHOW_AUDIO='false'
-B_SHOW_BASIC_RAID='false'
-B_SHOW_BASIC_CPU='false'
-B_SHOW_BASIC_DISK='false'
-B_SHOW_BASIC_OPTICAL='false'
-B_SHOW_BATTERY='false'
-B_SHOW_BATTERY_FORCED='false'
-B_SHOW_CPU='false'
-B_SHOW_DISPLAY_DATA='false'
-B_SHOW_DISK_TOTAL='false'
-B_SHOW_DISK='false'
-# Show full hard disk output
-B_SHOW_FULL_HDD='false'
-B_SHOW_FULL_OPTICAL='false'
-B_SHOW_GRAPHICS='false'
-# Set this to 'false' to avoid printing the hostname, can be set false now
-B_SHOW_HOST='true'
-B_SHOW_INFO='false'
-B_SHOW_IP='false'
-B_SHOW_LABELS='false'
-B_SHOW_MACHINE='false'
-B_SHOW_MEMORY='false'
-B_SHOW_NETWORK='false'
-# either -v > 3 or -P will show partitions
-B_SHOW_PARTITIONS='false'
-B_SHOW_PARTITIONS_FULL='false'
-B_SHOW_PS_CPU_DATA='false'
-B_SHOW_PS_MEM_DATA='false'
-B_SHOW_RAID='false'
-# because many systems have no mdstat file, -b/-F should not show error if no raid file found
-B_SHOW_RAID_R='false'
-B_SHOW_REPOS='false'
-B_SHOW_SENSORS='false'
-# triggers only short inxi output
-B_SHOW_SHORT_OUTPUT='false'
-B_SHOW_SYSTEM='false'
-B_SHOW_UNMOUNTED_PARTITIONS='false'
-B_SHOW_UUIDS='false'
-B_SHOW_WEATHER='false'
-B_SYSCTL='false'
-# triggers various debugging and new option testing
-B_TESTING_1='false'
-B_TESTING_2='false'
-B_UPLOAD_DEBUG_DATA='false'
-B_USB_NETWORKING='false'
-# set to true here for debug logging from script start
-B_USE_LOGGING='false'
-B_UUID_SET='false'
-B_WGET='true'
-B_XORG_LOG='false'
-
-## Directory/file exist flags; test as [[ $(boolean) ]] not [[ $boolean ]]
-B_ASOUND_DEVICE_FILE='false'
-B_ASOUND_VERSION_FILE='false'
-B_BASH_ARRAY='false'
-B_CPUINFO_FILE='false'
-B_DMESG_BOOT_FILE='false' # bsd only
-B_LSB_FILE='false'
-B_MDSTAT_FILE='false'
-B_MEMINFO_FILE='false'
-B_MODULES_FILE='false' #
-B_MOUNTS_FILE='false'
-B_OS_RELEASE_FILE='false' # new default distro id file? will this one work where lsb-release didn't?
-B_PARTITIONS_FILE='false' #
-B_PROC_DIR='false'
-B_SCSI_FILE='false'
-
-## app tested for and present, to avoid repeat tests
-B_FILE_TESTED='false'
-B_HDDTEMP_TESTED='false'
-B_MODINFO_TESTED='false'
-B_SUDO_TESTED='false'
-
-# cpu 64 bit able or not. Does not tell you actual kernel/OS installed
-# if ((1<<32)); then
-# BITS=64
-# else
-# BITS=32
-# fi
-# echo $BITS
-
-### CONSTANTS/INITIALIZE - SOME MAY BE RESET LATER ###
-BASH=${BASH_VERSION%%[^0-9]*} # some bash 4 things can be used but only if tested
-DCOPOBJ="default"
-DEBUG=0 # Set debug levels from 1-10 (8-10 trigger logging levels)
-# Debug Buffer Index, index into a debug buffer storing debug messages until inxi is 'all up'
-DEBUG_BUFFER_INDEX=0
-DISPLAY_OPT='' # for console switches
-## note: the debugger rerouting to /dev/null has been moved to the end of the get_parameters function
-## so -@[number] debug levels can be set if there is a failure, otherwise you can't even see the errors
-SED_I='-i' # for gnu sed, will be set to -i '' for bsd sed
-SED_RX='-r' # for gnu sed, will be set to -E for bsd sed for backward compatibility
-
-# default to false, no konversation found, 1 is native konvi (qt3/KDE3) script mode, 2 is /cmd inxi start,
-## 3 is Konversation > 1.2 (qt4/KDE4)
-KONVI=0
-NO_SSL=''
-NO_SSL_OPT=''
-# NO_CPU_COUNT=0 # Whether or not the string "dual" or similar is found in cpuinfo output. If so, avoid dups.
-# This is a variable that controls how many parameters inxi will parse in a /proc/<pid>/cmdline file before stopping.
-PARAMETER_LIMIT=30
-SCHEME=0 # set default scheme - do not change this, it's set dynamically
-# this is set in user prefs file, to override dynamic temp1/temp2 determination of sensors output in case
-# cpu runs colder than mobo
-SENSORS_CPU_NO=''
-# SHOW_IRC=1 to avoid showing the irc client version number, or SHOW_IRC=0 to disable client information completely.
-SHOW_IRC=2
-# Verbosity level defaults to 0, this can also be set with -v0, -v2, -v3, etc as a parameter.
-VERBOSITY_LEVEL=0
-# Supported number of verbosity levels, including 0
-VERBOSITY_LEVELS=7
-
-### LOGGING ###
-## logging eval variables, start and end function: Insert to LOGFS LOGFE when debug level >= 8
-LOGFS_STRING='log_function_data fs $FUNCNAME "$( echo $@ )"'
-LOGFE_STRING='log_function_data fe $FUNCNAME'
-LOGFS=''
-LOGFE=''
-# uncomment for debugging from script start
-# LOGFS=$LOGFS_STRING
-# LOGFE=$LOGFE_STRING
-
-### FILE NAMES/PATHS/URLS - must be non root writable ###
-# File's used when present
-FILE_ASOUND_DEVICE='/proc/asound/cards'
-FILE_ASOUND_MODULES='/proc/asound/modules' # not used but maybe for -A?
-FILE_ASOUND_VERSION='/proc/asound/version'
-FILE_CPUINFO='/proc/cpuinfo'
-FILE_DMESG_BOOT='/var/run/dmesg.boot'
-FILE_LSB_RELEASE='/etc/lsb-release'
-FILE_MDSTAT='/proc/mdstat'
-FILE_MEMINFO='/proc/meminfo'
-FILE_MODULES='/proc/modules'
-FILE_MOUNTS='/proc/mounts'
-FILE_OS_RELEASE='/etc/os-release'
-FILE_PARTITIONS='/proc/partitions'
-FILE_SCSI='/proc/scsi/scsi'
-FILE_XORG_LOG='/var/log/Xorg.0.log' # if not found, search and replace with actual location
-
-FILE_PATH=''
-HDDTEMP_PATH=''
-MODINFO_PATH=''
-SUDO_PATH=''
-
-ALTERNATE_FTP='' # for data uploads
-ALTERNATE_WEATHER_LOCATION='' # weather alternate location
-SELF_CONFIG_DIR=''
-SELF_DATA_DIR=''
-LOG_FILE='inxi.log'
-LOG_FILE_1='inxi.1.log'
-LOG_FILE_2='inxi.2.log'
-MAN_FILE_DOWNLOAD='https://github.com/smxi/inxi/raw/master/inxi.1.gz'
-SELF_PATH='' # filled-in in Main
-SELF_DOWNLOAD='https://github.com/smxi/inxi/raw/master/'
-SELF_DOWNLOAD_BRANCH_1='https://github.com/smxi/inxi/raw/one/'
-SELF_DOWNLOAD_BRANCH_2='https://github.com/smxi/inxi/raw/two/'
-SELF_DOWNLOAD_BRANCH_3='https://github.com/smxi/inxi/raw/three/'
-SELF_DOWNLOAD_DEV='https://smxi.org/test/'
-# note, you can use any ip url here as long as it's the only line on the output page.
-# Also the ip address must be the last thing on that line. If you abuse this ip tool
-# you will be banned from further access. Most > 24x daily automated queries to it are abuse.
-WAN_IP_URL='https://smxi.org/opt/ip.php'
-KONVI_CFG="konversation/scripts/$SELF_NAME.conf" # relative path to $(kde-config --path data)
-
-### INITIALIZE VARIABLES NULL ###
-ARCH='' # cpu microarchitecture
-BSD_TYPE=''
-BSD_VERSION=
-CMDL_MAX=''
-CPU_COUNT_ALPHA=''
-CURRENT_KERNEL=''
-DEV_DISK_ID=''
-DEV_DISK_LABEL=''
-DEV_DISK_MAPPER=''
-DEV_DISK_UUID=''
-DMIDECODE_DATA=''
-DMESG_BOOT_DATA=''
-DNSTOOL=''
-DOWNLOADER='wget'
-IRC_CLIENT=''
-IRC_CLIENT_VERSION=''
-LINE_LENGTH=0
-LSPCI_V_DATA=''
-LSPCI_N_DATA=''
-MEMORY=''
-PS_THROTTLED=''
-RAID_TYPE=''
-REPO_DATA=''
-SYSCTL_A_DATA=''
-UP_TIME=''
-
-### LAYOUT ###
-# These two determine separators in single line output, to force irc clients not to break off sections
-SEP1='~'
-SEP2=' '
-# these will assign a separator to non irc states. Important! Using ':' can trigger stupid emoticon
+#!/usr/bin/env perl
+## infobash: Copyright (C) 2005-2007 Michiel de Boer aka locsmif
+## inxi: Copyright (C) 2008-2018 Harald Hope
+## Additional features (C) Scott Rogers - kde, cpu info
+## Further fixes (listed as known): Horst Tritremmel <hjt at sidux.com>
+## Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch
+## Jarett.Stevens - dmidecode -M patch for older systems with the /sys
+##
+## License: GNU GPL v3 or greater
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+## If you don't understand what Free Software is, please read (or reread)
+## this page: http://www.gnu.org/philosophy/free-sw.html
+
+use strict;
+use warnings;
+# use diagnostics;
+use 5.008;
+
+use Cwd qw(abs_path); # qw(abs_path);#abs_path realpath getcwd
+use Data::Dumper qw(Dumper); # print_r
+use File::Find;
+use Getopt::Long qw(GetOptions);
+# Note: default auto_abbrev is enabled, that's fine
+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);
+
+## INXI INFO ##
+my $self_name='inxi';
+my $self_version='3.0.07';
+my $self_date='2018-04-17';
+my $self_patch='00';
+## END INXI INFO ##
+
+### INITIALIZE VARIABLES ###
+
+## Self data
+my ($self_path, $user_config_dir, $user_config_file,$user_data_dir);
+
+## 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);
+# NOTE: redhat removed HiRes from Perl Core Modules. Why? who knows.
+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, %client, %colors, %dl, %files, %rows, %system_files, %use );
+
+## Arrays
+# ps_aux is full output, ps_cmd is only the last 10 to last
+my (@app,@dmesg_boot,@dmi,@gpudata,@ifs,@ifs_bsd,@paths,@pci,@ps_aux,@ps_cmd,
+@sysctl,@sysctl_battery,@sysctl_sensors,@sysctl_machine,@uname,@usb);
+## Disk arrays
+my (@dm_boot_disk,@dm_boot_optical,@glabel,@gpart,@labels,@lsblk,@partitions,
+@raid,@sysctl_disks,@uuids);
+my @test = (0,0,0,0,0);
+
+## Booleans
+my ($b_arm,$b_console_irc,$b_debug_gz,$b_display,$b_dmesg_boot_check,$b_dmi,
+$b_dmidecode_force,$b_force_display,$b_gpudata,$b_irc,$b_log,$b_log_colors,
+$b_log_full,$b_man,$b_mem,$b_pci,$b_root,$b_running_in_display,$b_sysctl,$b_usb_check);
+## Disk checks
+my ($b_dm_boot_disk,$b_dm_boot_optical,$b_glabel,$b_lsblk,$b_partitions,
+$b_partition_extra,$b_raid);
+my ($b_sysctl_disk,$b_update,$b_weather) = (1,1,1);
+
+## System
+my ($bsd_type,$language,$os) = ('','','');
+my ($cpu_sleep,$dl_timeout,$limit,$ps_count,$usb_level) = (0.35,4,10,5,0);
+my $sensors_cpu_nu = 0;
+my ($bits_sys);
+
+## Tools
+my ($display,$ftp_alt,$tty_session);
+my $display_opt = '';
+
+## Output
+my $extra = 0;# supported values: 0-3
+my $filter_string = '<filter>';
+my $line1 = "----------------------------------------------------------------------\n";
+my $line2 = "======================================================================\n";
+my $line3 = "----------------------------------------\n";
+my ($output_file,$output_type) = ('','screen');
+my $prefix = 0; # for the primiary row hash key prefix
+
+# these will assign a separator to non irc states. Important! Using ':' can
+# trigger stupid emoticon. Note: SEP1/SEP2 from short form not used anymore.
# behaviors in output on IRC, so do not use those.
-SEP3_IRC=''
-SEP3_CONSOLE=':'
-SEP3='' # do not set, will be set dynamically
-LINE1='---------------------------------------------------------------------------'
-LINE2='- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
-
-# Default indentation level. NOTE: actual indent is 1 greater to allow for spacing
-INDENT=10
-
-### COLUMN WIDTHS ###
-COLS_INNER='' ## for width minus INDENT
-COLS_MAX=''
-
-# these will be set dynamically in main()
-TERM_COLUMNS=80
-TERM_LINES=100
-
-# Only for legacy user config files se we can test and convert the var name
-LINE_MAX_CONSOLE=''
-LINE_MAX_IRC=''
-
-### COLORS ###
-# Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Use following variables in config
-# files to change defaults for each type, or global
-# Same as runtime parameter.
-DEFAULT_COLOR_SCHEME=2
-## color variables - set dynamically
-COLOR_SCHEME=''
-C1=''
-C2=''
-CN=''
-## Always leave these blank, these are only going to be set in inxi.conf files, that makes testing
-## for user changes easier after sourcing the files
-ESC='\x1b'
-GLOBAL_COLOR_SCHEME=''
-IRC_COLOR_SCHEME=''
-IRC_CONS_COLOR_SCHEME=''
-IRC_X_TERM_COLOR_SCHEME=''
-CONSOLE_COLOR_SCHEME=''
-VIRT_TERM_COLOR_SCHEME=''
-
-## Output colors
-# A more elegant way to have a scheme that doesn't print color codes (neither ANSI nor mIRC) at all. See below.
-unset EMPTY
-# DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW
-ANSI_COLORS="       "
-IRC_COLORS=" \x0314 \x0301 \x0304 \x0305 \x0309 \x0303 \x0308 \x0307"
-# BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL
-ANSI_COLORS="$ANSI_COLORS         "
-IRC_COLORS=" $IRC_COLORS \x0312 \x0302 \x0313 \x0306 \x0311 \x0310 \x0300 \x0315 \x03"
-
-#ANSI_COLORS=($ANSI_COLORS); IRC_COLORS=($IRC_COLORS)
-A_COLORS_AVAILABLE=( DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL )
-
-# See above for notes on EMPTY
-## note: group 1: 0, 1 are null/normal
-## Following: group 2: generic, light/dark or dark/light; group 3: dark on light; group 4 light on dark;
-# this is the count of the first two groups, starting at zero
-SAFE_COLOR_COUNT=12
-A_COLOR_SCHEMES=(
-EMPTY,EMPTY,EMPTY
-NORMAL,NORMAL,NORMAL
-
-BLUE,NORMAL,NORMAL
-BLUE,RED,NORMAL
-CYAN,BLUE,NORMAL
-DCYAN,NORMAL,NORMAL
-DCYAN,BLUE,NORMAL
-DGREEN,NORMAL,NORMAL
-DYELLOW,NORMAL,NORMAL
-GREEN,DGREEN,NORMAL
-GREEN,NORMAL,NORMAL
-MAGENTA,NORMAL,NORMAL
-RED,NORMAL,NORMAL
-
-BLACK,DGREY,NORMAL
-DBLUE,DGREY,NORMAL
-DBLUE,DMAGENTA,NORMAL
-DBLUE,DRED,NORMAL
-DBLUE,BLACK,NORMAL
-DGREEN,DYELLOW,NORMAL
-DYELLOW,BLACK,NORMAL
-DMAGENTA,BLACK,NORMAL
-DCYAN,DBLUE,NORMAL
-
-WHITE,GREY,NORMAL
-GREY,WHITE,NORMAL
-CYAN,GREY,NORMAL
-GREEN,WHITE,NORMAL
-GREEN,YELLOW,NORMAL
-YELLOW,WHITE,NORMAL
-MAGENTA,CYAN,NORMAL
-MAGENTA,YELLOW,NORMAL
-RED,CYAN,NORMAL
-RED,WHITE,NORMAL
-BLUE,WHITE,NORMAL
-
-RED,BLUE,NORMAL
-RED,DBLUE,NORMAL
-BLACK,BLUE,NORMAL
-BLACK,DBLUE,NORMAL
-NORMAL,BLUE,NORMAL
-BLUE,MAGENTA,NORMAL
-DBLUE,MAGENTA,NORMAL
-BLACK,MAGENTA,NORMAL
-MAGENTA,BLUE,NORMAL
-MAGENTA,DBLUE,NORMAL
-)
-
-#echo ${#A_COLOR_SCHEMES[@]};exit
-
-# WARNING: In the main part below (search for 'KONVI')
-# there's a check for Konversation-specific config files.
-# Any one of these can override the above if inxi is run
-# from Konversation!
-
-## DISTRO DATA/ID ##
-# In cases of derived distros where the version file of the base distro can also be found under /etc,
-# the derived distro's version file should go first. (Such as with Sabayon / Gentoo)
-DISTROS_DERIVED="antix-version aptosid-version kanotix-version knoppix-version mandrake-release mx-version pardus-release porteus-version sabayon-release siduction-version sidux-version slitaz-release solusos-release turbolinux-release zenwalk-version"
-# debian_version excluded from DISTROS_PRIMARY so Debian can fall through to /etc/issue detection. Same goes for Ubuntu.
-DISTROS_EXCLUDE_LIST="debian_version devuan_version ubuntu_version"
-DISTROS_PRIMARY="arch-release gentoo-release redhat-release slackware-version SuSE-release"
-DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-release manjaro-release"
-# this is being used both by core distros and derived distros now, eg, solusos 1 uses it for solusos id, while
-# debian, solusos base, uses it as well, so we have to know which it is.
-DISTROS_OS_RELEASE_GOOD="arch-release SuSE-release "
-## Distros with known problems
-# DSL (Bash 2.05b: grep -m doesn't work; arrays won't work) --> unusable output
-# Puppy Linux 4.1.2 (Bash 3.0: arrays won't work) --> works partially
-
-## OUTPUT FILTERS/SEARCH ##
-# Note that \<ltd\> bans only words, not parts of strings; in \<corp\> you can't use punctuation characters like . or ,
-# we're saving about 10+% of the total script exec time by hand building the ban lists here, using hard quotes.
-
-BAN_LIST_NORMAL='chipset|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|incorporation|industrial|international|nee|revision|semiconductor|software|technologies|technology|ltd\.|\<ltd\>|inc\.|\<inc\>|intl\.|co\.|\<co\>|corp\.|\<corp\>|\(tm\)|\(r\)|®|\(rev ..\)'
-BAN_LIST_CPU='@|cpu |cpu deca|([0-9]+|single|dual|triple|tri|quad|penta|hepta|hexa|octa|multi)[ -]core|ennea|genuine|multi|processor|single|triple|[0-9\.]+ *[MmGg][Hh][Zz]'
-# See github issue 75 for more details on value: *, triggers weird behaviors if present in value
-# /sys/devices/virtual/dmi/id/product_name:['*']
-# this is for bash arrays AND avoiding * in arrays: ( fred * greg ) expands to the contents of the directory
-BAN_LIST_ARRAY=',|\*'
-
-SENSORS_GPU_SEARCH='amdgpu|intel|radeon|nouveau'
-
-### USB networking search string data, because some brands can have other products than
-### wifi/nic cards, they need further identifiers, with wildcards.
-### putting the most common and likely first, then the less common, then some specifics
-USB_NETWORK_SEARCH="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"
-USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|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|54 Mbps"
-# then a few known hard to ID ones added
-# belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda;
-USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|050d:935b|0bda:8189|0bda:8197"
+my %sep = (
+'s1-irc' => ':',
+'s1-console' => ':',
+'s2-irc' => '',
+'s2-console' => ':',
+);
+
+my %show = ('host' => 1);
+
+my %size = (
+'console' => 115,
+# Default indentation level. NOTE: actual indent is 1 greater to allow for
+# spacing
+'indent' => 11,
+'indent-min' => 90,
+'irc' => 100, # shorter because IRC clients have nick lists etc
+'max' => 0,
+'no-display' => 130,
+# these will be set dynamically in set_display_width()
+'term' => 80,
+'term-lines' => 100,
+);
+
+## debug temp tools
+$client{'test-konvi'} = 0;
########################################################################
#### STARTUP
@@ -701,15637 +128,16338 @@ USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|050d:935b|0bda:8189|0bda:8197"
#### MAIN
#### -------------------------------------------------------------------
-main()
-{
- # This must be set first so log paths are present when logging starts.
- set_user_paths
-
- eval $LOGFS
-
- local color_scheme='' kde_config_app=''
- # this will be used by all functions following, lower case for bash parameter expansion
- local Ps_aux_Data="$( ps aux | tr '[:upper:]' '[:lower:]' )"
-
- # This function just initializes variables
- initialize_data
-
- # Source global config overrides, needs to be here because some things
- # can be reset that were set in initialize, but check_required_apps needs
- if [[ -s /etc/$SELF_NAME.conf ]];then
- source /etc/$SELF_NAME.conf
- fi
- # Source user config variables override /etc/inxi.conf variables
- if [[ -s $SELF_CONFIG_DIR/$SELF_NAME.conf ]];then
- source $SELF_CONFIG_DIR/$SELF_NAME.conf
- fi
-
- set_display_width 'live' # can be reset with -y
-
- # echo SCHEME $SCHEME
- # echo B_IRC $B_IRC
- # echo sep3: $SEP3
- # Check for dependencies BEFORE running ANYTHING else except above functions
- # Not all distro's have these depends installed by default. Don't want to run
- # this if the user is requesting to see this information in the first place
- # Only continue if required apps tests ok
- if [[ $1 != '--recommends' ]];then
- check_required_apps
- check_recommended_apps
- fi
- # previous source location, check for bugs
-
- ## this needs to run before the KONVI stuff is set below
- ## Konversation 1.2 apparently does not like the $PPID test in get_start_client
- ## So far there is no known way to detect if qt4_konvi is the parent process
- ## this method will infer qt4_konvi as parent
- get_start_client
-
- # note: this only works if it's run from inside konversation as a script builtin or something
- # only do this if inxi has been started as a konversation script, otherwise bypass this
- # KONVI=3 ## for testing puroses
- if [[ $KONVI -eq 1 || $KONVI -eq 3 ]];then
- if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (ie 1.x < 1.2(qt3))
- DCPORT="$1"
- DCSERVER="$2"
- DCTARGET="$3"
- shift 3
- elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4))
- DCSERVER="$1" ##dbus testing
- DCTARGET="$2" ##dbus testing
- shift 2
- fi
- # always have the current stable kde version tested first,
- # then use fallbacks and future proofing
- if type -p kde4-config &>/dev/null;then
- kde_config_app='kde4-config'
- elif type -p kde5-config &>/dev/null;then
- kde_config_app='kde5-config'
- elif type -p kde-config &>/dev/null;then
- kde_config_app='kde-config'
- fi
- # The section below is on request of Argonel from the Konversation developer team:
- # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf
- if [[ -n $kde_config_app ]];then
- IFS=":"
- for kde_config in $( $kde_config_app --path data )
- do
- if [[ -r $kde_config$KONVI_CFG ]];then
- source "$kde_config$KONVI_CFG"
- break
- fi
- done
- IFS="$ORIGINAL_IFS"
- fi
- fi
-
- ## leave this for debugging dcop stuff if we get that working
- # print_screen_output "DCPORT: $DCPORT"
- # print_screen_output "DCSERVER: $DCSERVER"
- # print_screen_output "DCTARGET: $DCTARGET"
-
- # first init function must be set first for colors etc. Remember, no debugger
- # stuff works on this function unless you set the debugging flag manually.
- # Debugging flag -@ [number] will not work until get_parameters runs.
-
- # "$@" passes every parameter separately quoted, "$*" passes all parameters as one quoted parameter.
- # must be here to allow debugger and other flags to be set.
- get_parameters "$@"
-
- # If no colorscheme was set in the parameter handling routine, then set the default scheme
- if [[ $B_COLOR_SCHEME_SET != 'true' ]];then
- # This let's user pick their color scheme. For IRC, only shows the color schemes, no interactive
- # The override value only will be placed in user config files. /etc/inxi.conf can also override
- if [[ $B_RUN_COLOR_SELECTOR == 'true' ]];then
- select_default_color_scheme
- else
- # set the default, then override as required
- color_scheme=$DEFAULT_COLOR_SCHEME
- if [[ -n $GLOBAL_COLOR_SCHEME ]];then
- color_scheme=$GLOBAL_COLOR_SCHEME
- else
- if [[ $B_IRC == 'false' ]];then
- if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
- color_scheme=$CONSOLE_COLOR_SCHEME
- elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
- color_scheme=$VIRT_TERM_COLOR_SCHEME
- fi
- else
- if [[ -n $IRC_X_TERM_COLOR_SCHEME && $B_CONSOLE_IRC == 'true' && -n $B_RUNNING_IN_DISPLAY ]];then
- color_scheme=$IRC_X_TERM_COLOR_SCHEME
- elif [[ -n $IRC_CONS_COLOR_SCHEME && -z $DISPLAY ]];then
- color_scheme=$IRC_CONS_COLOR_SCHEME
- elif [[ -n $IRC_COLOR_SCHEME ]];then
- color_scheme=$IRC_COLOR_SCHEME
- fi
- fi
- fi
- set_color_scheme $color_scheme
- fi
- fi
- if [[ $B_IRC == 'false' ]];then
- SEP3=$SEP3_CONSOLE
- else
- # too hard to read if no colors, so force that for users on irc
- if [[ $SCHEME == 0 ]];then
- SEP3=$SEP3_CONSOLE
- else
- SEP3=$SEP3_IRC
- fi
- fi
-
- # all the pre-start stuff is in place now
- B_SCRIPT_UP='true'
- self_debugger "Debugger: $SELF_NAME is up and running..."
-
- # then create the output
- print_it_out
-
- eval $LOGFE
- # weechat's executor plugin forced me to do this, and rightfully so, because else the exit code
- # from the last command is taken..
- exit 0
+sub main {
+# print Dumper \@ARGV;
+ eval $start if $b_log;
+ initialize();
+ ## use for start client debugging
+ # $debug = 10;
+ # set_debugger(); # for debugging of konvi issues
+ #my $ob_start = StartClient->new();
+ #$ob_start->get_client_data();
+ StartClient::get_client_data();
+ # print_line( Dumper \%client);
+ get_options();
+ set_debugger(); # right after so it's set
+ check_tools();
+ set_colors();
+ set_sep();
+ # print download_file('stdout','https://') . "\n";
+ generate_lines();
+ eval $end if $b_log;
+ cleanup();
+ # weechat's executor plugin forced me to do this, and rightfully so,
+ # because else the exit code from the last command is taken..
+ exit 0;
}
#### -------------------------------------------------------------------
#### INITIALIZE
#### -------------------------------------------------------------------
-# No args taken.
-check_recommended_apps()
-{
- eval $LOGFS
- local bash_array_test=( "one" "two" )
-
- # check for array ability of bash, this is only good for the warning at this time
- # the boolean could be used later
- # bash version 2.05b is used in DSL
- # bash version 3.0 is used in Puppy Linux; it has a known array bug <reference to be placed here>
- # versions older than 3.1 don't handle arrays
- # distro's using below 2.05b are unknown, released in 2002
- if [[ ${bash_array_test[1]} -eq "two" ]];then
- B_BASH_ARRAY='true'
- else
- self_debugger "Suggestion: update to Bash v3.1 for optimal inxi output"
- fi
- # test for a few apps that bsds may not have after initial tests
- if type -p lspci &>/dev/null;then
- B_LSPCI='true'
- fi
- if [[ -n $BSD_TYPE ]];then
- if type -p sysctl &>/dev/null;then
- B_SYSCTL='true'
- fi
- if type -p pciconf &>/dev/null;then
- B_PCICONF='true'
- fi
- fi
- # now setting qdbus/dcop for first run, some systems can have both by the way
- if type -p qdbus &>/dev/null;then
- B_QDBUS='true'
- fi
- if type -p dcop &>/dev/null;then
- B_DCOP='true'
- fi
- eval $LOGFE
-}
-
-# Determine if any of the absolutely necessary tools are absent
-# No args taken.
-check_required_apps()
-{
- eval $LOGFS
- local app_name=''
- # bc removed from deps for now
- local depends="df gawk grep ps readlink tr uname wc"
-
- if [[ -z $BSD_TYPE ]];then
- depends="$depends lspci"
- elif [[ $BSD_TYPE == 'bsd' ]];then
- depends="$depends sysctl"
- # debian-bsd has lspci but you must be root to run it
- elif [[ $BSD_TYPE == 'debian-bsd' ]];then
- depends="$depends sysctl lspci"
- fi
- # no need to add xprop because it will just give N/A if not there, but if we expand use of xprop,
- # should add that here as a test, then use the B_SHOW_DISPLAY_DATA flag to trigger the tests in de function
- local x_apps="xrandr xdpyinfo glxinfo"
-
- if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
- for app_name in $x_apps
- do
- if ! type -p $app_name &>/dev/null;then
- self_debugger "Resuming in non X mode: $app_name not found. For package install advice run: $SELF_NAME --recommends"
- B_SHOW_DISPLAY_DATA='false'
- break
- fi
- done
- fi
-
- app_name=''
-
- for app_name in $depends
- do
- if ! type -p $app_name &>/dev/null;then
- error_handler 5 "$app_name"
- fi
- done
- eval $LOGFE
-}
-
-# Set PATH data so we can access all programs as user. Set BAN lists.
-# initialize some boleans, these directories are used throughout the script
-# some apps are used for extended functions any directory used, should be
-# checked here first.
-# No args taken.
-initialize_data()
-{
- eval $LOGFS
- BSD_VERSION=$( uname -s 2>/dev/null | tr '[A-Z]' '[a-z]' )
- # note: archbsd says they are a freebsd distro, so assuming it's the same as freebsd
- if [[ -z ${BSD_VERSION/*bsd*/} || -z ${BSD_VERSION/*dragonfly*/} || -z ${BSD_VERSION/*darwin*/} ]];then
- if [[ -z ${BSD_VERSION/*openbsd*/} ]];then
- BSD_VERSION='openbsd'
- elif [[ -z ${BSD_VERSION/*darwin*/} ]];then
- BSD_VERSION='darwin'
- fi
- # GNU/kfreebsd will by definition have GNU tools like sed/grep
- if [[ -z ${BSD_VERSION/*kfreebsd*/} ]];then
- BSD_TYPE='debian-bsd' # debian gnu bsd
- else
- BSD_TYPE='bsd' # all other bsds
- SED_I="-i ''"
- SED_RX='-E'
- ESC=$(echo | tr '\n' '\033')
- fi
- fi
- # now set the script BOOLEANS for files required to run features
- # note that freebsd has /proc but it's empty
- if [[ -d "/proc/" && -z $BSD_TYPE ]];then
- B_PROC_DIR='true'
- elif [[ -n $BSD_TYPE ]];then
- B_PROC_DIR='false'
- else
- error_handler 6
- fi
- initialize_paths
- if type -p dig &>/dev/null;then
- DNSTOOL='dig'
- fi
- # set downloaders.
- set_downloader
- if [[ -n $BSD_TYPE ]];then
- if [[ -e $FILE_DMESG_BOOT ]];then
- B_DMESG_BOOT_FILE='true'
- fi
- else
- # found a case of battery existing but having nothing in it on desktop mobo
- # not all laptops show the first. /proc/acpi/battery is deprecated.
- if [[ -n $( ls /proc/acpi/battery 2>/dev/null ) || -n $( ls /sys/class/power_supply/ 2>/dev/null ) ]];then
- B_POSSIBLE_PORTABLE='true'
- fi
- fi
- if [[ -e $FILE_CPUINFO ]]; then
- B_CPUINFO_FILE='true'
- fi
- if [[ -e $FILE_MEMINFO ]];then
- B_MEMINFO_FILE='true'
- fi
- if [[ -e $FILE_ASOUND_DEVICE ]];then
- B_ASOUND_DEVICE_FILE='true'
- fi
- if [[ -e $FILE_ASOUND_VERSION ]];then
- B_ASOUND_VERSION_FILE='true'
- fi
- if [[ -f $FILE_LSB_RELEASE ]];then
- B_LSB_FILE='true'
- fi
- if [[ -f $FILE_OS_RELEASE ]];then
- B_OS_RELEASE_FILE='true'
- fi
- if [[ -e $FILE_SCSI ]];then
- B_SCSI_FILE='true'
- fi
- if [[ -n $DISPLAY ]];then
- B_SHOW_DISPLAY_DATA='true'
- B_RUNNING_IN_DISPLAY='true'
- fi
- if [[ -e $FILE_MDSTAT ]];then
- B_MDSTAT_FILE='true'
- fi
- if [[ -e $FILE_MODULES ]];then
- B_MODULES_FILE='true'
- fi
- if [[ -e $FILE_MOUNTS ]];then
- B_MOUNTS_FILE='true'
- fi
- if [[ -e $FILE_PARTITIONS ]];then
- B_PARTITIONS_FILE='true'
- fi
- # default to the normal location, then search for it
- if [[ -e $FILE_XORG_LOG ]];then
- B_XORG_LOG='true'
- else
- # Detect location of the Xorg log file
- if type -p xset &>/dev/null; then
- FILE_XORG_LOG=$( xset q 2>/dev/null | grep -i 'Log file' | gawk '{print $3}')
- if [[ -e $FILE_XORG_LOG ]];then
- B_XORG_LOG='true'
- fi
- fi
- fi
- # gfx output will require this flag
- if [[ $( whoami ) == 'root' ]];then
- B_ROOT='true'
- fi
- eval $LOGFE
-}
-
-initialize_paths()
-{
- local path='' added_path='' b_path_found='' sys_path=''
- # Extra path variable to make execute failures less likely, merged below
- local extra_paths="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/local/bin"
-
- # this needs to be set here because various options call the parent initialize function directly.
- SELF_PATH=$( dirname "$0" )
- # Fallback paths put into $extra_paths; This might, among others, help on gentoo.
- # Now, create a difference of $PATH and $extra_paths and add that to $PATH:
- IFS=":"
- for path in $extra_paths
- do
- b_path_found='false'
- for sys_path in $PATH
- do
- if [[ $path == $sys_path ]];then
- b_path_found='true'
- fi
- done
- if [[ $b_path_found == 'false' ]];then
- added_path="$added_path:$path"
- fi
- done
-
- IFS="$ORIGINAL_IFS"
- PATH="$PATH$added_path"
- # echo "PATH='$PATH'"
- ##/bin/sh -c 'echo "PATH in subshell=\"$PATH\""'
-}
-
-# arg: $1 - version number: main/patch/date
-parse_version_data()
-{
- # note, this is only now used for self updater function
- case $1 in
- date)
- SELF_DATE=$( gawk -F '=' '
- /^SELF_DATE/ {
- print $NF
- exit
- }' "$SELF_PATH/$SELF_NAME" )
- ;;
- main)
- SELF_VERSION=$( gawk -F '=' '
- /^SELF_VERSION/ {
- print $NF
- exit
- }' "$SELF_PATH/$SELF_NAME" )
- ;;
- patch)
- SELF_PATCH=$( gawk -F '=' '
- /^SELF_PATCH/ {
- print $NF
- exit
- }' "$SELF_PATH/$SELF_NAME" )
- ;;
- esac
-}
-
-# Set the colorscheme
-# args: $1 = <scheme number>|<"none">
-set_color_scheme()
-{
- eval $LOGFS
- local i='' a_output_colors='' a_color_codes=''
-
- if [[ $1 -ge ${#A_COLOR_SCHEMES[@]} ]];then
- set -- 1
- fi
- # Set a global variable to allow checking for chosen scheme later
- SCHEME="$1"
- if [[ $B_IRC == 'false' ]];then
- a_color_codes=( $ANSI_COLORS )
- else
- a_color_codes=( $IRC_COLORS )
- fi
- for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ ))
- do
- eval "${A_COLORS_AVAILABLE[i]}=\"${a_color_codes[i]}\""
- done
- IFS=","
- a_output_colors=( ${A_COLOR_SCHEMES[$1]} )
- IFS="$ORIGINAL_IFS"
- # then assign the colors globally
- C1="${!a_output_colors[0]}"
- C2="${!a_output_colors[1]}"
- CN="${!a_output_colors[2]}"
- # ((COLOR_SCHEME++)) ## note: why is this? ##
- # handle some explicit colors that are used for no color 0
- if [[ $SCHEME -eq 0 ]];then
- NORMAL=''
- RED=''
- fi
- eval $LOGFE
-}
-
-# args: $1 - default OR override default cols max integer count
-set_display_width()
-{
- local cols_max_override=$1
-
- if [[ $cols_max_override == 'live' ]];then
+sub initialize {
+ set_os();
+ set_path();
+ set_user_paths();
+ set_basics();
+ system_files('set');
+ get_configs();
+ # set_downloader();
+ set_display_width('live');
+}
+
+sub check_tools {
+ my ($action,$program,$message,@data,%commands,%hash);
+ if ( $b_dmi ){
+ $action = 'use';
+ if ($program = check_program('dmidecode')) {
+ my $result = system("$program -t chassis >/dev/null 2>&1");
+ if (!$result){
+ if ($b_root) {
+ @data = grabber("$program --type chassis");
+ if ( grep { $_ =~ /No SMBIOS/i } @data ){
+ $action = 'smbios';
+ }
+ }
+ }
+ elsif ($result){
+ $action = 'permissions';
+ }
+ }
+ else {
+ $action = 'missing';
+ }
+ %hash = (
+ 'dmidecode' => {
+ 'action' => $action,
+ 'missing' => 'Required program dmidecode not available',
+ 'permissions' => 'Unable to run dmidecode. Are you root?',
+ 'smbios' => 'No SMBIOS data for dmidecode to process',
+ },
+ );
+ %alerts = (%alerts, %hash);
+ }
+ # 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_pci || $b_sysctl){
+ if (!$bsd_type){
+ if ($b_pci ){
+ %hash = ('lspci' => '-n',);
+ %commands = (%commands,%hash);
+ }
+ }
+ else {
+ if ($b_pci ){
+ %hash = ('pciconf' => '-l',);
+ %commands = (%commands,%hash);
+ }
+ if ($b_sysctl ){
+ # note: there is a case of kernel.osrelease but it's a linux distro
+ %hash = ('sysctl' => 'kern.osrelease',);
+ %commands = (%commands,%hash);
+ }
+ }
+ foreach ( keys %commands ){
+ $action = 'use';
+ if ($program = check_program($_)) {
+ # > 0 means error in shell
+ #my $cmd = "$program $commands{$_} >/dev/null";
+ #print "$cmd\n";
+ $action = 'permissions' if system("$program $commands{$_} >/dev/null 2>&1");
+ }
+ else {
+ $action = 'missing';
+ }
+ %hash = (
+ $_ => {
+ 'action' => $action,
+ 'missing' => "Missing system tool: $_. Output will be incomplete",
+ 'permissions' => "Unable to run $_. Root required?",
+ },
+ );
+ %alerts = (%alerts, %hash);
+ }
+ }
+ %commands = ();
+ if ( $show{'sensor'} ){
+ %commands = ('sensors' => 'linux',);
+ }
+ # note: lsusb ships in FreeBSD ports sysutils/usbutils
+ if ( $usb_level ){
+ %hash = ('lsusb' => 'all',);
+ %commands = (%commands,%hash);
+ %hash = ('usbdevs' => 'bsd',);
+ %commands = (%commands,%hash);
+ }
+ if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})){
+ %hash = (
+ 'ip' => 'linux',
+ 'ifconfig' => 'all',
+ );
+ %commands = (%commands,%hash);
+ }
+ foreach ( keys %commands ){
+ $action = 'use';
+ $message = 'Present and working';
+ if ( ($commands{$_} eq 'linux' && $os ne 'linux' ) || ($commands{$_} eq 'bsd' && $os eq 'linux' ) ){
+ $message = "No " . ucfirst($os) . " support. Is a comparable $_ tool available?";
+ $action = 'platform';
+ }
+ elsif (!check_program($_)){
+ $message = "Required tool $_ not installed. Check --recommends";
+ $action = 'missing';
+ }
+ %hash = (
+ $_ => {
+ 'action' => $action,
+ 'missing' => $message,
+ 'platform' => $message,
+ },
+ );
+ %alerts = (%alerts, %hash);
+ }
+ # print Dumper \%alerts;
+}
+sub set_basics {
+ ### LOCALIZATION - DO NOT CHANGE! ###
+ # set to default LANG to avoid locales errors with , or .
+ # Make sure every program speaks English.
+ $ENV{'LANG'}='C';
+ $ENV{'LC_ALL'}='C';
+ # remember, perl uses the opposite t/f return as shell!!!
+ $b_irc = ( system('tty >/dev/null') ) ? 1 : 0;
+ # print "birc: $b_irc\n";
+ $b_display = ( $ENV{'DISPLAY'} ) ? 1 : 0;
+ $b_root = ( $ENV{'HOME'} eq '/root' ) ? 1 : 0;
+ $dl{'dl'} = 'curl';
+ $dl{'curl'} = 1;
+ $dl{'tiny'} = 1; # note: two modules needed, tested for in set_downloader
+ $dl{'wget'} = 1;
+ $dl{'fetch'} = 1;
+ $client{'console-irc'} = 0;
+ $client{'dcop'} = (check_program('dcop')) ? 1 : 0;
+ $client{'qdbus'} = (check_program('qdbus')) ? 1 : 0;
+ $client{'konvi'} = 0;
+ $client{'name'} = '';
+ $client{'name-print'} = '';
+ $client{'su-start'} = ''; # shows sudo/su
+ $client{'version'} = '';
+ $colors{'default'} = 2;
+}
+
+# args: $1 - default OR override default cols max integer count. $_[0]
+# is the display width override.
+sub set_display_width {
+ my ($width) = @_;
+ if ( $width eq 'live' ){
## sometimes tput will trigger an error (mageia) if irc client
- if [[ $B_IRC == 'false' ]];then
- if type -p tput &>/dev/null;then
- TERM_COLUMNS=$(tput cols)
- TERM_LINES=$(tput lines)
- fi
+ if ( ! $b_irc ){
+ if ( check_program('tput') ) {
+ # trips error if use qx()...
+ chomp($size{'term'}=qx{tput cols});
+ chomp($size{'term-lines'}=qx{tput lines});
+ $size{'term-cols'} = $size{'term'};
+ }
+ # print "tc: $size{'term'} cmc: $size{'console'}\n";
# double check, just in case it's missing functionality or whatever
- if [[ -z $TERM_COLUMNS || -n ${TERM_COLUMNS//[0-9]/} ]];then
- TERM_COLUMNS=80
- TERM_LINES=100
- fi
- fi
- # Convert to new variable names if set in config files, legacy test
- if [[ -n $LINE_MAX_CONSOLE ]];then
- COLS_MAX_CONSOLE=$LINE_MAX_CONSOLE
- fi
- if [[ -n $LINE_MAX_IRC ]];then
- COLS_MAX_IRC=$LINE_MAX_IRC
- fi
- # this lets you set different widths for in or out of display server
- # if [[ $B_RUNNING_IN_DISPLAY == 'false' && -n $COLS_MAX_NO_DISPLAY ]];then
- # COLS_MAX_CONSOLE=$COLS_MAX_NO_DISPLAY
- # fi
- # TERM_COLUMNS is set in top globals, using tput cols
- # echo tc: $TERM_COLUMNS cmc: $COLS_MAX_CONSOLE
- if [[ $TERM_COLUMNS -lt $COLS_MAX_CONSOLE ]];then
- COLS_MAX_CONSOLE=$TERM_COLUMNS
- fi
+ if ( $size{'term'} == 0 || $size{'term'} !~ /\d/ ){
+ $size{'term'}=80;
+ # we'll be using this for terminal dimensions later so don't set default.
+ # $size{'term-lines'}=100;
+ }
+ }
+ # this lets you set different size for in or out of display server
+ # if ( ! $b_running_in_display && $configs{'COLS_MAX_NO_DISPLAY'} != 0 ){
+ # $size{'console'}=$configs{'COLS_MAX_NO_DISPLAY'};
+ # }
+ # term_cols is set in top globals, using tput cols
+ # print "tc: $size{'term'} cmc: $size{'console'}\n";
+ if ( $size{'term'} < $size{'console'} ){
+ $size{'console'}=$size{'term'};
+ }
# adjust, some terminals will wrap if output cols == term cols
- COLS_MAX_CONSOLE=$(( $COLS_MAX_CONSOLE - 2 ))
- # echo cmc: $COLS_MAX_CONSOLE
+ $size{'console'}=( $size{'console'} - 2 );
+ # echo cmc: $size{'console'}
# comes after source for user set stuff
- if [[ $B_IRC == 'false' ]];then
- COLS_MAX=$COLS_MAX_CONSOLE
- else
- COLS_MAX=$COLS_MAX_IRC
- fi
- else
- COLS_MAX=$cols_max_override
- fi
- COLS_INNER=$(( $COLS_MAX - $INDENT - 1 ))
- # echo cm: $COLS_MAX ci: $COLS_INNER
-}
-
-set_downloader()
-{
- # curl/wget are faster than HTTP::Tiny
- if $B_CURL == 'true' && type -p curl &>/dev/null;then
- DOWNLOADER='curl'
- NO_SSL=' --insecure'
- # wget has had some issues with not testing their code leading to -O failure
- elif $B_WGET == 'true' && type -p wget &>/dev/null;then
- DOWNLOADER='wget'
- NO_SSL=' --no-check-certificate'
- # check for bsd stuff
- elif $B_FETCH == 'true' && type -p fetch &>/dev/null;then
- DOWNLOADER='fetch'
- NO_SSL=' --no-verify-peer'
- # this is much slower than curl or wget
- elif type -p perl &>/dev/null && perl -MHTTP::Tiny -e 1 &>/dev/null;then
- DOWNLOADER='perl' # does not use ssl by default
- elif [[ $BSD_VERSION == 'openbsd' ]] && type -p ftp &>/dev/null;then
- DOWNLOADER='ftp'
- else
- DOWNLOADER='no-downloader'
- fi
- # echo $DOWNLOADER
-}
-
-set_user_paths()
-{
- local b_conf='false' b_data='false'
+ if ( ! $b_irc ){
+ $size{'max'}=$size{'console'};
+ }
+ else {
+ $size{'max'}=$size{'irc'};
+ }
+ }
+ else {
+ $size{'max'}=$width;
+ }
+ # print "tc: $size{'term'} cmc: $size{'console'} cm: $size{'max'}\n";
+}
+# NOTE: most tests internally are against !$bsd_type
+sub set_os {
+ @uname = uname();
+ $os = lc($uname[0]);
+ my $type = lc($uname[-1]);
+ $b_arm = 1 if $type =~ /arm|aarch/;
+ if ($type =~ /(armv[1-7]|aarch32|sparc_v9)/){
+ $bits_sys = 32;
+ }
+ elsif ($type =~ /(alpha|64)/){
+ $bits_sys = 64;
+ }
+ if ( $os =~ /(bsd|dragonfly|darwin)/ ){
+ if ( $os =~ /openbsd/ ){
+ $os = 'openbsd';
+ }
+ elsif ($os =~ /darwin/){
+ $os = 'darwin';
+ }
+ if ($os =~ /kfreebsd/){
+ $bsd_type = 'debian-bsd';
+ }
+ else {
+ $bsd_type = $os;
+ }
+ }
+}
+# This data is hard set top of program but due to a specific project's
+# foolish idea that ignoring the FSH totally is somehow a positive step
+# forwards for free software, we also have to padd the results with PATH.
+sub set_path {
+ # Extra path variable to make execute failures less likely, merged below
+ my (@path);
+ @paths = qw(/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin /usr/X11R6/bin);
+ @path = split /:/, $ENV{'PATH'} if $ENV{'PATH'};
+ # print "paths: @paths\nPATH: $ENV{'PATH'}\n";
+ # Create a difference of $PATH and $extra_paths and add that to $PATH:
+ foreach my $id (@path) {
+ if ( !(grep { /^$id$/ } @paths) && $id !~ /(game)/ ){
+ push @paths, $id;
+ }
+ }
+ # print "paths: @paths\n";
+}
+
+sub set_sep {
+ if ( $b_irc ){
+ # too hard to read if no colors, so force that for users on irc
+ if ($colors{'scheme'} == 0 ){
+ $sep{'s1'} = $sep{'s1-console'};
+ $sep{'s2'} = $sep{'s2-console'};
+ }
+ else {
+ $sep{'s1'} = $sep{'s1-irc'};
+ $sep{'s2'} = $sep{'s2-irc'};
+ }
+ }
+ else {
+ $sep{'s1'} = $sep{'s1-console'};
+ $sep{'s2'} = $sep{'s2-console'};
+ }
+}
+
+sub set_user_paths {
+ my ( $b_conf, $b_data );
+ # this needs to be set here because various options call the parent
+ # initialize function directly.
+ $self_path = $0;
+ $self_path =~ s/[^\/]+$//;
- if [[ -n $XDG_CONFIG_HOME ]];then
- SELF_CONFIG_DIR=$XDG_CONFIG_HOME
- b_conf=true
- elif [[ -d $HOME/.config ]];then
- SELF_CONFIG_DIR=$HOME/.config
- b_conf=true
- else
- SELF_CONFIG_DIR="$HOME/.$SELF_NAME"
- fi
- if [[ -n $XDG_DATA_HOME ]];then
- SELF_DATA_DIR=$XDG_DATA_HOME/$SELF_NAME
- b_data=true
- elif [[ -d $HOME/.local/share ]];then
- SELF_DATA_DIR=$HOME/.local/share/$SELF_NAME
- b_data=true
- else
- SELF_DATA_DIR="$HOME/.$SELF_NAME"
- fi
+ if ( defined $ENV{'XDG_CONFIG_HOME'} && $ENV{'XDG_CONFIG_HOME'} ){
+ $user_config_dir=$ENV{'XDG_CONFIG_HOME'};
+ $b_conf=1;
+ }
+ elsif ( -d "$ENV{'HOME'}/.config" ){
+ $user_config_dir="$ENV{'HOME'}/.config";
+ $b_conf=1;
+ }
+ else {
+ $user_config_dir="$ENV{'HOME'}/.$self_name";
+ }
+ if ( defined $ENV{'XDG_DATA_HOME'} && $ENV{'XDG_DATA_HOME'} ){
+ $user_data_dir="$ENV{'XDG_DATA_HOME'}/$self_name";
+ $b_data=1;
+ }
+ elsif ( -d "$ENV{'HOME'}/.local/share" ){
+ $user_data_dir="$ENV{'HOME'}/.local/share/$self_name";
+ $b_data=1;
+ }
+ else {
+ $user_data_dir="$ENV{'HOME'}/.$self_name";
+ }
# note, this used to be created/checked in specific instance, but we'll just do it
# universally so it's done at script start.
- if [[ ! -d $SELF_DATA_DIR ]];then
- mkdir $SELF_DATA_DIR
- fi
-
- if [[ $b_conf == 'true' && -f $HOME/.$SELF_NAME/$SELF_NAME.conf ]];then
- mv -f $HOME/.$SELF_NAME/$SELF_NAME.conf $SELF_CONFIG_DIR
- echo "Moved $SELF_NAME.conf from $HOME/.$SELF_NAME to $SELF_CONFIG_DIR"
- fi
- if [[ $b_data == 'true' && -d $HOME/.$SELF_NAME ]];then
- mv -f $HOME/.$SELF_NAME/* $SELF_DATA_DIR
- rm -Rf $HOME/.$SELF_NAME
- echo "Moved data dir $HOME/.$SELF_NAME to $SELF_DATA_DIR"
- fi
-
- LOG_FILE=$SELF_DATA_DIR/$LOG_FILE
- LOG_FILE_1=$SELF_DATA_DIR/$LOG_FILE_1
- LOG_FILE_2=$SELF_DATA_DIR/$LOG_FILE_2
+ if ( ! -d $user_data_dir ){
+ mkdir $user_data_dir;
+ # system "echo", "Made: $user_data_dir";
+ }
+ if ( $b_conf && -f "$ENV{'HOME'}/.$self_name/$self_name.conf" ){
+ #system 'mv', "-f $ENV{'HOME'}/.$self_name/$self_name.conf", $user_config_dir;
+ # print "WOULD: Moved $self_name.conf from $ENV{'HOME'}/.$self_name to $user_config_dir\n";
+ }
+ if ( $b_data && -d "$ENV{'HOME'}/.$self_name" ){
+ #system 'mv', '-f', "$ENV{'HOME'}/.$self_name/*", $user_data_dir;
+ #system 'rm', '-Rf', "$ENV{'HOME'}/.$self_name";
+ # print "WOULD: Moved data dir $ENV{'HOME'}/.$self_name to $user_data_dir\n";
+ }
+ $log_file="$user_data_dir/$self_name.log";
+ #system 'echo', "$ENV{'HOME'}/.$self_name/* $user_data_dir";
+ # print "scd: $user_config_dir sdd: $user_data_dir \n";
+}
+# args: 1: set|hash key to return either null or path
+sub system_files {
+ my ($file) = @_;
+ if ( $file eq 'set'){
+ %files = (
+ 'asound-cards' => '/proc/asound/cards',
+ 'asound-modules' => '/proc/asound/modules',
+ 'asound-version' => '/proc/asound/version',
+ 'cpuinfo' => '/proc/cpuinfo',
+ 'dmesg-boot' => '/var/run/dmesg.boot',
+ 'lsb-release' => '/etc/lsb-release',
+ 'mdstat' => '/proc/mdstat',
+ 'meminfo' => '/proc/meminfo',
+ 'modules' => '/proc/modules',
+ 'mounts' => '/proc/mounts',
+ 'os-release' => '/etc/os-release',
+ 'partitions' => '/proc/partitions',
+ 'scsi' => '/proc/scsi/scsi',
+ 'version' => '/proc/version',
+ 'xorg-log' => '/var/log/Xorg.0.log'
+ );
+ foreach ( keys %files ){
+ $system_files{$_} = ( -e $files{$_} ) ? $files{$_} : '';
+ }
+ if ( ! $system_files{'xorg-log'} && check_program('xset') ){
+ my $data = qx(xset q 2>/dev/null);
+ foreach ( split /\n/, $data){
+ if ($_ =~ /Log file/i){
+ $system_files{'xorg-log'} = get_piece($_,3);
+ last;
+ }
+ }
+ }
+ }
+ else {
+ return $system_files{$file};
+ }
}
-
########################################################################
#### UTILITIES
########################################################################
#### -------------------------------------------------------------------
-#### COLOR SELECTOR
+#### COLORS
#### -------------------------------------------------------------------
-select_default_color_scheme()
+## arg: 1 - the type of action, either integer, count, or full
+sub get_color_scheme {
+ my ($type) = @_;
+ eval $start if $b_log;
+ my @color_schemes = (
+ [qw(EMPTY EMPTY EMPTY )],
+ [qw(NORMAL NORMAL NORMAL )],
+ # for dark OR light backgrounds
+ [qw(BLUE NORMAL NORMAL)],
+ [qw(BLUE RED NORMAL )],
+ [qw(CYAN BLUE NORMAL )],
+ [qw(DCYAN NORMAL NORMAL)],
+ [qw(DCYAN BLUE NORMAL )],
+ [qw(DGREEN NORMAL NORMAL )],
+ [qw(DYELLOW NORMAL NORMAL )],
+ [qw(GREEN DGREEN NORMAL )],
+ [qw(GREEN NORMAL NORMAL )],
+ [qw(MAGENTA NORMAL NORMAL)],
+ [qw(RED NORMAL NORMAL)],
+ # for light backgrounds
+ [qw(BLACK DGREY NORMAL)],
+ [qw(DBLUE DGREY NORMAL )],
+ [qw(DBLUE DMAGENTA NORMAL)],
+ [qw(DBLUE DRED NORMAL )],
+ [qw(DBLUE BLACK NORMAL)],
+ [qw(DGREEN DYELLOW NORMAL )],
+ [qw(DYELLOW BLACK NORMAL)],
+ [qw(DMAGENTA BLACK NORMAL)],
+ [qw(DCYAN DBLUE NORMAL)],
+ # for dark backgrounds
+ [qw(WHITE GREY NORMAL)],
+ [qw(GREY WHITE NORMAL)],
+ [qw(CYAN GREY NORMAL )],
+ [qw(GREEN WHITE NORMAL )],
+ [qw(GREEN YELLOW NORMAL )],
+ [qw(YELLOW WHITE NORMAL )],
+ [qw(MAGENTA CYAN NORMAL )],
+ [qw(MAGENTA YELLOW NORMAL)],
+ [qw(RED CYAN NORMAL)],
+ [qw(RED WHITE NORMAL )],
+ [qw(BLUE WHITE NORMAL)],
+ # miscellaneous
+ [qw(RED BLUE NORMAL )],
+ [qw(RED DBLUE NORMAL)],
+ [qw(BLACK BLUE NORMAL)],
+ [qw(BLACK DBLUE NORMAL)],
+ [qw(NORMAL BLUE NORMAL)],
+ [qw(BLUE MAGENTA NORMAL)],
+ [qw(DBLUE MAGENTA NORMAL)],
+ [qw(BLACK MAGENTA NORMAL)],
+ [qw(MAGENTA BLUE NORMAL)],
+ [qw(MAGENTA DBLUE NORMAL)],
+ );
+ if ($type eq 'count' ){
+ return scalar @color_schemes;
+ }
+ if ($type eq 'full' ){
+ return @color_schemes;
+ }
+ else {
+ return @{$color_schemes[$type]};
+ # print Dumper $color_schemes[$scheme_nu];
+ }
+ eval $end if $b_log;
+}
+
+sub set_color_scheme {
+ eval $start if $b_log;
+ my ($scheme) = @_;
+ $colors{'scheme'} = $scheme;
+ my $index = ( $b_irc ) ? 1 : 0; # defaults to non irc
+
+ # NOTE: qw(...) kills the escape, it is NOT the same as using
+ # Literal "..", ".." despite docs saying it is.
+ my %color_palette = (
+ 'EMPTY' => [ '', '' ],
+ 'DGREY' => [ "\e[1;30m", "\x0314" ],
+ 'BLACK' => [ "\e[0;30m", "\x0301" ],
+ 'RED' => [ "\e[1;31m", "\x0304" ],
+ 'DRED' => [ "\e[0;31m", "\x0305" ],
+ 'GREEN' => [ "\e[1;32m", "\x0309" ],
+ 'DGREEN' => [ "\e[0;32m", "\x0303" ],
+ 'YELLOW' => [ "\e[1;33m", "\x0308" ],
+ 'DYELLOW' => [ "\e[0;33m", "\x0307" ],
+ 'BLUE' => [ "\e[1;34m", "\x0312" ],
+ 'DBLUE' => [ "\e[0;34m", "\x0302" ],
+ 'MAGENTA' => [ "\e[1;35m", "\x0313" ],
+ 'DMAGENTA' => [ "\e[0;35m", "\x0306" ],
+ 'CYAN' => [ "\e[1;36m", "\x0311" ],
+ 'DCYAN' => [ "\e[0;36m", "\x0310" ],
+ 'WHITE' => [ "\e[1;37m", "\x0300" ],
+ 'GREY' => [ "\e[0;37m", "\x0315" ],
+ 'NORMAL' => [ "\e[0m", "\x03" ],
+ );
+ my @scheme = get_color_scheme($colors{'scheme'});
+ $colors{'c1'} = $color_palette{$scheme[0]}[$index];
+ $colors{'c2'} = $color_palette{$scheme[1]}[$index];
+ $colors{'cn'} = $color_palette{$scheme[2]}[$index];
+ # print Dumper \@scheme;
+ # print "$colors{'c1'}here$colors{'c2'} we are!$colors{'cn'}\n";
+ eval $end if $b_log;
+}
+
+sub set_colors {
+ eval $start if $b_log;
+ # it's already been set with -c 0-43
+ if ( exists $colors{'c1'} ){
+ return 1;
+ }
+ # This let's user pick their color scheme. For IRC, only shows the color schemes,
+ # no interactive. The override value only will be placed in user config files.
+ # /etc/inxi.conf can also override
+ if (exists $colors{'selector'}){
+ my $ob_selector = SelectColors->new($colors{'selector'});
+ $ob_selector->select_schema();
+ return 1;
+ }
+ # set the default, then override as required
+ my $color_scheme = $colors{'default'};
+ # these are set in user configs
+ if (defined $colors{'global'}){
+ $color_scheme = $colors{'global'};
+ }
+ else {
+ if ( $b_irc ){
+ if (defined $colors{'irc-virt-term'} && $b_display && $client{'console-irc'}){
+ $color_scheme = $colors{'irc-virt-term'};
+ }
+ elsif (defined $colors{'irc-console'} && !$b_display){
+ $color_scheme = $colors{'irc-console'};
+ }
+ elsif ( defined $colors{'irc-gui'}) {
+ $color_scheme = $colors{'irc-gui'};
+ }
+ }
+ else {
+ if (defined $colors{'console'} && !$b_display){
+ $color_scheme = $colors{'console'};
+ }
+ elsif (defined $colors{'virt-term'}){
+ $color_scheme = $colors{'virt-term'};
+ }
+ }
+ }
+ # force 0 for | or > output, all others prints to irc or screen
+ if (!$b_irc && ! -t STDOUT ){
+ $color_scheme = 0;
+ }
+ set_color_scheme($color_scheme);
+ eval $end if $b_log;
+}
+
+## SelectColors
{
- eval $LOGFS
- local spacer=' ' options='' user_selection='' config_variable=''
- local config_file="$SELF_CONFIG_DIR/$SELF_NAME.conf"
- local irc_clear=""
- local irc_gui='Unset' irc_console='Unset' irc_x_term='Unset'
- local console='Unset' virt_term='Unset' global='Unset'
-
- if [[ -n $IRC_COLOR_SCHEME ]];then
- irc_gui="Set: $IRC_COLOR_SCHEME"
- fi
- if [[ -n $IRC_CONS_COLOR_SCHEME ]];then
- irc_console="Set: $IRC_CONS_COLOR_SCHEME"
- fi
- if [[ -n $IRC_X_TERM_COLOR_SCHEME ]];then
- irc_x_term="Set: $IRC_X_TERM_COLOR_SCHEME"
- fi
- if [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
- virt_term="Set: $VIRT_TERM_COLOR_SCHEME"
- fi
- if [[ -n $CONSOLE_COLOR_SCHEME ]];then
- console="Set: $CONSOLE_COLOR_SCHEME"
- fi
- if [[ -n $GLOBAL_COLOR_SCHEME ]];then
- global="Set: $GLOBAL_COLOR_SCHEME"
- fi
-
- # don't want these printing in irc since they show literally
- if [[ $B_IRC == 'true' ]];then
- irc_clear=''
- fi
- # first make output neutral so it's just plain default for console client
- set_color_scheme "0"
- # print_lines_basic "0" "" ""
- if [[ $B_IRC == 'false' ]];then
- print_lines_basic "0" "" "Welcome to $SELF_NAME! Please select the default $COLOR_SELECTION color scheme."
- # print_screen_output "You will see this message only one time per user account, unless you set preferences in: /etc/$SELF_NAME.conf"
- print_screen_output " "
- fi
- print_lines_basic "0" "" "Because there is no way to know your $COLOR_SELECTION foreground/background colors, you can set your color preferences from color scheme option list below. 0 is no colors, 1 neutral. After these, there are 4 sets: 1-dark or light backgrounds; 2-light backgrounds; 3-dark backgrounds; 4-miscellaneous."
- if [[ $B_IRC == 'false' ]];then
- print_lines_basic "0" "" "Please note that this will set the $COLOR_SELECTION preferences only for user: $(whoami)"
- fi
- print_screen_output "$LINE1"
- for (( i=0; i < ${#A_COLOR_SCHEMES[@]}; i++ ))
- do
- if [[ $i -gt 9 ]];then
- spacer=' '
- fi
- # only offer the safe universal defaults
- case $COLOR_SELECTION in
- global|irc|irc-console|irc-virtual-terminal)
- if [[ $i -gt $SAFE_COLOR_COUNT ]];then
- break
- fi
- ;;
- esac
- set_color_scheme $i
- print_screen_output "$irc_clear $i)$spacer${C1}Card:${C2} nVidia G86 [GeForce 8400 GS] ${C1}Display Server${C2} x11 (X.Org 1.7.7)"
- done
- set_color_scheme 0
-
- if [[ $B_IRC == 'false' ]];then
- echo -n ""
-
- print_screen_output "$irc_clear $i)${spacer}Remove all color settings. Restore $SELF_NAME default."
- print_screen_output "$irc_clear $(($i+1)))${spacer}Continue, no changes or config file setting."
- print_screen_output "$irc_clear $(($i+2)))${spacer}Exit, use another terminal, or set manually."
- print_screen_output "$LINE1"
- print_lines_basic "0" "" "Simply type the number for the color scheme that looks best to your eyes for your $COLOR_SELECTION settings and hit ENTER. NOTE: You can bring this option list up by starting $SELF_NAME with option: -c plus one of these numbers:"
- print_lines_basic "0" "" "94^(console,^no X^-^$console); 95^(terminal,^X^-^$virt_term); 96^(irc,^gui,^X^-^$irc_gui); 97^(irc,^X,^in^terminal^-^$irc_x_term); 98^(irc,^no^X^-^$irc_console); 99^(global^-^$global)"
- print_lines_basic "0" "" ""
- print_screen_output "Your selection(s) will be stored here: $config_file"
- print_lines_basic "0" "" "Global overrides all individual color schemes. Individual schemes remove the global setting."
- print_screen_output "$LINE1"
- read user_selection
- if [[ "$user_selection" =~ ^([0-9]+)$ && $user_selection -lt $i ]];then
- case $COLOR_SELECTION in
- irc)
- config_variable='IRC_COLOR_SCHEME'
- ;;
- irc-console)
- config_variable='IRC_CONS_COLOR_SCHEME'
- ;;
- irc-virtual-terminal)
- config_variable='IRC_X_TERM_COLOR_SCHEME'
- ;;
- console)
- config_variable='CONSOLE_COLOR_SCHEME'
- ;;
- virtual-terminal)
- config_variable='VIRT_TERM_COLOR_SCHEME'
- ;;
- global)
- config_variable='GLOBAL_COLOR_SCHEME'
- ;;
- esac
- set_color_scheme $user_selection
- # make file/directory first if missing
- if [[ ! -f $config_file ]];then
- touch $config_file
- fi
- if [[ -z $( grep -s "$config_variable=" $config_file ) ]];then
- print_lines_basic "0" "" "Creating and updating config file for $COLOR_SELECTION color scheme now..."
- echo "$config_variable=$user_selection" >> $config_file
- else
- print_screen_output "Updating config file for $COLOR_SELECTION color scheme now..."
- sed $SED_I "s/$config_variable=.*/$config_variable=$user_selection/" $config_file
- fi
- # file exists now so we can go on to cleanup
- case $COLOR_SELECTION in
- irc|irc-console|irc-virtual-terminal|console|virtual-terminal)
- sed $SED_I '/GLOBAL_COLOR_SCHEME=/d' $config_file
- ;;
- global)
- sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' -e '/IRC_COLOR_SCHEME=/d' \
- -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
- ;;
- esac
- elif [[ $user_selection == $i ]];then
- print_screen_output "Removing all color settings from config file now..."
- sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/GLOBAL_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' \
- -e '/IRC_COLOR_SCHEME=/d' -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
- set_color_scheme $DEFAULT_COLOR_SCHEME
- elif [[ $user_selection == $(( $i+1 )) ]];then
- print_lines_basic "0" "" "Ok, continuing $SELF_NAME unchanged. You can set the colors anytime by starting with: -c 95 to 99"
- if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
- set_color_scheme $CONSOLE_COLOR_SCHEME
- elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
- set_color_scheme $VIRT_TERM_COLOR_SCHEME
- else
- set_color_scheme $DEFAULT_COLOR_SCHEME
- fi
- elif [[ $user_selection == $(( $i+2 )) ]];then
- set_color_scheme $DEFAULT_COLOR_SCHEME
- print_screen_output "Ok, exiting $SELF_NAME now. You can set the colors later."
- exit 0
- else
- print_screen_output "Error - Invalid Selection. You entered this: $user_selection"
- print_screen_output " "
- select_default_color_scheme
- fi
- else
- print_screen_output "$LINE1"
- print_lines_basic "0" "" "After finding the scheme number you like, simply run this again in a terminal to set the configuration data file for your irc client. You can set color schemes for the following: start inxi with -c plus:"
- print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
- print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
- exit 0
- fi
- eval $LOGFE
+package SelectColors;
+
+# use warnings;
+# use strict;
+# use diagnostics;
+# use 5.008;
+
+my (@data,@rows,%configs,%status);
+my ($type,$w_fh);
+my $safe_color_count = 12; # null/normal + default color group
+my $count = 0;
+
+# args: 1 - type
+sub new {
+ my $class = shift;
+ ($type) = @_;
+ my $self = {};
+ return bless $self, $class;
+}
+sub select_schema {
+ eval $start if $b_log;
+ assign_selectors();
+ main::set_color_scheme(0);
+ set_status();
+ start_selector();
+ create_color_selections();
+ if (! $b_irc ){
+ main::check_config_file();
+ get_selection();
+ }
+ else {
+ print_irc_message();
+ }
+ eval $end if $b_log;
+}
+
+sub set_status {
+ $status{'console'} = (defined $colors{'console'}) ? "Set: $colors{'console'}" : 'Not Set';
+ $status{'virt-term'} = (defined $colors{'virt-term'}) ? "Set: $colors{'virt-term'}" : 'Not Set';
+ $status{'irc-console'} = (defined $colors{'irc-console'}) ? "Set: $colors{'irc-console'}" : 'Not Set';
+ $status{'irc-gui'} = (defined $colors{'irc-gui'}) ? "Set: $colors{'irc-gui'}" : 'Not Set';
+ $status{'irc-virt-term'} = (defined $colors{'irc-virt-term'}) ? "Set: $colors{'irc-virt-term'}" : 'Not Set';
+ $status{'global'} = (defined $colors{'global'}) ? "Set: $colors{'global'}" : 'Not Set';
+}
+
+sub assign_selectors {
+ if ($type == 94){
+ $configs{'variable'} = 'CONSOLE_COLOR_SCHEME';
+ $configs{'selection'} = 'console';
+ }
+ elsif ($type == 95){
+ $configs{'variable'} = 'VIRT_TERM_COLOR_SCHEME';
+ $configs{'selection'} = 'virt-term';
+ }
+ elsif ($type == 96){
+ $configs{'variable'} = 'IRC_COLOR_SCHEME';
+ $configs{'selection'} = 'irc-gui';
+ }
+ elsif ($type == 97){
+ $configs{'variable'} = 'IRC_X_TERM_COLOR_SCHEME';
+ $configs{'selection'} = 'irc-virt-term';
+ }
+ elsif ($type == 98){
+ $configs{'variable'} = 'IRC_CONS_COLOR_SCHEME';
+ $configs{'selection'} = 'irc-console';
+ }
+ elsif ($type == 99){
+ $configs{'variable'} = 'GLOBAL_COLOR_SCHEME';
+ $configs{'selection'} = 'global';
+ }
+}
+sub start_selector {
+ my $whoami = getpwuid($<) || "unknown???";
+ if ( ! $b_irc ){
+ @data = (
+ [ 0, '', '', "Welcome to $self_name! Please select the default
+ $configs{'selection'} color scheme."],
+ );
+ }
+ @rows = (
+ [ 0, '', '', "Because there is no way to know your $configs{'selection'}
+ foreground/background colors, you can set your color preferences from
+ color scheme option list below:"],
+ [ 0, '', '', "0 is no colors; 1 is neutral."],
+ [ 0, '', '', "After these, there are 4 sets:"],
+ [ 0, '', '', "1-dark^or^light^backgrounds; 2-light^backgrounds;
+ 3-dark^backgrounds; 4-miscellaneous"],
+ [ 0, '', '', ""],
+ );
+ push @data, @rows;
+ if ( ! $b_irc ){
+ @rows = (
+ [ 0, '', '', "Please note that this will set the $configs{'selection'}
+ preferences only for user: $whoami"],
+ );
+ push @data, @rows;
+ }
+ @rows = (
+ [ 0, '', '', "$line1"],
+ );
+ push @data, @rows;
+ main::print_basic(@data);
+ @data = ();
+}
+sub create_color_selections {
+ my $spacer = '^^'; # printer removes double spaces, but replaces ^ with ' '
+ $count = ( main::get_color_scheme('count') - 1 );
+ for my $i (0 .. $count){
+ if ($i > 9){
+ $spacer = '^';
+ }
+ if ($configs{'selection'} =~ /^global|irc-gui|irc-console|irc-virt-term$/ && $i > $safe_color_count ){
+ last;
+ }
+ main::set_color_scheme($i);
+ @rows = (
+ [0, '', '', "$i)$spacer$colors{'c1'}Card:$colors{'c2'}^nVidia^GT218
+ $colors{'c1'}Display^Server$colors{'c2'}^x11^(X.Org^1.7.7)$colors{'cn'}"],
+ );
+ push @data, @rows;
+ }
+ main::print_basic(@data);
+ @data = ();
+ main::set_color_scheme(0);
+}
+sub get_selection {
+ my $number = $count + 1;
+ @data = (
+ [0, '', '', ($number++) . ")^Remove all color settings. Restore $self_name default."],
+ [0, '', '', ($number++) . ")^Continue, no changes or config file setting."],
+ [0, '', '', ($number++) . ")^Exit, use another terminal, or set manually."],
+ [0, '', '', "$line1"],
+ [0, '', '', "Simply type the number for the color scheme that looks best to your
+ eyes for your $configs{'selection'} settings and hit <ENTER>. NOTE: You can bring this
+ option list up by starting $self_name with option: -c plus one of these numbers:"],
+ [0, '', '', "94^-^console,^not^in^desktop^-^$status{'console'}"],
+ [0, '', '', "95^-^terminal,^desktop^-^$status{'virt-term'}"],
+ [0, '', '', "96^-^irc,^gui,^desktop^-^$status{'irc-gui'}"],
+ [0, '', '', "97^-^irc,^desktop,^in^terminal^-^$status{'irc-virt-term'}"],
+ [0, '', '', "98^-^irc,^not^in^desktop^-^$status{'irc-console'}"],
+ [0, '', '', "99^-^global^-^$status{'global'}"],
+ [0, '', '', ""],
+ [0, '', '', "Your selection(s) will be stored here: $user_config_file"],
+ [0, '', '', "Global overrides all individual color schemes. Individual
+ schemes remove the global setting."],
+ [0, '', '', "$line1"],
+ );
+ main::print_basic(@data);
+ @data = ();
+ my $response = <STDIN>;
+ chomp $response;
+ if ($response =~ /[^0-9]/ || $response > ($count + 3)){
+ @data = (
+ [0, '', '', "Error - Invalid Selection. You entered this: $response. Hit <ENTER> to continue."],
+ [0, '', '', "$line1"],
+ );
+ main::print_basic(@data);
+ my $response = <STDIN>;
+ start_selector();
+ create_color_selections();
+ get_selection();
+ }
+ else {
+ process_selection($response);
+ }
+}
+sub process_selection {
+ my $response = shift;
+ if ($response == ($count + 3) ){
+ @data = ([0, '', '', "Ok, exiting $self_name now. You can set the colors later."],);
+ main::print_basic(@data);
+ exit 1;
+ }
+ elsif ($response == ($count + 2)){
+ @data = (
+ [0, '', '', "Ok, continuing $self_name unchanged."],
+ [0, '', '', "$line1"],
+ );
+ main::print_basic(@data);
+ if ( defined $colors{'console'} && !$b_display ){
+ main::set_color_scheme($colors{'console'});
+ }
+ if ( defined $colors{'virt-term'} ){
+ main::set_color_scheme($colors{'virt-term'});
+ }
+ else {
+ main::set_color_scheme($colors{'default'});
+ }
+ }
+ elsif ($response == ($count + 1)){
+ @data = (
+ [0, '', '', "Removing all color settings from config file now..."],
+ [0, '', '', "$line1"],
+ );
+ main::print_basic(@data);
+ delete_all_config_colors();
+ main::set_color_scheme($colors{'default'});
+ }
+ else {
+ main::set_color_scheme($response);
+ @data = (
+ [0, '', '', "Updating config file for $configs{'selection'} color scheme now..."],
+ [0, '', '', "$line1"],
+ );
+ main::print_basic(@data);
+ if ($configs{'selection'} eq 'global'){
+ delete_all_config_colors();
+ }
+ set_config_color_scheme($response);
+ }
+}
+sub delete_all_config_colors {
+ my @file_lines = main::reader( $user_config_file );
+ open( $w_fh, '>', $user_config_file ) or error_handler('open', $user_config_file, $!);
+ foreach ( @file_lines ) {
+ if ( $_ !~ /^(CONSOLE_COLOR_SCHEME|GLOBAL_COLOR_SCHEME|IRC_COLOR_SCHEME|IRC_CONS_COLOR_SCHEME|IRC_X_TERM_COLOR_SCHEME|VIRT_TERM_COLOR_SCHEME)/){
+ print {$w_fh} "$_";
+ }
+ }
+ close $w_fh;
+}
+sub set_config_color_scheme {
+ my $value = shift;
+ my @file_lines = main::reader( $user_config_file );
+ my $b_found = 0;
+ open( $w_fh, '>', $user_config_file ) or error_handler('open', $user_config_file, $!);
+ foreach ( @file_lines ) {
+ if ( $_ =~ /^$configs{'variable'}/ ){
+ $_ = "$configs{'variable'}=$value";
+ $b_found = 1;
+ }
+ print $w_fh "$_\n";
+ }
+ if (! $b_found ){
+ print $w_fh "$configs{'variable'}=$value\n";
+ }
+ close $w_fh;
+}
+
+sub print_irc_message {
+ @data = (
+ [ 0, '', '', "$line1"],
+ [ 0, '', '', "After finding the scheme number you like, simply run this again
+ in a terminal to set the configuration data file for your irc client. You can
+ set color schemes for the following: start inxi with -c plus:"],
+ [ 0, '', '', "94 (console,^not^in^desktop^-^$status{'console'})"],
+ [ 0, '', '', "95 (terminal, desktop^-^$status{'virt-term'})"],
+ [ 0, '', '', "96 (irc,^gui,^desktop^-^$status{'irc-gui'})"],
+ [ 0, '', '', "97 (irc,^desktop,^in terminal^-^$status{'irc-virt-term'})"],
+ [ 0, '', '', "98 (irc,^not^in^desktop^-^$status{'irc-console'})"],
+ [ 0, '', '', "99 (global^-^$status{'global'})"]
+ );
+ main::print_basic(@data);
+ exit 1;
+}
+
+}
+
+#### -------------------------------------------------------------------
+#### CONFIGS
+#### -------------------------------------------------------------------
+
+sub check_config_file {
+ $user_config_file = "$user_config_dir/$self_name.conf";
+ if ( ! -f $user_config_file ){
+ open( my $fh, '>', $user_config_file ) or error_handler('create', $user_config_file, $!);
+ }
+}
+
+sub get_configs {
+ my (@configs) = @_;
+ my ($key, $val,@config_files);
+ if (!@configs){
+ @config_files = (
+ qq(/etc/$self_name.conf),
+ qq($user_config_dir/$self_name.conf)
+ );
+ }
+ else {
+ @config_files = (@configs);
+ }
+ # Config files should be passed in an array as a param to this function.
+ # Default intended use: global @CONFIGS;
+ foreach (@config_files) {
+ next unless open (my $fh, '<', "$_");
+ while (<$fh>) {
+ chomp;
+ s/#.*//;
+ s/^\s+//;
+ s/\s+$//;
+ s/'|"//g;
+ s/true/1/; # switch to 1/0 perl boolean
+ s/false/0/; # switch to 1/0 perl boolean
+ next unless length;
+ ($key, $val) = split(/\s*=\s*/, $_, 2);
+ get_config_item($key,$val);
+ # print "f: $file key: $key val: $val\n";
+ }
+ close $fh;
+ }
+}
+
+# args: 0: key; 1: value
+sub get_config_item {
+ my ($key,$val) = @_;
+ if ($key eq 'ALLOW_UPDATE' || $key eq 'B_ALLOW_UPDATE') {$b_update = int($val)}
+ elsif ($key eq 'ALLOW_WEATHER' || $key eq 'B_ALLOW_WEATHER') {$b_weather = int($val)}
+ elsif ($key eq 'CPU_SLEEP') {$cpu_sleep = $val if $val =~ /^[0-9\.]$/}
+ elsif ($key eq 'DL_TIMEOUT') {$dl_timeout = int($val)}
+ elsif ($key eq 'DOWNLOADER') {
+ if ($val =~ /^(curl|fetch|ftp|perl|wget)$/){
+ # this dumps all the other data and resets %dl for only the
+ # desired downloader.
+ $val = set_perl_downloader($val);
+ %dl = ('dl' => $val, $val => 1);
+ }}
+ elsif ($key eq 'FILTER_STRING') {$filter_string = $val}
+ elsif ($key eq 'LANGUAGE') {$language = $val if $val =~ /^(en)$/}
+ elsif ($key eq 'LIMIT') {$limit = int($val)}
+ elsif ($key eq 'OUTPUT_TYPE') {$output_type = $val if $val =~ /^json|screen|xml/}
+ elsif ($key eq 'PS_COUNT') {$ps_count = int($val) }
+ elsif ($key eq 'SENSORS_CPU_NO') {$sensors_cpu_nu = int($val)}
+ elsif ($key eq 'SHOW_HOST' || $key eq 'B_SHOW_HOST') { $show{'host'} = int($val)}
+ # layout
+ elsif ($key eq 'CONSOLE_COLOR_SCHEME') {$colors{'console'} = int($val)}
+ elsif ($key eq 'GLOBAL_COLOR_SCHEME') {$colors{'global'} = int($val)}
+ elsif ($key eq 'IRC_COLOR_SCHEME') {$colors{'irc-gui'} = int($val)}
+ elsif ($key eq 'IRC_CONS_COLOR_SCHEME') {$colors{'irc-console'} = int($val)}
+ elsif ($key eq 'IRC_X_TERM_COLOR_SCHEME') {$colors{'irc-virt-term'} = int($val)}
+ elsif ($key eq 'VIRT_TERM_COLOR_SCHEME') {$colors{'virt-term'} = int($val)}
+ # note: not using the old short SEP1/SEP2
+ elsif ($key eq 'SEP1_IRC') {$sep{'s1-irc'} = $val}
+ elsif ($key eq 'SEP1_CONSOLE') {$sep{'s1-console'} = $val}
+ elsif ($key eq 'SEP[23]_IRC') {$sep{'s2-irc'} = $val}
+ elsif ($key eq 'SEP[23]_CONSOLE') {$sep{'s2-console'} = $val}
+ # size
+ elsif ($key eq 'COLS_MAX_CONSOLE') {$size{'console'} = int($val)}
+ elsif ($key eq 'COLS_MAX_IRC') {$size{'irc'} = int($val)}
+ elsif ($key eq 'COLS_MAX_NO_DISPLAY') {$size{'no-display'} = int($val)}
+ elsif ($key eq 'INDENT') {$size{'indent'} = int($val)}
+ elsif ($key eq 'INDENT_MIN') {$size{'indent-min'} = int($val)}
+ # print "mc: key: $key val: $val\n";
+ # print Dumper (keys %size) . "\n";
}
#### -------------------------------------------------------------------
#### DEBUGGERS
#### -------------------------------------------------------------------
-# args: $1 - debug data type: sys|xorg|disk
-debug_data_collector()
+# called in the initial -@ 10 program args setting so we can get logging
+# as soon as possible # will have max 3 files, inxi.log, inxi.1.log,
+# inxi.2.log
+sub begin_logging {
+ return 1 if $fh_l; # if we want to start logging for testing before options
+ my $log_file_2="$user_data_dir/$self_name.1.log";
+ my $log_file_3="$user_data_dir/$self_name.2.log";
+ my $data = '';
+ $end='main::log_data("fe", (caller(1))[3], "");';
+ $start='main::log_data("fs", (caller(1))[3], \@_);';
+ #$t3 = tv_interval ($t0, [gettimeofday]);
+ $t3 = eval 'Time::HiRes::tv_interval (\@t0, [Time::HiRes::gettimeofday()]);' if $b_hires;
+ #print Dumper $@;
+ my $now = strftime "%Y-%m-%d %H:%M:%S", localtime;
+ # do the rotation if logfile exists
+ if ( -f $log_file ){
+ # copy if present second to third
+ if ( -f $log_file_2 ){
+ rename $log_file_2, $log_file_3 or error_handler('rename', "$log_file_2 -> $log_file_3", "$!");
+ }
+ # then copy initial to second
+ rename $log_file, $log_file_2 or error_handler('rename', "$log_file -> $log_file_2", "$!");
+ }
+ # now create the logfile
+ # print "Opening log file for reading: $log_file\n";
+ open $fh_l, '>', $log_file or error_handler(4, $log_file, "$!");
+ # and echo the start data
+ $data = $line2;
+ $data .= "START $self_name LOGGING:\n";
+ $data .= "NOTE: HiRes timer not available.\n" if !$b_hires;
+ $data .= "$now\n";
+ $data .= "Elapsed since start: $t3\n";
+ $data .= "n: $self_name v: $self_version p: $self_patch d: $self_date\n";
+ $data .= '@paths:' . joiner(\@paths, '::', 'unset') . "\n";
+ $data .= $line2;
+
+ print $fh_l $data;
+}
+# NOTE: no logging available until get_parameters is run, since that's what
+# sets logging # in order to trigger earlier logging manually set $b_log
+# to true in top variables.
+# args: $1 - type [fs|fe|cat|dump|raw] OR data to log
+# arg: $2 -
+# arg: $one type (fs/fe/cat/dump/raw) or logged data;
+# [$two is function name; [$three - function args]]
+sub log_data {
+ return if ! $b_log;
+ my ($one, $two, $three) = @_;
+ my $args = '';
+ my $data = '';
+ my $spacer = ' ';
+ # print "1: $one 2: $two 3: $three\n";
+ if ($one eq 'fs') {
+ if (ref $three eq 'ARRAY'){
+ my @temp = @$three;
+ # print Data::Dumper::Dumper \@$three;
+ $args = "\n${spacer}Args: " . joiner($three, '; ', 'unset');
+ }
+ else {
+ $args = "\n${spacer}Args: None";
+ }
+ # $t1 = [gettimeofday];
+ #$t3 = tv_interval ($t0, [gettimeofday]);
+ $t3 = eval 'Time::HiRes::tv_interval(\@t0, [Time::HiRes::gettimeofday()])' if $b_hires;
+ #print Dumper $@;
+ $data = "Start: Function: $two$args\n${spacer}Elapsed: $t3\n";
+ $spacer='';
+ }
+ elsif ( $one eq 'fe') {
+ # print 'timer:', Time::HiRes::tv_interval(\@t0, [Time::HiRes::gettimeofday()]),"\n";
+ #$t3 = tv_interval ($t0, [gettimeofday]);
+ eval '$t3 = Time::HiRes::tv_interval(\@t0, [Time::HiRes::gettimeofday()])' if $b_hires;
+ #print Dumper $t3;
+ $data = "${spacer}Elapsed: $t3\nEnd: Function: $two\n";
+ $spacer='';
+ }
+ elsif ( $one eq 'cat') {
+ if ( $b_log_full ){
+ for my $file ($two){
+ my $contents = do { local( @ARGV, $/ ) = $file; <> }; # or: qx(cat $file)
+ $data = "$data${line3}Full file data: $file\n\n$contents\n$line3\n";
+ }
+ $spacer='';
+ }
+ }
+ elsif ($one eq 'cmd'){
+ $data = "Command: $two\n";
+ $data .= qx($two);
+ }
+ elsif ($one eq 'data'){
+ $data = "$two\n";
+ }
+ elsif ( $one eq 'dump') {
+ $data = "$two:\n";
+ if (ref $three eq 'HASH'){
+ $data .= Data::Dumper::Dumper \%$three;
+ }
+ elsif (ref $three eq 'ARRAY'){
+ # print Data::Dumper::Dumper \@$three;
+ $data .= Data::Dumper::Dumper \@$three;
+ }
+ else {
+ $data .= Data::Dumper::Dumper $three;
+ }
+ $data .= "\n";
+ # print $data;
+ }
+ elsif ( $one eq 'raw') {
+ if ( $b_log_full ){
+ $data = "\n${line3}Raw System Data:\n\n$two\n$line3";
+ $spacer='';
+ }
+ }
+ else {
+ $data = "$two\n";
+ }
+ # print "d: $data";
+ if ($data){
+ print $fh_l "$spacer$data";
+ }
+}
+
+sub set_debugger {
+ if ( $debug < 10 || $debug > 12){
+ $end = '';
+ $start = '';
+ if ( $debug >= 20 ){
+ error_handler('not-in-irc', 'debug data generator') if $b_irc;
+ my $option = ( $debug > 22 ) ? 'main-full' : 'main';
+ $b_debug_gz = 1 if ($debug == 22 || $debug == 24);
+ my $ob_sys = SystemDebugger->new($option);
+ $ob_sys->run_debugger();
+ $ob_sys->upload_file($ftp_alt) if $debug > 20;
+ exit 0;
+ }
+ }
+ elsif ($debug >= 10 && $debug <= 12){
+ $b_log = 1;
+ if ($debug == 11){
+ $b_log_full = 1;
+ }
+ elsif ($debug == 12){
+ $b_log_colors = 1;
+ }
+ begin_logging();
+ }
+}
+
+## SystemDebugger
{
- local sys_data_file='' error='' bsd_string='' sys_traverse_data=''
- local xorg_d_files='' xorg_file='' a_distro_ids=''
- local completed_gz_file='' Ftp_Upload='ftp.techpatterns.com/incoming'
- local Line='-------------------------'
- local start_directory=$( pwd )
- local host='' debug_i='' root_string='' b_uploaded='false'
-
- if [[ -n $ALTERNATE_FTP ]];then
- Ftp_Upload=$ALTERNATE_FTP
- fi
-
- if (( "$BASH" >= 4 ));then
- host="${HOSTNAME,,}"
- else
- host=$( tr '[A-Z]' '[a-z]' <<< "$HOSTNAME" )
- fi
- if [[ $B_DEBUG_I == 'true' ]];then
- debug_i='i'
- fi
- if [[ -n $host ]];then
- host=${host// /-}
- else
- host="-no-host"
- fi
- if [[ -n $BSD_TYPE ]];then
- bsd_string="-$BSD_TYPE-$BSD_VERSION"
- fi
- if [[ $( whoami ) == 'root' ]];then
- root_string='-root'
- fi
-
- local Debug_Data_Dir="$SELF_NAME$bsd_string-$host-$(date +%Y%m%d-%H%M%S)-$1$root_string"
- local debug_gz="$Debug_Data_Dir.tar.gz"
+package SystemDebugger;
+
+# use File::Find q(find);
+#no warnings 'File::Find';
+# use File::Spec::Functions;
+#use File::Copy;
+#use POSIX qw(strftime);
+
+my $option = 'main';
+my $upload = '';
+my $data_dir = '';
+my $debug_dir = '';
+my $debug_gz = '';
+my @content = ();
+my $b_debug = 0;
+my $b_delete_dir = 1;
+# args: 1 - type
+# args: 2 - upload
+sub new {
+ my $class = shift;
+ ($option) = @_;
+ my $self = {};
+ # print "$f\n";
+ # print "$option\n";
+ return bless $self, $class;
+}
+
+sub run_debugger {
+ require File::Copy;
+ import File::Copy;
+ require File::Spec::Functions;
+ import File::Spec::Functions;
+
+ print "Starting $self_name debugging data collector...\n";
+ create_debug_directory();
+ print "Note: for dmidecode data you must be root.\n" if !$b_root;
+ print $line3;
+ if (!$b_debug){
+ audio_data();
+ disk_data();
+ display_data();
+ network_data();
+ perl_modules();
+ system_data();
+ }
+ system_files();
+ print $line3;
+ if (!$b_debug){
+ if ( -d '/sys' && main::count_dir_files('/sys') ){
+ sys_tree();
+ sys_traverse_data();
+ }
+ else {
+ print "Skipping /sys data collection. /sys not present, or empty.\n";
+ }
+ print $line3;
+ }
+ run_self();
+ print $line3;
+ compress_dir();
+}
+
+sub create_debug_directory {
+ my $host = main::get_hostname();
+ $host =~ s/ /-/g;
+ $host ||= 'no-host';
+ my ($arm_string,$bsd_string,$root_string) = ('','','');
+ # note: Time::Piece was introduced in perl 5.9.5
+ my ($sec,$min,$hour,$mday,$mon,$year) = localtime;
+ my $version = substr($self_version,0,3);
+ $year = $year+1900;
+ $mon += 1;
+ if (length($sec) == 1) {$sec = "0$sec";}
+ if (length($min) == 1) {$min = "0$min";}
+ if (length($hour) == 1) {$hour = "0$hour";}
+ if (length($mon) == 1) {$mon = "0$mon";}
+ if (length($mday) == 1) {$mday = "0$mday";}
+
+ my $today = "$year-$mon-${mday}_$hour$min$sec";
+ # my $date = strftime "-%Y-%m-%d_", localtime;
+ if ($b_root){
+ $root_string = '-root';
+ }
+ $bsd_string = "-BSD-$bsd_type" if $bsd_type;
+ $arm_string = '-ARM' if $b_arm;
+ $debug_dir = "$self_name$arm_string$bsd_string-$host-$today$root_string-$version";
+ $debug_gz = "$debug_dir.tar.gz";
+ $data_dir = "$user_data_dir/$debug_dir";
+ if ( -d $data_dir ){
+ unlink $data_dir or main::error_handler('remove', "$data_dir", "$!");
+ }
+ mkdir $data_dir or main::error_handler('mkdir', "$data_dir", "$!");
+ if ( -e "$user_data_dir/$debug_gz" ){
+ #rmdir "$user_data_dir$debug_gz" or main::error_handler('remove', "$user_data_dir/$debug_gz", "$!");
+ print "Failed removing leftover directory:\n$user_data_dir$debug_gz error: $?" if system('rm','-rf',"$user_data_dir$debug_gz");
+ }
+ print "Data going into:\n$data_dir\n";
+}
+sub compress_dir {
+ print "Creating tar.gz compressed file of this material...\n";
+ print "File: $debug_gz\n";
+ system("cd $user_data_dir; tar -czf $debug_gz $debug_dir");
+ print "Removing $data_dir...\n";
+ #rmdir $data_dir or print "failed removing: $data_dir error: $!\n";
+ return 1 if !$b_delete_dir;
+ if (system('rm','-rf',$data_dir) ){
+ print "Failed removing: $data_dir\nError: $?\n";
+ }
+ else {
+ print "Directory removed.\n";
+ }
+}
+# NOTE: incomplete, don't know how to ever find out
+# what sound server is actually running, and is in control
+sub audio_data {
+ my (%data,@files,@files2);
+ print "Collecting audio data...\n";
+ my @cmds = (
+ ['aplay', '-l'], # alsa
+ ['pactl', 'list'], # pulseaudio
+ );
+ run_commands(\@cmds,'audio');
+ @files = main::globber('/proc/asound/card*/codec*');
+ if (@files){
+ my $asound = qx(head -n 1 /proc/asound/card*/codec* 2>&1);
+ $data{'proc-asound-codecs'} = $asound;
+ }
+ else {
+ $data{'proc-asound-codecs'} = undef;
+ }
- if [[ $B_IRC == 'false' ]];then
- echo "Starting $SELF_NAME debugging data collection type: $1"
- cd $SELF_DATA_DIR
- if [[ -d $SELF_DATA_DIR/$Debug_Data_Dir ]];then
- echo "Deleting previous $SELF_NAME debugger data directory..."
- rm -rf $SELF_DATA_DIR/$Debug_Data_Dir
- fi
- mkdir $SELF_DATA_DIR/$Debug_Data_Dir
- if [[ -f $SELF_DATA_DIR/$debug_gz ]];then
- echo 'Deleting previous tar.gz file...'
- rm -f $SELF_DATA_DIR/$debug_gz
- fi
- echo "Data going into: $SELF_DATA_DIR/$Debug_Data_Dir"
- echo 'Note: for dmidecode data you must be root.'
- echo $Line
- echo "Collecting system data..."
-
- # bsd tools http://cb.vu/unixtoolbox.xhtml
- # freebsd
- if type -p pciconf &>/dev/null;then
- pciconf -l -cv &> $Debug_Data_Dir/bsd-pciconf-cvl.txt
- pciconf -vl &> $Debug_Data_Dir/bsd-pciconf-vl.txt
- pciconf -l &> $Debug_Data_Dir/bsd-pciconf-l.txt
- else
- touch $Debug_Data_Dir/bsd-pciconf-absent
- fi
- # openbsd
- if type -p pcidump &>/dev/null;then
- pcidump &> $Debug_Data_Dir/bsd-pcidump-openbsd.txt
- pcidump -v &> $Debug_Data_Dir/bsd-pcidump-v-openbsd.txt
- else
- touch $Debug_Data_Dir/bsd-pcidump-openbsd-absent
- fi
- # netbsd
- if type -p pcictl &>/dev/null;then
- pcictl list &> $Debug_Data_Dir/bsd-pcictl-list-netbsd.txt
- pcictl list -n &> $Debug_Data_Dir/bsd-pcictl-list-n-netbsd.txt
- else
- touch $Debug_Data_Dir/bsd-pcictl-netbsd-absent
- fi
- if type -p sysctl &>/dev/null;then
- sysctl -a &> $Debug_Data_Dir/bsd-sysctl-a.txt
- else
- touch $Debug_Data_Dir/bsd-sysctl-absent
- fi
- if type -p usbdevs &>/dev/null;then
- usbdevs -v &> $Debug_Data_Dir/bsd-usbdevs-v.txt
- else
- touch $Debug_Data_Dir/bsd-usbdevs-absent
- fi
- if type -p kldstat &>/dev/null;then
- kldstat &> $Debug_Data_Dir/bsd-kldstat.txt
- else
- touch $Debug_Data_Dir/bsd-kldstat-absent
- fi
- # diskinfo -v <disk>
- # fdisk <disk>
- dmidecode &> $Debug_Data_Dir/dmidecode.txt
- dmesg &> $Debug_Data_Dir/dmesg.txt
- lscpu &> $Debug_Data_Dir/lscpu.txt
- lspci &> $Debug_Data_Dir/lspci.txt
- lspci -k &> $Debug_Data_Dir/lspci-k.txt
- lspci -knn &> $Debug_Data_Dir/lspci-knn.txt
- lspci -n &> $Debug_Data_Dir/lspci-n.txt
- lspci -nn &> $Debug_Data_Dir/lspci-nn.txt
- lspci -mm &> $Debug_Data_Dir/lspci-mm.txt
- lspci -mmnn &> $Debug_Data_Dir/lspci-mmnn.txt
- lspci -mmnnv &> $Debug_Data_Dir/lspci-mmnnv.txt
- lspci -v &> $Debug_Data_Dir/lspci-v.txt
- if type -p lsusb &>/dev/null;then
- lsusb &> $Debug_Data_Dir/lsusb.txt
- lsusb -v &> $Debug_Data_Dir/lsusb-v.txt
- else
- touch $Debug_Data_Dir/lsusb-absent
- fi
- if type -p hciconfig &>/dev/null;then
- hciconfig -a &> $Debug_Data_Dir/hciconfig-a.txt
- else
- touch $Debug_Data_Dir/hciconfig-absent
- fi
- ps aux &> $Debug_Data_Dir/ps-aux.txt
- ps -e &> $Debug_Data_Dir/ps-e.txt
- ps -p 1 &> $Debug_Data_Dir/ps-p-1.txt
- runlevel &> $Debug_Data_Dir/runlevel.txt
- if type -p rc-status &>/dev/null;then
- rc-status -a &> $Debug_Data_Dir/rc-status-a.txt
- rc-status -l &> $Debug_Data_Dir/rc-status-l.txt
- rc-status -r &> $Debug_Data_Dir/rc-status-r.txt
- else
- touch $Debug_Data_Dir/rc-status-absent
- fi
- if type -p systemctl &>/dev/null;then
- systemctl list-units &> $Debug_Data_Dir/systemctl-list-units.txt
- systemctl list-units --type=target &> $Debug_Data_Dir/systemctl-list-units-target.txt
- else
- touch $Debug_Data_Dir/systemctl-absent
- fi
- if type -p initctl &>/dev/null;then
- initctl list &> $Debug_Data_Dir/initctl-list.txt
- else
- touch $Debug_Data_Dir/initctl-absent
- fi
- sensors &> $Debug_Data_Dir/sensors.txt
- if type -p strings &>/dev/null;then
- touch $Debug_Data_Dir/strings-present
- else
- touch $Debug_Data_Dir/strings-absent
- fi
- # leaving this commented out to remind that some systems do not
- # support strings --version, but will just simply hang at that command
- # which you can duplicate by simply typing: strings then hitting enter, you will get hang.
- # strings --version &> $Debug_Data_Dir/strings.txt
- if type -p nvidia-smi &>/dev/null;then
- nvidia-smi -q &> $Debug_Data_Dir/nvidia-smi-q.txt
- nvidia-smi -q -x &> $Debug_Data_Dir/nvidia-smi-xq.txt
- else
- touch $Debug_Data_Dir/nvidia-smi-absent
- fi
- echo $CC &> $Debug_Data_Dir/cc-content.txt
- ls /usr/bin/gcc* &> $Debug_Data_Dir/gcc-sys-versions.txt
- if type -p gcc &>/dev/null;then
- gcc --version &> $Debug_Data_Dir/gcc-version.txt
- else
- touch $Debug_Data_Dir/gcc-absent
- fi
- if type -p clang &>/dev/null;then
- clang --version &> $Debug_Data_Dir/clang-version.txt
- else
- touch $Debug_Data_Dir/clang-absent
- fi
- if type -p systemd-detect-virt &>/dev/null;then
- systemd-detect-virt &> $Debug_Data_Dir/systemd-detect-virt-info.txt
- else
- touch $Debug_Data_Dir/systemd-detect-virt-absent
- fi
- echo "Collecting Perl module data..."
- if type -p perl &>/dev/null;then
- perl -MFile::Find=find -MFile::Spec::Functions -Tlwe 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2>/dev/null | sort &> $Debug_Data_Dir/perl-modules.txt
- else
- touch $Debug_Data_Dir/perl-missing.txt
- fi
- echo "Collecting system file data..."
- cat /proc/1/comm &> $Debug_Data_Dir/proc-1-comm.txt
- if type -t get_repo_data &>/dev/null;then
- get_repo_data "$SELF_DATA_DIR/$Debug_Data_Dir"
- fi
- head -n 1 /proc/asound/card*/codec* &> $Debug_Data_Dir/proc-asound-card-codec.txt
- if [[ -f /proc/version ]];then
- cat /proc/version &> $Debug_Data_Dir/proc-version.txt
- else
- touch $Debug_Data_Dir/proc-version-absent
- fi
- local id_dir='/sys/class/power_supply/'
- local ids=$( ls $id_dir 2>/dev/null )
- if [[ -n $ids ]];then
- for batid in $ids
- do
- cat $id_dir$batid'/uevent' &> $Debug_Data_Dir/sys-power-supply-$batid.txt
- done
- else
- touch $Debug_Data_Dir/sys-power-supply-none
- fi
- if type -p shopt &>/dev/null;then
- shopt -s nullglob
- a_distro_ids=(/etc/*[-_]{release,version})
- shopt -u nullglob
- echo ${a_distro_ids[@]} &> $Debug_Data_Dir/etc-distro-files.txt
- for distro_file in ${a_distro_ids[@]} /etc/issue
- do
- if [[ -f $distro_file ]];then
- cat $distro_file &> $Debug_Data_Dir/distro-file${distro_file//\//-}
- fi
- done
- fi
- cat /etc/src.conf &> $Debug_Data_Dir/bsd-etc-src-conf.txt
- cat /etc/make.conf &> $Debug_Data_Dir/bsd-etc-make-conf.txt
- cat /etc/issue &> $Debug_Data_Dir/etc-issue.txt
- cat $FILE_LSB_RELEASE &> $Debug_Data_Dir/lsb-release.txt
- cat $FILE_OS_RELEASE &> $Debug_Data_Dir/os-release.txt
- cat $FILE_ASOUND_DEVICE &> $Debug_Data_Dir/proc-asound-device.txt
- cat $FILE_ASOUND_VERSION &> $Debug_Data_Dir/proc-asound-version.txt
- cat $FILE_CPUINFO &> $Debug_Data_Dir/proc-cpu-info.txt
- cat $FILE_MEMINFO &> $Debug_Data_Dir/proc-meminfo.txt
- cat $FILE_MODULES &> $Debug_Data_Dir/proc-modules.txt
- cat /proc/net/arp &> $Debug_Data_Dir/proc-net-arp.txt
- # bsd data
- cat /var/run/dmesg.boot &> $Debug_Data_Dir/bsd-var-run-dmesg.boot.txt
- echo $COLS_INNER &> $Debug_Data_Dir/cols-inner.txt
- echo $XDG_CONFIG_HOME &> $Debug_Data_Dir/xdg_config_home.txt
- echo $XDG_CONFIG_DIRS &> $Debug_Data_Dir/xdg_config_dirs.txt
- echo $XDG_DATA_HOME &> $Debug_Data_Dir/xdg_data_home.txt
- echo $XDG_DATA_DIRS &> $Debug_Data_Dir/xdg_data_dirs.txt
- if type -t check_recommends_user_output &>/dev/null;then
- check_recommends_user_output &> $Debug_Data_Dir/check-recommends-user-output.txt
- fi
- if [[ $1 == 'xorg' || $1 == 'all' ]];then
- if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
- echo 'Warning: only some of the data collection can occur if you are not in X'
- touch $Debug_Data_Dir/warning-user-not-in-x
- fi
- if [[ $B_ROOT == 'true' ]];then
- echo 'Warning: only some of the data collection can occur if you are running as Root user'
- touch $Debug_Data_Dir/warning-root-user
- fi
- echo 'Collecting Xorg log and xorg.conf files...'
- if [[ -e $FILE_XORG_LOG ]];then
- cat $FILE_XORG_LOG &> $Debug_Data_Dir/xorg-log-file.txt
- else
- touch $Debug_Data_Dir/xorg-log-file-absent
- fi
- if [[ -e /etc/X11/xorg.conf ]];then
- cat /etc/X11/xorg.conf &> $Debug_Data_Dir/xorg-conf.txt
- else
- touch $Debug_Data_Dir/xorg-conf-file-absent
- fi
- if [[ -n $( ls /etc/X11/xorg.conf.d/ 2>/dev/null ) ]];then
- ls /etc/X11/xorg.conf.d &> $Debug_Data_Dir/ls-etc-x11-xorg-conf-d.txt
- xorg_d_files=$(ls /etc/X11/xorg.conf.d)
- for xorg_file in $xorg_d_files
- do
- cat /etc/X11/xorg.conf.d/$xorg_file &> $Debug_Data_Dir/xorg-conf-d-$xorg_file.txt
- done
- else
- touch $Debug_Data_Dir/xorg-conf-d-files-absent
- fi
- echo 'Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, wayland, weston...'
- if type -p weston-info &>/dev/null; then
- weston-info &> $Debug_Data_Dir/weston-info.txt
- else
- touch $Debug_Data_Dir/weston-info-absent
- fi
- if type -p weston &>/dev/null; then
- weston --version &> $Debug_Data_Dir/weston-version.txt
- else
- touch $Debug_Data_Dir/weston-absent
- fi
- if type -p xprop &>/dev/null; then
- xprop -root &> $Debug_Data_Dir/xprop_root.txt
- else
- touch $Debug_Data_Dir/xprop-absent
- fi
- if type -p glxinfo &>/dev/null; then
- glxinfo &> $Debug_Data_Dir/glxinfo-full.txt
- glxinfo -B &> $Debug_Data_Dir/glxinfo-B.txt
- else
- touch $Debug_Data_Dir/glxinfo-absent
- fi
- if type -p xdpyinfo &>/dev/null; then
- xdpyinfo &> $Debug_Data_Dir/xdpyinfo.txt
- else
- touch $Debug_Data_Dir/xdpyinfo-absent
- fi
- if type -p xrandr &>/dev/null; then
- xrandr &> $Debug_Data_Dir/xrandr.txt
- else
- touch $Debug_Data_Dir/xrandr-absent
- fi
- if type -p X &>/dev/null; then
- X -version &> $Debug_Data_Dir/x-version.txt
- else
- touch $Debug_Data_Dir/x-absent
- fi
- if type -p Xorg &>/dev/null; then
- Xorg -version &> $Debug_Data_Dir/xorg-version.txt
- else
- touch $Debug_Data_Dir/xorg-absent
- fi
- echo $GNOME_DESKTOP_SESSION_ID &> $Debug_Data_Dir/gnome-desktop-session-id.txt
- # kde 3 id
- echo $KDE_FULL_SESSION &> $Debug_Data_Dir/kde3-full-session.txt
- echo $KDE_SESSION_VERSION &> $Debug_Data_Dir/kde-gte-4-session-version.txt
- if type -p kf5-config &>/dev/null; then
- kf5-config --version &> $Debug_Data_Dir/kde-kf5-config-version-data.txt
- elif type -p kf6-config &>/dev/null; then
- kf6-config --version &> $Debug_Data_Dir/kde-kf6-config-version-data.txt
- elif type -p kf$KDE_SESSION_VERSION-config &>/dev/null; then
- kf$KDE_SESSION_VERSION-config --version &> $Debug_Data_Dir/kde-kf$KDE_SESSION_VERSION-KSV-config-version-data.txt
- else
- touch $Debug_Data_Dir/kde-kf-config-absent
- fi
- if type -p plasmashell &>/dev/null; then
- plasmashell --version &> $Debug_Data_Dir/kde-plasmashell-version-data.txt
- else
- touch $Debug_Data_Dir/kde-plasmashell-absent
- fi
- if type -p kwin_x11 &>/dev/null; then
- kwin_x11 --version &> $Debug_Data_Dir/kde-kwin_x11-version-data.txt
- else
- touch $Debug_Data_Dir/kde-kwin_x11-absent
- fi
- if type -p kded4 &>/dev/null; then
- kded4 --version &> $Debug_Data_Dir/kded4-version-data.txt
- elif type -p kded5 &>/dev/null; then
- kded5 --version &> $Debug_Data_Dir/kded5-version-data.txt
- elif type -p kded &>/dev/null; then
- kded --version &> $Debug_Data_Dir/kded-version-data.txt
- else
- touch $Debug_Data_Dir/kded-$KDE_SESSION_VERSION-absent
- fi
- # kde 5/plasma desktop 5, this is maybe an extra package and won't be used
- if type -p about-distro &>/dev/null; then
- about-distro &> $Debug_Data_Dir/kde-about-distro.txt
- else
- touch $Debug_Data_Dir/kde-about-distro-absent
- fi
- echo $XDG_CURRENT_DESKTOP &> $Debug_Data_Dir/xdg-current-desktop.txt
- echo $XDG_SESSION_DESKTOP &> $Debug_Data_Dir/xdg-session-desktop.txt
- echo $DESKTOP_SESSION &> $Debug_Data_Dir/desktop-session.txt
- echo $GDMSESSION &> $Debug_Data_Dir/gdmsession.txt
- # wayland data collectors:
- echo $XDG_SESSION_TYPE &> $Debug_Data_Dir/xdg-session-type.txt
- echo $WAYLAND_DISPLAY &> $Debug_Data_Dir/wayland-display.txt
- echo $GDK_BACKEND &> $Debug_Data_Dir/gdk-backend.txt
- echo $QT_QPA_PLATFORM &> $Debug_Data_Dir/qt-qpa-platform.txt
- echo $CLUTTER_BACKEND &> $Debug_Data_Dir/clutter-backend.txt
- echo $SDL_VIDEODRIVER &> $Debug_Data_Dir/sdl-videodriver.txt
- if type -p loginctl &>/dev/null;then
- loginctl --no-pager list-sessions &> $Debug_Data_Dir/loginctl-list-sessions.txt
- else
- touch $Debug_Data_Dir/loginctl-absent
- fi
- fi
- if [[ $1 == 'disk' || $1 == 'all' ]];then
- echo 'Collecting dev, label, disk, uuid data, df...'
- ls -l /dev &> $Debug_Data_Dir/dev-data.txt
- ls -l /dev/disk &> $Debug_Data_Dir/dev-disk-data.txt
- ls -l /dev/disk/by-id &> $Debug_Data_Dir/dev-disk-id-data.txt
- ls -l /dev/disk/by-label &> $Debug_Data_Dir/dev-disk-label-data.txt
- ls -l /dev/disk/by-uuid &> $Debug_Data_Dir/dev-disk-uuid-data.txt
- # http://comments.gmane.org/gmane.linux.file-systems.zfs.user/2032
- ls -l /dev/disk/by-wwn &> $Debug_Data_Dir/dev-disk-wwn-data.txt
- ls -l /dev/disk/by-path &> $Debug_Data_Dir/dev-disk-path-data.txt
- ls -l /dev/mapper &> $Debug_Data_Dir/dev-disk-mapper-data.txt
- readlink /dev/root &> $Debug_Data_Dir/dev-root.txt
- df -h -T -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 --exclude-type=devfs --exclude-type=linprocfs --exclude-type=sysfs --exclude-type=fdescfs &> $Debug_Data_Dir/df-h-T-P-excludes.txt
- df -T -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 --exclude-type=devfs --exclude-type=linprocfs --exclude-type=sysfs --exclude-type=fdescfs &> $Debug_Data_Dir/df-T-P-excludes.txt
- df -T -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 --exclude-type=devfs --exclude-type=linprocfs --exclude-type=sysfs --exclude-type=fdescfs --total &> $Debug_Data_Dir/df-T-P-excludes-total.txt
- df -h -T &> $Debug_Data_Dir/bsd-df-h-T-no-excludes.txt
- df -h &> $Debug_Data_Dir/bsd-df-h-no-excludes.txt
- df -k -T &> $Debug_Data_Dir/bsd-df-k-T-no-excludes.txt
- df -k &> $Debug_Data_Dir/bsd-df-k-no-excludes.txt
- atacontrol list &> $Debug_Data_Dir/bsd-atacontrol-list.txt
- camcontrol devlist &> $Debug_Data_Dir/bsd-camcontrol-devlist.txt
- # bsd tool
- mount &> $Debug_Data_Dir/mount.txt
- btrfs filesystem show &> $Debug_Data_Dir/btrfs-filesystem-show.txt
- btrfs filesystem show --mounted &> $Debug_Data_Dir/btrfs-filesystem-show-mounted.txt
- # btrfs filesystem show --all-devices &> $Debug_Data_Dir/btrfs-filesystem-show-all-devices.txt
- gpart list &> $Debug_Data_Dir/bsd-gpart-list.txt
- gpart show &> $Debug_Data_Dir/bsd-gpart-show.txt
- gpart status &> $Debug_Data_Dir/bsd-gpart-status.txt
- swapctl -l -k &> $Debug_Data_Dir/bsd-swapctl-l-k.txt
- swapon -s &> $Debug_Data_Dir/swapon-s.txt
- sysctl -b kern.geom.conftxt &> $Debug_Data_Dir/bsd-sysctl-b-kern.geom.conftxt.txt
- sysctl -b kern.geom.confxml &> $Debug_Data_Dir/bsd-sysctl-b-kern.geom.confxml.txt
- zfs list &> $Debug_Data_Dir/zfs-list.txt
- zpool list &> $Debug_Data_Dir/zpool-list.txt
- zpool list -v &> $Debug_Data_Dir/zpool-list-v.txt
- df -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 &> $Debug_Data_Dir/df-P-excludes.txt
- df -P &> $Debug_Data_Dir/bsd-df-P-no-excludes.txt
- cat /proc/mdstat &> $Debug_Data_Dir/proc-mdstat.txt
- cat $FILE_PARTITIONS &> $Debug_Data_Dir/proc-partitions.txt
- cat $FILE_SCSI &> $Debug_Data_Dir/proc-scsi.txt
- cat $FILE_MOUNTS &> $Debug_Data_Dir/proc-mounts.txt
- cat $FILE_MDSTAT &> $Debug_Data_Dir/proc-mdstat.txt
- cat /proc/sys/dev/cdrom/info &> $Debug_Data_Dir/proc-cdrom-info.txt
- ls /proc/ide/ &> $Debug_Data_Dir/proc-ide.txt
- cat /proc/ide/*/* &> $Debug_Data_Dir/proc-ide-hdx-cat.txt
- cat /etc/fstab &> $Debug_Data_Dir/etc-fstab.txt
- cat /etc/mtab &> $Debug_Data_Dir/etc-mtab.txt
- if type -p nvme &>/dev/null; then
- touch $Debug_Data_Dir/nvme-present
- else
- touch $Debug_Data_Dir/nvme-absent
- fi
- fi
- if [[ $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
- echo 'Collecting networking data...'
- ifconfig &> $Debug_Data_Dir/ifconfig.txt
- ip addr &> $Debug_Data_Dir/ip-addr.txt
- fi
- # create the error file in case it's needed
- if [[ $B_UPLOAD_DEBUG_DATA == 'true' || $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
- touch $SELF_DATA_DIR/$Debug_Data_Dir/sys-dir-error.txt
- fi
- # just on the off chance bsds start having a fake /sys
- ls /sys &> $Debug_Data_Dir/sys-ls-1.txt
- # note, only bash 4> supports ;;& for case, so using if/then here
- if [[ -z $BSD_TYPE ]] && [[ $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
- echo $Line
- sys_data_file=$SELF_DATA_DIR/$Debug_Data_Dir/sys-dir-traverse.txt
- echo "Getting file paths in /sys..."
- sys_tree
- # note, this generates more lines than the full sys parsing, so only use if required
- # ls_sys 5
- touch $sys_data_file
- if type -p perl &>/dev/null;then
- echo "Parsing /sys files..."
- echo -n "Using Perl: " && perl --version | grep -oE 'v[0-9.]+'
- sys_traverse_data="$( sys_traverse_data )"
- if [[ -z "$sys_traverse_data" ]];then
- echo -e "ERROR: failed to generate /sys data - removing data file.\nContinuing with incomplete data collection."
- echo "Continuing with incomplete data collection."
- rm -f $sys_data_file
- echo "/sys data generation failed. No data collected." >> $Debug_Data_Dir/sys-dir-error.txt
- else
- echo 'Completed /sys data collection.'
- echo -n "$sys_traverse_data" > $sys_data_file
- fi
- fi
- fi
- # running in inxi
- if type -t check_recommends_user_output &>/dev/null;then
- echo $Line
- echo "Creating $SELF_NAME output file now. This can take a few seconds..."
- echo "Starting $SELF_NAME from: $start_directory"
- cd $start_directory
- $SELF_PATH/$SELF_NAME -F${debug_i}Rfrploudmxxx -c 0 -@ 8 -y 120 > $SELF_DATA_DIR/$Debug_Data_Dir/inxi-F${debug_i}Rfrploudmxxxy120.txt
- cp $LOG_FILE $SELF_DATA_DIR/$Debug_Data_Dir
- elif type -p inxi &>/dev/null;then
- echo $Line
- echo "Creating basic inxi output file..."
- inxi -Fxxx > $Debug_Data_Dir/inxi-Fxxx.txt
- else
- touch $Debug_Data_Dir/inxi-absent.txt
- fi
- cd $SELF_DATA_DIR
- echo $Line
- echo 'Creating tar.gz compressed file of this material...'
- tar -czf $debug_gz $Debug_Data_Dir
- echo 'Cleaning up leftovers...'
- rm -rf $Debug_Data_Dir
- echo 'Testing gzip file integrity...'
- gzip -t $debug_gz
- if [[ $? -gt 0 ]];then
- echo 'Data in gz is corrupted, removing gzip file, try running data collector again.'
- rm -f $debug_gz
- echo "Data in gz is corrupted, removed gzip file" >> $Debug_Data_Dir/gzip-error.txt
- else
- echo 'All done, you can find your data gzipped directory here:'
- completed_gz_file=$SELF_DATA_DIR/$debug_gz
- echo $completed_gz_file
- if [[ $B_UPLOAD_DEBUG_DATA == 'true' ]];then
- echo $Line
- upload_debugger_data "$completed_gz_file" "$Ftp_Upload"
- if [[ $? -gt 0 ]];then
- echo "Error: looks like the Perl ftp upload failed. Error number: $?"
- else
- b_uploaded='true'
- echo "Hurray! Looks like the Perl ftp upload worked!"
- fi
- else
- echo 'You can upload this here using most file managers: ftp.techpatterns.com/incoming'
- echo 'then let a maintainer know it is uploaded.'
- fi
- fi
- else
- echo 'This feature only available in console or shell client! Exiting now.'
- fi
- exit 0
-}
-
-## args: $1 - depth
-ls_sys()
-{
- local files=''
- case $1 in
- 1)files='/sys/';;
- 2)files='/sys/*/';;
- 3)files='/sys/*/*/';;
- 4)files='/sys/*/*/*/';; # this should be enough for most use cases
- 5)files='/sys/*/*/*/*/';; # very large file, shows best shortcuts though
- 6)files='/sys/*/*/*/*/*/';; # slows down too much, too big, can cause ls error
- 7)files='/sys/*/*/*/*/*/*/';; # impossibly big, will fail
- esac
- ls -l $files 2>/dev/null | awk '{
- if (NF > 7) {
- if ($1 ~/^d/){
- f="d - "
- }
- else if ($1 ~/^l/){
- f="l - "
+ write_data(\%data,'audio');
+ @files = (
+ '/proc/asound/cards',
+ '/proc/asound/version',
+ );
+ @files2 = main::globber('/proc/asound/*/usbid');
+ @files = (@files,@files2) if @files2;
+ copy_files(\@files,'audio');
+}
+## NOTE: >/dev/null 2>&1 is sh, and &>/dev/null is bash, fix this
+# ls -w 1 /sysrs > tester 2>&1
+sub disk_data {
+ my (%data,@files,@files2);
+ print "Collecting dev, label, disk, uuid data, df...\n";
+ @files = (
+ '/etc/fstab',
+ '/etc/mtab',
+ '/proc/mdstat',
+ '/proc/mounts',
+ '/proc/partitions',
+ '/proc/scsi/scsi',
+ '/proc/sys/dev/cdrom/info',
+ );
+ # very old systems
+ if (-d '/proc/ide/'){
+ my @ides = main::globber('/proc/ide/*/*');
+ @files = (@files, @ides) if @ides;
+ }
+ else {
+ push (@files, '/proc-ide-directory');
+ }
+ copy_files(\@files, 'disk');
+ my @cmds = (
+ ['btrfs', 'filesystem show'],
+ ['btrfs', 'filesystem show --mounted'],
+ # ['btrfs', 'filesystem show --all-devices'],
+ ['df', '-h -T'],
+ ['df', '-h'],
+ ['df', '-k'],
+ ['df', '-k -T'],
+ ['df', '-k -T -P'],
+ ['df', '-P'],
+ ['lsblk', '-fs'],
+ ['lsblk', '-fsr'],
+ ['lsblk', '-fsP'],
+ ['lsblk', '-a'],
+ ['lsblk', '-aP'],
+ ['lsblk', '-ar'],
+ ['lsblk', '-p'],
+ ['lsblk', '-pr'],
+ ['lsblk', '-pP'],
+ ['lsblk', '-r'],
+ ['lsblk', '-r --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT'],
+ ['lsblk', '-rb --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT'],
+ ['lsblk', '-Pb --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT'],
+ ['gpart', 'list'],
+ ['gpart', 'show'],
+ ['gpart', 'status'],
+ ['ls', '-l /dev'],
+ ['ls', '-l /dev/disk'],
+ ['ls', '-l /dev/disk/by-id'],
+ ['ls', '-l /dev/disk/by-label'],
+ ['ls', '-l /dev/disk/by-uuid'],
+ # http://comments.gmane.org/gmane.linux.file-systems.zfs.user/2032
+ ['ls', '-l /dev/disk/by-wwn'],
+ ['ls', '-l /dev/disk/by-path'],
+ ['ls', '-l /dev/mapper'],
+ ['mount', ''],
+ ['nvme', 'present'],
+ ['readlink', '/dev/root'],
+ ['swapon', '-s'],
+ ['zfs', 'list'],
+ ['zpool', 'list'],
+ ['zpool', 'list -v'],
+ );
+ run_commands(\@cmds,'disk');
+ @cmds = (
+ ['atacontrol', 'list'],
+ ['camcontrol', 'devlist'],
+ ['glabel', 'status'],
+ ['swapctl', '-l -k'],
+ ['swapctl', '-l -k'],
+ ['vmstat', '-H'],
+ );
+ run_commands(\@cmds,'disk-bsd');
+}
+sub display_data {
+ my (%data,@files,@files2);
+ my $working = '';
+ if ( ! $b_display ){
+ print "Warning: only some of the data collection can occur if you are not in X\n";
+ main::toucher("$data_dir/display-data-warning-user-not-in-x");
+ }
+ if ( $b_root ){
+ print "Warning: only some of the data collection can occur if you are running as Root user\n";
+ main::toucher("$data_dir/display-data-warning-root-user");
+ }
+ print "Collecting Xorg log and xorg.conf files...\n";
+ if ( -d "/etc/X11/xorg.conf.d/" ){
+ @files = main::globber("/etc/X11/xorg.conf.d/*");
+ }
+ else {
+ @files = ('/xorg-conf-d');
+ }
+ push (@files, $files{'xorg-log'});
+ push (@files, '/etc/X11/xorg.conf');
+ copy_files(\@files,'display-xorg');
+ print "Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, wayland, weston...\n";
+ %data = (
+ 'desktop-session' => $ENV{'DESKTOP_SESSION'},
+ 'gdmsession' => $ENV{'GDMSESSION'},
+ 'gnome-desktop-session-id' => $ENV{'GNOME_DESKTOP_SESSION_ID'},
+ 'kde3-full-session' => $ENV{'KDE_FULL_SESSION'},
+ 'xdg-current-desktop' => $ENV{'XDG_CURRENT_DESKTOP'},
+ 'kde-gte-4-session-version' => $ENV{'KDE_SESSION_VERSION'},
+ 'xdg-session-desktop' => $ENV{'XDG_SESSION_DESKTOP'},
+ # wayland data collectors:
+ 'xdg-session-type' => $ENV{'XDG_SESSION_TYPE'},
+ 'wayland-display' => $ENV{'WAYLAND_DISPLAY'},
+ 'gdk-backend' => $ENV{'GDK_BACKEND'},
+ 'qt-qpa-platform' => $ENV{'QT_QPA_PLATFORM'},
+ 'clutter-backend' => $ENV{'CLUTTER_BACKEND'},
+ 'sdl-videodriver' => $ENV{'SDL_VIDEODRIVER'},
+ # program display values
+ 'size-indent' => $size{'indent'},
+ 'size-indent-min' => $size{'indent-min'},
+ 'size-cols-max' => $size{'max'},
+ );
+ write_data(\%data,'display');
+ my @cmds = (
+ # kde 5/plasma desktop 5, this is maybe an extra package and won't be used
+ ['about-distro',''],
+ ['aticonfig','--adapter=all --od-gettemperature'],
+ ['glxinfo',''],
+ ['glxinfo','-B'],
+ ['kded','--version'],
+ ['kded1','--version'],
+ ['kded2','--version'],
+ ['kded3','--version'],
+ ['kded4','--version'],
+ ['kded5','--version'],
+ ['kded6','--version'],
+ ['kf4-config','--version'],
+ ['kf5-config','--version'],
+ ['kf6-config','--version'],
+ ['kwin_x11','--version'],
+ ['loginctl','--no-pager list-sessions'],
+ ['nvidia-settings','-q screens'],
+ ['nvidia-settings','-c :0.0 -q all'],
+ ['nvidia-smi','-q'],
+ ['nvidia-smi','-q -x'],
+ ['plasmashell','--version'],
+ ['weston-info',''],
+ ['wmctrl','-m'],
+ ['weston','--version'],
+ ['xdpyinfo',''],
+ ['Xorg','-version'],
+ ['xprop','-root'],
+ ['xrandr',''],
+ );
+ run_commands(\@cmds,'display');
+}
+sub network_data {
+ print "Collecting networking data...\n";
+# no warnings 'uninitialized';
+ my @cmds = (
+ ['ifconfig',''],
+ ['ip','addr'],
+ ['ip','-s link'],
+ );
+ run_commands(\@cmds,'network');
+}
+sub perl_modules {
+ print "Collecting Perl module data (this can take a while)...\n";
+ my @modules = ();
+ my ($dirname,$holder,$mods,$value) = ('','','','');
+ my $filename = 'perl-modules.txt';
+ my @inc;
+ foreach (sort @INC){
+ # some BSD installs have '.' n @INC path
+ if (-d $_ && $_ ne '.'){
+ $_ =~ s/\/$//; # just in case, trim off trailing slash
+ $value .= "EXISTS: $_\n";
+ push @inc, $_;
+ }
+ else {
+ $value .= "ABSENT: $_\n";
+ }
+ }
+ main::writer("$data_dir/perl-inc-data.txt",$value);
+ File::Find::find { wanted => sub {
+ push @modules, File::Spec->canonpath($_) if /\.pm\z/
+ }, no_chdir => 1 }, @inc;
+ @modules = sort(@modules);
+ foreach (@modules){
+ my $dir = $_;
+ $dir =~ s/[^\/]+$//;
+ if (!$holder || $holder ne $dir ){
+ $holder = $dir;
+ $value = "DIR: $dir\n";
+ $_ =~ s/^$dir//;
+ $value .= " $_\n";
+ }
+ else {
+ $value = $_;
+ $value =~ s/^$dir//;
+ $value = " $value\n";
+ }
+ $mods .= $value;
+ }
+ open (my $fh, '>', "$data_dir/$filename");
+ print $fh $mods;
+ close $fh;
+}
+sub system_data {
+ print "Collecting system data...\n";
+ my %data = (
+ 'cc' => $ENV{'CC'},
+ # @(#)MIRBSD KSH R56 2018/03/09: ksh and mksh
+ 'ksh-version' => $ENV{'KSH_VERSION'},
+ 'manpath' => $ENV{'MANPATH'},
+ 'path' => $ENV{'PATH'},
+ 'xdg-config-home' => $ENV{'XDG_CONFIG_HOME'},
+ 'xdg-config-dirs' => $ENV{'XDG_CONFIG_DIRS'},
+ 'xdg-data-home' => $ENV{'XDG_DATA_HOME'},
+ 'xdg-data-dirs' => $ENV{'XDG_DATA_DIRS'},
+ );
+ my @files = main::globber('/usr/bin/gcc*');
+ if (@files){
+ $data{'gcc-versions'} = join "\n",@files;
+ }
+ else {
+ $data{'gcc-versions'} = undef;
+ }
+ @files = main::globber('/sys/*');
+ if (@files){
+ $data{'sys-tree-ls-1-basic'} = join "\n", @files;
+ }
+ else {
+ $data{'sys-tree-ls-1-basic'} = undef;
+ }
+ write_data(\%data,'system');
+ # bsd tools http://cb.vu/unixtoolbox.xhtml
+ my @cmds = (
+ # general
+ ['sysctl', '-b kern.geom.conftxt'],
+ ['sysctl', '-b kern.geom.confxml'],
+ ['usbdevs','-v'],
+ # freebsd
+ ['pciconf','-l -cv'],
+ ['pciconf','-vl'],
+ ['pciconf','-l'],
+ # openbsd
+ ['pcidump',''],
+ ['pcidump','-v'],
+ # netbsd
+ ['kldstat',''],
+ ['pcictl','list'],
+ ['pcictl','list -ns'],
+ );
+ run_commands(\@cmds,'system-bsd');
+ # diskinfo -v <disk>
+ # fdisk <disk>
+ @cmds = (
+ ['clang','--version'],
+ ['dmidecode',''],
+ ['dmesg',''],
+ ['gcc','--version'],
+ ['hciconfig','-a'],
+ ['initctl','list'],
+ ['ipmi-sensors',''],
+ ['ipmi-sensors','--output-sensor-thresholds'],
+ ['ipmitool','sensor'],
+ ['lscpu',''],
+ ['lspci','-k'],
+ ['lspci','-knn'],
+ ['lspci','-knnv'],# returns ports
+ ['lspci','-n'],
+ ['lspci','-nn'],
+ ['lspci','-nnk'],
+ ['lspci','-mm'],
+ ['lspci','-mmk'],
+ ['lspci','-mmkv'],
+ ['lspci','-mmnn'],
+ ['lspci','-v'],
+ ['lspci',''],
+ ['lsusb',''],
+ ['lsusb','-v'],
+ ['ps','aux'],
+ ['ps','-e'],
+ ['ps','-p 1'],
+ ['runlevel',''],
+ ['rc-status','-a'],
+ ['rc-status','-l'],
+ ['rc-status','-r'],
+ ['sensors',''],
+ # leaving this commented out to remind that some systems do not
+ # support strings --version, but will just simply hang at that command
+ # which you can duplicate by simply typing: strings then hitting enter.
+ # ['strings','--version'],
+ ['strings','present'],
+ ['sysctl','-a'],
+ ['systemctl','list-units'],
+ ['systemctl','list-units --type=target'],
+ ['systemd-detect-virt',''],
+ ['uptime',''],
+ );
+ run_commands(\@cmds,'system');
+ @files = main::globber('/dev/bus/usb/*/*');
+ copy_files(\@files, 'system');
+}
+sub system_files {
+ print "Collecting system files data...\n";
+ my (%data,@files,@files2);
+ @files = RepoData::get($data_dir);
+ copy_files(\@files, 'repo');
+ # chdir "/etc";
+ @files = main::globber("/etc/*[-_]{[rR]elease,[vV]ersion}");
+ push (@files, '/etc/issue');
+ push (@files, '/etc/lsb-release');
+ push (@files, '/etc/os-release');
+ copy_files(\@files,'system-distro');
+ @files = (
+ '/proc/1/comm',
+ '/proc/cpuinfo',
+ '/proc/meminfo',
+ '/proc/modules',
+ '/proc/net/arp',
+ '/proc/version',
+ );
+ @files2=main::globber('/sys/class/power_supply/*/uevent');
+ if (@files2){
+ @files = (@files,@files2);
+ }
+ else {
+ push (@files, '/sys-class-power-supply-empty');
+ }
+ copy_files(\@files, 'system');
+ @files = (
+ '/etc/make.conf',
+ '/etc/src.conf',
+ '/var/run/dmesg.boot',
+ );
+ copy_files(\@files,'system-bsd');
+}
+
+sub copy_files {
+ my ($files_ref, $type) = @_;
+ my ($absent,$error,$good,$name,$unreadable);
+ foreach (@$files_ref) {
+ $name = $_;
+ $name =~ s/^\///;
+ $name =~ s/\//-/g;
+ $name = "$data_dir/$type-file-$name";
+ $good = $name . '.txt';
+ $absent = $name . '-absent';
+ $error = $name . '-error';
+ $unreadable = $name . '-unreadable';
+ if (-e $_ ) {
+ if (-r $_){
+ copy($_,"$good") or main::toucher($error);
}
else {
- f="f - "
+ main::toucher($unreadable);
}
- # includes -> target for symbolic link if present
- print "\t" f $9 " " $10 " " $11
- }
- else if (!/^total / ) {
- print $0
- }
- }' &> $Debug_Data_Dir/sys-ls-$1.txt
+ }
+ else {
+ main::toucher($absent);
+ }
+ }
}
-# prior to script up set, pack the data into an array
-# then we'll print it out later.
-# args: $1 - $@ debugging string text
-self_debugger()
-{
- eval $LOGFS
- if [[ $B_SCRIPT_UP == 'true' ]];then
- # only return if debugger is off and no pre start up errors have occurred
- if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then
- return 0
- # print out the stored debugging information if errors occurred
- elif [[ $DEBUG_BUFFER_INDEX -gt 0 ]];then
- for (( DEBUG_BUFFER_INDEX=0; DEBUG_BUFFER_INDEX < ${#A_DEBUG_BUFFER[@]}; DEBUG_BUFFER_INDEX++ ))
- do
- print_screen_output "${A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]}"
- done
- DEBUG_BUFFER_INDEX=0
- fi
- # or print out normal debugger messages if debugger is on
- if [[ $DEBUG -gt 0 ]];then
- print_screen_output "$1"
- fi
- else
- if [[ $B_DEBUG_FLOOD == 'true' && $DEBUG_BUFFER_INDEX -gt 10 ]];then
- error_handler 2
- # this case stores the data for later printout, will print out only
- # at B_SCRIPT_UP == 'true' if array index > 0
- else
- A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]="$1"
- # increment count for next pre script up debugging error
- (( DEBUG_BUFFER_INDEX++ ))
- fi
- fi
- eval $LOGFE
-}
-
-sys_traverse_data()
-{
- local sys_traverse_data="$( perl -e '
- use File::Find;
- use strict;
- # use warnings;
- use 5.008;
- my @content = ();
- find( \&wanted, "/sys");
- process_data( @content );
- sub wanted {
- return if -d; # not directory
- return unless -e; # Must exist
- return unless -r; # Must be readable
- return unless -f; # Must be file
- # note: a new file in 4.11 /sys can hang this, it is /parameter/ then
- # a few variables. Since inxi does not need to see that file, we will
- # not use it. Also do not need . files or __ starting files
- return if $File::Find::name =~ /\/(\.[a-z]|__|kernel\/|parameters\/|debug\/)/;
- # comment this one out if you experience hangs or if
- # we discover syntax of foreign language characters
- # Must be ascii like. This is questionable and might require further
- # investigation, it is removing some characters that we might want
- return unless -T;
- # print $File::Find::name . "\n";
- push @content, $File::Find::name;
- return;
- }
- sub process_data {
- my $result = "";
- my $row = "";
- my $fh;
- my $data="";
- my $sep="";
- # no sorts, we want the order it comes in
- # @content = sort @content;
- foreach (@content){
- $data="";
- $sep="";
- open($fh, "<$_");
- while ($row = <$fh>) {
- chomp $row;
- $data .= $sep . "\"" . $row . "\"";
- $sep=", ";
- }
- $result .= "$_:[$data]\n";
- # print "$_:[$data]\n"
- }
- # print scalar @content . "\n";
- print "$result";
- } ' )"
- echo "$sys_traverse_data"
-}
-
-sys_tree()
-{
- if type -p tree &>/dev/null;then
- tree -a -L 10 /sys > $Debug_Data_Dir/sys-tree-full-10.txt
- for branch in $( tree -i -L 1 -d --noreport /sys | grep -v 'sys$' );do
- tree -a -L 10 /sys/$branch > $Debug_Data_Dir/sys-tree-$branch-10.txt
- done
- else
- # ls_sys 1
- ls_sys 2
- ls_sys 3
- ls_sys 4
- fi
-}
-
-## args: $1 - debugger file name; $2 - ftp destination [does not work]
-upload_debugger_data()
-{
- local result='' debugger_file=$1
-
- if ! type -p perl &>/dev/null;then
- echo "Perl is not installed!"
- return 2
- elif ! perl -MNet::FTP -e 1 &>/dev/null;then
- echo "Required Perl module Net::FTP not installed."
- return 3
- fi
- echo "Starting Perl Uploader..."
-
- result="$( perl -e '
- use strict;
- use warnings;
- use 5.008;
- use Net::FTP;
- my ($ftp, $host, $user, $pass, $dir, $fpath, $error);
- $host = "ftp.techpatterns.com";
+sub run_commands {
+ my ($cmds,$type) = @_;
+ my $holder = '';
+ my ($name,$cmd,$args);
+ foreach (@$cmds){
+ my @rows = @$_;
+ if (my $program = main::check_program($rows[0])){
+ if ($rows[1] eq 'present'){
+ $name = "$data_dir/$type-cmd-$rows[0]-present";
+ main::toucher($name);
+ }
+ else {
+ $args = $rows[1];
+ $args =~ s/\s|--|\/|=/-/g; # for:
+ $args =~ s/--/-/g;# strip out -- that result from the above
+ $args =~ s/^-//g;
+ $args = "-$args" if $args;
+ $name = "$data_dir/$type-cmd-$rows[0]$args.txt";
+ $cmd = "$program $rows[1] >$name 2>&1";
+ system($cmd);
+ }
+ }
+ else {
+ if ($holder ne $rows[0]){
+ $name = "$data_dir/$type-cmd-$rows[0]-absent";
+ main::toucher($name);
+ $holder = $rows[0];
+ }
+ }
+ }
+}
+sub write_data {
+ my ($data_ref, $type) = @_;
+ my ($empty,$error,$fh,$good,$name,$undefined,$value);
+ foreach (keys %$data_ref) {
+ $value = $$data_ref{$_};
+ $name = "$data_dir/$type-data-$_";
+ $good = $name . '.txt';
+ $empty = $name . '-empty';
+ $error = $name . '-error';
+ $undefined = $name . '-undefined';
+ if (defined $value) {
+ if ($value || $value eq '0'){
+ open($fh, '>', $good) or main::toucher($error);
+ print $fh "$value";
+ }
+ else {
+ main::toucher($empty);
+ }
+ }
+ else {
+ main::toucher($undefined);
+ }
+ }
+}
+
+sub run_self {
+ print "Creating $self_name output file now. This can take a few seconds...\n";
+ print "Starting $self_name from: $self_path\n";
+ my $i = ($option eq 'main-full')? ' -i' : '';
+ my $cmd = "$self_path/$self_name -FRfrploudmxxx$i -c 0 --usb --slots --debug 10 -y 120 > $data_dir/$self_name-FRfrploudmxxxyusbslots120.txt 2>&1";
+ system($cmd);
+ copy($log_file, "$data_dir") or main::error_handler('copy-failed', "$log_file", "$!");
+ system("$self_path/$self_name --recommends -y 120 > $data_dir/$self_name-recommends-120.txt 2>&1");
+}
+
+sub sys_tree {
+ print "Constructing /sys tree data...\n";
+ if ( main::check_program('tree') ){
+ my $dirname = '/sys';
+ my $cmd;
+ system("tree -a -L 10 /sys > $data_dir/sys-data-tree-full-10.txt");
+ opendir my($dh), $dirname or main::error_handler('open-dir',"$dirname", "$!");
+ my @files = readdir $dh;
+ closedir $dh;
+ foreach (@files){
+ next if /^\./;
+ $cmd = "tree -a -L 10 $dirname/$_ > $data_dir/sys-data-tree-$_-10.txt";
+ #print "$cmd\n";
+ system($cmd);
+ }
+ }
+ # for now, we want all of these as well for better debugging
+ #else {
+ sys_ls(1);
+ sys_ls(2);
+ sys_ls(3);
+ sys_ls(4);
+ #}
+}
+sub sys_ls {
+ my ( $depth) = @_;
+ my $cmd = do {
+ if ( $depth == 1 ){ 'ls -l /sys/ 2>/dev/null' }
+ elsif ( $depth == 2 ){ 'ls -l /sys/*/ 2>/dev/null' }
+ elsif ( $depth == 3 ){ 'ls -l /sys/*/*/ 2>/dev/null' }
+ elsif ( $depth == 4 ){ 'ls -l /sys/*/*/*/ 2>/dev/null' }
+ elsif ( $depth == 5 ){ 'ls -l /sys/*/*/*/*/ 2>/dev/null' }
+ elsif ( $depth == 5 ){ 'ls -l /sys/*/*/*/*/ 2>/dev/null' }
+ };
+ my @working = ();
+ my $output = '';
+ my ($type);
+ my $result = qx($cmd);
+ open my $ch, '<', \$result or main::error_handler('open-data',"$cmd", "$!");
+ while ( my $line = <$ch> ){
+ chomp($line);
+ $line =~ s/^\s+|\s+$//g;
+ @working = split /\s+/, $line;
+ $working[0] ||= '';
+ if ( scalar @working > 7 ){
+ if ($working[0] =~ /^d/ ){
+ $type = "d - ";
+ }
+ elsif ($working[0] =~ /^l/){
+ $type = "l - ";
+ }
+ else {
+ $type = "f - ";
+ }
+ $working[9] ||= '';
+ $working[10] ||= '';
+ $output = $output . " $type$working[8] $working[9] $working[10]\n";
+ }
+ elsif ( $working[0] !~ /^total/ ){
+ $output = $output . $line . "\n";
+ }
+ }
+ close $ch;
+ my $file = "$data_dir/sys-data-ls-$depth.txt";
+ open my $fh, '>', $file or main::error_handler('create',"$file", "$!");
+ print $fh $output;
+ close $fh;
+ # print "$output\n";
+}
+
+sub sys_traverse_data {
+ print "Parsing /sys files...\n";
+ # get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied
+ no warnings 'File::Find';
+ File::Find::find( \&wanted, "/sys");
+ process_data();
+}
+sub wanted {
+ return if -d; # not directory
+ return unless -e; # Must exist
+ return unless -r; # Must be readable
+ return unless -f; # Must be file
+ # note: a new file in 4.11 /sys can hang this, it is /parameter/ then
+ # a few variables. Since inxi does not need to see that file, we will
+ # not use it. Also do not need . files or __ starting files
+ # print $File::Find::name . "\n";
+ # block maybe: cfgroup\/
+ return if $File::Find::name =~ /\/(\.[a-z]|kernel\/|parameters\/|debug\/)/;
+ # comment this one out if you experience hangs or if
+ # we discover syntax of foreign language characters
+ # Must be ascii like. This is questionable and might require further
+ # investigation, it is removing some characters that we might want
+ return unless -T;
+ # print $File::Find::name . "\n";
+ push (@content, $File::Find::name);
+ return;
+}
+sub process_data {
+ my ($data,$fh,$result,$row,$sep);
+ my $filename = "sys-data-parse.txt";
+ # no sorts, we want the order it comes in
+ # @content = sort @content;
+ foreach (@content){
+ $data='';
+ $sep='';
+ open($fh, '<', $_);
+ while ($row = <$fh>) {
+ chomp $row;
+ $data .= $sep . '"' . $row . '"';
+ $sep=', ';
+ }
+ $result .= "$_:[$data]\n";
+ # print "$_:[$data]\n"
+ }
+ # print scalar @content . "\n";
+ open ($fh, '>', "$data_dir/$filename");
+ print $fh $result;
+ close $fh;
+ # print $fh "$result";
+}
+# args: 1 - path to file to be uploaded
+# args: 2 - optional: alternate ftp upload url
+# NOTE: must be in format: ftp.site.com/incoming
+sub upload_file {
+ require Net::FTP;
+ import Net::FTP;
+ my ($self, $ftp_url) = @_;
+ my ($ftp, $domain, $host, $user, $pass, $dir, $error);
+ $ftp_url ||= main::get_defaults('ftp-upload');
+ $ftp_url =~ s/\/$//g; # trim off trailing slash if present
+ my @url = split(/\//, $ftp_url);
+ my $file_path = "$user_data_dir/$debug_gz";
+ $host = $url[0];
+ $dir = $url[1];
+ $domain = $host;
+ $domain =~ s/^ftp\.//;
$user = "anonymous";
- $pass = "anonymous\@techpatterns.com";
- $dir = "incoming";
- $fpath = $ARGV[0];
- # NOTE: important: must explicitly set to passive true/1
- $ftp = Net::FTP->new($host, Debug => 0, Passive => 1);
- $ftp->login($user, $pass) || die $ftp->message;
- $ftp->binary();
- $ftp->cwd($dir);
- print "Connected to FTP server.\n";
- $ftp->put($fpath) || die $ftp->message;
- $ftp->quit;
- print "Uploaded file $fpath.\n";
- print $ftp->message;
- ' $debugger_file )"
-
- if [[ "$result" != '' ]];then
- echo "$result"
- fi
- if [[ "$result" == *Goodbye* ]];then
- return 0
- else
- return 1
- fi
+ $pass = "anonymous\@$domain";
+
+ print $line3;
+ print "Uploading to: $ftp_url\n";
+ # print "$host $domain $dir $user $pass\n";
+ print "File to be uploaded:\n$file_path\n";
+
+ if ($host && ( $file_path && -e $file_path ) ){
+ # NOTE: important: must explicitly set to passive true/1
+ $ftp = Net::FTP->new($host, Debug => 0, Passive => 1);
+ $ftp->login($user, $pass) || main::error_handler('ftp-login', $ftp->message);
+ $ftp->binary();
+ $ftp->cwd($dir);
+ print "Connected to FTP server.\n";
+ $ftp->put($file_path) || main::error_handler('ftp-upload', $ftp->message);
+ $ftp->quit;
+ print "Uploaded file successfully!\n";
+ print $ftp->message;
+ if ($b_debug_gz){
+ print "Removing debugger gz file:\n$file_path\n";
+ unlink $file_path or main::error_handler('remove',"$file_path", "$!");
+ print "File removed.\n";
+ }
+ print "Debugger data generation and upload completed. Thank you for your help.\n";
+ }
+ else {
+ main::error_handler('ftp-bad-path', "$file_path");
+ }
+}
}
#### -------------------------------------------------------------------
#### DOWNLOADER
#### -------------------------------------------------------------------
-download_file()
-{
- local retvalue=0
- local data=$( perl -e 'use strict;
- use warnings;
- use 5.008;
- use HTTP::Tiny;
- sub get_file {
- my ($type, $url, $file) = @_;
- my $response = HTTP::Tiny->new->get($url);
- my $return = 0;
- my $debug = 0;
- my $fh;
-
- if ($response->{success} == 0 ){
- # print "Failed to connect to server/file!\n";
- $return = 1;
+sub download_file {
+ my ($type, $url, $file) = @_;
+ my ($cmd,$args,$timeout) = ('','','');
+ my $debug_data = '';
+ my $result = 1;
+ $dl{'no-ssl-opt'} ||= '';
+ $dl{'spider'} ||= '';
+ $file ||= 'N/A'; # to avoid debug error
+ if ( ! $dl{'dl'} ){
+ return 0;
+ }
+ if ($dl{'timeout'}){
+ $timeout = "$dl{'timeout'}$dl_timeout";
+ }
+ # print "$dl{'no-ssl-opt'}\n";
+ # print "$dl{'dl'}\n";
+ # tiny supports spider sort of
+ ## NOTE: 1 is success, 0 false for Perl
+ if ($dl{'dl'} eq 'tiny' ){
+ $cmd = "Using tiny: type: $type \nurl: $url \nfile: $file";
+ $result = get_file($type, $url, $file);
+ $debug_data = ($type ne 'stdout') ? $result : 'Success: stdout data not null.';
+ }
+ # But: 0 is success, and 1 is false for these
+ # when strings are returned, they will be taken as true
+ else {
+ if ($type eq 'stdout'){
+ $args = $dl{'stdout'};
+ $cmd = "$dl{'dl'} $dl{'no-ssl-opt'} $timeout $args $url $dl{'null'}";
+ $result = qx($cmd);
+ $debug_data = ($result) ? 'Success: stdout data not null.' : 'Download resulted in null data!';
}
- else {
- if ( $debug ){
- print "$response->{success}\n";
- print "$response->{status} $response->{reason}\n";
- while (my ($key, $value) = each %{$response->{headers}}) {
- for (ref $value eq "ARRAY" ? @$value : $value) {
- print "$key: $_\n";
- }
+ elsif ($type eq 'file') {
+ $args = $dl{'file'};
+ $cmd = "$dl{'dl'} $dl{'no-ssl-opt'} $timeout $args $file $url $dl{'null'}";
+ system($cmd);
+ $result = ($?) ? 0 : 1; # reverse these into Perl t/f
+ $debug_data = $result;
+ }
+ elsif ( $dl{'dl'} eq 'wget' && $type eq 'spider'){
+ $cmd = "$dl{'dl'} $dl{'no-ssl-opt'} $timeout $dl{'spider'} $url";
+ system($cmd);
+ $result = ($?) ? 0 : 1; # reverse these into Perl t/f
+ $debug_data = $result;
+ }
+ }
+ print "-------\nDownloader Data:\n$cmd\nResult: $debug_data\n" if $test[1];
+ log_data('data',"$cmd\nResult: $result") if $b_log;
+ return $result;
+}
+
+sub get_file {
+ my ($type, $url, $file) = @_;
+ my $response = HTTP::Tiny->new->get($url);
+ my $return = 1;
+ my $debug = 0;
+ my $fh;
+ $file ||= 'N/A';
+ log_data('dump','%{$response}',\%{$response}) if $b_log;
+ # print Dumper \%{$response};
+ if ( ! $response->{success} ){
+ my $content = $response->{content};
+ $content ||= "N/A\n";
+ 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];
+ $return = 0;
+ }
+ else {
+ if ( $debug ){
+ print "$response->{success}\n";
+ print "$response->{status} $response->{reason}\n";
+ while (my ($key, $value) = each %{$response->{headers}}) {
+ for (ref $value eq "ARRAY" ? @$value : $value) {
+ print "$key: $_\n";
}
}
- if ( $type eq "stdout" || $type eq "ua-stdout" ){
- print "$response->{content}" if length $response->{content};
- }
- elsif ($type eq "spider"){
- # do nothing, just use the return value
- }
- elsif ($type eq "file"){
- open($fh, ">", $file);
- print $fh $response->{content};
- close $fh;
- }
}
- return $return;
+ if ( $type eq "stdout" || $type eq "ua-stdout" ){
+ $return = $response->{content};
+ }
+ elsif ($type eq "spider"){
+ # do nothing, just use the return value
+ }
+ elsif ($type eq "file"){
+ open($fh, ">", $file);
+ print $fh $response->{content}; # or die "can't write to file!\n";
+ close $fh;
+ }
}
- get_file($ARGV[0],$ARGV[1],$ARGV[2]);' "$1" "$2" "$3" )
- retvalue=$?
- if [[ "$data" != '' ]];then
- echo "$data"
- fi
- return $retvalue
+ return $return;
+}
+
+sub set_downloader {
+ eval $start if $b_log;
+ $dl{'no-ssl'} = '';
+ $dl{'null'} = '';
+ $dl{'spider'} = '';
+ # we only want to use HTTP::Tiny if it's present in user system.
+ # It is NOT part of core modules. IO::Socket::SSL is also required
+ # For some https connections so only use tiny as option if both present
+ if ($dl{'tiny'}){
+ if (check_module('HTTP::Tiny') && check_module('IO::Socket::SSL')){
+ import HTTP::Tiny;
+ import IO::Socket::SSL;
+ $dl{'tiny'} = 1;
+ }
+ else {
+ $dl{'tiny'} = 0;
+ }
+ }
+ #print $dl{'tiny'} . "\n";
+ if ($dl{'tiny'}){
+ $dl{'dl'} = 'tiny';
+ $dl{'file'} = '';
+ $dl{'stdout'} = '';
+ $dl{'timeout'} = '';
+ }
+ elsif ( $dl{'curl'} && check_program('curl') ){
+ $dl{'dl'} = 'curl';
+ $dl{'file'} = ' -L -s -o ';
+ $dl{'no-ssl'} = ' --insecure';
+ $dl{'stdout'} = ' -L -s ';
+ $dl{'timeout'} = ' -y ';
+ }
+ elsif ($dl{'wget'} && check_program('wget') ){
+ $dl{'dl'} = 'wget';
+ $dl{'file'} = ' -q -O ';
+ $dl{'no-ssl'} = ' --no-check-certificate';
+ $dl{'spider'} = ' -q --spider';
+ $dl{'stdout'} = ' -q -O -';
+ $dl{'timeout'} = ' -T ';
+ }
+ elsif ($dl{'fetch'} && check_program('fetch')){
+ $dl{'dl'} = 'fetch';
+ $dl{'file'} = ' -q -o ';
+ $dl{'no-ssl'} = ' --no-verify-peer';
+ $dl{'stdout'} = ' -q -o -';
+ $dl{'timeout'} = ' -T ';
+ }
+ elsif ( $bsd_type eq 'openbsd' && check_program('ftp') ){
+ $dl{'dl'} = 'ftp';
+ $dl{'file'} = ' -o ';
+ $dl{'null'} = ' 2>/dev/null';
+ $dl{'stdout'} = ' -o - ';
+ $dl{'timeout'} = '';
+ }
+ else {
+ $dl{'dl'} = '';
+ }
+ # no-ssl-opt is set to 1 with --no-ssl, so it is true, then assign
+ $dl{'no-ssl-opt'} = $dl{'no-ssl'} if $dl{'no-ssl-opt'};
+ eval $end if $b_log;
+}
+
+sub set_perl_downloader {
+ my ($downloader) = @_;
+ $downloader =~ s/perl/tiny/;
+ return $downloader;
}
-# download_file 'stdout' 'https://cnn.com/robots.txt' '';echo $?; exit
#### -------------------------------------------------------------------
#### ERROR HANDLER
#### -------------------------------------------------------------------
-# Error handling
-# args: $1 - error number; $2 - optional, extra information; $3 - optional extra info
-error_handler()
-{
- eval $LOGFS
- local error_message=''
-
- # assemble the error message
- case $1 in
- 2) error_message="large flood danger, debug buffer full!"
- ;;
- 3) error_message="unsupported color scheme number: $2"
- ;;
- 4) error_message="unsupported verbosity level: $2"
- ;;
- 5) error_message="dependency not met: $2 not found in path.\nFor distribution installation package names and missing apps information, run: $SELF_NAME --recommends"
- ;;
- 6) error_message="/proc not found! Quitting..."
- ;;
- 7) error_message="One of the options you entered in your script parameters: $2\nis not supported.The option may require extra arguments to work.\nFor supported options (and their arguments), check the help menu: $SELF_NAME -h"
- ;;
- 8) error_message="the self-updater failed, $DOWNLOADER exited with error: $2.\nYou probably need to be root.\nHint, to make for easy updates without being root, do: chown <user name> $SELF_PATH/$SELF_NAME"
- ;;
- 9) error_message="unsupported debugging level: $2"
- ;;
- 10)
- error_message="the alt download url you provided: $2\nappears to be wrong, download aborted. Please note, the url\nneeds to end in /, without $SELF_NAME, like: http://yoursite.com/downloads/"
- ;;
- 11)
- error_message="unsupported testing option argument: -! $2"
- ;;
- 12)
- error_message="the git branch download url: $2\nappears to be empty currently. Make sure there is an actual source branch version\nactive before you try this again. Check https://github.com/smxi/inxi\nto verify the branch status."
- ;;
- 13)
- error_message="The -t option requires the following extra arguments (no spaces between letters/numbers):\nc m cm [required], for example: -t cm8 OR -t cm OR -t c9\n(numbers: 1-20, > 5 throttled to 5 in irc clients) You entered: $2"
- ;;
- 14)
- error_message="failed to write correctly downloaded $SELF_NAME to location $SELF_PATH.\nThis usually means you don't have permission to write to that location, maybe you need to be root?\nThe operation failed with error: $2"
- ;;
- 15)
- error_message="failed set execute permissions on $SELF_NAME at location $SELF_PATH.\nThis usually means you don't have permission to set permissions on files there, maybe you need to be root?\nThe operation failed with error: $2"
- ;;
- 16)
- error_message="$SELF_NAME downloaded but the file data is corrupted. Purged data and using current version."
- ;;
- 17)
- error_message="All $SELF_NAME self updater features have been disabled by the distribution\npackage maintainer. This includes the option you used: $2"
- ;;
- 18)
- error_message="The argument you provided for $2 does not have supported syntax.\nPlease use the following formatting:\n$3"
- ;;
- 19)
- error_message="The option $2 has been deprecated. Please use $3 instead.\nSee -h for instructions and syntax."
- ;;
- 20)
- error_message="The option you selected has been deprecated. $2\nSee the -h (help) menu for currently supported options."
- ;;
- 21)
- error_message="Width option requires an integer value of 80 or more.\nYou entered: $2"
- ;;
- *) error_message="error unknown: $@"
- set -- 99
- ;;
- esac
- # then print it and exit
- print_screen_output "Error $1: $error_message"
- eval $LOGFE
- exit $1
+sub error_handler {
+ my ( $err, $one, $two) = @_;
+ my ($b_recommends,$b_help,$errno) = (0,0,0);
+ my $message = do {
+ if ( $err eq 'empty' ) { 'empty value' }
+ ## Basic rules
+ elsif ( $err eq 'not-in-irc' ) {
+ $errno=1; "You can't run option $one in an IRC client!" }
+ ## Internal/external options
+ elsif ( $err eq 'bad-arg' ) {
+ $errno=10; $b_help=1; "Unsupported value: $two for option: $one" }
+ elsif ( $err eq 'bad-arg-int' ) {
+ $errno=11; "Bad internal argument: $one" }
+ elsif ( $err eq 'distro-block' ) {
+ $errno=20; "Option: $one has been disabled by the $self_name distribution maintainer." }
+ elsif ( $err eq 'option-feature-incomplete' ) {
+ $errno=21; "Option: '$one' feature: '$two' has not been implemented yet." }
+ elsif ( $err eq 'unknown-option' ) {
+ $errno=22; $b_help=1; "Unsupported option: $one" }
+ ## Data
+ elsif ( $err eq 'open-data' ) {
+ $errno=32; "Error opening data for reading: $one \nError: $two" }
+ elsif ( $err eq 'download-error' ) {
+ $errno=33; "Error downloading file with $dl{'dl'}: $one \nError: $two" }
+ ## Files:
+ elsif ( $err eq 'copy-failed' ) {
+ $errno=40; "Error copying file: $one \nError: $two" }
+ elsif ( $err eq 'create' ) {
+ $errno=41; "Error creating file: $one \nError: $two" }
+ elsif ( $err eq 'downloader-error' ) {
+ $errno=42; "Error downloading file: $one \nfor download source: $two" }
+ elsif ( $err eq 'file-corrupt' ) {
+ $errno=43; "Downloaded file is corrupted: $one" }
+ elsif ( $err eq 'mkdir' ) {
+ $errno=44; "Error creating directory: $one \nError: $two" }
+ elsif ( $err eq 'open' ) {
+ $errno=45; "Error opening file: $one \nError: $two" }
+ elsif ( $err eq 'open-dir' ) {
+ $errno=46; "Error opening directory: $one \nError: $two" }
+ elsif ( $err eq 'output-file-bad' ) {
+ $errno=47; "Value for --output-file must be full path, a writable directory, \nand include file name. Path: $two" }
+ elsif ( $err eq 'not-writable' ) {
+ $errno=48; "The file: $one is not writable!" }
+ elsif ( $err eq 'open-dir-failed' ) {
+ $errno=49; "The directory: $one failed to open with error: $two" }
+ elsif ( $err eq 'remove' ) {
+ $errno=50; "Failed to remove file: $one Error: $two" }
+ elsif ( $err eq 'rename' ) {
+ $errno=51; "There was an error moving files: $one\nError: $two" }
+ elsif ( $err eq 'write' ) {
+ $errno=52; "Failed writing file: $one - Error: $two!" }
+ ## Downloaders
+ elsif ( $err eq 'missing-downloader' ) {
+ $errno=60; "Downloader program $two could not be located on your system." }
+ elsif ( $err eq 'missing-perl-downloader' ) {
+ $errno=61; $b_recommends=1; "Perl downloader missing required module." }
+ ## FTP
+ elsif ( $err eq 'ftp-bad-path' ) {
+ $errno=70; "Unable to locate for FTP upload file:\n$one" }
+ elsif ( $err eq 'ftp-login' ) {
+ $errno=71; "There was an error with login to ftp server: $one" }
+ elsif ( $err eq 'ftp-upload' ) {
+ $errno=72; "There was an error with upload to ftp server: $one" }
+ ## Modules
+ elsif ( $err eq 'required-module' ) {
+ $errno=80; $b_recommends=1; "The required $one Perl module is not installed:\n$two" }
+ ## DEFAULT
+ else {
+ $errno=255; "Error handler ERROR!! Unsupported options: $err!"}
+ };
+ print_line("Error $errno: $message\n");
+ if ($b_help){
+ print_line("Check -h for correct parameters.\n");
+ }
+ if ($b_recommends){
+ print_line("See --recommends for more information.\n");
+ }
+ exit 0;
+}
+sub error_defaults {
+ my ($type,$one) = @_;
+ $one ||= '';
+ my %errors = (
+ 'download-error' => "Download Failure:\n$one\n",
+ );
+ return $errors{$type};
}
#### -------------------------------------------------------------------
-#### LOGGING
+#### RECOMMENDS
#### -------------------------------------------------------------------
-# called in the initial -@ 10 script args setting so we can get logging as soon as possible
-# will have max 3 files, inxi.log, inxi.1.log, inxi.2.log
-create_rotate_logfiles()
+## CheckRecommends
{
- # do the rotation if logfile exists
- if [[ -f $LOG_FILE ]];then
- # copy if present second to third
- if [[ -f $LOG_FILE_1 ]];then
- mv -f $LOG_FILE_1 $LOG_FILE_2
- fi
- # then copy initial to second
- mv -f $LOG_FILE $LOG_FILE_1
- fi
- # now create the logfile
- touch $LOG_FILE
- # and echo the start data
- echo "=========================================================" >> $LOG_FILE
- echo "START $SELF_NAME LOGGING:" >> $LOG_FILE
- echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )" >> $LOG_FILE
- echo "=========================================================" >> $LOG_FILE
+package CheckRecommends;
+sub run {
+ main::error_handler('not-in-irc', 'recommends') if $b_irc;
+ my (@data,@rows);
+ my $line = make_line();
+ my $pm = get_pm();
+ @data = basic_data($line);
+ push @rows,@data;
+ if (!$bsd_type){
+ @data = check_items('required system directories',$line,$pm);
+ push @rows,@data;
+ }
+ @data = check_items('recommended system programs',$line,$pm);
+ push @rows,@data;
+ @data = check_items('recommended display information programs',$line,$pm);
+ push @rows,@data;
+ @data = check_items('recommended downloader programs',$line,$pm);
+ push @rows,@data;
+ @data = check_items('recommended Perl modules',$line,$pm);
+ push @rows,@data;
+ @data = check_items('recommended directories',$line,'');
+ push @rows,@data;
+ @data = check_items('recommended files',$line,'');
+ push @rows,@data;
+ @data = (
+ ['0', '', '', "$line"],
+ ['0', '', '', "Ok, all done with the checks. Have a nice day."],
+ ['0', '', '', " "],
+ );
+ push @rows,@data;
+ #print Data::Dumper::Dumper \@rows;
+ main::print_basic(@rows);
+ exit 1;
}
-# NOTE: no logging available until get_parameters is run, since that's what sets logging
-# in order to trigger earlier logging manually set B_USE_LOGGING to true in top variables.
-# $1 alone: logs data; $2 with or without $3 logs func start/end.
-# $1 type (fs/fe/cat/raw) or logged data; [$2 is $FUNCNAME; [$3 - function args]]
-log_function_data()
-{
- if [ "$B_USE_LOGGING" == 'true' ];then
- local logged_data='' spacer=' ' line='----------------------------------------'
- case $1 in
- fs)
- logged_data="Function: $2 - Primary: Start"
- if [ -n "$3" ];then
- logged_data="$logged_data\n${spacer}Args: $3"
- fi
- spacer=''
- ;;
- fe)
- logged_data="Function: $2 - Primary: End"
- spacer=''
- ;;
- cat)
- if [[ $B_LOG_FULL_DATA == 'true' ]];then
- for cat_file in $2
- do
- logged_data="$logged_data\n$line\nFull file data: cat $cat_file\n\n$( cat $cat_file )\n$line\n"
- done
- spacer=''
- fi
- ;;
- raw)
- if [[ $B_LOG_FULL_DATA == 'true' ]];then
- logged_data="\n$line\nRaw system data:\n\n$2\n$line\n"
- spacer=''
- fi
- ;;
- *)
- logged_data="$1"
- ;;
- esac
- # Create any required line breaks and strip out escape color code, either ansi (case 1)or irc (case 2).
- # This pattern doesn't work for irc colors, if we need that someone can figure it out
- if [[ -n $logged_data ]];then
- if [[ $B_LOG_COLORS != 'true' ]];then
- echo -e "${spacer}$logged_data" | sed $SED_RX 's/\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m//g' >> $LOG_FILE
- else
- echo -e "${spacer}$logged_data" >> $LOG_FILE
- fi
- fi
- fi
+sub basic_data {
+ my ($line) = @_;
+ my (@data,@rows);
+ my $client = $client{'name-print'};
+ $client .= ' ' . $client{'version'} if $client{'version'};
+ my $default_shell = 'N/A';
+ if ($ENV{'SHELL'}){
+ $default_shell = $ENV{'SHELL'};
+ $default_shell =~ s/.*\///;
+ }
+ my $sh = main::check_program('sh');
+ my $sh_real = Cwd::abs_path($sh);
+ @rows = (
+ ['0', '', '', "$self_name will now begin checking for the programs it needs
+ to operate."],
+ ['0', '', '', "" ],
+ ['0', '', '', "Check $self_name --help or the man page (man $self_name)
+ to see what options are available." ],
+ ['0', '', '', "$line" ],
+ ['0', '', '', "Test: core tools:" ],
+ ['0', '', '', "" ],
+ ['0', '', '', "Perl version: ^$]" ],
+ ['0', '', '', "Current shell: " . $client ],
+ ['0', '', '', "Default shell: " . $default_shell ],
+ ['0', '', '', "sh links to: $sh_real" ],
+ );
+ return @rows;
+}
+sub check_items {
+ my ($type,$line,$pm) = @_;
+ my (@data,%info,@missing,$row,@rows,$result,@unreadable);
+ my ($b_dir,$b_file,$b_module,$b_program,$item);
+ my ($about,$extra,$extra2,$extra3,$extra4,$info_os,$install) = ('','','','','','info','');
+ if ($type eq 'required system directories'){
+ @data = qw(/proc /sys);
+ $b_dir = 1;
+ $item = 'Directory';
+ }
+ elsif ($type eq 'recommended system programs'){
+ if ($bsd_type){
+ @data = qw(camcontrol dig dmidecode fdisk file glabel gpart ifconfig ipmi-sensors
+ ipmitool lsusb sudo smartctl sysctl tree uptime usbdevs);
+ $info_os = 'info-bsd';
+ }
+ else {
+ @data = qw(dig dmidecode fdisk file hddtemp ifconfig ip ipmitool ipmi-sensors
+ lsblk lsusb modinfo runlevel sensors strings sudo tree uptime);
+ }
+ $b_program = 1;
+ $item = 'Program';
+ $extra2 = "Note: IPMI sensors are generally only found on servers. To access
+ that data, you only need one of the ipmi items.";
+ }
+ elsif ($type eq 'recommended display information programs'){
+ if ($bsd_type){
+ @data = qw(glxinfo wmctrl xdpyinfo xprop xrandr);
+ $info_os = 'info-bsd';
+ }
+ else {
+ @data = qw(glxinfo wmctrl xdpyinfo xprop xrandr);
+ }
+ $b_program = 1;
+ $item = 'Program';
+ }
+ elsif ($type eq 'recommended downloader programs'){
+ if ($bsd_type){
+ @data = qw(curl dig fetch ftp wget);
+ $info_os = 'info-bsd';
+ }
+ else {
+ @data = qw(curl dig wget);
+ }
+ $b_program = 1;
+ $extra = ' (You only need one of these)';
+ $extra2 = "Perl HTTP::Tiny is the default downloader tool if IO::Socket::SSL is present.
+ See --help --alt 40-44 options for how to override default downloader(s) in case of issues. ";
+ $extra3 = "If dig is installed, it is the default for WAN IP data.
+ Strongly recommended. Dig is fast and accurate.";
+ $extra4 = ". However, you really only need dig in most cases. All systems should have ";
+ $extra4 .= "at least one of the downloader options present.";
+ $item = 'Program';
+ }
+ elsif ($type eq 'recommended Perl modules'){
+ @data = qw(HTTP::Tiny IO::Socket::SSL Time::HiRes Cpanel::JSON::XS JSON::XS XML::Dumper);
+ $b_module = 1;
+ $item = 'Perl Module';
+ $extra = ' (Optional)';
+ $extra2 = "None of these are strictly required, but if you have them all, you can eliminate
+ some recommended non Perl programs from the install. ";
+ $extra3 = "HTTP::Tiny and IO::Socket::SSL must both be present to use as a downloader option.
+ For json export Cpanel::JSON::XS is preferred over JSON::XS.";
+ }
+ elsif ($type eq 'recommended directories'){
+ if ($bsd_type){
+ @data = qw(/dev);
+ }
+ else {
+ @data = qw(/dev /dev/disk/by-id /dev/disk/by-label /dev/disk/by-path
+ /dev/disk/by-uuid /sys/class/dmi/id);
+ }
+ $b_dir = 1;
+ $item = 'Directory';
+ }
+ elsif ($type eq 'recommended files'){
+ if ($bsd_type){
+ @data = qw(/var/run/dmesg.boot /var/log/Xorg.0.log);
+ }
+ else {
+ @data = qw(/etc/lsb-release /etc/os-release /proc/asound/cards
+ /proc/asound/version /proc/cpuinfo /proc/mdstat /proc/meminfo /proc/modules
+ /proc/mounts /proc/scsi/scsi /var/log/Xorg.0.log );
+ }
+ $b_file = 1;
+ $item = 'File';
+ $extra2 = "Note that not all of these are used by every system,
+ so if one is missing it's usually not a big deal.";
+ }
+ @rows = (
+ ['0', '', '', "$line" ],
+ ['0', '', '', "Test: $type$extra:" ],
+ ['0', '', '', " " ],
+ );
+ if ($extra2){
+ $rows[scalar @rows] = (['0', '', '', $extra2]);
+ $rows[scalar @rows] = (['0', '', '', ' ']);
+ }
+ if ($extra3){
+ $rows[scalar @rows] = (['0', '', '', $extra3]);
+ $rows[scalar @rows] = (['0', '', '', ' ']);
+ }
+ foreach (@data){
+ $install = '';
+ $about = '';
+ %info = item_data($_);
+ $about = $info{$info_os};
+ if ( ( $b_dir && -d $_ ) || ( $b_file && -r $_ ) ||
+ ($b_program && main::check_program($_) ) || ($b_module && main::check_module($_)) ){
+ $result = 'Present';
+ }
+ elsif ($b_file && -f $_){
+ $result = 'Unreadable';
+ push @unreadable, "$_";
+ }
+ else {
+ $result = 'Missing';
+ $install = " ~ Install package: $info{$pm}" if (($b_program || $b_module) && $pm);
+ push @missing, "$_$install";
+ }
+ $row = make_row($_,$about,$result);
+ $rows[scalar @rows] = (['0', '', '', $row]);
+ }
+ $rows[scalar @rows] = (['0', '', '', " "]);
+ if (@missing){
+ $rows[scalar @rows] = (['0', '', '', "The following $type are missing$extra4:"]);
+ foreach (@missing) {
+ $rows[scalar @rows] = (['0', '', '', "$item: $_"]);
+ }
+ }
+ if (@unreadable){
+ $rows[scalar @rows] = (['0', '', '', "The following $type are not readable: "]);
+ foreach (@unreadable) {
+ $rows[scalar @rows] = (['0', '', '', "$item: $_"]);
+ }
+ }
+ if (!@missing && !@unreadable){
+ $rows[scalar @rows] = (['0', '', '', "All $type are present"]);
+ }
+ return @rows;
+}
+
+sub item_data {
+ my ($type) = @_;
+ my %data = (
+ # directory data
+ '/sys/class/dmi/id' => ({
+ 'info' => '-M system, motherboard, bios',
+ }),
+ '/dev' => ({
+ 'info' => '-l,-u,-o,-p,-P,-D disk partition data',
+ }),
+ '/dev/disk/by-id' => ({
+ 'info' => '-D serial numbers',
+ }),
+ '/dev/disk/by-path' => ({
+ 'info' => '-D extra data',
+ }),
+ '/dev/disk/by-label' => ({
+ 'info' => '-l,-o,-p,-P partition labels',
+ }),
+ '/dev/disk/by-uuid' => ({
+ 'info' => '-u,-o,-p,-P partition uuid',
+ }),
+ '/proc' => ({
+ 'info' => '',
+ }),
+ '/sys' => ({
+ 'info' => '',
+ }),
+ # file data
+ '/etc/lsb-release' => ({
+ 'info' => '-S distro version data (older version)',
+ }),
+ '/etc/os-release' => ({
+ 'info' => '-S distro version data (newer version)',
+ }),
+ '/proc/asound/cards' => ({
+ 'info' => '-A sound card data',
+ }),
+ '/proc/asound/version' => ({
+ 'info' => '-A ALSA data',
+ }),
+ '/proc/cpuinfo' => ({
+ 'info' => '-C cpu data',
+ }),
+ '/proc/mdstat' => ({
+ 'info' => '-R mdraid data (if you use dm-raid)',
+ }),
+ '/proc/meminfo' => ({
+ 'info' => '-I,-tm, -m memory data',
+ }),
+ '/proc/modules' => ({
+ 'info' => '-G module data (sometimes)',
+ }),
+ '/proc/mounts' => ({
+ 'info' => '-P,-p partition advanced data',
+ }),
+ '/proc/scsi/scsi' => ({
+ 'info' => '-D Advanced hard disk data (used rarely)',
+ }),
+ '/var/log/Xorg.0.log' => ({
+ 'info' => '-G graphics driver load status',
+ }),
+ '/var/run/dmesg.boot' => ({
+ 'info' => '-D,-d disk data',
+ }),
+ # system tools
+ # apt-dpkg,apt-get; pm-arch,pacman; rpm-redhat,suse
+ 'curl' => ({
+ 'info' => '-i (if no dig); -w,-W; -U',
+ 'info-bsd' => '-i (if no dig); -w,-W; -U',
+ 'apt' => 'curl',
+ 'pacman' => 'curl',
+ 'rpm' => 'curl',
+ }),
+ 'camcontrol' => ({
+ 'info' => '',
+ 'info-bsd' => '-R; -D; -P. Get actual gptid /dev path',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ }),
+ 'dig' => ({
+ 'info' => '-i wlan IP',
+ 'info-bsd' => '-i wlan IP',
+ 'apt' => 'dnsutils',
+ 'pacman' => 'dnsutils',
+ 'rpm' => 'bind-utils',
+ }),
+ 'dmidecode' => ({
+ 'info' => '-M if no sys machine data; -m',
+ 'info-bsd' => '-M if null sysctl; -m; -B if null sysctl',
+ 'apt' => 'dmidecode',
+ 'pacman' => 'dmidecode',
+ 'rpm' => 'dmidecode',
+ }),
+ 'fdisk' => ({
+ 'info' => '-D partition scheme (fallback)',
+ 'info-bsd' => '-D partition scheme',
+ 'apt' => 'fdisk',
+ 'pacman' => 'util-linux',
+ 'rpm' => 'util-linux',
+ }),
+ 'fetch' => ({
+ 'info' => '',
+ 'info-bsd' => '-i (if no dig); -w,-W; -U',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ }),
+ 'file' => ({
+ 'info' => '-o unmounted file system (if no lsblk)',
+ 'info-bsd' => '-o unmounted file system',
+ 'apt' => 'file',
+ 'pacman' => 'file',
+ 'rpm' => 'file',
+ }),
+ 'ftp' => ({
+ 'info' => '',
+ 'info-bsd' => '-i (if no dig); -w,-W; -U',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ }),
+ 'glabel' => ({
+ 'info' => '',
+ 'info-bsd' => '-R; -D; -P. Get actual gptid /dev path',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ }),
+ 'gpart' => ({
+ 'info' => '',
+ 'info-bsd' => '-p,-P file system, size',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ }),
+ 'hciconfig' => ({
+ 'info' => 'Experimental',
+ 'info-bsd' => '',
+ 'apt' => 'bluez',
+ 'pacman' => 'bluez-utils',
+ 'rpm' => 'bluez-utils',
+ }),
+ 'hddtemp' => ({
+ 'info' => '-Dx show hdd temp',
+ 'info-bsd' => '-Dx show hdd temp',
+ 'apt' => 'hddtemp',
+ 'pacman' => 'hddtemp',
+ 'rpm' => 'hddtemp',
+ }),
+ 'ifconfig' => ({
+ 'info' => '-i ip LAN (deprecated)',
+ 'info-bsd' => '-i ip LAN',
+ 'apt' => 'net-tools',
+ 'pacman' => 'net-tools',
+ 'rpm' => 'net-tools',
+ }),
+ 'ip' => ({
+ 'info' => '-i ip LAN',
+ 'info-bsd' => '',
+ 'apt' => 'iproute',
+ 'pacman' => 'iproute2',
+ 'rpm' => 'iproute',
+ }),
+ 'ipmi-sensors' => ({
+ 'info' => '-s IPMI sensors (servers)',
+ 'info-bsd' => '',
+ 'apt' => 'freeipmi-tools',
+ 'pacman' => 'freeipmi',
+ 'rpm' => 'freeipmi',
+ }),
+ 'ipmitool' => ({
+ 'info' => '-s IPMI sensors (servers)',
+ 'info-bsd' => '-s IPMI sensors (servers)',
+ 'apt' => 'ipmitool',
+ 'pacman' => 'ipmitool',
+ 'rpm' => 'ipmitool',
+ }),
+ 'lsblk' => ({
+ 'info' => '-o unmounted file system (best option)',
+ 'info-bsd' => '-o unmounted file system',
+ 'apt' => 'util-linux',
+ 'pacman' => 'util-linux',
+ 'rpm' => 'util-linux-ng',
+ }),
+ 'lsusb' => ({
+ 'info' => '-A usb audio; -N usb networking; --usb',
+ 'info-bsd' => '-A; -N; --usb. Alternate to usbdevs',
+ 'apt' => 'usbutils',
+ 'pacman' => 'usbutils',
+ 'rpm' => 'usbutils',
+ }),
+ 'modinfo' => ({
+ 'info' => 'Ax; -Nx module version',
+ 'info-bsd' => '',
+ 'apt' => 'module-init-tools',
+ 'pacman' => 'module-init-tools',
+ 'rpm' => 'module-init-tools',
+ }),
+ 'runlevel' => ({
+ 'info' => '-I fallback to Perl',
+ 'info-bsd' => '',
+ 'apt' => 'systemd or sysvinit',
+ 'pacman' => 'systemd',
+ 'rpm' => 'systemd or sysvinit',
+ }),
+ 'sensors' => ({
+ 'info' => '-s sensors output',
+ 'info-bsd' => '',
+ 'apt' => 'lm-sensors',
+ 'pacman' => 'lm-sensors',
+ 'rpm' => 'lm-sensors',
+ }),
+ 'smartctl' => ({
+ 'info' => '-Dx show hdd temp',
+ 'info-bsd' => '-Dx show hdd temp',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ }),
+ 'strings' => ({
+ 'info' => '-I sysvinit version',
+ 'info-bsd' => '',
+ 'apt' => 'binutils',
+ 'pacman' => '?',
+ 'rpm' => '?',
+ }),
+ 'sysctl' => ({
+ 'info' => '',
+ 'info-bsd' => '-C; -I; -m; -tm',
+ 'apt' => '?',
+ 'pacman' => '?',
+ 'rpm' => '?',
+ }),
+ 'sudo' => ({
+ 'info' => '-Dx hddtemp-user; -o file-user',
+ 'info-bsd' => '-Dx hddtemp-user; -o file-user',
+ 'apt' => 'sudo',
+ 'pacman' => 'sudo',
+ 'rpm' => 'sudo',
+ }),
+ 'tree' => ({
+ 'info' => '--debugger 20,21 /sys tree',
+ 'info-bsd' => '--debugger 20,21 /sys tree',
+ 'apt' => 'tree',
+ 'pacman' => 'tree',
+ 'rpm' => 'tree',
+ }),
+ 'uptime' => ({
+ 'info' => '-I uptime',
+ 'info-bsd' => '-I uptime',
+ 'apt' => 'procps',
+ 'pacman' => 'procps',
+ 'rpm' => 'procps',
+ }),
+ 'usbdevs' => ({
+ 'info' => '',
+ 'info-bsd' => '-A; -N; --usb;',
+ 'apt' => 'usbutils',
+ 'pacman' => 'usbutils',
+ 'rpm' => 'usbutils',
+ }),
+ 'wget' => ({
+ 'info' => '-i (if no dig); -w,-W; -U',
+ 'info-bsd' => '-i (if no dig); -w,-W; -U',
+ 'apt' => 'wget',
+ 'pacman' => 'wget',
+ 'rpm' => 'wget',
+ }),
+ # display tools
+ 'glxinfo' => ({
+ 'info' => '-G glx info',
+ 'info-bsd' => '-G glx info',
+ 'apt' => 'mesa-utils',
+ 'pacman' => 'mesa-demos',
+ 'rpm' => 'glx-utils (openSUSE 12.3 and later Mesa-demo-x)',
+ }),
+ 'wmctrl' => ({
+ 'info' => '-S active window manager (not all wm)',
+ 'info-bsd' => '-S active window managerr (not all wm)',
+ 'apt' => 'wmctrl',
+ 'pacman' => 'wmctrl',
+ 'rpm' => 'wmctrl',
+ }),
+ 'xdpyinfo' => ({
+ 'info' => '-G multi screen resolution',
+ 'info-bsd' => '-G multi screen resolution',
+ 'apt' => 'X11-utils',
+ 'pacman' => 'xorg-xdpyinfo',
+ 'rpm' => 'xorg-x11-utils',
+ }),
+ 'xprop' => ({
+ 'info' => '-S desktop data',
+ 'info-bsd' => '-S desktop data',
+ 'apt' => 'X11-utils',
+ 'pacman' => 'xorg-xprop',
+ 'rpm' => 'x11-utils',
+ }),
+ 'xrandr' => ({
+ 'info' => '-G single screen resolution',
+ 'info-bsd' => '-G single screen resolution',
+ 'apt' => 'x11-xserver-utils',
+ 'pacman' => 'xrandr',
+ 'rpm' => 'x11-server-utils',
+ }),
+ # Perl modules
+ 'Cpanel::JSON::XS' => ({
+ 'info' => '--output json - required for export.',
+ 'info-bsd' => '--output json - required for export.',
+ 'apt' => 'libcpanel-json-xs-perl',
+ 'pacman' => 'perl-cpanel-json-xs',
+ 'rpm' => 'perl-Cpanel-JSON-XS',
+ }),
+ 'HTTP::Tiny' => ({
+ 'info' => '-U; -w,-W; -i (if dig not installed).',
+ 'info-bsd' => '-U; -w,-W; -i (if dig not installed)',
+ 'apt' => 'libhttp-tiny-perl',
+ 'pacman' => 'Core Modules',
+ 'rpm' => 'Perl-http-tiny',
+ }),
+ 'IO::Socket::SSL' => ({
+ 'info' => '-U; -w,-W; -i (if dig not installed).',
+ 'info-bsd' => '-U; -w,-W; -i (if dig not installed)',
+ 'apt' => 'libio-socket-ssl-perl',
+ 'pacman' => 'perl-io-socket-ssl',
+ 'rpm' => 'perl-IO-Socket-SSL',
+ }),
+ 'JSON::XS' => ({
+ 'info' => '--output json - required for export (legacy).',
+ 'info-bsd' => '--output json - required for export (legacy).',
+ 'apt' => 'libjson-xs-perl',
+ 'pacman' => 'perl-json-xs',
+ 'rpm' => 'perl-JSON-XS',
+ }),
+ 'Time::HiRes' => ({
+ 'info' => '-C cpu sleep (not required); --debug timers',
+ 'info-bsd' => '-C cpu sleep (not required); --debug timers',
+ 'apt' => 'Core Modules',
+ 'pacman' => 'Core Modules',
+ 'rpm' => 'perl-Time-HiRes',
+ }),
+ 'XML::Dumper' => ({
+ 'info' => '--output xml - Crude and raw.',
+ 'info-bsd' => '--output xml - Crude and raw.',
+ 'apt' => 'libxml-dumper-perl',
+ 'pacman' => 'perl-xml-dumper',
+ 'rpm' => 'perl-XML-Dumper',
+ }),
+ );
+ my $ref = $data{$type};
+ my %values = %$ref;
+ return %values;
+}
+sub get_pm {
+ my ($pm) = ('');
+ if (main::check_program('dpkg')){
+ $pm = 'apt';
+ }
+ elsif (main::check_program('pacman')){
+ $pm = 'pacman';
+ }
+ elsif (main::check_program('rpm')){
+ $pm = 'rpm';
+ }
+ return $pm;
+}
+# note: end will vary, but should always be treated as longest value possible.
+# expected values: Present/Missing
+sub make_row {
+ my ($start,$middle,$end) = @_;
+ my ($dots,$line,$sep) = ('','',': ');
+ foreach (0 .. ($size{'max'} - 16 - length("$start$middle"))){
+ $dots .= '.';
+ }
+ $line = "$start$sep$middle$dots $end";
+ return $line;
+}
+sub make_line {
+ my $line = '';
+ foreach (0 .. $size{'max'} - 2 ){
+ $line .= '-';
+ }
+ return $line;
+}
}
#### -------------------------------------------------------------------
-#### RECOMMENDS
+#### TOOLS
#### -------------------------------------------------------------------
-check_recommends_user_output()
-{
- local Line=$LINE1
- local gawk_version='N/A' sed_version='N/A' sudo_version='N/A' python_version='N/A'
- local perl_version='N/A'
-
- if [[ $B_IRC == 'true' ]];then
- print_screen_output "Sorry, you can't run this option in an IRC client."
- exit 1
- fi
- initialize_paths
- print_lines_basic "0" "" "$SELF_NAME will now begin checking for the programs it needs to operate. First a check of the main languages and tools $SELF_NAME uses. Python is only for debugging data uploads unless Perl is missing."
- echo $Line
- echo "Bash version: $( bash --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU bash/ {print $4}' )"
- if type -p gawk &>/dev/null;then
- gawk_version=$( gawk --version 2>&1 | gawk 'BEGIN {IGNORECASE=1} /^GNU Awk/ {print $3}' )
- fi
- if type -p sed &>/dev/null;then
- # sed (GNU sed) 4.4 OR GNU sed version 4.4
- sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^(GNU sed version|sed)/ {print $4;exit}' )
- if [[ -z $sed_version ]];then
- # note: bsd sed shows error with --version flag
- sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^sed: illegal option/ {print "BSD sed";exit}' )
- fi
- fi
- if type -p sudo &>/dev/null;then
- sudo_version=$( sudo -V 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Sudo version/ {print $3}' )
- fi
- if type -p python &>/dev/null;then
- python_version=$( python --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Python/ {print $2}' )
- fi
- # NOTE: does not actually handle 5/6 version, but ok for now
- if type -p perl &>/dev/null;then
- perl_version=$(perl --version | grep -m 1 -oE 'v[0-9.]+')
- fi
- echo "Gawk version: $gawk_version"
- echo "Sed version: $sed_version"
- echo "Sudo version: $sudo_version"
- echo "Python version: $python_version (legacy, no longer used)"
- echo "Perl version: $perl_version"
- echo $Line
-
- echo "Test One: Required System Directories (Linux Only)."
- print_lines_basic "0" "" "If one of these system directories is missing, $SELF_NAME cannot operate:"
- echo
- check_recommends_items 'required-dirs'
-
- echo "Test Two: Required Core Applications."
- print_lines_basic "0" "" "If one of these applications is missing, $SELF_NAME cannot operate:"
- echo
- check_recommends_items 'required-apps'
-
- print_lines_basic "0" "" "Test Three: Script Recommends for Graphics Features."
- print_lines_basic "0" "" "NOTE: If you do not use X these do not matter (like a headless server). Otherwise, if one of these applications is missing, $SELF_NAME will have incomplete output:"
- echo
- check_recommends_items 'recommended-x-apps'
-
- echo 'Test Four: Script Recommends for Remaining Features.'
- print_lines_basic "0" "" "If one of these applications is missing, $SELF_NAME will have incomplete output:"
- echo
- check_recommends_items 'recommended-apps'
-
- echo 'Test Five: Script Recommends for Remaining Features.'
- print_lines_basic "0" "" "One of these downloaders needed for options -i/-w/-W (-U/-! [11-15], if supported):"
- echo
- check_recommends_items 'downloaders'
-
- echo 'Test Six: System Directories for Various Information.'
- echo '(Unless otherwise noted, these are for GNU/Linux systems)'
- print_lines_basic "0" "" "If one of these directories is missing, $SELF_NAME may have incomplete output:"
- echo
- check_recommends_items 'system-dirs'
-
- echo 'Test Seven: System Files for Various Information.'
- echo '(Unless otherwise noted, these are for GNU/Linux systems)'
- print_lines_basic "0" "" "If one of these files is missing, $SELF_NAME may have incomplete output:"
- echo
- check_recommends_items 'system-files'
-
- echo 'All tests completed.'
+# Duplicates the functionality of awk to allow for one liner
+# type data parsing. note: -1 corresponds to awk NF
+# args 1: array of data; 2: search term; 3: field result; 4: separator
+# correpsonds to: awk -F='separator' '/search/ {print $2}' <<< @data
+# array is sent by reference so it must be dereferenced
+# NOTE: if you just want the first row, pass it \S as search string
+# NOTE: if $num is undefined, it will skip the second step
+sub awk {
+ eval $start if $b_log;
+ my ($ref,$search,$num,$sep) = @_;
+ my ($result);
+ # print "search: $search\n";
+ return if ! @$ref || ! $search;
+ foreach (@$ref){
+ if (/$search/i){
+ $result = $_;
+ $result =~ s/^\s+|\s+$//g;
+ last;
+ }
+ }
+ if ($result && defined $num){
+ $sep ||= '\s+';
+ $num-- if $num > 0; # retain the negative values as is
+ $result = (split /$sep/, $result)[$num];
+ $result =~ s/^\s+|,|\s+$//g if $result;
+ }
+ eval $end if $b_log;
+ return $result;
+}
+# $1 - Perl module to check
+sub check_module {
+ my ($module) = @_;
+ my $b_present = 0;
+ eval "require $module";
+ $b_present = 1 if !$@;
+ return $b_present;
+}
+# arg: 1 - string or path to search gneerated @paths data for.
+# note: a few nano seconds are saved by using raw $_[0] for program
+sub check_program {
+ (grep { return "$_/$_[0]" if -e "$_/$_[0]"} @paths)[0];
}
-# Should come after above for debugging tests
-# args: $1 - check item
-check_recommends_items()
-{
- local item='' item_list='' item_string='' missing_items='' missing_string=''
- local package='' application='' feature='' type='' starter='' finisher=''
- local package_deb='' package_pacman='' package_rpm='' downloaders_bsd=''
- local print_string='' separator='' width=56
- local required_dirs='/proc /sys'
-
- if [[ -n $BSD_TYPE ]];then
- downloaders_bsd='fetch:BSD-only~BSD-only~BSD-only~:-i_wan_ip;-w/-W;-U/-!_[11-15]_[OR]
- ftp:ftp-OpenBSD-only~ftp-OpenBSD-only~ftp-OpenBSD-only~:-i_wan_ip;-w/-W;-U/-!_[11-15]_[OR]'
- fi
- # package-owner: 1 - debian/ubuntu; 2 - arch; 3 - yum/rpm
- # pardus: pisi sf -q /usr/bin/package
- # https://wiki.archlinux.org/index.php/Perl_Policy
- # https://www.debian.org/doc/packaging-manuals/perl-policy/index.html
- local required_apps='
- df:coreutils~coreutils~coreutils~:partition_data
- gawk:gawk~gawk~gawk~:core_tool
- grep:grep~grep~grep~:string_search
- perl:perl~perl~perl~:debugger_uploader;_debugger_/sys_traverse
- lspci:pciutils~pciutils~pciutils~:hardware_data
- ps:procps~procps~procps~:process_data
- readlink:coreutils~coreutils~coreutils~:
- sed:sed~sed~sed~:string_replace
- tr:coreutils~coreutils~coreutils~:character_replace
- uname:uname~coreutils~coreutils~:kernel_data
- wc:coreutils~coreutils~coreutils~:word_character_count
- '
- local x_recommends='
- glxinfo:mesa-utils~mesa-demos~glx-utils_(openSUSE_12.3_and_later_Mesa-demo-x)~:-G_glx_info
- xdpyinfo:X11-utils~xorg-xdpyinfo~xorg-x11-utils~:-G_multi_screen_resolution
- xprop:X11-utils~xorg-xprop~x11-utils~:-S_desktop_data
- xrandr:x11-xserver-utils~xrandr~x11-server-utils~:-G_single_screen_resolution
- '
- local recommended_apps='
- dig:dnsutils~dnsutils~bind-utils:-i_wlan_IP_(Default)
- dmidecode:dmidecode~dmidecode~dmidecode~:-M_if_no_sys_machine_data;_-m_memory
- file:file~file~file~:-o_unmounted_file_system
- hciconfig:bluez~bluez-utils~bluez-utils~:-n_-i_bluetooth_data-dev_only-not_used
- hddtemp:hddtemp~hddtemp~hddtemp~:-Dx_show_hdd_temp
- ifconfig:net-tools~net-tools~net-tools~:-i_ip_lan-deprecated
- ip:iproute~iproute2~iproute~:-i_ip_lan
- sensors:lm-sensors~lm_sensors~lm-sensors~:-s_sensors_output
- strings:binutils~~~:-I_sysvinit_version
- lsusb:usbutils~usbutils~usbutils~:-A_usb_audio;-N_usb_networking
- modinfo:module-init-tools~module-init-tools~module-init-tools~:-Ax,-Nx_module_version
- runlevel:sysvinit~sysvinit~systemd~:-I_runlevel
- sudo:sudo~sudo~sudo~:-Dx_hddtemp-user;-o_file-user
- tree:tree~tree~tree~:-@1[1-5]_debugger_sys_tree
- uptime:procps~procps~procps~:-I_uptime_(check_which_package_owns_Debian)
- '
-
- local downloaders="
- curl:curl~curl~curl~:-i_wan_ip;-w/-W;-U/-!_[11-15]_[Default|OR]
- wget:wget~wget~wget~:-i_wan_ip;-w/-W;-U/-!_[11-15]_[OR]
- $downloaders_bsd
- perl:perl~perl~perl~:-i_wan_ip;-w/-W;-U/-!_[11-15]_[Module_HTTP::Tiny]
- "
- local recommended_dirs='
- /sys/class/dmi/id:-M_system,_motherboard,_bios
- /dev:-l,-u,-o,-p,-P,-D_disk_partition_data
- /dev/disk/by-label:-l,-o,-p,-P_partition_labels
- /dev/disk/by-uuid:-u,-o,-p,-P_partition_uuid
- '
- local recommended_files="
- $FILE_ASOUND_DEVICE:-A_sound_card_data
- $FILE_ASOUND_VERSION:-A_ALSA_data
- $FILE_CPUINFO:-C_cpu_data
- $FILE_LSB_RELEASE:-S_distro_version_data_[deprecated]
- $FILE_MDSTAT:-R_mdraid_data
- $FILE_MEMINFO:-I_memory_data
- $FILE_OS_RELEASE:-S_distro_version_data
- $FILE_PARTITIONS:-p,-P_partitions_data
- $FILE_MODULES:-G_module_data
- $FILE_MOUNTS:-P,-p_partition_advanced_data
- $FILE_DMESG_BOOT:-D,-d_disk_data_[BSD_only]
- $FILE_SCSI:-D_Advanced_hard_disk_data_[used_rarely]
- $FILE_XORG_LOG:-G_graphics_driver_load_status
- "
- if [[ -n $COLS_INNER ]];then
- if [[ $COLS_INNER -ge 90 ]];then
- width=${#LINE1} # match width of $LINE1
- elif [[ $COLS_INNER -ge 78 ]];then
- width=$(( $COLS_INNER - 11 ))
- fi
- fi
- case $1 in
- downloaders)
- item_list=$downloaders
- item_string='Downloaders'
- item_string=''
- missing_string='downloaders, and their corresponding packages,'
- type='applications'
- ;;
- required-dirs)
- item_list=$required_dirs
- item_string='Required file system'
- item_string=''
- missing_string='system directories'
- type='directories'
- ;;
- required-apps)
- item_list=$required_apps
- item_string='Required application'
- item_string=''
- missing_string='applications, and their corresponding packages,'
- type='applications'
- ;;
- recommended-x-apps)
- item_list=$x_recommends
- item_string='Recommended X application'
- item_string=''
- missing_string='applications, and their corresponding packages,'
- type='applications'
- ;;
- recommended-apps)
- item_list=$recommended_apps
- item_string='Recommended application'
- item_string=''
- missing_string='applications, and their corresponding packages,'
- type='applications'
- ;;
- system-dirs)
- item_list=$recommended_dirs
- item_string='System directory'
- item_string=''
- missing_string='system directories'
- type='directories'
- ;;
- system-files)
- item_list=$recommended_files
- item_string='System file'
- item_string=''
- missing_string='system files'
- type='files'
- ;;
- esac
- # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
- # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
- # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
- # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
-
- for item in $item_list
- do
- if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 0 ]];then
- application=$item
- package=''
- feature=''
- location=''
- elif [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 1 ]];then
- application=$( cut -d ':' -f 1 <<< $item )
- package=''
- feature=$( cut -d ':' -f 2 <<< $item )
- location=''
- else
- application=$( cut -d ':' -f 1 <<< $item )
- package=$( cut -d ':' -f 2 <<< $item )
- location=$( type -p $application )
- if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -ge 2 ]];then
- feature=$( cut -d ':' -f 3-6 <<< $item )
- else
- feature=''
- fi
- fi
- if [[ -n $feature ]];then
- print_string="$item_string$application (info: $( sed 's/_/ /g' <<< $feature ))"
- else
- print_string="$item_string$application"
- fi
-
- starter="$( sed -e :a -e 's/^.\{1,'$width'\}$/&./;ta' <<< $print_string )"
- if [[ -z $( grep '^/' <<< $application ) && -n $location ]] || [[ -d $application || -f $application ]];then
- if [[ -n $location ]];then
- finisher=" $location"
- else
- finisher=" Present"
- fi
- else
- finisher=" Missing"
- missing_items="$missing_items$separator$application:$package"
- separator=' '
- fi
-
- echo "$starter$finisher"
- done
- echo
- if [[ -n $missing_items ]];then
- echo "The following $type are missing from your system:"
- for item in $missing_items
- do
- application=$( cut -d ':' -f 1 <<< $item )
- if [[ $type == 'applications' ]];then
- echo
- package=$( cut -d ':' -f 2 <<< $item )
- package_deb=$( cut -d '~' -f 1 <<< $package )
- package_pacman=$( cut -d '~' -f 2 <<< $package )
- package_rpm=$( cut -d '~' -f 3 <<< $package )
- echo "Application: $application"
- print_lines_basic "0" "" "To add to your system, install the proper distribution package for your system:"
- print_lines_basic "0" "" "Debian/Ubuntu:^$package_deb^:: Arch Linux:^$package_pacman^:: Redhat/Fedora/Suse:^$package_rpm"
- elif [[ $type == 'directories' ]];then
- echo "Directory: $application"
- elif [[ $type == 'files' ]];then
- echo "File: $application"
- fi
- done
- if [[ $item_string == 'System directory' ]];then
- print_lines_basic "0" "" "These directories are created by the kernel, so don't worry if they are not present."
- fi
- else
- echo "All the $( cut -d ' ' -f 1 <<< $item_string | sed -e 's/Re/re/' -e 's/Sy/sy/' ) $type are present."
- fi
- echo $Line
+sub cleanup {
+ # maybe add in future: , $fh_c, $fh_j, $fh_x
+ foreach my $fh ($fh_l){
+ if ($fh){
+ close $fh;
+ }
+ }
}
-#### -------------------------------------------------------------------
-#### UPDATER
-#### -------------------------------------------------------------------
+# returns count of files in directory, if 0, dir is empty
+sub count_dir_files {
+ return unless -d $_[0];
+ opendir my $dh, $_[0] or error_handler('open-dir-failed', "$_[0]", $!);
+ my $count = grep { ! /^\.{1,2}/ } readdir $dh; # strips out . and ..
+ return $count;
+}
-# args: $1 - download url, not including file name; $2 - string to print out
-# $3 - update type option
-# note that $1 must end in / to properly construct the url path
-self_updater()
-{
- eval $LOGFS
- set_downloader
- local downloader_error=0 file_contents='' downloader_man_error=0
- local man_file_location=$( set_man_location )
- local man_file_path="$man_file_location/inxi.1.gz"
-
- if [[ $B_IRC == 'true' ]];then
- print_screen_output "Sorry, you can't run the $SELF_NAME self updater option (-$3) in an IRC client."
- exit 1
- fi
- print_screen_output "Starting $SELF_NAME self updater."
- print_screen_output "Currently running $SELF_NAME version number: $SELF_VERSION"
- print_screen_output "Current version patch number: $SELF_PATCH"
- print_screen_output "Current version release date: $SELF_DATE"
- print_screen_output "Updating $SELF_NAME in $SELF_PATH using $2 as download source..."
- case $DOWNLOADER in
- curl)
- file_contents="$( curl $NO_SSL_OPT -L -s $1$SELF_NAME )" || downloader_error=$?
- ;;
- fetch)
- file_contents="$( fetch $NO_SSL_OPT -q -o - $1$SELF_NAME )" || downloader_error=$?
- ;;
- ftp)
- file_contents="$( ftp $NO_SSL_OPT -o - $1$SELF_NAME 2>/dev/null )" || downloader_error=$?
- ;;
- perl)
- file_contents="$( download_file 'stdout' $1$SELF_NAME )" || downloader_error=$?
- ;;
- wget)
- file_contents="$( wget $NO_SSL_OPT -q -O - $1$SELF_NAME )" || downloader_error=$?
- ;;
- no-downloader)
- downloader_error=1
- ;;
- esac
+# args: 1 - the string to get piece of
+# 2 - the position in string, starting at 1 for 0 index.
+# 3 - the separator, default is ' '
+sub get_piece {
+ eval $start if $b_log;
+ my ($string, $num, $sep) = @_;
+ $num--;
+ $sep ||= '\s+';
+ $string =~ s/^\s+|\s+$//g;
+ my @temp = split(/$sep/, $string);
+ eval $end if $b_log;
+ if ( exists $temp[$num] ){
+ $temp[$num] =~ s/,//g;
+ return $temp[$num];
+ }
+}
- # then do the actual download
- if [[ $downloader_error -eq 0 ]];then
- # make sure the whole file got downloaded and is in the variable
- if [[ -n $( grep '###\*\*EOF\*\*###' <<< "$file_contents" ) ]];then
- echo "$file_contents" > $SELF_PATH/$SELF_NAME || error_handler 14 "$?"
- chmod +x $SELF_PATH/$SELF_NAME || error_handler 15 "$?"
- parse_version_data 'main'
- parse_version_data 'patch'
- parse_version_data 'date'
- print_screen_output "Successfully updated to $2 version: $SELF_VERSION"
- print_screen_output "New $2 version patch number: $SELF_PATCH"
- print_screen_output "New $2 version release date: $SELF_DATE"
- print_screen_output "To run the new version, just start $SELF_NAME again."
- print_screen_output "----------------------------------------"
- print_screen_output "Starting download of man page file now."
- if [[ $B_MAN == 'false' ]];then
- print_screen_output "Skipping man download because branch version is being used."
- elif [[ ! -d $man_file_location ]];then
- print_screen_output "The required man directory was not detected on your system, unable to continue: $man_file_location"
- else
- if [[ $B_ROOT == 'true' ]];then
- print_screen_output "Checking Man page download URL..."
- if [[ -f /usr/share/man/man8/inxi.8.gz ]];then
- print_screen_output "Updating man page location to man1."
- mv -f /usr/share/man/man8/inxi.8.gz $man_file_location/inxi.1.gz
- if type -p mandb &>/dev/null;then
- exec $( type -p mandb ) -q
- fi
- fi
- case $DOWNLOADER in
- perl)
- download_file 'spider' $MAN_FILE_DOWNLOAD || downloader_man_error=$?
- ;;
- wget)
- wget $NO_SSL_OPT -q --spider $MAN_FILE_DOWNLOAD || downloader_man_error=$?
- ;;
- esac
- if [[ $downloader_man_error -eq 0 ]];then
- if [[ $DOWNLOADER == 'wget' ]];then
- print_screen_output "Man file download URL verified: $MAN_FILE_DOWNLOAD"
- fi
- print_screen_output "Downloading Man page file now."
- case $DOWNLOADER in
- curl)
- curl $NO_SSL_OPT -L -s -o $man_file_path $MAN_FILE_DOWNLOAD || downloader_man_error=$?
- ;;
- fetch)
- fetch $NO_SSL_OPT -q -o $man_file_path $MAN_FILE_DOWNLOAD || downloader_man_error=$?
- ;;
- ftp)
- ftp $NO_SSL_OPT -o $man_file_path $MAN_FILE_DOWNLOAD 2>/dev/null || downloader_man_error=$?
- ;;
- perl)
- download_file 'file' $MAN_FILE_DOWNLOAD $man_file_path || downloader_man_error=$?
- ;;
- wget)
- wget $NO_SSL_OPT -q -O $man_file_path $MAN_FILE_DOWNLOAD || downloader_man_error=$?
- ;;
- no-downloader)
- downloader_man_error=1
- ;;
- esac
- if [[ $downloader_man_error -gt 0 ]];then
- print_screen_output "Oh no! Something went wrong downloading the Man gz file at: $MAN_FILE_DOWNLOAD"
- print_screen_output "Check the error messages for what happened. Error: $downloader_man_error"
- else
- print_screen_output "Download/install of man page successful. Check to make sure it works: man inxi"
- fi
- else
- print_screen_output "Man file download URL failed, unable to continue: $MAN_FILE_DOWNLOAD"
- fi
- else
- print_screen_output "Updating / Installing the Man page requires root user, writing to: $man_file_location"
- print_screen_output "If you want the man page, you'll have to run $SELF_NAME -$3 as root."
- fi
- fi
- exit 0
- else
- error_handler 16
- fi
- # now run the error handlers on any wget failure
- else
- if [[ $2 == 'source server' ]];then
- error_handler 8 "$downloader_error"
- elif [[ $2 == 'alt server' ]];then
- error_handler 10 "$1"
- else
- error_handler 12 "$1"
- fi
- fi
- eval $LOGFS
-}
-
-set_man_location()
-{
- local location='' default_location='/usr/share/man/man1'
- local man_paths=$(man --path 2>/dev/null) man_local='/usr/local/share/man'
- local b_use_local=false
-
- if [[ -n "$man_paths" && -n $( grep $man_local <<< "$man_paths" ) ]];then
- b_use_local=true
- fi
-
- # for distro installs, existing inxi man manual installs, do nothing
- if [[ -f $default_location/inxi.1.gz ]];then
- location=$default_location
- else
- if [[ $b_use_local == 'true' ]];then
- if [[ ! -d $man_local/man1 ]];then
- mkdir $man_local/man1
- fi
- location="$man_local/man1"
- fi
-# print_screen_output "Updating man page location to man1."
-# mv -f /usr/share/man/man1/inxi.1.gz /usr/local/share/man/man1/inxi.1.gz
-# if type -p mandb &>/dev/null;then
-# exec $( type -p mandb ) -q
-# fi
- fi
-
- if [[ -z "$location" ]];then
- location=$default_location
- fi
-
- echo $location
+# arg: 1 - command to turn into an array; 2 - optional: splitter
+# 3 - optionsl, strip and clean data
+# similar to reader() except this creates an array of data
+# by lines from the command arg
+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;
+ }
+ eval $end if $b_log;
+ return @rows;
}
-########################################################################
-#### OUTPUT
-########################################################################
+# args: 1 - string value to glob
+sub globber {
+ eval $start if $b_log;
+ my @files = <$_[0]>;
+ eval $end if $b_log;
+ return @files;
+}
+# gets array ref, which may be undefined, plus join string
+# this helps avoid debugger print errors when we are printing arrays
+# which we don't know are defined or not null.
+# args: 1 - array ref; 2 - join string; 3 - default value, optional
+sub joiner {
+ my ($ref,$join,$default) = @_;
+ my @arr = @$ref;
+ $default ||= '';
+ my $string = '';
+ foreach (@arr){
+ if (defined $_){
+ $string .= $_ . $join;
+ }
+ else {
+ $string .= $default . $join;
+ }
+ }
+ return $string;
+}
-#### -------------------------------------------------------------------
-#### FILTERS
-#### -------------------------------------------------------------------
+# returns array of:
+# 0 - match string; 1 - search number; 2 - version string; 3 - Print name
+# 4 - console 0/1; 5 - 0/1 exit version loop at first iteration;
+# 6 - 0/1 write to stderr
+# arg: 1 - program lower case name
+sub program_values {
+ my ($app) = @_;
+ my (@client_data);
+ my %data = (
+ ## Clients
+ 'bitchx' => ['bitchx',2,'','BitchX',1,0,0],# special
+ 'finch' => ['finch',2,'-v','Finch',1,1,0],
+ 'gaim' => ['[0-9.]+',2,'-v','Gaim',0,1,0],
+ 'ircii' => ['[0-9.]+',3,'-v','ircII',1,1,0],
+ 'irssi' => ['irssi',2,'-v','Irssi',1,1,0],
+ 'irssi-text' => ['irssi',2,'-v','Irssi',1,1,0],
+ 'konversation' => ['konversation',2,'-v','Konversation',0,0,0],
+ 'kopete' => ['Kopete',2,'-v','Kopete',0,0,0],
+ 'kvirc' => ['[0-9.]+',2,'-v','KVIrc',0,0,1], # special
+ 'pidgin' => ['[0-9.]+',2,'-v','Pidgin',0,1,0],
+ 'quassel' => ['',1,'-v','Quassel [M]',0,0,0], # special
+ 'quasselclient' => ['',1,'-v','Quassel',0,0,0],# special
+ 'quasselcore' => ['',1,'-v','Quassel (core)',0,0,0],# special
+ 'gribble' => ['^Supybot',2,'--version','Gribble',1,0,0],# special
+ 'limnoria' => ['^Supybot',2,'--version','Limnoria',1,0,0],# special
+ 'supybot' => ['^Supybot',2,'--version','Supybot',1,0,0],# special
+ 'weechat' => ['[0-9.]+',1,'-v','WeeChat',1,0,0],
+ 'weechat-curses' => ['[0-9.]+',1,'-v','WeeChat',1,0,0],
+ 'xchat-gnome' => ['[0-9.]+',2,'-v','X-Chat-Gnome',1,1,0],
+ 'xchat' => ['[0-9.]+',2,'-v','X-Chat',1,1,0],
+ ## Desktops
+ 'afterstep' => ['^afterstep',3,'--version','AfterStep',0,1,0],
+ 'awesome' => ['^awesome',2,'--version','Awesome',0,1,0],
+ 'blackbox' => ['^Blackbox',2,'--version','Blackbox',0,1,0],
+ 'budgie' => ['^budgie-desktop',2,'--version','Budgie',0,1,0],
+ 'cinnamon' => ['^cinnamon',2,'--version','Cinnamon',0,1,0],
+ 'dwm' => ['^dwm',1,'-v','dwm',0,1,1],
+ 'fluxbox' => ['^fluxbox',2,'--version','Fluxbox',0,1,0],
+ 'fvwm' => ['^fvwm',2,'--version','FVWM',0,0,1],
+ # command: fvwm
+ 'fvwm-crystal' => ['^fvwm',2,'--version','FVWM-Crystal',0,0,0],
+ 'gnome-about' => ['gnome',3,'--version','Gnome',0,1,0],
+ 'gnome-shell' => ['gnome',3,'--version','Gnome',0,1,0],
+ 'herbstluftwm' => ['^herbstluftwm',-1,'--version','herbstluftwm',0,1,0],
+ 'jwm' => ['^jwm',2,'--version','JWM',0,1,0],
+ # i3 version 4.13 (2016-11-08) © 2009 Michael Stapelberg and contributors
+ 'i3' => ['^i3',3,'--version','i3',0,1,0],
+ 'icewm' => ['^icewm',2,'--version','IceWM',0,1,0],
+ 'kded' => ['^KDE Development Platform:',4,'--version','KDE',0,1,0],
+ 'kded1' => ['^KDE Development Platform:',4,'--version','KDE',0,1,0],
+ 'kded2' => ['^KDE Development Platform:',4,'--version','KDE',0,1,0],
+ 'kded3' => ['^KDE Development Platform:',4,'--version','KDE',0,1,0],
+ 'kded4' => ['^KDE Development Platform:',4,'--version','KDE',0,1,0],
+ # command: lxqt-about
+ 'lxqt' => ['^lxqt-about',2,'--version','LXQT',0,1,0],
+ 'mate-about' => ['^MATE[[:space:]]DESKTOP',-1,'--version','MATE',0,1,0],
+ # note, mate-session when launched with full path returns full path in version string
+ 'mate-session' => ['mate-session',-1,'--version','MATE',0,1,0],
+ 'openbox' => ['^openboxt',2,'--version','Openbox',0,1,0],
+ 'pekwm' => ['^pekwm',3,'--version','pekwm',0,1,0],
+ 'plasmashell' => ['^plasmashell',2,'--version','KDE Plasma',0,1,0],
+ 'qtdiag' => ['^qt',2,'--version','Qt',0,1,0],
+ 'sawfish' => ['^sawfish',3,'--version','Sawfish',0,1,0],
+ 'scrotwm' => ['^welcome.*scrotwm',4,'-v','Scrotwm',0,1,1],
+ 'spectrwm' => ['^spectrwm.*welcome.*spectrwm',5,'-v','Spectrwm',0,1,0],
+ 'unity' => ['^unity',2,'--version','Unity',0,1,0],
+ 'wm2' => ['^wm2',-1,'--version','WM2',0,1,0],
+ 'wmaker' => ['^Window[[:space:]]*Maker',-1,'--version','WindowMaker',0,1,0],
+ 'wmii' => ['^wmii',1,'--version','wmii',0,1,0], # note: in debian, wmii is wmii3
+ 'wmii2' => ['^wmii2',1,'--version','wmii2',0,1,0],
+ 'xfce4-panel' => ['^xfce4-panel',2,'--version','Xfce',0,1,0],
+ 'xfce5-panel' => ['^xfce5-panel',2,'--version','Xfce',0,1,0],
+ 'xfdesktop' => ['xfdesktop[[:space:]]version',5,'--version','Xfce',0,1,0],
+ # command: xfdesktop
+ 'xfdesktop-toolkit' => ['Built[[:space:]]with[[:space:]]GTK',4,'--version','Gtk',0,1,0],
+ ## Shells
+ 'bash' => ['^GNU[[:space:]]bash,[[:space:]]version',4,'--version','Bash',1,0,0],
+ 'csh' => ['^tcsh',2,'--version','csh',1,0,0],
+ 'dash' => ['dash',3,'--version','Dash',1,0,0], # no version, uses dpkg query, sigh
+ # ksh/lksh/mksh/pdksh can't be handled with version but we'll use the search string to
+ # trigger version return and tests
+ 'ksh' => ['ksh',5,'-v','ksh',1,0,0],
+ 'lksh' => ['ksh',5,'-v','lksh',1,0,0],
+ 'loksh' => ['ksh',5,'-v','lksh',1,0,0],
+ 'mksh' => ['ksh',5,'-v','mksh',1,0,0],
+ 'pdksh' => ['ksh',5,'-v','pdksh',1,0,0],
+ 'tcsh' => ['^tcsh',2,'--version','tcsh',1,0,0],
+ 'zsh' => ['^zsh',2,'--version','zsh',1,0,0],
+ ## Tools
+ 'clang' => ['clang',3,'--version','Clang',1,0,0],
+ 'gcc' => ['^gcc',3,'--version','GCC',1,0,0],
+ 'gcc-apple' => ['Apple[[:space:]]LLVM',2,'--version','LLVM',1,0,0],
+ 'sudo' => ['^Sudo',3,'--version','Sudo',1,0,0],
+ );
+ if ( defined $data{$app} ){
+ my $ref = $data{$app};
+ @client_data = @$ref;
+ }
+ #my $debug = main::Dumper \@client_data;
+ main::log_data('dump',"Client Data",\@client_data) if $b_log;
+ return @client_data;
+}
+# args: 1 - desktop/app command for --version; 2 - search string;
+# 3 - space print number; 4 - [optional] version arg: -v, version, etc
+# 5 - [optional] exit first find 0/1; 6 - [optional] 0/1 stderr output
+sub program_version {
+ eval $start if $b_log;
+ my ($app, $search, $num,$version,$exit,$b_stderr) = @_;
+ my ($cmd,$line,$output);
+ my $version_nu = '';
+ my $count = 0;
+ $exit ||= 100; # basically don't exit ever
+ $version ||= '--version';
+ # adjust to array index, not human readable
+ $num-- if (defined $num && $num > 0);
+ # ksh: Version JM 93t+ 2010--03-05
+ # mksh: @(#)MIRBSD KSH R56 2018/03/09
+ # loksh: @(#)PD KSH v5.2.14 99/07/13.2
+ # --version opens a new ksh, sigh... This so far does not work
+ # because the ENV variable is not visible internally
+ if ($search eq 'ksh'){
+ if ( $ENV{'KSH_VERSION'} ){
+ my @temp = split /\s+/, $ENV{'KSH_VERSION'};
+ if ($temp[2]){
+ $temp[2] =~ s/^v//i; # trim off leading v
+ log_data('data',"Program *ksh array: @temp version: $temp[2]") if $b_log;
+ return $temp[2];
+ }
+ }
+ return 0;
+ }
+ # konvi in particular doesn't like using $ENV{'PATH'} as set, so we need
+ # to always assign the full path if it hasn't already been done
+ if ( $app !~ /^\// ){
+ if (my $program = check_program($app) ){
+ $app = $program;
+ }
+ else {
+ log_data('data',"$app not found in path.");
+ return 0;
+ }
+ }
+ # note, some wm/apps send version info to stderr instead of stdout
+ if ( $b_stderr ) {
+ $cmd = "$app $version 2>&1";
+ }
+# elsif ( $app eq 'csh' ){
+# $app = 'tcsh';
+# }
+ # quick debian/buntu hack until I find a universal way to get version for these
+ elsif ( $app eq 'dash' ){
+ $cmd = "dpkg -l $app 2>/dev/null";
+ }
+ else {
+ $cmd = "$app $version 2>/dev/null";
+ }
+ log_data('data',"version: $version num: $num search: $search command: $cmd") if $b_log;
+ $output = qx($cmd);
+ # print "$cmd : $output\n";
+ # sample: dwm-5.8.2, ©.. etc, why no space? who knows. Also get rid of v in number string
+ # xfce, and other, output has , in it, so dump all commas and parentheses
+ if ($output){
+ open my $ch, '<', \$output or error_handler('open-data',"$cmd", "$!");
+ while (<$ch>){
+ #chomp;
+ last if $count > $exit;
+ if ( $_ =~ /$search/i ) {
+ $_ = trimmer($_);
+ # print "$_ ::$num\n";
+ my @data = split /\s+/, $_;
+ $version_nu = $data[$num];
+ last if ! defined $version_nu;
+ # some distros add their distro name before the version data, which
+ # breaks version detection. A quick fix attempt is to just add 1 to $num
+ # to get the next value.
+ $version_nu = $data[$num+1] if $data[$num+1] && $version_nu =~ /version/i;
+ $version_nu =~ s/(\([^)]+\)|,|dwm-|wmii2-|wmii-|v|V|\||\(|\))//g if $version_nu;
+ # print "$version_nu\n";
+ last;
+ }
+ $count++;
+ }
+ close $ch if $ch;
+ }
+ log_data('data',"Program version: $version_nu") if $b_log;
+ eval $end if $b_log;
+ return $version_nu;
+}
+# print program_version('bash', 'bash', 4) . "\n";
+
+# arg: 1 - full file path, returns array of file lines.
+# 2 - optionsl, strip and clean data
+# note: chomp has to chomp the entire action, not just <$fh>
+sub reader {
+ eval $start if $b_log;
+ my ($file,$strip) = @_;
+ return if ! $file;
+ open( my $fh, '<', $file ) or error_handler('open', $file, $!);
+ chomp(my @rows = <$fh>);
+ if ($strip && @rows){
+ @rows = grep {/^\s*[^#]/} @rows;
+ @rows = map {s/^\s+|\s+$//g; $_} @rows if @rows;
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+# args: 1 - the file to create if not exists
+sub toucher {
+ my $file = shift;
+ if ( ! -e $file ){
+ open( my $fh, '>', $file ) or error_handler('create', $file, $!);
+ }
+}
-# this removes newline and pipes.
-# args: $1 - string to clean
-remove_erroneous_chars()
-{
- eval $LOGFS
- ## RS is input record separator
- ## gsub is substitute;
- gawk '
- BEGIN {
- RS=""
- }
- {
- gsub(/\n$/,"") ## (newline; end of string) with (nothing)
- gsub(/\n/," "); ## (newline) with (space)
- gsub(/^ *| *$/, "") ## (pipe char) with (nothing)
- gsub(/ +/, " ") ## ( +) with (space)
- gsub(/ [ ]+/, " ") ## ([ ]+) with (space)
- gsub(/^ +| +$/, "") ## (pipe char) with (nothing)
- printf $0
- }' "$1" ## prints (returns) cleaned input
- eval $LOGFE
-}
-## note: this is now running inside each gawk sequence directly to avoid exiting gawk
-## looping in bash through arrays, then re-entering gawk to clean up, then writing back to array
-## in bash. For now I'll leave this here because there's still some interesting stuff to get re methods
-# Enforce boilerplate and buzzword filters
-# args: $1 - BAN_LIST_NORMAL/BAN_LIST_CPU; $2 - string to sanitize
-sanitize_characters()
-{
- eval $LOGFS
- # Cannot use strong quotes to unquote a string with pipes in it!
- # bash will interpret the |'s as usual and try to run a subshell!
- # Using weak quotes instead, or use '"..."'
- echo "$2" | gawk "
- BEGIN {
- IGNORECASE=1
- }
- {
- gsub(/${!1}/,\"\")
- gsub(/ [ ]+/,\" \") ## ([ ]+) with (space)
- gsub(/^ +| +$/,\"\") ## (pipe char) with (nothing)
- print ## prints (returns) cleaned input
- }"
- eval $LOGFE
+# calling it trimmer to avoid conflicts with existing trim stuff
+# arg: 1 - string to be right left trimmed. Also slices off \n so no chomp needed
+# this thing is super fast, no need to log its times etc, 0.0001 seconds or less
+sub trimmer {
+ #eval $start if $b_log;
+ my ($str) = @_;
+ $str =~ s/^\s+|\s+$|\n$//g;
+ #eval $end if $b_log;
+ return $str;
+}
+# args: 1 - hash
+# send array, assign to hash, return array, uniq values only.
+sub uniq {
+ my %seen;
+ grep !$seen{$_}++, @_;
+}
+# arg: 1 file full path to write to; 2 - arrayof data to write.
+# note: turning off strict refs so we can pass it a scalar or an array reference.
+sub writer {
+ my ($path, $ref_content) = @_;
+ my ($content);
+ no strict 'refs';
+ # print Dumper $ref_content, "\n";
+ if (ref $ref_content eq 'ARRAY'){
+ $content = join "\n", @$ref_content or die "failed with error $!";
+ }
+ else {
+ $content = scalar $ref_content;
+ }
+ open(my $fh, '>', $path) or error_handler('open',"$path", "$!");
+ print $fh $content;
+ close $fh;
}
#### -------------------------------------------------------------------
-#### PRINT
-#### -------------------------------------------------------------------
+#### UPDATER
+##### -------------------------------------------------------------------
+
+# arg 1: type to return
+sub get_defaults {
+ my ($type) = @_;
+ my %defaults = (
+ 'ftp-upload' => 'ftp.techpatterns.com/incoming',
+ 'inxi-branch-1' => 'https://github.com/smxi/inxi/raw/one/',
+ 'inxi-branch-2' => 'https://github.com/smxi/inxi/raw/two/',
+ '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-gh' => "https://github.com/smxi/inxi/raw/master/$self_name.1",
+ 'pinxi-man' => "https://smxi.org/in/$self_name.1.gz",
+ 'pinxi-man-gh' => "https://github.com/smxi/inxi/raw/inxi-perl/$self_name.1",
+ );
+ if ( exists $defaults{$type}){
+ return $defaults{$type};
+ }
+ else {
+ error_handler('bad-arg-int', $type);
+ }
+}
+# args: 1 - download url, not including file name; 2 - string to print out
+# 3 - update type option
+# note that 1 must end in / to properly construct the url path
+sub update_me {
+ eval $start if $b_log;
+ my ( $self_download, $download_id ) = @_;
+ my $downloader_error=1;
+ my $file_contents='';
+ my $output = '';
+ $self_path =~ s/\/$//; # dirname sometimes ends with /, sometimes not
+ $self_download =~ s/\/$//; # dirname sometimes ends with /, sometimes not
+ my $full_self_path = "$self_path/$self_name";
+
+ if ( $b_irc ){
+ error_handler('not-in-irc', "-U/--update" )
+ }
+ if ( ! -w $full_self_path ){
+ error_handler('not-writable', "$self_name", '');
+ }
+ $output .= "Starting $self_name self updater.\n";
+ $output .= "Using $dl{'dl'} as downloader.\n";
+ $output .= "Currently running $self_name version number: $self_version\n";
+ $output .= "Current version patch number: $self_patch\n";
+ $output .= "Current version release date: $self_date\n";
+ $output .= "Updating $self_name in $self_path using $download_id as download source...\n";
+ print $output;
+ $output = '';
+ $self_download = "$self_download/$self_name";
+ $file_contents = download_file('stdout', $self_download);
+
+ # then do the actual download
+ if ( $file_contents ){
+ # make sure the whole file got downloaded and is in the variable
+ if ( $file_contents =~ /###\*\*EOF\*\*###/ ){
+ open(my $fh, '>', $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();
+ $output .= "Successfully updated to $download_id version: $self_version\n";
+ $output .= "New $download_id version patch number: $self_patch\n";
+ $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){
+ update_man($download_id);
+ }
+ else {
+ print "Skipping man download because branch version is being used.\n";
+ }
+ exit 1;
+ }
+ else {
+ error_handler('file-corrupt', "$self_name");
+ }
+ }
+ # now run the error handlers on any downloader failure
+ else {
+ error_handler('download-error', $self_download, $download_id);
+ }
+ eval $end if $b_log;
+}
-# args: $1 - string to strip color code characters out of
-# returns count of string length minus colors
-# note; this cleanup may not be working on bsd sed
-calculate_line_length()
-{
- local string=$1
- # ansi:  irc: \x0312
- # note: using special trick for bsd sed, tr - NOTE irc sed must use " double quote
- string=$( sed -e 's/'$ESC'\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' -e "s/\\\x0[0-9]\{1,3\}//g" <<< $string )
- #echo $string
- LINE_LENGTH=${#string}
- # echo ${#string}
-}
-
-## this handles all verbose line construction with indentation/line starter
-## args: $1 - null (, actually: " ") or line starter; $2 - line content
-create_print_line()
-{
- eval $LOGFS
- # convoluted, yes, but it works to trim spaces off end
- local line=${2%${2##*[![:space:]]}}
- printf "${C1}%-${INDENT}s${C2} %s" "$1" "$line${CN}"
- eval $LOGFE
+sub update_man {
+ 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;
+ 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";
+ return 0;
+ }
+ if ( ! -w $man_file_location ){
+ print "Cannot write to $man_file_location! Are you root?\n";
+ print "Unable to continue: $man_file_location\n";
+ return 0;
+ }
+ if ( -f "/usr/share/man/man8/inxi.8.gz" ){
+ print "Updating man page location to man1.\n";
+ rename "/usr/share/man/man8/inxi.8.gz", "$man_file_location/inxi.1.gz";
+ if ( check_program('mandb') ){
+ 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";
+ }
+ }
+ }
+ 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";
+ }
+ }
+ 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";
+ }
}
-# inxi speaks through here. When run by Konversation script alias mode, uses DCOP
-# for dcop to work, must use 'say' operator, AND colors must be evaluated by echo -e
-# note: dcop does not seem able to handle \n so that's being stripped out and replaced with space.
-print_screen_output()
-{
- eval $LOGFS
- # the double quotes are needed to avoid losing whitespace in data when certain output types are used
- # trim off whitespace at end
- local print_data="$( echo -e "$1" )"
-
- # just using basic debugger stuff so you can tell which thing is printing out the data. This
- # should help debug kde 4 konvi issues when that is released into sid, we'll see. Turning off
- # the redundant debugger output which as far as I can tell does exactly nothing to help debugging.
- if [[ $DEBUG -gt 5 ]];then
- if [[ $KONVI -eq 1 ]];then
- # konvi doesn't seem to like \n characters, it just prints them literally
- # print_data="$( tr '\n' ' ' <<< "$print_data" )"
- # dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "konvi='$KONVI' saying : '$print_data'"
- print_data="KP-$KONVI: $print_data"
- elif [[ $KONVI -eq 2 ]];then
- # echo "konvi='$KONVI' saying : '$print_data'"
- print_data="KP-$KONVI: $print_data"
- else
- # echo "printing out: '$print_data'"
- print_data="P: $print_data"
- fi
- fi
- if [[ $KONVI -eq 1 && $B_DCOP == 'true' ]]; then ## dcop Konversation (<= 1.1 (qt3))
- # konvi doesn't seem to like \n characters, it just prints them literally
- $print_data="$( tr '\n' ' ' <<< "$print_data" )"
- dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "$print_data"
- elif [[ $KONVI -eq 3 && $B_QDBUS == 'true' ]]; then ## dbus Konversation (> 1.2 (qt4))
- qdbus org.kde.konversation /irc say "$DCSERVER" "$DCTARGET" "$print_data"
-# elif [[ $IRC_CLIENT == 'X-Chat' ]]; then
-# qdbus org.xchat.service print "$print_data\n"
- else
- # the -n is needed to avoid double spacing of output in terminal
- echo -ne "$print_data\n"
- fi
- eval $LOGFE
-}
-
-# uses $TERM_COLUMNS to set width using $COLS_MAX as max width
-# IMPORTANT: Must come after print_screen_output for debugging purposes
-# IMPORTANT: minimize use of subshells here or the output is too slow
-# IMPORTANT: each text chunk must be a continuous line, no line breaks. For anyone who uses a
-# code editor that can't do visual (not hard coded) line wrapping, upgrade to one that can.
-# args: $1 - 0 1 2 3 4 for indentation level; $2 -line starter, like -m; $3 - content of block.
-print_lines_basic()
-{
- local line_width=$COLS_MAX
- local print_string='' indent_inner='' indent_full='' indent_x=''
- local indent_working='' indent_working_full=''
- local line_starter='' line_1_starter='' line_x_starter=''
- # note: to create a padded string below
- local fake_string=' ' temp_count='' line_count='' spacer=''
- local indent_main=6 indent_x='' b_indent_x='true'
-
- case $1 in
- # for no options, start at left edge
- 0) indent_full=0
- line_1_starter=''
- line_x_starter=''
- b_indent_x='false'
- ;;
- 1) indent_full=$indent_main
- temp_count=${#2}
- if [[ $temp_count -le $indent_full ]];then
- indent_working=$indent_full
- else
- indent_working=$temp_count #$(( $temp_count + 1 ))
- fi
- line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
- ;;
- # first left pad 2 and 3, then right pad them
- 2) indent_full=$(( $indent_main + 6 ))
- indent_inner=3
- temp_count=${#2}
- if [[ $temp_count -le $indent_inner ]];then
- indent_working=$indent_inner
- #indent_working_full=$indent_full
- else
- indent_working=$(( $temp_count + 1 ))
- #indent_working_full=$(( $indent_full - $indent_inner - 1 ))
- fi
- line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
- line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
- ;;
- 3) indent_full=$(( $indent_main + 8 ))
- indent_inner=3
- temp_count=${#2}
- if [[ $temp_count -le $indent_inner ]];then
- indent_working=$indent_inner
- else
- indent_working=$(( $temp_count + 1 ))
- fi
- line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
- line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
- ;;
- # for long options
- 4) indent_full=$(( $indent_main + 8 ))
- temp_count=${#2}
- if [[ $temp_count -lt $indent_full ]];then
- indent_working=$indent_full
- else
- indent_working=$temp_count #$(( $temp_count + 1 ))
- fi
- line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
- ;;
- esac
-
- if [[ $b_indent_x == 'true' ]];then
- indent_x=$(( $indent_full + 1 ))
- line_x_starter="$(printf "%${indent_x}s" '')"
- fi
-
- line_count=$(( $line_width - $indent_full ))
-
- # bash loop is slow, only run this if required
- if [[ ${#3} -gt $line_count ]];then
- for word in $3
- do
- temp_string="$print_string$spacer$word"
- spacer=' '
- if [[ ${#temp_string} -lt $line_count ]];then
- print_string=$temp_string # lose any white space start/end
- # echo -n $(( $line_width - $indent_full ))
- else
- if [[ -n $line_1_starter ]];then
- line_starter="$line_1_starter"
- line_1_starter=''
- else
- line_starter="$line_x_starter"
- fi
- # clean up forced connections, ie, stuff we don't want wrapping
- print_string=${print_string//\^/ }
- print_screen_output "$line_starter$print_string"
- print_string="$word$spacer" # needed to handle second word on new line
- temp_string=''
- spacer=''
- fi
- done
- else
- # echo no loop
- print_string=$3
- fi
- # print anything left over
- if [[ -n $print_string ]];then
- if [[ -n $line_1_starter ]];then
- line_starter="$line_1_starter"
- line_1_starter=''
- else
- line_starter="$line_x_starter"
- fi
- print_string=${print_string//\^/ }
- print_screen_output "$line_starter$print_string"
- fi
-}
-# print_lines_basic '1' '-m' 'let us teest this string and lots more and stuff and more stuff and x is wy and z is x and fred is dead and gus is alive an yes we have to go now'
-# print_lines_basic '2' '7' 'and its substring this string and lots more and stuff and more stuff and x is wy and z is x and fred is dead and gus is alive an yes we have to go now'
-# print_lines_basic '2' '12' 'and its sss substring'
-# print_lines_basic '3' '12' 'and its sss substring this string and lots more and stuff and more stuff and x is wy and z is x and fred is dead and gus is alive an yes we have to go now'
-# exit
+sub set_man_location {
+ my $location='';
+ my $default_location='/usr/share/man/man1';
+ my $man_paths=qx(man --path 2>/dev/null);
+ my $man_local='/usr/local/share/man';
+ my $b_use_local=0;
+ if ( $man_paths && $man_paths =~ /$man_local/ ){
+ $b_use_local=1;
+ }
+ # for distro installs
+ if ( -f "$default_location/inxi.1.gz" ){
+ $location=$default_location;
+ }
+ else {
+ if ( $b_use_local ){
+ if ( ! -d "$man_local/man1" ){
+ mkdir "$man_local/man1";
+ }
+ $location="$man_local/man1";
+ }
+ }
+ if ( ! $location ){
+ $location=$default_location;
+ }
+ return $location;
+}
+
+# update for updater output version info
+# note, this is only now used for self updater function so it can get
+# the values from the UPDATED file, NOT the running program!
+sub set_version_data {
+ open (my $fh, '<', "$self_path/$self_name");
+ while( my $row = <$fh>){
+ chomp $row;
+ $row =~ s/'|;//g;
+ if ($row =~ /^my \$self_name/ ){
+ $self_name = (split /=/, $row)[1];
+ }
+ elsif ($row =~ /^my \$self_version/ ){
+ $self_version = (split /=/, $row)[1];
+ }
+ elsif ($row =~ /^my \$self_date/ ){
+ $self_date = (split /=/, $row)[1];
+ }
+ elsif ($row =~ /^my \$self_patch/ ){
+ $self_patch = (split /=/, $row)[1];
+ }
+ elsif ($row =~ /^## END INXI INFO/){
+ last;
+ }
+ }
+ close $fh;
+}
########################################################################
-#### OPTION AND VERSION HANDLERS
+#### OPTIONS HANDLER / VERSION
########################################################################
-# Get the parameters. Note: standard options should be lower case, advanced or testing, upper
-# args: $1 - full script startup args: $@
-get_parameters()
-{
- eval $LOGFS
- local opt='' downloader_test='' debug_data_type='' weather_flag='wW:'
- local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false
-
+sub get_options{
+ eval $start if $b_log;
+ my (@args) = @_;
+ $show{'short'} = 1;
+ my ($b_downloader,$b_help,$b_no_man,$b_no_man_force,$b_recommends,$b_updater,$b_version,
+ $b_use_man,$self_download, $download_id);
+ GetOptions (
+ 'A|audio' => sub {
+ $show{'short'} = 0;
+ $show{'audio'} = 1;},
+ 'b|basic' => sub {
+ $show{'short'} = 0;
+ $show{'battery'} = 1;
+ $show{'cpu-basic'} = 1;
+ $show{'raid-basic'} = 1;
+ $show{'disk-total'} = 1;
+ $show{'graphic'} = 1;
+ $show{'info'} = 1;
+ $show{'machine'} = 1;
+ $show{'network'} = 1;
+ $show{'system'} = 1;},
+ 'B|battery' => sub {
+ $show{'short'} = 0;
+ $show{'battery'} = 1;
+ $show{'battery-forced'} = 1; },
+ 'c|color:i' => sub {
+ my ($opt,$arg) = @_;
+ if ( $arg >= 0 && $arg < get_color_scheme('count') ){
+ set_color_scheme($arg);
+ }
+ elsif ( $arg >= 94 && $arg <= 99 ){
+ $colors{'selector'} = $arg;
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ } },
+ 'C|cpu' => sub {
+ $show{'short'} = 0;
+ $show{'cpu'} = 1; },
+ 'd|disk-full|optical' => sub {
+ $show{'short'} = 0;
+ $show{'disk'} = 1;
+ $show{'optical'} = 1; },
+ 'D' => sub {
+ $show{'short'} = 0;
+ $show{'disk'} = 1; },
+ 'f|flags|flag' => sub {
+ $show{'short'} = 0;
+ $show{'cpu'} = 1;
+ $show{'cpu-flag'} = 1; },
+ 'F|full' => sub {
+ $show{'short'} = 0;
+ $show{'audio'} = 1;
+ $show{'battery'} = 1;
+ $show{'cpu'} = 1;
+ $show{'disk'} = 1;
+ $show{'graphic'} = 1;
+ $show{'info'} = 1;
+ $show{'machine'} = 1;
+ $show{'network'} = 1;
+ $show{'network-advanced'} = 1;
+ $show{'partition'} = 1;
+ $show{'raid'} = 1;
+ $show{'sensor'} = 1;
+ $show{'system'} = 1; },
+ 'G|graphics|graphic' => sub {
+ $show{'short'} = 0;
+ $show{'graphic'} = 1; },
+ 'i|ip' => sub {
+ $show{'short'} = 0;
+ $show{'ip'} = 1;
+ $show{'network'} = 1;
+ $show{'network-advanced'} = 1;
+ $b_downloader = 1 if ! check_program('dig');},
+ 'I|info' => sub {
+ $show{'short'} = 0;
+ $show{'info'} = 1; },
+ 'l|labels|label' => sub {
+ $show{'short'} = 0;
+ $show{'label'} = 1;
+ $show{'partition'} = 1; },
+ 'limit:i' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg != 0){
+ $limit = $arg;
+ }
+ else {
+ error_handler('bad-arg',$opt,$arg);
+ } },
+ 'm|memory' => sub {
+ $show{'short'} = 0;
+ $show{'ram'} = 1; },
+ 'M|machine' => sub {
+ $show{'short'} = 0;
+ $show{'machine'} = 1; },
+ 'n|network-advanced' => sub {
+ $show{'short'} = 0;
+ $show{'network'} = 1;
+ $show{'network-advanced'} = 1; },
+ 'N|network' => sub {
+ $show{'short'} = 0;
+ $show{'network'} = 1; },
+ 'o|unmounted' => sub {
+ $show{'short'} = 0;
+ $show{'unmounted'} = 1; },
+ 'p|partition-full' => sub {
+ $show{'short'} = 0;
+ $show{'partition'} = 0;
+ $show{'partition-full'} = 1; },
+ 'P|partitions|partition' => sub {
+ $show{'short'} = 0;
+ $show{'partition'} = 1; },
+ 'r|repos|repo' => sub {
+ $show{'short'} = 0;
+ $show{'repo'} = 1; },
+ 'R|raid' => sub {
+ $show{'short'} = 0;
+ $show{'raid'} = 1;
+ $show{'raid-forced'} = 1; },
+ 's|sensors|sensor' => sub {
+ $show{'short'} = 0;
+ $show{'sensor'} = 1; },
+ 'sleep:s' => sub {
+ my ($opt,$arg) = @_;
+ $arg ||= 0;
+ if ($arg >= 0){
+ $cpu_sleep = $arg;
+ }
+ else {
+ error_handler('bad-arg',$opt,$arg);
+ } },
+ 'slots|slot' => sub {
+ $show{'short'} = 0;
+ $show{'slot'} = 1; },
+ 'S|system' => sub {
+ $show{'short'} = 0;
+ $show{'system'} = 1; },
+ 't|processes|process:s' => sub {
+ my ($opt,$arg) = @_;
+ $show{'short'} = 0;
+ $arg ||= 'cm';
+ my $num = $arg;
+ $num =~ s/^[cm]+// if $num;
+ if ( $arg =~ /^([cm]+)([0-9]+)?$/ && (!$num || $num =~ /^\d+/) ){
+ $show{'process'} = 1;
+ if ($arg =~ /c/){
+ $show{'ps-cpu'} = 1;
+ }
+ if ($arg =~ /m/){
+ $show{'ps-mem'} = 1;
+ }
+ $ps_count = $num if $num;
+ }
+ else {
+ error_handler('bad-arg',$opt,$arg);
+ } },
+ 'usb' => sub {
+ $show{'short'} = 0;
+ $show{'usb'} = 1; },
+ 'u|uuid' => sub {
+ $show{'short'} = 0;
+ $show{'partition'} = 1;
+ $show{'uuid'} = 1; },
+ 'v|verbosity:i' => sub {
+ my ($opt,$arg) = @_;
+ $show{'short'} = 0;
+ if ( $arg =~ /^[0-8]$/ ){
+ if ($arg == 0 ){
+ $show{'short'} = 1;
+ }
+ if ($arg >= 1 ){
+ $show{'cpu-basic'} = 1;
+ $show{'disk-total'} = 1;
+ $show{'graphic'} = 1;
+ $show{'info'} = 1;
+ $show{'system'} = 1;
+ }
+ if ($arg >= 2 ){
+ $show{'battery'} = 1;
+ $show{'disk-basic'} = 1;
+ $show{'raid-basic'} = 1;
+ $show{'machine'} = 1;
+ $show{'network'} = 1;
+ }
+ if ($arg >= 3 ){
+ $show{'network-advanced'} = 1;
+ $show{'cpu'} = 1;
+ $extra = 1;
+ }
+ if ($arg >= 4 ){
+ $show{'disk'} = 1;
+ $show{'partition'} = 1;
+ }
+ if ($arg >= 5 ){
+ $show{'audio'} = 1;
+ $show{'ram'} = 1;
+ $show{'label'} = 1;
+ $show{'optical-basic'} = 1;
+ $show{'ram'} = 1;
+ $show{'raid'} = 1;
+ $show{'sensor'} = 1;
+ $show{'uuid'} = 1;
+ }
+ if ($arg >= 6 ){
+ $show{'optical'} = 1;
+ $show{'partition-full'} = 1;
+ $show{'unmounted'} = 1;
+ $show{'usb'} = 1;
+ $extra = 2;
+ }
+ if ($arg >= 7 ){
+ $b_downloader = 1 if ! check_program('dig');
+ $show{'cpu-flag'} = 1;
+ $show{'ip'} = 1;
+ $show{'raid-forced'} = 1;
+ $extra = 3;
+ }
+ if ($arg >= 8 ){
+ $b_downloader = 1;
+ $show{'slot'} = 1;
+ $show{'process'} = 1;
+ $show{'ps-cpu'} = 1;
+ $show{'ps-mem'} = 1;
+ $show{'repo'} = 1;
+ #$show{'weather'} = 1;
+ }
+ }
+ else {
+ error_handler('bad-arg',$opt,$arg);
+ } },
+ 'w|weather' => sub {
+ my ($opt) = @_;
+ $show{'short'} = 0;
+ $b_downloader = 1;
+ if ( $b_weather ){
+ $show{'weather'} = 1;
+ }
+ else {
+ error_handler('distro-block', $opt);
+ } },
+ 'W|weather-location:s' => sub {
+ my ($opt,$arg) = @_;
+ $arg ||= '';
+ $arg =~ s/\s//g;
+ $show{'short'} = 0;
+ $b_downloader = 1;
+ if ( $b_weather ){
+ if ($arg){
+ $show{'weather'} = 1;
+ $show{'weather-location'} = $arg;
+ }
+ else {
+ error_handler('bad-arg',$opt,$arg);
+ }
+ }
+ else {
+ error_handler('distro-block', $opt);
+ } },
+ 'x|extra:i' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg > 0){
+ $extra = $arg;
+ }
+ else {
+ $extra++;
+ } },
+ 'y|width:i' => sub {
+ my ($opt, $arg) = @_;
+ $arg = 2000 if defined $arg && $arg == -1;
+ if ( $arg =~ /\d/ && $arg >= 80 ){
+ set_display_width($arg);
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ } },
+ 'z|filter' => sub {
+ $show{'filter'} = 1; },
+ 'Z|filter-override' => sub {
+ $show{'filter-override'} = 1; },
+ ## Start non data options
+ 'alt:i' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg == 40) {
+ $dl{'tiny'} = 0;
+ $b_downloader = 1;}
+ elsif ($arg == 41) {
+ $dl{'curl'} = 0;
+ $b_downloader = 1;}
+ elsif ($arg == 42) {
+ $dl{'fetch'} = 0;
+ $b_downloader = 1;}
+ elsif ($arg == 43) {
+ $dl{'wget'} = 0;
+ $b_downloader = 1;}
+ elsif ($arg == 44) {
+ $dl{'curl'} = 0;
+ $dl{'fetch'} = 0;
+ $dl{'wget'} = 0;
+ $b_downloader = 1;}
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }},
+ 'arm' => sub {
+ $b_arm = 1 },
+ 'bsd:s' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg =~ /^(darwin|dragonfly|freebsd|openbsd|netbsd)$/i){
+ $bsd_type = lc($arg);
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }
+ },
+ 'dbg:i' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg > 0) {
+ $test[$arg] = 1;
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }},
+ 'debug:i' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg =~ /^[1-3]|1[0-2]|2[0-4]$/){
+ $debug=$arg;
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ } },
+ 'display:s' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg =~ /^:?([0-9]+)?$/){
+ $display=$arg;
+ $display ||= ':0';
+ $display = ":$display" if $display !~ /^:/;
+ $b_display = ($b_root) ? 0 : 1;
+ $b_force_display = 1;
+ $display_opt = "-display $display";
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ } },
+ 'dmidecode' => sub {
+ $b_dmidecode_force = 1 },
+ 'downloader:s' => sub {
+ my ($opt,$arg) = @_;
+ $arg = lc($arg);
+ if ($arg =~ /^(curl|fetch|ftp|perl|wget)$/){
+ if ($arg eq 'perl' && (!check_module('HTTP::Tiny') || !check_module('IO::Socket::SSL') )){
+ error_handler('missing-perl-downloader', $opt, $arg);
+ }
+ elsif ( !check_program($arg)) {
+ 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);
+ %dl = ('dl' => $arg, $arg => 1);
+ $b_downloader = 1;
+ }
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ } },
+ 'ftp:s' => sub {
+ my ($opt,$arg) = @_;
+ # pattern: ftp.x.x/x
+ if ($arg =~ /^ftp\..+\..+\/[^\/]+$/ ){
+ $ftp_alt = $arg;
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }},
+ 'h|help|?' => sub {
+ $b_help = 1; },
+ 'host|hostname' => sub {
+ $show{'host'} = 1 },
+ 'indent-min:i' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg =~ /^\d+$/){
+ $size{'indent-min'} = 1;
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }},
+ 'irc' => sub {
+ $b_irc = 1; },
+ 'man' => sub {
+ $b_use_man = 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);
+ }
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }},
+ 'no-host|no-hostname' => sub {
+ $show{'host'} = 0 },
+ 'no-man' => sub {
+ $b_no_man_force = 0; },
+ 'no-ssl' => sub {
+ $dl{'no-ssl-opt'}=1 },
+ 'output-file:s' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg){
+ if ($arg eq 'print' || check_output_path($arg)){
+ $output_file = $arg;
+ }
+ else {
+ error_handler('output-file-bad', $opt, $arg);
+ }
+ }
+ else {
+ error_handler('bad-arg', $opt, $arg);
+ }},
+ 'recommends' => sub {
+ $b_recommends = 1; },
+ 'U|update:s' => sub { # 1,2,3 OR http://myserver/path/inxi
+ my ($opt,$arg) = @_;
+ $b_downloader = 1;
+ if ( $b_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);
+ } },
+ 'V|version' => sub {
+ $b_version = 1 },
+ '<>' => sub {
+ my ($opt) = @_;
+ error_handler('unknown-option', "$opt", "" ); }
+ ) ; #or error_handler('unknown-option', "@ARGV", '');
+ ## run all these after so that we can change widths, downloaders, etc
+ eval $end if $b_log;
+ CheckRecommends::run() if $b_recommends;
+ set_downloader() if $b_downloader;
+ 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;
+ if ($output_type){
+ if ($output_type ne 'screen' && ! $output_file){
+ error_handler('bad-arg', '--output', '--output-file not provided');
+ }
+ }
+ if ( $show{'ram'} || $show{'slot'} ||
+ ( ( $bsd_type || $b_dmidecode_force ) && ($show{'machine'} || $show{'battery'}) ) ){
+ $b_dmi = 1;
+ }
+ if ($show{'audio'} || $show{'graphic'} || $show{'network'} ){
+ $b_pci = 1;
+ }
+ if ($show{'usb'} || $show{'audio'} || $show{'network'} ){
+ # to detect wan/lan, we have to use long form to get as much data as possible
+ $usb_level = ($show{'usb'} || $show{'network'}) ? 2 : 1;
+ }
+ if ($bsd_type && ($show{'short'} || $show{'cpu'} || $show{'cpu-basic'} || $show{'machine'} ||
+ $show{'info'} || $show{'process'} || $show{'ram'} ) ){
+ $b_sysctl = 1;
+ }
+ if ($show{'filter-override'}){
+ $show{'filter'} = 0;
+ }
+ # override for things like -b or -v2 to -v3
+ $show{'cpu-basic'} = 0 if $show{'cpu'};
+ $show{'optical-basic'} = 0 if $show{'optical'};
+ $show{'partition'} = 0 if $show{'partition-full'};
+ if ($show{'disk'} || $show{'optical'} ){
+ $show{'disk-basic'} = 0;
+ $show{'disk-total'} = 0;
+ }
+ if ($bsd_type && ($show{'short'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'disk'})){
+ $b_dm_boot_disk = 1;
+ }
+ if ($bsd_type && ($show{'optical-basic'} || $show{'optical'})){
+ $b_dm_boot_optical = 1
+ }
+}
+
+sub show_options {
+ error_handler('not-in-irc', 'help') if $b_irc;
+ my (@row,@rows,@data);
+ my $line = '';
+ my $color_scheme_count = get_color_scheme('count') - 1;
+ my $partition_string='partition';
+ my $partition_string_u='Partition';
+ my $flags = ($b_arm) ? 'features' : 'flags' ;
+ if ( $bsd_type ){
+ $partition_string='slice';
+ $partition_string_u='Slice';
+ }
+ # fit the line to the screen!
+ for my $i ( 0 .. ( ( $size{'max'} / 2 ) - 2 ) ){
+ $line = $line . '- ';
+ }
+ @rows = (
+ ['0', '', '', "$self_name supports the following options. You can combine
+ these or list them one by one. For more detailed information, see man^$self_name.
+ Examples:^$self_name^-v4^-c6 OR
+ $self_name^-bDc^6. If you start $self_name with no arguments, it will display
+ a short system summary." ],
+ [0, '', '', '' ],
+ ['0', '', '', "The following options, if used without -F, -b, or -v, will
+ show option line(s): A, B, C, D, G, I, M, N, P, R, S, W, d, f, i, l, m, n,
+ o, p, r, s, t, u, w, --slots, --usb - you can use these alone or together
+ to show just the line(s) you want to see. If you use them with -v [level],
+ -b or -F, $self_name will combine the outputs." ],
+ ['0', '', '', $line ],
+ ['0', '', '', "Output Control Options:" ],
+ ['1', '-A', '--audio', "Audio/sound card(s), driver, sound server." ],
+ ['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ],
+ ['1', '-B', '--battery', "Battery info, including charge and condition, plus
+ extra info (if battery present)." ],
+ ['1', '-c', '--color', "Set color scheme (0-42). Example:^$self_name^-c^11" ],
+ ['1', '', '', "Color selectors let you set the config file value for the
+ selection (NOTE: IRC and global only show safe color set)" ],
+ ['2', '94', '', "Console, out of X" ],
+ ['2', '95', '', "Terminal, running in X - like xTerm" ],
+ ['2', '96', '', "Gui IRC, running in X - like Xchat, Quassel, Konversation etc." ],
+ ['2', '97', '', "Console IRC running in X - like irssi in xTerm" ],
+ ['2', '98', '', "Console IRC not in X" ],
+ ['2', '99', '', "Global - Overrides/removes all settings. Setting specific
+ removes global." ],
+ ['1', '-C', '--cpu', "CPU output, including per CPU clock speed and max
+ CPU speed (if available)." ],
+ ['1', '-d', '--disk-full, --optical', "Optical drive data (and floppy disks,
+ if present). Triggers -D." ],
+ ['1', '-D', '--disk', "Hard Disk info, including total storage and details
+ for each disk. Disk total used percentage includes swap partition size(s)." ],
+ ['1', '-f', '--flags', "All CPU $flags. Triggers -C. Not shown with -F to
+ avoid spamming." ],
+ ['1', '-F', '--full', "Full output. Includes all Upper Case line letters
+ except -W, plus -s and -n. Does not show extra verbose options such
+ as -d -f -i -l -m -o -p -r -t -u -x, unless specified." ],
+ ['1', '-G', '--graphics', "Graphics info (card(s), driver, display protocol
+ (if available), display server, resolution, renderer, OpenGL version)." ],
+ ['1', '-i', '--ip', "WAN IP address and local interfaces (requires ifconfig
+ or ip network tool). Triggers -n. Not shown with -F for user security reasons.
+ You shouldn't paste your local/WAN IP." ],
+ ['1', '-I', '--info', "General info, including processes, uptime, memory,
+ IRC client or shell type, $self_name version." ],
+ ['1', '-l', '--label', "$partition_string_u labels. Triggers -P.
+ For full -p output, use -pl." ],
+ ['1', '-m', '--memory', "Memory (RAM) data. Requires root. Numbers of
+ devices (slots) supported and individual memory devices (sticks of memory etc).
+ For devices, shows device locator, size, speed, type (e.g. DDR3).
+ If neither -I nor -tm are selected, also shows RAM used/total." ],
+ ['1', '-M', '--machine', "Machine data. Device type (desktop, server, laptop,
+ VM etc.), motherboard, BIOS and, if present, system builder (e.g. Lenovo).
+ Shows UEFI/BIOS/UEFI [Legacy]. Older systems/kernels without the required /sys
+ data can use dmidecode instead, run as root. Dmidecode can be forced with --dmidecode" ],
+ ['1', '-n', '--network-advanced', "Advanced Network card info. Triggers -N. Shows
+ interface, speed, MAC id, state, etc. " ],
+ ['1', '-N', '--network', "Network card(s), driver." ],
+ ['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)." ],
+ ['1', '', '', "Example: ^<username>^ALL^=^NOPASSWD:^/usr/bin/file^" ],
+ ['1', '-p', '--partitions-full', "Full $partition_string information (-P plus all other
+ detected ${partition_string}s)." ],
+ ['1', '-P', '--partitions', "Basic $partition_string info. Shows, if detected:
+ / /boot /home /opt /tmp /usr /var /var/log /var/tmp. Use -p to see all
+ mounted ${partition_string}s." ],
+ ['1', '-r', '--repos', "Distro repository data. Supported repo types: APK,
+ APT, EOPKG, PACMAN, PACMAN-G2, PISI, PORTAGE, PORTS (BSDs), SLACKPKG,
+ URPMQ, YUM/ZYPP." ],
+ ['1', '-R', '--raid', "RAID data. Shows RAID devices, states, levels,
+ and components. md-raid: If device is resyncing, also shows resync progress line." ],
+ ['1', '-s', '--sensors', "Sensors output (if sensors installed/configured):
+ mobo/CPU/GPU temp; detected fan speeds. GPU temp only for Fglrx/Nvidia drivers.
+ Nvidia shows screen number for > 1 screen. IPMI sensors if present." ],
+ ['1', '', '--slots', "PCI slots: type, speed, status. Requires root." ],
+ ['1', '-S', '--system', "System info: host name, kernel, desktop environment
+ (if in X/Wayland), distro." ],
+ ['1', '-t', '--processes', "Processes. Requires extra options: c (CPU), m
+ (memory), cm (CPU+memory). If followed by numbers 1-x, shows that number
+ of processes for each type (default: 5; if in IRC, max: 5). " ],
+ ['1', '', '', "Make sure that there is no space between letters and
+ numbers (e.g. write as^-t^cm10)." ],
+ ['1', '', '--usb', "Show USB data: Hubs and Devices." ],
+ ['1', '-u', '--uuid', "$partition_string_u UUIDs. Triggers -P. For full -p
+ output, use -pu." ],
+ ['1', '-v', '--verbosity', "Set $self_name verbosity level (0-8).
+ Should not be used with -b or -F. Example: $self_name^-v^4" ],
+ ['2', '0', '', "Same as: $self_name" ],
+ ['2', '1', '', "Basic verbose, -S + basic CPU + -G + basic Disk + -I." ],
+ ['2', '2', '', "Networking card (-N), Machine (-M), Battery (-B; if present),
+ and, if present, basic RAID (devices only; notes if inactive).
+ Same as $self_name^-b" ],
+ ['2', '3', '', "Advanced CPU (-C), battery (-B), network (-n);
+ triggers -x. " ],
+ ['2', '4', '', "$partition_string_u size/used data (-P) for
+ (if present) /, /home, /var/, /boot. Shows full disk data (-D). " ],
+ ['2', '5', '', "Audio card (-A), sensors (-s), memory/RAM (-m),
+ $partition_string label^(-l), UUID^(-u), short form of optical drives,
+ standard RAID data (-R). " ],
+ ['2', '6', '', "Full $partition_string (-p), unmounted $partition_string (-o),
+ optical drive (-d), USB (--usb), full RAID; triggers -xx." ],
+ ['2', '7', '', "Network IP data (-i); triggers -xxx."],
+ ['2', '8', '', "Everything available, including repos (-r), processes
+ (-tcm), PCI slots (--slots)."],
+ );
+ push @data, @rows;
# if distro maintainers don't want the weather feature disable it
- if [[ $B_ALLOW_WEATHER == 'false' ]];then
- weather_flag=''
- fi
- if [[ $1 == '--version' ]];then
- show_version_info
- exit 0
- elif [[ $1 == '--help' ]];then
- show_options
- exit 0
- elif [[ $1 == '--recommends' ]];then
- check_recommends_user_output
- exit 0
- # the short form only runs if no args output args are used
- # no need to run through these if there are no args
- # reserved for future use: -g for extra Graphics; -m for extra Machine; -d for extra Disk
- elif [[ -n $1 ]];then
- while getopts AbBc:CdDfFGhHiIlmMnNopPrRsSt:uUv:V${weather_flag}xy:zZ%@:!: opt
- do
- case $opt in
- A) B_SHOW_AUDIO='true'
- use_short='false'
- ;;
- b) use_short='false'
- B_SHOW_BASIC_CPU='true'
- B_SHOW_BASIC_RAID='true'
- B_SHOW_DISK_TOTAL='true'
- B_SHOW_GRAPHICS='true'
- B_SHOW_INFO='true'
- B_SHOW_MACHINE='true'
- B_SHOW_BATTERY='true'
- B_SHOW_NETWORK='true'
- B_SHOW_SYSTEM='true'
- ;;
- B) B_SHOW_BATTERY_FORCED='true'
- B_SHOW_BATTERY='true'
- use_short='false'
- ;;
- c) if [[ $OPTARG =~ ^[0-9][0-9]?$ ]];then
- case $OPTARG in
- 99)
- B_RUN_COLOR_SELECTOR='true'
- COLOR_SELECTION='global'
- ;;
- 98)
- B_RUN_COLOR_SELECTOR='true'
- COLOR_SELECTION='irc-console'
- ;;
- 97)
- B_RUN_COLOR_SELECTOR='true'
- COLOR_SELECTION='irc-virtual-terminal'
- ;;
- 96)
- B_RUN_COLOR_SELECTOR='true'
- COLOR_SELECTION='irc'
- ;;
- 95)
- B_RUN_COLOR_SELECTOR='true'
- COLOR_SELECTION='virtual-terminal'
- ;;
- 94)
- B_RUN_COLOR_SELECTOR='true'
- COLOR_SELECTION='console'
- ;;
- *)
- B_COLOR_SCHEME_SET='true'
- ## note: not sure about this, you'd think user values should be overridden, but
- ## we'll leave this for now
- if [[ -z $COLOR_SCHEME ]];then
- set_color_scheme "$OPTARG"
- fi
- ;;
- esac
- else
- error_handler 3 "$OPTARG"
- fi
- ;;
- C) B_SHOW_CPU='true'
- use_short='false'
- ;;
- d) B_SHOW_DISK='true'
- B_SHOW_FULL_OPTICAL='true'
- use_short='false'
- # error_handler 20 "-d has been replaced by -b"
- ;;
- D) B_SHOW_DISK='true'
- use_short='false'
- ;;
- f) B_SHOW_CPU='true'
- B_CPU_FLAGS_FULL='true'
- use_short='false'
- ;;
- F) # B_EXTRA_DATA='true'
- B_SHOW_ADVANCED_NETWORK='true'
- B_SHOW_AUDIO='true'
- # B_SHOW_BASIC_OPTICAL='true'
- B_SHOW_CPU='true'
- B_SHOW_DISK='true'
- B_SHOW_GRAPHICS='true'
- B_SHOW_INFO='true'
- B_SHOW_MACHINE='true'
- B_SHOW_BATTERY='true'
- B_SHOW_NETWORK='true'
- B_SHOW_PARTITIONS='true'
- B_SHOW_RAID='true'
- B_SHOW_SENSORS='true'
- B_SHOW_SYSTEM='true'
- use_short='false'
- ;;
- G) B_SHOW_GRAPHICS='true'
- use_short='false'
- ;;
- i) B_SHOW_IP='true'
- B_SHOW_NETWORK='true'
- B_SHOW_ADVANCED_NETWORK='true'
- use_short='false'
- ;;
- I) B_SHOW_INFO='true'
- use_short='false'
- ;;
- l) B_SHOW_LABELS='true'
- B_SHOW_PARTITIONS='true'
- use_short='false'
- ;;
- m) B_SHOW_MEMORY='true'
- use_short='false'
- ;;
- M) B_SHOW_MACHINE='true'
- use_short='false'
- ;;
- n) B_SHOW_ADVANCED_NETWORK='true'
- B_SHOW_NETWORK='true'
- use_short='false'
- ;;
- N) B_SHOW_NETWORK='true'
- use_short='false'
- ;;
- o) B_SHOW_UNMOUNTED_PARTITIONS='true'
- use_short='false'
- ;;
- p) B_SHOW_PARTITIONS_FULL='true'
- B_SHOW_PARTITIONS='true'
- use_short='false'
- ;;
- P) B_SHOW_PARTITIONS='true'
- use_short='false'
- ;;
- r) B_SHOW_REPOS='true'
- use_short='false'
- ;;
- R) B_SHOW_RAID='true'
- # it turns out only users with mdraid software installed will have raid,
- # so unless -R is explicitly called, blank -b/-F/-v6 and less output will not show
- # error if file is missing.
- B_SHOW_RAID_R='true'
- use_short='false'
- ;;
- s) B_SHOW_SENSORS='true'
- use_short='false'
- ;;
- S) B_SHOW_SYSTEM='true'
- use_short='false'
- ;;
- t) if [[ $OPTARG =~ ^(c|m|cm|mc)([1-9]|1[0-9]|20)?$ ]];then
- use_short='false'
- if [[ -n $( grep -E '[0-9]+' <<< $OPTARG ) ]];then
- PS_COUNT=$( sed 's/[^0-9]//g' <<< $OPTARG )
- fi
- if [[ -n $( grep 'c' <<< $OPTARG ) ]];then
- B_SHOW_PS_CPU_DATA='true'
- fi
- if [[ -n $( grep 'm' <<< $OPTARG ) ]];then
- B_SHOW_PS_MEM_DATA='true'
- fi
- else
- error_handler 13 "$OPTARG"
- fi
- ;;
- u) B_SHOW_UUIDS='true'
- B_SHOW_PARTITIONS='true'
- use_short='false'
- ;;
- v) if [[ $OPTARG =~ ^[0-9][0-9]?$ && $OPTARG -le $VERBOSITY_LEVELS ]];then
- if [[ $OPTARG -ge 1 ]];then
- use_short='false'
- B_SHOW_BASIC_CPU='true'
- B_SHOW_DISK_TOTAL='true'
- B_SHOW_GRAPHICS='true'
- B_SHOW_INFO='true'
- B_SHOW_SYSTEM='true'
- fi
- if [[ $OPTARG -ge 2 ]];then
- B_SHOW_BASIC_DISK='true'
- B_SHOW_BASIC_RAID='true'
- B_SHOW_BATTERY='true'
- B_SHOW_MACHINE='true'
- B_SHOW_NETWORK='true'
- fi
- if [[ $OPTARG -ge 3 ]];then
- B_SHOW_ADVANCED_NETWORK='true'
- B_SHOW_CPU='true'
- B_EXTRA_DATA='true'
- fi
- if [[ $OPTARG -ge 4 ]];then
- B_SHOW_DISK='true'
- B_SHOW_PARTITIONS='true'
- fi
- if [[ $OPTARG -ge 5 ]];then
- B_SHOW_AUDIO='true'
- B_SHOW_BASIC_OPTICAL='true'
- B_SHOW_MEMORY='true'
- B_SHOW_SENSORS='true'
- B_SHOW_LABELS='true'
- B_SHOW_UUIDS='true'
- B_SHOW_RAID='true'
- fi
- if [[ $OPTARG -ge 6 ]];then
- B_SHOW_FULL_OPTICAL='true'
- B_SHOW_PARTITIONS_FULL='true'
- B_SHOW_UNMOUNTED_PARTITIONS='true'
- B_EXTRA_EXTRA_DATA='true'
- fi
- if [[ $OPTARG -ge 7 ]];then
- B_EXTRA_EXTRA_EXTRA_DATA='true'
- B_SHOW_IP='true'
- B_SHOW_RAID_R='true'
- fi
- else
- error_handler 4 "$OPTARG"
- fi
- ;;
- U) if [[ $B_ALLOW_UPDATE == 'true' ]];then
- self_updater "$SELF_DOWNLOAD" 'source server' "$opt"
- else
- error_handler 17 "-$opt"
- fi
- ;;
- V) show_version_info
- exit 0
- ;;
- w) B_SHOW_WEATHER=true
- use_short='false'
- ;;
- W) ALTERNATE_WEATHER_LOCATION=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< $OPTARG )
- if [[ -n $( grep -Esi '([^,]+,.+|[0-9-]+)' <<< $ALTERNATE_WEATHER_LOCATION ) ]];then
- B_SHOW_WEATHER=true
- use_short='false'
- else
- error_handler 18 "-$opt: '$OPTARG'" "city,state OR latitude,longitude OR postal/zip code."
- fi
- ;;
- # this will trigger either with x, xx, xxx or with Fx but not with xF
- x) if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- B_EXTRA_EXTRA_EXTRA_DATA='true'
- elif [[ $B_EXTRA_DATA == 'true' ]];then
- B_EXTRA_EXTRA_DATA='true'
- else
- B_EXTRA_DATA='true'
- fi
- ;;
- y) if [[ -z ${OPTARG//[0-9]/} && $OPTARG -ge 80 ]];then
- set_display_width "$OPTARG"
- else
- error_handler 21 "$OPTARG"
- fi
- ;;
- z) B_OUTPUT_FILTER='true'
- ;;
- Z) B_OVERRIDE_FILTER='true'
- ;;
- h) show_options
- exit 0
- ;;
- H) show_options 'full'
- exit 0
- ;;
- ## debuggers and testing tools
- %) B_HANDLE_CORRUPT_DATA='true'
- ;;
- @) if [[ -n $( grep -E "^([1-9]|1[0-5])$" <<< $OPTARG ) ]];then
- DEBUG=$OPTARG
- if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- B_UPLOAD_DEBUG_DATA='true'
- fi
- exec 2>&1
- # switch on logging only for -@ 8-10
- case $OPTARG in
- 8|9|10)
- if [[ $OPTARG -eq 10 ]];then
- B_LOG_COLORS='true'
- elif [[ $OPTARG -eq 9 ]];then
- B_LOG_FULL_DATA='true'
- fi
- B_USE_LOGGING='true'
- # pack the logging data for evals function start/end
- LOGFS=$LOGFS_STRING
- LOGFE=$LOGFE_STRING
- create_rotate_logfiles # create/rotate logfiles before we do anything else
- ;;
- 11|12|13|14|15)
- case $OPTARG in
- 11)
- debug_data_type='sys'
- ;;
- 12)
- debug_data_type='xorg'
- ;;
- 13)
- debug_data_type='disk'
- ;;
- 14)
- debug_data_type='all'
- ;;
- 15)
- debug_data_type='all'
- B_DEBUG_I='true'
- ;;
- esac
- initialize_data
- debug_data_collector $debug_data_type
- ;;
- esac
- else
- error_handler 9 "$OPTARG"
- fi
- ;;
- !) # test for various supported methods
- case $OPTARG in
- 1) B_TESTING_1='true'
- ;;
- 2) B_TESTING_2='true'
- ;;
- 3) B_TESTING_1='true'
- B_TESTING_2='true'
- ;;
- 1[0-3]|http*)
- if [[ $B_ALLOW_UPDATE == 'true' ]];then
- case $OPTARG in
- 10)
- self_updater "$SELF_DOWNLOAD_DEV" 'dev server' "$opt $OPTARG"
- B_MAN='false'
- ;;
- 11)
- self_updater "$SELF_DOWNLOAD_BRANCH_1" 'branch one server' "$opt $OPTARG"
- B_MAN='false'
- ;;
- 12)
- self_updater "$SELF_DOWNLOAD_BRANCH_2" 'branch two server' "$opt $OPTARG"
- B_MAN='false'
- ;;
- 13)
- self_updater "$SELF_DOWNLOAD_BRANCH_3" 'branch three server' "$opt $OPTARG"
- B_MAN='false'
- ;;
- http*)
- self_updater "$OPTARG" 'alt server' "$opt <http...>"
- B_MAN='false'
- ;;
- esac
- else
- error_handler 17 "-$opt $OPTARG"
- fi
- ;;
- 30)
- B_IRC='false'
- ;;
- 31)
- B_SHOW_HOST='false'
- ;;
- 32)
- B_SHOW_HOST='true'
- ;;
- 33)
- B_FORCE_DMIDECODE='true'
- ;;
- 34)
- NO_SSL_OPT=$NO_SSL
- ;;
- 40*)
- DISPLAY=${OPTARG/40/}
- if [[ $DISPLAY == '' ]];then
- DISPLAY=':0'
- fi
- DISPLAY_OPT="-display $DISPLAY"
- B_SHOW_DISPLAY_DATA='true'
- B_RUNNING_IN_DISPLAY='true'
- ;;
- 41)
- B_CURL='false'
- set_downloader
- ;;
- 42)
- B_FETCH='false'
- set_downloader
- ;;
- 43)
- B_WGET='false'
- set_downloader
- ;;
- 44)
- B_CURL='false'
- B_FETCH='false'
- B_WGET='false'
- set_downloader
- ;;
- ftp*)
- ALTERNATE_FTP="$OPTARG"
- ;;
- # for weather function, allows user to set an alternate weather location
- location=*)
- error_handler 19 "-$opt location=" "-W"
- ;;
- *) error_handler 11 "$OPTARG"
- ;;
- esac
- ;;
- *) error_handler 7 "$1"
- ;;
- esac
- done
- fi
- ## this must occur here so you can use the debugging flag to show errors
- ## Reroute all error messages to the bitbucket (if not debugging)
- if [[ $DEBUG -eq 0 ]];then
- exec 2>/dev/null
- fi
- #((DEBUG)) && exec 2>&1 # This is for debugging konversation
-
- # after all the args have been processed, if no long output args used, run short output
- if [[ $use_short == 'true' ]];then
- B_SHOW_SHORT_OUTPUT='true'
- fi
- # just in case someone insists on using -zZ
- if [[ $B_OVERRIDE_FILTER == 'true' ]];then
- B_OUTPUT_FILTER='false'
- fi
- # change basic to full if user requested it or if arg overrides it
- if [[ $B_SHOW_RAID == 'true' && $B_SHOW_BASIC_RAID == 'true' ]];then
- B_SHOW_BASIC_RAID='false'
- fi
-
-
- eval $LOGFE
+ if ( $b_weather ){
+ @rows = (
+ ['1', '-w', '--weather', "Local weather data/time. To check an alternate
+ location, see -W."],
+ ['1', '-W', '--weather-location', "<location> Supported options for
+ <location>: postal code; city, state/country; latitude, longitude.
+ Only use if you want the weather somewhere other than the machine running
+ $self_name. Use only ASCII characters, replace spaces in city/state/country names with '+'.
+ Example:^$self_name^-W^new+york,ny"]
+ );
+ push @data, @rows;
+ }
+ @rows = (
+ ['1', '-x', '-extra', "Adds the following extra data (only works with
+ verbose or line output, not short form):" ],
+ ['2', '-B', '', "Vendor/model, status (if available)." ],
+ ['2', '-C', '', "CPU $flags, Bogomips on CPU; CPU microarchitecture +
+ revision (if found)." ],
+ ['2', '-d', '', "Extra optical drive features data; adds rev version to
+ optical drive." ],
+ ['2', '-D', '', "HDD temp with disk data if you have hddtemp installed, if
+ you are root, or if you have added to /etc/sudoers (sudo v. 1.7 or newer).
+ Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp" ],
+ ['2', '-G', '', "Direct rendering status (in X); Screen number GPU is
+ running on (Nvidia only)." ],
+ ['2', '-i', '', "For IPv6, show additional scope addresses: Global, Site,
+ Temporary, Unknown. See --limit for large counts of IP addresses." ],
+ ['2', '-I', '', "Default system GCC. With -xx, also shows other installed
+ GCC versions. If running in shell, not in IRC client, shows shell version
+ number, if detected. Init/RC type and runlevel (if available)." ],
+ ['2', '-m', '', "Max memory module size (if available), device type." ],
+ ['2', '-N -A', '', "Version/port(s)/driver version (if available)." ],
+ ['2', '-N -A -G', '', "PCI Bus ID/USB ID number of card." ],
+ ['2', '-R', '', "md-raid: second RAID Info line with extra data:
+ blocks, chunk size, bitmap (if present). Resync line, shows blocks
+ synced/total blocks." ],
+ ['2', '-s', '', "Basic voltages (ipmi only): 12v, 5v, 3.3v, vbat." ],
+ ['2', '-S', '', "Desktop toolkit, if available (GNOME/Xfce/KDE only);
+ Kernel gcc version" ],
+ ['2', '-t', '', "Adds memory use output to CPU (-xt c), and CPU use to
+ memory (-xt m)." ],
+ ['2', '--usb', '', "For Devices, shows USB version/speed." ],
+ );
+ push @data, @rows;
+ if ( $b_weather ){
+ @rows = (['2', '-w -W', '', "Wind speed and direction, humidity, pressure,
+ and (-w only) time zone." ]);
+ push @data, @rows;
+ }
+ @rows = (
+ ['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', '-C', '', "Minimum CPU speed, if available." ],
+ ['2', '-D', '', "Disk serial number." ],
+ ['2', '-G', '', "Chip vendor:product ID for each video card; OpenGL
+ compatibility version, if free drivers and available; compositor (experimental)." ],
+ ['2', '-I', '', "Other detected installed gcc versions (if present). System
+ default runlevel. Adds parent program (or tty) for shell info if not in
+ IRC. Adds Init version number, RC (if found)." ],
+ ['2', '-m', '', "Manufacturer, part number; single/double bank (if found)." ],
+ ['2', '-M', '', "Chassis info, BIOS ROM size (dmidecode only), if available." ],
+ ['2', '-N', '', "Chip vendor:product ID for each NIC." ],
+ ['2', '-R', '', "md-raid: Superblock (if present), algorithm. If resync,
+ shows progress bar." ],
+ ['2', '-s', '', "DIMM/SOC voltages (ipmi only)." ],
+ ['2', '-S', '', "Display manager (dm) in desktop output if in X (e.g. kdm,
+ gdm3, lightdm)." ],
+ ['2', '--slots', '', "Slot length." ],
+ ['2', '--usb', '', "Vendor:chip ID." ],
+ );
+ push @data, @rows;
+ if ( $b_weather ){
+ @rows = (['2', '-w -W', '', "Wind chill, dew point, heat index, if available." ]);
+ push @data, @rows;
+ }
+ @rows = (
+ ['1', '-xxx', '--extra 3', "Show extra, extra, extra data (only works
+ with verbose or line output, not short form):" ],
+ ['2', '-B', '', "Chemistry, cycles, location (if available)." ],
+ ['2', '-D', '', "Firmware rev. if available; partition scheme, in some cases." ],
+ ['2', '-I', '', "For 'Shell:' adds ([su|sudo|login]) to shell name if present;
+ for 'running in:' adds (SSH) if SSH session." ],
+ ['2', '-m', '', "Width of memory bus, data and total (if present and greater
+ than data); Detail for Type, if present; module voltage, if available; serial number." ],
+ ['2', '-R', '', "zfs-raid: portion allocated (used) by RAID devices/arrays.
+ md-raid: system md-raid support types (kernel support, read ahead, RAID events)." ],
+ ['2', '-S', '', "Panel/shell info in desktop output, if in X (like gnome-shell,
+ cinnamon, mate-panel); (if available) dm version number, active window manager." ]
+ );
+ push @data, @rows;
+ if ( $b_weather ){
+ @rows = (['2', '-w -W', '', "Location (uses -z/irc filter), weather observation
+ time, altitude (shows extra lines for data where relevant)." ] );
+ push @data, @rows;
+ }
+ @rows = (
+ ['1', '-y', '--width', "Output line width max (integer >= 80). Overrides IRC/Terminal
+ settings or actual widths. Example:^inxi^-y^130" ],
+ ['1', '-z', '--filter', "Adds security filters for IP/MAC addresses, serial numbers,
+ location (-w), user home directory name. Default on for IRC clients." ],
+ ['1', '-Z', '--filter-override', "Absolute override for output filters. Useful for
+ debugging networking issues in IRC, for example." ],
+ [0, '', '', "$line" ],
+ [0, '', '', "Additional Options:" ],
+ ['1', '-h', '--help', "This help menu." ],
+ ['1', '', '--recommends', "Checks $self_name application dependencies + recommends,
+ and directories, then shows what package(s) you need to install to add support
+ for that feature." ]
+ );
+ push @data, @rows;
+ if ( $b_update ){
+ @rows = (
+ ['1', '-U', '--update', "Auto-update $self_name. Will also install/update man
+ page. Note: if you installed as root, you must be root to update, otherwise
+ user is fine. Man page installs require root. No arguments downloads from
+ main $self_name git repo." ],
+ ['1', '', '', "Use alternate sources for updating $self_name" ],
+ ['2', '1', '', "Get the git branch one version." ],
+ ['2', '2', '', "Get the git branch two version." ],
+ ['3', '3', '', "Get the dev server (smxi.org) version." ],
+ ['2', '<http>', '', "Get a version of $self_name from your own server;
+ use the full download path, e.g.^$self_name^-U^https://myserver.com/inxi" ]
+ );
+ push @data, @rows;
+ }
+ @rows = (
+ ['1', '-V', '--version', "Prints $self_name version info then exits." ],
+ [0, '', '', "$line" ],
+ [0, '', '', "Debugging Options:" ],
+ ['1', '', '--debug', "Triggers debugging modes." ],
+ ['2', '1-3', '', "On screen debugger output." ],
+ ['2', '10', '', "Basic logging." ],
+ ['2', '11', '', "Full file/system info logging." ],
+ ['1', '', ,'', "The following create a tar.gz file of system data, plus $self_name
+ output. To automatically upload debugger data tar.gz file
+ to ftp.techpatterns.com: $self_name^--debug^21" ],
+ ['2', '20', '', "Full system data collection: /sys; xorg conf and log data, xrandr,
+ xprop, xdpyinfo, glxinfo etc.; data from dev, disks,
+ ${partition_string}s, etc." ],
+ ['2', '21', '', "Upload debugger dataset to $self_name debugger server
+ automatically, removes debugger data directory, leaves tar.gz debugger file." ],
+ ['2', '22', '', "Upload debugger dataset to $self_name debugger server
+ automatically, removes debugger data directory and debugger tar.gz file." ],
+ ['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.
+ Example:^$self_name^--debug^21^--ftp^ftp.myserver.com/incoming" ],
+ [0, '', '', "$line" ],
+ [0, '', '', "Advanced Options:" ],
+ [1, '', '--alt', "Trigger for various advanced options:" ],
+ ['2', '40', '', "Bypass Perl as a downloader option." ],
+ ['2', '41', '', "Bypass Curl as a downloader option." ],
+ ['2', '42', '', "Bypass Fetch as a downloader option." ],
+ ['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', '', '--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', '', '--host', "Turn on hostname for -S." ],
+ ['1', '', '--indent-min', "Set point where $self_name autowraps line starters." ],
+ ['1', '', '--limit', "[-1; 1-x] Set max output limit of IP addresses for -i
+ (default 10; -1 removes limit)." ],
+ );
+ push @data, @rows;
+ if ( $b_update ){
+ @rows = (
+ ['1', '', '--man', "Install correct man version for dev branch (-U 3) or pinxi using -U." ],
+ );
+ push @data, @rows;
+ }
+ @rows = (
+ ['1', '', '--no-host', "Turn off hostname for -S. Useful if showing output from servers etc." ],
+ );
+ push @data, @rows;
+ if ( $b_update ){
+ @rows = (
+ ['1', '', '--no-man', "Disable man install for all -U update actions." ],
+ );
+ push @data, @rows;
+ }
+ @rows = (
+ ['1', '', '--no-ssl', "Skip SSL certificate checks for all downloader actions
+ (Wget/Fetch/Curl only)." ],
+ ['1', '', '--output', "[json|screen|xml] Change data output type. Requires --output-file
+ if not screen." ],
+ ['1', '', '--output-file', "[Full filepath|print] Output file to be used for --output." ],
+ ['1', '', '--sleep', "[0-x.x] Change CPU sleep time, in seconds, for -C
+ (default:^$cpu_sleep). Allows system to catch up and show a more accurate CPU
+ use. Example:^$self_name^-Cxxx^--sleep^0.15" ],
+ ['0', '', '', $line ],
+ );
+ push @data, @rows;
+ print_basic(@data);
+ exit 1;
}
-## print out help menu, not including Testing or Debugger stuff because it's not needed
-show_options()
-{
- local color_scheme_count=$(( ${#A_COLOR_SCHEMES[@]} - 1 ))
- local partition_string='partition' partition_string_u='Partition'
-
- if [[ $B_IRC == 'true' ]];then
- print_screen_output "Sorry, you can't run the help option in an IRC client."
- exit 1
- fi
- if [[ -n $BSD_TYPE ]];then
- partition_string='slice'
- partition_string_u='Slice'
- fi
- # print_lines_basic "0" "" ""
- # print_lines_basic "1" "" ""
- # print_lines_basic "2" "" ""
- # print_screen_output " "
- print_lines_basic "0" "" "$SELF_NAME supports the following options. You can combine them, or list them one by one. Examples: $SELF_NAME^-v4^-c6 OR $SELF_NAME^-bDc^6. If you start $SELF_NAME with no arguments, it will show the short form."
- print_screen_output " "
- print_lines_basic "0" "" "The following options if used without -F, -b, or -v will show just option line(s): A, B, C, D, G, I, M, N, P, R, S, f, i, m, n, o, p, l, u, r, s, t - you can use these alone or together to show just the line(s) you want to see. If you use them with -v^[level], -b or -F, it will show the full output for that line along with the output for the chosen verbosity level."
- print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
- print_screen_output "Output Control Options:"
- print_lines_basic "1" "-A" "Audio/sound card information."
- print_lines_basic "1" "-b" "Basic output, short form. Like $SELF_NAME^-v^2, only minus hard disk names ."
- print_lines_basic "1" "-B" "Battery info, shows charge, condition, plus extra information (if battery present)."
- print_lines_basic "1" "-c" "Color schemes. Scheme number is required. Color selectors run a color selector option prior to $SELF_NAME starting which lets you set the config file value for the selection."
- print_lines_basic "1" "" "Supported color schemes: 0-$color_scheme_count Example:^$SELF_NAME^-c^11"
- print_lines_basic "1" "" "Color selectors for each type display (NOTE: irc and global only show safe color set):"
-# print_screen_output " Supported color schemes: 0-$color_scheme_count Example: $SELF_NAME -c 11"
-# print_screen_output " Color selectors for each type display (NOTE: irc and global only show safe color set):"
- print_lines_basic "2" "94" "Console, out of X"
- print_lines_basic "2" "95" "Terminal, running in X - like xTerm"
- print_lines_basic "2" "96" "Gui IRC, running in X - like Xchat, Quassel, Konversation etc."
- print_lines_basic "2" "97" "Console IRC running in X - like irssi in xTerm"
- print_lines_basic "2" "98" "Console IRC not in X"
- print_lines_basic "2" "99" "Global - Overrides/removes all settings. Setting specific removes global."
- print_lines_basic "1" "-C" "CPU output, including per CPU clockspeed and max CPU speed (if available)."
- print_lines_basic "1" "-d" "Optical drive data (and floppy disks, if present). Same as -Dd. See also -x and -xx."
- print_lines_basic "1" "-D" "Full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB. See also -x and -xx. Disk total used percentage includes swap partition size(s)."
- print_lines_basic "1" "-f" "All cpu flags, triggers -C. Not shown with -F to avoid spamming. ARM cpus show 'features'."
- print_lines_basic "1" "-F" "Full output for $SELF_NAME. Includes all Upper Case line letters, plus -s and -n. Does not show extra verbose options like -d -f -l -m -o -p -r -t -u -x"
- print_lines_basic "1" "-G" "Graphic card information (card, display server type/version, resolution, renderer, OpenGL version)."
- print_lines_basic "1" "-i" "Wan IP address, and shows local interfaces (requires ifconfig
- network tool). Same as -Nni. Not shown with -F for user security reasons, you shouldn't paste your local/wan IP."
- print_lines_basic "1" "-I" "Information: processes, uptime, memory, irc client (or shell type), $SELF_NAME version."
- print_lines_basic "1" "-l" "$partition_string_u labels. Default: short $partition_string -P. For full -p output, use: -pl (or -plu)."
- print_lines_basic "1" "-m" "Memory (RAM) data. Physical system memory array(s), capacity, how many devices (slots) supported, and individual memory devices (sticks of memory etc). For devices, shows device locator, size, speed, type (like: DDR3). If neither -I nor -tm are selected, also shows ram used/total. Also see -x, -xx, -xxx"
- print_lines_basic "1" "-M" "Machine data. Device type (desktop, server, laptop, VM etc.), Motherboard, Bios, and if present, System Builder (Like Lenovo). Shows UEFI/BIOS/UEFI [Legacy]. Older systems/kernels without the required /sys data can use dmidecode instead, run as root. Dmidecode can be forced with -! 33"
- print_lines_basic "1" "-n" "Advanced Network card information. Same as -Nn. Shows interface, speed, mac id, state, etc."
- print_lines_basic "1" "-N" "Network card information. With -x, shows PCI BusID, Port number."
- print_lines_basic "1" "-o" "Unmounted $partition_string information (includes UUID and LABEL if available). Shows file system type if you have file installed, if you are root OR if you have added to /etc/sudoers (sudo v. 1.7 or newer) Example:^<username>^ALL^=^NOPASSWD:^/usr/bin/file^"
- print_lines_basic "1" "-p" "Full $partition_string information (-P plus all other detected ${partition_string}s)."
- print_lines_basic "1" "-P" "Basic $partition_string information (shows what -v^4 would show, but without extra data). Shows, if detected: / /boot /home /opt /tmp /usr /var /var/log /var/tmp . Use -p to see all mounted ${partition_string}s."
- print_lines_basic "1" "-r" "Distro repository data. Supported repo types: APK; APT; PACMAN; PISI; PORTAGE; PORTS (BSDs); SLACKPKG; URPMQ; YUM; ZYPP."
- print_lines_basic "1" "-R" "RAID data. Shows RAID devices, states, levels, and components, and extra data with -x/-xx. md-raid: If device is resyncing, shows resync progress line as well."
- print_lines_basic "1" "-s" "Sensors output (if sensors installed/configured): mobo/cpu/gpu temp; detected fan speeds. Gpu temp only for Fglrx/Nvidia drivers. Nvidia shows screen number for > 1 screens."
- print_lines_basic "1" "-S" "System information: host name, kernel, desktop environment (if in X), distro"
- print_lines_basic "1" "-t" "Processes. Requires extra options: c^(cpu) m^(memory) cm^(cpu+memory). If followed by numbers 1-20, shows that number of processes for each type (default:^$PS_COUNT; if in irc, max:^5): -t^cm10"
- print_lines_basic "1" "" "Make sure to have no space between letters and numbers (-t^cm10 - right, -t^cm^10 - wrong)."
- print_lines_basic "1" "-u" "$partition_string_u UUIDs. Default: short $partition_string -P. For full -p output, use: -pu (or -plu)."
- print_lines_basic "1" "-v" "Script verbosity levels. Verbosity level number is required. Should not be used with -b or -F"
- print_lines_basic "1" "" "Supported levels: 0-$VERBOSITY_LEVELS Example: $SELF_NAME^-v^4"
- print_lines_basic "2" "0" "Short output, same as: $SELF_NAME"
- print_lines_basic "2" "1" "Basic verbose, -S + basic CPU + -G + basic Disk + -I."
- print_lines_basic "2" "2" "Networking card (-N), Machine (-M) data, if present, Battery (-B), basic hard disk data (names only), and, if present, basic raid (devices only, and if inactive, notes that). similar to: $SELF_NAME^-b"
- print_lines_basic "2" "3" "Advanced CPU (-C), battery, network (-n) data, and switches on -x advanced data option."
- print_lines_basic "2" "4" "$partition_string_u size/filled data (-P) for (if present): /, /home, /var/, /boot. Shows full disk data (-D)."
- print_lines_basic "2" "5" "Audio card (-A); sensors^(-s), memory/ram^(-m), $partition_string label^(-l) and UUID^(-u), short form of optical drives, standard raid data (-R)."
- print_lines_basic "2" "6" "Full $partition_string (-p), unmounted $partition_string (-o), optical drive (-d), full raid; triggers -xx."
- print_lines_basic "2" "7" "Network IP data (-i); triggers -xxx."
-
- # if distro maintainers don't want the weather feature disable it
- if [[ $B_ALLOW_WEATHER == 'true' ]];then
- print_lines_basic "1" "-w" "Local weather data/time. To check an alternate location, see: -W^<location>. For extra weather data options see -x, -xx, and -xxx."
- print_lines_basic "1" "-W" "<location> Supported options for <location>: postal code; city, state/country; latitude, longitude. Only use if you want the weather somewhere other than the machine running $SELF_NAME. Use only ascii characters, replace spaces in city/state/country names with '+'. Example:^$SELF_NAME^-W^new+york,ny"
- fi
- print_lines_basic "1" "-x" "Adds the following extra data (only works with verbose or line output, not short form):"
- print_lines_basic "2" "-B" "Vendor/model, status (if available)"
- print_lines_basic "2" "-C" "CPU Flags, Bogomips on Cpu;CPU microarchitecture / revision if found, like: (Sandy Bridge rev.2)"
- print_lines_basic "2" "-d" "Extra optical drive data; adds rev version to optical drive."
- print_lines_basic "2" "-D" "Hdd temp with disk data if you have hddtemp installed, if you are root OR if you have added to /etc/sudoers (sudo v. 1.7 or newer) Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp"
- print_lines_basic "2" "-G" "Direct rendering status for Graphics (in X)."
- print_lines_basic "2" "-G" "(for single gpu, nvidia driver) screen number gpu is running on."
- print_lines_basic "2" "-i" "For IPv6, show additional IP v6 scope addresses: Global, Site, Temporary, Unknown."
- print_lines_basic "2" "-I" "System GCC, default. With -xx, also show other installed GCC versions. If running in console, not in IRC client, shows shell version number, if detected. Init/RC Type and runlevel (if available)."
- print_lines_basic "2" "-m" "Part number; Max memory module size (if available)."
- print_lines_basic "2" "-N -A" "Version/port(s)/driver version (if available) for Network/Audio;"
- print_lines_basic "2" "-N -A -G" "Network, audio, graphics, shows PCI Bus ID/Usb ID number of card."
- print_lines_basic "2" "-R" "md-raid: Shows component raid id. Adds second RAID Info line: raid level; report on drives (like 5/5); blocks; chunk size; bitmap (if present). Resync line, shows blocks synced/total blocks. zfs-raid: Shows raid array full size; available size; portion allocated to RAID"
- print_lines_basic "2" "-S" "Desktop toolkit if available (GNOME/XFCE/KDE only); Kernel gcc version"
- print_lines_basic "2" "-t" "Memory use output to cpu (-xt c), and cpu use to memory (-xt m)."
- if [[ $B_ALLOW_WEATHER == 'true' ]];then
- print_lines_basic "2" "-w -W" "Wind speed and time zone (-w only)."
- fi
- print_lines_basic "1" "-xx" "Show extra, extra data (only works with verbose or line output, not short form):"
- print_lines_basic "2" "-A" "Chip vendor:product ID for each audio device."
- print_lines_basic "2" "-B" "serial number, voltage (if available)."
- print_lines_basic "2" "-C" "Minimum CPU speed, if available."
- print_lines_basic "2" "-D" "Disk serial number; Firmware rev. if available."
- print_lines_basic "2" "-G" "Chip vendor:product ID for each video card; (mir/wayland only) compositor (alpha test); OpenGL compatibility version, if free drivers and available."
- print_lines_basic "2" "-I" "Other detected installed gcc versions (if present). System default runlevel. Adds parent program (or tty) for shell info if not in IRC (like Konsole or Gterm). Adds Init/RC (if found) version number."
- print_lines_basic "2" "-m" "Manufacturer, Serial Number, single/double bank (if found)."
- print_lines_basic "2" "-M" "Chassis information, bios rom size (dmidecode only), if data for either is available."
- print_lines_basic "2" "-N" "Chip vendor:product ID for each nic."
- print_lines_basic "2" "-R" "md-raid: Superblock (if present); algorythm, U data. Adds system info line (kernel support,read ahead, raid events). If present, adds unused device line. Resync line, shows progress bar."
- print_lines_basic "2" "-S" "Display manager (dm) in desktop output, if in X (like kdm, gdm3, lightdm)."
- if [[ $B_ALLOW_WEATHER == 'true' ]];then
- print_lines_basic "2" "-w -W" "Humidity, barometric pressure."
- fi
- print_lines_basic "2" "-@ 11-14" "Automatically uploads debugger data tar.gz file to ftp.techpatterns.com. EG: $SELF_NAME^-xx@14"
- print_lines_basic "1" "-xxx" "Show extra, extra, extra data (only works with verbose or line output, not short form):"
- print_lines_basic "2" "-B" "chemistry, cycles, location (if available)."
- print_lines_basic "2" "-m" "Width of memory bus, data and total (if present and greater than data); Detail, if present, for Type; module voltage, if available."
- print_lines_basic "2" "-S" "Panel/shell information in desktop output, if in X (like gnome-shell, cinnamon, mate-panel)."
- if [[ $B_ALLOW_WEATHER == 'true' ]];then
- print_lines_basic "2" "-w -W" "Location (uses -z/irc filter), weather observation time, wind chill, heat index, dew point (shows extra lines for data where relevant)."
- fi
- print_lines_basic "1" "-y" "Required extra option: integer, 80 or greater. Set the output line width max. Overrides IRC/Terminal settings or actual widths. If used with -h, put -y option first. Example:^inxi^-y^130"
- print_lines_basic "1" "-z" "Security filters for IP/Mac addresses, location, user home directory name. Default on for irc clients."
- print_lines_basic "1" "-Z" "Absolute override for output filters. Useful for debugging networking issues in irc for example."
- print_screen_output " "
- print_screen_output "Additional Options:"
- print_lines_basic "4" "-h --help" "This help menu."
- print_lines_basic "4" "-H" "This help menu, plus developer options. Do not use dev options in normal operation!"
- print_lines_basic "4" "--recommends" "Checks $SELF_NAME application dependencies + recommends, and directories, then shows what package(s) you need to install to add support for that feature. "
- if [[ $B_ALLOW_UPDATE == 'true' ]];then
- print_lines_basic "4" "-U" "Auto-update script. Will also install/update man page. Note: if you installed as root, you must be root to update, otherwise user is fine. Man page installs require root user mode."
- fi
- print_lines_basic "4" "-V --version" "$SELF_NAME version information. Prints information then exits."
- print_screen_output " "
- print_screen_output "Debugging Options:"
- print_lines_basic "1" "-%" "Overrides defective or corrupted data."
- print_lines_basic "1" "-@" "Triggers debugger output. Requires debugging level 1-14 (8-10 - logging of data). Less than 8 just triggers $SELF_NAME debugger output on screen."
- print_lines_basic "2" "1-7" "On screen debugger output"
- print_lines_basic "2" "8" "Basic logging"
- print_lines_basic "2" "9" "Full file/sys info logging"
- print_lines_basic "2" "10" "Color logging."
- print_lines_basic "1" "" "The following create a tar.gz file of system data, plus collecting the inxi output to file. To automatically upload debugger data tar.gz file to ftp.techpatterns.com: inxi^-xx@^<11-14>"
- print_lines_basic "1" "" "For alternate ftp upload locations: Example:^inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
- print_lines_basic "2" "11" "With data file of tree traverse read of /sys."
- print_lines_basic "2" "12" "With xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc."
- print_lines_basic "2" "13" "With data from dev, disks, ${partition_string}s, etc., plus /sys tree traverse data file."
- print_lines_basic "2" "14" "Everything, full data collection."
- print_screen_output " "
- print_screen_output "Advanced Options:"
- print_lines_basic "1" "-! 31" "Turns off hostname in output. Useful if showing output from servers etc."
- print_lines_basic "1" "-! 32" "Turns on hostname in output. Overrides global B_SHOW_HOST='false'"
- print_lines_basic "1" "-! 33" "Forces use of dmidecode data instead of /sys where relevant (-M)."
- print_lines_basic "1" "-! 34" "Skips SSL certificate checks for all downloader activies (wget/fetch/curl only). Must go before other options."
- print_lines_basic "1" "-! 40" "Will try to get display data out of X. Default gets it from display :0. If you use this format: -! 40:1 it would get it from display 1 instead, or any display you specify as long as there is no space between -! 40 and the :[display-number]."
- print_lines_basic "1" "-! 41" "Bypass curl as a downloader option."
- print_lines_basic "1" "-! 42" "Bypass fetch as a downloader option."
- print_lines_basic "1" "-! 43" "Bypass wget as a downloader option."
- print_lines_basic "1" "-! 44" "Bypass curl, fetch, and wget as a downloader options. Forces Perl if HTTP::Tiny present."
-
- if [[ $1 == 'full' ]];then
- print_screen_output " "
- print_screen_output "Developer and Testing Options (Advanced):"
- print_lines_basic "1" "-! 1" "Sets testing flag B_TESTING_1='true' to trigger testing condition 1."
- print_lines_basic "1" "-! 2" "Sets testing flag B_TESTING_2='true' to trigger testing condition 2."
- print_lines_basic "1" "-! 3" "Sets flags B_TESTING_1='true' and B_TESTING_2='true'."
- if [[ $B_ALLOW_UPDATE == 'true' ]];then
- print_lines_basic "1" "-! 10" "Triggers an update from the primary dev download server instead of source server."
- print_lines_basic "1" "-! 11" "Triggers an update from source branch one - if present, of course."
- print_lines_basic "1" "-! 12" "Triggers an update from source branch two - if present, of course."
- print_lines_basic "1" "-! 13" "Triggers an update from source branch three - if present, of course."
- print_lines_basic "1" "-! " "<http://......> Triggers an update from whatever server you list."
- print_lines_basic "1" "" "Example: inxi^-!^http://yourserver.com/testing/inxi"
- fi
- print_lines_basic "1" "-! " "<ftp.......> Changes debugging data ftp upload location to whatever you enter here. Only used together with -xx@^11-14, and must be used in front of that."
- print_lines_basic "1" "" "Example: inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
- fi
- print_screen_output " "
-}
-
-## print out version information for -V/--version
-show_version_info()
-{
+sub show_version {
+ require Cwd;
+ import Cwd;
# if not in PATH could be either . or directory name, no slash starting
- local script_path=$SELF_PATH script_symbolic_start=''
- if [[ $script_path == '.' ]];then
- script_path=$( pwd )
- elif [[ -z $( grep '^/' <<< "$script_path" ) ]];then
- script_path="$( pwd )/$script_path"
- fi
- # handle if it's a symbolic link, rare, but can happen with script directories in irc clients
- # which would only matter if user starts inxi with -! 30 override in irc client
- if [[ -L $script_path/$SELF_NAME ]];then
- script_symbolic_start=$script_path/$SELF_NAME
- script_path=$( readlink $script_path/$SELF_NAME )
- script_path=$( dirname $script_path )
- fi
- print_screen_output "$SELF_NAME $SELF_VERSION-$SELF_PATCH ($SELF_DATE)"
- if [[ $B_IRC == 'false' ]];then
- print_screen_output "Program Location: $script_path"
- if [[ -n $script_symbolic_start ]];then
- print_screen_output "Started via symbolic link: $script_symbolic_start"
- fi
- print_lines_basic "0" "" "Website:^https://github.com/smxi/inxi^or^http://smxi.org/"
- print_lines_basic "0" "" "IRC:^irc.oftc.net channel:^#smxi"
- print_lines_basic "0" "" "Forums:^http://techpatterns.com/forums/forum-33.html"
- print_screen_output " "
- print_lines_basic "0" "" "$SELF_NAME - the universal, portable, system information tool for console and irc."
- print_screen_output " "
- print_lines_basic "0" "" "This program started life as a fork of Infobash 3.02: Copyright^(C)^2005-2007^Michiel^de^Boer^a.k.a.^locsmif."
- print_lines_basic "0" "" "Subsequent changes and modifications (after Infobash 3.02): Copyright^(C)^2008-${SELF_DATE%%-*}^Harald^Hope^aka^h2. CPU/Konversation^fixes:^Scott^Rogers^aka^trash80. USB^audio^fixes:^Steven^Barrett^aka^damentz."
- print_screen_output " "
- print_lines_basic "0" "" "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. (http://www.gnu.org/licenses/gpl.html)"
- fi
+ my $working_path=$self_path;
+ my (@data, @row, @rows, $link, $self_string);
+ if ( $working_path eq '.' ){
+ $working_path = getcwd();
+ }
+ elsif ( $working_path !~ /^\// ){
+ $working_path = getcwd() . "/$working_path";
+ }
+ # handle if it's a symbolic link, rare, but can happen with directories
+ # in irc clients which would only matter if user starts inxi with -! 30 override
+ # in irc client
+ if ( -l "$working_path/$self_name" ){
+ $link="$working_path/$self_name";
+ $working_path = readlink "$working_path/$self_name";
+ $working_path =~ s/[^\/]+$//;
+ }
+ # strange output /./ ending, but just trim it off, I don't know how it happens
+ $working_path =~ s%/\./%/%;
+ @row = ([ 0, '', '', "$self_name $self_version-$self_patch ($self_date)"],);
+ push @data, @row;
+ if ( ! $b_irc ){
+ @row = ([ 0, '', '', ""],);
+ push @data, @row;
+ my $year = (split/-/, $self_date)[0];
+ @row = [ 0, '', '', "Program Location: $working_path" ];
+ push @data, @row;
+ if ( $link ){
+ @row = [ 0, '', '', "Started via symbolic link: $link" ];
+ push @data, @row;
+ }
+ @rows = (
+ [ 0, '', '', "Website:^https://github.com/smxi/inxi^or^https://smxi.org/" ],
+ [ 0, '', '', "IRC:^irc.oftc.net channel:^#smxi" ],
+ [ 0, '', '', "Forums:^https://techpatterns.com/forums/forum-33.html" ],
+ [ 0, '', '', " " ],
+ [ 0, '', '', "$self_name - the universal, portable, system information tool
+ for console and irc." ],
+ [ 0, '', '', "Using Perl version: $]"],
+ [ 0, '', '', " " ],
+ [ 0, '', '', "This program started life as a fork of Infobash 3.02:
+ Copyright^(C)^2005-2007^Michiel^de^Boer^aka^locsmif." ],
+ [ 0, '', '', "Subsequent changes and modifications (after Infobash 3.02):
+ Copyright^(C)^2008-$year^Harald^Hope^aka^h2.
+ CPU/Konversation^fixes:^Scott^Rogers^aka^trash80.
+ USB^audio^fixes:^Steven^Barrett^aka^damentz." ],
+ [ 0, '', '', '' ],
+ [ 0, '', '', "This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3 of the License, or (at your option) any later version.
+ (https://www.gnu.org/licenses/gpl.html)" ]
+ );
+ push @data, @rows;
+ }
+ print_basic(@data);
+ exit 1;
}
########################################################################
#### STARTUP DATA
########################################################################
-# This needs some cleanup and comments, not quite understanding what is
-# happening, although generally output is known. Parse the null
-# separated commandline under /proc/<pid passed in $1>/cmdline
-# args: $1 - $PPID
-get_cmdline()
-{
- eval $LOGFS
- local i=0 ppid=$1
-
- if [[ ! -e /proc/$ppid/cmdline ]];then
- echo 0
- return
- fi
- ##print_screen_output "Marker"
- ##print_screen_output "\$ppid='$ppid' -=- $(< /proc/$ppid/cmdline)"
- unset A_CMDL
- # http://transnum.blogspot.com/2008/11/bashs-read-built-in-supports-0-as.html
-# Because BASH internally uses C-style strings, in which '\0' is the terminator,
-# read -d $'\0' is essentially equivalent to read -d ''. This is why I believed
-# read did not accept null-delimited strings. However, it turns out that BASH
-# actually handles this correctly.
-# I checked BASH’s source code and found the delimiter was simply determined by
-# delim = *list_optarg; (bash-3.2/builtins/read.def, line 296) where list_optarg
-# points to the argument following -d. Therefore, it makes no difference to the
-# value of delim whether $'\0' or '' is used.
- ## note: need to figure this one out, and ideally clean it up and make it readable
- while read -d $'\0' L && [[ $i -lt 32 ]]
- do
- A_CMDL[i++]="$L" ## note: make sure this is valid - What does L mean? ##
- done < /proc/$ppid/cmdline
- ##print_screen_output "\$i='$i'"
- if [[ $i -eq 0 ]];then
- A_CMDL[0]=$(< /proc/$ppid/cmdline)
- if [[ -n ${A_CMDL[0]} ]];then
- i=1
- fi
- fi
- CMDL_MAX=$i
- log_function_data "CMDL_MAX: $CMDL_MAX"
- eval $LOGFE
-}
-
-# Determine where inxi was run from, set IRC_CLIENT and IRC_CLIENT_VERSION
-get_start_client()
-{
- eval $LOGFS
- local Irc_Client_Path='' irc_client_path_lower='' non_native_konvi='' i=''
- local B_Non_Native_App='false' pppid='' App_Working_Name=''
- local b_qt4_konvi='false' ps_parent=''
-
- if [[ $B_IRC == 'false' ]];then
- IRC_CLIENT='Shell'
- unset IRC_CLIENT_VERSION
- # elif [[ -n $PPID ]];then
- elif [[ -n $PPID && -f /proc/$PPID/exe ]];then
- if [[ $B_OVERRIDE_FILTER != 'true' ]];then
- B_OUTPUT_FILTER='true'
- fi
- Irc_Client_Path=$( readlink /proc/$PPID/exe )
- # Irc_Client_Path=$( ps -p $PPID | gawk '!/[[:space:]]*PID/ {print $5}' )
- # echo $( ps -p $PPID )
- if (( "$BASH" >= 4 ));then
- irc_client_path_lower=${Irc_Client_Path,,}
- else
- irc_client_path_lower=$( tr '[A-Z]' '[a-z]' <<< "$Irc_Client_Path" )
- fi
-
- App_Working_Name=${irc_client_path_lower##*/}
- # handles the xchat/sh/bash/dash cases, and the konversation/perl cases, where clients
- # report themselves as perl or unknown shell. IE: when konversation starts inxi
- # from inside itself, as a script, the parent is konversation/xchat, not perl/bash etc
- # note: perl can report as: perl5.10.0, so it needs wildcard handling
- case $App_Working_Name in
- # bsd will never use this section
- bash|dash|sh|python*|perl*) # We want to know who wrapped it into the shell or perl.
- if [[ $BSD_TYPE != 'bsd' ]];then
- pppid=$( ps -p $PPID -o ppid --no-headers 2>/dev/null | gawk '{print $NF}' )
- else
- # without --no-headers we need the second line
- pppid=$( ps -p $PPID -o ppid 2>/dev/null | gawk '$1 ~ /^[0-9]+/ {print $5}' )
- fi
- if [[ -n $pppid && -f /proc/$pppid/exe ]];then
- Irc_Client_Path="$( readlink /proc/$pppid/exe )"
- if (( "$BASH" >= 4 ));then
- irc_client_path_lower=${Irc_Client_Path,,}
- else
- irc_client_path_lower=$( tr '[A-Z]' '[a-z]' <<< "$Irc_Client_Path" )
- fi
- App_Working_Name=${irc_client_path_lower##*/}
- B_Non_Native_App='true'
- fi
- ;;
- esac
- # sets version number if it can find it
- get_irc_client_version
- else
- ## lets look to see if qt4_konvi is the parent. There is no direct way to tell, so lets infer it.
- ## because $PPID does not work with qt4_konvi, the above case does not work
- if [[ $B_OVERRIDE_FILTER != 'true' ]];then
- B_OUTPUT_FILTER='true'
- fi
- b_qt4_konvi=$( is_this_qt4_konvi )
- if [[ $b_qt4_konvi == 'true' ]];then
- KONVI=3
- IRC_CLIENT='Konversation'
- IRC_CLIENT_VERSION=" $( konversation -v | gawk '
- /Konversation:/ {
- for ( i=2; i<=NF; i++ ) {
- if (i == NF) {
- print $i
- }
- else {
- printf $i" "
- }
- }
- exit
- }' )"
- else
- # this should handle certain cases where it's ssh or some other startup tool
- # that falls through all the other tests. Also bsd irc clients will land here
- if [[ $BSD_TYPE != 'bsd' ]];then
- App_Working_Name=$(ps -p $PPID --no-headers 2>/dev/null | gawk '{print $NF}' )
- else
- # without --no-headers we need the second line
- App_Working_Name=$(ps -p $PPID 2>/dev/null | gawk '$1 ~ /^[0-9]+/ {print $5}' )
- fi
-
- if [[ -n $App_Working_Name ]];then
- Irc_Client_Path=$App_Working_Name
- if (( "$BASH" >= 4 ));then
- irc_client_path_lower=${Irc_Client_Path,,}
- else
- irc_client_path_lower=$( tr '[A-Z]' '[a-z]' <<< "$Irc_Client_Path" )
- fi
- App_Working_Name=${irc_client_path_lower##*/}
- B_Non_Native_App='false'
- get_irc_client_version
- if [[ -z $IRC_CLIENT ]];then
- IRC_CLIENT=$App_Working_Name
- fi
- else
- IRC_CLIENT="PPID=\"$PPID\" - empty?"
- unset IRC_CLIENT_VERSION
- fi
- fi
- fi
-
- log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID"
- eval $LOGFE
-}
-
-# note: all variables set in caller so no need to pass
-get_irc_client_version()
+# StartClient
{
- local file_data=''
- # replacing loose detection with tight detection, bugs will be handled with app names
- # as they appear.
- case $App_Working_Name in
- # check for shell first
- bash|dash|sh)
- unset IRC_CLIENT_VERSION
- IRC_CLIENT="Shell wrapper"
- ;;
- # now start on irc clients, alphabetically
- bitchx)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
- /Version/ {
- a=tolower($2)
- gsub(/[()]|bitchx-/,"",a)
- print a
- exit
- }
- $2 == "version" {
- a=tolower($3)
- sub(/bitchx-/,"",a)
- print a
- exit
- }' )"
- B_CONSOLE_IRC='true'
- IRC_CLIENT="BitchX"
- ;;
- finch)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $2
- }' )"
- B_CONSOLE_IRC='true'
- IRC_CLIENT="Finch"
- ;;
- gaim)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $2
- }' )"
- IRC_CLIENT="Gaim"
- ;;
- hexchat)
- # the hexchat author decided to make --version/-v return a gtk dialogue box, lol...
- # so we need to read the actual config file for hexchat. Note that older hexchats
- # used xchat config file, so test first for default, then legacy. Because it's possible
- # for this file to be user edited, doing some extra checks here.
- if [[ -f ~/.config/hexchat/hexchat.conf ]];then
- file_data="$( cat ~/.config/hexchat/hexchat.conf )"
- elif [[ -f ~/.config/hexchat/xchat.conf ]];then
- file_data="$( cat ~/.config/hexchat/xchat.conf )"
- fi
- if [[ -n $file_data ]];then
- IRC_CLIENT_VERSION=$( gawk '
- BEGIN {
- IGNORECASE=1
- FS="="
- }
- /^[[:space:]]*version/ {
- # get rid of the space if present
- gsub(/[[:space:]]*/, "", $2 )
- print $2
- exit # usually this is the first line, no point in continuing
- }' <<< "$file_data" )
-
- IRC_CLIENT_VERSION=" $IRC_CLIENT_VERSION"
- else
- IRC_CLIENT_VERSION=' N/A'
- fi
- IRC_CLIENT="HexChat"
- ;;
- ircii)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $3
- }' )"
- B_CONSOLE_IRC='true'
- IRC_CLIENT="ircII"
- ;;
- irssi|irssi-text)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $2
- }' )"
- B_CONSOLE_IRC='true'
- IRC_CLIENT="Irssi"
- ;;
- konversation) ## konvi < 1.2 (qt4)
- # this is necessary to avoid the dcop errors from starting inxi as a /cmd started script
- if [[ $B_Non_Native_App == 'true' ]];then ## true negative is confusing
- KONVI=2
- else # if native app
- KONVI=1
- fi
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
- /Konversation:/ {
- for ( i=2; i<=NF; i++ ) {
- if (i == NF) {
- print $i
- }
- else {
- printf $i" "
- }
+package StartClient;
+
+# use warnings;
+# use strict;
+
+my $ppid = '';
+my $pppid = '';
+
+# NOTE: there's no reason to crete an object, we can just access
+# the features statically.
+# args: none
+# sub new {
+# my $class = shift;
+# my $self = {};
+# # print "$f\n";
+# # print "$type\n";
+# return bless $self, $class;
+# }
+
+sub get_client_data {
+ eval $start if $b_log;
+ $ppid = getppid();
+ main::set_ps_aux() if ! @ps_aux;
+ if (!$b_irc){
+ main::get_shell_data($ppid);
+ }
+ else {
+ $show{'filter'} = 1;
+ get_client_name();
+ if ($client{'konvi'} == 1 || $client{'konvi'} == 3){
+ set_konvi_data();
+ }
+ }
+ eval $end if $b_log;
+}
+
+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 =~ s/^\s+|\s+$//g;
+ $client_name =~ s/[0-9\.]+$//; # clean things like python2.7
+ if ($pppid && -f "/proc/$pppid/exe" ){
+ $client_name = lc(readlink "/proc/$pppid/exe");
+ $client_name =~ s/^.*\///;
+ $client{'native'} = 0;
+ }
+ }
+ $client{'name'} = $client_name;
+ get_client_version();
+ # print "c:$client_name p:$pppid\n";
+ }
+ else {
+ if (! check_modern_konvi() ){
+ $ppid = getppid();
+ $client_name = (main::grabber("ps -p $ppid"))[1];
+ if ($client_name){
+ my @data = split /\s+/, $client_name if $client_name;
+ if ($bsd_type){
+ $client_name = lc($data[5]);
}
- exit
- }' )"
- T=($IRC_CLIENT_VERSION)
- if [[ ${T[0]} == *+* ]];then
- # < Sho_> locsmif: The version numbers of SVN versions look like this:
- # "<version number of last release>+ #<build number", i.e. "1.0+ #3177" ...
- # for releases we remove the + and build number, i.e. "1.0" or soon "1.0.1"
- IRC_CLIENT_VERSION=" CVS $IRC_CLIENT_VERSION"
- T2="${T[0]/+/}"
- else
- IRC_CLIENT_VERSION=" ${T[0]}"
- T2="${T[0]}"
- fi
- # Remove any dots except the first, and make sure there are no trailing zeroes,
- T2=$( echo "$T2" | gawk '{
- sub(/\./, " ")
- gsub(/\./, "")
- sub(/ /, ".")
- printf("%g\n", $0)
- }' )
- # Since Konversation 1.0, the DCOP interface has changed a bit: dcop "$DCPORT" Konversation ..etc
- # becomes : dcop "$DCPORT" default ... or dcop "$DCPORT" irc ..etc. So we check for versions smaller
- # than 1 and change the DCOP parameter/object accordingly.
- if [[ $T2 -lt 1 ]];then
- DCOPOBJ="Konversation"
- fi
- IRC_CLIENT="Konversation"
- ;;
- kopete)
- IRC_CLIENT_VERSION=" $( kopete -v | gawk '
- /Kopete:/ {
- print $2
- exit
- }' )"
- IRC_CLIENT="Kopete"
- ;;
- kvirc)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>&1 | gawk '{
- for ( i=2; i<=NF; i++) {
- if ( i == NF ) {
- print $i
- }
- else {
- printf $i" "
- }
+ # gnu/linux uses last value
+ else {
+ $client_name = lc($data[-1]);
}
- exit
- }' )"
- IRC_CLIENT="KVIrc"
- ;;
- pidgin)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $2
- }' )"
- IRC_CLIENT="Pidgin"
- ;;
- # possible failure of wildcard so make it explicit
- quassel*)
- # sample: quassel -v
- ## Qt: 4.5.0 - in Qt4 the output came from src/common/quassel.cpp
- # KDE: 4.2.65 (KDE 4.2.65 (KDE 4.3 >= 20090226))
- # Quassel IRC: v0.4.0 [+60] (git-22effe5)
- # note: early < 0.4.1 quassels do not have -v
- ## Qt: 5: sample: quassel -v
- # quassel v0.13-pre (0.12.0+5 git-8e2f578)
- # because in Qt5 the internal CommandLineParser is used
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>/dev/null | gawk '
- BEGIN {
- IGNORECASE=1
- clientVersion=""
- }
- # qt 4 -v syntax
- /^Quassel IRC:/ {
- clientVersion = $3
- }
- # qt 5 -v syntax
- /^quassel\s[v]?[0-9]/ {
- clientVersion = $2
- }
- END {
- # this handles pre 0.4.1 cases with no -v
- if ( clientVersion == "" ) {
- clientVersion = "(pre v0.4.1)?"
- }
- print clientVersion
- }' )"
- # now handle primary, client, and core. quasselcore doesn't actually
- # handle scripts with exec, but it's here just to be complete
- case $App_Working_Name in
- quassel)
- IRC_CLIENT="Quassel [M]"
- ;;
- quasselclient)
- IRC_CLIENT="Quassel"
- ;;
- quasselcore)
- IRC_CLIENT="Quassel (core)"
- ;;
- esac
- ;;
- gribble|limnoria|supybot)
- IRC_CLIENT_VERSION=" $( get_program_version 'supybot' '^Supybot' '2' )"
- if [[ -n $IRC_CLIENT_VERSION ]];then
- if [[ -n ${IRC_CLIENT_VERSION/*gribble*/} || $App_Working_Name == 'gribble' ]];then
- IRC_CLIENT="Gribble"
- elif [[ -n ${IRC_CLIENT_VERSION/*limnoria*/} || $App_Working_Name == 'limnoria' ]];then
- IRC_CLIENT="Limnoria"
- else
- IRC_CLIENT="Supybot"
- fi
- fi
- ;;
- weechat|weechat-curses)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v ) "
- B_CONSOLE_IRC='true'
- IRC_CLIENT="WeeChat"
- ;;
- xchat-gnome)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $2
- }' )"
- IRC_CLIENT="X-Chat-Gnome"
- ;;
- xchat)
- IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
- print $2
- }' )"
- IRC_CLIENT="X-Chat"
- ;;
- # then do some perl type searches, do this last since it's a wildcard search
- perl*|ksirc|dsirc)
- unset IRC_CLIENT_VERSION
- # KSirc is one of the possibilities now. KSirc is a wrapper around dsirc, a perl client
- get_cmdline $PPID
- for (( i=0; i <= $CMDL_MAX; i++ ))
- do
- case ${A_CMDL[i]} in
- *dsirc*)
- IRC_CLIENT="KSirc"
- # Dynamic runpath detection is too complex with KSirc, because KSirc is started from
- # kdeinit. /proc/<pid of the grandparent of this process>/exe is a link to /usr/bin/kdeinit
- # with one parameter which contains parameters separated by spaces(??), first param being KSirc.
- # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed,
- # dsirc is the program that runs inxi, therefore that is the parent process that we see.
- # You can imagine how hosed I am if I try to make inxi find out dynamically with which path
- # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material.
- # (KSirc sucks anyway ;)
- IRC_CLIENT_VERSION=" $( ksirc -v | gawk '
- /KSirc:/ {
- print $2
- exit
- }' )"
- break
- ;;
- esac
- done
- B_CONSOLE_IRC='true'
- set_perl_python_client_data "$App_Working_Name"
- ;;
- python*)
- # B_CONSOLE_IRC='true' # are there even any python type console irc clients? check.
- set_perl_python_client_data "$App_Working_Name"
- ;;
- # then unset, set unknown data
- *)
- IRC_CLIENT="Unknown : ${Irc_Client_Path##*/}"
- unset IRC_CLIENT_VERSION
- ;;
- esac
- if [[ $SHOW_IRC -lt 2 ]];then
- unset IRC_CLIENT_VERSION
- fi
+ $client_name =~ s/.*\|-(|)//;
+ $client_name =~ s/[0-9\.]+$//; # clean things like python2.7
+ $client{'name'} = $client_name;
+ $client{'native'} = 1;
+ get_client_version();
+ }
+ else {
+ $client{'name'} = "PPID='$ppid' - Empty?";
+ }
+ }
+ }
+ if ($b_log){
+ my $string = "Client: $client{'name'} :: version: $client{'version'} :: konvi: $client{'konvi'} :: PPID: $ppid";
+ main::log_data('data', $string);
+ }
+ eval $end if $b_log;
+}
+sub get_client_version {
+ eval $start if $b_log;
+ @app = main::program_values($client{'name'});
+ my (@data,@working,$string);
+ if (@app){
+ $string = ($client{'name'} =~ /^gribble|limnoria|supybot$/) ? 'supybot' : $client{'name'};
+ $client{'version'} = main::program_version($string,$app[0],$app[1],$app[2],$app[4],$app[5],$app[6]);
+ $client{'name-print'} = $app[3];
+ $client{'console-irc'} = $app[4];
+ }
+ if ($client{'name'} =~ /^bash|dash|sh$/ ){
+ $client{'name-print'} = 'shell wrapper';
+ $client{'console-irc'} = 1;
+ }
+ elsif ($client{'name'} eq 'bitchx') {
+ @data = main::grabber("$client{'name'} -v");
+ $string = awk(\@data,'Version');
+ if ($string){
+ $string =~ s/[()]|bitchx-//g;
+ @data = split /\s+/, $string;
+ $_=lc for @data;
+ $client{'version'} = ($data[1] eq 'version') ? $data[2] : $data[1];
+ }
+ }
+ # 'hexchat' => ['',0,'','HexChat',0,0], # special
+ # the hexchat author decided to make --version/-v return a gtk dialogue box, lol...
+ # so we need to read the actual config file for hexchat. Note that older hexchats
+ # used xchat config file, so test first for default, then legacy. Because it's possible
+ # for this file to be user edited, doing some extra checks here.
+ elsif ($client{'name'} eq 'hexchat') {
+ if ( -f '~/.config/hexchat/hexchat.conf' ){
+ @data = main::reader('~/.config/hexchat/hexchat.conf','strip');
+ }
+ elsif ( -f '~/.config/hexchat/xchat.conf' ){
+ @data = main::reader('~/.config/hexchat/xchat.conf','strip');
+ }
+ $client{'version'} = main::awk(\@data,'version',2,'\s*=\s*');
+ $client{'name-print'} = 'HexChat';
+ }
+ # note: see legacy inxi konvi logic if we need to restore any of the legacy code.
+ elsif ($client{'name'} eq 'konversation') {
+ $client{'konvi'} = ( ! $client{'native'} ) ? 2 : 1;
+ }
+ elsif ($client{'name'} =~ /quassel/) {
+ @data = main::grabber("$client{'name'} -v 2>/dev/null");
+ foreach (@data){
+ if ($_ =~ /^Quassel IRC:/){
+ $client{'version'} = (split /\s+/, $_ )[2];
+ last;
+ }
+ elsif ($_ =~ /quassel\s[v]?[0-9]/){
+ $client{'version'} = (split /\s+/, $_ )[1];
+ last;
+ }
+ }
+ $client{'version'} ||= '(pre v0.4.1)?';
+ }
+ # then do some perl type searches, do this last since it's a wildcard search
+ elsif ($client{'name'} =~ /^perl.*|ksirc|dsirc$/ ) {
+ my @cmdline = main::get_cmdline();
+ # Dynamic runpath detection is too complex with KSirc, because KSirc is started from
+ # kdeinit. /proc/<pid of the grandparent of this process>/exe is a link to /usr/bin/kdeinit
+ # with one parameter which contains parameters separated by spaces(??), first param being KSirc.
+ # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed,
+ # dsirc is the program that runs inxi, therefore that is the parent process that we see.
+ # You can imagine how hosed I am if I try to make inxi find out dynamically with which path
+ # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material.
+ # (KSirc sucks anyway ;)
+ foreach (@cmdline){
+ if ( $_ =~ /dsirc/ ){
+ $client{'version'} = main::program_version('ksirc','KSirc:',2,'-v',0,0);
+ $client{'name'} = 'ksirc';
+ $client{'name-print'} = 'KSirc';
+ }
+ }
+ $client{'console-irc'} = 1;
+ perl_python_client();
+ }
+ elsif ($client{'name'} =~ /python/) {
+ perl_python_client();
+ }
+ if (!$client{'name-print'}) {
+ $client{'name-print'} = 'Unknown Client: ' . $client{'name'};
+ }
+ eval $end if $b_log;
+}
+sub get_cmdline {
+ eval $start if $b_log;
+ my @cmdline;
+ my $i = 0;
+ $ppid = getppid();
+ if (! -e "/proc/$ppid/cmdline" ){
+ return 1;
+ }
+ local $\ = '';
+ open( my $fh, '<', "/proc/$ppid/cmdline" ) or
+ print_line("Open /proc/$ppid/cmdline failed: $!");
+ my @rows = <$fh>;
+ close $fh;
+
+ foreach (@rows){
+ push @cmdline, $_;
+ $i++;
+ last if $i > 31;
+ }
+ if ( $i == 0 ){
+ $cmdline[0] = $rows[0];
+ $i = ($cmdline[0]) ? 1 : 0;
+ }
+ main::log_data('string',"cmdline: @cmdline count: $i") if $b_log;
+ eval $end if $b_log;
+ return @cmdline;
+}
+sub perl_python_client {
+ eval $start if $b_log;
+ return 1 if $client{'version'};
+ # this is a hack to try to show konversation if inxi is running but started via /cmd
+ # OR via program shortcuts, both cases in fact now
+ # main::print_line("konvi: " . scalar grep { $_ =~ /konversation/ } @ps_cmd);
+ if ( $b_display && main::check_program('konversation') && ( grep { $_ =~ /konversation/ } @ps_cmd )){
+ @app = main::program_values('konversation');
+ $client{'version'} = main::program_version('konversation',$app[0],$app[1],$app[2],$app[5],$app[6]);
+ $client{'name'} = 'konversation';
+ $client{'name-print'} = $app[3];
+ $client{'console-irc'} = $app[4];
+ }
+ ## NOTE: supybot only appears in ps aux using 'SHELL' command; the 'CALL' command
+ ## gives the user system irc priority, and you don't see supybot listed, so use SHELL
+ elsif ( !$b_display &&
+ (main::check_program('supybot') || main::check_program('gribble') || main::check_program('limnoria')) &&
+ ( grep { $_ =~ /supybot/ } @ps_cmd ) ){
+ @app = main::program_values('supybot');
+ $client{'version'} = main::program_version('supybot',$app[0],$app[1],$app[2],$app[5],$app[6]);
+ if ($client{'version'}){
+ if ( grep { $_ =~ /gribble/ } @ps_cmd ){
+ $client{'name'} = 'gribble';
+ $client{'name-print'} = 'Gribble';
+ }
+ if ( grep { $_ =~ /limnoria/ } @ps_cmd){
+ $client{'name'} = 'limnoria';
+ $client{'name-print'} = 'Limnoria';
+ }
+ else {
+ $client{'name'} = 'supybot';
+ $client{'name-print'} = 'Supybot';
+ }
+ }
+ else {
+ $client{'name'} = 'supybot';
+ $client{'name-print'} = 'Supybot';
+ }
+ $client{'console-irc'} = 1;
+ }
+ else {
+ $client{'name-print'} = "Unknown $client{'name'} client";
+ }
+ if ($b_log){
+ my $string = "namep: $client{'name-print'} name: $client{'name'} version: $client{'version'}";
+ main::log_data('data',$string);
+ }
+ eval $end if $b_log;
}
-
## try to infer the use of Konversation >= 1.2, which shows $PPID improperly
## no known method of finding Konvi >= 1.2 as parent process, so we look to see if it is running,
## and all other irc clients are not running. As of 2014-03-25 this isn't used in my cases
-is_this_qt4_konvi()
-{
- local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir=''
- local konvi='' b_is_qt4=''
-
- # fringe cases can throw error, always if untested app, use 2>/dev/null after testing if present
- if [[ $B_QDBUS == 'true' ]];then
- konvi_dbus_exist=$( qdbus 2>/dev/null | grep "org.kde.konversation" )
- fi
+sub check_modern_konvi {
+ eval $start if $b_log;
+
+ return 0 if ! $client{'qdbus'};
+ my $b_modern_konvi = 0;
+ my $konvi_version = '';
+ my $konvi = '';
+ my $pid = '';
+ my (@temp);
+ # main::log_data('data',"name: $client{'name'} :: qdb: $client{'qdbus'} :: version: $client{'version'} :: konvi: $client{'konvi'} :: PPID: $ppid") if $b_log;
# sabayon uses /usr/share/apps/konversation as path
- if [[ -n $konvi_dbus_exist ]] && [[ -e /usr/share/kde4/apps/konversation || -e /usr/share/apps/konversation ]]; then
- konvi_pid=$( ps -A | gawk 'BEGIN{IGNORECASE=1} /konversation/ { print $1 }' )
- konvi_home_dir=$( readlink /proc/$konvi_pid/exe )
- konvi=$( echo $konvi_home_dir | sed "s/\// /g" )
- konvi=($konvi)
-
- if [[ ${konvi[2]} == 'konversation' ]];then
+ if ( -d '/usr/share/kde4/apps/konversation' || -d '/usr/share/apps/konversation' ){
+ $pid = main::awk(\@ps_aux,'konversation',2,'\s+');
+ main::log_data('data',"pid: $pid") if $b_log;
+ $konvi = readlink ("/proc/$pid/exe");
+ $konvi =~ s/^.*\///; # basename
+ @app = main::program_values('konversation');
+ if ($konvi){
+ @app = main::program_values('konversation');
+ $konvi_version = main::program_version($konvi,$app[0],$app[1],$app[2],$app[5],$app[6]);
+ @temp = split /\./, $konvi_version;
+ $client{'console-irc'} = $app[4];
+ $client{'konvi'} = 3;
+ $client{'name'} = 'konversation';
+ $client{'name-print'} = $app[3];
+ $client{'version'} = $konvi_version;
# note: we need to change this back to a single dot number, like 1.3, not 1.3.2
- konvi_qt4_client=$( konversation -v | grep -i 'konversation' | \
- gawk '{ print $2 }' | cut -d '.' -f 1,2 )
- if [[ $konvi_qt4_client > 1.1 ]]; then
- b_is_qt4='true'
- fi
- fi
- else
- konvi_qt4="qt3"
- b_is_qt4='false'
- fi
- log_function_data "b_is_qt4: $b_is_qt4"
- echo $b_is_qt4
+ $konvi_version = $temp[0] . "." . $temp[1];
+ if ($konvi_version > 1.1){
+ $b_modern_konvi = 1;
+ }
+ }
+ }
+ main::log_data('data',"name: $client{'name'} name print: $client{'name-print'}
+ qdb: $client{'qdbus'} version: $konvi_version konvi: $konvi PID: $pid") if $b_log;
+ main::log_data('data',"b_is_qt4: $b_modern_konvi") if $b_log;
## for testing this module
- #qdbus org.kde.konversation /irc say $1 $2 "getpid_dir: $konvi_qt4 qt4_konvi: $konvi_qt4_ver verNum: $konvi_qt4_ver_num pid: $konvi_pid ppid: $PPID konvi_home_dir: ${konvi[2]}"
+# my $ppid = getppid();
+# system('qdbus org.kde.konversation', '/irc', 'say', $client{'dserver'}, $client{'dtarget'},
+# "getpid_dir: $konvi_qt4 verNum: $konvi_version pid: $pid ppid: $ppid" );
+ eval $end if $b_log;
+ return $b_modern_konvi;
}
-# args: $1 - App_Working_Name
-set_perl_python_client_data()
-{
- if [[ -z $IRC_CLIENT_VERSION ]];then
- local version=''
- # this is a hack to try to show konversation if inxi is running but started via /cmd
- # OR via script shortcuts, both cases in fact now
- if [[ $B_RUNNING_IN_DISPLAY == 'true' && -z ${Ps_aux_Data/*konversation*/} ]];then
- IRC_CLIENT='Konversation'
- version=$( get_program_version 'konversation' '^konversation' '2' )
- B_CONSOLE_IRC='false'
- ## NOTE: supybot only appears in ps aux using 'SHELL' command; the 'CALL' command
- ## gives the user system irc priority, and you don't see supybot listed, so use SHELL
- elif [[ $B_RUNNING_IN_DISPLAY == 'false' && -z ${Ps_aux_Data/*supybot*/} ]];then
- version=$( get_program_version 'supybot' '^Supybot' '2' )
- if [[ -n $version ]];then
- IRC_CLIENT_VERSION=" $version"
- if [[ -z ${version/*gribble*/} ]];then
- IRC_CLIENT='Gribble'
- elif [[ -z ${version/*limnoria*/} ]];then
- IRC_CLIENT='Limnoria'
- else
- IRC_CLIENT='Supybot'
- fi
- else
- IRC_CLIENT='Supybot'
- # currently all use the same actual app name, this will probably change.
- fi
- B_CONSOLE_IRC='true'
- else
- IRC_CLIENT="Unknown $1 client"
- fi
- if [[ -n $version ]];then
- IRC_CLIENT_VERSION=" $version"
- fi
- fi
+sub set_konvi_data {
+ eval $start if $b_log;
+ my $config_tool = '';
+ # https://userbase.kde.org/Konversation/Scripts/Scripting_guide
+ if ( $client{'konvi'} == 3 ){
+ $client{'dserver'} = shift @ARGV;
+ $client{'dtarget'} = shift @ARGV;
+ $client{'dobject'} = 'default';
+ }
+ elsif ( $client{'konvi'} == 1 ){
+ $client{'dport'} = shift @ARGV;
+ $client{'dserver'} = shift @ARGV;
+ $client{'dtarget'} = shift @ARGV;
+ $client{'dobject'} = 'Konversation';
+ }
+ # for some reason this logic hiccups on multiple spaces between args
+ @ARGV = grep { $_ ne '' } @ARGV;
+ # there's no current kde 5 konvi config tool that we're aware of. Correct if changes.
+ if ( main::check_program('kde4-config') ){
+ $config_tool = 'kde4-config';
+ }
+ elsif ( main::check_program('kde5-config') ){
+ $config_tool = 'kde5-config';
+ }
+ elsif ( main::check_program('kde-config') ){
+ $config_tool = 'kde-config';
+ }
+ # The section below is on request of Argonel from the Konversation developer team:
+ # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf
+ if ($config_tool){
+ my @data = main::grabber("$config_tool --path data 2>/dev/null",':');
+ main::get_configs(@data);
+ }
+ eval $end if $b_log;
+}
}
########################################################################
-#### DATA PROCESSORS
+#### OUTPUT
########################################################################
#### -------------------------------------------------------------------
-#### GET DATA
+#### FILTERS AND TOOLS
#### -------------------------------------------------------------------
-## create array of sound cards installed on system, and if found, use asound data as well
-get_audio_data()
-{
- eval $LOGFS
- local i='' alsa_data='' audio_driver='' device_count='' a_temp=''
+sub apply_filter {
+ my ($string) = @_;
+ if ($string){
+ $string = ( $show{'filter'} ) ? $filter_string : $string;
+ }
+ else {
+ $string = 'N/A';
+ }
+ return $string;
+}
- IFS=$'\n'
- # this first step handles the drivers for cases where the second step fails to find one
- device_count=$( echo "$LSPCI_V_DATA" | grep -iEc '(multimedia audio controller|audio device)' )
- if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
- audio_driver=$( gawk -F ']: ' '
- BEGIN {
- IGNORECASE=1
+sub clean_characters {
+ my ($data) = @_;
+ # newline, pipe, brackets, + sign, with space, then clear doubled
+ # spaces and then strip out trailing/leading spaces.
+ $data =~ s/\n|\|\+|\[\s\]|\s\s+/ /g if $data;
+ $data =~ s/^\s+|\s+$//g if $data;
+ return $data;
+}
+
+sub cleaner {
+ my ($item) = @_;
+ return $item if !$item;# handle cases where it was 0 or ''
+ $item =~ s/chipset|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|incorporation|industrial|international|nee|revision|semiconductor|software|technologies|technology|ltd\.|<ltd>|\bltd\b|inc\.|<inc>|\binc\b|intl\.|co\.|<co>|corp\.|<corp>|\(tm\)|\(r\)|®|\(rev ..\)|\'|\"|\sinc\s*$|\?//gi;
+ $item =~ s/,|\*/ /g;
+ $item =~ s/\s\s+/ /g;
+ $item =~ s/^\s+|\s+$//g;
+ return $item;
+}
+
+sub dmi_cleaner {
+ my ($string) = @_;
+ my $cleaner = '^Base Board .*|^Chassis .*|empty|Undefined.*|.*O\.E\.M\..*|.*OEM.*|^Not .*';
+ $cleaner .= '|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*|^0x[0]+$';
+ $cleaner .= '|\[Empty\]|<Bad Index>|Default string|^\.\.$|Manufacturer.*';
+ $cleaner .= '|AssetTagNum|Manufacturer| Or Motherboard|PartNum.*|SerNum';
+ $string =~ s/$cleaner//i;
+ $string =~ s/^\s+|\bbios\b|\bacpi\b|\s+$//gi;
+ $string =~ s/http:\/\/www.abit.com.tw\//Abit/i;
+ $string =~ s/\s\s+/ /g;
+ $string =~ s/^\s+|\s+$//g;
+ $string = remove_duplicates($string) if $string;
+ return $string;
+}
+sub remove_duplicates {
+ my ($string) = @_;
+ return if ! $string;
+ my $holder = '';
+ my (@temp);
+ my @data = split /\s+/, $string;
+ foreach (@data){
+ if ($holder ne $_){
+ push @temp, $_;
}
- # filtering out modems and usb devices like webcams, this might get a
- # usb audio card as well, this will take some trial and error
- $0 !~ /modem|usb|webcam/ {
- driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
- gsub(/^ +| +$/,"",driver)
- if ( driver != "" ){
- print driver
- }
- }' $FILE_ASOUND_DEVICE )
- log_function_data 'cat' "$FILE_ASOUND_DEVICE"
- fi
-
- # this is to safeguard against line breaks from results > 1, which if inserted into following
- # array will create a false array entry. This is a hack, not a permanent solution.
- audio_driver=$( echo $audio_driver )
- # now we'll build the main audio data, card name, driver, and port. If no driver is found,
- # and if the first method above is not null, and one card is found, it will use that instead.
- A_AUDIO_DATA=( $( echo "$LSPCI_V_DATA" | gawk -F ': ' -v audioDriver="$audio_driver" '
- BEGIN {
- IGNORECASE=1
- }
- /multimedia audio controller|audio device/ {
- audioCard=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
- # The doublequotes are necessary because of the pipes in the variable.
- gsub(/'"$BAN_LIST_NORMAL"'/, "", audioCard)
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", audioCard)
- if ( '$COLS_INNER' < 100 ){
- sub(/Series Family/,"Series", audioCard)
- sub(/High Definition/,"High Def.", audioCard)
- }
- gsub(/^ +| +$/, "", audioCard)
- gsub(/ [ \t]+/, " ", audioCard)
- aPciBusId[audioCard] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
- cards[audioCard]++
-
- # loop until you get to the end of the data block
- while (getline && !/^$/) {
- gsub(/'"$BAN_LIST_ARRAY"'/, "", $0 )
- if (/driver in use/) {
- drivers[audioCard] = drivers[audioCard] gensub( /(.*): (.*)/ ,"\\2", "g" ,$0 ) ""
- }
- else if (/kernel modules:/) {
- modules[audioCard] = modules[audioCard] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
- }
- else if (/^[[:space:]]*I\/O/) {
- portsTemp = gensub(/\t*I\/O ports at ([a-z0-9]+)(| \[.*\])/,"\\1","g",$0)
- ports[audioCard] = ports[audioCard] portsTemp " "
- }
- }
- }
-
- END {
- j=0
- for (i in cards) {
- useDrivers=""
- useModules=""
- usePorts=""
- usePciBusId=""
-
- if (cards[i]>1) {
- a[j]=cards[i]"x "i
- if (drivers[i] != "") {
- useDrivers=drivers[i]
- }
- }
- else {
- a[j]=i
- # little trick here to try to catch the driver if there is
- # only one card and it was null, from the first test of asound/cards
- if (drivers[i] != "") {
- useDrivers=drivers[i]
+ $holder = $_;
+ }
+ $string = join ' ', @temp;
+ return $string;
+}
+
+# args: $1 - size in KB, return KB, MB, GB, TB, PB, EB
+sub get_size {
+ my ($size,$b_int) = @_;
+ my (@data);
+ return ('','') if ! defined $size;
+ if ($size !~ /^[0-9\.]+$/){
+ $data[0] = $size;
+ $data[1] = '';
+ }
+ elsif ($size > 1024**5){
+ $data[0] = sprintf("%.2f",$size/1024**5);
+ $data[1] = 'EiB';
+ }
+ elsif ($size > 1024**4){
+ $data[0] = sprintf("%.2f",$size/1024**4);
+ $data[1] = 'PiB';
+ }
+ elsif ($size > 1024**3){
+ $data[0] = sprintf("%.2f",$size/1024**3);
+ $data[1] = 'TiB';
+ }
+ elsif ($size > 1024**2){
+ $data[0] = sprintf("%.2f",$size/1024**2);
+ $data[1] = 'GiB';
+ }
+ elsif ($size > 1024){
+ $data[0] = sprintf("%.1f",$size/1024);
+ $data[1] = 'MiB';
+ }
+ else {
+ $data[0] = sprintf("%.0f",$size);
+ $data[1] = 'KiB';
+ }
+ $data[0] = int($data[0]) if $b_int && $data[0];
+ return @data;
+}
+
+# not used, but keeping logic for now
+sub increment_starters {
+ my ($key,$indexes) = @_;
+ my $result = $key;
+ if (defined $$indexes{$key} ){
+ $$indexes{$key}++;
+ $result = "$key-$$indexes{$key}";
+ }
+ return $result;
+}
+sub memory_data_full {
+ eval $start if $b_log;
+ my ($source) = @_;
+ my $num = 0;
+ my ($memory,@rows);
+ my ($percent,$total,$used) = ('','','');
+ if (!$show{'info'}){
+ $memory = get_memory_data('splits');
+ if ($memory){
+ my @temp = split /:/, $memory;
+ my @temp2 = get_size($temp[0]);
+ $total = ($temp2[1]) ? $temp2[0] . ' ' . $temp2[1] : $temp2[0];
+ @temp2 = get_size($temp[1]);
+ $used = ($temp2[1]) ? $temp2[0] . ' ' . $temp2[1] : $temp2[0];
+ $used .= " ($temp[2]%)" if $temp[2];
+ }
+ my $key = ($source eq 'process') ? 'System RAM': 'RAM';
+ $rows[0]{main::key($num++,$key)} = '';
+ $rows[0]{main::key($num++,'total')} = $total;
+ $rows[0]{main::key($num++,'used')} = $used;
+ }
+ $b_mem = 1;
+ eval $end if $b_log;
+ return @rows;
+}
+
+sub pci_cleaner {
+ my ($string,$type) = @_;
+ #print "st1 $type:$string\n";
+ my $filter = 'compatible\scontroller|\b(device|controller|multimedia)\b|\([^)]+\)';
+ # \[[^\]]+\]$| not trimming off ending [...] initial type filters removes end
+ $filter = '\[[^\]]+\]$|' . $filter if $type eq 'pci';
+ $string =~ s/$filter//ig;
+ $string =~ s/\s\s+/ /g;
+ $string =~ s/^\s+|\s+$//g;
+ #print "st2 $type:$string\n";
+ $string = remove_duplicates($string) if $string;
+ return $string;
+}
+
+sub pci_long_filter {
+ my ($string) = @_;
+ if ($string =~ /\[AMD(\/ATI)?\]/){
+ $string =~ s/Advanced\sMicro\sDevices\s\[AMD(\/ATI)?\]/AMD/;
+ }
+ return $string;
+}
+
+sub row_defaults {
+ my ($type,$id) = @_;
+ $id ||= '';
+ my %unfound = (
+ 'arm-cpu-f' => 'Use -f option to see features',
+ 'arm-pci' => "PCI data type is not supported on ARM systems.",
+ 'battery-data' => "No battery data found. Is one present?",
+ 'battery-data-sys' => "No /sys data found. Old system?",
+ 'cpu-model-null' => "Model N/A",
+ 'darwin-feature' => "Feature not supported iu Darwin/OSX.",
+ 'disk-data-bsd' => "No disk data found for this BSD system.",
+ 'disk-data' => "No Disk data was found.",
+ 'disk-size-0' => "Total N/A",
+ 'display-console' => 'No advanced graphics data found on this system in console.',
+ 'display-null' => 'No advanced graphics data found on this system.',
+ 'display-root' => 'Advanced graphics data unavailable in console for root.',
+ 'display-root-x' => 'Advanced graphics data unavailable for root. Old System?',
+ 'display-server' => "No display server data found. Headless server?",
+ 'glxinfo-missing' => "Unable to show advanced data. Required tool glxinfo missing.",
+ 'display-try' => 'Advanced graphics data unavailable in console. Try -G --display',
+ 'dev' => 'Feature under development',
+ 'dmesg-boot-permissions' => 'dmesg.boot permissions',
+ 'dmesg-boot-missing' => 'dmesg.boot not found',
+ 'IP' => "No $id data found. Connected to the web? SSL issues?",
+ 'machine-data' => "No machine data: try newer kernel.",
+ 'machine-data-alt-33' => "No machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.",
+ 'machine-data-dmidecode' => "No machine data: try newer kernel, or install dmidecoce.",
+ 'optical-data' => "No Optical or Floppy data was found.",
+ 'optical-data-bsd' => "No floppy or optical data found for this BSD system.",
+ 'output-limit' => "Output throttled. IPs: $id; Limit: $limit; Override: --limit [1-x;-1 all]",
+ 'partition-data' => "No Partition data was found.",
+ 'pci-advanced-data' => 'bus/chip ids unavailable',
+ 'pci-card-data' => "No PCI card data found.",
+ 'pci-slot-data' => "No PCI slot data found. SOC?",
+ 'raid-data' => "No RAID data was found.",
+ 'ram-data' => "No RAM data was found. SOC?",
+ 'root-required' => "<root required>",
+ 'sensors-data-ipmi' => "No ipmi sensors data was found.",
+ 'sensors-data-linux' => "No sensors data was found. Is sensors configured?",
+ 'sensors-ipmi-root' => "Unable to run ipmi sensors. Are you root?",
+ '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.",
+ 'usb-data' => "No USB data was found. Server?",
+ 'unknown-desktop-version' => "ERR-101",
+ 'unknown-dev' => "ERR-102",
+ 'unknown-shell' => "ERR-100",
+ 'weather-null' => "No $id found. Internet connection working?",
+ 'xdpyinfo-missing' => '<xdpyinfo missing>',
+ );
+ return $unfound{$type};
+}
+# convert string passed to KB, based on GB/MB/TB id
+# NOTE: K 1024 KB 1000
+sub translate_size {
+ my ($working) = @_;
+ my $size = 0;
+ #print ":$working:\n";
+ return if ! defined $working;
+ my $math = ( $working =~ /B$/) ? 1000: 1024;
+ if ( $working =~ /^([0-9\.]+)M[B]?$/i){
+ $size = $1 * $math;
+ }
+ elsif ( $working =~ /^([0-9\.]+)G[B]?$/i){
+ $size = $1 * $math**2;
+ }
+ elsif ( $working =~ /^([0-9\.]+)T[B]?$/i){
+ $size = $1 * $math**3;
+ }
+ elsif ( $working =~ /^([0-9\.]+)P[B]?$/i){
+ $size = $1 * $math**4;
+ }
+ elsif ( $working =~ /^([0-9\.]+)E[B]?$/i){
+ $size = $1 * $math**5;
+ }
+ elsif ( $working =~ /^([0-9\.]+)K[B]?$/i){
+ $size = $1;
+ }
+ $size = int($size) if $size;
+ return $size;
+}
+
+#### -------------------------------------------------------------------
+#### GENERATE OUTPUT
+#### -------------------------------------------------------------------
+
+sub check_output_path {
+ my ($path) = @_;
+ my ($b_good,$dir,$file);
+ $dir = $path;
+ $dir =~ s/([^\/]+)$//;
+ $file = $1;
+ # print "file: $file : dir: $dir\n";
+ $b_good = 1 if (-d $dir && -w $dir && $dir =~ /^\// && $file);
+ return $b_good;
+}
+
+sub output_handler {
+ my (%data) = @_;
+ # print Dumper \%data;
+ if ($output_type eq 'screen'){
+ print_data(%data);
+ }
+ elsif ($output_type eq 'json'){
+ generate_json(%data);
+ }
+ elsif ($output_type eq 'xml'){
+ generate_xml(%data);
+ }
+}
+# NOTE: file has already been set and directory verified
+sub generate_json {
+ eval $start if $b_log;
+ my (%data) = @_;
+ my ($json);
+ my $b_debug = 1;
+ my ($b_cpanel,$b_valid);
+ error_handler('not-in-irc', 'help') if $b_irc;
+ #print Dumper \%data if $b_debug;
+ if (check_module('Cpanel::JSON::XS')){
+ import Cpanel::JSON::XS;
+ $json = Cpanel::JSON::XS::encode_json(\%data);
+ }
+ elsif (check_module('JSON::XS')){
+ import JSON::XS;
+ $json = JSON::XS::encode_json(\%data);
+ }
+ else {
+ error_handler('required-module', 'json', 'Cpanel::JSON::XS OR JSON::XS');
+ }
+ if ($json){
+ #$json =~ s/"[0-9]+#/"/g;
+ if ($output_file eq 'print'){
+ #$json =~ s/\}/}\n/g;
+ print "$json";
+ }
+ else {
+ print_line("Writing JSON data to: $output_file\n");
+ open(my $fh, '>', $output_file) or error_handler('open',$output_file,"$!");
+ print $fh "$json";
+ close $fh;
+ print_line("Data written successfully.\n");
+ }
+ }
+ eval $end if $b_log;
+}
+# NOTE: So far xml is substantially more difficult than json, so
+# using a crude dumper rather than making a nice xml file, but at
+# least xml has some output now.
+sub generate_xml {
+ eval $start if $b_log;
+ my (%data) = @_;
+ my ($xml);
+ my $b_debug = 0;
+ error_handler('not-in-irc', 'help') if $b_irc;
+ #print Dumper \%data if $b_debug;
+ if (check_module('XML::Dumper')){
+ import XML::Dumper;
+ $xml = XML::Dumper::pl2xml(\%data);
+ #$xml =~ s/"[0-9]+#/"/g;
+ if ($output_file eq 'print'){
+ print "$xml";
+ }
+ else {
+ print_line("Writing XML data to: $output_file\n");
+ open(my $fh, '>', $output_file) or error_handler('open',$output_file,"$!");
+ print $fh "$xml";
+ close $fh;
+ print_line("Data written successfully.\n");
+ }
+ }
+ else {
+ error_handler('required-module', 'xml', 'XML::Dumper');
+ }
+ eval $end if $b_log;
+}
+
+sub key {
+ return sprintf("%03d#%s", $_[0],$_[1]);
+}
+
+sub print_basic {
+ my (@data) = @_;
+ my $indent = 18;
+ my $indent_static = 18;
+ my $indent1_static = 5;
+ my $indent2_static = 8;
+ my $indent1 = 5;
+ my $indent2 = 8;
+ my $length = @data;
+ my ($start,$aref,$i,$j,$line);
+
+ if ( $size{'max'} > 110 ){
+ $indent_static = 22;
+ }
+ elsif ($size{'max'} < 90 ){
+ $indent_static = 15;
+ }
+ # print $length . "\n";
+ for my $i (0 .. $#data){
+ $aref = $data[$i];
+ #print "0: $data[$i][0]\n";
+ if ($data[$i][0] == 0 ){
+ $indent = 0;
+ $indent1 = 0;
+ $indent2 = 0;
+ }
+ elsif ($data[$i][0] == 1 ){
+ $indent = $indent_static;
+ $indent1 = $indent1_static;
+ $indent2= $indent2_static;
+ }
+ elsif ($data[$i][0] == 2 ){
+ $indent = ( $indent_static + 7 );
+ $indent1 = ( $indent_static + 5 );
+ $indent2 = 0;
+ }
+ $data[$i][3] =~ s/\n/ /g;
+ $data[$i][3] =~ s/\s+/ /g;
+ if ($data[$i][1] && $data[$i][2]){
+ $data[$i][1] = $data[$i][1] . ', ';
+ }
+ $start = sprintf("%${indent1}s%-${indent2}s",$data[$i][1],$data[$i][2]);
+ if ($indent > 1 && ( length($start) > ( $indent - 1) ) ){
+ $line = sprintf("%-${indent}s\n", "$start");
+ print_line($line);
+ $start = '';
+ #print "1-print.\n";
+ }
+ if ( ( $indent + length($data[$i][3]) ) < $size{'max'} ){
+ $data[$i][3] =~ s/\^/ /g;
+ $line = sprintf("%-${indent}s%s\n", "$start", $data[$i][3]);
+ print_line($line);
+ #print "2-print.\n";
+ }
+ else {
+ my $holder = '';
+ my $sep = ' ';
+ foreach my $word (split / /, $data[$i][3]){
+ #print "$word\n";
+ if ( ( $indent + length($holder) + length($word) ) < $size{'max'} ) {
+ $word =~ s/\^/ /g;
+ $holder .= $word . $sep;
+ #print "3-hold.\n";
}
- else if ( audioDriver != "" ) {
- useDrivers=audioDriver
+ #elsif ( ( $indent + length($holder) + length($word) ) >= $size{'max'}){
+ else {
+ $line = sprintf("%-${indent}s%s\n", "$start", $holder);
+ print_line($line);
+ $start = '';
+ $word =~ s/\^/ /g;
+ $holder = $word . $sep;
+ #print "4-print-hold.\n";
}
}
- if (ports[i] != "") {
- usePorts = ports[i]
+ if ($holder !~ /^[ ]*$/){
+ $line = sprintf("%-${indent}s%s\n", "$start", $holder);
+ print_line($line);
+ #print "5-print-last.\n";
}
- if (modules[i] != "" ) {
- useModules = modules[i]
- }
- if ( aPciBusId[i] != "" ) {
- usePciBusId = aPciBusId[i]
+ }
+ }
+}
+# this has to get a hash of hashes, at least for now.
+# because perl does not retain insertion order, I use a prefix for each
+# hash key to force sorts.
+sub print_data {
+ my (%data) = @_;
+ my $array = 0;
+ my $array_holder = 1;
+ my $counter=0;
+ my $split_count = 0;
+ my $hash = 0;
+ my $holder = '';
+ my $id_holder = 0;
+ my $start = '';
+ my $start2 = '';
+ my $length = 0;
+ my $indent = $size{'indent'};
+ my (@temp,@working,@values,%ids,$holder2,%row);
+ my ($key,$line,$val2,$val3);
+ # $size{'max'} = 88;
+ # NOTE: indent < 11 would break the output badly in some cases
+ if ($size{'max'} < $size{'indent-min'} || $size{'indent'} < 11 ){
+ $indent = 2;
+ }
+ #foreach my $key1 (sort { (split/#/, $a)[0] <=> (split/#/, $b)[0] } keys %data) {
+ foreach my $key1 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %data) {
+ #foreach my $key1 (sort { $a cmp $b } keys %data) {
+ $key = (split/#/, $key1)[1];
+ if ($key ne 'SHORT' ) {
+ $start = sprintf("$colors{'c1'}%-${indent}s$colors{'cn'}","$key$sep{'s1'}");
+ if ($indent < 10){
+ $line = "$start\n";
+ print_line($line);
+ $start = '';
+ $line = '';
}
- # create array primary item for master array
- sub( / $/, "", usePorts ) # clean off trailing whitespace
- print a[j] "," useDrivers "," usePorts "," useModules "," usePciBusId
- j++
}
- }') )
-
- # in case of failure of first check do this instead
- if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
- A_AUDIO_DATA=( $( gawk -F ']: ' '
- BEGIN {
- IGNORECASE=1
+ else {
+ $indent = 0;
}
- $1 !~ /modem/ && $2 !~ /modem/ {
- card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 )
- driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
- if ( card != "" ){
- print card","driver
+ if (ref($data{$key1}) eq 'ARRAY'){
+ # @working = @{$data{$key1}};
+ %ids = (
+ 'Array' => 1,
+ 'array' => 1,
+ 'Battery' => 1,
+ 'Card' => 1,
+ 'Device' => 1,
+ 'Floppy' => 1,
+ 'ID' => 1,
+ 'IF-ID' => 1,
+ 'Optical' => 1,
+ );
+ $array_holder = 1;
+ foreach my $val1 (@{$data{$key1}}){
+ $length = $indent;
+ if (ref($val1) eq 'HASH'){
+ #%row = %$val1;
+ $counter=0;
+ $split_count = 0;
+ $hash = scalar %$val1;
+ #foreach my $key2 (sort { (split/#/, $a)[0] <=> (split/#/, $b)[0] } keys %$val1){
+ foreach my $key2 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %$val1){
+ #foreach my $key2 (sort { $a cmp $b } keys %$val1){
+ $key = (split/#/, $key2)[1];
+ # for ram with > 1 system array, we want to reset device count to 1 for each
+ # new array
+ if ($key eq 'Array' && $array_holder != $ids{$key} ){
+ $array_holder = $ids{$key};
+ $ids{'Device'} = 1 if ($ids{'Device'} > 1);
+ }
+ if ($key eq 'Device' && $ids{'array'} > 1 && $id_holder != $ids{$key} ){
+ $id_holder = $ids{$key};
+ $ids{'array'} = 1 if ($ids{'array'} > 1);
+ }
+ if ($counter == 0 && defined $ids{$key}){
+ $key .= '-' . $ids{$key}++;
+ }
+ $val2 = $$val1{$key2};
+ # we have to handle cases where $val2 is 0
+ if ($val2 || $val2 eq '0'){
+ $val2 .= " ";
+ }
+ # see: Use of implicit split to @_ is deprecated. Only get this warning
+ # in Perl 5.08 oddly enough.
+ @temp = split/\s+/, $val2;
+ $split_count = scalar @temp;
+ if ( ( length( "$key$sep{'s2'} $val2" ) + $length ) < $size{'max'} ) {
+ $length += length("$key$sep{'s2'} $val2");
+ $holder .= "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val2";
+ #print "one\n";
+ }
+ # handle case where the opening key/value pair is > max, and where
+ # there are a lot of terms, like cpu flags, raid types supported. Raid
+ # can have the last row have a lot of devices, or many raid types
+ elsif ( ( length( "$key$sep{'s2'} $val2" ) + $indent ) > $size{'max'} &&
+ !defined $ids{$key} && $split_count > 2 ) {
+ @values = split/\s+/, $val2;
+ $val3 = shift @values;
+ # $length += length("$key$sep{'s2'} $val3 ") + $indent;
+ $start2 = "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val3 ";
+ $holder2 = '';
+ $length += length("$key$sep{'s2'} $val3 ");
+ # print scalar @values,"\n";
+ foreach (@values){
+ # my $l = (length("$_ ") + $length);
+ #print "$l\n";
+ if ( (length("$_ ") + $length) < $size{'max'} ){
+ #print "a\n";
+ if ($start2){
+ $holder2 .= "$start2$_ ";
+ $start2 = '';
+ #$length += $length2;
+ #$length2 = 0;
+ }
+ else {
+ $holder2 .= "$_ ";
+ }
+ $length += length("$_ ");
+ }
+ else {
+ #print "three\n";
+ if ($start2){
+ $holder2 = "$start2$holder2";
+ }
+ else {
+ $holder2 = "$colors{'c2'}$holder2";
+ }
+ #print "xx:$holder";
+ $line = sprintf("%-${indent}s%s$colors{'cn'}\n","$start","$holder$holder2");
+ print_line($line);
+ $holder = '';
+
+ $holder2 = "$_ ";
+ #print "h2: $holder2\n";
+ $length = length($holder2) + $indent;
+ $start2 = '';
+ $start = '';
+ #$length2 = 0;
+ }
+ }
+ if ($holder2 !~ /^\s*$/){
+ #print "four\n";
+ $holder2 = "$colors{'c2'}$holder2";
+ $line = sprintf("%-${indent}s%s$colors{'cn'}\n","$start","$holder$holder2");
+ print_line($line);
+ $holder = '';
+ $holder2 = '';
+ $length = $indent;
+ $start2 = '';
+ $start = '';
+ #$length2 = 0;
+ }
+ }
+ else {
+ #print "H: $counter $hash\n";
+ if ($holder){
+ #print "five\n";
+ $line = sprintf("%-${indent}s%s$colors{'cn'}\n",$start,"$holder");
+ $holder = "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val2";
+ $length = length("$key$sep{'s2'} $val2") + $indent;
+ print_line($line);
+ $start = '';
+ }
+ else {
+ #print "six\n";
+ $holder = "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val2";
+ #$line = sprintf("%-${indent}s%s$colors{'cn'}\n",$start,"$holder");
+ $length = $indent;
+ #$holder = '';
+ }
+ }
+ $counter++;
+ }
+ if ($holder !~ /^\s*$/){
+ #print "seven\n";
+ $line = sprintf("%-${indent}s%s$colors{'cn'}\n",$start,"$start2$holder");
+ print_line($line);
+ $holder = '';
+ $length = 0;
+ $start = '';
+ }
+ }
+ # only for repos?
+ elsif (ref($val1) eq 'ARRAY'){
+ #print "eight\n";
+ $array=0;
+ foreach my $item (@$val1){
+ $array++;
+ $line = "$colors{'c1'}$array$sep{'s2'} $colors{'c2'}$item$colors{'cn'}";
+ $line = sprintf("%-${indent}s%s\n","","$line");
+ print_line($line);
+ }
+ }
+ else {
+
+ }
}
- }' $FILE_ASOUND_DEVICE ) )
- fi
- IFS="$ORIGINAL_IFS"
- get_audio_usb_data
- # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
- if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]];then
- A_AUDIO_DATA[0]='Failed to Detect Sound Card!'
- fi
- a_temp=${A_AUDIO_DATA[@]}
- log_function_data "A_AUDIO_DATA: $a_temp"
+ }
+ }
+}
- eval $LOGFE
+sub print_line {
+ my ($line) = @_;
+ if ($b_irc && $client{'test-konvi'}){
+ $client{'konvi'} = 3;
+ $client{'dobject'} = 'Konversation';
+ }
+ if ($client{'konvi'} == 1 && $client{'dcop'} ){
+ # konvi doesn't seem to like \n characters, it just prints them literally
+ $line =~ s/\n//g;
+ #qx('dcop "$client{'dport'}" "$client{'dobject'}" say "$client{'dserver'}" "$client{'dtarget'}" "$line 1");
+ system('dcop', $client{'dport'}, $client{'dobject'}, 'say', $client{'dserver'}, $client{'dtarget'}, "$line 1");
+ }
+ elsif ($client{'konvi'} == 3 && $client{'qdbus'} ){
+ # print $line;
+ $line =~ s/\n//g;
+ #qx(qdbus org.kde.konversation /irc say "$client{'dserver'}" "$client{'dtarget'}" "$line");
+ system('qdbus', 'org.kde.konversation', '/irc', 'say', $client{'dserver'}, $client{'dtarget'}, $line);
+ }
+ else {
+ print $line;
+ }
}
-# alsa usb detection by damentz
-get_audio_usb_data()
+########################################################################
+#### DATA PROCESSORS
+########################################################################
+
+#### -------------------------------------------------------------------
+#### PRIMARY DATA GENERATORS
+#### -------------------------------------------------------------------
+# 0 type
+# 1 type_id
+# 2 bus_id
+# 3 sub_id
+# 4 device
+# 5 vendor_id
+# 6 chip_id
+# 7 rev
+# 8 port
+# 9 driver
+# 10 modules
+
+## AudioData
{
- eval $LOGFS
- local usb_proc_file='' array_count='' usb_data='' usb_id='' lsusb_data=''
- local a_temp=''
-
- IFS=$'\n'
- if type -p lsusb &>/dev/null;then
- lsusb_data=$( lsusb 2>/dev/null )
- fi
- log_function_data 'raw' "usb_data:\n$lsusb_data"
- if [[ -n $lsusb_data && -d /proc/asound/ ]];then
- # for every sound card symlink in /proc/asound - display information about it
- for usb_proc_file in /proc/asound/*
- do
- # If the file is a symlink, and contains an important usb exclusive file: continue
- if [[ -L $usb_proc_file && -e $usb_proc_file/usbid ]]; then
- # find the contents of usbid in lsusb and print everything after the 7th word on the
- # corresponding line. Finally, strip out commas as they will change the driver :)
- usb_id=$( cat $usb_proc_file/usbid )
- usb_data=$( grep "$usb_id" <<< "$lsusb_data" )
- if [[ -n $usb_data && -n $usb_id ]];then
- usb_data=$( gawk '
- BEGIN {
- IGNORECASE=1
- string=""
- separator=""
+package AudioData;
+
+sub get {
+ eval $start if $b_log;
+ my (@data,@rows);
+ my $num = 0;
+ if ($b_arm){
+ my $key = 'ARM';
+ @data = ({
+ main::key($num++,$key) => main::row_defaults('arm-pci',''),
+ },);
+ @rows = (@rows,@data);
+ }
+ else {
+ @data = card_data();
+ @rows = (@rows,@data);
+ }
+ if ( ( $b_arm || !@rows ) && (my $file = main::system_files('asound-cards') ) ){
+ @data = asound_data($file);
+ @rows = (@rows,@data);
+ }
+ @data = usb_data();
+ @rows = (@rows,@data);
+ if (!@rows){
+ my $key = 'Message';
+ @data = ({
+ main::key($num++,$key) => main::row_defaults('pci-card-data',''),
+ },);
+ @rows = (@rows,@data);
+ }
+ @data = sound_server_data();
+ @rows = (@rows,@data);
+ eval $end if $b_log;
+ return @rows;
+}
+
+sub card_data {
+ eval $start if $b_log;
+ my (@rows,@data);
+ my ($j,$num) = (0,1);
+ foreach (@pci){
+ $num = 1;
+ my @row = @$_;
+ if ($row[0] eq 'audio' || $row[0] eq 'multimedia'){
+ $j = scalar @rows;
+ my $driver = $row[9];
+ $driver ||= 'N/A';
+ my $card = $row[4];
+ $card = ($card) ? main::pci_cleaner($card,'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);
+ }
+ @data = ({
+ main::key($num++,'Card') => $card,
+ main::key($num++,'driver') => $driver,
+ },);
+ @rows = (@rows,@data);
+ if ($extra > 0 && !$bsd_type){
+ if ($row[9] ){
+ my $version = main::get_module_version($row[9]);
+ $rows[$j]{main::key($num++,'v')} = $version if $version;
+ }
+ }
+ if ($extra > 0){
+ $rows[$j]{main::key($num++,'bus ID')} = "$row[2].$row[3]";
+ }
+ if ($extra > 1){
+ $rows[$j]{main::key($num++,'chip ID')} = "$row[5]:$row[6]";
+ }
+ }
+ #print "$row[0]\n";
+ }
+ #my $ref = $pci[-1];
+ #print $$ref[0],"\n";
+ eval $end if $b_log;
+ return @rows;
+}
+# this handles fringe cases where there is no card on pcibus,
+# but there is a card present. I don't know the exact architecture
+# involved but I know this situation exists on at least one old machine.
+sub asound_data {
+ eval $start if $b_log;
+ my ($file) = @_;
+ my (@asound,@rows,@data);
+ my ($card,$driver,$j,$num) = ('','',0,1);
+ @asound = main::reader($file);
+ foreach (@asound){
+ # filtering out modems and usb devices like webcams, this might get a
+ # usb audio card as well, this will take some trial and error
+ if ( !/modem|usb/i && /^\s*[0-9]/ ) {
+ $num = 1;
+ my @working = split /:\s*/, $_;
+ # now let's get 1 2
+ $working[1] =~ /(.*)\s+-\s+(.*)/;
+ $card = $2;
+ $driver = $1;
+ if ( $card ){
+ $j = scalar @rows;
+ $driver ||= 'N/A';
+ @data = ({
+ main::key($num++,'Card') => $card,
+ main::key($num++,'driver') => $driver,
+ },);
+ @rows = (@rows,@data);
+ if ($extra > 0){
+ my $version = main::get_module_version($driver);
+ $rows[$j]{main::key($num++,'v')} = $version if $version;
+ $rows[$j]{main::key($num++,'message')} = main::row_defaults('pci-advanced-data','');
+ }
+ }
+ }
+ }
+ # print Data::Dumper:Dumper \s@rows;
+ eval $end if $b_log;
+ return @rows;
+}
+sub usb_data {
+ eval $start if $b_log;
+ my (@rows,@data,@ids,$driver,$product,$product2,@temp2,$vendor,$vendor2);
+ 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);
+ }
+ # lsusb is a very expensive operation
+ if (@ids){
+ if (!$bsd_type && !$b_usb_check){
+ main::set_usb_data();
+ $b_usb_check = 1;
+ }
+ }
+ main::log_data('dump','@ids',\@ids) if $b_log;
+ return if !@usb;
+ foreach my $id (@ids){
+ $j = scalar @rows;
+ foreach my $ref (@usb){
+ my @row = @$ref;
+ # a device will always be the second or > device on the bus
+ if ($row[1] > 1 && $row[2] eq $id){
+ $num = 1;
+ # makre sure to reset, or second device trips last flag
+ ($product,$product2,$vendor,$vendor2) = ('','','','');
+ if ($usb_level == 1){
+ $product = main::cleaner($row[3]);
+ }
+ else {
+ foreach my $line (@row){
+ my @working = split /:/, $line;
+ if ($working[0] eq 'idVendor' && $working[2]){
+ $vendor = main::cleaner($working[2]);
+ }
+ if ($working[0] eq 'idProduct' && $working[2]){
+ $product = main::cleaner($working[2]);
+ }
+ if ($working[0] eq 'iManufacturer' && $working[2]){
+ $vendor2 = main::cleaner($working[2]);
+ }
+ if ($working[0] eq 'iProduct' && $working[2]){
+ $product2 = main::cleaner($working[2]);
+ }
+ if ($working[0] eq 'Descriptor_Configuration'){
+ last;
+ }
+ }
+ }
+ if ($vendor && $product){
+ $product = ($product =~ /$vendor/) ? $product: "$vendor $product" ;
}
- {
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0 )
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
- gsub(/ [ \t]+/, " ", $0)
- for ( i=7; i<= NF; i++ ) {
- string = string separator $i
- separator = " "
+ elsif (!$product) {
+ if ($vendor && $product2){
+ $product = ($product2 =~ /$vendor/) ? $product2: "$vendor $product2" ;
}
- if ( $2 != "" ){
- sub(/:/,"", $4)
- print string ",USB Audio,,," $2 "-" $4 "," $6
+ elsif ($vendor2 && $product2){
+ $product = ($product2 =~ /$vendor2/) ? $product2: "$vendor2 $product2" ;
}
- }' <<< "$usb_data" )
- fi
- # this method is interesting, it shouldn't work but it does
- #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,USB Audio,," )
- # but until we learn why the above worked, I'm using this one, which is safer
- if [[ -n $usb_data ]];then
- array_count=${#A_AUDIO_DATA[@]}
- A_AUDIO_DATA[$array_count]="$usb_data"
- fi
- fi
- done
- fi
- IFS="$ORIGINAL_IFS"
- a_temp=${A_AUDIO_DATA[@]}
- log_function_data "A_AUDIO_DATA: $a_temp"
-
- eval $LOGFE
+ elsif ($vendor){
+ $product = $vendor;
+ }
+ elsif ($vendor2){
+ $product = $vendor2;
+ }
+ else {
+ $product = 'N/A';
+ }
+ }
+ @temp2 = main::get_usb_drivers($row[0],$row[2]) if !$bsd_type && -d "/sys/devices";
+ if (@temp2 && $temp2[0]){
+ $driver = $temp2[0];
+ }
+ $driver ||= 'snd-usb-audio';
+ @data = ({
+ main::key($num++,'Card') => $product,
+ main::key($num++,'type') => 'USB',
+ main::key($num++,'driver') => $driver,
+ },);
+ @rows = (@rows,@data);
+ if ($extra > 0){
+ $rows[$j]{main::key($num++,'bus ID')} = "$row[0]:$row[1]";
+ }
+ if ($extra > 1){
+ $rows[$j]{main::key($num++,'chip ID')} = $row[2];
+ }
+ }
+ }
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
}
-get_audio_alsa_data()
-{
- eval $LOGFS
- local alsa_data='' a_temp=''
-
- # now we'll get the alsa data if the file exists
- if [[ $B_ASOUND_VERSION_FILE == 'true' ]];then
- IFS=","
- A_ALSA_DATA=( $(
- gawk '
- BEGIN {
- IGNORECASE=1
- alsa=""
- version=""
- }
- # some alsa strings have the build date in (...)
- # remove trailing . and remove possible second line if compiled by user
- $0 !~ /compile/ {
- gsub(/Driver | [(].*[)]|\.$/,"",$0 )
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
- gsub(/^ +| +$/, "", $0)
- gsub(/ [ \t]+/, " ", $0)
- sub(/Advanced Linux Sound Architecture/, "ALSA", $0)
- if ( $1 == "ALSA" ){
- alsa=$1
- }
- version=$NF
- print alsa "," version
- }' $FILE_ASOUND_VERSION ) )
- IFS="$ORIGINAL_IFS"
- log_function_data 'cat' "$FILE_ASOUND_VERSION"
- fi
- a_temp=${A_ALSA_DATA[@]}
- log_function_data "A_ALSA_DATA: $a_temp"
- eval $LOGFE
-}
-
-get_battery_data()
+sub sound_server_data {
+ 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++,'Sound Server') => $server,
+ main::key($num++,'v') => $version,
+ },);
+ }
+ eval $end if $b_log;
+ return @data;
+}
+}
+
+## BatteryData
{
- eval $LOGFS
- local a_temp='' id_file='' count=0
- local id_dir='/sys/class/power_supply/'
- local ids=$( ls $id_dir 2>/dev/null ) battery_file=''
-
- # ids='BAT0 BAT1 BAT2'
- if [[ -n $ids && $B_FORCE_DMIDECODE == 'false' ]];then
- for idx in $ids
- do
- battery_file=$id_dir$idx'/uevent'
- if [[ -r $battery_file ]];then
- # echo $battery_file
- count=$(( $count + 1 ))
- IFS=$'\n'
- battery_data=$(
- gawk -F '=' '
- BEGIN {
- IGNORECASE=1
- name=""
- status=""
- present=""
- chemistry=""
- cycles=""
- voltage_min_design=""
- voltage_now=""
- power_now=""
- # charge: mAh
- charge_full_design=""
- charge_full=""
- charge_now=""
- # energy: Wh
- energy_full_design=""
- energy_full=""
- energy_now=""
- capacity=""
- capacity_level=""
- model=""
- company=""
- serial=""
- of_orig=""
- location=""
- b_ma="false" # trips ma x voltage
- }
- {
- gsub(/'"$BAN_LIST_NORMAL"'|,|battery|unknown/, "", $2)
- gsub(/^ +| +$/, "", $2)
+package BatteryData;
+
+sub get {
+ eval $start if $b_log;
+ my (@rows,$key1,%battery,$val1);
+ my $num = 0;
+ if ($bsd_type || $b_dmidecode_force){
+ my $ref = $alerts{'dmidecode'};
+ if ( $$ref{'action'} ne 'use'){
+ $key1 = $$ref{'action'};
+ $val1 = $$ref{$key1};
+ $key1 = ucfirst($key1);
+ @rows = ({main::key($num++,$key1) => $val1,});
+ }
+ else {
+ %battery = battery_data_dmi();
+ if (!%battery){
+ if ($show{'battery-forced'}){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('battery-data','');
+ @rows = ({main::key($num++,$key1) => $val1,});
}
- $1 ~ /^POWER_SUPPLY_NAME$/ {
- name=$NF
+ }
+ else {
+ @rows = create_output(%battery);
+ }
+ }
+ }
+ elsif (-d '/sys/class/power_supply/'){
+ %battery = battery_data_sys();
+ if (!%battery){
+ if ($show{'battery-forced'}){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('battery-data','');
+ @rows = ({main::key($num++,$key1) => $val1,});
+ }
+ }
+ else {
+ @rows = create_output(%battery);
+ }
+ }
+ else {
+ if ($show{'battery-forced'}){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('battery-data-sys','');
+ @rows = ({main::key($num++,$key1) => $val1,});
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+# alarm capacity capacity_level charge_full charge_full_design charge_now
+# cycle_count energy_full energy_full_design energy_now location manufacturer model_name
+# power_now present serial_number status technology type voltage_min_design voltage_now
+# 0 name - battery id, not used
+# 1 status
+# 2 present
+# 3 technology
+# 4 cycle_count
+# 5 voltage_min_design
+# 6 voltage_now
+# 7 power_now
+# 8 energy_full_design
+# 9 energy_full
+# 10 energy_now
+# 11 capacity
+# 12 capacity_level
+# 13 of_orig
+# 14 model_name
+# 15 manufacturer
+# 16 serial_number
+# 17 location
+sub create_output {
+ eval $start if $b_log;
+ my (%battery,@data,@rows) = @_;
+ my ($key);
+ my $num = 0;
+ my $j = 0;
+ foreach $key (sort keys %battery){
+ $num = 0;
+ my ($charge,$condition,$model,$serial,$status,$volts) = ('','','','','','');
+ my ($chemistry,$cycles,$location) = ('','','');
+ # $battery{$key}{''};
+ # we need to handle cases where charge or energy full is 0
+ $charge = ($battery{$key}{'energy_now'} || $battery{$key}{'energy_now'} eq 0) ? "$battery{$key}{'energy_now'} Wh" : 'N/A';
+ if ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full_design'}){
+ $battery{$key}{'energy_full_design'} ||= 'N/A';
+ $battery{$key}{'energy_full'}= ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full'} eq 0) ? $battery{$key}{'energy_full'} : 'N/A';
+ $condition = "$battery{$key}{'energy_full'}/$battery{$key}{'energy_full_design'} Wh";
+ if ($battery{$key}{'of_orig'}){
+ $condition .= " ($battery{$key}{'of_orig'}%)";
+ }
+ }
+ $condition ||= 'N/A';
+ $j = scalar @rows;
+ @data = ({
+ main::key($num++,'ID') => $key,
+ main::key($num++,'charge') => $charge,
+ main::key($num++,'condition') => $condition,
+ },);
+ @rows = (@rows,@data);
+ 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'}";
}
- $1 ~ /^POWER_SUPPLY_STATUS$/ {
- status=$NF
+ $volts ||= 'N/A';
+ $rows[$j]{main::key($num++,'volts')} = $volts;
+ }
+ if ($battery{$key}{'manufacturer'} || $battery{$key}{'model_name'}) {
+ if ($battery{$key}{'manufacturer'} && $battery{$key}{'model_name'}){
+ $model = "$battery{$key}{'manufacturer'} $battery{$key}{'model_name'}";
}
- $1 ~ /^POWER_SUPPLY$/ {
- present=$NF
+ elsif ($battery{$key}{'manufacturer'}){
+ $model = $battery{$key}{'manufacturer'};
}
- $1 ~ /^POWER_SUPPLY_TECHNOLOGY$/ {
- chemistry=$NF
+ elsif ($battery{$key}{'model_name'}){
+ $model = $battery{$key}{'model_name'};
}
- $1 ~ /^POWER_SUPPLY_CYCLE_COUNT$/ {
- cycles=$NF
+ }
+ else {
+ $model = 'N/A';
+ }
+ $rows[$j]{main::key($num++,'model')} = $model;
+ if ($extra > 2){
+ $chemistry = ( $battery{$key}{'technology'} ) ? $battery{$key}{'technology'}: 'N/A';
+ $rows[$j]{main::key($num++,'type')} = $chemistry;
+ }
+ if ($extra > 1){
+ $serial = main::apply_filter($battery{$key}{'serial_number'});
+ $rows[$j]{main::key($num++,'serial')} = $serial;
+ }
+ $status = ($battery{$key}{'status'}) ? $battery{$key}{'status'}: 'N/A';
+ $rows[$j]{main::key($num++,'status')} = $status;
+ if ($extra > 2){
+ if ($battery{$key}{'cycle_count'}){
+ $rows[$j]{main::key($num++,'cycles')} = $battery{$key}{'cycle_count'};
}
- $1 ~ /^POWER_SUPPLY_VOLTAGE_MIN_DESIGN$/ {
- voltage_min_design = $NF / 1000000
- voltage_min_design = sprintf( "%.1f", voltage_min_design )
+ if ($battery{$key}{'location'}){
+ $rows[$j]{main::key($num++,'location')} = $battery{$key}{'location'};
}
- $1 ~ /^POWER_SUPPLY_VOLTAGE_NOW$/ {
- voltage_now = $NF / 1000000
- voltage_now = sprintf( "%.1f", voltage_now )
+ }
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+
+# charge: mAh energy: Wh
+sub battery_data_sys {
+ eval $start if $b_log;
+ my ($b_ma,%battery,$file,$id,$item,$path,$value);
+ my $num = 0;
+ # NOTE: known ids: BAT[0-9] CMB[0-9]
+ my @batteries = main::globber("/sys/class/power_supply/[BC][AM][TB]*/");
+ # note: there is no 'location' file, but dmidecode has it
+ # 'type' is generic, like: Battery
+ # capacity_level is a string, like: Normal
+ my @items = qw(alarm capacity capacity_level charge_full charge_full_design charge_now
+ cycle_count energy_full energy_full_design energy_now location manufacturer model_name
+ power_now present serial_number status technology type voltage_min_design voltage_now);
+ foreach $item (@batteries){
+ $b_ma = 0;
+ $id = $item;
+ $id =~ s%/sys/class/power_supply/|\/$%%g;
+ $battery{$id} = ({});
+ foreach $file (@items){
+ $path = "$item$file";
+ $value = (-f $path) ? (main::reader($path))[0]: '';
+ if ($value){
+ if ($file eq 'voltage_min_design'){
+ $value = sprintf("%.1f", $value/1000000);
}
- $1 ~ /^POWER_SUPPLY_POWER_NOW$/ {
- power_now=$NF
+ elsif ($file eq 'voltage_now'){
+ $value = sprintf("%.1f", $value/1000000);
}
- $1 ~ /^POWER_SUPPLY_ENERGY_FULL_DESIGN$/ {
- energy_full_design = $NF / 1000000
+ elsif ($file eq 'energy_full_design'){
+ $value = $value/1000000;
}
- $1 ~ /^POWER_SUPPLY_ENERGY_FULL$/ {
- energy_full = $NF / 1000000
+ elsif ($file eq 'energy_full'){
+ $value = $value/1000000;
}
- $1 ~ /^POWER_SUPPLY_ENERGY_NOW$/ {
- energy_now = $NF / 1000000
- energy_now = sprintf( "%.1f", energy_now )
+ elsif ($file eq 'energy_now'){
+ $value = sprintf("%.1f", $value/1000000);
}
# note: the following 3 were off, 100000 instead of 1000000
# why this is, I do not know. I did not document any reason for that
# so going on assumption it is a mistake. CHARGE is mAh, which are converted
# to Wh by: mAh x voltage. Note: voltage fluctuates so will make results vary slightly.
- $1 ~ /^POWER_SUPPLY_CHARGE_FULL_DESIGN$/ {
- charge_full_design = $NF / 1000000
- b_ma="true"
- }
- $1 ~ /^POWER_SUPPLY_CHARGE_FULL$/ {
- charge_full = $NF / 1000000
- b_ma="true"
+ elsif ($file eq 'charge_full_design'){
+ $value = $value/1000000;
+ $b_ma = 1;
}
- $1 ~ /^POWER_SUPPLY_CHARGE_NOW$/ {
- charge_now = $NF / 1000000
- b_ma="true"
+ elsif ($file eq 'charge_full'){
+ $value = $value/1000000;
+ $b_ma = 1;
}
- $1 ~ /^POWER_SUPPLY_CAPACITY$/ {
- if ( $NF != "" ){
- capacity=$NF "%"
- }
+ elsif ($file eq 'charge_now'){
+ $value = $value/1000000;
+ $b_ma = 1;
}
- $1 ~ /^POWER_SUPPLY_CAPACITY_LEVEL$/ {
- capacity_level=$NF
+ elsif ($file eq 'manufacturer'){
+ $value = main::dmi_cleaner($value);
}
- $1 ~ /^POWER_SUPPLY_MODEL_NAME$/ {
- model=$NF
+ elsif ($file eq 'model_name'){
+ $value = main::dmi_cleaner($value);
}
- $1 ~ /^POWER_SUPPLY_MANUFACTURER$/ {
- company=$NF
- }
- $1 ~ /^POWER_SUPPLY_SERIAL_NUMBER$/ {
- serial=$NF
- }
- END {
- # note:voltage_now fluctuates, which will make capacity numbers change a bit
- # if any of these values failed, the math will be wrong, but no way to fix that
- # tests show more systems give right capacity/charge with voltage_min_design
- # than with voltage_now
- if (b_ma == "true" && voltage_min_design != ""){
- if (charge_now != ""){
- energy_now=charge_now*voltage_min_design
- }
- if (charge_full != ""){
- energy_full=charge_full*voltage_min_design
- }
- if (charge_full_design != ""){
- energy_full_design=charge_full_design*voltage_min_design
- }
- }
- if (energy_now != "" && energy_full != "" ){
- capacity = 100*energy_now/energy_full
- capacity = sprintf( "%.1f%", capacity )
- }
- if (energy_full_design != "" && energy_full != "" ){
- of_orig=100*energy_full/energy_full_design
- of_orig = sprintf( "%.0f%", of_orig )
- }
- if (energy_now != "" ){
- energy_now = sprintf( "%.1f", energy_now )
- }
- if (energy_full_design != "" ){
- energy_full_design = sprintf( "%.1f", energy_full_design )
- }
- if ( energy_full != "" ){
- energy_full = sprintf( "%.1f", energy_full )
- }
- entry = name "," status "," present "," chemistry "," cycles "," voltage_min_design "," voltage_now ","
- entry = entry power_now "," energy_full_design "," energy_full "," energy_now "," capacity ","
- entry = entry capacity_level "," of_orig "," model "," company "," serial "," location
- print entry
- }' < $battery_file )
- # <<< "$data" )
- # < $battery_file )
- A_BATTERY_DATA[$count]=$battery_data
- IFS="$ORIGINAL_IFS"
- fi
- done
- elif [[ $B_FORCE_DMIDECODE == 'true' ]] || [[ ! -d $id_dir && -z $ids ]];then
- set_dmidecode_data
- if [[ -n $DMIDECODE_DATA ]];then
- if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
- A_BATTERY_DATA[0]=$DMIDECODE_DATA
- # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
- else
- IFS=$'\n'
- # NOTE: this logic has a flaw, which is multiple batteries, which won't work without
- # gawk arrays, but sorry, too much of a pain given how little useful data from dmidecode
- A_BATTERY_DATA=( $( gawk -F ':' '
- BEGIN {
- IGNORECASE=1
- name=""
- status=""
- present=""
- chemistry=""
- cycles=""
- voltage_min_design=""
- voltage_now=""
- power_now=""
- charge_full_design=""
- charge_full=""
- charge_now=""
- capacity=""
- capacity_level=""
- model=""
- company=""
- serial=""
- of_orig=""
- location=""
- bItemFound="false"
+ }
+ $battery{$id}{$file} = $value;
+ # print "$battery{$id}{$file}\n";
+ }
+ # note:voltage_now fluctuates, which will make capacity numbers change a bit
+ # if any of these values failed, the math will be wrong, but no way to fix that
+ # tests show more systems give right capacity/charge with voltage_min_design
+ # than with voltage_now
+ if ($b_ma && $battery{$id}{'voltage_min_design'}){
+ if ($battery{$id}{'charge_now'}){
+ $battery{$id}{'energy_now'} = $battery{$id}{'charge_now'} * $battery{$id}{'voltage_min_design'};
+ }
+ if ($battery{$id}{'charge_full'}){
+ $battery{$id}{'energy_full'} = $battery{$id}{'charge_full'}*$battery{$id}{'voltage_min_design'};
+ }
+ if ($battery{$id}{'charge_full_design'}){
+ $battery{$id}{'energy_full_design'} = $battery{$id}{'charge_full_design'} * $battery{$id}{'voltage_min_design'};
+ }
+ }
+ if ( $battery{$id}{'energy_now'} && $battery{$id}{'energy_full'} ){
+ $battery{$id}{'capacity'} = 100 * $battery{$id}{'energy_now'}/$battery{$id}{'energy_full'};
+ $battery{$id}{'capacity'} = sprintf( "%.1f", $battery{$id}{'capacity'} );
+ }
+ if ( $battery{$id}{'energy_full_design'} && $battery{$id}{'energy_full'} ){
+ $battery{$id}{'of_orig'} = 100 * $battery{$id}{'energy_full'}/$battery{$id}{'energy_full_design'};
+ $battery{$id}{'of_orig'} = sprintf( "%.0f", $battery{$id}{'of_orig'} );
+ }
+ if ( $battery{$id}{'energy_now'} ){
+ $battery{$id}{'energy_now'} = sprintf( "%.1f", $battery{$id}{'energy_now'} );
+ }
+ if ( $battery{$id}{'energy_full_design'} ){
+ $battery{$id}{'energy_full_design'} = sprintf( "%.1f",$battery{$id}{'energy_full_design'} );
+ }
+ if ( $battery{$id}{'energy_full'} ){
+ $battery{$id}{'energy_full'} = sprintf( "%.1f", $battery{$id}{'energy_full'} );
+ }
+ }
+ eval $end if $b_log;
+ return %battery;
+}
+# note, dmidecode does not have charge_now or charge_full
+sub battery_data_dmi {
+ eval $start if $b_log;
+ my (%battery,$id);
+ my $i = 0;
+ foreach (@dmi){
+ my @ref = @$_;
+ # Portable Battery
+ if ($ref[0] == 22){
+ $id = "BAT$i";
+ $i++;
+ $battery{$id} = ({});
+ # skip first three row, we don't need that data
+ splice @ref, 0, 3 if @ref;
+ foreach my $item (@ref){
+ my @value = split /:\s+/, $item;
+ next if !$value[0];
+ if ($value[0] eq 'Location') {$battery{$id}{'location'} = $value[1] }
+ elsif ($value[0] eq 'Manufacturer') {$battery{$id}{'manufacturer'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] =~ /Chemistry/) {$battery{$id}{'technology'} = $value[1] }
+ elsif ($value[0] =~ /Serial Number/) {$battery{$id}{'serial_number'} = $value[1] }
+ elsif ($value[0] =~ /^Name/) {$battery{$id}{'model_name'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Design Capacity') {
+ $value[1] =~ s/\s*mwh$//i;
+ $battery{$id}{'energy_full_design'} = sprintf( "%.1f", $value[1]/1000);
+
}
- {
- gsub(/'"$BAN_LIST_NORMAL"'|,|battery|unknown/, "", $2)
- gsub(/^ +| +$/, "", $1)
- gsub(/^ +| +$/, "", $2)
- }
- /^Portable Battery/ {
- while ( getline && !/^$/ ) {
- if ( $1 ~ /^Location/ ) { location=$2 }
- if ( $1 ~ /^Manufacturer/ ) { company=$2 }
- if ( $1 ~ /^Serial/ ) { serial=$2 }
- if ( $1 ~ /^Name/ ) { model=$2 }
- if ( $1 ~ /^Design Capacity/ ) {
- sub(/^[[:space:]]*mwh/, "", $2)
- charge_full_design = $NF / 1000
- charge_full_design = sprintf( "%.1f", charge_full_design )
- }
- if ( $1 ~ /^Design Voltage/ ) {
- sub(/^[[:space:]]*mv/, "", $2)
- voltage_min_design = $NF / 1000
- voltage_min_design = sprintf( "%.1f", voltage_min_design )
- }
- if ( $1 ~ /^SBDS Chemistry/ ) { chemistry=$2 }
- }
- testString=company serial model charge_full_design voltage_min_design
- if ( testString != "" ) {
- bItemFound="true"
- exit # exit loop, we are not handling > 1 batteries
- }
+ elsif ($value[0] eq 'Design Voltage') {
+ $value[1] =~ s/\s*mv$//i;
+ $battery{$id}{'voltage_min_design'} = sprintf( "%.1f", $value[1]/1000);
}
- END {
- if ( bItemFound == "true" ) {
- name="BAT-1"
- if (charge_now != "" && charge_full != "" ){
- capacity = 100*charge_now/charge_full
- capacity = sprintf( "%.1f%", capacity )
- }
- if (charge_full_design != "" && charge_full != "" ){
- of_orig=100*charge_full/charge_full_design
- of_orig = sprintf( "%.0f%", of_orig )
- }
- entry = name "," status "," present "," chemistry "," cycles "," voltage_min_design "," voltage_now ","
- entry = entry power_now "," charge_full_design "," charge_full "," charge_now "," capacity ","
- entry = entry capacity_level "," of_orig "," model "," company "," serial "," location
- print entry
- }
- }' <<< "$DMIDECODE_DATA" ) )
- IFS="$ORIGINAL_IFS"
- fi
- fi
- fi
- # echo $array_string
-
- #echo ${#A_BATTERY_DATA[@]}
- a_temp=${A_BATTERY_DATA[@]}
-
- # echo $a_temp
- log_function_data "A_BATTERY_DATA: $a_temp"
- eval $LOGFE
+ }
+ if ($battery{$id}{'energy_now'} && $battery{$id}{'energy_full'} ){
+ $battery{$id}{'capacity'} = 100 * $battery{$id}{'energy_now'} / $battery{$id}{'energy_full'};
+ $battery{$id}{'capacity'} = sprintf( "%.1f%", $battery{$id}{'capacity'} );
+ }
+ if ($battery{$id}{'energy_full_design'} && $battery{$id}{'energy_full'} ){
+ $battery{$id}{'of_orig'} = 100 * $battery{$id}{'energy_full'} / $battery{$id}{'energy_full_design'};
+ $battery{$id}{'of_orig'} = sprintf( "%.0f%", $battery{$id}{'of_orig'} );
+ }
+ }
+ elsif ($ref[0] > 22){
+ last;
+ }
+ }
+ # print Data::Dumper::Dumper \%battery;
+ eval $end if $b_log;
+ return %battery;
}
-
-## args: $1 type [intel|amd|centaur|arm]; $2 family [hex]; $3 model id [hex];
-get_cpu_architecture()
-{
- eval $LOGFS
- case $1 in
- # https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
- amd)
- case $2 in
- 4)
- case $3 in
- 3|7|8|9|A)ARCH='Am486';;
- E|F)ARCH='Am5x86';;
- esac
- ;;
- 5)
- case $3 in
- 0|1|2|3)ARCH='K5';;
- 6|7)ARCH='K6';;
- 8)ARCH='K6-2';;
- 9|D)ARCH='K6-3';;
- A)ARCH='Geode';;
- esac
- ;;
- 6)
- case $3 in
- 1|2)ARCH='K7';;
- 3|4)ARCH='K7 Thunderbird';;
- 6|7|8|A)ARCH='K7 Palomino+';;
- *)ARCH='K7';;
- esac
- ;;
- F)
- case $3 in
- 4|5|7|8|B|C|E|F|14|15|17|18|1B|1C|1F)ARCH='K8';;
- 21|23|24|25|27|28|2C|2F)ARCH='K8 rev.E';;
- 41|43|48|4B|4C|4F|5D|5F|68|6B|6C|6F|7C|7F|C1)ARCH='K8 rev.F+';;
- *)ARCH='K8';;
- esac
- ;;
- 10)
- case $3 in
- 2|4|5|6|8|9|A)ARCH='K10';;
- *)ARCH='K10';;
- esac
- ;;
- 11)
- case $3 in
- 3)ARCH='Turion X2 Ultra';;
- esac
- ;;
- 12) # might also need cache handling like 14/16
- case $3 in
- 1)ARCH='Fusion';;
- *)ARCH='Fusion';;
- esac
- ;;
- 14) # SOC, apu
- case $3 in
- 1|2)ARCH='Bobcat';;
- *)ARCH='Bobcat';;
- esac
- ;;
- 15)
- case $3 in
- 0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)ARCH='Bulldozer';;
- 10|11|12|13|14|15|16|17|18|19|1A|1B|1C|1D|1E|1F)ARCH='Piledriver';;
- 30|31|32|33|34|35|36|37|38|39|3A|3B|3C|3D|3E|3F)ARCH='Steamroller';;
- 60|61|62|63|64|65|66|67|68|69|6A|6B|6C|6D|6E|6F|70|71|72|73|74|75|76|77|78|79|7A|7B|7C|7D|7E|7F)ARCH='Excavator';;
- *)ARCH='Bulldozer';;
- esac
- ;;
- 16) # SOC, apu
- case $3 in
- 0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)ARCH='Jaguar';;
- 30|31|32|33|34|35|36|37|38|39|3A|3B|3C|3D|3E|3F)ARCH='Puma';;
- *)ARCH='Jaguar';;
- esac
- ;;
- 17)
- case $3 in
- 1)ARCH='Zen';;
- *)ARCH='Zen';;
- esac
- ;;
- esac
- ;;
- arm)
- if [[ "$2" != '' ]];then
- ARCH="ARMv$2"
- else
- ARCH='ARM'
- fi
- ;;
- centaur) # aka VIA
- case $2 in
- 5)
- case $3 in
- 4)ARCH='WinChip C6';;
- 8)ARCH='WinChip 2';;
- 9)ARCH='WinChip 3';;
- esac
- ;;
- 6)
- case $3 in
- 6)ARCH='WinChip-based';;
- 7|8)ARCH='C3';;
- 9)ARCH='C3-2';;
- A|D)ARCH='C7';;
- F)ARCH='Isaiah';;
- esac
- ;;
- esac
- ;;
- intel)
- case $2 in
- 4)
- case $3 in
- 0|1|2|3|4|5|6|7|8|9)ARCH='486';;
- esac
- ;;
- 5)
- case $3 in
- 1|2|3|7)ARCH='P5';;
- 4|8)ARCH='P5';; # MMX
- 9)ARCH='Quark';;
- esac
- ;;
- 6)
- case $3 in
- 1)ARCH='P6 Pro';;
- 3|5|6)ARCH='P6 II';;
- 7|8|A|B)ARCH='P6 III';;
- 9)ARCH='Banias';; # pentium M
- 15)ARCH='Dothan Tolapai';; # pentium M system on chip
- D)ARCH='Dothan';; # Pentium M
- E)ARCH='Yonah';;
- F|16)ARCH='Conroe';;
- 17|1D)ARCH='Penryn';;
- 1A|1E|1F|2E|25|2C|2F)ARCH='Nehalem';;
- 1C|26)ARCH='Bonnell';;
- 27|35|36)ARCH='Saltwell';;
- 25|2C|2F)ARCH='Westmere';;
- 26|27)ARCH='Bonnell';;
- 2A|2D)ARCH='Sandy Bridge';;
- 37|4A|4D|5A)ARCH='Silvermont';;
- 3A|3E)ARCH='Ivy Bridge';;
- 3C|3F|45|46)ARCH='Haswell';;
- 3D|47|4F|56)ARCH='Broadwell';;
- 4E|55|9E)ARCH='Skylake';;
- 5E)ARCH='Skylake-S';;
- 4C|5D)ARCH='Airmont';;
- 8E|9E)ARCH='Kaby Lake';;
- 57)ARCH='Knights Landing';;
- 85)ARCH='Knights Mill';;
- # product codes: https://en.wikipedia.org/wiki/List_of_Intel_microprocessors
- # coming: coffee lake; cannonlake; icelake; tigerlake
- esac
- ;;
- B)
- case $3 in
- 1)ARCH='Knights Corner';;
- esac
- ;;
- F)
- case $3 in
- 0|1|2)ARCH='Netburst Willamette';;
- 3|4|6)ARCH='Netburst Prescott';; # Nocona
- *)ARCH='Netburst';;
- esac
- ;;
- esac
- ;;
-
- esac
- log_function_data "ARCH: $ARCH"
- eval $LOGFE
}
-## create A_CPU_CORE_DATA, currently with two values: integer core count; core string text
-## return value cpu core count string, this helps resolve the multi redundant lines of old style output
-get_cpu_core_count()
-{
- eval $LOGFS
- local cpu_physical_count='' cpu_core_count='' cpu_type='' cores_per_cpu=''
- local array_data=''
-
- if [[ $B_CPUINFO_FILE == 'true' ]]; then
- # load the A_CPU_TYPE_PCNT_CCNT core data array
- get_cpu_ht_multicore_smp_data
- ## Because of the upcoming release of cpus with core counts over 6, a count of cores is given after Deca (10)
- # count the number of processors given
- cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]}
- cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]}
- cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]}
-
- # match the numberic value to an alpha value
- get_cpu_core_count_alpha "$cpu_core_count"
-
- # create array, core count integer; core count string
- # A_CPU_CORE_DATA=( "$cpu_core_count" "$CPU_COUNT_ALPHA Core$cpu_type" )
- array_data="$cpu_physical_count,$CPU_COUNT_ALPHA,$cpu_type,$cpu_core_count"
- IFS=','
- A_CPU_CORE_DATA=( $array_data )
- IFS="$ORIGINAL_IFS"
- elif [[ -n $BSD_TYPE ]];then
- local gawk_fs=': '
-
- if [[ $BSD_VERSION == 'openbsd' ]];then
- gawk_fs='='
- fi
- cpu_core_count=$( gawk -F "$gawk_fs" -v bsdVersion="$BSD_VERSION" '
- # note: on openbsd can also be hw.ncpufound so exit after first
- BEGIN {
- coreCount=""
- }
- $1 ~ /^hw.ncpu$/ {
- coreCount=$NF
- }
- /^machdep.cpu.core_count/ {
- coreCount=$NF
- }
- END {
- print coreCount
- }' <<< "$SYSCTL_A_DATA" )
- cores_per_cpu=$( gawk -F "$gawk_fs" '
- /^machdep.cpu.cores_per_package/ {
- print $NF
- }' <<< "$SYSCTL_A_DATA" )
-
- if [[ -n $( grep -E '^[0-9]+$' <<< "$cpu_core_count" ) ]];then
- get_cpu_core_count_alpha "$cpu_core_count"
- if [[ $cpu_core_count -gt 1 ]];then
- cpu_type='-SMP-'
- else
- cpu_type='-UP-'
- fi
- fi
- if [[ -n $cores_per_cpu ]];then
- cpu_physical_count=$(( $cpu_core_count / $cores_per_cpu ))
- if [[ $cores_per_cpu -gt 1 ]];then
- cpu_type='-MCP-'
- fi
- # do not guess here, only use phys count if it actually exists, otherwise handle in print_cpu..
- # this 1 value should not be used for output, and is just to avoid math errors
- else
- cpu_physical_count=1
- fi
- array_data="$cpu_physical_count,$CPU_COUNT_ALPHA,$cpu_type,$cpu_core_count"
- IFS=','
- A_CPU_CORE_DATA=( $array_data )
- IFS="$ORIGINAL_IFS"
- fi
- a_temp=${A_CPU_CORE_DATA[@]}
- # echo $a_temp :: ${#A_CPU_CORE_DATA[@]}
- log_function_data "A_CPU_CORE_DATA: $a_temp"
- eval $LOGFE
-}
-
-# args: $1 - integer core count
-get_cpu_core_count_alpha()
+## CpuData
{
- eval $LOGFS
-
- case $1 in
- 1) CPU_COUNT_ALPHA='Single';;
- 2) CPU_COUNT_ALPHA='Dual';;
- 3) CPU_COUNT_ALPHA='Triple';;
- 4) CPU_COUNT_ALPHA='Quad';;
- *) CPU_COUNT_ALPHA=$1;;
- esac
- log_function_data "CPU_COUNT_ALPHA: $CPU_COUNT_ALPHA"
-
- eval $LOGFE
+package CpuData;
+
+sub get {
+ eval $start if $b_log;
+ my ($type) = @_;
+ my (@data,@rows,$single,$key1,$val1);
+ my $num = 0;
+ if ($type eq 'short' || $type eq 'basic'){
+ @rows = data_short($type);
+ }
+ else {
+ @rows = create_output_full();
+ }
+ eval $end if $b_log;
+ return @rows;
}
-
-## main cpu data collector
-get_cpu_data()
-{
- eval $LOGFS
- local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' a_temp=''
- local bsd_cpu_flags='' min_speed='' max_speed=''
-
- if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq ]];then
- max_speed=$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq)
- if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]];then
- min_speed=$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq)
- fi
- fi
-
- if [[ $B_CPUINFO_FILE == 'true' ]];then
- # stop script for a bit to let cpu slow down before parsing cpu /proc file
- sleep $CPU_SLEEP
- IFS=$'\n'
- A_CPU_DATA=( $(
- gawk -v cpuMin="$min_speed" -v cpuMax="$max_speed" -F': ' '
- BEGIN {
- IGNORECASE=1
- # need to prime nr for arm cpus, which do not have processor number output in some cases
- nr = 0
- count = 0
- bArm = "false"
- bProcInt = "false" # this will avoid certain double counts with processor/Processor lines
- # ARM cpus are erratic in /proc/cpuinfo this hack can sometimes resolve it. Linux only.
- sysSpeed="'$(get_cpu_speed_hack)'"
- speed = 0
- max = 0
- min = 0
- type=""
- family=""
- model_nu=""
- rev=""
- }
- # TAKE STRONGER NOTE: \t+ does NOT always work, MUST be [ \t]+
- # TAKE NOTE: \t+ will work for $FILE_CPUINFO, but SOME ARBITRARY FILE used for TESTING might contain SPACES!
- # Therefore PATCH to use [ \t]+ when TESTING!
- /^processor[ \t]+:/ {
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
- gsub(/^ +| +$/, "", $NF)
- if ( $NF ~ "^[0-9]+$" ) {
- nr = $NF
- bProcInt = "true"
+sub create_output_full {
+ eval $start if $b_log;
+ my $num = 0;
+ my ($b_flags,$flag_key,@flags,%cpu,@data,@rows);
+ my $sleep = $cpu_sleep * 1000000;
+ if ($b_hires){
+ eval 'Time::HiRes::usleep( $sleep )';
+ }
+ else {
+ select(undef, undef, undef, $cpu_sleep);
+ }
+ if (my $file = main::system_files('cpuinfo')){
+ %cpu = data_cpuinfo($file,'full');
+ }
+ elsif ($bsd_type ){
+ my ($key1,$val1) = ('','');
+ if ( $alerts{'sysctl'} ){
+ if ( $alerts{'sysctl'}{'action'} eq 'use' ){
+# $key1 = 'Status';
+# $val1 = main::row_defaults('dev');
+ %cpu = data_sysctl('full');
}
else {
- # this protects against double processor lines, one int, one string
- if ( bProcInt == "false" ){
- count += 1
- nr = count - 1
- }
- # note: alternate:
- # Processor : AArch64 Processor rev 4 (aarch64)
- # but no model name type
- if ( $NF ~ "(ARM|AArch)" ) {
- bArm = "true"
- if ( type=""){
- type="arm"
- }
- }
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
- gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
- gsub(/^ +| +$/, "", $NF)
- gsub(/ [ \t]+/, " ", $NF)
- cpu[nr, "model"] = $NF
+ $key1 = ucfirst($alerts{'sysctl'}{'action'});
+ $val1 = $alerts{'sysctl'}{$alerts{'sysctl'}{'action'}};
+ @data = ({main::key($num++,$key1) => $val1,});
+ return @data;
}
}
- # arm
- /^cpu architecture/ && (family = "") {
- gsub(/^ +| +$/, "", $NF)
- family=$NF
+ }
+ my %properties = cpu_properties(%cpu);
+ my $type = ($properties{'cpu-type'}) ? $properties{'cpu-type'}: '';
+ my $ref = $cpu{'processors'};
+ my @processors = @$ref;
+ my @speeds = cpu_speeds(@processors);
+ my $j = scalar @rows;
+ $cpu{'model_name'} ||= 'N/A';
+ @data = ({
+ main::key($num++,'Topology') => $properties{'cpu-layout'},
+ main::key($num++,'model') => $cpu{'model_name'},
+ },);
+ @rows = (@rows,@data);
+ $properties{'bits-sys'} ||= 'N/A';
+ $rows[$j]{main::key($num++,'bits')} = $properties{'bits-sys'};
+ if ($type){
+ $rows[$j]{main::key($num++,'type')} = $type;
+ }
+ if ($extra > 0){
+ $cpu{'arch'} ||= 'N/A';
+ $rows[$j]{main::key($num++,'arch')} = $cpu{'arch'};
+ if ( $cpu{'arch'} ne 'N/A' && $cpu{'rev'} ){
+ $rows[$j]{main::key($num++,'rev')} = $cpu{'rev'};
}
- /^cpu family/ && ( family == ""){
- gsub(/^ +| +$/, "", $NF)
- family=toupper( sprintf("%x", $NF) )
+ }
+ $properties{'l2-cache'} ||= 'N/A';
+ $rows[$j]{main::key($num++,'L2 cache')} = $properties{'l2-cache'} if (!$b_arm || ($b_arm && $properties{'l2-cache'} ne 'N/A'));
+ if ($extra > 0 && !$show{'cpu-flag'}){
+ $j = scalar @rows;
+ @flags = split /\s+/, $cpu{'flags'} if $cpu{'flags'};
+ $flag_key = ($b_arm || $bsd_type) ? 'features': 'flags';
+ my $flag = 'N/A';
+ if (@flags){
+ # failure to read dmesg.boot: dmesg.boot permissions
+ @flags = grep {/^(dmesg.boot|lm|nx|pae|permissions|pni|svm|vmx|(sss|ss)e([2-9])?([a-z])?(_[0-9])?)$/} @flags;
+ @flags = map {s/pni/sse3/; $_} @flags;
+ @flags = sort(@flags);
+ $flag = join ' ', @flags if @flags;
+ }
+ if ($b_arm && $flag eq 'N/A'){
+ $flag = main::row_defaults('arm-cpu-f');
}
- /^(stepping|cpu revission)/ && ( rev == "" ){
- gsub(/^ +| +$/, "", $NF)
- rev=$NF
+ @data = ({
+ main::key($num++,$flag_key) => $flag,
+ },);
+ @rows = (@rows,@data);
+ $b_flags = 1;
+ }
+ if ($extra > 0 && !$bsd_type){
+ my $bogomips = ($cpu{'bogomips'}) ? int($cpu{'bogomips'}) : 'N/A';
+ $rows[$j]{main::key($num++,'bogomips')} = $bogomips;
+ }
+ $j = scalar @rows;
+ my $core_key = (scalar @speeds > 1) ? 'Core speeds (MHz)' : 'Core speed (MHz)';
+ my $speed_key = ($properties{'speed-key'}) ? $properties{'speed-key'}: 'Speed';
+ my $min_max = ($properties{'min-max'}) ? $properties{'min-max'}: 'N/A';
+ my $min_max_key = ($properties{'min-max-key'}) ? $properties{'min-max-key'}: 'min/max';
+ my $speed = (defined $properties{'speed'}) ? $properties{'speed'}: 'N/A';
+ # aren't able to get per core speeds in bsds yet
+ my $core_speeds_value = (@speeds) ? '' : 'N/A';
+ $j = scalar @rows;
+ @data = ({
+ main::key($num++,$speed_key) => $speed,
+ main::key($num++,$min_max_key) => $min_max,
+ main::key($num++,$core_key) => $core_speeds_value,
+ }, );
+ @rows = (@rows,@data);
+ my $i = 1;
+ foreach (@speeds){
+ $rows[$j]{main::key($num++,$i++)} = $_;
+ }
+ if ($show{'cpu-flag'} && !$b_flags){
+ $flag_key = ($b_arm || $bsd_type) ? 'Features': 'Flags';
+ @flags = split /\s+/, $cpu{'flags'} if $cpu{'flags'};
+ my $flag = 'N/A';
+ if (@flags){
+ @flags = sort(@flags);
+ $flag = join ' ', @flags if @flags;
}
- /^model[ \t]*:/ && ( model_nu == ""){
- gsub(/^ +| +$/, "", $NF)
- model_nu=toupper( sprintf("%x", $NF) )
+ @data = ({
+ main::key($num++,$flag_key) => $flag,
+ },);
+ @rows = (@rows,@data);
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+sub create_output_short {
+ eval $start if $b_log;
+ my (@cpu) = @_;
+ my @data;
+ my $num = 0;
+ $cpu[1] ||= main::row_defaults('cpu-model-null');
+ $cpu[2] ||= 'N/A';
+ @data = ({
+ main::key($num++,$cpu[0]) => $cpu[1],
+ main::key($num++,'type') => $cpu[2],
+ },);
+ if ($extra > 0){
+ $data[0]{main::key($num++,'arch')} = $cpu[7];
+ }
+ $data[0]{main::key($num++,$cpu[3])} = $cpu[4];
+ if ($cpu[6]){
+ $data[0]{main::key($num++,$cpu[5])} = $cpu[6];
+ }
+ eval $end if $b_log;
+ return @data;
+}
+sub data_short {
+ eval $start if $b_log;
+ my ($type) = @_;
+ my $num = 0;
+ my (%cpu,@data,%speeds);
+ my $sys = '/sys/devices/system/cpu/cpufreq/policy0';
+ my $sleep = $cpu_sleep * 1000000;
+ if ($b_hires){
+ eval 'Time::HiRes::usleep( $sleep )';
+ }
+ else {
+ select(undef, undef, undef, $cpu_sleep);
+ }
+ # NOTE: : Permission denied, ie, this is not always readable
+ # /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
+ if (my $file = main::system_files('cpuinfo')){
+ %cpu = data_cpuinfo($file,$type);
+ }
+ elsif ($bsd_type ){
+ my ($key1,$val1) = ('','');
+ if ( $alerts{'sysctl'} ){
+ if ( $alerts{'sysctl'}{'action'} eq 'use' ){
+# $key1 = 'Status';
+# $val1 = main::row_defaults('dev');
+ %cpu = data_sysctl($type);
+ }
+ else {
+ $key1 = ucfirst($alerts{'sysctl'}{'action'});
+ $val1 = $alerts{'sysctl'}{$alerts{'sysctl'}{'action'}};
+ @data = ({main::key($num++,$key1) => $val1,});
+ return @data;
+ }
}
- /^model name|^cpu\t+:/ {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
- gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
- gsub(/^ +| +$/, "", $NF)
- gsub(/ [ \t]+/, " ", $NF)
- cpu[nr, "model"] = $NF
- if ( $NF ~ "^(ARM|AArch)" ) {
- bArm = "true"
+ }
+ # $cpu{'cur-freq'} = $cpu[0]{'core-id'}[0]{'speed'};
+ if ($type eq 'short' || $type eq 'basic'){
+ @data = prep_short_data(%cpu);
+ }
+ if ($type eq 'basic'){
+ @data = create_output_short(@data);
+ }
+ eval $end if $b_log;
+ return @data;
+}
+
+sub prep_short_data {
+ eval $start if $b_log;
+ my (%cpu) = @_;
+ my %properties = cpu_properties(%cpu);
+ my ($cpu,$speed_key,$speed,$type) = ('','speed',0,'');
+ $cpu = $cpu{'model_name'} if $cpu{'model_name'};
+ $type = $properties{'cpu-type'} if $properties{'cpu-type'};
+ $speed_key = $properties{'speed-key'} if $properties{'speed-key'};
+ $speed = $properties{'speed'} if $properties{'speed'};
+ my @result = (
+ $properties{'cpu-layout'},
+ $cpu,
+ $type,
+ $speed_key,
+ $speed,
+ $properties{'min-max-key'},
+ $properties{'min-max'},
+ );
+ if ($extra > 0){
+ $cpu{'arch'} ||= 'N/A';
+ $result[7] = $cpu{'arch'};
+ }
+ eval $end if $b_log;
+ return @result;
+}
+
+sub data_cpuinfo {
+ eval $start if $b_log;
+ my ($file,$type)= @_;
+ my ($arch,@ids,@line,$b_first,$b_proc_int,$starter);
+ # use --arm flag when testing arm cpus
+ # $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";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv7-new-format-model-name-single-core.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-2-die-96-core-rk01.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/16-core-32-mt-ryzen.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/2-16-core-epyc-abucodonosor.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/2-core-probook-antix.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-jean-antix.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-althlon-mjro.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-apu-vc-box.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-a10-5800k-1.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-core-ht-atom-bruh.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/core-2-i3.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/8-core-i7-damentz64.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-10-core-xeon-ht.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-core-xeon-fake-dual-die-zyanya.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-core-i5-fake-dual-die-hek.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-1-core-xeon-vm-vs2017.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-1-core-xeon-vps-frodo1.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-6-core-xeon-no-mt-lathander.txt";
+ my %speeds = set_cpu_speeds_sys();
+ my @cpuinfo = main::reader($file);
+ my @phys_cpus = (0);# start with 1 always
+ my ($cache,$core_count,$die_holder,$die_id,$phys_id,$proc_count,$speed) = (0,0,0,0,0,0,0);
+ my ($phys_holder) = (undef);
+ # need to prime for arm cpus, which do not have physical/core ids usually
+ # level 0 is phys id, level 1 is die id, level 2 is core id
+ #$ids[0] = ([(0)]);
+ $ids[0] = ([]);
+ $ids[0][0] = ([]);
+ my %cpu = set_cpu_data();
+ # note, there con be a lot of processors, 32 core HT would have 64, for example.
+ foreach (@cpuinfo){
+ next if /^\s*$/;
+ @line = split /\s*:\s*/, $_;
+ next if !$line[0];
+ $starter = $line[0]; # preserve case for one specific ARM issue
+ $line[0] = lc($line[0]);
+ if ($b_arm && !$b_first && $starter eq 'Processor' && $line[1] !~ /^\d+$/){
+ #print "l1:$line[1]\n";
+ $cpu{'model_name'} = main::cleaner($line[1]);
+ $cpu{'model_name'} = cpu_cleaner($cpu{'model_name'});
+ $cpu{'type'} = 'arm';
+ # Processor : AArch64 Processor rev 4 (aarch64)
+ # Processor : Feroceon 88FR131 rev 1 (v5l)
+ if ($cpu{'model_name'} && $cpu{'model_name'} =~ /(.*)\srev\s([\S]+)\s(\(([\S]+)\))?/){
+ $cpu{'model_name'} = $1;
+ $cpu{'rev'} = $2;
+ if ($4){
+ $cpu{'arch'} = $4;
+ $cpu{'model_name'} .= ' ' . $cpu{'arch'} if $cpu{'model_name'} !~ /$cpu{'arch'}/i;
+ }
+ $cpu{'processors'}[$proc_count] = 0;
+ $b_proc_int = 0;
+ $b_first = 1;
+ #print "p0:\n";
}
}
- /^cpu MHz|^clock\t+:/ {
- if (speed == 0) {
- speed = $NF
+ elsif ($line[0] eq 'processor'){
+ # this protects against double processor lines, one int, one string
+ if ($line[1] =~ /^\d+$/){
+ $b_proc_int = 1;
+ $b_first = 1;
+ $cpu{'processors'}[$proc_count] = 0;
+ $proc_count++;
+ #print "p1: $proc_count\n";
}
else {
- if ($NF < speed) {
- speed = $NF
+ if (!$b_proc_int){
+ $cpu{'processors'}[$proc_count] = 0;
+ $proc_count++;
+ #print "p2a: $proc_count\n";
}
+ if (!$b_first ){
+ # note: alternate:
+ # Processor : AArch64 Processor rev 4 (aarch64)
+ # but no model name type
+ if ( $b_arm || $line[1] =~ /ARM|AArch/i){
+ $b_arm = 1;
+ $cpu{'type'} = 'arm';
+ }
+ $cpu{'model_name'} = main::cleaner($line[1]);
+ $cpu{'model_name'} = cpu_cleaner($cpu{'model'});
+ #print "p2b:\n";
+ }
+ $b_first = 1;
+ }
+ }
+ elsif (!$cpu{'family'} &&
+ ($line[0] eq 'architecture' || $line[0] eq 'cpu family' || $line[0] eq 'cpu architecture' )){
+ if ($line[1] =~ /^\d+$/){
+ # translate integers to hex
+ $cpu{'family'} = uc(sprintf("%x", $line[1]));
}
- if ($NF > max) {
- max = $NF
+ elsif ($b_arm) {
+ $cpu{'arch'} = $line[1];
}
- gsub(/MHZ/,"",$NF) ## clears out for cell cpu
- gsub(/.00[0]+$/,".00",$NF) ## clears out excessive zeros
- cpu[nr, "speed"] = $NF
}
- /^cache size/ {
- cpu[nr, "cache"] = $NF
+ elsif (!$cpu{'rev'} && ($line[0] eq 'stepping' || $line[0] eq 'cpu revision' )){
+ $cpu{'rev'} = $line[1];
}
- /^flags|^features/ {
- cpu[nr, "flags"] = $NF
- # not all ARM cpus show ARM in model name
- if ( $1 ~ /^features/ ) {
- bArm = "true"
- }
+ # this is hex so uc for cpu arch id
+ elsif (!$cpu{'model_id'} && $line[0] eq 'model' ){
+ $cpu{'model_id'} = uc(sprintf("%x", $line[1]));
}
- /^bogomips/ {
- cpu[nr, "bogomips"] = $NF
- # print nr " " cpu[nr, "bogomips"] > "/dev/tty"
+ elsif (!$cpu{'model_id'} && $line[0] eq 'cpu variant' ){
+ $cpu{'model_id'} = uc($line[1]);
+ $cpu{'model_id'} =~ s/^0X//;
}
- /vendor_id/ {
- gsub(/genuine|authentic/,"",$NF)
- cpu[nr, "vendor"] = tolower( $NF )
- if ( type == ""){
- if ( $NF ~ /.*intel.*/ ) {
- type="intel"
- }
- else if ($NF ~ /.*amd.*/){
- type="amd"
- }
- # via
- else if ($NF ~ /.*centaur.*/){
- type="centaur"
+ # cpu can show in arm
+ elsif (!$cpu{'model_name'} &&( $line[0] eq 'model name' || $line[0] eq 'cpu' )){
+ $cpu{'model_name'} = main::cleaner($line[1]);
+ $cpu{'model_name'} = cpu_cleaner($cpu{'model_name'});
+ if ( $b_arm || $line[1] =~ /ARM|AArch/i){
+ $b_arm = 1;
+ $cpu{'type'} = 'arm';
+ if ($cpu{'model_name'} && $cpu{'model_name'} =~ /(.*)\srev\s([\S]+)\s(\(([\S]+)\))?/){
+ $cpu{'model_name'} = $1;
+ $cpu{'rev'} = $2;
+ if ($4){
+ $cpu{'arch'} = $4;
+ $cpu{'model_name'} .= ' ' . $cpu{'arch'} if $cpu{'model_name'} !~ /$cpu{'arch'}/i;
+ }
+ #$cpu{'processors'}[$proc_count] = 0;
}
}
}
- END {
- #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that
- for ( i = 0; i <= nr; i++ ) {
- # note: assuming bogomips for arm at 1 x clock
- # http://en.wikipedia.org/wiki/BogoMips ARM could change so watch this
- # maybe add: && bArm == "true" but I think most of the bogomips roughly equal cpu speed if not amd/intel
- # 2014-04-08: trying to use sysSpeed hack first, that is more accurate anyway.
- if ( ( cpu[i, "speed"] == "" && sysSpeed != "" ) || \
- ( cpu[i, "speed"] == "" && cpu[i, "bogomips"] != "" && cpu[i, "bogomips"] < 50 ) ) {
- cpu[i, "speed"] = sysSpeed
- }
- else if ( cpu[i, "bogomips"] != "" && cpu[i, "speed"] == "" ) {
- cpu[i, "speed"] = cpu[i, "bogomips"]
-
- }
- print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] "," cpu[nr, "vendor"] "," bArm
+ elsif ( $line[0] eq 'cpu mhz' ){
+ $speed = speed_cleaner($line[1]);
+ $cpu{'processors'}[$proc_count-1] = $speed;
+ #$ids[$phys_id][$die_id] = ([($speed)]);
+ }
+ elsif (!$cpu{'siblings'} && $line[0] eq 'siblings' ){
+ $cpu{'siblings'} = $line[1];
+ }
+ elsif (!$cpu{'cores'} && $line[0] eq 'cpu cores' ){
+ $cpu{'cores'} = $line[1];
+ }
+ # increment by 1 for every new physical id we see. These are in almost all cases
+ # separate cpus, not separate dies within a single cpu body.
+ elsif ( $line[0] eq 'physical id' ){
+ if ( !defined $phys_holder || $phys_holder != $line[1] ){
+ # only increment if not in array counter
+ push @phys_cpus, $line[1] if ! grep {/$line[1]/} @phys_cpus;
+ $phys_holder = $line[1];
+ $ids[$phys_holder] = ([]) if ! exists $ids[$phys_holder];
+ $ids[$phys_holder][$die_id] = ([]) if ! exists $ids[$phys_holder][$die_id];
+ #print "pid: $line[1] ph: $phys_holder did: $die_id\n";
+ $die_id = 0;
+ #$die_holder = 0;
}
- if (cpuMin != "") {
- min=cpuMin/1000
+ }
+ elsif ( $line[0] eq 'core id' ){
+ #print "ph: $phys_holder did: $die_id l1: $line[1] s: $speed\n";
+ # https://www.pcworld.com/article/3214635/components-processors/ryzen-threadripper-review-we-test-amds-monster-cpu.html
+ if ($line[1] > 0 ){
+ $die_holder = $line[1];
+ $core_count++;
}
- if (cpuMax != "") {
- max=cpuMax/1000
+ # NOTE: this logic won't work for die detections, unforutnately.
+ # ARM uses a different /sys based method, and ryzen relies on math on the cores
+ # in process_data
+ elsif ($line[1] == 0 && $die_holder > 0 ){
+ $die_holder = $line[1];
+ $core_count = 0;
+ $die_id++ if ($cpu{'type'} ne 'intel' && $cpu{'type'} ne 'amd' );
}
- # create last array index, to be used for min/max output
- sub(/\.[0-9]+$/,"",max)
- sub(/\.[0-9]+$/,"",speed)
- sub(/\.[0-9]+$/,"",min)
- if ( bArm == "true" ){
- type = "arm"
+ $phys_holder = 0 if ! defined $phys_holder;
+ $ids[$phys_holder][$die_id][$line[1]] = $speed;
+ #print "ph: $phys_holder did: $die_id l1: $line[1] s: $speed\n";
+ }
+ if (!$cpu{'type'} && $line[0] eq 'vendor_id' ){
+ $cpu{'type'} = cpu_vendor($line[1]);
+ }
+ ## this is only for -C full cpu output
+ if ( $type eq 'full' ){
+ if (!$cpu{'l2-cache'} && $line[0] eq 'cache size'){
+ if ($line[1] =~ /(\d+)\sKB$/){
+ $cpu{'l2-cache'} = $1;
+ }
+ elsif ($line[1] =~ /(\d+)\sMB$/){
+ $cpu{'l2-cache'} = ($1*1024);
+ }
}
- if (speed == 0) {
- print "N/A," min "," max "," type "," family "," model_nu
+ if (!$cpu{'flags'} && ($line[0] eq 'flags' || $line[0] eq 'features' )){
+ $cpu{'flags'} = $line[1];
}
- else {
- # print speed "," min "," max "," type "," family "," model_nu "," rev > "/dev/tty"
- print speed "," min "," max "," type "," family "," model_nu "," rev
+ }
+ if ( $extra > 0 && $type eq 'full' ){
+ if ($line[0] eq 'bogomips'){
+ # new arm shows bad bogomip value, so don't use it
+ $cpu{'bogomips'} += $line[1] if $line[1] > 50;
}
- }
- ' $FILE_CPUINFO ) )
-
- IFS="$ORIGINAL_IFS"
- log_function_data 'cat' "$FILE_CPUINFO"
- elif [[ -n $BSD_TYPE ]];then
- get_cpu_data_bsd
- fi
-
- a_temp=${A_CPU_DATA[@]}
- log_function_data "A_CPU_DATA: $a_temp"
-# echo ta: ${a_temp[@]}
- eval $LOGFE
-# echo getMainCpu: ${[@]}
-}
-# this triggers in one and only one case, ARM cpus that have fake bogomips data
-get_cpu_speed_hack()
-{
- local speed=$( cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 2>/dev/null )
-
- if [[ -n $speed ]];then
- speed=${speed%[0-9][0-9][0-9]} # trim off last 3 digits
- fi
- echo $speed
+ }
+ }
+ $cpu{'phys'} = scalar @phys_cpus;
+ $cpu{'dies'} = $die_id++; # count starts at 0, all cpus have 1 die at least
+ if ($b_arm && $cpu{'dies'} <= 1){
+ my $arm_dies = cpu_dies_sys();
+ # case were 4 core arm returned 4 sibling lists, obviously wrong
+ $cpu{'dies'} = $arm_dies if $arm_dies && $proc_count != $arm_dies;
+ }
+ $cpu{'type'} = 'arm' if $b_arm && !$cpu{'type'};
+ $cpu{'ids'} = (\@ids);
+ if ( $extra > 0 && !$cpu{'arch'} && $type ne 'short' ){
+ $cpu{'arch'} = cpu_arch($cpu{'type'},$cpu{'family'},$cpu{'model_id'});
+ #print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n";
+ }
+ if (!$speeds{'cur-freq'}){
+ $cpu{'cur-freq'} = $cpu{'processors'}[0];
+ $speeds{'min-freq'} = 0;
+ $speeds{'max-freq'} = 0;
+ }
+ else {
+ $cpu{'cur-freq'} = $speeds{'cur-freq'};
+ $cpu{'min-freq'} = $speeds{'min-freq'};
+ $cpu{'max-freq'} = $speeds{'max-freq'};
+ }
+ main::log_data('dump','%cpu',\%cpu) if $b_log;
+ print Data::Dumper::Dumper \%cpu if $test[8];
+ eval $end if $b_log;
+ return %cpu;
}
-get_cpu_data_bsd()
-{
- eval $LOGFS
-
- local bsd_cpu_flags=$( get_cpu_flags_bsd )
- local gawk_fs=': ' cpu_max=''
-
- if [[ $BSD_VERSION == 'openbsd' ]];then
- gawk_fs='='
- fi
- # avoid setting this for systems where you have no read/execute permissions
- # might be cases where the dmesg boot file was readable but sysctl perms failed
- if [[ -n $SYSCTL_A_DATA || -n $bsd_cpu_flags ]];then
- if [[ -n $DMESG_BOOT_DATA ]];then
- cpu_max=$( gawk -F ':' '
- BEGIN {
- IGNORECASE=1
- }
- # NOTE: freebsd may say: 2300-MHz, so check for dash as well
- $1 ~ /^(CPU|cpu0)$/ {
- if ( $NF ~ /[^0-9\.][0-9\.]+[\-[:space:]]*[MG]Hz/) {
- max=gensub(/.*[^0-9\.]([0-9\.]+[\-[:space:]]*[MG]Hz).*/,"\\1",1,$NF)
- if (max ~ /MHz/) {
- sub(/[-[:space:]]*MHz/,"",max)
- }
- if (max ~ /GHz/) {
- sub(/[-[:space:]]*GHz/,"",max)
- max=max*1000
- }
- print max
- exit
- }
- }' <<< "$DMESG_BOOT_DATA" )
- fi
- IFS=$'\n'
- A_CPU_DATA=( $(
- gawk -F "$gawk_fs" -v bsdVersion=$BSD_VERSION -v cpuFlags="$bsd_cpu_flags" -v cpuMax="$cpu_max" '
- BEGIN {
- IGNORECASE=1
- cpuModel=""
- cpuClock=""
- cpuCache=""
- cpuBogomips=""
- cpuVendor=""
- bSwitchFs="false"
- min=0
- max=0
- # these can be found in dmesg.boot just like in cpuinfo except all in one row
- type=""
- family=""
- model_nu=""
- rev=""
- }
- /^hw.model/ && ( bsdVersion != "darwin" ) {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
- gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
- gsub(/'"$BAN_LIST_ARRAY"'/," ",$NF)
- sub(/[a-z]+-core/, "", $NF )
- gsub(/^ +| +$|\"/, "", $NF)
- gsub(/ [ \t]+/, " ", $NF)
+sub data_sysctl {
+ eval $start if $b_log;
+ my ($type) = @_;
+ my %cpu = set_cpu_data();
+ my (@ids,@line,%speeds,@working);
+ my ($sep) = ('');
+ my ($cache,$die_holder,$die_id,$phys_holder,$phys_id,$proc_count,$speed) = (0,0,0,0,0,0,0);
+ foreach (@sysctl){
+ @line = split /\s*:\s*/, $_;
+ next if ! $line[0];
+ # darwin shows machine, like MacBook7,1, not cpu
+ # machdep.cpu.brand_string: Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz
+ if ( ($bsd_type ne 'darwin' && $line[0] eq 'hw.model' ) || $line[0] eq 'machdep.cpu.brand_string' ){
# cut L2 cache/cpu max speed out of model string, if available
- if ( $NF ~ /[0-9]+[[:space:]]*[KM]B[[:space:]]+L2 cache/) {
- cpuCache=gensub(/.*[^0-9]([0-9]+[[:space:]]*[KM]B)[[:space:]]+L2 cach.*/,"\\1",1,$NF)
+ # openbsd 5.6: AMD Sempron(tm) Processor 3400+ ("AuthenticAMD" 686-class, 256KB L2 cache)
+ # 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/) {
+ my $multiplier = ($2 eq 'KB') ? 1024: 1;
+ $cpu{'l2-cache'} = $1 * $multiplier;
}
- if ( $NF ~ /[^0-9\.][0-9\.]+[\-[:space:]]*[MG]Hz/) {
- max=gensub(/.*[^0-9\.]([0-9\.]+[\-[:space:]]*[MG]Hz).*/,"\\1",1,$NF)
- if (max ~ /MHz/) {
- sub(/[\-[:space:]]*MHz/,"",max)
+ if ( $line[1] =~ /([^0-9\.][0-9\.]+)[\-[:space:]]*[MG]Hz/) {
+ $cpu{'max-freq'} = $1;
+ if ($cpu{'max-freq'} =~ /MHz/i) {
+ $cpu{'max-freq'} =~ s/[\-[:space:]]*MHz//;
+ $cpu{'max-freq'} = speed_cleaner($cpu{'max-freq'},'mhz');
}
- if (max ~ /GHz/) {
- sub(/[\-[:space:]]*GHz/,"",max)
- max=max*1000
+ elsif ($cpu{'max-freq'} =~ /GHz/) {
+ $cpu{'max-freq'} =~ s/[\-[:space:]]*GHz//i;
+ $cpu{'max-freq'} = $cpu{'max-freq'} / 1000;
+ $cpu{'max-freq'} = speed_cleaner($cpu{'max-freq'},'mhz');
}
}
- if ( $NF ~ /\)$/ ){
- sub(/[[:space:]]*\(.*\)$/,"",$NF)
+ if ( $line[1] =~ /\)$/ ){
+ $line[1] =~ s/\s*\(.*\)$//;
}
- cpuModel=$NF
-# if ( cpuClock != "" ) {
-# exit
-# }
+ $cpu{'model_name'} = $line[1];
+ $cpu{'type'} = cpu_vendor($line[1]);
}
- /^hw.clock/ {
- cpuClock=$NF
-# if ( cpuModel != "" ) {
-# exit
-# }
+ # NOTE: hw.l1icachesize: hw.l1dcachesize:
+ elsif ($line[0] eq 'hw.l1icachesize') {
+ $cpu{'l1-cache'} = $line[1]/1024;
+ }
+ elsif ($line[0] eq 'hw.l2cachesize') {
+ $cpu{'l2-cache'} = $line[1]/1024;
+ }
+ # this is in mghz in samples
+ elsif ($line[0] eq 'hw.clockrate' || $line[0] eq 'hw.cpuspeed') {
+ $cpu{'cur-freq'} = $line[1];
}
- /^hw.cpufrequency/ {
- cpuClock = $NF / 1000000
+ # these are in hz: 2400000000
+ elsif ($line[0] eq 'hw.cpufrequency') {
+ $cpu{'cur-freq'} = $line[1]/1000000;
}
- /^hw.cpuspeed/ {
- cpuClock=$NF
+ elsif ($line[0] eq 'hw.busfrequency_min') {
+ $cpu{'min-freq'} = $line[1]/1000000;
}
- /^hw.l2cachesize/ {
- cpuCache=$NF/1024
- cpuCache=cpuCache " kB"
+ elsif ($line[0] eq 'hw.busfrequency_max') {
+ $cpu{'max-freq'} = $line[1]/1000000;
}
- /^machdep.cpu.vendor/ {
- cpuVendor=$NF
+ elsif ($line[0] eq 'machdep.cpu.vendor') {
+ $cpu{'type'} = cpu_vendor($line[1]);
+ }
+ # darwin only?
+ elsif ($line[0] eq 'machdep.cpu.features') {
+ $cpu{'flags'} = lc($line[1]);
+ }
+ elsif ($line[0] eq 'hw.ncpu' ) {
+ $cpu{'cores'} = $line[1];
}
# Freebsd does some voltage hacking to actually run at lowest listed frequencies.
# The cpu does not actually support all the speeds output here but works in freebsd.
- /^dev.cpu.0.freq_levels/ {
- gsub(/^[[:space:]]+|\/[0-9]+|[[:space:]]+$/,"",$NF)
- if ( $NF ~ /[0-9]+[[:space:]]+[0-9]+/ ) {
- min=gensub(/.*[[:space:]]([0-9]+)$/,"\\1",1,$NF)
- max=gensub(/^([0-9]+)[[:space:]].*/,"\\1",1,$NF)
- }
- }
- /^machdep.cpu.brand_string/ {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
- gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
- gsub(/'"$BAN_LIST_ARRAY"'/," ",$NF)
- sub(/[a-z]+-core/, "", $NF )
- gsub(/^ +| +$|\"/, "", $NF)
- gsub(/ [ \t]+/, " ", $NF)
- sub(/[[:space:]]*@.*/,"",$NF)
- cpuModel=$NF
- }
- END {
- if ( max == 0 && cpuMax != "" ) {
- max=cpuMax
- }
- if ( cpuClock == "" ) {
- cpuClock="N/A"
- }
- sub(/\.[0-9]+/,"",cpuClock)
- sub(/\.[0-9]+/,"",min)
- sub(/\.[0-9]+/,"",max)
- print cpuModel "," cpuClock "," cpuCache "," cpuFlags "," cpuBogomips "," cpuVendor
- # triggers print case, for architecture, check source for syntax
- print cpuClock "," min "," max ",,,,"
- }' <<< "$SYSCTL_A_DATA" ) )
- IFS="$ORIGINAL_IFS"
- fi
-
- eval $LOGFE
+ elsif ($line[0] eq 'dev.cpu.0.freq_levels') {
+ $line[1] =~ s/^\s+|\/[0-9]+|\s+$//g;
+ if ( $line[1] =~ /[0-9]+\s+[0-9]+/ ) {
+ my @temp = split /\s+/, $line[1];
+ $cpu{'max-freq'} = $temp[0];
+ $cpu{'min-freq'} = $temp[-1];
+ $cpu{'scalings'} = \@temp;
+ }
+ }
+ elsif (!$cpu{'cur-freq'} && $line[0] eq 'dev.cpu.0.freq' ) {
+ $cpu{'cur-freq'} = $line[1];
+ }
+ # the following have only been seen in DragonflyBSD data but thumbs up!
+ elsif ($line[0] eq 'hw.cpu_topology.members' ) {
+ my @temp = split /\s+/, $line[1];
+ my $count = scalar @temp;
+ $count-- if $count > 0;
+ $cpu{'processors'}[$count] = 0;
+ # no way to get per processor speeds yet, so assign 0 to each
+ foreach (0 .. $count){
+ $cpu{'processors'}[$_] = 0;
+ }
+ }
+ elsif ($line[0] eq 'hw.cpu_topology.cpu1.physical_siblings' ) {
+ # string, like: cpu0 cpu1
+ my @temp = split /\s+/, $line[1];
+ $cpu{'siblings'} = scalar @temp;
+ }
+ # increment by 1 for every new physical id we see. These are in almost all cases
+ # separate cpus, not separate dies within a single cpu body.
+ elsif ( $line[0] eq 'hw.cpu_topology.cpu0.physical_id' ){
+ if ($phys_holder != $line[1] ){
+ $phys_id++;
+ $phys_holder = $line[1];
+ $ids[$phys_id] = ([(0)]);
+ $ids[$phys_id][$die_id] = ([(0)]);
+ }
+ }
+ elsif ( $line[0] eq 'hw.cpu_topology.cpu0.core_id' ){
+ if ($line[1] > 0 ){
+ $die_holder = $line[1];
+ }
+ # this handles multi die cpus like 16 core ryzen
+ elsif ($line[1] == 0 && $die_holder > 0 ){
+ $die_id++ ;
+ $die_holder = $line[1];
+ }
+ $ids[$phys_id][$die_id][$line[1]] = $speed;
+ $cpu{'dies'} = $die_id;
+ }
+ }
+ if (!$cpu{'flags'}){
+ $cpu{'flags'} = cpu_flags_bsd();
+ }
+ main::log_data('dump','%cpu',\%cpu) if $b_log;
+ print Data::Dumper::Dumper \%cpu if $test[8];
+ eval $end if $b_log;
+ return %cpu;
}
-get_cpu_flags_bsd()
-{
- eval $LOGFS
-
- local cpu_flags=''
- local gawk_fs=':'
-
- if [[ -n $DMESG_BOOT_DATA ]];then
- cpu_flags=$( gawk -v bsdVersion="$BSD_VERSION" -F ":" '
- BEGIN {
- IGNORECASE=1
- cpuFlags=""
- }
- /^(CPU:|cpu0:)/ {
- while ( getline && !/memory|real mem/ ) {
- if ( $1 ~ /Features/ || ( bsdVersion == "openbsd" && $0 ~ /^cpu0.*[[:space:]][a-z][a-z][a-z][[:space:]][a-z][a-z][a-z][[:space:]]/ ) ) {
- # clean up odd stuff like <b23>
- gsub(/<[a-z0-9]+>/,"", $2)
- # all the flags are contained within < ... > on freebsd at least
- gsub(/.*<|>.*/,"", $2)
- gsub(/'"$BAN_LIST_ARRAY"'/," ", $2)
- cpuFlags = cpuFlags " " $2
- }
- }
- cpuFlags=tolower(cpuFlags)
- print cpuFlags
- exit
- }' <<< "$DMESG_BOOT_DATA" )
- elif [[ -n $SYSCTL_A_DATA ]];then
- if [[ $BSD_VERSION == 'openbsd' ]];then
- gawk_fs=':'
- fi
- cpu_flags=$( gawk -F "$gawk_fs" '
- BEGIN {
- cpuFlags=""
- }
- /^machdep.cpu.features/ {
- cpuFlags=tolower($NF)
- print cpuFlags
- exit
- }' <<< "$SYSCTL_A_DATA" )
- fi
- echo $cpu_flags
- log_function_data "$cpu_flags"
- eval $LOGFE
-}
-
-## this is for counting processors and finding HT types
-get_cpu_ht_multicore_smp_data()
-{
- eval $LOGFS
- # in /proc/cpuinfo
- local a_temp=''
-
- # note: known bug with xeon intel, they show a_core_id/physical_id as 0 for ht 4 core
- if [[ $B_CPUINFO_FILE == 'true' ]]; then
- A_CPU_TYPE_PCNT_CCNT=( $(
- gawk '
- BEGIN {
- FS=": "
- IGNORECASE = 1
- num_of_cores = 0
- num_of_processors = 0
- num_of_physical_cpus = 0
- cpu_core_count = 0
- siblings = 0
- # these 3 arrays cannot be declared because that sets the first element
- # but leaving this here so that we avoid doing that in the future
- # a_core_id = ""
- # a_processor_id = ""
- # a_physical_id = ""
- cpu_type = "-"
- # note: we need separate iterators because some cpuinfo data has only
- # processor, no core id or phys id
- proc_iter = 0
- core_iter = "" # set from actual NF data
- phys_iter = "" # set from actual NF data
- # needed to handle arm cpu, no processor number cases
- arm_count = 0
- nr = 0
- bArm = "false"
- bRyzen = "false"
- bProcInt = "false" # this will avoid certain double counts with processor/Processor lines
- bXeon = "false"
- }
- # hack to handle xeons which can have buggy /proc/cpuinfo files
- /^model name/ && ( $0 ~ /Xeon/ ) {
- bXeon = "true"
- }
- # amd rizen 16/32 core maybe
- /^cpu_family/ && ($2 == 23) {
- bRyzen = "true"
- }
- # only do this once since sibling count does not change.
- /^siblings/ && ( bXeon == "true" || bRyzen == "true" ) && ( siblings == 0 ) {
- gsub(/[^0-9]/,"",$NF)
- if ( $NF != "" ) {
- siblings = $NF
- }
- }
- # array of logical processors, both HT and physical
- # IMPORTANT: some variants have two lines, one the actual cpu id number,
- # the other a misnamed model name line.
- # processor : 0
- # Processor : AArch64 Processor rev 4 (aarch64)
- /^processor/ {
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
- gsub(/^ +| +$/, "", $NF)
- if ( $NF ~ "^[0-9]+$" ) {
- a_processor_id[proc_iter] = $NF
- proc_iter++
- bProcInt = "true"
+sub cpu_properties {
+ my (%cpu) = @_;
+ my ($b_amd_zen,$b_epyc,$b_ht,$b_intel,$b_ryzen,$b_xeon);
+ if ($cpu{'type'} ){
+ if ($cpu{'type'} eq 'intel'){
+ $b_intel = 1;
+ $b_xeon = 1 if $cpu{'model_name'} =~ /Xeon/i;
+ }
+ elsif ($cpu{'type'} eq 'amd' ){
+ if ( $cpu{'family'} && $cpu{'family'} eq '17' ) {
+ $b_amd_zen = 1;
+ if ($cpu{'model_name'} ){
+ if ($cpu{'model_name'} =~ /Ryzen/i ){
+ $b_ryzen = 1;
+ }
+ elsif ($cpu{'model_name'} =~ /EPYC/i){
+ $b_epyc = 1;
+ }
+ }
}
- else {
- # note, for dual core, this can be off by one because the first
- # line says: Processor : Arm.. but subsequent say: processor : 0 and so on as usual
- # Processor : AArch64 Processor rev 4 (aarch64)
- if ( $NF ~ "^(ARM|AArch)" ) {
- bArm = "true"
- }
- # this protects against double processor lines, one int, one string
- if ( bProcInt == "false" ){
- arm_count += 1
- nr = arm_count - 1
- # note: do not iterate because new ARM syntax puts cpu in processsor : 0 syntax
- a_processor_id[proc_iter] = nr
- }
- }
- }
- # array of physical cpu ids, note, this will be unset for vm cpus in many cases
- # because they have no physical cpu, so we cannot assume this will be here.
- /^physical/ {
- phys_iter = $NF
- a_physical_id[phys_iter] = $NF
- }
- # array of core ids, again, here we may have HT, so we need to create an array of the
- # actual core ids. As With physical, we cannot assume this will be here in a vm
- # also, for xeon/rizen, this can be misleading because there may be two cpus
- # inside the single cpu body, which leads to: 0-7 then 0-7 for a rizen 16 core ht
- /^core id/ {
- core_iter = $NF
- a_core_id[core_iter] = $NF
- }
- # this will be used to fix an intel glitch if needed, cause, intel
- # sometimes reports core id as the same number for each core,
- # so if cpu cores shows greater value than number of cores, use this.
- /^cpu cores/ {
- cpu_core_count = $NF
- }
- END {
- ## Look thru the array and filter same numbers.
- ## only unique numbers required
- ## this is to get an accurate count
- ## we are only concerned with array length
- i = 0
- ## count unique processors ##
- # note, this fails for intel cpus at times
- for ( i in a_processor_id ) {
- num_of_processors++
- }
- i = 0
- ## count unique physical cpus ##
- for ( i in a_physical_id ) {
- num_of_physical_cpus++
- }
- i = 0
- ## count unique cores. Fails for 16 core rizen, which appears to be
- ## using 2x8 core internally, core id 0-7 repeats 2 times.
- for ( i in a_core_id ) {
- num_of_cores++
- }
- # xeon may show wrong core / physical id count, if it does, fix it. A xeon
- # may show a repeated core id : 0 which gives a fake num_of_cores=1
- if ( bXeon == "true" && num_of_cores == 1 && siblings > 1 ) {
- num_of_cores = siblings/2
+ }
+ }
+ #my @dies = $phys[0][0];
+ my $ref = $cpu{'ids'};
+ my @phys = @$ref;
+ my $phyical_count = 0;
+ #my $phyical_count = scalar @phys;
+ my @processors;
+ my ($speed,$speed_key);
+ # handle case where cpu reports say, phys id 0, 2, 4, 6 [yes, seen it]
+ foreach (@phys) {
+ $phyical_count++ if $_;
+ }
+ $phyical_count ||= 1; # assume 1 if no id found, as with ARM
+ # count unique processors ##
+ # note, this fails for intel cpus at times
+ $ref = $cpu{'processors'};
+ @processors = @$ref;
+ #print ref $cpu{'processors'}, "\n";
+ my $processors_count = scalar @processors;
+ #print "p count:$processors_count\n";
+ #print Data::Dumper::Dumper \@processors;
+ # $cpu_cores is per physical cpu
+ my ($cpu_layout,$cpu_type,$min_max,$min_max_key) = ('','','','');
+ my ($cache,$core_count,$cpu_cores,$die_count) = (0,0,0,0);
+ foreach my $die_ref ( @phys ){
+ next if ! $die_ref;
+ my @dies = @$die_ref;
+ $core_count = 0;
+ $die_count = scalar @dies;
+ #$cpu{'dies'} = $die_count;
+ foreach my $core_ref (@dies){
+ next if ref $core_ref ne 'ARRAY';
+ my @cores = @$core_ref;
+ $core_count = 0;# reset for each die!!
+ # NOTE: the counters can be undefined because the index comes from
+ # core id: which can be 0 skip 1 then 2, which leaves index 1 undefined
+ # arm cpus do not actually show core id so ignore that counter
+ foreach my $id (@cores){
+ $core_count++ if defined $id && !$b_arm;
+ }
+ #print 'cores: ' . $core_count, "\n";
+ }
+ }
+ # this covers potentially cases where ARM cpus have > 1 die
+ $cpu{'dies'} = ($b_arm && $die_count <= 1 && $cpu{'dies'} > 1) ? $cpu{'dies'}: $die_count;
+ # this is an attempt to fix the amd family 15 bug with reported cores vs actual cores
+ # NOTE: amd A6-4400M APU 2 core reports: cores: 1 siblings: 2
+ # NOTE: AMD A10-5800K APU 4 core reports: cores: 2 siblings: 4
+ if ($cpu{'cores'} && ! $core_count || $cpu{'cores'} >= $core_count){
+ $cpu_cores = $cpu{'cores'};
+ }
+ elsif ($core_count > $cpu{'cores'}){
+ $cpu_cores = $core_count;
+ }
+ #print "cpu-c:$cpu_cores\n";
+ #$cpu_cores = $cpu{'cores'};
+ # like, intel core duo
+ # NOTE: sadly, not all core intel are HT/MT, oh well...
+ # xeon may show wrong core / physical id count, if it does, fix it. A xeon
+ # may show a repeated core id : 0 which gives a fake num_of_cores=1
+ if ($b_intel){
+ if ($cpu{'siblings'} && $cpu{'siblings'} > 1 && $cpu{'cores'} && $cpu{'cores'} > 1 ){
+ if ( $cpu{'siblings'}/$cpu{'cores'} == 1 ){
+ $b_intel = 0;
+ $b_ht = 0;
}
- #
- if ( bRyzen == "true"){
- num_of_cores = cpu_core_count
- }
- # final check, override the num of cores value if it clearly is wrong
- # and use the raw core count and synthesize the total instead of real count
- if ( ( num_of_cores == 0 ) && ( cpu_core_count * num_of_physical_cpus > 1 ) ) {
- num_of_cores = cpu_core_count * num_of_physical_cpus
- }
- # last check, seeing some intel cpus and vms with intel cpus that do not show any
- # core id data at all, or siblings.
- if ( num_of_cores == 0 && num_of_processors > 0 ) {
- num_of_cores = num_of_processors
- }
- # ARM/vm cpu fix, if no physical or core found, use count of 1 instead
- if ( num_of_physical_cpus == 0 ) {
- num_of_physical_cpus = 1
- }
-# print "NoCpu: " num_of_physical_cpus
-# print "NoCores: " num_of_cores
-# print "NoProc:" num_of_processors
-# print "CpuCoreCount:" cpu_core_count
- ####################################################################
- # algorithm
- # if > 1 processor && processor id (physical id) == core id then Multi threaded (MT)
- # if siblings > 1 && siblings == 2 * num_of_cores (cpu_core_count) then Multi threaded (MT)
- # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP)
- # if > 1 processor && processor ids (physical id) > 1 then Symmetric Multi Processing (SMP)
- # if = 1 processor then single core/processor Uni-Processor (UP)
- if ( num_of_processors > 1 || ( bXeon == "true" && siblings > 0 ) ) {
- # non-multicore MT
- if ( num_of_processors == (num_of_cores * 2) ) {
- cpu_type = cpu_type "MT-"
- }
- else if ( bXeon == "true" && siblings > 1 ) {
- cpu_type = cpu_type "MT-"
- }
- else if ( siblings > 1 && siblings == 2 * num_of_cores ){
- cpu_type = cpu_type "MT-"
- }
- # non-MT multi-core or MT multi-core
- if (( num_of_processors == num_of_cores) || ( num_of_physical_cpus < num_of_cores)) {
- cpu_type = cpu_type "MCP-"
- }
- # >1 cpu sockets active: Symetric Multi Processing
- if ( num_of_physical_cpus > 1 ) {
- cpu_type = cpu_type "SMP-"
- }
- }
else {
- cpu_type = cpu_type "UP-"
- }
-
- print cpu_type " " num_of_physical_cpus " " num_of_cores
+ $cpu_cores = ($cpu{'siblings'}/2);
+ $b_ht = 1;
+ }
+ }
+ }
+ # ryzen is made out of blocks of 8 core dies
+ elsif ($b_ryzen){
+ $cpu_cores = $cpu{'cores'};
+ # note: posix ceil isn't present in Perl for some reason, deprecated?
+ my $working = $cpu_cores / 8;
+ my @temp = split /\./, $working;
+ $cpu{'dies'} = ($temp[1] && $temp[1] > 0) ? $temp[0]++ : $temp[0];
+ }
+ # these always have 4 dies
+ elsif ($b_epyc) {
+ $cpu_cores = $cpu{'cores'};
+ $cpu{'dies'} = 4;
+ }
+ # final check, override the num of cores value if it clearly is wrong
+ # and use the raw core count and synthesize the total instead of real count
+ if ( $cpu_cores == 0 && ($cpu{'cores'} * $phyical_count > 1)){
+ $cpu_cores = ($cpu{'cores'} * $phyical_count);
+ }
+ # last check, seeing some intel cpus and vms with intel cpus that do not show any
+ # core id data at all, or siblings.
+ if ($cpu_cores == 0 && $processors_count > 0){
+ $cpu_cores = $processors_count;
+ }
+ # this happens with BSDs which have very little cpu data available
+ if ( $processors_count == 0 && $cpu_cores > 0 ){
+ $processors_count = $cpu_cores;
+ if ($bsd_type && ($b_ht || $b_amd_zen) && $cpu_cores > 2 ){
+ $cpu_cores = $cpu_cores/2;;
+ }
+ my $count = $processors_count;
+ $count-- if $count > 0;
+ $cpu{'processors'}[$count] = 0;
+ # no way to get per processor speeds yet, so assign 0 to each
+ # must be a numeric value. Could use raw speed from core 0, but
+ # that would just be a hack.
+ foreach (0 .. $count){
+ $cpu{'processors'}[$_] = 0;
+ }
+ }
+ # last test to catch some corner cases
+ # seen a case where a xeon vm in a dual xeon system actually had 2 cores, no MT
+ # so it reported 4 siblings, 2 cores, but actually only had 1 core per virtual cpu
+ #print "prc: $processors_count phc: $phyical_count coc: $core_count cpc: $cpu_cores\n";
+ if (!$b_arm && $processors_count == $phyical_count*$core_count && $cpu_cores > $core_count){
+ $b_ht = 0;
+ #$b_xeon = 0;
+ $b_intel = 0;
+ $cpu_cores = 1;
+ $core_count = 1;
+ $cpu{'siblings'} = 1;
+ }
+ #print "pc: $processors_count s: $cpu{'siblings'} cpuc: $cpu_cores corec: $core_count\n";
+ # Algorithm:
+ # if > 1 processor && processor id (physical id) == core id then Multi threaded (MT)
+ # if siblings > 1 && siblings == 2 * num_of_cores ($cpu{'cores'}) then Multi threaded (MT)
+ # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP)
+ # if > 1 processor && processor ids (physical id) > 1 then Symmetric Multi Processing (SMP)
+ # if = 1 processor then single core/processor Uni-Processor (UP)
+ if ( $processors_count > 1 || ( $b_intel && $cpu{'siblings'} > 0 ) ) {
+ # non-multicore MT
+ if ($processors_count == ($phyical_count * $cpu_cores * 2)){
+ #print "mt:1\n";
+ $cpu_type .= 'MT';
+ }
+# elsif ($b_xeon && $cpu{'siblings'} > 1){
+# #print "mt:2\n";
+# $cpu_type .= 'MT';
+# }
+ elsif ($cpu{'siblings'} > 1 && ($cpu{'siblings'} == 2 * $cpu_cores )){
+ #print "mt:3\n";
+ $cpu_type .= 'MT';
+ }
+ # non-MT multi-core or MT multi-core
+ if ( ($processors_count == $cpu_cores ) || ($phyical_count < $cpu_cores)){
+ my $sep = ($cpu_type) ? ' ' : '' ;
+ $cpu_type .= $sep . 'MCP';
}
- ' $FILE_CPUINFO ) )
- fi
- a_temp=${A_CPU_TYPE_PCNT_CCNT[@]}
- log_function_data "A_CPU_TYPE_PCNT_CCNT: $a_temp"
- eval $LOGFE
+ # only solidly known > 1 die cpus will use this, ryzen and arm for now
+ if ( $cpu{'dies'} > 1 ){
+ my $sep = ($cpu_type) ? ' ' : '' ;
+ $cpu_type .= $sep . 'MCM';
+ }
+ # >1 cpu sockets active: Symetric Multi Processing
+ if ($phyical_count > 1){
+ my $sep = ($cpu_type) ? ' ' : '' ;
+ $cpu_type .= $sep . 'SMP';
+ }
+ }
+ else {
+ $cpu_type = 'UP';
+ }
+ if ($phyical_count > 1){
+ $cpu_layout = $phyical_count . 'x ';
+ }
+ $cpu_layout .= count_alpha($cpu_cores) . 'Core';
+ $cpu_layout .= ' (' . $cpu{'dies'}. '-Die)' if !$bsd_type && $cpu{'dies'} > 1;
+ # the only possible change for bsds is if we can get phys counts in the future
+ if ($bsd_type){
+ $cache = $cpu{'l2-cache'} * $phyical_count;
+ }
+ # AMD SOS chips appear to report full L2 cache per core
+ elsif ($cpu{'type'} eq 'amd' && ($cpu{'family'} eq '14' || $cpu{'family'} eq '15' || $cpu{'family'} eq '16')){
+ $cache = $cpu{'l2-cache'} * $phyical_count;
+ }
+ elsif ($cpu{'type'} ne 'intel'){
+ $cache = $cpu{'l2-cache'} * $cpu_cores * $phyical_count;
+ }
+ ## note: this handles how intel reports L2, total instead of per core like AMD does
+ # note that we need to multiply by number of actual cpus here to get true cache size
+ else {
+ $cache = $cpu{'l2-cache'} * $phyical_count;
+ }
+ if ($cache > 10000){
+ $cache = sprintf("%.01f MiB",$cache/1024); # trim to no decimals?
+ }
+ elsif ($cache > 0){
+ $cache = "$cache KiB";
+ }
+ if ($cpu{'cur-freq'} && $cpu{'min-freq'} && $cpu{'max-freq'} ){
+ $min_max = "$cpu{'min-freq'}/$cpu{'max-freq'} MHz";
+ $min_max_key = "min/max";
+ $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed';
+ $speed = "$cpu{'cur-freq'} MHz";
+ }
+ elsif ($cpu{'cur-freq'} && $cpu{'max-freq'}){
+ $min_max = "$cpu{'max-freq'} MHz";
+ $min_max_key = "max";
+ $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed';
+ $speed = "$cpu{'cur-freq'} MHz";
+ }
+# elsif ($cpu{'cur-freq'} && $cpu{'max-freq'} && $cpu{'cur-freq'} == $cpu{'max-freq'}){
+# $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed';
+# $speed = "$cpu{'cur-freq'} MHz (max)";
+# }
+ elsif ($cpu{'cur-freq'} && $cpu{'min-freq'}){
+ $min_max = "$cpu{'min-freq'} MHz";
+ $min_max_key = "min";
+ $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed';
+ $speed = "$cpu{'cur-freq'} MHz";
+ }
+ elsif ($cpu{'cur-freq'} && !$cpu{'max-freq'}){
+ $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed';
+ $speed = "$cpu{'cur-freq'} MHz";
+ }
+
+ if ( !$bits_sys && !$b_arm && $cpu{'flags'} ){
+ $bits_sys = ($cpu{'flags'} =~ /\blm\b/) ? 64 : 32;
+ }
+ my %cpu_properties = (
+ 'bits-sys' => $bits_sys,
+ 'cpu-layout' => $cpu_layout,
+ 'cpu-type' => $cpu_type,
+ 'min-max-key' => $min_max_key,
+ 'min-max' => $min_max,
+ 'speed-key' => $speed_key,
+ 'speed' => $speed,
+ 'l2-cache' => $cache,
+ );
+ main::log_data('dump','%cpu_properties',\%cpu_properties) if $b_log;
+ #print Data::Dumper::Dumper \%cpu;
+ #print Data::Dumper::Dumper \%cpu_properties;
+ #my $dc = scalar @dies;
+ #print 'phys: ' . $pc . ' dies: ' . $dc, "\n";
+ eval $end if $b_log;
+ return %cpu_properties;
+}
+sub cpu_speeds {
+ eval $start if $b_log;
+ my (@processors) = @_;
+ my (@speeds);
+ my @files = main::globber('/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq');
+ foreach (@files){
+ my $speed = (main::reader($_))[0];
+ if ($speed || $speed eq '0'){
+ $speed = sprintf "%.0f", $speed/1000;
+ push @speeds, $speed;
+ }
+ }
+ if (!@speeds){
+ foreach (@processors){
+ if ($_ || $_ eq '0'){
+ $_ = sprintf "%.0f", $_;
+ push @speeds, $_;
+ }
+ }
+ }
+ #print join '; ', @speeds, "\n";
+ eval $end if $b_log;
+ return @speeds;
+}
+sub set_cpu_speeds_sys {
+ eval $start if $b_log;
+ my (@arm,%speeds);
+ my $sys = '/sys/devices/system/cpu/cpufreq/policy0';
+ my $sys2 = '/sys/devices/system/cpu/cpu0/cpufreq/';
+ my ($cur,$min,$max) = ('scaling_cur_freq','scaling_min_freq','scaling_max_freq');
+ if (!-d $sys && -d $sys2){
+ $sys = $sys2;
+ ($cur,$min,$max) = ('scaling_cur_freq','cpuinfo_min_freq','cpuinfo_max_freq');
+ }
+ if (-d $sys){
+ $speeds{'cur-freq'} = (main::reader("$sys/$cur"))[0];
+ $speeds{'cur-freq'} = speed_cleaner($speeds{'cur-freq'},'khz');
+ $speeds{'min-freq'} = (main::reader("$sys/$min"))[0];
+ $speeds{'min-freq'} = speed_cleaner($speeds{'min-freq'},'khz');
+ $speeds{'max-freq'} = (main::reader("$sys/$max"))[0];
+ $speeds{'max-freq'} = speed_cleaner($speeds{'max-freq'},'khz');
+ if ($b_arm){
+ @arm = main::globber('/sys/devices/system/cpu/cpufreq/policy*/');
+ # there are arm chips with two dies, that run at different min max speeds!!
+ # see: https://github.com/smxi/inxi/issues/128.
+ # it would be slick to show both die min/max/cur speeds, but this is
+ # ok for now.
+ if (scalar @arm > 1){
+ my ($current,$max,$min) = (0,0,0);
+ foreach (@arm){
+ $_ =~ s/\/$//; # strip off last slash in case globs have them
+ my $max_temp = main::reader("$_/cpuinfo_max_freq");
+ $max_temp = speed_cleaner($max_temp,'khz');
+ if ($max_temp > $max){
+ $max = $max_temp;
+ }
+ my $min_temp = main::reader("$_/cpuinfo_min_freq");
+ $min_temp = speed_cleaner($min_temp,'khz');
+ if ($min_temp < $min || $min == 0){
+ $max = $min_temp;
+ }
+ my $cur_temp = main::reader("$_/cpuinfo_max_freq");
+ $cur_temp = speed_cleaner($cur_temp,'khz');
+ if ($cur_temp > $current){
+ $current = $cur_temp;
+ }
+ }
+ $speeds{'cur-freq'} = $current if $current;
+ $speeds{'max-freq'} = $max if $max;
+ $speeds{'min-freq'} = $min if $min;
+ }
+ }
+ # policy4/cpuinfo_max_freq:["2000000"]
+ # policy4/cpuinfo_min_freq:["200000"]
+ if ($speeds{'min-freq'} > $speeds{'max-freq'} || $speeds{'min-freq'} == $speeds{'max-freq'}){
+ $speeds{'min-freq'} = 0;
+ }
+ }
+ main::log_data('dump','%speeds',\%speeds) if $b_log;
+ eval $end if $b_log;
+ return %speeds;
}
-# Detect desktop environment in use, initial rough logic from: compiz-check
-# http://forlong.blogage.de/entries/pages/Compiz-Check
-# NOTE $XDG_CURRENT_DESKTOP envvar is not reliable, but it shows certain desktops better.
-# most desktops are not using it as of 2014-01-13 (KDE, UNITY, LXDE. Not Gnome)
-get_desktop_environment()
-{
- eval $LOGFS
-
- # set the default, this function only runs in X, if null, don't print data out
- local desktop_environment='' xprop_root='' version2=''
- local version='' version_data='' version2_data='' toolkit=''
-
- # works on 4, assume 5 will id the same, why not, no need to update in future
- # KDE_SESSION_VERSION is the integer version of the desktop
- # NOTE: as of plasma 5, the tool: about-distro MAY be available, that will show
- # actual desktop data, so once that's in debian/ubuntu, if it gets in, add that test
- if [[ $XDG_CURRENT_DESKTOP == 'KDE' || -n $KDE_SESSION_VERSION ]]; then
- # note the command is actually like, kded4 --version, so we construct it
- # this was supposed to extend to 5, but 5 changed it, so it uses the more reliable way
- if [[ $KDE_SESSION_VERSION -le 4 ]];then
- version_data=$( kded$KDE_SESSION_VERSION --version 2>/dev/null )
- version=$( grep -si '^KDE Development Platform:' <<< "$version_data" | gawk '{print $4}' )
- else
- # NOTE: this command string is almost certain to change, and break, with next major plasma desktop, ie, 6
- # version=$( qdbus org.kde.plasmashell /MainApplication org.qtproject.Qt.QCoreApplication.applicationVersion 2>/dev/null )
- #Qt: 5.4.2
- #KDE Frameworks: 5.11.0
- #kf5-config: 1.0
- # for QT, and Frameworks if we use it
- if type -p kf$KDE_SESSION_VERSION-config &>/dev/null;then
- version_data=$( kf$KDE_SESSION_VERSION-config --version 2>/dev/null )
- # version=$( grep -si '^KDE Frameworks:' <<< "$version_data" | gawk '{print $NF}' )
- fi
- # plasmashell 5.3.90
- if type -p plasmashell &>/dev/null;then
- version2_data=$( plasmashell --version 2>/dev/null )
- version=$( grep -si '^plasmashell' <<< "$version2_data" | gawk '{print $NF}' )
- fi
- fi
- if [[ -z $version ]];then
- version=$KDE_SESSION_VERSION
- fi
- if [[ $B_EXTRA_DATA == 'true' && -n $version_data ]];then
- toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
- if [[ -n $toolkit ]];then
- version="$version (Qt $toolkit)"
- fi
- fi
- desktop_environment="KDE Plasma"
- # KDE_FULL_SESSION property is only available since KDE 3.5.5.
- # src: http://humanreadable.nfshost.com/files/startkde
- elif [[ $KDE_FULL_SESSION == 'true' ]]; then
- version_data=$( kded --version 2>/dev/null )
- version=$( grep -si '^KDE:' <<< "$version_data" | gawk '{print $2}' )
- # version=$( get_program_version 'kded' '^KDE:' '2' )
- if [[ -z $version ]];then
- version='3.5'
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
- if [[ -n $toolkit ]];then
- version="$version (Qt $toolkit)"
- fi
- fi
- desktop_environment="KDE"
- elif [[ $XDG_CURRENT_DESKTOP == 'Unity' ]];then
- version=$( get_program_version 'unity' '^unity' '2' )
- # not certain will always have version, so keep output right if not
- if [[ -n $version ]];then
- version="$version "
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_de_gtk_data )
- if [[ -n $toolkit ]];then
- version="$version(Gtk $toolkit)"
- fi
- fi
- desktop_environment="Unity"
- elif [[ $XDG_CURRENT_DESKTOP == *Budgie* ]];then
- version=$( get_program_version 'budgie-desktop' '^budgie-desktop' '2' )
- # not certain will always have version, so keep output right if not
- if [[ -n $version ]];then
- version="$version "
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_de_gtk_data )
- if [[ -n $toolkit ]];then
- version="$version(Gtk $toolkit)"
- fi
- fi
- desktop_environment="Budgie"
- elif [[ $XDG_CURRENT_DESKTOP == 'LXQt' ]];then
-# if type -p lxqt-about &>/dev/null;then
-# version=$( get_program_version 'lxqt-about' '^lxqt-about' '2' )
-# fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- if kded$KDE_SESSION_VERSION &>/dev/null;then
- version_data=$( kded$KDE_SESSION_VERSION --version 2>/dev/null )
- toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
- elif type -p qtdiag &>/dev/null;then
- toolkit=$( get_program_version 'qtdiag' '^qt' '2' )
- fi
- if [[ -n $toolkit ]];then
- version="$version (Qt $toolkit)"
- fi
- fi
- desktop_environment='LXQt'
- # note, X-Cinnamon value strikes me as highly likely to change, so just search for the last part
- elif [[ -n $XDG_CURRENT_DESKTOP && -z ${XDG_CURRENT_DESKTOP/*innamon*/} ]];then
- version=$( get_program_version 'cinnamon' '^cinnamon' '2' )
- # not certain cinn will always have version, so keep output right if not
- if [[ -n $version ]];then
- version="$version "
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_de_gtk_data )
- if [[ -n $toolkit ]];then
- version="$version(Gtk $toolkit)"
- fi
- fi
- desktop_environment="Cinnamon"
- fi
- # did we find it? If not, start the xprop tests
- if [[ -z $desktop_environment ]];then
- if type -p xprop &>/dev/null;then
- xprop_root="$( xprop -root $DISPLAY_OPT 2>/dev/null | tr '[:upper:]' '[:lower:]' )"
- fi
- # note that cinnamon split from gnome, and and can now be id'ed via xprop,
- # but it will still trigger the next gnome true case, so this needs to go before gnome test
- # eventually this needs to be better organized so all the xprop tests are in the same
- # section, but this is good enough for now.
- if [[ -n $xprop_root && -z ${xprop_root/*_muffin*/} ]];then
- version=$( get_program_version 'cinnamon' '^cinnamon' '2' )
- # not certain cinn will always have version, so keep output right if not
- if [[ -n $version ]];then
- version="$version "
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_de_gtk_data )
- if [[ -n $toolkit ]];then
- version="$version(Gtk $toolkit)"
- fi
- fi
- desktop_environment="Cinnamon"
- elif [[ $XDG_CURRENT_DESKTOP == 'MATE' ]] || [[ -n $xprop_root && -z ${xprop_root/*_marco*/} ]];then
- version=$( get_program_version 'mate-about' '^MATE[[:space:]]DESKTOP' 'NF' )
- # not certain cinn/mate will always have version, so keep output right if not
- if [[ -n $version ]];then
- version="$version "
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_de_gtk_data )
- if [[ -n $toolkit ]];then
- version="$version(Gtk $toolkit)"
- fi
- fi
- desktop_environment="MATE"
- # note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out
- # https://bugzilla.gnome.org/show_bug.cgi?id=542880
- elif [[ -n $GNOME_DESKTOP_SESSION_ID || $XDG_CURRENT_DESKTOP == 'GNOME' ]]; then
- if type -p gnome-shell &>/dev/null;then
- version=$( get_program_version 'gnome-shell' 'gnome' '3' )
- elif type -p gnome-about &>/dev/null;then
- version=$( get_program_version 'gnome-about' 'gnome' '3' )
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_de_gtk_data )
- if [[ -n $toolkit ]];then
- version="$version (Gtk $toolkit)"
- fi
- fi
- desktop_environment="Gnome"
- fi
- if [[ -z $desktop_environment ]];then
- # now that the primary ones have been handled, next is to find the ones with unique
- # xprop detections possible
- if [[ -n $xprop_root ]];then
- # String: "This is xfdesktop version 4.2.12"
- # alternate: xfce4-about --version > xfce4-about 4.10.0 (Xfce 4.10)
- if [[ -z ${xprop_root/*\"xfce4\"*/} ]];then
- version=$( get_program_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
- # arch linux reports null, so use alternate if null
- if [[ -z $version ]];then
- version=$( get_program_version 'xfce4-panel' '^xfce4-panel' '2' )
- if [[ -z $version ]];then
- version='4'
- fi
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_program_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
- if [[ -n $toolkit ]];then
- version="$version (Gtk $toolkit)"
- fi
- fi
- desktop_environment="Xfce"
- # when 5 is released, the string may need updating
- elif [[ -z ${xprop_root/*\"xfce5\"*/} ]];then
- version=$( get_program_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
- # arch linux reports null, so use alternate if null
- if [[ -z $version ]];then
- version=$( get_program_version 'xfce5-panel' '^xfce5-panel' '2' )
- if [[ -z $version ]];then
- version='5'
- fi
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_program_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
- if [[ -n $toolkit ]];then
- version="$version (Gtk $toolkit)"
- fi
- fi
- desktop_environment="Xfce"
- # case where no xfce number exists, just xfce
- elif [[ -z ${xprop_root/*xfce*/} ]];then
- version=$( get_program_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
- # arch linux reports null, so use alternate if null
- if [[ -z $version ]];then
- version=$( get_program_version 'xfce4-panel' '^xfce5-panel' '2' )
- if [[ -z $version ]];then
- # version=$( get_program_version 'xfce5-panel' '^xfce5-panel' '2' )
- #if [[ -z $version ]];then
- # version='5'
- #fi
- version='4'
- fi
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- toolkit=$( get_program_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
- if [[ -n $toolkit ]];then
- version="$version (Gtk $toolkit)"
- fi
- fi
- desktop_environment="Xfce"
- elif [[ -z ${xprop_root/*blackbox_pid*/} ]];then
- if [[ -z "${Ps_aux_Data/*fluxbox*/}" ]];then
- version=$( get_program_version 'fluxbox' '^fluxbox' '2' )
- desktop_environment='Fluxbox'
- else
- desktop_environment='Blackbox'
- fi
- elif [[ -z ${xprop_root/*openbox_pid*/} ]];then
- # note: openbox-lxde --version may be present, but returns openbox data
- version=$( get_program_version 'openbox' '^openbox' '2' )
- if [[ $XDG_CURRENT_DESKTOP == 'LXDE' || -z "${Ps_aux_Data/*\/lxsession*/}" ]];then
- if [[ -n $version ]];then
- version="(Openbox $version)"
- fi
- desktop_environment='LXDE'
- elif [[ $XDG_CURRENT_DESKTOP == 'Razor' || $XDG_CURRENT_DESKTOP == 'LXQt' ]] || \
- [[ -n $( grep -Es '(razor-desktop|lxqt-session)' <<< "$Ps_aux_Data" ) ]];then
- if [[ -z "${Ps_aux_Data/*lxqt-session*/}" ]];then
- desktop_environment='LXQt'
- elif [[ -z "${Ps_aux_Data/*razor-desktop*/}" ]];then
- desktop_environment='Razor-Qt'
- else
- desktop_environment='LX-Qt-Variant'
- fi
- if [[ -n $version ]];then
- version="(Openbox $version)"
- fi
- else
- desktop_environment='Openbox'
- fi
- elif [[ -z ${xprop_root/*icewm*/} ]];then
- version=$( get_program_version 'icewm' '^icewm' '2' )
- desktop_environment='IceWM'
- elif [[ -z ${xprop_root/*enlightenment*/} ]];then
- # no -v or --version but version is in xprop -root
- # ENLIGHTENMENT_VERSION(STRING) = "Enlightenment 0.16.999.49898"
- version=$( grep -is 'ENLIGHTENMENT_VERSION' <<< "$xprop_root" | cut -d '"' -f 2 | gawk '{print $2}' )
- desktop_environment='Enlightenment'
- # need to check starts line because it's so short
- elif [[ -n $( grep -s '^i3_' <<< "$xprop_root" ) ]];then
- version=$( get_program_version 'i3' '^i3' '3' )
- desktop_environment='i3'
- elif [[ -z ${xprop_root/*windowmaker*/} ]];then
- version=$( get_program_version 'wmaker' '^Window[[:space:]]*Maker' 'NF' )
- if [[ -n $version ]];then
- version="$version "
- fi
- desktop_environment="WindowMaker"
- # need to check starts line because it's so short
- elif [[ -n $( grep -s '^_wm2' <<< "$xprop_root" ) ]];then
- # note; there isn't actually a wm2 version available but error handling should cover it and return null
- # maybe one day they will add it?
- version=$( get_program_version 'wm2' '^wm2' 'NF' )
- # not certain will always have version, so keep output right if not
- if [[ -n $version ]];then
- version="$version "
- fi
- desktop_environment="WM2"
- elif [[ -z "${xprop_root/*herbstluftwm*/}" ]];then
- version=$( get_program_version 'herbstluftwm' '^herbstluftwm' 'NF' )
- if [[ -n $version ]];then
- version="$version "
- fi
- desktop_environment="herbstluftwm"
- fi
- fi
- # a few manual hacks for things that don't id with xprop, these are just good guesses
- # note that gawk is going to exit after first occurrence of search string, so no need for extra
- # http://www.xwinman.org/ for more possible wm
- if [[ -z $desktop_environment ]];then
- if [[ -z "${Ps_aux_Data/*fvwm-crystal*/}" ]];then
- version=$( get_program_version 'fvwm' '^fvwm' '2' )
- desktop_environment='FVWM-Crystal'
- elif [[ -z "${Ps_aux_Data/*fvwm*/}" ]];then
- version=$( get_program_version 'fvwm' '^fvwm' '2' )
- desktop_environment='FVWM'
- elif [[ -z "${Ps_aux_Data/*pekwm*/}" ]];then
- version=$( get_program_version 'pekwm' '^pekwm' '3' )
- desktop_environment='pekwm'
- elif [[ -z "${Ps_aux_Data/*awesome*/}" ]];then
- version=$( get_program_version 'awesome' '^awesome' '2' )
- desktop_environment='Awesome'
- elif [[ -z "${Ps_aux_Data/*scrotwm*/}" ]];then
- version=$( get_program_version 'scrotwm' '^welcome.*scrotwm' '4' )
- desktop_environment='Scrotwm' # no --version for this one
- elif [[ -z "${Ps_aux_Data/*spectrwm*/}" ]];then
- version=$( get_program_version 'spectrwm' '^spectrwm.*welcome.*spectrwm' '5' )
- desktop_environment='Spectrwm' # no --version for this one
- elif [[ -n $( grep -Es '([[:space:]]|/)twm' <<< "$Ps_aux_Data" ) ]];then
- desktop_environment='Twm' # no --version for this one
- elif [[ -n $( grep -Es '([[:space:]]|/)dwm' <<< "$Ps_aux_Data" ) ]];then
- version=$( get_program_version 'dwm' '^dwm' '1' )
- desktop_environment='dwm'
- elif [[ -z "${Ps_aux_Data/*wmii2*/}" ]];then
- version=$( get_program_version 'wmii2' '^wmii2' '1' )
- desktop_environment='wmii2'
- # note: in debian at least, wmii is actuall wmii3
- elif [[ -z "${Ps_aux_Data/*wmii*/}" ]];then
- version=$( get_program_version 'wmii' '^wmii' '1' )
- desktop_environment='wmii'
- elif [[ -n $( grep -Es '([[:space:]]|/)jwm' <<< "$Ps_aux_Data" ) ]];then
- version=$( get_program_version 'jwm' '^jwm' '2' )
- desktop_environment='JWM'
- elif [[ -z "${Ps_aux_Data/*sawfish*/}" ]];then
- version=$( get_program_version 'sawfish' '^sawfish' '3' )
- desktop_environment='Sawfish'
- elif [[ -z "${Ps_aux_Data/*afterstep*/}" ]];then
- version=$( get_program_version 'afterstep' '^afterstep' '3' )
- desktop_environment='AfterStep'
- fi
- fi
- fi
- fi
- if [[ -n $version ]];then
- version=" $version"
- fi
- log_function_data "desktop_environment version: $desktop_environment$version"
- echo "$desktop_environment$version"
- eval $LOGFE
-}
-
-get_desktop_extra_data()
-{
- eval $LOGFS
- local de_data=$( ps -A | gawk '
- BEGIN {
- IGNORECASE=1
- desktops=""
- separator=""
- }
- /(gnome-shell|gnome-panel|kicker|lxpanel|mate-panel|plasma-desktop|plasma-netbook|xfce4-panel)$/ {
- # only one entry per type, can be multiple
- if ( desktops !~ $NF ) {
- desktops = desktops separator $NF
- separator = ","
+# right now only using this for ARM cpus, this is not the same in intel/amd
+sub cpu_dies_sys {
+ eval $start if $b_log;
+ my @data = main::globber('/sys/devices/system/cpu/cpu*/topology/core_siblings_list');
+ my (@dies);
+ foreach (@data){
+ my $siblings = (main::reader($_))[0];
+ if (! grep {/$siblings/} @dies){
+ push @dies, $siblings;
}
}
- END {
- print desktops
+ my $die_count = scalar @dies;
+ eval $end if $b_log;
+ return $die_count;
+}
+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 ( $file && ! -r $file ){
+ $flags = main::row_defaults('dmesg-boot-permissions');
}
- ' )
- log_function_data "de_data: $de_data"
- echo $de_data
-
- eval $LOGFE
+ else {
+ 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: <....<b23>,<b34>>
+ # Features2=0x1e98220b<SSE3,PCLMULQDQ,MON,SSSE3,CX16,SSE4.1,SSE4.2,POPCNT,AESNI,XSAVE,OSXSAVE,AVX>
+ $line[1] =~ s/^[^<]*<|>[^>]*$//g;
+ # then get rid of <b23> 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;
+ }
+ }
+ eval $end if $b_log;
+ return $flags;
}
-get_de_gtk_data()
-{
- eval $LOGFS
-
- local toolkit=''
-
- # this is a hack, and has to be changed with every toolkit version change, and only dev systems
- # have this installed, but it's a cross distro command so let's test it first
- if type -p pkg-config &>/dev/null;then
- toolkit=$( pkg-config --modversion gtk+-4.0 2>/dev/null )
- # note: opensuse gets null output here, we need the command to get version and output sample
- if [[ -z $toolkit ]];then
- toolkit=$( pkg-config --modversion gtk+-3.0 2>/dev/null )
- fi
- if [[ -z $toolkit ]];then
- toolkit=$( pkg-config --modversion gtk+-2.0 2>/dev/null )
- fi
- fi
- # now let's go to more specific version tests, this will never cover everything and that's fine.
- if [[ -z $toolkit ]];then
- # we'll try some known package managers next. dpkg will handle a lot of distros
- # this is the most likely order as of: 2014-01-13. Not going to try to support all package managers
- # too much work, just the very biggest ones.
- if type -p dpkg &>/dev/null;then
- toolkit=$( dpkg -s libgtk-3-0 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
- # just guessing on gkt 4 package name
- if [[ -z $toolkit ]];then
- toolkit=$( dpkg -s libgtk-4-0 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
- fi
- if [[ -z $toolkit ]];then
- toolkit=$( dpkg -s libgtk2.0-0 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
- fi
- elif type -p pacman &>/dev/null;then
- toolkit=$( pacman -Qi gtk3 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
- # just guessing on gkt 4 package name
- if [[ -z $toolkit ]];then
- toolkit=$( pacman -Qi gtk4 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
- fi
- if [[ -z $toolkit ]];then
- toolkit=$( pacman -Qi gtk2 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
- fi
- # Name : libgtk-3-0
- # Version : 3.12.2
- elif type -p rpm &>/dev/null;then
- toolkit=$( rpm -qi libgtk-3-0 2>/dev/null | gawk -F ':' '
- /^[[:space:]]*Version/ {
- gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
- print $2
- }' )
- if [[ -z $toolkit ]];then
- toolkit=$( rpm -qi libgtk-4-0 2>/dev/null | gawk -F ':' '
- /^[[:space:]]*Version/ {
- gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
- print $2
- }' )
- fi
- if [[ -z $toolkit ]];then
- toolkit=$( rpm -qi libgtk-2-0 2>/dev/null | gawk -F ':' '
- /^[[:space:]]*Version/ {
- gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
- print $2
- }' )
- fi
- fi
- fi
- log_function_data "toolkit: $toolkit"
- echo $toolkit
-
- eval $LOGFE
+sub cpu_vendor {
+ eval $start if $b_log;
+ my ($string) = @_;
+ my ($vendor) = ('');
+ $string = lc($string);
+ if ($string =~ /intel/) {
+ $vendor = "intel"
+ }
+ elsif ($string =~ /amd/){
+ $vendor = "amd"
+ }
+ # via
+ elsif ($string =~ /centaur/){
+ $vendor = "centaur"
+ }
+ eval $end if $b_log;
+ return $vendor;
}
-get_device_data()
-{
- eval $LOGFS
-
- local device='un-determined'
- local chasis_id='' dmi_device=''
-
- # first: linked version
- if [[ -e /sys/class/dmi/id/chassis_type ]];then
- chasis_id=$(cat /sys/class/dmi/id/chassis_type)
- elif [[ -e /sys/devices/virtual/dmi/id/chassis_type ]];then
- chasis_id=$(cat /sys/devices/virtual/dmi/id/chassis_type)
- fi
- # src: http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.0.pdf
- # https://www.404techsupport.com/2012/03/pizza-box-lunch-box-and-other-pc-case-form-factors-identified-by-wmi/
- if [[ $chasis_id != '' ]];then
- case $chasis_id in
- 1)
- device=$(get_device_vm)
- ;;
- 2)
- device='unknown'
- ;;
- # note: 13 is all-in-one which we take as a mac type system
- 3|4|6|7|13|15|24)
- device='desktop'
- ;;
- # 5 - pizza box was a 1 U desktop enclosure, but some old laptops also id this way
- 5)
- device='pizza-box'
- ;;
- # note: lenovo T420 shows as 10, notebook, but it's not a notebook
- 9|10|16)
- device='laptop'
- ;;
- 14)
- device='notebook'
- ;;
- 8|11)
- device='portable'
- ;;
- 17|23|25)
- device='server'
- ;;
- 27|28|29)
- device='blade'
- ;;
- 12)
- device='docking-station'
- ;;
- 18)
- device='expansion-chassis'
- ;;
- 19)
- device='sub-chassis'
- ;;
- 20)
- device='bus-expansion'
- ;;
- 21)
- device='peripheral'
- ;;
- 22)
- device='RAID'
- ;;
- 26)
- device='compact-PCI'
- ;;
- esac
- else
- if ! type -p dmidecode &>/dev/null;then
- device='dmidecode-missing'
- elif [[ $B_ROOT == 'false' ]];then
- device='dmidecode-use-root'
- else
- set_dmidecode_data
- if [[ -n $DMIDECODE_DATA ]];then
- if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
- device='dmidecode-no-info'
- else
- dmi_device=$( gawk '
- BEGIN {
- IGNORECASE=1
- device="test"
- }
- /^Chassis Information/ {
- device= $1
- while (getline && !/^$/ ) {
- if ( $1 ~ /^Type/ ) {
- sub(/Type:\s*/,"",$0)
- device = $0
- break
- }
- }
- }
- END {
- print device
- }' <<< "$DMIDECODE_DATA" )
- if [[ -n $dmi_device ]];then
- device=$dmi_device
- fi
- if [[ $device == 'Other' ]];then
- device=$(get_device_vm)
- fi
- fi
- fi
- fi
- fi
- echo $device
-
- eval $LOGFE
+sub cpu_arch {
+ eval $start if $b_log;
+ my ($type,$family,$model) = @_;
+ my $arch = '';
+ # https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
+ # print "$type;$family;$model\n";
+ if ( $type eq 'amd'){
+ if ($family eq '4'){
+ if ( $model =~ /^(3|7|8|9|A)$/ ) {$arch = 'Am486'}
+ elsif ( $model =~ /^(E|F)$/ ) {$arch = 'Am5x86'}
+ }
+ elsif ($family eq '5'){
+ if ( $model =~ /^(0|1|2|3)$/ ) {$arch = 'K5'}
+ elsif ( $model =~ /^(6|7)$/ ) {$arch = 'K6'}
+ elsif ( $model =~ /^(8)$/ ) {$arch = 'K6-2'}
+ elsif ( $model =~ /^(9|D)$/ ) {$arch = 'K6-3'}
+ elsif ( $model =~ /^(A)$/ ) {$arch = 'Geode'}
+ }
+ elsif ($family eq '6'){
+ if ( $model =~ /^(1|2)$/ ) {$arch = 'K7'}
+ elsif ( $model =~ /^(3|4)$/ ) {$arch = 'K7 Thunderbird'}
+ elsif ( $model =~ /^(6|7|8|A)$/ ) {$arch = 'K7 Palomino+'}
+ else {$arch = 'K7'}
+ }
+ elsif ($family eq 'F'){
+ if ( $model =~ /^(4|5|7|8|B|C|E|F|14|15|17|18|1B|1C|1F)$/ ) {$arch = 'K8'}
+ elsif ( $model =~ /^(21|23|24|25|27|28|2C|2F)$/ ) {$arch = 'K8 rev.E'}
+ elsif ( $model =~ /^(41|43|48|4B|4C|4F|5D|5F|68|6B|6C|6F|7C|7F|C1)$/ ) {$arch = 'K8 rev.F+'}
+ else {$arch = 'K8'}
+ }
+ elsif ($family eq '10'){
+ if ( $model =~ /^(2|4|5|6|8|9|A)$/ ) {$arch = 'K10'}
+ else {$arch = 'K10'}
+ }
+ elsif ($family eq '11'){
+ if ( $model =~ /^(3)$/ ) {$arch = 'Turion X2 Ultra'}
+ }
+ # might also need cache handling like 14/16
+ elsif ($family eq '12'){
+ if ( $model =~ /^(1)$/ ) {$arch = 'Fusion'}
+ else {$arch = 'Fusion'}
+ }
+ # SOC, apu
+ elsif ($family eq '14'){
+ if ( $model =~ /^(1|2)$/ ) {$arch = 'Bobcat'}
+ else {$arch = 'Bobcat'}
+ }
+ elsif ($family eq '15'){
+ if ( $model =~ /^(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)$/ ) {$arch = 'Bulldozer'}
+ elsif ( $model =~ /^(10|11|12|13|14|15|16|17|18|19|1A|1B|1C|1D|1E|1F)$/ ) {$arch = 'Piledriver'}
+ elsif ( $model =~ /^(30|31|32|33|34|35|36|37|38|39|3A|3B|3C|3D|3E|3F)$/ ) {$arch = 'Steamroller'}
+ elsif ( $model =~ /^(60|61|62|63|64|65|66|67|68|69|6A|6B|6C|6D|6E|6F|70|71|72|73|74|75|76|77|78|79|7A|7B|7C|7D|7E|7F)$/ ) {$arch = 'Excavator'}
+ else {$arch = 'Bulldozer'}
+ }
+ # SOC, apu
+ elsif ($family eq '16'){
+ if ( $model =~ /^(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)$/ ) {$arch = 'Jaguar'}
+ elsif ( $model =~ /^(30|31|32|33|34|35|36|37|38|39|3A|3B|3C|3D|3E|3F)$/ ) {$arch = 'Puma'}
+ else {$arch = 'Jaguar'}
+ }
+ elsif ($family eq '17'){
+ if ( $model =~ /^(1)$/ ) {$arch = 'Zen'}
+ else {$arch = 'Zen'}
+ }
+ }
+ elsif ( $type eq 'arm'){
+ if ($family ne ''){$arch="ARMv$family";}
+ else {$arch='ARM';}
+ }
+ # aka VIA
+ elsif ( $type eq 'centaur'){
+ if ($family eq '5'){
+ if ( $model =~ /^(4)$/ ) {$arch = 'WinChip C6'}
+ elsif ( $model =~ /^(8)$/ ) {$arch = 'WinChip 2'}
+ elsif ( $model =~ /^(9)$/ ) {$arch = 'WinChip 3'}
+ }
+ elsif ($family eq '6'){
+ if ( $model =~ /^(6)$/ ) {$arch = 'WinChip-based'}
+ elsif ( $model =~ /^(7|8)$/ ) {$arch = 'C3'}
+ elsif ( $model =~ /^(9)$/ ) {$arch = 'C3-2'}
+ elsif ( $model =~ /^(A|D)$/ ) {$arch = 'C7'}
+ elsif ( $model =~ /^(F)$/ ) {$arch = 'Isaiah'}
+ }
+ }
+ elsif ( $type eq 'intel'){
+ if ($family eq '4'){
+ if ( $model =~ /^(0|1|2|3|4|5|6|7|8|9)$/ ) {$arch = '486'}
+ }
+ elsif ($family eq '5'){
+ if ( $model =~ /^(1|2|3|7)$/ ) {$arch = 'P5'}
+ elsif ( $model =~ /^(4|8)$/ ) {$arch = 'P5'} # MMX
+ elsif ( $model =~ /^(9)$/ ) {$arch = 'Quark'}
+ }
+ elsif ($family eq '6'){
+ if ( $model =~ /^(1)$/ ) {$arch = 'P6 Pro'}
+ elsif ( $model =~ /^(3|5|6)$/ ) {$arch = 'P6 II'}
+ elsif ( $model =~ /^(7|8)$/ ) {$arch = 'P6 III'}
+ elsif ( $model =~ /^(9)$/ ) {$arch = 'Banias'} # pentium M
+ elsif ( $model =~ /^(15)$/ ) {$arch = 'Dothan Tolapai'} # pentium M system on chip
+ elsif ( $model =~ /^(D)$/ ) {$arch = 'Dothan'} # Pentium M
+ elsif ( $model =~ /^(E)$/ ) {$arch = 'Yonah'}
+ elsif ( $model =~ /^(F|16)$/ ) {$arch = 'Conroe'}
+ elsif ( $model =~ /^(17|1D)$/ ) {$arch = 'Penryn'}
+ elsif ( $model =~ /^(1A|1E|1F|2E|25|2C|2F)$/ ) {$arch = 'Nehalem'}
+ elsif ( $model =~ /^(1C|26)$/ ) {$arch = 'Bonnell'}
+ elsif ( $model =~ /^(27|35|36)$/ ) {$arch = 'Saltwell'}
+ elsif ( $model =~ /^(25|2C|2F)$/ ) {$arch = 'Westmere'}
+ elsif ( $model =~ /^(26|27)$/ ) {$arch = 'Bonnell'}
+ elsif ( $model =~ /^(2A|2D)$/ ) {$arch = 'Sandy Bridge'}
+ elsif ( $model =~ /^(37|4A|4D|5A)$/ ) {$arch = 'Silvermont'}
+ elsif ( $model =~ /^(3A|3E)$/ ) {$arch = 'Ivy Bridge'}
+ elsif ( $model =~ /^(3C|3F|45|46)$/ ) {$arch = 'Haswell'}
+ elsif ( $model =~ /^(3D|47|4F|56)$/ ) {$arch = 'Broadwell'}
+ elsif ( $model =~ /^(4E|55|9E)$/ ) {$arch = 'Skylake'}
+ elsif ( $model =~ /^(5E)$/ ) {$arch = 'Skylake-S'}
+ elsif ( $model =~ /^(4C|5D)$/ ) {$arch = 'Airmont'}
+ elsif ( $model =~ /^(8E|9E)$/ ) {$arch = 'Kaby Lake'}
+ elsif ( $model =~ /^(57)$/ ) {$arch = 'Knights Landing'}
+ elsif ( $model =~ /^(85)$/ ) {$arch = 'Knights Mill'}
+ # product codes: https://en.wikipedia.org/wiki/List_of_Intel_microprocessors
+ # coming: coffee lake; cannonlake; icelake; tigerlake
+ }
+ elsif ($family eq 'B'){
+ if ( $model =~ /^(1)$/ ) {$arch = 'Knights Corne'}
+ }
+ elsif ($family eq 'F'){
+ if ( $model =~ /^(0|1|2)$/ ) {$arch = 'Netburst Willamette'}
+ elsif ( $model =~ /^(3|4|6)$/ ) {$arch = 'Netburst Prescott'} # Nocona
+ else {$arch = 'Netburst'}
+ }
+ }
+ eval $end if $b_log;
+ return $arch;
}
-get_device_vm()
-{
- eval $LOGFS
-
- local vm='other-vm?' vm_data='' vm_test=''
-
- # https://www.freedesktop.org/software/systemd/man/systemd-detect-virt.html
- # note: returns bosh for qemu-kvm so if that's the result, let the other tests
- # run
- if type -p systemd-detect-virt &>/dev/null;then
- vm_test=$(systemd-detect-virt 2>/dev/null | sed 's/none//' )
- if [[ -n $vm_test && $vm_test != 'none' ]];then
- vm=$vm_test
- fi
- fi
- # some simple to detect linux vm id's
- if [[ $vm == 'other-vm?' || $vm == 'bochs' ]];then
- if [[ -e /proc/vz ]];then
- vm='openvz'
- elif [[ -e /proc/xen ]];then
- vm='xen'
- elif [[ -e /dev/vzfs ]];then
- vm='virtuozzo'
- elif type -p lsmod &>/dev/null;then
- vm_data="$( lsmod 2>/dev/null )"
- if [[ -n $( grep -i 'kqemu' <<< "$vm_data" ) ]];then
- vm='kqemu'
- elif [[ -n $( grep -i 'kvm' <<< "$vm_data" ) ]];then
- vm='kvm'
- elif [[ -n $( grep -i 'qemu' <<< "$vm_data" ) ]];then
- vm='qemu'
- fi
- vm_data=''
- fi
- fi
- # this will catch many Linux systems and some BSDs
- if [[ $vm == 'other-vm?' || $vm == 'bochs' ]];then
- vm_data=$vm_data$LSPCI_V_DATA
- vm_data=$vm_data$SYSCTL_A_DATA
- vm_data=$vm_data$DMESG_BOOT_DATA
- if [[ -e /dev/disk/by-id ]];then
- vm_data=$vm_data$(ls -l /dev/disk/by-id 2>/dev/null )
- fi
- if [[ -n $( grep -iEs 'innotek|vbox|virtualbox' <<< $vm_data ) ]];then
- vm='virtualbox'
- elif [[ -n $( grep -is 'vmware' <<< $vm_data ) ]];then
- vm='vmware'
- elif [[ -n $( grep -is 'qemu' <<< $vm_data ) ]];then
- vm='qemu-or-kvm'
- elif [[ -n $( grep -s 'Virtual HD' <<< $vm_data ) ]];then
- vm='hyper-v'
- elif [[ -e /proc/cpuinfo && -n $( grep -is '^flags.*hypervisor' /proc/cpuinfo ) ]];then
- vm='virtual-machine'
- elif [[ -e /dev/vda || -e /dev/vdb || -e /dev/xvda || -e /dev/xvdb ]];then
- vm='virtual-machine'
- fi
- fi
- # this may catch some BSD and fringe Linux cases
- if [[ $vm == 'other-vm?' && $B_ROOT == 'true' ]];then
- if [[ -n $DMIDECODE_DATA && $DMIDECODE_DATA != 'dmidecode-error-'* ]];then
- product_name=$(dmidecode -s system-product-name 2>/dev/null )
- system_manufacturer=$( dmidecode -s system-manufacturer 2>/dev/null )
- if [[ $product_name == 'VMware'* ]];then
- vm='vmware'
- elif [[ $product_name == 'VirtualBox'* ]];then
- vm='virtualbox'
- elif [[ $product_name == 'KVM'* ]];then
- vm='kvm'
- elif [[ $product_name == 'Bochs'* ]];then
- vm='qemu'
- elif [[ $system_manufacturer == 'Xen' ]];then
- vm='xen'
- elif [[ -n $( grep -i 'hypervisor' <<< "$DMIDECODE_DATA" ) ]];then
- vm='virtual-machine'
- fi
- fi
- fi
-
- echo $vm
-
- eval $LOGFE
+sub count_alpha {
+ my ($count) = @_;
+ #print "$count\n";
+ my @alpha = qw(Single Dual Triple Quad);
+ if ($count > 4){
+ $count .= '-';
+ }
+ else {
+ $count = $alpha[$count-1] . ' ' if $count > 0;
+ }
+ return $count;
+}
+sub set_cpu_data {
+ my %cpu = (
+ 'arch' => '',
+ 'bogomips' => 0,
+ 'cores' => 0,
+ 'cur-freq' => 0,
+ 'dies' => 0,
+ 'family' => '',
+ 'flags' => '',
+ 'ids' => [],
+ 'l1-cache' => 0, # store in KB
+ 'l2-cache' => 0, # store in KB
+ 'l3-cache' => 0, # store in KB
+ 'max-freq' => 0,
+ 'min-freq' => 0,
+ 'model_id' => '',
+ 'model_name' => '',
+ 'processors' => [],
+ 'rev' => '',
+ 'scalings' => [],
+ 'siblings' => 0,
+ 'type' => '',
+ );
+ return %cpu;
+}
+# MHZ - cell cpus
+sub speed_cleaner {
+ my ($speed,$opt) = @_;
+ return if ! $speed || $speed eq '0';
+ $speed =~ s/[GMK]HZ$//gi;
+ $speed = ($speed/1000) if $opt && $opt eq 'khz';
+ $speed = sprintf "%.0f", $speed;
+ return $speed;
+}
+sub cpu_cleaner {
+ my ($cpu) = @_;
+ return if ! $cpu;
+ my $filters = '@|cpu |cpu deca|([0-9]+|single|dual|two|triple|three|tri|quad|four|';
+ $filters .= 'penta|five|hepta|six|hexa|seven|octa|eight|multi)[ -]core|';
+ $filters .= 'ennea|genuine|multi|processor|single|triple|[0-9\.]+ *[MmGg][Hh][Zz]';
+ $cpu =~ s/$filters//ig;
+ $cpu =~ s/\s\s+/ /g;
+ $cpu =~ s/^\s+|\s+$//g;
+ return $cpu;
+}
}
-# see which dm has started if any
-get_display_manager()
+## DiskData
{
- eval $LOGFS
- # ldm - LTSP display manager. Note that sddm does not appear to have a .pid extension in Arch
- # note: to avoid positives with directories, test for -f explicitly, not -e
- local dm_id_list='entranced.pid gdm.pid gdm3.pid kdm.pid ldm.pid lightdm.pid lxdm.pid mdm.pid nodm.pid sddm.pid sddm slim.lock tint2.pid wdm.pid xdm.pid'
- local dm_id='' dm='' separator=''
- # note we don't need to filter grep if we do it this way
- local x_is_running=$( grep '/usr.*/X' <<< "$Ps_aux_Data" | grep -iv '/Xprt' )
-
- for dm_id in $dm_id_list
- do
- # note: ${dm_id%.*}/$dm_id will create a dir name out of the dm id, then test if pid is in that
- # note: sddm, in an effort to be unique and special, do not use a pid/lock file, but rather a random
- # string inside a directory called /run/sddm/ so assuming the existence of the pid inside a directory named
- # from the dm. Hopefully this change will not have negative results.
- if [[ -f /run/$dm_id || -d /run/${dm_id%.*}/ || -f /var/run/$dm_id || \
- -d /var/run/${dm_id%.*}/ ]];then
- # just on the off chance that two dms are running, good info to have in that case, if possible
- dm=$dm$separator${dm_id%.*}
- separator=','
- fi
- done
- # might add this in, but the rate of new dm's makes it more likely it's an unknown dm, so
- # we'll keep output to N/A
- if [[ -n $x_is_running && -z $dm ]];then
- if [[ -z "${Ps_aux_Data/*startx*/}" ]];then
- dm='(startx)'
- fi
- fi
- echo $dm
-
- log_function_data "display manager: $dm"
-
- eval $LOGFE
-}
-
-# for more on distro id, please reference this python thread: http://bugs.python.org/issue1322
-## return distro name/id if found
-get_distro_data()
-{
- eval $LOGFS
- local i='' j='' distro='' distro_file='' a_distro_glob='' a_temp='' b_osr='false'
-
- # may need modification if archbsd / debian can be id'ed with /etc files
- if [[ -n $BSD_TYPE ]];then
- if [[ $BSD_VERSION != 'darwin' ]];then
- distro=$( uname -sr )
- else
- if [[ -f /System/Library/CoreServices/SystemVersion.plist ]];then
- distro=$( grep -A1 -E '(ProductName|ProductVersion)' /System/Library/CoreServices/SystemVersion.plist | grep '<string>' | sed -E 's/<[\/]?string>//g' )
- distro=$( echo $distro )
- fi
- if [[ -z $distro ]];then
- distro='Mac OS X'
- fi
- fi
- echo "$distro"
- log_function_data "distro: $distro"
- eval $LOGFE
- return 0
- fi
-
- # get the wild carded array of release/version /etc files if present
- shopt -s nullglob
- cd /etc
- # 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
- a_distro_glob=(*[-_]{release,version})
- cd "$OLDPWD"
- shopt -u nullglob
-
- a_temp=${a_distro_glob[@]}
- log_function_data "a_distro_glob: $a_temp"
-
- if [[ ${#a_distro_glob[@]} -eq 1 ]];then
- distro_file="$a_distro_glob"
- # use the file if it's in the known good lists
- elif [[ ${#a_distro_glob[@]} -gt 1 ]];then
- for i in $DISTROS_DERIVED $DISTROS_PRIMARY
- do
- # Only echo works with ${var[@]}, not print_screen_output() or self_debugger()
- # This is a known bug, search for the word "strange" inside comments
- # echo "i='$i' a_distro_glob[@]='${a_distro_glob[@]}'"
- if [[ " ${a_distro_glob[@]} " == *" $i "* ]];then
- # Now lets see if the distro file is in the known-good working-lsb-list
- # if so, use lsb-release, if not, then just use the found file
- # this is for only those distro's with self named release/version files
- # because Mint does not use such, it must be done as below
- ## this if statement requires the spaces and * as it is, else it won't work
- ##
- if [[ " $DISTROS_LSB_GOOD " == *" $i "* ]] && [[ $B_LSB_FILE == 'true' ]];then
- distro_file='lsb-release'
- elif [[ " $DISTROS_OS_RELEASE_GOOD " == *" $i "* ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
- distro_file='os-release'
- else
- distro_file="$i"
- fi
- break
- fi
- done
- fi
- log_function_data "distro_file: $distro_file"
- # first test for the legacy antiX distro id file
- if [[ -e /etc/antiX ]];then
- distro="$( grep -Eoi 'antix.*\.iso' <<< $( remove_erroneous_chars '/etc/antiX' ) | sed 's/\.iso//' )"
- # this handles case where only one release/version file was found, and it's lsb-release. This would
- # never apply for ubuntu or debian, which will filter down to the following conditions. In general
- # if there's a specific distro release file available, that's to be preferred, but this is a good backup.
- elif [[ -n $distro_file && $B_LSB_FILE == 'true' && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then
- distro=$( get_distro_lsb_os_release_data 'lsb-file' )
- elif [[ $distro_file == 'lsb-release' ]];then
- distro=$( get_distro_lsb_os_release_data 'lsb-file' )
- elif [[ $distro_file == 'os-release' ]];then
- distro=$( get_distro_lsb_os_release_data 'os-release-file' )
- b_osr='true'
- # then if the distro id file was found and it's not in the exluded primary distro file list, read it
- elif [[ -n $distro_file && -s /etc/$distro_file && " $DISTROS_EXCLUDE_LIST " != *" $distro_file "* ]];then
- # new opensuse uses os-release, but older ones may have a similar syntax, so just use the first line
- if [[ $distro_file == 'SuSE-release' ]];then
- # leaving off extra data since all new suse have it, in os-release, this file has line breaks, like os-release
- # but in case we want it, it's: CODENAME = Mantis | VERSION = 12.2
- # for now, just take first occurrence, which should be the first line, which does not use a variable type format
- distro=$( grep -i -m 1 'suse' /etc/$distro_file )
- else
- distro=$( remove_erroneous_chars "/etc/$distro_file" )
- fi
- # otherwise try the default debian/ubuntu /etc/issue file
- elif [[ -f /etc/issue ]];then
- # os-release/lsb gives more manageable and accurate output than issue, but mint should use issue for now
- # some bashism, boolean must be in parenthesis to work correctly, ie [[ $(boolean) ]] not [[ $boolean ]]
- if [[ $B_OS_RELEASE_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
- distro=$( get_distro_lsb_os_release_data 'os-release-file' )
- b_osr='true'
- elif [[ $B_LSB_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
- distro=$( get_distro_lsb_os_release_data 'lsb-file' )
- else
- distro=$( gawk '
- BEGIN {
- RS=""
+package DiskData;
+my ($b_hddtemp,$b_nvme,$b_sudo);
+my ($hddtemp,$nvme,$sudo) = ('','','');
+my (@by_id,@by_path);
+
+sub get {
+ eval $start if $b_log;
+ my (@data,@rows,$key1,$val1);
+ my ($type) = @_;
+ $type ||= 'standard';
+ my $num = 0;
+ @data = disk_data($type);
+ # NOTE:
+ if (@data){
+ if ($type eq 'standard'){
+ @data = create_output(@data);
+ @rows = (@rows,@data);
+ if ( $bsd_type && !@dm_boot_disk && $type eq 'standard' && $show{'disk'} ){
+ $key1 = 'Drive Report';
+ my $file = main::system_files('dmesg-boot');
+ if ( $file && ! -r $file ){
+ $val1 = main::row_defaults('dmesg-boot-permissions');
+ }
+ elsif (! -e $file){
+ $val1 = main::row_defaults('dmesg-boot-missing');
+ }
+ else {
+ $val1 = main::row_defaults('disk-data-bsd');
+ }
+ @data = ({main::key($num++,$key1) => $val1,});
+ @rows = (@rows,@data);
}
- {
- gsub(/\\[a-z]/, "")
- gsub(/'"$BAN_LIST_ARRAY"'/, " ")
- gsub(/^ +| +$/, "")
- gsub(/ [ \t]+/, " ")
- print
- }' /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 [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then
- distro='Arch Linux'
- fi
- fi
- fi
- # a final check. If a long value, before assigning the debugger output, if os-release
- # exists then let's use that if it wasn't tried already. Maybe that will be better.
- if [[ ${#distro} -gt 80 ]] && [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then
- if [[ $B_OS_RELEASE_FILE == 'true' && $b_osr == 'false' ]];then
- distro=$( get_distro_lsb_os_release_data 'os-release-file' )
- fi
- if [[ ${#distro} -gt 80 ]];then
- distro="${RED}/etc/$distro_file corrupted, use -% to override${NORMAL}"
- fi
- fi
- ## note: would like to actually understand the method even if it's not used
- # : ${distro:=Unknown distro o_O}
- ## 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
- # Because os-release is now more common, we'll test for it first.
- if [[ -z $distro ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
- distro=$( get_distro_lsb_os_release_data 'os-release-file' )
- fi
- if [[ -z $distro ]] && [[ $B_LSB_FILE == 'true' ]];then
- distro=$( get_distro_lsb_os_release_data 'lsb-file' )
- fi
-
- # now some final null tries
- if [[ -z $distro ]];then
- # if the file was null but present, which can happen in some cases, then use the file name itself to
- # set the distro value. Why say unknown if we have a pretty good idea, after all?
- if [[ -n $distro_file ]] && [[ " $DISTROS_DERIVED $DISTROS_PRIMARY " == *" $distro_file "* ]];then
- distro=$( sed $SED_RX -e 's/[-_]//' -e 's/(release|version)//' <<< $distro_file | sed $SED_RX 's/^([a-z])/\u\1/' )
- fi
- ## finally, if all else has failed, give up
- if [[ -z $distro ]];then
- distro='unknown'
- fi
- fi
- # final step cleanup of unwanted information
- # opensuse has the x86 etc type string in names, not needed as redundant since -S already shows that
- distro=$( gawk '
- BEGIN {
- IGNORECASE=1
- }
- {
- sub(/ *\(*(x86_64|i486|i586|i686|686|586|486)\)*/, "", $0)
- print $0
- }' <<< $distro )
- echo "$distro"
- log_function_data "distro: $distro"
- eval $LOGFE
-}
-
-# args: $1 - lsb-file/lsb-app/os-release-file
-get_distro_lsb_os_release_data()
-{
- eval $LOGFS
- local distro=''
-
- case $1 in
- lsb-file)
- if [[ $B_LSB_FILE == 'true' ]];then
- distro=$( gawk -F '=' '
- BEGIN {
- IGNORECASE=1
- }
- # clean out unwanted characters
- {
- gsub(/\\|\"|[:\47]/,"", $0 )
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
- }
- # note: adding the spacing directly to variable to make sure distro output is null if not found
- /^DISTRIB_ID/ {
- # this is needed because grep for "arch" is too loose to be safe
- if ( $2 == "arch" ) {
- distroId = "Arch Linux"
- }
- else if ( $2 != "n/a" ) {
- distroId = $2 " "
- }
+ }
+ else {
+ @rows = @data;
+ # print Data::Dumper::Dumper \@rows;
+ }
+ }
+ else {
+ $key1 = 'Message';
+ $val1 = main::row_defaults('disk-data');
+ @rows = ({main::key($num++,$key1) => $val1,});
+ }
+ if (!@rows){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('disk-data');
+ @data = ({main::key($num++,$key1) => $val1,});
+ }
+ #@rows = (@rows,@data);
+ @data = ();
+ if ($show{'optical'} || $show{'optical-basic'}){
+ @data = OpticalData::get();
+ @rows = (@rows,@data);
+ }
+ ($b_hddtemp,$b_nvme,$b_sudo,$hddtemp,$nvme,$sudo) = (undef,undef,undef,undef,undef,undef);
+ (@by_id,@by_path) = (undef,undef);
+ eval $end if $b_log;
+ return @rows;
+}
+sub create_output {
+ eval $start if $b_log;
+ my (@disks) = @_;
+ #print Data::Dumper::Dumper \@disks;
+ my (@data,@rows);
+ my ($num,$j) = (0,0);
+ my ($id,$model,$size,$used,$percent,$size_holder,$used_holder) = ('','','','','','','');
+ my @sizing = main::get_size($disks[0]{'size'}) if $disks[0]{'size'};
+ #print Data::Dumper::Dumper \@disks;
+ if (@sizing){
+ $size = $sizing[0];
+ # note: if a string is returned there will be no Size unit so just use string.
+ if (defined $sizing[0] && $sizing[1]){
+ $size .= ' ' . $sizing[1];
+ }
+ }
+ $size ||= 'N/A';
+ @sizing = main::get_size($disks[0]{'used'}) if $disks[0]{'used'};
+ if (@sizing){
+ $used = $sizing[0];
+ if (defined $sizing[0] && $sizing[1]){
+ $used .= ' ' . $sizing[1];
+ if (( $disks[0]{'size'} && $disks[0]{'size'} =~ /^[0-9]/ ) &&
+ ( $disks[0]{'used'} =~ /^[0-9]/ ) ){
+ $used = $used . ' (' . sprintf("%0.1f", $disks[0]{'used'}/$disks[0]{'size'}*100) . '%)';
+ }
+ }
+ }
+ $used ||= 'N/A';
+ @data = ({
+ main::key($num++,'HDD Total Size') => $size,
+ main::key($num++,'used') => $used,
+ });
+ @rows = (@rows,@data);
+ shift @disks;
+ if ( $show{'disk'} && @disks){
+ @disks = sort { $a->{'id'} cmp $b->{'id'} } @disks;
+ foreach my $ref (@disks){
+ ($id,$model,$size) = ('','','');
+ my %row = %$ref;
+ $num = 1;
+ $model = ($row{'model'}) ? $row{'model'}: 'N/A';
+ $id = ($row{'id'}) ? "/dev/$row{'id'}":'N/A';
+ my @sizing = main::get_size($row{'size'});
+ #print Data::Dumper::Dumper \@disks;
+ if (@sizing){
+ $size = $sizing[0];
+ # note: if a string is returned there will be no Size unit so just use string.
+ if (defined $sizing[0] && $sizing[1]){
+ $size .= ' ' . $sizing[1];
+ $size_holder = $sizing[0];
}
- /^DISTRIB_RELEASE/ {
- if ( $2 != "n/a" ) {
- distroRelease = $2 " "
- }
+ $size ||= 'N/A';
+ }
+ else {
+ $size = 'N/A';
+ }
+ $j = scalar @rows;
+ @data = ({
+ main::key($num++,'ID') => $id,
+ });
+ @rows = (@rows,@data);
+ if ($row{'type'}){
+ $rows[$j]{main::key($num++,'type')} = $row{'type'},
+ }
+ $rows[$j]{main::key($num++,'model')} = $model;
+ $rows[$j]{main::key($num++,'size')} = $size;
+ if ($extra > 0 && $row{'speed'}){
+ $rows[$j]{main::key($num++,'speed')} = $row{'speed'};
+ }
+ if ($extra > 1){
+ my $serial = main::apply_filter($row{'serial'});
+ $rows[$j]{main::key($num++,'serial')} = $serial;
+ if ($row{'firmware'}){
+ $rows[$j]{main::key($num++,'rev')} = $row{'firmware'};
}
- /^DISTRIB_CODENAME/ {
- if ( $2 != "n/a" ) {
- distroCodename = $2 " "
- }
+ }
+ if ($extra > 0 && $row{'temp'}){
+ $rows[$j]{main::key($num++,'temp')} = $row{'temp'} . ' C';
+ }
+ # extra level tests already done
+ if (defined $row{'partition-table'}){
+ $rows[$j]{main::key($num++,'scheme')} = $row{'partition-table'};
+ }
+ }
+ }
+
+ eval $end if $b_log;
+ return @rows;
+}
+sub disk_data {
+ eval $start if $b_log;
+ my ($type) = @_;
+ my (@rows,@data,@devs);
+ my $num = 0;
+ my ($used) = (0);
+ PartitionData::partition_data() if !$b_partitions;
+ foreach my $ref (@partitions){
+ my %row = %$ref;
+ # don't count remote used, also, some cases mount
+ # panfs is parallel NAS volume manager, need more data
+ next if ($row{'fs'} && $row{'fs'} =~ /nfs|panfs|sshfs|smbfs|unionfs/);
+ # in some cases, like redhat, mounted cdrom/dvds show up in partition data
+ next if ($row{'dev-base'} && $row{'dev-base'} =~ /^sr[0-9]+$/);
+ # this is used for specific cases where bind, or incorrect multiple mounts
+ # to same partitions, or btrfs sub volume mounts, is present. The value is
+ # searched for an earlier appearance of that partition and if it is present,
+ # the data is not added into the partition used size.
+ if ( $row{'dev-base'} !~ /^\/\/|:\// && ! (grep {/$row{'dev-base'}/} @devs) ){
+ $used += $row{'used'} if $row{'used'};
+ push @devs, $row{'dev-base'};
+ }
+ }
+ if (!$bsd_type && (my $file = main::system_files('partitions'))){
+ @data = proc_data($used,$file);
+ }
+ elsif ($bsd_type) {
+ @data = dmesg_boot_data($used);
+ }
+ #print Data::Dumper::Dumper \@data;
+ main::log_data('data',"used: $used") if $b_log;
+ eval $end if $b_log;
+ return @data;
+}
+sub proc_data {
+ eval $start if $b_log;
+ my ($used,$file) = @_;
+ my (@data,@drives);
+ my ($b_hdx,$size,$drive_size) = (0,0,0);
+ my @proc_partitions = main::reader($file,'strip');
+ shift @proc_partitions;
+ foreach (@proc_partitions){
+ next if (/^\s*$/);
+ my @row = split /\s+/, $_;
+ if ( $row[-1] =~ /^([hsv]d[a-z]+|(ada|mmcblk|n[b]?d|nvme[0-9]+n)[0-9]+)$/) {
+ $drive_size = $row[2];
+ $b_hdx = 1 if $row[-1] =~ /^hd[a-z]/;
+ @data = ({
+ 'firmware' => '',
+ 'id' => $row[-1],
+ 'model' => '',
+ 'serial' => '',
+ 'size' => $drive_size,
+ 'spec' => '',
+ 'speed' => '',
+ 'temp' => '',
+ 'type' => '',
+ 'vendor' => '',
+ });
+ @drives = (@drives,@data);
+ }
+ # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below
+ # See https://www.mjmwired.net/kernel/Documentation/devices.txt for kernel 4.x device numbers
+ # if ( $row[0] =~ /^(3|22|33|8)$/ && $row[1] % 16 == 0 ) {
+ # $size += $row[2];
+ # }
+ # special case from this data: 8 0 156290904 sda
+ # 43 0 48828124 nbd0
+ # note: known starters: vm: 252/253/254; grsec: 202; nvme: 259
+ if ( $row[0] =~ /^(3|8|22|33|43|202|252|253|254|259)$/ &&
+ $row[-1] =~ /(n[b]?d[0-9]+|nvme[0-9]+n[0-9]+|[hsv]d[a-z]+)$/ &&
+ ( $row[1] % 16 == 0 || $row[1] % 16 == 8 ) ) {
+ $size += $row[2];
+ }
+ }
+ # print Data::Dumper::Dumper \@drives;
+ main::log_data('data',"size: $size") if $b_log;
+ @data = ({
+ 'size' => $size,
+ 'used' => $used,
+ });
+ #print Data::Dumper::Dumper \@data;
+ if ( $show{'disk'} ){
+ @drives = (@data,@drives);
+ # print 'drives:', Data::Dumper::Dumper \@drives;
+ @data = proc_data_advanced($b_hdx,@drives);
+ }
+ main::log_data('dump','@data',\@data) if $b_log;
+ # print Data::Dumper::Dumper \@data;
+ eval $end if $b_log;
+ return @data;
+}
+sub proc_data_advanced {
+ eval $start if $b_log;
+ my ($b_hdx,@drives) = @_;
+ my ($i) = (0);
+ my (@data,@rows,@scsi,@temp,@working);
+ my ($pt_cmd) = ('unset');
+ my ($block_type,$file,$firmware,$model,$path,$partition_scheme,
+ $serial,$vendor,$working_path);
+ @by_id = main::globber('/dev/disk/by-id/*');
+ @by_path = main::globber('/dev/disk/by-path/*');
+ ## check for all ide type drives, non libata, only do it if hdx is in array
+ ## this is now being updated for new /sys type paths, this may handle that ok too
+ ## skip the first rows in the loops since that's the basic size/used data
+ if ($b_hdx){
+ for ($i = 1; $i < scalar @drives; $i++){
+ $file = "/proc/ide/$drives[$i]{'id'}/model";
+ if ( $drives[$i]{'id'} =~ /^hd[a-z]/ && -e $file){
+ $model = (main::reader($file,'strip'))[0];
+ $drives[$i]{'model'} = $model;
+ }
+ }
+ }
+ # scsi stuff
+ if ($file = main::system_files('scsi')){
+ @scsi = scsi_data($file);
+ }
+ #print 'drives:', Data::Dumper::Dumper \@drives;
+ for ($i = 1; $i < scalar @drives; $i++){
+ #next if $drives[$i]{'id'} =~ /^hd[a-z]/;
+ ($block_type,$firmware,$model,$partition_scheme,
+ $serial,$vendor,$working_path) = ('','','','','','','');
+ if ($extra > 2){
+ @data = partition_scheme($pt_cmd,$drives[$i]{'id'});
+ $pt_cmd = $data[0];
+ $drives[$i]{'partition-table'} = uc($data[1]) if $data[1];
+ }
+ #print "$drives[$i]{'id'}\n";
+ if ($drives[$i]{'id'} =~ /[sv]d[a-z]/){
+ $block_type = 'sdx';
+ $working_path = "/sys/block/$drives[$i]{'id'}/device/";
+ }
+ elsif ($drives[$i]{'id'} =~ /mmcblk/){
+ $block_type = 'mmc';
+ $working_path = "/sys/block/$drives[$i]{'id'}/device/";
+ }
+ elsif ($drives[$i]{'id'} =~ /nvme/){
+ $block_type = 'nvme';
+ # this results in:
+ # /sys/devices/pci0000:00/0000:00:03.2/0000:06:00.0/nvme/nvme0/nvme0n1
+ # but we want to go one level down so slice off trailing nvme0n1
+ $working_path = Cwd::abs_path("/sys/block/$drives[$i]{'id'}");
+ $working_path =~ s/nvme[^\/]*$//;
+ }
+ main::log_data('data',"working path: $working_path") if $b_log;
+ if ($block_type){
+ # NOTE: while path ${working_path}vendor exists, it contains junk value, like: ATA
+ $path = "${working_path}model";
+ if ( -e $path){
+ $model = (main::reader($path,'strip'))[0];
+ if ($model){
+ $model =~ s/\s/_/g;
+ #@temp = split /-/, $model;
+ #$drives[$i]{'model'} = $temp[0];
+ $drives[$i]{'model'} = $model;
}
- # sometimes some distros cannot do their lsb-release files correctly, so here is
- # one last chance to get it right.
- /^DISTRIB_DESCRIPTION/ {
- if ( $2 != "n/a" ) {
- distroDescription = $2
+ }
+ elsif ($block_type eq 'mmc' && -e "${working_path}name"){
+ $path = "${working_path}name";
+ if ( -e $path){
+ $model = (main::reader($path,'strip'))[0];
+ if ($model){
+ $model =~ s/\s/_/g;
+ #@temp = split /-/, $model;
+ #$drives[$i]{'model'} = $temp[0];
+ $drives[$i]{'model'} = $model;
}
}
- END {
- fullString=""
- if ( distroId == "" && distroRelease == "" && distroCodename == "" && distroDescription != "" ){
- fullString = distroDescription
- }
- else {
- fullString = distroId distroRelease distroCodename
- }
- print fullString
- }
- ' $FILE_LSB_RELEASE )
- log_function_data 'cat' "$FILE_LSB_RELEASE"
- fi
- ;;
- lsb-app)
- # this is HORRIBLY slow, not using
- if type -p lsb_release &>/dev/null;then
- distro=$( echo "$( lsb_release -irc )" | gawk -F ':' '
- BEGIN {
- IGNORECASE=1
- }
- # clean out unwanted characters
- {
- gsub(/\\|\"|[:\47]/,"", $0 )
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
- }
- /^Distributor ID/ {
- distroId = $2
- }
- /^Release/ {
- distroRelease = $2
- }
- /^Codename/ {
- distroCodename = $2
- }
- END {
- print distroId " " distroRelease " (" distroCodename ")"
- }' )
- fi
- ;;
- os-release-file)
- if [[ $B_OS_RELEASE_FILE == 'true' ]];then
- distro=$( gawk -F '=' '
- BEGIN {
- IGNORECASE=1
- prettyName=""
- regularName=""
- versionName=""
- versionId=""
- distroName=""
- }
- # clean out unwanted characters
- {
- gsub(/\\|\"|[:\47]/,"", $0 )
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
- }
- # note: adding the spacing directly to variable to make sure distro output is null if not found
- /^PRETTY_NAME/ {
- if ( $2 != "n/a" ) {
- prettyName = $2
+ }
+ elsif (@scsi && @by_id){
+ ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the
+ # discovered disk name AND ends with the correct identifier, sdx
+ # get rid of whitespace for some drive names and ids, and extra data after - in name
+ foreach my $ref (@scsi){
+ my %row = %$ref;
+ if ($row{'model'}){
+ $row{'model'} =~ s/\s/_/g;
+ $row{'model'} = (split /-/,$row{'model'})[0];
+ foreach my $id (@by_id){
+ if ($id =~ /$row{'model'}/ && "/dev/$drives[$i]{'id'}" eq Cwd::abs_path($id)){
+ $drives[$i]{'firmware'} = $row{'firmware'};
+ $drives[$i]{'model'} = $row{'model'};
+ $drives[$i]{'vendor'} = $row{'vendor'};
+ last;
+ }
+ }
}
}
- /^NAME/ {
- if ( $2 != "n/a" ) {
- regularName = $2
+ }
+ $path = "${working_path}removable";
+ if (-e $path){
+ my $b_removable = (main::reader($path,'strip'))[0]; # 0/1 value
+ $drives[$i]{'type'} = 'Removable' if $b_removable;
+ }
+ }
+ my $peripheral = peripheral_data($drives[$i]{'id'});
+ # note: we only want to update type if we found a peripheral, otherwise preserve value
+ $drives[$i]{'type'} = $peripheral if $peripheral;
+ # print "type:$drives[$i]{'type'}\n";
+ if ($extra > 0){
+ $drives[$i]{'temp'} = hdd_temp("/dev/$drives[$i]{'id'}");
+ if ($extra > 1){
+ $path = "${working_path}serial";
+ if ( -e $path){
+ $serial = (main::reader($path,'strip'))[0];
+ if ($serial){
+ $drives[$i]{'serial'} = $serial;
}
}
- /^VERSION/ {
- if ( $2 != "n/a" && $1 == "VERSION" ) {
- versionName = $2
+ else {
+ $drives[$i]{'serial'} = disk_serial_by_id("/dev/$drives[$i]{'id'}");
+ }
+ if ($extra > 2){
+ $path = "${working_path}rev";
+ if ( -e $path){
+ $drives[$i]{'firmware'} = (main::reader($path,'strip'))[0];
}
- else if ( $2 != "n/a" && $1 == "VERSION_ID" ) {
- versionId = $2
+ $path = "${working_path}fwrev";
+ if ( !$drives[$i]{'firmware'} && -e $path){
+ $drives[$i]{'firmware'} = (main::reader($path,'strip'))[0];
}
}
- END {
- # NOTE: tumbleweed has pretty name but pretty name does not have version id
- if ( prettyName != "" && regularName !~ /tumbleweed/ ) {
- distroName = prettyName
- }
- else if ( regularName != "" ) {
- distroName = regularName
- if ( versionName != "" ) {
- distroName = distroName " " versionName
- }
- else if ( versionId != "" ) {
- distroName = distroName " " versionId
- }
-
+ }
+ }
+ }
+ # print Data::Dumper::Dumper \@drives;
+ eval $end if $b_log;
+ return @drives;
+}
+# camcontrol identify <device> |grep ^serial (this might be (S)ATA specific)
+# smartcl -i <device> |grep ^Serial
+# see smartctl; camcontrol devlist; gptid status;
+sub dmesg_boot_data {
+ eval $start if $b_log;
+ my ($used) = @_;
+ my (@data,@drives,@temp);
+ my ($id_holder,$i,$size,$working) = ('',0,0,0);
+ my $file = main::system_files('dmesg-boot');
+ if (@dm_boot_disk){
+ foreach (@dm_boot_disk){
+ my @row = split /:\s*/, $_;
+ next if ! defined $row[1];
+ if ($id_holder ne $row[0]){
+ $i++ if $id_holder;
+ # print "$i $id_holder $row[0]\n";
+ $id_holder = $row[0];
+ }
+ # no dots, note: ada2: 2861588MB BUT: ada2: 600.000MB/s
+ if (! exists $drives[$i]){
+ $drives[$i] = ({});
+ $drives[$i]{'id'} = $row[0];
+ $drives[$i]{'firmware'} = '';
+ $drives[$i]{'temp'} = '';
+ $drives[$i]{'type'} = '';
+ $drives[$i]{'vendor'} = '';
+ }
+ #print "$i\n";
+ if ($bsd_type eq 'openbsd'){
+ if ($row[1] =~ /,\s*([0-9\.]+[MGTPE][B]?),.*\ssectors$|^</){
+ $working = main::translate_size($1);
+ $size += $working if $working;
+ $drives[$i]{'size'} = $working;
+ }
+ if ($row[2] && $row[2] =~ /<([^>]+)>/){
+ $drives[$i]{'model'} = $1 if $1;
+ $drives[$i]{'type'} = 'removable' if $_ =~ /removable$/;
+ # <Generic-, Compact Flash, 1.00>
+ my $count = ($drives[$i]{'model'} =~ tr/,//);
+ if ($count && $count > 1){
+ @temp = split /,\s*/, $drives[$i]{'model'};
+ $drives[$i]{'model'} = $temp[1];
}
- print distroName
}
- ' $FILE_OS_RELEASE )
- log_function_data 'cat' "$FILE_OS_RELEASE"
- fi
- ;;
- esac
- echo $distro
- log_function_data "distro: $distro"
- eval $LOGFE
+ # print "openbsd\n";
+ }
+ 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$|^</){
+ $row[1] =~ s/\sdevice$//g;
+ $row[1] =~ /<([^>]*)>\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'};
+ }
+ }
+ }
+ if (!$size){
+ $size = main::row_defaults('data-bsd');
+ }
+ }
+ elsif ( $file && ! -r $file ){
+ $size = main::row_defaults('dmesg-boot-permissions');
+ }
+ elsif (! -f $file ){
+ $size = main::row_defaults('dmesg-boot-missing');
+ }
+ @data = ({
+ 'size' => $size,
+ 'used' => $used,
+ });
+ #main::log_data('dump','@data',\@data) if $b_log;
+ if ( $show{'disk'} ){
+ @data = (@data,@drives);
+ # print 'drives:', Data::Dumper::Dumper \@drives;
+ }
+ # print Data::Dumper::Dumper \@data;
+ eval $end if $b_log;
+ return @data;
}
-get_gcc_system_version()
-{
- eval $LOGFS
- local separator='' gcc_installed='' gcc_list='' gcc_others='' a_temp=''
- local gcc_version=$(
- gcc --version 2>/dev/null | sed $SED_RX 's/\([^\)]*\)//g' | gawk '
- BEGIN {
- IGNORECASE=1
- }
- /^gcc/ {
- print $2
- exit
- }' )
- # can't use xargs -L basename because not all systems support thats
- if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- gcc_others=$( ls /usr/bin/gcc-* 2>/dev/null )
- if [[ -n $gcc_others ]];then
- for item in $gcc_others
- do
- item=${item##*/}
- gcc_installed=$( gawk -F '-' '
- $2 ~ /^[0-9\.]+$/ {
- print $2
- }' <<< $item )
- if [[ -n $gcc_installed && -z $( grep "^$gcc_installed" <<< $gcc_version ) ]];then
- gcc_list=$gcc_list$separator$gcc_installed
- separator=','
- fi
- done
- fi
- fi
- if [[ -n $gcc_version ]];then
- A_GCC_VERSIONS=( "$gcc_version" $gcc_list )
- fi
- a_temp=${A_GCC_VERSIONS[@]}
- log_function_data "A_GCC_VERSIONS: $a_temp"
- eval $LOGFE
-}
-
-get_gpu_temp_data()
-{
- local gpu_temp='' gpu_fan='' screens='' screen_nu='' gpu_temp_looper=''
-
- # we'll try for nvidia/ati, then add if more are shown
- if type -p nvidia-settings &>/dev/null;then
- # first get the number of screens. This only work if you are in X
- if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
- screens=$( nvidia-settings -q screens | gawk '
- /:[0-9]\.[0-9]/ {
- screens=screens gensub(/(.*)(:[0-9]\.[0-9])(.*)/, "\\2", "1", $0) " "
- }
- END {
- print screens
- }
- ' )
- else
- # do a guess, this will work for most users, it's better than nothing for out of X
- screens=':0.0'
- fi
- # now we'll get the gpu temp for each screen discovered. The print out function
- # will handle removing screen data for single gpu systems
- for screen_nu in $screens
- do
- gpu_temp_looper=$( nvidia-settings -c $screen_nu -q GPUCoreTemp 2>/dev/null | gawk -F ': ' '
- BEGIN {
- IGNORECASE=1
- gpuTemp=""
- gpuTempWorking=""
- }
- /Attribute (.*)[0-9]+\.$/ {
- gsub(/\./, "", $2)
- if ( $2 ~ /^[0-9]+$/ ) {
- gpuTemp=gpuTemp $2 "C "
- }
- }
- END {
- print gpuTemp
- }' )
- screen_nu=$( cut -d ':' -f 2 <<< $screen_nu )
- gpu_temp="$gpu_temp$screen_nu:$gpu_temp_looper "
- done
- elif type -p aticonfig &>/dev/null;then
-# gpu_temp=$( aticonfig --adapter=0 --od-gettemperature | gawk -F ': ' '
- gpu_temp=$( aticonfig --adapter=all --od-gettemperature | gawk -F ': ' '
- BEGIN {
- IGNORECASE=1
- gpuTemp=""
- gpuTempWorking=""
- }
- /Sensor (.*)[0-9\.]+ / {
- gpuTempWorking=gensub(/(.*) ([0-9\.]+) (.*)/, "\\2", "1", $2)
- if ( gpuTempWorking ~ /^[0-9\.]+$/ ) {
- gpuTemp=gpuTemp gpuTempWorking "C "
- }
- }
- END {
- print gpuTemp
- }' )
- # this handles some newer cases of free driver temp readouts, will require modifications as
- # more user data appears.
- elif [[ -n $Sensors_Data ]];then
- gpu_temp=$(
- gawk '
- BEGIN {
- IGNORECASE=1
- gpuTemp=""
- separator=""
- }
- /^('"$SENSORS_GPU_SEARCH"')-pci/ {
- while ( getline && !/^$/ ) {
- if ( /^temp/ ) {
- sub(/^[[:alnum:]]*.*:/, "", $0 ) # clear out everything to the :
- gsub(/[\+ \t°]/, "", $1) # ° is a special case, like a space for gawk
- gpuTemp=gpuTemp separator $1
- separator=","
- }
- }
- }
- END {
- print gpuTemp
- }' <<< "$Sensors_Data" )
- fi
-
- if [[ -n $gpu_temp ]];then
- echo $gpu_temp
- fi
+# check for usb/firewire/[and thunderwire when data found]
+sub peripheral_data {
+ eval $start if $b_log;
+ my ($id) = @_;
+ my ($type) = ('');
+ # print "$id here\n";
+ if (@by_id){
+ foreach (@by_id) {
+ if ("/dev/$id" eq Cwd::abs_path($_)){
+ #print "$id here\n";
+ if (/usb-/i){
+ $type = 'USB';
+ }
+ elsif (/ieee1394--/i){
+ $type = 'FireWire';
+ }
+ last;
+ }
+ }
+ }
+ # note: sometimes with wwn- numbering usb does not appear in by-id but it does in by-path
+ if (!$type && @by_path){
+ foreach (@by_path) {
+ if ("/dev/$id" eq Cwd::abs_path($_)){
+ if (/usb-/i){
+ $type = 'USB';
+ }
+ elsif (/ieee1394--/i){
+ $type = 'FireWire';
+ }
+ last;
+ }
+ }
+ }
+ eval $end if $b_log;
+ return $type;
}
-
-## for possible future data, not currently used
-get_graphics_agp_data()
-{
- eval $LOGFS
- local agp_module=''
-
- if [[ $B_MODULES_FILE == 'true' ]];then
- ## not used currently
- agp_module=$( gawk '
- /agp/ && !/agpgart/ && $3 > 0 {
- print(gensub(/(.*)_agp.*/,"\\1","g",$1))
- }' $FILE_MODULES )
- log_function_data 'cat' "$FILE_MODULES"
- fi
- log_function_data "agp_module: $agp_module"
- eval $LOGFE
-}
-
-## create array of gfx cards installed on system
-get_graphics_card_data()
-{
- eval $LOGFS
- local i='' a_temp=''
-
- IFS=$'\n'
- A_GRAPHICS_CARD_DATA=( $( gawk -F': ' '
- BEGIN {
- IGNORECASE=1
- busId=""
- trueCard=""
- card=""
- driver=""
- }
- # not using 3D controller yet, needs research: |3D controller |display controller
- # note: this is strange, but all of these can be either a separate or the same
- # card. However, by comparing bus id, say: 00:02.0 we can determine that the
- # cards are either the same or different. We want only the .0 version as a valid
- # card. .1 would be for example: Display Adapter with bus id x:xx.1, not the right one
- /vga compatible controller|3D controller|Display controller/ {
- driver=""
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF)
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
- if ( '$COLS_INNER' < 100 ){
- sub(/Core Processor Family/,"Core", $NF)
- }
- gsub(/^ +| +$/, "", $NF)
- gsub(/ [ \t]+/, " ", $NF)
- card=$NF
- busId=gensub(/^([0-9a-f:\.]+) (.+)$/,"\\1",1,$1)
- trueCard=gensub(/(.*)\.([0-9]+)$/,"\\2",1,busId)
- while ( getline && !/^$/) {
- if ( $1 ~ /Kernel driver in use/ ){
- driver=$2
- }
- }
- if ( trueCard == 0 ) {
- print card "," busId "," driver
- # print card "," busId "," driver > "/dev/tty"
- }
- }' <<< "$LSPCI_V_DATA" ) )
- IFS="$ORIGINAL_IFS"
-# for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
-# do
-# A_GRAPHICS_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GRAPHICS_CARD_DATA[i]}" )
-# done
-
- # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory..
- # GFXMEM="size=[$(echo "$LSPCI_V_DATA" | gawk '/VGA/{while (!/^$/) {getline;if (/size=[0-9][0-9]*M/) {size2=gensub(/.*\[size=([0-9]+)M\].*/,"\\1","g",$0);if (size<size2){size=size2}}}}END{print size2}')M]"
- a_temp=${A_GRAPHICS_CARD_DATA[@]}
- log_function_data "A_GRAPHICS_CARD_DATA: $a_temp"
- eval $LOGFE
-}
-
-get_graphics_driver()
-{
- eval $LOGFS
-
- # list is from sgfxi plus non-free drivers
- local driver_list='amdgpu|apm|ark|ati|chips|cirrus|cyrix|fbdev|fglrx|glint|i128|i740|i810|iftv|imstt|intel|ivtv|mach64|mesa|mga|modesetting|neomagic|newport|nouveau|nsc|nvidia|nv|openchrome|radeonhd|radeon|rendition|s3virge|s3|savage|siliconmotion|sisimedia|sisusb|sis|tdfx|tga|trident|tseng|unichrome|v4l|vboxvideo|vesa|vga|via|vmware|voodoo'
- local driver='' driver_string='' xorg_log_data='' status='' a_temp=''
-
- if [[ $B_XORG_LOG == 'true' ]];then
- A_GRAPHIC_DRIVERS=( $(
- gawk '
- BEGIN {
- driver=""
- bLoaded="false"
- IGNORECASE=1
- }
- # note that in file names, driver is always lower case
- /[[:space:]]Loading.*('"$driver_list"')_drv.so$/ {
- driver=gensub(/.*[[:space:]]Loading.*('"$driver_list"')_drv.so/, "\\1", 1, $0 )
- # we get all the actually loaded drivers first, we will use this to compare the
- # failed/unloaded, which have not always actually been truly loaded
- aDrivers[driver]="loaded"
- }
- # openbsd uses UnloadModule:
- /(Unloading[[:space:]]|UnloadModule).*('"$driver_list"')(\"||_drv.so)$/ {
- gsub(/\"/,"",$0)
- driver=gensub(/(.*)(Unloading[[:space:]]|UnloadModule).*('"$driver_list"')(\"||_drv.so)$/, "\\3", 1, $0 )
- # we need to make sure that the driver has already been truly loaded, not just discussed
- if ( driver in aDrivers ) {
- aDrivers[driver]="unloaded"
- }
- }
- /Failed.*('"$driver_list"')_drv.so|Failed.*\"('"$driver_list"')\"/ {
- driver=gensub(/(.*)Failed.*('"$driver_list"')_drv.so/, "\\2", 1, $0 )
- if ( driver == $0 ) {
- driver=gensub(/(.*)Failed.*\"('"$driver_list"')\".*|fred/, "\\2", 1, $0 )
- }
- # we need to make sure that the driver has already been truly loaded, not just discussed
- if ( driver != $0 && driver in aDrivers ) {
- aDrivers[driver]="failed"
- }
- }
- # verify that the driver actually started the desktop, even with false failed messages which can occur
- # this is the driver that is actually driving the display
- /.*\([0-9]+\):[[:space:]]Depth.*framebuffer/ {
- driver=gensub(/.*('"$driver_list"')\([0-9]+\):[[:space:]]Depth.*framebuffer.*/, "\\1", 1, $0 )
- # we need to make sure that the driver has already been truly loaded, not just discussed, also
- # set driver to lower case because sometimes it will show as RADEON or NVIDIA in the actual x start
- driver=tolower(driver)
- if ( driver != $0 && driver in aDrivers ) {
- aDrivers[driver]="loaded"
- }
- }
- END {
- for ( driver in aDrivers ) {
- print driver "," aDrivers[driver]
- }
- }' < $FILE_XORG_LOG ) )
- fi
- a_temp=${A_GRAPHIC_DRIVERS[@]}
- log_function_data "A_GRAPHIC_DRIVERS: $a_temp"
-
- eval $LOGFE
+sub partition_scheme {
+ eval $start if $b_log;
+ my ($set_cmd,$id) = @_;
+ my ($cmd,$pt,$program,@data,@return);
+ if ($set_cmd ne 'unset'){
+ $return[0] = $set_cmd;
+ }
+ else {
+ # runs as user, but is SLOW: udisksctl info -b /dev/sda
+ # line: org.freedesktop.UDisks2.PartitionTable:
+ # Type: dos
+ if (!$b_root){
+ if ($program = main::check_program('udevadm')){
+ $return[0] = "$program info -q property -n ";
+ }
+ }
+ if (!$return[0] && $b_root && -e "/lib/udev/udisks-part-id") {
+ $return[0] = "/lib/udev/udisks-part-id /dev/";
+ }
+ elsif (!$return[0] && $b_root && ($program = main::check_program('fdisk'))) {
+ $return[0] = "$program -l /dev/";
+ }
+ if (!$return[0]) {
+ $return[0] = 'na'
+ }
+ }
+ if ($return[0] ne 'na'){
+ $cmd = "$return[0]$id 2>&1";
+ main::log_data('cmd',$cmd) if $b_log;
+ @data = main::grabber($cmd);
+ # for pre ~ 2.30 fdisk did not show gpt, but did show gpt scheme error, so
+ # if no gpt match, it's dos = mbr
+ if ($cmd =~ /fdisk/){
+ foreach (@data){
+ if (/^WARNING:\s+GPT/){
+ $return[1] = 'gpt';
+ last;
+ }
+ elsif (/^Disklabel\stype:\s*(.+)/i){
+ $return[1] = $1;
+ last;
+ }
+ }
+ $return[1] = 'dos' if !$return[1];
+ }
+ else {
+ $return[1] = main::awk(\@data,'^(UDISKS_PARTITION_TABLE_SCHEME|ID_PART_TABLE_TYPE)',2,'=');
+ }
+ $return[1] = 'mbr' if $return[1] eq 'dos';
+ }
+ eval $end if $b_log;
+ return @return;
+}
+sub scsi_data {
+ eval $start if $b_log;
+ my ($file) = @_;
+ my @temp = main::reader($file);
+ my (@scsi);
+ my ($firmware,$model,$vendor) = ('','','');
+ foreach (@temp){
+ if (/Vendor:\s*(.*)\s+Model:\s*(.*)\s+Rev:\s*(.*)/i){
+ $vendor = $1;
+ $model = $2;
+ $firmware = $3;
+ }
+ if (/Type:/i){
+ if (/Type:\s*Direct-Access/i){
+ my @working = ({
+ 'vendor' => $vendor,
+ 'model' => $model,
+ 'firmware' => $firmware,
+ });
+ @scsi = (@scsi,@working);
+ }
+ else {
+ ($firmware,$model,$vendor) = ('','','');
+ }
+ }
+ }
+ main::log_data('dump','@scsi', \@scsi) if $b_log;
+ eval $end if $b_log;
+ return @scsi;
}
-## create array of glx data
-get_graphics_glx_data()
-{
- eval $LOGFS
- local a_temp=''
- # if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
- if [[ $B_SHOW_DISPLAY_DATA == 'true' ]];then
- IFS='^'
- # NOTE: glxinfo -B is not always available, unforunately
- A_GLX_DATA=( $( eval glxinfo $DISPLAY_OPT 2>/dev/null | gawk -F ': ' '
- # handle > 1 cases of detections
- function join( arr, sep ) {
- s=""
- i=flag=0
- for ( i in arr ) {
- if ( flag++ ) {
- s = s sep
- }
- s = s i
- }
- return s
- }
-
- BEGIN {
- IGNORECASE=1
- compatVersion=""
- # create empty arrays
- split("", a)
- split("", b)
- split("", c)
- split("", d)
- }
- /opengl renderer/ {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $2)
- gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
- gsub(/^ +| +$/, "", $2)
- if ( $2 ~ /mesa/ ) {
- # Allow all mesas
-# if ( $2 ~ / r[3-9][0-9][0-9] / ) {
- a[$2]
- # this counter failed in one case, a bug, and is not needed now
-# f++
-# }
- next
+sub disk_serial_by_id {
+ eval $start if $b_log;
+ my ($device) = @_;
+ my ($serial) = ('');
+ foreach (@by_id){
+ if ($device eq Cwd::abs_path($_)){
+ my @data = split /_/, $_;
+ $serial = $data[-1];
+ $serial =~ s/-[0-9]+:[0-9]+$//;
+ # print $device, ' ', Cwd::abs_path($_),' ', $serial,"\n";
+ last;
+ }
+ }
+ eval $end if $b_log;
+ return $serial;
+}
+# Normally hddtemp requires root, but you can set user rights in /etc/sudoers.
+# args: $1 - /dev/<disk> to be tested for
+sub hdd_temp {
+ eval $start if $b_log;
+ my ($device) = @_;
+ my ($path) = ('');
+ my (@data,$hdd_temp);
+ if (!$b_sudo){
+ $b_sudo = 1;
+ if (!$b_root && ($path = main::check_program('sudo') )) {
+ $sudo = "$path -n ";
+ }
+ }
+ if ($device =~ /nvme/i){
+ if (!$b_nvme){
+ $b_nvme = 1;
+ if ($path = main::check_program('nvme')) {
+ $nvme = $path;
}
-
- $2 && a[$2]
- }
- # dropping all conditions from this test to just show full mesa information
- # there is a user case where not f and mesa apply, atom mobo
- # /opengl version/ && ( f || $2 !~ /mesa/ ) {
- /opengl version/ {
- # fglrx started appearing with this extra string, does not appear to communicate anything of value
- sub(/(Compatibility Profile Context|\(Compatibility Profile\))/, "", $2 )
- gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
- gsub(/^ +| +$/, "", $2)
- $2 && b[$2]
- # note: this is going to be off if ever multi opengl versions appear, never seen one
- compatVersion=gensub(/^([^ \t]+)[ \t].*/,"\\1","g",$2)
- }
- /opengl core profile version/ {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $2)
- # fglrx started appearing with this extra string, does not appear to communicate anything of value
- sub(/(Core Profile Context|\(Core Profile\))/, "", $2 )
- gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
- gsub(/^ +| +$/, "", $2)
- $2 && d[$2]
- }
- /direct rendering/ {
- $2 && c[$2]
- }
- # if -B was always available, we could skip this, but it is not
- /GLX Visuals/ {
- exit
- }
- END {
- dr = join( c, ", " )
- oglr = join( a, ", " )
- oglv = join( b, ", " )
- oglcpv = join( d, ", " )
- # output processing done in print functions, important! do not use \n IFS
- # because Bash treats an empty value surrounded by \n\n as nothing, not an empty array key!
- # this came up re oglcpv being empty and compatVersion being used instead
- printf( "%s^%s^%s^%s^%s", oglr, oglv, dr, oglcpv, compatVersion )
- }' ) )
- IFS="$ORIGINAL_IFS"
-
- # GLXR=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl renderer/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
- # GLXV=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl version/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
- fi
- a_temp=${A_GLX_DATA[@]}
- log_function_data "A_GLX_DATA: $a_temp"
- eval $LOGFE
-}
-
-## return screen resolution / tty resolution
-## args: $1 - reg/tty
-get_graphics_res_data()
-{
- eval $LOGFS
- local screen_resolution='' xdpy_data='' screens_count=0 tty_session='' option=$1
-
- # if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
- if [[ $B_SHOW_DISPLAY_DATA == 'true' && $option != 'tty' ]];then
- # Added the two ?'s , because the resolution is now reported without spaces around the 'x', as in
- # 1400x1050 instead of 1400 x 1050. Change as of X.org version 1.3.0
- xdpy_data="$( xdpyinfo $DISPLAY_OPT 2>/dev/null )"
- xdpy_count=$( grep -c 'dimensions' <<< "$xdpy_data" )
- # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
- # multiple screens from different video cards
- if [[ $xdpy_count -eq 1 ]];then
- screen_resolution=$( xrandr $DISPLAY_OPT 2>/dev/null | gawk '
- /\*/ {
- res[++m] = gensub(/^.* ([0-9]+) ?x ?([0-9]+)[_ ].* ([0-9\.]+)\*.*$/,"\\1x\\2@\\3hz","g",$0)
- }
- END {
- for (n in res) {
- if (res[n] ~ /^[[:digit:]]+x[[:digit:]]+/) {
- line = line ? line ", " res[n] : res[n]
- }
+ }
+ if ($nvme){
+ $device =~ s/n[0-9]//;
+ @data = main::grabber("$sudo$nvme smart-log $device 2>/dev/null");
+ foreach (@data){
+ my @row = split /\s*:\s*/, $_;
+ # other rows may have: Temperature sensor 1 :
+ if ( $row[0] eq 'temperature') {
+ $row[1] =~ s/\s*C//;
+ $hdd_temp = $row[1];
+ last;
}
- if (line) {
- print(line)
- }
- }' )
- fi
- if [[ -z $screen_resolution || $xdpy_count -gt 1 ]];then
- screen_resolution=$( gawk '
- BEGIN {
- IGNORECASE=1
- screens = ""
- separator = ""
- }
- /dimensions/ {
- screens = screens separator # first time, this is null, next, has comma last
- screens = screens $2 # then tack on the new value for nice comma list
- separator = ", "
- }
- END {
- print screens
- }' <<< "$xdpy_data" )
- fi
- else
- if [[ $B_PROC_DIR == 'true' && -z $BSD_TYPE ]];then
- screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{
- print $2"x"$1
- }' )
- # really old systems may not support the above method
- if [[ -z $screen_resolution ]];then
- screen_resolution=$( stty -a | gawk -F ';' '
- /^speed/ {
- gsub(/[[:space:]]*(rows|columns)[[:space:]]*/,"",$0)
- gsub(/[[:space:]]*/,"",$2)
- gsub(/[[:space:]]*/,"",$3)
- print $3"x"$2
- }' )
- fi
- # note: this works fine for all systems but keeping the above for now since
- # the above is probably more accurate for linux systems.
- else
- if [[ $B_CONSOLE_IRC != 'true' ]];then
- screen_resolution=$( stty -a | gawk -F ';' '
- /^speed/ {
- gsub(/[[:space:]]*(rows|columns)[[:space:]]*/,"",$0)
- gsub(/[[:space:]]*/,"",$2)
- gsub(/[[:space:]]*/,"",$3)
- print $3"x"$2
- }' )
- else
- if [[ -n $BSD_TYPE ]];then
- tty_session=$( get_tty_console_irc )
- # getting information for tty that owns the irc client
- screen_resolution="$( stty -f /dev/pts/$tty_session size | gawk '{print $2"x"$1}' )"
- fi
- fi
- fi
- fi
- echo "$screen_resolution"
- log_function_data "screen_resolution: $screen_resolution"
- eval $LOGFE
-}
-
-## create array of display server vendor/version data
-get_graphics_display_server_data()
-{
- eval $LOGFS
- local vendor='' vendor_version='' a_temp='' xdpy_info='' a_display_vendor_working=''
- # note: this may not always be set, it won't be out of X, for example
- local server="$XDG_SESSION_TYPE" compositor='' compositor_version=''
-
- if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- compositor="$(get_graphics_display_compositor)" compositor_version=''
- fi
-
- if [[ $server == '' ]];then
- if [[ -n "$WAYLAND_DISPLAY" ]];then
- server='wayland'
- fi
- fi
- # if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
- if [[ $B_SHOW_DISPLAY_DATA == 'true' ]];then
- # X vendor and version detection.
- # new method added since radeon and X.org and the disappearance of <X server name> version : ...etc
- # Later on, the normal textual version string returned, e.g. like: X.Org version: 6.8.2
- # A failover mechanism is in place. (if $version is empty, the release number is parsed instead)
- # xdpy_info="$( xdpyinfo )"
- IFS=","
- a_display_vendor_working=( $( xdpyinfo $DISPLAY_OPT 2>/dev/null | gawk -F': +' '
- BEGIN {
- IGNORECASE=1
- vendorString=""
- version=""
- vendorRelease=""
- }
- /vendor string/ {
- gsub(/\ythe\y|\yinc\y|foundation|project|corporation/, "", $2)
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $2)
- gsub(/^ +| +$/, "", $2)
- gsub(/ [ \t]+/, " ", $2)
- vendorString = $2
- }
- /version:/ {
- version = $NF
- }
- /vendor release number/ {
- gsub(/0+$/, "", $2)
- gsub(/0+/, ".", $2)
- vendorRelease = $2
- }
- /(supported pixmap|keycode range|number of extensions|^screen)/ {
- exit # we are done with the info we want, no reason to read the rest
- }
- END {
- print vendorString "," version "," vendorRelease
- }' ) )
- vendor=${a_display_vendor_working[0]}
- vendor_version=${a_display_vendor_working[1]}
-
- # this gives better output than the failure last case, which would only show:
- # for example: X.org: 1.9 instead of: X.org: 1.9.0
- if [[ -z $vendor_version ]];then
- vendor_version=$( get_graphics_display_x_version )
- fi
- if [[ -z $vendor_version ]];then
- vendor_version=${a_display_vendor_working[2]}
- fi
-
- # some distros, like fedora, report themselves as the xorg vendor, so quick check
- # here to make sure the vendor string includes Xorg in string
- if [[ -z $( grep -E '(X|xorg|x\.org)' <<< $vendor ) ]];then
- vendor="$vendor X.org"
- fi
- IFS="$ORIGINAL_IFS"
- A_DISPLAY_SERVER_DATA[0]="$vendor"
- A_DISPLAY_SERVER_DATA[1]="$vendor_version"
- A_DISPLAY_SERVER_DATA[2]="$server"
- A_DISPLAY_SERVER_DATA[3]="$compositor"
- A_DISPLAY_SERVER_DATA[4]="$compositor_version"
- else
- vendor_version=$( get_graphics_display_x_version )
- if [[ -n $vendor_version ]];then
- vendor='X.org'
- A_DISPLAY_SERVER_DATA[0]="$vendor"
- A_DISPLAY_SERVER_DATA[1]="$vendor_version"
- A_DISPLAY_SERVER_DATA[2]="$server"
- A_DISPLAY_SERVER_DATA[3]="$compositor"
- A_DISPLAY_SERVER_DATA[4]="$compositor_version"
- fi
- fi
- a_temp=${A_DISPLAY_SERVER_DATA[@]}
- log_function_data "A_DISPLAY_SERVER_DATA: $a_temp"
- eval $LOGFE
-}
-
-get_graphics_display_compositor()
-{
- eval $LOGFS
- local compositor=''
-
- if [[ -z "${Ps_aux_Data/*mutter*/}" ]];then
- compositor='mutter'
- elif [[ -z "${Ps_aux_Data/*gnome-shell*/}" ]];then
- compositor='gnome-shell'
- elif [[ -z "${Ps_aux_Data/*kwin*/}" ]];then
- compositor='kwin'
- elif [[ -z "${Ps_aux_Data/*moblin*/}" ]];then
- compositor='moblin'
- elif [[ -z "${Ps_aux_Data/*kmscon*/}" ]];then
- compositor='kmscon'
- elif [[ -z "${Ps_aux_Data/*sway*/}" ]];then
- compositor='sway'
- elif [[ -z "${Ps_aux_Data/*grefson*/}" ]];then
- compositor='grefson'
- elif [[ -z "${Ps_aux_Data/*westford*/}" ]];then
- compositor='westford'
- elif [[ -z "${Ps_aux_Data/*rustland*/}" ]];then
- compositor='rustland'
- elif [[ -z "${Ps_aux_Data/*fireplace*/}" ]];then
- compositor='fireplace'
- elif [[ -z "${Ps_aux_Data/*wayhouse*/}" ]];then
- compositor='wayhouse'
- elif [[ -z "${Ps_aux_Data/*weston*/}" ]];then
- compositor='weston'
- elif [[ -z "${Ps_aux_Data/*compton*/}" ]];then
- compositor='compton'
- elif [[ -z "${Ps_aux_Data/*compiz*/}" ]];then
- compositor='compiz'
- elif [[ -z "${Ps_aux_Data/*swc*/}" ]];then
- compositor='swc'
- elif [[ -z "${Ps_aux_Data/*dwc*/}" ]];then
- compositor='dwc'
- fi
-
- log_function_data "compositor: $compositor"
- echo $compositor
- eval $LOGFE
+ }
+ }
+ }
+ else {
+ if (!$b_hddtemp){
+ $b_hddtemp = 1;
+ if ($path = main::check_program('hddtemp')) {
+ $hddtemp = $path;
+ }
+ }
+ if ($hddtemp){
+ $hdd_temp = (main::grabber("$sudo$hddtemp -nq -u C $device 2>/dev/null"))[0];
+ }
+ }
+ eval $end if $b_log;
+ return $hdd_temp;
+}
+# 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;
}
-
-## args: $1 - compositor
-get_graphics_display_wayland_version()
-{
- eval $LOGFS
-
- local version=''
-
- case $1 in
- mutter)
- :
- ;;
- esac
- log_function_data "version: $version"
- echo $version
-
- eval $LOGFE
}
-# if other tests fail, try this one, this works for root, out of X also
-get_graphics_display_x_version()
-{
- eval $LOGFS
- local version='' x_data=''
- # note that some users can have /usr/bin/Xorg but not /usr/bin/X
- if type -p X &>/dev/null;then
- # note: MUST be this syntax: X -version 2>&1
- # otherwise X -version overrides everything and this comes out null.
- # two knowns id strings: X.Org X Server 1.7.5 AND X Window System Version 1.7.5
- #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }'
- x_data="$( X -version 2>&1 )"
- elif type -p Xorg &>/dev/null;then
- x_data="$( Xorg -version 2>&1)"
- fi
- if [[ -n $x_data ]];then
- version=$(
- gawk '
- BEGIN {
- IGNORECASE=1
- }
- /^x.org x server/ {
- print $4
- exit
- }
- /^X Window System Version/ {
- print $5
- exit
- }' <<< "$x_data" )
- fi
- echo $version
- log_function_data " version: $version"
- eval $LOGFE
-}
-
-# this gets just the raw data, total space/percent used and disk/name/per disk capacity
-get_hdd_data_basic()
+## GraphicData
{
- eval $LOGFS
- local hdd_used='' a_temp='' df_string=''
- local hdd_data='' df_test='' swap_size=0
-
- if [[ -z $BSD_TYPE ]];then
- ## NOTE: older df do not have --total (eg: v: 6.10 2008)
- ## keep in mind the only value of use with --total is 'used' in blocks, which
- ## we can use later to calculate the real percentags based on disk sizes, not
- ## mounted partitions. Not using --total because it's more reliable to exclude non /dev
- df_string="df -P -T --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs
- --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=nfs
- --exclude-type=nfs3 --exclude-type=nfs4 --exclude-type=nfs5 --exclude-type=procfs --exclude-type=smbfs
- --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs"
- if swapon -s &>/dev/null;then
- swap_size=$( swapon -s 2>/dev/null | gawk '
- BEGIN {
- swapSize=0
- total=0
- }
- ( $2 == "partition" ) && ( $3 ~ /^[0-9]+$/ ) {
- total += ( 1000 / 1024 ) * $3
- }
- END {
- # result in kB, change to 1024 Byte blocks
- total = total * 1000 / 1024
- total = sprintf( "%.1f", total )
- print total
- }' )
- fi
- else
- # default size is 512, , so use -k for 1024 -H only for size in human readable format
- # older bsds don't support -T, pain, so we'll use partial output there
- if df -k -T &>/dev/null;then
- df_string='df -k -T'
- else
- df_string='df -k'
- fi
- if swapctl -l -k &>/dev/null;then
- swap_size=$( swapctl -l -k 2>/dev/null | gawk '
-BEGIN {
-swapSize=0
-total=0
-}
-( $1 ~ /^\/dev/ ) && ( $2 ~ /^[0-9]+$/ ) {
- total += $2
-}
-END {
- # result in blocks already
- print total
-}' )
- fi
- fi
- # echo ss: $swap_size
- hdd_data="$( eval $df_string )"
-
- # eval $df_string | awk 'BEGIN{tot=0} !/total/ {tot+=$4} END{print tot}'
- log_function_data 'raw' "hdd_data:\n$hdd_data"
- hdd_used=$( echo "$hdd_data" | gawk -v bsdType="$BSD_TYPE" -v swapSize="$swap_size" '
- BEGIN {
- # this is used for specific cases where bind, or incorrect multiple mounts to same partitions,
- # is present. The value is searched for an earlier appearance of that partition and if it is
- # present, the data is not added into the partition used size.
- partitionsSet=""
- # this handles a case where the same dev item is mounted twice to different points
- devSet=""
- devWorking=""
- mountWorking=""
- used=0
- }
- # using $1, not $2, because older bsd df do not have -T, filesystem type
- ( bsdType != "" ) && $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|filesystem|iso9660|linprocfs|nfs|nfs3|nfs4|nfs5|procfs|squashfs|smbfs|sysfs|tmpfs|type|unionfs)$/ {
- # note use next, not getline or it does not work right
- next
- }
- # also handles odd dm-1 type, from lvm, and mdraid, and some other bsd partition syntax
- # note that linux 3.2.45-grsec-9th types kernels have this type of partition name: /dev/xvdc (no number, letter)
- # note: btrfs does not seem to use partition integers, just the primary /dev/sdx identifier
- # df can also show /dev/disk/(by-label|by-uuid etc)
- /^\/dev\/(disk\/|mapper\/|[hsv]d[a-z]+[0-9]*|dm[-]?[0-9]+|(ada|mmcblk|nvme[0-9]+n)[0-9]+p[0-9]+.*|(ad|sd|wd)[0-9]+[a-z]|md[0-9]+|[aw]d[0-9]+s.*|xvd[a-z]+)|^ROOT/ {
- # this handles the case where the first item is too long
- # and makes df wrap output to next line, so here we advance
- # it to the next line for that single case. Using df -P should
- # make this unneeded but leave it in just in case
- if ( NF < 6 && $0 !~ /.*%/ ) {
- devSet = devSet "~" $1 "~"
- getline
- }
- # if the first item caused a wrap, use one less than standard
- # testing for the field with % in it, ie: 34%, then go down from there
- # this also protects against cases where the mount point has a space in the
- # file name, thus breaking going down from $NF directly.
- # some bsds will also have only 6 items
- if ( $5 ~ /.*%/ ) {
- devWorking="~" $1 "~"
- mountWorking="~" $6 "~"
- if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
- used += $3
- }
- partitionsSet = partitionsSet mountWorking
- # make sure to only include bsd real lines here, ie, short df output
- if ( $1 ~ /^\/dev\// ) {
- devSet = devSet devWorking
- }
- }
- # otherwise use standard
- else if ( $6 ~ /.*%/ ) {
- devWorking="~" $1 "~"
- mountWorking="~" $7 "~"
- if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
- used += $4
- }
- partitionsSet = partitionsSet mountWorking
- devSet = devSet devWorking
- }
- # and if this is not detected, give up, we need user data to debug
+package GraphicData;
+my $driver = ''; # we need this as a fallback in case no xorg.0.log
+sub get {
+ eval $start if $b_log;
+ my (@data,@rows);
+ my $num = 0;
+ if ($b_arm){
+ my $key = 'ARM';
+ @data = ({
+ main::key($num++,$key) => main::row_defaults('arm-pci',''),
+ },);
+ @rows = (@rows,@data);
+ }
+ else {
+ @data = card_data();
+ @rows = (@rows,@data);
+ if (!@rows){
+ my $key = 'Message';
+ @data = ({
+ main::key($num++,$key) => main::row_defaults('pci-card-data',''),
+ },);
+ @rows = (@rows,@data);
+ }
+ }
+ @data = display_data();
+ @rows = (@rows,@data);
+ @data = gl_data();
+ @rows = (@rows,@data);
+ eval $end if $b_log;
+ return @rows;
+}
+# 0 type
+# 1 type_id
+# 2 bus_id
+# 3 sub_id
+# 4 device
+# 5 vendor_id
+# 6 chip_id
+# 7 rev
+# 8 port
+# 9 driver
+# 10 modules
+# not using 3D controller yet, needs research: |3D controller |display controller
+# note: this is strange, but all of these can be either a separate or the same
+# card. However, by comparing bus id, say: 00:02.0 we can determine that the
+# cards are either the same or different. We want only the .0 version as a valid
+# card. .1 would be for example: Display Adapter with bus id x:xx.1, not the right one
+sub card_data {
+ eval $start if $b_log;
+ my (@rows,@data);
+ my ($j,$num) = (0,1);
+ foreach (@pci){
+ $num = 1;
+ my @row = @$_;
+ #print "$row[0] $row[3]\n";
+ if ($row[3] == 0 && ( $row[0] eq 'vga' || $row[0] eq 'display' || $row[0] eq '3d' ) ){
+ #print "$row[0] $row[3]\n";
+ $j = scalar @rows;
+ $driver = $row[9];
+ $driver ||= 'N/A';
+ my $card = main::trimmer($row[4]);
+ $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A';
+ #$card ||= '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);
+ }
+ @data = (
+ {
+ main::key($num++,'Card') => $card,
+ main::key($num++,'driver') => $driver,
+ },
+ );
+ @rows = (@rows,@data);
+ if ($row[9] && !$bsd_type){
+ my $version = main::get_module_version($row[9]);
+ $version ||= 'N/A';
+ $rows[$j]{main::key($num++,'v')} = $version;
+ }
+ if ($extra > 0){
+ $rows[$j]{main::key($num++,'bus ID')} = "$row[2].$row[3]";
+ }
+ if ($extra > 1){
+ $rows[$j]{main::key($num++,'chip ID')} = "$row[5]:$row[6]";
+ }
+ }
+ #print "$row[0]\n";
+ }
+ #my $ref = $pci[-1];
+ #print $$ref[0],"\n";
+ eval $end if $b_log;
+ return @rows;
+}
+sub display_data(){
+ eval $start if $b_log;
+ my (%graphics,@row);
+ my @xdpyinfo;
+ my $num = 0;
+ my ($protocol,$server) = ('','');
+ # note: these may not always be set, they won't be out of X, for example
+ $protocol = $ENV{'XDG_SESSION_TYPE'} if $ENV{'XDG_SESSION_TYPE'};
+ $protocol = $ENV{'WAYLAND_DISPLAY'} if (!$protocol && $ENV{'WAYLAND_DISPLAY'});
+ # 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 (my $program = main::check_program('loginctl')){
+ my $id = '';
+ # $id = $ENV{'XDG_SESSION_ID'}; # returns tty session in console
+ my @data = main::grabber("$program --no-pager --no-legend 2>/dev/null",'','strip');
+ foreach (@data){
+ next if /tty[0-6]$/;
+ $id = (split /\s+/, $_)[0];
+ last; # multiuser? too bad, we'll go for the first one
+ }
+ if ($id ){
+ my $temp = (main::grabber("$program show-session $id -p Type --no-pager --no-legend 2>/dev/null"))[0];
+ $temp =~ s/Type=// if $temp;
+ # ssh will not show /dev/ttyx so would have passed the first test
+ $protocol = $temp if $temp && $temp ne 'tty';
+ }
+ }
+ }
+ if ($extra > 1){
+ # initial tests, if wayland, it is certainly a compositor
+ $protocol = lc($protocol) if $protocol;
+ $graphics{'compositor'} = display_compositor($protocol);
+ }
+ if ( $b_display){
+ # X vendor and version detection.
+ # new method added since radeon and X.org and the disappearance of
+ # <X server name> version : ...etc. Later on, the normal textual version string
+ # returned, e.g. like: X.Org version: 6.8.2
+ # A failover mechanism is in place: if $version empty, release number parsed instead
+ if (my $program = main::check_program('xdpyinfo')){
+ my @xdpyinfo = main::grabber("$program $display_opt 2>/dev/null","\n",'strip');
+ #@xdpyinfo = map {s/^\s+//;$_} @xdpyinfo if @xdpyinfo;
+ #print join "\n",@xdpyinfo, "\n";
+ foreach (@xdpyinfo){
+ my @working = split /:\s+/, $_;
+ next if ( ($graphics{'dimensions'} && $working[0] ne 'dimensions' ) || !$working[0] );
+ #print "$_\n";
+ if ($working[0] eq 'vendor string'){
+ $working[1] =~ s/The\s|\sFoundation//g;
+ # some distros, like fedora, report themselves as the xorg vendor,
+ # so quick check here to make sure the vendor string includes Xorg in string
+ if ($working[1] !~ /x/i){
+ $working[1] .= ' X.org';
+ }
+ $graphics{'vendor'} = $working[1];
+ }
+ elsif ($working[0] eq 'version number'){
+ $graphics{'version-id'} = $working[1];
+ }
+ elsif ($working[0] eq 'vendor release number'){
+ $graphics{'vendor-release'} = $working[1];
+ }
+ elsif ($working[0] eq 'X.Org version'){
+ $graphics{'xorg-version'} = $working[1];
+ }
+ elsif ($working[0] eq 'dimensions'){
+ $working[1] =~ s/\spixels//;
+ $working[1] =~ s/\smillimeters/ mm/;
+ if ($graphics{'dimensions'}){
+ $graphics{'dimensions'} = ([@{$graphics{'dimensions'}},$working[1]]);
+ }
+ else {
+ $graphics{'dimensions'} = ([$working[1]]);
+ }
+ }
+ }
+ #$graphics{'dimensions'} = (\@dimensions);
+ # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
+ # multiple screens from different video cards
+ my $ref = $graphics{'dimensions'};
+ if (defined $ref){
+ my @screens = @$ref;
+ if (scalar @screens == 1){
+ if (my $program = main::check_program('xrandr')){
+ my @xrandr = main::grabber("$program $display_opt 2>/dev/null",'','strip');
+ foreach (@xrandr){
+ my @working = split /\s+/,$_;
+ print join "$_\n";
+ if ($working[1] =~ /\*/){
+ $working[1] =~ s/\*|\+//g;
+ $working[1] = sprintf("%0.0f",$working[1]);
+ my $screen = "$working[0]~$working[1]Hz";
+ if ($graphics{'screens'}){
+ $graphics{'screens'} = ([@{$graphics{'screens'}},$screen]);
+ }
+ else {
+ $graphics{'screens'} = ([$screen]);
+ }
+ }
+ }
+
+ }
+ }
+ }
+ else {
+ $graphics{'tty'} = tty_data();
+ }
+ }
else {
- next
- }
- }
- END {
- used=used + swapSize
- used = sprintf( "%.1f", used )
- print used
- }' )
- # echo hdu:$hdd_used
- if [[ -z $hdd_used ]];then
- hdd_used='na'
- fi
- log_function_data "hdd_used: $hdd_used"
- # create the initial array strings:
- # disk-dev, capacity, name, usb or not
- # final item is the total of the disk
- IFS=$'\n'
-
- if [[ $B_PARTITIONS_FILE == 'true' ]];then
- A_HDD_DATA=( $(
- gawk -v hddUsed=$hdd_used '
- /([hsv]d[a-z]+|(ada|mmcblk|nvme[0-9]+n)[0-9]+)$/ {
- driveSize = $(NF - 1)*1024/1000**3
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", driveSize)
- gsub(/^ +| +$/, "", driveSize)
- printf( $NF",%.1fGB,,\n", driveSize )
+ $graphics{'screens'} = ([main::row_defaults('xdpyinfo-missing')]);
}
- # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below
- # See https://www.mjmwired.net/kernel/Documentation/devices.txt for kernel 4.x device numbers
- # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0 {
- # size += $3
- # }
- # special case from this data: 8 0 156290904 sda
- # note: known starters: vm: 252/253/254; grsec: 202; nvme: 259
- $1 ~ /^(3|8|22|33|202|252|253|254|259)$/ && $NF ~ /(nvme[0-9]+n[0-9]+|[hsv]d[a-z]+)$/ && ( $2 % 16 == 0 || $2 % 16 == 8 ) {
- size += $3
- }
- END {
- size = size*1024/1000**3 # calculate size in GB size
- workingUsed = hddUsed*1024/1000**3 # calculate workingUsed in GB used
- # this handles a special case with livecds where no hdd_used is detected
- if ( size > 0 && hddUsed == "na" ) {
- size = sprintf( "%.1f", size )
- print size "GB,-,,.."
- }
- else if ( size > 0 && workingUsed > 0 ) {
- diskUsed = workingUsed*100/size # calculate used percentage
- diskUsed = sprintf( "%.1f", diskUsed )
- if ( int(diskUsed) > 100 ) {
- diskUsed = "Used Error!"
+ }
+ else {
+ $graphics{'tty'} = tty_data();
+ }
+ # this gives better output than the failure last case, which would only show:
+ # for example: X.org: 1.9 instead of: X.org: 1.9.0
+ $graphics{'version'} = $graphics{'xorg-version'} if $graphics{'xorg-version'};;
+ $graphics{'version'} = x_version() if !$graphics{'version'};
+ $graphics{'version'} = $graphics{'version-id'} if !$graphics{'version'};
+
+ undef @xdpyinfo;
+ #print Data::Dumper::Dumper \%graphics;
+ if (%graphics){
+ my $resolution = '';
+ my $server_string = '';
+ if ($graphics{'vendor'}){
+ my $version = ($graphics{'version'}) ? " $graphics{'version'}" : '';
+ $server_string = "$graphics{'vendor'}$version";
+ }
+ elsif ($graphics{'version'}) {
+ $server_string = "X.org $graphics{'version'}";
+ }
+ if ($graphics{'screens'}){
+ my $ref = $graphics{'screens'};
+ my @screens = @$ref;
+ my $sep = '';
+ foreach (@screens){
+ $resolution .= $sep . $_;
+ $sep = ', ';
+ }
+ }
+ my @drivers = x_drivers();
+ if (!$protocol && !$server_string && !$graphics{'vendor'} && !@drivers){
+ $server_string = main::row_defaults('display-server');
+ @row = ({
+ main::key($num++,'Display') => '',
+ main::key($num++,'server') => $server_string,
+ });
+ }
+ else {
+ $server_string ||= 'N/A';
+ # note: if no xorg log, and if wayland, there will be no xorg drivers,
+ # obviously, so we use the last driver found on the card section in that case.
+ # those come from lscpi kernel drivers so there should be no xorg/wayland issues.
+ $driver = ($drivers[0]) ? $drivers[0]: $driver;
+ @row = ({
+ main::key($num++,'Display') => $protocol,
+ main::key($num++,'server') => $server_string,
+ main::key($num++,'driver') => $driver,
+ });
+ if ($drivers[2]){
+ $row[0]{main::key($num++,'FAILED')} = $drivers[2];
+ }
+ if ($drivers[1]){
+ $row[0]{main::key($num++,'unloaded')} = $drivers[1];
+ }
+ if ($graphics{'compositor'}){
+ $row[0]{main::key($num++,'compositor')} = $graphics{'compositor'};
+ }
+ }
+ if ($resolution){
+ $row[0]{main::key($num++,'resolution')} = $resolution;
+ }
+ else {
+ $graphics{'tty'} ||= 'N/A';
+ $row[0]{main::key($num++,'tty')} = $graphics{'tty'};
+ }
+ }
+ eval $end if $b_log;
+ return @row;
+}
+sub gl_data(){
+ eval $start if $b_log;
+ my $num = 0;
+ my (@row,$arg);
+ #print ("$b_display : $b_root\n");
+ if ( $b_display){
+ if (my $program = main::check_program('glxinfo')){
+ # NOTE: glxinfo -B is not always available, unforunately
+ my @glxinfo = main::grabber("$program $display_opt 2>/dev/null");
+ if (!@glxinfo){
+ my $type = 'display-console';
+ if ($b_root){
+ $type = 'display-root-x';
}
else {
- diskUsed = diskUsed "% used"
+ $type = 'display-null';
}
- size = sprintf( "%.1f", size )
- print size "GB," diskUsed ",,.."
+ @row = ({
+ main::key($num++,'Message') => main::row_defaults($type),
+ });
+ return @row;
+ }
+ #print join "\n",@glxinfo,"\n";
+ my $compat_version = '';
+ my ($b_compat,@core_profile_version,@direct_render,@renderer,@opengl_version,@working);
+ foreach (@glxinfo){
+ next if /^\s/;
+ if (/^opengl renderer/i){
+ @working = split /:\s*/, $_;
+ $working[1] = main::cleaner($working[1]);
+ # Allow all mesas
+ #if ($working[1] =~ /mesa/i){
+ #
+ #}
+ push @renderer, $working[1];
+ }
+ # dropping all conditions from this test to just show full mesa information
+ # there is a user case where not f and mesa apply, atom mobo
+ # /opengl version/ && ( f || $2 !~ /mesa/ ) {
+ elsif (/^opengl version/i){
+ # fglrx started appearing with this extra string, does not appear
+ # to communicate anything of value
+ @working = split /:\s*/, $_;
+ $working[1] =~ s/(Compatibility Profile Context|\(Compatibility Profile\))//;
+ $working[1] =~ s/\s\s/ /g;
+ $working[1] =~ s/^\s+|\s+$//;
+ push @opengl_version, $working[1];
+ # note: this is going to be off if ever multi opengl versions appear, never seen one
+ @working = split /\s+/, $working[1];
+ $compat_version = $working[0];
+ }
+ elsif (/^opengl core profile version/i){
+ # fglrx started appearing with this extra string, does not appear
+ # to communicate anything of value
+ @working = split /:\s*/, $_;
+ $working[1] =~ s/(Compatibility Profile Context|\((Compatibility|Core) Profile\))//;
+ $working[1] =~ s/\s\s/ /g;
+ $working[1] =~ s/^\s+|\s+$//;
+ push @core_profile_version, $working[1];
+ }
+ elsif (/direct rendering/){
+ @working = split /:\s*/, $_;
+ push @direct_render, $working[1];
+ }
+ # if -B was always available, we could skip this, but it is not
+ elsif (/GLX Visuals/){
+ last;
+ }
+ }
+ my ($direct_render,$renderer,$version) = ('N/A','N/A','N/A');
+ $direct_render = join ', ', @direct_render if @direct_render;
+ # non free drivers once filtered and cleaned show the same for core and compat
+ # but this stopped for some reason at 4.5/4.6 nvidia
+ if (@core_profile_version && @opengl_version &&
+ join ('', @core_profile_version) ne join( '', @opengl_version) &&
+ !(grep {/nvidia/i} @opengl_version ) ){
+ @opengl_version = @core_profile_version;
+ $b_compat = 1;
+ }
+ $version = join ', ', @opengl_version if @opengl_version;
+ $renderer = join ', ', @renderer if @renderer;
+ @row = ({
+ main::key($num++,'OpenGL') => '',
+ main::key($num++,'renderer') => $renderer,
+ main::key($num++,'v') => $version,
+ });
+
+ if ($b_compat && $extra > 1 && $compat_version){
+ $row[0]{main::key($num++,'compat-v')} = $compat_version;
+ }
+ if ($extra > 0){
+ $row[0]{main::key($num++,'direct render')} = $direct_render;
+ }
+ }
+ else {
+ @row = ({
+ main::key($num++,'Message') => main::row_defaults('glxinfo-missing'),
+ });
+ }
+ }
+ else {
+ my $type = 'display-console';
+ if (!main::check_program('glxinfo')){
+ $type = 'glxinfo-missing';
+ }
+ else {
+ if ($b_root){
+ $type = 'display-root';
}
else {
- print "NA,-,,.." # print an empty array, this will be further handled in the print out function
- }
- }' $FILE_PARTITIONS ) )
- log_function_data 'cat' "$FILE_PARTITIONS"
- else
- if [[ -n $BSD_TYPE ]];then
- get_hard_drive_data_bsd "$hdd_used"
- fi
- fi
- IFS="$ORIGINAL_IFS"
- a_temp=${A_HDD_DATA[@]}
- # echo ${a_temp[@]}
- log_function_data "A_HDD_DATA: $a_temp"
- eval $LOGFE
-}
-
-## fills out the A_HDD_DATA array with disk names
-get_hard_drive_data_advanced()
-{
- eval $LOGFS
- local a_temp_working='' a_temp_scsi='' temp_holder='' temp_name='' i='' j=''
- local sd_ls_by_id='' ls_disk_by_id='' ls_disk_by_path='' usb_exists='' a_temp=''
- local firewire_exists='' thunderbolt_exists='' thunderbolt_exists='' hdd_temp hdd_serial=''
- local firmware_rev='' working_path='' block_type=''
+ $type = 'display-try';
+ }
+ }
+ @row = ({
+ main::key($num++,'Message') => main::row_defaults($type),
+ });
+ }
+ eval $end if $b_log;
+ return @row;
+}
+sub tty_data(){
+ eval $start if $b_log;
+ my ($tty);
+ if ($size{'term-cols'}){
+ $tty = "$size{'term-cols'}x$size{'term-lines'}";
+ }
+ elsif ($b_irc && $client{'console-irc'}){
+ my $tty_working = main::get_tty_console_irc();
+ if (my $program = main::check_program('stty')){
+ my $tty_arg = ($bsd_type) ? '-f' : '-F';
+ $tty = (main::grabber("$program $tty_arg /dev/pts/$tty_working size 2>/dev/null"))[0];
+ if ($tty){
+ my @temp = split /\s+/, $tty;
+ $tty = "$temp[1]x$temp[0]";
+ }
+ }
+ }
+ eval $end if $b_log;
+ return $tty;
+}
+sub x_drivers {
+ eval $start if $b_log;
+ my ($driver,@driver_data,,%drivers);
+ my ($failed,$loaded,$sep,$unloaded) = ('','','','');
+ if (my $log = main::system_files('xorg-log')){
+ my @xorg = main::reader($log);
+ # list is from sgfxi plus non-free drivers
+ my $list = 'amdgpu|apm|ark|ati|chips|cirrus|cyrix|fbdev|fglrx|glint|';
+ $list .= 'i128|i740|i810|iftv|imstt|intel|ivtv|mach64|mesa|mga|modesetting|';
+ $list .= 'neomagic|newport|nouveau|nsc|nvidia|nv|openchrome|radeonhd|radeon|';
+ $list .= 'rendition|s3virge|s3|savage|siliconmotion|sisimedia|sisusb|sis|tdfx|';
+ $list .= 'tga|trident|tseng|unichrome|v4l|vboxvideo|vesa|vga|via|vmware|voodoo';
+ # it's much cheaper to grab the simple pattern match then do the expensive one
+ # in the main loop.
+ #@xorg = grep {/Failed|Unload|Loading/} @xorg;
+ foreach (@xorg){
+ next if !/Failed|Unload|Loading/;
+ # note that in file names, driver is always lower case
+ if (/\sLoading.*($list)_drv.so$/i ) {
+ $driver=lc($1);
+ # we get all the actually loaded drivers first, we will use this to compare the
+ # failed/unloaded, which have not always actually been truly loaded
+ $drivers{$driver}="loaded";
+ }
+ # openbsd uses UnloadModule:
+ elsif (/(Unloading\s|UnloadModule).*($list)(_drv.so)?$/i ) {
+ $driver=lc($2);
+ # we get all the actually loaded drivers first, we will use this to compare the
+ # failed/unloaded, which have not always actually been truly loaded
+ $drivers{$driver}="unloaded" ;
+ }
+ # verify that the driver actually started the desktop, even with false failed messages
+ # which can occur. This is the driver that is actually driving the display
+ elsif (/Failed.*($list)\"?(_drv.so)?$/i ) {
+ $driver=lc($1);
+ # we need to make sure that the driver has already been truly loaded, not just
+ # discussed, also set driver to lower case because sometimes it will show as
+ # RADEON or NVIDIA in the actual x start
+ if (exists $drivers{$driver}){
+ $drivers{$driver}="failed";
+ }
+ }
+ }
+ my $sep = '';
+ foreach (sort keys %drivers){
+ if ($drivers{$_} eq 'loaded') {
+ $sep = ($loaded) ? ',' : '';
+ $loaded .= $sep . $_;
+ }
+ elsif ($drivers{$_} eq 'unloaded') {
+ $sep = ($unloaded) ? ',' : '';
+ $unloaded .= $sep . $_;
+ }
+ elsif ($drivers{$_} eq 'failed') {
+ $sep = ($failed) ? ',' : '';
+ $failed .= $sep . $_;
+ }
+ }
+ $loaded ||= 'none';
+ @driver_data = ($loaded,$unloaded,$failed);
+ }
+ eval $end if $b_log;
+ return @driver_data;
+}
+sub x_version {
+ eval $start if $b_log;
+ my ($version,@data,$program);
+ # IMPORTANT: both commands send version data to stderr!
+ if ($program = main::check_program('Xorg')){
+ @data = main::grabber("$program -version 2>&1");
+ }
+ elsif ($program = main::check_program('X')){
+ @data = main::grabber("$program -version 2>&1");
+ }
+ #print Data::Dumper::Dumper \@data;
+ if (@data){
+ foreach (@data){
+ if (/^X.org X server/i){
+ my @working = split /\s+/, $_;
+ $version = $working[3];
+ last;
+ }
+ elsif (/^X Window System Version/i) {
+ my @working = split /\s+/, $_;
+ $version = $working[4];
+ last;
+ }
+ }
+ }
+ eval $end if $b_log;
+ return $version;
+}
+# $1 - protocol: wayland|x11
+sub display_compositor {
+ eval $start if $b_log;
+ my ($protocol) = @_;
+ my ($compositor) = ('');
+ # NOTE: chains of greps of ps data are VERY expensive, so check for program presence
+ if (main::check_program('mutter') && (grep {/mutter/} @ps_cmd ) ) {
+ $compositor = 'mutter';
+ }
+ elsif (main::check_program('kwin') && (grep {/\bkwin\b/} @ps_cmd ) ) {
+ $compositor = 'kwin';
+ }
+ elsif (main::check_program('muffin') && (grep {/muffin/} @ps_cmd ) ) {
+ $compositor = 'muffin';
+ }
+ # Note: other strings have gnome-shell in them, so important to get exact one. Since we
+ # can't fully trust how this will appear, the pattern should tighten it
+ elsif (main::check_program('gnome-shell') && (grep {/^(\/[\S]+\/)?gnome-shell(\s|$)/} @ps_cmd ) ) {
+ $compositor = 'gnome-shell';
+ }
+ elsif (main::check_program('weston') && (grep {/weston/} @ps_cmd ) ) {
+ $compositor = 'weston';
+ }
+ elsif (main::check_program('compton') && (grep {/compton/} @ps_cmd ) ) {
+ $compositor = 'compton';
+ }
+ # owned by: compiz-core in debian
+ elsif (main::check_program('compiz') && (grep {/compiz/} @ps_cmd ) ) {
+ $compositor = 'compiz';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('moblin') && (grep {/moblin/} @ps_cmd ) ) {
+ $compositor = 'moblin';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('kmscon') && (grep {/kmscon/} @ps_cmd ) ) {
+ $compositor = 'kmscon';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('sway') && (grep {/\bsway\b/} @ps_cmd ) ) {
+ $compositor = 'sway';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('grefson') && (grep {/grefson/} @ps_cmd ) ) {
+ $compositor = 'grefson';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('westford') && (grep {/westford/} @ps_cmd ) ) {
+ $compositor = 'westford';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('rustland') && (grep {/rustland/} @ps_cmd ) ) {
+ $compositor = 'rustland';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('ireplace') && (grep {/fireplace/} @ps_cmd ) ) {
+ $compositor = 'fireplace';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('wayhouse') && (grep {/wayhouse/} @ps_cmd ) ) {
+ $compositor = 'wayhouse';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('swc') && (grep {/\bswc\b/} @ps_cmd ) ) {
+ $compositor = 'swc';
+ }
+ # did not find in debian apt
+ elsif (main::check_program('dwc') && (grep {/\bdwc\b/} @ps_cmd ) ) {
+ $compositor = 'dwc';
+ }
+ main::log_data('data',"compositor: $compositor") if $b_log;
+ eval $end if $b_log;
+ return $compositor;
+}
+}
- ## check for all ide type drives, non libata, only do it if hdx is in array
- ## this is now being updated for new /sys type paths, this may handle that ok too
- if [[ -n $( grep -Es 'hd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
- # remember, we're using the last array item to store the total size of disks
- for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
- do
- IFS=","
- a_temp_working=( ${A_HDD_DATA[i]} )
- IFS="$ORIGINAL_IFS"
- if [[ -z ${a_temp_working[0]/*hd[a-z]*/} ]];then
- if [[ -e /proc/ide/${a_temp_working[0]}/model ]];then
- a_temp_working[2]="$( remove_erroneous_chars /proc/ide/${a_temp_working[0]}/model )"
- else
- a_temp_working[2]=''
- fi
- # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
- for (( j=0; j < ${#a_temp_working[@]}; j++ ))
- do
- if [[ $j -gt 0 ]];then
- A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
- else
- A_HDD_DATA[i]="${a_temp_working[$j]}"
- fi
- done
- fi
- done
- fi
-
- ## then handle libata names
- # first get the ata device names, put them into an array
- IFS=$'\n'
- if [[ $B_SCSI_FILE == 'true' ]]; then
- a_temp_scsi=( $( gawk '
- BEGIN {
- IGNORECASE=1
- }
- /host/ {
- getline a[$0]
- getline b[$0]
- }
- END {
- for (i in a) {
- if (b[i] ~ / *type: *direct-access.*/) {
- #c=gensub(/^ *vendor: (.+) +model: (.+) +rev: (.+)$/,"\\1 \\2 \\3","g",a[i])
- #c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/,"\\1 \\2","g",a[i] )
- # the vendor: string is useless, and is a bug, ATA is not a vendor for example
- c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/, "\\2", "g", a[i] )
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", c)
- gsub(/^ +| +$/, "", c)
- gsub(/ [ \t]+/, " ", c)
- #print a[i]
- # we actually want this data, so leaving this off for now
-# if (c ~ /\<flash\>|\<pendrive\>|memory stick|memory card/) {
-# continue
-# }
- print c
- }
- }
- }' $FILE_SCSI ) )
- log_function_data 'cat' "$FILE_SCSI"
- fi
- IFS="$ORIGINAL_IFS"
- ## then we'll loop through that array looking for matches.
- if [[ -n $( grep -Es 'sd[a-z]|nvme' <<< ${A_HDD_DATA[@]} ) ]];then
- # first pack the main ls variable so we don't have to keep using ls /dev...
- # not all systems have /dev/disk/by-id
- ls_disk_by_id="$( ls -l /dev/disk/by-id 2>/dev/null )"
- ls_disk_by_path="$( ls -l /dev/disk/by-path 2>/dev/null )"
- for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
- do
- firmware_rev=''
- hdd_temp=''
- hdd_serial=''
- temp_name=''
- working_path=''
- block_type=''
- if [[ -z ${A_HDD_DATA[$i]/*nvme*/} ]];then
- block_type='nvme'
- elif [[ -z ${A_HDD_DATA[$i]/*sd[a-z]*/} ]];then
- block_type='sdx'
- fi
- if [[ -n $block_type ]];then
- IFS=","
- a_temp_working=( ${A_HDD_DATA[$i]} )
- IFS="$ORIGINAL_IFS"
- if [[ $block_type == 'sdx' ]];then
- working_path=/sys/block/${a_temp_working[0]}/device/
- elif [[ $block_type == 'nvme' ]];then
- # this results in:
- # /sys/devices/pci0000:00/0000:00:03.2/0000:06:00.0/nvme/nvme0/nvme0n1
- # but we want to go one level down so slice off trailing nvme0n1
- working_path=$(readlink -f /sys/block/${a_temp_working[0]} 2>/dev/null )
- working_path=${working_path%nvme*}
- fi
- # /sys/block/[sda,hda]/device/model
- # this is handles the new /sys data types first
- if [[ -e ${working_path}model ]];then
- temp_name="$( remove_erroneous_chars ${working_path}model )"
- temp_name=$( cut -d '-' -f 1 <<< ${temp_name// /_} )
- elif [[ ${#a_temp_scsi[@]} -gt 0 ]];then
- for (( j=0; j < ${#a_temp_scsi[@]}; j++ ))
- do
- ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the
- # discovered disk name AND ends with the correct identifier, sdx
- # get rid of whitespace for some drive names and ids, and extra data after - in name
- temp_name=$( cut -d '-' -f 1 <<< ${a_temp_scsi[$j]// /_} )
- sd_ls_by_id=$( grep -Em1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
- if [[ -n $sd_ls_by_id ]];then
- temp_name=${a_temp_scsi[$j]}
- break
- else
- # test to see if we can get a better name output when null
- if [[ -n $temp_name ]];then
- temp_name=$temp_name
- fi
- fi
- done
- fi
- # I don't know identifier for thunderbolt in /dev/disk/by-id / /dev/disk/by-path
- if [[ -n $temp_name && -n "$ls_disk_by_id" ]];then
- usb_exists=$( grep -Em1 "usb-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
- firewire_exists=$( grep -Em1 "ieee1394-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
- # thunderbolt_exists=$( grep -Em1 "ieee1394-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
- # note: sometimes with wwn- numbering usb does not appear in by-id but it does in by-path
- fi
- if [[ -n "$ls_disk_by_path" ]];then
- if [[ -z $usb_exists ]];then
- usb_exists=$( grep -Em1 "usb-.*${a_temp_working[0]}$" <<< "$ls_disk_by_path" )
- fi
- if [[ -n $usb_exists ]];then
- a_temp_working[3]='USB'
- fi
- if [[ -z $firewire_exists ]];then
- firewire_exists=$( grep -Em1 "ieee1394-.*${a_temp_working[0]}$" <<< "$ls_disk_by_path" )
- fi
- if [[ -n $firewire_exists ]];then
- a_temp_working[3]='FireWire'
- fi
- fi
- a_temp_working[2]=$temp_name
- for (( j=0; j < ${#a_temp_working[@]}; j++ ))
- do
- if [[ $j -gt 0 ]];then
- A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
- else
- A_HDD_DATA[i]="${a_temp_working[$j]}"
- fi
- done
- fi
- if [[ $B_EXTRA_DATA == 'true' ]];then
- IFS=","
- a_temp_working=( ${A_HDD_DATA[i]} )
- # echo "a:" ${a_temp_working[@]}
- IFS="$ORIGINAL_IFS"
-
- if [[ -n ${a_temp_working[1]} ]];then
- hdd_temp=$( get_hdd_temp_data "/dev/${a_temp_working[0]}" )
- fi
- if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- if [[ -e ${working_path}serial ]];then
- hdd_serial="$( remove_erroneous_chars ${working_path}serial )"
- else
- hdd_serial=$( get_hdd_serial_number "${a_temp_working[0]}" )
- fi
- if [[ -e ${working_path}firmware_rev ]];then
- firmware_rev="$( remove_erroneous_chars ${working_path}firmware_rev )"
- fi
- fi
- A_HDD_DATA[i]="${a_temp_working[0]},${a_temp_working[1]},${a_temp_working[2]},${a_temp_working[3]},$hdd_serial,$hdd_temp,$firmware_rev"
- # echo b: ${A_HDD_DATA[i]}
- fi
- done
- fi
- a_temp=${A_HDD_DATA[@]}
- log_function_data "A_HDD_DATA: $a_temp"
- eval $LOGFE
-}
-
-# args: $1 ~ hdd_used
-get_hard_drive_data_bsd()
+## MachineData
{
- eval $LOGFS
-
- local a_temp=''
-
- if [[ -n $DMESG_BOOT_DATA ]];then
- IFS=$'\n'
- A_HDD_DATA=( $( gawk -v hddUsed="$1" -F ':' '
- BEGIN {
- IGNORECASE=1
- size=0
- bSetSize="false"
- }
- $1 ~ /^(ad|ada|mmcblk|nvme[0-9]+n|sd|wd)[0-9]+(|[[:space:]]at.*)$/ {
- diskId=gensub(/^((ad|ada|mmcblk|nvme[0-9]+n|sd|wd)[0-9]+)[^0-9].*/,"\\1",1,$1)
- # note: /var/run/dmesg.boot may repeat items since it is not created
- # fresh every boot, this way, only the last items will be used per disk id
- if (aIds[diskId] == "" ) {
- aIds[diskId]=diskId
- if ( $0 !~ /raid/) {
- bSetSize="true"
- }
- }
- aDisks[diskId, "id"] = diskId
- if ($0 ~ /[^0-9][0-9\.]+[[:space:]]*[MG]B/ && $0 !~ /MB\/s/) {
- workingSize=gensub(/.*[^0-9]([0-9\.]+[[:space:]]*[MG]B).*/,"\\1",1,$0)
- if (workingSize ~ /GB/ ) {
- sub(/[[:space:]]*GB/,"",workingSize)
- workingSize=workingSize*1000
- }
- else if (workingSize ~ /MB/ ) {
- sub(/[[:space:]]*MB/,"",workingSize)
- workingSize=workingSize
- }
- aDisks[diskId, "size"] = workingSize
- if ( bSetSize == "true" ) {
- if ( workingSize != "" ){
- size=size+workingSize
- bSetSize="false"
- }
+package MachineData;
+
+sub get {
+ eval $start if $b_log;
+ my (%arm_machine,@data,@rows,$key1,$val1,$which);
+ my $num = 0;
+ if ($bsd_type || $b_dmidecode_force){
+ my $ref = $alerts{'dmidecode'};
+ if ( $$ref{'action'} ne 'use'){
+ $key1 = $$ref{'action'};
+ $val1 = $$ref{$key1};
+ $key1 = ucfirst($key1);
+ }
+ else {
+ @data = machine_data_dmi();
+ if (!@data && !$key1){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('machine-data','');
+ }
+ }
+ }
+ elsif (-d '/sys/class/dmi/id/') {
+ @data = machine_data_sys();
+ if (!@data){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('machine-data-dmidecode','');
+ }
+ }
+ elsif (!$bsd_type) {
+ # this uses /proc/cpuinfo so only GNU/Linux
+ if ($b_arm){
+ %arm_machine = machine_data_arm();
+ if (%arm_machine){
+ @data = create_output_arm(%arm_machine);
+ }
+ }
+ if (!@data){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('machine-data-alt-33','');
+ }
+ }
+ # if error case, null data, whatever
+ if ($key1) {
+ @data = ({main::key($num++,$key1) => $val1,});
+ }
+ eval $end if $b_log;
+ return @data;
+}
+## keys for machine data are:
+# 0-sys_vendor 1-product_name 2-product_version 3-product_serial 4-product_uuid
+# 5-board_vendor 6-board_name 7-board_version 8-board_serial
+# 9-bios_vendor 10-bios_version 11-bios_date
+## with extra data:
+# 12-chassis_vendor 13-chassis_type 14-chassis_version 15-chassis_serial
+## unused: 16-bios_rev 17-bios_romsize 18 - firmware type
+sub create_output {
+ eval $start if $b_log;
+ my ($ref) = @_;
+ my (%data,@row,@rows);
+ %data = %$ref;
+ my $firmware = 'BIOS';
+ my $num = 0;
+ my $j = 0;
+ my ($b_chassis,$b_skip_chassis,$b_skip_system);
+ my ($bios_date,$bios_rev,$bios_romsize,$bios_vendor,$bios_version,$chassis_serial,
+ $chassis_type,$chassis_vendor,$chassis_version, $mobo_model,$mobo_serial,$mobo_vendor,
+ $mobo_version,$product_name,$product_serial,$product_version,$system_vendor);
+# foreach my $key (keys %data){
+# print "$key: $data{$key}\n";
+# }
+ if (!$data{'sys_vendor'} || ($data{'board_vendor'} &&
+ $data{'sys_vendor'} eq $data{'board_vendor'} && !$data{'product_name'} &&
+ !$data{'product_version'} && !$data{'product_serial'})){
+ $b_skip_system = 1;
+ }
+ # found a case of battery existing but having nothing in it on desktop mobo
+ # not all laptops show the first. /proc/acpi/battery is deprecated.
+ elsif ( !glob('/proc/acpi/battery/*') && !glob('/sys/class/power_supply/*') ){
+ # ibm / ibm can be true; dell / quantum is false, so in other words, only do this
+ # in case where the vendor is the same and the version is the same and not null,
+ # otherwise the version information is going to be different in all cases I think
+ if ( ($data{'sys_vendor'} && $data{'sys_vendor'} eq $data{'board_vendor'} ) &&
+ ( ($data{'product_version'} && $data{'product_version'} eq $data{'board_version'} ) ||
+ (!$data{'product_version'} && $data{'product_name'} eq $data{'board_name'} ) ) ){
+ $b_skip_system = 1;
+ }
+ }
+ $data{'device'} ||= 'N/A';
+ $j = scalar @rows;
+ @row = ({
+ main::key($num++,'Type') => ucfirst($data{'device'}),
+ },);
+ @rows = (@rows,@row);
+ if (!$b_skip_system){
+ # this has already been tested for above so we know it's not null
+ $system_vendor = main::cleaner($data{'sys_vendor'});
+ $product_name = ($data{'product_name'}) ? $data{'product_name'}:'N/A';
+ $product_version = ($data{'product_version'}) ? $data{'product_version'}:'N/A';
+ $product_serial = main::apply_filter($data{'product_serial'});
+ $rows[$j]{main::key($num++,'System')} = $system_vendor;
+ $rows[$j]{main::key($num++,'product')} = $product_name;
+ $rows[$j]{main::key($num++,'v')} = $product_version;
+ $rows[$j]{main::key($num++,'serial')} = $product_serial;
+ # 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'}){
+ $b_skip_chassis = 1;
+ }
+ if (!$b_skip_chassis && $data{'chassis_vendor'} ){
+ if ($data{'chassis_vendor'} ne $data{'sys_vendor'} ){
+ $chassis_vendor = $data{'chassis_vendor'};
+ }
+ if ($data{'chassis_type'} ){
+ $chassis_type = $data{'chassis_type'};
+ }
+ if ($data{'chassis_version'}){
+ $chassis_version = $data{'chassis_version'}
+ }
+ $chassis_serial = main::apply_filter($data{'chassis_serial'});
+ $chassis_vendor ||= '';
+ $chassis_type ||= '';
+ $rows[$j]{main::key($num++,'Chassis')} = $chassis_vendor;
+ if ($chassis_type){
+ $rows[$j]{main::key($num++,'type')} = $chassis_type;
}
+ if ($chassis_version){
+ $rows[$j]{main::key($num++,'v')} = $chassis_version;
+ }
+ $rows[$j]{main::key($num++,'serial')} = $chassis_serial;
}
- if ( $NF ~ /<.*>/ ){
- gsub(/.*<|>.*/,"",$NF)
- aDisks[diskId, "model"] = $NF
+ }
+ $j++; # start new row
+ }
+ if ($data{'firmware'}){
+ $firmware = $data{'firmware'};
+ }
+ $mobo_vendor = ($data{'board_vendor'}) ? main::cleaner($data{'board_vendor'}) : 'N/A';
+ $mobo_model = ($data{'board_name'}) ? $data{'board_name'}: 'N/A';
+ $mobo_version = ($data{'board_version'})? $data{'board_version'} : '';
+ $mobo_serial = main::apply_filter($data{'board_serial'});
+ $bios_vendor = ($data{'bios_vendor'}) ? main::cleaner($data{'bios_vendor'}) : 'N/A';
+ if ($data{'bios_version'}){
+ $bios_version = $data{'bios_version'};
+ if ($data{'bios_rev'}){
+ $bios_rev = $data{'bios_rev'};
+ }
+ $bios_version ||= 'N/A';
+ }
+ if ($data{'bios_date'}){
+ $bios_date = $data{'bios_date'};
+ }
+ if ($extra > 1 && $data{'bios_romsize'}){
+ $bios_romsize = $data{'bios_romsize'};
+ }
+ $rows[$j]{main::key($num++,'Mobo')} = $mobo_vendor;
+ $rows[$j]{main::key($num++,'model')} = $mobo_model;
+ if ($mobo_version){
+ $rows[$j]{main::key($num++,'v')} = $mobo_version;
+ }
+ $rows[$j]{main::key($num++,'serial')} = $mobo_serial;
+ $rows[$j]{main::key($num++,$firmware)} = $bios_vendor;
+ $rows[$j]{main::key($num++,'v')} = $bios_version;
+ if ($bios_rev){
+ $rows[$j]{main::key($num++,'rev')} = $bios_rev;
+ }
+ $rows[$j]{main::key($num++,'date')} = $bios_date;
+ if ($bios_romsize){
+ $rows[$j]{main::key($num++,'rom size')} = $bios_romsize;
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+sub create_output_arm {
+ my (%data,@row,@rows);
+ my (%arm_machine) = @_;
+ my $num = 0;
+ my $j = 0;
+ #print Data::Dumper::Dumper \%arm_machine;
+ if ($arm_machine{'device'}){
+ my $device = main::cleaner( $arm_machine{'device'} );
+ $device ||= 'N/A';
+ $rows[$j]{main::key($num++,'Type')} = 'ARM Device';
+ $rows[$j]{main::key($num++,'System')} = $device;
+ }
+ # we're going to print N/A for 0000 values sine the item was there.
+ if ($arm_machine{'firmware'}){
+ # most samples I've seen are like: 0000
+ $arm_machine{'firmware'} =~ s/^[0]+$//;
+ $arm_machine{'firmware'} ||= 'N/A';
+ $rows[$j]{main::key($num++,'rev')} = $arm_machine{'firmware'};
+ }
+ # sometimes has value like: 0000
+ if (defined $arm_machine{'serial'}){
+ # most samples I've seen are like: 0000
+ $arm_machine{'serial'} =~ s/^[0]+$//;
+ $rows[$j]{main::key($num++,'serial')} = main::apply_filter($arm_machine{'serial'});
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+
+sub machine_data_sys {
+ eval $start if $b_log;
+ my (%data,$path,$vm);
+ my $sys_dir = '/sys/class/dmi/id/';
+ my $sys_dir_alt = '/sys/devices/virtual/dmi/id/';
+ my @sys_files = qw(bios_vendor bios_version bios_date
+ board_name board_serial board_vendor board_version chassis_type
+ product_name product_serial product_uuid product_version sys_vendor
+ );
+ if ($extra > 1){
+ splice @sys_files, 0, 0, qw( chassis_serial chassis_vendor chassis_version);
+ }
+ $data{'firmware'} = 'BIOS';
+ # print Data::Dumper::Dumper \@sys_files;
+ if (!-d $sys_dir ){
+ if ( -d $sys_dir_alt){
+ $sys_dir = $sys_dir_alt;
+ }
+ else {
+ return 0;
+ }
+ }
+ if ( -d '/sys/firmware/efi'){
+ $data{'firmware'} = 'UEFI';
+ }
+ elsif ( glob('/sys/firmware/acpi/tables/UEFI*') ){
+ $data{'firmware'} = 'UEFI [Legacy]';
+ }
+ foreach (@sys_files){
+ $path = "$sys_dir$_";
+ if (-r $path){
+ $data{$_} = (main::reader($path))[0];
+ $data{$_} = ($data{$_}) ? main::dmi_cleaner($data{$_}) : '';
+ }
+ else {
+ $data{$_} = '';
+ }
+ }
+ if ($data{'chassis_type'}){
+ if ( $data{'chassis_type'} == 1){
+ $data{'device'} = get_device_vm($data{'sys_vendor'},$data{'product_name'});
+ $data{'device'} ||= 'other-vm?';
+ }
+ else {
+ $data{'device'} = get_device_sys($data{'chassis_type'});
+ }
+ }
+# print "sys:\n";
+# foreach (keys %data){
+# print "$_: $data{$_}\n";
+# }
+ main::log_data('dump','%data',\%data) if $b_log;
+ my @rows = create_output(\%data);
+ eval $end if $b_log;
+ return @rows;
+}
+# this will create an alternate machine data source
+# which will be used for alt ARM machine data in cases
+# where no dmi data present, or by cpu data to guess at
+# certain actions for arm only.
+sub machine_data_arm {
+ eval $end if $b_log;
+ my (%arm_machine,@temp);
+ if (my $file = main::system_files('cpuinfo')){
+ #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-shevaplug-1.2ghz.txt";
+ my @data = main::reader($file);
+ foreach (@data){
+ if (/^Hardware/i){
+ @temp = split /\s*:\s*/, $_;
+ $arm_machine{'device'} = $temp[1];
}
- if ( $NF ~ /serial number/ ){
- sub(/serial[[:space:]]+number[[:space:]]*/,"",$NF)
- aDisks[diskId, "serial"] = $NF
+ elsif (/^Revision/i){
+ @temp = split /\s*:\s*/, $_;
+ $arm_machine{'firmware'} = $temp[1];
+ }
+ elsif (/^Serial/i){
+ @temp = split /\s*:\s*/, $_;
+ $arm_machine{'serial'} = $temp[1];
}
}
- END {
- # sde,3.9GB,STORE_N_GO,USB,C200431546D3CF49-0:0,0
- # sdd,250.1GB,ST3250824AS,,9ND08GKX,45
- # multi dimensional pseudo arrays are sorted at total random, not in order of
- # creation, so force a sort of the aIds, which deletes the array index but preserves
- # the sorted keys.
- asort(aIds)
-
- for ( key in aIds ) {
- # we are not adding to size above for raid, and we do not print it for raid
- # this is re openbsd raid, which uses sd0 for raid array, even though sd is for scsi
- if ( aDisks[aIds[key], "model"] !~ /raid/ ) {
- workingSize = aDisks[aIds[key], "size"]/1000
- workingSize = sprintf( "%.1fGB", workingSize )
- print aDisks[aIds[key], "id"] "," workingSize "," aDisks[aIds[key], "model"] "," "," aDisks[aIds[key], "serial"] ",,"
- }
- }
- size = size/1000 # calculate size in GB size
- # in kb
- workingUsed = hddUsed*1024/1000**3 # calculate workingUsed in GB used
- # this handles a special case with livecds where no hdd_used is detected
- if ( size > 0 && hddUsed == "na" ) {
- size = sprintf( "%.1f", size )
- print size "GB,-,,.."
- }
- else if ( size > 0 && workingUsed > 0 ) {
- diskUsed = workingUsed*100/size # calculate used percentage
- diskUsed = sprintf( "%.1f", diskUsed )
- if ( int(diskUsed) > 100 ) {
- diskUsed = "Used Error!"
+ }
+ #print Data::Dumper::Dumper \%arm_machine;
+ eval $end if $b_log;
+ return %arm_machine;
+}
+
+# bios_date: 09/07/2010
+# bios_romsize: dmi only
+# bios_vendor: American Megatrends Inc.
+# bios_version: P1.70
+# bios_rev: 8.14: dmi only
+# board_name: A770DE+
+# board_serial:
+# board_vendor: ASRock
+# board_version:
+# chassis_serial:
+# chassis_type: 3
+# chassis_vendor:
+# chassis_version:
+# firmware:
+# product_name:
+# product_serial:
+# product_uuid:
+# product_version:
+# sys_uuid: dmi only
+# sys_vendor:
+sub machine_data_dmi {
+ eval $start if $b_log;
+ my (%data,$vm);
+ return if ! @dmi;
+ $data{'firmware'} = 'BIOS';
+ # dmi types:
+ # 0 bios; 1 system info; 2 board|base board info; 3 chassis info;
+ # 4 processor info, use to check for hypervisor
+ foreach (@dmi){
+ my @ref = @$_;
+ # bios/firmware
+ if ($ref[0] == 0){
+ # skip first three row, we don't need that data
+ splice @ref, 0, 3 if @ref;
+ foreach my $item (@ref){
+ if ($item !~ /^~/){ # skip the indented rows
+ my @value = split /:\s+/, $item;
+ if ($value[0] eq 'Release Date') {$data{'bios_date'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Vendor') {$data{'bios_vendor'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Version') {$data{'bios_version'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'ROM Size') {$data{'bios_romsize'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'BIOS Revision') {$data{'bios_rev'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] =~ /^UEFI is supported/) {$data{'firmware'} = 'UEFI';}
}
- else {
- diskUsed = diskUsed "% used"
+ }
+ next;
+ }
+ # system information
+ elsif ($ref[0] == 1){
+ # skip first three row, we don't need that data
+ splice @ref, 0, 3 if @ref;
+ foreach my $item (@ref){
+ if ($item !~ /^~/){ # skip the indented rows
+ my @value = split /:\s+/, $item;
+ if ($value[0] eq 'Product Name') {$data{'product_name'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Version') {$data{'product_version'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Serial Number') {$data{'product_serial'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Manufacturer') {$data{'sys_vendor'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'UUID') {$data{'sys_uuid'} = main::dmi_cleaner($value[1]) }
}
- size = sprintf( "%.1f", size )
- print size "GB," diskUsed ",,.."
}
- else {
- print "NA,-,,.." # print an empty array, this will be further handled in the print out function
+ next;
+ }
+ # baseboard information
+ elsif ($ref[0] == 2){
+ # skip first three row, we don't need that data
+ splice @ref, 0, 3 if @ref;
+ foreach my $item (@ref){
+ if ($item !~ /^~/){ # skip the indented rows
+ my @value = split /:\s+/, $item;
+ if ($value[0] eq 'Product Name') {$data{'board_name'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Serial Number') {$data{'board_serial'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Manufacturer') {$data{'board_vendor'} = main::dmi_cleaner($value[1]) }
+ }
}
- }' <<< "$DMESG_BOOT_DATA" ) )
- IFS="$ORIGINAL_IFS"
- fi
-
- a_temp=${A_HDD_DATA[@]}
- # echo ${a_temp[@]}
- log_function_data "A_HDD_DATA: $a_temp"
-
- eval $LOGFE
+ next;
+ }
+ # chassis information
+ elsif ($ref[0] == 3){
+ # skip first three row, we don't need that data
+ splice @ref, 0, 3 if @ref;
+ foreach my $item (@ref){
+ if ($item !~ /^~/){ # skip the indented rows
+ my @value = split /:\s+/, $item;
+ if ($value[0] eq 'Serial Number') {$data{'chassis_serial'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Type') {$data{'chassis_type'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Manufacturer') {$data{'chassis_vendor'} = main::dmi_cleaner($value[1]) }
+ elsif ($value[0] eq 'Version') {$data{'chassis_version'} = main::dmi_cleaner($value[1]) }
+ }
+ }
+ if ( $data{'chassis_type'} && $data{'chassis_type'} ne 'Other' ){
+ $data{'device'} = $data{'chassis_type'};
+ }
+ next;
+ }
+ # this may catch some BSD and fringe Linux cases
+ # processor information: check for hypervisor
+ elsif ($ref[0] == 4){
+ # skip first three row, we don't need that data
+ splice @ref, 0, 3 if @ref;
+ if (!$data{'device'}){
+ if (grep {/hypervisor/i} @ref){
+ $data{'device'} = 'virtual-machine';
+ }
+ }
+ last;
+ }
+ elsif ($ref[0] > 4){
+ last;
+ }
+ }
+ if (!$data{'device'}){
+ $data{'device'} = get_device_vm($data{'sys_vendor'},$data{'product_name'});
+ $data{'device'} ||= 'other-vm?';
+ }
+# print "dmi:\n";
+# foreach (keys %data){
+# print "$_: $data{$_}\n";
+# }
+ main::log_data('dump','%data',\%data) if $b_log;
+ my @rows = create_output(\%data);
+ eval $end if $b_log;
+ return @rows;
}
-# args: $1 - which drive to get serial number of
-get_hdd_serial_number()
-{
- eval $LOGFS
-
- local hdd_serial=''
-
- get_partition_dev_data 'id'
-
- # lrwxrwxrwx 1 root root 9 Apr 26 09:32 scsi-SATA_ST3160827AS_5MT2HMH6 -> ../../sdc
- # exception: ata-InnoDisk_Corp._-_mSATA_3ME3_BCA34401050060191 -> ../../sda
- # exit on the first instance
- hdd_serial=$( gawk '
- /'$1'$/ {
- serial=gensub( /(.+)_([^_]+)$/, "\\2", 1, $9 )
- print serial
- exit
- }' <<< "$DEV_DISK_ID" )
-
- echo $hdd_serial
- log_function_data "hdd serial: $hdd_serial"
- eval $LOGFE
+sub get_device_sys {
+ eval $start if $b_log;
+ my ($chasis_id) = @_;
+ my ($device) = ('');
+ my @chassis;
+ # https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.8.0.pdf
+ $chassis[2] = 'unknown';
+ # note: 13 is all-in-one which we take as a mac type system
+ $chassis[3] = 'desktop';
+ $chassis[4] = 'desktop';
+ $chassis[6] = 'desktop';
+ $chassis[7] = 'desktop';
+ $chassis[13] = 'desktop';
+ $chassis[15] = 'desktop';
+ $chassis[24] = 'desktop';
+ # 5 - pizza box was a 1 U desktop enclosure, but some old laptops also id this way
+ $chassis[5] = 'pizza-box';
+ $chassis[9] = 'laptop';
+ # note: lenovo T420 shows as 10, notebook, but it's not a notebook
+ $chassis[10] = 'laptop';
+ $chassis[16] = 'laptop';
+ $chassis[14] = 'notebook';
+ $chassis[8] = 'portable';
+ $chassis[11] = 'portable';
+ $chassis[17] = 'server';
+ $chassis[23] = 'server';
+ $chassis[25] = 'server';
+ $chassis[27] = 'blade';
+ $chassis[25] = 'blade';
+ $chassis[29] = 'blade';
+ $chassis[12] = 'docking-station';
+ $chassis[18] = 'expansion-chassis';
+ $chassis[19] = 'sub-chassis';
+ $chassis[20] = 'bus-expansion';
+ $chassis[21] = 'peripheral';
+ $chassis[22] = 'RAID';
+ $chassis[26] = 'compact-PCI';
+ $device = $chassis[$chasis_id] if $chassis[$chasis_id];
+ eval $end if $b_log;
+ return $device;
}
-# a few notes, normally hddtemp requires root, but you can set user rights in /etc/sudoers.
-# args: $1 - /dev/<disk> to be tested for
-get_hdd_temp_data()
-{
- eval $LOGFS
- local hdd_temp='' sudo_command='' device=$1
-
- if [[ $B_SUDO_TESTED != 'true' ]];then
- B_SUDO_TESTED='true'
- SUDO_PATH=$( type -p sudo )
- fi
- # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
- # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
- # important: -n makes it non interactive, no prompt for password
- if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
- sudo_command='sudo -n '
- fi
- # try this to see if hddtemp gives result for the base name
- if [[ -z ${device/*nvme*/} ]];then
- if type -p nvme &>/dev/null;then
- device=${device%n[0-9]}
- # this will fail if regular user and no sudo present, but that's fine, it will just return null
- hdd_temp=$( eval $sudo_command nvme smart-log $device 2>/dev/null | gawk -F ':' '
- BEGIN {
- IGNORECASE=1
- }
- # other rows may have: Temperature sensor 1 :
- /^temperature\s*:/ {
- gsub(/^[[:space:]]+|[[:space:]]*C$/,"",$2)
- print $2
- }' )
- fi
- else
- if [[ $B_HDDTEMP_TESTED != 'true' ]];then
- B_HDDTEMP_TESTED='true'
- HDDTEMP_PATH=$( type -p hddtemp )
- fi
- if [[ -n $HDDTEMP_PATH && -n $device ]];then
- # this will fail if regular user and no sudo present, but that's fine, it will just return null
- hdd_temp=$( eval $sudo_command $HDDTEMP_PATH -nq -u C $device )
- fi
- fi
- if [[ -n $hdd_temp && -z ${hdd_temp//[0-9]/} ]];then
- echo $hdd_temp
- fi
- eval $LOGFE
-}
-
-get_init_data()
-{
- eval $LOGFS
-
- local init_type='' init_version='' rc_type='' rc_version='' a_temp=''
- local ls_run='' strings_init_version=''
- local runlevel=$( get_runlevel_data )
- local default_runlevel=$( get_runlevel_default )
-
- # this test is pretty solid, if pid 1 is owned by systemd, it is systemd
- # otherwise that is 'init', which covers the rest of the init systems, I think anyway.
- # more data may be needed for other init systems.
- if [[ -e /proc/1/comm && -n $( grep -s 'systemd' /proc/1/comm ) ]];then
- init_type='systemd'
- if type -p systemd &>/dev/null;then
- init_version=$( get_program_version 'systemd' '^systemd' '2' )
- fi
- if [[ -z $init_version ]];then
- if type -p systemctl &>/dev/null;then
- init_version=$( get_program_version 'systemctl' '^systemd' '2' )
- fi
- fi
- else
- ls_run=$(ls /run)
- # note: upstart-file-bridge.pid upstart-socket-bridge.pid upstart-udev-bridge.pid
- if [[ -n $( /sbin/init --version 2>/dev/null | grep 'upstart' ) ]];then
- init_type='Upstart'
- # /sbin/init --version == init (upstart 1.12.1)
- init_version=$( get_program_version 'init' 'upstart' '3' )
- elif [[ -e /proc/1/comm && -n $( grep -s 'epoch' /proc/1/comm ) ]];then
- init_type='Epoch'
- # epoch version == Epoch Init System 1.0.1 "Sage"
- init_version=$( get_program_version 'epoch' '^Epoch' '4' )
- # missing data: note, runit can install as a dependency without being the init system
- # http://smarden.org/runit/sv.8.html
- # NOTE: the proc test won't work on bsds, so if runit is used on bsds we will need more data
- elif [[ -e /proc/1/comm && -n $( grep -s 'runit' /proc/1/comm ) ]];then
- # elif [[ -e /sbin/runit-init || -e /etc/runit || -n $( type -p sv ) ]];then
- init_type='runit' # lower case
- # no data on version yet
- # freebsd at least
- elif type -p launchctl &>/dev/null;then
- init_type='launchd'
- # / launchd/ version.plist /etc/launchd.conf
- # init_version=$( get_program_version 'Launchd' '^Launchd' '4' )
- elif [[ -f /etc/inittab ]];then
- init_type='SysVinit'
- if type -p strings &>/dev/null;then
- strings_init_version="$( strings /sbin/init | grep -E 'version[[:space:]]+[0-9]' )"
- fi
- if [[ -n $strings_init_version ]];then
- init_version=$( gawk '{print $2}' <<< "$strings_init_version" )
- fi
- elif [[ -f /etc/ttys ]];then
- init_type='init (bsd)'
- fi
- if [[ -n $( grep 'openrc' <<< "$ls_run" ) ]];then
- rc_type='OpenRC'
- # /sbin/openrc --version == openrc (OpenRC) 0.13
- if type -p openrc &>/dev/null;then
- rc_version=$( get_program_version 'openrc' '^openrc' '3' )
- # /sbin/rc --version == rc (OpenRC) 0.11.8 (Gentoo Linux)
- elif type -p rc &>/dev/null;then
- rc_version=$( get_program_version 'rc' '^rc' '3' )
- fi
- if [[ -e /run/openrc/softlevel ]];then
- runlevel=$( cat /run/openrc/softlevel 2>/dev/null )
- elif [[ -e /var/run/openrc/softlevel ]];then
- runlevel=$( cat /var/run/openrc/softlevel 2>/dev/null )
- elif type -p rc-status &>/dev/null;then
- runlevel=$( rc-status -r 2>/dev/null )
- fi
- ## assume sysvrc, but this data is too buggy and weird and inconsistent to have meaning
- # leaving this off for now
-# elif [[ -f /etc/inittab ]];then
-# rc_type='SysVrc'
-# # this is a guess that rc and init are same versions, may need updates / fixes
-# rc_version=$init_version
- fi
- fi
- IFS=$'\n'
-
- A_INIT_DATA=(
- "$init_type"
- "$init_version"
- "$rc_type"
- "$rc_version"
- "$runlevel"
- "$default_runlevel" )
-
- IFS="$ORIGINAL_IFS"
-
- a_temp=${A_INIT_DATA[@]}
- log_function_data "A_INIT_DATA: $a_temp"
-
- eval $LOGFE
+sub get_device_vm {
+ eval $start if $b_log;
+ my ($manufacturer,$product_name) = @_;
+ my $vm;
+ if ( my $program = main::check_program('systemd-detect-virt') ){
+ my $vm_test = (main::grabber("$program 2>/dev/null"))[0];
+ if ($vm_test){
+ # kvm vbox reports as oracle, usually, unless they change it
+ if (lc($vm_test) eq 'oracle'){
+ $vm = 'virtualbox';
+ }
+ elsif ( $vm_test ne 'none'){
+ $vm = $vm_test;
+ }
+ }
+ }
+ if (!$vm || lc($vm) eq 'bochs') {
+ if (-e '/proc/vz'){$vm = 'openvz'}
+ elsif (-e '/proc/xen'){$vm = 'xen'}
+ elsif (-e '/dev/vzfs'){$vm = 'virtuozzo'}
+ elsif (my $program = main::check_program('lsmod')){
+ my @vm_data = main::grabber("$program 2>/dev/null");
+ if (@vm_data){
+ if (grep {/kqemu/i} @vm_data){$vm = 'kqemu'}
+ elsif (grep {/kvm/i} @vm_data){$vm = 'kvm'}
+ elsif (grep {/qemu/i} @vm_data){$vm = 'qemu'}
+ }
+ }
+ }
+ # this will catch many Linux systems and some BSDs
+ if (!$vm || lc($vm) eq 'bochs' ) {
+ my @vm_data = (@pci,@sysctl,@dmesg_boot);
+ if (-e '/dev/disk/by-id'){
+ my @dev = glob('/dev/disk/by-id/*');
+ @vm_data = (@vm_data,@dev);
+ }
+ if ( grep {/innotek|vbox|virtualbox/i} @vm_data){
+ $vm = 'virtualbox';
+ }
+ elsif (grep {/vmware/i} @vm_data){
+ $vm = 'vmware';
+ }
+ elsif (grep {/Virtual HD/i} @vm_data){
+ $vm = 'hyper-v';
+ }
+ if (!$vm && (my $file = main::system_files('cpuinfo'))){
+ my @info = main::reader($file);
+ $vm = 'virtual-machine' if grep {/^flags.*hypervisor/} @info;
+ }
+ if (!$vm && -e '/dev/vda' || -e '/dev/vdb' || -e '/dev/xvda' || -e '/dev/xvdb' ){
+ $vm = 'virtual-machine';
+ }
+ }
+ if (!$vm && $product_name){
+ if ($product_name eq 'VMware'){
+ $vm = 'vmware';
+ }
+ elsif ($product_name eq 'VirtualBox'){
+ $vm = 'virtualbox';
+ }
+ elsif ($product_name eq 'KVM'){
+ $vm = 'kvm';
+ }
+ elsif ($product_name eq 'Bochs'){
+ $vm = 'qemu';
+ }
+ }
+ if (!$vm && $manufacturer && $manufacturer eq 'Xen'){
+ $vm = 'xen';
+ }
+ eval $end if $b_log;
+ return $vm;
}
-get_kernel_compiler_version()
-{
- # note that we use gawk to get the last part because beta, alpha, git versions can be non-numeric
- local compiler_version='' compiler_type=''
-
- if [[ -e /proc/version ]];then
- compiler_version=$( grep -Eio 'gcc[[:space:]]*version[[:space:]]*([^ \t]*)' /proc/version 2>/dev/null | gawk '{print $3}' )
- if [[ -n $compiler_version ]];then
- compiler_type='gcc'
- fi
- else
- if [[ $BSD_VERSION == 'darwin' ]];then
- if type -p gcc &>/dev/null;then
- compiler_version=$( get_program_version 'gcc' 'Apple[[:space:]]LLVM' '4' )
- if [[ -n $compiler_version ]];then
- compiler_type='LLVM-GCC'
- fi
- fi
- else
- if [[ -f /etc/src.conf ]];then
- compiler_type=$( grep '^CC' /etc/src.conf | cut -d '=' -f 2 )
- elif [[ -f /etc/make.conf ]];then
- compiler_type=$( grep '^CC' /etc/make.conf | cut -d '=' -f 2 )
- fi
- if [[ -n $compiler_type ]];then
- if type -p $compiler_type &>/dev/null;then
- if [[ $compiler_type == 'gcc' ]];then
- compiler_version=$( get_program_version 'gcc' '^gcc' '3' )
- elif [[ $compiler_type == 'clang' ]];then
- # FreeBSD clang version 3.0 (tags/RELEASE_30/final 145349) 20111210
- compiler_version=$( get_program_version 'clang' 'clang' '4' )
- fi
- fi
- fi
- fi
- fi
- if [[ -n $compiler_version ]];then
- compiler_version="$compiler_type^$compiler_version"
- fi
- echo $compiler_version
-}
-
-get_kernel_version()
-{
- eval $LOGFS
-
- local kernel_version='' ksplice_kernel_version=''
-
- kernel_version=$( uname -rm )
- if [[ $BSD_VERSION == 'darwin' ]];then
- kernel_version="Darwin $kernel_version"
- fi
- if [[ -n $( type -p uptrack-uname ) && -n $kernel_version ]];then
- ksplice_kernel_version=$( uptrack-uname -rm )
- if [[ $kernel_version != $ksplice_kernel_version ]];then
- kernel_version="$ksplice_kernel_version (ksplice)"
- fi
- fi
- log_function_data "kernel_version: $kernel_version - ksplice_kernel_version: $ksplice_kernel_version"
-
- CURRENT_KERNEL=$kernel_version
-
- eval $LOGFE
}
-get_machine_data()
+## NetworkData
{
- eval $LOGFS
- local a_temp='' separator='' id_file='' file_data='' array_string=''
- local id_dir='/sys/class/dmi/id/' dmi_data='' firmware_type='BIOS'
- local machine_files="
- sys_vendor product_name product_version product_serial product_uuid
- board_vendor board_name board_version board_serial
- bios_vendor bios_version bios_date
- "
- if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- machine_files="$machine_files
- chassis_vendor chassis_type chassis_version chassis_serial
- "
- fi
- if [[ -d $id_dir && $B_FORCE_DMIDECODE == 'false' ]];then
- if [[ -d /sys/firmware/efi ]];then
- firmware_type='UEFI'
- elif [[ -n $(ls /sys/firmware/acpi/tables/UEFI* 2>/dev/null ) ]];then
- firmware_type='UEFI [Legacy]'
- fi
- for id_file in $machine_files
- do
- file_data=''
- if [[ -r $id_dir$id_file ]];then
- file_data=$( gawk '
- BEGIN {
- IGNORECASE=1
+package NetworkData;
+my ($b_ip_run,@ifs_found);
+sub get {
+ eval $start if $b_log;
+ my (@data,@rows);
+ my $num = 0;
+ if ($b_arm){
+ my $key = 'ARM';
+ @data = ({
+ main::key($num++,$key) => main::row_defaults('arm-pci',''),
+ },);
+ @rows = (@rows,@data);
+ }
+ else {
+ @data = card_data();
+ @rows = (@rows,@data) if @data;
+ @data = usb_data();
+ @rows = (@rows,@data) if @data;
+ }
+ if ($show{'network-advanced'}){
+ # @ifs_found = ();
+ # shift @ifs_found;
+ # pop @ifs_found;
+ if (!$bsd_type){
+ @data = advanced_data_sys('check','',0,'','');
+ @rows = (@rows,@data) if @data;
+ }
+ else {
+ @data = advanced_data_bsd('check');
+ @rows = (@rows,@data) if @data;
+ }
+ }
+ if ($show{'ip'}){
+ @data = wan_ip();
+ @rows = (@rows,@data);
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+# 1 type_id
+# 2 bus_id
+# 3 sub_id
+# 4 device
+# 5 vendor_id
+# 6 chip_id
+# 7 rev
+# 8 port
+# 9 driver
+# 10 modules
+# 11 driver nu (bsds)
+sub card_data {
+ eval $start if $b_log;
+ my ($b_wifi,@rows,@data,%holder);
+ my ($j,$num) = (0,1);
+ foreach (@pci){
+ $num = 1;
+ my @row = @$_;
+ #print "$row[0] $row[3]\n";
+ if ($row[0] eq 'network' || $row[0] eq 'ethernet' ){
+ #print "$row[0] $row[3]\n";
+ $j = scalar @rows;
+ my $driver = $row[9];
+ my $chip_id = "$row[5]:$row[6]";
+ # working around a virtuo bug same chip id is used on two nics
+ if (!defined $holder{$chip_id}){
+ $holder{$chip_id} = 0;
+ }
+ else {
+ $holder{$chip_id}++;
+ }
+ # 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';
+ $driver ||= 'N/A';
+ @data = (
+ {
+ main::key($num++,'Card') => $card,
+ main::key($num++,'driver') => $driver,
+ },
+ );
+ @rows = (@rows,@data);
+ if ($extra > 0){
+ if ($row[9] && !$bsd_type){
+ my $version = main::get_module_version($row[9]);
+ $version ||= 'N/A';
+ $rows[$j]{main::key($num++,'v')} = $version;
}
- {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
- # yes, there is a typo in a user data set, unknow
- # Base Board Version|Base Board Serial Number
- # Chassis Manufacturer|Chassis Version|Chassis Serial Number
- # System manufacturer|System Product Name|System Version
- # To Be Filled By O.E.M.
- sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|Default string|none|^To be filled.*/, "", $0)
- gsub(/\ybios\y|\yacpi\y/, "", $0) # note: biostar
- sub(/http:\/\/www.abit.com.tw\//, "Abit", $0)
- gsub(/^ +| +$/, "", $0)
- gsub(/ [ \t]+/, " ", $0)
- print $0
- }' < $id_dir$id_file )
- fi
- array_string="$array_string$separator$file_data"
- separator=','
- done
- if [[ $array_string != '' ]];then
- # note: dmidecode has two more data types possible, so always add 2 more
- if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
- array_string="$array_string,,"
- else
- array_string="$array_string,,,,,,"
- fi
- array_string="$array_string,$firmware_type"
- fi
- else
- set_dmidecode_data
- if [[ -n $DMIDECODE_DATA ]];then
- if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
- array_string=$DMIDECODE_DATA
- # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
- else
- array_string=$( gawk -F ':' '
- BEGIN {
- IGNORECASE=1
- baseboardManufacturer=""
- baseboardProductName=""
- baseboardSerialNumber=""
- baseboardVersion=""
- chassisManufacturer=""
- chassisSerialNumber=""
- chassisType=""
- chassisVersion=""
- firmwareReleaseDate=""
- firmwareRevision="" # only available from dmidecode
- firmwareRomSize="" # only available from dmidecode
- firmwareType="BIOS"
- firmwareVendor=""
- firmwareVersion=""
- systemManufacturer=""
- systemProductName=""
- systemVersion=""
- systemSerialNumber=""
- systemUuid=""
- bItemFound="" # we will only output if at least one item was found
- fullString=""
- testString=""
- bSys=""
- bCha=""
- bBio=""
- bBas=""
- }
- /^Bios Information/ {
- while ( getline && !/^$/ ) {
- if ( $1 ~ /^Release Date/ ) { firmwareReleaseDate=$2 }
- if ( $1 ~ /^BIOS Revision/ ) { firmwareRevision=$2 }
- if ( $1 ~ /^ROM Size/ ) { firmwareRomSize=$2 }
- if ( $1 ~ /^Vendor/ ) { firmwareVendor=$2 }
- if ( $1 ~ /^Version/ ) { firmwareVersion=$2 }
- if ( $1 ~ /^UEFI is supported/ ) { firmwareType="UEFI" }
- }
- testString=firmwareReleaseDate firmwareRevision firmwareRomSize firmwareVendor firmwareVersion
- if ( testString != "" ) {
- bItemFound="true"
- }
- bBio="true"
+ $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++,'port')} = $row[8] if (!$b_wifi || ( $b_wifi && $row[8] ne 'N/A') );
+ $rows[$j]{main::key($num++,'bus ID')} = $row[2] . '.' . $row[3];
+ }
+ if ($extra > 1){
+ $rows[$j]{main::key($num++,'chip ID')} = $chip_id;
+ }
+ if ($show{'network-advanced'}){
+ if (!$bsd_type){
+ @data = advanced_data_sys($row[5],$row[6],$holder{$chip_id},$b_wifi,'');
}
- /^Base Board Information/ {
- while ( getline && !/^$/ ) {
- if ( $1 ~ /^Manufacturer/ ) { baseboardManufacturer=$2 }
- if ( $1 ~ /^Product Name/ ) { baseboardProductName=$2 }
- if ( $1 ~ /^Serial Number/ ) { baseboardSerialNumber=$2 }
- }
- testString=baseboardManufacturer baseboardProductName baseboardSerialNumber
- if ( testString != "" ) {
- bItemFound="true"
- }
- bBas="true"
- }
- /^Chassis Information/ {
- while ( getline && !/^$/ ) {
- if ( $1 ~ /^Manufacturer/ ) { chassisManufacturer=$2 }
- if ( $1 ~ /^Serial Number/ ) { chassisSerialNumber=$2 }
- if ( $1 ~ /^Type/ ) { chassisType=$2 }
- if ( $1 ~ /^Version/ ) { chassisVersion=$2 }
+ else {
+ @data = advanced_data_bsd("$row[9]$row[11]",$b_wifi);
+ }
+ @rows = (@rows,@data);
+ }
+ }
+ #print "$row[0]\n";
+ }
+ # @rows = ();
+ if (!@rows){
+ my $key = 'Message';
+ @data = ({
+ main::key($num++,$key) => main::row_defaults('pci-card-data',''),
+ },);
+ @rows = (@rows,@data);
+
+ }
+ #my $ref = $pci[-1];
+ #print $$ref[0],"\n";
+ eval $end if $b_log;
+ return @rows;
+}
+sub usb_data {
+ eval $start if $b_log;
+ my (@data,@rows,@temp2,$b_wifi,$driver,$path,$product,$product2,$test,$vendor,$vendor2);
+ my ($j,$num) = (0,1);
+ return if !@usb;
+ foreach my $ref (@usb){
+ my @row = @$ref;
+ # a device will always be the second or > device on the bus
+ if ($row[1] > 1){
+ $num = 1;
+ ($product,$product2,$test,$vendor,$vendor2) = ('','','','','');
+ if ($usb_level == 1){
+ $product = main::cleaner($row[3]);
+ }
+ else {
+ foreach my $line (@row){
+ my @working = split /:/, $line;
+ if ($working[0] eq 'idVendor' && $working[2]){
+ $vendor = main::cleaner($working[2]);
}
- testString=chassisManufacturer chassisSerialNumber chassisType chassisVersion
- if ( testString != "" ) {
- bItemFound="true"
+ if ($working[0] eq 'idProduct' && $working[2]){
+ $product = main::cleaner($working[2]);
}
- bCha="true"
- }
- /^System Information/ {
- while ( getline && !/^$/ ) {
- if ( $1 ~ /^Manufacturer/ ) { systemManufacturer=$2 }
- if ( $1 ~ /^Product Name/ ) { systemProductName=$2 }
- if ( $1 ~ /^Version/ ) { systemVersion=$2 }
- if ( $1 ~ /^Serial Number/ ) { systemSerialNumber=$2 }
- if ( $1 ~ /^UUID/ ) { systemUuid=$2 }
+ if ($working[0] eq 'iVendor' && $working[2]){
+ $product2 = main::cleaner($working[2]);
}
- testString=systemManufacturer systemProductName systemVersion systemSerialNumber systemUuid
- if ( testString != "" ) {
- bItemFound="true"
+ if ($working[0] eq 'iProduct' && $working[2]){
+ $product2 = main::cleaner($working[2]);
}
- bSys="true"
- }
- ( bSys == "true" && bCha="true" && bBio == "true" && bBas == "true" ) {
- exit # stop the loop
- }
- END {
- # sys_vendor product_name product_version product_serial product_uuid
- # board_vendor board_name board_version board_serial
- # bios_vendor bios_version bios_date
- if ( bItemFound == "true" ) {
- fullString = systemManufacturer "," systemProductName "," systemVersion "," systemSerialNumber
- fullString = fullString "," systemUuid "," baseboardManufacturer "," baseboardProductName
- fullString = fullString "," baseboardVersion "," baseboardSerialNumber "," firmwareVendor
- fullString = fullString "," firmwareVersion "," firmwareReleaseDate "," chassisManufacturer
- fullString = fullString "," chassisType "," chassisVersion "," chassisSerialNumber
- fullString = fullString "," firmwareRevision "," firmwareRomSize "," firmwareType
-
- print fullString
+ if ($working[0] eq 'Descriptor_Configuration'){
+ last;
}
- }' <<< "$DMIDECODE_DATA" )
- fi
- fi
- fi
- # echo $array_string
- IFS=','
- A_MACHINE_DATA=( $array_string )
- IFS="$ORIGINAL_IFS"
- # echo ${A_MACHINE_DATA[5]}
- a_temp=${A_MACHINE_DATA[@]}
- # echo $a_temp
- log_function_data "A_MACHINE_DATA: $a_temp"
- eval $LOGFE
-}
-# B_ROOT='true';get_machine_data;exit
-## return memory used/installed
-get_memory_data()
-{
- eval $LOGFS
- local memory='' memory_full='' used_memory=''
- if [[ $B_MEMINFO_FILE == 'true' ]];then
- memory=$( gawk '
- /^MemTotal:/ {
- tot = $2
- }
- /^(MemFree|Buffers|Cached):/ {
- notused+=$2
- }
- END {
- used = tot - notused
- printf("%.1f/%.1fMB\n", used/1024, tot/1024)
- }' $FILE_MEMINFO )
- log_function_data 'cat' "$FILE_MEMINFO"
- elif [[ $B_SYSCTL == 'true' && -n $SYSCTL_A_DATA ]];then
- local gawk_fs=': '
- # darwin sysctl is broken and uses both : and = and repeats these items
- if [[ $BSD_VERSION == 'openbsd' ]];then
- gawk_fs='='
- fi
- # use this for all bsds, maybe we can get some useful data on other ones
- if [[ -n $( type -p vmstat) ]];then
- # avail mem:2037186560 (1942MB)
- used_memory=$( vmstat 2>/dev/null | tail -n 1 | gawk '
- # openbsd/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
- # freebsd:
- # 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 21880M 6444M 924 32 11 0 822 827 0 0 853 832 463 8 3 88
- # dragonfly
- # 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 424453025 1645645889 1254348072 35 38 26
-
- BEGIN {
- IGNORECASE=1
- memory=""
+ }
+ if ($vendor && $product){
+ $product = ($product =~ /$vendor/) ? $product: "$vendor $product";
+ }
+ elsif ($vendor && $product2){
+ $product = ($product2 =~ /$vendor/) ? $product2: "$vendor $product2";
+ }
+ elsif ($vendor2 && $product){
+ $product = ($product =~ /$vendor2/) ? $product: "$vendor2 $product";
+ }
+ elsif ($vendor2 && $product2){
+ $product = ($product2 =~ /$vendor2/) ? $product2: "$vendor2 $product2";
+ }
+ elsif ($vendor){
+ $product = $vendor;
+ }
+ elsif ($vendor2){
+ $product = $vendor2;
+ }
+ $test = "$vendor $product $vendor2 $vendor2";
}
- {
- if ($4 ~ /M/ ){
- sub(/M/,"",$4)
- memory=$4*1024
+ if ($product && network_device($test)){
+ @temp2 = main::get_usb_drivers($row[0],$row[2]) if !$bsd_type && -d "/sys/devices";
+ if (@temp2){
+ $driver = $temp2[0] if $temp2[0];
+ $path = $temp2[1] if $temp2[1];
}
- else if ($4 ~ /G/ ){
- sub(/G/,"",$4)
- memory=$4*1024*1000
+ $driver ||= 'usb-network';
+ @data = ({
+ main::key($num++,'Card') => $product,
+ main::key($num++,'type') => 'USB',
+ main::key($num++,'driver') => $driver,
+ },);
+ $b_wifi = check_wifi($product);
+ @rows = (@rows,@data);
+ if ($extra > 0){
+ $rows[$j]{main::key($num++,'bus ID')} = "$row[0]:$row[1]";
}
- else {
- sub(/K/,"",$4)
- # dragonfly can have 0 avm, but they may fix that so make test dynamic
- if ( $4 != 0 ) {
- memory=$4
- }
- else {
- memory="avm-0-" $5
+ if ($extra > 1){
+ $rows[$j]{main::key($num++,'chip ID')} = $row[2];
+ }
+ $j = scalar @rows;
+ if ($show{'network-advanced'}){
+ if (!$bsd_type){
+ my (@temp,$vendor,$chip);
+ @temp = split (/:/, $row[2]) if $row[2];
+ ($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);
+ #}
+ @rows = (@rows,@data) if @data;
}
- print memory " "
- exit
- }' )
- fi
- # for dragonfly, we will use free mem, not used because free is 0
- memory=$( grep -i 'mem' <<< "$SYSCTL_A_DATA" | gawk -v usedMemory="$used_memory" -F "$gawk_fs" '
- BEGIN {
- realMemory=""
- freeMemory=""
- }
- # freebsd seems to use bytes here
- /^hw.physmem/ && ( realMemory == "" ) {
- gsub(/^[^0-9]+|[^0-9]+$/,"",$2)
- realMemory = $2/1024
- if ( freeMemory != "" ) {
- exit
- }
- }
- # But, it uses K here. Openbsd does not seem to have this item
- # this can be either: Free Memory OR Free Memory Pages
- $1 ~ /^Free Memory/ {
- gsub(/[^0-9]/,"",$NF)
- freeMemory = $NF
- if ( realMemory != "" ) {
- exit
- }
- }
- END {
- # hack: temp fix for openbsd/darwin: in case no free mem was detected but we have physmem
- if ( freeMemory == "" && realMemory != "" ) {
- # use openbsd/dragonfly avail mem data if available
- if (usedMemory != "" ) {
- if (usedMemory !~ /^avm-0-/ ) {
- printf("%.1f/%.1fMB\n", usedMemory/1024, realMemory/1024)
+ }
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+sub advanced_data_sys {
+ eval $start if $b_log;
+ return if ! -d '/sys/class/net';
+ my ($vendor,$chip,$count,$b_wifi,$path_usb) = @_;
+ my $num = 0;
+ my $key = 'IF';
+ my ($b_check,$b_usb,$if,$path,@paths,@row,@rows);
+ # ntoe: we've already gotten the base path, now we
+ # we just need to get the IF path, which is one level in:
+ # usb1/1-1/1-1:1.0/net/enp0s20f0u1/
+ if ($path_usb){
+ $b_usb = 1;
+ @paths = main::globber("${path_usb}*/net/*");
+ }
+ else {
+ @paths = main::globber('/sys/class/net/*');
+ }
+ @paths = grep {!/\/lo$/} @paths;
+ if ( $count > 0 && $count < scalar @paths ){
+ @paths = splice @paths, $count, scalar @paths;
+ }
+ if ($vendor eq 'check'){
+ $b_check = 1;
+ $key = 'IF-ID';
+ }
+ #print join '; ', @paths, $count, "\n";
+ foreach (@paths){
+ my ($data1,$data2,$duplex,$mac,$speed,$state);
+ # for usb, we already know where we are
+ if (!$b_usb){
+ $path = "$_/device/vendor";
+ $data1 = (main::reader($path))[0] if -e $path;
+ $data1 =~ s/^0x// if $data1;
+ $path = "$_/device/device";
+ $data2 = (main::reader($path))[0] if -e $path;
+ $data2 =~ s/^0x// if $data2;
+ # this is a fix for a redhat bug in virtio
+ $data2 = (defined $data2 && $data2 eq '0001' && defined $chip && $chip eq '1000') ? '1000' : $data2;
+ }
+ #print "d1:$data1 v:$vendor d2:$data2 c:$chip\n";
+ if ( $b_usb || $b_check || ( $data1 && $data2 && $data1 eq $vendor && $data2 eq $chip )) {
+ $if = $_;
+ $if =~ s/^\/.+\///;
+ # print "top: if: $if ifs: @ifs_found\n";
+ next if ($b_check && grep {/$if/} @ifs_found);
+ $path = "$_/duplex";
+ $duplex = (main::reader($path))[0] if -e $path;
+ $duplex ||= 'N/A';
+ $path = "$_/address";
+ $mac = (main::reader($path))[0] if -e $path;
+ $mac = main::apply_filter($mac);
+ $path = "$_/speed";
+ $speed = (main::reader($path))[0] if -e $path;
+ $speed ||= 'N/A';
+ $path = "$_/operstate";
+ $state = (main::reader($path))[0] if -e $path;
+ $state ||= 'N/A';
+ #print "$speed \n";
+ @row = ({
+ main::key($num++,$key) => $if,
+ main::key($num++,'state') => $state,
+ },);
+ #my $j = scalar @row - 1;
+ push (@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found));
+ # print "push: if: $if ifs: @ifs_found\n";
+ # no print out for wifi since it doesn't have duplex/speed data available
+ # 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
+ $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
+ $speed = ($speed =~ /^[0-9]+$/) ? "$speed Mbps" : $speed;
+ $row[0]{main::key($num++,'speed')} = $speed;
+ $row[0]{main::key($num++,'duplex')} = $duplex;
+ }
+ $row[0]{main::key($num++,'mac')} = $mac;
+ if ($b_check){
+ @rows = (@rows,@row);
+ }
+ else {
+ @rows = @row;
+ }
+ if ($show{'ip'}){
+ @row = if_ip($if);
+ @rows = (@rows,@row);
+ }
+ last if !$b_check;
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+sub advanced_data_bsd {
+ eval $start if $b_log;
+ return if ! @ifs_bsd;
+ my ($if,$b_wifi) = @_;
+ my (@data,@row,@rows,$working_if);
+ my ($b_check,$state,$speed,$duplex,$mac);
+ my $num = 0;
+ my $key = 'IF';
+ my $j = 0;
+ if ($if eq 'check'){
+ $b_check = 1;
+ $key = 'IF-ID';
+ }
+ foreach my $ref (@ifs_bsd){
+ if (ref $ref ne 'ARRAY'){
+ $working_if = $ref;
+ # print "$working_if\n";
+ next;
+ }
+ else {
+ @data = @$ref;
+ }
+ 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);
+ foreach my $line (@data){
+ # ($state,$speed,$duplex,$mac)
+ $duplex = $data[2];
+ $duplex ||= 'N/A';
+ $mac = main::apply_filter($data[3]);
+ $speed = $data[1];
+ $speed ||= 'N/A';
+ $state = $data[0];
+ $state ||= 'N/A';
+ #print "$speed \n";
+ @row = ({
+ main::key($num++,$key) => $if,
+ main::key($num++,'state') => $state,
+ },);
+ push (@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found ));
+ # print "push: if: $if ifs: @ifs_found\n";
+ # no print out for wifi since it doesn't have duplex/speed data available
+ # note that some cards show 'unknown' for state, so only testing explicitly
+ # for 'down' string in that to skip showing speed/duplex
+ if (!$b_wifi && $state ne 'down' && $state ne 'no'){
+ # make sure the value is strictly numeric before appending Mbps
+ $speed = ($speed =~ /^[0-9]+$/) ? "$speed Mbps" : $speed;
+ $row[0]{main::key($num++,'speed')} = $speed;
+ $row[0]{main::key($num++,'duplex')} = $duplex;
+ }
+ $row[0]{main::key($num++,'mac')} = $mac;
+ }
+ @rows = (@rows,@row);
+ if ($show{'ip'}){
+ @row = if_ip($if) if $if;
+ @rows = (@rows,@row) if @row;
+ }
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+## values:
+# 0 - ipv
+# 1 - ip
+# 2 - broadcast, if found
+# 3 - scope, if found
+# 4 - scope if, if different from if
+sub if_ip {
+ eval $start if $b_log;
+ $b_ip_run = 1;
+ my ($if) = @_;
+ my (@data,@row,@rows,$working_if);
+ my $num = 0;
+ my $j = 0;
+ OUTER:
+ foreach my $ref (@ifs){
+ if (ref $ref ne 'ARRAY'){
+ $working_if = $ref;
+ # print "if:$if wif:$working_if\n";
+ next;
+ }
+ else {
+ @data = @$ref;
+ # print "ref:$ref\n";
+ }
+ if ($working_if eq $if){
+ foreach my $ref2 (@data){
+ $j = scalar @rows;
+ $num = 1;
+ if ($limit > 0 && $j >= $limit){
+ @row = ({
+ main::key($num++,'Message') => main::row_defaults('output-limit',scalar @data),
+ },);
+ @rows = (@rows,@row);
+ last OUTER;
+ }
+ my @data2 = @$ref2;
+ #print "$data2[0] $data2[1]\n";
+ my ($ipv,$ip,$broadcast,$scope,$scope_id);
+ $ipv = ($data2[0])? $data2[0]: 'N/A';
+ $ip = main::apply_filter($data2[1]);
+ $scope = ($data2[3])? $data2[3]: 'N/A';
+ if ($if ne 'all'){
+ if (defined $data2[4] && $working_if ne $data2[4]){
+ # scope global temporary deprecated dynamic
+ # scope global dynamic
+ # scope global temporary deprecated dynamic
+ # scope site temporary deprecated dynamic
+ # scope global eth0
+ # scope link
+ # scope site dynamic
+ # scope link
+ my $key = ($data2[4] =~ /deprecated|dynamic|temporary/ ) ? 'type':'virtual' ;
+ @row = ({
+ main::key($num++,"IP v$ipv") => $ip,
+ main::key($num++,$key) => $data2[4],
+ main::key($num++,'scope') => $scope,
+ },);
}
else {
- sub(/avm-0-/,"",usedMemory)
- int(usedMemory)
- # using free mem, not used for dragonfly
- usedMemory = realMemory - usedMemory
- printf("%.1f/%.1fMB\n", usedMemory/1024, realMemory/1024)
+ @row = ({
+ main::key($num++,"IP v$ipv") => $ip,
+ main::key($num++,'scope') => $scope,
+ },);
}
}
else {
- printf("NA/%.1fMB\n", realMemory/1024)
+ @row = ({
+ main::key($num++,'IF') => $if,
+ main::key($num++,"IP v$ipv") => $ip,
+ main::key($num++,'scope') => $scope,
+ },);
+ }
+ @rows = (@rows,@row);
+ if ($extra > 1 && $data2[2]){
+ $broadcast = main::apply_filter($data2[2]);
+ $rows[$j]{main::key($num++,'broadcast')} = $broadcast;
}
}
- else if ( freeMemory != "" && realMemory != "" ) {
- used = realMemory - freeMemory
- printf("%.1f/%.1fMB\n", used/1024, realMemory/1024)
- }
- }' )
- fi
- log_function_data "memory: $memory"
- MEMORY="$memory"
- eval $LOGFE
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
}
-
-## create array of network cards
-get_networking_data()
-{
- eval $LOGFS
-
- local B_USB_NETWORKING='false' a_temp=''
-
- IFS=$'\n'
- A_NETWORK_DATA=( $(
- echo "$LSPCI_V_DATA" | gawk '
- # NOTE: see version 2.1.28 or earlier for old logic if for some reason it is needed again
- # that used a modified string made from nic name for index, why, I have no idea, makes no sense and leads
- # to wrong ordered output as well. get_audio_data uses the old logic for now too.
- BEGIN {
- IGNORECASE=1
- counter=0
- }
- /^[0-9a-f:\.]+ ((ethernet|network) (controller|bridge)|infiniband)/ || /^[0-9a-f:\.]+ [^:]+: .*(ethernet|infiniband|network).*$/ {
- aNic[counter]=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
- #gsub(/realtek semiconductor/, "Realtek", aNic[counter])
- #gsub(/davicom semiconductor/, "Davicom", aNic[counter])
- # The doublequotes are necessary because of the pipes in the variable.
- gsub(/'"$BAN_LIST_NORMAL"'/, "", aNic[counter])
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", aNic[counter])
- if ( '$COLS_INNER' < 100 ){
- sub(/PCI Express/,"PCIE", aNic[counter])
- }
- gsub(/^ +| +$/, "", aNic[counter])
- gsub(/ [ \t]+/, " ", aNic[counter])
- aPciBusId[counter] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
- while ( getline && !/^$/ ) {
- gsub(/'"$BAN_LIST_ARRAY"'/, "", $0)
- if ( /^[[:space:]]*I\/O/ ) {
- aPorts[counter] = aPorts[counter] $4 " "
- }
- if ( /driver in use/ ) {
- aDrivers[counter] = aDrivers[counter] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
- }
- else if ( /kernel modules/ ) {
- aModules[counter] = aModules[counter] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
- }
- }
- counter++
- }
- END {
- for (i=0;i<counter;i++) {
- useDrivers=""
- usePorts=""
- useModules=""
- useNic=""
- usePciBusId=""
-
- ## note: this loses the plural ports case, is it needed anyway?
- if ( aPorts[i] != "" ) {
- usePorts = aPorts[i]
- }
- if ( aDrivers[i] != "" ) {
- useDrivers = aDrivers[i]
- }
- if ( aModules[i] != "" ) {
- useModules = aModules[i]
- }
- if ( aNic[i] != "" ) {
- useNic=aNic[i]
- }
- if ( aPciBusId[i] != "" ) {
- usePciBusId = aPciBusId[i]
- }
- # create array primary item for master array
- sub( / $/, "", usePorts ) # clean off trailing whitespace
- print useNic "," useDrivers "," usePorts "," useModules, "," usePciBusId
- }
- }' ) )
- IFS="$ORIGINAL_IFS"
- get_networking_usb_data
- if [[ $B_SHOW_ADVANCED_NETWORK == 'true' || $B_USB_NETWORKING == 'true' ]];then
- if [[ -z $BSD_TYPE ]];then
- get_network_advanced_data
- fi
- fi
- a_temp=${A_NETWORK_DATA[@]}
- log_function_data "A_NETWORK_DATA: $a_temp"
-
- eval $LOGFE
+# get ip using downloader to stdout. This is a clean, text only IP output url,
+# single line only, ending in the ip address. May have to modify this in the future
+# to handle ipv4 and ipv6 addresses but should not be necessary.
+# ip=$( echo 2001:0db8:85a3:0000:0000:8a2e:0370:7334 | gawk --re-interval '
+# ip=$( wget -q -O - $WAN_IP_URL | gawk --re-interval '
+# this generates a direct dns based ipv4 ip address, but if opendns.com goes down,
+# the fall backs will still work.
+# note: consistently slower than domain based:
+# dig +short +time=1 +tries=1 myip.opendns.com. A @208.67.222.222
+sub wan_ip {
+ eval $start if $b_log;
+ my (@data,$ip);
+ my $num = 0;
+ # time: 0.06 - 0.07 seconds
+ if (my $program = main::check_program('dig')){
+ $ip = (main::grabber("$program +short +time=1 +tries=1 myip.opendns.com \@resolver1.opendns.com 2>/dev/null"))[0];
+ }
+ else {
+ # 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.
+ my @urls = qw( http://whatismyip.akamai.com/ http://icanhazip.com/ https://smxi.org/opt/ip.php);
+ foreach (@urls){
+ $ip = main::download_file('stdout',$_);
+ if ($ip){
+ # print "$_\n";
+ chomp $ip;
+ $ip = (split /\s+/, $ip)[-1];
+ last;
+ }
+ }
+ }
+ if ($ip && $show{'filter'}){
+ $ip = $filter_string;
+ }
+ $ip ||= main::row_defaults('IP', 'WAN IP');
+ @data = ({
+ main::key($num++,'WAN IP') => $ip,
+ },);
+ eval $end if $b_log;
+ return @data;
}
-get_network_advanced_data()
-{
- eval $LOGFS
- local a_network_adv_working='' if_data='' working_path='' working_uevent_path='' dir_path=''
- local if_id='' speed='' duplex='' mac_id='' oper_state='' chip_id='' b_path_made='true'
- local usb_data='' usb_vendor='' usb_product='' product_path='' driver_test='' array_counter=0
- local full_path=''
- # we need to change to holder since we are updating the main array
- IFS=$'\n'
- local a_main_working=(${A_NETWORK_DATA[@]})
- IFS="$ORIGINAL_IFS"
-
- for (( i=0; i < ${#a_main_working[@]}; i++ ))
- do
- IFS=","
- a_network_adv_working=( ${a_main_working[i]} )
- IFS="$ORIGINAL_IFS"
- # reset these every go round
- driver_test=''
- if_data=''
- product_path=''
- usb_data=''
- usb_product=''
- usb_vendor=''
- working_path=''
- working_uevent_path=''
- if [[ -z $( grep '^usb-' <<< ${a_network_adv_working[4]} ) ]];then
- # note although this may exist technically don't use it, it's a virtual path
- # and causes weird cat errors when there's a missing file as well as a virtual path
- # /sys/bus/pci/devices/0000:02:02.0/net/eth1
- # real paths are: /sys/devices/pci0000:00/0000:00:1e/0/0000:02:02.0/net/eth1/uevent
- # and on older debian kernels: /sys/devices/pci0000:00/0000:02:02.0/net:eth1/uevent
- # but broadcom shows this sometimes, and older kernels maybe:
- # /sys/devices/pci0000:00/0000:00:01.0/0000:05:00.0/net/eth0/
- # /sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/ssb0:0/uevent:['DRIVER=b43', 'MODALIAS=ssb:v4243id0812rev0D']:
- # echo a ${a_network_adv_working[4]}
- if [[ -d /sys/bus/pci/devices/ ]];then
- working_path="/sys/bus/pci/devices/0000:${a_network_adv_working[4]}"
- elif [[ -d /sys/devices/pci0000:00/ ]];then
- working_path="/sys/devices/pci0000:00/0000:00:01.0/0000:${a_network_adv_working[4]}"
- fi
- #echo wp ${a_network_adv_working[4]} $i
- # now we want the real one, that xiin also displays, without symbolic links.
- if [[ -n $working_path && -e $working_path ]];then
- working_path=$( readlink -f $working_path 2>/dev/null )
- else
- working_path=$( find -P /sys/ -type d -name "*:${a_network_adv_working[4]}" 2>/dev/null )
- # just on off chance we get two returns, just one one
- working_path=${working_path%% *}
- fi
- # sometimes there is another directory between the path and /net
- if [[ -n $working_path && ! -e $working_path/net ]];then
- # using find here, probably will need to also use it in usb part since the grep
- # method seems to not be working now. Slice off the rest, which leaves the basic path
- working_path=$( find $working_path/*/net/*/uevent 2>/dev/null | \
- sed 's|/net.*||' )
- fi
- # working_path=$( ls /sys/devices/pci*/*/0000:${a_network_adv_working[4]}/net/*/uevent )
- else
- # now we'll use the actual vendor:product string instead
- usb_data=${a_network_adv_working[10]}
- usb_vendor=$( cut -d ':' -f 1 <<< $usb_data )
- usb_product=$( cut -d ':' -f 2 <<< $usb_data )
- # this grep returns the path plus the contents of the file, with a colon separator, so slice that off
- # /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/idVendor
- working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/*/idVendor | \
- sed -e "s/idVendor:$usb_vendor//" -e '/driver/d' )
- # try an alternate path if first one doesn't work
- # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/idVendor
- if [[ -z $working_path ]];then
- working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/idVendor | \
- sed -e "s/idVendor:$usb_vendor//" -e '/driver/d' )
- product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/idProduct | \
- sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
- else
- product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/*/idProduct | \
- sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
- fi
- # make sure it's the right product/vendor match here, it will almost always be but let's be sure
- if [[ -n $working_path && -n $product_path ]] && [[ $working_path == $product_path ]];then
- #if [[ -n $working_path ]];then
- # now ls that directory and get the numeric starting sub directory and that should be the full path
- # to the /net directory part
- dir_path=$( ls $working_path 2>/dev/null | grep -sE '^[0-9]' )
- working_uevent_path="$working_path$dir_path"
- fi
- fi
- # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/uevent grep for DRIVER=
- # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/1-1:1.0/uevent
- if [[ -n $usb_data ]];then
- driver_test=$( grep -si 'DRIVER=' $working_uevent_path/uevent | cut -d '=' -f 2 )
- if [[ -n $driver_test ]];then
- a_network_adv_working[1]=$driver_test
- fi
- fi
- #echo wp: $working_path
- log_function_data "PRE: working_path: $working_path\nworking_uevent_path: $working_uevent_path"
- # this applies in two different cases, one, default, standard, two, for usb, this is actually
- # the short path, minus the last longer numeric directory name, ie:
- # from debian squeeze 2.6.32-5-686:
- # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/net/wlan0/address
- if [[ -e $working_path/net ]];then
- # in cases like infiniband dual port devices, there can be two ids, like ib0 ib1,
- # with line break in output
- if_data=$( ls $working_path/net 2>/dev/null )
- b_path_made='false'
- # this is the normal usb detection if the first one didn't work
- elif [[ -n $usb_data && -e $working_uevent_path/net ]];then
- if_data=$( ls $working_uevent_path/net 2>/dev/null )
- working_path=$working_uevent_path/net/$if_data
- # 2.6.32 debian lenny kernel shows not: /net/eth0 but /net:eth0
- elif [[ -n ${working_path/\/sys*/} ]];then
- if_data=$( ls $working_path 2>/dev/null | grep 'net:' )
- if [[ -n $if_data ]];then
- working_path=$working_path/$if_data
- # we won't be using this for path any more, just the actual if id output
- # so prep it for the loop below
- if_data=$( cut -d ':' -f 2 <<< "$if_data" )
- fi
- fi
- # just in case we got a failed path, like /net or /, clear it out for tests below
- if [[ -n ${working_path/\/sys*/} ]];then
- working_path=''
- fi
- #echo id: $if_data
- log_function_data "POST: working_path: $working_path\nif_data: $if_data - if_id: $if_id"
- # there are virtual devices that will have no if data but which we still want in the array
- # as it loops. These will also have null working_path as well since no **/net is found
- # echo if_data: $if_data
- if [[ -z $if_data ]];then
- if_data='null-if-id'
- fi
- ## note: in cases of dual ports with different ids, this loop will create extra array items
- for if_item in $if_data
- do
- chip_id=
- duplex=''
- full_path=''
- if_id=''
- mac_id=''
- oper_state=''
- speed=''
- # strip out trailing spaces
- if_item=${if_item%% }
- #echo wp1: $working_path
- if [[ $working_path != '' ]];then
- if_id=$if_item
- if [[ $b_path_made == 'false' ]];then
- full_path=$working_path/net/$if_item
- else
- full_path=$working_path
- fi
- if [[ -r $full_path/speed ]];then
- speed=$( cat $full_path/speed 2>/dev/null )
- fi
- if [[ -r $full_path/duplex ]];then
- duplex=$( cat $full_path/duplex 2>/dev/null )
- fi
- if [[ -r $full_path/address ]];then
- mac_id=$( cat $full_path/address 2>/dev/null )
- fi
- if [[ -r $full_path/operstate ]];then
- oper_state=$( cat $full_path/operstate 2>/dev/null )
- fi
- if [[ -n ${a_network_adv_working[10]} ]];then
- chip_id=${a_network_adv_working[10]}
- fi
- fi
-
- #echo fp: $full_path
- #echo id: $if_id
- # echo "$if_data ii: $if_item $array_counter i: $i"
- A_NETWORK_DATA[$array_counter]=${a_network_adv_working[0]}","${a_network_adv_working[1]}","${a_network_adv_working[2]}","${a_network_adv_working[3]}","${a_network_adv_working[4]}","$if_id","$oper_state","$speed","$duplex","$mac_id","$chip_id
-
- ((array_counter++))
- done
- done
- a_temp=${A_NETWORK_DATA[@]}
- log_function_data "A_NETWORK_DATA (advanced): $a_temp"
+### 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
- eval $LOGFE
+# 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
+ my @tests = qw(wifi Wi-Fi.*Adapter Ethernet \bLAN\b WLAN Network 802\.11
+ Wireless.*Adapter 54\sMbps Network 100\/1000 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_wifi {
+ my ($item) = @_;
+ my $b_wifi = ($item =~ /wireless|wifi|wi-fi|wlan|802\.11|centrino/i) ? 1 : 0;
+ return $b_wifi;
+}
}
-get_networking_usb_data()
-{
- eval $LOGFS
- local lsusb_path='' lsusb_data='' a_usb='' array_count=''
-
- # now we'll check for usb wifi, a work in progress
- # USB_NETWORK_SEARCH
- # alsa usb detection by damentz
- # for every sound card symlink in /proc/asound - display information about it
- lsusb_path=$( type -p lsusb )
- # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue
- if [[ -n $lsusb_path ]]; then
- # send error messages of lsusb to /dev/null as it will display a bunch if not a super user
- lsusb_data="$( $lsusb_path 2>/dev/null )"
- # also, find the contents of usbid in lsusb and print everything after the 7th word on the
- # corresponding line. Finally, strip out commas as they will change the driver :)
- if [[ -n $lsusb_data ]];then
- IFS=$'\n'
- a_usb=( $(
- gawk '
- BEGIN {
- IGNORECASE=1
- string=""
- separator=""
- }
- /'"$USB_NETWORK_SEARCH"'/ && !/bluetooth| hub|keyboard|mouse|printer| ps2|reader|scan|storage/ {
- string=""
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0 )
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
- gsub(/ [ \t]+/, " ", $0)
- #sub(/realtek semiconductor/, "Realtek", $0)
- #sub(/davicom semiconductor/, "Davicom", $0)
- #sub(/Belkin Components/, "Belkin", $0)
-
- for ( i=7; i<= NF; i++ ) {
- string = string separator $i
- separator = " "
- }
- if ( $2 != "" ){
- sub(/:/, "", $4 )
- print string ",,,,usb-" $2 "-" $4 ",,,,,," $6
- }
- }' <<< "$lsusb_data" ) )
- IFS="$ORIGINAL_IFS"
- if [[ ${#a_usb[@]} -gt 0 ]];then
- array_count=${#A_NETWORK_DATA[@]}
- for (( i=0; i < ${#a_usb[@]}; i++ ))
- do
- A_NETWORK_DATA[$array_count]=${a_usb[i]}
- ((array_count++))
- done
- # need this to get the driver data for -N regular output, but no need
- # to run the advanced stuff unless required
- B_USB_NETWORKING='true'
- fi
- fi
- fi
-# echo $B_USB_NETWORKING
- eval $LOGFE
-}
-
-get_networking_wan_ip_data()
+## OpticalData
{
- eval $LOGFS
- local ip='' ip_data='' downloader_error=0 ua='' b_ipv4_good=true no_check_ssl=''
-
- # get ip using wget redirect to stdout. This is a clean, text only IP output url,
- # single line only, ending in the ip address. May have to modify this in the future
- # to handle ipv4 and ipv6 addresses but should not be necessary.
- # ip=$( echo 2001:0db8:85a3:0000:0000:8a2e:0370:7334 | gawk --re-interval '
- # ip=$( wget -q -O - $WAN_IP_URL | gawk --re-interval '
- # this generates a direct dns based ipv4 ip address, but if opendns.com goes down,
- # the fall backs will still work.
- # note: consistently slower than domain based: dig +short +time=1 +tries=1 myip.opendns.com. A @208.67.222.222
- if [[ -n $DNSTOOL ]];then
- ip=$( dig +short +time=1 +tries=1 myip.opendns.com @resolver1.opendns.com 2>/dev/null)
- fi
- if [[ $ip == '' ]];then
- case $DOWNLOADER in
- curl)
- if [[ -n $( grep 'smxi.org' <<< $WAN_IP_URL ) ]];then
- ua="-A s-tools/inxi-ip"
- fi
- ip_data="$( curl $NO_SSL_OPT $ua -L -y $DL_TIMEOUT -s $WAN_IP_URL )" || downloader_error=$?
- ;;
- fetch)
- ip_data="$( fetch $NO_SSL_OPT -T $DL_TIMEOUT -q -o - $WAN_IP_URL )" || downloader_error=$?
- ;;
- ftp)
- ip_data="$( ftp $NO_SSL_OPT -o - $WAN_IP_URL 2>/dev/null )" || downloader_error=$?
- ;;
- perl)
- if [[ -n $( grep 'smxi.org' <<< $WAN_IP_URL ) ]];then
- ua="s-tools/inxi-ip"
- fi
- ip_data="$( download_file 'ua-stdout' $WAN_IP_URL $ua )" || downloader_man_error=$?
- ;;
- wget)
- if [[ -n $( grep 'smxi.org' <<< $WAN_IP_URL ) ]];then
- ua="-U s-tools/inxi-ip"
- fi
- ip_data="$( wget $NO_SSL_OPT $ua -T $DL_TIMEOUT -q -O - $WAN_IP_URL )" || downloader_error=$?
- ;;
- no-downloader)
- downloader_error=1
- ;;
- esac
- ip=$( gawk --re-interval '
- {
- #gsub("\n","",$2")
- print $NF
- }' <<< "$ip_data" )
- fi
-
- # validate the data
- if [[ -z $ip ]];then
- ip='None Detected!'
- elif [[ -z $( grep -Es \
- '^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4})$' <<< $ip ) ]];then
- ip='IP Source Corrupt!'
- fi
- echo "$ip"
- log_function_data "ip: $ip"
- eval $LOGFE
-}
-
-get_networking_local_ip_data()
-{
- eval $LOGFS
-
- local ip_tool_command=$( type -p ip )
- local a_temp='' ip_tool='ip' ip_tool_data=''
- # the chances for all new systems to have ip by default are far higher than
- # the deprecated ifconfig. Only try for ifconfig if ip is not present in system
- if [[ -z $ip_tool_command ]];then
- ip_tool_command=$( type -p ifconfig )
- ip_tool='ifconfig'
- else
- ip_tool_command="$ip_tool_command addr"
- fi
- if [[ -n "$ip_tool_command" ]];then
- if [[ $ip_tool == 'ifconfig' ]];then
- ip_tool_data="$( $ip_tool_command | gawk '
- {
- line=gensub(/^([a-z]+[0-9][:]?[[:space:]].*)/, "\n\\1", $0)
- print line
- }' )"
- # note, ip addr does not have proper record separation, so creating new lines explicitly here at start
- # of each IF record item. Also getting rid of the unneeded numeric line starters, now it can be parsed
- # like ifconfig more or less
- elif [[ $ip_tool == 'ip' ]];then
- ip_tool_data="$( eval $ip_tool_command | sed 's/^[0-9]\+:[[:space:]]\+/\n/' )"
- fi
- fi
- if [[ -z $ip_tool_command ]];then
- A_INTERFACES_DATA=( "Interfaces program 'ip' missing. Please check: $SELF_NAME --recommends" )
- elif [[ -n "$ip_tool_data" ]];then
- IFS=$'\n' # $ip_tool_command
- A_INTERFACES_DATA=( $(
- gawk -v ipTool=$ip_tool -v bsdType=$BSD_TYPE '
- BEGIN {
- IGNORECASE=1
- addExtV6 = ""
- addIpV6 = ""
- interface=""
- ipExtV6=""
- ifIpV4=""
- ifIpV6=""
- ifMask=""
- }
- # skip past the lo item
- /^lo/ {
- while (getline && !/^$/ ) {
- # do nothing, just get past this entry item
- }
- }
- /^[a-zA-Z]+[0-9]/ {
- # not clear on why inet is coming through, but this gets rid of it
- # as first line item.
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
- gsub(/^ +| +$/, "", $0)
- gsub(/ [ \t]+/, " ", $0)
- interface = $1
- # prep this this for ip addr: eth0: but NOT eth0:1
- sub(/:$/, "", interface)
- ifIpV4=""
- ifIpV6=""
- ifMask=""
- ipExtV6=""
- aInterfaces[interface]++
+package OpticalData;
+
+sub get {
+ eval $start if $b_log;
+ my (@data,@rows,$key1,$val1);
+ my $num = 0;
+ if ($bsd_type){
+ #@data = optical_data_bsd();
+ $key1 = 'Optical Report';
+ $val1 = main::row_defaults('optical-data-bsd');
+ @data = ({main::key($num++,$key1) => $val1,});
+ if ( @dm_boot_optical){
+ @data = optical_data_bsd();
+ }
+ else{
+ my $file = main::system_files('dmesg-boot');
+ if ( $file && ! -r $file ){
+ $val1 = main::row_defaults('dmesg-boot-permissions');
+ }
+ elsif (! -e $file){
+ $val1 = main::row_defaults('dmesg-boot-missing');
+ }
+ else {
+ $val1 = main::row_defaults('optical-data-bsd');
+ }
+ $key1 = 'Optical Report';
+ @data = ({main::key($num++,$key1) => $val1,});
+ }
+ }
+ else {
+ @data = optical_data_linux();
+ }
+ if (!@data){
+ $key1 = 'Message';
+ $val1 = main::row_defaults('optical-data');
+ @data = ({main::key($num++,$key1) => $val1,});
+ }
+ @rows = (@rows,@data);
+ eval $end if $b_log;
+ return @rows;
+}
+sub create_output {
+ eval $start if $b_log;
+ my (%devices) = @_;
+ my (@data,@rows);
+ my $num = 0;
+ my $j = 0;
+ # build floppy if any
+ foreach my $key (sort keys %devices){
+ if ($devices{$key}{'type'} eq 'floppy'){
+ @data = ({ main::key($num++,ucfirst($devices{$key}{'type'})) => "/dev/$key"});
+ @rows = (@rows,@data);
+ delete $devices{$key};
+ }
+ }
+ foreach my $key (sort keys %devices){
+ $j = scalar @rows;
+ $num = 1;
+ my $vendor = $devices{$key}{'vendor'};
+ $vendor ||= 'N/A';
+ my $model = $devices{$key}{'model'};
+ $model ||= 'N/A';
+ @data = ({
+ main::key($num++,ucfirst($devices{$key}{'type'})) => "/dev/$key",
+ main::key($num++,'vendor') => $vendor,
+ main::key($num++,'model') => $model,
+ });
+ @rows = (@rows,@data);
+ if ($extra > 0){
+ my $rev = $devices{$key}{'rev'};
+ $rev ||= 'N/A';
+ $rows[$j]{ main::key($num++,'rev')} = $rev;
+ }
+ if ($extra > 1 && $devices{$key}{'serial'}){
+ $rows[$j]{ main::key($num++,'serial')} = main::apply_filter($devices{$key}{'serial'});
+ }
+ my $ref = $devices{$key}{'links'};
+ my $links = (@$ref) ? join ',', sort @$ref: 'N/A' ;
+ $rows[$j]{ main::key($num++,'dev-links')} = $links;
+ if ($show{'optical'}){
+ $j = scalar @rows;
+ my $speed = $devices{$key}{'speed'};
+ $speed ||= 'N/A';
+ my ($audio,$multisession) = ('','');
+ if (defined $devices{$key}{'multisession'}){
+ $multisession = ( $devices{$key}{'multisession'} == 1 ) ? 'yes' : 'no' ;
+ }
+ $multisession ||= 'N/A';
+ if (defined $devices{$key}{'audio'}){
+ $audio = ( $devices{$key}{'audio'} == 1 ) ? 'yes' : 'no' ;
+ }
+ $audio ||= 'N/A';
+ my $dvd = 'N/A';
+ my (@rw,$rws);
+ if (defined $devices{$key}{'dvd'}){
+ $dvd = ( $devices{$key}{'dvd'} == 1 ) ? 'yes' : 'no' ;
+ }
+ if ($devices{$key}{'cdr'}){
+ push @rw, 'cd-r';
+ }
+ if ($devices{$key}{'cdrw'}){
+ push @rw, 'cd-rw';
+ }
+ if ($devices{$key}{'dvdr'}){
+ push @rw, 'dvd-r';
+ }
+ if ($devices{$key}{'dvdram'}){
+ push @rw, 'dvd-ram';
+ }
+ $rws = (@rw) ? join ',', @rw: 'none' ;
+ @data = ({
+ main::key($num++,'Features') => '',
+ main::key($num++,'speed') => $speed,
+ main::key($num++,'multisession') => $multisession,
+ main::key($num++,'audio') => $audio,
+ main::key($num++,'dvd') => $dvd,
+ main::key($num++,'rw') => $rws,
+ });
+ @rows = (@rows,@data);
- while (getline && !/^$/ ) {
- addIpV6 = ""
- addExtV6 = ""
- if ( ipTool == "ifconfig" ) {
- if (/inet addr:/) {
- ifIpV4 = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 )
- if (/mask:/) {
- ifMask = gensub( /mask:([0-9\.]+)/, "\\1", "g", $NF )
- }
- }
- if (/inet6 addr:/) {
- # ^fe80:
- if ( $2 ~ /^fe80/) {
- addIpV6 = $2
- }
- else if ( $0 ~ /<global>/ || $0 ~ /Scope:Global/ ) {
- addExtV6 = "sg~" $2
- }
- # ^fec0:
- else if ( $0 ~ /<site>/ || $0 ~ /Scope:Site/ || $2 ~ /^fec0/ || $2 ~ /^fc00/) {
- addExtV6 = "ss~" $2
- }
- else {
- addExtV6 = "su~" $2
- }
- }
- if ( bsdType == "bsd" ) {
- if ( $1 == "inet" ) {
- ifIpV4 = $2
- if ( $3 == "netmask" ) {
- ifMask = $4
- }
- }
- # bsds end ip with %em1 (% + interface name)
- if ( $0 ~ /inet6.*%/ ){
- sub(/%.*/,"",$2)
- if ( $2 ~ /^fe80/ ) {
- addIpV6 = $2
- }
- else if ( $2 ~ /^fec0/ || $2 ~ /^fc00/ ) {
- addExtV6 = "ss~" $2
- }
- else {
- addExtV6 = "sg~" $2
- }
- }
- }
+ if ($extra > 0 ){
+ my $state = $devices{$key}{'state'};
+ $state ||= 'N/A';
+ $rows[$j]{ main::key($num++,'state')} = $state;
+ }
+ }
+ }
+ #print Data::Dumper::Dumper \%devices;
+ eval $end if $b_log;
+ return @rows;
+}
+sub optical_data_bsd {
+ eval $start if $b_log;
+ my (@data,%devices,@rows,@temp);
+ my ($count,$i,$working) = (0,0,'');
+ foreach (@dm_boot_optical){
+ $_ =~ s/(cd[0-9]+)\(([^:]+):([0-9]+):([0-9]+)\):/$1:$2-$3.$4,/;
+ my @row = split /:\s*/, $_;
+ next if ! defined $row[1];
+ if ($working ne $row[0]){
+ # print "$id_holder $row[0]\n";
+ $working = $row[0];
+ }
+ # no dots, note: ada2: 2861588MB BUT: ada2: 600.000MB/s
+ if (! exists $devices{$working}){
+ $devices{$working} = ({});
+ $devices{$working}{'links'} = ([]);
+ $devices{$working}{'model'} = '';
+ $devices{$working}{'rev'} = '';
+ $devices{$working}{'state'} = '';
+ $devices{$working}{'vendor'} = '';
+ $devices{$working}{'temp'} = '';
+ $devices{$working}{'type'} = ($working =~ /^cd/) ? 'optical' : 'unknown';
+ }
+ #print "$_\n";
+ if ($bsd_type ne 'openbsd'){
+ if ($row[1] && $row[1] =~ /^<([^>]+)>/){
+ $devices{$working}{'model'} = $1;
+ $count = ($devices{$working}{'model'} =~ tr/ //);
+ if ($count && $count > 1){
+ @temp = split /\s+/, $devices{$working}{'model'};
+ $devices{$working}{'vendor'} = $temp[0];
+ my $index = ($#temp > 2 ) ? ($#temp - 1): $#temp;
+ $devices{$working}{'model'} = join ' ', @temp[1..$index];
+ $devices{$working}{'rev'} = $temp[-1] if $count > 2;
}
- else if ( ipTool == "ip" ) {
- if ( $1 == "inet" ) {
- ifIpV4 = $2
+ if ($show{'optical'}){
+ if (/\bDVD\b/){
+ $devices{$working}{'dvd'} = 1;
}
- if ( $1 == "inet6" ){
- # filter out deprecated IPv6 privacy addresses
- if ( $0 ~ / temporary deprecated/) {
- addExtV6 = ""
- }
- else if ( $0 ~ /scope global temporary/) {
- addExtV6 = "st~" $2
- }
- else if ( $0 ~ /scope global/) {
- addExtV6 = "sg~" $2
- }
- # ^fe80:
- else if ( $2 ~ /^fe80/ || $0 ~ /scope link/) {
- addIpV6 = $2
- }
- # ^fec0:
- else if ( $2 ~ /^fec0/ || $2 ~ /^fc00/ || $0 ~ /scope site/) {
- addExtV6 = "ss~" $2
- }
- else {
- addExtV6 = "su~" $2
- }
+ if (/\bRW\b/){
+ $devices{$working}{'cdrw'} = 1;
+ $devices{$working}{'dvdr'} = 1 if $devices{$working}{'dvd'};
}
}
- if ( addIpV6 != "" ) {
- if ( ifIpV6 == "" ) {
- ifIpV6 = addIpV6
- }
- else {
- ifIpV6 = ifIpV6 "^" addIpV6
- }
+ }
+ if ($row[1] && $row[1] =~ /^Serial/){
+ @temp = split /\s+/,$row[1];
+ $devices{$working}{'serial'} = $temp[-1];
+ }
+ if ($show{'optical'}){
+ if ($row[1] =~ /^([0-9\.]+[MGTP][B]?\/s)/){
+ $devices{$working}{'speed'} = $1;
+ $devices{$working}{'speed'} =~ s/\.[0-9]+//;
}
- if (addExtV6 != "" ){
- if ( ipExtV6 == "" ){
- ipExtV6 = addExtV6
+ if (/\bDVD[-]?RAM\b/){
+ $devices{$working}{'cdr'} = 1;
+ $devices{$working}{'dvdram'} = 1;
+ }
+ if ($row[2] && $row[2] =~ /,\s(.*)$/){
+ $devices{$working}{'state'} = $1;
+ $devices{$working}{'state'} =~ s/\s+-\s+/, /;
+ }
+ }
+ }
+ else {
+ if ($row[2] && $row[2] =~ /<([^>]+)>/){
+ $devices{$working}{'model'} = $1;
+ $count = ($devices{$working}{'model'} =~ tr/,//);
+ #print "c: $count $row[2]\n";
+ if ($count && $count > 1){
+ @temp = split /,\s*/, $devices{$working}{'model'};
+ $devices{$working}{'vendor'} = $temp[0];
+ $devices{$working}{'model'} = $temp[1];
+ $devices{$working}{'rev'} = $temp[2];
+ }
+ if ($show{'optical'}){
+ if (/\bDVD\b/){
+ $devices{$working}{'dvd'} = 1;
}
- else {
- ipExtV6 = ipExtV6 "^" addExtV6
+ if (/\bRW\b/){
+ $devices{$working}{'cdrw'} = 1;
+ $devices{$working}{'dvdr'} = 1 if $devices{$working}{'dvd'};
+ }
+ if (/\bDVD[-]?RAM\b/){
+ $devices{$working}{'cdr'} = 1;
+ $devices{$working}{'dvdram'} = 1;
}
}
}
- # slice off the digits that are sometimes tacked to the end of the address,
- # like: /64 or /24
- sub(/\/[0-9]+/, "", ifIpV4)
- gsub(/\/[0-9]+/, "", ifIpV6) #
- ipAddresses[interface] = ifIpV4 "," ifMask "," ifIpV6 "," ipExtV6
- }
- END {
- j=0
- for (i in aInterfaces) {
- ifData = ""
- a[j] = i
- if (ipAddresses[i] != "") {
- ifData = ipAddresses[i]
- }
- # create array primary item for master array
- # tested needed to avoid bad data from above, if null it is garbage
- # this is the easiest way to handle junk I found, improve if you want
- if ( ifData != "" ) {
- print a[j] "," ifData
- }
- j++
- }
- }' <<< "$ip_tool_data" ) )
- IFS="$ORIGINAL_IFS"
- else
- A_INTERFACES_DATA=( "Interfaces program $ip_tool present but created no data. " )
- fi
- a_temp=${A_INTERFACES_DATA[@]}
- log_function_data "A_INTERFACES_DATA: $a_temp"
- eval $LOGFE
-}
-# get_networking_local_ip_data;exit
-
-get_optical_drive_data()
-{
- eval $LOGFS
-
- local a_temp='' sys_uevent_path='' proc_cdrom='' link_list=''
- local separator='' linked='' working_disk='' disk='' item_string='' proc_info_string=''
- local dev_disks_full=''
- dev_disks_full="$( ls /dev/dvd* /dev/cd* /dev/scd* /dev/sr* /dev/fd[0-9] 2>/dev/null | grep -vE 'random' )"
- ## Not using this now because newer kernel is NOT linking all optical drives. Some, but not all
- # Some systems don't support xargs -L plus the unlinked optical drive unit make this not a good option
- # get the actual disk dev location, first try default which is easier to run, need to preserve line breaks
- # local dev_disks_real="$( echo "$dev_disks_full" | xargs -L 1 readlink 2>/dev/null | sort -u )"
-
- #echo ddl: $dev_disks_full
- for working_disk in $dev_disks_full
- do
- disk=$( readlink $working_disk 2>/dev/null )
- if [[ -z $disk ]];then
- disk=$working_disk
- fi
- disk=${disk##*/} # puppy shows this as /dev/sr0, not sr0
- # if [[ -z $dev_disks_real || -z $( grep $disk <<< $dev_disks_real ) ]];then
- if [[ -n $disk && -z $( grep "$disk" <<< $dev_disks_real ) ]];then
- # need line break IFS for below, no white space
- dev_disks_real="$dev_disks_real$separator$disk"
- separator=$'\n'
- #separator=' '
- fi
- done
- dev_disks_real="$( sort -u <<< "$dev_disks_real" )"
- working_disk=''
- disk=''
- separator=''
- #echo ddr: $dev_disks_real
-
- # A_OPTICAL_DRIVE_DATA indexes: not going to use all these, but it's just as easy to build the full
- # data array and use what we need from it as to update it later to add features or items
- # 0 - true dev path, ie, sr0, hdc
- # 1 - dev links to true path
- # 2 - device vendor - for hdx drives, vendor model are one string from proc
- # 3 - device model
- # 4 - device rev version
- # 5 - speed
- # 6 - multisession support
- # 7 - MCN support
- # 8 - audio read
- # 9 - cdr
- # 10 - cdrw
- # 11 - dvd read
- # 12 - dvdr
- # 13 - dvdram
- # 14 - state
-
- if [[ -n $dev_disks_real ]];then
- if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
- proc_cdrom="$( cat /proc/sys/dev/cdrom/info 2>/dev/null )"
- fi
- IFS=$'\n'
- A_OPTICAL_DRIVE_DATA=( $(
- for disk in $dev_disks_real
- do
- for working_disk in $dev_disks_full
- do
- if [[ -n $( readlink $working_disk | grep $disk ) ]];then
- linked=${working_disk##*/}
- link_list="$link_list$separator$linked"
- separator='~'
- fi
- done
- item_string="$disk,$link_list"
- link_list=''
- linked=''
- separator=''
- vendor=''
- model=''
- proc_info_string=''
- rev_number=''
- state=""
- sys_path=''
- working_disk=''
- # this is only for new sd type paths in /sys, otherwise we'll use /proc/ide
- if [[ -z $( grep '^hd' <<< $disk ) ]];then
- # maybe newer kernels use this, not enough data.
- sys_path=$( ls /sys/devices/pci*/*/ata*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
- # maybe older kernels, this used to work (2014-03-16)
- if [[ -z $sys_path ]];then
- sys_path=$( ls /sys/devices/pci*/*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
- fi
- # no need to test for errors yet, probably other user systems will require some alternate paths though
- if [[ -n $sys_path ]];then
- vendor=$( cat $sys_path/vendor 2>/dev/null )
- model=$( cat $sys_path/model 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
- state=$( cat $sys_path/state 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
- rev_number=$( cat $sys_path/rev 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
- fi
- elif [[ -e /proc/ide/$disk/model ]];then
- vendor=$( cat /proc/ide/$disk/model 2>/dev/null )
- fi
- if [[ -n $vendor ]];then
- vendor=$( gawk '
- BEGIN {
- IGNORECASE=1
+ if ($show{'optical'}){
+ #print "$row[1]\n";
+ if (($row[1] =~ tr/,//) > 1){
+ @temp = split /,\s*/, $row[1];
+ $devices{$working}{'speed'} = $temp[2];
}
- {
- gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
- sub(/TSSTcorp/, "TSST ", $0) # seen more than one of these weird ones
- gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
- gsub(/^[[:space:]]*|[[:space:]]*$/, "", $0)
- gsub(/ [[:space:]]+/, " ", $0)
- print $0
- }' <<< $vendor )
- fi
- # this needs to run no matter if there's proc data or not to create the array comma list
- if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
- proc_info_string=$( gawk -v diskId=$disk '
- BEGIN {
- IGNORECASE=1
- position=""
- speed=""
- multisession=""
- mcn=""
- audio=""
- cdr=""
- cdrw=""
- dvd=""
- dvdr=""
- dvdram=""
- }
- # first get the position of the device name from top field
- # we will use this to get all the other data for that column
- /drive name:/ {
- for ( position=3; position <= NF; position++ ) {
- if ( $position == diskId ) {
- break
- }
+
+ }
+ }
+ }
+
+ main::log_data('dump','%devices',\%devices) if $b_log;
+ #print Data::Dumper::Dumper \%devices;
+ @rows = create_output(%devices) if %devices;
+ eval $end if $b_log;
+ return @rows;
+}
+sub optical_data_linux {
+ eval $start if $b_log;
+ my (@data,%devices,@info,@rows);
+ @data = main::globber('/dev/dvd* /dev/cdr* /dev/scd* /dev/sr* /dev/fd[0-9]');
+ # Newer kernel is NOT linking all optical drives. Some, but not all.
+ # Get the actual disk dev location, first try default which is easier to run,
+ # need to preserve line breaks
+ foreach (@data){
+ my $working = readlink($_);
+ $working = ($working) ? $working: $_;
+ next if $working =~ /random/;
+ # possible fix: puppy has these in /mnt not /dev they say
+ $working =~ s/\/(dev|media|mnt)\///;
+ $_ =~ s/\/(dev|media|mnt)\///;
+ if (! defined $devices{$working}){
+ my @temp = ($_ ne $working) ? ([$_]) : ([]);
+ $devices{$working} = ({'links' => @temp});
+ $devices{$working}{'type'} = ($working =~ /^fd/) ? 'floppy' : 'optical' ;
+ }
+ else {
+ my $ref = $devices{$working}{'links'};
+ push @$ref, $_ if $_ ne $working;
+ }
+ #print "$working\n";
+ }
+ if ($show{'optical'} && -e '/proc/sys/dev/cdrom/info'){
+ @info = main::reader('/proc/sys/dev/cdrom/info','strip');
+ }
+ #print join '; ', @data, "\n";
+ foreach my $key (keys %devices){
+ next if $devices{$key}{'type'} eq 'floppy';
+ my $device = "/sys/block/$key/device";