client: add FontSelector SettingsPage::hasChanged
[quassel.git] / data / scripts / inxi
1 #!/usr/bin/env bash
2 ########################################################################
3 ####  Script Name: inxi
4 ####  Version: 2.3.0
5 ####  Date: 2016-04-18
6 ####  Patch Number: 00
7 ########################################################################
8 ####  SPECIAL THANKS
9 ########################################################################
10 ####  Special thanks to all those in #lsc and #smxi for their tireless 
11 ####  dedication helping test inxi modules.
12 ########################################################################
13 ####  ABOUT INXI
14 ########################################################################
15 ####  inxi is a fork of infobash 3.02, the original bash sys info tool by locsmif
16 ####  As time permits functionality improvements and recoding will occur.
17 ####
18 ####  inxi, the universal, portable, system information tool for irc.
19 ####  Tested with Irssi, Xchat, Konversation, BitchX, KSirc, ircII,
20 ####  Gaim/Pidgin, Weechat, KVIrc and Kopete.
21 ####  Original infobash author and copyright holder:
22 ####  Copyright (C) 2005-2007  Michiel de Boer a.k.a. locsmif
23 ####  inxi version: Copyright (C) 2008-2016 Scott Rogers & Harald Hope
24 ####  Further fixes (listed as known): Horst Tritremmel <hjt at sidux.com>
25 ####  Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch
26 ####  Jarett.Stevens - dmidecde -M patch for older systems with the /sys 
27 ####
28 ####  Current script home page/wiki/git: https://github.com/smxi/inxi 
29 ####  Documentation/wiki pages will move to http://smxi.org soon.
30 ####  Script forums: http://techpatterns.com/forums/forum-33.html
31 ####  IRC support: irc.oftc.net channel #smxi
32 ####  Version control:
33 ####   * https://github.com/smxi/inxi
34 ####   * git: git pull https://github.com/smxi/inxi master
35 ####   * svn checkout url: https://github.com/smxi/inxi
36 ####
37 ####  This program is free software; you can redistribute it and/or modify
38 ####  it under the terms of the GNU General Public License as published by
39 ####  the Free Software Foundation; either version 3 of the License, or
40 ####  (at your option) any later version.
41 ####
42 ####  This program is distributed in the hope that it will be useful,
43 ####  but WITHOUT ANY WARRANTY; without even the implied warranty of
44 ####  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45 ####  GNU General Public License for more details.
46 ####
47 ####  You should have received a copy of the GNU General Public License
48 ####  along with this program.  If not, see <http://www.gnu.org/licenses/>.
49 ####
50 ####  If you don't understand what Free Software is, please read (or reread)
51 ####  this page: http://www.gnu.org/philosophy/free-sw.html
52 ########################################################################
53
54 ####
55 #### PACKAGE NAME NOTES
56 ####  * Package names in (...) are the Debian Squeeze package name. Check your 
57 ####    distro for proper package name by doing this: which <application> 
58 ####    then find what package owns that application file. Or run --recommends
59 ####    which shows package names for Debian/Ubuntu, Arch, and Fedora/Redhat/Suse
60 ####
61 ####  DEPENDENCIES
62 ####  * bash >=3.0 (bash); df, readlink, stty, tr, uname, wc (coreutils);
63 ####    gawk (gawk); grep (grep); lspci (pciutils);
64 ####    ps, find (findutils)
65 ####  * Also the proc filesystem should be present and mounted for Linux
66 ####  * Some features, like -M and -d will not work, or will work incompletely,
67 ####    if /sys is missing
68 ####
69 ####    Apparently unpatched bash 3.0 has arrays broken; bug reports:
70 ####    http://ftp.gnu.org/gnu/bash/bash-3.0-patches/bash30-008
71 ####    http://lists.gnu.org/archive/html/bug-bash/2004-08/msg00144.html
72 ####  Bash 3.1 for proper array use
73 ####
74 ####    Arrays work in bash 2.05b, but "grep -Em" does not
75 ####
76 ####  RECOMMENDS (Needed to run certain features, listed by option)
77 ####  -A - for output of usb audio information: lsusb (usbutils)
78 ####  -Ax -Nx - for audio/network module version: modinfo (module-init-tools)
79 ####  -Dx - for hdd temp output (root only default): hddtemp (hddtemp)
80 ####       For user level hdd temp output: sudo (sudo)
81 ####       Note: requires user action for this feature to run as user (edit /etc/sudoers file)
82 ####  -G - full graphics output requires:  glxinfo (mesa-utils); xdpyinfo (X11-utils);
83 ####       xrandr (x11-xserver-utils)
84 ####  -i - IP information, local/wan - ip (iproute) legacy, not used if ip present: ifconfig (net-tools)
85 ####  -I - uptime (procps, check Debian if changed)
86 ####  -Ix - view current runlevel while not in X window system (or with -x): runlevel (sysvinit)
87 ####  -m - all systems, dmidecode, unless someone can find a better way.
88 ####  -M - for older systems whose kernel does not have /sys data for machine, dmidecode (dmidecode)
89 ####  -o - for unmounted file system information in unmounted drives (root only default): file (file)
90 ####       Note: requires user action for this feature to run as user (edit /etc/sudoers file)
91 ####       For user level unmounted file system type output: sudo (sudo)
92 ####  -s   For any sensors output, fan, temp, etc: sensors (lm-sensors)
93 ####       Note: requires setup of lm-sensors (sensors-detect and adding modules/modprobe/reboot,
94 ####       and ideally, pwmconfig) prior to full output being available. 
95 ####  -S   For desktop environment, user must be in X and have xprop installed (in X11-utils)
96 ########################################################################
97 ####  BSD Adjustments
98 ####  * sed -i '' form supported by using SED_I="-i ''".
99 ####  * Note: New BSD sed supports using -r instead of -E for compatibility with gnu sed
100 ####    However, older, like FreeBSD 7.x, does not have -r so using SED_RX='-E' for this.
101 ####  * Gnu grep options can be used if the function component is only run in linux
102 ####    These are the options that bsd grep does not support that inxi uses: -m <number> -o 
103 ####    so make sure if you use those to have them in gnu/linux only sections.
104 ####    It appears that freebsd uses gnu grep but openbsd uses bsd grep, however.
105 ####  * BSD ps does not support --without-headers option, and also does not support --sort <option>
106 ####    Tests show that -m fails to sort memory as expected, but -r does sort cpu percentage.
107 ####  * BSD_TYPE is set with values null, debian-bsd (debian gnu/kfreebsd), bsd (all other bsds)
108 ####  * Subshell and array closing ) must not be on their own line unless you use an explicit \ 
109 ####    to indicate that logic continues to next line where closing ) or )) are located.
110 ########################################################################
111 ####  CONVENTIONS:
112 ####  * Character Encoding: UTF-8 - this file contains special characters that must be opened and saved as UTF8
113 ####  * Indentation: TABS
114 ####  * Do not use `....` (back quotes), those are totally non-reabable, use $(....).
115 ####  * Do not use one liner flow controls. 
116 ####    The ONLY time you should use ';' (semi-colon) is in this single case: if [[ condition ]];then.
117 ####    Never use compound 'if': ie, if [[ condition ]] && statement.
118 ####  * Note: [[ -n $something ]] - double brackets does not require quotes for variables: ie, "$something".
119 ####  * Always use quotes, double or single, for all string values.
120 ####  * All new code/methods must be in a function.
121
122 ####  * For all boolean tests, use 'true' / 'false'.
123 ####    !! Do NOT use 0 or 1 unless it's a function return. 
124 ####  * Avoid complicated tests in the if condition itself.
125 ####  * To 'return' a value in a function, use 'echo <var>'.
126 ####  * For gawk: use always if ( num_of_cores > 1 ) { hanging { starter for all blocks
127 ####    This lets us use one method for all gawk structures, including BEGIN/END, if, for, etc
128 ####  * Using ${VAR} is about 30% slower than $VAR because bash has to check the stuff for actions
129 ####  SUBSHELLS ARE EXPENSIVE! - run these two if you do not believe me.
130 ####  time for (( i=0; i<1000; i++ )) do ff='/usr/local/bin/foo.pid';ff=${ff##*/};ff=${ff%.*};done;echo $ff
131 ####  time for (( i=0; i<1000; i++ )) do ff='/usr/local/bin/foo.pid';ff=$( basename $ff | cut -d '.' -f 1 );done;echo $ff
132 ####
133 ####  VARIABLE/FUNCTION NAMING:
134 ####  * All functions should follow standard naming--verb adjective noun. 
135 ####      ie, get_cpu_data
136 ####  * All variables MUST be initialized / declared explicitly, either top of file, for Globals, or using local
137 ####  * All variables should clearly explain what they are, except counters like i, j.
138 ####  * Each word of Bash variable must be separated by '_' (underscore) (camel form), like: cpu_data
139 ####  * Each word of Gawk variable must be like this (first word lower, following start with upper): cpuData
140 ####  * Global variables are 'UPPER CASE', at top of this file.
141 ####      ie, SOME_VARIABLE=''
142 ####  * Local variables are 'lower case' and declared at the top of the function using local, always.
143 ####      ie: local some_variable=''
144 ####  * Locals that will be inherited by child functions have first char capitalized (so you know they are inherited).
145 ####      ie, Some_Variable 
146 ####  * Booleans should start with b_ (local) or B_ (global) and state clearly what is being tested.
147 ####  * Arrays should start with a_ (local) or A_ (global).
148 ####
149 ####  SPECIAL NOTES:
150 ####  * The color variable ${C2} must always be followed by a space unless you know what
151 ####    character is going to be next for certain. Otherwise irc color codes can be accidentally
152 ####    activated or altered.
153 ####  * For native script konversation support (check distro for correct konvi scripts path):
154 ####    ln -s <path to inxi> /usr/share/apps/konversation/scripts/inxi
155 ####    DCOP doesn't like \n, so avoid using it for most output unless required, as in error messages.
156 ####  * print_screen_output " " # requires space, not null, to avoid error in for example in irssi
157 ####  * For logging of array data, array must be placed into the a_temp, otherwise only the first key logs
158 ####  * In gawk search patterns, . is a wildcard EXCEPT in [0-9.] type containers, then it's a literal
159 ####    So outside of bracketed items, it must be escaped, \. but inside, no need. Outside of gawk it should 
160 ####    be escaped in search patterns if you are using it as a literal.
161 ####  
162 ####  PACKAGE MANAGER DATA (note, while inxi tries to avoid using package managers to get data, sometimes 
163 ####  it's the only way to get some data):
164 ####  * dpkg options: http://www.cyberciti.biz/howto/question/linux/dpkg-cheat-sheet.php
165 ####  * pacman options: https://wiki.archlinux.org/index.php/Pacman_Rosetta
166 ####
167 ####  As with all 'rules' there are acceptions, these are noted where used.
168 ###################################################################################
169 ####    KDE Konversation information.  Moving from dcop(qt3/KDE3) to dbus(qt4/KDE4)
170 ###################################################################################
171 ####  * dcop and dbus   -- these talk back to Konversation from this program
172 ####  * Scripting info  -- http://konversation.berlios.de/docs/scripting.html
173 ####    -- http://www.kde.org.uk/apps/konversation/
174 ####  * dbus info       -- http://dbus.freedesktop.org/doc/dbus-tutorial.html
175 ####    view dbus info  -- https://fedorahosted.org/d-feet/
176 ####    -- or run qdbus
177 ####  * Konvi dbus/usage-- qdbus org.kde.konversation /irc say <server> <target-channel> <output>
178 ####  * Python usage    -- http://wiki.python.org/moin/DbusExamples  (just in case)
179 ####
180 ####    Because webpages come and go, the above information needs to be moved to inxi's wiki
181 ########################################################################
182 ####  Valuable Resources
183 ####  CPU flags: http://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean
184 ####  Advanced Bash: http://wiki.bash-hackers.org/syntax/pe
185 ####  gawk arrays: http://www.math.utah.edu/docs/info/gawk_12.html
186 ####  raid mdstat: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
187 ####               http://www.howtoforge.com/replacing_hard_disks_in_a_raid1_array
188 ####               https://raid.wiki.kernel.org/index.php/Mdstat
189 ########################################################################
190 ####  TESTING FLAGS
191 ####  inxi supports advanced testing triggers to do various things, using -! <arg>
192 ####  -! 1  - triggers default B_TESTING_1='true' to trigger some test or other
193 ####  -! 2  - triggers default B_TESTING_2='true' to trigger some test or other
194 ####  -! 3  - triggers B_TESTING_1='true' and B_TESTING_2='true'
195 ####  -! 10 - triggers an update from the primary dev download server instead of svn
196 ####  -! 11 - triggers an update from svn branch one - if present, of course
197 ####  -! 12 - triggers an update from svn branch two - if present, of course
198 ####  -! 13 - triggers an update from svn branch three - if present, of course
199 ####  -! 14 - triggers an update from svn branch four - if present, of course
200 ####  -! <http://......> - Triggers an update from whatever server you list.
201 ####  LOG FLAGS (logs to $HOME/.inxi/inxi.log with rotate 3 total)
202 ####  -@ 8  - Basic data logging of generated data / array values
203 ####  -@ 9  - Full logging of all data used, including cat of files and system data
204 ####  -@ 10 - Basic data logging plus color code logging
205 ########################################################################
206 #### VARIABLES
207 ########################################################################
208
209 ## NOTE: we can use hwinfo if it's available in all systems, or most, to get
210 ## a lot more data and verbosity levels going
211
212 ### DISTRO MAINTAINER FLAGS ###
213 # flag to allow distro maintainers to turn off update features. If false, turns off
214 # -U and -! testing/advanced update options, as well as removing the -U help menu item
215 # NOTE: Usually you want to create these in /etc/inxi.conf to avoid having to update each time
216 B_ALLOW_UPDATE='true'
217 B_ALLOW_WEATHER='true'
218
219 ### USER CONFIGS: SET IN inxi.conf file see wiki for directions ###
220 # http://code.google.com/p/inxi/wiki/script_configuration_files
221 # override in user config if desired, seems like less than .3 doesn't work as reliably
222 CPU_SLEEP='0.3' 
223 FILTER_STRING='<filter>'
224
225 # for features like help/version will fit to terminal / console screen width. Console
226 # widths will be dynamically set in main() based on cols in term/console
227 COLS_MAX_CONSOLE='115'
228 COLS_MAX_IRC='105'
229 # note, this is console out of x/display server, will also be set dynamically
230 # not used currently, but maybe in future
231 COLS_MAX_NO_DISPLAY='140'
232 PS_COUNT=5
233 # change to less, or more if you have very slow connection
234 DL_TIMEOUT=8
235 ### END USER CONFIGS ###
236
237 ### LOCALIZATION - DO NOT CHANGE! ###
238 # set to default LANG to avoid locales errors with , or .
239 LANG=C
240 # Make sure every program speaks English.
241 LC_ALL="C"
242 export LC_ALL
243
244 ### ARRAYS ###
245 ## Prep
246 # Clear nullglob, because it creates unpredictable situations with IFS=$'\n' ARR=($VAR) IFS="$ORIGINAL_IFS"
247 # type constructs. Stuff like [rev a1] is now seen as a glob expansion pattern, and fails, and
248 # therefore results in nothing.
249 shopt -u nullglob
250 ## info on bash built in: $IFS - http://tldp.org/LDP/abs/html/internalvariables.html
251 # Backup the current Internal Field Separator
252 ORIGINAL_IFS="$IFS"
253
254 ## Initialize
255 A_ALSA_DATA=''
256 A_AUDIO_DATA=''
257 A_BATTERY_DATA=''
258 A_CMDL=''
259 A_CPU_CORE_DATA=''
260 A_CPU_DATA=''
261 A_CPU_TYPE_PCNT_CCNT=''
262 A_DEBUG_BUFFER=''
263 A_GCC_VERSIONS=''
264 A_GLX_DATA=''
265 A_GRAPHICS_CARD_DATA=''
266 A_GRAPHIC_DRIVERS=''
267 A_HDD_DATA=''
268 A_INIT_DATA=''
269 A_INTERFACES_DATA=''
270 A_MACHINE_DATA=''
271 A_MEMORY_DATA=''
272 A_NETWORK_DATA=''
273 A_OPTICAL_DRIVE_DATA=''
274 A_PARTITION_DATA=''
275 A_PCICONF_DATA=''
276 A_PS_DATA=''
277 A_RAID_DATA=''
278 A_SENSORS_DATA=''
279 A_UNMOUNTED_PARTITION_DATA=''
280 A_WEATHER_DATA=''
281 A_DISPLAY_SERVER_DATA=''
282
283 ### BOOLEANS ###
284 ## standard boolean flags ##
285 B_BSD_DISK_SET='false'
286 B_BSD_RAID='false'
287 B_COLOR_SCHEME_SET='false'
288 B_CONSOLE_IRC='false'
289 # triggers full display of cpu flags
290 B_CPU_FLAGS_FULL='false'
291 # test for dbus irc client
292 B_DBUS_CLIENT='false'
293 # kde dcop
294 B_DCOP='false'
295 # Debug flood override: make 'true' to allow long debug output
296 B_DEBUG_FLOOD='false'
297 # for special -i debugging cases
298 B_DEBUG_I='false'
299 B_DMIDECODE_SET='false'
300 # show extra output data
301 B_EXTRA_DATA='false'
302 # triggered by -xx
303 B_EXTRA_EXTRA_DATA='false'
304 B_FORCE_DMIDECODE='false'
305 B_ID_SET='false'
306 # override certain errors due to currupted data
307 B_HANDLE_CORRUPT_DATA='false'
308 B_LABEL_SET='false'
309 B_LSPCI='false'
310 B_LOG_COLORS='false'
311 B_LOG_FULL_DATA='false'
312 B_MAPPER_SET='false'
313 B_OUTPUT_FILTER='false'
314 B_OVERRIDE_FILTER='false'
315 B_PCICONF='false'
316 B_PCICONF_SET='false'
317 # kde qdbus
318 B_QDBUS='false'
319 B_PORTABLE='false'
320 B_RAID_SET='false'
321 B_ROOT='false'
322 B_RUN_COLOR_SELECTOR='false'
323 B_RUNNING_IN_DISPLAY='false' # in x type display server
324 if tty >/dev/null;then
325         B_IRC='false'
326 else
327         B_IRC='true'
328 fi
329 # this sets the debug buffer
330 B_SCRIPT_UP='false'
331 B_SHOW_ADVANCED_NETWORK='false'
332 # Show sound card data
333 B_SHOW_AUDIO='false'
334 B_SHOW_BASIC_RAID='false'
335 B_SHOW_BASIC_CPU='false'
336 B_SHOW_BASIC_DISK='false'
337 B_SHOW_BASIC_OPTICAL='false'
338 B_SHOW_BATTERY='false'
339 B_SHOW_BATTERY_FORCED='false'
340 B_SHOW_CPU='false'
341 B_SHOW_DISPLAY_DATA='false'
342 B_SHOW_DISK_TOTAL='false'
343 B_SHOW_DISK='false'
344 # Show full hard disk output
345 B_SHOW_FULL_HDD='false'
346 B_SHOW_FULL_OPTICAL='false'
347 B_SHOW_GRAPHICS='false'
348 # Set this to 'false' to avoid printing the hostname, can be set false now
349 B_SHOW_HOST='true'
350 B_SHOW_INFO='false'
351 B_SHOW_IP='false'
352 B_SHOW_LABELS='false'
353 B_SHOW_MACHINE='false'
354 B_SHOW_MEMORY='false'
355 B_SHOW_NETWORK='false'
356 # either -v > 3 or -P will show partitions
357 B_SHOW_PARTITIONS='false'
358 B_SHOW_PARTITIONS_FULL='false'
359 B_SHOW_PS_CPU_DATA='false'
360 B_SHOW_PS_MEM_DATA='false'
361 B_SHOW_RAID='false'
362 # because many systems have no mdstat file, -b/-F should not show error if no raid file found
363 B_SHOW_RAID_R='false' 
364 B_SHOW_REPOS='false'
365 B_SHOW_SENSORS='false'
366 # triggers only short inxi output
367 B_SHOW_SHORT_OUTPUT='false'
368 B_SHOW_SYSTEM='false'
369 B_SHOW_UNMOUNTED_PARTITIONS='false'
370 B_SHOW_UUIDS='false'
371 B_SHOW_WEATHER='false'
372 B_SYSCTL='false'
373 # triggers various debugging and new option testing
374 B_TESTING_1='false'
375 B_TESTING_2='false'
376 B_UPLOAD_DEBUG_DATA='false'
377 B_USB_NETWORKING='false'
378 # set to true here for debug logging from script start
379 B_USE_LOGGING='false'
380 B_UUID_SET='false'
381 B_XORG_LOG='false'
382
383 ## Directory/file exist flags; test as [[ $(boolean) ]] not [[ $boolean ]]
384 B_ASOUND_DEVICE_FILE='false'
385 B_ASOUND_VERSION_FILE='false'
386 B_BASH_ARRAY='false'
387 B_CPUINFO_FILE='false'
388 B_DMESG_BOOT_FILE='false' # bsd only
389 B_LSB_FILE='false'
390 B_MDSTAT_FILE='false'
391 B_MEMINFO_FILE='false'
392 B_MODULES_FILE='false' #
393 B_MOUNTS_FILE='false'
394 B_OS_RELEASE_FILE='false' # new default distro id file? will this one work where lsb-release didn't?
395 B_PARTITIONS_FILE='false' #
396 B_PROC_DIR='false'
397 B_SCSI_FILE='false'
398
399 ## app tested for and present, to avoid repeat tests
400 B_FILE_TESTED='false'
401 B_HDDTEMP_TESTED='false'
402 B_MODINFO_TESTED='false'
403 B_SUDO_TESTED='false'
404
405 ### CONSTANTS/INITIALIZE - SOME MAY BE RESET LATER ###
406 DCOPOBJ="default"
407 DEBUG=0 # Set debug levels from 1-10 (8-10 trigger logging levels)
408 # Debug Buffer Index, index into a debug buffer storing debug messages until inxi is 'all up'
409 DEBUG_BUFFER_INDEX=0
410 ## note: the debugger rerouting to /dev/null has been moved to the end of the get_parameters function
411 ## so -@[number] debug levels can be set if there is a failure, otherwise you can't even see the errors
412 SED_I='-i' # for gnu sed, will be set to -i '' for bsd sed
413 SED_RX='-r' # for gnu sed, will be set to -E for bsd sed for backward compatibility
414
415 # default to false, no konversation found, 1 is native konvi (qt3/KDE3) script mode, 2 is /cmd inxi start,
416 ##      3 is Konversation > 1.2 (qt4/KDE4) 
417 KONVI=0
418 # NO_CPU_COUNT=0        # Wether or not the string "dual" or similar is found in cpuinfo output. If so, avoid dups.
419 # This is a variable that controls how many parameters inxi will parse in a /proc/<pid>/cmdline file before stopping.
420 PARAMETER_LIMIT=30
421 SCHEME=0 # set default scheme - do not change this, it's set dynamically
422 # this is set in user prefs file, to override dynamic temp1/temp2 determination of sensors output in case
423 # cpu runs colder than mobo
424 SENSORS_CPU_NO=''
425 # SHOW_IRC=1 to avoid showing the irc client version number, or SHOW_IRC=0 to disable client information completely.
426 SHOW_IRC=2
427 # Verbosity level defaults to 0, this can also be set with -v0, -v2, -v3, etc as a parameter.
428 VERBOSITY_LEVEL=0
429 # Supported number of verbosity levels, including 0
430 VERBOSITY_LEVELS=7
431
432 ### LOGGING ###
433 ## logging eval variables, start and end function: Insert to LOGFS LOGFE when debug level >= 8
434 LOGFS_STRING='log_function_data fs $FUNCNAME "$( echo $@ )"'
435 LOGFE_STRING='log_function_data fe $FUNCNAME'
436 LOGFS=''
437 LOGFE=''
438 # uncomment for debugging from script start
439 # LOGFS=$LOGFS_STRING
440 # LOGFE=$LOGFE_STRING
441
442 ### FILE NAMES/PATHS/URLS - must be non root writable ###
443 # File's used when present
444 FILE_ASOUND_DEVICE='/proc/asound/cards'
445 FILE_ASOUND_MODULES='/proc/asound/modules' # not used but maybe for -A?
446 FILE_ASOUND_VERSION='/proc/asound/version'
447 FILE_CPUINFO='/proc/cpuinfo'
448 FILE_DMESG_BOOT='/var/run/dmesg.boot'
449 FILE_LSB_RELEASE='/etc/lsb-release'
450 FILE_MDSTAT='/proc/mdstat'
451 FILE_MEMINFO='/proc/meminfo'
452 FILE_MODULES='/proc/modules'
453 FILE_MOUNTS='/proc/mounts'
454 FILE_OS_RELEASE='/etc/os-release'
455 FILE_PARTITIONS='/proc/partitions'
456 FILE_SCSI='/proc/scsi/scsi'
457 FILE_XORG_LOG='/var/log/Xorg.0.log' # if not found, search and replace with actual location
458
459 FILE_PATH=''
460 HDDTEMP_PATH=''
461 MODINFO_PATH=''
462 SUDO_PATH=''
463
464 SCRIPT_DATA_DIR="$HOME/.inxi"
465 ALTERNATE_FTP='' # for data uploads
466 ALTERNATE_WEATHER_LOCATION='' # weather alternate location
467 LOG_FILE="$SCRIPT_DATA_DIR/inxi.log"
468 LOG_FILE_1="$SCRIPT_DATA_DIR/inxi.1.log"
469 LOG_FILE_2="$SCRIPT_DATA_DIR/inxi.2.log"
470 MAN_FILE_DOWNLOAD='https://github.com/smxi/inxi/raw/master/inxi.1.gz'
471 MAN_FILE_LOCATION='/usr/share/man/man1'
472 SCRIPT_NAME='inxi'
473 SCRIPT_PATCH_NUMBER=''
474 SCRIPT_PATH='' #filled-in in Main
475 SCRIPT_VERSION_NUMBER=""        #filled-in in Main
476 SCRIPT_DOWNLOAD='https://github.com/smxi/inxi/raw/master/'
477 SCRIPT_DOWNLOAD_BRANCH_1='https://github.com/smxi/inxi/raw/one/'
478 SCRIPT_DOWNLOAD_BRANCH_2='https://github.com/smxi/inxi/raw/two/'
479 SCRIPT_DOWNLOAD_BRANCH_3='https://github.com/smxi/inxi/raw/three/'
480 SCRIPT_DOWNLOAD_BRANCH_4='https://github.com/smxi/inxi/raw/four/'
481 SCRIPT_DOWNLOAD_BRANCH_BSD='https://github.com/smxi/inxi/raw/bsd/'
482 SCRIPT_DOWNLOAD_BRANCH_GNUBSD='https://github.com/smxi/inxi/raw/gnubsd/'
483 SCRIPT_DOWNLOAD_DEV='http://smxi.org/test/'
484 # note, you can use any ip url here as long as it's the only line on the output page.
485 # Also the ip address must be the last thing on that line. If you abuse this ip tool 
486 # you will be banned from further access. Most > 24x daily automated queries to it are abuse.
487 WAN_IP_URL='http://smxi.org/opt/ip.php'
488 KONVI_CFG="konversation/scripts/$SCRIPT_NAME.conf" # relative path to $(kde-config --path data)
489
490 ### INITIALIZE VARIABLES NULL ###
491 BSD_TYPE=''
492 BSD_VERSION=
493 CMDL_MAX=''
494
495 DEV_DISK_ID=''
496 DEV_DISK_LABEL=''
497 DEV_DISK_MAPPER=''
498 DEV_DISK_UUID=''
499 DMIDECODE_DATA=''
500 DNSTOOL=''
501 DOWNLOADER='wget'
502 IRC_CLIENT=''
503 IRC_CLIENT_VERSION=''
504 PS_THROTTLED=''
505 REPO_DATA=''
506
507 ### LAYOUT ###
508 # These two determine separators in single line output, to force irc clients not to break off sections
509 SEP1='~'
510 SEP2=' '
511 # these will assign a separator to non irc states. Important! Using ':' can trigger stupid emoticon
512 # behaviors in output on IRC, so do not use those.
513 SEP3_IRC=''
514 SEP3_CONSOLE=':'
515 SEP3='' # do not set, will be set dynamically
516 LINE1='---------------------------------------------------------------------------'
517 LINE2='- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
518
519 # Default indentation level. NOTE: actual indent is 1 greater to allow for spacing
520 INDENT=10
521
522 ### COLUMN WIDTHS ###
523 COLS_INNER='' ## for width minus INDENT
524 COLS_MAX=''
525
526 # these will be set dynamically in main()
527 TERM_COLUMNS=80
528 TERM_LINES=100
529
530 # Only for legacy user config files se we can test and convert the var name
531 LINE_MAX_CONSOLE=''
532 LINE_MAX_IRC=''
533
534 ### COLORS ###
535 # Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Use following variables in config 
536 # files to change defaults for each type, or global
537 # Same as runtime parameter.
538 DEFAULT_COLOR_SCHEME=2
539 ## color variables - set dynamically
540 COLOR_SCHEME=''
541 C1=''
542 C2=''
543 CN=''
544 ## Always leave these blank, these are only going to be set in inxi.conf files, that makes testing
545 ## for user changes easier after sourcing the files
546 ESC='\x1b'
547 GLOBAL_COLOR_SCHEME=''
548 IRC_COLOR_SCHEME=''
549 IRC_CONS_COLOR_SCHEME=''
550 IRC_X_TERM_COLOR_SCHEME=''
551 CONSOLE_COLOR_SCHEME=''
552 VIRT_TERM_COLOR_SCHEME=''
553
554 ## Output colors
555 # A more elegant way to have a scheme that doesn't print color codes (neither ANSI nor mIRC) at all. See below.
556 unset EMPTY
557 #             DGREY   BLACK   RED     DRED    GREEN   DGREEN  YELLOW  DYELLOW
558 ANSI_COLORS="\e[1;30m \e[0;30m \e[1;31m \e[0;31m \e[1;32m \e[0;32m \e[1;33m \e[0;33m"
559 IRC_COLORS="  \x0314  \x0301  \x0304  \x0305  \x0309  \x0303  \x0308  \x0307"
560 #                          BLUE    DBLUE   MAGENTA DMAGENTA CYAN   DCYAN   WHITE   GREY    NORMAL
561 ANSI_COLORS="$ANSI_COLORS \e[1;34m \e[0;34m \e[1;35m \e[0;35m \e[1;36m \e[0;36m \e[1;37m \e[0;37m \e[0;37m"
562 IRC_COLORS=" $IRC_COLORS    \x0312 \x0302  \x0313  \x0306  \x0311  \x0310  \x0300  \x0315  \x03"
563
564 #ANSI_COLORS=($ANSI_COLORS); IRC_COLORS=($IRC_COLORS)
565 A_COLORS_AVAILABLE=( DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL )
566
567 # See above for notes on EMPTY
568 ## note: group 1: 0, 1 are null/normal
569 ## Following: group 2: generic, light/dark or dark/light; group 3: dark on light; group 4 light on dark; 
570 # this is the count of the first two groups, starting at zero
571 SAFE_COLOR_COUNT=12
572 A_COLOR_SCHEMES=( 
573 EMPTY,EMPTY,EMPTY 
574 NORMAL,NORMAL,NORMAL 
575
576 BLUE,NORMAL,NORMAL
577 BLUE,RED,NORMAL 
578 CYAN,BLUE,NORMAL 
579 DCYAN,NORMAL,NORMAL
580 DCYAN,BLUE,NORMAL 
581 DGREEN,NORMAL,NORMAL 
582 DYELLOW,NORMAL,NORMAL 
583 GREEN,DGREEN,NORMAL 
584 GREEN,NORMAL,NORMAL 
585 MAGENTA,NORMAL,NORMAL
586 RED,NORMAL,NORMAL
587
588 BLACK,DGREY,NORMAL
589 DBLUE,DGREY,NORMAL 
590 DBLUE,DMAGENTA,NORMAL
591 DBLUE,DRED,NORMAL 
592 DBLUE,BLACK,NORMAL
593 DGREEN,DYELLOW,NORMAL 
594 DYELLOW,BLACK,NORMAL
595 DMAGENTA,BLACK,NORMAL
596 DCYAN,DBLUE,NORMAL
597
598 WHITE,GREY,NORMAL
599 GREY,WHITE,NORMAL
600 CYAN,GREY,NORMAL 
601 GREEN,WHITE,NORMAL 
602 GREEN,YELLOW,NORMAL 
603 YELLOW,WHITE,NORMAL 
604 MAGENTA,CYAN,NORMAL 
605 MAGENTA,YELLOW,NORMAL
606 RED,CYAN,NORMAL
607 RED,WHITE,NORMAL 
608 BLUE,WHITE,NORMAL
609
610 RED,BLUE,NORMAL 
611 RED,DBLUE,NORMAL
612 BLACK,BLUE,NORMAL
613 BLACK,DBLUE,NORMAL
614 NORMAL,BLUE,NORMAL
615 BLUE,MAGENTA,NORMAL
616 DBLUE,MAGENTA,NORMAL
617 BLACK,MAGENTA,NORMAL
618 MAGENTA,BLUE,NORMAL
619 MAGENTA,DBLUE,NORMAL
620 )
621
622 #echo ${#A_COLOR_SCHEMES[@]};exit
623
624 # WARNING: In the main part below (search for 'KONVI')
625 # there's a check for Konversation-specific config files.
626 # Any one of these can override the above if inxi is run
627 # from Konversation!
628
629 ## DISTRO DATA/ID ##
630 # In cases of derived distros where the version file of the base distro can also be found under /etc,
631 # the derived distro's version file should go first. (Such as with Sabayon / Gentoo)
632 DISTROS_DERIVED="antix-version aptosid-version kanotix-version knoppix-version mandrake-release pardus-release porteus-version sabayon-release siduction-version sidux-version slitaz-release solusos-release turbolinux-release zenwalk-version"
633 # debian_version excluded from DISTROS_PRIMARY so Debian can fall through to /etc/issue detection. Same goes for Ubuntu.
634 DISTROS_EXCLUDE_LIST="debian_version devuan_version ubuntu_version"
635 DISTROS_PRIMARY="arch-release gentoo-release redhat-release slackware-version SuSE-release"
636 DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-release"
637 # this is being used both by core distros and derived distros now, eg, solusos 1 uses it for solusos id, while
638 # debian, solusos base, uses it as well, so we have to know which it is.
639 DISTROS_OS_RELEASE_GOOD="arch-release SuSE-release "
640 ## Distros with known problems
641 # DSL (Bash 2.05b: grep -m doesn't work; arrays won't work) --> unusable output
642 # Puppy Linux 4.1.2 (Bash 3.0: arrays won't work) --> works partially
643
644 ## OUTPUT FILTERS/SEARCH ##
645 # Note that \<ltd\> bans only words, not parts of strings; in \<corp\> you can't use punctuation characters like . or ,
646 # we're saving about 10+% of the total script exec time by hand building the ban lists here, using hard quotes.
647
648 BAN_LIST_NORMAL='chipset|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|incorporation|industrial|international|nee|revision|semiconductor|software|technologies|technology|ltd\.|\<ltd\>|inc\.|\<inc\>|intl\.|co\.|\<co\>|corp\.|\<corp\>|\(tm\)|\(r\)|®|\(rev ..\)'
649 BAN_LIST_CPU='@||cpu |cpu deca|dual core|dual-core|tri core|tri-core|quad core|quad-core|ennea|genuine|hepta|hexa|multi|octa|penta|processor|single|triple|[0-9\.]+ *[MmGg][Hh][Zz]'
650 # See github issue 75 for more details on value: *, triggers weird behaviors if present in value
651 # /sys/devices/virtual/dmi/id/product_name:['*']
652 # this is for bash arrays AND avoiding * in arrays: ( fred * greg ) expands to the contents of the directory
653 BAN_LIST_ARRAY=',|\*'
654
655 SENSORS_GPU_SEARCH='amdgpu|intel|radeon|nouveau'
656
657 ### USB networking search string data, because some brands can have other products than
658 ### wifi/nic cards, they need further identifiers, with wildcards.
659 ### putting the most common and likely first, then the less common, then some specifics
660 USB_NETWORK_SEARCH="Wi-Fi.*Adapter|Wireless.*Adapter|Ethernet.*Adapter|WLAN.*Adapter|Network.*Adapter|802\.11|Atheros|Atmel|D-Link.*Adapter|D-Link.*Wireless|Linksys|Netgea|Ralink|Realtek.*Network|Realtek.*Wireless|Realtek.*WLAN|Belkin.*Wireless|Belkin.*WLAN|Belkin.*Network"
661 USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|Actiontec.*Wireless|Actiontec.*Network|AirLink.*Wireless|Asus.*Network|Asus.*Wireless|Buffalo.*Wireless|Davicom|DWA-.*RangeBooster|DWA-.*Wireless|ENUWI-.*Wireless|LG.*Wi-Fi|Rosewill.*Wireless|RNX-.*Wireless|Samsung.*LinkStick|Samsung.*Wireless|Sony.*Wireless|TEW-.*Wireless|TP-Link.*Wireless|WG[0-9][0-9][0-9].*Wireless|WNA[0-9][0-9][0-9]|WNDA[0-9][0-9][0-9]|Zonet.*ZEW.*Wireless|54 Mbps" 
662 # then a few known hard to ID ones added 
663 # belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda; 
664 USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|050d:935b|0bda:8189|0bda:8197"
665
666 ########################################################################
667 #### MAIN: Where it all begins
668 ########################################################################
669 main()
670 {
671         eval $LOGFS
672         
673         local color_scheme='' kde_config_app=''
674         # this will be used by all functions following
675         local Ps_aux_Data="$( ps aux )"
676
677         # This function just initializes variables
678         initialize_data
679         
680         # Source global config overrides, needs to be here because some things
681         # can be reset that were set in initialize, but check_required_apps needs
682         if [[ -s /etc/$SCRIPT_NAME.conf ]];then
683                 source /etc/$SCRIPT_NAME.conf
684         fi
685         # Source user config variables override /etc/inxi.conf variables
686         if [[ -s $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf ]];then
687                 source $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf
688         fi
689         set_display_width 'live' # can be reset with -y
690         
691         # echo SCHEME $SCHEME
692         # echo B_IRC $B_IRC
693         # echo sep3: $SEP3
694         # Check for dependencies BEFORE running ANYTHING else except above functions
695         # Not all distro's have these depends installed by default. Don't want to run
696         # this if the user is requesting to see this information in the first place
697         # Only continue if required apps tests ok
698         if [[ $1 != '--recommends' ]];then
699                 check_required_apps
700                 check_recommended_apps
701         fi
702
703         SCRIPT_VERSION_NUMBER=$( parse_version_data 'main' )
704         SCRIPT_PATCH_NUMBER=$( parse_version_data 'patch' )
705         
706         # previous source location, check for bugs
707
708         ## this needs to run before the KONVI stuff is set below
709         ## Konversation 1.2 apparently does not like the $PPID test in get_start_client
710         ## So far there is no known way to detect if qt4_konvi is the parent process
711         ## this method will infer qt4_konvi as parent
712         get_start_client
713
714         # note: this only works if it's run from inside konversation as a script builtin or something
715         # only do this if inxi has been started as a konversation script, otherwise bypass this 
716         #       KONVI=3 ## for testing puroses
717         if [[ $KONVI -eq 1 || $KONVI -eq 3 ]];then
718                 if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (ie 1.x < 1.2(qt3))    
719                         DCPORT="$1"
720                         DCSERVER="$2"
721                         DCTARGET="$3"
722                         shift 3
723                 elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4))
724                         DCSERVER="$1" ##dbus testing
725                         DCTARGET="$2" ##dbus testing
726                         shift 2
727                 fi
728                 # always have the current stable kde version tested first, 
729                 # then use fallbacks and future proofing
730                 if type -p kde4-config &>/dev/null;then
731                         kde_config_app='kde4-config'
732                 elif type -p kde5-config &>/dev/null;then
733                         kde_config_app='kde5-config'
734                 elif type -p kde-config &>/dev/null;then
735                         kde_config_app='kde-config'
736                 fi
737                 # The section below is on request of Argonel from the Konversation developer team:
738                 # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf
739                 if [[ -n $kde_config_app ]];then
740                         IFS=":"
741                         for kde_config in $( $kde_config_app --path data )
742                         do
743                                 if [[ -r $kde_config$KONVI_CFG ]];then
744                                         source "$kde_config$KONVI_CFG"
745                                         break
746                                 fi
747                         done
748                         IFS="$ORIGINAL_IFS"
749                 fi
750         fi
751
752         ## leave this for debugging dcop stuff if we get that working
753         #       print_screen_output "DCPORT: $DCPORT"
754         #       print_screen_output "DCSERVER: $DCSERVER"
755         #       print_screen_output "DCTARGET: $DCTARGET"
756         
757         # first init function must be set first for colors etc. Remember, no debugger
758         # stuff works on this function unless you set the debugging flag manually.
759         # Debugging flag -@ [number] will not work until get_parameters runs.
760         
761         # "$@" passes every parameter separately quoted, "$*" passes all parameters as one quoted parameter.
762         # must be here to allow debugger and other flags to be set.
763         get_parameters "$@"
764
765         # If no colorscheme was set in the parameter handling routine, then set the default scheme
766         if [[ $B_COLOR_SCHEME_SET != 'true' ]];then
767                 # This let's user pick their color scheme. For IRC, only shows the color schemes, no interactive
768                 # The override value only will be placed in user config files. /etc/inxi.conf can also override
769                 if [[ $B_RUN_COLOR_SELECTOR == 'true' ]];then 
770                         select_default_color_scheme
771                 else
772                         # set the default, then override as required
773                         color_scheme=$DEFAULT_COLOR_SCHEME
774                         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
775                                 color_scheme=$GLOBAL_COLOR_SCHEME
776                         else
777                                 if [[ $B_IRC == 'false' ]];then
778                                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
779                                                 color_scheme=$CONSOLE_COLOR_SCHEME
780                                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
781                                                 color_scheme=$VIRT_TERM_COLOR_SCHEME
782                                         fi
783                                 else
784                                         if [[ -n $IRC_X_TERM_COLOR_SCHEME && $B_CONSOLE_IRC == 'true' && -n $B_RUNNING_IN_DISPLAY ]];then
785                                                 color_scheme=$IRC_X_TERM_COLOR_SCHEME
786                                         elif [[ -n $IRC_CONS_COLOR_SCHEME && -z $DISPLAY ]];then
787                                                 color_scheme=$IRC_CONS_COLOR_SCHEME
788                                         elif [[ -n $IRC_COLOR_SCHEME ]];then
789                                                 color_scheme=$IRC_COLOR_SCHEME
790                                         fi
791                                 fi
792                         fi
793                         set_color_scheme $color_scheme
794                 fi
795         fi
796         if [[ $B_IRC == 'false' ]];then
797                 SEP3=$SEP3_CONSOLE
798         else
799                 # too hard to read if no colors, so force that for users on irc
800                 if [[ $SCHEME == 0 ]];then
801                         SEP3=$SEP3_CONSOLE
802                 else
803                         SEP3=$SEP3_IRC
804                 fi
805         fi
806         
807         # all the pre-start stuff is in place now
808         B_SCRIPT_UP='true'
809         script_debugger "Debugger: $SCRIPT_NAME is up and running..."
810         
811         # then create the output
812         print_it_out
813
814         eval $LOGFE
815         # weechat's executor plugin forced me to do this, and rightfully so, because else the exit code
816         # from the last command is taken..
817         exit 0
818 }
819
820 #### -------------------------------------------------------------------
821 #### basic tests: set script data, booleans, PATH, version numbers
822 #### -------------------------------------------------------------------
823
824 # Set PATH data so we can access all programs as user. Set BAN lists.
825 # initialize some boleans, these directories are used throughout the script
826 # some apps are used for extended functions any directory used, should be
827 # checked here first.
828 # No args taken.
829 initialize_data()
830 {
831         eval $LOGFS
832         BSD_VERSION=$( uname -s 2>/dev/null | tr '[A-Z]' '[a-z]' )
833         # note: archbsd says they are a freebsd distro, so assuming it's the same as freebsd
834         if [[ -z ${BSD_VERSION/*bsd*/} || -z ${BSD_VERSION/*dragonfly*/} || -z ${BSD_VERSION/*darwin*/} ]];then
835                 if [[ -z ${BSD_VERSION/*openbsd*/} ]];then
836                         BSD_VERSION='openbsd'
837                 elif [[ -z ${BSD_VERSION/*darwin*/} ]];then
838                         BSD_VERSION='darwin'
839                 fi
840                 # GNU/kfreebsd will by definition have GNU tools like sed/grep
841                 if [[ -z ${BSD_VERSION/*kfreebsd*/} ]];then
842                         BSD_TYPE='debian-bsd' # debian gnu bsd
843                 else
844                         BSD_TYPE='bsd' # all other bsds
845                         SED_I="-i ''"
846                         SED_RX='-E'
847                         ESC=$(echo | tr '\n' '\033')
848                 fi
849         fi
850         # now set the script BOOLEANS for files required to run features
851         # note that freebsd has /proc but it's empty
852         if [[ -d "/proc/" && -z $BSD_TYPE ]];then
853                 B_PROC_DIR='true'
854         elif [[ -n $BSD_TYPE ]];then
855                 B_PROC_DIR='false'
856         else
857                 error_handler 6
858         fi
859         
860         initialize_paths
861         
862         if type -p dig &>/dev/null;then
863                 DNSTOOL='dig'
864         fi
865         
866         # set downloaders. 
867         if ! type -p wget &>/dev/null;then
868                 # first check for bsd stuff
869                 if type -p fetch &>/dev/null;then
870                         DOWNLOADER='fetch'
871                 elif type -p curl &>/dev/null;then
872                         DOWNLOADER='curl'
873                 elif [[ $BSD_VERSION == 'openbsd' && -n $( type -p ftp ) ]];then
874                         DOWNLOADER='ftp'
875                 else
876                         DOWNLOADER='no-downloader'
877                 fi
878         fi
879         
880         if [[ -n $BSD_TYPE ]];then
881                 if [[ -e $FILE_DMESG_BOOT ]];then
882                         B_DMESG_BOOT_FILE='true'
883                 fi
884         else
885                 # found a case of battery existing but having nothing in it on desktop mobo
886                 # not all laptops show the first. /proc/acpi/battery is deprecated.
887                 if [[ -n $( ls /proc/acpi/battery 2>/dev/null ) || -n $( ls /sys/class/power_supply/ 2>/dev/null )  ]];then
888                         B_PORTABLE='true'
889                 fi
890         fi
891         if [[ -e $FILE_CPUINFO ]]; then
892                 B_CPUINFO_FILE='true'
893         fi
894         if [[ -e $FILE_MEMINFO ]];then
895                 B_MEMINFO_FILE='true'
896         fi
897         if [[ -e $FILE_ASOUND_DEVICE ]];then
898                 B_ASOUND_DEVICE_FILE='true'
899         fi
900         if [[ -e $FILE_ASOUND_VERSION ]];then
901                 B_ASOUND_VERSION_FILE='true'
902         fi
903         if [[ -f $FILE_LSB_RELEASE ]];then
904                 B_LSB_FILE='true'
905         fi
906         if [[ -f $FILE_OS_RELEASE ]];then
907                 B_OS_RELEASE_FILE='true'
908         fi
909         if [[ -e $FILE_SCSI ]];then
910                 B_SCSI_FILE='true'
911         fi
912         if [[ -n $DISPLAY ]];then
913                 B_SHOW_DISPLAY_DATA='true'
914                 B_RUNNING_IN_DISPLAY='true'
915         fi
916         if [[ -e $FILE_MDSTAT ]];then
917                 B_MDSTAT_FILE='true'
918         fi
919         if [[ -e $FILE_MODULES ]];then
920                 B_MODULES_FILE='true'
921         fi
922         if [[ -e $FILE_MOUNTS ]];then
923                 B_MOUNTS_FILE='true'
924         fi
925         if [[ -e $FILE_PARTITIONS ]];then
926                 B_PARTITIONS_FILE='true'
927         fi
928         # default to the normal location, then search for it
929         if [[ -e $FILE_XORG_LOG ]];then
930                 B_XORG_LOG='true'
931         else
932                 # Detect location of the Xorg log file
933                 if type -p xset &>/dev/null; then
934                         FILE_XORG_LOG=$( xset q 2>/dev/null | grep -i 'Log file' | gawk '{print $3}')
935                         if [[ -e $FILE_XORG_LOG ]];then
936                                 B_XORG_LOG='true'
937                         fi
938                 fi
939         fi
940         # gfx output will require this flag
941         if [[ $( whoami ) == 'root' ]];then
942                 B_ROOT='true'
943         fi
944         eval $LOGFE
945 }
946
947 # args: $1 - default OR override default cols max integer count
948 set_display_width()
949 {
950         local cols_max_override=$1
951         
952         if [[ $cols_max_override == 'live' ]];then
953                 ## sometimes tput will trigger an error (mageia) if irc client
954                 if [[ $B_IRC == 'false' ]];then
955                         if type -p tput &>/dev/null;then
956                                 TERM_COLUMNS=$(tput cols)
957                                 TERM_LINES=$(tput lines)
958                         fi
959                         # double check, just in case it's missing functionality or whatever
960                         if [[ -z $TERM_COLUMNS || -n ${TERM_COLUMNS//[0-9]/} ]];then
961                                 TERM_COLUMNS=80
962                                 TERM_LINES=100
963                         fi
964                 fi
965                 # Convert to new variable names if set in config files, legacy test
966                 if [[ -n $LINE_MAX_CONSOLE ]];then
967                         COLS_MAX_CONSOLE=$LINE_MAX_CONSOLE
968                 fi
969                 if [[ -n $LINE_MAX_IRC ]];then
970                         COLS_MAX_IRC=$LINE_MAX_IRC
971                 fi
972                 # this lets you set different widths for in or out of display server
973         #       if [[ $B_RUNNING_IN_DISPLAY == 'false' && -n $COLS_MAX_NO_DISPLAY ]];then
974         #               COLS_MAX_CONSOLE=$COLS_MAX_NO_DISPLAY
975         #       fi
976                 # TERM_COLUMNS is set in top globals, using tput cols
977                 # echo tc: $TERM_COLUMNS cmc: $COLS_MAX_CONSOLE
978                 if [[ $TERM_COLUMNS -lt $COLS_MAX_CONSOLE ]];then
979                         COLS_MAX_CONSOLE=$TERM_COLUMNS
980                 fi
981                 # adjust, some terminals will wrap if output cols == term cols
982                 COLS_MAX_CONSOLE=$(( $COLS_MAX_CONSOLE - 2 ))
983                 # echo cmc: $COLS_MAX_CONSOLE
984                 # comes after source for user set stuff
985                 if [[ $B_IRC == 'false' ]];then
986                         COLS_MAX=$COLS_MAX_CONSOLE
987                 else
988                         COLS_MAX=$COLS_MAX_IRC
989                 fi
990         else
991                 COLS_MAX=$cols_max_override
992         fi
993         COLS_INNER=$(( $COLS_MAX - $INDENT - 1 ))
994         # echo cm: $COLS_MAX ci: $COLS_INNER
995 }
996
997 # arg: $1 - version number: main/patch/date
998 parse_version_data()
999 {
1000         local version_data=''
1001
1002         # note, using ####[[:space:]]+ to avoid having this function also trip the version datas
1003         case $1 in
1004                 date)
1005                         version_data=$( gawk -F ': ' '
1006                         /####[[:space:]]+Date:/ {
1007                                 print $NF
1008                         }' "$SCRIPT_PATH/$SCRIPT_NAME" )
1009                         ;;
1010                 main)
1011                         version_data=$( gawk '
1012                         /####[[:space:]]+Version:/ {
1013                                 print $3
1014                         }' "$SCRIPT_PATH/$SCRIPT_NAME" )
1015                         ;;
1016                 patch)
1017                         version_data=$( gawk '
1018                         /####[[:space:]]+Patch Number:/ {
1019                                 print $4
1020                         }' "$SCRIPT_PATH/$SCRIPT_NAME" )
1021                         ;;
1022         esac
1023         echo $version_data
1024 }
1025
1026 initialize_paths()
1027 {
1028         local path='' added_path='' b_path_found='' sys_path=''
1029         # Extra path variable to make execute failures less likely, merged below
1030         local extra_paths="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/local/bin"
1031         
1032         # this needs to be set here because various options call the parent initialize function directly.
1033         SCRIPT_PATH=$( dirname "$0" )
1034
1035         # Fallback paths put into $extra_paths; This might, among others, help on gentoo.
1036         # Now, create a difference of $PATH and $extra_paths and add that to $PATH:
1037         IFS=":"
1038         for path in $extra_paths
1039         do
1040                 b_path_found='false'
1041                 for sys_path in $PATH
1042                 do
1043                         if [[ $path == $sys_path ]];then
1044                                 b_path_found='true'
1045                         fi
1046                 done
1047                 if [[ $b_path_found == 'false' ]];then
1048                         added_path="$added_path:$path"
1049                 fi
1050         done
1051
1052         IFS="$ORIGINAL_IFS"
1053         PATH="$PATH$added_path"
1054         # echo "PATH='$PATH'"
1055         ##/bin/sh -c 'echo "PATH in subshell=\"$PATH\""'
1056 }
1057 # No args taken.
1058 check_recommended_apps()
1059 {
1060         eval $LOGFS
1061         local bash_array_test=( "one" "two" )
1062
1063         # check for array ability of bash, this is only good for the warning at this time
1064         # the boolean could be used later
1065         # bash version 2.05b is used in DSL
1066         # bash version 3.0 is used in Puppy Linux; it has a known array bug <reference to be placed here>
1067         # versions older than 3.1 don't handle arrays
1068         # distro's using below 2.05b are unknown, released in 2002
1069         if [[ ${bash_array_test[1]} -eq "two" ]];then
1070                 B_BASH_ARRAY='true'
1071         else
1072                 script_debugger "Suggestion: update to Bash v3.1 for optimal inxi output"
1073         fi
1074         # test for a few apps that bsds may not have after initial tests
1075         if type -p lspci &>/dev/null;then
1076                 B_LSPCI='true'
1077         fi
1078         if [[ -n $BSD_TYPE ]];then
1079                 if type -p sysctl &>/dev/null;then
1080                         B_SYSCTL='true'
1081                 fi
1082                 if type -p pciconf &>/dev/null;then
1083                         B_PCICONF='true'
1084                 fi
1085         fi
1086         # now setting qdbus/dcop for first run, some systems can have both by the way
1087         if type -p qdbus &>/dev/null;then
1088                 B_QDBUS='true'
1089         fi
1090         if type -p dcop &>/dev/null;then
1091                 B_DCOP='true'
1092         fi
1093         eval $LOGFE
1094 }
1095
1096 # Determine if any of the absolutely necessary tools are absent
1097 # No args taken.
1098 check_required_apps()
1099 {
1100         eval $LOGFS
1101         local app_name=''
1102         # bc removed from deps for now
1103         local depends="df gawk grep ps readlink tr uname wc"
1104         
1105         if [[ -z $BSD_TYPE  ]];then
1106                 depends="$depends lspci"
1107         elif [[ $BSD_TYPE == 'bsd' ]];then
1108                 depends="$depends sysctl"
1109                 # debian-bsd has lspci but you must be root to run it
1110         elif [[ $BSD_TYPE == 'debian-bsd' ]];then
1111                 depends="$depends sysctl lspci"
1112         fi
1113         # no need to add xprop because it will just give N/A if not there, but if we expand use of xprop,
1114         # should add that here as a test, then use the B_SHOW_DISPLAY_DATA flag to trigger the tests in de function
1115         local x_apps="xrandr xdpyinfo glxinfo" 
1116
1117         if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
1118                 for app_name in $x_apps
1119                 do
1120                         if ! type -p $app_name &>/dev/null;then
1121                                 script_debugger "Resuming in non X mode: $app_name not found. For package install advice run: $SCRIPT_NAME --recommends"
1122                                 B_SHOW_DISPLAY_DATA='false'
1123                                 break
1124                         fi
1125                 done
1126         fi
1127
1128         app_name=''
1129
1130         for app_name in $depends
1131         do
1132                 if ! type -p $app_name &>/dev/null;then
1133                         error_handler 5 "$app_name"
1134                 fi
1135         done
1136         eval $LOGFE
1137 }
1138
1139 ## note: this is now running inside each gawk sequence directly to avoid exiting gawk
1140 ## looping in bash through arrays, then re-entering gawk to clean up, then writing back to array
1141 ## in bash. For now I'll leave this here because there's still some interesting stuff to get re methods
1142 # Enforce boilerplate and buzzword filters
1143 # args: $1 - BAN_LIST_NORMAL/BAN_LIST_CPU; $2 - string to sanitize
1144 sanitize_characters()
1145 {
1146         eval $LOGFS
1147         # Cannot use strong quotes to unquote a string with pipes in it!
1148         # bash will interpret the |'s as usual and try to run a subshell!
1149         # Using weak quotes instead, or use '"..."'
1150         echo "$2" | gawk "
1151         BEGIN {
1152                 IGNORECASE=1
1153         }
1154         {
1155                 gsub(/${!1}/,\"\")
1156                 gsub(/ [ ]+/,\" \")    ## ([ ]+) with (space)
1157                 gsub(/^ +| +$/,\"\")   ## (pipe char) with (nothing)
1158                 print                  ## prints (returns) cleaned input
1159         }"
1160         eval $LOGFE
1161 }
1162
1163 # Set the colorscheme
1164 # args: $1 = <scheme number>|<"none">
1165 set_color_scheme()
1166 {
1167         eval $LOGFS
1168         local i='' a_output_colors='' a_color_codes=''
1169
1170         if [[ $1 -ge ${#A_COLOR_SCHEMES[@]} ]];then
1171                 set -- 1
1172         fi
1173         # Set a global variable to allow checking for chosen scheme later
1174         SCHEME="$1"
1175         if [[ $B_IRC == 'false' ]];then
1176                 a_color_codes=( $ANSI_COLORS )
1177         else
1178                 a_color_codes=( $IRC_COLORS )
1179         fi
1180         for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ ))
1181         do
1182                 eval "${A_COLORS_AVAILABLE[i]}=\"${a_color_codes[i]}\""
1183         done
1184         IFS=","
1185         a_output_colors=( ${A_COLOR_SCHEMES[$1]} )
1186         IFS="$ORIGINAL_IFS"
1187         # then assign the colors globally
1188         C1="${!a_output_colors[0]}"
1189         C2="${!a_output_colors[1]}"
1190         CN="${!a_output_colors[2]}"
1191         # ((COLOR_SCHEME++)) ## note: why is this? ##
1192         # handle some explicit colors that are used for no color 0
1193         if [[ $SCHEME -eq 0 ]];then
1194                 NORMAL=''
1195                 RED=''
1196         fi
1197         eval $LOGFE
1198 }
1199
1200 select_default_color_scheme()
1201 {
1202         eval $LOGFS
1203         local spacer='  ' options='' user_selection='' config_variable=''
1204         local config_file="$HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf"
1205         local irc_clear="\e[0m" 
1206         local irc_gui='Unset' irc_console='Unset' irc_x_term='Unset'
1207         local console='Unset' virt_term='Unset' global='Unset' 
1208         
1209         if [[ -n $IRC_COLOR_SCHEME ]];then
1210                 irc_gui="Set: $IRC_COLOR_SCHEME"
1211         fi
1212         if [[ -n $IRC_CONS_COLOR_SCHEME ]];then
1213                 irc_console="Set: $IRC_CONS_COLOR_SCHEME"
1214         fi
1215         if [[ -n $IRC_X_TERM_COLOR_SCHEME ]];then
1216                 irc_x_term="Set: $IRC_X_TERM_COLOR_SCHEME"
1217         fi
1218         if [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1219                 virt_term="Set: $VIRT_TERM_COLOR_SCHEME"
1220         fi
1221         if [[ -n $CONSOLE_COLOR_SCHEME ]];then
1222                 console="Set: $CONSOLE_COLOR_SCHEME"
1223         fi
1224         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
1225                 global="Set: $GLOBAL_COLOR_SCHEME"
1226         fi
1227         
1228         # don't want these printing in irc since they show literally
1229         if [[ $B_IRC == 'true' ]];then
1230                 irc_clear=''
1231         fi
1232         # first make output neutral so it's just plain default for console client
1233         set_color_scheme "0"
1234         # print_lines_basic "0" "" ""
1235         if [[ $B_IRC == 'false' ]];then
1236                 print_lines_basic "0" "" "Welcome to $SCRIPT_NAME! Please select the default $COLOR_SELECTION color scheme."
1237                 # print_screen_output "You will see this message only one time per user account, unless you set preferences in: /etc/$SCRIPT_NAME.conf"
1238                 print_screen_output " "
1239         fi
1240         print_lines_basic "0" "" "Because there is no way to know your $COLOR_SELECTION foreground/background colors, you can set your color preferences from color scheme option list below. 0 is no colors, 1 neutral. After these, there are 4 sets: 1-dark or light backgrounds; 2-light backgrounds; 3-dark backgrounds; 4-miscellaneous."
1241         if [[ $B_IRC == 'false' ]];then
1242                 print_lines_basic "0" "" "Please note that this will set the $COLOR_SELECTION preferences only for user: $(whoami)"
1243         fi
1244         print_screen_output "$LINE1"
1245         for (( i=0; i < ${#A_COLOR_SCHEMES[@]}; i++ ))
1246         do
1247                 if [[ $i -gt 9 ]];then
1248                         spacer=' '
1249                 fi
1250                 # only offer the safe universal defaults
1251                 case $COLOR_SELECTION in
1252                         global|irc|irc-console|irc-virtual-terminal)
1253                                 if [[ $i -gt $SAFE_COLOR_COUNT ]];then
1254                                         break
1255                                 fi
1256                                 ;;
1257                 esac
1258                 set_color_scheme $i
1259                 print_screen_output "$irc_clear $i)$spacer${C1}Card:${C2} nVidia G86 [GeForce 8400 GS] ${C1}X.Org${C2} 1.7.7"
1260         done
1261         set_color_scheme 0
1262         
1263         if [[ $B_IRC == 'false' ]];then
1264                 echo -n "\e[0m"
1265                 
1266                 print_screen_output "$irc_clear $i)${spacer}Remove all color settings. Restore $SCRIPT_NAME default."
1267                 print_screen_output "$irc_clear $(($i+1)))${spacer}Continue, no changes or config file setting."
1268                 print_screen_output "$irc_clear $(($i+2)))${spacer}Exit, use another terminal, or set manually."
1269                 print_screen_output "$LINE1"
1270                 print_lines_basic "0" "" "Simply type the number for the color scheme that looks best to your eyes for your $COLOR_SELECTION settings and hit ENTER. NOTE: You can bring this option list up by starting $SCRIPT_NAME with option: -c plus one of these numbers:"
1271                 print_lines_basic "0" "" "94^(console,^no X^-^$console); 95^(terminal,^X^-^$virt_term); 96^(irc,^gui,^X^-^$irc_gui); 97^(irc,^X,^in^terminal^-^$irc_x_term); 98^(irc,^no^X^-^$irc_console); 99^(global^-^$global)"
1272                 print_lines_basic "0" "" ""
1273                 print_screen_output "Your selection(s) will be stored here: $config_file"
1274                 print_lines_basic "0" "" "Global overrides all individual color schemes. Individual schemes remove the global setting."
1275                 print_screen_output "$LINE1"
1276                 read user_selection
1277                 if [[ "$user_selection" =~ ^([0-9]+)$ && $user_selection -lt $i ]];then
1278                         case $COLOR_SELECTION in
1279                                 irc)
1280                                         config_variable='IRC_COLOR_SCHEME'
1281                                         ;;
1282                                 irc-console)
1283                                         config_variable='IRC_CONS_COLOR_SCHEME'
1284                                         ;;
1285                                 irc-virtual-terminal)
1286                                         config_variable='IRC_X_TERM_COLOR_SCHEME'
1287                                         ;;
1288                                 console)
1289                                         config_variable='CONSOLE_COLOR_SCHEME'
1290                                         ;;
1291                                 virtual-terminal)
1292                                         config_variable='VIRT_TERM_COLOR_SCHEME'
1293                                         ;;
1294                                 global)
1295                                         config_variable='GLOBAL_COLOR_SCHEME'
1296                                         ;;
1297                         esac
1298                         set_color_scheme $user_selection
1299                         # make file/directory first if missing
1300                         if [[ ! -f $config_file ]];then
1301                                 if [[ ! -d $HOME/.$SCRIPT_NAME ]];then
1302                                         mkdir $HOME/.$SCRIPT_NAME
1303                                 fi
1304                                 touch $config_file
1305                         fi
1306                         if [[ -z $( grep -s "$config_variable=" $config_file ) ]];then
1307                                 print_lines_basic "0" "" "Creating and updating config file for $COLOR_SELECTION color scheme now..."
1308                                 echo "$config_variable=$user_selection" >> $config_file
1309                         else
1310                                 print_screen_output "Updating config file for $COLOR_SELECTION color scheme now..."
1311                                 sed $SED_I "s/$config_variable=.*/$config_variable=$user_selection/" $config_file
1312                         fi
1313                         # file exists now so we can go on to cleanup
1314                         case $COLOR_SELECTION in
1315                                 irc|irc-console|irc-virtual-terminal|console|virtual-terminal)
1316                                         sed $SED_I '/GLOBAL_COLOR_SCHEME=/d' $config_file
1317                                         ;;
1318                                 global)
1319                                         sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' -e '/IRC_COLOR_SCHEME=/d' \
1320                                         -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1321                                         ;;
1322                         esac
1323                 elif [[ $user_selection == $i ]];then
1324                         print_screen_output "Removing all color settings from config file now..."
1325                         sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/GLOBAL_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' \
1326                         -e '/IRC_COLOR_SCHEME=/d' -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1327                         set_color_scheme $DEFAULT_COLOR_SCHEME
1328                 elif [[ $user_selection == $(( $i+1 )) ]];then
1329                         print_lines_basic "0" "" "Ok, continuing $SCRIPT_NAME unchanged. You can set the colors anytime by starting with: -c 95 to 99"
1330                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
1331                                 set_color_scheme $CONSOLE_COLOR_SCHEME
1332                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1333                                 set_color_scheme $VIRT_TERM_COLOR_SCHEME
1334                         else
1335                                 set_color_scheme $DEFAULT_COLOR_SCHEME
1336                         fi
1337                 elif [[ $user_selection == $(( $i+2 )) ]];then
1338                         set_color_scheme $DEFAULT_COLOR_SCHEME
1339                         print_screen_output "Ok, exiting $SCRIPT_NAME now. You can set the colors later."
1340                         exit 0
1341                 else
1342                         print_screen_output "Error - Invalid Selection. You entered this: $user_selection"
1343                         print_screen_output " "
1344                         select_default_color_scheme
1345                 fi
1346         else
1347                 print_screen_output "$LINE1"
1348                 print_lines_basic "0" "" "After finding the scheme number you like, simply run this again in a terminal to set the configuration data file for your irc client. You can set color schemes for the following: start inxi with -c plus:"
1349                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
1350                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
1351                 exit 0
1352         fi
1353
1354         eval $LOGFE
1355 }
1356
1357 ########################################################################
1358 #### UTILITY FUNCTIONS
1359 ########################################################################
1360
1361 #### -------------------------------------------------------------------
1362 #### error handler, debugger, script updater
1363 #### -------------------------------------------------------------------
1364
1365 # Error handling
1366 # args: $1 - error number; $2 - optional, extra information; $3 - optional extra info
1367 error_handler()
1368 {
1369         eval $LOGFS
1370         local error_message=''
1371
1372         # assemble the error message
1373         case $1 in
1374                 2)      error_message="large flood danger, debug buffer full!"
1375                         ;;
1376                 3)      error_message="unsupported color scheme number: $2"
1377                         ;;
1378                 4)      error_message="unsupported verbosity level: $2"
1379                         ;;
1380                 5)      error_message="dependency not met: $2 not found in path.\nFor distribution installation package names and missing apps information, run: $SCRIPT_NAME --recommends"
1381                         ;;
1382                 6)      error_message="/proc not found! Quitting..."
1383                         ;;
1384                 7)      error_message="One of the options you entered in your script parameters: $2\nis not supported.The option may require extra arguments to work.\nFor supported options (and their arguments), check the help menu: $SCRIPT_NAME -h"
1385                         ;;
1386                 8)      error_message="the self-updater failed, $DOWNLOADER exited with error: $2.\nYou probably need to be root.\nHint, to make for easy updates without being root, do: chown <user name> $SCRIPT_PATH/$SCRIPT_NAME"
1387                         ;;
1388                 9)      error_message="unsupported debugging level: $2"
1389                         ;;
1390                 10)
1391                         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/"
1392                         ;;
1393                 11)
1394                         error_message="unsupported testing option argument: -! $2"
1395                         ;;
1396                 12)
1397                         error_message="the git 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 https://github.com/smxi/inxi\nto verify the branch status."
1398                         ;;
1399                 13)
1400                         error_message="The -t option requires the following extra arguments (no spaces between letters/numbers):\nc m cm [required], for example: -t cm8 OR -t cm OR -t c9\n(numbers: 1-20, > 5 throttled to 5 in irc clients) You entered: $2"
1401                         ;;
1402                 14)
1403                         error_message="failed to write correctly downloaded $SCRIPT_NAME to location $SCRIPT_PATH.\nThis usually means you don't have permission to write to that location, maybe you need to be root?\nThe operation failed with error: $2"
1404                         ;;
1405                 15)
1406                         error_message="failed set execute permissions on $SCRIPT_NAME at location $SCRIPT_PATH.\nThis usually means you don't have permission to set permissions on files there, maybe you need to be root?\nThe operation failed with error: $2"
1407                         ;;
1408                 16)
1409                         error_message="$SCRIPT_NAME downloaded but the file data is corrupted. Purged data and using current version."
1410                         ;;
1411                 17)
1412                         error_message="All $SCRIPT_NAME self updater features have been disabled by the distribution\npackage maintainer. This includes the option you used: $2"
1413                         ;;
1414                 18)
1415                         error_message="The argument you provided for $2 does not have supported syntax.\nPlease use the following formatting:\n$3"
1416                         ;;
1417                 19)
1418                         error_message="The option $2 has been deprecated. Please use $3 instead.\nSee -h for instructions and syntax."
1419                         ;;
1420                 20)
1421                         error_message="The option you selected has been deprecated. $2\nSee the -h (help) menu for currently supported options."
1422                         ;;
1423                 21)
1424                         error_message="Width option requires an integer value of 80 or more.\nYou entered: $2"
1425                         ;;
1426                 *)      error_message="error unknown: $@"
1427                         set -- 99
1428                         ;;
1429         esac
1430         # then print it and exit
1431         print_screen_output "Error $1: $error_message"
1432         eval $LOGFE
1433         exit $1
1434 }
1435
1436 # prior to script up set, pack the data into an array
1437 # then we'll print it out later.
1438 # args: $1 - $@ debugging string text
1439 script_debugger()
1440 {
1441         eval $LOGFS
1442         if [[ $B_SCRIPT_UP == 'true' ]];then
1443                 # only return if debugger is off and no pre start up errors have occured
1444                 if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then
1445                         return 0
1446                 # print out the stored debugging information if errors occured
1447                 elif [[ $DEBUG_BUFFER_INDEX -gt 0 ]];then
1448                         for (( DEBUG_BUFFER_INDEX=0; DEBUG_BUFFER_INDEX < ${#A_DEBUG_BUFFER[@]}; DEBUG_BUFFER_INDEX++ ))
1449                         do
1450                                 print_screen_output "${A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]}"
1451                         done
1452                         DEBUG_BUFFER_INDEX=0
1453                 fi
1454                 # or print out normal debugger messages if debugger is on
1455                 if [[ $DEBUG -gt 0 ]];then
1456                         print_screen_output "$1"
1457                 fi
1458         else
1459                 if [[ $B_DEBUG_FLOOD == 'true' && $DEBUG_BUFFER_INDEX -gt 10 ]];then
1460                         error_handler 2
1461                 # this case stores the data for later printout, will print out only
1462                 # at B_SCRIPT_UP == 'true' if array index > 0
1463                 else
1464                         A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]="$1"
1465                         # increment count for next pre script up debugging error
1466                         (( DEBUG_BUFFER_INDEX++ ))
1467                 fi
1468         fi
1469         eval $LOGFE
1470 }
1471
1472 # NOTE: no logging available until get_parameters is run, since that's what sets logging
1473 # in order to trigger earlier logging manually set B_USE_LOGGING to true in top variables.
1474 # $1 alone: logs data; $2 with or without $3 logs func start/end.
1475 # $1 type (fs/fe/cat/raw) or logged data; [$2 is $FUNCNAME; [$3 - function args]]
1476 log_function_data()
1477 {
1478         if [ "$B_USE_LOGGING" == 'true' ];then
1479                 local logged_data='' spacer='   ' line='----------------------------------------'
1480                 case $1 in
1481                         fs)
1482                                 logged_data="Function: $2 - Primary: Start"
1483                                 if [ -n "$3" ];then
1484                                         logged_data="$logged_data\n${spacer}Args: $3"
1485                                 fi
1486                                 spacer=''
1487                                 ;;
1488                         fe)
1489                                 logged_data="Function: $2 - Primary: End"
1490                                 spacer=''
1491                                 ;;
1492                         cat)
1493                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1494                                         for cat_file in $2
1495                                         do
1496                                                 logged_data="$logged_data\n$line\nFull file data: cat $cat_file\n\n$( cat $cat_file )\n$line\n"
1497                                         done
1498                                         spacer=''
1499                                 fi
1500                                 ;;
1501                         raw)
1502                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1503                                         logged_data="\n$line\nRaw system data:\n\n$2\n$line\n"
1504                                         spacer=''
1505                                 fi
1506                                 ;;
1507                         *)
1508                                 logged_data="$1"
1509                                 ;;
1510                 esac
1511                 # Create any required line breaks and strip out escape color code, either ansi (case 1)or irc (case 2).
1512                 # This pattern doesn't work for irc colors, if we need that someone can figure it out
1513                 if [[ -n $logged_data ]];then
1514                         if [[ $B_LOG_COLORS != 'true' ]];then
1515                                 echo -e "${spacer}$logged_data" | sed $SED_RX 's/\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m//g' >> $LOG_FILE
1516                         else
1517                                 echo -e "${spacer}$logged_data" >> $LOG_FILE
1518                         fi
1519                 fi
1520         fi
1521 }
1522
1523 # called in the initial -@ 10 script args setting so we can get logging as soon as possible
1524 # will have max 3 files, inxi.log, inxi.1.log, inxi.2.log
1525 create_rotate_logfiles()
1526 {
1527         if [[ ! -d $SCRIPT_DATA_DIR ]];then
1528                 mkdir $SCRIPT_DATA_DIR
1529         fi
1530         # do the rotation if logfile exists
1531         if [[ -f $LOG_FILE ]];then
1532                 # copy if present second to third
1533                 if [[ -f $LOG_FILE_1 ]];then
1534                         mv -f $LOG_FILE_1 $LOG_FILE_2
1535                 fi
1536                 # then copy initial to second
1537                 mv -f $LOG_FILE $LOG_FILE_1
1538         fi
1539         # now create the logfile
1540         touch $LOG_FILE
1541         # and echo the start data
1542         echo "=========================================================" >> $LOG_FILE
1543         echo "START $SCRIPT_NAME LOGGING:"                               >> $LOG_FILE
1544         echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )"              >> $LOG_FILE
1545         echo "=========================================================" >> $LOG_FILE
1546 }
1547
1548 # args: $1 - download url, not including file name; $2 - string to print out
1549 # $3 - update type option
1550 # note that $1 must end in / to properly construct the url path
1551 script_self_updater()
1552 {
1553         eval $LOGFS
1554         local downloader_error=0 file_contents='' downloader_man_error=0 
1555         local man_file_path="$MAN_FILE_LOCATION/inxi.1.gz"
1556         
1557         if [[ $B_IRC == 'true' ]];then
1558                 print_screen_output "Sorry, you can't run the $SCRIPT_NAME self updater option (-$3) in an IRC client."
1559                 exit 1
1560         fi
1561
1562         print_screen_output "Starting $SCRIPT_NAME self updater."
1563         print_screen_output "Currently running $SCRIPT_NAME version number: $SCRIPT_VERSION_NUMBER"
1564         print_screen_output "Current version patch number: $SCRIPT_PATCH_NUMBER"
1565         print_screen_output "Updating $SCRIPT_NAME in $SCRIPT_PATH using $2 as download source..."
1566         case $DOWNLOADER in
1567                 curl)
1568                         file_contents="$( curl -s $1$SCRIPT_NAME )" || downloader_error=$?
1569                         ;;
1570                 fetch)
1571                         file_contents="$( fetch -q -o - $1$SCRIPT_NAME )" || downloader_error=$?
1572                         ;;
1573                 ftp)
1574                         file_contents="$( ftp -o - $1$SCRIPT_NAME 2>/dev/null )" || downloader_error=$?
1575                         ;;
1576                 wget)
1577                         file_contents="$( wget -q -O - $1$SCRIPT_NAME )" || downloader_error=$?
1578                         ;;
1579                 no-downloader)
1580                         downloader_error=1
1581                         ;;
1582         esac
1583
1584         # then do the actual download
1585         if [[  $downloader_error -eq 0 ]];then
1586                 # make sure the whole file got downloaded and is in the variable
1587                 if [[ -n $( grep '###\*\*EOF\*\*###' <<< "$file_contents" ) ]];then
1588                         echo "$file_contents" > $SCRIPT_PATH/$SCRIPT_NAME || error_handler 14 "$?"
1589                         chmod +x $SCRIPT_PATH/$SCRIPT_NAME || error_handler 15 "$?"
1590                         SCRIPT_VERSION_NUMBER=$( parse_version_data 'main' )
1591                         SCRIPT_PATCH_NUMBER=$( parse_version_data 'patch' )
1592                         print_screen_output "Successfully updated to $2 version: $SCRIPT_VERSION_NUMBER"
1593                         print_screen_output "New $2 version patch number: $SCRIPT_PATCH_NUMBER"
1594                         print_screen_output "To run the new version, just start $SCRIPT_NAME again."
1595                         print_screen_output "----------------------------------------"
1596                         print_screen_output "Starting download of man page file now."
1597                         if [[ ! -d $MAN_FILE_LOCATION ]];then
1598                                 print_screen_output "The required man directory was not detected on your system, unable to continue: $MAN_FILE_LOCATION"
1599                         else
1600                                 if [[ $B_ROOT == 'true' ]];then
1601                                         print_screen_output "Checking Man page download URL..."
1602                                         if [[ -f /usr/share/man/man8/inxi.8.gz ]];then
1603                                                 print_screen_output "Updating man page location to man1."
1604                                                 mv -f /usr/share/man/man8/inxi.8.gz /usr/share/man/man1/inxi.1.gz 
1605                                                 if type -p mandb &>/dev/null;then
1606                                                         exec $( type -p mandb ) -q 
1607                                                 fi
1608                                         fi
1609                                         if [[ $DOWNLOADER == 'wget' ]];then
1610                                                 wget -q --spider $MAN_FILE_DOWNLOAD || downloader_man_error=$?
1611                                         fi
1612                                         if [[ $downloader_man_error -eq 0 ]];then
1613                                                 if [[ $DOWNLOADER == 'wget' ]];then
1614                                                         print_screen_output "Man file download URL verified: $MAN_FILE_DOWNLOAD"
1615                                                 fi
1616                                                 print_screen_output "Downloading Man page file now."
1617                                                 case $DOWNLOADER in
1618                                                         curl)
1619                                                                 curl -s -o $man_file_path $MAN_FILE_DOWNLOAD || downloader_man_error=$?
1620                                                                 ;;
1621                                                         fetch)
1622                                                                 fetch -q -o $man_file_path $MAN_FILE_DOWNLOAD || downloader_man_error=$?
1623                                                                 ;;
1624                                                         ftp)
1625                                                                 ftp -o $man_file_path $MAN_FILE_DOWNLOAD 2>/dev/null || downloader_man_error=$?
1626                                                                 ;;
1627                                                         wget)
1628                                                                 wget -q -O $man_file_path $MAN_FILE_DOWNLOAD || downloader_man_error=$?
1629                                                                 ;;
1630                                                         no-downloader)
1631                                                                 downloader_man_error=1
1632                                                                 ;;
1633                                                 esac
1634                                                 if [[ $downloader_man_error -gt 0 ]];then
1635                                                         print_screen_output "Oh no! Something went wrong downloading the Man gz file at: $MAN_FILE_DOWNLOAD"
1636                                                         print_screen_output "Check the error messages for what happened. Error: $downloader_man_error"
1637                                                 else
1638                                                         print_screen_output "Download/install of man page successful. Check to make sure it works: man inxi"
1639                                                 fi
1640                                         else
1641                                                 print_screen_output "Man file download URL failed, unable to continue: $MAN_FILE_DOWNLOAD"
1642                                         fi
1643                                 else
1644                                         print_screen_output "Updating / Installing the Man page requires root user, writing to: $MAN_FILE_LOCATION"
1645                                         print_screen_output "If you want the man page, you'll have to run $SCRIPT_NAME -$3 as root."
1646                                 fi
1647                         fi
1648                         exit 0
1649                 else
1650                         error_handler 16
1651                 fi
1652         # now run the error handlers on any wget failure
1653         else
1654                 if [[ $2 == 'svn server' ]];then
1655                         error_handler 8 "$downloader_error"
1656                 elif [[ $2 == 'alt server' ]];then
1657                         error_handler 10 "$1"
1658                 else
1659                         error_handler 12 "$1"
1660                 fi
1661         fi
1662         eval $LOGFS
1663 }
1664
1665 # args: $1 - debug data type: sys|xorg|disk
1666 debug_data_collector()
1667 {
1668         local xiin_app='' xiin_data_file='' xiin_download='' error='' b_run_xiin='false'
1669         local debug_data_dir='' bsd_string='' xorg_d_files='' xorg_file='' a_distro_ids=''
1670         local completed_gz_file='' xiin_file='xiin.py' ftp_upload='ftp.techpatterns.com/incoming'
1671         local xiin_url="https://github.com/smxi/inxi/raw/xiin/$xiin_file"
1672         local Line='-------------------------' root_string=''
1673         local start_directory=$( pwd )
1674         local host=$( tr '[A-Z]' '[a-z]' <<< "$HOSTNAME" )
1675         local downloader_error=0 debug_i=''
1676         
1677         if [[ $B_DEBUG_I == 'true' ]];then
1678                 debug_i='i'
1679         fi
1680         
1681         if [[ -n $host ]];then
1682                 host=${host// /-}
1683         else
1684                 host="-no-host"
1685         fi
1686         if [[ -n $BSD_TYPE ]];then
1687                 bsd_string="-$BSD_TYPE-$BSD_VERSION"
1688         fi
1689         if [[ $( whoami ) == 'root' ]];then
1690                 root_string='-root'
1691         fi
1692         
1693         debug_data_dir="inxi$bsd_string-$host-$(date +%Y%m%d-%H%M%S)-$1$root_string" 
1694         
1695         if [[ $B_IRC == 'false' ]];then
1696                 if [[ -n $ALTERNATE_FTP ]];then
1697                         ftp_upload=$ALTERNATE_FTP
1698                 fi
1699                 echo "Starting debugging data collection type: $1"
1700                 echo -n "Checking/creating required directories... "
1701                 if [[ ! -d $SCRIPT_DATA_DIR ]];then
1702                         mkdir $SCRIPT_DATA_DIR
1703                 fi
1704                 echo 'completed'
1705                 cd $SCRIPT_DATA_DIR
1706                 if [[ -d $SCRIPT_DATA_DIR/$debug_data_dir ]];then
1707                         echo 'Deleting previous xiin data directory...'
1708                         rm -rf $SCRIPT_DATA_DIR/$debug_data_dir
1709                 fi
1710                 mkdir $SCRIPT_DATA_DIR/$debug_data_dir
1711                 if [[ -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz ]];then
1712                         echo 'Deleting previous tar.gz file...'
1713                         rm -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1714                 fi
1715                 
1716                 echo 'Collecting system info: sensors, lsusb, lspci, lspci -v data, plus /proc data'
1717                 echo 'also checking for dmidecode data: note, you must be root to have dmidecode work.'
1718                 echo "Data going into: $SCRIPT_DATA_DIR/$debug_data_dir"
1719                 # bsd tools http://cb.vu/unixtoolbox.xhtml
1720                 # freebsd
1721                 if type -p pciconf &>/dev/null;then
1722                         pciconf -l -cv &> $debug_data_dir/bsd-pciconf-cvl.txt
1723                         pciconf -vl &> $debug_data_dir/bsd-pciconf-vl.txt
1724                         pciconf -l &> $debug_data_dir/bsd-pciconf-l.txt
1725                 else
1726                         touch $debug_data_dir/bsd-pciconf-absent
1727                 fi
1728                 # openbsd
1729                 if type -p pcidump &>/dev/null;then
1730                         pcidump &> $debug_data_dir/bsd-pcidump-openbsd.txt
1731                         pcidump -v &> $debug_data_dir/bsd-pcidump-v-openbsd.txt
1732                 else
1733                         touch $debug_data_dir/bsd-pcidump-openbsd-absent
1734                 fi
1735                 # netbsd
1736                 if type -p pcictl &>/dev/null;then
1737                         pcictl list &> $debug_data_dir/bsd-pcictl-list-netbsd.txt
1738                         pcictl list -n &> $debug_data_dir/bsd-pcictl-list-n-netbsd.txt
1739                 else
1740                         touch $debug_data_dir/bsd-pcictl-netbsd-absent
1741                 fi
1742                 if type -p sysctl &>/dev/null;then
1743                         sysctl -a &> $debug_data_dir/bsd-sysctl-a.txt
1744                 else
1745                         touch $debug_data_dir/bsd-sysctl-absent
1746                 fi
1747                 if type -p usbdevs &>/dev/null;then
1748                         usbdevs -v  &> $debug_data_dir/bsd-usbdevs-v.txt
1749                 else
1750                         touch $debug_data_dir/bsd-usbdevs-absent
1751                 fi
1752                 if type -p kldstat &>/dev/null;then
1753                         kldstat  &> $debug_data_dir/bsd-kldstat.txt
1754                 else
1755                         touch $debug_data_dir/bsd-kldstat-absent
1756                 fi
1757                 # diskinfo -v <disk>
1758                 # fdisk <disk>
1759                 dmidecode &> $debug_data_dir/dmidecode.txt
1760                 
1761                 get_repo_data "$SCRIPT_DATA_DIR/$debug_data_dir"
1762                 
1763                 if type -p shopt &>/dev/null;then
1764                         shopt -s nullglob
1765                         a_distro_ids=(/etc/*[-_]{release,version})
1766                         shopt -u nullglob
1767                         echo ${a_distro_ids[@]} &> $debug_data_dir/etc-distro-files.txt
1768                         for distro_file in ${a_distro_ids[@]} /etc/issue
1769                         do
1770                                 if [[ -f $distro_file ]];then
1771                                         cat $distro_file &> $debug_data_dir/distro-file${distro_file//\//-}
1772                                 fi
1773                         done
1774                 fi
1775                 dmesg &> $debug_data_dir/dmesg.txt
1776                 lscpu &> $debug_data_dir/lscpu.txt
1777                 lspci &> $debug_data_dir/lspci.txt
1778                 lspci -k &> $debug_data_dir/lspci-k.txt
1779                 lspci -knn &> $debug_data_dir/lspci-knn.txt
1780                 lspci -n &> $debug_data_dir/lspci-n.txt
1781                 lspci -nn &> $debug_data_dir/lspci-nn.txt
1782                 lspci -mm &> $debug_data_dir/lspci-mm.txt
1783                 lspci -mmnn &> $debug_data_dir/lspci-mmnn.txt
1784                 lspci -mmnnv &> $debug_data_dir/lspci-mmnnv.txt
1785                 lspci -v &> $debug_data_dir/lspci-v.txt
1786                 lsusb &> $debug_data_dir/lsusb.txt
1787                 if type -p hciconfig &>/dev/null;then
1788                         hciconfig -a &> $debug_data_dir/hciconfig-a.txt
1789                 else
1790                         touch $debug_data_dir/hciconfig-absent
1791                 fi
1792                 ls /sys &> $debug_data_dir/ls-sys.txt
1793                 ps aux &> $debug_data_dir/ps-aux.txt
1794                 ps -e &> $debug_data_dir/ps-e.txt
1795                 ps -p 1 &> $debug_data_dir/ps-p-1.txt
1796                 cat /proc/1/comm &> $debug_data_dir/proc-1-comm.txt
1797                 runlevel &> $debug_data_dir/runlevel.txt
1798                 if type -p rc-status &>/dev/null;then
1799                         rc-status -a &> $debug_data_dir/rc-status-a.txt
1800                         rc-status -l &> $debug_data_dir/rc-status-l.txt
1801                         rc-status -r &> $debug_data_dir/rc-status-r.txt
1802                 else
1803                         touch $debug_data_dir/rc-status-absent
1804                 fi
1805                 if type -p systemctl &>/dev/null;then
1806                         systemctl list-units &> $debug_data_dir/systemctl-list-units.txt
1807                         systemctl list-units --type=target &> $debug_data_dir/systemctl-list-units-target.txt
1808                 else
1809                         touch $debug_data_dir/systemctl-absent
1810                 fi
1811                 if type -p initctl &>/dev/null;then
1812                         initctl list &> $debug_data_dir/initctl-list.txt
1813                 else
1814                         touch $debug_data_dir/initctl-absent
1815                 fi
1816                 sensors &> $debug_data_dir/sensors.txt
1817                 if type -p strings &>/dev/null;then
1818                         touch $debug_data_dir/strings-present
1819                 else
1820                         touch $debug_data_dir/strings-absent
1821                 fi
1822                 local id_dir='/sys/class/power_supply/' 
1823                 local ids=$( ls $id_dir 2>/dev/null )
1824                 if [[ -n $ids ]];then
1825                         for batid in $ids 
1826                         do
1827                                 cat $id_dir$batid'/uevent' &> $debug_data_dir/sys-power-supply-$batid.txt
1828                         done
1829                 else
1830                         touch $debug_data_dir/sys-power-supply-none
1831                 fi
1832                 
1833                 # leaving this commented out to remind that some systems do not
1834                 # support strings --version, but will just simply hang at that command
1835                 # which you can duplicate by simply typing: strings then hitting enter, you will get hang.
1836                 # strings --version  &> $debug_data_dir/strings.txt
1837                 if type -p nvidia-smi &>/dev/null;then
1838                         nvidia-smi -q &> $debug_data_dir/nvidia-smi-q.txt
1839                         nvidia-smi -q -x &> $debug_data_dir/nvidia-smi-xq.txt
1840                 else
1841                         touch $debug_data_dir/nvidia-smi-absent
1842                 fi
1843                 head -n 1 /proc/asound/card*/codec* &> $debug_data_dir/proc-asound-card-codec.txt
1844                 if [[ -f /proc/version ]];then
1845                         cat /proc/version &> $debug_data_dir/proc-version.txt
1846                 else
1847                         touch $debug_data_dir/proc-version-absent
1848                 fi
1849                 echo $CC &> $debug_data_dir/cc-content.txt
1850                 ls /usr/bin/gcc* &> $debug_data_dir/gcc-sys-versions.txt
1851                 if type -p gcc &>/dev/null;then
1852                         gcc --version &> $debug_data_dir/gcc-version.txt
1853                 else
1854                         touch $debug_data_dir/gcc-absent
1855                 fi
1856                 if type -p clang &>/dev/null;then
1857                         clang --version &> $debug_data_dir/clang-version.txt
1858                 else
1859                         touch $debug_data_dir/clang-absent
1860                 fi
1861                 cat /etc/src.conf &> $debug_data_dir/bsd-etc-src-conf.txt
1862                 cat /etc/make.conf &> $debug_data_dir/bsd-etc-make-conf.txt
1863                 cat /etc/issue &> $debug_data_dir/etc-issue.txt
1864                 cat $FILE_LSB_RELEASE &> $debug_data_dir/lsb-release.txt
1865                 cat $FILE_OS_RELEASE &> $debug_data_dir/os-release.txt
1866                 cat $FILE_ASOUND_DEVICE &> $debug_data_dir/proc-asound-device.txt
1867                 cat $FILE_ASOUND_VERSION &> $debug_data_dir/proc-asound-version.txt
1868                 cat $FILE_CPUINFO &> $debug_data_dir/proc-cpu-info.txt
1869                 cat $FILE_MEMINFO &> $debug_data_dir/proc-meminfo.txt
1870                 cat $FILE_MODULES &> $debug_data_dir/proc-modules.txt
1871                 cat /proc/net/arp &> $debug_data_dir/proc-net-arp.txt 
1872                 # bsd data
1873                 cat /var/run/dmesg.boot &> $debug_data_dir/bsd-var-run-dmesg.boot.txt 
1874                 echo $COLS_INNER &> $debug_data_dir/cols-inner.txt
1875                 
1876                 check_recommends_user_output &> $debug_data_dir/check-recommends-user-output.txt
1877                 # first download and verify xiin
1878                 if [[ $B_UPLOAD_DEBUG_DATA == 'true' || $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1879                         touch $SCRIPT_DATA_DIR/$debug_data_dir/xiin-error.txt
1880                         echo "Downloading required tree traverse tool $xiin_file..."
1881                         if [[ -f xiin && ! -f $xiin_file ]];then
1882                                 mv -f xiin $xiin_file
1883                         fi
1884                         # -Nc is creating really weird download anomolies, so using -O instead
1885                         case $DOWNLOADER in
1886                                 curl)
1887                                         xiin_download="$( curl -s $xiin_url )" || downloader_error=$?
1888                                         ;;
1889                                 fetch)
1890                                         xiin_download="$( fetch -q -o - $xiin_url )" || downloader_error=$?
1891                                         ;;
1892                                 ftp)
1893                                         xiin_download="$( ftp -o - $xiin_url 2>/dev/null )" || downloader_error=$?
1894                                         ;;
1895                                 wget)
1896                                         xiin_download="$( wget -q -O - $xiin_url )" || downloader_error=$?
1897                                         ;;
1898                                 no-downloader)
1899                                         downloader_error=1
1900                                         ;;
1901                         esac
1902                         # if nothing got downloaded kick out error, otherwise we'll use an older version
1903                         if [[ $downloader_error -gt 0 && ! -f $xiin_file ]];then
1904                                 echo -e "ERROR: Failed to download required file: $xiin_file\nMaybe the remote site is down or your networking is broken?"
1905                                 echo "Continuing with incomplete data collection."
1906                                 echo "$xiin_file download failed and no existing $xiin_file" >> $debug_data_dir/xiin-error.txt
1907                         elif [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) || -f $xiin_file ]];then
1908                                 if [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) ]];then
1909                                         echo "Updating $xiin_file from remote location"
1910                                         echo "$xiin_download" > $xiin_file
1911                                 else
1912                                         echo "Using local $xiin_file due to download failure"
1913                                 fi
1914                                 b_run_xiin='true'
1915                         else
1916                                 echo -e "ERROR: $xiin_file downloaded but the program file data is corrupted.\nContinuing with incomplete data collection."
1917                                 echo "$xiin_file downloaded but the program file data is corrupted." >> $debug_data_dir/xiin-error.txt
1918                         fi
1919                 fi
1920                 # note, only bash 4> supports ;;& for case, so using if/then here
1921                 if [[ $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1922                         xiin_data_file=$SCRIPT_DATA_DIR/$debug_data_dir/xiin-sys.txt
1923                         echo 'Collecting networking data...'
1924                         ifconfig &> $debug_data_dir/ifconfig.txt
1925                         ip addr &> $debug_data_dir/ip-addr.txt
1926                         if [[ $b_run_xiin == 'true' && -z $BSD_TYPE ]];then
1927                                 echo $Line
1928                                 echo "Running $xiin_file tool now on /sys..."
1929                                 echo "Using Python version:" && python --version
1930                                 python --version &> $debug_data_dir/python-version.txt
1931                                 python ./$xiin_file -d /sys -f $xiin_data_file
1932                                 if [[ $? -ne 0 ]];then
1933                                         error=$?
1934                                         echo -e "ERROR: $xiin_file exited with error $error - removing data file.\nContinuing with incomplete data collection."
1935                                         echo "Continuing with incomplete data collection."
1936                                         rm -f $xiin_data_file
1937                                         echo "$xiin_file data generation failed with python error $error" >> $debug_data_dir/xiin-error.txt
1938                                 fi
1939                                 echo $Line
1940                         fi
1941                 fi
1942                 if [[ $1 == 'xorg' || $1 == 'all' ]];then
1943                         if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
1944                                 echo 'Warning: only some of the data collection can occur if you are not in X'
1945                                 touch $debug_data_dir/warning-user-not-in-x
1946                         fi
1947                         if [[ $B_ROOT == 'true' ]];then
1948                                 echo 'Warning: only some of the data collection can occur if you are running as Root user'
1949                                 touch $debug_data_dir/warning-root-user
1950                         fi
1951                         echo 'Collecting Xorg log and xorg.conf files'
1952                         if [[ -e $FILE_XORG_LOG ]];then
1953                                 cat $FILE_XORG_LOG &> $debug_data_dir/xorg-log-file.txt
1954                         else
1955                                 touch $debug_data_dir/xorg-log-file-absent
1956                         fi
1957                         if [[ -e /etc/X11/xorg.conf ]];then
1958                                 cat /etc/X11/xorg.conf &> $debug_data_dir/xorg-conf.txt
1959                         else
1960                                 touch $debug_data_dir/xorg-conf-file-absent
1961                         fi
1962                         if [[ -n $( ls /etc/X11/xorg.conf.d/ 2>/dev/null ) ]];then
1963                                 ls /etc/X11/xorg.conf.d &> $debug_data_dir/ls-etc-x11-xorg-conf-d.txt
1964                                 xorg_d_files=$(ls /etc/X11/xorg.conf.d)
1965                                 for xorg_file in $xorg_d_files
1966                                 do
1967                                         cat /etc/X11/xorg.conf.d/$xorg_file &> $debug_data_dir/xorg-conf-d-$xorg_file.txt
1968                                 done
1969                         else
1970                                 touch $debug_data_dir/xorg-conf-d-files-absent
1971                         fi
1972                         echo 'Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, wayland, weston...'
1973                         if type -p weston-info &>/dev/null; then
1974                                 weston-info &> $debug_data_dir/weston-info.txt
1975                         else
1976                                 touch $debug_data_dir/weston-info-absent
1977                         fi
1978                         if type -p weston &>/dev/null; then
1979                                 weston --version &> $debug_data_dir/weston-version.txt
1980                         else
1981                                 touch $debug_data_dir/weston-absent
1982                         fi
1983                         if type -p xprop &>/dev/null; then
1984                                 xprop -root &> $debug_data_dir/xprop_root.txt
1985                         else
1986                                 touch $debug_data_dir/xprop-absent
1987                         fi
1988                         if type -p xprop &>/dev/null; then
1989                                 glxinfo &> $debug_data_dir/glxinfo.txt
1990                         else
1991                                 touch $debug_data_dir/glxinfo-absent
1992                         fi
1993                         if type -p xdpyinfo &>/dev/null; then
1994                                 xdpyinfo &> $debug_data_dir/xdpyinfo.txt
1995                         else
1996                                 touch $debug_data_dir/xdpyinfo-absent
1997                         fi
1998                         if type -p xrandr &>/dev/null; then
1999                                 xrandr &> $debug_data_dir/xrandr.txt
2000                         else
2001                                 touch $debug_data_dir/xrandr-absent
2002                         fi
2003                         if type -p X &>/dev/null; then
2004                                 X -version &> $debug_data_dir/x-version.txt
2005                         else
2006                                 touch $debug_data_dir/x-absent
2007                         fi
2008                         if type -p Xorg &>/dev/null; then
2009                                 Xorg -version &> $debug_data_dir/xorg-version.txt
2010                         else
2011                                 touch $debug_data_dir/xorg-absent
2012                         fi
2013                         
2014                         echo $GNOME_DESKTOP_SESSION_ID &> $debug_data_dir/gnome-desktop-session-id.txt
2015                         # kde 3 id
2016                         echo $KDE_FULL_SESSION &> $debug_data_dir/kde3-full-session.txt
2017                         echo $KDE_SESSION_VERSION &> $debug_data_dir/kde-gte-4-session-version.txt
2018                         if type -p kf5-config &>/dev/null; then
2019                                 kf5-config --version &> $debug_data_dir/kde-kf5-config-version-data.txt
2020                         elif type -p kf6-config &>/dev/null; then
2021                                 kf6-config --version &> $debug_data_dir/kde-kf6-config-version-data.txt
2022                         elif type -p kf$KDE_SESSION_VERSION-config &>/dev/null; then
2023                                 kf$KDE_SESSION_VERSION-config --version &> $debug_data_dir/kde-kf$KDE_SESSION_VERSION-KSV-config-version-data.txt
2024                         else
2025                                 touch $debug_data_dir/kde-kf-config-absent
2026                         fi
2027                         if type -p plasmashell &>/dev/null; then
2028                                 plasmashell --version &> $debug_data_dir/kde-plasmashell-version-data.txt
2029                         else
2030                                 touch $debug_data_dir/kde-plasmashell-absent
2031                         fi
2032                         if type -p kwin_x11 &>/dev/null; then
2033                                 kwin_x11 --version &> $debug_data_dir/kde-kwin_x11-version-data.txt
2034                         else
2035                                 touch $debug_data_dir/kde-kwin_x11-absent
2036                         fi
2037                         if type -p kded4 &>/dev/null; then
2038                                 kded4 --version &> $debug_data_dir/kded4-version-data.txt
2039                         elif type -p kded5 &>/dev/null; then
2040                                 kded5 --version &> $debug_data_dir/kded5-version-data.txt
2041                         elif type -p kded &>/dev/null; then
2042                                 kded --version &> $debug_data_dir/kded-version-data.txt
2043                         else
2044                                 touch $debug_data_dir/kded-$KDE_SESSION_VERSION-absent
2045                         fi
2046                         # kde 5/plasma desktop 5, this is maybe an extra package and won't be used
2047                         if type -p about-distro &>/dev/null; then
2048                                 about-distro &> $debug_data_dir/kde-about-distro.txt
2049                         else
2050                                 touch $debug_data_dir/kde-about-distro-absent
2051                         fi
2052                         echo $XDG_CURRENT_DESKTOP &> $debug_data_dir/xdg-current-desktop.txt
2053                 fi
2054                 if [[ $1 == 'disk' || $1 == 'all' ]];then
2055                         echo 'Collecting dev, label, disk, uuid data, df...'
2056                         ls -l /dev &> $debug_data_dir/dev-data.txt
2057                         ls -l /dev/disk &> $debug_data_dir/dev-disk-data.txt
2058                         ls -l /dev/disk/by-id &> $debug_data_dir/dev-disk-id-data.txt
2059                         ls -l /dev/disk/by-label &> $debug_data_dir/dev-disk-label-data.txt
2060                         ls -l /dev/disk/by-uuid &> $debug_data_dir/dev-disk-uuid-data.txt
2061                         # http://comments.gmane.org/gmane.linux.file-systems.zfs.user/2032
2062                         ls -l /dev/disk/by-wwn &> $debug_data_dir/dev-disk-wwn-data.txt
2063                         ls -l /dev/disk/by-path &> $debug_data_dir/dev-disk-path-data.txt
2064                         ls -l /dev/mapper &> $debug_data_dir/dev-disk-mapper-data.txt
2065                         readlink /dev/root &> $debug_data_dir/dev-root.txt
2066                         df -h -T -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 --exclude-type=devfs --exclude-type=linprocfs --exclude-type=sysfs --exclude-type=fdescfs &> $debug_data_dir/df-h-T-P-excludes.txt
2067                         df -T -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 --exclude-type=devfs --exclude-type=linprocfs --exclude-type=sysfs --exclude-type=fdescfs &> $debug_data_dir/df-T-P-excludes.txt
2068                         df -T -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 --exclude-type=devfs --exclude-type=linprocfs --exclude-type=sysfs --exclude-type=fdescfs --total &> $debug_data_dir/df-T-P-excludes-total.txt
2069                         df -h -T &> $debug_data_dir/bsd-df-h-T-no-excludes.txt
2070                         df -h &> $debug_data_dir/bsd-df-h-no-excludes.txt
2071                         df -k -T &> $debug_data_dir/bsd-df-k-T-no-excludes.txt
2072                         df -k &> $debug_data_dir/bsd-df-k-no-excludes.txt
2073                         atacontrol list &> $debug_data_dir/bsd-atacontrol-list.txt
2074                         camcontrol devlist &> $debug_data_dir/bsd-camcontrol-devlist.txt
2075                         # bsd tool
2076                         mount &> $debug_data_dir/mount.txt
2077                         btrfs filesystem show  &> $debug_data_dir/btrfs-filesystem-show.txt
2078                         btrfs filesystem show --mounted  &> $debug_data_dir/btrfs-filesystem-show-mounted.txt
2079                         # btrfs filesystem show --all-devices  &> $debug_data_dir/btrfs-filesystem-show-all-devices.txt
2080                         gpart list &> $debug_data_dir/bsd-gpart-list.txt
2081                         gpart show &> $debug_data_dir/bsd-gpart-show.txt
2082                         gpart status &> $debug_data_dir/bsd-gpart-status.txt
2083                         swapctl -l -k &> $debug_data_dir/bsd-swapctl-l-k.txt
2084                         swapon -s &> $debug_data_dir/swapon-s.txt
2085                         sysctl -b kern.geom.conftxt &> $debug_data_dir/bsd-sysctl-b-kern.geom.conftxt.txt
2086                         sysctl -b kern.geom.confxml &> $debug_data_dir/bsd-sysctl-b-kern.geom.confxml.txt
2087                         zfs list &> $debug_data_dir/bsd-zfs-list.txt
2088                         zpool list &> $debug_data_dir/bsd-zpool-list.txt
2089                         zpool list -v &> $debug_data_dir/bsd-zpool-list-v.txt
2090                         df -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 &> $debug_data_dir/df-P-excludes.txt
2091                         df -P &> $debug_data_dir/bsd-df-P-no-excludes.txt
2092                         cat /proc/mdstat &> $debug_data_dir/proc-mdstat.txt
2093                         cat $FILE_PARTITIONS &> $debug_data_dir/proc-partitions.txt
2094                         cat $FILE_SCSI &> $debug_data_dir/proc-scsi.txt
2095                         cat $FILE_MOUNTS &> $debug_data_dir/proc-mounts.txt
2096                         cat /proc/sys/dev/cdrom/info &> $debug_data_dir/proc-cdrom-info.txt
2097                         ls /proc/ide/ &> $debug_data_dir/proc-ide.txt
2098                         cat /proc/ide/*/* &> $debug_data_dir/proc-ide-hdx-cat.txt
2099                         cat /etc/fstab &> $debug_data_dir/etc-fstab.txt
2100                         cat /etc/mtab &> $debug_data_dir/etc-mtab.txt
2101                 fi
2102                 echo 'Creating inxi output file now. This can take a few seconds...'
2103                 echo "Starting $SCRIPT_NAME from: $start_directory"
2104                 cd $start_directory
2105                 $SCRIPT_PATH/$SCRIPT_NAME -F${debug_i}Rfrploudmxxx -c 0 -@ 8 -y 120 > $SCRIPT_DATA_DIR/$debug_data_dir/inxi-F${debug_i}Rfrploudmxxxy120.txt
2106                 cp $LOG_FILE $SCRIPT_DATA_DIR/$debug_data_dir
2107                 if [[ -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz ]];then
2108                         echo "Found and removing previous tar.gz data file: $debug_data_dir.tar.gz"
2109                         rm -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
2110                 fi
2111                 cd $SCRIPT_DATA_DIR
2112                 echo 'Creating tar.gz compressed file of this material now. Contents:'
2113                 echo $Line
2114                 tar -cvzf $debug_data_dir.tar.gz $debug_data_dir
2115                 echo $Line
2116                 echo 'Cleaning up leftovers...'
2117                 rm -rf $debug_data_dir
2118                 echo 'Testing gzip file integrity...'
2119                 gzip -t $debug_data_dir.tar.gz
2120                 if [[ $? -gt 0 ]];then
2121                         echo 'Data in gz is corrupted, removing gzip file, try running data collector again.'
2122                         rm -f $debug_data_dir.tar.gz
2123                         echo "Data in gz is corrupted, removed gzip file" >> $debug_data_dir/gzip-error.txt
2124                 else
2125                         echo 'All done, you can find your data gzipped directory here:'
2126                         completed_gz_file=$SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
2127                         echo $completed_gz_file
2128                         if [[ $B_UPLOAD_DEBUG_DATA == 'true' ]];then
2129                                 echo $Line
2130                                 if [[ $b_run_xiin == 'true' ]];then
2131                                         echo "Running automatic upload of data to remote server $ftp_upload now..."
2132                                         python ./$xiin_file --version
2133                                         python ./$xiin_file -u $completed_gz_file $ftp_upload
2134                                         if [[ $? -gt 0 ]];then
2135                                                 echo $Line
2136                                                 echo "Error: looks like the ftp upload failed. Error number: $?"
2137                                                 echo "The ftp upload failed. Error number: $?" >> $debug_data_dir/xiin-error.txt
2138                                         fi
2139                                 else
2140                                         echo 'Unable to run the automoatic ftp upload because of an error with the xiin download.'
2141                                         echo "Unable to run the automoatic ftp upload because of an error with the xiin download" >> $debug_data_dir/xiin-error.txt
2142                                 fi
2143                         else
2144                                 echo 'You can upload this here using most file managers: ftp.techpatterns.com/incoming'
2145                                 echo 'then let a maintainer know it is uploaded.'
2146                         fi
2147                 fi
2148         else
2149                 echo 'This feature only available in console or shell client! Exiting now.'
2150         fi
2151         exit 0
2152 }
2153
2154 check_recommends_user_output()
2155 {
2156         local Line=$LINE1
2157         local gawk_version='N/A' sed_version='N/A' sudo_version='N/A' python_version='N/A'
2158         local downloaders_bsd=''
2159         
2160         if [[ $B_IRC == 'true' ]];then
2161                 print_screen_output "Sorry, you can't run this option in an IRC client."
2162                 exit 1
2163         fi
2164         if [[ -n $BSD_TYPE ]];then
2165                 downloaders_bsd='
2166                 fetch:BSD-only~BSD-only~BSD-only~:-i_wan_ip;-w/-W;-U/-!_[11-15]_(BSDs)
2167                 ftp:ftp-OpenBSD-only~ftp-OpenBSD-only~ftp-OpenBSD-only~:-i_wan_ip;-w/-W;-U/-!_[11-15]_(OpenBSD_only)'
2168         fi
2169         initialize_paths
2170         print_lines_basic "0" "" "$SCRIPT_NAME will now begin checking for the programs it needs to operate. First a check of the main languages and tools $SCRIPT_NAME uses. Python is only for debugging data collection."
2171         echo $Line
2172         echo "Bash version: $( bash --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU bash/ {print $4}' )"
2173         if type -p gawk &>/dev/null;then
2174                 gawk_version=$( gawk --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU Awk/ {print $3}' )
2175         fi
2176         if type -p sed &>/dev/null;then
2177                 sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU sed version/ {print $4}' )
2178                 if [[ -z $sed_version ]];then
2179                         # note: bsd sed shows error with --version flag
2180                         sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^sed: illegal option/ {print "BSD sed"}' )
2181                 fi
2182         fi
2183         if type -p sudo &>/dev/null;then
2184                 sudo_version=$( sudo -V 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Sudo version/ {print $3}' )
2185         fi
2186         if type -p python &>/dev/null;then
2187                 python_version=$( python --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Python/ {print $2}' )
2188         fi
2189         echo "Gawk version: $gawk_version"
2190         echo "Sed version: $sed_version"
2191         echo "Sudo version: $sudo_version"
2192         echo "Python version: $python_version"
2193         echo $Line
2194         
2195         echo "Test One: Required System Directories (Linux Only)."
2196         print_lines_basic "0" "" "If one of these system directories is missing, $SCRIPT_NAME cannot operate:"
2197         echo 
2198         check_recommends_items 'required-dirs'
2199         
2200         echo "Test Two: Required Core Applications."
2201         print_lines_basic "0" "" "If one of these applications is missing, $SCRIPT_NAME cannot operate:"
2202         echo 
2203         check_recommends_items 'required-apps'
2204         
2205         print_lines_basic "0" "" "Test Three: Script Recommends for Graphics Features."
2206         print_lines_basic "0" "" "NOTE: If you do not use X these do not matter (like a headless server). Otherwise, if one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
2207         echo 
2208         check_recommends_items 'recommended-x-apps'
2209         
2210         echo 'Test Four: Script Recommends for Remaining Features.' 
2211         print_lines_basic "0" "" "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
2212         echo 
2213         check_recommends_items 'recommended-apps'
2214         
2215         echo 'Test Five: Script Recommends for Remaining Features.' 
2216         print_lines_basic "0" "" "One of these downloaders needed for options -i/-w/-W (-U/-! [11-15], if supported):"
2217         echo 
2218         check_recommends_items 'downloaders'
2219         
2220         echo 'Test Six: System Directories for Various Information.'
2221         echo '(Unless otherwise noted, these are for GNU/Linux systems)' 
2222         print_lines_basic "0" "" "If one of these directories is missing, $SCRIPT_NAME may have incomplete output:"
2223         echo 
2224         check_recommends_items 'system-dirs'
2225         
2226         echo 'Test Seven: System Files for Various Information.'
2227         echo '(Unless otherwise noted, these are for GNU/Linux systems)' 
2228         print_lines_basic "0" "" "If one of these files is missing, $SCRIPT_NAME may have incomplete output:"
2229         echo 
2230         check_recommends_items 'system-files'
2231         
2232         echo 'All tests completed.' 
2233 }
2234 # args: $1 - check item
2235 check_recommends_items()
2236 {
2237         local item='' item_list='' item_string='' missing_items='' missing_string=''
2238         local package='' application='' feature='' type='' starter='' finisher=''
2239         local package_deb='' package_pacman='' package_rpm='' 
2240         local print_string='' separator='' width=56
2241         local required_dirs='/proc /sys'
2242         # package-owner: 1 - debian/ubuntu; 2 - arch; 3 - yum/rpm
2243         # pardus: pisi sf -q /usr/bin/package
2244         local required_apps='
2245         df:coreutils~coreutils~coreutils~:partition_data 
2246         gawk:gawk~gawk~gawk~:core_tool
2247         grep:grep~grep~grep~:string_search 
2248         lspci:pciutils~pciutils~pciutils~:hardware_data 
2249         ps:procps~procps~procps~:process_data 
2250         readlink:coreutils~coreutils~coreutils~: 
2251         sed:sed~sed~sed~:string_replace 
2252         tr:coreutils~coreutils~coreutils~:character_replace 
2253         uname:uname~coreutils~coreutils~:kernel_data 
2254         wc:coreutils~coreutils~coreutils~:word_character_count
2255         '
2256         local x_recommends='
2257         glxinfo:mesa-utils~mesa-demos~glx-utils_(openSUSE_12.3_and_later_Mesa-demo-x)~:-G_glx_info 
2258         xdpyinfo:X11-utils~xorg-xdpyinfo~xorg-x11-utils~:-G_multi_screen_resolution 
2259         xprop:X11-utils~xorg-xprop~x11-utils~:-S_desktop_data 
2260         xrandr:x11-xserver-utils~xrandr~x11-server-utils~:-G_single_screen_resolution
2261         '
2262         local recommended_apps='
2263         dig:dnsutils~dnsutils~bind-utils:-i_first_wlan_ip_default_test
2264         dmidecode:dmidecode~dmidecode~dmidecode~:-M_if_no_sys_machine_data;_-m_memory 
2265         file:file~file~file~:-o_unmounted_file_system
2266         hciconfig:bluez~bluez-utils~bluez-utils~:-n_-i_bluetooth_data
2267         hddtemp:hddtemp~hddtemp~hddtemp~:-Dx_show_hdd_temp 
2268         ifconfig:net-tools~net-tools~net-tools~:-i_ip_lan-deprecated
2269         ip:iproute~iproute2~iproute~:-i_ip_lan
2270         sensors:lm-sensors~lm_sensors~lm-sensors~:-s_sensors_output
2271         strings:binutils~~~:-I_sysvinit_version
2272         lsusb:usbutils~usbutils~usbutils~:-A_usb_audio;-N_usb_networking 
2273         modinfo:module-init-tools~module-init-tools~module-init-tools~:-Ax,-Nx_module_version 
2274         runlevel:sysvinit~sysvinit~systemd~:-I_runlevel
2275         sudo:sudo~sudo~sudo~:-Dx_hddtemp-user;-o_file-user
2276         uptime:procps~procps~procps~:-I_uptime_(check_which_package_owns_Debian)
2277         '
2278         
2279         local downloaders="
2280         wget:wget~wget~wget~:-i_wan_ip;-w/-W;-U/-!_[11-15]_(if_supported)
2281         curl:curl~curl~curl~:-i_wan_ip;-w/-W;-U/-!_[11-15]_(if_supported)
2282         $downloaders_bsd
2283         "
2284         local recommended_dirs='
2285         /sys/class/dmi/id:-M_system,_motherboard,_bios
2286         /dev:-l,-u,-o,-p,-P,-D_disk_partition_data
2287         /dev/disk/by-label:-l,-o,-p,-P_partition_labels
2288         /dev/disk/by-uuid:-u,-o,-p,-P_partition_uuid
2289         '
2290         local recommended_files="
2291         $FILE_ASOUND_DEVICE:-A_sound_card_data
2292         $FILE_ASOUND_VERSION:-A_ALSA_data
2293         $FILE_CPUINFO:-C_cpu_data
2294         $FILE_LSB_RELEASE:-S_distro_version_data_[deprecated]
2295         $FILE_MDSTAT:-R_mdraid_data
2296         $FILE_MEMINFO:-I_memory_data
2297         $FILE_OS_RELEASE:-S_distro_version_data
2298         $FILE_PARTITIONS:-p,-P_partitions_data
2299         $FILE_MODULES:-G_module_data
2300         $FILE_MOUNTS:-P,-p_partition_advanced_data
2301         $FILE_DMESG_BOOT:-D,-d_disk_data_[BSD_only]
2302         $FILE_SCSI:-D_Advanced_hard_disk_data_[used_rarely]
2303         $FILE_XORG_LOG:-G_graphics_driver_load_status
2304         "
2305         
2306         if [[ -n $COLS_INNER ]];then
2307                 if [[ $COLS_INNER -ge 90 ]];then
2308                         width=${#LINE1} # match width of $LINE1
2309                 elif [[ $COLS_INNER -ge 78 ]];then
2310                         width=$(( $COLS_INNER - 11 ))
2311                 fi
2312         fi
2313         
2314         case $1 in
2315                 downloaders)
2316                         item_list=$downloaders
2317                         item_string='Downloaders'
2318                         item_string=''
2319                         missing_string='downloaders, and their corresponding packages,'
2320                         type='applications'
2321                         ;;
2322                 required-dirs)
2323                         item_list=$required_dirs
2324                         item_string='Required file system'
2325                         item_string=''
2326                         missing_string='system directories'
2327                         type='directories'
2328                         ;;
2329                 required-apps)
2330                         item_list=$required_apps
2331                         item_string='Required application'
2332                         item_string=''
2333                         missing_string='applications, and their corresponding packages,'
2334                         type='applications'
2335                         ;;
2336                 recommended-x-apps)
2337                         item_list=$x_recommends
2338                         item_string='Recommended X application'
2339                         item_string=''
2340                         missing_string='applications, and their corresponding packages,'
2341                         type='applications'
2342                         ;;
2343                 recommended-apps)
2344                         item_list=$recommended_apps
2345                         item_string='Recommended application'
2346                         item_string=''
2347                         missing_string='applications, and their corresponding packages,'
2348                         type='applications'
2349                         ;;
2350                 system-dirs)
2351                         item_list=$recommended_dirs
2352                         item_string='System directory'
2353                         item_string=''
2354                         missing_string='system directories'
2355                         type='directories'
2356                         ;;
2357                 system-files)
2358                         item_list=$recommended_files
2359                         item_string='System file'
2360                         item_string=''
2361                         missing_string='system files'
2362                         type='files'
2363                         ;;
2364         esac
2365         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
2366         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
2367         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
2368         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
2369         
2370         for item in $item_list
2371         do
2372                 if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 0 ]];then
2373                         application=$item
2374                         package=''
2375                         feature=''
2376                         location=''
2377                 elif [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 1 ]];then
2378                         application=$( cut -d ':' -f 1 <<< $item )
2379                         package=''
2380                         feature=$( cut -d ':' -f 2 <<< $item )
2381                         location=''
2382                 else
2383                         application=$( cut -d ':' -f 1 <<< $item )
2384                         package=$( cut -d ':' -f 2 <<< $item )
2385                         location=$( type -p $application )
2386                         if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 2 ]];then
2387                                 feature=$( cut -d ':' -f 3 <<< $item )
2388                         else
2389                                 feature=''
2390                         fi
2391                 fi
2392                 if [[ -n $feature ]];then
2393                         print_string="$item_string$application (info: $( sed 's/_/ /g' <<< $feature ))"
2394                 else
2395                         print_string="$item_string$application"
2396                 fi
2397                 
2398                 starter="$( sed -e :a -e 's/^.\{1,'$width'\}$/&./;ta' <<< $print_string )"
2399                 if [[ -z $( grep '^/' <<< $application ) && -n $location ]] || [[ -d $application || -f $application ]];then
2400                         if [[ -n $location ]];then
2401                                 finisher=" $location"
2402                         else
2403                                 finisher=" Present"
2404                         fi
2405                 else
2406                         finisher=" Missing"
2407                         missing_items="$missing_items$separator$application:$package"
2408                         separator=' '
2409                 fi
2410                 
2411                 echo "$starter$finisher"
2412         done
2413         echo 
2414         if [[ -n $missing_items ]];then
2415                 echo "The following $type are missing from your system:"
2416                 for item in $missing_items
2417                 do
2418                         application=$( cut -d ':' -f 1 <<< $item )
2419                         if [[ $type == 'applications' ]];then
2420                                 echo
2421                                 package=$( cut -d ':' -f 2 <<< $item )
2422                                 package_deb=$( cut -d '~' -f 1 <<< $package )
2423                                 package_pacman=$( cut -d '~' -f 2 <<< $package )
2424                                 package_rpm=$( cut -d '~' -f 3 <<< $package )
2425                                 echo "Application: $application"
2426                                 print_lines_basic "0" "" "To add to your system, install the proper distribution package for your system:"
2427                                 print_lines_basic "0" "" "Debian/Ubuntu:^$package_deb^:: Arch Linux:^$package_pacman^:: Redhat/Fedora/Suse:^$package_rpm"
2428                         elif [[ $type == 'directories' ]];then
2429                                 echo "Directory: $application"
2430                         elif [[ $type == 'files' ]];then
2431                                 echo "File: $application"
2432                         fi
2433                 done
2434                 if [[ $item_string == 'System directory' ]];then
2435                         print_lines_basic "0" "" "These directories are created by the kernel, so don't worry if they are not present."
2436                 fi
2437         else
2438                 echo "All the $( cut -d ' ' -f 1 <<< $item_string | sed -e 's/Re/re/' -e 's/Sy/sy/' ) $type are present."
2439         fi
2440         echo $Line
2441 }
2442
2443 #### -------------------------------------------------------------------
2444 #### print / output cleaners
2445 #### -------------------------------------------------------------------
2446
2447 # inxi speaks through here. When run by Konversation script alias mode, uses DCOP
2448 # for dcop to work, must use 'say' operator, AND colors must be evaluated by echo -e
2449 # note: dcop does not seem able to handle \n so that's being stripped out and replaced with space.
2450 print_screen_output()
2451 {
2452         eval $LOGFS
2453         # the double quotes are needed to avoid losing whitespace in data when certain output types are used
2454         # trim off whitespace at end
2455         local print_data="$( echo -e "$1" )" 
2456
2457         # just using basic debugger stuff so you can tell which thing is printing out the data. This
2458         # should help debug kde 4 konvi issues when that is released into sid, we'll see. Turning off
2459         # the redundant debugger output which as far as I can tell does exactly nothing to help debugging.
2460         if [[ $DEBUG -gt 5 ]];then
2461                 if [[ $KONVI -eq 1 ]];then
2462                         # konvi doesn't seem to like \n characters, it just prints them literally
2463                         # print_data="$( tr '\n' ' ' <<< "$print_data" )"
2464                         # dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "konvi='$KONVI' saying : '$print_data'"
2465                         print_data="KP-$KONVI: $print_data"
2466                 elif [[ $KONVI -eq 2 ]];then
2467                         # echo "konvi='$KONVI' saying : '$print_data'"
2468                         print_data="KP-$KONVI: $print_data"
2469                 else
2470                         # echo "printing out: '$print_data'"
2471                         print_data="P: $print_data"
2472                 fi
2473         fi
2474         if [[ $KONVI -eq 1 && $B_DCOP == 'true' ]]; then ## dcop Konversation (<= 1.1 (qt3))
2475                 # konvi doesn't seem to like \n characters, it just prints them literally
2476                 $print_data="$( tr '\n' ' ' <<< "$print_data" )"
2477                 dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "$print_data"
2478         elif [[ $KONVI -eq 3 && $B_QDBUS == 'true' ]]; then ## dbus Konversation (> 1.2 (qt4))
2479                 qdbus org.kde.konversation /irc say "$DCSERVER" "$DCTARGET" "$print_data"
2480 #       elif [[ $IRC_CLIENT == 'X-Chat' ]]; then
2481 #               qdbus org.xchat.service print "$print_data\n"
2482         else
2483                 # the -n is needed to avoid double spacing of output in terminal
2484                 echo -ne "$print_data\n"
2485         fi
2486         eval $LOGFE
2487 }
2488
2489 ## this handles all verbose line construction with indentation/line starter
2490 ## args: $1 - null (, actually: " ") or line starter; $2 - line content
2491 create_print_line()
2492 {
2493         eval $LOGFS
2494         # convoluted, yes, but it works to trim spaces off end
2495         local line=${2%${2##*[![:space:]]}}
2496         printf "${C1}%-${INDENT}s${C2} %s" "$1" "$line${CN}"
2497         eval $LOGFE
2498 }
2499
2500 # this removes newline and pipes.
2501 # args: $1 - string to clean
2502 remove_erroneous_chars()
2503 {
2504         eval $LOGFS
2505         ## RS is input record separator
2506         ## gsub is substitute;
2507         gawk '
2508         BEGIN {
2509                 RS=""
2510         }
2511         {
2512                 gsub(/\n$/,"")         ## (newline; end of string) with (nothing)
2513                 gsub(/\n/," ");        ## (newline) with (space)
2514                 gsub(/^ *| *$/, "")    ## (pipe char) with (nothing)
2515                 gsub(/  +/, " ")       ## ( +) with (space)
2516                 gsub(/ [ ]+/, " ")     ## ([ ]+) with (space)
2517                 gsub(/^ +| +$/, "")    ## (pipe char) with (nothing)
2518                 printf $0
2519         }' "$1"      ## prints (returns) cleaned input
2520         eval $LOGFE
2521 }
2522
2523 #### -------------------------------------------------------------------
2524 #### parameter handling, print usage functions.
2525 #### -------------------------------------------------------------------
2526
2527 # Get the parameters. Note: standard options should be lower case, advanced or testing, upper
2528 # args: $1 - full script startup args: $@
2529 get_parameters()
2530 {
2531         eval $LOGFS
2532         local opt='' downloader_test='' debug_data_type='' weather_flag='wW:' 
2533         local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false
2534
2535         # if distro maintainers don't want the weather feature disable it
2536         if [[ $B_ALLOW_WEATHER == 'false' ]];then
2537                 weather_flag=''
2538         fi
2539         if [[ $1 == '--version' ]];then
2540                 print_version_info
2541                 exit 0
2542         elif [[ $1 == '--help' ]];then
2543                 show_options
2544                 exit 0
2545         elif [[ $1 == '--recommends' ]];then
2546                 check_recommends_user_output
2547                 exit 0
2548         # the short form only runs if no args output args are used
2549         # no need to run through these if there are no args
2550         # reserved for future use: -g for extra Graphics; -m for extra Machine; -d for extra Disk
2551         elif [[ -n $1 ]];then
2552                 while getopts AbBc:CdDfFGhHiIlmMnNopPrRsSt:uUv:V${weather_flag}xy:zZ%@:!: opt
2553                 do
2554                         case $opt in
2555                         A)      B_SHOW_AUDIO='true'
2556                                 use_short='false'
2557                                 ;;
2558                         b)      use_short='false'
2559                                 B_SHOW_BASIC_CPU='true'
2560                                 B_SHOW_BASIC_RAID='true'
2561                                 B_SHOW_DISK_TOTAL='true'
2562                                 B_SHOW_GRAPHICS='true'
2563                                 B_SHOW_INFO='true'
2564                                 B_SHOW_MACHINE='true'
2565                                 B_SHOW_BATTERY='true'
2566                                 B_SHOW_NETWORK='true'
2567                                 B_SHOW_SYSTEM='true'
2568                                 ;;
2569                         B)      B_SHOW_BATTERY_FORCED='true'
2570                                 B_SHOW_BATTERY='true'
2571                                 use_short='false'
2572                                 ;;
2573                         c)      if [[ $OPTARG =~ ^[0-9][0-9]?$ ]];then
2574                                         case $OPTARG in
2575                                                 99)
2576                                                         B_RUN_COLOR_SELECTOR='true'
2577                                                         COLOR_SELECTION='global'
2578                                                         ;;
2579                                                 98)
2580                                                         B_RUN_COLOR_SELECTOR='true'
2581                                                         COLOR_SELECTION='irc-console'
2582                                                         ;;
2583                                                 97)
2584                                                         B_RUN_COLOR_SELECTOR='true'
2585                                                         COLOR_SELECTION='irc-virtual-terminal'
2586                                                         ;;
2587                                                 96)
2588                                                         B_RUN_COLOR_SELECTOR='true'
2589                                                         COLOR_SELECTION='irc'
2590                                                         ;;
2591                                                 95)
2592                                                         B_RUN_COLOR_SELECTOR='true'
2593                                                         COLOR_SELECTION='virtual-terminal'
2594                                                         ;;
2595                                                 94)
2596                                                         B_RUN_COLOR_SELECTOR='true'
2597                                                         COLOR_SELECTION='console'
2598                                                         ;;
2599                                                 *)      
2600                                                         B_COLOR_SCHEME_SET='true'
2601                                                         ## note: not sure about this, you'd think user values should be overridden, but
2602                                                         ## we'll leave this for now
2603                                                         if [[ -z $COLOR_SCHEME ]];then
2604                                                                 set_color_scheme "$OPTARG"
2605                                                         fi
2606                                                         ;;
2607                                         esac
2608                                 else
2609                                         error_handler 3 "$OPTARG"
2610                                 fi
2611                                 ;;
2612                         C)      B_SHOW_CPU='true'
2613                                 use_short='false'
2614                                 ;;
2615                         d)      B_SHOW_DISK='true'
2616                                 B_SHOW_FULL_OPTICAL='true'
2617                                 use_short='false'
2618                                 # error_handler 20 "-d has been replaced by -b"
2619                                 ;;
2620                         D)      B_SHOW_DISK='true'
2621                                 use_short='false'
2622                                 ;;
2623                         f)      B_SHOW_CPU='true'
2624                                 B_CPU_FLAGS_FULL='true'
2625                                 use_short='false'
2626                                 ;;
2627                         F)      # B_EXTRA_DATA='true'
2628                                 B_SHOW_ADVANCED_NETWORK='true'
2629                                 B_SHOW_AUDIO='true'
2630                                 # B_SHOW_BASIC_OPTICAL='true'
2631                                 B_SHOW_CPU='true'
2632                                 B_SHOW_DISK='true'
2633                                 B_SHOW_GRAPHICS='true'
2634                                 B_SHOW_INFO='true'
2635                                 B_SHOW_MACHINE='true'
2636                                 B_SHOW_BATTERY='true'
2637                                 B_SHOW_NETWORK='true'
2638                                 B_SHOW_PARTITIONS='true'
2639                                 B_SHOW_RAID='true'
2640                                 B_SHOW_SENSORS='true'
2641                                 B_SHOW_SYSTEM='true'
2642                                 use_short='false'
2643                                 ;;
2644                         G)      B_SHOW_GRAPHICS='true'
2645                                 use_short='false'
2646                                 ;;
2647                         i)      B_SHOW_IP='true'
2648                                 B_SHOW_NETWORK='true'
2649                                 B_SHOW_ADVANCED_NETWORK='true'
2650                                 use_short='false'
2651                                 ;;
2652                         I)      B_SHOW_INFO='true'
2653                                 use_short='false'
2654                                 ;;
2655                         l)      B_SHOW_LABELS='true'
2656                                 B_SHOW_PARTITIONS='true'
2657                                 use_short='false'
2658                                 ;;
2659                         m)      B_SHOW_MEMORY='true'
2660                                 use_short='false'
2661                                 ;;
2662                         M)      B_SHOW_MACHINE='true'
2663                                 B_SHOW_BATTERY='true'
2664                                 use_short='false'
2665                                 ;;
2666                         n)      B_SHOW_ADVANCED_NETWORK='true'
2667                                 B_SHOW_NETWORK='true'
2668                                 use_short='false'
2669                                 ;;
2670                         N)      B_SHOW_NETWORK='true'
2671                                 use_short='false'
2672                                 ;;
2673                         o)      B_SHOW_UNMOUNTED_PARTITIONS='true'
2674                                 use_short='false'
2675                                 ;;
2676                         p)      B_SHOW_PARTITIONS_FULL='true'
2677                                 B_SHOW_PARTITIONS='true'
2678                                 use_short='false'
2679                                 ;;
2680                         P)      B_SHOW_PARTITIONS='true'
2681                                 use_short='false'
2682                                 ;;
2683                         r)      B_SHOW_REPOS='true'
2684                                 use_short='false'
2685                                 ;;
2686                         R)      B_SHOW_RAID='true'
2687                                 # it turns out only users with mdraid software installed will have raid,
2688                                 # so unless -R is explicitly called, blank -b/-F/-v6 and less output will not show
2689                                 # error if file is missing.
2690                                 B_SHOW_RAID_R='true'
2691                                 use_short='false'
2692                                 ;;
2693                         s)      B_SHOW_SENSORS='true'
2694                                 use_short='false'
2695                                 ;;
2696                         S)      B_SHOW_SYSTEM='true'
2697                                 use_short='false'
2698                                 ;;
2699                         t)      if [[ $OPTARG =~ ^(c|m|cm|mc)([1-9]|1[0-9]|20)?$ ]];then
2700                                         use_short='false'
2701                                         if [[ -n $( grep -E '[0-9]+' <<< $OPTARG ) ]];then
2702                                                 PS_COUNT=$( sed 's/[^0-9]//g' <<< $OPTARG )
2703                                         fi
2704                                         if [[ -n $( grep 'c' <<< $OPTARG ) ]];then
2705                                                 B_SHOW_PS_CPU_DATA='true'
2706                                         fi
2707                                         if [[ -n $( grep 'm' <<< $OPTARG ) ]];then
2708                                                 B_SHOW_PS_MEM_DATA='true'
2709                                         fi
2710                                 else
2711                                         error_handler 13 "$OPTARG"
2712                                 fi
2713                                 ;;
2714                         u)      B_SHOW_UUIDS='true'
2715                                 B_SHOW_PARTITIONS='true'
2716                                 use_short='false'
2717                                 ;;
2718                         v)      if [[ $OPTARG =~ ^[0-9][0-9]?$ && $OPTARG -le $VERBOSITY_LEVELS ]];then
2719                                         if [[ $OPTARG -ge 1 ]];then
2720                                                 use_short='false'
2721                                                 B_SHOW_BASIC_CPU='true'
2722                                                 B_SHOW_DISK_TOTAL='true'
2723                                                 B_SHOW_GRAPHICS='true'
2724                                                 B_SHOW_INFO='true'
2725                                                 B_SHOW_SYSTEM='true'
2726                                         fi
2727                                         if [[ $OPTARG -ge 2 ]];then
2728                                                 B_SHOW_BASIC_DISK='true'
2729                                                 B_SHOW_BASIC_RAID='true'
2730                                                 B_SHOW_BATTERY='true'
2731                                                 B_SHOW_MACHINE='true'
2732                                                 B_SHOW_NETWORK='true'
2733                                         fi
2734                                         if [[ $OPTARG -ge 3 ]];then
2735                                                 B_SHOW_ADVANCED_NETWORK='true'
2736                                                 B_SHOW_CPU='true'
2737                                                 B_EXTRA_DATA='true'
2738                                         fi
2739                                         if [[ $OPTARG -ge 4 ]];then
2740                                                 B_SHOW_DISK='true'
2741                                                 B_SHOW_PARTITIONS='true'
2742                                         fi
2743                                         if [[ $OPTARG -ge 5 ]];then
2744                                                 B_SHOW_AUDIO='true'
2745                                                 B_SHOW_BASIC_OPTICAL='true'
2746                                                 B_SHOW_MEMORY='true'
2747                                                 B_SHOW_SENSORS='true'
2748                                                 B_SHOW_LABELS='true'
2749                                                 B_SHOW_UUIDS='true'
2750                                                 B_SHOW_RAID='true'
2751                                         fi
2752                                         if [[ $OPTARG -ge 6 ]];then
2753                                                 B_SHOW_FULL_OPTICAL='true'
2754                                                 B_SHOW_PARTITIONS_FULL='true'
2755                                                 B_SHOW_UNMOUNTED_PARTITIONS='true'
2756                                                 B_EXTRA_EXTRA_DATA='true'
2757                                         fi
2758                                         if [[ $OPTARG -ge 7 ]];then
2759                                                 B_EXTRA_EXTRA_EXTRA_DATA='true'
2760                                                 B_SHOW_IP='true'
2761                                                 B_SHOW_RAID_R='true'
2762                                         fi
2763                                 else
2764                                         error_handler 4 "$OPTARG"
2765                                 fi
2766                                 ;;
2767                         U)      if [[ $B_ALLOW_UPDATE == 'true' ]];then
2768                                         script_self_updater "$SCRIPT_DOWNLOAD" 'svn server' "$opt"
2769                                 else
2770                                         error_handler 17 "-$opt"
2771                                 fi
2772                                 ;;
2773                         V)      print_version_info
2774                                 exit 0
2775                                 ;;
2776                         w)      B_SHOW_WEATHER=true
2777                                 use_short='false'
2778                                 ;;
2779                         W)      ALTERNATE_WEATHER_LOCATION=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'  <<< $OPTARG )
2780                                 if [[ -n $( grep -Esi '([^,]+,.+|[0-9-]+)' <<< $ALTERNATE_WEATHER_LOCATION ) ]];then
2781                                         B_SHOW_WEATHER=true
2782                                         use_short='false'
2783                                 else
2784                                         error_handler 18 "-$opt: '$OPTARG'" "city,state OR latitude,longitude OR postal/zip code."
2785                                 fi
2786                                 ;;
2787                         # this will trigger either with x, xx, xxx or with Fx but not with xF
2788                         x)      if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2789                                         B_EXTRA_EXTRA_EXTRA_DATA='true'
2790                                 elif [[ $B_EXTRA_DATA == 'true' ]];then
2791                                         B_EXTRA_EXTRA_DATA='true'
2792                                 else
2793                                         B_EXTRA_DATA='true'
2794                                 fi
2795                                 ;;
2796                         y)      if [[ -z ${OPTARG//[0-9]/} && $OPTARG -ge 80 ]];then
2797                                         set_display_width "$OPTARG"
2798                                 else
2799                                         error_handler 21 "$OPTARG"
2800                                 fi
2801                                 ;;
2802                         z)      B_OUTPUT_FILTER='true'
2803                                 ;;
2804                         Z)      B_OVERRIDE_FILTER='true'
2805                                 ;;
2806                         h)      show_options
2807                                 exit 0
2808                                 ;;
2809                         H)      show_options 'full'
2810                                 exit 0
2811                                 ;;
2812                         ## debuggers and testing tools
2813                         %)      B_HANDLE_CORRUPT_DATA='true'
2814                                 ;;
2815                         @)      if [[ -n $( grep -E "^([1-9]|1[0-5])$" <<< $OPTARG ) ]];then
2816                                         DEBUG=$OPTARG
2817                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2818                                                 B_UPLOAD_DEBUG_DATA='true'
2819                                         fi
2820                                         exec 2>&1
2821                                         # switch on logging only for -@ 8-10
2822                                         case $OPTARG in
2823                                                 8|9|10)
2824                                                         if [[ $OPTARG -eq 10 ]];then
2825                                                                 B_LOG_COLORS='true'
2826                                                         elif [[ $OPTARG -eq 9 ]];then           
2827                                                                 B_LOG_FULL_DATA='true'
2828                                                         fi
2829                                                         B_USE_LOGGING='true'
2830                                                         # pack the logging data for evals function start/end
2831                                                         LOGFS=$LOGFS_STRING
2832                                                         LOGFE=$LOGFE_STRING
2833                                                         create_rotate_logfiles # create/rotate logfiles before we do anything else
2834                                                         ;;
2835                                                 11|12|13|14|15)
2836                                                         case $OPTARG in
2837                                                                 11)
2838                                                                         debug_data_type='sys'
2839                                                                         ;;
2840                                                                 12)
2841                                                                         debug_data_type='xorg'
2842                                                                         ;;
2843                                                                 13)
2844                                                                         debug_data_type='disk'
2845                                                                         ;;
2846                                                                 14)
2847                                                                         debug_data_type='all'
2848                                                                         ;;
2849                                                                 15)
2850                                                                         debug_data_type='all'
2851                                                                         B_DEBUG_I='true'
2852                                                                         ;;
2853                                                         esac
2854                                                         initialize_data
2855                                                         debug_data_collector $debug_data_type
2856                                                         ;;
2857                                         esac
2858                                 else
2859                                         error_handler 9 "$OPTARG"
2860                                 fi
2861                                 ;;
2862                         !)      # test for various supported methods
2863                                 case $OPTARG in
2864                                         1)      B_TESTING_1='true'
2865                                                 ;;
2866                                         2)      B_TESTING_2='true'
2867                                                 ;;
2868                                         3)      B_TESTING_1='true'
2869                                                 B_TESTING_2='true'
2870                                                 ;;
2871                                         1[0-6]|http*)
2872                                                 if [[ $B_ALLOW_UPDATE == 'true' ]];then
2873                                                         case $OPTARG in
2874                                                                 10)
2875                                                                         script_self_updater "$SCRIPT_DOWNLOAD_DEV" 'dev server' "$opt $OPTARG"
2876                                                                         ;;
2877                                                                 11)
2878                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_1" 'svn: branch one server' "$opt $OPTARG"
2879                                                                         ;;
2880                                                                 12)
2881                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_2" 'svn: branch two server' "$opt $OPTARG"
2882                                                                         ;;
2883                                                                 13)
2884                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_3" 'svn: branch three server' "$opt $OPTARG"
2885                                                                         ;;
2886                                                                 14)
2887                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_4" 'svn: branch four server' "$opt $OPTARG"
2888                                                                         ;;
2889                                                                 15)
2890                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_BSD" 'svn: branch bsd server' "$opt $OPTARG"
2891                                                                         ;;
2892                                                                 16)
2893                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_GNUBSD" 'svn: branch gnubsd server' "$opt $OPTARG"
2894                                                                         ;;
2895                                                                 http*)
2896                                                                         script_self_updater "$OPTARG" 'alt server' "$opt <http...>"
2897                                                                         ;;
2898                                                         esac
2899                                                 else
2900                                                         error_handler 17 "-$opt $OPTARG"
2901                                                 fi
2902                                                 ;;
2903                                         30)
2904                                                 B_IRC='false'
2905                                                 ;;
2906                                         31)
2907                                                 B_SHOW_HOST='false'
2908                                                 ;;
2909                                         32)
2910                                                 B_SHOW_HOST='true'
2911                                                 ;;
2912                                         33)
2913                                                 B_FORCE_DMIDECODE='true'
2914                                                 ;;
2915                                         ftp*)
2916                                                 ALTERNATE_FTP="$OPTARG"
2917                                                 ;;
2918                                         # for weather function, allows user to set an alternate weather location
2919                                         location=*)
2920                                                 error_handler 19 "-$opt location=" "-W"
2921                                                 ;;
2922                                         *)      error_handler 11 "$OPTARG"
2923                                                 ;;
2924                                 esac
2925                                 ;;
2926                         *)      error_handler 7 "$1"
2927                                 ;;
2928                         esac
2929                 done
2930         fi
2931         ## this must occur here so you can use the debugging flag to show errors
2932         ## Reroute all error messages to the bitbucket (if not debugging)
2933         if [[ $DEBUG -eq 0 ]];then
2934                 exec 2>/dev/null
2935         fi
2936         #((DEBUG)) && exec 2>&1 # This is for debugging konversation
2937
2938         # after all the args have been processed, if no long output args used, run short output
2939         if [[ $use_short == 'true' ]];then
2940                 B_SHOW_SHORT_OUTPUT='true'
2941         fi
2942         # just in case someone insists on using -zZ
2943         if [[ $B_OVERRIDE_FILTER == 'true' ]];then
2944                 B_OUTPUT_FILTER='false'
2945         fi
2946         # change basic to full if user requested it or if arg overrides it
2947         if [[ $B_SHOW_RAID == 'true' && $B_SHOW_BASIC_RAID == 'true' ]];then
2948                 B_SHOW_BASIC_RAID='false'
2949         fi
2950         
2951         
2952         eval $LOGFE
2953 }
2954
2955 ## print out help menu, not including Testing or Debugger stuff because it's not needed
2956 show_options()
2957 {
2958         local color_scheme_count=$(( ${#A_COLOR_SCHEMES[@]} - 1 ))
2959         local partition_string='partition' partition_string_u='Partition'
2960         
2961         if [[ $B_IRC == 'true' ]];then
2962                 print_screen_output "Sorry, you can't run the help option in an IRC client."
2963                 exit 1
2964         fi
2965         if [[ -n $BSD_TYPE ]];then
2966                 partition_string='slice'
2967                 partition_string_u='Slice'
2968         fi
2969         # print_lines_basic "0" "" ""
2970         # print_lines_basic "1" "" ""
2971         # print_lines_basic "2" "" ""
2972         # print_screen_output " "
2973         print_lines_basic "0" "" "$SCRIPT_NAME supports the following options. You can combine them, or list them one by one. Examples: $SCRIPT_NAME^-v4^-c6 OR $SCRIPT_NAME^-bDc^6. If you start $SCRIPT_NAME with no arguments, it will show the short form."
2974         print_screen_output " "
2975         print_lines_basic "0" "" "The following options if used without -F, -b, or -v will show just option line(s): A, B, C, D, G, I, M, N, P, R, S, f, i, m, n, o, p, l, u, r, s, t - you can use these alone or together to show just the line(s) you want to see. If you use them with -v^[level], -b or -F, it will show the full output for that line along with the output for the chosen verbosity level."
2976         print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
2977         print_screen_output "Output Control Options:"
2978         print_lines_basic "1" "-A" "Audio/sound card information."
2979         print_lines_basic "1" "-b" "Basic output, short form. Like $SCRIPT_NAME^-v^2, only minus hard disk names ."
2980         print_lines_basic "1" "-B" "Battery info, shows charge, condition, plus extra information (if battery present)."
2981         print_lines_basic "1" "-c" "Color schemes. Scheme number is required. Color selectors run a color selector option prior to $SCRIPT_NAME starting which lets you set the config file value for the selection."
2982         print_lines_basic "1" "" "Supported color schemes: 0-$color_scheme_count Example:^$SCRIPT_NAME^-c^11"
2983         print_lines_basic "1" "" "Color selectors for each type display (NOTE: irc and global only show safe color set):"
2984 #       print_screen_output "    Supported color schemes: 0-$color_scheme_count Example: $SCRIPT_NAME -c 11"
2985 #       print_screen_output "    Color selectors for each type display (NOTE: irc and global only show safe color set):"
2986         print_lines_basic "2" "94" "Console, out of X"
2987         print_lines_basic "2" "95" "Terminal, running in X - like xTerm"
2988         print_lines_basic "2" "96" "Gui IRC, running in X - like Xchat, Quassel, Konversation etc."
2989         print_lines_basic "2" "97" "Console IRC running in X - like irssi in xTerm"
2990         print_lines_basic "2" "98" "Console IRC not in  X"
2991         print_lines_basic "2" "99" "Global - Overrides/removes all settings. Setting specific removes global."
2992         print_lines_basic "1" "-C" "CPU output, including per CPU clockspeed and max CPU speed (if available)."
2993         print_lines_basic "1" "-d" "Optical drive data. Same as -Dd. See also -x and -xx."
2994         print_lines_basic "1" "-D" "Full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB. See also -x and -xx. Disk total used percentage includes swap partition size(s)."
2995         print_lines_basic "1" "-f" "All cpu flags, triggers -C. Not shown with -F to avoid spamming. ARM cpus show 'features'."
2996         print_lines_basic "1" "-F" "Full output for $SCRIPT_NAME. Includes all Upper Case line letters, plus -s and -n. Does not show extra verbose options like -d -f -l -m -o -p -r -t -u -x"
2997         print_lines_basic "1" "-G" "Graphic card information (card, display server type/version, resolution, glx renderer, version)."
2998         print_lines_basic "1" "-i" "Wan IP address, and shows local interfaces (requires ifconfig 
2999         network tool). Same as -Nni. Not shown with -F for user security reasons, you shouldn't paste your local/wan IP."
3000         print_lines_basic "1" "-I" "Information: processes, uptime, memory, irc client (or shell type), $SCRIPT_NAME version."
3001         print_lines_basic "1" "-l" "$partition_string_u labels. Default: short $partition_string -P. For full -p output, use: -pl (or -plu)."
3002         print_lines_basic "1" "-m" "Memory (RAM) data. Physical system memory array(s), capacity, how many devices (slots) supported, and individual memory devices (sticks of memory etc). For devices, shows device locator, size, speed, type (like: DDR3). Also see -x, -xx, -xxx"
3003         print_lines_basic "1" "-M" "Machine data. Motherboard, Bios, and if present, System Builder (Like Lenovo). Older systems/kernels without the required /sys data can use dmidecode instead, run as root. Dmidecode can be forced with -! 33"
3004         print_lines_basic "1" "-n" "Advanced Network card information. Same as -Nn. Shows interface, speed, mac id, state, etc."
3005         print_lines_basic "1" "-N" "Network card information. With -x, shows PCI BusID, Port number."
3006         print_lines_basic "1" "-o" "Unmounted $partition_string information (includes UUID and LABEL if available). Shows file system type if you have file installed, if you are root OR if you have added to /etc/sudoers (sudo v. 1.7 or newer) Example:^<username>^ALL^=^NOPASSWD:^/usr/bin/file^"
3007         print_lines_basic "1" "-p" "Full $partition_string information (-P plus all other detected ${partition_string}s)."
3008         print_lines_basic "1" "-P" "Basic $partition_string information (shows what -v^4 would show, but without extra data). Shows, if detected: / /boot /home /tmp /usr /var. Use -p to see all mounted ${partition_string}s."
3009         print_lines_basic "1" "-r" "Distro repository data. Supported repo types: APT; PACMAN; PISI; PORTAGE; PORTS (BSDs); SLACKPKG; URPMQ; YUM; ZYPP."
3010         print_lines_basic "1" "-R" "RAID data. Shows RAID devices, states, levels, and components, and extra data with -x/-xx. md-raid: If device is resyncing, shows resync progress line as well."
3011         print_lines_basic "1" "-s" "Sensors output (if sensors installed/configured): mobo/cpu/gpu temp; detected fan speeds. Gpu temp only for Fglrx/Nvidia drivers. Nvidia shows screen number for > 1 screens."
3012         print_lines_basic "1" "-S" "System information: host name, kernel, desktop environment (if in X), distro"
3013         print_lines_basic "1" "-t" "Processes. Requires extra options: c^(cpu) m^(memory) cm^(cpu+memory). If followed by numbers 1-20, shows that number of processes for each type (default:^$PS_COUNT; if in irc, max:^5): -t^cm10"
3014         print_lines_basic "1" "" "Make sure to have no space between letters and numbers (-t^cm10 - right, -t^cm^10 - wrong)."
3015         print_lines_basic "1" "-u" "$partition_string_u UUIDs. Default: short $partition_string -P. For full -p output, use: -pu (or -plu)."
3016         print_lines_basic "1" "-v" "Script verbosity levels. Verbosity level number is required. Should not be used with -b or -F"
3017         print_lines_basic "1" "" "Supported levels: 0-$VERBOSITY_LEVELS Example: $SCRIPT_NAME^-v^4"
3018         print_lines_basic "2" "0" "Short output, same as: $SCRIPT_NAME"
3019         print_lines_basic "2" "1" "Basic verbose, -S + basic CPU + -G + basic Disk + -I."
3020         print_lines_basic "2" "2" "Networking card (-N), Machine (-M) data, if present, Battery (-B), basic hard disk data (names only), and, if present, basic raid (devices only, and if inactive, notes that). similar to: $SCRIPT_NAME^-b"
3021         print_lines_basic "2" "3" "Advanced CPU (-C), battery, network (-n) data, and switches on -x advanced data option."
3022         print_lines_basic "2" "4" "$partition_string_u size/filled data (-P) for (if present): /, /home, /var/, /boot. Shows full disk data (-D)."
3023         print_lines_basic "2" "5" "Audio card (-A); sensors^(-s), memory/ram^(-m), $partition_string label^(-l) and UUID^(-u), short form of optical drives, standard raid data (-R)."
3024         print_lines_basic "2" "6" "Full $partition_string (-p), unmounted $partition_string (-o), optical drive (-d), full raid; triggers -xx."
3025         print_lines_basic "2" "7" "Network IP data (-i); triggers -xxx."
3026         
3027         # if distro maintainers don't want the weather feature disable it
3028         if [[ $B_ALLOW_WEATHER == 'true' ]];then
3029                 print_lines_basic "1" "-w" "Local weather data/time. To check an alternate location, see: -W^<location>. For extra weather data options see -x, -xx, and -xxx."
3030                 print_lines_basic "1" "-W" "<location> Supported options for <location>: postal code; city, state/country; latitude, longitude. Only use if you want the weather somewhere other than the machine running $SCRIPT_NAME. Use only ascii characters, replace spaces in city/state/country names with '+'. Example:^$SCRIPT_NAME^-W^new+york,ny"
3031         fi
3032         print_lines_basic "1" "-x" "Adds the following extra data (only works with verbose or line output, not short form):"
3033         print_lines_basic "2" "-B" "Vendor/model, status (if available)"
3034         print_lines_basic "2" "-C" "CPU Flags, Bogomips on Cpu;"
3035         print_lines_basic "2" "-d" "Extra optical drive data; adds rev version to optical drive."
3036         print_lines_basic "2" "-D" "Hdd temp with disk data if you have hddtemp installed, if you are root OR if you have added to /etc/sudoers (sudo v. 1.7 or newer) Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp"
3037         print_lines_basic "2" "-G" "Direct rendering status for Graphics (in X)."
3038         print_lines_basic "2" "-G" "(for single gpu, nvidia driver) screen number gpu is running on."
3039         print_lines_basic "2" "-i" "IPv6 as well for LAN interface (IF) devices."
3040         print_lines_basic "2" "-I" "System GCC, default. With -xx, also show other installed GCC versions. If running in console, not in IRC client, shows shell version number, if detected. Init/RC Type and runlevel (if available)."
3041         print_lines_basic "2" "-m" "Part number; Max memory module size (if available)."
3042         print_lines_basic "2" "-N -A" "Version/port(s)/driver version (if available) for Network/Audio;"
3043         print_lines_basic "2" "-N -A -G" "Network, audio, graphics, shows PCI Bus ID/Usb ID number of card."
3044         print_lines_basic "2" "-R" "md-raid: Shows component raid id. Adds second RAID Info line: raid level; report on drives (like 5/5); blocks; chunk size; bitmap (if present). Resync line, shows blocks synced/total blocks. zfs-raid:    Shows raid array full size; available size; portion allocated to RAID"
3045         print_lines_basic "2" "-S" "Desktop toolkit if avaliable (GNOME/XFCE/KDE only); Kernel gcc version"
3046         print_lines_basic "2" "-t" "Memory use output to cpu (-xt c), and cpu use to memory (-xt m)."
3047         if [[ $B_ALLOW_WEATHER == 'true' ]];then
3048                 print_lines_basic "2" "-w -W" "Wind speed and time zone (-w only)."
3049         fi
3050         print_lines_basic "1" "-xx" "Show extra, extra data (only works with verbose or line output, not short form):"
3051         print_lines_basic "2" "-A" "Chip vendor:product ID for each audio device."
3052         print_lines_basic "2" "-B" "serial number, voltage (if available)."
3053         print_lines_basic "2" "-C" "Minimum CPU speed, if available."
3054         print_lines_basic "2" "-D" "Disk serial number."
3055         print_lines_basic "2" "-G" "Chip vendor:product ID for each video card."
3056         print_lines_basic "2" "-I" "Other detected installed gcc versions (if present). System default runlevel. Adds parent program (or tty) for shell info if not in IRC (like Konsole or Gterm). Adds Init/RC (if found) version number."
3057         print_lines_basic "2" "-m" "Manufacturer, Serial Number, single/double bank (if found)."
3058         print_lines_basic "2" "-M" "Chassis information, bios rom size (dmidecode only), if data for either is available."
3059         print_lines_basic "2" "-N" "Chip vendor:product ID for each nic."
3060         print_lines_basic "2" "-R" "md-raid: Superblock (if present); algorythm, U data. Adds system info line (kernel support,read ahead, raid events). If present, adds unused device line. Resync line, shows progress bar."
3061         print_lines_basic "2" "-S" "Display manager (dm) in desktop output, if in X (like kdm, gdm3, lightdm)."
3062         if [[ $B_ALLOW_WEATHER == 'true' ]];then
3063                 print_lines_basic "2" "-w -W" "Humidity, barometric pressure."
3064         fi
3065         print_lines_basic "2" "-@ 11-14" "Automatically uploads debugger data tar.gz file to ftp.techpatterns.com. EG: $SCRIPT_NAME^-xx@14"
3066         print_lines_basic "1" "-xxx" "Show extra, extra, extra data (only works with verbose or line output, not short form):"
3067         print_lines_basic "2" "-B" "chemistry, cycles, location (if available)."
3068         print_lines_basic "2" "-m" "Width of memory bus, data and total (if present and greater than data); Detail, if present, for Type; module voltage, if available."
3069         print_lines_basic "2" "-S" "Panel/shell information in desktop output, if in X (like gnome-shell, cinnamon, mate-panel)."
3070         if [[ $B_ALLOW_WEATHER == 'true' ]];then
3071                 print_lines_basic "2" "-w -W" "Location (uses -z/irc filter), weather observation time, wind chill, heat index, dew point (shows extra lines for data where relevant)."
3072         fi
3073         print_lines_basic "1" "-y" "Required extra option: integer, 80 or greater. Set the output line width max. Overrides IRC/Terminal settings or actual widths. If used with -h, put -y option first. Example:^inxi^-y^130"
3074         print_lines_basic "1" "-z" "Security filters for IP/Mac addresses, location, user home directory name. Default on for irc clients."
3075         print_lines_basic "1" "-Z" "Absolute override for output filters. Useful for debugging networking issues in irc for example."
3076         print_screen_output " "
3077         print_screen_output "Additional Options:"
3078         print_lines_basic "4" "-h --help" "This help menu."
3079         print_lines_basic "4" "-H" "This help menu, plus developer options. Do not use dev options in normal operation!"
3080         print_lines_basic "4" "--recommends" "Checks $SCRIPT_NAME application dependencies + recommends, and directories, then shows what package(s) you need to install to add support for that feature. "
3081         if [[ $B_ALLOW_UPDATE == 'true' ]];then
3082                 print_lines_basic "4" "-U" "Auto-update script. Will also install/update man page. Note: if you installed as root, you must be root to update, otherwise user is fine. Man page installs require root user mode."
3083         fi
3084         print_lines_basic "4" "-V --version" "$SCRIPT_NAME version information. Prints information then exits."
3085         print_screen_output " "
3086         print_screen_output "Debugging Options:"
3087         print_lines_basic "1" "-%" "Overrides defective or corrupted data."
3088         print_lines_basic "1" "-@" "Triggers debugger output. Requires debugging level 1-14 (8-10 - logging of data). Less than 8 just triggers $SCRIPT_NAME debugger output on screen."
3089         print_lines_basic "2" "1-7" "On screen debugger output"
3090         print_lines_basic "2" "8" "Basic logging"
3091         print_lines_basic "2" "9" "Full file/sys info logging"
3092         print_lines_basic "2" "10" "Color logging."
3093         print_lines_basic "1" "" "The following create a tar.gz file of system data, plus collecting the inxi output to file. To automatically upload debugger data tar.gz file to ftp.techpatterns.com: inxi^-xx@^<11-14>"
3094         print_lines_basic "1" "" "For alternate ftp upload locations: Example:^inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
3095         print_lines_basic "2" "11" "With data file of xiin read of /sys."
3096         print_lines_basic "2" "12" "With xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc."
3097         print_lines_basic "2" "13" "With data from dev, disks, ${partition_string}s, etc., plus xiin data file."
3098         print_lines_basic "2" "14" "Everything, full data collection."
3099         print_screen_output " "
3100         print_screen_output "Advanced Options:"
3101         print_lines_basic "1" "-! 31" "Turns off hostname in output. Useful if showing output from servers etc."
3102         print_lines_basic "1" "-! 32" "Turns on hostname in output. Overrides global B_SHOW_HOST='false'"
3103         print_lines_basic "1" "-! 33" "Forces use of dmidecode data instead of /sys where relevant (-M)."
3104         
3105         if [[ $1 == 'full' ]];then
3106                 print_screen_output " "
3107                 print_screen_output "Developer and Testing Options (Advanced):"
3108                 print_lines_basic "1" "-! 1" "Sets testing flag B_TESTING_1='true' to trigger testing condition 1."
3109                 print_lines_basic "1" "-! 2" "Sets testing flag B_TESTING_2='true' to trigger testing condition 2."
3110                 print_lines_basic "1" "-! 3" "Sets flags B_TESTING_1='true' and B_TESTING_2='true'."
3111                 if [[ $B_ALLOW_UPDATE == 'true' ]];then
3112                         print_lines_basic "1" "-! 10" "Triggers an update from the primary dev download server instead of svn."
3113                         print_lines_basic "1" "-! 11" "Triggers an update from svn branch one - if present, of course."
3114                         print_lines_basic "1" "-! 12" "Triggers an update from svn branch two - if present, of course."
3115                         print_lines_basic "1" "-! 13" "Triggers an update from svn branch three - if present, of course."
3116                         print_lines_basic "1" "-! 14" "Triggers an update from svn branch four - if present, of course."
3117                         print_lines_basic "1" "-! 15" "Triggers an update from svn branch BSD - if present, of course."
3118                         print_lines_basic "1" "-! 16" "Triggers an update from svn branch GNUBSD - if present, of course."
3119                         print_lines_basic "1" "-! " "<http://......> Triggers an update from whatever server you list."
3120                         print_lines_basic "1" "" "Example: inxi^-!^http://yourserver.com/testing/inxi"
3121                 fi
3122                 print_lines_basic "1" "-! " "<ftp.......> Changes debugging data ftp upload location to whatever you enter here. Only used together with -xx@^11-14, and must be used in front of that."
3123                 print_lines_basic "1" "" "Example: inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
3124         fi
3125         print_screen_output " "
3126 }
3127
3128 # uses $TERM_COLUMNS to set width using $COLS_MAX as max width
3129 # IMPORTANT: minimize use of subshells here or the output is too slow
3130 # IMPORTANT: each text chunk must be a continuous line, no line breaks. For anyone who uses a 
3131 # code editor that can't do visual (not hard coded) line wrapping, upgrade to one that can.
3132 # args: $1 - 0 1 2 3 4 for indentation level; $2 -line starter, like -m; $3 - content of block.
3133 print_lines_basic()
3134 {
3135         local line_width=$COLS_MAX
3136         local print_string='' indent_inner='' indent_full='' indent_x='' 
3137         local indent_working='' indent_working_full=''
3138         local line_starter='' line_1_starter='' line_x_starter='' 
3139         # note: to create a padded string below
3140         local fake_string=' ' temp_count='' line_count='' spacer=''
3141         local indent_main=6 indent_x='' b_indent_x='true' 
3142         
3143         case $1 in
3144                 # for no options, start at left edge
3145                 0)      indent_full=0
3146                         line_1_starter=''
3147                         line_x_starter=''
3148                         b_indent_x='false'
3149                         ;;
3150                 1)      indent_full=$indent_main
3151                         temp_count=${#2}
3152                         if [[ $temp_count -le $indent_full ]];then
3153                                 indent_working=$indent_full
3154                         else
3155                                 indent_working=$temp_count #$(( $temp_count + 1 ))
3156                         fi
3157                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
3158                         ;;
3159                 # first left pad 2 and 3, then right pad them
3160                 2)      indent_full=$(( $indent_main + 6 ))
3161                         indent_inner=3
3162                         temp_count=${#2}
3163                         if [[ $temp_count -le $indent_inner ]];then
3164                                 indent_working=$indent_inner
3165                                 #indent_working_full=$indent_full
3166                         else
3167                                 indent_working=$(( $temp_count + 1 ))
3168                                 #indent_working_full=$(( $indent_full - $indent_inner - 1 ))
3169                         fi
3170                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
3171                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
3172                         ;;
3173                 3)      indent_full=$(( $indent_main + 8 ))
3174                         indent_inner=3
3175                         temp_count=${#2}
3176                         if [[ $temp_count -le $indent_inner ]];then
3177                                 indent_working=$indent_inner
3178                         else
3179                                 indent_working=$(( $temp_count + 1 ))
3180                         fi
3181                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
3182                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
3183                         ;;
3184                 # for long options
3185                 4)      indent_full=$(( $indent_main + 8 ))
3186                         temp_count=${#2}
3187                         if [[ $temp_count -lt $indent_full ]];then
3188                                 indent_working=$indent_full
3189                         else
3190                                 indent_working=$temp_count #$(( $temp_count + 1 ))
3191                         fi
3192                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
3193                         ;;
3194         esac
3195         
3196         if [[ $b_indent_x == 'true' ]];then
3197                 indent_x=$(( $indent_full + 1 ))
3198                 line_x_starter="$(printf "%${indent_x}s" '')"
3199         fi
3200         
3201         line_count=$(( $line_width - $indent_full ))
3202         
3203         # bash loop is slow, only run this if required
3204         if [[ ${#3} -gt $line_count ]];then
3205                 for word in $3
3206                 do
3207                         temp_string="$print_string$spacer$word"
3208                         spacer=' '
3209                         if [[ ${#temp_string} -lt $line_count ]];then
3210                                 print_string=$temp_string # lose any white space start/end
3211                                 # echo -n $(( $line_width - $indent_full ))
3212                         else
3213                                 if [[ -n $line_1_starter ]];then
3214                                         line_starter="$line_1_starter"
3215                                         line_1_starter=''
3216                                 else
3217                                         line_starter="$line_x_starter"
3218                                 fi
3219                                 # clean up forced connections, ie, stuff we don't want wrapping
3220                                 print_string=${print_string//\^/ }
3221                                 print_screen_output "$line_starter$print_string"
3222                                 print_string="$word$spacer" # needed to handle second word on new line
3223                                 temp_string=''
3224                                 spacer=''
3225                         fi
3226                 done
3227         else
3228                 # echo no loop
3229                 print_string=$3
3230         fi
3231         # print anything left over
3232         if [[ -n $print_string ]];then
3233                 if [[ -n $line_1_starter ]];then
3234                         line_starter="$line_1_starter"
3235                         line_1_starter=''
3236                 else
3237                         line_starter="$line_x_starter"
3238                 fi
3239                 print_string=${print_string//\^/ }
3240                 print_screen_output "$line_starter$print_string"
3241         fi
3242 }
3243 # print_lines_basic '1' '-m' 'let us teest this string and lots more and stuff and more stuff and x is wy and z is x and fred is dead and gus is alive an yes we have to go now'
3244 # print_lines_basic '2' '7' 'and its substring this string and lots more and stuff and more stuff and x is wy and z is x and fred is dead and gus is alive an yes we have to go now'
3245 # print_lines_basic '2' '12' 'and its sss substring'
3246 # print_lines_basic '3' '12' 'and its sss substring this string and lots more and stuff and more stuff and x is wy and z is x and fred is dead and gus is alive an yes we have to go now'
3247 # exit
3248
3249 ## print out version information for -V/--version
3250 print_version_info()
3251 {
3252         # if not in PATH could be either . or directory name, no slash starting
3253         local script_path=$SCRIPT_PATH script_symbolic_start=''
3254         if [[ $script_path == '.' ]];then
3255                 script_path=$( pwd )
3256         elif [[ -z $( grep '^/' <<< "$script_path" ) ]];then
3257                 script_path="$( pwd )/$script_path"
3258         fi
3259         # handle if it's a symbolic link, rare, but can happen with script directories in irc clients
3260         # which would only matter if user starts inxi with -! 30 override in irc client
3261         if [[ -L $script_path/$SCRIPT_NAME ]];then
3262                 script_symbolic_start=$script_path/$SCRIPT_NAME
3263                 script_path=$( readlink $script_path/$SCRIPT_NAME )
3264                 script_path=$( dirname $script_path )
3265         fi
3266         local last_modified=$( parse_version_data 'date' ) 
3267         local year_modified=$( gawk '{print $NF}' <<< "$last_modified" )
3268         
3269         print_screen_output "$SCRIPT_NAME $SCRIPT_VERSION_NUMBER-$SCRIPT_PATCH_NUMBER ($last_modified)"
3270         if [[ $B_IRC == 'false' ]];then
3271                 print_screen_output "Program Location: $script_path"
3272                 if [[ -n $script_symbolic_start ]];then
3273                         print_screen_output "Started via symbolic link: $script_symbolic_start"
3274                 fi
3275                 print_lines_basic "0" "" "Website:^https://github.com/smxi/inxi^or^http://smxi.org/"
3276                 print_lines_basic "0" "" "IRC:^irc.oftc.net channel:^#smxi"
3277                 print_lines_basic "0" "" "Forums:^http://techpatterns.com/forums/forum-33.html"
3278                 print_screen_output " "
3279                 print_lines_basic "0" "" "$SCRIPT_NAME - the universal, portable, system information tool for console and irc."
3280                 print_screen_output " "
3281                 print_lines_basic "0" "" "This program started life as a fork of Infobash 3.02: Copyright^(C)^2005-2007^Michiel^de^Boer^a.k.a.^locsmif."
3282                 print_lines_basic "0" "" "Subsequent changes and modifications (after Infobash 3.02): Copyright^(C)^2008-${year_modified%%-*}^Harald^Hope,^Scott^Rogers,^aka^h2^&trash80."
3283                 print_screen_output " "
3284                 print_lines_basic "0" "" "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. (http://www.gnu.org/licenses/gpl.html)"
3285         fi
3286 }
3287
3288 ########################################################################
3289 #### MAIN FUNCTIONS
3290 ########################################################################
3291
3292 #### -------------------------------------------------------------------
3293 #### initial startup stuff
3294 #### -------------------------------------------------------------------
3295
3296 # Determine where inxi was run from, set IRC_CLIENT and IRC_CLIENT_VERSION
3297 get_start_client()
3298 {
3299         eval $LOGFS
3300         local Irc_Client_Path='' irc_client_path_lower='' non_native_konvi='' i=''
3301         local B_Non_Native_App='false' pppid='' App_Working_Name=''
3302         local b_qt4_konvi='false' ps_parent=''
3303
3304         if [[ $B_IRC == 'false' ]];then
3305                 IRC_CLIENT='Shell'
3306                 unset IRC_CLIENT_VERSION
3307         # elif [[ -n $PPID ]];then
3308         elif [[ -n $PPID && -f /proc/$PPID/exe ]];then
3309                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
3310                         B_OUTPUT_FILTER='true'
3311                 fi
3312                 Irc_Client_Path=$( readlink /proc/$PPID/exe )
3313                 # Irc_Client_Path=$( ps -p $PPID | gawk '!/[[:space:]]*PID/ {print $5}'  )
3314                 # echo $( ps -p $PPID )
3315                 irc_client_path_lower=$( tr '[A-Z]' '[a-z]' <<< $Irc_Client_Path )
3316                 App_Working_Name=${irc_client_path_lower##*/}
3317                 # handles the xchat/sh/bash/dash cases, and the konversation/perl cases, where clients
3318                 # report themselves as perl or unknown shell. IE:  when konversation starts inxi
3319                 # from inside itself, as a script, the parent is konversation/xchat, not perl/bash etc
3320                 # note: perl can report as: perl5.10.0, so it needs wildcard handling
3321                 case $App_Working_Name in
3322                         # bsd will never use this section
3323                         bash|dash|sh|python*|perl*)     # We want to know who wrapped it into the shell or perl.
3324                                 if [[ $BSD_TYPE != 'bsd' ]];then
3325                                         pppid=$( ps -p $PPID -o ppid --no-headers 2>/dev/null | gawk '{print $NF}' )
3326                                 else
3327                                         # without --no-headers we need the second line
3328                                         pppid=$( ps -p $PPID -o ppid 2>/dev/null | gawk '$1 ~ /^[0-9]+/ {print $5}' )
3329                                 fi
3330                                 if [[ -n $pppid && -f /proc/$pppid/exe ]];then
3331                                         Irc_Client_Path="$( readlink /proc/$pppid/exe )"
3332                                         irc_client_path_lower=$( tr '[A-Z]' '[a-z]' <<< $Irc_Client_Path )
3333                                         App_Working_Name=${irc_client_path_lower##*/}
3334                                         B_Non_Native_App='true'
3335                                 fi
3336                                 ;;
3337                 esac
3338                 # sets version number if it can find it
3339                 get_irc_client_version
3340         else
3341                 ## lets look to see if qt4_konvi is the parent.  There is no direct way to tell, so lets infer it.
3342                 ## because $PPID does not work with qt4_konvi, the above case does not work
3343                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
3344                         B_OUTPUT_FILTER='true'
3345                 fi
3346                 b_qt4_konvi=$( is_this_qt4_konvi )
3347                 if [[ $b_qt4_konvi == 'true' ]];then
3348                         KONVI=3
3349                         IRC_CLIENT='Konversation'
3350                         IRC_CLIENT_VERSION=" $( konversation -v | gawk '
3351                                 /Konversation:/ {
3352                                         for ( i=2; i<=NF; i++ ) {
3353                                                 if (i == NF) {
3354                                                         print $i
3355                                                 }
3356                                                 else {
3357                                                         printf $i" "
3358                                                 }
3359                                         }
3360                                         exit
3361                                 }' )"
3362                 else
3363                         # this should handle certain cases where it's ssh or some other startup tool
3364                         # that falls through all the other tests. Also bsd irc clients will land here
3365                         if [[ $BSD_TYPE != 'bsd' ]];then
3366                                 App_Working_Name=$(ps -p $PPID --no-headers 2>/dev/null | gawk '{print $NF}' )
3367                         else
3368                                 # without --no-headers we need the second line
3369                                 App_Working_Name=$(ps -p $PPID 2>/dev/null | gawk '$1 ~ /^[0-9]+/ {print $5}' )
3370                         fi
3371                         
3372                         if [[ -n $App_Working_Name ]];then
3373                                 Irc_Client_Path=$App_Working_Name
3374                                 irc_client_path_lower=$( tr '[A-Z]' '[a-z]' <<< $Irc_Client_Path )
3375                                 App_Working_Name=${irc_client_path_lower##*/}
3376                                 B_Non_Native_App='false'
3377                                 get_irc_client_version
3378                                 if [[ -z $IRC_CLIENT ]];then
3379                                         IRC_CLIENT=$App_Working_Name
3380                                 fi
3381                         else
3382                                 IRC_CLIENT="PPID=\"$PPID\" - empty?"
3383                                 unset IRC_CLIENT_VERSION
3384                         fi
3385                 fi
3386         fi
3387
3388         log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID"
3389         eval $LOGFE
3390 }
3391 # note: all variables set in caller so no need to pass
3392 get_irc_client_version()
3393 {
3394         local file_data=''
3395         # replacing loose detection with tight detection, bugs will be handled with app names
3396         # as they appear.
3397         case $App_Working_Name in
3398                 # check for shell first
3399                 bash|dash|sh)
3400                         unset IRC_CLIENT_VERSION
3401                         IRC_CLIENT="Shell wrapper"
3402                         ;;
3403                 # now start on irc clients, alphabetically
3404                 bitchx)
3405                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
3406                         /Version/ {
3407                                 a=tolower($2)
3408                                 gsub(/[()]|bitchx-/,"",a)
3409                                 print a
3410                                 exit
3411                         }
3412                         $2 == "version" {
3413                                 a=tolower($3)
3414                                 sub(/bitchx-/,"",a)
3415                                 print a
3416                                 exit
3417                         }' )"
3418                         B_CONSOLE_IRC='true'
3419                         IRC_CLIENT="BitchX"
3420                         ;;
3421                 finch)
3422                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3423                                 print $2
3424                         }' )"
3425                         B_CONSOLE_IRC='true'
3426                         IRC_CLIENT="Finch"
3427                         ;;
3428                 gaim)
3429                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3430                                 print $2
3431                         }' )"
3432                         IRC_CLIENT="Gaim"
3433                         ;;
3434                 hexchat)
3435                         # the hexchat author decided to make --version/-v return a gtk dialogue box, lol...
3436                         # so we need to read the actual config file for hexchat. Note that older hexchats
3437                         # used xchat config file, so test first for default, then legacy. Because it's possible
3438                         # for this file to be use edited, doing some extra checks here.
3439                         if [[ -f ~/.config/hexchat/hexchat.conf ]];then
3440                                 file_data="$( cat ~/.config/hexchat/hexchat.conf )"
3441                         elif [[ -f  ~/.config/hexchat/xchat.conf ]];then
3442                                 file_data="$( cat ~/.config/hexchat/xchat.conf )"
3443                         fi
3444                         if [[ -n $file_data ]];then
3445                                 IRC_CLIENT_VERSION=$( gawk '
3446                                 BEGIN {
3447                                         IGNORECASE=1
3448                                         FS="="
3449                                 }
3450                                 /^[[:space:]]*version/ {
3451                                         # get rid of the space if present
3452                                         gsub(/[[:space:]]*/, "", $2 )
3453                                         print $2
3454                                         exit # usually this is the first line, no point in continuing
3455                                 }' <<< "$file_data" )
3456                                 
3457                                 IRC_CLIENT_VERSION=" $IRC_CLIENT_VERSION"
3458                         else
3459                                 IRC_CLIENT_VERSION=' N/A'
3460                         fi
3461                         IRC_CLIENT="HexChat"
3462                         ;;
3463                 ircii)
3464                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3465                                 print $3
3466                         }' )"
3467                         B_CONSOLE_IRC='true'
3468                         IRC_CLIENT="ircII"
3469                         ;;
3470                 irssi|irssi-text)
3471                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3472                                 print $2
3473                         }' )"
3474                         B_CONSOLE_IRC='true'
3475                         IRC_CLIENT="Irssi"
3476                         ;;
3477                 konversation) ## konvi < 1.2 (qt4)
3478                         # this is necessary to avoid the dcop errors from starting inxi as a /cmd started script
3479                         if [[ $B_Non_Native_App == 'true' ]];then  ## true negative is confusing
3480                                 KONVI=2
3481                         else # if native app
3482                                 KONVI=1
3483                         fi
3484                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
3485                         /Konversation:/ {
3486                                 for ( i=2; i<=NF; i++ ) {
3487                                         if (i == NF) {
3488                                                 print $i
3489                                         }
3490                                         else {
3491                                                 printf $i" "
3492                                         }
3493                                 }
3494                                 exit
3495                         }' )"
3496                         T=($IRC_CLIENT_VERSION)
3497                         if [[ ${T[0]} == *+* ]];then
3498                                 # < Sho_> locsmif: The version numbers of SVN versions look like this:
3499                                 #         "<version number of last release>+ #<build number", i.e. "1.0+ #3177" ...
3500                                 #         for releases we remove the + and build number, i.e. "1.0" or soon "1.0.1"
3501                                 IRC_CLIENT_VERSION=" CVS $IRC_CLIENT_VERSION"
3502                                 T2="${T[0]/+/}"
3503                         else
3504                                 IRC_CLIENT_VERSION=" ${T[0]}"
3505                                 T2="${T[0]}"
3506                         fi
3507                         # Remove any dots except the first, and make sure there are no trailing zeroes,
3508                         T2=$( echo "$T2" | gawk '{
3509                                 sub(/\./, " ")
3510                                 gsub(/\./, "")
3511                                 sub(/ /, ".")
3512                                 printf("%g\n", $0)
3513                         }' )
3514                         # Since Konversation 1.0, the DCOP interface has changed a bit: dcop "$DCPORT" Konversation ..etc
3515                         # becomes : dcop "$DCPORT" default ... or dcop "$DCPORT" irc ..etc. So we check for versions smaller
3516                         # than 1 and change the DCOP parameter/object accordingly.
3517                         if [[ $T2 -lt 1 ]];then
3518                                 DCOPOBJ="Konversation"
3519                         fi
3520                         IRC_CLIENT="Konversation"
3521                         ;;
3522                 kopete)
3523                         IRC_CLIENT_VERSION=" $( kopete -v | gawk '
3524                         /Kopete:/ {
3525                                 print $2
3526                                 exit
3527                         }' )"
3528                         IRC_CLIENT="Kopete"
3529                         ;;
3530                 kvirc)
3531                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>&1 | gawk '{
3532                                 for ( i=2; i<=NF; i++) {
3533                                         if ( i == NF ) {
3534                                                 print $i
3535                                         }
3536                                         else {
3537                                                 printf $i" "
3538                                         }
3539                                 }
3540                                 exit
3541                                 }' )"
3542                         IRC_CLIENT="KVIrc"
3543                         ;;
3544                 pidgin)
3545                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3546                                 print $2
3547                         }' )"
3548                         IRC_CLIENT="Pidgin"
3549                         ;;
3550                 # possible failure of wildcard so make it explicit
3551                 quassel*)
3552                         # sample: quassel -v
3553                         ## Qt: 4.5.0 - in Qt4 the output came from src/common/quassel.cpp
3554                         # KDE: 4.2.65 (KDE 4.2.65 (KDE 4.3 >= 20090226))
3555                         # Quassel IRC: v0.4.0 [+60] (git-22effe5)
3556                         # note: early < 0.4.1 quassels do not have -v
3557                         ## Qt: 5: sample: quassel -v
3558                         # quassel v0.13-pre (0.12.0+5 git-8e2f578)
3559                         # because in Qt5 the internal CommandLineParser is used 
3560                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>/dev/null | gawk '
3561                         BEGIN {
3562                                 IGNORECASE=1
3563                                 clientVersion=""
3564                         }
3565                         # qt 4 -v syntax
3566                         /^Quassel IRC:/ {
3567                                 clientVersion = $3
3568                         }
3569                         # qt 5 -v syntax
3570                         /^quassel\s[v]?[0-9]/ {
3571                                 clientVersion = $2
3572                         }
3573                         END {
3574                                 # this handles pre 0.4.1 cases with no -v
3575                                 if ( clientVersion == "" ) {
3576                                         clientVersion = "(pre v0.4.1)?"
3577                                 }
3578                                 print clientVersion
3579                         }' )"
3580                         # now handle primary, client, and core. quasselcore doesn't actually
3581                         # handle scripts with exec, but it's here just to be complete
3582                         case $App_Working_Name in
3583                                 quassel)
3584                                         IRC_CLIENT="Quassel [M]"
3585                                         ;;
3586                                 quasselclient)
3587                                         IRC_CLIENT="Quassel"
3588                                         ;;
3589                                 quasselcore)
3590                                         IRC_CLIENT="Quassel (core)"
3591                                         ;;
3592                         esac
3593                         ;;
3594                 gribble|limnoria|supybot)
3595                         IRC_CLIENT_VERSION=" $( get_program_version 'supybot' '^Supybot' '2' )"
3596                         if [[ -n $IRC_CLIENT_VERSION ]];then
3597                                 if [[ -n ${IRC_CLIENT_VERSION/*gribble*/} || $App_Working_Name == 'gribble' ]];then
3598                                         IRC_CLIENT="Gribble"
3599                                 elif [[ -n ${IRC_CLIENT_VERSION/*limnoria*/} || $App_Working_Name == 'limnoria' ]];then
3600                                         IRC_CLIENT="Limnoria"
3601                                 else
3602                                         IRC_CLIENT="Supybot"
3603                                 fi
3604                         fi
3605                         ;;
3606                 weechat|weechat-curses)
3607                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v ) "
3608                         B_CONSOLE_IRC='true'
3609                         IRC_CLIENT="WeeChat"
3610                         ;;
3611                 xchat-gnome)
3612                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3613                                 print $2
3614                         }' )"
3615                         IRC_CLIENT="X-Chat-Gnome"
3616                         ;;
3617                 xchat)
3618                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3619                                 print $2
3620                         }' )"
3621                         IRC_CLIENT="X-Chat"
3622                         ;;
3623                 # then do some perl type searches, do this last since it's a wildcard search
3624                 perl*|ksirc|dsirc)
3625                         unset IRC_CLIENT_VERSION
3626                         # KSirc is one of the possibilities now. KSirc is a wrapper around dsirc, a perl client
3627                         get_cmdline $PPID
3628                         for (( i=0; i <= $CMDL_MAX; i++ ))
3629                         do
3630                                 case ${A_CMDL[i]} in
3631                                         *dsirc*)
3632                                         IRC_CLIENT="KSirc"
3633                                         # Dynamic runpath detection is too complex with KSirc, because KSirc is started from
3634                                         # kdeinit. /proc/<pid of the grandparent of this process>/exe is a link to /usr/bin/kdeinit
3635                                         # with one parameter which contains parameters separated by spaces(??), first param being KSirc.
3636                                         # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed,
3637                                         # dsirc is the program that runs inxi, therefore that is the parent process that we see.
3638                                         # You can imagine how hosed I am if I try to make inxi find out dynamically with which path
3639                                         # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material.
3640                                         # (KSirc sucks anyway ;)
3641                                         IRC_CLIENT_VERSION=" $( ksirc -v | gawk '
3642                                         /KSirc:/ {
3643                                                 print $2
3644                                                 exit
3645                                         }' )"
3646                                         break
3647                                         ;;
3648                                 esac
3649                         done
3650                         B_CONSOLE_IRC='true'
3651                         set_perl_python_client_data "$App_Working_Name"
3652                         ;;
3653                 python*)
3654                         # B_CONSOLE_IRC='true' # are there even any python type console irc clients? check.
3655                         set_perl_python_client_data "$App_Working_Name"
3656                         ;;
3657                 # then unset, set unknown data
3658                 *)      
3659                         IRC_CLIENT="Unknown : ${Irc_Client_Path##*/}"
3660                         unset IRC_CLIENT_VERSION
3661                         ;;
3662         esac
3663         if [[ $SHOW_IRC -lt 2 ]];then
3664                 unset IRC_CLIENT_VERSION
3665         fi
3666 }
3667
3668 # args: $1 - App_Working_Name
3669 set_perl_python_client_data()
3670 {
3671         if [[ -z $IRC_CLIENT_VERSION ]];then
3672                 local version=''
3673                 # this is a hack to try to show konversation if inxi is running but started via /cmd
3674                 # OR via script shortcuts, both cases in fact now
3675                 if [[  $B_RUNNING_IN_DISPLAY == 'true' && -z ${Ps_aux_Data/*konversation*/} ]];then
3676                         IRC_CLIENT='Konversation'
3677                         version=$( get_program_version 'konversation' '^konversation' '2' )
3678                         B_CONSOLE_IRC='false'
3679                 ## NOTE: supybot only appears in ps aux using 'SHELL' command; the 'CALL' command
3680                 ## gives the user system irc priority, and you don't see supybot listed, so use SHELL
3681                 elif [[ $B_RUNNING_IN_DISPLAY == 'false' && -z ${Ps_aux_Data/*supybot*/} ]];then
3682                         version=$( get_program_version 'supybot' '^Supybot' '2' )
3683                         if [[ -n $version ]];then
3684                                 IRC_CLIENT_VERSION=" $version"
3685                                 if [[ -z ${version/*gribble*/} ]];then
3686                                         IRC_CLIENT='Gribble'
3687                                 elif [[ -z ${version/*limnoria*/} ]];then
3688                                         IRC_CLIENT='Limnoria'
3689                                 else
3690                                         IRC_CLIENT='Supybot'
3691                                 fi
3692                         else
3693                                 IRC_CLIENT='Supybot'
3694                         # currently all use the same actual app name, this will probably change.
3695                         fi
3696                         B_CONSOLE_IRC='true'
3697                 else
3698                         IRC_CLIENT="Unknown $1 client"
3699                 fi
3700                 if [[ -n $version ]];then
3701                         IRC_CLIENT_VERSION=" $version"
3702                 fi
3703         fi
3704 }
3705
3706 ## try to infer the use of Konversation >= 1.2, which shows $PPID improperly
3707 ## no known method of finding Kovni >= 1.2 as parent process, so we look to see if it is running,
3708 ## and all other irc clients are not running. As of 2014-03-25 this isn't used in my cases
3709 is_this_qt4_konvi()
3710 {
3711         local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir='' 
3712         local konvi='' b_is_qt4=''
3713         
3714         # fringe cases can throw error, always if untested app, use 2>/dev/null after testing if present
3715         if [[ $B_QDBUS == 'true' ]];then
3716                 konvi_dbus_exist=$( qdbus 2>/dev/null | grep "org.kde.konversation" )
3717         fi
3718         # sabayon uses /usr/share/apps/konversation as path
3719         if [[ -n $konvi_dbus_exist ]] && [[ -e /usr/share/kde4/apps/konversation || -e  /usr/share/apps/konversation ]]; then
3720                 konvi_pid=$( ps -A | gawk 'BEGIN{IGNORECASE=1} /konversation/ { print $1 }' ) 
3721                 konvi_home_dir=$( readlink /proc/$konvi_pid/exe )
3722                 konvi=$( echo $konvi_home_dir | sed "s/\// /g" )
3723                 konvi=($konvi)
3724
3725                 if [[ ${konvi[2]} == 'konversation' ]];then
3726                         # note: we need to change this back to a single dot number, like 1.3, not 1.3.2
3727                         konvi_qt4_client=$( konversation -v | grep -i 'konversation' | \
3728                         gawk '{ print $2 }' | cut -d '.' -f 1,2 )
3729                         if [[ $konvi_qt4_client > 1.1 ]]; then
3730                                 b_is_qt4='true'
3731                         fi
3732                 fi
3733         else
3734                 konvi_qt4="qt3"
3735                 b_is_qt4='false'
3736         fi
3737         log_function_data "b_is_qt4: $b_is_qt4"
3738         echo $b_is_qt4
3739         ## for testing this module
3740         #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]}"
3741 }
3742
3743 # This needs some cleanup and comments, not quite understanding what is happening, although generally output is known
3744 # Parse the null separated commandline under /proc/<pid passed in $1>/cmdline
3745 # args: $1 - $PPID
3746 get_cmdline()
3747 {
3748         eval $LOGFS
3749         local i=0 ppid=$1
3750
3751         if [[ ! -e /proc/$ppid/cmdline ]];then
3752                 echo 0
3753                 return
3754         fi
3755         ##print_screen_output "Marker"
3756         ##print_screen_output "\$ppid='$ppid' -=- $(< /proc/$ppid/cmdline)"
3757         unset A_CMDL
3758         ## note: need to figure this one out, and ideally clean it up and make it readable
3759         while read -d $'\0' L && [[ $i -lt 32 ]]
3760         do
3761                 A_CMDL[i++]="$L" ## note: make sure this is valid - What does L mean? ##
3762         done < /proc/$ppid/cmdline
3763         ##print_screen_output "\$i='$i'"
3764         if [[ $i -eq 0 ]];then
3765                 A_CMDL[0]=$(< /proc/$ppid/cmdline)
3766                 if [[ -n ${A_CMDL[0]} ]];then
3767                         i=1
3768                 fi
3769         fi
3770         CMDL_MAX=$i
3771         log_function_data "CMDL_MAX: $CMDL_MAX"
3772         eval $LOGFE
3773 }
3774
3775 #### -------------------------------------------------------------------
3776 #### get data types
3777 #### -------------------------------------------------------------------
3778 ## create array of sound cards installed on system, and if found, use asound data as well
3779 get_audio_data()
3780 {
3781         eval $LOGFS
3782         local i='' alsa_data='' audio_driver='' device_count='' a_temp=''
3783
3784         IFS=$'\n'
3785         # this first step handles the drivers for cases where the second step fails to find one
3786         device_count=$( echo "$Lspci_v_Data" | grep -iEc '(multimedia audio controller|audio device)' )
3787         if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
3788                 audio_driver=$( gawk -F ']: ' '
3789                 BEGIN {
3790                         IGNORECASE=1
3791                 }
3792                 # filtering out modems and usb devices like webcams, this might get a
3793                 # usb audio card as well, this will take some trial and error
3794                 $0 !~ /modem|usb|webcam/ {
3795                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
3796                         gsub(/^ +| +$/,"",driver)
3797                         if ( driver != "" ){
3798                                 print driver
3799                         }
3800                 }' $FILE_ASOUND_DEVICE ) 
3801                 log_function_data 'cat' "$FILE_ASOUND_DEVICE"
3802         fi
3803
3804         # this is to safeguard against line breaks from results > 1, which if inserted into following
3805         # array will create a false array entry. This is a hack, not a permanent solution.
3806         audio_driver=$( echo $audio_driver )
3807         # now we'll build the main audio data, card name, driver, and port. If no driver is found,
3808         # and if the first method above is not null, and one card is found, it will use that instead.
3809         A_AUDIO_DATA=( $( echo "$Lspci_v_Data" | gawk -F ': ' -v audioDriver="$audio_driver" '
3810         BEGIN {
3811                 IGNORECASE=1
3812         }
3813         /multimedia audio controller|audio device/ {
3814                 audioCard=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
3815                 # The doublequotes are necessary because of the pipes in the variable.
3816                 gsub(/'"$BAN_LIST_NORMAL"'/, "", audioCard)
3817                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", audioCard)
3818                 gsub(/^ +| +$/, "", audioCard)
3819                 gsub(/ [ \t]+/, " ", audioCard)
3820                 aPciBusId[audioCard] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
3821                 cards[audioCard]++
3822
3823                 # loop until you get to the end of the data block
3824                 while (getline && !/^$/) {
3825                         gsub(/'"$BAN_LIST_ARRAY"'/, "", $0 )
3826                         if (/driver in use/) {
3827                                 drivers[audioCard] = drivers[audioCard] gensub( /(.*): (.*)/ ,"\\2", "g" ,$0 ) ""
3828                         }
3829                         else if (/kernel modules:/) {
3830                                 modules[audioCard] = modules[audioCard] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
3831                         }
3832                         else if (/^[[:space:]]*I\/O/) {
3833                                 portsTemp = gensub(/\t*I\/O ports at ([a-z0-9]+)(| \[.*\])/,"\\1","g",$0)
3834                                 ports[audioCard] = ports[audioCard] portsTemp " "
3835                         }
3836                 }
3837         }
3838
3839         END {
3840                 j=0
3841                 for (i in cards) {
3842                         useDrivers=""
3843                         useModules=""
3844                         usePorts=""
3845                         usePciBusId=""
3846                          
3847                         if (cards[i]>1) {
3848                                 a[j]=cards[i]"x "i
3849                                 if (drivers[i] != "") {
3850                                         useDrivers=drivers[i]
3851                                 }
3852                         }
3853                         else {
3854                                 a[j]=i
3855                                 # little trick here to try to catch the driver if there is
3856                                 # only one card and it was null, from the first test of asound/cards
3857                                 if (drivers[i] != "") {
3858                                         useDrivers=drivers[i]
3859                                 }
3860                                 else if ( audioDriver != "" ) {
3861                                         useDrivers=audioDriver
3862                                 }
3863                         }
3864                         if (ports[i] != "") {
3865                                 usePorts = ports[i]
3866                         }
3867                         if (modules[i] != "" ) {
3868                                 useModules = modules[i]
3869                         }
3870                         if ( aPciBusId[i] != "" ) {
3871                                 usePciBusId = aPciBusId[i]
3872                         }
3873                         # create array primary item for master array
3874                         sub( / $/, "", usePorts ) # clean off trailing whitespace
3875                         print a[j] "," useDrivers "," usePorts "," useModules "," usePciBusId
3876                         j++
3877                 }
3878         }') )
3879
3880         # in case of failure of first check do this instead
3881         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
3882                 A_AUDIO_DATA=( $( gawk -F ']: ' '
3883                 BEGIN {
3884                         IGNORECASE=1
3885                 }
3886                 $1 !~ /modem/ && $2 !~ /modem/ {
3887                         card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 )
3888                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
3889                         if ( card != "" ){
3890                                 print card","driver
3891                         }
3892                 }' $FILE_ASOUND_DEVICE ) )
3893         fi
3894         IFS="$ORIGINAL_IFS"
3895         get_audio_usb_data
3896         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
3897         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]];then
3898                 A_AUDIO_DATA[0]='Failed to Detect Sound Card!'
3899         fi
3900         a_temp=${A_AUDIO_DATA[@]}
3901         log_function_data "A_AUDIO_DATA: $a_temp"
3902
3903         eval $LOGFE
3904 }
3905 # alsa usb detection by damentz
3906
3907 get_audio_usb_data()
3908 {
3909         eval $LOGFS
3910         local usb_proc_file='' array_count='' usb_data='' usb_id='' lsusb_data=''
3911         local a_temp=''
3912         
3913         IFS=$'\n'
3914         if type -p lsusb &>/dev/null;then
3915                 lsusb_data=$( lsusb 2>/dev/null )
3916         fi
3917         log_function_data 'raw' "usb_data:\n$lsusb_data"
3918         if [[ -n $lsusb_data && -d /proc/asound/ ]];then
3919                 # for every sound card symlink in /proc/asound - display information about it
3920                 for usb_proc_file in /proc/asound/*
3921                 do
3922                         # If the file is a symlink, and contains an important usb exclusive file: continue
3923                         if [[ -L $usb_proc_file && -e $usb_proc_file/usbid  ]]; then
3924                                 # find the contents of usbid in lsusb and print everything after the 7th word on the
3925                                 # corresponding line. Finally, strip out commas as they will change the driver :)
3926                                 usb_id=$( cat $usb_proc_file/usbid )
3927                                 usb_data=$( grep "$usb_id" <<< "$lsusb_data" )
3928                                 if [[ -n $usb_data && -n $usb_id ]];then
3929                                         usb_data=$( gawk '
3930                                         BEGIN {
3931                                                 IGNORECASE=1
3932                                                 string=""
3933                                                 separator=""
3934                                         }
3935                                         {
3936                                                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0 )
3937                                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
3938                                                 gsub(/ [ \t]+/, " ", $0)
3939                                                 for ( i=7; i<= NF; i++ ) {
3940                                                         string = string separator $i
3941                                                         separator = " "
3942                                                 }
3943                                                 if ( $2 != "" ){
3944                                                         sub(/:/,"", $4)
3945                                                         print string ",USB Audio,,," $2 "-" $4 "," $6
3946                                                 }
3947                                         }' <<< "$usb_data" )
3948                                 fi
3949                                 # this method is interesting, it shouldn't work but it does
3950                                 #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,USB Audio,," )
3951                                 # but until we learn why the above worked, I'm using this one, which is safer
3952                                 if [[ -n $usb_data ]];then
3953                                         array_count=${#A_AUDIO_DATA[@]}
3954                                         A_AUDIO_DATA[$array_count]="$usb_data"
3955                                 fi
3956                         fi
3957                 done
3958         fi
3959         IFS="$ORIGINAL_IFS"
3960         a_temp=${A_AUDIO_DATA[@]}
3961         log_function_data "A_AUDIO_DATA: $a_temp"
3962         
3963         eval $LOGFE
3964 }
3965
3966 get_audio_alsa_data()
3967 {
3968         eval $LOGFS
3969         local alsa_data='' a_temp=''
3970
3971         # now we'll get the alsa data if the file exists
3972         if [[ $B_ASOUND_VERSION_FILE == 'true' ]];then
3973                 IFS=","
3974                 A_ALSA_DATA=( $( 
3975                 gawk '
3976                         BEGIN {
3977                                 IGNORECASE=1
3978                                 alsa=""
3979                                 version=""
3980                         }
3981                         # some alsa strings have the build date in (...)
3982                         # remove trailing . and remove possible second line if compiled by user
3983                         $0 !~ /compile/ {
3984                                 gsub(/Driver | [(].*[)]|\.$/,"",$0 )
3985                                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
3986                                 gsub(/^ +| +$/, "", $0)
3987                                 gsub(/ [ \t]+/, " ", $0)
3988                                 sub(/Advanced Linux Sound Architecture/, "ALSA", $0)
3989                                 if ( $1 == "ALSA" ){
3990                                         alsa=$1
3991                                 }
3992                                 version=$NF
3993                                 print alsa "," version
3994                         }' $FILE_ASOUND_VERSION ) )
3995                 IFS="$ORIGINAL_IFS"
3996                 log_function_data 'cat' "$FILE_ASOUND_VERSION"
3997         fi
3998         a_temp=${A_ALSA_DATA[@]}
3999         log_function_data "A_ALSA_DATA: $a_temp"
4000         eval $LOGFE
4001 }
4002
4003 get_battery_data()
4004 {
4005         eval $LOGFS
4006         local a_temp='' id_file='' count=0
4007         local id_dir='/sys/class/power_supply/' 
4008         local ids=$( ls $id_dir 2>/dev/null )  battery_file='' 
4009         
4010         # ids='BAT0 BAT1 BAT2'
4011         if [[ -n $ids && $B_FORCE_DMIDECODE == 'false' ]];then
4012                 for idx in $ids
4013                 do
4014                         battery_file=$id_dir$idx'/uevent'
4015                         if [[ -r $battery_file ]];then
4016                                 #  echo $battery_file
4017                                 count=$(( $count + 1 ))
4018                                 IFS=$'\n'
4019                                 battery_data=$( 
4020                                 gawk -F '=' '
4021                                 BEGIN {
4022                                         IGNORECASE=1
4023                                         name=""
4024                                         status=""
4025                                         present=""
4026                                         chemistry=""
4027                                         cycles=""
4028                                         voltage_min_design=""
4029                                         voltage_now=""
4030                                         power_now=""
4031                                         charge_full_design=""
4032                                         charge_full=""
4033                                         charge_now=""
4034                                         capacity=""
4035                                         capacity_level=""
4036                                         model=""
4037                                         company=""
4038                                         serial=""
4039                                         of_orig=""
4040                                         location=""
4041                                 }
4042                                 {
4043                                         gsub(/'"$BAN_LIST_NORMAL"'|,|battery|unknown/, "", $2)
4044                                         gsub(/^ +| +$/, "", $2)
4045                                 }
4046                                 $1 ~ /^POWER_SUPPLY_NAME$/ {
4047                                         name=$NF
4048                                 }
4049                                 $1 ~ /^POWER_SUPPLY_STATUS$/ {
4050                                         status=$NF
4051                                 }
4052                                 $1 ~ /^POWER_SUPPLY$/ {
4053                                         present=$NF
4054                                 }
4055                                 $1 ~ /^POWER_SUPPLY_TECHNOLOGY$/ {
4056                                         chemistry=$NF
4057                                 }
4058                                 $1 ~ /^POWER_SUPPLY_CYCLE_COUNT$/ {
4059                                         cycles=$NF
4060                                 }
4061                                 $1 ~ /^POWER_SUPPLY_VOLTAGE_MIN_DESIGN$/ {
4062                                         voltage_min_design = $NF / 1000000
4063                                         voltage_min_design = sprintf( "%.1f", voltage_min_design )
4064                                 }
4065                                 $1 ~ /^POWER_SUPPLY_VOLTAGE_NOW$/ {
4066                                         voltage_now = $NF / 1000000
4067                                         voltage_now = sprintf( "%.1f", voltage_now )
4068                                 }
4069                                 $1 ~ /^POWER_SUPPLY_POWER_NOW$/ {
4070                                         power_now=$NF
4071                                 }
4072                                 $1 ~ /^POWER_SUPPLY_ENERGY_FULL_DESIGN$/ {
4073                                         charge_full_design = $NF / 1000000
4074                                 }
4075                                 $1 ~ /^POWER_SUPPLY_ENERGY_FULL$/ {
4076                                         charge_full = $NF / 1000000
4077                                 }
4078                                 $1 ~ /^POWER_SUPPLY_ENERGY_NOW$/ {
4079                                         charge_now = $NF / 1000000
4080                                         charge_now = sprintf( "%.1f", charge_now )
4081                                 }
4082                                 $1 ~ /^POWER_SUPPLY_CHARGE_FULL_DESIGN$/ {
4083                                         charge_full_design = $NF / 100000
4084                                 }
4085                                 $1 ~ /^POWER_SUPPLY_CHARGE_FULL$/ {
4086                                         charge_full = $NF / 100000
4087                                 }
4088                                 $1 ~ /^POWER_SUPPLY_CHARGE_NOW$/ {
4089                                         charge_now = $NF / 100000
4090                                 }
4091                                 $1 ~ /^POWER_SUPPLY_CAPACITY$/ {
4092                                         if ( $NF != "" ){
4093                                                 capacity=$NF "%"
4094                                         }
4095                                 }
4096                                 $1 ~ /^POWER_SUPPLY_CAPACITY_LEVEL$/ {
4097                                         capacity_level=$NF
4098                                 }
4099                                 $1 ~ /^POWER_SUPPLY_MODEL_NAME$/ {
4100                                         model=$NF
4101                                 }
4102                                 $1 ~ /^POWER_SUPPLY_MANUFACTURER$/ {
4103                                         company=$NF
4104                                 }
4105                                 $1 ~ /^POWER_SUPPLY_SERIAL_NUMBER$/ {
4106                                         serial=$NF
4107                                 }
4108                                 END {
4109                                         if (charge_now != "" && charge_full != "" ){
4110                                                 capacity = 100*charge_now/charge_full
4111                                                 capacity = sprintf( "%.1f%", capacity )
4112                                         }
4113                                         if (charge_full_design != "" && charge_full != "" ){
4114                                                 of_orig=100*charge_full/charge_full_design
4115                                                 of_orig = sprintf( "%.0f%", of_orig )
4116                                         }
4117                                         if (charge_now != "" ){
4118                                                 charge_now = sprintf( "%.1f", charge_now )
4119                                         }
4120                                         if (charge_full_design != "" ){
4121                                                 charge_full_design = sprintf( "%.1f", charge_full_design )
4122                                         }
4123                                         if ( charge_full != "" ){
4124                                                 charge_full = sprintf( "%.1f", charge_full )
4125                                         }
4126                                         entry = name "," status "," present "," chemistry "," cycles "," voltage_min_design "," voltage_now "," 
4127                                         entry = entry power_now "," charge_full_design "," charge_full "," charge_now "," capacity "," 
4128                                         entry = entry capacity_level "," of_orig "," model "," company "," serial "," location
4129                                         print entry
4130                                 }' < $battery_file )
4131                                 # <<< "$data" )
4132                                 # < $battery_file ) 
4133                                 A_BATTERY_DATA[$count]=$battery_data
4134                                 IFS="$ORIGINAL_IFS"
4135                         fi
4136                 done
4137         elif [[ $B_FORCE_DMIDECODE == 'true'  ]] || [[ ! -d $id_dir && -z $ids ]];then
4138                 get_dmidecode_data
4139                 if [[ -n $DMIDECODE_DATA ]];then
4140                         if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
4141                                 A_BATTERY_DATA[0]=$DMIDECODE_DATA
4142                         # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
4143                         else
4144                                 IFS=$'\n'
4145                                 # NOTE: this logic has a flaw, which is multiple batteries, which won't work without
4146                                 # gawk arrays, but sorry, too much of a pain given how little useful data from dmidecode
4147                                 A_BATTERY_DATA=( $( gawk -F ':' '
4148                                 BEGIN {
4149                                         IGNORECASE=1
4150                                         name=""
4151                                         status=""
4152                                         present=""
4153                                         chemistry=""
4154                                         cycles=""
4155                                         voltage_min_design=""
4156                                         voltage_now=""
4157                                         power_now=""
4158                                         charge_full_design=""
4159                                         charge_full=""
4160                                         charge_now=""
4161                                         capacity=""
4162                                         capacity_level=""
4163                                         model=""
4164                                         company=""
4165                                         serial=""
4166                                         of_orig=""
4167                                         location=""
4168                                         bItemFound="false"
4169                                 }
4170                                 {
4171                                         gsub(/'"$BAN_LIST_NORMAL"'|,|battery|unknown/, "", $2)
4172                                         gsub(/^ +| +$/, "", $1)
4173                                         gsub(/^ +| +$/, "", $2)
4174                                 }
4175                                 /^Portable Battery/ {
4176                                         while ( getline && !/^$/ ) {
4177                                                 if ( $1 ~ /^Location/ ) { location=$2 }
4178                                                 if ( $1 ~ /^Manufacturer/ ) { company=$2 }
4179                                                 if ( $1 ~ /^Serial/ ) { serial=$2 }
4180                                                 if ( $1 ~ /^Name/ ) { model=$2 }
4181                                                 if ( $1 ~ /^Design Capacity/ ) { 
4182                                                         sub(/^[[:space:]]*mwh/, "", $2)
4183                                                         charge_full_design = $NF / 1000
4184                                                         charge_full_design = sprintf( "%.1f", charge_full_design )
4185                                                 }
4186                                                 if ( $1 ~ /^Design Voltage/ ) { 
4187                                                         sub(/^[[:space:]]*mv/, "", $2)
4188                                                         voltage_min_design = $NF / 1000
4189                                                         voltage_min_design = sprintf( "%.1f", voltage_min_design )
4190                                                 }
4191                                                 if ( $1 ~ /^SBDS Chemistry/ ) { chemistry=$2 }
4192                                         }
4193                                         testString=company serial model charge_full_design voltage_min_design
4194                                         if ( testString != ""  ) {
4195                                                 bItemFound="true"
4196                                                 exit # exit loop, we are not handling > 1 batteries
4197                                         }
4198                                 }
4199                                 END {
4200                                         if ( bItemFound == "true" ) {
4201                                                 name="BAT-1"
4202                                                 if (charge_now != "" && charge_full != "" ){
4203                                                         capacity = 100*charge_now/charge_full
4204                                                         capacity = sprintf( "%.1f%", capacity )
4205                                                 }
4206                                                 if (charge_full_design != "" && charge_full != "" ){
4207                                                         of_orig=100*charge_full/charge_full_design
4208                                                         of_orig = sprintf( "%.0f%", of_orig )
4209                                                 }
4210                                                 entry = name "," status "," present "," chemistry "," cycles "," voltage_min_design "," voltage_now "," 
4211                                                 entry = entry power_now "," charge_full_design "," charge_full "," charge_now "," capacity "," 
4212                                                 entry = entry capacity_level "," of_orig "," model "," company "," serial "," location
4213                                                 print entry
4214                                         }
4215                                 }' <<< "$DMIDECODE_DATA" ) )
4216                                 IFS="$ORIGINAL_IFS"
4217                         fi
4218                 fi
4219         fi
4220         # echo $array_string
4221         
4222         #echo ${#A_BATTERY_DATA[@]}
4223         a_temp=${A_BATTERY_DATA[@]}
4224         
4225         # echo $a_temp
4226         log_function_data "A_BATTERY_DATA: $a_temp"
4227         eval $LOGFE
4228 }
4229
4230 ## create A_CPU_CORE_DATA, currently with two values: integer core count; core string text
4231 ## return value cpu core count string, this helps resolve the multi redundant lines of old style output
4232 get_cpu_core_count()
4233 {
4234         eval $LOGFS
4235         local cpu_physical_count='' cpu_core_count='' cpu_type='' cpu_alpha_count='' cores_per_cpu=''
4236         local array_data=''
4237         
4238         if [[ $B_CPUINFO_FILE == 'true' ]]; then
4239                 # load the A_CPU_TYPE_PCNT_CCNT core data array
4240                 get_cpu_ht_multicore_smp_data
4241                 ## Because of the upcoming release of cpus with core counts over 6, a count of cores is given after Deca (10)
4242                 # count the number of processors given
4243                 cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]}
4244                 cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]}
4245                 cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]}
4246
4247                 # match the numberic value to an alpha value
4248                 cpu_alpha_count=$( get_cpu_core_count_alpha "$cpu_core_count" )
4249                 
4250                 # create array, core count integer; core count string
4251                 # A_CPU_CORE_DATA=( "$cpu_core_count" "$cpu_alpha_count Core$cpu_type" )
4252                 array_data="$cpu_physical_count,$cpu_alpha_count,$cpu_type,$cpu_core_count"
4253                 IFS=','
4254                 A_CPU_CORE_DATA=( $array_data )
4255                 IFS="$ORIGINAL_IFS"
4256         elif [[ -n $BSD_TYPE ]];then
4257                 local gawk_fs=': '
4258         
4259                 if [[ $BSD_VERSION == 'openbsd' ]];then
4260                         gawk_fs='='
4261                 fi
4262                 cpu_core_count=$( gawk -F "$gawk_fs" -v bsdVersion="$BSD_VERSION" '
4263                 # note: on openbsd can also be hw.ncpufound so exit after first
4264                 BEGIN {
4265                         coreCount=""
4266                 }
4267                 $1 ~ /^hw.ncpu$/ {
4268                         coreCount=$NF
4269                 }
4270                 /^machdep.cpu.core_count/ {
4271                         coreCount=$NF
4272                 }
4273                 END {
4274                         print coreCount
4275                 }' <<< "$Sysctl_a_Data" )
4276                 cores_per_cpu=$( gawk -F "$gawk_fs" '
4277                 /^machdep.cpu.cores_per_package/ {
4278                         print $NF
4279                 }' <<< "$Sysctl_a_Data" )
4280                 
4281                 if [[ -n $( grep -E '^[0-9]+$' <<< "$cpu_core_count" ) ]];then
4282                         cpu_alpha_count=$( get_cpu_core_count_alpha "$cpu_core_count" )
4283                         if [[ $cpu_core_count -gt 1 ]];then
4284                                 cpu_type='-SMP-'
4285                         else
4286                                 cpu_type='-UP-'
4287                         fi
4288                 fi
4289                 if [[ -n $cores_per_cpu ]];then
4290                         cpu_physical_count=$(( $cpu_core_count / $cores_per_cpu ))
4291                         if [[ $cores_per_cpu -gt 1 ]];then
4292                                 cpu_type='-MCP-'
4293                         fi
4294                 # do not guess here, only use phys count if it actually exists, otherwise handle in print_cpu..
4295                 # this 1 value should not be used for output, and is just to avoid math errors
4296                 else
4297                         cpu_physical_count=1
4298                 fi
4299                 array_data="$cpu_physical_count,$cpu_alpha_count,$cpu_type,$cpu_core_count"
4300                 IFS=','
4301                 A_CPU_CORE_DATA=( $array_data )
4302                 IFS="$ORIGINAL_IFS"
4303         fi
4304         a_temp=${A_CPU_CORE_DATA[@]}
4305         # echo $a_temp :: ${#A_CPU_CORE_DATA[@]}
4306         log_function_data "A_CPU_CORE_DATA: $a_temp"
4307         eval $LOGFE
4308 }
4309
4310 # args: $1 - integer core count
4311 get_cpu_core_count_alpha()
4312 {
4313         eval $LOGFS
4314         local cpu_alpha_count=''
4315         
4316         case $1 in
4317                 1) cpu_alpha_count='Single';;
4318                 2) cpu_alpha_count='Dual';;
4319                 3) cpu_alpha_count='Triple';;
4320                 4) cpu_alpha_count='Quad';;
4321                 5) cpu_alpha_count='Penta';;
4322                 6) cpu_alpha_count='Hexa';;
4323                 7) cpu_alpha_count='Hepta';;
4324                 8) cpu_alpha_count='Octa';;
4325                 9) cpu_alpha_count='Ennea';;
4326                 10) cpu_alpha_count='Deca';;
4327                 *) cpu_alpha_count='Multi';;
4328         esac
4329         
4330         echo $cpu_alpha_count
4331         
4332         eval $LOGFE
4333 }
4334
4335 ## main cpu data collector
4336 get_cpu_data()
4337 {
4338         eval $LOGFS
4339         local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' a_temp=''
4340         local bsd_cpu_flags='' min_speed='' max_speed=''
4341         
4342         if [[ -f  /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq ]];then
4343                 max_speed=$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq)
4344                 if [[ -f  /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]];then
4345                         min_speed=$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq)
4346                 fi
4347         fi
4348
4349         if [[ $B_CPUINFO_FILE == 'true' ]];then
4350                 # stop script for a bit to let cpu slow down before parsing cpu /proc file
4351                 sleep $CPU_SLEEP
4352                 IFS=$'\n'
4353                 A_CPU_DATA=( $( 
4354                 gawk -v cpuMin="$min_speed" -v cpuMax="$max_speed" -F': ' '
4355                 BEGIN {
4356                         IGNORECASE=1
4357                         # need to prime nr for arm cpus, which do not have processor number output in some cases
4358                         nr = 0
4359                         count = 0
4360                         bArm = "false"
4361                         # ARM cpus are erratic in /proc/cpuinfo this hack can sometimes resolve it. Linux only.
4362                         sysSpeed="'$(get_cpu_speed_hack)'"
4363                         speed = 0
4364                         max = 0
4365                         min = 0
4366                 }
4367                 # TAKE STRONGER NOTE: \t+ does NOT always work, MUST be [ \t]+
4368                 # TAKE NOTE: \t+ will work for $FILE_CPUINFO, but SOME ARBITRARY FILE used for TESTING might contain SPACES!
4369                 # Therefore PATCH to use [ \t]+ when TESTING!
4370                 /^processor[ \t]+:/ {
4371                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
4372                         gsub(/^ +| +$/, "", $NF)
4373                         if ( $NF ~ "^[0-9]+$" ) {
4374                                 nr = $NF
4375                         }
4376                         else {
4377                                 if ( $NF ~ "^ARM" ) {
4378                                         bArm = "true"
4379                                 }
4380                                 count += 1
4381                                 nr = count - 1
4382                                 cpu[nr, "model"] = $NF
4383                         }
4384                 }
4385                 /^model name|^cpu\t+:/ {
4386                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
4387                         gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
4388                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
4389                         gsub(/^ +| +$/, "", $NF)
4390                         gsub(/ [ \t]+/, " ", $NF)
4391                         cpu[nr, "model"] = $NF
4392                         if ( $NF ~ "^ARM" ) {
4393                                 bArm = "true"
4394                         }
4395                 }
4396                 /^cpu MHz|^clock\t+:/ {
4397                         if (speed == 0) {
4398                                 speed = $NF
4399                         }
4400                         else {
4401                                 if ($NF < speed) {
4402                                         speed = $NF
4403                                 }
4404                         }
4405                         if ($NF > max) {
4406                                 max = $NF
4407                         }
4408                         gsub(/MHZ/,"",$NF) ## clears out for cell cpu
4409                         gsub(/.00[0]+$/,".00",$NF) ## clears out excessive zeros
4410                         cpu[nr, "speed"] = $NF
4411                 }
4412                 /^cache size/ {
4413                         cpu[nr, "cache"] = $NF
4414                 }
4415                 /^flags|^features/ {
4416                         cpu[nr, "flags"] = $NF
4417                         # not all ARM cpus show ARM in model name
4418                         if ( $1 ~ /^features/ ) {
4419                                 bArm = "true"
4420                         }
4421                 }
4422                 /^bogomips/ {
4423                         cpu[nr, "bogomips"] = $NF
4424                 }
4425                 /vendor_id/ {
4426                         gsub(/genuine|authentic/,"",$NF)
4427                         cpu[nr, "vendor"] = tolower( $NF )
4428                 }
4429                 END {
4430                         #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that
4431                         for ( i = 0; i <= nr; i++ ) {
4432                                 # note: assuming bogomips for arm at 1 x clock
4433                                 # http://en.wikipedia.org/wiki/BogoMips ARM could change so watch this
4434                                 # maybe add:  && bArm == "true" but I think most of the bogomips roughly equal cpu speed if not amd/intel
4435                                 # 2014-04-08: trying to use sysSpeed hack first, that is more accurate anyway.
4436                                 if ( ( cpu[i, "speed"] == "" && sysSpeed != "" ) || \
4437                                 ( cpu[i, "speed"] == "" && cpu[i, "bogomips"] != "" && cpu[i, "bogomips"] < 50  ) ) {
4438                                         cpu[i, "speed"] = sysSpeed
4439                                 }
4440                                 else if ( cpu[i, "bogomips"] != "" && cpu[i, "speed"] == "" ) {
4441                                         cpu[i, "speed"] = cpu[i, "bogomips"]
4442                                 }
4443                                 print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] ","  cpu[nr, "vendor"] "," bArm
4444                         }
4445                         if (cpuMin != "") {
4446                                 min=cpuMin/1000
4447                         }
4448                         if (cpuMax != "") {
4449                                 max=cpuMax/1000
4450                         }
4451                         # create last array index, to be used for min/max output
4452                         sub(/\.[0-9]+$/,"",max)
4453                         sub(/\.[0-9]+$/,"",speed)
4454                         sub(/\.[0-9]+$/,"",min)
4455                         if (speed == 0) {
4456                                 print "N/A," min "," max
4457                         }
4458                         else {
4459                                 print speed "," min "," max 
4460                         }
4461                 } 
4462                 ' $FILE_CPUINFO ) )
4463                 
4464                 IFS="$ORIGINAL_IFS"
4465                 log_function_data 'cat' "$FILE_CPUINFO"
4466         elif [[ -n $BSD_TYPE ]];then
4467                 get_cpu_data_bsd
4468         fi
4469         
4470         a_temp=${A_CPU_DATA[@]}
4471         log_function_data "A_CPU_DATA: $a_temp"
4472 #       echo ta: ${a_temp[@]}
4473         eval $LOGFE
4474 #       echo getMainCpu: ${[@]}
4475 }
4476 # this triggers in one and only one case, ARM cpus that have fake bogomips data
4477 get_cpu_speed_hack()
4478 {
4479         local speed=$( cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 2>/dev/null )
4480         
4481         if [[ -n $speed ]];then
4482                 speed=${speed%[0-9][0-9][0-9]} # trim off last 3 digits
4483         fi
4484         echo $speed
4485 }
4486
4487 get_cpu_data_bsd()
4488 {
4489         eval $LOGFS
4490
4491         local bsd_cpu_flags=$( get_cpu_flags_bsd )
4492         local gawk_fs=': ' cpu_max=''
4493         
4494         if [[ $BSD_VERSION == 'openbsd' ]];then
4495                 gawk_fs='='
4496         fi
4497         # avoid setting this for systems where you have no read/execute permissions
4498         # might be cases where the dmesg boot file was readable but sysctl perms failed
4499         if [[ -n $Sysctl_a_Data || -n $bsd_cpu_flags ]];then
4500                 if [[ -n $Dmesg_Boot_Data ]];then
4501                         cpu_max=$( gawk -F ':' '
4502                         BEGIN {
4503                         IGNORECASE=1
4504                         }
4505                         # NOTE: freebsd may say: 2300-MHz, so check for dash as well
4506                         $1 ~ /^(CPU|cpu0)$/ {
4507                                 if ( $NF ~ /[^0-9\.][0-9\.]+[\-[:space:]]*[MG]Hz/) {
4508                                         max=gensub(/.*[^0-9\.]([0-9\.]+[\-[:space:]]*[MG]Hz).*/,"\\1",1,$NF)
4509                                         if (max ~ /MHz/) {
4510                                                 sub(/[-[:space:]]*MHz/,"",max)
4511                                         }
4512                                         if (max ~ /GHz/) {
4513                                                 sub(/[-[:space:]]*GHz/,"",max)
4514                                                 max=max*1000
4515                                         }
4516                                         print max
4517                                         exit
4518                                 }
4519                         }' <<< "$Dmesg_Boot_Data" )
4520                 fi
4521                 IFS=$'\n'
4522                 A_CPU_DATA=( $( 
4523                 gawk -F "$gawk_fs" -v bsdVersion=$BSD_VERSION -v cpuFlags="$bsd_cpu_flags" -v cpuMax="$cpu_max" '
4524                 BEGIN {
4525                         IGNORECASE=1
4526                         cpuModel=""
4527                         cpuClock=""
4528                         cpuCache=""
4529                         cpuBogomips=""
4530                         cpuVendor=""
4531                         bSwitchFs="false"
4532                         min=0
4533                         max=0
4534                 }
4535                 /^hw.model/ && ( bsdVersion != "darwin" ) {
4536                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
4537                         gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
4538                         gsub(/'"$BAN_LIST_ARRAY"'/," ",$NF)
4539                         sub(/[a-z]+-core/, "", $NF )
4540                         gsub(/^ +| +$|\"/, "", $NF)
4541                         gsub(/ [ \t]+/, " ", $NF)
4542                         # cut L2 cache/cpu max speed out of model string, if available
4543                         if ( $NF ~ /[0-9]+[[:space:]]*[KM]B[[:space:]]+L2 cache/) {
4544                                 cpuCache=gensub(/.*[^0-9]([0-9]+[[:space:]]*[KM]B)[[:space:]]+L2 cach.*/,"\\1",1,$NF)
4545                         }
4546                         if ( $NF ~ /[^0-9\.][0-9\.]+[\-[:space:]]*[MG]Hz/) {
4547                                 max=gensub(/.*[^0-9\.]([0-9\.]+[\-[:space:]]*[MG]Hz).*/,"\\1",1,$NF)
4548                                 if (max ~ /MHz/) {
4549                                         sub(/[\-[:space:]]*MHz/,"",max)
4550                                 }
4551                                 if (max ~ /GHz/) {
4552                                         sub(/[\-[:space:]]*GHz/,"",max)
4553                                         max=max*1000
4554                                 }
4555                         }
4556                         if ( $NF ~ /\)$/ ){
4557                                 sub(/[[:space:]]*\(.*\)$/,"",$NF)
4558                         }
4559                         cpuModel=$NF
4560 #                       if ( cpuClock != "" ) {
4561 #                               exit
4562 #                       }
4563                 }
4564                 /^hw.clock/ {
4565                         cpuClock=$NF
4566 #                       if ( cpuModel != "" ) {
4567 #                               exit
4568 #                       }
4569                 }
4570                 /^hw.cpufrequency/ {
4571                         cpuClock = $NF / 1000000
4572                 }
4573                 /^hw.cpuspeed/ {
4574                         cpuClock=$NF
4575                 }
4576                 /^hw.l2cachesize/ {
4577                         cpuCache=$NF/1024
4578                         cpuCache=cpuCache " kB"
4579                 }
4580                 /^machdep.cpu.vendor/ {
4581                         cpuVendor=$NF
4582                 }
4583                 # Freebsd does some voltage hacking to actually run at lowest listed frequencies.
4584                 # The cpu does not actually support all the speeds output here but works in freebsd. 
4585                 /^dev.cpu.0.freq_levels/ {
4586                         gsub(/^[[:space:]]+|\/[0-9]+|[[:space:]]+$/,"",$NF)
4587                         if ( $NF ~ /[0-9]+[[:space:]]+[0-9]+/ ) {
4588                                 min=gensub(/.*[[:space:]]([0-9]+)$/,"\\1",1,$NF)
4589                                 max=gensub(/^([0-9]+)[[:space:]].*/,"\\1",1,$NF)
4590                         }
4591                 }
4592                 /^machdep.cpu.brand_string/ {
4593                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
4594                         gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
4595                         gsub(/'"$BAN_LIST_ARRAY"'/," ",$NF)
4596                         sub(/[a-z]+-core/, "", $NF )
4597                         gsub(/^ +| +$|\"/, "", $NF)
4598                         gsub(/ [ \t]+/, " ", $NF)
4599                         sub(/[[:space:]]*@.*/,"",$NF)
4600                         cpuModel=$NF
4601                 }
4602                 END {
4603                         if ( max == 0 && cpuMax != "" ) {
4604                                 max=cpuMax
4605                         }
4606                         if ( cpuClock == "" ) {
4607                                 cpuClock="N/A"
4608                         }
4609                         sub(/\.[0-9]+/,"",cpuClock)
4610                         sub(/\.[0-9]+/,"",min)
4611                         sub(/\.[0-9]+/,"",max)
4612                         print cpuModel "," cpuClock "," cpuCache "," cpuFlags "," cpuBogomips ","  cpuVendor
4613                         # triggers print case
4614                         print cpuClock "," min "," max
4615                 }' <<< "$Sysctl_a_Data" ) )
4616                 IFS="$ORIGINAL_IFS"
4617         fi
4618         
4619         eval $LOGFE
4620 }
4621
4622 get_cpu_flags_bsd()
4623 {
4624         eval $LOGFS
4625         
4626         local cpu_flags=''
4627         local gawk_fs=':'
4628         
4629         if [[ -n $Dmesg_Boot_Data ]];then
4630                 cpu_flags=$( gawk -v bsdVersion="$BSD_VERSION" -F ":" '
4631                 BEGIN {
4632                         IGNORECASE=1
4633                         cpuFlags=""
4634                 }
4635                 /^(CPU:|cpu0:)/ {
4636                         while ( getline && !/memory|real mem/  ) {
4637                                 if ( $1 ~ /Features/ || ( bsdVersion == "openbsd" && $0 ~ /^cpu0.*[[:space:]][a-z][a-z][a-z][[:space:]][a-z][a-z][a-z][[:space:]]/ ) ) {
4638                                         # clean up odd stuff like <b23>
4639                                         gsub(/<[a-z0-9]+>/,"", $2)
4640                                         # all the flags are contained within < ... > on freebsd at least
4641                                         gsub(/.*<|>.*/,"", $2)
4642                                         gsub(/'"$BAN_LIST_ARRAY"'/," ", $2)
4643                                         cpuFlags = cpuFlags " " $2
4644                                 }
4645                         }
4646                         cpuFlags=tolower(cpuFlags)
4647                         print cpuFlags
4648                         exit
4649                 }' <<< "$Dmesg_Boot_Data" )
4650         elif [[ -n $Sysctl_a_Data ]];then
4651                 if [[ $BSD_VERSION == 'openbsd' ]];then
4652                         gawk_fs=':'
4653                 fi
4654                 cpu_flags=$( gawk -F "$gawk_fs" '
4655                 BEGIN {
4656                         cpuFlags=""
4657                 }
4658                 /^machdep.cpu.features/ {
4659                         cpuFlags=tolower($NF)
4660                         print cpuFlags
4661                         exit
4662                 }' <<< "$Sysctl_a_Data" )
4663         fi
4664         echo $cpu_flags
4665         log_function_data "$cpu_flags"
4666         eval $LOGFE
4667 }
4668
4669 ## this is for counting processors and finding HT types
4670 get_cpu_ht_multicore_smp_data()
4671 {
4672         eval $LOGFS
4673         # in /proc/cpuinfo
4674         local a_temp=''
4675         
4676         # note: known bug with xeon intel, they show a_core_id/physical_id as 0 for ht 4 core
4677         if [[ $B_CPUINFO_FILE == 'true' ]]; then
4678                 A_CPU_TYPE_PCNT_CCNT=( $(
4679                 gawk '
4680                 BEGIN {
4681                         FS=": "
4682                         IGNORECASE = 1
4683                         num_of_cores = 0
4684                         num_of_processors = 0
4685                         num_of_physical_cpus = 0
4686                         cpu_core_count = 0
4687                         siblings = 0
4688                         # these 3 arrays cannot be declared because that sets the first element
4689                         # but leaving this here so that we avoid doing that in the future
4690                         # a_core_id = ""
4691                         # a_processor_id = ""
4692                         # a_physical_id = ""
4693                         cpu_type = "-"
4694                         # note: we need separate iterators because some cpuinfo data has only
4695                         # processor, no core id or phys id
4696                         proc_iter = 0
4697                         core_iter = "" # set from actual NF data
4698                         phys_iter = "" # set from actual NF data
4699                         # needed to handle arm cpu, no processor number cases
4700                         arm_count = 0
4701                         nr = 0
4702                         bArm = "false"
4703                         bXeon = "false"
4704                 }
4705                 # hack to handle xeons which can have buggy /proc/cpuinfo files
4706                 /^model name/ && ( $0 ~ /Xeon/ ) {
4707                         bXeon = "true"
4708                 }
4709                 # only do this once since sibling count does not change. 
4710                 /^siblings/ && ( bXeon == "true" ) && ( siblings == 0 ) {
4711                         gsub(/[^0-9]/,"",$NF)
4712                         if ( $NF != "" ) {
4713                                 siblings = $NF
4714                         }
4715                 }
4716                 # array of logical processors, both HT and physical
4717                 /^processor/ {
4718                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
4719                         gsub(/^ +| +$/, "", $NF)
4720                         if ( $NF ~ "^[0-9]+$" ) {
4721                                 a_processor_id[proc_iter] = $NF
4722                                 proc_iter++
4723                         }
4724                         else {
4725                                 # note, for dual core, this can be off by one because the first
4726                                 # line says: Processor : Arm.. but subsequent say: processor : 0 and so on as usual
4727                                 if ( $NF ~ "^ARM" ) {
4728                                         bArm = "true"
4729                                 }
4730                                 arm_count += 1
4731                                 nr = arm_count - 1
4732                                 # note: do not iterate because new ARM syntax puts cpu in processsor : 0 syntax
4733                                 a_processor_id[proc_iter] = nr
4734                         }
4735                 }
4736                 # array of physical cpu ids, note, this will be unset for vm cpus in many cases
4737                 # because they have no physical cpu, so we cannot assume this will be here.
4738                 /^physical/ {
4739                         phys_iter = $NF
4740                         a_physical_id[phys_iter] = $NF
4741                 }
4742                 # array of core ids, again, here we may have HT, so we need to create an array of the
4743                 # actual core ids. As With physical, we cannot assume this will be here in a vm
4744                 /^core id/ {
4745                         core_iter = $NF
4746                         a_core_id[core_iter] = $NF
4747                 }
4748                 # this will be used to fix an intel glitch if needed, cause, intel
4749                 # sometimes reports core id as the same number for each core, 
4750                 # so if cpu cores shows greater value than number of cores, use this. 
4751                 /^cpu cores/ {
4752                         cpu_core_count = $NF
4753                 }
4754                 END {
4755                         ##      Look thru the array and filter same numbers.
4756                         ##      only unique numbers required
4757                         ##      this is to get an accurate count
4758                         ##      we are only concerned with array length
4759                         i = 0
4760                         ## count unique processors ##
4761                         # note, this fails for intel cpus at times
4762                         for ( i in a_processor_id ) {
4763                                 num_of_processors++
4764                         }
4765                         i = 0
4766                         ## count unique physical cpus ##
4767                         for ( i in a_physical_id ) {
4768                                 num_of_physical_cpus++
4769                         }
4770                         i = 0
4771                         ## count unique cores ##
4772                         for ( i in a_core_id ) {
4773                                 num_of_cores++
4774                         }
4775                         # xeon may show wrong core / physical id count, if it does, fix it. A xeon
4776                         # may show a repeated core id : 0 which gives a fake num_of_cores=1
4777                         if ( bXeon == "true" && num_of_cores == 1 && siblings > 1 ) {
4778                                 num_of_cores = siblings/2
4779                         }
4780                         # final check, override the num of cores value if it clearly is wrong
4781                         # and use the raw core count and synthesize the total instead of real count
4782                         if ( ( num_of_cores == 0 ) && ( cpu_core_count * num_of_physical_cpus > 1 ) ) {
4783                                 num_of_cores = cpu_core_count * num_of_physical_cpus
4784                         }
4785                         # last check, seeing some intel cpus and vms with intel cpus that do not show any
4786                         # core id data at all, or siblings.
4787                         if ( num_of_cores == 0 && num_of_processors > 0 ) {
4788                                 num_of_cores = num_of_processors
4789                         }
4790                         # ARM/vm cpu fix, if no physical or core found, use count of 1 instead
4791                         if ( num_of_physical_cpus == 0 ) {
4792                                 num_of_physical_cpus = 1
4793                         }
4794 #                       print "NoCpu: " num_of_physical_cpus
4795 #                       print "NoCores: " num_of_cores
4796 #                       print "NoProc:" num_of_processors
4797 #                       print "CpuCoreCount:" cpu_core_count
4798                         ####################################################################
4799                         #                               algorithm
4800                         # if > 1 processor && processor id (physical id) == core id then Hyperthreaded (HT)
4801                         # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP)
4802                         # if > 1 processor && processor ids (physical id) > 1 then Multiple Processors (SMP)
4803                         # if = 1 processor then single core/processor Uni-Processor (UP)
4804                         if ( num_of_processors > 1 || ( bXeon == "true" && siblings > 0 ) ) {
4805                                 # non-multicore HT
4806                                 if ( num_of_processors == (num_of_cores * 2) ) {
4807                                         cpu_type = cpu_type "HT-"
4808                                 }
4809                                 else if ( bXeon == "true" && siblings > 1 ) {
4810                                         cpu_type = cpu_type "HT-"
4811                                 }
4812                                 # non-HT multi-core or HT multi-core
4813                                 if (( num_of_processors == num_of_cores) || ( num_of_physical_cpus < num_of_cores)) {
4814                                         cpu_type = cpu_type "MCP-"
4815                                 }
4816                                 # >1 cpu sockets active
4817                                 if ( num_of_physical_cpus > 1 ) {
4818                                         cpu_type = cpu_type "SMP-"
4819                                 }
4820                         } 
4821                         else {
4822                                 cpu_type = cpu_type "UP-"
4823                         }                       
4824                         
4825                         print cpu_type " " num_of_physical_cpus " " num_of_cores 
4826                 }
4827                 ' $FILE_CPUINFO ) )
4828         fi
4829         a_temp=${A_CPU_TYPE_PCNT_CCNT[@]}
4830         log_function_data "A_CPU_TYPE_PCNT_CCNT: $a_temp"
4831         eval $LOGFE
4832 }
4833
4834 # Detect desktop environment in use, initial rough logic from: compiz-check
4835 # http://forlong.blogage.de/entries/pages/Compiz-Check
4836 # NOTE $XDG_CURRENT_DESKTOP envvar is not reliable, but it shows certain desktops better.
4837 # most desktops are not using it as of 2014-01-13 (KDE, UNITY, LXDE. Not Gnome)
4838 get_desktop_environment()
4839 {
4840         eval $LOGFS
4841         
4842         # set the default, this function only runs in X, if null, don't print data out
4843         local desktop_environment='' xprop_root='' version2=''
4844         local version='' version_data='' version2_data='' toolkit=''
4845
4846         # works on 4, assume 5 will id the same, why not, no need to update in future
4847         # KDE_SESSION_VERSION is the integer version of the desktop
4848         # NOTE: as of plasma 5, the tool: about-distro MAY be available, that will show
4849         # actual desktop data, so once that's in debian/ubuntu, if it gets in, add that test
4850         if [[ $XDG_CURRENT_DESKTOP == 'KDE' || -n $KDE_SESSION_VERSION ]]; then
4851                 # note the command is actually like, kded4 --version, so we construct it
4852                 # this was supposed to extend to 5, but 5 changed it, so it uses the more reliable way
4853                 if [[ $KDE_SESSION_VERSION -le 4 ]];then
4854                         version_data=$( kded$KDE_SESSION_VERSION --version 2>/dev/null )
4855                         version=$( grep -si '^KDE Development Platform:' <<< "$version_data" | gawk '{print $4}' )
4856                 else
4857                         # NOTE: this command string is almost certain to change, and break, with next major plasma desktop, ie, 6
4858                         # version=$( qdbus org.kde.plasmashell /MainApplication org.qtproject.Qt.QCoreApplication.applicationVersion 2>/dev/null )
4859                         #Qt: 5.4.2
4860                         #KDE Frameworks: 5.11.0
4861                         #kf5-config: 1.0
4862                         # for QT, and Frameworks if we use it
4863                         if type -p kf$KDE_SESSION_VERSION-config &>/dev/null;then
4864                                 version_data=$( kf$KDE_SESSION_VERSION-config --version 2>/dev/null )
4865                                 # version=$( grep -si '^KDE Frameworks:' <<< "$version_data" | gawk '{print $NF}' )
4866                         fi
4867                         # plasmashell 5.3.90
4868                         if type -p plasmashell &>/dev/null;then
4869                                 version2_data=$( plasmashell --version 2>/dev/null )
4870                                 version=$( grep -si '^plasmashell' <<< "$version2_data" | gawk '{print $NF}' )
4871                         fi
4872                 fi
4873                 if [[ -z $version ]];then
4874                         version=$KDE_SESSION_VERSION
4875                 fi
4876                 if [[ $B_EXTRA_DATA == 'true' && -n $version_data ]];then
4877                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
4878                         if [[ -n $toolkit ]];then
4879                                 version="$version (Qt $toolkit)"
4880                         fi
4881                 fi
4882                 desktop_environment="KDE Plasma"
4883         # KDE_FULL_SESSION property is only available since KDE 3.5.5.
4884         # src: http://humanreadable.nfshost.com/files/startkde
4885         elif [[ $KDE_FULL_SESSION == 'true' ]]; then
4886                 version_data=$( kded --version 2>/dev/null )
4887                 version=$( grep -si '^KDE:' <<< "$version_data" | gawk '{print $2}' )
4888                 # version=$( get_program_version 'kded' '^KDE:' '2' )
4889                 if [[ -z $version ]];then
4890                         version='3.5'
4891                 fi
4892                 if [[ $B_EXTRA_DATA == 'true' ]];then
4893                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
4894                         if [[ -n $toolkit ]];then
4895                                 version="$version (Qt $toolkit)"
4896                         fi
4897                 fi
4898                 desktop_environment="KDE"
4899         elif [[ $XDG_CURRENT_DESKTOP == 'Unity' ]];then
4900                 version=$( get_program_version 'unity' '^unity' '2' )
4901                 # not certain will always have version, so keep output right if not
4902                 if [[ -n $version ]];then
4903                         version="$version "
4904                 fi
4905                 if [[ $B_EXTRA_DATA == 'true' ]];then
4906                         toolkit=$( get_de_gtk_data )
4907                         if [[ -n $toolkit ]];then
4908                                 version="$version(Gtk $toolkit)"
4909                         fi
4910                 fi
4911                 desktop_environment="Unity"
4912         elif [[ $XDG_CURRENT_DESKTOP == 'LXQt' ]];then
4913 #               if type -p lxqt-about &>/dev/null;then
4914 #                       version=$( get_program_version 'lxqt-about' '^lxqt-about' '2' )
4915 #               fi
4916                 if [[ $B_EXTRA_DATA == 'true' ]];then
4917                         if kded$KDE_SESSION_VERSION &>/dev/null;then
4918                                 version_data=$( kded$KDE_SESSION_VERSION --version 2>/dev/null )
4919                                 toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
4920                         elif type -p qtdiag &>/dev/null;then
4921                                 toolkit=$( get_program_version 'qtdiag' '^qt' '2' )
4922                         fi
4923                         if [[ -n $toolkit ]];then
4924                                 version="$version (Qt $toolkit)"
4925                         fi
4926                 fi
4927                 desktop_environment='LXQt'
4928         # note, X-Cinnamon value strikes me as highly likely to change, so just search for the last part
4929         elif [[ -n $XDG_CURRENT_DESKTOP && -z ${XDG_CURRENT_DESKTOP/*innamon*/} ]];then
4930                 version=$( get_program_version 'cinnamon' '^cinnamon' '2' )
4931                 # not certain cinn will always have version, so keep output right if not
4932                 if [[ -n $version ]];then
4933                         version="$version "
4934                 fi
4935                 if [[ $B_EXTRA_DATA == 'true' ]];then
4936                         toolkit=$( get_de_gtk_data )
4937                         if [[ -n $toolkit ]];then
4938                                 version="$version(Gtk $toolkit)"
4939                         fi
4940                 fi
4941                 desktop_environment="Cinnamon"
4942         fi
4943         # did we find it? If not, start the xprop tests
4944         if [[ -z $desktop_environment ]];then
4945                 if type -p xprop &>/dev/null;then
4946                         xprop_root="$( xprop -root 2>/dev/null )"
4947                 fi
4948                 # note that cinnamon split from gnome, and and can now be id'ed via xprop,
4949                 # but it will still trigger the next gnome true case, so this needs to go before gnome test
4950                 # eventually this needs to be better organized so all the xprop tests are in the same
4951                 # section, but this is good enough for now.
4952                 if [[ -n $xprop_root && -n $( grep -is '^_MUFFIN' <<< "$xprop_root" ) ]];then
4953                         version=$( get_program_version 'cinnamon' '^cinnamon' '2' )
4954                         # not certain cinn will always have version, so keep output right if not
4955                         if [[ -n $version ]];then
4956                                 version="$version "
4957                         fi
4958                         if [[ $B_EXTRA_DATA == 'true' ]];then
4959                                 toolkit=$( get_de_gtk_data )
4960                                 if [[ -n $toolkit ]];then
4961                                         version="$version(Gtk $toolkit)"
4962                                 fi
4963                         fi
4964                         desktop_environment="Cinnamon"
4965                 elif [[ $XDG_CURRENT_DESKTOP == 'MATE' ]] || [[ -n $xprop_root && -n $( grep -is '^_MARCO' <<< "$xprop_root" ) ]];then
4966                         version=$( get_program_version 'mate-about' '^MATE[[:space:]]DESKTOP' 'NF' )
4967                         # not certain cinn/mate will always have version, so keep output right if not
4968                         if [[ -n $version ]];then
4969                                 version="$version "
4970                         fi
4971                         if [[ $B_EXTRA_DATA == 'true' ]];then
4972                                 toolkit=$( get_de_gtk_data )
4973                                 if [[ -n $toolkit ]];then
4974                                         version="$version(Gtk $toolkit)"
4975                                 fi
4976                         fi
4977                         desktop_environment="MATE"
4978                 # note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out
4979                 # https://bugzilla.gnome.org/show_bug.cgi?id=542880
4980                 elif [[ -n $GNOME_DESKTOP_SESSION_ID || $XDG_CURRENT_DESKTOP == 'GNOME' ]]; then
4981                         if type -p gnome-shell &>/dev/null;then
4982                                 version=$( get_program_version 'gnome-shell' 'gnome' '3' )
4983                         elif type -p gnome-about &>/dev/null;then
4984                                 version=$( get_program_version 'gnome-about' 'gnome' '3' )
4985                         fi
4986                         if [[ $B_EXTRA_DATA == 'true' ]];then
4987                                 toolkit=$( get_de_gtk_data )
4988                                 if [[ -n $toolkit ]];then
4989                                         version="$version (Gtk $toolkit)"
4990                                 fi
4991                         fi
4992                         desktop_environment="Gnome"
4993                 fi
4994                 if [[ -z $desktop_environment ]];then
4995                 # now that the primary ones have been handled, next is to find the ones with unique
4996                 # xprop detections possible
4997                         if [[ -n $xprop_root ]];then
4998                                 # String: "This is xfdesktop version 4.2.12"
4999                                 # alternate: xfce4-about --version > xfce4-about 4.10.0 (Xfce 4.10)
5000                                 if [[ -n $( grep -Eis '\"xfce4\"' <<< "$xprop_root" ) ]];then
5001                                         version=$( get_program_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
5002                                         # arch linux reports null, so use alternate if null
5003                                         if [[ -z $version ]];then
5004                                                 version=$( get_program_version 'xfce4-panel' '^xfce4-panel' '2' )
5005                                                 if [[ -z $version ]];then
5006                                                         version='4'
5007                                                 fi
5008                                         fi
5009                                         if [[ $B_EXTRA_DATA == 'true' ]];then
5010                                                 toolkit=$( get_program_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
5011                                                 if [[ -n $toolkit ]];then
5012                                                         version="$version (Gtk $toolkit)"
5013                                                 fi
5014                                         fi
5015                                         desktop_environment="Xfce"
5016                                 # when 5 is released, the string may need updating
5017                                 elif [[ -n $( grep -is '\"xfce5\"' <<< "$xprop_root" ) ]];then
5018                                         version=$( get_program_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
5019                                         # arch linux reports null, so use alternate if null
5020                                         if [[ -z $version ]];then
5021                                                 version=$( get_program_version 'xfce5-panel' '^xfce5-panel' '2' )
5022                                                 if [[ -z $version ]];then
5023                                                         version='5'
5024                                                 fi
5025                                         fi
5026                                         if [[ $B_EXTRA_DATA == 'true' ]];then
5027                                                 toolkit=$( get_program_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
5028                                                 if [[ -n $toolkit ]];then
5029                                                         version="$version (Gtk $toolkit)"
5030                                                 fi
5031                                         fi
5032                                         desktop_environment="Xfce"
5033                                 # case where no xfce number exists, just xfce
5034                                 elif [[ -n $( grep -is 'xfce' <<< "$xprop_root" ) ]];then
5035                                         version=$( get_program_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
5036                                         # arch linux reports null, so use alternate if null
5037                                         if [[ -z $version ]];then
5038                                                 version=$( get_program_version 'xfce4-panel' '^xfce5-panel' '2' )
5039                                                 if [[ -z $version ]];then
5040                                                         # version=$( get_program_version 'xfce5-panel' '^xfce5-panel' '2' )
5041                                                         #if [[ -z $version ]];then
5042                                                         #       version='5'
5043                                                         #fi
5044                                                         version='4'
5045                                                 fi
5046                                         fi
5047                                         if [[ $B_EXTRA_DATA == 'true' ]];then
5048                                                 toolkit=$( get_program_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
5049                                                 if [[ -n $toolkit ]];then
5050                                                         version="$version (Gtk $toolkit)"
5051                                                 fi
5052                                         fi
5053                                         desktop_environment="Xfce"
5054                                 elif [[ -n $( grep -is 'BLACKBOX_PID' <<< "$xprop_root" ) ]];then
5055                                         if [[ -n $( grep -is 'fluxbox' <<< "$Ps_aux_Data" ) ]];then
5056                                                 version=$( get_program_version 'fluxbox' '^fluxbox' '2' )
5057                                                 desktop_environment='Fluxbox'
5058                                         else
5059                                                 desktop_environment='Blackbox'
5060                                         fi
5061                                 elif [[ -n $( grep -is 'OPENBOX_PID' <<< "$xprop_root" ) ]];then
5062                                         # note: openbox-lxde --version may be present, but returns openbox data
5063                                         version=$( get_program_version 'openbox' '^openbox' '2' )
5064                                         if [[ $XDG_CURRENT_DESKTOP == 'LXDE' || \
5065                                                         -n $( grep -is '/lxsession' <<< "$Ps_aux_Data" ) ]];then
5066                                                 if [[ -n $version ]];then
5067                                                         version="(Openbox $version)"
5068                                                 fi
5069                                                 desktop_environment='LXDE'
5070                                         elif [[  $XDG_CURRENT_DESKTOP == 'Razor' || $XDG_CURRENT_DESKTOP == 'LXQt' ]] || \
5071                                                 [[ -n $( grep -Eis '(razor-desktop|lxqt-session)' <<< "$Ps_aux_Data" ) ]];then
5072                                                 if [[ -n $( grep -is 'lxqt-session' <<< "$Ps_aux_Data" ) ]];then
5073                                                         desktop_environment='LXQt'
5074                                                 elif [[ -n $( grep -is 'razor-desktop' <<< "$Ps_aux_Data" ) ]];then
5075                                                         desktop_environment='Razor-Qt'
5076                                                 else
5077                                                         desktop_environment='LX-Qt-Variant'
5078                                                 fi
5079                                                 if [[ -n $version ]];then
5080                                                         version="(Openbox $version)"
5081                                                 fi
5082                                         else
5083                                                 desktop_environment='Openbox' 
5084                                         fi
5085                                 elif [[ -n $( grep -is 'ICEWM' <<< "$xprop_root" ) ]];then
5086                                         version=$( get_program_version 'icewm' '^icewm' '2' )
5087                                         desktop_environment='IceWM'
5088                                 elif [[ -n $( grep -is 'ENLIGHTENMENT' <<< "$xprop_root" ) ]];then
5089                                         # no -v or --version but version is in xprop -root
5090                                         # ENLIGHTENMENT_VERSION(STRING) = "Enlightenment 0.16.999.49898"
5091                                         version=$( grep -is 'ENLIGHTENMENT_VERSION' <<< "$xprop_root" | cut -d '"' -f 2 | gawk '{print $2}' )
5092                                         desktop_environment='Enlightenment'
5093                                 elif [[ -n $( grep -is '^I3_' <<< "$xprop_root" ) ]];then
5094                                         version=$( get_program_version 'i3' '^i3' '3' )
5095                                         desktop_environment='i3'
5096                                 elif [[ -n $( grep -is 'WINDOWMAKER' <<< "$xprop_root" ) ]];then
5097                                         version=$( get_program_version 'wmaker' '^Window[[:space:]]*Maker' 'NF' )
5098                                         if [[ -n $version ]];then
5099                                                 version="$version "
5100                                         fi
5101                                         desktop_environment="WindowMaker"
5102                                 elif [[ -n $( grep -is '^_WM2' <<< "$xprop_root" ) ]];then
5103                                         # note; there isn't actually a wm2 version available but error handling should cover it and return null
5104                                         # maybe one day they will add it?
5105                                         version=$( get_program_version 'wm2' '^wm2' 'NF' )
5106                                         # not certain will always have version, so keep output right if not
5107                                         if [[ -n $version ]];then
5108                                                 version="$version "
5109                                         fi
5110                                         desktop_environment="WM2"
5111                                 elif [[ -n $( grep -is 'herbstluftwm' <<< "$xprop_root" ) ]];then
5112                                         version=$( get_program_version 'herbstluftwm' '^herbstluftwm' 'NF' )
5113                                         if [[ -n $version ]];then
5114                                                 version="$version "
5115                                         fi
5116                                         desktop_environment="herbstluftwm"
5117                                 fi
5118                         fi
5119                         # a few manual hacks for things that don't id with xprop, these are just good guesses
5120                         # note that gawk is going to exit after first occurance of search string, so no need for extra
5121                         if [[ -z $desktop_environment ]];then
5122                                 if [[ -n $( grep -is 'fvwm-crystal'  <<< "$Ps_aux_Data" ) ]];then
5123                                         version=$( get_program_version 'fvwm' '^fvwm' '2' )
5124                                         desktop_environment='FVWM-Crystal'
5125                                 elif [[ -n $( grep -is 'fvwm'  <<< "$Ps_aux_Data" ) ]];then
5126                                         version=$( get_program_version 'fvwm' '^fvwm' '2' )
5127                                         desktop_environment='FVWM'
5128                                 elif [[ -n $( grep -is 'pekwm'  <<< "$Ps_aux_Data" ) ]];then
5129                                         version=$( get_program_version 'pekwm' '^pekwm' '3' )
5130                                         desktop_environment='pekwm'
5131                                 elif [[ -n $( grep -is 'awesome' <<< "$Ps_aux_Data" ) ]];then
5132                                         version=$( get_program_version 'awesome' '^awesome' '2' )
5133                                         desktop_environment='Awesome'
5134                                 elif [[ -n $( grep -is 'scrotwm' <<< "$Ps_aux_Data" ) ]];then
5135                                         version=$( get_program_version 'scrotwm' '^welcome.*scrotwm' '4' )
5136                                         desktop_environment='Scrotwm' # no --version for this one
5137                                 elif [[ -n $( grep -is 'spectrwm' <<< "$Ps_aux_Data" ) ]];then
5138                                         version=$( get_program_version 'spectrwm' '^spectrwm.*welcome.*spectrwm' '5' )
5139                                         desktop_environment='Spectrwm' # no --version for this one
5140                                 elif [[ -n $( grep -Eis '([[:space:]]|/)twm' <<< "$Ps_aux_Data" ) ]];then
5141                                         desktop_environment='Twm' # no --version for this one
5142                                 elif [[ -n $( grep -Eis '([[:space:]]|/)dwm' <<< "$Ps_aux_Data" ) ]];then
5143                                         version=$( get_program_version 'dwm' '^dwm' '1' )
5144                                         desktop_environment='dwm'
5145                                 elif [[ -n $( grep -is 'wmii2' <<< "$Ps_aux_Data" ) ]];then
5146                                         version=$( get_program_version 'wmii2' '^wmii2' '1' )
5147                                         desktop_environment='wmii2'
5148                                 # note: in debian at least, wmii is actuall wmii3
5149                                 elif [[ -n $( grep -is 'wmii' <<< "$Ps_aux_Data" ) ]];then
5150                                         version=$( get_program_version 'wmii' '^wmii' '1' )
5151                                         desktop_environment='wmii'
5152                                 elif [[ -n $( grep -Eis '([[:space:]]|/)jwm' <<< "$Ps_aux_Data" ) ]];then
5153                                         version=$( get_program_version 'jwm' '^jwm' '2' )
5154                                         desktop_environment='JWM'
5155                                 fi
5156                         fi
5157                 fi
5158         fi
5159         if [[ -n $version ]];then
5160                 version=" $version"
5161         fi
5162         log_function_data "desktop_environment version: $desktop_environment$version"
5163         echo "$desktop_environment$version"
5164         eval $LOGFE
5165 }
5166
5167 # note: gawk doesn't support white spaces in search string, gave errors, so use [[:space:]] instead
5168 # args: $1 - desktop/app command for --version; $2 - search string; $3 - gawk print number
5169 get_program_version()
5170 {
5171         local version_data='' version='' get_version='--version' 
5172         
5173         # mate-about -v = MATE Desktop Environment 1.4.0
5174         case $1 in
5175                 dwm|jwm|mate-about|wmii|wmii2)
5176                         get_version='-v'
5177                         ;;
5178                 epoch)
5179                         get_version='version'
5180                         ;;
5181         esac
5182         
5183         case $1 in
5184                 # note, some wm/apps send version info to stderr instead of stdout
5185                 dwm|ksh|scrotwm|spectrwm)
5186                         version_data="$( $1 $get_version 2>&1 )"
5187                         ;;
5188                 csh)
5189                         version_data="$( tcsh $get_version 2>/dev/null )"
5190                         ;;
5191                 # quick debian/buntu hack until I find a universal way to get version for these
5192                 dash)
5193                         if type -p dpkg &>/dev/null;then
5194                                 version_data="$( dpkg -l $1 2>/dev/null )"
5195                         fi
5196                         ;;
5197                 *)
5198                         version_data="$( $1 $get_version 2>/dev/null )"
5199                         ;;
5200         esac
5201         log_function_data "version data: $version_data"
5202         if [[ -n $version_data ]];then
5203                 version=$( gawk '
5204                 BEGIN {
5205                         IGNORECASE=1
5206                 }
5207                 /'$2'/ {
5208                         # sample: dwm-5.8.2, Â©.. etc, why no space? who knows. Also get rid of v in number string
5209                         # xfce, and other, output has , in it, so dump all commas and parentheses
5210                         gsub(/(,|dwm-|wmii2-|wmii-|v|V|\(|\))/, "",$'$3') 
5211                         print $'$3'
5212                         exit # quit after first match prints
5213                 }' <<< "$version_data" )
5214         fi
5215         log_function_data "program version: $version"
5216         echo $version
5217 }
5218
5219 get_desktop_extra_data()
5220 {
5221         eval $LOGFS
5222         local de_data=$( ps -A | gawk '
5223         BEGIN {
5224                 IGNORECASE=1
5225                 desktops=""
5226                 separator=""
5227         }
5228         /(gnome-shell|gnome-panel|kicker|lxpanel|mate-panel|plasma-desktop|plasma-netbook|xfce4-panel)$/ {
5229                 # only one entry per type, can be multiple
5230                 if ( desktops !~ $NF ) {
5231                         desktops = desktops separator $NF
5232                         separator = ","
5233                 }
5234         }
5235         END {
5236                 print desktops
5237         }
5238         ' )
5239         log_function_data "de_data: $de_data"
5240         echo $de_data
5241         
5242         eval $LOGFE
5243 }
5244
5245 get_de_gtk_data()
5246 {
5247         eval $LOGFS
5248         
5249         local toolkit=''
5250         
5251         # this is a hack, and has to be changed with every toolkit version change, and only dev systems
5252         # have this installed, but it's a cross distro command so let's test it first
5253         if type -p pkg-config &>/dev/null;then
5254                 toolkit=$( pkg-config --modversion gtk+-4.0 2>/dev/null )
5255                 # note: opensuse gets null output here, we need the command to get version and output sample
5256                 if [[ -z $toolkit ]];then
5257                         toolkit=$( pkg-config --modversion gtk+-3.0 2>/dev/null )
5258                 fi
5259                 if [[ -z $toolkit ]];then
5260                         toolkit=$( pkg-config --modversion gtk+-2.0 2>/dev/null )
5261                 fi
5262         fi
5263         # now let's go to more specific version tests, this will never cover everything and that's fine.
5264         if [[ -z $toolkit ]];then
5265                 # we'll try some known package managers next. dpkg will handle a lot of distros 
5266                 # this is the most likely order as of: 2014-01-13. Not going to try to support all package managers
5267                 # too much work, just the very biggest ones.
5268                 if type -p dpkg &>/dev/null;then
5269                         toolkit=$( dpkg -s libgtk-3-0 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
5270                         # just guessing on gkt 4 package name
5271                         if [[ -z $toolkit ]];then
5272                                 toolkit=$( dpkg -s libgtk-4-0 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
5273                         fi
5274                         if [[ -z $toolkit ]];then
5275                                 toolkit=$( dpkg -s libgtk2.0-0 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
5276                         fi
5277                 elif type -p pacman &>/dev/null;then
5278                         toolkit=$(  pacman -Qi gtk3 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
5279                         # just guessing on gkt 4 package name
5280                         if [[ -z $toolkit ]];then
5281                                 toolkit=$( pacman -Qi gtk4 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
5282                         fi
5283                         if [[ -z $toolkit ]];then
5284                                 toolkit=$( pacman -Qi gtk2 2>/dev/null | gawk -F ':' '/^[[:space:]]*Version/ {print $2}' )
5285                         fi
5286                 # Name        : libgtk-3-0
5287                 # Version     : 3.12.2
5288                 elif type -p rpm &>/dev/null;then
5289                         toolkit=$( rpm -qi libgtk-3-0 2>/dev/null | gawk -F ':' '
5290                         /^[[:space:]]*Version/ { 
5291                                 gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
5292                                 print $2 
5293                         }' )
5294                         if [[ -z $toolkit ]];then
5295                                 toolkit=$( rpm -qi libgtk-4-0 2>/dev/null | gawk -F ':' '
5296                                 /^[[:space:]]*Version/ {
5297                                         gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
5298                                         print $2
5299                                 }' )
5300                         fi
5301                         if [[ -z $toolkit ]];then
5302                                 toolkit=$( rpm -qi libgtk-2-0 2>/dev/null | gawk -F ':' '
5303                                 /^[[:space:]]*Version/ {
5304                                         gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
5305                                         print $2
5306                                 }' )
5307                         fi
5308                 fi
5309         fi
5310         log_function_data "toolkit: $toolkit"
5311         echo $toolkit
5312         
5313         eval $LOGFE
5314 }
5315
5316
5317 # see which dm has started if any
5318 get_display_manager()
5319 {
5320         eval $LOGFS
5321         # ldm - LTSP display manager. Note that sddm does not appear to have a .pid extension in Arch
5322         # note: to avoid positives with directories, test for -f explicitly, not -e
5323         local dm_id_list='entranced.pid gdm.pid gdm3.pid kdm.pid ldm.pid lightdm.pid lxdm.pid mdm.pid nodm.pid sddm.pid sddm slim.lock tint2.pid wdm.pid xdm.pid' 
5324         local dm_id='' dm='' separator=''
5325         # note we don't need to filter grep if we do it this way
5326         local x_is_running=$( grep '/usr.*/X' <<< "$Ps_aux_Data" | grep -iv '/Xprt' )
5327
5328         for dm_id in $dm_id_list
5329         do
5330                 # note: ${dm_id%.*}/$dm_id will create a dir name out of the dm id, then test if pid is in that
5331                 # note: sddm, in an effort to be unique and special, do not use a pid/lock file, but rather a random
5332                 # string inside a directory called /run/sddm/ so assuming the existence of the pid inside a directory named
5333                 # from the dm. Hopefully this change will not have negative results.
5334                 if [[ -f /run/$dm_id || -d /run/${dm_id%.*}/ || -f /var/run/$dm_id || \
5335                       -d /var/run/${dm_id%.*}/ ]];then
5336                         # just on the off chance that two dms are running, good info to have in that case, if possible
5337                         dm=$dm$separator${dm_id%.*}
5338                         separator=','
5339                 fi
5340         done
5341         # might add this in, but the rate of new dm's makes it more likely it's an unknown dm, so
5342         # we'll keep output to N/A
5343         if [[ -n $x_is_running && -z $dm ]];then
5344                 if [[ -n $( grep 'startx$' <<< "$Ps_aux_Data" ) ]];then
5345                         dm='(startx)'
5346                 fi
5347         fi
5348         echo $dm
5349
5350         log_function_data "display manager: $dm"
5351
5352         eval $LOGFE
5353 }
5354
5355 # for more on distro id, please reference this python thread: http://bugs.python.org/issue1322
5356 ## return distro name/id if found
5357 get_distro_data()
5358 {
5359         eval $LOGFS
5360         local i='' j='' distro='' distro_file='' a_distro_glob='' a_temp='' b_osr='false'
5361         
5362         # may need modification if archbsd / debian can be id'ed with /etc files
5363         if [[ -n $BSD_TYPE ]];then
5364                 if [[ $BSD_VERSION != 'darwin' ]];then
5365                         distro=$( uname -sr )
5366                 else
5367                         if [[ -f /System/Library/CoreServices/SystemVersion.plist ]];then
5368                                 distro=$( grep -A1 -E '(ProductName|ProductVersion)' /System/Library/CoreServices/SystemVersion.plist  | grep '<string>' | sed -E 's/<[\/]?string>//g' )
5369                                 distro=$( echo $distro )
5370                         fi
5371                         if [[ -z $distro ]];then
5372                                 distro='Mac OS X'
5373                         fi
5374                 fi
5375                 echo "$distro"
5376                 log_function_data "distro: $distro"
5377                 eval $LOGFE
5378                 return 0
5379         fi
5380
5381         # get the wild carded array of release/version /etc files if present
5382         shopt -s nullglob
5383         cd /etc
5384         # note: always exceptions, so wild card after release/version: /etc/lsb-release-crunchbang
5385         # wait to handle since crunchbang file is one of the few in the world that uses this method
5386         a_distro_glob=(*[-_]{release,version})
5387         cd "$OLDPWD"
5388         shopt -u nullglob
5389         
5390         a_temp=${a_distro_glob[@]}
5391         log_function_data "a_distro_glob: $a_temp"
5392
5393         if [[ ${#a_distro_glob[@]} -eq 1 ]];then
5394                 distro_file="$a_distro_glob"
5395         # use the file if it's in the known good lists
5396         elif [[ ${#a_distro_glob[@]} -gt 1 ]];then
5397                 for i in $DISTROS_DERIVED $DISTROS_PRIMARY
5398                 do
5399                         # Only echo works with ${var[@]}, not print_screen_output() or script_debugger()
5400                         # This is a known bug, search for the word "strange" inside comments
5401                         # echo "i='$i' a_distro_glob[@]='${a_distro_glob[@]}'"
5402                         if [[ " ${a_distro_glob[@]} " == *" $i "* ]];then
5403                                 # Now lets see if the distro file is in the known-good working-lsb-list
5404                                 # if so, use lsb-release, if not, then just use the found file
5405                                 # this is for only those distro's with self named release/version files
5406                                 # because Mint does not use such, it must be done as below 
5407                                 ## this if statement requires the spaces and * as it is, else it won't work
5408                                 ##
5409                                 if [[ " $DISTROS_LSB_GOOD " == *" $i "* ]] && [[ $B_LSB_FILE == 'true' ]];then
5410                                         distro_file='lsb-release'
5411                                 elif [[ " $DISTROS_OS_RELEASE_GOOD " == *" $i "* ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
5412                                         distro_file='os-release'
5413                                 else
5414                                         distro_file="$i"
5415                                 fi
5416                                 break
5417                         fi
5418                 done
5419         fi
5420         log_function_data "distro_file: $distro_file"
5421         # first test for the legacy antiX distro id file
5422         if [[ -e /etc/antiX ]];then
5423                 distro="$( grep -Eoi 'antix.*\.iso' <<< $( remove_erroneous_chars '/etc/antiX' ) | sed 's/\.iso//' )"
5424         # this handles case where only one release/version file was found, and it's lsb-release. This would
5425         # never apply for ubuntu or debian, which will filter down to the following conditions. In general
5426         # if there's a specific distro release file available, that's to be preferred, but this is a good backup.
5427         elif [[ -n $distro_file && $B_LSB_FILE == 'true' && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then
5428                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
5429         elif [[ $distro_file == 'lsb-release' ]];then
5430                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
5431         elif [[ $distro_file == 'os-release' ]];then
5432                 distro=$( get_distro_lsb_os_release_data 'os-release-file' )
5433                 b_osr='true'
5434         # then if the distro id file was found and it's not in the exluded primary distro file list, read it
5435         elif [[ -n $distro_file && -s /etc/$distro_file && " $DISTROS_EXCLUDE_LIST " != *" $distro_file "* ]];then
5436                 # new opensuse uses os-release, but older ones may have a similar syntax, so just use the first line
5437                 if [[ $distro_file == 'SuSE-release' ]];then
5438                         # leaving off extra data since all new suse have it, in os-release, this file has line breaks, like os-release
5439                         # but in case we  want it, it's: CODENAME = Mantis  | VERSION = 12.2 
5440                         # for now, just take first occurance, which should be the first line, which does not use a variable type format
5441                         distro=$( grep -i -m 1 'suse' /etc/$distro_file )
5442                 else
5443                         distro=$( remove_erroneous_chars "/etc/$distro_file" )
5444                 fi
5445         # otherwise try  the default debian/ubuntu /etc/issue file
5446         elif [[ -f /etc/issue ]];then
5447                 # os-release/lsb gives more manageable and accurate output than issue, but mint should use issue for now
5448                 # some bashism, boolean must be in parenthesis to work correctly, ie [[ $(boolean) ]] not [[ $boolean ]]
5449                 if [[ $B_OS_RELEASE_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
5450                         distro=$( get_distro_lsb_os_release_data 'os-release-file' )
5451                         b_osr='true'
5452                 elif [[ $B_LSB_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
5453                         distro=$( get_distro_lsb_os_release_data 'lsb-file' )
5454                 else
5455                         distro=$( gawk '
5456                         BEGIN {
5457                                 RS=""
5458                         }
5459                         {
5460                                 gsub(/\\[a-z]/, "")
5461                                 gsub(/'"$BAN_LIST_ARRAY"'/, " ")
5462                                 gsub(/^ +| +$/, "")
5463                                 gsub(/ [ \t]+/, " ")
5464                                 print
5465                         }' /etc/issue )
5466                         
5467                         # this handles an arch bug where /etc/arch-release is empty and /etc/issue is corrupted
5468                         # only older arch installs that have not been updated should have this fallback required, new ones use
5469                         # os-release
5470                         if [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then
5471                                 distro='Arch Linux'
5472                         fi
5473                 fi
5474         fi
5475         # a final check. If a long value, before assigning the debugger output, if os-release
5476         # exists then let's use that if it wasn't tried already. Maybe that will be better.
5477         if [[ ${#distro} -gt 80 ]] && [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then
5478                 if [[ $B_OS_RELEASE_FILE == 'true' && $b_osr == 'false' ]];then
5479                         distro=$( get_distro_lsb_os_release_data 'os-release-file' )
5480                 fi
5481                 if [[ ${#distro} -gt 80 ]];then
5482                         distro="${RED}/etc/$distro_file corrupted, use -% to override${NORMAL}"
5483                 fi
5484         fi
5485         ## note: would like to actually understand the method even if it's not used
5486         # : ${distro:=Unknown distro o_O}
5487         ## test for /etc/lsb-release as a backup in case of failure, in cases where > one version/release file
5488         ## were found but the above resulted in null distro value
5489         # Because os-release is now more common, we'll test for it first.
5490         if [[ -z $distro ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
5491                 distro=$( get_distro_lsb_os_release_data 'os-release-file' )
5492         fi
5493         if [[ -z $distro ]] && [[ $B_LSB_FILE == 'true' ]];then
5494                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
5495         fi
5496         
5497         # now some final null tries
5498         if [[ -z $distro ]];then
5499                 # if the file was null but present, which can happen in some cases, then use the file name itself to 
5500                 # set the distro value. Why say unknown if we have a pretty good idea, after all?
5501                 if [[ -n $distro_file ]] && [[ " $DISTROS_DERIVED $DISTROS_PRIMARY " == *" $distro_file "* ]];then
5502                         distro=$( sed $SED_RX -e 's/[-_]//' -e 's/(release|version)//' <<< $distro_file | sed $SED_RX 's/^([a-z])/\u\1/' )
5503                 fi
5504                 ## finally, if all else has failed, give up
5505                 if [[ -z $distro ]];then
5506                         distro='unknown'
5507                 fi
5508         fi
5509         # final step cleanup of unwanted information
5510         # opensuse has the x86 etc type string in names, not needed as redundant since -S already shows that
5511         distro=$( gawk '
5512         BEGIN {
5513                 IGNORECASE=1
5514         }
5515         {
5516                 sub(/ *\(*(x86_64|i486|i586|i686|686|586|486)\)*/, "", $0)
5517                 print $0
5518         }' <<< $distro )
5519         echo "$distro"
5520         log_function_data "distro: $distro"
5521         eval $LOGFE
5522 }
5523
5524 # args: $1 - lsb-file/lsb-app/os-release-file
5525 get_distro_lsb_os_release_data()
5526 {
5527         eval $LOGFS
5528         local distro=''
5529         
5530         case $1 in
5531                 lsb-file)
5532                         if [[ $B_LSB_FILE == 'true' ]];then
5533                                 distro=$( gawk -F '=' '
5534                                 BEGIN {
5535                                         IGNORECASE=1
5536                                 }
5537                                 # clean out unwanted characters
5538                                 { 
5539                                         gsub(/\\|\"|[:\47]/,"", $0 )
5540                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
5541                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
5542                                 }
5543                                 # note: adding the spacing directly to variable to make sure distro output is null if not found
5544                                 /^DISTRIB_ID/ {
5545                                         # this is needed because grep for "arch" is too loose to be safe
5546                                         if ( $2 == "arch" ) {
5547                                                 distroId = "Arch Linux"
5548                                         }
5549                                         else if ( $2 != "n/a" ) {
5550                                                 distroId = $2 " "
5551                                         }
5552                                 }
5553                                 /^DISTRIB_RELEASE/ {
5554                                         if ( $2 != "n/a" ) {
5555                                                 distroRelease = $2 " "
5556                                         }
5557                                 }
5558                                 /^DISTRIB_CODENAME/ {
5559                                         if ( $2 != "n/a" ) {
5560                                                 distroCodename = $2 " "
5561                                         }
5562                                 }
5563                                 # sometimes some distros cannot do their lsb-release files correctly, so here is
5564                                 # one last chance to get it right.
5565                                 /^DISTRIB_DESCRIPTION/ {
5566                                         if ( $2 != "n/a" ) {
5567                                                 distroDescription = $2
5568                                         }
5569                                 }
5570                                 END {
5571                                         fullString=""
5572                                         if ( distroId == "" && distroRelease == "" && distroCodename == "" && distroDescription != "" ){
5573                                                 fullString = distroDescription
5574                                         }
5575                                         else {
5576                                                 fullString = distroId distroRelease distroCodename
5577                                         }
5578                                         print fullString
5579                                 }
5580                                 ' $FILE_LSB_RELEASE )
5581                                 log_function_data 'cat' "$FILE_LSB_RELEASE"
5582                         fi
5583                         ;;
5584                 lsb-app)
5585                         # this is HORRIBLY slow, not using
5586                         if type -p lsb_release &>/dev/null;then
5587                                 distro=$( echo "$( lsb_release -irc )" | gawk -F ':' '
5588                                 BEGIN { 
5589                                         IGNORECASE=1 
5590                                 }
5591                                 # clean out unwanted characters
5592                                 { 
5593                                         gsub(/\\|\"|[:\47]/,"", $0 )
5594                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
5595                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
5596                                 }
5597                                 /^Distributor ID/ {
5598                                         distroId = $2
5599                                 }
5600                                 /^Release/ {
5601                                         distroRelease = $2
5602                                 }
5603                                 /^Codename/ {
5604                                         distroCodename = $2
5605                                 }
5606                                 END {
5607                                         print distroId " " distroRelease " (" distroCodename ")"
5608                                 }' )
5609                         fi
5610                         ;;
5611                 os-release-file)
5612                         if [[ $B_OS_RELEASE_FILE == 'true' ]];then
5613                                 distro=$( gawk -F '=' '
5614                                 BEGIN {
5615                                         IGNORECASE=1
5616                                         prettyName=""
5617                                         regularName=""
5618                                         versionName=""
5619                                         versionId=""
5620                                         distroName=""
5621                                 }
5622                                 # clean out unwanted characters
5623                                 { 
5624                                         gsub(/\\|\"|[:\47]/,"", $0 )
5625                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
5626                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
5627                                 }
5628                                 # note: adding the spacing directly to variable to make sure distro output is null if not found
5629                                 /^PRETTY_NAME/ {
5630                                         if ( $2 != "n/a" ) {
5631                                                 prettyName = $2
5632                                         }
5633                                 }
5634                                 /^NAME/ {
5635                                         if ( $2 != "n/a" ) {
5636                                                 regularName = $2
5637                                         }
5638                                 }
5639                                 /^VERSION/ {
5640                                         if ( $2 != "n/a" && $1 == "VERSION" ) {
5641                                                 versionName = $2
5642                                         }
5643                                         else if ( $2 != "n/a" && $1 == "VERSION_ID" ) {
5644                                                 versionId = $2
5645                                         }
5646                                 }
5647                                 END {
5648                                         if ( prettyName != "" ) {
5649                                                 distroName = prettyName
5650                                         }
5651                                         else if ( regularName != "" ) {
5652                                                 distroName = regularName
5653                                                 if ( versionName != "" ) {
5654                                                         distroName = distroName " " versionName
5655                                                 }
5656                                                 else if ( versionId != "" ) {
5657                                                         distroName = distroName " " versionId
5658                                                 }
5659                                                 
5660                                         }
5661                                         print distroName
5662                                 }
5663                                 ' $FILE_OS_RELEASE )
5664                                 log_function_data 'cat' "$FILE_OS_RELEASE"
5665                         fi
5666                         ;;
5667         esac
5668         echo $distro
5669         log_function_data "distro: $distro"
5670         eval $LOGFE
5671 }
5672
5673 get_dmidecode_data()
5674 {
5675         eval $LOGFS
5676         
5677         local dmiData="" b_debugger='false'
5678
5679         if [[ $B_DMIDECODE_SET != 'true' ]];then
5680                 dmidecodePath=$( type -p dmidecode 2>/dev/null )
5681                 if [[ -z $dmidecodePath ]];then
5682                         DMIDECODE_DATA='dmidecode-error-not-installed'
5683                 else
5684                         # note stripping out these lines: Handle 0x0016, DMI type 17, 27 bytes
5685                         # but NOT deleting them, in case the dmidecode data is missing empty lines which will be
5686                         # used to separate results. Then we remove the doubled empty lines to keep it clean and
5687                         # strip out all the stuff we don't want to see in the results. We want the error data in 
5688                         # stdout for error handling
5689                         if [[ $b_debugger == 'true' && $HOSTNAME == 'yawn' ]];then
5690                                 dmiData="$( cat ~/bin/scripts/inxi/svn/misc/data/dmidecode/dmidecode-memory-variants-2.txt )"
5691                         else 
5692                                 dmiData="$( $dmidecodePath 2>&1 )"
5693                         fi
5694                         # these tests first, because bsd error messages like this (note how many : are in the string)
5695                         # inxi: line 4928: /usr/local/sbin/dmidecode: Permission denied
5696                         if [[ ${#dmiData} -lt 200  ]];then
5697                                 if [[ -z ${dmiData/*Permission denied*/} ]];then
5698                                 # if [[ -n $( grep -i 'Permission denied' <<< "$dmiData" ) ]];then
5699                                         DMIDECODE_DATA='dmidecode-error-requires-root'
5700                                 # this handles very old systems, like Lenny 2.6.26, with dmidecode, but no data
5701                                 elif [[ -n $( grep -i 'no smbios ' <<< "$dmiData" ) ]];then
5702                                         DMIDECODE_DATA='dmidecode-error-no-smbios-dmi-data'
5703                                 else
5704                                         DMIDECODE_DATA='dmidecode-error-unknown-error'
5705                                 fi
5706                         else
5707                                 DMIDECODE_DATA="$( echo "$dmiData" | gawk -F ':' '
5708                                 BEGIN {
5709                                         IGNORECASE=1
5710                                         cutExtraTab="false"
5711                                         twoData=""
5712                                         oneData=""
5713                                 }
5714                                 {
5715                                         # no idea why, but freebsd gawk does not do this right
5716                                         oneData=$1
5717                                         twoData=$2
5718                                         if ( twoData != "" ) {
5719                                                 twoHolder="true"
5720                                         }
5721                                         else {
5722                                                 twoHolder="false"
5723                                         }
5724                                         if ( $0 ~ /^\tDMI type/ ) {
5725                                                 sub(/^\tDMI type.*/, "", $0)
5726                                                 cutExtraTab="true"
5727                                         }
5728                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", twoData)
5729                                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", twoData)
5730                                         # clean out Handle line
5731                                         # sub(/^Handle.*/,"", $0)
5732                                         sub(/^[[:space:]]*Inactive.*/,"",twoData)
5733                                         # yes, there is a typo in a user data set, unknow
5734                                         # Base Board Version|Base Board Serial Number
5735                                         # Chassis Manufacturer|Chassis Version|Chassis Serial Number
5736                                         # System manufacturer|System Product Name|System Version
5737                                         # To Be Filled By O.E.M.
5738                                         # strip out starting white space so that the following stuff will clear properly
5739                                         sub(/^[[:space:]]+/, "", twoData)
5740                                         sub(/^Base Board .*|^Chassis .*|empty|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*|^0x[0]+$|\[Empty\]|<Bad Index>|^\.\.$/, "", twoData) 
5741                                         sub(/.*(AssetTagNum|Manufacturer| Or Motherboard|PartNum.*|SerNum).*/, "", twoData)
5742                                         gsub(/bios|acpi/, "", twoData)
5743                                         sub(/http:\/\/www.abit.com.tw\//, "Abit", twoData)
5744                                         
5745                                         # for double indented values replace with ~ so later can test for it, we are trusting that
5746                                         # indentation will be tabbed in this case
5747                                         # special case, dmidecode 2.2 has an extra tab and a DMI type line
5748                                         if ( cutExtraTab == "true" ) {
5749                                                 sub(/^\t\t\t+/, "~", oneData)
5750                                         }
5751                                         else {
5752                                                 sub(/^\t\t+/, "~", oneData)
5753                                         }
5754                                         gsub(/ [ \t]+/, " ", twoData)
5755                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", twoData)
5756                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", oneData)
5757                                         
5758                                         # reconstructing the line for processing so gawk can use -F : again
5759                                         if ( oneData != "" && twoHolder == "true" ) {
5760                                                 print oneData ":" twoData
5761                                         }
5762                                         else {
5763                                                 # make sure all null lines have no spaces in them!
5764                                                 gsub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
5765                                                 print $0
5766                                         }
5767                                 }' \
5768                                 | sed '/^$/{
5769 N
5770 /^\n$/D
5771 }' \
5772                                 )"
5773                         fi
5774                         # echo ":${DMIDECODE_DATA}:"
5775                         log_function_data "DMIDECODE_DATA (PRE): $DMIDECODE_DATA"
5776                         
5777                 fi
5778                 B_DMIDECODE_SET='true'
5779                 log_function_data "DMIDECODE_DATA (POST): $DMIDECODE_DATA"
5780         fi
5781
5782         eval $LOGFE
5783 }
5784 # get_dmidecode_data;echo "$DMIDECODE_DATA";exit
5785
5786 # BSD only
5787 get_dmesg_boot_data()
5788 {
5789         eval $LOGFS
5790         
5791         local dmsg_boot_data=''
5792         
5793         if [[ $B_DMESG_BOOT_FILE == 'true' ]];then
5794                 # replace all indented items with ~ so we can id them easily while processing
5795                 # note that if user, may get error of read permissions
5796                 # for some weird reason, real mem and avail mem are use a '=' separator, who knows why, the others are ':'
5797                 dmsg_boot_data="$( cat $FILE_DMESG_BOOT 2>/dev/null | gawk '
5798                 {
5799                         sub(/[[:space:]]*=[[:space:]]*|:[[:space:]]*/,":", $0)
5800                         gsub(/'"$BAN_LIST_ARRAY"'/," ", $0)
5801                         gsub(/\"/, "", $0)
5802                         gsub(/[[:space:]][[:space:]]/, " ", $0)
5803                         print $0
5804                 }' )"
5805         fi
5806         echo "$dmsg_boot_data"
5807         # log_function_data "$dmsg_boot_data"
5808         eval $LOGFE
5809 }
5810
5811 get_gcc_system_version()
5812 {
5813         eval $LOGFS
5814         local separator='' gcc_installed='' gcc_list='' gcc_others='' a_temp=''
5815         local gcc_version=$( 
5816         gcc --version 2>/dev/null | sed $SED_RX 's/\([^\)]*\)//g' | gawk '
5817         BEGIN {
5818                 IGNORECASE=1
5819         }
5820         /^gcc/ {
5821                 print $2
5822                 exit
5823         }' )
5824         # can't use xargs -L basename because not all systems support thats
5825         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
5826                 gcc_others=$( ls /usr/bin/gcc-* 2>/dev/null )
5827                 if [[ -n $gcc_others ]];then
5828                         for item in $gcc_others
5829                         do
5830                                 item=${item##*/}
5831                                 gcc_installed=$( gawk -F '-' '
5832                                 $2 ~ /^[0-9\.]+$/ {
5833                                         print $2
5834                                 }' <<< $item )
5835                                 if [[ -n $gcc_installed && -z $( grep "^$gcc_installed" <<< $gcc_version ) ]];then
5836                                         gcc_list=$gcc_list$separator$gcc_installed
5837                                         separator=','
5838                                 fi
5839                         done
5840                 fi
5841         fi
5842         if [[ -n $gcc_version ]];then
5843                 A_GCC_VERSIONS=( "$gcc_version" $gcc_list )
5844         fi
5845         a_temp=${A_GCC_VERSIONS[@]}
5846         log_function_data "A_GCC_VERSIONS: $a_temp"
5847         eval $LOGFE
5848 }
5849
5850 get_gpu_temp_data()
5851 {
5852         local gpu_temp='' gpu_fan='' screens='' screen_nu='' gpu_temp_looper=''
5853
5854         # we'll try for nvidia/ati, then add if more are shown
5855         if type -p nvidia-settings &>/dev/null;then
5856                 # first get the number of screens. This only work if you are in X
5857                 if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
5858                         screens=$( nvidia-settings -q screens | gawk '
5859                         /:[0-9]\.[0-9]/ {
5860                                 screens=screens gensub(/(.*)(:[0-9]\.[0-9])(.*)/, "\\2", "1", $0) " "
5861                         }
5862                         END {
5863                                 print screens
5864                         }
5865                         ' )
5866                 else
5867                         # do a guess, this will work for most users, it's better than nothing for out of X
5868                         screens=':0.0'
5869                 fi
5870                 # now we'll get the gpu temp for each screen discovered. The print out function
5871                 # will handle removing screen data for single gpu systems
5872                 for screen_nu in $screens
5873                 do
5874                         gpu_temp_looper=$( nvidia-settings -c $screen_nu -q GPUCoreTemp 2>/dev/null | gawk -F ': ' '
5875                         BEGIN {
5876                                 IGNORECASE=1
5877                                 gpuTemp=""
5878                                 gpuTempWorking=""
5879                         }
5880                         /Attribute (.*)[0-9]+\.$/ {
5881                                 gsub(/\./, "", $2)
5882                                 if ( $2 ~ /^[0-9]+$/ ) {
5883                                         gpuTemp=gpuTemp $2 "C "
5884                                 }
5885                         }
5886                         END {
5887                                 print gpuTemp
5888                         }'      )
5889                         screen_nu=$( cut -d ':' -f 2 <<< $screen_nu )
5890                         gpu_temp="$gpu_temp$screen_nu:$gpu_temp_looper "
5891                 done
5892         elif type -p aticonfig &>/dev/null;then
5893 #               gpu_temp=$( aticonfig --adapter=0 --od-gettemperature | gawk -F ': ' '
5894                 gpu_temp=$( aticonfig --adapter=all --od-gettemperature | gawk -F ': ' '
5895                 BEGIN {
5896                         IGNORECASE=1
5897                         gpuTemp=""
5898                         gpuTempWorking=""
5899                 }
5900                 /Sensor (.*)[0-9\.]+ / {
5901                         gpuTempWorking=gensub(/(.*) ([0-9\.]+) (.*)/, "\\2", "1", $2)
5902                         if ( gpuTempWorking ~ /^[0-9\.]+$/ ) {
5903                                 gpuTemp=gpuTemp gpuTempWorking "C "
5904                         }
5905                 }
5906                 END {
5907                         print gpuTemp
5908                 }'      )
5909         # this handles some newer cases of free driver temp readouts, will require modifications as
5910         # more user data appears.
5911         elif [[ -n $Sensors_Data ]];then
5912                 gpu_temp=$( 
5913                 gawk '
5914                 BEGIN {
5915                         IGNORECASE=1
5916                         gpuTemp=""
5917                         separator=""
5918                 }
5919                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
5920                         while ( getline && !/^$/  ) {
5921                                 if ( /^temp/ ) {
5922                                         sub(/^[[:alnum:]]*.*:/, "", $0 ) # clear out everything to the :
5923                                         gsub(/[\+ \t°]/, "", $1) # Â° is a special case, like a space for gawk
5924                                         gpuTemp=gpuTemp separator $1
5925                                         separator=","
5926                                 }       
5927                         }
5928                 }
5929                 END {
5930                         print gpuTemp
5931                 }' <<< "$Sensors_Data" )
5932         fi
5933         
5934         if [[ -n $gpu_temp ]];then
5935                 echo $gpu_temp
5936         fi
5937 }
5938
5939 ## for possible future data, not currently used
5940 get_graphics_agp_data()
5941 {
5942         eval $LOGFS
5943         local agp_module=''
5944
5945         if [[ $B_MODULES_FILE == 'true' ]];then
5946                 ## not used currently
5947                 agp_module=$( gawk '
5948                 /agp/ && !/agpgart/ && $3 > 0 {
5949                         print(gensub(/(.*)_agp.*/,"\\1","g",$1))
5950                 }' $FILE_MODULES )
5951                 log_function_data 'cat' "$FILE_MODULES"
5952         fi
5953         log_function_data "agp_module: $agp_module"
5954         eval $LOGFE
5955 }
5956
5957 ## create array of gfx cards installed on system
5958 get_graphics_card_data()
5959 {
5960         eval $LOGFS
5961         local i='' a_temp=''
5962
5963         IFS=$'\n'
5964         A_GRAPHICS_CARD_DATA=( $( gawk -F': ' '
5965         BEGIN {
5966                 IGNORECASE=1
5967                 busId=""
5968                 trueCard=""
5969         }
5970         # not using 3D controller yet, needs research: |3D controller |display controller
5971         # note: this is strange, but all of these can be either a separate or the same
5972         # card. However, by comparing bus id, say: 00:02.0 we can determine that the
5973         # cards are  either the same or different. We want only the .0 version as a valid
5974         # card. .1 would be for example: Display Adapter with bus id x:xx.1, not the right one
5975         /vga compatible controller|3D controller|Display controller/ {
5976                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF)
5977                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", $NF)
5978                 gsub(/^ +| +$/, "", $NF)
5979                 gsub(/ [ \t]+/, " ", $NF)
5980                 busId=gensub(/^([0-9a-f:\.]+) (.+)$/,"\\1","",$1)
5981                 trueCard=gensub(/(.*)\.([0-9]+)$/,"\\2","",busId)
5982                 if ( trueCard == 0 ) {
5983                         print $NF "," busId
5984                 }
5985         }' <<< "$Lspci_v_Data" ) )
5986         IFS="$ORIGINAL_IFS"
5987 #       for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
5988 #       do
5989 #               A_GRAPHICS_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GRAPHICS_CARD_DATA[i]}" )
5990 #       done
5991
5992         # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory..
5993         # GFXMEM="size=[$(echo "$Lspci_v_Data" | gawk '/VGA/{while (!/^$/) {getline;if (/size=[0-9][0-9]*M/) {size2=gensub(/.*\[size=([0-9]+)M\].*/,"\\1","g",$0);if (size<size2){size=size2}}}}END{print size2}')M]"
5994         a_temp=${A_GRAPHICS_CARD_DATA[@]}
5995         log_function_data "A_GRAPHICS_CARD_DATA: $a_temp"
5996         eval $LOGFE
5997 }
5998
5999 get_graphics_driver()
6000 {
6001         eval $LOGFS
6002         
6003         # list is from sgfxi plus non-free drivers
6004         local driver_list='amdgpu|apm|ark|ati|chips|cirrus|cyrix|fbdev|fglrx|glint|i128|i740|intel|i810|imstt|mach64|mga|neomagic|nsc|nvidia|nv|openchrome|nouveau|radeon|radeonhd|rendition|s3virge|s3|savage|siliconmotion|sisusb|sis|tdfx|tga|trident|tseng|unichrome|vboxvideo|vesa|vga|via|voodoo|vmware|v4l'
6005         local driver='' driver_string='' xorg_log_data='' status='' a_temp=''
6006
6007         if [[ $B_XORG_LOG == 'true' ]];then
6008                 A_GRAPHIC_DRIVERS=( $(
6009                 gawk '
6010                 BEGIN {
6011                         driver=""
6012                         bLoaded="false"
6013                         IGNORECASE=1
6014                 }
6015                 # note that in file names, driver is always lower case
6016                 /[[:space:]]Loading.*('"$driver_list"')_drv.so$/ {
6017                         driver=gensub(/.*[[:space:]]Loading.*('"$driver_list"')_drv.so/, "\\1", 1, $0 )
6018                         # we get all the actually loaded drivers first, we will use this to compare the
6019                         # failed/unloaded, which have not always actually been truly loaded
6020                         aDrivers[driver]="loaded" 
6021                 }
6022                 # openbsd uses UnloadModule: 
6023                 /(Unloading[[:space:]]|UnloadModule).*('"$driver_list"')(\"||_drv.so)$/ {
6024                         gsub(/\"/,"",$0)
6025                         driver=gensub(/(.*)(Unloading[[:space:]]|UnloadModule).*('"$driver_list"')(\"||_drv.so)$/, "\\3", 1, $0 )
6026                         # we need to make sure that the driver has already been truly loaded, not just discussed
6027                         if ( driver in aDrivers ) {
6028                                 aDrivers[driver]="unloaded"
6029                         }
6030                 }
6031                 /Failed.*('"$driver_list"')_drv.so|Failed.*\"('"$driver_list"')\"/ {
6032                         driver=gensub(/(.*)Failed.*('"$driver_list"')_drv.so/, "\\2", 1, $0 )
6033                         if ( driver == $0 ) {
6034                                 driver=gensub(/(.*)Failed.*\"('"$driver_list"')\".*|fred/, "\\2", 1, $0 )
6035                         }
6036                         # we need to make sure that the driver has already been truly loaded, not just discussed
6037                         if ( driver != $0 && driver in aDrivers ) {
6038                                 aDrivers[driver]="failed"
6039                         }
6040                 }
6041                 # verify that the driver actually started the desktop, even with false failed messages which can occur
6042                 # this is the driver that is actually driving the display
6043                 /.*\([0-9]+\):[[:space:]]Depth.*framebuffer/ {
6044                         driver=gensub(/.*('"$driver_list"')\([0-9]+\):[[:space:]]Depth.*framebuffer.*/, "\\1", 1, $0 )
6045                         # we need to make sure that the driver has already been truly loaded, not just discussed, also
6046                         # set driver to lower case because sometimes it will show as RADEON or NVIDIA in the actual x start
6047                         driver=tolower(driver)
6048                         if ( driver != $0 && driver in aDrivers ) {
6049                                 aDrivers[driver]="loaded"
6050                         }
6051                 }
6052                 END {
6053                         for ( driver in aDrivers ) {
6054                                 print driver "," aDrivers[driver]
6055                         }
6056                 }' < $FILE_XORG_LOG ) )
6057         fi
6058         a_temp=${A_GRAPHIC_DRIVERS[@]}
6059         log_function_data "A_GRAPHIC_DRIVERS: $a_temp"
6060         
6061         eval $LOGFE
6062 }
6063
6064 ## create array of glx data
6065 get_graphics_glx_data()
6066 {
6067         eval $LOGFS
6068         local a_temp=''
6069         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
6070                 IFS=$'\n'
6071                 A_GLX_DATA=( $( glxinfo | gawk -F ': ' '
6072                 # note: function declarations go before BEGIN? It appears so, confirm.
6073                 # the real question here though is why this function is even here, seems
6074                 # just to be a complicated way to pack/print a variable, but maybe the
6075                 # original idea was to handle > 1 cases of detections I guess
6076                 function join( arr, sep ) {
6077                         s=""
6078                         i=flag=0
6079                         for ( i in arr ) {
6080                                 if ( flag++ ) {
6081                                         s = s sep
6082                                 }
6083                                 s = s i
6084                         }
6085                         return s
6086                 }
6087
6088                 BEGIN {
6089                         IGNORECASE=1
6090                 }
6091                 /opengl renderer/ {
6092                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $2)
6093                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
6094                         gsub(/^ +| +$/, "", $2)
6095                         if ( $2 ~ /mesa/ ) {
6096                                 # Allow all mesas
6097 #                               if ( $2 ~ / r[3-9][0-9][0-9] / ) {
6098                                         a[$2]
6099                                         # this counter failed in one case, a bug, and is not needed now
6100 #                                       f++
6101 #                               }
6102                                 next
6103                         }
6104                         
6105                         $2 && a[$2]
6106                 }
6107                 # dropping all conditions from this test to just show full mesa information
6108                 # there is a user case where not f and mesa apply, atom mobo
6109                 # /opengl version/ && ( f || $2 !~ /mesa/ ) {
6110                 /opengl version/ {
6111                         # fglrx started appearing with this extra string, does not appear to communicate anything of value
6112                         sub(/Compatibility Profile Context/, "- CPC", $2 )
6113                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
6114                         gsub(/^ +| +$/, "", $2)
6115                         $2 && b[$2]
6116                 }
6117                 /direct rendering/ {
6118                         $2 && c[$2]
6119                 }
6120                 END {
6121                         printf( "%s\n%s\n%s\n", join( a, ", " ), join( b, ", " ), join( c, ", " ) )
6122                 }' ) )
6123                 IFS="$ORIGINAL_IFS"
6124
6125                 # GLXR=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl renderer/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
6126                 #    GLXV=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl version/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
6127         fi
6128         a_temp=${A_GLX_DATA[@]}
6129         log_function_data "A_GLX_DATA: $a_temp"
6130         eval $LOGFE
6131 }
6132
6133 ## return screen resolution / tty resolution
6134 get_graphics_res_data()
6135 {
6136         eval $LOGFS
6137         local screen_resolution='' xdpy_data='' screens_count=0 tty_session=''
6138
6139         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
6140                 # Added the two ?'s , because the resolution is now reported without spaces around the 'x', as in
6141                 # 1400x1050 instead of 1400 x 1050. Change as of X.org version 1.3.0
6142                 xdpy_data="$( xdpyinfo )"
6143                 xdpy_count=$( grep -c 'dimensions' <<< "$xdpy_data" )
6144                 # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
6145                 # multiple screens from different video cards
6146                 if [[ $xdpy_count -eq 1 ]];then
6147                         screen_resolution=$( xrandr | gawk '
6148                         /\*/ {
6149                                 res[++m] = gensub(/^.* ([0-9]+) ?x ?([0-9]+)[_ ].* ([0-9\.]+)\*.*$/,"\\1x\\2@\\3hz","g",$0)
6150                         }
6151                         END {
6152                                 for (n in res) {
6153                                         if (res[n] ~ /^[[:digit:]]+x[[:digit:]]+/) {
6154                                                 line = line ? line ", " res[n] : res[n]
6155                                         }
6156                                 }
6157                                 if (line) {
6158                                         print(line)
6159                                 }
6160                         }' )
6161                 fi
6162                 if [[ -z $screen_resolution || $xdpy_count -gt 1 ]];then
6163                         screen_resolution=$( gawk '
6164                         BEGIN {
6165                                 IGNORECASE=1
6166                                 screens = ""
6167                                 separator = ""
6168                         }
6169                         /dimensions/ {
6170                                 screens = screens separator # first time, this is null, next, has comma last
6171                                 screens = screens $2 # then tack on the new value for nice comma list
6172                                 separator = ", "
6173                         }
6174                         END {
6175                                 print screens
6176                         }' <<< "$xdpy_data" )
6177                 fi
6178         else
6179                 if [[ $B_PROC_DIR == 'true' && -z $BSD_TYPE ]];then
6180                         screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{
6181                                 print $2"x"$1
6182                         }' )
6183                 # note: this works fine for all systems but keeping the above for now since
6184                 # the above is probably more accurate for linux systems.
6185                 else
6186                         if [[ $B_CONSOLE_IRC != 'true' ]];then
6187                                 screen_resolution=$( stty -a | gawk -F ';' '
6188                                         /^speed/ {
6189                                                 gsub(/[[:space:]]*(rows|columns)[[:space:]]*/,"",$0)
6190                                                 gsub(/[[:space:]]*/,"",$2)
6191                                                 gsub(/[[:space:]]*/,"",$3)
6192                                                 print $3"x"$2
6193                                         }' )
6194                         else
6195                                 if [[ -n $BSD_TYPE ]];then
6196                                         tty_session=$( get_tty_console_irc )
6197                                         # getting information for tty that owns the irc client
6198                                         screen_resolution="$( stty -f /dev/pts/$tty_session size | gawk '{print $2"x"$1}' )"
6199                                 fi
6200                         fi
6201                 fi
6202         fi
6203         echo "$screen_resolution"
6204         log_function_data "screen_resolution: $screen_resolution"
6205         eval $LOGFE
6206 }
6207
6208 ## create array of display server vendor/version data
6209 get_graphics_display_server_data()
6210 {
6211         eval $LOGFS
6212         local vendor='' version='' a_temp='' xdpy_info='' a_display_vendor_working=''
6213
6214         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
6215                 # X vendor and version detection.
6216                 # new method added since radeon and X.org and the disappearance of <X server name> version : ...etc
6217                 # Later on, the normal textual version string returned, e.g. like: X.Org version: 6.8.2
6218                 # A failover mechanism is in place. (if $version is empty, the release number is parsed instead)
6219                 # xdpy_info="$( xdpyinfo )"
6220                 IFS=","
6221                 a_display_vendor_working=( $( xdpyinfo | gawk -F': +' '
6222                 BEGIN {
6223                         IGNORECASE=1
6224                         vendorString=""
6225                         version=""
6226                         vendorRelease=""
6227                 }
6228                 /vendor string/ {
6229                         gsub(/the|inc|foundation|project|corporation/, "", $2)
6230                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $2)
6231                         gsub(/^ +| +$/, "", $2)
6232                         gsub(/ [ \t]+/, " ", $2)
6233                         vendorString = $2
6234                 }
6235                 /version:/ {
6236                         version = $NF
6237                 }
6238                 /vendor release number/ {
6239                         gsub(/0+$/, "", $2)
6240                         gsub(/0+/, ".", $2)
6241                         vendorRelease = $2
6242                 }
6243                 END {
6244                         print vendorString "," version "," vendorRelease
6245                 }' ) )
6246                 vendor=${a_display_vendor_working[0]}
6247                 version=${a_display_vendor_working[1]}
6248
6249                 # this gives better output than the failure last case, which would only show:
6250                 # for example: X.org: 1.9 instead of: X.org: 1.9.0
6251                 if [[ -z $version ]];then
6252                         version=$( get_graphics_display_server_version )
6253                 fi
6254                 if [[ -z $version ]];then
6255                         version=${a_display_vendor_working[2]}
6256                 fi
6257                 
6258                 # some distros, like fedora, report themselves as the xorg vendor, so quick check
6259                 # here to make sure the vendor string includes Xorg in string
6260                 if [[ -z $( grep -E '(X|xorg|x\.org)' <<< $vendor ) ]];then
6261                         vendor="$vendor X.org"
6262                 fi
6263                 IFS="$ORIGINAL_IFS"
6264                 A_DISPLAY_SERVER_DATA[0]="$vendor"
6265                 A_DISPLAY_SERVER_DATA[1]="$version"
6266         else
6267                 version=$( get_graphics_display_server_version )
6268                 if [[ -n $version ]];then
6269                         vendor='X.org'
6270                         A_DISPLAY_SERVER_DATA[0]="$vendor"
6271                         A_DISPLAY_SERVER_DATA[1]="$version"
6272                 fi
6273         fi
6274         a_temp=${A_DISPLAY_SERVER_DATA[@]}
6275         log_function_data "A_DISPLAY_SERVER_DATA: $a_temp"
6276         eval $LOGFE
6277 }
6278
6279 # if other tests fail, try this one, this works for root, out of X also
6280 get_graphics_display_server_version()
6281 {
6282         eval $LOGFS
6283         local version='' x_data=''
6284         # note that some users can have /usr/bin/Xorg but not /usr/bin/X
6285         if type -p X &>/dev/null;then
6286                 # note: MUST be this syntax: X -version 2>&1
6287                 # otherwise X -version overrides everything and this comes out null.
6288                 # two knowns id strings: X.Org X Server 1.7.5 AND X Window System Version 1.7.5
6289                 #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }'
6290                 x_data="$( X -version 2>&1 )"
6291         elif type -p Xorg &>/dev/null;then
6292                 x_data="$( Xorg -version 2>&1)"
6293         fi
6294         if [[ -n $x_data ]];then
6295                 version=$( 
6296                 gawk '
6297                 BEGIN {
6298                         IGNORECASE=1
6299                 }
6300                 /^x.org x server/ {
6301                         print $4
6302                         exit
6303                 }
6304                 /^X Window System Version/ {
6305                         print $5
6306                         exit
6307                 }' <<< "$x_data" )
6308         fi
6309         echo $version
6310         log_function_data " version: $version"
6311         eval $LOGFE
6312 }
6313
6314 # this gets just the raw data, total space/percent used and disk/name/per disk capacity
6315 get_hdd_data_basic()
6316 {
6317         eval $LOGFS
6318         local hdd_used='' a_temp='' df_string=''
6319         local hdd_data='' df_test='' swap_size=0
6320         
6321         if [[ -z $BSD_TYPE ]];then
6322                 ## NOTE: older df do not have --total (eg: v: 6.10 2008)
6323                 ## keep in mind the only value of use with --total is 'used' in blocks, which
6324                 ## we can use later to calculate the real percentags based on disk sizes, not
6325                 ## mounted partitions. Not using --total because it's more reliable to exclude non /dev
6326                 df_string="df -P -T --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs 
6327                 --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=nfs
6328                 --exclude-type=nfs3 --exclude-type=nfs4 --exclude-type=nfs5 --exclude-type=procfs  --exclude-type=smbfs
6329                 --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs"
6330                 if swapon -s &>/dev/null;then
6331                         swap_size=$( swapon -s 2>/dev/null | gawk '
6332                         BEGIN { 
6333                         swapSize=0
6334                         total=0
6335                         }
6336                         ( $2 == "partition" ) && ( $3 ~ /^[0-9]+$/ ) {
6337                                 total += ( 1000 / 1024 ) * $3
6338                         }
6339                         END {
6340                                 # result in kB, change to 1024 Byte blocks
6341                                 total = total * 1000 / 1024
6342                                 total = sprintf( "%.1f", total )
6343                                 print total
6344                         }' )
6345                 fi
6346         else
6347                 # default size is 512, , so use -k for 1024 -H only for size in human readable format
6348                 # older bsds don't support -T, pain, so we'll use partial output there
6349                 if df -k -T &>/dev/null;then
6350                         df_string='df -k -T'
6351                 else
6352                         df_string='df -k'
6353                 fi
6354                 if swapctl -l -k &>/dev/null;then
6355                         swap_size=$( swapctl -l -k 2>/dev/null | gawk '
6356                         BEGIN { 
6357                         swapSize=0
6358                         total=0
6359                         }
6360                         ( $1 ~ /^\/dev/ ) && ( $2 ~ /^[0-9]+$/ ) {
6361                                 total += $2
6362                         }
6363                         END {
6364                                 # result in blocks already
6365                                 print total
6366                         }' )
6367                 fi
6368         fi
6369         # echo ss: $swap_size
6370         hdd_data="$( eval $df_string )"
6371         # eval $df_string | awk 'BEGIN{tot=0} !/total/ {tot+=$4} END{print tot}'
6372         log_function_data 'raw' "hdd_data:\n$hdd_data"
6373         hdd_used=$( echo "$hdd_data" | gawk -v bsdType="$BSD_TYPE" -v swapSize="$swap_size" '
6374         BEGIN {
6375                 # this is used for specific cases where bind, or incorrect multiple mounts to same partitions,
6376                 # is present. The value is searched for an earlier appearance of that partition and if it is 
6377                 # present, the data is not added into the partition used size.
6378                 partitionsSet=""
6379                 # this handles a case where the same dev item is mounted twice to different points
6380                 devSet=""
6381                 devWorking=""
6382                 mountWorking=""
6383                 used=0
6384         }
6385         # using $1, not $2, because older bsd df do not have -T, filesystem type
6386         ( bsdType != "" ) && $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|filesystem|iso9660|linprocfs|nfs|nfs3|nfs4|nfs5|procfs|squashfs|smbfs|sysfs|tmpfs|type|unionfs)$/ {
6387                 # note use next, not getline or it does not work right
6388                 next 
6389         }
6390         # also handles odd dm-1 type, from lvm, and mdraid, and some other bsd partition syntax
6391         # note that linux 3.2.45-grsec-9th types kernels have this type of partition name: /dev/xvdc (no number, letter)
6392         # note: btrfs does not seem to use partition integers, just the primary /dev/sdx identifier
6393         # df can also show /dev/disk/(by-label|by-uuid etc)
6394         /^\/dev\/(disk\/|mapper\/|[hsv]d[a-z]+[0-9]*|dm[-]?[0-9]+|(ada|mmcblk|nvme[0-9]+n)[0-9]+p[0-9]+.*|(ad|sd|wd)[0-9]+[a-z]|md[0-9]+|[aw]d[0-9]+s.*|xvd[a-z]+)|^ROOT/ {
6395                 # this handles the case where the first item is too long
6396                 # and makes df wrap output to next line, so here we advance
6397                 # it to the next line for that single case. Using df -P should
6398                 # make this unneeded but leave it in just in case
6399                 if ( NF < 6 && $0 !~ /.*%/ ) {
6400                         devSet = devSet "~" $1 "~"
6401                         getline
6402                 }
6403                 # if the first item caused a wrap, use one less than standard
6404                 # testing for the field with % in it, ie: 34%, then go down from there
6405                 # this also protects against cases where the mount point has a space in the
6406                 # file name, thus breaking going down from $NF directly.
6407                 # some bsds will also have only 6 items
6408                 if ( $5 ~ /.*%/ ) {
6409                         devWorking="~" $1 "~"
6410                         mountWorking="~" $6 "~"
6411                         if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
6412                                 used += $3
6413                         }
6414                         partitionsSet = partitionsSet mountWorking
6415                         # make sure to only include bsd real lines here, ie, short df output
6416                         if ( $1 ~ /^\/dev\// ) {
6417                                 devSet = devSet devWorking
6418                         }
6419                 }
6420                 # otherwise use standard
6421                 else if ( $6 ~ /.*%/ ) {
6422                         devWorking="~" $1 "~"
6423                         mountWorking="~" $7 "~"
6424                         if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
6425                                 used += $4
6426                         }
6427                         partitionsSet = partitionsSet mountWorking
6428                         devSet = devSet devWorking
6429                 }
6430                 # and if this is not detected, give up, we need user data to debug
6431                 else {
6432                         next
6433                 }
6434         }
6435         END {
6436                 used=used + swapSize
6437                 used = sprintf( "%.1f", used )
6438                 print used 
6439         }' )
6440         # echo hdu:$hdd_used
6441         if [[ -z $hdd_used ]];then
6442                 hdd_used='na'
6443         fi
6444         log_function_data "hdd_used: $hdd_used"
6445         # create the initial array strings:
6446         # disk-dev, capacity, name, usb or not
6447         # final item is the total of the disk
6448         IFS=$'\n'
6449
6450         if [[ $B_PARTITIONS_FILE == 'true' ]];then
6451                 A_HDD_DATA=( $(
6452                 gawk -v hddUsed=$hdd_used '
6453                 /([hsv]d[a-z]+|(ada|mmcblk|nvme[0-9]+n)[0-9]+)$/ {
6454                         driveSize = $(NF - 1)*1024/1000**3
6455                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", driveSize)
6456                         gsub(/^ +| +$/, "", driveSize)
6457                         printf( $NF",%.1fGB,,\n", driveSize )
6458                 }
6459                 # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below
6460                 # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0  {
6461                 #       size += $3
6462                 # }
6463                 # special case from this data: 8     0  156290904 sda
6464                 # note: vm has 252/253/254 known starter, grsec has 202
6465                 $1 ~ /^(3|8|22|33|202|252|253|254)$/ && $NF ~ /[hsv]d[a-z]+$/ && ( $2 % 16 == 0 || $2 % 16 == 8 ) {
6466                         size += $3
6467                 }
6468                 END {
6469                         size = size*1024/1000**3                   # calculate size in GB size
6470                         workingUsed = hddUsed*1024/1000**3         # calculate workingUsed in GB used
6471                         # this handles a special case with livecds where no hdd_used is detected
6472                         if ( size > 0 && hddUsed == "na" ) {
6473                                 size = sprintf( "%.1f", size )
6474                                 print size "GB,-,,.."
6475                         }
6476                         else if ( size > 0 && workingUsed > 0 ) {
6477                                 diskUsed = workingUsed*100/size  # calculate used percentage
6478                                 diskUsed = sprintf( "%.1f", diskUsed )
6479                                 if ( int(diskUsed) > 100 ) {
6480                                         diskUsed = "Used Error!"
6481                                 }
6482                                 else {
6483                                         diskUsed = diskUsed "% used"
6484                                 }
6485                                 size = sprintf( "%.1f", size )
6486                                 print size "GB," diskUsed ",,.." 
6487                         }
6488                         else {
6489                                 print "NA,-,,.." # print an empty array, this will be further handled in the print out function
6490                         }
6491                 }' $FILE_PARTITIONS ) )
6492                 log_function_data 'cat' "$FILE_PARTITIONS"
6493         else
6494                 if [[ -n $BSD_TYPE ]];then
6495                         get_hard_drive_data_bsd "$hdd_used"
6496                 fi
6497         fi
6498         IFS="$ORIGINAL_IFS"
6499         a_temp=${A_HDD_DATA[@]}
6500         # echo ${a_temp[@]}
6501         log_function_data "A_HDD_DATA: $a_temp"
6502         eval $LOGFE
6503 }
6504
6505 ## fills out the A_HDD_DATA array with disk names
6506 get_hard_drive_data_advanced()
6507 {
6508         eval $LOGFS
6509         local a_temp_working='' a_temp_scsi='' temp_holder='' temp_name='' i='' j=''
6510         local sd_ls_by_id='' ls_disk_by_id='' ls_disk_by_path='' usb_exists='' a_temp=''
6511         local firewire_exists='' thunderbolt_exists='' thunderbolt_exists='' hdd_temp hdd_serial=''
6512
6513         ## check for all ide type drives, non libata, only do it if hdx is in array
6514         ## this is now being updated for new /sys type paths, this may handle that ok too
6515         if [[ -n $( grep -E 'hd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
6516                 # remember, we're using the last array item to store the total size of disks
6517                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
6518                 do
6519                         IFS=","
6520                         a_temp_working=( ${A_HDD_DATA[i]} )
6521                         IFS="$ORIGINAL_IFS"
6522                         if [[ -n $( grep -E '^hd[a-z]' <<< ${a_temp_working[0]} ) ]];then
6523                                 if [[ -e /proc/ide/${a_temp_working[0]}/model ]];then
6524                                         a_temp_working[2]="$( remove_erroneous_chars /proc/ide/${a_temp_working[0]}/model )"
6525                                 else
6526                                         a_temp_working[2]="Name n/a"
6527                                 fi
6528                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
6529                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
6530                                 do
6531                                         if [[ $j -gt 0 ]];then
6532                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
6533                                         else
6534                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
6535                                         fi
6536                                 done
6537                         fi
6538                 done
6539         fi
6540
6541         ## then handle libata names
6542         # first get the ata device names, put them into an array
6543         IFS=$'\n'
6544         if [[ $B_SCSI_FILE == 'true' ]]; then
6545                 a_temp_scsi=( $( gawk  '
6546                 BEGIN {
6547                         IGNORECASE=1
6548                 }
6549                 /host/ {
6550                         getline a[$0]
6551                         getline b[$0]
6552                 }
6553                 END {
6554                         for (i in a) {
6555                                 if (b[i] ~ / *type: *direct-access.*/) {
6556                                         #c=gensub(/^ *vendor: (.+) +model: (.+) +rev: (.+)$/,"\\1 \\2 \\3","g",a[i])
6557                                         #c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/,"\\1 \\2","g",a[i] )
6558                                         # the vendor: string is useless, and is a bug, ATA is not a vendor for example
6559                                         c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/, "\\2", "g", a[i] )
6560                                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", c)
6561                                         gsub(/^ +| +$/, "", c)
6562                                         gsub(/ [ \t]+/, " ", c)
6563                                         #print a[i]
6564                                         # we actually want this data, so leaving this off for now
6565 #                                       if (c ~ /\<flash\>|\<pendrive\>|memory stick|memory card/) {
6566 #                                               continue
6567 #                                       }
6568                                         print c
6569                                 }
6570                         }
6571                 }' $FILE_SCSI ) )
6572                 log_function_data 'cat' "$FILE_SCSI"
6573         fi
6574         IFS="$ORIGINAL_IFS"
6575
6576         ## then we'll loop through that array looking for matches.
6577         if [[ -n $( grep -E 'sd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
6578                 # first pack the main ls variable so we don't have to keep using ls /dev...
6579                 # not all systems have /dev/disk/by-id
6580                 ls_disk_by_id="$( ls -l /dev/disk/by-id 2>/dev/null )"
6581                 ls_disk_by_path="$( ls -l /dev/disk/by-path 2>/dev/null )"
6582                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
6583                 do
6584                         if [[ -n $( grep -E '^sd[a-z]' <<< ${A_HDD_DATA[$i]} ) ]];then
6585                                 IFS=","
6586                                 a_temp_working=( ${A_HDD_DATA[$i]} )
6587                                 IFS="$ORIGINAL_IFS"
6588                                 # /sys/block/[sda,hda]/device/model
6589                                 # this is handles the new /sys data types first
6590                                 if [[ -e /sys/block/${a_temp_working[0]}/device/model ]];then
6591                                         temp_name="$( remove_erroneous_chars /sys/block/${a_temp_working[0]}/device/model )"
6592                                         temp_name=$( cut -d '-' -f 1 <<< ${temp_name// /_} )
6593                                 elif [[ ${#a_temp_scsi[@]} -gt 0 ]];then
6594                                         for (( j=0; j < ${#a_temp_scsi[@]}; j++ ))
6595                                         do
6596                                                 ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the
6597                                                 # discovered disk name AND ends with the correct identifier, sdx
6598                                                 # get rid of whitespace for some drive names and ids, and extra data after - in name
6599                                                 temp_name=$( cut -d '-' -f 1 <<< ${a_temp_scsi[$j]// /_} )
6600                                                 sd_ls_by_id=$( grep -Em1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
6601                                                 if [[ -n $sd_ls_by_id ]];then
6602                                                         temp_name=${a_temp_scsi[$j]}
6603                                                         break
6604                                                 else
6605                                                         # test to see if we can get a better name output when null
6606                                                         if [[ -n $temp_name ]];then
6607                                                                 temp_name=$temp_name
6608                                                         fi
6609                                                 fi
6610                                         done
6611                                 fi
6612                                 
6613                                 if [[ -z $temp_name ]];then
6614                                         temp_name="Name n/a"
6615                                 # maybe remove this from the conditional, detection of usb may not depend on the name
6616                                 else # 
6617                                         usb_exists=$( grep -Em1 "usb-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
6618                                         firewire_exists=$( grep -Em1 "ieee1394-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
6619                                         # thunderbolt_exists=$( grep -Em1 "ieee1394-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
6620                                         # note: sometimes with wwn- numbering usb does not appear in by-id but it does in by-path
6621                                         if [[ -z $usb_exists ]];then
6622                                                 usb_exists=$( grep -Em1 "usb-.*${a_temp_working[0]}$" <<< "$ls_disk_by_path" )
6623                                         fi
6624                                         if [[ -n $usb_exists ]];then
6625                                                 a_temp_working[3]='USB'
6626                                         fi
6627                                         if [[ -z $firewire_exists ]];then
6628                                                 firewire_exists=$( grep -Em1 "ieee1394-.*${a_temp_working[0]}$" <<< "$ls_disk_by_path" )
6629                                         fi
6630                                         if [[ -n $firewire_exists ]];then
6631                                                 a_temp_working[3]='FireWire'
6632                                         fi
6633                                 fi
6634                                 a_temp_working[2]=$temp_name
6635                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
6636                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
6637                                 do
6638                                         if [[ $j -gt 0 ]];then
6639                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
6640                                         else
6641                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
6642                                         fi
6643                                 done
6644                         fi
6645                         if [[ $B_EXTRA_DATA == 'true' ]];then
6646                                 IFS=","
6647                                 a_temp_working=( ${A_HDD_DATA[i]} )
6648                                 # echo "a:" ${a_temp_working[@]}
6649                                 IFS="$ORIGINAL_IFS"
6650                                 hdd_temp=''
6651                                 hdd_serial=''
6652                                 if [[ -n ${a_temp_working[1]} ]];then
6653                                         hdd_temp=$( get_hdd_temp_data "/dev/${a_temp_working[0]}" )
6654                                 fi
6655                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
6656                                         hdd_serial=$( get_hdd_serial_number "${a_temp_working[0]}" )
6657                                 fi
6658                                 A_HDD_DATA[i]="${a_temp_working[0]},${a_temp_working[1]},${a_temp_working[2]},${a_temp_working[3]},$hdd_serial,$hdd_temp"
6659                                 # echo b: ${A_HDD_DATA[i]}
6660                         fi
6661                 done
6662         fi
6663         a_temp=${A_HDD_DATA[@]}
6664         log_function_data "A_HDD_DATA: $a_temp"
6665         eval $LOGFE
6666 }
6667
6668 # args: $1 ~ hdd_used
6669 get_hard_drive_data_bsd()
6670 {
6671         eval $LOGFS
6672         
6673         local a_temp=''
6674         
6675         if [[ -n $Dmesg_Boot_Data ]];then
6676                 IFS=$'\n'
6677                 A_HDD_DATA=( $( gawk -v hddUsed="$1" -F ':' '
6678                 BEGIN {
6679                         IGNORECASE=1
6680                         size=0
6681                         bSetSize="false"
6682                 }
6683                 $1 ~ /^(ad|ada|mmcblk|nvme[0-9]+n|sd|wd)[0-9]+(|[[:space:]]at.*)$/ {
6684                         diskId=gensub(/^((ad|ada|mmcblk|nvme[0-9]+n|sd|wd)[0-9]+)[^0-9].*/,"\\1",1,$1)
6685                         # note: /var/run/dmesg.boot may repeat items since it is not created
6686                         # fresh every boot, this way, only the last items will be used per disk id
6687                         if (aIds[diskId] == "" ) {
6688                                 aIds[diskId]=diskId
6689                                 if ( $0 !~ /raid/) { 
6690                                         bSetSize="true"
6691                                 }
6692                         }
6693                         aDisks[diskId, "id"] = diskId
6694                         if ($0 ~ /[^0-9][0-9\.]+[[:space:]]*[MG]B/ && $0 !~ /MB\/s/) {
6695                                 workingSize=gensub(/.*[^0-9]([0-9\.]+[[:space:]]*[MG]B).*/,"\\1",1,$0)
6696                                 if (workingSize ~ /GB/ ) {
6697                                         sub(/[[:space:]]*GB/,"",workingSize)
6698                                         workingSize=workingSize*1000
6699                                 }
6700                                 else if (workingSize ~ /MB/ ) {
6701                                         sub(/[[:space:]]*MB/,"",workingSize)
6702                                         workingSize=workingSize
6703                                 }
6704                                 aDisks[diskId, "size"] = workingSize
6705                                 if ( bSetSize == "true" ) {
6706                                         if ( workingSize != "" ){
6707                                                 size=size+workingSize
6708                                                 bSetSize="false"
6709                                         }
6710                                 }
6711                         }
6712                         if ( $NF ~ /<.*>/ ){
6713                                 gsub(/.*<|>.*/,"",$NF)
6714                                 aDisks[diskId, "model"] = $NF
6715                         }
6716                         if ( $NF ~ /serial number/ ){
6717                                 sub(/serial[[:space:]]+number[[:space:]]*/,"",$NF)
6718                                 aDisks[diskId, "serial"] = $NF
6719                         }
6720                 }
6721                 END {
6722                         # sde,3.9GB,STORE_N_GO,USB,C200431546D3CF49-0:0,0
6723                         # sdd,250.1GB,ST3250824AS,,9ND08GKX,45
6724                         # multi dimensional pseudo arrays are sorted at total random, not in order of
6725                         # creation, so force a sort of the aIds, which deletes the array index but preserves
6726                         # the sorted keys.
6727                         asort(aIds) 
6728                         
6729                         for ( key in aIds ) {
6730                                 # we are not adding to size above for raid, and we do not print it for raid
6731                                 # this is re openbsd raid, which uses sd0 for raid array, even though sd is for scsi
6732                                 if ( aDisks[aIds[key], "model"] !~ /raid/ ) {
6733                                         workingSize = aDisks[aIds[key], "size"]/1000
6734                                         workingSize = sprintf( "%.1fGB", workingSize )
6735                                         print aDisks[aIds[key], "id"] "," workingSize "," aDisks[aIds[key], "model"] "," "," aDisks[aIds[key], "serial"] "," 
6736                                 }
6737                         }
6738                         size = size/1000                # calculate size in GB size
6739                         # in kb
6740                         workingUsed = hddUsed*1024/1000**3         # calculate workingUsed in GB used
6741                         # this handles a special case with livecds where no hdd_used is detected
6742                         if ( size > 0 && hddUsed == "na" ) {
6743                                 size = sprintf( "%.1f", size )
6744                                 print size "GB,-,,.."
6745                         }
6746                         else if ( size > 0 && workingUsed > 0 ) {
6747                                 diskUsed = workingUsed*100/size  # calculate used percentage
6748                                 diskUsed = sprintf( "%.1f", diskUsed )
6749                                 if ( int(diskUsed) > 100 ) {
6750                                         diskUsed = "Used Error!"
6751                                 }
6752                                 else {
6753                                         diskUsed = diskUsed "% used"
6754                                 }
6755                                 size = sprintf( "%.1f", size )
6756                                 print size "GB," diskUsed ",,.." 
6757                         }
6758                         else {
6759                                 print "NA,-,,.." # print an empty array, this will be further handled in the print out function
6760                         }
6761                 }' <<< "$Dmesg_Boot_Data" ) )
6762                 IFS="$ORIGINAL_IFS"
6763         fi
6764         
6765         a_temp=${A_HDD_DATA[@]}
6766         # echo ${a_temp[@]}
6767         log_function_data "A_HDD_DATA: $a_temp"
6768         
6769         eval $LOGFE
6770 }
6771
6772 # args: $1 - which drive to get serial number of
6773 get_hdd_serial_number()
6774 {
6775         eval $LOGFS
6776         
6777         local hdd_serial=''
6778         
6779         get_partition_dev_data 'id'
6780         
6781         # lrwxrwxrwx 1 root root  9 Apr 26 09:32 scsi-SATA_ST3160827AS_5MT2HMH6 -> ../../sdc
6782         # exit on the first instance
6783         hdd_serial=$( gawk '
6784         /'$1'$/ {
6785                 serial=gensub( /^(.+)_([^_]+)$/, "\\2", 1, $9 )
6786                 print serial
6787                 exit
6788         }' <<< "$DEV_DISK_ID" )
6789         
6790         echo $hdd_serial
6791         log_function_data "hdd serial: $hdd_serial"
6792         eval $LOGFE
6793 }
6794
6795 # a few notes, normally hddtemp requires root, but you can set user rights in /etc/sudoers.
6796 # args: $1 - /dev/<disk> to be tested for
6797 get_hdd_temp_data()
6798 {
6799         eval $LOGFS
6800         local hdd_temp='' sudo_command='' 
6801
6802         if [[ $B_HDDTEMP_TESTED != 'true' ]];then
6803                 B_HDDTEMP_TESTED='true'
6804                 HDDTEMP_PATH=$( type -p hddtemp )
6805         fi
6806         if [[ $B_SUDO_TESTED != 'true' ]];then
6807                 B_SUDO_TESTED='true'
6808                 SUDO_PATH=$( type -p sudo )
6809         fi
6810         
6811         if [[ -n $HDDTEMP_PATH && -n $1 ]];then
6812                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
6813                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
6814                 # important: -n makes it non interactive, no prompt for password
6815                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
6816                         sudo_command='sudo -n '
6817                 fi
6818                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
6819                 hdd_temp=$( eval $sudo_command $HDDTEMP_PATH -nq -u C $1 )
6820                 if [[ -n $hdd_temp && -n $( grep -E '^([0-9\.]+)$' <<< $hdd_temp ) ]];then
6821                         echo $hdd_temp
6822                 fi
6823         fi
6824         eval $LOGFE
6825 }
6826
6827 get_init_data()
6828 {
6829         eval $LOGFS
6830         
6831         local init_type='' init_version='' rc_type='' rc_version='' a_temp=''
6832         local ls_run='' strings_init_version=''
6833         local runlevel=$( get_runlevel_data )
6834         local default_runlevel=$( get_runlevel_default )
6835         
6836         # this test is pretty solid, if pid 1 is owned by systemd, it is systemd
6837         # otherwise that is 'init', which covers the rest of the init systems, I think anyway.
6838         # more data may be needed for other init systems.
6839         if [[ -e /proc/1/comm && -n $( grep -s 'systemd' /proc/1/comm ) ]];then
6840                 init_type='systemd'
6841                 if type -p systemd &>/dev/null;then
6842                         init_version=$( get_program_version 'systemd' '^systemd' '2' )
6843                 fi
6844                 if [[ -z $init_version ]];then
6845                         if type -p systemctl &>/dev/null;then
6846                                 init_version=$( get_program_version 'systemctl' '^systemd' '2' )
6847                         fi
6848                 fi
6849         else
6850                 ls_run=$(ls /run)
6851                 # note: upstart-file-bridge.pid upstart-socket-bridge.pid upstart-udev-bridge.pid
6852                 if [[ -n $( /sbin/init --version 2>/dev/null | grep 'upstart' ) ]];then
6853                         init_type='Upstart'
6854                         # /sbin/init --version == init (upstart 1.12.1)
6855                         init_version=$( get_program_version 'init' 'upstart' '3' )
6856                 elif [[ -e /proc/1/comm && -n $( grep -s 'epoch' /proc/1/comm ) ]];then
6857                         init_type='Epoch'
6858                         # epoch version == Epoch Init System 1.0.1 "Sage"
6859                         init_version=$( get_program_version 'epoch' '^Epoch' '4' )
6860                 # missing data: note, runit can install as a dependency without being the init system
6861                 # http://smarden.org/runit/sv.8.html
6862                 # NOTE: the proc test won't work on bsds, so if runit is used on bsds we will need more data
6863                 elif [[ -e /proc/1/comm && -n $( grep -s 'runit' /proc/1/comm ) ]];then
6864                 # elif [[ -e /sbin/runit-init || -e /etc/runit || -n $( type -p sv ) ]];then
6865                         init_type='runit' # lower case
6866                         # no data on version yet
6867                 # freebsd at least
6868                 elif type -p launchctl &>/dev/null;then
6869                         init_type='launchd'
6870                         #  / launchd/ version.plist /etc/launchd.conf
6871                         # init_version=$( get_program_version 'Launchd' '^Launchd' '4' )
6872                 elif [[ -f /etc/inittab ]];then
6873                         init_type='SysVinit'
6874                         if type -p strings &>/dev/null;then
6875                                 strings_init_version="$( strings /sbin/init | grep -E 'version[[:space:]]+[0-9]' )"
6876                         fi
6877                         if [[ -n $strings_init_version ]];then
6878                                 init_version=$( gawk '{print $2}' <<< "$strings_init_version" )
6879                         fi
6880                 elif [[ -f /etc/ttys ]];then
6881                         init_type='init (bsd)'
6882                 fi
6883                 if [[ -n $( grep 'openrc' <<< "$ls_run" ) ]];then
6884                         rc_type='OpenRC'
6885                         # /sbin/openrc --version == openrc (OpenRC) 0.13
6886                         if type -p openrc &>/dev/null;then
6887                                 rc_version=$( get_program_version 'openrc' '^openrc' '3' )
6888                         # /sbin/rc --version == rc (OpenRC) 0.11.8 (Gentoo Linux)
6889                         elif type -p rc &>/dev/null;then
6890                                 rc_version=$( get_program_version 'rc' '^rc' '3' )
6891                         fi
6892                         if [[ -e /run/openrc/softlevel ]];then
6893                                 runlevel=$( cat /run/openrc/softlevel 2>/dev/null )
6894                         elif [[ -e /var/run/openrc/softlevel ]];then
6895                                 runlevel=$( cat /var/run/openrc/softlevel 2>/dev/null )
6896                         elif type -p rc-status &>/dev/null;then
6897                                 runlevel=$( rc-status -r 2>/dev/null )
6898                         fi
6899                 ## assume sysvrc, but this data is too buggy and weird and inconsistent to have meaning
6900                 # leaving this off for now
6901 #               elif [[ -f /etc/inittab ]];then
6902 #                       rc_type='SysVrc'
6903 #                       # this is a guess that rc and init are same versions, may need updates / fixes
6904 #                       rc_version=$init_version
6905                 fi
6906         fi
6907         IFS=$'\n'
6908         
6909         A_INIT_DATA=( 
6910         "$init_type"
6911         "$init_version"
6912         "$rc_type"
6913         "$rc_version"
6914         "$runlevel"
6915         "$default_runlevel" )
6916         
6917         IFS="$ORIGINAL_IFS"
6918         
6919         a_temp=${A_INIT_DATA[@]}
6920         log_function_data "A_INIT_DATA: $a_temp"
6921         
6922         eval $LOGFE
6923 }
6924
6925 get_kernel_compiler_version()
6926 {
6927         # note that we use gawk to get the last part because beta, alpha, git versions can be non-numeric
6928         local compiler_version='' compiler_type=''
6929         
6930         if [[ -e /proc/version ]];then
6931                 compiler_version=$( grep -Eio 'gcc[[:space:]]*version[[:space:]]*([^ \t]*)' /proc/version 2>/dev/null | gawk '{print $3}' )
6932                 if [[ -n $compiler_version ]];then
6933                         compiler_type='gcc'
6934                 fi
6935         else
6936                 if [[ $BSD_VERSION == 'darwin' ]];then
6937                         if type -p gcc &>/dev/null;then
6938                                 compiler_version=$( get_program_version 'gcc' 'Apple[[:space:]]LLVM' '4' )
6939                                 if [[ -n $compiler_version ]];then
6940                                         compiler_type='LLVM-GCC'
6941                                 fi
6942                         fi
6943                 else
6944                         if [[ -f /etc/src.conf ]];then
6945                                 compiler_type=$( grep '^CC' /etc/src.conf | cut -d '=' -f 2 )
6946                         elif [[ -f /etc/make.conf ]];then
6947                                 compiler_type=$( grep '^CC' /etc/make.conf | cut -d '=' -f 2 )
6948                         fi
6949                         if [[ -n $compiler_type ]];then
6950                                 if type -p $compiler_type &>/dev/null;then
6951                                         if [[ $compiler_type == 'gcc' ]];then
6952                                                 compiler_version=$( get_program_version 'gcc' '^gcc' '3' )
6953                                         elif [[ $compiler_type == 'clang' ]];then
6954                                                 # FreeBSD clang version 3.0 (tags/RELEASE_30/final 145349) 20111210
6955                                                 compiler_version=$( get_program_version 'clang' 'clang' '4' )
6956                                         fi
6957                                 fi
6958                         fi
6959                 fi
6960         fi
6961         if [[ -n $compiler_version ]];then
6962                 compiler_version="$compiler_type^$compiler_version"
6963         fi
6964         echo $compiler_version
6965 }
6966
6967
6968 get_kernel_version()
6969 {
6970         eval $LOGFS
6971         
6972         local kernel_version='' ksplice_kernel_version=''
6973         
6974         kernel_version=$( uname -rm )
6975         if [[ $BSD_VERSION == 'darwin' ]];then
6976                 kernel_version="Darwin $kernel_version"
6977         fi
6978         if [[ -n $( type -p uptrack-uname ) && -n $kernel_version ]];then
6979                 ksplice_kernel_version=$( uptrack-uname -rm )
6980                 if [[ $kernel_version != $ksplice_kernel_version ]];then
6981                         kernel_version="$ksplice_kernel_version (ksplice)"
6982                 fi
6983         fi
6984         log_function_data "kernel_version: $kernel_version - ksplice_kernel_version: $ksplice_kernel_version"
6985         
6986         echo $kernel_version
6987         
6988         eval $LOGFE
6989 }
6990
6991 # args: $1 - v/n 
6992 get_lspci_data()
6993 {
6994         eval $LOGFS
6995         local lspci_data=''
6996
6997         if [[ $B_LSPCI == 'true' ]];then
6998                 lspci_data="$( lspci -$1 | gawk '{
6999                         gsub(/\(prog-if[^)]*\)/,"")
7000                         sub(/^0000:/, "", $0) # seen case where the 0000: is prepended, rare, but happens
7001                         print
7002                 }' )"
7003         fi
7004         
7005         echo "$lspci_data"
7006         log_function_data 'raw' "lspci_data $1:\n$lspci_data"
7007         eval $LOGFE
7008 }
7009
7010 # args: $1 - busid
7011 get_lspci_chip_id()
7012 {
7013         eval $LOGFS
7014         
7015         local chip_id=''
7016         
7017         chip_id=$( gawk '
7018         /^'$1'/ {
7019                 if ( $3 != "" ) {
7020                         print $3
7021                 }
7022         }' <<< "$Lspci_n_Data" )
7023         
7024         echo $chip_id
7025         
7026         eval $LOGFE
7027 }
7028
7029 get_machine_data()
7030 {
7031         eval $LOGFS
7032         local a_temp='' separator='' id_file='' file_data='' array_string=''
7033         local id_dir='/sys/class/dmi/id/' dmi_data='' 
7034         local machine_files="
7035         sys_vendor product_name product_version product_serial product_uuid 
7036         board_vendor board_name board_version board_serial 
7037         bios_vendor bios_version bios_date 
7038         "
7039         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
7040                 machine_files="$machine_files
7041                 chassis_vendor chassis_type chassis_version chassis_serial
7042                 "
7043         fi
7044         if [[ -d $id_dir && $B_FORCE_DMIDECODE == 'false' ]];then
7045                 for id_file in $machine_files
7046                 do
7047                         file_data=''
7048                         if [[ -r $id_dir$id_file ]];then
7049                                 file_data=$( gawk '
7050                                 BEGIN {
7051                                         IGNORECASE=1
7052                                 }
7053                                 {
7054                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
7055                                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
7056                                         # yes, there is a typo in a user data set, unknow
7057                                         # Base Board Version|Base Board Serial Number
7058                                         # Chassis Manufacturer|Chassis Version|Chassis Serial Number
7059                                         # System manufacturer|System Product Name|System Version
7060                                         # To Be Filled By O.E.M.
7061                                         sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", $0)
7062                                         gsub(/bios|acpi/, "", $0)
7063                                         sub(/http:\/\/www.abit.com.tw\//, "Abit", $0)
7064                                         gsub(/^ +| +$/, "", $0)
7065                                         gsub(/ [ \t]+/, " ", $0)
7066                                         print $0
7067                                 }' < $id_dir$id_file )
7068                         fi
7069                         array_string="$array_string$separator$file_data"
7070                         separator=','
7071                 done
7072         else
7073                 get_dmidecode_data
7074                 if [[ -n $DMIDECODE_DATA ]];then
7075                         if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
7076                                 array_string=$DMIDECODE_DATA
7077                         # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
7078                         else
7079                                 array_string=$( gawk -F ':' '
7080                                 BEGIN {
7081                                         IGNORECASE=1
7082                                         baseboardManufacturer=""
7083                                         baseboardProductName=""
7084                                         baseboardSerialNumber=""
7085                                         baseboardVersion=""
7086                                         biosReleaseDate=""
7087                                         biosRevision="" # only available from dmidecode
7088                                         biosRomSize="" # only available from dmidecode
7089                                         biosVendor=""
7090                                         biosVersion=""
7091                                         chassisManufacturer=""
7092                                         chassisSerialNumber=""
7093                                         chassisType=""
7094                                         chassisVersion=""
7095                                         systemManufacturer=""
7096                                         systemProductName=""
7097                                         systemVersion=""
7098                                         systemSerialNumber=""
7099                                         systemUuid=""
7100                                         bItemFound="" # we will only output if at least one item was found
7101                                         fullString=""
7102                                         testString=""
7103                                         bSys=""
7104                                         bCha=""
7105                                         bBio=""
7106                                         bBas=""
7107                                 }
7108                                 /^Bios Information/ {
7109                                         while ( getline && !/^$/ ) {
7110                                                 if ( $1 ~ /^Release Date/ ) { biosReleaseDate=$2 }
7111                                                 if ( $1 ~ /^BIOS Revision/ ) { biosRevision=$2 }
7112                                                 if ( $1 ~ /^ROM Size/ ) { biosRomSize=$2 }
7113                                                 if ( $1 ~ /^Vendor/ ) { biosVendor=$2 }
7114                                                 if ( $1 ~ /^Version/ ) { biosVersion=$2 }
7115                                         }
7116                                         testString=biosReleaseDate biosRevision biosRomSize biosVendor biosVersion
7117                                         if ( testString != ""  ) {
7118                                                 bItemFound="true"
7119                                         }
7120                                         bBio="true"
7121                                 }
7122                                 /^Base Board Information/ {
7123                                         while ( getline && !/^$/ ) {
7124                                                 if ( $1 ~ /^Manufacturer/ ) { baseboardManufacturer=$2 }
7125                                                 if ( $1 ~ /^Product Name/ ) { baseboardProductName=$2 }
7126                                                 if ( $1 ~ /^Serial Number/ ) { baseboardSerialNumber=$2 }
7127                                         }
7128                                         testString=baseboardManufacturer baseboardProductName baseboardSerialNumber
7129                                         if ( testString != ""  ) {
7130                                                 bItemFound="true"
7131                                         }
7132                                         bBas="true"
7133                                 }
7134                                 /^Chassis Information/ {
7135                                         while ( getline && !/^$/ ) {
7136                                                 if ( $1 ~ /^Manufacturer/ ) { chassisManufacturer=$2 }
7137                                                 if ( $1 ~ /^Serial Number/ ) { chassisSerialNumber=$2 }
7138                                                 if ( $1 ~ /^Type/ ) { chassisType=$2 }
7139                                                 if ( $1 ~ /^Version/ ) { chassisVersion=$2 }
7140                                         }
7141                                         testString=chassisManufacturer chassisSerialNumber chassisType chassisVersion
7142                                         if ( testString != ""  ) {
7143                                                 bItemFound="true"
7144                                         }
7145                                         bCha="true"
7146                                 }
7147                                 /^System Information/ {
7148                                         while ( getline && !/^$/ ) {
7149                                                 if ( $1 ~ /^Manufacturer/ ) { systemManufacturer=$2 }
7150                                                 if ( $1 ~ /^Product Name/ ) { systemProductName=$2 }
7151                                                 if ( $1 ~ /^Version/ ) { systemVersion=$2 }
7152                                                 if ( $1 ~ /^Serial Number/ ) { systemSerialNumber=$2 }
7153                                                 if ( $1 ~ /^UUID/ ) { systemUuid=$2 }
7154                                         }
7155                                         testString=systemManufacturer systemProductName systemVersion systemSerialNumber systemUuid
7156                                         if ( testString != ""  ) {
7157                                                 bItemFound="true"
7158                                         }
7159                                         bSys="true"
7160                                 }
7161                                 ( bSys == "true" && bCha="true" && bBio == "true" && bBas == "true" ) {
7162                                         exit # stop the loop
7163                                 }
7164                                 END {
7165                                         # sys_vendor product_name product_version product_serial product_uuid 
7166                                         # board_vendor board_name board_version board_serial 
7167                                         # bios_vendor bios_version bios_date 
7168                                         if ( bItemFound == "true" ) {
7169                                                 fullString = systemManufacturer "," systemProductName "," systemVersion "," systemSerialNumber 
7170                                                 fullString = fullString "," systemUuid "," baseboardManufacturer "," baseboardProductName 
7171                                                 fullString = fullString "," baseboardVersion "," baseboardSerialNumber "," biosVendor
7172                                                 fullString = fullString "," biosVersion "," biosReleaseDate "," chassisManufacturer
7173                                                 fullString = fullString "," chassisType "," chassisVersion "," chassisSerialNumber 
7174                                                 fullString = fullString ","  biosRevision "," biosRomSize
7175                                                 
7176                                                 print fullString
7177                                         }
7178                                 }' <<< "$DMIDECODE_DATA" )
7179                         fi
7180                 fi
7181         fi
7182         # echo $array_string
7183         IFS=','
7184         A_MACHINE_DATA=( $array_string )
7185         IFS="$ORIGINAL_IFS"
7186         # echo ${A_MACHINE_DATA[5]}
7187         a_temp=${A_MACHINE_DATA[@]}
7188         # echo $a_temp
7189         log_function_data "A_MACHINE_DATA: $a_temp"
7190         eval $LOGFE
7191 }
7192 # B_ROOT='true';get_machine_data;exit
7193 ## return memory used/installed
7194 get_memory_data()
7195 {
7196         eval $LOGFS
7197         local memory='' memory_full='' used_memory=''
7198         if [[ $B_MEMINFO_FILE == 'true' ]];then
7199                 memory=$( gawk '
7200                 /^MemTotal:/ {
7201                         tot = $2
7202                 }
7203                 /^(MemFree|Buffers|Cached):/ {
7204                         notused+=$2
7205                 }
7206                 END {
7207                         used = tot - notused
7208                         printf("%.1f/%.1fMB\n", used/1024, tot/1024)
7209                 }' $FILE_MEMINFO )
7210                 log_function_data 'cat' "$FILE_MEMINFO"
7211         elif [[ $B_SYSCTL == 'true' && -n $Sysctl_a_Data ]];then
7212                 local gawk_fs=': '
7213                 # darwin sysctl is broken and uses both : and = and repeats these items
7214                 if [[ $BSD_VERSION == 'openbsd' ]];then
7215                         gawk_fs='='
7216                 fi
7217                 # use this for all bsds, maybe we can get some useful data on other ones
7218                 if [[ -n $( type -p vmstat) ]];then
7219                         # avail mem:2037186560 (1942MB)
7220                         used_memory=$( vmstat 2>/dev/null | tail -n 1 | gawk '
7221                         # openbsd/linux
7222                         # procs    memory       page                    disks    traps          cpu
7223                         # r b w    avm     fre  flt  re  pi  po  fr  sr wd0 wd1  int   sys   cs us sy id
7224                         # 0 0 0  55256 1484092  171   0   0   0   0   0   2   0   12   460   39  3  1 96
7225                         # freebsd:
7226                         # procs      memory      page                    disks     faults         cpu
7227                         # r b w     avm    fre   flt  re  pi  po    fr  sr ad0 ad1   in   sy   cs us sy id
7228                         # 0 0 0  21880M  6444M   924  32  11   0   822 827   0   0  853  832  463  8  3 88
7229                         # dragonfly
7230                         #  procs      memory      page                    disks     faults      cpu
7231                         #  r b w     avm    fre  flt  re  pi  po  fr  sr ad0 ad1   in   sy  cs us sy id
7232                         #  0 0 0       0  84060 30273993 2845 12742 1164 407498171 320960902   0   0 424453025 1645645889 1254348072 35 38 26
7233                         
7234                         BEGIN {
7235                                 IGNORECASE=1
7236                                 memory=""
7237                         }
7238                         {
7239                                 if ($4 ~ /M/ ){
7240                                         sub(/M/,"",$4)
7241                                         memory=$4*1024
7242                                 }
7243                                 else if ($4 ~ /G/ ){
7244                                         sub(/G/,"",$4)
7245                                         memory=$4*1024*1000
7246                                 }
7247                                 else {
7248                                         sub(/K/,"",$4)
7249                                         # dragonfly can have 0 avm, but they may fix that so make test dynamic
7250                                         if ( $4 != 0 ) {
7251                                                 memory=$4
7252                                         }
7253                                         else {
7254                                                 memory="avm-0-" $5
7255                                         }
7256                                 }
7257                                 print memory " " 
7258                                 exit
7259                         }' )
7260                 fi
7261                 # for dragonfly, we will use free mem, not used because free is 0
7262                 memory=$( grep -i 'mem' <<< "$Sysctl_a_Data" | gawk -v usedMemory="$used_memory" -F "$gawk_fs"  '
7263                 BEGIN {
7264                         realMemory=""
7265                         freeMemory=""
7266                 }
7267                 # freebsd seems to use bytes here
7268                 /^hw.physmem/ && ( realMemory == "" ) {
7269                         gsub(/^[^0-9]+|[^0-9]+$/,"",$2)
7270                         realMemory = $2/1024
7271                         if ( freeMemory != "" ) {
7272                                 exit
7273                         }
7274                 }
7275                 # But, it uses K here. Openbsd does not seem to have this item
7276                 # this can be either: Free Memory OR Free Memory Pages
7277                 $1 ~ /^Free Memory/ {
7278                         gsub(/[^0-9]/,"",$NF)
7279                         freeMemory = $NF
7280                         if ( realMemory != "" ) {
7281                                 exit
7282                         }
7283                 }
7284                 END {
7285                         # hack: temp fix for openbsd/darwin: in case no free mem was detected but we have physmem
7286                         if ( freeMemory == "" && realMemory != "" ) {
7287                                 # use openbsd/dragonfly avail mem data if available
7288                                 if (usedMemory != "" ) {
7289                                         if (usedMemory !~ /^avm-0-/ ) {
7290                                                 printf("%.1f/%.1fMB\n", usedMemory/1024, realMemory/1024)
7291                                         }
7292                                         else {
7293                                                 sub(/avm-0-/,"",usedMemory)
7294                                                 int(usedMemory)
7295                                                 # using free mem, not used for dragonfly
7296                                                 usedMemory = realMemory - usedMemory
7297                                                 printf("%.1f/%.1fMB\n", usedMemory/1024, realMemory/1024)
7298                                         }
7299                                 }
7300                                 else {
7301                                         printf("NA/%.1fMB\n", realMemory/1024)
7302                                 }
7303                         }
7304                         else if ( freeMemory != "" && realMemory != "" ) {
7305                                 used = realMemory - freeMemory
7306                                 printf("%.1f/%.1fMB\n", used/1024, realMemory/1024)
7307                         }
7308                 }' )
7309         fi
7310         echo "$memory"
7311         log_function_data "memory: $memory"
7312         eval $LOGFE
7313 }
7314
7315 # process and return module version data
7316 get_module_version_number()
7317 {
7318         eval $LOGFS
7319         local module_version=''
7320         
7321         if [[ $B_MODINFO_TESTED != 'true' ]];then
7322                 B_MODINFO_TESTED='true'
7323                 MODINFO_PATH=$( type -p modinfo )
7324         fi
7325
7326         if [[ -n $MODINFO_PATH ]];then
7327                 module_version=$( $MODINFO_PATH $1 2>/dev/null | gawk '
7328                 BEGIN {
7329                         IGNORECASE=1
7330                 }
7331                 /^version/ {
7332                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $2)
7333                         gsub(/^ +| +$/, "", $2)
7334                         gsub(/ [ \t]+/, " ", $2)
7335                         print $2
7336                 }
7337                 ' )
7338         fi
7339
7340         echo "$module_version"
7341         log_function_data "module_version: $module_version"
7342         eval $LOGFE
7343 }
7344
7345
7346 ## create array of network cards
7347 get_networking_data()
7348 {
7349         eval $LOGFS
7350         
7351         local B_USB_NETWORKING='false' a_temp=''
7352         
7353         IFS=$'\n'
7354         A_NETWORK_DATA=( $( 
7355         echo "$Lspci_v_Data" | gawk '
7356         # NOTE: see version 2.1.28 or earlier for old logic if for some reason it is needed again
7357         # that used a modified string made from nic name for index, why, I have no idea, makes no sense and leads
7358         # to wrong ordered output as well. get_audio_data uses the old logic for now too.
7359         BEGIN {
7360                 IGNORECASE=1
7361                 counter=0 
7362         }
7363         /^[0-9a-f:\.]+ ((ethernet|network) (controller|bridge)|infiniband)/ || /^[0-9a-f:\.]+ [^:]+: .*(ethernet|infiniband|network).*$/ {
7364                 aNic[counter]=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
7365                 #gsub(/realtek semiconductor/, "Realtek", aNic[counter])
7366                 #gsub(/davicom semiconductor/, "Davicom", aNic[counter])
7367                 # The doublequotes are necessary because of the pipes in the variable.
7368                 gsub(/'"$BAN_LIST_NORMAL"'/, "", aNic[counter])
7369                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", aNic[counter])
7370                 gsub(/^ +| +$/, "", aNic[counter])
7371                 gsub(/ [ \t]+/, " ", aNic[counter])
7372                 aPciBusId[counter] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
7373                 while ( getline && !/^$/ ) {
7374                         gsub(/'"$BAN_LIST_ARRAY"'/, "", $0)
7375                         if ( /^[[:space:]]*I\/O/ ) {
7376                                 aPorts[counter] = aPorts[counter] $4 " "
7377                         }
7378                         if ( /driver in use/ ) {
7379                                 aDrivers[counter] = aDrivers[counter] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
7380                         }
7381                         else if ( /kernel modules/ ) {
7382                                 aModules[counter] = aModules[counter] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
7383                         }
7384                 }
7385                 counter++
7386         }
7387         END {
7388                 for (i=0;i<counter;i++) {
7389                         useDrivers=""
7390                         usePorts=""
7391                         useModules=""
7392                         useNic=""
7393                         usePciBusId=""
7394
7395                         ## note: this loses the plural ports case, is it needed anyway?
7396                         if ( aPorts[i] != "" ) {
7397                                 usePorts = aPorts[i]
7398                         }
7399                         if ( aDrivers[i] != "" ) {
7400                                 useDrivers = aDrivers[i]
7401                         }
7402                         if ( aModules[i] != "" ) {
7403                                 useModules = aModules[i]
7404                         }
7405                         if ( aNic[i] != "" ) {
7406                                 useNic=aNic[i]
7407                         }
7408                         if ( aPciBusId[i] != "" ) {
7409                                 usePciBusId = aPciBusId[i]
7410                         }
7411                         # create array primary item for master array
7412                         sub( / $/, "", usePorts ) # clean off trailing whitespace
7413                         print useNic "," useDrivers "," usePorts "," useModules, "," usePciBusId
7414                 }
7415         }' ) )
7416         IFS="$ORIGINAL_IFS"
7417         get_networking_usb_data
7418         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' || $B_USB_NETWORKING == 'true' ]];then
7419                 if [[ -z $BSD_TYPE ]];then
7420                         get_network_advanced_data
7421                 fi
7422         fi
7423         a_temp=${A_NETWORK_DATA[@]}
7424         log_function_data "A_NETWORK_DATA: $a_temp"
7425         
7426         eval $LOGFE
7427 }
7428
7429 get_network_advanced_data()
7430 {
7431         eval $LOGFS
7432         local a_network_adv_working='' if_data='' working_path='' working_uevent_path='' dir_path=''
7433         local if_id='' speed='' duplex='' mac_id='' oper_state=''  chip_id='' b_path_made='true'
7434         local usb_data='' usb_vendor='' usb_product='' product_path='' driver_test='' array_counter=0
7435         local full_path=''
7436         # we need to change to holder since we are updating the main array
7437         IFS=$'\n'
7438         local a_main_working=(${A_NETWORK_DATA[@]})
7439         IFS="$ORIGINAL_IFS"
7440         
7441         for (( i=0; i < ${#a_main_working[@]}; i++ ))
7442         do
7443                 IFS=","
7444                 a_network_adv_working=( ${a_main_working[i]} )
7445                 IFS="$ORIGINAL_IFS"
7446                 # reset these every go round
7447                 driver_test=''
7448                 if_data=''
7449                 product_path=''
7450                 usb_data=''
7451                 usb_product=''
7452                 usb_vendor=''
7453                 working_path=''
7454                 working_uevent_path=''
7455                 if [[ -z $( grep '^usb-' <<< ${a_network_adv_working[4]} ) ]];then
7456                         # note although this may exist technically don't use it, it's a virtual path
7457                         # and causes weird cat errors when there's a missing file as well as a virtual path
7458                         # /sys/bus/pci/devices/0000:02:02.0/net/eth1
7459                         # real paths are: /sys/devices/pci0000:00/0000:00:1e/0/0000:02:02.0/net/eth1/uevent
7460                         # and on older debian kernels: /sys/devices/pci0000:00/0000:02:02.0/net:eth1/uevent
7461                         # but broadcom shows this sometimes, and older kernels maybe:
7462                         # /sys/devices/pci0000:00/0000:00:01.0/0000:05:00.0/net/eth0/
7463                         # /sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/ssb0:0/uevent:['DRIVER=b43', 'MODALIAS=ssb:v4243id0812rev0D']:
7464                         # echo a ${a_network_adv_working[4]}
7465                         if [[ -d /sys/bus/pci/devices/ ]];then
7466                                 working_path="/sys/bus/pci/devices/0000:${a_network_adv_working[4]}"
7467                         elif [[ -d /sys/devices/pci0000:00/ ]];then
7468                                 working_path="/sys/devices/pci0000:00/0000:00:01.0/0000:${a_network_adv_working[4]}"
7469                         fi
7470                         #echo wp ${a_network_adv_working[4]} $i
7471                         # now we want the real one, that xiin also displays, without symbolic links.
7472                         if [[ -n $working_path && -e $working_path ]];then
7473                                 working_path=$( readlink -f $working_path 2>/dev/null )
7474                         else
7475                                 working_path=$( find -P /sys/ -type d -name "*:${a_network_adv_working[4]}" 2>/dev/null )
7476                                 # just on off chance we get two returns, just one one
7477                                 working_path=${working_path%% *}
7478                         fi
7479                         # sometimes there is another directory between the path and /net
7480                         if [[ -n $working_path && ! -e $working_path/net ]];then
7481                                 # using find here, probably will need to also use it in usb part since the grep
7482                                 # method seems to not be working now. Slice off the rest, which leaves the basic path
7483                                 working_path=$( find $working_path/*/net/*/uevent 2>/dev/null | \
7484                                 sed 's|/net.*||' )
7485                         fi
7486                         # working_path=$( ls /sys/devices/pci*/*/0000:${a_network_adv_working[4]}/net/*/uevent  )
7487                 else
7488                         # now we'll use the actual vendor:product string instead
7489                         usb_data=${a_network_adv_working[10]}
7490                         usb_vendor=$( cut -d ':' -f 1 <<< $usb_data )
7491                         usb_product=$( cut -d ':' -f 2 <<< $usb_data )
7492                         # this grep returns the path plus the contents of the file, with a colon separator, so slice that off
7493                         # /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/idVendor
7494                         working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/*/idVendor | \
7495                         sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
7496                         # try an alternate path if first one doesn't work
7497                         # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/idVendor
7498                         if [[ -z $working_path ]];then
7499                                 working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/idVendor | \
7500                                 sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
7501                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/idProduct | \
7502                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
7503                         else
7504                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/*/idProduct | \
7505                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
7506                         fi
7507                         # make sure it's the right product/vendor match here, it will almost always be but let's be sure
7508                         if [[ -n $working_path && -n $product_path ]] && [[ $working_path == $product_path ]];then
7509                         #if [[ -n $working_path ]];then
7510                                 # now ls that directory and get the numeric starting sub directory and that should be the full path
7511                                 # to the /net directory part
7512                                 dir_path=$( ls $working_path 2>/dev/null | grep -sE '^[0-9]' )
7513                                 working_uevent_path="$working_path$dir_path"
7514                         fi
7515                 fi
7516                 # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/uevent grep for DRIVER=
7517                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/1-1:1.0/uevent
7518                 if [[ -n $usb_data ]];then
7519                         driver_test=$( grep -si 'DRIVER=' $working_uevent_path/uevent | cut -d '=' -f 2 )
7520                         if [[ -n $driver_test ]];then
7521                                 a_network_adv_working[1]=$driver_test
7522                         fi
7523                 fi
7524                 #echo wp: $working_path
7525                 log_function_data "PRE: working_path: $working_path\nworking_uevent_path: $working_uevent_path"
7526                 # this applies in two different cases, one, default, standard, two, for usb, this is actually
7527                 # the short path, minus the last longer numeric directory name, ie: 
7528                 # from debian squeeze 2.6.32-5-686: 
7529                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/net/wlan0/address
7530                 if [[ -e $working_path/net ]];then
7531                         # in cases like infiniband dual port devices, there can be two ids, like ib0 ib1, 
7532                         # with line break in output
7533                         if_data=$( ls $working_path/net 2>/dev/null )
7534                         b_path_made='false'
7535                 # this is the normal usb detection if the first one didn't work
7536                 elif [[ -n $usb_data && -e $working_uevent_path/net ]];then
7537                         if_data=$( ls $working_uevent_path/net 2>/dev/null )
7538                         working_path=$working_uevent_path/net/$if_data
7539                 # 2.6.32 debian lenny kernel shows not: /net/eth0 but /net:eth0
7540                 elif [[ -n ${working_path/\/sys*/} ]];then
7541                         if_data=$( ls $working_path 2>/dev/null | grep 'net:' )
7542                         if [[ -n $if_data ]];then
7543                                 working_path=$working_path/$if_data
7544                                 # we won't be using this for path any more, just the actual if id output
7545                                 # so prep it for the loop below
7546                                 if_data=$( cut -d ':' -f 2 <<< "$if_data" )
7547                         fi
7548                 fi
7549                 # just in case we got a failed path, like /net or /, clear it out for tests below
7550                 if [[ -n ${working_path/\/sys*/} ]];then
7551                         working_path=''
7552                 fi
7553                 #echo id: $if_data
7554                 log_function_data "POST: working_path: $working_path\nif_data: $if_data - if_id: $if_id"
7555                 # there are virtual devices that will have no if data but which we still want in the array
7556                 # as it loops. These will also have null working_path as well since no **/net is found
7557                 # echo if_data: $if_data
7558                 if [[ -z $if_data ]];then
7559                         if_data='null-if-id'
7560                 fi
7561                 ## note: in cases of dual ports with different ids, this loop will create extra array items
7562                 for if_item in $if_data
7563                 do
7564                         chip_id=
7565                         duplex=''
7566                         full_path=''
7567                         if_id=''
7568                         mac_id=''
7569                         oper_state=''
7570                         speed=''
7571                         # strip out trailing spaces
7572                         if_item=${if_item%% }
7573                         #echo wp1: $working_path
7574                         if [[ $working_path != '' ]];then
7575                                 if_id=$if_item
7576                                 if [[ $b_path_made == 'false' ]];then
7577                                         full_path=$working_path/net/$if_item
7578                                 else
7579                                         full_path=$working_path
7580                                 fi
7581                                 if [[ -r $full_path/speed ]];then
7582                                         speed=$( cat $full_path/speed 2>/dev/null )
7583                                 fi
7584                                 if [[ -r $full_path/duplex ]];then
7585                                         duplex=$( cat $full_path/duplex 2>/dev/null )
7586                                 fi
7587                                 if [[ -r $full_path/address ]];then
7588                                         mac_id=$( cat $full_path/address 2>/dev/null )
7589                                 fi
7590                                 if [[ -r $full_path/operstate ]];then
7591                                         oper_state=$( cat $full_path/operstate 2>/dev/null )
7592                                 fi
7593                                 if [[ -n ${a_network_adv_working[10]} ]];then
7594                                         chip_id=${a_network_adv_working[10]}
7595                                 fi
7596                         fi
7597                         
7598                         #echo fp: $full_path 
7599                         #echo id: $if_id
7600                         # echo "$if_data ii:  $if_item $array_counter i: $i"
7601                         A_NETWORK_DATA[$array_counter]=${a_network_adv_working[0]}","${a_network_adv_working[1]}","${a_network_adv_working[2]}","${a_network_adv_working[3]}","${a_network_adv_working[4]}","$if_id","$oper_state","$speed","$duplex","$mac_id","$chip_id
7602                         
7603                         ((array_counter++))
7604                 done
7605         done
7606         a_temp=${A_NETWORK_DATA[@]}
7607         log_function_data "A_NETWORK_DATA (advanced): $a_temp"
7608
7609         eval $LOGFE
7610 }
7611
7612 get_networking_usb_data()
7613 {
7614         eval $LOGFS
7615         local lsusb_path='' lsusb_data='' a_usb='' array_count=''
7616         
7617         # now we'll check for usb wifi, a work in progress
7618         # USB_NETWORK_SEARCH
7619         # alsa usb detection by damentz
7620         # for every sound card symlink in /proc/asound - display information about it
7621         lsusb_path=$( type -p lsusb )
7622         # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue
7623         if [[ -n $lsusb_path ]]; then
7624                 # send error messages of lsusb to /dev/null as it will display a bunch if not a super user
7625                 lsusb_data="$( $lsusb_path 2>/dev/null )"
7626                 # also, find the contents of usbid in lsusb and print everything after the 7th word on the
7627                 # corresponding line. Finally, strip out commas as they will change the driver :)
7628                 if [[ -n $lsusb_data ]];then
7629                         IFS=$'\n'
7630                         a_usb=( $( 
7631                         gawk '
7632                         BEGIN {
7633                                 IGNORECASE=1
7634                                 string=""
7635                                 separator=""
7636                         }
7637                         /'"$USB_NETWORK_SEARCH"'/ && !/bluetooth| hub|keyboard|mouse|printer| ps2|reader|scan|storage/ {
7638                                 string=""
7639                                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0 )
7640                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
7641                                 gsub(/ [ \t]+/, " ", $0)
7642                                 #sub(/realtek semiconductor/, "Realtek", $0)
7643                                 #sub(/davicom semiconductor/, "Davicom", $0)
7644                                 #sub(/Belkin Components/, "Belkin", $0)
7645                                 
7646                                 for ( i=7; i<= NF; i++ ) {
7647                                         string = string separator $i
7648                                         separator = " "
7649                                 }
7650                                 if ( $2 != "" ){
7651                                         sub(/:/, "", $4 )
7652                                         print string ",,,,usb-" $2 "-" $4 ",,,,,," $6
7653                                 }
7654                         }' <<< "$lsusb_data" ) )
7655                         IFS="$ORIGINAL_IFS"
7656                         if [[ ${#a_usb[@]} -gt 0 ]];then
7657                                 array_count=${#A_NETWORK_DATA[@]}
7658                                 for (( i=0; i < ${#a_usb[@]}; i++ ))
7659                                 do
7660                                         A_NETWORK_DATA[$array_count]=${a_usb[i]}
7661                                         ((array_count++))
7662                                 done
7663                                 # need this to get the driver data for -N regular output, but no need
7664                                 # to run the advanced stuff unless required
7665                                 B_USB_NETWORKING='true'
7666                         fi
7667                 fi
7668         fi
7669 #       echo $B_USB_NETWORKING
7670         eval $LOGFE
7671 }
7672
7673 get_networking_wan_ip_data()
7674 {
7675         eval $LOGFS
7676         local ip='' ip_data='' downloader_error=0 ua='' b_ipv4_good=true
7677         
7678         # get ip using wget redirect to stdout. This is a clean, text only IP output url,
7679         # single line only, ending in the ip address. May have to modify this in the future
7680         # to handle ipv4 and ipv6 addresses but should not be necessary.
7681         # awk has bad regex handling so checking it with grep -E instead
7682         # ip=$( echo  2001:0db8:85a3:0000:0000:8a2e:0370:7334 | gawk  --re-interval '
7683         # ip=$( wget -q -O - $WAN_IP_URL | gawk  --re-interval '
7684         # this generates a direct dns based ipv4 ip address, but if opendns.com goes down, the fall
7685         # note: consistently slower than domain based: dig +short +time=1 +tries=1 myip.opendns.com. A @208.67.222.222
7686         # backs will still work. 
7687         if [[ -n $DNSTOOL ]];then
7688                 ip=$( dig +short +time=1 +tries=1 myip.opendns.com @resolver1.opendns.com 2>/dev/null)
7689         fi
7690         if [[ $ip == '' ]];then
7691                 case $DOWNLOADER in
7692                         curl)
7693                                 if [[ -n $( grep 'smxi.org' <<< $WAN_IP_URL ) ]];then
7694                                         ua="-A s-tools/inxi-ip"
7695                                 fi
7696                                 ip_data="$( curl $ua -y $DL_TIMEOUT -s $WAN_IP_URL )" || downloader_error=$?
7697                                 ;;
7698                         fetch)
7699                                 ip_data="$( fetch -T $DL_TIMEOUT -q -o - $WAN_IP_URL )" || downloader_error=$?
7700                                 ;;
7701                         ftp)
7702                                 ip_data="$( ftp -o - $WAN_IP_URL 2>/dev/null )" || downloader_error=$?
7703                                 ;;
7704                         wget)
7705                                 if [[ -n $( grep 'smxi.org' <<< $WAN_IP_URL ) ]];then
7706                                         ua="-U s-tools/inxi-ip"
7707                                 fi
7708                                 ip_data="$( wget $ua -T $DL_TIMEOUT -q -O - $WAN_IP_URL )" || downloader_error=$?
7709                                 ;;
7710                         no-downloader)
7711                                 downloader_error=1
7712                                 ;;
7713                 esac
7714                 ip=$( gawk  --re-interval '
7715                 {
7716                         #gsub("\n","",$2")
7717                         print $NF
7718                 }' <<< "$ip_data" )
7719         fi
7720         
7721         # validate the data
7722         if [[ -z $ip ]];then
7723                 ip='None Detected!'
7724         elif [[ -z $( grep -Es \
7725         '^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4}:[[:alnum:]]{0,4})$' <<< $ip ) ]];then
7726                 ip='IP Source Corrupt!'
7727         fi
7728         echo "$ip"
7729         log_function_data "ip: $ip"
7730         eval $LOGFE
7731 }
7732
7733 get_networking_local_ip_data()
7734 {
7735         eval $LOGFS
7736         
7737         local ip_tool_command=$( type -p ip )
7738         local a_temp='' ip_tool='ip' ip_tool_data=''
7739         # the chances for all new systems to have ip by default are far higher than
7740         # the deprecated ifconfig. Only try for ifconfig if ip is not present in system
7741         if [[ -z $ip_tool_command ]];then
7742                 ip_tool_command=$( type -p ifconfig )
7743                 ip_tool='ifconfig'
7744         else
7745                 ip_tool_command="$ip_tool_command addr"
7746         fi
7747         if [[ -n "$ip_tool_command" ]];then
7748                 if [[ $ip_tool == 'ifconfig' ]];then
7749                         ip_tool_data="$( $ip_tool_command | gawk '
7750                         {
7751                                 line=gensub(/^([a-z]+[0-9][:]?[[:space:]].*)/, "\n\\1", $0)
7752                                 print line
7753                         }' )"
7754                 # note, ip addr does not have proper record separation, so creating new lines explicitly here at start
7755                 # of each IF record item. Also getting rid of the unneeded numeric line starters, now it can be parsed 
7756                 # like ifconfig more or less
7757                 elif [[ $ip_tool == 'ip' ]];then
7758                         ip_tool_data="$( eval $ip_tool_command | sed 's/^[0-9]\+:[[:space:]]\+/\n/' )"
7759                 fi
7760         fi
7761         if [[ -z $ip_tool_command ]];then
7762                 A_INTERFACES_DATA=( "Interfaces program 'ip' missing. Please check: $SCRIPT_NAME --recommends" )
7763         elif [[ -n "$ip_tool_data" ]];then
7764                 IFS=$'\n' # $ip_tool_command
7765                 A_INTERFACES_DATA=( $( 
7766                 gawk -v ipTool=$ip_tool -v bsdType=$BSD_TYPE '
7767                 BEGIN {
7768                         IGNORECASE=1
7769                         interface=""
7770                         ifIp=""
7771                         ifIpV6=""
7772                         ifMask=""
7773                 }
7774                 # skip past the lo item
7775                 /^lo/ {
7776                         while (getline && !/^$/ ) {
7777                                 # do nothing, just get past this entry item
7778                         }
7779                 }
7780                 /^[a-zA-Z]+[0-9]/ {
7781                         # not clear on why inet is coming through, but this gets rid of it
7782                         # as first line item.
7783                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
7784                         gsub(/^ +| +$/, "", $0)
7785                         gsub(/ [ \t]+/, " ", $0)
7786                         interface = $1
7787                         # prep this this for ip addr: eth0: 
7788                         sub(/:/, "", interface)
7789                         ifIp=""
7790                         ifIpV6=""
7791                         ifMask=""
7792                         aInterfaces[interface]++
7793
7794                         while (getline && !/^$/ ) {
7795                                 if ( ipTool == "ifconfig" ) {
7796                                         if (/inet addr:/) {
7797                                                 ifIp = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 )
7798                                                 if (/mask:/) {
7799                                                         ifMask = gensub( /mask:([0-9\.]+)/, "\\1", "g", $NF )
7800                                                 }
7801                                         }
7802                                         if (/inet6 addr:/) {
7803                                                 ifIpV6 = $3
7804                                         }
7805                                         if ( bsdType == "bsd" ) {
7806                                                 if ( $1 == "inet" ) {
7807                                                         ifIp = $2
7808                                                         if ( $3 == "netmask" ) {
7809                                                                 ifMask = $4
7810                                                         }
7811                                                 }
7812                                                 if ( $0 ~ /inet6.*%/ ) {
7813                                                         sub(/%.*/,"",$2)
7814                                                         ifIpV6 = $2
7815                                                 }
7816                                         }
7817                                 }
7818                                 else if ( ipTool == "ip" ) {
7819                                         if ( $1 == "inet" ) {
7820                                                 ifIp = $2
7821                                         }
7822                                         if ( $1 == "inet6" ) {
7823                                                 ifIpV6 = $2
7824                                         }
7825                                 }
7826                         }
7827                         # slice off the digits that are sometimes tacked to the end of the address, 
7828                         # like: /64 or /24
7829                         sub(/\/[0-9]+/, "", ifIp)
7830                         sub(/\/[0-9]+/, "", ifIpV6)
7831                         ipAddresses[interface] = ifIp "," ifMask "," ifIpV6
7832                 }
7833                 END {
7834                         j=0
7835                         for (i in aInterfaces) {
7836                                 ifData = ""
7837                                 a[j] = i
7838                                 if (ipAddresses[i] != "") {
7839                                         ifData = ipAddresses[i]
7840                                 }
7841                                 # create array primary item for master array
7842                                 # tested needed to avoid bad data from above, if null it is garbage
7843                                 # this is the easiest way to handle junk I found, improve if you want
7844                                 if ( ifData != "" ) {
7845                                         print a[j] "," ifData
7846                                 }
7847                                 j++
7848                         }
7849                 }' <<< "$ip_tool_data" ) )
7850                 IFS="$ORIGINAL_IFS"
7851         else
7852                 A_INTERFACES_DATA=( "Interfaces program $ip_tool present but created no data. " )
7853         fi
7854         a_temp=${A_INTERFACES_DATA[@]}
7855         log_function_data "A_INTERFACES_DATA: $a_temp"
7856         eval $LOGFE
7857 }
7858 # get_networking_local_ip_data;exit
7859
7860 get_optical_drive_data()
7861 {
7862         eval $LOGFS
7863         
7864         local a_temp='' sys_uevent_path='' proc_cdrom='' link_list=''
7865         local separator='' linked='' working_disk='' disk='' item_string='' proc_info_string='' 
7866         local dev_disks_full=''
7867         dev_disks_full="$( ls /dev/dvd* /dev/cd* /dev/scd* /dev/sr* 2>/dev/null | grep -vE 'random' )"
7868         ## Not using this now because newer kernel is NOT linking all optical drives. Some, but not all
7869         # Some systems don't support xargs -L plus the unlinked optical drive unit make this not a good option
7870         # get the actual disk dev location, first try default which is easier to run, need to preserve line breaks
7871         # local dev_disks_real="$( echo "$dev_disks_full" | xargs -L 1 readlink 2>/dev/null | sort -u )"
7872         
7873         #echo ddl: $dev_disks_full
7874         for working_disk in $dev_disks_full
7875         do
7876                 disk=$( readlink $working_disk 2>/dev/null )
7877                 if [[ -z $disk ]];then
7878                         disk=$working_disk
7879                 fi
7880                 disk=${disk##*/}  # puppy shows this as /dev/sr0, not sr0
7881                 # if [[ -z $dev_disks_real || -z $( grep $disk <<< $dev_disks_real ) ]];then
7882                 if [[ -n $disk && -z $( grep "$disk" <<< $dev_disks_real ) ]];then
7883                         # need line break IFS for below, no white space
7884                         dev_disks_real="$dev_disks_real$separator$disk"
7885                         separator=$'\n'
7886                         #separator=' '
7887                 fi
7888         done
7889         dev_disks_real="$( sort -u <<< "$dev_disks_real" )"
7890         working_disk=''
7891         disk=''
7892         separator=''
7893         #echo ddr: $dev_disks_real
7894
7895         # A_OPTICAL_DRIVE_DATA indexes: not going to use all these, but it's just as easy to build the full
7896         # data array and use what we need from it as to update it later to add features or items
7897         # 0 - true dev path, ie, sr0, hdc
7898         # 1 - dev links to true path
7899         # 2 - device vendor - for hdx drives, vendor model are one string from proc
7900         # 3 - device model
7901         # 4 - device rev version
7902         # 5 - speed
7903         # 6 - multisession support
7904         # 7 - MCN support
7905         # 8 - audio read
7906         # 9 - cdr
7907         # 10 - cdrw
7908         # 11 - dvd read
7909         # 12 - dvdr
7910         # 13 - dvdram
7911         # 14 - state
7912         
7913         if [[ -n $dev_disks_real ]];then
7914                 if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
7915                         proc_cdrom="$( cat /proc/sys/dev/cdrom/info 2>/dev/null )"
7916                 fi
7917                 IFS=$'\n'
7918                 A_OPTICAL_DRIVE_DATA=( $(
7919                 for disk in $dev_disks_real
7920                 do
7921                         for working_disk in $dev_disks_full 
7922                         do
7923                                 if [[ -n $( readlink $working_disk | grep $disk ) ]];then
7924                                         linked=${working_disk##*/}
7925                                         link_list="$link_list$separator$linked"
7926                                         separator='~'
7927                                 fi
7928                         done
7929                         item_string="$disk,$link_list"
7930                         link_list=''
7931                         linked=''
7932                         separator=''
7933                         vendor=''
7934                         model=''
7935                         proc_info_string=''
7936                         rev_number=''
7937                         state=""
7938                         sys_path=''
7939                         working_disk=''
7940                         # this is only for new sd type paths in /sys, otherwise we'll use /proc/ide
7941                         if [[ -z $( grep '^hd' <<< $disk ) ]];then
7942                                 # maybe newer kernels use this, not enough data.
7943                                 sys_path=$( ls /sys/devices/pci*/*/ata*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
7944                                 # maybe older kernels, this used to work (2014-03-16)
7945                                 if [[ -z $sys_path ]];then
7946                                         sys_path=$( ls /sys/devices/pci*/*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
7947                                 fi
7948                                 # no need to test for errors yet, probably other user systems will require some alternate paths though
7949                                 if [[ -n $sys_path ]];then
7950                                         vendor=$( cat $sys_path/vendor 2>/dev/null )
7951                                         model=$( cat $sys_path/model 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
7952                                         state=$( cat $sys_path/state 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
7953                                         rev_number=$( cat $sys_path/rev 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
7954                                 fi
7955                         elif [[ -e /proc/ide/$disk/model ]];then
7956                                 vendor=$( cat /proc/ide/$disk/model 2>/dev/null )
7957                         fi
7958                         if [[ -n $vendor ]];then
7959                                 vendor=$( gawk '
7960                                 BEGIN {
7961                                         IGNORECASE=1
7962                                 }
7963                                 {
7964                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
7965                                         sub(/TSSTcorp/, "TSST ", $0) # seen more than one of these weird ones
7966                                         gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0)
7967                                         gsub(/^[[:space:]]*|[[:space:]]*$/, "", $0)
7968                                         gsub(/ [[:space:]]+/, " ", $0)
7969                                         print $0
7970                                 }'      <<< $vendor )
7971                         fi
7972                         # this needs to run no matter if there's proc data or not to create the array comma list
7973                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
7974                                 proc_info_string=$( gawk -v diskId=$disk '
7975                                 BEGIN {
7976                                         IGNORECASE=1
7977                                         position=""
7978                                         speed=""
7979                                         multisession=""
7980                                         mcn=""
7981                                         audio=""
7982                                         cdr=""
7983                                         cdrw=""
7984                                         dvd=""
7985                                         dvdr=""
7986                                         dvdram=""
7987                                 }
7988                                 # first get the position of the device name from top field
7989                                 # we will use this to get all the other data for that column
7990                                 /drive name:/ {
7991                                         for ( position=3; position <= NF; position++ ) {
7992                                                 if ( $position == diskId ) {
7993                                                         break
7994                                                 }
7995                                         }
7996                                 }
7997                                 /drive speed:/ {
7998                                         speed = $position
7999                                 }
8000                                 /Can read multisession:/ {
8001                                         multisession=$( position + 1 )
8002                                 }
8003                                 /Can read MCN:/ {
8004                                         mcn=$( position + 1 )
8005                                 }
8006                                 /Can play audio:/ {
8007                                         audio=$( position + 1 )
8008                                 }
8009                                 /Can write CD-R:/ {
8010                                         cdr=$( position + 1 )
8011                                 }
8012                                 /Can write CD-RW:/ {
8013                                         cdrw=$( position + 1 )
8014                                 }
8015                                 /Can read DVD:/ {
8016                                         dvd=$( position + 1 )
8017                                 }
8018                                 /Can write DVD-R:/ {
8019                                         dvdr=$( position + 1 )
8020                                 }
8021                                 /Can write DVD-RAM:/ {
8022                                         dvdram=$( position + 1 )
8023                                 }
8024                                 END {
8025                                         print speed "," multisession "," mcn "," audio "," cdr "," cdrw "," dvd "," dvdr "," dvdram
8026                                 }
8027                                 ' <<< "$proc_cdrom" )
8028                         fi
8029                         item_string="$item_string,$vendor,$model,$rev_number,$proc_info_string,$state"
8030                         echo $item_string
8031                 done \
8032                 ) )
8033                 IFS="$ORIGINAL_IFS"
8034         fi
8035         a_temp=${A_OPTICAL_DRIVE_DATA[@]}
8036         # echo "$a_temp"
8037         log_function_data "A_OPTICAL_DRIVE_DATA: $a_temp"
8038         eval $LOGFE
8039 }
8040 # get_optical_drive_data;exit
8041
8042 get_optical_drive_data_bsd()
8043 {
8044         eval $LOGFS
8045         
8046         local a_temp=''
8047         
8048         if [[ -n $Dmesg_Boot_Data ]];then
8049                 IFS=$'\n'
8050                 A_OPTICAL_DRIVE_DATA=( $( gawk -F ':' '
8051                 BEGIN {
8052                         IGNORECASE=1
8053                 }
8054                 # sde,3.9GB,STORE_N_GO,USB,C200431546D3CF49-0:0,0
8055                 # sdd,250.1GB,ST3250824AS,,9ND08GKX,45
8056                 $1 ~ /^(cd|dvd)[0-9]+/ {
8057                         diskId=gensub(/^((cd|dvd)[0-9]+)[^0-9].*/,"\\1",1,$1)
8058                         # note: /var/run/dmesg.boot may repeat items since it is not created
8059                         # fresh every boot, this way, only the last items will be used per disk id
8060                         if (aIds[diskId] == "" ) {
8061                                 aIds[diskId]=diskId
8062                         }
8063                         aDisks[diskId, "id"] = diskId
8064                         if ( $NF ~ /<.*>/ ){
8065                                 gsub(/.*<|>.*/,"",$NF)
8066                                 rev_number=gensub(/.*[^0-9\.]([0-9\.]+)$/,"\\1",1,$NF)
8067                                 if (rev_number ~ /^[0-9\.]+$/) {
8068                                         aDisks[diskId, "rev"] = rev_number
8069                                 }
8070                                 model=gensub(/(.*[^0-9\.])[0-9\.]+$/,"\\1",1,$NF)
8071                                 sub(/[[:space:]]+$/,"",model)
8072                                 aDisks[diskId, "model"] = model
8073                         }
8074                         if ( $NF ~ /serial number/ ){
8075                                 sub(/serial[[:space:]]+number[[:space:]]*/,"",$NF)
8076                                 aDisks[diskId, "serial"] = $NF
8077                         }
8078                         if ( $NF ~ /[GM]B\/s/ ){
8079                                 speed=gensub(/^([0-9\.]+[[:space:]]*[GM]B\/s).*/,"\\1",1,$NF)
8080                                 sub(/\.[0-9]+/,"",speed)
8081                                 if ( speed ~ /^[0-9]+/ ) {
8082                                         aDisks[diskId, "speed"] = speed
8083                                 }
8084                         }
8085                 }
8086                 # "$link,dev-readlinks,$vendor,$model,$rev_number,$proc_info_string,$state"
8087                 # $proc_info_string: print speed "," multisession "," mcn "," audio "," cdr "," cdrw "," dvd "," dvdr "," dvdram
8088                 END {
8089                         # multi dimensional pseudo arrays are sorted at total random, not in order of
8090                         # creation, so force a sort of the aIds, which deletes the array index but preserves
8091                         # the sorted keys.
8092                         asort(aIds) 
8093                         for ( key in aIds ) {
8094                                 print aDisks[aIds[key], "id"] ",,," aDisks[aIds[key], "model"] "," aDisks[aIds[key], "rev"] "," aDisks[aIds[key], "speed"] ",,,,,,,," 
8095                         }
8096                 }' <<< "$Dmesg_Boot_Data" ) )
8097                 IFS="$ORIGINAL_IFS"
8098         fi
8099         
8100         a_temp=${A_OPTICAL_DRIVE_DATA[@]}
8101         # echo ${a_temp[@]}
8102         log_function_data "A_OPTICAL_DRIVE_DATA: $a_temp"
8103         
8104         eval $LOGFE
8105 }
8106
8107 get_partition_data()
8108 {
8109         eval $LOGFS
8110         
8111         local a_partition_working='' dev_item='' a_temp='' dev_working_item='' 
8112         local swap_data='' df_string='' main_partition_data='' fs_type=''
8113         local mount_data='' dev_bsd_item=''
8114         #local excluded_file_types='--exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660'
8115         # df doesn't seem to work in script with variables like at the command line
8116         # added devfs linprocfs sysfs fdescfs which show on debian kfreebsd kernel output
8117         if [[ -z $BSD_TYPE ]];then
8118                 swap_data="$( swapon -s 2>/dev/null )"
8119                 df_string='df -h -T -P --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs 
8120                 --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=procfs
8121                 --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs'
8122         else
8123                 swap_data="$( swapctl -l -k 2>/dev/null )"
8124                 # default size is 512, -H only for size in human readable format
8125                 # older bsds don't support -T, pain, so we'll use partial output there
8126                 if df -h -T &>/dev/null;then
8127                         df_string='df -h -T'
8128                 else
8129                         df_string='df -h'
8130                 fi
8131         fi
8132         main_partition_data="$( eval $df_string )"
8133         # set dev disk label/mapper/uuid data globals
8134         get_partition_dev_data 'label'
8135         get_partition_dev_data 'mapper'
8136         get_partition_dev_data 'uuid'
8137         
8138         log_function_data 'raw' "main_partition_data:\n$main_partition_data\n\nswap_data:\n$swap_data"
8139         
8140         # new kernels/df have rootfs and / repeated, creating two entries for the same partition
8141         # so check for two string endings of / then slice out the rootfs one, I could check for it
8142         # before slicing it out, but doing that would require the same action twice re code execution
8143         if [[ $( grep -cs '[[:space:]]/$' <<< "$main_partition_data" ) -gt 1 ]];then
8144                 main_partition_data="$( grep -vs '^rootfs' <<< "$main_partition_data" )"
8145         fi
8146         # echo "$main_partition_data"
8147         log_function_data 'raw' "main_partition_data_post_rootfs:\n$main_partition_data\n\nswap_data:\n$swap_data"
8148         IFS=$'\n'
8149         # $NF = partition name; $(NF - 4) = partition size; $(NF - 3) = used, in gB; $(NF - 1) = percent used
8150         ## note: by subtracting from the last field number NF, we avoid a subtle issue with LVM df output, where if
8151         ## the first field is too long, it will occupy its own line, this way we are getting only the needed data
8152         A_PARTITION_DATA=( $( echo "$main_partition_data" | gawk -v bsdType="$BSD_TYPE" -v bsdVersion="$BSD_VERSION" '
8153         BEGIN {
8154                 IGNORECASE=1
8155                 fileSystem=""
8156         }
8157         # this has to be nulled for every iteration so it does not retain value from last iteration
8158         devBase=""
8159         # skipping these file systems because bsds do not support df --exclude-type=<fstype>
8160         # note that using $1 to handle older bsd df, which do not support -T. This will not be reliable but we will see
8161         ( bsdType != "" ) {
8162                 # skip if non disk/partition, or if raid primary id, which will not have a / in it. 
8163                 # Note: kfreebsd uses /sys, not sysfs, is this a bug or expected behavior?
8164                 if ( $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|iso9660|linprocfs|procfs|squashfs|\/sys|sysfs|tmpfs|type|unionfs)$/ || 
8165                 ( $1 ~ /^([^\/]+)$/ && $1 !~ /^ROOT/ ) ) {
8166                         # note use next, not getline or it does not work right
8167                         next 
8168                 }
8169         }
8170         # this is required because below we are subtracting from NF, so it has to be > 5
8171         # the real issue is long file system names that force the wrap of df output: //fileserver/main
8172         # but we still need to handle more dynamically long space containing file names, but later.
8173         # Using df -P should fix this, ie, no wrapping of line lines, but leaving this for now
8174         ( NF < 6 ) && ( $0 !~ /[0-9]+%/ ) {
8175                 # set the dev location here for cases of wrapped output
8176                 if ( NF == 1 ) {
8177                         devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
8178                 }
8179                 getline
8180         }
8181         
8182         # next set devBase if it didn not get set above here
8183         ( devBase == "" ) && ( $1 ~ /^\/dev\/|:\/|\/\// ) {
8184                 devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
8185         }
8186         # this handles zfs type devices/partitions, which do not start with / but contain /
8187         ( bsdType != "" && devBase == "" && $1 ~ /^[^\/]+\/.+/ ) {
8188                 devBase=gensub( /^([^\/]+\/)([^\/]+)$/, "non-dev-\\1\\2", 1, $1 )
8189         }
8190         # this handles yet another fredforfaen special case where a mounted drive
8191         # has the search string in its name
8192         $NF ~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$/ {
8193                 # note, older df in bsd do not have file system column
8194                 if ( NF == "7" && $(NF - 1) ~ /[0-9]+%/ ) {
8195                         fileSystem=$(NF - 5)
8196                 }
8197                 else {
8198                         fileSystem=""
8199                 }
8200                 # /dev/disk0s2    249G    24G   225G    10% 5926984 54912758   10%   /
8201                 if ( bsdVersion == "darwin" && $(NF - 4) ~ /[0-9]+%/ ) {
8202                         print $NF "," $(NF - 7) "," $(NF - 6) "," $(NF - 4) ",main," fileSystem "," devBase 
8203                 }
8204                 else {
8205                         print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",main," fileSystem "," devBase 
8206                 }
8207         }
8208         # skip all these, including the first, header line. Use the --exclude-type
8209         # to handle new filesystems types we do not want listed here
8210         $NF !~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$|^filesystem/ {
8211                 # this is to avoid file systems with spaces in their names, that will make
8212                 # the test show the wrong data in each of the fields, if no x%, then do not use
8213                 # using 3 cases, first default, standard, 2nd, 3rd, handles one and two spaces in name
8214                 if ( bsdVersion == "darwin" && $(NF - 4) ~ /[0-9]+%/ ) {
8215                         fileSystem=""
8216                         print $NF "," $(NF - 7) "," $(NF - 6) "," $(NF - 4) ",main," fileSystem "," devBase 
8217                 }
8218                 else if ( $(NF - 1) ~ /[0-9]+%/ ) {
8219                         # note, older df in bsd do not have file system column
8220                         if ( NF == "7" ) {
8221                                 fileSystem=$(NF - 5)
8222                         }
8223                         else {
8224                                 fileSystem=""
8225                         }
8226                         print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",secondary," fileSystem "," devBase 
8227                 }
8228                 # these two cases construct the space containing name
8229                 else if ( $(NF - 2) ~ /[0-9]+%/ ) {
8230                         # note, older df in bsd do not have file system column
8231                         if ( NF == "8" && $(NF - 6) !~ /^[0-9]+/ ) {
8232                                 fileSystem=$(NF - 6)
8233                         }
8234                         else {
8235                                 fileSystem=""
8236                         }
8237                         print $(NF - 1) " " $NF "," $(NF - 5) "," $(NF - 4) "," $(NF - 2) ",secondary," fileSystem "," devBase
8238                 }
8239                 else if ( $(NF - 3) ~ /[0-9]+%/ ) {
8240                         # note, older df in bsd do not have file system column
8241                         if ( NF == "9" && $(NF - 7) !~ /^[0-9]+/ ) {
8242                                 fileSystem=$(NF - 7)
8243                         }
8244                         else {
8245                                 fileSystem=""
8246                         }
8247                         print $(NF - 2) " " $(NF - 1) " " $NF "," $(NF - 6) "," $(NF - 5) "," $(NF - 3) ",secondary," fileSystem "," devBase 
8248                 }
8249         }' )
8250         # now add the swap partition data, don't want to show swap files, just partitions,
8251         # though this can include /dev/ramzswap0. Note: you can also use /proc/swaps for this
8252         # data, it's the same exact output as swapon -s
8253         $( echo "$swap_data" | gawk -v bsdType=$BSD_TYPE '
8254         BEGIN {
8255                 swapCounter = 1
8256                 usedHolder=""
8257                 sizeHolder=""
8258         }
8259         /^\/dev/ {
8260                 if ( bsdType == "" ) {
8261                         usedHolder=$4
8262                         sizeHolder=$3
8263                 }
8264                 else {
8265                         usedHolder=$3
8266                         sizeHolder=$2
8267                 }
8268                 size = sprintf( "%.2f", sizeHolder*1024/1000**3 )
8269                 devBase = gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
8270                 used = sprintf( "%.2f", usedHolder*1024/1000**3 )
8271                 percentUsed = sprintf( "%.0f", ( usedHolder/sizeHolder )*100 )
8272                 print "swap-" swapCounter "," size "GB," used "GB," percentUsed "%,main," "swap," devBase
8273                 swapCounter = ++swapCounter
8274         }' ) )
8275         IFS="$ORIGINAL_IFS"
8276         
8277         a_temp=${A_PARTITION_DATA[@]}
8278         # echo $a_temp
8279         log_function_data "1: A_PARTITION_DATA:\n$a_temp"
8280         
8281         # we'll use this for older systems where no filesystem type is shown in df
8282         if [[ $BSD_TYPE == 'bsd' ]];then
8283                 mount_data="$( mount )"
8284         fi
8285         # now we'll handle some fringe cases where irregular df -hT output shows /dev/disk/.. instead of 
8286         # /dev/h|sdxy type data for column 1, . A_PARTITION_DATA[6]
8287         # Here we just search for the uuid/label and then grab the end of the line to get the right dev item.
8288         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
8289         do
8290                 IFS=","
8291                 a_partition_working=( ${A_PARTITION_DATA[i]} )
8292                 IFS="$ORIGINAL_IFS"
8293                 
8294                 dev_item=${a_partition_working[6]} # reset each loop
8295                 fs_type=${a_partition_working[5]}
8296                 # older bsds have df minus -T so can't get fs type easily, try using mount instead
8297                 if [[ $BSD_TYPE == 'bsd' ]] && [[ -z $fs_type && -n $dev_item ]];then
8298                         dev_bsd_item=$( sed -e 's/non-dev-//' -e 's|/|\\/|g' <<< "$dev_item" )
8299                         fs_type=$( gawk -v bsdVersion="$BSD_VERSION" -F '(' '
8300                         BEGIN {
8301                                 IGNORECASE=1
8302                                 fileSystem=""
8303                         }
8304                         /'$dev_bsd_item'/ {
8305                                 if ( bsdVersion != "openbsd" ) {
8306                                         # slice out everything after / plus the first comma
8307                                         sub( /,.*/, "", $2 )
8308                                         fileSystem=$2
8309                                 }
8310                                 else {
8311                                         # for openbsd: /dev/wd0f on /usr type ffs (local, nodev)
8312                                         gsub(/^.*type[[:space:]]+|[[:space:]]*$/, "", $1 )
8313                                         fileSystem=$1
8314                                 }
8315                                 print fileSystem
8316                                 exit
8317                         }' <<< "$mount_data" )
8318                 fi
8319                 # note: for swap this will already be set
8320                 if [[ -n $( grep -E '(by-uuid|by-label)' <<< $dev_item ) ]];then
8321                         dev_working_item=${dev_item##*/}
8322                         if [[ -n $DEV_DISK_UUID ]];then
8323                                 dev_item=$( echo "$DEV_DISK_UUID" | gawk '
8324                                         $0 ~ /[ /t]'$dev_working_item'[ /t]/ {
8325                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
8326                                                 print item
8327                                                 exit
8328                                         }' )
8329                         fi
8330                         # if we didn't find anything for uuid try label
8331                         if [[ -z $dev_item && -n $DEV_DISK_LABEL ]];then
8332                                 dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
8333                                         $0 ~ /[ /t]'$dev_working_item'[ /t]/ {
8334                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
8335                                                 print item
8336                                                 exit
8337                                         }' )
8338                         fi
8339                 elif [[ -n $( grep 'mapper/' <<< $dev_item ) ]];then
8340                         # get the mapper actual dev item
8341                         dev_item=$( get_dev_processed_item "$dev_item" )
8342                 fi
8343                 
8344                 if [[ -n $dev_item ]];then
8345                         # assemble everything we could get for dev/h/dx, label, and uuid
8346                         IFS=","
8347                         A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","$fs_type","$dev_item
8348                         IFS="$ORIGINAL_IFS"
8349                 fi
8350         done
8351         a_temp=${A_PARTITION_DATA[@]}
8352         # echo $a_temp;exit
8353         log_function_data "2: A_PARTITION_DATA:\n$a_temp"
8354         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
8355                 get_partition_data_advanced
8356         fi
8357         eval $LOGFE
8358 }
8359
8360 # first get the locations of the mount points for label/uuid detection
8361 get_partition_data_advanced()
8362 {
8363         eval $LOGFS
8364         local a_partition_working='' dev_partition_data=''
8365         local dev_item='' dev_label='' dev_uuid='' a_temp=''
8366         local mount_point=''
8367         # set dev disk label/mapper/uuid data globals
8368         get_partition_dev_data 'label'
8369         get_partition_dev_data 'mapper'
8370         get_partition_dev_data 'uuid'
8371
8372         if [[ $B_MOUNTS_FILE == 'true' ]];then
8373                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
8374                 do
8375                         IFS=","
8376                         a_partition_working=( ${A_PARTITION_DATA[i]} )
8377                         IFS="$ORIGINAL_IFS"
8378                         
8379                         # note: for swap this will already be set
8380                         if [[ -z ${a_partition_working[6]} ]];then
8381                                 
8382                                 mount_point=$( sed 's|/|\\/|g'  <<< ${a_partition_working[0]} )
8383                                 #echo mount_point $mount_point
8384                                 dev_partition_data=$( gawk '
8385                                 BEGIN {
8386                                         IGNORECASE = 1
8387                                         partition = ""
8388                                         partTemp = ""
8389                                 }
8390                                 # trying to handle space in name
8391 #                               gsub(/\\040/, " ", $0 )
8392                                 /[ \t]'$mount_point'[ \t]/ && $1 != "rootfs" {
8393                                         # initialize the variables
8394                                         label = ""
8395                                         uuid = ""
8396
8397                                         # slice out the /dev
8398                                         partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
8399                                         # label and uuid can occur for root, set partition to null now
8400                                         if ( partition ~ /by-label/ ) {
8401                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, $1 )
8402                                                 partition = ""
8403                                         }
8404                                         if ( partition ~ /by-uuid/ ) {
8405                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, $1 )
8406                                                 partition = ""
8407                                         }
8408
8409                                         # handle /dev/root for / id
8410                                         if ( partition == "root" ) {
8411                                                 # if this works, great, otherwise, just set this to null values
8412                                                 partTemp="'$( readlink /dev/root 2>/dev/null )'"
8413                                                 if ( partTemp != "" ) {
8414                                                         if ( partTemp ~ /[hsv]d[a-z]+[0-9]{1,2}/ ) {
8415                                                                 partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, partTemp )
8416                                                         }
8417                                                         else if ( partTemp ~ /by-uuid/ ) {
8418                                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, partTemp )
8419                                                                 partition="" # set null to let real location get discovered
8420                                                         }
8421                                                         else if ( partTemp ~ /by-label/ ) {
8422                                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, partTemp )
8423                                                                 partition="" # set null to let real location get discovered
8424                                                         }
8425                                                 }
8426                                                 else {
8427                                                         partition = ""
8428                                                         label = ""
8429                                                         uuid = ""
8430                                                 }
8431                                         }
8432                                         print partition "," label "," uuid
8433                                         exit
8434                                 }'      $FILE_MOUNTS )
8435
8436                                 # assemble everything we could get for dev/h/dx, label, and uuid
8437                                 IFS=","
8438                                 A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","${a_partition_working[5]}","$dev_partition_data
8439                                 IFS="$ORIGINAL_IFS"
8440                         fi
8441                         ## now we're ready to proceed filling in the data
8442                         IFS=","
8443                         a_partition_working=( ${A_PARTITION_DATA[i]} )
8444                         IFS="$ORIGINAL_IFS"
8445                         # get the mapper actual dev item first, in case it's mapped
8446                         dev_item=$( get_dev_processed_item "${a_partition_working[6]}" )
8447                         # make sure not to slice off rest if it's a network mounted file system
8448                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
8449                                 dev_item=${dev_item##*/} ## needed to avoid error in case name still has / in it
8450                         fi
8451                         dev_label=${a_partition_working[7]}
8452                         dev_uuid=${a_partition_working[8]}
8453                         # then if dev data/uuid is incomplete, try to get missing piece
8454                         # it's more likely we'll get a uuid than a label. But this should get the
8455                         # dev item set no matter what, so then we can get the rest of any missing data
8456                         # first we'll get the dev_item if it's missing
8457                         if [[ -z $dev_item ]];then
8458                                 if [[ -n $DEV_DISK_UUID && -n $dev_uuid ]];then
8459                                         dev_item=$( echo "$DEV_DISK_UUID" | gawk '
8460                                                 $0 ~ /[ \t]'$dev_uuid'[ \t]/ {
8461                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
8462                                                         print item
8463                                                         exit
8464                                                 }' )
8465                                 elif [[ -n $DEV_DISK_LABEL && -n $dev_label ]];then
8466                                         dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
8467                                                 # first we need to change space x20 in by-label back to a real space
8468                                                 #gsub(/x20/, " ", $0 )
8469                                                 # then we can see if the string is there
8470                                                 $0 ~ /[ \t]'$dev_label'[ \t]/ {
8471                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
8472                                                         print item
8473                                                         exit
8474                                                 }' )
8475                                 fi
8476                         fi
8477                         
8478                         # this can trigger all kinds of weird errors if it is a non /dev path, like: remote:/machine/name
8479                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
8480                                 if [[ -n $DEV_DISK_UUID && -z $dev_uuid ]];then
8481                                         dev_uuid=$( echo "$DEV_DISK_UUID" | gawk  '
8482                                         /'$dev_item'$/ {
8483                                                 print $(NF - 2)
8484                                                 exit
8485                                         }' )
8486                                 fi
8487                                 if [[ -n $DEV_DISK_LABEL && -z $dev_label ]];then
8488                                         dev_label=$( echo "$DEV_DISK_LABEL" | gawk '
8489                                         /'$dev_item'$/ {
8490                                                 print $(NF - 2)
8491                                                 exit
8492                                         }' )
8493                                 fi
8494                         fi
8495
8496                         # assemble everything we could get for dev/h/dx, label, and uuid
8497                         IFS=","
8498                         A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","${a_partition_working[5]}","$dev_item","$dev_label","$dev_uuid
8499                         IFS="$ORIGINAL_IFS"
8500                 done
8501                 log_function_data 'cat' "$FILE_MOUNTS"
8502         else
8503                 if [[ $BSD_TYPE == 'bsd' ]];then
8504                         get_partition_data_advanced_bsd
8505                 fi
8506         fi
8507         a_temp=${A_PARTITION_DATA[@]}
8508         # echo $a_temp
8509         log_function_data "3-advanced: A_PARTITION_DATA:\n$a_temp"
8510         eval $LOGFE
8511 }
8512
8513 get_partition_data_advanced_bsd()
8514 {
8515         eval $LOGFS
8516         local gpart_data="$( gpart list 2>/dev/null )"
8517         local a_partition_working='' label_uuid='' dev_item=''
8518         
8519         if [[ -n $gpart_data ]];then
8520                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
8521                 do
8522                         IFS=","
8523                         a_partition_working=( ${A_PARTITION_DATA[i]} )
8524                         IFS="$ORIGINAL_IFS"
8525                         # no need to use the rest of the name if it's not a straight /dev/item
8526                         dev_item=${a_partition_working[6]##*/}
8527                         
8528                         label_uuid=$( gawk -F ':' '
8529                         BEGIN {
8530                                 IGNORECASE=1
8531                                 label=""
8532                                 uuid=""
8533                         }
8534                         /^[0-9]+\.[[:space:]]*Name.*'$dev_item'/ {
8535                                 while ( getline && $1 !~ /^[0-9]+\.[[:space:]]*Name/ ) {
8536                                         if ( $1 ~ /rawuuid/ ) {
8537                                                 gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
8538                                                 uuid=$2
8539                                         }
8540                                         if ( $1 ~ /label/ ) {
8541                                                 gsub(/^[[:space:]]+|[[:space:]]+$|none|\(null\)/,"",$2)
8542                                                 label=$2
8543                                         }
8544                                 }
8545                                 print label","uuid
8546                                 exit
8547                         }' <<< "$gpart_data" )
8548
8549                         # assemble everything we could get for dev/h/dx, label, and uuid
8550                         IFS=","
8551                         A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","${a_partition_working[5]}","${a_partition_working[6]}","$label_uuid
8552                         IFS="$ORIGINAL_IFS"
8553                 done
8554         fi
8555         eval $LOGFE
8556 }
8557
8558 # args: $1 - uuid/label/id/mapper
8559 get_partition_dev_data()
8560 {
8561         eval $LOGFS
8562         
8563         # only run these tests once per directory to avoid excessive queries to fs
8564         case $1 in
8565                 id)
8566                         if [[ $B_ID_SET != 'true' ]];then
8567                                 if [[ -d /dev/disk/by-id ]];then
8568                                         DEV_DISK_ID="$( ls -l /dev/disk/by-id )"
8569                                 fi
8570                                 B_ID_SET='true'
8571                         fi
8572                         ;;
8573                 label)
8574                         if [[ $B_LABEL_SET != 'true' ]];then
8575                                 if [[ -d /dev/disk/by-label ]];then
8576                                         DEV_DISK_LABEL="$( ls -l /dev/disk/by-label )"
8577                                 fi
8578                                 B_LABEL_SET='true'
8579                         fi
8580                         ;;
8581                 mapper)
8582                         if [[ $B_MAPPER_SET != 'true' ]];then
8583                                 if [[ -d /dev/mapper ]];then
8584                                         DEV_DISK_MAPPER="$( ls -l /dev/mapper )"
8585                                 fi
8586                                 B_MAPPER_SET='true'
8587                         fi
8588                         ;;
8589                 uuid)
8590                         if [[ $B_UUID_SET != 'true' ]];then
8591                                 if [[ -d /dev/disk/by-uuid ]];then
8592                                         DEV_DISK_UUID="$( ls -l /dev/disk/by-uuid )"
8593                                 fi
8594                                 B_UUID_SET='true'
8595                         fi
8596                         ;;
8597                 
8598         esac
8599         log_function_data 'raw' "DEV_DISK_LABEL:\n$DEV_DISK_LABEL\n\nDEV_DISK_UUID:\n$DEV_DISK_UUID\n\nDEV_DISK_ID:\n$DEV_DISK_ID\n\nDEV_DISK_MAPPER:\n$DEV_DISK_MAPPER"
8600         # debugging section, uncomment to insert user data
8601 #       DEV_DISK_LABEL='
8602 #
8603 # '
8604 # DEV_DISK_UUID='
8605 #
8606 # '
8607 # DEV_DISK_MAPPER='
8608 #
8609 # '
8610         eval $LOGFE
8611 }
8612
8613 # args: $1 - dev item, check for mapper, then get actual dev item if mapped
8614 # eg: lrwxrwxrwx 1 root root       7 Sep 26 15:10 truecrypt1 -> ../dm-2 
8615 get_dev_processed_item()
8616 {
8617         eval $LOGFS
8618         
8619         local dev_item=$1 dev_return=''
8620         
8621         if [[ -n $DEV_DISK_MAPPER && -n $( grep -is 'mapper/' <<< $dev_item ) ]];then
8622                 dev_return=$( echo "$DEV_DISK_MAPPER" | gawk '
8623                 $( NF - 2 ) ~ /^'${dev_item##*/}'$/ {
8624                         item=gensub( /..\/(.+)/, "\\1", 1, $NF )
8625                         print item
8626                 }' )
8627         fi
8628         if [[ -z $dev_return ]];then
8629                 dev_return=$dev_item
8630         fi
8631         
8632         echo $dev_return
8633
8634         eval $LOGFE
8635 }
8636
8637 get_patch_version_string()
8638 {
8639         local patch_version_number=$( sed 's/^[0]*//' <<< $SCRIPT_PATCH_NUMBER )
8640         
8641         if [[ -n $patch_version_number ]];then
8642                 patch_version_number="-$patch_version_number"
8643                 # for cases where it was for example: 00-bsd cleaned to --bsd trim out one -
8644                 if [[ -n $( grep '\--' <<< $patch_version_number ) ]];then
8645                         patch_version_number=$( sed 's/--/-/' <<< $patch_version_number )
8646                 fi
8647         fi
8648         echo $patch_version_number
8649 }
8650
8651 get_pciconf_data()
8652 {
8653         eval $LOGFS
8654         
8655         local pciconf_data='' a_temp=''
8656         
8657         if [[ $B_PCICONF == 'true' ]];then
8658                 pciconf_data="$( pciconf -lv 2>/dev/null )"
8659                 if [[ -n $pciconf_data ]];then
8660                         pciconf_data=$( gawk '
8661                         BEGIN {
8662                                 IGNORECASE=1
8663                         }
8664                         {
8665                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
8666                                         gsub(/[[:space:]]+=[[:space:]]+/, "=",$0)
8667                                         gsub(/^[[:space:]]+|'"'"'|\"|,/, "", $0)
8668                                         gsub(/=0x/,"=",$0)
8669                                         # line=gensub(/.*[[:space:]]+(class=[^[:space:]]*|card=[^[:space:]]*)|chip=[^[:space:]]*|rev=[^[:space:]]*|hdr=[^[:space:]]*).*/,"\n\\1","g",$0)
8670                                         line=gensub(/(.*@.*)/,"\n\\1",$0)
8671                                         print line
8672                         }' <<< "$pciconf_data" )
8673                         # create empty last line with this spacing trick
8674                         pciconf_data="$pciconf_data
8675
8676 EOF"
8677                         # echo "$pciconf_data"
8678                         # now insert into arrays
8679                         IFS=$'\n'
8680                         A_PCICONF_DATA=( $( gawk '
8681                         BEGIN {
8682                                 fullLine=""
8683                                 driver=""
8684                                 vendor=""
8685                                 device=""
8686                                 class=""
8687                                 chipId=""
8688                                 pciId=""
8689                                 itemData=""
8690                                 IGNORECASE=1
8691                         }
8692                         /^.*@/ {
8693                                 pciId=""
8694                                 vendor=""
8695                                 class=""
8696                                 driver=""
8697                                 device=""
8698                                 chipId=""
8699                                 itemData=$1
8700                                 
8701                                 driver=gensub(/^([^@]+)@.*/, "\\1", itemData )
8702                                 pciId=gensub(/^.*@pci([0-9\.:]+).*/, "\\1", itemData )
8703                                 sub(/:$/, "", pciId)
8704                                 itemData=$4
8705                                 chipId=gensub(/.*chip=([0-9a-f][0-9a-f][0-9a-f][0-9a-f])([0-9a-f][0-9a-f][0-9a-f][0-9a-f]).*/, "\\2:\\1", itemData )
8706                                 if ( $2 ~ /class=020000/ ) {
8707                                         class="network"
8708                                 }
8709                                 else if ( $2 == "class=030000" ) {
8710                                         class="display"
8711                                 }
8712                                 else if ( $2 ~ /class=040300|class=040100/ ) {
8713                                         class="audio"
8714                                 }
8715                                 
8716                                 while ( getline && $1 !~ /^$/ ) {
8717                                         if ( $1 ~ /^vendor/ ) {
8718                                                 sub(/^vendor=/, "", $1 )
8719                                                 vendor=$0
8720                                         }
8721                                         else if ( $1 ~ /^device/ ) {
8722                                                 sub(/^device=/, "", $1 )
8723                                                 device=$0
8724                                         }
8725                                         else if ( $1 ~ /^class=/ && class == "" ) {
8726                                                 sub(/^class=/, "", $1)
8727                                                 class=$0
8728                                         }
8729                                 }
8730                                 if ( device == "" ) {
8731                                         device=vendor
8732                                 }
8733                                 fullLine=class "," device "," vendor "," driver "," pciId "," chipId
8734                                 print fullLine
8735                         }' <<< "$pciconf_data" ))
8736                         IFS="$ORIGINAL_IFS"
8737                 fi
8738         else
8739                 A_PCICONF_DATA='pciconf-not-installed'
8740         fi
8741         B_PCICONF_SET='true'
8742         a_temp=${A_PCICONF_DATA[@]}
8743         log_function_data "$a_temp"
8744         log_function_data "$pciconf_data"
8745         eval $LOGFE
8746 }
8747
8748 # packs standard card arrays using the pciconf stuff
8749 # args: $1 - audio/network/display - matches first item in A_PCICONF_DATA arrays
8750 get_pciconf_card_data()
8751 {
8752         eval $LOGFS
8753         local a_temp='' array_string='' j=0 device_string=''
8754         local ip_tool_command=$( type -p ifconfig )
8755         local mac='' state='' speed='' duplex='' network_string=''
8756         
8757         for (( i=0;i<${#A_PCICONF_DATA[@]};i++ ))
8758         do
8759                 IFS=','
8760                 a_temp=( ${A_PCICONF_DATA[i]} )
8761                 IFS="$ORIGINAL_IFS"
8762                 
8763                 if [[ ${a_temp[0]} == $1 ]];then
8764                         # don't print the vendor if it's already in the device name
8765                         if [[ -z $( grep -i "${a_temp[2]}" <<< "${a_temp[1]}" ) ]];then
8766                                 device_string="${a_temp[2]} ${a_temp[1]}"
8767                         else
8768                                 device_string=${a_temp[1]}
8769                         fi
8770                         case $1 in
8771                                 audio)
8772                                         array_string="$device_string,${a_temp[3]},,,${a_temp[4]},,${a_temp[5]}"
8773                                         A_AUDIO_DATA[j]=$array_string
8774                                         ;;
8775                                 display)
8776                                         array_string="$device_string,${a_temp[4]},${a_temp[5]}"
8777                                         A_GRAPHICS_CARD_DATA[j]=$array_string
8778                                         ;;
8779                                 network)
8780                                         if [[ -n $ip_tool_command && -n ${a_temp[3]} ]];then
8781                                                 network_string=$(       $ip_tool_command ${a_temp[3]} | gawk '
8782                                                 BEGIN {
8783                                                         IGNORECASE=1
8784                                                         mac=""
8785                                                         state=""
8786                                                         speed=""
8787                                                         duplex=""
8788                                                 }
8789                                                 /^[[:space:]]*ether/ {
8790                                                         mac = $2
8791                                                 }
8792                                                 /^[[:space:]]*media/ {
8793                                                         if ( $0 ~ /<.*>/ ) {
8794                                                                 duplex=gensub(/.*<([^>]+)>.*/,"\\1",$0)
8795                                                         }
8796                                                         if ( $0 ~ /\(.*\)/ ) {
8797                                                                 speed=gensub(/.*\(([^<[:space:]]+).*\).*/,"\\1",$0)
8798                                                         }
8799                                                 }
8800                                                 /^[[:space:]]*status/ {
8801                                                         sub(/.*status[:]?[[:space:]]*/,"", $0)
8802                                                         state=$0
8803                                                 }
8804                                                 END {
8805                                                         print state "~" speed "~" mac "~" duplex
8806                                                 }')
8807                                         fi
8808                                         if [[ -n $network_string ]];then
8809                                                 mac=$( cut -d '~' -f 3 <<< $network_string )
8810                                                 state=$( cut -d '~' -f 1 <<< $network_string )
8811                                                 speed=$( cut -d '~' -f 2 <<< $network_string )
8812                                                 duplex=$( cut -d '~' -f 4 <<< $network_string )
8813                                         fi
8814                                         array_string="$device_string,${a_temp[3]},,,${a_temp[4]},${a_temp[3]},$state,$speed,$duplex,$mac,${a_temp[5]}"
8815                                         A_NETWORK_DATA[j]=$array_string
8816                                         ;;
8817                         esac
8818                         ((j++))
8819                 fi
8820         done
8821         
8822         eval $LOGFE
8823 }
8824
8825 # args: $1 - type cpu/mem 
8826 get_ps_tcm_data()
8827 {
8828         eval $LOGFS
8829         local array_length='' reorder_temp='' i=0 head_tail='' sort_type='' ps_data=''
8830         
8831         # bummer, have to make it more complex here because of reverse sort
8832         # orders in output, pesky lack of support of +rss in old systems
8833         case $1 in
8834                 mem)
8835                         if [[ $BSD_TYPE != 'bsd' ]];then
8836                                 sort_type='ps aux --sort -rss'
8837                                 head_tail='head'
8838                         else
8839                                 sort_type='ps aux -m'
8840                                 head_tail='head'
8841                         fi
8842                         ;;
8843                 cpu)
8844                         if [[ $BSD_TYPE != 'bsd' ]];then
8845                                 sort_type='ps aux --sort %cpu'
8846                                 head_tail='tail'
8847                         else
8848                                 sort_type='ps aux -r'
8849                                 head_tail='head'
8850                         fi
8851                         ;;
8852         esac
8853         
8854         # throttle potential irc abuse
8855         if [[ $B_IRC == 'true' && $PS_COUNT -gt 5 ]];then
8856                 PS_THROTTLED=$PS_COUNT
8857                 PS_COUNT=5
8858         fi
8859         # use eval here to avoid glitches with -
8860         ps_data="$( eval $sort_type )"
8861
8862         IFS=$'\n'
8863         # note that inxi can use a lot of cpu, and can actually show up here as the script runs
8864         A_PS_DATA=( $( echo "$ps_data" | grep -Ev "($SCRIPT_NAME|%CPU|[[:space:]]ps[[:space:]])" | $head_tail -n $PS_COUNT | gawk '
8865         BEGIN {
8866                 IGNORECASE=1
8867                 appName=""
8868                 appPath=""
8869                 appStarterName=""
8870                 appStarterPath=""
8871                 cpu=""
8872                 mem=""
8873                 pid=""
8874                 user=""
8875                 rss=""
8876         }
8877         {
8878                 cpu=$3
8879                 mem=$4
8880                 pid=$2
8881                 user=$1
8882                 rss=sprintf( "%.2f", $6/1024 )
8883                 # have to get rid of [,],(,) eg: [lockd] which break the printout function compare in bash
8884                 gsub(/\[|\]|\(|\)/,"~", $0 )
8885                 if ( $12 ~ /^\// ){
8886                         appStarterPath=$11
8887                         appPath=$12
8888                 }
8889                 else {
8890                         appStarterPath=$11
8891                         appPath=$11
8892                 }
8893                 appStarterName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appStarterPath )
8894                 appName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appPath )
8895                 print appName "," appPath "," appStarterName "," appStarterPath "," cpu "," mem "," pid "," rss "," user
8896         }
8897         ' ) )
8898         # make the array ordered highest to lowest so output looks the way we expect it to
8899         # this isn't necessary for -rss, and we can't make %cpu ordered the other way, so
8900         # need to reverse it here. -rss is used because on older systems +rss is not supported
8901         if [[ $1 == 'cpu' && $BSD_TYPE != 'bsd' ]];then
8902                 array_length=${#A_PS_DATA[@]}; 
8903                 while (( $i < $array_length/2 ))
8904                 do 
8905                         reorder_temp=${A_PS_DATA[i]}f
8906                         A_PS_DATA[i]=${A_PS_DATA[$array_length-$i-1]}
8907                         A_PS_DATA[$array_length-$i-1]=$reorder_temp
8908                         (( i++ ))
8909                 done 
8910         fi
8911
8912         IFS="$ORIGINAL_IFS"
8913         
8914 #       echo ${A_PS_DATA[@]}
8915         eval $LOGFE
8916 }
8917
8918 # mdstat syntax information: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
8919 # note that this does NOT use either Disk or Partition information for now, ie, there
8920 # is no connection between the data types, but the output should still be consistent
8921 get_raid_data()
8922 {
8923         eval $LOGFS
8924         
8925         local mdstat=''
8926                 
8927         if [[ $B_MDSTAT_FILE == 'true' ]];then
8928                 mdstat="$( cat $FILE_MDSTAT 2>/dev/null )"
8929         fi
8930         
8931         if [[ -n $mdstat ]];then
8932                 # need to make sure there's always a newline in front of each record type, and
8933                 # also correct possible weird formats for the output from older kernels etc.
8934                 mdstat="$( sed -e 's/^md/\nmd/' -e 's/^unused[[:space:]]/\nunused /' \
8935                 -e 's/read_ahead/\nread_ahead/' -e 's/^resync=/\nresync=/' -e 's/^Event/\nEvent/' \
8936                 -e 's/^[[:space:]]*$//' -e 's/[[:space:]]read_ahead/\nread_ahead/' <<< "$mdstat" )"
8937                 # some fringe cases do not end as expected, so need to add newlines plus EOF to make sure while loop doesn't spin
8938                 mdstat=$( echo -e "$mdstat\n\nEOF" )
8939
8940                 IFS=$'\n'
8941                 A_RAID_DATA=( $(
8942                 gawk '
8943                 BEGIN {
8944                         IGNORECASE=1
8945                         RS="\n"
8946                 }
8947                 
8948                 /^personalities/ {
8949                         KernelRaidSupport = gensub(/personalities[[:space:]]*:[[:space:]]*(.*)/, "\\1", 1, $0)
8950                         # clean off the brackets
8951                         gsub(/[\[\]]/,"",KernelRaidSupport)
8952                         print "KernelRaidSupport," KernelRaidSupport
8953                 }
8954                 /^read_ahead/ {
8955                         ReadAhead=gensub(/read_ahead (.*)/, "\\1", 1 )
8956                         print "ReadAhead," ReadAhead
8957                 }
8958                 /^Event:/ {
8959                         print "raidEvent," $NF
8960                 }
8961                 # print logic will search for this value and use it to print out the unused devices data
8962                 /^unused devices/ {
8963                         unusedDevices = gensub(/^unused devices:[[:space:]][<]?([^>]*)[>]?.*/, "\\1", 1, $0)
8964                         print "UnusedDevices," unusedDevices
8965                 }
8966                 
8967                 /^md/ {
8968                         # reset for each record loop through
8969                         deviceState = ""
8970                         bitmapValues = ""
8971                         blocks = ""
8972                         chunkSize = ""
8973                         components = ""
8974                         device = ""
8975                         deviceReport = ""
8976                         finishTime = ""
8977                         recoverSpeed = ""
8978                         recoveryProgressBar = ""
8979                         recoveryPercent = ""
8980                         raidLevel = ""
8981                         sectorsRecovered = ""
8982                         separator = ""
8983                         superBlock = ""
8984                         uData = ""
8985                         
8986                         while ( !/^[[:space:]]*$/  ) {
8987                                 gsub(/'"$BAN_LIST_ARRAY"'/, " ", $0 )
8988                                 gsub(/[[:space:]]+/, " ", $0 )
8989                                 if ( $0 ~ /^md/ ) {
8990                                         device = gensub(/(md.*)[[:space:]]?:/, "\\1", "1", $1 )
8991                                 }
8992                                 if ( $0 ~ /mirror|raid[0-9]+/ ) {
8993                                         raidLevel = gensub(/(.*)raid([0-9]+)(.*)/, "\\2", "g", $0 )
8994                                 }
8995                                 if ( $0 ~ /(active \(auto-read-only\)|active|inactive)/ ) {
8996                                         deviceState = gensub(/(.*) (active \(auto-read-only\)|active|inactive) (.*)/, "\\2", "1", $0 )
8997                                 }
8998                                 # gawk will not return all the components using gensub, only last one
8999                                 separator = ""
9000                                 for ( i=3; i<=NF; i++ ) {
9001                                         if ( $i ~ /[hs]d[a-z][0-9]*(\[[0-9]+\])?(\([SF]\))?/ ) {
9002                                                 components = components separator $i
9003                                                 separator=" "
9004                                         }
9005                                 }
9006                                 if ( $0 ~ /blocks/ ) {
9007                                         blocks = gensub(/(.*[[:space:]]+)?([0-9]+)[[:space:]]blocks.*/, "\\2", "1", $0)
9008                                 }
9009                                 if ( $0 ~ /super[[:space:]][0-9\.]+/ ) {
9010                                         superBlock = gensub(/.*[[:space:]]super[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
9011                                 }
9012                                 if ( $0 ~ /algorithm[[:space:]][0-9\.]+/ ) {
9013                                         algorithm = gensub(/.*[[:space:]]algorithm[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
9014                                 }
9015                                 if ( $0 ~ /\[[0-9]+\/[0-9]+\]/ ) {
9016                                         deviceReport = gensub(/.*[[:space:]]\[([0-9]+\/[0-9]+)\][[:space:]].*/, "\\1", "1", $0)
9017                                         uData = gensub(/.*[[:space:]]\[([U_]+)\]/, "\\1", "1", $0)
9018                                 }
9019                                 # need to avoid this:  bitmap: 0/10 pages [0KB], 16384KB chunk
9020                                 # while currently all the normal chunks are marked with k, not kb, this can change in the future
9021                                 if ( $0 ~ /[0-9]+[k] chunk/ && $0 !~ /bitmap/ ) {
9022                                         chunkSize = gensub(/(.*) ([0-9]+[k]) chunk.*/, "\\2", "1", $0)
9023                                 }
9024                                 if ( $0 ~ /^resync=/ ) {
9025                                         sub(/resync=/,"")
9026                                         print "resyncStatus," $0
9027                                 }
9028                                 if ( $0 ~ /\[[=]*>[\.]*\].*(resync|recovery)/ ) {
9029                                         recoveryProgressBar = gensub(/.*(\[[=]*>[\.]*\]).*/, "\\1",1,$0)
9030                                 }
9031                                 if ( $0 ~ / (resync|recovery)[[:space:]]*=/ ) {
9032                                         recoveryPercent = gensub(/.* (resync|recovery)[[:space:]]*=[[:space:]]*([0-9\.]+%).*/, "\\1~\\2", 1 )
9033                                         if ( $0 ~ /[[:space:]]\([0-9]+\/[0-9]+\)/ ) {
9034                                                 sectorsRecovered = gensub(/.* \(([0-9]+\/[0-9]+)\).*/, "\\1", 1, $0 )
9035                                         }
9036                                         if ( $0 ~ /finish[[:space:]]*=/ ) {
9037                                                 finishTime = gensub(/.* finish[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+) .*/, "\\1 \\2", 1, $0 )
9038                                         }
9039                                         if ( $0 ~ /speed[[:space:]]*=/ ) {
9040                                                 recoverSpeed = gensub(/.* speed[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+\/[a-z]+)/, "\\1 \\2", 1, $0 )
9041                                         }
9042                                 }
9043                                 if ( $0 ~ /bitmap/ ) {
9044                                         bitmapValues = gensub(/(.*[[:space:]])?bitmap:(.*)/, "\\2", 1, $0 )
9045                                 }
9046                                 
9047                                 getline
9048                         }
9049                         raidString = device "," deviceState "," raidLevel "," components "," deviceReport "," uData 
9050                         raidString = raidString "," blocks "," superBlock "," algorithm "," chunkSize "," bitmapValues
9051                         raidString = raidString "," recoveryProgressBar "," recoveryPercent "," sectorsRecovered "," finishTime "," recoverSpeed
9052                         
9053                         print raidString
9054                 }
9055                 ' <<< "$mdstat" ) )
9056                 IFS="$ORIGINAL_IFS"
9057         else
9058                 if [[ $BSD_TYPE == 'bsd' ]];then
9059                         get_raid_data_bsd
9060                 fi
9061         fi
9062         B_RAID_SET='true'
9063         a_temp=${A_RAID_DATA[@]}
9064         log_function_data "A_RAID_DATA: $a_temp"
9065 #       echo -e "A_RAID_DATA:\n${a_temp}"
9066         
9067         eval $LOGFE
9068 }
9069
9070 get_raid_data_bsd()
9071 {
9072         eval $LOGFS
9073         local zpool_path=$( type -p zpool 2>/dev/null )
9074         local zpool_data='' zpool_arg='v'
9075         
9076         if [[ -n $zpool_path ]];then
9077                 B_BSD_RAID='true'
9078                 # bsd sed does not support inserting a true \n so use this trick
9079                 # some zfs does not have -v
9080                 if $zpool_path list -v &>/dev/null;then
9081                         zpool_data="$( $zpool_path list -v 2>/dev/null | sed $SED_RX 's/^([^[:space:]])/\
9082 \1/' )"
9083                 else
9084                         zpool_data="$( $zpool_path list 2>/dev/null | sed $SED_RX 's/^([^[:space:]])/\
9085 \1/' )"
9086                         zpool_arg='no-v'
9087                 fi
9088 #               echo "$zpool_data"
9089                 IFS=$'\n'
9090                 A_RAID_DATA=( $(
9091                 gawk '
9092                 BEGIN {
9093                         IGNORECASE=1
9094                         raidString=""
9095                         separator=""
9096                         components=""
9097                         reportSize=""
9098                         blocksAvailable=""
9099                         chunkRaidAllocated=""
9100                 }
9101                 /SIZE.*ALLOC/ {
9102                         sub(/.*ALLOC.*/,"", $0)
9103                 }
9104                 # gptid/d874c7e7-3f6d-11e4-b7dc-080027ea466c
9105                 /^[^[:space:]]/ {
9106                         components=""
9107                         separator=""
9108                         raidLevel=""
9109                         device=$1
9110                         deviceState=$7
9111                         reportSize=$2
9112                         blocksAvailable=$4
9113                         chunkRaidAllocated=$3
9114                         
9115                         getline
9116                         # raid level is the second item in the output, unless it is not, sometimes it is absent
9117                         if ( $1 != "" ) {
9118                                 if ( $1 ~ /raid|mirror/ ) {
9119                                         raidLevel="zfs " $1
9120                                 }
9121                                 else {
9122                                         raidLevel="zfs-no-raid"
9123                                         components = $1
9124                                         separator=" "
9125                                 }
9126                         }
9127                         
9128                         while ( getline && $1 !~ /^$/ ) {
9129                                 # https://blogs.oracle.com/eschrock/entry/zfs_hot_spares
9130                                 if ($1 ~ /spares/) {
9131                                         getline
9132                                 }
9133                                 # print $1
9134                                 components = components separator $1
9135                                 separator=" "
9136                         }
9137                         # some issues if we use ~ here
9138                         gsub(/\//,"%",components)
9139                         # print $1
9140                         raidString = device "," deviceState "," raidLevel "," components "," reportSize "," uData 
9141                         raidString = raidString "," blocksAvailable "," superBlock "," algorithm "," chunkRaidAllocated 
9142                         # none of these are used currently
9143                         raidString = raidString "," bitmapValues  "," recoveryProgressBar "," recoveryPercent 
9144                         raidString = raidString "," sectorsRecovered "," finishTime "," recoverSpeed
9145                         gsub(/~/,"",raidString)
9146                         print raidString
9147                 }' <<< "$zpool_data" ) )
9148                 IFS="$ORIGINAL_IFS"
9149                 # pass the zpool type, so we know how to get the components
9150                 get_raid_component_data_bsd "$zpool_arg"
9151         fi
9152         eval $LOGFE
9153 }
9154
9155 # note, we've already tested for zpool so no further tests required
9156 # args: $1 - zpool type, v will have a single row output, no-v has stacked for components
9157 get_raid_component_data_bsd()
9158 {
9159         eval $LOGFS
9160         local a_raid_data='' array_string='' component='' component_string='' 
9161         local zpool_status='' device='' separator='' component_status=''
9162         
9163         for (( i=0; i<${#A_RAID_DATA[@]}; i++))
9164         do
9165                 IFS=","
9166                 a_raid_data=( ${A_RAID_DATA[i]} )
9167                 IFS="$ORIGINAL_IFS"
9168                 separator=''
9169                 component_string=''
9170                 component_status=''
9171                 zpool_status=''
9172                 device=${a_raid_data[0]}
9173                 zpool_status="$( zpool status $device )"
9174                 # we will remove ONLINE for status and only use OFFLINE/DEGRADED as tests
9175                 # for print output display of issues with components
9176                 # note: different zfs outputs vary, some have the components listed by line
9177                 if [[ $1 == 'v' ]];then
9178                         for component in ${a_raid_data[3]}
9179                         do
9180                                 component_status=$( gawk '
9181                                 BEGIN {
9182                                         IGNORECASE=1
9183                                         separator=""
9184                                 }
9185                                 {
9186                                         gsub(/\//,"%",$1)
9187                                 }
9188                                 $1 ~ /^'$component'$/ {
9189                                         sub( /ONLINE/, "", $2 )
9190                                         print "'$component'" $2
9191                                         exit
9192                                 }' <<< "$zpool_status" )
9193                                 component_string="$component_string$separator$component_status"
9194                                 separator=' '
9195                         done
9196                         array_string="$device,${a_raid_data[1]},${a_raid_data[2]},${component_string//%/\/},${a_raid_data[4]}"
9197                         array_string="$array_string,${a_raid_data[5]},${a_raid_data[6]},${a_raid_data[7]},${a_raid_data[8]}"
9198                         array_string="$array_string,${a_raid_data[9]},${a_raid_data[10]},${a_raid_data[11]},${a_raid_data[12]},"
9199                         array_string="$array_string${a_raid_data[13]},${a_raid_data[14]},${a_raid_data[15]}"
9200                 else
9201                         component_string=$( gawk '
9202                         BEGIN {
9203                                 IGNORECASE=1
9204                                 separator=""
9205                                 components=""
9206                                 raidLevel=""
9207                         }
9208                         $1 ~ /^'$device'$/ {
9209                                 while ( getline && !/^$/ ) {
9210                                         # raid level is the second item in the output, unless it is not, sometimes it is absent
9211                                         if ( $1 != "" ) {
9212                                                 if ( raidLevel == "" ) {
9213                                                         if (  $1 ~ /raid|mirror/ ) {
9214                                                                 raidLevel="zfs " $1
9215                                                                 getline
9216                                                         }
9217                                                         else {
9218                                                                 raidLevel="zfs-no-raid"
9219                                                         }
9220                                                 }
9221                                         }
9222                                         # https://blogs.oracle.com/eschrock/entry/zfs_hot_spares
9223                                         if ($1 ~ /spares/) {
9224                                                 getline
9225                                         }
9226                                         sub( /ONLINE/, "", $2 )
9227                                         components=components separator $1 separator $2
9228                                         separator=" "
9229                                 }
9230                                 print raidLevel "," components
9231                         }' <<< "$zpool_status" )
9232                         # note: component_string is raid type AND components
9233                         array_string="$device,${a_raid_data[1]},$component_string,${a_raid_data[4]}"
9234                         array_string="$array_string,${a_raid_data[5]},${a_raid_data[6]},${a_raid_data[7]},${a_raid_data[8]}"
9235                         array_string="$array_string,${a_raid_data[9]},${a_raid_data[10]},${a_raid_data[11]},${a_raid_data[12]},"
9236                         array_string="$array_string${a_raid_data[13]},${a_raid_data[14]},${a_raid_data[15]}"
9237                 fi
9238                 IFS=","
9239                 A_RAID_DATA[i]=$array_string
9240                 IFS="$ORIGINAL_IFS"
9241         done
9242         
9243         eval $LOGFE
9244 }
9245 # get_raid_data_bsd;exit
9246
9247 get_ram_data()
9248 {
9249         eval $LOGFS
9250         
9251         local a_temp='' array_string=''
9252         
9253         get_dmidecode_data
9254         
9255         if [[ -n $DMIDECODE_DATA ]];then
9256                 if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
9257                         A_MEMORY_DATA[0]=$DMIDECODE_DATA
9258                 # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
9259                 else
9260                         IFS=$'\n'
9261                         A_MEMORY_DATA=( $( 
9262                         gawk -F ':' '
9263                         BEGIN {
9264                                 IGNORECASE=1
9265                                 arrayHandle=""
9266                                 bankLocator=""
9267                                 clockSpeed=""
9268                                 configuredClockSpeed=""
9269                                 dataWidth=""
9270                                 deviceManufacturer=""
9271                                 devicePartNumber=""
9272                                 deviceSerialNumber=""
9273                                 deviceSpeed=""
9274                                 deviceType=""
9275                                 deviceTypeDetail=""
9276                                 deviceSize=""
9277                                 errorCorrection=""
9278                                 formFactor=""
9279                                 handle=""
9280                                 location=""
9281                                 locator=""
9282                                 aArrayData[0,"maxCapacity5"]=0
9283                                 aArrayData[0,"maxCapacity16"]=0
9284                                 aArrayData[0,"usedCapacity"]=0
9285                                 aArrayData[0,"maxModuleSize"]=0
9286                                 aArrayData[0,"derivedModuleSize"]=0
9287                                 aArrayData[0,"deviceCount5"]=0
9288                                 aArrayData[0,"deviceCount16"]=0
9289                                 aArrayData[0,"deviceCountFound"]=0
9290                                 aArrayData[0,"moduleVoltage5"]=""
9291                                 moduleVoltage=""
9292                                 numberOfDevices=""
9293                                 primaryType=""
9294                                 totalWidth=""
9295                                 use=""
9296                                 i=0
9297                                 j=0
9298                                 k=0
9299                                 bDebugger1="false"
9300                                 dDebugger2="false"
9301                                 bType5="false"
9302                         }
9303                         function calculateSize(data,size) {
9304                                 if ( data ~ /^[0-9]+[[:space:]]*[GMTP]B/) {
9305                                         if ( data ~ /GB/ ) {
9306                                                 data=gensub(/([0-9]+)[[:space:]]*GB/,"\\1",1,data) * 1024
9307                                         }
9308                                         else if ( data ~ /MB/ ) {
9309                                                 data=gensub(/([0-9]+)[[:space:]]*MB/,"\\1",1,data)
9310                                         }
9311                                         else if ( data ~ /TB/ ) {
9312                                                 data=gensub(/([0-9]+)[[:space:]]*TB/,"\\1",1,data) * 1024 * 1000
9313                                         }
9314                                         else if ( data ~ /PB/ ) {
9315                                                 data=gensub(/([0-9]+)[[:space:]]*TB/,"\\1",1,data) * 1024 * 1000 * 1000
9316                                         }
9317                                         if (data ~ /^[0-9][0-9]+$/ && data > size ) {
9318                                                 size=data
9319                                         }
9320                                 }
9321                                 return size
9322                         }
9323                         /^Table[[:space:]]+at[[:space:]]/ {
9324                                 bType5="false"
9325                                 # we need to start count here because for testing > 1 array, and we want always to have
9326                                 # the actual module data assigned to the right primary array, even when it is out of
9327                                 # position in dmidecode output
9328                                 i=0
9329                                 j=0
9330                                 k++
9331                         }
9332                         # {print k ":k:" $0}
9333                         /^Handle .* DMI[[:space:]]+type[[:space:]]+5(,|[[:space:]])/ {
9334                                 while ( getline && !/^$/ ) {
9335                                         if ( $1 == "Maximum Memory Module Size" ) {
9336                                                 aArrayData[k,"maxModuleSize"]=calculateSize($2,aArrayData[k,"maxModuleSize"])
9337                                                 # print "mms:" aArrayData[k,"maxModuleSize"] ":" $2
9338                                         }
9339                                         if ($1 == "Maximum Total Memory Size") {
9340                                                 aArrayData[k,"maxCapacity5"]=calculateSize($2,aArrayData[k,"maxCapacity5"])
9341                                         }
9342                                         if ( $1 == "Memory Module Voltage" ) {
9343                                                 aArrayData[k,"moduleVoltage5"]=$2
9344                                         }
9345                                 }
9346                                 aArrayData[k,"data-type"]="memory-array"
9347                                 # print k ":data5:"aArrayData[k,"data-type"]
9348                                 bType5="true"
9349                         }
9350                         /^Handle .* DMI[[:space:]]+type[[:space:]]+6(,|[[:space:]])/ {
9351                                 while ( getline && !/^$/ ) {
9352                                         if ( $1 == "Installed Size" ) {
9353                                                 # get module size
9354                                                 aMemory[k,j,18]=calculateSize($2,0)
9355                                                 # get data after module size
9356                                                 sub(/ Connection/,"",$2)
9357                                                 sub(/^[0-9]+[[:space:]]*[MGTP]B[[:space:]]*/,"",$2)
9358                                                 aMemory[k,j,16]=$2
9359                                         }
9360                                         if ( $1 == "Current Speed" ) {
9361                                                 aMemory[k,j,17]=$2
9362                                         }
9363                                 }
9364                                 j++
9365                         }
9366                         
9367                         /^Handle .* DMI[[:space:]]+type[[:space:]]+16/ {
9368                                 arrayHandle=gensub(/Handle[[:space:]]([0-9a-zA-Z]+)([[:space:]]|,).*/,"\\1",$0)
9369                                 while ( getline && !/^$/ ) {
9370                                         # print $0
9371                                         if ( $1 == "Maximum Capacity") {
9372                                                 aArrayData[k,"maxCapacity16"]=calculateSize($2,aArrayData[k,"maxCapacity16"])
9373                                                 #print "mc:" aArrayData[k,"maxCapacity16"] ":" $2
9374                                         }
9375                                         # note: these 3 have cleaned data in get_dmidecode_data, so replace stuff manually
9376                                         if ( $1 == "Location") {
9377                                                 sub(/[[:space:]]Or[[:space:]]Motherboard/,"",$2)
9378                                                 location=$2
9379                                                 if ( location == "" ){
9380                                                         location="System Board"
9381                                                 }
9382                                         }
9383                                         if ( $1 == "Use") {
9384                                                 use=$2
9385                                                 if ( use == "" ){
9386                                                         use="System Memory"
9387                                                 }
9388                                         }
9389                                         if ( $1 == "Error Correction Type") {
9390                                                 errorCorrection=$2
9391                                                 if ( errorCorrection == "" ){
9392                                                         errorCorrection="None"
9393                                                 }
9394                                         }
9395                                         if ( $1 == "Number of Devices") {
9396                                                 numberOfDevices=$2
9397                                         }
9398                                 }
9399                                 aArrayData[k,"data-type"]="memory-array"
9400                                 # print k ":data16:"aArrayData[k,"data-type"]
9401                                 aArrayData[k,"handle"]=arrayHandle
9402                                 aArrayData[k,"location"]=location
9403                                 aArrayData[k,"deviceCount16"]=numberOfDevices
9404                                 aArrayData[k,"use"]=use
9405                                 aArrayData[k,"errorCorrection"]=errorCorrection
9406                                 
9407                                 # reset
9408                                 primaryType=""
9409                                 arrayHandle=""
9410                                 location=""
9411                                 numberOfDevices=""
9412                                 use=""
9413                                 errorCorrection=""
9414                                 moduleVoltage=""
9415                                 
9416                                 aDerivedModuleSize[k+1]=0
9417                                 aArrayData[k+1,"deviceCountFound"]=0
9418                                 aArrayData[k+1,"maxCapacity5"]=0
9419                                 aArrayData[k+1,"maxCapacity16"]=0
9420                                 aArrayData[k+1,"maxModuleSize"]=0
9421                         }
9422                         /^Handle .* DMI[[:space:]]+type[[:space:]]+17/ {
9423                                 while ( getline && !/^$/ ) {
9424                                         if ( $1 == "Array Handle") {
9425                                                 arrayHandle=$2
9426                                         }
9427                                         if ( $1 == "Data Width") {
9428                                                 dataWidth=$2
9429                                         }
9430                                         if ( $1 == "Total Width") {
9431                                                 totalWidth=$2
9432                                         }
9433                                         if ( $1 == "Size") {
9434                                                 # do not try to guess from installed modules, only use this to correct type 5 data
9435                                                 aArrayData[k,"derivedModuleSize"]=calculateSize($2,aArrayData[k,"derivedModuleSize"])
9436                                                 workingSize=calculateSize($2,0)
9437                                                 if ( workingSize ~ /^[0-9][0-9]+$/ ){
9438                                                         aArrayData[k,"deviceCountFound"]++
9439                                                         # build up actual capacity found for override tests
9440                                                         aArrayData[k,"usedCapacity"]=workingSize + aArrayData[k,"usedCapacity"]
9441                                                 }
9442                                                 # print aArrayData[k,"derivedModuleSize"] " dm:" k ":mm " aMaxModuleSize[k] " uc:" aArrayData[k,"usedCapacity"]
9443                                                 # we want any non real size data to be preserved
9444                                                 if ( $2 ~ /^[0-9]+[[:space:]]*[MTPG]B/ ) {
9445                                                         deviceSize=workingSize
9446                                                 }
9447                                                 else {
9448                                                         deviceSize=$2
9449                                                 }
9450                                         }
9451                                         if ( $1 == "Locator") {
9452                                                 # sub(/.*_/,"",$2)
9453                                                 #sub(/RAM slot #|^DIMM/, "Slot",$2)
9454                                                 sub(/RAM slot #/, "Slot",$2)
9455                                                 
9456                                                 #locator=toupper($2)
9457                                                 locator=$2
9458                                         }
9459                                         if ( $1 == "Bank Locator") {
9460                                                 #sub(/_.*/,"",$2)
9461                                                 #sub(/RAM slot #|Channel|Chan/,"bank",$2)
9462                                                 #sub(/RAM slot #|Channel|Chan/,"bank",$2)
9463                                                 #bankLocator=toupper($2)
9464                                                 bankLocator=$2
9465                                         }
9466                                         if ( $1 == "Form Factor") {
9467                                                 formFactor=$2
9468                                         }
9469                                         if ( $1 == "Type") {
9470                                                 deviceType=$2
9471                                         }
9472                                         if ( $1 == "Type Detail") {
9473                                                 deviceTypeDetail=$2
9474                                         }
9475                                         if ( $1 == "Speed") {
9476                                                 deviceSpeed=$2
9477                                         }
9478                                         if ( $1 == "Configured Clock Speed") {
9479                                                 configuredClockSpeed=$2
9480                                         }
9481                                         if ( $1 == "Manufacturer") {
9482                                                 gsub(/(^[0]+$|Undefined.*|.*Manufacturer.*)/,"",$2)
9483                                                 deviceManufacturer=$2
9484                                         }
9485                                         if ( $1 == "Part Number") {
9486                                                 sub(/(^[0]+$||.*Module.*|Undefined.*)/,"",$2)
9487                                                 devicePartNumber=$2
9488                                         }
9489                                         if ( $1 == "Serial Number") {
9490                                                 gsub(/(^[0]+$|Undefined.*)/,"",$2)
9491                                                 deviceSerialNumber=$2
9492                                         }
9493                                 }
9494                                 # because of the wide range of bank/slot type data, we will just use
9495                                 # the one that seems most likely to be right. Some have: Bank: SO DIMM 0 slot: J6A
9496                                 # so we dump the useless data and use the one most likely to be visibly correct
9497                                 if ( bankLocator ~ /DIMM/ ) {
9498                                         mainLocator=bankLocator
9499                                 }
9500                                 else {
9501                                         mainLocator=locator
9502                                 }
9503                                 # sometimes the data is just wrong, they reverse total/data. data I believe is
9504                                 # used for the actual memory bus width, total is some synthetic thing, sometimes missing.
9505                                 # note that we do not want a regular string comparison, because 128 bit memory buses are
9506                                 # in our future, and 128 bits < 64 bits with string compare
9507                                 intData=gensub(/(^[0-9]+).*/,"\\1",1,dataWidth)
9508                                 intTotal=gensub(/(^[0-9]+).*/,"\\1",1,totalWidth)
9509                                 if (intData != "" && intTotal != "" && intData > intTotal ) {
9510                                         tempWidth=dataWidth
9511                                         dataWidth=totalWidth
9512                                         totalWidth=tempWidth
9513                                 }
9514                                 
9515                                 aMemory[k,i,0]="memory-device"
9516                                 aMemory[k,i,1]=arrayHandle
9517                                 aMemory[k,i,2]=deviceSize
9518                                 aMemory[k,i,3]=bankLocator
9519                                 aMemory[k,i,4]=locator
9520                                 aMemory[k,i,5]=formFactor
9521                                 aMemory[k,i,6]=deviceType
9522                                 aMemory[k,i,7]=deviceTypeDetail
9523                                 aMemory[k,i,8]=deviceSpeed
9524                                 aMemory[k,i,9]=configuredClockSpeed
9525                                 aMemory[k,i,10]=dataWidth
9526                                 aMemory[k,i,11]=totalWidth
9527                                 aMemory[k,i,12]=deviceManufacturer
9528                                 aMemory[k,i,13]=devicePartNumber
9529                                 aMemory[k,i,14]=deviceSerialNumber
9530                                 aMemory[k,i,15]=mainLocator
9531                                 
9532                                 primaryType=""
9533                                 arrayHandle=""
9534                                 deviceSize=""
9535                                 bankLocator=""
9536                                 locator=""
9537                                 mainLocator=""
9538                                 mainLocator=""
9539                                 formFactor=""
9540                                 deviceType=""
9541                                 deviceTypeDetail=""
9542                                 deviceSpeed=""
9543                                 configuredClockSpeed=""
9544                                 dataWidth=""
9545                                 totalWidth=""
9546                                 deviceManufacturer=""
9547                                 devicePartNumber=""
9548                                 deviceSerialNumber=""
9549                                 i++
9550                         }
9551                         END {
9552                                 ## CRITICAL: gawk keeps changing integers to strings, so be explicit with int() in math
9553                                 # print primaryType "," arrayHandle "," location "," maxCapacity "," numberOfDevices "," use "," errorCorrection "," maxModuleSize "," moduleVoltage
9554                                 
9555                                 # print primaryType "," arrayHandle "," deviceSize "," bankLocator "," locator "," formFactor "," deviceType "," deviceTypeDetail "," deviceSpeed "," configuredClockSpeed "," dataWidth "," totalWidth "," deviceManufacturer "," devicePartNumber "," deviceSerialNumber "," mainLocator
9556                                 
9557                                 for ( m=1;m<=k;m++ ) {
9558                                         estCap=""
9559                                         estMod=""
9560                                         unit=""
9561                                         altCap=0
9562                                         workingMaxCap=int(aArrayData[m,"maxCapacity16"])
9563                                         
9564                                         if ( bDebugger1 == "true" ){
9565                                                 print ""
9566                                                 print "count: " m
9567                                                 print "1: mmods: " aArrayData[m,"maxModuleSize"] " :dmmods: " aArrayData[m,"derivedModuleSize"] " :mcap: " workingMaxCap " :ucap: " aArrayData[m,"usedCapacity"] 
9568                                         }
9569                                         # 1: if max cap 1 is null, and max cap 2 not null, use 2
9570                                         if ( workingMaxCap == 0 ) {
9571                                                 if ( aArrayData[m,"maxCapacity5"] != 0 ) {
9572                                                         workingMaxCap=aArrayData[m,"maxCapacity5"]
9573                                                 }
9574                                         }
9575                                         if ( aArrayData[m,"deviceCount16"] == "" ) {
9576                                                 aArrayData[m,"deviceCount16"] = 0
9577                                         }
9578                                         if ( bDebugger1 == "true" ){
9579                                                 print "2: mmods: " aArrayData[m,"maxModuleSize"] " :dmmods: " aArrayData[m,"derivedModuleSize"] " :mcap: " workingMaxCap " :ucap: " aArrayData[m,"usedCapacity"]
9580                                         }
9581                                         # 2: now check to see if actually found module sizes are > than listed max module, replace if >
9582                                         if (aArrayData[m,"maxModuleSize"] != 0 && aArrayData[m,"derivedModuleSize"] != 0 && int(aArrayData[m,"derivedModuleSize"]) > int(aArrayData[m,"maxModuleSize"]) ) {
9583                                                 aArrayData[m,"maxModuleSize"]=aArrayData[m,"derivedModuleSize"]
9584                                                 estMod=" (est)"
9585                                         }
9586                                         aArrayData[m,"maxModuleSize"]=int(aArrayData[m,"maxModuleSize"])
9587                                         aArrayData[m,"derivedModuleSize"]=int(aArrayData[m,"derivedModuleSize"])
9588                                         aArrayData[m,"usedCapacity"]=int(aArrayData[m,"usedCapacity"])
9589                                         workingMaxCap=int(workingMaxCap) 
9590                                          
9591                                         # note: some cases memory capacity == max module size, so one stick will fill it
9592                                         # but I think only with cases of 2 slots does this happen, so if > 2, use the count of slots.
9593                                         if ( bDebugger1 == "true" ){
9594                                                 print "3: fmod: " aArrayData[m,"deviceCountFound"] " :modc: " aArrayData[m,"deviceCount16"] " :maxc1: " aArrayData[m,"maxCapacity5"] " :maxc2: " aArrayData[m,"maxCapacity16"]
9595                                         }
9596                                         if (workingMaxCap != 0 && ( aArrayData[m,"deviceCountFound"] != 0 || aArrayData[m,"deviceCount16"] != 0 ) ) {
9597                                                 aArrayData[m,"deviceCount16"]=int(aArrayData[m,"deviceCount16"])
9598                                                 ## first check that actual memory found is not greater than listed max cap, or
9599                                                 ## checking to see module count * max mod size is not > used capacity
9600                                                 if ( aArrayData[m,"usedCapacity"] != 0 && aArrayData[m,"maxCapacity16"] != 0 ) {
9601                                                         if ( aArrayData[m,"usedCapacity"] > workingMaxCap ) {
9602                                                                 if ( aArrayData[m,"maxModuleSize"] != 0 && 
9603                                                                         aArrayData[m,"usedCapacity"] < aArrayData[m,"deviceCount16"] * aArrayData[m,"maxModuleSize"] ) {
9604                                                                         workingMaxCap=aArrayData[m,"deviceCount16"] * aArrayData[m,"maxModuleSize"]
9605                                                                         estCap=" (est)"
9606                                                                         if ( bDebugger1 == "true" ){
9607                                                                                 print "A"
9608                                                                         }
9609                                                                 }
9610                                                                 else if ( aArrayData[m,"derivedModuleSize"] != 0 && 
9611                                                                                         aArrayData[m,"usedCapacity"] < aArrayData[m,"deviceCount16"] * aArrayData[m,"derivedModuleSize"] ) {
9612                                                                         workingMaxCap=aArrayData[m,"deviceCount16"] *  aArrayData[m,"derivedModuleSize"]
9613                                                                         estCap=" (est)"
9614                                                                         if ( bDebugger1 == "true" ){
9615                                                                                 print "B"
9616                                                                         }
9617                                                                 }
9618                                                                 else {
9619                                                                         workingMaxCap=aArrayData[m,"usedCapacity"]
9620                                                                         estCap=" (est)"
9621                                                                         if ( bDebugger1 == "true" ){
9622                                                                                 print "C"
9623                                                                         }
9624                                                                 }
9625                                                         }
9626                                                 } 
9627                                                 # note that second case will never really activate except on virtual machines and maybe
9628                                                 # mobile devices
9629                                                 if ( estCap == "" ) {
9630                                                         # do not do this for only single modules found, max mod size can be equal to the array size
9631                                                         if ( ( aArrayData[m,"deviceCount16"] > 1 && aArrayData[m,"deviceCountFound"] > 1 ) && 
9632                                                                 ( workingMaxCap < aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCount16"] ) ) {
9633                                                                 workingMaxCap = aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCount16"]
9634                                                                 estCap=" (est)"
9635                                                                 if ( bDebugger1 == "true" ){
9636                                                                         print "D"
9637                                                                 }
9638                                                         }
9639                                                         else if ( ( aArrayData[m,"deviceCountFound"] > 0 ) && 
9640                                                                                 ( workingMaxCap < aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCountFound"] ) ) {
9641                                                                 workingMaxCap = aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCountFound"]
9642                                                                 estCap=" (est)"
9643                                                                 if ( bDebugger1 == "true" ){
9644                                                                         print "E"
9645                                                                 }
9646                                                         }
9647                                                         ## handle cases where we have type 5 data: mms x device count equals type 5 max cap
9648                                                         # however do not use it if cap / devices equals the derived module size
9649                                                         else if ( aArrayData[m,"maxModuleSize"] > 0 && 
9650                                                                                 ( aArrayData[m,"maxModuleSize"] * aArrayData[m,"deviceCount16"] == aArrayData[m,"maxCapacity5"] ) && 
9651                                                                                 aArrayData[m,"maxCapacity5"] != aArrayData[m,"maxCapacity16"] && 
9652                                                                                 aArrayData[m,"maxCapacity16"] / aArrayData[m,"deviceCount16"] != aArrayData[m,"derivedModuleSize"] ) {
9653                                                                 workingMaxCap = aArrayData[m,"maxCapacity5"]
9654                                                                 altCap=aArrayData[m,"maxCapacity5"] # not used
9655                                                                 estCap=" (check)"
9656                                                                 if ( bDebugger1 == "true" ){
9657                                                                         print "F"
9658                                                                 }
9659                                                         }
9660                                                 }
9661                                         }
9662                                         altCap=int(altCap)
9663                                         workingMaxCap=int(workingMaxCap)
9664                                         if ( bDebugger1 == "true" ){
9665                                                 print "4: mmods: " aArrayData[m,"maxModuleSize"] " :dmmods: " aArrayData[m,"derivedModuleSize"] " :mcap: " workingMaxCap " :ucap: " aArrayData[m,"usedCapacity"]
9666                                         }
9667                                         # some cases of type 5 have too big module max size, just dump the data then since
9668                                         # we cannot know if it is valid or not, and a guess can be wrong easily
9669                                         if ( aArrayData[m,"maxModuleSize"] != 0 && workingMaxCap != "" && 
9670                                                 ( aArrayData[m,"maxModuleSize"] > workingMaxCap ) ){
9671                                                 aArrayData[m,"maxModuleSize"] = 0
9672                                                 # print "yes"
9673                                         }
9674                                         if ( bDebugger1 == "true" ){
9675                                                 print "5: dms: " aArrayData[m,"derivedModuleSize"] " :dc: " aArrayData[m,"deviceCount16"] " :wmc: " workingMaxCap
9676                                         }
9677                                         ## prep for output ##
9678                                         if (aArrayData[m,"maxModuleSize"] == 0 ){
9679                                                 aArrayData[m,"maxModuleSize"]=""
9680                                                 # ie: 2x4gB
9681                                                 if ( estCap == "" && int(aArrayData[m,"derivedModuleSize"]) > 0 &&
9682                                                     workingMaxCap > ( int(aArrayData[m,"derivedModuleSize"]) * int(aArrayData[m,"deviceCount16"]) * 4 ) ) { 
9683                                                         estCap=" (check)"
9684                                                         if ( bDebugger1 == "true" ){
9685                                                                 print "G"
9686                                                         }
9687                                                 }
9688                                         }
9689                                         else {
9690                                                 # case where listed max cap is too big for actual slots x max cap, eg:
9691                                                 # listed max cap, 8gb, max mod 2gb, slots 2
9692                                                 if ( estCap == "" && aArrayData[m,"maxModuleSize"] > 0 ) {
9693                                                         if ( int(workingMaxCap) > int(aArrayData[m,"maxModuleSize"]) * aArrayData[m,"deviceCount16"] ) {
9694                                                                 estCap=" (check)"
9695                                                                 if ( bDebugger1 == "true" ){
9696                                                                         print "H"
9697                                                                 }
9698                                                         }
9699                                                 }
9700                                                 if (aArrayData[m,"maxModuleSize"] > 1023 ) {
9701                                                         aArrayData[m,"maxModuleSize"]=aArrayData[m,"maxModuleSize"] / 1024 " GB"
9702                                                 }
9703                                                 else {
9704                                                         aArrayData[m,"maxModuleSize"]=aArrayData[m,"maxModuleSize"] " MB"
9705                                                 }
9706                                         }
9707                                         if ( aArrayData[m,"deviceCount16"] == 0 ) {
9708                                                 aArrayData[m,"deviceCount16"] = ""
9709                                         }
9710                                         if (workingMaxCap != 0 ) {
9711                                                 if ( workingMaxCap < 1024 ) {
9712                                                         workingMaxCap = workingMaxCap
9713                                                         unit=" MB"
9714                                                 }
9715                                                 else if ( workingMaxCap < 1024000 ) {
9716                                                         workingMaxCap = workingMaxCap / 1024
9717                                                         unit=" GB"
9718                                                 }
9719                                                 else if ( workingMaxCap < 1024000000 ) {
9720                                                         workingMaxCap = workingMaxCap / 1024000
9721                                                         unit=" TB"
9722                                                 }
9723                                                 # we only want a max 2 decimal places, this trick gives 0 to 2
9724                                                 workingMaxCap=gensub(/([0-9]+\.[0-9][0-9]).*/,"\\1",1,workingMaxCap)
9725                                                 workingMaxCap = workingMaxCap unit estCap
9726                                                 
9727                                         }
9728                                         else {
9729                                                 workingMaxCap == ""
9730                                         }
9731                                         
9732                                         print aArrayData[m,"data-type"] "," aArrayData[m,"handle"] "," aArrayData[m,"location"] "," workingMaxCap "," aArrayData[m,"deviceCount16"] "," aArrayData[m,"use"] "," aArrayData[m,"errorCorrection"] "," aArrayData[m,"maxModuleSize"] estMod "," aArrayData[m,"voltage5"] 
9733                                         # print device rows next
9734                                         for ( j=0;j<=100;j++ ) {
9735                                                 if (aMemory[m,j,0] != "" ) {
9736                                                         unit=""
9737                                                         workingSize=aMemory[m,j,2]
9738                                                         if ( workingSize ~ /^[0-9]+$/ ) {
9739                                                                 workingSize=int(workingSize)
9740                                                                 if ( workingSize < 1024 ) {
9741                                                                         workingSize = workingSize
9742                                                                         unit=" MB"
9743                                                                 }
9744                                                                 else if ( workingSize < 1024000 ) {
9745                                                                         workingSize = workingSize / 1024
9746                                                                         unit=" GB"
9747                                                                 }
9748                                                                 else if ( workingSize < 1024000000 ) {
9749                                                                         workingSize = workingSize / 1024000
9750                                                                         unit=" TB"
9751                                                                 }
9752                                                                 # we only want a max 2 decimal places, this trick gives 0 to 2
9753                                                                 workingSize=gensub(/([0-9]+\.[0-9][0-9]).*/,"\\1",1,workingSize)
9754                                                                 workingSize = workingSize unit
9755                                                         }
9756                                                         print aMemory[m,j,0] "," aMemory[m,j,1] "," workingSize "," aMemory[m,j,3] "," aMemory[m,j,4] "," aMemory[m,j,5] "," aMemory[m,j,6] "," aMemory[m,j,7] "," aMemory[m,j,8]  "," aMemory[m,j,9] "," aMemory[m,j,10] "," aMemory[m,j,11] "," aMemory[m,j,12] "," aMemory[m,j,13] "," aMemory[m,j,14] "," aMemory[m,j,15] "," aMemory[m,j,16] "," aMemory[m,j,17]
9757                                                 }
9758                                                 else {
9759                                                         break
9760                                                 }
9761                                         }
9762                                 }
9763                         }' <<< "$DMIDECODE_DATA" ) )
9764                 fi
9765         fi
9766         IFS="$ORIGINAL_IFS"
9767         a_temp=${A_MEMORY_DATA[@]}
9768         
9769         # echo "${a_temp[@]}"
9770         log_function_data "A_MEMORY_DATA: $a_temp"
9771         
9772         eval $LOGFE
9773 }
9774
9775 # Repos will be added as we get distro package manager data to create the repo data. 
9776 # This method will output the file name also, which is useful to create output that's 
9777 # neat and readable. Each line of the total number contains the following sections,
9778 # separated by a : for splitting in the print function
9779 # part one, repo type/string : part two, file name, if present, of info : part 3, repo data
9780 # args: $1 - [file location of debug data file - optional, only for debugging data collection] 
9781 get_repo_data()
9782 {
9783         eval $LOGFS
9784         local repo_file='' repo_data_working='' repo_data_working2='' repo_line='' repo_files=''
9785         local repo_name=''
9786         local apt_file='/etc/apt/sources.list' yum_repo_dir='/etc/yum.repos.d/' yum_conf='/etc/yum.conf'
9787         local pacman_conf='/etc/pacman.conf' pacman_repo_dir='/etc/pacman.d/' pisi_dir='/etc/pisi/'
9788         local zypp_repo_dir='/etc/zypp/repos.d/' ports_conf='/etc/portsnap.conf' openbsd_conf='/etc/pkg.conf'
9789         local bsd_pkg_dir='/usr/local/etc/pkg/repos/' slackpkg_file='/etc/slackpkg/mirrors'
9790         local netbsd_file='/usr/pkg/etc/pkgin/repositories.conf' freebsd_file='/etc/freebsd-update.conf'
9791         local freebsd_pkg_file='/etc/pkg/FreeBSD.conf' slackpkg_plus_file='/etc/slackpkg/slackpkgplus.conf'
9792         local portage_repo_dir='/etc/portage/repos.conf/'
9793         
9794         # apt - debian, buntus, also sometimes some yum/rpm repos may create apt repos here as well
9795         if [[ -f $apt_file || -d $apt_file.d ]];then
9796                 repo_files=$(ls /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null)
9797                 log_function_data "apt repo files: $repo_files"
9798                 for repo_file in $repo_files
9799                 do
9800                         if [[ -n $1 ]];then
9801                                 cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
9802                         fi
9803                         repo_data_working="$( gawk -v repoFile="$repo_file" '
9804                         !/^[[:space:]]*$|^[[:space:]]*#/ {
9805                                 print "apt sources^" repoFile "^" $0
9806                         }' $repo_file )"
9807                         get_repo_builder "$repo_data_working"
9808                 done
9809                 repo_data_working=''
9810         fi
9811         # yum - fedora, redhat, centos, etc. Note that rpmforge also may create apt sources
9812         # in /etc/apt/sources.list.d/. Therefore rather than trying to assume what package manager is
9813         # actually running, inxi will merely note the existence of each repo type for apt/yum. 
9814         # Also, in rpm, you can install apt-rpm for the apt-get command, so it's not good to check for
9815         # only the commands in terms of selecting which repos to show.
9816         if [[ -d $yum_repo_dir || -f $yum_conf || -d $zypp_repo_dir ]];then
9817                 if [[ -d $yum_repo_dir || -f $yum_conf ]];then
9818                         # older redhats put their yum data in /etc/yum.conf
9819                         repo_files=$( ls $yum_repo_dir*.repo $yum_conf 2>/dev/null )
9820                         repo_name='yum'
9821                         log_function_data "yum repo files: $repo_files"
9822                 elif [[ -d $zypp_repo_dir ]];then
9823                         repo_files=$( ls $zypp_repo_dir*.repo 2>/dev/null )
9824                         repo_name='zypp'
9825                         log_function_data "zypp repo files: $repo_files"
9826                 fi
9827                 if [[ -n $repo_files ]];then
9828                         for repo_file in $repo_files
9829                         do
9830                                 if [[ -n $1 ]];then
9831                                         cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
9832                                 fi
9833                                 repo_data_working="$( gawk -v repoFile="$repo_file" '
9834                                 # construct the string for the print function to work with, file name: data
9835                                 function print_line( fileName, repoId, repoUrl ){
9836                                         print "'$repo_name' sources^" fileName "^" repoId  repoUrl
9837                                 }
9838                                 BEGIN {
9839                                         FS="\n"
9840                                         IGNORECASE=1
9841                                         enabledStatus=""
9842                                         repoTitle=""
9843                                         urlData=""
9844                                 }
9845                                 # this is a hack, assuming that each item has these fields listed, we collect the 3
9846                                 # items one by one, then when the url/enabled fields are set, we print it out and
9847                                 # reset the data. Not elegant but it works. Note that if enabled was not present
9848                                 # we assume it is enabled then, and print the line, reset the variables. This will
9849                                 # miss the last item, so it is printed if found in END
9850                                 /^\[.+\]/ {
9851                                         if ( urlData != "" && repoTitle != "" ){
9852                                                 print_line( repoFile, repoTitle, urlData )
9853                                                 enabledStatus=""
9854                                                 urlData=""
9855                                                 repoTitle=""
9856                                         }
9857                                         gsub(/\[|\]/, "", $1 ) # strip out the brackets
9858                                         repoTitle = $1 " ~ "
9859                                 }
9860                                 /^(mirrorlist|baseurl)/ {
9861                                         sub( /(mirrorlist|baseurl)[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
9862                                         urlData = $1
9863                                 }
9864                                 # note: enabled = 1. enabled = 0 means disabled
9865                                 /^enabled[[:space:]]*=/ {
9866                                         enabledStatus = $1
9867                                 }
9868                                 # print out the line if all 3 values are found, otherwise if a new
9869                                 # repoTitle is hit above, it will print out the line there instead
9870                                 { 
9871                                         if ( urlData != "" && enabledStatus != "" && repoTitle != "" ){
9872                                                 if ( enabledStatus !~ /enabled[[:space:]]*=[[:space:]]*0/ ){
9873                                                         print_line( repoFile, repoTitle, urlData )
9874                                                 }
9875                                                 enabledStatus=""
9876                                                 urlData=""
9877                                                 repoTitle=""
9878                                         }
9879                                 }
9880                                 END {
9881                                         # print the last one if there is data for it
9882                                         if ( urlData != ""  && repoTitle != "" ){
9883                                                 print_line( repoFile, repoTitle, urlData )
9884                                         }
9885                                 }
9886                                 ' $repo_file )"
9887                                 # then load the global for each file as it gets filled
9888                                 get_repo_builder "$repo_data_working"
9889                         done
9890                 fi
9891                 repo_data_working=''
9892         # pacman - archlinux, going to assume that pisi and arch/pacman, etc don't have the above issue with apt/yum
9893         elif [[ -f $pacman_conf ]];then
9894                 # get list of mirror include files, trim white space off ends
9895                 repo_data_working="$( gawk '
9896                 BEGIN {
9897                         FS="="
9898                         IGNORECASE=1
9899                 }
9900                 /^[[:space:]]*Include/ {
9901                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
9902                         print $2
9903                 }
9904                 ' $pacman_conf )"
9905                 # sort into unique paths only, to be used to search for server = data
9906                 repo_data_working=$( sort -bu <<< "$repo_data_working" | uniq ) 
9907                 repo_data_working="$repo_data_working $pacman_conf"
9908                 for repo_file in $repo_data_working 
9909                 do
9910                         if [[ -n $1 ]];then
9911                                 cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
9912                         fi
9913                         if [[ -f $repo_file ]];then
9914                                 # inserting a new line after each found / processed match
9915                                 repo_data_working2="$repo_data_working2$( gawk -v repoFile=$repo_file '
9916                                 BEGIN {
9917                                         FS="="
9918                                         IGNORECASE=1
9919                                 }
9920                                 /^[[:space:]]*Server/ {
9921                                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
9922                                         print "pacman repo servers^" repoFile "^" $2 "\\n"
9923                                 }
9924                                 ' $repo_file )"
9925                         else
9926                                 echo "Error: file listed in $pacman_conf does not exist - $repo_file"
9927                         fi
9928                 done
9929                 # execute line breaks
9930                 REPO_DATA="$( echo -e $repo_data_working2 )"
9931                 repo_data_working=''
9932         # pisi - pardus
9933         elif [[ -f $slackpkg_file || -f $slackpkg_plus_file ]];then
9934                 # note, only one file, but loop it in case more are added in future
9935                 if [[ -f $slackpkg_file ]];then
9936                         if [[ -n $1 ]];then
9937                                 cat $slackpkg_file &> $1/repo-data_${slackpkg_file//\//-}.txt
9938                         fi
9939                         repo_data_working="$( gawk -v repoFile="$slackpkg_file" '
9940                         !/^[[:space:]]*$|^[[:space:]]*#/ {
9941                                 print "slackpkg sources^" repoFile "^" $0
9942                         }' $slackpkg_file )"
9943                         get_repo_builder "$repo_data_working"
9944                 fi
9945                 if [[ -f $slackpkg_plus_file ]];then
9946                         if [[ -n $1 ]];then
9947                                 cat $slackpkg_plus_file &> $1/repo-data_${slackpkg_plus_file//\//-}.txt
9948                         fi
9949                         # see sample for syntax
9950                         repo_data_working="$( gawk -F '=' -v repoFile="$slackpkg_plus_file" '
9951                         BEGIN {
9952                                 activeRepos=""
9953                         }
9954                         # stop if set to off
9955                         /^SLACKPKGPLUS/ {
9956                                 if ( $2 == "off" ){
9957                                         exit
9958                                 }
9959                         }
9960                         # get list of current active repos
9961                         /^REPOPLUS/ {
9962                                 activeRepos=$2
9963                         }
9964                         # print out repo line if found
9965                         /^MIRRORPLUS/ {
9966                                 if ( activeRepos != "" ) {
9967                                         gsub(/MIRRORPLUS\['\''|'\''\]/,"",$1)
9968                                         if ( match( activeRepos, $1 ) ){
9969                                                 print "slackpkg+ sources^" repoFile "^" $1 " ~ " $2
9970                                         }
9971                                 }
9972                         }' $slackpkg_plus_file )"
9973                         get_repo_builder "$repo_data_working"
9974                 fi
9975                 repo_data_working=''
9976         elif [[ -d $portage_repo_dir && -n $( type -p emerge ) ]];then
9977                 repo_files=$( ls $portage_repo_dir*.conf 2>/dev/null )
9978                 repo_name='portage'
9979                 log_function_data "portage repo files: $repo_files"
9980                 if [[ -n $repo_files ]];then
9981                         for repo_file in $repo_files
9982                         do
9983                                 if [[ -n $1 ]];then
9984                                         cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
9985                                 fi
9986                                 repo_data_working="$( gawk -v repoFile="$repo_file" '
9987                                 # construct the string for the print function to work with, file name: data
9988                                 function print_line( fileName, repoId, repoUrl ){
9989                                         print "'$repo_name' sources^" fileName "^" repoId  repoUrl
9990                                 }
9991                                 BEGIN {
9992                                         FS="\n"
9993                                         IGNORECASE=1
9994                                         enabledStatus=""
9995                                         repoTitle=""
9996                                         urlData=""
9997                                 }
9998                                 # this is a hack, assuming that each item has these fields listed, we collect the 3
9999                                 # items one by one, then when the url/enabled fields are set, we print it out and
10000                                 # reset the data. Not elegant but it works. Note that if enabled was not present
10001                                 # we assume it is enabled then, and print the line, reset the variables. This will
10002                                 # miss the last item, so it is printed if found in END
10003                                 /^\[.+\]/ {
10004                                         if ( urlData != "" && repoTitle != "" ){
10005                                                 print_line( repoFile, repoTitle, urlData )
10006                                                 enabledStatus=""
10007                                                 urlData=""
10008                                                 repoTitle=""
10009                                         }
10010                                         gsub(/\[|\]/, "", $1 ) # strip out the brackets
10011                                         repoTitle = $1 " ~ "
10012                                 }
10013                                 /^(sync-uri)/ {
10014                                         sub( /sync-uri[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
10015                                         urlData = $1
10016                                 }
10017                                 # note: enabled = 1. enabled = 0 means disabled
10018                                 /^auto-sync[[:space:]]*=/ {
10019                                         sub( /auto-sync[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
10020                                         enabledStatus = $1
10021                                 }
10022                                 # print out the line if all 3 values are found, otherwise if a new
10023                                 # repoTitle is hit above, it will print out the line there instead
10024                                 { 
10025                                         if ( urlData != "" && enabledStatus != "" && repoTitle != "" ){
10026                                                 if ( enabledStatus !~ /enabled[[:space:]]*=[[:space:]]*0/ ){
10027                                                         print_line( repoFile, repoTitle, urlData )
10028                                                 }
10029                                                 enabledStatus=""
10030                                                 urlData=""
10031                                                 repoTitle=""
10032                                         }
10033                                 }
10034                                 END {
10035                                         # print the last one if there is data for it
10036                                         if ( urlData != ""  && repoTitle != "" ){
10037                                                 print_line( repoFile, repoTitle, urlData )
10038                                         }
10039                                 }
10040                                 ' $repo_file )"
10041                                 # then load the global for each file as it gets filled
10042                                 get_repo_builder "$repo_data_working"
10043                         done
10044                 fi
10045         elif [[ -d $pisi_dir && -n $( type -p pisi ) ]];then
10046                 REPO_DATA="$( pisi list-repo )"
10047                 if [[ -n $1 ]];then
10048                         echo "$REPO_DATA" &> $1/repo-data_pisi-list-repo.txt
10049                 fi
10050                 log_function_data "pisi-list-repo: $REPO_DATA"
10051                 # now we need to create the structure: repo info: repo path
10052                 # we do that by looping through the lines of the output and then
10053                 # putting it back into the <data>:<url> format print repos expects to see
10054                 # note this structure in the data, so store first line and make start of line
10055                 # then when it's an http line, add it, and create the full line collection.
10056 # Pardus-2009.1 [Aktiv]
10057 #       http://packages.pardus.org.tr/pardus-2009.1/pisi-index.xml.bz2
10058 # Contrib [Aktiv]
10059 #       http://packages.pardus.org.tr/contrib-2009/pisi-index.xml.bz2
10060                 while read repo_line
10061                 do
10062                         repo_line=$( gawk '
10063                         {
10064                                 # need to dump leading/trailing spaces and clear out color codes for irc output
10065                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
10066 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
10067                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
10068                                 print $0
10069                         }' <<< $repo_line )
10070                         if [[ -n $( grep '://' <<< $repo_line ) ]];then
10071                                 repo_data_working="$repo_data_working^$repo_line\n"
10072                         else
10073                                 repo_data_working="${repo_data_working}pisi repo^$repo_line"
10074                         fi
10075                 done <<< "$REPO_DATA"
10076                 # echo and execute the line breaks inserted
10077                 REPO_DATA="$( echo -e $repo_data_working )"
10078                 repo_data_working=''
10079         # Mandriva/Mageia using: urpmq
10080         elif type -p urpmq &>/dev/null;then
10081                 REPO_DATA="$( urpmq --list-media active --list-url )"
10082                 if [[ -n $1 ]];then
10083                         echo "$REPO_DATA" &> $1/repo-data_urpmq-list-media-active.txt
10084                 fi
10085                 # now we need to create the structure: repo info: repo path
10086                 # we do that by looping through the lines of the output and then
10087                 # putting it back into the <data>:<url> format print repos expects to see
10088                 # note this structure in the data, so store first line and make start of line
10089                 # then when it's an http line, add it, and create the full line collection.
10090 # Contrib ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/release
10091 # Contrib Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/updates
10092 # Non-free ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/release
10093 # Non-free Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/updates
10094 # Nonfree Updates (Local19) /mnt/data/mirrors/mageia/distrib/cauldron/x86_64/media/nonfree/updates
10095                 while read repo_line
10096                 do
10097                         repo_line=$( gawk '
10098                         {
10099                                 # need to dump leading/trailing spaces and clear out color codes for irc output
10100                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
10101 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
10102                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
10103                                 print $0
10104                         }' <<< $repo_line )
10105                         # urpmq output is the same each line, repo name space repo url, can be:
10106                         # rsync://, ftp://, file://, http:// OR repo is locally mounted on FS in some cases
10107                         if [[ -n $( grep -E '(://|[[:space:]]/)' <<< $repo_line ) ]];then
10108                                 # cut out the repo first
10109                                 repo_data_working2=$( grep -Eo '([^[:space:]]+://|[[:space:]]/).*' <<< $repo_line )
10110                                 # then get the repo name string by slicing out the url string
10111                                 repo_name=$( sed "s|[[:space:]]*$repo_data_working2||" <<< $repo_line )
10112                                 repo_data_working="${repo_data_working}urpmq repo^$repo_name^$repo_data_working2\n"
10113                         fi
10114                 done <<< "$REPO_DATA"
10115                 # echo and execute the line breaks inserted
10116                 REPO_DATA="$( echo -e $repo_data_working )"
10117         elif [[ -f $ports_conf || -f $freebsd_file || -d $bsd_pkg_dir ]];then
10118                 if [[ -f $ports_conf ]];then
10119                         if [[ -n $1 ]];then
10120                                 cat $ports_conf &> $1/repo-data_${ports_conf//\//-}.txt
10121                         fi
10122                         repo_data_working="$( gawk -F '=' -v repoFile=$ports_conf '
10123                         BEGIN {
10124                                 IGNORECASE=1
10125                         }
10126                         /^SERVERNAME/ {
10127                                 print "BSD ports server^" repoFile "^" $2
10128                                 exit
10129                         }
10130                         ' $ports_conf )"
10131                         get_repo_builder "$repo_data_working"
10132                 fi
10133                 if [[ -f $freebsd_file ]];then
10134                         if [[ -n $1 ]];then
10135                                 cat $freebsd_file &> $1/repo-data_${freebsd_file//\//-}.txt
10136                         fi
10137                         repo_data_working="$( gawk -v repoFile=$freebsd_file '
10138                         BEGIN {
10139                                 IGNORECASE=1
10140                         }
10141                         /^ServerName/ {
10142                                 print "FreeBSD update server^" repoFile "^" $2
10143                                 exit
10144                         }
10145                         ' $freebsd_file )"
10146                         get_repo_builder "$repo_data_working"
10147                 fi
10148                 if [[ -f $freebsd_pkg_file ]];then
10149                         if [[ -n $1 ]];then
10150                                 cat $freebsd_pkg_file &> $1/repo-data_${freebsd_pkg_file//\//-}.txt
10151                         fi
10152                         repo_data_working="$( gawk -F ': ' -v repoFile=$freebsd_pkg_file '
10153                         BEGIN {
10154                                 IGNORECASE=1
10155                         }
10156                         $1 ~ /^[[:space:]]*url/ {
10157                                 gsub(/\"|pkg\+|,/,"",$2)
10158                                 print "FreeBSD default pkg server^" repoFile "^" $2
10159                                 exit
10160                         }
10161                         ' $freebsd_pkg_file )"
10162                         get_repo_builder "$repo_data_working"
10163                 fi
10164                 
10165                 if [[ -d $bsd_pkg_dir ]];then
10166                         repo_files=$(ls ${bsd_pkg_dir}*.conf 2>/dev/null )
10167                         for repo_file in $repo_files
10168                         do
10169                                 if [[ -n $1 ]];then
10170                                         cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
10171                                 fi
10172                                 repo_data_working="$( gawk -v repoFile=$repo_file '
10173                                 BEGIN {
10174                                         FS=":"
10175                                         IGNORECASE=1
10176                                         repoName=""
10177                                         repoUrl=""
10178                                         enabled=""
10179                                 }
10180                                 {
10181                                         gsub(/{|}|^#.*/,"",$0)
10182                                 }
10183                                 /^[^[:space:]]/ {
10184                                         repoName=$1
10185                                         repoUrl=""
10186                                         enabled=""
10187                                         while ( getline && $0 !~ /^[[:space:]]*$/ ) {
10188                                                 gsub(/'"$BAN_LIST_ARRAY"'/,"",$0)
10189                                                 gsub(/({|}|^[[:space:]]+|[[:space:]]+$)/,"",$1)
10190                                                 gsub(/({|}|^[[:space:]]+|[[:space:]]+$)/,"",$2)
10191                                                 if ( $1 == "url" ) {
10192                                                         repoUrl=$2$3
10193                                                 }
10194                                                 if ( $1 == "enabled" ) {
10195                                                         if ( $2 == "yes" ) {
10196                                                                 print "BSD pkg server^" repoFile "^" repoName " ~ " repoUrl 
10197                                                         }
10198                                                 }
10199                                         }
10200                                 }
10201                                 ' $repo_file )"
10202                                 get_repo_builder "$repo_data_working"
10203                         done
10204                 fi
10205                 repo_data_working=''
10206         elif [[ -f $openbsd_conf ]];then
10207                 if [[ -n $1 ]];then
10208                         cat $openbsd_conf &> $1/repo-data_${openbsd_conf//\//-}.txt
10209                 fi
10210                 REPO_DATA="$( gawk -F '=' -v repoFile=$openbsd_conf '
10211                 BEGIN {
10212                         IGNORECASE=1
10213                 }
10214                 /^installpath/ {
10215                         print "OpenBSD pkg mirror^" repoFile "^" $2
10216                 }
10217                 ' $openbsd_conf )"
10218         elif [[ -f $netbsd_file ]];then
10219                 # note, only one file, but loop it in case more are added in future
10220                 for repo_file in $netbsd_file
10221                 do
10222                         if [[ -n $1 ]];then
10223                                 cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
10224                         fi
10225                         repo_data_working="$( gawk -v repoFile="$repo_file" '
10226                         !/^[[:space:]]*$|^[[:space:]]*#/ {
10227                                 print "NetBSD pkg servers^" repoFile "^" $0
10228                         }' $repo_file )"
10229                         get_repo_builder "$repo_data_working"
10230                 done
10231                 repo_data_working=''
10232         fi
10233         eval $LOGFE
10234 }
10235 # build the total REPO_DATA global here
10236 # args: $1 - the repo line/s
10237 get_repo_builder()
10238 {
10239         if [[ -n $1 ]];then
10240                 if [[ -z $REPO_DATA ]];then
10241                         REPO_DATA="$1"
10242                 else
10243                         REPO_DATA="$REPO_DATA
10244 $1"
10245                 fi
10246         fi
10247 }
10248
10249 get_runlevel_data()
10250 {
10251         eval $LOGFS
10252         local runlvl=''
10253
10254         if type -p runlevel &>/dev/null;then
10255                 runlvl="$( runlevel | gawk '{ print $2 }' )"
10256         fi
10257         echo $runlvl
10258         eval $LOGFE
10259 }
10260
10261 # note: it appears that at least as of 2014-01-13, /etc/inittab is going to be used for
10262 # default runlevel in upstart/sysvinit. systemd default is not always set so check to see 
10263 # if it's linked.
10264 get_runlevel_default()
10265 {
10266         eval $LOGFS
10267         local default_runlvl=''
10268         local inittab='/etc/inittab'
10269         local systemd_default='/etc/systemd/system/default.target'
10270         local upstart_default='/etc/init/rc-sysinit.conf'
10271         
10272         # note: systemd systems do not necessarily have this link created
10273         if [[ -L $systemd_default  ]];then
10274                 default_runlvl=$( readlink $systemd_default )
10275                 if [[ -n $default_runlvl ]];then
10276                         default_runlvl=${default_runlvl##*/}
10277                 fi
10278         # http://askubuntu.com/questions/86483/how-can-i-see-or-change-default-run-level
10279         # note that technically default can be changed at boot but for inxi purposes that does
10280         # not matter, we just want to know the system default
10281         elif [[ -e $upstart_default ]];then
10282                 # env DEFAULT_RUNLEVEL=2
10283                 default_runlvl=$( gawk -F '=' '/^env[[:space:]]+DEFAULT_RUNLEVEL/ {
10284                 print $2
10285                 }' $upstart_default )
10286         fi
10287         
10288         # handle weird cases where null but inittab exists
10289         if [[ -z $default_runlvl && -f $inittab ]];then
10290                 default_runlvl=$( gawk -F ':' '
10291                 /^id.*initdefault/ {
10292                         print $2
10293                 }' $inittab )
10294         fi
10295         echo $default_runlvl
10296         eval $LOGFE
10297 }
10298
10299 get_sensors_data()
10300 {
10301         eval $LOGFS
10302         
10303         
10304         local a_temp=''
10305                 
10306         IFS=$'\n'
10307         if [[ -n $Sensors_Data ]];then
10308                 # note: non-configured sensors gives error message, which we need to redirect to stdout
10309                 # also, -F ':' no space, since some cases have the data starting right after,like - :1287
10310                 A_SENSORS_DATA=( $( 
10311                 gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" '
10312                 BEGIN {
10313                         IGNORECASE=1
10314                         core0Temp="" # these only if all else fails...
10315                         cpuPeciTemp="" # use if temps are missing or wrong
10316                         cpuTemp=""
10317                         cpuTempReal=""
10318                         fanWorking=""
10319                         indexCountaFanMain=0
10320                         indexCountaFanDefault=0
10321                         i=""
10322                         j=""
10323                         moboTemp=""
10324                         moboTempReal=""
10325                         psuTemp=""
10326                         separator=""
10327                         sysFanString=""
10328                         temp1=""
10329                         temp2=""
10330                         temp3=""
10331                         tempDiff=20 # for C, handled for F after that is determined
10332                         tempFanType="" # set to 1 or 2
10333                         tempUnit=""
10334                         tempWorking=""
10335                         tempWorkingUnit=""
10336                 }
10337                 # new data arriving: gpu temp in sensors, have to skip that
10338                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
10339                         while ( getline && !/^$/ ) {
10340                                 # do nothing, just skip it
10341                         }
10342                 }
10343                 # dumping the extra + signs after testing for them,  nobody has negative temps.
10344                 # also, note gawk treats Â° as a space, so we have to get the C/F data
10345                 # there are some guesses here, but with more sensors samples it will get closer.
10346                 # note: using arrays starting at 1 for all fan arrays to make it easier overall
10347                 # more validation because gensub if fails to get match returns full string, so
10348                 # we have to be sure we are working with the actual real string before assiging
10349                 # data to real variables and arrays. Extracting C/F degree unit as well to use
10350                 # when constructing temp items for array. 
10351                 # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign 
10352                 # used, but it is required in testing regex to avoid error.
10353                 /^(M\/B|MB|SIO|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10354                         moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 )
10355                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10356                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10357                                 tempUnit=tempWorkingUnit
10358                         }
10359                 }
10360                 # issue 58 msi/asus show wrong for CPUTIN so overwrite it if PECI 0 is present
10361                 # http://www.spinics.net/lists/lm-sensors/msg37308.html
10362                 /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10363                         cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10364                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10365                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10366                                 tempUnit=tempWorkingUnit
10367                         }
10368                 }
10369                 /^PECI[[:space:]]Agent[[:space:]]0(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10370                         cpuPeciTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10371                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10372                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10373                                 tempUnit=tempWorkingUnit
10374                         }
10375                 }
10376                 /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10377                         psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10378                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10379                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10380                                 tempUnit=tempWorkingUnit
10381                         }
10382                 }
10383                 # for temp1/2 only use temp1/2 if they are null or greater than the last ones
10384                 $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10385                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10386                         if ( temp1 == "" || ( tempWorking != "" && tempWorking > 0 ) ) {
10387                                 temp1=tempWorking
10388                         }
10389                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10390                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10391                                 tempUnit=tempWorkingUnit
10392                         }
10393                 }
10394                 $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10395                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10396                         if ( temp2 == "" || ( tempWorking != "" && tempWorking > 0 ) ) {
10397                                 temp2=tempWorking
10398                         }
10399                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10400                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10401                                 tempUnit=tempWorkingUnit
10402                         }
10403                 }
10404                 # temp3 is only used as an absolute override for systems with all 3 present
10405                 $1 ~ /^temp3$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10406                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10407                         if ( temp3 == "" || ( tempWorking != "" && tempWorking > 0 ) ) {
10408                                 temp3=tempWorking
10409                         }
10410                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10411                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10412                                 tempUnit=tempWorkingUnit
10413                         }
10414                 }
10415                 # final fallback if all else fails, funtoo user showed sensors putting
10416                 # temp on wrapped second line, not handled
10417                 /^(core0|core 0|Physical id 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
10418                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
10419                         if ( tempWorking != "" && core0Temp == "" && tempWorking > 0 ) {
10420                                 core0Temp=tempWorking
10421                         }
10422                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
10423                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
10424                                 tempUnit=tempWorkingUnit
10425                         }
10426                 }
10427                 # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before
10428                 # $2 starts (like so :1234 RPM), so skip that space test in regex
10429                 /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10430                         aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10431                 }
10432                 /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10433                         aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10434                 }
10435                 /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10436                         aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10437                 }
10438                 # note that the counters are dynamically set for fan numbers here
10439                 # otherwise you could overwrite eg aux fan2 with case fan2 in theory
10440                 # note: cpu/mobo/ps are 1/2/3
10441                 # NOTE: test: ! i in array does NOT work, this appears to be an awk/gawk bug
10442                 /^(AUX(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10443                         for ( i = 4; i < 7; i++ ){
10444                                 if ( i in aFanMain ){
10445                                         ##
10446                                 }
10447                                 else {
10448                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10449                                         break
10450                                 }
10451                         }
10452                 }
10453                 /^(AUX([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10454                         for ( i = 5; i < 30; i++ ){
10455                                 if ( i in aFanMain ) {
10456                                         ##
10457                                 }
10458                                 else {
10459                                         sysFanNu = i
10460                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10461                                         break
10462                                 }
10463                         }
10464                 }
10465                 # in rare cases syntax is like: fan1: xxx RPM
10466                 /^(FAN(1)?[ \t:])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10467                         aFanDefault[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10468                 }
10469                 /^FAN([2-9]|1[0-9])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
10470                         fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
10471                         sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 )
10472                         if ( sysFanNu ~ /^([0-9]+)$/ ) {
10473                                 # add to array if array index does not exist OR if number is > existing number
10474                                 if ( sysFanNu in aFanDefault ) {
10475                                         if ( fanWorking >= aFanDefault[sysFanNu] ) {
10476                                                 aFanDefault[sysFanNu]=fanWorking
10477                                         }
10478                                 }
10479                                 else {
10480                                         aFanDefault[sysFanNu]=fanWorking
10481                                 }
10482                         }
10483                 }
10484                 END {
10485                         # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo:
10486                         # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment
10487                         # this is wrong for systems with > 2 tempX readings, but the logic is too complex with 3 variables
10488                         # so have to accept that it will be wrong in some cases, particularly for motherboard temp readings.
10489                         if ( temp1 != "" && temp2 != "" ){
10490                                 if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) {
10491                                         tempFanType=userCpuNo
10492                                 }
10493                                 else {
10494                                         # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed
10495                                         # but only if other fan speed is 0.
10496                                         if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) {
10497                                                 tempFanType=2
10498                                         }
10499                                         else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) {
10500                                                 tempFanType=1
10501                                         }
10502                                         # then handle the standard case if these fringe cases are false
10503                                         else if ( temp1 >= temp2 ) {
10504                                                 tempFanType=1
10505                                         }
10506                                         else {
10507                                                 tempFanType=2
10508                                         }
10509                                 }
10510                         }
10511                         # need a case for no temps at all reported, like with old intels
10512                         else if ( temp2 == "" && cpuTemp == "" ){
10513                                 if ( temp1 == "" && moboTemp == "" ){
10514                                         tempFanType=1
10515                                 }
10516                                 else if ( temp1 != "" && moboTemp == "" ){
10517                                         tempFanType=1
10518                                 }
10519                                 else if ( temp1 != "" && moboTemp != "" ){
10520                                         tempFanType=1
10521                                 }
10522                         }
10523                         # convert the diff number for F, it needs to be bigger that is
10524                         if ( tempUnit == "F" ) {
10525                                 tempDiff = tempDiff * 1.8
10526                         }
10527                         if ( cpuTemp != "" ) {
10528                                 # specific hack to handle broken CPUTIN temps with PECI
10529                                 if ( cpuPeciTemp != "" && ( cpuTemp - cpuPeciTemp ) > tempDiff ){
10530                                         cpuTempReal=cpuPeciTemp
10531                                 }
10532                                 # then get the real cpu temp, best guess is hottest is real
10533                                 else {
10534                                         cpuTempReal=cpuTemp
10535                                 }
10536                         }
10537                         else {
10538                                 if ( tempFanType != "" ){
10539                                         # there are some weird scenarios
10540                                         if ( tempFanType == 1 ){
10541                                                 if ( temp1 != "" && temp2 != "" && temp2 > temp1 ) {
10542                                                         cpuTempReal=temp2
10543                                                 }
10544                                                 else {
10545                                                         cpuTempReal=temp1
10546                                                 }
10547                                         }
10548                                         else {
10549                                                 if ( temp1 != "" && temp2 != "" && temp1 > temp2 ) {
10550                                                         cpuTempReal=temp1
10551                                                 }
10552                                                 else {
10553                                                         cpuTempReal=temp2
10554                                                 }
10555                                         }
10556                                 }
10557                                 else {
10558                                         cpuTempReal=temp1 # can be null, that is ok
10559                                 }
10560                                 if ( cpuTempReal != "" ) {
10561                                         # using temp3 is just not reliable enough, more errors caused than fixed imo
10562                                         #if ( temp3 != "" && temp3 > cpuTempReal ) {
10563                                         #       cpuTempReal=temp3
10564                                         #}
10565                                         # there are some absurdly wrong temp1: acpitz-virtual-0 temp1: +13.8°C
10566                                         if ( core0Temp != "" && (core0Temp - cpuTempReal) > tempDiff ) {
10567                                                 cpuTempReal=core0Temp
10568                                         }
10569                                 }
10570                         }
10571                         # if all else fails, use core0/peci temp if present and cpu is null
10572                         if ( cpuTempReal == "" ) {
10573                                 if ( core0Temp != "" ) {
10574                                         cpuTempReal=core0Temp
10575                                 }
10576                                 # note that peci temp is known to be colder than the actual system
10577                                 # sometimes so it is the last fallback we want to use even though in theory
10578                                 # it is more accurate, but fact suggests theory wrong.
10579                                 else if ( cpuPeciTemp != "" ) {
10580                                         cpuTempReal=cpuPeciTemp
10581                                 }
10582                         }
10583                         # then the real mobo temp
10584                         if ( moboTemp != "" ){
10585                                 moboTempReal=moboTemp
10586                         }
10587                         else if ( tempFanType != "" ){
10588                                 if ( tempFanType == 1 ) {
10589                                         if ( temp1 != "" && temp2 != "" && temp2 > temp1 ) {
10590                                                 moboTempReal=temp1
10591                                         }
10592                                         else {
10593                                                 moboTempReal=temp2
10594                                         }
10595                                 }
10596                                 else {
10597                                         if ( temp1 != "" && temp2 != "" && temp1 > temp2 ) {
10598                                                 moboTempReal=temp2
10599                                         }
10600                                         else {
10601                                                 moboTempReal=temp1
10602                                         }
10603                                 }
10604                                 ## NOTE: not safe to assume temp3 is the mobo temp, sad to say
10605                                 #if ( temp1 != "" && temp2 != "" && temp3 != "" && temp3 < moboTempReal ) {
10606                                 #       moboTempReal= temp3
10607                                 #}
10608                         }
10609                         else {
10610                                 moboTempReal=temp2
10611                         }
10612                         # then set the cpu fan speed
10613                         if ( aFanMain[1] == "" ) {
10614                                 # note, you cannot test for aFanDefault[1] or [2] != "" 
10615                                 # because that creates an array item in gawk just by the test itself
10616                                 if ( tempFanType == 1 && 1 in aFanDefault ) {
10617                                         aFanMain[1]=aFanDefault[1]
10618                                         aFanDefault[1]=""
10619                                 }
10620                                 else if ( tempFanType == 2 && 2 in aFanDefault ) {
10621                                         aFanMain[1]=aFanDefault[2]
10622                                         aFanDefault[2]=""
10623                                 }
10624                         }
10625                         # then we need to get the actual numeric max array count for both fan arrays
10626                         for (i = 0; i <= 29; i++) {
10627                                 if ( i in aFanMain && i > indexCountaFanMain ) {
10628                                         indexCountaFanMain=i
10629                                 }
10630                         }
10631                         for (i = 0; i <= 14; i++) {
10632                                 if ( i in aFanDefault && i > indexCountaFanDefault ) {
10633                                         indexCountaFanDefault=i
10634                                 }
10635                         }
10636                         # clear out any duplicates. Primary fan real trumps fan working always if same speed
10637                         for (i = 1; i <= indexCountaFanMain; i++) {
10638                                 if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) {
10639                                         for (j = 1; j <= indexCountaFanDefault; j++) {
10640                                                 if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) {
10641                                                         aFanDefault[j] = ""
10642                                                 }
10643                                         }
10644                                 }
10645                         }
10646                         # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo
10647                         # note that gawk is returning true for some test cases when aFanDefault[j] < 5000
10648                         # which has to be a gawk bug, unless there is something really weird with arrays
10649                         # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually 
10650                         # assign that value below, the > 5000 test works again, and a print of the value
10651                         # shows the proper value, so the corruption might be internal in awk. 
10652                         # Note: gensub is the culprit I think, assigning type string for range 501-1000 but 
10653                         # type integer for all others, this triggers true for >
10654                         for (j = 1; j <= indexCountaFanDefault; j++) {
10655                                 if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) {
10656                                         aFanMain[2] = aFanDefault[j]
10657                                         aFanDefault[j] = ""
10658                                         # then add one if required for output
10659                                         if ( indexCountaFanMain < 2 ) {
10660                                                 indexCountaFanMain = 2
10661                                         }
10662                                 }
10663                         }
10664                         # then construct the sys_fan string for echo, note that iteration 1
10665                         # makes: fanDefaultString separator null, ie, no space or ,
10666                         for (j = 1; j <= indexCountaFanDefault; j++) {
10667                                 fanDefaultString = fanDefaultString separator aFanDefault[j]
10668                                 separator=","
10669                         }
10670                         separator="" # reset to null for next loop
10671                         # then construct the sys_fan string for echo
10672                         for (j = 1; j <= indexCountaFanMain; j++) {
10673                                 fanMainString = fanMainString separator aFanMain[j]
10674                                 separator=","
10675                         }
10676                         
10677                         # and then build the temps:
10678                         if ( moboTempReal != "" ) {
10679                                 moboTempReal = moboTempReal tempUnit
10680                         }
10681                         if ( cpuTempReal != "" ) {
10682                                 cpuTempReal = cpuTempReal tempUnit
10683                         }
10684                         # if they are ALL null, print error message. psFan is not used in output currently
10685                         if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) {
10686                                 print "No active sensors found. Have you configured your sensors yet?"
10687                         }
10688                         else {
10689                                 # then build array arrays: 
10690                                 print cpuTempReal "," moboTempReal "," psuTemp
10691                                 # this is for output, a null print line does NOT create a new array index in bash
10692                                 if ( fanMainString == "" ) {
10693                                         fanMainString=","
10694                                 }
10695                                 print fanMainString
10696                                 print fanDefaultString
10697                         }
10698                 }' <<< "$Sensors_Data" ) )
10699         fi
10700         
10701         IFS="$ORIGINAL_IFS"
10702         a_temp=${A_SENSORS_DATA[@]}
10703         log_function_data "A_SENSORS_DATA: $a_temp"
10704 #       echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}"
10705         eval $LOGFE
10706 }
10707
10708 get_sensors_output()
10709 {
10710         local sensors_data=''
10711         
10712         if type -p sensors &>/dev/null;then
10713                 sensors_data="$( sensors 2>/dev/null )"
10714                 if [[ -n "$sensors_data" ]];then
10715                         # make sure the file ends in newlines then characters, the newlines are lost in the echo unless
10716                         # the data ends in some characters
10717                         sensors_data="$sensors_data\n\n###" 
10718                 fi
10719         fi
10720         echo -e "$sensors_data"
10721 }
10722
10723 get_shell_data()
10724 {
10725         eval $LOGFS
10726
10727         local shell_type="$( ps -p $PPID -o comm= 2>/dev/null )"
10728         local shell_version='' 
10729         
10730         if [[ $B_EXTRA_DATA == 'true' && -n $shell_type ]];then
10731                 case $shell_type in
10732                         bash)
10733                                 shell_version=$( get_program_version "$shell_type" "^GNU[[:space:]]bash,[[:space:]]version" "4" | \
10734                                 sed $SED_RX 's/(\(.*|-release|-version)//' )
10735                                 ;;
10736                         # csh/dash use dpkg package version data, debian/buntu only
10737                         csh)
10738                                 shell_version=$( get_program_version "$shell_type" "^tcsh" "2" )
10739                                 ;;
10740                         dash)
10741                                 shell_version=$( get_program_version "$shell_type" "$shell_type" "3" )
10742                                 ;;
10743                         ksh)
10744                                 shell_version=$( get_program_version "$shell_type" "version" "5" )
10745                                 ;;
10746                         tcsh)
10747                                 shell_version=$( get_program_version "$shell_type" "^tcsh" "2" )
10748                                 ;;
10749                         zsh)
10750                                 shell_version=$( get_program_version "$shell_type" "^zsh" "2" )
10751                                 ;;
10752                 esac
10753         fi
10754         if [[ -n $shell_version ]];then
10755                 shell_type="$shell_type $shell_version"
10756         fi
10757         echo $shell_type
10758         log_function_data "shell type: $shell_type"
10759         eval $LOGFE
10760 }
10761
10762 get_shell_parent()
10763 {
10764         eval $LOGFS
10765         local shell_parent='' script_parent='' 
10766         
10767         # removed --no-headers to make bsd safe, adding in -j to make output the same
10768         script_parent=$( ps -j -fp $PPID 2>/dev/null | gawk '/'"$PPID"'/ { print $3 }' )
10769         log_function_data "script parent: $script_parent"
10770         shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
10771         # no idea why have to do script_parent action twice in su case, but you do, oh well.
10772         if [[ $shell_parent == 'su' ]];then
10773                 script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
10774                 script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
10775                 shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
10776         fi
10777         echo $shell_parent
10778         log_function_data "shell parent final: $shell_parent"
10779         eval $LOGFE
10780 }
10781
10782 # this will be used for some bsd data types
10783 # args: $1 - option type
10784 get_sysctl_data()
10785 {
10786         eval $LOGFS
10787         
10788         local sysctl_data=''
10789         
10790         if [[ $B_SYSCTL ]];then
10791                 # darwin sysctl has BOTH = and : separators, and repeats data. Why? No bsd discipline, that's for sure
10792                 if [[ $BSD_VERSION == 'darwin' ]];then
10793                         sysctl_data="$( sysctl -$1 | sed 's/[[:space:]]*=[[:space:]]*/: /' )"
10794                 else
10795                         sysctl_data="$( sysctl -$1 )"
10796                 fi
10797         fi
10798         # log_function_data "sysctl_data: $sysctl_data"
10799         echo "$sysctl_data"
10800         
10801         eval $LOGFE
10802 }
10803
10804 get_tty_console_irc()
10805 {
10806         eval $LOGFS
10807         local tty_number=''
10808         if [[ -n $IRC_CLIENT ]];then
10809                 tty_number=$( gawk '
10810                         BEGIN {
10811                                 IGNORECASE=1
10812                         }
10813                         # if multiple irc clients open, can give wrong results
10814                         # so make sure to also use the PPID number to get the right tty
10815                         /.*'$PPID'.*'$IRC_CLIENT'/ {
10816                                 gsub(/[^0-9]/, "", $7)
10817                                 print $7
10818                                 exit
10819                         }' <<< "$Ps_aux_Data" )
10820         fi
10821         log_function_data "tty_number: $tty_number"
10822         echo $tty_number
10823         eval $LOGFE
10824 }
10825
10826 get_tty_number()
10827 {
10828         eval $LOGFS
10829         
10830         local tty_number=$( tty 2>/dev/null | sed 's/[^0-9]*//g' )
10831         tty_number=${tty_number##*/}
10832         echo ${tty_number##*/}
10833         
10834         eval $LOGFE
10835 }
10836
10837 get_unmounted_partition_data()
10838 {
10839         eval $LOGFS
10840         local a_unmounted_working='' mounted_partitions='' separator='|' unmounted_fs=''
10841         local dev_working='' uuid_working='' label_working='' a_raid_working='' raid_partitions=''
10842         
10843         if [[ $B_PARTITIONS_FILE == 'true' ]];then
10844                 # set dev disk label/uuid data globals
10845                 get_partition_dev_data 'label'
10846                 get_partition_dev_data 'uuid'
10847                 # load the raid data array here so we can exclude its partitions
10848                 if [[ $B_RAID_SET != 'true' ]];then
10849                         get_raid_data
10850                 fi
10851                 # sr0 type cd drives are showing up now as unmounted partitions
10852                 mounted_partitions="scd[0-9]+|sr[0-9]+|cdrom[0-9]*|cdrw[0-9]*|dvd[0-9]*|dvdrw[0-9]*"
10853                 # create list for slicing out the mounted partitions
10854                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
10855                 do
10856                         IFS=","
10857                         a_unmounted_working=( ${A_PARTITION_DATA[i]} )
10858                         IFS="$ORIGINAL_IFS"
10859                         if [[ -n ${a_unmounted_working[6]} ]];then
10860                                 mounted_partitions="$mounted_partitions$separator${a_unmounted_working[6]}"
10861                         fi
10862                 done
10863                 # now we need to exclude the mdraid partitions from the unmounted partition output as well
10864                 for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
10865                 do
10866                         IFS=","
10867                         a_raid_working=( ${A_RAID_DATA[i]} )
10868                         IFS="$ORIGINAL_IFS"
10869                         if [[ -n ${a_raid_working[3]} ]];then
10870                                 raid_partitions=$( sed $SED_RX 's/(\([^\)]*\)|\[[^\]]*\])//g' <<< ${a_raid_working[3]}\
10871                                 | sed 's/[[:space:]]\+/|/g' )
10872                                 mounted_partitions="$mounted_partitions$separator$raid_partitions"
10873                         fi
10874                 done
10875         
10876                 A_UNMOUNTED_PARTITION_DATA=( $( grep -Ev '[[:space:]]('$mounted_partitions')$' $FILE_PARTITIONS | gawk '
10877                 BEGIN {
10878                         IGNORECASE=1
10879                 }
10880                 # note that size 1 means it is a logical extended partition container
10881                 # lvm might have dm-1 type syntax
10882                 # need to exclude loop type file systems, squashfs for example
10883                 /[a-z][0-9]+$|dm-[0-9]+$/ && $3 != 1 && $NF !~ /loop/ {
10884                         size = sprintf( "%.2f", $3*1024/1000**3 )
10885                         print $4 "," size "G"
10886                 }' ) )
10887
10888                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
10889                 do
10890                         IFS=","
10891                         a_unmounted_working=( ${A_UNMOUNTED_PARTITION_DATA[i]} )
10892                         IFS="$ORIGINAL_IFS"
10893                         
10894                         label_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_LABEL"  | gawk '{
10895                                 print $(NF - 2)
10896                         }' )
10897                         uuid_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_UUID"  | gawk '{
10898                                 print $(NF - 2)
10899                         }' )
10900                         unmounted_fs=$( get_unmounted_partition_filesystem "/dev/${a_unmounted_working[0]}" )
10901                         
10902                         IFS=","
10903                         A_UNMOUNTED_PARTITION_DATA[i]=${a_unmounted_working[0]}","${a_unmounted_working[1]}","$label_working","$uuid_working","$unmounted_fs
10904                         IFS="$ORIGINAL_IFS"
10905                 done
10906         fi
10907 #       echo "${A_PARTITION_DATA[@]}"
10908 #       echo "${A_UNMOUNTED_PARTITION_DATA[@]}"
10909         eval $LOGFE
10910 }
10911
10912 # a few notes, normally file -s requires root, but you can set user rights in /etc/sudoers.
10913 # list of file systems: http://en.wikipedia.org/wiki/List_of_file_systems
10914 # args: $1 - /dev/<disk><part> to be tested for
10915 get_unmounted_partition_filesystem()
10916 {
10917         eval $LOGFS
10918         local partition_filesystem='' sudo_command=''
10919         
10920         if [[ $B_FILE_TESTED != 'true' ]];then
10921                 B_FILE_TESTED='true'
10922                 FILE_PATH=$( type -p file )
10923         fi
10924         
10925         if [[ $B_SUDO_TESTED != 'true' ]];then
10926                 B_SUDO_TESTED='true'
10927                 SUDO_PATH=$( type -p sudo )
10928         fi
10929         
10930         if [[ -n $FILE_PATH && -n $1 ]];then
10931                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
10932                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
10933                 # important: -n makes it non interactive, no prompt for password
10934                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
10935                         sudo_command='sudo -n '
10936                 fi
10937                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
10938                 # note the hack that simply slices out the first line if > 1 items found in string
10939                 # also, if grub/lilo is on partition boot sector, no file system data is available
10940                 # BSD fix: -Eio -Em 1
10941                 partition_filesystem=$( eval $sudo_command $FILE_PATH -s $1 | grep -Eio '(ext2|ext3|ext4|ext5|ext[[:space:]]|ntfs|fat32|fat16|fat[[:space:]]\(.*\)|vfat|fatx|tfat|swap|btrfs|ffs[[:space:]]|hfs\+|hfs[[:space:]]plus|hfs[[:space:]]extended[[:space:]]version[[:space:]][1-9]|hfsj|hfs[[:space:]]|jfs[[:space:]]|nss[[:space:]]|reiserfs|reiser4|ufs2|ufs[[:space:]]|xfs[[:space:]]|zfs[[:space:]])' | grep -Em 1 '.*' )
10942                 if [[ -n $partition_filesystem ]];then
10943                         echo $partition_filesystem
10944                 fi
10945         fi
10946         eval $LOGFE
10947 }
10948
10949 ## return uptime string
10950 get_uptime()
10951 {
10952         eval $LOGFS
10953         local uptime_value=''
10954         ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a
10955         if type -p uptime &>/dev/null;then
10956                 uptime_value="$( uptime | gawk '{
10957                         a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0)
10958                         print a
10959                 }' )"
10960         fi
10961         echo "$uptime_value"
10962         log_function_data "uptime_value: $uptime_value"
10963         eval $LOGFE
10964 }
10965
10966 get_weather_data()
10967 {
10968         eval $LOGFS
10969         
10970         local location_site='http://geoip.ubuntu.com/lookup'
10971         local weather_feed='http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query='
10972         local weather_spider='http://wunderground.com/'
10973         local data_grab_error='' downloader_error=0 
10974         local b_test_loc=false b_test_weather=false b_debug=false
10975         local test_dir="$HOME/bin/scripts/inxi/data/weather/"
10976         local test_location='location2.xml' test_weather='weather-feed.xml'
10977         local location_data='' location='' weather_data='' location_array_value='' a_location=''
10978         local weather_array_value='' site_elevation='' a_temp=''
10979         
10980         # first we get the location data, once that is parsed and handled, we move to getting the 
10981         # actual weather data, assuming no errors
10982         if [[ -n $ALTERNATE_WEATHER_LOCATION ]];then
10983                 # note, this api does not support spaces in names, replace spaces with + sign.
10984                 location=$ALTERNATE_WEATHER_LOCATION
10985                 # echo $ALTERNATE_WEATHER_LOCATION;exit
10986         else
10987                 if [[ $b_test_loc != 'true' ]];then
10988                         case $DOWNLOADER in
10989                                 curl)
10990                                         location_data="$( curl -y $DL_TIMEOUT -s $location_site )" || downloader_error=$?
10991                                         ;;
10992                                 fetch)
10993                                         location_data="$( fetch -T $DL_TIMEOUT -q -o - $location_site )" || downloader_error=$?
10994                                         ;;
10995                                 ftp)
10996                                         location_data="$( ftp -o - $location_site 2>/dev/null )" || downloader_error=$?
10997                                         ;;
10998                                 wget)
10999                                         location_data="$( wget -t 1 -T $DL_TIMEOUT -q -O - $location_site )" || downloader_error=$?
11000                                         ;;
11001                                 no-downloader)
11002                                         downloader_error=100
11003                                         ;;
11004                         esac
11005                         log_function_data "$location_data"
11006                         
11007                         if [[ $downloader_error -ne 0 ]];then
11008                                 if [[ $downloader_error -eq 100 ]];then
11009                                         data_grab_error="Error: No downloader tool available. Install wget, curl, or fetch."
11010                                 else
11011                                         data_grab_error="Error: location server up but download error - $DOWNLOADER: $downloader_error"
11012                                 fi
11013                         fi
11014                         downloader_error=0
11015                 else
11016                         if [[ -f $test_dir$test_location ]];then
11017                                 location_data="$( cat $test_dir$test_location )"
11018                         else
11019                                 data_grab_error="Error: location xml local file not found."
11020                         fi
11021                 fi
11022                 if [[ -n $data_grab_error ]];then
11023                         :
11024                 elif [[ -z $( grep -i '<Response' <<< $location_data ) ]];then
11025                         data_grab_error="Error: location downloaded but data contains no xml."
11026                 else
11027                         # clean up xml and make easy to process with newlines, note, bsd sed has no support for inserting
11028                         # \n dircctly so we have to use this hack
11029                         # location_data="$( sed $SED_RX 's|><|>\n<|g' <<< $location_data )"
11030                         location_data="$( sed $SED_RX 's|><|>\
11031 <|g' <<< $location_data )"
11032                         # echo -e "ld:\n$location_data"
11033                         location_array_value=$( gawk '
11034                         function clean(data) {
11035                                 returnData=""
11036                                 # some lines might be empty, so ignore those
11037                                 if (data !~ /^<[^>]+>$/ ) {
11038                                         returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
11039                                 }
11040                                 return returnData
11041                         }
11042                         BEGIN {
11043                                 IGNORECASE=1
11044                                 locationString=""
11045                                 countryCode=""
11046                                 countryCode3=""
11047                                 countryName=""
11048                                 regionCode=""
11049                                 regionName=""
11050                                 city=""
11051                                 postalCode=""
11052                                 latitude=""
11053                                 longitude=""
11054                                 timeZone=""
11055                                 areaCode=""
11056                         }
11057                         /CountryCode/ {
11058                                 if ( $0 ~ /CountryCode3/ ){
11059                                         countryCode3=clean($0)
11060                                 }
11061                                 else {
11062                                         countryCode=clean($0)
11063                                 }
11064                         }
11065                         /CountryName/ {
11066                                 countryName = clean($0)
11067                         }
11068                         /RegionCode/ {
11069                                 regionCode = clean($0)
11070                         }
11071                         /RegionName/ {
11072                                 regionName = clean($0)
11073                         }
11074                         /City/ {
11075                                 city = clean($0)
11076                         }
11077                         /ZipPostalCode/ {
11078                                 postalCode = clean($0)
11079                         }
11080                         /Latitude/ {
11081                                 latitude = clean($0)
11082                         }
11083                         /Longitude/ {
11084                                 longitude = clean($0)
11085                         }
11086                         /TimeZone/ {
11087                                 timeZone = clean($0)
11088                         }
11089                         END {
11090                                 locationString = city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3 
11091                                 locationString = locationString  ";" latitude "," longitude ";" postalCode ";" timeZone
11092                                 print locationString
11093                         }' <<< "$location_data" )
11094                 fi
11095                 A_WEATHER_DATA[0]=$location_array_value
11096                 IFS=";"
11097                 a_location=( ${A_WEATHER_DATA[0]} )
11098                 IFS="$ORIGINAL_IFS"
11099                 
11100                 # assign location, cascade from most accurate
11101                 # latitude,longitude first
11102                 if [[ -n ${a_location[6]} ]];then
11103                         location="${a_location[6]}"
11104                 # city,state next
11105                 elif [[ -n ${a_location[0]} && -n ${a_location[1]} ]];then
11106                         location="${a_location[0]},${a_location[1]}"
11107                 # postal code last, that can be a very large region
11108                 elif [[ -n ${a_location[7]} ]];then
11109                         location=${a_location[7]}
11110                 fi
11111         fi
11112         if [[ $b_debug == 'true' ]];then
11113                 echo -e "location array:\n${A_WEATHER_DATA[0]}"
11114                 echo "location: $location"
11115         fi
11116         log_function_data "location: $location"
11117         
11118         if [[ -z $location && -z $data_grab_error ]];then
11119                 data_grab_error="Error: location data downloaded but no location detected."
11120         fi
11121
11122         # now either dump process or go on to get weather data
11123         if [[ -z $data_grab_error ]];then
11124                 if [[ $b_test_weather != 'true' ]];then
11125                         case $DOWNLOADER in
11126                                 curl)
11127                                         weather_data="$( curl -y $DL_TIMEOUT -s $weather_feed"$location" )" || downloader_error=$?
11128                                         ;;
11129                                 fetch)
11130                                         weather_data="$( fetch -T $DL_TIMEOUT -q -o - $weather_feed"$location" )" || downloader_error=$?
11131                                         ;;
11132                                 ftp)
11133                                         weather_data="$( ftp -o - $weather_feed"$location" 2>/dev/null )" || downloader_error=$?
11134                                         ;;
11135                                 wget)
11136                                         weather_data="$( wget -t 1 -T $DL_TIMEOUT -q -O - $weather_feed"$location" )" || downloader_error=$?
11137                                         ;;
11138                                 no-downloader)
11139                                         downloader_error=100
11140                                         ;;
11141                         esac
11142                         if [[ $downloader_error -ne 0 ]];then
11143                                 if [[ $downloader_error -eq 100 ]];then
11144                                         data_grab_error="Error: No downloader tool available. Install wget, curl, or fetch."
11145                                 else
11146                                         data_grab_error="Error: weather server up but download error - $DOWNLOADER: $downloader_error"
11147                                 fi
11148                         fi
11149                         log_function_data "$weather_data"
11150                 else
11151                         if [[ -f $test_dir$test_weather ]];then
11152                                 weather_data="$( cat $test_dir$test_weather)"
11153                         else
11154                                 data_grab_error="Error: weather feed xml local file not found."
11155                         fi
11156                 fi
11157                 if [[ -z $data_grab_error && -z $( grep -i '<current_observation' <<< $weather_data ) ]];then
11158                         data_grab_error="Error: weather data downloaded but shows no xml start."
11159                 fi
11160                 if [[ -z $data_grab_error ]];then
11161                         # trim off zeros
11162                         weather_data=$( sed 's/^[[:space:]]*//' <<< "$weather_data" )
11163                         site_elevation=$( grep -im 1 '<elevation>' <<< "$weather_data" | sed $SED_RX -e 's/<[^>]*>//g' \
11164                         -e 's/\.[0-9]*//' )
11165                         # we need to grab the location data from the feed for remote checks 
11166                         if [[ -n $ALTERNATE_WEATHER_LOCATION && -n $weather_data ]];then
11167                                 location_data=$( sed -e '/<current_observation>/,/<display_location>/d' -e '/<\/display_location>/,/<\/current_observation>/d' <<< "$weather_data" )
11168                                 # echo -e "ld1:\n$location_data"
11169                                 A_WEATHER_DATA[0]=$( gawk '
11170                                 function clean(data) {
11171                                         returnData=""
11172                                         # some lines might be empty, so ignore those
11173                                         if (data !~ /^<[^>]+>$/ ) {
11174                                                 returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
11175                                                 gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
11176                                         }
11177                                         return returnData
11178                                 }
11179                                 BEGIN {
11180                                         IGNORECASE=1
11181                                         city=""
11182                                         state=""
11183                                         country=""
11184                                 }
11185                                 /<city>/ {
11186                                         city=clean($0)
11187                                 }
11188                                 /<state>/ {
11189                                         state=clean($0)
11190                                 }
11191                                 /<country>/ {
11192                                         country=clean($0)
11193                                 }
11194                                 END {
11195                                         print city ";" state ";;;;" country
11196                                 }' <<< "$location_data" )
11197                                 # echo -e "location:\n${A_WEATHER_DATA[0]}"
11198                         fi
11199                         
11200                         # clean off everything before/after observation_location
11201                         weather_data=$( sed -e '/<current_observation>/,/<observation_location>/d' \
11202                         -e '/<icons>/,/<\/current_observation>/d' <<< "$weather_data" -e 's/^[[:space:]]*$//g' -e '/^$/d' )
11203                         
11204                         # echo "$weather_data";exit 
11205                         weather_array_value=$( gawk -v siteElevation="$site_elevation" '
11206                         function clean(data) {
11207                                 returnData=""
11208                                 # some lines might be empty, so ignore those
11209                                 if (data !~ /^<[^>]+>$/ ) {
11210                                         returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
11211                                         gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
11212                                 }
11213                                 return returnData
11214                         }
11215                         BEGIN {
11216                                 IGNORECASE=1
11217                                 observationTime=""
11218                                 localTime=""
11219                                 weather=""
11220                                 tempString=""
11221                                 humidity=""
11222                                 windString=""
11223                                 pressureString=""
11224                                 dewpointString=""
11225                                 heatIndexString=""
11226                                 windChillString=""
11227                                 weatherString=""
11228                         }
11229                         /observation_time>/ {
11230                                 observationTime=clean($0)
11231                                 sub(/Last Updated on /, "", observationTime )
11232                         }
11233                         /local_time>/ {
11234                                 localTime=clean($0)
11235                         }
11236                         /<weather/ {
11237                                 weather=clean($0)
11238                         }
11239                         /temperature_string/ {
11240                                 tempString=clean($0)
11241                         }
11242                         /relative_humidity/ {
11243                                 humidity=clean($0)
11244                         }
11245                         /wind_string/ {
11246                                 windString=clean($0)
11247                         }
11248                         /pressure_string/ {
11249                                 pressureString=clean($0)
11250                         }
11251                         /heat_index_string/ {
11252                                 heatIndexString=clean($0)
11253                         }
11254                         /windchill_string/ {
11255                                 windChillString=clean($0)
11256                         }
11257                         END {
11258                                 weatherString = observationTime ";" localTime ";" weather ";" tempString ";" humidity 
11259                                 weatherString = weatherString ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
11260                                 weatherString = weatherString ";" windChillString ";" siteElevation
11261                                 print weatherString
11262                         }' <<< "$weather_data" )
11263                 fi
11264                 if [[ -z $weather_array_value ]];then
11265                         data_grab_error="Error: weather info downloaded but no data detected."
11266                 else
11267                         A_WEATHER_DATA[1]=$weather_array_value
11268                 fi
11269         fi
11270         # now either dump process or go on to get weather data
11271         if [[ -n $data_grab_error ]];then
11272                 A_WEATHER_DATA=$data_grab_error
11273                 log_function_data "data grab error: $data_grab_error"
11274         fi
11275         
11276         if [[ $b_debug == 'true' ]];then
11277                 echo "site_elevation: $site_elevation"
11278                 echo "${A_WEATHER_DATA[1]}"
11279         fi
11280         a_temp=${A_WEATHER_DATA[@]}
11281         log_function_data "A_WEATHER_DATA: $a_temp"
11282         
11283         eval $LOGFE
11284 }
11285 # ALTERNATE_WEATHER_LOCATION='portland,or'
11286 # get_weather_data;exit
11287
11288 #### -------------------------------------------------------------------
11289 #### special data handling for specific options and conditions
11290 #### -------------------------------------------------------------------
11291
11292 # args: $1 - string to strip color code characters out of
11293 # returns count of string length minus colors
11294 # note; this cleanup may not be working on bsd sed
11295 calculate_line_length()
11296 {
11297         local string=$1
11298         # ansi: \e[1;34m irc: \x0312
11299         # note: using special trick for bsd sed, tr - NOTE irc sed must use " double quote
11300         string=$( sed -e 's/'$ESC'\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' -e "s/\\\x0[0-9]\{1,3\}//g" <<< $string )
11301         count=${#string}
11302         echo $count
11303 }
11304
11305 ## multiply the core count by the data to be calculated, bmips, cache
11306 # args: $1 - string to handle; $2 - cpu count
11307 calculate_multicore_data()
11308 {
11309         eval $LOGFS
11310         local string_number=$1 string_data=''
11311
11312         if [[ -n $( grep -Ei '( mb| kb)' <<< $1 ) ]];then
11313                 string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output
11314                 string_number=$( gawk '{print $1}' <<< $1 )
11315         fi
11316         # handle weird error cases where it's not a number
11317         if [[ -n $( grep -E '^[0-9\.,]+$' <<< $string_number ) ]];then
11318                 string_number=$( echo $string_number $2 | gawk '{
11319                         total = $1*$2
11320                         print total
11321                 }' )
11322         elif [[ $string_number == '' ]];then
11323                 string_number='N/A'
11324         else
11325                 # I believe that the above returns 'unknown' by default so no need for extra text
11326                 string_number="$string_number "
11327         fi
11328         echo "$string_number$string_data"
11329         log_function_data "string_numberstring_data: $string_number$string_data"
11330         eval $LOGFE
11331 }
11332
11333 # prints out shortened list of flags, the main ones of interest
11334 # args: $1 - string of cpu flags to process
11335 process_cpu_flags()
11336 {
11337         eval $LOGFS
11338         
11339         local cpu_flags_working=$1
11340         local bits=$( uname -m | grep 64 )
11341         
11342         # no need to show pae for 64 bit cpus, it's pointless
11343         if [[ -n $bits ]];then
11344                 cpu_flags_working=$( sed 's/[[:space:]]*pae//' <<< "$cpu_flags_working" )
11345         fi
11346         # must have a space after last item in list for RS=" "
11347         cpu_flags_working="$cpu_flags_working "
11348         
11349         # nx = AMD stack protection extensions
11350         # lm = Intel 64bit extensions
11351         # sse, sse2, pni = sse1,2,3,4,5 gfx extensions
11352         # svm = AMD pacifica virtualization extensions
11353         # vmx = Intel IVT (vanderpool) virtualization extensions
11354         cpu_flags=$( gawk '
11355         BEGIN {
11356                 RS=" "
11357                 count = 0
11358                 i = 1 # start at one because of for increment issue
11359                 flag_string = ""
11360         }
11361         
11362         /^(lm|nx|pae|pni|svm|vmx|(sss|ss)e([2-9])?([a-z])?(_[0-9])?)$/ {
11363                 if ( $0 == "pni" ){
11364                         a_flags[i] = "sse3"
11365                 }
11366                 else {
11367                         a_flags[i] = $0
11368                 }
11369                 i++
11370         }
11371         END {
11372                 count = asort( a_flags )
11373                 # note: why does gawk increment before the loop and not after? weird.
11374                 for ( i=0; i <= count; i++ ){
11375                         if ( flag_string == "" ) {
11376                                 flag_string = a_flags[i] 
11377                         }
11378                         else {
11379                                 flag_string = flag_string " " a_flags[i]
11380                         }
11381                 }
11382                 print flag_string
11383         }' <<< "$cpu_flags_working" )
11384
11385         #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' '))
11386         if [[ -z $cpu_flags ]];then
11387                 cpu_flags="-"
11388         fi
11389         echo "$cpu_flags"
11390         log_function_data "cpu_flags: $cpu_flags"
11391         eval $LOGFE
11392 }
11393
11394 #### -------------------------------------------------------------------
11395 #### print and processing of output data
11396 #### -------------------------------------------------------------------
11397
11398 #### MASTER PRINT FUNCTION - triggers all line item print functions
11399 ## main function to print out, master for all sub print functions.
11400 print_it_out()
11401 {
11402         eval $LOGFS
11403         # note that print_it_out passes local variable values on to its children,
11404         # and in some cases, their children, with Lspci_v_Data
11405         local Lspci_v_Data='' Lspci_n_Data='' # only for verbose
11406         local Sysctl_a_Data='' Dmesg_Boot_Data=''
11407         
11408         if [[ -n $BSD_TYPE ]];then
11409                 Sysctl_a_Data="$( get_sysctl_data 'a' )"
11410                 Dmesg_Boot_Data="$( get_dmesg_boot_data )"
11411         fi
11412
11413         if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then
11414                 print_short_data
11415         else
11416                 Lspci_v_Data="$( get_lspci_data 'v' )"
11417                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
11418                         Lspci_n_Data="$( get_lspci_data 'n' )"
11419                 fi
11420                 if [[ $B_SHOW_SYSTEM == 'true' ]];then
11421                         print_system_data
11422                 fi
11423                 if [[ $B_SHOW_MACHINE == 'true' ]];then
11424                         print_machine_data
11425                 fi
11426                 if [[ $B_SHOW_BATTERY == 'true' ]];then
11427                         print_battery_data
11428                 fi
11429                 if [[ $B_SHOW_BASIC_CPU == 'true' || $B_SHOW_CPU == 'true' ]];then
11430                         print_cpu_data
11431                 fi
11432                 if [[ $B_SHOW_MEMORY == 'true' ]];then
11433                         print_ram_data
11434                 fi
11435                 if [[ $B_SHOW_GRAPHICS == 'true' ]];then
11436                         print_graphics_data
11437                 fi
11438                 if [[ $B_SHOW_AUDIO == 'true' ]];then
11439                         print_audio_data
11440                 fi
11441                 if [[ $B_SHOW_NETWORK == 'true' ]];then
11442                         print_networking_data
11443                 fi
11444                 if [[ $B_SHOW_DISK_TOTAL == 'true' || $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
11445                         print_hard_disk_data
11446                 fi
11447                 if [[ $B_SHOW_PARTITIONS == 'true' ]];then
11448                         print_partition_data
11449                 fi
11450                 if [[ $B_SHOW_RAID == 'true' || $B_SHOW_BASIC_RAID == 'true' ]];then
11451                         print_raid_data
11452                 fi
11453                 if [[ $B_SHOW_UNMOUNTED_PARTITIONS == 'true' ]];then
11454                         print_unmounted_partition_data
11455                 fi
11456                 if [[ $B_SHOW_SENSORS == 'true' ]];then
11457                         print_sensors_data
11458                 fi
11459                 if [[ $B_SHOW_REPOS == 'true' ]];then
11460                         print_repo_data
11461                 fi
11462                 if [[ $B_SHOW_PS_CPU_DATA == 'true' || $B_SHOW_PS_MEM_DATA == 'true' ]];then
11463                         print_ps_data
11464                 fi
11465                 if [[ $B_SHOW_WEATHER == 'true' ]];then
11466                         print_weather_data
11467                 fi
11468                 if [[ $B_SHOW_INFO == 'true' ]];then
11469                         print_info_data
11470                 fi
11471         fi
11472         ## last steps, clear any lingering colors
11473         if [[ $B_IRC == 'false' && $SCHEME -gt 0 ]];then
11474                 echo -n "\e[0m"
11475         fi
11476         
11477         eval $LOGFE
11478 }
11479
11480 #### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0
11481 # all the get data stuff is loaded here to keep execution time down for single line print commands
11482 # these will also be loaded in each relevant print function for long output
11483 print_short_data()
11484 {
11485         eval $LOGFS
11486         local current_kernel=$( get_kernel_version ) 
11487         local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
11488         local short_data='' i='' b_background_black='false'
11489         local memory=$( get_memory_data )
11490         local up_time="$( get_uptime )"
11491         if [[ -z $up_time ]];then
11492                 up_time='N/A - missing uptime?'
11493         fi
11494
11495         # set A_CPU_CORE_DATA
11496         get_cpu_core_count
11497         local cpc_plural='' cpu_count_print='' model_plural='' current_max_clock=''
11498         local cpu_physical_count=${A_CPU_CORE_DATA[0]}
11499         local cpu_core_count=${A_CPU_CORE_DATA[3]}
11500         local cpu_core_alpha=${A_CPU_CORE_DATA[1]}
11501         local cpu_type=${A_CPU_CORE_DATA[2]}
11502         local kernel_os='' speed_starter='speed'
11503         local cpu_data_string=''
11504         
11505         if [[ -z $BSD_TYPE || -n $cpu_type ]];then
11506                 cpu_type=" ($cpu_type)"
11507         fi
11508         
11509         if [[ $BSD_TYPE == 'bsd' ]];then
11510                 kernel_os="${C1}OS${C2}$SEP1$( uname -rsp )" 
11511         else
11512                 kernel_os="${C1}Kernel${C2}$SEP1$current_kernel"
11513         fi
11514
11515         if [[ $cpu_physical_count -gt 1 ]];then
11516                 cpc_plural='(s)'
11517                 model_plural='s'
11518                 cpu_count_print="$cpu_physical_count "
11519                 # for multicpu systems, divide total cores by cpu count to get per cpu cores
11520                 $cpu_core_count=$(($cpu_core_count/$cpu_physical_count))
11521         fi
11522         if [[ -z $BSD_TYPE ]];then
11523                 cpu_data_string="$cpu_count_print$cpu_core_alpha core"
11524         else
11525                 cpu_data_string="$cpu_count_print$cpu_core_count core"
11526         fi
11527 #       local cpu_core_count=${A_CPU_CORE_DATA[0]}
11528
11529         # load A_HDD_DATA
11530         get_hdd_data_basic
11531         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
11532         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
11533         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
11534         IFS=","
11535         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
11536         IFS="$ORIGINAL_IFS"
11537         local hdd_capacity=${a_hdd_basic_working[0]}
11538         local hdd_used=${a_hdd_basic_working[1]}
11539
11540         # load A_CPU_DATA
11541         get_cpu_data
11542
11543         IFS=","
11544         local a_cpu_working=(${A_CPU_DATA[0]})
11545         # this gets that weird min/max final array item, which almost never contains any data of use
11546         local current_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
11547         local a_cpu_speeds=(${A_CPU_DATA[$current_max_clock_nu]})
11548         IFS="$ORIGINAL_IFS"
11549         local cpu_model="${a_cpu_working[0]}"
11550         ## assemble data for output
11551         local cpu_clock="${a_cpu_working[1]}" # old CPU3
11552         # echo $cpu_clock
11553         # if [[ -z ${a_cpu_working[1]} || ${a_cpu_working[1]} < 50 ]];then
11554         #       a_cpu_working[1]=$(get_cpu_speed_hack)
11555         # fi
11556         
11557         # this handles the case of for example ARM cpus, which will not have data for
11558         # min/max, since they don't have speed. Since that sets a flag, not found, just
11559         # look for that and use the speed from the first array array, same where we got 
11560         # model from
11561         # index: 0 speed ; 1 min ; 2 max
11562         # this handles bsd types which always should show N/A unless we get a way to get min / max data
11563         if [[ "${a_cpu_speeds[0]}" == 'N/A' && ${a_cpu_working[1]} != '' ]];then
11564                 current_max_clock="${a_cpu_working[1]} MHz"
11565         else
11566                 if [[ ${a_cpu_speeds[2]} != 0 ]];then
11567                         if [[ ${a_cpu_speeds[0]} == ${a_cpu_speeds[2]} ]];then
11568                                 current_max_clock="${a_cpu_speeds[0]} MHz (max)"
11569                         else
11570                                 current_max_clock="${a_cpu_speeds[0]}/${a_cpu_speeds[2]} MHz"
11571                                 speed_starter='speed/max'
11572                         fi
11573                 fi
11574         fi
11575         local patch_version_number=$( get_patch_version_string )
11576
11577         #set_color_scheme 12
11578         if [[ $B_IRC == 'true' ]];then
11579                 for i in $C1 $C2 $CN
11580                 do
11581                         case "$i" in
11582                                 "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN")
11583                                         b_background_black='true'
11584                                         ;;
11585                         esac
11586                 done
11587                 if [[ $b_background_black == 'true' ]];then
11588                         for i in C1 C2 CN
11589                         do
11590                                 ## these need to be in quotes, don't know why
11591                                 if [[ ${!i} == $NORMAL ]];then
11592                                         declare $i="${!i}15,1"
11593                                 else
11594                                         declare $i="${!i},1"
11595                                 fi
11596                         done
11597                         #C1="${C1},1"; C2="${C2},1"; CN="${CN},1"
11598                 fi
11599         fi
11600         short_data="${C1}CPU$cpc_plural${C2}$SEP1$cpu_data_string $cpu_model$model_plural$cpu_type ${C1}$speed_starter${C2}$SEP1$current_max_clock$SEP2$kernel_os$SEP2${C1}Up${C2}$SEP1$up_time$SEP2${C1}Mem${C2}$SEP1$memory$SEP2${C1}HDD${C2}$SEP1$hdd_capacity($hdd_used)$SEP2${C1}Procs${C2}$SEP1$processes$SEP2"
11601
11602         if [[ $SHOW_IRC -gt 0 ]];then
11603                 short_data="$short_data${C1}Client${C2}$SEP1$IRC_CLIENT$IRC_CLIENT_VERSION$SEP2"
11604         fi
11605         short_data="$short_data${C1}$SCRIPT_NAME${C2}$SEP1$SCRIPT_VERSION_NUMBER$patch_version_number$SEP2${CN}"
11606         if [[ $SCHEME -gt 0 ]];then
11607                 short_data="$short_data $NORMAL"
11608         fi
11609         print_screen_output "$short_data"
11610         eval $LOGFE
11611 }
11612
11613 #### LINE ITEM PRINT FUNCTIONS
11614
11615 # print sound card data
11616 print_audio_data()
11617 {
11618         eval $LOGFS
11619         local i='' card_id='' audio_data='' a_audio_data='' port_data='' pci_bus_id='' card_string=''
11620         local a_audio_working='' audio_driver='' alsa_data='' port_plural='' module_version='' chip_id=''
11621         local bus_usb_text='' bus_usb_id='' line_starter='Audio:' alsa='' alsa_version='' print_data=''
11622         local driver=''
11623         # set A_AUDIO_DATA and get alsa data
11624         if [[ $BSD_TYPE == 'bsd' ]];then
11625                 if [[ $B_PCICONF == 'true' ]];then
11626                         if [[ $B_PCICONF_SET == 'false' ]];then
11627                                 get_pciconf_data
11628                         fi
11629                         get_pciconf_card_data 'audio'
11630                 elif [[ $B_LSPCI == 'true' ]];then
11631                         get_audio_data
11632                 fi
11633         else
11634                 get_audio_data
11635         fi
11636         
11637         get_audio_alsa_data
11638         # alsa driver data now prints out no matter what
11639         if [[ -n $A_ALSA_DATA ]];then
11640                 IFS=","
11641                 if [[ -n ${A_ALSA_DATA[0]} ]];then
11642                         alsa=${A_ALSA_DATA[0]}
11643                 else
11644                         alsa='N/A'
11645                 fi
11646                 if [[ -n ${A_ALSA_DATA[1]} ]];then
11647                         alsa_version=${A_ALSA_DATA[1]}
11648                 else
11649                         alsa_version='N/A'
11650                 fi
11651                 alsa_data="${C1}Sound$SEP3${C2} $alsa ${C1}v$SEP3${C2} $alsa_version"
11652                 IFS="$ORIGINAL_IFS"
11653         fi
11654         # note, error handling is done in the get function, so this will never be null, but
11655         # leaving the test just in case it's changed.
11656         if [[ -n ${A_AUDIO_DATA[@]} ]];then
11657                 for (( i=0; i< ${#A_AUDIO_DATA[@]}; i++ ))
11658                 do
11659                         IFS=","
11660                         a_audio_working=( ${A_AUDIO_DATA[i]} )
11661                         IFS="$ORIGINAL_IFS"
11662                         port_data=''
11663                         audio_driver=''
11664                         audio_data=''
11665                         card_string=''
11666                         port_plural=''
11667                         module_version=''
11668                         pci_bus_id=''
11669                         bus_usb_text=''
11670                         bus_usb_id=''
11671                         print_data=''
11672                         chip_id=''
11673                         
11674                         if [[ ${#A_AUDIO_DATA[@]} -gt 1 ]];then
11675                                 card_id="-$(( $i + 1 ))"
11676                         fi
11677                         if [[ $BSD_TYPE != 'bsd' ]];then
11678                                 if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then
11679                                         module_version=$( print_module_version "${a_audio_working[3]}" 'audio' )
11680                                 elif [[ -n ${a_audio_working[1]} && $B_EXTRA_DATA == 'true' ]];then
11681                                         module_version=$( print_module_version "${a_audio_working[1]}" 'audio' )
11682                                 fi
11683                         fi
11684                         # we're testing for the presence of the 2nd array item here, which is the driver name
11685                         if [[ -n ${a_audio_working[1]} ]];then
11686                                 # note: linux drivers can have numbers, like tg3
11687                                 if [[ $BSD_TYPE == 'bsd' ]];then
11688                                         driver=$( sed 's/[0-9]$//' <<< ${a_audio_working[1]} )
11689                                 else
11690                                         driver=${a_audio_working[1]}
11691                                 fi
11692                                 audio_driver="${C1}driver$SEP3${C2} $driver "
11693                         fi
11694                         if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then
11695                                 if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then
11696                                         port_plural='s'
11697                                 fi
11698                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_audio_working[2]} "
11699                         fi
11700                         if [[ -n ${a_audio_working[4]} && $B_EXTRA_DATA == 'true' ]];then
11701                                 if [[ ${a_audio_working[1]} != 'USB Audio' ]];then
11702                                         bus_usb_text='bus-ID'
11703                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
11704                                                 if [[ $BSD_TYPE != 'bsd' ]];then
11705                                                         chip_id=$( get_lspci_chip_id "${a_audio_working[4]}" )
11706                                                 else
11707                                                         chip_id=${a_audio_working[6]}
11708                                                 fi
11709                                         fi
11710                                 else
11711                                         bus_usb_text='usb-ID'
11712                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
11713                                                 chip_id=${a_audio_working[5]}
11714                                         fi
11715                                 fi
11716                                 bus_usb_id=${a_audio_working[4]}
11717                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id "
11718                                 if [[ -n $chip_id ]];then
11719                                         chip_id="${C1}chip-ID$SEP3${C2} $chip_id "
11720                                 fi
11721                         fi
11722                         if [[ -n ${a_audio_working[0]} ]];then
11723                                 card_string="${C1}Card$card_id$EP3${C2} ${a_audio_working[0]} "
11724                                 audio_data="$audio_driver$port_data$pci_bus_id$chip_id"
11725                         fi
11726                         # only print alsa on last line if short enough, otherwise print on its own line
11727                         if [[ $i -eq 0 ]];then
11728                                 if [[ -n $alsa_data && $( calculate_line_length "$card_string$audio_data$alsa_data" ) -lt $COLS_INNER ]];then
11729                                         audio_data="$audio_data$alsa_data"
11730                                         alsa_data=''
11731                                 fi
11732                         fi
11733                         if [[ -n $audio_data ]];then
11734                                 if [[ $( calculate_line_length "$card_string$audio_data" ) -lt $COLS_INNER ]];then
11735                                         print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
11736                                         print_screen_output "$print_data"
11737                                 # print the line
11738                                 else
11739                                         # keep the driver on the same line no matter what, looks weird alone on its own line
11740                                         if [[ $( calculate_line_length "$card_string$audio_data" ) -gt $COLS_INNER ]];then
11741                                                 print_data=$( create_print_line "$line_starter" "$card_string" )
11742                                                 print_screen_output "$print_data"
11743                                                 line_starter=' '
11744                                                 print_data=$( create_print_line "$line_starter" "$audio_data" )
11745                                                 print_screen_output "$print_data"
11746                                         else
11747                                                 print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
11748                                                 print_screen_output "$print_data"
11749                                         fi
11750                                 fi
11751                                 line_starter=' '
11752                         fi
11753                 done
11754         fi
11755         if [[ -n $alsa_data ]];then
11756                 if [[ $( calculate_line_length "${alsa_data/ALSA/Advanced Linux Sound Architecture}" ) -lt $COLS_INNER ]];then
11757                         # alsa_data=$( sed 's/ALSA/Advanced Linux Sound Architecture/' <<< $alsa_data )
11758                         alsa_data=${alsa_data/ALSA/Advanced Linux Sound Architecture}
11759                 fi
11760                 alsa_data=$( create_print_line "$line_starter" "$alsa_data" )
11761                 print_screen_output "$alsa_data"
11762         fi
11763         eval $LOGFE
11764 }
11765
11766 print_battery_data()
11767 {
11768         eval $LOGFS
11769         local line_starter='Battery' print_data='' 
11770         get_battery_data
11771         if [[ -n ${A_BATTERY_DATA[@]} ]];then
11772                 local battery_data='' battery_string=''
11773                 local present='' chemistry='' cycles='' voltage_min_design='' voltage_now=''
11774                 local power_now='' charge_full_design='' charge_full='' charge_now='' capacity=''
11775                 local capacity_level='' model='' company='' serial='' of_orig='' model='' condition=''
11776                 local power=''
11777                 
11778                 # echo ${A_BATTERY_DATA[@]}
11779                 for (( i=0; i< ${#A_BATTERY_DATA[@]}; i++ ))
11780                 do
11781                         battery_data='' 
11782                         print_data=''
11783                         battery_string=''
11784                         charge=''
11785                         model=''
11786                         condition=''
11787                         voltage=''
11788                         
11789                         name=''
11790                         status=''
11791                         present=''
11792                         chemistry=''
11793                         cycles=''
11794                         voltage_min_design=''
11795                         voltage_now=''
11796                         power_now=''
11797                         charge_full_design=''
11798                         charge_full=''
11799                         charge_now=''
11800                         capacity=''
11801                         capacity_level=''
11802                         of_orig=''
11803                         model=''
11804                         company=''
11805                         serial=''
11806                         location='' # dmidecode only
11807                         IFS=","
11808                         a_battery_working=( ${A_BATTERY_DATA[i]} )
11809                         IFS="$ORIGINAL_IFS"
11810                         bat_id="$(( $i + 1 ))"
11811                         
11812                         if [[ -n ${a_battery_working[10]} ]];then
11813                                 charge="${a_battery_working[10]} Wh "
11814                         fi
11815                         if [[ -n ${a_battery_working[11]} ]];then
11816                                 charge="$charge${a_battery_working[11]} "
11817                         fi
11818                         if [[ $charge == '' ]];then
11819                                 charge='N/A '
11820                         fi
11821                         charge="${C1}charge$SEP3${C2} $charge"
11822                         if [[ -n ${a_battery_working[9]} ]];then
11823                                 condition="${a_battery_working[9]}"
11824                         else
11825                                 condition='NA'
11826                         fi
11827                         if [[ -n ${a_battery_working[8]} ]];then
11828                                 condition="$condition/${a_battery_working[8]} Wh "
11829                         else
11830                                 condition="$condition/NA Wh "
11831                         fi
11832                         if [[ -n ${a_battery_working[13]} ]];then
11833                                 condition="$condition(${a_battery_working[13]}) "
11834                         fi
11835                         if [[ $condition == '' ]];then
11836                                 condition='N/A '
11837                         fi
11838                         condition="${C1}condition$SEP3${C2} $condition"
11839                         if [[ $B_EXTRA_DATA == 'true' ]];then
11840                                 if [[ -n ${a_battery_working[15]} ]];then
11841                                         model="${a_battery_working[15]} "
11842                                 fi
11843                                 if [[ -n ${a_battery_working[14]} ]];then
11844                                         model="$model${a_battery_working[14]} "
11845                                 fi
11846                                 if [[ $model == '' ]];then
11847                                         model='N/A '
11848                                 fi
11849                                 model="${C1}model$SEP3${C2} $model"
11850                         
11851                                 if [[ -n ${a_battery_working[1]} ]];then
11852                                         status="${a_battery_working[1]} "
11853                                 else
11854                                         status="N/A "
11855                                 fi
11856                                 status="${C1}status$SEP3${C2} $status"
11857                         fi
11858                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
11859                                 if [[ -n ${a_battery_working[16]} ]];then
11860                                         serial="${a_battery_working[16]} "
11861                                 else 
11862                                         serial='N/A '
11863                                 fi
11864                                 serial="${C1}serial$SEP3${C2} $serial"
11865                                 if [[ -n ${a_battery_working[6]} ]];then
11866                                         voltage="${a_battery_working[6]}"
11867                                 fi
11868                                 if [[ -n ${a_battery_working[5]} ]];then
11869                                         if [[ $voltage == '' ]];then
11870                                                 voltage='NA'
11871                                         fi
11872                                         voltage="$voltage/${a_battery_working[5]} "
11873                                 fi
11874                                 if [[ $voltage == '' ]];then
11875                                         voltage='NA '
11876                                 fi
11877                                 voltage="${C1}volts$SEP3${C2} $voltage"
11878                         fi
11879                         if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
11880                                 if [[ -n ${a_battery_working[3]} ]];then
11881                                         chemistry="${a_battery_working[3]} "
11882                                 fi
11883                                 if [[ -n ${a_battery_working[4]} ]];then
11884                                         cycles="${C1}cycles$SEP3${C2} ${a_battery_working[4]} "
11885                                 fi
11886                                 # location is dmidecode only
11887                                 if [[ -n ${a_battery_working[17]} ]];then
11888                                         location="${C1}loc$SEP3${C2} ${a_battery_working[17]} "
11889                                 fi
11890                         fi
11891                         if [[ -n ${a_battery_working[15]} ]];then
11892                                 battery_string="${C1}${a_battery_working[0]}$SEP3${C2} $charge$condition"
11893                                 battery_data="$model$chemistry$serial$status$cycles$location"
11894                         fi
11895                         
11896                         if [[ ${A_BATTERY_DATA[0]} == 'dmidecode-error-'* ]];then
11897                                 error_string=$( print_dmidecode_error 'bat' "${A_BATTERY_DATA[0]}" )
11898                                 battery_string=${C2}$error_string
11899                                 battery_data=''
11900                                 voltage=''
11901                         fi
11902                         
11903                         if [[ -n $battery_string ]];then
11904                                 if [[ $( calculate_line_length "$battery_string$voltage$battery_data" ) -lt $COLS_INNER ]];then
11905                                         #echo one
11906                                         print_data=$( create_print_line "$line_starter" "$battery_string$voltage$battery_data" )
11907                                         print_screen_output "$print_data"
11908                                 # print the line
11909                                 else
11910                                         # keep the driver on the same line no matter what, looks weird alone on its own line
11911                                         if [[ $( calculate_line_length "$battery_string$voltage$battery_data" ) -gt $COLS_INNER ]];then
11912                                                 if [[ $( calculate_line_length "$battery_string$voltage" ) -gt $COLS_INNER ]];then
11913                                                         print_data=$( create_print_line "$line_starter" "$battery_string" )
11914                                                         print_screen_output "$print_data"
11915                                                         line_starter=' '
11916                                                         battery_string=''
11917                                                         print_data=$( create_print_line "$line_starter" "$voltage" )
11918                                                         print_screen_output "$print_data"
11919                                                         voltage=''
11920                                                 else 
11921                                                         print_data=$( create_print_line "$line_starter" "$battery_string$voltage" )
11922                                                         print_screen_output "$print_data"
11923                                                         line_starter=' '
11924                                                         voltage=''
11925                                                         battery_string=''
11926                                                 fi
11927                                                 #echo two
11928                                                 if [[ $battery_data != '' ]];then
11929                                                         print_data=$( create_print_line "$line_starter" "$battery_data" )
11930                                                         print_screen_output "$print_data"
11931                                                 fi
11932                                         else
11933                                                 #echo three
11934                                                 print_data=$( create_print_line "$line_starter" "$battery_string$voltage$battery_data" )
11935                                                 print_screen_output "$print_data"
11936                                         fi
11937                                 fi
11938                                 line_starter=' '
11939                         fi
11940                 done
11941         elif [[ $B_SHOW_BATTERY_FORCED == 'true' ]];then
11942                 print_data=$( create_print_line "$line_starter" "No battery data found in /sys or dmidecode. Is one present?" )
11943                 print_screen_output "$print_data"
11944         fi
11945         eval $LOGFE
11946 }
11947
11948 print_cpu_data()
11949 {
11950         eval $LOGFS
11951         local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data='' a_cpu_speeds=''
11952         local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags='' flag_feature='flags'
11953         local a_cpu_working='' cpu_model='' cpu_clock='' cpu_null_error='' max_speed=''
11954         local cpc_plural='' cpu_count_print='' model_plural='' cpu_data_string=''
11955         local cpu_physical_count='' cpu_core_count='' cpu_core_alpha='' cpu_type=''
11956         local cpu_2_data='' working_cpu='' temp1='' per_cpu_cores='' current_max_clock_nu=''
11957         local line_starter="CPU:" multi_cpu_starter="${C1}clock speeds$SEP3${C2} "
11958         local speed_starter='speed'
11959
11960         ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\""
11961         # Array A_CPU_DATA always has one extra element: max clockfreq found.
11962         # that's why its count is one more than you'd think from cores/cpus alone
11963         # load A_CPU_DATA
11964         get_cpu_data
11965
11966         IFS=","
11967         a_cpu_working=(${A_CPU_DATA[0]})
11968         current_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
11969         a_cpu_speeds=(${A_CPU_DATA[$current_max_clock_nu]})
11970         IFS="$ORIGINAL_IFS"
11971
11972         # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1
11973         # as the parameter to output to the screen, then passing "<text1> ${ARR[@]} <text2>"
11974         # will output only <text1> and first element of ARR. That "@" splits in elements and "*" _doesn't_,
11975         # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note.
11976         # This has been confirmed by #bash on freenode.
11977         # The above mentioned only emerges when using the debugging markers below
11978         ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------"
11979         # unless all these are null, process whatever you have
11980         if [[ -n ${a_cpu_working[0]} || -n ${a_cpu_working[1]} || -n ${a_cpu_working[2]} || -n ${a_cpu_working[3]} ]];then
11981                 cpu_model="${a_cpu_working[0]}"
11982                 ## assemble data for output
11983                 cpu_clock="${a_cpu_working[1]}"
11984                 cpu_vendor=${a_cpu_working[5]}
11985                 # set A_CPU_CORE_DATA
11986                 get_cpu_core_count
11987                 cpu_physical_count=${A_CPU_CORE_DATA[0]}
11988                 cpu_core_count=${A_CPU_CORE_DATA[3]}
11989                 cpu_core_alpha=${A_CPU_CORE_DATA[1]}
11990                 cpu_type=${A_CPU_CORE_DATA[2]}
11991                 
11992                 if [[ $cpu_physical_count -gt 1 ]];then
11993                         cpc_plural='(s)'
11994                         cpu_count_print="$cpu_physical_count "
11995                         model_plural='s'
11996                 fi
11997                 line_starter="CPU$cpc_plural:"
11998                 if [[ -z $BSD_TYPE ]];then
11999                         cpu_data_string="$cpu_count_print$cpu_core_alpha core"
12000                         cpu_data="${C1}$cpu_data_string${C2} ${a_cpu_working[0]}$model_plural ($cpu_type)"
12001                 else
12002                         if [[ $cpu_physical_count -gt 1 ]];then
12003                                 per_cpu_cores=$(($cpu_core_count/$cpu_physical_count))
12004                                 cpu_data_string="${C1}Cores$SEP3${C2} $cpu_core_count ($cpu_physical_count $per_cpu_cores core cpus) "
12005                         else
12006                                 cpu_data_string="${C1}Cores$SEP3${C2} $cpu_core_count "
12007                         fi
12008                         if [[ -n $cpu_type ]];then
12009                                 cpu_type=" ($cpu_type)"
12010                         fi
12011                         cpu_data="$cpu_data_string${C1}model$SEP3${C2} ${a_cpu_working[0]}$cpu_type"
12012                 fi
12013                 if [[ $B_SHOW_CPU == 'true' ]];then
12014                         # update for multicore, bogomips x core count.
12015                         if [[ $B_EXTRA_DATA == 'true' ]];then
12016         #                       if [[ $cpu_vendor != 'intel' ]];then
12017                                 # ARM may use the faked 1 cpucorecount to make this work
12018                                 # echo $cpu_core_count $cpu_physical_count
12019                                 if [[ -n ${a_cpu_working[4]} ]];then
12020                                         # new arm shows bad bogomip value, so don't use it
12021                                         if [[ ${a_cpu_working[4]%.*} -gt 50 ]];then
12022                                                 bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" )
12023                                         fi
12024                                         bmip_data=${bmip_data%.*}
12025                                 fi
12026         #                       else
12027         #                               bmip_data="${a_cpu_working[4]}"
12028         #                       fi
12029                                 # bogomips are a linux thing, but my guess is over time bsds will use them somewhere anyway
12030                                 if [[ -n $BSD_TYPE && -z $bmip_data ]];then
12031                                         bmip_data=''
12032                                 else
12033                                         bmip_data="${C1}bmips$SEP3${C2} $bmip_data "
12034                                 fi
12035                         fi
12036                         ## note: this handles how intel reports L2, total instead of per core like AMD does
12037                         # note that we need to multiply by number of actual cpus here to get true cache size
12038                         if [[ -n ${a_cpu_working[2]} ]];then
12039                                 if [[ -z $BSD_TYPE ]];then
12040                                         if [[ $cpu_vendor != 'intel' ]];then
12041                                                 cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))"  )
12042                                         else
12043                                                 cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count"  )
12044                                         fi
12045                                 else
12046                                         cpu_cache=${a_cpu_working[2]}
12047                                 fi
12048                         else
12049                                 cpu_cache='N/A'
12050                         fi
12051                         # only print shortened list
12052                         if [[ $B_CPU_FLAGS_FULL != 'true' ]];then
12053                                 # gawk has already sorted this output, no flags returns -
12054                                 if [[ $B_EXTRA_DATA == 'true' ]];then
12055                                         cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" "${a_cpu_working[6]}" )
12056                                         cpu_flags="($cpu_flags)"
12057                                         if [[ ${a_cpu_working[6]} == 'true' ]];then
12058                                                 flag_feature='features'
12059                                         fi
12060                                         cpu_flags="${C1}$flag_feature$SEP3${C2} $cpu_flags "
12061                                 fi
12062                         fi
12063                         # arm cpus do not have flags or cache
12064                         if [[ ${a_cpu_working[6]} != 'true' ]];then
12065                                 cpu_data="$cpu_data${C2} ${C1}cache$SEP3${C2} $cpu_cache"
12066                                 cpu_2_data="$cpu_flags$bmip_data"
12067                         else
12068                                 cpu_data="$cpu_data${C2} (ARM)$bmip_data"
12069                         fi
12070                 fi
12071                 # we don't this printing out extra line unless > 1 cpu core
12072                 if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
12073                         cpu_clock_speed='' # null < verbosity level 5
12074                 else
12075                         if [[ -z ${a_cpu_working[1]} ]];then
12076                                 if [[ -z ${cpu_data/*ARM*/} ]];then
12077                                         temp1=' (ARM)'
12078                                 fi
12079                                 a_cpu_working[1]="N/A$temp1"
12080                         else
12081                                 a_cpu_working[1]="${a_cpu_working[1]%.*} MHz"
12082                         fi
12083                         # this handles bsd case unless we get a way to get max/min cpu speeds
12084                         if [[ ${a_cpu_speeds[0]} != 'N/A' && ${a_cpu_speeds[2]} != 0 ]];then
12085                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && ${#A_CPU_DATA[@]} -eq 2 && 
12086                                       $B_SHOW_CPU == 'true' && ${a_cpu_speeds[1]} != 0 ]];then
12087                                         a_cpu_working[1]="${a_cpu_speeds[0]}/${a_cpu_speeds[1]}/${a_cpu_speeds[2]} MHz"
12088                                         speed_starter='speed/min/max'
12089                                 else
12090                                         if [[ ${a_cpu_speeds[0]} == ${a_cpu_speeds[2]} ]];then
12091                                                 a_cpu_working[1]="${a_cpu_speeds[0]} MHz (max)"
12092                                         else
12093                                                 a_cpu_working[1]="${a_cpu_speeds[0]}/${a_cpu_speeds[2]} MHz"
12094                                                 speed_starter='speed/max'
12095                                         fi
12096                                 fi
12097                         fi
12098                         cpu_clock_speed="${C1}$speed_starter$SEP3${C2} ${a_cpu_working[1]}"
12099                 fi
12100                 cpu_2_data="$cpu_2_data$cpu_clock_speed"
12101         else
12102                 if [[ $BSD_TYPE == 'bsd' && $B_ROOT != 'true' ]];then
12103                         cpu_null_error=' No permissions for sysctl use?'
12104                 fi
12105                 cpu_data="${C2}No CPU data available.$cpu_null_error"
12106         fi
12107 #       echo $cpu_data $cpu_2_data
12108 #       echo ln: $( calculate_line_length "$cpu_data $cpu_2_data" )
12109 #       echo cpl: $( create_print_line "$line_starter" "$cpu_2_data" ):
12110 #       echo icols: $COLS_INNER
12111 #       echo tc: $TERM_COLUMNS
12112         # echo :${cpu_2_data}:
12113         if [[ -n $cpu_2_data && $( calculate_line_length "$cpu_data $cpu_2_data" ) -gt $COLS_INNER ]];then
12114                 cpu_data=$( create_print_line "$line_starter" "$cpu_data" )
12115                 line_starter=' '
12116                 print_screen_output "$cpu_data"
12117                 cpu_data=$( create_print_line " " "$cpu_2_data" )
12118                 print_screen_output "$cpu_data"
12119         else
12120                 cpu_data=$( create_print_line "$line_starter" "$cpu_data" )
12121                 print_screen_output "$cpu_data $cpu_2_data"
12122         fi
12123         # we don't do this printing out extra line unless > 1 cpu core
12124         # note the numbering, the last array item is the min/max/not found for cpu speeds
12125         if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
12126                 if [[ ${a_cpu_speeds[2]} != 0 ]];then
12127                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && ${a_cpu_speeds[1]} != 0 ]];then
12128                                 max_speed="${C1}min/max$SEP3${C2} ${a_cpu_speeds[1]}/${a_cpu_speeds[2]} MHz "
12129                         else
12130                                 max_speed="${C1}max$SEP3${C2} ${a_cpu_speeds[2]} MHz "
12131                         fi
12132                 fi
12133                 for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ ))
12134                 do
12135                         IFS=","
12136                         a_cpu_working=(${A_CPU_DATA[i]})
12137                         IFS="$ORIGINAL_IFS"
12138                         # note: the first iteration will create a first space, for color code separation below
12139                         # someone actually appeared with a 16 core system, so going to stop the cpu core throttle
12140                         # if this had some other purpose which we can't remember we'll add it back in
12141                         #if [[ $i -gt 10 ]];then
12142                         #       break
12143                         #fi
12144                         # echo $(calculate_line_length "$multi_cpu_starter$SEP3 $cpu_multi_clock_data" )
12145                         working_cpu="$max_speed${C1}$(( i + 1 ))$SEP3${C2} ${a_cpu_working[1]%.*} MHz "
12146                         max_speed=''
12147                         if [[ -n $cpu_multi_clock_data && \
12148                         $( calculate_line_length "$multi_cpu_starter$cpu_multi_clock_data$working_cpu" ) -gt $COLS_INNER ]];then
12149                                 cpu_multi_clock_data=$( create_print_line " " "$multi_cpu_starter$cpu_multi_clock_data" )
12150                                 print_screen_output "$cpu_multi_clock_data"
12151                                 multi_cpu_starter=''
12152                                 cpu_multi_clock_data="$working_cpu"
12153                         else
12154                                 cpu_multi_clock_data="$cpu_multi_clock_data$working_cpu"
12155                         fi
12156                 done
12157         fi
12158         # print the last line if it exists after loop
12159         if [[ -n $cpu_multi_clock_data ]];then
12160                 cpu_multi_clock_data=$( create_print_line " " "$multi_cpu_starter$cpu_multi_clock_data" )
12161                 print_screen_output "$cpu_multi_clock_data"
12162         fi
12163         if [[ $B_CPU_FLAGS_FULL == 'true' ]];then
12164                 print_cpu_flags_full "${a_cpu_working[3]}" "${a_cpu_working[6]}"
12165         fi
12166         eval $LOGFE
12167 }
12168
12169 # takes list of all flags, split them and prints x per line
12170 # args: $1 - cpu flag string; $2 - arm true/false
12171 print_cpu_flags_full()
12172 {
12173         eval $LOGFS
12174         # note: sort only sorts lines, not words in a string, so convert to lines
12175         local cpu_flags_full="$( echo $1 | tr " " "\n" | sort )" 
12176         local a_cpu_flags='' line_starter='' temp_string=''
12177         local i=0 counter=0 starter_length=0 flag='' flag_data=''
12178         local line_length='' flag_feature='Flags' spacer='' flag_string=''
12179         
12180         if [[ $2 == 'true' ]];then
12181                 flag_feature='Features'
12182         fi
12183         line_starter="CPU $flag_feature$SEP3"
12184         starter_length=$(( ${#line_starter} + 1 ))
12185         line_starter="${C1}$line_starter${C2} "
12186         line_length=$(( $COLS_INNER - $starter_length ))
12187         # build the flag line array
12188         for flag in $cpu_flags_full
12189         do
12190                 temp_string="$flag_string$spacer$flag"
12191                 spacer=' '
12192                 # handle inner line starter
12193                 if [[ $counter -gt 0 ]];then
12194                         line_length=$COLS_INNER
12195                 fi
12196                 if [[ $line_length -ge ${#temp_string} ]];then
12197                         flag_string=$temp_string
12198                 else
12199                         a_cpu_flags[$counter]=$flag_string
12200                         flag_string=$flag
12201                         (( counter++ ))
12202                 fi      
12203                 temp_string=''
12204         done
12205         if [[ -n $flag_string ]];then
12206                 a_cpu_flags[$counter]=$flag_string
12207         else
12208                 a_cpu_flags[$counter]='No CPU flag data found.'
12209         fi
12210         # then print it out
12211         for (( i=0; i < ${#a_cpu_flags[@]};i++ ))
12212         do
12213                 if [[ $i -gt 0 ]];then
12214                         line_starter=''
12215                 fi
12216                 flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" )
12217                 print_screen_output "$flag_data"
12218         done
12219         eval $LOGFE
12220 }
12221
12222 # args: $1 - type [sys/bat/default]; $2 - get_dmidecode_data error return
12223 print_dmidecode_error()
12224 {
12225         eval $LOGFS
12226         local error_message='Unknown dmidecode error.'
12227         local sysDmiError='Using '
12228         
12229         if [[ $1 == 'sys' || $1 == 'bat' ]];then
12230                 if [[ $B_FORCE_DMIDECODE == 'true' ]];then
12231                         sysDmiError='Forcing '
12232                 # dragonfly has /sys, but it's empty
12233                 elif [[ $1 == 'sys' ]] && [[ $BSD_TYPE == '' || -d /sys/devices ]];then
12234                         sysDmiError='No /sys/class/dmi; using '
12235                 #elif [[ $1 == 'bat' ]] && [[ $BSD_TYPE == '' || -d /sys/devices ]];then
12236                 #       sysDmiError='No /sys/ battery; using '
12237                 else
12238                         sysDmiError='Using '
12239                 fi
12240         fi
12241         if [[ $2 == 'dmidecode-error-requires-root' ]];then
12242                 error_message="${sysDmiError}dmidecode: you must be root to run dmidecode"
12243         elif [[ $2 == 'dmidecode-error-not-installed' ]];then
12244                 error_message="${sysDmiError}dmidecode: dmidecode is not installed."
12245         elif [[ $2 == 'dmidecode-error-no-smbios-dmi-data' ]];then
12246                 error_message="${sysDmiError}dmidecode: no smbios data available. Old system?"
12247         elif [[ $2 == 'dmidecode-error-no-battery-data' ]];then
12248                 error_message="${sysDmiError}dmidecode: no battery data available."
12249         elif [[ $2 == 'dmidecode-error-unknown-error' ]];then
12250                 error_message="${sysDmiError}dmidecode: unknown error occured"
12251         fi
12252         echo $error_message
12253         eval $LOGFE
12254 }
12255
12256 print_graphics_data()
12257 {
12258         eval $LOGFS
12259         local graphics_data='' card_id='' i='' root_alert='' root_x_string='' a_graphics_working=''
12260         local b_is_mesa='false' display_full_string='' card_bus_id='' card_data=''
12261         local res_tty='Resolution' xorg_data='' display_vendor_string='' chip_id=''
12262         local spacer='' driver='' driver_string='' driver_plural='' direct_render_string=''
12263         local separator_loaded='' separator_unloaded='' separator_failed='' 
12264         local loaded='' unloaded='' failed='' display_server_string=''
12265         local line_starter='Graphics:' part_1_data='' part_2_data=''
12266         local screen_resolution="$( get_graphics_res_data )"
12267         
12268         # set A_DISPLAY_SERVER_DATA
12269         get_graphics_display_server_data
12270         local display_vendor=${A_DISPLAY_SERVER_DATA[0]}
12271         local display_version=${A_DISPLAY_SERVER_DATA[1]}
12272         # set A_GLX_DATA
12273         get_graphics_glx_data
12274         local glx_renderer="${A_GLX_DATA[0]}"
12275         local glx_version="${A_GLX_DATA[1]}"
12276         # this can contain a long No case debugging message, so it's being sliced off
12277         # note: using grep -ioE '(No|Yes)' <<< ${A_GLX_DATA[2]} did not work in Arch, no idea why
12278         local glx_direct_render=$( gawk '{print $1}' <<< "${A_GLX_DATA[2]}" )
12279         
12280         # set A_GRAPHICS_CARD_DATA
12281         if [[ $BSD_TYPE == 'bsd' ]];then
12282                 if [[ $B_PCICONF == 'true' ]];then
12283                         if [[ $B_PCICONF_SET == 'false' ]];then
12284                                 get_pciconf_data
12285                         fi
12286                         get_pciconf_card_data 'display'
12287                 elif [[ $B_LSPCI == 'true' ]];then
12288                         get_graphics_card_data
12289                 fi
12290         else
12291                 get_graphics_card_data
12292         fi
12293         # set A_GRAPHIC_DRIVERS
12294         get_graphics_driver
12295         
12296         if [[ ${#A_GRAPHIC_DRIVERS[@]} -eq 0 ]];then
12297                 driver=' N/A'
12298         else
12299                 for (( i=0; i < ${#A_GRAPHIC_DRIVERS[@]}; i++ ))
12300                 do
12301                         IFS=","
12302                         a_graphics_working=( ${A_GRAPHIC_DRIVERS[i]} )
12303                         IFS="$ORIGINAL_IFS"
12304                         case ${a_graphics_working[1]} in
12305                                 loaded)
12306                                         loaded="$loaded$separator_loaded${a_graphics_working[0]}"
12307                                         separator_loaded=','
12308                                         ;;
12309                                 unloaded)
12310                                         unloaded="$unloaded$separator_unloaded${a_graphics_working[0]}"
12311                                         separator_unloaded=','
12312                                         ;;
12313                                 failed)
12314                                         failed="$failed$separator_failed${a_graphics_working[0]}"
12315                                         separator_failed=','
12316                                         ;;              
12317                         esac
12318                 done
12319         fi
12320         if [[ -n $loaded ]];then
12321                 driver="$driver $loaded"
12322         fi
12323         if [[ -n $unloaded ]];then
12324                 driver="$driver (unloaded: $unloaded)"
12325         fi
12326         if [[ -n $failed ]];then
12327                 driver="$driver ${RED}FAILED$SEP3${C2} $failed"
12328         fi
12329         # sometimes for some reason there is no driver found but the array is started
12330         if [[ -z $driver ]];then
12331                 driver=' N/A'
12332         fi
12333         if [[ ${#A_GRAPHIC_DRIVERS[@]} -gt 1 ]];then
12334                 driver_plural='s'
12335         fi
12336         # some basic error handling:
12337         if [[ -z $screen_resolution ]];then
12338                 screen_resolution='N/A'
12339         fi
12340         # note: fix this, we may find a display server that has no version
12341         if [[ -z $display_vendor || -z $display_version ]];then
12342                 display_vendor_string="N/A"
12343         else
12344                 display_vendor_string="$display_vendor $display_version"
12345         fi
12346         display_server_string="${C1}Display Server${SEP3}${C2} $display_vendor_string "
12347         driver_string="${C1}driver$driver_plural$SEP3${C2}$driver "
12348
12349         if [[ $B_ROOT == 'true' ]];then
12350                 root_x_string='for root '
12351                 if [[ $B_IRC == 'false' || $B_CONSOLE_IRC == 'true' ]];then
12352                         res_tty='tty size'
12353                 fi
12354         fi
12355         if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
12356                 root_x_string="${root_x_string}out of X"
12357                 res_tty='tty size'
12358         fi
12359         
12360         if [[ -n $root_x_string ]];then
12361                 root_x_string="${C1}Advanced Data$SEP3${C2} N/A $root_x_string"
12362         fi
12363         # note, this comes out with a count of 1 sometimes for null data
12364         if [[ ${A_GRAPHICS_CARD_DATA[0]} != '' ]];then
12365                 for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
12366                 do
12367                         IFS=","
12368                         a_graphics_working=( ${A_GRAPHICS_CARD_DATA[i]} )
12369                         IFS="$ORIGINAL_IFS"
12370                         card_bus_id=''
12371                         card_data=${a_graphics_working[0]}
12372                         if [[ $B_EXTRA_DATA == 'true' ]];then
12373                                 if [[ -n ${a_graphics_working[1]} ]];then
12374                                         card_bus_id="${a_graphics_working[1]}"
12375                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
12376                                                 if [[ $BSD_TYPE != 'bsd' ]];then
12377                                                         chip_id=$( get_lspci_chip_id "${a_graphics_working[1]}" )
12378                                                 else
12379                                                         chip_id=${a_graphics_working[2]}
12380                                                 fi
12381                                         fi
12382                                 else
12383                                         card_bus_id='N/A'
12384                                 fi
12385                         fi
12386                         if [[ -n $card_bus_id ]];then
12387                                 card_bus_id="${C1}bus-ID$SEP3${C2} $card_bus_id "
12388                         fi
12389                         if [[ -n $chip_id ]];then
12390                                 chip_id="${C1}chip-ID$SEP3${C2} $chip_id"
12391                         fi
12392                         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 1 ]];then
12393                                 card_id="-$(($i+1))"
12394                         fi
12395                         
12396                         part_1_data="${C1}Card$card_id$SEP3${C2} $card_data "
12397                         part_2_data="$card_bus_id$chip_id"
12398                         
12399                         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 1 ]];then
12400                                 if [[ $( calculate_line_length "$part_1_data$part_2_data" ) -gt $COLS_INNER ]];then
12401                                         graphics_data=$( create_print_line "$line_starter" "$part_1_data" )
12402                                         print_screen_output "$graphics_data"
12403                                         part_1_data=''
12404                                         line_starter=' '
12405                                 fi
12406                                 if [[ -n $( grep -vE '^[[:space:]]*$' <<< $part_1_data$part_2_data ) ]];then
12407                                         graphics_data=$( create_print_line "$line_starter" "$part_1_data$part_2_data" )
12408                                         print_screen_output "$graphics_data"
12409                                 fi
12410                                 part_1_data=''
12411                                 part_2_data=''
12412                                 line_starter=' '
12413                                 graphics_data=''
12414                         fi
12415                 done
12416         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
12417         else
12418                 part_1_data="${C1}Card$SEP3${C2} Failed to Detect Video Card! "
12419         fi
12420         # Print cards if not dual card system
12421         if [[ -n $part_1_data$part_2_data ]];then 
12422                 if [[ $( calculate_line_length "$part_1_data$part_2_data" ) -gt $COLS_INNER ]];then
12423                         graphics_data=$( create_print_line "$line_starter" "$part_1_data" )
12424                         print_screen_output "$graphics_data"
12425                         part_1_data=''
12426                         line_starter=' '
12427                 fi
12428                 if [[ -n $( grep -vE '^[[:space:]]*$' <<< $part_1_data$part_2_data ) ]];then
12429                         graphics_data=$( create_print_line "$line_starter" "$part_1_data$part_2_data" )
12430                         print_screen_output "$graphics_data"
12431                 fi
12432         fi
12433         line_starter=' '
12434         graphics_data=''
12435         
12436         part_1_data="$display_server_string$driver_string"
12437         part_2_data="${C1}$res_tty$SEP3${C2} $screen_resolution $root_x_string"
12438         if [[ -n $( grep -vE '^[[:space:]]*$' <<< $part_1_data$part_2_data ) && \
12439               $( calculate_line_length "$part_1_data $part_2_data" ) -gt $COLS_INNER ]];then
12440                 graphics_data=$( create_print_line "$line_starter" "$part_1_data" )
12441                 print_screen_output "$graphics_data"
12442                 line_starter=' '
12443                 part_1_data=''
12444                 graphics_data=$part_2_data
12445         fi
12446         if [[ -n $( grep -vE '^[[:space:]]*$' <<< $part_1_data$part_2_data ) ]];then
12447                 graphics_data=$( create_print_line "$line_starter" "$part_1_data$part_2_data" )
12448                 print_screen_output "$graphics_data"
12449                 line_starter=' '
12450         fi
12451         # if [[ -z $glx_renderer || -z $glx_version ]];then
12452         #       b_is_mesa='true'
12453         # fi
12454
12455         ## note: if glx render or display_version have no content, then mesa is true
12456         # if [[ $B_SHOW_DISPLAY_DATA == 'true' ]] && [[ $b_is_mesa != 'true' ]];then
12457         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
12458                 if [[ -z $glx_renderer ]];then
12459                         glx_renderer='N/A'
12460                 fi
12461                 if [[ -z $glx_version ]];then
12462                         glx_version='N/A'
12463                 fi
12464                 if [[ -z $glx_direct_render ]];then
12465                         glx_direct_render='N/A'
12466                 fi
12467                 if [[ $B_HANDLE_CORRUPT_DATA == 'true' || $B_EXTRA_DATA == 'true' ]];then
12468                         direct_render_string=" ${C1}Direct Rendering$SEP3${C2} $glx_direct_render"
12469                 fi
12470                 part_1_data="${C1}GLX Renderer$SEP3${C2} $glx_renderer "
12471                 part_2_data="${C1}GLX Version$SEP3${C2} $glx_version$direct_render_string"
12472                 # echo $line_starter
12473                 if [[ $( calculate_line_length "$part_1_data$part_2_data" ) -gt $COLS_INNER ]];then
12474                         graphics_data=$( create_print_line "$line_starter" "$part_1_data" )
12475                         print_screen_output "$graphics_data"
12476                         part_1_data=''
12477                         line_starter=' '
12478                 fi
12479                 if [[ -n $part_1_data$part_2_data ]];then
12480                         graphics_data=$( create_print_line "$line_starter" "$part_1_data$part_2_data" )
12481                         print_screen_output "$graphics_data"
12482                 fi
12483         fi
12484         eval $LOGFE
12485 }
12486
12487 print_hard_disk_data()
12488 {
12489         eval $LOGFS
12490         local hdd_data='' hdd_data_2='' a_hdd_working='' hdd_temp_data='' hdd_string=''
12491         local hdd_serial='' dev_string='/dev/'
12492         local dev_data='' size_data='' hdd_model='' usb_data='' hdd_name=''
12493         local Line_Starter='Drives:' # inherited by print_optical_drives
12494         # load A_HDD_DATA - this will also populate the full bsd disk data array values
12495         get_hdd_data_basic
12496         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
12497         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
12498         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
12499         IFS=","
12500         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
12501         IFS="$ORIGINAL_IFS"
12502         local hdd_capacity="${a_hdd_basic_working[0]}"
12503         local hdd_used=${a_hdd_basic_working[1]}
12504         local bsd_error="No HDD Info. $FILE_DMESG_BOOT not readable?"
12505         local hdd_name_temp='' part_1_data='' part_2_data=''
12506         local row_starter="${C1}HDD Total Size$SEP3${C2} $hdd_capacity ($hdd_used) "
12507         # in bsd, /dev/wd0c is disk id
12508         if [[ -n $BSD_TYPE ]];then
12509                 dev_string=''
12510         fi
12511
12512         if [[ $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
12513                 ## note: the output part of this should be in the print hdd data function, not here
12514                 get_hard_drive_data_advanced
12515                 
12516                 # temporary message to indicate not yet supported
12517                 if [[ $BSD_TYPE == 'bsd' && -z $Dmesg_Boot_Data ]];then
12518                         hdd_data=$bsd_error
12519                         hdd_data=$( create_print_line "$Line_Starter" "$hdd_data" )
12520                         print_screen_output "$hdd_data"
12521                         Line_Starter=' '
12522                 else
12523                         for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
12524                         do
12525                                 # this adds the (x) numbering in front of each disk found, and creates the full disk string
12526                                 IFS=","
12527                                 a_hdd_working=( ${A_HDD_DATA[i]} )
12528                                 IFS="$ORIGINAL_IFS"
12529                                 if [[ $B_SHOW_DISK == 'true' ]];then
12530                                         if [[ -n ${a_hdd_working[3]} ]];then
12531                                                 usb_data="${a_hdd_working[3]} "
12532                                         else
12533                                                 usb_data=''
12534                                         fi
12535                                         size_data=" ${C1}size$SEP3${C2} ${a_hdd_working[1]}"
12536                                         if [[ $B_EXTRA_DATA == 'true' ]];then
12537                                                 hdd_temp_data=${a_hdd_working[5]}
12538                                                 # error handling is done in get data function
12539                                                 if [[ -n $hdd_temp_data ]];then
12540                                                         hdd_temp_data=" ${C1}temp$SEP3${C2} ${hdd_temp_data}C"
12541                                                 else
12542                                                         hdd_temp_data=''
12543                                                 fi
12544                                         fi
12545                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
12546                                                 hdd_serial=${a_hdd_working[4]}
12547                                                 if [[ -z $hdd_serial ]];then
12548                                                         hdd_serial='N/A'
12549                                                 fi
12550                                                 hdd_serial=" ${C1}serial$SEP3${C2} $hdd_serial"
12551                                         fi
12552                                         dev_data="$dev_string${a_hdd_working[0]} "
12553                                 fi
12554                                 if [[ -n ${a_hdd_working[2]} ]];then
12555                                         hdd_name_temp=${a_hdd_working[2]}
12556                                 else
12557                                         hdd_name_temp='N/A'
12558                                 fi
12559                                 # echo "loop: $i"
12560                                 hdd_name="${C1}model$SEP3${C2} $hdd_name_temp"
12561                                 hdd_string="${C1}ID-$((i+1))$SEP3${C2} $usb_data$dev_data$hdd_name$size_data$hdd_serial$hdd_temp_data"
12562                                 part_1_data="$hdd_model$hdd_string "
12563                                 
12564                                 if [[ $i -eq 0 ]];then
12565                                         if [[ $( calculate_line_length "$row_starter$part_1_data" ) -gt $COLS_INNER ]];then
12566                                                 hdd_data=$( create_print_line "$Line_Starter" "$row_starter" )
12567                                                 print_screen_output "$hdd_data"
12568                                                 #echo 0
12569                                                 Line_Starter=' '
12570                                                 row_starter=''
12571                                                 hdd_data=$( create_print_line "$Line_Starter" "$part_1_data" )
12572                                                 print_screen_output "$hdd_data"
12573                                                 part_1_data=''
12574                                                 #echo 1
12575                                         else
12576                                                 hdd_data=$( create_print_line "$Line_Starter" "$row_starter$part_1_data" )
12577                                                 print_screen_output "$hdd_data"
12578                                                 Line_Starter=' '
12579                                                 row_starter=''
12580                                                 part_1_data=''
12581                                                 #echo 2
12582                                         fi
12583                                 fi
12584                                 if [[ $( calculate_line_length "$row_starter$part_2_data$part_1_data" ) -gt $COLS_INNER ]];then
12585                                         if [[ -n $( grep -vE '^[[:space:]]*$' <<< $part_2_data ) ]];then
12586                                                 hdd_data=$( create_print_line "$Line_Starter" "$row_starter$part_2_data" )
12587                                                 print_screen_output "$hdd_data"
12588                                                 #echo 3
12589                                                 Line_Starter=' '
12590                                                 row_starter=''
12591                                                 part_2_data=''
12592                                         fi
12593                                         hdd_data=$( create_print_line "$Line_Starter" "$row_starter$part_1_data" )
12594                                         print_screen_output "$hdd_data"
12595                                         part_1_data=''
12596                                         #echo 4
12597                                 elif [[ -n $part_2_data && \
12598                                                 $( calculate_line_length "$row_starter$part_2_data$part_1_data" ) -le $COLS_INNER ]];then
12599                                         hdd_data=$( create_print_line "$Line_Starter" "$row_starter$part_2_data$part_1_data" )
12600                                         print_screen_output "$hdd_data"
12601                                         #echo 3
12602                                         Line_Starter=' '
12603                                         row_starter=''
12604                                         part_1_data=''
12605                                         part_2_data=''
12606                                 else
12607                                         part_2_data=$part_1_data
12608                                 fi
12609                         done
12610                         # then print any leftover items
12611                         if [[ -n $part_2_data ]];then
12612                                 hdd_data=$( create_print_line "$Line_Starter" "$part_2_data" )
12613                                 print_screen_output "$hdd_data"
12614                                 #echo 5
12615                         fi
12616                 fi
12617         else
12618                 hdd_data="$row_starter"
12619                 hdd_data=$( create_print_line "$Line_Starter" "$hdd_data" )
12620                 print_screen_output "$hdd_data"
12621                 Line_Starter=' '
12622         fi
12623         if [[ $B_SHOW_FULL_OPTICAL == 'true' || $B_SHOW_BASIC_OPTICAL == 'true' ]];then
12624                 print_optical_drive_data
12625         fi
12626
12627         eval $LOGFE
12628 }
12629
12630 print_info_data()
12631 {
12632         eval $LOGFS
12633
12634         local info_data='' line_starter='Info:' runlvl_default='' runlvl='' runlvl_title='runlevel' 
12635         local init_data='' init_type='' init_version='' rc_type='' rc_version=''
12636         local client_data='' shell_data='' shell_parent='' tty_session=''
12637         local memory="$( get_memory_data )"
12638         local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
12639         local up_time="$( get_uptime )"
12640         if [[ -z $up_time ]];then
12641                 up_time='N/A - missing uptime?'
12642         fi
12643         local patch_version_number=$( get_patch_version_string )
12644         local gcc_installed='' gcc_others='' closing_data='' 
12645         
12646         if [[ -z $memory ]];then
12647                 memory='N/A'
12648         fi
12649         
12650         if [[ $B_EXTRA_DATA == 'true' ]];then
12651                 get_gcc_system_version
12652                 if [[ ${#A_GCC_VERSIONS[@]} -gt 0 ]];then
12653                         if [[ -n ${A_GCC_VERSIONS[0]} ]];then
12654                                 gcc_installed=${A_GCC_VERSIONS[0]}
12655                         else
12656                                 gcc_installed='N/A'
12657                         fi
12658                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_GCC_VERSIONS[1]} ]];then
12659                                 # gcc_others=" ${C1}alt$SEP3${C2} $( tr ',' '/' <<< ${A_GCC_VERSIONS[1]} )"
12660                                 gcc_others=" ${C1}alt$SEP3${C2} ${A_GCC_VERSIONS[1]//,//}"
12661                         fi
12662                         gcc_installed="${C1}Gcc sys$SEP3${C2} $gcc_installed$gcc_others "
12663                 fi
12664         fi
12665         if [[  $B_IRC == 'false' ]];then
12666                 shell_data=$( get_shell_data )
12667                 if [[ -n $shell_data ]];then
12668                         # note, if you start this in tty, it will give 'login' as the parent, which we don't want.
12669                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
12670                                 if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
12671                                         shell_parent=$( get_tty_number )
12672                                         shell_parent="tty $shell_parent"
12673                                 else
12674                                         shell_parent=$( get_shell_parent )
12675                                 fi
12676                                 if [[ $shell_parent == 'login' ]];then
12677                                         shell_parent=''
12678                                 elif [[ -n $shell_parent ]];then
12679                                         shell_parent=" running in ${shell_parent##*/}"
12680                                 fi
12681                         fi
12682                         IRC_CLIENT="$IRC_CLIENT ($shell_data$shell_parent)"
12683                 fi
12684         fi
12685
12686         # Some code could look superfluous but BitchX doesn't like lines not ending in a newline. F*&k that bitch!
12687         # long_last=$( echo -ne "${C1}Processes$SEP3${C2} $processes${CN} | ${C1}Uptime$SEP3${C2} $up_time${CN} | ${C1}Memory$SEP3${C2} $MEM${CN}" )
12688         info_data="${C1}Processes$SEP3${C2} $processes ${C1}Uptime$SEP3${C2} $up_time ${C1}Memory$SEP3${C2} $memory "
12689
12690         # this only triggers if no X data is present or if extra data switch is on
12691         if [[ $B_SHOW_DISPLAY_DATA != 'true' || $B_EXTRA_DATA == 'true' ]];then
12692                 get_init_data
12693                 if [[ ${A_INIT_DATA[0]} == 'systemd' && -z $( grep -E '^[0-9]$' <<< ${A_INIT_DATA[4]} ) ]];then
12694                         runlvl_title='target'
12695                 fi
12696                 init_type=${A_INIT_DATA[0]}
12697                 if [[ -z $init_type ]];then
12698                         init_type='N/A'
12699                 fi
12700                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
12701                         init_version=${A_INIT_DATA[1]}
12702                         if [[ -z $init_version ]];then
12703                                 init_version='N/A'
12704                         fi
12705                         init_version=" ${C1}v$SEP3${C2} $init_version"
12706                         rc_version=${A_INIT_DATA[3]}
12707                         if [[ -n $rc_version ]];then
12708                                 rc_version="${C1}v$SEP3${C2} $rc_version "
12709                         fi
12710                         runlvl_default=${A_INIT_DATA[5]}
12711                 fi
12712                 # currently only using openrc here, otherwise show nothing
12713                 rc_type=${A_INIT_DATA[2]}
12714                 if [[ -n $rc_type ]];then
12715                         rc_type="${C1}rc$SEP3${C2} $rc_type $rc_version"
12716                 fi
12717                 init_type="${C1}Init$SEP3${C2} $init_type$init_version "
12718                 runlvl=${A_INIT_DATA[4]}
12719                 if [[ -n $runlvl ]];then
12720                         runlvl="${C1}$runlvl_title$SEP3${C2} $runlvl "
12721                 fi
12722                 if [[ -n $runlvl_default ]];then
12723                         runlvl_default="${C1}default$SEP3${C2} $runlvl_default "
12724                 fi
12725                 init_data="$init_type$rc_type$runlvl$runlvl_default"
12726         fi
12727         if [[ $SHOW_IRC -gt 0 ]];then
12728                 client_data="${C1}Client$SEP3${C2} $IRC_CLIENT$IRC_CLIENT_VERSION "
12729         fi
12730         # info_data="$info_data"
12731         closing_data="$client_data${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$patch_version_number"
12732         # sometimes gcc is very long, and default runlevel can be long with systemd, so create a gcc-less line first
12733         if [[ $( calculate_line_length "$info_data$init_data$gcc_installed" ) -gt $COLS_INNER ]];then
12734                 # info_data=$info_data
12735                 info_data=$( create_print_line "$line_starter" "$info_data" )
12736                 print_screen_output "$info_data"
12737                 info_data=''
12738                 # closing_data=''
12739                 line_starter=' '
12740                 #echo 1
12741         fi
12742         if [[ $( calculate_line_length "$init_data$gcc_installed" ) -gt $COLS_INNER ]];then
12743                 info_data=$init_data
12744                 info_data=$( create_print_line "$line_starter" "$info_data" )
12745                 print_screen_output "$info_data"
12746                 info_data=''
12747                 init_data=''
12748                 line_starter=' '
12749                 #echo 2
12750         fi
12751         if [[ $( calculate_line_length "$info_data$init_data$gcc_installed$closing_data" ) -gt $COLS_INNER ]];then
12752                 info_data=$info_data$init_data$gcc_installed
12753                 info_data=$( create_print_line "$line_starter" "$info_data" )
12754                 print_screen_output "$info_data"
12755                 info_data=''
12756                 gcc_installed=''
12757                 init_data=''
12758                 line_starter=' '
12759                 #echo 3
12760         fi
12761         info_data="$info_data$init_data$gcc_installed$closing_data"
12762         
12763         info_data=$( create_print_line "$line_starter" "$info_data" )
12764         if [[ $SCHEME -gt 0 ]];then
12765                 info_data="$info_data ${NORMAL}"
12766         fi
12767         print_screen_output "$info_data"
12768         
12769         eval $LOGFE
12770 }
12771 #print_info_data;exit 
12772 print_machine_data()
12773 {
12774         eval $LOGFS
12775         
12776         local system_line='' mobo_line='' bios_line='' chassis_line=''
12777         local mobo_vendor='' mobo_model='' mobo_version='' mobo_serial=''
12778         local bios_vendor='' bios_version='' bios_date='' bios_rom='' error_string=''
12779         local system_vendor='' product_name='' product_version='' product_serial='' product_uuid=''
12780         local chassis_vendor='' chassis_type='' chassis_version='' chassis_serial='' 
12781         local b_skip_system='false' b_skip_chassis='false'
12782         local sysDmiNull='No /sys/class/dmi machine data: try newer kernel, or install dmidecode'
12783         # set A_MACHINE_DATA
12784         get_machine_data
12785         
12786         IFS=','
12787         ## keys for machine data are:
12788         # 0-sys_vendor 1-product_name 2-product_version 3-product_serial 4-product_uuid 
12789         # 5-board_vendor 6-board_name 7-board_version 8-board_serial 
12790         # 9-bios_vendor 10-bios_version 11-bios_date 
12791         ## with extra data: 
12792         # 12-chassis_vendor 13-chassis_type 14-chassis_version 15-chassis_serial
12793         # a null array always has a count of 1
12794         if [[ ${#A_MACHINE_DATA[@]} -gt 1 ]];then
12795                 # note: in some case a mobo/version will match a product name/version, do not print those
12796                 # but for laptops, or even falsely id'ed desktops with batteries, let's print it all if it matches
12797                 # there can be false id laptops if battery appears so need to make sure system is filled
12798                 if [[ -z ${A_MACHINE_DATA[0]} ]];then
12799                         b_skip_system='true'
12800                 else
12801                         if [[ $B_PORTABLE != 'true'  ]];then
12802                                 # ibm / ibm can be true; dell / quantum is false, so in other words, only do this
12803                                 # in case where the vendor is the same and the version is the same and not null, 
12804                                 # otherwise the version information is going to be different in all cases I think
12805                                 if [[ -n ${A_MACHINE_DATA[0]} && ${A_MACHINE_DATA[0]} == ${A_MACHINE_DATA[5]} ]];then
12806                                         if [[ -n ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[2]} == ${A_MACHINE_DATA[7]} ]] || \
12807                                         [[ -z ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[1]} == ${A_MACHINE_DATA[6]} ]];then
12808                                                 b_skip_system='true'
12809                                         fi
12810                                 fi
12811                         fi
12812                 fi
12813                 # no point in showing chassis if system isn't there, it's very unlikely that would be correct
12814                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && $b_skip_system != 'true' ]];then
12815                         if [[ -n ${A_MACHINE_DATA[7]} && ${A_MACHINE_DATA[14]} == ${A_MACHINE_DATA[7]} ]];then
12816                                 b_skip_chassis='true'
12817                         fi
12818                         if [[ -n ${A_MACHINE_DATA[12]} && $b_skip_chassis != 'true' ]];then
12819                                 # no need to print the vendor string again if it's the same
12820                                 if [[ ${A_MACHINE_DATA[12]} != ${A_MACHINE_DATA[0]} ]];then
12821                                         chassis_vendor=" ${A_MACHINE_DATA[12]}"
12822                                 fi
12823                                 if [[ -n ${A_MACHINE_DATA[13]} ]];then
12824                                         chassis_type=" ${C1}type$SEP3${C2} ${A_MACHINE_DATA[13]}"
12825                                 fi
12826                                 if [[ -n ${A_MACHINE_DATA[14]} ]];then
12827                                         chassis_version=" ${C1}v$SEP3${C2} ${A_MACHINE_DATA[14]}"
12828                                 fi
12829                                 if [[ -n ${A_MACHINE_DATA[15]} && $B_OUTPUT_FILTER != 'true' ]];then
12830                                         chassis_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[15]}"
12831                                 fi
12832                                 if [[ -n "$chassis_vendor$chassis_type$chassis_version$chassis_serial" ]];then
12833                                         chassis_line="${C1}Chassis$SEP3${C2}$chassis_vendor$chassis_type$chassis_version$chassis_serial"
12834                                 fi
12835                         fi
12836                 fi
12837                 if [[ -n ${A_MACHINE_DATA[5]} ]];then
12838                         mobo_vendor=${A_MACHINE_DATA[5]}
12839                 else
12840                         mobo_vendor='N/A'
12841                 fi
12842                 if [[ -n ${A_MACHINE_DATA[6]} ]];then
12843                         mobo_model=${A_MACHINE_DATA[6]}
12844                 else
12845                         mobo_model='N/A'
12846                 fi
12847                 if [[ -n ${A_MACHINE_DATA[7]} ]];then
12848                         mobo_version=" ${C1}v$SEP3${C2} ${A_MACHINE_DATA[7]}"
12849                 fi
12850                 if [[ -n ${A_MACHINE_DATA[8]} && $B_OUTPUT_FILTER != 'true' ]];then
12851                         mobo_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[8]}"
12852                 fi
12853                 if [[ -n ${A_MACHINE_DATA[9]} ]];then
12854                         bios_vendor=${A_MACHINE_DATA[9]}
12855                 else
12856                         bios_vendor='N/A'
12857                 fi
12858                 if [[ -n ${A_MACHINE_DATA[10]} ]];then
12859                         bios_version=${A_MACHINE_DATA[10]}
12860                         if [[ -n ${A_MACHINE_DATA[16]} ]];then
12861                                 bios_version="$bios_version rv ${A_MACHINE_DATA[16]}"
12862                         fi
12863                 else
12864                         bios_version='N/A'
12865                 fi
12866                 if [[ -n ${A_MACHINE_DATA[11]} ]];then
12867                         bios_date=${A_MACHINE_DATA[11]}
12868                 else
12869                         bios_date='N/A'
12870                 fi
12871                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_MACHINE_DATA[17]} ]];then
12872                         bios_rom=" ${C1}rom size$SEP3${C2} ${A_MACHINE_DATA[17]}"
12873                 fi
12874                 mobo_line="${C1}Mobo$SEP3${C2} $mobo_vendor ${C1}model$SEP3${C2} $mobo_model$mobo_version$mobo_serial"
12875                 bios_line="${C1}Bios$SEP3${C2} $bios_vendor ${C1}v$SEP3${C2} $bios_version ${C1}date$SEP3${C2} $bios_date$bios_rom"
12876                 if [[ $( calculate_line_length "$mobo_line$bios_line" ) -lt $COLS_INNER ]];then
12877                         mobo_line="$mobo_line $bios_line"
12878                         bios_line=''
12879                 fi
12880                 if [[ $b_skip_system == 'true' ]];then
12881                         system_line=$mobo_line
12882                         mobo_line=''
12883                 else
12884                         # this has already been tested for above so we know it's not null
12885                         system_vendor=${A_MACHINE_DATA[0]}
12886                         if [[ $B_PORTABLE == 'true' ]];then
12887                                 system_vendor="$system_vendor (portable)"
12888                         fi
12889                         if [[ -n ${A_MACHINE_DATA[1]} ]];then
12890                                 product_name=${A_MACHINE_DATA[1]}
12891                         else
12892                                 product_name='N/A'
12893                         fi
12894                         if [[ -n ${A_MACHINE_DATA[2]} ]];then
12895                                 product_version=" ${C1}v$SEP3${C2} ${A_MACHINE_DATA[2]}"
12896                         fi
12897                         if [[ -n ${A_MACHINE_DATA[3]} && $B_OUTPUT_FILTER != 'true' ]];then
12898                                 product_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[3]} "
12899                         fi
12900                         system_line="${C1}System$SEP3${C2} $system_vendor ${C1}product$SEP3${C2} $product_name$product_version$product_serial"
12901                         if [[ -n $chassis_line && $( calculate_line_length "$system_line$chassis_line" ) -lt $COLS_INNER ]];then
12902                                 system_line="$system_line $chassis_line"
12903                                 chassis_line=''
12904                         fi
12905                 fi
12906         else
12907                 system_line="${C2}$sysDmiNull"
12908         fi
12909         IFS="$ORIGINAL_IFS"
12910         # patch to dump all of above if dmidecode was data source and a dmidecode error is present
12911         if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-error-'* ]];then
12912                 error_string=$( print_dmidecode_error 'sys' "${A_MACHINE_DATA[0]}" )
12913                 system_line=${C2}$error_string
12914                 mobo_line=''
12915                 bios_line=''
12916                 chassis_line=''
12917         fi
12918         system_line=$( create_print_line "Machine:" "$system_line" )
12919         print_screen_output "$system_line"
12920         if [[ -n $mobo_line ]];then
12921                 mobo_line=$( create_print_line " " "$mobo_line" )
12922                 print_screen_output "$mobo_line"
12923         fi
12924         if [[ -n $bios_line ]];then
12925                 bios_line=$( create_print_line " " "$bios_line" )
12926                 print_screen_output "$bios_line"
12927         fi
12928         if [[ -n $chassis_line ]];then
12929                 chassis_line=$( create_print_line " " "$chassis_line" )
12930                 print_screen_output "$chassis_line"
12931         fi
12932         
12933         eval $LOGFE
12934 }
12935
12936 # args: $1 - module name (could be > 1, so loop it ); $2 - audio (optional)
12937 print_module_version()
12938 {
12939         eval $LOGFS
12940         local module_versions='' module='' version='' prefix='' modules=$1
12941         
12942         # note that sound driver data tends to have upper case, but modules are lower
12943         if [[ $2 == 'audio' ]];then
12944                 if [[ -z $( grep -E '^snd' <<< $modules ) ]];then
12945                         prefix='snd_' # sound modules start with snd_
12946                 fi
12947                 modules=$( tr '[A-Z]' '[a-z]' <<< "$modules" )
12948                 modules=${modules//-/_}
12949                 # special intel processing, generally no version info though
12950                 if [[ $modules == 'hda intel' ]];then
12951                         modules='hda_intel'
12952                 elif [[ $modules == 'intel ich' ]];then
12953                         modules='intel8x0'
12954                 fi
12955         fi
12956
12957         for module in $modules
12958         do
12959                 version=$( get_module_version_number "$prefix$module" )
12960                 if [[ -n $version ]];then
12961                         module_versions="$module_versions $version"
12962                 fi
12963         done
12964
12965         if [[ -n $module_versions ]];then
12966                 echo " ${C1}v$SEP3${C2}$module_versions"
12967         fi
12968         eval $LOGFE
12969 }
12970
12971 print_networking_data()
12972 {
12973         eval $LOGFS
12974         local i='' card_id='' network_data='' a_network_working='' port_data='' driver_data=''
12975         local card_string='' port_plural='' module_version='' pci_bus_id='' bus_usb_text=''
12976         local bus_usb_id='' line_starter='Network:' card_string='' card_data='' chip_id=''
12977         local driver='' part_2_data=''
12978         
12979         # set A_NETWORK_DATA
12980         if [[ $BSD_TYPE == 'bsd' ]];then
12981                 if [[ $B_PCICONF == 'true' ]];then
12982                         if [[ $B_PCICONF_SET == 'false' ]];then
12983                                 get_pciconf_data
12984                         fi
12985                         get_pciconf_card_data 'network'
12986                 elif [[ $B_LSPCI == 'true' ]];then
12987                         get_networking_data
12988                 fi
12989         else
12990                 get_networking_data
12991         fi
12992
12993         # will never be null because null is handled in get_network_data, but in case we change
12994         # that leaving this test in place.
12995         if [[ -n ${A_NETWORK_DATA[@]} ]];then
12996                 for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
12997                 do
12998                         IFS=","
12999                         a_network_working=( ${A_NETWORK_DATA[i]} )
13000                         IFS="$ORIGINAL_IFS"
13001                         bus_usb_id=''
13002                         bus_usb_text=''
13003                         card_data=''
13004                         card_string=''
13005                         driver_data=''
13006                         module_version=''
13007                         network_data=''
13008                         pci_bus_id=''
13009                         port_data=''
13010                         port_plural=''
13011                         chip_id=''
13012                         part_2_data=''
13013
13014                         if [[ ${#A_NETWORK_DATA[@]} -gt 1 ]];then
13015                                 card_id="-$(( $i + 1 ))"
13016                         fi
13017                         if [[ -n ${a_network_working[1]} && $B_EXTRA_DATA == 'true' && $BSD_TYPE != 'bsd' ]];then
13018                                 module_version=$( print_module_version "${a_network_working[1]}" )
13019                         fi
13020                         if [[ -n ${a_network_working[1]} ]];then
13021                                 # note: linux drivers can have numbers, like tg3
13022                                 if [[ $BSD_TYPE == 'bsd' ]];then
13023                                         driver=$( sed 's/[0-9]*$//' <<< ${a_network_working[1]} )
13024                                 else
13025                                         driver=${a_network_working[1]}
13026                                 fi
13027                                 driver_data="${C1}driver$SEP3${C2} $driver$module_version "
13028                         fi
13029                         if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then
13030                                 if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then
13031                                         port_plural='s'
13032                                 fi
13033                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_network_working[2]} "
13034                         fi
13035                         if [[ -n ${a_network_working[4]} && $B_EXTRA_DATA == 'true' ]];then
13036                                 if [[ -z $( grep '^usb-' <<< ${a_network_working[4]} ) ]];then
13037                                         bus_usb_text='bus-ID'
13038                                         bus_usb_id=${a_network_working[4]}
13039                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
13040                                                 if [[ $BSD_TYPE != 'bsd' ]];then
13041                                                         chip_id=$( get_lspci_chip_id "${a_network_working[4]}" )
13042                                                 else
13043                                                         chip_id=${a_network_working[10]}
13044                                                 fi
13045                                         fi
13046                                 else
13047                                         bus_usb_text='usb-ID'
13048                                         bus_usb_id=$( cut -d '-' -f '2-4' <<< ${a_network_working[4]} )
13049                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
13050                                                 chip_id=${a_network_working[10]}
13051                                         fi
13052                                 fi
13053                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id"
13054                                 if [[ -n $chip_id ]];then
13055                                         chip_id=" ${C1}chip-ID$SEP3${C2} $chip_id"
13056                                 fi
13057                         fi
13058                         card_string="${C1}Card$card_id$SEP3${C2} ${a_network_working[0]} "
13059                         card_data="$driver_data$port_data"
13060                         part_2_data="$pci_bus_id$chip_id"
13061                         if [[ $( calculate_line_length "$card_string$card_data$part_2_data" ) -gt $COLS_INNER ]];then
13062                                 network_data=$( create_print_line "$line_starter" "$card_string" )
13063                                 line_starter=' '
13064                                 card_string=''
13065                                 print_screen_output "$network_data"
13066                         fi
13067                         if [[ $( calculate_line_length "$card_string$card_data$part_2_data" ) -gt $COLS_INNER ]];then
13068                                 network_data=$( create_print_line "$line_starter" "$card_string$card_data" )
13069                                 print_screen_output "$network_data"
13070                                 line_starter=' '
13071                                 card_data=''
13072                                 card_string=''
13073                                 
13074                         fi
13075                         if [[ -n $card_string$card_data$part_2_data ]];then
13076                                 network_data=$( create_print_line "$line_starter" "$card_string$card_data$part_2_data" )
13077                                 print_screen_output "$network_data"
13078                                 line_starter=' '
13079                                 card_data=''
13080                                 card_string=''
13081                                 part_2_data=''
13082                         fi
13083                         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' ]];then
13084                                 print_network_advanced_data
13085                         fi
13086                 done
13087         else
13088                 network_data="${C1}Card$SEP3${C2} Failed to Detect Network Card! "
13089                 network_data=$( create_print_line "$line_starter" "$network_data" )
13090                 print_screen_output "$network_data"
13091         fi
13092         if [[ $B_SHOW_IP == 'true' ]];then
13093                 print_networking_ip_data
13094         fi
13095         eval $LOGFE
13096 }
13097
13098 print_network_advanced_data()
13099 {
13100         eval $LOGFS
13101         local network_data='' if_id='N/A' duplex='N/A' mac_id='N/A' speed='N/A' oper_state='N/A'
13102         local b_is_wifi='false' speed_string='' duplex_string='' part_2_data=''
13103         
13104                 # first check if it's a known wifi id'ed card, if so, no print of duplex/speed
13105         if [[ -n $( grep -Esi '(wireless|wifi|wi-fi|wlan|802\.11|centrino)' <<< ${a_network_working[0]} ) ]];then
13106                 b_is_wifi='true'
13107         fi
13108         if [[ -n ${a_network_working[5]} ]];then
13109                 if_id=${a_network_working[5]}
13110         fi
13111         if [[ -n ${a_network_working[6]} ]];then
13112                 oper_state=${a_network_working[6]}
13113         fi
13114         # no print out for wifi since it doesn't have duplex/speed data availabe
13115         # note that some cards show 'unknown' for state, so only testing explicitly
13116         # for 'down' string in that to skip showing speed/duplex
13117         if [[ $b_is_wifi != 'true' && $oper_state != 'down' ]];then
13118                 if [[ -n ${a_network_working[7]} ]];then
13119                         # make sure the value is strictly numeric before appending Mbps
13120                         if [[ -n $( grep -E '^[0-9\.,]+$' <<< "${a_network_working[7]}" ) ]];then
13121                                 speed="${a_network_working[7]} Mbps"
13122                         else
13123                                 speed=${a_network_working[7]}
13124                         fi
13125                 fi
13126                 speed_string="${C1}speed$SEP3${C2} $speed "
13127                 if [[ -n ${a_network_working[8]} ]];then
13128                         duplex=${a_network_working[8]}
13129                 fi
13130                 duplex_string="${C1}duplex$SEP3${C2} $duplex "
13131         fi
13132         if [[ -n ${a_network_working[9]} ]];then
13133                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
13134                         mac_id=$FILTER_STRING
13135                 else
13136                         mac_id=${a_network_working[9]}
13137                 fi
13138         fi
13139         network_data="${C1}IF$SEP3${C2} $if_id ${C1}state$SEP3${C2} $oper_state $speed_string$duplex_string"
13140         part_2_data="${C1}mac$SEP3${C2} $mac_id"
13141         if [[ $( calculate_line_length "$network_data$part_2_data" ) -gt $COLS_INNER ]];then
13142                 network_data=$( create_print_line " " "$network_data" )
13143                 print_screen_output "$network_data"
13144                 network_data=''
13145         fi
13146         if [[ -n $network_data$part_2_data ]];then
13147                 network_data=$( create_print_line " " "$network_data$part_2_data" )
13148                 print_screen_output "$network_data"
13149                 network_data=''
13150         fi
13151         
13152         eval $LOGFE
13153 }
13154
13155 print_networking_ip_data()
13156 {
13157         eval $LOGFS
13158         local ip=$( get_networking_wan_ip_data )
13159         local wan_ip_data='' a_interfaces_working='' interfaces='' i=0
13160         local if_id='' if_ip='' if_ipv6='' if_ipv6_string='' full_string='' if_string=''
13161         local if_id_string='' if_ip_string='' if_string_holding=''
13162
13163         # set A_INTERFACES_DATA
13164         get_networking_local_ip_data
13165         # first print output for wan ip line. Null is handled in the get function
13166         if [[ -z $ip ]];then
13167                 ip='N/A'
13168         else
13169                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
13170                         ip=$FILTER_STRING
13171                 fi
13172         fi
13173         wan_ip_data="${C1}WAN IP$SEP3${C2} $ip "
13174         # then create the list of local interface/ip
13175         i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1
13176         while [[ -n ${A_INTERFACES_DATA[i]} ]]
13177         do
13178                 IFS=","
13179                 a_interfaces_working=(${A_INTERFACES_DATA[i]})
13180                 IFS="$ORIGINAL_IFS"
13181                 if_id='N/A'
13182                 if_ip='N/A'
13183                 if_ipv6='N/A'
13184                 if_ipv6_string=''
13185                 if [[ -z $( grep '^Interface' <<< ${a_interfaces_working[0]} ) ]];then
13186                         if [[ -n ${a_interfaces_working[1]} ]];then
13187                                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
13188                                         if_ip=$FILTER_STRING
13189                                 else
13190                                         if_ip=${a_interfaces_working[1]}
13191                                 fi
13192                         fi
13193                         if_ip_string=" ${C1}ip-v4$SEP3${C2} $if_ip"
13194                         if [[ $B_EXTRA_DATA == 'true' ]];then
13195                                 if [[ -n ${a_interfaces_working[3]} ]];then
13196                                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
13197                                                 if_ipv6=$FILTER_STRING
13198                                         else
13199                                                 if_ipv6=${a_interfaces_working[3]}
13200                                         fi
13201                                 fi
13202                                 if_ipv6_string=" ${C1}ip-v6$SEP3${C2} $if_ipv6"
13203                         fi
13204                 fi
13205                 if [[ -n ${a_interfaces_working[0]} ]];then
13206                         if_id=${a_interfaces_working[0]}
13207                 fi
13208                 if_string="${C1}IF$SEP3${C2} $if_id$if_ip_string$if_ipv6_string "
13209                 # first line, print wan on its own line if too long
13210                 if [[ $i -eq 0 ]];then
13211                         if [[ $( calculate_line_length "$wan_ip_data$if_string" ) -gt $COLS_INNER ]];then
13212                                 full_string=$( create_print_line " " "$wan_ip_data" )
13213                                 print_screen_output "$full_string"
13214                                 wan_ip_data=''
13215                                 full_string=$( create_print_line " " "$if_string" )
13216                                 print_screen_output "$full_string"
13217                                 if_string=''
13218                         else
13219                                 full_string=$( create_print_line " " "$wan_ip_data$if_string" )
13220                                 print_screen_output "$full_string"
13221                                 wan_ip_data=''
13222                                 if_string=''
13223                         fi
13224                 else 
13225                         if [[ $( calculate_line_length "$if_string_holding$if_string" ) -gt $COLS_INNER ]];then
13226                                 if [[ -n $if_string_holding ]];then
13227                                         full_string=$( create_print_line " " "$if_string_holding" )
13228                                         print_screen_output "$full_string"
13229                                 fi
13230                                 if_string_holding="$if_string"
13231                         else
13232                                 if_string_holding="$if_string_holding$if_string"
13233                         fi
13234                 fi
13235                 ((i++))
13236         done
13237         
13238         # then print out anything not printed already
13239         if [[ -n $if_string_holding ]];then
13240                 full_string=$( create_print_line " " "$if_string_holding" )
13241                 print_screen_output "$full_string"
13242         fi
13243         eval $LOGFE
13244 }
13245
13246 print_optical_drive_data()
13247 {
13248         eval $LOGFS
13249         local a_drives='' drive_data='' counter='' dev_string='/dev/' speed_string='x'
13250         local drive_id='' drive_links='' vendor='' speed='' multisession='' mcn='' audio=''
13251         local dvd='' state='' rw_support='' rev='' separator='' drive_string='' part_2_data=''
13252         if [[ -z $BSD_TYPE ]];then
13253                 get_optical_drive_data
13254         else
13255                 get_optical_drive_data_bsd
13256                 dev_string=''
13257                 speed_string=''
13258         fi
13259         # 0 - true dev path, ie, sr0, hdc
13260         # 1 - dev links to true path
13261         # 2 - device vendor - for hdx drives, vendor model are one string from proc
13262         # 3 - device model
13263         # 4 - device rev version
13264         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 0 ]];then
13265                 for (( i=0; i < ${#A_OPTICAL_DRIVE_DATA[@]}; i++ ))
13266                 do
13267                         IFS=","
13268                         a_drives=(${A_OPTICAL_DRIVE_DATA[i]})
13269                         IFS="$ORIGINAL_IFS"
13270                         audio=''
13271                         drive_data=''
13272                         drive_id=''
13273                         drive_links=''
13274                         dvd='' 
13275                         mcn='' 
13276                         multisession='' 
13277                         rev='' 
13278                         rw_support='' 
13279                         separator=''
13280                         speed='' 
13281                         state='' 
13282                         vendor=''
13283                         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -eq 1 && -z ${a_drives[0]} && -z ${a_drives[1]} ]];then
13284                                 drive_string="No optical drives detected."
13285                                 B_SHOW_FULL_OPTICAL='false'
13286                         else
13287                                 if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 1 ]];then
13288                                         counter="-$(( i + 1 ))"
13289                                 fi
13290                                 if [[ -z ${a_drives[0]} ]];then
13291                                         drive_id='N/A'
13292                                 else
13293                                         drive_id="$dev_string${a_drives[0]}"
13294                                 fi
13295                                 drive_links=$( sed 's/~/,/g' <<< ${a_drives[1]} )
13296                                 if [[ -z $drive_links ]];then
13297                                         drive_links='N/A'
13298                                 fi
13299                                 if [[ -n ${a_drives[2]} ]];then
13300                                         vendor=${a_drives[2]}
13301                                         if [[ -n ${a_drives[3]} ]];then
13302                                                 vendor="$vendor ${a_drives[3]}"
13303                                         fi
13304                                 fi
13305                                 if [[ -z $vendor ]];then
13306                                         if [[ -n ${a_drives[3]} ]];then
13307                                                 vendor=${a_drives[3]}
13308                                         else
13309                                                 vendor='N/A'
13310                                         fi
13311                                 fi
13312                                 if [[ $B_EXTRA_DATA == 'true' ]];then
13313                                         if [[ -n ${a_drives[4]} ]];then
13314                                                 rev=${a_drives[4]}
13315                                         else
13316                                                 rev='N/A'
13317                                         fi
13318                                         rev="${C1}rev$SEP3${C2} $rev "
13319                                 fi
13320                                 drive_string="$drive_id ${C1}model$SEP3${C2} $vendor "
13321                                 part_2_data="$rev${C1}dev-links$SEP3${C2} $drive_links"
13322                         fi
13323                         drive_data="${C1}Optical${counter}$SEP3${C2} $drive_string"
13324                         if [[ $( calculate_line_length "$drive_data$part_2_data" ) -lt $COLS_INNER ]];then
13325                                 drive_data=$( create_print_line "$Line_Starter" "$drive_data$part_2_data" )
13326                                 print_screen_output "$drive_data"
13327                                 Line_Starter=' '
13328                                 drive_data=''
13329                                 part_2_data=''
13330                         else
13331                                 if [[ $( calculate_line_length "$drive_data" ) -gt $COLS_INNER ]];then
13332                                         drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
13333                                         print_screen_output "$drive_data"
13334                                         Line_Starter=' '
13335                                         drive_data=''
13336                                 fi
13337                                 if [[ $( calculate_line_length "$drive_data$part_2_data" ) -lt $COLS_INNER ]];then
13338                                         drive_data=$( create_print_line "$Line_Starter" "$drive_data$part_2_data" )
13339                                         print_screen_output "$drive_data"
13340                                         Line_Starter=' '
13341                                         part_2_data=''
13342                                         drive_data=''
13343                                 else
13344                                         drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
13345                                         print_screen_output "$drive_data"
13346                                         drive_data=''
13347                                         Line_Starter=' '
13348                                         drive_data=$( create_print_line "$Line_Starter" "$part_2_data" )
13349                                         print_screen_output "$drive_data"
13350                                         Line_Starter=' '
13351                                         part_2_data=''
13352                                 fi
13353                         fi
13354                         
13355                         # 5 - speed
13356                         # 6 - multisession support
13357                         # 7 - MCN support
13358                         # 8 - audio read
13359                         # 9 - cdr
13360                         # 10 - cdrw
13361                         # 11 - dvd read
13362                         # 12 - dvdr
13363                         # 13 - dvdram
13364                         # 14 - state
13365                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
13366                                 if [[ -z ${a_drives[5]} ]];then
13367                                         speed='N/A'
13368                                 else
13369                                         speed="${a_drives[5]}$speed_string"
13370                                 fi
13371                                 if [[ -z ${a_drives[8]} ]];then
13372                                         audio='N/A'
13373                                 elif [[ ${a_drives[8]} == 1 ]];then
13374                                         audio='yes'
13375                                 else
13376                                         audio='no'
13377                                 fi
13378                                 audio="${C1}audio$SEP3${C2} $audio "
13379                                 if [[ -z ${a_drives[6]} ]];then
13380                                         multisession='N/A'
13381                                 elif [[ ${a_drives[6]} == 1 ]];then
13382                                         multisession='yes'
13383                                 else
13384                                         multisession='no'
13385                                 fi
13386                                 multisession="${C1}multisession$SEP3${C2} $multisession "
13387                                 if [[ -z ${a_drives[11]} ]];then
13388                                         dvd='N/A'
13389                                 elif [[ ${a_drives[11]} == 1 ]];then
13390                                         dvd='yes'
13391                                 else
13392                                         dvd='no'
13393                                 fi
13394                                 if [[ $B_EXTRA_DATA == 'true' ]];then
13395                                         if [[ -z ${a_drives[14]} ]];then
13396                                                 state='N/A'
13397                                         else
13398                                                 state="${a_drives[14]}"
13399                                         fi
13400                                         state="${C1}state$SEP3${C2} $state "
13401                                 fi
13402                                 if [[ -n ${a_drives[9]} && ${a_drives[9]} == 1 ]];then
13403                                         rw_support='cd-r'
13404                                         separator=','
13405                                 fi
13406                                 if [[ -n ${a_drives[10]} && ${a_drives[10]} == 1 ]];then
13407                                         rw_support="$rw_support${separator}cd-rw"
13408                                         separator=','
13409                                 fi
13410                                 if [[ -n ${a_drives[12]} && ${a_drives[12]} == 1 ]];then
13411                                         rw_support="$rw_support${separator}dvd-r"
13412                                         separator=','
13413                                 fi
13414                                 if [[ -n ${a_drives[13]} && ${a_drives[13]} == 1 ]];then
13415                                         rw_support="$rw_support${separator}dvd-ram"
13416                                         separator=','
13417                                 fi
13418                                 if [[ -z $rw_support ]];then
13419                                         rw_support='none'
13420                                 fi
13421                                 drive_data="${C1}Features: speed$SEP3${C2} $speed $multisession"
13422                                 part_2_data="$audio${C1}dvd$SEP3${C2} $dvd ${C1}rw$SEP3${C2} $rw_support $state"
13423                                 if [[ $( calculate_line_length "$drive_data$part_2_data" ) -lt $COLS_INNER ]];then
13424                                         drive_data=$( create_print_line "$Line_Starter" "$drive_data$part_2_data" )
13425                                         print_screen_output "$drive_data"
13426                                         Line_Starter=' '
13427                                 else
13428                                         drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
13429                                         print_screen_output "$drive_data"
13430                                         drive_data=$( create_print_line "$Line_Starter" "$part_2_data" )
13431                                         print_screen_output "$drive_data"
13432                                         Line_Starter=' '
13433                                 fi
13434                         fi
13435                 done
13436         else
13437                 :
13438         fi
13439         eval $LOGFE
13440 }
13441
13442 print_partition_data()
13443 {
13444         eval $LOGFS
13445         local a_partition_working='' partition_used='' partition_data=''
13446         local counter=0 i=0 part_id=0 a_partition_data='' line_starter='' 
13447         local partitionIdClean='' part_dev='' full_dev='' part_label='' full_label=''
13448         local part_uuid='' full_uuid='' dev_remote='' full_fs='' 
13449         local b_non_dev='false' holder=''
13450
13451         # set A_PARTITION_DATA
13452         get_partition_data
13453
13454         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
13455         do
13456                 IFS=","
13457                 a_partition_working=(${A_PARTITION_DATA[i]})
13458                 IFS="$ORIGINAL_IFS"
13459                 full_label=''
13460                 full_uuid=''
13461
13462                 if [[ $B_SHOW_PARTITIONS_FULL == 'true' ]] || [[ ${a_partition_working[4]} == 'main' ]];then
13463                         if [[ -n ${a_partition_working[2]} ]];then
13464                                 partition_used="${C1}used$SEP3${C2} ${a_partition_working[2]} (${a_partition_working[3]}) "
13465                         else
13466                                 partition_used='' # reset partition used to null
13467                         fi
13468                         if [[ -n ${a_partition_working[5]} ]];then
13469                                 full_fs="${a_partition_working[5]}"
13470                         else
13471                                 full_fs='N/A' # reset partition fs type
13472                         fi
13473                         full_fs="${C1}fs$SEP3${C2} $full_fs "
13474                         if [[ -n ${a_partition_working[6]} ]];then
13475                                 if [[ -z $( grep -E '(^//|:/|non-dev)' <<< ${a_partition_working[6]} ) ]];then
13476                                         part_dev="/dev/${a_partition_working[6]}"
13477                                         dev_remote='dev'
13478                                 elif [[ -n $( grep '^non-dev' <<< ${a_partition_working[6]} ) ]];then
13479                                         holder=$( sed 's/non-dev-//' <<< ${a_partition_working[6]} )
13480                                         part_dev="$holder"
13481                                         dev_remote='raid'
13482                                 else
13483                                         part_dev="${a_partition_working[6]}"
13484                                         dev_remote='remote'
13485                                 fi
13486                         else
13487                                 dev_remote='dev'
13488                                 part_dev='N/A'
13489                         fi
13490                         full_dev="${C1}$dev_remote$SEP3${C2} $part_dev "
13491                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
13492                                 if [[ $B_SHOW_LABELS == 'true' && $dev_remote != 'remote' ]];then
13493                                         if [[ -n ${a_partition_working[7]} ]];then
13494                                                 part_label="${a_partition_working[7]}"
13495                                         else
13496                                                 part_label='N/A'
13497                                         fi
13498                                         full_label="${C1}label$SEP3${C2} $part_label "
13499                                 fi
13500                                 if [[ $B_SHOW_UUIDS == 'true' && $dev_remote != 'remote' ]];then
13501                                         if [[ -n ${a_partition_working[8]} ]];then
13502                                                 part_uuid="${a_partition_working[8]}"
13503                                         else
13504                                                 part_uuid='N/A'
13505                                         fi
13506                                         full_uuid="${C1}uuid$SEP3${C2} $part_uuid"
13507                                 fi
13508                         fi
13509                         # don't show user names in output
13510                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
13511                                 partitionIdClean=$( sed $SED_RX "s|/home/([^/]+)/(.*)|/home/$FILTER_STRING/\2|" <<< ${a_partition_working[0]} )
13512                         else
13513                                 partitionIdClean=${a_partition_working[0]}
13514                         fi
13515                         id_size_fs="${C1}ID-$((part_id+1))$SEP3${C2} $partitionIdClean ${C1}size$SEP3${C2} ${a_partition_working[1]} $partition_used$full_fs$full_dev"
13516                         label_uuid="$full_label$full_uuid"
13517                         # label/uuid always print one per line, so only wrap if it's very long
13518                         if [[ $B_SHOW_UUIDS == 'true' || $B_SHOW_LABELS == 'true' ]] && \
13519                            [[ $( calculate_line_length "${a_partition_data[$counter]}$id_size_fs$label_uuid" ) -gt $COLS_INNER ]];then
13520                                 a_partition_data[$counter]="$id_size_fs"
13521                                 ((counter++))
13522                                 a_partition_data[$counter]="$label_uuid"
13523                         else
13524                                 if [[ $( calculate_line_length "${a_partition_data[$counter]}$id_size_fs$label_uuid" ) -gt $COLS_INNER ]];then
13525                                         a_partition_data[$counter]="${a_partition_data[$counter]}"
13526                                         ((counter++))
13527                                         a_partition_data[$counter]="$id_size_fs$label_uuid"
13528                                 else
13529                                         a_partition_data[$counter]="${a_partition_data[$counter]}$id_size_fs$label_uuid"
13530                                 fi
13531                         fi
13532                         ((counter++))
13533                         ((part_id++))
13534                 fi
13535         done
13536         # print out all lines, line starter on first line
13537         for (( i=0; i < ${#a_partition_data[@]};i++ ))
13538         do
13539                 if [[ $i -eq 0 ]];then
13540                         line_starter='Partition:'
13541                 else
13542                         line_starter=' '
13543                 fi
13544                 if [[ -n ${a_partition_data[$i]} ]];then
13545                         partition_data=$( create_print_line "$line_starter" "${a_partition_data[$i]}" )
13546                         print_screen_output "$partition_data"
13547                 fi
13548         done
13549         
13550         eval $LOGFE
13551 }
13552 # legacy not used
13553 print_program_version()
13554 {
13555         local patch_version_number=$( get_patch_version_string )
13556         local program_version="${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$patch_version_number${CN}"
13557         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
13558         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
13559         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
13560         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
13561         #local line_max=$COLS_INNER
13562         #program_version="$( sed -e :a -e "s/^.\{1,$line_max\}$/ &/;ta" <<< $program_version )" # use to create padding if needed
13563         # program_version=$( create_print_line "Version:" "$program_version${CN}" )
13564         print_screen_output "$program_version"
13565 }
13566
13567 print_ps_data()
13568 {
13569         eval $LOGFS
13570         
13571         local b_print_first='true' 
13572
13573         if [[ $B_SHOW_PS_CPU_DATA == 'true' ]];then
13574                 get_ps_tcm_data 'cpu'
13575                 print_ps_item 'cpu' "$b_print_first"
13576                 b_print_first='false' 
13577         fi
13578         if [[ $B_SHOW_PS_MEM_DATA == 'true' ]];then
13579                 get_ps_tcm_data 'mem'
13580                 print_ps_item 'mem' "$b_print_first"
13581         fi
13582         
13583         eval $LOGFE
13584 }
13585
13586 # args: $1 - cpu/mem; $2 true/false
13587 print_ps_item()
13588 {
13589         eval $LOGFS
13590         local a_ps_data='' ps_data='' line_starter='' line_start_data='' full_line=''
13591         local app_name='' app_pid='' app_cpu='' app_mem='' throttled='' app_daemon=''
13592         local b_print_first=$2 line_counter=0 i=0 count_nu='' extra_data='' memory='' extra_text=''
13593         
13594         if [[ -n $PS_THROTTLED ]];then
13595                 throttled=" ${C1} - throttled from${C2} $PS_THROTTLED"
13596         fi
13597         # important: ${C2} $PS_COUNT must have space after ${C2} for irc output or the number vanishes
13598         case $1 in
13599                 cpu)
13600                         if [[  $B_EXTRA_DATA == 'true' ]];then
13601                                 extra_text=" ${C1}- Memory$SEP3 MB / % used"
13602                                 if [[ $B_SHOW_INFO == 'false' && $B_SHOW_PS_MEM_DATA == 'false' ]];then
13603                                         memory=" - ${C1}Used/Total$SEP3${C2} $( get_memory_data )"
13604                                 fi
13605                         fi
13606                         line_start_data="${C1}CPU$SEP3 % used$extra_text$memory${C1} - top${C2} $PS_COUNT ${C1}active$throttled"
13607                         ;;
13608                 mem)
13609                         if [[  $B_EXTRA_DATA == 'true' ]];then
13610                                 extra_text=" ${C1}- CPU$SEP3 % used"
13611                         fi
13612                         if [[ $B_SHOW_INFO == 'false' ]];then
13613                                 memory=" - ${C1}Used/Total$SEP3${C2} $( get_memory_data )"
13614                         fi
13615                         line_start_data="${C1}Memory$SEP3 MB / % used$memory$extra_text${C1} - top${C2} $PS_COUNT ${C1}active$throttled"
13616                         ;;
13617         esac
13618         
13619         if [[ $b_print_first == 'true' ]];then
13620                 line_starter='Processes:'
13621         else
13622                 line_starter=' '
13623         fi
13624         
13625         # appName, appPath, appStarterName, appStarterPath, cpu, mem, pid, vsz, user
13626         ps_data=$( create_print_line "$line_starter" "$line_start_data" )
13627         print_screen_output "$ps_data"
13628
13629         for (( i=0; i < ${#A_PS_DATA[@]}; i++ ))
13630         do
13631                 IFS=","
13632                 a_ps_data=(${A_PS_DATA[i]})
13633                 IFS="$ORIGINAL_IFS"
13634                 
13635                 # handle the converted app names, with ~..~ means it didn't have a path
13636                 if [[ -n $( grep -E '^~.*~$' <<<  ${a_ps_data[0]} ) ]];then
13637                         app_daemon='daemon'
13638                 else
13639                         app_daemon='command'
13640                 fi
13641
13642                 app_name=" ${C1}$app_daemon$SEP3${C2} ${a_ps_data[0]}"
13643                 if [[ ${a_ps_data[0]} != ${a_ps_data[2]} ]];then
13644                         app_name="$app_name ${C1}(started by$SEP3${C2} ${a_ps_data[2]}${C1})${C2}"
13645                 fi
13646                 app_pid=" ${C1}pid$SEP3${C2} ${a_ps_data[6]}"
13647                 #  ${C1}user$SEP3${C2} ${a_ps_data[8]}
13648                 case $1 in
13649                         cpu)
13650                                 app_cpu=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
13651                                 if [[ $B_EXTRA_DATA == 'true' ]];then
13652                                         extra_data=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
13653                                 fi
13654                                 ;;
13655                         mem)
13656                                 app_mem=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
13657                                 if [[ $B_EXTRA_DATA == 'true' ]];then
13658                                         extra_data=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
13659                                 fi
13660                                 ;;
13661                 esac
13662                 (( line_counter++ ))
13663                 count_nu="${C1}$line_counter$SEP3${C2}"
13664                 full_line="$count_nu$app_cpu$app_mem$app_name$app_pid$extra_data"
13665                 ps_data=$( create_print_line " " "$full_line" )
13666                 print_screen_output "$ps_data"
13667         done
13668         
13669         eval $LOGFE
13670 }
13671
13672 print_raid_data()
13673 {
13674         eval $LOGFS
13675         local device='' device_string='' device_state='' raid_level='' device_components=''
13676         local device_report='' u_data='' blocks='' super_blocks='' algorithm='' chunk_size=''
13677         local bitmap_values='' recovery_progress_bar='' recovery_percent='' recovered_sectors=''
13678         local finish_time='' recovery_speed='' raid_counter=0 device_counter=1 basic_counter=1
13679         local a_raid_working='' raid_data='' kernel_support='' read_ahead='' unused_devices=''
13680         local basic_raid='' basic_raid_separator='' basic_raid_plural='' inactive=''
13681         local component_separator='' device_id='' print_string='' loop_limit=0 array_count_unused=''
13682         local array_count='' raid_event='' b_print_lines='true'
13683         local no_raid_detected='' dev_string='/dev/'
13684         local empty_raid_data='' report_size='report' blocks_avail='blocks' chunk_raid_usage='chunk size'
13685         
13686         if [[ -n $BSD_TYPE ]];then
13687                 no_raid_detected='No zfs software RAID detected-other types not yet supported.'
13688                 empty_raid_data='No zfs RAID data available-other types not yet supported.'
13689                 report_size='size'
13690                 blocks_avail='available'
13691                 chunk_raid_usage='allocated'
13692         else
13693                 no_raid_detected="No RAID data: $FILE_MDSTAT missing-is md_mod kernel module loaded?"
13694                 empty_raid_data="No RAID devices: $FILE_MDSTAT, md_mod kernel module present"
13695         fi
13696         
13697         if [[ $BSD_TYPE == 'bsd' ]];then
13698                 dev_string=''
13699         fi
13700         if [[ $B_RAID_SET != 'true' ]];then
13701                 get_raid_data
13702         fi
13703
13704         for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
13705         do
13706                 IFS=","
13707                 a_raid_working=(${A_RAID_DATA[i]})
13708                 IFS="$ORIGINAL_IFS"
13709                 
13710                 # reset on each iteration
13711                 algorithm=''
13712                 bitmap_values=''
13713                 blocks=''
13714                 component_separator=''
13715                 device=''
13716                 device_components=''
13717                 device_id=''
13718                 device_report=''
13719                 device_state=''
13720                 failed=''
13721                 finish_time=''
13722                 inactive=''
13723                 raid_event=''
13724                 raid_level=''
13725                 recovery_percent=''
13726                 recovery_progress_bar=''
13727                 recovered_sectors=''
13728                 recovery_speed=''
13729                 spare=''
13730                 super_blocks=''
13731                 u_data=''
13732                 
13733                 if [[ -n $( grep '^md' <<< ${a_raid_working[0]} ) && -z $BSD_TYPE ]] || \
13734                 [[ -n $BSD_TYPE && ${a_raid_working[0]} != '' ]];then
13735                         if [[ $B_SHOW_BASIC_RAID == 'true' ]];then
13736                                 if [[ $basic_raid != '' ]];then
13737                                         basic_raid_plural='s'
13738                                 fi
13739                                 if [[ ${a_raid_working[1]} == 'inactive' ]];then
13740                                         inactive=" - ${a_raid_working[1]}"
13741                                 fi
13742                                 basic_raid="$basic_raid$basic_raid_separator${C1}$basic_counter$SEP3${C2} $dev_string${a_raid_working[0]}$inactive"
13743                                 basic_raid_separator=' '
13744                                 (( basic_counter++ ))
13745                         else
13746                                 device_id="-$device_counter"
13747                                 device="$dev_string${a_raid_working[0]}"
13748                                 
13749                                 (( device_counter++ ))
13750                                 if [[ ${a_raid_working[1]} != '' ]];then
13751                                         device_state=" - ${a_raid_working[1]}"
13752                                 fi
13753                                 
13754                                 if [[ ${a_raid_working[2]} == '' ]];then
13755                                         raid_level='N/A'
13756                                 else
13757                                         raid_level=${a_raid_working[2]}
13758                                 fi
13759                                 # there's one case: md0 : inactive  that has to be protected against
13760                                 if [[ ${a_raid_working[2]} == '' && ${a_raid_working[1]} == 'inactive' ]];then
13761                                         raid_level=''
13762                                 else
13763                                         raid_level=" ${C1}raid$SEP3${C2} $raid_level"
13764                                 fi
13765                                 if [[ ${a_raid_working[4]} != '' ]];then
13766                                         device_report="${a_raid_working[4]}"
13767                                 else
13768                                         device_report="N/A"
13769                                 fi
13770                                 if [[ $B_EXTRA_DATA == 'true' ]];then
13771                                         if [[ ${a_raid_working[6]} != '' ]];then
13772                                                 blocks=${a_raid_working[6]}
13773                                         else
13774                                                 blocks='N/A'
13775                                         fi
13776                                         blocks=" ${C1}$blocks_avail$SEP3${C2} $blocks"
13777                                         
13778                                         if [[ ${a_raid_working[9]} != '' ]];then
13779                                                 chunk_size=${a_raid_working[9]}
13780                                         else
13781                                                 chunk_size='N/A'
13782                                         fi
13783                                         chunk_size=" ${C1}$chunk_raid_usage$SEP3${C2} $chunk_size"
13784                                         if [[ ${a_raid_working[10]} != '' ]];then
13785                                                 bitmap_value='true'
13786                                                 bitmap_value=" ${C1}bitmap$SEP3${C2} $bitmap_value"
13787                                         fi
13788                                 fi
13789                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
13790                                         if [[ ${a_raid_working[5]} != '' ]];then
13791                                                 u_data=" ${a_raid_working[5]}"
13792                                         fi
13793                                         if [[ ${a_raid_working[7]} != '' ]];then
13794                                                 super_blocks=" ${C1}super blocks$SEP3${C2} ${a_raid_working[7]}"
13795                                         fi
13796                                         if [[ ${a_raid_working[8]} != '' ]];then
13797                                                 algorithm=" ${C1}algorithm$SEP3${C2} ${a_raid_working[8]}"
13798                                         fi
13799                                 fi
13800                                 if [[ ${a_raid_working[3]} == '' ]];then
13801                                         if [[ ${a_raid_working[1]} != 'inactive' ]];then
13802                                                 device_components=" ${C1}components$SEP3${C2} N/A"
13803                                         fi
13804                                 else
13805                                         for component in ${a_raid_working[3]}
13806                                         do
13807                                                 if [[ $B_EXTRA_DATA != 'true' ]];then
13808                                                         component=$( sed 's/\[[0-9]\+\]//' <<< $component )
13809                                                 fi
13810                                                 # NOTE: for bsd zfs, states are: ONLINE,DEGRADED,OFFLINE (at least)
13811                                                 if [[ -n $( grep -E '(F|DEGRADED)' <<< $component ) ]];then
13812                                                         component=$( sed -e 's/(F)//' -e 's/F//' -e 's/DEGRADED//' <<<  $component )
13813                                                         failed="$failed $component"
13814                                                         component=''
13815                                                 elif [[ -n $( grep -E '(S|OFFLINE)' <<< $component ) ]];then
13816                                                         component=$( sed -e 's/(S)//' -e 's/S//' -e 's/OFFLINE//' <<<  $component )
13817                                                         spare="$spare $component"
13818                                                         component=''
13819                                                 else
13820                                                         device_components="$device_components$component_separator$component"
13821                                                         component_separator=' '
13822                                                 fi
13823                                         done
13824                                         if [[ $failed != '' ]];then
13825                                                 failed=" ${C1}FAILED$SEP3${C2}$failed${C2}"
13826                                         fi
13827                                         if [[ $spare != '' ]];then
13828                                                 spare=" ${C1}spare$SEP3${C2}$spare${C2}"
13829                                         fi
13830                                         if [[ -n $device_components || -n $spare || -n $failed ]];then
13831                                                 if [[ $B_EXTRA_DATA != 'true' && -z $BSD_TYPE ]];then
13832                                                         if [[ $device_report != 'N/A' && -n $device_components ]];then
13833                                                                 device_components="$device_report - $device_components"
13834                                                         fi
13835                                                 fi
13836                                                 if [[ $device_components == '' ]];then
13837                                                         device_components='none'
13838                                                 fi
13839                                                 device_components="${C1}online$SEP3${C2} $device_components"
13840                                                 device_components=" ${C1}components$SEP3${C2} $device_components$failed$spare"
13841                                         fi
13842                                 fi
13843                                 a_raid_data[$raid_counter]="${C1}Device$device_id$SEP3${C2} $device$device_state$raid_level$device_components"
13844                                 
13845                                 if [[ $B_EXTRA_DATA == 'true' && ${a_raid_working[1]} != 'inactive' ]];then
13846                                         a_raid_data[$raid_counter]="${C1}Device$device_id$SEP3${C2} $device$device_state$device_components"
13847                                         (( raid_counter++ ))
13848                                         print_string="${C1}Info$SEP3${C2}$raid_level ${C1}$report_size$SEP3${C2} $device_report$u_data"
13849                                         print_string="$print_string$blocks$chunk_size$bitmap_value$super_blocks$algorithm"
13850                                         a_raid_data[$raid_counter]="$print_string"
13851                                 else
13852                                         a_raid_data[$raid_counter]="${C1}Device$device_id$SEP3${C2} $device$device_state$raid_level$device_components"
13853                                 fi
13854                                 (( raid_counter++ ))
13855                                 
13856                                 # now let's do the recover line if required
13857                                 if [[ ${a_raid_working[12]} != '' ]];then
13858                                         recovery_percent=$( cut -d '~' -f 2 <<< ${a_raid_working[12]} )
13859                                         if [[ ${a_raid_working[14]} != '' ]];then
13860                                                 finish_time=${a_raid_working[14]}
13861                                         else
13862                                                 finish_time='N/A'
13863                                         fi
13864                                         finish_time=" ${C1}time remaining$SEP3${C2} $finish_time"
13865                                         if [[ $B_EXTRA_DATA == 'true' ]];then
13866                                                 if [[ ${a_raid_working[13]} != '' ]];then
13867                                                         recovered_sectors=" ${C1}sectors$SEP3${C2} ${a_raid_working[13]}"
13868                                                 fi
13869                                         fi
13870                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
13871                                                 if [[ ${a_raid_working[11]} != '' ]];then
13872                                                         recovery_progress_bar=" ${a_raid_working[11]}"
13873                                                 fi
13874                                                 if [[ ${a_raid_working[15]} != '' ]];then
13875                                                         recovery_speed=" ${C1}speed$SEP3${C2} ${a_raid_working[15]}"
13876                                                 fi
13877                                         fi
13878                                         a_raid_data[$raid_counter]="${C1}Recovering$SEP3${C2} $recovery_percent$recovery_progress_bar$recovered_sectors$finish_time$recovery_speed"
13879                                         (( raid_counter++ ))
13880                                 fi
13881                         fi
13882                 elif [[ ${a_raid_working[0]} == 'KernelRaidSupport' ]];then
13883                         if [[ ${a_raid_working[1]} == '' ]];then
13884                                 kernel_support='N/A'
13885                         else
13886                                 kernel_support=${a_raid_working[1]}
13887                         fi
13888                         kernel_support=" ${C1}supported$SEP3${C2} $kernel_support"
13889                 elif [[ ${a_raid_working[0]} == 'ReadAhead' ]];then
13890                         if [[ ${a_raid_working[1]} != '' ]];then
13891                                 read_ahead=${a_raid_working[1]}
13892                                 read_ahead=" ${C1}read ahead$SEP3${C2} $read_ahead"
13893                         fi
13894                 elif [[ ${a_raid_working[0]} == 'UnusedDevices' ]];then
13895                         if [[ ${a_raid_working[1]} == '' ]];then
13896                                 unused_devices='N/A'
13897                         else
13898                                 unused_devices=${a_raid_working[1]}
13899                         fi
13900                         unused_devices="${C1}Unused Devices$SEP3${C2} $unused_devices"
13901                 elif [[ ${a_raid_working[0]} == 'raidEvent' ]];then
13902                         if [[ ${a_raid_working[1]} != '' ]];then
13903                                 raid_event=${a_raid_working[1]}
13904                                 raid_event=" ${C1}Raid Event$SEP3${C2} ${a_raid_working[1]}"
13905                         fi
13906                 fi
13907         done
13908         
13909         if [[ $B_SHOW_BASIC_RAID == 'true' && $basic_raid != '' ]];then
13910                 a_raid_data[0]="${C1}Device$basic_raid_plural$SEP3${C2} $basic_raid"
13911         fi
13912         # note bsd temp test hack to make it run
13913         if [[ $B_MDSTAT_FILE != 'true' && -z $BSD_TYPE ]] || \
13914         [[ -n $BSD_TYPE && $B_BSD_RAID == 'false' ]];then
13915                 if [[ $B_SHOW_RAID_R == 'true' ]];then
13916                         a_raid_data[0]="$no_raid_detected"
13917                 else
13918                         b_print_lines='false'
13919                 fi
13920         else
13921                 if [[ ${a_raid_data[0]} == '' ]];then
13922                         if [[ $B_SHOW_BASIC_RAID != 'true' ]];then
13923                                 a_raid_data[0]="$empty_raid_data"
13924                         else
13925                                 b_print_lines='false'
13926                         fi
13927                 fi
13928                 # now let's add on the system line and the unused device line. Only print on -xx
13929                 if [[ $kernel_support$read_ahead$raid_event != '' ]];then
13930                         array_count=${#a_raid_data[@]}
13931                         a_raid_data[array_count]="${C1}System$SEP3${C2}$kernel_support$read_ahead$raid_event"
13932                         loop_limit=1
13933                 fi
13934                 if [[ $unused_devices != '' ]];then
13935                         array_count_unused=${#a_raid_data[@]}
13936                         a_raid_data[array_count_unused]="$unused_devices"
13937                         loop_limit=2
13938                 fi
13939         fi
13940
13941         # we don't want to print anything if it's -b and no data is present, just a waste of a line
13942         if [[ $b_print_lines == 'true' ]];then
13943                 # print out all lines, line starter on first line
13944                 for (( i=0; i < ${#a_raid_data[@]} - $loop_limit;i++ ))
13945                 do
13946                         if [[ $i -eq 0 ]];then
13947                                 line_starter='RAID:'
13948                         else
13949                                 line_starter=' '
13950                         fi
13951                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && $array_count != '' ]];then
13952                                 if [[ $i == 0 ]];then
13953                                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[array_count]}" )
13954                                         print_screen_output "$raid_data"
13955                                         line_starter=' '
13956                                 fi
13957                         fi
13958                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[i]}" )
13959                         print_screen_output "$raid_data"
13960                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && $array_count_unused != '' ]];then
13961                                 if [[ $i == $(( array_count_unused - 2 )) ]];then
13962                                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[array_count_unused]}" )
13963                                         print_screen_output "$raid_data"
13964                                 fi
13965                         fi
13966                 done
13967         fi
13968         
13969         eval $LOGFE
13970 }
13971
13972 print_ram_data()
13973 {
13974         eval $LOGFS
13975         local memory_line='' line_2='' line_3='' b_module_present='true'
13976         local error_string='' a_memory_item='' line_starter='Memory:' array_counter=1 device_counter=1
13977         local dmidecodeNull='No dmidecode memory data: try newer kernel.'
13978         
13979         local manufacturer='' part_nu='' serial_nu='' device_speed='' configured_speed='' bus_width=
13980         local data_width='' total_width='' device_type='' device_type_detail='' bank='' slot='' form_factor=''
13981         local device_size='' array_use='' location='' error_correction='' max_capacity='' nu_of_devices=''
13982         local max_module_size='' module_voltage='' bank_connection=''
13983         
13984         get_ram_data
13985         #echo ${#A_MEMORY_DATA[@]}
13986         #echo ${A_MEMORY_DATA[0]}
13987         if [[ ${#A_MEMORY_DATA[@]} -gt 0 ]];then
13988                 if [[ ${A_MEMORY_DATA[0]} == 'dmidecode-error-'* ]];then
13989                         error_string=$( print_dmidecode_error 'default' "${A_MEMORY_DATA[0]}" )
13990                         memory_line="${C2}$error_string"
13991                 else
13992                         for (( i=0;i<${#A_MEMORY_DATA[@]};i++ ))
13993                         do
13994                                 IFS=','
13995                                 a_memory_item=(${A_MEMORY_DATA[i]})
13996                                 IFS="$ORIGINAL_IFS"
13997                                 memory_line=''
13998                                 line_2=''
13999                                 line_3=''
14000                                 bus_width=''
14001                                 data_width=
14002                                 total_width=
14003                                 part_nu=''
14004                                 serial_nu=''
14005                                 manufacturer=''
14006                                 max_module_size='' 
14007                                 module_voltage=''
14008                                 bank_connection=''
14009                                 # memory-array,0x0012,System Board,8 GB,4,System Memory,None,max size,moudule voltage
14010                                 if [[ ${a_memory_item[0]} == 'memory-array' ]];then
14011                                         if [[ -n ${a_memory_item[4]} ]];then
14012                                                 nu_of_devices=${a_memory_item[4]}
14013                                         else
14014                                                 nu_of_devices='N/A'
14015                                         fi
14016                                         if [[ -n ${a_memory_item[3]} ]];then
14017                                                 max_capacity=${a_memory_item[3]}
14018                                         else
14019                                                 max_capacity='N/A'
14020                                         fi
14021                                         if [[ -n ${a_memory_item[6]} ]];then
14022                                                 error_correction=${a_memory_item[6]}
14023                                         else
14024                                                 error_correction='N/A'
14025                                         fi
14026                                         if [[ $B_EXTRA_DATA == 'true' ]];then
14027                                                 if [[ -n ${a_memory_item[7]} ]];then
14028                                                         max_module_size="${C1}max module size${SEP3}${C2} ${a_memory_item[7]} "
14029                                                 fi
14030                                         fi
14031                                         if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
14032                                                 if [[ -n ${a_memory_item[8]} ]];then
14033                                                         module_voltage="${C1}module voltage$SEP3${C2} ${a_memory_item[8]}"
14034                                                 fi
14035                                         fi
14036                                         memory_line="${C1}Array-$array_counter capacity$SEP3${C2} $max_capacity ${C1}devices$SEP3${C2} $nu_of_devices ${C1}EC$SEP3${C2} $error_correction "
14037                                         line_2="$max_module_size$module_voltage"
14038                                         if [[ -n $line_2 && $( calculate_line_length "$memory_line$line_2" ) -gt $COLS_INNER ]];then
14039                                                 memory_line=$( create_print_line "$line_starter" "$memory_line" )
14040                                                 print_screen_output "$memory_line"
14041                                                 memory_line="$line_2"
14042                                                 line_starter=' '
14043                                                 line_2=''
14044                                         else
14045                                                 memory_line="$memory_line$line_2"
14046                                                 line_2=''
14047                                         fi
14048                                         (( array_counter++ ))
14049                                         device_counter=1 # reset so device matches device count per array
14050                                 else
14051                                         # not used for now
14052 #                                       if [[ -n ${a_memory_item[3333]} ]];then
14053 #                                               if [[ -z ${a_memory_item[3]/BANK*/} ]];then
14054 #                                                       #bank=${a_memory_item[3]#BANK}
14055 #                                                       bank=${a_memory_item[3]}
14056 #                                                       bank=${bank## }
14057 #                                               else
14058 #                                                       bank=${a_memory_item[3]}
14059 #                                               fi
14060 #                                       else
14061 #                                               bank='N/A'
14062 #                                       fi
14063 #                                       # not used for now
14064 #                                       if [[ -n ${a_memory_item[44444]} ]];then
14065 #                                               if [[ -z ${a_memory_item[4]/SLOT*/} ]];then
14066 #                                                       #slot=${a_memory_item[4]#SLOT}
14067 #                                                       slot=${a_memory_item[4]}
14068 #                                                       slot=${slot## }
14069 #                                               else
14070 #                                                       slot=${a_memory_item[4]}
14071 #                                               fi
14072 #                                       else
14073 #                                               slot='N/A'
14074 #                                       fi
14075                                         if [[ -n ${a_memory_item[15]} ]];then
14076                                                 locator=${a_memory_item[15]}
14077                                                 locator=${locator## }
14078                                         else
14079                                                 locator='N/A'
14080                                         fi
14081                                         if [[ -n ${a_memory_item[2]} ]];then
14082                                                 device_size=${a_memory_item[2]}
14083                                                 if [[ $device_size == 'No Module Installed' ]];then
14084                                                         b_module_present='false'
14085                                                 else
14086                                                         b_module_present='true'
14087                                                 fi
14088                                         else
14089                                                 device_size='N/A'
14090                                         fi
14091                                         if [[ -n ${a_memory_item[6]} ]];then
14092                                                 device_type=${a_memory_item[6]}
14093                                                 if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' && -n ${a_memory_item[7]} \
14094                                                       && ${a_memory_item[7]} != 'Other' ]];then
14095                                                         device_type="$device_type (${a_memory_item[7]})"
14096                                                 fi
14097                                         else
14098                                                 device_type='N/A'
14099                                         fi
14100                                         device_type="${C1}type$SEP3${C2} $device_type "
14101                                         if [[ -n ${a_memory_item[8]} ]];then
14102                                                 if [[ -n ${a_memory_item[9]} ]];then
14103                                                         device_speed=${a_memory_item[9]}
14104                                                 else
14105                                                         device_speed=${a_memory_item[8]}
14106                                                 fi
14107                                         else
14108                                                 device_speed='N/A'
14109                                         fi
14110                                         if [[ $b_module_present == 'true' ]];then
14111                                                 device_speed="${C1}speed$SEP3${C2} $device_speed "
14112                                         else
14113                                                 device_speed=''
14114                                         fi
14115                                         # memory-device,0x002C,8192 MB,ChannelD,ChannelD_Dimm2,DIMM,DDR3,Synchronous,2400 MHz,2400 MHz,64 bits,64 bits,Undefined,F3-19200C10-8GBZH,00000000
14116                                         if [[ $b_module_present == 'true' ]];then
14117                                                 if [[ $B_EXTRA_DATA == 'true' ]];then
14118                                                         if [[ -n ${a_memory_item[13]} ]];then
14119                                                                 part_nu=${a_memory_item[13]}
14120                                                         else
14121                                                                 part_nu='N/A'
14122                                                         fi
14123                                                         part_nu="${C1}part$SEP3${C2} $part_nu "
14124                                                 fi
14125                                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
14126                                                         if [[ -n ${a_memory_item[12]} ]];then
14127                                                                 manufacturer=${a_memory_item[12]}
14128                                                         else
14129                                                                 manufacturer='N/A' 
14130                                                         fi
14131                                                         manufacturer="${C1}manufacturer$SEP3${C2} $manufacturer "
14132                                                         if [[ -n ${a_memory_item[14]} ]];then
14133                                                                 serial_nu=${a_memory_item[14]}
14134                                                         else
14135                                                                 serial_nu='N/A'
14136                                                         fi
14137                                                         serial_nu="${C1}serial$SEP3${C2} $serial_nu "
14138                                                         
14139                                                         if [[ $device_size != 'N/A' && -n ${a_memory_item[16]} ]];then
14140                                                                 bank_connection=" ${a_memory_item[16]}"
14141                                                         fi
14142                                                 fi
14143                                         fi
14144                                         if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
14145                                                 if [[ $b_module_present == 'true' ]] || \
14146                                                      [[ -n ${a_memory_item[11]} || -n ${a_memory_item[10]} ]];then
14147                                                         # only create this if the total exists and is > data width
14148                                                         if [[ -n ${a_memory_item[10]/ bits/} && -n ${a_memory_item[11]/ bits} && \
14149                                                               ${a_memory_item[11]/ bits/} -gt ${a_memory_item[10]/ bits/} ]];then
14150                                                                 total_width=" (total$SEP3 ${a_memory_item[11]})"
14151                                                         fi
14152                                                         if [[ -n ${a_memory_item[10]} ]];then
14153                                                                 data_width=${a_memory_item[10]}
14154                                                         else
14155                                                                 data_width='N/A'
14156                                                         fi
14157                                                         bus_width="${C1}bus width$SEP3${C2} $data_width$total_width "
14158                                                 fi
14159                                         fi
14160                                         memory_line="${C1}Device-$device_counter$SEP3${C2} $locator ${C1}size$SEP3${C2} $device_size$bank_connection $device_speed"
14161                                         if [[ $( calculate_line_length "$memory_line$device_type" ) -le $COLS_INNER ]];then
14162                                                 memory_line="$memory_line$device_type"
14163                                                 device_type=''
14164                                         fi
14165                                         line_3="$manufacturer$part_nu$serial_nu"
14166                                         line_2="$device_type$bus_width"
14167                                         # echo $( calculate_line_length "$memory_line" )
14168                                         # echo $( calculate_line_length "$memory_line$line_2" )
14169                                         if [[ $( calculate_line_length "$memory_line$line_2$line_3" ) -gt $COLS_INNER ]];then
14170                                                 memory_line=$( create_print_line "$line_starter" "$memory_line" )
14171                                                 print_screen_output "$memory_line"
14172                                                 memory_line="$line_2"
14173                                                 line_starter=' '
14174                                                 if [[ -n $memory_line && -n $line_3 && $( calculate_line_length "$memory_line$line_3" ) -gt $COLS_INNER ]];then
14175                                                         memory_line=$( create_print_line "$line_starter" "$memory_line" )
14176                                                         print_screen_output "$memory_line"
14177                                                         memory_line="$line_3"
14178                                                 else
14179                                                         memory_line="$memory_line$line_3"
14180                                                 fi
14181                                         else
14182                                                 memory_line="$memory_line$line_2$line_3"
14183                                         fi
14184                                         (( device_counter++ ))
14185                                 fi
14186                                 memory_line=$( create_print_line "$line_starter" "$memory_line" )
14187                                 print_screen_output "$memory_line"
14188                                 line_starter=' '
14189                         done
14190                         memory_line=' '
14191                 fi
14192         else
14193                 memory_line="${C2}$dmidecodeNull"
14194         fi
14195         IFS="$ORIGINAL_IFS"
14196         memory_line=${memory_line## }
14197         if [[ -n $memory_line ]];then
14198                 memory_line=$( create_print_line "$line_starter" "$memory_line" )
14199                 print_screen_output "$memory_line"
14200         fi
14201
14202         eval $LOGFE
14203 }
14204
14205
14206 # currently only apt using distros support this feature, but over time we can add others
14207 print_repo_data()
14208 {
14209         eval $LOGFS
14210         local repo_count=0 repo_line='' file_name='' file_content='' file_name_holder=''
14211         local repo_full='' b_print_next_line='false' repo_type=''
14212         
14213         get_repo_data
14214         
14215         if [[ -n $REPO_DATA ]];then
14216                 # loop through the variable's lines one by one, update counter each iteration
14217                 while read repo_line
14218                 do
14219                         (( repo_count++ ))
14220                         repo_type=$( cut -d '^' -f 1 <<< $repo_line )
14221                         file_name=$( cut -d '^' -f 2 <<< $repo_line )
14222                         file_content=$( cut -d '^' -f 3-7 <<< $repo_line )
14223                         # this will dump unwanted white space line starters. Some irc channels
14224                         # use bots that show page title for urls, so need to break the url by adding 
14225                         # a white space.
14226                         if [[ $B_IRC == 'true' ]];then
14227                                 file_content=$( echo ${file_content/:\/\//: \/\/} )
14228                         else
14229                                 file_content=$( echo $file_content )
14230                         fi
14231                         # echo $file_name : $file_name_holder : $repo_type : $file_content
14232                         # check file name, if different, update the holder for print out
14233                         if [[ $file_name != $file_name_holder ]];then
14234                                 if [[ $repo_type == 'pisi repo' || $repo_type == 'urpmq repo' ]];then
14235                                         repo_full="${C1}$repo_type$SEP3${C2} $file_name"
14236                                 else
14237                                         repo_full="${C1}Active $repo_type in file$SEP3${C2} $file_name"
14238                                 fi
14239                                 file_name_holder=$file_name
14240                                 b_print_next_line='true'
14241                         else
14242                                 repo_full="${C2}$file_content"
14243                         fi
14244                         # first line print Repos: 
14245                         if [[ $repo_count -eq 1 ]];then
14246                                 repo_full=$( create_print_line "Repos:" "$repo_full" )
14247                         else
14248                                 repo_full=$( create_print_line " " "$repo_full" )
14249                         fi
14250                         print_screen_output "$repo_full"
14251                         # this prints the content of the file as well as the file name
14252                         if [[ $b_print_next_line == 'true' ]];then
14253                                 repo_full=$( create_print_line " " "$file_content" )
14254                                 print_screen_output "$repo_full"
14255                                 b_print_next_line='false'
14256                         fi
14257                 done <<< "$REPO_DATA"
14258         else
14259                 if [[ $BSD_TYPE == 'bsd' ]];then
14260                         repo_type='OS type'
14261                 else
14262                         repo_type="package manager"
14263                 fi
14264                 repo_full=$( create_print_line "Repos:" "${C1}Error$SEP3${C2} No repo data detected. Does $SCRIPT_NAME support your $repo_type?" )
14265                 print_screen_output "$repo_full"
14266         fi
14267         eval $LOGFE
14268 }
14269
14270 print_sensors_data()
14271 {
14272         eval $LOGFS
14273         local mobo_temp='' cpu_temp='' psu_temp='' cpu_fan='' mobo_fan='' ps_fan='' sys_fans='' sys_fans2='' 
14274         local temp_data='' fan_data='' fan_data2='' b_is_error='false' fan_count=0 gpu_temp=''
14275         local a_sensors_working=''
14276         local no_sensors_message='None detected - is lm-sensors installed and configured?'
14277         local Sensors_Data="$( get_sensors_output )"
14278         get_sensors_data
14279         
14280         if [[ $BSD_TYPE == 'bsd' ]];then
14281                 no_sensors_message='This feature is not yet supported for BSD systems.'
14282         fi
14283         
14284         IFS=","
14285         a_sensors_working=( ${A_SENSORS_DATA[0]} )
14286         IFS="$ORIGINAL_IFS"
14287         # initial error cases, for missing app or unconfigured sensors. Note that array 0
14288         # always has at least 3 items, cpu/mobo/psu temp in it. If the count is 0, then
14289         # no sensors are installed/configured
14290         if [[ ${#a_sensors_working[@]} -eq 0 ]];then
14291                 cpu_temp=$no_sensors_message
14292                 b_is_error='true'
14293         else
14294                 for (( i=0; i < ${#A_SENSORS_DATA[@]}; i++ ))
14295                 do
14296                         IFS=","
14297                         a_sensors_working=( ${A_SENSORS_DATA[i]} )
14298                         IFS="$ORIGINAL_IFS"
14299                         case $i in
14300                                 # first the temp data
14301                                 0)
14302                                         if [[ -n ${a_sensors_working[0]} ]];then
14303                                                 cpu_temp=${a_sensors_working[0]}
14304                                         else
14305                                                 cpu_temp='N/A'
14306                                         fi
14307                                         cpu_temp="${C1}System Temperatures: cpu$SEP3${C2} $cpu_temp "
14308
14309                                         if [[ -n ${a_sensors_working[1]} ]];then
14310                                                 mobo_temp=${a_sensors_working[1]}
14311                                         else
14312                                                 mobo_temp='N/A'
14313                                         fi
14314                                         mobo_temp="${C1}mobo$SEP3${C2} $mobo_temp "
14315
14316                                         if [[ -n ${a_sensors_working[2]} ]];then
14317                                                 psu_temp="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
14318                                         fi
14319                                         gpu_temp=$( get_gpu_temp_data )
14320                                         # dump the unneeded screen data for single gpu systems 
14321                                         if [[ $( wc -w <<< $gpu_temp ) -eq 1 && $B_EXTRA_DATA != 'true' ]];then
14322                                                 gpu_temp=${gpu_temp#*:}
14323                                         fi
14324                                         if [[ -n $gpu_temp ]];then
14325                                                 gpu_temp="${C1}gpu$SEP3${C2} $gpu_temp "
14326                                         fi
14327                                         ;;
14328                                 # then the fan data from main fan array
14329                                 1)
14330                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
14331                                         do
14332                                                 case $j in
14333                                                         0)
14334                                                                 # we need to make sure it's either cpu fan OR cpu fan and sys fan 1
14335                                                                 if [[ -n ${a_sensors_working[0]} ]];then
14336                                                                         cpu_fan="${a_sensors_working[0]}"
14337                                                                 elif [[ -z ${a_sensors_working[0]} && -n ${a_sensors_working[1]} ]];then
14338                                                                         cpu_fan="${a_sensors_working[1]}"
14339                                                                 else
14340                                                                         cpu_fan='N/A'
14341                                                                 fi
14342                                                                 cpu_fan="${C1}Fan Speeds (in rpm): cpu$SEP3${C2} $cpu_fan "
14343                                                                 (( fan_count++ ))
14344                                                                 ;;
14345                                                         1)
14346                                                                 if [[ -n ${a_sensors_working[1]} ]];then
14347                                                                         mobo_fan="${C1}mobo$SEP3${C2} ${a_sensors_working[1]} "
14348                                                                         (( fan_count++ ))
14349                                                                 fi
14350                                                                 ;;
14351                                                         2)
14352                                                                 if [[ -n ${a_sensors_working[2]} ]];then
14353                                                                         ps_fan="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
14354                                                                         (( fan_count++ ))
14355                                                                 fi
14356                                                                 ;;
14357                                                         [3-9]|[1-9][0-9])
14358                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
14359                                                                         fan_number=$(( $j - 2 )) # sys fans start on array key 5
14360                                                                         # wrap after fan 6 total
14361                                                                         if [[ $fan_count -lt 7 ]];then
14362                                                                                 sys_fans="$sys_fans${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
14363                                                                         else
14364                                                                                 sys_fans2="$sys_fans2${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
14365                                                                         fi
14366                                                                         (( fan_count++ ))
14367                                                                 fi
14368                                                                 ;;
14369                                                 esac
14370                                         done
14371                                         ;;
14372                                 2)
14373                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
14374                                         do
14375                                                 case $j in
14376                                                         [0-9]|[1-9][0-9])
14377                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
14378                                                                         fan_number=$(( $j + 1 )) # sys fans start on array key 5
14379                                                                         # wrap after fan 6 total
14380                                                                         if [[ $fan_count -lt 7 ]];then
14381                                                                                 sys_fans="$sys_fans${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
14382                                                                         else
14383                                                                                 sys_fans2="$sys_fans2${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
14384                                                                         fi
14385                                                                         (( fan_count++ ))
14386                                                                 fi
14387                                                                 ;;
14388                                                 esac
14389                                         done
14390                                         ;;
14391                         esac
14392                 done
14393         fi
14394         # turning off all output for case where no sensors detected or no sensors output 
14395         # unless -s used explicitly. So for -F type output won't show unless valid or -! 1 used
14396         if [[ $b_is_error != 'true' || $B_SHOW_SENSORS == 'true' || $B_TESTING_1 == 'true' ]];then
14397                 temp_data="$cpu_temp$mobo_temp$psu_temp$gpu_temp"
14398                 temp_data=$( create_print_line "Sensors:" "$temp_data" )
14399                 print_screen_output "$temp_data"
14400                 # don't print second or subsequent lines if error data
14401                 fan_data="$cpu_fan$mobo_fan$ps_fan$sys_fans"
14402                 if [[ $b_is_error != 'true' && -n $fan_data ]];then
14403                         fan_data=$( create_print_line " " "$fan_data" )
14404                         print_screen_output "$fan_data"
14405                         # and then second wrapped fan line if needed
14406                         if [[ -n $sys_fans2 ]];then
14407                                 fan_data2=$( create_print_line " " "$sys_fans2" )
14408                                 print_screen_output "$fan_data2"
14409                         fi
14410                 fi
14411         fi
14412         eval $LOGFE
14413 }
14414
14415 print_system_data()
14416 {
14417         eval $LOGFS
14418         local system_data='' bits='' desktop_environment='' dm_data='' de_extra_data=''
14419         local de_string='' distro_string='' line_starter='System:'
14420         local host_kernel_string='' host_string='' desktop_type='Desktop'
14421         local host_name=$HOSTNAME
14422         local current_kernel=$( get_kernel_version ) 
14423         local distro="$( get_distro_data )"
14424         local tty_session='' compiler_string='' distro_os='Distro'
14425         
14426         if [[ -n $BSD_TYPE ]];then
14427                 distro_os='OS'
14428         fi
14429         
14430         # I think these will work, maybe, if logged in as root and in X
14431         if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
14432                 desktop_environment=$( get_desktop_environment )
14433                 if [[ -z $desktop_environment ]];then
14434                         desktop_environment='N/A'
14435                 fi
14436                 
14437                 if [[  $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
14438                         de_extra_data=$( get_desktop_extra_data )
14439                         if [[ -n $de_extra_data ]];then
14440                                 de_extra_data=" ${C1}info$SEP3${C2} $de_extra_data"
14441                         fi
14442                 fi
14443         else
14444                 tty_session=$( get_tty_number )
14445                 if [[ -z $tty_session && $B_CONSOLE_IRC == 'true' ]];then
14446                         tty_session=$( get_tty_console_irc )
14447                 fi
14448                 if [[ -n $tty_session ]];then
14449                         tty_session=" $tty_session"
14450                 fi
14451                 desktop_environment="tty$tty_session"
14452                 desktop_type='Console'
14453         fi
14454         # having dm type can be useful if you are accessing remote system
14455         # or are out of X and don't remember which dm is running the system
14456         if [[  $B_EXTRA_EXTRA_DATA == 'true' ]];then
14457                 dm_data=$( get_display_manager )
14458                 # here we only want the dm info to show N/A if in X
14459                 if [[ -z $dm_data && $B_RUNNING_IN_DISPLAY == 'true' ]];then
14460                         dm_data='N/A'
14461                 fi
14462                 # only print out of X if dm_data has info, then it's actually useful, but
14463                 # for headless servers, no need to print dm stuff.
14464                 if [[ -n $dm_data ]];then
14465                         dm_data=" ${C1}dm$SEP3${C2} $dm_data"
14466                 fi
14467         fi
14468         if [[ $B_EXTRA_DATA == 'true' ]];then
14469                 compiler_string=$( get_kernel_compiler_version )
14470                 if [[ -n $compiler_string ]];then
14471                         compiler_string=" ${C1}${compiler_string%^*}$SEP3${C2} ${compiler_string#*^}"
14472                 fi
14473         fi
14474         # check for 64 bit first
14475         if [[ -n $( uname -m | grep -E '(x86_64|amd64)' ) ]];then
14476                 bits="64"
14477         else
14478                 bits="32"
14479         fi
14480         bits=" ($bits bit$compiler_string)"
14481         if [[ $B_SHOW_HOST == 'true' ]];then
14482                 if [[ -z $HOSTNAME ]];then
14483                         if [[ -n $( type p hostname ) ]];then
14484                                 host_name=$( hostname )
14485                         fi
14486                         if [[ -z $host_name ]];then
14487                                 host_name='N/A'
14488                         fi
14489                 fi
14490                 host_string="${C1}Host$SEP3${C2} $host_name "
14491         fi
14492         host_kernel_string="$host_string${C1}Kernel$SEP3${C2} $current_kernel$bits "
14493         de_string="${C1}$desktop_type$SEP3${C2} $desktop_environment$de_extra_data$dm_data "
14494         distro_string="${C1}$distro_os$SEP3${C2} $distro "
14495         
14496         if [[ $( calculate_line_length "$host_kernel_string$de_string" ) -gt $COLS_INNER ]];then
14497                 system_data=$( create_print_line "$line_starter" "$host_kernel_string" )
14498                 print_screen_output "$system_data"
14499                 host_kernel_string=''
14500                 line_starter=' '
14501         fi
14502         if [[ $( calculate_line_length "$host_kernel_string$de_string$distro_string" ) -gt $COLS_INNER ]];then
14503                 system_data=$( create_print_line "$line_starter" "$host_kernel_string$de_string" )
14504                 print_screen_output "$system_data"
14505                 host_kernel_string=''
14506                 de_string=''
14507                 line_starter=' '
14508         fi
14509         system_data="$host_kernel_string$de_string$distro_string"
14510         if [[ -n $system_data ]];then
14511                 system_data="$host_kernel_string$de_string$distro_string"
14512                 system_data=$( create_print_line "$line_starter" "$system_data" )
14513                 print_screen_output "$system_data"
14514         fi
14515         
14516         eval $LOGFE
14517 }
14518
14519 print_unmounted_partition_data()
14520 {
14521         eval $LOGFS
14522         local a_unmounted_data='' line_starter='' unmounted_data='' full_fs=''
14523         local full_dev='' full_size='' full_label='' full_uuid='' full_string=''
14524         local bsd_unsupported='This feature is not yet supported for BSD systems.'
14525         local line_starter='Unmounted:' part_2_data='' 
14526         
14527         if [[ -z ${A_PARTITION_DATA} ]];then
14528                 get_partition_data
14529         fi
14530         get_unmounted_partition_data
14531         if [[ ${#A_UNMOUNTED_PARTITION_DATA[@]} -ge 1 ]];then
14532                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
14533                 do
14534                         full_string=''
14535                         part_2_data=''
14536                         IFS=","
14537                         a_unmounted_data=(${A_UNMOUNTED_PARTITION_DATA[i]})
14538                         IFS="$ORIGINAL_IFS"
14539                         if [[ -z ${a_unmounted_data[0]} ]];then
14540                                 full_dev='N/A'
14541                         else
14542                                 full_dev="/dev/${a_unmounted_data[0]}"
14543                         fi
14544                         full_dev="${C1}ID-$((i+1))$SEP3${C2} $full_dev "
14545                         if [[ -z ${a_unmounted_data[1]} ]];then
14546                                 full_size='N/A'
14547                         else
14548                                 full_size=${a_unmounted_data[1]}
14549                         fi
14550                         full_size="${C1}size$SEP3${C2} $full_size "
14551                         if [[ -z ${a_unmounted_data[2]} ]];then
14552                                 full_label='N/A'
14553                         else
14554                                 full_label=${a_unmounted_data[2]}
14555                         fi
14556                         full_label="${C1}label$SEP3${C2} $full_label "
14557                         if [[ -z ${a_unmounted_data[3]} ]];then
14558                                 full_uuid='N/A'
14559                         else
14560                                 full_uuid=${a_unmounted_data[3]}
14561                         fi
14562                         full_uuid="${C1}uuid$SEP3${C2} $full_uuid "
14563                         if [[ -z ${a_unmounted_data[4]} ]];then
14564                                 full_fs=''
14565                         else
14566                                 full_fs="${C1}fs$SEP3${C2} ${a_unmounted_data[4]} "
14567                         fi
14568                         # temporary message to indicate not yet supported
14569                         if [[ $BSD_TYPE == 'bsd' ]];then
14570                                 full_string=$bsd_unsupported
14571                         else
14572                                 full_string="$full_dev$full_size"
14573                                 part_2_data="$full_fs$full_label$full_uuid"
14574                         fi
14575                         if [[ $( calculate_line_length "$full_string$part_2_data" ) -gt $COLS_INNER ]];then
14576                                 unmounted_data=$( create_print_line "$line_starter" "$full_string" )
14577                                 print_screen_output "$unmounted_data"
14578                                 line_starter=' '
14579                                 unmounted_data=$( create_print_line "$line_starter" "$part_2_data" )
14580                                 print_screen_output "$unmounted_data"
14581                         else
14582                                 unmounted_data=$( create_print_line "$line_starter" "$full_string$part_2_data" )
14583                                 print_screen_output "$unmounted_data"
14584                                 line_starter=' '
14585                         fi
14586                 done
14587         else
14588                 unmounted_data=$( create_print_line "$line_starter" "No unmounted partitions detected" )
14589                 print_screen_output "$unmounted_data"
14590         fi
14591         
14592         eval $LOGFE
14593 }
14594
14595 print_weather_data()
14596 {
14597         eval $LOGFS
14598         
14599         local weather_data='' location_string='' local_time='' time_string='' pressure=''
14600         local a_location='' a_weather='' weather_string='' weather='' temp='' winds='' humidity=''
14601         local time_zone='' observation_time='' city='' state='' country='' altitude=''
14602         local heat_index='' wind_chill='' dewpoint='' xxx_humidity=''
14603         local openP='(' closeP=')'
14604         
14605         if [[ $B_IRC == 'true' ]];then
14606                 openP=''
14607                 closeP=''
14608         fi
14609         
14610         get_weather_data
14611         
14612         # city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3 
14613         #  ";" latitude "," longitude ";" postalCode ";" timeZone
14614         
14615         # observationTime ";" localTime ";" weather ";" tempString ";" humidity 
14616         # ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
14617         # ";" windChillString ";" siteElevation
14618
14619         if [[ ${#A_WEATHER_DATA[@]} -eq 2 ]];then
14620                 IFS=";"
14621                 a_location=(${A_WEATHER_DATA[0]})
14622                 a_weather=(${A_WEATHER_DATA[1]})
14623                 IFS="$ORIGINAL_IFS"
14624                 
14625                 if [[ -n ${a_weather[3]} ]];then
14626                         temp=${a_weather[3]}
14627                 else
14628                         temp='N/A'
14629                 fi
14630                 if [[ -n ${a_weather[2]} ]];then
14631                         weather=" - ${a_weather[2]}"
14632                 else
14633                         weather=''
14634                 fi
14635                 if [[ $B_EXTRA_DATA == 'true' ]];then
14636                         if [[ -n ${a_weather[5]} ]];then
14637                                 winds=" ${C1}Wind$SEP3${C2} ${a_weather[5]}"
14638                         fi
14639                 fi
14640                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
14641                         if [[ -n ${a_weather[4]} ]];then
14642                                 humidity=" ${C1}Humidity$SEP3${C2} ${a_weather[4]}"
14643                         fi
14644                         if [[ -n ${a_weather[6]} ]];then
14645                                 pressure="${C1}Pressure$SEP3${C2} ${a_weather[6]} "
14646                         fi
14647                 fi
14648                 weather_string="${C1}Conditions$SEP3${C2} $temp$weather$winds$humidity"
14649                 
14650                 if [[ -n ${a_weather[1]} ]];then
14651                         local_time=" ${a_weather[1]}"
14652                 else
14653                         local_time=" $(date)"
14654                 fi
14655                 if [[ $B_EXTRA_DATA == 'true' && -n ${a_location[8]} ]];then
14656                         time_zone=" (${a_location[8]})"
14657                 fi
14658                 time_string="${C1}Time$SEP3${C2}$local_time$time_zone"
14659
14660                 if [[ $B_EXTRA_DATA != 'true' ]];then
14661                         weather_data="$weather_string $time_string"
14662                         weather_data=$( create_print_line "Weather:" "$weather_data" )
14663                         print_screen_output "$weather_data"
14664                 else
14665                         weather_data="$weather_string"
14666                         weather_data=$( create_print_line "Weather:" "$weather_data" )
14667                         print_screen_output "$weather_data"
14668                         if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
14669                                 if [[ -n ${a_weather[8]} ]];then
14670                                         heat_index="${C1}Heat Index$SEP3${C2} ${a_weather[8]} "
14671                                 fi
14672                                 if [[ -n ${a_weather[9]} ]];then
14673                                         wind_chill="${C1}Wind Chill$SEP3${C2} ${a_weather[9]} "
14674                                 fi
14675                                 if [[ -n ${a_weather[7]} ]];then
14676                                         dew_point="${C1}Dew Point$SEP3${C2} ${a_weather[7]} "
14677                                 fi
14678                                 if [[ -n ${a_weather[0]} ]];then
14679                                         observation_time=" ${C1}Observation Time$SEP3${C2} ${a_weather[0]} "
14680                                 fi
14681                                 if [[ $B_OUTPUT_FILTER != 'true' ]];then
14682                                         if [[ -n ${a_location[0]} ]];then
14683                                                 city=" ${a_location[0]}"
14684                                         fi
14685                                         if [[ -n ${a_location[1]} ]];then
14686                                                 state=" ${a_location[1]}"
14687                                         fi
14688                                         if [[ -n ${a_location[5]} ]];then
14689                                                 country=" $openP${a_location[5]}$closeP"
14690                                         fi
14691                                         if [[ -n ${a_weather[10]} ]];then
14692                                                 altitude=" ${C1}Altitude$SEP3${C2} ${a_weather[10]}"
14693                                         fi
14694                                         location_string="${C1}Location$SEP3${C2}$city$state$country$altitude "
14695                                 else
14696                                         location_string=$time_string$observation_time
14697                                         time_string=''
14698                                         observation_time=''
14699                                 fi
14700                                 # the last three are oftenblank
14701                                 if [[ -z "$heat_index$wind_chill$dew_point" ]];then
14702                                         weather_data=$( create_print_line " " "$pressure$location_string" )
14703                                         print_screen_output "$weather_data"
14704                                 else
14705                                         weather_data=$( create_print_line " " "$pressure$heat_index$wind_chill$dew_point" )
14706                                         print_screen_output "$weather_data"
14707                                         if [[ $B_OUTPUT_FILTER != 'true' ]];then
14708                                                 weather_data=$( create_print_line " " "$location_string" )
14709                                                 print_screen_output "$weather_data"
14710                                         fi
14711                                 fi
14712                                 if [[ -n $time_string$observation_time ]];then
14713                                         weather_data=$( create_print_line " " "$time_string$observation_time" )
14714                                         print_screen_output "$weather_data"
14715                                 fi
14716                         else
14717                                 if [[ -n $pressure$time_string ]];then
14718                                         weather_data="$pressure$time_string"
14719                                         weather_data=$( create_print_line " " "$weather_data" )
14720                                         print_screen_output "$weather_data"
14721                                 fi
14722                         fi
14723                 fi
14724         else
14725                 weather_data=$( create_print_line "Weather:" "${C2}Weather data failure: $(date)" )
14726                 print_screen_output "$weather_data"
14727                 weather_data=$( create_print_line " " "${C2}${A_WEATHER_DATA}" )
14728                 print_screen_output "$weather_data"
14729         fi
14730         eval $LOGFE
14731 }
14732
14733 ########################################################################
14734 #### SCRIPT EXECUTION
14735 ########################################################################
14736
14737 main $@ ## From the End comes the Beginning
14738
14739 ## note: this EOF is needed for smxi handling, this is what triggers the full download ok
14740 ###**EOF**###