diff options
Diffstat (limited to 'inxi')
-rw-r--r-- | inxi/PKGBUILD | 18 | ||||
-rw-r--r-- | inxi/inxi | 4428 |
2 files changed, 4446 insertions, 0 deletions
diff --git a/inxi/PKGBUILD b/inxi/PKGBUILD new file mode 100644 index 0000000..781f3c4 --- /dev/null +++ b/inxi/PKGBUILD @@ -0,0 +1,18 @@ +# Contributor: Florian Pritz <f-p@gmx.at> +pkgname=inxi +pkgver=1.1.13 +pkgrel=1 +pkgdesc="script to get system information" +arch=('any') +url="http://inxi.org" +license=('GPL') +source=("http://inxi.googlecode.com/svn/trunk/inxi") + +build() { + cd "$srcdir" + install -D -m755 inxi $pkgdir/usr/bin/inxi +} + +# vim:set ts=2 sw=2 et: +md5sums=('c5c2830ede9eed63d2434527e56ee541') +sha256sums=('3d8f0736829754f7aa2d7f85ba3e8bb5b7bd0b3c7ac110abe6c66b440109b5d2') diff --git a/inxi/inxi b/inxi/inxi new file mode 100644 index 0000000..f857208 --- /dev/null +++ b/inxi/inxi @@ -0,0 +1,4428 @@ +#!/bin/bash +######################################################################## +#### Script Name: inxi +#### version: 1.1.13 +#### Date: August 6 2009 +######################################################################## +#### 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 script by locsmif +#### As time permits functionality improvements and recoding will occur. +#### +#### inxi, the universal, portable, system info script 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-9 Scott Rogers & Harald Hope +#### Further fixes (listed as known): Horst Tritremmel <hjt at sidux.com> +#### Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch +#### +#### Current script home page: http://techpatterns.com/forums/about1131.html +#### Script svn: http://code.google.com/p/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 +######################################################################## +#### DEPENDENCIES +#### bash >=3.0(bash), df;readlink;stty;tr;uname;wc(coreutils), +#### gawk(gawk), grep(grep), hostname(hostname), lspci(pciutils), +#### ps;uptime(procps), glxinfo;xdpyinfo;xrandr(xbase-clients) +#### Also the proc filesystem should be present and mounted +#### +#### 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 +#### +#### Arrays work in bash 2.05b, but "egrep -m" does not +#### +#### RECOMMENDS (Needed to run certain features) +#### For local interfaces/IP test: ifconfig (in net-tools for Debian systems) +#### runlevel(sysvinit): to view current runlevel while not in X window system +#### Bash 3.1 for proper array use +######################################################################## +#### CONVENTIONS: +#### 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. +#### +#### 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 +#### +#### VARIABLE/FUNCTION NAMING: +#### All functions should follow standard naming--verb adjective noun. +#### ie, get_cpu_data +#### All variables MUST be initialized / declared explicitly. +#### All variables should clearly explain what they are, except counters like i, j. +#### Each word of variable must be separated by '_' (underscore) (camel form). +#### Global variables are 'UPPER CASE', at top of script. +#### ie, SOME_VARIABLE='' +#### Local variables are 'lower case' and declared at the top of the function. +#### ie, 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. +#### +#### 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 script +#### +#### 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 +#### gawk arrays: http://www.math.utah.edu/docs/info/gawk_12.html +######################################################################## +#### 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 svn +#### -! 11 - triggers an update from svn branch one - if present, of course +#### -! 12 - triggers an update from svn branch two - if present, of course +#### -! 13 - triggers an update from svn branch three - if present, of course +#### -! 14 - triggers an update from svn 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 +# set to default LANG to avoid locales errors with , or . +LANG=C +### Variable initializations: null values +CMDL_MAX='' +COLOR_SCHEME='' +COLOR_SCHEME_SET='' +IRC_CLIENT='' +IRC_CLIENT_VERSION='' + +### primary data array holders ## usage: 'A_<var>' +A_AUDIO_DATA='' +A_CMDL='' +A_CPU_CORE_DATA='' +A_CPU_DATA='' +A_CPU_TYPE_PCNT_CCNT='' +A_DEBUG_BUFFER='' +A_GFX_CARD_DATA='' +A_GLX_DATA='' +A_HDD_DATA='' +A_INTERFACES_DATA='' +A_NETWORK_DATA='' +A_PARTITION_DATA='' +A_SENSORS_DATA='' +A_X_DATA='' + +### Boolean true/false globals ## usage: 'B_<var>' +# 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 +B_ALLOW_UPDATE='true' +# triggers full display of cpu flags +B_CPU_FLAGS_FULL='false' +# Debug flood override: make 'true' to allow long debug output +B_DEBUG_FLOOD='false' +# show extra output data +B_EXTRA_DATA='false' +# override certain errors due to currupted data +B_HANDLE_CORRUPT_DATA='false' +B_LOG_COLORS='false' +B_LOG_FULL_DATA='false' +B_ROOT='false' +# Running in a shell? Defaults to false, and is determined later. +B_RUNNING_IN_SHELL='false' +# this sets the debug buffer +B_SCRIPT_UP='false' +# sensors only if installed +B_SENSORS='false' +# Show sound card data +B_SHOW_AUDIO='false' +B_SHOW_CPU='false' +B_SHOW_DISK='false' +# Show full hard disk output +B_SHOW_FULL_HDD='false' +B_SHOW_GRAPHICS='false' +# Set this to 'false' to avoid printing the hostname +B_SHOW_HOST='true' +B_SHOW_INFO='false' +B_SHOW_IP='false' +B_SHOW_LABELS='false' +B_SHOW_NETWORK='false' +# either -v > 3 or -P will show partitions +B_SHOW_PARTITIONS='false' +B_SHOW_PARTITIONS_FULL='false' +B_SHOW_SENSORS='false' +# triggers only short inxi output +B_SHOW_SHORT_OUTPUT='false' +B_SHOW_SYSTEM='false' +B_SHOW_UUIDS='false' +# triggers various debugging and new option testing +B_TESTING_1='false' +B_TESTING_2='false' +# set to true here for debug logging from script start +B_USE_LOGGING='false' +# Test for X running +B_X_RUNNING='false' +# test for dbus irc client +B_DBUS_CLIENT='false' + +### Directory/file exist flags; test as [[ $(boolean) ]] not [[ $boolean ]] +B_PROC='false' +B_CPUINFO='false' +B_MEMINFO='false' +B_ASOUND_CARDS='false' +B_ASOUND_VERSION='false' +B_BASH_ARRAY='false' +B_IFCONFIG='false' +B_LSB_DIR='false' +B_SCSI_DIR='false' +B_MODULES_DIR='false' # +B_MOUNTS_DIR='false' +B_PARTITIONS_DIR='false' # + +### File's used when present +FILE_CPUINFO='/proc/cpuinfo' +FILE_MEMINFO='/proc/meminfo' +FILE_ASOUND_DEVICE='/proc/asound/cards' +FILE_ASOUND_VERSION='/proc/asound/version' +FILE_LSB_RELEASE='/etc/lsb-release' +FILE_SCSI='/proc/scsi/scsi' +FILE_MODULES='/proc/modules' +FILE_MOUNTS='/proc/mounts' +FILE_PARTITIONS='/proc/partitions' + +### Variable initializations: constants +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 +## 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 + +# Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Set to any other valid scheme you like. +# Same as runtime parameter. +DEFAULT_SCHEME=2 + +# Default indentation level +INDENT=10 + +# 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 + +# 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_CPU_COUNT=0 # Wether 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 +# 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=5 + +# 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" + +# These two determine separators in single line output, to force irc clients not to break off sections +SEP1='-' +SEP2='~' + +### Script names/paths - must be non root writable +SCRIPT_DATA_DIR="$HOME/.inxi" +LOG_FILE="$SCRIPT_DATA_DIR/inxi.log" +LOG_FILE_1="$SCRIPT_DATA_DIR/inxi.1.log" +LOG_FILE_2="$SCRIPT_DATA_DIR/inxi.2.log" +SCRIPT_NAME="inxi" +SCRIPT_PATH="" #filled-in in Main +SCRIPT_VERSION_NUMBER="" #filled-in in Main +SCRIPT_DOWNLOAD='http://inxi.googlecode.com/svn/trunk/' +SCRIPT_DOWNLOAD_BRANCH_1='http://inxi.googlecode.com/svn/branches/one/' +SCRIPT_DOWNLOAD_BRANCH_2='http://inxi.googlecode.com/svn/branches/two/' +SCRIPT_DOWNLOAD_BRANCH_3='http://inxi.googlecode.com/svn/branches/three/' +SCRIPT_DOWNLOAD_BRANCH_4='http://inxi.googlecode.com/svn/branches/four/' +SCRIPT_DOWNLOAD_DEV='http://smxi.org/test/' +KONVI_CFG="konversation/scripts/$SCRIPT_NAME.conf" # relative path to $(kde-config --path data) + +### Script Localization +# Make sure every program speaks English. +LC_ALL="C" +export LC_ALL + +### 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="[1;30m [0;30m [1;31m [0;31m [1;32m [0;32m [1;33m [0;33m" +IRC_COLORS=" \x0314 \x0301 \x0304 \x0305 \x0309 \x0303 \x0308 \x0307" +# BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL +ANSI_COLORS="$ANSI_COLORS [1;34m [0;34m [1;35m [0;35m [1;36m [0;36m [1;37m [0;37m [0;37m" +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 +A_COLOR_SCHEMES=( EMPTY,EMPTY,EMPTY NORMAL,NORMAL,NORMAL BLUE,NORMAL,NORMAL GREEN,YELLOW,NORMAL DYELLOW,NORMAL,NORMAL CYAN,BLUE,NORMAL RED,NORMAL,NORMAL GREEN,NORMAL,NORMAL YELLOW,NORMAL,NORMAL GREEN,DGREEN,NORMAL BLUE,RED,NORMAL BLUE,NORMAL,RED YELLOW,WHITE,GREEN BLUE,NORMAL,GREEN DCYAN,NORMAL,DMAGENTA ) +## Actual color variables +C1='' +C2='' +CN='' + +### Distro Data +# 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 kanotix-version knoppix-version mandrake-release pardus-release sabayon-release sidux-version 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 ubuntu_version" +DISTROS_PRIMARY="gentoo-release redhat-release slackware-version SuSE-release" +DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-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 + +### Bans Data +# Precede a banword with $'\2' to prevent it from being subject to automated escaping by the make_ban_lists routine +# $'\1' gets weird results : +# user@host $ ARR=($'\x01'"one two" three four); echo ${ARR[0]} | hd -v +# 00000000 01 01 6f 6e 65 20 74 77 6f 0a |..one two.| +A_NORMAL_BANS=( corporation communications gmbh technologies technology group $'\2'"\<ltd\>" ltd. $'\2'"\<inc\>" inc. $'\2'\<co\> co. "(tm)" "(r)" "®" $'\2'"\(rev ..\)" ) +A_CPU_BANS=( @ cpu deca 'dual core' dual-core 'tri core' tri-core 'quad core' quad-core ennea genuine hepta hexa multi octa penta 'processor' processor single triple $'\2'"[0-9.]+ *[MmGg][Hh][Zz]" ) +# after processing, the ban arrays will be put into these: +BAN_LIST_NORMAL='' +BAN_LIST_CPU='' + +# 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! + +######################################################################## +#### MAIN: Where it all begins +######################################################################## +main() +{ + eval $LOGFS + + # This function just initializes variables + initialize_script_data + + # Check for dependencies BEFORE running ANYTHING else except above functions + # Not all distro's have these depends installed by default + check_script_depends + check_script_suggested_apps + + # 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. + + ### Only continue if depends ok + SCRIPT_PATH=$( dirname $0 ) + SCRIPT_VERSION_NUMBER=$( grep -im 1 'version:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3}' ) + + ### Source global config overrides + if [[ -s /etc/$SCRIPT_NAME.conf ]];then + source /etc/$SCRIPT_NAME.conf + fi + # Source user config overrides, ~/.inxi/inxi.conf + if [[ -s $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf ]];then + source $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf + fi + + ## 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 + + # 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 + IFS=":" + for kde_config in $( kde-config --path data ) + do + if [[ -r ${kde_config}${KONVI_CFG} ]];then + source "${kde_config}${KONVI_CFG}" + break + fi + done + IFS="$ORIGINAL_IFS" + 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" + + # "$@" 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 [[ $COLOR_SCHEME_SET != 'true' ]];then + set_color_scheme "$DEFAULT_SCHEME" + fi + + # all the pre-start stuff is in place now + B_SCRIPT_UP='true' + script_debugger "Debugger: $SCRIPT_NAME is up and running..." + + # then create the output + print_it_out + + ## last steps + if [[ $B_RUNNING_IN_SHELL == 'true' && $SCHEME -gt 0 ]];then + echo -n "[0m" + fi + 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 +} + +#### ------------------------------------------------------------------- +#### basic tests: set script data, booleans, PATH +#### ------------------------------------------------------------------- + +# 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_script_data() +{ + eval $LOGFS + local path='' sys_path='' added_path='' b_path_found='' + # 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" + + # 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\""' + + # Do this after sourcing of config overrides so user can customize banwords + BAN_LIST_NORMAL=$( make_ban_lists "${A_NORMAL_BANS[@]}" ) # Contrary to my previous belief, "${ARR[@]}" passes a quoted list, not one string + BAN_LIST_CPU=$( make_ban_lists "${A_CPU_BANS[@]}" ) + ##echo "BAN_LIST_NORMAL='$BAN_LIST_NORMAL'" + + # now set the script BOOLEANS for files required to run features + if [[ -d "/proc/" ]];then + B_PROC='true' + else + error_handler 6 + fi + + if [[ -e $FILE_CPUINFO ]]; then + B_CPUINFO='true' + fi + + if [[ -e $FILE_MEMINFO ]];then + B_MEMINFO='true' + fi + + if [[ -e $FILE_ASOUND_DEVICE ]];then + B_ASOUND_CARDS='true' + fi + + if [[ -e $FILE_ASOUND_VERSION ]];then + B_ASOUND_VERSION='true' + fi + + if [[ -f $FILE_LSB_RELEASE ]];then + B_LSB_DIR='true' + fi + + if [[ -e $FILE_SCSI ]];then + B_SCSI_DIR='true' + fi + + # lack of ifconfig will throw an error only upon it's usage + if [[ -n $( type -p ifconfig ) ]]; then + B_IFCONFIG='true' + else + A_INTERFACES_DATA=( "Interfaces tool requires missing app: ifconfig" ) + fi + + if [[ -n $( type -p sensors ) ]];then + B_SENSORS='true' + fi + + if [[ -n $DISPLAY ]];then + B_X_RUNNING='true' + fi + + if [[ -e $FILE_MODULES ]];then + B_MODULES_DIR='true' + fi + + if [[ -e $FILE_MOUNTS ]];then + B_MOUNTS_DIR='true' + fi + + if [[ -e $FILE_PARTITIONS ]];then + B_PARTITIONS_DIR='true' + fi + # gfx output will require this flag + if [[ $( whoami ) == 'root' ]];then + B_ROOT='true' + fi + eval $LOGFE +} + +# No args taken. +check_script_suggested_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 + script_debugger "Suggestion: update to Bash v3.1 for optimal inxi output" + fi + eval $LOGFE +} + +# Determine if any of the absolutely necessary tools are absent +# No args taken. +check_script_depends() +{ + eval $LOGFS + local app_name='' app_data='' + # bc removed from deps for now + local depends="df free gawk grep hostname lspci ps readlink tr uname uptime wc" + local x_apps="xrandr xdpyinfo glxinfo" + + if [[ $B_X_RUNNING == 'true' ]];then + for app_name in $x_apps + do + app_data=$( type -p $app_name ) + if [[ -z $app_data ]];then + script_debugger "Resuming in non X mode: $app_name not found in path" + B_X_RUNNING='false' + break + fi + done + fi + + app_name='' + + for app_name in $depends + do + app_data=$( type -p $app_name ) + if [[ -z $app_data ]];then + error_handler 5 "$app_name" + fi + done + 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 +} + +# Filter boilerplate & buzzwords. +# args: $1 - quoted: "$@" array of ban terms +make_ban_lists() +{ + eval $LOGFS + local ban_list='' + # Iterate over $@ + ## note: this is a weird, non-intuitive method, needs some documentation or rewriting + ## if you declare ban_string it stops working, have to read up on this + for ban_string + do + # echo "term=\"$ban_string\"" # >&2 + if [[ ${ban_string:0:1} = $'\2' ]];then + ban_list="${ban_list}${ban_list+|}${ban_string:1:${#ban_string}-1}" + else + # Automatically escapes [ ] ( ) . and + + ban_list="${ban_list}${ban_list+|}$( echo "$ban_string" | gawk '{ + gsub(/([\[\]+().])/,"\\\\&") + print + }' )" + fi + done + + echo "$ban_list" + eval $LOGFS +} +# make_ban_lists "${A_CPU_BANS[@]}";exit + +# Set the colorscheme +# args: $1 = <scheme number>|<"none"> +set_color_scheme() +{ + eval $LOGFS + local i='' script_colors='' 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_RUNNING_IN_SHELL == 'true' ]];then + color_codes=( $ANSI_COLORS ) + else + color_codes=( $IRC_COLORS ) + fi + for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ )) + do + eval "${A_COLORS_AVAILABLE[i]}=\"${color_codes[i]}\"" + done + IFS="," + script_colors=( ${A_COLOR_SCHEMES[$1]} ) + IFS="$ORIGINAL_IFS" + # then assign the colors globally + C1="${!script_colors[0]}" + C2="${!script_colors[1]}" + CN="${!script_colors[2]}" + # ((COLOR_SCHEME++)) ## note: why is this? ## + eval $LOGFE +} + +######################################################################## +#### UTILITY FUNCTIONS +######################################################################## + +#### ------------------------------------------------------------------- +#### error handler, debugger, script updater +#### ------------------------------------------------------------------- + +# Error handling +# args: $1 - error number; $2 - optional, extra information +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" + ;; + 6) error_message="/proc not found! Quitting..." + ;; + 7) error_message="One of the options you entered in your script parameters: $2\nIs not supported. For supported options, check the help menu: $SCRIPT_NAME -h" + ;; + 8) error_message="the self-updater failed, wget exited with error: $2.\nYou probably need to be root.\nHint, to make for easy updates without being root, do: chown <user name> $SCRIPT_PATH/$SCRIPT_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 $SCRIPT_NAME, like: http://yoursite.com/downloads/" + ;; + 11) + error_message="unsupported testing option argument: -! $2" + ;; + 12) + error_message="the svn branch download url: $2\nappears to be empty currently. Make sure there is an actual svn branch version\nactive before you try this again. Check http://code.google.com/p/inxi\nto verify the branch status." + ;; + *) error_message="error unknown: $@" + set -- 99 + ;; + esac + # then print it and exit + print_screen_output "Error $1: $error_message" + eval $LOGFE + exit $1 +} + +# prior to script up set, pack the data into an array +# then we'll print it out later. +# args: $1 - $@ debugging string text +script_debugger() +{ + eval $LOGFS + if [[ $B_SCRIPT_UP == 'true' ]];then + # only return if debugger is off and no pre start up errors have occured + if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then + return 0 + # print out the stored debugging information if errors occured + 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 +} + +# 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 + logged_data="\n$line\nFull file data: cat $2\n\n$( cat $2 )\n$line\n" + 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 -r '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 +} + +# 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() +{ + if [[ ! -d $SCRIPT_DATA_DIR ]];then + mkdir $SCRIPT_DATA_DIR + fi + # 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 $SCRIPT_NAME LOGGING:" >> $LOG_FILE + echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )" >> $LOG_FILE + echo "=========================================================" >> $LOG_FILE +} + +# args: $1 - download url, not including file name; $2 - string to print out +# note that $1 must end in / to properly construct the url path +script_self_updater() +{ + eval $LOGFS + local wget_error=0 + print_screen_output "Starting $SCRIPT_NAME self updater." + print_screen_output "Currently running $SCRIPT_NAME version number: $SCRIPT_VERSION_NUMBER" + print_screen_output "Updating $SCRIPT_NAME in $SCRIPT_PATH using $2 as download source..." + # first test if path is good, need to make sure it's good because we're -O overwriting file + wget -q --spider $1$SCRIPT_NAME || wget_error=$? + # then do the actual download + if [[ $wget_error -eq 0 ]];then + wget -q -O $SCRIPT_PATH/$SCRIPT_NAME $1$SCRIPT_NAME || wget_error=$? + if [[ $wget_error -eq 0 ]];then + SCRIPT_VERSION_NUMBER=$( grep -im 1 'version:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3}' ) + print_screen_output "Successfully updated to $2 version: $SCRIPT_VERSION_NUMBER" + print_screen_output "To run the new version, just start $SCRIPT_NAME again." + exit 0 + fi + fi + # now run the error handlers on any wget failure + if [[ $wget_error -gt 0 ]];then + if [[ $2 == 'svn server' ]];then + error_handler 8 "$wget_error" + elif [[ $2 == 'alt server' ]];then + error_handler 10 "$1" + else + error_handler 12 "$1" + fi + fi + eval $LOGFS +} + +#### ------------------------------------------------------------------- +#### print / output cleaners +#### ------------------------------------------------------------------- + +# 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 + 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 ]]; 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 ]]; 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 +} + +## 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 + printf "${C1}%-${INDENT}s${C2} %s" "$1" "$2" + eval $LOGFE +} + +# 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 +} + +#### ------------------------------------------------------------------- +#### parameter handling, print usage functions. +#### ------------------------------------------------------------------- + +# 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='' wget_test='' update_flags='U!:' + local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false + + # <comment here. what is this for?> + if [[ $B_ALLOW_UPDATE == 'false' ]];then + update_flags='' + fi + + # the short form only runs if no args output args are used + # no need to run through these if there are no args + if [[ -n $1 ]];then + while getopts Ac:CdDfFGhHiIlNpPsSuv:Vx%@:${update_flags} opt + do + case $opt in + A) B_SHOW_AUDIO='true' + use_short='false' + ;; + c) if [[ -n $( egrep '^[0-9][0-9]?$' <<< $OPTARG ) ]];then + 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 + else + error_handler 3 "$OPTARG" + fi + ;; + C) B_SHOW_CPU='true' + use_short='false' + ;; + d) VERBOSITY_LEVEL=1 + use_short='false' + ;; + D) B_SHOW_DISK='true' + use_short='false' + ;; + f) B_SHOW_CPU='true' + B_CPU_FLAGS_FULL='true' + use_short='false' + ;; + F) VERBOSITY_LEVEL=$VERBOSITY_LEVELS + B_EXTRA_DATA='true' + B_SHOW_DISK='true' + B_SHOW_PARTITIONS='true' + B_SHOW_AUDIO='true' + use_short='false' + ;; + G) B_SHOW_GRAPHICS='true' + use_short='false' + ;; + i) B_SHOW_IP='true' + B_SHOW_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' + ;; + N) B_SHOW_NETWORK='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' + ;; + s) B_SHOW_SENSORS='true' + use_short='false' + ;; + S) B_SHOW_SYSTEM='true' + use_short='false' + ;; + u) B_SHOW_UUIDS='true' + B_SHOW_PARTITIONS='true' + use_short='false' + ;; + v) if [[ -n $( egrep "^[0-9][0-9]?$" <<< $OPTARG ) && $OPTARG -le $VERBOSITY_LEVELS ]];then + VERBOSITY_LEVEL="$OPTARG" + if [[ $OPTARG -gt 0 ]];then + use_short='false' + fi + else + error_handler 4 "$OPTARG" + fi + ;; + U) script_self_updater "$SCRIPT_DOWNLOAD" 'svn server' + ;; + V) print_version_info + exit 0 + ;; + x) B_EXTRA_DATA='true' + ;; + h) show_options + exit 0 + ;; + H) show_options 'full' + exit 0 + ;; + ## debuggers and testing tools + %) B_HANDLE_CORRUPT_DATA='true' + ;; + @) if [[ -n $( egrep "^([1-9]|10)$" <<< $OPTARG ) ]];then + DEBUG=$OPTARG + exec 2>&1 + # switch on logging only for -@ 8-10 + if [[ $OPTARG -ge 8 ]];then + 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 + fi + 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' + ;; + 10) + script_self_updater "$SCRIPT_DOWNLOAD_DEV" 'dev server' + ;; + 11) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_1" 'svn: branch one server' + ;; + 12) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_2" 'svn: branch two server' + ;; + 13) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_3" 'svn: branch three server' + ;; + 14) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_4" 'svn: branch four server' + ;; + http*) + script_self_updater "$OPTARG" 'alt server' + ;; + *) 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 + eval $LOGFE +} + +## print out help menu, not including Testing or Debugger stuff because it's not needed +show_options() +{ + local color_scheme_count=${#A_COLOR_SCHEMES[@]} + + print_screen_output "$SCRIPT_NAME supports the following options. You can combine them, or list them" + print_screen_output "one by one: Examples: $SCRIPT_NAME -v4 -c6 OR $SCRIPT_NAME -dDc 6" + print_screen_output "" + print_screen_output "If you start $SCRIPT_NAME with no arguments, it will show the short form." + print_screen_output "The following options if used without -d or -v will show just that complete line:" + print_screen_output "A,C,D,G,I,N,P,S - you can use these together to show just the lines you want to see." + print_screen_output "If you use them with a -v level (or -d), it will show the full output for that line " + print_screen_output "along with the output for the chosen verbosity level." + print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -" + print_screen_output "Output Control Options:" + print_screen_output "-A Show Audio/sound card information." + print_screen_output "-c Available color schemes. Scheme number is required." + print_screen_output " Supported schemes: 0-$color_scheme_count Example: $SCRIPT_NAME -c 11" + print_screen_output "-C Show full CPU output, including per CPU clockspeed." + print_screen_output "-d Default output verbosity level, same as: $SCRIPT_NAME -v 1" + print_screen_output "-D Show full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB." + print_screen_output "-f Show all cpu flags used, not just the short list. Not shown with -F to avoid spamming." + print_screen_output "-F Show Full output for $SCRIPT_NAME. Does not show extra verbose options like -f -u -l or -p" + print_screen_output "-G Show Graphic card information (card, x type, resolution, glx renderer, version)." + print_screen_output "-i Show Wan IP address, and shows local interfaces (requires ifconfig network tool)." + print_screen_output " Not shown with -F for user security reasons, you shouldn't paste your local/wan IP." + print_screen_output "-I Show Information: processes, uptime, memory, irc client, inxi version." + print_screen_output "-l Show partition labels. Default: short partition -P. For full -p output, use: -pl (or -plu)." + print_screen_output "-N Show Network card information." + print_screen_output "-p Show full partition information (-P plus all other detected partitions)." + print_screen_output "-P Show Partition information (shows what -v 4 would show, but without extra data)." + print_screen_output " Shows, if detected: / /boot /home /tmp /usr /var. Use -p to see all mounted partitions." + print_screen_output "-s Show sensors output (if sensors installed/configured): mobo/cpu temp; detected fan speeds." + print_screen_output "-S Show System information: host name, kernel, distro" + print_screen_output "-u Show partition UUIDs. Default: short partition -P. For full -p output, use: -pu (or -plu)." + print_screen_output "-v Script verbosity levels. Verbosity level number is required." + print_screen_output " Supported levels: 0-${VERBOSITY_LEVELS} Example: $SCRIPT_NAME -v 4" + print_screen_output " 0 - short output, same as: $SCRIPT_NAME" + print_screen_output " 1 - basic verbose, same as: $SCRIPT_NAME -d" + print_screen_output " 2 - Also show networking card data" + print_screen_output " 3 - Also show hard disk names as detected." + print_screen_output " 4 - Also show partition size/filled data for (if present):/, /home, /var/, /boot" + print_screen_output " 5 - For multicore systems, also shows: per core clock speeds; audio card; full disk data." + print_screen_output "-x Show extra data: bogomips on Cpu; driver version (if available) for Network/Audio;" + print_screen_output " direct rendering status for Graphics (in X). Only works with verbose or line output." + print_screen_output " Shows hdd temp with disk data if you have hddtemp installed, if you are root OR if you have" + print_screen_output " added to /etc/sudoers (sudo v. 1.7 or newer) (path to hddtemp): <username> ALL = NOPASSWD: /usr/sbin/hddtemp" + print_screen_output "" + print_screen_output "Additional Options:" + print_screen_output "-h - this help menu." + if [[ $B_ALLOW_UPDATE == 'true' ]];then + print_screen_output "-U Auto-update script. Note: if you installed as root, you" + print_screen_output " must be root to update, otherwise user is fine." + fi + print_screen_output "-V $SCRIPT_NAME version information. Prints information then exits." + print_screen_output "-% Overrides defective or corrupted data." + print_screen_output "-@ Triggers debugger output. Requires debugging level 1-10 (8-10 - logging)." + print_screen_output " 8 - basic logging; 9 - full file/sys info logging; 10 - color logging." + if [[ $1 == 'full' ]];then + print_screen_output "" + print_screen_output "Developer and Testing Options (Advanced):" + print_screen_output "-! 1 - Sets testing flag B_TESTING_1='true' to trigger testing condition 1." + print_screen_output "-! 2 - Sets testing flag B_TESTING_2='true' to trigger testing condition 2." + print_screen_output "-! 3 - Sets flags B_TESTING_1='true' and B_TESTING_2='true'." + print_screen_output "-! 10 - Triggers an update from the primary dev download server instead of svn." + print_screen_output "-! 11 - Triggers an update from svn branch one - if present, of course." + print_screen_output "-! 12 - Triggers an update from svn branch two - if present, of course." + print_screen_output "-! 13 - Triggers an update from svn branch three - if present, of course." + print_screen_output "-! 14 - Triggers an update from svn branch four - if present, of course." + print_screen_output "-! <http://......> - Triggers an update from whatever server you list." + print_screen_output "" + fi + print_screen_output "" +} + +## print out version information for -V/--version +print_version_info() +{ + local last_modified=$( grep -im 1 'date:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3,$4,$5}' ) + + print_screen_output "$SCRIPT_NAME - the universal, portable, system info script for irc." + print_screen_output "Version: $SCRIPT_VERSION_NUMBER" + print_screen_output "Script Last Modified: $last_modified" + print_screen_output "Script Location: $SCRIPT_PATH" + print_screen_output "" + print_screen_output "Tested with Irssi, Xchat, Konversation, BitchX, KSirc, ircII," + print_screen_output "Gaim/Pidgin, Weechat, KVIrc and Kopete." + print_screen_output "" + print_screen_output "This script is a fork of Infobash 3.02, which is:" + print_screen_output "Copyright (C) 2005-2007 Michiel de Boer a.k.a. locsmif" + print_screen_output "Subsequent changes and modifications (after Infobash 3.02) are:" + print_screen_output "Copyright (C) 2008-9 Scott Rogers, Harald Hope, aka trash80 & h2" + print_screen_output "" + print_screen_output "This program is free software; you can redistribute it and/or modify" + print_screen_output "it under the terms of the GNU General Public License as published by" + print_screen_output "the Free Software Foundation; either version 3 of the License, or" + print_screen_output "(at your option) any later version." +} + +######################################################################## +#### MAIN FUNCTIONS +######################################################################## + +#### ------------------------------------------------------------------- +#### initial startup stuff +#### ------------------------------------------------------------------- + +# 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' + + if tty >/dev/null;then + IRC_CLIENT='Shell' + unset IRC_CLIENT_VERSION + B_RUNNING_IN_SHELL='true' + elif [[ -n $PPID && -f /proc/$PPID/exe ]];then + irc_client_path=$( readlink /proc/$PPID/exe ) + irc_client_path_lower=$( tr '[:upper:]' '[:lower:]' <<< $irc_client_path ) + app_working_name=$( basename $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 + bash|dash|sh|perl*) # We want to know who wrapped it into the shell or perl. + pppid="$( ps -p $PPID -o ppid --no-headers | sed 's/ //g' )" + if [[ -n $pppid && -f /proc/$pppid/exe ]];then + irc_client_path="$( readlink /proc/$pppid/exe )" + irc_client_path_lower="$( tr '[:upper:]' '[:lower:]' <<< $irc_client_path )" + app_working_name=$( basename $irc_client_path_lower ) + b_non_native_app='true' + fi + ;; + esac + # 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 + }' )" + IRC_CLIENT="BitchX" + ;; + finch) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="Finch" + ;; + gaim) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="Gaim" + ;; + ircii) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $3 + }' )" + IRC_CLIENT="ircII" + ;; + irssi-text|irssi) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + 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" " + } + } + 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" " + } + } + exit + }' )" + IRC_CLIENT="KVIrc" + ;; + pidgin) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="Pidgin" + ;; + quassel*) + # sample: quassel -v + # Qt: 4.5.0 + # 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 + IRC_CLIENT_VERSION=" $( $irc_client_path -v 2>/dev/null | gawk -F ': ' ' + BEGIN { + IGNORECASE=1 + clientVersion="" + } + /Quassel IRC/ { + 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 + ;; + weechat-curses) + IRC_CLIENT_VERSION=" $( $irc_client_path -v ) " + 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 + if [[ -z $IRC_CLIENT_VERSION ]];then + IRC_CLIENT="Unknown Perl client" + fi + ;; + # 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 + 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 + 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 + IRC_CLIENT="PPID=\"$PPID\" - empty?" + unset IRC_CLIENT_VERSION + fi + fi + log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID" + eval $LOGFE +} + +## try to infer the use of Konversation >= 1.2, which shows $PPID improperly +## no known method of finding Kovni >= 1.2 as parent process, so we look to see if it is running, +## and all other irc clients are not running. +is_this_qt4_konvi() +{ + local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir='' + local konvi='' konvi_qt4_ver='' b_is_qt4='' + + konvi_dbus_exist=$( qdbus | grep "org.kde.konversation" ) + + if [[ -n $konvi_dbus_exist && -e /usr/share/kde4/apps/konversation ]]; then + + konvi_pid=$( ps -A | grep -i 'konversation' ) + konvi_pid=$( echo $konvi_pid | gawk '{ 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 + konvi_qt4_ver=$( konversation -v | grep -i 'konversation' ) + konvi_qt4_client=$( echo "$konvi_qt4_ver" | gawk '{ print $2 }' ) + + if [[ $konvi_qt4_client > 1.1 ]]; then + b_is_qt4='true' + fi + fi + else + konvi_qt4="qt3" + b_is_qt4='false' + fi + + echo $b_is_qt4 + ## 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]}" +} + +# 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 + ## 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 +} + +#### ------------------------------------------------------------------- +#### get data types +#### ------------------------------------------------------------------- +## 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='' alsa_driver='' device_count='' + local usb_proc_file='' array_count='' usb_id='' usb_data='' + + IFS=$'\n' + # this first step handles the drivers for cases where the second step fails to find one + device_count=$( echo "$Lspci_Data" | egrep -ic '(multimedia audio controller|audio device)' ) + if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_CARDS == 'true' ]];then + alsa_driver=$( gawk -F ']: ' ' + BEGIN { + IGNORECASE=1 + } + # 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/ || $0 !~ /usb/ { + 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. + alsa_driver=$( echo $alsa_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_Data" | gawk -F ': ' -v alsaDriver="$alsa_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(/,/, " ", audioCard) + gsub(/^ +| +$/, "", audioCard) + gsub(/ [ \t]+/, " ", audioCard) + + cards[audioCard]++ + + # loop until you get to the end of the data block + while (getline && !/^$/) { + 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 (/I\/O/) { + portsTemp = gensub(/\t*I\/O ports at (.*) \[.*\]/,"\\1","g",$0) + ports[audioCard] = ports[audioCard] portsTemp " " + } + } + } + + END { + j=0 + for (i in cards) { + useDrivers="" + useModules="" + usePorts="" + if (cards[i]>1) { + a[j]=cards[i]"x "i + if (drivers[i] != "") { + useDrivers=drivers[i] + } + if (ports[i] != "") { + usePorts = ports[i] + } + if (modules[i] != "" ) { + useModules = modules[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] + } + else if ( alsaDriver != "" ) { + useDrivers=alsaDriver + } + if (ports[i] != "") { + usePorts=ports[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + # create array primary item for master array + print a[j] "," useDrivers "," usePorts "," useModules + j++ + } + }') ) + + # in case of failure of first check do this instead + if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_CARDS == 'true' ]];then + A_AUDIO_DATA=( $( gawk -F ']: ' ' + BEGIN { + IGNORECASE=1 + } + $1 !~ /modem/ && $2 !~ /modem/ { + card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 ) + driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 ) + if ( card != "" ){ + print card","driver + } + }' $FILE_ASOUND_DEVICE ) ) + fi + + # alsa usb detection by damentz + # for every sound card symlink in /proc/asound - display information about it + for usb_proc_file in /proc/asound/* + do + # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue + if [[ -n $( which lsusb ) && -L $usb_proc_file && -e $usb_proc_file/usbid ]]; then + # send error messages of lsusb to /dev/null as it will display a bunch if not a super user + # 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 :) + usb_id=$( cat $usb_proc_file/usbid ) + usb_data=$( lsusb -v 2>/dev/null | grep "$usb_id" ) + log_function_data 'raw' "usb_data:\n$usb_data" + usb_data=$( gawk '{ + gsub( /,/, " ", $0 ) + for( i=7; i <= NF; i++ ) { + printf( $i " " ) + } + }' <<< "$usb_data" ) + # this method is interesting, it shouldn't work but it does + #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,snd-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,snd-usb-audio,," + fi + fi + done + IFS="$ORIGINAL_IFS" + + # 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 + log_function_data "A_AUDIO_DATA: ${A_AUDIO_DATA[@]}" + eval $LOGFE +} + +get_audio_alsa_data() +{ + eval $LOGFS + local alsa_data='' + + # now we'll get the alsa data if the file exists + if [[ $B_ASOUND_VERSION == 'true' ]];then + alsa_data=$( gawk ' + BEGIN { + IGNORECASE=1 + } + # 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(/,/, " ", $0) + gsub(/^ +| +$/, "", $0) + gsub(/ [ \t]+/, " ", $0) + if ( $0 != "" ){ + print $0 + } + }' $FILE_ASOUND_VERSION ) + log_function_data 'cat' "$FILE_ASOUND_VERSION" + fi + echo "$alsa_data" + log_function_data "alsa_data: $alsa_data" + 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 + if [[ $B_CPUINFO == '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 + local cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]} + local cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]} + local cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]} + + # match the numberic value to an alpha value + case $cpu_core_count in + 1) cpu_alpha_count='Single';; + 2) cpu_alpha_count='Dual';; + 3) cpu_alpha_count='Triple';; + 4) cpu_alpha_count='Quad';; + 5) cpu_alpha_count='Penta';; + 6) cpu_alpha_count='Hexa';; + 7) cpu_alpha_count='Hepta';; + 8) cpu_alpha_count='Octa';; + 9) cpu_alpha_count='Ennea';; + 10) cpu_alpha_count='Deca';; + *) cpu_alpha_count='Multi';; + esac + # create array, core count integer; core count string + # A_CPU_CORE_DATA=( "$cpu_core_count" "$cpu_alpha_count Core$cpu_type" ) + A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" ) + fi + log_function_data "A_CPU_CORE_DATA: ${A_CPU_CORE_DATA[@]}" + eval $LOGFE +} + +## main cpu data collector +get_cpu_data() +{ + eval $LOGFS + local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' + + if [[ $B_CPUINFO == 'true' ]];then + IFS=$'\n' + A_CPU_DATA=( $( gawk -F': ' ' + BEGIN { + IGNORECASE=1 + } + # 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]+:/ { + nr = $NF + } + + /^model name|^cpu\t+:/ { + gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF ) + gsub(/'"$BAN_LIST_CPU"'/, "", $NF ) + gsub(/,/, " ", $NF) + gsub(/^ +| +$/, "", $NF) + gsub(/ [ \t]+/, " ", $NF) + cpu[nr, "model"] = $NF + } + + /^cpu MHz|^clock\t+:/ { + if (!min) { + min = $NF + } + else { + if ($NF < min) { + min = $NF + } + } + + if ($NF > max) { + max = $NF + } + 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 + } + + /^flags/ { + cpu[nr, "flags"] = $NF + } + + /^bogomips/ { + cpu[nr, "bogomips"] = $NF + } + + /vendor_id/ { + gsub(/genuine|authentic/,"",$NF) + cpu[nr, "vendor"] = tolower( $NF ) + } + + END { + #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that + for ( i = 0; i <= nr; i++ ) { + print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] "," cpu[nr, "vendor"] + } + if (!min) { + print "not found" + exit + } + if (min != max) { + printf("Min:%s%s Max:%s%s\n", min, "Mhz", max, "Mhz") + } + else { + printf("%s %s\n", max, "Mhz") + } + }' $FILE_CPUINFO ) ) + log_function_data 'cat' "$FILE_CPUINFO" + fi + + IFS="$ORIGINAL_IFS" + log_function_data "A_CPU_DATA: ${A_CPU_DATA[@]}" + eval $LOGFE +# echo getMainCpu: ${[@]} +} + +## this is for counting processors and finding HT types +get_cpu_ht_multicore_smp_data() +{ + eval $LOGFS + # in /proc/cpuinfo + # algorithm + # if > 1 processor && processor id (physical id) == core id then Hyperthreaded (HT) + # if > 1 processor && different processor ids then Multiple Processors (SMP) + # if > 1 processor && processor id != core id then Multi-Core Processors (MCP) + # if = 1 processor then single core/processor Uni-Processor (UP) + + if [[ $B_CPUINFO == 'true' ]]; then + A_CPU_TYPE_PCNT_CCNT=( $( + gawk ' + BEGIN { + FS=": " + IGNORECASE = 1 + core_count = 0 + i = 0 + index_temp = "" + num_of_cores = 0 + physical_cpu_count = 0 + processor_logical_count = 0 + processors = 1 + type = "UP" + } + # counts logical processors, both HT and physical + /^processor/ { + processor_logical_count = $NF + 1 + } + # counts physical cores (not used currently) + /^cpu cores/ { + num_of_cores = $NF + } + # array of physical cpus ids + /^physical/ { + a_physical_id[i] = $NF + } + # array of core ids + /^core id/ { + a_core_id[i] = $NF + i++ + } + END { + # look for the largest id number, and assign it + for ( j = 0; j < processor_logical_count; j++ ) { + if ( a_core_id[j] > core_count ) { + core_count = a_core_id[j] + } + } + core_count = core_count + 1 + # trick, set the index equal to value, if the same, it will overwrite + # this lets us create the actual array of true cpu physical ids + for ( j in a_physical_id ) { + index_temp = a_physical_id[j] + a_cpu_physical_working[index_temp] = a_physical_id[j] + } + # note that length() is a gawk >= 3.1.5 only method, better to do it manually + for ( j in a_cpu_physical_working ) { + ++physical_cpu_count + } + + # looking at logical processor counts over 1, which means either HT, SMP or MCP + # http://en.wikipedia.org/wiki/Symmetric_multiprocessing + if ( processor_logical_count > 1 && core_count > 1 ) { + if ( processor_logical_count > core_count && physical_cpu_count > 1 ) { + type = "SMP-HT" # could be Xeon/P4 HT dual cpu + } + else if ( processor_logical_count > core_count ) { + type = "HT" # this is more than likely a P4 w/HT or an Atom 270 + } + else { + type = "SMP" + } + } + # make sure to handle up cpus too + else { + core_count = 1 + physical_cpu_count = 1 + } + print type " " physical_cpu_count " " core_count + } + ' $FILE_CPUINFO ) ) + fi + log_function_data "A_CPU_TYPE_PCNT_CCNT: ${A_CPU_TYPE_PCNT_CCNT[@]}" + 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='' + + # get the wild carded array of release/version /etc files if present + shopt -s nullglob + cd /etc + a_distro_glob=(*[-_]{release,version}) + cd "$OLDPWD" + shopt -u nullglob + + 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 script_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_DIR == 'true' ]];then + distro_file='lsb-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="$( egrep -oi '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 && -f $FILE_LSB_RELEASE && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then + distro=$( get_distro_lsb_data ) + elif [[ $distro_file == 'lsb-release' ]];then + distro=$( get_distro_lsb_data ) + # 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 + distro=$( remove_erroneous_chars "/etc/$distro_file" ) + # otherwise try the default debian/ubuntu /etc/issue file + elif [[ -f /etc/issue ]];then + # 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_LSB_DIR == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then + distro=$( get_distro_lsb_data ) + else + distro=$( gawk ' + BEGIN { + RS="" + } + { + gsub(/\\[a-z]/, "") + gsub(/,/, " ") + gsub(/^ +| +$/, "") + gsub(/ [ \t]+/, " ") + print + }' /etc/issue ) + fi + fi + + if [[ ${#distro} -gt 80 ]] && [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then + distro="${RED}/etc/${distro_file} corrupted, use -% to override${NORMAL}" + 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 + if [[ -z $distro ]] && [[ $B_LSB_DIR == 'true' ]];then + distro=$( get_distro_lsb_data ) + fi + ## finally, if all else has failed, give up + if [[ -z $distro ]];then + distro='Unknown distro o_O' + fi + + # this handles an arch bug where /etc/arch-release is empty and /etc/issue is corrupted + if [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then + distro='Arch Linux' + fi + + echo "$distro" + log_function_data "distro: $distro" + eval $LOGFE +} + +# args: $1 - optional, app, uses the app test, not being used now +get_distro_lsb_data() +{ + eval $LOGFS + local distro='' + + if [[ $B_LSB_DIR == 'true' ]] && [[ $1 != 'app' ]];then + distro=$( gawk -F '=' ' + BEGIN { + IGNORECASE=1 + } + # note: adding the spacing directly to variable to make sure distro output is null if not found + /^DISTRIB_ID/ { + gsub(/^ +| +$/, "", $NF) + # this is needed because grep for "arch" is too loose to be safe + if ( $NF == "arch" ) { + distroId = "Arch Linux" + } + else if ( $NF != "n/a" ) { + distroId = $NF " " + } + } + /^DISTRIB_RELEASE/ { + gsub(/^ +| +$/, "", $NF) + if ( $NF != "n/a" ) { + distroRelease = $NF " " + } + } + /^DISTRIB_CODENAME/ { + gsub(/^ +| +$/, "", $NF) + if ( $NF != "n/a" ) { + distroCodename = $NF " " + } + } + END { + print distroId distroRelease distroCodename + }' $FILE_LSB_RELEASE ) + log_function_data 'cat' "$FILE_LSB_RELEASE" + fi + # this is HORRIBLY slow, but I don't know why, it runs fast in shell +# if [[ -n $( which lsb_release ) && $1 == 'app' ]];then +# distro=$( echo "$( lsb_release -irc )" | gawk ' +# { IGNORECASE=1 } +# /^Distributor ID/ { +# gsub(/^ +| +$/, "", $NF) +# distroId = $NF +# } +# /^Release/ { +# gsub(/^ +| +$/, "", $NF) +# distroRelease = $NF +# } +# /^Codename/ { +# gsub(/^ +| +$/, "", $NF) +# distroCodename = $NF +# } +# END { +# print distroId " " distroRelease " (" distroCodename ")" +# }' ) +# fi + + echo $distro + log_function_data "distro: $distro" + eval $LOGFE +} + +get_gpu_temp_data() +{ + local gpu_temp='' gpu_fan='' + + # we'll try for nvidia/ati, then add if more are shown + if [[ -n $( type -p nvidia-settings ) ]];then + gpu_temp=$( nvidia-settings -q GPUCoreTemp | gawk -F ': ' ' + BEGIN { + IGNORECASE=1 + gpuTemp="" + gpuTempWorking="" + } + /Attribute (.*)[0-9]+\.$/ { + gsub(/\./, "", $2) + if ( $2 ~ /^[0-9]+$/ ) { + gpuTemp=gpuTemp $2 "C " + } + } + END { + print gpuTemp + }' + ) + elif [[ -n $( type -p aticonfig ) ]];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 + }' + ) + fi + + if [[ -n $gpu_temp ]];then + echo $gpu_temp + fi +} + +## create array of gfx cards installed on system +get_graphics_card_data() +{ + eval $LOGFS + local i='' + + IFS=$'\n' + A_GFX_CARD_DATA=( $( echo "$Lspci_Data" | gawk -F': ' ' + BEGIN { + IGNORECASE=1 + } + /vga compatible controller/ { + gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF) + gsub(/,/, " ", $NF) + gsub(/^ +| +$/, "", $NF) + gsub(/ [ \t]+/, " ", $NF) + print $NF + }' ) ) + IFS="$ORIGINAL_IFS" +# for (( i=0; i < ${#A_GFX_CARD_DATA[@]}; i++ )) +# do +# A_GFX_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GFX_CARD_DATA[i]}" ) +# done + # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes.. + if [[ ${#A_GFX_CARD_DATA[@]} -eq 0 ]];then + A_GFX_CARD_DATA[0]='Failed to Detect Video Card!' + fi + + # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory.. + # GFXMEM="size=[$(echo "$Lspci_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]" + log_function_data "A_GFX_CARD_DATA: ${A_GFX_CARD_DATA[@]}" + eval $LOGFE +} + +## create array of glx data +get_graphics_glx_data() +{ + eval $LOGFS + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + IFS=$'\n' + A_GLX_DATA=( $( glxinfo | gawk -F ': ' ' + # note: function declarations go before BEGIN? It appears so, confirm. + # the real question here though is why this function is even here, seems + # just to be a complicated way to pack/print a variable, but maybe the + # original idea was to handle > 1 cases of detections I guess + 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 + } + /opengl renderer/ { + if ( $2 ~ /mesa/ ) { + # Allow all mesas +# if ( $2 ~ / r[3-9][0-9][0-9] / ) { + gsub(/'"$BAN_LIST_NORMAL"'/, "", $2) + a[$2] + # this counter failed in one case, a bug, and is not needed now +# f++ +# } + next + } + $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/ { + $2 && b[$2] + } + /direct rendering/ { + $2 && c[$2] + } + END { + printf( "%s\n%s\n%s\n", join( a, ", " ), join( b, ", " ), join( c, ", " ) ) + }' ) ) + 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 + log_function_data "A_GLX_DATA: ${A_GLX_DATA[@]}" + eval $LOGFE +} + +## return screen resolution / tty resolution +get_graphics_res_data() +{ + eval $LOGFS + local screen_resolution='' + + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];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 + screen_resolution=$( xrandr | 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 (line) { + print(line) + } + }' ) + if [[ -z $screen_resolution ]];then + screen_resolution=$( xdpyinfo | gawk ' + /dimensions/ { + print $2 + }' ) + fi + else + screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{ + print $2"x"$1 + }' ) + fi + echo "$screen_resolution" + log_function_data "screen_resolution: $screen_resolution" + eval $LOGFE +} + +## for possible future data, not currently used +get_graphics_agp_data() +{ + eval $LOGFS + local agp_module='' + + if [[ $B_MODULES_DIR == '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 x vendor/version data +get_graphics_x_data() +{ + eval $LOGFS + local x_vendor='' x_version='' + + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + # X vendor and version detection. + x_vendor=$( xdpyinfo | gawk -F': +' ' + BEGIN { + IGNORECASE=1 + } + /vendor string/ { + gsub(/the|inc|foundation|project|corporation/, "", $2) + gsub(/,/, " ", $2) + gsub(/^ +| +$/, "", $2) + gsub(/ [ \t]+/, " ", $2) + print $2 + }' ) + + # 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 $x_version is empty, the release number is parsed instead) + x_version=$( xdpyinfo | gawk ' + /version:/ { + print $NF + }' ) + if [[ -z $x_version ]];then + x_version=$(xdpyinfo | gawk -F': +' ' + BEGIN { + IGNORECASE=1 + } + /vendor release number/ { + gsub(/0+$/, "", $2) + gsub(/0+/, ".", $2) + print $2 + }' ) + fi + A_X_DATA[0]="$x_vendor" + A_X_DATA[1]="$x_version" + + #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }' + #This method could be used in the future to detect X when X is not running, + #however currently inxi ignores X checks when X is not found. + fi + log_function_data "A_X_DATA: ${A_X_DATA[@]}" + eval $LOGFE +} + +# this gets just the raw data, total space/percent used and disk/name/per disk capacity +get_hdd_data_basic() +{ + eval $LOGFS + local hdd_used='' + local hdd_data="$( df --exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660 )" + log_function_data 'raw' "hdd_data:\n$hdd_data" + + hdd_used=$( echo "$hdd_data" | gawk ' + # also handles odd dm-1 type, from lvm + /^\/dev\/(mapper\/|[hs]d[a-z][0-9]+|dm[-]?[0-9]+)/ { + # 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 + if ( NF < 5 && $0 !~ /.*\%/ ) { + 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. + if ( $4 ~ /.*\%/ ) { + used += $2 + } + # otherwise use standard + else if ( $5 ~ /.*\%/ ) { + used += $3 + } + # and if this is not detected, give up, we need user data to debug + else { + next + } + } + END { + print 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_DIR == 'true' ]];then + A_HDD_DATA=( $( + gawk -v hddused="$hdd_used" ' + /[hs]d[a-z]$/ { + driveSize = $(NF - 1)*1024/1000**3 + gsub(/,/, " ", driveSize) + gsub(/^ +| +$/, "", driveSize) + printf( $NF",%.1fGB,,\n", driveSize ) + } + # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below + # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0 { + # size += $3 + # } + # special case from this data: 8 0 156290904 sda + $1 ~ /^(3|22|33|8)$/ && $NF ~ /[hs]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 ) + size = sprintf( "%.1f", size ) + print size "GB," diskUsed "% used" + } + 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" + fi + IFS="$ORIGINAL_IFS" + log_function_data "A_HDD_DATA: ${A_HDD_DATA[@]}" + 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='' + + ## check for all ide type drives, non libata, only do it if hdx is in array + if [[ -n $( egrep '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 [[ -n $( egrep '^hd[a-z]' <<< ${a_temp_working[0]} ) ]];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]="Name n/a" + 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_DIR == '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(/,/, " ", 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 $( egrep 'sd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then + # first pack the main ls variable so we don't have to keep using ls /dev... + ls_disk_by_id="$( ls -l /dev/disk/by-id )" + for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ )) + do + if [[ -n $( egrep '^sd[a-z]' <<< ${A_HDD_DATA[$i]} ) ]];then + IFS="," + a_temp_working=( ${A_HDD_DATA[$i]} ) + IFS="$ORIGINAL_IFS" + if [[ ${#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=$( tr ' ' '_' <<< ${a_temp_scsi[$j]} | cut -d '-' -f 1 ) + sd_ls_by_id=$( egrep -m1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" ) + + if [[ -n $sd_ls_by_id ]];then + a_temp_working[2]=${a_temp_scsi[$j]} + if [[ -n $( grep 'usb-' <<< $sd_ls_by_id ) ]];then + a_temp_working[3]='USB' + fi + break + else + # test to see if we can get a better name output when null + if [[ -n $temp_name ]];then + a_temp_working[2]=$temp_name + else + a_temp_working[2]="Name n/a" + fi + fi + done + else + a_temp_working[2]="Name n/a" + 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 + unset ls_disk_by_id # and then let's dump the data we don't need + fi + log_function_data "A_HDD_DATA: ${A_HDD_DATA[@]}" + eval $LOGFE +} + +# 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() +{ + local hdd_temp='' sudo_command='' + + if [[ -n $( which hddtemp ) && -n $1 ]];then + # 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 $( which sudo ) ]];then + sudo_command='sudo -n ' + fi + # 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 -nq -u C $1 ) + if [[ -n $hdd_temp && -n $( grep -E '^([0-9]+)$' <<< $hdd_temp ) ]];then + echo $hdd_temp + fi + fi +} + +get_lspci_data() +{ + eval $LOGFS + local lspci_data="$( lspci -v | gawk '{ + gsub(/\(prog-if[^)]*\)/,"") + print + }' )" + + echo "$lspci_data" + log_function_data 'raw' "lspci_data:\n$lspci_data" + eval $LOGFE +} + +## return memory used/installed +get_memory_data() +{ + eval $LOGFS + local memory='' + if [[ $B_MEMINFO == '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" + fi + echo "$memory" + log_function_data "memory: $memory" + eval $LOGFE +} + +# process and return module version data +get_module_version_number() +{ + eval $LOGFS + local module_version='' + + if [[ -n $( which modinfo ) ]];then + module_version=$( modinfo $1 | gawk ' + BEGIN { + IGNORECASE=1 + } + /^version/ { + gsub(/,/, " ", $2) + gsub(/^ +| +$/, "", $2) + gsub(/ [ \t]+/, " ", $2) + print $2 + } + ' ) + fi + + echo "$module_version" + log_function_data "module_version: $module_version" + eval $LOGFE +} + +## create array of network cards +get_networking_data() +{ + eval $LOGFS + IFS=$'\n' + A_NETWORK_DATA=( $( echo "$Lspci_Data" | gawk ' + BEGIN { + IGNORECASE=1 + } + /^[0-9a-f:.]+ (ethernet|network) (controller|bridge)/ || /^[0-9a-f:.]+ [^:]+: .*(ethernet|network).*$/ { + nic=gensub(/^[0-9a-f:.]+ [^:]+: (.+)$/,"\\1","g",$0) + gsub(/realtek semiconductor/, "Realtek", nic) + gsub(/davicom semiconductor/, "Davicom", nic) + # The doublequotes are necessary because of the pipes in the variable. + gsub(/'"$BAN_LIST_NORMAL"'/, "", nic) + gsub(/,/, " ", nic) + gsub(/^ +| +$/, "", nic) + gsub(/ [ \t]+/, " ", nic) + + eth[nic]++ + while (getline && !/^$/) { + if (/I\/O/) { + ports[nic] = ports[nic] $4 " " + } + if (/driver in use/) { + drivers[nic] = drivers[nic] gensub(/(.*): (.*)/,"\\2","g",$0) "" + } + else if (/kernel modules/) { + modules[nic] = modules[nic] gensub(/(.*): (.*)/,"\\2","g",$0) "" + } + } + } + + END { + j=0 + for (i in eth) { + useDrivers="" + usePorts="" + useModules="" + if (eth[i]>1) { + a[j]=eth[i]"x "i + ## note: this loses the plural ports case, is it needed anyway? + if (ports[i] != "") { + usePorts=ports[i] + } + if (drivers[i] != "") { + useDrivers=drivers[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + else { + a[j]=i + if (ports[i] != "") { + usePorts=ports[i] + } + if (drivers[i] != "") { + useDrivers=drivers[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + # create array primary item for master array + print a[j] "," useDrivers "," usePorts "," useModules + j++ + } + }') ) + IFS="$ORIGINAL_IFS" + log_function_data "A_NETWORK_DATA: ${A_NETWORK_DATA[@]}" + eval $LOGFE +} + +get_networking_wan_ip_data() +{ + eval $LOGFS + local ip='' + + # get ip using wget redirect to stdout. This is a clean, text only IP output url. + ip=$( wget -q -O - http://smxi.org/opt/ip.php | gawk -F 'is: ' '{ + #gsub("\n","",$2") + print $2 + }' ) + + if [[ -z $ip ]];then + ip='None Detected!' + fi + echo "$ip" + log_function_data "ip: $ip" + eval $LOGFE +} + +get_networking_local_ip_data() +{ + eval $LOGFS + if [[ $B_IFCONFIG == 'true' ]];then + IFS=$'\n' + A_INTERFACES_DATA=( $( ifconfig | gawk ' + BEGIN { + IGNORECASE=1 + } + $0 !~ /^lo/ { + # not clear on why inet is coming through, but this gets rid of it + # as first line item. + interface = $1 + gsub(/,/, " ", interface) + gsub(/^ +| +$/, "", interface) + gsub(/ [ \t]+/, " ", interface) + + aInterfaces[interface]++ + while (getline && !/^$/) { + if (/inet addr:/) { + ipAddresses[interface] = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 ) + } + } + } + + END { + j=0 + for (i in aInterfaces) { + useInterfaceIp = "" + a[j] = i + if (ipAddresses[i] != "") { + useInterfaceIp = 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 ( useInterfaceIp != "" ) { + print a[j] "," useInterfaceIp + } + j++ + } + }') ) + IFS="$ORIGINAL_IFS" + fi + log_function_data "A_INTERFACES_DATA: ${A_INTERFACES_DATA[@]}" + eval $LOGFE +} + +get_partition_data() +{ + eval $LOGFS + #local excluded_file_types='--exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660' + # df doesn't seem to work in script with variables like at the command line + local main_partition_data="$( df -h -T --exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660 )" + local swap_data="$( swapon -s )" + log_function_data 'raw' "main_partition_data:\n$main_partition_data\n\nswap_data:\n$swap_data" + + IFS=$'\n' + # sample line: /dev/sda2 ext3 15G 8.9G 4.9G 65% /home + # $NF = partition name; $(NF - 4) = partition size; $(NF - 3) = used, in gB; $(NF - 1) = percent used + ## note: by subtracting from the last field number NF, we avoid a subtle issue with LVM df output, where if + ## the first field is too long, it will occupy its own line, this way we are getting only the needed data + A_PARTITION_DATA=( $( echo "$main_partition_data" | gawk ' + BEGIN { + IGNORECASE=1 + } + # this has to be nulled for every iteration so it does not retain value from last iteration + devBase="" + # this is required because below we are subtracting from NF, so it has to be > 4 + # the real issue is long file system names that force the wrap of df output: //fileserver/main + # but we still need to handle more dynamically long space containing file names, but later. + ( NF < 5 ) && ( $0 !~ /[0-9]+\%/ ) { + # set the dev location here for cases of wrapped output + if ( NF == 1 ){ + devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 ) + } + getline + } + # this handles yet another fredforfaen special case where a mounted drive + # has the search string in its name + $NF ~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$/ { + print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",main," devBase + } + # skip all these, including the first, header line. Use the --exclude-type + # to handle new filesystems types we do not want listed here + $NF !~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$|^filesystem/ { + # this is to avoid file systems with spaces in their names, that will make + # the test show the wrong data in each of the fields, if no x%, then do not use + # using 3 cases, first default, standard, 2nd, 3rd, handles one and two spaces in name + if ( $(NF - 1) ~ /[0-9]+\%/ ) { + print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",secondary," devBase + } + # these two cases construct the space containing name + else if ( $(NF - 2) ~ /[0-9]+\%/ ) { + print $(NF - 1) " " $NF "," $(NF - 5) "," $(NF - 4) "," $(NF - 2) ",secondary," devBase + } + else if ( $(NF - 3) ~ /[0-9]+\%/ ) { + print $(NF - 2) " " $(NF - 1) " " $NF "," $(NF - 6) "," $(NF - 5) "," $(NF - 3) ",secondary," devBase + } + } + ' ) + # now add the swap partition data, don't want to show swap files, just partitions, + # though this can include /dev/ramzswap0. Note: you can also use /proc/swaps for this + # data, it's the same exact output as swapon -s + $( echo "$swap_data" | gawk ' + BEGIN { + swapCounter = 1 + } + /^\/dev/ { + size = sprintf( "%.2f", $3*1024/1000**3 ) + devBase = gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 ) + used = sprintf( "%.2f", $4*1024/1000**3 ) + percentUsed = sprintf( "%.0f", ( $4/$3 )*100 ) + print "swap-" swapCounter "," size "GB," used "GB," percentUsed "\%,main," devBase + swapCounter = ++swapCounter + }' ) ) + IFS="$ORIGINAL_IFS" + + if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then + get_partition_data_advanced + fi + log_function_data "A_PARTITION_DATA: ${A_PARTITION_DATA[@]}" + eval $LOGFE +} + +# first get the locations of the mount points for label/uuid detection +get_partition_data_advanced() +{ + eval $LOGFS + local a_partition_working='' dev_partition_data='' + local dev_disk_label='' dev_disk_uuid='' dev_item='' dev_label='' dev_uuid='' + local mount_point='' + + if [[ -d /dev/disk/by-label ]];then + dev_disk_label="$( ls -l /dev/disk/by-label )" + fi + if [[ -d /dev/disk/by-uuid ]];then + dev_disk_uuid="$( ls -l /dev/disk/by-uuid )" + fi + log_function_data 'raw' "dev_disk_label:\n$dev_disk_label\n\ndev_disk_uuid:\n$dev_disk_uuid" + + if [[ $B_MOUNTS_DIR == 'true' ]];then + for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ )) + do + IFS="," + a_partition_working=( ${A_PARTITION_DATA[i]} ) + IFS="$ORIGINAL_IFS" + # note: for swap this will already be set + if [[ -z ${a_partition_working[5]} ]];then + mount_point=$( sed 's|/|\\/|g' <<< ${a_partition_working[0]} ) + #echo mount_point $mount_point + dev_partition_data=$( gawk ' + BEGIN { + IGNORECASE = 1 + partition = "" + partTemp = "" + } + # trying to handle space in name +# gsub( /\\040/, " ", $0 ) + /[ \t]'$mount_point'[ \t]/ && $1 != "rootfs" { + # initialize the variables + label = "" + uuid = "" + + # slice out the /dev + partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 ) + # label and uuid can occur for root, set partition to null now + if ( partition ~ /by-label/ ) { + label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, $1 ) + partition = "" + } + if ( partition ~ /by-uuid/ ) { + uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, $1 ) + partition = "" + } + + # handle /dev/root for / id + if ( partition == "root" ) { + # if this works, great, otherwise, just set this to null values + partTemp="'$( readlink /dev/root 2>/dev/null )'" + if ( partTemp != "" ) { + if ( partTemp ~ /[hs]d[a-z][0-9]/ ) { + partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, partTemp ) + } + else if ( partTemp ~ /by-uuid/ ) { + uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, partTemp ) + partition="" # set null to let real location get discovered + } + else if ( partTemp ~ /by-label/ ) { + label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, partTemp ) + partition="" # set null to let real location get discovered + } + } + else { + partition = "" + label = "" + uuid = "" + } + } + print partition "," label "," uuid + }' $FILE_MOUNTS ) + +# echo dev_partition_data: $dev_partition_data + # assemble everything we could get for dev/h/dx, label, and uuid + IFS="," + A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","$dev_partition_data + IFS="$ORIGINAL_IFS" + fi + ## now we're ready to proceed filling in the data + IFS="," + a_partition_working=( ${A_PARTITION_DATA[i]} ) + IFS="$ORIGINAL_IFS" + + dev_item=${a_partition_working[5]} + dev_label=${a_partition_working[6]} + dev_uuid=${a_partition_working[7]} + + # then if dev data/uuid is incomplete, try to get missing piece + # it's more likely we'll get a uuid than a label. But this should get the + # dev item set no matter what, so then we can get the rest of any missing data + # first we'll get the dev_item if it's missing + if [[ -n $dev_disk_uuid ]] && [[ -z $dev_item && -n $dev_uuid ]];then + dev_item=$( echo "$dev_disk_uuid" | gawk ' + /'$dev_uuid'/ { + item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF ) + print item + }' ) + elif [[ -n $dev_disk_label ]] && [[ -z $dev_item && -n $dev_label ]];then + dev_item=$( echo "$dev_disk_label" | gawk ' + # first we need to change space x20 in by-label back to a real space + #gsub( /x20/, " ", $0 ) + # then we can see if the string is there + /'$dev_label'/ { + item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF ) + print item + }' ) + fi + if [[ -n $dev_disk_uuid ]] && [[ -n $dev_item && -z $dev_uuid ]];then + dev_uuid=$( echo "$dev_disk_uuid" | gawk ' + /'$dev_item'$/ { + print $(NF - 2) + }' ) + fi + if [[ -n $dev_disk_label ]] && [[ -n $dev_item && -z $dev_label ]];then + dev_label=$( echo "$dev_disk_label" | gawk ' + /'$dev_item'/ { + print $(NF - 2) + }' ) + + fi + # assemble everything we could get for dev/h/dx, label, and uuid + IFS="," + A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","$dev_item","$dev_label","$dev_uuid + IFS="$ORIGINAL_IFS" + done + log_function_data 'cat' "$FILE_MOUNTS" + fi + log_function_data "A_PARTITION_DATA: ${A_PARTITION_DATA[@]}" + eval $LOGFE +} + +get_sensors_data() +{ + eval $LOGFS + + IFS=$'\n' + if [[ $B_SENSORS == 'true' ]];then + # note: non-configured sensors gives error message, which we need to redirect to stdout + # also, -F ':' no space, since some cases have the data starting right after,like - :1287 + A_SENSORS_DATA=( $( + sensors | gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" ' + BEGIN { + IGNORECASE=1 + core0Temp="" # only if all else fails... + cpuTemp="" + cpuTempReal="" + fanWorking="" + indexCountaFanMain=0 + indexCountaFanDefault=0 + i="" + j="" + moboTemp="" + moboTempReal="" + psuTemp="" + separator="" + sysFanString="" + temp1="" + temp2="" + tempFanType="" # set to 1 or 2 + tempUnit="" + tempWorking="" + tempWorkingUnit="" + } + # dumping the extra + signs after testing for them, nobody has negative temps. + # also, note gawk treats ° as a space, so we have to get the C/F data + # there are some guesses here, but with more sensors samples it will get closer. + # note: using arrays starting at 1 for all fan arrays to make it easier overall + # more validation because gensub if fails to get match returns full string, so + # we have to be sure we are working with the actual real string before assiging + # data to real variables and arrays. Extracting C/F degree unit as well to use + # when constructing temp items for array. + # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign + # used, but it is required in testing regex to avoid error. + /^(M\/B|MB|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 ) + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + if ( temp1 == "" || tempWorking > 0 ) { + temp1=tempWorking + } + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + if ( temp2 == "" || tempWorking > 0 ) { + temp2=tempWorking + } + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + + # final fallback if all else fails, funtoo user showed sensors putting + # temp on wrapped second line, not handled + /^(core0|core 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + if ( core0Temp == "" || tempWorking > 0 ) { + core0Temp=tempWorking + } + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + + # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before + # $2 starts (like so :1234 RPM), so skip that space test in regex + /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + + /^(AUX|FAN(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[4]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + /^(FAN([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ { + sysFanNu=gensub( /^(FAN|CASE|CHASSIS)([2-9])[ \t]+(.*)/, "\\2", 1, $1 ) + if ( sysFanNu ~ /^([2-9])$/ ) { + # note: cpu/mobo/ps/fan1 above are 1/2/3/4 + sysFanNu = sysFanNu + 3 + aFanMain[sysFanNu]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + } + /^fan([0-9]+)(.*)[ \t]*([0-9]+)[ \t]RPM/ { + fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 ) + if ( sysFanNu ~ /^([0-9]+)$/ ) { + # add to array if array index does not exist OR if number is > existing number + if ( ! sysFanNu in aFanDefault || fanWorking >= aFanDefault[sysFanNu] ) { + aFanDefault[sysFanNu]=fanWorking + } + } + } + + END { + # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo: + # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment + if ( temp1 != "" && temp2 != "" ){ + if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) { + tempFanType=userCpuNo + } + else { + # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed + # but only if other fan speed is 0 + if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) { + tempFanType=2 + } + else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) { + tempFanType=1 + } + # then handle the standard case if these fringe cases are false + else if ( temp1 >= temp2 ) { + tempFanType=1 + } + else { + tempFanType=2 + } + } + } + # need a case for no temps at all reported, like with old intels + else if ( temp1 == "" && temp2 == "" && cpuTemp == "" && moboTemp == "" ){ + tempFanType=1 + } + + # then get the real cpu temp, best guess is hottest is real + if ( cpuTemp != "" ){ + cpuTempReal=cpuTemp + } + else if ( tempFanType != "" ){ + if ( tempFanType == 1 ){ + cpuTempReal=temp1 + } + else { + cpuTempReal=temp2 + } + } + else { + cpuTempReal=temp1 + } + # if all else fails, use core0 temp if it is present and cpu is null + if ( cpuTempReal == "" && core0Temp != "" ) { + cpuTempReal=core0Temp + } + + # then the real mobo temp + if ( moboTemp != "" ){ + moboTempReal=moboTemp + } + else if ( tempFanType != "" ){ + if ( tempFanType == 1 ) { + moboTempReal=temp2 + } + else { + moboTempReal=temp1 + } + } + else { + moboTempReal=temp2 + } + # then set the cpu fan speed + if ( aFanMain[1] == "" ) { + # note, you cannot test for aFanDefault[1] or [2] != "" + # because that creates an array item in gawk just by the test itself + if ( tempFanType == 1 && 1 in aFanDefault ) { + aFanMain[1]=aFanDefault[1] + aFanDefault[1]="" + } + else if ( tempFanType == 2 && 2 in aFanDefault ) { + aFanMain[1]=aFanDefault[2] + aFanDefault[2]="" + } + } + + # then we need to get the actual numeric max array count for both fan arrays + for (i = 0; i <= 14; i++) { + if ( i in aFanMain && i > indexCountaFanMain ) { + indexCountaFanMain=i + } + } + for (i = 0; i <= 14; i++) { + if ( i in aFanDefault && i > indexCountaFanDefault ) { + indexCountaFanDefault=i + } + } + + # clear out any duplicates. Primary fan real trumps fan working always if same speed + for (i = 1; i <= indexCountaFanMain; i++) { + if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) { + for (j = 1; j <= indexCountaFanDefault; j++) { + if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) { + aFanDefault[j] = "" + } + } + + } + } + + # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo + # note that gawk is returning true for some test cases when aFanDefault[j] < 5000 + # which has to be a gawk bug, unless there is something really weird with arrays + # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually + # assign that value below, the > 5000 test works again, and a print of the value + # shows the proper value, so the corruption might be internal in awk. + # Note: gensub is the culprit I think, assigning type string for range 501-1000 but + # type integer for all others, this triggers true for > + for (j = 1; j <= indexCountaFanDefault; j++) { + if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) { + aFanMain[2] = aFanDefault[j] + aFanDefault[j] = "" + # then add one if required for output + if ( indexCountaFanMain < 2 ) { + indexCountaFanMain = 2 + } + } + } + + # then construct the sys_fan string for echo, note that iteration 1 + # makes: fanDefaultString separator null, ie, no space or , + for (j = 1; j <= indexCountaFanDefault; j++) { + fanDefaultString = fanDefaultString separator aFanDefault[j] + separator="," + } + separator="" # reset to null for next loop + # then construct the sys_fan string for echo + for (j = 1; j <= indexCountaFanMain; j++) { + fanMainString = fanMainString separator aFanMain[j] + separator="," + } + + # and then build the temps: + if ( moboTempReal != "" ) { + moboTempReal = moboTempReal tempUnit + } + if ( cpuTempReal != "" ) { + cpuTempReal = cpuTempReal tempUnit + } + + # if they are ALL null, print error message. psFan is not used in output currently + if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) { + print "No active sensors found. Have you configured your sensors yet?" + } + else { + # then build array arrays: + print cpuTempReal "," moboTempReal "," psuTemp + # this is for output, a null print line does NOT create a new array index in bash + if ( fanMainString == "" ) { + fanMainString="," + } + print fanMainString + print fanDefaultString + } + } + ' + ) ) + # the error case needs to go here because we are setting special array delimiter ',' + else + A_SENSORS_DATA=( "You do not have the sensors app installed." ) + fi + + IFS="$ORIGINAL_IFS" + log_function_data "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}" +# echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}" + eval $LOGFE +} + +## return uptime string +get_uptime() +{ + eval $LOGFS + ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a + local uptime_value="$( uptime | gawk '{ + a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0) + print a + }' )" + echo "$uptime_value" + log_function_data "uptime_value: $uptime_value" + eval $LOGFE +} + +#### ------------------------------------------------------------------- +#### special data handling for specific options and conditions +#### ------------------------------------------------------------------- + +## multiply the core count by the data to be calculated, bmips, cache +# args: $1 - string to handle; $2 - cpu count +calculate_multicore_data() +{ + eval $LOGFS + local string_number=$1 string_data='' + + if [[ -n $( egrep -i '( mb| kb)' <<< $1 ) ]];then + string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output + string_number=$( gawk '{print $1}' <<< $1 ) + fi + # handle weird error cases where it's not a number + if [[ -n $( egrep '^[0-9\.,]+$' <<< $string_number ) ]];then + string_number=$( echo $string_number $2 | gawk '{ + total = $1*$2 + print total + }' ) + elif [[ $string_number == '' ]];then + string_number='Not Available' + else + # I believe that the above returns 'unknown' by default so no need for extra text + string_number="$string_number " + fi + echo "$string_number$string_data" + log_function_data "string_numberstring_data: $string_number$string_data" + eval $LOGFE +} + +# prints out shortened list of flags, the main ones of interest +# args: $1 - string of cpu flags to process +process_cpu_flags() +{ + eval $LOGFS + local cpu_flags="$1" + + # nx = AMD stack protection extensions + # lm = Intel 64bit extensions + # sse, sse2, pni = sse1,2,3,4,5 gfx extensions + # svm = AMD pacifica virtualization extensions + # vmx = Intel IVT (vanderpool) virtualization extensions + cpu_flags=$( echo "$cpu_flags" | gawk ' + BEGIN { + RS=" " + a_ssel["sse"] = 1 + a_ssel["sse2"] = 2 + a_ssel["pni"] = 3 + a_ssel["sse4a"] = 4 # 4a must precede 4 + a_ssel["sse4"] = 5 + a_ssel["sse5"] = 6 + a_sses[1] = "sse" + a_sses[2] = "sse2" + a_sses[3] = "sse3" + a_sses[4] = "sse4a" + a_sses[5] = "sse4" + a_sses[6] = "sse5" + sseCounter = 0 + flag_string = "" + } + /^(nx|lm|svm|vmx)$/ { + if ( flag_string != "" ) { + flag_string = flag_string " " $0 + } + else { + flag_string = $0 + } + } + /^(sse|sse2|sse4a|sse4|sse5|pni)$/ { + if ( a_ssel[$0] > sseCounter ) { + sseCounter = a_ssel[$0] + } + } + END { + if ( sseCounter > 0 ) { + if ( flag_string != "" ) { + flag_string = a_sses[sseCounter] " " flag_string + } + else { + flag_string = a_sses[sseCounter] + } + } + print flag_string + }' ) + + #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' ')) + if [[ -z $cpu_flags ]];then + cpu_flags="-" + fi + echo "$cpu_flags" + log_function_data "cpu_flags: $cpu_flags" + eval $LOGFE +} + +#### ------------------------------------------------------------------- +#### print and processing of output data +#### ------------------------------------------------------------------- + +#### MASTER PRINT FUNCTION - triggers all line item print functions +## main function to print out, master for all sub print functions. +print_it_out() +{ + eval $LOGFS + # note that print_it_out passes local variable values on to its children, + # and in some cases, their children, with Lspci_Data + local Lspci_Data='' # only for verbose + + if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then + print_short_data + else + Lspci_Data="$( get_lspci_data )" + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_SYSTEM == 'true' ]];then + print_system_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_CPU == 'true' ]];then + print_cpu_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_GRAPHICS == 'true' ]];then + print_gfx_data + fi + if [[ $VERBOSITY_LEVEL -ge 5 || $B_SHOW_AUDIO == 'true' ]];then + print_audio_data + fi + if [[ $VERBOSITY_LEVEL -ge 2 || $B_SHOW_NETWORK == 'true' ]];then + print_networking_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_DISK == 'true' ]];then + print_hard_disk_data + fi + if [[ $VERBOSITY_LEVEL -ge 4 || $B_SHOW_PARTITIONS == 'true' ]];then + print_partition_data + fi + if [[ $VERBOSITY_LEVEL -ge 5 || $B_SHOW_SENSORS == 'true' ]];then + print_sensors_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_INFO == 'true' ]];then + print_info_data + fi + fi + eval $LOGFE +} + +#### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0 +# all the get data stuff is loaded here to keep execution time down for single line print commands +# these will also be loaded in each relevant print function for long output +print_short_data() +{ + eval $LOGFS + local current_kernel=$( uname -rm ) # | gawk '{print $1,$3,$(NF-1)}' ) + local processes="$(( $( ps aux | wc -l ) - 1 ))" + local short_data='' i='' b_background_black='false' + local memory=$( get_memory_data ) + local up_time="$( get_uptime )" + + # set A_CPU_CORE_DATA + get_cpu_core_count + local cpc_plural='' cpu_count_print='' model_plural='' + local cpu_physical_count=${A_CPU_CORE_DATA[0]} + local cpu_core_count=${A_CPU_CORE_DATA[3]} + local cpu_core_alpha=${A_CPU_CORE_DATA[1]} + local cpu_type=${A_CPU_CORE_DATA[2]} + + if [[ $cpu_physical_count -gt 1 ]];then + cpc_plural='(s)' + model_plural='s' + cpu_count_print="$cpu_physical_count " + fi + + local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core" +# local cpu_core_count=${A_CPU_CORE_DATA[0]} + + # load A_HDD_DATA + get_hdd_data_basic + ## note: if hdd_model is declared prior to use, whatever string you want inserted will + ## be inserted first. In this case, it's desirable to print out (x) before each disk found. + local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 )) + IFS="," + local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} ) + IFS="$ORIGINAL_IFS" + local hdd_capacity=${a_hdd_basic_working[0]} + local hdd_used=${a_hdd_basic_working[1]} + + # load A_CPU_DATA + get_cpu_data + + IFS="," + local a_cpu_working=(${A_CPU_DATA[0]}) + IFS="$ORIGINAL_IFS" + local cpu_model="${a_cpu_working[0]}" + ## assemble data for output + local cpu_clock="${a_cpu_working[1]}" # old CPU3 + # this gets that weird min/max final array item + local min_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 )) + local min_max_clock=${A_CPU_DATA[$min_max_clock_nu]} + + #set_color_scheme 12 + if [[ $B_RUNNING_IN_SHELL == 'false' ]];then + for i in $C1 $C2 $CN + do + case "$i" in + "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN") + b_background_black='true' + ;; + esac + done + if [[ $b_background_black == 'true' ]];then + for i in C1 C2 CN + do + ## these need to be in quotes, don't know why + if [[ ${!i} == $NORMAL ]];then + declare $i="${!i}15,1" + else + declare $i="${!i},1" + fi + done + #C1="${C1},1"; C2="${C2},1"; CN="${CN},1" + fi + fi + short_data="${C1}CPU$cpc_plural${CN}[${C2}${SEP1}${cpu_data_string} ${cpu_model}$model_plural (${cpu_type}) clocked at ${min_max_clock}${SEP1}${CN}] ${C1}Kernel${CN}[${C2}${SEP1}${current_kernel}${SEP1}${CN}] ${C1}Up${CN}[${C2}${SEP1}${up_time}${SEP1}${CN}] ${C1}Mem${CN}[${C2}${SEP1}${memory}${SEP1}${CN}] ${C1}HDD${CN}[${C2}${SEP1}${hdd_capacity}($hdd_used)${SEP1}${CN}] ${C1}Procs${CN}[${C2}${SEP1}${processes}${SEP1}${CN}]" + + if [[ $SHOW_IRC -gt 0 ]];then + short_data="${short_data} ${C1}Client${CN}[${C2}${SEP1}${IRC_CLIENT}${IRC_CLIENT_VERSION}${SEP1}${CN}]" + fi + short_data="${short_data} ${C1}$SCRIPT_NAME${C2}${CN}[${C2}${SEP1}$SCRIPT_VERSION_NUMBER${SEP1}${CN}]" + if [[ $SCHEME -gt 0 ]];then + short_data="${short_data} $NORMAL" + fi + print_screen_output "$short_data" + eval $LOGFE +} + +#### LINE ITEM PRINT FUNCTIONS + +# print sound card data +print_audio_data() +{ + eval $LOGFS + local i='' card_one='Card-1' audio_data='' a_audio_data='' port_data='' + local a_audio_working='' alsa_driver='' alsa_data='' port_plural='' module_version='' + # set A_AUDIO_DATA and get alsa data + get_audio_data + alsa_data=$( get_audio_alsa_data ) + IFS="," + a_audio_working=(${A_AUDIO_DATA[0]}) + IFS="$ORIGINAL_IFS" + + if [[ -n ${A_AUDIO_DATA[@]} ]];then + # slightly complicated because 2nd array item could be the alsa data + if [[ ${#A_AUDIO_DATA[@]} -le 1 ]];then + card_one='Card' + fi + +# if [[ -n ${a_audio_working[2]} ]];then +# port_data=" ${C1}at port${C2} ${a_audio_working[2]}" +# fi + # this should only trigger if the $FILE_ASOUND_DEVICE data is used, not lspci -nn + if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_audio_working[3]}" ) + fi + if [[ -n ${a_audio_working[1]} ]];then + alsa_driver=" ${C1}driver${C2} ${a_audio_working[1]}$module_version" + fi + if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_audio_working[2]}" + fi + audio_data="${C1}$card_one${C2} ${a_audio_working[0]}$alsa_driver$port_data" + audio_data=$( create_print_line "Audio:" "$audio_data" ) + print_screen_output "$audio_data" + i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1 + while [[ -n ${A_AUDIO_DATA[++i]} ]] + do + IFS="," + a_audio_working=( ${A_AUDIO_DATA[i]} ) + IFS="$ORIGINAL_IFS" + port_data='' + alsa_driver='' + port_plural='' + module_version='' + if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_audio_working[3]}" ) + fi + # we're testing for the presence of the 2nd array item here, which is the driver name + if [[ -n ${a_audio_working[1]} ]];then + alsa_driver="${C1}driver${C2} ${a_audio_working[1]}" + fi + if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_audio_working[2]}" + fi + if [[ -n ${a_audio_working[0]} ]];then + audio_data="${C1}Card-$(( $i + 1 ))${C2} ${a_audio_working[0]}$alsa_driver$port_data" + fi + if [[ -n $audio_data ]];then + audio_data=$( create_print_line " " "$audio_data" ) + print_screen_output "$audio_data" + fi + done + # alsa driver data only prints out if sound card data is found + if [[ -n $alsa_data ]];then + audio_data="${C1}Sound:${C2} $alsa_data" + audio_data=$( create_print_line " " "$audio_data" ) + print_screen_output "$audio_data" + fi + fi + eval $LOGFE +} + +print_cpu_data() +{ + eval $LOGFS + local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data='' + local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags='' + + ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\"" + # Array A_CPU_DATA always has one extra element: max clockfreq found. + # that's why its count is one more than you'd think from cores/cpus alone + # load A_CPU_DATA + get_cpu_data + + IFS="," + local a_cpu_working=(${A_CPU_DATA[0]}) + IFS="$ORIGINAL_IFS" + local cpu_model="${a_cpu_working[0]}" + ## assemble data for output + local cpu_clock="${a_cpu_working[1]}" + + cpu_vendor=${a_cpu_working[5]} + + # set A_CPU_CORE_DATA + get_cpu_core_count + local cpc_plural='' cpu_count_print='' model_plural='' + local cpu_physical_count=${A_CPU_CORE_DATA[0]} + local cpu_core_count=${A_CPU_CORE_DATA[3]} + local cpu_core_alpha=${A_CPU_CORE_DATA[1]} + local cpu_type=${A_CPU_CORE_DATA[2]} + + if [[ $cpu_physical_count -gt 1 ]];then + cpc_plural='(s)' + cpu_count_print="$cpu_physical_count " + model_plural='s' + fi + + local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core" + # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1 + # as the parameter to output to the screen, then passing "<text1> ${ARR[@]} <text2>" + # will output only <text1> and first element of ARR. That "@" splits in elements and "*" _doesn't_, + # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note. + # This has been confirmed by #bash on freenode. + # The above mentioned only emerges when using the debugging markers below + ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------" + + if [[ -z ${a_cpu_working[2]} ]];then + a_cpu_working[2]="unknown" + fi + + cpu_data=$( create_print_line "CPU$cpc_plural:" "${C1}${cpu_data_string}${C2} ${a_cpu_working[0]}$model_plural (${cpu_type})" ) + if [[ $VERBOSITY_LEVEL -ge 3 || $B_SHOW_CPU == 'true' ]];then + # update for multicore, bogomips x core count. + if [[ $B_EXTRA_DATA == 'true' ]];then +# if [[ $cpu_vendor != 'intel' ]];then + bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" ) +# else +# bmip_data="${a_cpu_working[4]}" +# fi + bmip_data=" ${C1}bmips${C2} $bmip_data" + fi + ## 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 + if [[ $cpu_vendor != 'intel' ]];then + cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))" ) + else + cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count" ) + fi + # only print shortened list + if [[ $B_CPU_FLAGS_FULL != 'true' ]];then + cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" ) + cpu_flags=" ${C1}flags${C2} ($cpu_flags)" + fi + cpu_data="$cpu_data${C2} ${C1}cache${C2} $cpu_cache$cpu_flags$bmip_data${CN}" + fi + # we don't this printing out extra line unless > 1 cpu core + if [[ ${#A_CPU_DATA[@]} -gt 2 ]] && [[ $B_SHOW_CPU == 'true' || $VERBOSITY_LEVEL -ge 5 ]];then + cpu_clock_speed='' # null < verbosity level 5 + else + cpu_data="$cpu_data ${C1}clocked at${C2} ${a_cpu_working[1]} MHz${CN}" + fi + + cpu_data="$cpu_data $cpu_clock_speed" + print_screen_output "$cpu_data" + + # we don't this printing out extra line unless > 1 cpu core + if [[ ${#A_CPU_DATA[@]} -gt 2 ]] && [[ $B_SHOW_CPU == 'true' || $VERBOSITY_LEVEL -ge 5 ]];then + for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ )) + do + IFS="," + a_cpu_working=(${A_CPU_DATA[i]}) + IFS="$ORIGINAL_IFS" + # note: the first iteration will create a first space, for color code separation below + cpu_multi_clock_data="$cpu_multi_clock_data ${C1}($(( i + 1 )))${C2} ${a_cpu_working[1]} MHz${CN}" + if [[ $i -gt 10 ]];then + break + fi + done + if [[ -n $cpu_multi_clock_data ]];then + cpu_multi_clock_data=$( create_print_line " " "${C1}Clock Speeds:${C2}$cpu_multi_clock_data" ) + print_screen_output "$cpu_multi_clock_data" + fi + fi + if [[ $B_CPU_FLAGS_FULL == 'true' ]];then + print_cpu_flags_full "${a_cpu_working[3]}" + fi + eval $LOGFE +} + +# takes list of all flags, split them and prints x per line +# args: $1 - cpu flag string +print_cpu_flags_full() +{ + eval $LOGFS + local cpu_flags_full="$1" a_cpu_flags='' line_starter='' + local i=0 counter=0 max_length=18 max_length_add=18 flag='' flag_data='' + + # build the flag line array + for flag in $cpu_flags_full + do + a_cpu_flags[$counter]="${a_cpu_flags[$counter]}$flag " + if [[ $i -ge $max_length ]];then + (( counter++ )) + max_length=$(( $max_length + $max_length_add )) + fi + ((i++)) + done + # then print it out + for (( i=0; i < ${#a_cpu_flags[@]};i++ )) + do + if [[ $i -eq 0 ]];then + line_starter="${C1}CPU Flags${C2} " + else + line_starter='' + fi + flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" ) + print_screen_output "$flag_data" + done + eval $LOGFE +} + +print_gfx_data() +{ + eval $LOGFS + local gfx_data='' i='' card_one='Card' root_alert='' + local screen_resolution="$( get_graphics_res_data )" + local b_is_mesa='false' display_full_string='' + # set A_GFX_CARD_DATA + get_graphics_card_data + # set A_X_DATA + get_graphics_x_data + local x_vendor=${A_X_DATA[0]} + local x_version=${A_X_DATA[1]} + # set A_GLX_DATA + get_graphics_glx_data + local glx_renderer="${A_GLX_DATA[0]}" + local glx_version="${A_GLX_DATA[1]}" + # this can contain a long No case debugging message, so it's being sliced off + # note: using grep -ioE '(No|Yes)' <<< ${A_GLX_DATA[2]} did not work in Arch, no idea why + local glx_direct_render=$( gawk '{ + print $1 + }' <<< "${A_GLX_DATA[2]}" ) + # some basic error handling: + if [[ -z $screen_resolution ]];then + screen_resolution='N/A' + fi + + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + if [[ -z $x_vendor || -z $x_version ]];then + x_vendor='X-Vendor: N/A' + fi + display_full_string="${C1}$x_vendor${C2} $x_version ${C1}Res:${C2} ${screen_resolution} " + else + if [[ $B_X_RUNNING == 'true' && $B_ROOT == 'true' ]];then + root_alert="${C1}Gfx Data:${C2} N/A for root user" + fi + display_full_string="${C1}tty res:${C2} ${screen_resolution} $root_alert" + fi + + if [[ ${#A_GFX_CARD_DATA[@]} -gt 1 ]];then + i=1 + while [[ -n ${A_GFX_CARD_DATA[i]} && $i -le 3 ]] + do + gfx_data=" ${C1}Card-$(($i+1))${C2} ${A_GFX_CARD_DATA[i]}" + ((i++)) + done + card_one='Card-1' + fi + gfx_data=$( create_print_line "Graphics:" "${C1}$card_one${C2} ${A_GFX_CARD_DATA[0]}${gfx_data} $display_full_string" ) + print_screen_output "$gfx_data" + +# if [[ -z $glx_renderer || -z $glx_version ]];then +# b_is_mesa='true' +# fi + + ## note: if glx render or version have no content, then mesa is true + # if [[ $B_X_RUNNING == 'true' ]] && [[ $b_is_mesa != 'true' ]];then + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + if [[ -z $glx_renderer ]];then + glx_renderer='N/A' + fi + if [[ -z $glx_version ]];then + glx_version='N/A' + fi + if [[ -z $glx_direct_render ]];then + glx_direct_render='N/A' + fi + gfx_data=$( create_print_line " " "${C1}GLX Renderer${C2} ${glx_renderer} ${C1}GLX Version${C2} ${glx_version}${CN}" ) + if [[ $B_HANDLE_CORRUPT_DATA == 'true' || $B_EXTRA_DATA == 'true' ]];then + gfx_data="$gfx_data ${C1}Direct Rendering${C2} ${glx_direct_render}${CN}" + fi + print_screen_output "$gfx_data" + fi + eval $LOGFE +} + +print_hard_disk_data() +{ + eval $LOGFS + local hdd_data='' hdd_data_2='' a_hdd_working='' hdd_temp_data='' hdd_string='' + local dev_data='' size_data='' hdd_model='' usb_data='' hdd_name='' divisor=5 + + # load A_HDD_DATA + get_hdd_data_basic + ## note: if hdd_model is declared prior to use, whatever string you want inserted will + ## be inserted first. In this case, it's desirable to print out (x) before each disk found. + local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 )) + IFS="," + local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} ) + IFS="$ORIGINAL_IFS" + local hdd_capacity=${a_hdd_basic_working[0]} + local hdd_used=${a_hdd_basic_working[1]} + + if [[ $VERBOSITY_LEVEL -ge 3 || $B_SHOW_DISK == 'true' ]];then + ## note: the output part of this should be in the print hdd data function, not here + get_hard_drive_data_advanced + for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ )) + do + # this adds the (x) numbering in front of each disk found, and creates the full disk string + IFS="," + a_hdd_working=( ${A_HDD_DATA[i]} ) + IFS="$ORIGINAL_IFS" + if [[ $B_SHOW_DISK == 'true' || $VERBOSITY_LEVEL -ge 5 ]];then + if [[ -n ${a_hdd_working[3]} ]];then + usb_data="${a_hdd_working[3]} " + else + usb_data='' + fi + dev_data="/dev/${a_hdd_working[0]} " + size_data=" ${a_hdd_working[1]}" + if [[ $B_EXTRA_DATA == 'true' && -n $dev_data ]];then + hdd_temp_data=$( get_hdd_temp_data "$dev_data" ) + # error handling is done in get data function + if [[ -n $hdd_temp_data ]];then + hdd_temp_data=" ${hdd_temp_data}C" + else + hdd_temp_data='' + fi + fi + divisor=2 # for modulus line print out, either 2 items for full, or default for short + fi + hdd_name="${a_hdd_working[2]}" + hdd_string="$usb_data$dev_data$hdd_name$size_data$hdd_temp_data" + hdd_model="${hdd_model}${C1}$(($i+1)):${C2} $hdd_string " + # printing line one, then new lines according to $divisor setting, and after, if leftovers, print that line. + case $i in + 0) + hdd_data=$( create_print_line "Disks:" "${C1}HDD${C2} ${C1}Total Size:${C2} ${hdd_capacity} (${hdd_used}) ${hdd_model}" ) + print_screen_output "$hdd_data" + hdd_model='' + ;; + *) + # using modulus here, if divisible by $divisor, print line, otherwise skip + if [[ $(( $i % $divisor )) -eq 0 ]];then + hdd_data=$( create_print_line " " "${hdd_model}${CN}" ) + print_screen_output "$hdd_data" + hdd_model='' + fi + ;; + esac + done + # then print any leftover items + if [[ -n $hdd_model ]];then + hdd_data=$( create_print_line " " "${hdd_model}${CN}" ) + print_screen_output "$hdd_data" + fi + else + hdd_data=$( create_print_line "Disks:" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})${CN}" ) + print_screen_output "$hdd_data" + fi + + eval $LOGFE +} + +print_info_data() +{ + eval $LOGFS + local suggested_app="runlevel" + local info_data='' + local runlvl='' + local memory="$( get_memory_data )" + local processes="$(( $( ps aux | wc -l ) - 1 ))" + local up_time="$( get_uptime )" + + # Some code could look superfluous but BitchX doesn't like lines not ending in a newline. F*&k that bitch! + # long_last=$( echo -ne "${C1}Processes${C2} ${processes}${CN} | ${C1}Uptime${C2} ${up_time}${CN} | ${C1}Memory${C2} ${MEM}${CN}" ) + info_data=$( create_print_line "Info:" "${C1}Processes${C2} ${processes} ${C1}Uptime${C2} ${up_time} ${C1}Memory${C2} ${memory}${CN}" ) + + # this only triggers if no X data is present + if [[ $B_X_RUNNING != 'true' ]];then + if [[ -e $suggested_app ]];then + runlvl="$( runlevel | gawk '{ print $2 }' )" + info_data="${info_data} ${C1}Runlevel${C2} ${runlvl}${CN}" + fi + fi + + if [[ $SHOW_IRC -gt 0 ]];then + info_data="${info_data} ${C1}Client${C2} ${IRC_CLIENT}${IRC_CLIENT_VERSION}${CN}" + fi + info_data="${info_data} ${C1}$SCRIPT_NAME${C2} $SCRIPT_VERSION_NUMBER${CN}" + + if [[ $SCHEME -gt 0 ]];then + info_data="${info_data} ${NORMAL}" + fi + print_screen_output "$info_data" + eval $LOGFE +} + +# args: $1 - module name (could be > 1, so loop it ) +print_module_version() +{ + eval $LOGFS + local module_versions='' module='' version='' + + for module in $1 + do + version=$( get_module_version_number $module ) + if [[ -n $version ]];then + module_versions="$module_versions $version" + fi + done + + if [[ -n $module_versions ]];then + echo " ${C1}v:${C2}$module_versions" + fi + eval $LOGFE +} + +print_networking_data() +{ + eval $LOGFS + local i='' card_one='Card-1' network_data='' a_network_working='' port_data='' driver_data='' + local card_string='' port_plural='' module_version='' + # set A_NETWORK_DATA + get_networking_data + + IFS="," + a_network_working=(${A_NETWORK_DATA[0]}) + IFS="$ORIGINAL_IFS" + + # will never be null because null is handled in get_network_data, but in case we change + # that leaving this test in place. + if [[ -n ${A_NETWORK_DATA[@]} ]];then + if [[ ${#A_NETWORK_DATA[@]} -le 1 ]];then + card_one='Card' + fi + if [[ -n ${a_network_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_network_working[3]}" ) + fi + if [[ -n ${a_network_working[1]} ]];then + driver_data=" ${C1}driver${C2} ${a_network_working[1]}$module_version" + fi + if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_network_working[2]}" + fi + card_string='' + network_data="${C1}$card_one${C2} ${a_network_working[0]}$driver_data$port_data" + network_data=$( create_print_line "Network:" "$network_data" ) + print_screen_output "$network_data" + i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1 + while [[ -n ${A_NETWORK_DATA[++i]} ]] + do + IFS="," + a_network_working=( ${A_NETWORK_DATA[i]} ) + IFS="$ORIGINAL_IFS" + port_data='' + driver_data='' + port_plural='' + module_version='' + if [[ -n ${a_network_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_network_working[3]}" ) + fi + if [[ -n ${a_network_working[1]} ]];then + driver_data=" ${C1}driver${C2} ${a_network_working[1]}$module_version" + fi + if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_network_working[2]}" + fi + network_data="${C1}Card-$(( $i + 1 ))${C2} ${a_network_working[0]}$driver_data$port_data" + network_data=$( create_print_line " " "$network_data" ) + print_screen_output "$network_data" + done + fi + if [[ $B_SHOW_IP == 'true' ]];then + print_networking_ip_data + fi + eval $LOGFE +} + +print_networking_ip_data() +{ + eval $LOGFS + local ip=$( get_networking_wan_ip_data ) + local ip_data='' a_interfaces_working='' interfaces='' interfaces_2='' i='' + + # set A_INTERFACES_DATA + get_networking_local_ip_data + # first print output for wan ip line. Null is handled in the get function + ip_data=$( create_print_line " " "${C1}Wan IP:${C2} $ip" ) + + # then create the list of local interface/ip + interfaces=" ${C1}Interface:${C2}" + i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1 + while [[ -n ${A_INTERFACES_DATA[i]} ]] + do + IFS="," + a_interfaces_working=(${A_INTERFACES_DATA[i]}) + IFS="$ORIGINAL_IFS" + if [[ $i -lt 3 ]];then + if [[ -n ${a_interfaces_working[0]} ]];then + interfaces="$interfaces ${C1}${a_interfaces_working[0]}${C2} ${a_interfaces_working[1]}" + fi + else + if [[ -n ${a_interfaces_working[0]} ]];then + # space on end here for lining up with line starter + interfaces_2="$interfaces_2${C1}${a_interfaces_working[0]}${C2} ${a_interfaces_working[1]} " + fi + fi + ((i++)) + done + print_screen_output "$ip_data$interfaces" + # then wrap it if needed + if [[ -n $interfaces_2 ]];then + interfaces_2=$( create_print_line " " "$interfaces_2" ) + print_screen_output "$interfaces_2" + fi + eval $LOGFE +} + +print_partition_data() +{ + eval $LOGFS + local a_partition_working='' partition_used='' partition_data='' + local counter=0 line_max=160 i=0 a_partition_data='' line_starter='' + local partitionIdClean='' part_dev='' full_dev='' part_label='' full_label='' + local part_uuid='' full_uuid='' dev_remote='' + + # this handles the different, shorter, irc colors strings embedded in variable data + if [[ $B_RUNNING_IN_SHELL != 'true' ]];then + line_max=130 + fi + # and no color string data at all + if [[ $SCHEME -eq 0 ]];then + line_max=75 + fi + if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then + line_max=20 + fi + + # set A_PARTITION_DATA + get_partition_data + + for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ )) + do + IFS="," + a_partition_working=(${A_PARTITION_DATA[i]}) + IFS="$ORIGINAL_IFS" + full_label='' + full_uuid='' + if [[ $B_SHOW_PARTITIONS_FULL == 'true' ]] || [[ ${a_partition_working[4]} == 'main' ]];then + if [[ -n ${a_partition_working[2]} ]];then + partition_used=" ${C1}used:${C2} ${a_partition_working[2]} (${a_partition_working[3]})" + else + partition_used='' # reset partition used to null + fi + + # don't show user names in output + if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then + if [[ -n ${a_partition_working[5]} ]];then + if [[ -z $( grep -E '(^//|:/)' <<< ${a_partition_working[5]} ) ]];then + part_dev="/dev/${a_partition_working[5]}" + dev_remote='dev' + else + part_dev="${a_partition_working[5]}" + dev_remote='remote' + fi + else + dev_remote='dev' + part_dev='N/A' + fi + full_dev=" ${C1}$dev_remote:${C2} $part_dev" + if [[ $B_SHOW_LABELS == 'true' && $dev_remote != 'remote' ]];then + if [[ -n ${a_partition_working[6]} ]];then + part_label="${a_partition_working[6]}" + else + part_label='N/A' + fi + full_label=" ${C1}label:${C2} $part_label" + fi + if [[ $B_SHOW_UUIDS == 'true' && $dev_remote != 'remote' ]];then + if [[ -n ${a_partition_working[7]} ]];then + part_uuid="${a_partition_working[7]}" + else + part_uuid='N/A' + fi + full_uuid=" ${C1}uuid:${C2} $part_uuid" + fi + fi + partitionIdClean=$( sed -r 's|/home/(.*)/(.*)|/home/##/\2|' <<< ${a_partition_working[0]} ) + # because these lines can vary widely, using dynamic length handling here + a_partition_data[$counter]="${a_partition_data[$counter]}${C1}ID:${C2}$partitionIdClean ${C1}size:${C2} ${a_partition_working[1]}$partition_used$full_dev$full_label$full_uuid " + + if [[ $( wc -c <<< ${a_partition_data[$counter]} ) -gt $line_max ]];then + ((counter++)) + fi + fi + done + # print out all lines, line starter on first line + for (( i=0; i < ${#a_partition_data[@]};i++ )) + do + if [[ $i -eq 0 ]];then + line_starter='Partition:' + else + line_starter=' ' + fi + partition_data=$( create_print_line "$line_starter" "${a_partition_data[$i]}" ) + print_screen_output "$partition_data" + done + eval $LOGFE +} + +print_sensors_data() +{ + eval $LOGFS + local mobo_temp='' cpu_temp='' psu_temp='' cpu_fan='' mobo_fan='' ps_fan='' sys_fans='' sys_fans2='' + local temp_data='' fan_data='' fan_data2='' b_is_error='false' fan_count=0 gpu_temp='' + local a_sensors_working='' + get_sensors_data + + IFS="," + a_sensors_working=( ${A_SENSORS_DATA[0]} ) + IFS="$ORIGINAL_IFS" + # initial error cases, for missing app or unconfigured sensors. Note that array 0 + # always has at least 3 items, cpu/mobo/psu temp in it. If it's a single item, then + # it's an error message, not the real data arrays. + if [[ ${#a_sensors_working[@]} -eq 1 ]];then + cpu_temp="${C1}Error:${C2} ${A_SENSORS_DATA[0]}" + b_is_error='true' + else + for (( i=0; i < ${#A_SENSORS_DATA[@]}; i++ )) + do + IFS="," + a_sensors_working=( ${A_SENSORS_DATA[i]} ) + IFS="$ORIGINAL_IFS" + case $i in + # first the temp data + 0) + if [[ -n ${a_sensors_working[0]} ]];then + cpu_temp=${a_sensors_working[0]} + else + cpu_temp='N/A' + fi + cpu_temp="${C1}System Temperatures: cpu:${C2} $cpu_temp " + + if [[ -n ${a_sensors_working[1]} ]];then + mobo_temp=${a_sensors_working[1]} + else + mobo_temp='N/A' + fi + mobo_temp="${C1}mobo:${C2} $mobo_temp " + + if [[ -n ${a_sensors_working[2]} ]];then + psu_temp="${C1}psu:${C2} ${a_sensors_working[2]} " + fi + gpu_temp=$( get_gpu_temp_data ) + if [[ -n $gpu_temp ]];then + gpu_temp="${C1}gpu:${C2} ${gpu_temp} " + fi + ;; + # then the fan data from main fan array + 1) + for (( j=0; j < ${#a_sensors_working[@]}; j++ )) + do + case $j in + 0) + # we need to make sure it's either cpu fan OR cpu fan and sys fan 1 + if [[ -n ${a_sensors_working[0]} ]];then + cpu_fan="${a_sensors_working[0]}" + elif [[ -z ${a_sensors_working[0]} && -n ${a_sensors_working[1]} ]];then + cpu_fan="${a_sensors_working[1]}" + else + cpu_fan='N/A' + fi + cpu_fan="${C1}Fan Speeds (in rpm): cpu:${C2} $cpu_fan " + (( fan_count++ )) + ;; + 1) + if [[ -n ${a_sensors_working[1]} ]];then + mobo_fan="${C1}mobo:${C2} ${a_sensors_working[1]} " + (( fan_count++ )) + fi + ;; + 2) + if [[ -n ${a_sensors_working[2]} ]];then + ps_fan="${C1}psu:${C2} ${a_sensors_working[2]} " + (( fan_count++ )) + fi + ;; + [3-9]) + if [[ -n ${a_sensors_working[$j]} ]];then + fan_number=$(( $j - 2 )) # sys fans start on array key 5 + # wrap after fan 6 total + if [[ $fan_count -lt 7 ]];then + sys_fans="$sys_fans${C1}sys-$fan_number:${C2} ${a_sensors_working[$j]} " + else + sys_fans2="$sys_fans2${C1}sys-$fan_number:${C2} ${a_sensors_working[$j]} " + fi + (( fan_count++ )) + fi + ;; + esac + done + ;; + 2) + for (( j=0; j < ${#a_sensors_working[@]}; j++ )) + do + case $j in + [0-9]|10|11|12|13|14) + if [[ -n ${a_sensors_working[$j]} ]];then + fan_number=$(( $j + 1 )) # sys fans start on array key 5 + # wrap after fan 6 total + if [[ $fan_count -lt 7 ]];then + sys_fans="$sys_fans${C1}fan-$fan_number:${C2} ${a_sensors_working[$j]} " + else + sys_fans2="$sys_fans2${C1}fan-$fan_number:${C2} ${a_sensors_working[$j]} " + fi + (( fan_count++ )) + fi + ;; + esac + done + ;; + esac + done + fi + # turning off all output for case where no sensors detected or no sensors output + # unless -s used explicitly. So for -F type output won't show unless valid or -! 1 used + if [[ $b_is_error != 'true' || $B_SHOW_SENSORS == 'true' || $B_TESTING_1 == 'true' ]];then + temp_data="$cpu_temp$mobo_temp$psu_temp$gpu_temp" + temp_data=$( create_print_line "Sensors:" "$temp_data" ) + print_screen_output "$temp_data" + # don't print second or subsequent lines if error data + fan_data="$cpu_fan$mobo_fan$ps_fan$sys_fans" + if [[ $b_is_error != 'true' && -n $fan_data ]];then + fan_data=$( create_print_line " " "$fan_data" ) + print_screen_output "$fan_data" + # and then second wrapped fan line if needed + if [[ -n $sys_fans2 ]];then + fan_data2=$( create_print_line " " "$sys_fans2" ) + print_screen_output "$fan_data2" + fi + fi + fi + eval $LOGFE +} + +print_system_data() +{ + eval $LOGFS + local system_data='' bits='' + local host_name=$( hostname ) + local current_kernel=$( uname -rm ) # | gawk '{print $1,$3,$(NF-1)}' ) + local distro="$( get_distro_data )" + # check for 64 bit first + if [[ -n $( uname -m | grep -o 'x86_64' ) ]];then + bits="(64 bit)" + else + bits="(32 bit)" + fi + + if [[ $B_SHOW_HOST == 'true' ]];then + system_data=$( create_print_line "System:" "${C1}Host${C2} $host_name ${C1}Kernel${C2}" ) + else + system_data=$( create_print_line "System:" "${C1}Kernel${C2}" ) + fi + system_data="$system_data $current_kernel $bits ${C1}Distro${C2} $distro" + print_screen_output "$system_data" + eval $LOGFE +} + +######################################################################## +#### SCRIPT EXECUTION +######################################################################## + +main $@ ## From the End comes the Beginning + +## note: this EOF is needed for smxi handling, this is what triggers the full download ok +###**EOF**### |